diff --git a/.gitignore b/.gitignore
index cc98b94..add8735 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,7 @@ oo2core*
# wrangler local cache
.wrangler/
+
+AGENTS.md
+CLAUDE.md
+.claude/
diff --git a/Dockerfile b/Dockerfile
index 5ef0d22..fd68f9b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,9 +23,11 @@ RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.version=${VERSION}"
FROM alpine:3.22
# gcompat + libstdc++: the runtime-downloaded Oodle decompressor is a glibc
# binary; gcompat lets musl-based Alpine dlopen it.
-RUN apk add --no-cache ca-certificates tzdata gcompat libstdc++ \
+RUN apk add --no-cache ca-certificates tzdata gcompat libstdc++ curl \
&& addgroup -S palhelm && adduser -S -G palhelm palhelm
COPY --from=backend /out/palhelm /usr/local/bin/palhelm
+COPY --chmod=755 scripts/fetch-map-tiles.sh /usr/local/bin/fetch-map-tiles
+COPY --chmod=755 scripts/fetch-pal-icons.sh /usr/local/bin/fetch-pal-icons
USER palhelm
ENV PALHELM_ADDR=:8080 PALHELM_DATA_DIR=/data
VOLUME /data
diff --git a/README.md b/README.md
index 8cf6881..50e49c4 100644
--- a/README.md
+++ b/README.md
@@ -64,6 +64,7 @@ Palhelm slots into the Compose project you already run your server from. Minimal
# config editor (optional): let Palhelm edit this compose file's env block
PALHELM_COMPOSE_FILE: "/compose/docker-compose.yml"
PALHELM_GAME_SERVICE: "palworld"
+ PALHELM_PANEL_SERVICE: "palhelm"
volumes:
- ../data/Pal/Saved:/game/Saved # rw: restore writes here
- ../palhelm-data:/data # panel DB, backups, map tiles, Oodle lib
@@ -75,8 +76,8 @@ The game server side needs `RCON_ENABLED=true` and an `ADMIN_PASSWORD` (which al
Optional extras, fetched once into your data volume because the art is game-derived and never shipped:
```sh
-scripts/fetch-map-tiles.sh ./palhelm-data/map-tiles # live map tiles
-scripts/fetch-pal-icons.sh ./palhelm-data/pal-icons # pal preview icons
+docker compose exec palhelm palhelm fetch-map-tiles # live map tiles
+docker compose exec palhelm palhelm fetch-pal-icons # pal preview icons
```
## Optional configuration
@@ -94,6 +95,7 @@ scripts/fetch-pal-icons.sh ./palhelm-data/pal-icons # pal preview icons
| `PALWORLD_RCON_ADDR` | — | e.g. `palworld:25575` |
| `PALWORLD_SAVE_DIR` | — | the mounted `Saved/` directory |
| `PALHELM_COMPOSE_FILE` / `PALHELM_GAME_SERVICE` | unset / `palworld` | enable Config when the containing directory supports safe atomic writes |
+| `PALHELM_PANEL_SERVICE` | `palhelm` | panel service in the Compose file; resolves its `container_name` for host commands shown in the UI |
| `PALHELM_DOCKER_CONTROL` | ignored | retained for v0.2 compatibility; one-click apply is disabled in v0.3.0 |
| `PALHELM_METRICS_INTERVAL` | `5s` | metrics sampling |
| `PALHELM_SAVE_SYNC_INTERVAL` | `10m` | save parsing cadence |
diff --git a/backend/cmd/palhelm/main.go b/backend/cmd/palhelm/main.go
index e319e90..3ab4149 100644
--- a/backend/cmd/palhelm/main.go
+++ b/backend/cmd/palhelm/main.go
@@ -9,6 +9,7 @@ import (
"log/slog"
"net/http"
"os"
+ "os/exec"
"os/signal"
"path/filepath"
"strings"
@@ -24,6 +25,14 @@ import (
// version is stamped at build time via -ldflags "-X main.version=...".
var version = "dev"
+var fetchMapTilesCommand = func(args ...string) *exec.Cmd {
+ return exec.Command("/usr/local/bin/fetch-map-tiles", args...)
+}
+
+var fetchPalIconsCommand = func(args ...string) *exec.Cmd {
+ return exec.Command("/usr/local/bin/fetch-pal-icons", args...)
+}
+
func main() {
server.PanelVersion = version
if err := run(); err != nil {
@@ -49,9 +58,47 @@ func run() error {
return errors.New("usage: palhelm parse ")
}
return parse(args[0])
+ case "fetch-map-tiles":
+ return fetchMapTiles(args)
+ case "fetch-pal-icons":
+ return fetchPalIcons(args)
default:
- return fmt.Errorf("unknown subcommand %q (expected serve or parse)", command)
+ return fmt.Errorf("unknown subcommand %q (expected serve, parse, fetch-map-tiles, or fetch-pal-icons)", command)
+ }
+}
+func fetchMapTiles(args []string) error {
+ if len(args) == 0 {
+ dataDir := os.Getenv("PALHELM_DATA_DIR")
+ if dataDir == "" {
+ dataDir = "/data"
+ }
+ args = []string{filepath.Join(dataDir, "map-tiles")}
}
+ cmd := fetchMapTilesCommand(args...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("fetch map tiles: %w", err)
+ }
+ return nil
+}
+func fetchPalIcons(args []string) error {
+ if len(args) == 0 {
+ dataDir := os.Getenv("PALHELM_DATA_DIR")
+ if dataDir == "" {
+ dataDir = "/data"
+ }
+ args = []string{filepath.Join(dataDir, "pal-icons")}
+ }
+ cmd := fetchPalIconsCommand(args...)
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ if err := cmd.Run(); err != nil {
+ return fmt.Errorf("fetch pal icons: %w", err)
+ }
+ return nil
}
func parse(path string) error {
var v any
diff --git a/backend/cmd/palhelm/main_test.go b/backend/cmd/palhelm/main_test.go
new file mode 100644
index 0000000..22e56bd
--- /dev/null
+++ b/backend/cmd/palhelm/main_test.go
@@ -0,0 +1,106 @@
+package main
+
+import (
+ "os/exec"
+ "reflect"
+ "strings"
+ "testing"
+)
+
+func TestFetchMapTiles(t *testing.T) {
+ original := fetchMapTilesCommand
+ t.Cleanup(func() { fetchMapTilesCommand = original })
+
+ t.Run("uses data directory as default destination", func(t *testing.T) {
+ t.Setenv("PALHELM_DATA_DIR", "/custom/data")
+ var got []string
+ fetchMapTilesCommand = func(args ...string) *exec.Cmd {
+ got = append([]string(nil), args...)
+ return exec.Command("sh", "-c", "exit 0")
+ }
+
+ if err := fetchMapTiles(nil); err != nil {
+ t.Fatalf("fetchMapTiles() error = %v", err)
+ }
+ want := []string{"/custom/data/map-tiles"}
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("fetchMapTiles() args = %q, want %q", got, want)
+ }
+ })
+
+ t.Run("forwards explicit arguments", func(t *testing.T) {
+ var got []string
+ fetchMapTilesCommand = func(args ...string) *exec.Cmd {
+ got = append([]string(nil), args...)
+ return exec.Command("sh", "-c", "exit 0")
+ }
+ want := []string{"--dest", "/tiles", "--force"}
+
+ if err := fetchMapTiles(want); err != nil {
+ t.Fatalf("fetchMapTiles() error = %v", err)
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("fetchMapTiles() args = %q, want %q", got, want)
+ }
+ })
+
+ t.Run("returns downloader failure", func(t *testing.T) {
+ fetchMapTilesCommand = func(args ...string) *exec.Cmd {
+ return exec.Command("sh", "-c", "exit 17")
+ }
+
+ err := fetchMapTiles(nil)
+ if err == nil || !strings.Contains(err.Error(), "fetch map tiles: exit status 17") {
+ t.Fatalf("fetchMapTiles() error = %v", err)
+ }
+ })
+}
+
+func TestFetchPalIcons(t *testing.T) {
+ original := fetchPalIconsCommand
+ t.Cleanup(func() { fetchPalIconsCommand = original })
+
+ t.Run("uses data directory as default destination", func(t *testing.T) {
+ t.Setenv("PALHELM_DATA_DIR", "/custom/data")
+ var got []string
+ fetchPalIconsCommand = func(args ...string) *exec.Cmd {
+ got = append([]string(nil), args...)
+ return exec.Command("sh", "-c", "exit 0")
+ }
+
+ if err := fetchPalIcons(nil); err != nil {
+ t.Fatalf("fetchPalIcons() error = %v", err)
+ }
+ want := []string{"/custom/data/pal-icons"}
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("fetchPalIcons() args = %q, want %q", got, want)
+ }
+ })
+
+ t.Run("forwards explicit arguments", func(t *testing.T) {
+ var got []string
+ fetchPalIconsCommand = func(args ...string) *exec.Cmd {
+ got = append([]string(nil), args...)
+ return exec.Command("sh", "-c", "exit 0")
+ }
+ want := []string{"--force"}
+
+ if err := fetchPalIcons(want); err != nil {
+ t.Fatalf("fetchPalIcons() error = %v", err)
+ }
+ if !reflect.DeepEqual(got, want) {
+ t.Fatalf("fetchPalIcons() args = %q, want %q", got, want)
+ }
+ })
+
+ t.Run("returns downloader failure", func(t *testing.T) {
+ fetchPalIconsCommand = func(args ...string) *exec.Cmd {
+ return exec.Command("sh", "-c", "exit 17")
+ }
+
+ err := fetchPalIcons(nil)
+ if err == nil || !strings.Contains(err.Error(), "fetch pal icons: exit status 17") {
+ t.Fatalf("fetchPalIcons() error = %v", err)
+ }
+ })
+}
diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go
index 67d8bda..078d3d4 100644
--- a/backend/internal/config/config.go
+++ b/backend/internal/config/config.go
@@ -18,7 +18,7 @@ import (
type Config struct {
Addr, DataDir, AdminPassword, ViewerPassword, SessionSecret string
RESTURL, RESTUser, PalworldPassword, RCONAddr, SaveDir string
- ComposeFile, GameService string
+ ComposeFile, GameService, PanelService string
// SteamWebAPIKey is optional; when empty, player avatars resolve via Steam's
// keyless public community endpoint instead of the Web API.
SteamWebAPIKey string
@@ -40,6 +40,7 @@ func Load() (Config, error) {
PalworldPassword: os.Getenv("PALWORLD_ADMIN_PASSWORD"), RCONAddr: os.Getenv("PALWORLD_RCON_ADDR"),
SaveDir: os.Getenv("PALWORLD_SAVE_DIR"),
ComposeFile: os.Getenv("PALHELM_COMPOSE_FILE"), GameService: env("PALHELM_GAME_SERVICE", "palworld"),
+ PanelService: env("PALHELM_PANEL_SERVICE", "palhelm"),
SteamWebAPIKey: strings.TrimSpace(os.Getenv("STEAM_WEB_API_KEY")),
}
var err error
diff --git a/backend/internal/config/config_test.go b/backend/internal/config/config_test.go
index 2cf2e77..4ea4e3f 100644
--- a/backend/internal/config/config_test.go
+++ b/backend/internal/config/config_test.go
@@ -17,6 +17,26 @@ func TestLoadTrustedProxyAndSecureCookieSettings(t *testing.T) {
}
}
+func TestLoadPanelService(t *testing.T) {
+ t.Setenv("PALHELM_PANEL_SERVICE", "")
+ cfg, err := Load()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if cfg.PanelService != "palhelm" {
+ t.Fatalf("PanelService = %q, want palhelm", cfg.PanelService)
+ }
+
+ t.Setenv("PALHELM_PANEL_SERVICE", "dashboard")
+ cfg, err = Load()
+ if err != nil {
+ t.Fatal(err)
+ }
+ if cfg.PanelService != "dashboard" {
+ t.Fatalf("PanelService = %q, want dashboard", cfg.PanelService)
+ }
+}
+
func TestLoadRejectsInvalidTrustedProxy(t *testing.T) {
t.Setenv("PALHELM_TRUSTED_PROXIES", "not-a-cidr")
t.Setenv("PALHELM_SECURE_COOKIES", "")
diff --git a/backend/internal/server/docker_compose.go b/backend/internal/server/docker_compose.go
new file mode 100644
index 0000000..90c3412
--- /dev/null
+++ b/backend/internal/server/docker_compose.go
@@ -0,0 +1,66 @@
+package server
+
+import (
+ "os"
+ "strings"
+
+ "github.com/8tp/palhelm/internal/config"
+ "gopkg.in/yaml.v3"
+)
+
+type composeContainerNames struct {
+ Services map[string]struct {
+ ContainerName string `yaml:"container_name"`
+ } `yaml:"services"`
+}
+
+func mapTilesInstallCommand(cfg config.Config) string {
+ return installCommand(cfg, "fetch-map-tiles")
+}
+
+func palIconsInstallCommand(cfg config.Config) string {
+ return installCommand(cfg, "fetch-pal-icons")
+}
+
+func installCommand(cfg config.Config, command string) string {
+ service := strings.TrimSpace(cfg.PanelService)
+ if service == "" {
+ service = "palhelm"
+ }
+ if b, err := os.ReadFile(cfg.ComposeFile); err == nil {
+ var compose composeContainerNames
+ if yaml.Unmarshal(b, &compose) == nil {
+ name := strings.TrimSpace(compose.Services[service].ContainerName)
+ if validDockerName(name) {
+ return "docker exec " + name + " palhelm " + command
+ }
+ }
+ }
+ return "docker compose exec " + shellArg(service) + " palhelm " + command
+}
+
+func validDockerName(name string) bool {
+ if name == "" {
+ return false
+ }
+ for i, r := range name {
+ if i == 0 && !asciiAlphaNumeric(r) {
+ return false
+ }
+ if !asciiAlphaNumeric(r) && r != '_' && r != '.' && r != '-' {
+ return false
+ }
+ }
+ return true
+}
+
+func asciiAlphaNumeric(r rune) bool {
+ return r >= 'a' && r <= 'z' || r >= 'A' && r <= 'Z' || r >= '0' && r <= '9'
+}
+
+func shellArg(value string) string {
+ if validDockerName(value) {
+ return value
+ }
+ return "'" + strings.ReplaceAll(value, "'", "'\"'\"'") + "'"
+}
diff --git a/backend/internal/server/docker_compose_test.go b/backend/internal/server/docker_compose_test.go
new file mode 100644
index 0000000..cdcb94c
--- /dev/null
+++ b/backend/internal/server/docker_compose_test.go
@@ -0,0 +1,73 @@
+package server
+
+import (
+ "os"
+ "path/filepath"
+ "testing"
+
+ "github.com/8tp/palhelm/internal/config"
+)
+
+func TestMapTilesInstallCommand(t *testing.T) {
+ t.Run("uses explicit container name", func(t *testing.T) {
+ path := filepath.Join(t.TempDir(), "docker-compose.yml")
+ compose := "services:\n dashboard:\n container_name: palworld-dashboard\n"
+ if err := os.WriteFile(path, []byte(compose), 0o600); err != nil {
+ t.Fatal(err)
+ }
+ cfg := config.Config{ComposeFile: path, PanelService: "dashboard"}
+ if got, want := mapTilesInstallCommand(cfg), "docker exec palworld-dashboard palhelm fetch-map-tiles"; got != want {
+ t.Fatalf("mapTilesInstallCommand() = %q, want %q", got, want)
+ }
+ })
+
+ t.Run("falls back to compose service", func(t *testing.T) {
+ path := filepath.Join(t.TempDir(), "docker-compose.yml")
+ compose := "services:\n dashboard:\n image: palhelm\n"
+ if err := os.WriteFile(path, []byte(compose), 0o600); err != nil {
+ t.Fatal(err)
+ }
+ cfg := config.Config{ComposeFile: path, PanelService: "dashboard"}
+ if got, want := mapTilesInstallCommand(cfg), "docker compose exec dashboard palhelm fetch-map-tiles"; got != want {
+ t.Fatalf("mapTilesInstallCommand() = %q, want %q", got, want)
+ }
+ })
+
+ t.Run("does not render compose interpolation as shell", func(t *testing.T) {
+ path := filepath.Join(t.TempDir(), "docker-compose.yml")
+ compose := "services:\n palhelm:\n container_name: ${PALHELM_CONTAINER_NAME:-palhelm}\n"
+ if err := os.WriteFile(path, []byte(compose), 0o600); err != nil {
+ t.Fatal(err)
+ }
+ cfg := config.Config{ComposeFile: path}
+ if got, want := mapTilesInstallCommand(cfg), "docker compose exec palhelm palhelm fetch-map-tiles"; got != want {
+ t.Fatalf("mapTilesInstallCommand() = %q, want %q", got, want)
+ }
+ })
+}
+
+func TestPalIconsInstallCommand(t *testing.T) {
+ t.Run("uses explicit container name", func(t *testing.T) {
+ path := filepath.Join(t.TempDir(), "docker-compose.yml")
+ compose := "services:\n dashboard:\n container_name: palworld-dashboard\n"
+ if err := os.WriteFile(path, []byte(compose), 0o600); err != nil {
+ t.Fatal(err)
+ }
+ cfg := config.Config{ComposeFile: path, PanelService: "dashboard"}
+ if got, want := palIconsInstallCommand(cfg), "docker exec palworld-dashboard palhelm fetch-pal-icons"; got != want {
+ t.Fatalf("palIconsInstallCommand() = %q, want %q", got, want)
+ }
+ })
+
+ t.Run("falls back to compose service", func(t *testing.T) {
+ path := filepath.Join(t.TempDir(), "docker-compose.yml")
+ compose := "services:\n dashboard:\n image: palhelm\n"
+ if err := os.WriteFile(path, []byte(compose), 0o600); err != nil {
+ t.Fatal(err)
+ }
+ cfg := config.Config{ComposeFile: path, PanelService: "dashboard"}
+ if got, want := palIconsInstallCommand(cfg), "docker compose exec dashboard palhelm fetch-pal-icons"; got != want {
+ t.Fatalf("palIconsInstallCommand() = %q, want %q", got, want)
+ }
+ })
+}
diff --git a/backend/internal/server/openapi.json b/backend/internal/server/openapi.json
index dfd161c..6cb62f5 100644
--- a/backend/internal/server/openapi.json
+++ b/backend/internal/server/openapi.json
@@ -217,7 +217,7 @@
"PlayerPaldeckSpecies": {"type":"object","required":["characterId","displayName","known","captureCount","unlocked"],"properties":{"characterId":{"type":"string"},"displayName":{"type":"string"},"known":{"type":"boolean"},"captureCount":{"type":["integer","null"],"format":"int64","minimum":0},"unlocked":{"type":["boolean","null"]}}},
"PlayerPaldeck": {"type":"object","required":["player","coverage","catalog","captureTotal","uniquePalsCaptured","paldeckUnlocked","species"],"properties":{"player":{"type":"object","required":["uid","name"],"properties":{"uid":{"type":"string"},"name":{"type":"string"}}},"coverage":{"$ref":"#/components/schemas/PlayerPaldeckCoverage"},"catalog":{"$ref":"#/components/schemas/PaldeckCatalog"},"captureTotal":{"type":["integer","null"],"format":"int64","minimum":0},"uniquePalsCaptured":{"type":["integer","null"],"minimum":0},"paldeckUnlocked":{"type":["integer","null"],"minimum":0},"species":{"type":"array","maxItems":4096,"items":{"$ref":"#/components/schemas/PlayerPaldeckSpecies"}}}},
"GuildDetail": {"type":"object","required":["id","name","adminUid","memberCount","members","bases","palCount","palsTruncated","pals","activity"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"adminUid":{"type":"string"},"memberCount":{"type":"integer","minimum":0},"members":{"type":"array","items":{"type":"object","required":["uid","name","level","online","lastSeenAt","playtimeSec","captureTotal","uniquePalsCaptured","paldeckUnlocked","observedDurationSec","observedSessionCount","currentSession"],"properties":{"uid":{"type":"string"},"name":{"type":"string"},"level":{"type":"integer"},"online":{"type":"boolean"},"lastSeenAt":{"type":["string","null"],"format":"date-time"},"playtimeSec":{"type":"integer","format":"int64","minimum":0},"captureTotal":{"type":["integer","null"],"format":"int64","minimum":0},"uniquePalsCaptured":{"type":["integer","null"],"minimum":0},"paldeckUnlocked":{"type":["integer","null"],"minimum":0},"observedDurationSec":{"type":"integer","format":"int64","minimum":0},"observedSessionCount":{"type":"integer","minimum":0},"currentSession":{"type":"boolean"}}}},"bases":{"type":"array","items":{"type":"object","required":["id","name","location","level","palCount"],"properties":{"id":{"type":"string"},"name":{"type":["string","null"]},"location":{"oneOf":[{"$ref":"#/components/schemas/IntegrationLocation"},{"type":"null"}]},"level":{"type":"integer"},"palCount":{"type":"integer","minimum":0}}}},"palCount":{"type":"integer","minimum":0},"palsTruncated":{"type":"boolean"},"pals":{"type":"array","maxItems":500,"items":{"type":"object","required":["instanceId","characterId","displayName","level","rank","isAlpha","isLucky","isBoss","placement","baseId","ownerUid","ownerName","ownerSource","ownerResolved","association"],"properties":{"instanceId":{"type":"string"},"characterId":{"type":"string"},"displayName":{"type":"string"},"level":{"type":"integer"},"rank":{"type":["integer","null"],"minimum":1,"maximum":5,"description":"Pal Condenser rank: 1 (never condensed) through 5 (four stars). null when the save carried no Rank property; never inferred as 0."},"isAlpha":{"type":"boolean"},"isLucky":{"type":"boolean"},"isBoss":{"type":"boolean"},"placement":{"type":"string","enum":["party","box","base","unknown"]},"baseId":{"type":["string","null"]},"ownerUid":{"type":"string"},"ownerName":{"type":"string"},"ownerSource":{"type":"string","enum":["save","personal_container","last_observed","unresolved"]},"ownerResolved":{"type":"boolean"},"association":{"type":"string","enum":["guild_base","current_member_owner"]}}}},"activity":{"type":"object","required":["coverage","attribution","window","since","through","trackingSince","analysisTruncated","durationSec","sessionCount","activePlayers"],"properties":{"coverage":{"type":"string","const":"panel_observed_sessions"},"attribution":{"type":"string","const":"current_guild_membership"},"window":{"type":"string","const":"30d"},"since":{"type":"string","format":"date-time"},"through":{"type":"string","format":"date-time"},"trackingSince":{"type":["string","null"],"format":"date-time"},"analysisTruncated":{"type":"boolean"},"durationSec":{"type":"integer","format":"int64","minimum":0},"sessionCount":{"type":"integer","minimum":0},"activePlayers":{"type":"integer","minimum":0}}}}},
- "ServerInfo": {"type": "object", "required": ["name", "description", "version", "worldGuid", "state", "uptimeSec", "panelVersion", "sessionDays", "saveSyncMinutes"], "properties": {"name": {"type": "string"}, "description": {"type": "string"}, "version": {"type": "string"}, "worldGuid": {"type": "string"}, "state": {"type": "string"}, "uptimeSec": {"type": "integer", "format": "int64"}, "panelVersion": {"type": "string"}, "sessionDays": {"type": "integer", "minimum": 1, "description": "Login session lifetime in whole days (PALHELM_SESSION_DAYS)."}, "saveSyncMinutes": {"type": "integer", "minimum": 0, "description": "Save-sync poll interval in whole minutes (PALHELM_SAVE_SYNC_INTERVAL)."}}},
+ "ServerInfo": {"type": "object", "required": ["name", "description", "version", "worldGuid", "state", "uptimeSec", "panelVersion", "sessionDays", "saveSyncMinutes", "mapTilesCommand", "palIconsCommand"], "properties": {"name": {"type": "string"}, "description": {"type": "string"}, "version": {"type": "string"}, "worldGuid": {"type": "string"}, "state": {"type": "string"}, "uptimeSec": {"type": "integer", "format": "int64"}, "panelVersion": {"type": "string"}, "sessionDays": {"type": "integer", "minimum": 1, "description": "Login session lifetime in whole days (PALHELM_SESSION_DAYS)."}, "saveSyncMinutes": {"type": "integer", "minimum": 0, "description": "Save-sync poll interval in whole minutes (PALHELM_SAVE_SYNC_INTERVAL)."}, "mapTilesCommand": {"type": "string", "description": "Host command for installing map tiles, resolved from the panel service's Compose container_name when available."}, "palIconsCommand": {"type": "string", "description": "Host command for installing Pal icons, resolved from the panel service's Compose container_name when available."}}},
"BackupStorage": {"type": "object", "required": ["totalBytes", "freeBytes"], "properties": {"totalBytes": {"type": ["integer", "null"], "format": "int64", "minimum": 0, "description": "Total capacity of the backup filesystem, or null when unavailable."}, "freeBytes": {"type": ["integer", "null"], "format": "int64", "minimum": 0, "description": "Free space on the backup filesystem, or null when unavailable."}}},
"Backup": {"type": "object", "required": ["id", "file", "createdAt", "sizeBytes", "trigger"], "properties": {"id": {"type": "integer", "format": "int64"}, "file": {"type": "string"}, "createdAt": {"type": "string", "format": "date-time"}, "sizeBytes": {"type": "integer", "format": "int64", "minimum": 0}, "trigger": {"type": "string", "enum": ["scheduled", "manual", "pre-restore", "imported"]}, "worldDay": {"type": "integer", "format": "int64"}}},
"BackupEntry": {"type": "object", "required": ["path", "sizeBytes", "modifiedAt"], "properties": {"path": {"type": "string"}, "sizeBytes": {"type": "integer", "format": "int64", "minimum": 0}, "modifiedAt": {"type": "string", "format": "date-time"}}},
diff --git a/backend/internal/server/server.go b/backend/internal/server/server.go
index 4864776..8ccea7b 100644
--- a/backend/internal/server/server.go
+++ b/backend/internal/server/server.go
@@ -321,7 +321,7 @@ func (s *Server) serverInfo(w http.ResponseWriter, r *http.Request) {
if days < 1 {
days = 7
}
- writeJSON(w, 200, map[string]any{"name": i.ServerName, "description": i.Description, "version": i.Version, "worldGuid": i.WorldGUID, "state": state, "uptimeSec": i.Uptime, "panelVersion": PanelVersion, "sessionDays": days, "saveSyncMinutes": int(s.cfg.SaveSyncInterval.Minutes())})
+ writeJSON(w, 200, map[string]any{"name": i.ServerName, "description": i.Description, "version": i.Version, "worldGuid": i.WorldGUID, "state": state, "uptimeSec": i.Uptime, "panelVersion": PanelVersion, "sessionDays": days, "saveSyncMinutes": int(s.cfg.SaveSyncInterval.Minutes()), "mapTilesCommand": mapTilesInstallCommand(s.cfg), "palIconsCommand": palIconsInstallCommand(s.cfg)})
}
func (s *Server) serverHealth(w http.ResponseWriter, r *http.Request) {
rest, rcon, save, at := s.health.Snapshot()
diff --git a/backend/internal/webdist/dist/assets/Activity-CN5lRrug.css b/backend/internal/webdist/dist/assets/Activity-CN5lRrug.css
new file mode 100644
index 0000000..327cfa0
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Activity-CN5lRrug.css
@@ -0,0 +1 @@
+.activity-page{gap:var(--space-4);flex-direction:column;display:flex}.activity-head{justify-content:space-between;align-items:flex-end;row-gap:var(--space-2);flex-wrap:wrap}.activity-window-tabs{border:1px solid var(--line);border-radius:var(--radius-ctl);background:var(--surface-2);gap:4px;padding:3px;display:flex}.activity-window-tabs button{color:var(--ink-3);font-size:var(--text-xs);cursor:pointer;background:0 0;border:0;border-radius:5px;padding:5px 10px}.activity-window-tabs button.is-active{color:var(--accent-ink);background:var(--surface);box-shadow:inset 0 0 0 1px var(--line-strong)}.activity-skeleton{width:100%;height:180px}.activity-kpis{gap:var(--space-3);grid-template-columns:repeat(3,1fr);display:grid}.activity-kpi{flex-direction:column;gap:4px;display:flex}.activity-kpi span{color:var(--ink-3);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--track-caps)}.activity-kpi strong{font-family:var(--font-mono);font-size:var(--text-2xl);font-variant-numeric:tabular-nums}.activity-kpi small{color:var(--ink-3);font-size:var(--text-xs)}.activity-layout{gap:var(--space-3);grid-template-columns:minmax(0,1.5fr) minmax(300px,1fr);align-items:start;display:grid}.activity-bars{border-bottom:1px solid var(--line-strong);align-items:flex-end;gap:3px;height:190px;padding-top:8px;display:flex}.activity-bar-slot{flex:1;align-items:flex-end;min-width:2px;height:100%;display:flex}.activity-bar-slot>span{background:var(--accent);opacity:.78;border-radius:2px 2px 0 0;width:100%;min-height:2px}.activity-bar-slot:hover>span{opacity:1}.activity-chart-foot{color:var(--ink-3);justify-content:space-between;gap:12px;padding-top:7px;font-size:10px;display:flex}.activity-peak-list>div{border-bottom:1px solid var(--line);font-size:var(--text-xs);grid-template-columns:28px minmax(0,1fr) auto;align-items:center;gap:8px;padding:11px 14px;display:grid}.activity-peak-list>div:last-child{border-bottom:0}.activity-peak-list b{color:var(--accent-ink);font-family:var(--font-mono)}.activity-peak-list strong{color:var(--ink-2);font-family:var(--font-mono);font-size:10px}.activity-table-wrap{overflow-x:auto}.activity-table td strong,.activity-table td small{display:block}.activity-table td small{color:var(--ink-3);margin-top:2px;font-size:10px}.activity-attribution-note{border-top:1px solid var(--line);color:var(--ink-3);margin:0;padding:10px 14px;font-size:10px;line-height:1.45}@media (width<=900px){.activity-layout{grid-template-columns:1fr}}@media (width<=700px){.activity-head{align-items:stretch}.activity-window-tabs{align-self:flex-start}.activity-kpis{grid-template-columns:1fr}}
diff --git a/backend/internal/webdist/dist/assets/Activity-DUaeqEfU.js b/backend/internal/webdist/dist/assets/Activity-DUaeqEfU.js
new file mode 100644
index 0000000..f25f969
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Activity-DUaeqEfU.js
@@ -0,0 +1 @@
+import{U as e,_t as t,ht as n,j as r,q as i}from"./icons-CpYMTu_k.js";import{Mn as a,s as o}from"./index-BpCavHBc.js";import{t as s}from"./Banner-DSN1nEJn.js";import{n as c,r as l,t as u}from"./Card-D55CMzdw.js";import{t as d}from"./EmptyState-DTSMkv56.js";var f=t(n(),1);function p(e,t=3){return[...e].sort((e,t)=>t.averagePlayers-e.averagePlayers||t.peakPlayers-e.peakPlayers||e.at.localeCompare(t.at)).slice(0,Math.max(0,t))}function m(e){return e.analysisTruncated?`Analysis hit its cap; rankings and concurrency may be incomplete.`:e.trackingSince?new Date(e.trackingSince)>new Date(e.since)?`Tracking began ${new Date(e.trackingSince).toLocaleString()}, partway through this window.`:`Tracking since ${new Date(e.trackingSince).toLocaleString()} — the full window is covered.`:`No player sessions observed yet.`}function h(e,t){let n=new Date(e);return t>=86400?n.toLocaleDateString(void 0,{month:`short`,day:`numeric`}):n.toLocaleString(void 0,{weekday:`short`,hour:`numeric`})}var g=i(),_=[{value:`24h`,label:`24 hours`},{value:`7d`,label:`7 days`},{value:`30d`,label:`30 days`}];function v(){let[t,n]=(0,f.useState)(`7d`),i=e({queryKey:[`activity`,t],queryFn:()=>r.activity.get(t),refetchInterval:6e4}),v=i.data,b=Math.max(1,...v?.concurrency.map(e=>e.peakPlayers)??[1]),x=p(v?.concurrency??[]);return(0,g.jsxs)(`main`,{className:`content activity-page`,children:[(0,g.jsxs)(`div`,{className:`page-head activity-head`,children:[(0,g.jsxs)(`div`,{children:[(0,g.jsx)(`h1`,{children:`Player activity`}),(0,g.jsx)(`span`,{className:`sub`,children:`observed sessions · rolling windows`})]}),(0,g.jsx)(`div`,{className:`activity-window-tabs`,"aria-label":`Activity window`,children:_.map(e=>(0,g.jsx)(`button`,{type:`button`,className:t===e.value?`is-active`:``,onClick:()=>n(e.value),children:e.label},e.value))})]}),i.isError?(0,g.jsx)(s,{tone:`warn`,children:`Couldn't load observed player activity.`}):i.isPending||!v?(0,g.jsx)(u,{children:(0,g.jsx)(c,{children:(0,g.jsx)(`span`,{className:`skel skel-text activity-skeleton`})})}):v.activePlayers===0?(0,g.jsx)(u,{children:(0,g.jsx)(c,{children:(0,g.jsx)(d,{title:`No observed sessions`,description:`Activity appears once players join while the panel is running.`})})}):(0,g.jsxs)(g.Fragment,{children:[(0,g.jsxs)(s,{tone:v.analysisTruncated?`warn`:`info`,children:[m(v),` Only sessions observed by this panel are counted.`]}),(0,g.jsxs)(`div`,{className:`activity-kpis`,children:[(0,g.jsx)(y,{label:`Active players`,value:String(v.activePlayers),detail:`${v.newPlayers} first observed · ${v.returningPlayers} returning`}),(0,g.jsx)(y,{label:`Peak concurrency`,value:String(v.peakConcurrency),detail:v.peakAt?new Date(v.peakAt).toLocaleString():`No peak observed`}),(0,g.jsx)(y,{label:`In a guild`,value:String(v.activePlayers-v.unattributedPlayers),detail:`${v.unattributedPlayers} without a current guild`})]}),(0,g.jsxs)(`div`,{className:`activity-layout`,children:[(0,g.jsxs)(u,{className:`activity-concurrency-card`,children:[(0,g.jsx)(l,{title:`Concurrency`,hint:`${o(v.bucketSec)} buckets`}),(0,g.jsxs)(c,{children:[(0,g.jsx)(`div`,{className:`activity-bars`,"aria-label":`Observed concurrency timeline`,children:v.concurrency.map(e=>(0,g.jsx)(`div`,{className:`activity-bar-slot`,title:`${h(e.at,v.bucketSec)} · avg ${e.averagePlayers.toFixed(1)} · peak ${e.peakPlayers}`,children:(0,g.jsx)(`span`,{style:{height:`${Math.max(2,e.averagePlayers/b*100)}%`}})},e.at))}),(0,g.jsxs)(`div`,{className:`activity-chart-foot`,children:[(0,g.jsx)(`span`,{children:new Date(v.since).toLocaleString()}),(0,g.jsx)(`span`,{children:new Date(v.through).toLocaleString()})]})]})]}),(0,g.jsxs)(u,{children:[(0,g.jsx)(l,{title:`Peak hours`,hint:`browser local time`}),(0,g.jsx)(c,{flush:!0,children:(0,g.jsx)(`div`,{className:`activity-peak-list`,children:x.map((e,t)=>(0,g.jsxs)(`div`,{children:[(0,g.jsxs)(`b`,{children:[`#`,t+1]}),(0,g.jsx)(`span`,{children:h(e.at,v.bucketSec)}),(0,g.jsxs)(`strong`,{children:[e.averagePlayers.toFixed(1),` avg · `,e.peakPlayers,` peak`]})]},e.at))})})]})]}),(0,g.jsxs)(`div`,{className:`activity-layout`,children:[(0,g.jsxs)(u,{children:[(0,g.jsx)(l,{title:`Most active players`,hint:`top ${v.players.length} · selected window`}),(0,g.jsx)(c,{flush:!0,className:`activity-table-wrap`,children:(0,g.jsxs)(`table`,{className:`table activity-table`,children:[(0,g.jsx)(`thead`,{children:(0,g.jsxs)(`tr`,{children:[(0,g.jsx)(`th`,{children:`Player`}),(0,g.jsx)(`th`,{children:`Observed`}),(0,g.jsx)(`th`,{children:`Sessions`})]})}),(0,g.jsx)(`tbody`,{children:v.players.map(e=>(0,g.jsxs)(`tr`,{children:[(0,g.jsxs)(`td`,{children:[(0,g.jsx)(`strong`,{children:e.name||`Unknown player`}),(0,g.jsx)(`small`,{children:e.firstObserved?`New this window`:e.currentSession?`Online now`:e.guildName||`No current guild`})]}),(0,g.jsx)(`td`,{className:`num`,children:o(e.durationSec)}),(0,g.jsx)(`td`,{className:`num`,children:e.sessionCount})]},e.uid))})]})})]}),(0,g.jsxs)(u,{children:[(0,g.jsx)(l,{title:`Guild activity`,hint:`credited to current membership`}),v.guilds.length===0?(0,g.jsx)(c,{children:(0,g.jsx)(d,{title:`No attributable guild activity`,description:`Observed players do not currently have guild evidence.`})}):(0,g.jsxs)(c,{flush:!0,className:`activity-table-wrap`,children:[(0,g.jsxs)(`table`,{className:`table activity-table`,children:[(0,g.jsx)(`thead`,{children:(0,g.jsxs)(`tr`,{children:[(0,g.jsx)(`th`,{children:`Guild`}),(0,g.jsx)(`th`,{children:`Observed`}),(0,g.jsx)(`th`,{children:`Players`})]})}),(0,g.jsx)(`tbody`,{children:v.guilds.map(e=>(0,g.jsxs)(`tr`,{children:[(0,g.jsxs)(`td`,{children:[(0,g.jsx)(`strong`,{children:(0,g.jsx)(a,{to:`/guilds/${encodeURIComponent(e.guildId)}`,children:e.guildName||`Unnamed guild`})}),(0,g.jsxs)(`small`,{children:[e.sessionCount,` observed sessions`]})]}),(0,g.jsx)(`td`,{className:`num`,children:o(e.durationSec)}),(0,g.jsx)(`td`,{className:`num`,children:e.activePlayers})]},e.guildId))})]}),(0,g.jsx)(`p`,{className:`activity-attribution-note`,children:`Time is credited to each player's current guild; past membership is not stored.`})]})]})]})]})]})}function y({label:e,value:t,detail:n}){return(0,g.jsx)(u,{children:(0,g.jsxs)(c,{className:`activity-kpi`,children:[(0,g.jsx)(`span`,{children:e}),(0,g.jsx)(`strong`,{children:t}),(0,g.jsx)(`small`,{children:n})]})})}export{v as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Backups-BhZCFkO5.js b/backend/internal/webdist/dist/assets/Backups-BhZCFkO5.js
new file mode 100644
index 0000000..e6df34d
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Backups-BhZCFkO5.js
@@ -0,0 +1 @@
+import{D as e,H as t,K as n,U as r,_t as i,ht as a,j as o,q as s,r as c}from"./icons-CpYMTu_k.js";import{t as l}from"./useMutation-S28PAV4D.js";import{n as u,r as d,t as f}from"./DropdownMenu-fCf3CXmF.js";import{An as p,Dn as m,a as h,d as g,f as _,i as v,o as y,p as b,s as x}from"./index-BpCavHBc.js";import{t as S}from"./Banner-DSN1nEJn.js";import{n as C,r as w,t as T}from"./Card-D55CMzdw.js";import{t as E}from"./EmptyState-DTSMkv56.js";import{t as D}from"./CodeWell-Mu33yg_R.js";var O=i(a(),1),k=s();function A({value:e,max:t}){let n=t>0?Math.max(0,Math.min(100,e/t*100)):0;return(0,k.jsx)(`div`,{className:`meter`,children:(0,k.jsx)(`div`,{className:`fill`,style:{width:`${n}%`}})})}var j={add:`add`,modify:`chg`,delete:`rem`},M={add:`+`,modify:`~`,delete:`−`};function N({items:e}){return(0,k.jsx)(`div`,{className:`diff-list`,children:e.map((e,t)=>(0,k.jsxs)(`div`,{className:j[e.kind],children:[M[e.kind],` `,e.text]},t))})}var P={scheduled:`idle`,manual:`ok`,"pre-restore":`warn`,imported:`idle`};function F(){let e=p(),t=n(),i=m(),a=r({queryKey:[`backups`],queryFn:()=>o.backups.list()}),s=r({queryKey:[`backups`,`schedule`],queryFn:()=>o.backups.schedule()}),b=r({queryKey:[`backups`,`storage`],queryFn:()=>o.backups.storage()}),[D,j]=(0,O.useState)(``),[M,N]=(0,O.useState)(`all`),[F,z]=(0,O.useState)(null),[B,V]=(0,O.useState)(null),[H,U]=(0,O.useState)(null),W=l({mutationFn:()=>o.backups.create(),onSuccess:e=>{t.invalidateQueries({queryKey:[`backups`]}),i.push(`Backup ${e.file} created.`,`ok`)},onError:()=>i.push(`Backup failed to start. Check the panel logs.`,`danger`)}),G=(0,O.useMemo)(()=>a.data??[],[a.data]),K=(0,O.useMemo)(()=>{let e=D.trim().toLowerCase();return G.filter(t=>!(M!==`all`&&t.trigger!==M||e&&!t.file.toLowerCase().includes(e)))},[G,D,M]),q=G.reduce((e,t)=>e+t.sizeBytes,0),J=G[G.length-1],Y=s.data?.nextRunAt?new Date(s.data.nextRunAt).getTime()-Date.now():null;return(0,k.jsxs)(`main`,{className:`content`,children:[(0,k.jsxs)(`div`,{className:`page-head`,children:[(0,k.jsx)(`h1`,{children:`Backups`}),(0,k.jsx)(`span`,{className:`sub`,children:a.data?`${G.length} snapshots · ${h(q)}`:`loading…`})]}),(0,k.jsxs)(`div`,{className:`backups-layout`,children:[(0,k.jsxs)(`div`,{className:`backups-main`,children:[(0,k.jsxs)(`div`,{className:`toolbar`,children:[e&&(0,k.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:W.isPending,onClick:()=>W.mutate(),children:W.isPending?`Backing up…`:`Back up now`}),(0,k.jsx)(v,{placeholder:`Search snapshots…`,value:D,onChange:e=>j(e.target.value),"aria-label":`Search snapshots`}),(0,k.jsxs)(`select`,{className:`input`,style:{width:`auto`},value:M,onChange:e=>N(e.target.value),"aria-label":`Filter by trigger`,children:[(0,k.jsx)(`option`,{value:`all`,children:`All triggers`}),(0,k.jsx)(`option`,{value:`scheduled`,children:`Scheduled`}),(0,k.jsx)(`option`,{value:`manual`,children:`Manual`}),(0,k.jsx)(`option`,{value:`pre-restore`,children:`Pre-restore`}),(0,k.jsx)(`option`,{value:`imported`,children:`Imported`})]}),(0,k.jsx)(`div`,{className:`spacer`}),s.data?.enabled&&Y!==null&&Y>0&&(0,k.jsxs)(`span`,{className:`next-hint`,children:[`next scheduled backup in `,x(Y/1e3)]})]}),(0,k.jsx)(T,{children:a.isError?(0,k.jsx)(C,{children:(0,k.jsx)(S,{tone:`warn`,children:`Couldn't load backups. Check the panel's data volume.`})}):a.isLoading?(0,k.jsx)(C,{children:(0,k.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:120}})}):K.length===0?(0,k.jsx)(C,{children:(0,k.jsx)(E,{icon:(0,k.jsx)(c,{}),title:G.length===0?`No backups yet`:`No snapshots match`,description:G.length===0?`Create one now or enable the schedule — snapshots of the world save appear here.`:`Try a different search or trigger filter.`})}):(0,k.jsx)(C,{flush:!0,style:{overflowX:`auto`},children:(0,k.jsxs)(`table`,{className:`table`,children:[(0,k.jsx)(`thead`,{children:(0,k.jsxs)(`tr`,{children:[(0,k.jsx)(`th`,{children:`Snapshot`}),(0,k.jsx)(`th`,{children:`Created`}),(0,k.jsx)(`th`,{children:`Size`}),(0,k.jsx)(`th`,{children:`Trigger`}),(0,k.jsx)(`th`,{className:`actions`})]})}),(0,k.jsx)(`tbody`,{children:K.map(t=>(0,k.jsxs)(O.Fragment,{children:[(0,k.jsxs)(`tr`,{className:F===t.id?`row-selected`:void 0,children:[(0,k.jsxs)(`td`,{children:[(0,k.jsx)(`div`,{className:`snap-name`,children:t.file}),t.worldDay!==void 0&&(0,k.jsxs)(`div`,{className:`snap-day`,children:[`Day `,t.worldDay]})]}),(0,k.jsx)(`td`,{className:`num`,children:y(t.createdAt)}),(0,k.jsx)(`td`,{className:`num`,children:h(t.sizeBytes)}),(0,k.jsx)(`td`,{children:(0,k.jsx)(g,{tone:P[t.trigger],children:t.trigger})}),(0,k.jsx)(`td`,{className:`actions`,children:(0,k.jsxs)(f,{triggerLabel:`Actions for ${t.file}`,children:[(0,k.jsx)(u,{onClick:()=>z(F===t.id?null:t.id),children:F===t.id?`Hide contents`:`Browse contents`}),e&&(0,k.jsx)(u,{onClick:()=>V(t),children:`Restore…`}),(0,k.jsx)(d,{href:`/api/v1/backups/${t.id}/download`,download:!0,children:`Download`}),e&&(0,k.jsx)(u,{danger:!0,onClick:()=>U(t),children:`Delete`})]})})]}),F===t.id&&(0,k.jsx)(`tr`,{className:`row-selected`,children:(0,k.jsx)(`td`,{colSpan:5,style:{padding:0},children:(0,k.jsx)(I,{backup:t,onClose:()=>z(null)})})})]},t.id))})]})})})]}),(0,k.jsxs)(`aside`,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-4)`},children:[(0,k.jsx)(R,{}),(0,k.jsxs)(T,{children:[(0,k.jsx)(w,{title:`Storage`}),(0,k.jsx)(C,{children:(()=>{let e=b.data?.totalBytes??null,t=b.data?.freeBytes??null,n=`${G.length} snapshots kept${J?` · oldest ${x((Date.now()-new Date(J.createdAt).getTime())/1e3)} ago`:``}`;return(0,k.jsxs)(`div`,{className:`stat`,style:{padding:0},children:[(0,k.jsx)(`span`,{className:`label`,children:`Used by backups`}),(0,k.jsxs)(`div`,{className:`value`,children:[h(q),e!==null&&(0,k.jsxs)(`small`,{children:[` of `,h(e)]})]}),e===null?(0,k.jsxs)(`div`,{className:`delta`,children:[n,(0,k.jsx)(`div`,{style:{marginTop:4,color:`var(--ink-3)`},children:`Total volume capacity isn't reported by this panel build.`})]}):(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`div`,{style:{marginTop:10},children:(0,k.jsx)(A,{value:q,max:e})}),(0,k.jsxs)(`div`,{className:`delta`,children:[n,t===null?``:` · ${h(t)} free on volume`]})]})]})})()})]})]})]}),(0,k.jsx)(L,{backup:B,onClose:()=>V(null)}),(0,k.jsx)(_,{open:H!==null,title:`Delete ${H?.file??``}`,onClose:()=>U(null),danger:!0,confirmLabel:`Delete snapshot`,onConfirm:async()=>{if(H){try{await o.backups.remove(H.id),t.invalidateQueries({queryKey:[`backups`]}),i.push(`Snapshot deleted.`,`ok`)}catch{i.push(`Couldn't delete the snapshot.`,`danger`)}U(null)}},children:(0,k.jsx)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:`Permanently removes this snapshot from the backup volume. This can't be undone.`})})]})}function I({backup:e,onClose:t}){let n=r({queryKey:[`backups`,e.id,`contents`],queryFn:()=>o.backups.contents(e.id)});return(0,k.jsxs)(`div`,{className:`contents-drawer`,children:[(0,k.jsxs)(`h3`,{children:[`Contents — `,e.file]}),n.isError?(0,k.jsx)(S,{tone:`warn`,children:`Couldn't read the archive contents.`}):n.isLoading?(0,k.jsx)(`span`,{className:`skel skel-text`,style:{width:`60%`}}):(0,k.jsx)(`div`,{className:`contents-list`,children:(n.data??[]).map(e=>(0,k.jsxs)(`div`,{className:`row`,children:[(0,k.jsx)(`span`,{className:`path`,children:e.path}),(0,k.jsx)(`span`,{className:`size`,children:h(e.sizeBytes)})]},e.path))}),(0,k.jsx)(`div`,{children:(0,k.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:t,children:`Close`})})]})}function L({backup:i,onClose:a}){let s=n(),c=m(),[u,d]=(0,O.useState)(``),[f,p]=(0,O.useState)(null),g=r({queryKey:[`backups`,i?.id,`dry-run`],queryFn:()=>o.backups.dryRun(i.id),enabled:i!==null,staleTime:0}),_=l({mutationFn:()=>o.backups.restore(i.id,u),onSuccess:()=>{s.invalidateQueries({queryKey:[`backups`]}),c.push(`Restore started. A pre-restore backup was taken first.`,`ok`),v()},onError:e=>{p(e instanceof t?e:new t(0,`unknown`,`Restore failed. Try again.`))}});function v(){d(``),p(null),a()}let y=(g.data??{changes:[]}).changes.map(e=>({kind:e.kind,text:e.kind===`modify`&&e.fromSize!==void 0&&e.toSize!==void 0?`${e.path} (${h(e.fromSize)} → ${h(e.toSize)})`:e.kind===`add`&&e.toSize!==void 0?`${e.path} (new)`:e.path})),x=typeof f?.extra.manualCommand==`string`?f.extra.manualCommand:null;return(0,k.jsx)(b,{open:i!==null,title:`Restore ${i?.file??``}`,onClose:v,footer:(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:v,children:`Cancel`}),(0,k.jsx)(`button`,{type:`button`,className:`btn btn-danger-solid`,disabled:u!==`RESTORE`||_.isPending||g.isLoading||g.isError,onClick:()=>_.mutate(),children:_.isPending?`Restoring…`:`Restore this snapshot`})]}),children:g.isError?(0,k.jsx)(S,{tone:`warn`,children:`Couldn't compute the restore dry-run. Try again.`}):g.isLoading?(0,k.jsxs)(k.Fragment,{children:[(0,k.jsx)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:`Comparing the snapshot against the live save…`}),(0,k.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:48}})]}):(0,k.jsxs)(k.Fragment,{children:[(0,k.jsxs)(`div`,{className:`dryrun`,children:[(0,k.jsx)(`h3`,{children:`Restore dry-run — changes vs the live save`}),(0,k.jsx)(N,{items:y}),(0,k.jsxs)(`div`,{className:`banner banner-warn`,children:[(0,k.jsx)(e,{}),`Restoring requires stopping the server. A pre-restore backup is always taken first.`]}),f&&(0,k.jsxs)(k.Fragment,{children:[(0,k.jsxs)(`div`,{className:`banner`,style:{background:`var(--danger-soft)`,borderColor:`transparent`,color:`var(--danger-ink)`},children:[(0,k.jsx)(e,{}),f.message]}),x&&(0,k.jsx)(D,{children:x})]})]}),(0,k.jsxs)(`div`,{className:`field confirm-word`,children:[(0,k.jsxs)(`label`,{htmlFor:`confirm-restore`,children:[`Type `,(0,k.jsx)(`b`,{style:{fontFamily:`var(--font-mono)`},children:`RESTORE`}),` to confirm`]}),(0,k.jsx)(`input`,{id:`confirm-restore`,className:`input`,value:u,onChange:e=>{d(e.target.value),f&&p(null)},autoComplete:`off`,spellCheck:!1})]})]})})}function R(){let e=p(),t=n(),i=m(),a=r({queryKey:[`backups`,`schedule`],queryFn:()=>o.backups.schedule()}),s=l({mutationFn:e=>o.backups.setSchedule({...a.data,...e}),onSuccess:e=>{t.setQueryData([`backups`,`schedule`],e),i.push(`Backup schedule updated.`,`ok`)},onError:()=>i.push(`Couldn't update the schedule.`,`danger`)}),c=a.data,u=c?.enabled&&c.nextRunAt?new Date(c.nextRunAt).getTime()-Date.now():null;return(0,k.jsxs)(T,{children:[(0,k.jsx)(w,{title:`Schedule`,children:c&&(0,k.jsx)(g,{tone:c.enabled?`ok`:`idle`,children:c.enabled?`Enabled`:`Off`})}),a.isError?(0,k.jsx)(C,{children:(0,k.jsx)(S,{tone:`warn`,children:`Couldn't load the schedule.`})}):c?(0,k.jsxs)(C,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-3)`},children:[(0,k.jsxs)(`div`,{className:`field`,children:[(0,k.jsx)(`label`,{htmlFor:`sched-every`,children:`Every`}),(0,k.jsxs)(`select`,{id:`sched-every`,className:`input`,value:c.everyMinutes,disabled:!e||s.isPending,onChange:e=>s.mutate({everyMinutes:Number(e.target.value)}),children:[(0,k.jsx)(`option`,{value:60,children:`1 hour`}),(0,k.jsx)(`option`,{value:120,children:`2 hours`}),(0,k.jsx)(`option`,{value:240,children:`4 hours`}),(0,k.jsx)(`option`,{value:360,children:`6 hours`}),(0,k.jsx)(`option`,{value:720,children:`12 hours`})]})]}),(0,k.jsxs)(`div`,{className:`field`,children:[(0,k.jsx)(`label`,{htmlFor:`sched-keep`,children:`Keep`}),(0,k.jsxs)(`select`,{id:`sched-keep`,className:`input`,value:c.keepDays,disabled:!e||s.isPending,onChange:e=>s.mutate({keepDays:Number(e.target.value)}),children:[(0,k.jsx)(`option`,{value:7,children:`7 days`}),(0,k.jsx)(`option`,{value:14,children:`14 days`}),(0,k.jsx)(`option`,{value:30,children:`30 days`}),(0,k.jsx)(`option`,{value:60,children:`60 days`})]})]}),(0,k.jsxs)(`div`,{className:`sched-next`,children:[(0,k.jsx)(`span`,{className:`label`,children:`Next run`}),(0,k.jsxs)(`span`,{className:`num`,children:[c.enabled&&c.nextRunAt?new Date(c.nextRunAt).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`,hour12:!1}):`Not scheduled`,` `,u!==null&&u>0&&(0,k.jsxs)(`span`,{style:{color:`var(--ink-3)`},children:[`· in `,x(u/1e3)]})]})]})]}):(0,k.jsx)(C,{children:(0,k.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:60}})})]})}export{F as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Backups-hnJGe2yy.css b/backend/internal/webdist/dist/assets/Backups-hnJGe2yy.css
new file mode 100644
index 0000000..56b2522
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Backups-hnJGe2yy.css
@@ -0,0 +1 @@
+.backups-layout{gap:var(--space-4);grid-template-columns:1fr 300px;align-items:start;display:grid}@media (width<=1100px){.backups-layout{grid-template-columns:1fr}}.backups-main{gap:var(--space-3);flex-direction:column;min-width:0;display:flex}.toolbar{gap:var(--space-2);align-items:center;display:flex}.toolbar .search{width:300px}.toolbar .spacer{flex:1}.toolbar .next-hint{color:var(--ink-3);font-size:var(--text-xs)}.snap-name{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink);white-space:nowrap}.snap-day{font-family:var(--font-mono);color:var(--ink-3);margin-top:2px;font-size:11px}.table .num{white-space:nowrap}.contents-drawer{background:var(--bg);border-top:1px solid var(--line);padding:var(--space-4);gap:var(--space-3);flex-direction:column;display:flex}.contents-drawer h3{font-size:var(--text-sm);color:var(--ink);font-weight:600}.contents-list{font-family:var(--font-mono);font-size:var(--text-sm);background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);flex-direction:column;gap:4px;padding:10px 14px;display:flex}.contents-list .row{gap:var(--space-4);display:flex}.contents-list .row .path{text-overflow:ellipsis;flex:1;min-width:0;overflow:hidden}.contents-list .row .size{color:var(--ink-3);font-variant-numeric:tabular-nums}.dryrun{background:var(--bg);border-radius:var(--radius-ctl);box-shadow:inset 3px 0 0 var(--accent);padding:var(--space-4);gap:var(--space-3);flex-direction:column;display:flex}.dryrun h3{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink);font-weight:600}.sched-next{padding-top:var(--space-2);border-top:1px solid var(--line);justify-content:space-between;align-items:center;display:flex}.sched-next .label{font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3)}.sched-next .num{font-family:var(--font-mono);font-size:var(--text-sm)}.confirm-word .input{font-family:var(--font-mono);letter-spacing:.08em}
diff --git a/backend/internal/webdist/dist/assets/Banner-DSN1nEJn.js b/backend/internal/webdist/dist/assets/Banner-DSN1nEJn.js
new file mode 100644
index 0000000..d6a5feb
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Banner-DSN1nEJn.js
@@ -0,0 +1 @@
+import{D as e,p as t,q as n}from"./icons-CpYMTu_k.js";var r=n();function i({tone:n,children:i}){return(0,r.jsxs)(`div`,{className:`banner banner-${n}`,children:[n===`info`?(0,r.jsx)(`span`,{className:`stamp-i`,"aria-hidden":`true`,children:(0,r.jsx)(t,{})}):(0,r.jsx)(e,{}),(0,r.jsx)(`span`,{children:i})]})}export{i as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Card-D55CMzdw.js b/backend/internal/webdist/dist/assets/Card-D55CMzdw.js
new file mode 100644
index 0000000..d923ee5
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Card-D55CMzdw.js
@@ -0,0 +1 @@
+import{q as e}from"./icons-CpYMTu_k.js";var t=e();function n({children:e,className:n=``,span2:r=!1,style:i}){return(0,t.jsx)(`div`,{className:[`card`,r?`span-2`:``,n].filter(Boolean).join(` `),style:i,children:e})}function r({title:e,hint:n,children:r}){return(0,t.jsxs)(`div`,{className:`card-head`,children:[(0,t.jsx)(`h2`,{children:e}),n&&(0,t.jsx)(`span`,{className:`hint`,children:n}),(0,t.jsx)(`div`,{className:`spacer`}),r]})}function i({children:e,flush:n=!1,chart:r=!1,className:i=``,style:a}){let o=[`card-body`,n?`flush`:``,r?`chart`:``,i].filter(Boolean).join(` `);return(0,t.jsx)(`div`,{className:o,style:a,children:e})}export{i as n,r,n as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/CodeWell-Mu33yg_R.js b/backend/internal/webdist/dist/assets/CodeWell-Mu33yg_R.js
new file mode 100644
index 0000000..c6fed03
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/CodeWell-Mu33yg_R.js
@@ -0,0 +1 @@
+import{q as e}from"./icons-CpYMTu_k.js";var t=e();function n({children:e}){return(0,t.jsx)(`div`,{className:`code-well`,children:e})}export{n as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Config-CLoXdISl.js b/backend/internal/webdist/dist/assets/Config-CLoXdISl.js
new file mode 100644
index 0000000..f15e6ec
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Config-CLoXdISl.js
@@ -0,0 +1 @@
+import{H as e,K as t,P as n,U as r,_t as i,ht as a,j as o,q as s}from"./icons-CpYMTu_k.js";import{t as c}from"./useMutation-S28PAV4D.js";import{An as l,Dn as u,d}from"./index-BpCavHBc.js";import{t as f}from"./Banner-DSN1nEJn.js";import{n as p,r as m,t as h}from"./Card-D55CMzdw.js";import{t as g}from"./CodeWell-Mu33yg_R.js";import{t as _}from"./Tabs-DecjeYAq.js";var v=i(a(),1),y=s(),b=[{key:`editor`,label:`Settings editor`},{key:`raw`,label:`Raw ini (read-only)`}],x={DIFFICULTY:[{value:`None`,label:`None`},{value:`Casual`,label:`Casual`},{value:`Normal`,label:`Normal`},{value:`Hard`,label:`Hard`}],DEATH_PENALTY:[{value:`None`,label:`None`},{value:`Item`,label:`Item`},{value:`ItemAndEquipment`,label:`All items drop`},{value:`All`,label:`All items and Pals drop`}]};function S(){let[e,t]=(0,v.useState)(`editor`);return(0,y.jsxs)(`main`,{className:`content`,children:[(0,y.jsxs)(`div`,{className:`page-head`,children:[(0,y.jsx)(`h1`,{children:`Configuration`}),(0,y.jsx)(`span`,{className:`sub`,children:`PalWorldSettings.ini · via compose environment`})]}),(0,y.jsx)(f,{tone:`info`,children:`This server generates PalWorldSettings.ini from docker-compose environment variables on every boot. Palhelm edits the compose file — changes apply after a container restart.`}),(0,y.jsx)(_,{items:b,active:e,onChange:t}),e===`editor`?(0,y.jsx)(C,{}):(0,y.jsx)(T,{})]})}function C(){let i=l(),a=t(),s=u(),m=r({queryKey:[`config`],queryFn:()=>o.config.get()}),[_,b]=(0,v.useState)({}),x=(0,v.useMemo)(()=>m.data?.settings??[],[m.data]),S=(0,v.useMemo)(()=>new Map(x.map(e=>[e.key,e])),[x]),C=Object.keys(_).filter(e=>{let t=S.get(e);return t!==void 0&&_[e]!==String(t.value)}),T=C.length>0,E=x.filter(e=>e.pending).length,D=c({mutationFn:()=>{let e={};for(let t of C)e[t]=_[t];let t=m.data?.version;if(!t)throw Error(`The compose version is unavailable; reload configuration.`);return o.config.put(t,e)},onSuccess:e=>{n(a,e),b({}),s.push(`Written to the compose file — restart the server to apply.`,`ok`)},onError:t=>{t instanceof e&&t.code===`config_conflict`?(a.invalidateQueries({queryKey:[`config`]}),b({}),s.push(`The compose file changed elsewhere. Configuration was reloaded; review your edit and try again.`,`danger`)):s.push(`Couldn't write the compose file.`,`danger`)}});function O(e){return _[e.key]??String(e.value)}function k(e,t){b(n=>({...n,[e]:t}))}function A(e){return _[e.key]!==void 0&&_[e.key]!==String(e.value)}if(m.isError)return(0,y.jsx)(h,{children:(0,y.jsx)(p,{children:(0,y.jsx)(f,{tone:`warn`,children:`Couldn't load the configuration. Check the compose file mount.`})})});if(m.isLoading)return(0,y.jsx)(h,{children:(0,y.jsx)(p,{children:(0,y.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:120}})})});let j=[];for(let e of x)j.includes(e.group)||j.push(e.group);let M=m.data.capabilities.write;return(0,y.jsxs)(y.Fragment,{children:[!M.available&&(0,y.jsxs)(f,{tone:`warn`,children:[`Configuration is read-only: `,M.reason??`the compose deployment does not support safe atomic writes`,`.`]}),(0,y.jsx)(`div`,{className:`grid cols-2`,children:j.map(e=>(0,y.jsx)(w,{group:e,settings:x.filter(t=>t.group===e),value:O,setValue:k,isDirty:A,editable:i&&M.available},e))}),i&&T&&(0,y.jsx)(h,{className:`footer-bar`,children:(0,y.jsxs)(p,{children:[(0,y.jsxs)(d,{tone:`warn`,children:[C.length,` pending change`,C.length===1?``:`s`]}),(0,y.jsx)(`div`,{className:`spacer`}),(0,y.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:()=>b({}),children:`Discard`}),(0,y.jsx)(`button`,{type:`button`,className:`btn`,disabled:D.isPending,onClick:()=>D.mutate(),children:D.isPending?`Writing…`:`Write to compose file`})]})}),!T&&E>0&&(0,y.jsxs)(f,{tone:`warn`,children:[E,` setting`,E===1?``:`s`,` written to the compose file but not yet applied. From the host directory containing your compose file (relative bind paths resolve from there), run:`,(0,y.jsx)(g,{children:m.data.manualCommand})]})]})}function w({group:e,settings:t,value:n,setValue:r,isDirty:i,editable:a}){let o=t.every(e=>e.readOnly),s=e===`gameplay`,[c,l]=(0,v.useState)({}),u=t.map(e=>{if(e.readOnly&&e.type===`boolean`)return(0,y.jsxs)(`div`,{className:`kv-row`,children:[(0,y.jsx)(`span`,{className:`k`,children:e.key.replace(/_ENABLED$/,``)}),(0,y.jsx)(d,{tone:e.effectiveValue===!0?`ok`:`idle`,children:e.effectiveValue===!0?`Enabled`:`Disabled`})]},e.key);let t=/password/i.test(e.key),o=i(e),u=o?(0,y.jsxs)(`span`,{className:`field-hint warn`,children:[`modified — will be written to compose (default `,e.default||`empty`,`)`]}):e.pending?(0,y.jsxs)(`span`,{className:`field-hint warn`,children:[`written, not yet applied — server is running with `,e.effectiveValue||`empty`]}):e.readOnly?(0,y.jsx)(`span`,{className:`field-hint`,children:`read-only in this deployment`}):n(e)===String(e.default)?(0,y.jsx)(`span`,{className:`field-hint`,children:`default`}):null;if(x[e.key]){let t=x[e.key];return(0,y.jsxs)(`div`,{className:`field${o?` modified`:``}`,children:[(0,y.jsx)(`label`,{htmlFor:`cfg-${e.key}`,children:e.key}),(0,y.jsx)(`select`,{id:`cfg-${e.key}`,className:`input`,value:n(e),disabled:!a||!e.editable,onChange:t=>r(e.key,t.target.value),children:t.map(e=>(0,y.jsx)(`option`,{value:e.value,children:e.label},e.value))}),u]},e.key)}if(e.type===`boolean`)return(0,y.jsxs)(`div`,{className:`field${o?` modified`:``}`,children:[(0,y.jsx)(`label`,{htmlFor:`cfg-${e.key}`,children:e.key}),(0,y.jsxs)(`select`,{id:`cfg-${e.key}`,className:`input`,value:n(e),disabled:!a||!e.editable,onChange:t=>r(e.key,t.target.value),children:[(0,y.jsx)(`option`,{value:`true`,children:`Enabled`}),(0,y.jsx)(`option`,{value:`false`,children:`Disabled`})]}),u]},e.key);if(t){let t=c[e.key]??!1;return(0,y.jsxs)(`div`,{className:`field${o?` modified`:``}`,children:[(0,y.jsx)(`label`,{htmlFor:`cfg-${e.key}`,children:e.key}),(0,y.jsxs)(`div`,{style:{display:`flex`,gap:8},children:[(0,y.jsx)(`input`,{id:`cfg-${e.key}`,className:`input input-mono`,type:t?`text`:`password`,value:n(e)===`•••`?``:n(e),placeholder:`unchanged — enter a new value`,readOnly:!a||!e.editable,onChange:t=>r(e.key,t.target.value),style:{flex:1}}),(0,y.jsx)(`button`,{type:`button`,className:`btn btn-sm btn-ghost`,onClick:()=>l(n=>({...n,[e.key]:!t})),children:t?`Hide`:`Show`})]}),o?u:(0,y.jsx)(`span`,{className:`field-hint`,children:`write-only · the current value is never returned`})]},e.key)}return(0,y.jsxs)(`div`,{className:`field${o?` modified`:``}`,children:[(0,y.jsx)(`label`,{htmlFor:`cfg-${e.key}`,children:e.key}),(0,y.jsx)(`input`,{id:`cfg-${e.key}`,className:`input${e.type===`number`||e.type===`integer`?` input-mono`:``}`,type:e.type===`number`||e.type===`integer`?`number`:`text`,step:e.type===`integer`?`1`:e.type===`number`?`0.1`:void 0,value:n(e),readOnly:!a||!e.editable,style:(e.type===`number`||e.type===`integer`)&&!s?{width:120}:void 0,onChange:t=>r(e.key,t.target.value)}),u]},e.key)});return(0,y.jsxs)(h,{children:[(0,y.jsx)(m,{title:e.replace(/(^|-)(\w)/g,(e,t,n)=>`${t?` `:``}${n.toUpperCase()}`),hint:o?`read-only`:void 0}),(0,y.jsxs)(p,{className:void 0,style:s?void 0:{display:`flex`,flexDirection:`column`,gap:`var(--space-3)`},children:[s?(0,y.jsx)(`div`,{className:`field-grid`,children:u}):u,o&&(0,y.jsx)(`span`,{className:`field-hint`,children:`These values are displayed for status and cannot be changed through this editor.`})]})]})}function T(){let e=r({queryKey:[`config`,`raw`],queryFn:()=>o.config.raw()});return(0,y.jsxs)(h,{children:[(0,y.jsx)(m,{title:`PalWorldSettings.ini`,hint:`read-only · regenerated on every boot`}),e.isError?(0,y.jsx)(p,{children:(0,y.jsx)(f,{tone:`warn`,children:`Couldn't read the live ini file.`})}):e.isLoading?(0,y.jsx)(p,{children:(0,y.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:80}})}):(0,y.jsx)(p,{flush:!0,children:(0,y.jsx)(`pre`,{className:`raw-ini`,children:e.data})})]})}export{S as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Config-CXg6qAk9.css b/backend/internal/webdist/dist/assets/Config-CXg6qAk9.css
new file mode 100644
index 0000000..2d9eb22
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Config-CXg6qAk9.css
@@ -0,0 +1 @@
+.banner-info{background:var(--surface);border:var(--border-card) solid color-mix(in srgb, var(--accent) 55%, transparent);border-radius:var(--radius-card);box-shadow:var(--shadow-card);color:var(--ink-2);padding:11px 14px}.banner-info .stamp-i{border:var(--border-ctl) solid color-mix(in srgb, var(--accent) 55%, transparent);background:var(--accent-soft);width:26px;height:26px;color:var(--accent-ink);border-radius:7px;flex:none;place-items:center;display:grid;rotate:-3deg}.card .field>label{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-2)}.field-hint{font-size:var(--text-xs);color:var(--ink-3)}.field-hint.warn{color:var(--warn-ink)}.field-grid{gap:var(--space-4);grid-template-columns:1fr 1fr;display:grid}@media (width<=700px){.field-grid{grid-template-columns:1fr}}.field.modified{position:relative}.field.modified:before{content:"";background:var(--warn);border-radius:1.5px;width:3px;position:absolute;top:3px;bottom:3px;left:-11px}.field.modified>label{color:var(--warn-ink)}.field.modified>label:after{content:" ✱";color:var(--warn)}.field.modified .input{border-color:var(--warn)}.kv-row{border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;padding:8px 0;display:flex}.kv-row:last-child{border-bottom:0}.kv-row .k{font-size:var(--text-sm);color:var(--ink-2)}.footer-bar{box-shadow:var(--shadow-pop);border-color:var(--line-strong)}.footer-bar .card-body{align-items:center;gap:var(--space-3);flex-wrap:wrap;display:flex}.footer-bar .spacer{flex:1}.manual-note{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--ink-3);text-align:right;margin-top:-8px}.raw-ini{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink);background:var(--bg);border-radius:var(--radius-ctl);padding:var(--space-4);white-space:pre;line-height:1.6;overflow-x:auto}
diff --git a/backend/internal/webdist/dist/assets/Console-B-5ZyxL5.css b/backend/internal/webdist/dist/assets/Console-B-5ZyxL5.css
new file mode 100644
index 0000000..1d6a03a
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Console-B-5ZyxL5.css
@@ -0,0 +1 @@
+.console-layout{gap:var(--space-4);flex:1;grid-template-columns:1fr 300px;align-items:stretch;min-height:0;display:grid}@media (width<=1100px){.console-layout{grid-template-columns:1fr}}.console-card{flex-direction:column;min-height:0;display:flex}.console-card .console{border-radius:0;flex:1 1 0;min-height:420px}.prompt-row{gap:var(--space-2);padding:var(--space-3);border-top:var(--border-ctl) solid var(--line);background:var(--surface);display:flex}.prompt-row .input{flex:1}.saved-cmd{border-bottom:1px solid var(--line);align-items:center;gap:10px;padding:10px 16px;display:flex}.saved-cmd:hover{background:var(--surface-2)}.saved-cmd:last-child{border-bottom:0}.saved-cmd .meta{flex:1;min-width:0}.saved-cmd .name{font-size:var(--text-sm);font-weight:500}.saved-cmd code{font-family:var(--font-mono);color:var(--ink-3);white-space:nowrap;text-overflow:ellipsis;font-size:11px;display:block;overflow:hidden}.cmd-ref{font-size:var(--text-sm);color:var(--ink-2);flex-direction:column;gap:8px;display:flex}.cmd-ref code{font-family:var(--font-mono);color:var(--ink);background:var(--surface-2);border:1px solid var(--line);border-radius:4px;padding:1px 5px;font-size:12px}.cmd-ref .foot{color:var(--ink-3);font-size:var(--text-xs);padding-top:4px}kbd{font-family:var(--font-mono);color:var(--ink-2);background:var(--surface-2);border:var(--border-ctl) solid var(--line-strong);border-bottom-width:2px;border-radius:3px;padding:1px 5px;font-size:10px}
diff --git a/backend/internal/webdist/dist/assets/Console-zetfhyb9.js b/backend/internal/webdist/dist/assets/Console-zetfhyb9.js
new file mode 100644
index 0000000..924dbb8
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Console-zetfhyb9.js
@@ -0,0 +1,2 @@
+import{K as e,U as t,_t as n,ht as r,j as i,q as a}from"./icons-CpYMTu_k.js";import{t as o}from"./useMutation-S28PAV4D.js";import{An as s,Dn as c,On as l,d as u,f as d,kn as f,m as p,p as m,r as h}from"./index-BpCavHBc.js";import{t as g}from"./Banner-DSN1nEJn.js";import{n as _,r as v,t as y}from"./Card-D55CMzdw.js";import{t as b}from"./EmptyState-DTSMkv56.js";var x=n(r(),1),S=a();function C(e){return new Date(e).toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1})}function w(){let n=s(),{username:r}=f(),a=e(),m=c(),h=t({queryKey:[`server`,`health`],queryFn:()=>i.server.health(),refetchInterval:15e3}),C=t({queryKey:[`console`,`log`],queryFn:()=>i.console.log(200)}),w=t({queryKey:[`console`,`saved`],queryFn:()=>i.console.savedList()}),[D,O]=(0,x.useState)(``),[k,A]=(0,x.useState)(null),[j,M]=(0,x.useState)(!1),[N,P]=(0,x.useState)(null),F=(0,x.useRef)(null),I=(0,x.useRef)(null),{consoleInsertRequest:L,clearConsoleInsertRequest:R}=l();(0,x.useEffect)(()=>{L&&(O(L.command),A(null),I.current?.focus(),R())},[L,R]);let z=o({mutationFn:e=>i.console.exec(e),onSettled:()=>a.invalidateQueries({queryKey:[`console`,`log`]}),onError:()=>m.push(`Command failed to send. Check the RCON connection.`,`danger`)}),B=C.data??[],V=B.map(e=>e.command);(0,x.useEffect)(()=>{let e=F.current;e&&(e.scrollTop=e.scrollHeight)},[B.length]);function H(){let e=D.trim();!e||z.isPending||(z.mutate(e),O(``),A(null))}function U(e){if(e.key===`Enter`)e.preventDefault(),H();else if(e.key===`ArrowUp`){if(e.preventDefault(),V.length===0)return;let t=k===null?V.length-1:Math.max(0,k-1);A(t),O(V[t]??``)}else if(e.key===`ArrowDown`){if(e.preventDefault(),k===null)return;let t=k+1;t>=V.length?(A(null),O(``)):(A(t),O(V[t]??``))}}let W=h.data?.rcon;return(0,S.jsxs)(`main`,{className:`content`,style:{minHeight:`calc(100vh - var(--helmstrip-h))`},children:[(0,S.jsxs)(`div`,{className:`page-head`,children:[(0,S.jsx)(`h1`,{children:`Console`}),(0,S.jsx)(`span`,{className:`sub`,children:`RCON session · audit-logged`}),(0,S.jsx)(`div`,{className:`spacer`}),W===`ok`?(0,S.jsx)(u,{tone:`ok`,children:`Connected`}):W===`error`?(0,S.jsx)(u,{tone:`danger`,children:`Disconnected`}):null]}),(0,S.jsxs)(`div`,{className:`console-layout`,children:[(0,S.jsxs)(y,{className:`console-card`,children:[C.isError?(0,S.jsx)(_,{children:(0,S.jsx)(g,{tone:`warn`,children:`Couldn't load the console log. Check the panel's RCON connection.`})}):(0,S.jsxs)(`div`,{className:`console`,role:`log`,"aria-label":`RCON session`,ref:F,children:[(0,S.jsxs)(`div`,{className:`line`,children:[(0,S.jsx)(`span`,{className:`ts`}),(0,S.jsxs)(`span`,{className:`sys`,children:[`— session opened by `,r,` —`]})]}),B.map((e,t)=>(0,S.jsx)(T,{entry:e},t)),B.length===0&&!C.isLoading&&(0,S.jsxs)(`div`,{className:`line`,children:[(0,S.jsx)(`span`,{className:`ts`}),(0,S.jsx)(`span`,{className:`sys`,children:`no commands yet — type one below`})]})]}),(0,S.jsxs)(`div`,{className:`prompt-row`,children:[(0,S.jsx)(`input`,{ref:I,className:`input input-mono`,type:`text`,placeholder:n?`Type an RCON command — ↑ for history`:`Viewer role — console is read-only`,"aria-label":`RCON command`,value:D,disabled:!n,onChange:e=>{O(e.target.value),A(null)},onKeyDown:U}),(0,S.jsx)(`button`,{type:`button`,className:`btn btn-primary`,onClick:H,disabled:!n||z.isPending,children:z.isPending?`Sending…`:`Send`})]})]}),(0,S.jsxs)(`aside`,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-4)`},children:[(0,S.jsxs)(y,{children:[(0,S.jsx)(v,{title:`Saved commands`,children:n&&(0,S.jsx)(`button`,{type:`button`,className:`btn btn-sm btn-ghost`,onClick:()=>M(!0),children:`+ New`})}),w.isError?(0,S.jsx)(_,{children:(0,S.jsx)(g,{tone:`warn`,children:`Couldn't load saved commands.`})}):(w.data??[]).length===0?(0,S.jsx)(_,{children:(0,S.jsx)(b,{title:`No saved commands`,description:n?`Save a command you run often and it appears here for one-click reuse.`:`None saved yet.`})}):(0,S.jsx)(_,{flush:!0,children:(w.data??[]).map(e=>(0,S.jsxs)(`div`,{className:`saved-cmd`,children:[(0,S.jsxs)(`div`,{className:`meta`,children:[(0,S.jsx)(`div`,{className:`name`,children:e.name}),(0,S.jsx)(`code`,{children:e.command})]}),n&&(0,S.jsxs)(S.Fragment,{children:[(0,S.jsx)(`button`,{type:`button`,className:`btn btn-sm`,disabled:z.isPending,onClick:()=>z.mutate(e.command),children:`Run`}),(0,S.jsx)(p,{label:`Delete`,children:(0,S.jsx)(`button`,{type:`button`,className:`btn btn-sm btn-ghost`,"aria-label":`Delete saved command ${e.name}`,onClick:()=>P({id:e.id,name:e.name}),children:`✕`})})]})]},e.id))})]}),(0,S.jsxs)(y,{children:[(0,S.jsx)(v,{title:`Command reference`}),(0,S.jsxs)(_,{className:`cmd-ref`,children:[(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`code`,{children:`ShowPlayers`}),` — list connected players`]}),(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`code`,{children:`Broadcast `}),` — message all players (no spaces; use _)`]}),(0,S.jsx)(`div`,{children:(0,S.jsx)(`code`,{children:`KickPlayer `})}),(0,S.jsxs)(`div`,{children:[(0,S.jsx)(`code`,{children:`Shutdown `}),` — graceful stop with warning`]}),(0,S.jsxs)(`div`,{className:`foot`,children:[`Vanilla RCON is limited — most moderation actions in Palhelm use the REST API instead. `,(0,S.jsx)(`kbd`,{children:`↑`}),` cycles history.`]})]})]})]})]}),(0,S.jsx)(E,{open:j,onClose:()=>M(!1)}),(0,S.jsx)(d,{open:N!==null,title:`Delete "${N?.name}"`,onClose:()=>P(null),danger:!0,confirmLabel:`Delete saved command`,onConfirm:async()=>{if(N){try{await i.console.savedDelete(N.id),a.invalidateQueries({queryKey:[`console`,`saved`]}),m.push(`Saved command deleted.`,`ok`)}catch{m.push(`Couldn't delete the saved command.`,`danger`)}P(null)}},children:(0,S.jsx)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:`Removes the shortcut only — it doesn't run or undo anything on the server.`})})]})}function T({entry:e}){let t=e.output.split(`
+`);return(0,S.jsxs)(S.Fragment,{children:[(0,S.jsxs)(`div`,{className:`line`,children:[(0,S.jsx)(`span`,{className:`ts`,children:C(e.at)}),(0,S.jsx)(`span`,{className:`cmd`,children:e.command})]}),(0,S.jsxs)(`div`,{className:`line`,children:[(0,S.jsx)(`span`,{className:`ts`,children:C(e.at)}),(0,S.jsx)(`span`,{className:e.isError?`err`:void 0,children:t.map((e,n)=>(0,S.jsxs)(`span`,{children:[e,na(e.target.value),autoFocus:!0}),(0,S.jsx)(h,{label:`Command`,mono:!0,placeholder:`ShowPlayers`,value:o,onChange:e=>s(e.target.value)})]})}export{w as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Dashboard-BycK1nhV.css b/backend/internal/webdist/dist/assets/Dashboard-BycK1nhV.css
new file mode 100644
index 0000000..c374f99
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Dashboard-BycK1nhV.css
@@ -0,0 +1 @@
+.uplot,.uplot *,.uplot :before,.uplot :after{box-sizing:border-box}.uplot{width:min-content;font-family:system-ui,-apple-system,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}.u-title{text-align:center;font-size:18px;font-weight:700}.u-wrap{-webkit-user-select:none;user-select:none;position:relative}.u-over,.u-under{position:absolute}.u-under{overflow:hidden}.uplot canvas{width:100%;height:100%;display:block;position:relative}.u-axis{position:absolute}.u-legend{text-align:center;margin:auto;font-size:14px}.u-inline{display:block}.u-inline *{display:inline-block}.u-inline tr{margin-right:16px}.u-legend th{font-weight:600}.u-legend th>*{vertical-align:middle;display:inline-block}.u-legend .u-marker{width:1em;height:1em;margin-right:4px;background-clip:padding-box!important}.u-inline.u-live th:after{content:":";vertical-align:middle}.u-inline:not(.u-live) .u-value{display:none}.u-series>*{padding:4px}.u-series th{cursor:pointer}.u-legend .u-off>*{opacity:.3}.u-select{pointer-events:none;background:#00000012;position:absolute}.u-cursor-x,.u-cursor-y{pointer-events:none;will-change:transform;position:absolute;top:0;left:0}.u-hz .u-cursor-x,.u-vt .u-cursor-y{border-right:1px dashed #607d8b;height:100%}.u-hz .u-cursor-y,.u-vt .u-cursor-x{border-bottom:1px dashed #607d8b;width:100%}.u-cursor-pt{pointer-events:none;will-change:transform;border:0 solid;border-radius:50%;position:absolute;top:0;left:0;background-clip:padding-box!important}.u-axis.u-off,.u-select.u-off,.u-cursor-x.u-off,.u-cursor-y.u-off,.u-cursor-pt.u-off{display:none}.frame-time{border-top:1px solid var(--line);flex-direction:column;gap:6px;padding:12px 16px 4px;display:flex}.frame-time .frame-time-head{font-size:var(--text-xs);color:var(--ink-3);text-transform:uppercase;letter-spacing:var(--track-caps);justify-content:space-between;align-items:baseline;display:flex}
diff --git a/backend/internal/webdist/dist/assets/Dashboard-Cmb9dKW2.js b/backend/internal/webdist/dist/assets/Dashboard-Cmb9dKW2.js
new file mode 100644
index 0000000..f7d5923
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Dashboard-Cmb9dKW2.js
@@ -0,0 +1,10 @@
+import{U as e,_t as t,ht as n,j as r,q as i}from"./icons-CpYMTu_k.js";import{Mn as a,a as o,c as s,d as c,l,o as u,s as d}from"./index-BpCavHBc.js";import{t as f}from"./Banner-DSN1nEJn.js";import{n as p,r as m,t as h}from"./Card-D55CMzdw.js";import{t as g}from"./EventMessage-UG0hgRVA.js";var _=t(n(),1),v=i();function y({label:e,value:t,unit:n,delta:r,deltaTone:i}){return(0,v.jsxs)(`div`,{className:`card stat`,children:[(0,v.jsx)(`span`,{className:`label`,children:e}),(0,v.jsxs)(`div`,{className:`value`,children:[t,n!==void 0&&(0,v.jsxs)(`small`,{children:[` `,n]})]}),r!==void 0&&(0,v.jsx)(`div`,{className:[`delta`,i??``].filter(Boolean).join(` `),children:r})]})}function b(){return(0,v.jsxs)(`div`,{className:`card stat`,children:[(0,v.jsx)(`span`,{className:`skel skel-text`,style:{width:`60%`}}),(0,v.jsx)(`div`,{className:`value`,style:{marginTop:6},children:(0,v.jsx)(`span`,{className:`skel skel-text`,style:{width:`40%`,height:22}})}),(0,v.jsx)(`div`,{className:`delta`,style:{marginTop:6},children:(0,v.jsx)(`span`,{className:`skel skel-text`,style:{width:`70%`}})})]})}var x=!0,S=`uplot`,C=`u-hz`,w=`u-vt`,T=`u-title`,E=`u-wrap`,ee=`u-under`,D=`u-over`,te=`u-axis`,ne=`u-off`,re=`u-select`,ie=`u-cursor-x`,ae=`u-cursor-y`,oe=`u-cursor-pt`,se=`u-legend`,ce=`u-live`,le=`u-inline`,ue=`u-series`,de=`u-marker`,O=`u-label`,fe=`u-value`,pe=`width`,k=`height`,me=`top`,he=`bottom`,ge=`left`,_e=`right`,A=`#000`,ve=`#0000`,ye=`mousemove`,be=`mousedown`,xe=`mouseup`,Se=`mouseenter`,Ce=`mouseleave`,we=`dblclick`,Te=`resize`,Ee=`scroll`,De=`change`,Oe=`dppxchange`,ke=`--`,Ae=typeof window<`u`,je=Ae?document:null,Me=Ae?window:null,j=Ae?navigator:null,M,Ne;function Pe(){let e=devicePixelRatio;M!=e&&(M=e,Ne&&qe(De,Ne,Pe),Ne=matchMedia(`(min-resolution: ${M-.001}dppx) and (max-resolution: ${M+.001}dppx)`),Ke(De,Ne,Pe),Me.dispatchEvent(new CustomEvent(Oe)))}function Fe(e,t){if(t!=null){let n=e.classList;!n.contains(t)&&n.add(t)}}function Ie(e,t){let n=e.classList;n.contains(t)&&n.remove(t)}function N(e,t,n){e.style[t]=n+`px`}function Le(e,t,n,r){let i=je.createElement(e);return t!=null&&Fe(i,t),n?.insertBefore(i,r),i}function Re(e,t){return Le(`div`,e,t)}var ze=new WeakMap;function Be(e,t,n,r,i){let a=`translate(`+t+`px,`+n+`px)`;a!=ze.get(e)&&(e.style.transform=a,ze.set(e,a),t<0||n<0||t>r||n>i?Fe(e,ne):Ie(e,ne))}var P=new WeakMap;function Ve(e,t,n){let r=t+n;r!=P.get(e)&&(P.set(e,r),e.style.background=t,e.style.borderColor=n)}var He=new WeakMap;function Ue(e,t,n,r){let i=t+``+n;i!=He.get(e)&&(He.set(e,i),e.style.height=n+`px`,e.style.width=t+`px`,e.style.marginLeft=r?-t/2+`px`:0,e.style.marginTop=r?-n/2+`px`:0)}var We={passive:!0},Ge={...We,capture:!0};function Ke(e,t,n,r){t.addEventListener(e,n,r?Ge:We)}function qe(e,t,n,r){t.removeEventListener(e,n,We)}Ae&&Pe();function Je(e,t,n,r){let i;n||=0,r||=t.length-1;let a=r<=2147483647;for(;r-n>1;)i=a?n+r>>1:ft((n+r)/2),t[i]{let i=-1,a=-1;for(let a=n;a<=r;a++)if(e(t[a])){i=a;break}for(let i=r;i>=n;i--)if(e(t[i])){a=i;break}return[i,a]}}var Xe=e=>e!=null,Ze=e=>e!=null&&e>0,F=Ye(Xe),I=Ye(Ze);function Qe(e,t,n,r=0,i=!1){let a=i?I:F,o=i?Ze:Xe;[t,n]=a(e,t,n);let s=e[t],c=e[t];if(t>-1)if(r==1)s=e[t],c=e[n];else if(r==-1)s=e[n],c=e[t];else for(let r=t;r<=n;r++){let t=e[r];o(t)&&(tc&&(c=t))}return[s??z,c??-z]}function $e(e,t,n,r){let i=vt(e),a=vt(t);e==t&&(i==-1?(e*=n,t/=n):(e/=n,t*=n));let o=n==10?yt:bt,s=i==1?ft:mt,c=a==1?mt:ft,l=s(o(R(e))),u=c(o(R(t))),d=_t(n,l),f=_t(n,u);return n==10&&(l<0&&(d=V(d,-l)),u<0&&(f=V(f,-u))),r||n==2?(e=d*i,t=f*a):(e=It(e,d),t=Ft(t,f)),[e,t]}function et(e,t,n,r){let i=$e(e,t,n,r);return e==0&&(i[0]=0),t==0&&(i[1]=0),i}var tt=.1,nt={mode:3,pad:tt},rt={pad:0,soft:null,mode:0},it={min:rt,max:rt};function at(e,t,n,r){return qt(n)?st(e,t,n):(rt.pad=n,rt.soft=r?0:null,rt.mode=r?3:0,st(e,t,it))}function L(e,t){return e??t}function ot(e,t,n){for(t=L(t,0),n=L(n,e.length-1);t<=n;){if(e[t]!=null)return!0;t++}return!1}function st(e,t,n){let r=n.min,i=n.max,a=L(r.pad,0),o=L(i.pad,0),s=L(r.hard,-z),c=L(i.hard,z),l=L(r.soft,z),u=L(i.soft,-z),d=L(r.mode,0),f=L(i.mode,0),p=t-e,m=yt(p),h=gt(R(e),R(t)),g=R(yt(h)-m);(p<1e-24||g>10)&&(p=0,(e==0||t==0)&&(p=1e-24,d==2&&l!=z&&(a=0),f==2&&u!=-z&&(o=0)));let _=p||h||1e3,v=_t(10,ft(yt(_))),y=V(It(e-_*(p==0?e==0?.1:1:a),v/10),24),b=e>=l&&(d==1||d==3&&y<=l||d==2&&y>=l)?l:z,x=gt(s,y=b?b:ht(b,y)),S=V(Ft(t+_*(p==0?t==0?.1:1:o),v/10),24),C=t<=u&&(f==1||f==3&&S>=u||f==2&&S<=u)?u:-z,w=ht(c,S>C&&t<=C?C:gt(C,S));return x==w&&x==0&&(w=100),[x,w]}var ct=new Intl.NumberFormat(Ae?j.language:`en-US`),lt=e=>ct.format(e),ut=Math,dt=ut.PI,R=ut.abs,ft=ut.floor,pt=ut.round,mt=ut.ceil,ht=ut.min,gt=ut.max,_t=ut.pow,vt=ut.sign,yt=ut.log10,bt=ut.log2,xt=(e,t=1)=>ut.sinh(e)*t,St=(e,t=1)=>ut.asinh(e/t),z=1/0;function Ct(e){return(yt((e^e>>31)-(e>>31))|0)+1}function wt(e,t,n){return ht(gt(e,t),n)}function Tt(e){return typeof e==`function`}function B(e){return Tt(e)?e:()=>e}var Et=()=>{},Dt=e=>e,Ot=(e,t)=>t,kt=e=>null,At=e=>!0,jt=(e,t)=>e==t,Mt=/\.\d*?(?=9{6,}|0{6,})/gm,Nt=e=>{if(Wt(e)||Lt.has(e))return e;let t=`${e}`,n=t.match(Mt);if(n==null)return e;let r=n[0].length-1;if(t.indexOf(`e-`)!=-1){let[e,n]=t.split(`e`);return+`${Nt(e)}e${n}`}return V(e,r)};function Pt(e,t){return Nt(V(Nt(e/t))*t)}function Ft(e,t){return Nt(mt(Nt(e/t))*t)}function It(e,t){return Nt(ft(Nt(e/t))*t)}function V(e,t=0){if(Wt(e))return e;let n=10**t;return pt(e*n*(1+2**-52))/n}var Lt=new Map;function Rt(e){return((``+e).split(`.`)[1]||``).length}function zt(e,t,n,r){let i=[],a=r.map(Rt);for(let o=t;o=0?0:t)+(o>=a[s]?0:a[s]),u=e==10?c:V(c,l);i.push(u),Lt.set(u,l)}}return i}var Bt={},Vt=[],Ht=[null,null],Ut=Array.isArray,Wt=Number.isInteger,Gt=e=>e===void 0;function Kt(e){return typeof e==`string`}function qt(e){let t=!1;if(e!=null){let n=e.constructor;t=n==null||n==Object}return t}function Jt(e){return typeof e==`object`&&!!e}var Yt=Object.getPrototypeOf(Uint8Array),Xt=`__proto__`;function Zt(e,t=qt){let n;if(Ut(e)){let r=e.find(e=>e!=null);if(Ut(r)||t(r)){n=Array(e.length);for(let r=0;ra){for(i=o-1;i>=0&&e[i]==null;)e[i--]=null;for(i=o+1;ie-t)],i=r[0].length,a=new Map;for(let e=0;e`u`?e=>Promise.resolve().then(e):queueMicrotask;function nn(e){let t=e[0],n=t.length,r=Array(n);for(let e=0;et[e]-t[n]);let i=[];for(let t=0;t=r&&e[i]==null;)i--;if(i<=r)return!0;let a=gt(1,ft((i-r+1)/t));for(let t=e[r],n=r+a;n<=i;n+=a){let r=e[n];if(r!=null){if(r<=t)return!1;t=r}}return!0}var on=[`January`,`February`,`March`,`April`,`May`,`June`,`July`,`August`,`September`,`October`,`November`,`December`],sn=[`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`,`Saturday`];function cn(e){return e.slice(0,3)}var ln=sn.map(cn),un={MMMM:on,MMM:on.map(cn),WWWW:sn,WWW:ln};function dn(e){return(e<10?`0`:``)+e}function fn(e){return(e<10?`00`:e<100?`0`:``)+e}var pn={YYYY:e=>e.getFullYear(),YY:e=>(e.getFullYear()+``).slice(2),MMMM:(e,t)=>t.MMMM[e.getMonth()],MMM:(e,t)=>t.MMM[e.getMonth()],MM:e=>dn(e.getMonth()+1),M:e=>e.getMonth()+1,DD:e=>dn(e.getDate()),D:e=>e.getDate(),WWWW:(e,t)=>t.WWWW[e.getDay()],WWW:(e,t)=>t.WWW[e.getDay()],HH:e=>dn(e.getHours()),H:e=>e.getHours(),h:e=>{let t=e.getHours();return t==0?12:t>12?t-12:t},AA:e=>e.getHours()>=12?`PM`:`AM`,aa:e=>e.getHours()>=12?`pm`:`am`,a:e=>e.getHours()>=12?`p`:`a`,mm:e=>dn(e.getMinutes()),m:e=>e.getMinutes(),ss:e=>dn(e.getSeconds()),s:e=>e.getSeconds(),fff:e=>fn(e.getMilliseconds())};function mn(e,t){t||=un;let n=[],r=/\{([a-z]+)\}|[^{]+/gi,i;for(;i=r.exec(e);)n.push(i[0][0]==`{`?pn[i[1]]:i[0]);return e=>{let r=``;for(let i=0;ie%1==0,vn=[1,2,2.5,5],yn=zt(10,-32,0,vn),bn=zt(10,0,32,vn),xn=bn.filter(_n),Sn=yn.concat(bn),Cn=`{YYYY}`,wn=`
+{YYYY}`,Tn=`{M}/{D}`,En=`
+{M}/{D}`,Dn=`
+{M}/{D}/{YY}`,On=`{h}:{mm}{aa}`,kn=`
+{h}:{mm}{aa}`,An=`:{ss}`,G=null;function jn(e){let t=e*1e3,n=t*60,r=n*60,i=r*24,a=i*30,o=i*365,s=(e==1?zt(10,0,3,vn).filter(_n):zt(10,-3,0,vn)).concat([t,t*5,t*10,t*15,t*30,n,n*5,n*10,n*15,n*30,r,r*2,r*3,r*4,r*6,r*8,r*12,i,i*2,i*3,i*4,i*5,i*6,i*7,i*8,i*9,i*10,i*15,a,a*2,a*3,a*4,a*6,o,o*2,o*5,o*10,o*25,o*50,o*100]),c=[[o,Cn,G,G,G,G,G,G,1],[i*28,`{MMM}`,wn,G,G,G,G,G,1],[i,Tn,wn,G,G,G,G,G,1],[r,`{h}{aa}`,Dn,G,En,G,G,G,1],[n,On,Dn,G,En,G,G,G,1],[t,An,`
+{M}/{D}/{YY} {h}:{mm}{aa}`,G,`
+{M}/{D} {h}:{mm}{aa}`,G,kn,G,1],[e,`:{ss}.{fff}`,`
+{M}/{D}/{YY} {h}:{mm}{aa}`,G,`
+{M}/{D} {h}:{mm}{aa}`,G,kn,G,1]];function l(t){return(s,c,l,u,d,f)=>{let p=[],m=d>=o,h=d>=a&&d=i?i:d,o=y+(ft(l)-ft(_))+Ft(_-y,a);p.push(o);let m=t(o),h=m.getHours()+m.getMinutes()/n+m.getSeconds()/r,g=d/r,v=f/s.axes[c]._space;for(;o=V(o+d,e==1?0:3),!(o>u);)if(g>1){let e=ft(V(h+g,6))%24,n=t(o).getHours()-e;n>1&&(n=-1),o-=n*r,h=(h+g)%24;let i=p[p.length-1];V((o-i)/d,3)*v>=.7&&p.push(o)}else p.push(o)}return p}}return[s,c,l]}var[Mn,Nn,Pn]=jn(1),[Fn,In,Ln]=jn(.001);zt(2,-53,53,[1]);function Rn(e,t){return e.map(e=>e.map((n,r)=>r==0||r==8||n==null?n:t(r==1||e[8]==0?n:e[1]+n)))}function zn(e,t){return(n,r,i,a,o)=>{let s=t.find(e=>o>=e[0])||t[t.length-1],c,l,u,d,f,p;return r.map(t=>{let n=e(t),r=n.getFullYear(),i=n.getMonth(),a=n.getDate(),o=n.getHours(),m=n.getMinutes(),h=n.getSeconds(),g=r!=c&&s[2]||i!=l&&s[3]||a!=u&&s[4]||o!=d&&s[5]||m!=f&&s[6]||h!=p&&s[7]||s[1];return c=r,l=i,u=a,d=o,f=m,p=h,g(n)})}}function Bn(e,t){let n=mn(t);return(t,r,i,a,o)=>r.map(t=>n(e(t)))}function Vn(e,t,n){return new Date(e,t,n)}function Hn(e,t){return t(e)}var Un=`{YYYY}-{MM}-{DD} {h}:{mm}{aa}`;function Wn(e,t){return(n,r,i,a)=>a==null?ke:t(e(r))}function Gn(e,t){let n=e.series[t];return n.width?n.stroke(e,t):n.points.width?n.points.stroke(e,t):null}function Kn(e,t){return e.series[t].fill(e,t)}var qn={show:!0,live:!0,isolate:!1,mount:Et,markers:{show:!0,width:2,stroke:Gn,fill:Kn,dash:`solid`},idx:null,idxs:null,values:[]};function Jn(e,t){let n=e.cursor.points,r=Re(),i=n.size(e,t);N(r,pe,i),N(r,k,i);let a=i/-2;N(r,`marginLeft`,a),N(r,`marginTop`,a);let o=n.width(e,t,i);return o&&N(r,`borderWidth`,o),r}function Yn(e,t){let n=e.series[t].points;return n._fill||n._stroke}function Xn(e,t){let n=e.series[t].points;return n._stroke||n._fill}function Zn(e,t){return e.series[t].points.size}var Qn=[0,0];function $n(e,t,n){return Qn[0]=t,Qn[1]=n,Qn}function K(e,t,n,r=!0){return e=>{e.button==0&&(!r||e.target==t)&&n(e)}}function q(e,t,n,r=!0){return e=>{(!r||e.target==t)&&n(e)}}var er={show:!0,x:!0,y:!0,lock:!1,move:$n,points:{one:!1,show:Jn,size:Zn,width:0,stroke:Xn,fill:Yn},bind:{mousedown:K,mouseup:K,click:K,dblclick:K,mousemove:q,mouseleave:q,mouseenter:q},drag:{setScale:!0,x:!0,y:!1,dist:0,uni:null,click:(e,t)=>{t.stopPropagation(),t.stopImmediatePropagation()},_x:!1,_y:!1},focus:{dist:(e,t,n,r,i)=>r-i,prox:-1,bias:0},hover:{skip:[void 0],prox:null,bias:0},left:-10,top:-10,idx:null,dataIdx:null,idxs:null,event:null},J={show:!0,stroke:`rgba(0,0,0,0.07)`,width:2},tr=H({},J,{filter:Ot}),nr=H({},tr,{size:10}),rr=H({},J,{show:!1}),ir=`12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"`,ar=`bold 12px system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"`,or=1.5,sr={show:!0,scale:`x`,stroke:A,space:50,gap:5,alignTo:1,size:50,labelGap:0,labelSize:30,labelFont:ar,side:2,grid:tr,ticks:nr,border:rr,font:ir,lineGap:or,rotate:0},cr=`Value`,lr=`Time`,ur={show:!0,scale:`x`,auto:!1,sorted:1,min:z,max:-1/0,idxs:[]};function dr(e,t,n,r,i){return t.map(e=>e==null?``:lt(e))}function fr(e,t,n,r,i,a,o){let s=[],c=Lt.get(i)||0;n=o?n:V(Ft(n,i),c);for(let e=n;e<=r;e=V(e+i,c))s.push(Object.is(e,-0)?0:e);return s}function pr(e,t,n,r,i,a,o){let s=[],c=e.scales[e.axes[t].scale].log;i=_t(c,ft((c==10?yt:bt)(n))),c==10&&(i=Sn[Je(i,Sn)]);let l=n,u=i*c;c==10&&(u=Sn[Je(u,Sn)]);do s.push(l),l+=i,c==10&&!Lt.has(l)&&(l=V(l,Lt.get(i))),l>=u&&(i=l,u=i*c,c==10&&(u=Sn[Je(u,Sn)]));while(l<=r);return s}function mr(e,t,n,r,i,a,o){let s=e.scales[e.axes[t].scale].asinh,c=r>s?pr(e,t,gt(s,n),r,i):[s],l=r>=0&&n<=0?[0]:[];return(n<-s?pr(e,t,gt(s,-r),-n,i):[s]).reverse().map(e=>-e).concat(l,c)}var hr=/./,gr=/[12357]/,_r=/[125]/,vr=/1/,yr=(e,t,n,r)=>e.map((e,i)=>t==4&&e==0||i%r==0&&n.test(e.toExponential()[+(e<0)])?e:null);function br(e,t,n,r,i){let a=e.axes[n],o=a.scale,s=e.scales[o],c=e.valToPos,l=a._space,u=c(10,o),d=c(9,o)-u>=l?hr:c(7,o)-u>=l?gr:c(5,o)-u>=l?_r:vr;if(d==vr){let e=R(c(1,o)-u);if(ei,Or={show:!0,auto:!0,sorted:0,gaps:Dr,alpha:1,facets:[H({},Er,{scale:`x`}),H({},Er,{scale:`y`})]},kr={scale:`y`,auto:!0,sorted:0,show:!0,spanGaps:!1,gaps:Dr,alpha:1,points:{show:Tr,filter:null},values:null,min:z,max:-1/0,idxs:[],path:null,clip:null};function Ar(e,t,n,r,i){return n/10}var jr={time:x,auto:!0,distr:1,log:10,asinh:1,min:null,max:null,dir:1,ori:0},Mr=H({},jr,{time:!1,ori:1}),Nr={};function Pr(e,t){let n=Nr[e];return n||(n={key:e,plots:[],sub(e){n.plots.push(e)},unsub(e){n.plots=n.plots.filter(t=>t!=e)},pub(e,t,r,i,a,o,s){for(let c=0;c{let h=e.pxRound,g=s.dir*(s.ori==0?1:-1),_=s.ori==0?Jr:Yr,v,y;g==1?(v=n,y=r):(v=r,y=n);let b=h(l(t[v],s,p,d)),x=h(u(o[v],c,m,f)),S=h(l(t[y],s,p,d)),C=h(u(a==1?c.max:c.min,c,m,f)),w=new Path2D(i);return _(w,S,C),_(w,b,C),_(w,b,x),w})}function Vr(e,t,n,r,i,a){let o=null;if(e.length>0){o=new Path2D;let s=t==0?Xr:Zr,c=n;for(let t=0;tn[0]){let e=n[0]-c;e>0&&s(o,c,r,e,r+a),c=n[1]}}let l=n+i-c;l>0&&s(o,c,r-10/2,l,r+a+10)}return o}function Hr(e,t,n){let r=e[e.length-1];r&&r[0]==t?r[1]=n:e.push([t,n])}function Ur(e,t,n,r,i,a,o){let s=[],c=e.length;for(let l=i==1?n:r;l>=n&&l<=r;l+=i)if(t[l]===null){let u=l,d=l;if(i==1)for(;++l<=r&&t[l]===null;)d=l;else for(;--l>=n&&t[l]===null;)d=l;let f=a(e[u]),p=d==u?f:a(e[d]),m=u-i;f=o<=0&&m>=0&&m=0&&h>=0&&h=f&&s.push([f,p])}return s}function Wr(e){return e==0?Dt:e==1?pt:t=>Pt(t,e)}function Gr(e){let t=e==0?Kr:qr,n=e==0?(e,t,n,r,i,a)=>{e.arcTo(t,n,r,i,a)}:(e,t,n,r,i,a)=>{e.arcTo(n,t,i,r,a)},r=e==0?(e,t,n,r,i)=>{e.rect(t,n,r,i)}:(e,t,n,r,i)=>{e.rect(n,t,i,r)};return(e,i,a,o,s,c=0,l=0)=>{c==0&&l==0?r(e,i,a,o,s):(c=ht(c,o/2,s/2),l=ht(l,o/2,s/2),t(e,i+c,a),n(e,i+o,a,i+o,a+s,c),n(e,i+o,a+s,i,a+s,l),n(e,i,a+s,i,a,l),n(e,i,a,i+o,a,c),e.closePath())}}var Kr=(e,t,n)=>{e.moveTo(t,n)},qr=(e,t,n)=>{e.moveTo(n,t)},Jr=(e,t,n)=>{e.lineTo(t,n)},Yr=(e,t,n)=>{e.lineTo(n,t)},Xr=Gr(0),Zr=Gr(1),Qr=(e,t,n,r,i,a)=>{e.arc(t,n,r,i,a)},$r=(e,t,n,r,i,a)=>{e.arc(n,t,r,i,a)},ei=(e,t,n,r,i,a,o)=>{e.bezierCurveTo(t,n,r,i,a,o)},ti=(e,t,n,r,i,a,o)=>{e.bezierCurveTo(n,t,i,r,o,a)};function ni(e){return(e,t,n,r,i)=>Lr(e,t,(t,a,o,s,c,l,u,d,f,p,m)=>{let{pxRound:h,points:g}=t,_,v;s.ori==0?(_=Kr,v=Qr):(_=qr,v=$r);let y=V(g.width*M,3),b=(g.size-g.width)/2*M,x=V(b*2,3),S=new Path2D,C=new Path2D,{left:w,top:T,width:E,height:ee}=e.bbox;Xr(C,w-x,T-x,E+x*2,ee+x*2);let D=e=>{if(o[e]!=null){let t=h(l(a[e],s,p,d)),n=h(u(o[e],c,m,f));_(S,t+b,n),v(S,t,n,b,0,dt*2)}};if(i)i.forEach(D);else for(let e=n;e<=r;e++)D(e);return{stroke:y>0?S:null,fill:S,clip:C,flags:3}})}function ri(e){return(t,n,r,i,a,o)=>{r!=i&&(a!=r&&o!=r&&e(t,n,r),a!=i&&o!=i&&e(t,n,i),e(t,n,o))}}var ii=ri(Jr),ai=ri(Yr);function oi(e){let t=L(e?.alignGaps,0);return(e,n,r,i)=>Lr(e,n,(a,o,s,c,l,u,d,f,p,m,h)=>{[r,i]=F(s,r,i);let g=a.pxRound,_=e=>g(u(e,c,m,f)),v=e=>g(d(e,l,h,p)),y,b;c.ori==0?(y=Jr,b=ii):(y=Yr,b=ai);let x=c.dir*(c.ori==0?1:-1),S={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:Fr},C=S.stroke,w=!1;if(i-r>=m*4){let t=t=>e.posToVal(t,c.key,!0),n=null,a=null,l,u,d,f=_(o[x==1?r:i]),p=_(o[r]),m=_(o[i]),h=t(x==1?p+1:m-1);for(let e=x==1?r:i;e>=r&&e<=i;e+=x){let r=o[e],i=(x==1?rh)?f:_(r),c=s[e];i==f?c==null?c===null&&(w=!0):(u=c,n==null?(y(C,i,v(u)),l=n=a=u):ua&&(a=u)):(n!=null&&b(C,f,v(n),v(a),v(l),v(u)),c==null?(n=a=null,c===null&&(w=!0)):(u=c,y(C,i,v(u)),n=a=l=u),f=i,h=t(f+x))}n!=null&&n!=a&&d!=f&&b(C,f,v(n),v(a),v(l),v(u))}else for(let e=x==1?r:i;e>=r&&e<=i;e+=x){let t=s[e];t===null?w=!0:t!=null&&y(C,_(o[e]),v(t))}let[T,E]=Rr(e,n);if(a.fill!=null||T!=0){let t=S.fill=new Path2D(C),s=v(a.fillTo(e,n,a.min,a.max,T)),c=_(o[r]),l=_(o[i]);x==-1&&([l,c]=[c,l]),y(t,l,s),y(t,c,s)}if(!a.spanGaps){let l=[];w&&l.push(...Ur(o,s,r,i,x,_,t)),S.gaps=l=a.gaps(e,n,r,i,l),S.clip=Vr(l,c.ori,f,p,m,h)}return E!=0&&(S.band=E==2?[Br(e,n,r,i,C,-1),Br(e,n,r,i,C,1)]:Br(e,n,r,i,C,E)),S})}function si(e){let t=L(e.align,1),n=L(e.ascDesc,!1),r=L(e.alignGaps,0),i=L(e.extend,!1);return(e,a,o,s)=>Lr(e,a,(c,l,u,d,f,p,m,h,g,_,v)=>{[o,s]=F(u,o,s);let y=c.pxRound,{left:b,width:x}=e.bbox,S=e=>y(p(e,d,_,h)),C=e=>y(m(e,f,v,g)),w=d.ori==0?Jr:Yr,T={stroke:new Path2D,fill:null,clip:null,band:null,gaps:null,flags:Fr},E=T.stroke,ee=d.dir*(d.ori==0?1:-1),D=C(u[ee==1?o:s]),te=S(l[ee==1?o:s]),ne=te,re=te;i&&t==-1&&(re=b,w(E,re,D)),w(E,te,D);for(let e=ee==1?o:s;e>=o&&e<=s;e+=ee){let n=u[e];if(n==null)continue;let r=S(l[e]),i=C(n);t==1?w(E,r,D):w(E,ne,i),w(E,r,i),D=i,ne=r}let ie=ne;i&&t==1&&(ie=b+x,w(E,ie,D));let[ae,oe]=Rr(e,a);if(c.fill!=null||ae!=0){let t=T.fill=new Path2D(E),n=C(c.fillTo(e,a,c.min,c.max,ae));w(t,ie,n),w(t,re,n)}if(!c.spanGaps){let i=[];i.push(...Ur(l,u,o,s,ee,S,r));let f=c.width*M/2,p=n||t==1?f:-f,m=n||t==-1?-f:f;i.forEach(e=>{e[0]+=p,e[1]+=m}),T.gaps=i=c.gaps(e,a,o,s,i),T.clip=Vr(i,d.ori,h,g,_,v)}return oe!=0&&(T.band=oe==2?[Br(e,a,o,s,E,-1),Br(e,a,o,s,E,1)]:Br(e,a,o,s,E,oe)),T})}function ci(e,t,n,r,i,a,o=z){if(e.length>1){let s=null;for(let c=0,l=1/0;c{}),{fill:d,stroke:f}=l;return(e,t,i,p)=>Lr(e,t,(m,h,g,_,v,y,b,x,S,C,w)=>{let T=m.pxRound,E=n,ee=r*M,D=s*M,te=c*M,ne,re;_.ori==0?[ne,re]=a(e,t):[re,ne]=a(e,t);let ie=_.dir*(_.ori==0?1:-1),ae=_.ori==0?Xr:Zr,oe=_.ori==0?u:(e,t,n,r,i,a,o)=>{u(e,t,n,i,r,o,a)},se=L(e.bands,Vt).find(e=>e.series[0]==t),ce=se==null?0:se.dir,le=m.fillTo(e,t,m.min,m.max,ce),ue=T(b(le,v,w,S)),de,O,fe,pe=C,k=T(m.width*M),me=!1,he=null,ge=null,_e=null,A=null;d!=null&&(k==0||f!=null)&&(me=!0,he=d.values(e,t,i,p),ge=new Map,new Set(he).forEach(e=>{e!=null&&ge.set(e,new Path2D)}),k>0&&(_e=f.values(e,t,i,p),A=new Map,new Set(_e).forEach(e=>{e!=null&&A.set(e,new Path2D)})));let{x0:ve,size:ye}=l;if(ve!=null&&ye!=null){E=1,h=ve.values(e,t,i,p),ve.unit==2&&(h=h.map(t=>e.posToVal(x+t*C,_.key,!0)));let n=ye.values(e,t,i,p);O=ye.unit==2?n[0]*C:y(n[0],_,C,x)-y(0,_,C,x),pe=ci(h,g,y,_,C,x,pe),fe=pe-O+ee}else pe=ci(h,g,y,_,C,x,pe),fe=pe*o+ee,O=pe-fe;fe<1&&(fe=0),k>=O/2&&(k=0),fe<5&&(T=Dt);let be=fe>0,xe=pe-fe-(be?k:0);O=T(wt(xe,te,D)),de=(E==0?O/2:E==ie?0:O)-E*ie*((E==0?ee/2:0)+(be?k/2:0));let Se={stroke:null,fill:null,clip:null,band:null,gaps:null,flags:0},Ce=me?null:new Path2D,we=null;if(se!=null)we=e.data[se.series[1]];else{let{y0:n,y1:r}=l;n!=null&&r!=null&&(g=r.values(e,t,i,p),we=n.values(e,t,i,p))}let Te=ne*O,Ee=re*O;for(let n=ie==1?i:p;n>=i&&n<=p;n+=ie){let r=g[n];if(r==null)continue;if(we!=null){let e=we[n]??0;if(r-e==0)continue;ue=b(e,v,w,S)}let i=y(_.distr!=2||l!=null?h[n]:n,_,C,x),a=b(L(r,le),v,w,S),o=T(i-de),s=T(gt(a,ue)),c=T(ht(a,ue)),u=s-c;if(r!=null){let i=r<0?Ee:Te,a=r<0?Te:Ee;me?(k>0&&_e[n]!=null&&ae(A.get(_e[n]),o,c+ft(k/2),O,gt(0,u-k),i,a),he[n]!=null&&ae(ge.get(he[n]),o,c+ft(k/2),O,gt(0,u-k),i,a)):ae(Ce,o,c+ft(k/2),O,gt(0,u-k),i,a),oe(e,t,n,o-k/2,c,O+k,u)}}return k>0?Se.stroke=me?A:Ce:me||(Se._fill=m.width==0?m._fill:m._stroke??m._fill,Se.width=0),Se.fill=me?ge:Ce,Se})}function ui(e,t){let n=L(t?.alignGaps,0);return(t,r,i,a)=>Lr(t,r,(o,s,c,l,u,d,f,p,m,h,g)=>{[i,a]=F(c,i,a);let _=o.pxRound,v=e=>_(d(e,l,h,p)),y=e=>_(f(e,u,g,m)),b,x,S;l.ori==0?(b=Kr,S=Jr,x=ei):(b=qr,S=Yr,x=ti);let C=l.dir*(l.ori==0?1:-1),w=v(s[C==1?i:a]),T=w,E=[],ee=[];for(let e=C==1?i:a;e>=i&&e<=a;e+=C)if(c[e]!=null){let t=s[e],n=v(t);E.push(T=n),ee.push(y(c[e]))}let D={stroke:e(E,ee,b,S,x,_),fill:null,clip:null,band:null,gaps:null,flags:Fr},te=D.stroke,[ne,re]=Rr(t,r);if(o.fill!=null||ne!=0){let e=D.fill=new Path2D(te),n=y(o.fillTo(t,r,o.min,o.max,ne));S(e,T,n),S(e,w,n)}if(!o.spanGaps){let e=[];e.push(...Ur(s,c,i,a,C,v,n)),D.gaps=e=o.gaps(t,r,i,a,e),D.clip=Vr(e,l.ori,p,m,h,g)}return re!=0&&(D.band=re==2?[Br(t,r,i,a,te,-1),Br(t,r,i,a,te,1)]:Br(t,r,i,a,te,re)),D})}function di(e){return ui(fi,e)}function fi(e,t,n,r,i,a){let o=e.length;if(o<2)return null;let s=new Path2D;if(n(s,e[0],t[0]),o==2)r(s,e[1],t[1]);else{let n=Array(o),r=Array(o-1),a=Array(o-1),c=Array(o-1);for(let n=0;n0!=r[e]>0?n[e]=0:(n[e]=3*(c[e-1]+c[e])/((2*c[e]+c[e-1])/r[e-1]+(c[e]+2*c[e-1])/r[e]),isFinite(n[e])||(n[e]=0));n[o-1]=r[o-2];for(let r=0;r{Y.pxRatio=M}));var hi=oi(),gi=ni();function _i(e,t,n,r){return(r?[e[0],e[1]].concat(e.slice(2)):[e[0]].concat(e.slice(1))).map((e,r)=>yi(e,r,t,n))}function vi(e,t){return e.map((e,n)=>n==0?{}:H({},t,e))}function yi(e,t,n,r){return H({},t==0?n:r,e)}function bi(e,t,n){return t==null?Ht:[t,n]}var xi=bi;function Si(e,t,n){return t==null?Ht:at(t,n,tt,!0)}function Ci(e,t,n,r){return t==null?Ht:$e(t,n,e.scales[r].log,!1)}var wi=Ci;function Ti(e,t,n,r){return t==null?Ht:et(t,n,e.scales[r].log,!1)}var Ei=Ti;function Di(e,t,n,r,i){let a=gt(Ct(e),Ct(t)),o=t-e,s=Je(i/r*o,n);do{let e=n[s],t=r*e/o;if(t>=i&&a+(e<5?Lt.get(e):0)<=17)return[e,t]}while(++s(t=pt((n=+r)*M))+`px`),[e,t,n]}function ki(e){e.show&&[e.font,e.labelFont].forEach(e=>{let t=V(e[2]*M,1);e[0]=e[0].replace(/[0-9.]+px/,t+`px`),e[1]=t})}function Y(e,t,n){let r={mode:L(e.mode,1)},i=r.mode;function a(e,t,n,r){let i=t.valToPct(e);return r+n*(t.dir==-1?1-i:i)}function o(e,t,n,r){let i=t.valToPct(e);return r+n*(t.dir==-1?i:1-i)}function s(e,t,n,r){return t.ori==0?a(e,t,n,r):o(e,t,n,r)}r.valToPosH=a,r.valToPosV=o;let c=!1;r.status=0;let l=r.root=Re(S);if(e.id!=null&&(l.id=e.id),Fe(l,e.class),e.title){let t=Re(T,l);t.textContent=e.title}let u=Le(`canvas`),d=r.ctx=u.getContext(`2d`),f=Re(E,l);Ke(`click`,f,e=>{e.target===m&&(X!=Ni||Z!=Pi)&&Ri.click(r,e)},!0);let p=r.under=Re(ee,f);f.appendChild(u);let m=r.over=Re(D,f);e=Zt(e);let h=+L(e.pxAlign,1),g=Wr(h);(e.plugins||[]).forEach(t=>{t.opts&&(e=t.opts(r,e)||e)});let _=e.ms||.001,v=r.series=i==1?_i(e.series||[],ur,kr,!1):vi(e.series||[null],Or),y=r.axes=_i(e.axes||[],sr,Cr,!0),b=r.scales={},x=r.bands=e.bands||[];x.forEach(e=>{e.fill=B(e.fill||null),e.dir=L(e.dir,-1)});let A=i==2?v[1].facets[0].scale:v[0].scale,Te={axes:ni,series:Gr},Ee=(e.drawOrder||[`axes`,`series`]).map(e=>Te[e]);function De(e){let t=e.distr==3?t=>yt(t>0?t:e.clamp(r,t,e.min,e.max,e.key)):e.distr==4?t=>St(t,e.asinh):e.distr==100?t=>e.fwd(t):e=>e;return n=>{let r=t(n),{_min:i,_max:a}=e,o=a-i;return(r-i)/o}}function Ae(t){let n=b[t];if(n==null){let r=(e.scales||Bt)[t]||Bt;if(r.from!=null){Ae(r.from);let e=H({},b[r.from],r,{key:t});e.valToPct=De(e),b[t]=e}else{n=b[t]=H({},t==A?jr:Mr,r),n.key=t;let e=n.time,a=n.range,o=Ut(a);if((t!=A||i==2&&!e)&&(o&&(a[0]==null||a[1]==null)&&(a={min:a[0]==null?nt:{mode:1,hard:a[0],soft:a[0]},max:a[1]==null?nt:{mode:1,hard:a[1],soft:a[1]}},o=!1),!o&&qt(a))){let e=a;a=(t,n,r)=>n==null?Ht:at(n,r,e)}n.range=B(a||(e?xi:t==A?n.distr==3?wi:n.distr==4?Ei:bi:n.distr==3?Ci:n.distr==4?Ti:Si)),n.auto=B(!o&&n.auto),n.clamp=B(n.clamp||Ar),n._min=n._max=null,n.valToPct=De(n)}}}Ae(`x`),Ae(`y`),i==1&&v.forEach(e=>{Ae(e.scale)}),y.forEach(e=>{Ae(e.scale)});for(let t in e.scales)Ae(t);let j=b[A],Ne=j.distr,Pe,ze;j.ori==0?(Fe(l,C),Pe=a,ze=o):(Fe(l,w),Pe=o,ze=a);let P={};for(let e in b){let t=b[e];(t.min!=null||t.max!=null)&&(P[e]={min:t.min,max:t.max},t.min=t.max=null)}let He=e.tzDate||(e=>new Date(pt(e/_))),We=e.fmtDate||mn,Ge=_==1?Pn(He):Ln(He),Ye=zn(He,Rn(_==1?Nn:In,We)),Xe=Wn(He,Hn(Un,We)),Ze=[],F=r.legend=H({},qn,e.legend),I=r.cursor=H({},er,{drag:{y:i==2}},e.cursor),rt=F.show,it=I.show,st=F.markers;F.idxs=Ze,st.width=B(st.width),st.dash=B(st.dash),st.stroke=B(st.stroke),st.fill=B(st.fill);let ct,lt,ut,ft=[],vt=[],bt,Ct=!1,Et={};if(F.live){let e=v[1]?v[1].values:null;Ct=e!=null,bt=Ct?e(r,1,0):{_:0};for(let e in bt)Et[e]=ke}if(rt)if(ct=Le(`table`,se,l),ut=Le(`tbody`,null,ct),F.mount(r,ct),Ct){lt=Le(`thead`,null,ct,ut);let e=Le(`tr`,null,lt);for(var Dt in Le(`th`,null,e),bt)Le(`th`,O,e).textContent=Dt}else Fe(ct,le),F.live&&Fe(ct,ce);let Mt={show:!0},Nt={show:!1};function Ft(e,t){if(t==0&&(Ct||!F.live||i==2))return Ht;let n=[],a=Le(`tr`,ue,ut,ut.childNodes[t]);Fe(a,e.class),e.show||Fe(a,ne);let o=Le(`th`,null,a);if(st.show){let e=Re(de,o);if(t>0){let n=st.width(r,t);n&&(e.style.border=n+`px `+st.dash(r,t)+` `+st.stroke(r,t)),e.style.background=st.fill(r,t)}}let s=Re(O,o);for(var c in e.label instanceof HTMLElement?s.appendChild(e.label):s.textContent=e.label,t>0&&(st.show||(s.style.color=e.width>0?st.stroke(r,t):st.fill(r,t)),zt(`click`,o,t=>{if(I._lock)return;Tn(t);let n=v.indexOf(e);if((t.ctrlKey||t.metaKey)!=F.isolate){let e=v.some((e,t)=>t>0&&t!=n&&e.show);v.forEach((t,r)=>{r>0&&Gi(r,e?r==n?Mt:Nt:Mt,!0,$.setSeries)})}else Gi(n,{show:!e.show},!0,$.setSeries)},!1),On&&zt(Se,o,t=>{I._lock||(Tn(t),Gi(v.indexOf(e),$i,!0,$.setSeries))},!1)),bt){let e=Le(`td`,fe,a);e.textContent=`--`,n.push(e)}return[a,n]}let It=new Map;function zt(e,t,n,i=!0){let a=It.get(t)||{},o=I.bind[e](r,t,n,i);o&&(Ke(e,t,a[e]=o),It.set(t,a))}function Wt(e,t,n){let r=It.get(t)||{};for(let n in r)(e==null||n==e)&&(qe(n,t,r[n]),delete r[n]);e??It.delete(t)}let Yt=0,Xt=0,U=0,W=0,Qt=0,$t=0,en=Qt,nn=$t,rn=U,an=W,on=0,sn=0,cn=0,ln=0;r.bbox={};let un=!1,dn=!1,fn=!1,pn=!1,hn=!1,gn=!1;function _n(e,t,n){(n||e!=r.width||t!=r.height)&&vn(e,t),ri(!1),fn=!0,dn=!0,ci()}function vn(e,t){r.width=Yt=U=e,r.height=Xt=W=t,Qt=$t=0,Cn(),wn();let n=r.bbox;on=n.left=Pt(Qt*M,.5),sn=n.top=Pt($t*M,.5),cn=n.width=Pt(U*M,.5),ln=n.height=Pt(W*M,.5)}function yn(){let e=!1,t=0;for(;!e;){t++;let n=ei(t),i=ti(t);e=t==3||n&&i,e||(vn(r.width,r.height),dn=!0)}}function bn({width:e,height:t}){_n(e,t)}r.setSize=bn;function Cn(){let e=!1,t=!1,n=!1,r=!1;y.forEach((i,a)=>{if(i.show&&i._show){let{side:a,_size:o}=i,s=a%2,c=o+(i.label==null?0:i.labelSize);c>0&&(s?(U-=c,a==3?(Qt+=c,r=!0):n=!0):(W-=c,a==0?($t+=c,e=!0):t=!0))}}),Yn[0]=e,Yn[1]=n,Yn[2]=t,Yn[3]=r,U-=$n[1]+$n[3],Qt+=$n[3],W-=$n[2]+$n[0],$t+=$n[0]}function wn(){let e=Qt+U,t=$t+W,n=Qt,r=$t;function i(i,a){switch(i){case 1:return e+=a,e-a;case 2:return t+=a,t-a;case 3:return n-=a,n+a;case 0:return r-=a,r+a}}y.forEach((e,t)=>{if(e.show&&e._show){let t=e.side;e._pos=i(t,e._size),e.label!=null&&(e._lpos=i(t,e.labelSize))}})}if(I.dataIdx==null){let e=I.hover,n=e.skip=new Set(e.skip??[]);n.add(void 0);let r=e.prox=B(e.prox),i=e.bias??=0;I.dataIdx=(e,a,o,s)=>{if(a==0)return o;let c=o,l=r(e,a,o,s)??z,u=l>=0&&l0;)n.has(m[r])||(e=r);if(i==0||i==1)for(r=o;t==null&&r++l&&(c=null);return c}}let Tn=e=>{I.event=e};I.idxs=Ze,I._lock=!1;let En=I.points;En.show=B(En.show),En.size=B(En.size),En.stroke=B(En.stroke),En.width=B(En.width),En.fill=B(En.fill);let Dn=r.focus=H({},e.focus||{alpha:.3},I.focus),On=Dn.prox>=0,kn=On&&En.one,An=[],G=[],jn=[];function Vn(e,t){let n=En.show(r,t);if(n instanceof HTMLElement)return Fe(n,oe),Fe(n,e.class),Be(n,-10,-10,U,W),m.insertBefore(n,An[t]),n}function Gn(e,t){if(i==1||t>0){let t=i==1&&b[e.scale].time,n=e.value;e.value=t?Kt(n)?Wn(He,Hn(n,We)):n||Xe:n||Sr,e.label=e.label||(t?lr:cr)}if(kn||t>0){e.width=e.width==null?1:e.width,e.paths=e.paths||hi||kt,e.fillTo=B(e.fillTo||zr),e.pxAlign=+L(e.pxAlign,h),e.pxRound=Wr(e.pxAlign),e.stroke=B(e.stroke||null),e.fill=B(e.fill||null),e._stroke=e._fill=e._paths=e._focus=null;let t=wr(gt(1,e.width),1),n=e.points=H({},{size:t,width:gt(1,t*.2),stroke:e.stroke,space:t*2,paths:gi,_stroke:null,_fill:null},e.points);n.show=B(n.show),n.filter=B(n.filter),n.fill=B(n.fill),n.stroke=B(n.stroke),n.paths=B(n.paths),n.pxAlign=e.pxAlign}if(rt){let n=Ft(e,t);ft.splice(t,0,n[0]),vt.splice(t,0,n[1]),F.values.push(null)}if(it){Ze.splice(t,0,null);let n=null;kn?t==0&&(n=Vn(e,t)):t>0&&(n=Vn(e,t)),An.splice(t,0,n),G.splice(t,0,0),jn.splice(t,0,0)}Oa(`addSeries`,t)}function Kn(e,t){t??=v.length,e=i==1?yi(e,t,ur,kr):yi(e,t,{},Or),v.splice(t,0,e),Gn(v[t],t)}r.addSeries=Kn;function Jn(e){if(v.splice(e,1),rt){F.values.splice(e,1),vt.splice(e,1);let t=ft.splice(e,1)[0];Wt(null,t.firstChild),t.remove()}it&&(Ze.splice(e,1),An.splice(e,1)[0].remove(),G.splice(e,1),jn.splice(e,1)),Oa(`delSeries`,e)}r.delSeries=Jn;let Yn=[!1,!1,!1,!1];function Xn(e,t){if(e._show=e.show,e.show){let n=e.side%2,i=b[e.scale];i??=(e.scale=n?v[1].scale:A,b[e.scale]);let a=i.time;e.size=B(e.size),e.space=B(e.space),e.rotate=B(e.rotate),Ut(e.incrs)&&e.incrs.forEach(e=>{!Lt.has(e)&&Lt.set(e,Rt(e))}),e.incrs=B(e.incrs||(i.distr==2?xn:a?_==1?Mn:Fn:Sn)),e.splits=B(e.splits||(a&&i.distr==1?Ge:i.distr==3?pr:i.distr==4?mr:fr)),e.stroke=B(e.stroke),e.grid.stroke=B(e.grid.stroke),e.ticks.stroke=B(e.ticks.stroke),e.border.stroke=B(e.border.stroke);let o=e.values;e.values=Ut(o)&&!Ut(o[0])?B(o):a?Ut(o)?zn(He,Rn(o,We)):Kt(o)?Bn(He,o):o||Ye:o||dr,e.filter=B(e.filter||(i.distr>=3&&i.log==10?br:i.distr==3&&i.log==2?xr:Ot)),e.font=Oi(e.font),e.labelFont=Oi(e.labelFont),e._size=e.size(r,null,t,0),e._space=e._rotate=e._incrs=e._found=e._splits=e._values=null,e._size>0&&(Yn[t]=!0,e._el=Re(te,f))}}function Zn(e,t,n,r){let[i,a,o,s]=n,c=t%2,l=0;return c==0&&(s||a)&&(l=t==0&&!i||t==2&&!o?pt(sr.size/3):0),c==1&&(i||o)&&(l=t==1&&!a||t==3&&!s?pt(Cr.size/2):0),l}let Qn=r.padding=(e.padding||[Zn,Zn,Zn,Zn]).map(e=>B(L(e,Zn))),$n=r._padding=Qn.map((e,t)=>e(r,t,Yn,0)),K,q=null,J=null,tr=i==1?v[0].idxs:null,nr=null,rr=!1;function ir(e,n){if(t=e??[],r.data=r._data=t,i==2){K=0;for(let e=1;e=0,gn=!0,ci()}}r.setData=ir;function ar(){rr=!0;let e,n;i==1&&(K>0?(q=tr[0]=0,J=tr[1]=K-1,e=t[0][q],n=t[0][J],Ne==2?(e=q,n=J):e==n&&(Ne==3?[e,n]=$e(e,e,j.log,!1):Ne==4?[e,n]=et(e,e,j.log,!1):j.time?n=e+pt(86400/_):[e,n]=at(e,n,tt,!0))):(q=tr[0]=e=null,J=tr[1]=n=null)),Wi(A,e,n)}let or,hr,gr,_r,vr,yr,Tr,Er,Dr,Nr;function Lr(e,t,n,r,i,a){e??=ve,n??=Vt,r??=`butt`,i??=ve,a??=`round`,e!=or&&(d.strokeStyle=or=e),i!=hr&&(d.fillStyle=hr=i),t!=gr&&(d.lineWidth=gr=t),a!=vr&&(d.lineJoin=vr=a),r!=yr&&(d.lineCap=yr=r),n!=_r&&d.setLineDash(_r=n)}function Rr(e,t,n,r){t!=hr&&(d.fillStyle=hr=t),e!=Tr&&(d.font=Tr=e),n!=Er&&(d.textAlign=Er=n),r!=Dr&&(d.textBaseline=Dr=r)}function Br(e,t,n,i,a=0){if(i.length>0&&e.auto(r,rr)&&(t==null||t.min==null)){let t=L(q,0),r=L(J,i.length-1),o=n.min==null?Qe(i,t,r,a,e.distr==3):[n.min,n.max];e.min=ht(e.min,n.min=o[0]),e.max=gt(e.max,n.max=o[1])}}let Vr={min:null,max:null};function Hr(){for(let e in b){let t=b[e];P[e]==null&&(t.min==null||P[A]!=null&&t.auto(r,rr))&&(P[e]=Vr)}for(let e in b){let t=b[e];P[e]==null&&t.from!=null&&P[t.from]!=null&&(P[e]=Vr)}P[A]!=null&&ri(!0);let e={};for(let t in P){let n=P[t];if(n!=null){let a=e[t]=Zt(b[t],Jt);if(n.min!=null)H(a,n);else if(t!=A||i==2)if(K==0&&a.from==null){let e=a.range(r,null,null,t);a.min=e[0],a.max=e[1]}else a.min=z,a.max=-1/0}}if(K>0){v.forEach((n,a)=>{if(i==1){let i=n.scale,o=P[i];if(o==null)return;let s=e[i];if(a==0){let e=s.range(r,s.min,s.max,i);s.min=e[0],s.max=e[1],q=Je(s.min,t[0]),J=Je(s.max,t[0]),J-q>1&&(t[0][q]s.max&&J--),n.min=nr[q],n.max=nr[J]}else n.show&&n.auto&&Br(s,o,n,t[a],n.sorted);n.idxs[0]=q,n.idxs[1]=J}else if(a>0&&n.show&&n.auto){let[r,i]=n.facets,o=r.scale,s=i.scale,[c,l]=t[a],u=e[o],d=e[s];u!=null&&Br(u,P[o],r,c,r.sorted),d!=null&&Br(d,P[s],i,l,i.sorted),n.min=i.min,n.max=i.max}});for(let t in e){let n=e[t],i=P[t];if(n.from==null&&(i==null||i.min==null)){let e=n.range(r,n.min==z?null:n.min,n.max==-1/0?null:n.max,t);n.min=e[0],n.max=e[1]}}}for(let t in e){let n=e[t];if(n.from!=null){let i=e[n.from];if(i.min==null)n.min=n.max=null;else{let e=n.range(r,i.min,i.max,t);n.min=e[0],n.max=e[1]}}}let n={},a=!1;for(let t in e){let r=e[t],i=b[t];if(i.min!=r.min||i.max!=r.max){i.min=r.min,i.max=r.max;let e=i.distr;i._min=e==3?yt(i.min):e==4?St(i.min,i.asinh):e==100?i.fwd(i.min):i.min,i._max=e==3?yt(i.max):e==4?St(i.max,i.asinh):e==100?i.fwd(i.max):i.max,n[t]=a=!0}}if(a){v.forEach((e,t)=>{i==2?t>0&&n.y&&(e._paths=null):n[e.scale]&&(e._paths=null)});for(let e in n)fn=!0,Oa(`setScale`,e);it&&I.left>=0&&(pn=gn=!0)}for(let e in P)P[e]=null}function Ur(e){let t=wt(q-1,0,K-1),n=wt(J+1,0,K-1);for(;e[t]==null&&t>0;)t--;for(;e[n]==null&&n0){let e=v.some(e=>e._focus)&&Nr!=Dn.alpha;e&&(d.globalAlpha=Nr=Dn.alpha),v.forEach((e,n)=>{if(n>0&&e.show&&(Kr(n,!1),Kr(n,!0),e._paths==null)){let a=Nr;Nr!=e.alpha&&(d.globalAlpha=Nr=e.alpha);let o=i==2?[0,t[n][0].length-1]:Ur(t[n]);e._paths=e.paths(r,n,o[0],o[1]),Nr!=a&&(d.globalAlpha=Nr=a)}}),v.forEach((e,t)=>{if(t>0&&e.show){let n=Nr;Nr!=e.alpha&&(d.globalAlpha=Nr=e.alpha),e._paths!=null&&qr(t,!1);{let n=e._paths==null?null:e._paths.gaps,i=e.points.show(r,t,q,J,n),a=e.points.filter(r,t,i,n);(i||a)&&(e.points._paths=e.points.paths(r,t,q,J,a),qr(t,!0))}Nr!=n&&(d.globalAlpha=Nr=n),Oa(`drawSeries`,t)}}),e&&(d.globalAlpha=Nr=1)}}function Kr(e,t){let n=t?v[e].points:v[e];n._stroke=n.stroke(r,e),n._fill=n.fill(r,e)}function qr(e,t){let n=t?v[e].points:v[e],{stroke:r,fill:i,clip:a,flags:o,_stroke:s=n._stroke,_fill:c=n._fill,_width:l=n.width}=n._paths;l=V(l*M,3);let u=null,f=l%2/2;t&&c==null&&(c=l>0?`#fff`:s);let p=n.pxAlign==1&&f>0;if(p&&d.translate(f,f),!t){let e=on-l/2,t=sn-l/2,n=cn+l,r=ln+l;u=new Path2D,u.rect(e,t,n,r)}t?Yr(s,l,n.dash,n.cap,c,r,i,o,a):Jr(e,s,l,n.dash,n.cap,c,r,i,o,u,a),p&&d.translate(-f,-f)}function Jr(e,n,i,a,o,s,c,l,u,d,f){let p=!1;u!=0&&x.forEach((m,h)=>{if(m.series[0]==e){let e=v[m.series[1]],g=t[m.series[1]],_=(e._paths||Bt).band;Ut(_)&&(_=m.dir==1?_[0]:_[1]);let y,b=null;e.show&&_&&ot(g,q,J)?(b=m.fill(r,h)||s,y=e._paths.clip):_=null,Yr(n,i,a,o,b,c,l,u,d,f,y,_),p=!0}}),p||Yr(n,i,a,o,s,c,l,u,d,f)}function Yr(e,t,n,r,i,a,o,s,c,l,u,f){Lr(e,t,n,r,i),(c||l||f)&&(d.save(),c&&d.clip(c),l&&d.clip(l)),f?(s&3)==3?(d.clip(f),u&&d.clip(u),Zr(i,o),Xr(e,a,t)):s&Ir?(Zr(i,o),d.clip(f),Xr(e,a,t)):s&Fr&&(d.save(),d.clip(f),u&&d.clip(u),Zr(i,o),d.restore(),Xr(e,a,t)):(Zr(i,o),Xr(e,a,t)),(c||l||f)&&d.restore()}function Xr(e,t,n){n>0&&(t instanceof Map?t.forEach((e,t)=>{d.strokeStyle=or=t,d.stroke(e)}):t!=null&&e&&d.stroke(t))}function Zr(e,t){t instanceof Map?t.forEach((e,t)=>{d.fillStyle=hr=t,d.fill(e)}):t!=null&&e&&d.fill(t)}function Qr(e,t,n,i){let a=y[e],o;if(i<=0)o=[0,0];else{let s=a._space=a.space(r,e,t,n,i);o=Di(t,n,a._incrs=a.incrs(r,e,t,n,i,s),i,s)}return a._found=o}function $r(e,t,n,r,i,a,o,s,c,l){let u=o%2/2;h==1&&d.translate(u,u),Lr(s,o,c,l,s),d.beginPath();let f,p,m,g,_=i+(r==0||r==3?-a:a);n==0?(p=i,g=_):(f=i,m=_);for(let r=0;r{if(!n.show)return;let a=b[n.scale];if(a.min==null){n._show&&(t=!1,n._show=!1,ri(!1));return}n._show||(t=!1,n._show=!0,ri(!1));let o=n.side,s=o%2,{min:c,max:l}=a,[u,d]=Qr(i,c,l,s==0?U:W);if(d==0)return;let f=a.distr==2,p=n._splits=n.splits(r,i,c,l,u,d,f),m=a.distr==2?p.map(e=>nr[e]):p,h=a.distr==2?nr[p[1]]-nr[p[0]]:u,g=n._values=n.values(r,n.filter(r,m,i,d,h),i,d,h);n._rotate=o==2?n.rotate(r,g,i,d):0;let _=n._size;n._size=mt(n.size(r,g,i,e)),_!=null&&n._size!=_&&(t=!1)}),t}function ti(e){let t=!0;return Qn.forEach((n,i)=>{let a=n(r,i,Yn,e);a!=$n[i]&&(t=!1),$n[i]=a}),t}function ni(){for(let e=0;enr[e]):_,x=p.distr==2?nr[_[1]]-nr[_[0]]:u,S=t.ticks,C=t.border,w=S.show?S.size:0,T=pt(w*M),E=pt((t.alignTo==2?t._size-w-t.gap:t.gap)*M),ee=t._rotate*-dt/180,D=g(t._pos*M),te=D+(T+E)*l;o=i==0?te:0,a=i==1?te:0;let ne=t.font[0];Rr(ne,c,t.align==1?ge:t.align==2?_e:ee>0?ge:ee<0?_e:i==0?`center`:n==3?_e:ge,ee||i==1?`middle`:n==2?me:he);let re=t.font[1]*t.lineGap,ie=_.map(e=>g(s(e,p,m,h))),ae=t._values;for(let e=0;e{n>0&&(t._paths=null,e&&(i==1?(t.min=null,t.max=null):t.facets.forEach(e=>{e.min=null,e.max=null})))})}let ii=!1,ai=!1,oi=[];function si(){ai=!1;for(let e=0;e0&&queueMicrotask(si)}r.batch=li;function ui(){if(un&&=(Hr(),!1),fn&&=(yn(),!1),dn){if(N(p,ge,Qt),N(p,me,$t),N(p,pe,U),N(p,k,W),N(m,ge,Qt),N(m,me,$t),N(m,pe,U),N(m,k,W),N(f,pe,Yt),N(f,k,Xt),u.width=pt(Yt*M),u.height=pt(Xt*M),y.forEach(({_el:e,_show:t,_size:n,_pos:r,side:i})=>{if(e!=null)if(t){let t=i===3||i===0?n:0,a=i%2==1;N(e,a?`left`:`top`,r-t),N(e,a?`width`:`height`,n),N(e,a?`top`:`left`,a?$t:Qt),N(e,a?`height`:`width`,a?W:U),Ie(e,ne)}else Fe(e,ne)}),or=hr=gr=vr=yr=Tr=Er=Dr=_r=null,Nr=1,fa(!0),Qt!=en||$t!=nn||U!=rn||W!=an){ri(!1);let e=U/rn,t=W/an;if(it&&!pn&&I.left>=0){I.left*=e,I.top*=t,Y&&Be(Y,pt(I.left),0,U,W),Ai&&Be(Ai,0,pt(I.top),U,W);for(let n=0;n=0&&Q.width>0){Q.left*=e,Q.width*=e,Q.top*=t,Q.height*=t;for(let e in ha)N(Vi,e,Q[e])}en=Qt,nn=$t,rn=U,an=W}Oa(`setSize`),dn=!1}Yt>0&&Xt>0&&(d.clearRect(0,0,u.width,u.height),Oa(`drawClear`),Ee.forEach(e=>e()),Oa(`draw`)),Q.show&&hn&&(Hi(Q),hn=!1),it&&pn&&(ua(null,!0,!1),pn=!1),F.show&&F.live&&gn&&(ca(),gn=!1),c||(c=!0,r.status=1,Oa(`ready`)),rr=!1,ii=!1}r.redraw=(e,t)=>{fn=t||!1,e===!1?ci():Wi(A,j.min,j.max)};function di(e,n){let i=b[e];if(i.from==null){if(K==0){let t=i.range(r,n.min,n.max,e);n.min=t[0],n.max=t[1]}if(n.min>n.max){let e=n.min;n.min=n.max,n.max=e}if(K>1&&n.min!=null&&n.max!=null&&n.max-n.min<1e-16)return;e==A&&i.distr==2&&K>0&&(n.min=Je(n.min,t[0]),n.max=Je(n.max,t[0]),n.min==n.max&&n.max++),P[e]=n,un=!0,ci()}}r.setScale=di;let fi,mi,Y,Ai,ji,Mi,Ni,Pi,Fi,Ii,X,Z,Li=!1,Ri=I.drag,zi=Ri.x,Bi=Ri.y;it&&(I.x&&(fi=Re(ie,m)),I.y&&(mi=Re(ae,m)),j.ori==0?(Y=fi,Ai=mi):(Y=mi,Ai=fi),X=I.left,Z=I.top);let Q=r.select=H({show:!0,over:!0,left:0,width:0,top:0,height:0},e.select),Vi=Q.show?Re(re,Q.over?m:p):null;function Hi(e,t){if(Q.show){for(let t in e)Q[t]=e[t],t in ha&&N(Vi,t,e[t]);t!==!1&&Oa(`setSelect`)}}r.setSelect=Hi;function Ui(e){if(v[e].show)rt&&Ie(ft[e],ne);else if(rt&&Fe(ft[e],ne),it){let t=kn?An[0]:An[e];t!=null&&Be(t,-10,-10,U,W)}}function Wi(e,t,n){di(e,{min:t,max:n})}function Gi(e,t,n,a){t.focus!=null&&ea(e),t.show!=null&&v.forEach((n,r)=>{r>0&&(e==r||e==null)&&(n.show=t.show,Ui(r),i==2?(Wi(n.facets[0].scale,null,null),Wi(n.facets[1].scale,null,null)):Wi(n.scale,null,null),ci())}),n!==!1&&Oa(`setSeries`,e,t),a&&Ma(`setSeries`,r,e,t)}r.setSeries=Gi;function Ki(e,t){H(x[e],t)}function qi(e,t){e.fill=B(e.fill||null),e.dir=L(e.dir,-1),t??=x.length,x.splice(t,0,e)}function Ji(e){e==null?x.length=0:x.splice(e,1)}r.addBand=qi,r.setBand=Ki,r.delBand=Ji;function Yi(e,t){v[e].alpha=t,it&&An[e]!=null&&(An[e].style.opacity=t),rt&&ft[e]&&(ft[e].style.opacity=t)}let Xi,Zi,Qi,$i={focus:!0};function ea(e){if(e!=Qi){let t=e==null,n=Dn.alpha!=1;v.forEach((r,a)=>{if(i==1||a>0){let i=t||a==0||a==e;r._focus=t?null:i,n&&Yi(a,i?1:Dn.alpha)}}),Qi=e,n&&ci()}}rt&&On&&zt(Ce,ct,e=>{I._lock||(Tn(e),Qi!=null&&Gi(null,$i,!0,$.setSeries))});function ta(e,t,n){let r=b[t];n&&(e=e/M-(r.ori==1?$t:Qt));let i=U;r.ori==1&&(i=W,e=i-e),r.dir==-1&&(e=i-e);let a=r._min,o=r._max,s=e/i,c=a+(o-a)*s,l=r.distr;return l==3?_t(10,c):l==4?xt(c,r.asinh):l==100?r.bwd(c):c}function na(e,n){return Je(ta(e,A,n),t[0],q,J)}r.valToIdx=e=>Je(e,t[0]),r.posToIdx=na,r.posToVal=ta,r.valToPos=(e,t,n)=>b[t].ori==0?a(e,b[t],n?cn:U,n?on:0):o(e,b[t],n?ln:W,n?sn:0),r.setCursor=(e,t,n)=>{X=e.left,Z=e.top,ua(null,t,n)};function ra(e,t){N(Vi,ge,Q.left=e),N(Vi,pe,Q.width=t)}function ia(e,t){N(Vi,me,Q.top=e),N(Vi,k,Q.height=t)}let aa=j.ori==0?ra:ia,oa=j.ori==1?ra:ia;function sa(){if(rt&&F.live)for(let e=+(i==2);e{Ze[t]=e}):Gt(e.idx)||Ze.fill(e.idx),F.idx=Ze[0]),rt&&F.live){for(let e=0;e0||i==1&&!Ct)&&la(e,Ze[e]);sa()}gn=!1,t!==!1&&Oa(`setLegend`)}r.setLegend=ca;function la(e,n){let i=v[e],a=e==0&&Ne==2?nr:t[e],o;Ct?o=i.values(r,e,n)??Et:(o=i.value(r,n==null?null:a[n],e,n),o=o==null?Et:{_:o}),F.values[e]=o}function ua(e,n,a){Fi=X,Ii=Z,[X,Z]=I.move(r,X,Z),I.left=X,I.top=Z,it&&(Y&&Be(Y,pt(X),0,U,W),Ai&&Be(Ai,0,pt(Z),U,W));let o,s=q>J;Xi=z,Zi=null;let c=j.ori==0?U:W,l=j.ori==1?U:W;if(X<0||K==0||s){o=I.idx=null;for(let e=0;e0&&g.show){let n=x==null?-10:x==o?a:Pe(i==1?t[0][x]:t[e][0][x],j,c,0),_=S==null?-10:ze(S,i==1?b[g.scale]:b[g.facets[1].scale],l,0);if(On&&S!=null){let t=j.ori==1?X:Z,n=R(Dn.dist(r,e,x,_,t));if(n=0?1:-1,o=i>=0?1:-1;o==a&&(o==1?r==1?S>=i:S<=i:r==1?S<=i:S>=i)&&(Xi=n,Zi=e)}else Xi=n,Zi=e}}if(gn||kn){let t,i;j.ori==0?(t=n,i=_):(t=_,i=n);let a,o,c,l,g,v,y=!0,b=En.bbox;if(b!=null){y=!1;let t=b(r,e);c=t.left,l=t.top,a=t.width,o=t.height}else c=t,l=i,a=o=En.size(r,e);if(v=En.fill(r,e),g=En.stroke(r,e),kn)e==Zi&&Xi<=Dn.prox&&(s=c,u=l,d=a,f=o,p=y,m=v,h=g);else{let t=An[e];t!=null&&(G[e]=c,jn[e]=l,Ue(t,a,o,y),Ve(t,v,g),Be(t,mt(c),mt(l),U,W))}}}}if(kn){let e=Dn.prox;if(gn||(Qi==null?Xi<=e:Xi>e||Zi!=Qi)){let e=An[0];e!=null&&(G[0]=s,jn[0]=u,Ue(e,d,f,p),Ve(e,m,h),Be(e,mt(s),mt(u),U,W))}}}if(Q.show&&Li)if(e!=null){let[t,n]=$.scales,[r,i]=$.match,[a,o]=e.cursor.sync.scales,s=e.cursor.drag;if(zi=s._x,Bi=s._y,zi||Bi){let{left:s,top:u,width:d,height:f}=e.select,p=e.scales[a].ori,m=e.posToVal,h,g,_,v,y,x=t!=null&&r(t,a),S=n!=null&&i(n,o);x&&zi?(p==0?(h=s,g=d):(h=u,g=f),_=b[t],v=Pe(m(h,a),_,c,0),y=Pe(m(h+g,a),_,c,0),aa(ht(v,y),R(y-v))):aa(0,c),S&&Bi?(p==1?(h=s,g=d):(h=u,g=f),_=b[n],v=ze(m(h,o),_,l,0),y=ze(m(h+g,o),_,l,0),oa(ht(v,y),R(y-v))):oa(0,l)}else ga()}else{let e=R(Fi-ji),t=R(Ii-Mi);if(j.ori==1){let n=e;e=t,t=n}zi=Ri.x&&e>=Ri.dist,Bi=Ri.y&&t>=Ri.dist;let n=Ri.uni;n==null?Ri.x&&Ri.y&&(zi||Bi)&&(zi=Bi=!0):zi&&Bi&&(zi=e>=n,Bi=t>=n,!zi&&!Bi&&(t>e?Bi=!0:zi=!0));let r,i;zi&&(j.ori==0?(r=Ni,i=X):(r=Pi,i=Z),aa(ht(r,i),R(i-r)),Bi||oa(0,l)),Bi&&(j.ori==1?(r=Ni,i=X):(r=Pi,i=Z),oa(ht(r,i),R(i-r)),zi||aa(0,c)),!zi&&!Bi&&(aa(0,0),oa(0,0))}if(Ri._x=zi,Ri._y=Bi,e==null){if(a){if(Aa!=null){let[e,t]=$.scales;$.values[0]=e==null?null:ta(j.ori==0?X:Z,e),$.values[1]=t==null?null:ta(j.ori==1?X:Z,t)}Ma(ye,r,X,Z,U,W,o)}if(On){let e=a&&$.setSeries,t=Dn.prox;Qi==null?Xi<=t&&Gi(Zi,$i,!0,e):Xi>t?Gi(null,$i,!0,e):Zi!=Qi&&Gi(Zi,$i,!0,e)}}gn&&(F.idx=o,ca()),n!==!1&&Oa(`setCursor`)}let da=null;Object.defineProperty(r,"rect",{get(){return da??fa(!1),da}});function fa(e=!1){e?da=null:(da=m.getBoundingClientRect(),Oa(`syncRect`,da))}function pa(e,t,n,r,i,a,o){I._lock||Li&&e!=null&&e.movementX==0&&e.movementY==0||(ma(e,t,n,r,i,a,o,!1,e!=null),e==null?ua(t,!0,!1):ua(null,!0,!0))}function ma(e,t,n,i,a,o,c,l,u){if(da??fa(!1),Tn(e),e!=null)n=e.clientX-da.left,i=e.clientY-da.top;else{if(n<0||i<0){X=-10,Z=-10;return}let[e,r]=$.scales,c=t.cursor.sync,[l,u]=c.values,[d,f]=c.scales,[p,m]=$.match,h=t.axes[0].side%2==1,g=j.ori==0?U:W,_=j.ori==1?U:W,v=h?o:a,y=h?a:o,x=h?i:n,S=h?n:i;if(n=d==null?x/v*g:p(e,d)?s(l,b[e],g,0):-10,i=f==null?S/y*_:m(r,f)?s(u,b[r],_,0):-10,j.ori==1){let e=n;n=i,i=e}}u&&(t==null||t.cursor.event.type==ye)&&((n<=1||n>=U-1)&&(n=Pt(n,U)),(i<=1||i>=W-1)&&(i=Pt(i,W))),l?(ji=n,Mi=i,[Ni,Pi]=I.move(r,n,i)):(X=n,Z=i)}let ha={width:0,height:0,left:0,top:0};function ga(){Hi(ha,!1)}let _a,va,ya,ba;function xa(e,t,n,i,a,o,s){Li=!0,zi=Bi=Ri._x=Ri._y=!1,ma(e,t,n,i,a,o,s,!0,!1),e!=null&&(zt(xe,je,Sa,!1),Ma(be,r,Ni,Pi,U,W,null));let{left:c,top:l,width:u,height:d}=Q;_a=c,va=l,ya=u,ba=d}function Sa(e,t,n,i,a,o,s){Li=Ri._x=Ri._y=!1,ma(e,t,n,i,a,o,s,!1,!0);let{left:c,top:l,width:u,height:d}=Q,f=u>0||d>0,p=_a!=c||va!=l||ya!=u||ba!=d;if(f&&p&&Hi(Q),Ri.setScale&&f&&p){let e=c,t=u,n=l,r=d;if(j.ori==1&&(e=l,t=d,n=c,r=u),zi&&Wi(A,ta(e,A),ta(e+t,A)),Bi)for(let e in b){let t=b[e];e!=A&&t.from==null&&t.min!=z&&Wi(e,ta(n+r,e),ta(n,e))}ga()}else I.lock&&(I._lock=!I._lock,ua(t,!0,e!=null));e!=null&&(Wt(xe,je),Ma(xe,r,X,Z,U,W,null))}function Ca(e,t,n,r,i,a,o){if(I._lock)return;Tn(e);let s=Li;if(Li){let e=!0,t=!0,n,r;j.ori==0?(n=zi,r=Bi):(n=Bi,r=zi),n&&r&&(e=X<=10||X>=U-10,t=Z<=10||Z>=W-10),n&&e&&(X=X{let a=$.match[2];n=a(r,t,n),n!=-1&&Gi(n,i,!0,!1)},it&&(zt(be,m,xa),zt(ye,m,pa),zt(Se,m,e=>{Tn(e),fa(!1)}),zt(Ce,m,Ca),zt(we,m,wa),pi.add(r),r.syncRect=fa);let Da=r.hooks=e.hooks||{};function Oa(e,t,n){ai?oi.push([e,t,n]):e in Da&&Da[e].forEach(e=>{e.call(null,r,t,n)})}(e.plugins||[]).forEach(e=>{for(let t in e.hooks)Da[t]=(Da[t]||[]).concat(e.hooks[t])});let ka=(e,t,n)=>n,$=H({key:null,setSeries:!1,filters:{pub:At,sub:At},scales:[A,v[1]?v[1].scale:null],match:[jt,jt,ka],values:[null,null]},I.sync);$.match.length==2&&$.match.push(ka),I.sync=$;let Aa=$.key,ja=Pr(Aa);function Ma(e,t,n,r,i,a,o){$.filters.pub(e,t,n,r,i,a,o)&&ja.pub(e,t,n,r,i,a,o)}ja.sub(r);function Na(e,t,n,r,i,a,o){$.filters.sub(e,t,n,r,i,a,o)&&Ea[e](null,t,n,r,i,a,o)}r.pub=Na;function Pa(){ja.unsub(r),pi.delete(r),It.clear(),qe(Oe,Me,Ta),l.remove(),ct?.remove(),Oa(`destroy`)}r.destroy=Pa;function Fa(){Oa(`init`,e,t),ir(t||e.data,!1),P[A]?di(A,P[A]):ar(),hn=Q.show&&(Q.width>0||Q.height>0),pn=gn=!0,_n(e.width,e.height)}return v.forEach(Gn),y.forEach(Xn),n?n instanceof HTMLElement?(n.appendChild(l),Fa()):n(r,Fa):Fa(),r}Y.assign=H,Y.fmtNum=lt,Y.rangeNum=at,Y.rangeLog=$e,Y.rangeAsinh=et,Y.orient=Lr,Y.pxRatio=M,Y.join=en,Y.fmtDate=mn,Y.tzDate=gn,Y.sync=Pr;{Y.addGap=Hr,Y.clipGaps=Vr;let e=Y.paths={points:ni};e.linear=oi,e.stepped=si,e.bars=li,e.spline=di}function Ai(e,t){return typeof window>`u`?t:getComputedStyle(document.documentElement).getPropertyValue(e).trim()||t}function ji({data:e,height:t=180,ariaLabel:n,xFormat:r,yFormat:i,yRange:a,annotation:o,xAxis:s=!0}){let c=(0,_.useRef)(null),l=(0,_.useRef)(null),u=(0,_.useRef)(null),d=(0,_.useRef)(o);return d.current=o,(0,_.useLayoutEffect)(()=>{let o=c.current;if(!o)return;let f=Ai(`--chart-line`,`#5c7030`),p=Ai(`--chart-fill`,`rgba(92,112,48,0.14)`),m=Ai(`--chart-grid`,`rgba(42,36,20,0.10)`),h=Ai(`--ink-3`,`#665c40`),g=Ai(`--surface`,`#faf5e6`),_=`10px "IBM Plex Mono", ui-monospace, monospace`,v=new Y({width:o.clientWidth||600,height:t,cursor:{points:{show:!0},drag:{x:!1,y:!1}},legend:{show:!1},scales:{x:{time:!1},y:a?{range:a}:{range:(e,t,n)=>[Math.min(0,t),n*1.08]}},axes:[{show:s,stroke:h,grid:{show:!1},ticks:{show:!1},font:_,values:(e,t)=>t.map(e=>r?r(e):String(e))},{stroke:h,grid:{stroke:m,width:1},ticks:{show:!1},size:34,font:_,values:(e,t)=>t.map(e=>i?i(e):String(e))}],series:[{},{stroke:f,width:2,fill:p,points:{show:!1}}],hooks:{draw:[e=>{let t=e.data[0],n=e.data[1];if(!t||t.length===0)return;let r=t.length-1,i=t[r],a=n?.[r];if(i==null||a==null)return;let o=e.valToPos(i,`x`,!0),s=e.valToPos(a,`y`,!0),c=e.ctx;c.save(),c.beginPath(),c.arc(o,s,3.5,0,Math.PI*2),c.fillStyle=f,c.fill(),c.lineWidth=2,c.strokeStyle=g,c.stroke(),c.restore();let l=d.current,p=u.current;if(p)if(l&&t[l.index]!=null&&n?.[l.index]!=null){let r=e.valToPos(t[l.index],`x`,!0),i=e.valToPos(n[l.index],`y`,!0);p.style.display=`block`,p.style.left=`${r}px`,p.style.top=`${Math.min(e.height-26,i+10)}px`,p.textContent=l.text}else p.style.display=`none`}]}},e,o);l.current=v,o.setAttribute(`role`,`img`),o.setAttribute(`aria-label`,n);let y=new ResizeObserver(()=>{if(!c.current)return;let e=c.current.clientWidth;e>0&&v.setSize({width:e,height:t})});return y.observe(o),()=>{y.disconnect(),v.destroy(),l.current=null}},[t,n,s,a?.[0],a?.[1]]),(0,_.useEffect)(()=>{l.current?.setData(e)},[e]),(0,v.jsxs)(`div`,{className:`uplot-wrap`,children:[(0,v.jsx)(`div`,{ref:c,className:`uplot-host`}),(0,v.jsx)(`div`,{ref:u,className:`chart-annotation`,"aria-hidden":`true`})]})}function Mi(e){let t=new Date(e*1e3);return`${String(t.getHours()).padStart(2,`0`)}:${String(t.getMinutes()).padStart(2,`0`)}`}function Ni(){let[t,n]=(0,_.useState)(`1h`),i=e({queryKey:[`server`],queryFn:()=>r.server.get()}),x=e({queryKey:[`server`,`health`],queryFn:()=>r.server.health(),refetchInterval:15e3}),S=e({queryKey:[`metrics`,`current`],queryFn:()=>r.metrics.current(),refetchInterval:5e3}),C=e({queryKey:[`metrics`,`history`,t],queryFn:()=>r.metrics.history(t),refetchInterval:3e4}),w=e({queryKey:[`metrics`,`history`,`24h`],queryFn:()=>r.metrics.history(`24h`),refetchInterval:6e4}),T=e({queryKey:[`guilds`],queryFn:()=>r.guilds.list()}),E=e({queryKey:[`backups`],queryFn:()=>r.backups.list()}),ee=e({queryKey:[`players`],queryFn:()=>r.players.list()}),D=e({queryKey:[`events`,5],queryFn:()=>r.events.list(5)}),te=(0,_.useMemo)(()=>{let e=C.data?.series;return[e?.t??[],e?.fps??[]]},[C.data]),ne=(0,_.useMemo)(()=>{let e=C.data?.series;return[e?.t??[],e?.frameTimeMs??[]]},[C.data]),re=(0,_.useMemo)(()=>{let e=w.data?.series;return[e?.t??[],e?.players??[]]},[w.data]),ie=(0,_.useMemo)(()=>{let e=C.data?.series.fps;if(!e||e.length===0)return;let t=Math.min(...e),n=Math.max(...e);return[Math.max(0,Math.floor((t-6)/10)*10),Math.ceil((n+2)/10)*10]},[C.data]),ae=(0,_.useMemo)(()=>{let e=C.data?.series.fps;if(!e||e.length===0)return;let t=0;for(let n=1;ne-t);if(!(n>=(r[Math.floor(r.length/2)]??0)*.9))return{index:t,text:`${Math.round(n)} fps dip`}},[C.data]),oe=(0,_.useMemo)(()=>{let e=ee.data;if(!e)return null;let t=Date.now()-864e5;return e.filter(e=>new Date(e.lastSeenAt).getTime()>=t).length},[ee.data]),se=(0,_.useMemo)(()=>T.data?.filter(e=>e.bases.length>0).length??null,[T.data]),ce=E.data?.[0],le=E.data?.reduce((e,t)=>e+t.sizeBytes,0)??0,ue=S.data,de=i.data,O=x.data;return(0,v.jsxs)(`main`,{className:`content`,children:[(0,v.jsxs)(`div`,{className:`page-head`,children:[(0,v.jsx)(`h1`,{children:`Overview`}),(0,v.jsx)(`span`,{className:`sub`,children:de?`${de.name} · ${de.version}`:i.isError?`server unreachable`:`loading…`})]}),(0,v.jsxs)(`div`,{className:`grid cols-4`,children:[S.isLoading?(0,v.jsx)(b,{}):S.isError?(0,v.jsx)(h,{className:`stat`,children:(0,v.jsx)(f,{tone:`warn`,children:`Couldn't load server metrics.`})}):(0,v.jsx)(y,{label:`Server FPS`,value:ue.fps,delta:`frame time ${ue.frameTimeMs.toFixed(1)} ms`}),S.isLoading?(0,v.jsx)(b,{}):S.isError?(0,v.jsx)(h,{className:`stat`,children:(0,v.jsx)(f,{tone:`warn`,children:`Couldn't load player count.`})}):(0,v.jsx)(y,{label:`Players online`,value:ue.players,unit:`of ${ue.maxPlayers}`,delta:oe===null?void 0:`${oe} seen in last 24 h`}),S.isLoading?(0,v.jsx)(b,{}):S.isError?(0,v.jsx)(h,{className:`stat`,children:(0,v.jsx)(f,{tone:`warn`,children:`Couldn't load base camps.`})}):(0,v.jsx)(y,{label:`Base camps`,value:ue.baseCamps,delta:se===null?void 0:`across ${se} guilds`}),E.isLoading?(0,v.jsx)(b,{}):E.isError?(0,v.jsx)(h,{className:`stat`,children:(0,v.jsx)(f,{tone:`warn`,children:`Couldn't load backups.`})}):ce?(0,v.jsx)(y,{label:`Last backup`,value:d((Date.now()-new Date(ce.createdAt).getTime())/1e3),unit:`ago`,delta:`${E.data.length} kept · ${o(le)} total`,deltaTone:`up`}):(0,v.jsx)(y,{label:`Last backup`,value:`—`,delta:`no backups yet`})]}),(0,v.jsxs)(`div`,{className:`grid cols-3`,children:[(0,v.jsxs)(h,{span2:!0,children:[(0,v.jsx)(m,{title:`Server performance`,hint:`sampled every 5 s`,children:(0,v.jsxs)(`div`,{className:`legend-row`,role:`tablist`,"aria-label":`Time range`,children:[(0,v.jsx)(`button`,{type:`button`,className:t===`24h`?`btn btn-sm`:`btn btn-ghost btn-sm`,"aria-selected":t===`24h`,onClick:()=>n(`24h`),children:`24 h`}),(0,v.jsx)(`button`,{type:`button`,className:t===`1h`?`btn btn-sm`:`btn btn-ghost btn-sm`,"aria-selected":t===`1h`,onClick:()=>n(`1h`),children:`60 min`})]})}),C.isError?(0,v.jsx)(p,{children:(0,v.jsx)(f,{tone:`warn`,children:`Couldn't load performance history.`})}):(0,v.jsxs)(p,{chart:!0,children:[(0,v.jsx)(ji,{data:te,height:180,ariaLabel:`Server FPS over the last ${t===`1h`?`60 minutes`:`24 hours`}`,xFormat:Mi,yFormat:e=>String(Math.round(e)),yRange:ie,annotation:ae}),(0,v.jsxs)(`div`,{className:`frame-time`,children:[(0,v.jsxs)(`div`,{className:`frame-time-head`,children:[(0,v.jsx)(`span`,{children:`Frame time`}),(0,v.jsx)(`span`,{children:`ms`})]}),(0,v.jsx)(ji,{data:ne,height:48,ariaLabel:`Frame time over the same window`,yFormat:e=>e.toFixed(0),xAxis:!1})]})]})]}),(0,v.jsxs)(h,{children:[(0,v.jsx)(m,{title:`Server`}),i.isError?(0,v.jsx)(p,{children:(0,v.jsx)(f,{tone:`warn`,children:`Server is unreachable.`})}):(0,v.jsx)(p,{flush:!0,children:(0,v.jsx)(`table`,{className:`table`,children:(0,v.jsxs)(`tbody`,{children:[(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`Name`}),(0,v.jsx)(`td`,{className:`num`,children:de?.name??`—`})]}),(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`Version`}),(0,v.jsx)(`td`,{className:`num`,children:de?.version??`—`})]}),(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`Panel`}),(0,v.jsxs)(`td`,{className:`num`,children:[`v`,de?.panelVersion??`—`]})]}),(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`World`}),(0,v.jsx)(`td`,{className:`num`,title:de?.worldGuid,children:de?l(de.worldGuid):`—`})]}),(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`RCON`}),(0,v.jsx)(`td`,{children:O?(0,v.jsx)(c,{tone:O.rcon===`ok`?`ok`:`danger`,children:O.rcon===`ok`?`Connected`:`Error`}):`—`})]}),(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`REST API`}),(0,v.jsx)(`td`,{children:O?(0,v.jsx)(c,{tone:O.rest===`ok`?`ok`:`danger`,children:O.rest===`ok`?`Connected`:`Error`}):`—`})]}),(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`Save sync`}),(0,v.jsx)(`td`,{children:O?(0,v.jsx)(c,{tone:`idle`,children:s(O.save.lastSyncAt)}):`—`})]})]})})})]})]}),(0,v.jsxs)(`div`,{className:`grid cols-3`,children:[(0,v.jsxs)(h,{children:[(0,v.jsx)(m,{title:`Players online`,hint:`last 24 h`}),w.isError?(0,v.jsx)(p,{children:(0,v.jsx)(f,{tone:`warn`,children:`Couldn't load player history.`})}):(0,v.jsx)(p,{chart:!0,children:(0,v.jsx)(ji,{data:re,height:120,ariaLabel:`Players online over the last 24 hours`,xFormat:Mi,yFormat:e=>String(Math.round(e))})})]}),(0,v.jsxs)(h,{span2:!0,children:[(0,v.jsx)(m,{title:`Recent events`,children:(0,v.jsx)(a,{to:`/events`,className:`hint`,children:`view all`})}),D.isError?(0,v.jsx)(p,{children:(0,v.jsx)(f,{tone:`warn`,children:`Couldn't load recent events.`})}):(0,v.jsx)(p,{flush:!0,children:(0,v.jsx)(`table`,{className:`table`,children:(0,v.jsxs)(`tbody`,{children:[(D.data??[]).map((e,t)=>(0,v.jsxs)(`tr`,{children:[(0,v.jsx)(`td`,{style:{width:90},className:`num`,children:u(e.at).slice(11,16)}),(0,v.jsx)(`td`,{children:(0,v.jsx)(c,{tone:e.kind===`join`?`ok`:e.kind===`system`?`warn`:`idle`,children:e.kind})}),(0,v.jsx)(`td`,{children:(0,v.jsx)(g,{text:e.message})})]},t)),D.data&&D.data.length===0&&(0,v.jsx)(`tr`,{children:(0,v.jsx)(`td`,{colSpan:3,style:{color:`var(--ink-3)`},children:`No events yet.`})})]})})})]})]})]})}export{Ni as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Diagnostics-CTBJNOCA.js b/backend/internal/webdist/dist/assets/Diagnostics-CTBJNOCA.js
new file mode 100644
index 0000000..d6e1db8
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Diagnostics-CTBJNOCA.js
@@ -0,0 +1 @@
+import{U as e,_t as t,ht as n,j as r,q as i}from"./icons-CpYMTu_k.js";import{a,c as o,d as s,o as c,s as l}from"./index-BpCavHBc.js";import{t as u}from"./Banner-DSN1nEJn.js";import{n as d,r as f,t as p}from"./Card-D55CMzdw.js";var m=t(n(),1);function h(e,t,n,r=Date.now()){if(!e)return{tone:`idle`,label:`Unavailable`,ageMs:null};let i=new Date(e).getTime();if(!Number.isFinite(i)||i<=0)return{tone:`idle`,label:`Unavailable`,ageMs:null};let a=Math.max(0,r-i);return a>=n?{tone:`danger`,label:`Stale`,ageMs:a}:a>=t?{tone:`warn`,label:`Aging`,ageMs:a}:{tone:`ok`,label:`Current`,ageMs:a}}function g(e){return e===`ready`?`ok`:e===`stale`||e===`pending`?`warn`:e===`unavailable`||e===`unauthorized`?`danger`:`idle`}function _(e){switch(e){case`ready`:return`The shared Game Data poller has a usable snapshot.`;case`stale`:return`The last accepted snapshot is retained while the poller retries.`;case`pending`:return`Enabled; waiting for the first accepted snapshot.`;case`disabled`:return`The optional Game Data capability is disabled.`;case`unsupported`:return`The game server does not expose the required endpoint.`;case`unauthorized`:return`The configured game API credentials were rejected.`;case`unavailable`:return`No accepted snapshot is currently available.`}}function v(e,t){let n=Math.max(0,e)+Math.max(0,t);return n===0?{value:`Unavailable`,detail:`No accepted base-Pal actors to link.`}:{value:`${Math.round(Math.max(0,e)/n*100)}%`,detail:`${Math.max(0,e)} linked · ${Math.max(0,t)} unresolved`}}var y=i();function b({children:e}){return(0,y.jsx)(`dl`,{className:`diagnostic-rows`,children:e})}function x({label:e,value:t,detail:n,tone:r}){return(0,y.jsxs)(`div`,{className:`diagnostic-row`,children:[(0,y.jsx)(`dt`,{children:e}),(0,y.jsxs)(`dd`,{children:[(0,y.jsx)(`span`,{className:`diagnostic-value`,children:r?(0,y.jsx)(s,{tone:r,children:t}):t}),n&&(0,y.jsx)(`span`,{className:`diagnostic-detail`,children:n})]})]})}function S({label:e,reason:t}){return(0,y.jsx)(x,{label:e,value:`Unavailable`,detail:t,tone:`idle`})}var C=15e3;function w({loading:e,error:t,children:n}){return t?(0,y.jsx)(d,{children:(0,y.jsx)(u,{tone:`warn`,children:`This diagnostic source could not be loaded.`})}):e?(0,y.jsx)(d,{children:(0,y.jsx)(`span`,{className:`skel skel-text diagnostics-skeleton`})}):(0,y.jsx)(y.Fragment,{children:n})}function T(e){return e?`${o(e)} · ${c(e)}`:`No successful observation has been recorded.`}function E(e){let t=(new Date(e).getTime()-Date.now())/1e3;return t>0?`in ${l(t)}`:o(e)}function D(){let[t,n]=(0,m.useState)(!1),i=e({queryKey:[`server`,`health`],queryFn:()=>r.server.health(),refetchInterval:C}),s=e({queryKey:[`world`],queryFn:()=>r.world.get(),refetchInterval:C}),u=e({queryKey:[`world`,`snapshot`],queryFn:()=>r.world.snapshot(),refetchInterval:C}),D=e({queryKey:[`backups`],queryFn:()=>r.backups.list(),refetchInterval:6e4}),O=e({queryKey:[`backups`,`schedule`],queryFn:()=>r.backups.schedule(),refetchInterval:6e4}),k=e({queryKey:[`backups`,`storage`],queryFn:()=>r.backups.storage(),refetchInterval:6e4,retry:!1});async function A(){n(!0);try{await Promise.all([i.refetch(),s.refetch(),u.refetch(),D.refetch(),O.refetch(),k.refetch()])}finally{n(!1)}}let j=i.data,M=s.data,N=u.data,P=D.data,F=O.data,I=k.data,L=P?.[0],R=P?.reduce((e,t)=>e+t.sizeBytes,0)??0,z=N?v(N.diagnostics.linkedBasePals,N.diagnostics.unresolvedBasePals):null,B=Math.max(N?.diagnostics.scheduledDelayMs??0,3e4),V=h(N?.capturedAt,B*2,B*4);return(0,y.jsxs)(`main`,{className:`content diagnostics-page`,children:[(0,y.jsxs)(`div`,{className:`page-head diagnostics-head`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h1`,{children:`Diagnostics`}),(0,y.jsx)(`span`,{className:`sub`,children:`read-only health evidence · cached pollers`})]}),(0,y.jsx)(`button`,{type:`button`,className:`btn btn-sm`,disabled:t,onClick:A,children:t?`Refreshing…`:`Refresh now`})]}),(0,y.jsxs)(`div`,{className:`diagnostics-grid`,children:[(0,y.jsxs)(p,{children:[(0,y.jsx)(f,{title:`Core pollers`,hint:`15 s refresh`}),(0,y.jsx)(w,{loading:i.isLoading,error:i.isError,children:(0,y.jsx)(d,{flush:!0,children:(0,y.jsxs)(b,{children:[(0,y.jsx)(x,{label:`Palworld REST`,value:j?.rest??`Unavailable`,tone:j?.rest===`ok`?`ok`:`danger`,detail:`Shared metrics, players, and server-info source.`}),(0,y.jsx)(x,{label:`RCON probe`,value:j?.rcon??`Unavailable`,tone:j?.rcon===`ok`?`ok`:`danger`,detail:`Background command-channel health probe.`}),(0,y.jsx)(x,{label:`Save discovery`,value:j?.save.state??`Unavailable`,tone:j?.save.state===`ok`?`ok`:j?.save.state===`error`?`danger`:`idle`,detail:T(j?.save.lastSyncAt)}),(0,y.jsx)(S,{label:`Metrics sample time`,reason:`The current-metrics contract does not expose a sample timestamp.`})]})})})]}),(0,y.jsxs)(p,{children:[(0,y.jsx)(f,{title:`Save parser`,hint:`decoded world snapshot`}),(0,y.jsx)(w,{loading:s.isLoading,error:s.isError,children:(0,y.jsx)(d,{flush:!0,children:(0,y.jsxs)(b,{children:[(0,y.jsx)(x,{label:`Last completed parse`,value:M?.lastParseAt?o(M.lastParseAt):`Never`,tone:M?.lastParseAt?`ok`:`idle`,detail:M?.lastParseAt?c(M.lastParseAt):`No completed parser snapshot is available.`}),(0,y.jsx)(x,{label:`Parse duration`,value:M?.lastParseAt?`${M.parseDurationMs.toLocaleString()} ms`:`Unavailable`}),(0,y.jsx)(x,{label:`Format coverage`,value:M?.formatDrift?`Drift detected`:`Complete`,tone:M?.formatDrift?`warn`:`ok`,detail:M?`${M.stats.skippedProps} skipped properties`:void 0}),(0,y.jsx)(x,{label:`Decoded records`,value:M?`${M.stats.players} players · ${M.stats.pals} Pals · ${M.stats.guilds} guilds`:`Unavailable`,detail:M?`World day ${M.day}`:void 0})]})})})]}),(0,y.jsxs)(p,{className:`diagnostics-wide`,children:[(0,y.jsx)(f,{title:`Game Data`,hint:`optional Palworld 1.0 poller`}),(0,y.jsx)(w,{loading:u.isLoading,error:u.isError,children:(0,y.jsx)(d,{flush:!0,children:(0,y.jsxs)(`div`,{className:`diagnostics-columns`,children:[(0,y.jsxs)(b,{children:[(0,y.jsx)(x,{label:`Capability state`,value:N?.state??`Unavailable`,tone:N?g(N.state):`idle`,detail:N?_(N.state):void 0}),(0,y.jsx)(x,{label:`Snapshot freshness`,value:V.label,tone:V.tone,detail:T(N?.capturedAt)}),(0,y.jsx)(x,{label:`Last attempt`,value:N?.lastAttemptAt?o(N.lastAttemptAt):`Never`,detail:N?.lastAttemptAt?c(N.lastAttemptAt):`The poller has not attempted a request.`}),(0,y.jsx)(x,{label:`Request latency`,value:N?`${N.diagnostics.lastRequestDurationMs.toLocaleString()} ms`:`Unavailable`,detail:`Last completed upstream request.`}),(0,y.jsx)(x,{label:`Accepted actors`,value:N?N.diagnostics.lastAcceptedActorCount.toLocaleString():`Unavailable`,detail:N?.truncated?`The browser projection was capped.`:`Bounded count only; raw actor data is not shown here.`})]}),(0,y.jsxs)(b,{children:[(0,y.jsx)(x,{label:`Base-Pal link coverage`,value:z?.value??`Unavailable`,tone:N?.diagnostics.linkLookupFailed?`danger`:z?.value===`100%`?`ok`:`warn`,detail:N?.diagnostics.linkLookupFailed?`Save-link lookup failed for this attempt.`:z?.detail}),(0,y.jsx)(x,{label:`Last error category`,value:N?.diagnostics.lastErrorCategory||`none`,tone:N?.diagnostics.lastErrorCategory&&N.diagnostics.lastErrorCategory!==`none`?`warn`:`ok`,detail:`Bounded category; upstream messages and bodies are never exposed.`}),(0,y.jsx)(x,{label:`Retry delay`,value:N?l(N.diagnostics.scheduledDelayMs/1e3):`Unavailable`,detail:`Backoff reported by the shared poller.`}),(0,y.jsx)(x,{label:`Next attempt`,value:N?.diagnostics.nextAttemptAt?E(N.diagnostics.nextAttemptAt):`Not scheduled`,detail:N?.diagnostics.nextAttemptAt?c(N.diagnostics.nextAttemptAt):`Disabled or no retry deadline is available.`}),(0,y.jsx)(x,{label:`Accepted totals`,value:N?`${N.counts.players} players · ${N.counts.basePals} base Pals · ${N.counts.palBoxes} PalBoxes`:`Unavailable`,detail:`Aggregate counts from the accepted snapshot.`})]})]})})})]}),(0,y.jsxs)(p,{children:[(0,y.jsx)(f,{title:`Backups`,hint:`indexed archives`}),(0,y.jsx)(w,{loading:D.isLoading||O.isLoading,error:D.isError||O.isError,children:(0,y.jsx)(d,{flush:!0,children:(0,y.jsxs)(b,{children:[(0,y.jsx)(x,{label:`Latest archive`,value:L?o(L.createdAt):`None`,tone:L?`ok`:`warn`,detail:L?`${c(L.createdAt)} · ${L.trigger} · ${a(L.sizeBytes)}`:`No indexed backup is available.`}),(0,y.jsx)(x,{label:`Schedule`,value:F?.enabled?`Every ${l(F.everyMinutes*60)}`:`Disabled`,tone:F?.enabled?`ok`:`idle`,detail:F?.enabled?`${F.keepDays} day retention`:`Automatic backups are not scheduled.`}),(0,y.jsx)(x,{label:`Next scheduled run`,value:F?.nextRunAt?E(F.nextRunAt):`Not scheduled`,detail:F?.nextRunAt?c(F.nextRunAt):void 0})]})})})]}),(0,y.jsxs)(p,{children:[(0,y.jsx)(f,{title:`Local storage`,hint:`safe aggregate facts`}),(0,y.jsx)(w,{loading:D.isLoading,error:D.isError,children:(0,y.jsx)(d,{flush:!0,children:(0,y.jsxs)(b,{children:[(0,y.jsx)(x,{label:`Indexed archives`,value:P?P.length.toLocaleString():`Unavailable`,detail:P?`${a(R)} indexed in total`:void 0}),I&&I.totalBytes!==null&&I.freeBytes!==null?(0,y.jsx)(x,{label:`Filesystem headroom`,value:`${a(I.freeBytes)} free`,tone:I.freeBytes/I.totalBytes<.1?`warn`:`ok`,detail:`${a(I.totalBytes)} volume capacity · host path is not exposed`}):(0,y.jsx)(S,{label:`Filesystem headroom`,reason:`This panel build does not report backup-volume disk capacity.`}),(0,y.jsx)(S,{label:`Database schema`,reason:`SQLite internals and migration state are not exposed by the authenticated API.`})]})})})]})]})]})}export{D as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Diagnostics-CdVImtbq.css b/backend/internal/webdist/dist/assets/Diagnostics-CdVImtbq.css
new file mode 100644
index 0000000..22b9119
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Diagnostics-CdVImtbq.css
@@ -0,0 +1 @@
+.diagnostics-head{align-items:center}.diagnostics-head>div:first-child{min-width:0}.diagnostics-grid{gap:var(--space-4);grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.diagnostics-wide{grid-column:1/-1}.diagnostics-columns{grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.diagnostics-columns>.diagnostic-rows+.diagnostic-rows{border-left:1px solid var(--line)}.diagnostic-rows{margin:0}.diagnostic-row{gap:var(--space-4);border-bottom:1px solid var(--line);grid-template-columns:minmax(130px,.72fr) minmax(0,1.28fr);padding:13px 16px;display:grid}.diagnostic-row:last-child{border-bottom:0}.diagnostic-row dt{color:var(--ink-2);font-size:var(--text-sm)}.diagnostic-row dd{flex-direction:column;align-items:flex-start;gap:4px;min-width:0;display:flex}.diagnostic-value{color:var(--ink);font-family:var(--font-mono);font-size:var(--text-sm);font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.diagnostic-detail{color:var(--ink-3);font-size:var(--text-xs);line-height:1.4}.diagnostics-skeleton{width:100%;height:140px;display:block}@media (width<=980px){.diagnostics-grid,.diagnostics-columns{grid-template-columns:1fr}.diagnostics-columns>.diagnostic-rows+.diagnostic-rows{border-left:0;border-top:1px solid var(--line)}}@media (width<=620px){.diagnostic-row{grid-template-columns:1fr;gap:5px}}
diff --git a/backend/internal/webdist/dist/assets/DropdownMenu-fCf3CXmF.js b/backend/internal/webdist/dist/assets/DropdownMenu-fCf3CXmF.js
new file mode 100644
index 0000000..90a15e3
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/DropdownMenu-fCf3CXmF.js
@@ -0,0 +1 @@
+import{_t as e,ht as t,m as n,q as r}from"./icons-CpYMTu_k.js";import{$ as i,$t as a,A as o,At as s,B as c,Bt as l,C as u,Cn as d,Ct as f,D as p,Dt as m,E as h,En as g,Et as _,F as v,Ft as y,G as b,Gt as x,H as S,Ht as C,I as w,In as T,J as ee,Jt as E,K as D,Kt as O,L as k,Lt as A,M as j,Mt as M,N as te,Nt as N,O as ne,Ot as P,P as F,Pt as I,Q as L,Qt as R,R as z,Rt as B,S as V,Sn as H,St as U,T as W,Tn as G,Tt as re,U as K,V as q,W as ie,X as ae,Xt as oe,Y as se,Yt as ce,Z as le,Zt as ue,_ as de,_n as fe,_t as pe,an as me,at as he,b as ge,bn as J,bt as Y,cn as _e,ct as ve,dn as X,dt as ye,en as be,fn as xe,ft as Se,g as Ce,gn as we,gt as Te,h as Ee,hn as De,ht as Oe,in as ke,it as Ae,j as je,jt as Me,k as Ne,kt as Z,ln as Pe,lt as Fe,mn as Ie,mt as Le,nn as Re,nt as ze,on as Be,ot as Ve,pn as He,pt as Ue,q as We,qt as Ge,rn as Ke,rt as qe,sn as Je,st as Ye,tn as Xe,tt as Ze,un as Qe,ut as $e,v as et,vn as tt,vt as nt,w as rt,wn as it,wt as at,x as ot,xn as st,xt as ct,y as lt,yn as ut,yt as dt,z as ft,zt as pt}from"./index-BpCavHBc.js";var Q=e(t(),1),mt=0;function ht(e,t={}){let{preventScroll:n=!1,sync:r=!1,shouldFocus:i}=t;cancelAnimationFrame(mt);function a(){i&&!i()||e?.focus({preventScroll:n})}if(r)return a(),E;let o=requestAnimationFrame(a);return mt=o,()=>{mt===o&&(cancelAnimationFrame(o),mt=0)}}var gt={inert:new WeakMap,"aria-hidden":new WeakMap},_t=`data-base-ui-inert`,vt={inert:new WeakSet,"aria-hidden":new WeakSet},yt=new WeakMap,bt=0;function xt(e){return vt[e]}function St(e){return e?X(e)?e.host:St(e.parentNode):null}var Ct=(e,t)=>t.map(t=>{if(e.contains(t))return t;let n=St(t);return e.contains(n)?n:null}).filter(e=>e!=null),wt=e=>{let t=new Set;return e.forEach(e=>{let n=e;for(;n&&!t.has(n);)t.add(n),n=n.parentNode}),t},Tt=(e,t,n)=>{let r=[],i=e=>{!e||n.has(e)||Array.from(e.children).forEach(e=>{me(e)!==`script`&&(t.has(e)?i(e):r.push(e))})};return i(e),r};function Et(e,t,n,r,{mark:i=!0}){let a=null;r?a=`inert`:n&&(a=`aria-hidden`);let o=null,s=null,c=Ct(t,e),l=i?Tt(t,wt(c),new Set(c)):[],u=[],d=[];if(a){let e=gt[a],n=xt(a);s=n,o=e;let r=Ct(t,Array.from(t.querySelectorAll(`[aria-live]`))),i=c.concat(r);Tt(t,wt(i),new Set(i)).forEach(t=>{let r=t.getAttribute(a),i=r!==null&&r!==`false`,o=(e.get(t)||0)+1;e.set(t,o),u.push(t),o===1&&i&&n.add(t),i||t.setAttribute(a,a===`inert`?``:`true`)})}return i&&l.forEach(e=>{let t=(yt.get(e)||0)+1;yt.set(e,t),d.push(e),t===1&&e.setAttribute(_t,``)}),bt+=1,()=>{o&&u.forEach(e=>{let t=(o.get(e)||0)-1;o.set(e,t),t||(!s?.has(e)&&a&&e.removeAttribute(a),s?.delete(e))}),i&&d.forEach(e=>{let t=(yt.get(e)||0)-1;yt.set(e,t),t||e.removeAttribute(_t)}),--bt,bt||(gt.inert=new WeakMap,gt[`aria-hidden`]=new WeakMap,vt.inert=new WeakSet,vt[`aria-hidden`]=new WeakSet,yt=new WeakMap)}}function Dt(e,t={}){let{ariaHidden:n=!1,inert:r=!1,mark:i=!0}=t,a=_(e[0]).body;return Et(e,a,n,r,{mark:i})}var $=r();function Ot(e,t){let n=Je(be(e));return e instanceof n.KeyboardEvent?`keyboard`:e instanceof n.FocusEvent?t||`keyboard`:`pointerType`in e?e.pointerType||`keyboard`:`touches`in e?`touch`:e instanceof n.MouseEvent?t||(e.detail===0?`keyboard`:`mouse`):``}var kt=20,At=[];function jt(){At=At.filter(e=>e.deref()?.isConnected)}function Mt(e){jt(),e&&me(e)!==`body`&&(At.push(new WeakRef(e)),At.length>kt&&(At=At.slice(-20)))}function Nt(){return jt(),At[At.length-1]?.deref()}function Pt(e){return e?pe(e)?e:nt(e)[0]||e:null}function Ft(e){if(e.hasAttribute(`tabindex`)&&!e.hasAttribute(`data-tabindex`)||!e.getAttribute(`role`)?.includes(`dialog`))return;let t=ye(e).filter(e=>{let t=e.getAttribute(`data-tabindex`)||``;return pe(e)||e.hasAttribute(`data-tabindex`)&&!t.startsWith(`-`)}),n=e.getAttribute(`tabindex`);t.length===0?n!==`0`&&(e.setAttribute(`tabindex`,`0`),e.setAttribute(`data-tabindex`,`0`)):(n!==`-1`||e.hasAttribute(`data-tabindex`)&&e.getAttribute(`data-tabindex`)!==`-1`)&&(e.setAttribute(`tabindex`,`-1`),e.setAttribute(`data-tabindex`,`-1`))}function It(e){let{context:t,children:n,disabled:r=!1,initialFocus:o=!0,returnFocus:c=!0,restoreFocus:l=!1,modal:u=!0,closeOnFocusOut:f=!0,openInteractionType:p=``,nextFocusableElement:m,previousFocusableElement:h,beforeContentFocusGuardRef:g,externalTree:v,getInsideElements:y}=e,x=`rootStore`in t?t.rootStore:t,S=x.useState(`open`),C=x.useState(`domReferenceElement`),w=x.useState(`floatingElement`),{events:T,dataRef:ee}=x.context,E=Z(()=>ee.current.floatingContext?.nodeId),D=o===!1,O=oe(C)&&D,k=s(o),j=s(c),te=s(p),ne=s(S),F=ae(v),L=i(),z=Q.useRef(!1),B=Q.useRef(!1),V=Q.useRef(!1),H=Q.useRef(null),W=Q.useRef(``),G=Q.useRef(``),K=Q.useRef(null),q=Q.useRef(null),ie=Me(K,g,L?.beforeInsideRef),se=Me(q,L?.afterInsideRef),le=st(),de=st(),he=P(),ge=L!=null,J=ce(w),Y=Z((e=J)=>e?nt(e):[]),X=Z(()=>y?.().filter(e=>e!=null)??[]);Q.useEffect(()=>{if(r||!u)return;function e(e){e.key===`Tab`&&a(J,R(_(J)))&&Y().length===0&&!O&&De(e)}let t=_(J);return N(t,`keydown`,e)},[r,J,u,O,Y]),Q.useEffect(()=>{if(r||!S)return;let e=_(J);function t(){V.current=!1}function n(e){let t=be(e),n=X(),r=a(w,t)||a(C,t)||a(L?.portalNode,t)||n.some(e=>e===t||a(e,t));V.current=!r,G.current=e.pointerType||`keyboard`,t?.closest(`[data-base-ui-click-trigger]`)&&(B.current=!0,de.start(0,()=>{B.current=!1}))}function i(){G.current=`keyboard`}return M(N(e,`pointerdown`,n,!0),N(e,`pointerup`,t,!0),N(e,`pointercancel`,t,!0),N(e,`keydown`,i,!0),t)},[r,w,C,J,S,L,de,X]),Q.useEffect(()=>{if(r||!f)return;let e=_(J);function t(){B.current=!0,de.start(0,()=>{B.current=!1})}function n(e){let t=be(e);pe(t)&&(H.current=t)}function i(t){let n=t.relatedTarget,r=t.currentTarget,i=be(t);u&&n==null&&i!=null&&a(w,i)&&Mt(i),queueMicrotask(()=>{let o=E(),s=x.context.triggerElements,c=X(),d=n?.hasAttribute(ve(`focus-guard`))&&[K.current,q.current,L?.beforeInsideRef.current,L?.afterInsideRef.current,L?.beforeOutsideRef.current,L?.afterOutsideRef.current,b(h),b(m)].includes(n),f=!(a(C,n)||a(w,n)||a(n,w)||a(L?.portalNode,n)||c.some(e=>e===n||a(e,n))||n!=null&&s.hasElement(n)||s.hasMatchingElement(e=>a(e,n))||d||F&&($e(F.nodesRef.current,o).find(e=>a(e.context?.elements.floating,n)||a(e.context?.elements.domReference,n))||Fe(F.nodesRef.current,o).find(e=>[e.context?.elements.floating,ce(e.context?.elements.floating)].includes(n)||e.context?.elements.domReference===n)));if(r===C&&J&&Ft(J),l&&r!==C&&!U(i)&&R(e)===e.body){if(_e(J)&&(J.focus(),l===`popup`)){he.request(()=>{J.focus()});return}let e=Y(),t=H.current,n=(t&&e.includes(t)?t:null)||e[e.length-1]||J;_e(n)&&n.focus()}if(ee.current.insideReactTree){ee.current.insideReactTree=!1;return}(O||!u)&&n&&f&&!B.current&&(O||n!==Nt())&&(z.current=!0,x.setOpen(!1,I(A,t)))})}function o(){V.current||(ee.current.insideReactTree=!0,le.start(0,()=>{ee.current.insideReactTree=!1}))}let s=_e(C)?C:null;if(!(!w&&!s))return M(s&&N(s,`focusout`,i),s&&N(s,`pointerdown`,t),w&&N(w,`focusin`,n),w&&N(w,`focusout`,i),w&&L&&N(w,`focusout`,o,!0))},[r,C,w,J,u,F,L,x,f,l,Y,O,E,ee,le,de,he,m,h,X]),Q.useEffect(()=>{if(r||!w||!S)return;let e=Array.from(L?.portalNode?.querySelectorAll(`[${ve(`portal`)}]`)||[]),t=(F?Fe(F.nodesRef.current,E()):[]).find(e=>oe(e.context?.elements.domReference||null))?.context?.elements.domReference,n=Dt([w,...e,K.current,q.current,L?.beforeOutsideRef.current,L?.afterOutsideRef.current,...X(),t,b(h),b(m),O?C:null].filter(e=>e!=null),{ariaHidden:u||O,mark:!1}),i=Dt([w,...e].filter(e=>e!=null));return()=>{i(),n()}},[S,r,C,w,u,L,O,F,E,m,h,X]),d(()=>{if(!S||r||!_e(J))return;let e=_(J),t=R(e);queueMicrotask(()=>{let n=k.current,r=typeof n==`function`?n(te.current||``):n;if(r===void 0||r===!1||a(J,t))return;let i=null,o=()=>(i??=Y(J),i[0]||J),s;s=r===!0||r===null?o():b(r),s||=o();let c=a(J,R(e));ht(s,{preventScroll:s===J,shouldFocus(){if(!ne.current)return!1;if(c)return!0;let t=R(e);return!(t!==s&&a(J,t))}})})},[r,S,J,Y,k,te,ne]),d(()=>{if(r||!J)return;let e=_(J),t=R(e),n=te.current==null;Mt(t);function i(e){if(e.open||(W.current=Ot(e.nativeEvent,G.current)),e.reason===`trigger-hover`&&e.nativeEvent.type===`mouseleave`&&(z.current=!0),e.reason===`outside-press`)if(e.nested)z.current=!1;else if(He(e.nativeEvent)||Ie(e.nativeEvent))z.current=!1;else{let e=!1;_(J).createElement(`div`).focus({get preventScroll(){return e=!0,!1}}),e?z.current=!1:z.current=!0}}T.on(`openchange`,i);function o(){let e=j.current,r=typeof e==`function`?e(W.current):e;if(r===void 0||r===!1)return null;r===null&&(r=!0);let i=C?.isConnected?C:null,a=t?.isConnected&&me(t)!==`body`?t:null,o=n?a||i:i||a;return o||=Nt()||null,typeof r==`boolean`?o:b(r)||o||null}return()=>{T.off(`openchange`,i);let t=R(e),n=X(),r=a(w,t)||n.some(e=>e===t||a(e,t))||F&&$e(F.nodesRef.current,E(),!1).some(e=>a(e.context?.elements.floating,t)),s=j.current,c=o();queueMicrotask(()=>{let n=Pt(c),i=typeof s!=`boolean`;s&&!z.current&&_e(n)&&(!(!i&&n!==t&&t!==e.body)||r)&&n.focus({preventScroll:!0}),z.current=!1})}},[r,w,J,j,te,T,F,C,E,X]),d(()=>{if(!fe||S||!w)return;let e=R(_(w));!_e(e)||!ue(e)||a(w,e)&&e.blur()},[S,w]),d(()=>{if(!(r||!L))return L.setFocusManagerState({modal:u,closeOnFocusOut:f,open:S,onOpenChange:x.setOpen,domReference:C}),()=>{L.setFocusManagerState(null)}},[r,L,u,S,x,f,C]),d(()=>{if(!(r||!J))return Ft(J),()=>{queueMicrotask(jt)}},[r,J]);let ye=!r&&(!u||!O)&&(ge||u);return(0,$.jsxs)(Q.Fragment,{children:[ye&&(0,$.jsx)(re,{"data-type":`inside`,ref:ie,onFocus:e=>{if(u){let e=Y();ht(e[e.length-1])}else L?.portalNode&&(z.current=!1,Te(e,L.portalNode)?Se(C)?.focus():b(h??L.beforeOutsideRef)?.focus())}}),n,ye&&(0,$.jsx)(re,{"data-type":`inside`,ref:se,onFocus:e=>{u?ht(Y()[0]):L?.portalNode&&(f&&(z.current=!0),Te(e,L.portalNode)?Ue(C)?.focus():b(m??L.afterOutsideRef)?.focus())}})]})}function Lt(e,t={}){let{enabled:n=!0,event:r=`click`,toggle:i=!0,ignoreMouse:a=!1,stickIfOpen:o=!0,touchOpenDelay:s=0,reason:c=x}=t,l=`rootStore`in e?e.rootStore:e,u=l.context.dataRef,d=Q.useRef(void 0),f=P(),p=st(),m=Q.useMemo(()=>{function e(e,t,n,r){let i=I(c,t,n);e&&r===`touch`&&s>0?p.start(s,()=>{l.setOpen(!0,i)}):l.setOpen(e,i)}function t(e,t,n){let r=u.current.openEvent,a=l.select(`domReferenceElement`)!==t;return e&&a||!e||!i?!0:r&&o?!n(r.type):!1}return{onPointerDown(e){d.current=e.pointerType},onMouseDown(n){let i=d.current,o=n.nativeEvent,s=l.select(`open`);if(n.button!==0||r===`click`||xe(i,!0)&&a)return;let c=t(s,n.currentTarget,e=>e===`click`||e===`mousedown`),u=be(o);if(ue(u)){e(c,o,u,i);return}let p=n.currentTarget;f.request(()=>{e(c,o,p,i)})},onClick(n){if(r===`mousedown-only`)return;let i=d.current;if(r===`mousedown`&&i){d.current=void 0;return}xe(i,!0)&&a||e(t(l.select(`open`),n.currentTarget,e=>e===`click`||e===`mousedown`||e===`keydown`||e===`keyup`),n.nativeEvent,n.currentTarget,i)},onKeyDown(){d.current=void 0}}},[u,r,a,c,l,o,i,f,p,s]);return Q.useMemo(()=>n?{reference:m}:Ge,[n,m])}var Rt=`Escape`;function zt(e,t,n){switch(e){case`vertical`:return t;case`horizontal`:return n;default:return t||n}}function Bt(e,t){return zt(t,e===`ArrowUp`||e===`ArrowDown`,e===`ArrowLeft`||e===`ArrowRight`)}function Vt(e,t,n){return zt(t,e===`ArrowDown`,n?e===`ArrowLeft`:e===`ArrowRight`)||e===`Enter`||e===` `||e===``}function Ht(e,t,n){return zt(t,n?e===Re:e===Ke,e===Xe)}function Ut(e,t,n,r){return t===`both`||t===`horizontal`&&r?e===Rt:zt(t,n?e===Ke:e===Re,e===ke)}function Wt(e,t){let{listRef:n,activeIndex:r,onNavigate:i=()=>{},enabled:o=!0,selectedIndex:c=null,allowEscape:u=!1,loopFocus:p=!1,nested:m=!1,rtl:h=!1,virtual:g=!1,focusItemOnOpen:v=`auto`,focusItemOnHover:y=!0,openOnArrowKeyDown:b=!0,disabledIndices:x=void 0,orientation:S=`vertical`,parentOrientation:C,id:w,resetOnPointerLeave:T=!0,externalTree:ee,grid:E}=t,D=E!=null,O=`rootStore`in e?e.rootStore:e,k=O.useState(`open`),j=O.useState(`floatingElement`),M=O.useState(`domReferenceElement`),te=O.context.dataRef,N=ce(j),ne=oe(M),F=s(N),L=se(),z=ae(ee),B=Q.useRef(v),V=Q.useRef(c??-1),H=Q.useRef(null),U=Q.useRef(!0),W=Z(e=>{i(V.current===-1?null:V.current,e)}),G=Q.useRef(!!j),re=Q.useRef(k),K=Q.useRef(!1),q=Q.useRef(!1),ie=Q.useRef(null),le=s(x),ue=s(k),de=s(c),fe=s(T),pe=P(),me=P(),he=Z(()=>{function e(e){g?z?.events.emit(`virtualfocus`,e):ie.current=ht(e,{sync:K.current,preventScroll:!0})}let t=n.current[V.current],r=q.current;t&&e(t),(K.current?e=>e():e=>pe.request(e))(()=>{let i=n.current[V.current]||t;i&&(t||e(i),xe&&(r||!U.current)&&i.scrollIntoView?.({block:`nearest`,inline:`nearest`}))})});d(()=>{te.current.orientation=S},[te,S]),d(()=>{o&&(k&&j?(V.current=c??-1,B.current&&c!=null&&(q.current=!0,W())):G.current&&(V.current=-1,W()))},[o,k,j,c,W]),d(()=>{if(o){if(!k){K.current=!1;return}if(j)if(r==null){if(K.current=!1,de.current!=null)return;if(G.current&&(V.current=-1,he()),(!re.current||!G.current)&&B.current&&(H.current!=null||B.current===!0&&H.current==null)){let e=0,t=()=>{n.current[0]==null?(e<2&&(e?e=>me.request(e):queueMicrotask)(t),e+=1):(V.current=H.current==null||Vt(H.current,S,h)||m?ct(n):Y(n),H.current=null,W())};t()}}else f(n.current,r)||(V.current=r,he(),q.current=!1)}},[o,k,j,r,de,m,n,S,h,W,he,me]),d(()=>{if(!o||j||!z||g||!G.current)return;let e=z.nodesRef.current,t=e.find(e=>e.id===L)?.context?.elements.floating,n=R(_(M??t??null)),r=e.some(e=>e.context&&a(e.context.elements.floating,n));t&&!r&&U.current&&t.focus({preventScroll:!0})},[o,j,M,z,L,g]),d(()=>{re.current=k,G.current=!!j}),d(()=>{k||(H.current=null,B.current=v)},[k,v]);let ge=r!=null,J=Z(e=>{if(!ue.current)return;let t=n.current.indexOf(e.currentTarget);t!==-1&&(V.current!==t||r!==t)&&(V.current=t,W(e))}),ve=Z(()=>C??z?.nodesRef.current.find(e=>e.id===L)?.context?.dataRef?.current.orientation),X=Z(()=>ct(n,le.current)),ye=Z(e=>{if(U.current=!1,K.current=!0,e.which===229||!ue.current&&e.currentTarget===F.current)return;if(m&&Ut(e.key,S,h,D)){Bt(e.key,ve())||De(e),O.setOpen(!1,I(l,e.nativeEvent)),_e(M)&&(g?z?.events.emit(`virtualfocus`,M):M.focus());return}let t=V.current,r=ct(n,x),i=Y(n,x);if(ne||(e.key===`Home`&&(De(e),V.current=r,W(e)),e.key===`End`&&(De(e),V.current=i,W(e))),E!=null){let t=E(e,V.current,n,S,p,h,x,r,i);if(t!=null&&(V.current=t,W(e)),S===`both`)return}if(Bt(e.key,S)){if(De(e),k&&!g&&R(e.currentTarget.ownerDocument)===e.currentTarget){V.current=Vt(e.key,S,h)?r:i,W(e);return}Vt(e.key,S,h)?p?t>=i?u&&t!==n.current.length?V.current=-1:(K.current=!1,V.current=r):V.current=dt(n.current,{startingIndex:t,disabledIndices:x}):V.current=Math.min(i,dt(n.current,{startingIndex:t,disabledIndices:x})):p?t<=r?u&&t!==-1?V.current=n.current.length:(K.current=!1,V.current=i):V.current=dt(n.current,{startingIndex:t,decrement:!0,disabledIndices:x}):V.current=Math.max(r,dt(n.current,{startingIndex:t,decrement:!0,disabledIndices:x})),f(n.current,V.current)&&(V.current=-1),W(e)}}),xe=Q.useMemo(()=>({onFocus(e){K.current=!0,J(e)},onClick:({currentTarget:e})=>e.focus({preventScroll:!0}),onMouseMove(e){K.current=!0,q.current=!1,y&&J(e)},onPointerLeave(e){if(!ue.current||!U.current||e.pointerType===`touch`)return;K.current=!0;let t=e.relatedTarget;if(!(!y||n.current.includes(t))&&fe.current&&(ie.current?.(),ie.current=null,V.current=-1,W(e),!g)){let e=F.current,t=R(_(e));e&&a(e,t)&&e.focus({preventScroll:!0})}}}),[J,ue,F,y,n,W,fe,g]),Se=Q.useMemo(()=>g&&k&&ge&&{"aria-activedescendant":`${w}-${r}`},[g,k,ge,w,r]),Ce=Q.useMemo(()=>({"aria-orientation":S===`both`?void 0:S,...ne?{}:Se,onKeyDown(e){if(e.key===`Tab`&&e.shiftKey&&k&&!g){let t=be(e.nativeEvent);if(t&&!a(F.current,t))return;De(e),O.setOpen(!1,I(A,e.nativeEvent)),_e(M)&&M.focus();return}ye(e)},onPointerMove(){U.current=!0}}),[Se,ye,F,S,ne,O,k,g,M]),we=Q.useMemo(()=>{function e(e){O.setOpen(!0,I(l,e.nativeEvent,e.currentTarget))}function t(e){v===`auto`&&He(e.nativeEvent)&&(B.current=!g)}function n(e){B.current=v,v===`auto`&&Ie(e.nativeEvent)&&(B.current=!0)}return{onKeyDown(t){let n=O.select(`open`);U.current=!1;let r=t.key.startsWith(`Arrow`),i=Ht(t.key,ve(),h),a=Bt(t.key,S),o=(m?i:a)||t.key===`Enter`||t.key.trim()===``;if(g&&n)return ye(t);if(!(!n&&!b&&r)){if(o){let e=Bt(t.key,ve());H.current=m&&e?null:t.key}if(m){i&&(De(t),n?(V.current=X(),W(t)):e(t));return}a&&(de.current!=null&&(V.current=de.current),De(t),!n&&b?e(t):ye(t),n&&W(t))}},onFocus(e){O.select(`open`)&&!g&&(V.current=-1,W(e))},onPointerDown:n,onPointerEnter:n,onMouseDown:t,onClick:t}},[ye,v,X,m,W,O,b,S,ve,h,de,g]),Te=Q.useMemo(()=>({...Se,...we}),[Se,we]);return Q.useMemo(()=>o?{reference:Te,floating:Ce,item:xe,trigger:we}:{},[o,Te,Ce,we,xe])}function Gt(e,t){let{listRef:n,elementsRef:r,activeIndex:i,onMatch:o,disabledIndices:s,onTyping:c,enabled:l=!0,resetMs:u=750,selectedIndex:f=null}=t,p=`rootStore`in e?e.rootStore:e,m=p.useState(`open`),h=st(),g=Q.useRef(``),_=Q.useRef(f??i??-1),v=Q.useRef(null),y=Z(e=>{function t(e){let t=r?.current[e];return!t||U(t)}function a(e){return t(e)?s==null||!at(O,e,s):!1}function l(e,t,n=0){if(e.length===0)return-1;let r=(n%e.length+e.length)%e.length,i=t.toLowerCase();for(let t=0;t0&&e.key===` `&&(De(e),c?.(!0)),g.current.length>0&&g.current[0]!==` `&&l(d,g.current)===-1&&e.key!==` `&&c?.(!1),d==null||e.key.length!==1||e.ctrlKey||e.metaKey||e.altKey)return;m&&e.key!==` `&&(De(e),c?.(!0));let p=g.current===``;p&&(_.current=f??i??-1),d.every((e,t)=>e&&a(t)?e[0]?.toLowerCase()!==e[1]?.toLowerCase():!0)&&g.current===e.key&&(g.current=``,_.current=v.current),g.current+=e.key,h.start(u,()=>{g.current=``,_.current=v.current,c?.(!1)});let y=((p?f??i??-1:_.current)??0)+1,b=l(d,g.current,y);b===-1?e.key!==` `&&(g.current=``,c?.(!1)):(o?.(b),v.current=b)}),b=Z(e=>{let t=e.relatedTarget,n=p.select(`domReferenceElement`),r=p.select(`floatingElement`);a(n,t)||a(r,t)||(h.clear(),g.current=``,_.current=v.current,c?.(!1))});d(()=>{!m&&f!==null||(h.clear(),v.current=null,g.current!==``&&(g.current=``))},[m,f,h]),d(()=>{m&&g.current===``&&(_.current=f??i??-1)},[m,f,i]);let x=Q.useMemo(()=>({onKeyDown:y,onBlur:b}),[y,b]);return Q.useMemo(()=>l?{reference:x,floating:x}:{},[l,x])}function Kt(e){return Ve(19)?e:e?`true`:void 0}var qt=Q.createContext(void 0);function Jt(e){let t=Q.useContext(qt);if(t===void 0&&!e)throw Error(H(33));return t}var Yt=Q.createContext(void 0);function Xt(e){let t=Q.useContext(Yt);if(t===void 0&&!e)throw Error(H(36));return t}var Zt=Q.createContext(void 0);function Qt(e=!0){let t=Q.useContext(Zt);if(t===void 0&&!e)throw Error(H(25));return t}var $t=Q.createContext(void 0);function en(e=!1){let t=Q.useContext($t);if(t===void 0&&!e)throw Error(H(16));return t}function tn(e){let{focusableWhenDisabled:t,disabled:n,composite:r=!1,tabIndex:i=0,isNativeButton:a}=e,o=r&&t!==!1,s=r&&t===!1;return{props:Q.useMemo(()=>{let e={onKeyDown(e){n&&t&&e.key!==`Tab`&&e.preventDefault()}};return r||(e.tabIndex=i,!a&&n&&(e.tabIndex=t?i:-1)),(a&&(t||o)||!a&&n)&&(e[`aria-disabled`]=n),a&&(!t||s)&&(e.disabled=n),e},[r,n,t,o,s,a,i])}}function nn(e={}){let{disabled:t=!1,focusableWhenDisabled:n,tabIndex:r=0,native:i=!0,composite:a}=e,o=Q.useRef(null),s=en(!0),c=a??s!==void 0,{props:l}=tn({focusableWhenDisabled:n,disabled:t,composite:c,tabIndex:r,isNativeButton:i}),u=Q.useCallback(()=>{let e=o.current;rn(e)&&c&&t&&l.disabled===void 0&&e.disabled&&(e.disabled=!1)},[t,l.disabled,c]);return d(u,[u]),{getButtonProps:Q.useCallback((e={})=>{let{onClick:n,onMouseDown:r,onKeyUp:a,onKeyDown:o,onPointerDown:s,...u}=e;return he({onClick(e){if(t){e.preventDefault();return}n?.(e)},onMouseDown(e){t||r?.(e)},onKeyDown(e){if(t||(Ae(e),o?.(e),e.baseUIHandlerPrevented))return;let r=e.target===e.currentTarget,a=e.currentTarget,s=rn(a),l=!i&&an(a),u=r&&(i?s:!l),d=e.key===`Enter`,f=e.key===` `,p=a.getAttribute(`role`),m=p?.startsWith(`menuitem`)||p===`option`||p===`gridcell`;if(r&&c&&f){if(e.defaultPrevented&&m)return;e.preventDefault(),l||i&&s?(a.click(),e.preventBaseUIHandler()):u&&(n?.(e),e.preventBaseUIHandler());return}u&&(!i&&(f||d)&&e.preventDefault(),!i&&d&&n?.(e))},onKeyUp(e){if(!t){if(Ae(e),a?.(e),e.target===e.currentTarget&&i&&c&&rn(e.currentTarget)&&e.key===` `){e.preventDefault();return}e.baseUIHandlerPrevented||e.target===e.currentTarget&&!i&&!c&&e.key===` `&&n?.(e)}},onPointerDown(e){if(t){e.preventDefault();return}s?.(e)}},i?{type:`button`}:{role:`button`},l,u)},[t,l,c,i]),buttonRef:Z(e=>{o.current=e,u()})}}function rn(e){return _e(e)&&e.tagName===`BUTTON`}function an(e){return!!(e?.tagName===`A`&&e?.href)}function on(e){let{closeOnClick:t,highlighted:n,id:r,nodeId:i,store:a,typingRef:o,itemRef:s,itemMetadata:c}=e,{events:l}=a.useState(`floatingTreeRoot`),u=a.useState(`open`),d=Qt(!0),f=d!==void 0;return Q.useMemo(()=>({id:r,role:`menuitem`,tabIndex:u&&n?0:-1,onKeyDown(e){e.key===` `&&o?.current&&e.preventDefault()},onMouseMove(e){i&&l.emit(`itemhover`,{nodeId:i,target:e.currentTarget})},onClick(e){t&&l.emit(`close`,{domEvent:e,reason:pt})},onMouseUp(e){if(d){let t=d.initialCursorPointRef.current;if(d.initialCursorPointRef.current=null,f&&t&&Math.abs(e.clientX-t.x)<=1&&Math.abs(e.clientY-t.y)<=1||f&&!ut&&e.button===2)return}s.current&&a.context.allowMouseUpTriggerRef.current&&(!f||e.button===2)&&(!c||c.type===`regular-item`)&&s.current.click()}}),[t,n,r,l,i,u,a,o,s,d,f,c])}var sn={type:`regular-item`};function cn(e){let{closeOnClick:t,disabled:n=!1,highlighted:r,id:i,store:a,typingRef:o=a.context.typingRef,nativeButton:s,itemMetadata:c,nodeId:l}=e,u=a.useState(`disabled`),d=n||u,f=Q.useRef(null),{getButtonProps:p,buttonRef:m}=nn({disabled:d,focusableWhenDisabled:!0,native:s,composite:!0}),h=on({closeOnClick:t,highlighted:r,id:i,nodeId:l,store:a,typingRef:o,itemRef:f,itemMetadata:c}),g=Q.useCallback(e=>he(h,{onMouseEnter(){c.type===`submenu-trigger`&&c.setActive()}},e,p),[h,p,c]),_=Me(f,m);return Q.useMemo(()=>({getItemProps:g,itemRef:_}),[g,_])}var ln=Q.createContext({register:()=>{},unregister:()=>{},subscribeMapChange:()=>()=>{},elementsRef:{current:[]},nextIndexRef:{current:0}});function un(){return Q.useContext(ln)}var dn=function(e){return e[e.None=0]=`None`,e[e.GuessFromOrder=1]=`GuessFromOrder`,e}({});function fn(e={}){let{label:t,metadata:n,textRef:r,indexGuessBehavior:i,index:a}=e,{register:o,unregister:s,subscribeMapChange:c,elementsRef:l,labelsRef:u,nextIndexRef:f}=un(),p=Q.useRef(-1),[m,h]=Q.useState(a??(i===dn.GuessFromOrder?()=>{if(p.current===-1){let e=f.current;f.current+=1,p.current=e}return p.current}:-1)),g=Q.useRef(null),_=Q.useCallback(e=>{if(g.current=e,m!==-1&&e!==null&&(l.current[m]=e,u)){let n=t!==void 0;u.current[m]=n?t:r?.current?.textContent??e.textContent}},[m,l,u,t,r]);return d(()=>{if(a!=null)return;let e=g.current;if(e)return o(e,n),()=>{s(e)}},[a,o,s,n]),d(()=>{if(a==null)return c(e=>{let t=g.current?e.get(g.current)?.index:null;t!=null&&h(t)})},[a,c,h]),{ref:_,index:m}}var pn=Q.forwardRef(function(e,t){let{render:n,className:r,id:i,label:a,nativeButton:o=!1,disabled:s=!1,closeOnClick:c=!0,style:l,...u}=e,d=fn({label:a}),f=Jt(!0),p=ge(i),{store:m}=Xt(),h=m.useState(`isActive`,d.index),g=m.useState(`itemProps`),{getItemProps:_,itemRef:v}=cn({closeOnClick:c,disabled:s,highlighted:h,id:p,store:m,nativeButton:o,nodeId:f?.context.nodeId,itemMetadata:sn});return qe(`div`,e,{state:{disabled:s,highlighted:h},props:[g,u,_],ref:[v,t,d.ref]})}),mn=Q.forwardRef(function(e,t){let{render:n,className:r,id:i,label:a,closeOnClick:o=!1,style:s,...c}=e,l=Q.useRef(null),u=fn({label:a}),d=Jt(!0)?.context.nodeId,f=ge(i),{store:p}=Xt(),m=p.useState(`isActive`,u.index),h=p.useState(`itemProps`),g=p.context.typingRef,{getButtonProps:_,buttonRef:v}=nn({native:!1,composite:!0}),y=on({closeOnClick:o,highlighted:m,id:f,nodeId:d,store:p,typingRef:g,itemRef:l});function b(e){return he(y,e,_)}return qe(`a`,e,{state:{highlighted:m},props:[h,c,b],ref:[l,v,t,u.ref]})}),hn=Q.createContext(void 0);function gn(e){let t=Q.useContext(hn);if(t===void 0&&!e)throw Error(H(69));return t}var _n=`ArrowUp`,vn=`ArrowDown`,yn=`ArrowLeft`,bn=`ArrowRight`,xn=`Home`,Sn=new Set([yn,bn]),Cn=new Set([_n,vn]),wn=new Set([...Sn,...Cn]),Tn=new Set([...wn,xn,`End`]),En={...ot,...c},Dn=Q.forwardRef(function(e,t){let{render:n,className:r,style:i,finalFocus:a,...o}=e,{store:s}=Xt(),{side:c,align:l}=Jt(),u=gn(!0)!=null,d=s.useState(`open`),f=s.useState(`transitionStatus`),p=s.useState(`popupProps`),m=s.useState(`mounted`),h=s.useState(`instantType`),g=s.useState(`activeTriggerElement`),_=s.useState(`parent`),v=s.useState(`lastOpenChangeReason`),y=s.useState(`rootId`),b=s.useState(`floatingRootContext`),x=s.useState(`floatingTreeRoot`),S=s.useState(`closeDelay`),C=s.useState(`activeTriggerElement`),w=s.useState(`hoverEnabled`),T=s.useState(`disabled`),ee=s.useState(`openMethod`),E=_.type===`context-menu`;z({open:d,ref:s.context.popupRef,onComplete(){d&&s.context.onOpenChangeComplete?.(!0)}}),Q.useEffect(()=>{function e(e){s.setOpen(!1,I(e.reason,e.domEvent))}return x.events.on(`close`,e),()=>{x.events.off(`close`,e)}},[x.events,s]),W(b,{enabled:w&&!T&&!E&&_.type!==`menubar`,closeDelay:S});let D=Q.useCallback(e=>{s.set(`popupElement`,e)},[s]),O={transitionStatus:f,side:c,align:l,open:d,nested:_.type===`menu`,instant:h},k=qe(`div`,e,{state:O,ref:[t,s.context.popupRef,D],stateAttributesMapping:En,props:[p,{onKeyDown(e){u&&Tn.has(e.key)&&e.stopPropagation()}},Ce(f),o,{"data-rootownerid":y}]}),A=_.type===void 0||E;return(g||_.type===`menubar`&&v!==`outside-press`)&&(A=!0),(0,$.jsx)(It,{context:b,openInteractionType:ee,modal:E,disabled:!m,returnFocus:a===void 0?A:a,initialFocus:_.type!==`menu`,restoreFocus:!0,externalTree:_.type===`menubar`?void 0:x,previousFocusableElement:C,nextFocusableElement:_.type===void 0?s.context.triggerFocusTargetRef:void 0,beforeContentFocusGuardRef:_.type===void 0?s.context.beforeContentFocusGuardRef:void 0,children:k})}),On=Q.createContext(void 0);function kn(){let e=Q.useContext(On);if(e===void 0)throw Error(H(32));return e}var An=Q.forwardRef(function(e,t){let{keepMounted:n=!1,...r}=e,{store:i}=Xt();return i.useState(`mounted`)||n?(0,$.jsx)(On.Provider,{value:n,children:(0,$.jsx)(L,{ref:t,...r})}):null});function jn(e){let{children:t,elementsRef:n,labelsRef:r,onMapChange:i}=e,a=Z(i),o=Q.useRef(0),s=g(Nn).current,c=g(Mn).current,[l,u]=Q.useState(0),f=Q.useRef(l),p=Z((e,t)=>{c.set(e,t??null),f.current+=1,u(f.current)}),m=Z(e=>{c.delete(e),f.current+=1,u(f.current)}),h=Q.useMemo(()=>{let e=new Map;return Array.from(c.keys()).filter(e=>e.isConnected).sort(Pn).forEach((t,n)=>{let r=c.get(t)??{};e.set(t,{...r,index:n})}),e},[c,l]);d(()=>{if(typeof MutationObserver!=`function`||h.size===0)return;let e=new MutationObserver(e=>{let t=new Set,n=e=>t.has(e)?t.delete(e):t.add(e);e.forEach(e=>{e.removedNodes.forEach(n),e.addedNodes.forEach(n)}),t.size===0&&(f.current+=1,u(f.current))});return h.forEach((t,n)=>{n.parentElement&&e.observe(n.parentElement,{childList:!0})}),()=>{e.disconnect()}},[h]),d(()=>{f.current===l&&(n.current.length!==h.size&&(n.current.length=h.size),r&&r.current.length!==h.size&&(r.current.length=h.size),o.current=h.size),a(h)},[a,h,n,r,l]),d(()=>()=>{n.current=[]},[n]),d(()=>()=>{r&&(r.current=[])},[r]);let _=Z(e=>(s.add(e),()=>{s.delete(e)}));d(()=>{s.forEach(e=>e(h))},[s,h]);let v=Q.useMemo(()=>({register:p,unregister:m,subscribeMapChange:_,elementsRef:n,labelsRef:r,nextIndexRef:o}),[p,m,_,n,r,o]);return(0,$.jsx)(ln.Provider,{value:v,children:t})}function Mn(){return new Map}function Nn(){return new Set}function Pn(e,t){let n=e.compareDocumentPosition(t);return n&Node.DOCUMENT_POSITION_FOLLOWING||n&Node.DOCUMENT_POSITION_CONTAINED_BY?-1:n&Node.DOCUMENT_POSITION_PRECEDING||n&Node.DOCUMENT_POSITION_CONTAINS?1:0}var Fn=Q.forwardRef(function(e,t){let{cutout:n,...r}=e,i;if(n){let e=n.getBoundingClientRect();i=`polygon(0% 0%,100% 0%,100% 100%,0% 100%,0% 0%,${e.left}px ${e.top}px,${e.left}px ${e.bottom}px,${e.right}px ${e.bottom}px,${e.right}px ${e.top}px,${e.left}px ${e.top}px)`}return(0,$.jsx)(`div`,{ref:t,role:`presentation`,"data-base-ui-inert":``,...r,style:{position:`fixed`,inset:0,userSelect:`none`,WebkitUserSelect:`none`,clipPath:i}})}),In={},Ln={},Rn=``;function zn(e){if(typeof document>`u`)return!1;let t=_(e);return Je(t).innerWidth-t.documentElement.clientWidth>0}function Bn(e){if(!(typeof CSS<`u`&&CSS.supports&&CSS.supports(`scrollbar-gutter`,`stable`))||typeof document>`u`)return!1;let t=_(e),n=t.documentElement,r=t.body,i=Qe(n)?n:r,a=i.style.overflowY,o=n.style.scrollbarGutter;n.style.scrollbarGutter=`stable`,i.style.overflowY=`scroll`;let s=i.offsetWidth;i.style.overflowY=`hidden`;let c=i.offsetWidth;return i.style.overflowY=a,n.style.scrollbarGutter=o,s===c}function Vn(e){let t=_(e),n=t.documentElement,r=t.body,i=Qe(n)?n:r,a={overflowY:i.style.overflowY,overflowX:i.style.overflowX};return Object.assign(i.style,{overflowY:`hidden`,overflowX:`hidden`}),()=>{Object.assign(i.style,a)}}function Hn(e){let t=_(e),n=t.documentElement,r=t.body,i=Je(n),a=0,o=0,s=!1,c=m.create();if(fe&&(i.visualViewport?.scale??1)!==1)return()=>{};function l(){let t=i.getComputedStyle(n),c=i.getComputedStyle(r),l=(t.scrollbarGutter||``).includes(`both-edges`)?`stable both-edges`:`stable`;a=n.scrollTop,o=n.scrollLeft,In={scrollbarGutter:n.style.scrollbarGutter,overflowY:n.style.overflowY,overflowX:n.style.overflowX},Rn=n.style.scrollBehavior,Ln={position:r.style.position,height:r.style.height,width:r.style.width,boxSizing:r.style.boxSizing,overflowY:r.style.overflowY,overflowX:r.style.overflowX,scrollBehavior:r.style.scrollBehavior};let u=n.scrollHeight>n.clientHeight,d=n.scrollWidth>n.clientWidth,f=t.overflowY===`scroll`||c.overflowY===`scroll`,p=t.overflowX===`scroll`||c.overflowX===`scroll`,m=Math.max(0,i.innerWidth-r.clientWidth),h=Math.max(0,i.innerHeight-r.clientHeight),g=parseFloat(c.marginTop)+parseFloat(c.marginBottom),_=parseFloat(c.marginLeft)+parseFloat(c.marginRight),v=Qe(n)?n:r;if(s=Bn(e),s){n.style.scrollbarGutter=l,v.style.overflowY=`hidden`,v.style.overflowX=`hidden`;return}Object.assign(n.style,{scrollbarGutter:l,overflowY:`hidden`,overflowX:`hidden`}),(u||f)&&(n.style.overflowY=`scroll`),(d||p)&&(n.style.overflowX=`scroll`),Object.assign(r.style,{position:`relative`,height:g||h?`calc(100dvh - ${g+h}px)`:`100dvh`,width:_||m?`calc(100vw - ${_+m}px)`:`100vw`,boxSizing:`border-box`,overflow:`hidden`,scrollBehavior:`unset`}),r.scrollTop=a,r.scrollLeft=o,n.setAttribute(`data-base-ui-scroll-locked`,``),n.style.scrollBehavior=`unset`}function u(){Object.assign(n.style,In),Object.assign(r.style,Ln),s||(n.scrollTop=a,n.scrollLeft=o,n.removeAttribute(`data-base-ui-scroll-locked`),n.style.scrollBehavior=Rn)}function d(){u(),c.request(l)}l();let f=N(i,`resize`,d);return()=>{c.cancel(),u(),typeof i.removeEventListener==`function`&&f()}}var Un=new class{lockCount=0;restore=null;timeoutLock=J.create();timeoutUnlock=J.create();acquire(e){return this.lockCount+=1,this.lockCount===1&&this.restore===null&&this.timeoutLock.start(0,()=>this.lock(e)),this.release}release=()=>{--this.lockCount,this.lockCount===0&&this.restore&&this.timeoutUnlock.start(0,this.unlock)};unlock=()=>{this.lockCount===0&&this.restore&&(this.restore?.(),this.restore=null)};lock(e){if(this.lockCount===0||this.restore!==null)return;let t=_(e).documentElement,n=Je(t).getComputedStyle(t).overflowY;if(n===`hidden`||n===`clip`){this.restore=E;return}let r=tt||!zn(e);this.restore=r?Vn(e):Hn(e)}};function Wn(e=!0,t=null){d(()=>{if(e)return Un.acquire(t)},[e,t])}var Gn=20;function Kn(e,t,n,r){let[i,a]=Q.useState(!1);d(()=>{if(!e||!t||n==null){a(!1);return}let r=_(n).documentElement.clientWidth,i=n.offsetWidth;a(r>0&&i>0&&i>=r-Gn)},[e,t,n]),Wn(e&&(!t||i),r)}var qn=Q.forwardRef(function(e,t){let{anchor:n,positionMethod:r=`absolute`,className:i,render:a,side:o,align:s,sideOffset:c=0,alignOffset:l=0,collisionBoundary:u=`clipping-ancestors`,collisionPadding:f=5,arrowPadding:p=5,sticky:m=!1,disableAnchorTracking:h=!1,collisionAvoidance:g=Ze,style:_,...v}=e,{store:y}=Xt(),b=kn(),x=Qt(!0),S=y.useState(`parent`),w=y.useState(`floatingRootContext`),T=y.useState(`floatingTreeRoot`),ee=y.useState(`mounted`),E=y.useState(`open`),O=y.useState(`modal`),k=y.useState(`openMethod`),A=y.useState(`activeTriggerElement`),j=y.useState(`transitionStatus`),M=y.useState(`positionerElement`),te=y.useState(`instantType`),N=y.useState(`hasViewport`),ne=y.useState(`lastOpenChangeReason`),P=y.useState(`floatingNodeId`),F=y.useState(`floatingParentNodeId`),L=w.useState(`domReferenceElement`),R=Q.useRef(null),z=ft(M,!1,!1),B=n,V=c,H=l,U=s,W=g;S.type===`context-menu`&&(B=n??S.context?.anchor,U??=`start`,!o&&U!==`center`&&(H=e.alignOffset??2,V=e.sideOffset??-5));let G=o,re=U;S.type===`menu`?(G??=`inline-end`,re??=`start`,W=e.collisionAvoidance??ze):S.type===`menubar`&&(G??=S.context.orientation===`vertical`?`inline-end`:`bottom`,re??=`start`);let K=S.type===`context-menu`,q=de({anchor:B,floatingRootContext:w,positionMethod:x?`fixed`:r,mounted:ee,side:G,sideOffset:V,align:re,alignOffset:H,arrowPadding:K?0:p,collisionBoundary:u,collisionPadding:f,sticky:m,nodeId:P,keepMounted:b,disableAnchorTracking:h,collisionAvoidance:W,shiftCrossAxis:K&&!(`side`in W&&W.side===`flip`),externalTree:T,adaptiveOrigin:N?et:void 0});Q.useEffect(()=>{function e(e){e.open&&(e.parentNodeId===P&&y.set(`hoverEnabled`,!1),e.nodeId!==P&&e.parentNodeId===y.select(`floatingParentNodeId`)&&y.setOpen(!1,I(C)))}return T.events.on(`menuopenchange`,e),()=>{T.events.off(`menuopenchange`,e)}},[y,T.events,P]),Q.useEffect(()=>{if(y.select(`floatingParentNodeId`)==null)return;function e(e){if(e.open||e.nodeId!==y.select(`floatingParentNodeId`))return;let t=e.reason??`sibling-open`;y.setOpen(!1,I(t))}return T.events.on(`menuopenchange`,e),()=>{T.events.off(`menuopenchange`,e)}},[T.events,y]);let ie=st();Q.useEffect(()=>{E||ie.clear()},[E,ie]),Q.useEffect(()=>{function e(e){if(!(!E||e.nodeId!==y.select(`floatingParentNodeId`)))if(e.target&&A&&A!==e.target){let e=y.select(`closeDelay`);e>0?ie.isStarted()||ie.start(e,()=>{y.setOpen(!1,I(C))}):y.setOpen(!1,I(C))}else ie.clear()}return T.events.on(`itemhover`,e),()=>{T.events.off(`itemhover`,e)}},[T.events,E,A,y,ie]),Q.useEffect(()=>{let e={open:E,nodeId:P,parentNodeId:F,reason:y.select(`lastOpenChangeReason`)};T.events.emit(`menuopenchange`,e)},[T.events,E,y,P,F]),d(()=>{let e=L,t=R.current;if(e&&(R.current=e),t&&e&&e!==t){y.set(`instantType`,void 0);let e=new AbortController;return z(()=>{y.set(`instantType`,`trigger-change`)},e.signal),()=>{e.abort()}}},[L,z,y]);let ae={open:E,side:q.side,align:q.align,anchorHidden:q.anchorHidden,nested:S.type===`menu`,instant:te},oe=S.type===`menubar`&&S.context.modal;Kn(E&&(oe||O&&ne!==`trigger-hover`),k===`touch`,M,A);let se=Ee(e,ae,{styles:q.positionerStyles,transitionStatus:j,props:v,refs:[t,y.useStateSetter(`positionerElement`)],hidden:!ee,inert:!E}),ce=ee&&S.type!==`menu`&&(S.type!==`menubar`&&O&&ne!==`trigger-hover`||S.type===`menubar`&&S.context.modal),le=null;return S.type===`menubar`?le=S.context.contentElement:S.type===void 0&&(le=A),(0,$.jsxs)(qt.Provider,{value:q,children:[ce&&(0,$.jsx)(Fn,{ref:S.type===`context-menu`||S.type===`nested-context-menu`?S.context.internalBackdropRef:null,inert:Kt(!E),cutout:le}),(0,$.jsx)(D,{id:P,children:(0,$.jsx)(jn,{elementsRef:y.context.itemDomElements,labelsRef:y.context.itemLabels,children:se})})]})}),Jn=Q.createContext(null);function Yn(e){let t=Q.useContext(Jn);if(t===null&&!e)throw Error(H(5));return t}function Xn(e){let t=Q.useRef(``),n=Q.useCallback(n=>{n.defaultPrevented||(t.current=n.pointerType,e(n,n.pointerType))},[e]);return{onClick:Q.useCallback(n=>{if(n.detail===0){e(n,`keyboard`);return}`pointerType`in n?e(n,n.pointerType):e(n,t.current),t.current=``},[e]),onPointerDown:n}}function Zn(e,t){let n=Q.useRef(e),r=Z(t);d(()=>{n.current!==e&&r(n.current)},[e,r]),d(()=>{n.current=e},[e])}function Qn(e,t){let{onClick:n,onPointerDown:r}=Xn(Z((n,r)=>{(typeof e==`function`?e():e)||t(r||(tt?`touch`:``))}));return Q.useMemo(()=>({onClick:n,onPointerDown:r}),[n,r])}function $n(e){let[t,n]=Q.useState(null),r=Qn(e,n);return Zn(e,t=>{t&&!e&&n(null)}),Q.useMemo(()=>({openMethod:t,triggerProps:r}),[t,r])}var er={...ne,disabled:K(e=>e.parent.type===`menubar`&&e.parent.context.disabled||e.disabled),modal:K(e=>(e.parent.type===void 0||e.parent.type===`context-menu`)&&(e.modal??!0)),openMethod:K(e=>e.openMethod),allowMouseEnter:K(e=>e.allowMouseEnter),highlightItemOnHover:K(e=>e.highlightItemOnHover),stickIfOpen:K(e=>e.stickIfOpen),parent:K(e=>e.parent),rootId:K(e=>e.parent.type===`menu`?e.parent.store.select(`rootId`):e.parent.type===void 0?e.rootId:e.parent.context.rootId),activeIndex:K(e=>e.activeIndex),isActive:K((e,t)=>e.activeIndex===t),hoverEnabled:K(e=>e.hoverEnabled),instantType:K(e=>e.instantType),lastOpenChangeReason:K(e=>e.openChangeReason),floatingTreeRoot:K(e=>e.parent.type===`menu`?e.parent.store.select(`floatingTreeRoot`):e.floatingTreeRoot),floatingNodeId:K(e=>e.floatingNodeId),floatingParentNodeId:K(e=>e.floatingParentNodeId),itemProps:K(e=>e.itemProps),closeDelay:K(e=>e.closeDelay),hasViewport:K(e=>e.hasViewport),keyboardEventRelay:K(e=>{if(e.keyboardEventRelay)return e.keyboardEventRelay;if(e.parent.type===`menu`)return e.parent.store.select(`keyboardEventRelay`)})},tr=class e extends S{constructor(e){super({...nr(),...e},{positionerRef:Q.createRef(),popupRef:Q.createRef(),typingRef:{current:!1},itemDomElements:{current:[]},itemLabels:{current:[]},allowMouseUpTriggerRef:{current:!1},triggerFocusTargetRef:Q.createRef(),beforeContentFocusGuardRef:Q.createRef(),onOpenChangeComplete:void 0,triggerElements:new Ne},er),this.unsubscribeParentListener=this.observe(`parent`,e=>{if(this.unsubscribeParentListener?.(),e.type===`menu`){let t=e.store.select(`rootId`),n=e.store.select(`floatingTreeRoot`),r=e.store.select(`keyboardEventRelay`);this.unsubscribeParentListener=e.store.subscribe(()=>{let i=e.store.select(`rootId`),a=e.store.select(`floatingTreeRoot`),o=e.store.select(`keyboardEventRelay`);(t!==i||n!==a||r!==o)&&(t=i,n=a,r=o,this.notifyAll())}),this.context.allowMouseUpTriggerRef=e.store.context.allowMouseUpTriggerRef;return}e.type!==void 0&&(this.context.allowMouseUpTriggerRef=e.context.allowMouseUpTriggerRef),this.unsubscribeParentListener=null})}setOpen(e,t){this.state.floatingRootContext.context.events.emit(`setOpen`,{open:e,eventDetails:t})}static useStore(t,n){let r=g(()=>new e(n)).current;return t??r}unsubscribeParentListener=null};function nr(){return{...p(),disabled:!1,modal:!0,openMethod:null,allowMouseEnter:!1,highlightItemOnHover:!0,stickIfOpen:!0,parent:{type:void 0},rootId:void 0,activeIndex:null,hoverEnabled:!0,instantType:void 0,openChangeReason:null,floatingTreeRoot:new le,floatingNodeId:void 0,floatingParentNodeId:null,itemProps:Ge,keyboardEventRelay:void 0,closeDelay:0,hasViewport:!1}}var rr=Q.createContext(void 0);function ir(){return Q.useContext(rr)}var ar=it(function(e){let{children:t,open:n,onOpenChange:r,onOpenChangeComplete:i,defaultOpen:a=!1,disabled:s=!1,modal:c,loopFocus:l=!0,orientation:u=`vertical`,actionsRef:f,closeParentOnEsc:p=!1,handle:m,triggerId:h,defaultTriggerId:g=null,highlightItemOnHover:_=!0}=e,y=Qt(!0),b=Xt(!0),x=Yn(!0),S=ir(),C=Q.useMemo(()=>S&&b?{type:`menu`,store:b.store}:x?{type:`menubar`,context:x}:y&&!b?{type:`context-menu`,context:y}:{type:void 0},[y,b,x,S]),T=tr.useStore(m?.store,{open:a,openProp:n,activeTriggerId:g,triggerIdProp:h,parent:C});F(T,n,a,g),T.useControlledProp(`openProp`,n),T.useControlledProp(`triggerIdProp`,h),T.useContextCallback(`onOpenChangeComplete`,i);let E=Ye(),D=Ye(),k=T.useState(`floatingTreeRoot`),A=ee(k),M=se(),N=T.useState(`open`),ne=T.useState(`activeTriggerElement`),P=T.useState(`positionerElement`),L=T.useState(`hoverEnabled`),R=T.useState(`disabled`),z=T.useState(`lastOpenChangeReason`),V=T.useState(`parent`),H=T.useState(`activeIndex`),U=T.useState(`payload`),W=T.useState(`floatingParentNodeId`),G=Q.useRef(null),re=Q.useRef(V.type!==`context-menu`),K=st(),ae=Q.useRef(!0),oe=st(),ce=W!=null,{openMethod:le,triggerProps:ue}=$n(N);T.useSyncedValues({disabled:s,highlightItemOnHover:_,modal:V.type===void 0?c:void 0,openMethod:le,rootId:E}),te(T);let{forceUnmount:de}=v(N,T,()=>{T.update({allowMouseEnter:!1,stickIfOpen:!0})});d(()=>{y&&!b?T.update({parent:{type:`context-menu`,context:y},floatingNodeId:A,floatingParentNodeId:M}):b&&T.update({floatingNodeId:A,floatingParentNodeId:M})},[y,b,A,M,T]),Q.useEffect(()=>{if(N||(G.current=null),V.type===`context-menu`){if(!N){K.clear(),re.current=!1;return}K.start(500,()=>{re.current=!0})}},[K,N,V.type]),d(()=>{!N&&!L&&T.set(`hoverEnabled`,!0)},[N,L,T]);let fe=Z((e,t)=>{let n=t.reason;if(N===e&&t.trigger===ne&&z===n)return;let i=je(t);if(!e&&t.trigger==null&&(t.trigger=ne??void 0),r?.(e,t),t.isCanceled)return;T.state.floatingRootContext.dispatchOpenChange(e,t);let a=t.event;if(e===!1&&a?.type===`click`&&a.pointerType===`touch`&&!ae.current)return;e&&n===`trigger-focus`?(ae.current=!1,oe.start(300,()=>{ae.current=!0})):(ae.current=!0,oe.clear());let o=(n===`trigger-press`||n===`item-press`)&&a.detail===0&&a?.isTrusted,s=!e&&(n===`escape-key`||n==null),c={open:e,openChangeReason:n};G.current=t.event??null,j(c,e,t.trigger,i()),T.update(c),V.type===`menubar`&&(n===`trigger-focus`||n===`focus-out`||n===`trigger-hover`||n===`list-navigation`||n===`sibling-open`)?T.set(`instantType`,`group`):o||s?T.set(`instantType`,o?`click`:`dismiss`):T.set(`instantType`,void 0)}),pe=q({popupStore:T,floatingId:D,nested:M!=null,onOpenChange:fe}),me=pe.context.events;Q.useEffect(()=>{let e=({open:e,eventDetails:t})=>fe(e,t);return me.on(`setOpen`,e),()=>{me?.off(`setOpen`,e)}},[me,fe]);let ge=Q.useCallback(()=>{T.setOpen(!1,I(B))},[T]);Q.useImperativeHandle(f,()=>({unmount:de,close:ge}),[de,ge]);let J;V.type===`context-menu`&&(J=V.context),Q.useImperativeHandle(J?.positionerRef,()=>P,[P]),Q.useImperativeHandle(J?.actionsRef,()=>({setOpen:fe}),[fe]);let Y=ie(pe,{enabled:!R,bubbles:{escapeKey:p&&V.type===`menu`},outsidePress(){return V.type!==`context-menu`||G.current?.type===`contextmenu`||re.current},externalTree:ce?k:void 0}),_e=lt(),ve=Q.useCallback(e=>{T.select(`activeIndex`)!==e&&T.set(`activeIndex`,e)},[T]),X=Wt(pe,{enabled:!R,listRef:T.context.itemDomElements,activeIndex:H,nested:V.type!==void 0,loopFocus:l,orientation:u,parentOrientation:V.type===`menubar`?V.context.orientation:void 0,rtl:_e===`rtl`,disabledIndices:O,onNavigate:ve,openOnArrowKeyDown:V.type!==`context-menu`,externalTree:ce?k:void 0,focusItemOnHover:_}),ye=Q.useCallback(e=>{T.context.typingRef.current=e},[T]),be=Gt(pe,{enabled:!R,listRef:T.context.itemLabels,elementsRef:T.context.itemDomElements,activeIndex:H,resetMs:500,onMatch:e=>{N&&e!==H&&T.set(`activeIndex`,e)},onTyping:ye}),xe=Q.useMemo(()=>{let e=he(be.reference,X.reference,Y.reference,{onMouseMove(){T.set(`allowMouseEnter`,!0)}},ue);return e[`aria-haspopup`]=`menu`,e[`aria-expanded`]=N,e},[T,be.reference,X.reference,Y.reference,ue,N]),Se=Q.useMemo(()=>{let e=he(X.trigger,Y.trigger,ue);return e[`aria-haspopup`]=`menu`,e[`aria-expanded`]=!1,e},[X.trigger,Y.trigger,ue]),Ce=Q.useMemo(()=>he(o,{id:D,role:`menu`,"aria-labelledby":ne?.id,onMouseMove(){T.set(`allowMouseEnter`,!0),V.type===`menu`&&T.set(`hoverEnabled`,!1)},onClick(){T.select(`hoverEnabled`)&&T.set(`hoverEnabled`,!1)},onKeyDown(e){let t=T.select(`keyboardEventRelay`);t&&!e.isPropagationStopped()&&t(e)}},be.floating,X.floating,Y.floating),[ne,D,V.type,T,be.floating,X.floating,Y.floating]),we=X.item??Ge;w(T,{floatingRootContext:pe,activeTriggerProps:xe,inactiveTriggerProps:Se,popupProps:Ce,itemProps:we});let Te=Q.useMemo(()=>({store:T,parent:C}),[T,C]),Ee=(0,$.jsx)(Yt.Provider,{value:Te,children:typeof t==`function`?t({payload:U}):t});return V.type===void 0||V.type===`context-menu`?(0,$.jsx)(We,{externalTree:k,children:Ee}):Ee});function or(e){let t=e.getBoundingClientRect(),n=Je(e);if(we)return t;let r=n.getComputedStyle(e,`::before`),i=n.getComputedStyle(e,`::after`);if(r.content===`none`&&i.content===`none`)return t;let a=parseFloat(r.width)||0,o=parseFloat(r.height)||0,s=parseFloat(i.width)||0,c=parseFloat(i.height)||0,l=Math.max(t.width,a,s),u=Math.max(t.height,o,c),d=l-t.width,f=u-t.height;return{left:t.left-d/2,right:t.right+d/2,top:t.top-f/2,bottom:t.bottom+f/2}}function sr(e={}){let{highlightItemOnHover:t,highlightedIndex:n,onHighlightedIndexChange:r}=en(),{ref:i,index:a}=fn(e),o=n===a,s=Q.useRef(null),c=Me(i,s);return{compositeProps:{tabIndex:o?0:-1,onFocus(){r(a)},onMouseMove(){let e=s.current;if(!t||!e)return;let n=e.hasAttribute(`disabled`)||e.ariaDisabled===`true`;!o&&!n&&e.focus()}},compositeRef:c,index:a}}function cr(e){let{render:t,className:n,style:r,state:i=Ge,props:a=O,refs:o=O,metadata:s,stateAttributesMapping:c,tag:l=`div`,...u}=e,{compositeProps:d,compositeRef:f}=sr({metadata:s});return qe(l,e,{state:i,ref:[...o,f],props:[d,...a,u],stateAttributesMapping:c})}function lr(e){if(_e(e)&&e.hasAttribute(`data-rootownerid`))return e.getAttribute(`data-rootownerid`)??void 0;if(!Pe(e))return lr(Be(e))}var ur=e(T(),1);function dr(e,t){let n=Q.useRef(null);function r(t){ur.flushSync(()=>{e.setOpen(!1,I(A,t.nativeEvent,t.currentTarget))}),Oe(n.current)?.focus()}function i(n){let r=e.select(`positionerElement`);if(r&&Te(n,r))e.context.beforeContentFocusGuardRef.current?.focus();else{ur.flushSync(()=>{e.setOpen(!1,I(A,n.nativeEvent,n.currentTarget))});let i=Le(e.context.triggerFocusTargetRef.current||t.current);for(;i!==null&&a(r,i);){let e=i;if(i=Se(i),i===e)break}i?.focus()}}return{preFocusGuardRef:n,handlePreFocusGuardFocus:r,handleFocusTargetFocus:i}}function fr(e){let{enabled:t=!0,mouseDownAction:n,open:r}=e,i=Q.useRef(!1);return Q.useMemo(()=>t?{onMouseDown:e=>{(n===`open`&&!r||n===`close`&&r)&&(i.current=!0,_(e.currentTarget).addEventListener(`click`,()=>{i.current=!1},{once:!0}))},onClick:e=>{i.current&&(i.current=!1,e.preventBaseUIHandler())}}:Ge,[t,n,r])}var pr=2,mr=G(function(e,t){let{render:n,className:r,style:i,disabled:o=!1,nativeButton:s=!0,id:c,openOnHover:l,delay:d=100,closeDelay:f=0,handle:p,payload:m,...g}=e,v=Xt(!0),b=p?.store??v?.store;if(!b)throw Error(H(85));let x=ge(c),S=b.useState(`isTriggerActive`,x),C=b.useState(`floatingRootContext`),w=b.useState(`isOpenedByTrigger`,x),T=b.useState(`triggerPopupId`,x),E=Q.useRef(null),D=gr(),O=en(!0),A=ae(),j=Q.useMemo(()=>A??new le,[A]),M=ee(j),te=se(),{registerTrigger:N,isMountedByThisTrigger:ne}=k(x,E,b,{payload:m,closeDelay:f,parent:D,floatingTreeRoot:j,floatingNodeId:M,floatingParentNodeId:te,keyboardEventRelay:O?.relayKeyboardEvent}),P=D.type===`menubar`,F=b.useState(`disabled`),I=o||F||P&&D.context.disabled,{getButtonProps:L,buttonRef:R}=nn({disabled:I,native:s});Q.useEffect(()=>{!w&&D.type===void 0&&(b.context.allowMouseUpTriggerRef.current=!1)},[b,w,D.type]);let z=Q.useRef(null),B=st(),U=Z(e=>{if(!z.current)return;B.clear(),b.context.allowMouseUpTriggerRef.current=!1;let t=e.target;if(a(z.current,t)||a(b.select(`positionerElement`),t)||t===z.current||t!=null&&lr(t)===b.select(`rootId`))return;let n=or(z.current);e.clientX>=n.left-pr&&e.clientX<=n.right+pr&&e.clientY>=n.top-pr&&e.clientY<=n.bottom+pr||j.events.emit(`close`,{domEvent:e,reason:y})});Q.useEffect(()=>{w&&b.select(`lastOpenChangeReason`)===`trigger-hover`&&_(z.current).addEventListener(`mouseup`,U,{once:!0})},[w,U,b]);let W=P&&D.context.hasSubmenuOpen,G=rt(C,{enabled:(l??W)&&!I&&D.type!==`context-menu`&&(!P||W&&!ne),handleClose:u({blockPointerEvents:!P}),mouseOnly:!0,move:!1,restMs:D.type===void 0?d:void 0,delay:{close:f},triggerElementRef:E,externalTree:j,isActiveTrigger:S,isClosing:()=>b.select(`transitionStatus`)===`ending`}),K=hr(w,b.select(`lastOpenChangeReason`)),q=Lt(C,{enabled:!I&&D.type!==`context-menu`,event:w&&P?`click`:`mousedown`,toggle:!0,ignoreMouse:!1,stickIfOpen:D.type===void 0&&K}),ie=h(C,{enabled:!I&&W}),oe=fr({open:w,enabled:P,mouseDownAction:`open`}),ce=Q.useMemo(()=>he(ie.reference,q.reference),[ie.reference,q.reference]),ue=b.useState(`triggerProps`,ne),{preFocusGuardRef:de,handlePreFocusGuardFocus:fe,handleFocusTargetFocus:pe}=dr(b,E),me={disabled:I,open:w},J=[z,t,R,N,E],Y=[ce,G??Ge,ue,{"aria-haspopup":`menu`,"aria-controls":T,id:x,onMouseDown:e=>{b.select(`open`)||(B.start(200,()=>{b.context.allowMouseUpTriggerRef.current=!0}),_(e.currentTarget).addEventListener(`mouseup`,U,{once:!0}))}},P?{role:`menuitem`}:{},oe,g,L],_e=qe(`button`,e,{enabled:!P,stateAttributesMapping:V,state:me,ref:J,props:Y});return P?(0,$.jsx)(cr,{tag:`button`,render:n,className:r,style:i,state:me,refs:J,props:Y,stateAttributesMapping:V}):w?(0,$.jsxs)(Q.Fragment,{children:[(0,$.jsx)(re,{ref:de,onFocus:fe},`${x}-pre-focus-guard`),(0,$.jsx)(Q.Fragment,{children:_e},x),(0,$.jsx)(re,{ref:b.context.triggerFocusTargetRef,onFocus:pe},`${x}-post-focus-guard`)]}):(0,$.jsx)(Q.Fragment,{children:_e},x)});function hr(e,t){let n=st(),[r,i]=Q.useState(!1);return d(()=>{e&&t===`trigger-hover`?(i(!0),n.start(500,()=>{i(!1)})):e||(n.clear(),i(!1))},[e,t,n]),r}function gr(){let e=Qt(!0),t=Xt(!0),n=Yn(!0);return Q.useMemo(()=>n?{type:`menubar`,context:n}:e&&!t?{type:`context-menu`,context:e}:{type:void 0},[e,t,n])}function _r({children:e,trigger:t,triggerLabel:r=`More actions`,triggerClassName:i=`btn btn-sm btn-ghost row-kebab`,align:a=`end`,side:o=`bottom`}){return(0,$.jsxs)(ar,{children:[(0,$.jsx)(mr,{type:`button`,className:i,"aria-label":r,children:t??(0,$.jsx)(n,{})}),(0,$.jsx)(An,{children:(0,$.jsx)(qn,{side:o,align:a,sideOffset:6,className:`menu-positioner`,children:(0,$.jsx)(Dn,{className:`menu-popup`,children:e})})})]})}function vr({danger:e=!1,className:t=``,...n}){return(0,$.jsx)(pn,{className:[`menu-item`,e?`menu-item-danger`:``,t].filter(Boolean).join(` `),...n})}function yr({danger:e=!1,className:t=``,...n}){return(0,$.jsx)(mn,{className:[`menu-item`,e?`menu-item-danger`:``,t].filter(Boolean).join(` `),...n})}export{vr as n,yr as r,_r as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/EmptyState-DTSMkv56.js b/backend/internal/webdist/dist/assets/EmptyState-DTSMkv56.js
new file mode 100644
index 0000000..188cf69
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/EmptyState-DTSMkv56.js
@@ -0,0 +1 @@
+import{q as e}from"./icons-CpYMTu_k.js";var t=e();function n({icon:e,title:n,description:r,children:i}){return(0,t.jsxs)(`div`,{className:`empty`,children:[e,(0,t.jsx)(`h3`,{children:n}),r&&(0,t.jsx)(`p`,{children:r}),i]})}export{n as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/EventMessage-UG0hgRVA.js b/backend/internal/webdist/dist/assets/EventMessage-UG0hgRVA.js
new file mode 100644
index 0000000..9812728
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/EventMessage-UG0hgRVA.js
@@ -0,0 +1 @@
+import{_t as e,ht as t,q as n}from"./icons-CpYMTu_k.js";var r=e(t(),1),i=n();function a({text:e}){let t=e.split(/(\*\*[^*]+\*\*|`[^`]+`|~[^~]+~)/g).filter(e=>e!==``);return(0,i.jsx)(i.Fragment,{children:t.map((e,t)=>e.startsWith(`**`)&&e.endsWith(`**`)?(0,i.jsx)(`strong`,{children:e.slice(2,-2)},t):e.startsWith("`")&&e.endsWith("`")?(0,i.jsx)(`span`,{className:`num`,children:e.slice(1,-1)},t):e.startsWith(`~`)&&e.endsWith(`~`)?(0,i.jsx)(`span`,{className:`num`,style:{color:`var(--ink-3)`},children:e.slice(1,-1)},t):(0,i.jsx)(r.Fragment,{children:e},t))})}export{a as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Events-DSAko0ZN.js b/backend/internal/webdist/dist/assets/Events-DSAko0ZN.js
new file mode 100644
index 0000000..8358112
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Events-DSAko0ZN.js
@@ -0,0 +1 @@
+import{U as e,_t as t,ht as n,j as r,q as i}from"./icons-CpYMTu_k.js";import{d as a,i as o,o as s}from"./index-BpCavHBc.js";import{t as c}from"./Banner-DSN1nEJn.js";import{n as l,t as u}from"./Card-D55CMzdw.js";import{t as d}from"./EmptyState-DTSMkv56.js";import{t as f}from"./EventMessage-UG0hgRVA.js";var p=t(n(),1),m=[{id:`all`,label:`All events`,description:`Combined timeline`,kinds:[`join`,`leave`,`backup`,`panel`,`config`,`system`]},{id:`player`,label:`Player activity`,description:`Joins and leaves`,kinds:[`join`,`leave`]},{id:`operations`,label:`Operations & audit`,description:`Backups and panel changes`,kinds:[`backup`,`panel`,`config`]},{id:`health`,label:`Health incidents`,description:`System health transitions`,kinds:[`system`]}],h=new Map([[`join`,`player`],[`leave`,`player`],[`backup`,`operations`],[`panel`,`operations`],[`config`,`operations`],[`system`,`health`]]);function g(e){return h.get(e)??`all`}function _(e){return m.find(t=>t.id===e)?.kinds??[]}function v(e){let t={all:e.length,player:0,operations:0,health:0};for(let n of e){let e=g(n.kind);e!==`all`&&(t[e]+=1)}return t}function y(e,t,n,r){let i=r.trim().toLocaleLowerCase();return e.filter(e=>t!==`all`&&g(e.kind)!==t||n!==`all`&&e.kind!==n?!1:!i||e.message.toLocaleLowerCase().includes(i)||e.kind.includes(i))}var b=i(),x=25,S=500,C={all:`All kinds`,join:`Joins`,leave:`Leaves`,backup:`Backups`,system:`System`,panel:`Panel audit`,config:`Configuration`};function w(e){return e===`join`?`ok`:e===`system`||e===`config`?`warn`:e===`panel`?`danger`:`idle`}function T(){let[t,n]=(0,p.useState)(`all`),[i,h]=(0,p.useState)(`all`),[g,T]=(0,p.useState)(``),[E,D]=(0,p.useState)(0),O=e({queryKey:[`events`,S],queryFn:()=>r.events.list(S),refetchInterval:3e4}),k=O.data??[],A=v(k),j=y(k,t,i,g),M=_(t),N=Math.max(1,Math.ceil(j.length/x)),P=Math.min(E,N-1),F=j.slice(P*x,(P+1)*x);function I(e){n(e),h(`all`),D(0)}function L(e){h(e),D(0)}return(0,b.jsxs)(`main`,{className:`content`,children:[(0,b.jsxs)(`div`,{className:`page-head`,children:[(0,b.jsx)(`h1`,{children:`Events & audit`}),(0,b.jsx)(`span`,{className:`sub`,children:`player activity · operations & audit · health incidents`})]}),(0,b.jsx)(`div`,{className:`event-lanes`,role:`group`,"aria-label":`Event lanes`,children:m.map(e=>(0,b.jsxs)(`button`,{type:`button`,"aria-pressed":t===e.id,className:`event-lane ${t===e.id?`is-active`:``}`,onClick:()=>I(e.id),children:[(0,b.jsx)(`span`,{className:`event-lane-name`,children:e.label}),(0,b.jsx)(`span`,{className:`event-lane-count`,children:A[e.id].toLocaleString()}),(0,b.jsx)(`span`,{className:`event-lane-description`,children:e.description})]},e.id))}),(0,b.jsxs)(`p`,{className:`events-scope`,children:[`Counts cover the newest `,k.length.toLocaleString(),` events (up to `,S,`).`]}),(0,b.jsxs)(`div`,{className:`events-toolbar`,children:[(0,b.jsx)(o,{value:g,onChange:e=>{T(e.target.value),D(0)},placeholder:`Search event messages…`,"aria-label":`Search events`}),(0,b.jsxs)(`select`,{className:`input`,value:i,onChange:e=>L(e.target.value),"aria-label":`Filter event kind`,children:[(0,b.jsx)(`option`,{value:`all`,children:C.all}),M.map(e=>(0,b.jsx)(`option`,{value:e,children:C[e]},e))]}),(0,b.jsxs)(`span`,{className:`events-count`,children:[j.length.toLocaleString(),` matching · page `,P+1,` of `,N]})]}),(0,b.jsx)(u,{children:O.isError?(0,b.jsx)(l,{children:(0,b.jsx)(c,{tone:`warn`,children:`Couldn't load panel events.`})}):O.isLoading?(0,b.jsx)(l,{children:(0,b.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:100}})}):F.length===0?(0,b.jsx)(l,{children:(0,b.jsx)(d,{title:`No matching events`,description:`Try a different event type or search phrase.`})}):(0,b.jsx)(l,{flush:!0,className:`events-table-wrap`,children:(0,b.jsxs)(`table`,{className:`table events-table`,children:[(0,b.jsx)(`thead`,{children:(0,b.jsxs)(`tr`,{children:[(0,b.jsx)(`th`,{children:`Time`}),(0,b.jsx)(`th`,{children:`Type`}),(0,b.jsx)(`th`,{children:`Event`}),(0,b.jsx)(`th`,{children:`Actor`})]})}),(0,b.jsx)(`tbody`,{children:F.map((e,t)=>{let n=typeof e.meta?.actor==`string`?e.meta.actor:`—`;return(0,b.jsxs)(`tr`,{children:[(0,b.jsx)(`td`,{className:`num events-time`,children:s(e.at)}),(0,b.jsx)(`td`,{children:(0,b.jsx)(a,{tone:w(e.kind),children:e.kind})}),(0,b.jsx)(`td`,{children:(0,b.jsx)(f,{text:e.message})}),(0,b.jsx)(`td`,{className:`num`,children:n})]},`${e.at}-${e.kind}-${P*x+t}`)})})]})})}),j.length>x&&(0,b.jsxs)(`div`,{className:`events-pagination`,"aria-label":`Event pages`,children:[(0,b.jsx)(`button`,{type:`button`,className:`btn btn-sm`,disabled:P===0,onClick:()=>D(P-1),children:`Previous`}),(0,b.jsxs)(`span`,{className:`num`,children:[`Page `,P+1,` of `,N]}),(0,b.jsx)(`button`,{type:`button`,className:`btn btn-sm`,disabled:P>=N-1,onClick:()=>D(P+1),children:`Next`})]})]})}export{T as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Events-Y3iu26GS.css b/backend/internal/webdist/dist/assets/Events-Y3iu26GS.css
new file mode 100644
index 0000000..cba2cb7
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Events-Y3iu26GS.css
@@ -0,0 +1 @@
+.event-lanes{gap:var(--space-3);grid-template-columns:repeat(4,minmax(0,1fr));display:grid}.event-lane{gap:3px var(--space-2);min-width:0;color:var(--ink-2);text-align:left;background:var(--surface);border:var(--border-ctl) solid var(--line);border-radius:var(--radius-card);cursor:pointer;grid-template-columns:minmax(0,1fr) auto;padding:11px 12px;display:grid}.event-lane:hover{border-color:var(--line-strong);background:var(--surface-2)}.event-lane.is-active{color:var(--accent-ink);border-color:var(--accent);background:var(--accent-soft)}.event-lane-name{min-width:0;font-weight:600}.event-lane-count{font-family:var(--font-mono);font-variant-numeric:tabular-nums;font-weight:600}.event-lane-description{color:var(--ink-3);font-size:var(--text-xs);white-space:nowrap;text-overflow:ellipsis;grid-column:1/-1;overflow:hidden}.events-scope{margin:7px 2px var(--space-3);color:var(--ink-3);font:var(--text-xs)/1.4 var(--font-mono)}.events-toolbar{align-items:center;gap:var(--space-3);margin-bottom:var(--space-3);display:flex}.events-toolbar .search{width:min(360px,100%)}.events-toolbar .input{width:auto}.events-count{color:var(--ink-3);font:var(--text-xs)/1.4 var(--font-mono);margin-left:auto}.events-table-wrap{overflow-x:auto}.events-table .events-time{white-space:nowrap;width:190px}.events-pagination{justify-content:center;align-items:center;gap:var(--space-3);margin-top:var(--space-3);display:flex}@media (width<=700px){.event-lanes{grid-template-columns:repeat(2,minmax(0,1fr))}.events-toolbar{flex-direction:column;align-items:stretch}.events-toolbar .search,.events-toolbar .input{width:100%}.events-count{margin-left:0}}@media (width<=420px){.event-lanes{grid-template-columns:1fr}}
diff --git a/backend/internal/webdist/dist/assets/Guilds-Iqca6q84.js b/backend/internal/webdist/dist/assets/Guilds-Iqca6q84.js
new file mode 100644
index 0000000..c29f993
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Guilds-Iqca6q84.js
@@ -0,0 +1 @@
+import{H as e,U as t,j as n,q as r,z as i}from"./icons-CpYMTu_k.js";import{Fn as a,Mn as o,c as s,d as c,s as l}from"./index-BpCavHBc.js";import{t as u}from"./Banner-DSN1nEJn.js";import{n as d,r as f,t as p}from"./Card-D55CMzdw.js";import{t as m}from"./EmptyState-DTSMkv56.js";import{t as h}from"./guildDisplay-LZYrk7hc.js";import{t as g}from"./PalIcon-BoDQgR3K.js";import{t as _}from"./PalStars-CiCl8RwT.js";import{o as v,r as y,s as b}from"./palExplorer-IChZ_UBL.js";var x=r();function S(){let{guildId:r}=a(),i=t({queryKey:[`guilds`],queryFn:()=>n.guilds.list(),enabled:!r}),s=t({queryKey:[`guilds`,`detail`,r],queryFn:()=>n.guilds.detail(r??``),enabled:!!r}),c=r?s.isPending:i.isPending,l=r?s.isError:i.isError,g=s.error instanceof e&&s.error.status===404;return(0,x.jsxs)(`main`,{className:`content guilds-page`,children:[(0,x.jsxs)(`div`,{className:`page-head guilds-head`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`h1`,{children:r?s.data?h(s.data):`Guild detail`:`Guilds`}),(0,x.jsx)(`span`,{className:`sub`,children:`rosters · bases · members from the latest save`})]}),r&&(0,x.jsx)(o,{className:`btn btn-sm btn-ghost`,to:`/guilds`,children:`All guilds`})]}),g?(0,x.jsx)(p,{children:(0,x.jsx)(d,{children:(0,x.jsx)(m,{title:`Guild not found`,description:`It may have disbanded or changed in the latest parsed save.`})})}):l?(0,x.jsx)(u,{tone:`warn`,children:`Couldn't load guild data from the latest parsed save.`}):c?(0,x.jsx)(p,{children:(0,x.jsx)(d,{children:(0,x.jsx)(`span`,{className:`skel skel-text guilds-skeleton`})})}):s.data?(0,x.jsx)(C,{guild:s.data}):(i.data??[]).length===0?(0,x.jsx)(p,{children:(0,x.jsx)(d,{children:(0,x.jsx)(m,{title:`No guilds found`,description:`Guilds appear after the world save has been parsed.`})})}):(0,x.jsx)(`div`,{className:`guilds-grid`,children:(i.data??[]).map(e=>(0,x.jsxs)(p,{children:[(0,x.jsx)(f,{title:(0,x.jsx)(o,{to:`/guilds/${encodeURIComponent(e.id)}`,children:h(e)}),hint:`${e.memberCount} members`}),(0,x.jsxs)(d,{className:`guild-card-body`,children:[(0,x.jsxs)(`span`,{children:[e.bases.length,` `,e.bases.length===1?`base`:`bases`]}),(0,x.jsx)(`span`,{children:e.members.length>0?e.members.map(e=>e.name||`Unknown player`).join(`, `):`No known members`})]})]},e.id))})]})}function C({guild:e}){return(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(u,{tone:e.activity.analysisTruncated?`warn`:`info`,children:[`Roster from the latest parsed save. Activity is panel-observed over the last 30 days and credited to current membership.`,e.activity.analysisTruncated?` Analysis was truncated.`:``]}),(0,x.jsxs)(`div`,{className:`guilds-stats`,"aria-label":`Guild summary`,children:[(0,x.jsx)(p,{children:(0,x.jsxs)(d,{className:`guild-stat`,children:[(0,x.jsx)(`span`,{children:`Members`}),(0,x.jsx)(`strong`,{children:e.memberCount}),(0,x.jsxs)(`small`,{children:[e.members.filter(e=>e.online).length,` online now`]})]})}),(0,x.jsx)(p,{children:(0,x.jsxs)(d,{className:`guild-stat`,children:[(0,x.jsx)(`span`,{children:`Bases`}),(0,x.jsx)(`strong`,{children:e.bases.length}),(0,x.jsxs)(`small`,{children:[e.bases.reduce((e,t)=>e+t.palCount,0),` base workers`]})]})}),(0,x.jsx)(p,{children:(0,x.jsxs)(d,{className:`guild-stat`,children:[(0,x.jsx)(`span`,{children:`Linked Pals`}),(0,x.jsx)(`strong`,{children:e.palCount}),(0,x.jsx)(`small`,{children:`at bases or owned by members`})]})}),(0,x.jsx)(p,{children:(0,x.jsxs)(d,{className:`guild-stat`,children:[(0,x.jsx)(`span`,{children:`Activity · 30d`}),(0,x.jsx)(`strong`,{children:l(e.activity.durationSec)}),(0,x.jsxs)(`small`,{children:[e.activity.sessionCount,` sessions · `,e.activity.activePlayers,` players`]})]})})]}),(0,x.jsxs)(`div`,{className:`guilds-detail-grid`,children:[(0,x.jsxs)(p,{children:[(0,x.jsx)(f,{title:`Members`,hint:`from the latest save`}),e.members.length===0?(0,x.jsx)(d,{children:(0,x.jsx)(m,{title:`No linked players`,description:`The save has no player identities linked to this guild.`})}):(0,x.jsx)(d,{flush:!0,className:`guild-table-wrap`,children:(0,x.jsxs)(`table`,{className:`table`,children:[(0,x.jsx)(`thead`,{children:(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{children:`Player`}),(0,x.jsx)(`th`,{children:`Level`}),(0,x.jsx)(`th`,{children:`Observed · 30d`}),(0,x.jsx)(`th`,{children:`Progress`})]})}),(0,x.jsx)(`tbody`,{children:e.members.map(e=>(0,x.jsxs)(`tr`,{children:[(0,x.jsxs)(`td`,{children:[(0,x.jsx)(`strong`,{children:(0,x.jsx)(o,{to:`/players?player=${encodeURIComponent(e.uid)}`,children:e.name||`Unknown player`})}),(0,x.jsx)(`small`,{children:e.online?(0,x.jsx)(c,{tone:`ok`,children:`Online`}):`seen ${s(e.lastSeenAt)}`})]}),(0,x.jsx)(`td`,{className:`num`,children:e.level}),(0,x.jsxs)(`td`,{className:`num`,children:[l(e.observedDurationSec),(0,x.jsxs)(`small`,{children:[e.observedSessionCount,` sessions`]})]}),(0,x.jsx)(`td`,{children:e.paldeckUnlocked===null?(0,x.jsx)(`span`,{className:`guild-muted`,children:`Unavailable`}):(0,x.jsxs)(o,{to:`/paldeck?player=${encodeURIComponent(e.uid)}`,children:[e.paldeckUnlocked,` Paldeck unlocks`]})})]},e.uid))})]})})]}),(0,x.jsxs)(p,{children:[(0,x.jsx)(f,{title:`Bases`,hint:`in-game map coordinates`}),e.bases.length===0?(0,x.jsx)(d,{children:(0,x.jsx)(m,{title:`No bases found`,description:`No current base records are linked to this guild.`})}):(0,x.jsx)(d,{flush:!0,className:`guild-table-wrap`,children:(0,x.jsxs)(`table`,{className:`table`,children:[(0,x.jsx)(`thead`,{children:(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`th`,{children:`Base`}),(0,x.jsx)(`th`,{children:`Level`}),(0,x.jsx)(`th`,{children:`Pals`}),(0,x.jsx)(`th`,{children:`Location`})]})}),(0,x.jsx)(`tbody`,{children:e.bases.map((e,t)=>{let n=e.location?i(e.location.x,e.location.y):null;return(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:e.name??`Base ${t+1}`}),(0,x.jsx)(`td`,{className:`num`,children:e.level}),(0,x.jsx)(`td`,{className:`num`,children:e.palCount}),(0,x.jsx)(`td`,{children:n?(0,x.jsxs)(o,{to:`/map?x=${n.x}&y=${n.y}`,children:[n.x,`, `,n.y]}):(0,x.jsx)(`span`,{className:`guild-muted`,children:`Unavailable`})})]},e.id)})})]})})]})]}),(0,x.jsxs)(p,{children:[(0,x.jsx)(f,{title:`Linked Pals`,hint:`${e.pals.length} shown${e.palsTruncated?` · list capped`:``}`,children:(0,x.jsx)(o,{to:y({placement:`base`}),children:`Open Pal explorer`})}),e.pals.length===0?(0,x.jsx)(d,{children:(0,x.jsx)(m,{title:`No linked Pals`,description:`No Pals at this guild's bases or owned by its members.`})}):(0,x.jsx)(d,{className:`guild-pal-grid`,children:e.pals.map(e=>{let t=b(e);return(0,x.jsxs)(`article`,{className:`guild-pal`,children:[(0,x.jsx)(g,{characterId:e.characterId,displayName:e.displayName}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`strong`,{children:e.displayName}),(0,x.jsxs)(`small`,{children:[`Lv `,e.level,` · `,t.length?t.map(e=>e===`Boss`?`◆ Boss`:e).join(` · `):`Standard`,e.rank!=null&&e.rank>1&&(0,x.jsxs)(x.Fragment,{children:[` · `,(0,x.jsx)(_,{rank:e.rank})]})]}),(0,x.jsx)(`small`,{children:e.association===`guild_base`?`Guild base`:v(e)})]}),(0,x.jsx)(o,{to:y({q:e.displayName,placement:e.association===`guild_base`?`base`:``}),children:`Roster`})]},e.instanceId)})})]})]})}export{S as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Guilds-VTJeI58t.css b/backend/internal/webdist/dist/assets/Guilds-VTJeI58t.css
new file mode 100644
index 0000000..5c60370
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Guilds-VTJeI58t.css
@@ -0,0 +1 @@
+.guilds-page{gap:var(--space-4)}.guilds-head{justify-content:space-between;align-items:center;row-gap:var(--space-2);flex-wrap:wrap}.guilds-head>div{align-items:baseline;gap:var(--space-3);flex-wrap:wrap;min-width:0;display:flex}.guilds-grid{gap:var(--space-3);grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.guild-card-body{color:var(--ink-2);font-size:var(--text-sm);flex-direction:column;gap:6px;display:flex}.guild-card-body span:last-child{color:var(--ink-3)}.guilds-skeleton{width:100%;height:150px}.guilds-stats{gap:var(--space-3);grid-template-columns:repeat(4,minmax(0,1fr));display:grid}.guild-stat{flex-direction:column;gap:4px;display:flex}.guild-stat span{color:var(--ink-3);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--track-caps)}.guild-stat strong{font:600 var(--text-2xl)/1 var(--font-mono);font-variant-numeric:tabular-nums}.guild-stat small{color:var(--ink-3)}.guilds-detail-grid{gap:var(--space-3);grid-template-columns:repeat(2,minmax(0,1fr));align-items:start;display:grid}.guild-table-wrap{overflow-x:auto}.guild-table-wrap td strong,.guild-table-wrap td small{display:block}.guild-table-wrap td small{color:var(--ink-3);margin-top:3px;font-size:10px}.guild-muted{color:var(--ink-3)}.guild-pal-grid{gap:var(--space-2);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.guild-pal{border:1px solid var(--line);border-radius:var(--radius-ctl);background:var(--surface-2);grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:9px;padding:9px;display:grid}.guild-pal>div{min-width:0}.guild-pal strong,.guild-pal small{text-overflow:ellipsis;white-space:nowrap;display:block;overflow:hidden}.guild-pal small{color:var(--ink-3);font-size:10px}@media (width<=850px){.guilds-grid,.guilds-detail-grid{grid-template-columns:1fr}.guilds-stats,.guild-pal-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width<=620px){.guilds-head,.guilds-head>div{align-items:flex-start}.guilds-head>div{flex-direction:column;gap:2px}.guilds-stats,.guild-pal-grid{grid-template-columns:1fr}.guild-pal{grid-template-columns:auto minmax(0,1fr)}.guild-pal>a{grid-column:2;justify-self:start}}
diff --git a/backend/internal/webdist/dist/assets/Map-BIP07Cn0.js b/backend/internal/webdist/dist/assets/Map-BIP07Cn0.js
new file mode 100644
index 0000000..e8bb70f
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Map-BIP07Cn0.js
@@ -0,0 +1 @@
+import{A as e,B as t,F as n,I as r,L as i,O as a,R as o,U as s,V as c,_ as l,_t as u,b as d,d as f,g as p,ht as m,j as h,k as ee,q as g,v as te,y as ne,z as _}from"./icons-CpYMTu_k.js";import{Dn as re,c as ie,i as ae,l as oe,m as v}from"./index-BpCavHBc.js";import{n as se,r as ce,t as le}from"./Card-D55CMzdw.js";import{t as ue}from"./EmptyState-DTSMkv56.js";import{t as de}from"./CodeWell-Mu33yg_R.js";import{t as fe}from"./guildDisplay-LZYrk7hc.js";var y=u(m(),1);function pe(e,t,n,r,i){let a=Math.ceil(Math.log2(e*t/n));return Math.max(r,Math.min(i,a))}function me(e,t=48,n=null){if(!Number.isFinite(t)||t<=0)return e.map(e=>({type:`single`,key:e.key,x:e.x,y:e.y,member:e}));let r=[...e].sort((e,t)=>e.key.localeCompare(t.key)),i=t*t,a=[];for(let e of r){let t=e.key===n?void 0:a.find(t=>!t.locked&&t.members[0].kind===e.kind&&t.members[0].layerId===e.layerId&&t.members.every(t=>{let n=t.x-e.x,r=t.y-e.y;return n*n+r*r<=i}));t?t.members.push(e):a.push({locked:e.key===n,members:[e]})}return a.map(({members:e})=>{if(e.length===1){let t=e[0];return{type:`single`,key:t.key,x:t.x,y:t.y,member:t}}return{type:`cluster`,key:`cluster:${e[0].layerId}:${e[0].kind}:${e.map(e=>e.key).join(`|`)}`,x:e.reduce((e,t)=>e+t.x,0)/e.length,y:e.reduce((e,t)=>e+t.y,0)/e.length,members:e}})}var he=Object.freeze({Players:!0,Bases:!0,Workers:!1,PalBoxes:!1});function ge(e,t,n,r){let i=Math.min(r.max,Math.max(r.min,e.scale*t)),a=i/e.scale;return{scale:i,tx:n.x-(n.x-e.tx)*a,ty:n.y-(n.y-e.ty)*a}}function _e(e){return e<0?1.25:.8}function ve(e,t){return Math.min(t.max,Math.max(t.min,e))}function ye(e,t,n,r){let i=ve(n,r);return{scale:i,tx:t.width/2-e.x*i,ty:t.height/2-e.y*i}}function be(e,t,n,r=48){let i=e.filter(e=>Number.isFinite(e.x)&&Number.isFinite(e.y));if(i.length===0||t.width<=0||t.height<=0)return null;let a=Math.min(...i.map(e=>e.x)),o=Math.max(...i.map(e=>e.x)),s=Math.min(...i.map(e=>e.y)),c=Math.max(...i.map(e=>e.y)),l=o-a,u=c-s,d=Math.max(1,t.width-r*2),f=Math.max(1,t.height-r*2),p=l===0&&u===0?n.min*4:Math.min(l>0?d/l:1/0,u>0?f/u:1/0);return ye({x:(a+o)/2,y:(s+c)/2},t,p,n)}function xe(e,t,n=8){let r=t.trim().toLocaleLowerCase();return r?e.filter(e=>`${e.label} ${e.detail}`.toLocaleLowerCase().includes(r)).sort((e,t)=>{let n=e.label.toLocaleLowerCase(),i=t.label.toLocaleLowerCase();return(n===r?0:n.startsWith(r)?1:2)-(i===r?0:i.startsWith(r)?1:2)||e.label.localeCompare(t.label)||e.key.localeCompare(t.key)}).slice(0,Math.max(0,n)):[]}function Se(e){let t=new URLSearchParams(e),n=t.get(`x`),r=t.get(`y`);if(n===null||r===null)return null;let i=Number(n),a=Number(r);if(!Number.isFinite(i)||!Number.isFinite(a))return null;let o=t.get(`layer`),s=o&&/^[a-zA-Z0-9_-]{1,64}$/.test(o)?o:null;return{x:Math.round(i),y:Math.round(a),layerId:s}}function Ce(e,t,n){let r=new URL(e);return r.searchParams.set(`x`,String(Math.round(t.x))),r.searchParams.set(`y`,String(Math.round(t.y))),r.searchParams.set(`layer`,n),r.toString()}function we(e,t){let n=e=>{e.preventDefault(),e.stopPropagation(),t(e)};return e.addEventListener(`wheel`,n,{passive:!1}),()=>e.removeEventListener(`wheel`,n)}function b(e){return e!=null&&Number.isFinite(e.x)&&Number.isFinite(e.y)}function Te(e){return e?.state!==`ready`||e.truncated?{available:!1,workers:[],palBoxes:[]}:{available:!0,workers:e.actors.filter(e=>e.kind===`BaseCampPal`&&e.linked===!0&&!!e.instanceId&&!!e.baseId&&b(e.location)),palBoxes:e.actors.filter(e=>e.kind===`PalBox`&&b(e.location))}}function x(e){return e.activity===`incapacitated`||e.hpPercent!==void 0&&e.hpPercent<25}function S(e){let t=e.filter(x).length;return{label:t>0?`${e.length} workers · ${t} hurt`:`${e.length} workers`,hurt:t,danger:t>0}}function Ee(e,t){let n=e.filter(e=>e.online&&b(e.location)).map(e=>({key:e.uid,name:e.name,location:e.location}));if(t?.state!==`ready`||t.truncated)return{markers:n,usedLive:!1};let r=new Map;for(let e of t.actors){if(e.kind!==`Player`||e.active!==!0||!e.name||!b(e.location))continue;let t=r.get(e.name)??[];t.push(e.location),r.set(e.name,t)}let i=new Map;for(let e of n)i.set(e.name,(i.get(e.name)??0)+1);let a=!1;return{markers:n.map(e=>{let t=r.get(e.name);return i.get(e.name)!==1||t?.length!==1?e:(a=!0,{...e,location:{x:t[0].x,y:t[0].y}})}),usedLive:a}}var C=g();function w({pressed:e,onClick:t,children:n,count:r}){return(0,C.jsxs)(`button`,{type:`button`,className:`chip-toggle`,"aria-pressed":e,onClick:t,children:[n,r!==void 0&&(0,C.jsx)(`span`,{className:`n`,children:r})]})}var De={id:`legacy`,label:`Map`,format:`png`,path:``,tileSize:256,minZoom:0,maxZoom:6,transform:null,bounds:null};function Oe(e){let t=e?.layers??[];return t.length===0?[De]:t.map(e=>({id:e.id,label:e.label||e.id,format:e.format??`png`,path:e.path,tileSize:e.tile_size??256,minZoom:e.min_zoom,maxZoom:e.max_zoom,transform:e.transform??null,bounds:e.bounds??null}))}function ke(e,t,n,r){return`${e.path?`/map-tiles/${e.path}`:`/map-tiles`}/${t}/${n}/${r}.${e.format}`}function T(e,n,r){return e.transform?t(n,r,e.transform,e.tileSize):c(n,r)}function Ae(e,t,n){return e.transform?r(t,n,e.transform,e.tileSize):i(t,n)}function E(e,t,n){return!e.bounds||o(t,n,e.bounds)}function D(){let t=re(),r=(0,y.useRef)(typeof window>`u`?null:Se(window.location.search)),i=(0,y.useRef)(!1),[o,c]=(0,y.useState)(()=>({...he})),[u,d]=(0,y.useState)(`checking`),[m,g]=(0,y.useState)(null),[ve,b]=(0,y.useState)(null),[x,S]=(0,y.useState)(()=>{let e=r.current;return e?{x:e.x,y:e.y}:null}),[D,Fe]=(0,y.useState)(``),[Ie,O]=(0,y.useState)(!1),[k,Le]=(0,y.useState)(null),[Re,ze]=(0,y.useState)(null),[A,j]=(0,y.useState)(()=>r.current?.layerId??null),M=(0,y.useRef)(null),N=(0,y.useRef)(null),P=s({queryKey:[`server`],queryFn:()=>h.server.get()}),Be=s({queryKey:[`server`,`health`],queryFn:()=>h.server.health()}),Ve=s({queryKey:[`players`],queryFn:()=>h.players.list(),refetchInterval:3e4}),He=s({queryKey:[`guilds`],queryFn:()=>h.guilds.list()}),F=s({queryKey:[`map`,`dataset`],queryFn:()=>h.map.dataset()}),Ue=s({queryKey:[`world`,`snapshot`],queryFn:()=>h.world.snapshot(),refetchInterval:3e4}),We=typeof window<`u`&&new URLSearchParams(window.location.search).has(`mocktiles`),I=(0,y.useMemo)(()=>Oe(F.data),[F.data]),Ge=(F.data?.game_version??`pre-1.0`)!==`1.0`;(0,y.useEffect)(()=>{I.length!==0&&(A===null||!I.some(e=>e.id===A))&&j(I[0].id)},[I,A]);let L=I.find(e=>e.id===A)??I[0]??De;(0,y.useEffect)(()=>{if(e){d(We?`mockgrid`:`missing`);return}if(F.isLoading)return;let t=!1,n=new Image;return n.onload=()=>!t&&d(`tiles`),n.onerror=()=>!t&&d(We?`mockgrid`:`missing`),n.src=ke(L,0,0,0),()=>{t=!0}},[We,F.isLoading,L]);let R=(0,y.useCallback)(()=>{let e=M.current;if(!e)return null;let{clientWidth:t,clientHeight:n}=e;if(t===0||n===0)return null;let r=Math.min(t,n)/256;return{scale:r,tx:(t-256*r)/2,ty:(n-256*r)/2}},[]);(0,y.useEffect)(()=>{if((u===`tiles`||u===`mockgrid`)&&m===null){let e=R();e&&g(e)}},[u,m,R]);let z=(0,y.useCallback)(e=>{let t=M.current,n=t?Math.min(t.clientWidth,t.clientHeight)/256*2**e.minZoom:1;return{min:n,max:n*2**e.maxZoom}},[]),Ke=(0,y.useCallback)(()=>z(L),[L,z]),B=(0,y.useCallback)((e,t,n)=>{g(r=>{if(!r)return r;let i=M.current;return ge(r,e,{x:t??(i?i.clientWidth/2:0),y:n??(i?i.clientHeight/2:0)},Ke())})},[Ke]),qe=(0,y.useCallback)(()=>{let e=R();e&&g(e)},[R]);(0,y.useEffect)(()=>{let e=M.current;if(!(!e||u!==`tiles`&&u!==`mockgrid`))return we(e,t=>{let n=e.getBoundingClientRect();B(_e(t.deltaY),t.clientX-n.left,t.clientY-n.top)})},[u,B]);let Je=(0,y.useCallback)((e,t)=>{let n=M.current;if(!n||!m)return null;let r=n.getBoundingClientRect(),i=(e-r.left-m.tx)/m.scale,a=(t-r.top-m.ty)/m.scale;if(i<0||a<0||i>256||a>256)return null;let o=Ae(L,i,a);return _(o.x,o.y)},[L,m]);function Ye(e){m&&(e.target.closest(`button, a, input, select, textarea`)||(e.target.setPointerCapture?.(e.pointerId),N.current={startX:e.clientX,startY:e.clientY,tx:m.tx,ty:m.ty,moved:!1}))}function Xe(e){let t=Je(e.clientX,e.clientY);t&&b(t);let n=N.current;n&&((Math.abs(e.clientX-n.startX)>4||Math.abs(e.clientY-n.startY)>4)&&(n.moved=!0),g(t=>t&&{...t,tx:n.tx+(e.clientX-n.startX),ty:n.ty+(e.clientY-n.startY)}))}function Ze(e){let t=N.current;if(t&&!t.moved){let t=Je(e.clientX,e.clientY);t&&(S(t),b(t))}N.current=null}function Qe(){N.current=null}let $e=m?pe(m.scale,256,L.tileSize,L.minZoom,L.maxZoom):0,V=Ue.isError||Ue.isRefetchError?void 0:Ue.data,H=Ee(Ve.data??[],V),U=H.markers,W=(He.data??[]).flatMap(e=>e.bases.map(t=>({...t,guildName:t.name??fe(e)}))).filter(e=>e.location!==null),G=Te(V),K=G.workers,et=G.palBoxes,tt=(0,y.useMemo)(()=>{let e=new Map;for(let t of K){let n=e.get(t.baseId)??[];n.push(t),e.set(t.baseId,n)}return[...e.entries()].map(([e,t])=>({baseId:e,name:W.find(t=>t.id===e)?.guildName??`Base ${e.slice(0,8)}`,members:t,lowHP:t.filter(e=>e.hpPercent!==void 0&&e.hpPercent<25).length,incapacitated:t.filter(e=>e.activity===`incapacitated`).length,idle:t.filter(e=>e.activity===`idle`||e.activity===`inactive`).length}))},[K,W]),q=(0,y.useMemo)(()=>[...U.map(e=>({key:`player:${e.key}`,kind:`player`,label:e.name,detail:`Online player`,location:e.location})),...W.map(e=>{let t=_(e.location.x,e.location.y);return{key:`base:${e.id}`,kind:`base`,label:e.guildName,detail:`Base · ${t.x}, ${t.y}`,location:e.location}})],[U,W]),nt=(0,y.useMemo)(()=>xe(q,D),[q,D]),rt=q.find(e=>e.key===k)??null,J=(0,y.useCallback)((e,t,n,r)=>{let i=M.current;if(!i)return;let a=r&&E(r,e.x,e.y)?r:E(L,e.x,e.y)?L:I.find(t=>E(t,e.x,e.y));if(!a)return;let o=z(a),s=a.id===L.id?m?.scale??o.min:o.min,l=T(a,e.x,e.y);j(a.id),g(ye(l,{width:i.clientWidth,height:i.clientHeight},Math.max(s,o.min*3),o)),t&&c(e=>({...e,[t===`player`?`Players`:`Bases`]:!0})),n&&Le(n),S(_(e.x,e.y))},[L,I,z,m?.scale]),Y=(0,y.useCallback)(e=>{J(e.location,e.kind,e.key),Fe(e.label),O(!1),ze(null)},[J]);function it(e){let t=(e===`player`?U.map(e=>e.location):W.map(e=>e.location)).filter(e=>E(L,e.x,e.y)).map(e=>T(L,e.x,e.y)),n=M.current;if(!n)return;let r=be(t,{width:n.clientWidth,height:n.clientHeight},z(L));r&&g(r),c(t=>({...t,[e===`player`?`Players`:`Bases`]:!0}))}async function at(){let e=x??ve;if(!e||typeof window>`u`)return;let n=Ce(window.location.href,e,L.id);window.history.replaceState(null,``,n);try{if(!navigator.clipboard)throw Error(`clipboard unavailable`);await navigator.clipboard.writeText(n),t.push(`Map link copied for ${e.x}, ${e.y}.`,`ok`)}catch{t.push(`Coordinates were added to the address bar; copy the link from your browser.`)}}let X=(0,y.useCallback)((e,t)=>m?{x:m.tx+e*m.scale,y:m.ty+t*m.scale}:{x:0,y:0},[m]),ot=(0,y.useMemo)(()=>me(q.filter(e=>E(L,e.location.x,e.location.y)).map(e=>{let t=T(L,e.location.x,e.location.y),n=X(t.x,t.y);return{key:e.key,kind:e.kind,layerId:L.id,x:n.x,y:n.y,value:e}}),48,k),[L,q,k,X]),st=ot.filter(e=>je(e)===`base`),ct=ot.filter(e=>je(e)===`player`),lt=(0,y.useCallback)(e=>{let t=M.current;if(!t)return;let n=be(e.members.map(({value:e})=>T(L,e.location.x,e.location.y)),{width:t.clientWidth,height:t.clientHeight},z(L));if(n&&(!m||n.scale>m.scale*1.15)){ze(null),g(n);return}ze(t=>t===e.key?null:e.key)},[L,z,m]),ut=(0,y.useMemo)(()=>me(K.filter(e=>E(L,e.location.x,e.location.y)).map(e=>{let t=T(L,e.location.x,e.location.y),n=X(t.x,t.y);return{key:`worker:${e.instanceId}`,kind:`worker`,layerId:L.id,x:n.x,y:n.y,value:e}}),48),[L,K,X]),Z=u===`tiles`||u===`mockgrid`;(0,y.useEffect)(()=>{let e=r.current;if(!e||i.current||!Z||!m)return;let t=n(e.x,e.y),a=e.layerId?I.find(t=>t.id===e.layerId):void 0;J(t,void 0,void 0,a),i.current=!0},[I,J,Z,m]);let dt=U.filter(e=>E(L,e.location.x,e.location.y)).length,ft=W.filter(e=>E(L,e.location.x,e.location.y)).length,Q=x??ve,$=x?n(x.x,x.y):null,pt=$&&E(L,$.x,$.y)?(()=>{let e=T(L,$.x,$.y);return X(e.x,e.y)})():null;return(0,C.jsxs)(`main`,{className:`content`,children:[(0,C.jsxs)(`div`,{className:`page-head`,children:[(0,C.jsx)(`h1`,{children:`Live map`}),(0,C.jsx)(`span`,{className:`sub`,title:P.data?.worldGuid,children:P.data?`world ${oe(P.data.worldGuid)}`:`world positions from save data`})]}),(0,C.jsxs)(le,{className:`map-card`,children:[(0,C.jsx)(ce,{title:`World map`,hint:H.usedLive?`live game data`:`positions from save data`,children:H.usedLive&&V?.capturedAt?(0,C.jsxs)(`span`,{className:`hint`,children:[`live snapshot `,ie(V.capturedAt)]}):Be.data?(0,C.jsxs)(`span`,{className:`hint`,children:[`synced `,ie(Be.data.save.lastSyncAt)]}):null}),(0,C.jsxs)(`div`,{className:`map-actionbar`,children:[(0,C.jsxs)(`form`,{className:`map-search`,role:`search`,onSubmit:e=>{e.preventDefault();let t=nt[0];t&&Y(t)},onBlur:e=>{e.currentTarget.contains(e.relatedTarget)||O(!1)},children:[(0,C.jsx)(ae,{value:D,onChange:e=>{Fe(e.target.value),O(!0)},onFocus:()=>O(!0),placeholder:`Search online players or bases…`,"aria-label":`Search online players or bases`,"aria-expanded":Ie&&D.trim().length>0,"aria-controls":`map-search-results`,autoComplete:`off`}),Ie&&D.trim()&&(0,C.jsx)(`div`,{className:`map-search-results`,id:`map-search-results`,children:nt.length===0?(0,C.jsx)(`span`,{className:`map-search-empty`,children:`No matching online player or base`}):nt.map(e=>(0,C.jsxs)(`button`,{type:`button`,onClick:()=>Y(e),children:[(0,C.jsx)(`span`,{className:`map-search-result-icon`,children:e.kind===`player`?(0,C.jsx)(ne,{}):(0,C.jsx)(p,{})}),(0,C.jsxs)(`span`,{children:[(0,C.jsx)(`strong`,{children:e.label}),(0,C.jsx)(`small`,{children:e.detail})]})]},e.key))})]}),(0,C.jsxs)(`button`,{type:`button`,className:`btn btn-sm map-action`,disabled:!rt,onClick:()=>rt&&Y(rt),children:[(0,C.jsx)(f,{}),` Focus selected`]}),(0,C.jsxs)(`button`,{type:`button`,className:`btn btn-sm map-action`,disabled:dt===0,onClick:()=>it(`player`),children:[(0,C.jsx)(ne,{}),` Fit online (`,dt,`)`]}),(0,C.jsxs)(`button`,{type:`button`,className:`btn btn-sm map-action`,disabled:ft===0,onClick:()=>it(`base`),children:[(0,C.jsx)(p,{}),` Fit bases (`,ft,`)`]}),(0,C.jsx)(`button`,{type:`button`,className:`btn btn-sm map-action`,disabled:!Q,onClick:at,children:`Copy coordinate link`})]}),(0,C.jsxs)(`div`,{ref:M,className:`map-well${Z?` pannable`:``}`,"aria-label":`World map`,onPointerDown:Z?Ye:void 0,onPointerMove:Z?Xe:void 0,onPointerUp:Z?Ze:void 0,onPointerCancel:Z?Qe:void 0,onPointerLeave:Z?Qe:void 0,children:[Z&&(0,C.jsxs)(`div`,{className:`map-overlays`,children:[(0,C.jsxs)(`div`,{className:`map-toggles`,role:`group`,"aria-label":`Map layers`,children:[(0,C.jsx)(w,{pressed:o.Players??!1,onClick:()=>c(e=>({...e,Players:!e.Players})),count:U.length,children:`Players`}),(0,C.jsx)(w,{pressed:o.Bases??!1,onClick:()=>c(e=>({...e,Bases:!e.Bases})),count:W.length,children:`Bases`}),(0,C.jsx)(w,{pressed:o.Workers??!1,onClick:()=>c(e=>({...e,Workers:!e.Workers})),count:K.length,children:`Workers`}),(0,C.jsx)(w,{pressed:o.PalBoxes??!1,onClick:()=>c(e=>({...e,PalBoxes:!e.PalBoxes})),count:et.length,children:`PalBoxes`}),Ge&&(0,C.jsx)(`span`,{className:`stamp stamp-warn stamp-tilt`,children:`Map data: pre-1.0`}),V?.state===`stale`&&(0,C.jsx)(`span`,{className:`stamp stamp-warn`,children:`Live data stale`}),V?.state===`unsupported`&&(0,C.jsx)(`span`,{className:`stamp stamp-warn`,children:`Game data unavailable`}),V?.state===`unauthorized`&&(0,C.jsx)(`span`,{className:`stamp stamp-warn`,children:`Game data unauthorized`}),V?.state===`unavailable`&&(0,C.jsx)(`span`,{className:`stamp stamp-warn`,children:`Game data unavailable`}),V?.truncated&&(0,C.jsx)(`span`,{className:`stamp stamp-warn`,children:`Live data incomplete`})]}),I.length>1&&(0,C.jsx)(`div`,{className:`map-toggles map-layer-toggles`,role:`group`,"aria-label":`Map tile layer`,children:I.map(e=>(0,C.jsx)(w,{pressed:L.id===e.id,onClick:()=>j(e.id),children:e.label},e.id))})]}),u===`missing`&&(0,C.jsx)(`div`,{className:`map-empty-fill`,children:(0,C.jsxs)(ue,{icon:(0,C.jsx)(l,{}),title:`Map tiles not installed`,children:[(0,C.jsx)(`p`,{children:`Map tiles come from the game's own assets, which Palhelm can't ship (they're Pocketpair's). Generate them once from your server's install:`}),(0,C.jsx)(de,{children:P.data?.mapTilesCommand??`docker compose exec palhelm palhelm fetch-map-tiles`})]})}),Z&&m&&(0,C.jsxs)(C.Fragment,{children:[(0,C.jsx)(`div`,{className:`map-layer`,style:{transform:`translate(${m.tx}px, ${m.ty}px) scale(${m.scale})`},"aria-hidden":`true`,children:u===`mockgrid`?(0,C.jsx)(`div`,{className:`map-grid`,style:{width:256,height:256}}):(0,C.jsx)(Pe,{layer:L,z:$e,onTileError:()=>d(`missing`)})}),o.Bases&&st.map(e=>(0,C.jsx)(Me,{group:e,selectedTargetKey:k,expanded:Re===e.key,onTarget:Y,onCluster:lt},e.key)),o.Players&&ct.map(e=>(0,C.jsx)(Me,{group:e,selectedTargetKey:k,expanded:Re===e.key,onTarget:Y,onCluster:lt},e.key)),o.Workers&&ut.map(e=>(0,C.jsx)(Ne,{group:e},e.key)),o.PalBoxes&&et.filter(e=>E(L,e.location.x,e.location.y)).map((e,t)=>{let n=T(L,e.location.x,e.location.y),r=X(n.x,n.y);return(0,C.jsxs)(`div`,{className:`marker marker-palbox`,style:{left:r.x,top:r.y},children:[(0,C.jsx)(`span`,{className:`marker-symbol`,children:(0,C.jsx)(te,{})}),(0,C.jsx)(`span`,{className:`chip`,children:e.guildName||`Palbox`})]},`${e.guildName??`palbox`}-${t}`)}),x&&pt&&(0,C.jsxs)(`div`,{className:`marker marker-coordinate`,style:{left:pt.x,top:pt.y},children:[(0,C.jsx)(`span`,{className:`coordinate-crosshair`,"aria-hidden":`true`}),(0,C.jsxs)(`span`,{className:`chip`,children:[x.x,`, `,x.y]})]}),(0,C.jsxs)(`div`,{className:`map-zoom`,children:[(0,C.jsx)(v,{label:`Zoom in`,side:`right`,children:(0,C.jsx)(`button`,{type:`button`,"aria-label":`Zoom in`,onClick:()=>B(1.5),children:(0,C.jsx)(a,{})})}),(0,C.jsx)(v,{label:`Zoom out`,side:`right`,children:(0,C.jsx)(`button`,{type:`button`,"aria-label":`Zoom out`,onClick:()=>B(1/1.5),children:(0,C.jsx)(ee,{})})}),(0,C.jsx)(v,{label:`Fit map`,side:`right`,children:(0,C.jsx)(`button`,{type:`button`,"aria-label":`Fit map`,onClick:qe,children:(0,C.jsx)(f,{})})})]}),(0,C.jsx)(`button`,{type:`button`,className:`map-coord`,disabled:!Q,onClick:at,children:Q?`${x?`Pinned`:`Cursor`} ${Q.x}, ${Q.y} · Copy link`:`Tap map to pin coordinates`})]})]})]}),G.available&&V&&(0,C.jsxs)(le,{children:[(0,C.jsx)(ce,{title:`Live base health`,hint:`save-linked workers`,children:(0,C.jsxs)(`span`,{className:`hint`,children:[V.diagnostics.unresolvedBasePals,` unresolved`]})}),(0,C.jsx)(se,{children:tt.length===0?(0,C.jsx)(`p`,{className:`hint`,children:`No live base workers loaded right now.`}):(0,C.jsx)(`div`,{className:`base-health-grid`,children:tt.map(e=>(0,C.jsxs)(`div`,{className:`base-health-item`,children:[(0,C.jsx)(`strong`,{children:e.name}),(0,C.jsxs)(`span`,{children:[e.members.length,` loaded · `,e.idle,` idle · `,e.lowHP,` low HP · `,e.incapacitated,` incapacitated`]})]},e.baseId))})})]})]})}function je(e){return e.type===`single`?e.member.value.kind:e.members[0].value.kind}function Me({group:e,selectedTargetKey:t,expanded:n,onTarget:r,onCluster:i}){let a=je(e),o=a===`player`?ne:p;if(e.type===`single`){let n=e.member.value;return(0,C.jsxs)(`button`,{type:`button`,className:`marker marker-action marker-${a}${t===n.key?` is-selected`:``}`,style:{left:e.x,top:e.y},title:`Focus ${n.label}`,onClick:()=>r(n),children:[(0,C.jsx)(`span`,{className:`marker-symbol`,children:(0,C.jsx)(o,{})}),(0,C.jsx)(`span`,{className:`chip`,children:n.label})]})}let s=a===`player`?`online players`:`bases`,c=e.members.map(({value:e})=>e.label);return(0,C.jsxs)(C.Fragment,{children:[(0,C.jsxs)(`button`,{type:`button`,className:`marker marker-action marker-${a} marker-cluster`,style:{left:e.x,top:e.y},"aria-label":`${e.members.length} nearby ${s}: ${c.join(`, `)}`,"aria-expanded":n,title:c.join(`, `),onClick:()=>i(e),children:[(0,C.jsxs)(`span`,{className:`marker-symbol`,children:[(0,C.jsx)(o,{}),(0,C.jsx)(`span`,{className:`marker-count`,children:e.members.length})]}),(0,C.jsxs)(`span`,{className:`chip`,children:[e.members.length,` nearby`]})]}),n&&(0,C.jsx)(`div`,{className:`marker-cluster-menu`,style:{left:e.x,top:e.y},role:`group`,"aria-label":`Choose one of ${e.members.length} nearby ${s}`,children:e.members.map(({value:e})=>{let t=_(e.location.x,e.location.y);return(0,C.jsxs)(`button`,{type:`button`,onClick:()=>r(e),children:[(0,C.jsx)(`span`,{children:e.label}),(0,C.jsxs)(`small`,{children:[t.x,`, `,t.y]})]},e.key)})})]})}function Ne({group:e}){if(e.type===`single`){let t=e.member.value,n=x(t);return(0,C.jsxs)(`div`,{className:`marker marker-worker${n?` danger`:``}`,style:{left:e.x,top:e.y},children:[(0,C.jsx)(`span`,{className:`marker-symbol`,children:(0,C.jsx)(d,{})}),(0,C.jsxs)(`span`,{className:`chip`,children:[t.name||t.characterId||`Pal`,` · `,t.activity]})]})}let{label:t,danger:n}=S(e.members.map(({value:e})=>e));return(0,C.jsxs)(`div`,{className:`marker marker-worker marker-cluster${n?` danger`:``}`,style:{left:e.x,top:e.y},"aria-label":t,children:[(0,C.jsxs)(`span`,{className:`marker-symbol`,children:[(0,C.jsx)(d,{}),(0,C.jsx)(`span`,{className:`marker-count`,children:e.members.length})]}),(0,C.jsx)(`span`,{className:`chip`,children:t})]})}function Pe({layer:e,z:t,onTileError:n}){let r=2**t,i=256/r,a=[];for(let o=0;ospan:last-child{flex-direction:column;min-width:0;display:flex}.map-search-results strong{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.map-search-results small{color:var(--ink-3)}.map-search-result-icon{width:24px;height:24px;color:var(--accent);flex:none;place-items:center;display:grid}.map-search-result-icon svg{width:18px;height:18px}.map-search-empty{color:var(--ink-3);font-size:var(--text-sm);padding:11px;display:block}.map-well{background:var(--bg);touch-action:none;overscroll-behavior:contain;flex:1;min-height:0;display:flex;position:relative;overflow:hidden}.map-well.pannable{cursor:grab}.map-well.pannable:active{cursor:grabbing}.map-layer{transform-origin:0 0;position:absolute;top:0;left:0}.map-layer img{image-rendering:auto;-webkit-user-select:none;user-select:none;-webkit-user-drag:none;display:block;position:absolute}.map-grid{background:linear-gradient(var(--chart-grid) 1px, transparent 1px), linear-gradient(90deg, var(--chart-grid) 1px, transparent 1px);border:1px solid var(--line);background-size:16px 16px;position:absolute;top:0;left:0}.map-overlays{z-index:2;flex-direction:column;align-items:flex-start;gap:8px;max-width:calc(100% - 24px);display:flex;position:absolute;top:12px;left:12px}.map-toggles{flex-wrap:wrap;gap:6px;max-width:100%;display:flex}.map-coord{z-index:2;font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-2);background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);font-variant-numeric:tabular-nums;cursor:pointer;padding:7px 12px;position:absolute;bottom:12px;right:12px}.map-coord:hover:not(:disabled){background:var(--surface-2)}.map-coord:disabled{cursor:default;color:var(--ink-3)}.map-zoom{z-index:2;border:1px solid var(--line);border-radius:var(--radius-ctl);background:var(--surface);flex-direction:column;display:flex;position:absolute;bottom:12px;left:12px;overflow:hidden}.map-zoom button{width:36px;height:36px;color:var(--ink-2);cursor:pointer;background:0 0;border:0;place-items:center;line-height:1;display:grid}.map-zoom button+button{border-top:1px solid var(--line)}.map-zoom button:hover{background:var(--surface-3)}.map-zoom button:focus-visible{z-index:1;outline:2px solid var(--accent);outline-offset:-2px;position:relative}.map-zoom svg{width:17px;height:17px}.marker{z-index:1;pointer-events:none;position:absolute;transform:translate(-50%,-50%)}.marker-action{pointer-events:auto;cursor:pointer;appearance:none;font:inherit;text-align:left;background:0 0;border:0;padding:0}.marker-action:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:var(--radius-ctl)}.marker-action:hover .chip{background:var(--surface-2)}.marker-player{align-items:center;gap:6px;display:flex}.marker-symbol{width:25px;height:25px;color:var(--ink-2);background:var(--surface);box-shadow:0 2px 5px color-mix(in srgb, var(--ink) 20%, transparent);border:1px solid;border-radius:7px;flex:none;place-items:center;display:grid}.marker-symbol svg{width:17px;height:17px}.marker-player .marker-symbol{color:var(--accent);border-radius:50%}.marker.is-selected .marker-symbol{box-shadow:0 0 0 3px var(--accent-soft), 0 0 0 5px var(--accent)}.marker-cluster{z-index:2}.marker-cluster .marker-symbol{width:31px;height:31px;position:relative}.marker-count{border:2px solid var(--surface);color:#fff;background:var(--accent);border-radius:999px;place-items:center;min-width:18px;height:18px;padding:0 4px;font-size:10px;font-weight:700;line-height:1;display:grid;position:absolute;top:-8px;right:-7px}.marker-base.marker-cluster .marker-count{background:var(--ink-2)}.marker-cluster-menu{z-index:4;background:var(--surface);border:1px solid var(--line-strong);border-radius:var(--radius-card);width:min(220px,100vw - 32px);max-height:180px;box-shadow:var(--shadow-pop);padding:4px;position:absolute;overflow-y:auto;transform:translate(-50%,24px)}.marker-cluster-menu button{border-radius:var(--radius-ctl);width:100%;color:var(--ink);cursor:pointer;text-align:left;background:0 0;border:0;justify-content:space-between;align-items:baseline;gap:8px;padding:7px 8px;display:flex}.marker-cluster-menu button:hover,.marker-cluster-menu button:focus-visible{background:var(--surface-2)}.marker-cluster-menu small{color:var(--ink-3);font-family:var(--font-mono);white-space:nowrap}.marker-player .chip{color:var(--ink);background:var(--surface);border:1px solid var(--line-strong);border-radius:var(--radius-ctl);white-space:nowrap;padding:2px 7px;font-size:11px;font-weight:500}.marker-base{align-items:center;gap:6px;display:flex}.marker-base .marker-symbol{color:var(--ink-2);background:color-mix(in srgb, var(--ink-2) 8%, var(--surface))}.marker-base .chip{color:var(--ink-2);background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);white-space:nowrap;padding:2px 7px;font-size:11px}.marker-travel{align-items:center;gap:6px;display:flex}.marker-travel .diamond{background:var(--ok);border:2px solid var(--surface);width:11px;height:11px;box-shadow:0 0 0 1px var(--ok);flex:none;transform:rotate(45deg)}.marker-travel .chip{color:var(--ok-ink);background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);white-space:nowrap;padding:2px 7px;font-size:11px}.marker-tower{align-items:center;gap:6px;display:flex}.marker-tower .tri{border-left:6px solid #0000;border-right:6px solid #0000;border-bottom:10px solid var(--danger);flex:none;width:0;height:0}.marker-tower .chip{color:var(--danger-ink);background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);white-space:nowrap;padding:2px 7px;font-size:11px}.marker-worker{align-items:center;gap:5px;display:flex}.marker-worker .marker-symbol{color:var(--ok);border-radius:50% 50% 45% 45%}.marker-worker .chip,.marker-palbox .chip{color:var(--ink);background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);white-space:nowrap;padding:2px 6px;font-size:10px}.marker-worker.danger .marker-symbol{color:var(--danger)}.marker-worker.danger .chip{color:var(--danger-ink);border-color:var(--danger)}.marker-worker.marker-cluster .marker-count{background:var(--ok)}.marker-worker.marker-cluster.danger .marker-count{background:var(--danger)}.marker-palbox{align-items:center;gap:5px;display:flex}.marker-palbox .marker-symbol{color:var(--accent)}.marker-coordinate{z-index:3;align-items:center;gap:6px;display:flex}.marker-coordinate .coordinate-crosshair{border:2px solid var(--danger);background:color-mix(in srgb, var(--danger) 12%, var(--surface));width:19px;height:19px;box-shadow:0 1px 4px color-mix(in srgb, var(--ink) 25%, transparent);border-radius:50%;position:relative}.marker-coordinate .coordinate-crosshair:before,.marker-coordinate .coordinate-crosshair:after{content:"";background:var(--danger);position:absolute}.marker-coordinate .coordinate-crosshair:before{width:1px;height:25px;top:-5px;left:7px}.marker-coordinate .coordinate-crosshair:after{width:25px;height:1px;top:7px;left:-5px}.marker-coordinate .chip{font:600 11px/1.2 var(--font-mono);color:var(--danger-ink);background:var(--surface);border:1px solid var(--danger);border-radius:var(--radius-ctl);white-space:nowrap;padding:3px 6px}.base-health-grid{gap:var(--space-2);grid-template-columns:repeat(auto-fit,minmax(230px,1fr));display:grid}.base-health-item{padding:var(--space-2);border:1px solid var(--line);border-radius:var(--radius-ctl);flex-direction:column;gap:3px;display:flex}.base-health-item span{color:var(--ink-2);font-size:var(--text-sm)}.map-empty-fill{margin:auto}@media (width<=900px){.map-card{height:75dvh;min-height:560px}.map-actionbar{flex-wrap:wrap}.map-search{flex-basis:100%}.map-action{flex:auto;justify-content:center}}@media (width<=600px){.map-card{height:78dvh;min-height:600px}.map-actionbar{gap:6px;padding:8px}.map-action{min-height:40px;font-size:var(--text-sm);padding-inline:9px}.map-overlays{max-width:calc(100% - 16px);top:8px;left:8px}.map-toggles{overscroll-behavior-x:contain;scrollbar-width:thin;flex-wrap:nowrap;padding-bottom:3px;overflow-x:auto}.map-zoom{flex-direction:row;bottom:8px;left:8px}.map-zoom button{width:44px;height:44px}.map-zoom button+button{border-top:0;border-left:1px solid var(--line)}.map-coord{text-align:center;min-height:40px;bottom:60px;left:8px;right:8px}.marker-player .chip,.marker-base .chip{text-overflow:ellipsis;max-width:125px;overflow:hidden}}
diff --git a/backend/internal/webdist/dist/assets/PalDetails-Bl23SosS.css b/backend/internal/webdist/dist/assets/PalDetails-Bl23SosS.css
new file mode 100644
index 0000000..0629fdb
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/PalDetails-Bl23SosS.css
@@ -0,0 +1 @@
+.pal-info-button{width:24px;height:24px;color:var(--ink-3);background:var(--surface-2);border:1px solid var(--line);cursor:pointer;border-radius:999px;flex:none;place-items:center;padding:0;display:inline-grid}.pal-info-button:hover,.pal-info-button.is-active{color:var(--accent-ink);border-color:color-mix(in srgb, var(--accent) 55%, transparent);background:var(--accent-soft)}.pal-info-button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}.pal-detail-panel{color:var(--ink-2);background:color-mix(in srgb, var(--surface-2) 76%, var(--accent-soft));border-top:1px solid var(--line);border-bottom:1px solid var(--line);flex-direction:column;gap:12px;padding:12px;display:flex}.pal-detail-facts{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px;display:grid}.pal-detail-fact,.pal-talent-box{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);min-width:0;padding:8px}.pal-detail-fact>span,.pal-talent-box>span{color:var(--ink-3);text-transform:uppercase;letter-spacing:var(--track-caps);font-size:10px;display:block}.pal-detail-fact strong{font-size:var(--text-xs);overflow-wrap:anywhere;margin-top:3px;display:block}.pal-detail-section h4{font-size:var(--text-xs);color:var(--ink-2);margin:0 0 6px}.pal-detail-section-source{color:var(--ink-3);margin-left:4px;font-size:10px;font-weight:400}.pal-talent-grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;display:grid}.pal-talent-box{text-align:center}.pal-talent-box strong{font-family:var(--font-mono);font-size:var(--text-md);margin-top:2px;display:block}.pal-skill-list{flex-wrap:wrap;gap:6px;display:flex}.pal-skill-list span{color:var(--ink-2);background:var(--surface);border:1px solid var(--line);border-radius:999px;padding:4px 7px;font-size:11px;line-height:1.2}.pal-detail-muted{color:var(--ink-3);font-size:var(--text-xs)}.pal-detail-identity{color:var(--ink-3);font-family:var(--font-mono);flex-wrap:wrap;justify-content:space-between;gap:6px 12px;font-size:10px;display:flex}.pal-work-grid{grid-template-columns:repeat(auto-fit,minmax(138px,1fr));gap:6px;display:grid}.pal-work-badge{--work-color:var(--ink-3);min-width:0;color:var(--ink-2);background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-ctl);grid-template-columns:28px minmax(0,1fr) auto;align-items:center;gap:7px;padding:6px 7px;display:grid}.pal-work-icon{width:28px;height:28px;color:var(--work-color);background:color-mix(in srgb, var(--work-color) 11%, var(--surface-2));border:1px solid color-mix(in srgb, var(--work-color) 28%, var(--line));border-radius:8px;place-items:center;display:inline-grid}.pal-work-name{min-width:0;font-size:11px;line-height:1.15}.pal-work-level{color:var(--work-color);font-family:var(--font-mono);font-variant-numeric:tabular-nums;white-space:nowrap;font-size:11px}.pal-work-badge.is-kindling{--work-color:#dc6a37}.pal-work-badge.is-watering{--work-color:#3e82c4}.pal-work-badge.is-planting,.pal-work-badge.is-farming{--work-color:#5f8c47}.pal-work-badge.is-electricity{--work-color:#b68a20}.pal-work-badge.is-handiwork,.pal-work-badge.is-transporting{--work-color:#8b6b4c}.pal-work-badge.is-gathering{--work-color:#7d7251}.pal-work-badge.is-lumbering{--work-color:#658052}.pal-work-badge.is-mining{--work-color:#657183}.pal-work-badge.is-medicine{--work-color:#8a5b91}.pal-work-badge.is-cooling{--work-color:#4f8f9f}@media (width<=520px){.pal-detail-facts{grid-template-columns:1fr}.pal-talent-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
diff --git a/backend/internal/webdist/dist/assets/PalDetails-Dl-UCtTN.js b/backend/internal/webdist/dist/assets/PalDetails-Dl-UCtTN.js
new file mode 100644
index 0000000..0c82380
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/PalDetails-Dl-UCtTN.js
@@ -0,0 +1 @@
+import{p as e,q as t}from"./icons-CpYMTu_k.js";import{u as n}from"./index-BpCavHBc.js";import{n as r,t as i}from"./PalStars-CiCl8RwT.js";function a(e){return e.replace(/^PassiveSkill_/i,``).replace(/_PAL$/i,``).replace(/_/g,` `).replace(/([a-z])([A-Z])/g,`$1 $2`).replace(/([A-Za-z])(\d+)/g,`$1 $2`).replace(/\bup\b/gi,`Up`).replace(/\bdown\b/gi,`Down`).replace(/\s+/g,` `).trim()}function o(e){return e.placement===`base`||e.baseId?e.baseId?`Base worker · ${e.baseId.slice(0,8)}`:`Base worker`:e.inParty?`Party slot ${(e.partySlot??0)+1}`:e.boxPage===null?`Placement unavailable`:`Box ${e.boxPage+1} · slot ${(e.boxSlot??0)+1}`}function s(e){return e===`male`?`Male ♂`:e===`female`?`Female ♀`:`Unknown`}var c=`2026-07-11T18:13:31.866Z`,l=[{name:`Palworld Save Pal`,version:`e46188978a13e74d84c9a1ce5569497ee0555cae`,url:`https://raw.githubusercontent.com/oMaN-Rod/palworld-save-pal/e46188978a13e74d84c9a1ce5569497ee0555cae/data/json/pals.json`,attribution:`Data extracted by oMaN-Rod/palworld-save-pal`},{name:`PalCalc`,version:`b5e13e90fedc2e95d54fa223da77be464c313001`,url:`https://raw.githubusercontent.com/tylercamp/palcalc/b5e13e90fedc2e95d54fa223da77be464c313001/PalCalc.Model/db.json`,attribution:`PalCalc © Tyler Camp, MIT; generated from Palworld game data`}],u={alpaca:[[`MonsterFarm`,`Farming`,2]],amaterasuwolf:[[`EmitFlame`,`Kindling`,3]],amaterasuwolf_dark:[[`EmitFlame`,`Kindling`,4]],amaterasuwolf_dark_quest_enemy:[[`EmitFlame`,`Kindling`,4]],amaterasuwolf_dark_quest_friend:[[`EmitFlame`,`Kindling`,4]],anubis:[[`Handcraft`,`Handiwork`,6],[`Mining`,`Mining`,6],[`Transport`,`Transporting`,4]],badcatgirl:[[`Handcraft`,`Handiwork`,4],[`Collection`,`Gathering`,4],[`Deforest`,`Lumbering`,2],[`Transport`,`Transporting`,3]],baphomet:[[`EmitFlame`,`Kindling`,3],[`Handcraft`,`Handiwork`,2],[`Mining`,`Mining`,3],[`Transport`,`Transporting`,2]],baphomet_dark:[[`Handcraft`,`Handiwork`,2],[`Mining`,`Mining`,1],[`Transport`,`Transporting`,2]],bastet:[[`Collection`,`Gathering`,1],[`MonsterFarm`,`Farming`,1]],bastet_ice:[[`Cool`,`Cooling`,1],[`MonsterFarm`,`Farming`,1]],berrygoat:[[`Seeding`,`Planting`,2],[`MonsterFarm`,`Farming`,1]],berrygoat_dark:[[`Seeding`,`Planting`,2],[`MonsterFarm`,`Farming`,1]],birddragon:[[`EmitFlame`,`Kindling`,2],[`Transport`,`Transporting`,3]],birddragon_ice:[[`Cool`,`Cooling`,2],[`Transport`,`Transporting`,3]],blackcentaur:[[`Deforest`,`Lumbering`,6],[`Mining`,`Mining`,6]],blackfurdragon:[],blackgriffon:[[`Collection`,`Gathering`,1]],blackmetaldragon:[[`Handcraft`,`Handiwork`,3],[`Mining`,`Mining`,7]],blackpuppy:[[`Collection`,`Gathering`,2]],blackpuppy_ice:[[`Collection`,`Gathering`,2],[`Cool`,`Cooling`,2]],blueberryfairy:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,2],[`ProductMedicine`,`Medicine Production`,3],[`Transport`,`Transporting`,1]],bluedragon:[[`Watering`,`Watering`,4]],bluedragon_ice:[[`Cool`,`Cooling`,4]],blueplatypus:[[`Watering`,`Watering`,1],[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1]],blueplatypus_fire:[[`EmitFlame`,`Kindling`,2],[`Watering`,`Watering`,2],[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1]],blueskydragon:[[`Watering`,`Watering`,8],[`Collection`,`Gathering`,5]],bluethunderhorse:[[`GenerateElectricity`,`Generating Electricity`,5]],boar:[[`Mining`,`Mining`,1]],brownrabbit:[[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,4],[`Mining`,`Mining`,2],[`Transport`,`Transporting`,1]],cactusdoll:[[`Seeding`,`Planting`,3],[`Collection`,`Gathering`,3],[`Transport`,`Transporting`,1]],cactusdoll_dark:[[`Seeding`,`Planting`,3],[`Collection`,`Gathering`,3],[`Transport`,`Transporting`,1]],candleghost:[[`EmitFlame`,`Kindling`,3],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,2],[`Mining`,`Mining`,3],[`MonsterFarm`,`Farming`,2]],captainpenguin:[[`Watering`,`Watering`,2],[`Handcraft`,`Handiwork`,2],[`Mining`,`Mining`,3],[`Cool`,`Cooling`,2],[`Transport`,`Transporting`,3]],captainpenguin_black:[[`Watering`,`Watering`,2],[`GenerateElectricity`,`Generating Electricity`,3],[`Handcraft`,`Handiwork`,2],[`Mining`,`Mining`,3],[`Transport`,`Transporting`,3]],carbunclo:[[`Seeding`,`Planting`,1],[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Deforest`,`Lumbering`,1],[`ProductMedicine`,`Medicine Production`,1]],catbat:[[`Collection`,`Gathering`,2],[`Mining`,`Mining`,3],[`Transport`,`Transporting`,2]],catmage:[[`Handcraft`,`Handiwork`,3],[`ProductMedicine`,`Medicine Production`,3],[`Transport`,`Transporting`,2]],catmage_fire:[[`EmitFlame`,`Kindling`,3],[`Handcraft`,`Handiwork`,3],[`ProductMedicine`,`Medicine Production`,3],[`Transport`,`Transporting`,2]],catvampire:[[`ProductMedicine`,`Medicine Production`,3]],chickenpal:[[`Collection`,`Gathering`,1],[`MonsterFarm`,`Farming`,1]],clionetwins:[[`Watering`,`Watering`,1],[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,1]],cloverfairy:[[`Seeding`,`Planting`,1],[`Collection`,`Gathering`,1]],clownrabbit:[[`EmitFlame`,`Kindling`,7],[`Handcraft`,`Handiwork`,5],[`ProductMedicine`,`Medicine Production`,4],[`Transport`,`Transporting`,2]],colorfulbird:[[`Collection`,`Gathering`,1]],cowpal:[[`MonsterFarm`,`Farming`,2]],cubeturtle:[[`Mining`,`Mining`,4]],cubeturtle_neutral:[[`Mining`,`Mining`,6]],cutebutterfly:[[`Seeding`,`Planting`,2],[`Collection`,`Gathering`,2],[`ProductMedicine`,`Medicine Production`,2]],cutefox:[[`Collection`,`Gathering`,1],[`MonsterFarm`,`Farming`,1]],cutemole:[[`Handcraft`,`Handiwork`,1],[`Mining`,`Mining`,1],[`Transport`,`Transporting`,1]],dandeliongirl:[[`Seeding`,`Planting`,2],[`Transport`,`Transporting`,2]],darkalien:[[`Deforest`,`Lumbering`,2],[`Transport`,`Transporting`,2]],darkcrow:[[`Deforest`,`Lumbering`,2],[`MonsterFarm`,`Farming`,1]],darkflamefox:[[`EmitFlame`,`Kindling`,4],[`Handcraft`,`Handiwork`,5],[`ProductMedicine`,`Medicine Production`,3],[`Transport`,`Transporting`,2]],darkmechadragon:[[`Collection`,`Gathering`,1]],darkmutant:[],darkscorpion:[[`Deforest`,`Lumbering`,3],[`Mining`,`Mining`,5]],darkscorpion_ground:[[`Deforest`,`Lumbering`,3],[`Mining`,`Mining`,6]],deer:[[`Deforest`,`Lumbering`,2]],deer_ground:[[`Deforest`,`Lumbering`,2]],domearmordragon:[[`Mining`,`Mining`,8]],dreamdemon:[[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,1]],drillgame:[[`Mining`,`Mining`,4]],eagle:[[`Collection`,`Gathering`,2]],eleccat:[[`GenerateElectricity`,`Generating Electricity`,1],[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1],[`MonsterFarm`,`Farming`,1]],eleclizard:[[`GenerateElectricity`,`Generating Electricity`,3]],elecpanda:[[`GenerateElectricity`,`Generating Electricity`,5],[`Handcraft`,`Handiwork`,4],[`Deforest`,`Lumbering`,3],[`Transport`,`Transporting`,5]],elecpomeranian:[[`GenerateElectricity`,`Generating Electricity`,2],[`Transport`,`Transporting`,1]],elecsnail:[[`GenerateElectricity`,`Generating Electricity`,4]],elecsnail_ground:[[`GenerateElectricity`,`Generating Electricity`,4]],fairydragon:[[`Deforest`,`Lumbering`,3]],fairydragon_water:[[`Watering`,`Watering`,4],[`Deforest`,`Lumbering`,3]],featherostrich:[[`Collection`,`Gathering`,2]],fengyundeeper:[[`Deforest`,`Lumbering`,3]],fengyundeeper_electric:[[`GenerateElectricity`,`Generating Electricity`,5],[`Deforest`,`Lumbering`,4]],firekirin:[[`EmitFlame`,`Kindling`,4],[`Deforest`,`Lumbering`,2]],firekirin_dark:[[`EmitFlame`,`Kindling`,4],[`Deforest`,`Lumbering`,3]],flamebambi:[[`EmitFlame`,`Kindling`,1],[`MonsterFarm`,`Farming`,1]],flamebuffalo:[[`EmitFlame`,`Kindling`,3],[`Deforest`,`Lumbering`,2]],flowerdinosaur:[[`Seeding`,`Planting`,3],[`Deforest`,`Lumbering`,3]],flowerdinosaur_electric:[[`GenerateElectricity`,`Generating Electricity`,3],[`Deforest`,`Lumbering`,4]],flowerdoll:[[`Seeding`,`Planting`,4],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`ProductMedicine`,`Medicine Production`,4],[`Transport`,`Transporting`,2]],flowerdoll_fire:[[`EmitFlame`,`Kindling`,4],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`ProductMedicine`,`Medicine Production`,4],[`Transport`,`Transporting`,2]],flowerprince:[[`Seeding`,`Planting`,8],[`Handcraft`,`Handiwork`,6],[`Collection`,`Gathering`,5],[`ProductMedicine`,`Medicine Production`,6],[`Transport`,`Transporting`,3]],flowerrabbit:[[`Seeding`,`Planting`,1],[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`ProductMedicine`,`Medicine Production`,1],[`Transport`,`Transporting`,1]],fluffybird:[[`Cool`,`Cooling`,2],[`Transport`,`Transporting`,1]],flyingmanta:[[`Watering`,`Watering`,1],[`Transport`,`Transporting`,1]],flyingmanta_thunder:[[`Watering`,`Watering`,1],[`GenerateElectricity`,`Generating Electricity`,2],[`Transport`,`Transporting`,1]],foxexorcist:[[`EmitFlame`,`Kindling`,7],[`Handcraft`,`Handiwork`,6],[`Transport`,`Transporting`,2]],foxmage:[[`EmitFlame`,`Kindling`,3],[`Handcraft`,`Handiwork`,3],[`Transport`,`Transporting`,2]],foxmage_dark:[[`EmitFlame`,`Kindling`,4],[`Handcraft`,`Handiwork`,4],[`Transport`,`Transporting`,2]],ganesha:[[`Watering`,`Watering`,1]],garm:[[`Collection`,`Gathering`,1]],ghostanglerfish:[[`Watering`,`Watering`,5],[`Transport`,`Transporting`,2]],ghostanglerfish_fire:[[`EmitFlame`,`Kindling`,5],[`Watering`,`Watering`,5],[`Transport`,`Transporting`,2]],ghostbeast:[[`Collection`,`Gathering`,4],[`Mining`,`Mining`,4]],ghostblackcat:[[`Handcraft`,`Handiwork`,2],[`Deforest`,`Lumbering`,1],[`ProductMedicine`,`Medicine Production`,1],[`Transport`,`Transporting`,1]],ghostdragon:[[`Transport`,`Transporting`,6]],ghostdragon_fire:[[`EmitFlame`,`Kindling`,6],[`Transport`,`Transporting`,6]],ghostrabbit:[[`Handcraft`,`Handiwork`,4],[`Transport`,`Transporting`,2]],ghostrabbit_grass:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,4],[`Transport`,`Transporting`,2]],goldenhorse:[[`Collection`,`Gathering`,5]],gorilla:[[`Handcraft`,`Handiwork`,2],[`Deforest`,`Lumbering`,3],[`Transport`,`Transporting`,3]],gorilla_ground:[[`Handcraft`,`Handiwork`,2],[`Mining`,`Mining`,3],[`Transport`,`Transporting`,3]],grassgolem:[[`Seeding`,`Planting`,3],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,5],[`Mining`,`Mining`,6],[`Transport`,`Transporting`,6]],grassgolem_dark:[[`Seeding`,`Planting`,3],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,5],[`Mining`,`Mining`,6],[`Transport`,`Transporting`,6]],grassmammoth:[[`Seeding`,`Planting`,4],[`Deforest`,`Lumbering`,4],[`Mining`,`Mining`,4]],grassmammoth_ice:[[`Deforest`,`Lumbering`,5],[`Mining`,`Mining`,4],[`Cool`,`Cooling`,5]],grassminotaur:[[`Seeding`,`Planting`,3],[`Collection`,`Gathering`,2],[`Deforest`,`Lumbering`,3],[`Mining`,`Mining`,2],[`Transport`,`Transporting`,3]],grassminotaur_ice:[[`Deforest`,`Lumbering`,3],[`Mining`,`Mining`,3],[`Cool`,`Cooling`,5],[`Transport`,`Transporting`,3]],grasspanda:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,2],[`Deforest`,`Lumbering`,4],[`Transport`,`Transporting`,4]],grasspanda_electric:[[`GenerateElectricity`,`Generating Electricity`,4],[`Handcraft`,`Handiwork`,3],[`Deforest`,`Lumbering`,4],[`Transport`,`Transporting`,4]],grassrabbitman:[[`Seeding`,`Planting`,4],[`Handcraft`,`Handiwork`,5],[`Collection`,`Gathering`,5],[`Deforest`,`Lumbering`,3],[`Transport`,`Transporting`,3]],grimgirl:[[`Handcraft`,`Handiwork`,6],[`Deforest`,`Lumbering`,3],[`ProductMedicine`,`Medicine Production`,5],[`Transport`,`Transporting`,2]],guardiandog:[[`Collection`,`Gathering`,2]],hadesbird:[[`Transport`,`Transporting`,3]],hadesbird_electric:[[`GenerateElectricity`,`Generating Electricity`,3],[`Transport`,`Transporting`,3]],hawkbird:[[`Collection`,`Gathering`,2]],hedgehog:[[`GenerateElectricity`,`Generating Electricity`,1]],hedgehog_ice:[[`Cool`,`Cooling`,1]],herculesbeetle:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,3],[`Deforest`,`Lumbering`,4],[`Transport`,`Transporting`,5]],herculesbeetle_ground:[[`Handcraft`,`Handiwork`,2],[`Mining`,`Mining`,5],[`Transport`,`Transporting`,5]],hoodghost:[[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1]],horus:[[`EmitFlame`,`Kindling`,3],[`Transport`,`Transporting`,3]],horus_water:[[`Watering`,`Watering`,6],[`Transport`,`Transporting`,5]],icecrocodile:[[`Watering`,`Watering`,2],[`Cool`,`Cooling`,3],[`Transport`,`Transporting`,1]],icedeer:[[`Deforest`,`Lumbering`,3],[`Cool`,`Cooling`,3]],icefox:[[`Cool`,`Cooling`,4],[`MonsterFarm`,`Farming`,3]],icehorse:[[`Cool`,`Cooling`,7]],icehorse_dark:[[`Collection`,`Gathering`,7]],icenarwhal:[[`Watering`,`Watering`,5],[`Cool`,`Cooling`,6]],icenarwhal_fire:[[`EmitFlame`,`Kindling`,5],[`Cool`,`Cooling`,6]],iceseal:[[`Watering`,`Watering`,3],[`Cool`,`Cooling`,4]],iceseal_ground:[[`Mining`,`Mining`,4],[`Cool`,`Cooling`,4]],icewitch:[[`Handcraft`,`Handiwork`,5],[`ProductMedicine`,`Medicine Production`,4],[`Cool`,`Cooling`,5],[`Transport`,`Transporting`,2]],jellyfishfairy:[[`Watering`,`Watering`,2],[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1]],jellyfishghost:[[`Watering`,`Watering`,2],[`Handcraft`,`Handiwork`,1],[`ProductMedicine`,`Medicine Production`,1],[`Transport`,`Transporting`,1]],jetdragon:[[`Collection`,`Gathering`,8]],kabukiman:[[`EmitFlame`,`Kindling`,8],[`Handcraft`,`Handiwork`,6],[`Collection`,`Gathering`,5],[`Transport`,`Transporting`,5]],kelpie:[[`Watering`,`Watering`,1],[`MonsterFarm`,`Farming`,1]],kelpie_fire:[[`EmitFlame`,`Kindling`,1],[`MonsterFarm`,`Farming`,1]],kendofrog:[[`Watering`,`Watering`,1],[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,1]],kendofrog_dark:[[`Watering`,`Watering`,1],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,1]],kingalpaca:[[`Collection`,`Gathering`,2]],kingalpaca_ice:[[`Collection`,`Gathering`,2],[`Cool`,`Cooling`,4]],kingbahamut:[[`EmitFlame`,`Kindling`,6],[`Mining`,`Mining`,7]],kingbahamut_dragon:[[`Mining`,`Mining`,4]],kingsunfish:[[`Watering`,`Watering`,4]],kingsunfish_thunder:[[`Watering`,`Watering`,4],[`GenerateElectricity`,`Generating Electricity`,6]],kingwhale:[],kirin:[[`GenerateElectricity`,`Generating Electricity`,3],[`Deforest`,`Lumbering`,1]],kirin_ice:[[`Deforest`,`Lumbering`,3],[`Cool`,`Cooling`,6]],kitsunebi:[[`EmitFlame`,`Kindling`,1]],kitsunebi_ice:[[`Cool`,`Cooling`,2]],lanternbutler:[[`EmitFlame`,`Kindling`,4],[`Handcraft`,`Handiwork`,4],[`ProductMedicine`,`Medicine Production`,4]],lavagirl:[[`EmitFlame`,`Kindling`,1],[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1],[`MonsterFarm`,`Farming`,1]],lazycatfish:[[`Watering`,`Watering`,2],[`Mining`,`Mining`,2],[`Transport`,`Transporting`,1],[`MonsterFarm`,`Farming`,1]],lazycatfish_gold:[[`Watering`,`Watering`,2],[`Mining`,`Mining`,2],[`Transport`,`Transporting`,1],[`MonsterFarm`,`Farming`,4]],lazydragon:[[`Watering`,`Watering`,3],[`Transport`,`Transporting`,3]],lazydragon_electric:[[`GenerateElectricity`,`Generating Electricity`,6],[`Transport`,`Transporting`,4]],leafmomonga:[[`Seeding`,`Planting`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,1]],leafprincess:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,2],[`ProductMedicine`,`Medicine Production`,3]],legenddeer:[[`Collection`,`Gathering`,1]],lilyqueen:[[`Seeding`,`Planting`,7],[`Handcraft`,`Handiwork`,5],[`Collection`,`Gathering`,6],[`ProductMedicine`,`Medicine Production`,5]],lilyqueen_dark:[[`Handcraft`,`Handiwork`,5],[`Collection`,`Gathering`,6],[`ProductMedicine`,`Medicine Production`,7]],littlebriarrose:[[`Seeding`,`Planting`,2],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,2],[`ProductMedicine`,`Medicine Production`,2],[`Transport`,`Transporting`,1]],lizardman:[[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,1]],lizardman_fire:[[`EmitFlame`,`Kindling`,2],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,1]],longcat:[[`Collection`,`Gathering`,2]],lotusdragon:[[`Watering`,`Watering`,5],[`Seeding`,`Planting`,7]],manticore:[[`EmitFlame`,`Kindling`,5],[`Deforest`,`Lumbering`,3]],manticore_dark:[[`EmitFlame`,`Kindling`,5],[`Deforest`,`Lumbering`,3]],mimicdog:[[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,2]],monkey:[[`Seeding`,`Planting`,1],[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Deforest`,`Lumbering`,1],[`Transport`,`Transporting`,1]],monkey_fire:[[`EmitFlame`,`Kindling`,1],[`Handcraft`,`Handiwork`,1],[`Deforest`,`Lumbering`,1],[`Transport`,`Transporting`,1]],monochromequeen:[[`Handcraft`,`Handiwork`,8],[`Collection`,`Gathering`,4],[`Transport`,`Transporting`,2]],moonchild:[[`Handcraft`,`Handiwork`,6],[`ProductMedicine`,`Medicine Production`,6],[`Transport`,`Transporting`,1]],moonqueen:[[`Handcraft`,`Handiwork`,7],[`ProductMedicine`,`Medicine Production`,6],[`Transport`,`Transporting`,3]],mopbaby:[[`Collection`,`Gathering`,1],[`Cool`,`Cooling`,1]],mopking:[[`Collection`,`Gathering`,2],[`Cool`,`Cooling`,3]],mothman:[[`Seeding`,`Planting`,6],[`Handcraft`,`Handiwork`,6],[`Collection`,`Gathering`,4],[`ProductMedicine`,`Medicine Production`,8],[`Transport`,`Transporting`,2]],mummypal:[[`Handcraft`,`Handiwork`,5],[`ProductMedicine`,`Medicine Production`,4],[`Transport`,`Transporting`,2]],mushroomdragon:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,2],[`MonsterFarm`,`Farming`,3]],mushroomdragon_dark:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,2]],mushroomlady:[[`Seeding`,`Planting`,6],[`Handcraft`,`Handiwork`,4],[`Collection`,`Gathering`,4],[`ProductMedicine`,`Medicine Production`,6]],mutant:[[`Handcraft`,`Handiwork`,4],[`Collection`,`Gathering`,2],[`Transport`,`Transporting`,2]],mysterymask:[[`Collection`,`Gathering`,5]],naughtycat:[[`Collection`,`Gathering`,3]],negativekoala:[[`Handcraft`,`Handiwork`,1],[`Mining`,`Mining`,1],[`Transport`,`Transporting`,1],[`MonsterFarm`,`Farming`,1]],negativeoctopus:[[`Watering`,`Watering`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,2]],negativeoctopus_neutral:[[`Watering`,`Watering`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,2]],nightbluehorse:[[`Collection`,`Gathering`,5]],nightbluehorse_neutral:[[`Collection`,`Gathering`,7]],nightfox:[[`Collection`,`Gathering`,1]],nightlady:[[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,2]],nightlady_dark:[[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,2]],octopusgirl:[[`Watering`,`Watering`,2],[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,2]],octopusgirl_neutral:[[`Watering`,`Watering`,2],[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,2]],onighostgirl:[[`Handcraft`,`Handiwork`,3],[`ProductMedicine`,`Medicine Production`,4],[`Transport`,`Transporting`,2]],pandagirl:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`Transport`,`Transporting`,2]],penguin:[[`Watering`,`Watering`,1],[`Handcraft`,`Handiwork`,1],[`Cool`,`Cooling`,1],[`Transport`,`Transporting`,1]],penguin_electric:[[`Watering`,`Watering`,1],[`GenerateElectricity`,`Generating Electricity`,2],[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1]],pinkcat:[[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Mining`,`Mining`,1],[`Transport`,`Transporting`,1]],pinklizard:[[`Handcraft`,`Handiwork`,3],[`Mining`,`Mining`,2],[`ProductMedicine`,`Medicine Production`,3],[`Transport`,`Transporting`,2]],pinkrabbit:[[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,1]],pinkrabbit_grass:[[`Seeding`,`Planting`,2],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,2],[`Transport`,`Transporting`,1]],plantslime:[[`Seeding`,`Planting`,1]],plantslime_flower:[[`Seeding`,`Planting`,1]],plesiosaur:[[`Seeding`,`Planting`,5],[`Collection`,`Gathering`,5],[`Mining`,`Mining`,3]],police_hawkbird:[[`Collection`,`Gathering`,2]],police_thunderdog:[[`GenerateElectricity`,`Generating Electricity`,4]],poseidonorca:[[`Watering`,`Watering`,7]],predator_flowerrabbit_quest:[[`Seeding`,`Planting`,1],[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`ProductMedicine`,`Medicine Production`,1],[`Transport`,`Transporting`,1]],purplespider:[[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`ProductMedicine`,`Medicine Production`,2],[`Transport`,`Transporting`,2]],queenbee:[[`Seeding`,`Planting`,4],[`Handcraft`,`Handiwork`,4],[`Collection`,`Gathering`,4],[`Deforest`,`Lumbering`,3],[`ProductMedicine`,`Medicine Production`,4]],raijindaughter:[[`GenerateElectricity`,`Generating Electricity`,3],[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,2]],raijindaughter_water:[[`GenerateElectricity`,`Generating Electricity`,1],[`Handcraft`,`Handiwork`,1],[`ProductMedicine`,`Medicine Production`,1],[`Transport`,`Transporting`,2]],redarmorbird:[[`EmitFlame`,`Kindling`,4],[`Transport`,`Transporting`,5]],redflowerbird:[[`Seeding`,`Planting`,5],[`Collection`,`Gathering`,5]],robinhood:[[`Seeding`,`Planting`,2],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,2],[`ProductMedicine`,`Medicine Production`,1],[`Transport`,`Transporting`,2]],robinhood_ground:[[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,2],[`ProductMedicine`,`Medicine Production`,2],[`Transport`,`Transporting`,2]],rockbeast:[[`Mining`,`Mining`,5]],rockbeast_ice:[[`Mining`,`Mining`,5],[`Cool`,`Cooling`,6]],ronin:[[`EmitFlame`,`Kindling`,2],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,1],[`Deforest`,`Lumbering`,3],[`Transport`,`Transporting`,2]],ronin_dark:[[`EmitFlame`,`Kindling`,2],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,1],[`Deforest`,`Lumbering`,5],[`Transport`,`Transporting`,2]],saintcentaur:[[`Deforest`,`Lumbering`,6],[`Mining`,`Mining`,6]],sakurasaurus:[[`Seeding`,`Planting`,5]],sakurasaurus_water:[[`Watering`,`Watering`,5]],samuraidog:[[`Collection`,`Gathering`,1],[`Deforest`,`Lumbering`,1],[`Transport`,`Transporting`,1]],scorpionman:[[`Collection`,`Gathering`,2],[`Deforest`,`Lumbering`,4],[`ProductMedicine`,`Medicine Production`,2]],scorpionman_electric:[[`GenerateElectricity`,`Generating Electricity`,3],[`Collection`,`Gathering`,2],[`Deforest`,`Lumbering`,4],[`ProductMedicine`,`Medicine Production`,2]],sekhmet:[[`Handcraft`,`Handiwork`,6],[`Mining`,`Mining`,3],[`Transport`,`Transporting`,2]],serpent:[[`Watering`,`Watering`,3],[`MonsterFarm`,`Farming`,2]],serpent_ground:[[`Collection`,`Gathering`,3]],sharkkid:[[`Watering`,`Watering`,2],[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,1]],sharkkid_fire:[[`EmitFlame`,`Kindling`,2],[`Handcraft`,`Handiwork`,2],[`Transport`,`Transporting`,1]],sheepball:[[`Handcraft`,`Handiwork`,1],[`Transport`,`Transporting`,1],[`MonsterFarm`,`Farming`,1]],sifudog:[[`Handcraft`,`Handiwork`,4],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,3],[`ProductMedicine`,`Medicine Production`,2],[`Transport`,`Transporting`,3]],skydragon:[[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,3],[`Mining`,`Mining`,4],[`Transport`,`Transporting`,5]],skydragon_grass:[[`Seeding`,`Planting`,5],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,4],[`Mining`,`Mining`,3],[`Transport`,`Transporting`,4]],sleeverabbit:[[`Handcraft`,`Handiwork`,6],[`Collection`,`Gathering`,5]],smallarmadillo:[[`Mining`,`Mining`,1]],smallyeti:[[`Handcraft`,`Handiwork`,2],[`Mining`,`Mining`,3],[`Cool`,`Cooling`,3],[`Transport`,`Transporting`,2]],snakegirl:[[`Handcraft`,`Handiwork`,6],[`Collection`,`Gathering`,6],[`ProductMedicine`,`Medicine Production`,5],[`Transport`,`Transporting`,2]],snowpeafowl:[[`Collection`,`Gathering`,2],[`Cool`,`Cooling`,4]],snowtigerbeastman:[[`Deforest`,`Lumbering`,6],[`Mining`,`Mining`,5],[`Cool`,`Cooling`,8]],soldierbee:[[`Seeding`,`Planting`,2],[`Handcraft`,`Handiwork`,2],[`Collection`,`Gathering`,3],[`Deforest`,`Lumbering`,2],[`ProductMedicine`,`Medicine Production`,2],[`Transport`,`Transporting`,2],[`MonsterFarm`,`Farming`,3]],stuffedshark:[[`Watering`,`Watering`,2],[`Transport`,`Transporting`,1]],stuffedshark_fire:[[`EmitFlame`,`Kindling`,2],[`Watering`,`Watering`,2],[`Transport`,`Transporting`,1]],sumodog:[[`Mining`,`Mining`,4],[`Transport`,`Transporting`,3]],suzaku:[[`EmitFlame`,`Kindling`,5]],suzaku_water:[[`Watering`,`Watering`,6]],sweetssheep:[[`MonsterFarm`,`Farming`,1]],sweetssheep_ground:[[`MonsterFarm`,`Farming`,1]],swordcutlassfish:[[`Watering`,`Watering`,4],[`Collection`,`Gathering`,1],[`Deforest`,`Lumbering`,4]],swordcutlassfish_fire:[[`EmitFlame`,`Kindling`,3],[`Watering`,`Watering`,2],[`Collection`,`Gathering`,2],[`Deforest`,`Lumbering`,3]],tentacleturtle:[[`Watering`,`Watering`,2],[`Mining`,`Mining`,1],[`Transport`,`Transporting`,1]],tentacleturtle_ground:[[`Watering`,`Watering`,2],[`Mining`,`Mining`,3],[`Transport`,`Transporting`,1]],thiefbird:[[`Collection`,`Gathering`,5],[`Transport`,`Transporting`,5]],thunderbird:[[`GenerateElectricity`,`Generating Electricity`,4],[`Collection`,`Gathering`,2],[`Transport`,`Transporting`,5]],thunderbird_ice:[[`Collection`,`Gathering`,2],[`Cool`,`Cooling`,5],[`Transport`,`Transporting`,5]],thunderdog:[[`GenerateElectricity`,`Generating Electricity`,4]],thunderdog_ice:[[`Cool`,`Cooling`,3]],thunderdragonman:[[`GenerateElectricity`,`Generating Electricity`,8],[`Handcraft`,`Handiwork`,3],[`Transport`,`Transporting`,4]],thunderfluffybird:[[`GenerateElectricity`,`Generating Electricity`,6],[`Collection`,`Gathering`,3],[`Transport`,`Transporting`,3]],tropicalostrich:[[`Seeding`,`Planting`,4],[`Collection`,`Gathering`,4],[`Mining`,`Mining`,5]],umihebi:[[`Watering`,`Watering`,7]],umihebi_fire:[[`EmitFlame`,`Kindling`,7]],venusflytrap:[[`Seeding`,`Planting`,6],[`Handcraft`,`Handiwork`,4],[`Collection`,`Gathering`,4],[`Transport`,`Transporting`,2]],violetfairy:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,3],[`ProductMedicine`,`Medicine Production`,3],[`Transport`,`Transporting`,2],[`MonsterFarm`,`Farming`,2]],volcanicmonster:[[`EmitFlame`,`Kindling`,5],[`Mining`,`Mining`,5]],volcanicmonster_ice:[[`Mining`,`Mining`,5],[`Cool`,`Cooling`,5]],volcanodragon:[[`EmitFlame`,`Kindling`,5],[`Mining`,`Mining`,5]],volcanodragon_ice:[[`Mining`,`Mining`,5],[`Cool`,`Cooling`,5]],weaseldragon:[[`Collection`,`Gathering`,1],[`Cool`,`Cooling`,2]],weaseldragon_fire:[[`EmitFlame`,`Kindling`,4],[`Collection`,`Gathering`,3]],werewolf:[[`Handcraft`,`Handiwork`,2]],werewolf_ice:[[`Handcraft`,`Handiwork`,4],[`Cool`,`Cooling`,4]],whitealiendragon:[[`Mining`,`Mining`,4]],whitedeer:[[`Collection`,`Gathering`,4],[`Deforest`,`Lumbering`,7]],whitedeer_dark:[[`Collection`,`Gathering`,4],[`Deforest`,`Lumbering`,8]],whitemoth:[[`ProductMedicine`,`Medicine Production`,3],[`Cool`,`Cooling`,3],[`MonsterFarm`,`Farming`,3]],whitemoth_neutral:[[`ProductMedicine`,`Medicine Production`,3],[`MonsterFarm`,`Farming`,4]],whiteshielddragon:[[`Deforest`,`Lumbering`,6]],whitetiger:[[`Handcraft`,`Handiwork`,3],[`Deforest`,`Lumbering`,4],[`Cool`,`Cooling`,4],[`Transport`,`Transporting`,4]],whitetiger_ground:[[`Handcraft`,`Handiwork`,2],[`Deforest`,`Lumbering`,6],[`Mining`,`Mining`,5],[`Transport`,`Transporting`,4]],windchimes:[[`Handcraft`,`Handiwork`,1],[`Collection`,`Gathering`,1],[`Transport`,`Transporting`,2]],windchimes_ice:[[`Handcraft`,`Handiwork`,3],[`Collection`,`Gathering`,2],[`Cool`,`Cooling`,2],[`Transport`,`Transporting`,3]],winggolem:[[`Collection`,`Gathering`,3],[`Mining`,`Mining`,4],[`Transport`,`Transporting`,4]],winggolem_fire:[[`EmitFlame`,`Kindling`,5],[`Mining`,`Mining`,7],[`Transport`,`Transporting`,7]],wizardowl:[[`Collection`,`Gathering`,1]],woolfox:[[`Collection`,`Gathering`,1],[`MonsterFarm`,`Farming`,2]],yakushimaboss001:[[`Transport`,`Transporting`,4]],yakushimaboss001_small:[[`Transport`,`Transporting`,1]],yakushimamonster001:[[`Transport`,`Transporting`,1]],yakushimamonster001_blue:[[`Transport`,`Transporting`,1]],yakushimamonster001_pink:[[`Transport`,`Transporting`,1]],yakushimamonster001_purple:[[`Transport`,`Transporting`,1]],yakushimamonster001_rainbow:[[`Transport`,`Transporting`,1]],yakushimamonster001_red:[[`Transport`,`Transporting`,1]],yakushimamonster002:[[`Deforest`,`Lumbering`,1]],yakushimamonster003:[[`Collection`,`Gathering`,1]],yakushimamonster003_purple:[[`Collection`,`Gathering`,1]],yeti:[[`Handcraft`,`Handiwork`,3],[`Deforest`,`Lumbering`,5],[`Cool`,`Cooling`,5],[`Transport`,`Transporting`,6]],yeti_grass:[[`Seeding`,`Planting`,3],[`Handcraft`,`Handiwork`,3],[`Deforest`,`Lumbering`,5],[`Transport`,`Transporting`,6]]},d=[`kindling`,`watering`,`planting`,`electricity`,`handiwork`,`gathering`,`lumbering`,`mining`,`medicine`,`cooling`,`transporting`,`farming`,`unknown`],f=new Map(Object.entries(u).map(([e,t])=>[e,t.map(([e,t,n])=>({id:e,name:t,level:n}))])),p=[`Version-pinned species metadata`,`generated ${c}`,l.length>0?`sources: ${l.map(e=>e.name).join(`, `)}`:null].filter(Boolean).join(` · `);function m(e){let t=e.trim().replace(/^(?:BOSS_)+/i,``).toLocaleLowerCase(`en-US`),n=f.get(t);if(n)return[...n].sort((e,t)=>d.indexOf(h(e.id,e.name))-d.indexOf(h(t.id,t.name))||t.level-e.level||e.name.localeCompare(t.name))}function h(e,t){let n=`${e} ${t}`.toLocaleLowerCase(`en-US`).replace(/[^a-z]/g,``);return n.includes(`emitflame`)||n.includes(`kindling`)?`kindling`:n.includes(`watering`)?`watering`:n.includes(`seeding`)||n.includes(`planting`)?`planting`:n.includes(`generateelectricity`)||n.includes(`generatingelectricity`)?`electricity`:n.includes(`handcraft`)||n.includes(`handiwork`)?`handiwork`:n.includes(`collection`)||n.includes(`gathering`)?`gathering`:n.includes(`deforest`)||n.includes(`lumbering`)?`lumbering`:n.includes(`mining`)?`mining`:n.includes(`productmedicine`)||n.includes(`medicineproduction`)?`medicine`:n.includes(`cooling`)||n.includes(`cool`)?`cooling`:n.includes(`transport`)?`transporting`:n.includes(`monsterfarm`)||n.includes(`farming`)?`farming`:`unknown`}var g=t();function _({characterId:e}){let t=m(e);return t===void 0?(0,g.jsx)(`span`,{className:`pal-detail-muted`,children:`Unavailable in the pinned Paldeck snapshot`}):t.length===0?(0,g.jsx)(`span`,{className:`pal-detail-muted`,children:`No work suitability`}):(0,g.jsx)(`div`,{className:`pal-work-grid`,children:t.map(e=>(0,g.jsx)(v,{work:e},e.id))})}function v({work:e}){let t=h(e.id,e.name);return(0,g.jsxs)(`div`,{className:`pal-work-badge is-${t}`,title:`${e.name} level ${e.level}`,children:[(0,g.jsx)(`span`,{className:`pal-work-icon`,children:(0,g.jsx)(y,{kind:t})}),(0,g.jsx)(`span`,{className:`pal-work-name`,children:e.name}),(0,g.jsxs)(`strong`,{className:`pal-work-level`,"aria-label":`level ${e.level}`,children:[`Lv `,e.level]})]})}function y({kind:e}){let t={width:18,height:18,viewBox:`0 0 18 18`,fill:`none`,stroke:`currentColor`,strokeWidth:1.55,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":!0};switch(e){case`kindling`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`M10.4 1.7c.5 2.8-1.8 3.8-.9 5.7.6 1.3 2 1.4 2.5 2.8.5-1.1.6-2.2.2-3.4 2.3 1.8 3.1 4.2 1.9 6.6-1.4 2.9-5.8 3.7-8.5 1.4-2.2-1.8-2-4.9-.8-6.9 1.2-2 3.5-3.3 5.6-6.2Z`}),(0,g.jsx)(`path`,{d:`M9.1 10.1c1.6 1.3 1.5 3.5-.2 4.5-1.2-.5-1.8-1.5-1.4-2.6.3-.8 1.1-1.2 1.6-1.9Z`})]});case`watering`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`M9 1.8C7.1 4.5 4.8 7 4.8 10.3a4.2 4.2 0 0 0 8.4 0C13.2 7 10.9 4.5 9 1.8Z`}),(0,g.jsx)(`path`,{d:`M7 11.2c.2 1.1.9 1.8 2 2`})]});case`planting`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`M9 15.8V8.6`}),(0,g.jsx)(`path`,{d:`M9 9C5.6 9 3.5 7.2 3.3 3.7 6.7 3.5 8.7 5.3 9 9Z`}),(0,g.jsx)(`path`,{d:`M9 11.7c3.2 0 5.2-1.7 5.4-4.9-3.2-.2-5.1 1.5-5.4 4.9Z`}),(0,g.jsx)(`path`,{d:`M4.2 15.8h9.6`})]});case`electricity`:return(0,g.jsx)(`svg`,{...t,children:(0,g.jsx)(`path`,{d:`m10.4 1.6-6 8.2h4l-.8 6.6 6-8.6H9.7l.7-6.2Z`})});case`handiwork`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`m3.1 14.9 6.2-6.2`}),(0,g.jsx)(`path`,{d:`m7.7 3.2 2.1-1.4 5 5-1.4 2.1-2.1-2.1-6.5 6.5`}),(0,g.jsx)(`path`,{d:`m2.5 13.6 1.9 1.9`})]});case`gathering`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`M3.1 7.7h11.8l-1.1 7.5H4.2L3.1 7.7Z`}),(0,g.jsx)(`path`,{d:`M6 7.7a3 3 0 0 1 6 0M6.5 10.6v2.1M9 10.6v2.1M11.5 10.6v2.1`})]});case`lumbering`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`m4 15 7.4-7.4`}),(0,g.jsx)(`path`,{d:`m8.8 4.1 2.3-2.3 4.8 4.8-2.3 2.3c-2.2-.8-4-2.6-4.8-4.8Z`}),(0,g.jsx)(`path`,{d:`m2.8 13.8 1.4 1.4`})]});case`mining`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`m5 15 6.7-10.7`}),(0,g.jsx)(`path`,{d:`M2.1 5.8c3.7-2.9 8.9-2.8 13.8.4-3.4-1-6.6-.4-9.1 1.7L2.1 5.8Z`})]});case`medicine`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`M7 1.8h4M8 1.8v4.1l-4 7a2 2 0 0 0 1.7 3h6.6a2 2 0 0 0 1.7-3l-4-7V1.8`}),(0,g.jsx)(`path`,{d:`M5.5 11h7M7.5 13.3h3`})]});case`cooling`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`M9 1.5v15M2.5 5.2l13 7.6M2.5 12.8l13-7.6`}),(0,g.jsx)(`path`,{d:`m7 3.4 2 1.2 2-1.2M7 14.6 9 13.4l2 1.2M4.2 6.6l.1 2.3-2 1.1M13.8 11.4l-.1-2.3 2-1.1`})]});case`transporting`:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`path`,{d:`M2.2 5.2 9 1.8l6.8 3.4v7.6L9 16.2l-6.8-3.4V5.2Z`}),(0,g.jsx)(`path`,{d:`m2.2 5.2 6.8 3.4 6.8-3.4M9 8.6v7.6M5.6 3.5l6.8 3.4`})]});case`farming`:return(0,g.jsx)(`svg`,{...t,children:(0,g.jsx)(`path`,{d:`M9 16V5.4M9 7.3C6.4 7.3 4.7 6 4.5 3.5 7.1 3.3 8.7 4.6 9 7.3ZM9 10.7c2.6 0 4.3-1.3 4.5-3.8-2.6-.2-4.2 1.1-4.5 3.8ZM9 13.8c-2.2 0-3.6-1.1-3.8-3.2 2.2-.2 3.6.9 3.8 3.2Z`})});default:return(0,g.jsxs)(`svg`,{...t,children:[(0,g.jsx)(`circle`,{cx:`9`,cy:`9`,r:`6.5`}),(0,g.jsx)(`path`,{d:`M9 5.4v4.2M9 12.7v.1`})]})}}function b({pal:t,expanded:n,controls:r,onClick:i}){return(0,g.jsx)(`button`,{type:`button`,className:[`pal-info-button`,n?`is-active`:``].filter(Boolean).join(` `),"aria-label":`${n?`Hide`:`Show`} details for ${t.displayName}`,"aria-expanded":n,"aria-controls":r,title:`${n?`Hide`:`Show`} Pal details`,onClick:e=>{e.stopPropagation(),i()},children:(0,g.jsx)(e,{width:14,height:14})})}function x({pal:e,id:t}){let a=e.talents,c=e.passiveSkillIds,l=e.equippedSkillIds;return(0,g.jsxs)(`section`,{id:t,className:`pal-detail-panel`,"aria-label":`${e.displayName} details`,children:[(0,g.jsxs)(`div`,{className:`pal-detail-facts`,children:[(0,g.jsx)(S,{label:`Gender`,value:s(e.gender)}),(0,g.jsx)(S,{label:`Current HP`,value:e.hp===void 0||e.hp===null?`Unavailable`:T(e.hp)}),(0,g.jsx)(S,{label:`Placement`,value:o(e)}),(0,g.jsx)(S,{label:`Specimen`,value:[e.isAlpha?`Alpha`:null,e.isLucky?`Lucky`:null].filter(Boolean).join(` · `)||`Standard`}),(0,g.jsx)(S,{label:`Condensed`,value:r(e.rank)===null?`Unavailable`:(0,g.jsx)(i,{rank:e.rank})})]}),(0,g.jsxs)(`div`,{className:`pal-detail-section`,children:[(0,g.jsx)(`h4`,{children:`Individual talents`}),(0,g.jsxs)(`div`,{className:`pal-talent-grid`,children:[(0,g.jsx)(C,{label:`HP`,value:a?.hp}),(0,g.jsx)(C,{label:`Melee`,value:a?.melee}),(0,g.jsx)(C,{label:`Ranged`,value:a?.shot}),(0,g.jsx)(C,{label:`Defense`,value:a?.defense})]})]}),(0,g.jsxs)(`div`,{className:`pal-detail-section`,children:[(0,g.jsxs)(`h4`,{children:[`Work suitability `,(0,g.jsx)(`span`,{className:`pal-detail-section-source`,title:p,children:`pinned species data`})]}),(0,g.jsx)(_,{characterId:e.characterId})]}),(0,g.jsx)(w,{title:`Passive skills`,values:c}),(0,g.jsx)(w,{title:`Equipped attacks`,values:l}),(0,g.jsxs)(`div`,{className:`pal-detail-identity`,children:[(0,g.jsxs)(`span`,{title:e.characterId,children:[`Species ID `,n(e.characterId,14,6)]}),(0,g.jsxs)(`span`,{title:e.instanceId,children:[`Instance `,n(e.instanceId,10,6)]})]})]})}function S({label:e,value:t}){return(0,g.jsxs)(`div`,{className:`pal-detail-fact`,children:[(0,g.jsx)(`span`,{children:e}),(0,g.jsx)(`strong`,{children:t})]})}function C({label:e,value:t}){return(0,g.jsxs)(`div`,{className:`pal-talent-box`,children:[(0,g.jsx)(`span`,{children:e}),(0,g.jsx)(`strong`,{children:t??`—`})]})}function w({title:e,values:t}){return(0,g.jsxs)(`div`,{className:`pal-detail-section`,children:[(0,g.jsx)(`h4`,{children:e}),t===void 0?(0,g.jsx)(`span`,{className:`pal-detail-muted`,children:`Unavailable from this save parse`}):t.length===0?(0,g.jsx)(`span`,{className:`pal-detail-muted`,children:`None observed`}):(0,g.jsx)(`div`,{className:`pal-skill-list`,children:t.map(e=>(0,g.jsx)(`span`,{title:e,children:a(e)},e))})]})}function T(e){return Number.isInteger(e)?String(e):e.toFixed(1)}export{b as n,o as r,x as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/PalIcon-BoDQgR3K.js b/backend/internal/webdist/dist/assets/PalIcon-BoDQgR3K.js
new file mode 100644
index 0000000..0561392
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/PalIcon-BoDQgR3K.js
@@ -0,0 +1 @@
+import{A as e,U as t,_t as n,ht as r,j as i,q as a}from"./icons-CpYMTu_k.js";var o=n(r(),1),s={plantslime_flower:`plantslime`,grasspanda_electric_tower:`grasspanda_electric`,lazydragon_electric_tower:`lazydragon_electric`};function c(e){let t=e.trim().toLowerCase();if(t===`boss_hunter_rifle`)return t;let n=t;for(;n.startsWith(`boss_`);)n=n.slice(5);return s[n]??n}var l=a();function u(e){return e.slice(0,2).toUpperCase()}function d(){let{data:e}=t({queryKey:[`paldeck`,`icon-dataset`],queryFn:()=>i.paldeck.iconDataset(),staleTime:1/0});return(0,o.useMemo)(()=>new Set((e?.characterIds??[]).map(e=>e.toLowerCase())),[e])}function f({characterId:t,displayName:n}){let r=d(),[a,s]=(0,o.useState)(!1),f=c(t),p=!e&&!a&&r.has(f);return(0,l.jsx)(`span`,{className:`pal-chip`,children:p?(0,l.jsx)(`img`,{src:i.paldeck.iconUrl(f),alt:``,loading:`lazy`,onError:()=>s(!0)}):u(n)})}export{f as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/PalStars-CiCl8RwT.js b/backend/internal/webdist/dist/assets/PalStars-CiCl8RwT.js
new file mode 100644
index 0000000..1127ccc
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/PalStars-CiCl8RwT.js
@@ -0,0 +1 @@
+import{q as e}from"./icons-CpYMTu_k.js";function t(e){return e==null?null:Math.max(0,Math.min(4,Math.round(e)-1))}var n=e();function r({rank:e,className:r}){let i=t(e);if(i===null)return null;let a=`Condensed ${i} of 4 stars`;return(0,n.jsx)(`span`,{className:[`pal-stars`,r].filter(Boolean).join(` `),role:`img`,"aria-label":a,title:a,children:Array.from({length:4},(e,t)=>(0,n.jsx)(`span`,{className:tr&&!`${e.displayName} ${e.characterId}`.toLocaleLowerCase().includes(r)?!1:n===`captured`?e.captureCount!==null&&e.captureCount>0:n===`unseen`?e.captureCount===0:n!==`unavailable`||e.captureCount===null)}var y=i();function b(){let[t,n]=o(),i=t.get(`player`)??``,[a,s]=(0,g.useState)(``),[c,d]=(0,g.useState)(`all`),p=e({queryKey:[`players`],queryFn:()=>r.players.list()}),m=e({queryKey:[`paldeck`,`server`],queryFn:()=>r.paldeck.get(),enabled:!i}),h=e({queryKey:[`paldeck`,`player`,i],queryFn:()=>r.paldeck.player(i),enabled:!!i}),_=i?h.data:m.data,b=i?h:m,S=!(_&&(`player`in _?_.coverage.captureCountsAvailable&&!_.coverage.captureCountsTruncated:_.coverage.playersTotal>0&&_.coverage.playersWithCaptureCounts===_.coverage.playersTotal&&!_.coverage.captureCountsTruncated))&&c===`unseen`?`all`:c,C=(0,g.useMemo)(()=>v(_?.species??[],a,S),[_?.species,a,S]);function w(e){let r=new URLSearchParams(t);e?r.set(`player`,e):r.delete(`player`),n(r,{replace:!0})}return(0,y.jsxs)(`main`,{className:`content paldeck-page`,children:[(0,y.jsxs)(`div`,{className:`page-head paldeck-head`,children:[(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`h1`,{children:`Paldeck`}),(0,y.jsx)(`span`,{className:`sub`,children:`capture progress from parsed saves · 1.0 catalog`})]}),(0,y.jsxs)(`label`,{className:`paldeck-player-select`,children:[(0,y.jsx)(`span`,{children:`Progress view`}),(0,y.jsxs)(`select`,{className:`input`,value:i,onChange:e=>w(e.target.value),children:[(0,y.jsx)(`option`,{value:``,children:`All players`}),(p.data??[]).map(e=>(0,y.jsx)(`option`,{value:e.uid,children:e.name||`Unknown player`},e.uid))]})]})]}),b.isError?(0,y.jsx)(l,{tone:`warn`,children:`Couldn't load Paldeck data from player saves.`}):b.isPending||!_?(0,y.jsx)(f,{children:(0,y.jsx)(u,{children:(0,y.jsx)(`span`,{className:`skel skel-text paldeck-skeleton`})})}):(0,y.jsx)(x,{data:_,search:a,setSearch:s,filter:c,setFilter:d,species:C})]})}function x({data:t,search:n,setSearch:i,filter:o,setFilter:g,species:v}){let b=e({queryKey:[`paldeck`,`icon-dataset`],queryFn:()=>r.paldeck.iconDataset(),staleTime:1/0}),x=e({queryKey:[`server`],queryFn:()=>r.server.get()}),C=`player`in t,w=C?t.coverage.captureCountsAvailable:t.coverage.playersWithCaptureCounts>0,T=t.coverage.captureCountsTruncated,E=C?t.coverage.captureCountsAvailable&&!T:t.coverage.playersTotal>0&&t.coverage.playersWithCaptureCounts===t.coverage.playersTotal&&!T,D=C?t.coverage.unlockFlagsAvailable&&!t.coverage.unlockFlagsTruncated:t.coverage.playersTotal>0&&t.coverage.playersWithUnlockFlags===t.coverage.playersTotal&&!t.coverage.unlockFlagsTruncated,O=C?t.coverage.captureObservedAt:t.coverage.latestObservedAt,k=C?t.uniquePalsCaptured:t.uniqueSpeciesCaptured,A=E?t.species.filter(e=>e.known&&e.captureCount!==null&&e.captureCount>0).length:null,j=D?t.species.filter(e=>e.known&&(C?e.unlocked===!0:(e.unlockedByPlayers??0)>0)).length:null;return(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(l,{tone:E?`info`:`warn`,children:[C?w?`Capture data from ${s(O)}.`:`No capture data decoded for this player yet.`:`Capture data covers ${t.coverage.playersWithCaptureCounts} of ${t.coverage.playersTotal} players.`,T?` The capture map was truncated, so “unseen” is not conclusive.`:` Missing data is never counted as zero.`]}),b.data?.count===0&&(0,y.jsxs)(l,{tone:`warn`,children:[`Pal icons are not installed. Initials are shown instead. Run `,(0,y.jsx)(`code`,{children:x.data?.palIconsCommand??`docker compose exec palhelm palhelm fetch-pal-icons`}),` to add portraits.`]}),(0,y.jsxs)(`div`,{className:`paldeck-stats`,"aria-label":`Paldeck summary`,children:[(0,y.jsx)(S,{label:`Species captured`,value:A,denominator:t.catalog.knownSpecies,percent:_(A,t.catalog.knownSpecies)}),(0,y.jsx)(S,{label:`Entries unlocked`,value:j,denominator:t.catalog.knownSpecies,percent:_(j,t.catalog.knownSpecies)}),(0,y.jsx)(f,{children:(0,y.jsxs)(u,{className:`paldeck-stat`,children:[(0,y.jsx)(`span`,{children:`Total captures`}),(0,y.jsx)(`strong`,{children:t.captureTotal??`Unavailable`}),(0,y.jsx)(`small`,{children:`sum of save counters`})]})}),(0,y.jsx)(f,{children:(0,y.jsxs)(u,{className:`paldeck-stat`,children:[(0,y.jsx)(`span`,{children:`Unique species counter`}),(0,y.jsx)(`strong`,{children:k??`Unavailable`}),(0,y.jsx)(`small`,{children:`from the save · may include unlisted IDs`})]})})]}),(0,y.jsxs)(f,{children:[(0,y.jsx)(d,{title:`Species`,hint:`${v.length} shown of ${t.catalog.knownSpecies}`}),(0,y.jsx)(u,{children:(0,y.jsxs)(`div`,{className:`paldeck-tools`,children:[(0,y.jsx)(c,{value:n,onChange:e=>i(e.target.value),placeholder:`Search Pal name…`,"aria-label":`Search Paldeck species`}),(0,y.jsxs)(`select`,{className:`input`,"aria-label":`Capture filter`,value:!E&&o===`unseen`?`all`:o,onChange:e=>g(e.target.value),children:[(0,y.jsx)(`option`,{value:`all`,children:`All species`}),(0,y.jsx)(`option`,{value:`captured`,children:`Captured`}),(0,y.jsx)(`option`,{value:`unseen`,disabled:!E,children:`Unseen (needs full data)`}),(0,y.jsx)(`option`,{value:`unavailable`,children:`No data`})]})]})}),v.length===0?(0,y.jsx)(u,{children:(0,y.jsx)(p,{title:`No species match`,description:`Clear the search or choose another filter.`})}):(0,y.jsx)(u,{className:`paldeck-grid`,children:v.map(e=>{let t=e.captureCount,n=!E&&t===0,r=C?null:e,i=C?e:null;return(0,y.jsxs)(`article`,{className:`paldeck-species`,children:[(0,y.jsx)(m,{characterId:e.characterId,displayName:e.displayName}),(0,y.jsxs)(`div`,{children:[(0,y.jsx)(`strong`,{children:e.displayName}),(0,y.jsx)(`small`,{children:e.known?t===null?`No capture data`:n?`None seen in partial data`:t===0?`Not captured`:`${t} captured`:`Unlisted ID · ${e.characterId}`})]}),(0,y.jsxs)(`div`,{className:`paldeck-species-meta`,children:[r&&r.capturedByPlayers!==null&&(0,y.jsxs)(`span`,{children:[r.capturedByPlayers,` players`]}),i?.unlocked!==null&&i?.unlocked!==void 0&&(0,y.jsx)(`span`,{children:i.unlocked?`Unlocked`:`Locked`}),t!==null&&t>0&&(0,y.jsx)(a,{to:h({q:e.displayName}),children:`View roster`})]})]},e.characterId)})})]}),(0,y.jsxs)(`p`,{className:`paldeck-footnote`,children:[`Catalog `,t.catalog.version,` · `,t.catalog.observedUnknownSpecies,` IDs outside the catalog. Counts reflect the latest parsed save.`]})]})}function S({label:e,value:t,denominator:n,percent:r}){return(0,y.jsx)(f,{children:(0,y.jsxs)(u,{className:`paldeck-stat`,children:[(0,y.jsx)(`span`,{children:e}),(0,y.jsx)(`strong`,{children:t===null?`Unavailable`:`${t} / ${n}`}),(0,y.jsx)(`small`,{children:r===null?`needs full capture data`:`${r}% of catalog`}),r!==null&&(0,y.jsx)(`progress`,{max:`100`,value:r,"aria-label":`${e}: ${r}%`})]})})}export{b as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Paldeck-gNJw7ewz.css b/backend/internal/webdist/dist/assets/Paldeck-gNJw7ewz.css
new file mode 100644
index 0000000..dbdda93
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Paldeck-gNJw7ewz.css
@@ -0,0 +1 @@
+.paldeck-page{gap:var(--space-4)}.paldeck-head{justify-content:space-between;align-items:flex-end;row-gap:var(--space-2);flex-wrap:wrap}.paldeck-head>div:first-child{align-items:baseline;gap:var(--space-3);flex-wrap:wrap;min-width:0;display:flex}.paldeck-player-select{min-width:220px;color:var(--ink-3);font-size:var(--text-xs);flex-direction:column;gap:4px;display:flex}.paldeck-stats{gap:var(--space-3);grid-template-columns:repeat(4,minmax(0,1fr));display:grid}.paldeck-stat{flex-direction:column;gap:5px;display:flex}.paldeck-stat>span{color:var(--ink-3);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--track-caps)}.paldeck-stat strong{font:600 var(--text-xl)/1.2 var(--font-mono);font-variant-numeric:tabular-nums}.paldeck-stat small{color:var(--ink-3)}.paldeck-stat progress{width:100%;height:7px;accent-color:var(--accent)}.paldeck-tools{gap:var(--space-2);grid-template-columns:minmax(220px,1fr) 180px;display:grid}.paldeck-grid{gap:var(--space-2);grid-template-columns:repeat(3,minmax(0,1fr));padding-top:0;display:grid}.paldeck-species{border:1px solid var(--line);border-radius:var(--radius-ctl);background:var(--surface-2);grid-template-columns:auto minmax(0,1fr);align-items:center;gap:9px;padding:10px;display:grid}.paldeck-species>div:nth-child(2){min-width:0}.paldeck-species strong,.paldeck-species small{display:block}.paldeck-species strong{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.paldeck-species small{color:var(--ink-3);margin-top:2px;font-size:10px;line-height:1.35}.paldeck-species-meta{color:var(--ink-3);grid-column:1/-1;justify-content:flex-end;align-items:center;gap:8px;font-size:10px;display:flex}.paldeck-species-meta a{margin-left:auto}.paldeck-footnote{color:var(--ink-3);font-size:var(--text-xs);line-height:1.5}.paldeck-skeleton{width:100%;height:190px}@media (width<=1000px){.paldeck-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width<=800px){.paldeck-stats{grid-template-columns:1fr}}@media (width<=650px){.paldeck-head{flex-direction:column;align-items:stretch}.paldeck-head>div:first-child{flex-direction:column;align-items:flex-start;gap:2px}.paldeck-player-select{min-width:0}.paldeck-tools,.paldeck-grid{grid-template-columns:1fr}}
diff --git a/backend/internal/webdist/dist/assets/Pals-CQBg4Vgc.js b/backend/internal/webdist/dist/assets/Pals-CQBg4Vgc.js
new file mode 100644
index 0000000..371d12a
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Pals-CQBg4Vgc.js
@@ -0,0 +1 @@
+import{J as e,W as t,X as n,Z as r,_t as i,ht as a,j as o,q as s}from"./icons-CpYMTu_k.js";import{Nn as c,i as l}from"./index-BpCavHBc.js";import{t as u}from"./Banner-DSN1nEJn.js";import{n as d,r as f,t as p}from"./Card-D55CMzdw.js";import{t as m}from"./EmptyState-DTSMkv56.js";import{t as h}from"./PalIcon-BoDQgR3K.js";import{t as g}from"./PalStars-CiCl8RwT.js";import{a as _,i as v,n as y,o as b,s as x,t as S}from"./palExplorer-IChZ_UBL.js";import{n as C,r as w,t as T}from"./PalDetails-Dl-UCtTN.js";var E=class extends e{constructor(e,t){super(e,t)}bindMethods(){super.bindMethods(),this.fetchNextPage=this.fetchNextPage.bind(this),this.fetchPreviousPage=this.fetchPreviousPage.bind(this)}setOptions(e){e._type=`infinite`,super.setOptions(e)}getOptimisticResult(e){return e._type=`infinite`,super.getOptimisticResult(e)}fetchNextPage(e){return this.fetch({...e,meta:{fetchMore:{direction:`forward`}}})}fetchPreviousPage(e){return this.fetch({...e,meta:{fetchMore:{direction:`backward`}}})}createResult(e,t){let{state:i}=e,a=super.createResult(e,t),{isFetching:o,isRefetching:s,isError:c,isRefetchError:l}=a,u=i.fetchMeta?.fetchMore?.direction,d=c&&u===`forward`,f=o&&u===`forward`,p=c&&u===`backward`,m=o&&u===`backward`;return{...a,fetchNextPage:this.fetchNextPage,fetchPreviousPage:this.fetchPreviousPage,hasNextPage:n(t,i.data),hasPreviousPage:r(t,i.data),isFetchNextPageError:d,isFetchingNextPage:f,isFetchPreviousPageError:p,isFetchingPreviousPage:m,isRefetchError:l&&!d&&!p,isRefetching:s&&!f&&!m}}};function D(e,n){return t(e,E,n)}var O=i(a(),1),k=s();function A({variant:e=`default`,sm:t=!1,className:n=``,...r}){let i=[`btn`,e==="default"?``:`btn-${e}`,t?`btn-sm`:``,n].filter(Boolean).join(` `);return(0,k.jsx)(`button`,{className:i,...r})}function j(){let[e,t]=c(),n=(0,O.useMemo)(()=>y(e),[e]),[r,i]=(0,O.useState)(``),[a,s]=(0,O.useState)(null);(0,O.useEffect)(()=>{let e=window.setTimeout(()=>i(n.q),250);return()=>window.clearTimeout(e)},[n.q]);let h=v({...n,q:r}),g=h.minLevel!==void 0&&h.maxLevel!==void 0&&h.minLevel>h.maxLevel,b=D({queryKey:[`pals`,`explorer`,h],initialPageParam:``,enabled:!g,queryFn:({pageParam:e})=>o.pals.list({...h,cursor:e||void 0,limit:48}),getNextPageParam:(e,t)=>{if(!(t.reduce((e,t)=>e+t.data.length,0)>=480))return e.nextCursor??void 0}}),x=b.data?.pages.flatMap(e=>e.data)??[],C=x.length>=480&&b.data?.pages.at(-1)?.nextCursor!==null;function w(r,i){t(_({...n,[r]:i},e),{replace:!0}),s(null)}return(0,k.jsxs)(`main`,{className:`content pals-explorer`,children:[(0,k.jsxs)(`div`,{className:`page-head`,children:[(0,k.jsx)(`h1`,{children:`Pal explorer`}),(0,k.jsx)(`span`,{className:`sub`,children:`every Pal on the server, from parsed saves`})]}),(0,k.jsxs)(p,{className:`pals-filter-card`,children:[(0,k.jsx)(f,{title:`Filters`}),(0,k.jsx)(d,{children:(0,k.jsxs)(`div`,{className:`pals-filter-grid`,children:[(0,k.jsxs)(`label`,{className:`pals-search-filter`,children:[(0,k.jsx)(`span`,{children:`Pal or owner`}),(0,k.jsx)(l,{value:n.q,placeholder:`Mammorest, Anubis, Kestrel…`,"aria-label":`Search Pals or owners`,onChange:e=>w(`q`,e.target.value)})]}),(0,k.jsxs)(M,{label:`Placement`,value:n.placement,onChange:e=>w(`placement`,e),children:[(0,k.jsx)(`option`,{value:``,children:`Everywhere`}),(0,k.jsx)(`option`,{value:`party`,children:`Party`}),(0,k.jsx)(`option`,{value:`box`,children:`Palbox`}),(0,k.jsx)(`option`,{value:`base`,children:`Base workers`}),(0,k.jsx)(`option`,{value:`unknown`,children:`Unknown`})]}),(0,k.jsxs)(M,{label:`Specimen`,value:n.specimen,onChange:e=>w(`specimen`,e),children:[(0,k.jsx)(`option`,{value:``,children:`All specimens`}),(0,k.jsx)(`option`,{value:`standard`,children:`Standard`}),(0,k.jsx)(`option`,{value:`alpha`,children:`Alpha`}),(0,k.jsx)(`option`,{value:`lucky`,children:`Lucky`}),(0,k.jsx)(`option`,{value:`boss`,children:`Boss`})]}),(0,k.jsxs)(M,{label:`Owner source`,value:n.ownerSource,onChange:e=>w(`ownerSource`,e),children:[(0,k.jsx)(`option`,{value:``,children:`Any source`}),(0,k.jsx)(`option`,{value:`personal_container`,children:`Current container`}),(0,k.jsx)(`option`,{value:`save`,children:`Save owner`}),(0,k.jsx)(`option`,{value:`last_observed`,children:`Last known`}),(0,k.jsx)(`option`,{value:`unresolved`,children:`Unresolved`})]}),(0,k.jsxs)(`label`,{children:[(0,k.jsx)(`span`,{children:`Min level`}),(0,k.jsx)(`input`,{className:`input`,type:`number`,min:`0`,max:`999`,inputMode:`numeric`,value:n.minLevel,onChange:e=>w(`minLevel`,e.target.value),placeholder:`0`})]}),(0,k.jsxs)(`label`,{children:[(0,k.jsx)(`span`,{children:`Max level`}),(0,k.jsx)(`input`,{className:`input`,type:`number`,min:`0`,max:`999`,inputMode:`numeric`,value:n.maxLevel,onChange:e=>w(`maxLevel`,e.target.value),placeholder:`Any`})]}),(0,k.jsx)(A,{sm:!0,variant:`ghost`,className:`pals-clear`,onClick:()=>{t(_(S,e),{replace:!0}),s(null)},children:`Clear filters`})]})})]}),g?(0,k.jsx)(u,{tone:`warn`,children:`Min level cannot be higher than max level.`}):b.isError?(0,k.jsx)(u,{tone:`warn`,children:`Couldn't load the Pal roster. Save data may not have been parsed yet.`}):b.isPending?(0,k.jsx)(p,{children:(0,k.jsx)(d,{children:(0,k.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:180}})})}):x.length===0?(0,k.jsx)(p,{children:(0,k.jsx)(d,{children:(0,k.jsx)(m,{title:`No Pals match`,description:`Widen the level range or clear a filter.`})})}):(0,k.jsxs)(k.Fragment,{children:[(0,k.jsxs)(`div`,{className:`pals-results-head`,children:[(0,k.jsxs)(`span`,{children:[x.length,` loaded`]}),(0,k.jsx)(`span`,{children:`ordered by save instance`})]}),(0,k.jsx)(`div`,{className:`pals-card-grid`,children:x.map(e=>(0,k.jsx)(N,{pal:e,expanded:a===e.instanceId,onToggle:()=>s(t=>t===e.instanceId?null:e.instanceId)},e.instanceId))}),(0,k.jsx)(`div`,{className:`pals-load-more`,children:C?(0,k.jsxs)(u,{tone:`info`,children:[`Showing the first `,480,` matches. Narrow the filters to inspect the rest.`]}):b.hasNextPage?(0,k.jsx)(A,{disabled:b.isFetchingNextPage,onClick:()=>b.fetchNextPage(),children:b.isFetchingNextPage?`Loading…`:`Load 48 more`}):(0,k.jsx)(`span`,{children:`End of results`})})]})]})}function M({label:e,value:t,onChange:n,children:r}){return(0,k.jsxs)(`label`,{children:[(0,k.jsx)(`span`,{children:e}),(0,k.jsx)(`select`,{className:`input`,value:t,onChange:e=>n(e.target.value),children:r})]})}function N({pal:e,expanded:t,onToggle:n}){let r=`pal-explorer-${e.instanceId}`,i=x(e);return(0,k.jsxs)(`article`,{className:[`pal-explorer-card`,t?`is-expanded`:``].filter(Boolean).join(` `),children:[(0,k.jsxs)(`div`,{className:`pal-explorer-card-main`,children:[(0,k.jsx)(h,{characterId:e.characterId,displayName:e.displayName}),(0,k.jsxs)(`div`,{className:`pal-explorer-card-copy`,children:[(0,k.jsxs)(`div`,{className:`pal-explorer-name-line`,children:[(0,k.jsx)(`h2`,{children:e.displayName}),(0,k.jsxs)(`span`,{className:`pal-explorer-level`,children:[`Lv `,e.level]})]}),(0,k.jsxs)(`div`,{className:`pal-explorer-tags`,children:[i.map(e=>(0,k.jsx)(`span`,{className:`pal-explorer-tag is-${e.toLowerCase()}`,children:e===`Boss`?`◆ Boss`:e},e)),i.length===0&&(0,k.jsx)(`span`,{className:`pal-explorer-tag`,children:`Standard`}),e.rank!=null&&e.rank>1&&(0,k.jsx)(g,{rank:e.rank})]}),(0,k.jsx)(`strong`,{className:e.ownerResolved?``:`is-muted`,children:b(e)}),(0,k.jsx)(`span`,{children:w(e)})]}),(0,k.jsx)(C,{pal:e,expanded:t,controls:r,onClick:n})]}),t&&(0,k.jsx)(T,{pal:e,id:r})]})}export{j as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Pals-D_KCRg-r.css b/backend/internal/webdist/dist/assets/Pals-D_KCRg-r.css
new file mode 100644
index 0000000..c5d795c
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Pals-D_KCRg-r.css
@@ -0,0 +1 @@
+.pals-explorer{gap:var(--space-4);flex-direction:column;display:flex}.pals-filter-card .card-body{padding-block:var(--space-3)}.pals-filter-grid{gap:var(--space-3);grid-template-columns:minmax(240px,1.7fr) repeat(3,minmax(145px,1fr)) minmax(110px,.65fr) minmax(110px,.65fr) auto;align-items:end;display:grid}.pals-filter-grid label{flex-direction:column;gap:5px;min-width:0;display:flex}.pals-filter-grid label>span{color:var(--ink-3);font-size:var(--text-xs);font-weight:600}.pals-filter-grid .search{width:100%}.pals-clear{white-space:nowrap}.pals-results-head{justify-content:space-between;gap:var(--space-3);color:var(--ink-3);font-size:var(--text-xs);display:flex}.pals-card-grid{gap:var(--space-3);grid-template-columns:repeat(3,minmax(0,1fr));align-items:start;display:grid}.pal-explorer-card{background:var(--surface);border:var(--border-ctl) solid var(--line);border-radius:var(--radius-card);min-width:0;overflow:hidden}.pal-explorer-card.is-expanded{border-color:var(--line-strong);grid-row:span 2}.pal-explorer-card-main{grid-template-columns:56px minmax(0,1fr) auto;align-items:start;gap:12px;padding:14px;display:grid}.pal-explorer-card .pal-chip{width:56px;height:56px;font-size:var(--text-md);border-radius:10px}.pal-explorer-card-copy{min-width:0;color:var(--ink-3);font-size:var(--text-xs);flex-direction:column;gap:5px;display:flex}.pal-explorer-card-copy strong{color:var(--ink-2);text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.pal-explorer-card-copy strong.is-muted{color:var(--ink-3);font-weight:500}.pal-explorer-name-line{align-items:baseline;gap:8px;min-width:0;display:flex}.pal-explorer-name-line h2{text-overflow:ellipsis;white-space:nowrap;font-family:var(--font-display);font-size:var(--text-md);color:var(--ink-1);overflow:hidden}.pal-explorer-level{color:var(--ink-3);font-family:var(--font-mono);font-size:var(--text-xs);flex:none}.pal-explorer-tags{flex-wrap:wrap;gap:4px;min-height:18px;display:flex}.pal-explorer-tag{border:1px solid var(--line);color:var(--ink-3);font-family:var(--font-mono);border-radius:999px;padding:1px 6px;font-size:10px}.pal-explorer-tag.is-boss{color:var(--danger-ink,var(--warn-ink));border-color:color-mix(in srgb, var(--danger,var(--warn)) 50%, var(--line))}.pal-explorer-tag.is-alpha{color:var(--warn-ink);border-color:color-mix(in srgb, var(--warn) 50%, var(--line))}.pal-explorer-tag.is-lucky{color:var(--accent-ink);border-color:color-mix(in srgb, var(--accent) 50%, var(--line))}.pal-explorer-card>.pal-detail-panel{border-top:1px solid var(--line)}.pals-load-more{min-height:44px;color:var(--ink-3);font-size:var(--text-xs);justify-content:center;align-items:center;display:flex}@media (width<=1280px){.pals-filter-grid{grid-template-columns:repeat(3,minmax(0,1fr))}.pals-search-filter{grid-column:span 2}.pals-card-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width<=760px){.pals-filter-grid,.pals-card-grid{grid-template-columns:1fr}.pals-search-filter{grid-column:auto}.pals-results-head{flex-direction:column;gap:3px}}
diff --git a/backend/internal/webdist/dist/assets/Players-5fYfLSwo.css b/backend/internal/webdist/dist/assets/Players-5fYfLSwo.css
new file mode 100644
index 0000000..91dd4a4
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Players-5fYfLSwo.css
@@ -0,0 +1 @@
+.players-layout{gap:var(--space-4);grid-template-columns:1fr 340px;align-items:start;display:grid}@media (width<=1100px){.players-layout{grid-template-columns:1fr}}.players-main{gap:var(--space-3);flex-direction:column;min-width:0;display:flex}.toolbar{gap:var(--space-2);align-items:center;display:flex}.toolbar .search{width:280px}.toolbar .spacer{flex:1}.toolbar .sync-hint{color:var(--ink-3);font-size:var(--text-xs)}.detail-head{border-bottom:var(--border-ctl) solid var(--line);align-items:center;gap:12px;padding:16px;display:flex}.detail-head .avatar{width:40px;height:40px;font-size:14px}.detail-head h2{font-family:var(--font-display);font-size:var(--text-lg);font-weight:700}.detail-head .id{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--ink-3)}.kv{background:var(--line);grid-template-columns:1fr 1fr;gap:1px;display:grid}.kv>div{background:var(--surface);padding:10px 16px}.kv .label{font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3);display:block}.kv .val{font-family:var(--font-mono);font-size:var(--text-sm);font-variant-numeric:tabular-nums}.kv .label .label-note{text-transform:none;letter-spacing:normal;color:var(--ink-3);opacity:.85}.player-activity{border-top:1px solid var(--line)}.player-activity .card-head{border-bottom:1px solid var(--line)}.player-activity-current{color:var(--ink-3);font-size:var(--text-xs);justify-content:space-between;align-items:baseline;gap:12px;padding:10px 16px;display:flex}.player-activity-current strong{color:var(--ink-1);font-family:var(--font-mono);font-size:var(--text-sm);font-variant-numeric:tabular-nums}.player-activity-windows{background:var(--line);border-block:1px solid var(--line);grid-template-columns:repeat(3,1fr);gap:1px;display:grid}.player-activity-windows>div{background:var(--surface-2);flex-direction:column;gap:2px;min-width:0;padding:9px 10px;display:flex}.player-activity-windows span{color:var(--ink-3);text-transform:uppercase;letter-spacing:var(--track-caps);font-size:10px}.player-activity-windows strong{font-family:var(--font-mono);font-size:var(--text-sm);font-variant-numeric:tabular-nums}.player-activity-windows small{color:var(--ink-3);font-size:10px}.player-activity-coverage,.player-activity-empty{color:var(--ink-3);margin:0;padding:9px 16px 11px;font-size:10px;line-height:1.45}.pal-row{border-bottom:1px solid var(--line);font-size:var(--text-sm);align-items:center;gap:10px;padding:8px 16px;display:flex}.pal-row:hover{background:var(--surface-2)}.pal-entry:last-child .pal-row{border-bottom:0}.pal-row .lvl{font-family:var(--font-mono);color:var(--ink-3);font-variant-numeric:tabular-nums;margin-left:auto}.pal-chip{background:var(--surface-3);border:var(--border-ctl) solid var(--line-strong);width:24px;height:24px;color:var(--ink-2);border-radius:5px;flex:none;place-items:center;font-size:10px;font-weight:600;display:grid;overflow:hidden}.pal-chip img{object-fit:cover;width:100%;height:100%;display:block}.pal-tag{font-family:var(--font-mono);border-radius:4px;padding:0 5px;font-size:10px;font-weight:600;line-height:16px}.pal-tag.alpha{color:var(--warn-ink);background:linear-gradient(var(--warn-soft), var(--warn-soft)) var(--surface);border:1px solid color-mix(in srgb, var(--warn) 55%, transparent)}.pal-tag.lucky{color:var(--accent-ink);background:linear-gradient(var(--accent-soft), var(--accent-soft)) var(--surface);border:1px solid color-mix(in srgb, var(--accent) 55%, transparent)}.pal-more{text-align:center;width:100%;color:var(--ink-3);font-size:var(--text-xs);cursor:pointer;background:0 0;border:0;padding:8px 16px;display:block}.pal-more:hover{color:var(--ink-2);background:var(--surface-2)}.whitelist-row{gap:var(--space-2);border-bottom:1px solid var(--line);align-items:center;padding:8px 16px;display:flex}.whitelist-row:last-child{border-bottom:0}.whitelist-row .input{flex:1}.whitelist-foot{gap:var(--space-2);border-top:1px solid var(--line);align-items:center;padding:12px 16px;display:flex}dialog.dialog.pal-box-dialog{width:min(780px,94vw)}.pal-box{gap:var(--space-3);flex-direction:column;display:flex}.pal-box-empty{color:var(--ink-3);font-size:var(--text-sm);padding:var(--space-4) 0;text-align:center}.pal-box-nav{justify-content:space-between;align-items:center;gap:8px;display:flex}.pal-box-title{font-family:var(--font-display);font-weight:700;font-size:var(--text-md);text-align:center;flex-direction:column;align-items:center;gap:2px;display:flex}.pal-box-count{font-family:var(--font-mono);font-size:var(--text-xs);color:var(--ink-3);font-weight:500}.pal-grid{gap:8px;display:grid}.pal-cell{border-radius:var(--radius-ctl);background:var(--surface-2);border:var(--border-ctl) solid var(--line);text-align:center;flex-direction:column;align-items:center;gap:4px;min-height:92px;padding:8px 4px;display:flex;position:relative;overflow:hidden}.pal-cell-info{position:absolute;top:5px;right:5px}.pal-cell-info .pal-info-button{background:color-mix(in srgb, var(--surface) 88%, transparent);width:21px;height:21px}.pal-cell-empty{border-style:dashed;border-color:var(--line);background:0 0}.pal-cell .pal-chip{width:40px;height:40px;font-size:13px}.pal-cell-name{font-size:var(--text-xs);color:var(--ink-2);text-overflow:ellipsis;white-space:nowrap;max-width:100%;line-height:1.2;overflow:hidden}.pal-cell-meta{font-family:var(--font-mono);color:var(--ink-3);font-variant-numeric:tabular-nums;flex-wrap:wrap;justify-content:center;align-items:center;gap:4px;font-size:10px;display:flex}.pal-box-tabs{border-top:1px solid var(--line);padding-top:var(--space-3);flex-wrap:wrap;justify-content:center;gap:6px;display:flex}.pal-box-tab{font-size:var(--text-xs);cursor:pointer;color:var(--ink-3);border:1px solid var(--line);background:0 0;border-radius:999px;padding:3px 10px}.pal-box-tab:hover{color:var(--ink-2);background:var(--surface-2)}.pal-box-tab.is-active{color:var(--accent-ink);border-color:color-mix(in srgb, var(--accent) 55%, transparent);background:var(--accent-soft)}
diff --git a/backend/internal/webdist/dist/assets/Players-CVTzm-84.js b/backend/internal/webdist/dist/assets/Players-CVTzm-84.js
new file mode 100644
index 0000000..c483a06
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Players-CVTzm-84.js
@@ -0,0 +1 @@
+import{A as e,K as t,U as n,_t as r,a as i,ht as a,j as o,o as s,q as c,w as l,z as u}from"./icons-CpYMTu_k.js";import{t as d}from"./useMutation-S28PAV4D.js";import{n as f,t as p}from"./DropdownMenu-fCf3CXmF.js";import{An as m,Dn as h,Mn as g,Nn as _,On as v,Pn as y,c as b,d as x,f as S,i as C,p as w,r as T,s as E,u as D}from"./index-BpCavHBc.js";import{t as O}from"./Banner-DSN1nEJn.js";import{n as k,r as A,t as j}from"./Card-D55CMzdw.js";import{t as M}from"./EmptyState-DTSMkv56.js";import{t as N}from"./Tabs-DecjeYAq.js";import{t as P}from"./guildDisplay-LZYrk7hc.js";import{t as F}from"./PalIcon-BoDQgR3K.js";import{t as I}from"./PalStars-CiCl8RwT.js";import{n as L,t as R}from"./PalDetails-Dl-UCtTN.js";var z=r(a(),1),B=c();function ee(){return(0,B.jsxs)(`svg`,{viewBox:`0 0 24 24`,width:`60%`,height:`60%`,fill:`currentColor`,"aria-hidden":`true`,children:[(0,B.jsx)(`circle`,{cx:`12`,cy:`8.4`,r:`3.3`}),(0,B.jsx)(`path`,{d:`M12 12.9c-4.3 0-7.7 2.8-7.7 7.1a1 1 0 0 0 1 1h13.4a1 1 0 0 0 1-1c0-4.3-3.4-7.1-7.7-7.1z`}),(0,B.jsx)(`path`,{d:`M8.4 13.5L14.7 20.6`,stroke:`var(--surface-3)`,strokeWidth:`1.3`,strokeLinecap:`round`,fill:`none`})]})}function V({name:t,uid:n,className:r}){let[i,a]=(0,z.useState)(!1),s=!e&&!i&&!!n;return(0,B.jsx)(`span`,{className:[`avatar`,r].filter(Boolean).join(` `),title:t,children:s?(0,B.jsx)(`img`,{src:o.players.avatarUrl(n),alt:``,loading:`lazy`,onError:()=>a(!0)}):(0,B.jsx)(ee,{})})}var H=5,U=30;function te(e){let t=[],n=e.filter(e=>e.inParty).sort((e,t)=>(e.partySlot??0)-(t.partySlot??0));if(n.length>0){let e=Array(H).fill(null);n.forEach((t,n)=>{let r=t.partySlot??n;r>=0&&r!e.inParty&&e.boxPage!==null),i=r.reduce((e,t)=>Math.max(e,t.boxPage??0),-1);for(let e=0;e<=i;e++){let n=Array(U).fill(null);for(let t of r){if(t.boxPage!==e)continue;let r=t.boxSlot??-1;r>=0&&r!e.inParty&&e.boxPage===null);return a.length>0&&t.push({key:`other`,label:`Base & expeditions`,slots:a,columns:6}),t}function ne({pal:e,expanded:t,onInfo:n}){if(!e)return(0,B.jsx)(`div`,{className:`pal-cell pal-cell-empty`,"aria-hidden":`true`});let r=`box-pal-details-${e.instanceId}`;return(0,B.jsxs)(`div`,{className:`pal-cell`,title:`${e.displayName} · Lv ${e.level}`,children:[(0,B.jsx)(`span`,{className:`pal-cell-info`,children:(0,B.jsx)(L,{pal:e,expanded:t,controls:r,onClick:n})}),(0,B.jsx)(F,{characterId:e.characterId,displayName:e.displayName}),(0,B.jsx)(`span`,{className:`pal-cell-name`,children:e.displayName}),(0,B.jsxs)(`span`,{className:`pal-cell-meta`,children:[`Lv `,e.level,e.isAlpha&&(0,B.jsx)(`span`,{className:`pal-tag alpha`,children:`α`}),e.isLucky&&(0,B.jsx)(`span`,{className:`pal-tag lucky`,children:`✦`}),e.rank!=null&&e.rank>1&&(0,B.jsx)(I,{rank:e.rank})]})]})}function W({open:e,onClose:t,playerName:n,pals:r}){let a=(0,z.useMemo)(()=>te(r),[r]),[o,c]=(0,z.useState)(0),[l,u]=(0,z.useState)(null),d=a.length===0?null:a[Math.min(o,a.length-1)],f=Math.min(o,Math.max(0,a.length-1)),p=d?.slots.find(e=>e?.instanceId===l)??null;return(0,z.useEffect)(()=>u(null),[f,e]),(0,B.jsx)(w,{open:e,title:`${n} · Pals`,onClose:t,className:`pal-box-dialog`,children:d===null?(0,B.jsx)(`div`,{className:`pal-box-empty`,children:`No Pals in the latest save.`}):(0,B.jsxs)(`div`,{className:`pal-box`,children:[(0,B.jsxs)(`div`,{className:`pal-box-nav`,children:[(0,B.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>c(e=>Math.max(0,e-1)),disabled:f===0,"aria-label":`Previous box`,children:(0,B.jsx)(i,{})}),(0,B.jsxs)(`span`,{className:`pal-box-title`,children:[d.label,(0,B.jsxs)(`span`,{className:`pal-box-count`,children:[d.slots.filter(Boolean).length,` pal`,d.slots.filter(Boolean).length===1?``:`s`,a.length>1&&` · ${f+1}/${a.length}`]})]}),(0,B.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>c(e=>Math.min(a.length-1,e+1)),disabled:f>=a.length-1,"aria-label":`Next box`,children:(0,B.jsx)(s,{})})]}),(0,B.jsx)(`div`,{className:`pal-grid`,style:{gridTemplateColumns:`repeat(${d.columns}, 1fr)`},children:d.slots.map((e,t)=>(0,B.jsx)(ne,{pal:e,expanded:e?.instanceId===l,onInfo:()=>u(e?.instanceId===l?null:e?.instanceId??null)},e?e.instanceId:`empty-${t}`))}),p&&(0,B.jsx)(R,{pal:p,id:`box-pal-details-${p.instanceId}`}),a.length>1&&(0,B.jsx)(`div`,{className:`pal-box-tabs`,children:a.map((e,t)=>(0,B.jsx)(`button`,{type:`button`,className:[`pal-box-tab`,t===f?`is-active`:``].filter(Boolean).join(` `),onClick:()=>c(t),children:e.label},e.key))})]})})}function G(e){return e.slice(0,2).toUpperCase()}function K(e){if(e.online)return`now`;let t=new Date(e.lastSeenAt),n=t.getFullYear()===new Date().getFullYear(),r=Math.floor((Date.now()-t.getTime())/864e5),i=t.toLocaleTimeString(void 0,{hour:`2-digit`,minute:`2-digit`,hour12:!1});return r<1?`today ${i}`:r<2?`yesterday ${i}`:`${t.toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:n?void 0:`numeric`})}, ${i}`}function q({p:e}){return e.banned?(0,B.jsx)(x,{tone:`danger`,children:`Banned`}):e.online?(0,B.jsx)(x,{tone:`ok`,children:`Online`}):(0,B.jsx)(x,{tone:`idle`,children:`Offline`})}function J(){let[e,t]=(0,z.useState)(`players`),[r,i]=_(),a=r.get(`player`),s=e=>{let t=new URLSearchParams(r);e?t.set(`player`,e):t.delete(`player`),i(t,{replace:!0})},c=n({queryKey:[`players`],queryFn:()=>o.players.list(),refetchInterval:15e3}),l=n({queryKey:[`guilds`],queryFn:()=>o.guilds.list()}),u=n({queryKey:[`whitelist`],queryFn:()=>o.whitelist.get()}),d=n({queryKey:[`server`,`health`],queryFn:()=>o.server.health()}),f=c.data??[],p=f.filter(e=>e.online).length,m=f.filter(e=>e.banned).length,h=a??f.find(e=>e.online)?.uid??f[0]?.uid??null;return(0,B.jsxs)(`main`,{className:`content`,children:[(0,B.jsxs)(`div`,{className:`page-head`,children:[(0,B.jsx)(`h1`,{children:`Players`}),(0,B.jsx)(`span`,{className:`sub`,children:c.data?`${p} online · ${f.length} known`:`loading…`})]}),(0,B.jsx)(N,{items:[{key:`players`,label:`Players`,count:c.data?f.length:void 0},{key:`guilds`,label:`Guilds`,count:l.data?.length},{key:`whitelist`,label:`Player notes`,count:u.data?.length},{key:`bans`,label:`Bans`,count:c.data?m:void 0}],active:e,onChange:e=>t(e)}),e===`players`&&(0,B.jsx)(Y,{players:f,loading:c.isLoading,error:c.isError,selectedUid:h,onSelect:s,lastSyncAt:d.data?.save.lastSyncAt}),e===`guilds`&&(0,B.jsx)(ie,{}),e===`whitelist`&&(0,B.jsx)(ae,{}),e===`bans`&&(0,B.jsx)(oe,{players:f,error:c.isError})]})}function Y({players:e,loading:t,error:n,selectedUid:r,onSelect:i,lastSyncAt:a}){let o=m(),s=y(),[c,d]=(0,z.useState)(``),[h,_]=(0,z.useState)(`all`),[x,S]=(0,z.useState)(null),[w,T]=(0,z.useState)(null),{playerActionRequest:E,clearPlayerActionRequest:D}=v();(0,z.useEffect)(()=>{if(!E)return;let t=e.find(e=>e.uid===E.uid);t&&(S({kind:E.kind,player:t}),D())},[E,e,D]);let A=(0,z.useMemo)(()=>{let t=c.trim().toLowerCase();return e.filter(e=>!(h===`online`&&!e.online||h===`offline`&&e.online||t&&!e.name.toLowerCase().includes(t)&&!e.steamId.includes(t)))},[e,c,h]);return(0,B.jsxs)(`div`,{className:`players-layout`,children:[(0,B.jsxs)(`div`,{className:`players-main`,children:[(0,B.jsxs)(`div`,{className:`toolbar`,children:[(0,B.jsx)(C,{placeholder:`Search name or Steam ID…`,value:c,onChange:e=>d(e.target.value),"aria-label":`Search players`}),(0,B.jsxs)(`select`,{className:`input`,style:{width:`auto`},value:h,onChange:e=>_(e.target.value),"aria-label":`Filter players`,children:[(0,B.jsx)(`option`,{value:`all`,children:`All players`}),(0,B.jsx)(`option`,{value:`online`,children:`Online now`}),(0,B.jsx)(`option`,{value:`offline`,children:`Offline`})]}),(0,B.jsx)(`div`,{className:`spacer`}),a&&(0,B.jsxs)(`span`,{className:`sync-hint`,children:[`save data synced `,b(a)]})]}),(0,B.jsx)(j,{children:n?(0,B.jsx)(k,{children:(0,B.jsx)(O,{tone:`warn`,children:`Couldn't load players. The save data may not be parsed yet.`})}):t?(0,B.jsx)(k,{children:(0,B.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:120}})}):A.length===0?(0,B.jsx)(k,{children:(0,B.jsx)(M,{icon:(0,B.jsx)(l,{width:40,height:40}),title:`No players match`,description:`Try a different search or filter — players appear here once they've joined the server at least once.`})}):(0,B.jsx)(k,{flush:!0,style:{overflowX:`auto`},children:(0,B.jsxs)(`table`,{className:`table`,children:[(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Player`}),(0,B.jsx)(`th`,{children:`Status`}),(0,B.jsx)(`th`,{children:`Level`}),(0,B.jsx)(`th`,{children:`Guild`}),(0,B.jsx)(`th`,{children:`Ping`}),(0,B.jsx)(`th`,{children:`Last seen`}),(0,B.jsx)(`th`,{className:`actions`})]})}),(0,B.jsx)(`tbody`,{children:A.map(e=>(0,B.jsxs)(`tr`,{className:e.uid===r?`row-selected`:void 0,onClick:()=>i(e.uid),style:{cursor:`pointer`},children:[(0,B.jsx)(`td`,{children:(0,B.jsxs)(`div`,{className:`who-cell`,children:[(0,B.jsx)(V,{name:e.name,uid:e.uid}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`div`,{className:`name`,children:e.name}),(0,B.jsxs)(`div`,{className:`id`,children:[`steam_`,e.steamId]})]})]})}),(0,B.jsx)(`td`,{children:(0,B.jsx)(q,{p:e})}),(0,B.jsx)(`td`,{className:`num`,children:e.level}),(0,B.jsx)(`td`,{onClick:e=>e.stopPropagation(),children:e.guildId&&e.guildName?(0,B.jsx)(g,{to:`/guilds/${encodeURIComponent(e.guildId)}`,children:e.guildName}):`—`}),(0,B.jsx)(`td`,{className:`num`,children:e.ping===null?`—`:`${e.ping} ms`}),(0,B.jsx)(`td`,{className:`num`,children:K(e)}),(0,B.jsx)(`td`,{className:`actions`,onClick:e=>e.stopPropagation(),children:o&&(0,B.jsxs)(p,{triggerLabel:`Actions for ${e.name}`,children:[(0,B.jsx)(f,{onClick:()=>T(e),children:`Message…`}),(0,B.jsx)(f,{disabled:!e.location,onClick:()=>{if(i(e.uid),!e.location)return;let t=u(e.location.x,e.location.y);s(`/map?x=${t.x}&y=${t.y}`)},children:`Show on map`}),e.banned?(0,B.jsx)(f,{onClick:()=>S({kind:`unban`,player:e}),children:`Unban`}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(f,{disabled:!e.online,onClick:()=>S({kind:`kick`,player:e}),children:`Kick…`}),(0,B.jsx)(f,{danger:!0,onClick:()=>S({kind:`ban`,player:e}),children:`Ban…`})]})]})})]},e.uid))})]})})})]}),(0,B.jsx)(X,{uid:r,onAction:(e,t)=>S({kind:e,player:t})}),(0,B.jsx)($,{action:x,onClose:()=>S(null)}),(0,B.jsx)(Q,{open:w!==null,onClose:()=>T(null),playerName:w?.name??``})]})}function X({uid:e,onAction:t}){let r=m(),i=y(),[a,s]=(0,z.useState)(!1),[c,l]=(0,z.useState)(!1),[d,f]=(0,z.useState)(null);(0,z.useEffect)(()=>f(null),[e]);let p=n({queryKey:[`players`,e],queryFn:()=>o.players.detail(e),enabled:e!==null,refetchInterval:6e4});if(!e)return(0,B.jsx)(`aside`,{className:`card`,"aria-label":`Player detail`,children:(0,B.jsx)(k,{children:(0,B.jsx)(M,{title:`No player selected`,description:`Select a row to see save-data detail here.`})})});let h=p.data,_=h?.pals??[],v=_.filter(e=>e.inParty).sort((e,t)=>(e.partySlot??0)-(t.partySlot??0)),b=v.length>0?v:[..._].sort((e,t)=>t.level-e.level).slice(0,5),x=h?.location?u(h.location.x,h.location.y):null;return(0,B.jsx)(`aside`,{className:`card`,"aria-label":`Player detail`,children:p.isError?(0,B.jsx)(k,{children:(0,B.jsx)(O,{tone:`warn`,children:`Couldn't load player detail.`})}):h?(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`div`,{className:`detail-head`,children:[(0,B.jsx)(V,{name:h.name,uid:h.uid}),(0,B.jsxs)(`div`,{style:{minWidth:0},children:[(0,B.jsx)(`h2`,{children:h.name}),(0,B.jsxs)(`div`,{className:`id`,children:[`steam_`,h.steamId,` · uid `,D(h.uid,8,0)]})]}),(0,B.jsx)(`span`,{style:{marginLeft:`auto`},children:(0,B.jsx)(q,{p:h})})]}),(0,B.jsxs)(`div`,{className:`kv`,children:[(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{className:`label`,children:`Level`}),(0,B.jsx)(`span`,{className:`val`,children:h.level})]}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{className:`label`,children:`Guild`}),(0,B.jsx)(`span`,{className:`val`,children:h.guildId&&h.guildName?(0,B.jsx)(g,{to:`/guilds/${encodeURIComponent(h.guildId)}`,children:h.guildName}):`—`})]}),(0,B.jsxs)(`div`,{children:[(0,B.jsxs)(`span`,{className:`label`,children:[`Position `,(0,B.jsx)(`span`,{className:`label-note`,children:`last save`})]}),(0,B.jsx)(`span`,{className:`val`,children:x?`${x.x}, ${x.y}`:`—`})]}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{className:`label`,children:`Ping`}),(0,B.jsx)(`span`,{className:`val`,children:h.ping===null?`—`:`${h.ping} ms`})]}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{className:`label`,children:`First seen`}),(0,B.jsx)(`span`,{className:`val`,children:new Date(h.firstSeenAt).toLocaleDateString(void 0,{month:`short`,day:`numeric`,year:`numeric`})})]}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{className:`label`,children:`Total tracked`}),(0,B.jsx)(`span`,{className:`val`,children:E(h.playtimeSec)})]})]}),(0,B.jsx)(re,{activity:h.activity}),(0,B.jsxs)(`div`,{className:`card-head`,style:{borderTop:`1px solid var(--line)`},children:[(0,B.jsx)(`h2`,{children:`Pals`}),(0,B.jsx)(`span`,{className:`hint`,children:v.length>0?`party of ${v.length} · ${_.length} owned`:`${_.length} owned`})]}),(0,B.jsxs)(`div`,{children:[_.length===0&&(0,B.jsx)(`div`,{className:`pal-row`,style:{color:`var(--ink-3)`},children:`No Pals in the latest save.`}),b.map(e=>{let t=`player-pal-details-${e.instanceId}`,n=d===e.instanceId;return(0,B.jsxs)(`div`,{className:`pal-entry`,children:[(0,B.jsxs)(`div`,{className:`pal-row`,children:[(0,B.jsx)(F,{characterId:e.characterId,displayName:e.displayName}),` `,e.displayName,e.isAlpha&&(0,B.jsx)(`span`,{className:`pal-tag alpha`,children:`α`}),e.isLucky&&(0,B.jsx)(`span`,{className:`pal-tag lucky`,children:`✦`}),(0,B.jsxs)(`span`,{className:`lvl`,children:[`Lv `,e.level]}),(0,B.jsx)(L,{pal:e,expanded:n,controls:t,onClick:()=>f(n?null:e.instanceId)})]}),n&&(0,B.jsx)(R,{pal:e,id:t})]},e.instanceId)}),_.length>b.length&&(0,B.jsxs)(`button`,{type:`button`,className:`pal-more`,onClick:()=>s(!0),children:[`show all `,_.length]})]}),(0,B.jsx)(W,{open:a,onClose:()=>s(!1),playerName:h.name,pals:_}),r&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`div`,{className:`card-head`,style:{borderTop:`1px solid var(--line)`},children:(0,B.jsx)(`h2`,{children:`Actions`})}),(0,B.jsxs)(k,{style:{display:`flex`,gap:`var(--space-2)`,flexWrap:`wrap`},children:[(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:()=>l(!0),children:`Message`}),(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm`,disabled:!x,onClick:()=>x&&i(`/map?x=${x.x}&y=${x.y}`),children:`Show on map`}),h.banned?(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:()=>t(`unban`,h),children:`Unban`}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm btn-ghost`,disabled:!h.online,onClick:()=>t(`kick`,h),children:`Kick…`}),(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm btn-danger`,onClick:()=>t(`ban`,h),children:`Ban…`})]})]})]}),(0,B.jsx)(Q,{open:c,onClose:()=>l(!1),playerName:h.name})]}):(0,B.jsx)(k,{children:(0,B.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:60}})})})}function re({activity:e}){return(0,B.jsxs)(`section`,{className:`player-activity`,"aria-label":`Observed player activity`,children:[(0,B.jsxs)(`div`,{className:`card-head`,children:[(0,B.jsx)(`h2`,{children:`Observed activity`}),(0,B.jsx)(`span`,{className:`hint`,children:`panel tracking only`})]}),e.trackingSince===null?(0,B.jsx)(`div`,{className:`player-activity-empty`,children:`No sessions observed yet.`}):(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`div`,{className:`player-activity-current`,children:[(0,B.jsx)(`span`,{children:`Current session`}),(0,B.jsx)(`strong`,{children:e.currentSession?E(e.currentSession.durationSec):`Offline`})]}),(0,B.jsxs)(`div`,{className:`player-activity-windows`,children:[(0,B.jsx)(Z,{label:`24 hours`,value:e.windows.last24Hours}),(0,B.jsx)(Z,{label:`7 days`,value:e.windows.last7Days}),(0,B.jsx)(Z,{label:`30 days`,value:e.windows.last30Days})]}),(0,B.jsxs)(`p`,{className:`player-activity-coverage`,children:[`Tracked since `,new Date(e.trackingSince).toLocaleString(),`.`,e.recentSessionsTruncated?` Showing the 20 most recent sessions.`:``]})]})]})}function Z({label:e,value:t}){return(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`span`,{children:e}),(0,B.jsx)(`strong`,{children:E(t.durationSec)}),(0,B.jsxs)(`small`,{children:[t.sessionCount,` `,t.sessionCount===1?`session`:`sessions`]})]})}function Q({open:e,onClose:t,playerName:n}){let[r,i]=(0,z.useState)(``),[a,s]=(0,z.useState)(!1),c=h();async function l(){if(r.trim()){s(!0);try{await o.server.announce(`@${n}: ${r.trim()}`),c.push(`Broadcast sent.`,`ok`),i(``),t()}catch{c.push(`Broadcast failed. Try again.`,`danger`)}finally{s(!1)}}}return(0,B.jsxs)(w,{open:e,title:`Message ${n}`,onClose:t,footer:(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:t,children:`Cancel`}),(0,B.jsx)(`button`,{type:`button`,className:`btn btn-primary`,onClick:l,disabled:a||!r.trim(),children:a?`Sending…`:`Send broadcast`})]}),children:[(0,B.jsxs)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:[`The vanilla server has no private messages — this broadcasts to all players, prefixed with @`,n,`.`]}),(0,B.jsx)(T,{label:`Message`,value:r,onChange:e=>i(e.target.value),autoFocus:!0})]})}function $({action:e,onClose:n}){let r=t(),i=h(),[a,s]=(0,z.useState)(``),c=d({mutationFn:async e=>{let t=a.trim()||void 0;return e.kind===`kick`?await o.players.kick(e.player.uid,t):e.kind===`ban`?await o.players.ban(e.player.uid,t):await o.players.unban(e.player.uid),e},onSuccess:e=>{let t=e.kind===`kick`?`kicked`:e.kind===`ban`?`banned`:`unbanned`;i.push(`${e.player.name} ${t}.`,`ok`),r.invalidateQueries({queryKey:[`players`]}),r.invalidateQueries({queryKey:[`events`]}),s(``),n()},onError:()=>{i.push(`Action failed. Check the server connection and try again.`,`danger`)}}),l=e?.kind,u=e?.player,f=e?l===`kick`?`Kick ${u.name}…`:l===`ban`?`Ban ${u.name}…`:`Unban ${u.name}`:``;return(0,B.jsxs)(S,{open:e!==null,title:f,onClose:()=>{s(``),n()},onConfirm:()=>e&&c.mutate(e),confirmLabel:l===`kick`?`Kick player`:l===`ban`?`Ban player`:`Unban player`,danger:l!==`unban`,busy:c.isPending,children:[l===`kick`&&u&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:[`Disconnects `,u.name,` from the server. They can rejoin immediately.`]}),(0,B.jsx)(T,{label:`Message shown to the player (optional)`,value:a,onChange:e=>s(e.target.value),autoFocus:!0})]}),l===`ban`&&u&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsxs)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:[`Bans steam_`,u.steamId,` from the server until unbanned. If online, they are disconnected now.`]}),(0,B.jsx)(T,{label:`Message shown to the player (optional)`,value:a,onChange:e=>s(e.target.value),autoFocus:!0})]}),l===`unban`&&u&&(0,B.jsxs)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:[`Removes the ban on steam_`,u.steamId,`. They can rejoin the server.`]})]})}function ie(){let e=n({queryKey:[`guilds`],queryFn:()=>o.guilds.list()});return(0,B.jsx)(j,{children:e.isError?(0,B.jsx)(k,{children:(0,B.jsx)(O,{tone:`warn`,children:`Couldn't load guilds from save data.`})}):e.isLoading?(0,B.jsx)(k,{children:(0,B.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:120}})}):(0,B.jsx)(k,{flush:!0,style:{overflowX:`auto`},children:(0,B.jsxs)(`table`,{className:`table`,children:[(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Guild`}),(0,B.jsx)(`th`,{children:`Members`}),(0,B.jsx)(`th`,{children:`Bases`}),(0,B.jsx)(`th`,{children:`Roster`})]})}),(0,B.jsx)(`tbody`,{children:(e.data??[]).map(e=>(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`td`,{children:(0,B.jsxs)(`div`,{className:`who-cell`,children:[(0,B.jsx)(`span`,{className:`avatar`,children:G(P(e))}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`div`,{className:`name`,children:(0,B.jsx)(g,{to:`/guilds/${encodeURIComponent(e.id)}`,children:P(e)})}),(0,B.jsx)(`div`,{className:`id`,children:e.id})]})]})}),(0,B.jsx)(`td`,{className:`num`,children:e.memberCount}),(0,B.jsx)(`td`,{className:`num`,children:e.bases.length}),(0,B.jsx)(`td`,{style:{color:`var(--ink-2)`},children:e.members.length>0?e.members.map(e=>e.name).join(`, `):(0,B.jsx)(`span`,{style:{color:`var(--ink-3)`},children:`no known players`})})]},e.id))})]})})})}function ae(){let e=m(),r=t(),i=h(),a=n({queryKey:[`whitelist`],queryFn:()=>o.whitelist.get()}),[s,c]=(0,z.useState)(null),l=s??a.data??[],u=s!==null,f=d({mutationFn:e=>o.whitelist.put(e.filter(e=>e.steamId.trim()!==``)),onSuccess:e=>{r.setQueryData([`whitelist`],e),r.invalidateQueries({queryKey:[`players`]}),c(null),i.push(`Player notes saved.`,`ok`)},onError:()=>i.push(`Couldn't save player notes. Try again.`,`danger`)});function p(e,t){c(l.map((n,r)=>r===e?{...n,...t}:n))}return(0,B.jsxs)(j,{children:[(0,B.jsx)(A,{title:`Player notes`,hint:`local labels only — does not control who can join`}),a.isError?(0,B.jsx)(k,{children:(0,B.jsx)(O,{tone:`warn`,children:`Couldn't load player notes.`})}):a.isLoading?(0,B.jsx)(k,{children:(0,B.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:80}})}):(0,B.jsxs)(k,{flush:!0,children:[l.length===0&&(0,B.jsx)(M,{title:`No player notes`,description:e?`Add Steam IDs to label players in Palhelm. These notes are not enforced by Palworld.`:`No local player annotations yet.`}),l.map((t,n)=>(0,B.jsxs)(`div`,{className:`whitelist-row`,children:[(0,B.jsx)(`input`,{className:`input input-mono`,value:t.steamId,placeholder:`7656119…`,"aria-label":`Steam ID`,readOnly:!e,onChange:e=>p(n,{steamId:e.target.value})}),(0,B.jsx)(`input`,{className:`input`,value:t.name??``,placeholder:`name (optional)`,"aria-label":`Player name`,readOnly:!e,onChange:e=>p(n,{name:e.target.value})}),e&&(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm btn-ghost`,"aria-label":`Remove ${t.name||t.steamId}`,onClick:()=>c(l.filter((e,t)=>t!==n)),children:`Remove`})]},n)),e&&(0,B.jsxs)(`div`,{className:`whitelist-foot`,children:[(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:()=>c([...l,{steamId:``,name:``}]),children:`+ Add entry`}),(0,B.jsx)(`div`,{style:{flex:1}}),u&&(0,B.jsxs)(B.Fragment,{children:[(0,B.jsx)(`button`,{type:`button`,className:`btn btn-ghost btn-sm`,onClick:()=>c(null),children:`Discard`}),(0,B.jsx)(`button`,{type:`button`,className:`btn btn-primary btn-sm`,disabled:f.isPending,onClick:()=>f.mutate(l),children:f.isPending?`Saving…`:`Save player notes`})]})]})]})]})}function oe({players:e,error:t}){let n=m(),[r,i]=(0,z.useState)(null),a=e.filter(e=>e.banned);return(0,B.jsxs)(j,{children:[t?(0,B.jsx)(k,{children:(0,B.jsx)(O,{tone:`warn`,children:`Couldn't load players.`})}):a.length===0?(0,B.jsx)(k,{children:(0,B.jsx)(M,{icon:(0,B.jsx)(l,{width:40,height:40}),title:`No banned players`,description:`Players you ban appear here so the ban can be reviewed or lifted.`})}):(0,B.jsx)(k,{flush:!0,style:{overflowX:`auto`},children:(0,B.jsxs)(`table`,{className:`table`,children:[(0,B.jsx)(`thead`,{children:(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`th`,{children:`Player`}),(0,B.jsx)(`th`,{children:`Level`}),(0,B.jsx)(`th`,{children:`Last seen`}),(0,B.jsx)(`th`,{className:`actions`})]})}),(0,B.jsx)(`tbody`,{children:a.map(e=>(0,B.jsxs)(`tr`,{children:[(0,B.jsx)(`td`,{children:(0,B.jsxs)(`div`,{className:`who-cell`,children:[(0,B.jsx)(V,{name:e.name,uid:e.uid}),(0,B.jsxs)(`div`,{children:[(0,B.jsx)(`div`,{className:`name`,children:e.name}),(0,B.jsxs)(`div`,{className:`id`,children:[`steam_`,e.steamId]})]})]})}),(0,B.jsx)(`td`,{className:`num`,children:e.level}),(0,B.jsx)(`td`,{className:`num`,children:K(e)}),(0,B.jsx)(`td`,{className:`actions`,children:n&&(0,B.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:()=>i({kind:`unban`,player:e}),children:`Unban`})})]},e.uid))})]})}),(0,B.jsx)($,{action:r,onClose:()=>i(null)})]})}export{J as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Settings-DDAtAokj.css b/backend/internal/webdist/dist/assets/Settings-DDAtAokj.css
new file mode 100644
index 0000000..304bb18
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Settings-DDAtAokj.css
@@ -0,0 +1 @@
+.kv-row{border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;gap:var(--space-3);padding:8px 0;display:flex}.kv-row:last-child{border-bottom:0}.kv-row .k{font-size:var(--text-sm);color:var(--ink-2);flex:none}.kv-row .v{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.theme-row{gap:var(--space-2);display:flex}.theme-row .btn[aria-pressed=true]{background:var(--accent);color:var(--on-accent);border-color:#0000}.theme-row .btn[aria-pressed=true]:hover{background:var(--accent);filter:brightness(1.08)}.about-links{gap:var(--space-4);font-size:var(--text-sm);display:flex}.field-hint{font-size:var(--text-xs);color:var(--ink-3)}.field-hint.mono{font-family:var(--font-mono)}.key-reveal-row{align-items:center;gap:var(--space-2);display:flex}.key-reveal-row .code-well{flex:1;min-width:0}.key-reveal-value{word-break:break-all;display:block}
diff --git a/backend/internal/webdist/dist/assets/Settings-urvtAKwL.js b/backend/internal/webdist/dist/assets/Settings-urvtAKwL.js
new file mode 100644
index 0000000..065989c
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Settings-urvtAKwL.js
@@ -0,0 +1 @@
+import{H as e,K as t,U as n,_t as r,ht as i,j as a,q as o}from"./icons-CpYMTu_k.js";import{t as s}from"./useMutation-S28PAV4D.js";import{An as c,Dn as l,c as u,d,f,n as p,o as m,p as h,r as g,t as _}from"./index-BpCavHBc.js";import{t as v}from"./Banner-DSN1nEJn.js";import{n as y,r as b,t as x}from"./Card-D55CMzdw.js";import{t as S}from"./EmptyState-DTSMkv56.js";import{t as C}from"./CodeWell-Mu33yg_R.js";var w=r(i(),1),T=o();function E(){let e=c(),t=n({queryKey:[`server`],queryFn:()=>a.server.get()}),r=n({queryKey:[`server`,`health`],queryFn:()=>a.server.health(),refetchInterval:15e3}),i=n({queryKey:[`config`],queryFn:()=>a.config.get()}),o=r.data,s=t.data?.panelVersion;return(0,T.jsxs)(`main`,{className:`content`,children:[(0,T.jsx)(`div`,{className:`page-head`,children:(0,T.jsx)(`h1`,{children:`Panel settings`})}),(0,T.jsxs)(`div`,{className:`grid cols-2`,children:[(0,T.jsxs)(x,{children:[(0,T.jsx)(b,{title:`Connections`}),r.isError?(0,T.jsx)(y,{children:(0,T.jsx)(v,{tone:`warn`,children:`Couldn't reach the panel API for connection health.`})}):(0,T.jsx)(y,{flush:!0,children:(0,T.jsx)(`table`,{className:`table`,children:(0,T.jsxs)(`tbody`,{children:[(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`REST API`}),(0,T.jsx)(`td`,{className:`num`,children:`game server`}),(0,T.jsx)(`td`,{children:o?(0,T.jsx)(d,{tone:o.rest===`ok`?`ok`:`danger`,children:o.rest===`ok`?`Connected`:`Error`}):`—`})]}),(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`RCON`}),(0,T.jsx)(`td`,{className:`num`,children:`game server`}),(0,T.jsx)(`td`,{children:o?(0,T.jsx)(d,{tone:o.rcon===`ok`?`ok`:`danger`,children:o.rcon===`ok`?`Connected`:`Error`}):`—`})]}),(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`Save data`}),(0,T.jsx)(`td`,{className:`num`,children:`mounted volume`}),(0,T.jsx)(`td`,{children:o?(0,T.jsx)(d,{tone:o.save.state===`ok`?`ok`:`danger`,children:o.save.state===`ok`?`synced ${u(o.save.lastSyncAt)}`:`Error`}):`—`})]}),(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`td`,{style:{color:`var(--ink-2)`},children:`Compose file`}),(0,T.jsx)(`td`,{className:`num`,title:i.data?.composeFile,children:i.data?.composeFile??`—`}),(0,T.jsx)(`td`,{children:(0,T.jsx)(d,{tone:`idle`,children:`read-write`})})]})]})})})]}),(0,T.jsx)(O,{})]}),(0,T.jsx)(`div`,{className:`grid cols-2`,children:(0,T.jsx)(D,{})}),(0,T.jsxs)(`div`,{className:`grid cols-2`,children:[(0,T.jsxs)(x,{children:[(0,T.jsx)(b,{title:`Authentication`}),(0,T.jsxs)(y,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-3)`},children:[(0,T.jsxs)(`div`,{className:`field`,children:[(0,T.jsx)(`label`,{htmlFor:`auth-admin`,children:`Admin password`}),(0,T.jsx)(`input`,{id:`auth-admin`,className:`input input-mono`,type:`text`,value:`PALHELM_ADMIN_PASSWORD`,readOnly:!0}),(0,T.jsx)(`span`,{className:`field-hint`,children:`set via environment variable — not editable from the panel`})]}),(0,T.jsxs)(`div`,{className:`field`,children:[(0,T.jsx)(`label`,{htmlFor:`auth-viewer`,children:`Viewer role`}),(0,T.jsx)(`input`,{id:`auth-viewer`,className:`input input-mono`,type:`text`,value:`PALHELM_VIEWER_PASSWORD`,readOnly:!0}),(0,T.jsx)(`span`,{className:`field-hint`,children:`optional read-only login, also configured via environment variable`})]}),(0,T.jsxs)(`div`,{className:`field`,children:[(0,T.jsx)(`label`,{htmlFor:`auth-session`,children:`Session duration`}),(0,T.jsx)(`input`,{id:`auth-session`,className:`input`,style:{width:200},type:`text`,value:t.data?.sessionDays==null?`—`:`${t.data.sessionDays} day${t.data.sessionDays===1?``:`s`}`,readOnly:!0}),(0,T.jsx)(`span`,{className:`field-hint`,children:`configured via PALHELM_SESSION_DAYS`})]})]})]}),(0,T.jsx)(k,{})]}),e&&(0,T.jsx)(`div`,{className:`grid cols-2`,children:(0,T.jsx)(M,{})}),(0,T.jsx)(`div`,{className:`grid cols-2`,children:(0,T.jsxs)(x,{className:`span-2`,children:[(0,T.jsx)(b,{title:`About`}),(0,T.jsxs)(y,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-2)`},children:[(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Palhelm`}),(0,T.jsx)(`span`,{className:`v`,children:s?`v${s}`:`—`})]}),(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`License`}),(0,T.jsx)(`span`,{className:`v`,children:`Apache-2.0`})]}),(0,T.jsxs)(`div`,{className:`about-links`,children:[(0,T.jsx)(`a`,{href:`https://docs.palhelm.com`,target:`_blank`,rel:`noreferrer`,children:`Documentation`}),(0,T.jsx)(`a`,{href:`https://github.com/8tp/palhelm`,target:`_blank`,rel:`noreferrer`,children:`Source`}),(0,T.jsx)(`a`,{href:`https://github.com/8tp/palhelm/issues`,target:`_blank`,rel:`noreferrer`,children:`Report an issue`}),(0,T.jsx)(`a`,{href:`https://github.com/8tp/palhelm/releases`,target:`_blank`,rel:`noreferrer`,children:`Release notes`})]})]})]})})]})}function D(){let e=n({queryKey:[`world`,`snapshot`],queryFn:()=>a.world.snapshot(),refetchInterval:15e3}),t=e.data,r=t?.state??`pending`,i=r===`ready`?`ok`:r===`pending`?`idle`:`warn`,o=t?.diagnostics,s=t?.activity;return(0,T.jsxs)(x,{className:`span-2`,children:[(0,T.jsx)(b,{title:`Game Data API diagnostics`,children:(0,T.jsx)(d,{tone:i,children:r})}),(0,T.jsx)(y,{children:e.isError?(0,T.jsx)(v,{tone:`warn`,children:`Couldn't load Game Data API diagnostics.`}):(0,T.jsxs)(T.Fragment,{children:[(0,T.jsxs)(`div`,{className:`grid cols-2`,children:[(0,T.jsxs)(`div`,{children:[(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Snapshot freshness`}),(0,T.jsx)(`span`,{className:`v`,children:t?.capturedAt?u(t.capturedAt):`no accepted snapshot`})]}),(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Upstream request`}),(0,T.jsx)(`span`,{className:`v mono`,children:o?`${o.lastRequestDurationMs} ms`:`—`})]}),(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Loaded actors`}),(0,T.jsx)(`span`,{className:`v mono`,children:o?.lastAcceptedActorCount??`—`})]}),(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`FPS`}),(0,T.jsx)(`span`,{className:`v mono`,children:t?`${t.fps.toFixed(1)} · avg ${t.fpsAvg.toFixed(1)}`:`—`})]})]}),(0,T.jsxs)(`div`,{children:[(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Linked workers`}),(0,T.jsx)(`span`,{className:`v mono`,children:o?`${o.linkedBasePals}/${t?.counts.basePals??0}`:`—`})]}),(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Unresolved workers`}),(0,T.jsx)(`span`,{className:`v mono`,children:o?.unresolvedBasePals??`—`})]}),(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Last poll result`}),(0,T.jsx)(`span`,{className:`v`,children:o?.lastErrorCategory??`—`})]}),(0,T.jsxs)(`div`,{className:`kv-row`,children:[(0,T.jsx)(`span`,{className:`k`,children:`Next attempt`}),(0,T.jsx)(`span`,{className:`v`,children:o?.nextAttemptAt?u(o.nextAttemptAt):`not scheduled`})]})]})]}),o?.linkLookupFailed&&(0,T.jsx)(v,{tone:`warn`,children:`The snapshot loaded, but workers couldn't be matched to their save identities.`}),s&&(0,T.jsxs)(`p`,{className:`field-hint mono`,style:{marginTop:`var(--space-3)`},children:[`workers · `,s.working,` working · `,s.transporting,` transporting · `,s.eating,` eating · `,s.sleeping,` sleeping · `,s.idle,` idle · `,s.incapacitated,` incapacitated · `,s.unknown,` unknown`]})]})})]})}function O(){let e=c(),r=t(),i=l(),o=n({queryKey:[`world`],queryFn:()=>a.world.get()}),u=n({queryKey:[`server`],queryFn:()=>a.server.get()}).data?.saveSyncMinutes,f=s({mutationFn:()=>a.world.parse(),onSuccess:()=>{i.push(`Save re-parse started.`,`ok`),r.invalidateQueries({queryKey:[`world`]}),r.invalidateQueries({queryKey:[`players`]}),r.invalidateQueries({queryKey:[`guilds`]})},onError:()=>i.push(`Parse is already running or failed to start.`,`danger`)}),p=o.data;return(0,T.jsxs)(x,{children:[(0,T.jsx)(b,{title:`Save sync`,children:p?.formatDrift&&(0,T.jsx)(d,{tone:`warn`,children:`format drift`})}),o.isError?(0,T.jsx)(y,{children:(0,T.jsx)(v,{tone:`warn`,children:`Couldn't load save-sync status.`})}):(0,T.jsxs)(y,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-3)`},children:[(0,T.jsxs)(`div`,{className:`field`,children:[(0,T.jsx)(`label`,{htmlFor:`sync-interval`,children:`Interval`}),(0,T.jsx)(`input`,{id:`sync-interval`,className:`input`,style:{width:200},type:`text`,value:u==null?`—`:`${u} minute${u===1?``:`s`}`,readOnly:!0}),(0,T.jsx)(`span`,{className:`field-hint`,children:`configured via PALHELM_SAVE_SYNC_INTERVAL`})]}),e&&(0,T.jsx)(`div`,{children:(0,T.jsx)(`button`,{type:`button`,className:`btn`,disabled:f.isPending,onClick:()=>f.mutate(),children:f.isPending?`Parsing…`:`Parse now`})}),p&&(0,T.jsxs)(`span`,{className:`field-hint mono`,children:[`last parse `,(p.parseDurationMs/1e3).toFixed(1),` s · `,p.stats.guilds,` guilds · `,p.stats.players,` players ·`,` `,p.stats.skippedProps,` skipped properties`]})]})]})}function k(){let[e,t]=(0,w.useState)(()=>p());function n(e){_(e),t(e)}return(0,T.jsxs)(x,{children:[(0,T.jsx)(b,{title:`Appearance`}),(0,T.jsx)(y,{children:(0,T.jsxs)(`div`,{className:`field`,children:[(0,T.jsx)(`label`,{children:`Theme`}),(0,T.jsx)(`div`,{className:`theme-row`,role:`radiogroup`,"aria-label":`Theme`,children:[{key:`system`,label:`System`},{key:`dark`,label:`Dark`},{key:`light`,label:`Light`}].map(t=>(0,T.jsx)(`button`,{type:`button`,className:`btn`,role:`radio`,"aria-pressed":e===t.key,"aria-checked":e===t.key,onClick:()=>n(t.key),children:t.label},t.key))})]})})]})}var A=64,j=100;function M(){let e=t(),r=l(),i=n({queryKey:[`integration-keys`],queryFn:()=>a.integrationKeys.list()}),[o,c]=(0,w.useState)(!1),[p,h]=(0,w.useState)(null),[g,_]=(0,w.useState)(null),E=s({mutationFn:e=>a.integrationKeys.revoke(e),onSuccess:()=>{e.invalidateQueries({queryKey:[`integration-keys`]}),r.push(`Integration key revoked.`,`ok`),h(null)},onError:()=>r.push(`Couldn't revoke the key. Try again.`,`danger`)}),D=i.data??[],O=D.filter(e=>e.revokedAt===null).length,k=O>=j;return(0,T.jsxs)(x,{className:`span-2`,children:[(0,T.jsx)(b,{title:`Integration API`,hint:`${O} active key${O===1?``:`s`}`,children:(0,T.jsx)(`button`,{type:`button`,className:`btn btn-sm`,disabled:k,onClick:()=>c(!0),children:`+ New key`})}),i.isError?(0,T.jsx)(y,{children:(0,T.jsx)(v,{tone:`warn`,children:`Couldn't load integration keys.`})}):i.isLoading?(0,T.jsx)(y,{children:(0,T.jsx)(`span`,{className:`skel skel-text`,style:{width:`100%`,height:80}})}):D.length===0?(0,T.jsx)(y,{children:(0,T.jsx)(S,{title:`No integration keys yet`,description:`Create a key to let a bot or dashboard read player, pal, and guild data over the read-only Integration API.`})}):(0,T.jsx)(y,{flush:!0,style:{overflowX:`auto`},children:(0,T.jsxs)(`table`,{className:`table`,children:[(0,T.jsx)(`thead`,{children:(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`th`,{children:`Label`}),(0,T.jsx)(`th`,{children:`Key ID`}),(0,T.jsx)(`th`,{children:`Created`}),(0,T.jsx)(`th`,{children:`Last used`}),(0,T.jsx)(`th`,{children:`Status`}),(0,T.jsx)(`th`,{})]})}),(0,T.jsx)(`tbody`,{children:D.map(e=>(0,T.jsxs)(`tr`,{children:[(0,T.jsx)(`td`,{children:e.label}),(0,T.jsx)(`td`,{className:`num`,children:e.id}),(0,T.jsx)(`td`,{className:`num`,children:m(e.createdAt)}),(0,T.jsx)(`td`,{className:`num`,children:u(e.lastUsedAt)}),(0,T.jsx)(`td`,{children:(0,T.jsx)(d,{tone:e.revokedAt?`idle`:`ok`,children:e.revokedAt?`revoked`:`active`})}),(0,T.jsx)(`td`,{style:{textAlign:`right`},children:!e.revokedAt&&(0,T.jsx)(`button`,{type:`button`,className:`btn btn-sm btn-ghost`,onClick:()=>h(e),children:`Revoke`})})]},e.id))})]})}),k&&(0,T.jsx)(y,{style:{paddingTop:0},children:(0,T.jsxs)(v,{tone:`warn`,children:[`Active key limit reached (`,j,`/`,j,`) — revoke a key before creating another.`]})}),(0,T.jsxs)(y,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-2)`,paddingTop:0},children:[(0,T.jsx)(`span`,{className:`field-hint`,children:`Read-only bearer-token access for bots and dashboards:`}),(0,T.jsx)(C,{children:`curl -H "Authorization: Bearer phk_..." https://host/api/integration/v1/players`})]}),(0,T.jsx)(N,{open:o,onClose:()=>c(!1),onCreated:t=>{c(!1),_(t),e.invalidateQueries({queryKey:[`integration-keys`]})}}),(0,T.jsx)(P,{keyRecord:g,onClose:()=>_(null)}),(0,T.jsx)(f,{open:p!==null,title:`Revoke "${p?.label??``}"`,onClose:()=>h(null),danger:!0,confirmLabel:`Revoke key`,busy:E.isPending,onConfirm:()=>{p&&E.mutate(p.id)},children:(0,T.jsx)(`p`,{style:{color:`var(--ink-2)`,fontSize:`var(--text-sm)`},children:`Any bot or script using this key immediately loses access. This can't be undone — issue a new key to replace it.`})})]})}function N({open:t,onClose:n,onCreated:r}){let[i,o]=(0,w.useState)(``),c=s({mutationFn:e=>a.integrationKeys.create(e),onSuccess:e=>{o(``),c.reset(),r(e)}});function l(){o(``),c.reset(),n()}let u=i.trim(),d=c.isError&&c.error instanceof e?c.error.message:c.isError?`Couldn't create the key. Try again.`:null;return(0,T.jsxs)(h,{open:t,title:`New integration key`,onClose:l,footer:(0,T.jsxs)(T.Fragment,{children:[(0,T.jsx)(`button`,{type:`button`,className:`btn btn-ghost`,onClick:l,children:`Cancel`}),(0,T.jsx)(`button`,{type:`button`,className:`btn btn-primary`,disabled:!u||u.length>A||c.isPending,onClick:()=>c.mutate(u),children:c.isPending?`Creating…`:`Create key`})]}),children:[(0,T.jsx)(g,{label:`Label`,placeholder:`discord-bot`,value:i,maxLength:A,autoFocus:!0,onChange:e=>o(e.target.value),hint:(0,T.jsxs)(`span`,{className:`field-hint`,children:[u.length,`/`,A,` — identifies this key in the list below; never sent to bots`]})}),d&&(0,T.jsx)(v,{tone:`warn`,children:d})]})}function P({keyRecord:e,onClose:t}){let n=l();async function r(){if(e)try{await navigator.clipboard.writeText(e.key),n.push(`Key copied to clipboard.`,`ok`)}catch{n.push(`Couldn't copy automatically — select and copy the key manually.`,`danger`)}}return(0,T.jsx)(h,{open:e!==null,title:`Integration key created`,onClose:t,footer:(0,T.jsx)(`button`,{type:`button`,className:`btn btn-primary`,onClick:t,children:`Done — I've saved it`}),children:e&&(0,T.jsxs)(`div`,{style:{display:`flex`,flexDirection:`column`,gap:`var(--space-3)`},children:[(0,T.jsx)(v,{tone:`warn`,children:`This key is shown once and will not be shown again — Palhelm never stores the plaintext. Copy it now.`}),(0,T.jsxs)(`div`,{className:`field`,children:[(0,T.jsx)(`span`,{style:{fontSize:`var(--text-sm)`,fontWeight:500,color:`var(--ink-2)`},children:e.label}),(0,T.jsxs)(`div`,{className:`key-reveal-row`,children:[(0,T.jsx)(C,{children:(0,T.jsx)(`span`,{className:`key-reveal-value`,children:e.key})}),(0,T.jsx)(`button`,{type:`button`,className:`btn btn-sm`,onClick:r,children:`Copy`})]})]})]})})}export{E as default};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/Tabs-DecjeYAq.js b/backend/internal/webdist/dist/assets/Tabs-DecjeYAq.js
new file mode 100644
index 0000000..6332013
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Tabs-DecjeYAq.js
@@ -0,0 +1 @@
+import{q as e}from"./icons-CpYMTu_k.js";var t=e();function n({items:e,active:n,onChange:r}){return(0,t.jsx)(`div`,{className:`tabs`,role:`tablist`,children:e.map(e=>(0,t.jsxs)(`button`,{type:`button`,role:`tab`,className:`tab`,"aria-selected":e.key===n,onClick:()=>r(e.key),children:[e.label,e.count!==void 0&&(0,t.jsx)(`span`,{className:`count`,children:e.count})]},e.key))})}export{n as t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/guildDisplay-LZYrk7hc.js b/backend/internal/webdist/dist/assets/guildDisplay-LZYrk7hc.js
new file mode 100644
index 0000000..c622dea
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/guildDisplay-LZYrk7hc.js
@@ -0,0 +1 @@
+function e(e){let t=(e??``).trim();return t===``||t.toLowerCase()===`unnamed guild`}function t(t){let n=(t.name??``).trim();if(!e(n))return n;let r=(t.members??[]).filter(e=>(e.name??``).trim()!==``);return r.length===0?`Unnamed guild`:`${((t.adminUid?r.find(e=>e.uid===t.adminUid):void 0)??r[0]).name.trim()}'s guild`}export{t};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/hero-paper-Dw4QRDvw.png b/backend/internal/webdist/dist/assets/hero-paper-Dw4QRDvw.png
new file mode 100644
index 0000000..6916bfb
Binary files /dev/null and b/backend/internal/webdist/dist/assets/hero-paper-Dw4QRDvw.png differ
diff --git a/backend/internal/webdist/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 b/backend/internal/webdist/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2
new file mode 100644
index 0000000..0804aaf
Binary files /dev/null and b/backend/internal/webdist/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 differ
diff --git a/backend/internal/webdist/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 b/backend/internal/webdist/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2
new file mode 100644
index 0000000..67aeeb0
Binary files /dev/null and b/backend/internal/webdist/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 differ
diff --git a/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 b/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2
new file mode 100644
index 0000000..f0ee65d
Binary files /dev/null and b/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2 differ
diff --git a/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 b/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2
new file mode 100644
index 0000000..6d5527e
Binary files /dev/null and b/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2 differ
diff --git a/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 b/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2
new file mode 100644
index 0000000..08c0d5a
Binary files /dev/null and b/backend/internal/webdist/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2 differ
diff --git a/backend/internal/webdist/dist/assets/icons-CpYMTu_k.js b/backend/internal/webdist/dist/assets/icons-CpYMTu_k.js
new file mode 100644
index 0000000..c51c404
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/icons-CpYMTu_k.js
@@ -0,0 +1,5 @@
+var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,o)=>(o=n==null?{}:e(i(n)),s(r||!n||!n.__esModule||!a.call(n,`default`)?t(o,`default`,{value:n,enumerable:!0}):o,n)),l=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var S=Array.isArray;function C(){}var w={H:null,A:null,T:null,S:null},ee=Object.prototype.hasOwnProperty;function T(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function E(e,t){return T(e.type,t,e.props)}function D(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function te(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var O=/\/+/g;function k(e,t){return typeof e==`object`&&e&&e.key!=null?te(``+e.key):t.toString(36)}function A(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(C,C):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function j(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,j(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+k(e,0):a,S(o)?(i=``,c!=null&&(i=c.replace(O,`$&/`)+`/`),j(o,r,i,``,function(e){return e})):o!=null&&(D(o)&&(o=E(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(O,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(S(e))for(var u=0;u{t.exports=l()})),d=class{constructor(){this.listeners=new Set,this.subscribe=this.subscribe.bind(this)}subscribe(e){return this.listeners.add(e),this.onSubscribe(),()=>{this.listeners.delete(e),this.onUnsubscribe()}}hasListeners(){return this.listeners.size>0}onSubscribe(){}onUnsubscribe(){}},f=new class extends d{#e;#t;#n;constructor(){super(),this.#n=e=>{if(typeof window<`u`&&window.addEventListener){let t=()=>e();return window.addEventListener(`visibilitychange`,t,!1),()=>{window.removeEventListener(`visibilitychange`,t)}}}}onSubscribe(){this.#t||this.setEventListener(this.#n)}onUnsubscribe(){this.hasListeners()||(this.#t?.(),this.#t=void 0)}setEventListener(e){this.#n=e,this.#t?.(),this.#t=e(e=>{typeof e==`boolean`?this.setFocused(e):this.onFocus()})}setFocused(e){this.#e!==e&&(this.#e=e,this.onFocus())}onFocus(){let e=this.isFocused();this.listeners.forEach(t=>{t(e)})}isFocused(){return typeof this.#e==`boolean`?this.#e:globalThis.document?.visibilityState!==`hidden`}},p={setTimeout:(e,t)=>setTimeout(e,t),clearTimeout:e=>clearTimeout(e),setInterval:(e,t)=>setInterval(e,t),clearInterval:e=>clearInterval(e)},m=new class{#e=p;setTimeoutProvider(e){this.#e=e}setTimeout(e,t){return this.#e.setTimeout(e,t)}clearTimeout(e){this.#e.clearTimeout(e)}setInterval(e,t){return this.#e.setInterval(e,t)}clearInterval(e){this.#e.clearInterval(e)}};function h(e){setTimeout(e,0)}var g=typeof window>`u`||`Deno`in globalThis;function _(){}function v(e,t){return typeof e==`function`?e(t):e}function y(e){return typeof e==`number`&&e>=0&&e!==1/0}function b(e,t){return Math.max(e+(t||0)-Date.now(),0)}function x(e,t){return typeof e==`function`?e(t):e}function S(e,t){return typeof e==`function`?e(t):e}function C(e,t){let{type:n=`all`,exact:r,fetchStatus:i,predicate:a,queryKey:o,stale:s}=e;if(o){if(r){if(t.queryHash!==ee(o,t.options))return!1}else if(!E(t.queryKey,o))return!1}if(n!==`all`){let e=t.isActive();if(n===`active`&&!e||n===`inactive`&&e)return!1}return!(typeof s==`boolean`&&t.isStale()!==s||i&&i!==t.state.fetchStatus||a&&!a(t))}function w(e,t){let{exact:n,status:r,predicate:i,mutationKey:a}=e;if(a){if(!t.options.mutationKey)return!1;if(n){if(T(t.options.mutationKey)!==T(a))return!1}else if(!E(t.options.mutationKey,a))return!1}return!(r&&t.state.status!==r||i&&!i(t))}function ee(e,t){return(t?.queryKeyHashFn||T)(e)}function T(e){return JSON.stringify(e,(e,t)=>A(t)?Object.keys(t).sort().reduce((e,n)=>(e[n]=t[n],e),{}):t)}function E(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(e&&t&&typeof e==`object`&&typeof t==`object`){if(Array.isArray(e)&&Array.isArray(t)){for(let n=0;n500)return t;let r=k(e)&&k(t);if(!r&&!(A(e)&&A(t)))return t;let i=(r?e:Object.keys(e)).length,a=r?t:Object.keys(t),o=a.length,s=r?Array(o):{},c=0;for(let l=0;l{m.setTimeout(t,e)})}function N(e,t,n){return typeof n.structuralSharing==`function`?n.structuralSharing(e,t):n.structuralSharing===!1?t:te(e,t)}function ne(e,t,n=0){let r=[...e,t];return n&&r.length>n?r.slice(1):r}function re(e,t,n=0){let r=[t,...e];return n&&r.length>n?r.slice(0,-1):r}var ie=Symbol();function ae(e,t){return!e.queryFn&&t?.initialPromise?()=>t.initialPromise:!e.queryFn||e.queryFn===ie?()=>Promise.reject(Error(`Missing queryFn: '${e.queryHash}'`)):e.queryFn}function oe(e,t){return typeof e==`function`?e(...t):!!e}function se(e,t,n){let r=!1,i;return Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(i??=t(),r?i:(r=!0,i.aborted?n():i.addEventListener(`abort`,n,{once:!0}),i))}),e}var P=(()=>{let e=()=>g;return{isServer(){return e()},setIsServer(t){e=t}}})();function ce(){let e,t,n=new Promise((n,r)=>{e=n,t=r});n.status=`pending`,n.catch(()=>{});function r(e){Object.assign(n,e),delete n.resolve,delete n.reject}return n.resolve=t=>{r({status:`fulfilled`,value:t}),e(t)},n.reject=e=>{r({status:`rejected`,reason:e}),t(e)},n}var le=h;function ue(){let e=[],t=0,n=e=>{e()},r=e=>{e()},i=le,a=r=>{t?e.push(r):i(()=>{n(r)})},o=()=>{let t=e;e=[],t.length&&i(()=>{r(()=>{t.forEach(e=>{n(e)})})})};return{batch:e=>{let n;t++;try{n=e()}finally{t--,t||o()}return n},batchCalls:e=>(...t)=>{a(()=>{e(...t)})},schedule:a,setNotifyFunction:e=>{n=e},setBatchNotifyFunction:e=>{r=e},setScheduler:e=>{i=e}}}var de=ue(),fe=new class extends d{#e=!0;#t;#n;constructor(){super(),this.#n=e=>{if(typeof window<`u`&&window.addEventListener){let t=()=>e(!0),n=()=>e(!1);return window.addEventListener(`online`,t,!1),window.addEventListener(`offline`,n,!1),()=>{window.removeEventListener(`online`,t),window.removeEventListener(`offline`,n)}}}}onSubscribe(){this.#t||this.setEventListener(this.#n)}onUnsubscribe(){this.hasListeners()||(this.#t?.(),this.#t=void 0)}setEventListener(e){this.#n=e,this.#t?.(),this.#t=e(this.setOnline.bind(this))}setOnline(e){this.#e!==e&&(this.#e=e,this.listeners.forEach(t=>{t(e)}))}isOnline(){return this.#e}};function pe(e){return Math.min(1e3*2**e,3e4)}function me(e){return(e??`online`)!==`online`||fe.isOnline()}var he=class extends Error{constructor(e){super(`CancelledError`),this.revert=e?.revert,this.silent=e?.silent}};function ge(e){let t=!1,n=0,r,i=ce(),a=()=>i.status!==`pending`,o=t=>{if(!a()){let n=new he(t);p(n),e.onCancel?.(n)}},s=()=>{t=!0},c=()=>{t=!1},l=()=>f.isFocused()&&(e.networkMode===`always`||fe.isOnline())&&e.canRun(),u=()=>me(e.networkMode)&&e.canRun(),d=e=>{a()||(r?.(),i.resolve(e))},p=e=>{a()||(r?.(),i.reject(e))},m=()=>new Promise(t=>{r=e=>{(a()||l())&&t(e)},e.onPause?.()}).then(()=>{r=void 0,a()||e.onContinue?.()}),h=()=>{if(a())return;let r,i=n===0?e.initialPromise:void 0;try{r=i??e.fn()}catch(e){r=Promise.reject(e)}Promise.resolve(r).then(d).catch(r=>{if(a())return;let i=e.retry??(P.isServer()?0:3),o=e.retryDelay??pe,s=typeof o==`function`?o(n,r):o,c=i===!0||typeof i==`number`&&nl()?void 0:m()).then(()=>{t?p(r):h()})})};return{promise:i,status:()=>i.status,cancel:o,continue:()=>(r?.(),i),cancelRetry:s,continueRetry:c,canStart:u,start:()=>(u()?h():m().then(h),i)}}var _e=class{#e;destroy(){this.clearGcTimeout()}scheduleGc(){this.clearGcTimeout(),y(this.gcTime)&&(this.#e=m.setTimeout(()=>{this.optionalRemove()},this.gcTime))}updateGcTime(e){this.gcTime=Math.max(this.gcTime||0,e??(P.isServer()?1/0:3e5))}clearGcTimeout(){this.#e!==void 0&&(m.clearTimeout(this.#e),this.#e=void 0)}};function ve(e){return{onFetch:(t,n)=>{let r=t.options,i=t.fetchOptions?.meta?.fetchMore?.direction,a=t.state.data?.pages||[],o=t.state.data?.pageParams||[],s={pages:[],pageParams:[]},c=0,l=async()=>{let n=!1,l=e=>{se(e,()=>t.signal,()=>n=!0)},u=ae(t.options,t.fetchOptions),d=async(e,r,i)=>{if(n)return Promise.reject(t.signal.reason);if(r==null&&e.pages.length)return Promise.resolve(e);let a=(()=>{let e={client:t.client,queryKey:t.queryKey,pageParam:r,direction:i?`backward`:`forward`,meta:t.options.meta};return l(e),e})(),o=await u(a),{maxPages:s}=t.options,c=i?re:ne;return{pages:c(e.pages,o,s),pageParams:c(e.pageParams,r,s)}};if(i&&a.length){let e=i===`backward`,t=e?be:ye,n={pages:a,pageParams:o};s=await d(n,t(r,n),e)}else{let t=e??a.length;do{let e=c===0?o[0]??r.initialPageParam:ye(r,s);if(c>0&&e==null)break;s=await d(s,e),c++}while(ct.options.persister?.(l,{client:t.client,queryKey:t.queryKey,meta:t.options.meta,signal:t.signal},n):l}}}function ye(e,{pages:t,pageParams:n}){let r=t.length-1;return t.length>0?e.getNextPageParam(t[r],t,n[r],n):void 0}function be(e,{pages:t,pageParams:n}){return t.length>0?e.getPreviousPageParam?.(t[0],t,n[0],n):void 0}function xe(e,t){return t?ye(e,t)!=null:!1}function Se(e,t){return!t||!e.getPreviousPageParam?!1:be(e,t)!=null}var Ce=class extends _e{#e;#t;#n;#r;#i;#a;#o;#s;constructor(e){super(),this.#s=!1,this.#o=e.defaultOptions,this.setOptions(e.options),this.observers=[],this.#i=e.client,this.#r=this.#i.getQueryCache(),this.queryKey=e.queryKey,this.queryHash=e.queryHash,this.#t=Ee(this.options),this.state=e.state??this.#t,this.scheduleGc()}get meta(){return this.options.meta}get queryType(){return this.#e}get promise(){return this.#a?.promise}setOptions(e){if(this.options={...this.#o,...e},e?._type&&(this.#e=e._type),this.updateGcTime(this.options.gcTime),this.state&&this.state.data===void 0){let e=Ee(this.options);e.data!==void 0&&(this.setState(Te(e.data,e.dataUpdatedAt)),this.#t=e)}}optionalRemove(){!this.observers.length&&this.state.fetchStatus===`idle`&&this.#r.remove(this)}setData(e,t){let n=N(this.state.data,e,this.options);return this.#l({data:n,type:`success`,dataUpdatedAt:t?.updatedAt,manual:t?.manual}),n}setState(e){this.#l({type:`setState`,state:e})}cancel(e){let t=this.#a?.promise;return this.#a?.cancel(e),t?t.then(_).catch(_):Promise.resolve()}destroy(){super.destroy(),this.cancel({silent:!0})}get resetState(){return this.#t}reset(){this.destroy(),this.setState(this.resetState)}isActive(){return this.observers.some(e=>S(e.options.enabled,this)!==!1)}isDisabled(){return this.getObserversCount()>0?!this.isActive():this.options.queryFn===ie||!this.isFetched()}isFetched(){return this.state.dataUpdateCount+this.state.errorUpdateCount>0}isStatic(){return this.getObserversCount()>0&&this.observers.some(e=>x(e.options.staleTime,this)===`static`)}isStale(){return this.getObserversCount()>0?this.observers.some(e=>e.getCurrentResult().isStale):this.state.data===void 0||this.state.isInvalidated}isStaleByTime(e=0){return this.state.data===void 0?!0:e===`static`?!1:this.state.isInvalidated?!0:!b(this.state.dataUpdatedAt,e)}onFocus(){this.observers.find(e=>e.shouldFetchOnWindowFocus())?.refetch({cancelRefetch:!1}),this.#a?.continue()}onOnline(){this.observers.find(e=>e.shouldFetchOnReconnect())?.refetch({cancelRefetch:!1}),this.#a?.continue()}addObserver(e){this.observers.includes(e)||(this.observers.push(e),this.clearGcTimeout(),this.#r.notify({type:`observerAdded`,query:this,observer:e}))}removeObserver(e){this.observers.includes(e)&&(this.observers=this.observers.filter(t=>t!==e),this.observers.length||(this.#a&&(this.#s||this.#c()?this.#a.cancel({revert:!0}):this.#a.cancelRetry()),this.scheduleGc()),this.#r.notify({type:`observerRemoved`,query:this,observer:e}))}getObserversCount(){return this.observers.length}#c(){return this.state.fetchStatus===`paused`&&this.state.status===`pending`}invalidate(){this.state.isInvalidated||this.#l({type:`invalidate`})}async fetch(e,t){if(this.state.fetchStatus!==`idle`&&this.#a?.status()!==`rejected`){if(this.state.data!==void 0&&t?.cancelRefetch)this.cancel({silent:!0});else if(this.#a)return this.#a.continueRetry(),this.#a.promise}if(e&&this.setOptions(e),!this.options.queryFn){let e=this.observers.find(e=>e.options.queryFn);e&&this.setOptions(e.options)}let n=new AbortController,r=e=>{Object.defineProperty(e,"signal",{enumerable:!0,get:()=>(this.#s=!0,n.signal)})},i=()=>{let e=ae(this.options,t),n=(()=>{let e={client:this.#i,queryKey:this.queryKey,meta:this.meta};return r(e),e})();return this.#s=!1,this.options.persister?this.options.persister(e,n,this):e(n)},a=(()=>{let e={fetchOptions:t,options:this.options,queryKey:this.queryKey,client:this.#i,state:this.state,fetchFn:i};return r(e),e})();(this.#e===`infinite`?ve(this.options.pages):this.options.behavior)?.onFetch(a,this),this.#n=this.state,(this.state.fetchStatus===`idle`||this.state.fetchMeta!==a.fetchOptions?.meta)&&this.#l({type:`fetch`,meta:a.fetchOptions?.meta}),this.#a=ge({initialPromise:t?.initialPromise,fn:a.fetchFn,onCancel:e=>{e instanceof he&&e.revert&&this.setState({...this.#n,fetchStatus:`idle`}),n.abort()},onFail:(e,t)=>{this.#l({type:`failed`,failureCount:e,error:t})},onPause:()=>{this.#l({type:`pause`})},onContinue:()=>{this.#l({type:`continue`})},retry:a.options.retry,retryDelay:a.options.retryDelay,networkMode:a.options.networkMode,canRun:()=>!0});try{let e=await this.#a.start();if(e===void 0)throw Error(`${this.queryHash} data is undefined`);return this.setData(e),this.#r.config.onSuccess?.(e,this),this.#r.config.onSettled?.(e,this.state.error,this),e}catch(e){if(e instanceof he){if(e.silent)return this.#a.promise;if(e.revert){if(this.state.data===void 0)throw e;return this.state.data}}throw this.#l({type:`error`,error:e}),this.#r.config.onError?.(e,this),this.#r.config.onSettled?.(this.state.data,e,this),e}finally{this.scheduleGc()}}#l(e){let t=t=>{switch(e.type){case`failed`:return{...t,fetchFailureCount:e.failureCount,fetchFailureReason:e.error};case`pause`:return{...t,fetchStatus:`paused`};case`continue`:return{...t,fetchStatus:`fetching`};case`fetch`:return{...t,...we(t.data,this.options),fetchMeta:e.meta??null};case`success`:let n={...t,...Te(e.data,e.dataUpdatedAt),dataUpdateCount:t.dataUpdateCount+1,...!e.manual&&{fetchStatus:`idle`,fetchFailureCount:0,fetchFailureReason:null}};return this.#n=e.manual?n:void 0,n;case`error`:let r=e.error;return{...t,error:r,errorUpdateCount:t.errorUpdateCount+1,errorUpdatedAt:Date.now(),fetchFailureCount:t.fetchFailureCount+1,fetchFailureReason:r,fetchStatus:`idle`,status:`error`,isInvalidated:!0};case`invalidate`:return{...t,isInvalidated:!0};case`setState`:return{...t,...e.state}}};this.state=t(this.state),de.batch(()=>{this.observers.forEach(e=>{e.onQueryUpdate()}),this.#r.notify({query:this,type:`updated`,action:e})})}};function we(e,t){return{fetchFailureCount:0,fetchFailureReason:null,fetchStatus:me(t.networkMode)?`fetching`:`paused`,...e===void 0&&{error:null,status:`pending`}}}function Te(e,t){return{data:e,dataUpdatedAt:t??Date.now(),error:null,isInvalidated:!1,status:`success`}}function Ee(e){let t=typeof e.initialData==`function`?e.initialData():e.initialData,n=t!==void 0,r=n?typeof e.initialDataUpdatedAt==`function`?e.initialDataUpdatedAt():e.initialDataUpdatedAt:0;return{data:t,dataUpdateCount:0,dataUpdatedAt:n?r??Date.now():0,error:null,errorUpdateCount:0,errorUpdatedAt:0,fetchFailureCount:0,fetchFailureReason:null,fetchMeta:null,isInvalidated:!1,status:n?`success`:`pending`,fetchStatus:`idle`}}var De=class extends d{constructor(e,t){super(),this.options=t,this.#e=e,this.#s=null,this.#o=ce(),this.bindMethods(),this.setOptions(t)}#e;#t=void 0;#n=void 0;#r=void 0;#i;#a;#o;#s;#c;#l;#u;#d;#f;#p;#m=new Set;bindMethods(){this.refetch=this.refetch.bind(this)}onSubscribe(){this.listeners.size===1&&(this.#t.addObserver(this),ke(this.#t,this.options)?this.#h():this.updateResult(),this.#y())}onUnsubscribe(){this.hasListeners()||this.destroy()}shouldFetchOnReconnect(){return Ae(this.#t,this.options,this.options.refetchOnReconnect)}shouldFetchOnWindowFocus(){return Ae(this.#t,this.options,this.options.refetchOnWindowFocus)}destroy(){this.listeners=new Set,this.#b(),this.#x(),this.#t.removeObserver(this)}setOptions(e){let t=this.options,n=this.#t;if(this.options=this.#e.defaultQueryOptions(e),this.options.enabled!==void 0&&typeof this.options.enabled!=`boolean`&&typeof this.options.enabled!=`function`&&typeof S(this.options.enabled,this.#t)!=`boolean`)throw Error(`Expected enabled to be a boolean or a callback that returns a boolean`);this.#S(),this.#t.setOptions(this.options),t._defaulted&&!O(this.options,t)&&this.#e.getQueryCache().notify({type:`observerOptionsUpdated`,query:this.#t,observer:this});let r=this.hasListeners();r&&je(this.#t,n,this.options,t)&&this.#h(),this.updateResult(),r&&(this.#t!==n||S(this.options.enabled,this.#t)!==S(t.enabled,this.#t)||x(this.options.staleTime,this.#t)!==x(t.staleTime,this.#t))&&this.#g();let i=this.#_();r&&(this.#t!==n||S(this.options.enabled,this.#t)!==S(t.enabled,this.#t)||i!==this.#p)&&this.#v(i)}getOptimisticResult(e){let t=this.#e.getQueryCache().build(this.#e,e),n=this.createResult(t,e);return Ne(this,n)&&(this.#r=n,this.#a=this.options,this.#i=this.#t.state),n}getCurrentResult(){return this.#r}trackResult(e,t){return new Proxy(e,{get:(e,n)=>(this.trackProp(n),t?.(n),n===`promise`&&(this.trackProp(`data`),!this.options.experimental_prefetchInRender&&this.#o.status===`pending`&&this.#o.reject(Error(`experimental_prefetchInRender feature flag is not enabled`))),Reflect.get(e,n))})}trackProp(e){this.#m.add(e)}getCurrentQuery(){return this.#t}refetch({...e}={}){return this.fetch({...e})}fetchOptimistic(e){let t=this.#e.defaultQueryOptions(e),n=this.#e.getQueryCache().build(this.#e,t);return n.fetch().then(()=>this.createResult(n,t))}fetch(e){return this.#h({...e,cancelRefetch:e.cancelRefetch??!0}).then(()=>(this.updateResult(),this.#r))}#h(e){this.#S();let t=this.#t.fetch(this.options,e);return e?.throwOnError||(t=t.catch(_)),t}#g(){this.#b();let e=x(this.options.staleTime,this.#t);if(P.isServer()||this.#r.isStale||!y(e))return;let t=b(this.#r.dataUpdatedAt,e)+1;this.#d=m.setTimeout(()=>{this.#r.isStale||this.updateResult()},t)}#_(){return(typeof this.options.refetchInterval==`function`?this.options.refetchInterval(this.#t):this.options.refetchInterval)??!1}#v(e){this.#x(),this.#p=e,!(P.isServer()||S(this.options.enabled,this.#t)===!1||!y(this.#p)||this.#p===0)&&(this.#f=m.setInterval(()=>{(this.options.refetchIntervalInBackground||f.isFocused())&&this.#h()},this.#p))}#y(){this.#g(),this.#v(this.#_())}#b(){this.#d!==void 0&&(m.clearTimeout(this.#d),this.#d=void 0)}#x(){this.#f!==void 0&&(m.clearInterval(this.#f),this.#f=void 0)}createResult(e,t){let n=this.#t,r=this.options,i=this.#r,a=this.#i,o=this.#a,s=e===n?this.#n:e.state,{state:c}=e,l={...c},u=!1,d;if(t._optimisticResults){let i=this.hasListeners(),a=!i&&ke(e,t),o=i&&je(e,n,t,r);(a||o)&&(l={...l,...we(c.data,e.options)}),t._optimisticResults===`isRestoring`&&(l.fetchStatus=`idle`)}let{error:f,errorUpdatedAt:p,status:m}=l;d=l.data;let h=!1;if(t.placeholderData!==void 0&&d===void 0&&m===`pending`){let e;i?.isPlaceholderData&&t.placeholderData===o?.placeholderData?(e=i.data,h=!0):e=typeof t.placeholderData==`function`?t.placeholderData(this.#u?.state.data,this.#u):t.placeholderData,e!==void 0&&(m=`success`,d=N(i?.data,e,t),u=!0)}if(t.select&&d!==void 0&&!h)if(i&&d===a?.data&&t.select===this.#c)d=this.#l;else try{this.#c=t.select,d=t.select(d),d=N(i?.data,d,t),this.#l=d,this.#s=null}catch(e){this.#s=e}this.#s&&(f=this.#s,d=this.#l,p=Date.now(),m=`error`);let g=l.fetchStatus===`fetching`,_=m===`pending`,v=m===`error`,y=_&&g,b=d!==void 0,x={status:m,fetchStatus:l.fetchStatus,isPending:_,isSuccess:m===`success`,isError:v,isInitialLoading:y,isLoading:y,data:d,dataUpdatedAt:l.dataUpdatedAt,error:f,errorUpdatedAt:p,failureCount:l.fetchFailureCount,failureReason:l.fetchFailureReason,errorUpdateCount:l.errorUpdateCount,isFetched:e.isFetched(),isFetchedAfterMount:l.dataUpdateCount>s.dataUpdateCount||l.errorUpdateCount>s.errorUpdateCount,isFetching:g,isRefetching:g&&!_,isLoadingError:v&&!b,isPaused:l.fetchStatus===`paused`,isPlaceholderData:u,isRefetchError:v&&b,isStale:Me(e,t),refetch:this.refetch,promise:this.#o,isEnabled:S(t.enabled,e)!==!1};if(this.options.experimental_prefetchInRender){let t=x.data!==void 0,r=x.status===`error`&&!t,i=e=>{r?e.reject(x.error):t&&e.resolve(x.data)},a=()=>{let e=this.#o=x.promise=ce();i(e)},o=this.#o;switch(o.status){case`pending`:e.queryHash===n.queryHash&&i(o);break;case`fulfilled`:(r||x.data!==o.value)&&a();break;case`rejected`:(!r||x.error!==o.reason)&&a()}}return x}updateResult(){let e=this.#r,t=this.createResult(this.#t,this.options);this.#i=this.#t.state,this.#a=this.options,this.#i.data!==void 0&&(this.#u=this.#t),!O(t,e)&&(this.#r=t,this.#C({listeners:(()=>{if(!e)return!0;let{notifyOnChangeProps:t}=this.options,n=typeof t==`function`?t():t;if(n===`all`||!n&&!this.#m.size)return!0;let r=new Set(n??this.#m);return this.options.throwOnError&&r.add(`error`),Object.keys(this.#r).some(t=>{let n=t;return this.#r[n]!==e[n]&&r.has(n)})})()}))}#S(){let e=this.#e.getQueryCache().build(this.#e,this.options);if(e===this.#t)return;let t=this.#t;this.#t=e,this.#n=e.state,this.hasListeners()&&(t?.removeObserver(this),e.addObserver(this))}onQueryUpdate(){this.updateResult(),this.hasListeners()&&this.#y()}#C(e){de.batch(()=>{e.listeners&&this.listeners.forEach(e=>{e(this.#r)}),this.#e.getQueryCache().notify({query:this.#t,type:`observerResultsUpdated`})})}};function Oe(e,t){return S(t.enabled,e)!==!1&&e.state.data===void 0&&(e.state.status!==`error`||S(t.retryOnMount,e)!==!1)}function ke(e,t){return Oe(e,t)||e.state.data!==void 0&&Ae(e,t,t.refetchOnMount)}function Ae(e,t,n){if(S(t.enabled,e)!==!1&&x(t.staleTime,e)!==`static`){let r=typeof n==`function`?n(e):n;return r===`always`||r!==!1&&Me(e,t)}return!1}function je(e,t,n,r){return(e!==t||S(r.enabled,e)===!1)&&(!n.suspense||e.state.status!==`error`)&&Me(e,n)}function Me(e,t){return S(t.enabled,e)!==!1&&e.isStaleByTime(x(t.staleTime,e))}function Ne(e,t){return!O(e.getCurrentResult(),t)}var Pe=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),Fe=o(((e,t)=>{t.exports=Pe()})),F=c(u(),1),I=Fe(),Ie=F.createContext(void 0),Le=e=>{let t=F.useContext(Ie);if(e)return e;if(!t)throw Error(`No QueryClient set, use QueryClientProvider to set one`);return t},Re=({client:e,children:t})=>(F.useEffect(()=>(e.mount(),()=>{e.unmount()}),[e]),(0,I.jsx)(Ie.Provider,{value:e,children:t})),ze=F.createContext(!1),Be=()=>F.useContext(ze);ze.Provider;function Ve(){let e=!1;return{clearReset:()=>{e=!1},reset:()=>{e=!0},isReset:()=>e}}var He=F.createContext(Ve()),Ue=()=>F.useContext(He),We=(e,t,n)=>{let r=n?.state.error&&typeof e.throwOnError==`function`?oe(e.throwOnError,[n.state.error,n]):e.throwOnError;(e.suspense||e.experimental_prefetchInRender||r)&&(t.isReset()||(e.retryOnMount=!1))},Ge=e=>{F.useEffect(()=>{e.clearReset()},[e])},Ke=({result:e,errorResetBoundary:t,throwOnError:n,query:r,suspense:i})=>e.isError&&!t.isReset()&&!e.isFetching&&r&&(i&&e.data===void 0||oe(n,[e.error,r])),qe=e=>{if(e.suspense){let t=1e3,n=e=>e===`static`?e:Math.max(e??t,t),r=e.staleTime;e.staleTime=typeof r==`function`?(...e)=>n(r(...e)):n(r),typeof e.gcTime==`number`&&(e.gcTime=Math.max(e.gcTime,t))}},Je=(e,t)=>e.isLoading&&e.isFetching&&!t,Ye=(e,t)=>e?.suspense&&t.isPending,Xe=(e,t,n)=>t.fetchOptimistic(e).catch(()=>{n.clearReset()});function Ze(e,t,n){let r=Be(),i=Ue(),a=Le(n),o=a.defaultQueryOptions(e);a.getDefaultOptions().queries?._experimental_beforeQuery?.(o);let s=a.getQueryCache().get(o.queryHash),c=e.subscribed!==!1;o._optimisticResults=r?`isRestoring`:c?`optimistic`:void 0,qe(o),We(o,i,s),Ge(i);let l=!a.getQueryCache().get(o.queryHash),[u]=F.useState(()=>new t(a,o)),d=u.getOptimisticResult(o),f=!r&&c;if(F.useSyncExternalStore(F.useCallback(e=>{let t=f?u.subscribe(de.batchCalls(e)):_;return u.updateResult(),t},[u,f]),()=>u.getCurrentResult(),()=>u.getCurrentResult()),F.useEffect(()=>{u.setOptions(o)},[o,u]),Ye(o,d))throw Xe(o,u,i);if(Ke({result:d,errorResetBoundary:i,throwOnError:o.throwOnError,query:s,suspense:o.suspense}))throw d.error;return a.getDefaultOptions().queries?._experimental_afterQuery?.(o,d),o.experimental_prefetchInRender&&!P.isServer()&&Je(d,r)&&(l?Xe(o,u,i):s?.promise)?.catch(_).finally(()=>{u.updateResult()}),o.notifyOnChangeProps?d:u.trackResult(d)}function Qe(e,t){return Ze(e,De,t)}var L=class extends Error{code;status;extra;constructor(e,t,n,r={}){super(n),this.name=`ApiRequestError`,this.status=e,this.code=t,this.extra=r}},$e=-999940,et=-738920;function tt(e,t){let n=(e-$e)/1447840;return{x:(t-et)/1447840*256,y:(1-n)*256}}function nt(e,t){let n=e/256;return{x:$e+(1-t/256)*1447840,y:et+n*1447840}}function rt(e,t){return{x:Math.round((t-158e3)/459),y:Math.round((e+123888)/459)}}function R(e,t){return{x:t*459-123888,y:e*459+158e3}}function it(e,t,n,r){return{x:(n.a*t+n.b)/r*256,y:(n.c*e+n.d)/r*256}}function at(e,t,n,r){let i=e/256*r;return{x:(t/256*r-n.d)/n.c,y:(i-n.b)/n.a}}function ot(e,t,n){let[[r,i],[a,o]]=n;return e>=Math.min(r,a)&&e<=Math.max(r,a)&&t>=Math.min(i,o)&&t<=Math.max(i,o)}function z(e=50,t=200){let n=e+Math.random()*(t-e);return new Promise(e=>setTimeout(e,n))}function st(e,t){return e+(Math.random()-.5)*2*t}var ct=`palhelm.mock.session`;function lt(){try{let e=sessionStorage.getItem(ct);return e?JSON.parse(e):null}catch{return null}}function ut(e){e?sessionStorage.setItem(ct,JSON.stringify(e)):sessionStorage.removeItem(ct)}function B(){let e=lt();if(!e)throw new L(401,`unauthorized`,`Sign in to continue.`);return e}function V(){let e=B();if(e.role!==`admin`)throw new L(403,`forbidden`,`This action requires the admin role.`);return e}var dt=Date.now()-216e5-72e4,H=[{uid:`84C20A31-1234-4B7E-9A11-000000000001`,steamId:`76561198012345678`,name:`Kestrel`,accountName:`kestrel`,online:!0,level:31,guildId:`g-nightloom`,guildName:`Nightloom`,ping:23,location:R(-361,292),firstSeenAt:`2026-07-04T09:12:00Z`,lastSeenAt:new Date().toISOString(),playtimeSec:77760,captureTotal:146,uniquePalsCaptured:8,paldeckUnlocked:9,banned:!1,whitelisted:!0},{uid:`1F60E842-1234-4B7E-9A11-000000000002`,steamId:`76561198087654321`,name:`VossR`,accountName:`vossr`,online:!0,level:29,guildId:`g-nightloom`,guildName:`Nightloom`,ping:41,location:R(118,-412),firstSeenAt:`2026-07-04T10:02:00Z`,lastSeenAt:new Date().toISOString(),playtimeSec:65100,captureTotal:113,uniquePalsCaptured:7,paldeckUnlocked:8,banned:!1,whitelisted:!0},{uid:`5A9C2E10-1234-4B7E-9A11-000000000003`,steamId:`76561198055512345`,name:`mika_o`,accountName:`mika_o`,online:!1,level:27,guildId:`g-nightloom`,guildName:`Nightloom`,ping:null,location:null,firstSeenAt:`2026-07-05T08:00:00Z`,lastSeenAt:`2026-07-09T22:18:00Z`,playtimeSec:57060,captureTotal:82,uniquePalsCaptured:5,paldeckUnlocked:6,banned:!1,whitelisted:!0},{uid:`3B7D1F44-1234-4B7E-9A11-000000000004`,steamId:`76561198033398765`,name:`HaruQ`,accountName:`haruq`,online:!1,level:14,guildId:`g-driftbone`,guildName:`Driftbone`,ping:null,location:null,firstSeenAt:`2026-07-06T14:20:00Z`,lastSeenAt:`2026-07-06T19:51:00Z`,playtimeSec:22320,banned:!1,whitelisted:!1},{uid:`9E4A6C77-1234-4B7E-9A11-000000000005`,steamId:`76561198099911223`,name:`tessellate`,accountName:`tessellate`,online:!1,level:8,guildId:null,guildName:null,ping:null,location:null,firstSeenAt:`2026-07-05T02:00:00Z`,lastSeenAt:`2026-07-05T03:12:00Z`,playtimeSec:7440,banned:!0,whitelisted:!1},{uid:`7C1B8D22-1234-4B7E-9A11-000000000006`,steamId:`76561198044456789`,name:`Ferro`,accountName:`ferro`,online:!1,level:19,guildId:`g-cinderwake`,guildName:`Cinderwake`,ping:null,location:null,firstSeenAt:`2026-07-06T11:00:00Z`,lastSeenAt:`2026-07-08T20:30:00Z`,playtimeSec:32580,banned:!1,whitelisted:!1},{uid:`2D8F3A55-1234-4B7E-9A11-000000000007`,steamId:`76561198077765432`,name:`Wren`,accountName:`wren`,online:!1,level:22,guildId:`g-palisade`,guildName:`Palisade`,ping:null,location:null,firstSeenAt:`2026-07-05T16:40:00Z`,lastSeenAt:`2026-07-09T18:05:00Z`,playtimeSec:41220,banned:!1,whitelisted:!1}],ft=[`Nightloom`,`Driftbone`,`Cinderwake`,`Palisade`,`Thornmere`,`Greywatch`,`Amberfen`],pt={"g-nightloom":[{x:-660,y:490,name:`Nightloom HQ`},{x:-80,y:-430,name:null}],"g-driftbone":[{x:430,y:370,name:null},{x:610,y:-160,name:`Coal Ridge`}],"g-cinderwake":[{x:-300,y:-640,name:null}],"g-palisade":[{x:250,y:720,name:null}]},U=ft.map((e,t)=>{let n=`g-${e.toLowerCase()}`,r=H.filter(e=>e.guildId===n).map(e=>({uid:e.uid,name:e.name})),i=pt[n]??[];return{id:n,name:e,adminUid:r[0]?.uid??`synthetic-${t}`,memberCount:Math.max(r.length,t===0?3:t===1?2:1),members:r,bases:i.map((e,r)=>({id:`${n}-base-${r}`,name:e.name,location:R(e.x,e.y),level:3+(t+r)%5}))}}),mt=[{id:`g-driftless-org`,name:`Driftless (solo org)`,adminUid:`synthetic-solo`,memberCount:0,members:[],bases:[]}],ht=[...U,...mt],gt=e=>e.bases.length>0&&e.members.length>0,W=[{steamId:`76561198012345678`,name:`Kestrel`},{steamId:`76561198087654321`,name:`VossR`},{steamId:`76561198055512345`,name:`mika_o`}],G=[{id:`b1`,file:`world-2026-07-09-2342.tar.gz`,createdAt:`2026-07-09T23:42:07Z`,sizeBytes:14680064,trigger:`scheduled`,worldDay:3},{id:`b2`,file:`world-2026-07-09-1942.tar.gz`,createdAt:`2026-07-09T19:42:11Z`,sizeBytes:146e5,trigger:`scheduled`,worldDay:3},{id:`b3`,file:`world-2026-07-09-1811.tar.gz`,createdAt:`2026-07-09T18:11:03Z`,sizeBytes:146e5,trigger:`pre-restore`,worldDay:3},{id:`b4`,file:`world-2026-07-09-1542.tar.gz`,createdAt:`2026-07-09T15:42:09Z`,sizeBytes:145e5,trigger:`scheduled`,worldDay:3},{id:`b5`,file:`world-2026-07-09-1142.tar.gz`,createdAt:`2026-07-09T11:42:02Z`,sizeBytes:144e5,trigger:`scheduled`,worldDay:3},{id:`b6`,file:`world-2026-07-08-2342.tar.gz`,createdAt:`2026-07-08T23:42:05Z`,sizeBytes:142e5,trigger:`scheduled`,worldDay:2},{id:`b7`,file:`world-2026-07-08-1633.tar.gz`,createdAt:`2026-07-08T16:33:41Z`,sizeBytes:139e5,trigger:`manual`,worldDay:2},{id:`b8`,file:`world-2026-07-07-2216.tar.gz`,createdAt:`2026-07-07T22:16:18Z`,sizeBytes:128e5,trigger:`manual`,worldDay:1}],_t={enabled:!0,everyMinutes:240,keepDays:30,nextRunAt:new Date(Date.now()+468e4).toISOString()},vt=[{key:`SERVER_NAME`,value:`My Palworld Server`,effectiveValue:`My Palworld Server`,type:`string`,group:`general`,default:`Palworld Server`,pending:!1,editable:!0,readOnly:!1},{key:`SERVER_DESCRIPTION`,value:`1.0 server`,effectiveValue:`1.0 server`,type:`string`,group:`general`,default:``,pending:!1,editable:!0,readOnly:!1},{key:`SERVER_PASSWORD`,value:`•••`,effectiveValue:`•••`,type:`string`,group:`general`,default:``,pending:!1,editable:!0,readOnly:!1},{key:`ADMIN_PASSWORD`,value:`•••`,effectiveValue:`•••`,type:`string`,group:`general`,default:``,pending:!1,editable:!0,readOnly:!1},{key:`PLAYERS`,value:16,effectiveValue:16,type:`integer`,group:`general`,default:32,pending:!1,editable:!0,readOnly:!1},{key:`EXP_RATE`,value:1.5,effectiveValue:1,type:`number`,group:`gameplay`,default:1,pending:!0,editable:!0,readOnly:!1},{key:`PAL_CAPTURE_RATE`,value:1,effectiveValue:1,type:`number`,group:`gameplay`,default:1,pending:!1,editable:!0,readOnly:!1},{key:`DAY_TIME_SPEED_RATE`,value:1,effectiveValue:1,type:`number`,group:`gameplay`,default:1,pending:!1,editable:!0,readOnly:!1},{key:`NIGHT_TIME_SPEED_RATE`,value:1,effectiveValue:1,type:`number`,group:`gameplay`,default:1,pending:!1,editable:!0,readOnly:!1},{key:`DIFFICULTY`,value:`None`,effectiveValue:`None`,type:`string`,group:`gameplay`,default:`None`,pending:!1,editable:!0,readOnly:!1},{key:`DEATH_PENALTY`,value:`All`,effectiveValue:`All`,type:`string`,group:`gameplay`,default:`All`,pending:!1,editable:!0,readOnly:!1},{key:`PUBLIC_PORT`,value:8211,effectiveValue:8211,type:`integer`,group:`network`,default:8211,pending:!1,editable:!0,readOnly:!1},{key:`RCON_ENABLED`,value:!0,effectiveValue:!0,type:`boolean`,group:`panel-managed`,default:!0,pending:!1,editable:!1,readOnly:!0},{key:`REST_API_ENABLED`,value:!0,effectiveValue:!0,type:`boolean`,group:`panel-managed`,default:!0,pending:!1,editable:!1,readOnly:!0}],K=`mock:1`,yt=[{at:`2026-07-09T22:30:11Z`,user:`admin`,command:`Info`,output:`Welcome to Pal Server[v1.0.0.100427] My Palworld Server`,isError:!1},{at:`2026-07-09T22:31:40Z`,user:`admin`,command:`ShowPlayers`,output:`name,playeruid,steamid
+Kestrel,84C20A31,76561198012345678
+VossR,1F60E842,76561198087654321`,isError:!1},{at:`2026-07-09T22:33:02Z`,user:`admin`,command:`Broadcast Server_restarting_at_midnight`,output:`Broadcasted: Server_restarting_at_midnight`,isError:!1},{at:`2026-07-09T22:33:20Z`,user:`admin`,command:`TeleportToPlayer 76561198012345678`,output:`Error: this command is only available in-game.`,isError:!0},{at:`2026-07-09T22:36:48Z`,user:`admin`,command:`Save`,output:`Complete Save`,isError:!1}],q=[{id:`s1`,name:`Who's on`,command:`ShowPlayers`},{id:`s2`,name:`Save world`,command:`Save`},{id:`s3`,name:`Restart in 5 min`,command:`Shutdown 300 Restarting_in_5_minutes`}],J=[{at:`2026-07-09T23:42:00Z`,kind:`backup`,message:"Scheduled backup completed — `14.6 MB` in 1.2 s"},{at:`2026-07-09T22:31:00Z`,kind:`system`,message:"Server started (world `A1B2C3D4…5678`)"},{at:`2026-07-09T22:30:00Z`,kind:`panel`,message:`Palhelm connected to RCON and REST API`},{at:`2026-07-09T18:04:00Z`,kind:`leave`,message:`**Kestrel** left after 2h 41m`},{at:`2026-07-09T15:23:00Z`,kind:`join`,message:`**Kestrel** joined ~steam_76561198012345678~`}],bt=0;async function xt(e){if(await z(150,350),e===`admin`)return ut({role:`admin`,username:`admin`}),{role:`admin`};if(e===`viewer`)return ut({role:`viewer`,username:`viewer`}),{role:`viewer`};throw new L(401,`invalid_credentials`,`Incorrect password.`)}async function St(){await z(),ut(null)}async function Ct(){return await z(30,120),B()}async function wt(){return B(),await z(),{name:`My Palworld Server`,description:`1.0 server`,version:`v1.0.0.100427`,worldGuid:`A1B2C3D4E5F6478090ABCDEF12345678`,state:`running`,uptimeSec:Math.floor((Date.now()-dt)/1e3),panelVersion:`0.9.1`,sessionDays:7,saveSyncMinutes:10}}async function Tt(){return B(),await z(),{rest:`ok`,rcon:`ok`,save:{state:`ok`,lastSyncAt:new Date(Date.now()-24e4).toISOString()}}}async function Et(e){V(),await z(150,300)}async function Dt(){V(),await z(200,500)}async function Ot(e,t,n){V(),await z(200,400)}async function kt(){V(),await z()}async function At(){B(),await z(40,150),bt+=1;let e=Math.round(st(59,1.5));return{fps:Math.max(1,e),fpsAvg:59.3,frameTimeMs:Math.round(1e3/Math.max(1,e)*10)/10,players:H.filter(e=>e.online).length,maxPlayers:16,day:3,uptimeSec:Math.floor((Date.now()-dt)/1e3),baseCamps:U.reduce((e,t)=>e+t.bases.length,0)}}function jt(e,t,n){let r=Math.floor(Date.now()/1e3),i=[],a=[],o=[],s=[];for(let c=0;c({...e,banned:e.banned}))}function Pt(e){return e.map((e,t)=>t<5?{...e,inParty:!0,partySlot:t,boxPage:null,boxSlot:null,placement:`party`,baseId:null}:{...e,inParty:!1,partySlot:null,boxPage:Math.floor((t-5)/30),boxSlot:(t-5)%30,placement:`box`,baseId:null})}var Y={Kestrel:[{instanceId:`pal-k1`,characterId:`Anubis`,displayName:`Anubis`,level:34,isAlpha:!0,isLucky:!1,hp:1240.5,gender:`male`,rank:5,talents:{hp:87,melee:73,shot:92,defense:81},passiveSkillIds:[`CraftSpeed_up2`,`ElementBoost_Earth_2_PAL`],equippedSkillIds:[`RockLance`,`StoneShotgun`,`GroundWave`]},{instanceId:`pal-k2`,characterId:`Grizzbolt`,displayName:`Grizzbolt`,level:31,isAlpha:!1,isLucky:!1,rank:3},{instanceId:`pal-k3`,characterId:`Faleris`,displayName:`Faleris`,level:30,isAlpha:!1,isLucky:!1,rank:1},{instanceId:`pal-k4`,characterId:`Digtoise`,displayName:`Digtoise`,level:27,isAlpha:!1,isLucky:!1},{instanceId:`pal-k5`,characterId:`Penking`,displayName:`Penking`,level:25,isAlpha:!1,isLucky:!0,rank:2},{instanceId:`pal-k6`,characterId:`Rayhound`,displayName:`Rayhound`,level:24,isAlpha:!1,isLucky:!1},{instanceId:`pal-k7`,characterId:`Tombat`,displayName:`Tombat`,level:22,isAlpha:!1,isLucky:!1},{instanceId:`pal-k8`,characterId:`Foxparks`,displayName:`Foxparks`,level:19,isAlpha:!1,isLucky:!1},{instanceId:`pal-k9`,characterId:`Lamball`,displayName:`Lamball`,level:12,isAlpha:!1,isLucky:!1},{instanceId:`pal-k10`,characterId:`Cattiva`,displayName:`Cattiva`,level:11,isAlpha:!1,isLucky:!1},{instanceId:`pal-k11`,characterId:`Chikipi`,displayName:`Chikipi`,level:8,isAlpha:!1,isLucky:!1},{instanceId:`pal-k12`,characterId:`Pengullet`,displayName:`Pengullet`,level:7,isAlpha:!1,isLucky:!1}],VossR:[{instanceId:`pal-v1`,characterId:`Frostallion`,displayName:`Frostallion`,level:32,isAlpha:!1,isLucky:!1,rank:4},{instanceId:`pal-v2`,characterId:`Ragnahawk`,displayName:`Ragnahawk`,level:28,isAlpha:!1,isLucky:!1},{instanceId:`pal-v3`,characterId:`Surfent`,displayName:`Surfent`,level:26,isAlpha:!1,isLucky:!1},{instanceId:`pal-v4`,characterId:`Direhowl`,displayName:`Direhowl`,level:20,isAlpha:!1,isLucky:!1}],mika_o:[{instanceId:`pal-m1`,characterId:`Mossanda`,displayName:`Mossanda`,level:27,isAlpha:!1,isLucky:!1},{instanceId:`pal-m2`,characterId:`Bristla`,displayName:`Bristla`,level:21,isAlpha:!1,isLucky:!1},{instanceId:`pal-m3`,characterId:`Petallia`,displayName:`Petallia`,level:18,isAlpha:!1,isLucky:!1}],HaruQ:[{instanceId:`pal-h1`,characterId:`Eikthyrdeer`,displayName:`Eikthyrdeer`,level:13,isAlpha:!1,isLucky:!1},{instanceId:`pal-h2`,characterId:`Fuack`,displayName:`Fuack`,level:9,isAlpha:!1,isLucky:!1}],tessellate:[{instanceId:`pal-t1`,characterId:`Depresso`,displayName:`Depresso`,level:6,isAlpha:!1,isLucky:!1}]};async function Ft(e={}){B(),await z();let t=e.q?.trim().toLowerCase()??``,n=H.flatMap(e=>Pt(Y[e.name]??[]).map(t=>({...t,isBoss:t.characterId.toLowerCase().startsWith(`boss_`),placement:t.placement??`unknown`,ownerUid:e.uid,ownerName:e.name,ownerSource:`personal_container`,ownerResolved:!0}))).sort((e,t)=>e.instanceId.localeCompare(t.instanceId)).filter(n=>!(e.cursor&&n.instanceId<=e.cursor||t&&!`${n.displayName} ${n.characterId} ${n.ownerName}`.toLowerCase().includes(t)||e.ownerSource&&n.ownerSource!==e.ownerSource||e.placement&&n.placement!==e.placement||e.minLevel!==void 0&&n.levele.maxLevel||e.specimen===`standard`&&(n.isAlpha||n.isLucky||n.isBoss)||e.specimen===`alpha`&&(!n.isAlpha||n.isBoss)||e.specimen===`lucky`&&!n.isLucky||e.specimen===`boss`&&!n.isBoss)),r=Math.max(1,Math.min(e.limit??48,100)),i=n.slice(0,r);return{data:i,nextCursor:n.length>r?i.at(-1)?.instanceId??null:null}}async function It(e){B(),await z();let t=H.find(t=>t.uid===e);if(!t)throw new L(404,`not_found`,`Player not found.`);let n=t.online?{joinedAt:new Date(Date.now()-624e4).toISOString(),leftAt:null,durationSec:6240}:null,r=n?[n]:[{joinedAt:t.firstSeenAt,leftAt:t.lastSeenAt,durationSec:Math.min(t.playtimeSec,9700)}];return{...t,pals:Pt(Y[t.name]??[]),sessions:r,activity:{coverage:`panel_observed_sessions`,trackingSince:t.firstSeenAt,currentSession:n,windows:{last24Hours:{durationSec:n?.durationSec??0,sessionCount:+!!n},last7Days:{durationSec:Math.min(t.playtimeSec,43200),sessionCount:Math.min(4,Math.max(1,Math.ceil(t.playtimeSec/7200)))},last30Days:{durationSec:t.playtimeSec,sessionCount:Math.min(12,Math.max(1,Math.ceil(t.playtimeSec/7200)))}},recentSessions:r,recentSessionsTruncated:!1}}}async function Lt(e=`7d`){B(),await z();let t=new Date,n=e===`24h`?864e5:e===`7d`?6048e5:2592e6,r=e===`24h`?36e5:e===`7d`?216e5:864e5,i=new Date(t.getTime()-n),a=Array.from({length:n/r},(e,t)=>{let n=Math.max(0,Math.sin(t/4*Math.PI)),a=Number((n*2.2).toFixed(2));return{at:new Date(i.getTime()+t*r).toISOString(),peakPlayers:Math.ceil(a),averagePlayers:a}}),o=[...H].map((e,t)=>({uid:e.uid,name:e.name,guildId:e.guildId??``,guildName:e.guildName??``,durationSec:Math.min(e.playtimeSec,Math.floor(n/1e3/(t+3))),sessionCount:Math.max(1,6-t),currentSession:e.online,firstObserved:new Date(e.firstSeenAt)>=i})).sort((e,t)=>t.durationSec-e.durationSec),s=ft.slice(0,3).map(e=>{let t=o.filter(t=>t.guildName===e);return{guildId:`g-${e.toLowerCase()}`,guildName:e,durationSec:t.reduce((e,t)=>e+t.durationSec,0),sessionCount:t.reduce((e,t)=>e+t.sessionCount,0),activePlayers:t.length}}).filter(e=>e.activePlayers>0),c=Math.max(0,...a.map(e=>e.peakPlayers));return{coverage:`panel_observed_sessions`,trackingSince:H.map(e=>e.firstSeenAt).sort()[0]??null,window:e,since:i.toISOString(),through:t.toISOString(),bucketSec:r/1e3,analysisTruncated:!1,activePlayers:o.length,newPlayers:o.filter(e=>e.firstObserved).length,returningPlayers:o.filter(e=>!e.firstObserved).length,peakConcurrency:c,peakAt:a.find(e=>e.peakPlayers===c)?.at??null,concurrency:a,players:o,guilds:s,guildAttribution:`current_player_guild`,unattributedPlayers:o.filter(e=>!e.guildId).length,unattributedDurationSec:o.filter(e=>!e.guildId).reduce((e,t)=>e+t.durationSec,0)}}async function Rt(e,t){V(),await z(150,300);let n=H.find(t=>t.uid===e);n&&(n.online=!1,n.ping=null,n.location=null,n.lastSeenAt=new Date().toISOString(),J.unshift({at:new Date().toISOString(),kind:`leave`,message:`**${n.name}** was kicked by admin`}))}async function zt(e,t){V(),await z(150,300);let n=H.find(t=>t.uid===e);n&&(n.banned=!0,n.online&&(n.online=!1,n.ping=null,n.location=null,n.lastSeenAt=new Date().toISOString()),J.unshift({at:new Date().toISOString(),kind:`panel`,message:`**${n.name}** was banned by admin`}))}async function Bt(e){V(),await z(150,300);let t=H.find(t=>t.uid===e);t&&(t.banned=!1)}async function Vt(){return B(),await z(),W}async function Ht(e){V(),await z(150,300),W=e;for(let e of H)e.whitelisted=W.some(t=>t.steamId===e.steamId);return W}async function Ut(){return B(),await z(),ht.filter(gt)}async function Wt(e){B(),await z();let t=ht.find(t=>t.id===e);if(!t)throw new L(404,`not_found`,`Guild not found.`);let n=H.filter(e=>e.guildId===t.id),r=new Date,i=new Date(r.getTime()-2592e6),a=n.flatMap(e=>Pt(Y[e.name]??[]).map(t=>({instanceId:t.instanceId,characterId:t.characterId,displayName:t.displayName,level:t.level,rank:t.rank??null,isAlpha:t.isAlpha,isLucky:t.isLucky,isBoss:t.characterId.toLowerCase().startsWith(`boss_`),placement:t.placement??`unknown`,baseId:null,ownerUid:e.uid,ownerName:e.name,ownerSource:`personal_container`,ownerResolved:!0,association:`current_member_owner`})));return{id:t.id,name:t.name,adminUid:t.adminUid,memberCount:t.memberCount,members:t.members.map(e=>{let t=H.find(t=>t.uid===e.uid);return{uid:e.uid,name:e.name,level:t?.level??0,online:t?.online??!1,lastSeenAt:t?.lastSeenAt??null,playtimeSec:t?.playtimeSec??0,captureTotal:t?.captureTotal??null,uniquePalsCaptured:t?.uniquePalsCaptured??null,paldeckUnlocked:t?.paldeckUnlocked??null,observedDurationSec:t?Math.min(t.playtimeSec,108e3):0,observedSessionCount:t?Math.max(1,Math.ceil(t.playtimeSec/7200)):0,currentSession:t?.online??!1}}),bases:t.bases.map(e=>({...e,palCount:0})),palCount:a.length,palsTruncated:!1,pals:a,activity:{coverage:`panel_observed_sessions`,attribution:`current_guild_membership`,window:`30d`,since:i.toISOString(),through:r.toISOString(),trackingSince:n.map(e=>e.firstSeenAt).sort()[0]??null,analysisTruncated:!1,durationSec:n.reduce((e,t)=>e+Math.min(t.playtimeSec,108e3),0),sessionCount:n.reduce((e,t)=>e+Math.max(1,Math.ceil(t.playtimeSec/7200)),0),activePlayers:n.length}}}var Gt=100,Kt=64,X=[],qt=`0123456789abcdef`,Jt=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_`;function Yt(e,t){let n=``;for(let r=0;rt.id===e);)e=Yt(qt,8);return e}function Zt(){return`MOCKNOTAREALKEY-`+Yt(Jt,27)}async function Qt(){return V(),await z(),[...X].sort((e,t)=>t.createdAt.localeCompare(e.createdAt))}async function $t(e){V(),await z(150,300);let t=e.trim(),n=/[\u0000-\u001f\u007f-\u009f]/.test(t);if(!t||t.length>Kt||n)throw new L(400,`invalid_request`,`Label must be 1–64 characters with no control characters.`);if(X.filter(e=>e.revokedAt===null).length>=Gt)throw new L(409,`too_many_keys`,`The 100 active integration key limit has been reached.`);let r=Xt(),i={id:r,label:t,createdAt:new Date().toISOString(),lastUsedAt:null,revokedAt:null};return X.push(i),J.unshift({at:i.createdAt,kind:`panel`,message:`Integration key "${t}" created`}),{...i,key:`phk_${r}_${Zt()}`}}async function en(e){V(),await z(150,300);let t=X.find(t=>t.id===e);if(!t)throw new L(404,`not_found`,`Integration key not found.`);return t.revokedAt===null&&(t.revokedAt=new Date().toISOString(),J.unshift({at:t.revokedAt,kind:`panel`,message:`Integration key "${t.label}" revoked`})),{...t}}var tn=[[`Anubis`,`Anubis`],[`Bristla`,`Bristla`],[`Depresso`,`Depresso`],[`Eikthyrdeer`,`Eikthyrdeer`],[`Fuack`,`Fuack`],[`Grizzbolt`,`Grizzbolt`],[`Lamball`,`Lamball`],[`Mammorest`,`Mammorest`],[`Mossanda`,`Mossanda`],[`Petallia`,`Petallia`],[`Relaxaurus`,`Relaxaurus`],[`Shadowbeak`,`Shadowbeak`]];function nn(e,t){return new Set((Y[H[e]?.name??``]??[]).map(e=>e.characterId.toLowerCase())).has(t.toLowerCase())?e+1:0}async function rn(){B(),await z();let e=H.slice(0,3),t=tn.map(([t,n])=>{let r=e.map((e,n)=>nn(n,t));return{characterId:t,displayName:n,known:!0,captureCount:r.reduce((e,t)=>e+t,0),capturedByPlayers:r.filter(e=>e>0).length,unlockedByPlayers:r.filter(e=>e>0).length}});return{coverage:{source:`player_save_record_data`,playersTotal:H.length,playersWithCaptureCounts:e.length,playersWithUnlockFlags:e.length,captureCountsTruncated:!1,unlockFlagsTruncated:!1,oldestObservedAt:`2026-07-10T08:00:00Z`,latestObservedAt:new Date().toISOString()},catalog:{version:`palworld_1.0_pinned`,knownSpecies:tn.length,observedUnknownSpecies:0},captureTotal:e.reduce((e,t)=>e+(t.captureTotal??0),0),uniqueSpeciesCaptured:t.filter(e=>(e.captureCount??0)>0).length,speciesUnlocked:t.filter(e=>(e.unlockedByPlayers??0)>0).length,species:t}}async function an(e){B(),await z();let t=H.findIndex(t=>t.uid===e);if(t<0)throw new L(404,`not_found`,`Player not found.`);let n=H[t],r=t<3;return{player:{uid:n.uid,name:n.name},coverage:{source:`player_save_record_data`,captureCountsAvailable:r,unlockFlagsAvailable:r,captureCountsTruncated:!1,unlockFlagsTruncated:!1,captureObservedAt:r?new Date().toISOString():null,unlockObservedAt:r?new Date().toISOString():null},catalog:{version:`palworld_1.0_pinned`,knownSpecies:tn.length,observedUnknownSpecies:0},captureTotal:n.captureTotal??null,uniquePalsCaptured:n.uniquePalsCaptured??null,paldeckUnlocked:n.paldeckUnlocked??null,species:tn.map(([e,n])=>{let i=r?nn(t,e):null;return{characterId:e,displayName:n,known:!0,captureCount:i,unlocked:i===null?null:i>0}})}}async function on(){return B(),await z(30,100),{source:`palworld.gg`,fetchedAt:new Date(Date.now()-1728e5).toISOString(),count:2,characterIds:[`anubis`,`grizzbolt`]}}var sn={source:`thgl`,fetched_at:`2026-07-10T13:05:22Z`,game_version:`1.0`,notes:`THGL maintainer notes the redrawn Palpagos offset still needs fixing upstream; treat pixel alignment as best-effort.`,layers:[{id:`default`,label:`Palpagos`,path:`default`,format:`webp`,tile_size:512,min_zoom:0,max_zoom:4,transform:{a:.000353395913859746,b:256,c:-.000353395913859746,d:123.47653230259525},bounds:[[-1099399,-724399],[349399,724399]]},{id:`tree`,label:`World Tree`,path:`tree`,format:`webp`,tile_size:512,min_zoom:0,max_zoom:4,transform:{a:.0014979651664584533,b:1225.6306053008072,c:-.0014979651664584533,d:1032.3204475170935},bounds:[[347352.5,-818196],[689147.5,-476401]]}]},cn={fetched_at:null,game_version:`pre-1.0`,source:`palworld.gg`,layers:[]};async function ln(){return B(),await z(),typeof window<`u`&&new URLSearchParams(window.location.search).has(`mocktiles`)?sn:cn}async function un(){return B(),await z(),{day:3,lastParseAt:new Date(Date.now()-24e4).toISOString(),parseDurationMs:1200,stats:{players:H.length,pals:46,guilds:U.length,skippedProps:0},formatDrift:!1}}var dn=U[0]?.bases[0]?.location??{x:0,y:0},fn=U[0]?.bases[0]?.id,pn=[`Anubis`,`Grizzbolt`,`Digtoise`,`Penking`,`Foxparks`,`Lamball`,`Cattiva`,`Chikipi`,`Tombat`,`Rayhound`,`Melpaca`,`Vixy`,`Tanzee`,`Lifmunk`,`Fuack`,`Depresso`],mn=pn.map((e,t)=>{let n=t/pn.length*Math.PI*2,r=2600+t%4*1500,i=t===3||t===9,a=t===12;return{kind:`BaseCampPal`,characterId:e,name:e,level:8+t*7%28,hpPercent:a?0:i?14:70+t*13%30,active:!0,activity:a?`incapacitated`:t%5==0?`transporting`:t%3==0?`idle`:`working`,linked:!0,instanceId:`mock-worker-${t+1}`,baseId:fn,ownerName:H[0]?.name,location:{x:dn.x+Math.cos(n)*r,y:dn.y+Math.sin(n)*r,z:0}}});async function hn(){B(),await z();let e=H.filter(e=>e.online&&e.location);return{state:`ready`,capturedAt:new Date(Date.now()-12e3).toISOString(),lastAttemptAt:new Date(Date.now()-12e3).toISOString(),sourceTime:`2026-07-14 13:00:00`,fps:57,fpsAvg:55.4,counts:{players:e.length,partyPals:e.length*2,basePals:mn.length,wildPals:84,npcs:11,palBoxes:1,unknown:0},activity:{working:9,transporting:2,eating:1,sleeping:2,idle:2,inactive:1,combat:0,incapacitated:1,moving:0,unknown:0},actors:[...e.map(e=>({kind:`Player`,name:e.name,guildName:e.guildName??void 0,level:e.level,activity:`idle`,active:!0,location:{x:e.location.x,y:e.location.y,z:0}})),{kind:`PalBox`,guildName:U[0]?.name,activity:`unknown`,location:{x:dn.x,y:dn.y,z:0}},...mn],truncated:!1,diagnostics:{lastRequestDurationMs:184,lastAcceptedActorCount:118,lastErrorCategory:`none`,linkedBasePals:18,unresolvedBasePals:0,linkLookupFailed:!1,scheduledDelayMs:3e4,nextAttemptAt:new Date(Date.now()+18e3).toISOString()}}}async function gn(){V(),await z(400,900)}function _n(e){let[t,...n]=e.trim().split(/\s+/);switch((t??``).toLowerCase()){case`info`:return{output:`Welcome to Pal Server[v1.0.0.100427] My Palworld Server`,isError:!1};case`showplayers`:return{output:[`name,playeruid,steamid`,...H.filter(e=>e.online).map(e=>`${e.name},${e.uid.slice(0,8)},${e.steamId}`)].join(`
+`),isError:!1};case`save`:return{output:`Complete Save`,isError:!1};case`broadcast`:return n.length?{output:`Broadcasted: ${n.join(` `)}`,isError:!1}:{output:`Error: Broadcast requires a message.`,isError:!0};case`shutdown`:return{output:`Shutdown scheduled: ${n.join(` `)||`now`}`,isError:!1};case`kickplayer`:return n.length?{output:`Kicked: ${n[0]}`,isError:!1}:{output:`Error: KickPlayer requires a steamid.`,isError:!0};default:return{output:`Unknown command: ${e}`,isError:!0}}}async function vn(e){let t=V();await z(100,300);let{output:n,isError:r}=_n(e);return yt.push({at:new Date().toISOString(),user:t.username,command:e,output:n,isError:r}),{output:n}}async function yn(e){return B(),await z(),yt}async function bn(){return B(),await z(),q}async function xn(e,t){V(),await z();let n={id:`s${q.length+1}`,name:e,command:t};return q.push(n),n}async function Sn(e){V(),await z(),q=q.filter(t=>t.id!==e)}async function Cn(){return B(),await z(),G}async function wn(){V(),await z(300,700);let e={id:`b${G.length+1}`,file:`world-${new Date().toISOString().slice(0,16).replace(/[-:T]/g,``).slice(0,12)}.tar.gz`,createdAt:new Date().toISOString(),sizeBytes:147e5,trigger:`manual`,worldDay:3};return G.unshift(e),e}async function Tn(e){B(),await z();let t=G.find(t=>t.id===e);if(!t)throw new L(404,`not_found`,`Backup not found.`);return[{path:`Level.sav`,sizeBytes:139e5,modifiedAt:t.createdAt},{path:`LevelMeta.sav`,sizeBytes:4096,modifiedAt:t.createdAt},{path:`Players/84C20A31.sav`,sizeBytes:21e4,modifiedAt:t.createdAt}]}async function En(e){if(V(),await z(300,600),!G.find(t=>t.id===e))throw new L(404,`not_found`,`Backup not found.`);return{changes:[{path:`Players/84C20A31….sav`,kind:`add`,toSize:21e4},{path:`Level.sav`,kind:`modify`,fromSize:146e5,toSize:139e5},{path:`1 base camp`,kind:`delete`}],requiresStop:!0}}async function Dn(e,t){throw V(),t===`RESTORE`?G.find(t=>t.id===e)?(await z(500,1200),new L(409,`server_running`,`The game server is still running, and Palhelm has no docker.sock access to stop it. Stop the container, then retry the restore.`,{manualCommand:`docker compose stop palworld`})):new L(404,`not_found`,`Backup not found.`):new L(400,`bad_request`,`Type "RESTORE" to confirm.`)}async function On(e){V(),await z(150,300);let t=G.findIndex(t=>t.id===e);t>=0&&G.splice(t,1)}async function kn(){return B(),await z(),_t}async function An(){return B(),await z(),{totalBytes:5e11,freeBytes:4215e8}}async function jn(e){return V(),await z(150,300),_t={...e,nextRunAt:e.enabled?new Date(Date.now()+e.everyMinutes*6e4).toISOString():null},_t}async function Mn(){return B(),await z(),{source:`compose`,composeFile:`/compose/docker-compose.yml`,service:`palworld`,version:K,capabilities:{write:{available:!0},apply:{available:!1,reason:`One-click apply is intentionally disabled.`}},manualCommand:`docker compose up -d palworld`,settings:vt}}async function Nn(e,t){if(V(),await z(200,450),e!==K)throw new L(409,`config_conflict`,`The compose file changed after it was loaded.`);for(let[e,n]of Object.entries(t)){let t=vt.find(t=>t.key===e);t&&(t.value=n,t.pending=n!==t.effectiveValue)}return K=`mock:${Number(K.split(`:`)[1])+1}`,Mn()}async function Pn(){return B(),await z(),[`; This file is generated by the container entrypoint from compose environment variables.`,`; Edits made here are overwritten on every boot — use the Palhelm settings editor instead.`,`[/Script/Pal.PalGameWorldSettings]`,`OptionSettings=(${vt.filter(e=>e.key!==`ADMIN_PASSWORD`&&e.key!==`SERVER_PASSWORD`).map(e=>{let t=e.type===`string`?`"${e.effectiveValue}"`:e.effectiveValue;return`${e.key}=${t}`}).join(`,`)},AdminPassword="***")`,``].join(`
+`)}async function Fn(){throw V(),await z(400,900),new L(501,`docker_apply_disabled`,`One-click Docker apply is intentionally disabled; run the manual command from the host directory containing the compose file.`,{manualCommand:`docker compose up -d palworld`})}async function In(e,t){return B(),await z(),(t?J.filter(e=>e.kind===t):J).slice(0,e)}function Ln(e){if(typeof e!=`object`||!e)return!1;let t=e;return typeof t.key==`string`&&[`string`,`integer`,`number`,`boolean`].includes(String(t.type))&&typeof t.group==`string`&&typeof t.pending==`boolean`&&typeof t.editable==`boolean`&&typeof t.readOnly==`boolean`&&t.editable!==t.readOnly}function Rn(e){if(typeof e!=`object`||!e)throw TypeError(`Config response is not an object`);let t=e,n=t.capabilities,r=n?.write,i=n?.apply;if(t.source!==`compose`&&t.source!==`ini`||typeof t.service!=`string`||typeof t.manualCommand!=`string`||typeof r?.available!=`boolean`||typeof i?.available!=`boolean`||!Array.isArray(t.settings)||!t.settings.every(Ln))throw TypeError(`Config response does not match the frontend contract`);return e}function zn(e,t){e.setQueryData([`config`],Rn(t))}var Bn=new Set;function Vn(e){return Bn.add(e),()=>{Bn.delete(e)}}function Hn(e){e===401&&Bn.forEach(e=>e())}function Un(e,t){let n=typeof t==`object`&&t&&`status`in t?t.status:void 0;return n===401||n===403||n===429?!1:e<1}var Z=typeof window<`u`&&new URLSearchParams(window.location.search).has(`mock`),Wn=`/api/v1`;async function Gn(e){let t=`unknown_error`,n=e.statusText||`Request failed`,r={};try{let i=await e.json();if(i.error){let{code:e,message:a,...o}=i.error;typeof e==`string`&&(t=e),typeof a==`string`&&(n=a);let s={...i};delete s.error,r={...s,...o}}}catch{}return Hn(e.status),new L(e.status,t,n,r)}async function Q(e,t,n){let r=await fetch(Wn+t,{method:e,headers:n===void 0?{}:{"Content-Type":`application/json`},body:n===void 0?void 0:JSON.stringify(n),credentials:`include`});if(!r.ok)throw await Gn(r);if(r.status===204)return;let i=await r.text();return i?JSON.parse(i):void 0}async function Kn(e,t){let n=await fetch(Wn+t,{method:e,credentials:`include`});if(!n.ok)throw await Gn(n);return n.text()}var qn={auth:{login:e=>Z?xt(e):Q(`POST`,`/auth/login`,{password:e}),logout:()=>Z?St():Q(`POST`,`/auth/logout`),session:()=>Z?Ct():Q(`GET`,`/auth/session`)},server:{get:()=>Z?wt():Q(`GET`,`/server`),health:()=>Z?Tt():Q(`GET`,`/server/health`),announce:e=>Z?Et(e):Q(`POST`,`/server/announce`,{message:e}),save:()=>Z?Dt():Q(`POST`,`/server/save`),shutdown:(e,t,n)=>Z?Ot(e,t,n):Q(`POST`,`/server/shutdown`,{waitSec:e,message:t,countdown:n}),cancelShutdown:()=>Z?kt():Q(`POST`,`/server/shutdown/cancel`)},metrics:{current:()=>Z?At():Q(`GET`,`/metrics/current`),history:e=>Z?Mt(e):Q(`GET`,`/metrics/history?window=${e}`)},activity:{get:(e=`7d`)=>Z?Lt(e):Q(`GET`,`/activity?window=${e}`)},players:{list:()=>Z?Nt():Q(`GET`,`/players`),detail:e=>Z?It(e):Q(`GET`,`/players/${e}`),kick:(e,t)=>Z?Rt(e,t):Q(`POST`,`/players/${e}/kick`,{message:t}),ban:(e,t)=>Z?zt(e,t):Q(`POST`,`/players/${e}/ban`,{message:t}),unban:e=>Z?Bt(e):Q(`POST`,`/players/${e}/unban`),avatarUrl:e=>`${Wn}/players/${encodeURIComponent(e)}/avatar`},pals:{list:(e={})=>{if(Z)return Ft(e);let t=new URLSearchParams;return e.cursor&&t.set(`cursor`,e.cursor),e.limit!==void 0&&t.set(`limit`,String(e.limit)),e.q&&t.set(`q`,e.q),e.ownerSource&&t.set(`ownerSource`,e.ownerSource),e.placement&&t.set(`placement`,e.placement),e.specimen&&t.set(`specimen`,e.specimen),e.minLevel!==void 0&&t.set(`minLevel`,String(e.minLevel)),e.maxLevel!==void 0&&t.set(`maxLevel`,String(e.maxLevel)),Q(`GET`,`/pals${t.size>0?`?${t}`:``}`)}},whitelist:{get:()=>Z?Vt():Q(`GET`,`/whitelist`),put:e=>Z?Ht(e):Q(`PUT`,`/whitelist`,e)},guilds:{list:()=>Z?Ut():Q(`GET`,`/guilds`),detail:e=>Z?Wt(e):Q(`GET`,`/guilds/${encodeURIComponent(e)}`)},integrationKeys:{list:()=>Z?Qt():Q(`GET`,`/integration-keys`),create:e=>Z?$t(e):Q(`POST`,`/integration-keys`,{label:e}),revoke:e=>Z?en(e):Q(`DELETE`,`/integration-keys/${e}`)},paldeck:{get:()=>Z?rn():Q(`GET`,`/paldeck`),player:e=>Z?an(e):Q(`GET`,`/players/${encodeURIComponent(e)}/paldeck`),iconDataset:()=>Z?on():Q(`GET`,`/paldeck/icon-dataset`),iconUrl:e=>`${Wn}/paldeck/icon/${encodeURIComponent(e.toLowerCase())}`},map:{dataset:()=>Z?ln():Q(`GET`,`/map/dataset`)},world:{get:()=>Z?un():Q(`GET`,`/world`),snapshot:()=>Z?hn():Q(`GET`,`/world/snapshot`),activity:(e=`1h`)=>Q(`GET`,`/world/activity?window=${e}`),parse:()=>Z?gn():Q(`POST`,`/world/parse`)},console:{exec:e=>Z?vn(e):Q(`POST`,`/console/exec`,{command:e}),log:(e=200)=>Z?yn(e):Q(`GET`,`/console/log?limit=${e}`),savedList:()=>Z?bn():Q(`GET`,`/console/saved`),savedCreate:(e,t)=>Z?xn(e,t):Q(`POST`,`/console/saved`,{name:e,command:t}),savedDelete:e=>Z?Sn(e):Q(`DELETE`,`/console/saved/${e}`)},backups:{list:()=>Z?Cn():Q(`GET`,`/backups`),create:()=>Z?wn():Q(`POST`,`/backups`),contents:e=>Z?Tn(e):Q(`GET`,`/backups/${e}/contents`),dryRun:e=>Z?En(e):Q(`POST`,`/backups/${e}/restore/dry-run`),restore:(e,t)=>Z?Dn(e,t):Q(`POST`,`/backups/${e}/restore`,{confirm:t}),remove:e=>Z?On(e):Q(`DELETE`,`/backups/${e}`),schedule:()=>Z?kn():Q(`GET`,`/backups/schedule`),storage:()=>Z?An():Q(`GET`,`/backups/storage`),setSchedule:e=>Z?jn(e):Q(`PUT`,`/backups/schedule`,e)},config:{get:async()=>Rn(Z?await Mn():await Q(`GET`,`/config`)),put:async(e,t)=>Rn(Z?await Nn(e,t):await Q(`PUT`,`/config`,{version:e,changes:t})),raw:()=>Z?Pn():Kn(`GET`,`/config/raw`),apply:()=>Z?Fn():Q(`POST`,`/config/apply`)},events:{list:(e=100,t)=>Z?In(e,t):Q(`GET`,`/events?limit=${e}${t?`&kind=${t}`:``}`)}};function $(e){return{width:16,height:16,viewBox:`0 0 16 16`,fill:`none`,"aria-hidden":!0,...e}}function Jn({size:e=26,strokeWidth:t=1.8,dotRadius:n=1.2,wheelClassName:r,...i}){let a=(0,I.jsxs)(I.Fragment,{children:[(0,I.jsx)(`path`,{d:`M6.99 19.01 A8.5 8.5 0 1 1 19.01 6.99 Z`,fill:`var(--sphere)`}),(0,I.jsx)(`path`,{d:`M6.99 19.01 L19.01 6.99`,stroke:`var(--accent)`,strokeWidth:t,strokeLinecap:`round`}),(0,I.jsx)(`rect`,{x:`15.1`,y:`15.1`,width:`3`,height:`3`,rx:`0.6`,transform:`rotate(45 16.6 16.6)`,fill:`var(--sphere)`}),(0,I.jsx)(`circle`,{cx:`13`,cy:`13`,r:`8.5`,stroke:`var(--accent)`,strokeWidth:t}),(0,I.jsxs)(`g`,{stroke:`var(--accent)`,strokeWidth:t,strokeLinecap:`round`,children:[(0,I.jsx)(`path`,{d:`M13 1.5v4`}),(0,I.jsx)(`path`,{d:`M13 20.5v4`}),(0,I.jsx)(`path`,{d:`M1.5 13h4`}),(0,I.jsx)(`path`,{d:`M20.5 13h4`}),(0,I.jsx)(`path`,{d:`M4.87 4.87l2.83 2.83`}),(0,I.jsx)(`path`,{d:`M18.3 18.3l2.83 2.83`}),(0,I.jsx)(`path`,{d:`M21.13 4.87l-2.83 2.83`}),(0,I.jsx)(`path`,{d:`M7.7 18.3l-2.83 2.83`})]})]});return(0,I.jsx)(`svg`,{width:e,height:e,viewBox:`0 0 26 26`,fill:`none`,"aria-hidden":`true`,...i,children:r?(0,I.jsx)(`g`,{className:r,children:a}):a})}function Yn(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`path`,{d:`M2 9a6 6 0 1 1 12 0`}),(0,I.jsx)(`path`,{d:`M8 9l3-3`}),(0,I.jsx)(`path`,{d:`M2.5 12h11`})]})}function Xn(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`circle`,{cx:`6`,cy:`5`,r:`2.5`}),(0,I.jsx)(`path`,{d:`M1.5 13.5c0-2.5 2-4 4.5-4s4.5 1.5 4.5 4`}),(0,I.jsx)(`path`,{d:`M11 3.2a2.5 2.5 0 0 1 0 4.6`}),(0,I.jsx)(`path`,{d:`M12.5 9.8c1.2.6 2 1.7 2 3.2`})]})}function Zn(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`M2 13.5V2.5M2 13.5h12`}),(0,I.jsx)(`path`,{d:`m4 10 2.5-3 2.2 1.8L12.5 4`}),(0,I.jsx)(`circle`,{cx:`4`,cy:`10`,r:`.7`,fill:`currentColor`,stroke:`none`}),(0,I.jsx)(`circle`,{cx:`6.5`,cy:`7`,r:`.7`,fill:`currentColor`,stroke:`none`}),(0,I.jsx)(`circle`,{cx:`8.7`,cy:`8.8`,r:`.7`,fill:`currentColor`,stroke:`none`}),(0,I.jsx)(`circle`,{cx:`12.5`,cy:`4`,r:`.7`,fill:`currentColor`,stroke:`none`})]})}function Qn(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`M1.5 3.5l4-1.5 5 1.5 4-1.5v10l-4 1.5-5-1.5-4 1.5z`}),(0,I.jsx)(`path`,{d:`M5.5 2v10.5M10.5 3.5V14`})]})}function $n(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`circle`,{cx:`8`,cy:`5`,r:`2.25`}),(0,I.jsx)(`path`,{d:`M3.7 13.5c.2-2.5 1.9-4 4.3-4s4.1 1.5 4.3 4`})]})}function er(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.4`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`M4.2 5.3 2.8 2.2l3.4 1.5M11.8 5.3l1.4-3.1-3.4 1.5`}),(0,I.jsx)(`path`,{d:`M3.6 7.4c0-2.5 1.9-4.2 4.4-4.2s4.4 1.7 4.4 4.2v1.3c0 2.6-1.9 4.5-4.4 4.5s-4.4-1.9-4.4-4.5z`}),(0,I.jsx)(`path`,{d:`M5.8 8.2h.1M10.1 8.2h.1M6.4 10.6c1 .7 2.2.7 3.2 0`})]})}function tr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`M3 14V2.2M3.4 3h8.8l-1.7 2.5 1.7 2.5H3.4`}),(0,I.jsx)(`path`,{d:`M1.7 14h3`})]})}function nr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.4`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`M2.2 2.5h4.2c.9 0 1.6.7 1.6 1.6v9.4c0-.9-.7-1.6-1.6-1.6H2.2z`}),(0,I.jsx)(`path`,{d:`M13.8 2.5H9.6c-.9 0-1.6.7-1.6 1.6v9.4c0-.9.7-1.6 1.6-1.6h4.2z`}),(0,I.jsx)(`circle`,{cx:`8`,cy:`7.1`,r:`1.3`})]})}function rr(e){return(0,I.jsx)(er,{...e})}function ir(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`m2.2 7.2 5.8-5 5.8 5`}),(0,I.jsx)(`path`,{d:`M3.8 6.2v7.3h8.4V6.2M6.5 13.5V9.8h3v3.7`})]})}function ar(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`rect`,{x:`2.2`,y:`4`,width:`11.6`,height:`9.2`,rx:`1.2`}),(0,I.jsx)(`path`,{d:`M5 4V2.5h6V4M2.2 7.1h11.6M6.4 9.7h3.2`})]})}function or(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`circle`,{cx:`7`,cy:`7`,r:`4.5`}),(0,I.jsx)(`path`,{d:`m10.3 10.3 3.4 3.4M7 4.8v4.4M4.8 7h4.4`})]})}function sr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`circle`,{cx:`7`,cy:`7`,r:`4.5`}),(0,I.jsx)(`path`,{d:`m10.3 10.3 3.4 3.4M4.8 7h4.4`})]})}function cr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`M6 2.5H2.5V6M10 2.5h3.5V6M6 13.5H2.5V10M10 13.5h3.5V10`}),(0,I.jsx)(`circle`,{cx:`8`,cy:`8`,r:`1.5`})]})}function lr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`path`,{d:`M3 5l3 3-3 3`}),(0,I.jsx)(`path`,{d:`M8 11.5h5`})]})}function ur(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`path`,{d:`M3 2.5h10v11H3z`}),(0,I.jsx)(`path`,{d:`M5.5 5h5M5.5 8h5M5.5 11h3`})]})}function dr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`rect`,{x:`2`,y:`2.5`,width:`12`,height:`3.5`,rx:`0.5`}),(0,I.jsx)(`path`,{d:`M3 6v6.5a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V6`}),(0,I.jsx)(`path`,{d:`M6.5 9h3`})]})}function fr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`path`,{d:`M2 5h8M12.5 5H14M2 11h2M6.5 11H14`}),(0,I.jsx)(`circle`,{cx:`10.5`,cy:`5`,r:`1.8`}),(0,I.jsx)(`circle`,{cx:`4.5`,cy:`11`,r:`1.8`})]})}function pr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`circle`,{cx:`8`,cy:`8`,r:`2.2`}),(0,I.jsx)(`path`,{d:`M8 1.8v2M8 12.2v2M1.8 8h2M12.2 8h2M3.6 3.6l1.4 1.4M11 11l1.4 1.4M12.4 3.6L11 5M5 11l-1.4 1.4`})]})}function mr(e){return(0,I.jsxs)(`svg`,{width:14,height:14,viewBox:`0 0 14 14`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.5`,"aria-hidden":`true`,...e,children:[(0,I.jsx)(`circle`,{cx:`6`,cy:`6`,r:`4.2`}),(0,I.jsx)(`path`,{d:`M9.5 9.5L13 13`,strokeLinecap:`round`})]})}function hr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:[(0,I.jsx)(`path`,{d:`M8 1.5l7 12.5H1z`}),(0,I.jsx)(`path`,{d:`M8 6.2v3.2`}),(0,I.jsx)(`circle`,{cx:`8`,cy:`11.6`,r:`0.6`,fill:`currentColor`,stroke:`none`})]})}function gr(e){return(0,I.jsxs)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:[(0,I.jsx)(`circle`,{cx:`8`,cy:`8`,r:`6.3`}),(0,I.jsx)(`path`,{d:`M8 7.2v4M8 5.1v.05`})]})}function _r(e){return(0,I.jsxs)(`svg`,{...$(e),fill:`currentColor`,"aria-hidden":`true`,children:[(0,I.jsx)(`circle`,{cx:`8`,cy:`3.4`,r:`1.3`}),(0,I.jsx)(`circle`,{cx:`8`,cy:`8`,r:`1.3`}),(0,I.jsx)(`circle`,{cx:`8`,cy:`12.6`,r:`1.3`})]})}function vr(e){return(0,I.jsx)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,children:(0,I.jsx)(`path`,{d:`M3.5 3.5l9 9M12.5 3.5l-9 9`})})}function yr(e){return(0,I.jsx)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:(0,I.jsx)(`path`,{d:`M10 4l-4 4 4 4`})})}function br(e){return(0,I.jsx)(`svg`,{...$(e),stroke:`currentColor`,strokeWidth:`1.5`,strokeLinecap:`round`,strokeLinejoin:`round`,children:(0,I.jsx)(`path`,{d:`M6 4l4 4-4 4`})})}function xr(e){return(0,I.jsxs)(`svg`,{width:40,height:40,viewBox:`0 0 40 40`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinejoin:`round`,"aria-hidden":`true`,...e,children:[(0,I.jsx)(`path`,{d:`M4 9l11-4 14 4 11-4v26l-11 4-14-4-11 4z`}),(0,I.jsx)(`path`,{d:`M15 5v26M26 9v26`}),(0,I.jsx)(`path`,{d:`M8 34l24-24`,strokeDasharray:`2 3`})]})}function Sr(e){return(0,I.jsxs)(`svg`,{width:40,height:40,viewBox:`0 0 40 40`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.5`,strokeLinejoin:`round`,"aria-hidden":`true`,...e,children:[(0,I.jsx)(`rect`,{x:`5`,y:`6`,width:`30`,height:`8`,rx:`1`}),(0,I.jsx)(`path`,{d:`M7 14v16a2 2 0 0 0 2 2h22a2 2 0 0 0 2-2V14`}),(0,I.jsx)(`path`,{d:`M16 21h8`,strokeLinecap:`round`})]})}export{ge as $,Z as A,it as B,er as C,hr as D,pr as E,R as F,Re as G,L as H,at as I,De as J,Le as K,nt as L,Vn as M,Un as N,or as O,zn as P,_e as Q,ot as R,nr as S,mr as T,Qe as U,tt as V,Ze as W,xe as X,Ce as Y,Se as Z,xr as _,c as _t,yr as a,w as at,rr as b,fr as c,E as ct,cr as d,oe as dt,fe as et,tr as f,ie as ft,ir as g,o as gt,Qn as h,u as ht,dr as i,ee as it,qn as j,sr as k,lr as l,x as lt,_r as m,d as mt,Zn as n,v as nt,br as o,C as ot,gr as p,f as pt,Fe as q,Sr as r,T as rt,vr as s,_ as st,Jn as t,de as tt,ur as u,O as ut,ar as v,Xn as w,Yn as x,$n as y,rt as z};
\ No newline at end of file
diff --git a/backend/internal/webdist/dist/assets/index-38JxCrNC.css b/backend/internal/webdist/dist/assets/index-38JxCrNC.css
new file mode 100644
index 0000000..67c10ca
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/index-38JxCrNC.css
@@ -0,0 +1 @@
+@font-face{font-family:IBM Plex Sans;src:url(/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2)format("woff2");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:IBM Plex Sans;src:url(/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2)format("woff2");font-weight:500;font-style:normal;font-display:swap}@font-face{font-family:IBM Plex Sans;src:url(/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2)format("woff2");font-weight:600;font-style:normal;font-display:swap}@font-face{font-family:IBM Plex Mono;src:url(/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2)format("woff2");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:IBM Plex Mono;src:url(/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2)format("woff2");font-weight:600;font-style:normal;font-display:swap}:root{--font-display:"Charter", "Bitstream Charter", "Sitka Text", Cambria, Georgia, serif;--font-ui:"IBM Plex Sans", "Segoe UI", system-ui, sans-serif;--font-mono:"IBM Plex Mono", ui-monospace, "Cascadia Mono", monospace;--text-xs:12px;--text-sm:13px;--text-md:14px;--text-lg:16px;--text-xl:18px;--text-2xl:22px;--text-3xl:28px;--leading-tight:1.25;--leading-body:1.5;--track-caps:.07em;--space-1:4px;--space-2:8px;--space-3:12px;--space-4:16px;--space-5:20px;--space-6:24px;--space-8:32px;--space-10:40px;--radius-ctl:8px;--radius-card:10px;--border-card:2px;--border-ctl:1.5px;--rail-w:232px;--helmstrip-h:56px;--brass:#c9964a;--brass-bright:#dfb679;--sphere:#63ad50;--band-bg:#3c461e;--band-edge:#262d10;--band-ink:#f2ecd6;--band-ink-2:#c9cfa4;--band-well:#f2ecd61a;--band-well-2:#f2ecd633;--band-line:#f2ecd63d;--band-line-strong:#f2ecd670;--band-ok:#9ed37f;--band-ok-ink:#b9e3a4;--band-ok-soft:#6fb35b2e;--band-warn:#e6b06a;--band-warn-ink:#f3d2a9;--band-warn-soft:#d59a522e;--band-danger:#ef9382;--band-danger-ink:#f9b5aa;--band-danger-soft:#e0705c33;--band-idle-ink:#c9cfa4;--band-chart:#ccd79b;--lightningcss-light:initial;--lightningcss-dark: ;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--bg:#ede3c8;--surface:#faf5e6;--surface-2:#f0e7cf;--surface-3:#e2d5b2;--line:#d3c7a4;--line-strong:#a89a6e;--ink:#2a2414;--ink-2:#57503a;--ink-3:#665c40;--accent:#55682b;--accent-ink:#47591f;--accent-soft:#55682b1f;--on-accent:#fbf7ea;--ok:#2e7a32;--ok-ink:#2c6e2f;--ok-soft:#2e7a3224;--warn:#a05f14;--warn-ink:#8a5216;--warn-soft:#a05f1424;--danger:#b23a2a;--danger-ink:#a2372a;--danger-soft:#b23a2a1f;--on-danger:#fbf7ea;--chart-line:#5c7030;--chart-fill:#5c703024;--chart-grid:#2a24141a;--page-ink:var(--ink);--page-ink-2:var(--ink-2);--page-ink-3:var(--ink-3);--page-surface:var(--surface);--page-surface-2:var(--surface-2);--page-surface-3:var(--surface-3);--page-line:var(--line);--page-line-strong:var(--line-strong);--page-bg:var(--bg);--page-accent:var(--accent);--page-accent-ink:var(--accent-ink);--page-accent-soft:var(--accent-soft);--page-on-accent:var(--on-accent);--page-ok:var(--ok);--page-ok-ink:var(--ok-ink);--page-ok-soft:var(--ok-soft);--page-warn:var(--warn);--page-warn-ink:var(--warn-ink);--page-warn-soft:var(--warn-soft);--page-danger:var(--danger);--page-danger-ink:var(--danger-ink);--page-danger-soft:var(--danger-soft);--page-on-danger:var(--on-danger);--page-chart-line:var(--chart-line);--console-bg:var(--bg);--console-out:var(--ink);--console-ts:var(--ink-3);--console-sys:var(--ink-2);--console-cmd:var(--accent-ink);--console-err:var(--danger-ink);--console-shadow:#2a241412;--focus-ring:0 0 0 2px var(--bg), 0 0 0 4px var(--accent);--shadow-card:0 1px 0 #2a241414, 0 2px 6px #2a24140d;--shadow-pop:0 10px 28px #2a241447;--paper-grain-opacity:.5}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg:#181206;--surface:#221a0b;--surface-2:#2d2412;--surface-3:#3a2f19;--line:#3b311c;--line-strong:#5a4c2b;--ink:#efe6cd;--ink-2:#bfb28a;--ink-3:#9e9166;--accent:#93a653;--accent-ink:#b4c878;--accent-soft:#93a65329;--on-accent:#1c1608;--ok:#6fb35b;--ok-ink:#93c77e;--ok-soft:#6fb35b29;--warn:#d59a52;--warn-ink:#e0ab6b;--warn-soft:#d59a5229;--danger:#e0705c;--danger-ink:#ef9382;--danger-soft:#e0705c2e;--on-danger:#1c1608;--chart-line:#b4c878;--chart-fill:#b4c8781f;--chart-grid:#efe6cd14;--page-ink:var(--ink);--page-ink-2:var(--ink-2);--page-ink-3:var(--ink-3);--page-surface:var(--surface);--page-surface-2:var(--surface-2);--page-surface-3:var(--surface-3);--page-line:var(--line);--page-line-strong:var(--line-strong);--page-bg:var(--bg);--page-accent:var(--accent);--page-accent-ink:var(--accent-ink);--page-accent-soft:var(--accent-soft);--page-on-accent:var(--on-accent);--page-ok:var(--ok);--page-ok-ink:var(--ok-ink);--page-ok-soft:var(--ok-soft);--page-warn:var(--warn);--page-warn-ink:var(--warn-ink);--page-warn-soft:var(--warn-soft);--page-danger:var(--danger);--page-danger-ink:var(--danger-ink);--page-danger-soft:var(--danger-soft);--page-on-danger:var(--on-danger);--page-chart-line:var(--chart-line);--console-bg:#120c02;--console-out:#dce4b4;--console-ts:#a99f70;--console-sys:#c4b98d;--console-cmd:#b9cd7d;--console-err:#ef9382;--console-shadow:#00000080;--focus-ring:0 0 0 2px var(--bg), 0 0 0 4px var(--accent);--shadow-card:0 1px 0 #00000059, 0 2px 6px #00000040;--shadow-pop:0 10px 28px #0000008c;--paper-grain-opacity:.06}}:root[data-theme=light]{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--bg:#ede3c8;--surface:#faf5e6;--surface-2:#f0e7cf;--surface-3:#e2d5b2;--line:#d3c7a4;--line-strong:#a89a6e;--ink:#2a2414;--ink-2:#57503a;--ink-3:#665c40;--accent:#55682b;--accent-ink:#47591f;--accent-soft:#55682b1f;--on-accent:#fbf7ea;--ok:#2e7a32;--ok-ink:#2c6e2f;--ok-soft:#2e7a3224;--warn:#a05f14;--warn-ink:#8a5216;--warn-soft:#a05f1424;--danger:#b23a2a;--danger-ink:#a2372a;--danger-soft:#b23a2a1f;--on-danger:#fbf7ea;--chart-line:#5c7030;--chart-fill:#5c703024;--chart-grid:#2a24141a;--page-ink:var(--ink);--page-ink-2:var(--ink-2);--page-ink-3:var(--ink-3);--page-surface:var(--surface);--page-surface-2:var(--surface-2);--page-surface-3:var(--surface-3);--page-line:var(--line);--page-line-strong:var(--line-strong);--page-bg:var(--bg);--page-accent:var(--accent);--page-accent-ink:var(--accent-ink);--page-accent-soft:var(--accent-soft);--page-on-accent:var(--on-accent);--page-ok:var(--ok);--page-ok-ink:var(--ok-ink);--page-ok-soft:var(--ok-soft);--page-warn:var(--warn);--page-warn-ink:var(--warn-ink);--page-warn-soft:var(--warn-soft);--page-danger:var(--danger);--page-danger-ink:var(--danger-ink);--page-danger-soft:var(--danger-soft);--page-on-danger:var(--on-danger);--page-chart-line:var(--chart-line);--console-bg:var(--bg);--console-out:var(--ink);--console-ts:var(--ink-3);--console-sys:var(--ink-2);--console-cmd:var(--accent-ink);--console-err:var(--danger-ink);--console-shadow:#2a241412;--focus-ring:0 0 0 2px var(--bg), 0 0 0 4px var(--accent);--shadow-card:0 1px 0 #2a241414, 0 2px 6px #2a24140d;--shadow-pop:0 10px 28px #2a241447;--paper-grain-opacity:.5}:root[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg:#181206;--surface:#221a0b;--surface-2:#2d2412;--surface-3:#3a2f19;--line:#3b311c;--line-strong:#5a4c2b;--ink:#efe6cd;--ink-2:#bfb28a;--ink-3:#9e9166;--accent:#93a653;--accent-ink:#b4c878;--accent-soft:#93a65329;--on-accent:#1c1608;--ok:#6fb35b;--ok-ink:#93c77e;--ok-soft:#6fb35b29;--warn:#d59a52;--warn-ink:#e0ab6b;--warn-soft:#d59a5229;--danger:#e0705c;--danger-ink:#ef9382;--danger-soft:#e0705c2e;--on-danger:#1c1608;--chart-line:#b4c878;--chart-fill:#b4c8781f;--chart-grid:#efe6cd14;--page-ink:var(--ink);--page-ink-2:var(--ink-2);--page-ink-3:var(--ink-3);--page-surface:var(--surface);--page-surface-2:var(--surface-2);--page-surface-3:var(--surface-3);--page-line:var(--line);--page-line-strong:var(--line-strong);--page-bg:var(--bg);--page-accent:var(--accent);--page-accent-ink:var(--accent-ink);--page-accent-soft:var(--accent-soft);--page-on-accent:var(--on-accent);--page-ok:var(--ok);--page-ok-ink:var(--ok-ink);--page-ok-soft:var(--ok-soft);--page-warn:var(--warn);--page-warn-ink:var(--warn-ink);--page-warn-soft:var(--warn-soft);--page-danger:var(--danger);--page-danger-ink:var(--danger-ink);--page-danger-soft:var(--danger-soft);--page-on-danger:var(--on-danger);--page-chart-line:var(--chart-line);--console-bg:#120c02;--console-out:#dce4b4;--console-ts:#a99f70;--console-sys:#c4b98d;--console-cmd:#b9cd7d;--console-err:#ef9382;--console-shadow:#00000080;--focus-ring:0 0 0 2px var(--bg), 0 0 0 4px var(--accent);--shadow-card:0 1px 0 #00000059, 0 2px 6px #00000040;--shadow-pop:0 10px 28px #0000008c;--paper-grain-opacity:.06}*{box-sizing:border-box;margin:0;padding:0}html,body{height:100%}body{font-family:var(--font-ui);font-size:var(--text-md);line-height:var(--leading-body);color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased}body:before{content:"";z-index:2000;pointer-events:none;mix-blend-mode:multiply;opacity:var(--paper-grain-opacity);background:url(/assets/tex-noise-canvas-Cczou4P1.png) 0 0/512px 512px;position:fixed;inset:0}:root[data-theme=dark] body:before{mix-blend-mode:overlay}@media (prefers-color-scheme:dark){:root:not([data-theme=light]) body:before{mix-blend-mode:overlay}}a{color:var(--accent-ink);text-decoration:none}a:hover{text-decoration:underline}:is(button,a,input,select,textarea,summary,[tabindex]):focus-visible{box-shadow:var(--focus-ring);border-radius:var(--radius-ctl);outline:none}@media (prefers-reduced-motion:reduce){*,:before,:after{transition:none!important;animation:none!important}}@media (forced-colors:active){:is(button,a,input,select,textarea,summary,[tabindex]):focus-visible,.input:focus{outline-offset:2px;box-shadow:none;outline:2px solid #0000}}.shell{grid-template-columns:var(--rail-w) 1fr;min-height:100vh;display:grid}.rail{background:var(--surface);border-right:var(--border-card) solid var(--line);flex-direction:column;height:100vh;display:flex;position:sticky;top:0}.rail-brand{border-bottom:var(--border-card) solid var(--line);align-items:center;gap:10px;padding:14px 16px;display:flex}.rail-brand .mark{flex:none}.rail-brand .word{font-family:var(--font-mono);letter-spacing:.04em;color:var(--ink);font-size:15px;font-weight:600}.rail-brand .word b{color:var(--accent-ink);font-weight:600}.rail-nav{padding:var(--space-2);flex-direction:column;flex:1;gap:2px;display:flex}.rail-group{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3);padding:14px 10px 4px;font-size:11px}.rail-item{border-radius:var(--radius-ctl);color:var(--ink-2);font-size:var(--text-md);align-items:center;gap:10px;padding:7px 10px;font-weight:500;display:flex}.rail-item:hover{background:var(--surface-2);color:var(--ink);text-decoration:none}.rail-item[aria-current=page]{background:var(--accent-soft);color:var(--accent-ink);position:relative}.rail-item[aria-current=page]:before{content:"";background:var(--accent);border-radius:1.5px;width:3px;position:absolute;top:6px;bottom:6px;left:-8px}.rail-item svg{opacity:.85;flex:none}.rail-foot{border-top:var(--border-card) solid var(--line);font-size:var(--text-xs);color:var(--ink-3);justify-content:space-between;align-items:center;padding:10px 16px;display:flex}.rail-foot .who{flex-direction:column;display:flex}.rail-foot .who b{color:var(--ink-2);font-weight:500}.main{flex-direction:column;min-width:0;display:flex}.helmstrip{height:var(--helmstrip-h);background:var(--band-bg);border-bottom:3px solid var(--band-edge);padding:0 var(--space-5);align-items:stretch;gap:var(--space-6);z-index:10;color:var(--band-ink);--ink:var(--band-ink);--ink-2:var(--band-ink-2);--ink-3:var(--band-ink-2);--surface:var(--band-bg);--surface-2:var(--band-well);--surface-3:var(--band-well-2);--line:var(--band-line);--line-strong:var(--band-line-strong);--bg:var(--band-bg);--accent:var(--band-chart);--ok:var(--band-ok);--ok-ink:var(--band-ok-ink);--ok-soft:var(--band-ok-soft);--warn:var(--band-warn);--warn-ink:var(--band-warn-ink);--warn-soft:var(--band-warn-soft);--danger:var(--band-danger);--danger-ink:var(--band-danger-ink);--danger-soft:var(--band-danger-soft);--chart-line:var(--band-chart);--on-accent:var(--band-edge);--on-danger:var(--band-edge);--accent-ink:var(--band-chart);--accent-soft:#ccd79b24;display:flex;position:sticky;top:0}dialog.dialog{--ink:var(--page-ink);--ink-2:var(--page-ink-2);--ink-3:var(--page-ink-3);--surface:var(--page-surface);--surface-2:var(--page-surface-2);--surface-3:var(--page-surface-3);--line:var(--page-line);--line-strong:var(--page-line-strong);--bg:var(--page-bg);--accent:var(--page-accent);--accent-ink:var(--page-accent-ink);--accent-soft:var(--page-accent-soft);--on-accent:var(--page-on-accent);--ok:var(--page-ok);--ok-ink:var(--page-ok-ink);--ok-soft:var(--page-ok-soft);--warn:var(--page-warn);--warn-ink:var(--page-warn-ink);--warn-soft:var(--page-warn-soft);--danger:var(--page-danger);--danger-ink:var(--page-danger-ink);--danger-soft:var(--page-danger-soft);--on-danger:var(--page-on-danger);--chart-line:var(--page-chart-line)}.instrument{align-items:center;gap:10px;min-width:0;display:flex}.instrument+.instrument{border-left:1px solid var(--band-line);padding-left:var(--space-6)}.instrument .label{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--band-ink-2);white-space:nowrap;font-size:11px;display:block}.instrument .value{font-family:var(--font-mono);font-size:var(--text-md);color:var(--band-ink);font-variant-numeric:tabular-nums;white-space:nowrap;font-weight:600}.instrument .value small{color:var(--band-ink-2);font-weight:400}.helmstrip .grow{flex:1}.helmstrip .actions{align-items:center;gap:var(--space-2);display:flex}@media (width<=1150px){.helmstrip{gap:var(--space-3);padding:0 var(--space-3)}.instrument+.instrument{padding-left:var(--space-3)}}@media (width<=1000px){.instrument-secondary{display:none}}.pill{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;border:var(--border-ctl) solid;border-radius:5px;align-items:center;gap:6px;padding:2px 8px;font-size:11px;font-weight:600;display:inline-flex}.pill .dot{border-radius:50%;flex:none;width:7px;height:7px}.pill-ok{background:linear-gradient(var(--ok-soft), var(--ok-soft)) var(--surface);color:var(--ok-ink);border-color:color-mix(in srgb, var(--ok) 55%, transparent)}.pill-ok .dot{background:var(--ok)}.pill-warn{background:linear-gradient(var(--warn-soft), var(--warn-soft)) var(--surface);color:var(--warn-ink);border-color:color-mix(in srgb, var(--warn) 55%, transparent)}.pill-warn .dot{background:var(--warn)}.pill-danger{background:linear-gradient(var(--danger-soft), var(--danger-soft)) var(--surface);color:var(--danger-ink);border-color:color-mix(in srgb, var(--danger) 55%, transparent)}.pill-danger .dot{background:var(--danger)}.pill-idle{background:var(--surface-2);color:var(--ink-2);border-color:color-mix(in srgb, var(--ink-3) 45%, transparent)}.pill-idle .dot{background:var(--ink-3)}@keyframes pulse{50%{opacity:.35}}.pill-ok .dot{animation:2.4s ease-in-out infinite pulse}.stamp{font:600 11px/1 var(--font-mono);text-transform:uppercase;letter-spacing:.05em;white-space:nowrap;border:var(--border-ctl) solid color-mix(in srgb, var(--ink-3) 45%, transparent);background:var(--surface);color:var(--ink-2);border-radius:5px;align-items:center;gap:6px;padding:6px 10px;display:inline-flex}.stamp-ok{color:var(--ok-ink);border-color:color-mix(in srgb, var(--ok) 55%, transparent);background:linear-gradient(var(--ok-soft), var(--ok-soft)) var(--surface)}.stamp-warn{color:var(--warn-ink);border-color:color-mix(in srgb, var(--warn) 55%, transparent);background:linear-gradient(var(--warn-soft), var(--warn-soft)) var(--surface)}.stamp-danger{color:var(--danger-ink);border-color:color-mix(in srgb, var(--danger) 55%, transparent);background:linear-gradient(var(--danger-soft), var(--danger-soft)) var(--surface)}.stamp-tilt{rotate:-1.5deg}.chip-toggle{font:600 11px/1 var(--font-mono);text-transform:uppercase;letter-spacing:.05em;border:var(--border-ctl) solid color-mix(in srgb, var(--ink-3) 45%, transparent);background:var(--surface);color:var(--ink-2);box-shadow:var(--shadow-card);cursor:pointer;white-space:nowrap;border-radius:5px;align-items:center;gap:6px;padding:6px 10px;display:inline-flex}.chip-toggle:before{content:"";border:var(--border-ctl) solid var(--ink-3);border-radius:50%;flex:none;width:7px;height:7px}.chip-toggle:hover{background:var(--surface-2);color:var(--ink)}.chip-toggle:active{translate:0 1px}.chip-toggle[aria-pressed=true]{background:linear-gradient(var(--accent-soft), var(--accent-soft)) var(--surface);color:var(--accent-ink);border-color:color-mix(in srgb, var(--accent) 55%, transparent)}.chip-toggle[aria-pressed=true]:before{background:var(--accent);border:0}.chip-toggle .n{font-weight:400}.content{padding:var(--space-6);gap:var(--space-5);flex-direction:column;display:flex}.page-head{align-items:baseline;gap:var(--space-3);display:flex}.page-head h1{font-family:var(--font-display);font-size:var(--text-2xl);letter-spacing:0;font-weight:700}.page-head .sub{color:var(--ink-2);font-size:var(--text-sm);font-family:var(--font-mono)}.page-head .spacer{flex:1}.tabs{border-bottom:2px solid var(--line);gap:2px;display:flex}.tab{font-family:var(--font-mono);font-size:var(--text-xs);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-2);cursor:pointer;border-radius:var(--radius-ctl) var(--radius-ctl) 0 0;background:0 0;border:0;border-bottom:3px solid #0000;margin-bottom:-2px;padding:9px 14px;font-weight:600}.tab:hover{color:var(--ink);background:var(--surface-2)}.tab[aria-selected=true]{color:var(--accent-ink);background:var(--accent-soft);border-bottom-color:var(--accent)}.tab .count{color:var(--ink-2);background:var(--surface-2);border:1px solid color-mix(in srgb, var(--ink-3) 40%, transparent);font-variant-numeric:tabular-nums;border-radius:5px;margin-left:6px;padding:1px 6px;font-size:11px}.toolbar{gap:var(--space-2);align-items:center;display:flex}.toolbar .hint{font-family:var(--font-mono);font-variant-numeric:tabular-nums}.card{background:var(--surface);border:var(--border-card) solid var(--line);border-radius:var(--radius-card);box-shadow:var(--shadow-card);flex-direction:column;min-width:0;display:flex;overflow:hidden}.card-head{align-items:center;gap:var(--space-2);border-bottom:var(--border-ctl) solid var(--line);padding:12px 16px;display:flex}.card-head h2{font-family:var(--font-display);font-size:var(--text-lg);font-weight:700}.card-head .hint{color:var(--ink-3);font-size:var(--text-xs)}.card-head .spacer{flex:1}.card-body{padding:var(--space-4)}.card-body.flush{padding:0}.stat{padding:14px 16px}.stat .label{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3);font-size:11px}.stat .value{font-family:var(--font-mono);font-size:var(--text-2xl);font-variant-numeric:tabular-nums;font-weight:600;line-height:var(--leading-tight);margin-top:2px}.stat .value small{font-size:var(--text-sm);color:var(--ink-3);font-weight:400}.stat .delta{font-size:var(--text-xs);color:var(--ink-2);margin-top:4px}.stat .delta.up{color:var(--ok-ink)}.stat .delta.down{color:var(--danger-ink)}.stat .delta.up:before{content:"▲ " / ""}.stat .delta.down:before{content:"▼ " / ""}.btn{font:500 var(--text-md)/1 var(--font-ui);border-radius:var(--radius-ctl);border:var(--border-ctl) solid var(--line-strong);background:var(--surface-2);color:var(--ink);cursor:pointer;white-space:nowrap;align-items:center;gap:7px;padding:7px 14px;display:inline-flex}.btn:hover{background:var(--surface-3)}.btn:active{translate:0 1px}.btn-primary{background:var(--accent);color:var(--on-accent);border-color:#0000}.btn-primary:hover{filter:brightness(1.08);background:var(--accent)}.btn-danger{border-color:var(--danger);color:var(--danger-ink);background:0 0}.btn-danger:hover{background:var(--danger-soft)}.btn-danger-solid{background:var(--danger);color:var(--on-danger);border-color:#0000}.btn-danger-solid:hover{filter:brightness(1.08);background:var(--danger)}.btn-ghost{color:var(--ink-2);background:0 0;border-color:#0000}.btn-ghost:hover{background:var(--surface-2);color:var(--ink)}.btn-sm{font-size:var(--text-sm);padding:4px 10px}.btn[disabled]{opacity:.45;cursor:not-allowed}.field{flex-direction:column;gap:6px;display:flex}.field>label{font-size:var(--text-sm);color:var(--ink-2);font-weight:500}.input,select.input{font:400 var(--text-md)/1.4 var(--font-ui);color:var(--ink);background:var(--bg);border:var(--border-ctl) solid var(--line-strong);border-radius:var(--radius-ctl);width:100%;padding:7px 10px}.input::placeholder{color:var(--ink-3)}.input:focus{box-shadow:var(--focus-ring);outline:none}.input-mono{font-family:var(--font-mono);font-size:var(--text-sm)}.input[readonly]{border-color:var(--line);color:var(--ink-2);background:0 0}.field-hint{font-size:var(--text-xs);color:var(--ink-3)}.field-hint.warn{color:var(--warn-ink)}.search{position:relative}.search .input{padding-left:30px}.search svg{color:var(--ink-3);position:absolute;top:50%;left:9px;translate:0 -50%}.table{border-collapse:collapse;width:100%;font-size:var(--text-sm)}.table th{text-align:left;font-family:var(--font-mono);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3);background:var(--surface-2);border-bottom:var(--border-ctl) solid var(--line);white-space:nowrap;padding:8px 12px;font-size:11px;font-weight:600}.table td{border-bottom:1px solid var(--line);vertical-align:middle;padding:9px 12px}.table tbody tr:last-child td{border-bottom:0}.table tbody tr:hover{background:var(--surface-2)}.table .num{font-family:var(--font-mono);font-variant-numeric:tabular-nums}.table .actions{text-align:right;white-space:nowrap}.table .actions .btn{visibility:hidden}.table tr:hover .actions .btn{visibility:visible}.table tbody tr.row-selected,.table tbody tr.row-selected:hover{background:var(--accent-soft)}.row-selected td:first-child{box-shadow:inset 3px 0 0 var(--accent)}.who-cell{align-items:center;gap:10px;min-width:0;display:flex}.avatar{width:28px;height:28px;color:var(--ink-2);background:var(--surface-3);border:var(--border-ctl) solid var(--line-strong);border-radius:50%;flex:none;place-items:center;font-size:11px;font-weight:600;display:grid;overflow:hidden}.avatar img{object-fit:cover;border-radius:50%;width:100%;height:100%;display:block}.who-cell .name{color:var(--ink);font-weight:500}.who-cell .id{font-family:var(--font-mono);color:var(--ink-3);font-size:11px}.kv{background:var(--line);grid-template-columns:1fr 1fr;gap:1px;display:grid}.kv>div{background:var(--surface);padding:10px 16px}.kv .label{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3);font-size:11px;display:block}.kv .val{font-family:var(--font-mono);font-size:var(--text-sm);font-variant-numeric:tabular-nums}.kv-row{border-bottom:1px solid var(--line);justify-content:space-between;align-items:center;gap:var(--space-3);padding:8px 0;display:flex}.kv-row:last-child{border-bottom:0}.kv-row .k{font-size:var(--text-sm);color:var(--ink-2);flex:none}.kv-row .v{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink);text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.console{background:var(--console-bg);color:var(--console-out);font-family:var(--font-mono);font-size:var(--text-sm);padding:var(--space-4);box-shadow:inset 0 2px 6px var(--console-shadow);flex-direction:column;gap:3px;display:flex;overflow-y:auto}.console .line{gap:var(--space-3);grid-template-columns:66px 1fr;display:grid}.console .ts{color:var(--console-ts);font-variant-numeric:tabular-nums}.console .cmd{color:var(--console-cmd)}.console .cmd:before{content:"❯ ";color:var(--console-ts)}.console .err{color:var(--console-err)}.console .sys{color:var(--console-sys)}.chart{position:relative}.chart svg{width:100%;height:auto;display:block}.chart .axis{font-family:var(--font-mono);fill:var(--ink-3);font-variant-numeric:tabular-nums;font-size:10px}.legend-row{gap:var(--space-4);font-size:var(--text-xs);color:var(--ink-2);align-items:center;display:flex}.legend-row .key{align-items:center;gap:6px;display:inline-flex}.legend-row .swatch{background:var(--chart-line);border-radius:2px;width:10px;height:3px}.empty{justify-content:center;align-items:center;gap:var(--space-2);padding:var(--space-10) var(--space-6);text-align:center;color:var(--ink-2);flex-direction:column;display:flex}.empty svg{color:var(--ink-3);margin-bottom:var(--space-2)}.empty h3:not(.stamp){font-family:var(--font-display);font-size:var(--text-lg);color:var(--ink);font-weight:700}.empty p{font-size:var(--text-sm);max-width:42ch}.banner{border:var(--border-ctl) solid var(--line);border-radius:var(--radius-card);font-size:var(--text-sm);align-items:center;gap:10px;padding:10px 14px;display:flex}.banner-warn{background:linear-gradient(var(--warn-soft), var(--warn-soft)) var(--surface);border-color:color-mix(in srgb, var(--warn) 45%, transparent);color:var(--warn-ink)}.banner-info{background:linear-gradient(var(--accent-soft), var(--accent-soft)) var(--surface);border-color:color-mix(in srgb, var(--accent) 45%, transparent);color:var(--accent-ink)}.code-well{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink);background:var(--surface);border:var(--border-ctl) solid var(--line-strong);border-radius:var(--radius-ctl);box-shadow:var(--shadow-card);padding:10px 14px;display:inline-block}.diff-list{font-family:var(--font-mono);font-size:var(--text-sm);background:var(--surface);border:var(--border-ctl) solid var(--line);border-radius:var(--radius-ctl);box-shadow:var(--shadow-card);flex-direction:column;display:flex;overflow:hidden}.diff-list>div{border-bottom:1px solid var(--line);padding:7px 14px}.diff-list>div:last-child{border-bottom:0}.diff-list .add{color:var(--ok-ink);box-shadow:inset 3px 0 0 var(--ok)}.diff-list .chg{color:var(--warn-ink);box-shadow:inset 3px 0 0 var(--warn)}.diff-list .rem{color:var(--danger-ink);box-shadow:inset 3px 0 0 var(--danger)}.meter{background:var(--surface-2);border:var(--border-ctl) solid var(--line-strong);border-radius:5px;height:10px;margin-top:10px;position:relative;overflow:hidden}.meter:after{content:"";pointer-events:none;background:repeating-linear-gradient(to right, transparent 0 calc(10% - 1px), var(--line) calc(10% - 1px) 10%);position:absolute;inset:0}.meter .fill{z-index:1;background:var(--accent);height:100%;position:relative}.grid{gap:var(--space-4);display:grid}.cols-4{grid-template-columns:repeat(4,1fr)}.cols-3{grid-template-columns:repeat(3,1fr)}.cols-2{grid-template-columns:repeat(2,1fr)}.span-2{grid-column:span 2}@media (width<=1100px){.cols-4{grid-template-columns:repeat(2,1fr)}.cols-3,.cols-2{grid-template-columns:1fr}.span-2{grid-column:span 1}}@media (width<=860px){.shell{grid-template-columns:1fr}.rail{border-right:0;border-bottom:var(--border-card) solid var(--line);flex-direction:row;align-items:center;height:auto;position:static;overflow-x:auto}.rail-nav{padding:0 var(--space-2);flex-direction:row}.rail-group,.rail-foot{display:none}.helmstrip{overflow-x:auto}.helmstrip .instrument{flex:none}}#root{min-height:100vh}.btn[aria-pressed=true]{background:var(--accent);color:var(--on-accent);border-color:#0000}.btn[aria-pressed=true]:hover{background:var(--accent);filter:brightness(1.08)}.row-kebab{opacity:0;pointer-events:none}.table .actions .btn.row-kebab{visibility:visible}.table tbody tr:hover .actions .btn.row-kebab,.actions .btn.row-kebab:focus-visible,.actions .btn.row-kebab[aria-expanded=true]{opacity:1;pointer-events:auto}.menu-positioner{z-index:60;outline:none}.menu-popup{background:var(--surface);border:var(--border-ctl) solid var(--line-strong);border-radius:var(--radius-card);min-width:180px;box-shadow:var(--shadow-pop);transform-origin:var(--transform-origin);outline:none;flex-direction:column;gap:1px;padding:6px;transition:opacity .12s,transform .12s;display:flex}.menu-popup[data-starting-style],.menu-popup[data-ending-style]{opacity:0;transform:scale(.96)translateY(-2px)}.menu-group-label{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3);padding:6px 10px 4px;font-size:11px;font-weight:600}.menu-item{font:500 var(--text-sm)/1 var(--font-ui);color:var(--ink);border-radius:var(--radius-ctl);cursor:pointer;white-space:nowrap;-webkit-user-select:none;user-select:none;align-items:center;gap:8px;padding:7px 10px;display:flex}.menu-item[data-highlighted]{background:var(--surface-2);outline:none}.menu-item[data-disabled]{color:var(--ink-3);cursor:not-allowed}.menu-item-danger{color:var(--danger-ink)}.menu-item-danger[data-highlighted]{background:var(--danger-soft)}.tooltip-positioner{z-index:70;outline:none}.tooltip-popup{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:.04em;color:var(--on-accent);background:var(--accent-ink);border-radius:var(--radius-ctl);box-shadow:var(--shadow-pop);padding:5px 9px;font-size:11px;font-weight:600;transition:opacity .1s,transform .1s}.tooltip-popup[data-starting-style],.tooltip-popup[data-ending-style]{opacity:0;transform:scale(.96)}.popover-positioner{z-index:60;outline:none}.popover-popup{background:var(--surface);border:var(--border-card) solid var(--line-strong);border-radius:var(--radius-card);min-width:240px;max-width:320px;box-shadow:var(--shadow-pop);padding:var(--space-3) var(--space-4);outline:none;transition:opacity .12s,transform .12s}.popover-popup[data-starting-style],.popover-popup[data-ending-style]{opacity:0;transform:scale(.97)translateY(-2px)}.popover-title{font-family:var(--font-display);font-size:var(--text-md);margin-bottom:4px;font-weight:700}.popover-description{font-size:var(--text-sm);color:var(--ink-2)}.skel{border-radius:var(--radius-ctl);background:linear-gradient(90deg, var(--surface-2) 25%, var(--surface-3) 37%, var(--surface-2) 63%);background-size:400% 100%;animation:1.6s infinite skel-shimmer;display:inline-block}.skel-text{height:12px}@keyframes skel-shimmer{0%{background-position:100%}to{background-position:0}}@media (prefers-reduced-motion:reduce){.skel{animation:none}}dialog.dialog{background:var(--surface);color:var(--ink);border:var(--border-card) solid var(--line-strong);border-radius:var(--radius-card);width:min(440px,92vw);box-shadow:var(--shadow-pop);margin:auto;padding:0}dialog.dialog::backdrop{background:#140f048c}.dialog-head{border-bottom:var(--border-ctl) solid var(--line);justify-content:space-between;align-items:center;padding:14px 16px;display:flex}.dialog-head h2{font-family:var(--font-display);font-size:var(--text-lg);font-weight:700}.dialog-body{padding:var(--space-4);gap:var(--space-3);flex-direction:column;display:flex}.dialog-foot{justify-content:flex-end;gap:var(--space-2);padding:12px var(--space-4);border-top:var(--border-ctl) solid var(--line);display:flex}.dialog-checkbox{font-size:var(--text-sm);color:var(--ink-2);align-items:center;gap:8px;display:flex}.toast-stack{right:var(--space-5);bottom:var(--space-5);z-index:100;gap:var(--space-2);flex-direction:column;max-width:360px;display:flex;position:fixed}.toast{background:var(--surface-2);border:var(--border-ctl) solid var(--line-strong);color:var(--ink);border-radius:var(--radius-card);font-size:var(--text-sm);box-shadow:var(--shadow-pop);padding:10px 14px}.toast-ok{border-color:color-mix(in srgb, var(--ok) 55%, transparent);color:var(--ok-ink)}.toast-danger{border-color:color-mix(in srgb, var(--danger) 55%, transparent);color:var(--danger-ink)}.uplot-wrap{width:100%;position:relative}.uplot-host{width:100%}.uplot-host .u-legend{display:none}.chart-annotation{font-family:var(--font-mono);color:var(--ink-3);white-space:nowrap;pointer-events:none;font-size:10px;display:none;position:absolute;transform:translate(-50%)}.page-loader{background:var(--bg);place-items:center;min-height:100vh;display:grid}.route-loader{place-content:center;justify-items:center;gap:var(--space-3);min-height:min(62vh,42rem);color:var(--ink-3);font-family:var(--font-mono);font-size:var(--text-xs);display:grid}.page-loader .helm-mark .wheel,.route-loader .helm-mark .wheel{transform-origin:50%;animation:1.1s linear infinite helm-spin}@keyframes helm-spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){.page-loader .helm-mark .wheel,.route-loader .helm-mark .wheel{animation:none}}dialog.dialog-command[open]{width:min(640px,94vw);max-height:min(72vh,560px);margin:10vh auto auto;padding:0;display:flex}dialog.dialog-command .dialog-body{gap:0;min-height:0;padding:0;display:flex}.palette-command{outline:none;flex-direction:column;flex:1;min-height:0;display:flex}.palette-input-row{border-bottom:var(--border-ctl) solid var(--line);color:var(--ink-3);align-items:center;gap:10px;padding:14px 16px;display:flex}[cmdk-input]{font:400 var(--text-lg)/1.3 var(--font-ui);color:var(--ink);background:0 0;border:0;outline:none;flex:1}[cmdk-input]::placeholder{color:var(--ink-3)}[cmdk-list]{padding:var(--space-2);min-height:120px;overflow-y:auto}[cmdk-empty]{padding:var(--space-6) var(--space-4);text-align:center;color:var(--ink-3);font-size:var(--text-sm)}[cmdk-group]{padding-top:6px}[cmdk-group-items]{flex-direction:column;gap:1px;display:flex}[cmdk-group-heading]{font-family:var(--font-mono);text-transform:uppercase;letter-spacing:var(--track-caps);color:var(--ink-3);padding:8px 10px 4px;font-size:11px;font-weight:600}[cmdk-item]{font:500 var(--text-sm)/1.3 var(--font-ui);color:var(--ink);border-radius:var(--radius-ctl);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:10px;padding:8px 10px;display:flex}[cmdk-item] svg{color:var(--ink-3);flex:none}[cmdk-item][data-selected=true]{background:var(--accent-soft);color:var(--accent-ink);box-shadow:inset 3px 0 0 var(--accent)}[cmdk-item][data-selected=true] svg{color:var(--accent-ink)}[cmdk-item][data-disabled=true]{color:var(--ink-3);cursor:not-allowed}[cmdk-item].palette-item-danger{color:var(--danger-ink)}[cmdk-item].palette-item-danger[data-selected=true]{background:var(--danger-soft);box-shadow:inset 3px 0 0 var(--danger)}.palette-row{justify-content:space-between;align-items:center;gap:var(--space-3);flex:1;min-width:0;display:flex}.palette-row>span:first-child{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.palette-hint{font-family:var(--font-mono);color:var(--ink-3);text-overflow:ellipsis;white-space:nowrap;max-width:45%;font-size:11px;overflow:hidden}.palette-kbd{font:600 11px/1 var(--font-mono);text-transform:uppercase;color:var(--ink-2);background:var(--surface-2);border:var(--border-ctl) solid var(--line-strong);border-radius:5px;justify-content:center;align-items:center;min-width:20px;padding:3px 6px;display:inline-flex}.palette-foot{align-items:center;gap:var(--space-4);border-top:var(--border-ctl) solid var(--line);font-size:var(--text-xs);color:var(--ink-3);padding:10px 16px;display:flex}.palette-foot span{align-items:center;gap:6px;display:inline-flex}@media (width<=700px){dialog.dialog-command{width:94vw;margin-top:6vh}}.login-page{place-items:center;min-height:100vh;display:grid;position:relative}.desk{z-index:-1;background:url(/assets/hero-paper-Dw4QRDvw.png) 50%/cover no-repeat;position:fixed;inset:0}@media (prefers-color-scheme:dark){:root:not([data-theme=light]) .desk{opacity:.13}}:root[data-theme=dark] .desk{opacity:.13}.login-wrap{align-items:center;gap:var(--space-6);padding:var(--space-6);flex-direction:column;width:100%;max-width:420px;display:flex}.login-brand{align-items:center;gap:var(--space-3);flex-direction:column;display:flex}.login-brand .word{font-family:var(--font-ui);font-weight:600;font-size:var(--text-3xl);letter-spacing:.02em;color:var(--accent-ink);rotate:-1.5deg}.login-brand .tagline{font-family:var(--font-display);font-style:italic;font-size:var(--text-md);color:var(--ink-2)}@keyframes stamp-press{0%{opacity:0;transform:scale(1.6)rotate(-10deg)}55%{opacity:1;transform:scale(.94)rotate(1.5deg)}to{opacity:1;transform:scale(1)rotate(0)}}.helm-mark{display:block}.helm-mark .wheel{transform-origin:50%;animation:.55s cubic-bezier(.2,.9,.3,1.2) both stamp-press}@media (prefers-reduced-motion:reduce){.helm-mark .wheel{animation:none}}.login-card{width:100%;padding:var(--space-6);gap:var(--space-4);flex-direction:column;display:flex;position:relative;overflow:visible}.login-card:before{content:"";border:1px solid var(--line);border-radius:calc(var(--radius-card) - 4px);pointer-events:none;position:absolute;inset:6px}.login-card h1{font-family:var(--font-display);font-size:var(--text-xl);font-weight:700}.login-card .server{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--ink-2);margin-top:2px}.login-card .form-error{font-size:var(--text-sm);color:var(--danger-ink);background:linear-gradient(var(--danger-soft), var(--danger-soft)) var(--surface);border:var(--border-ctl) solid color-mix(in srgb, var(--danger) 45%, transparent);border-radius:var(--radius-ctl);padding:8px 10px}.login-foot{font-size:var(--text-xs);color:var(--ink-2);gap:var(--space-3);display:flex}.login-foot a{color:var(--ink-2);text-decoration:underline}
diff --git a/backend/internal/webdist/dist/assets/index-BpCavHBc.js b/backend/internal/webdist/dist/assets/index-BpCavHBc.js
new file mode 100644
index 0000000..d496562
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/index-BpCavHBc.js
@@ -0,0 +1,10 @@
+const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/Dashboard-Cmb9dKW2.js","assets/icons-CpYMTu_k.js","assets/Banner-DSN1nEJn.js","assets/Card-D55CMzdw.js","assets/EventMessage-UG0hgRVA.js","assets/Dashboard-BycK1nhV.css","assets/Players-CVTzm-84.js","assets/useMutation-S28PAV4D.js","assets/DropdownMenu-fCf3CXmF.js","assets/EmptyState-DTSMkv56.js","assets/Tabs-DecjeYAq.js","assets/guildDisplay-LZYrk7hc.js","assets/PalIcon-BoDQgR3K.js","assets/PalStars-CiCl8RwT.js","assets/PalStars-osSMQvdm.css","assets/PalDetails-Dl-UCtTN.js","assets/PalDetails-Bl23SosS.css","assets/Players-5fYfLSwo.css","assets/Activity-DUaeqEfU.js","assets/Activity-CN5lRrug.css","assets/Pals-CQBg4Vgc.js","assets/palExplorer-IChZ_UBL.js","assets/Pals-D_KCRg-r.css","assets/Guilds-Iqca6q84.js","assets/Guilds-VTJeI58t.css","assets/Paldeck-5QAn5NW_.js","assets/Paldeck-gNJw7ewz.css","assets/Console-zetfhyb9.js","assets/Console-B-5ZyxL5.css","assets/Map-BIP07Cn0.js","assets/CodeWell-Mu33yg_R.js","assets/Map-BPJLiHEM.css","assets/Backups-BhZCFkO5.js","assets/Backups-hnJGe2yy.css","assets/Config-CLoXdISl.js","assets/Config-CXg6qAk9.css","assets/Settings-urvtAKwL.js","assets/Settings-DDAtAokj.css","assets/Events-DSAko0ZN.js","assets/Events-Y3iu26GS.css","assets/Diagnostics-CTBJNOCA.js","assets/Diagnostics-CdVImtbq.css"])))=>i.map(i=>d[i]);
+import{$ as e,A as t,C as n,E as r,G as i,H as a,K as o,M as s,N as c,Q as l,S as u,T as d,U as f,Y as p,_t as m,at as h,c as g,ct as _,et as v,f as y,ft as b,gt as x,h as S,ht as C,i as w,it as T,j as E,l as D,lt as O,mt as k,n as A,nt as j,ot as M,p as ee,pt as N,q as P,rt as te,s as ne,st as re,t as ie,tt as F,u as I,w as ae,x as oe}from"./icons-CpYMTu_k.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var se=x((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,S||(S=!0,O());else{var t=n(l);t!==null&&j(x,t.startTime-e)}}var S=!1,C=-1,w=5,T=-1;function E(){return g?!0:!(e.unstable_now()-Tt&&E());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&j(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}}}finally{i?O():S=!1}}}var O;if(typeof y==`function`)O=function(){y(D)};else if(typeof MessageChannel<`u`){var k=new MessageChannel,A=k.port2;k.port1.onmessage=D,O=function(){A.postMessage(null)}}else O=function(){_(D,0)};function j(t,n){C=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(C),C=-1):h=!0,j(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,S||(S=!0,O()))),r},e.unstable_shouldYield=E,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),ce=x(((e,t)=>{t.exports=se()})),le=x((e=>{var t=C();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=le()})),de=x((e=>{var t=ce(),n=C(),r=ue();function i(e){var t=`https://react.dev/errors/`+e;if(1re||(e.current=ne[re],ne[re]=null,re--)}function I(e,t){re++,ne[re]=e.current,e.current=t}var ae=ie(null),oe=ie(null),se=ie(null),le=ie(null);function de(e,t){switch(I(se,t),I(oe,e),I(ae,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}F(ae),I(ae,e)}function fe(){F(ae),F(oe),F(se)}function pe(e){e.memoizedState!==null&&I(le,e);var t=ae.current,n=Hd(t,e.type);t!==n&&(I(oe,e),I(ae,n))}function me(e){oe.current===e&&(F(ae),F(oe)),le.current===e&&(F(le),Qf._currentValue=te)}var he,ge;function _e(e){if(he===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);he=t&&t[1]||``,ge=-1)`:-1i||c[r]!==l[i]){var u=`
+`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{ve=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?_e(n):``}function ye(e,t){switch(e.tag){case 26:case 27:case 5:return _e(e.type);case 16:return _e(`Lazy`);case 13:return e.child!==t&&t!==null?_e(`Suspense Fallback`):_e(`Suspense`);case 19:return _e(`SuspenseList`);case 0:case 15:return L(e.type,!1);case 11:return L(e.type.render,!1);case 1:return L(e.type,!0);case 31:return _e(`Activity`);default:return``}}function be(e){try{var t=``,n=null;do t+=ye(e,n),n=e,e=e.return;while(e);return t}catch(e){return`
+Error generating stack: `+e.message+`
+`+e.stack}}var xe=Object.prototype.hasOwnProperty,Se=t.unstable_scheduleCallback,Ce=t.unstable_cancelCallback,we=t.unstable_shouldYield,Te=t.unstable_requestPaint,Ee=t.unstable_now,R=t.unstable_getCurrentPriorityLevel,De=t.unstable_ImmediatePriority,Oe=t.unstable_UserBlockingPriority,ke=t.unstable_NormalPriority,Ae=t.unstable_LowPriority,je=t.unstable_IdlePriority,Me=t.log,Ne=t.unstable_setDisableYieldValue,Pe=null,Fe=null;function Ie(e){if(typeof Me==`function`&&Ne(e),Fe&&typeof Fe.setStrictMode==`function`)try{Fe.setStrictMode(Pe,e)}catch{}}var Le=Math.clz32?Math.clz32:Be,Re=Math.log,ze=Math.LN2;function Be(e){return e>>>=0,e===0?32:31-(Re(e)/ze|0)|0}var Ve=256,He=262144,Ue=4194304;function We(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function Ge(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=We(n))):i=We(o):i=We(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=We(n))):i=We(o)):i=We(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function Ke(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function qe(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+250;case 16:case 32:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return t+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Je(){var e=Ue;return Ue<<=1,!(Ue&62914560)&&(Ue=4194304),e}function Ye(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function Xe(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function Ze(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),un=!1;if(ln)try{var dn={};Object.defineProperty(dn,"passive",{get:function(){un=!0}}),window.addEventListener(`test`,dn,dn),window.removeEventListener(`test`,dn,dn)}catch{un=!1}var fn=null,pn=null,mn=null;function hn(){if(mn)return mn;var e,t=pn,n=t.length,r,i=`value`in fn?fn.value:fn.textContent,a=i.length;for(e=0;e=qn),Xn=` `,Zn=!1;function Qn(e,t){switch(e){case`keyup`:return Gn.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function $n(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var er=!1;function tr(e,t){switch(e){case`compositionend`:return $n(t);case`keypress`:return t.which===32?(Zn=!0,Xn):null;case`textInput`:return e=t.data,e===Xn&&Zn?null:e;default:return null}}function nr(e,t){if(er)return e===`compositionend`||!Kn&&Qn(e,t)?(e=hn(),mn=pn=fn=null,er=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=z(n)}}function Tr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Tr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Er(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=It(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=It(e.document)}return t}function Dr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Or=ln&&`documentMode`in document&&11>=document.documentMode,kr=null,Ar=null,jr=null,Mr=!1;function Nr(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Mr||kr==null||kr!==It(r)||(r=kr,`selectionStart`in r&&Dr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),jr&&Cr(jr,r)||(jr=r,r=Td(Ar,`onSelect`),0>=o,i-=o,V=1<<32-Le(t)+i|n<m?(h=d,d=null):h=d.sibling;var g=p(i,d,s[m],c);if(g===null){d===null&&(d=h);break}e&&d&&g.alternate===null&&t(i,d),a=o(g,a,m),u===null?l=g:u.sibling=g,u=g,d=h}if(m===s.length)return n(i,d),U&&Ti(i,m),l;if(d===null){for(;mh?(g=m,m=null):g=m.sibling;var y=p(a,m,v.value,l);if(y===null){m===null&&(m=g);break}e&&m&&y.alternate===null&&t(a,m),s=o(y,s,h),d===null?u=y:d.sibling=y,d=y,m=g}if(v.done)return n(a,m),U&&Ti(a,h),u;if(m===null){for(;!v.done;h++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,h),d===null?u=v:d.sibling=v,d=v);return U&&Ti(a,h),u}for(m=r(m);!v.done;h++,v=c.next())v=_(m,a,h,v.value,l),v!==null&&(e&&v.alternate!==null&&m.delete(v.key===null?h:v.key),s=o(v,s,h),d===null?u=v:d.sibling=v,d=v);return e&&m.forEach(function(e){return t(a,e)}),U&&Ti(a,h),u}function x(e,r,o,c){if(typeof o==`object`&&o&&o.type===g&&o.key===null&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case m:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===g){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===E&&wa(l)===r.type){n(e,r.sibling),c=a(r,o.props),Aa(c,o),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}o.type===g?(c=di(o.props.children,e.mode,c,o.key),c.return=e,e=c):(c=ui(o.type,o.key,o.props,null,e.mode,c),Aa(c,o),c.return=e,e=c)}return s(e);case h:a:{for(l=o.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}else{n(e,r);break}t(e,r),r=r.sibling}c=mi(o,e.mode,c),c.return=e,e=c}return s(e);case E:return o=wa(o),x(e,r,o,c)}if(ee(o))return v(e,r,o,c);if(A(o)){if(l=A(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),y(e,r,o,c)}if(typeof o.then==`function`)return x(e,r,W(o),c);if(o.$$typeof===b)return x(e,r,Qi(e,o),c);ja(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=fi(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{ka=0;var i=x(e,t,n,r);return Oa=null,i}catch(t){if(t===va||t===ba)throw t;var a=oi(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Na=Ma(!0),Pa=Ma(!1),Fa=!1;function Ia(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function La(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Ra(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function za(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,Y&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=ri(e),ni(e,null,n),t}return $r(e,r,t,n),ri(e)}function Ba(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,$e(e,n)}}function Va(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var G=!1;function Ha(){if(G){var e=la;if(e!==null)throw e}}function Ua(e,t,n,r){G=!1;var i=e.updateQueue;Fa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var p=s.lane&-536870913,m=p!==s.lane;if(m?(Q&p)===p:(r&p)===p){p!==0&&p===ca&&(G=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var h=e,g=s;p=t;var _=n;switch(g.tag){case 1:if(h=g.payload,typeof h==`function`){d=h.call(_,d,p);break a}d=h;break a;case 3:h.flags=h.flags&-65537|128;case 0:if(h=g.payload,p=typeof h==`function`?h.call(_,d,p):h,p==null)break a;d=f({},d,p);break a;case 2:Fa=!0}}p=s.callback,p!==null&&(e.flags|=64,m&&(e.flags|=8192),m=i.callbacks,m===null?i.callbacks=[p]:m.push(p))}else m={lane:p,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=m,c=d):u=u.next=m,o|=p;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;m=s,s=m.next,m.next=null,i.lastBaseUpdate=m,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Ul|=o,e.lanes=o,e.memoizedState=d}}function Wa(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function Ga(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=N.T,s={};N.T=s,As(e,!1,t,n);try{var c=i(),l=N.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?ks(e,t,fa(c,r),du(e)):ks(e,t,r,du(e))}catch(n){ks(e,t,{then:function(){},status:`rejected`,reason:n},du())}finally{P.p=a,o!==null&&s.types!==null&&(o.types=s.types),N.T=o}}function ys(){}function bs(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=xs(e).queue;vs(e,a,t,te,n===null?ys:function(){return Ss(e),n(r)})}function xs(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:te,baseState:te,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:jo,lastRenderedState:te},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:jo,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function Ss(e){var t=xs(e);t.next===null&&(t=e.alternate.memoizedState),ks(e,t.next.queue,{},du())}function Cs(){return Zi(Qf)}function ws(){return Eo().memoizedState}function Ts(){return Eo().memoizedState}function Es(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=du();e=Ra(n);var r=za(t,e,n);r!==null&&(pu(r,t,n),Ba(r,t,n)),t={cache:ia()},e.payload=t;return}t=t.return}}function Ds(e,t,n){var r=du();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},js(e)?Ms(t,n):(n=ei(e,t,n,r),n!==null&&(pu(n,e,r),Ns(n,t,r)))}function Os(e,t,n){ks(e,t,n,du())}function ks(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(js(e))Ms(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Sr(s,o))return $r(e,t,i,0),X===null&&Qr(),!1}catch{}if(n=ei(e,t,i,r),n!==null)return pu(n,e,r),Ns(n,t,r),!0}return!1}function As(e,t,n,r){if(r={lane:2,revertLane:ud(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},js(e)){if(t)throw Error(i(479))}else t=ei(e,n,r,2),t!==null&&pu(t,e,2)}function js(e){var t=e.alternate;return e===K||t!==null&&t===K}function Ms(e,t){lo=co=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Ns(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,$e(e,n)}}var Ps={readContext:Zi,use:ko,useCallback:go,useContext:go,useEffect:go,useImperativeHandle:go,useLayoutEffect:go,useInsertionEffect:go,useMemo:go,useReducer:go,useRef:go,useState:go,useDebugValue:go,useDeferredValue:go,useTransition:go,useSyncExternalStore:go,useId:go,useHostTransitionStatus:go,useFormState:go,useActionState:go,useOptimistic:go,useMemoCache:go,useCacheRefresh:go};Ps.useEffectEvent=go;var Fs={readContext:Zi,use:ko,useCallback:function(e,t){return To().memoizedState=[e,t===void 0?null:t],e},useContext:Zi,useEffect:as,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),rs(4194308,4,ds.bind(null,t,e),n)},useLayoutEffect:function(e,t){return rs(4194308,4,e,t)},useInsertionEffect:function(e,t){rs(4,2,e,t)},useMemo:function(e,t){var n=To();t=t===void 0?null:t;var r=e();if(uo){Ie(!0);try{e()}finally{Ie(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=To();if(n!==void 0){var i=n(t);if(uo){Ie(!0);try{n(t)}finally{Ie(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Ds.bind(null,K,e),[r.memoizedState,e]},useRef:function(e){var t=To();return e={current:e},t.memoizedState=e},useState:function(e){e=Vo(e);var t=e.queue,n=Os.bind(null,K,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:ps,useDeferredValue:function(e,t){return gs(To(),e,t)},useTransition:function(){var e=Vo(!1);return e=vs.bind(null,K,e.queue,!0,!1),To().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=K,a=To();if(U){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),X===null)throw Error(i(349));Q&127||Io(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,as(Ro.bind(null,r,o,e),[e]),r.flags|=2048,ts(9,{destroy:void 0},Lo.bind(null,r,o,n,t),null),n},useId:function(){var e=To(),t=X.identifierPrefix;if(U){var n=wi,r=V;n=(r&~(1<<32-Le(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=fo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[ot]=t,o[st]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(Pd(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&kc(t)}}return Pc(t),Ac(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&kc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=se.current,Li(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=Ai,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[ot]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||jd(e.nodeValue,n)),e||Pi(t,!0)}else e=Bd(e).createTextNode(r),e[ot]=t,t.stateNode=e}return Pc(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Li(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[ot]=t}else Ri(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Pc(t),e=!1}else n=zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(ro(t),t):(ro(t),null);if(t.flags&128)throw Error(i(558))}return Pc(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=Li(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[ot]=t}else Ri(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;Pc(t),a=!1}else a=zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(ro(t),t):(ro(t),null)}return ro(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Mc(t,t.updateQueue),Pc(t),null);case 4:return fe(),e===null&&xd(t.stateNode.containerInfo),Pc(t),null;case 10:return Gi(t.type),Pc(t),null;case 19:if(F(io),r=t.memoizedState,r===null)return Pc(t),null;if(a=!!(t.flags&128),o=r.rendering,o===null)if(a)Nc(r,!1);else{if(Hl!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=ao(e),o!==null){for(t.flags|=128,Nc(r,!1),e=o.updateQueue,t.updateQueue=e,Mc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)li(n,e),n=n.sibling;return I(io,io.current&1|2),U&&Ti(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Ee()>$l&&(t.flags|=128,a=!0,Nc(r,!1),t.lanes=4194304)}else{if(!a)if(e=ao(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,Mc(t,e),Nc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!o.alternate&&!U)return Pc(t),null}else 2*Ee()-r.renderingStartTime>$l&&n!==536870912&&(t.flags|=128,a=!0,Nc(r,!1),t.lanes=4194304);r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}return r.tail===null?(Pc(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Ee(),e.sibling=null,n=io.current,I(io,a?n&1|2:n&1),U&&Ti(t,r.treeForkCount),e);case 22:case 23:return ro(t),Xa(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(Pc(t),t.subtreeFlags&6&&(t.flags|=8192)):Pc(t),n=t.updateQueue,n!==null&&Mc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&F(ma),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Gi(ra),Pc(t),null;case 25:return null;case 30:return null}throw Error(i(156,t.tag))}function Ic(e,t){switch(Oi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Gi(ra),fe(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return me(t),null;case 31:if(t.memoizedState!==null){if(ro(t),t.alternate===null)throw Error(i(340));Ri()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(ro(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));Ri()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return F(io),null;case 4:return fe(),null;case 10:return Gi(t.type),null;case 22:case 23:return ro(t),Xa(),e!==null&&F(ma),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Gi(ra),null;case 25:return null;default:return null}}function Lc(e,t){switch(Oi(t),t.tag){case 3:Gi(ra),fe();break;case 26:case 27:case 5:me(t);break;case 4:fe();break;case 31:t.memoizedState!==null&&ro(t);break;case 13:ro(t);break;case 19:F(io);break;case 10:Gi(t.type);break;case 22:case 23:ro(t),Xa(),e!==null&&F(ma);break;case 24:Gi(ra)}}function Rc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Uu(t,t.return,e)}}function zc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Uu(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Uu(t,t.return,e)}}function Bc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{Ga(t,n)}catch(t){Uu(e,e.return,t)}}}function Vc(e,t,n){n.props=Hs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Uu(e,t,n)}}function Hc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Uu(e,t,n)}}function Uc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Uu(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Uu(e,t,n)}else n.current=null}function Wc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Uu(e,e.return,t)}}function Gc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[st]=t}catch(t){Uu(e,e.return,t)}}function Kc(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function qc(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||Kc(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Jc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=$t));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(Jc(e,t,n),e=e.sibling;e!==null;)Jc(e,t,n),e=e.sibling}function Yc(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(Yc(e,t,n),e=e.sibling;e!==null;)Yc(e,t,n),e=e.sibling}function Xc(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[ot]=e,t[st]=n}catch(t){Uu(e,e.return,t)}}var Zc=!1,Qc=!1,$c=!1,el=typeof WeakSet==`function`?WeakSet:Set,tl=null;function nl(e,t){if(e=e.containerInfo,Rd=sp,e=Er(e),Dr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var a=r.anchorOffset,o=r.focusNode;r=r.focusOffset;try{n.nodeType,o.nodeType}catch{n=null;break a}var s=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||a!==0&&f.nodeType!==3||(c=s+a),f!==o||r!==0&&f.nodeType!==3||(l=s+r),f.nodeType===3&&(s+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===a&&(c=s),p===o&&++d===r&&(l=s),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,tl=t;tl!==null;)if(t=tl,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,tl=e;else for(;tl!==null;){switch(t=tl,o=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(o,r,n),o[ot]=e,yt(o),r=o;break a;case`link`:var s=Vf(`link`,`href`,a).get(r+(n.href||``));if(s){for(var c=0;cg&&(o=g,g=h,h=o);var _=wr(s,h),v=wr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,N.T=null,n=su,su=null;var o=ru,s=au;if(nu=0,iu=ru=null,au=0,Y&6)throw Error(i(331));var c=Y;if(Y|=4,jl(o.current),Cl(o,o.current,s,n),Y=c,rd(0,!1),Fe&&typeof Fe.onPostCommitFiberRoot==`function`)try{Fe.onPostCommitFiberRoot(Pe,o)}catch{}return!0}finally{P.p=a,N.T=r,zu(e,t)}}function Hu(e,t,n){t=gi(n,t),t=Js(e.stateNode,t,2),e=za(e,t,2),e!==null&&(Xe(e,2),nd(e))}function Uu(e,t,n){if(e.tag===3)Hu(e,e,n);else for(;t!==null;){if(t.tag===3){Hu(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(tu===null||!tu.has(r))){e=gi(n,e),n=Ys(2),r=za(t,n,2),r!==null&&(Xs(n,r,t,e),Xe(r,2),nd(r));break}}t=t.return}}function Wu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Fl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Bl=!0,i.add(n),e=Gu.bind(null,e,t,n),t.then(e,e))}function Gu(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,X===e&&(Q&n)===n&&(Hl===4||Hl===3&&(Q&62914560)===Q&&300>Ee()-Zl?!(Y&2)&&bu(e,0):Gl|=n,ql===Q&&(ql=0)),nd(e)}function Ku(e,t){t===0&&(t=Je()),e=ti(e,t),e!==null&&(Xe(e,t),nd(e))}function qu(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Ku(e,n)}function Ju(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),Ku(e,n)}function Yu(e,t){return Se(e,t)}var Xu=null,Zu=null,Qu=!1,$u=!1,ed=!1,td=0;function nd(e){e!==Zu&&e.next===null&&(Zu===null?Xu=Zu=e:Zu=Zu.next=e),$u=!0,Qu||(Qu=!0,ld())}function rd(e,t){if(!ed&&$u){ed=!0;do for(var n=!1,r=Xu;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-Le(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,cd(r,a))}else a=Q,a=Ge(r,r===X?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||Ke(r,a)||(n=!0,cd(r,a));r=r.next}while(n);ed=!1}}function id(){ad()}function ad(){$u=Qu=!1;var e=0;td!==0&&Gd()&&(e=td);for(var t=Ee(),n=null,r=Xu;r!==null;){var i=r.next,a=od(r,t);a===0?(r.next=null,n===null?Xu=i:n.next=i,i===null&&(Zu=n)):(n=r,(e!==0||a&3)&&($u=!0)),r=i}nu!==0&&nu!==5||rd(e,!1),td!==0&&(td=0)}function od(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=Rt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),yt(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+Rt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+Rt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+Rt(n.imageSizes)+`"]`)):i+=`[href="`+Rt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=f({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),yt(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+Rt(r)+`"][href="`+Rt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=f({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),yt(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=vt(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=f({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);yt(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=vt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=f({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),yt(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=vt(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=f({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),yt(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var a=(a=se.current)?gf(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=vt(a).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var o=vt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(jf(e)))&&!o._p&&(s.instance=o,s.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),o||Nf(a,e,n,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=vt(a).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Af(e){return`href="`+Rt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return f({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),yt(t),e.head.appendChild(t))}function Pf(e){return`[src="`+Rt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+Rt(n.href)+`"]`);if(r)return t.instance=r,yt(r),r;var a=f({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),yt(r),Pd(r,`style`,a),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Af(n.href);var o=e.querySelector(jf(a));if(o)return t.state.loading|=4,t.instance=o,yt(o),o;r=Mf(n),(a=mf.get(a))&&Rf(r,a),o=(e.ownerDocument||e).createElement(`link`),yt(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),Pd(o,`link`,r),t.state.loading|=4,Lf(o,n.precedence,e),t.instance=o;case`script`:return o=Pf(n.src),(a=e.querySelector(Ff(o)))?(t.instance=a,yt(a),a):(r=n,(a=mf.get(o))&&(r=f({},n),zf(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),yt(a),Pd(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,yt(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),yt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=de()})),pe=/^(?:[a-z][a-z0-9+.-]*:|[\\/]{2})/i,me=/^[\\/]{2}/;function he(e,t){return t+e.replace(/\\/g,`/`)}var ge=`popstate`;function _e(e){return typeof e==`object`&&!!e&&`pathname`in e&&`search`in e&&`hash`in e&&`state`in e&&`key`in e}function ve(e={}){function t(e,t){let n=t.state?.masked,{pathname:r,search:i,hash:a}=n||e.location;return Se(``,{pathname:r,search:i,hash:a},t.state&&t.state.usr||null,t.state&&t.state.key||`default`,n?{pathname:e.location.pathname,search:e.location.search,hash:e.location.hash}:void 0)}function n(e,t){return typeof t==`string`?t:Ce(t)}return Te(t,n,null,e)}function L(e,t){if(e===!1||e==null)throw Error(t)}function ye(e,t){if(!e){typeof console<`u`&&console.warn(t);try{throw Error(t)}catch{}}}function be(){return Math.random().toString(36).substring(2,10)}function xe(e,t){return{usr:e.state,key:e.key,idx:t,masked:e.mask?{pathname:e.pathname,search:e.search,hash:e.hash}:void 0}}function Se(e,t,n=null,r,i){return{pathname:typeof e==`string`?e:e.pathname,search:``,hash:``,...typeof t==`string`?we(t):t,state:n,key:t&&t.key||r||be(),mask:i}}function Ce({pathname:e=`/`,search:t=``,hash:n=``}){return t&&t!==`?`&&(e+=t.charAt(0)===`?`?t:`?`+t),n&&n!==`#`&&(e+=n.charAt(0)===`#`?n:`#`+n),e}function we(e){let t={};if(e){let n=e.indexOf(`#`);n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf(`?`);r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function Te(e,t,n,r={}){let{window:i=document.defaultView,v5Compat:a=!1}=r,o=i.history,s=`POP`,c=null,l=u();l??(l=0,o.replaceState({...o.state,idx:l},``));function u(){return(o.state||{idx:null}).idx}function d(){s=`POP`;let e=u(),t=e==null?null:e-l;l=e,c&&c({action:s,location:h.location,delta:t})}function f(e,t){s=`PUSH`;let r=_e(e)?e:Se(h.location,e,t);n&&n(r,e),l=u()+1;let d=xe(r,l),f=h.createHref(r.mask||r);try{o.pushState(d,``,f)}catch(e){if(e instanceof DOMException&&e.name===`DataCloneError`)throw e;i.location.assign(f)}a&&c&&c({action:s,location:h.location,delta:1})}function p(e,t){s=`REPLACE`;let r=_e(e)?e:Se(h.location,e,t);n&&n(r,e),l=u();let i=xe(r,l),d=h.createHref(r.mask||r);o.replaceState(i,``,d),a&&c&&c({action:s,location:h.location,delta:0})}function m(e){return Ee(i,e)}let h={get action(){return s},get location(){return e(i,o)},listen(e){if(c)throw Error(`A history only accepts one active listener`);return i.addEventListener(ge,d),c=e,()=>{i.removeEventListener(ge,d),c=null}},createHref(e){return t(i,e)},createURL:m,encodeLocation(e){let t=m(e);return{pathname:t.pathname,search:t.search,hash:t.hash}},push:f,replace:p,go(e){return o.go(e)}};return h}function Ee(e,t,n=!1){let r=`http://localhost`;e&&(r=e.location.origin===`null`?e.location.href:e.location.origin),L(r,`No window.location.(origin|href) available to create URL`);let i=typeof t==`string`?t:Ce(t);return i=i.replace(/ $/,`%20`),!n&&me.test(i)&&(i=r+i),new URL(i,r)}var R=m(C(),1);function De(e,t,n=`/`){return Oe(e,t,n,!1)}function Oe(e,t,n,r,i){let a=Ye((typeof t==`string`?we(t):t).pathname||`/`,n);if(a==null)return null;let o=i??ke(e),s=null,c=Je(a);for(let e=0;s==null&&e{let c={relativePath:s===void 0?e.path||``:s,caseSensitive:e.caseSensitive===!0,childrenIndex:a,route:e};if(c.relativePath.startsWith(`/`)){if(!c.relativePath.startsWith(r)&&o)return;L(c.relativePath.startsWith(r),`Absolute route path "${c.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),c.relativePath=c.relativePath.slice(r.length)}let l=rt([r,c.relativePath]),u=n.concat(c);e.children&&e.children.length>0&&(L(e.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${l}".`),Ae(e.children,t,u,l,o)),!(e.path==null&&!e.index)&&t.push({path:l,score:He(l,e.index),routesMeta:u.map((e,t)=>{let[n,r]=qe(e.relativePath,e.caseSensitive,t===u.length-1);return{...e,matcher:n,compiledParams:r}})})};return e.forEach((e,t)=>{if(e.path===``||!e.path?.includes(`?`))a(e,t);else for(let n of je(e.path))a(e,t,!0,n)}),t}function je(e){let t=e.split(`/`);if(t.length===0)return[];let[n,...r]=t,i=n.endsWith(`?`),a=n.replace(/\?$/,``);if(r.length===0)return i?[a,``]:[a];let o=je(r.join(`/`)),s=[];return s.push(...o.map(e=>e===``?a:[a,e].join(`/`))),i&&s.push(...o),s.map(t=>e.startsWith(`/`)&&t===``?`/`:t)}function Me(e){e.sort((e,t)=>e.score===t.score?Ue(e.routesMeta.map(e=>e.childrenIndex),t.routesMeta.map(e=>e.childrenIndex)):t.score-e.score)}var Ne=/^:[\w-]+$/,Pe=/^:[\w-]+/,Fe=3.5,Ie=3,Le=2,Re=1,ze=10,Be=-2,Ve=e=>e===`*`;function He(e,t){let n=e.split(`/`),r=n.length;return n.some(Ve)&&(r+=Be),t&&(r+=Le),n.filter(e=>!Ve(e)).reduce((e,t)=>e+(Ne.test(t)?Ie:Pe.test(t)?Fe:t===``?Re:ze),r)}function Ue(e,t){return e.length===t.length&&e.slice(0,-1).every((e,n)=>e===t[n])?e[e.length-1]-t[t.length-1]:0}function We(e,t,n=!1){let{routesMeta:r}=e,i={},a=`/`,o=[];for(let e=0;e{if(t===`*`){let e=s[r]||``;o=a.slice(0,a.length-e.length).replace(/(.)\/+$/,`$1`)}let i=s[r];return e[t]=n&&!i?void 0:(i||``).replace(/%2F/g,`/`),e},{}),pathname:a,pathnameBase:o,pattern:e}}function qe(e,t=!1,n=!0){ye(e===`*`||!e.endsWith(`*`)||e.endsWith(`/*`),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,`/*`)}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,`/*`)}".`);let r=[],i=`^`+e.replace(/\/*\*?$/,``).replace(/^\/*/,`/`).replace(/[\\.*+^${}|()[\]]/g,`\\$&`).replace(/\/:([\w-]+)(\?)?/g,(e,t,n,i,a)=>{if(r.push({paramName:t,isOptional:n!=null}),n){let t=a.charAt(i+e.length);return t&&t!==`/`?`/([^\\/]*)`:`(?:/([^\\/]*))?`}return`/([^\\/]+)`}).replace(/\/([\w-]+)\?(?=\/|$|\()/g,`(?:/$1)?`);return e.endsWith(`*`)?(r.push({paramName:`*`}),i+=e===`*`||e===`/*`?`(.*)$`:`(?:\\/(.+)|\\/*)$`):n?i+=`\\/*$`:e!==``&&e!==`/`&&(i+=`(?:(?=\\/|$))`),[new RegExp(i,t?void 0:`i`),r]}function Je(e){try{return e.split(`/`).map(e=>decodeURIComponent(e).replace(/\//g,`%2F`)).join(`/`)}catch(t){return ye(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Ye(e,t){if(t===`/`)return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith(`/`)?t.length-1:t.length,r=e.charAt(n);return r&&r!==`/`?null:e.slice(n)||`/`}function Xe(e,t=`/`){let{pathname:n,search:r=``,hash:i=``}=typeof e==`string`?we(e):e,a;return n?(n=nt(n),a=n.startsWith(`/`)?Ze(n.substring(1),`/`):Ze(n,t)):a=t,{pathname:a,search:ot(r),hash:st(i)}}function Ze(e,t){let n=it(t).split(`/`);return e.split(`/`).forEach(e=>{e===`..`?n.length>1&&n.pop():e!==`.`&&n.push(e)}),n.length>1?n.join(`/`):`/`}function Qe(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function $e(e){return e.filter((e,t)=>t===0||e.route.path&&e.route.path.length>0)}function et(e){let t=$e(e);return t.map((e,n)=>n===t.length-1?e.pathname:e.pathnameBase)}function tt(e,t,n,r=!1){let i;typeof e==`string`?i=we(e):(i={...e},L(!i.pathname||!i.pathname.includes(`?`),Qe(`?`,`pathname`,`search`,i)),L(!i.pathname||!i.pathname.includes(`#`),Qe(`#`,`pathname`,`hash`,i)),L(!i.search||!i.search.includes(`#`),Qe(`#`,`search`,`hash`,i)));let a=e===``||i.pathname===``,o=a?`/`:i.pathname,s;if(o==null)s=n;else{let e=t.length-1;if(!r&&o.startsWith(`..`)){let t=o.split(`/`);for(;t[0]===`..`;)t.shift(),--e;i.pathname=t.join(`/`)}s=e>=0?t[e]:`/`}let c=Xe(i,s),l=o&&o!==`/`&&o.endsWith(`/`),u=(a||o===`.`)&&n.endsWith(`/`);return!c.pathname.endsWith(`/`)&&(l||u)&&(c.pathname+=`/`),c}var nt=e=>e.replace(/[\\/]{2,}/g,`/`),rt=e=>nt(e.join(`/`)),it=e=>e.replace(/\/+$/,``),at=e=>it(e).replace(/^\/*/,`/`),ot=e=>!e||e===`?`?``:e.startsWith(`?`)?e:`?`+e,st=e=>!e||e===`#`?``:e.startsWith(`#`)?e:`#`+e,ct=class{status;statusText;data;error;internal;constructor(e,t,n,r=!1){this.status=e,this.statusText=t||``,this.internal=r,n instanceof Error?(this.data=n.toString(),this.error=n):this.data=n}};function lt(e){return e!=null&&typeof e.status==`number`&&typeof e.statusText==`string`&&typeof e.internal==`boolean`&&`data`in e}function ut(e){return rt(e.map(e=>e.route.path).filter(Boolean))||`/`}var dt=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0;function ft(e,t){let n=e;if(typeof n!=`string`||!pe.test(n))return{absoluteURL:void 0,isExternal:!1,to:n};let r=n,i=!1;if(dt)try{let e=new URL(window.location.href),r=me.test(n)?new URL(he(n,e.protocol)):new URL(n),a=Ye(r.pathname,t);r.origin===e.origin&&a!=null?n=a+r.search+r.hash:i=!0}catch{ye(!1,` contains an invalid URL which will probably break when clicked - please update to a valid URL path.`)}return{absoluteURL:r,isExternal:i,to:n}}var pt=[`POST`,`PUT`,`PATCH`,`DELETE`];new Set(pt);var mt=[`GET`,...pt];new Set(mt);var ht=[`about:`,`blob:`,`chrome:`,`chrome-untrusted:`,`content:`,`data:`,`devtools:`,`file:`,`filesystem:`,`javascript:`];function gt(e){try{return ht.includes(new URL(e).protocol)}catch{return!1}}var _t=R.createContext(null);_t.displayName=`DataRouter`;var vt=R.createContext(null);vt.displayName=`DataRouterState`;var yt=R.createContext(!1);function bt(){return R.useContext(yt)}var xt=R.createContext({isTransitioning:!1});xt.displayName=`ViewTransition`;var St=R.createContext(new Map);St.displayName=`Fetchers`;var Ct=R.createContext(null);Ct.displayName=`Await`;var wt=R.createContext(null);wt.displayName=`Navigation`;var Tt=R.createContext(null);Tt.displayName=`Location`;var Et=R.createContext({outlet:null,matches:[],isDataRoute:!1});Et.displayName=`Route`;var Dt=R.createContext(null);Dt.displayName=`RouteError`;var Ot=`REACT_ROUTER_ERROR`,kt=`REDIRECT`,At=`ROUTE_ERROR_RESPONSE`;function jt(e){if(e.startsWith(`${Ot}:${kt}:{`))try{let t=JSON.parse(e.slice(28));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`&&typeof t.location==`string`&&typeof t.reloadDocument==`boolean`&&typeof t.replace==`boolean`)return t}catch{}}function Mt(e){if(e.startsWith(`${Ot}:${At}:{`))try{let t=JSON.parse(e.slice(40));if(typeof t==`object`&&t&&typeof t.status==`number`&&typeof t.statusText==`string`)return new ct(t.status,t.statusText,t.data)}catch{}}function Nt(e,{relative:t}={}){L(Pt(),`useHref() may be used only in the context of a component.`);let{basename:n,navigator:r}=R.useContext(wt),{hash:i,pathname:a,search:o}=Ht(e,{relative:t}),s=a;return n!==`/`&&(s=a===`/`?n:rt([n,a])),r.createHref({pathname:s,search:o,hash:i})}function Pt(){return R.useContext(Tt)!=null}function Ft(){return L(Pt(),`useLocation() may be used only in the context of a component.`),R.useContext(Tt).location}var It=`You should call navigate() in a React.useEffect(), not when your component is first rendered.`;function Lt(){let{isDataRoute:e}=R.useContext(Et);return e?on():Rt()}function Rt(){L(Pt(),`useNavigate() may be used only in the context of a component.`);let e=R.useContext(_t),{basename:t,navigator:n}=R.useContext(wt),{matches:r}=R.useContext(Et),{pathname:i}=Ft(),a=JSON.stringify(et(r)),o=R.useRef(!1);return R.useLayoutEffect(()=>{o.current=!0}),R.useCallback((r,s={})=>{if(ye(o.current,It),!o.current)return;if(typeof r==`number`){n.go(r);return}let c=tt(r,JSON.parse(a),i,s.relative===`path`);e==null&&t!==`/`&&(c.pathname=c.pathname===`/`?t:rt([t,c.pathname])),(s.replace?n.replace:n.push)(c,s.state,s)},[t,n,a,i,e])}var zt=R.createContext(null);function Bt(e){let t=R.useContext(Et).outlet;return R.useMemo(()=>t&&R.createElement(zt.Provider,{value:e},t),[t,e])}function Vt(){let{matches:e}=R.useContext(Et);return e[e.length-1]?.params??{}}function Ht(e,{relative:t}={}){let{matches:n}=R.useContext(Et),{pathname:r}=Ft(),i=JSON.stringify(et(n));return R.useMemo(()=>tt(e,JSON.parse(i),r,t===`path`),[e,i,r,t])}function Ut(e,t){return Wt(e,t)}function Wt(e,t,n){L(Pt(),`useRoutes() may be used only in the context of a component.`);let{navigator:r}=R.useContext(wt),{matches:i}=R.useContext(Et),a=i[i.length-1],o=a?a.params:{};a&&a.pathname;let s=a?a.pathnameBase:`/`;a&&a.route;let c=Ft(),l;if(t){let e=typeof t==`string`?we(t):t;L(s===`/`||e.pathname?.startsWith(s),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${s}" but pathname "${e.pathname}" was given in the \`location\` prop.`),l=e}else l=c;let u=l.pathname||`/`,d=u;if(s!==`/`){let e=s.replace(/^\//,``).split(`/`);d=`/`+u.replace(/^\//,``).split(`/`).slice(e.length).join(`/`)}let f=n&&n.state.matches.length?n.state.matches.map(e=>Object.assign(e,{route:n.manifest[e.route.id]||e.route})):De(e,{pathname:d}),p=Zt(f&&f.map(e=>Object.assign({},e,{params:Object.assign({},o,e.params),pathname:rt([s,r.encodeLocation?r.encodeLocation(e.pathname.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathname]),pathnameBase:e.pathnameBase===`/`?s:rt([s,r.encodeLocation?r.encodeLocation(e.pathnameBase.replace(/%/g,`%25`).replace(/\?/g,`%3F`).replace(/#/g,`%23`)).pathname:e.pathnameBase])})),i,n);return t&&p?R.createElement(Tt.Provider,{value:{location:{pathname:`/`,search:``,hash:``,state:null,key:`default`,mask:void 0,...l},navigationType:`POP`}},p):p}function Gt(){let e=an(),t=lt(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null;return R.createElement(R.Fragment,null,R.createElement(`h2`,null,`Unexpected Application Error!`),R.createElement(`h3`,{style:{fontStyle:`italic`}},t),n?R.createElement(`pre`,{style:{padding:`0.5rem`,backgroundColor:`rgba(200,200,200, 0.5)`}},n):null,null)}var Kt=R.createElement(Gt,null),qt=class extends R.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static contextType=yt;static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!==`idle`&&e.revalidation===`idle`?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error===void 0?t.error:e.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){this.props.onError?this.props.onError(e,t):console.error(`React Router caught the following error during render`,e)}render(){let e=this.state.error;if(this.context&&typeof e==`object`&&e&&`digest`in e&&typeof e.digest==`string`){let t=Mt(e.digest);t&&(e=t)}let t=e===void 0?this.props.children:R.createElement(Et.Provider,{value:this.props.routeContext},R.createElement(Dt.Provider,{value:e,children:this.props.component}));return this.context?R.createElement(Yt,{error:e},t):t}},Jt=new WeakMap;function Yt({children:e,error:t}){let{basename:n}=R.useContext(wt);if(typeof t==`object`&&t&&`digest`in t&&typeof t.digest==`string`){let e=jt(t.digest);if(e){let r=Jt.get(t);if(r)throw r;let i=ft(e.location,n),a=i.absoluteURL||i.to;if(gt(a))throw Error(`Invalid redirect location`);if(dt&&!Jt.get(t))if(i.isExternal||e.reloadDocument)window.location.href=a;else{let n=Promise.resolve().then(()=>window.__reactRouterDataRouter.navigate(i.to,{replace:e.replace}));throw Jt.set(t,n),n}return R.createElement(`meta`,{httpEquiv:`refresh`,content:`0;url=${a}`})}}return e}function Xt({routeContext:e,match:t,children:n}){let r=R.useContext(_t);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),R.createElement(Et.Provider,{value:e},n)}function Zt(e,t=[],n){let r=n?.state;if(e==null){if(!r)return null;if(r.errors)e=r.matches;else if(t.length===0&&!r.initialized&&r.matches.length>0)e=r.matches;else return null}let i=e,a=r?.errors;if(a!=null){let e=i.findIndex(e=>e.route.id&&a?.[e.route.id]!==void 0);L(e>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(a).join(`,`)}`),i=i.slice(0,Math.min(i.length,e+1))}let o=!1,s=-1;if(n&&r){o=r.renderFallback;for(let e=0;e=0?i.slice(0,s+1):[i[0]];break}}}}let c=n?.onError,l=r&&c?(e,t)=>{c(e,{location:r.location,params:r.matches?.[0]?.params??{},pattern:ut(r.matches),errorInfo:t})}:void 0;return i.reduceRight((e,n,c)=>{let u,d=!1,f=null,p=null;r&&(u=a&&n.route.id?a[n.route.id]:void 0,f=n.route.errorElement||Kt,o&&(s<0&&c===0?(cn(`route-fallback`,!1,"No `HydrateFallback` element provided to render during initial hydration"),d=!0,p=null):s===c&&(d=!0,p=n.route.hydrateFallbackElement||null)));let m=t.concat(i.slice(0,c+1)),h=()=>{let t;return t=u?f:d?p:n.route.Component?R.createElement(n.route.Component,null):n.route.element?n.route.element:e,R.createElement(Xt,{match:n,routeContext:{outlet:e,matches:m,isDataRoute:r!=null},children:t})};return r&&(n.route.ErrorBoundary||n.route.errorElement||c===0)?R.createElement(qt,{location:r.location,revalidation:r.revalidation,component:f,error:u,children:h(),routeContext:{outlet:null,matches:m,isDataRoute:!0},onError:l}):h()},null)}function Qt(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function $t(e){let t=R.useContext(_t);return L(t,Qt(e)),t}function en(e){let t=R.useContext(vt);return L(t,Qt(e)),t}function tn(e){let t=R.useContext(Et);return L(t,Qt(e)),t}function nn(e){let t=tn(e),n=t.matches[t.matches.length-1];return L(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function rn(){return nn(`useRouteId`)}function an(){let e=R.useContext(Dt),t=en(`useRouteError`),n=nn(`useRouteError`);return e===void 0?t.errors?.[n]:e}function on(){let{router:e}=$t(`useNavigate`),t=nn(`useNavigate`),n=R.useRef(!1);return R.useLayoutEffect(()=>{n.current=!0}),R.useCallback(async(r,i={})=>{ye(n.current,It),n.current&&(typeof r==`number`?await e.navigate(r):await e.navigate(r,{fromRouteId:t,...i}))},[e,t])}var sn={};function cn(e,t,n){!t&&!sn[e]&&(sn[e]=!0,ye(!1,n))}R.memo(ln);function ln({routes:e,manifest:t,future:n,state:r,isStatic:i,onError:a}){return Wt(e,void 0,{manifest:t,state:r,isStatic:i,onError:a,future:n})}function un({to:e,replace:t,state:n,relative:r}){L(Pt(),` may be used only in the context of a component.`);let{static:i}=R.useContext(wt);ye(!i,` must not be used on the initial render in a . This is a no-op, but you should modify your code so the is only ever rendered in response to some user interaction or state change.`);let{matches:a}=R.useContext(Et),{pathname:o}=Ft(),s=Lt(),c=tt(e,et(a),o,r===`path`),l=JSON.stringify(c);return R.useEffect(()=>{s(JSON.parse(l),{replace:t,state:n,relative:r})},[s,l,r,t,n]),null}function dn(e){return Bt(e.context)}function fn(e){L(!1,`A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .`)}function pn({basename:e=`/`,children:t=null,location:n,navigationType:r=`POP`,navigator:i,static:a=!1,useTransitions:o}){L(!Pt(),`You cannot render a inside another . You should never have more than one in your app.`);let s=e.replace(/^\/*/,`/`),c=R.useMemo(()=>({basename:s,navigator:i,static:a,useTransitions:o,future:{}}),[s,i,a,o]);typeof n==`string`&&(n=we(n));let{pathname:l=`/`,search:u=``,hash:d=``,state:f=null,key:p=`default`,mask:m}=n,h=R.useMemo(()=>{let e=Ye(l,s);return e==null?null:{location:{pathname:e,search:u,hash:d,state:f,key:p,mask:m},navigationType:r}},[s,l,u,d,f,p,r,m]);return ye(h!=null,` is not able to match the URL "${l}${u}${d}" because it does not start with the basename, so the won't render anything.`),h==null?null:R.createElement(wt.Provider,{value:c},R.createElement(Tt.Provider,{children:t,value:h}))}function mn({children:e,location:t}){return Ut(hn(e),t)}R.Component;function hn(e,t=[]){let n=[];return R.Children.forEach(e,(e,r)=>{if(!R.isValidElement(e))return;let i=[...t,r];if(e.type===R.Fragment){n.push.apply(n,hn(e.props.children,i));return}L(e.type===fn,`[${typeof e.type==`string`?e.type:e.type.name}] is not a component. All component children of must be a or `);let a=e.props;L(!a.index||!a.children,`An index route cannot have child routes.`);let o={id:a.id||i.join(`-`),caseSensitive:a.caseSensitive,element:a.element,Component:a.Component,index:a.index,path:a.path,middleware:a.middleware,loader:a.loader,action:a.action,hydrateFallbackElement:a.hydrateFallbackElement,HydrateFallback:a.HydrateFallback,errorElement:a.errorElement,ErrorBoundary:a.ErrorBoundary,shouldRevalidate:a.shouldRevalidate,handle:a.handle,lazy:a.lazy};a.children&&(o.children=hn(a.children,i)),n.push(o)}),n}var gn=`application/x-www-form-urlencoded`;function _n(e){return typeof HTMLElement<`u`&&e instanceof HTMLElement}function vn(e){return _n(e)&&e.tagName.toLowerCase()===`button`}function yn(e){return _n(e)&&e.tagName.toLowerCase()===`form`}function bn(e){return _n(e)&&e.tagName.toLowerCase()===`input`}function xn(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function Sn(e,t){return e.button===0&&(!t||t===`_self`)&&!xn(e)}function Cn(e=``){return new URLSearchParams(typeof e==`string`||Array.isArray(e)||e instanceof URLSearchParams?e:Object.keys(e).reduce((t,n)=>{let r=e[n];return t.concat(Array.isArray(r)?r.map(e=>[n,e]):[[n,r]])},[]))}function wn(e,t){let n=Cn(e);return t&&t.forEach((e,r)=>{n.has(r)||t.getAll(r).forEach(e=>{n.append(r,e)})}),n}var Tn=null;function En(){if(Tn===null)try{new FormData(document.createElement(`form`),0),Tn=!1}catch{Tn=!0}return Tn}var Dn=new Set([`application/x-www-form-urlencoded`,`multipart/form-data`,`text/plain`]);function On(e){return e!=null&&!Dn.has(e)?(ye(!1,`"${e}" is not a valid \`encType\` for \`
- docker exec palhelm palhelm fetch-map-tiles
+ {serverQuery.data?.mapTilesCommand ?? "docker compose exec palhelm palhelm fetch-map-tiles"}
)}
diff --git a/frontend/src/routes/paldeck/Paldeck.tsx b/frontend/src/routes/paldeck/Paldeck.tsx
index f8f54bc..5c4ddde 100644
--- a/frontend/src/routes/paldeck/Paldeck.tsx
+++ b/frontend/src/routes/paldeck/Paldeck.tsx
@@ -74,6 +74,12 @@ function PaldeckContent({ data, search, setSearch, filter, setFilter, species }:
setFilter: (value: PaldeckSpeciesFilter) => void;
species: PaldeckSpecies[];
}) {
+ const iconDatasetQuery = useQuery({
+ queryKey: ["paldeck", "icon-dataset"],
+ queryFn: () => api.paldeck.iconDataset(),
+ staleTime: Infinity,
+ });
+ const serverQuery = useQuery({ queryKey: ["server"], queryFn: () => api.server.get() });
const isPlayer = "player" in data;
const captureAvailable = isPlayer ? data.coverage.captureCountsAvailable : data.coverage.playersWithCaptureCounts > 0;
const captureTruncated = data.coverage.captureCountsTruncated;
@@ -96,6 +102,11 @@ function PaldeckContent({ data, search, setSearch, filter, setFilter, species }:
: `Capture data covers ${data.coverage.playersWithCaptureCounts} of ${data.coverage.playersTotal} players.`}
{captureTruncated ? " The capture map was truncated, so “unseen” is not conclusive." : " Missing data is never counted as zero."}
+ {iconDatasetQuery.data?.count === 0 && (
+
+ Pal icons are not installed. Initials are shown instead. Run {serverQuery.data?.palIconsCommand ?? "docker compose exec palhelm palhelm fetch-pal-icons"} to add portraits.
+
+ )}
diff --git a/frontend/src/routes/pals/Pals.tsx b/frontend/src/routes/pals/Pals.tsx
index 1ca7088..e72d1fc 100644
--- a/frontend/src/routes/pals/Pals.tsx
+++ b/frontend/src/routes/pals/Pals.tsx
@@ -10,7 +10,7 @@ import { EmptyState } from "../../components/EmptyState";
import { PalDetailPanel, PalInfoButton } from "../../components/PalDetails";
import { PalIcon } from "../../components/PalIcon";
import { PalStars } from "../../components/PalStars";
-import { palPlacementLabel } from "../../components/palDetails";
+import { palPlacementLabel } from "../../components/PalDetailsModel";
import { SearchField } from "../../components/Field";
import {
PAL_EXPLORER_CLIENT_CAP,
diff --git a/frontend/tests/guild-paldeck-routes.test.mjs b/frontend/tests/guild-paldeck-routes.test.mjs
index 3e6642a..04e3591 100644
--- a/frontend/tests/guild-paldeck-routes.test.mjs
+++ b/frontend/tests/guild-paldeck-routes.test.mjs
@@ -28,5 +28,17 @@ test("Paldeck screen distinguishes partial save observations from pinned progres
assert.match(source, /Species captured/);
assert.match(source, /Unique species counter/);
assert.match(source, /Missing data is never counted as zero/);
+ assert.match(source, /api\.paldeck\.iconDataset/);
+ assert.match(source, /Pal icons are not installed/);
assert.match(source, /Unseen \(needs full data\)/);
});
+
+test("Paldeck icon notice uses the container downloader command", async () => {
+ const source = await readFile(new URL("../src/routes/paldeck/Paldeck.tsx", import.meta.url), "utf8");
+ assert.match(source, /docker compose exec palhelm palhelm fetch-pal-icons/);
+});
+
+test("Paldeck icon notice uses the server-resolved Compose container command", async () => {
+ const source = await readFile(new URL("../src/routes/paldeck/Paldeck.tsx", import.meta.url), "utf8");
+ assert.match(source, /serverQuery\.data\?\.palIconsCommand/);
+});
diff --git a/frontend/tests/mapInteraction.test.mjs b/frontend/tests/mapInteraction.test.mjs
index 852630d..f873e1d 100644
--- a/frontend/tests/mapInteraction.test.mjs
+++ b/frontend/tests/mapInteraction.test.mjs
@@ -124,3 +124,9 @@ test("map route wires search, focus, fit, sharing, and mobile-safe controls", as
assert.match(css, /@media \(max-width: 600px\)/);
assert.match(css, /touch-action: none/);
});
+
+test("map tile install command comes from server runtime metadata", async () => {
+ const route = await readFile(new URL("../src/routes/map/Map.tsx", import.meta.url), "utf8");
+ assert.match(route, /serverQuery\.data\?\.mapTilesCommand/);
+ assert.doesNotMatch(route, /docker exec palhelm palhelm fetch-map-tiles/);
+});
diff --git a/frontend/tests/pal-details.test.mjs b/frontend/tests/pal-details.test.mjs
index a03e064..98319f7 100644
--- a/frontend/tests/pal-details.test.mjs
+++ b/frontend/tests/pal-details.test.mjs
@@ -1,7 +1,7 @@
import assert from "node:assert/strict";
import test from "node:test";
import { readFile } from "node:fs/promises";
-import { humanizePalIdentifier, palGenderLabel, palPlacementLabel } from "../src/components/palDetails.ts";
+import { humanizePalIdentifier, palGenderLabel, palPlacementLabel } from "../src/components/PalDetailsModel.ts";
import { PAL_WORK_DATA_PROVENANCE, workSuitabilitiesFor, workSuitabilityKind } from "../src/components/workSuitabilities.ts";
test("Pal detail labels humanize save identifiers and preserve unknown data honestly", () => {
diff --git a/frontend/tests/pal-stars.test.mjs b/frontend/tests/pal-stars.test.mjs
index 263e5e1..136d156 100644
--- a/frontend/tests/pal-stars.test.mjs
+++ b/frontend/tests/pal-stars.test.mjs
@@ -1,7 +1,7 @@
import assert from "node:assert/strict";
import test from "node:test";
import { readFile } from "node:fs/promises";
-import { condensedStars, MAX_CONDENSE_STARS } from "../src/components/palStars.ts";
+import { condensedStars, MAX_CONDENSE_STARS } from "../src/components/PalStarsModel.ts";
test("condensed stars map rank 1..5 to 0..4 filled stars", () => {
assert.equal(MAX_CONDENSE_STARS, 4);