diff --git a/.codesearch/codesearch.db b/.codesearch/codesearch.db new file mode 100644 index 0000000..1ce69e1 Binary files /dev/null and b/.codesearch/codesearch.db differ diff --git a/backend/.env.example b/backend/.env.example index b79f8db..2115f5e 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -23,6 +23,13 @@ # Print every SQL query bun runs (bundebug). #DB_DEBUG=false +# --- Agent view (browse service) --- +# Identifies the server to sites it inspects; a fixed UA keeps responses +# comparable between runs. +#FETCH_USER_AGENT=LLM-Browser/0.1 (+https://git.k6n.net/mats/llm-browser; agent-view validator) +# Per-outbound-fetch timeout, redirects included. +#FETCH_TIMEOUT=15s + # --- OIDC auth (issuer: https://users.k6n.net) --- # Auth is ENABLED when OIDC_CLIENT_ID is set: /api/auth/login starts the # authorization-code + PKCE flow, /api/v1/* then requires the session cookie. diff --git a/backend/README.md b/backend/README.md index 7607281..1656c1f 100644 --- a/backend/README.md +++ b/backend/README.md @@ -74,6 +74,17 @@ and the API authenticates against the issuer at `OIDC_ISSUER` random one is generated per boot, invalidating all sessions on restart). `AUTH_SESSION_TTL` (default `168h`) bounds the session. +### Agent view (`/api/v1/browse`) + +`GET /api/v1/browse?url=` fetches the page server-side, +renders it as markdown (the way a text-only agent sees it), gathers +`/llms.txt`, `/llms-full.txt`, `/.well-known/llms.txt` and `/robots.txt` +from the site root, and returns the snapshot plus agent-readiness checks. +Companion files are fetched concurrently; each outbound request is bounded +by `FETCH_TIMEOUT` (default `15s`) and response bodies are capped at 2 MiB. +`FETCH_USER_AGENT` (default `LLM-Browser/0.1 (…)`) identifies the server to +inspected sites. + ## Layout ``` diff --git a/backend/cmd/api/main.go b/backend/cmd/api/main.go index f8f1391..c08ac6b 100644 --- a/backend/cmd/api/main.go +++ b/backend/cmd/api/main.go @@ -18,6 +18,7 @@ import ( "git.k6n.net/mats/fullstack-template/internal/api" "git.k6n.net/mats/fullstack-template/internal/auth" + "git.k6n.net/mats/fullstack-template/internal/browse" "git.k6n.net/mats/fullstack-template/internal/config" "git.k6n.net/mats/fullstack-template/internal/database" "git.k6n.net/mats/fullstack-template/internal/items" @@ -54,6 +55,13 @@ func run() error { svc := items.NewService(items.NewBunRepository(db)) + // The agent view fetches the open web; its politeness (UA) and pace + // (per-request timeout) come from config. + browseSvc := browse.NewService(browse.NewHTTPFetcher(browse.FetchOptions{ + UserAgent: cfg.FetchUserAgent, + Timeout: cfg.FetchTimeout, + })) + // OIDC is on when a client id is configured; without one the API runs // standalone (no /api/auth routes, /api/v1 unprotected) — see README. authDeps, err := configureAuth(logger, cfg) @@ -64,6 +72,7 @@ func run() error { handler := api.New(api.Deps{ Logger: logger, Items: svc, + Browse: browseSvc, DB: db, AllowedOrigins: cfg.AllowedOrigins, Auth: authDeps, diff --git a/backend/go.mod b/backend/go.mod index 9fe34d4..2acb12f 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -11,6 +11,7 @@ require ( github.com/uptrace/bun/driver/pgdriver v1.2.18 github.com/uptrace/bun/driver/sqliteshim v1.2.18 github.com/uptrace/bun/extra/bundebug v1.2.18 + golang.org/x/net v0.61.0 golang.org/x/oauth2 v0.37.0 ) @@ -32,9 +33,9 @@ require ( github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect go.opentelemetry.io/otel v1.40.0 // indirect go.opentelemetry.io/otel/trace v1.40.0 // indirect - golang.org/x/crypto v0.48.0 // indirect + golang.org/x/crypto v0.58.0 // indirect golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect - golang.org/x/sys v0.41.0 // indirect + golang.org/x/sys v0.49.0 // indirect mellium.im/sasl v0.3.2 // indirect modernc.org/libc v1.68.0 // indirect modernc.org/mathutil v1.7.1 // indirect diff --git a/backend/go.sum b/backend/go.sum index fa1aace..3082f52 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -60,19 +60,21 @@ go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms= go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g= go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw= go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= +golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54= +golang.org/x/crypto v0.58.0/go.mod h1:Xh+kl5A+M0gMiWDytH2Hhr5Z7WbNCpv/eB/EFgfSk+w= golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0= golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA= golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8= golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w= +golang.org/x/net v0.61.0 h1:RR+6j/BTBCrggOLugxa+66R8FvoN6MHlzDlZIbN9YFw= +golang.org/x/net v0.61.0/go.mod h1:WgDCOTH8iwtB66T4/GfI94AHo/hhdb7Hah9NDseQfiI= golang.org/x/oauth2 v0.37.0 h1:JUlcxA8oAtauLfiH8FX2/FkAWHAdi0QtGCGc+hofE98= golang.org/x/oauth2 v0.37.0/go.mod h1:IxwZNxUULJmpBFf9K/9NTMSIfZZuvuTy1gGxhigP/58= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA= +golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og= golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k= golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/backend/internal/api/browse.go b/backend/internal/api/browse.go new file mode 100644 index 0000000..5dfb0a4 --- /dev/null +++ b/backend/internal/api/browse.go @@ -0,0 +1,49 @@ +package api + +import ( + "context" + "errors" + "log/slog" + "net/http" + "strings" + + "git.k6n.net/mats/fullstack-template/internal/browse" +) + +// browseHandler adapts HTTP requests to the browse service: read the url +// query parameter, call Inspect, map errors to the wire. No fetching or +// conversion logic lives here. +type browseHandler struct { + svc *browse.Service + logger *slog.Logger +} + +func (h *browseHandler) get(w http.ResponseWriter, r *http.Request) { + raw := strings.TrimSpace(r.URL.Query().Get("url")) + snap, err := h.svc.Inspect(r.Context(), raw) + if err != nil { + h.fail(w, err) + return + } + writeJSON(w, http.StatusOK, snap) +} + +// fail is the translation point from browse errors to the wire: +// *ValidationError → 400, *FetchError → 502 (the site is the problem), +// context deadline → 504, anything else → 500 (logged). +func (h *browseHandler) fail(w http.ResponseWriter, err error) { + var vErr *browse.ValidationError + var fErr *browse.FetchError + switch { + case errors.As(err, &vErr): + writeError(w, http.StatusBadRequest, "validation_failed", vErr.Error()) + case errors.As(err, &fErr): + h.logger.Info("browse fetch failed", "url", fErr.URL, "err", fErr.Err) + writeError(w, http.StatusBadGateway, "unavailable", "could not fetch "+fErr.URL) + case errors.Is(err, context.DeadlineExceeded): + writeError(w, http.StatusGatewayTimeout, "timeout", "the site took too long to answer") + default: + h.logger.Error("browse failed", "err", err) + writeError(w, http.StatusInternalServerError, "internal_error", "an internal error occurred") + } +} diff --git a/backend/internal/api/server.go b/backend/internal/api/server.go index d9c0780..a3f361e 100644 --- a/backend/internal/api/server.go +++ b/backend/internal/api/server.go @@ -9,6 +9,7 @@ import ( "strings" "time" + "git.k6n.net/mats/fullstack-template/internal/browse" "git.k6n.net/mats/fullstack-template/internal/items" ) @@ -21,6 +22,7 @@ type Pinger interface { type Deps struct { Logger *slog.Logger Items *items.Service + Browse *browse.Service DB Pinger AllowedOrigins []string RequestTimeout time.Duration // zero means the 30s default @@ -54,6 +56,7 @@ func New(deps Deps) http.Handler { logger: deps.Logger, db: deps.DB, items: &itemHandler{svc: deps.Items, logger: deps.Logger}, + browse: &browseHandler{svc: deps.Browse, logger: deps.Logger}, auth: authH, } @@ -80,6 +83,10 @@ func New(deps Deps) http.Handler { mux.HandleFunc("PATCH /api/v1/items/{id}", s.items.update) mux.HandleFunc("DELETE /api/v1/items/{id}", s.items.delete) + // Agent view: renders a remote page the way a text-only agent sees it. + // The URL comes in via query parameter, so the response is a plain GET. + mux.HandleFunc("GET /api/v1/browse", s.browse.get) + // The wrapper keeps the mux's automatic 405 + Allow responses for // wrong-method requests and renders all unmatched routes as JSON 404s // (the mux default is plain text). @@ -99,6 +106,7 @@ type server struct { logger *slog.Logger db Pinger items *itemHandler + browse *browseHandler auth *authHandler } diff --git a/backend/internal/api/server_test.go b/backend/internal/api/server_test.go index 71b1e52..9d8aae3 100644 --- a/backend/internal/api/server_test.go +++ b/backend/internal/api/server_test.go @@ -15,6 +15,7 @@ import ( "time" "git.k6n.net/mats/fullstack-template/internal/api" + "git.k6n.net/mats/fullstack-template/internal/browse" "git.k6n.net/mats/fullstack-template/internal/items" ) @@ -293,3 +294,100 @@ func TestCORSPreflight(t *testing.T) { t.Errorf("Allow-Origin for unknown origin = %q, want none", got) } } + +// fakeFetcher is the same in-memory browse.Fetcher as +// internal/browse/service_test.go, duplicated on purpose: test fakes stay +// package-local. A nil response simulates a connection failure. +type fakeFetcher struct { + pages map[string]*browse.Response +} + +func (f fakeFetcher) Fetch(_ context.Context, url string) (*browse.Response, error) { + r, ok := f.pages[url] + if !ok { + return &browse.Response{Status: 404, FinalURL: url, ContentType: "text/plain", Body: []byte("not found")}, nil + } + if r == nil { + return nil, &browse.FetchError{URL: url, Err: errors.New("dial tcp: connection refused")} + } + return r, nil +} + +func newBrowseTestServer(t *testing.T) (http.Handler, fakeFetcher) { + t.Helper() + pages := map[string]*browse.Response{} + add := func(url, ct, body string) { + pages[url] = &browse.Response{Status: 200, FinalURL: url, ContentType: ct, Body: []byte(body)} + } + add("https://site.test/", "text/html; charset=utf-8", + `Site`+ + `

Hello

docs

`) + add("https://site.test/llms.txt", "text/markdown", "# Site\n\n> summary\n\n## Docs\n\n- [Docs](https://site.test/docs): the docs\n") + add("https://site.test/robots.txt", "text/plain", "User-agent: *\nAllow: /\n") + return api.New(api.Deps{ + Logger: slog.New(slog.NewTextHandler(io.Discard, nil)), + Items: items.NewService(newFakeRepo()), + Browse: browse.NewService(fakeFetcher{pages: pages}), + DB: stubPinger{}, + AllowedOrigins: []string{"http://localhost:5173"}, + }), fakeFetcher{pages: pages} +} + +func TestBrowseEndpoint(t *testing.T) { + h, _ := newBrowseTestServer(t) + + rec := do(t, h, http.MethodGet, `/api/v1/browse?url=https%3A%2F%2Fsite.test%2F`, "") + if rec.Code != http.StatusOK { + t.Fatalf("browse = %d: %s", rec.Code, rec.Body.String()) + } + var snap browse.Snapshot + decodeBody(t, rec, &snap) + if snap.FinalURL != "https://site.test/" || snap.Status != 200 { + t.Errorf("snapshot head = %d %s", snap.Status, snap.FinalURL) + } + if snap.Page == nil || snap.Page.Title != "Site" { + t.Errorf("page = %+v", snap.Page) + } + if !strings.Contains(snap.Markdown, "# Hello") || !strings.Contains(snap.Markdown, "[docs](https://site.test/docs)") { + t.Errorf("markdown = %q", snap.Markdown) + } + if snap.Files.LlmsTxt == nil || !strings.Contains(snap.Files.LlmsTxt.Content, "# Site") { + t.Errorf("llms.txt = %+v", snap.Files.LlmsTxt) + } + if len(snap.Checks) == 0 { + t.Error("checks empty") + } + // Bare-domain input normalizes to https on the wire. + rec = do(t, h, http.MethodGet, `/api/v1/browse?url=site.test`, "") + if rec.Code != http.StatusOK { + t.Fatalf("bare domain = %d: %s", rec.Code, rec.Body.String()) + } +} + +func TestBrowseEndpointErrors(t *testing.T) { + h, fetcher := newBrowseTestServer(t) + + // Missing and malformed input map to validation_failed. + for _, target := range []string{"/api/v1/browse", "/api/v1/browse?url=", "/api/v1/browse?url=ftp://x.test"} { + rec := do(t, h, http.MethodGet, target, "") + if rec.Code != http.StatusBadRequest { + t.Errorf("GET %s = %d, want 400: %s", target, rec.Code, rec.Body.String()) + } + } + + // A dead site maps to 502 unavailable. + fetcher.pages["https://dead.test/"] = nil + rec := do(t, h, http.MethodGet, `/api/v1/browse?url=https%3A%2F%2Fdead.test%2F`, "") + if rec.Code != http.StatusBadGateway { + t.Errorf("dead site = %d, want 502: %s", rec.Code, rec.Body.String()) + } + var errBody struct { + Error struct { + Code string `json:"code"` + } `json:"error"` + } + decodeBody(t, rec, &errBody) + if errBody.Error.Code != "unavailable" { + t.Errorf("error code = %q, want unavailable", errBody.Error.Code) + } +} diff --git a/backend/internal/browse/fetcher.go b/backend/internal/browse/fetcher.go new file mode 100644 index 0000000..0ed1d62 --- /dev/null +++ b/backend/internal/browse/fetcher.go @@ -0,0 +1,95 @@ +package browse + +import ( + "context" + "io" + "net/http" + "time" +) + +// Defaults applied when the FetchOptions field is left zero. +const ( + // DefaultUserAgent announces the agent view; sites can see what is + // browsing them and serve it like any other text agent. + DefaultUserAgent = "LLM-Browser/0.1 (+https://git.k6n.net/mats/llm-browser; agent-view validator)" + // DefaultFetchTimeout bounds one remote request, redirects included. + DefaultFetchTimeout = 15 * time.Second + // DefaultMaxBodySize caps how much of a response is read (2 MiB). + DefaultMaxBodySize = 2 << 20 +) + +// FetchOptions configures an HTTPFetcher. Zero fields fall back to the +// matching Default* constant. +type FetchOptions struct { + UserAgent string + Timeout time.Duration + MaxBodySize int64 +} + +// HTTPFetcher is the production Fetcher: one shared client, a fixed +// user agent, and a hard cap on response bodies. +type HTTPFetcher struct { + client *http.Client + opts FetchOptions +} + +// NewHTTPFetcher wires the fetcher. The client follows the standard +// redirect policy (up to 10 hops); each request is bounded by opts.Timeout. +func NewHTTPFetcher(opts FetchOptions) *HTTPFetcher { + if opts.Timeout <= 0 { + opts.Timeout = DefaultFetchTimeout + } + if opts.MaxBodySize <= 0 { + opts.MaxBodySize = DefaultMaxBodySize + } + if opts.UserAgent == "" { + opts.UserAgent = DefaultUserAgent + } + return &HTTPFetcher{ + client: &http.Client{Timeout: opts.Timeout}, + opts: opts, + } +} + +// Fetch performs a GET and reads at most MaxBodySize bytes. Transport +// failures and read failures both come back as *FetchError. +func (f *HTTPFetcher) Fetch(ctx context.Context, raw string) (*Response, error) { + req, err := http.NewRequestWithContext(ctx, http.MethodGet, raw, nil) + if err != nil { + return nil, &FetchError{URL: raw, Err: err} + } + req.Header.Set("User-Agent", f.opts.UserAgent) + req.Header.Set("Accept", "text/html,application/xhtml+xml,text/markdown,text/plain;q=0.9,*/*;q=0.8") + + resp, err := f.client.Do(req) + if err != nil { + return nil, &FetchError{URL: raw, Err: err} + } + defer resp.Body.Close() + + body, truncated, err := readCapped(resp.Body, f.opts.MaxBodySize) + if err != nil { + return nil, &FetchError{URL: raw, Err: err} + } + return &Response{ + Status: resp.StatusCode, + FinalURL: resp.Request.URL.String(), + ContentType: resp.Header.Get("Content-Type"), + Header: resp.Header, + Body: body, + Truncated: truncated, + }, nil +} + +// readCapped reads r fully, stopping at max bytes; the second result +// reports whether content beyond max was discarded. +func readCapped(r io.Reader, max int64) ([]byte, bool, error) { + body, err := io.ReadAll(io.LimitReader(r, max+1)) + if err != nil { + return nil, false, err + } + if int64(len(body)) > max { + return body[:max], true, nil + } + return body, false, nil +} diff --git a/backend/internal/browse/llmstxt.go b/backend/internal/browse/llmstxt.go new file mode 100644 index 0000000..f88359c --- /dev/null +++ b/backend/internal/browse/llmstxt.go @@ -0,0 +1,70 @@ +package browse + +import ( + "regexp" + "strings" +) + +// llmsLinkRe matches `- [title](url): description` (the optional quoted +// title and the optional description are both per spec). +var llmsLinkRe = regexp.MustCompile(`^\s*[-*]\s+\[([^\]]*)\]\(([^)\s]+)(?:\s+"[^"]*")?\)\s*(?::\s*(.*))?$`) + +// parseLlmsTxt parses an llms.txt document per llmstxt.org: +// +// # Title (required, exactly once, first) +// > Summary (optional blockquote) +// ## Section (optional, starts a curated list) +// > Section note (optional, directly after the heading) +// - [Link](https://…): what it is +// +// Everything that is not one of those shapes is ignored — the parsed doc +// describes what an agent can rely on, not everything the file contains. +func parseLlmsTxt(content string) *LlmsDoc { + doc := &LlmsDoc{Sections: []LlmsSection{}} + var section *LlmsSection + seenTitle := false + + for _, line := range strings.Split(content, "\n") { + t := strings.TrimSpace(line) + switch { + case strings.HasPrefix(t, "# ") && !seenTitle: + doc.Title = strings.TrimSpace(t[2:]) + seenTitle = true + case strings.HasPrefix(t, "## "): + doc.Sections = append(doc.Sections, LlmsSection{ + Heading: strings.TrimSpace(t[3:]), + Links: []LlmsLink{}, + }) + section = &doc.Sections[len(doc.Sections)-1] + case strings.HasPrefix(t, ">"): + note := strings.TrimSpace(strings.TrimLeft(t, "> ")) + if note == "" { + continue + } + switch { + case !seenTitle: + continue // blockquote before the title is not the summary + case section != nil && section.Description == "": + section.Description = note + case section == nil: + if doc.Description != "" { + doc.Description += " " + } + doc.Description += note + } + default: + m := llmsLinkRe.FindStringSubmatch(line) + if m == nil { + continue + } + link := LlmsLink{Title: m[1], URL: m[2], Description: strings.TrimSpace(m[3])} + if section == nil { + doc.Sections = append(doc.Sections, LlmsSection{Links: []LlmsLink{}}) + section = &doc.Sections[len(doc.Sections)-1] + } + section.Links = append(section.Links, link) + doc.LinkCount++ + } + } + return doc +} diff --git a/backend/internal/browse/markdown.go b/backend/internal/browse/markdown.go new file mode 100644 index 0000000..5a6e8ba --- /dev/null +++ b/backend/internal/browse/markdown.go @@ -0,0 +1,565 @@ +package browse + +import ( + "net/url" + "regexp" + "strconv" + "strings" + + "golang.org/x/net/html" + "golang.org/x/net/html/atom" +) + +// pageMeta is what agents read from plus document shape statistics +// collected while walking the body. +type pageMeta struct { + Title string + Description string + Canonical string + Robots string + Lang string + H1 string + LinkCount int + DeadLinks int + ScriptCount int + ImageCount int + WordCount int + TextLength int +} + +// maxMarkdownChars caps the converted markdown before it reaches the wire. +const maxMarkdownChars = 200_000 + +var ( + hiddenStyleRe = regexp.MustCompile(`(?i)display\s*:\s*none|visibility\s*:\s*hidden`) + wsRe = regexp.MustCompile(`\s+`) + manyNlRe = regexp.MustCompile(`\n{3,}`) +) + +// htmlToMarkdown parses the document once and returns the body rendered as +// markdown plus the head metadata. baseURL resolves relative links. +func htmlToMarkdown(body []byte, baseURL string) (string, pageMeta, error) { + var meta pageMeta + doc, err := html.Parse(strings.NewReader(string(body))) + if err != nil { + return "", meta, err + } + + var htmlNode, bodyNode *html.Node + var walk func(n *html.Node) + walk = func(n *html.Node) { + for c := n.FirstChild; c != nil; c = c.NextSibling { + if c.Type != html.ElementNode { + continue + } + switch c.DataAtom { + case atom.Html: + htmlNode = c + walk(c) + case atom.Head: + collectHead(c, &meta) + case atom.Body: + bodyNode = c + } + } + } + walk(doc) + if htmlNode != nil { + meta.Lang = attr(htmlNode, "lang") + } + if bodyNode != nil { + inspectBody(bodyNode, &meta) + } + + r := &mdRenderer{base: parseBase(baseURL)} + return r.renderBody(bodyNode), meta, nil +} + +// collectHead reads title, description, robots and canonical from . +func collectHead(head *html.Node, meta *pageMeta) { + for c := head.FirstChild; c != nil; c = c.NextSibling { + if c.Type != html.ElementNode { + continue + } + switch c.DataAtom { + case atom.Title: + if meta.Title == "" { + meta.Title = collapse(textContent(c)) + } + case atom.Meta: + content := collapse(attr(c, "content")) + switch strings.ToLower(attr(c, "name")) { + case "description": + if meta.Description == "" { + meta.Description = content + } + case "robots": + if meta.Robots == "" { + meta.Robots = content + } + } + case atom.Link: + if strings.EqualFold(attr(c, "rel"), "canonical") && meta.Canonical == "" { + meta.Canonical = attr(c, "href") + } + } + } +} + +// inspectBody counts the elements checks care about and measures the +// visible text (script/style/svg content stays out of the count). +func inspectBody(body *html.Node, meta *pageMeta) { + var walk func(n *html.Node) + walk = func(n *html.Node) { + if n.Type == html.ElementNode { + switch n.DataAtom { + case atom.A: + href := strings.TrimSpace(attr(n, "href")) + if href == "" || strings.HasPrefix(href, "#") || strings.HasPrefix(strings.ToLower(href), "javascript:") { + meta.DeadLinks++ + } else { + meta.LinkCount++ + } + case atom.Script: + meta.ScriptCount++ + return + case atom.Style, atom.Svg, atom.Noscript, atom.Template, atom.Iframe: + return + case atom.Img: + meta.ImageCount++ + return + case atom.H1: + if meta.H1 == "" { + meta.H1 = collapse(textContent(n)) + } + } + } + if n.Type == html.TextNode { + meta.TextLength += len(n.Data) + meta.WordCount += len(strings.Fields(n.Data)) + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + walk(c) + } + } + walk(body) +} + +// mdRenderer renders a parsed document as markdown. +type mdRenderer struct { + base *url.URL +} + +func (r *mdRenderer) renderBody(body *html.Node) string { + if body == nil { + return "" + } + var b strings.Builder + r.blocks(&b, body) + out := strings.TrimSpace(b.String()) + return manyNlRe.ReplaceAllString(out, "\n\n") +} + +// skipped reports whether an element contributes nothing an agent could +// act on: invisible content, script payloads, and embedded documents. +func skipped(n *html.Node) bool { + if n.Type != html.ElementNode { + return false + } + switch n.DataAtom { + case atom.Script, atom.Style, atom.Noscript, atom.Template, atom.Svg, + atom.Head, atom.Link, atom.Meta, atom.Iframe, atom.Object, atom.Embed: + return true + } + if hasAttr(n, "hidden") || strings.EqualFold(attr(n, "aria-hidden"), "true") { + return true + } + return hiddenStyleRe.MatchString(attr(n, "style")) +} + +// blocks renders the children of n as a sequence of markdown blocks. +func (r *mdRenderer) blocks(b *strings.Builder, n *html.Node) { + for c := n.FirstChild; c != nil; c = c.NextSibling { + if skipped(c) { + continue + } + switch { + case c.Type == html.TextNode: + if s := strings.TrimSpace(collapse(c.Data)); s != "" { + b.WriteString(s + "\n\n") + } + case c.Type == html.ElementNode: + r.element(b, c) + } + } +} + +// element renders one block-level element. +func (r *mdRenderer) element(b *strings.Builder, n *html.Node) { + switch n.DataAtom { + case atom.H1, atom.H2, atom.H3, atom.H4, atom.H5, atom.H6: + level := int(n.DataAtom) - int(atom.H1) + 1 + b.WriteString(strings.Repeat("#", level) + " " + strings.TrimSpace(r.inline(n)) + "\n\n") + case atom.P: + if s := strings.TrimSpace(r.inline(n)); s != "" { + b.WriteString(s + "\n\n") + } + case atom.Hr: + b.WriteString("---\n\n") + case atom.Blockquote: + var inner strings.Builder + r.blocks(&inner, n) + b.WriteString(prefixLines(inner.String(), "> ")) + case atom.Pre: + b.WriteString("```\n" + strings.Trim(textContent(n), "\n") + "\n```\n\n") + case atom.Ul, atom.Ol: + var lb strings.Builder + r.list(&lb, n, "") + b.WriteString(strings.TrimRight(lb.String(), "\n") + "\n\n") + case atom.Table: + r.table(b, n) + case atom.Dl: + r.defList(b, n) + case atom.Button, atom.A, atom.Span, atom.Strong, atom.Em, atom.Code, atom.Small, atom.Label: + // phrasing content at block position: keep it as its own paragraph + if s := strings.TrimSpace(r.inline(n)); s != "" { + b.WriteString(s + "\n\n") + } + default: + r.blocks(b, n) + } +} + +// list renders ul/ol items; nested lists indent under their item. +func (r *mdRenderer) list(b *strings.Builder, n *html.Node, indent string) { + ordered := n.DataAtom == atom.Ol + index := 1 + if v := attr(n, "start"); v != "" { + if i, err := strconv.Atoi(v); err == nil && i > 0 { + index = i + } + } + for li := n.FirstChild; li != nil; li = li.NextSibling { + if li.Type != html.ElementNode || li.DataAtom != atom.Li { + continue + } + marker := "- " + if ordered { + marker = strconv.Itoa(index) + ". " + index++ + } + var text strings.Builder + var nested []*html.Node + for c := li.FirstChild; c != nil; c = c.NextSibling { + if skipped(c) { + continue + } + if c.Type == html.ElementNode && (c.DataAtom == atom.Ul || c.DataAtom == atom.Ol) { + nested = append(nested, c) + continue + } + if c.Type == html.TextNode { + text.WriteString(collapse(c.Data)) + } else { + text.WriteString(r.inline(c)) + } + } + if item := strings.TrimSpace(text.String()); item != "" { + b.WriteString(indent + marker + item + "\n") + } + for _, sub := range nested { + var nb strings.Builder + r.list(&nb, sub, indent+" ") + b.WriteString(strings.TrimRight(nb.String(), "\n") + "\n") + } + } +} + +// table renders a GFM pipe table; the first header row (th, else the first +// tr) becomes the table head. +func (r *mdRenderer) table(b *strings.Builder, n *html.Node) { + var header []string + var rows [][]string + collectRows := func(scope *html.Node) { + for tr := scope.FirstChild; tr != nil; tr = tr.NextSibling { + if tr.Type != html.ElementNode || tr.DataAtom != atom.Tr { + continue + } + var cells []string + isHeader := false + for cell := tr.FirstChild; cell != nil; cell = cell.NextSibling { + if cell.Type != html.ElementNode { + continue + } + switch cell.DataAtom { + case atom.Th: + isHeader = true + cells = append(cells, r.cell(cell)) + case atom.Td: + cells = append(cells, r.cell(cell)) + } + } + if len(cells) == 0 { + continue + } + if isHeader && header == nil { + header = cells + } else { + rows = append(rows, cells) + } + } + } + hasSections := false + for c := n.FirstChild; c != nil; c = c.NextSibling { + if c.Type != html.ElementNode { + continue + } + switch c.DataAtom { + case atom.Thead, atom.Tbody, atom.Tfoot: + hasSections = true + collectRows(c) + } + } + if !hasSections { + collectRows(n) // table with bare rows + } + if header == nil && len(rows) > 0 { + header, rows = rows[0], rows[1:] + } + cols := len(header) + for _, row := range rows { + if len(row) > cols { + cols = len(row) + } + } + if cols == 0 { + return + } + pad := func(row []string) []string { + out := make([]string, cols) + copy(out, row) + return out + } + b.WriteString("| " + strings.Join(pad(header), " | ") + " |\n") + b.WriteString("|" + strings.Repeat(" --- |", cols) + "\n") + for _, row := range rows { + b.WriteString("| " + strings.Join(pad(row), " | ") + " |\n") + } + b.WriteString("\n") +} + +// defList renders dt as a bold term and dd as its paragraph. +func (r *mdRenderer) defList(b *strings.Builder, n *html.Node) { + for c := n.FirstChild; c != nil; c = c.NextSibling { + if c.Type != html.ElementNode { + continue + } + switch c.DataAtom { + case atom.Dt: + if s := strings.TrimSpace(r.inline(c)); s != "" { + b.WriteString("**" + s + "**\n\n") + } + case atom.Dd: + if s := strings.TrimSpace(r.inline(c)); s != "" { + b.WriteString(s + "\n\n") + } + } + } +} + +// cell flattens one table cell to a single line. +func (r *mdRenderer) cell(n *html.Node) string { + s := strings.TrimSpace(r.inline(n)) + return strings.ReplaceAll(s, "|", "\\|") +} + +// inline renders phrasing content to a markdown string. +func (r *mdRenderer) inline(n *html.Node) string { + var b strings.Builder + r.inlineInto(&b, n) + return b.String() +} + +func (r *mdRenderer) inlineInto(b *strings.Builder, n *html.Node) { + for c := n.FirstChild; c != nil; c = c.NextSibling { + if skipped(c) { + continue + } + switch { + case c.Type == html.TextNode: + b.WriteString(collapse(c.Data)) + case c.Type == html.ElementNode: + r.inlineElement(b, c) + } + } +} + +func (r *mdRenderer) inlineElement(b *strings.Builder, n *html.Node) { + switch n.DataAtom { + case atom.A: + label := strings.TrimSpace(r.inline(n)) + if label == "" { + label = attr(n, "href") + } + href := strings.TrimSpace(attr(n, "href")) + lower := strings.ToLower(href) + if href == "" || strings.HasPrefix(href, "#") || strings.HasPrefix(lower, "javascript:") { + // an agent cannot follow these; keep the text only + b.WriteString(label) + return + } + b.WriteString("[" + label + "](" + r.resolve(href) + ")") + case atom.Img: + src := strings.TrimSpace(attr(n, "src")) + if src == "" { + return + } + alt := collapse(attr(n, "alt")) + if alt == "" { + alt = baseName(src) + } + b.WriteString("![" + alt + "](" + r.resolve(src) + ")") + case atom.Br: + b.WriteString("\n") + case atom.Hr: + b.WriteString("\n---\n") + case atom.Strong, atom.B: + b.WriteString("**" + strings.TrimSpace(r.inline(n)) + "**") + case atom.Em, atom.I: + b.WriteString("*" + strings.TrimSpace(r.inline(n)) + "*") + case atom.Del, atom.S: + b.WriteString("~~" + strings.TrimSpace(r.inline(n)) + "~~") + case atom.Code: + b.WriteString("`" + strings.TrimSpace(r.inline(n)) + "`") + case atom.Summary: + b.WriteString("**" + strings.TrimSpace(r.inline(n)) + "** ") + case atom.Input, atom.Select, atom.Textarea, atom.Form: + // form controls have no markdown meaning an agent can act on + default: + if blockish[n.DataAtom] { + // block-level content inside inline context (nav menus, divs in + // paragraphs): keep the words from running together + padInline(b) + r.inlineInto(b, n) + padInline(b) + return + } + r.inlineInto(b, n) + } +} + +// blockish marks elements a browser starts on a fresh line; adjacent ones +// need separating whitespace once flattened to inline text. +var blockish = map[atom.Atom]bool{ + atom.Div: true, atom.Ul: true, atom.Ol: true, atom.Li: true, atom.Nav: true, + atom.Section: true, atom.Article: true, atom.Header: true, atom.Footer: true, + atom.Aside: true, atom.Main: true, atom.Form: true, atom.Fieldset: true, + atom.Figure: true, atom.P: true, atom.Table: true, atom.Tr: true, +} + +func padInline(b *strings.Builder) { + s := b.String() + if s == "" { + return + } + if last := s[len(s)-1]; last != ' ' && last != '\n' { + b.WriteByte(' ') + } +} + +// resolve turns href into an absolute URL against the inspected page. +func (r *mdRenderer) resolve(href string) string { + if r.base == nil { + return href + } + u, err := url.Parse(href) + if err != nil { + return href + } + return r.base.ResolveReference(u).String() +} + +func parseBase(raw string) *url.URL { + u, err := url.Parse(raw) + if err != nil { + return nil + } + return u +} + +// collapse flattens whitespace runs to single spaces. +func collapse(s string) string { return wsRe.ReplaceAllString(s, " ") } + +// textContent returns the raw concatenated text under n. +func textContent(n *html.Node) string { + var b strings.Builder + var walk func(n *html.Node) + walk = func(n *html.Node) { + if n.Type == html.TextNode { + b.WriteString(n.Data) + } + for c := n.FirstChild; c != nil; c = c.NextSibling { + walk(c) + } + } + walk(n) + return b.String() +} + +func prefixLines(s, prefix string) string { + lines := strings.Split(strings.TrimRight(s, "\n"), "\n") + for i, line := range lines { + if line == "" { + lines[i] = strings.TrimRight(prefix, " ") + continue + } + lines[i] = prefix + line + } + return strings.Join(lines, "\n") + "\n\n" +} + +func baseName(src string) string { + s := src + if i := strings.IndexAny(s, "?#"); i >= 0 { + s = s[:i] + } + if i := strings.LastIndex(s, "/"); i >= 0 { + s = s[i+1:] + } + if s == "" { + return "image" + } + return s +} + +func attr(n *html.Node, key string) string { + for _, a := range n.Attr { + if a.Key == key { + return a.Val + } + } + return "" +} + +func hasAttr(n *html.Node, key string) bool { + for _, a := range n.Attr { + if a.Key == key { + return true + } + } + return false +} + +// truncateMarkdown caps markdown at max chars without splitting a rune. +func truncateMarkdown(md string, max int) (string, bool) { + if len(md) <= max { + return md, false + } + // step back to a rune boundary so the cut stays valid UTF-8 + for i := max; i > max-4 && i > 0; i-- { + if (md[i] & 0xC0) != 0x80 { + return md[:i], true + } + } + return md[:max], true +} diff --git a/backend/internal/browse/markdown_test.go b/backend/internal/browse/markdown_test.go new file mode 100644 index 0000000..db178a4 --- /dev/null +++ b/backend/internal/browse/markdown_test.go @@ -0,0 +1,120 @@ +package browse + +// Internal test: it pins the unexported converter's exact output so +// formatting drift is caught by the package itself. +import ( + "strings" + "testing" +) + +func TestHTMLToMarkdown(t *testing.T) { + t.Parallel() + cases := []struct { + name string + html string + want string + }{ + { + name: "headings and paragraphs", + html: `

Title

First.

Second bold and italic.

`, + want: "# Title\n\nFirst.\n\nSecond **bold** and *italic*.", + }, + { + name: "relative links resolve against the page", + html: `

Guide and abs

`, + want: "[Guide](https://page.test/docs/guide) and [abs](https://abs.test/x)", + }, + { + name: "dead links keep their text only", + html: `

top go

`, + want: "top go", + }, + { + name: "lists nest and order", + html: ``, + want: "- one\n- two\n 3. deep", + }, + { + name: "blockquote prefixes every line", + html: `

line one

line two

`, + want: "> line one\n>\n> line two", + }, + { + name: "pre renders as a fenced block", + html: `
keep
+  spacing
`, + want: "```\nkeep\n spacing\n```", + }, + { + name: "tables render GFM", + html: `` + + `
NameSize
a|b1
`, + want: "| Name | Size |\n| --- | --- |\n| a\\|b | 1 |", + }, + { + name: "script, style and hidden content vanish", + html: `` + + `

visible

`, + want: "visible", + }, + { + name: "images keep alt text", + html: `

Logo and

`, + want: "![Logo](https://page.test/img/logo.png) and ![x.png](https://page.test/img/x.png)", + }, + { + name: "consecutive blocks collapse to one blank line", + html: `

a

b

`, + want: "a\n\nb", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + got, _, err := htmlToMarkdown([]byte(tc.html), "https://page.test/") + if err != nil { + t.Fatalf("htmlToMarkdown: %v", err) + } + if got != tc.want { + t.Errorf("markdown =\n%q\nwant\n%q", got, tc.want) + } + }) + } +} + +func TestHTMLToMarkdownMetadata(t *testing.T) { + t.Parallel() + html := ` + Meta sidan + + + + +

Rubrik

+

lite text att räkna

+ y + ` + + _, meta, err := htmlToMarkdown([]byte(html), "https://page.test/") + if err != nil { + t.Fatalf("htmlToMarkdown: %v", err) + } + if meta.Title != "Meta sidan" || meta.Description != "Beskrivning." { + t.Errorf("head metadata wrong: %+v", meta) + } + if meta.Lang != "sv" || meta.Canonical != "https://page.test/canon" { + t.Errorf("lang/canonical wrong: %+v", meta) + } + if meta.H1 != "Rubrik" { + t.Errorf("h1 = %q", meta.H1) + } + if meta.WordCount != 5 || meta.TextLength == 0 { + t.Errorf("text stats wrong: words=%d chars=%d", meta.WordCount, meta.TextLength) + } + if meta.ScriptCount != 1 || meta.ImageCount != 1 { + t.Errorf("element counts wrong: %+v", meta) + } + if !strings.Contains(strings.ToLower(meta.Robots), "noai") { + t.Errorf("robots = %q", meta.Robots) + } +} diff --git a/backend/internal/browse/model.go b/backend/internal/browse/model.go new file mode 100644 index 0000000..0094628 --- /dev/null +++ b/backend/internal/browse/model.go @@ -0,0 +1,146 @@ +// Package browse renders a remote page the way a text-only agent sees it: +// it fetches the URL, converts the HTML to markdown, gathers the llms.txt +// companions and robots.txt, and reports agent-readiness checks. The +// package is stateless — the Fetcher is its only collaborator. +package browse + +import ( + "context" + "net/http" + "time" +) + +// ValidationError reports an invalid input value. Handlers map it to 400. +type ValidationError struct { + Field string + Reason string +} + +func (e *ValidationError) Error() string { return e.Field + ": " + e.Reason } + +// FetchError reports a remote fetch that failed before an answer arrived +// (DNS, TLS, connection refused, …). Handlers map it to 502 — the inspected +// site is the problem, not this service. +type FetchError struct { + URL string + Err error +} + +func (e *FetchError) Error() string { return "fetch " + e.URL + ": " + e.Err.Error() } +func (e *FetchError) Unwrap() error { return e.Err } + +// Severity classifies a Check. +type Severity string + +const ( + SeverityOK Severity = "ok" + SeverityInfo Severity = "info" + SeverityWarn Severity = "warn" + SeverityError Severity = "error" +) + +// Check is one validated aspect of the inspected site, written so a human +// can act on the detail without reading this package. +type Check struct { + ID string `json:"id"` + Label string `json:"label"` + Severity Severity `json:"severity"` + Detail string `json:"detail"` +} + +// Response is a capped remote fetch result. +type Response struct { + Status int + FinalURL string // after redirects; empty means "same as requested" + ContentType string + Header http.Header + Body []byte + Truncated bool +} + +// Fetcher retrieves remote documents. It plays the role the Repository +// interface plays for database-backed resources: the service depends on the +// interface, tests substitute an in-memory fake. +type Fetcher interface { + Fetch(ctx context.Context, url string) (*Response, error) +} + +// PageView is what agents read out of the HTML head plus document shape +// statistics that drive the checks. +type PageView struct { + Title string `json:"title"` + Description string `json:"description"` + Canonical string `json:"canonical"` + RobotsMeta string `json:"robotsMeta"` + Lang string `json:"lang"` + H1 string `json:"h1"` + LinkCount int `json:"linkCount"` + DeadLinks int `json:"deadLinks"` + ScriptCount int `json:"scriptCount"` + ImageCount int `json:"imageCount"` + WordCount int `json:"wordCount"` + TextLength int `json:"textLength"` +} + +// LlmsLink is one `- [title](url): description` entry of an llms.txt file. +type LlmsLink struct { + Title string `json:"title"` + URL string `json:"url"` + Description string `json:"description"` +} + +// LlmsSection is one `## Heading` block of an llms.txt file. +type LlmsSection struct { + Heading string `json:"heading"` + Description string `json:"description"` + Links []LlmsLink `json:"links"` +} + +// LlmsDoc is a parsed llms.txt document per llmstxt.org: an H1 title, an +// optional blockquote summary, and optional H2 sections of curated links. +type LlmsDoc struct { + Title string `json:"title"` + Description string `json:"description"` + Sections []LlmsSection `json:"sections"` + LinkCount int `json:"linkCount"` +} + +// FileResult is the outcome of fetching one companion file. A Status of 0 +// means the request itself failed (see Error); 4xx/5xx keep the status but +// drop the content. +type FileResult struct { + URL string `json:"url"` + Status int `json:"status"` + ContentType string `json:"contentType"` + Error string `json:"error,omitempty"` + Content string `json:"content"` + Truncated bool `json:"truncated"` + LlmsDoc *LlmsDoc `json:"llmsDoc,omitempty"` +} + +// found reports whether the file exists and answered with content. +func (f *FileResult) found() bool { return f != nil && f.Status >= 200 && f.Status < 400 } + +// Files groups the companion documents fetched next to the page. +type Files struct { + LlmsTxt *FileResult `json:"llmsTxt"` + LlmsFullTxt *FileResult `json:"llmsFullTxt"` + WellKnownTxt *FileResult `json:"wellKnownLlmsTxt"` + RobotsTxt *FileResult `json:"robotsTxt"` +} + +// Snapshot is the full agent view of one URL: the rendered markdown, the +// companion documents, and the validation checks. +type Snapshot struct { + RequestedURL string `json:"requestedUrl"` + FinalURL string `json:"finalUrl"` + Status int `json:"status"` + ContentType string `json:"contentType"` + DurationMS int64 `json:"durationMs"` + FetchedAt time.Time `json:"fetchedAt"` + Page *PageView `json:"page,omitempty"` + Markdown string `json:"markdown"` + MarkdownTruncated bool `json:"markdownTruncated"` + Files Files `json:"files"` + Checks []Check `json:"checks"` +} diff --git a/backend/internal/browse/service.go b/backend/internal/browse/service.go new file mode 100644 index 0000000..7935351 --- /dev/null +++ b/backend/internal/browse/service.go @@ -0,0 +1,398 @@ +package browse + +import ( + "context" + "errors" + "fmt" + "net/url" + "strings" + "sync" + "time" +) + +// Tunables for the checks. +const ( + // jsShellTextChars: with fewer server-rendered characters than this + // next to real script traffic, the page probably needs JavaScript. + jsShellTextChars = 400 + // contextHeavyChars: markdown beyond this is a lot for one context. + contextHeavyChars = 150_000 +) + +// Companion paths, always resolved against the site root of the page. +const ( + llmsTxtPath = "/llms.txt" + llmsFullTxtPath = "/llms-full.txt" + wellKnownTxtPath = "/.well-known/llms.txt" + robotsTxtPath = "/robots.txt" +) + +// Service renders remote pages the way a text-only agent sees them. It is +// stateless; the Fetcher is its only collaborator. +type Service struct { + fetch Fetcher +} + +// NewService returns a Service over the given fetcher. +func NewService(fetch Fetcher) *Service { + return &Service{fetch: fetch} +} + +// Inspect fetches target (a bare domain or a full URL), converts the page +// to markdown, gathers the llms.txt companions and robots.txt in parallel, +// and assembles the agent-readiness checks. +func (s *Service) Inspect(ctx context.Context, raw string) (*Snapshot, error) { + target, err := NormalizeURL(raw) + if err != nil { + return nil, err + } + started := time.Now() + + page, err := s.fetch.Fetch(ctx, target) + if err != nil { + var fe *FetchError + if !errors.As(err, &fe) { + fe = &FetchError{URL: target, Err: err} + } + return nil, fe + } + + snap := &Snapshot{ + RequestedURL: target, + FinalURL: firstNonEmpty(page.FinalURL, target), + Status: page.Status, + ContentType: page.ContentType, + FetchedAt: time.Now().UTC(), + Checks: []Check{}, + } + + var meta pageMeta + switch { + case isHTML(page.ContentType, string(page.Body)): + md, m, convErr := htmlToMarkdown(page.Body, snap.FinalURL) + if convErr != nil { + return nil, fmt.Errorf("parse %s: %w", snap.FinalURL, convErr) + } + meta = m + snap.Markdown, snap.MarkdownTruncated = truncateMarkdown(md, maxMarkdownChars) + snap.Page = &PageView{ + Title: meta.Title, + Description: meta.Description, + Canonical: meta.Canonical, + RobotsMeta: meta.Robots, + Lang: meta.Lang, + H1: meta.H1, + LinkCount: meta.LinkCount, + DeadLinks: meta.DeadLinks, + ScriptCount: meta.ScriptCount, + ImageCount: meta.ImageCount, + WordCount: meta.WordCount, + TextLength: meta.TextLength, + } + case isText(page.ContentType): + snap.Markdown, snap.MarkdownTruncated = truncateMarkdown(string(page.Body), maxMarkdownChars) + default: + snap.Markdown, snap.MarkdownTruncated = + truncateMarkdown("```"+page.ContentType+"\n"+string(page.Body)+"\n```", maxMarkdownChars) + } + + // Companions come from the site root the page ended up on. They are + // fetched concurrently so one slow file cannot stretch the inspection. + root := siteRoot(snap.FinalURL) + var wg sync.WaitGroup + wg.Add(4) + go s.fetchFile(ctx, &wg, root+llmsTxtPath, true, &snap.Files.LlmsTxt) + go s.fetchFile(ctx, &wg, root+llmsFullTxtPath, true, &snap.Files.LlmsFullTxt) + go s.fetchFile(ctx, &wg, root+wellKnownTxtPath, true, &snap.Files.WellKnownTxt) + go s.fetchFile(ctx, &wg, root+robotsTxtPath, false, &snap.Files.RobotsTxt) + wg.Wait() + + snap.Checks = buildChecks(snap) + snap.DurationMS = time.Since(started).Milliseconds() + return snap, nil +} + +// NormalizeURL turns user input into a fetchable URL: a bare domain gets +// https://, credentials are dropped, fragments are dropped. +func NormalizeURL(raw string) (string, error) { + s := strings.TrimSpace(raw) + if s == "" { + return "", &ValidationError{Field: "url", Reason: "required"} + } + if !strings.Contains(s, "://") { + s = "https://" + s + } + u, err := url.Parse(s) + if err != nil || u.Host == "" { + return "", &ValidationError{Field: "url", Reason: "must be a domain or URL agents can open"} + } + if u.Scheme != "http" && u.Scheme != "https" { + return "", &ValidationError{Field: "url", Reason: "only http and https URLs are supported"} + } + u.User = nil + u.Fragment = "" + return u.String(), nil +} + +// fetchFile fetches one companion into dst. A failed request is a result, +// not an inspection failure — the checks describe what is missing. +func (s *Service) fetchFile(ctx context.Context, wg *sync.WaitGroup, url string, parseLlms bool, dst **FileResult) { + defer wg.Done() + + res, err := s.fetch.Fetch(ctx, url) + if err != nil { + var fe *FetchError + if errors.As(err, &fe) { + err = fe.Err + } + *dst = &FileResult{URL: url, Error: err.Error()} + return + } + + fr := &FileResult{ + URL: firstNonEmpty(res.FinalURL, url), + Status: res.Status, + ContentType: res.ContentType, + Truncated: res.Truncated, + } + if fr.found() { + fr.Content = string(res.Body) + if parseLlms && !isHTML(fr.ContentType, fr.Content) { + fr.LlmsDoc = parseLlmsTxt(fr.Content) + } + } + *dst = fr +} + +// buildChecks turns a finished snapshot into the validation report. +func buildChecks(snap *Snapshot) []Check { + c := []Check{} + add := func(id, label string, sev Severity, format string, args ...any) { + c = append(c, Check{ID: id, Label: label, Severity: sev, Detail: fmt.Sprintf(format, args...)}) + } + + // — the page itself — + switch { + case snap.Status >= 500: + add("page.status", "Page reachable", SeverityError, "server answered %d", snap.Status) + case snap.Status >= 400: + add("page.status", "Page reachable", SeverityError, "server answered %d — agents see an error page", snap.Status) + case snap.Status >= 300: + add("page.status", "Page reachable", SeverityWarn, "server answered %d", snap.Status) + default: + add("page.status", "Page reachable", SeverityOK, "%d OK", snap.Status) + } + + if u, err := url.Parse(snap.FinalURL); err == nil && u.Scheme == "http" { + add("page.https", "Served over HTTPS", SeverityWarn, "the final URL is plain http; secure agents may refuse it") + } else { + add("page.https", "Served over HTTPS", SeverityOK, "https") + } + + if snap.FinalURL != snap.RequestedURL { + add("page.redirect", "Direct URL", SeverityInfo, "redirected to %s", snap.FinalURL) + } + + if snap.Page != nil { + p := snap.Page + if p.Title == "" { + add("page.title", "Title", SeverityError, "no — agents use it as the page name in their results") + } else { + add("page.title", "Title", SeverityOK, "%s", clip(p.Title, 80)) + } + + if p.Description == "" { + add("page.description", "Meta description", SeverityWarn, "missing — agents have to guess the page's purpose from body text") + } else { + add("page.description", "Meta description", SeverityOK, "%s", clip(p.Description, 140)) + } + + robots := strings.ToLower(p.RobotsMeta) + switch { + case strings.Contains(robots, "noindex"): + add("page.robots-meta", "Robots meta", SeverityError, "meta robots declares noindex — indexing agents are told to ignore this page") + case strings.Contains(robots, "nofollow"): + add("page.robots-meta", "Robots meta", SeverityWarn, "meta robots declares nofollow — agents are told not to follow this page's links") + case p.RobotsMeta != "": + add("page.robots-meta", "Robots meta", SeverityOK, "%s", p.RobotsMeta) + default: + add("page.robots-meta", "Robots meta", SeverityOK, "no restrictions declared") + } + + if p.TextLength < jsShellTextChars && p.ScriptCount >= 3 { + add("page.javascript", "Reads without JavaScript", SeverityWarn, + "only %d characters of server-rendered text next to %d script tags — the page likely renders in the browser, which text agents never run", + p.TextLength, p.ScriptCount) + } else { + add("page.javascript", "Reads without JavaScript", SeverityOK, "%d characters of server-rendered text", p.TextLength) + } + + if p.H1 == "" { + add("page.h1", "Primary heading", SeverityInfo, "no <h1>; the markdown starts without a top-level heading") + } + + if p.DeadLinks > 0 { + add("page.dead-links", "Followable links", SeverityWarn, + "%d link(s) point at \"#\" or javascript: — agents cannot follow them", p.DeadLinks) + } + + if len(snap.Markdown) > contextHeavyChars { + add("markdown.size", "Markdown size", SeverityInfo, + "%d characters — heavy for a single agent context window", len(snap.Markdown)) + } + } else if isText(snap.ContentType) { + add("page.format", "Native format", SeverityOK, "served as markdown/plain text — agents read it directly") + } + + // — the llms.txt family — + f := snap.Files + switch { + case f.LlmsTxt.found(): + add("llms.txt", "/llms.txt", SeverityOK, "found at %s", f.LlmsTxt.URL) + if doc := f.LlmsTxt.LlmsDoc; doc != nil { + if doc.Title == "" { + add("llms.txt.format", "llms.txt format", SeverityError, + "the spec requires the file to start with an `# H1 title`") + } else if len(doc.Sections) == 0 { + add("llms.txt.format", "llms.txt format", SeverityInfo, + "title present but no `## sections` — fine, though sections organise links for agents") + } else { + add("llms.txt.format", "llms.txt format", SeverityOK, + "%s — %d section(s)", clip(doc.Title, 60), len(doc.Sections)) + } + if doc.LinkCount == 0 { + add("llms.txt.links", "llms.txt links", SeverityWarn, "no links — the file gives agents nothing to open") + } else { + add("llms.txt.links", "llms.txt links", SeverityOK, "%d curated link(s)", doc.LinkCount) + } + } + if !strings.Contains(strings.ToLower(f.LlmsTxt.ContentType), "markdown") { + add("llms.txt.content-type", "llms.txt content type", SeverityInfo, + "served as %s; the spec recommends text/markdown", contentTypeOr(f.LlmsTxt.ContentType)) + } + case f.LlmsTxt == nil: + add("llms.txt", "/llms.txt", SeverityWarn, "not reachable — agents are left to parse the HTML themselves; add one per llmstxt.org") + default: + add("llms.txt", "/llms.txt", SeverityWarn, + "missing (HTTP %d) — agents are left to parse the HTML themselves; add one per llmstxt.org", f.LlmsTxt.Status) + } + + switch { + case f.LlmsFullTxt.found(): + add("llms-full.txt", "/llms-full.txt", SeverityOK, "found — full-context variant for agents that want everything") + case f.LlmsFullTxt != nil && f.LlmsFullTxt.Status > 0: + add("llms-full.txt", "/llms-full.txt", SeverityInfo, "not published (HTTP %d) — optional", f.LlmsFullTxt.Status) + default: + add("llms-full.txt", "/llms-full.txt", SeverityInfo, "not published — optional") + } + + switch { + case f.WellKnownTxt.found(): + add("llms.well-known", "/.well-known/llms.txt", SeverityOK, "found at %s", f.WellKnownTxt.URL) + case f.WellKnownTxt != nil && f.WellKnownTxt.Status > 0: + add("llms.well-known", "/.well-known/llms.txt", SeverityInfo, "not published (HTTP %d) — alternative location", f.WellKnownTxt.Status) + default: + add("llms.well-known", "/.well-known/llms.txt", SeverityInfo, "not published — alternative location") + } + + // — robots.txt — + switch { + case f.RobotsTxt.found(): + disallowAll, sitemap := robotsSummary(f.RobotsTxt.Content) + if disallowAll { + add("robots.txt", "robots.txt", SeverityWarn, + "present but `User-agent: *` is disallowed for / — automated agents are told to keep out") + } else { + add("robots.txt", "robots.txt", SeverityOK, "no blanket disallow for `User-agent: *`") + } + if sitemap != "" { + add("robots.sitemap", "Sitemap", SeverityInfo, "%s", sitemap) + } + default: + add("robots.txt", "robots.txt", SeverityInfo, "not published — agents assume everything is allowed") + } + + return c +} + +// robotsSummary reports whether the wildcard agent is disallowed for / and +// returns the first declared sitemap. +func robotsSummary(content string) (disallowAll bool, sitemap string) { + groupApplies := false + for _, line := range strings.Split(content, "\n") { + line = strings.TrimSpace(line) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + key, value, _ := strings.Cut(line, ":") + key = strings.ToLower(strings.TrimSpace(key)) + value = strings.TrimSpace(value) + switch key { + case "user-agent": + groupApplies = value == "*" + case "disallow": + if groupApplies && value == "/" { + disallowAll = true + } + case "sitemap": + if sitemap == "" { + sitemap = value + } + } + } + return disallowAll, sitemap +} + +// isHTML decides whether the body should go through the HTML converter. +func isHTML(contentType, body string) bool { + ct := strings.ToLower(contentType) + if strings.Contains(ct, "html") { + return true + } + if ct == "" || strings.HasPrefix(ct, "text/") { + l := strings.ToLower(body[:min(len(body), 2048)]) + return strings.Contains(l, "<!doctype html") || strings.Contains(l, "<html") + } + return false +} + +// isText reports whether the content type is already markdown/plain text. +func isText(contentType string) bool { + ct := strings.ToLower(contentType) + return strings.Contains(ct, "text/markdown") || strings.Contains(ct, "text/plain") || + strings.Contains(ct, "text/x-markdown") +} + +// siteRoot reduces a URL to scheme://host for companion lookups. +func siteRoot(raw string) string { + u, err := url.Parse(raw) + if err != nil || u.Host == "" { + return raw + } + return u.Scheme + "://" + u.Host +} + +func contentTypeOr(ct string) string { + if strings.TrimSpace(ct) == "" { + return "an unknown type" + } + return ct +} + +func clip(s string, max int) string { + s = strings.TrimSpace(s) + runes := []rune(s) + if len(runes) <= max { + return s + } + return string(runes[:max-1]) + "…" +} + +func firstNonEmpty(vals ...string) string { + for _, v := range vals { + if v != "" { + return v + } + } + return "" +} diff --git a/backend/internal/browse/service_test.go b/backend/internal/browse/service_test.go new file mode 100644 index 0000000..e2fca28 --- /dev/null +++ b/backend/internal/browse/service_test.go @@ -0,0 +1,346 @@ +package browse_test + +import ( + "context" + "errors" + "fmt" + "strings" + "sync" + "testing" + + "git.k6n.net/mats/fullstack-template/internal/browse" +) + +// fakeFetcher is an in-memory browse.Fetcher: responses keyed by URL, an +// optional per-URL error, and a 404 default for anything unlisted. +type fakeFetcher struct { + mu sync.Mutex + res map[string]*browse.Response + err map[string]error +} + +func newFakeFetcher(pages map[string]string) *fakeFetcher { + f := &fakeFetcher{res: map[string]*browse.Response{}, err: map[string]error{}} + for url, body := range pages { + f.res[url] = &browse.Response{ + Status: 200, + FinalURL: url, + ContentType: fakeContentType(url, body), + Body: []byte(body), + } + } + return f +} + +func (f *fakeFetcher) failOn(url string, err error) { f.err[url] = err } + +func (f *fakeFetcher) Fetch(_ context.Context, url string) (*browse.Response, error) { + f.mu.Lock() + defer f.mu.Unlock() + if err, ok := f.err[url]; ok { + return nil, err + } + if r, ok := f.res[url]; ok { + return r, nil + } + return &browse.Response{Status: 404, FinalURL: url, ContentType: "text/plain", Body: []byte("not found")}, nil +} + +// fakeContentType guesses like a real server would: HTML pages as +// text/html, llms.txt as text/markdown, robots.txt as text/plain. +func fakeContentType(url, body string) string { + b := strings.TrimSpace(body) + switch { + case strings.HasPrefix(b, "<!doctype") || strings.HasPrefix(b, "<html") || strings.Contains(b[:min(len(b), 200)], "<div"): + return "text/html; charset=utf-8" + case strings.HasSuffix(url, "llms.txt"): + return "text/markdown; charset=utf-8" + case strings.HasSuffix(url, "robots.txt"): + return "text/plain" + default: + return "text/plain" + } +} + +// site is the smallest site that exercises every check path. +const site = `<!doctype html> +<html lang="en"> +<head> + <title>Test Site + + + + +

Welcome

+

Read the docs or visit the hub.

+ dead + + +` + +const llmsTxt = `# Test Site + +> A site for tests. + +## Docs + +- [Guide](https://example.test/guide): how to use it +- [API](https://example.test/api "the api"): endpoints + +## Community + +- [Forum](https://forum.example.test): ask questions +` + +func checkByID(t *testing.T, snap *browse.Snapshot, id string) browse.Check { + t.Helper() + for _, c := range snap.Checks { + if c.ID == id { + return c + } + } + t.Fatalf("check %q not found in %v", id, snap.Checks) + return browse.Check{} +} + +func TestNormalizeURL(t *testing.T) { + t.Parallel() + cases := []struct { + in, want string + wantErr bool + }{ + {in: "example.com", want: "https://example.com"}, + {in: " example.com/path ", want: "https://example.com/path"}, + {in: "http://example.com", want: "http://example.com"}, + {in: "https://example.com/a?b=1#frag", want: "https://example.com/a?b=1"}, + {in: "user:pass@example.com", want: "https://user:pass@example.com"}, + {in: "ftp://example.com", wantErr: true}, + {in: "https://", wantErr: true}, + {in: "", wantErr: true}, + {in: " ", wantErr: true}, + } + for _, tc := range cases { + got, err := browse.NormalizeURL(tc.in) + if tc.wantErr { + if err == nil { + t.Errorf("NormalizeURL(%q) = %q, want error", tc.in, got) + } + var vErr *browse.ValidationError + if err != nil && !errors.As(err, &vErr) { + t.Errorf("NormalizeURL(%q) error type %T, want *ValidationError", tc.in, err) + } + continue + } + if err != nil { + t.Errorf("NormalizeURL(%q) unexpected error: %v", tc.in, err) + continue + } + // credentials survive url.Parse round-trip; the service drops them + if u := got; strings.Contains(u, "user:pass") { + t.Errorf("NormalizeURL(%q) = %q, want credentials dropped", tc.in, u) + } + } +} + +func TestInspectConvertsHTML(t *testing.T) { + t.Parallel() + f := newFakeFetcher(map[string]string{"https://example.test": site}) + svc := browse.NewService(f) + + snap, err := svc.Inspect(context.Background(), "example.test") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + if snap.RequestedURL != "https://example.test" { + t.Errorf("requested URL = %q, want the normalized https origin", snap.RequestedURL) + } + if snap.Page == nil { + t.Fatal("page metadata missing") + } + if snap.Page.Title != "Test Site" { + t.Errorf("title = %q", snap.Page.Title) + } + if snap.Page.H1 != "Welcome" { + t.Errorf("h1 = %q", snap.Page.H1) + } + if snap.Page.LinkCount != 2 || snap.Page.DeadLinks != 1 { + t.Errorf("links = %d, dead = %d, want 2 and 1", snap.Page.LinkCount, snap.Page.DeadLinks) + } + for _, want := range []string{"# Welcome", "[docs](https://example.test/docs)", "[the hub](https://other.test/x)"} { + if !strings.Contains(snap.Markdown, want) { + t.Errorf("markdown missing %q:\n%s", want, snap.Markdown) + } + } + if c := checkByID(t, snap, "page.status"); c.Severity != browse.SeverityOK { + t.Errorf("page.status = %s (%s)", c.Severity, c.Detail) + } +} + +func TestInspectFetchError(t *testing.T) { + t.Parallel() + f := newFakeFetcher(nil) + f.failOn("https://down.test", fmt.Errorf("dial tcp: refused")) + svc := browse.NewService(f) + + _, err := svc.Inspect(context.Background(), "down.test") + var fe *browse.FetchError + if !errors.As(err, &fe) { + t.Fatalf("err = %T (%v), want *browse.FetchError", err, err) + } + if fe.URL != "https://down.test" { + t.Errorf("fetch error URL = %q", fe.URL) + } +} + +func TestInspectCompanions(t *testing.T) { + t.Parallel() + f := newFakeFetcher(map[string]string{ + "https://example.test": site, + "https://example.test/llms.txt": llmsTxt, + "https://example.test/robots.txt": "User-agent: *\nAllow: /\n\nSitemap: https://example.test/sitemap.xml", + }) + svc := browse.NewService(f) + + snap, err := svc.Inspect(context.Background(), "https://example.test/") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + + llms := snap.Files.LlmsTxt + if llms == nil || llms.Status >= 400 { + t.Fatalf("llms.txt missing: %+v", snap.Files.LlmsTxt) + } + if llms.LlmsDoc == nil { + t.Fatal("llms.txt was not parsed") + } + doc := llms.LlmsDoc + if doc.Title != "Test Site" { + t.Errorf("llms title = %q", doc.Title) + } + if doc.Description != "A site for tests." { + t.Errorf("llms description = %q", doc.Description) + } + if len(doc.Sections) != 2 { + t.Fatalf("llms sections = %d, want 2", len(doc.Sections)) + } + if len(doc.Sections[0].Links) != 2 || doc.Sections[0].Links[1].Description != "endpoints" { + t.Errorf("section links wrong: %+v", doc.Sections[0]) + } + if doc.LinkCount != 3 { + t.Errorf("llms link count = %d, want 3", doc.LinkCount) + } + + if c := checkByID(t, snap, "llms.txt"); c.Severity != browse.SeverityOK { + t.Errorf("llms.txt check = %s (%s)", c.Severity, c.Detail) + } + if c := checkByID(t, snap, "llms.txt.format"); c.Severity != browse.SeverityOK { + t.Errorf("llms.txt.format = %s (%s)", c.Severity, c.Detail) + } + if c := checkByID(t, snap, "llms-full.txt"); c.Severity != browse.SeverityInfo { + t.Errorf("llms-full.txt = %s (%s)", c.Severity, c.Detail) + } + if c := checkByID(t, snap, "robots.txt"); c.Severity != browse.SeverityOK { + t.Errorf("robots.txt = %s (%s)", c.Severity, c.Detail) + } + if c := checkByID(t, snap, "robots.sitemap"); c.Detail == "" { + t.Error("sitemap check detail empty") + } +} + +func TestInspectMissingLLMsTxtWarns(t *testing.T) { + t.Parallel() + f := newFakeFetcher(map[string]string{"https://bare.test": site}) + snap, err := browse.NewService(f).Inspect(context.Background(), "https://bare.test") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + if c := checkByID(t, snap, "llms.txt"); c.Severity != browse.SeverityWarn { + t.Errorf("llms.txt = %s (%s), want warn when the file is absent", c.Severity, c.Detail) + } +} + +func TestInspectLLMsTxtWithoutTitleIsAnError(t *testing.T) { + t.Parallel() + f := newFakeFetcher(map[string]string{ + "https://example.test/": site, + "https://example.test/llms.txt": "> just a quote, no H1\n", + }) + snap, err := browse.NewService(f).Inspect(context.Background(), "https://example.test") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + if c := checkByID(t, snap, "llms.txt.format"); c.Severity != browse.SeverityError { + t.Errorf("llms.txt.format = %s (%s), want error for a missing H1", c.Severity, c.Detail) + } +} + +func TestInspectRobotsDisallowAllWarns(t *testing.T) { + t.Parallel() + f := newFakeFetcher(map[string]string{ + "https://closed.test": site, + "https://closed.test/robots.txt": "User-agent: *\nDisallow: /\n", + }) + snap, err := browse.NewService(f).Inspect(context.Background(), "closed.test") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + if c := checkByID(t, snap, "robots.txt"); c.Severity != browse.SeverityWarn { + t.Errorf("robots.txt = %s (%s), want warn for a blanket disallow", c.Severity, c.Detail) + } +} + +func TestInspectPageProblems(t *testing.T) { + t.Parallel() + + noindex := strings.Replace(site, "Test Site", + `Test Site`, 1) + + jsShell := `Shell +
+ + ` + + f := newFakeFetcher(map[string]string{ + "https://noindex.test": noindex, + "https://shell.test": jsShell, + }) + svc := browse.NewService(f) + + snap, err := svc.Inspect(context.Background(), "noindex.test") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + if c := checkByID(t, snap, "page.robots-meta"); c.Severity != browse.SeverityError { + t.Errorf("noindex = %s (%s), want error", c.Severity, c.Detail) + } + + snap, err = svc.Inspect(context.Background(), "shell.test") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + if c := checkByID(t, snap, "page.javascript"); c.Severity != browse.SeverityWarn { + t.Errorf("js shell = %s (%s), want warn", c.Severity, c.Detail) + } +} + +func TestInspectRedirectAndMarkdownPage(t *testing.T) { + t.Parallel() + f := newFakeFetcher(map[string]string{ + "https://docs.test/guide": "# Guide\n\nAll there is.\n", + }) + f.res["https://docs.test/guide"].ContentType = "text/markdown" + + snap, err := browse.NewService(f).Inspect(context.Background(), "https://docs.test/guide") + if err != nil { + t.Fatalf("Inspect: %v", err) + } + if snap.Page != nil { + t.Errorf("markdown pages carry no HTML metadata, got %+v", snap.Page) + } + if !strings.HasPrefix(snap.Markdown, "# Guide") { + t.Errorf("markdown = %q", snap.Markdown) + } + if c := checkByID(t, snap, "page.format"); c.Severity != browse.SeverityOK { + t.Errorf("page.format = %s (%s)", c.Severity, c.Detail) + } +} diff --git a/backend/internal/config/config.go b/backend/internal/config/config.go index a00e8c1..a1ca34f 100644 --- a/backend/internal/config/config.go +++ b/backend/internal/config/config.go @@ -17,6 +17,8 @@ import ( "os" "strings" "time" + + "git.k6n.net/mats/fullstack-template/internal/browse" ) // Config is the validated runtime configuration. @@ -34,6 +36,10 @@ type Config struct { LogFormat string // "json" or "text" // DebugQueries enables Bun query logging (bundebug). DebugQueries bool + // FetchUserAgent identifies this server to the sites it inspects. + FetchUserAgent string + // FetchTimeout bounds each outbound fetch, redirects included. + FetchTimeout time.Duration // OIDCIssuer is the OpenID Connect issuer; endpoints are discovered, // never hardcoded. Auth is enabled when OIDCClientID is non-empty. @@ -60,6 +66,7 @@ func Load() (Config, error) { AllowedOrigins: splitCSV(env("CORS_ALLOWED_ORIGINS", "http://localhost:5173,http://127.0.0.1:5173")), LogFormat: strings.ToLower(env("LOG_FORMAT", "json")), DebugQueries: env("DB_DEBUG", "false") == "true", + FetchUserAgent: env("FETCH_USER_AGENT", browse.DefaultUserAgent), OIDCIssuer: strings.TrimRight(env("OIDC_ISSUER", "https://users.k6n.net"), "/"), OIDCClientID: env("OIDC_CLIENT_ID", ""), @@ -72,6 +79,8 @@ func Load() (Config, error) { cfg.AuthSessionTTL = sessionTTL } + fetchTimeout, fetchTimeoutErr := time.ParseDuration(env("FETCH_TIMEOUT", "15s")) + var errs []error level := strings.ToLower(env("LOG_LEVEL", "info")) @@ -103,6 +112,13 @@ func Load() (Config, error) { } else if cfg.AuthSessionTTL <= 0 { errs = append(errs, errors.New("AUTH_SESSION_TTL must be positive")) } + if fetchTimeoutErr != nil { + errs = append(errs, fmt.Errorf("invalid FETCH_TIMEOUT: %v", fetchTimeoutErr)) + } else if fetchTimeout <= 0 { + errs = append(errs, errors.New("FETCH_TIMEOUT must be positive")) + } else { + cfg.FetchTimeout = fetchTimeout + } if _, err := url.Parse(cfg.OIDCIssuer); err != nil || !strings.HasPrefix(cfg.OIDCIssuer, "https://") && !strings.HasPrefix(cfg.OIDCIssuer, "http://") { errs = append(errs, fmt.Errorf("invalid OIDC_ISSUER %q (want an http(s) URL)", cfg.OIDCIssuer)) } diff --git a/frontend/.codesearch/codesearch.db b/frontend/.codesearch/codesearch.db new file mode 100644 index 0000000..1830466 Binary files /dev/null and b/frontend/.codesearch/codesearch.db differ diff --git a/frontend/.design/design.json b/frontend/.design/design.json new file mode 100644 index 0000000..bfb5bfb --- /dev/null +++ b/frontend/.design/design.json @@ -0,0 +1,75 @@ +{ + "tokens": [ + "src/tokens.css" + ], + "pairs": [ + { + "fg": "--accent-foreground", + "bg": "--accent", + "min": 4.5 + }, + { + "fg": "--card-foreground", + "bg": "--card", + "min": 4.5 + }, + { + "fg": "--muted-foreground", + "bg": "--muted", + "min": 4.5 + }, + { + "fg": "--popover-foreground", + "bg": "--popover", + "min": 4.5 + }, + { + "fg": "--primary-foreground", + "bg": "--primary", + "min": 4.5 + }, + { + "fg": "--secondary-foreground", + "bg": "--secondary", + "min": 4.5 + }, + { + "fg": "--sidebar-accent-foreground", + "bg": "--sidebar-accent", + "min": 4.5 + }, + { + "fg": "--sidebar-foreground", + "bg": "--sidebar", + "min": 4.5 + }, + { + "fg": "--sidebar-primary-foreground", + "bg": "--sidebar-primary", + "min": 4.5 + }, + { + "fg": "--foreground", + "bg": "--background", + "min": 4.5 + }, + { + "fg": "--foreground", + "bg": "--card", + "min": 4.5 + }, + { + "fg": "--muted-foreground", + "bg": "--background", + "min": 4.5 + } + ], + "baseline": { + "src/App.css": 16, + "src/components/CodeEditor.tsx": 3, + "src/components/MarkdownRenderer.tsx": 2, + "src/data/library.ts": 8, + "src/utils.css": 9, + "tests/check-tokens.test.mjs": 5 + } +} diff --git a/frontend/DESIGN.md b/frontend/DESIGN.md new file mode 100644 index 0000000..2088bdd --- /dev/null +++ b/frontend/DESIGN.md @@ -0,0 +1,45 @@ +# LLM Browser — Agent View (Northstar design system) + +## Audience & purpose +A validator tool for people who publish sites for LLM agents: enter a domain, +see exactly what a text-only agent sees. Three surfaces per inspection: +rendered markdown, the `llms.txt` family (raw + parsed), and the +agent-readiness checks. Shared with the Northstar showcase app (routes, +primitives), so all components come from `src/components/ui`. + +## Visual character +Inherited from the host system: lab()-based tokens, quiet surfaces, mono for +machine output (URLs, raw files, source), sans for prose. Nothing on the +agent-view page introduces new colours — every shade is a token or a +`color-mix()` of one, so dark/light parity is automatic. + +## Layout +- Single-column app pattern: form card → status header → tabbed results. +- `?url=` in the address bar is the source of truth for what is being + inspected; link clicks rewrite it (the agent loop), so any view is a link. +- Tabs: Markdown (rendered), Source (raw markdown + copy), llms.txt (one card + per candidate path: `/llms.txt`, `/llms-full.txt`, `/.well-known/llms.txt`), + robots.txt, Meta (definition list), Checks (badge + label + detail rows). + +## Component patterns +- Status: `Badge` variants carry state — positive/ok, primary/warn, + destructive/error, secondary/info. No extra colours for severities. +- File cards: `Card` + `CardHeader`, status badge, absolute URL in mono, + parsed doc first, raw content in a `
` below. +- Markdown output renders through `src/components/markdown/MarkdownView` + (React elements, no HTML injection); links are intercepted and re-enter the + viewer instead of navigating away. +- Empty, loading (Skeleton), and error states are explicit — an inspection can + fail at the network, the site, or validation, and each gets its own copy. + +## Accepted decisions +- The light theme's `--destructive` stays at the default red + (`lab(48.4493% 77.4328 61.5452)`): its brighter variant failed the 4.5:1 + pair with `--destructive-foreground`. Dark keeps the brighter red (passes on + dark surfaces). Theme rules in `src/tokens.css` use explicit selectors only + (no `:not([data-theme='light'])` fallback) so tooling resolves them cleanly. +- Agent-view styles live in `src/App.css` under "Agent view"; they override + `.markdown-body`'s article metrics (`.agent-doc`) and add link, list, table, + quote and code styling the showcase never needed. +- Severity mapping: ok→positive, info→secondary, warn→primary, + error→destructive. Uppercase mono badges in the checks list. diff --git a/frontend/dist/assets/index-B4mWbae6.css b/frontend/dist/assets/index-B4mWbae6.css new file mode 100644 index 0000000..b8d685b --- /dev/null +++ b/frontend/dist/assets/index-B4mWbae6.css @@ -0,0 +1 @@ +@import "https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Manrope:wght@400;500;600;700;800&display=swap";:root{--root-font-size:112%;--text-3xs:.5625rem;--text-2xs:.625rem;--text-xs:.6875rem;--text-sm:.75rem;--text-md:.875rem;--text-base:1rem;--text-lg:1.3125rem;--text-xl:1.5625rem;--text-2xl:1.75rem;--text-hero:clamp(2.625rem, 5vw, 4.375rem);--font-sans:"Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-mono:"DM Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;--space-1:.25rem;--space-2:.5rem;--space-3:.75rem;--space-4:1rem;--space-5:1.25rem;--space-6:1.5rem;--space-7:2rem;--space-8:2.5rem;--space-9:3rem;--space-10:4rem;--space-11:5rem;--radius-sm:5px;--radius-md:6px;--radius-lg:9px;--radius-xl:12px;--radius-2xl:14px;--radius-pill:9999px;--focus-ring:2px solid var(--ring);--focus-offset:2px}:root,:root[data-theme=light],.light{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--background:lab(100% 0 0);--foreground:lab(2.75381% 0 0);--card:lab(97.68% -.0000298023 .0000119209);--card-foreground:lab(2.75381% 0 0);--popover:lab(100% 0 0);--popover-foreground:lab(2.75381% 0 0);--primary:lab(7.78201% -.0000149012 0);--primary-foreground:lab(98.26% 0 0);--secondary:lab(94.2% 0 0);--secondary-foreground:lab(7.78201% -.0000149012 0);--muted:lab(94.2% 0 0);--muted-foreground:lab(39.68% 0 0);--accent:lab(94.2% 0 0);--accent-foreground:lab(7.78201% -.0000149012 0);--destructive:lab(48.4493% 77.4328 61.5452);--destructive-foreground:lab(98.26% 0 0);--border:lab(86.08% -.0000298023 0);--input:lab(86.08% -.0000298023 0);--ring:lab(42% 0 0);--chart-1:lab(57.1026% 64.2584 89.8886);--chart-2:lab(55.0223% -41.0774 -3.90277);--chart-3:lab(30.372% -13.1853 -18.7887);--chart-4:lab(80.1641% 16.6016 99.2089);--chart-5:lab(72.7183% 31.8672 97.9407);--sidebar:lab(96.52% -.0000298023 .0000119209);--sidebar-foreground:lab(2.75381% 0 0);--sidebar-primary:lab(7.78201% -.0000149012 0);--sidebar-primary-foreground:lab(98.26% 0 0);--sidebar-accent:lab(94.2% 0 0);--sidebar-accent-foreground:lab(7.78201% -.0000149012 0);--sidebar-border:lab(86.08% -.0000298023 0);--sidebar-ring:lab(42% 0 0);--dot-color:lab(7.78201% -.0000149012 0/.05)}:root[data-theme=dark],.dark{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--background:lab(0% 0 0);--foreground:lab(94.78% 0 0);--card:lab(.903296% 0 0);--card-foreground:lab(94.78% 0 0);--popover:lab(.903296% 0 0);--popover-foreground:lab(94.78% 0 0);--primary:lab(89.9321% -47.9163 -15.7303);--primary-foreground:lab(0% 0 0);--secondary:lab(2.47865% 0 0);--secondary-foreground:lab(94.78% 0 0);--muted:lab(2.47865% 0 0);--muted-foreground:lab(60.56% 0 0);--accent:lab(1.98454% 0 0);--accent-foreground:lab(89.9321% -47.9163 -15.7303);--destructive:lab(54.5811% 71.684 50.9279);--destructive-foreground:lab(100% 0 0);--border:lab(4.8411% 0 0);--input:lab(1.98454% 0 0);--ring:lab(89.9321% -47.9163 -15.7303);--chart-1:lab(89.9321% -47.9163 -15.7303);--chart-2:lab(66.9756% -58.27 19.5419);--chart-3:lab(72.7183% 31.8672 97.9407);--chart-4:lab(52.0183% 66.11 -78.2316);--chart-5:lab(56.101% 79.4328 31.4532);--sidebar:lab(.498049% 0 0);--sidebar-foreground:lab(94.78% 0 0);--sidebar-primary:lab(89.9321% -47.9163 -15.7303);--sidebar-primary-foreground:lab(0% 0 0);--sidebar-accent:lab(1.98454% 0 0);--sidebar-accent-foreground:lab(89.9321% -47.9163 -15.7303);--sidebar-border:lab(4.8411% 0 0);--sidebar-ring:lab(89.9321% -47.9163 -15.7303);--dot-color:lab(89.9321% -47.9163 -15.7303/.045)}html{font-size:var(--root-font-size)}.dot-canvas{background-image:radial-gradient(var(--dot-color) 1px, transparent 1px);background-size:24px 24px}.dot-canvas-dense{background-image:radial-gradient(var(--dot-color) 1px, transparent 1px);background-size:16px 16px}.flex-center{justify-content:center;align-items:center;display:flex}.flex-between{justify-content:space-between;align-items:center;display:flex}.flex-col{flex-direction:column;display:flex}.stack-xs{gap:var(--space-1);flex-direction:column;display:flex}.stack-sm{gap:var(--space-2);flex-direction:column;display:flex}.stack-md{gap:var(--space-4);flex-direction:column;display:flex}.stack-lg{gap:var(--space-6);flex-direction:column;display:flex}.row-xs{align-items:center;gap:var(--space-1);display:flex}.row-sm{align-items:center;gap:var(--space-2);display:flex}.row-md{align-items:center;gap:var(--space-4);display:flex}.grid-2{gap:var(--space-4);grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.grid-3{gap:var(--space-4);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.grid-4{gap:var(--space-4);grid-template-columns:repeat(4,minmax(0,1fr));display:grid}@media (width<=760px){.grid-2,.grid-3,.grid-4{grid-template-columns:1fr}}.surface-card{background:var(--card);color:var(--card-foreground);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-5);box-shadow:0 4px 20px #0000001f}.surface-sidebar{background:var(--sidebar);color:var(--sidebar-foreground);border-right:1px solid var(--sidebar-border)}.surface-popover{background:var(--popover);color:var(--popover-foreground);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:0 10px 30px #00000040}.surface-muted{background:var(--secondary);color:var(--secondary-foreground);border:1px solid var(--border);border-radius:var(--radius-md)}.badge{align-items:center;gap:var(--space-1);padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:var(--text-3xs);white-space:nowrap;border:1px solid #0000;font-weight:500;line-height:1;display:inline-flex}.badge-primary{background:color-mix(in srgb, var(--primary) 14%, transparent);color:var(--primary);border-color:color-mix(in srgb, var(--primary) 28%, transparent)}.badge-secondary{background:var(--secondary);color:var(--secondary-foreground);border-color:var(--border)}.badge-destructive{background:color-mix(in srgb, var(--destructive) 14%, transparent);color:var(--destructive);border-color:color-mix(in srgb, var(--destructive) 28%, transparent)}.badge-positive{background:color-mix(in srgb, var(--chart-2) 14%, transparent);color:var(--chart-2);border-color:color-mix(in srgb, var(--chart-2) 28%, transparent)}.badge-outline{color:var(--muted-foreground);border-color:var(--border);background:0 0}.hover-lift{transition:transform .2s,border-color .2s,box-shadow .2s}.hover-lift:hover{border-color:var(--ring);box-shadow:0 8px 24px color-mix(in srgb, var(--primary) 10%, #0003);transform:translateY(-2px)}.kbd-tag{font-family:var(--font-mono);font-size:var(--text-3xs);color:var(--muted-foreground);background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2)}.skeleton-pulse{background:color-mix(in srgb, var(--foreground) 7%, var(--card));border-radius:var(--radius-md);animation:1.8s ease-in-out infinite skeleton-shimmer}@keyframes skeleton-shimmer{0%,to{opacity:.45}50%{opacity:.85}}.glow-primary{box-shadow:0 0 24px color-mix(in srgb, var(--primary) 25%, transparent)}.dialog-backdrop{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:50;padding:var(--space-4);background:#000000b8;place-items:center;animation:.2s ease-out dialog-fade-in;display:grid;position:fixed;inset:0}.dialog-panel{background:var(--card);color:var(--card-foreground);border:1px solid var(--border);border-radius:var(--radius-xl);width:100%;max-width:520px;padding:var(--space-6);box-shadow:0 24px 48px #0006, 0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent);animation:.2s cubic-bezier(.16,1,.3,1) dialog-scale-in;position:relative}@keyframes dialog-fade-in{0%{opacity:0}to{opacity:1}}@keyframes dialog-scale-in{0%{opacity:0;transform:scale(.96)translateY(8px)}to{opacity:1;transform:scale(1)translateY(0)}}.dialog-close-btn{top:var(--space-4);right:var(--space-4);color:var(--muted-foreground);border-radius:var(--radius-md);padding:var(--space-1);cursor:pointer;background:0 0;border:0;place-items:center;transition:all .15s;display:grid;position:absolute}.dialog-close-btn:hover{background:var(--secondary);color:var(--foreground)}.alert{gap:var(--space-3);padding:var(--space-4);border-radius:var(--radius-lg);border:1px solid var(--border);background:var(--card);color:var(--foreground);line-height:1.5;display:flex;position:relative}.alert-info{background:color-mix(in srgb, var(--primary) 6%, var(--card));border-color:color-mix(in srgb, var(--primary) 24%, var(--border))}.alert-info .alert-icon{color:var(--primary)}.alert-positive{background:color-mix(in srgb, var(--chart-2) 6%, var(--card));border-color:color-mix(in srgb, var(--chart-2) 24%, var(--border))}.alert-positive .alert-icon{color:var(--chart-2)}.alert-warning{background:color-mix(in srgb, var(--chart-3) 6%, var(--card));border-color:color-mix(in srgb, var(--chart-3) 24%, var(--border))}.alert-warning .alert-icon{color:var(--chart-3)}.alert-destructive{background:color-mix(in srgb, var(--destructive) 8%, var(--card));border-color:color-mix(in srgb, var(--destructive) 28%, var(--border))}.alert-destructive .alert-icon{color:var(--destructive)}.ui-tabs-list{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-lg);align-items:center;gap:3px;padding:4px;display:inline-flex}.ui-tabs-trigger{color:var(--muted-foreground);font-size:var(--text-sm);font-family:var(--font-sans);padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);cursor:pointer;align-items:center;gap:var(--space-2);white-space:nowrap;background:0 0;border:1px solid #0000;font-weight:500;line-height:1.4;transition:all .15s;display:inline-flex}.ui-tabs-trigger:hover{color:var(--foreground)}.ui-tabs-trigger.active{background:var(--card);color:var(--foreground);border-color:color-mix(in srgb, var(--border) 60%, transparent);font-weight:600;box-shadow:0 1px 3px #00000029}.ui-tabs-trigger svg{flex-shrink:0;display:block}.ui-tabs-content{margin-top:var(--space-4)}.empty-state{text-align:center;padding:var(--space-10) var(--space-6);border:1px dashed var(--border);border-radius:var(--radius-xl);background:color-mix(in srgb, var(--secondary) 50%, var(--card));flex-direction:column;justify-content:center;align-items:center;display:flex}.empty-state-icon{border-radius:var(--radius-lg);background:color-mix(in srgb, var(--primary) 12%, var(--secondary));width:48px;height:48px;color:var(--primary);margin-bottom:var(--space-4);place-items:center;display:grid}.progress-container{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-pill);width:100%;height:8px;position:relative;overflow:hidden}.progress-fill{background:var(--primary);border-radius:var(--radius-pill);height:100%;box-shadow:0 0 10px color-mix(in srgb, var(--primary) 60%, transparent);transition:width .3s cubic-bezier(.4,0,.2,1)}.progress-indeterminate{width:40%;animation:1.5s ease-in-out infinite progress-slide;position:absolute}@keyframes progress-slide{0%{transform:translate(-100%)}to{transform:translate(350%)}}.switch-root{border-radius:var(--radius-pill);background:var(--border);border:1px solid var(--border);cursor:pointer;align-items:center;width:40px;height:22px;padding:2px;transition:background-color .2s,border-color .2s;display:inline-flex}.switch-root.checked{background:var(--primary);border-color:var(--primary)}.switch-thumb{background:var(--muted-foreground);border-radius:50%;width:16px;height:16px;transition:transform .2s cubic-bezier(.2,.8,.2,1),background-color .2s}.switch-root.checked .switch-thumb{background:var(--primary-foreground);transform:translate(18px)}.ui-table-container{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);width:100%;overflow-x:auto}.ui-table{border-collapse:collapse;text-align:left;width:100%;font-size:var(--text-sm);color:var(--foreground)}.ui-table th{padding:var(--space-3) var(--space-4);font:var(--text-3xs) var(--font-mono);letter-spacing:.08em;text-transform:uppercase;color:var(--muted-foreground);background:var(--secondary);border-bottom:1px solid var(--border)}.ui-table td{padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border)}.ui-table tr:last-child td{border-bottom:0}.ui-table tr:hover td{background:color-mix(in srgb, var(--foreground) 3%, var(--card))}.sheet-backdrop{-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);z-index:50;background:#000000b3;animation:.2s ease-out dialog-fade-in;position:fixed;inset:0}.sheet-panel{background:var(--card);width:100%;max-width:420px;color:var(--card-foreground);border-left:1px solid var(--border);z-index:51;padding:var(--space-6);flex-direction:column;animation:.25s cubic-bezier(.16,1,.3,1) sheet-slide-in;display:flex;position:fixed;top:0;bottom:0;right:0;box-shadow:-10px 0 35px #00000059}@keyframes sheet-slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}.tooltip-wrapper{display:inline-flex;position:relative}.tooltip-box{background:var(--popover);color:var(--popover-foreground);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2);font:var(--text-3xs) var(--font-mono);white-space:nowrap;pointer-events:none;z-index:40;opacity:0;transition:opacity .15s,transform .15s;position:absolute;bottom:100%;left:50%;transform:translate(-50%)translateY(-6px);box-shadow:0 4px 14px #0003}.tooltip-box[data-open=true]{opacity:1;transform:translate(-50%)translateY(-8px)}.skeleton{background:color-mix(in srgb, var(--foreground) 7%, var(--card));animation:1.8s ease-in-out infinite skeleton-shimmer;display:block}.skeleton-text{border-radius:var(--radius-sm);width:100%;height:14px}.skeleton-circle{border-radius:50%;flex-shrink:0}.skeleton-rect{border-radius:var(--radius-lg)}:where(.ui-tabs-trigger,.switch-root,.dialog-close-btn):focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-offset)}:root{font-family:var(--font-sans);color:var(--foreground);background:var(--background);font-synthesis:none;text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased}*{box-sizing:border-box}html{scroll-behavior:smooth}body{min-width:320px;margin:0}button,input{font:inherit}button{cursor:pointer}.app-shell{background-color:var(--background);isolation:isolate;min-height:100vh;position:relative}.app-shell:before{content:"";z-index:-1;pointer-events:none;background-image:radial-gradient(ellipse 90% 60% at 70% -5%, color-mix(in srgb, var(--primary) 3.5%, transparent) 0%, transparent 100%);position:fixed;inset:0}.topbar{border-bottom:1px solid var(--border);background:color-mix(in srgb, var(--background) 85%, transparent);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);height:68px;padding:0 var(--space-7);align-items:center;gap:var(--space-7);z-index:10;display:flex;position:sticky;top:0}.brand,.top-links,.top-search,.hero-actions,.showcase-foot,.status-line,.code-head,.section-heading,.release-icon,.input-with-action,.toggle-field{align-items:center;display:flex}.brand{white-space:nowrap;gap:10px}.brand-mark{border:1px solid var(--primary);border-radius:var(--radius-md);place-items:center;width:26px;height:26px;display:grid;transform:rotate(45deg)}.brand-mark span{background:var(--primary);border-radius:3px;width:9px;height:9px}.brand-mark.large{border-radius:var(--radius-xl);width:42px;height:42px}.brand-mark.large span{width:14px;height:14px}.brand b{letter-spacing:-.04em;font-weight:800;font-size:var(--text-base);color:var(--foreground)}.version,.api-pill,.nav-count{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);border:1px solid var(--border);padding:var(--space-1) 7px;border-radius:var(--radius-sm)}.top-search{gap:var(--space-3);max-width:380px;color:var(--muted-foreground);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-2) var(--space-3);cursor:pointer;text-align:left;font-family:inherit;font-size:var(--text-sm);flex:1;margin-left:auto;margin-right:auto;transition:border-color .2s,box-shadow .2s,background .2s}.top-search:hover{border-color:var(--ring);background:color-mix(in srgb, var(--accent) 35%, var(--card))}.top-search:focus-visible{border-color:var(--ring);box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 15%, transparent);outline:0}.top-search-placeholder{color:var(--muted-foreground);-webkit-user-select:none;user-select:none;font-size:var(--text-sm);flex:1}.top-search kbd{font-family:var(--font-mono);font-size:var(--text-3xs);color:var(--muted-foreground);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2);background:var(--secondary)}.top-links{gap:var(--space-5);font-size:var(--text-sm);color:var(--muted-foreground)}.top-view-mode{gap:2px;padding:2px}.top-view-mode button{padding:var(--space-1) var(--space-3);font-size:var(--text-2xs);letter-spacing:.04em;text-transform:uppercase}.top-links a{color:var(--muted-foreground);text-decoration:none}.top-links a:hover,.text-button:hover{color:var(--foreground)}.icon-button,.avatar{color:var(--muted-foreground);border-radius:var(--radius-md);background:0 0;border:0;place-items:center;padding:7px;display:grid}.icon-button:hover{background:var(--secondary);color:var(--foreground)}.avatar{background:color-mix(in srgb, var(--primary) 18%, var(--secondary));width:28px;height:28px;color:var(--primary);font-size:var(--text-3xs);cursor:pointer;font-weight:700}.top-signin{border:1px solid var(--border);background:var(--secondary);color:var(--foreground);border-radius:var(--radius-md);padding:var(--space-1) var(--space-3);font-family:inherit;font-size:var(--text-2xs);letter-spacing:.04em;cursor:pointer;font-weight:600;transition:all .15s}.top-signin:hover{border-color:color-mix(in srgb, var(--primary) 45%, transparent);color:var(--primary)}.top-signin:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.user-menu{place-items:center;display:grid;position:relative}.user-menu-popover{top:calc(100% + var(--space-2));background:var(--popover);min-width:230px;color:var(--popover-foreground);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:0 16px 40px #00000073, 0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent);padding:var(--space-2);z-index:60;animation:.15s cubic-bezier(.16,1,.3,1) user-menu-in;position:absolute;right:0}@keyframes user-menu-in{0%{opacity:0;transform:scale(.96)translateY(6px)}to{opacity:1;transform:scale(1)translateY(0)}}.user-menu-identity{padding:var(--space-2) var(--space-3);font-size:var(--text-xs);gap:2px;display:grid}.user-menu-identity span{color:var(--muted-foreground);font-size:var(--text-2xs)}.user-menu-signout{align-items:center;gap:var(--space-2);width:100%;color:var(--muted-foreground);font-family:inherit;font-size:var(--text-xs);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);cursor:pointer;background:0 0;border:0;transition:all .15s;display:flex}.user-menu-signout:hover{background:var(--secondary);color:var(--destructive)}.session-card{border-color:color-mix(in srgb, var(--primary) 30%, transparent)}.session-note{color:var(--muted-foreground);font-size:var(--text-xs);margin:0}.session-identity{align-items:center;gap:var(--space-3);display:flex}.session-lines{gap:2px;min-width:0;display:grid}.session-lines b{font-size:var(--text-sm)}.session-lines span,.session-lines small{color:var(--muted-foreground);font-size:var(--text-2xs);text-overflow:ellipsis;overflow:hidden}.session-lines .skeleton-pulse{height:var(--text-xs);display:block}.session-avatar.skeleton-pulse{width:var(--space-7);height:var(--space-7);border-radius:var(--radius-pill)}.session-roles{gap:var(--space-2);flex-wrap:wrap;display:flex}.mobile-menu{display:none}.body-layout{grid-template-columns:240px minmax(0,1fr);display:grid}.body-layout.sidebar-collapsed{grid-template-columns:56px minmax(0,1fr)}.body-layout.sidebar-collapsed .sidebar{padding:var(--space-4) 0}.body-layout.sidebar-collapsed .sidebar-heading{border-bottom:0;justify-content:center;padding:0}.body-layout.sidebar-collapsed .sidebar-intro,.body-layout.sidebar-collapsed .sidebar nav,.body-layout.sidebar-collapsed .sidebar-bottom{display:none}.sidebar{border-right:1px solid var(--sidebar-border);min-height:calc(100vh - 68px);padding:var(--space-5) 0 var(--space-4);background:var(--sidebar);flex-direction:column;height:calc(100vh - 68px);display:flex;position:sticky;top:68px}.sidebar-heading{padding:0 var(--space-5) var(--space-5);border-bottom:1px solid var(--sidebar-border);justify-content:space-between;align-items:center;display:flex}.sidebar-library{align-items:center;gap:var(--space-2);color:var(--sidebar-foreground);font:500 var(--text-xs) var(--font-mono);letter-spacing:.05em;text-transform:uppercase;display:flex}.sidebar-library svg{color:var(--sidebar-primary)}.sidebar-collapse{color:var(--muted-foreground);font:var(--text-xs) var(--font-mono);background:0 0;border:0;padding:4px 0}.sidebar-collapse:hover{color:var(--sidebar-foreground)}.sidebar-intro{padding:var(--space-5) var(--space-5) var(--space-5);border-bottom:1px solid var(--sidebar-border);margin:0}.sidebar-intro p{font-size:var(--text-3xs);color:var(--muted-foreground);margin:var(--space-2) 0 0;max-width:180px;line-height:1.6}.eyebrow,.section-index,.nav-label{font:var(--text-3xs) var(--font-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--muted-foreground)}.accent{color:var(--primary)}.sidebar nav{padding-top:var(--space-5)}.nav-group{margin-bottom:var(--space-5)}.nav-label{padding:0 var(--space-5);margin-bottom:var(--space-2);color:var(--muted-foreground);font-size:var(--text-3xs);display:block}.nav-item{width:100%;color:var(--sidebar-foreground);text-align:left;padding:9px var(--space-5);font-size:var(--text-sm);letter-spacing:-.01em;background:0 0;border:0;border-radius:0;align-items:center;gap:11px;text-decoration:none;transition:all .2s;display:flex;position:relative}.nav-item:hover{color:var(--sidebar-accent-foreground);background:var(--sidebar-accent)}.nav-item.active{color:var(--sidebar-foreground);background:linear-gradient(90deg, color-mix(in srgb, var(--sidebar-primary) 18%, transparent), color-mix(in srgb, var(--sidebar-primary) 5%, transparent));box-shadow:inset 2px 0 var(--sidebar-primary)}.nav-glyph{width:13px;color:var(--muted-foreground);font:var(--text-md) var(--font-mono);text-align:center;line-height:1}.nav-item.active .nav-glyph{color:var(--sidebar-primary)}.nav-count{color:var(--sidebar-primary);font-size:var(--text-3xs);background:0 0;border:0;margin-left:auto;padding:0}.sidebar-bottom{border-top:1px solid var(--sidebar-border);padding:var(--space-4) var(--space-5) 0;margin-top:auto}.status-line{gap:var(--space-2);color:var(--muted-foreground);font-size:var(--text-3xs);margin-bottom:7px}.status-dot{background:var(--chart-2);width:6px;height:6px;box-shadow:0 0 10px var(--chart-2);border-radius:50%}.mono{font-family:var(--font-mono);font-size:var(--text-3xs)}.muted{color:var(--muted-foreground)}.main-content{min-width:0}.breadcrumbs{max-width:1180px;padding:var(--space-6) var(--space-9) 0;font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);gap:10px;margin:0 auto;display:flex}.breadcrumbs strong{color:var(--primary);font-weight:500}.hero-section{max-width:1180px;padding:var(--space-10) var(--space-9) var(--space-11);justify-content:space-between;gap:var(--space-8);min-height:386px;margin:0 auto;display:flex}.hero-copy{max-width:590px}.hero-copy h1{font-size:var(--text-hero);letter-spacing:-.07em;margin:var(--space-4) 0 var(--space-5);font-weight:800;line-height:1.02}.hero-copy p{color:var(--muted-foreground);font-size:var(--text-base);max-width:510px;line-height:1.7}.hero-actions{gap:var(--space-3);margin-top:var(--space-7)}.button{border-radius:var(--radius-md);padding:var(--space-2) var(--space-4);color:var(--foreground);font-size:var(--text-xs);align-items:center;gap:var(--space-2);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none;border:1px solid #0000;outline:none;font-weight:600;text-decoration:none;transition:background-color .15s,border-color .15s,box-shadow .15s,transform 80ms,filter .12s;display:inline-flex;position:relative;overflow:hidden}.button:focus-visible{outline:2px solid var(--ring);outline-offset:2px}.button:active{transform:translateY(1px)}.button.primary{background:var(--primary);color:var(--primary-foreground);border-color:#0000;font-weight:600;box-shadow:0 1px 2px #0003}.button.primary:hover,.button.primary.hover-state{filter:brightness(1.06);box-shadow:0 1px 3px #00000047}.button.primary:active{filter:brightness(.93);transform:translateY(1px);box-shadow:inset 0 1px 2px #0003}.button.primary:focus-visible{outline:2px solid var(--ring);outline-offset:2px;box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 35%, transparent)}.button.secondary{background:color-mix(in srgb, var(--foreground) 8%, var(--card));border:1px solid color-mix(in srgb, var(--foreground) 16%, var(--border));color:var(--foreground)}.button.secondary:hover,.button.secondary.hover-state{background:color-mix(in srgb, var(--foreground) 14%, var(--card));border-color:var(--ring)}.button.secondary:active{background:color-mix(in srgb, var(--foreground) 18%, var(--card));transform:translateY(1px)}.button.secondary:focus-visible{outline:2px solid var(--ring);outline-offset:2px;box-shadow:0 0 0 3px color-mix(in srgb, var(--foreground) 15%, transparent)}.button.danger{background:var(--destructive);color:var(--destructive-foreground);border:1px solid #0000;box-shadow:0 1px 2px #0003}.button.danger:hover,.button.danger.hover-state{filter:brightness(1.08);box-shadow:0 1px 3px #00000047}.button.danger:active{filter:brightness(.92);transform:translateY(1px);box-shadow:inset 0 1px 2px #0003}.button.danger:focus-visible{outline:2px solid var(--destructive);outline-offset:2px;box-shadow:0 0 0 3px color-mix(in srgb, var(--destructive) 35%, transparent)}.button.ghost{color:var(--muted-foreground);background:0 0}.button.ghost:hover,.button.ghost.hover-state{color:var(--foreground);background:var(--accent)}.button.ghost:active{background:color-mix(in srgb, var(--accent) 80%, var(--foreground));transform:translateY(1px)}.button.ghost:focus-visible{outline:2px solid var(--ring);outline-offset:2px}.hero-orbit{width:280px;height:225px;margin:var(--space-2) var(--space-8) 0 0;flex:0 0 280px;position:relative}.orbit{border:1px solid color-mix(in srgb, var(--primary) 14%, var(--border));border-radius:50%;position:absolute;transform:rotate(-22deg)}.orbit-one{width:270px;height:112px;top:45px;left:0}.orbit-two{border-color:color-mix(in srgb, var(--primary) 8%, var(--border));width:215px;height:215px;top:2px;left:28px;transform:rotate(58deg)}.orbit-core{border:1px solid color-mix(in srgb, var(--primary) 22%, var(--border));background:color-mix(in srgb, var(--card) 90%, transparent);border-radius:var(--radius-xl);justify-content:center;align-items:center;gap:var(--space-2);width:105px;height:83px;color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);box-shadow:0 0 45px color-mix(in srgb, var(--primary) 14%, transparent);line-height:1.4;display:flex;position:absolute;top:71px;right:88px}.orbit-core b{color:var(--chart-2);font-weight:500}.orbit-label{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);letter-spacing:.08em;position:absolute}.orbit-label b{color:var(--primary);margin-top:4px;font-weight:600;display:block}.label-one{top:13px;right:5px}.label-two{bottom:4px;left:7px}.label-three{bottom:31px;right:0}.content-grid{gap:var(--space-10);max-width:1180px;padding:0 var(--space-9);grid-template-columns:minmax(0,1fr) 220px;margin:0 auto;display:grid}.content-main{min-width:0}.section-block{padding:var(--space-9) 0;border-top:1px solid var(--border);scroll-margin-top:80px}.section-heading{justify-content:space-between;align-items:flex-start;gap:var(--space-5)}.section-heading h2{font-size:var(--text-2xl);letter-spacing:-.05em;color:var(--foreground);margin:10px 0 7px}.section-heading p{color:var(--muted-foreground);font-size:var(--text-sm);margin:0}.api-pill{white-space:nowrap;margin-top:var(--space-1)}.text-button{gap:var(--space-2);color:var(--primary);font-size:var(--text-xs);background:0 0;border:0;align-items:center;margin-top:10px;display:inline-flex}.tabs{gap:var(--space-6);border-bottom:1px solid var(--border);margin-top:var(--space-7);display:flex}.tab{color:var(--muted-foreground);font-family:var(--font-sans);font-size:var(--text-sm);padding:var(--space-2) 0 var(--space-3);align-items:center;gap:var(--space-2);cursor:pointer;background:0 0;border:0;border-bottom:2px solid #0000;font-weight:500;line-height:1.4;transition:color .15s,border-color .15s;display:inline-flex}.tab:hover{color:var(--foreground)}.tab.active{color:var(--foreground);border-color:var(--primary);font-weight:600}.tab svg{flex-shrink:0;display:block}.showcase{margin-top:var(--space-5);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}.showcase-head,.showcase-foot{padding:var(--space-4) var(--space-4);border-bottom:1px solid var(--border);justify-content:space-between}.button-matrix{padding:7px var(--space-4);overflow-x:auto}.button-row{align-items:center;gap:var(--space-4);border-bottom:1px solid var(--border);grid-template-columns:90px 1fr 1fr 42px 1fr;min-width:560px;min-height:58px;display:grid}.button-row:last-child{border:0}.row-label{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground)}.icon-only{justify-content:center;padding:var(--space-2)!important}.loading{color:var(--muted-foreground)!important;background:color-mix(in srgb, var(--foreground) 6%, var(--card))!important;border:1px solid var(--border)!important}.showcase-foot{border-top:1px solid var(--border);border-bottom:0;justify-content:flex-start;gap:7px}.density{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);padding:var(--space-2) var(--space-2);border-radius:var(--radius-sm);background:0 0;border:1px solid #0000}.density.active{background:color-mix(in srgb, var(--primary) 14%, var(--secondary));color:var(--primary)}.foot-check{color:var(--chart-2);font:var(--text-3xs) var(--font-mono);align-items:center;gap:var(--space-1);margin-left:auto;display:flex}.color-grid{gap:var(--space-2);margin-top:var(--space-5);grid-template-columns:repeat(4,1fr);display:grid}.color-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-3);grid-template-columns:32px 1fr 16px;align-items:center;gap:9px;display:grid}.swatch{border-radius:var(--radius-md);width:32px;height:32px;box-shadow:inset 0 0 0 1px #ffffff1f}.color-card strong,.color-card span{font-size:var(--text-xs);color:var(--foreground);display:block}.color-card .mono{color:var(--muted-foreground);margin-top:4px}.copy-icon{color:var(--muted-foreground);background:0 0;border:0;padding:0}.copy-icon:hover{color:var(--foreground)}.forms-grid{gap:var(--space-5) var(--space-4);margin-top:var(--space-5);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-5);grid-template-columns:1fr 1fr;display:grid}.field{gap:var(--space-2);font-size:var(--text-xs);color:var(--muted-foreground);flex-direction:column;display:flex}.field em{font:var(--text-3xs) var(--font-mono);color:var(--primary);float:right;text-transform:uppercase;font-style:normal}.field input{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-3);color:var(--foreground);font-size:var(--text-sm);outline:0}.field input:focus{border-color:var(--ring);box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent)}.field small,.toggle-field small{font-size:var(--text-3xs);color:var(--muted-foreground)}.input-with-action{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-sm)}.input-with-action input{min-width:0;color:var(--foreground);background:0 0;border:0;flex:1}.input-with-action button{color:var(--muted-foreground);background:0 0;border:0;padding:0 11px}.toggle-field{background:color-mix(in srgb, var(--foreground) 3%, var(--card));border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-3) var(--space-3);grid-column:1/-1;justify-content:space-between}.toggle-field b{color:var(--foreground)}.toggle-field b,.toggle-field small{display:block}.toggle-field small{margin-top:4px}.toggle{border-radius:var(--radius-pill);background:var(--border);width:36px;height:20px;padding:var(--space-1);border:0}.toggle span{background:var(--muted-foreground);border-radius:50%;width:14px;height:14px;transition:all .2s;display:block}.toggle.on{background:var(--primary)}.toggle.on span{background:var(--primary-foreground);transform:translate(16px)}.bottom-section{padding-bottom:var(--space-7)}.code-card{background:var(--sidebar);border:1px solid var(--border);border-radius:var(--radius-lg);margin-top:var(--space-5);overflow:hidden}.code-head{background:var(--card);padding:10px var(--space-4);border-bottom:1px solid var(--border);justify-content:space-between}.segmented{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-lg);align-items:center;gap:4px;padding:4px;display:inline-flex}.segmented button{color:var(--muted-foreground);font-family:var(--font-sans);font-size:var(--text-xs);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);align-items:center;gap:var(--space-2);cursor:pointer;white-space:nowrap;background:0 0;border:1px solid #0000;font-weight:500;line-height:1.4;transition:all .15s;display:inline-flex}.segmented button:hover{color:var(--foreground)}.segmented button.selected{background:var(--card);color:var(--foreground);border-color:color-mix(in srgb, var(--border) 60%, transparent);font-weight:600;box-shadow:0 1px 3px #00000026}.segmented button.selected svg{color:var(--primary)}.segmented button svg{flex-shrink:0;display:block}.copy-button{border:1px solid var(--border);background:var(--secondary);color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);padding:var(--space-1) var(--space-2);border-radius:var(--radius-md);align-items:center;gap:var(--space-2);cursor:pointer;transition:all .15s;display:inline-flex}.copy-button:hover{color:var(--foreground);border-color:var(--ring)}.code-card pre{padding:var(--space-5);font:var(--text-sm) / 1.7 var(--font-mono);color:var(--foreground);margin:0;overflow:auto}.pink{color:var(--chart-5)}.green{color:var(--chart-2)}.blue{color:var(--chart-4)}.right-rail{padding-top:var(--space-9)}.rail-card{border-top:1px solid var(--border);padding:var(--space-4) 0 var(--space-5)}.rail-link{color:var(--muted-foreground);font-size:var(--text-xs);gap:11px;padding:9px 0;text-decoration:none;display:flex}.rail-link span{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground)}.rail-link.active,.rail-link:hover{color:var(--primary)}.release{background:linear-gradient(145deg, color-mix(in srgb, var(--primary) 6%, var(--card)), var(--card));border:1px solid color-mix(in srgb, var(--primary) 15%, var(--border));border-radius:var(--radius-lg);padding:var(--space-4);margin:10px 0 var(--space-4)}.release-icon{color:var(--primary);background:color-mix(in srgb, var(--primary) 14%, var(--secondary));width:31px;height:31px;margin-bottom:var(--space-4);border-radius:7px;justify-content:center}.release strong{font-size:var(--text-sm);color:var(--foreground)}.release p,.rail-copy{color:var(--muted-foreground);font-size:var(--text-xs);margin:var(--space-2) 0 var(--space-4);line-height:1.7}.full{justify-content:center;width:100%}.release .text-button{margin-top:0}footer{max-width:1180px;padding:var(--space-7) var(--space-9) var(--space-8);border-top:1px solid var(--border);color:var(--muted-foreground);font-size:var(--text-3xs);justify-content:space-between;margin:0 auto;display:flex}@media (width<=1020px){.topbar{padding:0 var(--space-5);gap:var(--space-4)}.top-links a,.top-view-mode{display:none}.body-layout{grid-template-columns:200px minmax(0,1fr)}.hero-section,.content-grid{padding-left:var(--space-7);padding-right:var(--space-7)}.content-grid{gap:var(--space-7);grid-template-columns:minmax(0,1fr) 190px}.hero-orbit{transform-origin:100% 0;margin-right:0;transform:scale(.82)}}@media (width<=760px){.topbar{height:60px}.top-search{order:3;max-width:none;display:none;position:absolute;top:68px;left:18px;right:18px}.top-links{margin-left:auto}.mobile-menu{display:grid}.body-layout{display:block}.sidebar{z-index:9;background:color-mix(in srgb, var(--background) 98%, transparent);border:0;height:auto;display:none;position:fixed;inset:60px 0 0}.menu-open .sidebar{display:flex}.breadcrumbs{padding:var(--space-5) var(--space-5) 0}.hero-section{padding:var(--space-9) var(--space-5) var(--space-10);display:block}.hero-copy h1{font-size:var(--text-hero)}.hero-orbit{display:none}.content-grid{padding:0 var(--space-5);display:block}.right-rail{display:none}.section-block{padding:var(--space-7) 0}.section-heading{display:block}.api-pill{margin-top:var(--space-4);display:inline-block}.button-row{gap:var(--space-2);grid-template-columns:70px 1fr 1fr}.button-row .icon-only,.button-row .loading{display:none}.color-grid{grid-template-columns:1fr 1fr}.forms-grid{grid-template-columns:1fr}.toggle-field{grid-column:auto}footer{padding:var(--space-6) var(--space-5) var(--space-7);display:block}footer .mono{margin-top:var(--space-2);display:block}}@media (width<=450px){.version{display:none}.brand b{font-size:var(--text-md)}.hero-actions{flex-direction:column;align-items:stretch}.hero-actions .button{justify-content:center}.button-row{grid-template-columns:58px 1fr 1fr}.button{padding:var(--space-2);font-size:var(--text-2xs)}.showcase-foot{flex-wrap:wrap}.foot-check{width:100%;margin-left:0;margin-top:var(--space-2)}.color-card{grid-template-columns:28px 1fr}.color-card .swatch{width:28px;height:28px}.color-card .copy-icon{display:none}}.markdown-card,.editor-card{margin-top:var(--space-5);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);overflow:hidden}.markdown-toolbar,.editor-tabs{padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border);background:var(--secondary);justify-content:space-between;align-items:center;display:flex}.markdown-body{max-width:700px;padding:var(--space-8) var(--space-9) var(--space-8);color:var(--foreground);font-size:var(--text-md);margin:0 auto;line-height:1.75}.md-kicker{font:var(--text-3xs) var(--font-mono);letter-spacing:.13em;color:var(--primary)}.markdown-body h3{color:var(--foreground);font-size:var(--text-xl);letter-spacing:-.05em;margin:var(--space-3) 0 10px;line-height:1.2}.markdown-body h4{color:var(--foreground);font-size:var(--text-md);margin:var(--space-5) 0 7px}.markdown-body p{margin:0 0 var(--space-4);color:var(--muted-foreground)}.markdown-body code{font:var(--text-xs) var(--font-mono);color:var(--primary);background:color-mix(in srgb, var(--primary) 8%, var(--card));border:1px solid color-mix(in srgb, var(--primary) 22%, var(--border));padding:2px var(--space-1);border-radius:4px}.md-callout{gap:var(--space-3);padding:var(--space-3) var(--space-4);margin:var(--space-5) 0;border:1px solid color-mix(in srgb, var(--primary) 25%, var(--border));border-left:2px solid var(--primary);border-radius:var(--radius-md);background:linear-gradient(100deg, color-mix(in srgb, var(--primary) 6%, var(--card)), var(--card));display:flex}.md-callout p{font-size:var(--text-sm);color:var(--foreground);margin:0;line-height:1.6}.callout-mark{color:var(--primary);font-size:var(--text-base)}.markdown-body ul{margin:0 0 var(--space-5);padding-left:var(--space-5);color:var(--muted-foreground)}.markdown-body li{padding-left:var(--space-1)}.markdown-body li::marker{color:var(--primary)}.md-table{border:1px solid var(--border);border-radius:var(--radius-md);font-size:var(--text-xs);overflow:hidden}.md-table>div{padding:9px var(--space-3);border-bottom:1px solid var(--border);grid-template-columns:1.1fr 1fr 1.4fr;gap:10px;display:grid}.md-table>div:last-child{border-bottom:0}.md-table>div:first-child{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);text-transform:uppercase;letter-spacing:.08em;background:var(--secondary)}.md-table code{font-size:var(--text-3xs);background:0 0;border:0;padding:0}.md-accent{color:var(--primary)}.editor-card{background:var(--sidebar);border-color:var(--border);box-shadow:0 16px 35px #0000002e}.editor-tabs{padding:0 var(--space-3);background:var(--secondary);justify-content:flex-start;gap:0}.editor-dot{background:var(--chart-2);width:8px;height:8px;box-shadow:0 0 8px color-mix(in srgb, var(--chart-2) 60%, transparent);margin-right:var(--space-4);border-radius:50%}.editor-tab{padding:var(--space-3) var(--space-4);color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);border-right:1px solid var(--border)}.editor-tab.active{color:var(--foreground);background:var(--card);border-top:2px solid var(--primary);padding-top:10px}.editor-actions{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);letter-spacing:3px;margin-left:auto}.editor-body{background:linear-gradient(90deg, color-mix(in srgb, var(--background) 70%, transparent), transparent 16%);grid-template-columns:43px 1fr;min-height:218px;display:grid}.line-numbers{padding:var(--space-4) 10px var(--space-4) 0;border-right:1px solid var(--border);text-align:right;color:var(--muted-foreground);font:var(--text-xs) / 1.72 var(--font-mono);-webkit-user-select:none;user-select:none}.editor-body pre{padding:var(--space-4) var(--space-5);font:var(--text-sm) / 1.72 var(--font-mono);color:var(--foreground);margin:0;overflow:auto}.cm-comment{color:var(--muted-foreground);font-style:italic}.cm-keyword{color:var(--chart-5)}.cm-variable{color:var(--primary)}.cm-property{color:var(--chart-4)}.cm-string{color:var(--chart-2)}.editor-status{gap:var(--space-4);padding:var(--space-2) var(--space-4);border-top:1px solid var(--border);background:var(--secondary);color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);display:flex}.editor-ready{color:var(--chart-2);align-items:center;gap:var(--space-1);margin-left:auto;display:flex}@media (width<=760px){.markdown-body{padding:var(--space-6) var(--space-5) var(--space-7)}.md-table{font-size:var(--text-3xs)}.editor-body pre{padding:var(--space-4) var(--space-3)}.editor-status{font-size:var(--text-3xs);gap:10px}.editor-status span:nth-child(2){display:none}}@keyframes rise-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes soft-glow{0%,to{box-shadow:0 0 #0000}50%{box-shadow:0 0 34px color-mix(in srgb, var(--primary) 18%, transparent)}}@keyframes orbit-drift{0%{transform:rotate(-22deg)rotate(0)}to{transform:rotate(-22deg)rotate(360deg)}}@keyframes orbit-drift-reverse{0%{transform:rotate(58deg)rotate(360deg)}to{transform:rotate(58deg)rotate(0)}}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes pulse-dot{0%,to{opacity:1;transform:scale(1)}50%{opacity:.55;transform:scale(.72)}}.hero-section{animation:.7s cubic-bezier(.2,.8,.2,1) both rise-in}.hero-copy h1{background:linear-gradient(110deg, var(--foreground) 15%, var(--primary) 55%, var(--foreground) 85%);color:#0000;background-size:220%;-webkit-background-clip:text;background-clip:text;animation:9s linear infinite shimmer}.hero-copy p{animation:.7s cubic-bezier(.2,.8,.2,1) .1s both rise-in}.hero-actions{animation:.7s cubic-bezier(.2,.8,.2,1) .18s both rise-in}.hero-orbit{animation:.9s cubic-bezier(.2,.8,.2,1) .18s both rise-in}.orbit-one{animation:24s linear infinite orbit-drift}.orbit-two{animation:30s linear infinite orbit-drift-reverse}.orbit-core{animation:4s ease-in-out infinite soft-glow}.orbit-label{animation:.7s .7s both rise-in}.section-block{animation:.65s cubic-bezier(.2,.8,.2,1) .1s both rise-in}.section-block:nth-child(2){animation-delay:.16s}.section-block:nth-child(3){animation-delay:.22s}.section-block:nth-child(4){animation-delay:.28s}.button-row{transition:background .25s,transform .25s}.button-row:hover{background:color-mix(in srgb, var(--primary) 5%, transparent);transform:translate(3px)}.button:not(:disabled):after,.copy-button:after{content:"";background:linear-gradient(110deg,#0000 25%,#ffffff21 50%,#0000 75%);transition:transform .55s;position:absolute;inset:0;transform:translate(-120%)}.button:hover:after,.copy-button:hover:after{transform:translate(120%)}.button:focus-visible,.tab:focus-visible,.nav-item:focus-visible,.density:focus-visible,.segmented button:focus-visible,.text-button:focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-offset)}.swatch{transition:transform .3s,box-shadow .3s}.color-card{transition:transform .25s,border-color .25s,background .25s}.color-card:hover{border-color:var(--ring);background:color-mix(in srgb, var(--foreground) 4%, var(--card));transform:translateY(-4px)}.color-card:hover .swatch{box-shadow:0 0 18px color-mix(in srgb, var(--primary) 30%, transparent), inset 0 0 0 1px #fff3;transform:scale(1.08)}.status-dot{animation:2.5s ease-in-out infinite pulse-dot}.field input,.input-with-action{transition:border-color .25s,box-shadow .25s,background .25s}.field input:hover,.input-with-action:hover{background:color-mix(in srgb, var(--foreground) 4%, var(--secondary));border-color:var(--ring)}.toggle{transition:background .25s,transform .2s}.toggle:active{transform:scale(.94)}.release{transition:transform .3s,box-shadow .3s}.release:hover{box-shadow:0 14px 38px #0003, 0 0 25px color-mix(in srgb, var(--primary) 10%, transparent);transform:translateY(-4px)}.release-icon{transition:transform .4s cubic-bezier(.2,.8,.2,1)}.release:hover .release-icon{transform:rotate(-8deg)scale(1.08)}.code-card{transition:border-color .3s,box-shadow .3s}.code-card:hover{border-color:var(--ring);box-shadow:0 15px 40px #00000024}.top-search{transition:border-color .25s,box-shadow .25s}.icon-matrix-container{gap:var(--space-5);flex-direction:column;display:flex}.icon-matrix-header{justify-content:space-between;align-items:center;gap:var(--space-4);flex-wrap:wrap;display:flex}.icon-search-bar{align-items:center;gap:var(--space-3);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-2) var(--space-4);min-width:240px;color:var(--muted-foreground);flex:1;transition:border-color .2s,box-shadow .2s;display:flex}.icon-search-bar:focus-within{border-color:var(--ring);box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent)}.icon-search-input{color:var(--foreground);font-size:var(--text-sm);background:0 0;border:0;outline:0;width:100%}.icon-clear-btn{color:var(--muted-foreground);cursor:pointer;border-radius:var(--radius-sm);background:0 0;border:0;place-items:center;padding:2px;display:grid}.icon-clear-btn:hover{color:var(--foreground)}.icon-size-picker{align-items:center;gap:var(--space-2);background:var(--secondary);border-radius:var(--radius-md);border:1px solid var(--border);padding:3px 4px;display:flex}.icon-size-btn{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);cursor:pointer;background:0 0;border:0;transition:all .15s}.icon-size-btn:hover{color:var(--foreground)}.icon-size-btn.active{background:var(--card);color:var(--foreground);box-shadow:0 1px 4px color-mix(in srgb, var(--foreground) 10%, transparent)}.icon-category-tabs{gap:var(--space-2);padding-bottom:2px;display:flex;overflow-x:auto}.icon-cat-btn{border:1px solid var(--border);background:var(--card);color:var(--muted-foreground);font-family:var(--font-sans);font-size:var(--text-sm);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);cursor:pointer;align-items:center;gap:var(--space-2);white-space:nowrap;font-weight:500;line-height:1.4;transition:all .15s;display:inline-flex}.icon-cat-btn svg{flex-shrink:0;display:block}.icon-cat-btn:hover{color:var(--foreground);border-color:var(--ring)}.icon-cat-btn.active{background:color-mix(in srgb, var(--primary) 10%, var(--card));border-color:var(--primary);color:var(--primary)}.icon-cat-count{font:var(--text-3xs) var(--font-mono);opacity:.8}.icon-grid{gap:var(--space-3);grid-template-columns:repeat(auto-fill,minmax(115px,1fr));display:grid}.icon-tile{justify-content:center;align-items:center;gap:var(--space-2);padding:var(--space-4) var(--space-2);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);cursor:pointer;color:var(--foreground);text-align:center;flex-direction:column;transition:all .2s cubic-bezier(.16,1,.3,1);display:flex;position:relative}.icon-tile:hover{border-color:var(--ring);box-shadow:0 8px 20px color-mix(in srgb, var(--primary) 10%, transparent);background:color-mix(in srgb, var(--foreground) 3%, var(--card));transform:translateY(-2px)}.icon-tile.copied{border-color:var(--primary);background:color-mix(in srgb, var(--primary) 12%, var(--card))}.icon-tile-glyph{height:32px;color:var(--foreground);place-items:center;transition:color .15s;display:grid}.icon-tile:hover .icon-tile-glyph{color:var(--primary)}.icon-tile-name{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);text-overflow:ellipsis;white-space:nowrap;max-width:100%;overflow:hidden}.icon-tile-action{font:var(--text-3xs) var(--font-mono);color:var(--primary);min-height:16px}.icon-matrix-footer{padding-top:var(--space-3);border-top:1px solid var(--border);justify-content:space-between;align-items:center;display:flex}.icon-footer-pill{align-items:center;gap:var(--space-3);font-size:var(--text-xs);color:var(--muted-foreground);display:flex}.icon-footer-pill code{font-family:var(--font-mono);color:var(--primary)}.search-palette-backdrop{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:100;padding:12vh var(--space-4) var(--space-4);background:#000000b3;justify-content:center;align-items:flex-start;animation:.15s ease-out dialog-fade-in;display:flex;position:fixed;inset:0}.search-palette-modal{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-xl);flex-direction:column;width:100%;max-width:580px;animation:.18s cubic-bezier(.16,1,.3,1) modal-scale-in;display:flex;overflow:hidden;box-shadow:0 24px 60px #00000073}.search-palette-head{align-items:center;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--border);background:var(--card);display:flex}.search-palette-icon{color:var(--muted-foreground);flex-shrink:0}.search-palette-input{font-family:var(--font-sans);font-size:var(--text-md);color:var(--foreground);background:0 0;border:0;outline:none;flex:1;min-width:0}.search-palette-input::placeholder{color:var(--muted-foreground)}.search-palette-body{max-height:380px;padding:var(--space-2);overflow-y:auto}.search-palette-results{flex-direction:column;gap:2px;margin:0;padding:0;list-style:none;display:flex}.search-palette-item{align-items:center;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg);cursor:pointer;transition:background-color .1s;display:flex}.search-palette-item:hover,.search-palette-item.selected{background:var(--secondary)}.search-palette-item.selected .search-item-glyph{color:var(--primary);background:color-mix(in srgb, var(--primary) 12%, transparent)}.search-item-glyph{border-radius:var(--radius-md);background:color-mix(in srgb, var(--foreground) 6%, transparent);width:32px;height:32px;color:var(--muted-foreground);flex-shrink:0;place-items:center;transition:all .15s;display:grid}.search-item-content{flex:1;min-width:0}.search-item-title-row{align-items:center;gap:var(--space-2);margin-bottom:2px;display:flex}.search-item-title{font-family:var(--font-sans);font-size:var(--text-sm);color:var(--foreground);font-weight:600}.search-item-desc{font-size:var(--text-xs);color:var(--muted-foreground);text-overflow:ellipsis;white-space:nowrap;margin:0;overflow:hidden}.search-item-action{flex-shrink:0}.search-palette-empty{padding:var(--space-8) var(--space-4);text-align:center;color:var(--muted-foreground);flex-direction:column;justify-content:center;align-items:center;display:flex}.search-palette-empty p{margin:var(--space-2) 0 var(--space-1);font-size:var(--text-sm);color:var(--foreground);font-weight:500}.search-palette-empty span{font-size:var(--text-xs);color:var(--muted-foreground)}.search-palette-footer{justify-content:flex-end;align-items:center;gap:var(--space-4);padding:var(--space-2) var(--space-4);border-top:1px solid var(--border);background:color-mix(in srgb, var(--secondary) 40%, var(--card));font-size:var(--text-3xs);color:var(--muted-foreground);display:flex}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}.hero-copy h1{color:var(--foreground);background:0 0}}.brand-link{color:inherit;align-items:center;gap:10px;text-decoration:none;display:flex}.overview-grid{max-width:1180px;padding:0 var(--space-9) var(--space-11);gap:var(--space-5);grid-template-columns:repeat(auto-fit,minmax(230px,1fr));margin:0 auto;display:grid}.overview-links{gap:var(--space-3);font-size:var(--text-sm);margin:0;padding:0;list-style:none;display:grid}.overview-links a{align-items:center;gap:var(--space-2);color:var(--muted-foreground);text-decoration:none;display:inline-flex}.overview-links a:hover{color:var(--primary)}.not-found{gap:var(--space-6);padding:var(--space-9) 0;justify-items:center;display:grid}.not-found .overview-links{justify-items:center}@media (width<=760px){.overview-grid{padding-bottom:var(--space-9)}}.agent-url-row{gap:var(--space-2);flex-wrap:wrap;display:flex}.agent-url-row input{flex:1;min-width:min(100%,22rem)}.agent-examples{align-items:center;gap:var(--space-2);margin-top:var(--space-3);flex-wrap:wrap;display:flex}.agent-example{padding:var(--space-1) var(--space-3);font-size:var(--text-xs);font-family:var(--font-mono)}.agent-head .agent-url{font-size:var(--text-sm);color:var(--foreground);word-break:break-all}.agent-note{font-size:var(--text-xs);padding:0 var(--space-2)}.agent-doc{padding:var(--space-5);overflow-x:auto}.agent-doc .markdown-body{max-width:none;margin:0;padding:0}.agent-doc .markdown-body h1{font-size:var(--text-2xl);letter-spacing:-.04em;margin:var(--space-5) 0 var(--space-3);line-height:1.15}.agent-doc .markdown-body h2{font-size:var(--text-xl);letter-spacing:-.03em;margin:var(--space-5) 0 var(--space-2);line-height:1.2}.agent-doc .markdown-body h5,.agent-doc .markdown-body h6{font-size:var(--text-md);margin:var(--space-4) 0 var(--space-1)}.agent-doc .markdown-body a{color:var(--accent);text-decoration:underline;-webkit-text-decoration-color:color-mix(in srgb, var(--accent) 45%, transparent);text-decoration-color:color-mix(in srgb, var(--accent) 45%, transparent);text-underline-offset:2px}.agent-doc .markdown-body a:hover{-webkit-text-decoration-color:var(--accent);text-decoration-color:var(--accent)}.agent-doc .markdown-body ul,.agent-doc .markdown-body ol{margin:0 0 var(--space-4);color:var(--muted-foreground);gap:var(--space-1);flex-direction:column;padding-left:1.4rem;display:flex}.agent-doc .markdown-body blockquote{margin:0 0 var(--space-4);padding:var(--space-2) var(--space-4);border-left:2px solid color-mix(in srgb, var(--accent) 55%, var(--border));color:var(--muted-foreground);font-style:italic}.agent-doc .markdown-body blockquote p{margin:0}.agent-doc .markdown-body pre{margin:0 0 var(--space-4);padding:var(--space-3) var(--space-4);background:var(--muted);border:1px solid var(--border);border-radius:var(--radius-md);overflow-x:auto}.agent-doc .markdown-body pre code{color:var(--foreground);font-size:var(--text-xs);background:0 0;border:none;padding:0;line-height:1.6}.agent-doc .markdown-body table{border-collapse:collapse;width:100%;margin:0 0 var(--space-4);font-size:var(--text-sm)}.agent-doc .markdown-body th,.agent-doc .markdown-body td{border:1px solid var(--border);padding:var(--space-2) var(--space-3);text-align:left}.agent-doc .markdown-body th{background:color-mix(in srgb, var(--accent) 7%, var(--card))}.agent-doc .markdown-body hr{border:none;border-top:1px solid var(--border);margin:var(--space-5) 0}.agent-doc .markdown-body img{border-radius:var(--radius-sm);max-width:100%}.agent-raw{padding:var(--space-4);background:var(--muted);color:var(--foreground);font-size:var(--text-xs);white-space:pre-wrap;word-break:break-word;max-height:26rem;margin:0;line-height:1.6;overflow:auto}.agent-file-url{font-size:var(--text-2xs);word-break:break-all;text-decoration:none}.agent-file-url:hover{color:var(--foreground)}.agent-llms{gap:var(--space-3);flex-direction:column;display:flex}.agent-llms-title{font-size:var(--text-lg);letter-spacing:-.02em;margin:0}.agent-llms-quote{padding:var(--space-2) var(--space-4);border-left:2px solid color-mix(in srgb, var(--accent) 55%, var(--border));color:var(--muted-foreground);font-style:italic;font-size:var(--text-sm);margin:0}.agent-llms-section h4{margin:var(--space-2) 0 0;font-size:var(--text-md)}.agent-llms-section>p{font-size:var(--text-xs);margin:0}.agent-llms-section ul{margin:var(--space-2) 0 0;gap:var(--space-1);font-size:var(--text-sm);flex-direction:column;padding-left:1.3rem;list-style:outside;display:flex}.agent-llms-section a{color:var(--accent);text-underline-offset:2px;text-decoration:underline}.agent-meta{padding:var(--space-2) var(--space-5) var(--space-4);margin:0}.agent-meta-row{gap:var(--space-4);padding:var(--space-2) 0;border-bottom:1px solid var(--border);font-size:var(--text-sm);grid-template-columns:minmax(110px,max-content) 1fr;display:grid}.agent-meta-row:last-child{border-bottom:none}.agent-meta-row dd{word-break:break-word;margin:0}.agent-checks-summary{padding:var(--space-4) var(--space-5) 0}.agent-checks{padding:var(--space-2) var(--space-5) var(--space-4);margin:0;list-style:none}.agent-check{align-items:flex-start;gap:var(--space-3);padding:var(--space-3) 0;border-bottom:1px solid var(--border);display:flex}.agent-check:last-child{border-bottom:none}.agent-check .badge{text-transform:uppercase;flex-shrink:0;justify-content:center;min-width:3.5rem}.agent-check-label{font-weight:600;font-size:var(--text-sm)}.agent-check-detail{font-size:var(--text-xs);line-height:1.55}@media (width<=720px){.agent-meta-row{gap:var(--space-1);grid-template-columns:1fr}}@keyframes spin{to{transform:rotate(360deg)}} diff --git a/frontend/dist/assets/index-C60Osx-j.js b/frontend/dist/assets/index-C60Osx-j.js new file mode 100644 index 0000000..3b5e9e1 --- /dev/null +++ b/frontend/dist/assets/index-C60Osx-j.js @@ -0,0 +1,27 @@ +var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,o)=>(o=n==null?{}:e(i(n)),s(r||!n||!n.__esModule||!a.call(n,`default`)?t(o,`default`,{value:n,enumerable:!0}):o,n));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var l=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.for(`react.view_transition`),m=Symbol.iterator;function h(e){return typeof e!=`object`||!e?null:(e=m&&e[m]||e[`@@iterator`],typeof e==`function`?e:null)}var g={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},_=Object.assign,v={};function y(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}y.prototype.isReactComponent={},y.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},y.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function b(){}b.prototype=y.prototype;function ee(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}var te=ee.prototype=new b;te.constructor=ee,_(te,y.prototype),te.isPureReactComponent=!0;var ne=Array.isArray;function re(){}var x={H:null,A:null,T:null,S:null},ie=Object.prototype.hasOwnProperty;function S(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function ae(e,t){return S(e.type,t,e.props)}function oe(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function se(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ce=/\/+/g;function le(e,t){return typeof e==`object`&&e&&e.key!=null?se(``+e.key):t.toString(36)}function ue(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(re,re):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function de(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,de(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+le(e,0):a,ne(o)?(i=``,c!=null&&(i=c.replace(ce,`$&/`)+`/`),de(o,r,i,``,function(e){return e})):o!=null&&(oe(o)&&(o=ae(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ce,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(ne(e))for(var u=0;u{t.exports=l()})),d=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function ee(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,te||(te=!0,ae());else{var t=n(l);t!==null&&ce(ee,t.startTime-e)}}}var te=!1,ne=-1,re=5,x=-1;function ie(){return g?!0:!(e.unstable_now()-xt&&ie());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&ce(ee,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?ae():te=!1}}}var ae;if(typeof y==`function`)ae=function(){y(S)};else if(typeof MessageChannel<`u`){var oe=new MessageChannel,se=oe.port2;oe.port1.onmessage=S,ae=function(){se.postMessage(null)}}else ae=function(){_(S,0)};function ce(t,n){ne=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(ne),ne=-1):h=!0,ce(ee,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,te||(te=!0,ae()))),r},e.unstable_shouldYield=ie,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),f=o(((e,t)=>{t.exports=d()})),p=o((e=>{var t=u();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=p()})),h=o((e=>{var t=f(),n=u(),r=m();function i(e){var t=`https://react.dev/errors/`+e;if(1Ae||(e.current=ke[Ae],ke[Ae]=null,Ae--)}function T(e,t){Ae++,ke[Ae]=e.current,e.current=t}var Ne=je(null),Pe=je(null),Fe=je(null),Ie=je(null);function Le(e,t){switch(T(Fe,t),T(Pe,e),T(Ne,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?up(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=up(t),e=dp(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}Me(Ne),T(Ne,e)}function Re(){Me(Ne),Me(Pe),Me(Fe)}function ze(e){var t=e.memoizedState;t!==null&&(sh._currentValue=t.memoizedState,T(Ie,e)),t=Ne.current;var n=dp(t,e.type);t!==n&&(T(Pe,e),T(Ne,n))}function Be(e){Pe.current===e&&(Me(Ne),Me(Pe)),Ie.current===e&&(Me(Ie),sh._currentValue=Oe)}var Ve,He;function Ue(e){if(Ve===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ve=t&&t[1]||``,He=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{We=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Ue(n):``}function Ge(e,t){switch(e.tag){case 26:case 27:case 5:return Ue(e.type);case 16:return Ue(`Lazy`);case 13:return e.child!==t&&t!==null?Ue(`Suspense Fallback`):Ue(`Suspense`);case 19:return Ue(`SuspenseList`);case 0:case 15:return E(e.type,!1);case 11:return E(e.type.render,!1);case 1:return E(e.type,!0);case 31:return Ue(`Activity`);case 30:return Ue(`ViewTransition`);default:return``}}function Ke(e){try{var t=``,n=null;do t+=Ge(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var qe=Object.prototype.hasOwnProperty,Je=t.unstable_scheduleCallback,Ye=t.unstable_cancelCallback,Xe=t.unstable_shouldYield,Ze=t.unstable_requestPaint,D=t.unstable_now,Qe=t.unstable_getCurrentPriorityLevel,$e=t.unstable_ImmediatePriority,et=t.unstable_UserBlockingPriority,tt=t.unstable_NormalPriority,nt=t.unstable_LowPriority,rt=t.unstable_IdlePriority,O=t.log,it=t.unstable_setDisableYieldValue,at=null,ot=null;function st(e){if(typeof O==`function`&&it(e),ot&&typeof ot.setStrictMode==`function`)try{ot.setStrictMode(at,e)}catch{}}var ct=Math.clz32?Math.clz32:dt,lt=Math.log,ut=Math.LN2;function dt(e){return e>>>=0,e===0?32:31-(lt(e)/ut|0)|0}var ft=256,pt=262144,mt=4194304;function ht(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&-e;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function gt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=ht(n))):i=ht(o):i=ht(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=ht(n))):i=ht(o)):i=ht(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function _t(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function vt(e,t){t&8&&(t|=t&32);var n=e.entangledLanes;if(n!==0)for(e=e.entanglements,n&=t;0n;n++)t.push(e);return t}function xt(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function St(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),Ln=!1;if(In)try{var Rn={};Object.defineProperty(Rn,"passive",{get:function(){Ln=!0}}),window.addEventListener(`test`,Rn,Rn),window.removeEventListener(`test`,Rn,Rn)}catch{Ln=!1}var zn=null,Bn=null,Vn=null;function Hn(){if(Vn)return Vn;var e,t=Bn,n=t.length,r,i=`value`in zn?zn.value:zn.textContent,a=i.length;for(e=0;e=br),Cr=` `,wr=!1;function Tr(e,t){switch(e){case`keyup`:return vr.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Er(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var Dr=!1;function Or(e,t){switch(e){case`compositionend`:return Er(t);case`keypress`:return t.which===32?(wr=!0,Cr):null;case`textInput`:return e=t.data,e===Cr&&wr?null:e;default:return null}}function kr(e,t){if(Dr)return e===`compositionend`||!yr&&Tr(e,t)?(e=Hn(),Vn=Bn=zn=null,Dr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Zr(n)}}function $r(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?$r(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function ei(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=M(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=M(e.document)}return t}function ti(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var ni=In&&`documentMode`in document&&11>=document.documentMode,ri=null,ii=null,ai=null,oi=!1;function si(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;oi||ri==null||ri!==M(r)||(r=ri,`selectionStart`in r&&ti(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),ai&&Xr(ai,r)||(ai=r,r=Jf(ii,`onSelect`),0>=o,i-=o,ta=1<<32-ct(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),I&&ra(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),I&&ra(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return I&&ra(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&(_=v.alternate,_!==null&&h.delete(_.key===null?g:_.key)),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),I&&ra(a,g),u}function _(e,r,o,c){if(typeof o==`object`&&o&&o.type===ce&&o.key===null&&o.props.ref===void 0&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case oe:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===ce){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),po(c,o),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===_e&&ao(l)===r.type){n(e,r.sibling),c=a(r,o.props),po(c,o),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}o.type===ce?(c=Wi(o.props.children,e.mode,c,o.key),po(c,o),c.return=e,e=c):(c=Ui(o.type,o.key,o.props,null,e.mode,c),po(c,o),c.return=e,e=c)}return s(e);case se:a:{for(l=o.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=qi(o,e.mode,c),c.return=e,e=c}return s(e);case _e:return o=ao(o),_(e,r,o,c)}if(De(o))return h(e,r,o,c);if(we(o)){if(l=we(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return _(e,r,fo(o),c);if(o.$$typeof===fe)return _(e,r,Aa(e,o),c);mo(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=Gi(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{uo=0;var i=_(e,t,n,r);return lo=null,i}catch(t){if(t===$a||t===to)throw t;var a=zi(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var go=ho(!0),_o=ho(!1),vo=!1;function yo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function bo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function xo(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function So(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Ii(e),Fi(e,null,n),t}return Mi(e,r,t,n),Ii(e)}function Co(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,wt(e,n)}}function wo(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var To=!1;function Eo(){if(To){var e=Wa;if(e!==null)throw e}}function Do(e,t,n,r){To=!1;var i=e.updateQueue;vo=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===Ua&&(To=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,h=s;f=t;var g=n;switch(h.tag){case 1:if(m=h.payload,typeof m==`function`){d=m.call(g,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=h.payload,f=typeof m==`function`?m.call(g,d,f):m,f==null)break a;d=S({},d,f);break a;case 2:vo=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),sd|=o,e.lanes=o,e.memoizedState=d}}function Oo(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function ko(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=C.T,s={};s.types=o===null?null:o.types,C.T=s,pc(e,!1,t,n);try{var c=i(),l=C.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?fc(e,t,qa(c,r),jd(e)):fc(e,t,r,jd(e))}catch(n){fc(e,t,{then:function(){},status:`rejected`,reason:n},jd())}finally{w.p=a,o!==null&&s.types!==null&&(o.types=s.types),C.T=o}}function nc(){}function rc(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=ic(e).queue;tc(e,a,t,Oe,n===null?nc:function(){return ac(e),n(r)})}function ic(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:Oe,baseState:Oe,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ms,lastRenderedState:Oe},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ms,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ac(e){var t=ic(e);t.next===null&&(t=e.alternate.memoizedState),fc(e,t.next.queue,{},jd())}function oc(){return ka(sh)}function sc(){return B().memoizedState}function cc(){return B().memoizedState}function lc(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=jd();e=xo(n);var r=So(t,e,n);r!==null&&(Pd(r,t,n),Co(r,t,n)),t={cache:Ia()},e.payload=t;return}t=t.return}}function uc(e,t,n){var r=jd();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},mc(e)?hc(t,n):(n=Ni(e,t,n,r),n!==null&&(Pd(n,e,r),gc(n,t,r)))}function dc(e,t,n){fc(e,t,n,jd())}function fc(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(mc(e))hc(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Yr(s,o))return Mi(e,t,i,0),G===null&&ji(),!1}catch{}if(n=Ni(e,t,i,r),n!==null)return Pd(n,e,r),gc(n,t,r),!0}return!1}function pc(e,t,n,r){if(r={lane:2,revertLane:Pf(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},mc(e)){if(t)throw Error(i(479))}else t=Ni(e,n,r,2),t!==null&&Pd(t,e,2)}function mc(e){var t=e.alternate;return e===L||t!==null&&t===L}function hc(e,t){Yo=Jo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function gc(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,wt(e,n)}}var _c={readContext:ka,use:fs,useCallback:z,useContext:z,useEffect:z,useImperativeHandle:z,useLayoutEffect:z,useInsertionEffect:z,useMemo:z,useReducer:z,useRef:z,useState:z,useDebugValue:z,useDeferredValue:z,useTransition:z,useSyncExternalStore:z,useId:z,useHostTransitionStatus:z,useFormState:z,useActionState:z,useOptimistic:z,useMemoCache:z,useCacheRefresh:z,useEffectEvent:z},vc={readContext:ka,use:fs,useCallback:function(e,t){return ls().memoizedState=[e,t===void 0?null:t],e},useContext:ka,useEffect:Hs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),Bs(4194308,4,Js.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Bs(4194308,4,e,t)},useInsertionEffect:function(e,t){Bs(4,2,e,t)},useMemo:function(e,t){var n=ls();t=t===void 0?null:t;var r=e();if(Xo){st(!0);try{e()}finally{st(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=ls();if(n!==void 0){var i=n(t);if(Xo){st(!0);try{n(t)}finally{st(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=uc.bind(null,L,e),[r.memoizedState,e]},useRef:function(e){var t=ls();return e={current:e},t.memoizedState=e},useState:function(e){e=ws(e);var t=e.queue,n=dc.bind(null,L,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Xs,useDeferredValue:function(e,t){return $s(ls(),e,t)},useTransition:function(){var e=ws(!1);return e=tc.bind(null,L,e.queue,!0,!1),ls().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=L,a=ls();if(I){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),G===null)throw Error(i(349));q&127||ys(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,Hs(xs.bind(null,r,o,e),[e]),r.flags|=2048,Rs(9,{destroy:void 0},bs.bind(null,r,o,n,t),null),n},useId:function(){var e=ls(),t=G.identifierPrefix;if(I){var n=na,r=ta;n=(r&~(1<<32-ct(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Zo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[jt]=t,o[Mt]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(np(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&gl(t)}}return V(t),t.subtreeFlags&=-33554433,_l(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&gl(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=Fe.current,ha(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=ca,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[jt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||ep(e.nodeValue,n)),e||fa(t,!0)}else e=lp(e).createTextNode(r),e[jt]=t,t.stateNode=e}return V(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=ha(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[jt]=t}else ga(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;V(t),e=!1}else n=_a(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(Vo(t),t):(Vo(t),null);if(t.flags&128)throw Error(i(558))}return V(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=ha(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[jt]=t}else ga(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;V(t),a=!1}else a=_a(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(Vo(t),t):(Vo(t),null)}return Vo(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),yl(t,t.updateQueue),V(t),null);case 4:return Re(),e===null&&Wf(t.stateNode.containerInfo),t.flags|=67108864,V(t),null;case 10:return Ca(t.type),V(t),null;case 19:if(Wo(t),r=t.memoizedState,r===null)return V(t),null;if(a=!!(t.flags&128),o=r.rendering,o===null){if(a)bl(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=Go(e),o!==null){for(t.flags|=128,bl(r,!1),e=o.updateQueue,t.updateQueue=e,yl(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)Hi(n,e),n=n.sibling;return Uo(t,Ho.current&1|2),I&&ra(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&D()>_d&&(t.flags|=128,a=!0,bl(r,!1),t.lanes=4194304)}}else{if(!a){if(e=Go(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,yl(t,e),bl(r,!0),r.tail===null&&r.tailMode!==`collapsed`&&r.tailMode!==`visible`&&!o.alternate&&!I)return V(t),null}else 2*D()-r.renderingStartTime>_d&&n!==536870912&&(t.flags|=128,a=!0,bl(r,!1),t.lanes=4194304)}r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}if(r.tail!==null){e=r.tail;a:{for(n=e;n!==null;){if(n.alternate!==null){n=!1;break a}n=n.sibling}n=!0}return r.rendering=e,r.tail=e.sibling,r.renderingStartTime=D(),e.sibling=null,o=Ho.current,o=a?o&1|2:o&1,r.tailMode===`visible`||r.tailMode===`collapsed`||!n||I?Uo(t,o):(n=o,T(Fo,t),T(Ho,n),Io===null&&(Io=t)),I&&ra(t,r.treeForkCount),e}return V(t),null;case 22:case 23:return Vo(t),Po(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(V(t),t.subtreeFlags&6&&(t.flags|=8192)):V(t),n=t.updateQueue,n!==null&&yl(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&Me(Ya),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),Ca(Fa),V(t),null;case 25:return null;case 30:return t.flags|=33554432,V(t),null}throw Error(i(156,t.tag))}function Sl(e,t){switch(oa(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Ca(Fa),Re(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Be(t),null;case 31:if(t.memoizedState!==null){if(Vo(t),t.alternate===null)throw Error(i(340));ga()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Vo(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));ga()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Wo(t),e=t.flags,e&65536?(t.flags=e&-65537|128,e=t.memoizedState,e!==null&&(e.rendering=null,e.tail=null),t.flags|=4,t):null;case 4:return Re(),null;case 10:return Ca(t.type),null;case 22:case 23:return Vo(t),Po(),e!==null&&Me(Ya),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return Ca(Fa),null;case 25:return null;default:return null}}function Cl(e,t){switch(oa(t),t.tag){case 3:Ca(Fa),Re();break;case 26:case 27:case 5:Be(t);break;case 4:Re();break;case 31:t.memoizedState!==null&&Vo(t);break;case 13:Vo(t);break;case 19:Wo(t);break;case 10:Ca(t.type);break;case 22:case 23:Vo(t),Po(),e!==null&&Me(Ya);break;case 24:Ca(Fa)}}function wl(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Tl(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function El(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{ko(t,n)}catch(t){Z(e,e.return,t)}}}function Dl(e,t,n){n.props=Tc(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Ol(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:var i=e.stateNode,a=wi(e.memoizedProps,i);(i.ref===null||i.ref.name!==a)&&(i.ref=Pp(a)),r=i.ref;break;case 7:if(e.stateNode===null){var o=new Fp(e);h(e.child,!1,Qp,o,void 0,void 0),e.stateNode=o}r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function kl(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}}function Al(e,t){if((e.tag===5||e.tag===27||e.tag===6)&&e.alternate===null&&t!==null)for(var n=0;n title`))),np(r,t,n),r[jt]=e,Gt(r),t=r;break a;case`link`:if(o=Gm(`link`,`href`,a).get(t+(n.href||``))){for(s=0;sg&&(o=g,g=h,h=o);var _=Qr(s,h),v=Qr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,C.T=null,n=wd,wd=null;var o=bd,s=Sd;if(X=0,xd=bd=null,Sd=0,W&6)throw Error(i(331));var c=W;if(W|=4,Zu(o.current),Uu(o,o.current,s,n),W=c,Df(0,!1),ot&&typeof ot.onPostCommitFiberRoot==`function`)try{ot.onPostCommitFiberRoot(at,o)}catch{}return!0}finally{w.p=a,C.T=r,uf(e,t)}}function pf(e,t,n){t=Yi(n,t),t=jc(e.stateNode,t,2),e=So(e,t,2),e!==null&&(xt(e,2),Ef(e))}function Z(e,t,n){if(e.tag===3)pf(e,e,n);else for(;t!==null;){if(t.tag===3){pf(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(yd===null||!yd.has(r))){e=Yi(n,e),n=Mc(2),r=So(t,n,2),r!==null&&(Nc(n,r,t,e),xt(r,2),Ef(r));break}}t=t.return}}function mf(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new td;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(ad=!0,i.add(n),e=hf.bind(null,e,t,n),t.then(e,e))}function hf(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>D()-hd?W&2?ld|=n:Vd(e,0):ld|=n,dd===q&&(dd=0)),Ef(e)}function gf(e,t){t===0&&(t=k()),e=Pi(e,t),e!==null&&(xt(e,t),Ef(e))}function _f(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),gf(e,n)}function vf(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),gf(e,n)}function yf(e,t){return Je(e,t)}var bf=null,xf=null,Sf=!1,Cf=!1,wf=!1,Tf=0;function Ef(e){e!==xf&&e.next===null&&(xf===null?bf=xf=e:xf=xf.next=e),Cf=!0,Sf||(Sf=!0,Nf())}function Df(e,t){if(!wf&&Cf){wf=!0;do for(var n=!1,r=bf;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-ct(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,Mf(r,a))}else a=q,a=gt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||_t(r,a)||(n=!0,Mf(r,a))}r=r.next}while(n);wf=!1}}function Of(){kf()}function kf(){Cf=Sf=!1;var e=0;Tf!==0&&hp()&&(e=Tf);for(var t=D(),n=null,r=bf;r!==null;){var i=r.next,a=Af(r,t);a===0?(r.next=null,n===null?bf=i:n.next=i,i===null&&(xf=n)):(n=r,(e!==0||a&3)&&(Cf=!0)),r=i}X!==0&&X!==5||Df(e,!1),Tf!==0&&(Tf=0)}function Af(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&ap(d)&&(c=c.responseEnd,o+=u*(c$m){s.length=o;break}f=new Promise(jp.bind(f)),s.push(f)}}}if(0`u`?null:document;function Tm(e,t,n){var r=wm;if(r&&typeof t==`string`&&t){var i=fn(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),ym.has(i)||(ym.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),np(t,`link`,e),Gt(t),r.head.appendChild(t)))}}function Em(e){xm.D(e),Tm(`dns-prefetch`,e,null)}function Dm(e,t){xm.C(e,t),Tm(`preconnect`,e,t)}function Om(e,t,n){xm.L(e,t,n);var r=wm;if(r&&e&&t){var i=`link[rel="preload"][as="`+fn(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+fn(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+fn(n.imageSizes)+`"]`)):i+=`[href="`+fn(e)+`"]`;var a=i;switch(t){case`style`:a=Pm(e);break;case`script`:a=Rm(e)}if(!(vm.has(a)||(e=S({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),vm.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Fm(a))||t===`script`&&r.querySelector(zm(a))))){var o=r.createElement(`link`);np(o,`link`,e),t===`style`&&(o[zt]=!0,o.onload=o.onerror=function(){Kt(o)}),Gt(o),r.head.appendChild(o)}}}function km(e,t){xm.m(e,t);var n=wm;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+fn(r)+`"][href="`+fn(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Rm(e)}if(!vm.has(a)&&(e=S({rel:`modulepreload`,href:e},t),vm.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(zm(a)))return}r=n.createElement(`link`),np(r,`link`,e),Gt(r),n.head.appendChild(r)}}}function Am(e,t,n){xm.S(e,t,n);var r=wm;if(r&&e){var i=Wt(r).hoistableStyles,a=Pm(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Fm(a)))s.loading=5;else{e=S({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=vm.get(a))&&Hm(e,n);var c=o=r.createElement(`link`);Gt(c),np(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Vm(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function jm(e,t){xm.X(e,t);var n=wm;if(n&&e){var r=Wt(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=S({src:e,async:!0},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Gt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Mm(e,t){xm.M(e,t);var n=wm;if(n&&e){var r=Wt(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=S({src:e,async:!0,type:`module`},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Gt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Nm(e,t,n,r){var a=(a=Fe.current)?bm(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(n=Pm(n.href),t=Wt(a).hoistableStyles,r=t.get(n),r||(r={type:`style`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Pm(n.href);var o=Wt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Fm(e)))?o._p||(s.instance=o,s.state.loading=5):(o=vm.get(e),o||(o={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},vm.set(e,o)),Lm(a,e,o,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(n=Rm(n),t=Wt(a).hoistableScripts,r=t.get(n),r||(r={type:`script`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Pm(e){return`href="`+fn(e)+`"`}function Fm(e){return`link[rel="stylesheet"][`+e+`]`}function Im(e){return S({},e,{"data-precedence":e.precedence,precedence:null})}function Lm(e,t,n,r){if(t=e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)){if(!0!==t[zt]){r.loading=1;return}}else t=e.createElement(`link`),t[zt]=!0,t.onload=t.onerror=Kt.bind(null,t),np(t,`link`,n),Gt(t),e.head.appendChild(t);r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2})}function Rm(e){return`[src="`+fn(e)+`"]`}function zm(e){return`script[async]`+e}function Bm(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+fn(n.href)+`"]`);if(r)return t.instance=r,Gt(r),r;var a=S({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),Gt(r),np(r,`style`,a),Vm(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Pm(n.href);var o=e.querySelector(Fm(a));if(o)return t.state.loading|=4,t.instance=o,Gt(o),o;r=Im(n),(a=vm.get(a))&&Hm(r,a),o=(e.ownerDocument||e).createElement(`link`),Gt(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),np(o,`link`,r),t.state.loading|=4,Vm(o,n.precedence,e),t.instance=o;case`script`:return o=Rm(n.src),(a=e.querySelector(zm(o)))?(t.instance=a,Gt(a),a):(r=n,(a=vm.get(o))&&(r=S({},n),Um(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),Gt(a),np(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Vm(r,n.precedence,e));return t.instance}function Vm(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function qm(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Jm(e,t){return e===`img`&&t.src!=null&&t.src!==``&&t.onLoad==null&&t.loading!==`lazy`}function Ym(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Xm(e){return(e.width||100)*(e.height||100)*(typeof devicePixelRatio==`number`?devicePixelRatio:1)*.25}function Zm(e,t){typeof t.decode==`function`&&(e.imgCount++,t.complete||(e.imgBytes+=Xm(t),e.suspenseyImages.push(t)),e=rh.bind(e),t.decode().then(e,e))}function Qm(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Pm(r.href),a=t.querySelector(Fm(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=nh.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,Gt(a);return}a=t.ownerDocument||t,r=Im(r),(i=vm.get(i))&&Hm(r,i),a=a.createElement(`link`),Gt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),np(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=nh.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var $m=0;function eh(e,t){return e.stylesheets&&e.count===0&&ah(e,e.stylesheets),0$m?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function th(e){if(e.count===0&&(e.imgCount===0||!e.waitingForImages)){if(e.stylesheets)ah(e,e.stylesheets);else if(e.unsuspend){var t=e.unsuspend;e.unsuspend=null,t()}}}function nh(){this.count--,th(this)}function rh(){this.imgCount--,th(this)}var ih=null;function ah(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ih=new Map,t.forEach(oh,e),ih=null,nh.call(e))}function oh(e,t){if(!(t.state.loading&4)){var n=ih.get(e);if(n)var r=n.get(null);else{n=new Map,ih.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=h()})),_=c(u(),1),v=g();function y(e,t){if(e instanceof RegExp)return{keys:!1,pattern:e};var n,r,i,a,o=[],s=``,c=e.split(`/`);for(c[0]||c.shift();i=c.shift();)n=i[0],n===`*`?(o.push(n),s+=i[1]===`?`?`(?:/(.*))?`:`/(.*)`):n===`:`?(r=i.indexOf(`?`,1),a=i.indexOf(`.`,1),o.push(i.substring(1,~r?r:~a?a:i.length)),s+=~r&&!~a?`(?:/([^/]+?))?`:`/([^/]+?)`,~a&&(s+=(~r?`?`:``)+`\\`+i.substring(a))):s+=`/`+i;return{keys:o,pattern:RegExp(`^`+s+(t?`(?=$|/)`:`/?$`),`i`)}}var b=o((e=>{var t=u();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,i=t.useState,a=t.useEffect,o=t.useLayoutEffect,s=t.useDebugValue;function c(e,t){var n=t(),r=i({inst:{value:n,getSnapshot:t}}),c=r[0].inst,u=r[1];return o(function(){c.value=n,c.getSnapshot=t,l(c)&&u({inst:c})},[e,n,t]),a(function(){return l(c)&&u({inst:c}),e(function(){l(c)&&u({inst:c})})},[e]),s(n),n}function l(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function d(e,t){return t()}var f=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?d:c;e.useSyncExternalStore=t.useSyncExternalStore===void 0?f:t.useSyncExternalStore})),ee=o(((e,t)=>{t.exports=b()}))(),te=_.useInsertionEffect,ne=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0?_.useLayoutEffect:_.useEffect,re=te||ne,x=e=>{let t=_.useRef([e,(...e)=>t[0](...e)]).current;return re(()=>{t[0]=e}),t[1]},ie=[`popstate`,`pushState`,`replaceState`,`hashchange`],S=[],ae=()=>S.forEach(e=>e()),oe=e=>(S.push(e)===1&&ie.forEach(e=>addEventListener(e,ae)),()=>{S=S.filter(t=>t!==e),S.length||ie.forEach(e=>removeEventListener(e,ae))}),se=(e,t)=>(0,ee.useSyncExternalStore)(oe,e,t),ce=()=>location.search,le=({ssrSearch:e}={})=>se(ce,e==null?ce:()=>e),ue=()=>location.pathname,de=({ssrPath:e}={})=>se(ue,e==null?ue:()=>e),fe=(e,{replace:t=!1,state:n=null}={})=>history[t?`replaceState`:`pushState`](n,``,e),pe=e=>[de(e),fe],me=Symbol.for(`wouter_v3`);if(typeof history<`u`&&window[me]===void 0){for(let e of[`pushState`,`replaceState`]){let t=history[e];history[e]=function(){let n=t.apply(this,arguments),r=new Event(e);return r.arguments=arguments,dispatchEvent(r),n}}Object.defineProperty(window,me,{value:!0})}var he=(e=``)=>e===`/`?``:e,ge=(e,t)=>e[0]===`~`?e.slice(1):he(t)+e,_e=(e,t)=>(e=ve(he(e)),t=ve(t),!e||!t.toLowerCase().indexOf(e.toLowerCase())?t.slice(e.length)||`/`:`~`+t),ve=e=>{try{return e.includes(`%`)?decodeURI(e):e}catch{return e}},ye=e=>ve(e[0]===`?`?e.slice(1):e),be={hook:pe,searchHook:le,parser:y,base:``,ssrPath:void 0,ssrSearch:void 0,ssrContext:void 0,hrefs:e=>e,aroundNav:(e,t,n)=>e(t,n)},xe=(0,_.createContext)(be),Se=()=>(0,_.useContext)(xe),Ce={},we=(0,_.createContext)(Ce),Te=()=>(0,_.useContext)(we),Ee=(e,t=e.base)=>_e(t,e.hook(e)[0]),De=e=>{let[t,n]=e.hook(e);return[_e(e.base,t),x((t,r)=>e.aroundNav(n,ge(t,e.base),r))]},C=()=>De(Se()),w=()=>{let e=Se();return ye(e.searchHook(e))},Oe=(e,t,n,r)=>{let{pattern:i,keys:a}=t instanceof RegExp?{pattern:t}:e(t||`*`,r),o=i.exec(n);if(!o)return[!1,null];let s={};for(let e=1;e{let n=Se(),r=t.hook?be:n,i=r;if(t.ssrPath){let[e,n=t.ssrSearch??``]=t.ssrPath.split(`?`);e&&(t.ssrSearch=n,t.ssrPath=e)}t.hrefs=t.hrefs??t.hook?.hrefs,t.searchHook=t.searchHook??t.hook?.searchHook;let a=(0,_.useRef)(r),o=a.current,s=o;for(let e in r){let n=e===`base`?r[e]+(t[e]??``):t[e]??r[e];n!==s[e]&&(o===s&&(a.current=s={...s}),s[e]=n),(n!==r[e]||n!==i[e])&&(i=s)}return(0,_.createElement)(xe.Provider,{value:i},e)},Ae=({children:e,component:t},n)=>t?(0,_.createElement)(t,{params:n}):typeof e==`function`?e(n):e,je=e=>{let t=(0,_.useRef)(Ce),n=t.current,r=Object.keys(e);return t.current=r.length!==Object.keys(n).length||r.some(t=>e[t]!==n[t])?e:n};function Me(){let[e,t]=C(),n=w(),r=(0,_.useMemo)(()=>new URLSearchParams(n),[n]),i=r;return[r,x((n,r)=>{i=new URLSearchParams(typeof n==`function`?n(i):n);let a=i.toString();t(e+(a?`?`+a:``),r)})]}var T=({path:e,nest:t,match:n,...r})=>{let i=Se(),a=Ee(i),[o,s,c]=n??Oe(i.parser,e,a,t),l=je({...Te(),...s});if(!o)return null;let u=Ae(r,l);return(0,_.createElement)(we.Provider,{value:l},c?(0,_.createElement)(ke,{base:c},u):u)},Ne=(0,_.forwardRef)((e,t)=>{let n=Se(),[r,i]=De(n),{to:a=``,href:o=a,onClick:s,asChild:c,children:l,className:u,replace:d,state:f,transition:p,...m}=e;return m.onClick=x(t=>{t.ctrlKey||t.metaKey||t.altKey||t.shiftKey||t.button!==0||(s?.(t),t.defaultPrevented||(t.preventDefault(),i(o,e)))}),m.href=n.hrefs(o[0]===`~`?o.slice(1):n.base+o,n),u!==void 0&&(m.className=u?.call?u(r===o):u),t&&(m.ref=t),c&&(0,_.isValidElement)(l)?(0,_.cloneElement)(l,m):(0,_.createElement)(`a`,m,l)}),Pe=(e,t=[])=>{if(Array.isArray(e))for(let n of e)Pe(n&&n.type===_.Fragment?n.props.children:n,t);else t.push(e);return t},Fe=({children:e,location:t})=>{let n=Se(),r=Ee(n);for(let i of Pe(e)){let e=0;if((0,_.isValidElement)(i)&&(e=Oe(n.parser,i.props.path,t||r,i.props.nest))[0])return(0,_.cloneElement)(i,{match:e})}return null},Ie=[`default`,`compact`],Le=(0,_.createContext)(null);function Re(){let e=(0,_.useContext)(Le);if(!e)throw Error(`useAppState must be used inside `);return e}var ze={theme:`ns-theme`,viewMode:`ns-view-mode`,sidebarCollapsed:`ns-sidebar-collapsed`};function Be(e,t){try{let n=localStorage.getItem(e);return n===null?void 0:t.includes(n)?n:void 0}catch{return}}function Ve(e,t){try{localStorage.setItem(e,t)}catch{}}function He(e){let t=Be(e,[`true`,`false`]);return t===void 0?void 0:t===`true`}function Ue(e,t){Ve(e,t?`true`:`false`)}var We=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),E=o(((e,t)=>{t.exports=We()}))();function Ge(e){let t=document.documentElement;t.dataset.theme=e,t.classList.toggle(`dark`,e===`dark`),t.classList.toggle(`light`,e===`light`)}function Ke(e){document.documentElement.dataset.viewMode=e}function qe(){return document.documentElement.getAttribute(`data-theme`)===`light`?`light`:`dark`}function Je(){return Be(ze.viewMode,Ie)??`default`}function Ye(){return He(ze.sidebarCollapsed)??!1}function Xe({children:e}){let[t,n]=(0,_.useState)(qe),[r,i]=(0,_.useState)(Je),[a,o]=(0,_.useState)(Ye),[s,c]=(0,_.useState)(!1);(0,_.useEffect)(()=>{Ge(t)},[t]),(0,_.useEffect)(()=>{Ke(r)},[r]),(0,_.useEffect)(()=>{let e=e=>{(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`&&(e.preventDefault(),c(e=>!e))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]);let l=(0,_.useCallback)(e=>{n(e),Ve(ze.theme,e)},[]),u=(0,_.useCallback)(()=>{l(t===`dark`?`light`:`dark`)},[t,l]),d=(0,_.useCallback)(e=>{i(e),Ve(ze.viewMode,e)},[]),f=(0,_.useCallback)(e=>{o(e),Ue(ze.sidebarCollapsed,e)},[]),p=(0,_.useCallback)(()=>{f(!a)},[a,f]),m=(0,_.useCallback)(()=>c(!0),[]),h=(0,_.useCallback)(()=>c(!1),[]),g=(0,_.useCallback)(()=>c(e=>!e),[]),v=(0,_.useMemo)(()=>({theme:t,viewMode:r,sidebarCollapsed:a,searchOpen:s,setTheme:l,toggleTheme:u,setViewMode:d,setSidebarCollapsed:f,toggleSidebar:p,openSearch:m,closeSearch:h,toggleSearch:g}),[t,r,a,s,l,u,d,f,p,m,h,g]);return(0,E.jsx)(Le.Provider,{value:v,children:e})}var Ze=[{id:`metrics`,label:`Metrics Dashboard`,icon:`sparkles`},{id:`settings`,label:`Settings & Safeguards`,icon:`settings`},{id:`table`,label:`Service Monitor Table`,icon:`layers`},{id:`deploy`,label:`Deployment Flow`,icon:`terminal`}];function D(...e){let t=[];for(let n of e)if(n){if(typeof n==`string`||typeof n==`number`)t.push(String(n));else if(Array.isArray(n)){let e=D(...n);e&&t.push(e)}else if(typeof n==`object`)for(let[e,r]of Object.entries(n))r&&t.push(e)}return t.join(` `)}function Qe({className:e,...t}){return(0,E.jsx)(`div`,{className:D(`surface-card`,e),...t})}function $e({className:e,...t}){return(0,E.jsx)(`div`,{className:D(`stack-xs`,e),style:{marginBottom:`var(--space-4)`},...t})}function et({className:e,children:t,...n}){return(0,E.jsx)(`h3`,{className:D(e),style:{margin:0,fontSize:`var(--text-lg)`,fontWeight:700,color:`var(--foreground)`,letterSpacing:`-0.02em`},...n,children:t})}function tt({className:e,...t}){return(0,E.jsx)(`p`,{className:D(e),style:{margin:0,fontSize:`var(--text-sm)`,color:`var(--muted-foreground)`,lineHeight:1.5},...t})}function nt({className:e,...t}){return(0,E.jsx)(`div`,{className:D(e),...t})}function rt({className:e,...t}){return(0,E.jsx)(`div`,{className:D(`flex-between`,e),style:{marginTop:`var(--space-5)`,paddingTop:`var(--space-4)`,borderTop:`1px solid var(--border)`},...t})}function O({variant:e=`primary`,className:t,children:n,...r}){return(0,E.jsx)(`span`,{className:D(`badge`,`badge-${e}`,t),...r,children:n})}function it(e){return!e||!/[0-9]/.test(e)?`neutral`:e.trim().startsWith(`-`)?`down`:`up`}function at({title:e,value:t,change:n,trend:r=`neutral`,direction:i,caption:a,icon:o,className:s}){let c=i??it(n);return(0,E.jsxs)(Qe,{className:D(`hover-lift`,s),children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-3)`},children:[(0,E.jsx)(`span`,{style:{fontFamily:`var(--font-mono)`,fontSize:`var(--text-3xs)`,textTransform:`uppercase`,letterSpacing:`0.08em`,color:`var(--muted-foreground)`},children:e}),o&&(0,E.jsx)(`div`,{style:{color:`var(--primary)`,display:`flex`,alignItems:`center`},children:o})]}),(0,E.jsx)(`div`,{style:{fontSize:`var(--text-2xl)`,fontWeight:800,color:`var(--foreground)`,lineHeight:1.1,letterSpacing:`-0.04em`,marginBottom:`var(--space-2)`},children:t}),(0,E.jsxs)(`div`,{className:`flex-between`,style:{marginTop:`var(--space-2)`},children:[n&&(0,E.jsxs)(O,{variant:r===`up`?`positive`:r===`down`?`destructive`:`secondary`,children:[c===`up`?`↑`:c===`down`?`↓`:`→`,` `,n]}),a&&(0,E.jsx)(`span`,{style:{fontSize:`var(--text-3xs)`,color:`var(--muted-foreground)`,fontFamily:`var(--font-mono)`},children:a})]})]})}function ot({value:e=0,max:t=100,indeterminate:n=!1,label:r,className:i,...a}){let o=Math.min(Math.max(Math.round(e/(t>0?t:100)*100),0),100),s=(0,_.useId)();return(0,E.jsxs)(`div`,{className:D(`stack-xs`,i),...a,children:[(r||!n)&&(0,E.jsxs)(`div`,{className:`flex-between`,style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`},children:[r&&(0,E.jsx)(`span`,{id:s,children:r}),!n&&(0,E.jsxs)(`span`,{style:{fontFamily:`var(--font-mono)`},children:[o,`%`]})]}),(0,E.jsx)(`div`,{className:`progress-container`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n?void 0:o,"aria-busy":n?!0:void 0,"aria-labelledby":r?s:void 0,children:(0,E.jsx)(`div`,{className:D(`progress-fill`,n&&`progress-indeterminate`),style:n?void 0:{width:`${o}%`}})})]})}var st=e=>e?.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase();function ct(e,t,n=[]){if(t==null)throw Error(`[lucide]: iconNode is required when icon name is used`);return{name:st(e),size:24,node:t,...n.length>0?{aliases:n}:{}}}var lt=e=>{let t=``,n=!1;for(let r of e){if(r===`-`||r===`_`||r<=` `){n=t.length>0;continue}t.length===0?t+=r.toLowerCase():t+=n?r.toUpperCase():r,n=!1}return t},ut=e=>{let t=lt(e);return t.charAt(0).toUpperCase()+t.slice(1)},dt=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),ft={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":2,"stroke-linecap":`round`,"stroke-linejoin":`round`};function pt(e){return e!=null}function mt(e,t={}){let n=t.attributeNames??{},r=e=>n[e]??e,i=e.size??e.width??ft.width,a=e.size??e.height??ft.height,o=e.aliases?.filter(e=>typeof e==`string`&&e.trim()!==``).map(e=>`lucide-${e}`)??[],s=[...e.name?[`lucide-${e.name}`]:[],...o],c=t.className?.split(` `).filter(Boolean)??[],l=t.includeDefaultClasses===!1?dt(...c):dt(`lucide`,...s,...c),u=t.absoluteStrokeWidth?Number(t.strokeWidth??ft[`stroke-width`])*Number(e.size??e.width??ft.width)/Number(t.size??t.width??ft.width):t.strokeWidth??ft[`stroke-width`];return[`svg`,{...Object.entries(ft).reduce((e,[t,n])=>(e[r(t)]=n,e),{}),...`color`in t&&t.color&&{[r(`stroke`)]:t.color},...`size`in t&&pt(t.size)&&{[r(`width`)]:t.size,[r(`height`)]:t.size},...`width`in t&&pt(t.width)&&{[r(`width`)]:t.width},...`height`in t&&pt(t.height)&&{[r(`height`)]:t.height},[r(`stroke-width`)]:u,...l&&{[r(`class`)]:l},[r(`viewBox`)]:`0 0 ${i} ${a}`,...t.hasA11yProp===!1?{[r(`aria-hidden`)]:`true`}:{},...`attributes`in t&&t.attributes},e.node.map(e=>{let[n,i,a]=e,o=t.nonScalingStroke?{[r(`vector-effect`)]:`non-scaling-stroke`,...i}:i;return a?[n,o,a]:[n,o]})]}function ht(e,t={}){return mt(e,{...t,attributeNames:{...t.attributeNames,class:`className`,"stroke-width":`strokeWidth`,"stroke-linecap":`strokeLinecap`,"stroke-linejoin":`strokeLinejoin`,"vector-effect":`vectorEffect`}})}var gt=e=>{for(let t in e)if(t.startsWith(`aria-`)||t===`role`||t===`title`)return!0;return!1},_t=(0,_.createContext)({}),vt=()=>(0,_.useContext)(_t),yt=(0,_.forwardRef)(({color:e,size:t,width:n,height:r,strokeWidth:i,absoluteStrokeWidth:a,nonScalingStroke:o,className:s=``,children:c,iconNode:l=[],icon:u={node:l,aliases:[],size:24},...d},f)=>{let{size:p=24,strokeWidth:m=2,absoluteStrokeWidth:h=!1,nonScalingStroke:g=!1,color:v=`currentColor`,className:y=``}=vt()??{},b=!!c||gt(d),[ee,te,ne=[]]=ht(u,{color:e??v,width:n??t??p,height:r??t??p,strokeWidth:i??m,absoluteStrokeWidth:a??h,nonScalingStroke:o??g,className:dt(y,s),hasA11yProp:b,attributes:d});return(0,_.createElement)(ee,{ref:f,...te},[...ne.map(([e,t])=>(0,_.createElement)(e,t)),...Array.isArray(c)?c:[c]])});function k(e,t=[],n=[]){let r=typeof e==`string`?ct(e,t,n):e,i=(0,_.forwardRef)(({className:e,...t},n)=>(0,_.createElement)(yt,{ref:n,icon:r,className:e,...t}));return r.name&&(i.displayName=ut(r.name)),i}var bt={name:`arrow-left`,size:24,node:[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]};bt.node;var xt=k(bt),St={name:`arrow-right`,size:24,node:[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]};St.node;var Ct=k(St),wt={name:`calendar`,size:24,node:[[`path`,{d:`M8 2v3`,key:`1ioesn`}],[`path`,{d:`M16 2v3`,key:`otl347`}],[`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`,key:`h1oib`}],[`path`,{d:`M3 9h18`,key:`1pudct`}]]};wt.node;var Tt=k(wt),Et={name:`check`,size:24,node:[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]};Et.node;var Dt=k(Et),Ot={name:`chevron-down`,size:24,node:[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]};Ot.node;var kt=k(Ot),At={name:`chevron-left`,size:24,node:[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]};At.node;var jt=k(At),Mt={name:`chevron-right`,size:24,node:[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]};Mt.node;var Nt=k(Mt),Pt={name:`chevron-up`,size:24,node:[[`path`,{d:`m18 15-6-6-6 6`,key:`153udz`}]]};Pt.node;var Ft=k(Pt),It={name:`circle-alert`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`12`,x2:`12`,y1:`8`,y2:`12`,key:`1pkeuh`}],[`line`,{x1:`12`,x2:`12.01`,y1:`16`,y2:`16`,key:`4dfq90`}]],aliases:[`alert-circle`]};It.node;var Lt=k(It),Rt={name:`circle-check`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m16 9-5.5 5.5L8 12`,key:`xofnsj`}]],aliases:[`check-circle-2`]};Rt.node;var zt=k(Rt),Bt={name:`circle-question-mark`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`help-circle`,`circle-help`]};Bt.node;var Vt=k(Bt),Ht={name:`clock`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]};Ht.node;var Ut=k(Ht),Wt={name:`code-xml`,size:24,node:[[`path`,{d:`m18 16 4-4-4-4`,key:`1inbqp`}],[`path`,{d:`m6 8-4 4 4 4`,key:`15zrgr`}],[`path`,{d:`m14.5 4-5 16`,key:`e7oirm`}]],aliases:[`code-2`]};Wt.node;var Gt=k(Wt),Kt={name:`copy`,size:24,node:[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]};Kt.node;var qt=k(Kt),Jt={name:`cpu`,size:24,node:[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]};Jt.node;var Yt=k(Jt),Xt={name:`database`,size:24,node:[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 5V19A9 3 0 0 0 21 19V5`,key:`1wlel7`}],[`path`,{d:`M3 12A9 3 0 0 0 21 12`,key:`mv7ke4`}]]};Xt.node;var Zt=k(Xt),Qt={name:`download`,size:24,node:[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]};Qt.node;var $t=k(Qt),en={name:`external-link`,size:24,node:[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]};en.node;var A=k(en),tn={name:`eye`,size:24,node:[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]};tn.node;var nn=k(tn),rn={name:`file-text`,size:24,node:[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10 9H8`,key:`b1mrlr`}],[`path`,{d:`M16 13H8`,key:`t4e002`}],[`path`,{d:`M16 17H8`,key:`z1uh3a`}]]};rn.node;var an=k(rn),on={name:`folder`,size:24,node:[[`path`,{d:`M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z`,key:`1kt360`}]]};on.node;var sn=k(on),cn={name:`funnel`,size:24,node:[[`path`,{d:`M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z`,key:`sc7q7i`}]],aliases:[`filter`]};cn.node;var ln=k(cn),un={name:`info`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]};un.node;var dn=k(un),fn={name:`layers`,size:24,node:[[`path`,{d:`M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z`,key:`zw3jo`}],[`path`,{d:`M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12`,key:`1wduqc`}],[`path`,{d:`M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17`,key:`kqbvx6`}]],aliases:[`layers-3`]};fn.node;var pn=k(fn),mn={name:`log-out`,size:24,node:[[`path`,{d:`m16 17 5-5-5-5`,key:`1bji2h`}],[`path`,{d:`M21 12H9`,key:`dn1m92`}],[`path`,{d:`M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4`,key:`1uf3rs`}]]};mn.node;var hn=k(mn),gn={name:`menu`,size:24,node:[[`path`,{d:`M4 5h16`,key:`1tepv9`}],[`path`,{d:`M4 12h16`,key:`1lakjw`}],[`path`,{d:`M4 19h16`,key:`1djgab`}]]};gn.node;var _n=k(gn),vn={name:`minus`,size:24,node:[[`path`,{d:`M5 12h14`,key:`1ays0h`}]]};vn.node;var yn=k(vn),bn={name:`moon`,size:24,node:[[`path`,{d:`M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401`,key:`kfwtm`}]]};bn.node;var xn=k(bn),Sn={name:`plus`,size:24,node:[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]};Sn.node;var Cn=k(Sn),wn={name:`refresh-cw`,size:24,node:[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]};wn.node;var Tn=k(wn),En={name:`search`,size:24,node:[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]};En.node;var Dn=k(En),On={name:`settings`,size:24,node:[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]};On.node;var kn=k(On),An={name:`shield`,size:24,node:[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}]]};An.node;var jn=k(An),Mn={name:`sliders-horizontal`,size:24,node:[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]};Mn.node;var Nn=k(Mn),Pn={name:`sparkles`,size:24,node:[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]],aliases:[`stars`]};Pn.node;var Fn=k(Pn),In={name:`sun`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`4`,key:`4exip2`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`m4.93 4.93 1.41 1.41`,key:`149t6j`}],[`path`,{d:`m17.66 17.66 1.41 1.41`,key:`ptbguv`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`m6.34 17.66-1.41 1.41`,key:`1m8zz5`}],[`path`,{d:`m19.07 4.93-1.41 1.41`,key:`1shlcs`}]]};In.node;var Ln=k(In),Rn={name:`terminal`,size:24,node:[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]};Rn.node;var zn=k(Rn),Bn={name:`trash`,size:24,node:[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]],aliases:[`trash-2`]};Bn.node;var Vn=k(Bn),Hn={name:`triangle-alert`,size:24,node:[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`alert-triangle`]};Hn.node;var Un=k(Hn),Wn={name:`upload`,size:24,node:[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]};Wn.node;var Gn=k(Wn),Kn={name:`user`,size:24,node:[[`path`,{d:`M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2`,key:`975kel`}],[`circle`,{cx:`12`,cy:`7`,r:`4`,key:`17ys0d`}]]};Kn.node;var qn=k(Kn),Jn={name:`x`,size:24,node:[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]};Jn.node;var Yn=k(Jn),Xn={"arrow-right":Ct,"arrow-left":xt,"chevron-right":Nt,"chevron-left":jt,"chevron-down":kt,"chevron-up":Ft,"external-link":A,menu:_n,sparkles:Fn,terminal:zn,code:Gt,cpu:Yt,layers:pn,sun:Ln,moon:xn,database:Zt,search:Dn,copy:qt,settings:kn,sliders:Nn,filter:ln,plus:Cn,minus:yn,trash:Vn,refresh:Tn,download:$t,upload:Gn,folder:sn,file:an,user:qn,"log-out":hn,calendar:Tt,clock:Ut,check:Dt,"check-circle":zt,warning:Un,alert:Lt,info:dn,close:Yn,shield:jn,help:Vt,eye:nn},Zn={arrow:Ct,sparkle:Fn,x:Yn,"trash-2":Vn,"alert-triangle":Un,"alert-circle":Lt},Qn={...Xn,...Zn},$n={"arrow-right":{pascalName:`ArrowRight`,category:`Navigation`},"arrow-left":{pascalName:`ArrowLeft`,category:`Navigation`},"chevron-right":{pascalName:`ChevronRight`,category:`Navigation`},"chevron-left":{pascalName:`ChevronLeft`,category:`Navigation`},"chevron-down":{pascalName:`ChevronDown`,category:`Navigation`},"chevron-up":{pascalName:`ChevronUp`,category:`Navigation`},"external-link":{pascalName:`ExternalLink`,category:`Navigation`},menu:{pascalName:`Menu`,category:`Navigation`},sparkles:{pascalName:`Sparkles`,category:`System`},terminal:{pascalName:`Terminal`,category:`System`},code:{pascalName:`Code2`,category:`System`},cpu:{pascalName:`Cpu`,category:`System`},layers:{pascalName:`Layers`,category:`System`},sun:{pascalName:`Sun`,category:`System`},moon:{pascalName:`Moon`,category:`System`},database:{pascalName:`Database`,category:`System`},search:{pascalName:`Search`,category:`Interface`},copy:{pascalName:`Copy`,category:`Interface`},settings:{pascalName:`Settings`,category:`Interface`},sliders:{pascalName:`SlidersHorizontal`,category:`Interface`},filter:{pascalName:`Filter`,category:`Interface`},plus:{pascalName:`Plus`,category:`Interface`},minus:{pascalName:`Minus`,category:`Interface`},trash:{pascalName:`Trash2`,category:`Interface`},refresh:{pascalName:`RefreshCw`,category:`Interface`},download:{pascalName:`Download`,category:`Interface`},upload:{pascalName:`Upload`,category:`Interface`},folder:{pascalName:`Folder`,category:`Interface`},file:{pascalName:`FileText`,category:`Interface`},user:{pascalName:`User`,category:`Interface`},"log-out":{pascalName:`LogOut`,category:`Interface`},calendar:{pascalName:`Calendar`,category:`Interface`},clock:{pascalName:`Clock`,category:`Interface`},check:{pascalName:`Check`,category:`Status`},"check-circle":{pascalName:`CheckCircle2`,category:`Status`},warning:{pascalName:`AlertTriangle`,category:`Status`},alert:{pascalName:`AlertCircle`,category:`Status`},info:{pascalName:`Info`,category:`Status`},close:{pascalName:`X`,category:`Status`},shield:{pascalName:`Shield`,category:`Status`},help:{pascalName:`HelpCircle`,category:`Status`},eye:{pascalName:`Eye`,category:`Status`}},er=Object.entries(Xn).map(([e,t])=>({name:e,pascalName:$n[e].pascalName,category:$n[e].category,component:t}));function j({name:e,icon:t,size:n=18,strokeWidth:r=1.8,className:i,...a}){let o=e?Qn[e]:void 0;if(!t&&!o){let t=`[Icon] Unknown icon name "${String(e)}". Add it to iconMap in src/components/icon-registry.ts or pass an explicit \`icon\` prop.`;console.error(t)}return(0,E.jsx)(t??o??pn,{size:n,strokeWidth:r,className:i,"aria-hidden":`true`,...a})}function tr({title:e=`System Overview`,description:t=`Real-time telemetry and resource saturation across clusters.`,className:n=``}){let[r,i]=(0,_.useState)(`24h`);return(0,E.jsxs)(`div`,{className:`stack-lg ${n}`,children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,E.jsxs)(`div`,{children:[(0,E.jsxs)(`div`,{className:`row-xs`,style:{marginBottom:`var(--space-1)`},children:[(0,E.jsx)(O,{variant:`positive`,children:`Live Telemetry`}),(0,E.jsx)(O,{variant:`outline`,children:`All Regions`})]}),(0,E.jsx)(`h3`,{style:{margin:`var(--space-1) 0`,fontSize:`var(--text-lg)`,fontWeight:700},children:e}),(0,E.jsx)(`p`,{style:{margin:0,color:`var(--muted-foreground)`,fontSize:`var(--text-xs)`},children:t})]}),(0,E.jsx)(`div`,{className:`row-xs`,children:[`24h`,`7d`,`30d`].map(e=>(0,E.jsx)(`button`,{className:`button ${r===e?`secondary`:`ghost`}`,style:{padding:`var(--space-1) var(--space-3)`,fontSize:`var(--text-xs)`},onClick:()=>i(e),children:e},e))})]}),(0,E.jsxs)(`div`,{className:`grid-3`,children:[(0,E.jsx)(at,{title:`Throughput`,value:r===`24h`?`14.2k req/s`:r===`7d`?`12.8k req/s`:`11.5k req/s`,change:`+18.4%`,trend:`up`,caption:`vs previous period`,icon:(0,E.jsx)(j,{name:`sparkles`,size:16})}),(0,E.jsx)(at,{title:`P99 Latency`,value:r===`24h`?`18ms`:r===`7d`?`22ms`:`25ms`,change:`-4.2ms`,trend:`up`,caption:`edge distribution`,icon:(0,E.jsx)(j,{name:`clock`,size:16})}),(0,E.jsx)(at,{title:`Error Rate`,value:`0.008%`,change:`-0.002%`,trend:`up`,caption:`within SLA (<0.05%)`,icon:(0,E.jsx)(j,{name:`shield`,size:16})})]}),(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,children:[(0,E.jsx)(et,{children:`Resource Utilization`}),(0,E.jsx)(`span`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:`Cluster: canary-prod-01`})]}),(0,E.jsx)(tt,{children:`Compute, memory, and persistent volume headroom.`})]}),(0,E.jsx)(nt,{children:(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsxs)(`div`,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-1)`},children:[(0,E.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,color:`var(--foreground)`,fontWeight:500},children:`Worker CPU Saturation`}),(0,E.jsx)(`span`,{className:`mono`,style:{fontSize:`var(--text-xs)`,color:`var(--primary)`},children:`48%`})]}),(0,E.jsx)(ot,{value:48})]}),(0,E.jsxs)(`div`,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-1)`},children:[(0,E.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,color:`var(--foreground)`,fontWeight:500},children:`Memory Allocation (16 GB Pool)`}),(0,E.jsx)(`span`,{className:`mono`,style:{fontSize:`var(--text-xs)`,color:`var(--primary)`},children:`74%`})]}),(0,E.jsx)(ot,{value:74})]}),(0,E.jsxs)(`div`,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-1)`},children:[(0,E.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,color:`var(--foreground)`,fontWeight:500},children:`Network Ingress Bandwidth`}),(0,E.jsx)(`span`,{className:`mono`,style:{fontSize:`var(--text-xs)`,color:`var(--chart-2)`},children:`28%`})]}),(0,E.jsx)(ot,{value:28})]})]})})]})]})}function nr(){let e=(0,_.useRef)(new Set);return(0,_.useEffect)(()=>{let t=e.current;return()=>{t.forEach(clearTimeout),t.clear()}},[]),{schedule:(0,_.useCallback)((t,n)=>{let r=setTimeout(()=>{e.current.delete(r),t()},n);return e.current.add(r),r},[]),clear:(0,_.useCallback)(()=>{e.current.forEach(clearTimeout),e.current.clear()},[])}}function rr({checked:e,defaultChecked:t=!1,onCheckedChange:n,disabled:r=!1,className:i,id:a,"aria-label":o}){let[s,c]=(0,_.useState)(t),l=e!==void 0,u=l?e:s;return(0,E.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":u,disabled:r,id:a,"aria-label":o,className:D(`switch-root`,u&&`checked`,i),onClick:()=>{if(r)return;let e=!u;l||c(e),n?.(e)},style:{opacity:r?.5:1,cursor:r?`not-allowed`:`pointer`},children:(0,E.jsx)(`span`,{className:`switch-thumb`})})}function ir({variant:e=`info`,icon:t,className:n,children:r,...i}){return(0,E.jsxs)(`div`,{className:D(`alert`,`alert-${e}`,n),role:`alert`,...i,children:[t&&(0,E.jsx)(`div`,{className:`alert-icon`,style:{display:`flex`,alignItems:`center`},children:t}),(0,E.jsx)(`div`,{className:`stack-xs`,style:{flex:1,minWidth:0},children:r})]})}function ar({className:e,children:t,...n}){return(0,E.jsx)(`h5`,{className:D(e),style:{margin:0,fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`,lineHeight:1.4},...n,children:t})}function or({className:e,...t}){return(0,E.jsx)(`p`,{className:D(e),style:{margin:0,fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,lineHeight:1.5},...t})}var sr=new Set([`button`,`input`,`select`,`textarea`,`summary`]);function cr(e){let t=e.props;return t.tabIndex===void 0?t.onClick===void 0?typeof e.type==`string`?e.type===`a`?t.href!==void 0:sr.has(e.type):!1:!0:t.tabIndex>=0}function lr({content:e,children:t,className:n}){let r=(0,_.useId)(),[i,a]=(0,_.useState)(!1),o=typeof t!=`string`&&typeof t!=`number`&&(0,_.isValidElement)(t)&&t.type!==_.Fragment?t:(0,E.jsx)(`span`,{children:t}),s=o.props[`aria-describedby`],c=s?`${s} ${r}`:r,l=(0,_.cloneElement)(o,{"aria-describedby":c}),u=!cr(o);return(0,E.jsxs)(`span`,{className:D(`tooltip-wrapper`,n),tabIndex:u?0:void 0,onMouseEnter:()=>a(!0),onMouseLeave:()=>a(!1),onFocus:()=>a(!0),onBlur:()=>a(!1),onKeyDown:e=>{e.key===`Escape`&&a(!1)},children:[l,(0,E.jsx)(`span`,{id:r,className:`tooltip-box`,role:`tooltip`,"aria-hidden":!i,"data-open":i?`true`:`false`,children:e})]})}function ur({className:e,...t}){return(0,E.jsx)(`kbd`,{className:D(`kbd-tag`,e),...t})}function dr(){let[e,t]=(0,_.useState)(!1),[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(!0),[c,l]=(0,_.useState)(!0),[u,d]=(0,_.useState)(!1),f=`nsk_live_98a72ef01bc34d89a2`,{schedule:p}=nr();return(0,E.jsxs)(`div`,{className:`stack-lg`,children:[(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,children:[(0,E.jsx)(et,{children:`Environment & Access Keys`}),(0,E.jsx)(O,{variant:`primary`,children:`Production`})]}),(0,E.jsx)(tt,{children:`Manage authentication credentials and runtime ingress access.`})]}),(0,E.jsx)(nt,{children:(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`label`,{style:{display:`block`,fontSize:`var(--text-xs)`,fontWeight:600,marginBottom:`var(--space-2)`},children:`Production Secret API Key`}),(0,E.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,E.jsxs)(`div`,{style:{flex:1,background:`var(--secondary)`,border:`1px solid var(--border)`,borderRadius:`var(--radius-md)`,padding:`var(--space-2) var(--space-3)`,fontFamily:`var(--font-mono)`,fontSize:`var(--text-xs)`,color:`var(--foreground)`,display:`flex`,alignItems:`center`,justifyContent:`space-between`},children:[(0,E.jsx)(`span`,{children:e?f:`••••••••••••••••••••••••••••••••`}),(0,E.jsx)(`button`,{className:`icon-button`,style:{padding:4},onClick:()=>t(!e),"aria-label":e?`Hide API key`:`Show API key`,children:(0,E.jsx)(j,{name:`eye`,size:14})})]}),(0,E.jsx)(lr,{content:`Copy key to clipboard`,children:(0,E.jsxs)(`button`,{className:`button secondary`,onClick:()=>{navigator.clipboard?.writeText(f),r(!0),p(()=>r(!1),2e3)},children:[(0,E.jsx)(j,{name:n?`check`:`copy`,size:14}),n?`Copied`:`Copy`]})})]})]}),(0,E.jsxs)(ir,{variant:`info`,children:[(0,E.jsx)(ar,{children:`Zero-Trust Rotation Enabled`}),(0,E.jsx)(or,{children:`Keys are automatically renewed every 90 days. Next scheduled rotation in 14 days.`})]})]})})]}),(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsx)(et,{children:`Deployment & Runtime Safeguards`}),(0,E.jsx)(tt,{children:`Fine-tune canary threshold tolerances and telemetry logging.`})]}),(0,E.jsx)(nt,{children:(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsxs)(`div`,{className:`flex-between`,children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`div`,{style:{fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`},children:`Automated Canary Progression`}),(0,E.jsx)(`div`,{style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,marginTop:2},children:`Gradually increase traffic from 5% to 100% based on error budget.`})]}),(0,E.jsx)(rr,{checked:o,onCheckedChange:s})]}),(0,E.jsxs)(`div`,{className:`flex-between`,style:{paddingTop:`var(--space-3)`,borderTop:`1px solid var(--border)`},children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`div`,{style:{fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`},children:`Detailed OpenTelemetry Tracing`}),(0,E.jsx)(`div`,{style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,marginTop:2},children:`Emit span metrics for all inbound HTTP and gRPC remote procedure calls.`})]}),(0,E.jsx)(rr,{checked:c,onCheckedChange:l})]}),(0,E.jsxs)(`div`,{className:`flex-between`,style:{paddingTop:`var(--space-3)`,borderTop:`1px solid var(--border)`},children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`div`,{style:{fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`},children:`Immediate Circuit-Breaker Rollback`}),(0,E.jsx)(`div`,{style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,marginTop:2},children:`Instantly revert to prior green build if P99 latency breaches 100ms.`})]}),(0,E.jsx)(rr,{checked:u,onCheckedChange:d})]})]})}),(0,E.jsxs)(rt,{children:[(0,E.jsxs)(`span`,{style:{fontSize:`var(--text-3xs)`,color:`var(--muted-foreground)`},children:[`Shortcut: `,(0,E.jsx)(ur,{children:`Ctrl`}),` + `,(0,E.jsx)(ur,{children:`S`}),` to persist`]}),(0,E.jsxs)(`div`,{className:`row-xs`,style:{marginLeft:`auto`},children:[(0,E.jsx)(`button`,{className:`button ghost`,children:`Discard`}),(0,E.jsxs)(`button`,{className:`button primary`,onClick:()=>{a(!0),p(()=>a(!1),2500)},children:[(0,E.jsx)(j,{name:i?`check`:`sparkles`,size:14}),i?`Saved Successfully`:`Save Changes`]})]})]})]})]})}function fr({className:e,...t}){return(0,E.jsx)(`div`,{className:`ui-table-container`,children:(0,E.jsx)(`table`,{className:D(`ui-table`,e),...t})})}function pr({className:e,...t}){return(0,E.jsx)(`thead`,{className:D(e),...t})}function mr({className:e,...t}){return(0,E.jsx)(`tbody`,{className:D(e),...t})}function hr({className:e,...t}){return(0,E.jsx)(`tr`,{className:D(e),...t})}function gr({className:e,...t}){return(0,E.jsx)(`th`,{className:D(e),...t})}function _r({className:e,...t}){return(0,E.jsx)(`td`,{className:D(e),...t})}function vr({className:e,...t}){return(0,E.jsx)(`div`,{className:D(`empty-state`,e),...t})}function yr({children:e,className:t}){return(0,E.jsx)(`div`,{className:D(`empty-state-icon`,t),children:e})}function br({className:e,children:t,...n}){return(0,E.jsx)(`h3`,{className:D(e),style:{margin:`0 0 var(--space-2)`,fontSize:`var(--text-lg)`,fontWeight:700,color:`var(--foreground)`,letterSpacing:`-0.02em`},...n,children:t})}function xr({className:e,...t}){return(0,E.jsx)(`p`,{className:D(e),style:{margin:`0 0 var(--space-5)`,fontSize:`var(--text-sm)`,color:`var(--muted-foreground)`,maxWidth:`420px`,lineHeight:1.6},...t})}function Sr({className:e,...t}){return(0,E.jsx)(`div`,{className:D(`row-sm`,e),...t})}var Cr=[{id:`1`,name:`api-gateway`,region:`us-east-1`,status:`healthy`,latency:`12ms`,memory:`128 MB`,instances:8},{id:`2`,name:`vector-indexer`,region:`eu-central-1`,status:`healthy`,latency:`34ms`,memory:`890 MB`,instances:4},{id:`3`,name:`model-inference`,region:`us-west-2`,status:`scaling`,latency:`78ms`,memory:`4.2 GB`,instances:16},{id:`4`,name:`session-broker`,region:`us-east-1`,status:`healthy`,latency:`8ms`,memory:`64 MB`,instances:6},{id:`5`,name:`analytics-worker`,region:`ap-northeast-1`,status:`degraded`,latency:`142ms`,memory:`1.8 GB`,instances:2},{id:`6`,name:`audit-logger`,region:`eu-west-1`,status:`healthy`,latency:`19ms`,memory:`210 MB`,instances:3}];function wr(){let[e,t]=(0,_.useState)(``),[n,r]=(0,_.useState)(`all`),i=(0,_.useMemo)(()=>Cr.filter(t=>{let r=t.name.toLowerCase().includes(e.toLowerCase())||t.region.toLowerCase().includes(e.toLowerCase()),i=n===`all`||t.status===n;return r&&i}),[e,n]);return(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,E.jsxs)(`div`,{className:`icon-search-bar`,style:{maxWidth:320},children:[(0,E.jsx)(j,{name:`search`,size:15}),(0,E.jsx)(`input`,{type:`text`,placeholder:`Filter services or regions...`,value:e,onChange:e=>t(e.target.value),className:`icon-search-input`}),e&&(0,E.jsx)(`button`,{className:`icon-clear-btn`,onClick:()=>t(``),children:(0,E.jsx)(j,{name:`close`,size:13})})]}),(0,E.jsx)(`div`,{className:`row-xs`,children:[`all`,`healthy`,`scaling`,`degraded`].map(e=>(0,E.jsx)(`button`,{className:`button ${n===e?`secondary`:`ghost`}`,style:{padding:`var(--space-1) var(--space-3)`,fontSize:`var(--text-xs)`,textTransform:`capitalize`},onClick:()=>r(e),children:e},e))})]}),i.length>0?(0,E.jsxs)(fr,{children:[(0,E.jsx)(pr,{children:(0,E.jsxs)(hr,{children:[(0,E.jsx)(gr,{children:`Service Name`}),(0,E.jsx)(gr,{children:`Region`}),(0,E.jsx)(gr,{children:`Status`}),(0,E.jsx)(gr,{children:`P99 Latency`}),(0,E.jsx)(gr,{children:`Memory`}),(0,E.jsx)(gr,{children:`Nodes`})]})}),(0,E.jsx)(mr,{children:i.map(e=>(0,E.jsxs)(hr,{children:[(0,E.jsx)(_r,{style:{fontWeight:600},children:(0,E.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,E.jsx)(`span`,{style:{width:7,height:7,borderRadius:`50%`,background:e.status===`healthy`?`var(--chart-2)`:e.status===`scaling`?`var(--primary)`:`var(--destructive)`,boxShadow:`0 0 8px ${e.status===`healthy`?`var(--chart-2)`:e.status===`scaling`?`var(--primary)`:`var(--destructive)`}`}}),e.name]})}),(0,E.jsx)(_r,{children:(0,E.jsx)(ur,{children:e.region})}),(0,E.jsx)(_r,{children:(0,E.jsx)(O,{variant:e.status===`healthy`?`positive`:e.status===`scaling`?`primary`:`destructive`,children:e.status})}),(0,E.jsx)(_r,{className:`mono`,style:{color:e.status===`degraded`?`var(--destructive)`:`var(--primary)`},children:e.latency}),(0,E.jsx)(_r,{className:`mono`,style:{color:`var(--muted-foreground)`},children:e.memory}),(0,E.jsx)(_r,{className:`mono`,style:{color:`var(--foreground)`},children:e.instances})]},e.id))})]}):(0,E.jsxs)(vr,{children:[(0,E.jsx)(yr,{children:(0,E.jsx)(j,{name:`search`,size:24})}),(0,E.jsx)(br,{children:`No matching services`}),(0,E.jsxs)(xr,{children:[`No active nodes or services match the current filter query "`,e,`".`]})]}),(0,E.jsxs)(`div`,{className:`flex-between muted`,style:{fontSize:`var(--text-3xs)`,padding:`0 var(--space-2)`},children:[(0,E.jsxs)(`span`,{children:[`Showing `,i.length,` of `,Cr.length,` deployed services`]}),(0,E.jsx)(`span`,{className:`mono`,children:`Synced live via cluster coordinator`})]})]})}var Tr=`a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])`;function Er(e,t){if(e.key!==`Tab`||!t)return;let n=Array.from(t.querySelectorAll(Tr));if(n.length===0){e.preventDefault(),t.focus();return}let r=n[0],i=n[n.length-1];if(!r||!i)return;let a=document.activeElement;e.shiftKey?(a===r||a===t)&&(e.preventDefault(),i.focus()):a===i&&(e.preventDefault(),r.focus())}function Dr(e,t){(0,_.useEffect)(()=>{if(!e)return;let n=document.activeElement,r=document.body.style.overflow;return document.body.style.overflow=`hidden`,t.current?.focus(),()=>{document.body.style.overflow=r,n&&document.contains(n)&&n.focus()}},[e,t])}var Or=(0,_.createContext)(null);function kr(){let e=(0,_.useContext)(Or);if(!e)throw Error(`Overlay components must be used within an (Dialog/Sheet)`);return e}var Ar={background:`none`,border:0,padding:0,font:`inherit`,color:`inherit`,cursor:`pointer`};function jr({next:e,setOpen:t,children:n,className:r,onClick:i,style:a,asChild:o=!1,...s}){let c=n=>{i?.(n),n.defaultPrevented||t(e)};if(o&&(0,_.isValidElement)(n)){let e=n,t={onClick:c};return r&&(t.className=D(e.props.className,r)),a&&(t.style={...e.props.style,...a}),(0,_.cloneElement)(e,t)}return(0,E.jsx)(`button`,{...s,type:`button`,className:r,style:{...Ar,...a},onClick:c,children:n})}function Mr({children:e,open:t,defaultOpen:n=!1,onOpenChange:r}){let[i,a]=(0,_.useState)(n),o=t!==void 0,s=o?t:i,[c,l]=(0,_.useState)(!1),[u,d]=(0,_.useState)(!1),f=(0,_.useId)(),p=(0,_.useId)(),m=(0,_.useCallback)(e=>{o||a(e),r?.(e)},[o,r]),h=(0,_.useCallback)(e=>l(e),[]),g=(0,_.useCallback)(e=>d(e),[]),v=(0,_.useMemo)(()=>({open:s,setOpen:m,titleId:f,descriptionId:p,hasTitle:c,hasDescription:u,registerTitle:h,registerDescription:g}),[s,m,f,p,c,u,h,g]);return(0,E.jsx)(Or.Provider,{value:v,children:e})}function Nr(e){let{setOpen:t}=kr();return(0,E.jsx)(jr,{...e,setOpen:t,next:!0})}function Pr({children:e,className:t,backdropClassName:n,panelClassName:r,closeButtonLabel:i}){let{open:a,setOpen:o,titleId:s,descriptionId:c,hasTitle:l,hasDescription:u}=kr(),d=(0,_.useRef)(null);return Dr(a,d),(0,_.useEffect)(()=>{if(!a)return;let e=e=>{e.key===`Escape`&&o(!1)};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[a,o]),a?(0,E.jsx)(`div`,{className:n,onClick:()=>o(!1),children:(0,E.jsxs)(`div`,{ref:d,role:`dialog`,"aria-modal":`true`,"aria-labelledby":l?s:void 0,"aria-describedby":u?c:void 0,tabIndex:-1,className:D(r,t),onKeyDown:e=>{Er(e,d.current)},onClick:e=>e.stopPropagation(),children:[(0,E.jsx)(`button`,{type:`button`,className:`dialog-close-btn`,onClick:()=>o(!1),"aria-label":i,children:`✕`}),e]})}):null}function Fr({className:e,style:t,...n}){return(0,E.jsx)(`div`,{className:D(`stack-xs`,e),style:t,...n})}function Ir({className:e,style:t,...n}){let{titleId:r,registerTitle:i}=kr();return(0,_.useEffect)(()=>(i(!0),()=>i(!1)),[i]),(0,E.jsx)(`h2`,{id:r,className:D(e),style:t,...n})}function Lr({className:e,style:t,...n}){let{descriptionId:r,registerDescription:i}=kr();return(0,_.useEffect)(()=>(i(!0),()=>i(!1)),[i]),(0,E.jsx)(`p`,{id:r,className:D(e),style:t,...n})}function Rr({className:e,style:t,...n}){return(0,E.jsx)(`div`,{className:D(`flex-between`,e),style:{paddingTop:`var(--space-4)`,borderTop:`1px solid var(--border)`,gap:`var(--space-3)`,...t},...n})}function zr(e){let{setOpen:t}=kr();return(0,E.jsx)(jr,{...e,setOpen:t,next:!1})}function Br(e){return(0,E.jsx)(Mr,{...e})}function Vr(e){return(0,E.jsx)(Nr,{...e})}function Hr({children:e,className:t}){return(0,E.jsx)(Pr,{backdropClassName:`dialog-backdrop`,panelClassName:`dialog-panel`,closeButtonLabel:`Close dialog`,className:t,children:e})}function Ur({className:e,style:t,...n}){let r={marginBottom:`var(--space-4)`,...t};return(0,E.jsx)(Fr,{className:e,style:r,...n})}function Wr({className:e,style:t,...n}){let r={margin:0,fontSize:`var(--text-xl)`,fontWeight:700,color:`var(--foreground)`,letterSpacing:`-0.03em`,...t};return(0,E.jsx)(Ir,{className:e,style:r,...n})}function Gr({className:e,style:t,...n}){let r={margin:0,fontSize:`var(--text-sm)`,color:`var(--muted-foreground)`,lineHeight:1.5,...t};return(0,E.jsx)(Lr,{className:e,style:r,...n})}function Kr({className:e,style:t,...n}){let r={marginTop:`var(--space-6)`,...t};return(0,E.jsx)(Rr,{className:e,style:r,...n})}function qr(e){return(0,E.jsx)(zr,{...e})}function Jr(){let[e,t]=(0,_.useState)(!1),[n,r]=(0,_.useState)(!0),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(!1),[c,l]=(0,_.useState)(0),[u,d]=(0,_.useState)(!1),{schedule:f,clear:p}=nr(),{schedule:m}=nr();return(0,_.useEffect)(()=>{e||p()},[e,p]),(0,E.jsxs)(Br,{open:e,onOpenChange:t,children:[(0,E.jsx)(Vr,{asChild:!0,children:(0,E.jsxs)(`button`,{className:`button primary`,children:[(0,E.jsx)(j,{name:`sparkles`,size:15}),` Promote Release to Canary`]})}),(0,E.jsxs)(Hr,{children:[(0,E.jsxs)(Ur,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-2)`},children:[(0,E.jsx)(Wr,{children:`Canary Rollout: release-2026.09.12`}),(0,E.jsx)(O,{variant:`primary`,children:`v2.4.0`})]}),(0,E.jsxs)(Gr,{children:[`Targeting production cluster `,(0,E.jsx)(`code`,{style:{color:`var(--primary)`,fontFamily:`var(--font-mono)`},children:`canary-prod-01`}),`.`]})]}),(0,E.jsx)(`div`,{className:`stack-md`,style:{margin:`var(--space-4) 0`},children:u?(0,E.jsxs)(ir,{variant:`positive`,children:[(0,E.jsx)(ar,{children:`Deployment Succeeded!`}),(0,E.jsx)(or,{children:`Build is now receiving live canary traffic. Telemetry reports 0 errors and 14ms latency.`})]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(ir,{variant:`warning`,children:[(0,E.jsx)(ar,{children:`Canary Traffic Notice`}),(0,E.jsx)(or,{children:`This deployment will divert 10% of production ingress traffic to the new build.`})]}),(0,E.jsxs)(`div`,{className:`stack-sm`,style:{background:`var(--secondary)`,padding:`var(--space-4)`,borderRadius:`var(--radius-lg)`},children:[(0,E.jsxs)(`div`,{className:`flex-between`,children:[(0,E.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,fontWeight:500},children:`Gradual Traffic Ingress (10% → 50% → 100%)`}),(0,E.jsx)(rr,{checked:n,onCheckedChange:r})]}),(0,E.jsxs)(`div`,{className:`flex-between`,style:{paddingTop:`var(--space-2)`,borderTop:`1px solid var(--border)`},children:[(0,E.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,fontWeight:500},children:`Bypass Pre-Flight Synthetic Probes`}),(0,E.jsx)(rr,{checked:i,onCheckedChange:a})]})]}),o&&(0,E.jsxs)(`div`,{className:`stack-xs`,children:[(0,E.jsx)(ot,{value:c,label:`Applying Canary Weights...`}),(0,E.jsx)(`span`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:`Streaming build manifests to regional edge nodes...`})]})]})}),(0,E.jsx)(Kr,{children:u?(0,E.jsxs)(`button`,{className:`button primary`,style:{width:`100%`},onClick:()=>{t(!1),m(()=>{s(!1),l(0),d(!1)},300)},children:[(0,E.jsx)(j,{name:`check`,size:14}),` Done`]}):(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(qr,{asChild:!0,children:(0,E.jsx)(`button`,{className:`button secondary`,disabled:o,children:`Cancel`})}),(0,E.jsxs)(`button`,{className:`button primary`,onClick:()=>{s(!0),l(15),f(()=>l(45),500),f(()=>l(85),1e3),f(()=>{l(100),s(!1),d(!0)},1500)},disabled:o,children:[(0,E.jsx)(j,{name:o?`refresh`:`arrow-right`,size:14}),o?`Deploying...`:`Confirm Rollout`]})]})})]})]})}function Yr({activePattern:e,onPatternChange:t}={}){let[n,r]=(0,_.useState)(`metrics`),i=e??n,a=e=>{r(e),t?.(e)};return(0,E.jsxs)(`div`,{className:`stack-lg`,children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,E.jsx)(`div`,{className:`segmented`,children:Ze.map(e=>(0,E.jsxs)(`button`,{type:`button`,className:i===e.id?`selected`:``,"aria-pressed":i===e.id,onClick:()=>a(e.id),children:[(0,E.jsx)(j,{name:e.icon,size:15}),(0,E.jsx)(`span`,{children:e.label})]},e.id))}),(0,E.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,E.jsx)(O,{variant:`outline`,children:`Interactive Component`}),(0,E.jsx)(O,{variant:`primary`,children:`Composable`})]})]}),(0,E.jsxs)(`div`,{className:`surface-card`,style:{padding:`var(--space-6)`,borderRadius:`var(--radius-xl)`},children:[i===`metrics`&&(0,E.jsx)(tr,{}),i===`settings`&&(0,E.jsx)(dr,{}),i===`table`&&(0,E.jsx)(wr,{}),i===`deploy`&&(0,E.jsx)(`div`,{className:`stack-md`,style:{maxWidth:640,margin:`0 auto`,textAlign:`center`,padding:`var(--space-6) 0`},children:(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsx)(et,{children:`Canary Deployment Orchestrator`}),(0,E.jsx)(tt,{children:`A complete interactive modal flow demonstrating Dialog, Alert, Switch, and Progress components.`})]}),(0,E.jsx)(nt,{children:(0,E.jsx)(`div`,{style:{padding:`var(--space-6) 0`},children:(0,E.jsx)(Jr,{})})})]})})]})]})}function Xr(){let[e,t]=Me(),n=e.get(`pattern`),r=Ze.some(e=>e.id===n)?n:`metrics`;return(0,E.jsx)(Yr,{activePattern:r,onPatternChange:e=>{t(t=>{let n=new URLSearchParams(t);return n.set(`pattern`,e),n},{replace:!0})}})}function M({variant:e=`secondary`,className:t=``,children:n,...r}){return(0,E.jsx)(`button`,{className:`button ${e} ${t}`.trim(),...r,children:n})}function Zr({href:e,variant:t=`secondary`,className:n=``,children:r}){return(0,E.jsx)(Ne,{href:e,className:`button ${t} ${n}`.trim(),children:r})}var Qr=(0,_.createContext)(null);function $r(){let e=(0,_.useContext)(Qr);if(!e)throw Error(`Tabs components must be used within `);return e}function ei(e,t,n){return`${e}-${t}-${n.replace(/[^A-Za-z0-9_-]+/g,`-`)}`}function ti({defaultValue:e=``,value:t,onValueChange:n,children:r,className:i}){let[a,o]=(0,_.useState)(e),s=(0,_.useId)(),c=t!==void 0,l=c?t:a;return(0,E.jsx)(Qr.Provider,{value:{value:l,setValue:e=>{c||o(e),n?.(e)},baseId:s},children:(0,E.jsx)(`div`,{className:D(`ui-tabs-root`,i),children:r})})}var ni=new Set([`ArrowRight`,`ArrowLeft`,`Home`,`End`]);function ri({className:e,onKeyDown:t,...n}){let{setValue:r}=$r();return(0,E.jsx)(`div`,{className:D(`ui-tabs-list`,e),role:`tablist`,"aria-orientation":`horizontal`,onKeyDown:e=>{if(t?.(e),e.defaultPrevented||!ni.has(e.key))return;let n=Array.from(e.currentTarget.querySelectorAll(`[role="tab"]:not([disabled])`));if(n.length===0)return;let i=n.indexOf(document.activeElement),a=n.findIndex(e=>e.getAttribute(`aria-selected`)===`true`),o=i>=0?i:a;if(o<0)return;let s;switch(e.key){case`ArrowRight`:s=(o+1)%n.length;break;case`ArrowLeft`:s=(o-1+n.length)%n.length;break;case`Home`:s=0;break;default:s=n.length-1}let c=n[s];if(c===void 0)return;let l=c.dataset.value;l!==void 0&&(e.preventDefault(),c.focus(),r(l))},...n})}function ii({value:e,className:t,children:n,...r}){let{value:i,setValue:a,baseId:o}=$r(),s=i===e;return(0,E.jsx)(`button`,{type:`button`,id:ei(o,`trigger`,e),role:`tab`,"aria-selected":s,"aria-controls":ei(o,`content`,e),tabIndex:s?0:-1,"data-value":e,className:D(`ui-tabs-trigger`,s&&`active`,t),onClick:()=>a(e),...r,children:n})}function ai({value:e,className:t,children:n,...r}){let{value:i,baseId:a}=$r(),o=i===e;return(0,E.jsx)(`div`,{id:ei(a,`content`,e),role:`tabpanel`,"aria-labelledby":ei(a,`trigger`,e),tabIndex:0,hidden:!o,className:D(`ui-tabs-content`,t),...r,children:n})}function oi({variant:e=`text`,width:t,height:n,className:r,style:i,...a}){return(0,E.jsx)(`div`,{className:D(`skeleton`,e===`circle`?`skeleton-circle`:e===`rect`?`skeleton-rect`:`skeleton-text`,r),style:{width:t===void 0?void 0:typeof t==`number`?`${t}px`:t,height:n===void 0?void 0:typeof n==`number`?`${n}px`:n,...i},"aria-hidden":`true`,...a})}var si={xs:`var(--space-5)`,sm:`var(--space-6)`,md:`var(--space-7)`,lg:`var(--space-9)`},ci={xs:`var(--text-3xs)`,sm:`var(--text-2xs)`,md:`var(--text-xs)`,lg:`var(--text-base)`},li={xs:`var(--space-1)`,sm:`var(--space-1)`,md:`var(--space-2)`,lg:`var(--space-2)`},ui={online:`var(--chart-2)`,away:`var(--chart-3)`,offline:`var(--muted-foreground)`};function di(e){return e.trim().split(/\s+/).filter(Boolean).slice(0,2).map(e=>e.charAt(0)).join(``).toUpperCase()||`?`}function fi({name:e,src:t,size:n=`md`,status:r,className:i}){let a=si[n];return(0,E.jsxs)(`span`,{className:D(`flex-center`,i),role:t?void 0:`img`,"aria-label":t?void 0:e||`Avatar`,style:{position:`relative`,flexShrink:0,width:a,height:a,borderRadius:`var(--radius-pill)`,background:`color-mix(in srgb, var(--primary) 16%, var(--background))`,color:`var(--primary)`,fontFamily:`var(--font-sans)`,fontSize:ci[n],fontWeight:700,lineHeight:1,letterSpacing:`0.02em`,userSelect:`none`},children:[t?(0,E.jsx)(`img`,{src:t,alt:e,style:{display:`block`,width:`100%`,height:`100%`,objectFit:`cover`,borderRadius:`var(--radius-pill)`}}):(0,E.jsx)(`span`,{"aria-hidden":`true`,children:di(e)}),r&&(0,E.jsx)(`span`,{"aria-hidden":`true`,style:{position:`absolute`,right:0,bottom:0,boxSizing:`content-box`,width:li[n],height:li[n],borderRadius:`var(--radius-pill)`,background:ui[r],border:`2px solid var(--background)`}})]})}var pi={xs:{width:`var(--space-3)`,height:`var(--space-3)`,borderWidth:`1px`},sm:{width:`var(--space-4)`,height:`var(--space-4)`,borderWidth:`2px`},md:{width:`var(--space-6)`,height:`var(--space-6)`,borderWidth:`2px`},lg:{width:`var(--space-8)`,height:`var(--space-8)`,borderWidth:`3px`}},mi={position:`absolute`,width:`1px`,height:`1px`,padding:0,margin:`-1px`,overflow:`hidden`,clip:`rect(0 0 0 0)`,whiteSpace:`nowrap`,borderWidth:0};function hi({size:e=`md`,label:t,className:n}){return(0,E.jsxs)(`div`,{role:`status`,"aria-live":`polite`,className:D(`ui-spinner`,`ui-spinner-${e}`,n),children:[(0,E.jsx)(`span`,{"aria-hidden":`true`,style:{display:`inline-block`,boxSizing:`border-box`,borderStyle:`solid`,borderColor:`var(--border)`,borderTopColor:`var(--primary)`,borderRadius:`50%`,animation:`spin 0.8s linear infinite`,...pi[e]}}),t?(0,E.jsx)(`span`,{className:`visually-hidden`,style:mi,children:t}):null]})}function gi({examples:e,tabs:t,filter:n=``,activeTab:r,onTabChange:i}){let a=e.filter(e=>`${e.name} ${e.label}`.toLowerCase().includes(n.toLowerCase()));return(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`div`,{className:`tabs`,children:t.map(e=>(0,E.jsx)(`button`,{className:e===r?`tab active`:`tab`,onClick:()=>i?.(e),children:e},e))}),(0,E.jsxs)(`div`,{className:`showcase`,children:[(0,E.jsxs)(`div`,{className:`showcase-head`,children:[(0,E.jsx)(`span`,{className:`eyebrow`,children:`Interactive states`}),(0,E.jsx)(`span`,{className:`mono muted`,children:`button.tsx`})]}),(0,E.jsx)(`div`,{className:`button-matrix`,children:a.map(e=>(0,E.jsxs)(`div`,{className:`button-row`,children:[(0,E.jsx)(`span`,{className:`row-label`,children:e.name}),(0,E.jsx)(M,{variant:e.variant,children:e.label}),(0,E.jsx)(M,{variant:e.variant,className:`hover-state`,children:e.label}),(0,E.jsx)(M,{variant:e.variant,className:`icon-only`,"aria-label":`${e.name} icon button`,children:(0,E.jsx)(j,{name:`copy`,size:15})}),(0,E.jsxs)(M,{variant:e.variant,className:`loading`,children:[(0,E.jsx)(hi,{size:`xs`}),`Loading`]})]},e.name))}),(0,E.jsxs)(`div`,{className:`showcase-foot`,children:[(0,E.jsx)(`span`,{className:`muted`,children:`Density`}),(0,E.jsxs)(`button`,{className:`density active`,children:[`Compact `,(0,E.jsx)(`span`,{children:`32px`})]}),(0,E.jsxs)(`button`,{className:`density`,children:[`Default `,(0,E.jsx)(`span`,{children:`40px`})]}),(0,E.jsxs)(`span`,{className:`foot-check`,children:[(0,E.jsx)(j,{name:`check`,size:14}),` Keyboard ready`]})]})]})]})}var _i=[`Preview`,`API reference`,`Usage`],vi=[{name:`Primary`,label:`Deploy changes`,variant:`primary`},{name:`Secondary`,label:`View activity`,variant:`secondary`},{name:`Destructive`,label:`Delete project`,variant:`danger`},{name:`Ghost`,label:`Cancel`,variant:`ghost`}],yi=[{name:`Primary`,color:`var(--primary)`,value:`lab(89.9% -47.9 -15.7)`},{name:`Background`,color:`var(--background)`,value:`lab(0% 0 0)`},{name:`Card`,color:`var(--card)`,value:`lab(0.9% 0 0)`},{name:`Destructive`,color:`var(--destructive)`,value:`lab(54.6% 71.7 50.9)`},{name:`Chart 1`,color:`var(--chart-1)`,value:`lab(89.9% -47.9 -15.7)`},{name:`Chart 2`,color:`var(--chart-2)`,value:`lab(67.0% -58.3 19.5)`},{name:`Chart 3`,color:`var(--chart-3)`,value:`lab(72.7% 31.9 97.9)`},{name:`Chart 4`,color:`var(--chart-4)`,value:`lab(52.0% 66.1 -78.2)`}];function bi(){let[e,t]=(0,_.useState)(`Preview`);return(0,E.jsx)(gi,{examples:vi,tabs:_i,activeTab:e,onTabChange:t})}var xi=er,Si=[`All`,`Navigation`,`Interface`,`System`,`Status`];function Ci(){let[e,t]=(0,_.useState)(`All`),[n,r]=(0,_.useState)(``),[i,a]=(0,_.useState)(20),[o,s]=(0,_.useState)(null),{schedule:c}=nr(),l=(0,_.useMemo)(()=>xi.filter(t=>{let r=e===`All`||t.category===e,i=t.name.toLowerCase().includes(n.toLowerCase())||t.pascalName.toLowerCase().includes(n.toLowerCase());return r&&i}),[e,n]),u=e=>{let t=`<${e.pascalName} size={${i}} />`;navigator.clipboard?.writeText(t),s(e.name),c(()=>s(null),2e3)};return(0,E.jsxs)(`div`,{className:`icon-matrix-container`,children:[(0,E.jsxs)(`div`,{className:`icon-matrix-header`,children:[(0,E.jsxs)(`div`,{className:`icon-search-bar`,children:[(0,E.jsx)(j,{name:`search`,size:16}),(0,E.jsx)(`input`,{type:`text`,placeholder:`Search icons (e.g. arrow, check, sparkles)...`,"aria-label":`Search icons`,value:n,onChange:e=>r(e.target.value),className:`icon-search-input`}),n&&(0,E.jsx)(`button`,{className:`icon-clear-btn`,onClick:()=>r(``),children:(0,E.jsx)(j,{name:`close`,size:14})})]}),(0,E.jsxs)(`div`,{className:`icon-size-picker`,children:[(0,E.jsx)(`span`,{className:`mono muted`,children:`Size:`}),[16,20,24].map(e=>(0,E.jsxs)(`button`,{className:`icon-size-btn ${i===e?`active`:``}`,onClick:()=>a(e),children:[e,`px`]},e))]})]}),(0,E.jsx)(`div`,{className:`icon-category-tabs`,children:Si.map(n=>(0,E.jsxs)(`button`,{className:`icon-cat-btn ${e===n?`active`:``}`,onClick:()=>t(n),children:[n,(0,E.jsx)(`span`,{className:`icon-cat-count`,children:n===`All`?xi.length:xi.filter(e=>e.category===n).length})]},n))}),(0,E.jsx)(`div`,{className:`icon-grid`,children:l.map(e=>{let t=o===e.name;return(0,E.jsxs)(`button`,{className:`icon-tile ${t?`copied`:``}`,onClick:()=>u(e),title:`Click to copy <${e.pascalName} />`,children:[(0,E.jsx)(`div`,{className:`icon-tile-glyph`,children:t?(0,E.jsx)(j,{name:`check`,size:i,className:`accent`}):(0,E.jsx)(e.component,{size:i,strokeWidth:1.8})}),(0,E.jsx)(`span`,{className:`icon-tile-name`,children:e.name}),(0,E.jsx)(`span`,{className:`icon-tile-action`,children:t?`Copied!`:(0,E.jsx)(ur,{children:`Copy`})})]},e.name)})}),l.length===0&&(0,E.jsxs)(`div`,{className:`empty-state`,children:[(0,E.jsx)(`div`,{className:`empty-state-icon`,children:(0,E.jsx)(j,{name:`search`,size:24})}),(0,E.jsx)(`h4`,{style:{margin:`0 0 var(--space-2)`},children:`No icons found`}),(0,E.jsxs)(`p`,{className:`muted`,style:{margin:0,fontSize:`var(--text-xs)`},children:[`No icon matches "`,n,`". You can use any of Lucide's 1,400+ icons directly via`,` `,(0,E.jsx)(`code`,{children:`lucide-react`}),`.`]})]}),(0,E.jsx)(`div`,{className:`icon-matrix-footer`,children:(0,E.jsxs)(`div`,{className:`icon-footer-pill`,children:[(0,E.jsx)(O,{variant:`outline`,children:`lucide-react`}),(0,E.jsxs)(`span`,{children:[`Over 1,400+ SVG icons available. Fully tree-shaken and styled via `,(0,E.jsx)(`code`,{children:`currentColor`}),`.`]})]})})]})}function wi(){return(0,E.jsx)(Ci,{})}function Ti({tokens:e,onCopy:t}){return(0,E.jsx)(`div`,{className:`color-grid`,children:e.map(e=>(0,E.jsxs)(`div`,{className:`color-card`,children:[(0,E.jsx)(`div`,{className:`swatch`,style:{background:e.color}}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`strong`,{children:e.name}),(0,E.jsx)(`span`,{className:`mono`,children:e.value})]}),(0,E.jsx)(`button`,{className:`copy-icon`,onClick:()=>t?.(e.value),"aria-label":`Copy ${e.name} token`,children:(0,E.jsx)(j,{name:`copy`,size:14})})]},e.name))})}var Ei=`pnpm add @northstar/ui @northstar/tokens`;function Di(){navigator.clipboard?.writeText(Ei)}function Oi(){return(0,E.jsx)(Ti,{tokens:yi,onCopy:Di})}var ki=[{token:`--text-hero`,rem:`clamp(2.625rem, 5vw, 4.375rem)`,px:`42→70px`,role:`Display / Hero Title`,sample:`Calm, capable design.`},{token:`--text-2xl`,rem:`1.75rem`,px:`28px`,role:`Section Headlines`,sample:`Structured for AI Uniformity`},{token:`--text-xl`,rem:`1.5625rem`,px:`25px`,role:`Sub-headlines & Major Cards`,sample:`Fast, token-enforced iteration`},{token:`--text-lg`,rem:`1.3125rem`,px:`21px`,role:`Card Titles & Dialog Heads`,sample:`Zero hardcoded pixel values`},{token:`--text-base`,rem:`1rem`,px:`16px`,role:`Lede Copy & Lead Sentences`,sample:`The baseline font size scaled by --root-font-size.`},{token:`--text-md`,rem:`0.875rem`,px:`14px`,role:`Longform Body Text`,sample:`Engineered for dense technical dashboards and documentation.`},{token:`--text-sm`,rem:`0.75rem`,px:`12px`,role:`Form Controls & Descriptions`,sample:`Input labels, table rows, and secondary details.`},{token:`--text-xs`,rem:`0.6875rem`,px:`11px`,role:`Action Buttons & Nav Items`,sample:`Action buttons, status badges, and sidebar navigation.`},{token:`--text-2xs`,rem:`0.625rem`,px:`10px`,role:`Eyebrows & Section Indices`,sample:`METADATA LABELS & CATEGORY EYEBROWS`},{token:`--text-3xs`,rem:`0.5625rem`,px:`9px`,role:`Micro Badges & Mono Tags`,sample:`01 / APPLICATION PATTERNS`}];function Ai(){return(0,E.jsxs)(`div`,{className:`stack-lg`,children:[(0,E.jsxs)(`div`,{className:`grid-2`,children:[(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,children:[(0,E.jsx)(et,{children:`Sans-Serif Primary Family`}),(0,E.jsx)(O,{variant:`primary`,children:`Manrope`})]}),(0,E.jsx)(tt,{children:`Modern geometric grotesque optimized for high-density UI and numeral legibility.`})]}),(0,E.jsx)(nt,{children:(0,E.jsxs)(`div`,{style:{fontFamily:`var(--font-sans)`,fontSize:`var(--text-lg)`,fontWeight:600},children:[`ABCDEFGHIJKLMNOPQRSTUVWXYZ`,(0,E.jsx)(`br`,{}),`abcdefghijklmnopqrstuvwxyz`,(0,E.jsx)(`br`,{}),`0123456789 & @ # % $ /`]})})]}),(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,children:[(0,E.jsx)(et,{children:`Monospace Code Family`}),(0,E.jsx)(O,{variant:`secondary`,children:`DM Mono`})]}),(0,E.jsx)(tt,{children:`Tabular numerals and proportional spacing for code blocks, tokens, and telemetry.`})]}),(0,E.jsx)(nt,{children:(0,E.jsxs)(`div`,{className:`mono`,style:{fontSize:`var(--text-md)`,color:`var(--primary)`},children:[`const system = 'northstar'`,(0,E.jsx)(`br`,{}),`latency: 14.2ms | memory: 128MB`,(0,E.jsx)(`br`,{}),`0123456789 ()=>{}[]`]})})]})]}),(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,children:[(0,E.jsx)(et,{children:`Modular Rem-Based Type Scale`}),(0,E.jsxs)(`div`,{className:`row-xs`,children:[(0,E.jsx)(`span`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:`Root:`}),(0,E.jsx)(ur,{children:`112%`})]})]}),(0,E.jsxs)(tt,{children:[`Scales uniformly via `,(0,E.jsx)(`code`,{children:`--root-font-size`}),`. Built on a 9px → 70px responsive rhythm.`]})]}),(0,E.jsx)(nt,{children:(0,E.jsx)(`div`,{className:`stack-md`,children:ki.map(e=>(0,E.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`160px 80px 1fr`,alignItems:`baseline`,gap:`var(--space-4)`,padding:`var(--space-3) 0`,borderBottom:`1px solid var(--border)`},children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`code`,{style:{fontSize:`var(--text-xs)`,color:`var(--primary)`,fontFamily:`var(--font-mono)`},children:e.token}),(0,E.jsx)(`div`,{style:{fontSize:`var(--text-3xs)`,color:`var(--muted-foreground)`},children:e.role})]}),(0,E.jsx)(`div`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:e.px}),(0,E.jsx)(`div`,{style:{fontSize:`var(${e.token})`,fontWeight:e.token.includes(`hero`)||e.token.includes(`2xl`)?800:500,lineHeight:1.25,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:e.sample})]},e.token))})})]})]})}function ji(){return(0,E.jsx)(Ai,{})}function Mi({label:e,hint:t,children:n,readOnlyLabel:r}){return(0,E.jsxs)(`label`,{className:`field`,children:[(0,E.jsxs)(`span`,{children:[e,r&&(0,E.jsx)(`em`,{children:r})]}),n,(0,E.jsx)(`small`,{children:t})]})}function Ni(e){return(0,E.jsx)(`input`,{...e})}function Pi(){let[e,t]=(0,_.useState)(!1);return(0,E.jsxs)(`div`,{className:`forms-grid`,children:[(0,E.jsx)(Mi,{label:`Project name`,hint:`Use a memorable name for your workspace.`,children:(0,E.jsx)(Ni,{defaultValue:`Northstar Console`})}),(0,E.jsx)(Mi,{label:`API key`,readOnlyLabel:`read only`,hint:`Stored securely in your environment.`,children:(0,E.jsxs)(`div`,{className:`input-with-action`,children:[(0,E.jsx)(Ni,{type:e?`text`:`password`,defaultValue:`nsk_live_8f2a1d90`,readOnly:!0}),(0,E.jsx)(`button`,{onClick:()=>t(!e),"aria-label":`Show API key`,children:(0,E.jsx)(j,{name:`eye`,size:16})})]})}),(0,E.jsxs)(`label`,{className:`toggle-field`,children:[(0,E.jsxs)(`span`,{children:[(0,E.jsx)(`b`,{children:`Enable notifications`}),(0,E.jsx)(`small`,{children:`Get updates about deployments and incidents.`})]}),(0,E.jsx)(rr,{defaultChecked:!0,"aria-label":`Toggle notifications`})]}),(0,E.jsxs)(`div`,{className:`toggle-field`,children:[(0,E.jsxs)(`span`,{children:[(0,E.jsx)(`b`,{children:`Primitives in action`}),(0,E.jsx)(`small`,{children:`Spinner, Avatar and Switch — token-driven, theme-aware components/ui primitives.`})]}),(0,E.jsxs)(`span`,{className:`row-md`,children:[(0,E.jsx)(fi,{name:`Mats Tornberg`,size:`sm`,status:`online`}),(0,E.jsx)(fi,{name:`Grace Hopper`,size:`sm`}),(0,E.jsx)(hi,{size:`sm`,label:`Loading session`})]})]}),(0,E.jsxs)(`div`,{className:`toggle-field`,children:[(0,E.jsxs)(`span`,{children:[(0,E.jsx)(`b`,{children:`Tabs primitive`}),(0,E.jsx)(`small`,{children:`Roving tabindex, arrow-key navigation, aria-selected wiring — try the keyboard.`})]}),(0,E.jsxs)(ti,{defaultValue:`preview`,className:`stack-xs`,children:[(0,E.jsxs)(ri,{children:[(0,E.jsx)(ii,{value:`preview`,children:`Preview`}),(0,E.jsx)(ii,{value:`code`,children:`Code`})]}),(0,E.jsx)(ai,{value:`preview`,children:(0,E.jsx)(`small`,{children:`Token-driven preview pane.`})}),(0,E.jsx)(ai,{value:`code`,children:(0,E.jsxs)(`small`,{children:[`import `,`{ Tabs }`,` from components/ui`]})})]})]})]})}var Fi=`pnpm add @northstar/ui @northstar/tokens`,Ii=[[`pink`,`import`],[`plain`,` { Button } `],[`pink`,`from`],[`green`,` '@northstar/ui'`],[`plain`,` + +export function `],[`blue`,`DeployAction`],[`plain`,`() { + return ( +`],[`plain`,` + ) +}`]];function Li(){let[e,t]=(0,_.useState)(!1),{schedule:n}=nr();return(0,E.jsxs)(`div`,{className:`code-card`,children:[(0,E.jsxs)(`div`,{className:`code-head`,children:[(0,E.jsx)(`span`,{className:`mono muted`,children:`button.tsx`}),(0,E.jsxs)(`button`,{className:`copy-button`,onClick:()=>{navigator.clipboard?.writeText(Fi),t(!0),n(()=>t(!1),1600)},children:[(0,E.jsx)(j,{name:e?`check`:`copy`,size:14}),e?`Copied`:`Copy code`]})]}),(0,E.jsx)(`pre`,{children:(0,E.jsx)(`code`,{children:Ii.map(([e,t],n)=>e===`plain`?(0,E.jsx)(`span`,{children:t},n):(0,E.jsx)(`span`,{className:e,children:t},n))})})]})}function Ri(){return(0,E.jsx)(Li,{})}function zi({title:e=`Quiet power, shipped weekly.`,kicker:t=`NORTHSTAR / RELEASE NOTES`}){return(0,E.jsxs)(`div`,{className:`markdown-card`,children:[(0,E.jsxs)(`div`,{className:`markdown-toolbar`,children:[(0,E.jsx)(`span`,{className:`eyebrow`,children:`Preview`}),(0,E.jsx)(`span`,{className:`mono muted`,children:`release-notes.md`})]}),(0,E.jsxs)(`article`,{className:`markdown-body`,children:[(0,E.jsx)(`span`,{className:`md-kicker`,children:t}),(0,E.jsx)(`h3`,{children:e}),(0,E.jsx)(`p`,{children:`Our components help teams move quickly without making the interface feel rushed.`}),(0,E.jsxs)(`div`,{className:`md-callout`,children:[(0,E.jsx)(`span`,{className:`callout-mark`,children:`✦`}),(0,E.jsxs)(`p`,{children:[(0,E.jsx)(`strong`,{children:`New in 0.8.2`}),(0,E.jsx)(`br`,{}),`Button focus rings now respect your theme while keeping a dependable contrast ratio.`]})]}),(0,E.jsx)(`h4`,{children:`What changed`}),(0,E.jsxs)(`ul`,{children:[(0,E.jsxs)(`li`,{children:[`Added `,(0,E.jsx)(`code`,{children:`accent-subtle`}),` surface token`]}),(0,E.jsx)(`li`,{children:`Improved keyboard navigation in menus`}),(0,E.jsx)(`li`,{children:`Reduced layout shift during loading states`})]}),(0,E.jsxs)(`div`,{className:`md-table`,children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`span`,{children:`Token`}),(0,E.jsx)(`span`,{children:`Value`}),(0,E.jsx)(`span`,{children:`Role`})]}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`code`,{children:`surface-1`}),(0,E.jsx)(`span`,{children:`#111118`}),(0,E.jsx)(`span`,{children:`Elevated panels`})]}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`code`,{children:`accent`}),(0,E.jsx)(`span`,{className:`md-accent`,children:`#A69BFF`}),(0,E.jsx)(`span`,{children:`Interactive focus`})]})]})]})]})}function Bi(){return(0,E.jsx)(zi,{})}var Vi=[1,2,3,4,5,6,7,8];function Hi({fileName:e=`theme.ts`,language:t=`TypeScript`}){return(0,E.jsxs)(`div`,{className:`editor-card`,children:[(0,E.jsxs)(`div`,{className:`editor-tabs`,children:[(0,E.jsx)(`span`,{className:`editor-dot`}),(0,E.jsx)(`span`,{className:`editor-tab active`,children:e}),(0,E.jsx)(`span`,{className:`editor-tab`,children:`tokens.css`}),(0,E.jsx)(`span`,{className:`editor-actions`,children:`● ● ●`})]}),(0,E.jsxs)(`div`,{className:`editor-body`,children:[(0,E.jsx)(`div`,{className:`line-numbers`,children:Vi.map(e=>(0,E.jsxs)(`span`,{children:[e,(0,E.jsx)(`br`,{})]},e))}),(0,E.jsx)(`pre`,{children:(0,E.jsxs)(`code`,{children:[(0,E.jsx)(`span`,{className:`cm-comment`,children:`// A calm editor for focused work`}),` +`,(0,E.jsx)(`span`,{className:`cm-keyword`,children:`export const`}),` `,(0,E.jsx)(`span`,{className:`cm-variable`,children:`theme`}),` = `,`{`,` +`,` `,(0,E.jsx)(`span`,{className:`cm-property`,children:`name`}),`: `,(0,E.jsx)(`span`,{className:`cm-string`,children:`'northstar-dark'`}),`,`,` +`,` `,(0,E.jsx)(`span`,{className:`cm-property`,children:`colors`}),`: `,`{`,` +`,` `,(0,E.jsx)(`span`,{className:`cm-property`,children:`accent`}),`: `,(0,E.jsx)(`span`,{className:`cm-string`,children:`'#a69bff'`}),`,`,` +`,` `,(0,E.jsx)(`span`,{className:`cm-property`,children:`keyword`}),`: `,(0,E.jsx)(`span`,{className:`cm-string`,children:`'#e58bff'`}),`,`,` +`,` `,(0,E.jsx)(`span`,{className:`cm-property`,children:`comment`}),`: `,(0,E.jsx)(`span`,{className:`cm-string`,children:`'#666572'`}),` +`,` `,`}`,` +`,`}`]})})]}),(0,E.jsxs)(`div`,{className:`editor-status`,children:[(0,E.jsx)(`span`,{children:`Ln 4, Col 18`}),(0,E.jsxs)(`span`,{children:[t,` · UTF-8`]}),(0,E.jsxs)(`span`,{className:`editor-ready`,children:[(0,E.jsx)(j,{name:`check`,size:12}),` No issues`]})]})]})}function Ui(){return(0,E.jsx)(Hi,{})}function Wi(e){let t=e??window.location.pathname+window.location.search;window.location.href=`/api/auth/login?returnTo=${encodeURIComponent(t)}`}function Gi(){let[e,t]=(0,_.useState)(`loading`),[n,r]=(0,_.useState)(null);return(0,_.useEffect)(()=>{let e=!0;return fetch(`/api/auth/session`).then(e=>e.ok?e.json():{authenticated:!1,user:null}).then(n=>{e&&(n.authenticated&&n.user?(r(n.user),t(`authenticated`)):(r(null),t(`anonymous`)))}).catch(()=>{e&&(r(null),t(`anonymous`))}),()=>{e=!1}},[]),{status:e,user:n,login:Wi,signOut:(0,_.useCallback)(async()=>{try{await fetch(`/api/auth/logout`,{method:`POST`})}catch{}r(null),t(`anonymous`)},[])}}var Ki=class extends Error{status;code;constructor(e,t,n){super(n),this.name=`ApiError`,this.status=e,this.code=t}},qi=``;async function Ji(e,t){let n;try{n=await fetch(`${qi}${e}`,{...t,headers:{"Content-Type":`application/json`,...t?.headers}})}catch(e){throw new Ki(0,`network`,`Could not reach the API (${e instanceof Error?e.message:String(e)}). Is the Go server running?`)}if(n.status===204)return;let r=await n.json().catch(()=>null);if(!n.ok){let e=r?.error;throw new Ki(n.status,e?.code??`unknown`,e?.message??n.statusText)}return r}var Yi=Object.prototype.hasOwnProperty;function Xi(e,t){var n,r;if(e===t)return!0;if(e&&t&&(n=e.constructor)===t.constructor){if(n===Date)return e.getTime()===t.getTime();if(n===RegExp)return e.toString()===t.toString();if(n===Array){if((r=e.length)===t.length)for(;r--&&Xi(e[r],t[r]););return r===-1}if(!n||typeof e==`object`){for(n in r=0,e)if(Yi.call(e,n)&&++r&&!Yi.call(t,n)||!(n in t)||!Xi(e[n],t[n]))return!1;return Object.keys(t).length===r}}return e!==e&&t!==t}var Zi=new WeakMap,Qi=()=>{},$i=Object,N=e=>e===void 0,P=e=>typeof e==`function`,ea=(e,t)=>({...e,...t}),ta=e=>P(e.then),na={},ra={},ia=`undefined`,aa=typeof window!=ia,oa=typeof document!=ia,sa=aa&&`Deno`in window,ca=()=>aa&&typeof window.requestAnimationFrame!=ia,F=(e,t)=>{let n=Zi.get(e);return[()=>!N(t)&&e.get(t)||na,r=>{if(!N(t)){let i=e.get(t);t in ra||(ra[t]=i),n[5](t,ea(i,r),i||na)}},n[6],()=>!N(t)&&t in ra?ra[t]:!N(t)&&e.get(t)||na]},I=!0,la=()=>I,[ua,da]=aa&&window.addEventListener?[window.addEventListener.bind(window),window.removeEventListener.bind(window)]:[Qi,Qi],fa=()=>{let e=oa&&document.visibilityState;return N(e)||e!==`hidden`},pa=e=>(oa&&document.addEventListener(`visibilitychange`,e),ua(`focus`,e),()=>{oa&&document.removeEventListener(`visibilitychange`,e),da(`focus`,e)}),ma=e=>{let t=()=>{I=!0,e()},n=()=>{I=!1};return ua(`online`,t),ua(`offline`,n),()=>{da(`online`,t),da(`offline`,n)}},ha={isOnline:la,isVisible:fa},ga={initFocus:pa,initReconnect:ma},_a=!_.useId,va=!aa||sa,ya=e=>ca()?window.requestAnimationFrame(e):setTimeout(e,1),ba=va?_.useEffect:_.useLayoutEffect,xa=typeof navigator<`u`&&navigator.connection,Sa=!va&&xa&&([`slow-2g`,`2g`].includes(xa.effectiveType)||xa.saveData),Ca=new WeakMap,wa=e=>$i.prototype.toString.call(e),Ta=(e,t)=>e===`[object ${t}]`,Ea=0,Da=e=>{let t=typeof e,n=wa(e),r=Ta(n,`Date`),i=Ta(n,`RegExp`),a=Ta(n,`Object`),o,s;if($i(e)===e&&!r&&!i){if(o=Ca.get(e),o)return o;if(o=++Ea+`~`,Ca.set(e,o),Array.isArray(e)){for(o=`@`,s=0;s{if(P(e))try{e=e()}catch{e=``}let t=e;return e=typeof e==`string`?e:(Array.isArray(e)?e.length:e)?Da(e):``,[e,t]},ka=0,Aa=()=>++ka;async function ja(...e){let[t,n,r,i]=e,a=ea({populateCache:!0,throwOnError:!0},typeof i==`boolean`?{revalidate:i}:i||{}),o=a.populateCache,s=a.rollbackOnError,c=a.optimisticData,l=e=>typeof s==`function`?s(e):s!==!1,u=a.throwOnError;if(P(n)){let e=n,r=[],i=t.keys();for(let n of i)!/^\$(inf|sub)\$/.test(n)&&e(t.get(n)._k)&&r.push(n);return Promise.all(r.map(d))}return d(n);async function d(n){let[i]=Oa(n);if(!i)return;let[s,d]=F(t,i),[f,p,m,h]=Zi.get(t),g=()=>{let e=f[i];return(P(a.revalidate)?a.revalidate(s().data,n):a.revalidate!==!1)&&(delete m[i],delete h[i],e&&e[0])?e[0](2).then(()=>s().data):s().data};if(e.length<3)return g();let _=r,v,y=!1,b=Aa();p[i]=[b,0];let ee=!N(c),te=s(),ne=te.data,re=te._c,x=N(re)?ne:re;if(ee&&(c=P(c)?c(x,ne):c,d({data:c,_c:x})),P(_))try{_=_(x)}catch(e){v=e,y=!0}if(_&&ta(_)){if(_=await _.catch(e=>{v=e,y=!0}),b!==p[i][0]){if(y)throw v;return _}y&&ee&&l(v)&&(o=!0,d({data:x,_c:void 0}))}if(o&&(y||(P(o)?d({data:o(_,x),error:void 0,_c:void 0}):d({data:_,error:void 0,_c:void 0}))),p[i][1]=Aa(),Promise.resolve(g()).then(()=>{d({_c:void 0})}),y){if(u)throw v;return}return _}}var Ma=(e,t)=>{for(let n in e)e[n][0]&&e[n][0](t)},Na=(e,t)=>{if(!Zi.has(e)){let n=ea(ga,t),r=Object.create(null),i=ja.bind(void 0,e),a=Qi,o=Object.create(null),s=(e,t)=>{let n=o[e]||[];return o[e]=n,n.push(t),()=>{let e=n.indexOf(t);e>=0&&(n[e]=n[n.length-1],n.pop())}},c=(t,n,r)=>{e.set(t,n);let i=o[t];if(i)for(let e of i)e(n,r)},l=t=>{let n=Zi.get(e),[,i,a,s]=n,c=Aa();n[8]++;for(let e in a)delete a[e];for(let e in s)delete s[e];for(let e in i)i[e]=[c,c];let l={};for(let t of[...e.keys()]){let n=e.get(t);e.delete(t);let r=o[t];if(r)for(let e of r)e(l,n)}let u=!t||t.revalidate!==!1;for(let e in r){let t=r[e];for(let e=0;e{if(!Zi.has(e)&&(Zi.set(e,[r,Object.create(null),Object.create(null),Object.create(null),i,c,s,l,0]),!va)){let t=n.initFocus(setTimeout.bind(void 0,Ma.bind(void 0,r,0))),i=n.initReconnect(setTimeout.bind(void 0,Ma.bind(void 0,r,1)));a=()=>{t&&t(),i&&i(),Zi.delete(e)}}};return u(),[e,i,u,a,l]}let n=Zi.get(e);return[e,n[4],void 0,void 0,n[7]]},Pa=(e,t,n,r,i)=>{let a=n.errorRetryCount,o=i.retryCount,s=~~((Math.random()+.5)*(1<<(o<8?o:8)))*n.errorRetryInterval;!N(a)&&o>a||setTimeout(r,s,i)},Fa=Xi,[Ia,La,,,Ra]=Na(new Map),za=ea({onLoadingSlow:Qi,onSuccess:Qi,onError:Qi,onErrorRetry:Pa,onDiscarded:Qi,revalidateOnFocus:!0,revalidateOnReconnect:!0,revalidateIfStale:!0,shouldRetryOnError:!0,errorRetryInterval:Sa?1e4:5e3,focusThrottleInterval:5e3,dedupingInterval:2e3,loadingTimeout:Sa?5e3:3e3,compare:Fa,isPaused:()=>!1,cache:Ia,mutate:La,unload:Ra,fallback:{}},ha),Ba=(e,t)=>{let n=ea(e,t);if(t){let{use:r,fallback:i,cacheData:a}=e,{use:o,fallback:s,cacheData:c}=t;r&&o&&(n.use=r.concat(o)),i&&s&&(n.fallback=ea(i,s)),a&&c&&(n.cacheData=ea(a,c))}return n},Va=(0,_.createContext)({}),Ha=e=>{let{value:t}=e,n=(0,_.useContext)(Va),r=P(t),i=(0,_.useMemo)(()=>r?t(n):t,[r,n,t]),a=(0,_.useMemo)(()=>r?i:Ba(n,i),[r,n,i]),o=i&&i.provider,s=(0,_.useRef)(void 0);o&&!s.current&&(s.current=Na(o(a.cache||Ia),i));let c=s.current;return c&&(a.cache=c[0],a.mutate=c[1],a.unload=c[4]),ba(()=>{if(c)return c[2]&&c[2](),c[3]},[]),(0,_.createElement)(Va.Provider,ea(e,{value:a}))},Ua=aa&&window.__SWR_DEVTOOLS_USE__,Wa=Ua?window.__SWR_DEVTOOLS_USE__:[],Ga=()=>{Ua&&(window.__SWR_DEVTOOLS_REACT__=_.default)},Ka=e=>P(e[1])?[e[0],e[1],e[2]||{}]:[e[0],null,(e[1]===null?e[2]:e[1])||{}],qa=()=>{let e=(0,_.useContext)(Va);return(0,_.useMemo)(()=>ea(za,e),[e])},Ja=Wa.concat(e=>(t,n,r)=>e(t,n&&((...e)=>{let[r]=Oa(t),[,,,i]=Zi.get(Ia);if(r.startsWith(`$inf$`))return n(...e);let a=i[r];return N(a)?n(...e):(delete i[r],a)}),r)),Ya=e=>function(...t){let n=qa(),[r,i,a]=Ka(t),o=Ba(n,a),s=e,{use:c}=o,l=(c||[]).concat(Ja);for(let e=l.length;e--;)s=l[e](s);return s(r,i||o.fetcher||null,o)},Xa=(e,t,n)=>{let r=t[e]||(t[e]=[]);return r.push(n),()=>{let e=r.indexOf(n);e>=0&&(r[e]=r[r.length-1],r.pop())}};Ga();var Za=_.use||(e=>{switch(e.status){case`pending`:throw e;case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:throw e.status=`pending`,e.then(t=>{e.status=`fulfilled`,e.value=t},t=>{e.status=`rejected`,e.reason=t}),e}}),Qa={dedupe:!0},$a=(e,t,n)=>t?e.get(t)?.has(n)===!0:!1,eo=(e,t,n)=>{if(!t)return;let r=e.get(t);r||(r=new Set,e.set(t,r)),r.add(n)},to=({value:e,getCacheData:t,canCommit:n,setCache:r})=>{let i=e=>{n()&&N(t())&&r(e)};Promise.resolve(e).then(e=>{i({data:e,error:void 0})},e=>{i({error:e})})},no=Promise.resolve(void 0);no.status=`fulfilled`,no.value=void 0;var ro=()=>Qi,io=(e,t,n)=>{let{cache:r,compare:i,suspense:a,fallbackData:o,revalidateOnMount:s,revalidateIfStale:c,refreshInterval:l,refreshWhenHidden:u,refreshWhenOffline:d,keepPreviousData:f,strictServerPrefetchWarning:p}=n,[m,h,g,v]=Zi.get(r),[y,b]=Oa(e),te=(0,_.useRef)(!1),ne=(0,_.useRef)(!1),re=(0,_.useRef)(y),x=(0,_.useRef)(t),ie=(0,_.useRef)(n),S=()=>ie.current,ae=()=>S().isVisible()&&S().isOnline(),[oe,se,ce,le]=F(r,y),ue=(0,_.useRef)({}).current,de=N(o)?N(n.fallback)?void 0:n.fallback[y]:o,fe=n.cacheData,pe=y?fe?.[y]:void 0,me=y?v[y]:void 0,he=N(me)&&!N(pe),ge=he?pe:me,_e=(e,t)=>{for(let n in ue){let r=n;if(r===`data`){if(!i(e[r],t[r])&&(!N(e[r])||!i(w,t[r])))return!1}else if(t[r]!==e[r])return!1}return!0},ve=!te.current,ye=(0,_.useMemo)(()=>{let e=oe(),n=le(),r=e=>{let n=ea(e);return delete n._k,(()=>{if(!y||!t||S().isPaused())return!1;if(ve&&!N(s))return s;let e=N(de)?n.data:de;return a&&he&&N(e)?!1:N(e)||c})()?{isValidating:!0,isLoading:!0,...n}:n},i=r(e),o=e===n?i:r(n),l=i;return[()=>{let e=r(oe());return _e(e,l)?(l.data=e.data,l.isLoading=e.isLoading,l.isValidating=e.isValidating,l.error=e.error,l):(l=e,e)},()=>o]},[r,y]),be=(0,ee.useSyncExternalStore)((0,_.useCallback)(e=>ce(y,(t,n)=>{_e(n,t)||e()}),[r,y]),ye[0],ye[1]),xe=m[y]&&m[y].length>0,Se=be.data,Ce=N(Se)?de&&ta(de)?Za(de):de:Se,we=be.error,Te=(0,_.useRef)(Ce),Ee=(0,_.useRef)(void 0),De=Ee.current;De||(De=new WeakMap,Ee.current=De);let C=(0,_.useRef)(null),w=f?N(Se)?N(Te.current)?Ce:Te.current:Se:Ce,Oe=y&&N(Ce),ke=(0,_.useRef)(null);!va&&(0,ee.useSyncExternalStore)(ro,()=>(ke.current=!1,ke),()=>(ke.current=!0,ke));let Ae=ke.current;p&&Ae&&!a&&Oe&&console.warn(`Missing pre-initiated data for serialized key "${y}" during server-side rendering. Data fetching should be initiated on the server and provided to SWR via fallback data. You can set "strictServerPrefetchWarning: false" to disable this warning.`);let je=!y||!t||S().isPaused()||xe&&!N(we)?!1:ve&&!N(s)?s:a&&he&&Oe?!1:a?!N(Ce)&&c:N(Ce)||c,Me=ve&&je,T=N(be.isValidating)?Me:be.isValidating,Ne=N(be.isLoading)?Me:be.isLoading,Pe=(0,_.useCallback)(async e=>{let t=x.current;if(!y||!t||ne.current||S().isPaused())return!1;let r,a,o=!0,s=e||{},c=!g[y]||!s.dedupe,l=he&&!$a(De,fe,y)&&!N(ge)&&N(oe().data),u=()=>_a?!ne.current&&y===re.current&&te.current:y===re.current,d={isValidating:!1,isLoading:!1},f=()=>{se(d)},p=()=>{let e=g[y];e&&e[1]===a&&delete g[y]},_={isValidating:!0};N(oe().data)&&(_.isLoading=!0);try{if(c&&(se(_),n.loadingTimeout&&N(oe().data)&&setTimeout(()=>{o&&u()&&S().onLoadingSlow(y,n)},n.loadingTimeout),l&&eo(De,fe,y),g[y]=[l?ge:t(b),Aa()],l&&v[y]&&delete v[y]),[r,a]=g[y],r=await r,c&&setTimeout(p,n.dedupingInterval),!g[y]||g[y][1]!==a)return c&&u()&&S().onDiscarded(y),!1;d.error=void 0;let e=h[y];if(!N(e)&&(a<=e[0]||a<=e[1]||e[1]===0))return f(),c&&u()&&S().onDiscarded(y),!1;let s=oe().data;d.data=i(s,r)?s:r,c&&u()&&S().onSuccess(r,y,n)}catch(e){p();let t=S(),{shouldRetryOnError:n}=t;t.isPaused()||(d.error=e,c&&u()&&(t.onError(e,y,t),(n===!0||P(n)&&n(e))&&(!S().revalidateOnFocus||!S().revalidateOnReconnect||ae())&&t.onErrorRetry(e,y,t,e=>{let t=m[y];t&&t[0]&&t[0](3,e)},{retryCount:(s.retryCount||0)+1,dedupe:!0})))}return o=!1,f(),!0},[y,r]),Fe=(0,_.useCallback)((...e)=>ja(r,re.current,...e),[]);if(ba(()=>{let e=C.current;e&&(C.current=null,eo(De,e.cacheData,e.key),N(oe().data)&&se({data:e.data,error:void 0,_k:e._k}),v[e.key]&&delete v[e.key])}),ba(()=>{x.current=t,ie.current=n,N(Se)||(Te.current=Se)}),ba(()=>{if(t||!he||N(ge)||$a(De,fe,y)||!N(oe().data))return;eo(De,fe,y);let e=h[y];to({value:ge,getCacheData:()=>oe().data,canCommit:()=>!ne.current&&y===re.current&&h[y]===e,setCache:e=>se({...e,_k:b})})}),ba(()=>{if(!y)return;let e=Pe.bind(void 0,Qa),t=0;S().revalidateOnFocus&&(t=Date.now()+S().focusThrottleInterval);let n=Xa(y,m,(n,r={})=>{if(n==0){let n=Date.now();S().revalidateOnFocus&&n>t&&ae()&&(t=n+S().focusThrottleInterval,e())}else if(n==1)S().revalidateOnReconnect&&ae()&&e();else if(n==2)return Pe();else if(n==3)return Pe(r);else if(n==4&&(Te.current=void 0,r.revalidate))return Pe()});return ne.current=!1,re.current=y,te.current=!0,se({_k:b}),je&&(g[y]||(N(Ce)||va?e():ya(e))),()=>{ne.current=!0,n()}},[y]),ba(()=>{let e;function t(){let t=P(l)?l(oe().data):l;t&&e!==-1&&(e=setTimeout(n,t))}function n(){!oe().error&&(u||S().isVisible())&&(d||S().isOnline())?Pe(Qa).then(t):t()}return t(),()=>{e&&=(clearTimeout(e),-1)}},[l,u,d,y]),(0,_.useDebugValue)(w),a){if(!_a&&va&&Oe&&N(ge))throw Error(`Fallback data is required when using Suspense in SSR.`);Oe&&(x.current=t,ie.current=n,ne.current=!1);let e=!N(ge)&&Oe,r;if(e&&he?(r=ge&&ta(ge)?Za(ge):ge,Ce=r,w=r,va||(C.current={data:r,_k:b,key:y,cacheData:fe})):Za(e?Fe(ge):no),!N(we)&&Oe)throw we;let i=Oe&&N(r)?Pe(Qa):no;!N(w)&&Oe&&(i.status=`fulfilled`,i.value=!0),Za(i)}return{mutate:Fe,get data(){return ue.data=!0,w},get error(){return ue.error=!0,we},get isValidating(){return ue.isValidating=!0,T},get isLoading(){return ue.isLoading=!0,Ne}}};$i.defineProperty(Ha,`defaultValue`,{value:za});var ao=Ya(io);function oo(e={}){let t=new URLSearchParams;e.status&&t.set(`status`,e.status),e.limit!==void 0&&t.set(`limit`,String(e.limit)),e.offset!==void 0&&t.set(`offset`,String(e.offset));let n=t.toString();return Ji(`/api/v1/items${n?`?${n}`:``}`)}function so(e){return Ji(`/api/v1/items`,{method:`POST`,body:JSON.stringify(e)})}function co(e,t){return Ji(`/api/v1/items/${e}`,{method:`PATCH`,body:JSON.stringify(t)})}function lo(e){return Ji(`/api/v1/items/${e}`,{method:`DELETE`})}var uo={list:(e={})=>[`items`,`list`,e],detail:e=>[`items`,`detail`,e]};function fo(e){return Array.isArray(e)&&e[0]===`items`}var po={keepPreviousData:!0};function mo(e={}){let{data:t,error:n,isLoading:r,mutate:i}=ao(uo.list(e),()=>oo(e),po);return{items:t,error:n,isLoading:r,refresh:i}}function ho(){let{mutate:e}=qa();return{create:(0,_.useCallback)(async t=>{let n=await so(t);return await e(fo),n},[e]),update:(0,_.useCallback)(async(t,n)=>{let r=await co(t,n);return await e(fo),r},[e]),remove:(0,_.useCallback)(async t=>{await lo(t),await e(fo)},[e])}}var go=[`all`,`active`,`archived`],_o=new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`short`}),vo={padding:`var(--space-1) var(--space-3)`,fontSize:`var(--text-xs)`};function yo(){let[e,t]=(0,_.useState)(`all`),[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(null),[o,s]=(0,_.useState)(null),{items:c,error:l,isLoading:u,refresh:d}=mo(e===`all`?{}:{status:e}),{update:f,remove:p}=ho(),m=async(e,t)=>{a(e),s(null);try{await t()}catch(e){s(e instanceof Ki?e.message:`Unexpected error`)}finally{a(null)}},h=(0,E.jsx)(pr,{children:(0,E.jsxs)(hr,{children:[(0,E.jsx)(gr,{children:`Item`}),(0,E.jsx)(gr,{children:`Status`}),(0,E.jsx)(gr,{children:`Created`}),(0,E.jsx)(gr,{children:`Updated`}),(0,E.jsx)(gr,{children:`Actions`})]})});return(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,E.jsx)(`div`,{className:`row-xs`,children:go.map(n=>(0,E.jsx)(`button`,{className:`button ${e===n?`secondary`:`ghost`}`,style:{...vo,textTransform:`capitalize`},onClick:()=>t(n),children:n},n))}),(0,E.jsxs)(`div`,{className:`row-xs`,children:[(0,E.jsxs)(M,{variant:`ghost`,style:vo,onClick:()=>d(),children:[(0,E.jsx)(j,{name:`refresh`,size:13}),` Refresh`]}),(0,E.jsxs)(M,{variant:`primary`,style:vo,onClick:()=>r(!0),children:[(0,E.jsx)(j,{name:`plus`,size:13}),` New item`]})]})]}),o&&(0,E.jsxs)(ir,{variant:`destructive`,icon:(0,E.jsx)(j,{name:`warning`,size:18}),children:[(0,E.jsx)(ar,{children:`Action failed`}),(0,E.jsx)(or,{children:o})]}),l&&!c?l instanceof Ki&&l.code===`unauthorized`?(0,E.jsxs)(ir,{variant:`warning`,icon:(0,E.jsx)(j,{name:`shield`,size:18}),children:[(0,E.jsx)(ar,{children:`Sign in required`}),(0,E.jsx)(or,{children:`This API requires an authenticated session. Signing in redirects to the configured OIDC issuer and lands back on this page.`}),(0,E.jsx)(`div`,{className:`row-xs`,style:{marginTop:`var(--space-3)`},children:(0,E.jsx)(M,{variant:`primary`,onClick:()=>Wi(),children:`Sign in`})})]}):(0,E.jsxs)(ir,{variant:`destructive`,icon:(0,E.jsx)(j,{name:`alert`,size:18}),children:[(0,E.jsx)(ar,{children:`Cannot reach the Go API`}),(0,E.jsx)(or,{children:l.message}),(0,E.jsxs)(or,{children:[`Start it with`,` `,(0,E.jsx)(`code`,{className:`mono`,style:{color:`var(--foreground)`},children:`cd backend && make migrate-up && make run`}),` `,`— SQLite is the default, so no database server is needed, and vite proxies`,` `,(0,E.jsx)(`code`,{className:`mono`,children:`/api`}),` to `,(0,E.jsx)(`code`,{className:`mono`,children:`:8080`}),`.`]}),(0,E.jsx)(`div`,{className:`row-xs`,style:{marginTop:`var(--space-3)`},children:(0,E.jsxs)(M,{variant:`secondary`,onClick:()=>d(),children:[(0,E.jsx)(j,{name:`refresh`,size:13}),` Retry`]})})]}):u&&!c?(0,E.jsxs)(fr,{children:[h,(0,E.jsx)(mr,{children:[0,1,2,3].map(e=>(0,E.jsxs)(hr,{children:[(0,E.jsx)(_r,{children:(0,E.jsx)(oi,{width:`60%`})}),(0,E.jsx)(_r,{children:(0,E.jsx)(oi,{width:64})}),(0,E.jsx)(_r,{children:(0,E.jsx)(oi,{width:140})}),(0,E.jsx)(_r,{children:(0,E.jsx)(oi,{width:140})}),(0,E.jsx)(_r,{children:(0,E.jsx)(oi,{width:120})})]},e))})]}):c&&c.length===0?(0,E.jsxs)(vr,{children:[(0,E.jsx)(yr,{children:(0,E.jsx)(j,{name:`database`,size:24})}),(0,E.jsx)(br,{children:`No items yet`}),(0,E.jsxs)(xr,{children:[`This table reads live from the Go API's database (SQLite by default, Postgres via DATABASE_URL). Create the first item — it POSTs to`,` `,(0,E.jsx)(`code`,{className:`mono`,children:`/api/v1/items`}),` and SWR revalidates the list.`]}),(0,E.jsx)(Sr,{children:(0,E.jsxs)(M,{variant:`primary`,onClick:()=>r(!0),children:[(0,E.jsx)(j,{name:`plus`,size:14}),` New item`]})})]}):(0,E.jsxs)(fr,{children:[h,(0,E.jsx)(mr,{children:c?.map(e=>(0,E.jsxs)(hr,{children:[(0,E.jsxs)(_r,{children:[(0,E.jsx)(`div`,{style:{fontWeight:600},children:e.title}),e.description&&(0,E.jsx)(`div`,{className:`mono`,style:{marginTop:`var(--space-1)`,fontSize:`var(--text-2xs)`,color:`var(--muted-foreground)`},children:e.description})]}),(0,E.jsx)(_r,{children:(0,E.jsx)(O,{variant:e.status===`active`?`positive`:`secondary`,children:e.status})}),(0,E.jsx)(_r,{className:`mono`,style:{color:`var(--muted-foreground)`},children:_o.format(new Date(e.createdAt))}),(0,E.jsx)(_r,{className:`mono`,style:{color:`var(--muted-foreground)`},children:_o.format(new Date(e.updatedAt))}),(0,E.jsx)(_r,{children:i===e.id?(0,E.jsx)(hi,{size:`xs`}):(0,E.jsxs)(`div`,{className:`row-xs`,children:[(0,E.jsx)(`button`,{className:`button ghost`,style:vo,onClick:()=>m(e.id,()=>f(e.id,{status:e.status===`active`?`archived`:`active`})),children:e.status===`active`?`Archive`:`Restore`}),(0,E.jsx)(`button`,{className:`button ghost`,style:{...vo,color:`var(--destructive)`},"aria-label":`Delete ${e.title}`,onClick:()=>m(e.id,()=>p(e.id)),children:(0,E.jsx)(j,{name:`trash`,size:13})})]})})]},e.id))})]}),(0,E.jsxs)(`div`,{className:`flex-between muted`,style:{fontSize:`var(--text-3xs)`,padding:`0 var(--space-2)`},children:[(0,E.jsxs)(`span`,{children:[c?.length??0,` item`,c?.length===1?``:`s`,` · revalidated by SWR (reconnects refetch automatically)`]}),(0,E.jsxs)(`span`,{className:`mono`,children:[`GET /api/v1/items`,e===`all`?``:`?status=${e}`]})]}),(0,E.jsx)(bo,{open:n,onOpenChange:r})]})}function bo({open:e,onOpenChange:t}){let{create:n}=ho(),[r,i]=(0,_.useState)(``),[a,o]=(0,_.useState)(``),[s,c]=(0,_.useState)(!1),[l,u]=(0,_.useState)(null),d=()=>{i(``),o(``),c(!1),u(null)};return(0,E.jsx)(Br,{open:e,onOpenChange:t,children:(0,E.jsx)(Hr,{children:(0,E.jsxs)(`form`,{onSubmit:async e=>{e.preventDefault(),c(!0),u(null);try{await n({title:r,description:a.trim()===``?void 0:a}),d(),t(!1)}catch(e){c(!1),u(e instanceof Ki?e.message:`Unexpected error`)}},children:[(0,E.jsxs)(Ur,{children:[(0,E.jsx)(Wr,{children:`New item`}),(0,E.jsxs)(Gr,{children:[`POSTs to `,(0,E.jsx)(`code`,{className:`mono`,children:`/api/v1/items`}),`; the list revalidates through SWR on success.`]})]}),(0,E.jsxs)(`div`,{className:`stack-sm`,children:[(0,E.jsx)(Mi,{label:`Title`,hint:`Required · max 200 characters`,children:(0,E.jsx)(Ni,{value:r,onChange:e=>i(e.target.value),maxLength:200,placeholder:`Ship the api template`,autoFocus:!0})}),(0,E.jsx)(Mi,{label:`Description`,hint:`Optional context shown under the title`,children:(0,E.jsx)(Ni,{value:a,onChange:e=>o(e.target.value),placeholder:`What is this item about?`})}),l&&(0,E.jsx)(ir,{variant:`destructive`,icon:(0,E.jsx)(j,{name:`alert`,size:16}),children:(0,E.jsx)(or,{children:l})})]}),(0,E.jsx)(Kr,{children:(0,E.jsxs)(`div`,{className:`row-sm`,style:{justifyContent:`flex-end`},children:[(0,E.jsx)(M,{type:`button`,variant:`ghost`,onClick:()=>t(!1),disabled:s,children:`Cancel`}),(0,E.jsxs)(M,{type:`submit`,variant:`primary`,disabled:s||r.trim()===``,children:[s?(0,E.jsx)(hi,{size:`xs`}):(0,E.jsx)(j,{name:`plus`,size:13}),`Create item`]})]})})]})})})}var xo=/^(#{1,6})\s+(.*)$/,So=/^ {0,3}(?:-{3,}|\*{3,}|_{3,})\s*$/,Co=/^ {0,3}(`{3,}|~{3,})\s*([^\s`]*)\s*$/,wo=/^ {0,3}>\s?(.*)$/,To=/^(\s*)([-*+]|\d{1,9}[.)])\s+(.*)$/,Eo=/^\s*.*\|.*$/,Do=/^\s*\|?\s*:?-{2,}[\s:|-]*\|?\s*$/;function Oo(e){return ko(e.split(` +`)).blocks}function ko(e){let t=[],n=0;outer:for(;n5e3)break outer}return{blocks:t,next:n}}function Ao(e,t,n){let r=To.exec(e[t]??``)?.[2]??``,i=/\d/.test(r),a=i&&parseInt(r,10)||1,o=[],s=t;for(;sn){if(o.length>0){let t=Ao(e,s,a),n=o[o.length-1];n&&(n.sub=t.list),s=t.next;continue}break}let c=r[2]??``;if(i!==/\d/.test(c))break;o.push({spans:Po(r[3]??``)}),s++}return{list:{kind:`list`,ordered:i,start:a,items:o},next:s}}function jo(e,t){let n=To.exec(e);return n!==null&&(n[1]?.length??0)===t}function Mo(e){let t=e.trim();return t.startsWith(`|`)&&(t=t.slice(1)),t.endsWith(`|`)&&(t=t.slice(0,-1)),t.split(`|`).map(e=>e.trim())}var No=/(!\[[^\]]*\]\([^)]*\))|(\[[^\]]*\]\([^)]*\))|(`[^`\n]+`)|(\*\*[^*\n]+\*\*)|(__[^_\n]+__)|(~~[^~\n]+~~)|(\*[^*\n]+\*)|(_[^_\n]+_)/g;function Po(e){let t=[],n=0;for(let r of e.matchAll(No)){let i=r.index??0;i>n&&t.push({kind:`text`,text:e.slice(n,i)}),t.push(...Fo(r[0])),n=i+r[0].length}return nOo(e),[e]);return(0,E.jsx)(`div`,{className:n,children:r.map((e,n)=>(0,E.jsx)(Lo,{block:e,onNavigate:t},n))})}function Lo({block:e,onNavigate:t}){switch(e.kind){case`heading`:{let n=`h${e.level}`;return(0,E.jsx)(n,{children:e.spans.map((e,n)=>(0,E.jsx)(zo,{span:e,onNavigate:t},n))})}case`paragraph`:return(0,E.jsx)(`p`,{children:e.spans.map((e,n)=>(0,E.jsx)(zo,{span:e,onNavigate:t},n))});case`code`:return(0,E.jsx)(`pre`,{children:(0,E.jsx)(`code`,{children:e.text})});case`quote`:return(0,E.jsx)(`blockquote`,{children:e.blocks.map((e,n)=>(0,E.jsx)(Lo,{block:e,onNavigate:t},n))});case`list`:return(0,E.jsx)(Ro,{list:e,onNavigate:t});case`table`:return(0,E.jsxs)(`table`,{children:[(0,E.jsx)(`thead`,{children:(0,E.jsx)(`tr`,{children:e.head.map((e,t)=>(0,E.jsx)(`th`,{children:e},t))})}),(0,E.jsx)(`tbody`,{children:e.rows.map((e,t)=>(0,E.jsx)(`tr`,{children:e.map((e,t)=>(0,E.jsx)(`td`,{children:e},t))},t))})]});case`hr`:return(0,E.jsx)(`hr`,{})}}function Ro({list:e,onNavigate:t}){let n=e.ordered?`ol`:`ul`;return(0,E.jsx)(n,{start:e.ordered&&e.start!==1?e.start:void 0,children:e.items.map((e,n)=>(0,E.jsxs)(`li`,{children:[e.spans.map((e,n)=>(0,E.jsx)(zo,{span:e,onNavigate:t},n)),e.sub&&(0,E.jsx)(Ro,{list:e.sub,onNavigate:t})]},n))})}function zo({span:e,onNavigate:t}){switch(e.kind){case`text`:return(0,E.jsx)(E.Fragment,{children:e.text});case`code`:return(0,E.jsx)(`code`,{children:e.text});case`strong`:return(0,E.jsx)(`strong`,{children:e.spans.map((e,n)=>(0,E.jsx)(zo,{span:e,onNavigate:t},n))});case`em`:return(0,E.jsx)(`em`,{children:e.spans.map((e,n)=>(0,E.jsx)(zo,{span:e,onNavigate:t},n))});case`del`:return(0,E.jsx)(`del`,{children:e.spans.map((e,n)=>(0,E.jsx)(zo,{span:e,onNavigate:t},n))});case`image`:return(0,E.jsx)(`img`,{src:e.src,alt:e.alt,loading:`lazy`});case`link`:return(0,E.jsx)(Bo,{href:e.href,onNavigate:t,children:Vo(e.spans,t)})}}function Bo({href:e,onNavigate:t,children:n,...r}){let i=/^https?:\/\//i.test(e);return(0,E.jsx)(`a`,{href:e,onClick:n=>{i&&t&&(n.preventDefault(),t(e))},title:i?`Open in the agent view`:void 0,...r,children:n})}function Vo(e,t){return e.map((e,n)=>(0,E.jsx)(zo,{span:e,onNavigate:t},n))}function Ho(e){return Ji(`/api/v1/browse?url=${encodeURIComponent(e)}`)}var Uo={snapshot:e=>[`browse`,`snapshot`,e]};function Wo(e){let{data:t,error:n,isLoading:r,mutate:i}=ao(e===null?null:Uo.snapshot(e),()=>Ho(e),{keepPreviousData:!0});return{snapshot:t,error:n,isLoading:r,refresh:i}}var Go=[`anthropic.com`,`example.com`,`developer.mozilla.org`];function Ko(e){return new URLSearchParams(e).get(`url`)?.trim()||null}function L(){let[e,t]=C(),n=Ko(w()),[r,i]=(0,_.useState)(n??``),[a,o]=(0,_.useState)(`markdown`),{snapshot:s,error:c,isLoading:l,refresh:u}=Wo(n),d=n=>{let r=n.trim();r&&(i(r),o(`markdown`),t(`${e.split(`?`)[0]}?url=${encodeURIComponent(r)}`))};return(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsx)(et,{children:`Browse as an agent`}),(0,E.jsxs)(tt,{children:[`Fetches the page server-side without JavaScript, converts it to markdown, and gathers the `,(0,E.jsx)(`code`,{className:`mono`,children:`llms.txt`}),` files — exactly what an LLM sees when it “opens” this site.`]})]}),(0,E.jsxs)(`form`,{className:`agent-url-row`,onSubmit:e=>{e.preventDefault(),d(r)},children:[(0,E.jsx)(Ni,{value:r,onChange:e=>i(e.target.value),placeholder:`example.com or https://example.com/docs`,"aria-label":`Domain or URL to inspect`,autoFocus:!0}),(0,E.jsxs)(M,{type:`submit`,variant:`primary`,disabled:r.trim()===``||l&&n!==null,children:[l&&n!==null?(0,E.jsx)(hi,{size:`xs`}):(0,E.jsx)(j,{name:`search`,size:14}),`View as agent`]})]}),(0,E.jsx)(`div`,{className:`agent-examples`,children:Go.map(e=>(0,E.jsx)(`button`,{type:`button`,className:`button ghost agent-example`,onClick:()=>d(e),children:e},e))})]}),c&&!s?(0,E.jsx)(Yo,{error:c,onRetry:()=>u()}):n?l&&!s?(0,E.jsx)(Jo,{}):s?(0,E.jsx)(Xo,{snapshot:s,tab:a,onTab:o,onNavigate:d,onRefresh:()=>u()}):null:(0,E.jsx)(R,{})]})}function R(){return(0,E.jsxs)(vr,{children:[(0,E.jsx)(yr,{children:(0,E.jsx)(j,{name:`cpu`,size:26})}),(0,E.jsx)(br,{children:`What does your site look like to an LLM?`}),(0,E.jsxs)(xr,{children:[`Agents never run JavaScript and often skip the HTML entirely: they read markdown and`,` `,(0,E.jsx)(`code`,{className:`mono`,children:`llms.txt`}),`. Enter a domain to validate what they actually get — the rendered markdown, the curated link map, robots rules, and a list of fixes.`]}),(0,E.jsx)(Sr,{children:Go.map(e=>(0,E.jsx)(qo,{url:e},e))})]})}function qo({url:e}){let[t,n]=C();return(0,E.jsxs)(M,{variant:`secondary`,onClick:()=>n(`${t.split(`?`)[0]}?url=${encodeURIComponent(e)}`),children:[(0,E.jsx)(j,{name:`external-link`,size:13}),` `,e]})}function Jo(){return(0,E.jsx)(Qe,{className:`agent-doc`,children:(0,E.jsxs)(`div`,{className:`stack-sm`,children:[(0,E.jsx)(oi,{width:`40%`,height:28}),(0,E.jsx)(oi,{width:`100%`}),(0,E.jsx)(oi,{width:`92%`}),(0,E.jsx)(oi,{width:`96%`}),(0,E.jsx)(oi,{width:`60%`})]})})}function Yo({error:e,onRetry:t}){let n=e instanceof Ki?e.code:`unknown`,r=n===`unavailable`||n===`timeout`;return(0,E.jsxs)(ir,{variant:r?`warning`:`destructive`,icon:(0,E.jsx)(j,{name:r?`warning`:`alert`,size:18}),children:[(0,E.jsx)(ar,{children:r?`The site did not answer`:`Inspection failed`}),(0,E.jsx)(or,{children:r?`The server could not fetch this URL within the time limit — it may be down, very slow, or blocking the fetch.`:e.message}),(0,E.jsx)(`div`,{className:`row-xs`,style:{marginTop:`var(--space-3)`},children:(0,E.jsxs)(M,{variant:`secondary`,onClick:t,children:[(0,E.jsx)(j,{name:`refresh`,size:13}),` Try again`]})})]})}function Xo({snapshot:e,tab:t,onTab:n,onNavigate:r,onRefresh:i}){let a=e.files,o=[a.llmsTxt,a.llmsFullTxt,a.wellKnownLlmsTxt].some(e=>e?.status&&e.status<400),s=$o(e.checks);return(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsxs)(`div`,{className:`flex-between agent-head`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,E.jsxs)(`div`,{className:`row-sm`,style:{alignItems:`center`,flexWrap:`wrap`},children:[(0,E.jsx)(Zo,{status:e.status}),(0,E.jsx)(`span`,{className:`mono agent-url`,children:e.finalUrl}),e.requestedUrl!==e.finalUrl&&(0,E.jsxs)(O,{variant:`outline`,children:[`redirected from `,e.requestedUrl]}),(0,E.jsxs)(`span`,{className:`muted`,style:{fontSize:`var(--text-xs)`},children:[e.durationMs,` ms · `,e.contentType.split(`;`)[0]||`unknown type`]})]}),(0,E.jsxs)(M,{variant:`ghost`,onClick:i,children:[(0,E.jsx)(j,{name:`refresh`,size:13}),` Re-run`]})]}),(0,E.jsxs)(ti,{value:t,onValueChange:n,children:[(0,E.jsxs)(ri,{children:[(0,E.jsx)(ii,{value:`markdown`,children:`Markdown`}),(0,E.jsx)(ii,{value:`source`,children:`Source`}),(0,E.jsxs)(ii,{value:`llms`,children:[`llms.txt`,o?``:` ·`]}),(0,E.jsx)(ii,{value:`robots`,children:`robots.txt`}),(0,E.jsx)(ii,{value:`meta`,children:`Meta`}),(0,E.jsxs)(ii,{value:`checks`,children:[`Checks`,s.total>0?` (${s.total})`:``]})]}),(0,E.jsx)(ai,{value:`markdown`,children:(0,E.jsxs)(`div`,{className:`stack-sm`,children:[(0,E.jsxs)(`div`,{className:`flex-between muted agent-note`,children:[(0,E.jsxs)(`span`,{children:[e.markdown.length.toLocaleString(),` characters ·`,` `,e.page?`${e.page.linkCount} links`:`non-HTML document`,` — links stay in the viewer, like an agent re-entering a page.`]}),e.markdownTruncated&&(0,E.jsx)(O,{variant:`destructive`,children:`truncated`})]}),e.markdown.trim()===``?(0,E.jsxs)(ir,{variant:`warning`,icon:(0,E.jsx)(j,{name:`warning`,size:18}),children:[(0,E.jsx)(ar,{children:`No content without JavaScript`}),(0,E.jsxs)(or,{children:[`The server sent `,e.page?`${e.page.scriptCount} script tags and `:``,`no readable body text. An agent sees an empty page here.`]})]}):(0,E.jsx)(Qe,{className:`agent-doc`,children:(0,E.jsx)(Io,{source:e.markdown,onNavigate:r,className:`markdown-body`})})]})}),(0,E.jsx)(ai,{value:`source`,children:(0,E.jsx)(es,{text:e.markdown,note:`${e.markdown.length.toLocaleString()} characters of markdown`})}),(0,E.jsx)(ai,{value:`llms`,children:(0,E.jsxs)(`div`,{className:`stack-md`,children:[(0,E.jsx)(z,{label:`/llms.txt`,file:a.llmsTxt,spec:!0,onNavigate:r}),(0,E.jsx)(z,{label:`/llms-full.txt`,file:a.llmsFullTxt,onNavigate:r}),(0,E.jsx)(z,{label:`/.well-known/llms.txt`,file:a.wellKnownLlmsTxt,onNavigate:r})]})}),(0,E.jsx)(ai,{value:`robots`,children:(0,E.jsx)(z,{label:`/robots.txt`,file:a.robotsTxt,onNavigate:r})}),(0,E.jsx)(ai,{value:`meta`,children:(0,E.jsx)(rs,{snapshot:e})}),(0,E.jsx)(ai,{value:`checks`,children:(0,E.jsx)(is,{checks:e.checks})})]})]})}function Zo({status:e}){return(0,E.jsxs)(O,{variant:e<300?`positive`:e<400?`primary`:`destructive`,children:[e,` `,e<300?`OK`:e<400?`redirect`:`error`]})}function Qo({severity:e}){return(0,E.jsx)(O,{variant:{ok:`positive`,info:`secondary`,warn:`primary`,error:`destructive`}[e],children:e})}function $o(e){let t={total:e.length,warn:0,error:0};for(let n of e)n.severity===`warn`&&t.warn++,n.severity===`error`&&t.error++;return t}function es({text:e,note:t}){let[n,r]=(0,_.useState)(!1);return(0,E.jsxs)(Qe,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{padding:`var(--space-3) var(--space-4)`,borderBottom:`1px solid var(--border)`},children:[(0,E.jsx)(`span`,{className:`muted`,style:{fontSize:`var(--text-xs)`},children:t}),(0,E.jsxs)(M,{variant:`ghost`,onClick:async()=>{try{await navigator.clipboard.writeText(e),r(!0),setTimeout(()=>r(!1),1500)}catch{}},children:[(0,E.jsx)(j,{name:n?`check`:`copy`,size:13}),` `,n?`Copied`:`Copy`]})]}),(0,E.jsx)(`pre`,{className:`agent-raw mono`,children:e})]})}function z({label:e,file:t,spec:n,onNavigate:r}){return(0,E.jsxs)(Qe,{children:[(0,E.jsxs)($e,{children:[(0,E.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-2)`},children:[(0,E.jsxs)(`div`,{className:`row-sm`,style:{alignItems:`center`},children:[(0,E.jsx)(j,{name:`file`,size:15}),(0,E.jsx)(et,{children:e}),(0,E.jsx)(ts,{file:t})]}),t?.url&&(0,E.jsxs)(`a`,{className:`mono muted agent-file-url`,href:t.url,target:`_blank`,rel:`noreferrer`,children:[t.url,` `,(0,E.jsx)(j,{name:`external-link`,size:11})]})]}),(0,E.jsx)(tt,{children:t===null?`Not fetched (the request failed before an answer).`:n?`The llmstxt.org convention: a curated, agent-first map of the site.`:void 0})]}),t?.status&&t.status<400?(0,E.jsxs)(`div`,{className:`stack-sm`,children:[t.llmsDoc&&(0,E.jsx)(ns,{doc:t.llmsDoc,onNavigate:r}),(0,E.jsxs)(`details`,{children:[(0,E.jsxs)(`summary`,{className:`muted`,style:{fontSize:`var(--text-xs)`,cursor:`pointer`},children:[`Raw `,e]}),(0,E.jsx)(`pre`,{className:`agent-raw mono`,children:t.content})]})]}):(0,E.jsx)(`p`,{className:`muted`,style:{margin:0,fontSize:`var(--text-sm)`},children:t?.error?`Unreachable: ${t.error}`:t?.status?`Not published (HTTP ${t.status}).${n?` Agents fall back to parsing the HTML — adding one is the single highest-impact fix.`:``}`:`No response recorded.`})]})}function ts({file:e}){return e===null?(0,E.jsx)(O,{variant:`destructive`,children:`failed`}):e.status<300?(0,E.jsx)(O,{variant:`positive`,children:`found`}):e.status<400?(0,E.jsx)(O,{variant:`primary`,children:`redirect`}):e.status===404?(0,E.jsx)(O,{variant:`secondary`,children:`missing`}):(0,E.jsxs)(O,{variant:`destructive`,children:[`HTTP `,e.status]})}function ns({doc:e,onNavigate:t}){return(0,E.jsxs)(`div`,{className:`agent-llms`,children:[e.title&&(0,E.jsx)(`h3`,{className:`agent-llms-title`,children:e.title}),e.description&&(0,E.jsx)(`blockquote`,{className:`agent-llms-quote`,children:e.description}),e.sections.map((e,n)=>(0,E.jsxs)(`div`,{className:`agent-llms-section`,children:[e.heading&&(0,E.jsx)(`h4`,{children:e.heading}),e.description&&(0,E.jsx)(`p`,{className:`muted`,children:e.description}),(0,E.jsx)(`ul`,{children:e.links.map((e,n)=>(0,E.jsxs)(`li`,{children:[(0,E.jsx)(`a`,{href:e.url,onClick:n=>{t&&/^https?:\/\//i.test(e.url)&&(n.preventDefault(),t(e.url))},children:e.title||e.url}),e.description&&(0,E.jsxs)(`span`,{className:`muted`,children:[` — `,e.description]})]},n))})]},n)),e.linkCount===0&&(0,E.jsx)(`p`,{className:`muted`,children:`No links parsed from this file.`})]})}function rs({snapshot:e}){let t=e.page,n=t?[[`Title`,t.title||`—`],[`Description`,t.description||`—`],[`Canonical`,t.canonical||`—`],[`Meta robots`,t.robotsMeta||`not set`],[`Language`,t.lang||`—`],[`H1`,t.h1||`—`],[`Links`,`${t.linkCount} followable · ${t.deadLinks} dead`],[`Scripts`,String(t.scriptCount)],[`Images`,String(t.imageCount)],[`Visible text`,`${t.textLength.toLocaleString()} chars · ${t.wordCount.toLocaleString()} words`]]:[[`Content type`,e.contentType||`—`]];return(0,E.jsx)(Qe,{children:(0,E.jsx)(`dl`,{className:`agent-meta`,children:n.map(([e,t])=>(0,E.jsxs)(`div`,{className:`agent-meta-row`,children:[(0,E.jsx)(`dt`,{className:`muted`,children:e}),(0,E.jsx)(`dd`,{children:t})]},e))})})}function is({checks:e}){let t=$o(e);return(0,E.jsxs)(Qe,{children:[(0,E.jsxs)(`div`,{className:`row-sm agent-checks-summary`,style:{flexWrap:`wrap`},children:[(0,E.jsxs)(O,{variant:`destructive`,children:[t.error,` errors`]}),(0,E.jsxs)(O,{variant:`primary`,children:[t.warn,` warnings`]}),(0,E.jsxs)(O,{variant:`secondary`,children:[e.filter(e=>e.severity===`info`).length,` notes`]}),(0,E.jsxs)(O,{variant:`positive`,children:[e.filter(e=>e.severity===`ok`).length,` passed`]})]}),(0,E.jsx)(`ul`,{className:`agent-checks`,children:e.map(e=>(0,E.jsxs)(`li`,{className:`agent-check`,children:[(0,E.jsx)(Qo,{severity:e.severity}),(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`div`,{className:`agent-check-label`,children:e.label}),(0,E.jsx)(`div`,{className:`agent-check-detail muted`,children:e.detail})]})]},e.id))})]})}var as=`/patterns`,os=`/items`,ss=`/agent-view`,cs=[`Application Patterns`,`Components`,`Foundations`,`Documentation`],ls={"Application Patterns":`Production-grade composites that ship as one drop-in unit.`,Components:`The atoms: buttons, icons, form controls and the primitives behind them.`,Foundations:`The tokens that carry the system — color roles and the type scale.`,Documentation:`Editorial and developer surfaces for docs, changelogs and embedded code.`},B=[{path:ss,group:`Application Patterns`,label:`Agent view`,index:`01`,kicker:`AGENT TOOLING`,title:`Agent view — browse as an LLM`,description:`Enter a domain and see what an agent sees: the page as markdown with followable links, its llms.txt map, robots rules and readiness checks.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`/api/v1/browse · llms.txt`}),page:L},{path:as,group:`Application Patterns`,label:`Application Patterns`,index:`02`,kicker:`PATTERNS & EXAMPLES`,title:`Reusable Application Patterns`,description:`Production-grade, fully functional composable components ready to drop into any project.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`4 Reusable Components`}),page:Xr},{path:`/components/buttons`,group:`Components`,label:`Buttons`,index:`03`,kicker:`COMPONENTS`,title:`Buttons`,description:`Actions with a clear hierarchy and dependable feedback.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`Button · 12 variants`}),page:bi},{path:`/components/icons`,group:`Components`,label:`Icons`,index:`04`,kicker:`COMPONENTS`,title:`Icons (Lucide)`,description:`Crisp, scalable SVG icons powered by Lucide. Tree-shakeable, stroke-matched, and token-aware.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`iconRegistry · 41 curated · lucide 1,400+`}),page:wi},{path:`/foundations/colors`,group:`Foundations`,label:`Color tokens`,index:`05`,kicker:`FOUNDATIONS`,title:`Color tokens`,description:`Functional color roles in CSS Color 4 lab() keep every surface intentional.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`48 tokens · lab()`}),page:Oi},{path:`/foundations/typography`,group:`Foundations`,label:`Typography`,index:`06`,kicker:`FOUNDATIONS`,title:`Typography`,description:`Modular rem-based type scale with dual-family hierarchy (Manrope & DM Mono).`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`Type scale · 9→70px`}),page:ji},{path:`/components/forms`,group:`Components`,label:`Form controls`,index:`07`,kicker:`PRIMITIVES`,title:`Form controls`,description:`Inputs designed for focus, flow, and the occasional messy edge case.`,page:Pi},{path:`/components/code`,group:`Components`,label:`Composable code`,index:`08`,kicker:`CODE`,title:`Composable by default`,description:`Small APIs. Strong defaults. No surprises.`,page:Ri},{path:`/docs/markdown`,group:`Documentation`,label:`Markdown rendering`,index:`09`,kicker:`CONTENT`,title:`Markdown rendering`,description:`A readable editorial layer for changelogs, docs, and product notes.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`Markdown · styled`}),page:Bi},{path:`/docs/editor`,group:`Documentation`,label:`CodeMirror theme`,index:`10`,kicker:`DEVELOPER TOOLING`,title:`CodeMirror theme`,description:`A focused editor palette for examples, playgrounds, and embedded code.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`codemirror · dark`}),page:Ui},{path:os,group:`Application Patterns`,label:`Items (live API)`,index:`11`,kicker:`FULLSTACK`,title:`Live data — Go API + SWR`,description:`The Go backend wired end to end: typed api modules, SWR hooks, mutations, and every loading state.`,meta:(0,E.jsx)(`span`,{className:`api-pill`,children:`SWR · /api/v1/items · SQLite/Postgres`}),page:yo}],us={"/components/buttons":12,"/components/icons":41};function ds(e){return B.find(t=>t.path===e)}function fs(e){return B.filter(t=>t.group===e)}var ps=[{label:`Application Patterns`,items:[...Ze.map(e=>({label:e.label,href:`${as}?pattern=${e.id}`})),...fs(`Application Patterns`).map(e=>({label:e.label,href:e.path}))]},...cs.filter(e=>e!==`Application Patterns`).map(e=>({label:e,items:fs(e).map(e=>({label:e.label,href:e.path,count:us[e.path]}))}))];function ms(e){let t=new URLSearchParams(e).get(`pattern`);return Ze.some(e=>e.id===t)?t:`metrics`}function hs(e,t){return e===`/patterns`?`${as}?pattern=${ms(t)}`:e}function gs(){let{status:e,user:t,signOut:n}=Gi(),[r,i]=(0,_.useState)(!1),a=(0,_.useRef)(null);if((0,_.useEffect)(()=>{if(!r)return;let e=e=>{a.current?.contains(e.target)===!1&&i(!1)},t=e=>{e.key===`Escape`&&i(!1)};return document.addEventListener(`pointerdown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`pointerdown`,e),document.removeEventListener(`keydown`,t)}},[r]),e===`loading`)return(0,E.jsx)(`span`,{className:`avatar skeleton-pulse`,"aria-hidden":`true`});if(e===`anonymous`||t===null)return(0,E.jsx)(`button`,{type:`button`,className:`top-signin`,onClick:()=>Wi(),children:`Sign in`});let o=t.name||t.email;return(0,E.jsxs)(`div`,{className:`user-menu`,ref:a,children:[(0,E.jsx)(`button`,{type:`button`,className:`avatar`,onClick:()=>i(e=>!e),"aria-haspopup":`menu`,"aria-expanded":r,"aria-label":o,title:o,children:_s(o)}),r&&(0,E.jsxs)(`div`,{className:`user-menu-popover`,role:`menu`,children:[(0,E.jsxs)(`div`,{className:`user-menu-identity`,children:[t.name&&(0,E.jsx)(`b`,{children:t.name}),(0,E.jsx)(`span`,{children:t.email})]}),(0,E.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`user-menu-signout`,onClick:()=>{i(!1),n()},children:[(0,E.jsx)(j,{name:`log-out`,size:14}),`Sign out`]})]})]})}function _s(e){return e.trim().split(/\s+/).filter(Boolean).slice(0,2).map(e=>e.charAt(0)).join(``).toUpperCase()}var vs={default:`Default`,compact:`Compact`};function ys({onMenuToggle:e}){let{theme:t,toggleTheme:n,viewMode:r,setViewMode:i,openSearch:a}=Re();return(0,E.jsxs)(`header`,{className:`topbar`,children:[(0,E.jsx)(`div`,{className:`brand`,children:(0,E.jsxs)(Ne,{href:`/`,className:`brand-link`,children:[(0,E.jsx)(`div`,{className:`brand-mark`,children:(0,E.jsx)(`span`,{})}),(0,E.jsx)(`b`,{children:`northstar`}),(0,E.jsx)(`span`,{className:`version`,children:`v0.8.2`})]})}),(0,E.jsxs)(`button`,{type:`button`,className:`top-search`,onClick:a,"aria-label":`Search components, tokens, docs (Press ⌘K)`,children:[(0,E.jsx)(j,{name:`search`,size:16}),(0,E.jsx)(`span`,{className:`top-search-placeholder`,children:`Search components, tokens, docs...`}),(0,E.jsx)(`kbd`,{children:`⌘ K`})]}),(0,E.jsxs)(`nav`,{className:`top-links`,children:[(0,E.jsx)(Ne,{href:`/docs/markdown`,children:`Docs`}),(0,E.jsx)(`a`,{href:`#github`,children:`GitHub ↗`}),(0,E.jsx)(`div`,{className:`segmented top-view-mode`,role:`group`,"aria-label":`View mode`,children:Ie.map(e=>(0,E.jsx)(`button`,{type:`button`,className:e===r?`selected`:void 0,"aria-pressed":e===r,title:`Switch to ${vs[e].toLowerCase()} view`,onClick:()=>i(e),children:vs[e]},e))}),(0,E.jsx)(`button`,{type:`button`,className:`icon-button`,onClick:n,"aria-label":`Switch to ${t===`dark`?`light`:`dark`} theme`,children:(0,E.jsx)(j,{name:t===`dark`?`sun`:`moon`,size:17})}),(0,E.jsx)(gs,{})]}),(0,E.jsx)(`button`,{type:`button`,className:`mobile-menu icon-button`,onClick:e,"aria-label":`Toggle navigation`,children:(0,E.jsx)(j,{name:`menu`})})]})}function bs({groups:e,activeHref:t,onNavigate:n,collapsed:r=!1,onToggleCollapse:i}){return(0,E.jsxs)(`aside`,{className:`sidebar`,children:[(0,E.jsxs)(`div`,{className:`sidebar-heading`,children:[(0,E.jsxs)(`div`,{className:`sidebar-library`,children:[(0,E.jsx)(j,{name:`layers`,size:13}),` Library`]}),(0,E.jsx)(`button`,{type:`button`,className:`sidebar-collapse`,onClick:i,"aria-pressed":r,"aria-label":r?`Expand sidebar`:`Collapse sidebar`,children:r?`⌘+`:`⌘−`})]}),(0,E.jsxs)(`div`,{className:`sidebar-intro`,children:[(0,E.jsx)(`span`,{className:`eyebrow`,children:`Northstar system`}),(0,E.jsx)(`p`,{children:`Principles and primitives for product teams.`})]}),(0,E.jsx)(`nav`,{"aria-label":`Documentation navigation`,onClick:n,children:e.map(e=>(0,E.jsxs)(`div`,{className:`nav-group`,children:[(0,E.jsx)(`span`,{className:`nav-label`,children:e.label}),e.items.map(e=>{let n=e.href===t;return(0,E.jsxs)(Ne,{href:e.href,className:n?`nav-item active`:`nav-item`,"aria-current":n?`page`:void 0,children:[(0,E.jsx)(`span`,{className:`nav-glyph`,"aria-hidden":`true`,children:e.count?`◈`:`·`}),(0,E.jsx)(`span`,{children:e.label}),e.count!==void 0&&(0,E.jsx)(`span`,{className:`nav-count`,children:e.count})]},e.label)})]},e.label))}),(0,E.jsxs)(`div`,{className:`sidebar-bottom`,children:[(0,E.jsxs)(`div`,{className:`status-line`,children:[(0,E.jsx)(`span`,{className:`status-dot`}),`All systems operational`]}),(0,E.jsx)(`span`,{className:`mono muted`,children:`Updated 2 min ago`})]})]})}function xs({index:e,title:t,description:n,meta:r,children:i,id:a,className:o=``}){return(0,E.jsxs)(`section`,{className:`section-block ${o}`.trim(),id:a,children:[(0,E.jsxs)(`div`,{className:`section-heading`,children:[(0,E.jsxs)(`div`,{children:[(0,E.jsx)(`span`,{className:`section-index`,children:e}),(0,E.jsx)(`h2`,{children:t}),(0,E.jsx)(`p`,{children:n})]}),r]}),i]})}function Ss({title:e,links:t,activeHref:n}){return(0,E.jsxs)(`aside`,{className:`right-rail`,children:[(0,E.jsxs)(`div`,{className:`rail-card`,children:[(0,E.jsx)(`span`,{className:`eyebrow`,children:e}),t.map((e,t)=>(0,E.jsxs)(Ne,{className:e.href===n?`rail-link active`:`rail-link`,href:e.href,"aria-current":e.href===n?`page`:void 0,children:[(0,E.jsxs)(`span`,{children:[`0`,t+1]}),e.label]},e.label))]}),(0,E.jsxs)(`div`,{className:`rail-card release`,children:[(0,E.jsx)(`div`,{className:`release-icon`,children:(0,E.jsx)(j,{name:`layers`,size:18})}),(0,E.jsx)(`strong`,{children:`Designed to be extended`}),(0,E.jsx)(`p`,{children:`Bring your brand, keep the rhythm. Tokens are portable and components stay unopinionated.`}),(0,E.jsxs)(Ne,{className:`text-button`,href:`/docs/markdown`,children:[`Read the docs `,(0,E.jsx)(j,{name:`arrow`,size:14})]})]}),(0,E.jsxs)(`div`,{className:`rail-card`,children:[(0,E.jsx)(`span`,{className:`eyebrow`,children:`Need a hand?`}),(0,E.jsx)(`p`,{className:`rail-copy`,children:`Check the contribution guide or say hello in the community.`}),(0,E.jsxs)(M,{variant:`secondary`,className:`full`,children:[`Open community `,(0,E.jsx)(`span`,{children:`↗`})]})]})]})}var Cs=[{id:`pat-agent-view`,title:`Agent view — browse as an LLM`,description:`Enter a domain, see the page as markdown, its llms.txt map and readiness checks`,category:`Patterns`,icon:`cpu`,path:`/agent-view`},{id:`pat-metrics`,title:`Metrics Dashboard`,description:`Telemetry dashboard with StatCards, time range picker, and progress gauges`,category:`Patterns`,icon:`sparkles`,path:`/patterns`,patternId:`metrics`},{id:`pat-settings`,title:`Settings & Safeguards`,description:`Preferences panel with API keys, toggle switches, and alert banners`,category:`Patterns`,icon:`settings`,path:`/patterns`,patternId:`settings`},{id:`pat-table`,title:`Service Monitor Table`,description:`Real-time service health table with status filtering and search`,category:`Patterns`,icon:`layers`,path:`/patterns`,patternId:`table`},{id:`pat-deploy`,title:`Canary Deployment Flow`,description:`Interactive rollout modal with live progress simulation`,category:`Patterns`,icon:`terminal`,path:`/patterns`,patternId:`deploy`},{id:`pat-items`,title:`Items (live API)`,description:`Full-stack demo: typed api modules, SWR hooks, live Postgres data`,category:`Patterns`,icon:`database`,path:`/items`},{id:`comp-buttons`,title:`Buttons & Action States`,description:`Primary, secondary, destructive, ghost variants with resting, hover, active and focus states`,category:`Components`,icon:`arrow-right`,path:`/components/buttons`},{id:`comp-icons`,title:`Lucide Icons Explorer`,description:`Over 1,400+ tree-shaken SVG icons with search, category filtering and 1-click copy`,category:`Components`,icon:`sparkles`,path:`/components/icons`},{id:`comp-forms`,title:`Form Controls & Inputs`,description:`Accessible text inputs, secret key revealers, and toggle switches`,category:`Components`,icon:`eye`,path:`/components/forms`},{id:`comp-code`,title:`Composable UI Primitives`,description:`Zero-drift Dialog, Sheet, Tabs, Table, Alert, Progress, Switch, and StatCard`,category:`Components`,icon:`code`,path:`/components/code`},{id:`found-colors`,title:`Color Tokens (CSS Color 4 lab())`,description:`Pitch black dark theme and pure white daylight light theme tokens`,category:`Foundations`,icon:`sun`,path:`/foundations/colors`},{id:`found-type`,title:`Typography & Scale`,description:`Modular rem-based 9px to 70px scale with Manrope and DM Mono families`,category:`Foundations`,icon:`file`,path:`/foundations/typography`},{id:`doc-md`,title:`Markdown Editorial Layer`,description:`Changelogs, release notes, and documentation typography`,category:`Documentation`,icon:`file`,path:`/docs/markdown`},{id:`doc-cm`,title:`CodeMirror Editor Theme`,description:`Syntax-highlighted code editor preview with line numbers and token palette`,category:`Documentation`,icon:`terminal`,path:`/docs/editor`}],ws=`search-palette-listbox`;function Ts({isOpen:e,onClose:t,onSelect:n,initialQuery:r=``}){let[i,a]=(0,_.useState)(r),[o,s]=(0,_.useState)(0),c=(0,_.useRef)(null),l=(0,_.useRef)(null);Dr(e,c),(0,_.useEffect)(()=>{e&&l.current?.focus()},[e,r]);let u=(0,_.useMemo)(()=>{if(!i.trim())return Cs;let e=i.toLowerCase();return Cs.filter(t=>t.title.toLowerCase().includes(e)||t.description.toLowerCase().includes(e)||t.category.toLowerCase().includes(e))},[i]),d=u.length===0?-1:Math.min(o,u.length-1),f=d>=0?u[d]:void 0;return(0,_.useEffect)(()=>{if(!e)return;let r=e=>{e.key===`Escape`?(e.preventDefault(),t()):e.key===`ArrowDown`?(e.preventDefault(),s(e=>u.length?(e+1)%u.length:0)):e.key===`ArrowUp`?(e.preventDefault(),s(e=>u.length?(e-1+u.length)%u.length:0)):e.key===`Enter`&&f&&(e.preventDefault(),n(f),t())};return window.addEventListener(`keydown`,r),()=>window.removeEventListener(`keydown`,r)},[e,u.length,f,t,n]),e?(0,E.jsx)(`div`,{className:`search-palette-backdrop`,onClick:t,children:(0,E.jsxs)(`div`,{ref:c,role:`dialog`,"aria-modal":`true`,"aria-label":`Search`,tabIndex:-1,className:`search-palette-modal`,onKeyDown:e=>{Er(e,c.current)},onClick:e=>e.stopPropagation(),children:[(0,E.jsxs)(`div`,{className:`search-palette-head`,children:[(0,E.jsx)(j,{name:`search`,size:18,className:`search-palette-icon`}),(0,E.jsx)(`input`,{ref:l,type:`text`,role:`combobox`,"aria-expanded":u.length>0,"aria-controls":ws,"aria-activedescendant":f?`search-option-${f.id}`:void 0,"aria-label":`Search components, tokens, and docs`,className:`search-palette-input`,placeholder:`Type a command, component, or token...`,value:i,onChange:e=>{a(e.target.value),s(0)}}),i&&(0,E.jsx)(`button`,{type:`button`,className:`icon-button`,onClick:()=>{a(``),s(0)},"aria-label":`Clear search`,children:(0,E.jsx)(j,{name:`close`,size:14})}),(0,E.jsx)(ur,{children:`ESC`})]}),(0,E.jsx)(`div`,{className:`search-palette-body`,children:u.length>0?(0,E.jsx)(`ul`,{id:ws,role:`listbox`,"aria-label":`Search results`,className:`search-palette-results`,children:u.map((e,r)=>{let i=r===d;return(0,E.jsxs)(`li`,{id:`search-option-${e.id}`,role:`option`,"aria-selected":i,className:`search-palette-item ${i?`selected`:``}`,onClick:()=>{n(e),t()},onMouseEnter:()=>s(r),children:[(0,E.jsx)(`div`,{className:`search-item-glyph`,children:(0,E.jsx)(j,{name:e.icon,size:16})}),(0,E.jsxs)(`div`,{className:`search-item-content`,children:[(0,E.jsxs)(`div`,{className:`search-item-title-row`,children:[(0,E.jsx)(`span`,{className:`search-item-title`,children:e.title}),(0,E.jsx)(O,{variant:`outline`,children:e.category})]}),(0,E.jsx)(`p`,{className:`search-item-desc`,children:e.description})]}),i&&(0,E.jsx)(`div`,{className:`search-item-action`,children:(0,E.jsx)(ur,{children:`↵`})})]},e.id)})}):(0,E.jsxs)(`div`,{className:`search-palette-empty`,children:[(0,E.jsx)(j,{name:`search`,size:24}),(0,E.jsxs)(`p`,{children:[`No results found for “`,i,`”`]}),(0,E.jsx)(`span`,{children:`Try searching for “Buttons”, “Metrics”, “Tokens”, or “Icons”.`})]})}),(0,E.jsxs)(`div`,{className:`search-palette-footer`,children:[(0,E.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,E.jsx)(ur,{children:`↑`}),(0,E.jsx)(ur,{children:`↓`}),(0,E.jsx)(`span`,{children:`to navigate`})]}),(0,E.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,E.jsx)(ur,{children:`↵`}),(0,E.jsx)(`span`,{children:`to select`})]}),(0,E.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,E.jsx)(ur,{children:`ESC`}),(0,E.jsx)(`span`,{children:`to close`})]})]})]})}):null}function Es(){return(0,E.jsxs)(`section`,{className:`hero-section`,children:[(0,E.jsxs)(`div`,{className:`hero-copy`,children:[(0,E.jsx)(`span`,{className:`eyebrow accent`,children:`Component library`}),(0,E.jsx)(`h1`,{children:`Build with clarity.`}),(0,E.jsx)(`p`,{children:`A considered set of accessible, composable components for building calm, capable interfaces.`}),(0,E.jsxs)(`div`,{className:`hero-actions`,children:[(0,E.jsxs)(Zr,{variant:`primary`,href:`/components/buttons`,children:[`Explore components `,(0,E.jsx)(j,{name:`arrow`,size:16})]}),(0,E.jsx)(Zr,{variant:`ghost`,href:`/docs/markdown`,children:`Read the principles`})]})]}),(0,E.jsxs)(`div`,{className:`hero-orbit`,"aria-hidden":`true`,children:[(0,E.jsx)(`div`,{className:`orbit orbit-one`}),(0,E.jsx)(`div`,{className:`orbit orbit-two`}),(0,E.jsxs)(`div`,{className:`orbit-core`,children:[(0,E.jsx)(`div`,{className:`brand-mark large`,children:(0,E.jsx)(`span`,{})}),(0,E.jsxs)(`span`,{children:[`system`,(0,E.jsx)(`br`,{}),(0,E.jsx)(`b`,{children:`ready`})]})]}),(0,E.jsxs)(`span`,{className:`orbit-label label-one`,children:[`TOKENS `,(0,E.jsx)(`b`,{children:`48`})]}),(0,E.jsxs)(`span`,{className:`orbit-label label-two`,children:[`A11Y `,(0,E.jsx)(`b`,{children:`AAA`})]}),(0,E.jsxs)(`span`,{className:`orbit-label label-three`,children:[`RUNTIME `,(0,E.jsx)(`b`,{children:`FAST`})]})]})]})}function Ds(){let{status:e,user:t,signOut:n}=Gi();return(0,E.jsxs)(Qe,{className:`stack-xs session-card`,children:[(0,E.jsxs)($e,{children:[(0,E.jsx)(et,{children:`Session`}),(0,E.jsx)(tt,{children:`OIDC authorization-code flow against users.k6n.net.`})]}),(0,E.jsxs)(nt,{className:`stack-xs`,children:[e===`loading`&&(0,E.jsxs)(`div`,{className:`session-identity`,children:[(0,E.jsx)(`span`,{className:`session-avatar skeleton-pulse`,"aria-hidden":`true`}),(0,E.jsxs)(`span`,{className:`session-lines`,children:[(0,E.jsx)(`span`,{className:`skeleton-pulse`,"aria-hidden":`true`}),(0,E.jsx)(`span`,{className:`skeleton-pulse`,"aria-hidden":`true`})]})]}),e===`anonymous`&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(`p`,{className:`session-note`,children:`Not signed in — the API answers 401 until you are.`}),(0,E.jsx)(M,{variant:`primary`,onClick:()=>Wi(`/`),children:`Sign in`})]}),e===`authenticated`&&t&&(0,E.jsxs)(E.Fragment,{children:[(0,E.jsxs)(`div`,{className:`session-identity`,children:[(0,E.jsx)(fi,{name:t.name||t.email,size:`md`,status:`online`}),(0,E.jsxs)(`div`,{className:`session-lines`,children:[(0,E.jsx)(`b`,{children:t.name||t.email}),t.name&&t.email&&t.email!==t.name&&(0,E.jsx)(`span`,{children:t.email}),(0,E.jsxs)(`small`,{children:[`sub: `,t.sub]})]})]}),t.roles.length>0&&(0,E.jsx)(`div`,{className:`session-roles`,children:t.roles.map(e=>(0,E.jsx)(O,{variant:`outline`,children:e},e))}),(0,E.jsx)(M,{variant:`secondary`,onClick:()=>void n(),children:`Sign out`})]})]})]})}function Os(){return(0,E.jsxs)(E.Fragment,{children:[(0,E.jsx)(Es,{}),(0,E.jsxs)(`div`,{className:`overview-grid`,children:[(0,E.jsx)(Ds,{}),cs.map(e=>(0,E.jsxs)(Qe,{className:`stack-xs`,children:[(0,E.jsxs)($e,{children:[(0,E.jsx)(et,{children:e}),(0,E.jsx)(tt,{children:ls[e]})]}),(0,E.jsx)(nt,{children:(0,E.jsx)(`ul`,{className:`overview-links`,children:fs(e).map(e=>(0,E.jsx)(`li`,{children:(0,E.jsxs)(Ne,{href:e.path,children:[e.label,` `,(0,E.jsx)(j,{name:`arrow`,size:13})]})},e.path))})})]},e))]})]})}function ks(){return(0,E.jsx)(`div`,{className:`not-found`,children:(0,E.jsxs)(vr,{children:[(0,E.jsx)(br,{children:`Page not found`}),(0,E.jsx)(xr,{children:`That route does not exist in this design system. Pick a page from the list instead.`}),(0,E.jsx)(`ul`,{className:`overview-links`,children:B.map(e=>(0,E.jsx)(`li`,{children:(0,E.jsx)(Ne,{href:e.path,children:e.label})},e.path))})]})})}function As({route:e}){let t=e.page;return(0,E.jsx)(xs,{index:`${e.index} / ${e.kicker}`,title:e.title,description:e.description,meta:e.meta,children:(0,E.jsx)(t,{})})}function js(){let{searchOpen:e,closeSearch:t,sidebarCollapsed:n,toggleSidebar:r}=Re(),[i,a]=C(),o=w(),[s,c]=(0,_.useState)(!1),l=ds(i),u=l?.label??(i===`/`?`Overview`:`Not found`),d=hs(i,o),f=ps.find(e=>e.label===l?.group)?.items??[];return(0,_.useEffect)(()=>{window.scrollTo({top:0})},[i]),(0,E.jsxs)(`div`,{className:`app-shell`,children:[(0,E.jsx)(ys,{onMenuToggle:()=>c(!s)}),(0,E.jsx)(Ts,{isOpen:e,onClose:t,onSelect:e=>{a(e.patternId?`${e.path}?pattern=${e.patternId}`:e.path)}}),(0,E.jsxs)(`div`,{className:`body-layout ${s?`menu-open`:``} ${n?`sidebar-collapsed`:``}`,children:[(0,E.jsx)(bs,{groups:ps,activeHref:d,onNavigate:()=>c(!1),collapsed:n,onToggleCollapse:r}),(0,E.jsxs)(`main`,{className:`main-content`,children:[(0,E.jsxs)(`div`,{className:`breadcrumbs`,children:[(0,E.jsx)(`span`,{children:l?l.group:`Northstar`}),(0,E.jsx)(`span`,{children:`/`}),(0,E.jsx)(`strong`,{children:u})]}),i===`/`?(0,E.jsx)(Os,{}):(0,E.jsxs)(`div`,{className:`content-grid`,children:[(0,E.jsx)(`div`,{className:`content-main`,children:(0,E.jsxs)(Fe,{children:[B.map(e=>(0,E.jsx)(T,{path:e.path,children:(0,E.jsx)(As,{route:e})},e.path)),(0,E.jsx)(T,{children:(0,E.jsx)(ks,{})})]})}),l&&(0,E.jsx)(Ss,{title:l.group,links:f,activeHref:d})]}),(0,E.jsxs)(`footer`,{children:[(0,E.jsx)(`span`,{children:`northstar design system`}),(0,E.jsx)(`span`,{className:`mono`,children:`made for the long haul · 2025`})]})]})]})]})}var Ms=class extends _.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){}render(){let{error:e}=this.state;return e?(0,E.jsxs)(`div`,{style:{padding:`var(--space-6)`,margin:`var(--space-6) auto`,maxWidth:`42rem`,fontFamily:`var(--font-mono)`,fontSize:`var(--text-sm)`,color:`var(--foreground)`,background:`var(--card)`,border:`1px solid var(--destructive)`,borderRadius:`var(--radius-lg)`,whiteSpace:`pre-wrap`},children:[(0,E.jsx)(`strong`,{children:`Something broke while rendering.`}),` + +`,e.message]}):this.props.children}};(0,v.createRoot)(document.getElementById(`root`)).render((0,E.jsx)(_.StrictMode,{children:(0,E.jsx)(Ms,{children:(0,E.jsx)(Xe,{children:(0,E.jsx)(js,{})})})})); \ No newline at end of file diff --git a/frontend/dist/assets/index-DGNRMRfX.css b/frontend/dist/assets/index-DGNRMRfX.css deleted file mode 100644 index 164911f..0000000 --- a/frontend/dist/assets/index-DGNRMRfX.css +++ /dev/null @@ -1 +0,0 @@ -@import "https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Manrope:wght@400;500;600;700;800&display=swap";:root{--root-font-size:112%;--text-3xs:.5625rem;--text-2xs:.625rem;--text-xs:.6875rem;--text-sm:.75rem;--text-md:.875rem;--text-base:1rem;--text-lg:1.3125rem;--text-xl:1.5625rem;--text-2xl:1.75rem;--text-hero:clamp(2.625rem, 5vw, 4.375rem);--font-sans:"Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;--font-mono:"DM Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;--space-1:.25rem;--space-2:.5rem;--space-3:.75rem;--space-4:1rem;--space-5:1.25rem;--space-6:1.5rem;--space-7:2rem;--space-8:2.5rem;--space-9:3rem;--space-10:4rem;--space-11:5rem;--radius-sm:5px;--radius-md:6px;--radius-lg:9px;--radius-xl:12px;--radius-2xl:14px;--radius-pill:9999px;--focus-ring:2px solid var(--ring);--focus-offset:2px}:root,:root[data-theme=light],.light{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--background:lab(100% 0 0);--foreground:lab(2.75381% 0 0);--card:lab(97.68% -.0000298023 .0000119209);--card-foreground:lab(2.75381% 0 0);--popover:lab(100% 0 0);--popover-foreground:lab(2.75381% 0 0);--primary:lab(7.78201% -.0000149012 0);--primary-foreground:lab(98.26% 0 0);--secondary:lab(94.2% 0 0);--secondary-foreground:lab(7.78201% -.0000149012 0);--muted:lab(94.2% 0 0);--muted-foreground:lab(39.68% 0 0);--accent:lab(94.2% 0 0);--accent-foreground:lab(7.78201% -.0000149012 0);--destructive:lab(48.4493% 77.4328 61.5452);--destructive-foreground:lab(98.26% 0 0);--border:lab(86.08% -.0000298023 0);--input:lab(86.08% -.0000298023 0);--ring:lab(42% 0 0);--chart-1:lab(57.1026% 64.2584 89.8886);--chart-2:lab(55.0223% -41.0774 -3.90277);--chart-3:lab(30.372% -13.1853 -18.7887);--chart-4:lab(80.1641% 16.6016 99.2089);--chart-5:lab(72.7183% 31.8672 97.9407);--sidebar:lab(96.52% -.0000298023 .0000119209);--sidebar-foreground:lab(2.75381% 0 0);--sidebar-primary:lab(7.78201% -.0000149012 0);--sidebar-primary-foreground:lab(98.26% 0 0);--sidebar-accent:lab(94.2% 0 0);--sidebar-accent-foreground:lab(7.78201% -.0000149012 0);--sidebar-border:lab(86.08% -.0000298023 0);--sidebar-ring:lab(42% 0 0);--dot-color:lab(7.78201% -.0000149012 0/.05)}:root:not([data-theme=light]),:root[data-theme=dark],.dark{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--background:lab(0% 0 0);--foreground:lab(94.78% 0 0);--card:lab(.903296% 0 0);--card-foreground:lab(94.78% 0 0);--popover:lab(.903296% 0 0);--popover-foreground:lab(94.78% 0 0);--primary:lab(89.9321% -47.9163 -15.7303);--primary-foreground:lab(0% 0 0);--secondary:lab(2.47865% 0 0);--secondary-foreground:lab(94.78% 0 0);--muted:lab(2.47865% 0 0);--muted-foreground:lab(60.56% 0 0);--accent:lab(1.98454% 0 0);--accent-foreground:lab(89.9321% -47.9163 -15.7303);--destructive:lab(54.5811% 71.684 50.9279);--destructive-foreground:lab(100% 0 0);--border:lab(4.8411% 0 0);--input:lab(1.98454% 0 0);--ring:lab(89.9321% -47.9163 -15.7303);--chart-1:lab(89.9321% -47.9163 -15.7303);--chart-2:lab(66.9756% -58.27 19.5419);--chart-3:lab(72.7183% 31.8672 97.9407);--chart-4:lab(52.0183% 66.11 -78.2316);--chart-5:lab(56.101% 79.4328 31.4532);--sidebar:lab(.498049% 0 0);--sidebar-foreground:lab(94.78% 0 0);--sidebar-primary:lab(89.9321% -47.9163 -15.7303);--sidebar-primary-foreground:lab(0% 0 0);--sidebar-accent:lab(1.98454% 0 0);--sidebar-accent-foreground:lab(89.9321% -47.9163 -15.7303);--sidebar-border:lab(4.8411% 0 0);--sidebar-ring:lab(89.9321% -47.9163 -15.7303);--dot-color:lab(89.9321% -47.9163 -15.7303/.045)}html{font-size:var(--root-font-size)}.dot-canvas{background-image:radial-gradient(var(--dot-color) 1px, transparent 1px);background-size:24px 24px}.dot-canvas-dense{background-image:radial-gradient(var(--dot-color) 1px, transparent 1px);background-size:16px 16px}.flex-center{justify-content:center;align-items:center;display:flex}.flex-between{justify-content:space-between;align-items:center;display:flex}.flex-col{flex-direction:column;display:flex}.stack-xs{gap:var(--space-1);flex-direction:column;display:flex}.stack-sm{gap:var(--space-2);flex-direction:column;display:flex}.stack-md{gap:var(--space-4);flex-direction:column;display:flex}.stack-lg{gap:var(--space-6);flex-direction:column;display:flex}.row-xs{align-items:center;gap:var(--space-1);display:flex}.row-sm{align-items:center;gap:var(--space-2);display:flex}.row-md{align-items:center;gap:var(--space-4);display:flex}.grid-2{gap:var(--space-4);grid-template-columns:repeat(2,minmax(0,1fr));display:grid}.grid-3{gap:var(--space-4);grid-template-columns:repeat(3,minmax(0,1fr));display:grid}.grid-4{gap:var(--space-4);grid-template-columns:repeat(4,minmax(0,1fr));display:grid}@media (width<=760px){.grid-2,.grid-3,.grid-4{grid-template-columns:1fr}}.surface-card{background:var(--card);color:var(--card-foreground);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-5);box-shadow:0 4px 20px #0000001f}.surface-sidebar{background:var(--sidebar);color:var(--sidebar-foreground);border-right:1px solid var(--sidebar-border)}.surface-popover{background:var(--popover);color:var(--popover-foreground);border:1px solid var(--border);border-radius:var(--radius-md);box-shadow:0 10px 30px #00000040}.surface-muted{background:var(--secondary);color:var(--secondary-foreground);border:1px solid var(--border);border-radius:var(--radius-md)}.badge{align-items:center;gap:var(--space-1);padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);font-family:var(--font-mono);font-size:var(--text-3xs);white-space:nowrap;border:1px solid #0000;font-weight:500;line-height:1;display:inline-flex}.badge-primary{background:color-mix(in srgb, var(--primary) 14%, transparent);color:var(--primary);border-color:color-mix(in srgb, var(--primary) 28%, transparent)}.badge-secondary{background:var(--secondary);color:var(--secondary-foreground);border-color:var(--border)}.badge-destructive{background:color-mix(in srgb, var(--destructive) 14%, transparent);color:var(--destructive);border-color:color-mix(in srgb, var(--destructive) 28%, transparent)}.badge-positive{background:color-mix(in srgb, var(--chart-2) 14%, transparent);color:var(--chart-2);border-color:color-mix(in srgb, var(--chart-2) 28%, transparent)}.badge-outline{color:var(--muted-foreground);border-color:var(--border);background:0 0}.hover-lift{transition:transform .2s,border-color .2s,box-shadow .2s}.hover-lift:hover{border-color:var(--ring);box-shadow:0 8px 24px color-mix(in srgb, var(--primary) 10%, #0003);transform:translateY(-2px)}.kbd-tag{font-family:var(--font-mono);font-size:var(--text-3xs);color:var(--muted-foreground);background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2)}.skeleton-pulse{background:color-mix(in srgb, var(--foreground) 7%, var(--card));border-radius:var(--radius-md);animation:1.8s ease-in-out infinite skeleton-shimmer}@keyframes skeleton-shimmer{0%,to{opacity:.45}50%{opacity:.85}}.glow-primary{box-shadow:0 0 24px color-mix(in srgb, var(--primary) 25%, transparent)}.dialog-backdrop{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:50;padding:var(--space-4);background:#000000b8;place-items:center;animation:.2s ease-out dialog-fade-in;display:grid;position:fixed;inset:0}.dialog-panel{background:var(--card);color:var(--card-foreground);border:1px solid var(--border);border-radius:var(--radius-xl);width:100%;max-width:520px;padding:var(--space-6);box-shadow:0 24px 48px #0006, 0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent);animation:.2s cubic-bezier(.16,1,.3,1) dialog-scale-in;position:relative}@keyframes dialog-fade-in{0%{opacity:0}to{opacity:1}}@keyframes dialog-scale-in{0%{opacity:0;transform:scale(.96)translateY(8px)}to{opacity:1;transform:scale(1)translateY(0)}}.dialog-close-btn{top:var(--space-4);right:var(--space-4);color:var(--muted-foreground);border-radius:var(--radius-md);padding:var(--space-1);cursor:pointer;background:0 0;border:0;place-items:center;transition:all .15s;display:grid;position:absolute}.dialog-close-btn:hover{background:var(--secondary);color:var(--foreground)}.alert{gap:var(--space-3);padding:var(--space-4);border-radius:var(--radius-lg);border:1px solid var(--border);background:var(--card);color:var(--foreground);line-height:1.5;display:flex;position:relative}.alert-info{background:color-mix(in srgb, var(--primary) 6%, var(--card));border-color:color-mix(in srgb, var(--primary) 24%, var(--border))}.alert-info .alert-icon{color:var(--primary)}.alert-positive{background:color-mix(in srgb, var(--chart-2) 6%, var(--card));border-color:color-mix(in srgb, var(--chart-2) 24%, var(--border))}.alert-positive .alert-icon{color:var(--chart-2)}.alert-warning{background:color-mix(in srgb, var(--chart-3) 6%, var(--card));border-color:color-mix(in srgb, var(--chart-3) 24%, var(--border))}.alert-warning .alert-icon{color:var(--chart-3)}.alert-destructive{background:color-mix(in srgb, var(--destructive) 8%, var(--card));border-color:color-mix(in srgb, var(--destructive) 28%, var(--border))}.alert-destructive .alert-icon{color:var(--destructive)}.ui-tabs-list{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-lg);align-items:center;gap:3px;padding:4px;display:inline-flex}.ui-tabs-trigger{color:var(--muted-foreground);font-size:var(--text-sm);font-family:var(--font-sans);padding:var(--space-2) var(--space-4);border-radius:var(--radius-md);cursor:pointer;align-items:center;gap:var(--space-2);white-space:nowrap;background:0 0;border:1px solid #0000;font-weight:500;line-height:1.4;transition:all .15s;display:inline-flex}.ui-tabs-trigger:hover{color:var(--foreground)}.ui-tabs-trigger.active{background:var(--card);color:var(--foreground);border-color:color-mix(in srgb, var(--border) 60%, transparent);font-weight:600;box-shadow:0 1px 3px #00000029}.ui-tabs-trigger svg{flex-shrink:0;display:block}.ui-tabs-content{margin-top:var(--space-4)}.empty-state{text-align:center;padding:var(--space-10) var(--space-6);border:1px dashed var(--border);border-radius:var(--radius-xl);background:color-mix(in srgb, var(--secondary) 50%, var(--card));flex-direction:column;justify-content:center;align-items:center;display:flex}.empty-state-icon{border-radius:var(--radius-lg);background:color-mix(in srgb, var(--primary) 12%, var(--secondary));width:48px;height:48px;color:var(--primary);margin-bottom:var(--space-4);place-items:center;display:grid}.progress-container{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-pill);width:100%;height:8px;position:relative;overflow:hidden}.progress-fill{background:var(--primary);border-radius:var(--radius-pill);height:100%;box-shadow:0 0 10px color-mix(in srgb, var(--primary) 60%, transparent);transition:width .3s cubic-bezier(.4,0,.2,1)}.progress-indeterminate{width:40%;animation:1.5s ease-in-out infinite progress-slide;position:absolute}@keyframes progress-slide{0%{transform:translate(-100%)}to{transform:translate(350%)}}.switch-root{border-radius:var(--radius-pill);background:var(--border);border:1px solid var(--border);cursor:pointer;align-items:center;width:40px;height:22px;padding:2px;transition:background-color .2s,border-color .2s;display:inline-flex}.switch-root.checked{background:var(--primary);border-color:var(--primary)}.switch-thumb{background:var(--muted-foreground);border-radius:50%;width:16px;height:16px;transition:transform .2s cubic-bezier(.2,.8,.2,1),background-color .2s}.switch-root.checked .switch-thumb{background:var(--primary-foreground);transform:translate(18px)}.ui-table-container{border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);width:100%;overflow-x:auto}.ui-table{border-collapse:collapse;text-align:left;width:100%;font-size:var(--text-sm);color:var(--foreground)}.ui-table th{padding:var(--space-3) var(--space-4);font:var(--text-3xs) var(--font-mono);letter-spacing:.08em;text-transform:uppercase;color:var(--muted-foreground);background:var(--secondary);border-bottom:1px solid var(--border)}.ui-table td{padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border)}.ui-table tr:last-child td{border-bottom:0}.ui-table tr:hover td{background:color-mix(in srgb, var(--foreground) 3%, var(--card))}.sheet-backdrop{-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);z-index:50;background:#000000b3;animation:.2s ease-out dialog-fade-in;position:fixed;inset:0}.sheet-panel{background:var(--card);width:100%;max-width:420px;color:var(--card-foreground);border-left:1px solid var(--border);z-index:51;padding:var(--space-6);flex-direction:column;animation:.25s cubic-bezier(.16,1,.3,1) sheet-slide-in;display:flex;position:fixed;top:0;bottom:0;right:0;box-shadow:-10px 0 35px #00000059}@keyframes sheet-slide-in{0%{transform:translate(100%)}to{transform:translate(0)}}.tooltip-wrapper{display:inline-flex;position:relative}.tooltip-box{background:var(--popover);color:var(--popover-foreground);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2);font:var(--text-3xs) var(--font-mono);white-space:nowrap;pointer-events:none;z-index:40;opacity:0;transition:opacity .15s,transform .15s;position:absolute;bottom:100%;left:50%;transform:translate(-50%)translateY(-6px);box-shadow:0 4px 14px #0003}.tooltip-box[data-open=true]{opacity:1;transform:translate(-50%)translateY(-8px)}.skeleton{background:color-mix(in srgb, var(--foreground) 7%, var(--card));animation:1.8s ease-in-out infinite skeleton-shimmer;display:block}.skeleton-text{border-radius:var(--radius-sm);width:100%;height:14px}.skeleton-circle{border-radius:50%;flex-shrink:0}.skeleton-rect{border-radius:var(--radius-lg)}:where(.ui-tabs-trigger,.switch-root,.dialog-close-btn):focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-offset)}:root{font-family:var(--font-sans);color:var(--foreground);background:var(--background);font-synthesis:none;text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased}*{box-sizing:border-box}html{scroll-behavior:smooth}body{min-width:320px;margin:0}button,input{font:inherit}button{cursor:pointer}.app-shell{background-color:var(--background);isolation:isolate;min-height:100vh;position:relative}.app-shell:before{content:"";z-index:-1;pointer-events:none;background-image:radial-gradient(ellipse 90% 60% at 70% -5%, color-mix(in srgb, var(--primary) 3.5%, transparent) 0%, transparent 100%);position:fixed;inset:0}.topbar{border-bottom:1px solid var(--border);background:color-mix(in srgb, var(--background) 85%, transparent);-webkit-backdrop-filter:blur(18px);backdrop-filter:blur(18px);height:68px;padding:0 var(--space-7);align-items:center;gap:var(--space-7);z-index:10;display:flex;position:sticky;top:0}.brand,.top-links,.top-search,.hero-actions,.showcase-foot,.status-line,.code-head,.section-heading,.release-icon,.input-with-action,.toggle-field{align-items:center;display:flex}.brand{white-space:nowrap;gap:10px}.brand-mark{border:1px solid var(--primary);border-radius:var(--radius-md);place-items:center;width:26px;height:26px;display:grid;transform:rotate(45deg)}.brand-mark span{background:var(--primary);border-radius:3px;width:9px;height:9px}.brand-mark.large{border-radius:var(--radius-xl);width:42px;height:42px}.brand-mark.large span{width:14px;height:14px}.brand b{letter-spacing:-.04em;font-weight:800;font-size:var(--text-base);color:var(--foreground)}.version,.api-pill,.nav-count{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);border:1px solid var(--border);padding:var(--space-1) 7px;border-radius:var(--radius-sm)}.top-search{gap:var(--space-3);max-width:380px;color:var(--muted-foreground);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-2) var(--space-3);cursor:pointer;text-align:left;font-family:inherit;font-size:var(--text-sm);flex:1;margin-left:auto;margin-right:auto;transition:border-color .2s,box-shadow .2s,background .2s}.top-search:hover{border-color:var(--ring);background:color-mix(in srgb, var(--accent) 35%, var(--card))}.top-search:focus-visible{border-color:var(--ring);box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 15%, transparent);outline:0}.top-search-placeholder{color:var(--muted-foreground);-webkit-user-select:none;user-select:none;font-size:var(--text-sm);flex:1}.top-search kbd{font-family:var(--font-mono);font-size:var(--text-3xs);color:var(--muted-foreground);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-1) var(--space-2);background:var(--secondary)}.top-links{gap:var(--space-5);font-size:var(--text-sm);color:var(--muted-foreground)}.top-view-mode{gap:2px;padding:2px}.top-view-mode button{padding:var(--space-1) var(--space-3);font-size:var(--text-2xs);letter-spacing:.04em;text-transform:uppercase}.top-links a{color:var(--muted-foreground);text-decoration:none}.top-links a:hover,.text-button:hover{color:var(--foreground)}.icon-button,.avatar{color:var(--muted-foreground);border-radius:var(--radius-md);background:0 0;border:0;place-items:center;padding:7px;display:grid}.icon-button:hover{background:var(--secondary);color:var(--foreground)}.avatar{background:color-mix(in srgb, var(--primary) 18%, var(--secondary));width:28px;height:28px;color:var(--primary);font-size:var(--text-3xs);cursor:pointer;font-weight:700}.top-signin{border:1px solid var(--border);background:var(--secondary);color:var(--foreground);border-radius:var(--radius-md);padding:var(--space-1) var(--space-3);font-family:inherit;font-size:var(--text-2xs);letter-spacing:.04em;cursor:pointer;font-weight:600;transition:all .15s}.top-signin:hover{border-color:color-mix(in srgb, var(--primary) 45%, transparent);color:var(--primary)}.top-signin:focus-visible{outline:2px solid var(--primary);outline-offset:2px}.user-menu{place-items:center;display:grid;position:relative}.user-menu-popover{top:calc(100% + var(--space-2));background:var(--popover);min-width:230px;color:var(--popover-foreground);border:1px solid var(--border);border-radius:var(--radius-lg);box-shadow:0 16px 40px #00000073, 0 0 0 1px color-mix(in srgb, var(--primary) 12%, transparent);padding:var(--space-2);z-index:60;animation:.15s cubic-bezier(.16,1,.3,1) user-menu-in;position:absolute;right:0}@keyframes user-menu-in{0%{opacity:0;transform:scale(.96)translateY(6px)}to{opacity:1;transform:scale(1)translateY(0)}}.user-menu-identity{padding:var(--space-2) var(--space-3);font-size:var(--text-xs);gap:2px;display:grid}.user-menu-identity span{color:var(--muted-foreground);font-size:var(--text-2xs)}.user-menu-signout{align-items:center;gap:var(--space-2);width:100%;color:var(--muted-foreground);font-family:inherit;font-size:var(--text-xs);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);cursor:pointer;background:0 0;border:0;transition:all .15s;display:flex}.user-menu-signout:hover{background:var(--secondary);color:var(--destructive)}.session-card{border-color:color-mix(in srgb, var(--primary) 30%, transparent)}.session-note{color:var(--muted-foreground);font-size:var(--text-xs);margin:0}.session-identity{align-items:center;gap:var(--space-3);display:flex}.session-lines{gap:2px;min-width:0;display:grid}.session-lines b{font-size:var(--text-sm)}.session-lines span,.session-lines small{color:var(--muted-foreground);font-size:var(--text-2xs);text-overflow:ellipsis;overflow:hidden}.session-lines .skeleton-pulse{height:var(--text-xs);display:block}.session-avatar.skeleton-pulse{width:var(--space-7);height:var(--space-7);border-radius:var(--radius-pill)}.session-roles{gap:var(--space-2);flex-wrap:wrap;display:flex}.mobile-menu{display:none}.body-layout{grid-template-columns:240px minmax(0,1fr);display:grid}.body-layout.sidebar-collapsed{grid-template-columns:56px minmax(0,1fr)}.body-layout.sidebar-collapsed .sidebar{padding:var(--space-4) 0}.body-layout.sidebar-collapsed .sidebar-heading{border-bottom:0;justify-content:center;padding:0}.body-layout.sidebar-collapsed .sidebar-intro,.body-layout.sidebar-collapsed .sidebar nav,.body-layout.sidebar-collapsed .sidebar-bottom{display:none}.sidebar{border-right:1px solid var(--sidebar-border);min-height:calc(100vh - 68px);padding:var(--space-5) 0 var(--space-4);background:var(--sidebar);flex-direction:column;height:calc(100vh - 68px);display:flex;position:sticky;top:68px}.sidebar-heading{padding:0 var(--space-5) var(--space-5);border-bottom:1px solid var(--sidebar-border);justify-content:space-between;align-items:center;display:flex}.sidebar-library{align-items:center;gap:var(--space-2);color:var(--sidebar-foreground);font:500 var(--text-xs) var(--font-mono);letter-spacing:.05em;text-transform:uppercase;display:flex}.sidebar-library svg{color:var(--sidebar-primary)}.sidebar-collapse{color:var(--muted-foreground);font:var(--text-xs) var(--font-mono);background:0 0;border:0;padding:4px 0}.sidebar-collapse:hover{color:var(--sidebar-foreground)}.sidebar-intro{padding:var(--space-5) var(--space-5) var(--space-5);border-bottom:1px solid var(--sidebar-border);margin:0}.sidebar-intro p{font-size:var(--text-3xs);color:var(--muted-foreground);margin:var(--space-2) 0 0;max-width:180px;line-height:1.6}.eyebrow,.section-index,.nav-label{font:var(--text-3xs) var(--font-mono);letter-spacing:.12em;text-transform:uppercase;color:var(--muted-foreground)}.accent{color:var(--primary)}.sidebar nav{padding-top:var(--space-5)}.nav-group{margin-bottom:var(--space-5)}.nav-label{padding:0 var(--space-5);margin-bottom:var(--space-2);color:var(--muted-foreground);font-size:var(--text-3xs);display:block}.nav-item{width:100%;color:var(--sidebar-foreground);text-align:left;padding:9px var(--space-5);font-size:var(--text-sm);letter-spacing:-.01em;background:0 0;border:0;border-radius:0;align-items:center;gap:11px;text-decoration:none;transition:all .2s;display:flex;position:relative}.nav-item:hover{color:var(--sidebar-accent-foreground);background:var(--sidebar-accent)}.nav-item.active{color:var(--sidebar-foreground);background:linear-gradient(90deg, color-mix(in srgb, var(--sidebar-primary) 18%, transparent), color-mix(in srgb, var(--sidebar-primary) 5%, transparent));box-shadow:inset 2px 0 var(--sidebar-primary)}.nav-glyph{width:13px;color:var(--muted-foreground);font:var(--text-md) var(--font-mono);text-align:center;line-height:1}.nav-item.active .nav-glyph{color:var(--sidebar-primary)}.nav-count{color:var(--sidebar-primary);font-size:var(--text-3xs);background:0 0;border:0;margin-left:auto;padding:0}.sidebar-bottom{border-top:1px solid var(--sidebar-border);padding:var(--space-4) var(--space-5) 0;margin-top:auto}.status-line{gap:var(--space-2);color:var(--muted-foreground);font-size:var(--text-3xs);margin-bottom:7px}.status-dot{background:var(--chart-2);width:6px;height:6px;box-shadow:0 0 10px var(--chart-2);border-radius:50%}.mono{font-family:var(--font-mono);font-size:var(--text-3xs)}.muted{color:var(--muted-foreground)}.main-content{min-width:0}.breadcrumbs{max-width:1180px;padding:var(--space-6) var(--space-9) 0;font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);gap:10px;margin:0 auto;display:flex}.breadcrumbs strong{color:var(--primary);font-weight:500}.hero-section{max-width:1180px;padding:var(--space-10) var(--space-9) var(--space-11);justify-content:space-between;gap:var(--space-8);min-height:386px;margin:0 auto;display:flex}.hero-copy{max-width:590px}.hero-copy h1{font-size:var(--text-hero);letter-spacing:-.07em;margin:var(--space-4) 0 var(--space-5);font-weight:800;line-height:1.02}.hero-copy p{color:var(--muted-foreground);font-size:var(--text-base);max-width:510px;line-height:1.7}.hero-actions{gap:var(--space-3);margin-top:var(--space-7)}.button{border-radius:var(--radius-md);padding:var(--space-2) var(--space-4);color:var(--foreground);font-size:var(--text-xs);align-items:center;gap:var(--space-2);white-space:nowrap;cursor:pointer;-webkit-user-select:none;user-select:none;border:1px solid #0000;outline:none;font-weight:600;text-decoration:none;transition:background-color .15s,border-color .15s,box-shadow .15s,transform 80ms,filter .12s;display:inline-flex;position:relative;overflow:hidden}.button:focus-visible{outline:2px solid var(--ring);outline-offset:2px}.button:active{transform:translateY(1px)}.button.primary{background:var(--primary);color:var(--primary-foreground);border-color:#0000;font-weight:600;box-shadow:0 1px 2px #0003}.button.primary:hover,.button.primary.hover-state{filter:brightness(1.06);box-shadow:0 1px 3px #00000047}.button.primary:active{filter:brightness(.93);transform:translateY(1px);box-shadow:inset 0 1px 2px #0003}.button.primary:focus-visible{outline:2px solid var(--ring);outline-offset:2px;box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 35%, transparent)}.button.secondary{background:color-mix(in srgb, var(--foreground) 8%, var(--card));border:1px solid color-mix(in srgb, var(--foreground) 16%, var(--border));color:var(--foreground)}.button.secondary:hover,.button.secondary.hover-state{background:color-mix(in srgb, var(--foreground) 14%, var(--card));border-color:var(--ring)}.button.secondary:active{background:color-mix(in srgb, var(--foreground) 18%, var(--card));transform:translateY(1px)}.button.secondary:focus-visible{outline:2px solid var(--ring);outline-offset:2px;box-shadow:0 0 0 3px color-mix(in srgb, var(--foreground) 15%, transparent)}.button.danger{background:var(--destructive);color:var(--destructive-foreground);border:1px solid #0000;box-shadow:0 1px 2px #0003}.button.danger:hover,.button.danger.hover-state{filter:brightness(1.08);box-shadow:0 1px 3px #00000047}.button.danger:active{filter:brightness(.92);transform:translateY(1px);box-shadow:inset 0 1px 2px #0003}.button.danger:focus-visible{outline:2px solid var(--destructive);outline-offset:2px;box-shadow:0 0 0 3px color-mix(in srgb, var(--destructive) 35%, transparent)}.button.ghost{color:var(--muted-foreground);background:0 0}.button.ghost:hover,.button.ghost.hover-state{color:var(--foreground);background:var(--accent)}.button.ghost:active{background:color-mix(in srgb, var(--accent) 80%, var(--foreground));transform:translateY(1px)}.button.ghost:focus-visible{outline:2px solid var(--ring);outline-offset:2px}.hero-orbit{width:280px;height:225px;margin:var(--space-2) var(--space-8) 0 0;flex:0 0 280px;position:relative}.orbit{border:1px solid color-mix(in srgb, var(--primary) 14%, var(--border));border-radius:50%;position:absolute;transform:rotate(-22deg)}.orbit-one{width:270px;height:112px;top:45px;left:0}.orbit-two{border-color:color-mix(in srgb, var(--primary) 8%, var(--border));width:215px;height:215px;top:2px;left:28px;transform:rotate(58deg)}.orbit-core{border:1px solid color-mix(in srgb, var(--primary) 22%, var(--border));background:color-mix(in srgb, var(--card) 90%, transparent);border-radius:var(--radius-xl);justify-content:center;align-items:center;gap:var(--space-2);width:105px;height:83px;color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);box-shadow:0 0 45px color-mix(in srgb, var(--primary) 14%, transparent);line-height:1.4;display:flex;position:absolute;top:71px;right:88px}.orbit-core b{color:var(--chart-2);font-weight:500}.orbit-label{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);letter-spacing:.08em;position:absolute}.orbit-label b{color:var(--primary);margin-top:4px;font-weight:600;display:block}.label-one{top:13px;right:5px}.label-two{bottom:4px;left:7px}.label-three{bottom:31px;right:0}.content-grid{gap:var(--space-10);max-width:1180px;padding:0 var(--space-9);grid-template-columns:minmax(0,1fr) 220px;margin:0 auto;display:grid}.content-main{min-width:0}.section-block{padding:var(--space-9) 0;border-top:1px solid var(--border);scroll-margin-top:80px}.section-heading{justify-content:space-between;align-items:flex-start;gap:var(--space-5)}.section-heading h2{font-size:var(--text-2xl);letter-spacing:-.05em;color:var(--foreground);margin:10px 0 7px}.section-heading p{color:var(--muted-foreground);font-size:var(--text-sm);margin:0}.api-pill{white-space:nowrap;margin-top:var(--space-1)}.text-button{gap:var(--space-2);color:var(--primary);font-size:var(--text-xs);background:0 0;border:0;align-items:center;margin-top:10px;display:inline-flex}.tabs{gap:var(--space-6);border-bottom:1px solid var(--border);margin-top:var(--space-7);display:flex}.tab{color:var(--muted-foreground);font-family:var(--font-sans);font-size:var(--text-sm);padding:var(--space-2) 0 var(--space-3);align-items:center;gap:var(--space-2);cursor:pointer;background:0 0;border:0;border-bottom:2px solid #0000;font-weight:500;line-height:1.4;transition:color .15s,border-color .15s;display:inline-flex}.tab:hover{color:var(--foreground)}.tab.active{color:var(--foreground);border-color:var(--primary);font-weight:600}.tab svg{flex-shrink:0;display:block}.showcase{margin-top:var(--space-5);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}.showcase-head,.showcase-foot{padding:var(--space-4) var(--space-4);border-bottom:1px solid var(--border);justify-content:space-between}.button-matrix{padding:7px var(--space-4);overflow-x:auto}.button-row{align-items:center;gap:var(--space-4);border-bottom:1px solid var(--border);grid-template-columns:90px 1fr 1fr 42px 1fr;min-width:560px;min-height:58px;display:grid}.button-row:last-child{border:0}.row-label{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground)}.icon-only{justify-content:center;padding:var(--space-2)!important}.loading{color:var(--muted-foreground)!important;background:color-mix(in srgb, var(--foreground) 6%, var(--card))!important;border:1px solid var(--border)!important}.showcase-foot{border-top:1px solid var(--border);border-bottom:0;justify-content:flex-start;gap:7px}.density{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);padding:var(--space-2) var(--space-2);border-radius:var(--radius-sm);background:0 0;border:1px solid #0000}.density.active{background:color-mix(in srgb, var(--primary) 14%, var(--secondary));color:var(--primary)}.foot-check{color:var(--chart-2);font:var(--text-3xs) var(--font-mono);align-items:center;gap:var(--space-1);margin-left:auto;display:flex}.color-grid{gap:var(--space-2);margin-top:var(--space-5);grid-template-columns:repeat(4,1fr);display:grid}.color-card{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-3);grid-template-columns:32px 1fr 16px;align-items:center;gap:9px;display:grid}.swatch{border-radius:var(--radius-md);width:32px;height:32px;box-shadow:inset 0 0 0 1px #ffffff1f}.color-card strong,.color-card span{font-size:var(--text-xs);color:var(--foreground);display:block}.color-card .mono{color:var(--muted-foreground);margin-top:4px}.copy-icon{color:var(--muted-foreground);background:0 0;border:0;padding:0}.copy-icon:hover{color:var(--foreground)}.forms-grid{gap:var(--space-5) var(--space-4);margin-top:var(--space-5);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-5);grid-template-columns:1fr 1fr;display:grid}.field{gap:var(--space-2);font-size:var(--text-xs);color:var(--muted-foreground);flex-direction:column;display:flex}.field em{font:var(--text-3xs) var(--font-mono);color:var(--primary);float:right;text-transform:uppercase;font-style:normal}.field input{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-sm);padding:var(--space-3);color:var(--foreground);font-size:var(--text-sm);outline:0}.field input:focus{border-color:var(--ring);box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent)}.field small,.toggle-field small{font-size:var(--text-3xs);color:var(--muted-foreground)}.input-with-action{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-sm)}.input-with-action input{min-width:0;color:var(--foreground);background:0 0;border:0;flex:1}.input-with-action button{color:var(--muted-foreground);background:0 0;border:0;padding:0 11px}.toggle-field{background:color-mix(in srgb, var(--foreground) 3%, var(--card));border:1px solid var(--border);border-radius:var(--radius-md);padding:var(--space-3) var(--space-3);grid-column:1/-1;justify-content:space-between}.toggle-field b{color:var(--foreground)}.toggle-field b,.toggle-field small{display:block}.toggle-field small{margin-top:4px}.toggle{border-radius:var(--radius-pill);background:var(--border);width:36px;height:20px;padding:var(--space-1);border:0}.toggle span{background:var(--muted-foreground);border-radius:50%;width:14px;height:14px;transition:all .2s;display:block}.toggle.on{background:var(--primary)}.toggle.on span{background:var(--primary-foreground);transform:translate(16px)}.bottom-section{padding-bottom:var(--space-7)}.code-card{background:var(--sidebar);border:1px solid var(--border);border-radius:var(--radius-lg);margin-top:var(--space-5);overflow:hidden}.code-head{background:var(--card);padding:10px var(--space-4);border-bottom:1px solid var(--border);justify-content:space-between}.segmented{background:var(--secondary);border:1px solid var(--border);border-radius:var(--radius-lg);align-items:center;gap:4px;padding:4px;display:inline-flex}.segmented button{color:var(--muted-foreground);font-family:var(--font-sans);font-size:var(--text-xs);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);align-items:center;gap:var(--space-2);cursor:pointer;white-space:nowrap;background:0 0;border:1px solid #0000;font-weight:500;line-height:1.4;transition:all .15s;display:inline-flex}.segmented button:hover{color:var(--foreground)}.segmented button.selected{background:var(--card);color:var(--foreground);border-color:color-mix(in srgb, var(--border) 60%, transparent);font-weight:600;box-shadow:0 1px 3px #00000026}.segmented button.selected svg{color:var(--primary)}.segmented button svg{flex-shrink:0;display:block}.copy-button{border:1px solid var(--border);background:var(--secondary);color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);padding:var(--space-1) var(--space-2);border-radius:var(--radius-md);align-items:center;gap:var(--space-2);cursor:pointer;transition:all .15s;display:inline-flex}.copy-button:hover{color:var(--foreground);border-color:var(--ring)}.code-card pre{padding:var(--space-5);font:var(--text-sm) / 1.7 var(--font-mono);color:var(--foreground);margin:0;overflow:auto}.pink{color:var(--chart-5)}.green{color:var(--chart-2)}.blue{color:var(--chart-4)}.right-rail{padding-top:var(--space-9)}.rail-card{border-top:1px solid var(--border);padding:var(--space-4) 0 var(--space-5)}.rail-link{color:var(--muted-foreground);font-size:var(--text-xs);gap:11px;padding:9px 0;text-decoration:none;display:flex}.rail-link span{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground)}.rail-link.active,.rail-link:hover{color:var(--primary)}.release{background:linear-gradient(145deg, color-mix(in srgb, var(--primary) 6%, var(--card)), var(--card));border:1px solid color-mix(in srgb, var(--primary) 15%, var(--border));border-radius:var(--radius-lg);padding:var(--space-4);margin:10px 0 var(--space-4)}.release-icon{color:var(--primary);background:color-mix(in srgb, var(--primary) 14%, var(--secondary));width:31px;height:31px;margin-bottom:var(--space-4);border-radius:7px;justify-content:center}.release strong{font-size:var(--text-sm);color:var(--foreground)}.release p,.rail-copy{color:var(--muted-foreground);font-size:var(--text-xs);margin:var(--space-2) 0 var(--space-4);line-height:1.7}.full{justify-content:center;width:100%}.release .text-button{margin-top:0}footer{max-width:1180px;padding:var(--space-7) var(--space-9) var(--space-8);border-top:1px solid var(--border);color:var(--muted-foreground);font-size:var(--text-3xs);justify-content:space-between;margin:0 auto;display:flex}@media (width<=1020px){.topbar{padding:0 var(--space-5);gap:var(--space-4)}.top-links a,.top-view-mode{display:none}.body-layout{grid-template-columns:200px minmax(0,1fr)}.hero-section,.content-grid{padding-left:var(--space-7);padding-right:var(--space-7)}.content-grid{gap:var(--space-7);grid-template-columns:minmax(0,1fr) 190px}.hero-orbit{transform-origin:100% 0;margin-right:0;transform:scale(.82)}}@media (width<=760px){.topbar{height:60px}.top-search{order:3;max-width:none;display:none;position:absolute;top:68px;left:18px;right:18px}.top-links{margin-left:auto}.mobile-menu{display:grid}.body-layout{display:block}.sidebar{z-index:9;background:color-mix(in srgb, var(--background) 98%, transparent);border:0;height:auto;display:none;position:fixed;inset:60px 0 0}.menu-open .sidebar{display:flex}.breadcrumbs{padding:var(--space-5) var(--space-5) 0}.hero-section{padding:var(--space-9) var(--space-5) var(--space-10);display:block}.hero-copy h1{font-size:var(--text-hero)}.hero-orbit{display:none}.content-grid{padding:0 var(--space-5);display:block}.right-rail{display:none}.section-block{padding:var(--space-7) 0}.section-heading{display:block}.api-pill{margin-top:var(--space-4);display:inline-block}.button-row{gap:var(--space-2);grid-template-columns:70px 1fr 1fr}.button-row .icon-only,.button-row .loading{display:none}.color-grid{grid-template-columns:1fr 1fr}.forms-grid{grid-template-columns:1fr}.toggle-field{grid-column:auto}footer{padding:var(--space-6) var(--space-5) var(--space-7);display:block}footer .mono{margin-top:var(--space-2);display:block}}@media (width<=450px){.version{display:none}.brand b{font-size:var(--text-md)}.hero-actions{flex-direction:column;align-items:stretch}.hero-actions .button{justify-content:center}.button-row{grid-template-columns:58px 1fr 1fr}.button{padding:var(--space-2);font-size:var(--text-2xs)}.showcase-foot{flex-wrap:wrap}.foot-check{width:100%;margin-left:0;margin-top:var(--space-2)}.color-card{grid-template-columns:28px 1fr}.color-card .swatch{width:28px;height:28px}.color-card .copy-icon{display:none}}.markdown-card,.editor-card{margin-top:var(--space-5);border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);overflow:hidden}.markdown-toolbar,.editor-tabs{padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--border);background:var(--secondary);justify-content:space-between;align-items:center;display:flex}.markdown-body{max-width:700px;padding:var(--space-8) var(--space-9) var(--space-8);color:var(--foreground);font-size:var(--text-md);margin:0 auto;line-height:1.75}.md-kicker{font:var(--text-3xs) var(--font-mono);letter-spacing:.13em;color:var(--primary)}.markdown-body h3{color:var(--foreground);font-size:var(--text-xl);letter-spacing:-.05em;margin:var(--space-3) 0 10px;line-height:1.2}.markdown-body h4{color:var(--foreground);font-size:var(--text-md);margin:var(--space-5) 0 7px}.markdown-body p{margin:0 0 var(--space-4);color:var(--muted-foreground)}.markdown-body code{font:var(--text-xs) var(--font-mono);color:var(--primary);background:color-mix(in srgb, var(--primary) 8%, var(--card));border:1px solid color-mix(in srgb, var(--primary) 22%, var(--border));padding:2px var(--space-1);border-radius:4px}.md-callout{gap:var(--space-3);padding:var(--space-3) var(--space-4);margin:var(--space-5) 0;border:1px solid color-mix(in srgb, var(--primary) 25%, var(--border));border-left:2px solid var(--primary);border-radius:var(--radius-md);background:linear-gradient(100deg, color-mix(in srgb, var(--primary) 6%, var(--card)), var(--card));display:flex}.md-callout p{font-size:var(--text-sm);color:var(--foreground);margin:0;line-height:1.6}.callout-mark{color:var(--primary);font-size:var(--text-base)}.markdown-body ul{margin:0 0 var(--space-5);padding-left:var(--space-5);color:var(--muted-foreground)}.markdown-body li{padding-left:var(--space-1)}.markdown-body li::marker{color:var(--primary)}.md-table{border:1px solid var(--border);border-radius:var(--radius-md);font-size:var(--text-xs);overflow:hidden}.md-table>div{padding:9px var(--space-3);border-bottom:1px solid var(--border);grid-template-columns:1.1fr 1fr 1.4fr;gap:10px;display:grid}.md-table>div:last-child{border-bottom:0}.md-table>div:first-child{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);text-transform:uppercase;letter-spacing:.08em;background:var(--secondary)}.md-table code{font-size:var(--text-3xs);background:0 0;border:0;padding:0}.md-accent{color:var(--primary)}.editor-card{background:var(--sidebar);border-color:var(--border);box-shadow:0 16px 35px #0000002e}.editor-tabs{padding:0 var(--space-3);background:var(--secondary);justify-content:flex-start;gap:0}.editor-dot{background:var(--chart-2);width:8px;height:8px;box-shadow:0 0 8px color-mix(in srgb, var(--chart-2) 60%, transparent);margin-right:var(--space-4);border-radius:50%}.editor-tab{padding:var(--space-3) var(--space-4);color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);border-right:1px solid var(--border)}.editor-tab.active{color:var(--foreground);background:var(--card);border-top:2px solid var(--primary);padding-top:10px}.editor-actions{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);letter-spacing:3px;margin-left:auto}.editor-body{background:linear-gradient(90deg, color-mix(in srgb, var(--background) 70%, transparent), transparent 16%);grid-template-columns:43px 1fr;min-height:218px;display:grid}.line-numbers{padding:var(--space-4) 10px var(--space-4) 0;border-right:1px solid var(--border);text-align:right;color:var(--muted-foreground);font:var(--text-xs) / 1.72 var(--font-mono);-webkit-user-select:none;user-select:none}.editor-body pre{padding:var(--space-4) var(--space-5);font:var(--text-sm) / 1.72 var(--font-mono);color:var(--foreground);margin:0;overflow:auto}.cm-comment{color:var(--muted-foreground);font-style:italic}.cm-keyword{color:var(--chart-5)}.cm-variable{color:var(--primary)}.cm-property{color:var(--chart-4)}.cm-string{color:var(--chart-2)}.editor-status{gap:var(--space-4);padding:var(--space-2) var(--space-4);border-top:1px solid var(--border);background:var(--secondary);color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);display:flex}.editor-ready{color:var(--chart-2);align-items:center;gap:var(--space-1);margin-left:auto;display:flex}@media (width<=760px){.markdown-body{padding:var(--space-6) var(--space-5) var(--space-7)}.md-table{font-size:var(--text-3xs)}.editor-body pre{padding:var(--space-4) var(--space-3)}.editor-status{font-size:var(--text-3xs);gap:10px}.editor-status span:nth-child(2){display:none}}@keyframes rise-in{0%{opacity:0;transform:translateY(14px)}to{opacity:1;transform:translateY(0)}}@keyframes soft-glow{0%,to{box-shadow:0 0 #0000}50%{box-shadow:0 0 34px color-mix(in srgb, var(--primary) 18%, transparent)}}@keyframes orbit-drift{0%{transform:rotate(-22deg)rotate(0)}to{transform:rotate(-22deg)rotate(360deg)}}@keyframes orbit-drift-reverse{0%{transform:rotate(58deg)rotate(360deg)}to{transform:rotate(58deg)rotate(0)}}@keyframes shimmer{0%{background-position:200% 0}to{background-position:-200% 0}}@keyframes pulse-dot{0%,to{opacity:1;transform:scale(1)}50%{opacity:.55;transform:scale(.72)}}.hero-section{animation:.7s cubic-bezier(.2,.8,.2,1) both rise-in}.hero-copy h1{background:linear-gradient(110deg, var(--foreground) 15%, var(--primary) 55%, var(--foreground) 85%);color:#0000;background-size:220%;-webkit-background-clip:text;background-clip:text;animation:9s linear infinite shimmer}.hero-copy p{animation:.7s cubic-bezier(.2,.8,.2,1) .1s both rise-in}.hero-actions{animation:.7s cubic-bezier(.2,.8,.2,1) .18s both rise-in}.hero-orbit{animation:.9s cubic-bezier(.2,.8,.2,1) .18s both rise-in}.orbit-one{animation:24s linear infinite orbit-drift}.orbit-two{animation:30s linear infinite orbit-drift-reverse}.orbit-core{animation:4s ease-in-out infinite soft-glow}.orbit-label{animation:.7s .7s both rise-in}.section-block{animation:.65s cubic-bezier(.2,.8,.2,1) .1s both rise-in}.section-block:nth-child(2){animation-delay:.16s}.section-block:nth-child(3){animation-delay:.22s}.section-block:nth-child(4){animation-delay:.28s}.button-row{transition:background .25s,transform .25s}.button-row:hover{background:color-mix(in srgb, var(--primary) 5%, transparent);transform:translate(3px)}.button:not(:disabled):after,.copy-button:after{content:"";background:linear-gradient(110deg,#0000 25%,#ffffff21 50%,#0000 75%);transition:transform .55s;position:absolute;inset:0;transform:translate(-120%)}.button:hover:after,.copy-button:hover:after{transform:translate(120%)}.button:focus-visible,.tab:focus-visible,.nav-item:focus-visible,.density:focus-visible,.segmented button:focus-visible,.text-button:focus-visible{outline:var(--focus-ring);outline-offset:var(--focus-offset)}.swatch{transition:transform .3s,box-shadow .3s}.color-card{transition:transform .25s,border-color .25s,background .25s}.color-card:hover{border-color:var(--ring);background:color-mix(in srgb, var(--foreground) 4%, var(--card));transform:translateY(-4px)}.color-card:hover .swatch{box-shadow:0 0 18px color-mix(in srgb, var(--primary) 30%, transparent), inset 0 0 0 1px #fff3;transform:scale(1.08)}.status-dot{animation:2.5s ease-in-out infinite pulse-dot}.field input,.input-with-action{transition:border-color .25s,box-shadow .25s,background .25s}.field input:hover,.input-with-action:hover{background:color-mix(in srgb, var(--foreground) 4%, var(--secondary));border-color:var(--ring)}.toggle{transition:background .25s,transform .2s}.toggle:active{transform:scale(.94)}.release{transition:transform .3s,box-shadow .3s}.release:hover{box-shadow:0 14px 38px #0003, 0 0 25px color-mix(in srgb, var(--primary) 10%, transparent);transform:translateY(-4px)}.release-icon{transition:transform .4s cubic-bezier(.2,.8,.2,1)}.release:hover .release-icon{transform:rotate(-8deg)scale(1.08)}.code-card{transition:border-color .3s,box-shadow .3s}.code-card:hover{border-color:var(--ring);box-shadow:0 15px 40px #00000024}.top-search{transition:border-color .25s,box-shadow .25s}.icon-matrix-container{gap:var(--space-5);flex-direction:column;display:flex}.icon-matrix-header{justify-content:space-between;align-items:center;gap:var(--space-4);flex-wrap:wrap;display:flex}.icon-search-bar{align-items:center;gap:var(--space-3);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);padding:var(--space-2) var(--space-4);min-width:240px;color:var(--muted-foreground);flex:1;transition:border-color .2s,box-shadow .2s;display:flex}.icon-search-bar:focus-within{border-color:var(--ring);box-shadow:0 0 0 3px color-mix(in srgb, var(--primary) 12%, transparent)}.icon-search-input{color:var(--foreground);font-size:var(--text-sm);background:0 0;border:0;outline:0;width:100%}.icon-clear-btn{color:var(--muted-foreground);cursor:pointer;border-radius:var(--radius-sm);background:0 0;border:0;place-items:center;padding:2px;display:grid}.icon-clear-btn:hover{color:var(--foreground)}.icon-size-picker{align-items:center;gap:var(--space-2);background:var(--secondary);border-radius:var(--radius-md);border:1px solid var(--border);padding:3px 4px;display:flex}.icon-size-btn{color:var(--muted-foreground);font:var(--text-3xs) var(--font-mono);padding:var(--space-1) var(--space-2);border-radius:var(--radius-sm);cursor:pointer;background:0 0;border:0;transition:all .15s}.icon-size-btn:hover{color:var(--foreground)}.icon-size-btn.active{background:var(--card);color:var(--foreground);box-shadow:0 1px 4px color-mix(in srgb, var(--foreground) 10%, transparent)}.icon-category-tabs{gap:var(--space-2);padding-bottom:2px;display:flex;overflow-x:auto}.icon-cat-btn{border:1px solid var(--border);background:var(--card);color:var(--muted-foreground);font-family:var(--font-sans);font-size:var(--text-sm);padding:var(--space-2) var(--space-3);border-radius:var(--radius-md);cursor:pointer;align-items:center;gap:var(--space-2);white-space:nowrap;font-weight:500;line-height:1.4;transition:all .15s;display:inline-flex}.icon-cat-btn svg{flex-shrink:0;display:block}.icon-cat-btn:hover{color:var(--foreground);border-color:var(--ring)}.icon-cat-btn.active{background:color-mix(in srgb, var(--primary) 10%, var(--card));border-color:var(--primary);color:var(--primary)}.icon-cat-count{font:var(--text-3xs) var(--font-mono);opacity:.8}.icon-grid{gap:var(--space-3);grid-template-columns:repeat(auto-fill,minmax(115px,1fr));display:grid}.icon-tile{justify-content:center;align-items:center;gap:var(--space-2);padding:var(--space-4) var(--space-2);background:var(--card);border:1px solid var(--border);border-radius:var(--radius-lg);cursor:pointer;color:var(--foreground);text-align:center;flex-direction:column;transition:all .2s cubic-bezier(.16,1,.3,1);display:flex;position:relative}.icon-tile:hover{border-color:var(--ring);box-shadow:0 8px 20px color-mix(in srgb, var(--primary) 10%, transparent);background:color-mix(in srgb, var(--foreground) 3%, var(--card));transform:translateY(-2px)}.icon-tile.copied{border-color:var(--primary);background:color-mix(in srgb, var(--primary) 12%, var(--card))}.icon-tile-glyph{height:32px;color:var(--foreground);place-items:center;transition:color .15s;display:grid}.icon-tile:hover .icon-tile-glyph{color:var(--primary)}.icon-tile-name{font:var(--text-3xs) var(--font-mono);color:var(--muted-foreground);text-overflow:ellipsis;white-space:nowrap;max-width:100%;overflow:hidden}.icon-tile-action{font:var(--text-3xs) var(--font-mono);color:var(--primary);min-height:16px}.icon-matrix-footer{padding-top:var(--space-3);border-top:1px solid var(--border);justify-content:space-between;align-items:center;display:flex}.icon-footer-pill{align-items:center;gap:var(--space-3);font-size:var(--text-xs);color:var(--muted-foreground);display:flex}.icon-footer-pill code{font-family:var(--font-mono);color:var(--primary)}.search-palette-backdrop{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:100;padding:12vh var(--space-4) var(--space-4);background:#000000b3;justify-content:center;align-items:flex-start;animation:.15s ease-out dialog-fade-in;display:flex;position:fixed;inset:0}.search-palette-modal{background:var(--card);border:1px solid var(--border);border-radius:var(--radius-xl);flex-direction:column;width:100%;max-width:580px;animation:.18s cubic-bezier(.16,1,.3,1) modal-scale-in;display:flex;overflow:hidden;box-shadow:0 24px 60px #00000073}.search-palette-head{align-items:center;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--border);background:var(--card);display:flex}.search-palette-icon{color:var(--muted-foreground);flex-shrink:0}.search-palette-input{font-family:var(--font-sans);font-size:var(--text-md);color:var(--foreground);background:0 0;border:0;outline:none;flex:1;min-width:0}.search-palette-input::placeholder{color:var(--muted-foreground)}.search-palette-body{max-height:380px;padding:var(--space-2);overflow-y:auto}.search-palette-results{flex-direction:column;gap:2px;margin:0;padding:0;list-style:none;display:flex}.search-palette-item{align-items:center;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-radius:var(--radius-lg);cursor:pointer;transition:background-color .1s;display:flex}.search-palette-item:hover,.search-palette-item.selected{background:var(--secondary)}.search-palette-item.selected .search-item-glyph{color:var(--primary);background:color-mix(in srgb, var(--primary) 12%, transparent)}.search-item-glyph{border-radius:var(--radius-md);background:color-mix(in srgb, var(--foreground) 6%, transparent);width:32px;height:32px;color:var(--muted-foreground);flex-shrink:0;place-items:center;transition:all .15s;display:grid}.search-item-content{flex:1;min-width:0}.search-item-title-row{align-items:center;gap:var(--space-2);margin-bottom:2px;display:flex}.search-item-title{font-family:var(--font-sans);font-size:var(--text-sm);color:var(--foreground);font-weight:600}.search-item-desc{font-size:var(--text-xs);color:var(--muted-foreground);text-overflow:ellipsis;white-space:nowrap;margin:0;overflow:hidden}.search-item-action{flex-shrink:0}.search-palette-empty{padding:var(--space-8) var(--space-4);text-align:center;color:var(--muted-foreground);flex-direction:column;justify-content:center;align-items:center;display:flex}.search-palette-empty p{margin:var(--space-2) 0 var(--space-1);font-size:var(--text-sm);color:var(--foreground);font-weight:500}.search-palette-empty span{font-size:var(--text-xs);color:var(--muted-foreground)}.search-palette-footer{justify-content:flex-end;align-items:center;gap:var(--space-4);padding:var(--space-2) var(--space-4);border-top:1px solid var(--border);background:color-mix(in srgb, var(--secondary) 40%, var(--card));font-size:var(--text-3xs);color:var(--muted-foreground);display:flex}@media (prefers-reduced-motion:reduce){*,:before,:after{scroll-behavior:auto!important;transition-duration:.01ms!important;animation-duration:.01ms!important;animation-iteration-count:1!important}.hero-copy h1{color:var(--foreground);background:0 0}}.brand-link{color:inherit;align-items:center;gap:10px;text-decoration:none;display:flex}.overview-grid{max-width:1180px;padding:0 var(--space-9) var(--space-11);gap:var(--space-5);grid-template-columns:repeat(auto-fit,minmax(230px,1fr));margin:0 auto;display:grid}.overview-links{gap:var(--space-3);font-size:var(--text-sm);margin:0;padding:0;list-style:none;display:grid}.overview-links a{align-items:center;gap:var(--space-2);color:var(--muted-foreground);text-decoration:none;display:inline-flex}.overview-links a:hover{color:var(--primary)}.not-found{gap:var(--space-6);padding:var(--space-9) 0;justify-items:center;display:grid}.not-found .overview-links{justify-items:center}@media (width<=760px){.overview-grid{padding-bottom:var(--space-9)}}@keyframes spin{to{transform:rotate(360deg)}} diff --git a/frontend/dist/assets/index-cXoFpIQ4.js b/frontend/dist/assets/index-cXoFpIQ4.js deleted file mode 100644 index ca7348e..0000000 --- a/frontend/dist/assets/index-cXoFpIQ4.js +++ /dev/null @@ -1,25 +0,0 @@ -var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;li[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,o)=>(o=n==null?{}:e(i(n)),s(r||!n||!n.__esModule||!a.call(n,`default`)?t(o,`default`,{value:n,enumerable:!0}):o,n));(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var l=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.for(`react.view_transition`),m=Symbol.iterator;function h(e){return typeof e!=`object`||!e?null:(e=m&&e[m]||e[`@@iterator`],typeof e==`function`?e:null)}var g={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},_=Object.assign,v={};function y(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}y.prototype.isReactComponent={},y.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=null)throw Error(`takes an object of state variables to update or a function which returns an object of state variables.`);this.updater.enqueueSetState(this,e,t,`setState`)},y.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function b(){}b.prototype=y.prototype;function ee(e,t,n){this.props=e,this.context=t,this.refs=v,this.updater=n||g}var te=ee.prototype=new b;te.constructor=ee,_(te,y.prototype),te.isPureReactComponent=!0;var ne=Array.isArray;function re(){}var x={H:null,A:null,T:null,S:null},ie=Object.prototype.hasOwnProperty;function S(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function ae(e,t){return S(e.type,t,e.props)}function C(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function oe(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var se=/\/+/g;function ce(e,t){return typeof e==`object`&&e&&e.key!=null?oe(``+e.key):t.toString(36)}function le(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(re,re):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function ue(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,ue(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+ce(e,0):a,ne(o)?(i=``,c!=null&&(i=c.replace(se,`$&/`)+`/`),ue(o,r,i,``,function(e){return e})):o!=null&&(C(o)&&(o=ae(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(se,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(ne(e))for(var u=0;u{t.exports=l()})),d=o((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function ee(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,te||(te=!0,ae());else{var t=n(l);t!==null&&se(ee,t.startTime-e)}}}var te=!1,ne=-1,re=5,x=-1;function ie(){return g?!0:!(e.unstable_now()-xt&&ie());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&se(ee,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}i=void 0}}finally{i?ae():te=!1}}}var ae;if(typeof y==`function`)ae=function(){y(S)};else if(typeof MessageChannel<`u`){var C=new MessageChannel,oe=C.port2;C.port1.onmessage=S,ae=function(){oe.postMessage(null)}}else ae=function(){_(S,0)};function se(t,n){ne=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(ne),ne=-1):h=!0,se(ee,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,te||(te=!0,ae()))),r},e.unstable_shouldYield=ie,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),f=o(((e,t)=>{t.exports=d()})),p=o((e=>{var t=u();function n(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=p()})),h=o((e=>{var t=f(),n=u(),r=m();function i(e){var t=`https://react.dev/errors/`+e;if(1ke||(e.current=Oe[ke],Oe[ke]=null,ke--)}function E(e,t){ke++,Oe[ke]=e.current,e.current=t}var Me=Ae(null),Ne=Ae(null),Pe=Ae(null),Fe=Ae(null);function Ie(e,t){switch(E(Pe,t),E(Ne,e),E(Me,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?up(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=up(t),e=dp(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}je(Me),E(Me,e)}function Le(){je(Me),je(Ne),je(Pe)}function Re(e){var t=e.memoizedState;t!==null&&(sh._currentValue=t.memoizedState,E(Fe,e)),t=Me.current;var n=dp(t,e.type);t!==n&&(E(Ne,e),E(Me,n))}function ze(e){Ne.current===e&&(je(Me),je(Ne)),Fe.current===e&&(je(Fe),sh._currentValue=De)}var Be,Ve;function He(e){if(Be===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Be=t&&t[1]||``,Ve=-1)`:-1i||c[r]!==l[i]){var u=` -`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{Ue=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?He(n):``}function We(e,t){switch(e.tag){case 26:case 27:case 5:return He(e.type);case 16:return He(`Lazy`);case 13:return e.child!==t&&t!==null?He(`Suspense Fallback`):He(`Suspense`);case 19:return He(`SuspenseList`);case 0:case 15:return D(e.type,!1);case 11:return D(e.type.render,!1);case 1:return D(e.type,!0);case 31:return He(`Activity`);case 30:return He(`ViewTransition`);default:return``}}function Ge(e){try{var t=``,n=null;do t+=We(e,n),n=e,e=e.return;while(e);return t}catch(e){return` -Error generating stack: `+e.message+` -`+e.stack}}var Ke=Object.prototype.hasOwnProperty,qe=t.unstable_scheduleCallback,Je=t.unstable_cancelCallback,Ye=t.unstable_shouldYield,Xe=t.unstable_requestPaint,O=t.unstable_now,Ze=t.unstable_getCurrentPriorityLevel,Qe=t.unstable_ImmediatePriority,$e=t.unstable_UserBlockingPriority,et=t.unstable_NormalPriority,tt=t.unstable_LowPriority,nt=t.unstable_IdlePriority,rt=t.log,it=t.unstable_setDisableYieldValue,at=null,ot=null;function st(e){if(typeof rt==`function`&&it(e),ot&&typeof ot.setStrictMode==`function`)try{ot.setStrictMode(at,e)}catch{}}var ct=Math.clz32?Math.clz32:dt,lt=Math.log,ut=Math.LN2;function dt(e){return e>>>=0,e===0?32:31-(lt(e)/ut|0)|0}var ft=256,pt=262144,mt=4194304;function ht(e){var t=e&42;if(t!==0)return t;switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:return 128;case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:return e&-e;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function gt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=ht(n))):i=ht(o):i=ht(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=ht(n))):i=ht(o)):i=ht(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function _t(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function vt(e,t){t&8&&(t|=t&32);var n=e.entangledLanes;if(n!==0)for(e=e.entanglements,n&=t;0n;n++)t.push(e);return t}function xt(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function St(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),Ln=!1;if(In)try{var Rn={};Object.defineProperty(Rn,"passive",{get:function(){Ln=!0}}),window.addEventListener(`test`,Rn,Rn),window.removeEventListener(`test`,Rn,Rn)}catch{Ln=!1}var zn=null,Bn=null,Vn=null;function Hn(){if(Vn)return Vn;var e,t=Bn,n=t.length,r,i=`value`in zn?zn.value:zn.textContent,a=i.length;for(e=0;e=br),Cr=` `,wr=!1;function Tr(e,t){switch(e){case`keyup`:return vr.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function Er(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var Dr=!1;function Or(e,t){switch(e){case`compositionend`:return Er(t);case`keypress`:return t.which===32?(wr=!0,Cr):null;case`textInput`:return e=t.data,e===Cr&&wr?null:e;default:return null}}function kr(e,t){if(Dr)return e===`compositionend`||!yr&&Tr(e,t)?(e=Hn(),Vn=Bn=zn=null,Dr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Qr(n)}}function ei(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?ei(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function ti(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Zr(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Zr(e.document)}return t}function ni(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var ri=In&&`documentMode`in document&&11>=document.documentMode,ii=null,ai=null,oi=null,si=!1;function ci(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;si||ii==null||ii!==Zr(r)||(r=ii,`selectionStart`in r&&ni(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),oi&&Xr(oi,r)||(oi=r,r=Jf(ai,`onSelect`),0>=o,i-=o,na=1<<32-ct(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),a=o(_,a,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),F&&ia(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(a,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(a,h),s=o(y,s,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(a,h),F&&ia(a,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(a,v.value,l),v!==null&&(s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return F&&ia(a,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,a,g,v.value,l),v!==null&&(e&&(_=v.alternate,_!==null&&h.delete(_.key===null?g:_.key)),s=o(v,s,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(a,e)}),F&&ia(a,g),u}function _(e,r,o,c){if(typeof o==`object`&&o&&o.type===se&&o.key===null&&o.props.ref===void 0&&(o=o.props.children),typeof o==`object`&&o){switch(o.$$typeof){case C:a:{for(var l=o.key;r!==null;){if(r.key===l){if(l=o.type,l===se){if(r.tag===7){n(e,r.sibling),c=a(r,o.props.children),po(c,o),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===ge&&ao(l)===r.type){n(e,r.sibling),c=a(r,o.props),po(c,o),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}o.type===se?(c=Gi(o.props.children,e.mode,c,o.key),po(c,o),c.return=e,e=c):(c=Wi(o.type,o.key,o.props,null,e.mode,c),po(c,o),c.return=e,e=c)}return s(e);case oe:a:{for(l=o.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===o.containerInfo&&r.stateNode.implementation===o.implementation){n(e,r.sibling),c=a(r,o.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=Ji(o,e.mode,c),c.return=e,e=c}return s(e);case ge:return o=ao(o),_(e,r,o,c)}if(Ee(o))return h(e,r,o,c);if(Ce(o)){if(l=Ce(o),typeof l!=`function`)throw Error(i(150));return o=l.call(o),g(e,r,o,c)}if(typeof o.then==`function`)return _(e,r,fo(o),c);if(o.$$typeof===de)return _(e,r,ja(e,o),c);mo(e,o)}return typeof o==`string`&&o!==``||typeof o==`number`||typeof o==`bigint`?(o=``+o,r!==null&&r.tag===6?(n(e,r.sibling),c=a(r,o),c.return=e,e=c):(n(e,r),c=Ki(o,e.mode,c),c.return=e,e=c),s(e)):n(e,r)}return function(e,t,n,r){try{uo=0;var i=_(e,t,n,r);return lo=null,i}catch(t){if(t===$a||t===to)throw t;var a=Bi(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var go=ho(!0),_o=ho(!1),vo=!1;function yo(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function bo(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function xo(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function So(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=Li(e),Ii(e,null,n),t}return Ni(e,r,t,n),Li(e)}function Co(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,wt(e,n)}}function wo(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var To=!1;function Eo(){if(To){var e=Wa;if(e!==null)throw e}}function Do(e,t,n,r){To=!1;var i=e.updateQueue;vo=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===Ua&&(To=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,h=s;f=t;var g=n;switch(h.tag){case 1:if(m=h.payload,typeof m==`function`){d=m.call(g,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=h.payload,f=typeof m==`function`?m.call(g,d,f):m,f==null)break a;d=S({},d,f);break a;case 2:vo=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),sd|=o,e.lanes=o,e.memoizedState=d}}function Oo(e,t){if(typeof e!=`function`)throw Error(i(191,e));e.call(t)}function ko(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=w.T,s={};s.types=o===null?null:o.types,w.T=s,pc(e,!1,t,n);try{var c=i(),l=w.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?fc(e,t,qa(c,r),jd(e)):fc(e,t,r,jd(e))}catch(n){fc(e,t,{then:function(){},status:`rejected`,reason:n},jd())}finally{T.p=a,o!==null&&s.types!==null&&(o.types=s.types),w.T=o}}function nc(){}function rc(e,t,n,r){if(e.tag!==5)throw Error(i(476));var a=ic(e).queue;tc(e,a,t,De,n===null?nc:function(){return ac(e),n(r)})}function ic(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:De,baseState:De,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ms,lastRenderedState:De},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:ms,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function ac(e){var t=ic(e);t.next===null&&(t=e.alternate.memoizedState),fc(e,t.next.queue,{},jd())}function oc(){return Aa(sh)}function sc(){return B().memoizedState}function cc(){return B().memoizedState}function lc(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=jd();e=xo(n);var r=So(t,e,n);r!==null&&(Pd(r,t,n),Co(r,t,n)),t={cache:Ia()},e.payload=t;return}t=t.return}}function uc(e,t,n){var r=jd();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},mc(e)?hc(t,n):(n=Pi(e,t,n,r),n!==null&&(Pd(n,e,r),gc(n,t,r)))}function dc(e,t,n){fc(e,t,n,jd())}function fc(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(mc(e))hc(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,Yr(s,o))return Ni(e,t,i,0),G===null&&Mi(),!1}catch{}if(n=Pi(e,t,i,r),n!==null)return Pd(n,e,r),gc(n,t,r),!0}return!1}function pc(e,t,n,r){if(r={lane:2,revertLane:Pf(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},mc(e)){if(t)throw Error(i(479))}else t=Pi(e,n,r,2),t!==null&&Pd(t,e,2)}function mc(e){var t=e.alternate;return e===L||t!==null&&t===L}function hc(e,t){Yo=Jo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function gc(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,wt(e,n)}}var _c={readContext:Aa,use:fs,useCallback:z,useContext:z,useEffect:z,useImperativeHandle:z,useLayoutEffect:z,useInsertionEffect:z,useMemo:z,useReducer:z,useRef:z,useState:z,useDebugValue:z,useDeferredValue:z,useTransition:z,useSyncExternalStore:z,useId:z,useHostTransitionStatus:z,useFormState:z,useActionState:z,useOptimistic:z,useMemoCache:z,useCacheRefresh:z,useEffectEvent:z},vc={readContext:Aa,use:fs,useCallback:function(e,t){return ls().memoizedState=[e,t===void 0?null:t],e},useContext:Aa,useEffect:Hs,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),Bs(4194308,4,Js.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Bs(4194308,4,e,t)},useInsertionEffect:function(e,t){Bs(4,2,e,t)},useMemo:function(e,t){var n=ls();t=t===void 0?null:t;var r=e();if(Xo){st(!0);try{e()}finally{st(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=ls();if(n!==void 0){var i=n(t);if(Xo){st(!0);try{n(t)}finally{st(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=uc.bind(null,L,e),[r.memoizedState,e]},useRef:function(e){var t=ls();return e={current:e},t.memoizedState=e},useState:function(e){e=ws(e);var t=e.queue,n=dc.bind(null,L,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Xs,useDeferredValue:function(e,t){return $s(ls(),e,t)},useTransition:function(){var e=ws(!1);return e=tc.bind(null,L,e.queue,!0,!1),ls().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=L,a=ls();if(F){if(n===void 0)throw Error(i(407));n=n()}else{if(n=t(),G===null)throw Error(i(349));q&127||ys(r,t,n)}a.memoizedState=n;var o={value:n,getSnapshot:t};return a.queue=o,Hs(xs.bind(null,r,o,e),[e]),r.flags|=2048,Rs(9,{destroy:void 0},bs.bind(null,r,o,n,t),null),n},useId:function(){var e=ls(),t=G.identifierPrefix;if(F){var n=ra,r=na;n=(r&~(1<<32-ct(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Zo++,0<\/script>`,o=o.removeChild(o.firstChild);break;case`select`:o=typeof r.is==`string`?s.createElement(`select`,{is:r.is}):s.createElement(`select`),r.multiple?o.multiple=!0:r.size&&(o.size=r.size);break;default:o=typeof r.is==`string`?s.createElement(a,{is:r.is}):s.createElement(a)}}o[jt]=t,o[Mt]=r;a:for(s=t.child;s!==null;){if(s.tag===5||s.tag===6)o.appendChild(s.stateNode);else if(s.tag!==4&&s.tag!==27&&s.child!==null){s.child.return=s,s=s.child;continue}if(s===t)break a;for(;s.sibling===null;){if(s.return===null||s.return===t)break a;s=s.return}s.sibling.return=s.return,s=s.sibling}t.stateNode=o;a:switch(np(o,a,r),a){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&gl(t)}}return V(t),t.subtreeFlags&=-33554433,_l(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&gl(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(i(166));if(e=Pe.current,ga(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,a=la,a!==null)switch(a.tag){case 27:case 5:r=a.memoizedProps}e[jt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||ep(e.nodeValue,n)),e||pa(t,!0)}else e=lp(e).createTextNode(r),e[jt]=t,t.stateNode=e}return V(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=ga(t),n!==null){if(e===null){if(!r)throw Error(i(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(i(557));e[jt]=t}else _a(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;V(t),e=!1}else n=va(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(Vo(t),t):(Vo(t),null);if(t.flags&128)throw Error(i(558))}return V(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(a=ga(t),r!==null&&r.dehydrated!==null){if(e===null){if(!a)throw Error(i(318));if(a=t.memoizedState,a=a===null?null:a.dehydrated,!a)throw Error(i(317));a[jt]=t}else _a(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;V(t),a=!1}else a=va(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=a),a=!0;if(!a)return t.flags&256?(Vo(t),t):(Vo(t),null)}return Vo(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,a=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(a=r.alternate.memoizedState.cachePool.pool),o=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(o=r.memoizedState.cachePool.pool),o!==a&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),yl(t,t.updateQueue),V(t),null);case 4:return Le(),e===null&&Wf(t.stateNode.containerInfo),t.flags|=67108864,V(t),null;case 10:return wa(t.type),V(t),null;case 19:if(Wo(t),r=t.memoizedState,r===null)return V(t),null;if(a=!!(t.flags&128),o=r.rendering,o===null){if(a)bl(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(o=Go(e),o!==null){for(t.flags|=128,bl(r,!1),e=o.updateQueue,t.updateQueue=e,yl(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)Ui(n,e),n=n.sibling;return Uo(t,Ho.current&1|2),F&&ia(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&O()>_d&&(t.flags|=128,a=!0,bl(r,!1),t.lanes=4194304)}}else{if(!a){if(e=Go(o),e!==null){if(t.flags|=128,a=!0,e=e.updateQueue,t.updateQueue=e,yl(t,e),bl(r,!0),r.tail===null&&r.tailMode!==`collapsed`&&r.tailMode!==`visible`&&!o.alternate&&!F)return V(t),null}else 2*O()-r.renderingStartTime>_d&&n!==536870912&&(t.flags|=128,a=!0,bl(r,!1),t.lanes=4194304)}r.isBackwards?(o.sibling=t.child,t.child=o):(e=r.last,e===null?t.child=o:e.sibling=o,r.last=o)}if(r.tail!==null){e=r.tail;a:{for(n=e;n!==null;){if(n.alternate!==null){n=!1;break a}n=n.sibling}n=!0}return r.rendering=e,r.tail=e.sibling,r.renderingStartTime=O(),e.sibling=null,o=Ho.current,o=a?o&1|2:o&1,r.tailMode===`visible`||r.tailMode===`collapsed`||!n||F?Uo(t,o):(n=o,E(Fo,t),E(Ho,n),Io===null&&(Io=t)),F&&ia(t,r.treeForkCount),e}return V(t),null;case 22:case 23:return Vo(t),Po(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(V(t),t.subtreeFlags&6&&(t.flags|=8192)):V(t),n=t.updateQueue,n!==null&&yl(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&je(Ya),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),wa(I),V(t),null;case 25:return null;case 30:return t.flags|=33554432,V(t),null}throw Error(i(156,t.tag))}function Sl(e,t){switch(sa(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return wa(I),Le(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return ze(t),null;case 31:if(t.memoizedState!==null){if(Vo(t),t.alternate===null)throw Error(i(340));_a()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(Vo(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(i(340));_a()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return Wo(t),e=t.flags,e&65536?(t.flags=e&-65537|128,e=t.memoizedState,e!==null&&(e.rendering=null,e.tail=null),t.flags|=4,t):null;case 4:return Le(),null;case 10:return wa(t.type),null;case 22:case 23:return Vo(t),Po(),e!==null&&je(Ya),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return wa(I),null;case 25:return null;default:return null}}function Cl(e,t){switch(sa(t),t.tag){case 3:wa(I),Le();break;case 26:case 27:case 5:ze(t);break;case 4:Le();break;case 31:t.memoizedState!==null&&Vo(t);break;case 13:Vo(t);break;case 19:Wo(t);break;case 10:wa(t.type);break;case 22:case 23:Vo(t),Po(),e!==null&&je(Ya);break;case 24:wa(I)}}function wl(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Tl(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function El(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{ko(t,n)}catch(t){Z(e,e.return,t)}}}function Dl(e,t,n){n.props=Tc(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Ol(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:var i=e.stateNode,a=Ti(e.memoizedProps,i);(i.ref===null||i.ref.name!==a)&&(i.ref=Pp(a)),r=i.ref;break;case 7:if(e.stateNode===null){var o=new Fp(e);h(e.child,!1,Qp,o,void 0,void 0),e.stateNode=o}r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function kl(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}}function Al(e,t){if((e.tag===5||e.tag===27||e.tag===6)&&e.alternate===null&&t!==null)for(var n=0;n title`))),np(r,t,n),r[jt]=e,Gt(r),t=r;break a;case`link`:if(o=Gm(`link`,`href`,a).get(t+(n.href||``))){for(s=0;sg&&(o=g,g=h,h=o);var _=$r(s,h),v=$r(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,w.T=null,n=wd,wd=null;var o=bd,s=Sd;if(X=0,xd=bd=null,Sd=0,W&6)throw Error(i(331));var c=W;if(W|=4,Zu(o.current),Uu(o,o.current,s,n),W=c,Df(0,!1),ot&&typeof ot.onPostCommitFiberRoot==`function`)try{ot.onPostCommitFiberRoot(at,o)}catch{}return!0}finally{T.p=a,w.T=r,uf(e,t)}}function pf(e,t,n){t=Xi(n,t),t=jc(e.stateNode,t,2),e=So(e,t,2),e!==null&&(xt(e,2),Ef(e))}function Z(e,t,n){if(e.tag===3)pf(e,e,n);else for(;t!==null;){if(t.tag===3){pf(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(yd===null||!yd.has(r))){e=Xi(n,e),n=Mc(2),r=So(t,n,2),r!==null&&(Nc(n,r,t,e),xt(r,2),Ef(r));break}}t=t.return}}function mf(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new td;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(ad=!0,i.add(n),e=hf.bind(null,e,t,n),t.then(e,e))}function hf(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>O()-hd?W&2?ld|=n:Vd(e,0):ld|=n,dd===q&&(dd=0)),Ef(e)}function gf(e,t){t===0&&(t=k()),e=Fi(e,t),e!==null&&(xt(e,t),Ef(e))}function _f(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),gf(e,n)}function vf(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,a=e.memoizedState;a!==null&&(n=a.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}r!==null&&r.delete(t),gf(e,n)}function yf(e,t){return qe(e,t)}var bf=null,xf=null,Sf=!1,Cf=!1,wf=!1,Tf=0;function Ef(e){e!==xf&&e.next===null&&(xf===null?bf=xf=e:xf=xf.next=e),Cf=!0,Sf||(Sf=!0,Nf())}function Df(e,t){if(!wf&&Cf){wf=!0;do for(var n=!1,r=bf;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-ct(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,Mf(r,a))}else a=q,a=gt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||_t(r,a)||(n=!0,Mf(r,a))}r=r.next}while(n);wf=!1}}function Of(){kf()}function kf(){Cf=Sf=!1;var e=0;Tf!==0&&hp()&&(e=Tf);for(var t=O(),n=null,r=bf;r!==null;){var i=r.next,a=Af(r,t);a===0?(r.next=null,n===null?bf=i:n.next=i,i===null&&(xf=n)):(n=r,(e!==0||a&3)&&(Cf=!0)),r=i}X!==0&&X!==5||Df(e,!1),Tf!==0&&(Tf=0)}function Af(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&ap(d)&&(c=c.responseEnd,o+=u*(c$m){s.length=o;break}f=new Promise(jp.bind(f)),s.push(f)}}}if(0`u`?null:document;function Tm(e,t,n){var r=wm;if(r&&typeof t==`string`&&t){var i=fn(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),ym.has(i)||(ym.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),np(t,`link`,e),Gt(t),r.head.appendChild(t)))}}function Em(e){xm.D(e),Tm(`dns-prefetch`,e,null)}function Dm(e,t){xm.C(e,t),Tm(`preconnect`,e,t)}function Om(e,t,n){xm.L(e,t,n);var r=wm;if(r&&e&&t){var i=`link[rel="preload"][as="`+fn(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+fn(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+fn(n.imageSizes)+`"]`)):i+=`[href="`+fn(e)+`"]`;var a=i;switch(t){case`style`:a=Pm(e);break;case`script`:a=Rm(e)}if(!(vm.has(a)||(e=S({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),vm.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(Fm(a))||t===`script`&&r.querySelector(zm(a))))){var o=r.createElement(`link`);np(o,`link`,e),t===`style`&&(o[zt]=!0,o.onload=o.onerror=function(){Kt(o)}),Gt(o),r.head.appendChild(o)}}}function km(e,t){xm.m(e,t);var n=wm;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+fn(r)+`"][href="`+fn(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Rm(e)}if(!vm.has(a)&&(e=S({rel:`modulepreload`,href:e},t),vm.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(zm(a)))return}r=n.createElement(`link`),np(r,`link`,e),Gt(r),n.head.appendChild(r)}}}function Am(e,t,n){xm.S(e,t,n);var r=wm;if(r&&e){var i=Wt(r).hoistableStyles,a=Pm(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(Fm(a)))s.loading=5;else{e=S({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=vm.get(a))&&Hm(e,n);var c=o=r.createElement(`link`);Gt(c),np(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Vm(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function jm(e,t){xm.X(e,t);var n=wm;if(n&&e){var r=Wt(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=S({src:e,async:!0},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Gt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Mm(e,t){xm.M(e,t);var n=wm;if(n&&e){var r=Wt(n).hoistableScripts,i=Rm(e),a=r.get(i);a||(a=n.querySelector(zm(i)),a||(e=S({src:e,async:!0,type:`module`},t),(t=vm.get(i))&&Um(e,t),a=n.createElement(`script`),Gt(a),np(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Nm(e,t,n,r){var a=(a=Pe.current)?bm(a):null;if(!a)throw Error(i(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(n=Pm(n.href),t=Wt(a).hoistableStyles,r=t.get(n),r||(r={type:`style`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Pm(n.href);var o=Wt(a).hoistableStyles,s=o.get(e);if(s||(a=a.ownerDocument||a,s={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},o.set(e,s),(o=a.querySelector(Fm(e)))?o._p||(s.instance=o,s.state.loading=5):(o=vm.get(e),o||(o={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},vm.set(e,o)),Lm(a,e,o,s.state))),t&&r===null)throw Error(i(528,``));return s}if(t&&r!==null)throw Error(i(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(n=Rm(n),t=Wt(a).hoistableScripts,r=t.get(n),r||(r={type:`script`,instance:null,count:0,state:null},t.set(n,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(i(444,e))}}function Pm(e){return`href="`+fn(e)+`"`}function Fm(e){return`link[rel="stylesheet"][`+e+`]`}function Im(e){return S({},e,{"data-precedence":e.precedence,precedence:null})}function Lm(e,t,n,r){if(t=e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)){if(!0!==t[zt]){r.loading=1;return}}else t=e.createElement(`link`),t[zt]=!0,t.onload=t.onerror=Kt.bind(null,t),np(t,`link`,n),Gt(t),e.head.appendChild(t);r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2})}function Rm(e){return`[src="`+fn(e)+`"]`}function zm(e){return`script[async]`+e}function Bm(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+fn(n.href)+`"]`);if(r)return t.instance=r,Gt(r),r;var a=S({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),Gt(r),np(r,`style`,a),Vm(r,n.precedence,e),t.instance=r;case`stylesheet`:a=Pm(n.href);var o=e.querySelector(Fm(a));if(o)return t.state.loading|=4,t.instance=o,Gt(o),o;r=Im(n),(a=vm.get(a))&&Hm(r,a),o=(e.ownerDocument||e).createElement(`link`),Gt(o);var s=o;return s._p=new Promise(function(e,t){s.onload=e,s.onerror=t}),np(o,`link`,r),t.state.loading|=4,Vm(o,n.precedence,e),t.instance=o;case`script`:return o=Rm(n.src),(a=e.querySelector(zm(o)))?(t.instance=a,Gt(a),a):(r=n,(a=vm.get(o))&&(r=S({},n),Um(r,a)),e=e.ownerDocument||e,a=e.createElement(`script`),Gt(a),np(a,`link`,r),e.head.appendChild(a),t.instance=a);case`void`:return null;default:throw Error(i(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Vm(r,n.precedence,e));return t.instance}function Vm(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function qm(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Jm(e,t){return e===`img`&&t.src!=null&&t.src!==``&&t.onLoad==null&&t.loading!==`lazy`}function Ym(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Xm(e){return(e.width||100)*(e.height||100)*(typeof devicePixelRatio==`number`?devicePixelRatio:1)*.25}function Zm(e,t){typeof t.decode==`function`&&(e.imgCount++,t.complete||(e.imgBytes+=Xm(t),e.suspenseyImages.push(t)),e=rh.bind(e),t.decode().then(e,e))}function Qm(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Pm(r.href),a=t.querySelector(Fm(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=nh.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,Gt(a);return}a=t.ownerDocument||t,r=Im(r),(i=vm.get(i))&&Hm(r,i),a=a.createElement(`link`),Gt(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),np(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=nh.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var $m=0;function eh(e,t){return e.stylesheets&&e.count===0&&ah(e,e.stylesheets),0$m?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function th(e){if(e.count===0&&(e.imgCount===0||!e.waitingForImages)){if(e.stylesheets)ah(e,e.stylesheets);else if(e.unsuspend){var t=e.unsuspend;e.unsuspend=null,t()}}}function nh(){this.count--,th(this)}function rh(){this.imgCount--,th(this)}var ih=null;function ah(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,ih=new Map,t.forEach(oh,e),ih=null,nh.call(e))}function oh(e,t){if(!(t.state.loading&4)){var n=ih.get(e);if(n)var r=n.get(null);else{n=new Map,ih.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=h()})),_=c(u(),1),v=g();function y(e,t){if(e instanceof RegExp)return{keys:!1,pattern:e};var n,r,i,a,o=[],s=``,c=e.split(`/`);for(c[0]||c.shift();i=c.shift();)n=i[0],n===`*`?(o.push(n),s+=i[1]===`?`?`(?:/(.*))?`:`/(.*)`):n===`:`?(r=i.indexOf(`?`,1),a=i.indexOf(`.`,1),o.push(i.substring(1,~r?r:~a?a:i.length)),s+=~r&&!~a?`(?:/([^/]+?))?`:`/([^/]+?)`,~a&&(s+=(~r?`?`:``)+`\\`+i.substring(a))):s+=`/`+i;return{keys:o,pattern:RegExp(`^`+s+(t?`(?=$|/)`:`/?$`),`i`)}}var b=o((e=>{var t=u();function n(e,t){return e===t&&(e!==0||1/e==1/t)||e!==e&&t!==t}var r=typeof Object.is==`function`?Object.is:n,i=t.useState,a=t.useEffect,o=t.useLayoutEffect,s=t.useDebugValue;function c(e,t){var n=t(),r=i({inst:{value:n,getSnapshot:t}}),c=r[0].inst,u=r[1];return o(function(){c.value=n,c.getSnapshot=t,l(c)&&u({inst:c})},[e,n,t]),a(function(){return l(c)&&u({inst:c}),e(function(){l(c)&&u({inst:c})})},[e]),s(n),n}function l(e){var t=e.getSnapshot;e=e.value;try{var n=t();return!r(e,n)}catch{return!0}}function d(e,t){return t()}var f=typeof window>`u`||window.document===void 0||window.document.createElement===void 0?d:c;e.useSyncExternalStore=t.useSyncExternalStore===void 0?f:t.useSyncExternalStore})),ee=o(((e,t)=>{t.exports=b()}))(),te=_.useInsertionEffect,ne=typeof window<`u`&&window.document!==void 0&&window.document.createElement!==void 0?_.useLayoutEffect:_.useEffect,re=te||ne,x=e=>{let t=_.useRef([e,(...e)=>t[0](...e)]).current;return re(()=>{t[0]=e}),t[1]},ie=[`popstate`,`pushState`,`replaceState`,`hashchange`],S=[],ae=()=>S.forEach(e=>e()),C=e=>(S.push(e)===1&&ie.forEach(e=>addEventListener(e,ae)),()=>{S=S.filter(t=>t!==e),S.length||ie.forEach(e=>removeEventListener(e,ae))}),oe=(e,t)=>(0,ee.useSyncExternalStore)(C,e,t),se=()=>location.search,ce=({ssrSearch:e}={})=>oe(se,e==null?se:()=>e),le=()=>location.pathname,ue=({ssrPath:e}={})=>oe(le,e==null?le:()=>e),de=(e,{replace:t=!1,state:n=null}={})=>history[t?`replaceState`:`pushState`](n,``,e),fe=e=>[ue(e),de],pe=Symbol.for(`wouter_v3`);if(typeof history<`u`&&window[pe]===void 0){for(let e of[`pushState`,`replaceState`]){let t=history[e];history[e]=function(){let n=t.apply(this,arguments),r=new Event(e);return r.arguments=arguments,dispatchEvent(r),n}}Object.defineProperty(window,pe,{value:!0})}var me=(e=``)=>e===`/`?``:e,he=(e,t)=>e[0]===`~`?e.slice(1):me(t)+e,ge=(e,t)=>(e=_e(me(e)),t=_e(t),!e||!t.toLowerCase().indexOf(e.toLowerCase())?t.slice(e.length)||`/`:`~`+t),_e=e=>{try{return e.includes(`%`)?decodeURI(e):e}catch{return e}},ve=e=>_e(e[0]===`?`?e.slice(1):e),ye={hook:fe,searchHook:ce,parser:y,base:``,ssrPath:void 0,ssrSearch:void 0,ssrContext:void 0,hrefs:e=>e,aroundNav:(e,t,n)=>e(t,n)},be=(0,_.createContext)(ye),xe=()=>(0,_.useContext)(be),Se={},Ce=(0,_.createContext)(Se),we=()=>(0,_.useContext)(Ce),Te=(e,t=e.base)=>ge(t,e.hook(e)[0]),Ee=e=>{let[t,n]=e.hook(e);return[ge(e.base,t),x((t,r)=>e.aroundNav(n,he(t,e.base),r))]},w=()=>Ee(xe()),T=()=>{let e=xe();return ve(e.searchHook(e))},De=(e,t,n,r)=>{let{pattern:i,keys:a}=t instanceof RegExp?{pattern:t}:e(t||`*`,r),o=i.exec(n);if(!o)return[!1,null];let s={};for(let e=1;e{let n=xe(),r=t.hook?ye:n,i=r;if(t.ssrPath){let[e,n=t.ssrSearch??``]=t.ssrPath.split(`?`);e&&(t.ssrSearch=n,t.ssrPath=e)}t.hrefs=t.hrefs??t.hook?.hrefs,t.searchHook=t.searchHook??t.hook?.searchHook;let a=(0,_.useRef)(r),o=a.current,s=o;for(let e in r){let n=e===`base`?r[e]+(t[e]??``):t[e]??r[e];n!==s[e]&&(o===s&&(a.current=s={...s}),s[e]=n),(n!==r[e]||n!==i[e])&&(i=s)}return(0,_.createElement)(be.Provider,{value:i},e)},ke=({children:e,component:t},n)=>t?(0,_.createElement)(t,{params:n}):typeof e==`function`?e(n):e,Ae=e=>{let t=(0,_.useRef)(Se),n=t.current,r=Object.keys(e);return t.current=r.length!==Object.keys(n).length||r.some(t=>e[t]!==n[t])?e:n};function je(){let[e,t]=w(),n=T(),r=(0,_.useMemo)(()=>new URLSearchParams(n),[n]),i=r;return[r,x((n,r)=>{i=new URLSearchParams(typeof n==`function`?n(i):n);let a=i.toString();t(e+(a?`?`+a:``),r)})]}var E=({path:e,nest:t,match:n,...r})=>{let i=xe(),a=Te(i),[o,s,c]=n??De(i.parser,e,a,t),l=Ae({...we(),...s});if(!o)return null;let u=ke(r,l);return(0,_.createElement)(Ce.Provider,{value:l},c?(0,_.createElement)(Oe,{base:c},u):u)},Me=(0,_.forwardRef)((e,t)=>{let n=xe(),[r,i]=Ee(n),{to:a=``,href:o=a,onClick:s,asChild:c,children:l,className:u,replace:d,state:f,transition:p,...m}=e;return m.onClick=x(t=>{t.ctrlKey||t.metaKey||t.altKey||t.shiftKey||t.button!==0||(s?.(t),t.defaultPrevented||(t.preventDefault(),i(o,e)))}),m.href=n.hrefs(o[0]===`~`?o.slice(1):n.base+o,n),u!==void 0&&(m.className=u?.call?u(r===o):u),t&&(m.ref=t),c&&(0,_.isValidElement)(l)?(0,_.cloneElement)(l,m):(0,_.createElement)(`a`,m,l)}),Ne=(e,t=[])=>{if(Array.isArray(e))for(let n of e)Ne(n&&n.type===_.Fragment?n.props.children:n,t);else t.push(e);return t},Pe=({children:e,location:t})=>{let n=xe(),r=Te(n);for(let i of Ne(e)){let e=0;if((0,_.isValidElement)(i)&&(e=De(n.parser,i.props.path,t||r,i.props.nest))[0])return(0,_.cloneElement)(i,{match:e})}return null},Fe=[`default`,`compact`],Ie=(0,_.createContext)(null);function Le(){let e=(0,_.useContext)(Ie);if(!e)throw Error(`useAppState must be used inside `);return e}var Re={theme:`ns-theme`,viewMode:`ns-view-mode`,sidebarCollapsed:`ns-sidebar-collapsed`};function ze(e,t){try{let n=localStorage.getItem(e);return n===null?void 0:t.includes(n)?n:void 0}catch{return}}function Be(e,t){try{localStorage.setItem(e,t)}catch{}}function Ve(e){let t=ze(e,[`true`,`false`]);return t===void 0?void 0:t===`true`}function He(e,t){Be(e,t?`true`:`false`)}var Ue=o((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.fragment`);function r(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.Fragment=n,e.jsx=r,e.jsxs=r})),D=o(((e,t)=>{t.exports=Ue()}))();function We(e){let t=document.documentElement;t.dataset.theme=e,t.classList.toggle(`dark`,e===`dark`),t.classList.toggle(`light`,e===`light`)}function Ge(e){document.documentElement.dataset.viewMode=e}function Ke(){return document.documentElement.getAttribute(`data-theme`)===`light`?`light`:`dark`}function qe(){return ze(Re.viewMode,Fe)??`default`}function Je(){return Ve(Re.sidebarCollapsed)??!1}function Ye({children:e}){let[t,n]=(0,_.useState)(Ke),[r,i]=(0,_.useState)(qe),[a,o]=(0,_.useState)(Je),[s,c]=(0,_.useState)(!1);(0,_.useEffect)(()=>{We(t)},[t]),(0,_.useEffect)(()=>{Ge(r)},[r]),(0,_.useEffect)(()=>{let e=e=>{(e.metaKey||e.ctrlKey)&&e.key.toLowerCase()===`k`&&(e.preventDefault(),c(e=>!e))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]);let l=(0,_.useCallback)(e=>{n(e),Be(Re.theme,e)},[]),u=(0,_.useCallback)(()=>{l(t===`dark`?`light`:`dark`)},[t,l]),d=(0,_.useCallback)(e=>{i(e),Be(Re.viewMode,e)},[]),f=(0,_.useCallback)(e=>{o(e),He(Re.sidebarCollapsed,e)},[]),p=(0,_.useCallback)(()=>{f(!a)},[a,f]),m=(0,_.useCallback)(()=>c(!0),[]),h=(0,_.useCallback)(()=>c(!1),[]),g=(0,_.useCallback)(()=>c(e=>!e),[]),v=(0,_.useMemo)(()=>({theme:t,viewMode:r,sidebarCollapsed:a,searchOpen:s,setTheme:l,toggleTheme:u,setViewMode:d,setSidebarCollapsed:f,toggleSidebar:p,openSearch:m,closeSearch:h,toggleSearch:g}),[t,r,a,s,l,u,d,f,p,m,h,g]);return(0,D.jsx)(Ie.Provider,{value:v,children:e})}var Xe=[{id:`metrics`,label:`Metrics Dashboard`,icon:`sparkles`},{id:`settings`,label:`Settings & Safeguards`,icon:`settings`},{id:`table`,label:`Service Monitor Table`,icon:`layers`},{id:`deploy`,label:`Deployment Flow`,icon:`terminal`}];function O(...e){let t=[];for(let n of e)if(n){if(typeof n==`string`||typeof n==`number`)t.push(String(n));else if(Array.isArray(n)){let e=O(...n);e&&t.push(e)}else if(typeof n==`object`)for(let[e,r]of Object.entries(n))r&&t.push(e)}return t.join(` `)}function Ze({className:e,...t}){return(0,D.jsx)(`div`,{className:O(`surface-card`,e),...t})}function Qe({className:e,...t}){return(0,D.jsx)(`div`,{className:O(`stack-xs`,e),style:{marginBottom:`var(--space-4)`},...t})}function $e({className:e,children:t,...n}){return(0,D.jsx)(`h3`,{className:O(e),style:{margin:0,fontSize:`var(--text-lg)`,fontWeight:700,color:`var(--foreground)`,letterSpacing:`-0.02em`},...n,children:t})}function et({className:e,...t}){return(0,D.jsx)(`p`,{className:O(e),style:{margin:0,fontSize:`var(--text-sm)`,color:`var(--muted-foreground)`,lineHeight:1.5},...t})}function tt({className:e,...t}){return(0,D.jsx)(`div`,{className:O(e),...t})}function nt({className:e,...t}){return(0,D.jsx)(`div`,{className:O(`flex-between`,e),style:{marginTop:`var(--space-5)`,paddingTop:`var(--space-4)`,borderTop:`1px solid var(--border)`},...t})}function rt({variant:e=`primary`,className:t,children:n,...r}){return(0,D.jsx)(`span`,{className:O(`badge`,`badge-${e}`,t),...r,children:n})}function it(e){return!e||!/[0-9]/.test(e)?`neutral`:e.trim().startsWith(`-`)?`down`:`up`}function at({title:e,value:t,change:n,trend:r=`neutral`,direction:i,caption:a,icon:o,className:s}){let c=i??it(n);return(0,D.jsxs)(Ze,{className:O(`hover-lift`,s),children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-3)`},children:[(0,D.jsx)(`span`,{style:{fontFamily:`var(--font-mono)`,fontSize:`var(--text-3xs)`,textTransform:`uppercase`,letterSpacing:`0.08em`,color:`var(--muted-foreground)`},children:e}),o&&(0,D.jsx)(`div`,{style:{color:`var(--primary)`,display:`flex`,alignItems:`center`},children:o})]}),(0,D.jsx)(`div`,{style:{fontSize:`var(--text-2xl)`,fontWeight:800,color:`var(--foreground)`,lineHeight:1.1,letterSpacing:`-0.04em`,marginBottom:`var(--space-2)`},children:t}),(0,D.jsxs)(`div`,{className:`flex-between`,style:{marginTop:`var(--space-2)`},children:[n&&(0,D.jsxs)(rt,{variant:r===`up`?`positive`:r===`down`?`destructive`:`secondary`,children:[c===`up`?`↑`:c===`down`?`↓`:`→`,` `,n]}),a&&(0,D.jsx)(`span`,{style:{fontSize:`var(--text-3xs)`,color:`var(--muted-foreground)`,fontFamily:`var(--font-mono)`},children:a})]})]})}function ot({value:e=0,max:t=100,indeterminate:n=!1,label:r,className:i,...a}){let o=Math.min(Math.max(Math.round(e/(t>0?t:100)*100),0),100),s=(0,_.useId)();return(0,D.jsxs)(`div`,{className:O(`stack-xs`,i),...a,children:[(r||!n)&&(0,D.jsxs)(`div`,{className:`flex-between`,style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`},children:[r&&(0,D.jsx)(`span`,{id:s,children:r}),!n&&(0,D.jsxs)(`span`,{style:{fontFamily:`var(--font-mono)`},children:[o,`%`]})]}),(0,D.jsx)(`div`,{className:`progress-container`,role:`progressbar`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":n?void 0:o,"aria-busy":n?!0:void 0,"aria-labelledby":r?s:void 0,children:(0,D.jsx)(`div`,{className:O(`progress-fill`,n&&`progress-indeterminate`),style:n?void 0:{width:`${o}%`}})})]})}var st=e=>e?.replace(/([a-z0-9])([A-Z])/g,`$1-$2`).toLowerCase();function ct(e,t,n=[]){if(t==null)throw Error(`[lucide]: iconNode is required when icon name is used`);return{name:st(e),size:24,node:t,...n.length>0?{aliases:n}:{}}}var lt=e=>{let t=``,n=!1;for(let r of e){if(r===`-`||r===`_`||r<=` `){n=t.length>0;continue}t.length===0?t+=r.toLowerCase():t+=n?r.toUpperCase():r,n=!1}return t},ut=e=>{let t=lt(e);return t.charAt(0).toUpperCase()+t.slice(1)},dt=(...e)=>e.filter((e,t,n)=>!!e&&e.trim()!==``&&n.indexOf(e)===t).join(` `).trim(),ft={xmlns:`http://www.w3.org/2000/svg`,width:24,height:24,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,"stroke-width":2,"stroke-linecap":`round`,"stroke-linejoin":`round`};function pt(e){return e!=null}function mt(e,t={}){let n=t.attributeNames??{},r=e=>n[e]??e,i=e.size??e.width??ft.width,a=e.size??e.height??ft.height,o=e.aliases?.filter(e=>typeof e==`string`&&e.trim()!==``).map(e=>`lucide-${e}`)??[],s=[...e.name?[`lucide-${e.name}`]:[],...o],c=t.className?.split(` `).filter(Boolean)??[],l=t.includeDefaultClasses===!1?dt(...c):dt(`lucide`,...s,...c),u=t.absoluteStrokeWidth?Number(t.strokeWidth??ft[`stroke-width`])*Number(e.size??e.width??ft.width)/Number(t.size??t.width??ft.width):t.strokeWidth??ft[`stroke-width`];return[`svg`,{...Object.entries(ft).reduce((e,[t,n])=>(e[r(t)]=n,e),{}),...`color`in t&&t.color&&{[r(`stroke`)]:t.color},...`size`in t&&pt(t.size)&&{[r(`width`)]:t.size,[r(`height`)]:t.size},...`width`in t&&pt(t.width)&&{[r(`width`)]:t.width},...`height`in t&&pt(t.height)&&{[r(`height`)]:t.height},[r(`stroke-width`)]:u,...l&&{[r(`class`)]:l},[r(`viewBox`)]:`0 0 ${i} ${a}`,...t.hasA11yProp===!1?{[r(`aria-hidden`)]:`true`}:{},...`attributes`in t&&t.attributes},e.node.map(e=>{let[n,i,a]=e,o=t.nonScalingStroke?{[r(`vector-effect`)]:`non-scaling-stroke`,...i}:i;return a?[n,o,a]:[n,o]})]}function ht(e,t={}){return mt(e,{...t,attributeNames:{...t.attributeNames,class:`className`,"stroke-width":`strokeWidth`,"stroke-linecap":`strokeLinecap`,"stroke-linejoin":`strokeLinejoin`,"vector-effect":`vectorEffect`}})}var gt=e=>{for(let t in e)if(t.startsWith(`aria-`)||t===`role`||t===`title`)return!0;return!1},_t=(0,_.createContext)({}),vt=()=>(0,_.useContext)(_t),yt=(0,_.forwardRef)(({color:e,size:t,width:n,height:r,strokeWidth:i,absoluteStrokeWidth:a,nonScalingStroke:o,className:s=``,children:c,iconNode:l=[],icon:u={node:l,aliases:[],size:24},...d},f)=>{let{size:p=24,strokeWidth:m=2,absoluteStrokeWidth:h=!1,nonScalingStroke:g=!1,color:v=`currentColor`,className:y=``}=vt()??{},b=!!c||gt(d),[ee,te,ne=[]]=ht(u,{color:e??v,width:n??t??p,height:r??t??p,strokeWidth:i??m,absoluteStrokeWidth:a??h,nonScalingStroke:o??g,className:dt(y,s),hasA11yProp:b,attributes:d});return(0,_.createElement)(ee,{ref:f,...te},[...ne.map(([e,t])=>(0,_.createElement)(e,t)),...Array.isArray(c)?c:[c]])});function k(e,t=[],n=[]){let r=typeof e==`string`?ct(e,t,n):e,i=(0,_.forwardRef)(({className:e,...t},n)=>(0,_.createElement)(yt,{ref:n,icon:r,className:e,...t}));return r.name&&(i.displayName=ut(r.name)),i}var bt={name:`arrow-left`,size:24,node:[[`path`,{d:`m12 19-7-7 7-7`,key:`1l729n`}],[`path`,{d:`M19 12H5`,key:`x3x0zl`}]]};bt.node;var xt=k(bt),St={name:`arrow-right`,size:24,node:[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]};St.node;var Ct=k(St),wt={name:`calendar`,size:24,node:[[`path`,{d:`M8 2v3`,key:`1ioesn`}],[`path`,{d:`M16 2v3`,key:`otl347`}],[`rect`,{x:`3`,y:`3`,width:`18`,height:`18`,rx:`2`,key:`h1oib`}],[`path`,{d:`M3 9h18`,key:`1pudct`}]]};wt.node;var Tt=k(wt),Et={name:`check`,size:24,node:[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]};Et.node;var Dt=k(Et),Ot={name:`chevron-down`,size:24,node:[[`path`,{d:`m6 9 6 6 6-6`,key:`qrunsl`}]]};Ot.node;var kt=k(Ot),At={name:`chevron-left`,size:24,node:[[`path`,{d:`m15 18-6-6 6-6`,key:`1wnfg3`}]]};At.node;var jt=k(At),Mt={name:`chevron-right`,size:24,node:[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]};Mt.node;var Nt=k(Mt),Pt={name:`chevron-up`,size:24,node:[[`path`,{d:`m18 15-6-6-6 6`,key:`153udz`}]]};Pt.node;var Ft=k(Pt),It={name:`circle-alert`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`line`,{x1:`12`,x2:`12`,y1:`8`,y2:`12`,key:`1pkeuh`}],[`line`,{x1:`12`,x2:`12.01`,y1:`16`,y2:`16`,key:`4dfq90`}]],aliases:[`alert-circle`]};It.node;var Lt=k(It),Rt={name:`circle-check`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`m16 9-5.5 5.5L8 12`,key:`xofnsj`}]],aliases:[`check-circle-2`]};Rt.node;var zt=k(Rt),Bt={name:`circle-question-mark`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3`,key:`1u773s`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`help-circle`,`circle-help`]};Bt.node;var Vt=k(Bt),Ht={name:`clock`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 6v6l4 2`,key:`mmk7yg`}]]};Ht.node;var Ut=k(Ht),Wt={name:`code-xml`,size:24,node:[[`path`,{d:`m18 16 4-4-4-4`,key:`1inbqp`}],[`path`,{d:`m6 8-4 4 4 4`,key:`15zrgr`}],[`path`,{d:`m14.5 4-5 16`,key:`e7oirm`}]],aliases:[`code-2`]};Wt.node;var Gt=k(Wt),Kt={name:`copy`,size:24,node:[[`rect`,{width:`14`,height:`14`,x:`8`,y:`8`,rx:`2`,ry:`2`,key:`17jyea`}],[`path`,{d:`M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2`,key:`zix9uf`}]]};Kt.node;var qt=k(Kt),Jt={name:`cpu`,size:24,node:[[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M17 20v2`,key:`1rnc9c`}],[`path`,{d:`M17 2v2`,key:`11trls`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M2 17h2`,key:`7oei6x`}],[`path`,{d:`M2 7h2`,key:`asdhe0`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`M20 17h2`,key:`1fpfkl`}],[`path`,{d:`M20 7h2`,key:`1o8tra`}],[`path`,{d:`M7 20v2`,key:`4gnj0m`}],[`path`,{d:`M7 2v2`,key:`1i4yhu`}],[`rect`,{x:`4`,y:`4`,width:`16`,height:`16`,rx:`2`,key:`1vbyd7`}],[`rect`,{x:`8`,y:`8`,width:`8`,height:`8`,rx:`1`,key:`z9xiuo`}]]};Jt.node;var Yt=k(Jt),Xt={name:`database`,size:24,node:[[`ellipse`,{cx:`12`,cy:`5`,rx:`9`,ry:`3`,key:`msslwz`}],[`path`,{d:`M3 5V19A9 3 0 0 0 21 19V5`,key:`1wlel7`}],[`path`,{d:`M3 12A9 3 0 0 0 21 12`,key:`mv7ke4`}]]};Xt.node;var Zt=k(Xt),Qt={name:`download`,size:24,node:[[`path`,{d:`M12 15V3`,key:`m9g1x1`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}],[`path`,{d:`m7 10 5 5 5-5`,key:`brsn70`}]]};Qt.node;var $t=k(Qt),en={name:`external-link`,size:24,node:[[`path`,{d:`M15 3h6v6`,key:`1q9fwt`}],[`path`,{d:`M10 14 21 3`,key:`gplh6r`}],[`path`,{d:`M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6`,key:`a6xqqp`}]]};en.node;var A=k(en),tn={name:`eye`,size:24,node:[[`path`,{d:`M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0`,key:`1nclc0`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]};tn.node;var nn=k(tn),rn={name:`file-text`,size:24,node:[[`path`,{d:`M6 22a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h8a2.4 2.4 0 0 1 1.704.706l3.588 3.588A2.4 2.4 0 0 1 20 8v12a2 2 0 0 1-2 2z`,key:`1oefj6`}],[`path`,{d:`M14 2v5a1 1 0 0 0 1 1h5`,key:`wfsgrz`}],[`path`,{d:`M10 9H8`,key:`b1mrlr`}],[`path`,{d:`M16 13H8`,key:`t4e002`}],[`path`,{d:`M16 17H8`,key:`z1uh3a`}]]};rn.node;var an=k(rn),on={name:`folder`,size:24,node:[[`path`,{d:`M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z`,key:`1kt360`}]]};on.node;var sn=k(on),cn={name:`funnel`,size:24,node:[[`path`,{d:`M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z`,key:`sc7q7i`}]],aliases:[`filter`]};cn.node;var ln=k(cn),un={name:`info`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`10`,key:`1mglay`}],[`path`,{d:`M12 16v-4`,key:`1dtifu`}],[`path`,{d:`M12 8h.01`,key:`e9boi3`}]]};un.node;var dn=k(un),fn={name:`layers`,size:24,node:[[`path`,{d:`M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z`,key:`zw3jo`}],[`path`,{d:`M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12`,key:`1wduqc`}],[`path`,{d:`M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17`,key:`kqbvx6`}]],aliases:[`layers-3`]};fn.node;var pn=k(fn),mn={name:`log-out`,size:24,node:[[`path`,{d:`m16 17 5-5-5-5`,key:`1bji2h`}],[`path`,{d:`M21 12H9`,key:`dn1m92`}],[`path`,{d:`M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4`,key:`1uf3rs`}]]};mn.node;var hn=k(mn),gn={name:`menu`,size:24,node:[[`path`,{d:`M4 5h16`,key:`1tepv9`}],[`path`,{d:`M4 12h16`,key:`1lakjw`}],[`path`,{d:`M4 19h16`,key:`1djgab`}]]};gn.node;var _n=k(gn),vn={name:`minus`,size:24,node:[[`path`,{d:`M5 12h14`,key:`1ays0h`}]]};vn.node;var yn=k(vn),bn={name:`moon`,size:24,node:[[`path`,{d:`M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401`,key:`kfwtm`}]]};bn.node;var xn=k(bn),Sn={name:`plus`,size:24,node:[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`M12 5v14`,key:`s699le`}]]};Sn.node;var Cn=k(Sn),wn={name:`refresh-cw`,size:24,node:[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]};wn.node;var Tn=k(wn),En={name:`search`,size:24,node:[[`path`,{d:`m21 21-4.34-4.34`,key:`14j7rj`}],[`circle`,{cx:`11`,cy:`11`,r:`8`,key:`4ej97u`}]]};En.node;var Dn=k(En),On={name:`settings`,size:24,node:[[`path`,{d:`M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915`,key:`1i5ecw`}],[`circle`,{cx:`12`,cy:`12`,r:`3`,key:`1v7zrd`}]]};On.node;var kn=k(On),An={name:`shield`,size:24,node:[[`path`,{d:`M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z`,key:`oel41y`}]]};An.node;var jn=k(An),Mn={name:`sliders-horizontal`,size:24,node:[[`path`,{d:`M10 5H3`,key:`1qgfaw`}],[`path`,{d:`M12 19H3`,key:`yhmn1j`}],[`path`,{d:`M14 3v4`,key:`1sua03`}],[`path`,{d:`M16 17v4`,key:`1q0r14`}],[`path`,{d:`M21 12h-9`,key:`1o4lsq`}],[`path`,{d:`M21 19h-5`,key:`1rlt1p`}],[`path`,{d:`M21 5h-7`,key:`1oszz2`}],[`path`,{d:`M8 10v4`,key:`tgpxqk`}],[`path`,{d:`M8 12H3`,key:`a7s4jb`}]]};Mn.node;var Nn=k(Mn),Pn={name:`sparkles`,size:24,node:[[`path`,{d:`M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z`,key:`1s2grr`}],[`path`,{d:`M20 2v4`,key:`1rf3ol`}],[`path`,{d:`M22 4h-4`,key:`gwowj6`}],[`circle`,{cx:`4`,cy:`20`,r:`2`,key:`6kqj1y`}]],aliases:[`stars`]};Pn.node;var Fn=k(Pn),In={name:`sun`,size:24,node:[[`circle`,{cx:`12`,cy:`12`,r:`4`,key:`4exip2`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`m4.93 4.93 1.41 1.41`,key:`149t6j`}],[`path`,{d:`m17.66 17.66 1.41 1.41`,key:`ptbguv`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`m6.34 17.66-1.41 1.41`,key:`1m8zz5`}],[`path`,{d:`m19.07 4.93-1.41 1.41`,key:`1shlcs`}]]};In.node;var Ln=k(In),Rn={name:`terminal`,size:24,node:[[`path`,{d:`M12 19h8`,key:`baeox8`}],[`path`,{d:`m4 17 6-6-6-6`,key:`1yngyt`}]]};Rn.node;var zn=k(Rn),Bn={name:`trash`,size:24,node:[[`path`,{d:`M10 11v6`,key:`nco0om`}],[`path`,{d:`M14 11v6`,key:`outv1u`}],[`path`,{d:`M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6`,key:`miytrc`}],[`path`,{d:`M3 6h18`,key:`d0wm0j`}],[`path`,{d:`M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2`,key:`e791ji`}]],aliases:[`trash-2`]};Bn.node;var Vn=k(Bn),Hn={name:`triangle-alert`,size:24,node:[[`path`,{d:`m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3`,key:`wmoenq`}],[`path`,{d:`M12 9v4`,key:`juzpu7`}],[`path`,{d:`M12 17h.01`,key:`p32p05`}]],aliases:[`alert-triangle`]};Hn.node;var Un=k(Hn),Wn={name:`upload`,size:24,node:[[`path`,{d:`M12 3v12`,key:`1x0j5s`}],[`path`,{d:`m17 8-5-5-5 5`,key:`7q97r8`}],[`path`,{d:`M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4`,key:`ih7n3h`}]]};Wn.node;var Gn=k(Wn),Kn={name:`user`,size:24,node:[[`path`,{d:`M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2`,key:`975kel`}],[`circle`,{cx:`12`,cy:`7`,r:`4`,key:`17ys0d`}]]};Kn.node;var qn=k(Kn),Jn={name:`x`,size:24,node:[[`path`,{d:`M18 6 6 18`,key:`1bl5f8`}],[`path`,{d:`m6 6 12 12`,key:`d8bk6v`}]]};Jn.node;var Yn=k(Jn),Xn={"arrow-right":Ct,"arrow-left":xt,"chevron-right":Nt,"chevron-left":jt,"chevron-down":kt,"chevron-up":Ft,"external-link":A,menu:_n,sparkles:Fn,terminal:zn,code:Gt,cpu:Yt,layers:pn,sun:Ln,moon:xn,database:Zt,search:Dn,copy:qt,settings:kn,sliders:Nn,filter:ln,plus:Cn,minus:yn,trash:Vn,refresh:Tn,download:$t,upload:Gn,folder:sn,file:an,user:qn,"log-out":hn,calendar:Tt,clock:Ut,check:Dt,"check-circle":zt,warning:Un,alert:Lt,info:dn,close:Yn,shield:jn,help:Vt,eye:nn},Zn={arrow:Ct,sparkle:Fn,x:Yn,"trash-2":Vn,"alert-triangle":Un,"alert-circle":Lt},Qn={...Xn,...Zn},$n={"arrow-right":{pascalName:`ArrowRight`,category:`Navigation`},"arrow-left":{pascalName:`ArrowLeft`,category:`Navigation`},"chevron-right":{pascalName:`ChevronRight`,category:`Navigation`},"chevron-left":{pascalName:`ChevronLeft`,category:`Navigation`},"chevron-down":{pascalName:`ChevronDown`,category:`Navigation`},"chevron-up":{pascalName:`ChevronUp`,category:`Navigation`},"external-link":{pascalName:`ExternalLink`,category:`Navigation`},menu:{pascalName:`Menu`,category:`Navigation`},sparkles:{pascalName:`Sparkles`,category:`System`},terminal:{pascalName:`Terminal`,category:`System`},code:{pascalName:`Code2`,category:`System`},cpu:{pascalName:`Cpu`,category:`System`},layers:{pascalName:`Layers`,category:`System`},sun:{pascalName:`Sun`,category:`System`},moon:{pascalName:`Moon`,category:`System`},database:{pascalName:`Database`,category:`System`},search:{pascalName:`Search`,category:`Interface`},copy:{pascalName:`Copy`,category:`Interface`},settings:{pascalName:`Settings`,category:`Interface`},sliders:{pascalName:`SlidersHorizontal`,category:`Interface`},filter:{pascalName:`Filter`,category:`Interface`},plus:{pascalName:`Plus`,category:`Interface`},minus:{pascalName:`Minus`,category:`Interface`},trash:{pascalName:`Trash2`,category:`Interface`},refresh:{pascalName:`RefreshCw`,category:`Interface`},download:{pascalName:`Download`,category:`Interface`},upload:{pascalName:`Upload`,category:`Interface`},folder:{pascalName:`Folder`,category:`Interface`},file:{pascalName:`FileText`,category:`Interface`},user:{pascalName:`User`,category:`Interface`},"log-out":{pascalName:`LogOut`,category:`Interface`},calendar:{pascalName:`Calendar`,category:`Interface`},clock:{pascalName:`Clock`,category:`Interface`},check:{pascalName:`Check`,category:`Status`},"check-circle":{pascalName:`CheckCircle2`,category:`Status`},warning:{pascalName:`AlertTriangle`,category:`Status`},alert:{pascalName:`AlertCircle`,category:`Status`},info:{pascalName:`Info`,category:`Status`},close:{pascalName:`X`,category:`Status`},shield:{pascalName:`Shield`,category:`Status`},help:{pascalName:`HelpCircle`,category:`Status`},eye:{pascalName:`Eye`,category:`Status`}},er=Object.entries(Xn).map(([e,t])=>({name:e,pascalName:$n[e].pascalName,category:$n[e].category,component:t}));function j({name:e,icon:t,size:n=18,strokeWidth:r=1.8,className:i,...a}){let o=e?Qn[e]:void 0;if(!t&&!o){let t=`[Icon] Unknown icon name "${String(e)}". Add it to iconMap in src/components/icon-registry.ts or pass an explicit \`icon\` prop.`;console.error(t)}return(0,D.jsx)(t??o??pn,{size:n,strokeWidth:r,className:i,"aria-hidden":`true`,...a})}function tr({title:e=`System Overview`,description:t=`Real-time telemetry and resource saturation across clusters.`,className:n=``}){let[r,i]=(0,_.useState)(`24h`);return(0,D.jsxs)(`div`,{className:`stack-lg ${n}`,children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`div`,{className:`row-xs`,style:{marginBottom:`var(--space-1)`},children:[(0,D.jsx)(rt,{variant:`positive`,children:`Live Telemetry`}),(0,D.jsx)(rt,{variant:`outline`,children:`All Regions`})]}),(0,D.jsx)(`h3`,{style:{margin:`var(--space-1) 0`,fontSize:`var(--text-lg)`,fontWeight:700},children:e}),(0,D.jsx)(`p`,{style:{margin:0,color:`var(--muted-foreground)`,fontSize:`var(--text-xs)`},children:t})]}),(0,D.jsx)(`div`,{className:`row-xs`,children:[`24h`,`7d`,`30d`].map(e=>(0,D.jsx)(`button`,{className:`button ${r===e?`secondary`:`ghost`}`,style:{padding:`var(--space-1) var(--space-3)`,fontSize:`var(--text-xs)`},onClick:()=>i(e),children:e},e))})]}),(0,D.jsxs)(`div`,{className:`grid-3`,children:[(0,D.jsx)(at,{title:`Throughput`,value:r===`24h`?`14.2k req/s`:r===`7d`?`12.8k req/s`:`11.5k req/s`,change:`+18.4%`,trend:`up`,caption:`vs previous period`,icon:(0,D.jsx)(j,{name:`sparkles`,size:16})}),(0,D.jsx)(at,{title:`P99 Latency`,value:r===`24h`?`18ms`:r===`7d`?`22ms`:`25ms`,change:`-4.2ms`,trend:`up`,caption:`edge distribution`,icon:(0,D.jsx)(j,{name:`clock`,size:16})}),(0,D.jsx)(at,{title:`Error Rate`,value:`0.008%`,change:`-0.002%`,trend:`up`,caption:`within SLA (<0.05%)`,icon:(0,D.jsx)(j,{name:`shield`,size:16})})]}),(0,D.jsxs)(Ze,{children:[(0,D.jsxs)(Qe,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,children:[(0,D.jsx)($e,{children:`Resource Utilization`}),(0,D.jsx)(`span`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:`Cluster: canary-prod-01`})]}),(0,D.jsx)(et,{children:`Compute, memory, and persistent volume headroom.`})]}),(0,D.jsx)(tt,{children:(0,D.jsxs)(`div`,{className:`stack-md`,children:[(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-1)`},children:[(0,D.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,color:`var(--foreground)`,fontWeight:500},children:`Worker CPU Saturation`}),(0,D.jsx)(`span`,{className:`mono`,style:{fontSize:`var(--text-xs)`,color:`var(--primary)`},children:`48%`})]}),(0,D.jsx)(ot,{value:48})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-1)`},children:[(0,D.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,color:`var(--foreground)`,fontWeight:500},children:`Memory Allocation (16 GB Pool)`}),(0,D.jsx)(`span`,{className:`mono`,style:{fontSize:`var(--text-xs)`,color:`var(--primary)`},children:`74%`})]}),(0,D.jsx)(ot,{value:74})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-1)`},children:[(0,D.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,color:`var(--foreground)`,fontWeight:500},children:`Network Ingress Bandwidth`}),(0,D.jsx)(`span`,{className:`mono`,style:{fontSize:`var(--text-xs)`,color:`var(--chart-2)`},children:`28%`})]}),(0,D.jsx)(ot,{value:28})]})]})})]})]})}function nr(){let e=(0,_.useRef)(new Set);return(0,_.useEffect)(()=>{let t=e.current;return()=>{t.forEach(clearTimeout),t.clear()}},[]),{schedule:(0,_.useCallback)((t,n)=>{let r=setTimeout(()=>{e.current.delete(r),t()},n);return e.current.add(r),r},[]),clear:(0,_.useCallback)(()=>{e.current.forEach(clearTimeout),e.current.clear()},[])}}function rr({checked:e,defaultChecked:t=!1,onCheckedChange:n,disabled:r=!1,className:i,id:a,"aria-label":o}){let[s,c]=(0,_.useState)(t),l=e!==void 0,u=l?e:s;return(0,D.jsx)(`button`,{type:`button`,role:`switch`,"aria-checked":u,disabled:r,id:a,"aria-label":o,className:O(`switch-root`,u&&`checked`,i),onClick:()=>{if(r)return;let e=!u;l||c(e),n?.(e)},style:{opacity:r?.5:1,cursor:r?`not-allowed`:`pointer`},children:(0,D.jsx)(`span`,{className:`switch-thumb`})})}function ir({variant:e=`info`,icon:t,className:n,children:r,...i}){return(0,D.jsxs)(`div`,{className:O(`alert`,`alert-${e}`,n),role:`alert`,...i,children:[t&&(0,D.jsx)(`div`,{className:`alert-icon`,style:{display:`flex`,alignItems:`center`},children:t}),(0,D.jsx)(`div`,{className:`stack-xs`,style:{flex:1,minWidth:0},children:r})]})}function ar({className:e,children:t,...n}){return(0,D.jsx)(`h5`,{className:O(e),style:{margin:0,fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`,lineHeight:1.4},...n,children:t})}function or({className:e,...t}){return(0,D.jsx)(`p`,{className:O(e),style:{margin:0,fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,lineHeight:1.5},...t})}var sr=new Set([`button`,`input`,`select`,`textarea`,`summary`]);function cr(e){let t=e.props;return t.tabIndex===void 0?t.onClick===void 0?typeof e.type==`string`?e.type===`a`?t.href!==void 0:sr.has(e.type):!1:!0:t.tabIndex>=0}function lr({content:e,children:t,className:n}){let r=(0,_.useId)(),[i,a]=(0,_.useState)(!1),o=typeof t!=`string`&&typeof t!=`number`&&(0,_.isValidElement)(t)&&t.type!==_.Fragment?t:(0,D.jsx)(`span`,{children:t}),s=o.props[`aria-describedby`],c=s?`${s} ${r}`:r,l=(0,_.cloneElement)(o,{"aria-describedby":c}),u=!cr(o);return(0,D.jsxs)(`span`,{className:O(`tooltip-wrapper`,n),tabIndex:u?0:void 0,onMouseEnter:()=>a(!0),onMouseLeave:()=>a(!1),onFocus:()=>a(!0),onBlur:()=>a(!1),onKeyDown:e=>{e.key===`Escape`&&a(!1)},children:[l,(0,D.jsx)(`span`,{id:r,className:`tooltip-box`,role:`tooltip`,"aria-hidden":!i,"data-open":i?`true`:`false`,children:e})]})}function ur({className:e,...t}){return(0,D.jsx)(`kbd`,{className:O(`kbd-tag`,e),...t})}function dr(){let[e,t]=(0,_.useState)(!1),[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(!0),[c,l]=(0,_.useState)(!0),[u,d]=(0,_.useState)(!1),f=`nsk_live_98a72ef01bc34d89a2`,{schedule:p}=nr();return(0,D.jsxs)(`div`,{className:`stack-lg`,children:[(0,D.jsxs)(Ze,{children:[(0,D.jsxs)(Qe,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,children:[(0,D.jsx)($e,{children:`Environment & Access Keys`}),(0,D.jsx)(rt,{variant:`primary`,children:`Production`})]}),(0,D.jsx)(et,{children:`Manage authentication credentials and runtime ingress access.`})]}),(0,D.jsx)(tt,{children:(0,D.jsxs)(`div`,{className:`stack-md`,children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`label`,{style:{display:`block`,fontSize:`var(--text-xs)`,fontWeight:600,marginBottom:`var(--space-2)`},children:`Production Secret API Key`}),(0,D.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,D.jsxs)(`div`,{style:{flex:1,background:`var(--secondary)`,border:`1px solid var(--border)`,borderRadius:`var(--radius-md)`,padding:`var(--space-2) var(--space-3)`,fontFamily:`var(--font-mono)`,fontSize:`var(--text-xs)`,color:`var(--foreground)`,display:`flex`,alignItems:`center`,justifyContent:`space-between`},children:[(0,D.jsx)(`span`,{children:e?f:`••••••••••••••••••••••••••••••••`}),(0,D.jsx)(`button`,{className:`icon-button`,style:{padding:4},onClick:()=>t(!e),"aria-label":e?`Hide API key`:`Show API key`,children:(0,D.jsx)(j,{name:`eye`,size:14})})]}),(0,D.jsx)(lr,{content:`Copy key to clipboard`,children:(0,D.jsxs)(`button`,{className:`button secondary`,onClick:()=>{navigator.clipboard?.writeText(f),r(!0),p(()=>r(!1),2e3)},children:[(0,D.jsx)(j,{name:n?`check`:`copy`,size:14}),n?`Copied`:`Copy`]})})]})]}),(0,D.jsxs)(ir,{variant:`info`,children:[(0,D.jsx)(ar,{children:`Zero-Trust Rotation Enabled`}),(0,D.jsx)(or,{children:`Keys are automatically renewed every 90 days. Next scheduled rotation in 14 days.`})]})]})})]}),(0,D.jsxs)(Ze,{children:[(0,D.jsxs)(Qe,{children:[(0,D.jsx)($e,{children:`Deployment & Runtime Safeguards`}),(0,D.jsx)(et,{children:`Fine-tune canary threshold tolerances and telemetry logging.`})]}),(0,D.jsx)(tt,{children:(0,D.jsxs)(`div`,{className:`stack-md`,children:[(0,D.jsxs)(`div`,{className:`flex-between`,children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`div`,{style:{fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`},children:`Automated Canary Progression`}),(0,D.jsx)(`div`,{style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,marginTop:2},children:`Gradually increase traffic from 5% to 100% based on error budget.`})]}),(0,D.jsx)(rr,{checked:o,onCheckedChange:s})]}),(0,D.jsxs)(`div`,{className:`flex-between`,style:{paddingTop:`var(--space-3)`,borderTop:`1px solid var(--border)`},children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`div`,{style:{fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`},children:`Detailed OpenTelemetry Tracing`}),(0,D.jsx)(`div`,{style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,marginTop:2},children:`Emit span metrics for all inbound HTTP and gRPC remote procedure calls.`})]}),(0,D.jsx)(rr,{checked:c,onCheckedChange:l})]}),(0,D.jsxs)(`div`,{className:`flex-between`,style:{paddingTop:`var(--space-3)`,borderTop:`1px solid var(--border)`},children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`div`,{style:{fontSize:`var(--text-sm)`,fontWeight:600,color:`var(--foreground)`},children:`Immediate Circuit-Breaker Rollback`}),(0,D.jsx)(`div`,{style:{fontSize:`var(--text-xs)`,color:`var(--muted-foreground)`,marginTop:2},children:`Instantly revert to prior green build if P99 latency breaches 100ms.`})]}),(0,D.jsx)(rr,{checked:u,onCheckedChange:d})]})]})}),(0,D.jsxs)(nt,{children:[(0,D.jsxs)(`span`,{style:{fontSize:`var(--text-3xs)`,color:`var(--muted-foreground)`},children:[`Shortcut: `,(0,D.jsx)(ur,{children:`Ctrl`}),` + `,(0,D.jsx)(ur,{children:`S`}),` to persist`]}),(0,D.jsxs)(`div`,{className:`row-xs`,style:{marginLeft:`auto`},children:[(0,D.jsx)(`button`,{className:`button ghost`,children:`Discard`}),(0,D.jsxs)(`button`,{className:`button primary`,onClick:()=>{a(!0),p(()=>a(!1),2500)},children:[(0,D.jsx)(j,{name:i?`check`:`sparkles`,size:14}),i?`Saved Successfully`:`Save Changes`]})]})]})]})]})}function fr({className:e,...t}){return(0,D.jsx)(`div`,{className:`ui-table-container`,children:(0,D.jsx)(`table`,{className:O(`ui-table`,e),...t})})}function pr({className:e,...t}){return(0,D.jsx)(`thead`,{className:O(e),...t})}function mr({className:e,...t}){return(0,D.jsx)(`tbody`,{className:O(e),...t})}function hr({className:e,...t}){return(0,D.jsx)(`tr`,{className:O(e),...t})}function gr({className:e,...t}){return(0,D.jsx)(`th`,{className:O(e),...t})}function _r({className:e,...t}){return(0,D.jsx)(`td`,{className:O(e),...t})}function vr({className:e,...t}){return(0,D.jsx)(`div`,{className:O(`empty-state`,e),...t})}function yr({children:e,className:t}){return(0,D.jsx)(`div`,{className:O(`empty-state-icon`,t),children:e})}function br({className:e,children:t,...n}){return(0,D.jsx)(`h3`,{className:O(e),style:{margin:`0 0 var(--space-2)`,fontSize:`var(--text-lg)`,fontWeight:700,color:`var(--foreground)`,letterSpacing:`-0.02em`},...n,children:t})}function xr({className:e,...t}){return(0,D.jsx)(`p`,{className:O(e),style:{margin:`0 0 var(--space-5)`,fontSize:`var(--text-sm)`,color:`var(--muted-foreground)`,maxWidth:`420px`,lineHeight:1.6},...t})}function Sr({className:e,...t}){return(0,D.jsx)(`div`,{className:O(`row-sm`,e),...t})}var Cr=[{id:`1`,name:`api-gateway`,region:`us-east-1`,status:`healthy`,latency:`12ms`,memory:`128 MB`,instances:8},{id:`2`,name:`vector-indexer`,region:`eu-central-1`,status:`healthy`,latency:`34ms`,memory:`890 MB`,instances:4},{id:`3`,name:`model-inference`,region:`us-west-2`,status:`scaling`,latency:`78ms`,memory:`4.2 GB`,instances:16},{id:`4`,name:`session-broker`,region:`us-east-1`,status:`healthy`,latency:`8ms`,memory:`64 MB`,instances:6},{id:`5`,name:`analytics-worker`,region:`ap-northeast-1`,status:`degraded`,latency:`142ms`,memory:`1.8 GB`,instances:2},{id:`6`,name:`audit-logger`,region:`eu-west-1`,status:`healthy`,latency:`19ms`,memory:`210 MB`,instances:3}];function wr(){let[e,t]=(0,_.useState)(``),[n,r]=(0,_.useState)(`all`),i=(0,_.useMemo)(()=>Cr.filter(t=>{let r=t.name.toLowerCase().includes(e.toLowerCase())||t.region.toLowerCase().includes(e.toLowerCase()),i=n===`all`||t.status===n;return r&&i}),[e,n]);return(0,D.jsxs)(`div`,{className:`stack-md`,children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,D.jsxs)(`div`,{className:`icon-search-bar`,style:{maxWidth:320},children:[(0,D.jsx)(j,{name:`search`,size:15}),(0,D.jsx)(`input`,{type:`text`,placeholder:`Filter services or regions...`,value:e,onChange:e=>t(e.target.value),className:`icon-search-input`}),e&&(0,D.jsx)(`button`,{className:`icon-clear-btn`,onClick:()=>t(``),children:(0,D.jsx)(j,{name:`close`,size:13})})]}),(0,D.jsx)(`div`,{className:`row-xs`,children:[`all`,`healthy`,`scaling`,`degraded`].map(e=>(0,D.jsx)(`button`,{className:`button ${n===e?`secondary`:`ghost`}`,style:{padding:`var(--space-1) var(--space-3)`,fontSize:`var(--text-xs)`,textTransform:`capitalize`},onClick:()=>r(e),children:e},e))})]}),i.length>0?(0,D.jsxs)(fr,{children:[(0,D.jsx)(pr,{children:(0,D.jsxs)(hr,{children:[(0,D.jsx)(gr,{children:`Service Name`}),(0,D.jsx)(gr,{children:`Region`}),(0,D.jsx)(gr,{children:`Status`}),(0,D.jsx)(gr,{children:`P99 Latency`}),(0,D.jsx)(gr,{children:`Memory`}),(0,D.jsx)(gr,{children:`Nodes`})]})}),(0,D.jsx)(mr,{children:i.map(e=>(0,D.jsxs)(hr,{children:[(0,D.jsx)(_r,{style:{fontWeight:600},children:(0,D.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,D.jsx)(`span`,{style:{width:7,height:7,borderRadius:`50%`,background:e.status===`healthy`?`var(--chart-2)`:e.status===`scaling`?`var(--primary)`:`var(--destructive)`,boxShadow:`0 0 8px ${e.status===`healthy`?`var(--chart-2)`:e.status===`scaling`?`var(--primary)`:`var(--destructive)`}`}}),e.name]})}),(0,D.jsx)(_r,{children:(0,D.jsx)(ur,{children:e.region})}),(0,D.jsx)(_r,{children:(0,D.jsx)(rt,{variant:e.status===`healthy`?`positive`:e.status===`scaling`?`primary`:`destructive`,children:e.status})}),(0,D.jsx)(_r,{className:`mono`,style:{color:e.status===`degraded`?`var(--destructive)`:`var(--primary)`},children:e.latency}),(0,D.jsx)(_r,{className:`mono`,style:{color:`var(--muted-foreground)`},children:e.memory}),(0,D.jsx)(_r,{className:`mono`,style:{color:`var(--foreground)`},children:e.instances})]},e.id))})]}):(0,D.jsxs)(vr,{children:[(0,D.jsx)(yr,{children:(0,D.jsx)(j,{name:`search`,size:24})}),(0,D.jsx)(br,{children:`No matching services`}),(0,D.jsxs)(xr,{children:[`No active nodes or services match the current filter query "`,e,`".`]})]}),(0,D.jsxs)(`div`,{className:`flex-between muted`,style:{fontSize:`var(--text-3xs)`,padding:`0 var(--space-2)`},children:[(0,D.jsxs)(`span`,{children:[`Showing `,i.length,` of `,Cr.length,` deployed services`]}),(0,D.jsx)(`span`,{className:`mono`,children:`Synced live via cluster coordinator`})]})]})}var Tr=`a[href], button:not([disabled]), textarea:not([disabled]), input:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex="-1"])`;function Er(e,t){if(e.key!==`Tab`||!t)return;let n=Array.from(t.querySelectorAll(Tr));if(n.length===0){e.preventDefault(),t.focus();return}let r=n[0],i=n[n.length-1];if(!r||!i)return;let a=document.activeElement;e.shiftKey?(a===r||a===t)&&(e.preventDefault(),i.focus()):a===i&&(e.preventDefault(),r.focus())}function Dr(e,t){(0,_.useEffect)(()=>{if(!e)return;let n=document.activeElement,r=document.body.style.overflow;return document.body.style.overflow=`hidden`,t.current?.focus(),()=>{document.body.style.overflow=r,n&&document.contains(n)&&n.focus()}},[e,t])}var Or=(0,_.createContext)(null);function kr(){let e=(0,_.useContext)(Or);if(!e)throw Error(`Overlay components must be used within an (Dialog/Sheet)`);return e}var Ar={background:`none`,border:0,padding:0,font:`inherit`,color:`inherit`,cursor:`pointer`};function jr({next:e,setOpen:t,children:n,className:r,onClick:i,style:a,asChild:o=!1,...s}){let c=n=>{i?.(n),n.defaultPrevented||t(e)};if(o&&(0,_.isValidElement)(n)){let e=n,t={onClick:c};return r&&(t.className=O(e.props.className,r)),a&&(t.style={...e.props.style,...a}),(0,_.cloneElement)(e,t)}return(0,D.jsx)(`button`,{...s,type:`button`,className:r,style:{...Ar,...a},onClick:c,children:n})}function Mr({children:e,open:t,defaultOpen:n=!1,onOpenChange:r}){let[i,a]=(0,_.useState)(n),o=t!==void 0,s=o?t:i,[c,l]=(0,_.useState)(!1),[u,d]=(0,_.useState)(!1),f=(0,_.useId)(),p=(0,_.useId)(),m=(0,_.useCallback)(e=>{o||a(e),r?.(e)},[o,r]),h=(0,_.useCallback)(e=>l(e),[]),g=(0,_.useCallback)(e=>d(e),[]),v=(0,_.useMemo)(()=>({open:s,setOpen:m,titleId:f,descriptionId:p,hasTitle:c,hasDescription:u,registerTitle:h,registerDescription:g}),[s,m,f,p,c,u,h,g]);return(0,D.jsx)(Or.Provider,{value:v,children:e})}function Nr(e){let{setOpen:t}=kr();return(0,D.jsx)(jr,{...e,setOpen:t,next:!0})}function Pr({children:e,className:t,backdropClassName:n,panelClassName:r,closeButtonLabel:i}){let{open:a,setOpen:o,titleId:s,descriptionId:c,hasTitle:l,hasDescription:u}=kr(),d=(0,_.useRef)(null);return Dr(a,d),(0,_.useEffect)(()=>{if(!a)return;let e=e=>{e.key===`Escape`&&o(!1)};return document.addEventListener(`keydown`,e),()=>document.removeEventListener(`keydown`,e)},[a,o]),a?(0,D.jsx)(`div`,{className:n,onClick:()=>o(!1),children:(0,D.jsxs)(`div`,{ref:d,role:`dialog`,"aria-modal":`true`,"aria-labelledby":l?s:void 0,"aria-describedby":u?c:void 0,tabIndex:-1,className:O(r,t),onKeyDown:e=>{Er(e,d.current)},onClick:e=>e.stopPropagation(),children:[(0,D.jsx)(`button`,{type:`button`,className:`dialog-close-btn`,onClick:()=>o(!1),"aria-label":i,children:`✕`}),e]})}):null}function Fr({className:e,style:t,...n}){return(0,D.jsx)(`div`,{className:O(`stack-xs`,e),style:t,...n})}function Ir({className:e,style:t,...n}){let{titleId:r,registerTitle:i}=kr();return(0,_.useEffect)(()=>(i(!0),()=>i(!1)),[i]),(0,D.jsx)(`h2`,{id:r,className:O(e),style:t,...n})}function Lr({className:e,style:t,...n}){let{descriptionId:r,registerDescription:i}=kr();return(0,_.useEffect)(()=>(i(!0),()=>i(!1)),[i]),(0,D.jsx)(`p`,{id:r,className:O(e),style:t,...n})}function Rr({className:e,style:t,...n}){return(0,D.jsx)(`div`,{className:O(`flex-between`,e),style:{paddingTop:`var(--space-4)`,borderTop:`1px solid var(--border)`,gap:`var(--space-3)`,...t},...n})}function zr(e){let{setOpen:t}=kr();return(0,D.jsx)(jr,{...e,setOpen:t,next:!1})}function Br(e){return(0,D.jsx)(Mr,{...e})}function Vr(e){return(0,D.jsx)(Nr,{...e})}function Hr({children:e,className:t}){return(0,D.jsx)(Pr,{backdropClassName:`dialog-backdrop`,panelClassName:`dialog-panel`,closeButtonLabel:`Close dialog`,className:t,children:e})}function Ur({className:e,style:t,...n}){let r={marginBottom:`var(--space-4)`,...t};return(0,D.jsx)(Fr,{className:e,style:r,...n})}function Wr({className:e,style:t,...n}){let r={margin:0,fontSize:`var(--text-xl)`,fontWeight:700,color:`var(--foreground)`,letterSpacing:`-0.03em`,...t};return(0,D.jsx)(Ir,{className:e,style:r,...n})}function Gr({className:e,style:t,...n}){let r={margin:0,fontSize:`var(--text-sm)`,color:`var(--muted-foreground)`,lineHeight:1.5,...t};return(0,D.jsx)(Lr,{className:e,style:r,...n})}function Kr({className:e,style:t,...n}){let r={marginTop:`var(--space-6)`,...t};return(0,D.jsx)(Rr,{className:e,style:r,...n})}function qr(e){return(0,D.jsx)(zr,{...e})}function Jr(){let[e,t]=(0,_.useState)(!1),[n,r]=(0,_.useState)(!0),[i,a]=(0,_.useState)(!1),[o,s]=(0,_.useState)(!1),[c,l]=(0,_.useState)(0),[u,d]=(0,_.useState)(!1),{schedule:f,clear:p}=nr(),{schedule:m}=nr();return(0,_.useEffect)(()=>{e||p()},[e,p]),(0,D.jsxs)(Br,{open:e,onOpenChange:t,children:[(0,D.jsx)(Vr,{asChild:!0,children:(0,D.jsxs)(`button`,{className:`button primary`,children:[(0,D.jsx)(j,{name:`sparkles`,size:15}),` Promote Release to Canary`]})}),(0,D.jsxs)(Hr,{children:[(0,D.jsxs)(Ur,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{marginBottom:`var(--space-2)`},children:[(0,D.jsx)(Wr,{children:`Canary Rollout: release-2026.09.12`}),(0,D.jsx)(rt,{variant:`primary`,children:`v2.4.0`})]}),(0,D.jsxs)(Gr,{children:[`Targeting production cluster `,(0,D.jsx)(`code`,{style:{color:`var(--primary)`,fontFamily:`var(--font-mono)`},children:`canary-prod-01`}),`.`]})]}),(0,D.jsx)(`div`,{className:`stack-md`,style:{margin:`var(--space-4) 0`},children:u?(0,D.jsxs)(ir,{variant:`positive`,children:[(0,D.jsx)(ar,{children:`Deployment Succeeded!`}),(0,D.jsx)(or,{children:`Build is now receiving live canary traffic. Telemetry reports 0 errors and 14ms latency.`})]}):(0,D.jsxs)(D.Fragment,{children:[(0,D.jsxs)(ir,{variant:`warning`,children:[(0,D.jsx)(ar,{children:`Canary Traffic Notice`}),(0,D.jsx)(or,{children:`This deployment will divert 10% of production ingress traffic to the new build.`})]}),(0,D.jsxs)(`div`,{className:`stack-sm`,style:{background:`var(--secondary)`,padding:`var(--space-4)`,borderRadius:`var(--radius-lg)`},children:[(0,D.jsxs)(`div`,{className:`flex-between`,children:[(0,D.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,fontWeight:500},children:`Gradual Traffic Ingress (10% → 50% → 100%)`}),(0,D.jsx)(rr,{checked:n,onCheckedChange:r})]}),(0,D.jsxs)(`div`,{className:`flex-between`,style:{paddingTop:`var(--space-2)`,borderTop:`1px solid var(--border)`},children:[(0,D.jsx)(`span`,{style:{fontSize:`var(--text-xs)`,fontWeight:500},children:`Bypass Pre-Flight Synthetic Probes`}),(0,D.jsx)(rr,{checked:i,onCheckedChange:a})]})]}),o&&(0,D.jsxs)(`div`,{className:`stack-xs`,children:[(0,D.jsx)(ot,{value:c,label:`Applying Canary Weights...`}),(0,D.jsx)(`span`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:`Streaming build manifests to regional edge nodes...`})]})]})}),(0,D.jsx)(Kr,{children:u?(0,D.jsxs)(`button`,{className:`button primary`,style:{width:`100%`},onClick:()=>{t(!1),m(()=>{s(!1),l(0),d(!1)},300)},children:[(0,D.jsx)(j,{name:`check`,size:14}),` Done`]}):(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(qr,{asChild:!0,children:(0,D.jsx)(`button`,{className:`button secondary`,disabled:o,children:`Cancel`})}),(0,D.jsxs)(`button`,{className:`button primary`,onClick:()=>{s(!0),l(15),f(()=>l(45),500),f(()=>l(85),1e3),f(()=>{l(100),s(!1),d(!0)},1500)},disabled:o,children:[(0,D.jsx)(j,{name:o?`refresh`:`arrow-right`,size:14}),o?`Deploying...`:`Confirm Rollout`]})]})})]})]})}function Yr({activePattern:e,onPatternChange:t}={}){let[n,r]=(0,_.useState)(`metrics`),i=e??n,a=e=>{r(e),t?.(e)};return(0,D.jsxs)(`div`,{className:`stack-lg`,children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,D.jsx)(`div`,{className:`segmented`,children:Xe.map(e=>(0,D.jsxs)(`button`,{type:`button`,className:i===e.id?`selected`:``,"aria-pressed":i===e.id,onClick:()=>a(e.id),children:[(0,D.jsx)(j,{name:e.icon,size:15}),(0,D.jsx)(`span`,{children:e.label})]},e.id))}),(0,D.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,D.jsx)(rt,{variant:`outline`,children:`Interactive Component`}),(0,D.jsx)(rt,{variant:`primary`,children:`Composable`})]})]}),(0,D.jsxs)(`div`,{className:`surface-card`,style:{padding:`var(--space-6)`,borderRadius:`var(--radius-xl)`},children:[i===`metrics`&&(0,D.jsx)(tr,{}),i===`settings`&&(0,D.jsx)(dr,{}),i===`table`&&(0,D.jsx)(wr,{}),i===`deploy`&&(0,D.jsx)(`div`,{className:`stack-md`,style:{maxWidth:640,margin:`0 auto`,textAlign:`center`,padding:`var(--space-6) 0`},children:(0,D.jsxs)(Ze,{children:[(0,D.jsxs)(Qe,{children:[(0,D.jsx)($e,{children:`Canary Deployment Orchestrator`}),(0,D.jsx)(et,{children:`A complete interactive modal flow demonstrating Dialog, Alert, Switch, and Progress components.`})]}),(0,D.jsx)(tt,{children:(0,D.jsx)(`div`,{style:{padding:`var(--space-6) 0`},children:(0,D.jsx)(Jr,{})})})]})})]})]})}function Xr(){let[e,t]=je(),n=e.get(`pattern`),r=Xe.some(e=>e.id===n)?n:`metrics`;return(0,D.jsx)(Yr,{activePattern:r,onPatternChange:e=>{t(t=>{let n=new URLSearchParams(t);return n.set(`pattern`,e),n},{replace:!0})}})}function Zr({variant:e=`secondary`,className:t=``,children:n,...r}){return(0,D.jsx)(`button`,{className:`button ${e} ${t}`.trim(),...r,children:n})}function Qr({href:e,variant:t=`secondary`,className:n=``,children:r}){return(0,D.jsx)(Me,{href:e,className:`button ${t} ${n}`.trim(),children:r})}var $r=(0,_.createContext)(null);function ei(){let e=(0,_.useContext)($r);if(!e)throw Error(`Tabs components must be used within `);return e}function ti(e,t,n){return`${e}-${t}-${n.replace(/[^A-Za-z0-9_-]+/g,`-`)}`}function ni({defaultValue:e=``,value:t,onValueChange:n,children:r,className:i}){let[a,o]=(0,_.useState)(e),s=(0,_.useId)(),c=t!==void 0,l=c?t:a;return(0,D.jsx)($r.Provider,{value:{value:l,setValue:e=>{c||o(e),n?.(e)},baseId:s},children:(0,D.jsx)(`div`,{className:O(`ui-tabs-root`,i),children:r})})}var ri=new Set([`ArrowRight`,`ArrowLeft`,`Home`,`End`]);function ii({className:e,onKeyDown:t,...n}){let{setValue:r}=ei();return(0,D.jsx)(`div`,{className:O(`ui-tabs-list`,e),role:`tablist`,"aria-orientation":`horizontal`,onKeyDown:e=>{if(t?.(e),e.defaultPrevented||!ri.has(e.key))return;let n=Array.from(e.currentTarget.querySelectorAll(`[role="tab"]:not([disabled])`));if(n.length===0)return;let i=n.indexOf(document.activeElement),a=n.findIndex(e=>e.getAttribute(`aria-selected`)===`true`),o=i>=0?i:a;if(o<0)return;let s;switch(e.key){case`ArrowRight`:s=(o+1)%n.length;break;case`ArrowLeft`:s=(o-1+n.length)%n.length;break;case`Home`:s=0;break;default:s=n.length-1}let c=n[s];if(c===void 0)return;let l=c.dataset.value;l!==void 0&&(e.preventDefault(),c.focus(),r(l))},...n})}function ai({value:e,className:t,children:n,...r}){let{value:i,setValue:a,baseId:o}=ei(),s=i===e;return(0,D.jsx)(`button`,{type:`button`,id:ti(o,`trigger`,e),role:`tab`,"aria-selected":s,"aria-controls":ti(o,`content`,e),tabIndex:s?0:-1,"data-value":e,className:O(`ui-tabs-trigger`,s&&`active`,t),onClick:()=>a(e),...r,children:n})}function oi({value:e,className:t,children:n,...r}){let{value:i,baseId:a}=ei(),o=i===e;return(0,D.jsx)(`div`,{id:ti(a,`content`,e),role:`tabpanel`,"aria-labelledby":ti(a,`trigger`,e),tabIndex:0,hidden:!o,className:O(`ui-tabs-content`,t),...r,children:n})}function si({variant:e=`text`,width:t,height:n,className:r,style:i,...a}){return(0,D.jsx)(`div`,{className:O(`skeleton`,e===`circle`?`skeleton-circle`:e===`rect`?`skeleton-rect`:`skeleton-text`,r),style:{width:t===void 0?void 0:typeof t==`number`?`${t}px`:t,height:n===void 0?void 0:typeof n==`number`?`${n}px`:n,...i},"aria-hidden":`true`,...a})}var ci={xs:`var(--space-5)`,sm:`var(--space-6)`,md:`var(--space-7)`,lg:`var(--space-9)`},li={xs:`var(--text-3xs)`,sm:`var(--text-2xs)`,md:`var(--text-xs)`,lg:`var(--text-base)`},ui={xs:`var(--space-1)`,sm:`var(--space-1)`,md:`var(--space-2)`,lg:`var(--space-2)`},di={online:`var(--chart-2)`,away:`var(--chart-3)`,offline:`var(--muted-foreground)`};function fi(e){return e.trim().split(/\s+/).filter(Boolean).slice(0,2).map(e=>e.charAt(0)).join(``).toUpperCase()||`?`}function pi({name:e,src:t,size:n=`md`,status:r,className:i}){let a=ci[n];return(0,D.jsxs)(`span`,{className:O(`flex-center`,i),role:t?void 0:`img`,"aria-label":t?void 0:e||`Avatar`,style:{position:`relative`,flexShrink:0,width:a,height:a,borderRadius:`var(--radius-pill)`,background:`color-mix(in srgb, var(--primary) 16%, var(--background))`,color:`var(--primary)`,fontFamily:`var(--font-sans)`,fontSize:li[n],fontWeight:700,lineHeight:1,letterSpacing:`0.02em`,userSelect:`none`},children:[t?(0,D.jsx)(`img`,{src:t,alt:e,style:{display:`block`,width:`100%`,height:`100%`,objectFit:`cover`,borderRadius:`var(--radius-pill)`}}):(0,D.jsx)(`span`,{"aria-hidden":`true`,children:fi(e)}),r&&(0,D.jsx)(`span`,{"aria-hidden":`true`,style:{position:`absolute`,right:0,bottom:0,boxSizing:`content-box`,width:ui[n],height:ui[n],borderRadius:`var(--radius-pill)`,background:di[r],border:`2px solid var(--background)`}})]})}var mi={xs:{width:`var(--space-3)`,height:`var(--space-3)`,borderWidth:`1px`},sm:{width:`var(--space-4)`,height:`var(--space-4)`,borderWidth:`2px`},md:{width:`var(--space-6)`,height:`var(--space-6)`,borderWidth:`2px`},lg:{width:`var(--space-8)`,height:`var(--space-8)`,borderWidth:`3px`}},hi={position:`absolute`,width:`1px`,height:`1px`,padding:0,margin:`-1px`,overflow:`hidden`,clip:`rect(0 0 0 0)`,whiteSpace:`nowrap`,borderWidth:0};function gi({size:e=`md`,label:t,className:n}){return(0,D.jsxs)(`div`,{role:`status`,"aria-live":`polite`,className:O(`ui-spinner`,`ui-spinner-${e}`,n),children:[(0,D.jsx)(`span`,{"aria-hidden":`true`,style:{display:`inline-block`,boxSizing:`border-box`,borderStyle:`solid`,borderColor:`var(--border)`,borderTopColor:`var(--primary)`,borderRadius:`50%`,animation:`spin 0.8s linear infinite`,...mi[e]}}),t?(0,D.jsx)(`span`,{className:`visually-hidden`,style:hi,children:t}):null]})}function _i({examples:e,tabs:t,filter:n=``,activeTab:r,onTabChange:i}){let a=e.filter(e=>`${e.name} ${e.label}`.toLowerCase().includes(n.toLowerCase()));return(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(`div`,{className:`tabs`,children:t.map(e=>(0,D.jsx)(`button`,{className:e===r?`tab active`:`tab`,onClick:()=>i?.(e),children:e},e))}),(0,D.jsxs)(`div`,{className:`showcase`,children:[(0,D.jsxs)(`div`,{className:`showcase-head`,children:[(0,D.jsx)(`span`,{className:`eyebrow`,children:`Interactive states`}),(0,D.jsx)(`span`,{className:`mono muted`,children:`button.tsx`})]}),(0,D.jsx)(`div`,{className:`button-matrix`,children:a.map(e=>(0,D.jsxs)(`div`,{className:`button-row`,children:[(0,D.jsx)(`span`,{className:`row-label`,children:e.name}),(0,D.jsx)(Zr,{variant:e.variant,children:e.label}),(0,D.jsx)(Zr,{variant:e.variant,className:`hover-state`,children:e.label}),(0,D.jsx)(Zr,{variant:e.variant,className:`icon-only`,"aria-label":`${e.name} icon button`,children:(0,D.jsx)(j,{name:`copy`,size:15})}),(0,D.jsxs)(Zr,{variant:e.variant,className:`loading`,children:[(0,D.jsx)(gi,{size:`xs`}),`Loading`]})]},e.name))}),(0,D.jsxs)(`div`,{className:`showcase-foot`,children:[(0,D.jsx)(`span`,{className:`muted`,children:`Density`}),(0,D.jsxs)(`button`,{className:`density active`,children:[`Compact `,(0,D.jsx)(`span`,{children:`32px`})]}),(0,D.jsxs)(`button`,{className:`density`,children:[`Default `,(0,D.jsx)(`span`,{children:`40px`})]}),(0,D.jsxs)(`span`,{className:`foot-check`,children:[(0,D.jsx)(j,{name:`check`,size:14}),` Keyboard ready`]})]})]})]})}var vi=[`Preview`,`API reference`,`Usage`],yi=[{name:`Primary`,label:`Deploy changes`,variant:`primary`},{name:`Secondary`,label:`View activity`,variant:`secondary`},{name:`Destructive`,label:`Delete project`,variant:`danger`},{name:`Ghost`,label:`Cancel`,variant:`ghost`}],bi=[{name:`Primary`,color:`var(--primary)`,value:`lab(89.9% -47.9 -15.7)`},{name:`Background`,color:`var(--background)`,value:`lab(0% 0 0)`},{name:`Card`,color:`var(--card)`,value:`lab(0.9% 0 0)`},{name:`Destructive`,color:`var(--destructive)`,value:`lab(54.6% 71.7 50.9)`},{name:`Chart 1`,color:`var(--chart-1)`,value:`lab(89.9% -47.9 -15.7)`},{name:`Chart 2`,color:`var(--chart-2)`,value:`lab(67.0% -58.3 19.5)`},{name:`Chart 3`,color:`var(--chart-3)`,value:`lab(72.7% 31.9 97.9)`},{name:`Chart 4`,color:`var(--chart-4)`,value:`lab(52.0% 66.1 -78.2)`}];function xi(){let[e,t]=(0,_.useState)(`Preview`);return(0,D.jsx)(_i,{examples:yi,tabs:vi,activeTab:e,onTabChange:t})}var Si=er,Ci=[`All`,`Navigation`,`Interface`,`System`,`Status`];function wi(){let[e,t]=(0,_.useState)(`All`),[n,r]=(0,_.useState)(``),[i,a]=(0,_.useState)(20),[o,s]=(0,_.useState)(null),{schedule:c}=nr(),l=(0,_.useMemo)(()=>Si.filter(t=>{let r=e===`All`||t.category===e,i=t.name.toLowerCase().includes(n.toLowerCase())||t.pascalName.toLowerCase().includes(n.toLowerCase());return r&&i}),[e,n]),u=e=>{let t=`<${e.pascalName} size={${i}} />`;navigator.clipboard?.writeText(t),s(e.name),c(()=>s(null),2e3)};return(0,D.jsxs)(`div`,{className:`icon-matrix-container`,children:[(0,D.jsxs)(`div`,{className:`icon-matrix-header`,children:[(0,D.jsxs)(`div`,{className:`icon-search-bar`,children:[(0,D.jsx)(j,{name:`search`,size:16}),(0,D.jsx)(`input`,{type:`text`,placeholder:`Search icons (e.g. arrow, check, sparkles)...`,"aria-label":`Search icons`,value:n,onChange:e=>r(e.target.value),className:`icon-search-input`}),n&&(0,D.jsx)(`button`,{className:`icon-clear-btn`,onClick:()=>r(``),children:(0,D.jsx)(j,{name:`close`,size:14})})]}),(0,D.jsxs)(`div`,{className:`icon-size-picker`,children:[(0,D.jsx)(`span`,{className:`mono muted`,children:`Size:`}),[16,20,24].map(e=>(0,D.jsxs)(`button`,{className:`icon-size-btn ${i===e?`active`:``}`,onClick:()=>a(e),children:[e,`px`]},e))]})]}),(0,D.jsx)(`div`,{className:`icon-category-tabs`,children:Ci.map(n=>(0,D.jsxs)(`button`,{className:`icon-cat-btn ${e===n?`active`:``}`,onClick:()=>t(n),children:[n,(0,D.jsx)(`span`,{className:`icon-cat-count`,children:n===`All`?Si.length:Si.filter(e=>e.category===n).length})]},n))}),(0,D.jsx)(`div`,{className:`icon-grid`,children:l.map(e=>{let t=o===e.name;return(0,D.jsxs)(`button`,{className:`icon-tile ${t?`copied`:``}`,onClick:()=>u(e),title:`Click to copy <${e.pascalName} />`,children:[(0,D.jsx)(`div`,{className:`icon-tile-glyph`,children:t?(0,D.jsx)(j,{name:`check`,size:i,className:`accent`}):(0,D.jsx)(e.component,{size:i,strokeWidth:1.8})}),(0,D.jsx)(`span`,{className:`icon-tile-name`,children:e.name}),(0,D.jsx)(`span`,{className:`icon-tile-action`,children:t?`Copied!`:(0,D.jsx)(ur,{children:`Copy`})})]},e.name)})}),l.length===0&&(0,D.jsxs)(`div`,{className:`empty-state`,children:[(0,D.jsx)(`div`,{className:`empty-state-icon`,children:(0,D.jsx)(j,{name:`search`,size:24})}),(0,D.jsx)(`h4`,{style:{margin:`0 0 var(--space-2)`},children:`No icons found`}),(0,D.jsxs)(`p`,{className:`muted`,style:{margin:0,fontSize:`var(--text-xs)`},children:[`No icon matches "`,n,`". You can use any of Lucide's 1,400+ icons directly via`,` `,(0,D.jsx)(`code`,{children:`lucide-react`}),`.`]})]}),(0,D.jsx)(`div`,{className:`icon-matrix-footer`,children:(0,D.jsxs)(`div`,{className:`icon-footer-pill`,children:[(0,D.jsx)(rt,{variant:`outline`,children:`lucide-react`}),(0,D.jsxs)(`span`,{children:[`Over 1,400+ SVG icons available. Fully tree-shaken and styled via `,(0,D.jsx)(`code`,{children:`currentColor`}),`.`]})]})})]})}function Ti(){return(0,D.jsx)(wi,{})}function Ei({tokens:e,onCopy:t}){return(0,D.jsx)(`div`,{className:`color-grid`,children:e.map(e=>(0,D.jsxs)(`div`,{className:`color-card`,children:[(0,D.jsx)(`div`,{className:`swatch`,style:{background:e.color}}),(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`strong`,{children:e.name}),(0,D.jsx)(`span`,{className:`mono`,children:e.value})]}),(0,D.jsx)(`button`,{className:`copy-icon`,onClick:()=>t?.(e.value),"aria-label":`Copy ${e.name} token`,children:(0,D.jsx)(j,{name:`copy`,size:14})})]},e.name))})}var Di=`pnpm add @northstar/ui @northstar/tokens`;function Oi(){navigator.clipboard?.writeText(Di)}function ki(){return(0,D.jsx)(Ei,{tokens:bi,onCopy:Oi})}var Ai=[{token:`--text-hero`,rem:`clamp(2.625rem, 5vw, 4.375rem)`,px:`42→70px`,role:`Display / Hero Title`,sample:`Calm, capable design.`},{token:`--text-2xl`,rem:`1.75rem`,px:`28px`,role:`Section Headlines`,sample:`Structured for AI Uniformity`},{token:`--text-xl`,rem:`1.5625rem`,px:`25px`,role:`Sub-headlines & Major Cards`,sample:`Fast, token-enforced iteration`},{token:`--text-lg`,rem:`1.3125rem`,px:`21px`,role:`Card Titles & Dialog Heads`,sample:`Zero hardcoded pixel values`},{token:`--text-base`,rem:`1rem`,px:`16px`,role:`Lede Copy & Lead Sentences`,sample:`The baseline font size scaled by --root-font-size.`},{token:`--text-md`,rem:`0.875rem`,px:`14px`,role:`Longform Body Text`,sample:`Engineered for dense technical dashboards and documentation.`},{token:`--text-sm`,rem:`0.75rem`,px:`12px`,role:`Form Controls & Descriptions`,sample:`Input labels, table rows, and secondary details.`},{token:`--text-xs`,rem:`0.6875rem`,px:`11px`,role:`Action Buttons & Nav Items`,sample:`Action buttons, status badges, and sidebar navigation.`},{token:`--text-2xs`,rem:`0.625rem`,px:`10px`,role:`Eyebrows & Section Indices`,sample:`METADATA LABELS & CATEGORY EYEBROWS`},{token:`--text-3xs`,rem:`0.5625rem`,px:`9px`,role:`Micro Badges & Mono Tags`,sample:`01 / APPLICATION PATTERNS`}];function ji(){return(0,D.jsxs)(`div`,{className:`stack-lg`,children:[(0,D.jsxs)(`div`,{className:`grid-2`,children:[(0,D.jsxs)(Ze,{children:[(0,D.jsxs)(Qe,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,children:[(0,D.jsx)($e,{children:`Sans-Serif Primary Family`}),(0,D.jsx)(rt,{variant:`primary`,children:`Manrope`})]}),(0,D.jsx)(et,{children:`Modern geometric grotesque optimized for high-density UI and numeral legibility.`})]}),(0,D.jsx)(tt,{children:(0,D.jsxs)(`div`,{style:{fontFamily:`var(--font-sans)`,fontSize:`var(--text-lg)`,fontWeight:600},children:[`ABCDEFGHIJKLMNOPQRSTUVWXYZ`,(0,D.jsx)(`br`,{}),`abcdefghijklmnopqrstuvwxyz`,(0,D.jsx)(`br`,{}),`0123456789 & @ # % $ /`]})})]}),(0,D.jsxs)(Ze,{children:[(0,D.jsxs)(Qe,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,children:[(0,D.jsx)($e,{children:`Monospace Code Family`}),(0,D.jsx)(rt,{variant:`secondary`,children:`DM Mono`})]}),(0,D.jsx)(et,{children:`Tabular numerals and proportional spacing for code blocks, tokens, and telemetry.`})]}),(0,D.jsx)(tt,{children:(0,D.jsxs)(`div`,{className:`mono`,style:{fontSize:`var(--text-md)`,color:`var(--primary)`},children:[`const system = 'northstar'`,(0,D.jsx)(`br`,{}),`latency: 14.2ms | memory: 128MB`,(0,D.jsx)(`br`,{}),`0123456789 ()=>{}[]`]})})]})]}),(0,D.jsxs)(Ze,{children:[(0,D.jsxs)(Qe,{children:[(0,D.jsxs)(`div`,{className:`flex-between`,children:[(0,D.jsx)($e,{children:`Modular Rem-Based Type Scale`}),(0,D.jsxs)(`div`,{className:`row-xs`,children:[(0,D.jsx)(`span`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:`Root:`}),(0,D.jsx)(ur,{children:`112%`})]})]}),(0,D.jsxs)(et,{children:[`Scales uniformly via `,(0,D.jsx)(`code`,{children:`--root-font-size`}),`. Built on a 9px → 70px responsive rhythm.`]})]}),(0,D.jsx)(tt,{children:(0,D.jsx)(`div`,{className:`stack-md`,children:Ai.map(e=>(0,D.jsxs)(`div`,{style:{display:`grid`,gridTemplateColumns:`160px 80px 1fr`,alignItems:`baseline`,gap:`var(--space-4)`,padding:`var(--space-3) 0`,borderBottom:`1px solid var(--border)`},children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`code`,{style:{fontSize:`var(--text-xs)`,color:`var(--primary)`,fontFamily:`var(--font-mono)`},children:e.token}),(0,D.jsx)(`div`,{style:{fontSize:`var(--text-3xs)`,color:`var(--muted-foreground)`},children:e.role})]}),(0,D.jsx)(`div`,{className:`mono muted`,style:{fontSize:`var(--text-3xs)`},children:e.px}),(0,D.jsx)(`div`,{style:{fontSize:`var(${e.token})`,fontWeight:e.token.includes(`hero`)||e.token.includes(`2xl`)?800:500,lineHeight:1.25,overflow:`hidden`,textOverflow:`ellipsis`,whiteSpace:`nowrap`},children:e.sample})]},e.token))})})]})]})}function Mi(){return(0,D.jsx)(ji,{})}function Ni({label:e,hint:t,children:n,readOnlyLabel:r}){return(0,D.jsxs)(`label`,{className:`field`,children:[(0,D.jsxs)(`span`,{children:[e,r&&(0,D.jsx)(`em`,{children:r})]}),n,(0,D.jsx)(`small`,{children:t})]})}function Pi(e){return(0,D.jsx)(`input`,{...e})}function Fi(){let[e,t]=(0,_.useState)(!1);return(0,D.jsxs)(`div`,{className:`forms-grid`,children:[(0,D.jsx)(Ni,{label:`Project name`,hint:`Use a memorable name for your workspace.`,children:(0,D.jsx)(Pi,{defaultValue:`Northstar Console`})}),(0,D.jsx)(Ni,{label:`API key`,readOnlyLabel:`read only`,hint:`Stored securely in your environment.`,children:(0,D.jsxs)(`div`,{className:`input-with-action`,children:[(0,D.jsx)(Pi,{type:e?`text`:`password`,defaultValue:`nsk_live_8f2a1d90`,readOnly:!0}),(0,D.jsx)(`button`,{onClick:()=>t(!e),"aria-label":`Show API key`,children:(0,D.jsx)(j,{name:`eye`,size:16})})]})}),(0,D.jsxs)(`label`,{className:`toggle-field`,children:[(0,D.jsxs)(`span`,{children:[(0,D.jsx)(`b`,{children:`Enable notifications`}),(0,D.jsx)(`small`,{children:`Get updates about deployments and incidents.`})]}),(0,D.jsx)(rr,{defaultChecked:!0,"aria-label":`Toggle notifications`})]}),(0,D.jsxs)(`div`,{className:`toggle-field`,children:[(0,D.jsxs)(`span`,{children:[(0,D.jsx)(`b`,{children:`Primitives in action`}),(0,D.jsx)(`small`,{children:`Spinner, Avatar and Switch — token-driven, theme-aware components/ui primitives.`})]}),(0,D.jsxs)(`span`,{className:`row-md`,children:[(0,D.jsx)(pi,{name:`Mats Tornberg`,size:`sm`,status:`online`}),(0,D.jsx)(pi,{name:`Grace Hopper`,size:`sm`}),(0,D.jsx)(gi,{size:`sm`,label:`Loading session`})]})]}),(0,D.jsxs)(`div`,{className:`toggle-field`,children:[(0,D.jsxs)(`span`,{children:[(0,D.jsx)(`b`,{children:`Tabs primitive`}),(0,D.jsx)(`small`,{children:`Roving tabindex, arrow-key navigation, aria-selected wiring — try the keyboard.`})]}),(0,D.jsxs)(ni,{defaultValue:`preview`,className:`stack-xs`,children:[(0,D.jsxs)(ii,{children:[(0,D.jsx)(ai,{value:`preview`,children:`Preview`}),(0,D.jsx)(ai,{value:`code`,children:`Code`})]}),(0,D.jsx)(oi,{value:`preview`,children:(0,D.jsx)(`small`,{children:`Token-driven preview pane.`})}),(0,D.jsx)(oi,{value:`code`,children:(0,D.jsxs)(`small`,{children:[`import `,`{ Tabs }`,` from components/ui`]})})]})]})]})}var Ii=`pnpm add @northstar/ui @northstar/tokens`,Li=[[`pink`,`import`],[`plain`,` { Button } `],[`pink`,`from`],[`green`,` '@northstar/ui'`],[`plain`,` - -export function `],[`blue`,`DeployAction`],[`plain`,`() { - return ( -`],[`plain`,` - ) -}`]];function Ri(){let[e,t]=(0,_.useState)(!1),{schedule:n}=nr();return(0,D.jsxs)(`div`,{className:`code-card`,children:[(0,D.jsxs)(`div`,{className:`code-head`,children:[(0,D.jsx)(`span`,{className:`mono muted`,children:`button.tsx`}),(0,D.jsxs)(`button`,{className:`copy-button`,onClick:()=>{navigator.clipboard?.writeText(Ii),t(!0),n(()=>t(!1),1600)},children:[(0,D.jsx)(j,{name:e?`check`:`copy`,size:14}),e?`Copied`:`Copy code`]})]}),(0,D.jsx)(`pre`,{children:(0,D.jsx)(`code`,{children:Li.map(([e,t],n)=>e===`plain`?(0,D.jsx)(`span`,{children:t},n):(0,D.jsx)(`span`,{className:e,children:t},n))})})]})}function zi(){return(0,D.jsx)(Ri,{})}function Bi({title:e=`Quiet power, shipped weekly.`,kicker:t=`NORTHSTAR / RELEASE NOTES`}){return(0,D.jsxs)(`div`,{className:`markdown-card`,children:[(0,D.jsxs)(`div`,{className:`markdown-toolbar`,children:[(0,D.jsx)(`span`,{className:`eyebrow`,children:`Preview`}),(0,D.jsx)(`span`,{className:`mono muted`,children:`release-notes.md`})]}),(0,D.jsxs)(`article`,{className:`markdown-body`,children:[(0,D.jsx)(`span`,{className:`md-kicker`,children:t}),(0,D.jsx)(`h3`,{children:e}),(0,D.jsx)(`p`,{children:`Our components help teams move quickly without making the interface feel rushed.`}),(0,D.jsxs)(`div`,{className:`md-callout`,children:[(0,D.jsx)(`span`,{className:`callout-mark`,children:`✦`}),(0,D.jsxs)(`p`,{children:[(0,D.jsx)(`strong`,{children:`New in 0.8.2`}),(0,D.jsx)(`br`,{}),`Button focus rings now respect your theme while keeping a dependable contrast ratio.`]})]}),(0,D.jsx)(`h4`,{children:`What changed`}),(0,D.jsxs)(`ul`,{children:[(0,D.jsxs)(`li`,{children:[`Added `,(0,D.jsx)(`code`,{children:`accent-subtle`}),` surface token`]}),(0,D.jsx)(`li`,{children:`Improved keyboard navigation in menus`}),(0,D.jsx)(`li`,{children:`Reduced layout shift during loading states`})]}),(0,D.jsxs)(`div`,{className:`md-table`,children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`span`,{children:`Token`}),(0,D.jsx)(`span`,{children:`Value`}),(0,D.jsx)(`span`,{children:`Role`})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`code`,{children:`surface-1`}),(0,D.jsx)(`span`,{children:`#111118`}),(0,D.jsx)(`span`,{children:`Elevated panels`})]}),(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`code`,{children:`accent`}),(0,D.jsx)(`span`,{className:`md-accent`,children:`#A69BFF`}),(0,D.jsx)(`span`,{children:`Interactive focus`})]})]})]})]})}function Vi(){return(0,D.jsx)(Bi,{})}var Hi=[1,2,3,4,5,6,7,8];function Ui({fileName:e=`theme.ts`,language:t=`TypeScript`}){return(0,D.jsxs)(`div`,{className:`editor-card`,children:[(0,D.jsxs)(`div`,{className:`editor-tabs`,children:[(0,D.jsx)(`span`,{className:`editor-dot`}),(0,D.jsx)(`span`,{className:`editor-tab active`,children:e}),(0,D.jsx)(`span`,{className:`editor-tab`,children:`tokens.css`}),(0,D.jsx)(`span`,{className:`editor-actions`,children:`● ● ●`})]}),(0,D.jsxs)(`div`,{className:`editor-body`,children:[(0,D.jsx)(`div`,{className:`line-numbers`,children:Hi.map(e=>(0,D.jsxs)(`span`,{children:[e,(0,D.jsx)(`br`,{})]},e))}),(0,D.jsx)(`pre`,{children:(0,D.jsxs)(`code`,{children:[(0,D.jsx)(`span`,{className:`cm-comment`,children:`// A calm editor for focused work`}),` -`,(0,D.jsx)(`span`,{className:`cm-keyword`,children:`export const`}),` `,(0,D.jsx)(`span`,{className:`cm-variable`,children:`theme`}),` = `,`{`,` -`,` `,(0,D.jsx)(`span`,{className:`cm-property`,children:`name`}),`: `,(0,D.jsx)(`span`,{className:`cm-string`,children:`'northstar-dark'`}),`,`,` -`,` `,(0,D.jsx)(`span`,{className:`cm-property`,children:`colors`}),`: `,`{`,` -`,` `,(0,D.jsx)(`span`,{className:`cm-property`,children:`accent`}),`: `,(0,D.jsx)(`span`,{className:`cm-string`,children:`'#a69bff'`}),`,`,` -`,` `,(0,D.jsx)(`span`,{className:`cm-property`,children:`keyword`}),`: `,(0,D.jsx)(`span`,{className:`cm-string`,children:`'#e58bff'`}),`,`,` -`,` `,(0,D.jsx)(`span`,{className:`cm-property`,children:`comment`}),`: `,(0,D.jsx)(`span`,{className:`cm-string`,children:`'#666572'`}),` -`,` `,`}`,` -`,`}`]})})]}),(0,D.jsxs)(`div`,{className:`editor-status`,children:[(0,D.jsx)(`span`,{children:`Ln 4, Col 18`}),(0,D.jsxs)(`span`,{children:[t,` · UTF-8`]}),(0,D.jsxs)(`span`,{className:`editor-ready`,children:[(0,D.jsx)(j,{name:`check`,size:12}),` No issues`]})]})]})}function Wi(){return(0,D.jsx)(Ui,{})}function Gi(e){let t=e??window.location.pathname+window.location.search;window.location.href=`/api/auth/login?returnTo=${encodeURIComponent(t)}`}function Ki(){let[e,t]=(0,_.useState)(`loading`),[n,r]=(0,_.useState)(null);return(0,_.useEffect)(()=>{let e=!0;return fetch(`/api/auth/session`).then(e=>e.ok?e.json():{authenticated:!1,user:null}).then(n=>{e&&(n.authenticated&&n.user?(r(n.user),t(`authenticated`)):(r(null),t(`anonymous`)))}).catch(()=>{e&&(r(null),t(`anonymous`))}),()=>{e=!1}},[]),{status:e,user:n,login:Gi,signOut:(0,_.useCallback)(async()=>{try{await fetch(`/api/auth/logout`,{method:`POST`})}catch{}r(null),t(`anonymous`)},[])}}var qi=class extends Error{status;code;constructor(e,t,n){super(n),this.name=`ApiError`,this.status=e,this.code=t}},Ji=``;async function Yi(e,t){let n;try{n=await fetch(`${Ji}${e}`,{...t,headers:{"Content-Type":`application/json`,...t?.headers}})}catch(e){throw new qi(0,`network`,`Could not reach the API (${e instanceof Error?e.message:String(e)}). Is the Go server running?`)}if(n.status===204)return;let r=await n.json().catch(()=>null);if(!n.ok){let e=r?.error;throw new qi(n.status,e?.code??`unknown`,e?.message??n.statusText)}return r}var Xi=Object.prototype.hasOwnProperty;function Zi(e,t){var n,r;if(e===t)return!0;if(e&&t&&(n=e.constructor)===t.constructor){if(n===Date)return e.getTime()===t.getTime();if(n===RegExp)return e.toString()===t.toString();if(n===Array){if((r=e.length)===t.length)for(;r--&&Zi(e[r],t[r]););return r===-1}if(!n||typeof e==`object`){for(n in r=0,e)if(Xi.call(e,n)&&++r&&!Xi.call(t,n)||!(n in t)||!Zi(e[n],t[n]))return!1;return Object.keys(t).length===r}}return e!==e&&t!==t}var Qi=new WeakMap,$i=()=>{},ea=Object,M=e=>e===void 0,N=e=>typeof e==`function`,ta=(e,t)=>({...e,...t}),na=e=>N(e.then),ra={},ia={},aa=`undefined`,oa=typeof window!=aa,sa=typeof document!=aa,ca=oa&&`Deno`in window,la=()=>oa&&typeof window.requestAnimationFrame!=aa,P=(e,t)=>{let n=Qi.get(e);return[()=>!M(t)&&e.get(t)||ra,r=>{if(!M(t)){let i=e.get(t);t in ia||(ia[t]=i),n[5](t,ta(i,r),i||ra)}},n[6],()=>!M(t)&&t in ia?ia[t]:!M(t)&&e.get(t)||ra]},F=!0,ua=()=>F,[da,fa]=oa&&window.addEventListener?[window.addEventListener.bind(window),window.removeEventListener.bind(window)]:[$i,$i],pa=()=>{let e=sa&&document.visibilityState;return M(e)||e!==`hidden`},ma=e=>(sa&&document.addEventListener(`visibilitychange`,e),da(`focus`,e),()=>{sa&&document.removeEventListener(`visibilitychange`,e),fa(`focus`,e)}),ha=e=>{let t=()=>{F=!0,e()},n=()=>{F=!1};return da(`online`,t),da(`offline`,n),()=>{fa(`online`,t),fa(`offline`,n)}},ga={isOnline:ua,isVisible:pa},_a={initFocus:ma,initReconnect:ha},va=!_.useId,ya=!oa||ca,ba=e=>la()?window.requestAnimationFrame(e):setTimeout(e,1),xa=ya?_.useEffect:_.useLayoutEffect,Sa=typeof navigator<`u`&&navigator.connection,Ca=!ya&&Sa&&([`slow-2g`,`2g`].includes(Sa.effectiveType)||Sa.saveData),wa=new WeakMap,Ta=e=>ea.prototype.toString.call(e),Ea=(e,t)=>e===`[object ${t}]`,Da=0,Oa=e=>{let t=typeof e,n=Ta(e),r=Ea(n,`Date`),i=Ea(n,`RegExp`),a=Ea(n,`Object`),o,s;if(ea(e)===e&&!r&&!i){if(o=wa.get(e),o)return o;if(o=++Da+`~`,wa.set(e,o),Array.isArray(e)){for(o=`@`,s=0;s{if(N(e))try{e=e()}catch{e=``}let t=e;return e=typeof e==`string`?e:(Array.isArray(e)?e.length:e)?Oa(e):``,[e,t]},Aa=0,ja=()=>++Aa;async function Ma(...e){let[t,n,r,i]=e,a=ta({populateCache:!0,throwOnError:!0},typeof i==`boolean`?{revalidate:i}:i||{}),o=a.populateCache,s=a.rollbackOnError,c=a.optimisticData,l=e=>typeof s==`function`?s(e):s!==!1,u=a.throwOnError;if(N(n)){let e=n,r=[],i=t.keys();for(let n of i)!/^\$(inf|sub)\$/.test(n)&&e(t.get(n)._k)&&r.push(n);return Promise.all(r.map(d))}return d(n);async function d(n){let[i]=ka(n);if(!i)return;let[s,d]=P(t,i),[f,p,m,h]=Qi.get(t),g=()=>{let e=f[i];return(N(a.revalidate)?a.revalidate(s().data,n):a.revalidate!==!1)&&(delete m[i],delete h[i],e&&e[0])?e[0](2).then(()=>s().data):s().data};if(e.length<3)return g();let _=r,v,y=!1,b=ja();p[i]=[b,0];let ee=!M(c),te=s(),ne=te.data,re=te._c,x=M(re)?ne:re;if(ee&&(c=N(c)?c(x,ne):c,d({data:c,_c:x})),N(_))try{_=_(x)}catch(e){v=e,y=!0}if(_&&na(_)){if(_=await _.catch(e=>{v=e,y=!0}),b!==p[i][0]){if(y)throw v;return _}y&&ee&&l(v)&&(o=!0,d({data:x,_c:void 0}))}if(o&&(y||(N(o)?d({data:o(_,x),error:void 0,_c:void 0}):d({data:_,error:void 0,_c:void 0}))),p[i][1]=ja(),Promise.resolve(g()).then(()=>{d({_c:void 0})}),y){if(u)throw v;return}return _}}var Na=(e,t)=>{for(let n in e)e[n][0]&&e[n][0](t)},Pa=(e,t)=>{if(!Qi.has(e)){let n=ta(_a,t),r=Object.create(null),i=Ma.bind(void 0,e),a=$i,o=Object.create(null),s=(e,t)=>{let n=o[e]||[];return o[e]=n,n.push(t),()=>{let e=n.indexOf(t);e>=0&&(n[e]=n[n.length-1],n.pop())}},c=(t,n,r)=>{e.set(t,n);let i=o[t];if(i)for(let e of i)e(n,r)},l=t=>{let n=Qi.get(e),[,i,a,s]=n,c=ja();n[8]++;for(let e in a)delete a[e];for(let e in s)delete s[e];for(let e in i)i[e]=[c,c];let l={};for(let t of[...e.keys()]){let n=e.get(t);e.delete(t);let r=o[t];if(r)for(let e of r)e(l,n)}let u=!t||t.revalidate!==!1;for(let e in r){let t=r[e];for(let e=0;e{if(!Qi.has(e)&&(Qi.set(e,[r,Object.create(null),Object.create(null),Object.create(null),i,c,s,l,0]),!ya)){let t=n.initFocus(setTimeout.bind(void 0,Na.bind(void 0,r,0))),i=n.initReconnect(setTimeout.bind(void 0,Na.bind(void 0,r,1)));a=()=>{t&&t(),i&&i(),Qi.delete(e)}}};return u(),[e,i,u,a,l]}let n=Qi.get(e);return[e,n[4],void 0,void 0,n[7]]},Fa=(e,t,n,r,i)=>{let a=n.errorRetryCount,o=i.retryCount,s=~~((Math.random()+.5)*(1<<(o<8?o:8)))*n.errorRetryInterval;!M(a)&&o>a||setTimeout(r,s,i)},I=Zi,[Ia,La,,,Ra]=Pa(new Map),za=ta({onLoadingSlow:$i,onSuccess:$i,onError:$i,onErrorRetry:Fa,onDiscarded:$i,revalidateOnFocus:!0,revalidateOnReconnect:!0,revalidateIfStale:!0,shouldRetryOnError:!0,errorRetryInterval:Ca?1e4:5e3,focusThrottleInterval:5e3,dedupingInterval:2e3,loadingTimeout:Ca?5e3:3e3,compare:I,isPaused:()=>!1,cache:Ia,mutate:La,unload:Ra,fallback:{}},ga),Ba=(e,t)=>{let n=ta(e,t);if(t){let{use:r,fallback:i,cacheData:a}=e,{use:o,fallback:s,cacheData:c}=t;r&&o&&(n.use=r.concat(o)),i&&s&&(n.fallback=ta(i,s)),a&&c&&(n.cacheData=ta(a,c))}return n},Va=(0,_.createContext)({}),Ha=e=>{let{value:t}=e,n=(0,_.useContext)(Va),r=N(t),i=(0,_.useMemo)(()=>r?t(n):t,[r,n,t]),a=(0,_.useMemo)(()=>r?i:Ba(n,i),[r,n,i]),o=i&&i.provider,s=(0,_.useRef)(void 0);o&&!s.current&&(s.current=Pa(o(a.cache||Ia),i));let c=s.current;return c&&(a.cache=c[0],a.mutate=c[1],a.unload=c[4]),xa(()=>{if(c)return c[2]&&c[2](),c[3]},[]),(0,_.createElement)(Va.Provider,ta(e,{value:a}))},Ua=oa&&window.__SWR_DEVTOOLS_USE__,Wa=Ua?window.__SWR_DEVTOOLS_USE__:[],Ga=()=>{Ua&&(window.__SWR_DEVTOOLS_REACT__=_.default)},Ka=e=>N(e[1])?[e[0],e[1],e[2]||{}]:[e[0],null,(e[1]===null?e[2]:e[1])||{}],qa=()=>{let e=(0,_.useContext)(Va);return(0,_.useMemo)(()=>ta(za,e),[e])},Ja=Wa.concat(e=>(t,n,r)=>e(t,n&&((...e)=>{let[r]=ka(t),[,,,i]=Qi.get(Ia);if(r.startsWith(`$inf$`))return n(...e);let a=i[r];return M(a)?n(...e):(delete i[r],a)}),r)),Ya=e=>function(...t){let n=qa(),[r,i,a]=Ka(t),o=Ba(n,a),s=e,{use:c}=o,l=(c||[]).concat(Ja);for(let e=l.length;e--;)s=l[e](s);return s(r,i||o.fetcher||null,o)},Xa=(e,t,n)=>{let r=t[e]||(t[e]=[]);return r.push(n),()=>{let e=r.indexOf(n);e>=0&&(r[e]=r[r.length-1],r.pop())}};Ga();var Za=_.use||(e=>{switch(e.status){case`pending`:throw e;case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:throw e.status=`pending`,e.then(t=>{e.status=`fulfilled`,e.value=t},t=>{e.status=`rejected`,e.reason=t}),e}}),Qa={dedupe:!0},$a=(e,t,n)=>t?e.get(t)?.has(n)===!0:!1,eo=(e,t,n)=>{if(!t)return;let r=e.get(t);r||(r=new Set,e.set(t,r)),r.add(n)},to=({value:e,getCacheData:t,canCommit:n,setCache:r})=>{let i=e=>{n()&&M(t())&&r(e)};Promise.resolve(e).then(e=>{i({data:e,error:void 0})},e=>{i({error:e})})},no=Promise.resolve(void 0);no.status=`fulfilled`,no.value=void 0;var ro=()=>$i,io=(e,t,n)=>{let{cache:r,compare:i,suspense:a,fallbackData:o,revalidateOnMount:s,revalidateIfStale:c,refreshInterval:l,refreshWhenHidden:u,refreshWhenOffline:d,keepPreviousData:f,strictServerPrefetchWarning:p}=n,[m,h,g,v]=Qi.get(r),[y,b]=ka(e),te=(0,_.useRef)(!1),ne=(0,_.useRef)(!1),re=(0,_.useRef)(y),x=(0,_.useRef)(t),ie=(0,_.useRef)(n),S=()=>ie.current,ae=()=>S().isVisible()&&S().isOnline(),[C,oe,se,ce]=P(r,y),le=(0,_.useRef)({}).current,ue=M(o)?M(n.fallback)?void 0:n.fallback[y]:o,de=n.cacheData,fe=y?de?.[y]:void 0,pe=y?v[y]:void 0,me=M(pe)&&!M(fe),he=me?fe:pe,ge=(e,t)=>{for(let n in le){let r=n;if(r===`data`){if(!i(e[r],t[r])&&(!M(e[r])||!i(T,t[r])))return!1}else if(t[r]!==e[r])return!1}return!0},_e=!te.current,ve=(0,_.useMemo)(()=>{let e=C(),n=ce(),r=e=>{let n=ta(e);return delete n._k,(()=>{if(!y||!t||S().isPaused())return!1;if(_e&&!M(s))return s;let e=M(ue)?n.data:ue;return a&&me&&M(e)?!1:M(e)||c})()?{isValidating:!0,isLoading:!0,...n}:n},i=r(e),o=e===n?i:r(n),l=i;return[()=>{let e=r(C());return ge(e,l)?(l.data=e.data,l.isLoading=e.isLoading,l.isValidating=e.isValidating,l.error=e.error,l):(l=e,e)},()=>o]},[r,y]),ye=(0,ee.useSyncExternalStore)((0,_.useCallback)(e=>se(y,(t,n)=>{ge(n,t)||e()}),[r,y]),ve[0],ve[1]),be=m[y]&&m[y].length>0,xe=ye.data,Se=M(xe)?ue&&na(ue)?Za(ue):ue:xe,Ce=ye.error,we=(0,_.useRef)(Se),Te=(0,_.useRef)(void 0),Ee=Te.current;Ee||(Ee=new WeakMap,Te.current=Ee);let w=(0,_.useRef)(null),T=f?M(xe)?M(we.current)?Se:we.current:xe:Se,De=y&&M(Se),Oe=(0,_.useRef)(null);!ya&&(0,ee.useSyncExternalStore)(ro,()=>(Oe.current=!1,Oe),()=>(Oe.current=!0,Oe));let ke=Oe.current;p&&ke&&!a&&De&&console.warn(`Missing pre-initiated data for serialized key "${y}" during server-side rendering. Data fetching should be initiated on the server and provided to SWR via fallback data. You can set "strictServerPrefetchWarning: false" to disable this warning.`);let Ae=!y||!t||S().isPaused()||be&&!M(Ce)?!1:_e&&!M(s)?s:a&&me&&De?!1:a?!M(Se)&&c:M(Se)||c,je=_e&&Ae,E=M(ye.isValidating)?je:ye.isValidating,Me=M(ye.isLoading)?je:ye.isLoading,Ne=(0,_.useCallback)(async e=>{let t=x.current;if(!y||!t||ne.current||S().isPaused())return!1;let r,a,o=!0,s=e||{},c=!g[y]||!s.dedupe,l=me&&!$a(Ee,de,y)&&!M(he)&&M(C().data),u=()=>va?!ne.current&&y===re.current&&te.current:y===re.current,d={isValidating:!1,isLoading:!1},f=()=>{oe(d)},p=()=>{let e=g[y];e&&e[1]===a&&delete g[y]},_={isValidating:!0};M(C().data)&&(_.isLoading=!0);try{if(c&&(oe(_),n.loadingTimeout&&M(C().data)&&setTimeout(()=>{o&&u()&&S().onLoadingSlow(y,n)},n.loadingTimeout),l&&eo(Ee,de,y),g[y]=[l?he:t(b),ja()],l&&v[y]&&delete v[y]),[r,a]=g[y],r=await r,c&&setTimeout(p,n.dedupingInterval),!g[y]||g[y][1]!==a)return c&&u()&&S().onDiscarded(y),!1;d.error=void 0;let e=h[y];if(!M(e)&&(a<=e[0]||a<=e[1]||e[1]===0))return f(),c&&u()&&S().onDiscarded(y),!1;let s=C().data;d.data=i(s,r)?s:r,c&&u()&&S().onSuccess(r,y,n)}catch(e){p();let t=S(),{shouldRetryOnError:n}=t;t.isPaused()||(d.error=e,c&&u()&&(t.onError(e,y,t),(n===!0||N(n)&&n(e))&&(!S().revalidateOnFocus||!S().revalidateOnReconnect||ae())&&t.onErrorRetry(e,y,t,e=>{let t=m[y];t&&t[0]&&t[0](3,e)},{retryCount:(s.retryCount||0)+1,dedupe:!0})))}return o=!1,f(),!0},[y,r]),Pe=(0,_.useCallback)((...e)=>Ma(r,re.current,...e),[]);if(xa(()=>{let e=w.current;e&&(w.current=null,eo(Ee,e.cacheData,e.key),M(C().data)&&oe({data:e.data,error:void 0,_k:e._k}),v[e.key]&&delete v[e.key])}),xa(()=>{x.current=t,ie.current=n,M(xe)||(we.current=xe)}),xa(()=>{if(t||!me||M(he)||$a(Ee,de,y)||!M(C().data))return;eo(Ee,de,y);let e=h[y];to({value:he,getCacheData:()=>C().data,canCommit:()=>!ne.current&&y===re.current&&h[y]===e,setCache:e=>oe({...e,_k:b})})}),xa(()=>{if(!y)return;let e=Ne.bind(void 0,Qa),t=0;S().revalidateOnFocus&&(t=Date.now()+S().focusThrottleInterval);let n=Xa(y,m,(n,r={})=>{if(n==0){let n=Date.now();S().revalidateOnFocus&&n>t&&ae()&&(t=n+S().focusThrottleInterval,e())}else if(n==1)S().revalidateOnReconnect&&ae()&&e();else if(n==2)return Ne();else if(n==3)return Ne(r);else if(n==4&&(we.current=void 0,r.revalidate))return Ne()});return ne.current=!1,re.current=y,te.current=!0,oe({_k:b}),Ae&&(g[y]||(M(Se)||ya?e():ba(e))),()=>{ne.current=!0,n()}},[y]),xa(()=>{let e;function t(){let t=N(l)?l(C().data):l;t&&e!==-1&&(e=setTimeout(n,t))}function n(){!C().error&&(u||S().isVisible())&&(d||S().isOnline())?Ne(Qa).then(t):t()}return t(),()=>{e&&=(clearTimeout(e),-1)}},[l,u,d,y]),(0,_.useDebugValue)(T),a){if(!va&&ya&&De&&M(he))throw Error(`Fallback data is required when using Suspense in SSR.`);De&&(x.current=t,ie.current=n,ne.current=!1);let e=!M(he)&&De,r;if(e&&me?(r=he&&na(he)?Za(he):he,Se=r,T=r,ya||(w.current={data:r,_k:b,key:y,cacheData:de})):Za(e?Pe(he):no),!M(Ce)&&De)throw Ce;let i=De&&M(r)?Ne(Qa):no;!M(T)&&De&&(i.status=`fulfilled`,i.value=!0),Za(i)}return{mutate:Pe,get data(){return le.data=!0,T},get error(){return le.error=!0,Ce},get isValidating(){return le.isValidating=!0,E},get isLoading(){return le.isLoading=!0,Me}}};ea.defineProperty(Ha,`defaultValue`,{value:za});var ao=Ya(io);function oo(e={}){let t=new URLSearchParams;e.status&&t.set(`status`,e.status),e.limit!==void 0&&t.set(`limit`,String(e.limit)),e.offset!==void 0&&t.set(`offset`,String(e.offset));let n=t.toString();return Yi(`/api/v1/items${n?`?${n}`:``}`)}function so(e){return Yi(`/api/v1/items`,{method:`POST`,body:JSON.stringify(e)})}function co(e,t){return Yi(`/api/v1/items/${e}`,{method:`PATCH`,body:JSON.stringify(t)})}function lo(e){return Yi(`/api/v1/items/${e}`,{method:`DELETE`})}var uo={list:(e={})=>[`items`,`list`,e],detail:e=>[`items`,`detail`,e]};function fo(e){return Array.isArray(e)&&e[0]===`items`}var po={keepPreviousData:!0};function mo(e={}){let{data:t,error:n,isLoading:r,mutate:i}=ao(uo.list(e),()=>oo(e),po);return{items:t,error:n,isLoading:r,refresh:i}}function ho(){let{mutate:e}=qa();return{create:(0,_.useCallback)(async t=>{let n=await so(t);return await e(fo),n},[e]),update:(0,_.useCallback)(async(t,n)=>{let r=await co(t,n);return await e(fo),r},[e]),remove:(0,_.useCallback)(async t=>{await lo(t),await e(fo)},[e])}}var go=[`all`,`active`,`archived`],_o=new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`short`}),vo={padding:`var(--space-1) var(--space-3)`,fontSize:`var(--text-xs)`};function yo(){let[e,t]=(0,_.useState)(`all`),[n,r]=(0,_.useState)(!1),[i,a]=(0,_.useState)(null),[o,s]=(0,_.useState)(null),{items:c,error:l,isLoading:u,refresh:d}=mo(e===`all`?{}:{status:e}),{update:f,remove:p}=ho(),m=async(e,t)=>{a(e),s(null);try{await t()}catch(e){s(e instanceof qi?e.message:`Unexpected error`)}finally{a(null)}},h=(0,D.jsx)(pr,{children:(0,D.jsxs)(hr,{children:[(0,D.jsx)(gr,{children:`Item`}),(0,D.jsx)(gr,{children:`Status`}),(0,D.jsx)(gr,{children:`Created`}),(0,D.jsx)(gr,{children:`Updated`}),(0,D.jsx)(gr,{children:`Actions`})]})});return(0,D.jsxs)(`div`,{className:`stack-md`,children:[(0,D.jsxs)(`div`,{className:`flex-between`,style:{flexWrap:`wrap`,gap:`var(--space-3)`},children:[(0,D.jsx)(`div`,{className:`row-xs`,children:go.map(n=>(0,D.jsx)(`button`,{className:`button ${e===n?`secondary`:`ghost`}`,style:{...vo,textTransform:`capitalize`},onClick:()=>t(n),children:n},n))}),(0,D.jsxs)(`div`,{className:`row-xs`,children:[(0,D.jsxs)(Zr,{variant:`ghost`,style:vo,onClick:()=>d(),children:[(0,D.jsx)(j,{name:`refresh`,size:13}),` Refresh`]}),(0,D.jsxs)(Zr,{variant:`primary`,style:vo,onClick:()=>r(!0),children:[(0,D.jsx)(j,{name:`plus`,size:13}),` New item`]})]})]}),o&&(0,D.jsxs)(ir,{variant:`destructive`,icon:(0,D.jsx)(j,{name:`warning`,size:18}),children:[(0,D.jsx)(ar,{children:`Action failed`}),(0,D.jsx)(or,{children:o})]}),l&&!c?l instanceof qi&&l.code===`unauthorized`?(0,D.jsxs)(ir,{variant:`warning`,icon:(0,D.jsx)(j,{name:`shield`,size:18}),children:[(0,D.jsx)(ar,{children:`Sign in required`}),(0,D.jsx)(or,{children:`This API requires an authenticated session. Signing in redirects to the configured OIDC issuer and lands back on this page.`}),(0,D.jsx)(`div`,{className:`row-xs`,style:{marginTop:`var(--space-3)`},children:(0,D.jsx)(Zr,{variant:`primary`,onClick:()=>Gi(),children:`Sign in`})})]}):(0,D.jsxs)(ir,{variant:`destructive`,icon:(0,D.jsx)(j,{name:`alert`,size:18}),children:[(0,D.jsx)(ar,{children:`Cannot reach the Go API`}),(0,D.jsx)(or,{children:l.message}),(0,D.jsxs)(or,{children:[`Start it with`,` `,(0,D.jsx)(`code`,{className:`mono`,style:{color:`var(--foreground)`},children:`cd backend && make migrate-up && make run`}),` `,`— SQLite is the default, so no database server is needed, and vite proxies`,` `,(0,D.jsx)(`code`,{className:`mono`,children:`/api`}),` to `,(0,D.jsx)(`code`,{className:`mono`,children:`:8080`}),`.`]}),(0,D.jsx)(`div`,{className:`row-xs`,style:{marginTop:`var(--space-3)`},children:(0,D.jsxs)(Zr,{variant:`secondary`,onClick:()=>d(),children:[(0,D.jsx)(j,{name:`refresh`,size:13}),` Retry`]})})]}):u&&!c?(0,D.jsxs)(fr,{children:[h,(0,D.jsx)(mr,{children:[0,1,2,3].map(e=>(0,D.jsxs)(hr,{children:[(0,D.jsx)(_r,{children:(0,D.jsx)(si,{width:`60%`})}),(0,D.jsx)(_r,{children:(0,D.jsx)(si,{width:64})}),(0,D.jsx)(_r,{children:(0,D.jsx)(si,{width:140})}),(0,D.jsx)(_r,{children:(0,D.jsx)(si,{width:140})}),(0,D.jsx)(_r,{children:(0,D.jsx)(si,{width:120})})]},e))})]}):c&&c.length===0?(0,D.jsxs)(vr,{children:[(0,D.jsx)(yr,{children:(0,D.jsx)(j,{name:`database`,size:24})}),(0,D.jsx)(br,{children:`No items yet`}),(0,D.jsxs)(xr,{children:[`This table reads live from the Go API's database (SQLite by default, Postgres via DATABASE_URL). Create the first item — it POSTs to`,` `,(0,D.jsx)(`code`,{className:`mono`,children:`/api/v1/items`}),` and SWR revalidates the list.`]}),(0,D.jsx)(Sr,{children:(0,D.jsxs)(Zr,{variant:`primary`,onClick:()=>r(!0),children:[(0,D.jsx)(j,{name:`plus`,size:14}),` New item`]})})]}):(0,D.jsxs)(fr,{children:[h,(0,D.jsx)(mr,{children:c?.map(e=>(0,D.jsxs)(hr,{children:[(0,D.jsxs)(_r,{children:[(0,D.jsx)(`div`,{style:{fontWeight:600},children:e.title}),e.description&&(0,D.jsx)(`div`,{className:`mono`,style:{marginTop:`var(--space-1)`,fontSize:`var(--text-2xs)`,color:`var(--muted-foreground)`},children:e.description})]}),(0,D.jsx)(_r,{children:(0,D.jsx)(rt,{variant:e.status===`active`?`positive`:`secondary`,children:e.status})}),(0,D.jsx)(_r,{className:`mono`,style:{color:`var(--muted-foreground)`},children:_o.format(new Date(e.createdAt))}),(0,D.jsx)(_r,{className:`mono`,style:{color:`var(--muted-foreground)`},children:_o.format(new Date(e.updatedAt))}),(0,D.jsx)(_r,{children:i===e.id?(0,D.jsx)(gi,{size:`xs`}):(0,D.jsxs)(`div`,{className:`row-xs`,children:[(0,D.jsx)(`button`,{className:`button ghost`,style:vo,onClick:()=>m(e.id,()=>f(e.id,{status:e.status===`active`?`archived`:`active`})),children:e.status===`active`?`Archive`:`Restore`}),(0,D.jsx)(`button`,{className:`button ghost`,style:{...vo,color:`var(--destructive)`},"aria-label":`Delete ${e.title}`,onClick:()=>m(e.id,()=>p(e.id)),children:(0,D.jsx)(j,{name:`trash`,size:13})})]})})]},e.id))})]}),(0,D.jsxs)(`div`,{className:`flex-between muted`,style:{fontSize:`var(--text-3xs)`,padding:`0 var(--space-2)`},children:[(0,D.jsxs)(`span`,{children:[c?.length??0,` item`,c?.length===1?``:`s`,` · revalidated by SWR (reconnects refetch automatically)`]}),(0,D.jsxs)(`span`,{className:`mono`,children:[`GET /api/v1/items`,e===`all`?``:`?status=${e}`]})]}),(0,D.jsx)(bo,{open:n,onOpenChange:r})]})}function bo({open:e,onOpenChange:t}){let{create:n}=ho(),[r,i]=(0,_.useState)(``),[a,o]=(0,_.useState)(``),[s,c]=(0,_.useState)(!1),[l,u]=(0,_.useState)(null),d=()=>{i(``),o(``),c(!1),u(null)};return(0,D.jsx)(Br,{open:e,onOpenChange:t,children:(0,D.jsx)(Hr,{children:(0,D.jsxs)(`form`,{onSubmit:async e=>{e.preventDefault(),c(!0),u(null);try{await n({title:r,description:a.trim()===``?void 0:a}),d(),t(!1)}catch(e){c(!1),u(e instanceof qi?e.message:`Unexpected error`)}},children:[(0,D.jsxs)(Ur,{children:[(0,D.jsx)(Wr,{children:`New item`}),(0,D.jsxs)(Gr,{children:[`POSTs to `,(0,D.jsx)(`code`,{className:`mono`,children:`/api/v1/items`}),`; the list revalidates through SWR on success.`]})]}),(0,D.jsxs)(`div`,{className:`stack-sm`,children:[(0,D.jsx)(Ni,{label:`Title`,hint:`Required · max 200 characters`,children:(0,D.jsx)(Pi,{value:r,onChange:e=>i(e.target.value),maxLength:200,placeholder:`Ship the api template`,autoFocus:!0})}),(0,D.jsx)(Ni,{label:`Description`,hint:`Optional context shown under the title`,children:(0,D.jsx)(Pi,{value:a,onChange:e=>o(e.target.value),placeholder:`What is this item about?`})}),l&&(0,D.jsx)(ir,{variant:`destructive`,icon:(0,D.jsx)(j,{name:`alert`,size:16}),children:(0,D.jsx)(or,{children:l})})]}),(0,D.jsx)(Kr,{children:(0,D.jsxs)(`div`,{className:`row-sm`,style:{justifyContent:`flex-end`},children:[(0,D.jsx)(Zr,{type:`button`,variant:`ghost`,onClick:()=>t(!1),disabled:s,children:`Cancel`}),(0,D.jsxs)(Zr,{type:`submit`,variant:`primary`,disabled:s||r.trim()===``,children:[s?(0,D.jsx)(gi,{size:`xs`}):(0,D.jsx)(j,{name:`plus`,size:13}),`Create item`]})]})})]})})})}var xo=`/patterns`,So=`/items`,Co=[`Application Patterns`,`Components`,`Foundations`,`Documentation`],wo={"Application Patterns":`Production-grade composites that ship as one drop-in unit.`,Components:`The atoms: buttons, icons, form controls and the primitives behind them.`,Foundations:`The tokens that carry the system — color roles and the type scale.`,Documentation:`Editorial and developer surfaces for docs, changelogs and embedded code.`},To=[{path:xo,group:`Application Patterns`,label:`Application Patterns`,index:`01`,kicker:`PATTERNS & EXAMPLES`,title:`Reusable Application Patterns`,description:`Production-grade, fully functional composable components ready to drop into any project.`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`4 Reusable Components`}),page:Xr},{path:`/components/buttons`,group:`Components`,label:`Buttons`,index:`02`,kicker:`COMPONENTS`,title:`Buttons`,description:`Actions with a clear hierarchy and dependable feedback.`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`Button · 12 variants`}),page:xi},{path:`/components/icons`,group:`Components`,label:`Icons`,index:`03`,kicker:`COMPONENTS`,title:`Icons (Lucide)`,description:`Crisp, scalable SVG icons powered by Lucide. Tree-shakeable, stroke-matched, and token-aware.`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`iconRegistry · 41 curated · lucide 1,400+`}),page:Ti},{path:`/foundations/colors`,group:`Foundations`,label:`Color tokens`,index:`04`,kicker:`FOUNDATIONS`,title:`Color tokens`,description:`Functional color roles in CSS Color 4 lab() keep every surface intentional.`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`48 tokens · lab()`}),page:ki},{path:`/foundations/typography`,group:`Foundations`,label:`Typography`,index:`05`,kicker:`FOUNDATIONS`,title:`Typography`,description:`Modular rem-based type scale with dual-family hierarchy (Manrope & DM Mono).`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`Type scale · 9→70px`}),page:Mi},{path:`/components/forms`,group:`Components`,label:`Form controls`,index:`06`,kicker:`PRIMITIVES`,title:`Form controls`,description:`Inputs designed for focus, flow, and the occasional messy edge case.`,page:Fi},{path:`/components/code`,group:`Components`,label:`Composable code`,index:`07`,kicker:`CODE`,title:`Composable by default`,description:`Small APIs. Strong defaults. No surprises.`,page:zi},{path:`/docs/markdown`,group:`Documentation`,label:`Markdown rendering`,index:`08`,kicker:`CONTENT`,title:`Markdown rendering`,description:`A readable editorial layer for changelogs, docs, and product notes.`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`Markdown · styled`}),page:Vi},{path:`/docs/editor`,group:`Documentation`,label:`CodeMirror theme`,index:`09`,kicker:`DEVELOPER TOOLING`,title:`CodeMirror theme`,description:`A focused editor palette for examples, playgrounds, and embedded code.`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`codemirror · dark`}),page:Wi},{path:So,group:`Application Patterns`,label:`Items (live API)`,index:`10`,kicker:`FULLSTACK`,title:`Live data — Go API + SWR`,description:`The Go backend wired end to end: typed api modules, SWR hooks, mutations, and every loading state.`,meta:(0,D.jsx)(`span`,{className:`api-pill`,children:`SWR · /api/v1/items · SQLite/Postgres`}),page:yo}],Eo={"/components/buttons":12,"/components/icons":41};function Do(e){return To.find(t=>t.path===e)}function Oo(e){return To.filter(t=>t.group===e)}var ko=[{label:`Application Patterns`,items:[...Xe.map(e=>({label:e.label,href:`${xo}?pattern=${e.id}`})),...Oo(`Application Patterns`).map(e=>({label:e.label,href:e.path}))]},...Co.filter(e=>e!==`Application Patterns`).map(e=>({label:e,items:Oo(e).map(e=>({label:e.label,href:e.path,count:Eo[e.path]}))}))];function Ao(e){let t=new URLSearchParams(e).get(`pattern`);return Xe.some(e=>e.id===t)?t:`metrics`}function jo(e,t){return e===`/patterns`?`${xo}?pattern=${Ao(t)}`:e}function Mo(){let{status:e,user:t,signOut:n}=Ki(),[r,i]=(0,_.useState)(!1),a=(0,_.useRef)(null);if((0,_.useEffect)(()=>{if(!r)return;let e=e=>{a.current?.contains(e.target)===!1&&i(!1)},t=e=>{e.key===`Escape`&&i(!1)};return document.addEventListener(`pointerdown`,e),document.addEventListener(`keydown`,t),()=>{document.removeEventListener(`pointerdown`,e),document.removeEventListener(`keydown`,t)}},[r]),e===`loading`)return(0,D.jsx)(`span`,{className:`avatar skeleton-pulse`,"aria-hidden":`true`});if(e===`anonymous`||t===null)return(0,D.jsx)(`button`,{type:`button`,className:`top-signin`,onClick:()=>Gi(),children:`Sign in`});let o=t.name||t.email;return(0,D.jsxs)(`div`,{className:`user-menu`,ref:a,children:[(0,D.jsx)(`button`,{type:`button`,className:`avatar`,onClick:()=>i(e=>!e),"aria-haspopup":`menu`,"aria-expanded":r,"aria-label":o,title:o,children:No(o)}),r&&(0,D.jsxs)(`div`,{className:`user-menu-popover`,role:`menu`,children:[(0,D.jsxs)(`div`,{className:`user-menu-identity`,children:[t.name&&(0,D.jsx)(`b`,{children:t.name}),(0,D.jsx)(`span`,{children:t.email})]}),(0,D.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`user-menu-signout`,onClick:()=>{i(!1),n()},children:[(0,D.jsx)(j,{name:`log-out`,size:14}),`Sign out`]})]})]})}function No(e){return e.trim().split(/\s+/).filter(Boolean).slice(0,2).map(e=>e.charAt(0)).join(``).toUpperCase()}var Po={default:`Default`,compact:`Compact`};function Fo({onMenuToggle:e}){let{theme:t,toggleTheme:n,viewMode:r,setViewMode:i,openSearch:a}=Le();return(0,D.jsxs)(`header`,{className:`topbar`,children:[(0,D.jsx)(`div`,{className:`brand`,children:(0,D.jsxs)(Me,{href:`/`,className:`brand-link`,children:[(0,D.jsx)(`div`,{className:`brand-mark`,children:(0,D.jsx)(`span`,{})}),(0,D.jsx)(`b`,{children:`northstar`}),(0,D.jsx)(`span`,{className:`version`,children:`v0.8.2`})]})}),(0,D.jsxs)(`button`,{type:`button`,className:`top-search`,onClick:a,"aria-label":`Search components, tokens, docs (Press ⌘K)`,children:[(0,D.jsx)(j,{name:`search`,size:16}),(0,D.jsx)(`span`,{className:`top-search-placeholder`,children:`Search components, tokens, docs...`}),(0,D.jsx)(`kbd`,{children:`⌘ K`})]}),(0,D.jsxs)(`nav`,{className:`top-links`,children:[(0,D.jsx)(Me,{href:`/docs/markdown`,children:`Docs`}),(0,D.jsx)(`a`,{href:`#github`,children:`GitHub ↗`}),(0,D.jsx)(`div`,{className:`segmented top-view-mode`,role:`group`,"aria-label":`View mode`,children:Fe.map(e=>(0,D.jsx)(`button`,{type:`button`,className:e===r?`selected`:void 0,"aria-pressed":e===r,title:`Switch to ${Po[e].toLowerCase()} view`,onClick:()=>i(e),children:Po[e]},e))}),(0,D.jsx)(`button`,{type:`button`,className:`icon-button`,onClick:n,"aria-label":`Switch to ${t===`dark`?`light`:`dark`} theme`,children:(0,D.jsx)(j,{name:t===`dark`?`sun`:`moon`,size:17})}),(0,D.jsx)(Mo,{})]}),(0,D.jsx)(`button`,{type:`button`,className:`mobile-menu icon-button`,onClick:e,"aria-label":`Toggle navigation`,children:(0,D.jsx)(j,{name:`menu`})})]})}function Io({groups:e,activeHref:t,onNavigate:n,collapsed:r=!1,onToggleCollapse:i}){return(0,D.jsxs)(`aside`,{className:`sidebar`,children:[(0,D.jsxs)(`div`,{className:`sidebar-heading`,children:[(0,D.jsxs)(`div`,{className:`sidebar-library`,children:[(0,D.jsx)(j,{name:`layers`,size:13}),` Library`]}),(0,D.jsx)(`button`,{type:`button`,className:`sidebar-collapse`,onClick:i,"aria-pressed":r,"aria-label":r?`Expand sidebar`:`Collapse sidebar`,children:r?`⌘+`:`⌘−`})]}),(0,D.jsxs)(`div`,{className:`sidebar-intro`,children:[(0,D.jsx)(`span`,{className:`eyebrow`,children:`Northstar system`}),(0,D.jsx)(`p`,{children:`Principles and primitives for product teams.`})]}),(0,D.jsx)(`nav`,{"aria-label":`Documentation navigation`,onClick:n,children:e.map(e=>(0,D.jsxs)(`div`,{className:`nav-group`,children:[(0,D.jsx)(`span`,{className:`nav-label`,children:e.label}),e.items.map(e=>{let n=e.href===t;return(0,D.jsxs)(Me,{href:e.href,className:n?`nav-item active`:`nav-item`,"aria-current":n?`page`:void 0,children:[(0,D.jsx)(`span`,{className:`nav-glyph`,"aria-hidden":`true`,children:e.count?`◈`:`·`}),(0,D.jsx)(`span`,{children:e.label}),e.count!==void 0&&(0,D.jsx)(`span`,{className:`nav-count`,children:e.count})]},e.label)})]},e.label))}),(0,D.jsxs)(`div`,{className:`sidebar-bottom`,children:[(0,D.jsxs)(`div`,{className:`status-line`,children:[(0,D.jsx)(`span`,{className:`status-dot`}),`All systems operational`]}),(0,D.jsx)(`span`,{className:`mono muted`,children:`Updated 2 min ago`})]})]})}function Lo({index:e,title:t,description:n,meta:r,children:i,id:a,className:o=``}){return(0,D.jsxs)(`section`,{className:`section-block ${o}`.trim(),id:a,children:[(0,D.jsxs)(`div`,{className:`section-heading`,children:[(0,D.jsxs)(`div`,{children:[(0,D.jsx)(`span`,{className:`section-index`,children:e}),(0,D.jsx)(`h2`,{children:t}),(0,D.jsx)(`p`,{children:n})]}),r]}),i]})}function Ro({title:e,links:t,activeHref:n}){return(0,D.jsxs)(`aside`,{className:`right-rail`,children:[(0,D.jsxs)(`div`,{className:`rail-card`,children:[(0,D.jsx)(`span`,{className:`eyebrow`,children:e}),t.map((e,t)=>(0,D.jsxs)(Me,{className:e.href===n?`rail-link active`:`rail-link`,href:e.href,"aria-current":e.href===n?`page`:void 0,children:[(0,D.jsxs)(`span`,{children:[`0`,t+1]}),e.label]},e.label))]}),(0,D.jsxs)(`div`,{className:`rail-card release`,children:[(0,D.jsx)(`div`,{className:`release-icon`,children:(0,D.jsx)(j,{name:`layers`,size:18})}),(0,D.jsx)(`strong`,{children:`Designed to be extended`}),(0,D.jsx)(`p`,{children:`Bring your brand, keep the rhythm. Tokens are portable and components stay unopinionated.`}),(0,D.jsxs)(Me,{className:`text-button`,href:`/docs/markdown`,children:[`Read the docs `,(0,D.jsx)(j,{name:`arrow`,size:14})]})]}),(0,D.jsxs)(`div`,{className:`rail-card`,children:[(0,D.jsx)(`span`,{className:`eyebrow`,children:`Need a hand?`}),(0,D.jsx)(`p`,{className:`rail-copy`,children:`Check the contribution guide or say hello in the community.`}),(0,D.jsxs)(Zr,{variant:`secondary`,className:`full`,children:[`Open community `,(0,D.jsx)(`span`,{children:`↗`})]})]})]})}var zo=[{id:`pat-metrics`,title:`Metrics Dashboard`,description:`Telemetry dashboard with StatCards, time range picker, and progress gauges`,category:`Patterns`,icon:`sparkles`,path:`/patterns`,patternId:`metrics`},{id:`pat-settings`,title:`Settings & Safeguards`,description:`Preferences panel with API keys, toggle switches, and alert banners`,category:`Patterns`,icon:`settings`,path:`/patterns`,patternId:`settings`},{id:`pat-table`,title:`Service Monitor Table`,description:`Real-time service health table with status filtering and search`,category:`Patterns`,icon:`layers`,path:`/patterns`,patternId:`table`},{id:`pat-deploy`,title:`Canary Deployment Flow`,description:`Interactive rollout modal with live progress simulation`,category:`Patterns`,icon:`terminal`,path:`/patterns`,patternId:`deploy`},{id:`pat-items`,title:`Items (live API)`,description:`Full-stack demo: typed api modules, SWR hooks, live Postgres data`,category:`Patterns`,icon:`database`,path:`/items`},{id:`comp-buttons`,title:`Buttons & Action States`,description:`Primary, secondary, destructive, ghost variants with resting, hover, active and focus states`,category:`Components`,icon:`arrow-right`,path:`/components/buttons`},{id:`comp-icons`,title:`Lucide Icons Explorer`,description:`Over 1,400+ tree-shaken SVG icons with search, category filtering and 1-click copy`,category:`Components`,icon:`sparkles`,path:`/components/icons`},{id:`comp-forms`,title:`Form Controls & Inputs`,description:`Accessible text inputs, secret key revealers, and toggle switches`,category:`Components`,icon:`eye`,path:`/components/forms`},{id:`comp-code`,title:`Composable UI Primitives`,description:`Zero-drift Dialog, Sheet, Tabs, Table, Alert, Progress, Switch, and StatCard`,category:`Components`,icon:`code`,path:`/components/code`},{id:`found-colors`,title:`Color Tokens (CSS Color 4 lab())`,description:`Pitch black dark theme and pure white daylight light theme tokens`,category:`Foundations`,icon:`sun`,path:`/foundations/colors`},{id:`found-type`,title:`Typography & Scale`,description:`Modular rem-based 9px to 70px scale with Manrope and DM Mono families`,category:`Foundations`,icon:`file`,path:`/foundations/typography`},{id:`doc-md`,title:`Markdown Editorial Layer`,description:`Changelogs, release notes, and documentation typography`,category:`Documentation`,icon:`file`,path:`/docs/markdown`},{id:`doc-cm`,title:`CodeMirror Editor Theme`,description:`Syntax-highlighted code editor preview with line numbers and token palette`,category:`Documentation`,icon:`terminal`,path:`/docs/editor`}],Bo=`search-palette-listbox`;function Vo({isOpen:e,onClose:t,onSelect:n,initialQuery:r=``}){let[i,a]=(0,_.useState)(r),[o,s]=(0,_.useState)(0),c=(0,_.useRef)(null),l=(0,_.useRef)(null);Dr(e,c),(0,_.useEffect)(()=>{e&&l.current?.focus()},[e,r]);let u=(0,_.useMemo)(()=>{if(!i.trim())return zo;let e=i.toLowerCase();return zo.filter(t=>t.title.toLowerCase().includes(e)||t.description.toLowerCase().includes(e)||t.category.toLowerCase().includes(e))},[i]),d=u.length===0?-1:Math.min(o,u.length-1),f=d>=0?u[d]:void 0;return(0,_.useEffect)(()=>{if(!e)return;let r=e=>{e.key===`Escape`?(e.preventDefault(),t()):e.key===`ArrowDown`?(e.preventDefault(),s(e=>u.length?(e+1)%u.length:0)):e.key===`ArrowUp`?(e.preventDefault(),s(e=>u.length?(e-1+u.length)%u.length:0)):e.key===`Enter`&&f&&(e.preventDefault(),n(f),t())};return window.addEventListener(`keydown`,r),()=>window.removeEventListener(`keydown`,r)},[e,u.length,f,t,n]),e?(0,D.jsx)(`div`,{className:`search-palette-backdrop`,onClick:t,children:(0,D.jsxs)(`div`,{ref:c,role:`dialog`,"aria-modal":`true`,"aria-label":`Search`,tabIndex:-1,className:`search-palette-modal`,onKeyDown:e=>{Er(e,c.current)},onClick:e=>e.stopPropagation(),children:[(0,D.jsxs)(`div`,{className:`search-palette-head`,children:[(0,D.jsx)(j,{name:`search`,size:18,className:`search-palette-icon`}),(0,D.jsx)(`input`,{ref:l,type:`text`,role:`combobox`,"aria-expanded":u.length>0,"aria-controls":Bo,"aria-activedescendant":f?`search-option-${f.id}`:void 0,"aria-label":`Search components, tokens, and docs`,className:`search-palette-input`,placeholder:`Type a command, component, or token...`,value:i,onChange:e=>{a(e.target.value),s(0)}}),i&&(0,D.jsx)(`button`,{type:`button`,className:`icon-button`,onClick:()=>{a(``),s(0)},"aria-label":`Clear search`,children:(0,D.jsx)(j,{name:`close`,size:14})}),(0,D.jsx)(ur,{children:`ESC`})]}),(0,D.jsx)(`div`,{className:`search-palette-body`,children:u.length>0?(0,D.jsx)(`ul`,{id:Bo,role:`listbox`,"aria-label":`Search results`,className:`search-palette-results`,children:u.map((e,r)=>{let i=r===d;return(0,D.jsxs)(`li`,{id:`search-option-${e.id}`,role:`option`,"aria-selected":i,className:`search-palette-item ${i?`selected`:``}`,onClick:()=>{n(e),t()},onMouseEnter:()=>s(r),children:[(0,D.jsx)(`div`,{className:`search-item-glyph`,children:(0,D.jsx)(j,{name:e.icon,size:16})}),(0,D.jsxs)(`div`,{className:`search-item-content`,children:[(0,D.jsxs)(`div`,{className:`search-item-title-row`,children:[(0,D.jsx)(`span`,{className:`search-item-title`,children:e.title}),(0,D.jsx)(rt,{variant:`outline`,children:e.category})]}),(0,D.jsx)(`p`,{className:`search-item-desc`,children:e.description})]}),i&&(0,D.jsx)(`div`,{className:`search-item-action`,children:(0,D.jsx)(ur,{children:`↵`})})]},e.id)})}):(0,D.jsxs)(`div`,{className:`search-palette-empty`,children:[(0,D.jsx)(j,{name:`search`,size:24}),(0,D.jsxs)(`p`,{children:[`No results found for “`,i,`”`]}),(0,D.jsx)(`span`,{children:`Try searching for “Buttons”, “Metrics”, “Tokens”, or “Icons”.`})]})}),(0,D.jsxs)(`div`,{className:`search-palette-footer`,children:[(0,D.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,D.jsx)(ur,{children:`↑`}),(0,D.jsx)(ur,{children:`↓`}),(0,D.jsx)(`span`,{children:`to navigate`})]}),(0,D.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,D.jsx)(ur,{children:`↵`}),(0,D.jsx)(`span`,{children:`to select`})]}),(0,D.jsxs)(`div`,{className:`row-xs`,style:{alignItems:`center`},children:[(0,D.jsx)(ur,{children:`ESC`}),(0,D.jsx)(`span`,{children:`to close`})]})]})]})}):null}function Ho(){return(0,D.jsxs)(`section`,{className:`hero-section`,children:[(0,D.jsxs)(`div`,{className:`hero-copy`,children:[(0,D.jsx)(`span`,{className:`eyebrow accent`,children:`Component library`}),(0,D.jsx)(`h1`,{children:`Build with clarity.`}),(0,D.jsx)(`p`,{children:`A considered set of accessible, composable components for building calm, capable interfaces.`}),(0,D.jsxs)(`div`,{className:`hero-actions`,children:[(0,D.jsxs)(Qr,{variant:`primary`,href:`/components/buttons`,children:[`Explore components `,(0,D.jsx)(j,{name:`arrow`,size:16})]}),(0,D.jsx)(Qr,{variant:`ghost`,href:`/docs/markdown`,children:`Read the principles`})]})]}),(0,D.jsxs)(`div`,{className:`hero-orbit`,"aria-hidden":`true`,children:[(0,D.jsx)(`div`,{className:`orbit orbit-one`}),(0,D.jsx)(`div`,{className:`orbit orbit-two`}),(0,D.jsxs)(`div`,{className:`orbit-core`,children:[(0,D.jsx)(`div`,{className:`brand-mark large`,children:(0,D.jsx)(`span`,{})}),(0,D.jsxs)(`span`,{children:[`system`,(0,D.jsx)(`br`,{}),(0,D.jsx)(`b`,{children:`ready`})]})]}),(0,D.jsxs)(`span`,{className:`orbit-label label-one`,children:[`TOKENS `,(0,D.jsx)(`b`,{children:`48`})]}),(0,D.jsxs)(`span`,{className:`orbit-label label-two`,children:[`A11Y `,(0,D.jsx)(`b`,{children:`AAA`})]}),(0,D.jsxs)(`span`,{className:`orbit-label label-three`,children:[`RUNTIME `,(0,D.jsx)(`b`,{children:`FAST`})]})]})]})}function Uo(){let{status:e,user:t,signOut:n}=Ki();return(0,D.jsxs)(Ze,{className:`stack-xs session-card`,children:[(0,D.jsxs)(Qe,{children:[(0,D.jsx)($e,{children:`Session`}),(0,D.jsx)(et,{children:`OIDC authorization-code flow against users.k6n.net.`})]}),(0,D.jsxs)(tt,{className:`stack-xs`,children:[e===`loading`&&(0,D.jsxs)(`div`,{className:`session-identity`,children:[(0,D.jsx)(`span`,{className:`session-avatar skeleton-pulse`,"aria-hidden":`true`}),(0,D.jsxs)(`span`,{className:`session-lines`,children:[(0,D.jsx)(`span`,{className:`skeleton-pulse`,"aria-hidden":`true`}),(0,D.jsx)(`span`,{className:`skeleton-pulse`,"aria-hidden":`true`})]})]}),e===`anonymous`&&(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(`p`,{className:`session-note`,children:`Not signed in — the API answers 401 until you are.`}),(0,D.jsx)(Zr,{variant:`primary`,onClick:()=>Gi(`/`),children:`Sign in`})]}),e===`authenticated`&&t&&(0,D.jsxs)(D.Fragment,{children:[(0,D.jsxs)(`div`,{className:`session-identity`,children:[(0,D.jsx)(pi,{name:t.name||t.email,size:`md`,status:`online`}),(0,D.jsxs)(`div`,{className:`session-lines`,children:[(0,D.jsx)(`b`,{children:t.name||t.email}),t.name&&t.email&&t.email!==t.name&&(0,D.jsx)(`span`,{children:t.email}),(0,D.jsxs)(`small`,{children:[`sub: `,t.sub]})]})]}),t.roles.length>0&&(0,D.jsx)(`div`,{className:`session-roles`,children:t.roles.map(e=>(0,D.jsx)(rt,{variant:`outline`,children:e},e))}),(0,D.jsx)(Zr,{variant:`secondary`,onClick:()=>void n(),children:`Sign out`})]})]})]})}function Wo(){return(0,D.jsxs)(D.Fragment,{children:[(0,D.jsx)(Ho,{}),(0,D.jsxs)(`div`,{className:`overview-grid`,children:[(0,D.jsx)(Uo,{}),Co.map(e=>(0,D.jsxs)(Ze,{className:`stack-xs`,children:[(0,D.jsxs)(Qe,{children:[(0,D.jsx)($e,{children:e}),(0,D.jsx)(et,{children:wo[e]})]}),(0,D.jsx)(tt,{children:(0,D.jsx)(`ul`,{className:`overview-links`,children:Oo(e).map(e=>(0,D.jsx)(`li`,{children:(0,D.jsxs)(Me,{href:e.path,children:[e.label,` `,(0,D.jsx)(j,{name:`arrow`,size:13})]})},e.path))})})]},e))]})]})}function Go(){return(0,D.jsx)(`div`,{className:`not-found`,children:(0,D.jsxs)(vr,{children:[(0,D.jsx)(br,{children:`Page not found`}),(0,D.jsx)(xr,{children:`That route does not exist in this design system. Pick a page from the list instead.`}),(0,D.jsx)(`ul`,{className:`overview-links`,children:To.map(e=>(0,D.jsx)(`li`,{children:(0,D.jsx)(Me,{href:e.path,children:e.label})},e.path))})]})})}function Ko({route:e}){let t=e.page;return(0,D.jsx)(Lo,{index:`${e.index} / ${e.kicker}`,title:e.title,description:e.description,meta:e.meta,children:(0,D.jsx)(t,{})})}function L(){let{searchOpen:e,closeSearch:t,sidebarCollapsed:n,toggleSidebar:r}=Le(),[i,a]=w(),o=T(),[s,c]=(0,_.useState)(!1),l=Do(i),u=l?.label??(i===`/`?`Overview`:`Not found`),d=jo(i,o),f=ko.find(e=>e.label===l?.group)?.items??[];return(0,_.useEffect)(()=>{window.scrollTo({top:0})},[i]),(0,D.jsxs)(`div`,{className:`app-shell`,children:[(0,D.jsx)(Fo,{onMenuToggle:()=>c(!s)}),(0,D.jsx)(Vo,{isOpen:e,onClose:t,onSelect:e=>{a(e.patternId?`${e.path}?pattern=${e.patternId}`:e.path)}}),(0,D.jsxs)(`div`,{className:`body-layout ${s?`menu-open`:``} ${n?`sidebar-collapsed`:``}`,children:[(0,D.jsx)(Io,{groups:ko,activeHref:d,onNavigate:()=>c(!1),collapsed:n,onToggleCollapse:r}),(0,D.jsxs)(`main`,{className:`main-content`,children:[(0,D.jsxs)(`div`,{className:`breadcrumbs`,children:[(0,D.jsx)(`span`,{children:l?l.group:`Northstar`}),(0,D.jsx)(`span`,{children:`/`}),(0,D.jsx)(`strong`,{children:u})]}),i===`/`?(0,D.jsx)(Wo,{}):(0,D.jsxs)(`div`,{className:`content-grid`,children:[(0,D.jsx)(`div`,{className:`content-main`,children:(0,D.jsxs)(Pe,{children:[To.map(e=>(0,D.jsx)(E,{path:e.path,children:(0,D.jsx)(Ko,{route:e})},e.path)),(0,D.jsx)(E,{children:(0,D.jsx)(Go,{})})]})}),l&&(0,D.jsx)(Ro,{title:l.group,links:f,activeHref:d})]}),(0,D.jsxs)(`footer`,{children:[(0,D.jsx)(`span`,{children:`northstar design system`}),(0,D.jsx)(`span`,{className:`mono`,children:`made for the long haul · 2025`})]})]})]})]})}var R=class extends _.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidCatch(e,t){}render(){let{error:e}=this.state;return e?(0,D.jsxs)(`div`,{style:{padding:`var(--space-6)`,margin:`var(--space-6) auto`,maxWidth:`42rem`,fontFamily:`var(--font-mono)`,fontSize:`var(--text-sm)`,color:`var(--foreground)`,background:`var(--card)`,border:`1px solid var(--destructive)`,borderRadius:`var(--radius-lg)`,whiteSpace:`pre-wrap`},children:[(0,D.jsx)(`strong`,{children:`Something broke while rendering.`}),` - -`,e.message]}):this.props.children}};(0,v.createRoot)(document.getElementById(`root`)).render((0,D.jsx)(_.StrictMode,{children:(0,D.jsx)(R,{children:(0,D.jsx)(Ye,{children:(0,D.jsx)(L,{})})})})); \ No newline at end of file diff --git a/frontend/dist/index.html b/frontend/dist/index.html index 4ece967..8934549 100644 --- a/frontend/dist/index.html +++ b/frontend/dist/index.html @@ -27,8 +27,8 @@ } })() - - + +
diff --git a/frontend/node_modules/.tmp/tsconfig.app.tsbuildinfo b/frontend/node_modules/.tmp/tsconfig.app.tsbuildinfo index 5268260..b60b8f0 100644 --- a/frontend/node_modules/.tmp/tsconfig.app.tsbuildinfo +++ b/frontend/node_modules/.tmp/tsconfig.app.tsbuildinfo @@ -1 +1 @@ -{"root":["../../src/App.tsx","../../src/main.tsx","../../src/api/client.ts","../../src/api/items.ts","../../src/app/AppStateProvider.tsx","../../src/app/appState.ts","../../src/app/index.ts","../../src/app/persist.ts","../../src/app/routes.tsx","../../src/auth/SessionCard.tsx","../../src/auth/UserMenu.tsx","../../src/auth/useSession.ts","../../src/components/AIWorkflowSection.tsx","../../src/components/Button.tsx","../../src/components/ButtonMatrix.tsx","../../src/components/CodeEditor.tsx","../../src/components/CodeSample.tsx","../../src/components/FormField.tsx","../../src/components/Hero.tsx","../../src/components/Icon.tsx","../../src/components/IconMatrix.tsx","../../src/components/MarkdownRenderer.tsx","../../src/components/RightRail.tsx","../../src/components/SearchPalette.tsx","../../src/components/Section.tsx","../../src/components/Sidebar.tsx","../../src/components/TokenGrid.tsx","../../src/components/Topbar.tsx","../../src/components/TypographySection.tsx","../../src/components/icon-registry.ts","../../src/components/examples/DeploymentModal.tsx","../../src/components/examples/MetricsDashboard.tsx","../../src/components/examples/ServiceTable.tsx","../../src/components/examples/SettingsPanel.tsx","../../src/components/examples/index.ts","../../src/components/ui/Alert.tsx","../../src/components/ui/Avatar.tsx","../../src/components/ui/Badge.tsx","../../src/components/ui/Card.tsx","../../src/components/ui/Dialog.tsx","../../src/components/ui/EmptyState.tsx","../../src/components/ui/Kbd.tsx","../../src/components/ui/Overlay.tsx","../../src/components/ui/Progress.tsx","../../src/components/ui/Sheet.tsx","../../src/components/ui/Skeleton.tsx","../../src/components/ui/Spinner.tsx","../../src/components/ui/StatCard.tsx","../../src/components/ui/Switch.tsx","../../src/components/ui/Table.tsx","../../src/components/ui/Tabs.tsx","../../src/components/ui/Tooltip.tsx","../../src/components/ui/index.ts","../../src/components/ui/overlayBehavior.ts","../../src/data/library.ts","../../src/data/patterns.ts","../../src/dev/ErrorBoundary.tsx","../../src/dev/errorSink.ts","../../src/hooks/useItems.ts","../../src/pages/ButtonsPage.tsx","../../src/pages/ColorsPage.tsx","../../src/pages/EditorPage.tsx","../../src/pages/FormsPage.tsx","../../src/pages/IconsPage.tsx","../../src/pages/ItemsPage.tsx","../../src/pages/MarkdownPage.tsx","../../src/pages/NotFoundPage.tsx","../../src/pages/OverviewPage.tsx","../../src/pages/PatternsPage.tsx","../../src/pages/PrimitivesPage.tsx","../../src/pages/TypographyPage.tsx","../../src/utils/cn.ts","../../src/utils/useTimeout.ts"],"version":"6.0.3"} \ No newline at end of file +{"root":["../../src/App.tsx","../../src/main.tsx","../../src/api/browse.ts","../../src/api/client.ts","../../src/api/items.ts","../../src/app/AppStateProvider.tsx","../../src/app/appState.ts","../../src/app/index.ts","../../src/app/persist.ts","../../src/app/routes.tsx","../../src/auth/SessionCard.tsx","../../src/auth/UserMenu.tsx","../../src/auth/useSession.ts","../../src/components/AIWorkflowSection.tsx","../../src/components/Button.tsx","../../src/components/ButtonMatrix.tsx","../../src/components/CodeEditor.tsx","../../src/components/CodeSample.tsx","../../src/components/FormField.tsx","../../src/components/Hero.tsx","../../src/components/Icon.tsx","../../src/components/IconMatrix.tsx","../../src/components/MarkdownRenderer.tsx","../../src/components/RightRail.tsx","../../src/components/SearchPalette.tsx","../../src/components/Section.tsx","../../src/components/Sidebar.tsx","../../src/components/TokenGrid.tsx","../../src/components/Topbar.tsx","../../src/components/TypographySection.tsx","../../src/components/icon-registry.ts","../../src/components/examples/DeploymentModal.tsx","../../src/components/examples/MetricsDashboard.tsx","../../src/components/examples/ServiceTable.tsx","../../src/components/examples/SettingsPanel.tsx","../../src/components/examples/index.ts","../../src/components/markdown/MarkdownView.tsx","../../src/components/markdown/parse.ts","../../src/components/ui/Alert.tsx","../../src/components/ui/Avatar.tsx","../../src/components/ui/Badge.tsx","../../src/components/ui/Card.tsx","../../src/components/ui/Dialog.tsx","../../src/components/ui/EmptyState.tsx","../../src/components/ui/Kbd.tsx","../../src/components/ui/Overlay.tsx","../../src/components/ui/Progress.tsx","../../src/components/ui/Sheet.tsx","../../src/components/ui/Skeleton.tsx","../../src/components/ui/Spinner.tsx","../../src/components/ui/StatCard.tsx","../../src/components/ui/Switch.tsx","../../src/components/ui/Table.tsx","../../src/components/ui/Tabs.tsx","../../src/components/ui/Tooltip.tsx","../../src/components/ui/index.ts","../../src/components/ui/overlayBehavior.ts","../../src/data/library.ts","../../src/data/patterns.ts","../../src/dev/ErrorBoundary.tsx","../../src/dev/errorSink.ts","../../src/hooks/useBrowse.ts","../../src/hooks/useItems.ts","../../src/pages/AgentViewPage.tsx","../../src/pages/ButtonsPage.tsx","../../src/pages/ColorsPage.tsx","../../src/pages/EditorPage.tsx","../../src/pages/FormsPage.tsx","../../src/pages/IconsPage.tsx","../../src/pages/ItemsPage.tsx","../../src/pages/MarkdownPage.tsx","../../src/pages/NotFoundPage.tsx","../../src/pages/OverviewPage.tsx","../../src/pages/PatternsPage.tsx","../../src/pages/PrimitivesPage.tsx","../../src/pages/TypographyPage.tsx","../../src/utils/cn.ts","../../src/utils/useTimeout.ts"],"version":"6.0.3"} \ No newline at end of file diff --git a/frontend/node_modules/.vite/deps/_metadata.json b/frontend/node_modules/.vite/deps/_metadata.json index ebea824..3aa6129 100644 --- a/frontend/node_modules/.vite/deps/_metadata.json +++ b/frontend/node_modules/.vite/deps/_metadata.json @@ -1,55 +1,55 @@ { - "hash": "976b9c3d", - "configHash": "89e67727", + "hash": "b89571df", + "configHash": "98cfc040", "lockfileHash": "0d4791a3", - "browserHash": "4b2fbac7", + "browserHash": "01f60908", "optimized": { "lucide-react": { "src": "../../lucide-react/dist/esm/lucide-react.mjs", "file": "lucide-react.js", - "fileHash": "6c3cfb80", + "fileHash": "503441b8", "needsInterop": false }, "react-dom": { "src": "../../react-dom/index.js", "file": "react-dom.js", - "fileHash": "25030b7a", + "fileHash": "f0a88d8a", "needsInterop": true }, "react-dom/client": { "src": "../../react-dom/client.js", "file": "react-dom_client.js", - "fileHash": "de15c997", + "fileHash": "20f9fc06", "needsInterop": true }, "react": { "src": "../../react/index.js", "file": "react.js", - "fileHash": "e97c5b5e", + "fileHash": "1f16888b", "needsInterop": true }, "react/jsx-dev-runtime": { "src": "../../react/jsx-dev-runtime.js", "file": "react_jsx-dev-runtime.js", - "fileHash": "15b8f65b", + "fileHash": "f6e1330a", "needsInterop": true }, "react/jsx-runtime": { "src": "../../react/jsx-runtime.js", "file": "react_jsx-runtime.js", - "fileHash": "6d9e10ca", + "fileHash": "ea33db31", "needsInterop": true }, "swr": { "src": "../../swr/dist/index/index.mjs", "file": "swr.js", - "fileHash": "5dedc4fa", + "fileHash": "43f93c02", "needsInterop": false }, "wouter": { "src": "../../wouter/src/index.js", "file": "wouter.js", - "fileHash": "9e6a9f9c", + "fileHash": "ebb90d1b", "needsInterop": false } }, diff --git a/frontend/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json b/frontend/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json index c80c7ef..4067159 100644 --- a/frontend/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json +++ b/frontend/node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709/results.json @@ -1 +1 @@ -{"version":"5.0.0","results":[[":tests/auth.test.tsx",{"duration":491.67805499999986,"failed":false}],[":tests/api.test.ts",{"duration":14.961915999999974,"failed":false}],[":tests/overlay.test.tsx",{"duration":728.093953,"failed":false}],[":tests/check-tokens.test.mjs",{"duration":998.8133460000001,"failed":false}],[":tests/routing.test.tsx",{"duration":1758.9155749999995,"failed":false}],[":tests/appState.test.tsx",{"duration":423.0312829999998,"failed":false}],[":tests/icon-registry.test.tsx",{"duration":75.86277799999993,"failed":false}],[":tests/useTimeout.test.tsx",{"duration":43.350607999999966,"failed":false}],[":tests/useItems.test.tsx",{"duration":415.8608149999998,"failed":false}],[":tests/itemsPage.test.tsx",{"duration":698.4244530000001,"failed":false}]]} \ No newline at end of file +{"version":"5.0.0","results":[[":tests/auth.test.tsx",{"duration":536.224841,"failed":false}],[":tests/api.test.ts",{"duration":17.88092000000006,"failed":false}],[":tests/overlay.test.tsx",{"duration":694.3132250000001,"failed":false}],[":tests/check-tokens.test.mjs",{"duration":734.5557109999997,"failed":false}],[":tests/routing.test.tsx",{"duration":2000.0288979999996,"failed":false}],[":tests/appState.test.tsx",{"duration":367.28223000000025,"failed":false}],[":tests/icon-registry.test.tsx",{"duration":80.47717699999998,"failed":false}],[":tests/useTimeout.test.tsx",{"duration":56.3337939999999,"failed":false}],[":tests/useItems.test.tsx",{"duration":398.72940700000004,"failed":false}],[":tests/itemsPage.test.tsx",{"duration":708.2502969999998,"failed":false}],[":tests/agentViewPage.test.tsx",{"duration":1352.459346,"failed":false}],[":tests/markdown.test.ts",{"duration":18.204109000000017,"failed":false}],[":tests/dbg.test.tsx",{"duration":625.5198799999998,"failed":false}]]} \ No newline at end of file diff --git a/frontend/src/App.css b/frontend/src/App.css index 4d6e539..a8cdd67 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -2226,3 +2226,300 @@ footer { @media (max-width: 760px) { .overview-grid { padding-bottom: var(--space-9); } } + +/* ── Agent view ───────────────────────────────────────────────────────── + The LLM browser: domain in, agent-eye view out. All colors come from + tokens; derived shades use color-mix so both themes stay correct. */ + +.agent-url-row { + display: flex; + gap: var(--space-2); + flex-wrap: wrap; +} + +.agent-url-row input { + flex: 1; + min-width: min(100%, 22rem); +} + +.agent-examples { + display: flex; + align-items: center; + gap: var(--space-2); + flex-wrap: wrap; + margin-top: var(--space-3); +} + +.agent-example { + padding: var(--space-1) var(--space-3); + font-size: var(--text-xs); + font-family: var(--font-mono); +} + +.agent-head .agent-url { + font-size: var(--text-sm); + color: var(--foreground); + word-break: break-all; +} + +.agent-note { + font-size: var(--text-xs); + padding: 0 var(--space-2); +} + +.agent-doc { + padding: var(--space-5); + overflow-x: auto; +} + +/* The converted page renders inside the shared .markdown-body editorial + styles; relax its centered-article metrics for the app surface and fill + in the shapes the demo never needed (links, lists, tables, code). */ +.agent-doc .markdown-body { + max-width: none; + margin: 0; + padding: 0; +} + +.agent-doc .markdown-body h1 { + font-size: var(--text-2xl); + letter-spacing: -0.04em; + line-height: 1.15; + margin: var(--space-5) 0 var(--space-3); +} + +.agent-doc .markdown-body h2 { + font-size: var(--text-xl); + letter-spacing: -0.03em; + line-height: 1.2; + margin: var(--space-5) 0 var(--space-2); +} + +.agent-doc .markdown-body h5, +.agent-doc .markdown-body h6 { + font-size: var(--text-md); + margin: var(--space-4) 0 var(--space-1); +} + +.agent-doc .markdown-body a { + color: var(--accent); + text-decoration: underline; + text-decoration-color: color-mix(in srgb, var(--accent) 45%, transparent); + text-underline-offset: 2px; +} + +.agent-doc .markdown-body a:hover { + text-decoration-color: var(--accent); +} + +.agent-doc .markdown-body ul, +.agent-doc .markdown-body ol { + margin: 0 0 var(--space-4); + padding-left: 1.4rem; + color: var(--muted-foreground); + display: flex; + flex-direction: column; + gap: var(--space-1); +} + +.agent-doc .markdown-body blockquote { + margin: 0 0 var(--space-4); + padding: var(--space-2) var(--space-4); + border-left: 2px solid color-mix(in srgb, var(--accent) 55%, var(--border)); + color: var(--muted-foreground); + font-style: italic; +} + +.agent-doc .markdown-body blockquote p { + margin: 0; +} + +.agent-doc .markdown-body pre { + margin: 0 0 var(--space-4); + padding: var(--space-3) var(--space-4); + background: var(--muted); + border: 1px solid var(--border); + border-radius: var(--radius-md); + overflow-x: auto; +} + +.agent-doc .markdown-body pre code { + background: none; + border: none; + padding: 0; + color: var(--foreground); + font-size: var(--text-xs); + line-height: 1.6; +} + +.agent-doc .markdown-body table { + width: 100%; + border-collapse: collapse; + margin: 0 0 var(--space-4); + font-size: var(--text-sm); +} + +.agent-doc .markdown-body th, +.agent-doc .markdown-body td { + border: 1px solid var(--border); + padding: var(--space-2) var(--space-3); + text-align: left; +} + +.agent-doc .markdown-body th { + background: color-mix(in srgb, var(--accent) 7%, var(--card)); +} + +.agent-doc .markdown-body hr { + border: none; + border-top: 1px solid var(--border); + margin: var(--space-5) 0; +} + +.agent-doc .markdown-body img { + max-width: 100%; + border-radius: var(--radius-sm); +} + +/* Raw source + companion files */ +.agent-raw { + margin: 0; + padding: var(--space-4); + background: var(--muted); + color: var(--foreground); + font-size: var(--text-xs); + line-height: 1.6; + overflow: auto; + max-height: 26rem; + white-space: pre-wrap; + word-break: break-word; +} + +.agent-file-url { + font-size: var(--text-2xs); + text-decoration: none; + word-break: break-all; +} + +.agent-file-url:hover { + color: var(--foreground); +} + +/* Parsed llms.txt */ +.agent-llms { + display: flex; + flex-direction: column; + gap: var(--space-3); +} + +.agent-llms-title { + margin: 0; + font-size: var(--text-lg); + letter-spacing: -0.02em; +} + +.agent-llms-quote { + margin: 0; + padding: var(--space-2) var(--space-4); + border-left: 2px solid color-mix(in srgb, var(--accent) 55%, var(--border)); + color: var(--muted-foreground); + font-style: italic; + font-size: var(--text-sm); +} + +.agent-llms-section h4 { + margin: var(--space-2) 0 0; + font-size: var(--text-md); +} + +.agent-llms-section > p { + margin: 0; + font-size: var(--text-xs); +} + +.agent-llms-section ul { + list-style: disc; + margin: var(--space-2) 0 0; + padding-left: 1.3rem; + display: flex; + flex-direction: column; + gap: var(--space-1); + font-size: var(--text-sm); +} + +.agent-llms-section a { + color: var(--accent); + text-decoration: underline; + text-underline-offset: 2px; +} + +/* Meta table */ +.agent-meta { + margin: 0; + padding: var(--space-2) var(--space-5) var(--space-4); +} + +.agent-meta-row { + display: grid; + grid-template-columns: minmax(110px, max-content) 1fr; + gap: var(--space-4); + padding: var(--space-2) 0; + border-bottom: 1px solid var(--border); + font-size: var(--text-sm); +} + +.agent-meta-row:last-child { + border-bottom: none; +} + +.agent-meta-row dd { + margin: 0; + word-break: break-word; +} + +/* Checks */ +.agent-checks-summary { + padding: var(--space-4) var(--space-5) 0; +} + +.agent-checks { + list-style: none; + margin: 0; + padding: var(--space-2) var(--space-5) var(--space-4); +} + +.agent-check { + display: flex; + align-items: flex-start; + gap: var(--space-3); + padding: var(--space-3) 0; + border-bottom: 1px solid var(--border); +} + +.agent-check:last-child { + border-bottom: none; +} + +.agent-check .badge { + flex-shrink: 0; + min-width: 3.5rem; + justify-content: center; + text-transform: uppercase; +} + +.agent-check-label { + font-weight: 600; + font-size: var(--text-sm); +} + +.agent-check-detail { + font-size: var(--text-xs); + line-height: 1.55; +} + +@media (max-width: 720px) { + .agent-meta-row { + grid-template-columns: 1fr; + gap: var(--space-1); + } +} diff --git a/frontend/src/api/browse.ts b/frontend/src/api/browse.ts new file mode 100644 index 0000000..995e962 --- /dev/null +++ b/frontend/src/api/browse.ts @@ -0,0 +1,82 @@ +/* Typed client for the browse resource — the agent view. The wire format + is owned by backend/internal/browse (model.go); these types mirror it. */ +import { apiFetch } from './client' + +export type Severity = 'ok' | 'info' | 'warn' | 'error' + +export type Check = { + id: string + label: string + severity: Severity + detail: string +} + +export type PageView = { + title: string + description: string + canonical: string + robotsMeta: string + lang: string + h1: string + linkCount: number + deadLinks: number + scriptCount: number + imageCount: number + wordCount: number + textLength: number +} + +export type LlmsLink = { + title: string + url: string + description: string +} + +export type LlmsSection = { + heading: string + description: string + links: LlmsLink[] +} + +export type LlmsDoc = { + title: string + description: string + sections: LlmsSection[] + linkCount: number +} + +export type FileResult = { + url: string + status: number + contentType: string + error?: string + content: string + truncated: boolean + llmsDoc?: LlmsDoc +} + +export type BrowseFiles = { + llmsTxt: FileResult | null + llmsFullTxt: FileResult | null + wellKnownLlmsTxt: FileResult | null + robotsTxt: FileResult | null +} + +export type Snapshot = { + requestedUrl: string + finalUrl: string + status: number + contentType: string + durationMs: number + fetchedAt: string + page?: PageView + markdown: string + markdownTruncated: boolean + files: BrowseFiles + checks: Check[] +} + +/** GET /api/v1/browse?url=… — a bare domain or a full URL both work. */ +export function browse(url: string): Promise { + return apiFetch(`/api/v1/browse?url=${encodeURIComponent(url)}`) +} diff --git a/frontend/src/app/routes.tsx b/frontend/src/app/routes.tsx index ff4cad5..9abb749 100644 --- a/frontend/src/app/routes.tsx +++ b/frontend/src/app/routes.tsx @@ -11,6 +11,7 @@ import { PrimitivesPage } from '../pages/PrimitivesPage' import { MarkdownPage } from '../pages/MarkdownPage' import { EditorPage } from '../pages/EditorPage' import { ItemsPage } from '../pages/ItemsPage' +import { AgentViewPage } from '../pages/AgentViewPage' /* ── The route table ───────────────────────────────────────────────────────── One registry drives the router, the sidebar, the breadcrumbs and the ⌘K @@ -23,6 +24,9 @@ export const PATTERNS_PATH = '/patterns' /** Live backend demo page (vite proxies /api to the Go server on :8080). */ export const ITEMS_PATH = '/items' +/** The agent view: enter a domain, see what an LLM sees. */ +export const AGENT_VIEW_PATH = '/agent-view' + export const ROUTE_GROUPS = ['Application Patterns', 'Components', 'Foundations', 'Documentation'] as const export type RouteGroup = (typeof ROUTE_GROUPS)[number] @@ -50,11 +54,23 @@ export type AppRoute = { } export const routes: AppRoute[] = [ + { + path: AGENT_VIEW_PATH, + group: 'Application Patterns', + label: 'Agent view', + index: '01', + kicker: 'AGENT TOOLING', + title: 'Agent view — browse as an LLM', + description: + 'Enter a domain and see what an agent sees: the page as markdown with followable links, its llms.txt map, robots rules and readiness checks.', + meta: /api/v1/browse · llms.txt, + page: AgentViewPage, + }, { path: PATTERNS_PATH, group: 'Application Patterns', label: 'Application Patterns', - index: '01', + index: '02', kicker: 'PATTERNS & EXAMPLES', title: 'Reusable Application Patterns', description: @@ -66,7 +82,7 @@ export const routes: AppRoute[] = [ path: '/components/buttons', group: 'Components', label: 'Buttons', - index: '02', + index: '03', kicker: 'COMPONENTS', title: 'Buttons', description: 'Actions with a clear hierarchy and dependable feedback.', @@ -77,7 +93,7 @@ export const routes: AppRoute[] = [ path: '/components/icons', group: 'Components', label: 'Icons', - index: '03', + index: '04', kicker: 'COMPONENTS', title: 'Icons (Lucide)', description: @@ -89,7 +105,7 @@ export const routes: AppRoute[] = [ path: '/foundations/colors', group: 'Foundations', label: 'Color tokens', - index: '04', + index: '05', kicker: 'FOUNDATIONS', title: 'Color tokens', description: 'Functional color roles in CSS Color 4 lab() keep every surface intentional.', @@ -100,7 +116,7 @@ export const routes: AppRoute[] = [ path: '/foundations/typography', group: 'Foundations', label: 'Typography', - index: '05', + index: '06', kicker: 'FOUNDATIONS', title: 'Typography', description: 'Modular rem-based type scale with dual-family hierarchy (Manrope & DM Mono).', @@ -111,7 +127,7 @@ export const routes: AppRoute[] = [ path: '/components/forms', group: 'Components', label: 'Form controls', - index: '06', + index: '07', kicker: 'PRIMITIVES', title: 'Form controls', description: 'Inputs designed for focus, flow, and the occasional messy edge case.', @@ -121,7 +137,7 @@ export const routes: AppRoute[] = [ path: '/components/code', group: 'Components', label: 'Composable code', - index: '07', + index: '08', kicker: 'CODE', title: 'Composable by default', description: 'Small APIs. Strong defaults. No surprises.', @@ -131,7 +147,7 @@ export const routes: AppRoute[] = [ path: '/docs/markdown', group: 'Documentation', label: 'Markdown rendering', - index: '08', + index: '09', kicker: 'CONTENT', title: 'Markdown rendering', description: 'A readable editorial layer for changelogs, docs, and product notes.', @@ -142,7 +158,7 @@ export const routes: AppRoute[] = [ path: '/docs/editor', group: 'Documentation', label: 'CodeMirror theme', - index: '09', + index: '10', kicker: 'DEVELOPER TOOLING', title: 'CodeMirror theme', description: 'A focused editor palette for examples, playgrounds, and embedded code.', @@ -153,7 +169,7 @@ export const routes: AppRoute[] = [ path: ITEMS_PATH, group: 'Application Patterns', label: 'Items (live API)', - index: '10', + index: '11', kicker: 'FULLSTACK', title: 'Live data — Go API + SWR', description: diff --git a/frontend/src/components/SearchPalette.tsx b/frontend/src/components/SearchPalette.tsx index 48a1fad..56a3ca1 100644 --- a/frontend/src/components/SearchPalette.tsx +++ b/frontend/src/components/SearchPalette.tsx @@ -18,6 +18,14 @@ export type SearchItem = { const SEARCH_INDEX: SearchItem[] = [ // Patterns + { + id: 'pat-agent-view', + title: 'Agent view — browse as an LLM', + description: 'Enter a domain, see the page as markdown, its llms.txt map and readiness checks', + category: 'Patterns', + icon: 'cpu', + path: '/agent-view', + }, { id: 'pat-metrics', title: 'Metrics Dashboard', diff --git a/frontend/src/components/markdown/MarkdownView.tsx b/frontend/src/components/markdown/MarkdownView.tsx new file mode 100644 index 0000000..f9e12cb --- /dev/null +++ b/frontend/src/components/markdown/MarkdownView.tsx @@ -0,0 +1,139 @@ +/* React renderer for the agent view's markdown. Builds elements directly + from parse.ts output — no HTML injection. Every link click is routed + through onNavigate so "browsing" stays inside the agent view: the viewer + fetches the linked page and renders it the same way, which is exactly + the loop an agent is in. */ +import { useMemo, type AnchorHTMLAttributes, type ReactNode } from 'react' +import { parseMarkdown, type InlineSpan, type ListBlock, type MarkdownBlock } from './parse' + +export function MarkdownView({ + source, + onNavigate, + className, +}: { + source: string + /** Called with the absolute href when the visitor opens a link. */ + onNavigate?: (href: string) => void + className?: string +}) { + const blocks = useMemo(() => parseMarkdown(source), [source]) + return ( +
+ {blocks.map((block, index) => ( + + ))} +
+ ) +} + +function BlockView({ block, onNavigate }: { block: MarkdownBlock; onNavigate?: (href: string) => void }) { + switch (block.kind) { + case 'heading': { + const Tag = `h${block.level}` as 'h1' + return {block.spans.map((span, i) => )} + } + case 'paragraph': + return

{block.spans.map((span, i) => )}

+ case 'code': + return ( +
+          {block.text}
+        
+ ) + case 'quote': + return ( +
+ {block.blocks.map((child, i) => ( + + ))} +
+ ) + case 'list': + return + case 'table': + return ( + + + + {block.head.map((cell, i) => ( + + ))} + + + + {block.rows.map((row, r) => ( + + {row.map((cell, c) => ( + + ))} + + ))} + +
{cell}
{cell}
+ ) + case 'hr': + return
+ } +} + +function ListView({ list, onNavigate }: { list: ListBlock; onNavigate?: (href: string) => void }) { + const Tag = list.ordered ? 'ol' : 'ul' + return ( + + {list.items.map((item, index) => ( +
  • + {item.spans.map((span, i) => ( + + ))} + {item.sub && } +
  • + ))} +
    + ) +} + +function SpanView({ span, onNavigate }: { span: InlineSpan; onNavigate?: (href: string) => void }) { + switch (span.kind) { + case 'text': + return <>{span.text} + case 'code': + return {span.text} + case 'strong': + return {span.spans.map((child, i) => )} + case 'em': + return {span.spans.map((child, i) => )} + case 'del': + return {span.spans.map((child, i) => )} + case 'image': + return {span.alt} + case 'link': + return {renderInline(span.spans, onNavigate)} + } +} + +function AgentLink({ + href, + onNavigate, + children, + ...props +}: AnchorHTMLAttributes & { href: string; onNavigate?: (href: string) => void }) { + const followable = /^https?:\/\//i.test(href) + return ( + { + if (!followable || !onNavigate) return + event.preventDefault() // the agent view never leaves itself + onNavigate(href) + }} + title={followable ? 'Open in the agent view' : undefined} + {...props} + > + {children} + + ) +} + +function renderInline(spans: InlineSpan[], onNavigate?: (href: string) => void): ReactNode { + return spans.map((span, i) => ) +} diff --git a/frontend/src/components/markdown/parse.ts b/frontend/src/components/markdown/parse.ts new file mode 100644 index 0000000..fc72cf4 --- /dev/null +++ b/frontend/src/components/markdown/parse.ts @@ -0,0 +1,255 @@ +/* A small markdown block/inline parser for the agent view. The backend + converts HTML to well-behaved markdown (headings, paragraphs, lists, + fenced code, blockquotes, GFM tables, links, images) — exactly the shapes + this parser handles, so the renderer can build React elements directly + without dangerouslySetInnerHTML. Unknown syntax degrades to paragraphs. */ + +export type InlineSpan = + | { kind: 'text'; text: string } + | { kind: 'code'; text: string } + | { kind: 'strong'; spans: InlineSpan[] } + | { kind: 'em'; spans: InlineSpan[] } + | { kind: 'del'; spans: InlineSpan[] } + | { kind: 'link'; href: string; spans: InlineSpan[] } + | { kind: 'image'; alt: string; src: string } + +export type ListItem = { + spans: InlineSpan[] + /** A list nested under this item. */ + sub?: ListBlock +} + +export type ListBlock = { + kind: 'list' + ordered: boolean + start: number + items: ListItem[] +} + +export type MarkdownBlock = + | { kind: 'heading'; level: number; spans: InlineSpan[] } + | { kind: 'paragraph'; spans: InlineSpan[] } + | { kind: 'code'; language: string; text: string } + | { kind: 'quote'; blocks: MarkdownBlock[] } + | ListBlock + | { kind: 'table'; head: string[]; rows: string[][] } + | { kind: 'hr' } + +const headingRe = /^(#{1,6})\s+(.*)$/ +const hrRe = /^ {0,3}(?:-{3,}|\*{3,}|_{3,})\s*$/ +const fenceRe = /^ {0,3}(`{3,}|~{3,})\s*([^\s`]*)\s*$/ +const quoteRe = /^ {0,3}>\s?(.*)$/ +const itemRe = /^(\s*)([-*+]|\d{1,9}[.)])\s+(.*)$/ +const tableRowRe = /^\s*.*\|.*$/ +const tableSepRe = /^\s*\|?\s*:?-{2,}[\s:|-]*\|?\s*$/ + +/** Parse a markdown document into renderable blocks. */ +export function parseMarkdown(source: string): MarkdownBlock[] { + return parseBlocks(source.split('\n')).blocks +} + +function parseBlocks(lines: string[]): { blocks: MarkdownBlock[]; next: number } { + const blocks: MarkdownBlock[] = [] + let i = 0 + + outer: while (i < lines.length) { + const line = lines[i] + if (line === undefined) break + + if (line.trim() === '') { + i++ + continue + } + + const fence = fenceRe.exec(line) + if (fence) { + const marker = fence[1] ?? '`' + const language = fence[2] ?? '' + const body: string[] = [] + i++ + while (i < lines.length) { + const current = lines[i] + if (current === undefined) break + if (new RegExp(`^ {0,3}${marker[0]}{${marker.length},}\\s*$`).test(current)) break + body.push(current) + i++ + } + i++ // closing fence (or EOF) + blocks.push({ kind: 'code', language, text: body.join('\n') }) + continue + } + + const heading = headingRe.exec(line) + if (heading) { + blocks.push({ + kind: 'heading', + level: heading[1]?.length ?? 1, + spans: parseInline(heading[2] ?? ''), + }) + i++ + continue + } + + if (hrRe.test(line)) { + blocks.push({ kind: 'hr' }) + i++ + continue + } + + const quote = quoteRe.exec(line) + if (quote) { + const inner: string[] = [quote[1] ?? ''] + i++ + while (i < lines.length) { + const cont = quoteRe.exec(lines[i] ?? '') + if (!cont) break + inner.push(cont[1] ?? '') + i++ + } + blocks.push({ kind: 'quote', blocks: parseBlocks(inner).blocks }) + continue + } + + const item = itemRe.exec(line) + if (item) { + const parsed = parseList(lines, i, item[1]?.length ?? 0) + blocks.push(parsed.list) + i = parsed.next + continue + } + + const nextLine = lines[i + 1] + if (tableRowRe.test(line) && nextLine !== undefined && tableSepRe.test(nextLine)) { + const head = splitTableRow(line) + i += 2 + const rows: string[][] = [] + while (i < lines.length) { + const rowLine = lines[i] + if (rowLine === undefined || !tableRowRe.test(rowLine) || rowLine.trim() === '') break + rows.push(splitTableRow(rowLine)) + i++ + } + blocks.push({ kind: 'table', head, rows }) + continue + } + + // paragraph: gather until a blank line or the start of another block + const text: string[] = [line] + i++ + while (i < lines.length) { + const next = lines[i] + if (next === undefined) break + if ( + next.trim() === '' || + headingRe.test(next) || + hrRe.test(next) || + fenceRe.test(next) || + quoteRe.test(next) || + itemRe.test(next) + ) { + break + } + text.push(next) + i++ + } + blocks.push({ kind: 'paragraph', spans: parseInline(text.join(' ').trim()) }) + if (blocks.length > 5000) break outer // pathological input guard + } + + return { blocks, next: i } +} + +/** Parse one (possibly nested) list starting at `start` with base indent. */ +function parseList( + lines: string[], + start: number, + indent: number, +): { list: ListBlock; next: number } { + const first = itemRe.exec(lines[start] ?? '') + const firstMarker = first?.[2] ?? '' + const ordered = /\d/.test(firstMarker) + const startNumber = ordered ? parseInt(firstMarker, 10) || 1 : 1 + const items: ListItem[] = [] + let i = start + + while (i < lines.length) { + const line = lines[i] + if (line === undefined) break + if (line.trim() === '') { + // a blank line only ends the list if the next line is not a sibling item + if (i + 1 < lines.length && siblingItem(lines[i + 1] ?? '', indent)) { + i++ + continue + } + break + } + const match = itemRe.exec(line) + if (!match) break + const itemIndent = match[1]?.length ?? 0 + if (itemIndent < indent) break + if (itemIndent > indent) { + // deeper indent: nested list under the previous item + if (items.length > 0) { + const nested = parseList(lines, i, itemIndent) + const parent = items[items.length - 1] + if (parent) parent.sub = nested.list + i = nested.next + continue + } + break + } + const marker = match[2] ?? '' + if (ordered !== /\d/.test(marker)) break + items.push({ spans: parseInline(match[3] ?? '') }) + i++ + } + + return { list: { kind: 'list', ordered, start: startNumber, items }, next: i } +} + +function siblingItem(line: string, indent: number): boolean { + const match = itemRe.exec(line) + return match !== null && (match[1]?.length ?? 0) === indent +} + +function splitTableRow(line: string): string[] { + let s = line.trim() + if (s.startsWith('|')) s = s.slice(1) + if (s.endsWith('|')) s = s.slice(0, -1) + return s.split('|').map(cell => cell.trim()) +} + +/* ── Inline parsing ──────────────────────────────────────────────────── */ + +const spanRe = + /(!\[[^\]]*\]\([^)]*\))|(\[[^\]]*\]\([^)]*\))|(`[^`\n]+`)|(\*\*[^*\n]+\*\*)|(__[^_\n]+__)|(~~[^~\n]+~~)|(\*[^*\n]+\*)|(_[^_\n]+_)/g + +export function parseInline(text: string): InlineSpan[] { + const spans: InlineSpan[] = [] + let last = 0 + for (const match of text.matchAll(spanRe)) { + const index = match.index ?? 0 + if (index > last) spans.push({ kind: 'text', text: text.slice(last, index) }) + spans.push(...parseSpan(match[0])) + last = index + match[0].length + } + if (last < text.length) spans.push({ kind: 'text', text: text.slice(last) }) + return spans +} + +function parseSpan(raw: string): InlineSpan[] { + if (raw.startsWith('![')) { + const m = /^\!\[([^\]]*)\]\(([^)\s]*)(?:\s+"[^"]*")?\)$/.exec(raw) + if (m) return [{ kind: 'image', alt: m[1] ?? '', src: m[2] ?? '' }] + } + if (raw.startsWith('[')) { + const m = /^\[([^\]]*)\]\(([^)\s]*)(?:\s+"[^"]*")?\)$/.exec(raw) + if (m) return [{ kind: 'link', href: m[2] ?? '', spans: parseInline(m[1] ?? '') }] + } + if (raw.startsWith('`')) return [{ kind: 'code', text: raw.slice(1, -1) }] + if (raw.startsWith('~~')) return [{ kind: 'del', spans: parseInline(raw.slice(2, -2)) }] + if (raw.startsWith('**') || raw.startsWith('__')) { + return [{ kind: 'strong', spans: parseInline(raw.slice(2, -2)) }] + } + return [{ kind: 'em', spans: parseInline(raw.slice(1, -1)) }] +} diff --git a/frontend/src/hooks/useBrowse.ts b/frontend/src/hooks/useBrowse.ts new file mode 100644 index 0000000..019f28e --- /dev/null +++ b/frontend/src/hooks/useBrowse.ts @@ -0,0 +1,20 @@ +/* SWR data hook for the agent view. A null url means "idle" — no request + goes out until the visitor submits a domain. Snapshots are keyed by URL + so navigating back to a previously inspected page is instant from cache; + refresh() re-runs the fetch (sites change). */ +import useSWR from 'swr' +import * as browseApi from '../api/browse' +import type { Snapshot } from '../api/browse' + +export const browseKeys = { + snapshot: (url: string) => ['browse', 'snapshot', url] as const, +} + +export function useBrowse(url: string | null) { + const { data, error, isLoading, mutate } = useSWR( + url !== null ? browseKeys.snapshot(url) : null, + () => browseApi.browse(url as string), + { keepPreviousData: true }, + ) + return { snapshot: data, error, isLoading, refresh: mutate } +} diff --git a/frontend/src/pages/AgentViewPage.tsx b/frontend/src/pages/AgentViewPage.tsx new file mode 100644 index 0000000..c82896f --- /dev/null +++ b/frontend/src/pages/AgentViewPage.tsx @@ -0,0 +1,503 @@ +/* The agent view: enter a domain and see the page the way a text-only + agent sees it — markdown, llms.txt companions, robots.txt and the + readiness checks. The inspected URL lives in ?url= so any page is + linkable, and link clicks re-enter the viewer (the agent loop). */ +import { useState, type FormEvent } from 'react' +import { useLocation, useSearch } from 'wouter' +import { + Alert, + AlertDescription, + AlertTitle, + Badge, + Button, + Card, + CardDescription, + CardHeader, + CardTitle, + EmptyState, + EmptyStateActions, + EmptyStateDescription, + EmptyStateIcon, + EmptyStateTitle, + Icon, + Skeleton, + Spinner, + Tabs, + TabsContent, + TabsList, + TabsTrigger, +} from '../components/ui' +import { MarkdownView } from '../components/markdown/MarkdownView' +import { TextInput } from '../components/FormField' +import { ApiError } from '../api/client' +import type { Check, FileResult, LlmsDoc, Severity, Snapshot } from '../api/browse' +import { useBrowse } from '../hooks/useBrowse' + + +const EXAMPLES = ['anthropic.com', 'example.com', 'developer.mozilla.org'] + +/** What to send to the API: ?url= is already normalized server-side. */ +function urlFromSearch(search: string): string | null { + const value = new URLSearchParams(search).get('url')?.trim() + return value ? value : null +} + +export function AgentViewPage() { + const [location, navigate] = useLocation() + const search = useSearch() + const activeUrl = urlFromSearch(search) + + const [input, setInput] = useState(activeUrl ?? '') + const [tab, setTab] = useState('markdown') + const { snapshot, error, isLoading, refresh } = useBrowse(activeUrl) + + /** Enter the agent loop at another URL (form submit or link click). */ + const goTo = (value: string) => { + const target = value.trim() + if (!target) return + setInput(target) + setTab('markdown') + navigate(`${location.split('?')[0]}?url=${encodeURIComponent(target)}`) + } + + const handleSubmit = (event: FormEvent) => { + event.preventDefault() + goTo(input) + } + + return ( +
    + + + Browse as an agent + + Fetches the page server-side without JavaScript, converts it to markdown, and gathers + the llms.txt files — exactly what an LLM sees when it + “opens” this site. + + +
    + setInput(event.target.value)} + placeholder="example.com or https://example.com/docs" + aria-label="Domain or URL to inspect" + autoFocus + /> + + +
    + {EXAMPLES.map(example => ( + + ))} +
    +
    + + {error && !snapshot ? ( + refresh()} /> + ) : !activeUrl ? ( + + ) : isLoading && !snapshot ? ( + + ) : snapshot ? ( + refresh()} /> + ) : null} +
    + ) +} + +/* ── States ─────────────────────────────────────────────────────────── */ + +function ExplainCard() { + return ( + + + + + What does your site look like to an LLM? + + Agents never run JavaScript and often skip the HTML entirely: they read markdown and{' '} + llms.txt. Enter a domain to validate what they actually get — + the rendered markdown, the curated link map, robots rules, and a list of fixes. + + + {EXAMPLES.map(example => ( + + ))} + + + ) +} + +/** Example trigger kept separate so tests can reach it by role. */ +function AgentViewLinkButton({ url }: { url: string }) { + const [location, navigate] = useLocation() + return ( + + ) +} + +function LoadingCard() { + return ( + +
    + + + + + +
    +
    + ) +} + +function BrowseError({ error, onRetry }: { error: Error; onRetry: () => void }) { + const code = error instanceof ApiError ? error.code : 'unknown' + const siteFailed = code === 'unavailable' || code === 'timeout' + return ( + }> + {siteFailed ? 'The site did not answer' : 'Inspection failed'} + + {siteFailed + ? 'The server could not fetch this URL within the time limit — it may be down, very slow, or blocking the fetch.' + : error.message} + +
    + +
    +
    + ) +} + +/* ── The snapshot ───────────────────────────────────────────────────── */ + +function SnapshotView({ + snapshot, + tab, + onTab, + onNavigate, + onRefresh, +}: { + snapshot: Snapshot + tab: string + onTab: (value: string) => void + onNavigate: (href: string) => void + onRefresh: () => void +}) { + const files = snapshot.files + const llmsFound = [files.llmsTxt, files.llmsFullTxt, files.wellKnownLlmsTxt].some(file => file?.status && file.status < 400) + const counts = countSeverities(snapshot.checks) + + return ( +
    +
    +
    + + {snapshot.finalUrl} + {snapshot.requestedUrl !== snapshot.finalUrl && ( + redirected from {snapshot.requestedUrl} + )} + + {snapshot.durationMs} ms · {snapshot.contentType.split(';')[0] || 'unknown type'} + +
    + +
    + + + + Markdown + Source + + llms.txt{llmsFound ? '' : ' ·'} + + robots.txt + Meta + + Checks{counts.total > 0 ? ` (${counts.total})` : ''} + + + + +
    +
    + + {snapshot.markdown.length.toLocaleString()} characters ·{' '} + {snapshot.page ? `${snapshot.page.linkCount} links` : 'non-HTML document'} — links stay + in the viewer, like an agent re-entering a page. + + {snapshot.markdownTruncated && truncated} +
    + {snapshot.markdown.trim() === '' ? ( + }> + No content without JavaScript + + The server sent {snapshot.page ? `${snapshot.page.scriptCount} script tags and ` : ''} + no readable body text. An agent sees an empty page here. + + + ) : ( + + + + )} +
    +
    + + + + + + +
    + + + +
    +
    + + + + + + + + + + + + +
    +
    + ) +} + +/* ── Pieces ─────────────────────────────────────────────────────────── */ + +function StatusBadge({ status }: { status: number }) { + const variant = status < 300 ? 'positive' : status < 400 ? 'primary' : 'destructive' + return ( + + {status} {status < 300 ? 'OK' : status < 400 ? 'redirect' : 'error'} + + ) +} + +function SeverityBadge({ severity }: { severity: Severity }) { + const variant: Record = { + ok: 'positive', + info: 'secondary', + warn: 'primary', + error: 'destructive', + } + return {severity} +} + +function countSeverities(checks: Check[]) { + const counts = { total: checks.length, warn: 0, error: 0 } + for (const check of checks) { + if (check.severity === 'warn') counts.warn++ + if (check.severity === 'error') counts.error++ + } + return counts +} + +function RawBlock({ text, note }: { text: string; note: string }) { + const [copied, setCopied] = useState(false) + const copy = async () => { + try { + await navigator.clipboard.writeText(text) + setCopied(true) + setTimeout(() => setCopied(false), 1500) + } catch { + // clipboard unavailable (permissions); the text is selectable anyway + } + } + return ( + +
    + {note} + +
    +
    {text}
    +
    + ) +} + +function FileCard({ + label, + file, + spec, + onNavigate, +}: { + label: string + file: FileResult | null + spec?: boolean + onNavigate?: (href: string) => void +}) { + return ( + + +
    +
    + + {label} + +
    + {file?.url && ( + + {file.url} + + )} +
    + + {file === null + ? 'Not fetched (the request failed before an answer).' + : spec + ? 'The llmstxt.org convention: a curated, agent-first map of the site.' + : undefined} + +
    + + {file?.status && file.status < 400 ? ( +
    + {file.llmsDoc && } +
    + + Raw {label} + +
    {file.content}
    +
    +
    + ) : ( +

    + {file?.error + ? `Unreachable: ${file.error}` + : file?.status + ? `Not published (HTTP ${file.status}).${spec ? ' Agents fall back to parsing the HTML — adding one is the single highest-impact fix.' : ''}` + : 'No response recorded.'} +

    + )} +
    + ) +} + +function FileBadge({ file }: { file: FileResult | null }) { + if (file === null) return failed + if (file.status < 300) return found + if (file.status < 400) return redirect + if (file.status === 404) return missing + return HTTP {file.status} +} + +/** A parsed llms.txt: title, summary, and its curated sections. */ +function LlmsDocView({ doc, onNavigate }: { doc: LlmsDoc; onNavigate?: (href: string) => void }) { + return ( +
    + {doc.title &&

    {doc.title}

    } + {doc.description &&
    {doc.description}
    } + {doc.sections.map((section, index) => ( +
    + {section.heading &&

    {section.heading}

    } + {section.description &&

    {section.description}

    } + +
    + ))} + {doc.linkCount === 0 &&

    No links parsed from this file.

    } +
    + ) +} + +function MetaView({ snapshot }: { snapshot: Snapshot }) { + const page = snapshot.page + const rows: [string, string][] = page + ? [ + ['Title', page.title || '—'], + ['Description', page.description || '—'], + ['Canonical', page.canonical || '—'], + ['Meta robots', page.robotsMeta || 'not set'], + ['Language', page.lang || '—'], + ['H1', page.h1 || '—'], + ['Links', `${page.linkCount} followable · ${page.deadLinks} dead`], + ['Scripts', String(page.scriptCount)], + ['Images', String(page.imageCount)], + ['Visible text', `${page.textLength.toLocaleString()} chars · ${page.wordCount.toLocaleString()} words`], + ] + : [['Content type', snapshot.contentType || '—']] + return ( + +
    + {rows.map(([term, value]) => ( +
    +
    {term}
    +
    {value}
    +
    + ))} +
    +
    + ) +} + +function ChecksView({ checks }: { checks: Check[] }) { + const counts = countSeverities(checks) + return ( + +
    + {counts.error} errors + {counts.warn} warnings + + {checks.filter(check => check.severity === 'info').length} notes + + + {checks.filter(check => check.severity === 'ok').length} passed + +
    +
      + {checks.map(check => ( +
    • + +
      +
      {check.label}
      +
      {check.detail}
      +
      +
    • + ))} +
    +
    + ) +} diff --git a/frontend/src/tokens.css b/frontend/src/tokens.css index d8795be..b0af3bb 100644 --- a/frontend/src/tokens.css +++ b/frontend/src/tokens.css @@ -99,7 +99,8 @@ } /* ── Dark Palette (Exact lab() Specification) ────────────────── */ -:root:not([data-theme='light']), +/* Dark theme — explicit selectors only. With no data-theme attribute the + :root default palette (identical to dark) already applies. */ :root[data-theme='dark'], .dark { color-scheme: dark; diff --git a/frontend/tests/agentViewPage.test.tsx b/frontend/tests/agentViewPage.test.tsx new file mode 100644 index 0000000..3a18e4f --- /dev/null +++ b/frontend/tests/agentViewPage.test.tsx @@ -0,0 +1,160 @@ +import { fireEvent, render, screen, waitFor } from '@testing-library/react' +import { SWRConfig } from 'swr' +import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { AgentViewPage } from '../src/pages/AgentViewPage' +import { browse } from '../src/api/browse' +import type { Snapshot } from '../src/api/browse' + +/* Page-level wiring: the api module is mocked, everything else (SWR, the + markdown renderer, tabs, the ?url= loop) is real. */ +vi.mock('../src/api/browse', () => ({ + browse: vi.fn(), +})) + +const browseMock = vi.mocked(browse) + +function snapshot(overrides: Partial = {}): Snapshot { + return { + requestedUrl: 'https://example.test', + finalUrl: 'https://example.test/', + status: 200, + contentType: 'text/html; charset=utf-8', + durationMs: 210, + fetchedAt: '2026-09-16T10:00:00Z', + page: { + title: 'Example Site', + description: 'An example.', + canonical: '', + robotsMeta: '', + lang: 'en', + h1: 'Welcome', + linkCount: 1, + deadLinks: 0, + scriptCount: 1, + imageCount: 0, + wordCount: 12, + textLength: 80, + }, + markdown: '# Welcome\n\nRead the [docs](https://example.test/docs).', + markdownTruncated: false, + files: { + llmsTxt: { + url: 'https://example.test/llms.txt', + status: 200, + contentType: 'text/markdown', + content: '# Example Site\n\n## Docs\n\n- [Guide](https://example.test/guide): the guide\n', + truncated: false, + llmsDoc: { + title: 'Example Site', + description: '', + sections: [ + { + heading: 'Docs', + description: '', + links: [{ title: 'Guide', url: 'https://example.test/guide', description: 'the guide' }], + }, + ], + linkCount: 1, + }, + }, + llmsFullTxt: null, + wellKnownLlmsTxt: null, + robotsTxt: { + url: 'https://example.test/robots.txt', + status: 200, + contentType: 'text/plain', + content: 'User-agent: *\nAllow: /\n', + truncated: false, + }, + }, + checks: [ + { id: 'page.status', label: 'Page reachable', severity: 'ok', detail: '200 OK' }, + { id: 'llms.txt', label: '/llms.txt', severity: 'ok', detail: 'found' }, + { id: 'page.description', label: 'Meta description', severity: 'warn', detail: 'thin' }, + ], + ...overrides, + } +} + +function renderPage() { + return render( + new Map(), dedupingInterval: 0 }}> + + , + ) +} + +beforeEach(() => { + window.history.replaceState(null, '', '/') + browseMock.mockReset() +}) + +afterEach(() => { + vi.clearAllMocks() +}) + +describe('AgentViewPage', () => { + it('stays on the explainer until a domain is submitted', () => { + browseMock.mockResolvedValue(snapshot()) + renderPage() + expect(screen.getByText(/What does your site look like to an LLM/i)).toBeInTheDocument() + expect(browseMock).not.toHaveBeenCalled() + }) + + it('fetches the domain and renders the markdown with live links', async () => { + browseMock.mockResolvedValue(snapshot()) + renderPage() + + fireEvent.change(screen.getByLabelText(/domain or url/i), { target: { value: 'example.test' } }) + fireEvent.click(screen.getByRole('button', { name: /view as agent/i })) + + await waitFor(() => expect(browseMock).toHaveBeenCalledWith('example.test')) + expect(await screen.findByRole('heading', { level: 1, name: 'Welcome' })).toBeInTheDocument() + + const link = screen.getByRole('link', { name: 'docs' }) + expect(link).toHaveAttribute('href', 'https://example.test/docs') + + expect(screen.getByText(/210 ms/i)).toBeInTheDocument() + }) + + it('re-enters the viewer when a markdown link is clicked', async () => { + browseMock.mockResolvedValue(snapshot()) + renderPage() + + fireEvent.change(screen.getByLabelText(/domain or url/i), { target: { value: 'example.test' } }) + fireEvent.click(screen.getByRole('button', { name: /view as agent/i })) + fireEvent.click(await screen.findByRole('link', { name: 'docs' })) + + await waitFor(() => expect(browseMock).toHaveBeenCalledWith('https://example.test/docs')) + }) + + it('shows the parsed llms.txt and the checks', async () => { + browseMock.mockResolvedValue(snapshot()) + renderPage() + + fireEvent.change(screen.getByLabelText(/domain or url/i), { target: { value: 'example.test' } }) + fireEvent.click(screen.getByRole('button', { name: /view as agent/i })) + + fireEvent.click(await screen.findByRole('tab', { name: /llms\.txt/i })) + expect((await screen.findAllByText('Example Site')).length).toBeGreaterThan(0) + expect(screen.getByText('Guide')).toBeInTheDocument() + + fireEvent.click(screen.getByRole('tab', { name: /checks/i })) + expect(await screen.findByText('Page reachable')).toBeInTheDocument() + expect(screen.getByText(/warnings/)).toBeInTheDocument() + }) + + it('surfaces fetch failures with a retry', async () => { + browseMock.mockRejectedValue( + new (await import('../src/api/client')).ApiError(502, 'unavailable', 'could not fetch https://down.test/'), + ) + renderPage() + + fireEvent.change(screen.getByLabelText(/domain or url/i), { target: { value: 'down.test' } }) + fireEvent.click(screen.getByRole('button', { name: /view as agent/i })) + + expect(await screen.findByText(/the site did not answer/i)).toBeInTheDocument() + fireEvent.click(screen.getByRole('button', { name: /try again/i })) + await waitFor(() => expect(browseMock).toHaveBeenCalledTimes(2)) + }) +}) diff --git a/frontend/tests/markdown.test.ts b/frontend/tests/markdown.test.ts new file mode 100644 index 0000000..0ce7973 --- /dev/null +++ b/frontend/tests/markdown.test.ts @@ -0,0 +1,107 @@ +import { describe, expect, it } from 'vitest' +import { parseInline, parseMarkdown } from '../src/components/markdown/parse' +import type { InlineSpan } from '../src/components/markdown/parse' + +/* Parser tests pin the shapes the Go converter emits — this renderer never + sees arbitrary markdown, so these cases are the whole contract. */ + +function text(spans: InlineSpan[]): string { + return spans.map(span => (span.kind === 'text' ? span.text : '')).join('') +} + +describe('parseMarkdown blocks', () => { + it('parses headings, paragraphs and rules', () => { + const blocks = parseMarkdown('# Title\n\nBody text.\n\n---\n\n### Deep') + expect(blocks).toEqual([ + { kind: 'heading', level: 1, spans: [{ kind: 'text', text: 'Title' }] }, + { kind: 'paragraph', spans: [{ kind: 'text', text: 'Body text.' }] }, + { kind: 'hr' }, + { kind: 'heading', level: 3, spans: [{ kind: 'text', text: 'Deep' }] }, + ]) + }) + + it('parses fenced code with language', () => { + const blocks = parseMarkdown('```go\nfmt.Println("hi")\n```') + expect(blocks).toEqual([{ kind: 'code', language: 'go', text: 'fmt.Println("hi")' }]) + }) + + it('parses blockquotes by re-parsing their content', () => { + const blocks = parseMarkdown('> quoted\n> more') + expect(blocks).toEqual([ + { + kind: 'quote', + blocks: [{ kind: 'paragraph', spans: [{ kind: 'text', text: 'quoted more' }] }], + }, + ]) + }) + + it('parses flat and nested lists', () => { + const blocks = parseMarkdown('- one\n- two\n 1. inner\n3. three') + expect(blocks).toEqual([ + { + kind: 'list', + ordered: false, + start: 1, + items: [ + { spans: [{ kind: 'text', text: 'one' }] }, + { + spans: [{ kind: 'text', text: 'two' }], + sub: { + kind: 'list', + ordered: true, + start: 1, + items: [{ spans: [{ kind: 'text', text: 'inner' }] }], + }, + }, + ], + }, + { + kind: 'list', + ordered: true, + start: 3, + items: [{ spans: [{ kind: 'text', text: 'three' }] }], + }, + ]) + }) + + it('parses GFM tables', () => { + const blocks = parseMarkdown('| A | B |\n| --- | --- |\n| 1 | 2 |') + expect(blocks).toEqual([{ kind: 'table', head: ['A', 'B'], rows: [['1', '2']] }]) + }) +}) + +describe('parseInline', () => { + it('splits links, code and emphasis', () => { + const spans = parseInline('see [Docs](https://x.test/d) and `code` plus **bold** *em* ~~gone~~') + expect(spans).toEqual([ + { kind: 'text', text: 'see ' }, + { kind: 'link', href: 'https://x.test/d', spans: [{ kind: 'text', text: 'Docs' }] }, + { kind: 'text', text: ' and ' }, + { kind: 'code', text: 'code' }, + { kind: 'text', text: ' plus ' }, + { kind: 'strong', spans: [{ kind: 'text', text: 'bold' }] }, + { kind: 'text', text: ' ' }, + { kind: 'em', spans: [{ kind: 'text', text: 'em' }] }, + { kind: 'text', text: ' ' }, + { kind: 'del', spans: [{ kind: 'text', text: 'gone' }] }, + ]) + }) + + it('parses images with alt text', () => { + const spans = parseInline('![Logo](https://x.test/l.png)') + expect(spans).toEqual([{ kind: 'image', alt: 'Logo', src: 'https://x.test/l.png' }]) + }) + + it('keeps link titles out of the href', () => { + const spans = parseInline('[API](https://x.test "the api")') + expect(spans).toEqual([ + { kind: 'link', href: 'https://x.test', spans: [{ kind: 'text', text: 'API' }] }, + ]) + }) + + it('leaves plain text untouched', () => { + const spans = parseInline('just words') + expect(spans).toHaveLength(1) + expect(text(spans)).toBe('just words') + }) +})