feat(webui2): new webui with code browser, bug operations, auth

Michael Murรฉ and Claude Sonnet 4.6 created

Squashed from webui2 branch โ€” adds the complete new React/Vite/shadcn
webui (webui2/) along with Go backend additions for code browsing,
multi-repo support, and server config API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Change summary

api/auth/middleware.go                        |    23 
api/auth/oauth/github.go                      |    79 
api/auth/oauth/provider.go                    |    37 
api/auth/session.go                           |    54 
api/graphql/graph/prelude.generated.go        |    30 
api/graphql/graph/repository.generated.go     |    85 
api/graphql/graph/root.generated.go           |   222 
api/graphql/graph/root_.generated.go          |    55 
api/graphql/handler.go                        |    13 
api/graphql/models/gen_models.go              |    10 
api/graphql/resolvers/query.go                |    19 
api/graphql/resolvers/repo.go                 |     6 
api/graphql/resolvers/root.go                 |    11 
api/graphql/schema/repository.graphql         |     4 
api/graphql/schema/root.graphql               |    14 
api/http/auth_handler.go                      |   404 
api/http/git_browse_handler.go                |   442 
cache/multi_repo_cache.go                     |    19 
cache/repo_cache_common.go                    |    28 
commands/webui.go                             |    78 
doc/man/git-bug-webui.1                       |     8 
doc/md/git-bug_webui.md                       |    18 
go.mod                                        |     1 
repository/gogit.go                           |   288 
repository/mock_repo.go                       |     5 
repository/repo.go                            |    58 
webui2/.gitignore                             |    19 
webui2/.tool-versions                         |     1 
webui2/README.md                              |    58 
webui2/codegen.ts                             |    28 
webui2/components.json                        |    20 
webui2/index.html                             |    13 
webui2/package-lock.json                      | 14614 +++++++++++++++++++++
webui2/package.json                           |    48 
webui2/postcss.config.js                      |     6 
webui2/src/App.tsx                            |    52 
webui2/src/__generated__/graphql.ts           |   826 +
webui2/src/components/bugs/BugRow.tsx         |    78 
webui2/src/components/bugs/CommentBox.tsx     |   139 
webui2/src/components/bugs/IssueFilters.tsx   |   303 
webui2/src/components/bugs/LabelBadge.tsx     |    40 
webui2/src/components/bugs/LabelEditor.tsx    |    97 
webui2/src/components/bugs/QueryInput.tsx     |   341 
webui2/src/components/bugs/StatusBadge.tsx    |    28 
webui2/src/components/bugs/Timeline.tsx       |   225 
webui2/src/components/bugs/TitleEditor.tsx    |    98 
webui2/src/components/code/CodeBreadcrumb.tsx |    48 
webui2/src/components/code/CommitList.tsx     |   158 
webui2/src/components/code/FileTree.tsx       |   112 
webui2/src/components/code/FileViewer.tsx     |   113 
webui2/src/components/code/RefSelector.tsx    |   107 
webui2/src/components/content/Markdown.tsx    |    26 
webui2/src/components/layout/Header.tsx       |   132 
webui2/src/components/layout/Shell.tsx        |    15 
webui2/src/components/ui/avatar.tsx           |    44 
webui2/src/components/ui/badge.tsx            |    30 
webui2/src/components/ui/button.tsx           |    52 
webui2/src/components/ui/input.tsx            |    21 
webui2/src/components/ui/popover.tsx          |    28 
webui2/src/components/ui/separator.tsx        |    23 
webui2/src/components/ui/skeleton.tsx         |    12 
webui2/src/components/ui/textarea.tsx         |    20 
webui2/src/graphql/AllIdentities.graphql      |    15 
webui2/src/graphql/BugDetail.graphql          |   104 
webui2/src/graphql/BugList.graphql            |    35 
webui2/src/graphql/BugMutations.graphql       |    83 
webui2/src/graphql/Repositories.graphql       |    10 
webui2/src/graphql/ServerConfig.graphql       |     7 
webui2/src/graphql/UserProfile.graphql        |    57 
webui2/src/graphql/ValidLabels.graphql        |    14 
webui2/src/index.css                          |    81 
webui2/src/lib/apollo.ts                      |    19 
webui2/src/lib/auth.tsx                       |   177 
webui2/src/lib/gitApi.ts                      |    92 
webui2/src/lib/repo.tsx                       |    29 
webui2/src/lib/theme.tsx                      |    38 
webui2/src/lib/utils.ts                       |     6 
webui2/src/main.tsx                           |    20 
webui2/src/pages/BugDetailPage.tsx            |   134 
webui2/src/pages/BugListPage.tsx              |   296 
webui2/src/pages/CodePage.tsx                 |   179 
webui2/src/pages/CommitPage.tsx               |   165 
webui2/src/pages/IdentitySelectPage.tsx       |   124 
webui2/src/pages/NewBugPage.tsx               |   118 
webui2/src/pages/RepoPickerPage.tsx           |    55 
webui2/src/pages/UserProfilePage.tsx          |   278 
webui2/tailwind.config.ts                     |    74 
webui2/tsconfig.app.json                      |    24 
webui2/tsconfig.app.tsbuildinfo               |     0 
webui2/tsconfig.json                          |     7 
webui2/tsconfig.node.json                     |    18 
webui2/tsconfig.node.tsbuildinfo              |     1 
webui2/vite.config.ts                         |    24 
93 files changed, 22,244 insertions(+), 26 deletions(-)

Detailed changes

api/auth/middleware.go ๐Ÿ”—

@@ -6,6 +6,9 @@ import (
 	"github.com/git-bug/git-bug/entity"
 )
 
+// Middleware injects a fixed identity into every request context.
+// Used in local single-user mode where auth is implicit (identity comes from
+// git config at server startup rather than per-request login).
 func Middleware(fixedUserId entity.Id) func(http.Handler) http.Handler {
 	return func(next http.Handler) http.Handler {
 		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@@ -14,3 +17,23 @@ func Middleware(fixedUserId entity.Id) func(http.Handler) http.Handler {
 		})
 	}
 }
+
+// SessionMiddleware reads the session cookie on every request and, when a
+// valid session exists, injects the corresponding identity ID into the context.
+//
+// Requests without a valid session are served as unauthenticated rather than
+// rejected: GraphQL's userIdentity field returns null and mutations fail with
+// ErrNotAuthenticated. This allows the frontend to gracefully degrade rather
+// than receiving hard HTTP errors for every unauthenticated page load.
+func SessionMiddleware(store *SessionStore) func(http.Handler) http.Handler {
+	return func(next http.Handler) http.Handler {
+		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+			if cookie, err := r.Cookie(SessionCookie); err == nil {
+				if id, ok := store.Get(cookie.Value); ok {
+					r = r.WithContext(CtxWithUser(r.Context(), id))
+				}
+			}
+			next.ServeHTTP(w, r)
+		})
+	}
+}

api/auth/oauth/github.go ๐Ÿ”—

@@ -0,0 +1,79 @@
+package oauth
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	"net/http"
+
+	"golang.org/x/oauth2"
+	"golang.org/x/oauth2/github"
+)
+
+var _ Provider = &GitHub{}
+
+// GitHub implements Provider for GitHub OAuth2.
+// It uses the standard authorization-code flow (not the device flow used by
+// the bridge) because the webui has a browser redirect available.
+type GitHub struct {
+	clientID     string
+	clientSecret string
+}
+
+func NewGitHub(clientID, clientSecret string) *GitHub {
+	return &GitHub{clientID: clientID, clientSecret: clientSecret}
+}
+
+func (g *GitHub) Name() string      { return "github" }
+func (g *GitHub) HumanName() string { return "GitHub" }
+
+func (g *GitHub) config(callbackURL string) *oauth2.Config {
+	return &oauth2.Config{
+		ClientID:     g.clientID,
+		ClientSecret: g.clientSecret,
+		Endpoint:     github.Endpoint,
+		RedirectURL:  callbackURL,
+		// read:user for profile; user:email to get the primary email even when
+		// the user's email is set to private on their GitHub profile.
+		Scopes: []string{"read:user", "user:email"},
+	}
+}
+
+func (g *GitHub) AuthURL(state, callbackURL string) string {
+	return g.config(callbackURL).AuthCodeURL(state, oauth2.AccessTypeOnline)
+}
+
+func (g *GitHub) Exchange(ctx context.Context, code, callbackURL string) (*UserInfo, error) {
+	token, err := g.config(callbackURL).Exchange(ctx, code)
+	if err != nil {
+		return nil, fmt.Errorf("github: token exchange: %w", err)
+	}
+
+	client := g.config(callbackURL).Client(ctx, token)
+	resp, err := client.Get("https://api.github.com/user")
+	if err != nil {
+		return nil, fmt.Errorf("github: fetch profile: %w", err)
+	}
+	defer resp.Body.Close()
+
+	if resp.StatusCode != http.StatusOK {
+		return nil, fmt.Errorf("github: unexpected status %d from /user", resp.StatusCode)
+	}
+
+	var u struct {
+		Login     string `json:"login"`
+		Email     string `json:"email"`
+		Name      string `json:"name"`
+		AvatarURL string `json:"avatar_url"`
+	}
+	if err := json.NewDecoder(resp.Body).Decode(&u); err != nil {
+		return nil, fmt.Errorf("github: decode profile: %w", err)
+	}
+
+	return &UserInfo{
+		Login:     u.Login,
+		Email:     u.Email,
+		Name:      u.Name,
+		AvatarURL: u.AvatarURL,
+	}, nil
+}

api/auth/oauth/provider.go ๐Ÿ”—

@@ -0,0 +1,37 @@
+// Package oauth defines the Provider interface and UserInfo type used for
+// external OAuth2 authentication in the webui.
+//
+// Each concrete provider (GitHub, GitLab, โ€ฆ) implements Provider and is
+// registered by passing it to the auth handler at server startup.
+// The generic oauth2 flow (PKCE, state, cookie) is handled by the auth
+// handler; providers only need to supply endpoints and profile fetching.
+package oauth
+
+import "context"
+
+// Provider represents an external OAuth2 identity provider.
+type Provider interface {
+	// Name returns the machine-readable identifier, e.g. "github".
+	Name() string
+
+	// HumanName returns a user-facing display label, e.g. "GitHub".
+	HumanName() string
+
+	// AuthURL returns the URL the browser should be redirected to in order
+	// to begin the authorization-code flow.
+	AuthURL(state, callbackURL string) string
+
+	// Exchange converts an authorization code into a normalised UserInfo.
+	// The callbackURL must match the one used in AuthURL.
+	Exchange(ctx context.Context, code, callbackURL string) (*UserInfo, error)
+}
+
+// UserInfo holds the normalised user profile returned by a provider after a
+// successful OAuth2 exchange. Fields may be empty when the provider does not
+// supply them.
+type UserInfo struct {
+	Login     string
+	Email     string
+	Name      string
+	AvatarURL string
+}

api/auth/session.go ๐Ÿ”—

@@ -0,0 +1,54 @@
+package auth
+
+import (
+	"crypto/rand"
+	"encoding/base64"
+	"sync"
+
+	"github.com/git-bug/git-bug/entity"
+)
+
+// SessionCookie is the name of the HTTP cookie that holds the session token.
+const SessionCookie = "git-bug-session"
+
+// SessionStore holds in-memory sessions mapping opaque tokens to identity IDs.
+// Sessions are intentionally not persisted: users simply re-authenticate after
+// a server restart. This keeps the implementation simple and dependency-free,
+// which is appropriate for a locally-run webui.
+type SessionStore struct {
+	mu sync.RWMutex
+	m  map[string]entity.Id
+}
+
+func NewSessionStore() *SessionStore {
+	return &SessionStore{m: make(map[string]entity.Id)}
+}
+
+// Create generates a new session token for the given identity, stores it, and
+// returns the token. The token is 32 bytes of crypto/rand encoded as base64url.
+func (s *SessionStore) Create(userId entity.Id) (string, error) {
+	b := make([]byte, 32)
+	if _, err := rand.Read(b); err != nil {
+		return "", err
+	}
+	token := base64.RawURLEncoding.EncodeToString(b)
+	s.mu.Lock()
+	s.m[token] = userId
+	s.mu.Unlock()
+	return token, nil
+}
+
+// Get retrieves the identity ID associated with a token.
+func (s *SessionStore) Get(token string) (entity.Id, bool) {
+	s.mu.RLock()
+	id, ok := s.m[token]
+	s.mu.RUnlock()
+	return id, ok
+}
+
+// Delete removes a session token (logout).
+func (s *SessionStore) Delete(token string) {
+	s.mu.Lock()
+	delete(s.m, token)
+	s.mu.Unlock()
+}

api/graphql/graph/prelude.generated.go ๐Ÿ”—

@@ -2555,6 +2555,36 @@ func (ec *executionContext) marshalNString2string(ctx context.Context, sel ast.S
 	return res
 }
 
+func (ec *executionContext) unmarshalNString2แš•stringแš„(ctx context.Context, v any) ([]string, error) {
+	var vSlice []any
+	vSlice = graphql.CoerceList(v)
+	var err error
+	res := make([]string, len(vSlice))
+	for i := range vSlice {
+		ctx := graphql.WithPathContext(ctx, graphql.NewPathWithIndex(i))
+		res[i], err = ec.unmarshalNString2string(ctx, vSlice[i])
+		if err != nil {
+			return nil, err
+		}
+	}
+	return res, nil
+}
+
+func (ec *executionContext) marshalNString2แš•stringแš„(ctx context.Context, sel ast.SelectionSet, v []string) graphql.Marshaler {
+	ret := make(graphql.Array, len(v))
+	for i := range v {
+		ret[i] = ec.marshalNString2string(ctx, sel, v[i])
+	}
+
+	for _, e := range ret {
+		if e == graphql.Null {
+			return graphql.Null
+		}
+	}
+
+	return ret
+}
+
 func (ec *executionContext) marshalN__Directive2githubแš—comแš‹99designsแš‹gqlgenแš‹graphqlแš‹introspectionแšDirective(ctx context.Context, sel ast.SelectionSet, v introspection.Directive) graphql.Marshaler {
 	return ec.___Directive(ctx, sel, &v)
 }

api/graphql/graph/repository.generated.go ๐Ÿ”—

@@ -19,6 +19,7 @@ import (
 
 type RepositoryResolver interface {
 	Name(ctx context.Context, obj *models.Repository) (*string, error)
+	Slug(ctx context.Context, obj *models.Repository) (string, error)
 	AllBugs(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, query *string) (*models.BugConnection, error)
 	Bug(ctx context.Context, obj *models.Repository, prefix string) (models.BugWrapper, error)
 	AllIdentities(ctx context.Context, obj *models.Repository, after *string, before *string, first *int, last *int) (*models.IdentityConnection, error)
@@ -450,6 +451,50 @@ func (ec *executionContext) fieldContext_Repository_name(_ context.Context, fiel
 	return fc, nil
 }
 
+func (ec *executionContext) _Repository_slug(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
+	fc, err := ec.fieldContext_Repository_slug(ctx, field)
+	if err != nil {
+		return graphql.Null
+	}
+	ctx = graphql.WithFieldContext(ctx, fc)
+	defer func() {
+		if r := recover(); r != nil {
+			ec.Error(ctx, ec.Recover(ctx, r))
+			ret = graphql.Null
+		}
+	}()
+	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+		ctx = rctx // use context from middleware stack in children
+		return ec.resolvers.Repository().Slug(rctx, obj)
+	})
+	if err != nil {
+		ec.Error(ctx, err)
+		return graphql.Null
+	}
+	if resTmp == nil {
+		if !graphql.HasFieldError(ctx, fc) {
+			ec.Errorf(ctx, "must not be null")
+		}
+		return graphql.Null
+	}
+	res := resTmp.(string)
+	fc.Result = res
+	return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Repository_slug(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+	fc = &graphql.FieldContext{
+		Object:     "Repository",
+		Field:      field,
+		IsMethod:   true,
+		IsResolver: true,
+		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+			return nil, errors.New("field of type String does not have child fields")
+		},
+	}
+	return fc, nil
+}
+
 func (ec *executionContext) _Repository_allBugs(ctx context.Context, field graphql.CollectedField, obj *models.Repository) (ret graphql.Marshaler) {
 	fc, err := ec.fieldContext_Repository_allBugs(ctx, field)
 	if err != nil {
@@ -945,6 +990,8 @@ func (ec *executionContext) fieldContext_RepositoryConnection_nodes(_ context.Co
 			switch field.Name {
 			case "name":
 				return ec.fieldContext_Repository_name(ctx, field)
+			case "slug":
+				return ec.fieldContext_Repository_slug(ctx, field)
 			case "allBugs":
 				return ec.fieldContext_Repository_allBugs(ctx, field)
 			case "bug":
@@ -1147,6 +1194,8 @@ func (ec *executionContext) fieldContext_RepositoryEdge_node(_ context.Context,
 			switch field.Name {
 			case "name":
 				return ec.fieldContext_Repository_name(ctx, field)
+			case "slug":
+				return ec.fieldContext_Repository_slug(ctx, field)
 			case "allBugs":
 				return ec.fieldContext_Repository_allBugs(ctx, field)
 			case "bug":
@@ -1221,6 +1270,42 @@ func (ec *executionContext) _Repository(ctx context.Context, sel ast.SelectionSe
 				continue
 			}
 
+			out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+		case "slug":
+			field := field
+
+			innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
+				defer func() {
+					if r := recover(); r != nil {
+						ec.Error(ctx, ec.Recover(ctx, r))
+					}
+				}()
+				res = ec._Repository_slug(ctx, field, obj)
+				if res == graphql.Null {
+					atomic.AddUint32(&fs.Invalids, 1)
+				}
+				return res
+			}
+
+			if field.Deferrable != nil {
+				dfs, ok := deferred[field.Deferrable.Label]
+				di := 0
+				if ok {
+					dfs.AddField(field)
+					di = len(dfs.Values) - 1
+				} else {
+					dfs = graphql.NewFieldSet([]graphql.CollectedField{field})
+					deferred[field.Deferrable.Label] = dfs
+				}
+				dfs.Concurrently(di, func(ctx context.Context) graphql.Marshaler {
+					return innerFunc(ctx, dfs)
+				})
+
+				// don't run the out.Concurrently() call below
+				out.Values[i] = graphql.Null
+				continue
+			}
+
 			out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
 		case "allBugs":
 			field := field

api/graphql/graph/root.generated.go ๐Ÿ”—

@@ -4,6 +4,7 @@ package graph
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"strconv"
 	"sync/atomic"
@@ -28,6 +29,7 @@ type MutationResolver interface {
 	BugSetTitle(ctx context.Context, input models.BugSetTitleInput) (*models.BugSetTitlePayload, error)
 }
 type QueryResolver interface {
+	ServerConfig(ctx context.Context) (*models.ServerConfig, error)
 	Repository(ctx context.Context, ref *string) (*models.Repository, error)
 	Repositories(ctx context.Context, after *string, before *string, first *int, last *int) (*models.RepositoryConnection, error)
 }
@@ -1022,6 +1024,56 @@ func (ec *executionContext) fieldContext_Mutation_bugSetTitle(ctx context.Contex
 	return fc, nil
 }
 
+func (ec *executionContext) _Query_serverConfig(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
+	fc, err := ec.fieldContext_Query_serverConfig(ctx, field)
+	if err != nil {
+		return graphql.Null
+	}
+	ctx = graphql.WithFieldContext(ctx, fc)
+	defer func() {
+		if r := recover(); r != nil {
+			ec.Error(ctx, ec.Recover(ctx, r))
+			ret = graphql.Null
+		}
+	}()
+	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+		ctx = rctx // use context from middleware stack in children
+		return ec.resolvers.Query().ServerConfig(rctx)
+	})
+	if err != nil {
+		ec.Error(ctx, err)
+		return graphql.Null
+	}
+	if resTmp == nil {
+		if !graphql.HasFieldError(ctx, fc) {
+			ec.Errorf(ctx, "must not be null")
+		}
+		return graphql.Null
+	}
+	res := resTmp.(*models.ServerConfig)
+	fc.Result = res
+	return ec.marshalNServerConfig2แš–githubแš—comแš‹gitแš‘bugแš‹gitแš‘bugแš‹apiแš‹graphqlแš‹modelsแšServerConfig(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_Query_serverConfig(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+	fc = &graphql.FieldContext{
+		Object:     "Query",
+		Field:      field,
+		IsMethod:   true,
+		IsResolver: true,
+		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+			switch field.Name {
+			case "authMode":
+				return ec.fieldContext_ServerConfig_authMode(ctx, field)
+			case "oauthProviders":
+				return ec.fieldContext_ServerConfig_oauthProviders(ctx, field)
+			}
+			return nil, fmt.Errorf("no field named %q was found under type ServerConfig", field.Name)
+		},
+	}
+	return fc, nil
+}
+
 func (ec *executionContext) _Query_repository(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
 	fc, err := ec.fieldContext_Query_repository(ctx, field)
 	if err != nil {
@@ -1060,6 +1112,8 @@ func (ec *executionContext) fieldContext_Query_repository(ctx context.Context, f
 			switch field.Name {
 			case "name":
 				return ec.fieldContext_Repository_name(ctx, field)
+			case "slug":
+				return ec.fieldContext_Repository_slug(ctx, field)
 			case "allBugs":
 				return ec.fieldContext_Repository_allBugs(ctx, field)
 			case "bug":
@@ -1286,6 +1340,94 @@ func (ec *executionContext) fieldContext_Query___schema(_ context.Context, field
 	return fc, nil
 }
 
+func (ec *executionContext) _ServerConfig_authMode(ctx context.Context, field graphql.CollectedField, obj *models.ServerConfig) (ret graphql.Marshaler) {
+	fc, err := ec.fieldContext_ServerConfig_authMode(ctx, field)
+	if err != nil {
+		return graphql.Null
+	}
+	ctx = graphql.WithFieldContext(ctx, fc)
+	defer func() {
+		if r := recover(); r != nil {
+			ec.Error(ctx, ec.Recover(ctx, r))
+			ret = graphql.Null
+		}
+	}()
+	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+		ctx = rctx // use context from middleware stack in children
+		return obj.AuthMode, nil
+	})
+	if err != nil {
+		ec.Error(ctx, err)
+		return graphql.Null
+	}
+	if resTmp == nil {
+		if !graphql.HasFieldError(ctx, fc) {
+			ec.Errorf(ctx, "must not be null")
+		}
+		return graphql.Null
+	}
+	res := resTmp.(string)
+	fc.Result = res
+	return ec.marshalNString2string(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_ServerConfig_authMode(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+	fc = &graphql.FieldContext{
+		Object:     "ServerConfig",
+		Field:      field,
+		IsMethod:   false,
+		IsResolver: false,
+		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+			return nil, errors.New("field of type String does not have child fields")
+		},
+	}
+	return fc, nil
+}
+
+func (ec *executionContext) _ServerConfig_oauthProviders(ctx context.Context, field graphql.CollectedField, obj *models.ServerConfig) (ret graphql.Marshaler) {
+	fc, err := ec.fieldContext_ServerConfig_oauthProviders(ctx, field)
+	if err != nil {
+		return graphql.Null
+	}
+	ctx = graphql.WithFieldContext(ctx, fc)
+	defer func() {
+		if r := recover(); r != nil {
+			ec.Error(ctx, ec.Recover(ctx, r))
+			ret = graphql.Null
+		}
+	}()
+	resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (any, error) {
+		ctx = rctx // use context from middleware stack in children
+		return obj.OauthProviders, nil
+	})
+	if err != nil {
+		ec.Error(ctx, err)
+		return graphql.Null
+	}
+	if resTmp == nil {
+		if !graphql.HasFieldError(ctx, fc) {
+			ec.Errorf(ctx, "must not be null")
+		}
+		return graphql.Null
+	}
+	res := resTmp.([]string)
+	fc.Result = res
+	return ec.marshalNString2แš•stringแš„(ctx, field.Selections, res)
+}
+
+func (ec *executionContext) fieldContext_ServerConfig_oauthProviders(_ context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) {
+	fc = &graphql.FieldContext{
+		Object:     "ServerConfig",
+		Field:      field,
+		IsMethod:   false,
+		IsResolver: false,
+		Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) {
+			return nil, errors.New("field of type String does not have child fields")
+		},
+	}
+	return fc, nil
+}
+
 // endregion **************************** field.gotpl *****************************
 
 // region    **************************** input.gotpl *****************************
@@ -1422,6 +1564,28 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
 		switch field.Name {
 		case "__typename":
 			out.Values[i] = graphql.MarshalString("Query")
+		case "serverConfig":
+			field := field
+
+			innerFunc := func(ctx context.Context, fs *graphql.FieldSet) (res graphql.Marshaler) {
+				defer func() {
+					if r := recover(); r != nil {
+						ec.Error(ctx, ec.Recover(ctx, r))
+					}
+				}()
+				res = ec._Query_serverConfig(ctx, field)
+				if res == graphql.Null {
+					atomic.AddUint32(&fs.Invalids, 1)
+				}
+				return res
+			}
+
+			rrm := func(ctx context.Context) graphql.Marshaler {
+				return ec.OperationContext.RootResolverMiddleware(ctx,
+					func(ctx context.Context) graphql.Marshaler { return innerFunc(ctx, out) })
+			}
+
+			out.Concurrently(i, func(ctx context.Context) graphql.Marshaler { return rrm(innerCtx) })
 		case "repository":
 			field := field
 
@@ -1494,8 +1658,66 @@ func (ec *executionContext) _Query(ctx context.Context, sel ast.SelectionSet) gr
 	return out
 }
 
+var serverConfigImplementors = []string{"ServerConfig"}
+
+func (ec *executionContext) _ServerConfig(ctx context.Context, sel ast.SelectionSet, obj *models.ServerConfig) graphql.Marshaler {
+	fields := graphql.CollectFields(ec.OperationContext, sel, serverConfigImplementors)
+
+	out := graphql.NewFieldSet(fields)
+	deferred := make(map[string]*graphql.FieldSet)
+	for i, field := range fields {
+		switch field.Name {
+		case "__typename":
+			out.Values[i] = graphql.MarshalString("ServerConfig")
+		case "authMode":
+			out.Values[i] = ec._ServerConfig_authMode(ctx, field, obj)
+			if out.Values[i] == graphql.Null {
+				out.Invalids++
+			}
+		case "oauthProviders":
+			out.Values[i] = ec._ServerConfig_oauthProviders(ctx, field, obj)
+			if out.Values[i] == graphql.Null {
+				out.Invalids++
+			}
+		default:
+			panic("unknown field " + strconv.Quote(field.Name))
+		}
+	}
+	out.Dispatch(ctx)
+	if out.Invalids > 0 {
+		return graphql.Null
+	}
+
+	atomic.AddInt32(&ec.deferred, int32(len(deferred)))
+
+	for label, dfs := range deferred {
+		ec.processDeferredGroup(graphql.DeferredGroup{
+			Label:    label,
+			Path:     graphql.GetPath(ctx),
+			FieldSet: dfs,
+			Context:  ctx,
+		})
+	}
+
+	return out
+}
+
 // endregion **************************** object.gotpl ****************************
 
 // region    ***************************** type.gotpl *****************************
 
+func (ec *executionContext) marshalNServerConfig2githubแš—comแš‹gitแš‘bugแš‹gitแš‘bugแš‹apiแš‹graphqlแš‹modelsแšServerConfig(ctx context.Context, sel ast.SelectionSet, v models.ServerConfig) graphql.Marshaler {
+	return ec._ServerConfig(ctx, sel, &v)
+}
+
+func (ec *executionContext) marshalNServerConfig2แš–githubแš—comแš‹gitแš‘bugแš‹gitแš‘bugแš‹apiแš‹graphqlแš‹modelsแšServerConfig(ctx context.Context, sel ast.SelectionSet, v *models.ServerConfig) graphql.Marshaler {
+	if v == nil {
+		if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
+			ec.Errorf(ctx, "the requested element is null which the schema does not allow")
+		}
+		return graphql.Null
+	}
+	return ec._ServerConfig(ctx, sel, v)
+}
+
 // endregion ***************************** type.gotpl *****************************

api/graphql/graph/root_.generated.go ๐Ÿ”—

@@ -377,6 +377,7 @@ type ComplexityRoot struct {
 	Query struct {
 		Repositories func(childComplexity int, after *string, before *string, first *int, last *int) int
 		Repository   func(childComplexity int, ref *string) int
+		ServerConfig func(childComplexity int) int
 	}
 
 	Repository struct {
@@ -385,6 +386,7 @@ type ComplexityRoot struct {
 		Bug           func(childComplexity int, prefix string) int
 		Identity      func(childComplexity int, prefix string) int
 		Name          func(childComplexity int) int
+		Slug          func(childComplexity int) int
 		UserIdentity  func(childComplexity int) int
 		ValidLabels   func(childComplexity int, after *string, before *string, first *int, last *int) int
 	}
@@ -401,6 +403,11 @@ type ComplexityRoot struct {
 		Node   func(childComplexity int) int
 	}
 
+	ServerConfig struct {
+		AuthMode       func(childComplexity int) int
+		OauthProviders func(childComplexity int) int
+	}
+
 	Subscription struct {
 		AllEvents      func(childComplexity int, repoRef *string, typename *string) int
 		BugEvents      func(childComplexity int, repoRef *string) int
@@ -1795,6 +1802,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
 
 		return e.complexity.Query.Repository(childComplexity, args["ref"].(*string)), true
 
+	case "Query.serverConfig":
+		if e.complexity.Query.ServerConfig == nil {
+			break
+		}
+
+		return e.complexity.Query.ServerConfig(childComplexity), true
+
 	case "Repository.allBugs":
 		if e.complexity.Repository.AllBugs == nil {
 			break
@@ -1850,6 +1864,13 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
 
 		return e.complexity.Repository.Name(childComplexity), true
 
+	case "Repository.slug":
+		if e.complexity.Repository.Slug == nil {
+			break
+		}
+
+		return e.complexity.Repository.Slug(childComplexity), true
+
 	case "Repository.userIdentity":
 		if e.complexity.Repository.UserIdentity == nil {
 			break
@@ -1911,6 +1932,20 @@ func (e *executableSchema) Complexity(ctx context.Context, typeName, field strin
 
 		return e.complexity.RepositoryEdge.Node(childComplexity), true
 
+	case "ServerConfig.authMode":
+		if e.complexity.ServerConfig.AuthMode == nil {
+			break
+		}
+
+		return e.complexity.ServerConfig.AuthMode(childComplexity), true
+
+	case "ServerConfig.oauthProviders":
+		if e.complexity.ServerConfig.OauthProviders == nil {
+			break
+		}
+
+		return e.complexity.ServerConfig.OauthProviders(childComplexity), true
+
 	case "Subscription.allEvents":
 		if e.complexity.Subscription.AllEvents == nil {
 			break
@@ -2701,6 +2736,10 @@ type OperationEdge {
     """The name of the repository"""
     name: String
 
+    """URL-friendly slug for this repository. Named repos use their name;
+    the default (unnamed) repo derives the slug from the directory basename."""
+    slug: String!
+
     """All the bugs"""
     allBugs(
         """Returns the elements in the list that come after the specified cursor."""
@@ -2759,7 +2798,21 @@ type RepositoryEdge {
   node: Repository!
 }
 `, BuiltIn: false},
-	{Name: "../schema/root.graphql", Input: `type Query {
+	{Name: "../schema/root.graphql", Input: `"""Server-wide configuration, independent of any repository."""
+type ServerConfig {
+    """Authentication mode: 'local' (single user from git config),
+    'oauth' (multi-user via external providers), or 'readonly'."""
+    authMode: String!
+
+    """Names of the OAuth providers enabled on this server, e.g. ['github'].
+    Empty when authMode is not 'oauth'."""
+    oauthProviders: [String!]!
+}
+
+type Query {
+    """Server configuration and authentication mode."""
+    serverConfig: ServerConfig!
+
     """Access a repository by reference/name. If no ref is given, the default repository is returned if any."""
     repository(ref: String): Repository
 

api/graphql/handler.go ๐Ÿ”—

@@ -26,8 +26,17 @@ type Handler struct {
 	io.Closer
 }
 
-func NewHandler(mrc *cache.MultiRepoCache, errorOut io.Writer) Handler {
-	rootResolver := resolvers.NewRootResolver(mrc)
+// ServerConfig carries server-level configuration that is passed down to
+// GraphQL resolvers. It is constructed once at startup and does not change.
+type ServerConfig struct {
+	// AuthMode is one of "local", "oauth", or "readonly".
+	AuthMode string
+	// OAuthProviders lists the names of enabled OAuth providers, e.g. ["github"].
+	OAuthProviders []string
+}
+
+func NewHandler(mrc *cache.MultiRepoCache, cfg ServerConfig, errorOut io.Writer) Handler {
+	rootResolver := resolvers.NewRootResolver(mrc, cfg.AuthMode, cfg.OAuthProviders)
 	config := graph.Config{Resolvers: rootResolver}
 
 	h := handler.New(graph.NewExecutableSchema(config))

api/graphql/models/gen_models.go ๐Ÿ”—

@@ -342,5 +342,15 @@ type RepositoryEdge struct {
 	Node   *Repository `json:"node"`
 }
 
+// Server-wide configuration, independent of any repository.
+type ServerConfig struct {
+	// Authentication mode: 'local' (single user from git config),
+	//     'oauth' (multi-user via external providers), or 'readonly'.
+	AuthMode string `json:"authMode"`
+	// Names of the OAuth providers enabled on this server, e.g. ['github'].
+	//     Empty when authMode is not 'oauth'.
+	OauthProviders []string `json:"oauthProviders"`
+}
+
 type Subscription struct {
 }

api/graphql/resolvers/query.go ๐Ÿ”—

@@ -12,7 +12,23 @@ import (
 var _ graph.QueryResolver = &rootQueryResolver{}
 
 type rootQueryResolver struct {
-	cache *cache.MultiRepoCache
+	cache          *cache.MultiRepoCache
+	authMode       string
+	oauthProviders []string
+}
+
+// ServerConfig returns static server configuration including the auth mode.
+// The frontend uses this to decide whether to show a login button, show "Read only",
+// or operate silently in single-user local mode.
+func (r rootQueryResolver) ServerConfig(_ context.Context) (*models.ServerConfig, error) {
+	providers := r.oauthProviders
+	if providers == nil {
+		providers = []string{}
+	}
+	return &models.ServerConfig{
+		AuthMode:       r.authMode,
+		OauthProviders: providers,
+	}, nil
 }
 
 func (r rootQueryResolver) Repository(_ context.Context, ref *string) (*models.Repository, error) {
@@ -36,6 +52,7 @@ func (r rootQueryResolver) Repository(_ context.Context, ref *string) (*models.R
 }
 
 // Repositories returns all registered repositories as a relay connection.
+// Used by the repo picker UI.
 func (r rootQueryResolver) Repositories(_ context.Context, after *string, before *string, first *int, last *int) (*models.RepositoryConnection, error) {
 	input := models.ConnectionInput{
 		After:  after,

api/graphql/resolvers/repo.go ๐Ÿ”—

@@ -21,6 +21,12 @@ func (repoResolver) Name(_ context.Context, obj *models.Repository) (*string, er
 	return &name, nil
 }
 
+// Slug returns the URL-friendly identifier for the repo, used as the /:repo
+// path segment in the frontend.
+func (repoResolver) Slug(_ context.Context, obj *models.Repository) (string, error) {
+	return obj.Repo.Slug(), nil
+}
+
 func (repoResolver) AllBugs(_ context.Context, obj *models.Repository, after *string, before *string, first *int, last *int, queryStr *string) (*models.BugConnection, error) {
 	input := models.ConnectionInput{
 		Before: before,

api/graphql/resolvers/root.go ๐Ÿ”—

@@ -11,17 +11,24 @@ var _ graph.ResolverRoot = &RootResolver{}
 type RootResolver struct {
 	*cache.MultiRepoCache
 	bugRootSubResolver
+
+	authMode       string
+	oauthProviders []string
 }
 
-func NewRootResolver(mrc *cache.MultiRepoCache) *RootResolver {
+func NewRootResolver(mrc *cache.MultiRepoCache, authMode string, oauthProviders []string) *RootResolver {
 	return &RootResolver{
 		MultiRepoCache: mrc,
+		authMode:       authMode,
+		oauthProviders: oauthProviders,
 	}
 }
 
 func (r RootResolver) Query() graph.QueryResolver {
 	return &rootQueryResolver{
-		cache: r.MultiRepoCache,
+		cache:          r.MultiRepoCache,
+		authMode:       r.authMode,
+		oauthProviders: r.oauthProviders,
 	}
 }
 

api/graphql/schema/repository.graphql ๐Ÿ”—

@@ -2,6 +2,10 @@ type Repository {
     """The name of the repository"""
     name: String
 
+    """URL-friendly slug for this repository. Named repos use their name;
+    the default (unnamed) repo derives the slug from the directory basename."""
+    slug: String!
+
     """All the bugs"""
     allBugs(
         """Returns the elements in the list that come after the specified cursor."""

api/graphql/schema/root.graphql ๐Ÿ”—

@@ -1,4 +1,18 @@
+"""Server-wide configuration, independent of any repository."""
+type ServerConfig {
+    """Authentication mode: 'local' (single user from git config),
+    'oauth' (multi-user via external providers), or 'readonly'."""
+    authMode: String!
+
+    """Names of the OAuth providers enabled on this server, e.g. ['github'].
+    Empty when authMode is not 'oauth'."""
+    oauthProviders: [String!]!
+}
+
 type Query {
+    """Server configuration and authentication mode."""
+    serverConfig: ServerConfig!
+
     """Access a repository by reference/name. If no ref is given, the default repository is returned if any."""
     repository(ref: String): Repository
 

api/http/auth_handler.go ๐Ÿ”—

@@ -0,0 +1,404 @@
+// auth_handler.go implements the HTTP endpoints for the OAuth2 login flow:
+//
+//	GET  /auth/login?provider=<name>  โ€” redirect browser to provider
+//	GET  /auth/callback               โ€” receive code, match identity, set session
+//	GET  /auth/user                   โ€” return current user as JSON
+//	POST /auth/logout                 โ€” clear session cookie
+//	GET  /auth/identities             โ€” list identities available for adoption
+//	POST /auth/adopt                  โ€” link/create identity and start session
+//
+// The flow for a returning user (identity already has provider metadata):
+//
+//	browser โ†’ /auth/login โ†’ provider โ†’ /auth/callback โ†’ set cookie โ†’ /
+//
+// The flow for a first-time user:
+//
+//	browser โ†’ /auth/login โ†’ provider โ†’ /auth/callback
+//	       โ†’ store pending โ†’ /_/auth/select-identity
+//	       โ†’ POST /auth/adopt โ†’ set cookie โ†’ /
+package http
+
+import (
+	"crypto/rand"
+	"encoding/base64"
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"sync"
+	"time"
+
+	apiauth "github.com/git-bug/git-bug/api/auth"
+	"github.com/git-bug/git-bug/api/auth/oauth"
+	"github.com/git-bug/git-bug/cache"
+	"github.com/git-bug/git-bug/entity"
+)
+
+const (
+	oauthStateCookie   = "git-bug-oauth-state"
+	oauthPendingCookie = "git-bug-pending"
+)
+
+// providerMetaKey returns the immutable-metadata key used to link a git-bug
+// identity to an external OAuth provider account. This follows the same
+// convention as the GitHub bridge (metaKeyGithubLogin = "github-login") so
+// that identities imported via the bridge are automatically recognised on
+// first webui login.
+func providerMetaKey(providerName string) string {
+	return providerName + "-login"
+}
+
+// oauthState is JSON-encoded as the OAuth2 state parameter.
+// It carries both a CSRF nonce and the provider name, so the callback can
+// verify the request and dispatch to the right provider without extra cookies.
+type oauthState struct {
+	Nonce    string `json:"nonce"`
+	Provider string `json:"provider"`
+}
+
+// pendingAuth holds the OAuth profile for a user who has authenticated with
+// the provider but has not yet been linked to a git-bug identity.
+// It expires after 10 minutes to limit the window for token reuse.
+type pendingAuth struct {
+	UserInfo  *oauth.UserInfo
+	Provider  string
+	ExpiresAt time.Time
+}
+
+// AuthHandler handles the full OAuth2 login flow. It is intentionally
+// provider-agnostic: concrete providers implement oauth.Provider and are
+// passed in at construction time.
+type AuthHandler struct {
+	mrc       *cache.MultiRepoCache
+	sessions  *apiauth.SessionStore
+	providers map[string]oauth.Provider // provider name โ†’ implementation
+	baseURL   string                    // e.g. "http://localhost:3000"
+
+	// pending maps a short-lived random token (stored in a cookie) to an
+	// OAuth profile that needs identity selection before a real session is
+	// created.
+	pendingMu sync.Mutex
+	pending   map[string]*pendingAuth
+}
+
+func NewAuthHandler(mrc *cache.MultiRepoCache, sessions *apiauth.SessionStore, providers []oauth.Provider, baseURL string) *AuthHandler {
+	pm := make(map[string]oauth.Provider, len(providers))
+	for _, p := range providers {
+		pm[p.Name()] = p
+	}
+	return &AuthHandler{
+		mrc:       mrc,
+		sessions:  sessions,
+		providers: pm,
+		baseURL:   baseURL,
+		pending:   make(map[string]*pendingAuth),
+	}
+}
+
+// callbackURL builds the absolute URL the provider should redirect to.
+// It must match the URL registered in the provider's OAuth app settings.
+func (h *AuthHandler) callbackURL() string {
+	return h.baseURL + "/auth/callback"
+}
+
+// randToken generates a URL-safe random token of n bytes.
+func randToken(n int) (string, error) {
+	b := make([]byte, n)
+	if _, err := rand.Read(b); err != nil {
+		return "", err
+	}
+	return base64.RawURLEncoding.EncodeToString(b), nil
+}
+
+// HandleLogin initiates the OAuth2 authorization-code flow.
+// GET /auth/login?provider=<name>
+func (h *AuthHandler) HandleLogin(w http.ResponseWriter, r *http.Request) {
+	providerName := r.URL.Query().Get("provider")
+	p, ok := h.providers[providerName]
+	if !ok {
+		http.Error(w, fmt.Sprintf("unknown provider %q", providerName), http.StatusBadRequest)
+		return
+	}
+
+	nonce, err := randToken(16)
+	if err != nil {
+		http.Error(w, "internal error", http.StatusInternalServerError)
+		return
+	}
+
+	stateData, _ := json.Marshal(oauthState{Nonce: nonce, Provider: providerName})
+	stateEncoded := base64.RawURLEncoding.EncodeToString(stateData)
+
+	// Store the state in a short-lived cookie for CSRF verification on callback.
+	http.SetCookie(w, &http.Cookie{
+		Name:     oauthStateCookie,
+		Value:    stateEncoded,
+		MaxAge:   300, // 5 minutes โ€” enough time to complete the OAuth redirect
+		HttpOnly: true,
+		SameSite: http.SameSiteLaxMode,
+		Path:     "/",
+	})
+
+	http.Redirect(w, r, p.AuthURL(stateEncoded, h.callbackURL()), http.StatusFound)
+}
+
+// HandleCallback receives the authorization code from the provider.
+// GET /auth/callback?code=...&state=...
+func (h *AuthHandler) HandleCallback(w http.ResponseWriter, r *http.Request) {
+	// CSRF: verify that the state parameter matches the cookie we set.
+	stateCookie, err := r.Cookie(oauthStateCookie)
+	if err != nil || stateCookie.Value != r.URL.Query().Get("state") {
+		http.Error(w, "invalid OAuth state", http.StatusBadRequest)
+		return
+	}
+	http.SetCookie(w, &http.Cookie{Name: oauthStateCookie, MaxAge: -1, Path: "/"})
+
+	stateBytes, err := base64.RawURLEncoding.DecodeString(stateCookie.Value)
+	if err != nil {
+		http.Error(w, "malformed state", http.StatusBadRequest)
+		return
+	}
+	var state oauthState
+	if err := json.Unmarshal(stateBytes, &state); err != nil {
+		http.Error(w, "malformed state", http.StatusBadRequest)
+		return
+	}
+
+	p, ok := h.providers[state.Provider]
+	if !ok {
+		http.Error(w, fmt.Sprintf("unknown provider %q", state.Provider), http.StatusBadRequest)
+		return
+	}
+
+	info, err := p.Exchange(r.Context(), r.URL.Query().Get("code"), h.callbackURL())
+	if err != nil {
+		http.Error(w, "OAuth exchange failed: "+err.Error(), http.StatusBadGateway)
+		return
+	}
+
+	// Try to match to an existing git-bug identity via provider metadata.
+	// This reuses the same metadata key as the GitHub bridge
+	// ("github-login"), so bridge-imported identities are recognised
+	// automatically on first login.
+	metaKey := providerMetaKey(state.Provider)
+	for _, repo := range h.mrc.AllRepos() {
+		id, err := repo.Identities().ResolveIdentityImmutableMetadata(metaKey, info.Login)
+		if err == nil {
+			h.startSession(w, id.Id())
+			http.Redirect(w, r, "/", http.StatusFound)
+			return
+		}
+	}
+
+	// No matching identity โ€” store the OAuth profile temporarily and send
+	// the user to the identity selection page.
+	pendingToken, err := randToken(16)
+	if err != nil {
+		http.Error(w, "internal error", http.StatusInternalServerError)
+		return
+	}
+	h.pendingMu.Lock()
+	h.pending[pendingToken] = &pendingAuth{
+		UserInfo:  info,
+		Provider:  state.Provider,
+		ExpiresAt: time.Now().Add(10 * time.Minute),
+	}
+	h.pendingMu.Unlock()
+
+	http.SetCookie(w, &http.Cookie{
+		Name:     oauthPendingCookie,
+		Value:    pendingToken,
+		MaxAge:   600,
+		HttpOnly: true,
+		SameSite: http.SameSiteLaxMode,
+		Path:     "/",
+	})
+	http.Redirect(w, r, "/_/auth/select-identity", http.StatusFound)
+}
+
+// HandleUser returns the current authenticated user as JSON.
+// GET /auth/user โ€” used by the frontend in oauth mode to poll auth state.
+func (h *AuthHandler) HandleUser(w http.ResponseWriter, r *http.Request) {
+	cookie, err := r.Cookie(apiauth.SessionCookie)
+	if err != nil {
+		w.WriteHeader(http.StatusUnauthorized)
+		return
+	}
+	userId, ok := h.sessions.Get(cookie.Value)
+	if !ok {
+		w.WriteHeader(http.StatusUnauthorized)
+		return
+	}
+
+	for _, repo := range h.mrc.AllRepos() {
+		id, err := repo.Identities().Resolve(userId)
+		if err != nil {
+			continue
+		}
+		w.Header().Set("Content-Type", "application/json")
+		json.NewEncoder(w).Encode(map[string]any{
+			"id":          id.Id().String(),
+			"humanId":     id.Id().Human(),
+			"name":        id.Name(),
+			"displayName": id.DisplayName(),
+			"login":       id.Login(),
+			"email":       id.Email(),
+			"avatarUrl":   id.AvatarUrl(),
+		})
+		return
+	}
+	w.WriteHeader(http.StatusUnauthorized)
+}
+
+// HandleLogout clears the session and redirects to the root.
+// POST /auth/logout
+func (h *AuthHandler) HandleLogout(w http.ResponseWriter, r *http.Request) {
+	if cookie, err := r.Cookie(apiauth.SessionCookie); err == nil {
+		h.sessions.Delete(cookie.Value)
+	}
+	http.SetCookie(w, &http.Cookie{Name: apiauth.SessionCookie, MaxAge: -1, Path: "/"})
+	http.Redirect(w, r, "/", http.StatusFound)
+}
+
+// HandleIdentities returns all identities across all repos for the adoption UI.
+// GET /auth/identities โ€” only valid while a pending auth cookie is present.
+func (h *AuthHandler) HandleIdentities(w http.ResponseWriter, r *http.Request) {
+	if _, ok := h.getPending(r); !ok {
+		http.Error(w, "no pending authentication", http.StatusForbidden)
+		return
+	}
+
+	type identityJSON struct {
+		RepoSlug    string `json:"repoSlug"`
+		Id          string `json:"id"`
+		HumanId     string `json:"humanId"`
+		DisplayName string `json:"displayName"`
+		Login       string `json:"login,omitempty"`
+		AvatarUrl   string `json:"avatarUrl,omitempty"`
+	}
+
+	var identities []identityJSON
+	for _, repo := range h.mrc.AllRepos() {
+		for _, id := range repo.Identities().AllIds() {
+			i, err := repo.Identities().Resolve(id)
+			if err != nil {
+				continue
+			}
+			identities = append(identities, identityJSON{
+				RepoSlug:    repo.Slug(),
+				Id:          i.Id().String(),
+				HumanId:     i.Id().Human(),
+				DisplayName: i.DisplayName(),
+				Login:       i.Login(),
+				AvatarUrl:   i.AvatarUrl(),
+			})
+		}
+	}
+
+	w.Header().Set("Content-Type", "application/json")
+	json.NewEncoder(w).Encode(identities)
+}
+
+// HandleAdopt links the pending OAuth profile to a git-bug identity (existing
+// or newly created) and starts a real session.
+// POST /auth/adopt  body: {"identityId": "<id>"}  or  {"create": true}
+func (h *AuthHandler) HandleAdopt(w http.ResponseWriter, r *http.Request) {
+	pa, ok := h.getPending(r)
+	if !ok {
+		http.Error(w, "no pending authentication", http.StatusForbidden)
+		return
+	}
+
+	var body struct {
+		IdentityId string `json:"identityId"` // empty string โ†’ create new
+	}
+	json.NewDecoder(r.Body).Decode(&body)
+
+	metaKey := providerMetaKey(pa.Provider)
+	var userId entity.Id
+
+	if body.IdentityId == "" {
+		// Create a new git-bug identity from the OAuth profile, tagging it
+		// with the provider metadata so future logins match automatically.
+		repos := h.mrc.AllRepos()
+		if len(repos) == 0 {
+			http.Error(w, "no repositories available", http.StatusInternalServerError)
+			return
+		}
+		created, err := repos[0].Identities().NewRaw(
+			pa.UserInfo.Name,
+			pa.UserInfo.Email,
+			pa.UserInfo.Login,
+			pa.UserInfo.AvatarURL,
+			nil,
+			map[string]string{metaKey: pa.UserInfo.Login},
+		)
+		if err != nil {
+			http.Error(w, "failed to create identity: "+err.Error(), http.StatusInternalServerError)
+			return
+		}
+		userId = created.Id()
+	} else {
+		// Adopt an existing identity by adding the provider metadata to it.
+		// This links the identity to the OAuth account for future logins.
+		id := entity.Id(body.IdentityId)
+		for _, repo := range h.mrc.AllRepos() {
+			cached, err := repo.Identities().Resolve(id)
+			if err != nil {
+				continue
+			}
+			cached.SetMetadata(metaKey, pa.UserInfo.Login)
+			if err := cached.Commit(); err != nil {
+				http.Error(w, "failed to update identity: "+err.Error(), http.StatusInternalServerError)
+				return
+			}
+			userId = cached.Id()
+			break
+		}
+		if userId == "" {
+			http.Error(w, "identity not found", http.StatusNotFound)
+			return
+		}
+	}
+
+	h.clearPending(r, w)
+	h.startSession(w, userId)
+	w.WriteHeader(http.StatusOK)
+}
+
+func (h *AuthHandler) startSession(w http.ResponseWriter, userId entity.Id) {
+	token, err := h.sessions.Create(userId)
+	if err != nil {
+		http.Error(w, "internal error", http.StatusInternalServerError)
+		return
+	}
+	http.SetCookie(w, &http.Cookie{
+		Name:     apiauth.SessionCookie,
+		Value:    token,
+		HttpOnly: true,
+		SameSite: http.SameSiteLaxMode,
+		Path:     "/",
+	})
+}
+
+func (h *AuthHandler) getPending(r *http.Request) (*pendingAuth, bool) {
+	cookie, err := r.Cookie(oauthPendingCookie)
+	if err != nil {
+		return nil, false
+	}
+	h.pendingMu.Lock()
+	pa, ok := h.pending[cookie.Value]
+	h.pendingMu.Unlock()
+	if !ok || time.Now().After(pa.ExpiresAt) {
+		return nil, false
+	}
+	return pa, true
+}
+
+func (h *AuthHandler) clearPending(r *http.Request, w http.ResponseWriter) {
+	if cookie, err := r.Cookie(oauthPendingCookie); err == nil {
+		h.pendingMu.Lock()
+		delete(h.pending, cookie.Value)
+		h.pendingMu.Unlock()
+	}
+	http.SetCookie(w, &http.Cookie{Name: oauthPendingCookie, MaxAge: -1, Path: "/"})
+}

api/http/git_browse_handler.go ๐Ÿ”—

@@ -0,0 +1,442 @@
+package http
+
+import (
+	"encoding/json"
+	"fmt"
+	"net/http"
+	"strconv"
+	"strings"
+
+	"github.com/git-bug/git-bug/cache"
+	"github.com/git-bug/git-bug/repository"
+)
+
+// โ”€โ”€ shared helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+func writeJSON(w http.ResponseWriter, v any) {
+	w.Header().Set("Content-Type", "application/json")
+	if err := json.NewEncoder(w).Encode(v); err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+	}
+}
+
+// browseRepo resolves the default repo from the cache and type-asserts to
+// RepoBrowse. All four handlers use this helper.
+func browseRepo(mrc *cache.MultiRepoCache) (repository.ClockedRepo, repository.RepoBrowse, error) {
+	rc, err := mrc.DefaultRepo()
+	if err != nil {
+		return nil, nil, err
+	}
+	underlying := rc.GetRepo()
+	br, ok := underlying.(repository.RepoBrowse)
+	if !ok {
+		return nil, nil, fmt.Errorf("repository does not support code browsing")
+	}
+	return underlying, br, nil
+}
+
+// resolveTreeAtPath walks the git tree of a commit down to the given path.
+// path may be empty (returns root tree entries) or a slash-separated directory path.
+func resolveTreeAtPath(repo repository.ClockedRepo, commitHash repository.Hash, path string) ([]repository.TreeEntry, error) {
+	commit, err := repo.ReadCommit(commitHash)
+	if err != nil {
+		return nil, err
+	}
+
+	entries, err := repo.ReadTree(commit.TreeHash)
+	if err != nil {
+		return nil, err
+	}
+
+	if path == "" {
+		return entries, nil
+	}
+
+	for _, segment := range strings.Split(path, "/") {
+		if segment == "" {
+			continue
+		}
+		entry, ok := repository.SearchTreeEntry(entries, segment)
+		if !ok {
+			return nil, repository.ErrNotFound
+		}
+		if entry.ObjectType != repository.Tree {
+			return nil, repository.ErrNotFound
+		}
+		entries, err = repo.ReadTree(entry.Hash)
+		if err != nil {
+			return nil, err
+		}
+	}
+	return entries, nil
+}
+
+// resolveBlobAtPath walks the tree to the given file path and returns its hash.
+func resolveBlobAtPath(repo repository.ClockedRepo, commitHash repository.Hash, path string) (repository.Hash, error) {
+	parts := strings.Split(path, "/")
+	dirPath := strings.Join(parts[:len(parts)-1], "/")
+	fileName := parts[len(parts)-1]
+
+	entries, err := resolveTreeAtPath(repo, commitHash, dirPath)
+	if err != nil {
+		return "", err
+	}
+
+	entry, ok := repository.SearchTreeEntry(entries, fileName)
+	if !ok {
+		return "", repository.ErrNotFound
+	}
+	if entry.ObjectType != repository.Blob {
+		return "", repository.ErrNotFound
+	}
+	return entry.Hash, nil
+}
+
+// โ”€โ”€ GET /api/git/refs โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type gitRefsHandler struct{ mrc *cache.MultiRepoCache }
+
+func NewGitRefsHandler(mrc *cache.MultiRepoCache) http.Handler {
+	return &gitRefsHandler{mrc: mrc}
+}
+
+type refResponse struct {
+	Name      string `json:"name"`
+	ShortName string `json:"shortName"`
+	Type      string `json:"type"` // "branch" | "tag"
+	Hash      string `json:"hash"`
+	IsDefault bool   `json:"isDefault"`
+}
+
+func (h *gitRefsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	repo, br, err := browseRepo(h.mrc)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	defaultBranch, _ := br.GetDefaultBranch()
+
+	var refs []refResponse
+
+	for _, prefix := range []string{"refs/heads/", "refs/tags/"} {
+		names, err := repo.ListRefs(prefix)
+		if err != nil {
+			http.Error(w, err.Error(), http.StatusInternalServerError)
+			return
+		}
+		for _, name := range names {
+			hash, err := repo.ResolveRef(name)
+			if err != nil {
+				continue
+			}
+			refType := "branch"
+			if prefix == "refs/tags/" {
+				refType = "tag"
+			}
+			short := strings.TrimPrefix(name, prefix)
+			refs = append(refs, refResponse{
+				Name:      name,
+				ShortName: short,
+				Type:      refType,
+				Hash:      hash.String(),
+				IsDefault: short == defaultBranch,
+			})
+		}
+	}
+
+	writeJSON(w, refs)
+}
+
+// โ”€โ”€ GET /api/git/tree โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type gitTreeHandler struct{ mrc *cache.MultiRepoCache }
+
+func NewGitTreeHandler(mrc *cache.MultiRepoCache) http.Handler {
+	return &gitTreeHandler{mrc: mrc}
+}
+
+type treeEntryResponse struct {
+	Name       string              `json:"name"`
+	Type       string              `json:"type"` // "tree" | "blob"
+	Hash       string              `json:"hash"`
+	Mode       string              `json:"mode"`
+	LastCommit *commitMetaResponse `json:"lastCommit,omitempty"`
+}
+
+func (h *gitTreeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	ref := r.URL.Query().Get("ref")
+	path := r.URL.Query().Get("path")
+
+	if ref == "" {
+		http.Error(w, "missing ref", http.StatusBadRequest)
+		return
+	}
+
+	repo, br, err := browseRepo(h.mrc)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	commitHash, err := resolveRef(repo, ref)
+	if err != nil {
+		http.Error(w, "ref not found: "+ref, http.StatusNotFound)
+		return
+	}
+
+	entries, err := resolveTreeAtPath(repo, commitHash, path)
+	if err == repository.ErrNotFound {
+		http.Error(w, "path not found", http.StatusNotFound)
+		return
+	}
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	// Collect entry names and fetch last commits in one shallow history pass.
+	names := make([]string, len(entries))
+	for i, e := range entries {
+		names[i] = e.Name
+	}
+	lastCommits, _ := br.LastCommitForEntries(ref, path, names) // best-effort
+
+	resp := make([]treeEntryResponse, 0, len(entries))
+	for _, e := range entries {
+		objType := "blob"
+		mode := "100644"
+		if e.ObjectType == repository.Tree {
+			objType = "tree"
+			mode = "040000"
+		}
+
+		item := treeEntryResponse{
+			Name: e.Name,
+			Type: objType,
+			Hash: e.Hash.String(),
+			Mode: mode,
+		}
+		if cm, ok := lastCommits[e.Name]; ok {
+			item.LastCommit = toCommitMetaResponse(cm)
+		}
+
+		resp = append(resp, item)
+	}
+
+	writeJSON(w, resp)
+}
+
+// โ”€โ”€ GET /api/git/blob โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type gitBlobHandler struct{ mrc *cache.MultiRepoCache }
+
+func NewGitBlobHandler(mrc *cache.MultiRepoCache) http.Handler {
+	return &gitBlobHandler{mrc: mrc}
+}
+
+type blobResponse struct {
+	Path     string `json:"path"`
+	Content  string `json:"content"`
+	Size     int    `json:"size"`
+	IsBinary bool   `json:"isBinary"`
+}
+
+func (h *gitBlobHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	ref := r.URL.Query().Get("ref")
+	path := r.URL.Query().Get("path")
+
+	if ref == "" || path == "" {
+		http.Error(w, "missing ref or path", http.StatusBadRequest)
+		return
+	}
+
+	repo, _, err := browseRepo(h.mrc)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	commitHash, err := resolveRef(repo, ref)
+	if err != nil {
+		http.Error(w, "ref not found: "+ref, http.StatusNotFound)
+		return
+	}
+
+	blobHash, err := resolveBlobAtPath(repo, commitHash, path)
+	if err == repository.ErrNotFound {
+		http.Error(w, "path not found", http.StatusNotFound)
+		return
+	}
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	data, err := repo.ReadData(blobHash)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	isBinary := isBinaryContent(data)
+	content := ""
+	if !isBinary {
+		content = string(data)
+	}
+
+	writeJSON(w, blobResponse{
+		Path:     path,
+		Content:  content,
+		Size:     len(data),
+		IsBinary: isBinary,
+	})
+}
+
+// โ”€โ”€ GET /api/git/commits โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type gitCommitsHandler struct{ mrc *cache.MultiRepoCache }
+
+func NewGitCommitsHandler(mrc *cache.MultiRepoCache) http.Handler {
+	return &gitCommitsHandler{mrc: mrc}
+}
+
+type commitMetaResponse struct {
+	Hash        string `json:"hash"`
+	ShortHash   string `json:"shortHash"`
+	Message     string `json:"message"`
+	AuthorName  string `json:"authorName"`
+	AuthorEmail string `json:"authorEmail"`
+	Date        string `json:"date"` // RFC3339
+	Parents     []string `json:"parents"`
+}
+
+func toCommitMetaResponse(m repository.CommitMeta) *commitMetaResponse {
+	parents := make([]string, len(m.Parents))
+	for i, p := range m.Parents {
+		parents[i] = p.String()
+	}
+	return &commitMetaResponse{
+		Hash:        m.Hash.String(),
+		ShortHash:   m.ShortHash,
+		Message:     m.Message,
+		AuthorName:  m.AuthorName,
+		AuthorEmail: m.AuthorEmail,
+		Date:        m.Date.UTC().Format("2006-01-02T15:04:05Z"),
+		Parents:     parents,
+	}
+}
+
+func (h *gitCommitsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	ref := r.URL.Query().Get("ref")
+	path := r.URL.Query().Get("path")
+	after := repository.Hash(r.URL.Query().Get("after"))
+
+	limit := 20
+	if l := r.URL.Query().Get("limit"); l != "" {
+		if n, err := strconv.Atoi(l); err == nil && n > 0 && n <= 100 {
+			limit = n
+		}
+	}
+
+	if ref == "" {
+		http.Error(w, "missing ref", http.StatusBadRequest)
+		return
+	}
+
+	_, br, err := browseRepo(h.mrc)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	commits, err := br.CommitLog(ref, path, limit, after)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	resp := make([]*commitMetaResponse, len(commits))
+	for i, c := range commits {
+		resp[i] = toCommitMetaResponse(c)
+	}
+	writeJSON(w, resp)
+}
+
+// โ”€โ”€ GET /api/git/commit โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type gitCommitHandler struct{ mrc *cache.MultiRepoCache }
+
+func NewGitCommitHandler(mrc *cache.MultiRepoCache) http.Handler {
+	return &gitCommitHandler{mrc: mrc}
+}
+
+type changedFileResponse struct {
+	Path    string `json:"path"`
+	OldPath string `json:"oldPath,omitempty"`
+	Status  string `json:"status"`
+}
+
+type commitDetailResponse struct {
+	*commitMetaResponse
+	FullMessage string                `json:"fullMessage"`
+	Files       []changedFileResponse `json:"files"`
+}
+
+func (h *gitCommitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	hash := r.URL.Query().Get("hash")
+	if hash == "" {
+		http.Error(w, "missing hash", http.StatusBadRequest)
+		return
+	}
+
+	_, br, err := browseRepo(h.mrc)
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	detail, err := br.CommitDetail(repository.Hash(hash))
+	if err == repository.ErrNotFound {
+		http.Error(w, "commit not found", http.StatusNotFound)
+		return
+	}
+	if err != nil {
+		http.Error(w, err.Error(), http.StatusInternalServerError)
+		return
+	}
+
+	files := make([]changedFileResponse, len(detail.Files))
+	for i, f := range detail.Files {
+		files[i] = changedFileResponse{Path: f.Path, OldPath: f.OldPath, Status: f.Status}
+	}
+
+	writeJSON(w, commitDetailResponse{
+		commitMetaResponse: toCommitMetaResponse(detail.CommitMeta),
+		FullMessage:        detail.FullMessage,
+		Files:              files,
+	})
+}
+
+// โ”€โ”€ utilities โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+// resolveRef tries refs/heads/<ref>, refs/tags/<ref>, then raw hash.
+func resolveRef(repo repository.ClockedRepo, ref string) (repository.Hash, error) {
+	for _, prefix := range []string{"refs/heads/", "refs/tags/", ""} {
+		h, err := repo.ResolveRef(prefix + ref)
+		if err == nil {
+			return h, nil
+		}
+	}
+	return "", repository.ErrNotFound
+}
+
+// isBinaryContent returns true if data contains a null byte (simple heuristic).
+func isBinaryContent(data []byte) bool {
+	for _, b := range data {
+		if b == 0 {
+			return true
+		}
+	}
+	return false
+}

cache/multi_repo_cache.go ๐Ÿ”—

@@ -60,13 +60,20 @@ func (c *MultiRepoCache) DefaultRepo() (*RepoCache, error) {
 	panic("unreachable")
 }
 
-// ResolveRepo retrieves a repository by name
-func (c *MultiRepoCache) ResolveRepo(name string) (*RepoCache, error) {
-	r, ok := c.repos[name]
-	if !ok {
-		return nil, fmt.Errorf("unknown repo")
+// ResolveRepo retrieve a repository by name or slug
+func (c *MultiRepoCache) ResolveRepo(ref string) (*RepoCache, error) {
+	// Direct name lookup first
+	if r, ok := c.repos[ref]; ok {
+		return r, nil
+	}
+	// Slug lookup fallback โ€” allows using the human-readable slug (derived
+	// from the path basename) instead of the internal cache name.
+	for _, r := range c.repos {
+		if r.Slug() == ref {
+			return r, nil
+		}
 	}
-	return r, nil
+	return nil, fmt.Errorf("unknown repo %q", ref)
 }
 
 // AllRepos returns all registered repositories. Order is not guaranteed.

cache/repo_cache_common.go ๐Ÿ”—

@@ -1,6 +1,7 @@
 package cache
 
 import (
+	"path/filepath"
 	"sync"
 
 	"github.com/pkg/errors"
@@ -15,6 +16,26 @@ func (c *RepoCache) Name() string {
 	return c.name
 }
 
+// GetPath returns the root directory path of the underlying git repository.
+func (c *RepoCache) GetPath() string {
+	return c.repo.GetPath()
+}
+
+// Slug returns a URL-friendly identifier for this repository.
+// Named repos use their registered name. The default ("__default") repo
+// derives its slug from the last component of the filesystem path so
+// URLs look like /git-bug/issues rather than /__default/issues.
+func (c *RepoCache) Slug() string {
+	if c.name != defaultRepoName {
+		return c.name
+	}
+	path := c.repo.GetPath()
+	if path == "" {
+		return c.name
+	}
+	return filepath.Base(path)
+}
+
 // LocalConfig give access to the repository scoped configuration
 func (c *RepoCache) LocalConfig() repository.Config {
 	return c.repo.LocalConfig()
@@ -65,6 +86,13 @@ func (c *RepoCache) ReadData(hash repository.Hash) ([]byte, error) {
 	return c.repo.ReadData(hash)
 }
 
+// GetRepo returns the underlying repository for operations not covered by
+// RepoCache (e.g. git object browsing). Callers may type-assert to
+// repository.RepoBrowse for extended read-only access.
+func (c *RepoCache) GetRepo() repository.ClockedRepo {
+	return c.repo
+}
+
 // StoreData will store arbitrary data and return the corresponding hash
 func (c *RepoCache) StoreData(data []byte) (repository.Hash, error) {
 	return c.repo.StoreData(data)

commands/webui.go ๐Ÿ”—

@@ -22,6 +22,7 @@ import (
 	"github.com/spf13/cobra"
 
 	"github.com/git-bug/git-bug/api/auth"
+	"github.com/git-bug/git-bug/api/auth/oauth"
 	"github.com/git-bug/git-bug/api/graphql"
 	httpapi "github.com/git-bug/git-bug/api/http"
 	"github.com/git-bug/git-bug/cache"
@@ -41,6 +42,12 @@ type webUIOptions struct {
 	readOnly  bool
 	logErrors bool
 	query     string
+
+	// OAuth provider credentials. A provider is enabled when both its
+	// client-id and client-secret are non-empty. Multiple providers can be
+	// active simultaneously.
+	githubClientId     string
+	githubClientSecret string
 }
 
 func newWebUICommand(env *execenv.Env) *cobra.Command {
@@ -71,6 +78,11 @@ Available git config:
 	flags.BoolVar(&options.logErrors, "log-errors", false, "Whether to log errors")
 	flags.StringVarP(&options.query, "query", "q", "", "The query to open in the web UI bug list")
 
+	// GitHub OAuth: both flags must be provided together to enable GitHub login.
+	flags.StringVar(&options.githubClientId, "github-client-id", "", "GitHub OAuth application client ID (enables GitHub login)")
+	flags.StringVar(&options.githubClientSecret, "github-client-secret", "", "GitHub OAuth application client secret")
+	cmd.MarkFlagsRequiredTogether("github-client-id", "github-client-secret")
+
 	return cmd
 }
 
@@ -84,7 +96,8 @@ func runWebUI(env *execenv.Env, opts webUIOptions) error {
 	}
 
 	addr := net.JoinHostPort(opts.host, strconv.Itoa(opts.port))
-	webUiAddr := fmt.Sprintf("http://%s", addr)
+	baseURL := fmt.Sprintf("http://%s", addr)
+	webUiAddr := baseURL
 	toOpen := webUiAddr
 
 	if len(opts.query) > 0 {
@@ -92,12 +105,30 @@ func runWebUI(env *execenv.Env, opts webUIOptions) error {
 		toOpen = fmt.Sprintf("%s/?q=%s", webUiAddr, url.QueryEscape(opts.query))
 	}
 
+	// Collect enabled OAuth providers.
+	var providers []oauth.Provider
+	if opts.githubClientId != "" {
+		providers = append(providers, oauth.NewGitHub(opts.githubClientId, opts.githubClientSecret))
+	}
+
+	// Determine auth mode and configure middleware accordingly.
+	var authMode string
+	var sessions *auth.SessionStore
 	router := mux.NewRouter()
 
-	// If the webUI is not read-only, use an authentication middleware with a
-	// fixed identity: the default user of the repo
-	// TODO: support dynamic authentication with OAuth
-	if !opts.readOnly {
+	switch {
+	case opts.readOnly:
+		authMode = "readonly"
+		// No middleware: every request is unauthenticated.
+
+	case len(providers) > 0:
+		authMode = "oauth"
+		sessions = auth.NewSessionStore()
+		router.Use(auth.SessionMiddleware(sessions))
+
+	default:
+		authMode = "local"
+		// Single-user mode: inject the identity from git config for every request.
 		author, err := identity.GetUserIdentity(env.Repo)
 		if err != nil {
 			return err
@@ -119,13 +150,39 @@ func runWebUI(env *execenv.Env, opts webUIOptions) error {
 		errOut = env.Err
 	}
 
-	graphqlHandler := graphql.NewHandler(mrc, errOut)
+	// Collect provider names for GraphQL serverConfig.
+	providerNames := make([]string, len(providers))
+	for i, p := range providers {
+		providerNames[i] = p.Name()
+	}
+
+	graphqlHandler := graphql.NewHandler(mrc, graphql.ServerConfig{
+		AuthMode:       authMode,
+		OAuthProviders: providerNames,
+	}, errOut)
+
+	// Register OAuth routes before the catch-all static handler.
+	if authMode == "oauth" {
+		ah := httpapi.NewAuthHandler(mrc, sessions, providers, baseURL)
+		router.Path("/auth/login").Methods("GET").HandlerFunc(ah.HandleLogin)
+		router.Path("/auth/callback").Methods("GET").HandlerFunc(ah.HandleCallback)
+		router.Path("/auth/user").Methods("GET").HandlerFunc(ah.HandleUser)
+		router.Path("/auth/logout").Methods("POST").HandlerFunc(ah.HandleLogout)
+		router.Path("/auth/identities").Methods("GET").HandlerFunc(ah.HandleIdentities)
+		router.Path("/auth/adopt").Methods("POST").HandlerFunc(ah.HandleAdopt)
+	}
 
 	// Routes
 	router.Path("/playground").Handler(playground.Handler("git-bug", "/graphql"))
 	router.Path("/graphql").Handler(graphqlHandler)
 	router.Path("/gitfile/{repo}/{hash}").Handler(httpapi.NewGitFileHandler(mrc))
 	router.Path("/upload/{repo}").Methods("POST").Handler(httpapi.NewGitUploadFileHandler(mrc))
+	// Git browsing API (used by the code browser UI)
+	router.Path("/api/git/refs").Methods("GET").Handler(httpapi.NewGitRefsHandler(mrc))
+	router.Path("/api/git/tree").Methods("GET").Handler(httpapi.NewGitTreeHandler(mrc))
+	router.Path("/api/git/blob").Methods("GET").Handler(httpapi.NewGitBlobHandler(mrc))
+	router.Path("/api/git/commits").Methods("GET").Handler(httpapi.NewGitCommitsHandler(mrc))
+	router.Path("/api/git/commit").Methods("GET").Handler(httpapi.NewGitCommitHandler(mrc))
 	router.PathPrefix("/").Handler(webui.NewHandler())
 
 	srv := &http.Server{
@@ -157,12 +214,21 @@ func runWebUI(env *execenv.Env, opts webUIOptions) error {
 			env.Out.Println(err)
 		}
 
+		err = mrc.Close()
+		if err != nil {
+			env.Out.Println(err)
+		}
+
 		close(done)
 	}()
 
 	env.Out.Printf("Web UI: %s\n", webUiAddr)
 	env.Out.Printf("Graphql API: http://%s/graphql\n", addr)
 	env.Out.Printf("Graphql Playground: http://%s/playground\n", addr)
+	if authMode == "oauth" {
+		env.Out.Printf("OAuth callback URL: %s/auth/callback\n", baseURL)
+		env.Out.Println("  โ†ณ Register this URL in your OAuth application settings")
+	}
 	env.Out.Println("Press Ctrl+c to quit")
 
 	configOpen, err := env.Repo.AnyConfig().ReadBool(webUIOpenConfigKey)

doc/man/git-bug-webui.1 ๐Ÿ”—

@@ -45,6 +45,14 @@ Available git config:
 \fB-q\fP, \fB--query\fP=""
 	The query to open in the web UI bug list
 
+.PP
+\fB--github-client-id\fP=""
+	GitHub OAuth application client ID (enables GitHub login)
+
+.PP
+\fB--github-client-secret\fP=""
+	GitHub OAuth application client secret
+
 .PP
 \fB-h\fP, \fB--help\fP[=false]
 	help for webui

doc/md/git-bug_webui.md ๐Ÿ”—

@@ -17,14 +17,16 @@ git-bug webui [flags]
 ### Options
 
 ```
-      --host string    Network address or hostname to listen to (default to 127.0.0.1) (default "127.0.0.1")
-      --open           Automatically open the web UI in the default browser
-      --no-open        Prevent the automatic opening of the web UI in the default browser
-  -p, --port int       Port to listen to (default to random available port)
-      --read-only      Whether to run the web UI in read-only mode
-      --log-errors     Whether to log errors
-  -q, --query string   The query to open in the web UI bug list
-  -h, --help           help for webui
+      --host string                   Network address or hostname to listen to (default to 127.0.0.1) (default "127.0.0.1")
+      --open                          Automatically open the web UI in the default browser
+      --no-open                       Prevent the automatic opening of the web UI in the default browser
+  -p, --port int                      Port to listen to (default to random available port)
+      --read-only                     Whether to run the web UI in read-only mode
+      --log-errors                    Whether to log errors
+  -q, --query string                  The query to open in the web UI bug list
+      --github-client-id string       GitHub OAuth application client ID (enables GitHub login)
+      --github-client-secret string   GitHub OAuth application client secret
+  -h, --help                          help for webui
 ```
 
 ### SEE ALSO

go.mod ๐Ÿ”—

@@ -87,6 +87,7 @@ require (
 	github.com/golang/snappy v0.0.4 // indirect
 	github.com/google/go-querystring v1.1.0 // indirect
 	github.com/google/uuid v1.6.0 // indirect
+	github.com/gorilla/websocket v1.5.3
 	github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
 	github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
 	github.com/hashicorp/go-retryablehttp v0.7.7 // indirect

repository/gogit.go ๐Ÿ”—

@@ -827,6 +827,288 @@ func (repo *GoGitRepo) ReadCommit(hash Hash) (Commit, error) {
 	return result, nil
 }
 
+var _ RepoBrowse = &GoGitRepo{}
+
+func (repo *GoGitRepo) GetDefaultBranch() (string, error) {
+	repo.rMutex.Lock()
+	defer repo.rMutex.Unlock()
+
+	head, err := repo.r.Head()
+	if err != nil {
+		return "main", nil // sensible fallback for detached HEAD
+	}
+	return head.Name().Short(), nil
+}
+
+func (repo *GoGitRepo) ReadCommitMeta(hash Hash) (CommitMeta, error) {
+	repo.rMutex.Lock()
+	defer repo.rMutex.Unlock()
+
+	commit, err := repo.r.CommitObject(plumbing.NewHash(hash.String()))
+	if err == plumbing.ErrObjectNotFound {
+		return CommitMeta{}, ErrNotFound
+	}
+	if err != nil {
+		return CommitMeta{}, err
+	}
+
+	return commitToMeta(commit), nil
+}
+
+func (repo *GoGitRepo) CommitLog(ref string, path string, limit int, after Hash) ([]CommitMeta, error) {
+	repo.rMutex.Lock()
+	defer repo.rMutex.Unlock()
+
+	h, err := repo.resolveShortRef(ref)
+	if err != nil {
+		return nil, err
+	}
+
+	opts := &gogit.LogOptions{From: h}
+	if path != "" {
+		opts.PathFilter = func(p string) bool {
+			return p == path || strings.HasPrefix(p, path+"/")
+		}
+		// PathFilter requires OrderCommitterTime for correct results
+		opts.Order = gogit.LogOrderCommitterTime
+	}
+
+	iter, err := repo.r.Log(opts)
+	if err != nil {
+		return nil, err
+	}
+	defer iter.Close()
+
+	var commits []CommitMeta
+	skipping := after != ""
+
+	for {
+		if len(commits) >= limit {
+			break
+		}
+		commit, err := iter.Next()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return nil, err
+		}
+		if skipping {
+			if Hash(commit.Hash.String()) == after {
+				skipping = false
+			}
+			continue
+		}
+		commits = append(commits, commitToMeta(commit))
+	}
+
+	return commits, nil
+}
+
+// resolveShortRef resolves a short branch/tag name or full ref to a commit hash.
+// Must be called with rMutex held.
+func (repo *GoGitRepo) resolveShortRef(ref string) (plumbing.Hash, error) {
+	// Try as full ref first, then refs/heads/, refs/tags/, then raw hash.
+	for _, prefix := range []string{"", "refs/heads/", "refs/tags/"} {
+		r, err := repo.r.Reference(plumbing.ReferenceName(prefix+ref), true)
+		if err == nil {
+			return r.Hash(), nil
+		}
+	}
+	// Fall back to treating it as a commit hash directly.
+	h := plumbing.NewHash(ref)
+	if !h.IsZero() {
+		return h, nil
+	}
+	return plumbing.ZeroHash, fmt.Errorf("cannot resolve ref %q", ref)
+}
+
+func commitToMeta(c *object.Commit) CommitMeta {
+	msg := strings.TrimSpace(c.Message)
+	if i := strings.IndexByte(msg, '\n'); i >= 0 {
+		msg = msg[:i]
+	}
+	parents := make([]Hash, len(c.ParentHashes))
+	for i, p := range c.ParentHashes {
+		parents[i] = Hash(p.String())
+	}
+	h := Hash(c.Hash.String())
+	return CommitMeta{
+		Hash:        h,
+		ShortHash:   h.String()[:7],
+		Message:     msg,
+		AuthorName:  c.Author.Name,
+		AuthorEmail: c.Author.Email,
+		Date:        c.Author.When,
+		Parents:     parents,
+	}
+}
+
+// LastCommitForEntries walks the commit history once (newest-first) and returns
+// the most recent commit that modified each named entry in dirPath.
+//
+// Instead of computing recursive tree diffs, it reads only the shallow tree at
+// dirPath for consecutive commits and compares entry hashes directly. This is
+// O(commits ร— entries) with cheap hash comparisons rather than O(commits ร— all
+// changed files in repo).
+func (repo *GoGitRepo) LastCommitForEntries(ref string, dirPath string, names []string) (map[string]CommitMeta, error) {
+	repo.rMutex.Lock()
+	defer repo.rMutex.Unlock()
+
+	h, err := repo.resolveShortRef(ref)
+	if err != nil {
+		return nil, err
+	}
+
+	result := make(map[string]CommitMeta, len(names))
+	if len(names) == 0 {
+		return result, nil
+	}
+
+	// Build lookup set for fast membership test.
+	want := make(map[string]bool, len(names))
+	for _, n := range names {
+		want[n] = true
+	}
+
+	iter, err := repo.r.Log(&gogit.LogOptions{From: h, Order: gogit.LogOrderCommitterTime})
+	if err != nil {
+		return nil, err
+	}
+	defer iter.Close()
+
+	// dirHashes reads the entry hashes at dirPath for the given commit tree.
+	// Returns a map of entry name โ†’ blob/tree hash (shallow, no recursion).
+	dirHashes := func(tree *object.Tree) map[string]plumbing.Hash {
+		t := tree
+		if dirPath != "" {
+			sub, err := tree.Tree(dirPath)
+			if err != nil {
+				return nil
+			}
+			t = sub
+		}
+		m := make(map[string]plumbing.Hash, len(t.Entries))
+		for _, e := range t.Entries {
+			if want[e.Name] {
+				m[e.Name] = e.Hash
+			}
+		}
+		return m
+	}
+
+	// Walk newestโ†’oldest, comparing each commit's directory snapshot with the
+	// previous (newer) commit's snapshot. When a hash differs, the newer commit
+	// is the one that last changed that entry.
+	var prevHashes map[string]plumbing.Hash
+	var prevMeta CommitMeta
+
+	for len(result) < len(names) {
+		commit, err := iter.Next()
+		if err == io.EOF {
+			break
+		}
+		if err != nil {
+			return result, nil
+		}
+
+		tree, err := commit.Tree()
+		if err != nil {
+			continue
+		}
+		currHashes := dirHashes(tree)
+		meta := commitToMeta(commit)
+
+		if prevHashes != nil {
+			for name := range want {
+				if _, done := result[name]; done {
+					continue
+				}
+				prev, inPrev := prevHashes[name]
+				curr, inCurr := currHashes[name]
+				// If the entry existed in prevHashes but differs (or is gone now),
+				// the previous (newer) commit is when it was last changed.
+				if inPrev && (!inCurr || prev != curr) {
+					result[name] = prevMeta
+				}
+			}
+		}
+
+		prevHashes = currHashes
+		prevMeta = meta
+	}
+
+	// Any names still present in prevHashes were last changed at the oldest
+	// commit we reached (the entry existed there and we never saw it change).
+	for name := range want {
+		if _, done := result[name]; done {
+			continue
+		}
+		if _, exists := prevHashes[name]; exists {
+			result[name] = prevMeta
+		}
+	}
+
+	return result, nil
+}
+
+// CommitDetail returns full metadata for a commit plus its changed files.
+func (repo *GoGitRepo) CommitDetail(hash Hash) (CommitDetail, error) {
+	repo.rMutex.Lock()
+	defer repo.rMutex.Unlock()
+
+	commit, err := repo.r.CommitObject(plumbing.NewHash(hash.String()))
+	if err == plumbing.ErrObjectNotFound {
+		return CommitDetail{}, ErrNotFound
+	}
+	if err != nil {
+		return CommitDetail{}, err
+	}
+
+	detail := CommitDetail{
+		CommitMeta:  commitToMeta(commit),
+		FullMessage: strings.TrimSpace(commit.Message),
+	}
+
+	tree, err := commit.Tree()
+	if err != nil {
+		return detail, nil
+	}
+
+	var parentTree *object.Tree
+	if len(commit.ParentHashes) > 0 {
+		if parent, err := commit.Parent(0); err == nil {
+			parentTree, _ = parent.Tree()
+		}
+	}
+	if parentTree == nil {
+		parentTree = &object.Tree{}
+	}
+
+	changes, err := object.DiffTree(parentTree, tree)
+	if err != nil {
+		return detail, nil
+	}
+
+	for _, change := range changes {
+		from, to := change.From.Name, change.To.Name
+		var f ChangedFile
+		switch {
+		case from == "":
+			f = ChangedFile{Path: to, Status: "added"}
+		case to == "":
+			f = ChangedFile{Path: from, Status: "deleted"}
+		case from != to:
+			f = ChangedFile{Path: to, OldPath: from, Status: "renamed"}
+		default:
+			f = ChangedFile{Path: to, Status: "modified"}
+		}
+		detail.Files = append(detail.Files, f)
+	}
+
+	return detail, nil
+}
+
 func (repo *GoGitRepo) AllClocks() (map[string]lamport.Clock, error) {
 	repo.clocksMutex.Lock()
 	defer repo.clocksMutex.Unlock()
@@ -931,6 +1213,12 @@ func (repo *GoGitRepo) GetLocalRemote() string {
 	return repo.path
 }
 
+// GetPath returns the root directory of the repository (strips the trailing
+// /.git component so callers get the working-tree root, not the git dir).
+func (repo *GoGitRepo) GetPath() string {
+	return filepath.Clean(strings.TrimSuffix(repo.path, string(filepath.Separator)+".git"))
+}
+
 // EraseFromDisk delete this repository entirely from the disk
 func (repo *GoGitRepo) EraseFromDisk() error {
 	err := repo.Close()

repository/mock_repo.go ๐Ÿ”—

@@ -119,6 +119,11 @@ func (r *mockRepoCommon) GetRemotes() (map[string]string, error) {
 	}, nil
 }
 
+// GetPath returns an empty string for in-memory mock repos.
+func (r *mockRepoCommon) GetPath() string {
+	return ""
+}
+
 var _ RepoStorage = &mockRepoStorage{}
 
 type mockRepoStorage struct {

repository/repo.go ๐Ÿ”—

@@ -4,6 +4,7 @@ package repository
 import (
 	"errors"
 	"io"
+	"time"
 
 	"github.com/ProtonMail/go-crypto/openpgp"
 	"github.com/go-git/go-billy/v5"
@@ -74,6 +75,11 @@ type RepoCommon interface {
 
 	// GetRemotes returns the configured remotes repositories.
 	GetRemotes() (map[string]string, error)
+
+	// GetPath returns the root directory path of the repository (the directory
+	// that contains the .git folder for bare repos, or the .git folder itself
+	// for bare clones). Returns an empty string for in-memory/mock repos.
+	GetPath() string
 }
 
 type LocalStorage interface {
@@ -193,6 +199,58 @@ type RepoData interface {
 	ListCommits(ref string) ([]Hash, error)
 }
 
+// CommitMeta holds the display-relevant metadata of a git commit.
+type CommitMeta struct {
+	Hash        Hash
+	ShortHash   string
+	Message     string // first line only
+	AuthorName  string
+	AuthorEmail string
+	Date        time.Time
+	Parents     []Hash
+}
+
+// RepoBrowse extends a repo with read-only methods needed for code browsing.
+// Implemented by GoGitRepo; not part of the core Repo interface because not
+// all repository implementations (e.g. in-memory test repos) need it.
+type RepoBrowse interface {
+	// GetDefaultBranch returns the short name of the branch HEAD points to.
+	GetDefaultBranch() (string, error)
+
+	// ReadCommitMeta reads full commit metadata including author and message.
+	ReadCommitMeta(hash Hash) (CommitMeta, error)
+
+	// CommitLog returns up to limit commits reachable from ref (short name or
+	// full ref), optionally filtered to commits that touch path.
+	// If after is non-empty, results start after that commit hash (pagination).
+	CommitLog(ref string, path string, limit int, after Hash) ([]CommitMeta, error)
+
+	// LastCommitForEntries walks the commit history once and returns the most
+	// recent commit that touched each named entry inside dirPath.
+	// dirPath is the directory being browsed (empty = repo root).
+	// names are the immediate child names (files/dirs) inside that directory.
+	// The returned map is keyed by entry name; missing entries were not found.
+	LastCommitForEntries(ref string, dirPath string, names []string) (map[string]CommitMeta, error)
+
+	// CommitDetail returns the full metadata for a single commit plus the list
+	// of files it changed relative to its first parent.
+	CommitDetail(hash Hash) (CommitDetail, error)
+}
+
+// ChangedFile describes a single file changed by a commit.
+type ChangedFile struct {
+	Path    string // current path (or old path for deletions)
+	OldPath string // only set for renames
+	Status  string // "added" | "modified" | "deleted" | "renamed"
+}
+
+// CommitDetail extends CommitMeta with the full message body and changed files.
+type CommitDetail struct {
+	CommitMeta
+	FullMessage string
+	Files       []ChangedFile
+}
+
 // RepoClock give access to Lamport clocks
 type RepoClock interface {
 	// AllClocks return all the known clocks

webui2/.gitignore ๐Ÿ”—

@@ -0,0 +1,19 @@
+# See https://help.github.com/ignore-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/build
+
+# testing
+/coverage
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*

webui2/README.md ๐Ÿ”—

@@ -0,0 +1,58 @@
+# webui2
+
+New web interface for git-bug. Built with Vite + React + TypeScript + Tailwind + shadcn/ui.
+
+## Quickstart
+
+You need two processes running:
+
+```bash
+# 1. Go backend (from repo root)
+go run . webui --port 3000
+
+# 2. Vite dev server (from this directory)
+npm install
+npm run dev
+```
+
+Open http://localhost:5173. Vite proxies `/graphql`, `/api`, `/gitfile`, and `/upload` to the Go server on port 3000.
+
+Node 22 is required. If you use asdf, `.tool-versions` pins the right version automatically.
+
+## Code structure
+
+```
+src/
+โ”œโ”€โ”€ pages/          # One file per route (BugList, BugDetail, NewBug,
+โ”‚                   #   UserProfile, Code, Commit)
+โ”œโ”€โ”€ components/
+โ”‚   โ”œโ”€โ”€ bugs/       # Issue components (BugRow, Timeline, CommentBox,
+โ”‚   โ”‚               #   LabelEditor, TitleEditor, LabelBadge, StatusBadge)
+โ”‚   โ”œโ”€โ”€ code/       # Code browser (FileTree, FileViewer, CommitList,
+โ”‚   โ”‚               #   RefSelector, CodeBreadcrumb)
+โ”‚   โ”œโ”€โ”€ content/    # Markdown renderer
+โ”‚   โ”œโ”€โ”€ layout/     # Header + Shell
+โ”‚   โ””โ”€โ”€ ui/         # shadcn/ui โ€” never edit manually
+โ”‚                   # Update with: npx shadcn update <component>
+โ”œโ”€โ”€ graphql/        # .graphql source files โ€” edit these, then run codegen
+โ”œโ”€โ”€ __generated__/  # Generated typed hooks โ€” do not edit
+โ””โ”€โ”€ lib/            # apollo.ts, auth.tsx, theme.tsx, gitApi.ts, utils.ts
+```
+
+## Data flow
+
+**Bug tracking** uses GraphQL (`/graphql`). Queries and mutations are defined in `src/graphql/*.graphql` and codegen produces typed React hooks into `src/__generated__/graphql.ts`. After changing any `.graphql` file, run:
+
+```bash
+npm run codegen
+```
+
+**Code browser** uses REST endpoints at `/api/git/*` implemented in Go (`api/http/git_browse_handler.go`). The TypeScript client is `src/lib/gitApi.ts`.
+
+## Auth
+
+`AuthContext` (`src/lib/auth.tsx`) fetches `repository.userIdentity` on load. If the query returns null the UI enters read-only mode and all write actions are hidden. The context is designed for a future OAuth provider: swap `AuthProvider` for an `OAuthAuthProvider` without touching any other component.
+
+## Theming
+
+`ThemeProvider` (`src/lib/theme.tsx`) toggles the `dark` class on `<html>`. CSS variables for both modes are defined in `src/index.css`. shadcn/ui components pick them up automatically.

webui2/codegen.ts ๐Ÿ”—

@@ -0,0 +1,28 @@
+import type { CodegenConfig } from '@graphql-codegen/cli'
+
+const config: CodegenConfig = {
+  schema: '../api/graphql/schema/*.graphql',
+  documents: 'src/graphql/**/*.graphql',
+  generates: {
+    'src/__generated__/graphql.ts': {
+      plugins: [
+        'typescript',
+        'typescript-operations',
+        'typescript-react-apollo',
+      ],
+      config: {
+        withHooks: true,
+        withComponent: false,
+        withHOC: false,
+        scalars: {
+          Time: 'string',
+          Hash: 'string',
+          CombinedId: 'string',
+          Color: '{ R: number; G: number; B: number }',
+        },
+      },
+    },
+  },
+}
+
+export default config

webui2/components.json ๐Ÿ”—

@@ -0,0 +1,20 @@
+{
+  "$schema": "https://ui.shadcn.com/schema.json",
+  "style": "new-york",
+  "rsc": false,
+  "tsx": true,
+  "tailwind": {
+    "config": "tailwind.config.ts",
+    "css": "src/index.css",
+    "baseColor": "zinc",
+    "cssVariables": true,
+    "prefix": ""
+  },
+  "aliases": {
+    "components": "@/components",
+    "utils": "@/lib/utils",
+    "ui": "@/components/ui",
+    "lib": "@/lib",
+    "hooks": "@/hooks"
+  }
+}

webui2/index.html ๐Ÿ”—

@@ -0,0 +1,13 @@
+<!doctype html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <title>git-bug</title>
+  </head>
+  <body>
+    <div id="root"></div>
+    <script type="module" src="/src/main.tsx"></script>
+  </body>
+</html>

webui2/package-lock.json ๐Ÿ”—

@@ -0,0 +1,14614 @@
+{
+  "name": "git-bug-webui",
+  "version": "0.0.0",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "git-bug-webui",
+      "version": "0.0.0",
+      "dependencies": {
+        "@apollo/client": "^3.13.0",
+        "@radix-ui/react-avatar": "^1.1.3",
+        "@radix-ui/react-popover": "^1.1.6",
+        "@radix-ui/react-separator": "^1.1.1",
+        "@radix-ui/react-slot": "^1.1.2",
+        "@radix-ui/react-tooltip": "^1.1.8",
+        "class-variance-authority": "^0.7.1",
+        "clsx": "^2.1.1",
+        "date-fns": "^4.1.0",
+        "graphql": "^16.9.0",
+        "highlight.js": "^11.11.1",
+        "lucide-react": "^0.468.0",
+        "react": "^19.1.0",
+        "react-dom": "^19.1.0",
+        "react-markdown": "^9.0.1",
+        "react-router-dom": "^6.28.0",
+        "remark-gfm": "^4.0.0",
+        "tailwind-merge": "^2.5.5",
+        "tailwindcss-animate": "^1.0.7"
+      },
+      "devDependencies": {
+        "@graphql-codegen/cli": "^5.0.6",
+        "@graphql-codegen/typescript": "^4.1.5",
+        "@graphql-codegen/typescript-operations": "^4.5.1",
+        "@graphql-codegen/typescript-react-apollo": "^4.3.2",
+        "@tailwindcss/typography": "^0.5.15",
+        "@types/react": "^19.1.0",
+        "@types/react-dom": "^19.1.0",
+        "@vitejs/plugin-react": "^4.3.4",
+        "autoprefixer": "^10.4.20",
+        "postcss": "^8.4.49",
+        "tailwindcss": "^3.4.17",
+        "typescript": "^5.7.2",
+        "vite": "^6.0.7"
+      }
+    },
+    "node_modules/@alloc/quick-lru": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+      "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@apollo/client": {
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.14.0.tgz",
+      "integrity": "sha512-0YQKKRIxiMlIou+SekQqdCo0ZTHxOcES+K8vKB53cIDpwABNR0P0yRzPgsbgcj3zRJniD93S/ontsnZsCLZrxQ==",
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@wry/caches": "^1.0.0",
+        "@wry/equality": "^0.5.6",
+        "@wry/trie": "^0.5.0",
+        "graphql-tag": "^2.12.6",
+        "hoist-non-react-statics": "^3.3.2",
+        "optimism": "^0.18.0",
+        "prop-types": "^15.7.2",
+        "rehackt": "^0.1.0",
+        "symbol-observable": "^4.0.0",
+        "ts-invariant": "^0.10.3",
+        "tslib": "^2.3.0",
+        "zen-observable-ts": "^1.2.5"
+      },
+      "peerDependencies": {
+        "graphql": "^15.0.0 || ^16.0.0",
+        "graphql-ws": "^5.5.5 || ^6.0.3",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc",
+        "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc",
+        "subscriptions-transport-ws": "^0.9.0 || ^0.11.0"
+      },
+      "peerDependenciesMeta": {
+        "graphql-ws": {
+          "optional": true
+        },
+        "react": {
+          "optional": true
+        },
+        "react-dom": {
+          "optional": true
+        },
+        "subscriptions-transport-ws": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@ardatan/relay-compiler": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/@ardatan/relay-compiler/-/relay-compiler-13.0.0.tgz",
+      "integrity": "sha512-ite4+xng5McO8MflWCi0un0YmnorTujsDnfPfhzYzAgoJ+jkI1pZj6jtmTl8Jptyi1H+Pa0zlatJIsxDD++ETA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/runtime": "^7.26.10",
+        "immutable": "^5.1.5",
+        "invariant": "^2.2.4"
+      },
+      "peerDependencies": {
+        "graphql": "*"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.28.5",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+      "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+      "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.29.0",
+        "@babel/generator": "^7.29.0",
+        "@babel/helper-compilation-targets": "^7.28.6",
+        "@babel/helper-module-transforms": "^7.28.6",
+        "@babel/helpers": "^7.28.6",
+        "@babel/parser": "^7.29.0",
+        "@babel/template": "^7.28.6",
+        "@babel/traverse": "^7.29.0",
+        "@babel/types": "^7.29.0",
+        "@jridgewell/remapping": "^2.3.5",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.29.1",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+      "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/parser": "^7.29.0",
+        "@babel/types": "^7.29.0",
+        "@jridgewell/gen-mapping": "^0.3.12",
+        "@jridgewell/trace-mapping": "^0.3.28",
+        "jsesc": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+      "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/compat-data": "^7.28.6",
+        "@babel/helper-validator-option": "^7.27.1",
+        "browserslist": "^4.24.0",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-globals": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+      "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+      "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/traverse": "^7.28.6",
+        "@babel/types": "^7.28.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+      "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.28.6",
+        "@babel/helper-validator-identifier": "^7.28.5",
+        "@babel/traverse": "^7.28.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-plugin-utils": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+      "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.28.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+      "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+      "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
+      "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/template": "^7.28.6",
+        "@babel/types": "^7.28.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
+      "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.29.0"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-assertions": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz",
+      "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.28.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-react-jsx-self": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+      "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-react-jsx-source": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+      "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+      "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+      "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.28.6",
+        "@babel/parser": "^7.28.6",
+        "@babel/types": "^7.28.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+      "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.29.0",
+        "@babel/generator": "^7.29.0",
+        "@babel/helper-globals": "^7.28.0",
+        "@babel/parser": "^7.29.0",
+        "@babel/template": "^7.28.6",
+        "@babel/types": "^7.29.0",
+        "debug": "^4.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+      "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.28.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@envelop/core": {
+      "version": "5.5.1",
+      "resolved": "https://registry.npmjs.org/@envelop/core/-/core-5.5.1.tgz",
+      "integrity": "sha512-3DQg8sFskDo386TkL5j12jyRAdip/8yzK3x7YGbZBgobZ4aKXrvDU0GppU0SnmrpQnNaiTUsxBs9LKkwQ/eyvw==",
+      "dev": true,
+      "dependencies": {
+        "@envelop/instrumentation": "^1.0.0",
+        "@envelop/types": "^5.2.1",
+        "@whatwg-node/promise-helpers": "^1.2.4",
+        "tslib": "^2.5.0"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@envelop/instrumentation": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@envelop/instrumentation/-/instrumentation-1.0.0.tgz",
+      "integrity": "sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==",
+      "dev": true,
+      "dependencies": {
+        "@whatwg-node/promise-helpers": "^1.2.1",
+        "tslib": "^2.5.0"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@envelop/types": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/@envelop/types/-/types-5.2.1.tgz",
+      "integrity": "sha512-CsFmA3u3c2QoLDTfEpGr4t25fjMU31nyvse7IzWTvb0ZycuPjMjb0fjlheh+PbhBYb9YLugnT2uY6Mwcg1o+Zg==",
+      "dev": true,
+      "dependencies": {
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "tslib": "^2.5.0"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+      "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+      "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+      "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+      "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+      "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+      "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+      "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+      "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+      "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+      "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+      "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+      "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+      "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+      "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+      "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+      "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+      "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+      "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+      "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+      "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+      "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/openharmony-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+      "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openharmony"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+      "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+      "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+      "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+      "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@fastify/busboy": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz",
+      "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==",
+      "dev": true
+    },
+    "node_modules/@floating-ui/core": {
+      "version": "1.7.5",
+      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
+      "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+      "dependencies": {
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "node_modules/@floating-ui/dom": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
+      "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+      "dependencies": {
+        "@floating-ui/core": "^1.7.5",
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "node_modules/@floating-ui/react-dom": {
+      "version": "2.1.8",
+      "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
+      "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
+      "dependencies": {
+        "@floating-ui/dom": "^1.7.6"
+      },
+      "peerDependencies": {
+        "react": ">=16.8.0",
+        "react-dom": ">=16.8.0"
+      }
+    },
+    "node_modules/@floating-ui/utils": {
+      "version": "0.2.11",
+      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
+      "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="
+    },
+    "node_modules/@graphql-codegen/add": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz",
+      "integrity": "sha512-SxXPmramkth8XtBlAHu4H4jYcYXM/o3p01+psU+0NADQowA8jtYkK6MW5rV6T+CxkEaNZItfSmZRPgIuypcqnA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.0.3",
+        "tslib": "~2.6.0"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/add/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/cli": {
+      "version": "5.0.7",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.7.tgz",
+      "integrity": "sha512-h/sxYvSaWtxZxo8GtaA8SvcHTyViaaPd7dweF/hmRDpaQU1o3iU3EZxlcJ+oLTunU0tSMFsnrIXm/mhXxI11Cw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/generator": "^7.18.13",
+        "@babel/template": "^7.18.10",
+        "@babel/types": "^7.18.13",
+        "@graphql-codegen/client-preset": "^4.8.2",
+        "@graphql-codegen/core": "^4.0.2",
+        "@graphql-codegen/plugin-helpers": "^5.1.1",
+        "@graphql-tools/apollo-engine-loader": "^8.0.0",
+        "@graphql-tools/code-file-loader": "^8.0.0",
+        "@graphql-tools/git-loader": "^8.0.0",
+        "@graphql-tools/github-loader": "^8.0.0",
+        "@graphql-tools/graphql-file-loader": "^8.0.0",
+        "@graphql-tools/json-file-loader": "^8.0.0",
+        "@graphql-tools/load": "^8.1.0",
+        "@graphql-tools/prisma-loader": "^8.0.0",
+        "@graphql-tools/url-loader": "^8.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "@whatwg-node/fetch": "^0.10.0",
+        "chalk": "^4.1.0",
+        "cosmiconfig": "^8.1.3",
+        "debounce": "^1.2.0",
+        "detect-indent": "^6.0.0",
+        "graphql-config": "^5.1.1",
+        "inquirer": "^8.0.0",
+        "is-glob": "^4.0.1",
+        "jiti": "^1.17.1",
+        "json-to-pretty-yaml": "^1.2.2",
+        "listr2": "^4.0.5",
+        "log-symbols": "^4.0.0",
+        "micromatch": "^4.0.5",
+        "shell-quote": "^1.7.3",
+        "string-env-interpolation": "^1.0.1",
+        "ts-log": "^2.2.3",
+        "tslib": "^2.4.0",
+        "yaml": "^2.3.1",
+        "yargs": "^17.0.0"
+      },
+      "bin": {
+        "gql-gen": "cjs/bin.js",
+        "graphql-code-generator": "cjs/bin.js",
+        "graphql-codegen": "cjs/bin.js",
+        "graphql-codegen-esm": "esm/bin.js"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "@parcel/watcher": "^2.1.0",
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@parcel/watcher": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@graphql-codegen/client-preset": {
+      "version": "4.8.3",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.8.3.tgz",
+      "integrity": "sha512-QpEsPSO9fnRxA6Z66AmBuGcwHjZ6dYSxYo5ycMlYgSPzAbyG8gn/kWljofjJfWqSY+T/lRn+r8IXTH14ml24vQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.20.2",
+        "@babel/template": "^7.20.7",
+        "@graphql-codegen/add": "^5.0.3",
+        "@graphql-codegen/gql-tag-operations": "4.0.17",
+        "@graphql-codegen/plugin-helpers": "^5.1.1",
+        "@graphql-codegen/typed-document-node": "^5.1.2",
+        "@graphql-codegen/typescript": "^4.1.6",
+        "@graphql-codegen/typescript-operations": "^4.6.1",
+        "@graphql-codegen/visitor-plugin-common": "^5.8.0",
+        "@graphql-tools/documents": "^1.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "@graphql-typed-document-node/core": "3.2.0",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
+        "graphql-sock": "^1.0.0"
+      },
+      "peerDependenciesMeta": {
+        "graphql-sock": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@graphql-codegen/client-preset/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/core": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.2.tgz",
+      "integrity": "sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.0.3",
+        "@graphql-tools/schema": "^10.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "tslib": "~2.6.0"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/core/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/gql-tag-operations": {
+      "version": "4.0.17",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.17.tgz",
+      "integrity": "sha512-2pnvPdIG6W9OuxkrEZ6hvZd142+O3B13lvhrZ48yyEBh2ujtmKokw0eTwDHtlXUqjVS0I3q7+HB2y12G/m69CA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "auto-bind": "~4.0.0",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/gql-tag-operations/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/plugin-helpers": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.1.1.tgz",
+      "integrity": "sha512-28GHODK2HY1NhdyRcPP3sCz0Kqxyfiz7boIZ8qIxFYmpLYnlDgiYok5fhFLVSZihyOpCs4Fa37gVHf/Q4I2FEg==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^10.0.0",
+        "change-case-all": "1.0.15",
+        "common-tags": "1.8.2",
+        "import-from": "4.0.0",
+        "lodash": "~4.17.0",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/plugin-helpers/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/schema-ast": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.1.0.tgz",
+      "integrity": "sha512-kZVn0z+th9SvqxfKYgztA6PM7mhnSZaj4fiuBWvMTqA+QqQ9BBed6Pz41KuD/jr0gJtnlr2A4++/0VlpVbCTmQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.0.3",
+        "@graphql-tools/utils": "^10.0.0",
+        "tslib": "~2.6.0"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/schema-ast/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/typed-document-node": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typed-document-node/-/typed-document-node-5.1.2.tgz",
+      "integrity": "sha512-jaxfViDqFRbNQmfKwUY8hDyjnLTw2Z7DhGutxoOiiAI0gE/LfPe0LYaVFKVmVOOD7M3bWxoWfu4slrkbWbUbEw==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "auto-bind": "~4.0.0",
+        "change-case-all": "1.0.15",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/typed-document-node/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/typescript": {
+      "version": "4.1.6",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.1.6.tgz",
+      "integrity": "sha512-vpw3sfwf9A7S+kIUjyFxuvrywGxd4lmwmyYnnDVjVE4kSQ6Td3DpqaPTy8aNQ6O96vFoi/bxbZS2BW49PwSUUA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/schema-ast": "^4.0.2",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "auto-bind": "~4.0.0",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/typescript-operations": {
+      "version": "4.6.1",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.6.1.tgz",
+      "integrity": "sha512-k92laxhih7s0WZ8j5WMIbgKwhe64C0As6x+PdcvgZFMudDJ7rPJ/hFqJ9DCRxNjXoHmSjnr6VUuQZq4lT1RzCA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/typescript": "^4.1.6",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "auto-bind": "~4.0.0",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
+        "graphql-sock": "^1.0.0"
+      },
+      "peerDependenciesMeta": {
+        "graphql-sock": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@graphql-codegen/typescript-operations/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/typescript-react-apollo": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-react-apollo/-/typescript-react-apollo-4.4.1.tgz",
+      "integrity": "sha512-lrjUfDCNlCWQU07jO6EvZE8I2OLfJl9XKKGCcol27OhW6B9xaUEPaId+TvL6o/NfV+T4z4eQ/Y8BuKWyYjD+mQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^6.1.1",
+        "@graphql-codegen/visitor-plugin-common": "^6.2.4",
+        "auto-bind": "~4.0.0",
+        "change-case-all": "1.0.15",
+        "tslib": "^2.8.1"
+      },
+      "engines": {
+        "node": ">= 16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/typescript-react-apollo/node_modules/@graphql-codegen/plugin-helpers": {
+      "version": "6.1.1",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-6.1.1.tgz",
+      "integrity": "sha512-ipWZHA4ZG8PUdZWx87rvL6LCoIZVhrovVl+448FuxnKIGdzyLmL3+FJc/x96jsQZqKKrUcId9oEgssyh6p15eg==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "change-case-all": "1.0.15",
+        "common-tags": "1.8.2",
+        "import-from": "4.0.0",
+        "lodash": "~4.17.0",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/typescript-react-apollo/node_modules/@graphql-codegen/plugin-helpers/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/typescript-react-apollo/node_modules/@graphql-codegen/visitor-plugin-common": {
+      "version": "6.2.4",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-6.2.4.tgz",
+      "integrity": "sha512-iwiVCc7Mv8/XAa3K35AdFQ9chJSDv/gYEnBeQFF/Sq/W8EyJoHypOGOTTLk7OSrWO4xea65ggv0e7fGt7rPJjQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^6.1.1",
+        "@graphql-tools/optimize": "^2.0.0",
+        "@graphql-tools/relay-operation-optimizer": "^7.1.1",
+        "@graphql-tools/utils": "^11.0.0",
+        "auto-bind": "~4.0.0",
+        "change-case-all": "1.0.15",
+        "dependency-graph": "^1.0.0",
+        "graphql-tag": "^2.11.0",
+        "parse-filepath": "^1.0.2",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/typescript-react-apollo/node_modules/@graphql-codegen/visitor-plugin-common/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/typescript-react-apollo/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/typescript-react-apollo/node_modules/dependency-graph": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz",
+      "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@graphql-codegen/typescript/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-codegen/visitor-plugin-common": {
+      "version": "5.8.0",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.8.0.tgz",
+      "integrity": "sha512-lC1E1Kmuzi3WZUlYlqB4fP6+CvbKH9J+haU1iWmgsBx5/sO2ROeXJG4Dmt8gP03bI2BwjiwV5WxCEMlyeuzLnA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-tools/optimize": "^2.0.0",
+        "@graphql-tools/relay-operation-optimizer": "^7.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "auto-bind": "~4.0.0",
+        "change-case-all": "1.0.15",
+        "dependency-graph": "^0.11.0",
+        "graphql-tag": "^2.11.0",
+        "parse-filepath": "^1.0.2",
+        "tslib": "~2.6.0"
+      },
+      "engines": {
+        "node": ">=16"
+      },
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/@graphql-codegen/visitor-plugin-common/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+      "dev": true
+    },
+    "node_modules/@graphql-hive/signal": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-hive/signal/-/signal-2.0.0.tgz",
+      "integrity": "sha512-Pz8wB3K0iU6ae9S1fWfsmJX24CcGeTo6hE7T44ucmV/ALKRj+bxClmqrYcDT7v3f0d12Rh4FAXBb6gon+WkDpQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=20.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/apollo-engine-loader": {
+      "version": "8.0.28",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.28.tgz",
+      "integrity": "sha512-MzgDrUuoxp6dZeo54zLBL3cEJKJtM3N/2RqK0rbPxPq5X2z6TUA7EGg8vIFTUkt5xelAsUrm8/4ai41ZDdxOng==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "@whatwg-node/fetch": "^0.10.13",
+        "sync-fetch": "0.6.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/batch-execute": {
+      "version": "9.0.6",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-9.0.6.tgz",
+      "integrity": "sha512-S0mLTUJQJuItGmwouYZyXeFaRWOVmVCAMLi33M5PuZbnsoTwKMB/YPPkAQ72ay3GfclnW66XcO4EClbVynw7eQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^10.5.6",
+        "dataloader": "^2.2.2",
+        "tslib": "^2.4.0",
+        "value-or-promise": "^1.0.12"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/code-file-loader": {
+      "version": "8.1.28",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.1.28.tgz",
+      "integrity": "sha512-BL3Ft/PFlXDE5nNuqA36hYci7Cx+8bDrPDc8X3VSpZy9iKFBY+oQ+IwqnEHCkt8OSp2n2V0gqTg4u3fcQP1Kwg==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/graphql-tag-pluck": "8.3.27",
+        "@graphql-tools/utils": "^11.0.0",
+        "globby": "^11.0.3",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/code-file-loader/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/delegate": {
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.1.2.tgz",
+      "integrity": "sha512-2XXJdxjud0ROiKxIiieCx4SxzSjYNdCz1bVDrI6+nTFxV5kB15OnJU6jvom44kv+NJo4Dym5GOJNqlBEjxoFVA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/batch-execute": "^9.0.6",
+        "@graphql-tools/executor": "^1.3.3",
+        "@graphql-tools/schema": "^10.0.8",
+        "@graphql-tools/utils": "^10.5.6",
+        "@repeaterjs/repeater": "^3.0.6",
+        "dataloader": "^2.2.2",
+        "dset": "^3.1.2",
+        "tslib": "^2.5.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/documents": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/documents/-/documents-1.0.1.tgz",
+      "integrity": "sha512-aweoMH15wNJ8g7b2r4C4WRuJxZ0ca8HtNO54rkye/3duxTkW4fGBEutCx03jCIr5+a1l+4vFJNP859QnAVBVCA==",
+      "dev": true,
+      "dependencies": {
+        "lodash.sortby": "^4.7.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/executor": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.5.1.tgz",
+      "integrity": "sha512-n94Qcu875Mji9GQ52n5UbgOTxlgvFJicBPYD+FRks9HKIQpdNPjkkrKZUYNG51XKa+bf03rxNflm4+wXhoHHrA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "@graphql-typed-document-node/core": "^3.2.0",
+        "@repeaterjs/repeater": "^3.0.4",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/executor-common": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-common/-/executor-common-0.0.6.tgz",
+      "integrity": "sha512-JAH/R1zf77CSkpYATIJw+eOJwsbWocdDjY+avY7G+P5HCXxwQjAjWVkJI1QJBQYjPQDVxwf1fmTZlIN3VOadow==",
+      "dev": true,
+      "dependencies": {
+        "@envelop/core": "^5.3.0",
+        "@graphql-tools/utils": "^10.9.1"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/executor-graphql-ws": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-2.0.7.tgz",
+      "integrity": "sha512-J27za7sKF6RjhmvSOwOQFeNhNHyP4f4niqPnerJmq73OtLx9Y2PGOhkXOEB0PjhvPJceuttkD2O1yMgEkTGs3Q==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/executor-common": "^0.0.6",
+        "@graphql-tools/utils": "^10.9.1",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "graphql-ws": "^6.0.6",
+        "isomorphic-ws": "^5.0.0",
+        "tslib": "^2.8.1",
+        "ws": "^8.18.3"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/executor-http": {
+      "version": "1.1.9",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-1.1.9.tgz",
+      "integrity": "sha512-dJRj78QEGNNnlhkhqPUG9z+1uAr7znZ4dzabEVgY5uSXTmUIFcTKpOGYv2/QAuvyqGN40XxbcdVRJta6XHX2BQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^10.5.6",
+        "@repeaterjs/repeater": "^3.0.4",
+        "@whatwg-node/fetch": "^0.10.0",
+        "extract-files": "^11.0.0",
+        "meros": "^1.2.1",
+        "tslib": "^2.4.0",
+        "value-or-promise": "^1.0.12"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/executor-legacy-ws": {
+      "version": "1.1.25",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.1.25.tgz",
+      "integrity": "sha512-6uf4AEXO0QMxJ7AWKVPqEZXgYBJaiz5vf29X0boG8QtcqWy8mqkXKWLND2Swdx0SbEx0efoGFcjuKufUcB0ASQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "@types/ws": "^8.0.0",
+        "isomorphic-ws": "^5.0.0",
+        "tslib": "^2.4.0",
+        "ws": "^8.19.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/executor-legacy-ws/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/executor/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/git-loader": {
+      "version": "8.0.32",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.32.tgz",
+      "integrity": "sha512-H5HTp2vevv0rRMEnCJBVmVF8md3LpJI1C1+d6OtzvmuONJ8mOX2mkf9rtoqwiztynVegaDUekvMFsc9k5iE2WA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/graphql-tag-pluck": "8.3.27",
+        "@graphql-tools/utils": "^11.0.0",
+        "is-glob": "4.0.3",
+        "micromatch": "^4.0.8",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/git-loader/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/github-loader": {
+      "version": "8.0.22",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-8.0.22.tgz",
+      "integrity": "sha512-uQ4JNcNPsyMkTIgzeSbsoT9hogLjYrZooLUYd173l5eUGUi49EAcsGdiBCKaKfEjanv410FE8hjaHr7fjSRkJw==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/executor-http": "^1.1.9",
+        "@graphql-tools/graphql-tag-pluck": "^8.3.21",
+        "@graphql-tools/utils": "^10.9.1",
+        "@whatwg-node/fetch": "^0.10.0",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "sync-fetch": "0.6.0-2",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/github-loader/node_modules/node-fetch": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+      "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+      "dev": true,
+      "dependencies": {
+        "data-uri-to-buffer": "^4.0.0",
+        "fetch-blob": "^3.1.4",
+        "formdata-polyfill": "^4.0.10"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/node-fetch"
+      }
+    },
+    "node_modules/@graphql-tools/github-loader/node_modules/sync-fetch": {
+      "version": "0.6.0-2",
+      "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0-2.tgz",
+      "integrity": "sha512-c7AfkZ9udatCuAy9RSfiGPpeOKKUAUK5e1cXadLOGUjasdxqYqAK0jTNkM/FSEyJ3a5Ra27j/tw/PS0qLmaF/A==",
+      "dev": true,
+      "dependencies": {
+        "node-fetch": "^3.3.2",
+        "timeout-signal": "^2.0.0",
+        "whatwg-mimetype": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@graphql-tools/graphql-file-loader": {
+      "version": "8.1.12",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.1.12.tgz",
+      "integrity": "sha512-Nma7gBgJoUbqXWTmdHjouo36tjzewA8MptVcHoH7widzkciaUVzBhriHzqICFB/dVxig//g9MX8s1XawZo7UAg==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/import": "^7.1.12",
+        "@graphql-tools/utils": "^11.0.0",
+        "globby": "^11.0.3",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/graphql-file-loader/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/graphql-tag-pluck": {
+      "version": "8.3.27",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.3.27.tgz",
+      "integrity": "sha512-CJ0WVXhGYsfFngpRrAAcjRHyxSDHx4dEz2W15bkwvt9he/AWhuyXm07wuGcoLrl0q0iQp1BiRjU7D8SxWZo3JQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.26.10",
+        "@babel/parser": "^7.26.10",
+        "@babel/plugin-syntax-import-assertions": "^7.26.0",
+        "@babel/traverse": "^7.26.10",
+        "@babel/types": "^7.26.10",
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/graphql-tag-pluck/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/import": {
+      "version": "7.1.12",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-7.1.12.tgz",
+      "integrity": "sha512-QSsdPsdJ7yCgQ5XODyKYpC7NlB9R1Koi0R3418PT7GiRm+9O8gYXSs/23dumcOnpiLrnf4qR2aytBn1+JOAhnA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "resolve-from": "5.0.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/import/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/json-file-loader": {
+      "version": "8.0.26",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-8.0.26.tgz",
+      "integrity": "sha512-kwy9IFi5QtXXTLBgWkvA1RqsZeJDn0CxsTbhNlziCzmga9fNo7qtZ18k9FYIq3EIoQQlok+b7W7yeyJATA2xhw==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "globby": "^11.0.3",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/json-file-loader/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/load": {
+      "version": "8.1.8",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-8.1.8.tgz",
+      "integrity": "sha512-gxO662b64qZSToK3N6XUxWG5E6HOUjlg5jEnmGvD4bMtGJ0HwEe/BaVZbBQemCfLkxYjwRIBiVfOY9o0JyjZJg==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/schema": "^10.0.31",
+        "@graphql-tools/utils": "^11.0.0",
+        "p-limit": "3.1.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/load/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/merge": {
+      "version": "9.1.7",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.1.7.tgz",
+      "integrity": "sha512-Y5E1vTbTabvcXbkakdFUt4zUIzB1fyaEnVmIWN0l0GMed2gdD01TpZWLUm4RNAxpturvolrb24oGLQrBbPLSoQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/merge/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/optimize": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/optimize/-/optimize-2.0.0.tgz",
+      "integrity": "sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/prisma-loader": {
+      "version": "8.0.17",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-8.0.17.tgz",
+      "integrity": "sha512-fnuTLeQhqRbA156pAyzJYN0KxCjKYRU5bz1q/SKOwElSnAU4k7/G1kyVsWLh7fneY78LoMNH5n+KlFV8iQlnyg==",
+      "deprecated": "This package was intended to be used with an older versions of Prisma.\\nThe newer versions of Prisma has a different approach to GraphQL integration.\\nTherefore, this package is no longer needed and has been deprecated and removed.\\nLearn more: https://www.prisma.io/graphql",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/url-loader": "^8.0.15",
+        "@graphql-tools/utils": "^10.5.6",
+        "@types/js-yaml": "^4.0.0",
+        "@whatwg-node/fetch": "^0.10.0",
+        "chalk": "^4.1.0",
+        "debug": "^4.3.1",
+        "dotenv": "^16.0.0",
+        "graphql-request": "^6.0.0",
+        "http-proxy-agent": "^7.0.0",
+        "https-proxy-agent": "^7.0.0",
+        "jose": "^5.0.0",
+        "js-yaml": "^4.0.0",
+        "lodash": "^4.17.20",
+        "scuid": "^1.1.0",
+        "tslib": "^2.4.0",
+        "yaml-ast-parser": "^0.0.43"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/relay-operation-optimizer": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.1.1.tgz",
+      "integrity": "sha512-va+ZieMlz6Fj18xUbwyQkZ34PsnzIdPT6Ccy1BNOQw1iclQwk52HejLMZeE/4fH+4cu80Q2HXi5+FjCKpmnJCg==",
+      "dev": true,
+      "dependencies": {
+        "@ardatan/relay-compiler": "^13.0.0",
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/relay-operation-optimizer/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/schema": {
+      "version": "10.0.31",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.31.tgz",
+      "integrity": "sha512-ZewRgWhXef6weZ0WiP7/MV47HXiuFbFpiDUVLQl6mgXsWSsGELKFxQsyUCBos60Qqy1JEFAIu3Ns6GGYjGkqkQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/merge": "^9.1.7",
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/schema/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/url-loader": {
+      "version": "8.0.33",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-8.0.33.tgz",
+      "integrity": "sha512-Fu626qcNHcqAj8uYd7QRarcJn5XZ863kmxsg1sm0fyjyfBJnsvC7ddFt6Hayz5kxVKfsnjxiDfPMXanvsQVBKw==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/executor-graphql-ws": "^2.0.1",
+        "@graphql-tools/executor-http": "^1.1.9",
+        "@graphql-tools/executor-legacy-ws": "^1.1.19",
+        "@graphql-tools/utils": "^10.9.1",
+        "@graphql-tools/wrap": "^10.0.16",
+        "@types/ws": "^8.0.0",
+        "@whatwg-node/fetch": "^0.10.0",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "isomorphic-ws": "^5.0.0",
+        "sync-fetch": "0.6.0-2",
+        "tslib": "^2.4.0",
+        "ws": "^8.17.1"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/url-loader/node_modules/node-fetch": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+      "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+      "dev": true,
+      "dependencies": {
+        "data-uri-to-buffer": "^4.0.0",
+        "fetch-blob": "^3.1.4",
+        "formdata-polyfill": "^4.0.10"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/node-fetch"
+      }
+    },
+    "node_modules/@graphql-tools/url-loader/node_modules/sync-fetch": {
+      "version": "0.6.0-2",
+      "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0-2.tgz",
+      "integrity": "sha512-c7AfkZ9udatCuAy9RSfiGPpeOKKUAUK5e1cXadLOGUjasdxqYqAK0jTNkM/FSEyJ3a5Ra27j/tw/PS0qLmaF/A==",
+      "dev": true,
+      "dependencies": {
+        "node-fetch": "^3.3.2",
+        "timeout-signal": "^2.0.0",
+        "whatwg-mimetype": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/@graphql-tools/utils": {
+      "version": "10.11.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.11.0.tgz",
+      "integrity": "sha512-iBFR9GXIs0gCD+yc3hoNswViL1O5josI33dUqiNStFI/MHLCEPduasceAcazRH77YONKNiviHBV8f7OgcT4o2Q==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-tools/wrap": {
+      "version": "10.0.16",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.0.16.tgz",
+      "integrity": "sha512-O/sOoPCnG2tWfhfIeWLQMPS7ipzjMiVOxwhjOUD9DaQd39XFBD4Al/MmKNc2343ua7NyqMwdfgXQjqGH1LFlPA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/delegate": "^10.1.2",
+        "@graphql-tools/schema": "^10.0.8",
+        "@graphql-tools/utils": "^10.5.6",
+        "tslib": "^2.4.0",
+        "value-or-promise": "^1.0.12"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@graphql-typed-document-node/core": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz",
+      "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==",
+      "peerDependencies": {
+        "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/@inquirer/external-editor": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz",
+      "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==",
+      "dev": true,
+      "dependencies": {
+        "chardet": "^2.1.1",
+        "iconv-lite": "^0.7.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "@types/node": ">=18"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+      "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "node_modules/@jridgewell/remapping": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+      "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+      "dev": true,
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.31",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+      "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@radix-ui/primitive": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+      "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="
+    },
+    "node_modules/@radix-ui/react-arrow": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+      "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.1.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-arrow/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-avatar": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz",
+      "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==",
+      "dependencies": {
+        "@radix-ui/react-context": "1.1.3",
+        "@radix-ui/react-primitive": "2.1.4",
+        "@radix-ui/react-use-callback-ref": "1.1.1",
+        "@radix-ui/react-use-is-hydrated": "0.1.0",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-compose-refs": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+      "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-context": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
+      "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dismissable-layer": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
+      "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.3",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-callback-ref": "1.1.1",
+        "@radix-ui/react-use-escape-keydown": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-dismissable-layer/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-focus-guards": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
+      "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+      "license": "MIT",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-focus-scope": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+      "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+      "license": "MIT",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-callback-ref": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-focus-scope/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "license": "MIT",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-id": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+      "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+      "dependencies": {
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popover": {
+      "version": "1.1.15",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
+      "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
+      "license": "MIT",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.3",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-context": "1.1.2",
+        "@radix-ui/react-dismissable-layer": "1.1.11",
+        "@radix-ui/react-focus-guards": "1.1.3",
+        "@radix-ui/react-focus-scope": "1.1.7",
+        "@radix-ui/react-id": "1.1.1",
+        "@radix-ui/react-popper": "1.2.8",
+        "@radix-ui/react-portal": "1.1.9",
+        "@radix-ui/react-presence": "1.1.5",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-slot": "1.2.3",
+        "@radix-ui/react-use-controllable-state": "1.2.2",
+        "aria-hidden": "^1.2.4",
+        "react-remove-scroll": "^2.6.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-context": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+      "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+      "license": "MIT",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "license": "MIT",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popper": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
+      "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+      "dependencies": {
+        "@floating-ui/react-dom": "^2.0.0",
+        "@radix-ui/react-arrow": "1.1.7",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-context": "1.1.2",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-callback-ref": "1.1.1",
+        "@radix-ui/react-use-layout-effect": "1.1.1",
+        "@radix-ui/react-use-rect": "1.1.1",
+        "@radix-ui/react-use-size": "1.1.1",
+        "@radix-ui/rect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-context": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+      "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-popper/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-portal": {
+      "version": "1.1.9",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+      "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-portal/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-presence": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+      "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+      "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.4"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-separator": {
+      "version": "1.1.8",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
+      "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.1.4"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-slot": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
+      "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tooltip": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
+      "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+      "dependencies": {
+        "@radix-ui/primitive": "1.1.3",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-context": "1.1.2",
+        "@radix-ui/react-dismissable-layer": "1.1.11",
+        "@radix-ui/react-id": "1.1.1",
+        "@radix-ui/react-popper": "1.2.8",
+        "@radix-ui/react-portal": "1.1.9",
+        "@radix-ui/react-presence": "1.1.5",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-slot": "1.2.3",
+        "@radix-ui/react-use-controllable-state": "1.2.2",
+        "@radix-ui/react-visually-hidden": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+      "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-callback-ref": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+      "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-controllable-state": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+      "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+      "dependencies": {
+        "@radix-ui/react-use-effect-event": "0.0.2",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-effect-event": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+      "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+      "dependencies": {
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-escape-keydown": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+      "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+      "dependencies": {
+        "@radix-ui/react-use-callback-ref": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-is-hydrated": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz",
+      "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==",
+      "dependencies": {
+        "use-sync-external-store": "^1.5.0"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-layout-effect": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+      "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-rect": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+      "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+      "dependencies": {
+        "@radix-ui/rect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-use-size": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+      "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+      "dependencies": {
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-visually-hidden": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+      "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+      "dependencies": {
+        "@radix-ui/react-primitive": "2.1.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-primitive": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+      "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+      "dependencies": {
+        "@radix-ui/react-slot": "1.2.3"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "@types/react-dom": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
+        "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "@types/react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/react-visually-hidden/node_modules/@radix-ui/react-slot": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+      "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+      "dependencies": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@radix-ui/rect": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+      "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="
+    },
+    "node_modules/@remix-run/router": {
+      "version": "1.23.2",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
+      "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/@repeaterjs/repeater": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz",
+      "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==",
+      "dev": true
+    },
+    "node_modules/@rolldown/pluginutils": {
+      "version": "1.0.0-beta.27",
+      "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
+      "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
+      "dev": true
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+      "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+      "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+      "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+      "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+      "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+      "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+      "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+      "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+      "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+      "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+      "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+      "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+      "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+      "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+      "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+      "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+      "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+      "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+      "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-openbsd-x64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+      "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openbsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-openharmony-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+      "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "openharmony"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+      "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+      "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+      "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+      "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@tailwindcss/typography": {
+      "version": "0.5.19",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz",
+      "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==",
+      "dev": true,
+      "dependencies": {
+        "postcss-selector-parser": "6.0.10"
+      },
+      "peerDependencies": {
+        "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
+      }
+    },
+    "node_modules/@types/babel__core": {
+      "version": "7.20.5",
+      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+      "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/parser": "^7.20.7",
+        "@babel/types": "^7.20.7",
+        "@types/babel__generator": "*",
+        "@types/babel__template": "*",
+        "@types/babel__traverse": "*"
+      }
+    },
+    "node_modules/@types/babel__generator": {
+      "version": "7.27.0",
+      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+      "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__template": {
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+      "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+      "dev": true,
+      "dependencies": {
+        "@babel/parser": "^7.1.0",
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "node_modules/@types/babel__traverse": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+      "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+      "dev": true,
+      "dependencies": {
+        "@babel/types": "^7.28.2"
+      }
+    },
+    "node_modules/@types/debug": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
+      "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+      "dependencies": {
+        "@types/ms": "*"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="
+    },
+    "node_modules/@types/estree-jsx": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+      "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
+      "dependencies": {
+        "@types/estree": "*"
+      }
+    },
+    "node_modules/@types/hast": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+      "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+      "dependencies": {
+        "@types/unist": "*"
+      }
+    },
+    "node_modules/@types/js-yaml": {
+      "version": "4.0.9",
+      "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
+      "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
+      "dev": true
+    },
+    "node_modules/@types/mdast": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+      "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+      "dependencies": {
+        "@types/unist": "*"
+      }
+    },
+    "node_modules/@types/ms": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+      "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="
+    },
+    "node_modules/@types/node": {
+      "version": "25.4.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz",
+      "integrity": "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==",
+      "dev": true,
+      "dependencies": {
+        "undici-types": "~7.18.0"
+      }
+    },
+    "node_modules/@types/react": {
+      "version": "19.2.14",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+      "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+      "dependencies": {
+        "csstype": "^3.2.2"
+      }
+    },
+    "node_modules/@types/react-dom": {
+      "version": "19.2.3",
+      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+      "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+      "devOptional": true,
+      "peerDependencies": {
+        "@types/react": "^19.2.0"
+      }
+    },
+    "node_modules/@types/unist": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+      "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="
+    },
+    "node_modules/@types/ws": {
+      "version": "8.18.1",
+      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+      "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@ungap/structured-clone": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+      "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="
+    },
+    "node_modules/@vitejs/plugin-react": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
+      "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/core": "^7.28.0",
+        "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+        "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+        "@rolldown/pluginutils": "1.0.0-beta.27",
+        "@types/babel__core": "^7.20.5",
+        "react-refresh": "^0.17.0"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
+      }
+    },
+    "node_modules/@whatwg-node/disposablestack": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz",
+      "integrity": "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==",
+      "dev": true,
+      "dependencies": {
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "tslib": "^2.6.3"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@whatwg-node/fetch": {
+      "version": "0.10.13",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.10.13.tgz",
+      "integrity": "sha512-b4PhJ+zYj4357zwk4TTuF2nEe0vVtOrwdsrNo5hL+u1ojXNhh1FgJ6pg1jzDlwlT4oBdzfSwaBwMCtFCsIWg8Q==",
+      "dev": true,
+      "dependencies": {
+        "@whatwg-node/node-fetch": "^0.8.3",
+        "urlpattern-polyfill": "^10.0.0"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@whatwg-node/node-fetch": {
+      "version": "0.8.5",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.8.5.tgz",
+      "integrity": "sha512-4xzCl/zphPqlp9tASLVeUhB5+WJHbuWGYpfoC2q1qh5dw0AqZBW7L27V5roxYWijPxj4sspRAAoOH3d2ztaHUQ==",
+      "dev": true,
+      "dependencies": {
+        "@fastify/busboy": "^3.1.1",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "@whatwg-node/promise-helpers": "^1.3.2",
+        "tslib": "^2.6.3"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/@whatwg-node/promise-helpers": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/promise-helpers/-/promise-helpers-1.3.2.tgz",
+      "integrity": "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.6.3"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      }
+    },
+    "node_modules/@wry/caches": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz",
+      "integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==",
+      "dependencies": {
+        "tslib": "^2.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@wry/context": {
+      "version": "0.7.4",
+      "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz",
+      "integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==",
+      "dependencies": {
+        "tslib": "^2.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@wry/equality": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz",
+      "integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==",
+      "dependencies": {
+        "tslib": "^2.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@wry/trie": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz",
+      "integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==",
+      "dependencies": {
+        "tslib": "^2.3.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/agent-base": {
+      "version": "7.1.4",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+      "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+      "dev": true,
+      "engines": {
+        "node": ">= 14"
+      }
+    },
+    "node_modules/aggregate-error": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+      "dev": true,
+      "dependencies": {
+        "clean-stack": "^2.0.0",
+        "indent-string": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-escapes": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+      "dev": true,
+      "dependencies": {
+        "type-fest": "^0.21.3"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/any-promise": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+      "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/arg": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+      "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+    },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "node_modules/aria-hidden": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
+      "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+      "license": "MIT",
+      "dependencies": {
+        "tslib": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/astral-regex": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/auto-bind": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz",
+      "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/autoprefixer": {
+      "version": "10.4.27",
+      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz",
+      "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "browserslist": "^4.28.1",
+        "caniuse-lite": "^1.0.30001774",
+        "fraction.js": "^5.3.4",
+        "picocolors": "^1.1.1",
+        "postcss-value-parser": "^4.2.0"
+      },
+      "bin": {
+        "autoprefixer": "bin/autoprefixer"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/bail": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+      "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+      "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+      "dev": true,
+      "engines": {
+        "node": "18 || 20 || >=22"
+      }
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/baseline-browser-mapping": {
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
+      "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
+      "dev": true,
+      "bin": {
+        "baseline-browser-mapping": "dist/cli.cjs"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+      "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/bl": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+      "dev": true,
+      "dependencies": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
+      "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^4.0.2"
+      },
+      "engines": {
+        "node": "18 || 20 || >=22"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "dependencies": {
+        "fill-range": "^7.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.28.1",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+      "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "baseline-browser-mapping": "^2.9.0",
+        "caniuse-lite": "^1.0.30001759",
+        "electron-to-chromium": "^1.5.263",
+        "node-releases": "^2.0.27",
+        "update-browserslist-db": "^1.2.0"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/camel-case": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+      "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
+      "dev": true,
+      "dependencies": {
+        "pascal-case": "^3.1.2",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/camelcase-css": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+      "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001777",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz",
+      "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ]
+    },
+    "node_modules/capital-case": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz",
+      "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==",
+      "dev": true,
+      "dependencies": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3",
+        "upper-case-first": "^2.0.2"
+      }
+    },
+    "node_modules/ccount": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+      "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/change-case": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz",
+      "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==",
+      "dev": true,
+      "dependencies": {
+        "camel-case": "^4.1.2",
+        "capital-case": "^1.0.4",
+        "constant-case": "^3.0.4",
+        "dot-case": "^3.0.4",
+        "header-case": "^2.0.4",
+        "no-case": "^3.0.4",
+        "param-case": "^3.0.4",
+        "pascal-case": "^3.1.2",
+        "path-case": "^3.0.4",
+        "sentence-case": "^3.0.4",
+        "snake-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/change-case-all": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.15.tgz",
+      "integrity": "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==",
+      "dev": true,
+      "dependencies": {
+        "change-case": "^4.1.2",
+        "is-lower-case": "^2.0.2",
+        "is-upper-case": "^2.0.2",
+        "lower-case": "^2.0.2",
+        "lower-case-first": "^2.0.2",
+        "sponge-case": "^1.0.1",
+        "swap-case": "^2.0.2",
+        "title-case": "^3.0.3",
+        "upper-case": "^2.0.2",
+        "upper-case-first": "^2.0.2"
+      }
+    },
+    "node_modules/character-entities": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
+      "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/character-entities-html4": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+      "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/character-entities-legacy": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+      "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/character-reference-invalid": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+      "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/chardet": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz",
+      "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==",
+      "dev": true
+    },
+    "node_modules/chokidar": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+      "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/class-variance-authority": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+      "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+      "dependencies": {
+        "clsx": "^2.1.1"
+      },
+      "funding": {
+        "url": "https://polar.sh/cva"
+      }
+    },
+    "node_modules/clean-stack": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+      "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/cli-cursor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+      "dev": true,
+      "dependencies": {
+        "restore-cursor": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/cli-spinners": {
+      "version": "2.9.2",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+      "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cli-truncate": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+      "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+      "dev": true,
+      "dependencies": {
+        "slice-ansi": "^3.0.0",
+        "string-width": "^4.2.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cli-width": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+      "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/cliui": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/cliui/node_modules/wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/clone": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+      "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/clsx": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+      "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/colorette": {
+      "version": "2.0.20",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+      "dev": true
+    },
+    "node_modules/comma-separated-tokens": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+      "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/commander": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+      "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/common-tags": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+      "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/constant-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
+      "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==",
+      "dev": true,
+      "dependencies": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3",
+        "upper-case": "^2.0.2"
+      }
+    },
+    "node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "dev": true
+    },
+    "node_modules/cosmiconfig": {
+      "version": "8.3.6",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+      "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+      "dev": true,
+      "dependencies": {
+        "import-fresh": "^3.3.0",
+        "js-yaml": "^4.1.0",
+        "parse-json": "^5.2.0",
+        "path-type": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/d-fischer"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.9.5"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/cross-fetch": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
+      "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==",
+      "dev": true,
+      "dependencies": {
+        "node-fetch": "^2.7.0"
+      }
+    },
+    "node_modules/cross-inspect": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.1.tgz",
+      "integrity": "sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      }
+    },
+    "node_modules/cssesc": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+      "bin": {
+        "cssesc": "bin/cssesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+      "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="
+    },
+    "node_modules/data-uri-to-buffer": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+      "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+      "dev": true,
+      "engines": {
+        "node": ">= 12"
+      }
+    },
+    "node_modules/dataloader": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.3.tgz",
+      "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==",
+      "dev": true
+    },
+    "node_modules/date-fns": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+      "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/kossnocorp"
+      }
+    },
+    "node_modules/debounce": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
+      "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
+      "dev": true
+    },
+    "node_modules/debug": {
+      "version": "4.4.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/decode-named-character-reference": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
+      "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==",
+      "dependencies": {
+        "character-entities": "^2.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/defaults": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+      "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+      "dev": true,
+      "dependencies": {
+        "clone": "^1.0.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/dependency-graph": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz",
+      "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.6.0"
+      }
+    },
+    "node_modules/dequal": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+      "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/detect-indent": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+      "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/detect-node-es": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+      "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
+      "license": "MIT"
+    },
+    "node_modules/devlop": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+      "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+      "dependencies": {
+        "dequal": "^2.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/didyoumean": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+      "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+    },
+    "node_modules/dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "dependencies": {
+        "path-type": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/dlv": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+      "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+    },
+    "node_modules/dot-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
+      "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
+      "dev": true,
+      "dependencies": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/dotenv": {
+      "version": "16.6.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+      "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://dotenvx.com"
+      }
+    },
+    "node_modules/dset": {
+      "version": "3.1.4",
+      "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
+      "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.5.307",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz",
+      "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==",
+      "dev": true
+    },
+    "node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
+    },
+    "node_modules/error-ex": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+      "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+      "dev": true,
+      "dependencies": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+      "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+      "dev": true,
+      "hasInstallScript": true,
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.25.12",
+        "@esbuild/android-arm": "0.25.12",
+        "@esbuild/android-arm64": "0.25.12",
+        "@esbuild/android-x64": "0.25.12",
+        "@esbuild/darwin-arm64": "0.25.12",
+        "@esbuild/darwin-x64": "0.25.12",
+        "@esbuild/freebsd-arm64": "0.25.12",
+        "@esbuild/freebsd-x64": "0.25.12",
+        "@esbuild/linux-arm": "0.25.12",
+        "@esbuild/linux-arm64": "0.25.12",
+        "@esbuild/linux-ia32": "0.25.12",
+        "@esbuild/linux-loong64": "0.25.12",
+        "@esbuild/linux-mips64el": "0.25.12",
+        "@esbuild/linux-ppc64": "0.25.12",
+        "@esbuild/linux-riscv64": "0.25.12",
+        "@esbuild/linux-s390x": "0.25.12",
+        "@esbuild/linux-x64": "0.25.12",
+        "@esbuild/netbsd-arm64": "0.25.12",
+        "@esbuild/netbsd-x64": "0.25.12",
+        "@esbuild/openbsd-arm64": "0.25.12",
+        "@esbuild/openbsd-x64": "0.25.12",
+        "@esbuild/openharmony-arm64": "0.25.12",
+        "@esbuild/sunos-x64": "0.25.12",
+        "@esbuild/win32-arm64": "0.25.12",
+        "@esbuild/win32-ia32": "0.25.12",
+        "@esbuild/win32-x64": "0.25.12"
+      }
+    },
+    "node_modules/escalade": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/estree-util-is-identifier-name": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
+      "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+    },
+    "node_modules/extract-files": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz",
+      "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==",
+      "dev": true,
+      "engines": {
+        "node": "^12.20 || >= 14.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jaydenseric"
+      }
+    },
+    "node_modules/fast-glob": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+      "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+      "dependencies": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.8"
+      },
+      "engines": {
+        "node": ">=8.6.0"
+      }
+    },
+    "node_modules/fastq": {
+      "version": "1.20.1",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+      "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "node_modules/fetch-blob": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+      "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/jimmywarting"
+        },
+        {
+          "type": "paypal",
+          "url": "https://paypal.me/jimmywarting"
+        }
+      ],
+      "dependencies": {
+        "node-domexception": "^1.0.0",
+        "web-streams-polyfill": "^3.0.3"
+      },
+      "engines": {
+        "node": "^12.20 || >= 14.13"
+      }
+    },
+    "node_modules/figures": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+      "dev": true,
+      "dependencies": {
+        "escape-string-regexp": "^1.0.5"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/formdata-polyfill": {
+      "version": "4.0.10",
+      "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+      "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+      "dev": true,
+      "dependencies": {
+        "fetch-blob": "^3.1.2"
+      },
+      "engines": {
+        "node": ">=12.20.0"
+      }
+    },
+    "node_modules/fraction.js": {
+      "version": "5.3.4",
+      "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
+      "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/rawify"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true,
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
+    "node_modules/get-nonce": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+      "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/globby": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+      "dev": true,
+      "dependencies": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.2.9",
+        "ignore": "^5.2.0",
+        "merge2": "^1.4.1",
+        "slash": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/graphql": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz",
+      "integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==",
+      "engines": {
+        "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0"
+      }
+    },
+    "node_modules/graphql-config": {
+      "version": "5.1.6",
+      "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-5.1.6.tgz",
+      "integrity": "sha512-fCkYnm4Kdq3un0YIM4BCZHVR5xl0UeLP6syxxO7KAstdY7QVyVvTHP0kRPDYEP1v08uwtJVgis5sj3IOTLOniQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/graphql-file-loader": "^8.0.0",
+        "@graphql-tools/json-file-loader": "^8.0.0",
+        "@graphql-tools/load": "^8.1.0",
+        "@graphql-tools/merge": "^9.0.0",
+        "@graphql-tools/url-loader": "^9.0.0",
+        "@graphql-tools/utils": "^11.0.0",
+        "cosmiconfig": "^8.1.0",
+        "jiti": "^2.0.0",
+        "minimatch": "^10.0.0",
+        "string-env-interpolation": "^1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">= 16.0.0"
+      },
+      "peerDependencies": {
+        "cosmiconfig-toml-loader": "^1.0.0",
+        "graphql": "^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      },
+      "peerDependenciesMeta": {
+        "cosmiconfig-toml-loader": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/batch-execute": {
+      "version": "10.0.5",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-10.0.5.tgz",
+      "integrity": "sha512-dL13tXkfGvAzLq2XfzTKAy9logIcltKYRuPketxdh3Ok3U6PN1HKMCHfrE9cmtAsxD96/8Hlghz5AtM+LRv/ig==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/utils": "^11.0.0",
+        "@whatwg-node/promise-helpers": "^1.3.2",
+        "dataloader": "^2.2.3",
+        "tslib": "^2.8.1"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/delegate": {
+      "version": "12.0.9",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-12.0.9.tgz",
+      "integrity": "sha512-ugJCiJb4w3bmdUbAz+nKyVVuwzzoy6BZHQ4BJXpAx1i5KIEhSevIkMYq3CZo7drCZf6FMIpcKBxv99uIhzCvhA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/batch-execute": "^10.0.5",
+        "@graphql-tools/executor": "^1.4.13",
+        "@graphql-tools/schema": "^10.0.29",
+        "@graphql-tools/utils": "^11.0.0",
+        "@repeaterjs/repeater": "^3.0.6",
+        "@whatwg-node/promise-helpers": "^1.3.2",
+        "dataloader": "^2.2.3",
+        "tslib": "^2.8.1"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/executor-common": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-common/-/executor-common-1.0.6.tgz",
+      "integrity": "sha512-23/K5C+LSlHDI0mj2SwCJ33RcELCcyDUgABm1Z8St7u/4Z5+95i925H/NAjUyggRjiaY8vYtNiMOPE49aPX1sg==",
+      "dev": true,
+      "dependencies": {
+        "@envelop/core": "^5.4.0",
+        "@graphql-tools/utils": "^11.0.0"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/executor-graphql-ws": {
+      "version": "3.1.4",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-3.1.4.tgz",
+      "integrity": "sha512-wCQfWYLwg1JZmQ7rGaFy74AQyVFxpeqz19WWIGRgANiYlm+T0K3Hs6POgi0+nL3HvwxJIxhUlaRLFvkqm1zxSA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/executor-common": "^1.0.6",
+        "@graphql-tools/utils": "^11.0.0",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "graphql-ws": "^6.0.6",
+        "isows": "^1.0.7",
+        "tslib": "^2.8.1",
+        "ws": "^8.18.3"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/executor-http": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-3.1.0.tgz",
+      "integrity": "sha512-DTaNU1rT2sxffwQlt+Aw68cHQWfGkjsaRk1D8nvG+DcCR8RNQo0d9qYt7pXIcfXYcQLb/OkABcGSuCfkopvHJg==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-hive/signal": "^2.0.0",
+        "@graphql-tools/executor-common": "^1.0.6",
+        "@graphql-tools/utils": "^11.0.0",
+        "@repeaterjs/repeater": "^3.0.4",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "@whatwg-node/fetch": "^0.10.13",
+        "@whatwg-node/promise-helpers": "^1.3.2",
+        "meros": "^1.3.2",
+        "tslib": "^2.8.1"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/url-loader": {
+      "version": "9.0.6",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-9.0.6.tgz",
+      "integrity": "sha512-QdJI3f7ANDMYfYazRgJzzybznjOrQAOuDXweC9xmKgPZoTqNxEAsatiy69zcpTf6092taJLyrqRH6R7xUTzf4A==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/executor-graphql-ws": "^3.1.2",
+        "@graphql-tools/executor-http": "^3.0.6",
+        "@graphql-tools/executor-legacy-ws": "^1.1.25",
+        "@graphql-tools/utils": "^11.0.0",
+        "@graphql-tools/wrap": "^11.1.1",
+        "@types/ws": "^8.0.0",
+        "@whatwg-node/fetch": "^0.10.13",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "isomorphic-ws": "^5.0.0",
+        "sync-fetch": "0.6.0",
+        "tslib": "^2.4.0",
+        "ws": "^8.19.0"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/utils": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+      "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/@graphql-tools/wrap": {
+      "version": "11.1.9",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-11.1.9.tgz",
+      "integrity": "sha512-dSjBNCTPS8W7lWHDgIEgY0MEDwZi1GkqTfl7bJMDs/dJfKojj4Do74LN5QJbP/bIIwJakEwVUMPA8RUYVBP9eQ==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-tools/delegate": "^12.0.9",
+        "@graphql-tools/schema": "^10.0.29",
+        "@graphql-tools/utils": "^11.0.0",
+        "@whatwg-node/promise-helpers": "^1.3.2",
+        "tslib": "^2.8.1"
+      },
+      "engines": {
+        "node": ">=20.0.0"
+      },
+      "peerDependencies": {
+        "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0"
+      }
+    },
+    "node_modules/graphql-config/node_modules/jiti": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
+      "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+      "dev": true,
+      "bin": {
+        "jiti": "lib/jiti-cli.mjs"
+      }
+    },
+    "node_modules/graphql-request": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz",
+      "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==",
+      "dev": true,
+      "dependencies": {
+        "@graphql-typed-document-node/core": "^3.2.0",
+        "cross-fetch": "^3.1.5"
+      },
+      "peerDependencies": {
+        "graphql": "14 - 16"
+      }
+    },
+    "node_modules/graphql-tag": {
+      "version": "2.12.6",
+      "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz",
+      "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==",
+      "dependencies": {
+        "tslib": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0"
+      }
+    },
+    "node_modules/graphql-ws": {
+      "version": "6.0.7",
+      "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-6.0.7.tgz",
+      "integrity": "sha512-yoLRW+KRlDmnnROdAu7sX77VNLC0bsFoZyGQJLy1cF+X/SkLg/fWkRGrEEYQK8o2cafJ2wmEaMqMEZB3U3DYDg==",
+      "devOptional": true,
+      "engines": {
+        "node": ">=20"
+      },
+      "peerDependencies": {
+        "@fastify/websocket": "^10 || ^11",
+        "crossws": "~0.3",
+        "graphql": "^15.10.1 || ^16",
+        "ws": "^8"
+      },
+      "peerDependenciesMeta": {
+        "@fastify/websocket": {
+          "optional": true
+        },
+        "crossws": {
+          "optional": true
+        },
+        "ws": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/hast-util-to-jsx-runtime": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
+      "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
+      "dependencies": {
+        "@types/estree": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/unist": "^3.0.0",
+        "comma-separated-tokens": "^2.0.0",
+        "devlop": "^1.0.0",
+        "estree-util-is-identifier-name": "^3.0.0",
+        "hast-util-whitespace": "^3.0.0",
+        "mdast-util-mdx-expression": "^2.0.0",
+        "mdast-util-mdx-jsx": "^3.0.0",
+        "mdast-util-mdxjs-esm": "^2.0.0",
+        "property-information": "^7.0.0",
+        "space-separated-tokens": "^2.0.0",
+        "style-to-js": "^1.0.0",
+        "unist-util-position": "^5.0.0",
+        "vfile-message": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/hast-util-whitespace": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+      "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+      "dependencies": {
+        "@types/hast": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/header-case": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz",
+      "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==",
+      "dev": true,
+      "dependencies": {
+        "capital-case": "^1.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/highlight.js": {
+      "version": "11.11.1",
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
+      "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/hoist-non-react-statics": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+      "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+      "dependencies": {
+        "react-is": "^16.7.0"
+      }
+    },
+    "node_modules/html-url-attributes": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
+      "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/http-proxy-agent": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+      "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+      "dev": true,
+      "dependencies": {
+        "agent-base": "^7.1.0",
+        "debug": "^4.3.4"
+      },
+      "engines": {
+        "node": ">= 14"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+      "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+      "dev": true,
+      "dependencies": {
+        "agent-base": "^7.1.2",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 14"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+      "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+      "dev": true,
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/express"
+      }
+    },
+    "node_modules/ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/ignore": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+      "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+      "dev": true,
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/immutable": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
+      "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
+      "dev": true
+    },
+    "node_modules/import-fresh": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+      "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+      "dev": true,
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/import-fresh/node_modules/resolve-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/import-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz",
+      "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.2"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/indent-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+      "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "node_modules/inline-style-parser": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz",
+      "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="
+    },
+    "node_modules/inquirer": {
+      "version": "8.2.7",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.7.tgz",
+      "integrity": "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==",
+      "dev": true,
+      "dependencies": {
+        "@inquirer/external-editor": "^1.0.0",
+        "ansi-escapes": "^4.2.1",
+        "chalk": "^4.1.1",
+        "cli-cursor": "^3.1.0",
+        "cli-width": "^3.0.0",
+        "figures": "^3.0.0",
+        "lodash": "^4.17.21",
+        "mute-stream": "0.0.8",
+        "ora": "^5.4.1",
+        "run-async": "^2.4.0",
+        "rxjs": "^7.5.5",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0",
+        "through": "^2.3.6",
+        "wrap-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "dev": true,
+      "dependencies": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "node_modules/is-absolute": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+      "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
+      "dev": true,
+      "dependencies": {
+        "is-relative": "^1.0.0",
+        "is-windows": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-alphabetical": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
+      "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/is-alphanumerical": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
+      "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
+      "dependencies": {
+        "is-alphabetical": "^2.0.0",
+        "is-decimal": "^2.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+      "dev": true
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.16.1",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+      "dependencies": {
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-decimal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
+      "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-hexadecimal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
+      "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/is-interactive": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+      "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-lower-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz",
+      "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/is-plain-obj": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+      "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-relative": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+      "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
+      "dev": true,
+      "dependencies": {
+        "is-unc-path": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-unc-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+      "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
+      "dev": true,
+      "dependencies": {
+        "unc-path-regex": "^0.1.2"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-unicode-supported": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/is-upper-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz",
+      "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/isomorphic-ws": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
+      "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==",
+      "dev": true,
+      "peerDependencies": {
+        "ws": "*"
+      }
+    },
+    "node_modules/isows": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz",
+      "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/wevm"
+        }
+      ],
+      "peerDependencies": {
+        "ws": "*"
+      }
+    },
+    "node_modules/jiti": {
+      "version": "1.21.7",
+      "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+      "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+      "bin": {
+        "jiti": "bin/jiti.js"
+      }
+    },
+    "node_modules/jose": {
+      "version": "5.10.0",
+      "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
+      "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/panva"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+    },
+    "node_modules/js-yaml": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+      "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "dev": true,
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "dev": true
+    },
+    "node_modules/json-to-pretty-yaml": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz",
+      "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==",
+      "dev": true,
+      "dependencies": {
+        "remedial": "^1.0.7",
+        "remove-trailing-spaces": "^1.0.6"
+      },
+      "engines": {
+        "node": ">= 0.2.0"
+      }
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "dev": true,
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/lilconfig": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+      "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antonk52"
+      }
+    },
+    "node_modules/lines-and-columns": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+    },
+    "node_modules/listr2": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz",
+      "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==",
+      "dev": true,
+      "dependencies": {
+        "cli-truncate": "^2.1.0",
+        "colorette": "^2.0.16",
+        "log-update": "^4.0.0",
+        "p-map": "^4.0.0",
+        "rfdc": "^1.3.0",
+        "rxjs": "^7.5.5",
+        "through": "^2.3.8",
+        "wrap-ansi": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "peerDependencies": {
+        "enquirer": ">= 2.3.0 < 3"
+      },
+      "peerDependenciesMeta": {
+        "enquirer": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/listr2/node_modules/wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.23",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+      "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+      "dev": true
+    },
+    "node_modules/lodash.sortby": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+      "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
+      "dev": true
+    },
+    "node_modules/log-symbols": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "^4.1.0",
+        "is-unicode-supported": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-update": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+      "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+      "dev": true,
+      "dependencies": {
+        "ansi-escapes": "^4.3.0",
+        "cli-cursor": "^3.1.0",
+        "slice-ansi": "^4.0.0",
+        "wrap-ansi": "^6.2.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-update/node_modules/slice-ansi": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+      "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+      }
+    },
+    "node_modules/longest-streak": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
+      "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "dependencies": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      },
+      "bin": {
+        "loose-envify": "cli.js"
+      }
+    },
+    "node_modules/lower-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
+      "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/lower-case-first": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz",
+      "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/lucide-react": {
+      "version": "0.468.0",
+      "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz",
+      "integrity": "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==",
+      "peerDependencies": {
+        "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc"
+      }
+    },
+    "node_modules/map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/markdown-table": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
+      "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/mdast-util-find-and-replace": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
+      "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "escape-string-regexp": "^5.0.0",
+        "unist-util-is": "^6.0.0",
+        "unist-util-visit-parents": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/mdast-util-from-markdown": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
+      "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "@types/unist": "^3.0.0",
+        "decode-named-character-reference": "^1.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-to-string": "^4.0.0",
+        "micromark": "^4.0.0",
+        "micromark-util-decode-numeric-character-reference": "^2.0.0",
+        "micromark-util-decode-string": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0",
+        "unist-util-stringify-position": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-gfm": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
+      "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
+      "dependencies": {
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-gfm-autolink-literal": "^2.0.0",
+        "mdast-util-gfm-footnote": "^2.0.0",
+        "mdast-util-gfm-strikethrough": "^2.0.0",
+        "mdast-util-gfm-table": "^2.0.0",
+        "mdast-util-gfm-task-list-item": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-gfm-autolink-literal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
+      "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "ccount": "^2.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-find-and-replace": "^3.0.0",
+        "micromark-util-character": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-gfm-footnote": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
+      "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.1.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-gfm-strikethrough": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
+      "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-gfm-table": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
+      "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "markdown-table": "^3.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-gfm-task-list-item": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
+      "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-mdx-expression": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
+      "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
+      "dependencies": {
+        "@types/estree-jsx": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-mdx-jsx": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
+      "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
+      "dependencies": {
+        "@types/estree-jsx": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "@types/unist": "^3.0.0",
+        "ccount": "^2.0.0",
+        "devlop": "^1.1.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0",
+        "parse-entities": "^4.0.0",
+        "stringify-entities": "^4.0.0",
+        "unist-util-stringify-position": "^4.0.0",
+        "vfile-message": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-mdxjs-esm": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
+      "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
+      "dependencies": {
+        "@types/estree-jsx": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-phrasing": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
+      "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "unist-util-is": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-to-hast": {
+      "version": "13.2.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+      "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
+      "dependencies": {
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "@ungap/structured-clone": "^1.0.0",
+        "devlop": "^1.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "trim-lines": "^3.0.0",
+        "unist-util-position": "^5.0.0",
+        "unist-util-visit": "^5.0.0",
+        "vfile": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-to-markdown": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
+      "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "@types/unist": "^3.0.0",
+        "longest-streak": "^3.0.0",
+        "mdast-util-phrasing": "^4.0.0",
+        "mdast-util-to-string": "^4.0.0",
+        "micromark-util-classify-character": "^2.0.0",
+        "micromark-util-decode-string": "^2.0.0",
+        "unist-util-visit": "^5.0.0",
+        "zwitch": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/mdast-util-to-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
+      "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/meros": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.2.tgz",
+      "integrity": "sha512-Q3mobPbvEx7XbwhnC1J1r60+5H6EZyNccdzSz0eGexJRwouUtTZxPVRGdqKtxlpD84ScK4+tIGldkqDtCKdI0A==",
+      "dev": true,
+      "engines": {
+        "node": ">=13"
+      },
+      "peerDependencies": {
+        "@types/node": ">=13"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/micromark": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
+      "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "@types/debug": "^4.0.0",
+        "debug": "^4.0.0",
+        "decode-named-character-reference": "^1.0.0",
+        "devlop": "^1.0.0",
+        "micromark-core-commonmark": "^2.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-combine-extensions": "^2.0.0",
+        "micromark-util-decode-numeric-character-reference": "^2.0.0",
+        "micromark-util-encode": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-resolve-all": "^2.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "micromark-util-subtokenize": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-core-commonmark": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
+      "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "decode-named-character-reference": "^1.0.0",
+        "devlop": "^1.0.0",
+        "micromark-factory-destination": "^2.0.0",
+        "micromark-factory-label": "^2.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-factory-title": "^2.0.0",
+        "micromark-factory-whitespace": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-classify-character": "^2.0.0",
+        "micromark-util-html-tag-name": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-resolve-all": "^2.0.0",
+        "micromark-util-subtokenize": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-extension-gfm": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
+      "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
+      "dependencies": {
+        "micromark-extension-gfm-autolink-literal": "^2.0.0",
+        "micromark-extension-gfm-footnote": "^2.0.0",
+        "micromark-extension-gfm-strikethrough": "^2.0.0",
+        "micromark-extension-gfm-table": "^2.0.0",
+        "micromark-extension-gfm-tagfilter": "^2.0.0",
+        "micromark-extension-gfm-task-list-item": "^2.0.0",
+        "micromark-util-combine-extensions": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-extension-gfm-autolink-literal": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
+      "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
+      "dependencies": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-extension-gfm-footnote": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
+      "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
+      "dependencies": {
+        "devlop": "^1.0.0",
+        "micromark-core-commonmark": "^2.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-extension-gfm-strikethrough": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
+      "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
+      "dependencies": {
+        "devlop": "^1.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-classify-character": "^2.0.0",
+        "micromark-util-resolve-all": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-extension-gfm-table": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
+      "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
+      "dependencies": {
+        "devlop": "^1.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-extension-gfm-tagfilter": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
+      "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
+      "dependencies": {
+        "micromark-util-types": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-extension-gfm-task-list-item": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
+      "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
+      "dependencies": {
+        "devlop": "^1.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-factory-destination": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
+      "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-factory-label": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
+      "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "devlop": "^1.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-factory-space": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
+      "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-factory-title": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
+      "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-factory-whitespace": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
+      "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-character": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+      "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-chunked": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
+      "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-classify-character": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
+      "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-combine-extensions": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
+      "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-decode-numeric-character-reference": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
+      "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-decode-string": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
+      "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "decode-named-character-reference": "^1.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-decode-numeric-character-reference": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-encode": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+      "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ]
+    },
+    "node_modules/micromark-util-html-tag-name": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
+      "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ]
+    },
+    "node_modules/micromark-util-normalize-identifier": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
+      "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-resolve-all": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
+      "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-sanitize-uri": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+      "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-encode": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-subtokenize": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
+      "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "dependencies": {
+        "devlop": "^1.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-symbol": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+      "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ]
+    },
+    "node_modules/micromark-util-types": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+      "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==",
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ]
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "dependencies": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "10.2.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
+      "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^5.0.2"
+      },
+      "engines": {
+        "node": "18 || 20 || >=22"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+    },
+    "node_modules/mute-stream": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+      "dev": true
+    },
+    "node_modules/mz": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+      "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+      "dependencies": {
+        "any-promise": "^1.0.0",
+        "object-assign": "^4.0.1",
+        "thenify-all": "^1.0.0"
+      }
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/no-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
+      "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
+      "dev": true,
+      "dependencies": {
+        "lower-case": "^2.0.2",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/node-domexception": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+      "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+      "deprecated": "Use your platform's native DOMException instead",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/jimmywarting"
+        },
+        {
+          "type": "github",
+          "url": "https://paypal.me/jimmywarting"
+        }
+      ],
+      "engines": {
+        "node": ">=10.5.0"
+      }
+    },
+    "node_modules/node-fetch": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+      "dev": true,
+      "dependencies": {
+        "whatwg-url": "^5.0.0"
+      },
+      "engines": {
+        "node": "4.x || >=6.0.0"
+      },
+      "peerDependencies": {
+        "encoding": "^0.1.0"
+      },
+      "peerDependenciesMeta": {
+        "encoding": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.36",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
+      "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
+      "dev": true
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/object-hash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+      "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/onetime": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dev": true,
+      "dependencies": {
+        "mimic-fn": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/optimism": {
+      "version": "0.18.1",
+      "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.1.tgz",
+      "integrity": "sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==",
+      "dependencies": {
+        "@wry/caches": "^1.0.0",
+        "@wry/context": "^0.7.0",
+        "@wry/trie": "^0.5.0",
+        "tslib": "^2.3.0"
+      }
+    },
+    "node_modules/ora": {
+      "version": "5.4.1",
+      "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+      "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+      "dev": true,
+      "dependencies": {
+        "bl": "^4.1.0",
+        "chalk": "^4.1.0",
+        "cli-cursor": "^3.1.0",
+        "cli-spinners": "^2.5.0",
+        "is-interactive": "^1.0.0",
+        "is-unicode-supported": "^0.1.0",
+        "log-symbols": "^4.1.0",
+        "strip-ansi": "^6.0.0",
+        "wcwidth": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-map": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+      "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+      "dev": true,
+      "dependencies": {
+        "aggregate-error": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/param-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+      "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
+      "dev": true,
+      "dependencies": {
+        "dot-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/parse-entities": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
+      "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
+      "dependencies": {
+        "@types/unist": "^2.0.0",
+        "character-entities-legacy": "^3.0.0",
+        "character-reference-invalid": "^2.0.0",
+        "decode-named-character-reference": "^1.0.0",
+        "is-alphanumerical": "^2.0.0",
+        "is-decimal": "^2.0.0",
+        "is-hexadecimal": "^2.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/parse-entities/node_modules/@types/unist": {
+      "version": "2.0.11",
+      "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+      "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
+    },
+    "node_modules/parse-filepath": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
+      "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==",
+      "dev": true,
+      "dependencies": {
+        "is-absolute": "^1.0.0",
+        "map-cache": "^0.2.0",
+        "path-root": "^0.1.1"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/parse-json": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.0.0",
+        "error-ex": "^1.3.1",
+        "json-parse-even-better-errors": "^2.3.0",
+        "lines-and-columns": "^1.1.6"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/pascal-case": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
+      "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
+      "dev": true,
+      "dependencies": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/path-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz",
+      "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==",
+      "dev": true,
+      "dependencies": {
+        "dot-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "node_modules/path-root": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
+      "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==",
+      "dev": true,
+      "dependencies": {
+        "path-root-regex": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-root-regex": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz",
+      "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/pirates": {
+      "version": "4.0.7",
+      "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+      "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.8",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+      "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/postcss-import": {
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+      "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+      "dependencies": {
+        "postcss-value-parser": "^4.0.0",
+        "read-cache": "^1.0.0",
+        "resolve": "^1.1.7"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "peerDependencies": {
+        "postcss": "^8.0.0"
+      }
+    },
+    "node_modules/postcss-js": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
+      "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "camelcase-css": "^2.0.1"
+      },
+      "engines": {
+        "node": "^12 || ^14 || >= 16"
+      },
+      "peerDependencies": {
+        "postcss": "^8.4.21"
+      }
+    },
+    "node_modules/postcss-load-config": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
+      "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "lilconfig": "^3.1.1"
+      },
+      "engines": {
+        "node": ">= 18"
+      },
+      "peerDependencies": {
+        "jiti": ">=1.21.0",
+        "postcss": ">=8.0.9",
+        "tsx": "^4.8.1",
+        "yaml": "^2.4.2"
+      },
+      "peerDependenciesMeta": {
+        "jiti": {
+          "optional": true
+        },
+        "postcss": {
+          "optional": true
+        },
+        "tsx": {
+          "optional": true
+        },
+        "yaml": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/postcss-nested": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+      "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "postcss-selector-parser": "^6.1.1"
+      },
+      "engines": {
+        "node": ">=12.0"
+      },
+      "peerDependencies": {
+        "postcss": "^8.2.14"
+      }
+    },
+    "node_modules/postcss-nested/node_modules/postcss-selector-parser": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+      "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postcss-selector-parser": {
+      "version": "6.0.10",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+      "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+      "dev": true,
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postcss-value-parser": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+      "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+    },
+    "node_modules/prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "dependencies": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "node_modules/property-information": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
+      "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/react": {
+      "version": "19.2.4",
+      "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
+      "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-dom": {
+      "version": "19.2.4",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
+      "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+      "dependencies": {
+        "scheduler": "^0.27.0"
+      },
+      "peerDependencies": {
+        "react": "^19.2.4"
+      }
+    },
+    "node_modules/react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
+    "node_modules/react-markdown": {
+      "version": "9.1.0",
+      "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.1.0.tgz",
+      "integrity": "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==",
+      "dependencies": {
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "hast-util-to-jsx-runtime": "^2.0.0",
+        "html-url-attributes": "^3.0.0",
+        "mdast-util-to-hast": "^13.0.0",
+        "remark-parse": "^11.0.0",
+        "remark-rehype": "^11.0.0",
+        "unified": "^11.0.0",
+        "unist-util-visit": "^5.0.0",
+        "vfile": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      },
+      "peerDependencies": {
+        "@types/react": ">=18",
+        "react": ">=18"
+      }
+    },
+    "node_modules/react-refresh": {
+      "version": "0.17.0",
+      "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+      "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/react-remove-scroll": {
+      "version": "2.7.2",
+      "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
+      "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
+      "license": "MIT",
+      "dependencies": {
+        "react-remove-scroll-bar": "^2.3.7",
+        "react-style-singleton": "^2.2.3",
+        "tslib": "^2.1.0",
+        "use-callback-ref": "^1.3.3",
+        "use-sidecar": "^1.1.3"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/react-remove-scroll-bar": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+      "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+      "license": "MIT",
+      "dependencies": {
+        "react-style-singleton": "^2.2.2",
+        "tslib": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/react-router": {
+      "version": "6.30.3",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
+      "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
+      "dependencies": {
+        "@remix-run/router": "1.23.2"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.8"
+      }
+    },
+    "node_modules/react-router-dom": {
+      "version": "6.30.3",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
+      "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
+      "dependencies": {
+        "@remix-run/router": "1.23.2",
+        "react-router": "6.30.3"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "peerDependencies": {
+        "react": ">=16.8",
+        "react-dom": ">=16.8"
+      }
+    },
+    "node_modules/react-style-singleton": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+      "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+      "license": "MIT",
+      "dependencies": {
+        "get-nonce": "^1.0.0",
+        "tslib": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/read-cache": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+      "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+      "dependencies": {
+        "pify": "^2.3.0"
+      }
+    },
+    "node_modules/readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "dev": true,
+      "dependencies": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/rehackt": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz",
+      "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==",
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "*"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/remark-gfm": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
+      "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-gfm": "^3.0.0",
+        "micromark-extension-gfm": "^3.0.0",
+        "remark-parse": "^11.0.0",
+        "remark-stringify": "^11.0.0",
+        "unified": "^11.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/remark-parse": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
+      "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "micromark-util-types": "^2.0.0",
+        "unified": "^11.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/remark-rehype": {
+      "version": "11.1.2",
+      "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
+      "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
+      "dependencies": {
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "mdast-util-to-hast": "^13.0.0",
+        "unified": "^11.0.0",
+        "vfile": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/remark-stringify": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
+      "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
+      "dependencies": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-to-markdown": "^2.0.0",
+        "unified": "^11.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/remedial": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz",
+      "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==",
+      "dev": true,
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==",
+      "dev": true
+    },
+    "node_modules/remove-trailing-spaces": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.9.tgz",
+      "integrity": "sha512-xzG7w5IRijvIkHIjDk65URsJJ7k4J95wmcArY5PRcmjldIOl7oTvG8+X2Ag690R7SfwiOcHrWZKVc1Pp5WIOzA==",
+      "dev": true
+    },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.11",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+      "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+      "dependencies": {
+        "is-core-module": "^2.16.1",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/restore-cursor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+      "dev": true,
+      "dependencies": {
+        "onetime": "^5.1.0",
+        "signal-exit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/reusify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+      "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+      "dev": true
+    },
+    "node_modules/rollup": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
+      "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "1.0.8"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.59.0",
+        "@rollup/rollup-android-arm64": "4.59.0",
+        "@rollup/rollup-darwin-arm64": "4.59.0",
+        "@rollup/rollup-darwin-x64": "4.59.0",
+        "@rollup/rollup-freebsd-arm64": "4.59.0",
+        "@rollup/rollup-freebsd-x64": "4.59.0",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+        "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+        "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+        "@rollup/rollup-linux-arm64-musl": "4.59.0",
+        "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+        "@rollup/rollup-linux-loong64-musl": "4.59.0",
+        "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+        "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+        "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+        "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+        "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+        "@rollup/rollup-linux-x64-gnu": "4.59.0",
+        "@rollup/rollup-linux-x64-musl": "4.59.0",
+        "@rollup/rollup-openbsd-x64": "4.59.0",
+        "@rollup/rollup-openharmony-arm64": "4.59.0",
+        "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+        "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+        "@rollup/rollup-win32-x64-gnu": "4.59.0",
+        "@rollup/rollup-win32-x64-msvc": "4.59.0",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/run-async": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+      "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "node_modules/rxjs": {
+      "version": "7.8.2",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
+      "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "node_modules/scheduler": {
+      "version": "0.27.0",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+      "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="
+    },
+    "node_modules/scuid": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz",
+      "integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==",
+      "dev": true
+    },
+    "node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/sentence-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz",
+      "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==",
+      "dev": true,
+      "dependencies": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3",
+        "upper-case-first": "^2.0.2"
+      }
+    },
+    "node_modules/shell-quote": {
+      "version": "1.8.3",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
+      "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "dev": true
+    },
+    "node_modules/slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/slice-ansi": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+      "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/snake-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
+      "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
+      "dev": true,
+      "dependencies": {
+        "dot-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/space-separated-tokens": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+      "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/sponge-case": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz",
+      "integrity": "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dev": true,
+      "dependencies": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "node_modules/string-env-interpolation": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz",
+      "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==",
+      "dev": true
+    },
+    "node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/stringify-entities": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+      "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+      "dependencies": {
+        "character-entities-html4": "^2.0.0",
+        "character-entities-legacy": "^3.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/style-to-js": {
+      "version": "1.1.21",
+      "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
+      "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==",
+      "dependencies": {
+        "style-to-object": "1.0.14"
+      }
+    },
+    "node_modules/style-to-object": {
+      "version": "1.0.14",
+      "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz",
+      "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==",
+      "dependencies": {
+        "inline-style-parser": "0.2.7"
+      }
+    },
+    "node_modules/sucrase": {
+      "version": "3.35.1",
+      "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
+      "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.2",
+        "commander": "^4.0.0",
+        "lines-and-columns": "^1.1.6",
+        "mz": "^2.7.0",
+        "pirates": "^4.0.1",
+        "tinyglobby": "^0.2.11",
+        "ts-interface-checker": "^0.1.9"
+      },
+      "bin": {
+        "sucrase": "bin/sucrase",
+        "sucrase-node": "bin/sucrase-node"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/swap-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz",
+      "integrity": "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/symbol-observable": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
+      "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==",
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/sync-fetch": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0.tgz",
+      "integrity": "sha512-IELLEvzHuCfc1uTsshPK58ViSdNqXxlml1U+fmwJIKLYKOr/rAtBrorE2RYm5IHaMpDNlmC0fr1LAvdXvyheEQ==",
+      "dev": true,
+      "dependencies": {
+        "node-fetch": "^3.3.2",
+        "timeout-signal": "^2.0.0",
+        "whatwg-mimetype": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/sync-fetch/node_modules/node-fetch": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+      "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+      "dev": true,
+      "dependencies": {
+        "data-uri-to-buffer": "^4.0.0",
+        "fetch-blob": "^3.1.4",
+        "formdata-polyfill": "^4.0.10"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/node-fetch"
+      }
+    },
+    "node_modules/tailwind-merge": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz",
+      "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/dcastil"
+      }
+    },
+    "node_modules/tailwindcss": {
+      "version": "3.4.19",
+      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
+      "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
+      "dependencies": {
+        "@alloc/quick-lru": "^5.2.0",
+        "arg": "^5.0.2",
+        "chokidar": "^3.6.0",
+        "didyoumean": "^1.2.2",
+        "dlv": "^1.1.3",
+        "fast-glob": "^3.3.2",
+        "glob-parent": "^6.0.2",
+        "is-glob": "^4.0.3",
+        "jiti": "^1.21.7",
+        "lilconfig": "^3.1.3",
+        "micromatch": "^4.0.8",
+        "normalize-path": "^3.0.0",
+        "object-hash": "^3.0.0",
+        "picocolors": "^1.1.1",
+        "postcss": "^8.4.47",
+        "postcss-import": "^15.1.0",
+        "postcss-js": "^4.0.1",
+        "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
+        "postcss-nested": "^6.2.0",
+        "postcss-selector-parser": "^6.1.2",
+        "resolve": "^1.22.8",
+        "sucrase": "^3.35.0"
+      },
+      "bin": {
+        "tailwind": "lib/cli.js",
+        "tailwindcss": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/tailwindcss-animate": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
+      "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+      "peerDependencies": {
+        "tailwindcss": ">=3.0.0 || insiders"
+      }
+    },
+    "node_modules/tailwindcss/node_modules/glob-parent": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/tailwindcss/node_modules/postcss-selector-parser": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+      "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/thenify": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+      "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+      "dependencies": {
+        "any-promise": "^1.0.0"
+      }
+    },
+    "node_modules/thenify-all": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+      "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+      "dependencies": {
+        "thenify": ">= 3.1.0 < 4"
+      },
+      "engines": {
+        "node": ">=0.8"
+      }
+    },
+    "node_modules/through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+      "dev": true
+    },
+    "node_modules/timeout-signal": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/timeout-signal/-/timeout-signal-2.0.0.tgz",
+      "integrity": "sha512-YBGpG4bWsHoPvofT6y/5iqulfXIiIErl5B0LdtHT1mGXDFTAhhRrbUpTvBgYbovr+3cKblya2WAOcpoy90XguA==",
+      "dev": true,
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/tinyglobby": {
+      "version": "0.2.15",
+      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+      "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+      "dependencies": {
+        "fdir": "^6.5.0",
+        "picomatch": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/SuperchupuDev"
+      }
+    },
+    "node_modules/tinyglobby/node_modules/fdir": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/tinyglobby/node_modules/picomatch": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+      "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/title-case": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz",
+      "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+      "dev": true
+    },
+    "node_modules/trim-lines": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+      "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/trough": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+      "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/ts-interface-checker": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+      "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+    },
+    "node_modules/ts-invariant": {
+      "version": "0.10.3",
+      "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz",
+      "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==",
+      "dependencies": {
+        "tslib": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ts-log": {
+      "version": "2.2.7",
+      "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.7.tgz",
+      "integrity": "sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg==",
+      "dev": true
+    },
+    "node_modules/tslib": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+    },
+    "node_modules/type-fest": {
+      "version": "0.21.3",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+      "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/unc-path-regex": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+      "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "7.18.2",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
+      "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
+      "dev": true
+    },
+    "node_modules/unified": {
+      "version": "11.0.5",
+      "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
+      "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "bail": "^2.0.0",
+        "devlop": "^1.0.0",
+        "extend": "^3.0.0",
+        "is-plain-obj": "^4.0.0",
+        "trough": "^2.0.0",
+        "vfile": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-is": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+      "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+      "dependencies": {
+        "@types/unist": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-position": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+      "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+      "dependencies": {
+        "@types/unist": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-stringify-position": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+      "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+      "dependencies": {
+        "@types/unist": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-visit": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
+      "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "unist-util-is": "^6.0.0",
+        "unist-util-visit-parents": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-visit-parents": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
+      "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "unist-util-is": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unixify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz",
+      "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==",
+      "dev": true,
+      "dependencies": {
+        "normalize-path": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/unixify/node_modules/normalize-path": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+      "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
+      "dev": true,
+      "dependencies": {
+        "remove-trailing-separator": "^1.0.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+      "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "dependencies": {
+        "escalade": "^3.2.0",
+        "picocolors": "^1.1.1"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/upper-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz",
+      "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/upper-case-first": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz",
+      "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==",
+      "dev": true,
+      "dependencies": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "node_modules/urlpattern-polyfill": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz",
+      "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==",
+      "dev": true
+    },
+    "node_modules/use-callback-ref": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+      "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+      "license": "MIT",
+      "dependencies": {
+        "tslib": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/use-sidecar": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+      "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+      "license": "MIT",
+      "dependencies": {
+        "detect-node-es": "^1.1.0",
+        "tslib": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "peerDependencies": {
+        "@types/react": "*",
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/use-sync-external-store": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+      "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+      "peerDependencies": {
+        "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+      }
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+    },
+    "node_modules/value-or-promise": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz",
+      "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/vfile": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+      "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "vfile-message": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/vfile-message": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+      "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "unist-util-stringify-position": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/vite": {
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
+      "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+      "dev": true,
+      "dependencies": {
+        "esbuild": "^0.25.0",
+        "fdir": "^6.4.4",
+        "picomatch": "^4.0.2",
+        "postcss": "^8.5.3",
+        "rollup": "^4.34.9",
+        "tinyglobby": "^0.2.13"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
+        "jiti": ">=1.21.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "sass-embedded": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.16.0",
+        "tsx": "^4.8.1",
+        "yaml": "^2.4.2"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "jiti": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        },
+        "tsx": {
+          "optional": true
+        },
+        "yaml": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vite/node_modules/fdir": {
+      "version": "6.5.0",
+      "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+      "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.0.0"
+      },
+      "peerDependencies": {
+        "picomatch": "^3 || ^4"
+      },
+      "peerDependenciesMeta": {
+        "picomatch": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vite/node_modules/picomatch": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+      "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/wcwidth": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+      "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+      "dev": true,
+      "dependencies": {
+        "defaults": "^1.0.3"
+      }
+    },
+    "node_modules/web-streams-polyfill": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+      "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+      "dev": true,
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+      "dev": true
+    },
+    "node_modules/whatwg-mimetype": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+      "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "dev": true,
+      "dependencies": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
+    "node_modules/wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ws": {
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
+      "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+      "dev": true,
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "peerDependencies": {
+        "bufferutil": "^4.0.1",
+        "utf-8-validate": ">=5.0.2"
+      },
+      "peerDependenciesMeta": {
+        "bufferutil": {
+          "optional": true
+        },
+        "utf-8-validate": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true
+    },
+    "node_modules/yaml": {
+      "version": "2.8.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
+      "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
+      "devOptional": true,
+      "bin": {
+        "yaml": "bin.mjs"
+      },
+      "engines": {
+        "node": ">= 14.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/eemeli"
+      }
+    },
+    "node_modules/yaml-ast-parser": {
+      "version": "0.0.43",
+      "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz",
+      "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==",
+      "dev": true
+    },
+    "node_modules/yargs": {
+      "version": "17.7.2",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^8.0.1",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.1.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yargs-parser": {
+      "version": "21.1.1",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/zen-observable": {
+      "version": "0.8.15",
+      "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
+      "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ=="
+    },
+    "node_modules/zen-observable-ts": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz",
+      "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==",
+      "dependencies": {
+        "zen-observable": "0.8.15"
+      }
+    },
+    "node_modules/zwitch": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+      "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    }
+  },
+  "dependencies": {
+    "@alloc/quick-lru": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+      "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="
+    },
+    "@apollo/client": {
+      "version": "3.14.0",
+      "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.14.0.tgz",
+      "integrity": "sha512-0YQKKRIxiMlIou+SekQqdCo0ZTHxOcES+K8vKB53cIDpwABNR0P0yRzPgsbgcj3zRJniD93S/ontsnZsCLZrxQ==",
+      "requires": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@wry/caches": "^1.0.0",
+        "@wry/equality": "^0.5.6",
+        "@wry/trie": "^0.5.0",
+        "graphql-tag": "^2.12.6",
+        "hoist-non-react-statics": "^3.3.2",
+        "optimism": "^0.18.0",
+        "prop-types": "^15.7.2",
+        "rehackt": "^0.1.0",
+        "symbol-observable": "^4.0.0",
+        "ts-invariant": "^0.10.3",
+        "tslib": "^2.3.0",
+        "zen-observable-ts": "^1.2.5"
+      }
+    },
+    "@ardatan/relay-compiler": {
+      "version": "13.0.0",
+      "resolved": "https://registry.npmjs.org/@ardatan/relay-compiler/-/relay-compiler-13.0.0.tgz",
+      "integrity": "sha512-ite4+xng5McO8MflWCi0un0YmnorTujsDnfPfhzYzAgoJ+jkI1pZj6jtmTl8Jptyi1H+Pa0zlatJIsxDD++ETA==",
+      "dev": true,
+      "requires": {
+        "@babel/runtime": "^7.26.10",
+        "immutable": "^5.1.5",
+        "invariant": "^2.2.4"
+      }
+    },
+    "@babel/code-frame": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+      "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-validator-identifier": "^7.28.5",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.1.1"
+      }
+    },
+    "@babel/compat-data": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz",
+      "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==",
+      "dev": true
+    },
+    "@babel/core": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+      "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.29.0",
+        "@babel/generator": "^7.29.0",
+        "@babel/helper-compilation-targets": "^7.28.6",
+        "@babel/helper-module-transforms": "^7.28.6",
+        "@babel/helpers": "^7.28.6",
+        "@babel/parser": "^7.29.0",
+        "@babel/template": "^7.28.6",
+        "@babel/traverse": "^7.29.0",
+        "@babel/types": "^7.29.0",
+        "@jridgewell/remapping": "^2.3.5",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      }
+    },
+    "@babel/generator": {
+      "version": "7.29.1",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+      "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
+      "dev": true,
+      "requires": {
+        "@babel/parser": "^7.29.0",
+        "@babel/types": "^7.29.0",
+        "@jridgewell/gen-mapping": "^0.3.12",
+        "@jridgewell/trace-mapping": "^0.3.28",
+        "jsesc": "^3.0.2"
+      }
+    },
+    "@babel/helper-compilation-targets": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+      "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
+      "dev": true,
+      "requires": {
+        "@babel/compat-data": "^7.28.6",
+        "@babel/helper-validator-option": "^7.27.1",
+        "browserslist": "^4.24.0",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      }
+    },
+    "@babel/helper-globals": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+      "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
+      "dev": true
+    },
+    "@babel/helper-module-imports": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+      "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
+      "dev": true,
+      "requires": {
+        "@babel/traverse": "^7.28.6",
+        "@babel/types": "^7.28.6"
+      }
+    },
+    "@babel/helper-module-transforms": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+      "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-module-imports": "^7.28.6",
+        "@babel/helper-validator-identifier": "^7.28.5",
+        "@babel/traverse": "^7.28.6"
+      }
+    },
+    "@babel/helper-plugin-utils": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+      "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
+      "dev": true
+    },
+    "@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+      "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+      "dev": true
+    },
+    "@babel/helper-validator-identifier": {
+      "version": "7.28.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+      "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+      "dev": true
+    },
+    "@babel/helper-validator-option": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+      "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
+      "dev": true
+    },
+    "@babel/helpers": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
+      "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+      "dev": true,
+      "requires": {
+        "@babel/template": "^7.28.6",
+        "@babel/types": "^7.28.6"
+      }
+    },
+    "@babel/parser": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz",
+      "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.29.0"
+      }
+    },
+    "@babel/plugin-syntax-import-assertions": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz",
+      "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.28.6"
+      }
+    },
+    "@babel/plugin-transform-react-jsx-self": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz",
+      "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      }
+    },
+    "@babel/plugin-transform-react-jsx-source": {
+      "version": "7.27.1",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz",
+      "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.27.1"
+      }
+    },
+    "@babel/runtime": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+      "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+      "dev": true
+    },
+    "@babel/template": {
+      "version": "7.28.6",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+      "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.28.6",
+        "@babel/parser": "^7.28.6",
+        "@babel/types": "^7.28.6"
+      }
+    },
+    "@babel/traverse": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+      "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.29.0",
+        "@babel/generator": "^7.29.0",
+        "@babel/helper-globals": "^7.28.0",
+        "@babel/parser": "^7.29.0",
+        "@babel/template": "^7.28.6",
+        "@babel/types": "^7.29.0",
+        "debug": "^4.3.1"
+      }
+    },
+    "@babel/types": {
+      "version": "7.29.0",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+      "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.28.5"
+      }
+    },
+    "@envelop/core": {
+      "version": "5.5.1",
+      "resolved": "https://registry.npmjs.org/@envelop/core/-/core-5.5.1.tgz",
+      "integrity": "sha512-3DQg8sFskDo386TkL5j12jyRAdip/8yzK3x7YGbZBgobZ4aKXrvDU0GppU0SnmrpQnNaiTUsxBs9LKkwQ/eyvw==",
+      "dev": true,
+      "requires": {
+        "@envelop/instrumentation": "^1.0.0",
+        "@envelop/types": "^5.2.1",
+        "@whatwg-node/promise-helpers": "^1.2.4",
+        "tslib": "^2.5.0"
+      }
+    },
+    "@envelop/instrumentation": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/@envelop/instrumentation/-/instrumentation-1.0.0.tgz",
+      "integrity": "sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==",
+      "dev": true,
+      "requires": {
+        "@whatwg-node/promise-helpers": "^1.2.1",
+        "tslib": "^2.5.0"
+      }
+    },
+    "@envelop/types": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/@envelop/types/-/types-5.2.1.tgz",
+      "integrity": "sha512-CsFmA3u3c2QoLDTfEpGr4t25fjMU31nyvse7IzWTvb0ZycuPjMjb0fjlheh+PbhBYb9YLugnT2uY6Mwcg1o+Zg==",
+      "dev": true,
+      "requires": {
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "tslib": "^2.5.0"
+      }
+    },
+    "@esbuild/aix-ppc64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
+      "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
+      "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
+      "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/android-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
+      "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
+      "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/darwin-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
+      "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
+      "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/freebsd-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
+      "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
+      "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
+      "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ia32": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
+      "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-loong64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
+      "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-mips64el": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
+      "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-ppc64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
+      "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-riscv64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
+      "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-s390x": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
+      "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/linux-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
+      "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/netbsd-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
+      "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/netbsd-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
+      "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
+      "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openbsd-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
+      "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/openharmony-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
+      "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/sunos-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
+      "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-arm64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
+      "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-ia32": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
+      "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@esbuild/win32-x64": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
+      "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
+      "dev": true,
+      "optional": true
+    },
+    "@fastify/busboy": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-3.2.0.tgz",
+      "integrity": "sha512-m9FVDXU3GT2ITSe0UaMA5rU3QkfC/UXtCU8y0gSN/GugTqtVldOBWIB5V6V3sbmenVZUIpU6f+mPEO2+m5iTaA==",
+      "dev": true
+    },
+    "@floating-ui/core": {
+      "version": "1.7.5",
+      "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
+      "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+      "requires": {
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "@floating-ui/dom": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
+      "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+      "requires": {
+        "@floating-ui/core": "^1.7.5",
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "@floating-ui/react-dom": {
+      "version": "2.1.8",
+      "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz",
+      "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==",
+      "requires": {
+        "@floating-ui/dom": "^1.7.6"
+      }
+    },
+    "@floating-ui/utils": {
+      "version": "0.2.11",
+      "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
+      "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="
+    },
+    "@graphql-codegen/add": {
+      "version": "5.0.3",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz",
+      "integrity": "sha512-SxXPmramkth8XtBlAHu4H4jYcYXM/o3p01+psU+0NADQowA8jtYkK6MW5rV6T+CxkEaNZItfSmZRPgIuypcqnA==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.0.3",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/cli": {
+      "version": "5.0.7",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.7.tgz",
+      "integrity": "sha512-h/sxYvSaWtxZxo8GtaA8SvcHTyViaaPd7dweF/hmRDpaQU1o3iU3EZxlcJ+oLTunU0tSMFsnrIXm/mhXxI11Cw==",
+      "dev": true,
+      "requires": {
+        "@babel/generator": "^7.18.13",
+        "@babel/template": "^7.18.10",
+        "@babel/types": "^7.18.13",
+        "@graphql-codegen/client-preset": "^4.8.2",
+        "@graphql-codegen/core": "^4.0.2",
+        "@graphql-codegen/plugin-helpers": "^5.1.1",
+        "@graphql-tools/apollo-engine-loader": "^8.0.0",
+        "@graphql-tools/code-file-loader": "^8.0.0",
+        "@graphql-tools/git-loader": "^8.0.0",
+        "@graphql-tools/github-loader": "^8.0.0",
+        "@graphql-tools/graphql-file-loader": "^8.0.0",
+        "@graphql-tools/json-file-loader": "^8.0.0",
+        "@graphql-tools/load": "^8.1.0",
+        "@graphql-tools/prisma-loader": "^8.0.0",
+        "@graphql-tools/url-loader": "^8.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "@whatwg-node/fetch": "^0.10.0",
+        "chalk": "^4.1.0",
+        "cosmiconfig": "^8.1.3",
+        "debounce": "^1.2.0",
+        "detect-indent": "^6.0.0",
+        "graphql-config": "^5.1.1",
+        "inquirer": "^8.0.0",
+        "is-glob": "^4.0.1",
+        "jiti": "^1.17.1",
+        "json-to-pretty-yaml": "^1.2.2",
+        "listr2": "^4.0.5",
+        "log-symbols": "^4.0.0",
+        "micromatch": "^4.0.5",
+        "shell-quote": "^1.7.3",
+        "string-env-interpolation": "^1.0.1",
+        "ts-log": "^2.2.3",
+        "tslib": "^2.4.0",
+        "yaml": "^2.3.1",
+        "yargs": "^17.0.0"
+      }
+    },
+    "@graphql-codegen/client-preset": {
+      "version": "4.8.3",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.8.3.tgz",
+      "integrity": "sha512-QpEsPSO9fnRxA6Z66AmBuGcwHjZ6dYSxYo5ycMlYgSPzAbyG8gn/kWljofjJfWqSY+T/lRn+r8IXTH14ml24vQ==",
+      "dev": true,
+      "requires": {
+        "@babel/helper-plugin-utils": "^7.20.2",
+        "@babel/template": "^7.20.7",
+        "@graphql-codegen/add": "^5.0.3",
+        "@graphql-codegen/gql-tag-operations": "4.0.17",
+        "@graphql-codegen/plugin-helpers": "^5.1.1",
+        "@graphql-codegen/typed-document-node": "^5.1.2",
+        "@graphql-codegen/typescript": "^4.1.6",
+        "@graphql-codegen/typescript-operations": "^4.6.1",
+        "@graphql-codegen/visitor-plugin-common": "^5.8.0",
+        "@graphql-tools/documents": "^1.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "@graphql-typed-document-node/core": "3.2.0",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/core": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.2.tgz",
+      "integrity": "sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.0.3",
+        "@graphql-tools/schema": "^10.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/gql-tag-operations": {
+      "version": "4.0.17",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.17.tgz",
+      "integrity": "sha512-2pnvPdIG6W9OuxkrEZ6hvZd142+O3B13lvhrZ48yyEBh2ujtmKokw0eTwDHtlXUqjVS0I3q7+HB2y12G/m69CA==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "auto-bind": "~4.0.0",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/plugin-helpers": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.1.1.tgz",
+      "integrity": "sha512-28GHODK2HY1NhdyRcPP3sCz0Kqxyfiz7boIZ8qIxFYmpLYnlDgiYok5fhFLVSZihyOpCs4Fa37gVHf/Q4I2FEg==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^10.0.0",
+        "change-case-all": "1.0.15",
+        "common-tags": "1.8.2",
+        "import-from": "4.0.0",
+        "lodash": "~4.17.0",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/schema-ast": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.1.0.tgz",
+      "integrity": "sha512-kZVn0z+th9SvqxfKYgztA6PM7mhnSZaj4fiuBWvMTqA+QqQ9BBed6Pz41KuD/jr0gJtnlr2A4++/0VlpVbCTmQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.0.3",
+        "@graphql-tools/utils": "^10.0.0",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/typed-document-node": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typed-document-node/-/typed-document-node-5.1.2.tgz",
+      "integrity": "sha512-jaxfViDqFRbNQmfKwUY8hDyjnLTw2Z7DhGutxoOiiAI0gE/LfPe0LYaVFKVmVOOD7M3bWxoWfu4slrkbWbUbEw==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "auto-bind": "~4.0.0",
+        "change-case-all": "1.0.15",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/typescript": {
+      "version": "4.1.6",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.1.6.tgz",
+      "integrity": "sha512-vpw3sfwf9A7S+kIUjyFxuvrywGxd4lmwmyYnnDVjVE4kSQ6Td3DpqaPTy8aNQ6O96vFoi/bxbZS2BW49PwSUUA==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/schema-ast": "^4.0.2",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "auto-bind": "~4.0.0",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/typescript-operations": {
+      "version": "4.6.1",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.6.1.tgz",
+      "integrity": "sha512-k92laxhih7s0WZ8j5WMIbgKwhe64C0As6x+PdcvgZFMudDJ7rPJ/hFqJ9DCRxNjXoHmSjnr6VUuQZq4lT1RzCA==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-codegen/typescript": "^4.1.6",
+        "@graphql-codegen/visitor-plugin-common": "5.8.0",
+        "auto-bind": "~4.0.0",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/typescript-react-apollo": {
+      "version": "4.4.1",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-react-apollo/-/typescript-react-apollo-4.4.1.tgz",
+      "integrity": "sha512-lrjUfDCNlCWQU07jO6EvZE8I2OLfJl9XKKGCcol27OhW6B9xaUEPaId+TvL6o/NfV+T4z4eQ/Y8BuKWyYjD+mQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^6.1.1",
+        "@graphql-codegen/visitor-plugin-common": "^6.2.4",
+        "auto-bind": "~4.0.0",
+        "change-case-all": "1.0.15",
+        "tslib": "^2.8.1"
+      },
+      "dependencies": {
+        "@graphql-codegen/plugin-helpers": {
+          "version": "6.1.1",
+          "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-6.1.1.tgz",
+          "integrity": "sha512-ipWZHA4ZG8PUdZWx87rvL6LCoIZVhrovVl+448FuxnKIGdzyLmL3+FJc/x96jsQZqKKrUcId9oEgssyh6p15eg==",
+          "dev": true,
+          "requires": {
+            "@graphql-tools/utils": "^11.0.0",
+            "change-case-all": "1.0.15",
+            "common-tags": "1.8.2",
+            "import-from": "4.0.0",
+            "lodash": "~4.17.0",
+            "tslib": "~2.6.0"
+          },
+          "dependencies": {
+            "tslib": {
+              "version": "2.6.3",
+              "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+              "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+              "dev": true
+            }
+          }
+        },
+        "@graphql-codegen/visitor-plugin-common": {
+          "version": "6.2.4",
+          "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-6.2.4.tgz",
+          "integrity": "sha512-iwiVCc7Mv8/XAa3K35AdFQ9chJSDv/gYEnBeQFF/Sq/W8EyJoHypOGOTTLk7OSrWO4xea65ggv0e7fGt7rPJjQ==",
+          "dev": true,
+          "requires": {
+            "@graphql-codegen/plugin-helpers": "^6.1.1",
+            "@graphql-tools/optimize": "^2.0.0",
+            "@graphql-tools/relay-operation-optimizer": "^7.1.1",
+            "@graphql-tools/utils": "^11.0.0",
+            "auto-bind": "~4.0.0",
+            "change-case-all": "1.0.15",
+            "dependency-graph": "^1.0.0",
+            "graphql-tag": "^2.11.0",
+            "parse-filepath": "^1.0.2",
+            "tslib": "~2.6.0"
+          },
+          "dependencies": {
+            "tslib": {
+              "version": "2.6.3",
+              "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+              "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+              "dev": true
+            }
+          }
+        },
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        },
+        "dependency-graph": {
+          "version": "1.0.0",
+          "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-1.0.0.tgz",
+          "integrity": "sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-codegen/visitor-plugin-common": {
+      "version": "5.8.0",
+      "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.8.0.tgz",
+      "integrity": "sha512-lC1E1Kmuzi3WZUlYlqB4fP6+CvbKH9J+haU1iWmgsBx5/sO2ROeXJG4Dmt8gP03bI2BwjiwV5WxCEMlyeuzLnA==",
+      "dev": true,
+      "requires": {
+        "@graphql-codegen/plugin-helpers": "^5.1.0",
+        "@graphql-tools/optimize": "^2.0.0",
+        "@graphql-tools/relay-operation-optimizer": "^7.0.0",
+        "@graphql-tools/utils": "^10.0.0",
+        "auto-bind": "~4.0.0",
+        "change-case-all": "1.0.15",
+        "dependency-graph": "^0.11.0",
+        "graphql-tag": "^2.11.0",
+        "parse-filepath": "^1.0.2",
+        "tslib": "~2.6.0"
+      },
+      "dependencies": {
+        "tslib": {
+          "version": "2.6.3",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+          "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
+          "dev": true
+        }
+      }
+    },
+    "@graphql-hive/signal": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-hive/signal/-/signal-2.0.0.tgz",
+      "integrity": "sha512-Pz8wB3K0iU6ae9S1fWfsmJX24CcGeTo6hE7T44ucmV/ALKRj+bxClmqrYcDT7v3f0d12Rh4FAXBb6gon+WkDpQ==",
+      "dev": true
+    },
+    "@graphql-tools/apollo-engine-loader": {
+      "version": "8.0.28",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.28.tgz",
+      "integrity": "sha512-MzgDrUuoxp6dZeo54zLBL3cEJKJtM3N/2RqK0rbPxPq5X2z6TUA7EGg8vIFTUkt5xelAsUrm8/4ai41ZDdxOng==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^11.0.0",
+        "@whatwg-node/fetch": "^0.10.13",
+        "sync-fetch": "0.6.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/batch-execute": {
+      "version": "9.0.6",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-9.0.6.tgz",
+      "integrity": "sha512-S0mLTUJQJuItGmwouYZyXeFaRWOVmVCAMLi33M5PuZbnsoTwKMB/YPPkAQ72ay3GfclnW66XcO4EClbVynw7eQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^10.5.6",
+        "dataloader": "^2.2.2",
+        "tslib": "^2.4.0",
+        "value-or-promise": "^1.0.12"
+      }
+    },
+    "@graphql-tools/code-file-loader": {
+      "version": "8.1.28",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.1.28.tgz",
+      "integrity": "sha512-BL3Ft/PFlXDE5nNuqA36hYci7Cx+8bDrPDc8X3VSpZy9iKFBY+oQ+IwqnEHCkt8OSp2n2V0gqTg4u3fcQP1Kwg==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/graphql-tag-pluck": "8.3.27",
+        "@graphql-tools/utils": "^11.0.0",
+        "globby": "^11.0.3",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/delegate": {
+      "version": "10.1.2",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.1.2.tgz",
+      "integrity": "sha512-2XXJdxjud0ROiKxIiieCx4SxzSjYNdCz1bVDrI6+nTFxV5kB15OnJU6jvom44kv+NJo4Dym5GOJNqlBEjxoFVA==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/batch-execute": "^9.0.6",
+        "@graphql-tools/executor": "^1.3.3",
+        "@graphql-tools/schema": "^10.0.8",
+        "@graphql-tools/utils": "^10.5.6",
+        "@repeaterjs/repeater": "^3.0.6",
+        "dataloader": "^2.2.2",
+        "dset": "^3.1.2",
+        "tslib": "^2.5.0"
+      }
+    },
+    "@graphql-tools/documents": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/documents/-/documents-1.0.1.tgz",
+      "integrity": "sha512-aweoMH15wNJ8g7b2r4C4WRuJxZ0ca8HtNO54rkye/3duxTkW4fGBEutCx03jCIr5+a1l+4vFJNP859QnAVBVCA==",
+      "dev": true,
+      "requires": {
+        "lodash.sortby": "^4.7.0",
+        "tslib": "^2.4.0"
+      }
+    },
+    "@graphql-tools/executor": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.5.1.tgz",
+      "integrity": "sha512-n94Qcu875Mji9GQ52n5UbgOTxlgvFJicBPYD+FRks9HKIQpdNPjkkrKZUYNG51XKa+bf03rxNflm4+wXhoHHrA==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^11.0.0",
+        "@graphql-typed-document-node/core": "^3.2.0",
+        "@repeaterjs/repeater": "^3.0.4",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/executor-common": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-common/-/executor-common-0.0.6.tgz",
+      "integrity": "sha512-JAH/R1zf77CSkpYATIJw+eOJwsbWocdDjY+avY7G+P5HCXxwQjAjWVkJI1QJBQYjPQDVxwf1fmTZlIN3VOadow==",
+      "dev": true,
+      "requires": {
+        "@envelop/core": "^5.3.0",
+        "@graphql-tools/utils": "^10.9.1"
+      }
+    },
+    "@graphql-tools/executor-graphql-ws": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-2.0.7.tgz",
+      "integrity": "sha512-J27za7sKF6RjhmvSOwOQFeNhNHyP4f4niqPnerJmq73OtLx9Y2PGOhkXOEB0PjhvPJceuttkD2O1yMgEkTGs3Q==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/executor-common": "^0.0.6",
+        "@graphql-tools/utils": "^10.9.1",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "graphql-ws": "^6.0.6",
+        "isomorphic-ws": "^5.0.0",
+        "tslib": "^2.8.1",
+        "ws": "^8.18.3"
+      }
+    },
+    "@graphql-tools/executor-http": {
+      "version": "1.1.9",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-1.1.9.tgz",
+      "integrity": "sha512-dJRj78QEGNNnlhkhqPUG9z+1uAr7znZ4dzabEVgY5uSXTmUIFcTKpOGYv2/QAuvyqGN40XxbcdVRJta6XHX2BQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^10.5.6",
+        "@repeaterjs/repeater": "^3.0.4",
+        "@whatwg-node/fetch": "^0.10.0",
+        "extract-files": "^11.0.0",
+        "meros": "^1.2.1",
+        "tslib": "^2.4.0",
+        "value-or-promise": "^1.0.12"
+      }
+    },
+    "@graphql-tools/executor-legacy-ws": {
+      "version": "1.1.25",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.1.25.tgz",
+      "integrity": "sha512-6uf4AEXO0QMxJ7AWKVPqEZXgYBJaiz5vf29X0boG8QtcqWy8mqkXKWLND2Swdx0SbEx0efoGFcjuKufUcB0ASQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^11.0.0",
+        "@types/ws": "^8.0.0",
+        "isomorphic-ws": "^5.0.0",
+        "tslib": "^2.4.0",
+        "ws": "^8.19.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/git-loader": {
+      "version": "8.0.32",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.32.tgz",
+      "integrity": "sha512-H5HTp2vevv0rRMEnCJBVmVF8md3LpJI1C1+d6OtzvmuONJ8mOX2mkf9rtoqwiztynVegaDUekvMFsc9k5iE2WA==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/graphql-tag-pluck": "8.3.27",
+        "@graphql-tools/utils": "^11.0.0",
+        "is-glob": "4.0.3",
+        "micromatch": "^4.0.8",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/github-loader": {
+      "version": "8.0.22",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-8.0.22.tgz",
+      "integrity": "sha512-uQ4JNcNPsyMkTIgzeSbsoT9hogLjYrZooLUYd173l5eUGUi49EAcsGdiBCKaKfEjanv410FE8hjaHr7fjSRkJw==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/executor-http": "^1.1.9",
+        "@graphql-tools/graphql-tag-pluck": "^8.3.21",
+        "@graphql-tools/utils": "^10.9.1",
+        "@whatwg-node/fetch": "^0.10.0",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "sync-fetch": "0.6.0-2",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "node-fetch": {
+          "version": "3.3.2",
+          "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+          "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+          "dev": true,
+          "requires": {
+            "data-uri-to-buffer": "^4.0.0",
+            "fetch-blob": "^3.1.4",
+            "formdata-polyfill": "^4.0.10"
+          }
+        },
+        "sync-fetch": {
+          "version": "0.6.0-2",
+          "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0-2.tgz",
+          "integrity": "sha512-c7AfkZ9udatCuAy9RSfiGPpeOKKUAUK5e1cXadLOGUjasdxqYqAK0jTNkM/FSEyJ3a5Ra27j/tw/PS0qLmaF/A==",
+          "dev": true,
+          "requires": {
+            "node-fetch": "^3.3.2",
+            "timeout-signal": "^2.0.0",
+            "whatwg-mimetype": "^4.0.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/graphql-file-loader": {
+      "version": "8.1.12",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.1.12.tgz",
+      "integrity": "sha512-Nma7gBgJoUbqXWTmdHjouo36tjzewA8MptVcHoH7widzkciaUVzBhriHzqICFB/dVxig//g9MX8s1XawZo7UAg==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/import": "^7.1.12",
+        "@graphql-tools/utils": "^11.0.0",
+        "globby": "^11.0.3",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/graphql-tag-pluck": {
+      "version": "8.3.27",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.3.27.tgz",
+      "integrity": "sha512-CJ0WVXhGYsfFngpRrAAcjRHyxSDHx4dEz2W15bkwvt9he/AWhuyXm07wuGcoLrl0q0iQp1BiRjU7D8SxWZo3JQ==",
+      "dev": true,
+      "requires": {
+        "@babel/core": "^7.26.10",
+        "@babel/parser": "^7.26.10",
+        "@babel/plugin-syntax-import-assertions": "^7.26.0",
+        "@babel/traverse": "^7.26.10",
+        "@babel/types": "^7.26.10",
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/import": {
+      "version": "7.1.12",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-7.1.12.tgz",
+      "integrity": "sha512-QSsdPsdJ7yCgQ5XODyKYpC7NlB9R1Koi0R3418PT7GiRm+9O8gYXSs/23dumcOnpiLrnf4qR2aytBn1+JOAhnA==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^11.0.0",
+        "resolve-from": "5.0.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/json-file-loader": {
+      "version": "8.0.26",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-8.0.26.tgz",
+      "integrity": "sha512-kwy9IFi5QtXXTLBgWkvA1RqsZeJDn0CxsTbhNlziCzmga9fNo7qtZ18k9FYIq3EIoQQlok+b7W7yeyJATA2xhw==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^11.0.0",
+        "globby": "^11.0.3",
+        "tslib": "^2.4.0",
+        "unixify": "^1.0.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/load": {
+      "version": "8.1.8",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-8.1.8.tgz",
+      "integrity": "sha512-gxO662b64qZSToK3N6XUxWG5E6HOUjlg5jEnmGvD4bMtGJ0HwEe/BaVZbBQemCfLkxYjwRIBiVfOY9o0JyjZJg==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/schema": "^10.0.31",
+        "@graphql-tools/utils": "^11.0.0",
+        "p-limit": "3.1.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/merge": {
+      "version": "9.1.7",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.1.7.tgz",
+      "integrity": "sha512-Y5E1vTbTabvcXbkakdFUt4zUIzB1fyaEnVmIWN0l0GMed2gdD01TpZWLUm4RNAxpturvolrb24oGLQrBbPLSoQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/optimize": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/optimize/-/optimize-2.0.0.tgz",
+      "integrity": "sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.4.0"
+      }
+    },
+    "@graphql-tools/prisma-loader": {
+      "version": "8.0.17",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-8.0.17.tgz",
+      "integrity": "sha512-fnuTLeQhqRbA156pAyzJYN0KxCjKYRU5bz1q/SKOwElSnAU4k7/G1kyVsWLh7fneY78LoMNH5n+KlFV8iQlnyg==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/url-loader": "^8.0.15",
+        "@graphql-tools/utils": "^10.5.6",
+        "@types/js-yaml": "^4.0.0",
+        "@whatwg-node/fetch": "^0.10.0",
+        "chalk": "^4.1.0",
+        "debug": "^4.3.1",
+        "dotenv": "^16.0.0",
+        "graphql-request": "^6.0.0",
+        "http-proxy-agent": "^7.0.0",
+        "https-proxy-agent": "^7.0.0",
+        "jose": "^5.0.0",
+        "js-yaml": "^4.0.0",
+        "lodash": "^4.17.20",
+        "scuid": "^1.1.0",
+        "tslib": "^2.4.0",
+        "yaml-ast-parser": "^0.0.43"
+      }
+    },
+    "@graphql-tools/relay-operation-optimizer": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.1.1.tgz",
+      "integrity": "sha512-va+ZieMlz6Fj18xUbwyQkZ34PsnzIdPT6Ccy1BNOQw1iclQwk52HejLMZeE/4fH+4cu80Q2HXi5+FjCKpmnJCg==",
+      "dev": true,
+      "requires": {
+        "@ardatan/relay-compiler": "^13.0.0",
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/schema": {
+      "version": "10.0.31",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.31.tgz",
+      "integrity": "sha512-ZewRgWhXef6weZ0WiP7/MV47HXiuFbFpiDUVLQl6mgXsWSsGELKFxQsyUCBos60Qqy1JEFAIu3Ns6GGYjGkqkQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/merge": "^9.1.7",
+        "@graphql-tools/utils": "^11.0.0",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/url-loader": {
+      "version": "8.0.33",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-8.0.33.tgz",
+      "integrity": "sha512-Fu626qcNHcqAj8uYd7QRarcJn5XZ863kmxsg1sm0fyjyfBJnsvC7ddFt6Hayz5kxVKfsnjxiDfPMXanvsQVBKw==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/executor-graphql-ws": "^2.0.1",
+        "@graphql-tools/executor-http": "^1.1.9",
+        "@graphql-tools/executor-legacy-ws": "^1.1.19",
+        "@graphql-tools/utils": "^10.9.1",
+        "@graphql-tools/wrap": "^10.0.16",
+        "@types/ws": "^8.0.0",
+        "@whatwg-node/fetch": "^0.10.0",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "isomorphic-ws": "^5.0.0",
+        "sync-fetch": "0.6.0-2",
+        "tslib": "^2.4.0",
+        "ws": "^8.17.1"
+      },
+      "dependencies": {
+        "node-fetch": {
+          "version": "3.3.2",
+          "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+          "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+          "dev": true,
+          "requires": {
+            "data-uri-to-buffer": "^4.0.0",
+            "fetch-blob": "^3.1.4",
+            "formdata-polyfill": "^4.0.10"
+          }
+        },
+        "sync-fetch": {
+          "version": "0.6.0-2",
+          "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0-2.tgz",
+          "integrity": "sha512-c7AfkZ9udatCuAy9RSfiGPpeOKKUAUK5e1cXadLOGUjasdxqYqAK0jTNkM/FSEyJ3a5Ra27j/tw/PS0qLmaF/A==",
+          "dev": true,
+          "requires": {
+            "node-fetch": "^3.3.2",
+            "timeout-signal": "^2.0.0",
+            "whatwg-mimetype": "^4.0.0"
+          }
+        }
+      }
+    },
+    "@graphql-tools/utils": {
+      "version": "10.11.0",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.11.0.tgz",
+      "integrity": "sha512-iBFR9GXIs0gCD+yc3hoNswViL1O5josI33dUqiNStFI/MHLCEPduasceAcazRH77YONKNiviHBV8f7OgcT4o2Q==",
+      "dev": true,
+      "requires": {
+        "@graphql-typed-document-node/core": "^3.1.1",
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "cross-inspect": "1.0.1",
+        "tslib": "^2.4.0"
+      }
+    },
+    "@graphql-tools/wrap": {
+      "version": "10.0.16",
+      "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.0.16.tgz",
+      "integrity": "sha512-O/sOoPCnG2tWfhfIeWLQMPS7ipzjMiVOxwhjOUD9DaQd39XFBD4Al/MmKNc2343ua7NyqMwdfgXQjqGH1LFlPA==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/delegate": "^10.1.2",
+        "@graphql-tools/schema": "^10.0.8",
+        "@graphql-tools/utils": "^10.5.6",
+        "tslib": "^2.4.0",
+        "value-or-promise": "^1.0.12"
+      }
+    },
+    "@graphql-typed-document-node/core": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz",
+      "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==",
+      "requires": {}
+    },
+    "@inquirer/external-editor": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/@inquirer/external-editor/-/external-editor-1.0.3.tgz",
+      "integrity": "sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==",
+      "dev": true,
+      "requires": {
+        "chardet": "^2.1.1",
+        "iconv-lite": "^0.7.0"
+      }
+    },
+    "@jridgewell/gen-mapping": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+      "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+      "requires": {
+        "@jridgewell/sourcemap-codec": "^1.5.0",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "@jridgewell/remapping": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+      "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+      "dev": true,
+      "requires": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="
+    },
+    "@jridgewell/sourcemap-codec": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="
+    },
+    "@jridgewell/trace-mapping": {
+      "version": "0.3.31",
+      "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+      "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+      "requires": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "requires": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      }
+    },
+    "@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="
+    },
+    "@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "requires": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      }
+    },
+    "@radix-ui/primitive": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
+      "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="
+    },
+    "@radix-ui/react-arrow": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
+      "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
+      "requires": {
+        "@radix-ui/react-primitive": "2.1.3"
+      },
+      "dependencies": {
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/react-avatar": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.11.tgz",
+      "integrity": "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==",
+      "requires": {
+        "@radix-ui/react-context": "1.1.3",
+        "@radix-ui/react-primitive": "2.1.4",
+        "@radix-ui/react-use-callback-ref": "1.1.1",
+        "@radix-ui/react-use-is-hydrated": "0.1.0",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      }
+    },
+    "@radix-ui/react-compose-refs": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
+      "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
+      "requires": {}
+    },
+    "@radix-ui/react-context": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.3.tgz",
+      "integrity": "sha512-ieIFACdMpYfMEjF0rEf5KLvfVyIkOz6PDGyNnP+u+4xQ6jny3VCgA4OgXOwNx2aUkxn8zx9fiVcM8CfFYv9Lxw==",
+      "requires": {}
+    },
+    "@radix-ui/react-dismissable-layer": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
+      "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
+      "requires": {
+        "@radix-ui/primitive": "1.1.3",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-callback-ref": "1.1.1",
+        "@radix-ui/react-use-escape-keydown": "1.1.1"
+      },
+      "dependencies": {
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/react-focus-guards": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
+      "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
+      "requires": {}
+    },
+    "@radix-ui/react-focus-scope": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
+      "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
+      "requires": {
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-callback-ref": "1.1.1"
+      },
+      "dependencies": {
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/react-id": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
+      "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
+      "requires": {
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      }
+    },
+    "@radix-ui/react-popover": {
+      "version": "1.1.15",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
+      "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
+      "requires": {
+        "@radix-ui/primitive": "1.1.3",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-context": "1.1.2",
+        "@radix-ui/react-dismissable-layer": "1.1.11",
+        "@radix-ui/react-focus-guards": "1.1.3",
+        "@radix-ui/react-focus-scope": "1.1.7",
+        "@radix-ui/react-id": "1.1.1",
+        "@radix-ui/react-popper": "1.2.8",
+        "@radix-ui/react-portal": "1.1.9",
+        "@radix-ui/react-presence": "1.1.5",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-slot": "1.2.3",
+        "@radix-ui/react-use-controllable-state": "1.2.2",
+        "aria-hidden": "^1.2.4",
+        "react-remove-scroll": "^2.6.3"
+      },
+      "dependencies": {
+        "@radix-ui/react-context": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+          "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+          "requires": {}
+        },
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/react-popper": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
+      "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
+      "requires": {
+        "@floating-ui/react-dom": "^2.0.0",
+        "@radix-ui/react-arrow": "1.1.7",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-context": "1.1.2",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-callback-ref": "1.1.1",
+        "@radix-ui/react-use-layout-effect": "1.1.1",
+        "@radix-ui/react-use-rect": "1.1.1",
+        "@radix-ui/react-use-size": "1.1.1",
+        "@radix-ui/rect": "1.1.1"
+      },
+      "dependencies": {
+        "@radix-ui/react-context": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+          "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+          "requires": {}
+        },
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/react-portal": {
+      "version": "1.1.9",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
+      "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
+      "requires": {
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      },
+      "dependencies": {
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/react-presence": {
+      "version": "1.1.5",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
+      "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
+      "requires": {
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      }
+    },
+    "@radix-ui/react-primitive": {
+      "version": "2.1.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz",
+      "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==",
+      "requires": {
+        "@radix-ui/react-slot": "1.2.4"
+      }
+    },
+    "@radix-ui/react-separator": {
+      "version": "1.1.8",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz",
+      "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==",
+      "requires": {
+        "@radix-ui/react-primitive": "2.1.4"
+      }
+    },
+    "@radix-ui/react-slot": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz",
+      "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==",
+      "requires": {
+        "@radix-ui/react-compose-refs": "1.1.2"
+      }
+    },
+    "@radix-ui/react-tooltip": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
+      "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
+      "requires": {
+        "@radix-ui/primitive": "1.1.3",
+        "@radix-ui/react-compose-refs": "1.1.2",
+        "@radix-ui/react-context": "1.1.2",
+        "@radix-ui/react-dismissable-layer": "1.1.11",
+        "@radix-ui/react-id": "1.1.1",
+        "@radix-ui/react-popper": "1.2.8",
+        "@radix-ui/react-portal": "1.1.9",
+        "@radix-ui/react-presence": "1.1.5",
+        "@radix-ui/react-primitive": "2.1.3",
+        "@radix-ui/react-slot": "1.2.3",
+        "@radix-ui/react-use-controllable-state": "1.2.2",
+        "@radix-ui/react-visually-hidden": "1.2.3"
+      },
+      "dependencies": {
+        "@radix-ui/react-context": {
+          "version": "1.1.2",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
+          "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
+          "requires": {}
+        },
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/react-use-callback-ref": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
+      "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
+      "requires": {}
+    },
+    "@radix-ui/react-use-controllable-state": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
+      "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
+      "requires": {
+        "@radix-ui/react-use-effect-event": "0.0.2",
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      }
+    },
+    "@radix-ui/react-use-effect-event": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
+      "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
+      "requires": {
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      }
+    },
+    "@radix-ui/react-use-escape-keydown": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
+      "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
+      "requires": {
+        "@radix-ui/react-use-callback-ref": "1.1.1"
+      }
+    },
+    "@radix-ui/react-use-is-hydrated": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz",
+      "integrity": "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==",
+      "requires": {
+        "use-sync-external-store": "^1.5.0"
+      }
+    },
+    "@radix-ui/react-use-layout-effect": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
+      "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
+      "requires": {}
+    },
+    "@radix-ui/react-use-rect": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
+      "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
+      "requires": {
+        "@radix-ui/rect": "1.1.1"
+      }
+    },
+    "@radix-ui/react-use-size": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
+      "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
+      "requires": {
+        "@radix-ui/react-use-layout-effect": "1.1.1"
+      }
+    },
+    "@radix-ui/react-visually-hidden": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
+      "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
+      "requires": {
+        "@radix-ui/react-primitive": "2.1.3"
+      },
+      "dependencies": {
+        "@radix-ui/react-primitive": {
+          "version": "2.1.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
+          "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
+          "requires": {
+            "@radix-ui/react-slot": "1.2.3"
+          }
+        },
+        "@radix-ui/react-slot": {
+          "version": "1.2.3",
+          "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
+          "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
+          "requires": {
+            "@radix-ui/react-compose-refs": "1.1.2"
+          }
+        }
+      }
+    },
+    "@radix-ui/rect": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
+      "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="
+    },
+    "@remix-run/router": {
+      "version": "1.23.2",
+      "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
+      "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w=="
+    },
+    "@repeaterjs/repeater": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz",
+      "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==",
+      "dev": true
+    },
+    "@rolldown/pluginutils": {
+      "version": "1.0.0-beta.27",
+      "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz",
+      "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==",
+      "dev": true
+    },
+    "@rollup/rollup-android-arm-eabi": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz",
+      "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-android-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz",
+      "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-darwin-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz",
+      "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-darwin-x64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz",
+      "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-freebsd-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz",
+      "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-freebsd-x64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz",
+      "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz",
+      "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz",
+      "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz",
+      "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-arm64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz",
+      "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-loong64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz",
+      "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-loong64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz",
+      "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-ppc64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz",
+      "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-ppc64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz",
+      "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz",
+      "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz",
+      "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz",
+      "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-x64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz",
+      "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-linux-x64-musl": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz",
+      "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-openbsd-x64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz",
+      "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-openharmony-arm64": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz",
+      "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz",
+      "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz",
+      "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-win32-x64-gnu": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz",
+      "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==",
+      "dev": true,
+      "optional": true
+    },
+    "@rollup/rollup-win32-x64-msvc": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz",
+      "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==",
+      "dev": true,
+      "optional": true
+    },
+    "@tailwindcss/typography": {
+      "version": "0.5.19",
+      "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz",
+      "integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==",
+      "dev": true,
+      "requires": {
+        "postcss-selector-parser": "6.0.10"
+      }
+    },
+    "@types/babel__core": {
+      "version": "7.20.5",
+      "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+      "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+      "dev": true,
+      "requires": {
+        "@babel/parser": "^7.20.7",
+        "@babel/types": "^7.20.7",
+        "@types/babel__generator": "*",
+        "@types/babel__template": "*",
+        "@types/babel__traverse": "*"
+      }
+    },
+    "@types/babel__generator": {
+      "version": "7.27.0",
+      "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz",
+      "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "@types/babel__template": {
+      "version": "7.4.4",
+      "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+      "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+      "dev": true,
+      "requires": {
+        "@babel/parser": "^7.1.0",
+        "@babel/types": "^7.0.0"
+      }
+    },
+    "@types/babel__traverse": {
+      "version": "7.28.0",
+      "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
+      "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==",
+      "dev": true,
+      "requires": {
+        "@babel/types": "^7.28.2"
+      }
+    },
+    "@types/debug": {
+      "version": "4.1.12",
+      "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz",
+      "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==",
+      "requires": {
+        "@types/ms": "*"
+      }
+    },
+    "@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="
+    },
+    "@types/estree-jsx": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz",
+      "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==",
+      "requires": {
+        "@types/estree": "*"
+      }
+    },
+    "@types/hast": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz",
+      "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==",
+      "requires": {
+        "@types/unist": "*"
+      }
+    },
+    "@types/js-yaml": {
+      "version": "4.0.9",
+      "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
+      "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
+      "dev": true
+    },
+    "@types/mdast": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz",
+      "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==",
+      "requires": {
+        "@types/unist": "*"
+      }
+    },
+    "@types/ms": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+      "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="
+    },
+    "@types/node": {
+      "version": "25.4.0",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-25.4.0.tgz",
+      "integrity": "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw==",
+      "dev": true,
+      "requires": {
+        "undici-types": "~7.18.0"
+      }
+    },
+    "@types/react": {
+      "version": "19.2.14",
+      "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
+      "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==",
+      "requires": {
+        "csstype": "^3.2.2"
+      }
+    },
+    "@types/react-dom": {
+      "version": "19.2.3",
+      "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
+      "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
+      "devOptional": true,
+      "requires": {}
+    },
+    "@types/unist": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz",
+      "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="
+    },
+    "@types/ws": {
+      "version": "8.18.1",
+      "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+      "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+      "dev": true,
+      "requires": {
+        "@types/node": "*"
+      }
+    },
+    "@ungap/structured-clone": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz",
+      "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="
+    },
+    "@vitejs/plugin-react": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz",
+      "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==",
+      "dev": true,
+      "requires": {
+        "@babel/core": "^7.28.0",
+        "@babel/plugin-transform-react-jsx-self": "^7.27.1",
+        "@babel/plugin-transform-react-jsx-source": "^7.27.1",
+        "@rolldown/pluginutils": "1.0.0-beta.27",
+        "@types/babel__core": "^7.20.5",
+        "react-refresh": "^0.17.0"
+      }
+    },
+    "@whatwg-node/disposablestack": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/disposablestack/-/disposablestack-0.0.6.tgz",
+      "integrity": "sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==",
+      "dev": true,
+      "requires": {
+        "@whatwg-node/promise-helpers": "^1.0.0",
+        "tslib": "^2.6.3"
+      }
+    },
+    "@whatwg-node/fetch": {
+      "version": "0.10.13",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.10.13.tgz",
+      "integrity": "sha512-b4PhJ+zYj4357zwk4TTuF2nEe0vVtOrwdsrNo5hL+u1ojXNhh1FgJ6pg1jzDlwlT4oBdzfSwaBwMCtFCsIWg8Q==",
+      "dev": true,
+      "requires": {
+        "@whatwg-node/node-fetch": "^0.8.3",
+        "urlpattern-polyfill": "^10.0.0"
+      }
+    },
+    "@whatwg-node/node-fetch": {
+      "version": "0.8.5",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.8.5.tgz",
+      "integrity": "sha512-4xzCl/zphPqlp9tASLVeUhB5+WJHbuWGYpfoC2q1qh5dw0AqZBW7L27V5roxYWijPxj4sspRAAoOH3d2ztaHUQ==",
+      "dev": true,
+      "requires": {
+        "@fastify/busboy": "^3.1.1",
+        "@whatwg-node/disposablestack": "^0.0.6",
+        "@whatwg-node/promise-helpers": "^1.3.2",
+        "tslib": "^2.6.3"
+      }
+    },
+    "@whatwg-node/promise-helpers": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/@whatwg-node/promise-helpers/-/promise-helpers-1.3.2.tgz",
+      "integrity": "sha512-Nst5JdK47VIl9UcGwtv2Rcgyn5lWtZ0/mhRQ4G8NN2isxpq2TO30iqHzmwoJycjWuyUfg3GFXqP/gFHXeV57IA==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.6.3"
+      }
+    },
+    "@wry/caches": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/@wry/caches/-/caches-1.0.1.tgz",
+      "integrity": "sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==",
+      "requires": {
+        "tslib": "^2.3.0"
+      }
+    },
+    "@wry/context": {
+      "version": "0.7.4",
+      "resolved": "https://registry.npmjs.org/@wry/context/-/context-0.7.4.tgz",
+      "integrity": "sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==",
+      "requires": {
+        "tslib": "^2.3.0"
+      }
+    },
+    "@wry/equality": {
+      "version": "0.5.7",
+      "resolved": "https://registry.npmjs.org/@wry/equality/-/equality-0.5.7.tgz",
+      "integrity": "sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==",
+      "requires": {
+        "tslib": "^2.3.0"
+      }
+    },
+    "@wry/trie": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/@wry/trie/-/trie-0.5.0.tgz",
+      "integrity": "sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==",
+      "requires": {
+        "tslib": "^2.3.0"
+      }
+    },
+    "agent-base": {
+      "version": "7.1.4",
+      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
+      "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
+      "dev": true
+    },
+    "aggregate-error": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+      "dev": true,
+      "requires": {
+        "clean-stack": "^2.0.0",
+        "indent-string": "^4.0.0"
+      }
+    },
+    "ansi-escapes": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+      "dev": true,
+      "requires": {
+        "type-fest": "^0.21.3"
+      }
+    },
+    "ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "dev": true
+    },
+    "ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "requires": {
+        "color-convert": "^2.0.1"
+      }
+    },
+    "any-promise": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+      "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="
+    },
+    "anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "arg": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+      "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+    },
+    "argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "aria-hidden": {
+      "version": "1.2.6",
+      "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
+      "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
+      "requires": {
+        "tslib": "^2.0.0"
+      }
+    },
+    "array-union": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+      "dev": true
+    },
+    "astral-regex": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
+      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
+      "dev": true
+    },
+    "auto-bind": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz",
+      "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==",
+      "dev": true
+    },
+    "autoprefixer": {
+      "version": "10.4.27",
+      "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.27.tgz",
+      "integrity": "sha512-NP9APE+tO+LuJGn7/9+cohklunJsXWiaWEfV3si4Gi/XHDwVNgkwr1J3RQYFIvPy76GmJ9/bW8vyoU1LcxwKHA==",
+      "dev": true,
+      "requires": {
+        "browserslist": "^4.28.1",
+        "caniuse-lite": "^1.0.30001774",
+        "fraction.js": "^5.3.4",
+        "picocolors": "^1.1.1",
+        "postcss-value-parser": "^4.2.0"
+      }
+    },
+    "bail": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz",
+      "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="
+    },
+    "balanced-match": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
+      "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==",
+      "dev": true
+    },
+    "base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "dev": true
+    },
+    "baseline-browser-mapping": {
+      "version": "2.10.0",
+      "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz",
+      "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==",
+      "dev": true
+    },
+    "binary-extensions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+      "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="
+    },
+    "bl": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+      "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+      "dev": true,
+      "requires": {
+        "buffer": "^5.5.0",
+        "inherits": "^2.0.4",
+        "readable-stream": "^3.4.0"
+      }
+    },
+    "brace-expansion": {
+      "version": "5.0.4",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.4.tgz",
+      "integrity": "sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^4.0.2"
+      }
+    },
+    "braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "requires": {
+        "fill-range": "^7.1.1"
+      }
+    },
+    "browserslist": {
+      "version": "4.28.1",
+      "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz",
+      "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==",
+      "dev": true,
+      "requires": {
+        "baseline-browser-mapping": "^2.9.0",
+        "caniuse-lite": "^1.0.30001759",
+        "electron-to-chromium": "^1.5.263",
+        "node-releases": "^2.0.27",
+        "update-browserslist-db": "^1.2.0"
+      }
+    },
+    "buffer": {
+      "version": "5.7.1",
+      "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+      "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+      "dev": true,
+      "requires": {
+        "base64-js": "^1.3.1",
+        "ieee754": "^1.1.13"
+      }
+    },
+    "callsites": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+      "dev": true
+    },
+    "camel-case": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+      "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
+      "dev": true,
+      "requires": {
+        "pascal-case": "^3.1.2",
+        "tslib": "^2.0.3"
+      }
+    },
+    "camelcase-css": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+      "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
+    },
+    "caniuse-lite": {
+      "version": "1.0.30001777",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz",
+      "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==",
+      "dev": true
+    },
+    "capital-case": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz",
+      "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==",
+      "dev": true,
+      "requires": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3",
+        "upper-case-first": "^2.0.2"
+      }
+    },
+    "ccount": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz",
+      "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="
+    },
+    "chalk": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^4.1.0",
+        "supports-color": "^7.1.0"
+      }
+    },
+    "change-case": {
+      "version": "4.1.2",
+      "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz",
+      "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==",
+      "dev": true,
+      "requires": {
+        "camel-case": "^4.1.2",
+        "capital-case": "^1.0.4",
+        "constant-case": "^3.0.4",
+        "dot-case": "^3.0.4",
+        "header-case": "^2.0.4",
+        "no-case": "^3.0.4",
+        "param-case": "^3.0.4",
+        "pascal-case": "^3.1.2",
+        "path-case": "^3.0.4",
+        "sentence-case": "^3.0.4",
+        "snake-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "change-case-all": {
+      "version": "1.0.15",
+      "resolved": "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.15.tgz",
+      "integrity": "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==",
+      "dev": true,
+      "requires": {
+        "change-case": "^4.1.2",
+        "is-lower-case": "^2.0.2",
+        "is-upper-case": "^2.0.2",
+        "lower-case": "^2.0.2",
+        "lower-case-first": "^2.0.2",
+        "sponge-case": "^1.0.1",
+        "swap-case": "^2.0.2",
+        "title-case": "^3.0.3",
+        "upper-case": "^2.0.2",
+        "upper-case-first": "^2.0.2"
+      }
+    },
+    "character-entities": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz",
+      "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ=="
+    },
+    "character-entities-html4": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz",
+      "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="
+    },
+    "character-entities-legacy": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz",
+      "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="
+    },
+    "character-reference-invalid": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz",
+      "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw=="
+    },
+    "chardet": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-2.1.1.tgz",
+      "integrity": "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==",
+      "dev": true
+    },
+    "chokidar": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+      "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+      "requires": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "fsevents": "~2.3.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      }
+    },
+    "class-variance-authority": {
+      "version": "0.7.1",
+      "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
+      "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
+      "requires": {
+        "clsx": "^2.1.1"
+      }
+    },
+    "clean-stack": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+      "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+      "dev": true
+    },
+    "cli-cursor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
+      "dev": true,
+      "requires": {
+        "restore-cursor": "^3.1.0"
+      }
+    },
+    "cli-spinners": {
+      "version": "2.9.2",
+      "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+      "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
+      "dev": true
+    },
+    "cli-truncate": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
+      "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
+      "dev": true,
+      "requires": {
+        "slice-ansi": "^3.0.0",
+        "string-width": "^4.2.0"
+      }
+    },
+    "cli-width": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
+      "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
+      "dev": true
+    },
+    "cliui": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+      "dev": true,
+      "requires": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      },
+      "dependencies": {
+        "wrap-ansi": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+          "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          }
+        }
+      }
+    },
+    "clone": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
+      "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+      "dev": true
+    },
+    "clsx": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+      "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="
+    },
+    "color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "requires": {
+        "color-name": "~1.1.4"
+      }
+    },
+    "color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "colorette": {
+      "version": "2.0.20",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+      "dev": true
+    },
+    "comma-separated-tokens": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz",
+      "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="
+    },
+    "commander": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+      "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="
+    },
+    "common-tags": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz",
+      "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==",
+      "dev": true
+    },
+    "constant-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz",
+      "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==",
+      "dev": true,
+      "requires": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3",
+        "upper-case": "^2.0.2"
+      }
+    },
+    "convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "dev": true
+    },
+    "cosmiconfig": {
+      "version": "8.3.6",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+      "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+      "dev": true,
+      "requires": {
+        "import-fresh": "^3.3.0",
+        "js-yaml": "^4.1.0",
+        "parse-json": "^5.2.0",
+        "path-type": "^4.0.0"
+      }
+    },
+    "cross-fetch": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.2.0.tgz",
+      "integrity": "sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==",
+      "dev": true,
+      "requires": {
+        "node-fetch": "^2.7.0"
+      }
+    },
+    "cross-inspect": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.1.tgz",
+      "integrity": "sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.4.0"
+      }
+    },
+    "cssesc": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="
+    },
+    "csstype": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+      "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="
+    },
+    "data-uri-to-buffer": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+      "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+      "dev": true
+    },
+    "dataloader": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.3.tgz",
+      "integrity": "sha512-y2krtASINtPFS1rSDjacrFgn1dcUuoREVabwlOGOe4SdxenREqwjwjElAdwvbGM7kgZz9a3KVicWR7vcz8rnzA==",
+      "dev": true
+    },
+    "date-fns": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+      "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg=="
+    },
+    "debounce": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
+      "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
+      "dev": true
+    },
+    "debug": {
+      "version": "4.4.3",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+      "requires": {
+        "ms": "^2.1.3"
+      }
+    },
+    "decode-named-character-reference": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.3.0.tgz",
+      "integrity": "sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==",
+      "requires": {
+        "character-entities": "^2.0.0"
+      }
+    },
+    "defaults": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+      "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
+      "dev": true,
+      "requires": {
+        "clone": "^1.0.2"
+      }
+    },
+    "dependency-graph": {
+      "version": "0.11.0",
+      "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz",
+      "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==",
+      "dev": true
+    },
+    "dequal": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+      "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="
+    },
+    "detect-indent": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz",
+      "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==",
+      "dev": true
+    },
+    "detect-node-es": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
+      "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="
+    },
+    "devlop": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
+      "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==",
+      "requires": {
+        "dequal": "^2.0.0"
+      }
+    },
+    "didyoumean": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+      "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
+    },
+    "dir-glob": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+      "dev": true,
+      "requires": {
+        "path-type": "^4.0.0"
+      }
+    },
+    "dlv": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+      "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+    },
+    "dot-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
+      "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
+      "dev": true,
+      "requires": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "dotenv": {
+      "version": "16.6.1",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+      "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+      "dev": true
+    },
+    "dset": {
+      "version": "3.1.4",
+      "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz",
+      "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==",
+      "dev": true
+    },
+    "electron-to-chromium": {
+      "version": "1.5.307",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz",
+      "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==",
+      "dev": true
+    },
+    "emoji-regex": {
+      "version": "8.0.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+      "dev": true
+    },
+    "error-ex": {
+      "version": "1.3.4",
+      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+      "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
+      "dev": true,
+      "requires": {
+        "is-arrayish": "^0.2.1"
+      }
+    },
+    "esbuild": {
+      "version": "0.25.12",
+      "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
+      "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
+      "dev": true,
+      "requires": {
+        "@esbuild/aix-ppc64": "0.25.12",
+        "@esbuild/android-arm": "0.25.12",
+        "@esbuild/android-arm64": "0.25.12",
+        "@esbuild/android-x64": "0.25.12",
+        "@esbuild/darwin-arm64": "0.25.12",
+        "@esbuild/darwin-x64": "0.25.12",
+        "@esbuild/freebsd-arm64": "0.25.12",
+        "@esbuild/freebsd-x64": "0.25.12",
+        "@esbuild/linux-arm": "0.25.12",
+        "@esbuild/linux-arm64": "0.25.12",
+        "@esbuild/linux-ia32": "0.25.12",
+        "@esbuild/linux-loong64": "0.25.12",
+        "@esbuild/linux-mips64el": "0.25.12",
+        "@esbuild/linux-ppc64": "0.25.12",
+        "@esbuild/linux-riscv64": "0.25.12",
+        "@esbuild/linux-s390x": "0.25.12",
+        "@esbuild/linux-x64": "0.25.12",
+        "@esbuild/netbsd-arm64": "0.25.12",
+        "@esbuild/netbsd-x64": "0.25.12",
+        "@esbuild/openbsd-arm64": "0.25.12",
+        "@esbuild/openbsd-x64": "0.25.12",
+        "@esbuild/openharmony-arm64": "0.25.12",
+        "@esbuild/sunos-x64": "0.25.12",
+        "@esbuild/win32-arm64": "0.25.12",
+        "@esbuild/win32-ia32": "0.25.12",
+        "@esbuild/win32-x64": "0.25.12"
+      }
+    },
+    "escalade": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "dev": true
+    },
+    "escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "dev": true
+    },
+    "estree-util-is-identifier-name": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz",
+      "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg=="
+    },
+    "extend": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
+      "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
+    },
+    "extract-files": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz",
+      "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==",
+      "dev": true
+    },
+    "fast-glob": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+      "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+      "requires": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.8"
+      }
+    },
+    "fastq": {
+      "version": "1.20.1",
+      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+      "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+      "requires": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "fetch-blob": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+      "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+      "dev": true,
+      "requires": {
+        "node-domexception": "^1.0.0",
+        "web-streams-polyfill": "^3.0.3"
+      }
+    },
+    "figures": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
+      "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+      "dev": true,
+      "requires": {
+        "escape-string-regexp": "^1.0.5"
+      }
+    },
+    "fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "formdata-polyfill": {
+      "version": "4.0.10",
+      "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+      "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+      "dev": true,
+      "requires": {
+        "fetch-blob": "^3.1.2"
+      }
+    },
+    "fraction.js": {
+      "version": "5.3.4",
+      "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
+      "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
+      "dev": true
+    },
+    "fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "optional": true
+    },
+    "function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
+    },
+    "gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "dev": true
+    },
+    "get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true
+    },
+    "get-nonce": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
+      "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="
+    },
+    "glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "globby": {
+      "version": "11.1.0",
+      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+      "dev": true,
+      "requires": {
+        "array-union": "^2.1.0",
+        "dir-glob": "^3.0.1",
+        "fast-glob": "^3.2.9",
+        "ignore": "^5.2.0",
+        "merge2": "^1.4.1",
+        "slash": "^3.0.0"
+      }
+    },
+    "graphql": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.13.1.tgz",
+      "integrity": "sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ=="
+    },
+    "graphql-config": {
+      "version": "5.1.6",
+      "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-5.1.6.tgz",
+      "integrity": "sha512-fCkYnm4Kdq3un0YIM4BCZHVR5xl0UeLP6syxxO7KAstdY7QVyVvTHP0kRPDYEP1v08uwtJVgis5sj3IOTLOniQ==",
+      "dev": true,
+      "requires": {
+        "@graphql-tools/graphql-file-loader": "^8.0.0",
+        "@graphql-tools/json-file-loader": "^8.0.0",
+        "@graphql-tools/load": "^8.1.0",
+        "@graphql-tools/merge": "^9.0.0",
+        "@graphql-tools/url-loader": "^9.0.0",
+        "@graphql-tools/utils": "^11.0.0",
+        "cosmiconfig": "^8.1.0",
+        "jiti": "^2.0.0",
+        "minimatch": "^10.0.0",
+        "string-env-interpolation": "^1.0.1",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@graphql-tools/batch-execute": {
+          "version": "10.0.5",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-10.0.5.tgz",
+          "integrity": "sha512-dL13tXkfGvAzLq2XfzTKAy9logIcltKYRuPketxdh3Ok3U6PN1HKMCHfrE9cmtAsxD96/8Hlghz5AtM+LRv/ig==",
+          "dev": true,
+          "requires": {
+            "@graphql-tools/utils": "^11.0.0",
+            "@whatwg-node/promise-helpers": "^1.3.2",
+            "dataloader": "^2.2.3",
+            "tslib": "^2.8.1"
+          }
+        },
+        "@graphql-tools/delegate": {
+          "version": "12.0.9",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-12.0.9.tgz",
+          "integrity": "sha512-ugJCiJb4w3bmdUbAz+nKyVVuwzzoy6BZHQ4BJXpAx1i5KIEhSevIkMYq3CZo7drCZf6FMIpcKBxv99uIhzCvhA==",
+          "dev": true,
+          "requires": {
+            "@graphql-tools/batch-execute": "^10.0.5",
+            "@graphql-tools/executor": "^1.4.13",
+            "@graphql-tools/schema": "^10.0.29",
+            "@graphql-tools/utils": "^11.0.0",
+            "@repeaterjs/repeater": "^3.0.6",
+            "@whatwg-node/promise-helpers": "^1.3.2",
+            "dataloader": "^2.2.3",
+            "tslib": "^2.8.1"
+          }
+        },
+        "@graphql-tools/executor-common": {
+          "version": "1.0.6",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/executor-common/-/executor-common-1.0.6.tgz",
+          "integrity": "sha512-23/K5C+LSlHDI0mj2SwCJ33RcELCcyDUgABm1Z8St7u/4Z5+95i925H/NAjUyggRjiaY8vYtNiMOPE49aPX1sg==",
+          "dev": true,
+          "requires": {
+            "@envelop/core": "^5.4.0",
+            "@graphql-tools/utils": "^11.0.0"
+          }
+        },
+        "@graphql-tools/executor-graphql-ws": {
+          "version": "3.1.4",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-3.1.4.tgz",
+          "integrity": "sha512-wCQfWYLwg1JZmQ7rGaFy74AQyVFxpeqz19WWIGRgANiYlm+T0K3Hs6POgi0+nL3HvwxJIxhUlaRLFvkqm1zxSA==",
+          "dev": true,
+          "requires": {
+            "@graphql-tools/executor-common": "^1.0.6",
+            "@graphql-tools/utils": "^11.0.0",
+            "@whatwg-node/disposablestack": "^0.0.6",
+            "graphql-ws": "^6.0.6",
+            "isows": "^1.0.7",
+            "tslib": "^2.8.1",
+            "ws": "^8.18.3"
+          }
+        },
+        "@graphql-tools/executor-http": {
+          "version": "3.1.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-3.1.0.tgz",
+          "integrity": "sha512-DTaNU1rT2sxffwQlt+Aw68cHQWfGkjsaRk1D8nvG+DcCR8RNQo0d9qYt7pXIcfXYcQLb/OkABcGSuCfkopvHJg==",
+          "dev": true,
+          "requires": {
+            "@graphql-hive/signal": "^2.0.0",
+            "@graphql-tools/executor-common": "^1.0.6",
+            "@graphql-tools/utils": "^11.0.0",
+            "@repeaterjs/repeater": "^3.0.4",
+            "@whatwg-node/disposablestack": "^0.0.6",
+            "@whatwg-node/fetch": "^0.10.13",
+            "@whatwg-node/promise-helpers": "^1.3.2",
+            "meros": "^1.3.2",
+            "tslib": "^2.8.1"
+          }
+        },
+        "@graphql-tools/url-loader": {
+          "version": "9.0.6",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-9.0.6.tgz",
+          "integrity": "sha512-QdJI3f7ANDMYfYazRgJzzybznjOrQAOuDXweC9xmKgPZoTqNxEAsatiy69zcpTf6092taJLyrqRH6R7xUTzf4A==",
+          "dev": true,
+          "requires": {
+            "@graphql-tools/executor-graphql-ws": "^3.1.2",
+            "@graphql-tools/executor-http": "^3.0.6",
+            "@graphql-tools/executor-legacy-ws": "^1.1.25",
+            "@graphql-tools/utils": "^11.0.0",
+            "@graphql-tools/wrap": "^11.1.1",
+            "@types/ws": "^8.0.0",
+            "@whatwg-node/fetch": "^0.10.13",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "isomorphic-ws": "^5.0.0",
+            "sync-fetch": "0.6.0",
+            "tslib": "^2.4.0",
+            "ws": "^8.19.0"
+          }
+        },
+        "@graphql-tools/utils": {
+          "version": "11.0.0",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-11.0.0.tgz",
+          "integrity": "sha512-bM1HeZdXA2C3LSIeLOnH/bcqSgbQgKEDrjxODjqi3y58xai2TkNrtYcQSoWzGbt9VMN1dORGjR7Vem8SPnUFQA==",
+          "dev": true,
+          "requires": {
+            "@graphql-typed-document-node/core": "^3.1.1",
+            "@whatwg-node/promise-helpers": "^1.0.0",
+            "cross-inspect": "1.0.1",
+            "tslib": "^2.4.0"
+          }
+        },
+        "@graphql-tools/wrap": {
+          "version": "11.1.9",
+          "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-11.1.9.tgz",
+          "integrity": "sha512-dSjBNCTPS8W7lWHDgIEgY0MEDwZi1GkqTfl7bJMDs/dJfKojj4Do74LN5QJbP/bIIwJakEwVUMPA8RUYVBP9eQ==",
+          "dev": true,
+          "requires": {
+            "@graphql-tools/delegate": "^12.0.9",
+            "@graphql-tools/schema": "^10.0.29",
+            "@graphql-tools/utils": "^11.0.0",
+            "@whatwg-node/promise-helpers": "^1.3.2",
+            "tslib": "^2.8.1"
+          }
+        },
+        "jiti": {
+          "version": "2.6.1",
+          "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz",
+          "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==",
+          "dev": true
+        }
+      }
+    },
+    "graphql-request": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz",
+      "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==",
+      "dev": true,
+      "requires": {
+        "@graphql-typed-document-node/core": "^3.2.0",
+        "cross-fetch": "^3.1.5"
+      }
+    },
+    "graphql-tag": {
+      "version": "2.12.6",
+      "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz",
+      "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==",
+      "requires": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "graphql-ws": {
+      "version": "6.0.7",
+      "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-6.0.7.tgz",
+      "integrity": "sha512-yoLRW+KRlDmnnROdAu7sX77VNLC0bsFoZyGQJLy1cF+X/SkLg/fWkRGrEEYQK8o2cafJ2wmEaMqMEZB3U3DYDg==",
+      "devOptional": true,
+      "requires": {}
+    },
+    "has-flag": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+      "dev": true
+    },
+    "hasown": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+      "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+      "requires": {
+        "function-bind": "^1.1.2"
+      }
+    },
+    "hast-util-to-jsx-runtime": {
+      "version": "2.3.6",
+      "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz",
+      "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==",
+      "requires": {
+        "@types/estree": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/unist": "^3.0.0",
+        "comma-separated-tokens": "^2.0.0",
+        "devlop": "^1.0.0",
+        "estree-util-is-identifier-name": "^3.0.0",
+        "hast-util-whitespace": "^3.0.0",
+        "mdast-util-mdx-expression": "^2.0.0",
+        "mdast-util-mdx-jsx": "^3.0.0",
+        "mdast-util-mdxjs-esm": "^2.0.0",
+        "property-information": "^7.0.0",
+        "space-separated-tokens": "^2.0.0",
+        "style-to-js": "^1.0.0",
+        "unist-util-position": "^5.0.0",
+        "vfile-message": "^4.0.0"
+      }
+    },
+    "hast-util-whitespace": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz",
+      "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==",
+      "requires": {
+        "@types/hast": "^3.0.0"
+      }
+    },
+    "header-case": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz",
+      "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==",
+      "dev": true,
+      "requires": {
+        "capital-case": "^1.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "highlight.js": {
+      "version": "11.11.1",
+      "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
+      "integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="
+    },
+    "hoist-non-react-statics": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+      "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+      "requires": {
+        "react-is": "^16.7.0"
+      }
+    },
+    "html-url-attributes": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/html-url-attributes/-/html-url-attributes-3.0.1.tgz",
+      "integrity": "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="
+    },
+    "http-proxy-agent": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
+      "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
+      "dev": true,
+      "requires": {
+        "agent-base": "^7.1.0",
+        "debug": "^4.3.4"
+      }
+    },
+    "https-proxy-agent": {
+      "version": "7.0.6",
+      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
+      "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
+      "dev": true,
+      "requires": {
+        "agent-base": "^7.1.2",
+        "debug": "4"
+      }
+    },
+    "iconv-lite": {
+      "version": "0.7.2",
+      "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
+      "integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
+      "dev": true,
+      "requires": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      }
+    },
+    "ieee754": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+      "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+      "dev": true
+    },
+    "ignore": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+      "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+      "dev": true
+    },
+    "immutable": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz",
+      "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
+      "dev": true
+    },
+    "import-fresh": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+      "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+      "dev": true,
+      "requires": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "dependencies": {
+        "resolve-from": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+          "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+          "dev": true
+        }
+      }
+    },
+    "import-from": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz",
+      "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==",
+      "dev": true
+    },
+    "indent-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+      "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+      "dev": true
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "inline-style-parser": {
+      "version": "0.2.7",
+      "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz",
+      "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="
+    },
+    "inquirer": {
+      "version": "8.2.7",
+      "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.7.tgz",
+      "integrity": "sha512-UjOaSel/iddGZJ5xP/Eixh6dY1XghiBw4XK13rCCIJcJfyhhoul/7KhLLUGtebEj6GDYM6Vnx/mVsjx2L/mFIA==",
+      "dev": true,
+      "requires": {
+        "@inquirer/external-editor": "^1.0.0",
+        "ansi-escapes": "^4.2.1",
+        "chalk": "^4.1.1",
+        "cli-cursor": "^3.1.0",
+        "cli-width": "^3.0.0",
+        "figures": "^3.0.0",
+        "lodash": "^4.17.21",
+        "mute-stream": "0.0.8",
+        "ora": "^5.4.1",
+        "run-async": "^2.4.0",
+        "rxjs": "^7.5.5",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0",
+        "through": "^2.3.6",
+        "wrap-ansi": "^6.0.1"
+      }
+    },
+    "invariant": {
+      "version": "2.2.4",
+      "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
+      "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
+      "dev": true,
+      "requires": {
+        "loose-envify": "^1.0.0"
+      }
+    },
+    "is-absolute": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz",
+      "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==",
+      "dev": true,
+      "requires": {
+        "is-relative": "^1.0.0",
+        "is-windows": "^1.0.1"
+      }
+    },
+    "is-alphabetical": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz",
+      "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ=="
+    },
+    "is-alphanumerical": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz",
+      "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==",
+      "requires": {
+        "is-alphabetical": "^2.0.0",
+        "is-decimal": "^2.0.0"
+      }
+    },
+    "is-arrayish": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "requires": {
+        "binary-extensions": "^2.0.0"
+      }
+    },
+    "is-core-module": {
+      "version": "2.16.1",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+      "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+      "requires": {
+        "hasown": "^2.0.2"
+      }
+    },
+    "is-decimal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz",
+      "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A=="
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="
+    },
+    "is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true
+    },
+    "is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-hexadecimal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz",
+      "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg=="
+    },
+    "is-interactive": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+      "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+      "dev": true
+    },
+    "is-lower-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz",
+      "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+    },
+    "is-plain-obj": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
+      "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="
+    },
+    "is-relative": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz",
+      "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==",
+      "dev": true,
+      "requires": {
+        "is-unc-path": "^1.0.0"
+      }
+    },
+    "is-unc-path": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz",
+      "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==",
+      "dev": true,
+      "requires": {
+        "unc-path-regex": "^0.1.2"
+      }
+    },
+    "is-unicode-supported": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
+      "dev": true
+    },
+    "is-upper-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz",
+      "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "is-windows": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
+      "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
+      "dev": true
+    },
+    "isomorphic-ws": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz",
+      "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==",
+      "dev": true,
+      "requires": {}
+    },
+    "isows": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz",
+      "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==",
+      "dev": true,
+      "requires": {}
+    },
+    "jiti": {
+      "version": "1.21.7",
+      "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+      "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="
+    },
+    "jose": {
+      "version": "5.10.0",
+      "resolved": "https://registry.npmjs.org/jose/-/jose-5.10.0.tgz",
+      "integrity": "sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==",
+      "dev": true
+    },
+    "js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+    },
+    "js-yaml": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+      "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+      "dev": true,
+      "requires": {
+        "argparse": "^2.0.1"
+      }
+    },
+    "jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "dev": true
+    },
+    "json-parse-even-better-errors": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
+      "dev": true
+    },
+    "json-to-pretty-yaml": {
+      "version": "1.2.2",
+      "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz",
+      "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==",
+      "dev": true,
+      "requires": {
+        "remedial": "^1.0.7",
+        "remove-trailing-spaces": "^1.0.6"
+      }
+    },
+    "json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "dev": true
+    },
+    "lilconfig": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+      "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="
+    },
+    "lines-and-columns": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+    },
+    "listr2": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz",
+      "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==",
+      "dev": true,
+      "requires": {
+        "cli-truncate": "^2.1.0",
+        "colorette": "^2.0.16",
+        "log-update": "^4.0.0",
+        "p-map": "^4.0.0",
+        "rfdc": "^1.3.0",
+        "rxjs": "^7.5.5",
+        "through": "^2.3.8",
+        "wrap-ansi": "^7.0.0"
+      },
+      "dependencies": {
+        "wrap-ansi": {
+          "version": "7.0.0",
+          "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+          "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "string-width": "^4.1.0",
+            "strip-ansi": "^6.0.0"
+          }
+        }
+      }
+    },
+    "lodash": {
+      "version": "4.17.23",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+      "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+      "dev": true
+    },
+    "lodash.sortby": {
+      "version": "4.7.0",
+      "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
+      "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==",
+      "dev": true
+    },
+    "log-symbols": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
+      "dev": true,
+      "requires": {
+        "chalk": "^4.1.0",
+        "is-unicode-supported": "^0.1.0"
+      }
+    },
+    "log-update": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
+      "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
+      "dev": true,
+      "requires": {
+        "ansi-escapes": "^4.3.0",
+        "cli-cursor": "^3.1.0",
+        "slice-ansi": "^4.0.0",
+        "wrap-ansi": "^6.2.0"
+      },
+      "dependencies": {
+        "slice-ansi": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
+          "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
+          "dev": true,
+          "requires": {
+            "ansi-styles": "^4.0.0",
+            "astral-regex": "^2.0.0",
+            "is-fullwidth-code-point": "^3.0.0"
+          }
+        }
+      }
+    },
+    "longest-streak": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz",
+      "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g=="
+    },
+    "loose-envify": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+      "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+      "requires": {
+        "js-tokens": "^3.0.0 || ^4.0.0"
+      }
+    },
+    "lower-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
+      "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "lower-case-first": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz",
+      "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "dev": true,
+      "requires": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "lucide-react": {
+      "version": "0.468.0",
+      "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.468.0.tgz",
+      "integrity": "sha512-6koYRhnM2N0GGZIdXzSeiNwguv1gt/FAjZOiPl76roBi3xKEXa4WmfpxgQwTTL4KipXjefrnf3oV4IsYhi4JFA==",
+      "requires": {}
+    },
+    "map-cache": {
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
+      "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==",
+      "dev": true
+    },
+    "markdown-table": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
+      "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw=="
+    },
+    "mdast-util-find-and-replace": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz",
+      "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "escape-string-regexp": "^5.0.0",
+        "unist-util-is": "^6.0.0",
+        "unist-util-visit-parents": "^6.0.0"
+      },
+      "dependencies": {
+        "escape-string-regexp": {
+          "version": "5.0.0",
+          "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+          "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="
+        }
+      }
+    },
+    "mdast-util-from-markdown": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz",
+      "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "@types/unist": "^3.0.0",
+        "decode-named-character-reference": "^1.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-to-string": "^4.0.0",
+        "micromark": "^4.0.0",
+        "micromark-util-decode-numeric-character-reference": "^2.0.0",
+        "micromark-util-decode-string": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0",
+        "unist-util-stringify-position": "^4.0.0"
+      }
+    },
+    "mdast-util-gfm": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz",
+      "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==",
+      "requires": {
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-gfm-autolink-literal": "^2.0.0",
+        "mdast-util-gfm-footnote": "^2.0.0",
+        "mdast-util-gfm-strikethrough": "^2.0.0",
+        "mdast-util-gfm-table": "^2.0.0",
+        "mdast-util-gfm-task-list-item": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      }
+    },
+    "mdast-util-gfm-autolink-literal": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz",
+      "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "ccount": "^2.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-find-and-replace": "^3.0.0",
+        "micromark-util-character": "^2.0.0"
+      }
+    },
+    "mdast-util-gfm-footnote": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz",
+      "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.1.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0"
+      }
+    },
+    "mdast-util-gfm-strikethrough": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz",
+      "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      }
+    },
+    "mdast-util-gfm-table": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz",
+      "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "markdown-table": "^3.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      }
+    },
+    "mdast-util-gfm-task-list-item": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz",
+      "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      }
+    },
+    "mdast-util-mdx-expression": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz",
+      "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==",
+      "requires": {
+        "@types/estree-jsx": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      }
+    },
+    "mdast-util-mdx-jsx": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz",
+      "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==",
+      "requires": {
+        "@types/estree-jsx": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "@types/unist": "^3.0.0",
+        "ccount": "^2.0.0",
+        "devlop": "^1.1.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0",
+        "parse-entities": "^4.0.0",
+        "stringify-entities": "^4.0.0",
+        "unist-util-stringify-position": "^4.0.0",
+        "vfile-message": "^4.0.0"
+      }
+    },
+    "mdast-util-mdxjs-esm": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz",
+      "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==",
+      "requires": {
+        "@types/estree-jsx": "^1.0.0",
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "mdast-util-to-markdown": "^2.0.0"
+      }
+    },
+    "mdast-util-phrasing": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz",
+      "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "unist-util-is": "^6.0.0"
+      }
+    },
+    "mdast-util-to-hast": {
+      "version": "13.2.1",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.1.tgz",
+      "integrity": "sha512-cctsq2wp5vTsLIcaymblUriiTcZd0CwWtCbLvrOzYCDZoWyMNV8sZ7krj09FSnsiJi3WVsHLM4k6Dq/yaPyCXA==",
+      "requires": {
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "@ungap/structured-clone": "^1.0.0",
+        "devlop": "^1.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "trim-lines": "^3.0.0",
+        "unist-util-position": "^5.0.0",
+        "unist-util-visit": "^5.0.0",
+        "vfile": "^6.0.0"
+      }
+    },
+    "mdast-util-to-markdown": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz",
+      "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "@types/unist": "^3.0.0",
+        "longest-streak": "^3.0.0",
+        "mdast-util-phrasing": "^4.0.0",
+        "mdast-util-to-string": "^4.0.0",
+        "micromark-util-classify-character": "^2.0.0",
+        "micromark-util-decode-string": "^2.0.0",
+        "unist-util-visit": "^5.0.0",
+        "zwitch": "^2.0.0"
+      }
+    },
+    "mdast-util-to-string": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz",
+      "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==",
+      "requires": {
+        "@types/mdast": "^4.0.0"
+      }
+    },
+    "merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="
+    },
+    "meros": {
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.2.tgz",
+      "integrity": "sha512-Q3mobPbvEx7XbwhnC1J1r60+5H6EZyNccdzSz0eGexJRwouUtTZxPVRGdqKtxlpD84ScK4+tIGldkqDtCKdI0A==",
+      "dev": true,
+      "requires": {}
+    },
+    "micromark": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz",
+      "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==",
+      "requires": {
+        "@types/debug": "^4.0.0",
+        "debug": "^4.0.0",
+        "decode-named-character-reference": "^1.0.0",
+        "devlop": "^1.0.0",
+        "micromark-core-commonmark": "^2.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-combine-extensions": "^2.0.0",
+        "micromark-util-decode-numeric-character-reference": "^2.0.0",
+        "micromark-util-encode": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-resolve-all": "^2.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "micromark-util-subtokenize": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-core-commonmark": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz",
+      "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==",
+      "requires": {
+        "decode-named-character-reference": "^1.0.0",
+        "devlop": "^1.0.0",
+        "micromark-factory-destination": "^2.0.0",
+        "micromark-factory-label": "^2.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-factory-title": "^2.0.0",
+        "micromark-factory-whitespace": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-classify-character": "^2.0.0",
+        "micromark-util-html-tag-name": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-resolve-all": "^2.0.0",
+        "micromark-util-subtokenize": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-extension-gfm": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz",
+      "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==",
+      "requires": {
+        "micromark-extension-gfm-autolink-literal": "^2.0.0",
+        "micromark-extension-gfm-footnote": "^2.0.0",
+        "micromark-extension-gfm-strikethrough": "^2.0.0",
+        "micromark-extension-gfm-table": "^2.0.0",
+        "micromark-extension-gfm-tagfilter": "^2.0.0",
+        "micromark-extension-gfm-task-list-item": "^2.0.0",
+        "micromark-util-combine-extensions": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-extension-gfm-autolink-literal": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz",
+      "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==",
+      "requires": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-extension-gfm-footnote": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz",
+      "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==",
+      "requires": {
+        "devlop": "^1.0.0",
+        "micromark-core-commonmark": "^2.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-normalize-identifier": "^2.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-extension-gfm-strikethrough": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz",
+      "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==",
+      "requires": {
+        "devlop": "^1.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-classify-character": "^2.0.0",
+        "micromark-util-resolve-all": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-extension-gfm-table": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz",
+      "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==",
+      "requires": {
+        "devlop": "^1.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-extension-gfm-tagfilter": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz",
+      "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==",
+      "requires": {
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-extension-gfm-task-list-item": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz",
+      "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==",
+      "requires": {
+        "devlop": "^1.0.0",
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-factory-destination": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz",
+      "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==",
+      "requires": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-factory-label": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz",
+      "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==",
+      "requires": {
+        "devlop": "^1.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-factory-space": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz",
+      "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==",
+      "requires": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-factory-title": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz",
+      "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==",
+      "requires": {
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-factory-whitespace": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz",
+      "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==",
+      "requires": {
+        "micromark-factory-space": "^2.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-util-character": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz",
+      "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==",
+      "requires": {
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-util-chunked": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz",
+      "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==",
+      "requires": {
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "micromark-util-classify-character": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz",
+      "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==",
+      "requires": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-util-combine-extensions": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz",
+      "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==",
+      "requires": {
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-util-decode-numeric-character-reference": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz",
+      "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==",
+      "requires": {
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "micromark-util-decode-string": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz",
+      "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==",
+      "requires": {
+        "decode-named-character-reference": "^1.0.0",
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-decode-numeric-character-reference": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "micromark-util-encode": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz",
+      "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="
+    },
+    "micromark-util-html-tag-name": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz",
+      "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA=="
+    },
+    "micromark-util-normalize-identifier": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz",
+      "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==",
+      "requires": {
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "micromark-util-resolve-all": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz",
+      "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==",
+      "requires": {
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-util-sanitize-uri": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz",
+      "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==",
+      "requires": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-encode": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "micromark-util-subtokenize": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz",
+      "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==",
+      "requires": {
+        "devlop": "^1.0.0",
+        "micromark-util-chunked": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "micromark-util-symbol": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz",
+      "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="
+    },
+    "micromark-util-types": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz",
+      "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="
+    },
+    "micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "requires": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      }
+    },
+    "mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true
+    },
+    "minimatch": {
+      "version": "10.2.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.4.tgz",
+      "integrity": "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^5.0.2"
+      }
+    },
+    "ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+    },
+    "mute-stream": {
+      "version": "0.0.8",
+      "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
+      "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
+      "dev": true
+    },
+    "mz": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+      "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+      "requires": {
+        "any-promise": "^1.0.0",
+        "object-assign": "^4.0.1",
+        "thenify-all": "^1.0.0"
+      }
+    },
+    "nanoid": {
+      "version": "3.3.11",
+      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+      "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="
+    },
+    "no-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
+      "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
+      "dev": true,
+      "requires": {
+        "lower-case": "^2.0.2",
+        "tslib": "^2.0.3"
+      }
+    },
+    "node-domexception": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+      "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+      "dev": true
+    },
+    "node-fetch": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+      "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+      "dev": true,
+      "requires": {
+        "whatwg-url": "^5.0.0"
+      }
+    },
+    "node-releases": {
+      "version": "2.0.36",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz",
+      "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==",
+      "dev": true
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+    },
+    "object-assign": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+      "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
+    },
+    "object-hash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+      "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="
+    },
+    "onetime": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dev": true,
+      "requires": {
+        "mimic-fn": "^2.1.0"
+      }
+    },
+    "optimism": {
+      "version": "0.18.1",
+      "resolved": "https://registry.npmjs.org/optimism/-/optimism-0.18.1.tgz",
+      "integrity": "sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==",
+      "requires": {
+        "@wry/caches": "^1.0.0",
+        "@wry/context": "^0.7.0",
+        "@wry/trie": "^0.5.0",
+        "tslib": "^2.3.0"
+      }
+    },
+    "ora": {
+      "version": "5.4.1",
+      "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+      "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
+      "dev": true,
+      "requires": {
+        "bl": "^4.1.0",
+        "chalk": "^4.1.0",
+        "cli-cursor": "^3.1.0",
+        "cli-spinners": "^2.5.0",
+        "is-interactive": "^1.0.0",
+        "is-unicode-supported": "^0.1.0",
+        "log-symbols": "^4.1.0",
+        "strip-ansi": "^6.0.0",
+        "wcwidth": "^1.0.1"
+      }
+    },
+    "p-limit": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+      "dev": true,
+      "requires": {
+        "yocto-queue": "^0.1.0"
+      }
+    },
+    "p-map": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+      "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+      "dev": true,
+      "requires": {
+        "aggregate-error": "^3.0.0"
+      }
+    },
+    "param-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+      "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
+      "dev": true,
+      "requires": {
+        "dot-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "parent-module": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+      "dev": true,
+      "requires": {
+        "callsites": "^3.0.0"
+      }
+    },
+    "parse-entities": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz",
+      "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==",
+      "requires": {
+        "@types/unist": "^2.0.0",
+        "character-entities-legacy": "^3.0.0",
+        "character-reference-invalid": "^2.0.0",
+        "decode-named-character-reference": "^1.0.0",
+        "is-alphanumerical": "^2.0.0",
+        "is-decimal": "^2.0.0",
+        "is-hexadecimal": "^2.0.0"
+      },
+      "dependencies": {
+        "@types/unist": {
+          "version": "2.0.11",
+          "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz",
+          "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="
+        }
+      }
+    },
+    "parse-filepath": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
+      "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==",
+      "dev": true,
+      "requires": {
+        "is-absolute": "^1.0.0",
+        "map-cache": "^0.2.0",
+        "path-root": "^0.1.1"
+      }
+    },
+    "parse-json": {
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+      "dev": true,
+      "requires": {
+        "@babel/code-frame": "^7.0.0",
+        "error-ex": "^1.3.1",
+        "json-parse-even-better-errors": "^2.3.0",
+        "lines-and-columns": "^1.1.6"
+      }
+    },
+    "pascal-case": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
+      "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
+      "dev": true,
+      "requires": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "path-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz",
+      "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==",
+      "dev": true,
+      "requires": {
+        "dot-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+    },
+    "path-root": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz",
+      "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==",
+      "dev": true,
+      "requires": {
+        "path-root-regex": "^0.1.0"
+      }
+    },
+    "path-root-regex": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz",
+      "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==",
+      "dev": true
+    },
+    "path-type": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+      "dev": true
+    },
+    "picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+    },
+    "picomatch": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
+    },
+    "pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="
+    },
+    "pirates": {
+      "version": "4.0.7",
+      "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+      "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="
+    },
+    "postcss": {
+      "version": "8.5.8",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
+      "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
+      "requires": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "postcss-import": {
+      "version": "15.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+      "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+      "requires": {
+        "postcss-value-parser": "^4.0.0",
+        "read-cache": "^1.0.0",
+        "resolve": "^1.1.7"
+      }
+    },
+    "postcss-js": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
+      "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
+      "requires": {
+        "camelcase-css": "^2.0.1"
+      }
+    },
+    "postcss-load-config": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
+      "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
+      "requires": {
+        "lilconfig": "^3.1.1"
+      }
+    },
+    "postcss-nested": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+      "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+      "requires": {
+        "postcss-selector-parser": "^6.1.1"
+      },
+      "dependencies": {
+        "postcss-selector-parser": {
+          "version": "6.1.2",
+          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+          "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+          "requires": {
+            "cssesc": "^3.0.0",
+            "util-deprecate": "^1.0.2"
+          }
+        }
+      }
+    },
+    "postcss-selector-parser": {
+      "version": "6.0.10",
+      "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+      "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+      "dev": true,
+      "requires": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      }
+    },
+    "postcss-value-parser": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+      "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+    },
+    "prop-types": {
+      "version": "15.8.1",
+      "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+      "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+      "requires": {
+        "loose-envify": "^1.4.0",
+        "object-assign": "^4.1.1",
+        "react-is": "^16.13.1"
+      }
+    },
+    "property-information": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz",
+      "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="
+    },
+    "queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="
+    },
+    "react": {
+      "version": "19.2.4",
+      "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz",
+      "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="
+    },
+    "react-dom": {
+      "version": "19.2.4",
+      "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz",
+      "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==",
+      "requires": {
+        "scheduler": "^0.27.0"
+      }
+    },
+    "react-is": {
+      "version": "16.13.1",
+      "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+      "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+    },
+    "react-markdown": {
+      "version": "9.1.0",
+      "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-9.1.0.tgz",
+      "integrity": "sha512-xaijuJB0kzGiUdG7nc2MOMDUDBWPyGAjZtUrow9XxUeua8IqeP+VlIfAZ3bphpcLTnSZXz6z9jcVC/TCwbfgdw==",
+      "requires": {
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "devlop": "^1.0.0",
+        "hast-util-to-jsx-runtime": "^2.0.0",
+        "html-url-attributes": "^3.0.0",
+        "mdast-util-to-hast": "^13.0.0",
+        "remark-parse": "^11.0.0",
+        "remark-rehype": "^11.0.0",
+        "unified": "^11.0.0",
+        "unist-util-visit": "^5.0.0",
+        "vfile": "^6.0.0"
+      }
+    },
+    "react-refresh": {
+      "version": "0.17.0",
+      "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz",
+      "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==",
+      "dev": true
+    },
+    "react-remove-scroll": {
+      "version": "2.7.2",
+      "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz",
+      "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==",
+      "requires": {
+        "react-remove-scroll-bar": "^2.3.7",
+        "react-style-singleton": "^2.2.3",
+        "tslib": "^2.1.0",
+        "use-callback-ref": "^1.3.3",
+        "use-sidecar": "^1.1.3"
+      }
+    },
+    "react-remove-scroll-bar": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
+      "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
+      "requires": {
+        "react-style-singleton": "^2.2.2",
+        "tslib": "^2.0.0"
+      }
+    },
+    "react-router": {
+      "version": "6.30.3",
+      "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
+      "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
+      "requires": {
+        "@remix-run/router": "1.23.2"
+      }
+    },
+    "react-router-dom": {
+      "version": "6.30.3",
+      "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
+      "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
+      "requires": {
+        "@remix-run/router": "1.23.2",
+        "react-router": "6.30.3"
+      }
+    },
+    "react-style-singleton": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
+      "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
+      "requires": {
+        "get-nonce": "^1.0.0",
+        "tslib": "^2.0.0"
+      }
+    },
+    "read-cache": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+      "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+      "requires": {
+        "pify": "^2.3.0"
+      }
+    },
+    "readable-stream": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+      "dev": true,
+      "requires": {
+        "inherits": "^2.0.3",
+        "string_decoder": "^1.1.1",
+        "util-deprecate": "^1.0.1"
+      }
+    },
+    "readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "requires": {
+        "picomatch": "^2.2.1"
+      }
+    },
+    "rehackt": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/rehackt/-/rehackt-0.1.0.tgz",
+      "integrity": "sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==",
+      "requires": {}
+    },
+    "remark-gfm": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz",
+      "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-gfm": "^3.0.0",
+        "micromark-extension-gfm": "^3.0.0",
+        "remark-parse": "^11.0.0",
+        "remark-stringify": "^11.0.0",
+        "unified": "^11.0.0"
+      }
+    },
+    "remark-parse": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz",
+      "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-from-markdown": "^2.0.0",
+        "micromark-util-types": "^2.0.0",
+        "unified": "^11.0.0"
+      }
+    },
+    "remark-rehype": {
+      "version": "11.1.2",
+      "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz",
+      "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==",
+      "requires": {
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "mdast-util-to-hast": "^13.0.0",
+        "unified": "^11.0.0",
+        "vfile": "^6.0.0"
+      }
+    },
+    "remark-stringify": {
+      "version": "11.0.0",
+      "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz",
+      "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==",
+      "requires": {
+        "@types/mdast": "^4.0.0",
+        "mdast-util-to-markdown": "^2.0.0",
+        "unified": "^11.0.0"
+      }
+    },
+    "remedial": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz",
+      "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==",
+      "dev": true
+    },
+    "remove-trailing-separator": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
+      "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==",
+      "dev": true
+    },
+    "remove-trailing-spaces": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.9.tgz",
+      "integrity": "sha512-xzG7w5IRijvIkHIjDk65URsJJ7k4J95wmcArY5PRcmjldIOl7oTvG8+X2Ag690R7SfwiOcHrWZKVc1Pp5WIOzA==",
+      "dev": true
+    },
+    "require-directory": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+      "dev": true
+    },
+    "resolve": {
+      "version": "1.22.11",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz",
+      "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==",
+      "requires": {
+        "is-core-module": "^2.16.1",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      }
+    },
+    "resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+      "dev": true
+    },
+    "restore-cursor": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
+      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
+      "dev": true,
+      "requires": {
+        "onetime": "^5.1.0",
+        "signal-exit": "^3.0.2"
+      }
+    },
+    "reusify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+      "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="
+    },
+    "rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+      "dev": true
+    },
+    "rollup": {
+      "version": "4.59.0",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz",
+      "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==",
+      "dev": true,
+      "requires": {
+        "@rollup/rollup-android-arm-eabi": "4.59.0",
+        "@rollup/rollup-android-arm64": "4.59.0",
+        "@rollup/rollup-darwin-arm64": "4.59.0",
+        "@rollup/rollup-darwin-x64": "4.59.0",
+        "@rollup/rollup-freebsd-arm64": "4.59.0",
+        "@rollup/rollup-freebsd-x64": "4.59.0",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.59.0",
+        "@rollup/rollup-linux-arm-musleabihf": "4.59.0",
+        "@rollup/rollup-linux-arm64-gnu": "4.59.0",
+        "@rollup/rollup-linux-arm64-musl": "4.59.0",
+        "@rollup/rollup-linux-loong64-gnu": "4.59.0",
+        "@rollup/rollup-linux-loong64-musl": "4.59.0",
+        "@rollup/rollup-linux-ppc64-gnu": "4.59.0",
+        "@rollup/rollup-linux-ppc64-musl": "4.59.0",
+        "@rollup/rollup-linux-riscv64-gnu": "4.59.0",
+        "@rollup/rollup-linux-riscv64-musl": "4.59.0",
+        "@rollup/rollup-linux-s390x-gnu": "4.59.0",
+        "@rollup/rollup-linux-x64-gnu": "4.59.0",
+        "@rollup/rollup-linux-x64-musl": "4.59.0",
+        "@rollup/rollup-openbsd-x64": "4.59.0",
+        "@rollup/rollup-openharmony-arm64": "4.59.0",
+        "@rollup/rollup-win32-arm64-msvc": "4.59.0",
+        "@rollup/rollup-win32-ia32-msvc": "4.59.0",
+        "@rollup/rollup-win32-x64-gnu": "4.59.0",
+        "@rollup/rollup-win32-x64-msvc": "4.59.0",
+        "@types/estree": "1.0.8",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "run-async": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
+      "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
+      "dev": true
+    },
+    "run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "requires": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "rxjs": {
+      "version": "7.8.2",
+      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz",
+      "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true
+    },
+    "safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true
+    },
+    "scheduler": {
+      "version": "0.27.0",
+      "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
+      "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="
+    },
+    "scuid": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz",
+      "integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==",
+      "dev": true
+    },
+    "semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "dev": true
+    },
+    "sentence-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz",
+      "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==",
+      "dev": true,
+      "requires": {
+        "no-case": "^3.0.4",
+        "tslib": "^2.0.3",
+        "upper-case-first": "^2.0.2"
+      }
+    },
+    "shell-quote": {
+      "version": "1.8.3",
+      "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
+      "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
+      "dev": true
+    },
+    "signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "dev": true
+    },
+    "slash": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+      "dev": true
+    },
+    "slice-ansi": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
+      "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^4.0.0",
+        "astral-regex": "^2.0.0",
+        "is-fullwidth-code-point": "^3.0.0"
+      }
+    },
+    "snake-case": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz",
+      "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==",
+      "dev": true,
+      "requires": {
+        "dot-case": "^3.0.4",
+        "tslib": "^2.0.3"
+      }
+    },
+    "source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
+    },
+    "space-separated-tokens": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz",
+      "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="
+    },
+    "sponge-case": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz",
+      "integrity": "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "string_decoder": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "dev": true,
+      "requires": {
+        "safe-buffer": "~5.2.0"
+      }
+    },
+    "string-env-interpolation": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz",
+      "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==",
+      "dev": true
+    },
+    "string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dev": true,
+      "requires": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      }
+    },
+    "stringify-entities": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz",
+      "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==",
+      "requires": {
+        "character-entities-html4": "^2.0.0",
+        "character-entities-legacy": "^3.0.0"
+      }
+    },
+    "strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dev": true,
+      "requires": {
+        "ansi-regex": "^5.0.1"
+      }
+    },
+    "style-to-js": {
+      "version": "1.1.21",
+      "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz",
+      "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==",
+      "requires": {
+        "style-to-object": "1.0.14"
+      }
+    },
+    "style-to-object": {
+      "version": "1.0.14",
+      "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz",
+      "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==",
+      "requires": {
+        "inline-style-parser": "0.2.7"
+      }
+    },
+    "sucrase": {
+      "version": "3.35.1",
+      "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
+      "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
+      "requires": {
+        "@jridgewell/gen-mapping": "^0.3.2",
+        "commander": "^4.0.0",
+        "lines-and-columns": "^1.1.6",
+        "mz": "^2.7.0",
+        "pirates": "^4.0.1",
+        "tinyglobby": "^0.2.11",
+        "ts-interface-checker": "^0.1.9"
+      }
+    },
+    "supports-color": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+      "dev": true,
+      "requires": {
+        "has-flag": "^4.0.0"
+      }
+    },
+    "supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="
+    },
+    "swap-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz",
+      "integrity": "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "symbol-observable": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz",
+      "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ=="
+    },
+    "sync-fetch": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/sync-fetch/-/sync-fetch-0.6.0.tgz",
+      "integrity": "sha512-IELLEvzHuCfc1uTsshPK58ViSdNqXxlml1U+fmwJIKLYKOr/rAtBrorE2RYm5IHaMpDNlmC0fr1LAvdXvyheEQ==",
+      "dev": true,
+      "requires": {
+        "node-fetch": "^3.3.2",
+        "timeout-signal": "^2.0.0",
+        "whatwg-mimetype": "^4.0.0"
+      },
+      "dependencies": {
+        "node-fetch": {
+          "version": "3.3.2",
+          "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+          "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+          "dev": true,
+          "requires": {
+            "data-uri-to-buffer": "^4.0.0",
+            "fetch-blob": "^3.1.4",
+            "formdata-polyfill": "^4.0.10"
+          }
+        }
+      }
+    },
+    "tailwind-merge": {
+      "version": "2.6.1",
+      "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.1.tgz",
+      "integrity": "sha512-Oo6tHdpZsGpkKG88HJ8RR1rg/RdnEkQEfMoEk2x1XRI3F1AxeU+ijRXpiVUF4UbLfcxxRGw6TbUINKYdWVsQTQ=="
+    },
+    "tailwindcss": {
+      "version": "3.4.19",
+      "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
+      "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
+      "requires": {
+        "@alloc/quick-lru": "^5.2.0",
+        "arg": "^5.0.2",
+        "chokidar": "^3.6.0",
+        "didyoumean": "^1.2.2",
+        "dlv": "^1.1.3",
+        "fast-glob": "^3.3.2",
+        "glob-parent": "^6.0.2",
+        "is-glob": "^4.0.3",
+        "jiti": "^1.21.7",
+        "lilconfig": "^3.1.3",
+        "micromatch": "^4.0.8",
+        "normalize-path": "^3.0.0",
+        "object-hash": "^3.0.0",
+        "picocolors": "^1.1.1",
+        "postcss": "^8.4.47",
+        "postcss-import": "^15.1.0",
+        "postcss-js": "^4.0.1",
+        "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
+        "postcss-nested": "^6.2.0",
+        "postcss-selector-parser": "^6.1.2",
+        "resolve": "^1.22.8",
+        "sucrase": "^3.35.0"
+      },
+      "dependencies": {
+        "glob-parent": {
+          "version": "6.0.2",
+          "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+          "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+          "requires": {
+            "is-glob": "^4.0.3"
+          }
+        },
+        "postcss-selector-parser": {
+          "version": "6.1.2",
+          "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+          "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+          "requires": {
+            "cssesc": "^3.0.0",
+            "util-deprecate": "^1.0.2"
+          }
+        }
+      }
+    },
+    "tailwindcss-animate": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
+      "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
+      "requires": {}
+    },
+    "thenify": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+      "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+      "requires": {
+        "any-promise": "^1.0.0"
+      }
+    },
+    "thenify-all": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+      "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+      "requires": {
+        "thenify": ">= 3.1.0 < 4"
+      }
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
+      "dev": true
+    },
+    "timeout-signal": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/timeout-signal/-/timeout-signal-2.0.0.tgz",
+      "integrity": "sha512-YBGpG4bWsHoPvofT6y/5iqulfXIiIErl5B0LdtHT1mGXDFTAhhRrbUpTvBgYbovr+3cKblya2WAOcpoy90XguA==",
+      "dev": true
+    },
+    "tinyglobby": {
+      "version": "0.2.15",
+      "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+      "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+      "requires": {
+        "fdir": "^6.5.0",
+        "picomatch": "^4.0.3"
+      },
+      "dependencies": {
+        "fdir": {
+          "version": "6.5.0",
+          "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+          "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+          "requires": {}
+        },
+        "picomatch": {
+          "version": "4.0.3",
+          "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+          "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="
+        }
+      }
+    },
+    "title-case": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz",
+      "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "tr46": {
+      "version": "0.0.3",
+      "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+      "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+      "dev": true
+    },
+    "trim-lines": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz",
+      "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="
+    },
+    "trough": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz",
+      "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="
+    },
+    "ts-interface-checker": {
+      "version": "0.1.13",
+      "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+      "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="
+    },
+    "ts-invariant": {
+      "version": "0.10.3",
+      "resolved": "https://registry.npmjs.org/ts-invariant/-/ts-invariant-0.10.3.tgz",
+      "integrity": "sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==",
+      "requires": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "ts-log": {
+      "version": "2.2.7",
+      "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.7.tgz",
+      "integrity": "sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg==",
+      "dev": true
+    },
+    "tslib": {
+      "version": "2.8.1",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+      "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+    },
+    "type-fest": {
+      "version": "0.21.3",
+      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+      "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+      "dev": true
+    },
+    "typescript": {
+      "version": "5.9.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "dev": true
+    },
+    "unc-path-regex": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz",
+      "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==",
+      "dev": true
+    },
+    "undici-types": {
+      "version": "7.18.2",
+      "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
+      "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
+      "dev": true
+    },
+    "unified": {
+      "version": "11.0.5",
+      "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz",
+      "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==",
+      "requires": {
+        "@types/unist": "^3.0.0",
+        "bail": "^2.0.0",
+        "devlop": "^1.0.0",
+        "extend": "^3.0.0",
+        "is-plain-obj": "^4.0.0",
+        "trough": "^2.0.0",
+        "vfile": "^6.0.0"
+      }
+    },
+    "unist-util-is": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz",
+      "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==",
+      "requires": {
+        "@types/unist": "^3.0.0"
+      }
+    },
+    "unist-util-position": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz",
+      "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==",
+      "requires": {
+        "@types/unist": "^3.0.0"
+      }
+    },
+    "unist-util-stringify-position": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz",
+      "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==",
+      "requires": {
+        "@types/unist": "^3.0.0"
+      }
+    },
+    "unist-util-visit": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.1.0.tgz",
+      "integrity": "sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==",
+      "requires": {
+        "@types/unist": "^3.0.0",
+        "unist-util-is": "^6.0.0",
+        "unist-util-visit-parents": "^6.0.0"
+      }
+    },
+    "unist-util-visit-parents": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz",
+      "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==",
+      "requires": {
+        "@types/unist": "^3.0.0",
+        "unist-util-is": "^6.0.0"
+      }
+    },
+    "unixify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz",
+      "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==",
+      "dev": true,
+      "requires": {
+        "normalize-path": "^2.1.1"
+      },
+      "dependencies": {
+        "normalize-path": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
+          "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
+          "dev": true,
+          "requires": {
+            "remove-trailing-separator": "^1.0.1"
+          }
+        }
+      }
+    },
+    "update-browserslist-db": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+      "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+      "dev": true,
+      "requires": {
+        "escalade": "^3.2.0",
+        "picocolors": "^1.1.1"
+      }
+    },
+    "upper-case": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz",
+      "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "upper-case-first": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz",
+      "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==",
+      "dev": true,
+      "requires": {
+        "tslib": "^2.0.3"
+      }
+    },
+    "urlpattern-polyfill": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz",
+      "integrity": "sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==",
+      "dev": true
+    },
+    "use-callback-ref": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
+      "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
+      "requires": {
+        "tslib": "^2.0.0"
+      }
+    },
+    "use-sidecar": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
+      "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
+      "requires": {
+        "detect-node-es": "^1.1.0",
+        "tslib": "^2.0.0"
+      }
+    },
+    "use-sync-external-store": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz",
+      "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==",
+      "requires": {}
+    },
+    "util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+    },
+    "value-or-promise": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz",
+      "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==",
+      "dev": true
+    },
+    "vfile": {
+      "version": "6.0.3",
+      "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz",
+      "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==",
+      "requires": {
+        "@types/unist": "^3.0.0",
+        "vfile-message": "^4.0.0"
+      }
+    },
+    "vfile-message": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz",
+      "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==",
+      "requires": {
+        "@types/unist": "^3.0.0",
+        "unist-util-stringify-position": "^4.0.0"
+      }
+    },
+    "vite": {
+      "version": "6.4.1",
+      "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz",
+      "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
+      "dev": true,
+      "requires": {
+        "esbuild": "^0.25.0",
+        "fdir": "^6.4.4",
+        "fsevents": "~2.3.3",
+        "picomatch": "^4.0.2",
+        "postcss": "^8.5.3",
+        "rollup": "^4.34.9",
+        "tinyglobby": "^0.2.13"
+      },
+      "dependencies": {
+        "fdir": {
+          "version": "6.5.0",
+          "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+          "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+          "dev": true,
+          "requires": {}
+        },
+        "picomatch": {
+          "version": "4.0.3",
+          "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
+          "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
+          "dev": true
+        }
+      }
+    },
+    "wcwidth": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+      "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
+      "dev": true,
+      "requires": {
+        "defaults": "^1.0.3"
+      }
+    },
+    "web-streams-polyfill": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+      "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+      "dev": true
+    },
+    "webidl-conversions": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+      "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+      "dev": true
+    },
+    "whatwg-mimetype": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+      "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+      "dev": true
+    },
+    "whatwg-url": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+      "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+      "dev": true,
+      "requires": {
+        "tr46": "~0.0.3",
+        "webidl-conversions": "^3.0.0"
+      }
+    },
+    "wrap-ansi": {
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
+      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+      "dev": true,
+      "requires": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      }
+    },
+    "ws": {
+      "version": "8.19.0",
+      "resolved": "https://registry.npmjs.org/ws/-/ws-8.19.0.tgz",
+      "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==",
+      "dev": true,
+      "requires": {}
+    },
+    "y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "dev": true
+    },
+    "yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "dev": true
+    },
+    "yaml": {
+      "version": "2.8.2",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
+      "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
+      "devOptional": true
+    },
+    "yaml-ast-parser": {
+      "version": "0.0.43",
+      "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz",
+      "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==",
+      "dev": true
+    },
+    "yargs": {
+      "version": "17.7.2",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+      "dev": true,
+      "requires": {
+        "cliui": "^8.0.1",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.1.1"
+      }
+    },
+    "yargs-parser": {
+      "version": "21.1.1",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+      "dev": true
+    },
+    "yocto-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+      "dev": true
+    },
+    "zen-observable": {
+      "version": "0.8.15",
+      "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz",
+      "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ=="
+    },
+    "zen-observable-ts": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz",
+      "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==",
+      "requires": {
+        "zen-observable": "0.8.15"
+      }
+    },
+    "zwitch": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz",
+      "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="
+    }
+  }
+}

webui2/package.json ๐Ÿ”—

@@ -0,0 +1,48 @@
+{
+  "name": "git-bug-webui",
+  "private": true,
+  "version": "0.0.0",
+  "type": "module",
+  "scripts": {
+    "dev": "vite",
+    "build": "tsc -b && vite build",
+    "preview": "vite preview",
+    "codegen": "graphql-codegen --config codegen.ts"
+  },
+  "dependencies": {
+    "@apollo/client": "^3.13.0",
+    "@radix-ui/react-avatar": "^1.1.3",
+    "@radix-ui/react-separator": "^1.1.1",
+    "@radix-ui/react-slot": "^1.1.2",
+    "@radix-ui/react-popover": "^1.1.6",
+    "@radix-ui/react-tooltip": "^1.1.8",
+    "class-variance-authority": "^0.7.1",
+    "clsx": "^2.1.1",
+    "date-fns": "^4.1.0",
+    "highlight.js": "^11.11.1",
+    "graphql": "^16.9.0",
+    "lucide-react": "^0.468.0",
+    "react": "^19.1.0",
+    "react-dom": "^19.1.0",
+    "react-markdown": "^9.0.1",
+    "react-router-dom": "^6.28.0",
+    "remark-gfm": "^4.0.0",
+    "tailwind-merge": "^2.5.5",
+    "tailwindcss-animate": "^1.0.7"
+  },
+  "devDependencies": {
+    "@graphql-codegen/cli": "^5.0.6",
+    "@graphql-codegen/typescript": "^4.1.5",
+    "@graphql-codegen/typescript-operations": "^4.5.1",
+    "@graphql-codegen/typescript-react-apollo": "^4.3.2",
+    "@tailwindcss/typography": "^0.5.15",
+    "@types/react": "^19.1.0",
+    "@types/react-dom": "^19.1.0",
+    "@vitejs/plugin-react": "^4.3.4",
+    "autoprefixer": "^10.4.20",
+    "postcss": "^8.4.49",
+    "tailwindcss": "^3.4.17",
+    "typescript": "^5.7.2",
+    "vite": "^6.0.7"
+  }
+}

webui2/src/App.tsx ๐Ÿ”—

@@ -0,0 +1,52 @@
+import { createBrowserRouter, RouterProvider } from 'react-router-dom'
+import { Shell } from '@/components/layout/Shell'
+import { RepoShell } from '@/lib/repo'
+import { RepoPickerPage } from '@/pages/RepoPickerPage'
+import { BugListPage } from '@/pages/BugListPage'
+import { BugDetailPage } from '@/pages/BugDetailPage'
+import { NewBugPage } from '@/pages/NewBugPage'
+import { CodePage } from '@/pages/CodePage'
+import { UserProfilePage } from '@/pages/UserProfilePage'
+import { CommitPage } from '@/pages/CommitPage'
+import { IdentitySelectPage } from '@/pages/IdentitySelectPage'
+
+// Route structure:
+//   /                          โ†’ repo picker
+//   /:repo                     โ†’ code browser (repo home)
+//   /:repo/issues              โ†’ issue list
+//   /_/auth/select-identity    โ†’ OAuth identity adoption (first-time login)
+//
+// The /_/auth/* prefix uses "_" as a reserved namespace so it never collides
+// with a real repo slug.
+const router = createBrowserRouter([
+  {
+    path: '/',
+    element: <Shell />,
+    children: [
+      { index: true, element: <RepoPickerPage /> },
+      // Reserved namespace for app-level pages that are not repo-scoped.
+      {
+        path: '_',
+        children: [
+          { path: 'auth/select-identity', element: <IdentitySelectPage /> },
+        ],
+      },
+      {
+        path: ':repo',
+        element: <RepoShell />,
+        children: [
+          { index: true, element: <CodePage /> },
+          { path: 'issues', element: <BugListPage /> },
+          { path: 'issues/new', element: <NewBugPage /> },
+          { path: 'issues/:id', element: <BugDetailPage /> },
+          { path: 'user/:id', element: <UserProfilePage /> },
+          { path: 'commit/:hash', element: <CommitPage /> },
+        ],
+      },
+    ],
+  },
+])
+
+export function App() {
+  return <RouterProvider router={router} />
+}

webui2/src/__generated__/graphql.ts ๐Ÿ”—

@@ -0,0 +1,1759 @@
+import { gql } from '@apollo/client';
+import * as Apollo from '@apollo/client';
+export type Maybe<T> = T | null;
+export type InputMaybe<T> = Maybe<T>;
+export type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
+export type MakeOptional<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]?: Maybe<T[SubKey]> };
+export type MakeMaybe<T, K extends keyof T> = Omit<T, K> & { [SubKey in K]: Maybe<T[SubKey]> };
+export type MakeEmpty<T extends { [key: string]: unknown }, K extends keyof T> = { [_ in K]?: never };
+export type Incremental<T> = T | { [P in keyof T]?: P extends ' $fragmentName' | '__typename' ? T[P] : never };
+const defaultOptions = {} as const;
+/** All built-in and custom scalars, mapped to their actual values */
+export type Scalars = {
+  ID: { input: string; output: string; }
+  String: { input: string; output: string; }
+  Boolean: { input: boolean; output: boolean; }
+  Int: { input: number; output: number; }
+  Float: { input: number; output: number; }
+  CombinedId: { input: string; output: string; }
+  Hash: { input: string; output: string; }
+  Time: { input: string; output: string; }
+};
+
+/** An object that has an author. */
+export type Authored = {
+  /** The author of this object. */
+  author: Identity;
+};
+
+export type Bug = Authored & {
+  __typename?: 'Bug';
+  /** The actors of the bug. Actors are Identity that have interacted with the bug. */
+  actors: IdentityConnection;
+  author: Identity;
+  comments: BugCommentConnection;
+  createdAt: Scalars['Time']['output'];
+  /** The human version (truncated) identifier for this bug */
+  humanId: Scalars['String']['output'];
+  /** The identifier for this bug */
+  id: Scalars['ID']['output'];
+  labels: Array<Label>;
+  lastEdit: Scalars['Time']['output'];
+  operations: OperationConnection;
+  /**
+   * The participants of the bug. Participants are Identity that have created or
+   * added a comment on the bug.
+   */
+  participants: IdentityConnection;
+  status: Status;
+  timeline: BugTimelineItemConnection;
+  title: Scalars['String']['output'];
+};
+
+
+export type BugActorsArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+
+export type BugCommentsArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+
+export type BugOperationsArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+
+export type BugParticipantsArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+
+export type BugTimelineArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+export type BugAddCommentAndCloseInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The collection of file's hash required for the first message. */
+  files?: InputMaybe<Array<Scalars['Hash']['input']>>;
+  /** The message to be added to the bug. */
+  message: Scalars['String']['input'];
+  /** The bug ID's prefix. */
+  prefix: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+};
+
+export type BugAddCommentAndClosePayload = {
+  __typename?: 'BugAddCommentAndClosePayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting AddComment operation. */
+  commentOperation: BugAddCommentOperation;
+  /** The resulting SetStatusOperation. */
+  statusOperation: BugSetStatusOperation;
+};
+
+export type BugAddCommentAndReopenInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The collection of file's hash required for the first message. */
+  files?: InputMaybe<Array<Scalars['Hash']['input']>>;
+  /** The message to be added to the bug. */
+  message: Scalars['String']['input'];
+  /** The bug ID's prefix. */
+  prefix: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+};
+
+export type BugAddCommentAndReopenPayload = {
+  __typename?: 'BugAddCommentAndReopenPayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting AddComment operation. */
+  commentOperation: BugAddCommentOperation;
+  /** The resulting SetStatusOperation. */
+  statusOperation: BugSetStatusOperation;
+};
+
+export type BugAddCommentInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The collection of file's hash required for the first message. */
+  files?: InputMaybe<Array<Scalars['Hash']['input']>>;
+  /** The message to be added to the bug. */
+  message: Scalars['String']['input'];
+  /** The bug ID's prefix. */
+  prefix: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+};
+
+export type BugAddCommentOperation = Authored & Operation & {
+  __typename?: 'BugAddCommentOperation';
+  /** The author of this object. */
+  author: Identity;
+  /** The datetime when this operation was issued. */
+  date: Scalars['Time']['output'];
+  files: Array<Scalars['Hash']['output']>;
+  /** The identifier of the operation */
+  id: Scalars['ID']['output'];
+  message: Scalars['String']['output'];
+};
+
+export type BugAddCommentPayload = {
+  __typename?: 'BugAddCommentPayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting operation. */
+  operation: BugAddCommentOperation;
+};
+
+/** BugAddCommentTimelineItem is a BugTimelineItem that represent a BugComment and its edition history */
+export type BugAddCommentTimelineItem = Authored & BugTimelineItem & {
+  __typename?: 'BugAddCommentTimelineItem';
+  author: Identity;
+  createdAt: Scalars['Time']['output'];
+  edited: Scalars['Boolean']['output'];
+  files: Array<Scalars['Hash']['output']>;
+  history: Array<BugCommentHistoryStep>;
+  /** The identifier of the source operation */
+  id: Scalars['CombinedId']['output'];
+  lastEdit: Scalars['Time']['output'];
+  message: Scalars['String']['output'];
+  messageIsEmpty: Scalars['Boolean']['output'];
+};
+
+export type BugChangeLabelInput = {
+  /** The list of label to remove. */
+  Removed?: InputMaybe<Array<Scalars['String']['input']>>;
+  /** The list of label to add. */
+  added?: InputMaybe<Array<Scalars['String']['input']>>;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The bug ID's prefix. */
+  prefix: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+};
+
+export type BugChangeLabelPayload = {
+  __typename?: 'BugChangeLabelPayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting operation. */
+  operation: BugLabelChangeOperation;
+  /** The effect each source label had. */
+  results: Array<Maybe<LabelChangeResult>>;
+};
+
+/** Represents a comment on a bug. */
+export type BugComment = Authored & {
+  __typename?: 'BugComment';
+  /** The author of this comment. */
+  author: Identity;
+  /** All media's hash referenced in this comment */
+  files: Array<Scalars['Hash']['output']>;
+  id: Scalars['CombinedId']['output'];
+  /** The message of this comment. */
+  message: Scalars['String']['output'];
+};
+
+export type BugCommentConnection = {
+  __typename?: 'BugCommentConnection';
+  edges: Array<BugCommentEdge>;
+  nodes: Array<BugComment>;
+  pageInfo: PageInfo;
+  totalCount: Scalars['Int']['output'];
+};
+
+export type BugCommentEdge = {
+  __typename?: 'BugCommentEdge';
+  cursor: Scalars['String']['output'];
+  node: BugComment;
+};
+
+/** CommentHistoryStep hold one version of a message in the history */
+export type BugCommentHistoryStep = {
+  __typename?: 'BugCommentHistoryStep';
+  date: Scalars['Time']['output'];
+  message: Scalars['String']['output'];
+};
+
+/** The connection type for Bug. */
+export type BugConnection = {
+  __typename?: 'BugConnection';
+  /** A list of edges. */
+  edges: Array<BugEdge>;
+  nodes: Array<Bug>;
+  /** Information to aid in pagination. */
+  pageInfo: PageInfo;
+  /** Identifies the total count of items in the connection. */
+  totalCount: Scalars['Int']['output'];
+};
+
+export type BugCreateInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The collection of file's hash required for the first message. */
+  files?: InputMaybe<Array<Scalars['Hash']['input']>>;
+  /** The first message of the new bug. */
+  message: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+  /** The title of the new bug. */
+  title: Scalars['String']['input'];
+};
+
+export type BugCreateOperation = Authored & Operation & {
+  __typename?: 'BugCreateOperation';
+  /** The author of this object. */
+  author: Identity;
+  /** The datetime when this operation was issued. */
+  date: Scalars['Time']['output'];
+  files: Array<Scalars['Hash']['output']>;
+  /** The identifier of the operation */
+  id: Scalars['ID']['output'];
+  message: Scalars['String']['output'];
+  title: Scalars['String']['output'];
+};
+
+export type BugCreatePayload = {
+  __typename?: 'BugCreatePayload';
+  /** The created bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting operation. */
+  operation: BugCreateOperation;
+};
+
+/** BugCreateTimelineItem is a BugTimelineItem that represent the creation of a bug and its message edition history */
+export type BugCreateTimelineItem = Authored & BugTimelineItem & {
+  __typename?: 'BugCreateTimelineItem';
+  author: Identity;
+  createdAt: Scalars['Time']['output'];
+  edited: Scalars['Boolean']['output'];
+  files: Array<Scalars['Hash']['output']>;
+  history: Array<BugCommentHistoryStep>;
+  /** The identifier of the source operation */
+  id: Scalars['CombinedId']['output'];
+  lastEdit: Scalars['Time']['output'];
+  message: Scalars['String']['output'];
+  messageIsEmpty: Scalars['Boolean']['output'];
+};
+
+/** An edge in a connection. */
+export type BugEdge = {
+  __typename?: 'BugEdge';
+  /** A cursor for use in pagination. */
+  cursor: Scalars['String']['output'];
+  /** The item at the end of the edge. */
+  node: Bug;
+};
+
+export type BugEditCommentInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The collection of file's hash required for the first message. */
+  files?: InputMaybe<Array<Scalars['Hash']['input']>>;
+  /** The new message to be set. */
+  message: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+  /** A prefix of the CombinedId of the comment to be changed. */
+  targetPrefix: Scalars['String']['input'];
+};
+
+export type BugEditCommentOperation = Authored & Operation & {
+  __typename?: 'BugEditCommentOperation';
+  /** The author of this object. */
+  author: Identity;
+  /** The datetime when this operation was issued. */
+  date: Scalars['Time']['output'];
+  files: Array<Scalars['Hash']['output']>;
+  /** The identifier of the operation */
+  id: Scalars['ID']['output'];
+  message: Scalars['String']['output'];
+  target: Scalars['String']['output'];
+};
+
+export type BugEditCommentPayload = {
+  __typename?: 'BugEditCommentPayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting operation. */
+  operation: BugEditCommentOperation;
+};
+
+export type BugLabelChangeOperation = Authored & Operation & {
+  __typename?: 'BugLabelChangeOperation';
+  added: Array<Label>;
+  /** The author of this object. */
+  author: Identity;
+  /** The datetime when this operation was issued. */
+  date: Scalars['Time']['output'];
+  /** The identifier of the operation */
+  id: Scalars['ID']['output'];
+  removed: Array<Label>;
+};
+
+/** BugLabelChangeTimelineItem is a BugTimelineItem that represent a change in the labels of a bug */
+export type BugLabelChangeTimelineItem = Authored & BugTimelineItem & {
+  __typename?: 'BugLabelChangeTimelineItem';
+  added: Array<Label>;
+  author: Identity;
+  date: Scalars['Time']['output'];
+  /** The identifier of the source operation */
+  id: Scalars['CombinedId']['output'];
+  removed: Array<Label>;
+};
+
+export type BugSetStatusOperation = Authored & Operation & {
+  __typename?: 'BugSetStatusOperation';
+  /** The author of this object. */
+  author: Identity;
+  /** The datetime when this operation was issued. */
+  date: Scalars['Time']['output'];
+  /** The identifier of the operation */
+  id: Scalars['ID']['output'];
+  status: Status;
+};
+
+/** BugSetStatusTimelineItem is a BugTimelineItem that represent a change in the status of a bug */
+export type BugSetStatusTimelineItem = Authored & BugTimelineItem & {
+  __typename?: 'BugSetStatusTimelineItem';
+  author: Identity;
+  date: Scalars['Time']['output'];
+  /** The identifier of the source operation */
+  id: Scalars['CombinedId']['output'];
+  status: Status;
+};
+
+export type BugSetTitleInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The bug ID's prefix. */
+  prefix: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+  /** The new title. */
+  title: Scalars['String']['input'];
+};
+
+export type BugSetTitleOperation = Authored & Operation & {
+  __typename?: 'BugSetTitleOperation';
+  /** The author of this object. */
+  author: Identity;
+  /** The datetime when this operation was issued. */
+  date: Scalars['Time']['output'];
+  /** The identifier of the operation */
+  id: Scalars['ID']['output'];
+  title: Scalars['String']['output'];
+  was: Scalars['String']['output'];
+};
+
+export type BugSetTitlePayload = {
+  __typename?: 'BugSetTitlePayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting operation */
+  operation: BugSetTitleOperation;
+};
+
+/** BugLabelChangeTimelineItem is a BugTimelineItem that represent a change in the title of a bug */
+export type BugSetTitleTimelineItem = Authored & BugTimelineItem & {
+  __typename?: 'BugSetTitleTimelineItem';
+  author: Identity;
+  date: Scalars['Time']['output'];
+  /** The identifier of the source operation */
+  id: Scalars['CombinedId']['output'];
+  title: Scalars['String']['output'];
+  was: Scalars['String']['output'];
+};
+
+export type BugStatusCloseInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The bug ID's prefix. */
+  prefix: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+};
+
+export type BugStatusClosePayload = {
+  __typename?: 'BugStatusClosePayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting operation. */
+  operation: BugSetStatusOperation;
+};
+
+export type BugStatusOpenInput = {
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: InputMaybe<Scalars['String']['input']>;
+  /** The bug ID's prefix. */
+  prefix: Scalars['String']['input'];
+  /** The name of the repository. If not set, the default repository is used. */
+  repoRef?: InputMaybe<Scalars['String']['input']>;
+};
+
+export type BugStatusOpenPayload = {
+  __typename?: 'BugStatusOpenPayload';
+  /** The affected bug. */
+  bug: Bug;
+  /** A unique identifier for the client performing the mutation. */
+  clientMutationId?: Maybe<Scalars['String']['output']>;
+  /** The resulting operation. */
+  operation: BugSetStatusOperation;
+};
+
+/** An item in the timeline of bug events */
+export type BugTimelineItem = {
+  /** The identifier of the source operation */
+  id: Scalars['CombinedId']['output'];
+};
+
+/** The connection type for TimelineItem */
+export type BugTimelineItemConnection = {
+  __typename?: 'BugTimelineItemConnection';
+  edges: Array<BugTimelineItemEdge>;
+  nodes: Array<BugTimelineItem>;
+  pageInfo: PageInfo;
+  totalCount: Scalars['Int']['output'];
+};
+
+/** Represent a TimelineItem */
+export type BugTimelineItemEdge = {
+  __typename?: 'BugTimelineItemEdge';
+  cursor: Scalars['String']['output'];
+  node: BugTimelineItem;
+};
+
+/** Defines a color by red, green and blue components. */
+export type Color = {
+  __typename?: 'Color';
+  /** Blue component of the color. */
+  B: Scalars['Int']['output'];
+  /** Green component of the color. */
+  G: Scalars['Int']['output'];
+  /** Red component of the color. */
+  R: Scalars['Int']['output'];
+};
+
+/** Represents an identity */
+export type Identity = {
+  __typename?: 'Identity';
+  /** An url to an avatar */
+  avatarUrl?: Maybe<Scalars['String']['output']>;
+  /** A non-empty string to display, representing the identity, based on the non-empty values. */
+  displayName: Scalars['String']['output'];
+  /** The email of the person, if known. */
+  email?: Maybe<Scalars['String']['output']>;
+  /** The human version (truncated) identifier for this identity */
+  humanId: Scalars['String']['output'];
+  /** The identifier for this identity */
+  id: Scalars['ID']['output'];
+  /**
+   * isProtected is true if the chain of git commits started to be signed.
+   * If that's the case, only signed commit with a valid key for this identity can be added.
+   */
+  isProtected: Scalars['Boolean']['output'];
+  /** The login of the person, if known. */
+  login?: Maybe<Scalars['String']['output']>;
+  /** The name of the person, if known. */
+  name?: Maybe<Scalars['String']['output']>;
+};
+
+export type IdentityConnection = {
+  __typename?: 'IdentityConnection';
+  edges: Array<IdentityEdge>;
+  nodes: Array<Identity>;
+  pageInfo: PageInfo;
+  totalCount: Scalars['Int']['output'];
+};
+
+export type IdentityEdge = {
+  __typename?: 'IdentityEdge';
+  cursor: Scalars['String']['output'];
+  node: Identity;
+};
+
+/** Label for a bug. */
+export type Label = {
+  __typename?: 'Label';
+  /** Color of the label. */
+  color: Color;
+  /** The name of the label. */
+  name: Scalars['String']['output'];
+};
+
+export type LabelChangeResult = {
+  __typename?: 'LabelChangeResult';
+  /** The source label. */
+  label: Label;
+  /** The effect this label had. */
+  status: LabelChangeStatus;
+};
+
+export enum LabelChangeStatus {
+  Added = 'ADDED',
+  AlreadySet = 'ALREADY_SET',
+  DoesntExist = 'DOESNT_EXIST',
+  DuplicateInOp = 'DUPLICATE_IN_OP',
+  Removed = 'REMOVED'
+}
+
+export type LabelConnection = {
+  __typename?: 'LabelConnection';
+  edges: Array<LabelEdge>;
+  nodes: Array<Label>;
+  pageInfo: PageInfo;
+  totalCount: Scalars['Int']['output'];
+};
+
+export type LabelEdge = {
+  __typename?: 'LabelEdge';
+  cursor: Scalars['String']['output'];
+  node: Label;
+};
+
+export type Mutation = {
+  __typename?: 'Mutation';
+  /** Add a new comment to a bug */
+  bugAddComment: BugAddCommentPayload;
+  /** Add a new comment to a bug and close it */
+  bugAddCommentAndClose: BugAddCommentAndClosePayload;
+  /** Add a new comment to a bug and reopen it */
+  bugAddCommentAndReopen: BugAddCommentAndReopenPayload;
+  /** Add or remove a set of label on a bug */
+  bugChangeLabels: BugChangeLabelPayload;
+  /** Create a new bug */
+  bugCreate: BugCreatePayload;
+  /** Change a comment of a bug */
+  bugEditComment: BugEditCommentPayload;
+  /** Change a bug's title */
+  bugSetTitle: BugSetTitlePayload;
+  /** Change a bug's status to closed */
+  bugStatusClose: BugStatusClosePayload;
+  /** Change a bug's status to open */
+  bugStatusOpen: BugStatusOpenPayload;
+};
+
+
+export type MutationBugAddCommentArgs = {
+  input: BugAddCommentInput;
+};
+
+
+export type MutationBugAddCommentAndCloseArgs = {
+  input: BugAddCommentAndCloseInput;
+};
+
+
+export type MutationBugAddCommentAndReopenArgs = {
+  input: BugAddCommentAndReopenInput;
+};
+
+
+export type MutationBugChangeLabelsArgs = {
+  input?: InputMaybe<BugChangeLabelInput>;
+};
+
+
+export type MutationBugCreateArgs = {
+  input: BugCreateInput;
+};
+
+
+export type MutationBugEditCommentArgs = {
+  input: BugEditCommentInput;
+};
+
+
+export type MutationBugSetTitleArgs = {
+  input: BugSetTitleInput;
+};
+
+
+export type MutationBugStatusCloseArgs = {
+  input: BugStatusCloseInput;
+};
+
+
+export type MutationBugStatusOpenArgs = {
+  input: BugStatusOpenInput;
+};
+
+/** An operation applied to an entity. */
+export type Operation = {
+  /** The operations author. */
+  author: Identity;
+  /** The datetime when this operation was issued. */
+  date: Scalars['Time']['output'];
+  /** The identifier of the operation */
+  id: Scalars['ID']['output'];
+};
+
+/** The connection type for an Operation */
+export type OperationConnection = {
+  __typename?: 'OperationConnection';
+  edges: Array<OperationEdge>;
+  nodes: Array<Operation>;
+  pageInfo: PageInfo;
+  totalCount: Scalars['Int']['output'];
+};
+
+/** Represent an Operation */
+export type OperationEdge = {
+  __typename?: 'OperationEdge';
+  cursor: Scalars['String']['output'];
+  node: Operation;
+};
+
+/** Information about pagination in a connection. */
+export type PageInfo = {
+  __typename?: 'PageInfo';
+  /** When paginating forwards, the cursor to continue. */
+  endCursor: Scalars['String']['output'];
+  /** When paginating forwards, are there more items? */
+  hasNextPage: Scalars['Boolean']['output'];
+  /** When paginating backwards, are there more items? */
+  hasPreviousPage: Scalars['Boolean']['output'];
+  /** When paginating backwards, the cursor to continue. */
+  startCursor: Scalars['String']['output'];
+};
+
+export type Query = {
+  __typename?: 'Query';
+  /** List all registered repositories. */
+  repositories: RepositoryConnection;
+  /** Access a repository by reference/name. If no ref is given, the default repository is returned if any. */
+  repository?: Maybe<Repository>;
+  /** Server configuration and authentication mode. */
+  serverConfig: ServerConfig;
+};
+
+
+export type QueryRepositoriesArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+
+export type QueryRepositoryArgs = {
+  ref?: InputMaybe<Scalars['String']['input']>;
+};
+
+export type Repository = {
+  __typename?: 'Repository';
+  /** All the bugs */
+  allBugs: BugConnection;
+  /** All the identities */
+  allIdentities: IdentityConnection;
+  bug?: Maybe<Bug>;
+  identity?: Maybe<Identity>;
+  /** The name of the repository */
+  name?: Maybe<Scalars['String']['output']>;
+  /**
+   * URL-friendly slug for this repository. Named repos use their name;
+   * the default (unnamed) repo derives the slug from the directory basename.
+   */
+  slug: Scalars['String']['output'];
+  /** The identity created or selected by the user as its own */
+  userIdentity?: Maybe<Identity>;
+  /** List of valid labels. */
+  validLabels: LabelConnection;
+};
+
+
+export type RepositoryAllBugsArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+  query?: InputMaybe<Scalars['String']['input']>;
+};
+
+
+export type RepositoryAllIdentitiesArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+
+export type RepositoryBugArgs = {
+  prefix: Scalars['String']['input'];
+};
+
+
+export type RepositoryIdentityArgs = {
+  prefix: Scalars['String']['input'];
+};
+
+
+export type RepositoryValidLabelsArgs = {
+  after?: InputMaybe<Scalars['String']['input']>;
+  before?: InputMaybe<Scalars['String']['input']>;
+  first?: InputMaybe<Scalars['Int']['input']>;
+  last?: InputMaybe<Scalars['Int']['input']>;
+};
+
+export type RepositoryConnection = {
+  __typename?: 'RepositoryConnection';
+  edges: Array<RepositoryEdge>;
+  nodes: Array<Repository>;
+  pageInfo: PageInfo;
+  totalCount: Scalars['Int']['output'];
+};
+
+export type RepositoryEdge = {
+  __typename?: 'RepositoryEdge';
+  cursor: Scalars['String']['output'];
+  node: Repository;
+};
+
+/** Server-wide configuration, independent of any repository. */
+export type ServerConfig = {
+  __typename?: 'ServerConfig';
+  /**
+   * Authentication mode: 'local' (single user from git config),
+   * 'oauth' (multi-user via external providers), or 'readonly'.
+   */
+  authMode: Scalars['String']['output'];
+  /**
+   * Names of the OAuth providers enabled on this server, e.g. ['github'].
+   * Empty when authMode is not 'oauth'.
+   */
+  oauthProviders: Array<Scalars['String']['output']>;
+};
+
+export enum Status {
+  Closed = 'CLOSED',
+  Open = 'OPEN'
+}
+
+export type AllIdentitiesQueryVariables = Exact<{
+  ref?: InputMaybe<Scalars['String']['input']>;
+}>;
+
+
+export type AllIdentitiesQuery = { __typename?: 'Query', repository?: { __typename?: 'Repository', allIdentities: { __typename?: 'IdentityConnection', nodes: Array<{ __typename?: 'Identity', id: string, humanId: string, name?: string | null, email?: string | null, login?: string | null, displayName: string, avatarUrl?: string | null }> } } | null };
+
+export type BugDetailQueryVariables = Exact<{
+  ref?: InputMaybe<Scalars['String']['input']>;
+  prefix: Scalars['String']['input'];
+}>;
+
+

webui2/src/components/bugs/BugRow.tsx ๐Ÿ”—

@@ -0,0 +1,78 @@
+import { Link } from 'react-router-dom'
+import { MessageSquare, CircleDot, CircleCheck } from 'lucide-react'
+import { formatDistanceToNow } from 'date-fns'
+import { LabelBadge } from './LabelBadge'
+import { Status } from '@/__generated__/graphql'
+
+interface BugRowProps {
+  id: string
+  humanId: string
+  status: Status
+  title: string
+  labels: Array<{ name: string; color: { R: number; G: number; B: number } }>
+  author: { humanId: string; displayName: string; avatarUrl?: string | null }
+  createdAt: string
+  commentCount: number
+  /** Current repo slug, used to build /:repo/issues/:id and /:repo/user/:id links. */
+  repo: string | null
+  onLabelClick?: (name: string) => void
+}
+
+// Single row in the issue list. Shows status icon, title, labels, author and
+// comment count. Labels are clickable to filter the list by that label.
+export function BugRow({
+  humanId,
+  status,
+  title,
+  labels,
+  author,
+  createdAt,
+  commentCount,
+  repo,
+  onLabelClick,
+}: BugRowProps) {
+  const isOpen = status === Status.Open
+  const StatusIcon = isOpen ? CircleDot : CircleCheck
+
+  const issueHref = repo ? `/${repo}/issues/${humanId}` : `/issues/${humanId}`
+  const authorHref = repo ? `/${repo}/user/${author.humanId}` : `/user/${author.humanId}`
+
+  return (
+    <div className="flex items-start gap-3 border-b border-border px-4 py-3 last:border-0 hover:bg-muted/30">
+      <StatusIcon
+        className={
+          isOpen
+            ? 'mt-0.5 size-4 shrink-0 text-green-600 dark:text-green-400'
+            : 'mt-0.5 size-4 shrink-0 text-purple-600 dark:text-purple-400'
+        }
+      />
+
+      <div className="min-w-0 flex-1">
+        <div className="flex flex-wrap items-baseline gap-2">
+          <Link
+            to={issueHref}
+            className="font-medium text-foreground hover:text-primary hover:underline"
+          >
+            {title}
+          </Link>
+          {labels.map((label) => (
+            <LabelBadge key={label.name} name={label.name} color={label.color} onClick={onLabelClick} />
+          ))}
+        </div>
+        <p className="mt-0.5 text-xs text-muted-foreground">
+          #{humanId} opened {formatDistanceToNow(new Date(createdAt), { addSuffix: true })} by{' '}
+          <Link to={authorHref} className="hover:underline">
+            {author.displayName}
+          </Link>
+        </p>
+      </div>
+
+      {commentCount > 0 && (
+        <div className="flex shrink-0 items-center gap-1 text-xs text-muted-foreground">
+          <MessageSquare className="size-3.5" />
+          {commentCount}
+        </div>
+      )}
+    </div>
+  )
+}

webui2/src/components/bugs/CommentBox.tsx ๐Ÿ”—

@@ -0,0 +1,139 @@
+import { useState } from 'react'
+import { Button } from '@/components/ui/button'
+import { Textarea } from '@/components/ui/textarea'
+import { Markdown } from '@/components/content/Markdown'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { useAuth } from '@/lib/auth'
+import { Status } from '@/__generated__/graphql'
+import {
+  useBugAddCommentMutation,
+  useBugAddCommentAndCloseMutation,
+  useBugAddCommentAndReopenMutation,
+  useBugStatusCloseMutation,
+  useBugStatusOpenMutation,
+  BugDetailDocument,
+} from '@/__generated__/graphql'
+
+interface CommentBoxProps {
+  bugPrefix: string
+  bugStatus: Status
+  /** Current repo slug, passed as `ref` in refetch query variables. */
+  ref_?: string | null
+}
+
+// Write/preview comment form at the bottom of BugDetailPage. Also contains the
+// Close / Reopen button. Hidden entirely in read-only mode (no logged-in user).
+export function CommentBox({ bugPrefix, bugStatus, ref_ }: CommentBoxProps) {
+  const { user } = useAuth()
+  const [message, setMessage] = useState('')
+  const [preview, setPreview] = useState(false)
+
+  const refetchVars = { variables: { ref: ref_, prefix: bugPrefix } }
+  const refetch = { refetchQueries: [{ query: BugDetailDocument, ...refetchVars }] }
+
+  const [addComment, { loading: addingComment }] = useBugAddCommentMutation(refetch)
+  const [addAndClose, { loading: addingAndClosing }] = useBugAddCommentAndCloseMutation(refetch)
+  const [addAndReopen, { loading: addingAndReopening }] = useBugAddCommentAndReopenMutation(refetch)
+  const [statusClose, { loading: closing }] = useBugStatusCloseMutation(refetch)
+  const [statusOpen, { loading: reopening }] = useBugStatusOpenMutation(refetch)
+
+  const isOpen = bugStatus === Status.Open
+  const busy = addingComment || addingAndClosing || addingAndReopening || closing || reopening
+  const hasMessage = message.trim().length > 0
+
+  async function handleComment() {
+    await addComment({ variables: { input: { prefix: bugPrefix, message: message.trim() } } })
+    setMessage('')
+    setPreview(false)
+  }
+
+  async function handleToggleStatus() {
+    if (isOpen) {
+      if (hasMessage) {
+        await addAndClose({ variables: { input: { prefix: bugPrefix, message: message.trim() } } })
+      } else {
+        await statusClose({ variables: { input: { prefix: bugPrefix } } })
+      }
+    } else {
+      if (hasMessage) {
+        await addAndReopen({ variables: { input: { prefix: bugPrefix, message: message.trim() } } })
+      } else {
+        await statusOpen({ variables: { input: { prefix: bugPrefix } } })
+      }
+    }
+    setMessage('')
+    setPreview(false)
+  }
+
+  if (!user) return null
+
+  return (
+    <div className="flex gap-3">
+      <Avatar className="mt-1 size-8 shrink-0">
+        <AvatarImage src={user.avatarUrl ?? undefined} alt={user.displayName} />
+        <AvatarFallback className="text-xs">
+          {user.displayName.slice(0, 2).toUpperCase()}
+        </AvatarFallback>
+      </Avatar>
+
+      <div className="min-w-0 flex-1 rounded-md border border-border">
+        {/* Write / Preview tabs */}
+        <div className="flex border-b border-border">
+          <button
+            onClick={() => setPreview(false)}
+            className={`px-4 py-2 text-sm font-medium transition-colors ${
+              !preview
+                ? 'border-b-2 border-primary text-foreground'
+                : 'text-muted-foreground hover:text-foreground'
+            }`}
+          >
+            Write
+          </button>
+          <button
+            onClick={() => setPreview(true)}
+            disabled={!hasMessage}
+            className={`px-4 py-2 text-sm font-medium transition-colors disabled:opacity-40 ${
+              preview
+                ? 'border-b-2 border-primary text-foreground'
+                : 'text-muted-foreground hover:text-foreground'
+            }`}
+          >
+            Preview
+          </button>
+        </div>
+
+        {preview ? (
+          <div className="min-h-[120px] px-4 py-3">
+            <Markdown content={message} />
+          </div>
+        ) : (
+          <Textarea
+            placeholder="Leave a commentโ€ฆ"
+            className="min-h-[120px] rounded-none border-0 shadow-none focus-visible:ring-0"
+            value={message}
+            onChange={(e) => setMessage(e.target.value)}
+            disabled={busy}
+          />
+        )}
+
+        <div className="flex items-center justify-end gap-2 border-t border-border px-3 py-2">
+          <Button
+            variant="outline"
+            size="sm"
+            onClick={handleToggleStatus}
+            disabled={busy}
+          >
+            {isOpen ? 'Close issue' : 'Reopen issue'}
+          </Button>
+          <Button
+            size="sm"
+            onClick={handleComment}
+            disabled={!hasMessage || busy}
+          >
+            Comment
+          </Button>
+        </div>
+      </div>
+    </div>
+  )
+}

webui2/src/components/bugs/IssueFilters.tsx ๐Ÿ”—

@@ -0,0 +1,303 @@
+import { useState } from 'react'
+import { ChevronDown, Tag, User, X, Search, Check } from 'lucide-react'
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
+import { LabelBadge } from './LabelBadge'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { useValidLabelsQuery, useAllIdentitiesQuery } from '@/__generated__/graphql'
+import { useAuth } from '@/lib/auth'
+import { cn } from '@/lib/utils'
+import { useRepo } from '@/lib/repo'
+
+// Max authors shown in the non-searching state. We intentionally cap this to
+// avoid a giant list โ€” the current-user + recently-seen pattern covers the
+// common case; typing to search handles the rest.
+const INITIAL_AUTHOR_LIMIT = 8
+
+// Returns the value passed to author:... in the query string.
+// Preference order: login (never has spaces, safest) > name > humanId.
+// We avoid humanId-as-query where possible because it's opaque to the user;
+// the backend Match() also accepts login/name substring matches.
+//
+// Uses || (not ??) so that empty-string login/name fall through to the next
+// option. git-bug identities can have login="" (empty, not null) when the
+// login field was never set; ?? would return "" and the filter would silently
+// produce author:"" which buildQueryString then drops, making the filter a no-op.
+function authorQueryValue(i: { login?: string | null; name?: string | null; humanId: string }): string {
+  return i.login || i.name || i.humanId
+}
+
+interface IssueFiltersProps {
+  selectedLabels: string[]
+  onLabelsChange: (labels: string[]) => void
+  selectedAuthorId: string | null
+  onAuthorChange: (humanId: string | null, queryValue: string | null) => void
+  /** humanIds of authors appearing in the current bug list, used to rank the initial suggestions */
+  recentAuthorIds?: string[]
+}
+
+// Label and author filter dropdowns shown in the issue list header bar.
+//
+// The author dropdown has two display modes:
+//   - Not searching: shows current user first, then recently-seen authors from
+//     the visible bug list (recentAuthorIds), then alphabetical fill up to
+//     INITIAL_AUTHOR_LIMIT. This surfaces the most useful choices with no typing.
+//   - Searching: filters the full identity list reactively as-you-type.
+//
+// Note: onAuthorChange passes TWO values โ€” humanId (for UI matching, unique) and
+// queryValue (login/name for the query string). They're kept separate because
+// two identities can share the same display name, but humanId is always unique.
+export function IssueFilters({
+  selectedLabels,
+  onLabelsChange,
+  selectedAuthorId,
+  onAuthorChange,
+  recentAuthorIds = [],
+}: IssueFiltersProps) {
+  const { user } = useAuth()
+  const repo = useRepo()
+  const { data: labelsData } = useValidLabelsQuery({ variables: { ref: repo } })
+  const { data: authorsData } = useAllIdentitiesQuery({ variables: { ref: repo } })
+  const [labelSearch, setLabelSearch] = useState('')
+  const [authorSearch, setAuthorSearch] = useState('')
+
+  const validLabels = [...(labelsData?.repository?.validLabels.nodes ?? [])].sort((a, b) =>
+    a.name.localeCompare(b.name),
+  )
+
+  const allIdentities = [...(authorsData?.repository?.allIdentities.nodes ?? [])].sort((a, b) =>
+    a.displayName.localeCompare(b.displayName),
+  )
+
+  const filteredLabels = labelSearch.trim()
+    ? validLabels.filter((l) => l.name.toLowerCase().includes(labelSearch.toLowerCase()))
+    : validLabels
+
+  // Selected labels float to top, then alphabetical
+  const sortedLabels = [
+    ...filteredLabels.filter((l) => selectedLabels.includes(l.name)),
+    ...filteredLabels.filter((l) => !selectedLabels.includes(l.name)),
+  ]
+
+  // Build the displayed identity list:
+  // - When searching: filter full list reactively as-you-type
+  // - When not searching: show current user first, then recently-seen authors,
+  //   then others up to INITIAL_AUTHOR_LIMIT
+  const isSearching = authorSearch.trim() !== ''
+
+  const matchesSearch = (i: (typeof allIdentities)[number]) => {
+    const q = authorSearch.toLowerCase()
+    return (
+      i.displayName.toLowerCase().includes(q) ||
+      (i.name ?? '').toLowerCase().includes(q) ||
+      (i.login ?? '').toLowerCase().includes(q) ||
+      (i.email ?? '').toLowerCase().includes(q)
+    )
+  }
+
+  let visibleIdentities: typeof allIdentities
+  if (isSearching) {
+    visibleIdentities = allIdentities.filter(matchesSearch)
+  } else {
+    const pinned = new Set<string>()
+    const result: typeof allIdentities = []
+
+    // 1. Current user
+    if (user) {
+      const me = allIdentities.find((i) => i.id === user.id)
+      if (me) { result.push(me); pinned.add(me.id) }
+    }
+    // 2. Selected author (if not already added)
+    if (selectedAuthorId) {
+      const sel = allIdentities.find((i) => i.humanId === selectedAuthorId)
+      if (sel && !pinned.has(sel.id)) { result.push(sel); pinned.add(sel.id) }
+    }
+    // 3. Recently seen authors (recentAuthorIds are humanIds from bug rows)
+    for (const humanId of recentAuthorIds) {
+      const match = allIdentities.find((i) => i.humanId === humanId)
+      if (match && !pinned.has(match.id)) { result.push(match); pinned.add(match.id) }
+    }
+    // 4. Fill up to limit with remaining alphabetical
+    for (const i of allIdentities) {
+      if (result.length >= INITIAL_AUTHOR_LIMIT) break
+      if (!pinned.has(i.id)) result.push(i)
+    }
+    visibleIdentities = result
+  }
+
+  function toggleLabel(name: string) {
+    if (selectedLabels.includes(name)) {
+      onLabelsChange(selectedLabels.filter((l) => l !== name))
+    } else {
+      onLabelsChange([...selectedLabels, name])
+    }
+  }
+
+  const selectedAuthorIdentity = allIdentities.find((i) => i.humanId === selectedAuthorId)
+
+  return (
+    <div className="flex items-center gap-1">
+      {/* Label filter */}
+      <Popover onOpenChange={(open) => { if (!open) setLabelSearch('') }}>
+        <PopoverTrigger asChild>
+          <button
+            className={cn(
+              'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+              selectedLabels.length > 0
+                ? 'bg-accent text-accent-foreground'
+                : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
+            )}
+          >
+            <Tag className="size-3.5" />
+            Labels
+            {selectedLabels.length > 0 && (
+              <span className="rounded-full bg-muted px-1.5 py-0.5 text-xs leading-none">
+                {selectedLabels.length}
+              </span>
+            )}
+            <ChevronDown className="size-3" />
+          </button>
+        </PopoverTrigger>
+        <PopoverContent align="end" className="w-56 p-0 bg-popover shadow-lg">
+          {/* Search */}
+          <div className="flex items-center gap-2 border-b border-border px-3 py-2">
+            <Search className="size-3.5 shrink-0 text-muted-foreground" />
+            <input
+              autoFocus
+              placeholder="Search labelsโ€ฆ"
+              value={labelSearch}
+              onChange={(e) => setLabelSearch(e.target.value)}
+              className="w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground"
+            />
+          </div>
+          <div className="max-h-64 overflow-y-auto p-1">
+            {sortedLabels.length === 0 && (
+              <p className="px-2 py-3 text-center text-xs text-muted-foreground">No labels found</p>
+            )}
+            {sortedLabels.map((label) => {
+              const active = selectedLabels.includes(label.name)
+              return (
+                <button
+                  key={label.name}
+                  onClick={() => toggleLabel(label.name)}
+                  className="flex w-full items-center gap-2 rounded px-2 py-1.5 text-sm hover:bg-muted"
+                >
+                  <span
+                    className="size-2 shrink-0 rounded-full"
+                    style={{
+                      backgroundColor: `rgb(${label.color.R},${label.color.G},${label.color.B})`,
+                      opacity: active ? 1 : 0.35,
+                    }}
+                  />
+                  <LabelBadge name={label.name} color={label.color} />
+                  {active && <Check className="ml-auto size-3.5 shrink-0 text-foreground" />}
+                </button>
+              )
+            })}
+          </div>
+          {selectedLabels.length > 0 && (
+            <div className="border-t border-border p-1">
+              <button
+                onClick={() => onLabelsChange([])}
+                className="flex w-full items-center gap-1.5 rounded px-2 py-1.5 text-xs text-muted-foreground hover:bg-muted"
+              >
+                <X className="size-3" />
+                Clear labels
+              </button>
+            </div>
+          )}
+        </PopoverContent>
+      </Popover>
+
+      {/* Author filter */}
+      <Popover onOpenChange={(open) => { if (!open) setAuthorSearch('') }}>
+        <PopoverTrigger asChild>
+          <button
+            className={cn(
+              'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+              selectedAuthorId ? 'bg-accent text-accent-foreground' : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
+            )}
+          >
+            {selectedAuthorIdentity ? (
+              <>
+                <Avatar className="size-4">
+                  <AvatarImage
+                    src={selectedAuthorIdentity.avatarUrl ?? undefined}
+                    alt={selectedAuthorIdentity.displayName}
+                  />
+                  <AvatarFallback className="text-[8px]">
+                    {selectedAuthorIdentity.displayName.slice(0, 2).toUpperCase()}
+                  </AvatarFallback>
+                </Avatar>
+                {selectedAuthorIdentity.displayName}
+              </>
+            ) : (
+              <>
+                <User className="size-3.5" />
+                Author
+              </>
+            )}
+            <ChevronDown className="size-3" />
+          </button>
+        </PopoverTrigger>
+        <PopoverContent align="end" className="w-56 p-0 bg-popover shadow-lg">
+          {/* Search */}
+          <div className="flex items-center gap-2 border-b border-border px-3 py-2">
+            <Search className="size-3.5 shrink-0 text-muted-foreground" />
+            <input
+              autoFocus
+              placeholder="Search authorsโ€ฆ"
+              value={authorSearch}
+              onChange={(e) => setAuthorSearch(e.target.value)}
+              className="w-full bg-transparent text-sm outline-none placeholder:text-muted-foreground"
+            />
+          </div>
+          <div className="max-h-64 overflow-y-auto p-1">
+            {visibleIdentities.length === 0 && (
+              <p className="px-2 py-3 text-center text-xs text-muted-foreground">No authors found</p>
+            )}
+            {visibleIdentities.map((identity) => {
+              const active = selectedAuthorId === identity.humanId
+              return (
+                <button
+                  key={identity.id}
+                  onClick={() => onAuthorChange(active ? null : identity.humanId, active ? null : authorQueryValue(identity))}
+                  className="flex w-full items-center gap-2 rounded px-2 py-1.5 text-sm hover:bg-muted"
+                >
+                  <Avatar className="size-5 shrink-0">
+                    <AvatarImage src={identity.avatarUrl ?? undefined} alt={identity.displayName} />
+                    <AvatarFallback className="text-[8px]">
+                      {identity.displayName.slice(0, 2).toUpperCase()}
+                    </AvatarFallback>
+                  </Avatar>
+                  <div className="min-w-0 flex-1 text-left">
+                    <div className="truncate">{identity.displayName}</div>
+                    {identity.login && identity.login !== identity.displayName && (
+                      <div className="truncate text-xs text-muted-foreground">@{identity.login}</div>
+                    )}
+                  </div>
+                  {active && <Check className="size-3.5 shrink-0 text-foreground" />}
+                </button>
+              )
+            })}
+            {!isSearching && allIdentities.length > INITIAL_AUTHOR_LIMIT && (
+              <p className="px-2 py-1.5 text-center text-xs text-muted-foreground">
+                {allIdentities.length - visibleIdentities.length} more โ€” type to search
+              </p>
+            )}
+          </div>
+          {selectedAuthorId && (
+            <div className="border-t border-border p-1">
+              <button
+                onClick={() => onAuthorChange(null, null)}
+                className="flex w-full items-center gap-1.5 rounded px-2 py-1.5 text-xs text-muted-foreground hover:bg-muted"
+              >
+                <X className="size-3" />
+                Clear author
+              </button>
+            </div>
+          )}
+        </PopoverContent>
+      </Popover>
+    </div>
+  )
+}

webui2/src/components/bugs/LabelBadge.tsx ๐Ÿ”—

@@ -0,0 +1,40 @@
+interface LabelBadgeProps {
+  name: string
+  color: { R: number; G: number; B: number }
+  onClick?: (name: string) => void
+}
+
+function contrastColor(r: number, g: number, b: number): string {
+  // Perceived luminance โ€” pick black or white text for readability
+  const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
+  return luminance > 0.55 ? 'rgba(0,0,0,0.75)' : 'rgba(255,255,255,0.9)'
+}
+
+// Coloured label pill. Renders as a <button> when onClick is provided,
+// used in BugRow and UserProfilePage to filter issues by label.
+export function LabelBadge({ name, color, onClick }: LabelBadgeProps) {
+  const bg = `rgb(${color.R},${color.G},${color.B})`
+  const text = contrastColor(color.R, color.G, color.B)
+
+  if (onClick) {
+    return (
+      <button
+        type="button"
+        className="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium hover:opacity-80"
+        style={{ backgroundColor: bg, color: text }}
+        onClick={(e) => { e.preventDefault(); e.stopPropagation(); onClick(name) }}
+      >
+        {name}
+      </button>
+    )
+  }
+
+  return (
+    <span
+      className="inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium"
+      style={{ backgroundColor: bg, color: text }}
+    >
+      {name}
+    </span>
+  )
+}

webui2/src/components/bugs/LabelEditor.tsx ๐Ÿ”—

@@ -0,0 +1,97 @@
+import { Settings2 } from 'lucide-react'
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
+import { LabelBadge } from './LabelBadge'
+import { useAuth } from '@/lib/auth'
+import {
+  useValidLabelsQuery,
+  useBugChangeLabelsMutation,
+  BugDetailDocument,
+} from '@/__generated__/graphql'
+
+interface LabelEditorProps {
+  bugPrefix: string
+  currentLabels: Array<{ name: string; color: { R: number; G: number; B: number } }>
+  /** Current repo slug, passed as `ref` in refetch query variables. */
+  ref_?: string | null
+}
+
+// Gear-icon popover in the BugDetailPage sidebar for adding/removing labels.
+// Loads all valid labels from the repo and toggles them via bugChangeLabels.
+// Hidden in read-only mode.
+export function LabelEditor({ bugPrefix, currentLabels, ref_ }: LabelEditorProps) {
+  const { user } = useAuth()
+  const { data } = useValidLabelsQuery({ skip: !user, variables: { ref: ref_ } })
+  const [changeLabels] = useBugChangeLabelsMutation({
+    refetchQueries: [{ query: BugDetailDocument, variables: { ref: ref_, prefix: bugPrefix } }],
+  })
+
+  const validLabels = data?.repository?.validLabels.nodes ?? []
+  const currentNames = new Set(currentLabels.map((l) => l.name))
+
+  async function toggleLabel(name: string) {
+    const isSet = currentNames.has(name)
+    await changeLabels({
+      variables: {
+        input: {
+          prefix: bugPrefix,
+          added: isSet ? [] : [name],
+          Removed: isSet ? [name] : [],
+        },
+      },
+    })
+  }
+
+  return (
+    <div>
+      <div className="mb-2 flex items-center justify-between">
+        <h3 className="text-xs font-semibold uppercase tracking-wider text-muted-foreground">
+          Labels
+        </h3>
+        {user && validLabels.length > 0 && (
+          <Popover>
+            <PopoverTrigger asChild>
+              <button className="text-muted-foreground hover:text-foreground">
+                <Settings2 className="size-3.5" />
+              </button>
+            </PopoverTrigger>
+            <PopoverContent align="end" className="w-56 p-2">
+              <p className="mb-2 px-2 text-xs font-medium text-muted-foreground">
+                Apply labels
+              </p>
+              <div className="space-y-1">
+                {validLabels.map((label) => {
+                  const active = currentNames.has(label.name)
+                  return (
+                    <button
+                      key={label.name}
+                      onClick={() => toggleLabel(label.name)}
+                      className="flex w-full items-center gap-2 rounded px-2 py-1.5 text-sm hover:bg-muted"
+                    >
+                      <span
+                        className={`size-2 rounded-full border-2 transition-colors ${
+                          active ? 'border-transparent' : 'border-muted-foreground/40 bg-transparent'
+                        }`}
+                        style={active ? { backgroundColor: `rgb(${label.color.R},${label.color.G},${label.color.B})` } : {}}
+                      />
+                      <LabelBadge name={label.name} color={label.color} />
+                    </button>
+                  )
+                })}
+              </div>
+            </PopoverContent>
+          </Popover>
+        )}
+      </div>
+
+      {currentLabels.length === 0 ? (
+        <p className="text-sm text-muted-foreground">None yet</p>
+      ) : (
+        <div className="flex flex-wrap gap-1">
+          {currentLabels.map((label) => (
+            <LabelBadge key={label.name} name={label.name} color={label.color} />
+          ))}
+        </div>
+      )}
+    </div>
+  )
+}

webui2/src/components/bugs/QueryInput.tsx ๐Ÿ”—

@@ -0,0 +1,341 @@
+// Syntax-highlighted search input with label/author autocomplete.
+//
+// Architecture: two layers share the same font/padding so they appear identical:
+//   1. A "backdrop" div (aria-hidden) renders colored <span>s for each token.
+//   2. The real <input> floats on top with transparent text and bg, so the caret
+//      is visible but the text itself is hidden in favour of the backdrop.
+//
+// Autocomplete: when the cursor is inside a `label:` or `author:` token, a
+// dropdown appears with filtered suggestions fetched from GraphQL. Clicking or
+// keyboard-selecting a suggestion replaces the current token in the input.
+
+import { useState, useRef, useMemo, type ChangeEvent } from 'react'
+import { Search } from 'lucide-react'
+import { cn } from '@/lib/utils'
+import { useValidLabelsQuery, useAllIdentitiesQuery } from '@/__generated__/graphql'
+import { useRepo } from '@/lib/repo'
+
+// โ”€โ”€ Segment parsing (for the syntax-highlight backdrop) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type SegmentType = 'status-open' | 'status-closed' | 'label' | 'author' | 'text' | 'space'
+
+interface Segment {
+  text: string
+  type: SegmentType
+}
+
+// Parse the query string into typed segments, preserving all whitespace.
+// Walks char-by-char so that quoted values (e.g. label:"my label") are kept as
+// a single token and spaces inside quotes don't split the segment.
+function parseSegments(input: string): Segment[] {
+  const segments: Segment[] = []
+  let i = 0
+
+  while (i < input.length) {
+    // Whitespace runs โ€” preserved as a separate 'space' segment so the backdrop
+    // can use whitespace-pre and match the input exactly.
+    if (input[i] === ' ') {
+      let j = i
+      while (j < input.length && input[j] === ' ') j++
+      segments.push({ text: input.slice(i, j), type: 'space' })
+      i = j
+      continue
+    }
+
+    // Token โ€” consume until an unquoted space
+    let j = i
+    let inQuote = false
+    while (j < input.length) {
+      if (input[j] === '"') { inQuote = !inQuote; j++; continue }
+      if (!inQuote && input[j] === ' ') break
+      j++
+    }
+
+    const token = input.slice(i, j)
+    let type: SegmentType = 'text'
+    if (token === 'status:open') type = 'status-open'
+    else if (token === 'status:closed') type = 'status-closed'
+    else if (token.startsWith('label:')) type = 'label'
+    else if (token.startsWith('author:')) type = 'author'
+
+    segments.push({ text: token, type })
+    i = j
+  }
+
+  return segments
+}
+
+// Only the key portion (e.g. "label:") is colored; the value stays in foreground.
+function renderSegment(seg: Segment, i: number): React.ReactNode {
+  if (seg.type === 'space' || seg.type === 'text') {
+    return <span key={i}>{seg.text}</span>
+  }
+  const colon = seg.text.indexOf(':')
+  const key = seg.text.slice(0, colon + 1)
+  const val = seg.text.slice(colon + 1)
+
+  const keyClass =
+    seg.type === 'status-open'   ? 'text-green-600 dark:text-green-400' :
+    seg.type === 'status-closed' ? 'text-purple-600 dark:text-purple-400' :
+    seg.type === 'label'         ? 'text-yellow-600 dark:text-yellow-500' :
+    /* author */                   'text-blue-600 dark:text-blue-400'
+
+  return (
+    <span key={i}>
+      <span className={keyClass}>{key}</span>
+      <span>{val}</span>
+    </span>
+  )
+}
+
+// โ”€โ”€ Autocomplete logic โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+interface CompletionInfo {
+  type: 'label' | 'author'
+  /** Text typed after the prefix (e.g. "bu" for "label:bu"). Quotes stripped. */
+  query: string
+  /** Byte position in `value` where the current token starts. */
+  tokenStart: number
+}
+
+// Inspects the text to the left of `cursor` to determine if the user is in the
+// middle of a `label:` or `author:` token and what they've typed so far.
+// Returns null when not in an autocomplete-eligible position.
+function getCompletionInfo(value: string, cursor: number): CompletionInfo | null {
+  // Walk backward to find the start of the current token
+  let tokenStart = 0
+  for (let i = cursor - 1; i >= 0; i--) {
+    if (value[i] === ' ') { tokenStart = i + 1; break }
+  }
+
+  const partial = value.slice(tokenStart, cursor)
+  if (partial.startsWith('label:')) {
+    return { type: 'label', query: partial.slice(6), tokenStart }
+  }
+  if (partial.startsWith('author:')) {
+    // Strip a leading quote that the user may have typed
+    return { type: 'author', query: partial.slice(7).replace(/^"/, ''), tokenStart }
+  }
+  return null
+}
+
+// Find where the current token ends (next unquoted space, or end of string).
+// Used when replacing a token on suggestion selection so we don't leave stale text.
+function getTokenEnd(value: string, tokenStart: number): number {
+  let inQuote = false
+  for (let i = tokenStart; i < value.length; i++) {
+    if (value[i] === '"') { inQuote = !inQuote; continue }
+    if (!inQuote && value[i] === ' ') return i
+  }
+  return value.length
+}
+
+// โ”€โ”€ Component โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+interface QueryInputProps {
+  value: string
+  onChange: (value: string) => void
+  onSubmit: () => void
+  placeholder?: string
+  className?: string
+}
+
+export function QueryInput({ value, onChange, onSubmit, placeholder, className }: QueryInputProps) {
+  const inputRef = useRef<HTMLInputElement>(null)
+  const repo = useRepo()
+
+  // Autocomplete state: null when the dropdown is hidden.
+  const [completion, setCompletion] = useState<CompletionInfo | null>(null)
+  // Keyboard-highlighted index within the visible suggestions list.
+  const [acIndex, setAcIndex] = useState(0)
+
+  // Fetch all labels and identities for autocomplete suggestions.
+  // These queries are cheap (cached by Apollo) and already used by IssueFilters,
+  // so there is no extra network cost.
+  const { data: labelsData } = useValidLabelsQuery({ variables: { ref: repo } })
+  const { data: authorsData } = useAllIdentitiesQuery({ variables: { ref: repo } })
+
+  const allLabels = labelsData?.repository?.validLabels.nodes ?? []
+  const allAuthors = authorsData?.repository?.allIdentities.nodes ?? []
+
+  // Compute the filtered suggestion list whenever completion info changes.
+  const suggestions = useMemo(() => {
+    if (!completion) return []
+
+    if (completion.type === 'label') {
+      const q = completion.query.toLowerCase()
+      return allLabels
+        .filter((l) => q === '' || l.name.toLowerCase().includes(q))
+        .slice(0, 8)
+        .map((l) => ({
+          display: l.name,
+          // Quote the token value if the label name contains a space
+          completedToken: `label:${l.name.includes(' ') ? `"${l.name}"` : l.name}`,
+          color: l.color,
+        }))
+    }
+
+    // author suggestions โ€” match against displayName, login, and name
+    const q = completion.query.toLowerCase()
+    return allAuthors
+      .filter(
+        (a) =>
+          q === '' ||
+          a.displayName.toLowerCase().includes(q) ||
+          (a.login ?? '').toLowerCase().includes(q) ||
+          (a.name ?? '').toLowerCase().includes(q),
+      )
+      .slice(0, 8)
+      .map((a) => {
+        // Prefer login (no spaces, stable) โ†’ name โ†’ humanId as the query value.
+        // Same preference used by IssueFilters.authorQueryValue.
+        const qv = a.login ?? a.name ?? a.humanId
+        return {
+          display: a.displayName,
+          completedToken: `author:${qv.includes(' ') ? `"${qv}"` : qv}`,
+          color: null,
+        }
+      })
+  }, [completion, allLabels, allAuthors])
+
+  // โ”€โ”€ Recompute completion state after every input change or cursor move โ”€โ”€โ”€โ”€โ”€โ”€
+
+  function updateCompletion(newValue: string, cursor: number) {
+    const info = getCompletionInfo(newValue, cursor)
+    setCompletion(info)
+    setAcIndex(0)
+  }
+
+  function handleChange(e: ChangeEvent<HTMLInputElement>) {
+    const newValue = e.target.value
+    const cursor = e.target.selectionStart ?? newValue.length
+    onChange(newValue)
+    updateCompletion(newValue, cursor)
+  }
+
+  // onSelect fires on cursor movement (arrow keys, click-to-reposition), which
+  // lets us show/hide the dropdown correctly when the cursor moves into or out
+  // of an autocomplete-eligible token without changing the text.
+  function handleSelect(e: React.SyntheticEvent<HTMLInputElement>) {
+    updateCompletion(value, e.currentTarget.selectionStart ?? value.length)
+  }
+
+  // โ”€โ”€ Keyboard navigation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+  function handleKeyDown(e: React.KeyboardEvent<HTMLInputElement>) {
+    if (e.key === 'Enter' && !completion) {
+      e.preventDefault()
+      onSubmit()
+      return
+    }
+
+    if (!completion || suggestions.length === 0) return
+
+    if (e.key === 'ArrowDown') {
+      e.preventDefault()
+      setAcIndex((i) => (i + 1) % suggestions.length)
+    } else if (e.key === 'ArrowUp') {
+      e.preventDefault()
+      setAcIndex((i) => (i - 1 + suggestions.length) % suggestions.length)
+    } else if (e.key === 'Enter' || e.key === 'Tab') {
+      e.preventDefault()
+      applySuggestion(suggestions[acIndex])
+    } else if (e.key === 'Escape') {
+      setCompletion(null)
+    }
+  }
+
+  // โ”€โ”€ Apply a selected suggestion โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+  function applySuggestion(s: { completedToken: string }) {
+    if (!completion) return
+    const tokenEnd = getTokenEnd(value, completion.tokenStart)
+    // Replace the current token (from tokenStart to tokenEnd) with the completed
+    // token, then add a space so the user can type the next filter immediately.
+    const newValue =
+      value.slice(0, completion.tokenStart) +
+      s.completedToken +
+      ' ' +
+      value.slice(tokenEnd).trimStart()
+    onChange(newValue)
+    setCompletion(null)
+
+    // Restore focus and position cursor after the inserted token + space
+    const newCursor = completion.tokenStart + s.completedToken.length + 1
+    requestAnimationFrame(() => {
+      inputRef.current?.focus()
+      inputRef.current?.setSelectionRange(newCursor, newCursor)
+    })
+  }
+
+  // โ”€โ”€ Render โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+  const segments = parseSegments(value)
+  const showDropdown = completion !== null && suggestions.length > 0
+
+  return (
+    <div
+      className={cn(
+        'relative flex-1 flex items-center rounded-md border border-input bg-background',
+        'ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2',
+        className,
+      )}
+      onClick={() => inputRef.current?.focus()}
+    >
+      <Search className="pointer-events-none absolute left-3 size-4 shrink-0 text-muted-foreground" />
+
+      {/* Colored backdrop โ€” same font/size/padding as the input. aria-hidden so
+          screen readers only see the real input, not the duplicate text. */}
+      <div
+        aria-hidden
+        className="pointer-events-none absolute inset-0 flex items-center overflow-hidden pl-9 pr-3 font-mono text-sm text-foreground whitespace-pre"
+      >
+        {value === '' ? null : segments.map((seg, i) => renderSegment(seg, i))}
+      </div>
+
+      {/* Actual input โ€” transparent bg and text so the backdrop shows through.
+          caret-foreground keeps the cursor visible despite text-transparent. */}
+      <input
+        ref={inputRef}
+        type="text"
+        value={value}
+        placeholder={placeholder}
+        onChange={handleChange}
+        onKeyDown={handleKeyDown}
+        onSelect={handleSelect}
+        className="relative w-full bg-transparent py-2 pl-9 pr-3 font-mono text-sm text-transparent caret-foreground outline-none placeholder:font-sans placeholder:text-muted-foreground"
+        spellCheck={false}
+        autoComplete="off"
+      />
+
+      {/* Autocomplete dropdown โ€” positioned below the input via absolute+top-full.
+          Uses onMouseDown+preventDefault so clicking a suggestion doesn't blur
+          the input before the click registers (classic focus-race problem). */}
+      {showDropdown && (
+        <div className="absolute left-0 right-0 top-full z-50 mt-1 overflow-hidden rounded-md border border-border bg-popover shadow-md">
+          {suggestions.map((s, i) => (
+            <button
+              key={s.completedToken}
+              onMouseDown={(e) => { e.preventDefault(); applySuggestion(s) }}
+              className={cn(
+                'flex w-full items-center gap-2 px-3 py-1.5 text-left text-sm',
+                i === acIndex ? 'bg-accent text-accent-foreground' : 'hover:bg-muted',
+              )}
+            >
+              {s.color && (
+                <span
+                  className="size-2 shrink-0 rounded-full"
+                  style={{ backgroundColor: `rgb(${s.color.R},${s.color.G},${s.color.B})` }}
+                />
+              )}
+              <span className="font-mono">{s.completedToken}</span>
+              {s.display !== s.completedToken.split(':')[1]?.replace(/"/g, '') && (
+                <span className="ml-auto text-xs text-muted-foreground">{s.display}</span>
+              )}
+            </button>
+          ))}
+        </div>
+      )}
+    </div>
+  )
+}

webui2/src/components/bugs/StatusBadge.tsx ๐Ÿ”—

@@ -0,0 +1,28 @@
+import { CircleDot, CircleCheck } from 'lucide-react'
+import { cn } from '@/lib/utils'
+import { Status } from '@/__generated__/graphql'
+
+interface StatusBadgeProps {
+  status: Status
+  className?: string
+}
+
+// Open / Closed status badge with icon. Used in BugDetailPage header.
+export function StatusBadge({ status, className }: StatusBadgeProps) {
+  const isOpen = status === Status.Open
+
+  return (
+    <span
+      className={cn(
+        'inline-flex items-center gap-1.5 rounded-full px-2.5 py-1 text-xs font-medium',
+        isOpen
+          ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'
+          : 'bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400',
+        className,
+      )}
+    >
+      {isOpen ? <CircleDot className="size-3" /> : <CircleCheck className="size-3" />}
+      {isOpen ? 'Open' : 'Closed'}
+    </span>
+  )
+}

webui2/src/components/bugs/Timeline.tsx ๐Ÿ”—

@@ -0,0 +1,225 @@
+import { useState } from 'react'
+import { formatDistanceToNow } from 'date-fns'
+import { Link } from 'react-router-dom'
+import { Tag, GitPullRequestClosed, Pencil, CircleDot } from 'lucide-react'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { Markdown } from '@/components/content/Markdown'
+import { LabelBadge } from './LabelBadge'
+import { Button } from '@/components/ui/button'
+import { Textarea } from '@/components/ui/textarea'
+import {
+  Status,
+  type BugDetailQuery,
+  useBugEditCommentMutation,
+  BugDetailDocument,
+} from '@/__generated__/graphql'
+import { useAuth } from '@/lib/auth'
+
+type TimelineNode = NonNullable<
+  NonNullable<NonNullable<BugDetailQuery['repository']>['bug']>['timeline']['nodes'][number]
+>
+
+interface TimelineProps {
+  bugPrefix: string
+  items: TimelineNode[]
+}
+
+// Ordered sequence of events on a bug: comments (create and add-comment) and
+// inline events (label changes, status changes, title edits). Comment items
+// support inline editing for the logged-in user.
+export function Timeline({ bugPrefix, items }: TimelineProps) {
+  return (
+    <div className="space-y-4">
+      {items.map((item) => {
+        switch (item.__typename) {
+          case 'BugCreateTimelineItem':
+          case 'BugAddCommentTimelineItem':
+            return <CommentItem key={item.id} item={item} bugPrefix={bugPrefix} />
+          case 'BugLabelChangeTimelineItem':
+            return <LabelChangeItem key={item.id} item={item} />
+          case 'BugSetStatusTimelineItem':
+            return <StatusChangeItem key={item.id} item={item} />
+          case 'BugSetTitleTimelineItem':
+            return <TitleChangeItem key={item.id} item={item} />
+          default:
+            return null
+        }
+      })}
+    </div>
+  )
+}
+
+// โ”€โ”€ Comment (create or add-comment) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type CommentItem = Extract<
+  TimelineNode,
+  { __typename: 'BugCreateTimelineItem' | 'BugAddCommentTimelineItem' }
+>
+
+function CommentItem({ item, bugPrefix }: { item: CommentItem; bugPrefix: string }) {
+  const { user } = useAuth()
+  const [editing, setEditing] = useState(false)
+  const [editValue, setEditValue] = useState(item.message ?? '')
+
+  const [editComment, { loading }] = useBugEditCommentMutation({
+    refetchQueries: [{ query: BugDetailDocument, variables: { prefix: bugPrefix } }],
+  })
+
+  function handleSave() {
+    if (editValue.trim() === (item.message ?? '').trim()) {
+      setEditing(false)
+      return
+    }
+    editComment({
+      variables: { input: { targetPrefix: item.id, message: editValue } },
+    }).then(() => setEditing(false))
+  }
+
+  function handleCancel() {
+    setEditValue(item.message ?? '')
+    setEditing(false)
+  }
+
+  const canEdit = user !== null && user.id === item.author.id
+
+  return (
+    <div className="flex gap-3">
+      <Avatar className="mt-1 size-8 shrink-0">
+        <AvatarImage src={item.author.avatarUrl ?? undefined} alt={item.author.displayName} />
+        <AvatarFallback className="text-xs">
+          {item.author.displayName.slice(0, 2).toUpperCase()}
+        </AvatarFallback>
+      </Avatar>
+
+      <div className="min-w-0 flex-1 rounded-md border border-border">
+        <div className="flex items-center gap-2 border-b border-border bg-muted/40 px-4 py-2 text-sm">
+          <Link to={`/user/${item.author.humanId}`} className="font-medium text-foreground hover:underline">
+            {item.author.displayName}
+          </Link>
+          <span className="text-muted-foreground">
+            {formatDistanceToNow(new Date(item.createdAt), { addSuffix: true })}
+          </span>
+          {item.edited && !editing && (
+            <span className="text-xs text-muted-foreground">edited</span>
+          )}
+          {canEdit && !editing && (
+            <button
+              onClick={() => setEditing(true)}
+              className="ml-auto rounded px-1.5 py-0.5 text-xs text-muted-foreground hover:bg-muted hover:text-foreground"
+            >
+              Edit
+            </button>
+          )}
+        </div>
+
+        {editing ? (
+          <div className="space-y-2 p-3">
+            {/* Ctrl/Cmd+Enter saves; Escape cancels โ€” standard editor shortcuts */}
+            <Textarea
+              value={editValue}
+              onChange={(e) => setEditValue(e.target.value)}
+              className="min-h-24 font-mono text-sm"
+              autoFocus
+              onKeyDown={(e) => {
+                if (e.key === 'Escape') handleCancel()
+                if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) { e.preventDefault(); handleSave() }
+              }}
+            />
+            <div className="flex gap-2">
+              <Button size="sm" onClick={handleSave} disabled={loading}>
+                {loading ? 'Savingโ€ฆ' : 'Save'}
+              </Button>
+              <Button size="sm" variant="ghost" onClick={handleCancel} disabled={loading}>
+                Cancel
+              </Button>
+            </div>
+          </div>
+        ) : (
+          <div className="px-4 py-3">
+            {item.message ? (
+              <Markdown content={item.message} />
+            ) : (
+              <p className="text-sm italic text-muted-foreground">No description provided.</p>
+            )}
+          </div>
+        )}
+      </div>
+    </div>
+  )
+}
+
+// โ”€โ”€ Inline events โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+type LabelChangeItem = Extract<TimelineNode, { __typename: 'BugLabelChangeTimelineItem' }>
+type StatusChangeItem = Extract<TimelineNode, { __typename: 'BugSetStatusTimelineItem' }>
+type TitleChangeItem = Extract<TimelineNode, { __typename: 'BugSetTitleTimelineItem' }>
+
+function EventRow({ icon, children }: { icon: React.ReactNode; children: React.ReactNode }) {
+  return (
+    <div className="flex items-center gap-3 pl-2 text-sm text-muted-foreground">
+      <span className="flex size-8 shrink-0 items-center justify-center">{icon}</span>
+      {children}
+    </div>
+  )
+}
+
+function LabelChangeItem({ item }: { item: LabelChangeItem }) {
+  return (
+    <EventRow icon={<Tag className="size-4" />}>
+      <span>
+        <Link to={`/user/${item.author.humanId}`} className="font-medium text-foreground hover:underline">{item.author.displayName}</Link>{' '}
+        {item.added.length > 0 && (
+          <>
+            added{' '}
+            {item.added.map((l) => (
+              <LabelBadge key={l.name} name={l.name} color={l.color} />
+            ))}{' '}
+          </>
+        )}
+        {item.removed.length > 0 && (
+          <>
+            removed{' '}
+            {item.removed.map((l) => (
+              <LabelBadge key={l.name} name={l.name} color={l.color} />
+            ))}{' '}
+          </>
+        )}
+        {formatDistanceToNow(new Date(item.date), { addSuffix: true })}
+      </span>
+    </EventRow>
+  )
+}
+
+function StatusChangeItem({ item }: { item: StatusChangeItem }) {
+  const isOpen = item.status === Status.Open
+  return (
+    <EventRow
+      icon={
+        isOpen ? (
+          <CircleDot className="size-4 text-green-600 dark:text-green-400" />
+        ) : (
+          <GitPullRequestClosed className="size-4 text-purple-600 dark:text-purple-400" />
+        )
+      }
+    >
+      <span>
+        <Link to={`/user/${item.author.humanId}`} className="font-medium text-foreground hover:underline">{item.author.displayName}</Link>{' '}
+        {isOpen ? 'reopened' : 'closed'} this{' '}
+        {formatDistanceToNow(new Date(item.date), { addSuffix: true })}
+      </span>
+    </EventRow>
+  )
+}
+
+function TitleChangeItem({ item }: { item: TitleChangeItem }) {
+  return (
+    <EventRow icon={<Pencil className="size-4" />}>
+      <span>
+        <Link to={`/user/${item.author.humanId}`} className="font-medium text-foreground hover:underline">{item.author.displayName}</Link> changed the
+        title from <span className="line-through">{item.was}</span> to{' '}
+        <span className="font-medium text-foreground">{item.title}</span>{' '}
+        {formatDistanceToNow(new Date(item.date), { addSuffix: true })}
+      </span>
+    </EventRow>
+  )
+}

webui2/src/components/bugs/TitleEditor.tsx ๐Ÿ”—

@@ -0,0 +1,98 @@
+import { useState, useRef, useEffect } from 'react'
+import { Pencil } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import { useAuth } from '@/lib/auth'
+import { useBugSetTitleMutation, BugDetailDocument } from '@/__generated__/graphql'
+
+interface TitleEditorProps {
+  bugPrefix: string
+  title: string
+  humanId: string
+  /** Current repo slug, passed as `ref` in refetch query variables. */
+  ref_?: string | null
+}
+
+// Inline title editor in BugDetailPage. Shows the title as plain text with a
+// pencil icon on hover (auth-gated). Enter saves, Escape cancels.
+export function TitleEditor({ bugPrefix, title, humanId, ref_ }: TitleEditorProps) {
+  const { user } = useAuth()
+  const [editing, setEditing] = useState(false)
+  const [value, setValue] = useState(title)
+  const inputRef = useRef<HTMLInputElement>(null)
+
+  const [setTitle, { loading }] = useBugSetTitleMutation({
+    refetchQueries: [{ query: BugDetailDocument, variables: { ref: ref_, prefix: bugPrefix } }],
+  })
+
+  useEffect(() => {
+    if (editing) inputRef.current?.focus()
+  }, [editing])
+
+  // Keep local value in sync if title prop changes (e.g. after refetch)
+  useEffect(() => {
+    if (!editing) setValue(title)
+  }, [title, editing])
+
+  async function handleSave() {
+    const trimmed = value.trim()
+    if (trimmed && trimmed !== title) {
+      await setTitle({ variables: { input: { prefix: bugPrefix, title: trimmed } } })
+    }
+    setEditing(false)
+  }
+
+  function handleKeyDown(e: React.KeyboardEvent) {
+    if (e.key === 'Enter') handleSave()
+    if (e.key === 'Escape') {
+      setValue(title)
+      setEditing(false)
+    }
+  }
+
+  if (editing) {
+    return (
+      <div className="flex items-start gap-2">
+        <Input
+          ref={inputRef}
+          value={value}
+          onChange={(e) => setValue(e.target.value)}
+          onKeyDown={handleKeyDown}
+          className="text-xl font-semibold"
+          disabled={loading}
+        />
+        <Button size="sm" onClick={handleSave} disabled={loading || !value.trim()}>
+          Save
+        </Button>
+        <Button
+          size="sm"
+          variant="ghost"
+          onClick={() => {
+            setValue(title)
+            setEditing(false)
+          }}
+        >
+          Cancel
+        </Button>
+      </div>
+    )
+  }
+
+  return (
+    <div className="group flex items-start gap-2">
+      <h1 className="flex-1 text-2xl font-semibold leading-tight text-foreground">
+        {title}
+        <span className="ml-2 text-xl font-normal text-muted-foreground">#{humanId}</span>
+      </h1>
+      {user && (
+        <button
+          onClick={() => setEditing(true)}
+          className="mt-1 shrink-0 text-muted-foreground opacity-0 transition-opacity hover:text-foreground group-hover:opacity-100"
+          title="Edit title"
+        >
+          <Pencil className="size-4" />
+        </button>
+      )}
+    </div>
+  )
+}

webui2/src/components/code/CodeBreadcrumb.tsx ๐Ÿ”—

@@ -0,0 +1,48 @@
+import { ChevronRight } from 'lucide-react'
+
+interface CodeBreadcrumbProps {
+  repoName: string
+  ref: string
+  path: string
+  // called when user clicks a breadcrumb segment โ€” returns new path
+  onNavigate: (path: string) => void
+}
+
+// Path breadcrumb for the code browser: repo name / ref / path segments.
+// Each segment is clickable to navigate up the tree.
+export function CodeBreadcrumb({ repoName, ref, path, onNavigate }: CodeBreadcrumbProps) {
+  const parts = path ? path.split('/').filter(Boolean) : []
+
+  return (
+    <div className="flex flex-wrap items-center gap-1 font-mono text-sm">
+      <button
+        onClick={() => onNavigate('')}
+        className="font-medium text-foreground hover:underline"
+      >
+        {repoName}
+      </button>
+
+      {parts.map((part, i) => {
+        const partPath = parts.slice(0, i + 1).join('/')
+        const isLast = i === parts.length - 1
+        return (
+          <span key={partPath} className="flex items-center gap-1">
+            <ChevronRight className="size-3.5 text-muted-foreground" />
+            {isLast ? (
+              <span className="font-medium text-foreground">{part}</span>
+            ) : (
+              <button
+                onClick={() => onNavigate(partPath)}
+                className="text-muted-foreground hover:text-foreground hover:underline"
+              >
+                {part}
+              </button>
+            )}
+          </span>
+        )
+      })}
+
+      <span className="ml-2 text-xs text-muted-foreground">@ {ref}</span>
+    </div>
+  )
+}

webui2/src/components/code/CommitList.tsx ๐Ÿ”—

@@ -0,0 +1,158 @@
+import { useState, useEffect } from 'react'
+import { Link } from 'react-router-dom'
+import { formatDistanceToNow } from 'date-fns'
+import { GitCommit } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { Skeleton } from '@/components/ui/skeleton'
+import { getCommits } from '@/lib/gitApi'
+import type { GitCommit as GitCommitType } from '@/lib/gitApi'
+
+interface CommitListProps {
+  ref_: string
+  path?: string
+}
+
+const PAGE_SIZE = 30
+
+// Paginated commit history grouped by calendar date. Each row links to the
+// commit detail page. Used in CodePage's "History" view.
+export function CommitList({ ref_, path }: CommitListProps) {
+  const [commits, setCommits] = useState<GitCommitType[]>([])
+  const [loading, setLoading] = useState(true)
+  const [loadingMore, setLoadingMore] = useState(false)
+  const [error, setError] = useState<string | null>(null)
+  const [hasMore, setHasMore] = useState(true)
+
+  useEffect(() => {
+    setCommits([])
+    setHasMore(true)
+    setError(null)
+    setLoading(true)
+    getCommits(ref_, { path, limit: PAGE_SIZE })
+      .then((data) => {
+        setCommits(data)
+        setHasMore(data.length === PAGE_SIZE)
+      })
+      .catch((e: Error) => setError(e.message))
+      .finally(() => setLoading(false))
+  }, [ref_, path])
+
+  function loadMore() {
+    const last = commits[commits.length - 1]
+    if (!last) return
+    setLoadingMore(true)
+    getCommits(ref_, { path, limit: PAGE_SIZE, after: last.hash })
+      .then((data) => {
+        setCommits((prev) => [...prev, ...data])
+        setHasMore(data.length === PAGE_SIZE)
+      })
+      .catch((e: Error) => setError(e.message))
+      .finally(() => setLoadingMore(false))
+  }
+
+  if (loading) return <CommitListSkeleton />
+
+  if (error) {
+    return (
+      <div className="rounded-md border border-border px-4 py-8 text-center text-sm text-destructive">
+        {error}
+      </div>
+    )
+  }
+
+  // Group commits by date (YYYY-MM-DD)
+  const groups = groupByDate(commits)
+
+  return (
+    <div className="space-y-6">
+      {groups.map(([date, group]) => (
+        <div key={date}>
+          <h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
+            Commits on {date}
+          </h3>
+          <div className="overflow-hidden rounded-md border border-border divide-y divide-border">
+            {group.map((commit) => (
+              <CommitRow key={commit.hash} commit={commit} />
+            ))}
+          </div>
+        </div>
+      ))}
+
+      {hasMore && (
+        <div className="text-center">
+          <Button variant="outline" size="sm" onClick={loadMore} disabled={loadingMore}>
+            {loadingMore ? 'Loadingโ€ฆ' : 'Load more commits'}
+          </Button>
+        </div>
+      )}
+    </div>
+  )
+}
+
+function CommitRow({ commit }: { commit: GitCommitType }) {
+  return (
+    <div className="flex items-center gap-3 bg-background px-4 py-3 hover:bg-muted/30">
+      <GitCommit className="size-4 shrink-0 text-muted-foreground" />
+
+      <div className="min-w-0 flex-1">
+        <Link
+          to={`/commit/${commit.hash}`}
+          className="block truncate font-medium text-foreground hover:text-primary hover:underline"
+        >
+          {commit.message}
+        </Link>
+        <p className="mt-0.5 text-xs text-muted-foreground">
+          {commit.authorName} &middot;{' '}
+          {formatDistanceToNow(new Date(commit.date), { addSuffix: true })}
+        </p>
+      </div>
+
+      <Link
+        to={`/commit/${commit.hash}`}
+        className="shrink-0 font-mono text-xs text-muted-foreground hover:text-foreground hover:underline"
+        title={commit.hash}
+      >
+        {commit.shortHash}
+      </Link>
+    </div>
+  )
+}
+
+function groupByDate(commits: GitCommitType[]): [string, GitCommitType[]][] {
+  const map = new Map<string, GitCommitType[]>()
+  for (const c of commits) {
+    const date = new Date(c.date).toLocaleDateString('en-US', {
+      year: 'numeric',
+      month: 'long',
+      day: 'numeric',
+    })
+    const group = map.get(date) ?? []
+    group.push(c)
+    map.set(date, group)
+  }
+  return Array.from(map.entries())
+}
+
+function CommitListSkeleton() {
+  return (
+    <div className="space-y-6">
+      {Array.from({ length: 2 }).map((_, g) => (
+        <div key={g}>
+          <Skeleton className="mb-2 h-3 w-32" />
+          <div className="overflow-hidden rounded-md border border-border divide-y divide-border">
+            {Array.from({ length: 4 }).map((_, i) => (
+              <div key={i} className="flex items-center gap-3 px-4 py-3">
+                <Skeleton className="size-4 rounded" />
+                <div className="flex-1 space-y-1.5">
+                  <Skeleton className="h-4 w-2/3" />
+                  <Skeleton className="h-3 w-1/4" />
+                </div>
+                <Skeleton className="h-3 w-14" />
+              </div>
+            ))}
+          </div>
+        </div>
+      ))}
+    </div>
+  )
+}

webui2/src/components/code/FileTree.tsx ๐Ÿ”—

@@ -0,0 +1,112 @@
+import { Folder, File } from 'lucide-react'
+import { Link } from 'react-router-dom'
+import { formatDistanceToNow } from 'date-fns'
+import { Skeleton } from '@/components/ui/skeleton'
+import type { GitTreeEntry } from '@/lib/gitApi'
+
+interface FileTreeProps {
+  entries: GitTreeEntry[]
+  path: string
+  loading?: boolean
+  onNavigate: (entry: GitTreeEntry) => void
+  onNavigateUp: () => void
+}
+
+// Directory listing table for the code browser. Shows each entry's icon,
+// name, last-commit message (linked to commit detail), and relative date.
+export function FileTree({ entries, path, loading, onNavigate, onNavigateUp }: FileTreeProps) {
+  // Directories first, then files โ€” each group alphabetical
+  const sorted = [...entries].sort((a, b) => {
+    if (a.type !== b.type) return a.type === 'tree' ? -1 : 1
+    return a.name.localeCompare(b.name)
+  })
+
+  if (loading) return <FileTreeSkeleton />
+
+  return (
+    <div className="overflow-hidden rounded-md border border-border">
+      <table className="w-full text-sm">
+        <tbody className="divide-y divide-border">
+          {path && (
+            <tr
+              className="cursor-pointer hover:bg-muted/40"
+              onClick={onNavigateUp}
+            >
+              <td className="w-6 py-2 pl-4">
+                <Folder className="size-4 text-blue-500 dark:text-blue-400" />
+              </td>
+              <td className="px-3 py-2 font-mono text-muted-foreground">..</td>
+              <td className="hidden px-3 py-2 text-muted-foreground md:table-cell" />
+              <td className="hidden px-4 py-2 text-right text-muted-foreground md:table-cell" />
+            </tr>
+          )}
+          {sorted.map((entry) => (
+            <FileTreeRow key={entry.name} entry={entry} onNavigate={onNavigate} />
+          ))}
+        </tbody>
+      </table>
+    </div>
+  )
+}
+
+function FileTreeRow({
+  entry,
+  onNavigate,
+}: {
+  entry: GitTreeEntry
+  onNavigate: (entry: GitTreeEntry) => void
+}) {
+  const isDir = entry.type === 'tree'
+
+  return (
+    <tr
+      className="cursor-pointer hover:bg-muted/40"
+      onClick={() => onNavigate(entry)}
+    >
+      <td className="w-6 py-2 pl-4">
+        {isDir ? (
+          <Folder className="size-4 text-blue-500 dark:text-blue-400" />
+        ) : (
+          <File className="size-4 text-muted-foreground" />
+        )}
+      </td>
+      <td className="px-3 py-2">
+        <span className={`font-mono ${isDir ? 'font-medium text-foreground' : 'text-foreground'}`}>
+          {entry.name}
+        </span>
+      </td>
+      <td className="hidden max-w-xs truncate px-3 py-2 text-muted-foreground md:table-cell">
+        {entry.lastCommit && (
+          <Link
+            to={`/commit/${entry.lastCommit.hash}`}
+            className="hover:text-foreground hover:underline"
+            onClick={(e) => e.stopPropagation()}
+          >
+            {entry.lastCommit.message}
+          </Link>
+        )}
+      </td>
+      <td className="hidden whitespace-nowrap px-4 py-2 text-right text-xs text-muted-foreground md:table-cell">
+        {entry.lastCommit &&
+          formatDistanceToNow(new Date(entry.lastCommit.date), { addSuffix: true })}
+      </td>
+    </tr>
+  )
+}
+
+function FileTreeSkeleton() {
+  return (
+    <div className="overflow-hidden rounded-md border border-border">
+      <div className="divide-y divide-border">
+        {Array.from({ length: 8 }).map((_, i) => (
+          <div key={i} className="flex items-center gap-3 px-4 py-2">
+            <Skeleton className="size-4 rounded" />
+            <Skeleton className="h-4 w-32" />
+            <Skeleton className="ml-6 hidden h-4 w-64 md:block" />
+            <Skeleton className="ml-auto hidden h-4 w-20 md:block" />
+          </div>
+        ))}
+      </div>
+    </div>
+  )
+}

webui2/src/components/code/FileViewer.tsx ๐Ÿ”—

@@ -0,0 +1,113 @@
+import { useMemo } from 'react'
+import hljs from 'highlight.js'
+import { Copy, Download } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { Skeleton } from '@/components/ui/skeleton'
+import type { GitBlob } from '@/lib/gitApi'
+
+interface FileViewerProps {
+  blob: GitBlob
+  loading?: boolean
+}
+
+// Syntax-highlighted file viewer with line numbers, copy, and download buttons.
+// Uses highlight.js for highlighting; binary files show a placeholder.
+export function FileViewer({ blob, loading }: FileViewerProps) {
+  const { html, lineCount } = useMemo(() => {
+    if (blob.isBinary || !blob.content) return { html: '', lineCount: 0 }
+    const ext = blob.path.split('.').pop() ?? ''
+    const result = hljs.getLanguage(ext)
+      ? hljs.highlight(blob.content, { language: ext })
+      : hljs.highlightAuto(blob.content)
+    return {
+      html: result.value,
+      lineCount: blob.content.split('\n').length,
+    }
+  }, [blob])
+
+  if (loading) return <FileViewerSkeleton />
+
+  function copyToClipboard() {
+    navigator.clipboard.writeText(blob.content)
+  }
+
+  return (
+    <div className="overflow-hidden rounded-md border border-border">
+      {/* Metadata bar */}
+      <div className="flex items-center justify-between border-b border-border bg-muted/40 px-4 py-2 text-xs text-muted-foreground">
+        <span>
+          {lineCount.toLocaleString()} lines ยท {formatBytes(blob.size)}
+        </span>
+        <div className="flex items-center gap-1">
+          <Button
+            variant="ghost"
+            size="icon"
+            className="size-7"
+            onClick={copyToClipboard}
+            title="Copy"
+          >
+            <Copy className="size-3.5" />
+          </Button>
+          <Button variant="ghost" size="icon" className="size-7" asChild title="Download">
+            <a href={`/gitfile/default/${blob.path}`} download>
+              <Download className="size-3.5" />
+            </a>
+          </Button>
+        </div>
+      </div>
+
+      {blob.isBinary ? (
+        <div className="px-4 py-8 text-center text-sm text-muted-foreground">
+          Binary file โ€” {formatBytes(blob.size)}
+        </div>
+      ) : (
+        // Line numbers are a fixed column; code scrolls horizontally independently.
+        // Keeping them in separate divs avoids having to split highlighted HTML by line.
+        <div className="flex overflow-x-auto font-mono text-xs leading-5">
+          <div
+            className="select-none border-r border-border bg-muted/20 px-4 py-4 text-right text-muted-foreground/50"
+            aria-hidden
+          >
+            {Array.from({ length: lineCount }, (_, i) => (
+              <div key={i}>{i + 1}</div>
+            ))}
+          </div>
+          <pre className="flex-1 overflow-visible px-4 py-4">
+            <code
+              className="hljs"
+              dangerouslySetInnerHTML={{ __html: html }}
+            />
+          </pre>
+        </div>
+      )}
+    </div>
+  )
+}
+
+function formatBytes(bytes: number): string {
+  if (bytes < 1024) return `${bytes} B`
+  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
+  return `${(bytes / 1024 / 1024).toFixed(1)} MB`
+}
+
+function FileViewerSkeleton() {
+  return (
+    <div className="overflow-hidden rounded-md border border-border">
+      <div className="border-b border-border bg-muted/40 px-4 py-2">
+        <Skeleton className="h-4 w-32" />
+      </div>
+      <div className="flex gap-4 p-4">
+        <div className="space-y-1.5">
+          {Array.from({ length: 20 }).map((_, i) => (
+            <Skeleton key={i} className="h-3.5 w-6" />
+          ))}
+        </div>
+        <div className="flex-1 space-y-1.5">
+          {Array.from({ length: 20 }).map((_, i) => (
+            <Skeleton key={i} className="h-3.5" style={{ width: `${30 + Math.random() * 60}%` }} />
+          ))}
+        </div>
+      </div>
+    </div>
+  )
+}

webui2/src/components/code/RefSelector.tsx ๐Ÿ”—

@@ -0,0 +1,107 @@
+import { useState } from 'react'
+import { GitBranch, Tag, Check, ChevronsUpDown } from 'lucide-react'
+import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import type { GitRef } from '@/lib/gitApi'
+import { cn } from '@/lib/utils'
+
+interface RefSelectorProps {
+  refs: GitRef[]
+  currentRef: string
+  onSelect: (ref: GitRef) => void
+}
+
+// Branch / tag selector dropdown for the code browser. Shown in two groups
+// (branches, tags) with an inline search filter.
+export function RefSelector({ refs, currentRef, onSelect }: RefSelectorProps) {
+  const [open, setOpen] = useState(false)
+  const [filter, setFilter] = useState('')
+
+  const filtered = refs.filter((r) =>
+    r.shortName.toLowerCase().includes(filter.toLowerCase()),
+  )
+  const branches = filtered.filter((r) => r.type === 'branch')
+  const tags = filtered.filter((r) => r.type === 'tag')
+
+  return (
+    <Popover open={open} onOpenChange={setOpen}>
+      <PopoverTrigger asChild>
+        <Button variant="outline" size="sm" className="gap-2 font-mono text-xs">
+          <GitBranch className="size-3.5" />
+          {currentRef}
+          <ChevronsUpDown className="size-3 text-muted-foreground" />
+        </Button>
+      </PopoverTrigger>
+      <PopoverContent align="start" className="w-64 p-2">
+        <p className="mb-2 px-1 text-xs font-semibold text-muted-foreground">Switch branch / tag</p>
+        <Input
+          placeholder="Filterโ€ฆ"
+          className="mb-2 h-7 text-xs"
+          value={filter}
+          onChange={(e) => setFilter(e.target.value)}
+          autoFocus
+        />
+        <div className="max-h-64 overflow-y-auto">
+          {branches.length > 0 && (
+            <div className="mb-1">
+              <p className="px-2 py-1 text-xs text-muted-foreground">Branches</p>
+              {branches.map((ref) => (
+                <RefItem
+                  key={ref.name}
+                  ref_={ref}
+                  active={ref.shortName === currentRef}
+                  onSelect={() => { onSelect(ref); setOpen(false); setFilter('') }}
+                />
+              ))}
+            </div>
+          )}
+          {tags.length > 0 && (
+            <div>
+              <p className="px-2 py-1 text-xs text-muted-foreground">Tags</p>
+              {tags.map((ref) => (
+                <RefItem
+                  key={ref.name}
+                  ref_={ref}
+                  active={ref.shortName === currentRef}
+                  onSelect={() => { onSelect(ref); setOpen(false); setFilter('') }}
+                />
+              ))}
+            </div>
+          )}
+          {filtered.length === 0 && (
+            <p className="px-2 py-2 text-xs text-muted-foreground">No results</p>
+          )}
+        </div>
+      </PopoverContent>
+    </Popover>
+  )
+}
+
+function RefItem({
+  ref_,
+  active,
+  onSelect,
+}: {
+  ref_: GitRef
+  active: boolean
+  onSelect: () => void
+}) {
+  return (
+    <button
+      onClick={onSelect}
+      className={cn(
+        'flex w-full items-center gap-2 rounded px-2 py-1.5 text-left text-xs hover:bg-muted',
+        active && 'font-medium',
+      )}
+    >
+      {ref_.type === 'branch' ? (
+        <GitBranch className="size-3 shrink-0 text-muted-foreground" />
+      ) : (
+        <Tag className="size-3 shrink-0 text-muted-foreground" />
+      )}
+      <span className="flex-1 truncate font-mono">{ref_.shortName}</span>
+      {active && <Check className="size-3 text-muted-foreground" />}
+    </button>
+  )
+}

webui2/src/components/content/Markdown.tsx ๐Ÿ”—

@@ -0,0 +1,26 @@
+import ReactMarkdown from 'react-markdown'
+import remarkGfm from 'remark-gfm'
+import { cn } from '@/lib/utils'
+
+interface MarkdownProps {
+  content: string
+  className?: string
+}
+
+// Renders a Markdown string with GitHub-flavoured extensions (tables, task
+// lists, strikethrough). Used in Timeline comments and NewBugPage preview.
+export function Markdown({ content, className }: MarkdownProps) {
+  return (
+    <ReactMarkdown
+      remarkPlugins={[remarkGfm]}
+      className={cn(
+        'prose prose-sm dark:prose-invert max-w-none',
+        'prose-pre:bg-muted prose-pre:text-foreground',
+        'prose-code:bg-muted prose-code:px-1 prose-code:py-0.5 prose-code:rounded prose-code:text-sm prose-code:before:content-none prose-code:after:content-none',
+        className,
+      )}
+    >
+      {content}
+    </ReactMarkdown>
+  )
+}

webui2/src/components/layout/Header.tsx ๐Ÿ”—

@@ -0,0 +1,132 @@
+// Sticky top navigation bar. Adapts based on whether we're on the repo picker
+// page (root) or inside a specific repo:
+//   - Root: shows logo only, no Code/Issues links
+//   - Repo: shows Code + Issues nav links scoped to the current repo slug
+//
+// In oauth mode, shows a "Sign in" button when logged out and a sign-out
+// action when logged in.
+
+import { Link, useMatch, NavLink } from 'react-router-dom'
+import { Bug, Plus, Sun, Moon, LogIn, LogOut } from 'lucide-react'
+import { cn } from '@/lib/utils'
+import { useAuth } from '@/lib/auth'
+import { useTheme } from '@/lib/theme'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { Button } from '@/components/ui/button'
+
+// SignOutButton sends a POST to /auth/logout and reloads the page.
+// A full reload is the simplest way to reset all Apollo cache + React state.
+function SignOutButton() {
+  function handleSignOut() {
+    fetch('/auth/logout', { method: 'POST', credentials: 'include' }).finally(
+      () => window.location.assign('/'),
+    )
+  }
+  return (
+    <Button variant="ghost" size="sm" onClick={handleSignOut} title="Sign out">
+      <LogOut className="size-4" />
+    </Button>
+  )
+}
+
+export function Header() {
+  const { user, mode, oauthProviders } = useAuth()
+  const { theme, toggle } = useTheme()
+
+  // Detect if we're inside a /:repo route and grab the slug.
+  // useMatch works from any component in the tree, unlike useParams which is
+  // scoped to the nearest Route element.
+  const repoMatch = useMatch({ path: '/:repo/*', end: false })
+  const repo = repoMatch?.params.repo ?? null
+
+  // Don't match /_/auth/* as a repo slug.
+  const effectiveRepo = repo === '_' ? null : repo
+
+  return (
+    <header className="sticky top-0 z-50 border-b border-border bg-background/95 backdrop-blur">
+      <div className="mx-auto flex h-14 max-w-screen-xl items-center gap-6 px-4">
+        {/* Logo always goes to the repo picker root */}
+        <Link to="/" className="flex items-center gap-2 font-semibold text-foreground">
+          <Bug className="size-4" />
+          <span>git-bug</span>
+        </Link>
+
+        {/* Repo-scoped nav links โ€” only shown when inside a repo */}
+        {effectiveRepo && (
+          <nav className="flex items-center gap-1">
+            <NavLink
+              to={`/${effectiveRepo}`}
+              end
+              className={({ isActive }) => cn(
+                'rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+                isActive
+                  ? 'bg-accent text-accent-foreground'
+                  : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground',
+              )}
+            >
+              Code
+            </NavLink>
+            <NavLink
+              to={`/${effectiveRepo}/issues`}
+              className={({ isActive }) => cn(
+                'rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+                isActive
+                  ? 'bg-accent text-accent-foreground'
+                  : 'text-muted-foreground hover:bg-accent hover:text-accent-foreground',
+              )}
+            >
+              Issues
+            </NavLink>
+          </nav>
+        )}
+
+        <div className="ml-auto flex items-center gap-2">
+          {mode === 'readonly' && (
+            <span className="text-xs text-muted-foreground">Read only</span>
+          )}
+
+          <Button variant="ghost" size="icon" onClick={toggle} title="Toggle theme">
+            {theme === 'light' ? <Moon className="size-4" /> : <Sun className="size-4" />}
+          </Button>
+
+          {/* OAuth mode: show sign-in buttons when logged out */}
+          {mode === 'oauth' && !user && oauthProviders.map((provider) => (
+            <Button key={provider} asChild size="sm" variant="outline">
+              <a href={`/auth/login?provider=${provider}`}>
+                <LogIn className="size-4" />
+                Sign in with {providerLabel(provider)}
+              </a>
+            </Button>
+          ))}
+
+          {user && effectiveRepo && (
+            <>
+              <Button asChild size="sm" variant="outline">
+                <Link to={`/${effectiveRepo}/issues/new`}>
+                  <Plus className="size-4" />
+                  New issue
+                </Link>
+              </Button>
+              <Link to={`/${effectiveRepo}/user/${user.humanId}`}>
+                <Avatar className="size-7">
+                  <AvatarImage src={user.avatarUrl ?? undefined} alt={user.displayName} />
+                  <AvatarFallback className="text-xs">
+                    {user.displayName.slice(0, 2).toUpperCase()}
+                  </AvatarFallback>
+                </Avatar>
+              </Link>
+            </>
+          )}
+
+          {/* Sign out only shown in oauth mode when logged in */}
+          {mode === 'oauth' && user && <SignOutButton />}
+        </div>
+      </div>
+    </header>
+  )
+}
+
+function providerLabel(name: string): string {
+  const labels: Record<string, string> = { github: 'GitHub', gitlab: 'GitLab', gitea: 'Gitea' }
+  return labels[name] ?? name
+}

webui2/src/components/layout/Shell.tsx ๐Ÿ”—

@@ -0,0 +1,15 @@
+import { Outlet } from 'react-router-dom'
+import { Header } from './Header'
+
+// Top-level page wrapper used as the root layout in App.tsx. Renders the
+// Header above the current route's page component via <Outlet>.
+export function Shell() {
+  return (
+    <div className="min-h-screen bg-background font-sans antialiased">
+      <Header />
+      <main className="mx-auto max-w-screen-xl px-4 py-6">
+        <Outlet />
+      </main>
+    </div>
+  )
+}

webui2/src/components/ui/avatar.tsx ๐Ÿ”—

@@ -0,0 +1,44 @@
+import * as React from 'react'
+import * as AvatarPrimitive from '@radix-ui/react-avatar'
+import { cn } from '@/lib/utils'
+
+const Avatar = React.forwardRef<
+  React.ElementRef<typeof AvatarPrimitive.Root>,
+  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
+>(({ className, ...props }, ref) => (
+  <AvatarPrimitive.Root
+    ref={ref}
+    className={cn('relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full', className)}
+    {...props}
+  />
+))
+Avatar.displayName = AvatarPrimitive.Root.displayName
+
+const AvatarImage = React.forwardRef<
+  React.ElementRef<typeof AvatarPrimitive.Image>,
+  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
+>(({ className, ...props }, ref) => (
+  <AvatarPrimitive.Image
+    ref={ref}
+    className={cn('aspect-square h-full w-full', className)}
+    {...props}
+  />
+))
+AvatarImage.displayName = AvatarPrimitive.Image.displayName
+
+const AvatarFallback = React.forwardRef<
+  React.ElementRef<typeof AvatarPrimitive.Fallback>,
+  React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
+>(({ className, ...props }, ref) => (
+  <AvatarPrimitive.Fallback
+    ref={ref}
+    className={cn(
+      'flex h-full w-full items-center justify-center rounded-full bg-muted text-xs font-medium',
+      className,
+    )}
+    {...props}
+  />
+))
+AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
+
+export { Avatar, AvatarImage, AvatarFallback }

webui2/src/components/ui/badge.tsx ๐Ÿ”—

@@ -0,0 +1,30 @@
+import * as React from 'react'
+import { cva, type VariantProps } from 'class-variance-authority'
+import { cn } from '@/lib/utils'
+
+const badgeVariants = cva(
+  'inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2',
+  {
+    variants: {
+      variant: {
+        default: 'border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80',
+        secondary: 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
+        destructive: 'border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80',
+        outline: 'text-foreground',
+      },
+    },
+    defaultVariants: {
+      variant: 'default',
+    },
+  },
+)
+
+export interface BadgeProps
+  extends React.HTMLAttributes<HTMLDivElement>,
+    VariantProps<typeof badgeVariants> {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+  return <div className={cn(badgeVariants({ variant }), className)} {...props} />
+}
+
+export { Badge, badgeVariants }

webui2/src/components/ui/button.tsx ๐Ÿ”—

@@ -0,0 +1,52 @@
+import * as React from 'react'
+import { Slot } from '@radix-ui/react-slot'
+import { cva, type VariantProps } from 'class-variance-authority'
+import { cn } from '@/lib/utils'
+
+const buttonVariants = cva(
+  'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
+  {
+    variants: {
+      variant: {
+        default: 'bg-primary text-primary-foreground shadow hover:bg-primary/90',
+        destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90',
+        outline: 'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
+        secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
+        ghost: 'hover:bg-accent hover:text-accent-foreground',
+        link: 'text-primary underline-offset-4 hover:underline',
+      },
+      size: {
+        default: 'h-9 px-4 py-2',
+        sm: 'h-8 rounded-md px-3 text-xs',
+        lg: 'h-10 rounded-md px-8',
+        icon: 'h-9 w-9',
+      },
+    },
+    defaultVariants: {
+      variant: 'default',
+      size: 'default',
+    },
+  },
+)
+
+export interface ButtonProps
+  extends React.ButtonHTMLAttributes<HTMLButtonElement>,
+    VariantProps<typeof buttonVariants> {
+  asChild?: boolean
+}
+
+const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
+  ({ className, variant, size, asChild = false, ...props }, ref) => {
+    const Comp = asChild ? Slot : 'button'
+    return (
+      <Comp
+        className={cn(buttonVariants({ variant, size, className }))}
+        ref={ref}
+        {...props}
+      />
+    )
+  },
+)
+Button.displayName = 'Button'
+
+export { Button, buttonVariants }

webui2/src/components/ui/input.tsx ๐Ÿ”—

@@ -0,0 +1,21 @@
+import * as React from 'react'
+import { cn } from '@/lib/utils'
+
+const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<'input'>>(
+  ({ className, type, ...props }, ref) => {
+    return (
+      <input
+        type={type}
+        className={cn(
+          'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
+          className,
+        )}
+        ref={ref}
+        {...props}
+      />
+    )
+  },
+)
+Input.displayName = 'Input'
+
+export { Input }

webui2/src/components/ui/popover.tsx ๐Ÿ”—

@@ -0,0 +1,28 @@
+import * as React from 'react'
+import * as PopoverPrimitive from '@radix-ui/react-popover'
+import { cn } from '@/lib/utils'
+
+const Popover = PopoverPrimitive.Root
+const PopoverTrigger = PopoverPrimitive.Trigger
+const PopoverAnchor = PopoverPrimitive.Anchor
+
+const PopoverContent = React.forwardRef<
+  React.ElementRef<typeof PopoverPrimitive.Content>,
+  React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
+>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => (
+  <PopoverPrimitive.Portal>
+    <PopoverPrimitive.Content
+      ref={ref}
+      align={align}
+      sideOffset={sideOffset}
+      className={cn(
+        'z-50 w-72 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
+        className,
+      )}
+      {...props}
+    />
+  </PopoverPrimitive.Portal>
+))
+PopoverContent.displayName = PopoverPrimitive.Content.displayName
+
+export { Popover, PopoverTrigger, PopoverAnchor, PopoverContent }

webui2/src/components/ui/separator.tsx ๐Ÿ”—

@@ -0,0 +1,23 @@
+import * as React from 'react'
+import * as SeparatorPrimitive from '@radix-ui/react-separator'
+import { cn } from '@/lib/utils'
+
+const Separator = React.forwardRef<
+  React.ElementRef<typeof SeparatorPrimitive.Root>,
+  React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
+>(({ className, orientation = 'horizontal', decorative = true, ...props }, ref) => (
+  <SeparatorPrimitive.Root
+    ref={ref}
+    decorative={decorative}
+    orientation={orientation}
+    className={cn(
+      'shrink-0 bg-border',
+      orientation === 'horizontal' ? 'h-[1px] w-full' : 'h-full w-[1px]',
+      className,
+    )}
+    {...props}
+  />
+))
+Separator.displayName = SeparatorPrimitive.Root.displayName
+
+export { Separator }

webui2/src/components/ui/skeleton.tsx ๐Ÿ”—

@@ -0,0 +1,12 @@
+import { cn } from '@/lib/utils'
+
+function Skeleton({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) {
+  return (
+    <div
+      className={cn('animate-pulse rounded-md bg-primary/10', className)}
+      {...props}
+    />
+  )
+}
+
+export { Skeleton }

webui2/src/components/ui/textarea.tsx ๐Ÿ”—

@@ -0,0 +1,20 @@
+import * as React from 'react'
+import { cn } from '@/lib/utils'
+
+const Textarea = React.forwardRef<HTMLTextAreaElement, React.ComponentProps<'textarea'>>(
+  ({ className, ...props }, ref) => {
+    return (
+      <textarea
+        className={cn(
+          'flex min-h-[80px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
+          className,
+        )}
+        ref={ref}
+        {...props}
+      />
+    )
+  },
+)
+Textarea.displayName = 'Textarea'
+
+export { Textarea }

webui2/src/graphql/AllIdentities.graphql ๐Ÿ”—

@@ -0,0 +1,15 @@
+query AllIdentities($ref: String) {
+  repository(ref: $ref) {
+    allIdentities(first: 1000) {
+      nodes {
+        id
+        humanId
+        name
+        email
+        login
+        displayName
+        avatarUrl
+      }
+    }
+  }
+}

webui2/src/graphql/BugDetail.graphql ๐Ÿ”—

@@ -0,0 +1,104 @@
+query BugDetail($ref: String, $prefix: String!) {
+  repository(ref: $ref) {
+    bug(prefix: $prefix) {
+      id
+      humanId
+      status
+      title
+      labels {
+        name
+        color {
+          R
+          G
+          B
+        }
+      }
+      author {
+        id
+        humanId
+        displayName
+        avatarUrl
+      }
+      createdAt
+      lastEdit
+      participants(first: 20) {
+        nodes {
+          id
+          humanId
+          displayName
+          avatarUrl
+        }
+      }
+      timeline(first: 250) {
+        nodes {
+          __typename
+          id
+          ... on BugCreateTimelineItem {
+            author {
+              id
+              humanId
+              displayName
+              avatarUrl
+            }
+            message
+            createdAt
+            lastEdit
+            edited
+          }
+          ... on BugAddCommentTimelineItem {
+            author {
+              id
+              humanId
+              displayName
+              avatarUrl
+            }
+            message
+            createdAt
+            lastEdit
+            edited
+          }
+          ... on BugLabelChangeTimelineItem {
+            author {
+              humanId
+              displayName
+            }
+            date
+            added {
+              name
+              color {
+                R
+                G
+                B
+              }
+            }
+            removed {
+              name
+              color {
+                R
+                G
+                B
+              }
+            }
+          }
+          ... on BugSetStatusTimelineItem {
+            author {
+              humanId
+              displayName
+            }
+            date
+            status
+          }
+          ... on BugSetTitleTimelineItem {
+            author {
+              humanId
+              displayName
+            }
+            date
+            title
+            was
+          }
+        }
+      }
+    }
+  }
+}

webui2/src/graphql/BugList.graphql ๐Ÿ”—

@@ -0,0 +1,35 @@
+query BugList($ref: String, $query: String, $first: Int, $after: String) {
+  repository(ref: $ref) {
+    allBugs(query: $query, first: $first, after: $after) {
+      totalCount
+      pageInfo {
+        hasNextPage
+        endCursor
+      }
+      nodes {
+        id
+        humanId
+        status
+        title
+        labels {
+          name
+          color {
+            R
+            G
+            B
+          }
+        }
+        author {
+          id
+          humanId
+          displayName
+          avatarUrl
+        }
+        createdAt
+        comments {
+          totalCount
+        }
+      }
+    }
+  }
+}

webui2/src/graphql/BugMutations.graphql ๐Ÿ”—

@@ -0,0 +1,83 @@
+mutation BugCreate($input: BugCreateInput!) {
+  bugCreate(input: $input) {
+    bug {
+      id
+      humanId
+    }
+  }
+}
+
+mutation BugAddComment($input: BugAddCommentInput!) {
+  bugAddComment(input: $input) {
+    bug {
+      id
+    }
+  }
+}
+
+mutation BugAddCommentAndClose($input: BugAddCommentAndCloseInput!) {
+  bugAddCommentAndClose(input: $input) {
+    bug {
+      id
+    }
+  }
+}
+
+mutation BugAddCommentAndReopen($input: BugAddCommentAndReopenInput!) {
+  bugAddCommentAndReopen(input: $input) {
+    bug {
+      id
+    }
+  }
+}
+
+mutation BugEditComment($input: BugEditCommentInput!) {
+  bugEditComment(input: $input) {
+    bug {
+      id
+    }
+  }
+}
+
+mutation BugChangeLabels($input: BugChangeLabelInput) {
+  bugChangeLabels(input: $input) {
+    bug {
+      id
+      labels {
+        name
+        color {
+          R
+          G
+          B
+        }
+      }
+    }
+  }
+}
+
+mutation BugStatusOpen($input: BugStatusOpenInput!) {
+  bugStatusOpen(input: $input) {
+    bug {
+      id
+      status
+    }
+  }
+}
+
+mutation BugStatusClose($input: BugStatusCloseInput!) {
+  bugStatusClose(input: $input) {
+    bug {
+      id
+      status
+    }
+  }
+}
+
+mutation BugSetTitle($input: BugSetTitleInput!) {
+  bugSetTitle(input: $input) {
+    bug {
+      id
+      title
+    }
+  }
+}

webui2/src/graphql/UserProfile.graphql ๐Ÿ”—

@@ -0,0 +1,57 @@
+# Profile page query. We fetch open and closed counts unconditionally so both
+# can be shown in the toggle header regardless of which tab is active. The
+# paginated `bugs` alias fetches the selected status list separately.
+query UserProfile(
+  $ref: String
+  $prefix: String!
+  $openQuery: String!
+  $closedQuery: String!
+  $listQuery: String!
+  $after: String
+) {
+  repository(ref: $ref) {
+    identity(prefix: $prefix) {
+      id
+      humanId
+      name
+      email
+      login
+      displayName
+      avatarUrl
+      isProtected
+    }
+    # Always-fetched counts so we can show both numbers in the toggle.
+    openCount: allBugs(query: $openQuery, first: 1) {
+      totalCount
+    }
+    closedCount: allBugs(query: $closedQuery, first: 1) {
+      totalCount
+    }
+    # Paginated list for the currently-selected tab.
+    bugs: allBugs(query: $listQuery, first: 25, after: $after) {
+      totalCount
+      pageInfo {
+        hasNextPage
+        endCursor
+      }
+      nodes {
+        id
+        humanId
+        status
+        title
+        labels {
+          name
+          color {
+            R
+            G
+            B
+          }
+        }
+        createdAt
+        comments {
+          totalCount
+        }
+      }
+    }
+  }
+}

webui2/src/index.css ๐Ÿ”—

@@ -0,0 +1,81 @@
+/* highlight.js theme must be imported before any @layer rules (PostCSS requirement) */
+@import 'highlight.js/styles/github.css';
+
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+@layer base {
+  :root {
+    /* zinc palette โ€” clean neutral, GitHub-adjacent */
+    --background: 0 0% 100%;
+    --foreground: 240 10% 3.9%;
+    --card: 0 0% 100%;
+    --card-foreground: 240 10% 3.9%;
+    --popover: 0 0% 100%;
+    --popover-foreground: 240 10% 3.9%;
+    --primary: 240 5.9% 10%;
+    --primary-foreground: 0 0% 98%;
+    --secondary: 240 4.8% 95.9%;
+    --secondary-foreground: 240 5.9% 10%;
+    --muted: 240 4.8% 95.9%;
+    --muted-foreground: 240 3.8% 46.1%;
+    --accent: 240 4.8% 95.9%;
+    --accent-foreground: 240 5.9% 10%;
+    --destructive: 0 84.2% 60.2%;
+    --destructive-foreground: 0 0% 98%;
+    --border: 240 5.9% 90%;
+    --input: 240 5.9% 90%;
+    --ring: 240 5.9% 10%;
+    --radius: 0.375rem;
+  }
+
+  .dark {
+    /* dimmed dark โ€” comfortable grey, not pitch black */
+    --background: 220 13% 13%;
+    --foreground: 220 10% 88%;
+    --card: 220 13% 16%;
+    --card-foreground: 220 10% 88%;
+    --popover: 220 13% 16%;
+    --popover-foreground: 220 10% 88%;
+    --primary: 220 10% 90%;
+    --primary-foreground: 220 13% 11%;
+    --secondary: 220 10% 22%;
+    --secondary-foreground: 220 10% 88%;
+    --muted: 220 10% 22%;
+    --muted-foreground: 220 8% 55%;
+    --accent: 220 10% 22%;
+    --accent-foreground: 220 10% 88%;
+    --destructive: 0 65% 50%;
+    --destructive-foreground: 0 0% 98%;
+    --border: 220 10% 26%;
+    --input: 220 10% 26%;
+    --ring: 220 10% 70%;
+  }
+}
+
+@layer base {
+  * {
+    @apply border-border;
+  }
+  body {
+    @apply bg-background text-foreground;
+  }
+}
+
+/* โ”€โ”€ Dark-mode overrides for highlight.js (imported above) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */
+.dark .hljs {
+  background: hsl(220, 13%, 16%);
+  color: hsl(220, 10%, 85%);
+}
+.dark .hljs-keyword,
+.dark .hljs-selector-tag,
+.dark .hljs-built_in { color: #ff7b72; }
+.dark .hljs-string,
+.dark .hljs-attr { color: #a5d6ff; }
+.dark .hljs-comment { color: hsl(220, 8%, 50%); }
+.dark .hljs-number,
+.dark .hljs-literal { color: #79c0ff; }
+.dark .hljs-title,
+.dark .hljs-name { color: #d2a8ff; }
+.dark .hljs-type { color: #ffa657; }

webui2/src/lib/apollo.ts ๐Ÿ”—

@@ -0,0 +1,19 @@
+import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'
+
+const httpLink = createHttpLink({
+  uri: '/graphql',
+  // include credentials so future httpOnly auth cookies are sent automatically
+  credentials: 'include',
+})
+
+export const client = new ApolloClient({
+  link: httpLink,
+  cache: new InMemoryCache({
+    typePolicies: {
+      // Repository has no id field โ€” treat as a singleton per cache
+      Repository: {
+        keyFields: [],
+      },
+    },
+  }),
+})

webui2/src/lib/auth.tsx ๐Ÿ”—

@@ -0,0 +1,177 @@
+// auth.tsx โ€” authentication context for the webui.
+//
+// Auth has three modes determined by the server's serverConfig.authMode:
+//
+//   local    Single-user mode. The identity is taken from git config at
+//            server startup. No login UI is needed.
+//
+//   oauth    Multi-user mode. Users log in via an OAuth provider. The
+//            current user is fetched from GET /auth/user and can be null
+//            (not logged in) even while the server is running.
+//
+//   readonly No writes allowed. No identity is ever returned.
+//
+// All three modes expose the same AuthContextValue shape, so the rest of the
+// component tree doesn't need to know which mode is active.
+
+import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
+import { gql, useQuery } from '@apollo/client'
+import { useServerConfigQuery } from '@/__generated__/graphql'
+
+// AuthUser matches the Identity type fields we care about for auth purposes.
+export interface AuthUser {
+  id: string
+  humanId: string
+  name: string | null
+  displayName: string
+  avatarUrl: string | null
+  email: string | null
+  login: string | null
+}
+
+// 'local'    โ€” single-user mode, identity from git config
+// 'oauth'    โ€” multi-user mode, identity from OAuth session
+// 'readonly' โ€” no identity, write operations disabled
+export type AuthMode = 'local' | 'oauth' | 'readonly'
+
+export interface AuthContextValue {
+  user: AuthUser | null
+  mode: AuthMode
+  // List of enabled OAuth provider names, e.g. ['github']. Only set in oauth mode.
+  oauthProviders: string[]
+  loading: boolean
+}
+
+const AuthContext = createContext<AuthContextValue>({
+  user: null,
+  mode: 'readonly',
+  oauthProviders: [],
+  loading: true,
+})
+
+// โ”€โ”€ Local mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+const USER_IDENTITY_QUERY = gql`
+  query UserIdentity {
+    repository {
+      userIdentity {
+        id
+        humanId
+        name
+        displayName
+        avatarUrl
+        email
+        login
+      }
+    }
+  }
+`
+
+function LocalAuthProvider({
+  children,
+  oauthProviders,
+}: {
+  children: ReactNode
+  oauthProviders: string[]
+}) {
+  const { data, loading } = useQuery(USER_IDENTITY_QUERY)
+  const user: AuthUser | null = data?.repository?.userIdentity ?? null
+  const mode: AuthMode = loading ? 'local' : user ? 'local' : 'readonly'
+  return (
+    <AuthContext.Provider value={{ user, mode, oauthProviders, loading }}>
+      {children}
+    </AuthContext.Provider>
+  )
+}
+
+// โ”€โ”€ OAuth mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+// OAuthAuthProvider fetches the current user from the REST endpoint that the
+// Go auth handler exposes. A 401 response means "not logged in" (user is null),
+// not an error.
+function OAuthAuthProvider({
+  children,
+  oauthProviders,
+}: {
+  children: ReactNode
+  oauthProviders: string[]
+}) {
+  const [user, setUser] = useState<AuthUser | null>(null)
+  const [loading, setLoading] = useState(true)
+
+  useEffect(() => {
+    fetch('/auth/user', { credentials: 'include' })
+      .then((res) => {
+        if (res.status === 401) return null
+        if (!res.ok) throw new Error(`/auth/user returned ${res.status}`)
+        return res.json() as Promise<AuthUser>
+      })
+      .then((u) => setUser(u))
+      .catch(() => setUser(null))
+      .finally(() => setLoading(false))
+  }, [])
+
+  return (
+    <AuthContext.Provider
+      value={{ user, mode: 'oauth', oauthProviders, loading }}
+    >
+      {children}
+    </AuthContext.Provider>
+  )
+}
+
+// โ”€โ”€ Read-only mode โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+function ReadonlyAuthProvider({ children }: { children: ReactNode }) {
+  return (
+    <AuthContext.Provider
+      value={{ user: null, mode: 'readonly', oauthProviders: [], loading: false }}
+    >
+      {children}
+    </AuthContext.Provider>
+  )
+}
+
+// โ”€โ”€ Root provider โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+// AuthProvider first fetches serverConfig to learn the auth mode, then renders
+// the appropriate sub-provider. The split avoids conditional hook calls.
+export function AuthProvider({ children }: { children: ReactNode }) {
+  const { data, loading } = useServerConfigQuery()
+
+  if (loading || !data) {
+    // Keep the default context (readonly + loading:true) while the config loads.
+    return (
+      <AuthContext.Provider
+        value={{ user: null, mode: 'readonly', oauthProviders: [], loading: true }}
+      >
+        {children}
+      </AuthContext.Provider>
+    )
+  }
+
+  const { authMode, oauthProviders } = data.serverConfig
+
+  if (authMode === 'readonly') {
+    return <ReadonlyAuthProvider>{children}</ReadonlyAuthProvider>
+  }
+
+  if (authMode === 'oauth') {
+    return (
+      <OAuthAuthProvider oauthProviders={oauthProviders}>
+        {children}
+      </OAuthAuthProvider>
+    )
+  }
+
+  // Default: 'local'
+  return (
+    <LocalAuthProvider oauthProviders={oauthProviders}>
+      {children}
+    </LocalAuthProvider>
+  )
+}
+
+export function useAuth(): AuthContextValue {
+  return useContext(AuthContext)
+}

webui2/src/lib/gitApi.ts ๐Ÿ”—

@@ -0,0 +1,92 @@
+// REST API client for git repository browsing.
+// Endpoints are served by the Go backend at /api/git/*.
+
+export interface GitRef {
+  name: string       // full ref: "refs/heads/main"
+  shortName: string  // "main"
+  type: 'branch' | 'tag'
+  hash: string
+  isDefault: boolean
+}
+
+export interface GitTreeEntry {
+  name: string
+  type: 'tree' | 'blob'
+  hash: string
+  mode: string
+  // Last commit touching this entry (may be absent if expensive to compute)
+  lastCommit?: {
+    hash: string
+    shortHash: string
+    message: string
+    authorName: string
+    date: string
+  }
+}
+
+export interface GitBlob {
+  path: string
+  content: string   // UTF-8 text; empty string when isBinary is true
+  size: number
+  isBinary: boolean
+}
+
+export interface GitCommit {
+  hash: string
+  shortHash: string
+  message: string
+  authorName: string
+  authorEmail: string
+  date: string
+  parents: string[]
+}
+
+export interface GitCommitDetail extends GitCommit {
+  fullMessage: string
+  files: Array<{
+    path: string
+    oldPath?: string
+    status: 'added' | 'modified' | 'deleted' | 'renamed'
+  }>
+}
+
+// โ”€โ”€ Fetch helpers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+async function get<T>(path: string, params: Record<string, string> = {}): Promise<T> {
+  const search = new URLSearchParams(params).toString()
+  const url = `/api/git${path}${search ? `?${search}` : ''}`
+  const res = await fetch(url)
+  if (!res.ok) {
+    const text = await res.text().catch(() => res.statusText)
+    throw new Error(text || res.statusText)
+  }
+  return res.json()
+}
+
+// โ”€โ”€ API calls โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
+
+export function getRefs(): Promise<GitRef[]> {
+  return get('/refs')
+}
+
+export function getTree(ref: string, path: string): Promise<GitTreeEntry[]> {
+  return get('/tree', { ref, path })
+}
+
+export function getBlob(ref: string, path: string): Promise<GitBlob> {
+  return get('/blob', { ref, path })
+}
+
+export function getCommits(
+  ref: string,
+  opts: { path?: string; limit?: number; after?: string } = {},
+): Promise<GitCommit[]> {
+  const params: Record<string, string> = { ref, limit: String(opts.limit ?? 20) }
+  if (opts.path) params.path = opts.path
+  if (opts.after) params.after = opts.after
+  return get('/commits', params)
+}
+
+export function getCommit(hash: string): Promise<GitCommitDetail> {
+  return get('/commit', { hash })
+}

webui2/src/lib/repo.tsx ๐Ÿ”—

@@ -0,0 +1,29 @@
+// Provides the current repository slug (the :repo URL segment) to all
+// components rendered inside a /:repo/* route.
+//
+// Usage:
+//   - Wrap the /:repo route subtree with <RepoShell /> as the route element.
+//   - Read the current slug in any child component with useRepo().
+//   - Pass the slug as `ref` to all GraphQL repository queries.
+
+import { createContext, useContext } from 'react'
+import { useParams, Outlet } from 'react-router-dom'
+
+const RepoContext = createContext<string | null>(null)
+
+// Route element for /:repo routes. Reads the :repo param and provides it
+// via context so any descendant can call useRepo() without prop drilling.
+export function RepoShell() {
+  const { repo } = useParams<{ repo: string }>()
+  return (
+    <RepoContext.Provider value={repo ?? null}>
+      <Outlet />
+    </RepoContext.Provider>
+  )
+}
+
+// Returns the current repo slug from the nearest RepoShell ancestor.
+// Returns null when rendered outside of a /:repo route (e.g. the picker page).
+export function useRepo(): string | null {
+  return useContext(RepoContext)
+}

webui2/src/lib/theme.tsx ๐Ÿ”—

@@ -0,0 +1,38 @@
+import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'
+
+type Theme = 'light' | 'dark'
+
+interface ThemeContextValue {
+  theme: Theme
+  toggle: () => void
+}
+
+const ThemeContext = createContext<ThemeContextValue>({
+  theme: 'light',
+  toggle: () => {},
+})
+
+function getInitialTheme(): Theme {
+  const stored = localStorage.getItem('theme')
+  if (stored === 'light' || stored === 'dark') return stored
+  return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
+}
+
+export function ThemeProvider({ children }: { children: ReactNode }) {
+  const [theme, setTheme] = useState<Theme>(getInitialTheme)
+
+  useEffect(() => {
+    document.documentElement.classList.toggle('dark', theme === 'dark')
+    localStorage.setItem('theme', theme)
+  }, [theme])
+
+  function toggle() {
+    setTheme((t) => (t === 'light' ? 'dark' : 'light'))
+  }
+
+  return <ThemeContext.Provider value={{ theme, toggle }}>{children}</ThemeContext.Provider>
+}
+
+export function useTheme() {
+  return useContext(ThemeContext)
+}

webui2/src/lib/utils.ts ๐Ÿ”—

@@ -0,0 +1,6 @@
+import { type ClassValue, clsx } from 'clsx'
+import { twMerge } from 'tailwind-merge'
+
+export function cn(...inputs: ClassValue[]) {
+  return twMerge(clsx(inputs))
+}

webui2/src/main.tsx ๐Ÿ”—

@@ -0,0 +1,20 @@
+import { StrictMode } from 'react'
+import { createRoot } from 'react-dom/client'
+import { ApolloProvider } from '@apollo/client'
+import './index.css'
+import { client } from '@/lib/apollo'
+import { AuthProvider } from '@/lib/auth'
+import { ThemeProvider } from '@/lib/theme'
+import { App } from './App'
+
+createRoot(document.getElementById('root')!).render(
+  <StrictMode>
+    <ThemeProvider>
+      <ApolloProvider client={client}>
+        <AuthProvider>
+          <App />
+        </AuthProvider>
+      </ApolloProvider>
+    </ThemeProvider>
+  </StrictMode>,
+)

webui2/src/pages/BugDetailPage.tsx ๐Ÿ”—

@@ -0,0 +1,134 @@
+import { useParams, Link } from 'react-router-dom'
+import { ArrowLeft } from 'lucide-react'
+import { formatDistanceToNow } from 'date-fns'
+import { Skeleton } from '@/components/ui/skeleton'
+import { Separator } from '@/components/ui/separator'
+import { StatusBadge } from '@/components/bugs/StatusBadge'
+import { LabelEditor } from '@/components/bugs/LabelEditor'
+import { TitleEditor } from '@/components/bugs/TitleEditor'
+import { Timeline } from '@/components/bugs/Timeline'
+import { CommentBox } from '@/components/bugs/CommentBox'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { useBugDetailQuery } from '@/__generated__/graphql'
+import { useRepo } from '@/lib/repo'
+
+// Issue detail page (/:repo/issues/:id). Shows title, status, timeline of
+// comments and events, and a sidebar with labels and participants.
+export function BugDetailPage() {
+  const { id } = useParams<{ id: string }>()
+  const repo = useRepo()
+  const { data, loading, error } = useBugDetailQuery({
+    variables: { ref: repo, prefix: id! },
+  })
+
+  if (error) {
+    return (
+      <div className="py-16 text-center text-sm text-destructive">
+        Failed to load issue: {error.message}
+      </div>
+    )
+  }
+
+  if (loading && !data) {
+    return <BugDetailSkeleton />
+  }
+
+  const bug = data?.repository?.bug
+  if (!bug) {
+    return (
+      <div className="py-16 text-center text-sm text-muted-foreground">Issue not found.</div>
+    )
+  }
+
+  const issuesHref = repo ? `/${repo}/issues` : '/issues'
+  const authorHref = repo ? `/${repo}/user/${bug.author.humanId}` : `/user/${bug.author.humanId}`
+
+  return (
+    <div>
+      <Link
+        to={issuesHref}
+        className="mb-4 flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground"
+      >
+        <ArrowLeft className="size-3.5" />
+        Back to issues
+      </Link>
+
+      {/* Title row โ€” hover reveals edit button when logged in */}
+      <div className="mb-3">
+        <TitleEditor bugPrefix={bug.humanId} title={bug.title} humanId={bug.humanId} ref_={repo} />
+      </div>
+
+      <div className="mb-6 flex flex-wrap items-center gap-3 text-sm text-muted-foreground">
+        <StatusBadge status={bug.status} />
+        <span>
+          <Link to={authorHref} className="font-medium text-foreground hover:underline">
+            {bug.author.displayName}
+          </Link>{' '}
+          opened this issue {formatDistanceToNow(new Date(bug.createdAt), { addSuffix: true })}
+        </span>
+      </div>
+
+      <Separator className="mb-6" />
+
+      <div className="flex gap-8">
+        {/* Timeline + comment box */}
+        <div className="min-w-0 flex-1 space-y-4">
+          <Timeline bugPrefix={bug.humanId} items={bug.timeline.nodes} />
+          <CommentBox bugPrefix={bug.humanId} bugStatus={bug.status} ref_={repo} />
+        </div>
+
+        {/* Sidebar */}
+        <aside className="w-56 shrink-0 space-y-6">
+          <LabelEditor bugPrefix={bug.humanId} currentLabels={bug.labels} ref_={repo} />
+
+          <Separator />
+
+          <div>
+            <h3 className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
+              Participants
+            </h3>
+            <div className="flex flex-wrap gap-1.5">
+              {bug.participants.nodes.map((p) => {
+                const participantHref = repo ? `/${repo}/user/${p.humanId}` : `/user/${p.humanId}`
+                return (
+                  <Link key={p.id} to={participantHref} title={p.displayName}>
+                    <Avatar className="size-6">
+                      <AvatarImage src={p.avatarUrl ?? undefined} alt={p.displayName} />
+                      <AvatarFallback className="text-[10px]">
+                        {p.displayName.slice(0, 2).toUpperCase()}
+                      </AvatarFallback>
+                    </Avatar>
+                  </Link>
+                )
+              })}
+            </div>
+          </div>
+        </aside>
+      </div>
+    </div>
+  )
+}
+
+function BugDetailSkeleton() {
+  return (
+    <div className="space-y-4">
+      <Skeleton className="h-8 w-2/3" />
+      <Skeleton className="h-4 w-1/3" />
+      <Separator />
+      <div className="flex gap-8">
+        <div className="flex-1 space-y-4">
+          {Array.from({ length: 3 }).map((_, i) => (
+            <div key={i} className="rounded-md border border-border p-4">
+              <Skeleton className="mb-3 h-4 w-1/4" />
+              <Skeleton className="h-16 w-full" />
+            </div>
+          ))}
+        </div>
+        <div className="w-56 space-y-3">
+          <Skeleton className="h-4 w-full" />
+          <Skeleton className="h-4 w-3/4" />
+        </div>
+      </div>
+    </div>
+  )
+}

webui2/src/pages/BugListPage.tsx ๐Ÿ”—

@@ -0,0 +1,296 @@
+import { useState, useEffect } from 'react'
+import { CircleDot, CircleCheck, ChevronLeft, ChevronRight } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { Skeleton } from '@/components/ui/skeleton'
+import { BugRow } from '@/components/bugs/BugRow'
+import { IssueFilters } from '@/components/bugs/IssueFilters'
+import { QueryInput } from '@/components/bugs/QueryInput'
+import { useBugListQuery } from '@/__generated__/graphql'
+import { cn } from '@/lib/utils'
+import { useRepo } from '@/lib/repo'
+
+const PAGE_SIZE = 25
+
+type StatusFilter = 'open' | 'closed'
+
+// Issue list page (/:repo/issues). Search bar with structured query, open/closed toggle,
+// label+author filter dropdowns, and paginated bug rows.
+export function BugListPage() {
+  const repo = useRepo()
+  const [statusFilter, setStatusFilter] = useState<StatusFilter>('open')
+  const [selectedLabels, setSelectedLabels] = useState<string[]>([])
+  // humanId โ€” uniquely identifies the selection for the dropdown UI
+  const [selectedAuthorId, setSelectedAuthorId] = useState<string | null>(null)
+  // query value (login/name) โ€” what goes into author:... in the query string
+  const [selectedAuthorQuery, setSelectedAuthorQuery] = useState<string | null>(null)
+  const [freeText, setFreeText] = useState('')
+  const [draft, setDraft] = useState(() => buildQueryString('open', [], null, ''))
+
+  // Cursor-stack pagination: cursors[i] is the `after` value to fetch page i.
+  // cursors[0] is always undefined (first page needs no cursor).
+  const [cursors, setCursors] = useState<(string | undefined)[]>([undefined])
+  const page = cursors.length - 1  // 0-indexed current page
+
+  const query = buildQueryString(statusFilter, selectedLabels, selectedAuthorQuery, freeText)
+
+  const { data, loading, error } = useBugListQuery({
+    variables: { ref: repo, query, first: PAGE_SIZE, after: cursors[page] },
+  })
+
+  const bugs = data?.repository?.allBugs
+  const totalCount = bugs?.totalCount ?? 0
+  const totalPages = Math.max(1, Math.ceil(totalCount / PAGE_SIZE))
+  const hasNext = bugs?.pageInfo.hasNextPage ?? false
+  const hasPrev = page > 0
+
+  // Reset to page 1 whenever the query changes.
+  useEffect(() => { setCursors([undefined]) }, [query])
+
+  // Apply all filters at once, keeping draft in sync with the structured state.
+  function applyFilters(
+    status: StatusFilter,
+    labels: string[],
+    authorId: string | null,
+    authorQuery: string | null,
+    text: string,
+  ) {
+    setStatusFilter(status)
+    setSelectedLabels(labels)
+    setSelectedAuthorId(authorId)
+    setSelectedAuthorQuery(authorQuery)
+    setFreeText(text)
+    setDraft(buildQueryString(status, labels, authorQuery, text))
+  }
+
+  // Parse the draft text box on submit so manual edits update the dropdowns too.
+  // When parsing we don't know the humanId โ€” clear it so the dropdown resets.
+  // Called both from the <form> onSubmit (with event) and from QueryInput's
+  // Enter-key handler (without event), so e is optional.
+  function handleSearch(e?: React.FormEvent) {
+    e?.preventDefault()
+    const p = parseQueryString(draft)
+    applyFilters(p.status, p.labels, null, p.author, p.freeText)
+  }
+
+  function goNext() {
+    const endCursor = bugs?.pageInfo.endCursor
+    if (!endCursor) return
+    setCursors((prev) => [...prev, endCursor])
+  }
+
+  function goPrev() {
+    setCursors((prev) => prev.slice(0, -1))
+  }
+
+  return (
+    <div>
+      {/* Search bar */}
+      <form onSubmit={handleSearch} className="mb-4 flex gap-2">
+        <QueryInput
+          value={draft}
+          onChange={setDraft}
+          onSubmit={handleSearch}
+          placeholder="status:open author:โ€ฆ label:โ€ฆ"
+        />
+        <Button type="submit" variant="outline">
+          Search
+        </Button>
+      </form>
+
+      {/* List container */}
+      <div className="rounded-md border border-border">
+        {/* Open / Closed toggle + filter dropdowns */}
+        <div className="flex items-center border-b border-border px-4 py-2">
+          <div className="flex items-center gap-1">
+            <button
+              onClick={() => applyFilters('open', selectedLabels, selectedAuthorId, selectedAuthorQuery, freeText)}
+              className={cn(
+                'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+                statusFilter === 'open'
+                  ? 'bg-accent text-accent-foreground'
+                  : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
+              )}
+            >
+              <CircleDot className={cn('size-4', statusFilter === 'open' && 'text-green-600 dark:text-green-400')} />
+              Open
+              {bugs && statusFilter === 'open' && (
+                <span className="ml-0.5 rounded-full bg-muted px-1.5 py-0.5 text-xs leading-none">
+                  {bugs.totalCount}
+                </span>
+              )}
+            </button>
+
+            <button
+              onClick={() => applyFilters('closed', selectedLabels, selectedAuthorId, selectedAuthorQuery, freeText)}
+              className={cn(
+                'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+                statusFilter === 'closed'
+                  ? 'bg-accent text-accent-foreground'
+                  : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
+              )}
+            >
+              <CircleCheck className={cn('size-4', statusFilter === 'closed' && 'text-purple-600 dark:text-purple-400')} />
+              Closed
+              {bugs && statusFilter === 'closed' && (
+                <span className="ml-0.5 rounded-full bg-muted px-1.5 py-0.5 text-xs leading-none">
+                  {bugs.totalCount}
+                </span>
+              )}
+            </button>
+          </div>
+
+          <div className="ml-auto">
+            <IssueFilters
+              selectedLabels={selectedLabels}
+              onLabelsChange={(labels) => applyFilters(statusFilter, labels, selectedAuthorId, selectedAuthorQuery, freeText)}
+              selectedAuthorId={selectedAuthorId}
+              onAuthorChange={(id, qv) => applyFilters(statusFilter, selectedLabels, id, qv, freeText)}
+              recentAuthorIds={bugs?.nodes.map((b) => b.author.humanId) ?? []}
+            />
+          </div>
+        </div>
+
+        {/* Bug rows */}
+        {error && (
+          <p className="px-4 py-8 text-center text-sm text-destructive">
+            Failed to load issues: {error.message}
+          </p>
+        )}
+
+        {loading && !data && <BugListSkeleton />}
+
+        {bugs?.nodes.length === 0 && (
+          <p className="px-4 py-8 text-center text-sm text-muted-foreground">
+            No {statusFilter} issues found.
+          </p>
+        )}
+
+        {bugs?.nodes.map((bug) => (
+          <BugRow
+            key={bug.id}
+            id={bug.id}
+            humanId={bug.humanId}
+            status={bug.status}
+            title={bug.title}
+            labels={bug.labels}
+            author={bug.author}
+            createdAt={bug.createdAt}
+            commentCount={bug.comments.totalCount}
+            repo={repo}
+            onLabelClick={(name) => {
+              if (!selectedLabels.includes(name)) {
+                applyFilters(statusFilter, [...selectedLabels, name], selectedAuthorId, selectedAuthorQuery, freeText)
+              }
+            }}
+          />
+        ))}
+
+        {totalPages > 1 && (
+          <div className="flex items-center justify-center gap-2 border-t border-border px-4 py-2">
+            <Button
+              variant="ghost"
+              size="sm"
+              onClick={goPrev}
+              disabled={!hasPrev || loading}
+              className="gap-1 text-muted-foreground"
+            >
+              <ChevronLeft className="size-4" />
+              Previous
+            </Button>
+            <span className="text-sm text-muted-foreground">
+              Page {page + 1} of {totalPages}
+            </span>
+            <Button
+              variant="ghost"
+              size="sm"
+              onClick={goNext}
+              disabled={!hasNext || loading}
+              className="gap-1 text-muted-foreground"
+            >
+              Next
+              <ChevronRight className="size-4" />
+            </Button>
+          </div>
+        )}
+      </div>
+    </div>
+  )
+}
+
+// Build the structured query string sent to the GraphQL allBugs(query:) argument.
+// Multi-word label/author values are wrapped in quotes so the backend parser
+// treats them as a single token (e.g. label:"my label" vs label:my label).
+function buildQueryString(
+  status: StatusFilter,
+  labels: string[],
+  author: string | null,
+  freeText: string,
+): string {
+  const parts = [`status:${status}`]
+  for (const label of labels) {
+    parts.push(label.includes(' ') ? `label:"${label}"` : `label:${label}`)
+  }
+  if (author) {
+    parts.push(author.includes(' ') ? `author:"${author}"` : `author:${author}`)
+  }
+  if (freeText.trim()) parts.push(freeText.trim())
+  return parts.join(' ')
+}
+
+// Tokenize a query string, keeping quoted spans (e.g. author:"Renรฉ Descartes")
+// as single tokens. Quotes are preserved in the output so callers can strip them
+// when extracting values.
+function tokenizeQuery(input: string): string[] {
+  const tokens: string[] = []
+  let current = ''
+  let inQuote = false
+  for (const ch of input.trim()) {
+    if (ch === '"') { inQuote = !inQuote; current += ch }
+    else if (ch === ' ' && !inQuote) { if (current) { tokens.push(current); current = '' } }
+    else current += ch
+  }
+  if (current) tokens.push(current)
+  return tokens
+}
+
+// Parse a free-text query string back into structured filter state so that
+// manual edits to the search box are reflected in the dropdown UI on submit.
+// Strips surrounding quotes from values (they're an encoding detail, not part
+// of the value itself). Unknown tokens fall through to freeText.
+function parseQueryString(input: string): {
+  status: StatusFilter
+  labels: string[]
+  author: string | null
+  freeText: string
+} {
+  let status: StatusFilter = 'open'
+  const labels: string[] = []
+  let author: string | null = null
+  const free: string[] = []
+
+  for (const token of tokenizeQuery(input)) {
+    if (token === 'status:open') status = 'open'
+    else if (token === 'status:closed') status = 'closed'
+    else if (token.startsWith('label:')) labels.push(token.slice(6))
+    else if (token.startsWith('author:')) author = token.slice(7).replace(/^"|"$/g, '')
+    else free.push(token)
+  }
+
+  return { status, labels, author, freeText: free.join(' ') }
+}
+
+function BugListSkeleton() {
+  return (
+    <div className="divide-y divide-border">
+      {Array.from({ length: 8 }).map((_, i) => (
+        <div key={i} className="flex items-start gap-3 px-4 py-3">
+          <Skeleton className="mt-0.5 size-4 rounded-full" />
+          <div className="flex-1 space-y-2">
+            <Skeleton className="h-4 w-2/3" />
+            <Skeleton className="h-3 w-1/3" />
+          </div>
+        </div>
+      ))}
+    </div>
+  )
+}

webui2/src/pages/CodePage.tsx ๐Ÿ”—

@@ -0,0 +1,179 @@
+import { useState, useEffect } from 'react'
+import { useSearchParams } from 'react-router-dom'
+import { gql, useQuery } from '@apollo/client'
+import { AlertCircle, GitCommit } from 'lucide-react'
+import { CodeBreadcrumb } from '@/components/code/CodeBreadcrumb'
+import { RefSelector } from '@/components/code/RefSelector'
+import { FileTree } from '@/components/code/FileTree'
+import { FileViewer } from '@/components/code/FileViewer'
+import { CommitList } from '@/components/code/CommitList'
+import { Skeleton } from '@/components/ui/skeleton'
+import { Button } from '@/components/ui/button'
+import { getRefs, getTree, getBlob } from '@/lib/gitApi'
+import type { GitRef, GitTreeEntry, GitBlob } from '@/lib/gitApi'
+import { useRepo } from '@/lib/repo'
+
+const REPO_NAME_QUERY = gql`
+  query RepoName($ref: String) {
+    repository(ref: $ref) {
+      name
+    }
+  }
+`
+
+type ViewMode = 'tree' | 'blob' | 'commits'
+
+// Code browser page (/:repo). Switches between tree view, file viewer, and
+// commit history via the ?type= search param. Ref is selected via ?ref=.
+export function CodePage() {
+  const repo = useRepo()
+  const [searchParams, setSearchParams] = useSearchParams()
+
+  const [refs, setRefs] = useState<GitRef[]>([])
+  const [refsLoading, setRefsLoading] = useState(true)
+  const [error, setError] = useState<string | null>(null)
+
+  const [entries, setEntries] = useState<GitTreeEntry[]>([])
+  const [blob, setBlob] = useState<GitBlob | null>(null)
+  const [contentLoading, setContentLoading] = useState(false)
+
+  const currentRef = searchParams.get('ref') ?? ''
+  const currentPath = searchParams.get('path') ?? ''
+  const viewMode: ViewMode = (searchParams.get('type') as ViewMode) ?? 'tree'
+
+  // Load refs once on mount
+  useEffect(() => {
+    getRefs()
+      .then((data) => {
+        setRefs(data)
+        // If no ref in URL yet, use the default branch
+        if (!searchParams.get('ref')) {
+          const defaultRef = data.find((r) => r.isDefault) ?? data[0]
+          if (defaultRef) {
+            setSearchParams(
+              (prev) => { prev.set('ref', defaultRef.shortName); return prev },
+              { replace: true },
+            )
+          }
+        }
+      })
+      .catch((e: Error) => setError(e.message))
+      .finally(() => setRefsLoading(false))
+  }, []) // eslint-disable-line react-hooks/exhaustive-deps
+
+  // Load tree or blob when ref/path/mode changes
+  useEffect(() => {
+    if (!currentRef) return
+    setContentLoading(true)
+    setEntries([])
+    setBlob(null)
+
+    const load =
+      viewMode === 'blob'
+        ? getBlob(currentRef, currentPath).then((b) => setBlob(b))
+        : getTree(currentRef, currentPath).then((e) => setEntries(e))
+
+    load
+      .catch((e: Error) => setError(e.message))
+      .finally(() => setContentLoading(false))
+  }, [currentRef, currentPath, viewMode])
+
+  function navigate(path: string, type: ViewMode = 'tree') {
+    setSearchParams((prev) => {
+      prev.set('path', path)
+      prev.set('type', type)
+      return prev
+    })
+  }
+
+  function handleEntryClick(entry: GitTreeEntry) {
+    const newPath = currentPath ? `${currentPath}/${entry.name}` : entry.name
+    navigate(newPath, entry.type === 'blob' ? 'blob' : 'tree')
+  }
+
+  function handleNavigateUp() {
+    const parts = currentPath.split('/').filter(Boolean)
+    parts.pop()
+    navigate(parts.join('/'), 'tree')
+  }
+
+  function handleRefSelect(ref: GitRef) {
+    setSearchParams((prev) => {
+      prev.set('ref', ref.shortName)
+      prev.set('path', '')
+      prev.set('type', 'tree')
+      return prev
+    })
+  }
+
+  const { data: repoData } = useQuery(REPO_NAME_QUERY, { variables: { ref: repo } })
+  const repoName = repoData?.repository?.name ?? repo ?? 'git-bug'
+
+  if (error) {
+    return (
+      <div className="flex flex-col items-center gap-3 py-16 text-center">
+        <AlertCircle className="size-8 text-muted-foreground" />
+        <p className="text-sm font-medium">Code browser unavailable</p>
+        <p className="max-w-sm text-xs text-muted-foreground">{error}</p>
+        <p className="max-w-sm text-xs text-muted-foreground">
+          Make sure the git-bug server is running and the repository supports code browsing.
+        </p>
+      </div>
+    )
+  }
+
+  return (
+    <div className="space-y-4">
+      {/* Top bar: breadcrumb + ref selector */}
+      <div className="flex flex-wrap items-center justify-between gap-3">
+        {refsLoading ? (
+          <Skeleton className="h-5 w-48" />
+        ) : (
+          <CodeBreadcrumb
+            repoName={repoName}
+            ref={currentRef}
+            path={currentPath}
+            onNavigate={(p) => navigate(p, 'tree')}
+          />
+        )}
+        <div className="flex items-center gap-2">
+          {!refsLoading && (
+            <Button
+              variant={viewMode === 'commits' ? 'secondary' : 'outline'}
+              size="sm"
+              onClick={() =>
+                navigate(
+                  currentPath,
+                  viewMode === 'commits' ? 'tree' : 'commits',
+                )
+              }
+            >
+              <GitCommit className="size-3.5" />
+              History
+            </Button>
+          )}
+          {refsLoading ? (
+            <Skeleton className="h-8 w-28" />
+          ) : (
+            <RefSelector refs={refs} currentRef={currentRef} onSelect={handleRefSelect} />
+          )}
+        </div>
+      </div>
+
+      {/* Content */}
+      {viewMode === 'commits' ? (
+        <CommitList ref_={currentRef} path={currentPath || undefined} />
+      ) : viewMode === 'tree' || !blob ? (
+        <FileTree
+          entries={entries}
+          path={currentPath}
+          loading={contentLoading}
+          onNavigate={handleEntryClick}
+          onNavigateUp={handleNavigateUp}
+        />
+      ) : (
+        <FileViewer blob={blob} loading={contentLoading} />
+      )}
+    </div>
+  )
+}

webui2/src/pages/CommitPage.tsx ๐Ÿ”—

@@ -0,0 +1,165 @@
+import { useState, useEffect } from 'react'
+import { Link, useParams, useNavigate } from 'react-router-dom'
+import { format } from 'date-fns'
+import { ArrowLeft, FilePlus, FileMinus, FileEdit, GitCommit } from 'lucide-react'
+import { Skeleton } from '@/components/ui/skeleton'
+import { getCommit } from '@/lib/gitApi'
+import type { GitCommitDetail } from '@/lib/gitApi'
+import { useRepo } from '@/lib/repo'
+
+const statusIcon = {
+  added:    <FilePlus className="size-4 text-green-600 dark:text-green-400" />,
+  deleted:  <FileMinus className="size-4 text-red-500 dark:text-red-400" />,
+  modified: <FileEdit className="size-4 text-yellow-500 dark:text-yellow-400" />,
+  renamed:  <FileEdit className="size-4 text-blue-500 dark:text-blue-400" />,
+}
+
+const statusLabel = {
+  added: 'A', deleted: 'D', modified: 'M', renamed: 'R',
+}
+
+// Commit detail page (/:repo/commit/:hash). Shows commit metadata, full message,
+// parent links, and the list of files changed with add/modify/delete/rename status.
+export function CommitPage() {
+  const { hash } = useParams<{ hash: string }>()
+  const navigate = useNavigate()
+  const repo = useRepo()
+  const [commit, setCommit] = useState<GitCommitDetail | null>(null)
+  const [loading, setLoading] = useState(true)
+  const [error, setError] = useState<string | null>(null)
+
+  useEffect(() => {
+    setLoading(true)
+    setError(null)
+    getCommit(hash!)
+      .then(setCommit)
+      .catch((e: Error) => setError(e.message))
+      .finally(() => setLoading(false))
+  }, [hash])
+
+  if (loading) return <CommitPageSkeleton />
+
+  if (error) {
+    return (
+      <div className="py-16 text-center text-sm text-destructive">
+        Failed to load commit: {error}
+      </div>
+    )
+  }
+
+  if (!commit) return null
+
+  const date = new Date(commit.date)
+
+  return (
+    <div>
+      <button
+        onClick={() => navigate(-1)}
+        className="mb-6 flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground"
+      >
+        <ArrowLeft className="size-3.5" />
+        Back
+      </button>
+
+      {/* Header */}
+      <div className="mb-6 rounded-md border border-border p-5">
+        <div className="mb-1 flex items-start gap-3">
+          <GitCommit className="mt-1 size-5 shrink-0 text-muted-foreground" />
+          <h1 className="text-lg font-semibold leading-snug">{commit.message}</h1>
+        </div>
+
+        {/* Full message body (if multi-line) */}
+        {commit.fullMessage.includes('\n') && (
+          <pre className="mb-4 ml-8 mt-3 whitespace-pre-wrap font-sans text-sm text-muted-foreground">
+            {commit.fullMessage.split('\n').slice(1).join('\n').trim()}
+          </pre>
+        )}
+
+        <div className="ml-8 mt-3 flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted-foreground">
+          <span>
+            <span className="font-medium text-foreground">{commit.authorName}</span>
+            {commit.authorEmail && (
+              <span> &lt;{commit.authorEmail}&gt;</span>
+            )}
+          </span>
+          <span title={date.toISOString()}>{format(date, 'PPP')}</span>
+        </div>
+
+        <div className="ml-8 mt-3 flex flex-wrap gap-3 text-xs">
+          <span className="text-muted-foreground">
+            commit{' '}
+            <code className="font-mono text-foreground">{commit.hash}</code>
+          </span>
+          {commit.parents.map((p) => (
+            <span key={p} className="text-muted-foreground">
+              parent{' '}
+              <Link
+                to={repo ? `/${repo}/commit/${p}` : `/commit/${p}`}
+                className="font-mono text-foreground hover:underline"
+              >
+                {p.slice(0, 7)}
+              </Link>
+            </span>
+          ))}
+        </div>
+      </div>
+
+      {/* Changed files */}
+      <div>
+        <h2 className="mb-3 text-sm font-semibold text-muted-foreground">
+          {commit.files.length} file{commit.files.length !== 1 ? 's' : ''} changed
+        </h2>
+        <div className="overflow-hidden rounded-md border border-border divide-y divide-border">
+          {commit.files.length === 0 && (
+            <p className="px-4 py-4 text-sm text-muted-foreground">No file changes.</p>
+          )}
+          {commit.files.map((file) => (
+            <div key={file.path} className="flex items-center gap-3 px-4 py-2.5">
+              <span
+                className="w-4 shrink-0 text-center font-mono text-xs font-bold"
+                title={file.status}
+              >
+                {statusIcon[file.status]}
+              </span>
+              <span className="min-w-0 flex-1 font-mono text-sm">
+                {file.status === 'renamed' ? (
+                  <>
+                    <span className="text-muted-foreground line-through">{file.oldPath}</span>
+                    {' โ†’ '}
+                    <span>{file.path}</span>
+                  </>
+                ) : (
+                  file.path
+                )}
+              </span>
+              <span className="shrink-0 rounded border border-border px-1.5 py-0.5 font-mono text-xs text-muted-foreground">
+                {statusLabel[file.status]}
+              </span>
+            </div>
+          ))}
+        </div>
+      </div>
+    </div>
+  )
+}
+
+function CommitPageSkeleton() {
+  return (
+    <div className="space-y-6">
+      <Skeleton className="h-4 w-24" />
+      <div className="rounded-md border border-border p-5 space-y-3">
+        <Skeleton className="h-6 w-3/4" />
+        <Skeleton className="h-4 w-1/3" />
+        <Skeleton className="h-3 w-1/2" />
+      </div>
+      <div className="rounded-md border border-border divide-y divide-border">
+        {Array.from({ length: 5 }).map((_, i) => (
+          <div key={i} className="flex items-center gap-3 px-4 py-2.5">
+            <Skeleton className="size-4" />
+            <Skeleton className="h-4 flex-1" />
+          </div>
+        ))}
+      </div>
+    </div>
+  )
+}

webui2/src/pages/IdentitySelectPage.tsx ๐Ÿ”—

@@ -0,0 +1,124 @@
+// Identity selection page (/_/auth/select-identity).
+//
+// Reached after a successful OAuth login when no existing git-bug identity
+// could be matched automatically (via provider metadata set by the bridge).
+// The user can either adopt an existing identity โ€” which links it to their
+// OAuth account for future logins โ€” or create a fresh one from their OAuth
+// profile.
+
+import { useEffect, useState } from 'react'
+import { useNavigate } from 'react-router-dom'
+import { UserCircle, Plus, AlertCircle } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { Skeleton } from '@/components/ui/skeleton'
+
+interface IdentityItem {
+  repoSlug: string
+  id: string
+  humanId: string
+  displayName: string
+  login?: string
+  avatarUrl?: string
+}
+
+export function IdentitySelectPage() {
+  const navigate = useNavigate()
+  const [identities, setIdentities] = useState<IdentityItem[] | null>(null)
+  const [error, setError] = useState<string | null>(null)
+  const [working, setWorking] = useState(false)
+
+  useEffect(() => {
+    fetch('/auth/identities', { credentials: 'include' })
+      .then((res) => {
+        if (!res.ok) throw new Error(`unexpected status ${res.status}`)
+        return res.json() as Promise<IdentityItem[]>
+      })
+      .then(setIdentities)
+      .catch((e) => setError(String(e)))
+  }, [])
+
+  async function adopt(identityId: string | null) {
+    setWorking(true)
+    try {
+      const res = await fetch('/auth/adopt', {
+        method: 'POST',
+        credentials: 'include',
+        headers: { 'Content-Type': 'application/json' },
+        body: JSON.stringify(identityId ? { identityId } : {}),
+      })
+      if (!res.ok) throw new Error(`adopt failed: ${res.status}`)
+      // Full page reload to reset Apollo cache and auth state cleanly.
+      window.location.assign('/')
+    } catch (e) {
+      setError(String(e))
+      setWorking(false)
+    }
+  }
+
+  return (
+    <div className="mx-auto max-w-lg py-12">
+      <div className="mb-2 flex items-center gap-3">
+        <UserCircle className="size-6 text-muted-foreground" />
+        <h1 className="text-xl font-semibold">Choose your identity</h1>
+      </div>
+      <p className="mb-8 text-sm text-muted-foreground">
+        No git-bug identity was found linked to your account. Select an
+        existing identity to link it, or create a new one from your profile.
+      </p>
+
+      {error && (
+        <div className="mb-4 flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-4 py-3 text-sm text-destructive">
+          <AlertCircle className="size-4 shrink-0" />
+          {error}
+        </div>
+      )}
+
+      {!identities && !error && (
+        <div className="space-y-2">
+          {Array.from({ length: 3 }).map((_, i) => (
+            <Skeleton key={i} className="h-14 w-full rounded-md" />
+          ))}
+        </div>
+      )}
+
+      <div className="divide-y divide-border rounded-md border border-border">
+        {identities?.map((id) => (
+          <div key={id.id} className="flex items-center gap-3 px-4 py-3">
+            <div className="min-w-0 flex-1">
+              <p className="font-medium">{id.displayName}</p>
+              <p className="text-xs text-muted-foreground">
+                {id.login ? `@${id.login} ยท ` : ''}{id.repoSlug} ยท {id.humanId}
+              </p>
+            </div>
+            <Button
+              size="sm"
+              variant="outline"
+              disabled={working}
+              onClick={() => adopt(id.id)}
+            >
+              Adopt
+            </Button>
+          </div>
+        ))}
+
+        {/* Always offer to create a new identity */}
+        <div className="flex items-center gap-3 px-4 py-3">
+          <div className="min-w-0 flex-1">
+            <p className="font-medium">Create new identity</p>
+            <p className="text-xs text-muted-foreground">
+              A fresh git-bug identity will be created from your OAuth profile.
+            </p>
+          </div>
+          <Button
+            size="sm"
+            disabled={working}
+            onClick={() => adopt(null)}
+          >
+            <Plus className="size-4" />
+            Create
+          </Button>
+        </div>
+      </div>
+    </div>
+  )
+}

webui2/src/pages/NewBugPage.tsx ๐Ÿ”—

@@ -0,0 +1,118 @@
+import { useState } from 'react'
+import { useNavigate, Link } from 'react-router-dom'
+import { ArrowLeft } from 'lucide-react'
+import { Button } from '@/components/ui/button'
+import { Input } from '@/components/ui/input'
+import { Textarea } from '@/components/ui/textarea'
+import { Markdown } from '@/components/content/Markdown'
+import { useBugCreateMutation } from '@/__generated__/graphql'
+import { useRepo } from '@/lib/repo'
+
+// New issue form (/:repo/issues/new). Title + body with write/preview tabs.
+export function NewBugPage() {
+  const navigate = useNavigate()
+  const repo = useRepo()
+  const [title, setTitle] = useState('')
+  const [message, setMessage] = useState('')
+  const [preview, setPreview] = useState(false)
+
+  const [createBug, { loading, error }] = useBugCreateMutation()
+
+  async function handleSubmit(e: React.FormEvent) {
+    e.preventDefault()
+    if (!title.trim()) return
+    const result = await createBug({
+      variables: { input: { title: title.trim(), message: message.trim() } },
+    })
+    const humanId = result.data?.bugCreate.bug.humanId
+    if (humanId) {
+      navigate(repo ? `/${repo}/issues/${humanId}` : `/issues/${humanId}`)
+    }
+  }
+
+  const issuesHref = repo ? `/${repo}/issues` : '/issues'
+
+  return (
+    <div className="mx-auto max-w-3xl">
+      <Link
+        to={issuesHref}
+        className="mb-6 flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground"
+      >
+        <ArrowLeft className="size-3.5" />
+        Back to issues
+      </Link>
+
+      <h1 className="mb-6 text-xl font-semibold">New issue</h1>
+
+      <form onSubmit={handleSubmit} className="space-y-4">
+        <div>
+          <label htmlFor="title" className="mb-1.5 block text-sm font-medium">
+            Title
+          </label>
+          <Input
+            id="title"
+            placeholder="Brief description of the issue"
+            value={title}
+            onChange={(e) => setTitle(e.target.value)}
+            required
+            disabled={loading}
+          />
+        </div>
+
+        <div>
+          <div className="mb-1.5 flex items-center justify-between">
+            <label className="text-sm font-medium">Description</label>
+            <div className="flex gap-1 text-sm">
+              <button
+                type="button"
+                onClick={() => setPreview(false)}
+                className={`rounded px-2 py-0.5 transition-colors ${
+                  !preview ? 'bg-muted font-medium' : 'text-muted-foreground hover:text-foreground'
+                }`}
+              >
+                Write
+              </button>
+              <button
+                type="button"
+                onClick={() => setPreview(true)}
+                disabled={!message.trim()}
+                className={`rounded px-2 py-0.5 transition-colors disabled:opacity-40 ${
+                  preview ? 'bg-muted font-medium' : 'text-muted-foreground hover:text-foreground'
+                }`}
+              >
+                Preview
+              </button>
+            </div>
+          </div>
+
+          {preview ? (
+            <div className="min-h-[200px] rounded-md border border-input px-3 py-2">
+              <Markdown content={message} />
+            </div>
+          ) : (
+            <Textarea
+              placeholder="Describe the issue in detailโ€ฆ"
+              className="min-h-[200px]"
+              value={message}
+              onChange={(e) => setMessage(e.target.value)}
+              disabled={loading}
+            />
+          )}
+        </div>
+
+        {error && (
+          <p className="text-sm text-destructive">Failed to create issue: {error.message}</p>
+        )}
+
+        <div className="flex justify-end gap-2">
+          <Button type="button" variant="ghost" onClick={() => navigate(issuesHref)} disabled={loading}>
+            Cancel
+          </Button>
+          <Button type="submit" disabled={!title.trim() || loading}>
+            {loading ? 'Creatingโ€ฆ' : 'Submit new issue'}
+          </Button>
+        </div>
+      </form>
+    </div>
+  )
+}

webui2/src/pages/RepoPickerPage.tsx ๐Ÿ”—

@@ -0,0 +1,55 @@
+// Repository picker page (/). Shows all registered repos and lets the user
+// navigate into one. When there is only one repo, the list still renders
+// (no auto-redirect) so the user always knows which repo they're entering.
+
+import { Link } from 'react-router-dom'
+import { GitFork, FolderOpen, AlertCircle } from 'lucide-react'
+import { Skeleton } from '@/components/ui/skeleton'
+import { useRepositoriesQuery } from '@/__generated__/graphql'
+
+export function RepoPickerPage() {
+  const { data, loading, error } = useRepositoriesQuery()
+
+  return (
+    <div className="mx-auto max-w-lg py-12">
+      <div className="mb-8 flex items-center gap-3">
+        <GitFork className="size-6 text-muted-foreground" />
+        <h1 className="text-xl font-semibold">Repositories</h1>
+      </div>
+
+      {error && (
+        <div className="flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/10 px-4 py-3 text-sm text-destructive">
+          <AlertCircle className="size-4 shrink-0" />
+          Failed to load repositories: {error.message}
+        </div>
+      )}
+
+      {loading && !data && (
+        <div className="space-y-2">
+          {Array.from({ length: 3 }).map((_, i) => (
+            <Skeleton key={i} className="h-16 w-full rounded-md" />
+          ))}
+        </div>
+      )}
+
+      <div className="divide-y divide-border rounded-md border border-border">
+        {data?.repositories.nodes.map((repo) => (
+          <Link
+            key={repo.slug}
+            to={`/${repo.slug}`}
+            className="flex items-center gap-3 px-4 py-4 hover:bg-muted/50 transition-colors"
+          >
+            <FolderOpen className="size-5 shrink-0 text-muted-foreground" />
+            <p className="font-medium text-foreground">{repo.slug}</p>
+          </Link>
+        ))}
+
+        {data?.repositories.totalCount === 0 && (
+          <p className="px-4 py-8 text-center text-sm text-muted-foreground">
+            No repositories found.
+          </p>
+        )}
+      </div>
+    </div>
+  )
+}

webui2/src/pages/UserProfilePage.tsx ๐Ÿ”—

@@ -0,0 +1,278 @@
+// User profile page (/user/:id). Fetches an identity by prefix and shows:
+//   - avatar, display name, login, email, humanId, protected badge
+//   - open/closed issue toggle with BOTH counts always visible
+//   - paginated list of that user's bugs (cursor-stack, same approach as BugListPage)
+//
+// The :id param is treated as a humanId prefix and passed directly to the
+// identity(prefix) and allBugs(query:"author:...") GraphQL arguments.
+
+import { useState } from 'react'
+import { useParams, Link } from 'react-router-dom'
+import { formatDistanceToNow } from 'date-fns'
+import {
+  ArrowLeft, MessageSquare, CircleDot, CircleCheck, ShieldCheck,
+  ChevronLeft, ChevronRight,
+} from 'lucide-react'
+import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
+import { Button } from '@/components/ui/button'
+import { Skeleton } from '@/components/ui/skeleton'
+import { LabelBadge } from '@/components/bugs/LabelBadge'
+import { cn } from '@/lib/utils'
+import { Status, useUserProfileQuery } from '@/__generated__/graphql'
+import { useRepo } from '@/lib/repo'
+
+const PAGE_SIZE = 25
+
+export function UserProfilePage() {
+  const { id } = useParams<{ id: string }>()
+  const repo = useRepo()
+  const [statusFilter, setStatusFilter] = useState<'open' | 'closed'>('open')
+
+  // Cursor-stack pagination: cursors[i] is the `after` value to fetch page i.
+  // Resetting to [undefined] returns to page 1. Shared pattern with BugListPage.
+  const [cursors, setCursors] = useState<(string | undefined)[]>([undefined])
+  const page = cursors.length - 1
+
+  // Three allBugs aliases in one round-trip:
+  //   openCount / closedCount โ€” always fetched so both badge numbers are visible
+  //   bugs โ€” paginated list for the selected tab
+  const { data, loading, error } = useUserProfileQuery({
+    variables: {
+      ref: repo,
+      prefix: id!,
+      openQuery: `author:${id} status:open`,
+      closedQuery: `author:${id} status:closed`,
+      listQuery: `author:${id} status:${statusFilter}`,
+      after: cursors[page],
+    },
+  })
+
+  function switchStatus(next: 'open' | 'closed') {
+    if (next === statusFilter) return
+    setStatusFilter(next)
+    setCursors([undefined]) // reset to page 1 on tab change
+  }
+
+  if (error) {
+    return (
+      <div className="py-16 text-center text-sm text-destructive">
+        Failed to load profile: {error.message}
+      </div>
+    )
+  }
+
+  if (loading && !data) return <ProfileSkeleton />
+
+  const identity = data?.repository?.identity
+  if (!identity) {
+    return (
+      <div className="py-16 text-center text-sm text-muted-foreground">User not found.</div>
+    )
+  }
+
+  const openCount = data?.repository?.openCount.totalCount ?? 0
+  const closedCount = data?.repository?.closedCount.totalCount ?? 0
+
+  const bugs = data?.repository?.bugs
+  const totalPages = Math.max(1, Math.ceil((bugs?.totalCount ?? 0) / PAGE_SIZE))
+  const hasNext = bugs?.pageInfo.hasNextPage ?? false
+  const hasPrev = page > 0
+
+  function goNext() {
+    const cursor = bugs?.pageInfo.endCursor
+    if (cursor) setCursors((prev) => [...prev, cursor])
+  }
+
+  function goPrev() {
+    setCursors((prev) => prev.slice(0, -1))
+  }
+
+  const issuesHref = repo ? `/${repo}/issues` : '/issues'
+
+  return (
+    <div>
+      <Link
+        to={issuesHref}
+        className="mb-6 flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground"
+      >
+        <ArrowLeft className="size-3.5" />
+        Back to issues
+      </Link>
+
+      {/* โ”€โ”€ Profile header โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */}
+      <div className="mb-8 flex items-start gap-5">
+        <Avatar className="size-20">
+          <AvatarImage src={identity.avatarUrl ?? undefined} alt={identity.displayName} />
+          <AvatarFallback className="text-2xl">
+            {identity.displayName.slice(0, 2).toUpperCase()}
+          </AvatarFallback>
+        </Avatar>
+
+        <div className="pt-1">
+          <div className="flex items-center gap-2">
+            <h1 className="text-xl font-semibold">{identity.displayName}</h1>
+            {/* isProtected means this identity has been cryptographically signed */}
+            {identity.isProtected && (
+              <span title="Protected identity">
+                <ShieldCheck className="size-4 text-muted-foreground" />
+              </span>
+            )}
+          </div>
+          <div className="mt-1 space-y-0.5 text-sm text-muted-foreground">
+            {identity.login && <p>@{identity.login}</p>}
+            {identity.email && <p>{identity.email}</p>}
+            <p className="font-mono text-xs">#{identity.humanId}</p>
+          </div>
+
+          {/* Aggregate stats โ€” always visible, independent of selected tab */}
+          <div className="mt-3 flex items-center gap-4 text-sm">
+            <span className="flex items-center gap-1 text-muted-foreground">
+              <CircleDot className="size-3.5 text-green-600 dark:text-green-400" />
+              <span className="font-medium text-foreground">{openCount}</span> open
+            </span>
+            <span className="flex items-center gap-1 text-muted-foreground">
+              <CircleCheck className="size-3.5 text-purple-600 dark:text-purple-400" />
+              <span className="font-medium text-foreground">{closedCount}</span> closed
+            </span>
+          </div>
+        </div>
+      </div>
+
+      {/* โ”€โ”€ Issue list โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ */}
+      <div className="rounded-md border border-border">
+        {/* Open / Closed toggle โ€” mirrors BugListPage style */}
+        <div className="flex items-center gap-1 border-b border-border px-4 py-2">
+          <button
+            onClick={() => switchStatus('open')}
+            className={cn(
+              'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+              statusFilter === 'open'
+                ? 'bg-accent text-accent-foreground'
+                : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
+            )}
+          >
+            <CircleDot className={cn('size-4', statusFilter === 'open' && 'text-green-600 dark:text-green-400')} />
+            Open
+            <span className="ml-0.5 rounded-full bg-muted px-1.5 py-0.5 text-xs leading-none">
+              {openCount}
+            </span>
+          </button>
+
+          <button
+            onClick={() => switchStatus('closed')}
+            className={cn(
+              'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-sm font-medium transition-colors',
+              statusFilter === 'closed'
+                ? 'bg-accent text-accent-foreground'
+                : 'text-muted-foreground hover:bg-accent/50 hover:text-foreground',
+            )}
+          >
+            <CircleCheck className={cn('size-4', statusFilter === 'closed' && 'text-purple-600 dark:text-purple-400')} />
+            Closed
+            <span className="ml-0.5 rounded-full bg-muted px-1.5 py-0.5 text-xs leading-none">
+              {closedCount}
+            </span>
+          </button>
+        </div>
+
+        {bugs?.nodes.length === 0 && (
+          <p className="px-4 py-8 text-center text-sm text-muted-foreground">
+            No {statusFilter} issues.
+          </p>
+        )}
+
+        {bugs?.nodes.map((bug) => {
+          const isOpen = bug.status === Status.Open
+          const StatusIcon = isOpen ? CircleDot : CircleCheck
+          return (
+            <div
+              key={bug.id}
+              className="flex items-start gap-3 border-b border-border px-4 py-3 last:border-0"
+            >
+              <StatusIcon
+                className={cn(
+                  'mt-0.5 size-4 shrink-0',
+                  isOpen
+                    ? 'text-green-600 dark:text-green-400'
+                    : 'text-purple-600 dark:text-purple-400',
+                )}
+              />
+              <div className="min-w-0 flex-1">
+                <div className="flex flex-wrap items-baseline gap-2">
+                  <Link
+                    to={repo ? `/${repo}/issues/${bug.humanId}` : `/issues/${bug.humanId}`}
+                    className="font-medium text-foreground hover:text-primary hover:underline"
+                  >
+                    {bug.title}
+                  </Link>
+                  {bug.labels.map((label) => (
+                    <LabelBadge key={label.name} name={label.name} color={label.color} />
+                  ))}
+                </div>
+                <p className="mt-0.5 text-xs text-muted-foreground">
+                  #{bug.humanId} opened{' '}
+                  {formatDistanceToNow(new Date(bug.createdAt), { addSuffix: true })}
+                </p>
+              </div>
+              {bug.comments.totalCount > 0 && (
+                <div className="flex shrink-0 items-center gap-1 text-xs text-muted-foreground">
+                  <MessageSquare className="size-3.5" />
+                  {bug.comments.totalCount}
+                </div>
+              )}
+            </div>
+          )
+        })}
+
+        {/* Pagination footer โ€” only shown when there is more than one page */}
+        {totalPages > 1 && (
+          <div className="flex items-center justify-center gap-2 border-t border-border px-4 py-2">
+            <Button
+              variant="ghost"
+              size="sm"
+              onClick={goPrev}
+              disabled={!hasPrev || loading}
+              className="gap-1 text-muted-foreground"
+            >
+              <ChevronLeft className="size-4" />
+              Previous
+            </Button>
+            <span className="text-sm text-muted-foreground">
+              Page {page + 1} of {totalPages}
+            </span>
+            <Button
+              variant="ghost"
+              size="sm"
+              onClick={goNext}
+              disabled={!hasNext || loading}
+              className="gap-1 text-muted-foreground"
+            >
+              Next
+              <ChevronRight className="size-4" />
+            </Button>
+          </div>
+        )}
+      </div>
+    </div>
+  )
+}
+
+function ProfileSkeleton() {
+  return (
+    <div className="space-y-6">
+      <div className="flex items-start gap-5">
+        <Skeleton className="size-20 rounded-full" />
+        <div className="space-y-2 pt-1">
+          <Skeleton className="h-6 w-40" />
+          <Skeleton className="h-4 w-24" />
+          <Skeleton className="h-4 w-32" />
+        </div>
+      </div>
+      <div className="space-y-2">
+        {Array.from({ length: 4 }).map((_, i) => (
+          <Skeleton key={i} className="h-14 w-full" />
+        ))}
+      </div>
+    </div>
+  )
+}

webui2/tailwind.config.ts ๐Ÿ”—

@@ -0,0 +1,74 @@
+import type { Config } from 'tailwindcss'
+
+const config: Config = {
+  darkMode: ['class'],
+  content: ['./index.html', './src/**/*.{ts,tsx}'],
+  theme: {
+    extend: {
+      fontFamily: {
+        sans: ['ui-sans-serif', 'system-ui', 'sans-serif'],
+        mono: ['ui-monospace', 'SFMono-Regular', 'SF Mono', 'Menlo', 'monospace'],
+      },
+      colors: {
+        border: 'hsl(var(--border))',
+        input: 'hsl(var(--input))',
+        ring: 'hsl(var(--ring))',
+        background: 'hsl(var(--background))',
+        foreground: 'hsl(var(--foreground))',
+        primary: {
+          DEFAULT: 'hsl(var(--primary))',
+          foreground: 'hsl(var(--primary-foreground))',
+        },
+        secondary: {
+          DEFAULT: 'hsl(var(--secondary))',
+          foreground: 'hsl(var(--secondary-foreground))',
+        },
+        destructive: {
+          DEFAULT: 'hsl(var(--destructive))',
+          foreground: 'hsl(var(--destructive-foreground))',
+        },
+        muted: {
+          DEFAULT: 'hsl(var(--muted))',
+          foreground: 'hsl(var(--muted-foreground))',
+        },
+        accent: {
+          DEFAULT: 'hsl(var(--accent))',
+          foreground: 'hsl(var(--accent-foreground))',
+        },
+        popover: {
+          DEFAULT: 'hsl(var(--popover))',
+          foreground: 'hsl(var(--popover-foreground))',
+        },
+        card: {
+          DEFAULT: 'hsl(var(--card))',
+          foreground: 'hsl(var(--card-foreground))',
+        },
+      },
+      borderRadius: {
+        lg: 'var(--radius)',
+        md: 'calc(var(--radius) - 2px)',
+        sm: 'calc(var(--radius) - 4px)',
+      },
+      keyframes: {
+        'accordion-down': {
+          from: { height: '0' },
+          to: { height: 'var(--radix-accordion-content-height)' },
+        },
+        'accordion-up': {
+          from: { height: 'var(--radix-accordion-content-height)' },
+          to: { height: '0' },
+        },
+      },
+      animation: {
+        'accordion-down': 'accordion-down 0.2s ease-out',
+        'accordion-up': 'accordion-up 0.2s ease-out',
+      },
+    },
+  },
+  plugins: [
+    require('tailwindcss-animate'),
+    require('@tailwindcss/typography'),
+  ],
+}
+
+export default config

webui2/tsconfig.app.json ๐Ÿ”—

@@ -0,0 +1,24 @@
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "useDefineForClassFields": true,
+    "lib": ["ES2020", "DOM", "DOM.Iterable"],
+    "module": "ESNext",
+    "skipLibCheck": true,
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "isolatedModules": true,
+    "moduleDetection": "force",
+    "noEmit": true,
+    "jsx": "react-jsx",
+    "strict": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "noFallthroughCasesInSwitch": true,
+    "baseUrl": ".",
+    "paths": {
+      "@/*": ["./src/*"]
+    }
+  },
+  "include": ["src"]
+}

webui2/tsconfig.json ๐Ÿ”—

@@ -0,0 +1,7 @@
+{
+  "files": [],
+  "references": [
+    { "path": "./tsconfig.app.json" },
+    { "path": "./tsconfig.node.json" }
+  ]
+}

webui2/tsconfig.node.json ๐Ÿ”—

@@ -0,0 +1,18 @@
+{
+  "compilerOptions": {
+    "target": "ES2022",
+    "lib": ["ES2023"],
+    "module": "ESNext",
+    "moduleResolution": "bundler",
+    "allowImportingTsExtensions": true,
+    "isolatedModules": true,
+    "moduleDetection": "force",
+    "noEmit": true,
+    "skipLibCheck": true,
+    "strict": true,
+    "noUnusedLocals": true,
+    "noUnusedParameters": true,
+    "noFallthroughCasesInSwitch": true
+  },
+  "include": ["vite.config.ts", "tailwind.config.ts", "codegen.ts"]
+}

webui2/vite.config.ts ๐Ÿ”—

@@ -0,0 +1,24 @@
+import { defineConfig } from 'vite'
+import react from '@vitejs/plugin-react'
+import path from 'path'
+
+// The Go backend URL. Run: git-bug webui --port 3000
+const API_URL = process.env.VITE_API_URL || 'http://localhost:3000'
+
+export default defineConfig({
+  plugins: [react()],
+  resolve: {
+    alias: {
+      '@': path.resolve(__dirname, './src'),
+    },
+  },
+  server: {
+    proxy: {
+      '/graphql': { target: API_URL, changeOrigin: true },
+      '/gitfile': { target: API_URL, changeOrigin: true },
+      '/upload': { target: API_URL, changeOrigin: true },
+      '/api': { target: API_URL, changeOrigin: true },
+      '/auth': { target: API_URL, changeOrigin: true },
+    },
+  },
+})