From 1000d4c35fa848b0ba3f0171c040c37b571ad23e Mon Sep 17 00:00:00 2001
From: Mozartuss
Date: Thu, 30 Jul 2026 23:57:19 +0200
Subject: [PATCH 1/7] Add map tile fetching subcommand and Docker support
---
.gitignore | 4 ++++
Dockerfile | 3 ++-
backend/cmd/palhelm/main.go | 22 +++++++++++++++++++++-
3 files changed, 27 insertions(+), 2 deletions(-)
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..64ceca8 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -23,9 +23,10 @@ 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
USER palhelm
ENV PALHELM_ADDR=:8080 PALHELM_DATA_DIR=/data
VOLUME /data
diff --git a/backend/cmd/palhelm/main.go b/backend/cmd/palhelm/main.go
index e319e90..4c3a50a 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"
@@ -49,10 +50,29 @@ func run() error {
return errors.New("usage: palhelm parse ")
}
return parse(args[0])
+ case "fetch-map-tiles":
+ return fetchMapTiles(args)
default:
- return fmt.Errorf("unknown subcommand %q (expected serve or parse)", command)
+ return fmt.Errorf("unknown subcommand %q (expected serve, parse, or fetch-map-tiles)", 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 := exec.Command("/usr/local/bin/fetch-map-tiles", 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 parse(path string) error {
var v any
var err error
From 67527679a44af92391494e1c4af39445d7c06384 Mon Sep 17 00:00:00 2001
From: Mozartuss
Date: Fri, 31 Jul 2026 10:10:33 +0200
Subject: [PATCH 2/7] Make map tile fetch command injectable
---
backend/cmd/palhelm/main.go | 6 +++-
backend/cmd/palhelm/main_test.go | 57 ++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)
create mode 100644 backend/cmd/palhelm/main_test.go
diff --git a/backend/cmd/palhelm/main.go b/backend/cmd/palhelm/main.go
index 4c3a50a..4f5b88c 100644
--- a/backend/cmd/palhelm/main.go
+++ b/backend/cmd/palhelm/main.go
@@ -25,6 +25,10 @@ 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...)
+}
+
func main() {
server.PanelVersion = version
if err := run(); err != nil {
@@ -64,7 +68,7 @@ func fetchMapTiles(args []string) error {
}
args = []string{filepath.Join(dataDir, "map-tiles")}
}
- cmd := exec.Command("/usr/local/bin/fetch-map-tiles", args...)
+ cmd := fetchMapTilesCommand(args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
diff --git a/backend/cmd/palhelm/main_test.go b/backend/cmd/palhelm/main_test.go
new file mode 100644
index 0000000..22915de
--- /dev/null
+++ b/backend/cmd/palhelm/main_test.go
@@ -0,0 +1,57 @@
+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)
+ }
+ })
+}
From 9e3501aceed3b42fbe379fbd1cb94c56b8c68744 Mon Sep 17 00:00:00 2001
From: Mozartuss
Date: Fri, 31 Jul 2026 10:19:21 +0200
Subject: [PATCH 3/7] Expose runtime-resolved map tile install command
---
README.md | 2 +
backend/internal/config/config.go | 3 +-
backend/internal/config/config_test.go | 20 +++++++
backend/internal/server/docker_compose.go | 58 +++++++++++++++++++
.../internal/server/docker_compose_test.go | 47 +++++++++++++++
backend/internal/server/openapi.json | 2 +-
backend/internal/server/server.go | 2 +-
.../content/docs/getting-started/install.md | 2 +
docs/API.md | 2 +-
examples/docker-compose.yml | 1 +
frontend/src/api/types.ts | 1 +
frontend/src/routes/map/Map.tsx | 2 +-
frontend/tests/mapInteraction.test.mjs | 6 ++
13 files changed, 143 insertions(+), 5 deletions(-)
create mode 100644 backend/internal/server/docker_compose.go
create mode 100644 backend/internal/server/docker_compose_test.go
diff --git a/README.md b/README.md
index 8cf6881..2e0ae85 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
@@ -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/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..41050ff
--- /dev/null
+++ b/backend/internal/server/docker_compose.go
@@ -0,0 +1,58 @@
+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 {
+ 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 fetch-map-tiles"
+ }
+ }
+ }
+ return "docker compose exec " + shellArg(service) + " palhelm fetch-map-tiles"
+}
+
+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..84f0c43
--- /dev/null
+++ b/backend/internal/server/docker_compose_test.go
@@ -0,0 +1,47 @@
+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)
+ }
+ })
+}
diff --git a/backend/internal/server/openapi.json b/backend/internal/server/openapi.json
index dfd161c..54caaab 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"], "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."}}},
"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..06d71b5 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)})
}
func (s *Server) serverHealth(w http.ResponseWriter, r *http.Request) {
rest, rcon, save, at := s.health.Snapshot()
diff --git a/docs-site/src/content/docs/getting-started/install.md b/docs-site/src/content/docs/getting-started/install.md
index c38635e..7f893b5 100644
--- a/docs-site/src/content/docs/getting-started/install.md
+++ b/docs-site/src/content/docs/getting-started/install.md
@@ -76,6 +76,7 @@ services:
PALWORLD_SAVE_DIR: "/game/Saved"
PALHELM_COMPOSE_FILE: "/compose/docker-compose.yml" # enables the config editor
PALHELM_GAME_SERVICE: "palworld"
+ PALHELM_PANEL_SERVICE: "palhelm"
# PALHELM_TRUSTED_PROXIES: "10.0.0.0/8" # proxy CIDRs allowed to supply forwarded IP/HTTPS
# PALHELM_SECURE_COOKIES: "true" # force Secure cookies behind TLS termination
volumes:
@@ -106,6 +107,7 @@ These are the ones you set most often. The full table is in the project README.
| `PALWORLD_SAVE_DIR` | yes | The mounted save directory, `/game/Saved` above. |
| `PALHELM_COMPOSE_FILE` | no | Path to the Compose file inside the container. Enables the config editor. |
| `PALHELM_GAME_SERVICE` | no | The service name of the game server in that Compose file. Defaults to `palworld`. |
+| `PALHELM_PANEL_SERVICE` | no | The Palhelm service in that Compose file. Defaults to `palhelm` and lets the UI resolve its explicit `container_name`. |
| `PALHELM_DATA_DIR` | no | The data directory. Defaults to `/data`. |
| `PALHELM_GAME_DATA_ENABLED` | no | Turns on the optional live game-data poller for live map positions, base workers, and activity diagnostics. Defaults to off. |
| `PALHELM_ADDR` | no | Listen address. Defaults to `:8080`. |
diff --git a/docs/API.md b/docs/API.md
index 7aa3669..a97b2fa 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -14,7 +14,7 @@ Operation-specific recovery details, such as Config's `manualCommand`, stay insi
| GET | `/auth/session` | `{role, username}` or 401 |
## Server
-| GET | `/server` | `{name, description, version, worldGuid, state, uptimeSec, panelVersion, sessionDays, saveSyncMinutes}`. `sessionDays` is the login-session lifetime in whole days (`PALHELM_SESSION_DAYS`, now honored); `saveSyncMinutes` is the save-sync poll interval in whole minutes (`PALHELM_SAVE_SYNC_INTERVAL`). |
+| GET | `/server` | `{name, description, version, worldGuid, state, uptimeSec, panelVersion, sessionDays, saveSyncMinutes, mapTilesCommand}`. `sessionDays` is the login-session lifetime in whole days (`PALHELM_SESSION_DAYS`, now honored); `saveSyncMinutes` is the save-sync poll interval in whole minutes (`PALHELM_SAVE_SYNC_INTERVAL`). `mapTilesCommand` uses the panel service's explicit Compose `container_name`, falling back to `docker compose exec`. |
| GET | `/server/health` | `{rest: "ok"\|"error", rcon: "ok"\|"error", save: {state, lastSyncAt}}` |
| POST | `/server/announce` | `{message}` |
| POST | `/server/save` | trigger world save |
diff --git a/examples/docker-compose.yml b/examples/docker-compose.yml
index b5cf425..06da149 100644
--- a/examples/docker-compose.yml
+++ b/examples/docker-compose.yml
@@ -52,6 +52,7 @@ services:
# config editor: let Palhelm edit this compose file's env block
PALHELM_COMPOSE_FILE: "/compose/docker-compose.yml"
PALHELM_GAME_SERVICE: "palworld"
+ PALHELM_PANEL_SERVICE: "palhelm"
# One-click Docker apply is intentionally disabled. Palhelm displays the host command.
volumes:
- ../data/Pal/Saved:/game/Saved # rw: restore writes here
diff --git a/frontend/src/api/types.ts b/frontend/src/api/types.ts
index b8664dd..642a8f1 100644
--- a/frontend/src/api/types.ts
+++ b/frontend/src/api/types.ts
@@ -41,6 +41,7 @@ export interface ServerInfo {
// rather than static reference numbers. Optional so older backends still type-check.
sessionDays?: number;
saveSyncMinutes?: number;
+ mapTilesCommand?: string;
}
export type HealthState = "ok" | "error";
diff --git a/frontend/src/routes/map/Map.tsx b/frontend/src/routes/map/Map.tsx
index cd3ce5b..225a360 100644
--- a/frontend/src/routes/map/Map.tsx
+++ b/frontend/src/routes/map/Map.tsx
@@ -642,7 +642,7 @@ export default function MapRoute() {
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:
- docker exec palhelm palhelm fetch-map-tiles
+ {serverQuery.data?.mapTilesCommand ?? "docker compose exec palhelm palhelm fetch-map-tiles"}
)}
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/);
+});
From 2e4dfbbf7244d7ae2e6b1dc68fe8bc1e5cc9ce84 Mon Sep 17 00:00:00 2001
From: Mozartuss
Date: Fri, 31 Jul 2026 10:47:39 +0200
Subject: [PATCH 4/7] fix imports
---
.../webdist/dist/assets/Activity-CN5lRrug.css | 1 +
.../webdist/dist/assets/Activity-LIxhbXE9.js | 1 +
.../webdist/dist/assets/Backups-D0xRMMg_.js | 1 +
.../webdist/dist/assets/Backups-hnJGe2yy.css | 1 +
.../webdist/dist/assets/Banner-DSN1nEJn.js | 1 +
.../webdist/dist/assets/Card-D55CMzdw.js | 1 +
.../webdist/dist/assets/CodeWell-Mu33yg_R.js | 1 +
.../webdist/dist/assets/Config-C4QPTHpP.js | 1 +
.../webdist/dist/assets/Config-CXg6qAk9.css | 1 +
.../webdist/dist/assets/Console-B-5ZyxL5.css | 1 +
.../webdist/dist/assets/Console-CV5rct3U.js | 2 +
.../dist/assets/Dashboard-BycK1nhV.css | 1 +
.../webdist/dist/assets/Dashboard-CdHC4zJR.js | 10 +
.../dist/assets/Diagnostics-Bz5B5Zx0.js | 1 +
.../dist/assets/Diagnostics-CdVImtbq.css | 1 +
.../dist/assets/DropdownMenu-B8GDd0Lr.js | 1 +
.../dist/assets/EmptyState-DTSMkv56.js | 1 +
.../dist/assets/EventMessage-UG0hgRVA.js | 1 +
.../webdist/dist/assets/Events-B_aT42e0.js | 1 +
.../webdist/dist/assets/Events-Y3iu26GS.css | 1 +
.../webdist/dist/assets/Guilds-CXiI-XCc.js | 1 +
.../webdist/dist/assets/Guilds-VTJeI58t.css | 1 +
.../webdist/dist/assets/Map-BPJLiHEM.css | 1 +
.../webdist/dist/assets/Map-CEAHp7lv.js | 1 +
.../dist/assets/PalDetails-BINDGFj3.js | 1 +
.../dist/assets/PalDetails-Bl23SosS.css | 1 +
.../webdist/dist/assets/PalIcon-BoDQgR3K.js | 1 +
.../webdist/dist/assets/PalStars-CiCl8RwT.js | 1 +
.../webdist/dist/assets/PalStars-osSMQvdm.css | 1 +
.../webdist/dist/assets/Paldeck-C_yvNXNY.js | 1 +
.../webdist/dist/assets/Paldeck-gNJw7ewz.css | 1 +
.../webdist/dist/assets/Pals-BECL-Yeg.js | 1 +
.../webdist/dist/assets/Pals-D_KCRg-r.css | 1 +
.../webdist/dist/assets/Players-5fYfLSwo.css | 1 +
.../webdist/dist/assets/Players-DByi0CuW.js | 1 +
.../webdist/dist/assets/Settings-CbNDodqw.js | 1 +
.../webdist/dist/assets/Settings-DDAtAokj.css | 1 +
.../webdist/dist/assets/Tabs-DecjeYAq.js | 1 +
.../dist/assets/guildDisplay-LZYrk7hc.js | 1 +
.../dist/assets/hero-paper-Dw4QRDvw.png | Bin 0 -> 3198364 bytes
...-plex-mono-latin-400-normal-DMJ8VG8y.woff2 | Bin 0 -> 14708 bytes
...-plex-mono-latin-600-normal-BgSNZQsw.woff2 | Bin 0 -> 15620 bytes
...-plex-sans-latin-400-normal-CDDApCn2.woff2 | Bin 0 -> 22588 bytes
...-plex-sans-latin-500-normal-6ng42L7E.woff2 | Bin 0 -> 24184 bytes
...-plex-sans-latin-600-normal-CuJfVYMP.woff2 | Bin 0 -> 24252 bytes
.../webdist/dist/assets/icons-CpYMTu_k.js | 5 +
.../webdist/dist/assets/index-38JxCrNC.css | 1 +
.../webdist/dist/assets/index-Cb9c2VWC.js | 10 +
.../dist/assets/palExplorer-IChZ_UBL.js | 1 +
.../dist/assets/tex-noise-canvas-Cczou4P1.png | Bin 0 -> 1614901 bytes
.../dist/assets/useMutation-D2E7YVrA.js | 1 +
backend/internal/webdist/dist/favicon.svg | 21 +
backend/internal/webdist/dist/index.html | 31 +-
frontend/package-lock.json | 973 ++++++++++++------
frontend/package.json | 24 +-
frontend/src/components/PalDetails.tsx | 4 +-
.../{palDetails.ts => PalDetailsModel.ts} | 0
frontend/src/components/PalStars.tsx | 2 +-
.../{palStars.ts => PalStarsModel.ts} | 0
frontend/src/routes/pals/Pals.tsx | 2 +-
frontend/tests/pal-details.test.mjs | 2 +-
frontend/tests/pal-stars.test.mjs | 2 +-
62 files changed, 778 insertions(+), 350 deletions(-)
create mode 100644 backend/internal/webdist/dist/assets/Activity-CN5lRrug.css
create mode 100644 backend/internal/webdist/dist/assets/Activity-LIxhbXE9.js
create mode 100644 backend/internal/webdist/dist/assets/Backups-D0xRMMg_.js
create mode 100644 backend/internal/webdist/dist/assets/Backups-hnJGe2yy.css
create mode 100644 backend/internal/webdist/dist/assets/Banner-DSN1nEJn.js
create mode 100644 backend/internal/webdist/dist/assets/Card-D55CMzdw.js
create mode 100644 backend/internal/webdist/dist/assets/CodeWell-Mu33yg_R.js
create mode 100644 backend/internal/webdist/dist/assets/Config-C4QPTHpP.js
create mode 100644 backend/internal/webdist/dist/assets/Config-CXg6qAk9.css
create mode 100644 backend/internal/webdist/dist/assets/Console-B-5ZyxL5.css
create mode 100644 backend/internal/webdist/dist/assets/Console-CV5rct3U.js
create mode 100644 backend/internal/webdist/dist/assets/Dashboard-BycK1nhV.css
create mode 100644 backend/internal/webdist/dist/assets/Dashboard-CdHC4zJR.js
create mode 100644 backend/internal/webdist/dist/assets/Diagnostics-Bz5B5Zx0.js
create mode 100644 backend/internal/webdist/dist/assets/Diagnostics-CdVImtbq.css
create mode 100644 backend/internal/webdist/dist/assets/DropdownMenu-B8GDd0Lr.js
create mode 100644 backend/internal/webdist/dist/assets/EmptyState-DTSMkv56.js
create mode 100644 backend/internal/webdist/dist/assets/EventMessage-UG0hgRVA.js
create mode 100644 backend/internal/webdist/dist/assets/Events-B_aT42e0.js
create mode 100644 backend/internal/webdist/dist/assets/Events-Y3iu26GS.css
create mode 100644 backend/internal/webdist/dist/assets/Guilds-CXiI-XCc.js
create mode 100644 backend/internal/webdist/dist/assets/Guilds-VTJeI58t.css
create mode 100644 backend/internal/webdist/dist/assets/Map-BPJLiHEM.css
create mode 100644 backend/internal/webdist/dist/assets/Map-CEAHp7lv.js
create mode 100644 backend/internal/webdist/dist/assets/PalDetails-BINDGFj3.js
create mode 100644 backend/internal/webdist/dist/assets/PalDetails-Bl23SosS.css
create mode 100644 backend/internal/webdist/dist/assets/PalIcon-BoDQgR3K.js
create mode 100644 backend/internal/webdist/dist/assets/PalStars-CiCl8RwT.js
create mode 100644 backend/internal/webdist/dist/assets/PalStars-osSMQvdm.css
create mode 100644 backend/internal/webdist/dist/assets/Paldeck-C_yvNXNY.js
create mode 100644 backend/internal/webdist/dist/assets/Paldeck-gNJw7ewz.css
create mode 100644 backend/internal/webdist/dist/assets/Pals-BECL-Yeg.js
create mode 100644 backend/internal/webdist/dist/assets/Pals-D_KCRg-r.css
create mode 100644 backend/internal/webdist/dist/assets/Players-5fYfLSwo.css
create mode 100644 backend/internal/webdist/dist/assets/Players-DByi0CuW.js
create mode 100644 backend/internal/webdist/dist/assets/Settings-CbNDodqw.js
create mode 100644 backend/internal/webdist/dist/assets/Settings-DDAtAokj.css
create mode 100644 backend/internal/webdist/dist/assets/Tabs-DecjeYAq.js
create mode 100644 backend/internal/webdist/dist/assets/guildDisplay-LZYrk7hc.js
create mode 100644 backend/internal/webdist/dist/assets/hero-paper-Dw4QRDvw.png
create mode 100644 backend/internal/webdist/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2
create mode 100644 backend/internal/webdist/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2
create mode 100644 backend/internal/webdist/dist/assets/ibm-plex-sans-latin-400-normal-CDDApCn2.woff2
create mode 100644 backend/internal/webdist/dist/assets/ibm-plex-sans-latin-500-normal-6ng42L7E.woff2
create mode 100644 backend/internal/webdist/dist/assets/ibm-plex-sans-latin-600-normal-CuJfVYMP.woff2
create mode 100644 backend/internal/webdist/dist/assets/icons-CpYMTu_k.js
create mode 100644 backend/internal/webdist/dist/assets/index-38JxCrNC.css
create mode 100644 backend/internal/webdist/dist/assets/index-Cb9c2VWC.js
create mode 100644 backend/internal/webdist/dist/assets/palExplorer-IChZ_UBL.js
create mode 100644 backend/internal/webdist/dist/assets/tex-noise-canvas-Cczou4P1.png
create mode 100644 backend/internal/webdist/dist/assets/useMutation-D2E7YVrA.js
create mode 100644 backend/internal/webdist/dist/favicon.svg
rename frontend/src/components/{palDetails.ts => PalDetailsModel.ts} (100%)
rename frontend/src/components/{palStars.ts => PalStarsModel.ts} (100%)
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-LIxhbXE9.js b/backend/internal/webdist/dist/assets/Activity-LIxhbXE9.js
new file mode 100644
index 0000000..9eeac11
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Activity-LIxhbXE9.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-Cb9c2VWC.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-D0xRMMg_.js b/backend/internal/webdist/dist/assets/Backups-D0xRMMg_.js
new file mode 100644
index 0000000..6e2df5a
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Backups-D0xRMMg_.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-D2E7YVrA.js";import{n as u,r as d,t as f}from"./DropdownMenu-B8GDd0Lr.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-Cb9c2VWC.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-C4QPTHpP.js b/backend/internal/webdist/dist/assets/Config-C4QPTHpP.js
new file mode 100644
index 0000000..8697c6b
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Config-C4QPTHpP.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-D2E7YVrA.js";import{An as l,Dn as u,d}from"./index-Cb9c2VWC.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-CV5rct3U.js b/backend/internal/webdist/dist/assets/Console-CV5rct3U.js
new file mode 100644
index 0000000..04496c3
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Console-CV5rct3U.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-D2E7YVrA.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-Cb9c2VWC.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-CdHC4zJR.js b/backend/internal/webdist/dist/assets/Dashboard-CdHC4zJR.js
new file mode 100644
index 0000000..81a4bf6
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Dashboard-CdHC4zJR.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-Cb9c2VWC.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-Bz5B5Zx0.js b/backend/internal/webdist/dist/assets/Diagnostics-Bz5B5Zx0.js
new file mode 100644
index 0000000..3535e04
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Diagnostics-Bz5B5Zx0.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-Cb9c2VWC.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-B8GDd0Lr.js b/backend/internal/webdist/dist/assets/DropdownMenu-B8GDd0Lr.js
new file mode 100644
index 0000000..63a8c34
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/DropdownMenu-B8GDd0Lr.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-Cb9c2VWC.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-B_aT42e0.js b/backend/internal/webdist/dist/assets/Events-B_aT42e0.js
new file mode 100644
index 0000000..2cb8cc7
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Events-B_aT42e0.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-Cb9c2VWC.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-CXiI-XCc.js b/backend/internal/webdist/dist/assets/Guilds-CXiI-XCc.js
new file mode 100644
index 0000000..0a5e73d
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Guilds-CXiI-XCc.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-Cb9c2VWC.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-BPJLiHEM.css b/backend/internal/webdist/dist/assets/Map-BPJLiHEM.css
new file mode 100644
index 0000000..290343e
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Map-BPJLiHEM.css
@@ -0,0 +1 @@
+.map-card{height:70vh;min-height:480px}.map-actionbar{z-index:4;align-items:center;gap:var(--space-2);background:var(--surface);border-bottom:1px solid var(--line);padding:9px 12px;display:flex;position:relative}.map-actionbar .map-action svg{width:16px;height:16px}.map-search{flex:260px;min-width:180px;position:relative}.map-search .search{width:100%}.map-search-results{background:var(--surface);border:1px solid var(--line-strong);border-radius:var(--radius-card);width:min(420px,100vw - 40px);max-height:280px;box-shadow:var(--shadow-pop);position:absolute;top:calc(100% + 5px);left:0;overflow-y:auto}.map-search-results button{align-items:center;gap:var(--space-2);text-align:left;width:100%;color:var(--ink);border:0;border-bottom:1px solid var(--line);cursor:pointer;background:0 0;padding:9px 11px;display:flex}.map-search-results button:last-child{border-bottom:0}.map-search-results button:hover{background:var(--surface-2)}.map-search-results button>span: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/Map-CEAHp7lv.js b/backend/internal/webdist/dist/assets/Map-CEAHp7lv.js
new file mode 100644
index 0000000..d5ce762
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Map-CEAHp7lv.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-Cb9c2VWC.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;o[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/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/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:e,search:t,setSearch:n,filter:r,setFilter:i,species:o}){let g=`player`in e,v=g?e.coverage.captureCountsAvailable:e.coverage.playersWithCaptureCounts>0,b=e.coverage.captureCountsTruncated,x=g?e.coverage.captureCountsAvailable&&!b:e.coverage.playersTotal>0&&e.coverage.playersWithCaptureCounts===e.coverage.playersTotal&&!b,C=g?e.coverage.unlockFlagsAvailable&&!e.coverage.unlockFlagsTruncated:e.coverage.playersTotal>0&&e.coverage.playersWithUnlockFlags===e.coverage.playersTotal&&!e.coverage.unlockFlagsTruncated,w=g?e.coverage.captureObservedAt:e.coverage.latestObservedAt,T=g?e.uniquePalsCaptured:e.uniqueSpeciesCaptured,E=x?e.species.filter(e=>e.known&&e.captureCount!==null&&e.captureCount>0).length:null,D=C?e.species.filter(e=>e.known&&(g?e.unlocked===!0:(e.unlockedByPlayers??0)>0)).length:null;return(0,y.jsxs)(y.Fragment,{children:[(0,y.jsxs)(l,{tone:x?`info`:`warn`,children:[g?v?`Capture data from ${s(w)}.`:`No capture data decoded for this player yet.`:`Capture data covers ${e.coverage.playersWithCaptureCounts} of ${e.coverage.playersTotal} players.`,b?` The capture map was truncated, so “unseen” is not conclusive.`:` Missing data is never counted as zero.`]}),(0,y.jsxs)(`div`,{className:`paldeck-stats`,"aria-label":`Paldeck summary`,children:[(0,y.jsx)(S,{label:`Species captured`,value:E,denominator:e.catalog.knownSpecies,percent:_(E,e.catalog.knownSpecies)}),(0,y.jsx)(S,{label:`Entries unlocked`,value:D,denominator:e.catalog.knownSpecies,percent:_(D,e.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:e.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:T??`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:`${o.length} shown of ${e.catalog.knownSpecies}`}),(0,y.jsx)(u,{children:(0,y.jsxs)(`div`,{className:`paldeck-tools`,children:[(0,y.jsx)(c,{value:t,onChange:e=>n(e.target.value),placeholder:`Search Pal name…`,"aria-label":`Search Paldeck species`}),(0,y.jsxs)(`select`,{className:`input`,"aria-label":`Capture filter`,value:!x&&r===`unseen`?`all`:r,onChange:e=>i(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:!x,children:`Unseen (needs full data)`}),(0,y.jsx)(`option`,{value:`unavailable`,children:`No data`})]})]})}),o.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:o.map(e=>{let t=e.captureCount,n=!x&&t===0,r=g?null:e,i=g?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 `,e.catalog.version,` · `,e.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-BECL-Yeg.js b/backend/internal/webdist/dist/assets/Pals-BECL-Yeg.js
new file mode 100644
index 0000000..0357168
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Pals-BECL-Yeg.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-Cb9c2VWC.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-BINDGFj3.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-DByi0CuW.js b/backend/internal/webdist/dist/assets/Players-DByi0CuW.js
new file mode 100644
index 0000000..f3ebc81
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Players-DByi0CuW.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-D2E7YVrA.js";import{n as f,t as p}from"./DropdownMenu-B8GDd0Lr.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-Cb9c2VWC.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-BINDGFj3.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-CbNDodqw.js b/backend/internal/webdist/dist/assets/Settings-CbNDodqw.js
new file mode 100644
index 0000000..35fbf10
--- /dev/null
+++ b/backend/internal/webdist/dist/assets/Settings-CbNDodqw.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-D2E7YVrA.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-Cb9c2VWC.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/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/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 0000000000000000000000000000000000000000..6916bfb50ccd5a0115157e486250d04df57d6490
GIT binary patch
literal 3198364
zcmV)_K!3l9P)d<3HG;e{&;0n@4}O
zPX1}1IqsZ0>6$;|UApL5y5wHE>{+?$Tf62LT?>e>2SnF>%U8Thmjj|3{?)kIcmCL^6%bvw^o+Z-!bKa#3
zzSYZq@pV$XYgYo2YktXfvLz@h4#`S`(vpDqmS0rlU%TmFyFt2$?D8z0_bi-u&z%d1
zuJ~84xaQ6}rccVPP$1|SMjC(Ze8OylH
zay;c6PC15C&e4>MtdFN0qiN?@#yy_#PLKm~fhktpYnAthEpKAZk0Jh**YLolyW`OG
z+Ev|lRfj{UJ@gvyx(v6Sy4w!T9h>^LUE6OXE1EkF?Omtt
zzDqygGCXiI51qyVyY{Y4cbk)ST2#Fb{auT?kE~eLeP&f3uju7uJ!ENC_Hptav#Qsu
z?zL)f^QvB>v|TT5HA*^IMK`DFGDur=qDH;ANxjmbUai+lnw5(+lIb$}e7R(%bakR=
zY3$nE(52bIiwh%Hm&dM?vNm~BG*u#>uhNrC$vQQwt*Ye)*+Ti+)V1l4CkLPZ_VL*-
zV{eYFj9*tSRO(mi^sDtIaid|aUb|eaUaV9tR;ib3^`Zuow3(H)u+kQjsEL)dFk-Ua
z!OA*$MHeS)H!HeG^GSRC?9-t6g`a!sHa_&2o&>m8Ve|XA{d2-O6t#UKC2ai=G`}Ou
znEg}S@i|5c>>W97#9^bKY@}=81N?)vf=qziByG=l65$e%7>~WA?Jl
zZl3$L?F!kKVlL5En&02B@2^|-*UbkTmV-?zlrQ$Z4I3%@oA!eZ8!6w&3MpS4-@Z7>
z#=TA3{ulD6bAKK7l3nB?d+WBnJSkSPai462Ymy7vzkPL)BM&y6-@ZD(eR1H`9AwKk
zS~i^r8;)8q=n^v+;?z=~h
z*`P;Spc)$vatgTu*3Aazk~%|yI`3~-NqxwXd+V0H4ePfp=hrM3b}nXu^4)doK4~Ca
zitM$*3c2-$eK$w`wC(0CyX3y4jc^5WebNb}yJ%OyDf?t^mfOp+q+|DTJp4)OL#_iA
zGegg8SoiUCsQkqQn-CmXHtip8LE-z
zceC6s97Ar(!!l>y&+~X|7Ea0YP}Z?SpjWYb*KJsBE3}1wr1DNtd?&Y&)S3ae9-ozX7|139yd6v~DKdvYR#TWDKNwhm#)OEwp+k!$ObcZ~{P=@;LgYowS~G5o}o}qr<{9gS{N~7=y=}Cvjx?z`GCkua)v&cnA&%*$bo2E_VrldYtU>x_>N$2wi>-0Io
zd7Hyo4bui54S0fJl4B)vEPUYPxq}>;NaRn3EWd4V2ODOxoldQTO*1Lv;2kp1Fi}Yb
zjC(oKQ3kRF#u{cFhckrCE5lC8NSZ^MOjfp2q|Rifk)@uNJuJIv9bMVa8p&tf9`p|b
zZA=?>(+1LTvYo7KC$&2%?RG-F6<2M=l{-oGZd$vaHPD{fPO87gC!}=H*sKY%0DDaUXGmxbpGW6qX
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