@samanhappy/mcphub 1.2.1 → 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/constants/oauthServerDefaults.js +2 -0
  2. package/dist/constants/oauthServerDefaults.js.map +1 -1
  3. package/dist/controllers/credentialBindingController.js +30 -1
  4. package/dist/controllers/credentialBindingController.js.map +1 -1
  5. package/dist/controllers/oauthApprovalController.js +63 -0
  6. package/dist/controllers/oauthApprovalController.js.map +1 -0
  7. package/dist/controllers/oauthServerController.js +55 -20
  8. package/dist/controllers/oauthServerController.js.map +1 -1
  9. package/dist/controllers/serverController.js +19 -1
  10. package/dist/controllers/serverController.js.map +1 -1
  11. package/dist/dao/DaoFactory.js +7 -0
  12. package/dist/dao/DaoFactory.js.map +1 -1
  13. package/dist/dao/DatabaseDaoFactory.js +4 -0
  14. package/dist/dao/DatabaseDaoFactory.js.map +1 -1
  15. package/dist/dao/OAuthApprovalDao.js +52 -0
  16. package/dist/dao/OAuthApprovalDao.js.map +1 -0
  17. package/dist/dao/OAuthApprovalDaoDbImpl.js +26 -0
  18. package/dist/dao/OAuthApprovalDaoDbImpl.js.map +1 -0
  19. package/dist/dao/OAuthTokenDaoDbImpl.js +2 -0
  20. package/dist/dao/OAuthTokenDaoDbImpl.js.map +1 -1
  21. package/dist/dao/index.js +1 -0
  22. package/dist/dao/index.js.map +1 -1
  23. package/dist/db/entities/OAuthApproval.js +58 -0
  24. package/dist/db/entities/OAuthApproval.js.map +1 -0
  25. package/dist/db/entities/OAuthToken.js +4 -0
  26. package/dist/db/entities/OAuthToken.js.map +1 -1
  27. package/dist/db/entities/index.js +3 -1
  28. package/dist/db/entities/index.js.map +1 -1
  29. package/dist/middlewares/auth.js +2 -2
  30. package/dist/middlewares/auth.js.map +1 -1
  31. package/dist/middlewares/userContext.js +26 -5
  32. package/dist/middlewares/userContext.js.map +1 -1
  33. package/dist/models/OAuth.js +19 -3
  34. package/dist/models/OAuth.js.map +1 -1
  35. package/dist/routes/index.js +6 -1
  36. package/dist/routes/index.js.map +1 -1
  37. package/dist/services/credentialBindingService.js +39 -3
  38. package/dist/services/credentialBindingService.js.map +1 -1
  39. package/dist/services/forwardAuthService.js +27 -11
  40. package/dist/services/forwardAuthService.js.map +1 -1
  41. package/dist/services/oauthApprovalService.js +74 -0
  42. package/dist/services/oauthApprovalService.js.map +1 -0
  43. package/dist/services/oauthClientRegistration.js +9 -4
  44. package/dist/services/oauthClientRegistration.js.map +1 -1
  45. package/dist/services/oauthServerService.js +24 -7
  46. package/dist/services/oauthServerService.js.map +1 -1
  47. package/dist/services/sseService.js +16 -6
  48. package/dist/services/sseService.js.map +1 -1
  49. package/dist/services/userService.js +2 -0
  50. package/dist/services/userService.js.map +1 -1
  51. package/dist/services/vectorSearchService.js +139 -73
  52. package/dist/services/vectorSearchService.js.map +1 -1
  53. package/dist/utils/bearerAuth.js +23 -0
  54. package/dist/utils/bearerAuth.js.map +1 -1
  55. package/dist/utils/migration.js +1 -0
  56. package/dist/utils/migration.js.map +1 -1
  57. package/dist/utils/passthroughHeaders.js +4 -3
  58. package/dist/utils/passthroughHeaders.js.map +1 -1
  59. package/frontend/dist/assets/{ActivityPage-DZFLY-Um.js → ActivityPage-CB41zWix.js} +2 -2
  60. package/frontend/dist/assets/{ActivityPage-DZFLY-Um.js.map → ActivityPage-CB41zWix.js.map} +1 -1
  61. package/frontend/dist/assets/CredentialsPage-BecFRfro.js +2 -0
  62. package/frontend/dist/assets/CredentialsPage-BecFRfro.js.map +1 -0
  63. package/frontend/dist/assets/{Dashboard-BRU2Gk9z.js → Dashboard-CwifBwm4.js} +2 -2
  64. package/frontend/dist/assets/{Dashboard-BRU2Gk9z.js.map → Dashboard-CwifBwm4.js.map} +1 -1
  65. package/frontend/dist/assets/{EndpointCopy-3f1Uw-gu.js → EndpointCopy-BeLf_ow_.js} +2 -2
  66. package/frontend/dist/assets/{EndpointCopy-3f1Uw-gu.js.map → EndpointCopy-BeLf_ow_.js.map} +1 -1
  67. package/frontend/dist/assets/{GroupsPage-D_E7QL_o.js → GroupsPage-DLL1tFj8.js} +2 -2
  68. package/frontend/dist/assets/{GroupsPage-D_E7QL_o.js.map → GroupsPage-DLL1tFj8.js.map} +1 -1
  69. package/frontend/dist/assets/{LoginPage-Bsfdp4yD.js → LoginPage-DvHL1HNV.js} +2 -2
  70. package/frontend/dist/assets/{LoginPage-Bsfdp4yD.js.map → LoginPage-DvHL1HNV.js.map} +1 -1
  71. package/frontend/dist/assets/{LogsPage-CCHmA5cZ.js → LogsPage-Bva6Y11K.js} +2 -2
  72. package/frontend/dist/assets/{LogsPage-CCHmA5cZ.js.map → LogsPage-Bva6Y11K.js.map} +1 -1
  73. package/frontend/dist/assets/{MarketPage-DrQQT14y.js → MarketPage-DGxNuifk.js} +2 -2
  74. package/frontend/dist/assets/{MarketPage-DrQQT14y.js.map → MarketPage-DGxNuifk.js.map} +1 -1
  75. package/frontend/dist/assets/OAuthApprovalsPage-TzVNIJ27.js +2 -0
  76. package/frontend/dist/assets/OAuthApprovalsPage-TzVNIJ27.js.map +1 -0
  77. package/frontend/dist/assets/{OAuthConsentPage-934ieVvL.js → OAuthConsentPage-yQSgIbZ8.js} +2 -2
  78. package/frontend/dist/assets/{OAuthConsentPage-934ieVvL.js.map → OAuthConsentPage-yQSgIbZ8.js.map} +1 -1
  79. package/frontend/dist/assets/{PromptsPage-QAI8kF63.js → PromptsPage-CIAVpo9B.js} +2 -2
  80. package/frontend/dist/assets/{PromptsPage-QAI8kF63.js.map → PromptsPage-CIAVpo9B.js.map} +1 -1
  81. package/frontend/dist/assets/{ResourcesPage-TclV1l2q.js → ResourcesPage-C5g-98tB.js} +2 -2
  82. package/frontend/dist/assets/{ResourcesPage-TclV1l2q.js.map → ResourcesPage-C5g-98tB.js.map} +1 -1
  83. package/frontend/dist/assets/{ServersPage-Bc0tS2uo.js → ServersPage-CJEgBQr-.js} +4 -4
  84. package/frontend/dist/assets/{ServersPage-Bc0tS2uo.js.map → ServersPage-CJEgBQr-.js.map} +1 -1
  85. package/frontend/dist/assets/SettingsPage-Bub-g0mD.js +14 -0
  86. package/frontend/dist/assets/SettingsPage-Bub-g0mD.js.map +1 -0
  87. package/frontend/dist/assets/{StatusDot-C_UTW6B7.js → StatusDot-B81gkUBo.js} +2 -2
  88. package/frontend/dist/assets/{StatusDot-C_UTW6B7.js.map → StatusDot-B81gkUBo.js.map} +1 -1
  89. package/frontend/dist/assets/{ToggleGroup-CUUsTJDm.js → ToggleGroup-DZ39486g.js} +2 -2
  90. package/frontend/dist/assets/{ToggleGroup-CUUsTJDm.js.map → ToggleGroup-DZ39486g.js.map} +1 -1
  91. package/frontend/dist/assets/{UsersPage-MpTb3xJ-.js → UsersPage-pdkVxTsL.js} +2 -2
  92. package/frontend/dist/assets/{UsersPage-MpTb3xJ-.js.map → UsersPage-pdkVxTsL.js.map} +1 -1
  93. package/frontend/dist/assets/{clipboard-DVbqnePj.js → clipboard-BYlVdxdy.js} +2 -2
  94. package/frontend/dist/assets/{clipboard-DVbqnePj.js.map → clipboard-BYlVdxdy.js.map} +1 -1
  95. package/frontend/dist/assets/{costRevision-DXEYAFUy.js → costRevision-D-WY0B73.js} +2 -2
  96. package/frontend/dist/assets/{costRevision-DXEYAFUy.js.map → costRevision-D-WY0B73.js.map} +1 -1
  97. package/frontend/dist/assets/index-CyD60EHI.css +1 -0
  98. package/frontend/dist/assets/index-DKX_BExz.js +3 -0
  99. package/frontend/dist/assets/index-DKX_BExz.js.map +1 -0
  100. package/frontend/dist/assets/{resourceService-DPjgql8Z.js → resourceService-CKAaXBkJ.js} +2 -2
  101. package/frontend/dist/assets/{resourceService-DPjgql8Z.js.map → resourceService-CKAaXBkJ.js.map} +1 -1
  102. package/frontend/dist/assets/{useCostData-CDNXYHZf.js → useCostData-DzjFGnw4.js} +2 -2
  103. package/frontend/dist/assets/{useCostData-CDNXYHZf.js.map → useCostData-DzjFGnw4.js.map} +1 -1
  104. package/frontend/dist/assets/{variableDetection-DGr_LErx.js → variableDetection-D75LR7nZ.js} +2 -2
  105. package/frontend/dist/assets/{variableDetection-DGr_LErx.js.map → variableDetection-D75LR7nZ.js.map} +1 -1
  106. package/frontend/dist/index.html +2 -2
  107. package/mcp_settings.json +2 -0
  108. package/package.json +1 -1
  109. package/frontend/dist/assets/CredentialsPage-BqEsnkMx.js +0 -2
  110. package/frontend/dist/assets/CredentialsPage-BqEsnkMx.js.map +0 -1
  111. package/frontend/dist/assets/SettingsPage-Dfhl51E1.js +0 -14
  112. package/frontend/dist/assets/SettingsPage-Dfhl51E1.js.map +0 -1
  113. package/frontend/dist/assets/index-BNm-68Gn.js +0 -3
  114. package/frontend/dist/assets/index-BNm-68Gn.js.map +0 -1
  115. package/frontend/dist/assets/index-C33aH9Y7.css +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"costRevision-DXEYAFUy.js","sources":["../../src/utils/toolDescription.ts","../../src/utils/mcpClientSnippets.ts","../../src/components/ui/CopyClientConfigDialog.tsx","../../src/utils/costRevision.ts"],"sourcesContent":["type ToolDescriptionSource = {\n description?: string;\n defaultDescription?: string;\n hasDescriptionOverride?: boolean;\n};\n\nexport interface ToolDescriptionInfo {\n currentDescription: string;\n defaultDescription?: string;\n hasDescriptionOverride: boolean;\n}\n\nconst normalizeDescription = (description: string | undefined, fallback: string): string => {\n return description && description.trim() ? description : fallback;\n};\n\nexport const getToolDescriptionInfo = (\n tool: ToolDescriptionSource,\n noDescriptionText: string,\n): ToolDescriptionInfo => {\n const currentDescription = normalizeDescription(tool.description, noDescriptionText);\n\n if (!tool.hasDescriptionOverride) {\n return {\n currentDescription,\n hasDescriptionOverride: false,\n };\n }\n\n return {\n currentDescription,\n defaultDescription: normalizeDescription(tool.defaultDescription, noDescriptionText),\n hasDescriptionOverride: true,\n };\n};\n","/**\n * Per-client MCP configuration presets for the copy actions (#1165).\n *\n * MCPHub hands out HTTP endpoints, so every preset describes the same target -\n * a name, an optional URL/headers pair (HTTP) or command/args/env triple\n * (stdio) - in the shape the selected client expects. Eleven of the fourteen\n * presets were verified against the upstream sources below (URLs re-checked\n * 2026-09, the month this file landed); the remaining three reuse the generic\n * `mcpServers` shape (or, for the generic-http escape hatch, the bare entry)\n * these copy actions always produced.\n *\n * Which clients document an explicit transport field, and which do not:\n * - Documents a transport field (the `type` key is written into the entry):\n * claude-code (`type: \"http\" | \"sse\" | \"stdio\"`; a remote entry with `url`\n * but no `type` is a configuration error per\n * https://code.claude.com/docs/en/mcp), vscode (`\"http\" | \"sse\" | \"stdio\"`,\n * final URL after the 2026-09 migration:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers),\n * codebuddy (`type` marked Required; fixed `\"http\"` for HTTP, `\"sse\"` for\n * SSE and `\"stdio\"` for stdio, per\n * https://www.codebuddy.ai/docs/cli/mcp), qoder (every remote\n * example carries `type`; for Streamable HTTP the doc says to configure the\n * URL the same way as SSE and the IDE auto-detects it, so the http target\n * deliberately keeps the bare `url` + `headers` shape rather than tagging\n * it `sse`; https://docs.qoder.com/zh/user-guide/chat/model-context-protocol),\n * cherry-studio (`baseUrl` + `'sse' | 'streamableHttp'`, strict schema),\n * opencode (`type: 'remote' | 'local'`).\n * - Field table does not list a transport key: cursor\n * (https://cursor.com/docs/mcp), trae (https://docs.trae.ai/ide/add-mcp-servers),\n * zcode (https://zcode.z.ai/en/docs/mcp-services), windsurf\n * (https://docs.windsurf.com/windsurf/cascade/mcp). The `type: \"sse\"` marker\n * the generic shape injects for SSE targets on these presets is added on\n * the assumption that unknown keys are ignored, not required by their\n * documented shape; it is kept because SSE upstreams must not be dialed as\n * streamable HTTP.\n * - Verified but the format carries no `type` key at all: codex (TOML;\n * `codex-rs/config/src/mcp_types.rs`,\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs).\n * (The generic-http escape hatch, one of the three unverified presets, is not\n * a \"no `type`\" format: for a remote target it always writes an explicit\n * `type` - `\"http\"`, or `\"sse\"` for an SSE upstream.)\n *\n * Upstream sources used:\n * - Claude Code MCP configuration: https://code.claude.com/docs/en/mcp\n * - Cursor MCP docs: https://cursor.com/docs/mcp\n * - VS Code MCP configuration reference:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers\n * - Codex `codex-rs/config/src/mcp_types.rs`:\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs\n * - OpenCode mcp-servers docs: https://opencode.ai/docs/mcp-servers/\n * - Cherry Studio `mcpProtocolInstall.ts`:\n * https://github.com/CherryHQ/cherry-studio/blob/main/src/shared/data/types/mcpProtocolInstall.ts\n * - CodeBuddy MCP CLI docs: https://www.codebuddy.ai/docs/cli/mcp\n * - Qoder MCP user guide:\n * https://docs.qoder.com/zh/user-guide/chat/model-context-protocol\n * - Trae MCP docs: https://docs.trae.ai/ide/add-mcp-servers\n * - Windsurf MCP docs: https://docs.windsurf.com/windsurf/cascade/mcp\n * - ZCode MCP docs: https://zcode.z.ai/en/docs/mcp-services\n */\n\nexport type ClientSnippetId =\n | 'generic-mcp-servers'\n | 'generic-http'\n | 'claude-code'\n | 'cursor'\n | 'vscode'\n | 'codex'\n | 'opencode'\n | 'windsurf'\n | 'cherry-studio'\n | 'codebuddy'\n | 'qoder'\n | 'trae'\n | 'zcode'\n | 'workbuddy';\n\nexport interface ClientSnippetPreset {\n id: ClientSnippetId;\n}\n\n/** Tab the dialog opens on; the shape the copy actions produced before. */\nexport const DEFAULT_CLIENT_SNIPPET_ID: ClientSnippetId = 'generic-mcp-servers';\n\n/**\n * Tabs shown in the copy dialog, most common clients first. The first entry is\n * the shape the copy actions produced before the presets existed, so the\n * default tab stays familiar; the bare HTTP entry is the escape hatch for\n * clients that wrap the entry in their own container.\n */\nexport const CLIENT_SNIPPET_PRESETS: readonly ClientSnippetPreset[] = [\n { id: 'generic-mcp-servers' },\n { id: 'claude-code' },\n { id: 'cursor' },\n { id: 'vscode' },\n { id: 'codex' },\n { id: 'opencode' },\n { id: 'windsurf' },\n { id: 'cherry-studio' },\n { id: 'codebuddy' },\n { id: 'qoder' },\n { id: 'trae' },\n { id: 'zcode' },\n { id: 'workbuddy' },\n { id: 'generic-http' },\n];\n\nexport interface ClientSnippetTarget {\n name: string;\n /** Stored transport type; `sse` is called out so clients do not misdial it as http. */\n type?: 'stdio' | 'sse' | 'streamable-http' | 'openapi';\n /** HTTP targets carry a URL (and usually an Authorization header). */\n url?: string;\n headers?: Record<string, string>;\n /** stdio targets carry a command instead. */\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n description?: string;\n}\n\nexport interface ClientSnippetBlock {\n kind: 'config' | 'command';\n text: string;\n}\n\nexport interface ClientSnippetOptions {\n /** Description used by the VS Code token input prompt. */\n tokenPromptDescription?: string;\n}\n\n/** Placeholder MCPHub uses for snippets that need a token pasted in by hand. */\nexport const ACCESS_TOKEN_PLACEHOLDER = '<your-access-token>';\nconst TOKEN_INPUT_ID = 'mcphub-token';\n\nconst isHttpTarget = (target: ClientSnippetTarget): boolean => Boolean(target.url);\n\nconst definedHeaders = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.headers ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst definedEnv = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.env ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst stdioEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n const env = definedEnv(target);\n return {\n command: target.command ?? '',\n ...(args.length > 0 ? { args } : {}),\n ...(env ? { env } : {}),\n };\n};\n\n/**\n * HTTP/stdio entry for clients whose docs make the transport a required field.\n * Claude Code skips an entry that has a `url` but no `type` (it reads the\n * entry as stdio and reports a configuration error), and CodeBuddy's field\n * table marks `type` as Required, fixed to `\"http\"` for the HTTP form and\n * `\"sse\"` for the SSE form.\n *\n * Stdio targets differ between the two clients. Claude Code reads a type-less\n * entry as stdio (https://code.claude.com/docs/en/mcp), so its stdio shape\n * keeps the plain command/args/env form with no `type` key. CodeBuddy's docs\n * mark `type` as Required with the fixed value `\"stdio\"`\n * (https://www.codebuddy.ai/docs/cli/mcp), so its stdio shape writes\n * `\"type\": \"stdio\"`; pass `stdioType` only for CodeBuddy.\n */\nconst typedTransportEntry = (\n target: ClientSnippetTarget,\n stdioType: boolean = false,\n): Record<string, unknown> => {\n if (!isHttpTarget(target)) {\n return stdioType ? { type: 'stdio', ...stdioEntry(target) } : stdioEntry(target);\n }\n\n const headers = definedHeaders(target);\n return {\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\n// This helper feeds the generic `mcpServers` shape for the generic-mcp-servers,\n// qoder, cursor, windsurf, trae, zcode and workbuddy presets. Only qoder's\n// upstream docs carry a transport field for this shape; for the rest\n// (generic-mcp-servers, cursor, windsurf, trae, zcode, workbuddy) the\n// `type: \"sse\"` marker is added on the assumption that unknown keys are\n// ignored, so it is unverified against a field table. It is kept because an\n// SSE upstream must not be dialed as streamable HTTP.\nconst httpEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const headers = definedHeaders(target);\n return {\n // Only `sse` is spelled out: it is the one HTTP transport a client might\n // otherwise misdial as streamable HTTP. Every other target keeps the bare\n // `url` + `headers` shape these presets always produced.\n ...(target.type === 'sse' ? { type: 'sse' } : {}),\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\nconst withWrappedName = (\n wrapper: string,\n name: string,\n entry: Record<string, unknown>,\n): string => JSON.stringify({ [wrapper]: { [name]: entry } }, null, 2);\n\nconst jsonSnippet = (target: ClientSnippetTarget): string =>\n withWrappedName(\n 'mcpServers',\n target.name,\n isHttpTarget(target) ? httpEntry(target) : stdioEntry(target),\n );\n\n// VS Code wants the transport spelled out and can prompt for the token itself,\n// so the shared placeholder becomes an input reference plus an `inputs` entry.\nconst vscodeSnippet = (target: ClientSnippetTarget, options: ClientSnippetOptions): string => {\n const headers = definedHeaders(target);\n const placeholder = `Bearer ${ACCESS_TOKEN_PLACEHOLDER}`;\n const needsTokenInput = headers?.Authorization === placeholder;\n\n const body = needsTokenInput\n ? { ...headers, Authorization: `Bearer \\${input:${TOKEN_INPUT_ID}}` }\n : headers;\n\n const entry = isHttpTarget(target)\n ? {\n // VS Code distinguishes the SSE transport from streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url,\n ...(body ? { headers: body } : {}),\n }\n : { type: 'stdio', ...stdioEntry(target) };\n\n return JSON.stringify(\n {\n servers: { [target.name]: entry },\n ...(needsTokenInput\n ? {\n inputs: [\n {\n id: TOKEN_INPUT_ID,\n type: 'promptString',\n description: options.tokenPromptDescription ?? 'MCPHub access token',\n password: true,\n },\n ],\n }\n : {}),\n },\n null,\n 2,\n );\n};\n\nconst TOML_BARE_KEY = /^[A-Za-z0-9_-]+$/;\n\nconst tomlKey = (key: string): string => (TOML_BARE_KEY.test(key) ? key : JSON.stringify(key));\nconst tomlValue = (value: string): string => JSON.stringify(value);\nconst tomlInlineTable = (entries: Record<string, string>): string =>\n `{ ${Object.entries(entries)\n .map(([key, value]) => `${tomlKey(key)} = ${tomlValue(value)}`)\n .join(', ')} }`;\n\n// Codex calls the header map `http_headers` (there is no `headers` key), and\n// needs quoted table keys for names that are not bare TOML keys - group names\n// may contain spaces or CJK. Note `#[schemars(deny_unknown_fields)]` in\n// `mcp_types.rs` only constrains the generated JSON Schema; the Rust struct\n// itself has no `#[serde(deny_unknown_fields)]`, so TOML parsing may silently\n// ignore unknown fields instead of rejecting them.\nconst codexSnippet = (target: ClientSnippetTarget): string => {\n const key = tomlKey(target.name);\n const lines = [`[mcp_servers.${key}]`];\n\n if (isHttpTarget(target)) {\n lines.push(`url = ${tomlValue(target.url ?? '')}`);\n const headers = definedHeaders(target);\n if (headers) {\n lines.push(`http_headers = ${tomlInlineTable(headers)}`);\n }\n return lines.join('\\n');\n }\n\n lines.push(`command = ${tomlValue(target.command ?? '')}`);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n if (args.length > 0) {\n lines.push(`args = [${args.map(tomlValue).join(', ')}]`);\n }\n const env = definedEnv(target);\n if (env) {\n lines.push('', `[mcp_servers.${key}.env]`);\n for (const [name, value] of Object.entries(env)) {\n lines.push(`${tomlKey(name)} = ${tomlValue(value)}`);\n }\n }\n return lines.join('\\n');\n};\n\nconst openCodeSnippet = (target: ClientSnippetTarget): string => {\n if (!isHttpTarget(target)) {\n const env = definedEnv(target);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'local',\n command: [target.command ?? '', ...args],\n ...(env ? { environment: env } : {}),\n },\n },\n },\n null,\n 2,\n );\n }\n\n const headers = definedHeaders(target);\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'remote',\n url: target.url,\n ...(headers ? { headers } : {}),\n },\n },\n },\n null,\n 2,\n );\n};\n\n// Cherry Studio's `ProtocolMcpServerConfigSchema` is a strict object: remote\n// servers use `baseUrl` + `type: 'sse' | 'streamableHttp'` (no `url` key) and\n// stdio servers use command/args/env. The install-time metadata\n// (`installSource`, `isTrusted`, `installedAt`, `isActive: false`) belongs to\n// `ProtocolMcpServerInstallSchema`, the install *request* schema, not to this\n// hand-pasted config; an entry carrying `isActive` would not satisfy\n// `ProtocolMcpServerConfigSchema` (which has no such key).\nconst cherryStudioSnippet = (target: ClientSnippetTarget): string => {\n const base = {\n name: target.name,\n description: target.description ?? '',\n };\n\n const headers = definedHeaders(target);\n const entry = isHttpTarget(target)\n ? {\n ...base,\n // The schema accepts exactly two remote transports; keep SSE upstreams\n // spelled out so Cherry Studio does not dial them as streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'streamableHttp',\n baseUrl: target.url,\n ...(headers ? { headers } : {}),\n }\n : { ...base, type: 'stdio', ...stdioEntry(target) };\n\n return withWrappedName('mcpServers', target.name, entry);\n};\n\nconst CLI_SAFE = /^[A-Za-z0-9._:@/=-]+$/;\n\n// Single quotes are the only reliable POSIX quoting for a pasted command:\n// double quotes still let the shell expand `$(...)`, backticks and `${...}`\n// inside them. Within single quotes nothing is expanded, so the only character\n// needing special handling is `'` itself, escaped as `'\\''` (close quote,\n// escaped quote, reopen).\nconst shellQuote = (value: string): string => `'${value.replace(/'/g, \"'\\\\''\")}'`;\n\nconst cliArg = (value: string): string =>\n CLI_SAFE.test(value) ? value : shellQuote(value);\n\n// Claude Code's one-liner equivalent of the JSON block, in the documented\n// HTTP shape: `claude mcp add --transport <t> <name> <url> [--header ...]`.\n//\n// A positional that starts with `-` cannot be spelled safely in that shape:\n// shell quoting is gone by the time the CLI's tokenizer sees the value, and\n// the documented `--` separator belongs to the stdio form, so relying on it\n// for the HTTP form would be an unverified parsing assumption. Since\n// SERVER_NAME_PATTERN admits names like `-foo`, a name or URL starting with\n// a dash omits the command block outright - the JSON config block still\n// carries the full entry - rather than emitting a command the CLI would\n// misparse as one of its own options.\nconst claudeCodeCommand = (target: ClientSnippetTarget): string | undefined => {\n if (!isHttpTarget(target)) {\n return undefined;\n }\n\n if (target.name.startsWith('-') || (target.url ?? '').startsWith('-')) {\n return undefined;\n }\n\n const parts = [\n 'claude',\n 'mcp',\n 'add',\n '--transport',\n // SSE endpoints must not be dialed as streamable HTTP.\n target.type === 'sse' ? 'sse' : 'http',\n cliArg(target.name),\n cliArg(target.url ?? ''),\n ];\n for (const [name, value] of Object.entries(definedHeaders(target) ?? {})) {\n parts.push('--header', cliArg(`${name}: ${value}`));\n }\n return parts.join(' ');\n};\n\nconst asString = (value: unknown): string | undefined =>\n typeof value === 'string' && value.length > 0 ? value : undefined;\n\n/** Narrow a stored `type` to the four legal server types; anything else is dropped. */\nconst asServerType = (value: unknown): ClientSnippetTarget['type'] => {\n switch (value) {\n case 'stdio':\n case 'sse':\n case 'streamable-http':\n case 'openapi':\n return value;\n default:\n return undefined;\n }\n};\n\nconst asStringRecord = (value: unknown): Record<string, string> | undefined => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const entries = Object.entries(value as Record<string, unknown>).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst asStringArray = (value: unknown): string[] | undefined => {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const items = value.filter((item): item is string => typeof item === 'string');\n return items.length > 0 ? items : undefined;\n};\n\n/**\n * Narrow a stored server configuration (the `mcp-settings/export` payload\n * carries MCPHub's internal fields too) down to what a client snippet needs.\n */\nexport const toClientSnippetTarget = (\n name: string,\n config: Record<string, unknown> | undefined,\n): ClientSnippetTarget => {\n const source = config ?? {};\n\n return {\n name,\n ...(asServerType(source.type) ? { type: asServerType(source.type) } : {}),\n ...(asString(source.url) ? { url: asString(source.url) } : {}),\n ...(asStringRecord(source.headers) ? { headers: asStringRecord(source.headers) } : {}),\n ...(asString(source.command) ? { command: asString(source.command) } : {}),\n ...(asStringArray(source.args) ? { args: asStringArray(source.args) } : {}),\n ...(asStringRecord(source.env) ? { env: asStringRecord(source.env) } : {}),\n ...(asString(source.description) ? { description: asString(source.description) } : {}),\n };\n};\n\nconst configSnippet = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions,\n): string => {\n switch (id) {\n case 'generic-mcp-servers':\n return jsonSnippet(target);\n case 'generic-http':\n return JSON.stringify(\n isHttpTarget(target)\n ? { type: 'http', ...httpEntry(target) }\n : stdioEntry(target),\n null,\n 2,\n );\n case 'vscode':\n return vscodeSnippet(target, options);\n case 'codex':\n return codexSnippet(target);\n case 'opencode':\n return openCodeSnippet(target);\n case 'cherry-studio':\n return cherryStudioSnippet(target);\n case 'claude-code':\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target));\n case 'codebuddy':\n // CodeBuddy's field table marks `type` as Required, fixed to `\"stdio\"`\n // for stdio entries, so unlike Claude Code it always carries the type.\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target, true));\n default:\n return jsonSnippet(target);\n }\n};\n\nexport const buildClientSnippetBlocks = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions = {},\n): ClientSnippetBlock[] => {\n // OpenAPI-backed servers carry neither a URL nor a command, so every preset\n // would degrade to filler like `command: \"\"`. Return no blocks and let the\n // dialog explain that there is no client-side transport to copy.\n if (!target.url && !target.command) {\n return [];\n }\n\n const blocks: ClientSnippetBlock[] = [{ kind: 'config', text: configSnippet(id, target, options) }];\n\n if (id === 'claude-code') {\n const command = claudeCodeCommand(target);\n if (command) {\n blocks.push({ kind: 'command', text: command });\n }\n }\n\n return blocks;\n};\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Check, Copy, X } from 'lucide-react';\nimport {\n buildClientSnippetBlocks,\n CLIENT_SNIPPET_PRESETS,\n DEFAULT_CLIENT_SNIPPET_ID,\n type ClientSnippetId,\n type ClientSnippetTarget,\n} from '@/utils/mcpClientSnippets';\nimport { copyText } from '@/utils/clipboard';\nimport { useToast } from '@/contexts/ToastContext';\n\ninterface CopyClientConfigDialogProps {\n isOpen: boolean;\n onClose: () => void;\n /** Target to render; `null` keeps the dialog closed. */\n target: ClientSnippetTarget | null;\n}\n\n/**\n * Per-client MCP configuration presets for the copy actions (#1165): one tab\n * per client, each with the path it belongs in and a ready-to-paste snippet.\n */\nconst CopyClientConfigDialog = ({ isOpen, onClose, target }: CopyClientConfigDialogProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [activeId, setActiveId] = useState<ClientSnippetId>(DEFAULT_CLIENT_SNIPPET_ID);\n const [copiedBlock, setCopiedBlock] = useState<string | null>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const returnFocusRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!isOpen) {\n setCopiedBlock(null);\n setActiveId(DEFAULT_CLIENT_SNIPPET_ID);\n }\n }, [isOpen]);\n\n // Like the other hand-rolled modals in this codebase the dialog does not trap\n // focus; it does move focus inside on open and hand it back to the trigger on\n // close, so keyboard users are not left behind on the page underneath.\n useEffect(() => {\n if (!isOpen) return;\n returnFocusRef.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null;\n dialogRef.current?.focus();\n\n return () => {\n returnFocusRef.current?.focus();\n };\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, onClose]);\n\n const blocks = useMemo(\n () =>\n target\n ? buildClientSnippetBlocks(activeId, target, {\n tokenPromptDescription: t('clientConfig.tokenPrompt'),\n })\n : [],\n [activeId, target, t],\n );\n\n if (!isOpen || !target) {\n return null;\n }\n\n const handleCopy = async (key: string, value: string) => {\n const ok = await copyText(value);\n if (!ok) {\n showToast(t('common.copyFailed'), 'error');\n return;\n }\n setCopiedBlock(key);\n showToast(t('common.copySuccess'), 'success');\n setTimeout(() => setCopiedBlock((current) => (current === key ? null : current)), 1500);\n };\n\n return (\n <div\n className=\"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4\"\n onClick={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"hub-card w-full max-w-2xl\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t('clientConfig.title')}\n >\n <div\n className=\"flex items-start justify-between gap-3 px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <div className=\"min-w-0\">\n <div className=\"text-[14px] font-medium\" style={{ color: 'var(--hub-ink)' }}>\n {t('clientConfig.title')}\n </div>\n <div className=\"text-[12px] mt-0.5\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.description', { name: target.name })}\n </div>\n </div>\n <button className=\"hub-icon-btn sm\" onClick={onClose} aria-label={t('app.closeButton')}>\n <X size={13} />\n </button>\n </div>\n\n {/* A target with neither URL nor command (OpenAPI-backed servers) has no\n transport, so every preset returns the same empty result: offering 14\n clickable tabs would only suggest the dialog is broken. The tab strip\n and its per-client hint are therefore hidden and only the explanation\n below is shown. */}\n {blocks.length > 0 && (\n <div className=\"px-4 pt-3\">\n <div\n className=\"flex flex-wrap gap-1\"\n role=\"tablist\"\n aria-label={t('clientConfig.title')}\n >\n {CLIENT_SNIPPET_PRESETS.map((preset) => {\n const active = preset.id === activeId;\n return (\n <button\n key={preset.id}\n role=\"tab\"\n aria-selected={active}\n onClick={() => setActiveId(preset.id)}\n className=\"px-2.5 py-1 rounded-md text-[12px] transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{\n background: active ? 'var(--hub-surface)' : 'transparent',\n border: '1px solid ' + (active ? 'var(--hub-line)' : 'transparent'),\n color: active ? 'var(--hub-ink)' : 'var(--hub-ink-2)',\n }}\n >\n {t(`clientConfig.clients.${preset.id}.label`)}\n </button>\n );\n })}\n </div>\n\n <p className=\"text-[12px] mt-3\" style={{ color: 'var(--hub-ink-3)' }}>\n {t(`clientConfig.clients.${activeId}.hint`)}\n </p>\n </div>\n )}\n\n <div className=\"px-4 pb-4 pt-2 space-y-3 max-h-[60vh] overflow-auto\">\n {blocks.length === 0 ? (\n // OpenAPI-backed servers have no client-side transport to copy.\n <p className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.noTransport')}\n </p>\n ) : (\n blocks.map((block) => {\n const key = `${activeId}:${block.kind}`;\n const copied = copiedBlock === key;\n return (\n <div key={key}>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-[12px]\" style={{ color: 'var(--hub-ink-2)' }}>\n {t(\n block.kind === 'command'\n ? 'clientConfig.commandBlock'\n : 'clientConfig.configBlock',\n )}\n </span>\n <button\n className=\"hub-btn sm\"\n onClick={() => void handleCopy(key, block.text)}\n >\n {copied ? <Check size={12} className=\"text-[var(--hub-ok)]\" /> : <Copy size={12} />}\n {copied ? t('clientConfig.copied') : t('common.copy')}\n </button>\n </div>\n <pre\n className=\"hub-mono m-0 p-3 rounded-md overflow-auto\"\n style={{\n background: 'var(--hub-bg-2)',\n border: '1px solid var(--hub-line-2)',\n fontSize: 12,\n lineHeight: 1.5,\n color: 'var(--hub-ink-2)',\n maxHeight: 320,\n }}\n >\n <code>{block.text}</code>\n </pre>\n </div>\n );\n })\n )}\n </div>\n\n <div\n className=\"flex justify-end px-4 py-3\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <button className=\"hub-btn\" onClick={onClose}>\n {t('common.cancel')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CopyClientConfigDialog;\n","import type { Server } from '../types';\n\n// Ignore transient polling metadata, but include full definitions: equal tool\n// counts do not imply equal context costs.\nexport const serverCostRevision = (servers: Server[]): string =>\n JSON.stringify(\n servers.map(({ name, status, enabled, tools, prompts, resources }) => ({\n name,\n status,\n enabled,\n tools,\n prompts,\n resources,\n })),\n );\n"],"names":["normalizeDescription","description","fallback","getToolDescriptionInfo","tool","noDescriptionText","currentDescription","DEFAULT_CLIENT_SNIPPET_ID","CLIENT_SNIPPET_PRESETS","ACCESS_TOKEN_PLACEHOLDER","TOKEN_INPUT_ID","isHttpTarget","target","definedHeaders","entries","value","definedEnv","stdioEntry","args","_a","arg","env","typedTransportEntry","stdioType","headers","httpEntry","withWrappedName","wrapper","name","entry","jsonSnippet","vscodeSnippet","options","placeholder","needsTokenInput","body","TOML_BARE_KEY","tomlKey","key","tomlValue","tomlInlineTable","codexSnippet","lines","openCodeSnippet","cherryStudioSnippet","base","CLI_SAFE","shellQuote","cliArg","claudeCodeCommand","parts","asString","asServerType","asStringRecord","asStringArray","items","item","toClientSnippetTarget","config","source","configSnippet","id","buildClientSnippetBlocks","blocks","command","CopyClientConfigDialog","isOpen","onClose","useTranslation","showToast","useToast","activeId","setActiveId","useState","copiedBlock","setCopiedBlock","dialogRef","useRef","returnFocusRef","useEffect","onKeyDown","event","useMemo","handleCopy","copyText","current","jsx","jsxs","X","preset","active","block","copied","Check","Copy","serverCostRevision","servers","status","enabled","tools","prompts","resources"],"mappings":"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"}
1
+ {"version":3,"file":"costRevision-D-WY0B73.js","sources":["../../src/utils/toolDescription.ts","../../src/utils/mcpClientSnippets.ts","../../src/components/ui/CopyClientConfigDialog.tsx","../../src/utils/costRevision.ts"],"sourcesContent":["type ToolDescriptionSource = {\n description?: string;\n defaultDescription?: string;\n hasDescriptionOverride?: boolean;\n};\n\nexport interface ToolDescriptionInfo {\n currentDescription: string;\n defaultDescription?: string;\n hasDescriptionOverride: boolean;\n}\n\nconst normalizeDescription = (description: string | undefined, fallback: string): string => {\n return description && description.trim() ? description : fallback;\n};\n\nexport const getToolDescriptionInfo = (\n tool: ToolDescriptionSource,\n noDescriptionText: string,\n): ToolDescriptionInfo => {\n const currentDescription = normalizeDescription(tool.description, noDescriptionText);\n\n if (!tool.hasDescriptionOverride) {\n return {\n currentDescription,\n hasDescriptionOverride: false,\n };\n }\n\n return {\n currentDescription,\n defaultDescription: normalizeDescription(tool.defaultDescription, noDescriptionText),\n hasDescriptionOverride: true,\n };\n};\n","/**\n * Per-client MCP configuration presets for the copy actions (#1165).\n *\n * MCPHub hands out HTTP endpoints, so every preset describes the same target -\n * a name, an optional URL/headers pair (HTTP) or command/args/env triple\n * (stdio) - in the shape the selected client expects. Eleven of the fourteen\n * presets were verified against the upstream sources below (URLs re-checked\n * 2026-09, the month this file landed); the remaining three reuse the generic\n * `mcpServers` shape (or, for the generic-http escape hatch, the bare entry)\n * these copy actions always produced.\n *\n * Which clients document an explicit transport field, and which do not:\n * - Documents a transport field (the `type` key is written into the entry):\n * claude-code (`type: \"http\" | \"sse\" | \"stdio\"`; a remote entry with `url`\n * but no `type` is a configuration error per\n * https://code.claude.com/docs/en/mcp), vscode (`\"http\" | \"sse\" | \"stdio\"`,\n * final URL after the 2026-09 migration:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers),\n * codebuddy (`type` marked Required; fixed `\"http\"` for HTTP, `\"sse\"` for\n * SSE and `\"stdio\"` for stdio, per\n * https://www.codebuddy.ai/docs/cli/mcp), qoder (every remote\n * example carries `type`; for Streamable HTTP the doc says to configure the\n * URL the same way as SSE and the IDE auto-detects it, so the http target\n * deliberately keeps the bare `url` + `headers` shape rather than tagging\n * it `sse`; https://docs.qoder.com/zh/user-guide/chat/model-context-protocol),\n * cherry-studio (`baseUrl` + `'sse' | 'streamableHttp'`, strict schema),\n * opencode (`type: 'remote' | 'local'`).\n * - Field table does not list a transport key: cursor\n * (https://cursor.com/docs/mcp), trae (https://docs.trae.ai/ide/add-mcp-servers),\n * zcode (https://zcode.z.ai/en/docs/mcp-services), windsurf\n * (https://docs.windsurf.com/windsurf/cascade/mcp). The `type: \"sse\"` marker\n * the generic shape injects for SSE targets on these presets is added on\n * the assumption that unknown keys are ignored, not required by their\n * documented shape; it is kept because SSE upstreams must not be dialed as\n * streamable HTTP.\n * - Verified but the format carries no `type` key at all: codex (TOML;\n * `codex-rs/config/src/mcp_types.rs`,\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs).\n * (The generic-http escape hatch, one of the three unverified presets, is not\n * a \"no `type`\" format: for a remote target it always writes an explicit\n * `type` - `\"http\"`, or `\"sse\"` for an SSE upstream.)\n *\n * Upstream sources used:\n * - Claude Code MCP configuration: https://code.claude.com/docs/en/mcp\n * - Cursor MCP docs: https://cursor.com/docs/mcp\n * - VS Code MCP configuration reference:\n * https://code.visualstudio.com/docs/agent-customization/mcp-servers\n * - Codex `codex-rs/config/src/mcp_types.rs`:\n * https://github.com/openai/codex/blob/main/codex-rs/config/src/mcp_types.rs\n * - OpenCode mcp-servers docs: https://opencode.ai/docs/mcp-servers/\n * - Cherry Studio `mcpProtocolInstall.ts`:\n * https://github.com/CherryHQ/cherry-studio/blob/main/src/shared/data/types/mcpProtocolInstall.ts\n * - CodeBuddy MCP CLI docs: https://www.codebuddy.ai/docs/cli/mcp\n * - Qoder MCP user guide:\n * https://docs.qoder.com/zh/user-guide/chat/model-context-protocol\n * - Trae MCP docs: https://docs.trae.ai/ide/add-mcp-servers\n * - Windsurf MCP docs: https://docs.windsurf.com/windsurf/cascade/mcp\n * - ZCode MCP docs: https://zcode.z.ai/en/docs/mcp-services\n */\n\nexport type ClientSnippetId =\n | 'generic-mcp-servers'\n | 'generic-http'\n | 'claude-code'\n | 'cursor'\n | 'vscode'\n | 'codex'\n | 'opencode'\n | 'windsurf'\n | 'cherry-studio'\n | 'codebuddy'\n | 'qoder'\n | 'trae'\n | 'zcode'\n | 'workbuddy';\n\nexport interface ClientSnippetPreset {\n id: ClientSnippetId;\n}\n\n/** Tab the dialog opens on; the shape the copy actions produced before. */\nexport const DEFAULT_CLIENT_SNIPPET_ID: ClientSnippetId = 'generic-mcp-servers';\n\n/**\n * Tabs shown in the copy dialog, most common clients first. The first entry is\n * the shape the copy actions produced before the presets existed, so the\n * default tab stays familiar; the bare HTTP entry is the escape hatch for\n * clients that wrap the entry in their own container.\n */\nexport const CLIENT_SNIPPET_PRESETS: readonly ClientSnippetPreset[] = [\n { id: 'generic-mcp-servers' },\n { id: 'claude-code' },\n { id: 'cursor' },\n { id: 'vscode' },\n { id: 'codex' },\n { id: 'opencode' },\n { id: 'windsurf' },\n { id: 'cherry-studio' },\n { id: 'codebuddy' },\n { id: 'qoder' },\n { id: 'trae' },\n { id: 'zcode' },\n { id: 'workbuddy' },\n { id: 'generic-http' },\n];\n\nexport interface ClientSnippetTarget {\n name: string;\n /** Stored transport type; `sse` is called out so clients do not misdial it as http. */\n type?: 'stdio' | 'sse' | 'streamable-http' | 'openapi';\n /** HTTP targets carry a URL (and usually an Authorization header). */\n url?: string;\n headers?: Record<string, string>;\n /** stdio targets carry a command instead. */\n command?: string;\n args?: string[];\n env?: Record<string, string>;\n description?: string;\n}\n\nexport interface ClientSnippetBlock {\n kind: 'config' | 'command';\n text: string;\n}\n\nexport interface ClientSnippetOptions {\n /** Description used by the VS Code token input prompt. */\n tokenPromptDescription?: string;\n}\n\n/** Placeholder MCPHub uses for snippets that need a token pasted in by hand. */\nexport const ACCESS_TOKEN_PLACEHOLDER = '<your-access-token>';\nconst TOKEN_INPUT_ID = 'mcphub-token';\n\nconst isHttpTarget = (target: ClientSnippetTarget): boolean => Boolean(target.url);\n\nconst definedHeaders = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.headers ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst definedEnv = (target: ClientSnippetTarget): Record<string, string> | undefined => {\n const entries = Object.entries(target.env ?? {}).filter(([, value]) => value !== undefined);\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst stdioEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n const env = definedEnv(target);\n return {\n command: target.command ?? '',\n ...(args.length > 0 ? { args } : {}),\n ...(env ? { env } : {}),\n };\n};\n\n/**\n * HTTP/stdio entry for clients whose docs make the transport a required field.\n * Claude Code skips an entry that has a `url` but no `type` (it reads the\n * entry as stdio and reports a configuration error), and CodeBuddy's field\n * table marks `type` as Required, fixed to `\"http\"` for the HTTP form and\n * `\"sse\"` for the SSE form.\n *\n * Stdio targets differ between the two clients. Claude Code reads a type-less\n * entry as stdio (https://code.claude.com/docs/en/mcp), so its stdio shape\n * keeps the plain command/args/env form with no `type` key. CodeBuddy's docs\n * mark `type` as Required with the fixed value `\"stdio\"`\n * (https://www.codebuddy.ai/docs/cli/mcp), so its stdio shape writes\n * `\"type\": \"stdio\"`; pass `stdioType` only for CodeBuddy.\n */\nconst typedTransportEntry = (\n target: ClientSnippetTarget,\n stdioType: boolean = false,\n): Record<string, unknown> => {\n if (!isHttpTarget(target)) {\n return stdioType ? { type: 'stdio', ...stdioEntry(target) } : stdioEntry(target);\n }\n\n const headers = definedHeaders(target);\n return {\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\n// This helper feeds the generic `mcpServers` shape for the generic-mcp-servers,\n// qoder, cursor, windsurf, trae, zcode and workbuddy presets. Only qoder's\n// upstream docs carry a transport field for this shape; for the rest\n// (generic-mcp-servers, cursor, windsurf, trae, zcode, workbuddy) the\n// `type: \"sse\"` marker is added on the assumption that unknown keys are\n// ignored, so it is unverified against a field table. It is kept because an\n// SSE upstream must not be dialed as streamable HTTP.\nconst httpEntry = (target: ClientSnippetTarget): Record<string, unknown> => {\n const headers = definedHeaders(target);\n return {\n // Only `sse` is spelled out: it is the one HTTP transport a client might\n // otherwise misdial as streamable HTTP. Every other target keeps the bare\n // `url` + `headers` shape these presets always produced.\n ...(target.type === 'sse' ? { type: 'sse' } : {}),\n url: target.url ?? '',\n ...(headers ? { headers } : {}),\n };\n};\n\nconst withWrappedName = (\n wrapper: string,\n name: string,\n entry: Record<string, unknown>,\n): string => JSON.stringify({ [wrapper]: { [name]: entry } }, null, 2);\n\nconst jsonSnippet = (target: ClientSnippetTarget): string =>\n withWrappedName(\n 'mcpServers',\n target.name,\n isHttpTarget(target) ? httpEntry(target) : stdioEntry(target),\n );\n\n// VS Code wants the transport spelled out and can prompt for the token itself,\n// so the shared placeholder becomes an input reference plus an `inputs` entry.\nconst vscodeSnippet = (target: ClientSnippetTarget, options: ClientSnippetOptions): string => {\n const headers = definedHeaders(target);\n const placeholder = `Bearer ${ACCESS_TOKEN_PLACEHOLDER}`;\n const needsTokenInput = headers?.Authorization === placeholder;\n\n const body = needsTokenInput\n ? { ...headers, Authorization: `Bearer \\${input:${TOKEN_INPUT_ID}}` }\n : headers;\n\n const entry = isHttpTarget(target)\n ? {\n // VS Code distinguishes the SSE transport from streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'http',\n url: target.url,\n ...(body ? { headers: body } : {}),\n }\n : { type: 'stdio', ...stdioEntry(target) };\n\n return JSON.stringify(\n {\n servers: { [target.name]: entry },\n ...(needsTokenInput\n ? {\n inputs: [\n {\n id: TOKEN_INPUT_ID,\n type: 'promptString',\n description: options.tokenPromptDescription ?? 'MCPHub access token',\n password: true,\n },\n ],\n }\n : {}),\n },\n null,\n 2,\n );\n};\n\nconst TOML_BARE_KEY = /^[A-Za-z0-9_-]+$/;\n\nconst tomlKey = (key: string): string => (TOML_BARE_KEY.test(key) ? key : JSON.stringify(key));\nconst tomlValue = (value: string): string => JSON.stringify(value);\nconst tomlInlineTable = (entries: Record<string, string>): string =>\n `{ ${Object.entries(entries)\n .map(([key, value]) => `${tomlKey(key)} = ${tomlValue(value)}`)\n .join(', ')} }`;\n\n// Codex calls the header map `http_headers` (there is no `headers` key), and\n// needs quoted table keys for names that are not bare TOML keys - group names\n// may contain spaces or CJK. Note `#[schemars(deny_unknown_fields)]` in\n// `mcp_types.rs` only constrains the generated JSON Schema; the Rust struct\n// itself has no `#[serde(deny_unknown_fields)]`, so TOML parsing may silently\n// ignore unknown fields instead of rejecting them.\nconst codexSnippet = (target: ClientSnippetTarget): string => {\n const key = tomlKey(target.name);\n const lines = [`[mcp_servers.${key}]`];\n\n if (isHttpTarget(target)) {\n lines.push(`url = ${tomlValue(target.url ?? '')}`);\n const headers = definedHeaders(target);\n if (headers) {\n lines.push(`http_headers = ${tomlInlineTable(headers)}`);\n }\n return lines.join('\\n');\n }\n\n lines.push(`command = ${tomlValue(target.command ?? '')}`);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n if (args.length > 0) {\n lines.push(`args = [${args.map(tomlValue).join(', ')}]`);\n }\n const env = definedEnv(target);\n if (env) {\n lines.push('', `[mcp_servers.${key}.env]`);\n for (const [name, value] of Object.entries(env)) {\n lines.push(`${tomlKey(name)} = ${tomlValue(value)}`);\n }\n }\n return lines.join('\\n');\n};\n\nconst openCodeSnippet = (target: ClientSnippetTarget): string => {\n if (!isHttpTarget(target)) {\n const env = definedEnv(target);\n const args = target.args?.filter((arg) => arg !== undefined) ?? [];\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'local',\n command: [target.command ?? '', ...args],\n ...(env ? { environment: env } : {}),\n },\n },\n },\n null,\n 2,\n );\n }\n\n const headers = definedHeaders(target);\n return JSON.stringify(\n {\n mcp: {\n [target.name]: {\n type: 'remote',\n url: target.url,\n ...(headers ? { headers } : {}),\n },\n },\n },\n null,\n 2,\n );\n};\n\n// Cherry Studio's `ProtocolMcpServerConfigSchema` is a strict object: remote\n// servers use `baseUrl` + `type: 'sse' | 'streamableHttp'` (no `url` key) and\n// stdio servers use command/args/env. The install-time metadata\n// (`installSource`, `isTrusted`, `installedAt`, `isActive: false`) belongs to\n// `ProtocolMcpServerInstallSchema`, the install *request* schema, not to this\n// hand-pasted config; an entry carrying `isActive` would not satisfy\n// `ProtocolMcpServerConfigSchema` (which has no such key).\nconst cherryStudioSnippet = (target: ClientSnippetTarget): string => {\n const base = {\n name: target.name,\n description: target.description ?? '',\n };\n\n const headers = definedHeaders(target);\n const entry = isHttpTarget(target)\n ? {\n ...base,\n // The schema accepts exactly two remote transports; keep SSE upstreams\n // spelled out so Cherry Studio does not dial them as streamable HTTP.\n type: target.type === 'sse' ? 'sse' : 'streamableHttp',\n baseUrl: target.url,\n ...(headers ? { headers } : {}),\n }\n : { ...base, type: 'stdio', ...stdioEntry(target) };\n\n return withWrappedName('mcpServers', target.name, entry);\n};\n\nconst CLI_SAFE = /^[A-Za-z0-9._:@/=-]+$/;\n\n// Single quotes are the only reliable POSIX quoting for a pasted command:\n// double quotes still let the shell expand `$(...)`, backticks and `${...}`\n// inside them. Within single quotes nothing is expanded, so the only character\n// needing special handling is `'` itself, escaped as `'\\''` (close quote,\n// escaped quote, reopen).\nconst shellQuote = (value: string): string => `'${value.replace(/'/g, \"'\\\\''\")}'`;\n\nconst cliArg = (value: string): string =>\n CLI_SAFE.test(value) ? value : shellQuote(value);\n\n// Claude Code's one-liner equivalent of the JSON block, in the documented\n// HTTP shape: `claude mcp add --transport <t> <name> <url> [--header ...]`.\n//\n// A positional that starts with `-` cannot be spelled safely in that shape:\n// shell quoting is gone by the time the CLI's tokenizer sees the value, and\n// the documented `--` separator belongs to the stdio form, so relying on it\n// for the HTTP form would be an unverified parsing assumption. Since\n// SERVER_NAME_PATTERN admits names like `-foo`, a name or URL starting with\n// a dash omits the command block outright - the JSON config block still\n// carries the full entry - rather than emitting a command the CLI would\n// misparse as one of its own options.\nconst claudeCodeCommand = (target: ClientSnippetTarget): string | undefined => {\n if (!isHttpTarget(target)) {\n return undefined;\n }\n\n if (target.name.startsWith('-') || (target.url ?? '').startsWith('-')) {\n return undefined;\n }\n\n const parts = [\n 'claude',\n 'mcp',\n 'add',\n '--transport',\n // SSE endpoints must not be dialed as streamable HTTP.\n target.type === 'sse' ? 'sse' : 'http',\n cliArg(target.name),\n cliArg(target.url ?? ''),\n ];\n for (const [name, value] of Object.entries(definedHeaders(target) ?? {})) {\n parts.push('--header', cliArg(`${name}: ${value}`));\n }\n return parts.join(' ');\n};\n\nconst asString = (value: unknown): string | undefined =>\n typeof value === 'string' && value.length > 0 ? value : undefined;\n\n/** Narrow a stored `type` to the four legal server types; anything else is dropped. */\nconst asServerType = (value: unknown): ClientSnippetTarget['type'] => {\n switch (value) {\n case 'stdio':\n case 'sse':\n case 'streamable-http':\n case 'openapi':\n return value;\n default:\n return undefined;\n }\n};\n\nconst asStringRecord = (value: unknown): Record<string, string> | undefined => {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined;\n }\n\n const entries = Object.entries(value as Record<string, unknown>).filter(\n (entry): entry is [string, string] => typeof entry[1] === 'string',\n );\n return entries.length > 0 ? Object.fromEntries(entries) : undefined;\n};\n\nconst asStringArray = (value: unknown): string[] | undefined => {\n if (!Array.isArray(value)) {\n return undefined;\n }\n\n const items = value.filter((item): item is string => typeof item === 'string');\n return items.length > 0 ? items : undefined;\n};\n\n/**\n * Narrow a stored server configuration (the `mcp-settings/export` payload\n * carries MCPHub's internal fields too) down to what a client snippet needs.\n */\nexport const toClientSnippetTarget = (\n name: string,\n config: Record<string, unknown> | undefined,\n): ClientSnippetTarget => {\n const source = config ?? {};\n\n return {\n name,\n ...(asServerType(source.type) ? { type: asServerType(source.type) } : {}),\n ...(asString(source.url) ? { url: asString(source.url) } : {}),\n ...(asStringRecord(source.headers) ? { headers: asStringRecord(source.headers) } : {}),\n ...(asString(source.command) ? { command: asString(source.command) } : {}),\n ...(asStringArray(source.args) ? { args: asStringArray(source.args) } : {}),\n ...(asStringRecord(source.env) ? { env: asStringRecord(source.env) } : {}),\n ...(asString(source.description) ? { description: asString(source.description) } : {}),\n };\n};\n\nconst configSnippet = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions,\n): string => {\n switch (id) {\n case 'generic-mcp-servers':\n return jsonSnippet(target);\n case 'generic-http':\n return JSON.stringify(\n isHttpTarget(target)\n ? { type: 'http', ...httpEntry(target) }\n : stdioEntry(target),\n null,\n 2,\n );\n case 'vscode':\n return vscodeSnippet(target, options);\n case 'codex':\n return codexSnippet(target);\n case 'opencode':\n return openCodeSnippet(target);\n case 'cherry-studio':\n return cherryStudioSnippet(target);\n case 'claude-code':\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target));\n case 'codebuddy':\n // CodeBuddy's field table marks `type` as Required, fixed to `\"stdio\"`\n // for stdio entries, so unlike Claude Code it always carries the type.\n return withWrappedName('mcpServers', target.name, typedTransportEntry(target, true));\n default:\n return jsonSnippet(target);\n }\n};\n\nexport const buildClientSnippetBlocks = (\n id: ClientSnippetId,\n target: ClientSnippetTarget,\n options: ClientSnippetOptions = {},\n): ClientSnippetBlock[] => {\n // OpenAPI-backed servers carry neither a URL nor a command, so every preset\n // would degrade to filler like `command: \"\"`. Return no blocks and let the\n // dialog explain that there is no client-side transport to copy.\n if (!target.url && !target.command) {\n return [];\n }\n\n const blocks: ClientSnippetBlock[] = [{ kind: 'config', text: configSnippet(id, target, options) }];\n\n if (id === 'claude-code') {\n const command = claudeCodeCommand(target);\n if (command) {\n blocks.push({ kind: 'command', text: command });\n }\n }\n\n return blocks;\n};\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Check, Copy, X } from 'lucide-react';\nimport {\n buildClientSnippetBlocks,\n CLIENT_SNIPPET_PRESETS,\n DEFAULT_CLIENT_SNIPPET_ID,\n type ClientSnippetId,\n type ClientSnippetTarget,\n} from '@/utils/mcpClientSnippets';\nimport { copyText } from '@/utils/clipboard';\nimport { useToast } from '@/contexts/ToastContext';\n\ninterface CopyClientConfigDialogProps {\n isOpen: boolean;\n onClose: () => void;\n /** Target to render; `null` keeps the dialog closed. */\n target: ClientSnippetTarget | null;\n}\n\n/**\n * Per-client MCP configuration presets for the copy actions (#1165): one tab\n * per client, each with the path it belongs in and a ready-to-paste snippet.\n */\nconst CopyClientConfigDialog = ({ isOpen, onClose, target }: CopyClientConfigDialogProps) => {\n const { t } = useTranslation();\n const { showToast } = useToast();\n const [activeId, setActiveId] = useState<ClientSnippetId>(DEFAULT_CLIENT_SNIPPET_ID);\n const [copiedBlock, setCopiedBlock] = useState<string | null>(null);\n const dialogRef = useRef<HTMLDivElement>(null);\n const returnFocusRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n if (!isOpen) {\n setCopiedBlock(null);\n setActiveId(DEFAULT_CLIENT_SNIPPET_ID);\n }\n }, [isOpen]);\n\n // Like the other hand-rolled modals in this codebase the dialog does not trap\n // focus; it does move focus inside on open and hand it back to the trigger on\n // close, so keyboard users are not left behind on the page underneath.\n useEffect(() => {\n if (!isOpen) return;\n returnFocusRef.current =\n document.activeElement instanceof HTMLElement ? document.activeElement : null;\n dialogRef.current?.focus();\n\n return () => {\n returnFocusRef.current?.focus();\n };\n }, [isOpen]);\n\n useEffect(() => {\n if (!isOpen) return;\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') onClose();\n };\n document.addEventListener('keydown', onKeyDown);\n return () => document.removeEventListener('keydown', onKeyDown);\n }, [isOpen, onClose]);\n\n const blocks = useMemo(\n () =>\n target\n ? buildClientSnippetBlocks(activeId, target, {\n tokenPromptDescription: t('clientConfig.tokenPrompt'),\n })\n : [],\n [activeId, target, t],\n );\n\n if (!isOpen || !target) {\n return null;\n }\n\n const handleCopy = async (key: string, value: string) => {\n const ok = await copyText(value);\n if (!ok) {\n showToast(t('common.copyFailed'), 'error');\n return;\n }\n setCopiedBlock(key);\n showToast(t('common.copySuccess'), 'success');\n setTimeout(() => setCopiedBlock((current) => (current === key ? null : current)), 1500);\n };\n\n return (\n <div\n className=\"fixed inset-0 bg-black/50 z-[100] flex items-center justify-center p-4\"\n onClick={(event) => {\n if (event.target === event.currentTarget) onClose();\n }}\n >\n <div\n ref={dialogRef}\n tabIndex={-1}\n className=\"hub-card w-full max-w-2xl\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={t('clientConfig.title')}\n >\n <div\n className=\"flex items-start justify-between gap-3 px-4 py-3\"\n style={{ borderBottom: '1px solid var(--hub-line-2)' }}\n >\n <div className=\"min-w-0\">\n <div className=\"text-[14px] font-medium\" style={{ color: 'var(--hub-ink)' }}>\n {t('clientConfig.title')}\n </div>\n <div className=\"text-[12px] mt-0.5\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.description', { name: target.name })}\n </div>\n </div>\n <button className=\"hub-icon-btn sm\" onClick={onClose} aria-label={t('app.closeButton')}>\n <X size={13} />\n </button>\n </div>\n\n {/* A target with neither URL nor command (OpenAPI-backed servers) has no\n transport, so every preset returns the same empty result: offering 14\n clickable tabs would only suggest the dialog is broken. The tab strip\n and its per-client hint are therefore hidden and only the explanation\n below is shown. */}\n {blocks.length > 0 && (\n <div className=\"px-4 pt-3\">\n <div\n className=\"flex flex-wrap gap-1\"\n role=\"tablist\"\n aria-label={t('clientConfig.title')}\n >\n {CLIENT_SNIPPET_PRESETS.map((preset) => {\n const active = preset.id === activeId;\n return (\n <button\n key={preset.id}\n role=\"tab\"\n aria-selected={active}\n onClick={() => setActiveId(preset.id)}\n className=\"px-2.5 py-1 rounded-md text-[12px] transition-colors hover:bg-[var(--hub-surface-hover)]\"\n style={{\n background: active ? 'var(--hub-surface)' : 'transparent',\n border: '1px solid ' + (active ? 'var(--hub-line)' : 'transparent'),\n color: active ? 'var(--hub-ink)' : 'var(--hub-ink-2)',\n }}\n >\n {t(`clientConfig.clients.${preset.id}.label`)}\n </button>\n );\n })}\n </div>\n\n <p className=\"text-[12px] mt-3\" style={{ color: 'var(--hub-ink-3)' }}>\n {t(`clientConfig.clients.${activeId}.hint`)}\n </p>\n </div>\n )}\n\n <div className=\"px-4 pb-4 pt-2 space-y-3 max-h-[60vh] overflow-auto\">\n {blocks.length === 0 ? (\n // OpenAPI-backed servers have no client-side transport to copy.\n <p className=\"text-[12px]\" style={{ color: 'var(--hub-ink-3)' }}>\n {t('clientConfig.noTransport')}\n </p>\n ) : (\n blocks.map((block) => {\n const key = `${activeId}:${block.kind}`;\n const copied = copiedBlock === key;\n return (\n <div key={key}>\n <div className=\"flex items-center justify-between mb-1\">\n <span className=\"text-[12px]\" style={{ color: 'var(--hub-ink-2)' }}>\n {t(\n block.kind === 'command'\n ? 'clientConfig.commandBlock'\n : 'clientConfig.configBlock',\n )}\n </span>\n <button\n className=\"hub-btn sm\"\n onClick={() => void handleCopy(key, block.text)}\n >\n {copied ? <Check size={12} className=\"text-[var(--hub-ok)]\" /> : <Copy size={12} />}\n {copied ? t('clientConfig.copied') : t('common.copy')}\n </button>\n </div>\n <pre\n className=\"hub-mono m-0 p-3 rounded-md overflow-auto\"\n style={{\n background: 'var(--hub-bg-2)',\n border: '1px solid var(--hub-line-2)',\n fontSize: 12,\n lineHeight: 1.5,\n color: 'var(--hub-ink-2)',\n maxHeight: 320,\n }}\n >\n <code>{block.text}</code>\n </pre>\n </div>\n );\n })\n )}\n </div>\n\n <div\n className=\"flex justify-end px-4 py-3\"\n style={{ borderTop: '1px solid var(--hub-line-2)' }}\n >\n <button className=\"hub-btn\" onClick={onClose}>\n {t('common.cancel')}\n </button>\n </div>\n </div>\n </div>\n );\n};\n\nexport default CopyClientConfigDialog;\n","import type { Server } from '../types';\n\n// Ignore transient polling metadata, but include full definitions: equal tool\n// counts do not imply equal context costs.\nexport const serverCostRevision = (servers: Server[]): string =>\n JSON.stringify(\n servers.map(({ name, status, enabled, tools, prompts, resources }) => ({\n name,\n status,\n enabled,\n tools,\n prompts,\n resources,\n })),\n );\n"],"names":["normalizeDescription","description","fallback","getToolDescriptionInfo","tool","noDescriptionText","currentDescription","DEFAULT_CLIENT_SNIPPET_ID","CLIENT_SNIPPET_PRESETS","ACCESS_TOKEN_PLACEHOLDER","TOKEN_INPUT_ID","isHttpTarget","target","definedHeaders","entries","value","definedEnv","stdioEntry","args","_a","arg","env","typedTransportEntry","stdioType","headers","httpEntry","withWrappedName","wrapper","name","entry","jsonSnippet","vscodeSnippet","options","placeholder","needsTokenInput","body","TOML_BARE_KEY","tomlKey","key","tomlValue","tomlInlineTable","codexSnippet","lines","openCodeSnippet","cherryStudioSnippet","base","CLI_SAFE","shellQuote","cliArg","claudeCodeCommand","parts","asString","asServerType","asStringRecord","asStringArray","items","item","toClientSnippetTarget","config","source","configSnippet","id","buildClientSnippetBlocks","blocks","command","CopyClientConfigDialog","isOpen","onClose","useTranslation","showToast","useToast","activeId","setActiveId","useState","copiedBlock","setCopiedBlock","dialogRef","useRef","returnFocusRef","useEffect","onKeyDown","event","useMemo","handleCopy","copyText","current","jsx","jsxs","X","preset","active","block","copied","Check","Copy","serverCostRevision","servers","status","enabled","tools","prompts","resources"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ /*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */@layer properties{@supports ((-webkit-hyphens:none) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-space-y-reverse:0;--tw-space-x-reverse:0;--tw-divide-y-reverse:0;--tw-border-style:solid;--tw-gradient-position:initial;--tw-gradient-from:#0000;--tw-gradient-via:#0000;--tw-gradient-to:#0000;--tw-gradient-stops:initial;--tw-gradient-via-stops:initial;--tw-gradient-from-position:0%;--tw-gradient-via-position:50%;--tw-gradient-to-position:100%;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(97.1% .013 17.38);--color-red-100:oklch(93.6% .032 17.717);--color-red-200:oklch(88.5% .062 18.334);--color-red-300:oklch(80.8% .114 19.571);--color-red-400:oklch(70.4% .191 22.216);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-red-700:oklch(50.5% .213 27.518);--color-red-800:oklch(44.4% .177 26.899);--color-red-900:oklch(39.6% .141 25.723);--color-red-950:oklch(25.8% .092 26.042);--color-orange-50:oklch(98% .016 73.684);--color-orange-200:oklch(90.1% .076 70.697);--color-orange-300:oklch(83.7% .128 66.29);--color-orange-400:oklch(75% .183 55.934);--color-orange-700:oklch(55.3% .195 38.402);--color-orange-800:oklch(47% .157 37.304);--color-orange-900:oklch(40.8% .123 38.172);--color-amber-50:oklch(98.7% .022 95.277);--color-amber-100:oklch(96.2% .059 95.617);--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-amber-500:oklch(76.9% .188 70.08);--color-amber-600:oklch(66.6% .179 58.318);--color-amber-700:oklch(55.5% .163 48.998);--color-amber-800:oklch(47.3% .137 46.201);--color-amber-900:oklch(41.4% .112 45.904);--color-amber-950:oklch(27.9% .077 45.635);--color-yellow-50:oklch(98.7% .026 102.212);--color-yellow-100:oklch(97.3% .071 103.193);--color-yellow-200:oklch(94.5% .129 101.54);--color-yellow-300:oklch(90.5% .182 98.111);--color-yellow-400:oklch(85.2% .199 91.936);--color-yellow-500:oklch(79.5% .184 86.047);--color-yellow-600:oklch(68.1% .162 75.834);--color-yellow-700:oklch(55.4% .135 66.442);--color-yellow-800:oklch(47.6% .114 61.907);--color-yellow-900:oklch(42.1% .095 57.708);--color-yellow-950:oklch(28.6% .066 53.813);--color-green-50:oklch(98.2% .018 155.826);--color-green-100:oklch(96.2% .044 156.743);--color-green-200:oklch(92.5% .084 155.995);--color-green-300:oklch(87.1% .15 154.449);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-green-700:oklch(52.7% .154 150.069);--color-green-800:oklch(44.8% .119 151.328);--color-green-900:oklch(39.3% .095 152.535);--color-green-950:oklch(26.6% .065 152.934);--color-blue-50:oklch(97% .014 254.604);--color-blue-100:oklch(93.2% .032 255.585);--color-blue-200:oklch(88.2% .059 254.128);--color-blue-300:oklch(80.9% .105 251.813);--color-blue-400:oklch(70.7% .165 254.624);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-blue-700:oklch(48.8% .243 264.376);--color-blue-800:oklch(42.4% .199 265.638);--color-blue-900:oklch(37.9% .146 265.522);--color-blue-950:oklch(28.2% .091 267.935);--color-purple-100:oklch(94.6% .033 307.174);--color-purple-300:oklch(82.7% .119 306.383);--color-purple-400:oklch(71.4% .203 305.504);--color-purple-600:oklch(55.8% .288 302.321);--color-purple-800:oklch(43.8% .218 303.724);--color-purple-900:oklch(38.1% .176 304.987);--color-gray-50:oklch(98.5% .002 247.839);--color-gray-100:oklch(96.7% .003 264.542);--color-gray-200:oklch(92.8% .006 264.531);--color-gray-300:oklch(87.2% .01 258.338);--color-gray-400:oklch(70.7% .022 261.325);--color-gray-500:oklch(55.1% .027 264.364);--color-gray-600:oklch(44.6% .03 256.802);--color-gray-700:oklch(37.3% .034 259.733);--color-gray-800:oklch(27.8% .033 256.848);--color-gray-900:oklch(21% .034 264.665);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-md:28rem;--container-lg:32rem;--container-xl:36rem;--container-2xl:42rem;--container-3xl:48rem;--container-4xl:56rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-base:1rem;--text-base--line-height: 1.5 ;--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-xl:1.25rem;--text-xl--line-height:calc(1.75/1.25);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height: 1.2 ;--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--tracking-tight:-.025em;--tracking-wide:.025em;--tracking-wider:.05em;--leading-tight:1.25;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-out:cubic-bezier(0,0,.2,1);--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::-moz-placeholder{opacity:1}::placeholder{opacity:1}@supports (not (-webkit-appearance:-apple-pay-button)) or (contain-intrinsic-size:1px){::-moz-placeholder{color:currentColor}::placeholder{color:currentColor}@supports (color:color-mix(in lab,red,red)){::-moz-placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){-webkit-appearance:button;-moz-appearance:button;appearance:button}::file-selector-button{-webkit-appearance:button;-moz-appearance:button;appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}button:not(:disabled),[role=button]:not(:disabled){cursor:pointer}}@layer components;@layer utilities{.pointer-events-none{pointer-events:none}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.inset-0{inset:calc(var(--spacing)*0)}.inset-y-0{inset-block:calc(var(--spacing)*0)}.-top-1{top:calc(var(--spacing)*-1)}.top-0{top:calc(var(--spacing)*0)}.top-1\/2{top:50%}.top-2{top:calc(var(--spacing)*2)}.top-3{top:calc(var(--spacing)*3)}.top-4{top:calc(var(--spacing)*4)}.top-full{top:100%}.-right-0\.5{right:calc(var(--spacing)*-.5)}.-right-1{right:calc(var(--spacing)*-1)}.right-0{right:calc(var(--spacing)*0)}.right-1\.5{right:calc(var(--spacing)*1.5)}.right-2{right:calc(var(--spacing)*2)}.right-4{right:calc(var(--spacing)*4)}.-bottom-0\.5{bottom:calc(var(--spacing)*-.5)}.left-0{left:calc(var(--spacing)*0)}.-z-10{z-index:-10}.z-10{z-index:10}.z-20{z-index:20}.z-50{z-index:50}.z-\[60\]{z-index:60}.z-\[100\]{z-index:100}.m-0{margin:calc(var(--spacing)*0)}.-mx-1\.5{margin-inline:calc(var(--spacing)*-1.5)}.mx-1{margin-inline:calc(var(--spacing)*1)}.mx-4{margin-inline:calc(var(--spacing)*4)}.mx-auto{margin-inline:auto}.-my-1\.5{margin-block:calc(var(--spacing)*-1.5)}.my-4{margin-block:calc(var(--spacing)*4)}.my-6{margin-block:calc(var(--spacing)*6)}.mt-0\.5{margin-top:calc(var(--spacing)*.5)}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-1\.5{margin-top:calc(var(--spacing)*1.5)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.mt-5{margin-top:calc(var(--spacing)*5)}.mt-6{margin-top:calc(var(--spacing)*6)}.mr-1{margin-right:calc(var(--spacing)*1)}.mr-1\.5{margin-right:calc(var(--spacing)*1.5)}.mr-2{margin-right:calc(var(--spacing)*2)}.mr-3{margin-right:calc(var(--spacing)*3)}.mr-4{margin-right:calc(var(--spacing)*4)}.-mb-px{margin-bottom:-1px}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-1\.5{margin-bottom:calc(var(--spacing)*1.5)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.mb-5{margin-bottom:calc(var(--spacing)*5)}.mb-6{margin-bottom:calc(var(--spacing)*6)}.-ml-1{margin-left:calc(var(--spacing)*-1)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-1\.5{margin-left:calc(var(--spacing)*1.5)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-3{margin-left:calc(var(--spacing)*3)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-6{margin-left:calc(var(--spacing)*6)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.\!h-7{height:calc(var(--spacing)*7)!important}.\!h-\[30px\]{height:30px!important}.h-1\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-3{height:calc(var(--spacing)*3)}.h-3\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-5{height:calc(var(--spacing)*5)}.h-6{height:calc(var(--spacing)*6)}.h-7{height:calc(var(--spacing)*7)}.h-8{height:calc(var(--spacing)*8)}.h-10{height:calc(var(--spacing)*10)}.h-12{height:calc(var(--spacing)*12)}.h-20{height:calc(var(--spacing)*20)}.h-64{height:calc(var(--spacing)*64)}.h-96{height:calc(var(--spacing)*96)}.h-\[6px\]{height:6px}.h-\[18px\]{height:18px}.h-\[26px\]{height:26px}.h-\[38px\]{height:38px}.h-auto{height:auto}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-40{max-height:calc(var(--spacing)*40)}.max-h-48{max-height:calc(var(--spacing)*48)}.max-h-60{max-height:calc(var(--spacing)*60)}.max-h-64{max-height:calc(var(--spacing)*64)}.max-h-96{max-height:calc(var(--spacing)*96)}.max-h-\[60vh\]{max-height:60vh}.max-h-\[90vh\]{max-height:90vh}.max-h-\[calc\(90vh-120px\)\]{max-height:calc(90vh - 120px)}.max-h-\[calc\(100dvh-2rem\)\]{max-height:calc(100dvh - 2rem)}.max-h-screen{max-height:100vh}.min-h-0{min-height:calc(var(--spacing)*0)}.min-h-\[30px\]{min-height:30px}.min-h-\[38px\]{min-height:38px}.min-h-\[240px\]{min-height:240px}.min-h-screen{min-height:100vh}.\!w-\[30px\]{width:30px!important}.w-1\/2{width:50%}.w-2{width:calc(var(--spacing)*2)}.w-3{width:calc(var(--spacing)*3)}.w-3\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-5{width:calc(var(--spacing)*5)}.w-6{width:calc(var(--spacing)*6)}.w-7{width:calc(var(--spacing)*7)}.w-8{width:calc(var(--spacing)*8)}.w-10{width:calc(var(--spacing)*10)}.w-12{width:calc(var(--spacing)*12)}.w-14{width:calc(var(--spacing)*14)}.w-16{width:calc(var(--spacing)*16)}.w-20{width:calc(var(--spacing)*20)}.w-24{width:calc(var(--spacing)*24)}.w-40{width:calc(var(--spacing)*40)}.w-48{width:calc(var(--spacing)*48)}.w-56{width:calc(var(--spacing)*56)}.w-\[6px\]{width:6px}.w-\[30px\]{width:30px}.w-\[232px\]{width:232px}.w-full{width:100%}.max-w-2xl{max-width:var(--container-2xl)}.max-w-3xl{max-width:var(--container-3xl)}.max-w-4xl{max-width:var(--container-4xl)}.max-w-\[520px\]{max-width:520px}.max-w-\[1680px\]{max-width:1680px}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-md{max-width:var(--container-md)}.max-w-sm{max-width:var(--container-sm)}.max-w-xl{max-width:var(--container-xl)}.min-w-0{min-width:calc(var(--spacing)*0)}.min-w-48{min-width:calc(var(--spacing)*48)}.min-w-\[30px\]{min-width:30px}.min-w-\[100px\]{min-width:100px}.min-w-\[140px\]{min-width:140px}.min-w-\[200px\]{min-width:200px}.min-w-full{min-width:100%}.min-w-max{min-width:-moz-max-content;min-width:max-content}.flex-1{flex:1}.flex-\[2\]{flex:2}.flex-\[4\]{flex:4}.flex-shrink-0,.shrink-0{flex-shrink:0}.flex-grow{flex-grow:1}.basis-48{flex-basis:calc(var(--spacing)*48)}.translate-x-0{--tw-translate-x:calc(var(--spacing)*0);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-full{--tw-translate-x:100%;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\/2{--tw-translate-y: -50% ;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-full{--tw-translate-y:-100%;translate:var(--tw-translate-x)var(--tw-translate-y)}.rotate-0{rotate:none}.rotate-90{rotate:90deg}.rotate-180{rotate:180deg}.transform{transform:var(--tw-rotate-x,)var(--tw-rotate-y,)var(--tw-rotate-z,)var(--tw-skew-x,)var(--tw-skew-y,)}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-default{cursor:default}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.resize{resize:both}.resize-y{resize:vertical}.list-inside{list-style-position:inside}.list-disc{list-style-type:disc}.list-none{list-style-type:none}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-0\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-2\.5{gap:calc(var(--spacing)*2.5)}.gap-3{gap:calc(var(--spacing)*3)}.gap-3\.5{gap:calc(var(--spacing)*3.5)}.gap-4{gap:calc(var(--spacing)*4)}.gap-5{gap:calc(var(--spacing)*5)}.gap-px{gap:1px}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-3>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*3)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-5>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*5)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*5)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-6>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*6)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*6)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-8>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*8)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*8)*calc(1 - var(--tw-space-y-reverse)))}.gap-x-1\.5{-moz-column-gap:calc(var(--spacing)*1.5);column-gap:calc(var(--spacing)*1.5)}.gap-x-2{-moz-column-gap:calc(var(--spacing)*2);column-gap:calc(var(--spacing)*2)}.gap-x-3{-moz-column-gap:calc(var(--spacing)*3);column-gap:calc(var(--spacing)*3)}.gap-x-4{-moz-column-gap:calc(var(--spacing)*4);column-gap:calc(var(--spacing)*4)}:where(.space-x-2>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*2)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-3>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*3)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*3)*calc(1 - var(--tw-space-x-reverse)))}:where(.space-x-4>:not(:last-child)){--tw-space-x-reverse:0;margin-inline-start:calc(calc(var(--spacing)*4)*var(--tw-space-x-reverse));margin-inline-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-x-reverse)))}.gap-y-1{row-gap:calc(var(--spacing)*1)}.gap-y-2{row-gap:calc(var(--spacing)*2)}:where(.divide-y>:not(:last-child)){--tw-divide-y-reverse:0;border-bottom-style:var(--tw-border-style);border-top-style:var(--tw-border-style);border-top-width:calc(1px*var(--tw-divide-y-reverse));border-bottom-width:calc(1px*calc(1 - var(--tw-divide-y-reverse)))}:where(.divide-\[var\(--hub-line-2\)\]>:not(:last-child)){border-color:var(--hub-line-2)}:where(.divide-gray-200>:not(:last-child)){border-color:var(--color-gray-200)}.self-center{align-self:center}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overscroll-contain{overscroll-behavior:contain}.rounded{border-radius:.25rem}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-xl{border-radius:var(--radius-xl)}.rounded-t-\[9px\]{border-top-left-radius:9px;border-top-right-radius:9px}.rounded-t-lg{border-top-left-radius:var(--radius-lg);border-top-right-radius:var(--radius-lg)}.rounded-t-md{border-top-left-radius:var(--radius-md);border-top-right-radius:var(--radius-md)}.rounded-b{border-bottom-right-radius:.25rem;border-bottom-left-radius:.25rem}.rounded-b-md{border-bottom-right-radius:var(--radius-md);border-bottom-left-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-0{border-top-style:var(--tw-border-style);border-top-width:0}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-\[oklch\(0\.88_0\.04_85\)\]{border-color:#e4d6ba}.border-\[oklch\(0\.88_0\.04_145\)\]{border-color:#c8dfc8}.border-\[var\(--hub-line\)\]{border-color:var(--hub-line)}.border-\[var\(--hub-line-2\)\]{border-color:var(--hub-line-2)}.border-amber-200{border-color:var(--color-amber-200)}.border-amber-300{border-color:var(--color-amber-300)}.border-blue-200{border-color:var(--color-blue-200)}.border-blue-300{border-color:var(--color-blue-300)}.border-blue-500{border-color:var(--color-blue-500)}.border-gray-100{border-color:var(--color-gray-100)}.border-gray-200{border-color:var(--color-gray-200)}.border-gray-300{border-color:var(--color-gray-300)}.border-gray-500{border-color:var(--color-gray-500)}.border-green-200{border-color:var(--color-green-200)}.border-green-400{border-color:var(--color-green-400)}.border-green-500{border-color:var(--color-green-500)}.border-orange-200{border-color:var(--color-orange-200)}.border-red-200{border-color:var(--color-red-200)}.border-red-300{border-color:var(--color-red-300)}.border-red-400{border-color:var(--color-red-400)}.border-red-500{border-color:var(--color-red-500)}.border-transparent{border-color:#0000}.border-yellow-200{border-color:var(--color-yellow-200)}.border-yellow-500{border-color:var(--color-yellow-500)}.border-l-blue-500{border-left-color:var(--color-blue-500)}.border-l-green-500{border-left-color:var(--color-green-500)}.border-l-red-600{border-left-color:var(--color-red-600)}.border-l-yellow-500{border-left-color:var(--color-yellow-500)}.bg-\[\#13C3FF\]{background-color:#13c3ff}.bg-\[oklch\(0\.97_0\.02_85\)\]{background-color:#fbf4e6}.bg-\[oklch\(0\.97_0\.03_145\)\]{background-color:#e9fbe9}.bg-\[var\(--hub-bg-2\)\]{background-color:var(--hub-bg-2)}.bg-\[var\(--hub-surface\)\]{background-color:var(--hub-surface)}.bg-amber-50{background-color:var(--color-amber-50)}.bg-amber-100{background-color:var(--color-amber-100)}.bg-black\/50{background-color:#00000080}@supports (color:color-mix(in lab,red,red)){.bg-black\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-blue-50{background-color:var(--color-blue-50)}.bg-blue-100{background-color:var(--color-blue-100)}.bg-blue-400\/80{background-color:#54a2ffcc}@supports (color:color-mix(in lab,red,red)){.bg-blue-400\/80{background-color:color-mix(in oklab,var(--color-blue-400)80%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-gray-50{background-color:var(--color-gray-50)}.bg-gray-100{background-color:var(--color-gray-100)}.bg-gray-200{background-color:var(--color-gray-200)}.bg-gray-400{background-color:var(--color-gray-400)}.bg-gray-400\/80{background-color:#99a1afcc}@supports (color:color-mix(in lab,red,red)){.bg-gray-400\/80{background-color:color-mix(in oklab,var(--color-gray-400)80%,transparent)}}.bg-gray-900{background-color:var(--color-gray-900)}.bg-green-50{background-color:var(--color-green-50)}.bg-green-100{background-color:var(--color-green-100)}.bg-green-400\/80{background-color:#05df72cc}@supports (color:color-mix(in lab,red,red)){.bg-green-400\/80{background-color:color-mix(in oklab,var(--color-green-400)80%,transparent)}}.bg-green-600{background-color:var(--color-green-600)}.bg-orange-50{background-color:var(--color-orange-50)}.bg-orange-400\/80{background-color:#ff8b1acc}@supports (color:color-mix(in lab,red,red)){.bg-orange-400\/80{background-color:color-mix(in oklab,var(--color-orange-400)80%,transparent)}}.bg-purple-100{background-color:var(--color-purple-100)}.bg-purple-400\/80{background-color:#c07effcc}@supports (color:color-mix(in lab,red,red)){.bg-purple-400\/80{background-color:color-mix(in oklab,var(--color-purple-400)80%,transparent)}}.bg-red-50{background-color:var(--color-red-50)}.bg-red-100{background-color:var(--color-red-100)}.bg-red-400\/80{background-color:#ff6568cc}@supports (color:color-mix(in lab,red,red)){.bg-red-400\/80{background-color:color-mix(in oklab,var(--color-red-400)80%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/60{background-color:#fff9}@supports (color:color-mix(in lab,red,red)){.bg-white\/60{background-color:color-mix(in oklab,var(--color-white)60%,transparent)}}.bg-yellow-50{background-color:var(--color-yellow-50)}.bg-yellow-100{background-color:var(--color-yellow-100)}.bg-yellow-400\/80{background-color:#fac800cc}@supports (color:color-mix(in lab,red,red)){.bg-yellow-400\/80{background-color:color-mix(in oklab,var(--color-yellow-400)80%,transparent)}}.bg-gradient-to-br{--tw-gradient-position:to bottom right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.bg-gradient-to-r{--tw-gradient-position:to right in oklab;background-image:linear-gradient(var(--tw-gradient-stops))}.from-blue-500{--tw-gradient-from:var(--color-blue-500);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.from-gray-100{--tw-gradient-from:var(--color-gray-100);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-gray-200{--tw-gradient-to:var(--color-gray-200);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.to-purple-600{--tw-gradient-to:var(--color-purple-600);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.object-cover{-o-object-fit:cover;object-fit:cover}.\!p-0{padding:calc(var(--spacing)*0)!important}.p-0{padding:calc(var(--spacing)*0)}.p-0\.5{padding:calc(var(--spacing)*.5)}.p-1{padding:calc(var(--spacing)*1)}.p-1\.5{padding:calc(var(--spacing)*1.5)}.p-2{padding:calc(var(--spacing)*2)}.p-2\.5{padding:calc(var(--spacing)*2.5)}.p-3{padding:calc(var(--spacing)*3)}.p-3\.5{padding:calc(var(--spacing)*3.5)}.p-4{padding:calc(var(--spacing)*4)}.p-5{padding:calc(var(--spacing)*5)}.p-6{padding:calc(var(--spacing)*6)}.p-8{padding:calc(var(--spacing)*8)}.p-10{padding:calc(var(--spacing)*10)}.p-12{padding:calc(var(--spacing)*12)}.\!px-2{padding-inline:calc(var(--spacing)*2)!important}.px-1{padding-inline:calc(var(--spacing)*1)}.px-1\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-3\.5{padding-inline:calc(var(--spacing)*3.5)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-6{padding-inline:calc(var(--spacing)*6)}.py-0\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.py-5{padding-block:calc(var(--spacing)*5)}.py-12{padding-block:calc(var(--spacing)*12)}.pt-1{padding-top:calc(var(--spacing)*1)}.pt-2{padding-top:calc(var(--spacing)*2)}.pt-3{padding-top:calc(var(--spacing)*3)}.pt-4{padding-top:calc(var(--spacing)*4)}.pt-6{padding-top:calc(var(--spacing)*6)}.pr-7{padding-right:calc(var(--spacing)*7)}.pr-8{padding-right:calc(var(--spacing)*8)}.pr-9{padding-right:calc(var(--spacing)*9)}.pb-1\.5{padding-bottom:calc(var(--spacing)*1.5)}.pb-2{padding-bottom:calc(var(--spacing)*2)}.pb-3{padding-bottom:calc(var(--spacing)*3)}.pb-4{padding-bottom:calc(var(--spacing)*4)}.pb-5{padding-bottom:calc(var(--spacing)*5)}.pb-16{padding-bottom:calc(var(--spacing)*16)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.pl-5{padding-left:calc(var(--spacing)*5)}.text-center{text-align:center}.text-left{text-align:left}.text-right{text-align:right}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10\.5px\]{font-size:10.5px}.text-\[10px\]{font-size:10px}.text-\[11\.5px\]{font-size:11.5px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.leading-5{--tw-leading:calc(var(--spacing)*5);line-height:calc(var(--spacing)*5)}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[oklch\(0\.42_0\.12_145\)\]{color:#135d1d}.text-\[oklch\(0\.45_0\.07_85\)\]{color:#675223}.text-\[var\(--hub-err\)\]{color:var(--hub-err)}.text-\[var\(--hub-ink\)\]{color:var(--hub-ink)}.text-\[var\(--hub-ink-2\)\]{color:var(--hub-ink-2)}.text-\[var\(--hub-ink-3\)\]{color:var(--hub-ink-3)}.text-\[var\(--hub-ok\)\]{color:var(--hub-ok)}.text-amber-400{color:var(--color-amber-400)}.text-amber-600{color:var(--color-amber-600)}.text-amber-700{color:var(--color-amber-700)}.text-amber-800{color:var(--color-amber-800)}.text-amber-900{color:var(--color-amber-900)}.text-blue-500{color:var(--color-blue-500)}.text-blue-600{color:var(--color-blue-600)}.text-blue-700{color:var(--color-blue-700)}.text-blue-800{color:var(--color-blue-800)}.text-blue-900{color:var(--color-blue-900)}.text-gray-100{color:var(--color-gray-100)}.text-gray-400{color:var(--color-gray-400)}.text-gray-500{color:var(--color-gray-500)}.text-gray-600{color:var(--color-gray-600)}.text-gray-700{color:var(--color-gray-700)}.text-gray-800{color:var(--color-gray-800)}.text-gray-900{color:var(--color-gray-900)}.text-green-200{color:var(--color-green-200)}.text-green-500{color:var(--color-green-500)}.text-green-600{color:var(--color-green-600)}.text-green-700{color:var(--color-green-700)}.text-green-800{color:var(--color-green-800)}.text-orange-700{color:var(--color-orange-700)}.text-orange-800{color:var(--color-orange-800)}.text-purple-800{color:var(--color-purple-800)}.text-red-400{color:var(--color-red-400)}.text-red-500{color:var(--color-red-500)}.text-red-600{color:var(--color-red-600)}.text-red-700{color:var(--color-red-700)}.text-red-800{color:var(--color-red-800)}.text-white{color:var(--color-white)}.text-yellow-400{color:var(--color-yellow-400)}.text-yellow-500{color:var(--color-yellow-500)}.text-yellow-600{color:var(--color-yellow-600)}.text-yellow-700{color:var(--color-yellow-700)}.text-yellow-800{color:var(--color-yellow-800)}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline-offset-4{text-underline-offset:4px}.accent-\[var\(--hub-accent\)\]{accent-color:var(--hub-accent)}.opacity-0{opacity:0}.opacity-25{opacity:.25}.opacity-50{opacity:.5}.opacity-60{opacity:.6}.opacity-75{opacity:.75}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-1{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.ring-\[var\(--hub-line\)\]{--tw-ring-color:var(--hub-line)}.ring-blue-500{--tw-ring-color:var(--color-blue-500)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.invert{--tw-invert:invert(100%);filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\[width\]{transition-property:width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.ring-inset{--tw-ring-inset:inset}@media(hover:hover){.group-hover\:-translate-x-1:is(:where(.group):hover *){--tw-translate-x:calc(var(--spacing)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.group-hover\:text-\[var\(--hub-ink-2\)\]:is(:where(.group):hover *){color:var(--hub-ink-2)}.group-hover\:opacity-100:is(:where(.group):hover *){opacity:1}}.file\:mr-4::file-selector-button{margin-right:calc(var(--spacing)*4)}.file\:rounded-md::file-selector-button{border-radius:var(--radius-md)}.file\:border-0::file-selector-button{border-style:var(--tw-border-style);border-width:0}.file\:bg-blue-50::file-selector-button{background-color:var(--color-blue-50)}.file\:px-4::file-selector-button{padding-inline:calc(var(--spacing)*4)}.file\:py-2::file-selector-button{padding-block:calc(var(--spacing)*2)}.file\:text-sm::file-selector-button{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.file\:font-semibold::file-selector-button{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.file\:text-blue-700::file-selector-button{color:var(--color-blue-700)}.placeholder\:text-\[var\(--hub-ink-3\)\]::-moz-placeholder{color:var(--hub-ink-3)}.placeholder\:text-\[var\(--hub-ink-3\)\]::placeholder{color:var(--hub-ink-3)}.last\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}@media(hover:hover){.hover\:border-\[var\(--hub-ink-3\)\]:hover{border-color:var(--hub-ink-3)}.hover\:border-blue-400:hover{border-color:var(--color-blue-400)}.hover\:border-gray-300:hover{border-color:var(--color-gray-300)}.hover\:border-gray-400:hover{border-color:var(--color-gray-400)}.hover\:bg-\[\#00A5E5\]:hover{background-color:#00a5e5}.hover\:bg-\[var\(--hub-surface-hover\)\]:hover{background-color:var(--hub-surface-hover)}.hover\:bg-amber-200:hover{background-color:var(--color-amber-200)}.hover\:bg-blue-50:hover{background-color:var(--color-blue-50)}.hover\:bg-blue-100:hover{background-color:var(--color-blue-100)}.hover\:bg-blue-200:hover{background-color:var(--color-blue-200)}.hover\:bg-blue-600:hover{background-color:var(--color-blue-600)}.hover\:bg-gray-50:hover{background-color:var(--color-gray-50)}.hover\:bg-gray-100:hover{background-color:var(--color-gray-100)}.hover\:bg-gray-200:hover{background-color:var(--color-gray-200)}.hover\:bg-gray-300:hover{background-color:var(--color-gray-300)}.hover\:bg-green-100:hover{background-color:var(--color-green-100)}.hover\:bg-red-100:hover{background-color:var(--color-red-100)}.hover\:bg-red-600:hover{background-color:var(--color-red-600)}.hover\:bg-yellow-100:hover{background-color:var(--color-yellow-100)}.hover\:text-\[var\(--hub-ink\)\]:hover{color:var(--hub-ink)}.hover\:text-\[var\(--hub-ink-2\)\]:hover{color:var(--hub-ink-2)}.hover\:text-amber-700:hover{color:var(--color-amber-700)}.hover\:text-blue-600:hover{color:var(--color-blue-600)}.hover\:text-blue-800:hover{color:var(--color-blue-800)}.hover\:text-blue-900:hover{color:var(--color-blue-900)}.hover\:text-gray-500:hover{color:var(--color-gray-500)}.hover\:text-gray-600:hover{color:var(--color-gray-600)}.hover\:text-gray-700:hover{color:var(--color-gray-700)}.hover\:text-gray-900:hover{color:var(--color-gray-900)}.hover\:text-red-600:hover{color:var(--color-red-600)}.hover\:text-red-700:hover{color:var(--color-red-700)}.hover\:text-red-900:hover{color:var(--color-red-900)}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-80:hover{opacity:.8}.hover\:file\:bg-blue-100:hover::file-selector-button{background-color:var(--color-blue-100)}}.focus\:border-\[var\(--hub-ink-2\)\]:focus{border-color:var(--hub-ink-2)}.focus\:border-blue-500:focus{border-color:var(--color-blue-500)}.focus\:border-transparent:focus{border-color:#0000}.focus\:ring-1:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\:ring-amber-500:focus{--tw-ring-color:var(--color-amber-500)}.focus\:ring-blue-500:focus{--tw-ring-color:var(--color-blue-500)}.focus\:ring-green-500:focus{--tw-ring-color:var(--color-green-500)}.focus\:ring-red-500:focus{--tw-ring-color:var(--color-red-500)}.focus\:ring-yellow-500:focus{--tw-ring-color:var(--color-yellow-500)}.focus\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\:outline-none:focus{--tw-outline-style:none;outline-style:none}.active\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}@media(min-width:40rem){.sm\:w-auto{width:auto}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:grid-cols-\[1fr_1fr_auto\]{grid-template-columns:1fr 1fr auto}.sm\:flex-row{flex-direction:row}.sm\:justify-between{justify-content:space-between}.sm\:gap-3{gap:calc(var(--spacing)*3)}.sm\:p-6{padding:calc(var(--spacing)*6)}.sm\:text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}}@media(min-width:48rem){.md\:col-span-1{grid-column:span 1/span 1}.md\:col-span-2{grid-column:span 2/span 2}.md\:col-span-3{grid-column:span 3/span 3}.md\:col-span-4{grid-column:span 4/span 4}.md\:col-span-9{grid-column:span 9/span 9}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.md\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}.md\:grid-cols-6{grid-template-columns:repeat(6,minmax(0,1fr))}.md\:grid-cols-12{grid-template-columns:repeat(12,minmax(0,1fr))}}@media(min-width:64rem){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:px-8{padding-inline:calc(var(--spacing)*8)}}@media(min-width:80rem){.xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.xl\:px-10{padding-inline:calc(var(--spacing)*10)}}:where(.dark\:divide-gray-700:where(.dark,.dark *)>:not(:last-child)){border-color:var(--color-gray-700)}.dark\:border-amber-700:where(.dark,.dark *){border-color:var(--color-amber-700)}.dark\:border-amber-700\/60:where(.dark,.dark *){border-color:#b7500099}@supports (color:color-mix(in lab,red,red)){.dark\:border-amber-700\/60:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-amber-700)60%,transparent)}}.dark\:border-amber-900\/50:where(.dark,.dark *){border-color:#7b330680}@supports (color:color-mix(in lab,red,red)){.dark\:border-amber-900\/50:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-amber-900)50%,transparent)}}.dark\:border-blue-700\/60:where(.dark,.dark *){border-color:#1447e699}@supports (color:color-mix(in lab,red,red)){.dark\:border-blue-700\/60:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-blue-700)60%,transparent)}}.dark\:border-blue-800:where(.dark,.dark *){border-color:var(--color-blue-800)}.dark\:border-blue-900:where(.dark,.dark *){border-color:var(--color-blue-900)}.dark\:border-gray-600:where(.dark,.dark *){border-color:var(--color-gray-600)}.dark\:border-gray-700:where(.dark,.dark *){border-color:var(--color-gray-700)}.dark\:border-green-800:where(.dark,.dark *){border-color:var(--color-green-800)}.dark\:border-orange-700\/60:where(.dark,.dark *){border-color:#c53c0099}@supports (color:color-mix(in lab,red,red)){.dark\:border-orange-700\/60:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-orange-700)60%,transparent)}}.dark\:border-red-700\/60:where(.dark,.dark *){border-color:#bf000f99}@supports (color:color-mix(in lab,red,red)){.dark\:border-red-700\/60:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-red-700)60%,transparent)}}.dark\:border-red-800:where(.dark,.dark *){border-color:var(--color-red-800)}.dark\:border-red-900\/50:where(.dark,.dark *){border-color:#82181a80}@supports (color:color-mix(in lab,red,red)){.dark\:border-red-900\/50:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-red-900)50%,transparent)}}.dark\:border-yellow-700\/60:where(.dark,.dark *){border-color:#a3610099}@supports (color:color-mix(in lab,red,red)){.dark\:border-yellow-700\/60:where(.dark,.dark *){border-color:color-mix(in oklab,var(--color-yellow-700)60%,transparent)}}.dark\:border-yellow-800:where(.dark,.dark *){border-color:var(--color-yellow-800)}.dark\:bg-amber-900\/20:where(.dark,.dark *){background-color:#7b330633}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)20%,transparent)}}.dark\:bg-amber-900\/40:where(.dark,.dark *){background-color:#7b330666}@supports (color:color-mix(in lab,red,red)){.dark\:bg-amber-900\/40:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-amber-900)40%,transparent)}}.dark\:bg-amber-950:where(.dark,.dark *){background-color:var(--color-amber-950)}.dark\:bg-blue-900\/20:where(.dark,.dark *){background-color:#1c398e33}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-blue-900)20%,transparent)}}.dark\:bg-blue-900\/40:where(.dark,.dark *){background-color:#1c398e66}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-900\/40:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-blue-900)40%,transparent)}}.dark\:bg-blue-950:where(.dark,.dark *){background-color:var(--color-blue-950)}.dark\:bg-blue-950\/30:where(.dark,.dark *){background-color:#1624564d}@supports (color:color-mix(in lab,red,red)){.dark\:bg-blue-950\/30:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-blue-950)30%,transparent)}}.dark\:bg-gray-700:where(.dark,.dark *){background-color:var(--color-gray-700)}.dark\:bg-gray-800:where(.dark,.dark *){background-color:var(--color-gray-800)}.dark\:bg-gray-800\/60:where(.dark,.dark *){background-color:#1e293999}@supports (color:color-mix(in lab,red,red)){.dark\:bg-gray-800\/60:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-gray-800)60%,transparent)}}.dark\:bg-gray-900:where(.dark,.dark *){background-color:var(--color-gray-900)}.dark\:bg-green-900:where(.dark,.dark *){background-color:var(--color-green-900)}.dark\:bg-green-900\/20:where(.dark,.dark *){background-color:#0d542b33}@supports (color:color-mix(in lab,red,red)){.dark\:bg-green-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-green-900)20%,transparent)}}.dark\:bg-green-950:where(.dark,.dark *){background-color:var(--color-green-950)}.dark\:bg-orange-900\/20:where(.dark,.dark *){background-color:#7e2a0c33}@supports (color:color-mix(in lab,red,red)){.dark\:bg-orange-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-orange-900)20%,transparent)}}.dark\:bg-purple-900\/40:where(.dark,.dark *){background-color:#59168b66}@supports (color:color-mix(in lab,red,red)){.dark\:bg-purple-900\/40:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-purple-900)40%,transparent)}}.dark\:bg-red-900:where(.dark,.dark *){background-color:var(--color-red-900)}.dark\:bg-red-900\/20:where(.dark,.dark *){background-color:#82181a33}@supports (color:color-mix(in lab,red,red)){.dark\:bg-red-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-red-900)20%,transparent)}}.dark\:bg-red-950:where(.dark,.dark *){background-color:var(--color-red-950)}.dark\:bg-yellow-900\/20:where(.dark,.dark *){background-color:#733e0a33}@supports (color:color-mix(in lab,red,red)){.dark\:bg-yellow-900\/20:where(.dark,.dark *){background-color:color-mix(in oklab,var(--color-yellow-900)20%,transparent)}}.dark\:bg-yellow-950:where(.dark,.dark *){background-color:var(--color-yellow-950)}.dark\:from-gray-800:where(.dark,.dark *){--tw-gradient-from:var(--color-gray-800);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.dark\:to-gray-700:where(.dark,.dark *){--tw-gradient-to:var(--color-gray-700);--tw-gradient-stops:var(--tw-gradient-via-stops,var(--tw-gradient-position),var(--tw-gradient-from)var(--tw-gradient-from-position),var(--tw-gradient-to)var(--tw-gradient-to-position))}.dark\:text-amber-200:where(.dark,.dark *){color:var(--color-amber-200)}.dark\:text-amber-300:where(.dark,.dark *){color:var(--color-amber-300)}.dark\:text-amber-400:where(.dark,.dark *){color:var(--color-amber-400)}.dark\:text-amber-500:where(.dark,.dark *){color:var(--color-amber-500)}.dark\:text-blue-100:where(.dark,.dark *){color:var(--color-blue-100)}.dark\:text-blue-200:where(.dark,.dark *){color:var(--color-blue-200)}.dark\:text-blue-300:where(.dark,.dark *){color:var(--color-blue-300)}.dark\:text-blue-400:where(.dark,.dark *){color:var(--color-blue-400)}.dark\:text-gray-100:where(.dark,.dark *){color:var(--color-gray-100)}.dark\:text-gray-300:where(.dark,.dark *){color:var(--color-gray-300)}.dark\:text-gray-400:where(.dark,.dark *){color:var(--color-gray-400)}.dark\:text-gray-500:where(.dark,.dark *){color:var(--color-gray-500)}.dark\:text-green-200:where(.dark,.dark *){color:var(--color-green-200)}.dark\:text-green-300:where(.dark,.dark *){color:var(--color-green-300)}.dark\:text-green-400:where(.dark,.dark *){color:var(--color-green-400)}.dark\:text-orange-300:where(.dark,.dark *){color:var(--color-orange-300)}.dark\:text-purple-300:where(.dark,.dark *){color:var(--color-purple-300)}.dark\:text-red-200:where(.dark,.dark *){color:var(--color-red-200)}.dark\:text-red-300:where(.dark,.dark *){color:var(--color-red-300)}.dark\:text-red-400:where(.dark,.dark *){color:var(--color-red-400)}.dark\:text-red-500:where(.dark,.dark *){color:var(--color-red-500)}.dark\:text-white:where(.dark,.dark *){color:var(--color-white)}.dark\:text-yellow-200:where(.dark,.dark *){color:var(--color-yellow-200)}.dark\:text-yellow-300:where(.dark,.dark *){color:var(--color-yellow-300)}.dark\:text-yellow-400:where(.dark,.dark *){color:var(--color-yellow-400)}@media(hover:hover){.dark\:hover\:bg-amber-900\/60:where(.dark,.dark *):hover{background-color:#7b330699}@supports (color:color-mix(in lab,red,red)){.dark\:hover\:bg-amber-900\/60:where(.dark,.dark *):hover{background-color:color-mix(in oklab,var(--color-amber-900)60%,transparent)}}.dark\:hover\:bg-blue-900:where(.dark,.dark *):hover{background-color:var(--color-blue-900)}.dark\:hover\:bg-gray-100:where(.dark,.dark *):hover{background-color:var(--color-gray-100)}.dark\:hover\:bg-gray-600:where(.dark,.dark *):hover{background-color:var(--color-gray-600)}.dark\:hover\:bg-gray-700:where(.dark,.dark *):hover{background-color:var(--color-gray-700)}.dark\:hover\:bg-gray-800:where(.dark,.dark *):hover{background-color:var(--color-gray-800)}.dark\:hover\:bg-green-900:where(.dark,.dark *):hover{background-color:var(--color-green-900)}.dark\:hover\:bg-red-900:where(.dark,.dark *):hover{background-color:var(--color-red-900)}.dark\:hover\:bg-yellow-900:where(.dark,.dark *):hover{background-color:var(--color-yellow-900)}.dark\:hover\:text-gray-200:where(.dark,.dark *):hover{color:var(--color-gray-200)}.dark\:hover\:text-gray-300:where(.dark,.dark *):hover{color:var(--color-gray-300)}.dark\:hover\:text-gray-400:where(.dark,.dark *):hover{color:var(--color-gray-400)}}.dark\:focus\:ring-amber-400:where(.dark,.dark *):focus{--tw-ring-color:var(--color-amber-400)}.dark\:focus\:ring-offset-gray-900:where(.dark,.dark *):focus{--tw-ring-offset-color:var(--color-gray-900)}}:root{color-scheme:light;--hub-bg:oklch(98.5% .002 250);--hub-bg-2:oklch(97.5% .002 250);--hub-surface:#fff;--hub-surface-hover:oklch(97% .003 250);--hub-switch-track-on:oklch(30% .004 250);--hub-ink:oklch(18% .01 250);--hub-ink-2:oklch(42% .01 250);--hub-ink-3:oklch(60% .01 250);--hub-line:oklch(92% .004 250);--hub-line-2:oklch(96% .003 250);--hub-accent:oklch(55% .15 250);--hub-accent-soft:oklch(95% .04 250);--hub-ok:oklch(66% .15 145);--hub-warn:oklch(78% .13 80);--hub-err:oklch(62% .18 25);--hub-mono:"Geist Mono","JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace}.dark{color-scheme:dark;--hub-bg:oklch(18% .005 250);--hub-bg-2:oklch(21% .005 250);--hub-surface:oklch(22% .005 250);--hub-surface-hover:oklch(25% .005 250);--hub-switch-track-on:oklch(86% .004 250);--hub-ink:oklch(97% .005 250);--hub-ink-2:oklch(78% .005 250);--hub-ink-3:oklch(55% .005 250);--hub-line:oklch(30% .005 250);--hub-line-2:oklch(26% .005 250);--hub-accent-soft:oklch(32% .06 250)}.hub-card{background:var(--hub-surface);border:1px solid var(--hub-line);border-radius:10px}.hub-card-pad{padding:16px}.hub-surface{background:var(--hub-surface)}.hub-bg-2{background:var(--hub-bg-2)}.hub-border{border:1px solid var(--hub-line)}.hub-border-b{border-bottom:1px solid var(--hub-line-2)}.hub-border-t,.hub-divider>*+*{border-top:1px solid var(--hub-line-2)}.hub-mono{font-family:var(--hub-mono);font-feature-settings:"ss01";letter-spacing:-.01em}.hub-num{font-variant-numeric:tabular-nums}.hub-h1{letter-spacing:-.018em;color:var(--hub-ink);margin:0;font-size:22px;font-weight:600}.hub-sub{color:var(--hub-ink-3);margin:4px 0 0;font-size:13px}.hub-sect{color:var(--hub-ink-3);text-transform:uppercase;letter-spacing:.08em;font-size:11px;font-weight:500}.hub-card-title{color:var(--hub-ink);margin:0;font-size:13px;font-weight:500}.hub-status{color:var(--hub-ink-2);white-space:nowrap;align-items:center;gap:6px;font-size:12px;display:inline-flex}.hub-status-label{white-space:nowrap;text-overflow:ellipsis;min-width:0;overflow:hidden}.hub-dot{background:var(--hub-ink-3);border-radius:50%;flex-shrink:0;width:6px;height:6px}.hub-status.ok{color:#005813;color:oklch(40% .13 145)}.hub-status.ok .hub-dot{background:var(--hub-ok);box-shadow:0 0 0 3px #4ea95426}.hub-status.warn{color:#704e00;color:oklch(45% .13 80)}.hub-status.warn .hub-dot{background:var(--hub-warn);box-shadow:0 0 0 3px #e3ad4b2e}.hub-status.err{color:#a20519}.hub-status.err .hub-dot{background:var(--hub-err);box-shadow:0 0 0 3px #de4e4b26}.hub-status.muted{color:var(--hub-ink-3)}.hub-status.muted .hub-dot{background:var(--hub-ink-3)}.dark .hub-status.ok{color:#80cd82}.dark .hub-status.warn{color:#edbb64}.dark .hub-status.err{color:#ff958d;color:oklch(78% .15 25)}.hub-tag{color:var(--hub-ink-2);background:var(--hub-bg-2);border:1px solid var(--hub-line);font-size:11px;font-family:var(--hub-mono);white-space:nowrap;text-overflow:ellipsis;border-radius:5px;align-items:center;max-width:100%;padding:1px 7px;display:inline-flex;overflow:hidden}.hub-tag.accent{color:var(--hub-accent);background:var(--hub-accent-soft);border-color:#0000}.hub-tag.muted{color:var(--hub-ink-3)}.hub-kbd{font-family:var(--hub-mono);border:1px solid var(--hub-line);color:var(--hub-ink-3);background:var(--hub-surface);border-radius:4px;padding:1px 5px;font-size:11px}.hub-row{border-top:1px solid var(--hub-line-2);align-items:center;gap:12px;padding:11px 14px;display:grid}.hub-row:first-child{border-top:0}.hub-row.head{color:var(--hub-ink-3);text-transform:uppercase;letter-spacing:.08em;background:var(--hub-bg-2);padding:9px 14px;font-size:11px}.hub-row.hover:hover{background:var(--hub-surface-hover)}.hub-btn{border:1px solid var(--hub-line);background:var(--hub-surface);height:30px;color:var(--hub-ink);border-radius:7px;align-items:center;gap:6px;padding:0 12px;font-size:13px;font-weight:500;transition:background .15s,border-color .15s;display:inline-flex}.hub-btn:hover{background:var(--hub-surface-hover)}.hub-btn:disabled{opacity:.5;cursor:not-allowed}.hub-btn.primary{background:var(--hub-ink);color:var(--hub-bg);border-color:var(--hub-ink)}.hub-btn.primary:hover{background:#25292e}.dark .hub-btn.primary{color:#101214}.dark .hub-btn.primary:hover{background:#e2e5e8}.hub-btn.ghost{border-color:#0000}.hub-btn.ghost:hover{background:var(--hub-surface-hover);border-color:var(--hub-line)}.hub-btn.danger{color:var(--hub-err)}.hub-btn.danger:hover{background:#ffedeb;background:oklch(96% .04 25);border-color:#ffbab3;border-color:oklch(85% .1 25)}.dark .hub-btn.danger:hover{background:#4f1a18}.hub-btn.sm{height:26px;padding:0 9px;font-size:12px}.hub-icon-btn{width:30px;height:30px;color:var(--hub-ink-2);cursor:pointer;background:0 0;border:1px solid #0000;border-radius:7px;place-items:center;transition:background .15s,border-color .15s;display:inline-grid}.hub-icon-btn:hover{background:var(--hub-surface-hover);border-color:var(--hub-line)}.hub-icon-btn.sm{border-radius:6px;width:26px;height:26px}.hub-input{border:1px solid var(--hub-line);background:var(--hub-surface);height:32px;color:var(--hub-ink);border-radius:7px;outline:0;width:100%;padding:0 10px;font-size:13px}.hub-input:focus{border-color:var(--hub-ink-2)}.hub-input::-moz-placeholder{color:var(--hub-ink-3)}.hub-input::placeholder{color:var(--hub-ink-3)}.hub-input.mono{font-family:var(--hub-mono);font-size:12.5px}.hub-switch{--hub-switch-width:44px;--hub-switch-height:24px;--hub-switch-thumb-size:18px;--hub-switch-thumb-offset:3px;--hub-switch-thumb-translate:20px;width:var(--hub-switch-width);height:var(--hub-switch-height);background:var(--hub-surface);box-shadow:inset 0 0 0 1px var(--hub-line);flex:0 0 var(--hub-switch-width);cursor:pointer;border:0;border-radius:999px;padding:0;transition:background .15s,box-shadow .15s;position:relative}.hub-switch.compact{--hub-switch-width:30px;--hub-switch-height:18px;--hub-switch-thumb-size:14px;--hub-switch-thumb-offset:2px;--hub-switch-thumb-translate:12px}.hub-switch.card{--hub-switch-width:32px;--hub-switch-height:18px;--hub-switch-thumb-size:14px;--hub-switch-thumb-offset:2px;--hub-switch-thumb-translate:14px}.hub-switch:after{content:"";top:var(--hub-switch-thumb-offset);left:var(--hub-switch-thumb-offset);width:var(--hub-switch-thumb-size);height:var(--hub-switch-thumb-size);background:#fff;border-radius:50%;transition:transform .15s,background .15s,box-shadow .15s;position:absolute;box-shadow:0 1px 2px #0000001f}.hub-switch.on{background:var(--hub-switch-track-on);box-shadow:inset 0 0 0 1px var(--hub-switch-track-on)}.hub-switch.on:after{transform:translate(var(--hub-switch-thumb-translate))}.hub-switch:focus-visible{outline:2px solid var(--hub-ink-2);outline-offset:2px}.hub-switch:disabled{opacity:.5;cursor:not-allowed}.dark .hub-switch:after{background:#f3f5f8;box-shadow:0 1px 2px #00000047}.dark .hub-switch.on:after{background:#101214}.hub-server-card-row{grid-template-columns:minmax(180px,1.6fr) minmax(96px,.4fr) minmax(max-content,.45fr) minmax(100px,.5fr) repeat(3,minmax(76px,.36fr)) minmax(112px,.5fr) 44px 28px;align-items:center;gap:10px;display:grid}.hub-server-card-row>*{min-width:0}.hub-server-card-visibility{justify-self:start;width:100%}.hub-server-card-status-cell,.hub-server-card-transport-cell{justify-self:start;align-items:center;height:30px;display:flex}.hub-server-card-status-cell.hub-server-card-recovering{flex-direction:column;align-items:flex-start;height:auto}.hub-status.hub-server-card-status{gap:5px;min-height:24px;font-size:11.5px}.hub-status.hub-server-card-status .hub-dot{width:5px;height:5px}.hub-status.hub-server-card-status.ok .hub-dot{box-shadow:0 0 0 2px #4ea9541f}.hub-status.hub-server-card-status.warn .hub-dot{box-shadow:0 0 0 2px #e3ad4b24}.hub-status.hub-server-card-status.err .hub-dot{box-shadow:0 0 0 2px #de4e4b1f}.hub-server-card-transport-tag{letter-spacing:.02em;border-radius:999px;justify-content:center;min-width:-moz-max-content;min-width:max-content;height:24px;padding:0 7px;font-size:10.5px}.hub-server-card-select,.hub-server-card-visibility-badge{height:30px}.hub-server-card-select{border-radius:7px;padding:0 26px 0 9px!important;font-size:11px!important}.hub-server-card-visibility-badge{border-radius:7px;padding:0 9px;font-size:11px}.hub-server-capability-stat{border:1px solid var(--hub-line-2);background:var(--hub-bg-2);min-width:0;height:26px;color:var(--hub-ink-2);border-radius:6px;grid-template-columns:14px minmax(0,1fr);justify-self:stretch;align-items:center;gap:5px;padding:0 6px;font-size:11px;line-height:1;display:grid}.hub-server-capability-stat.is-empty{border-color:var(--hub-line-2);color:var(--hub-ink-3);opacity:.6;background:0 0}.hub-server-capability-icon{flex-shrink:0;justify-content:center;align-items:center;width:14px;height:14px;line-height:0;display:inline-flex}.hub-server-capability-icon svg{display:block}.hub-server-capability-value{white-space:nowrap;text-overflow:clip;min-width:-moz-max-content;min-width:max-content;overflow:visible}@media(max-width:1440px){.hub-server-card-row{grid-template-columns:minmax(150px,1.5fr) minmax(84px,.4fr) minmax(max-content,.42fr) minmax(88px,.5fr) repeat(3,minmax(66px,.34fr)) minmax(100px,.46fr) 44px 28px;gap:9px}.hub-server-capability-stat{gap:5px;padding:0 6px}}.hub-endpoint{border:1px solid var(--hub-line);background:var(--hub-bg-2);border-radius:8px;align-items:center;gap:0;min-width:0;height:32px;display:flex;overflow:hidden}.hub-endpoint .hub-endpoint-label{border-right:1px solid var(--hub-line);height:100%;color:var(--hub-ink-3);font-size:11px;font-family:var(--hub-mono);text-transform:uppercase;letter-spacing:.05em;flex:none;align-items:center;padding:0 10px;display:flex}.hub-endpoint .hub-endpoint-url{font-family:var(--hub-mono);color:var(--hub-ink-2);white-space:nowrap;text-overflow:ellipsis;letter-spacing:-.01em;flex:1;min-width:0;padding:0 10px;font-size:12.5px;overflow:hidden}.hub-endpoint .hub-endpoint-copy{border-left:1px solid var(--hub-line);width:32px;height:100%;color:var(--hub-ink-3);cursor:pointer;background:0 0;border-top:0;border-bottom:0;border-right:0;border-radius:0;place-items:center;transition:background .15s;display:inline-grid}.hub-endpoint .hub-endpoint-copy:hover{background:var(--hub-surface-hover)}.hub-endpoint .hub-endpoint-copy.copied{color:var(--hub-ok)}.page-card .bg-gray-50,.page-card .dark\:bg-gray-800.rounded-md{background:var(--hub-bg-2)!important}.hub-sr-fields>div{border:1px solid var(--hub-line)!important;background:var(--hub-bg-2)!important;box-shadow:none!important;border-radius:8px!important;padding:12px 14px!important}.hub-sr-fields h3{color:var(--hub-ink)!important;font-size:12.5px!important;font-weight:500!important}.hub-sr-fields h3 .text-red-500{color:var(--hub-err)!important}.hub-sr-fields p{color:var(--hub-ink-3)!important}.hub-sr-fields input,.hub-sr-fields select{border:1px solid var(--hub-line)!important;background:var(--hub-surface)!important;height:32px!important;color:var(--hub-ink)!important;box-shadow:none!important;border-radius:7px!important;outline:0!important;margin-top:0!important;padding:0 10px!important;font-size:13px!important}.hub-sr-fields input.mono,.hub-sr-fields select.mono{font-family:var(--hub-mono)!important}.hub-sr-fields input:focus,.hub-sr-fields select:focus{border-color:var(--hub-ink-2)!important;box-shadow:none!important}.page-card,.dashboard-card{background:var(--hub-surface)!important;border:1px solid var(--hub-line)!important;box-shadow:none!important;border-radius:10px!important;transition:background .15s,border-color .15s!important}.page-card:hover,.dashboard-card:hover{box-shadow:none!important;transform:none!important}.dark .page-card,.dark .dashboard-card{background:var(--hub-surface)!important;border-color:var(--hub-line)!important;box-shadow:none!important}.dark .bg-white,.dark .dark\:bg-gray-800{background:var(--hub-surface)!important}.loading-container{background:var(--hub-surface)!important;border:1px solid var(--hub-line)!important;box-shadow:none!important;border-radius:10px!important}.empty-state{background:var(--hub-surface)!important;border:1px solid var(--hub-line)!important;text-align:center!important;border-radius:10px!important;padding:2.5rem 1.5rem!important}.empty-state p{color:var(--hub-ink-3)!important}.error-box{color:#8a0012!important;color:oklch(40% .18 25)!important;box-shadow:none!important;background:#fff1f0!important;background:oklch(97% .03 25)!important;border:1px solid oklch(85% .1 25)!important;border-radius:8px!important}.dark .error-box{background:#4f1a18!important;border-color:#972527!important}.error-box h3{color:#8a0012!important;color:oklch(40% .18 25)!important}.btn-primary{background:var(--hub-ink)!important;color:var(--hub-bg)!important;box-shadow:none!important;border:1px solid #0000!important;border-radius:7px!important;font-weight:500!important;transition:background .15s!important}.btn-primary:hover{color:var(--hub-bg)!important;box-shadow:none!important;background:#25292e!important;transform:none!important}.dark .btn-primary{background:var(--hub-ink)!important;color:#101214!important;border-color:#0000!important}.dark .btn-primary:hover{color:#101214!important;box-shadow:none!important;background:#e2e5e8!important;transform:none!important}.btn-secondary{font-size:.875rem;background:var(--hub-surface)!important;color:var(--hub-ink)!important;border:1px solid var(--hub-line)!important;border-radius:7px!important;font-weight:500!important}.btn-secondary:hover{background:var(--hub-surface-hover)!important;color:var(--hub-ink)!important;border-color:var(--hub-line)!important;box-shadow:none!important;transform:none!important}.dark .btn-secondary,.dark .btn-secondary:hover{background:var(--hub-surface)!important;color:var(--hub-ink)!important;border-color:var(--hub-line)!important}.dark .btn-secondary:hover{background:var(--hub-surface-hover)!important}.btn-warning{color:#704e00!important;color:oklch(45% .13 80)!important;background:#fff0d7!important;background:oklch(96% .06 80)!important;border:1px solid oklch(85% .12 80)!important;border-radius:7px!important}.btn-warning:hover{color:#5f4200!important;color:oklch(40% .13 80)!important;background:#ffe4b7!important;background:oklch(93% .08 80)!important}.dark .btn-warning{color:#edbb64!important;background:#3e2a00!important;background:oklch(30% .08 80)!important;border-color:#704e00!important;border-color:oklch(45% .1 80)!important}.btn-danger{background:var(--hub-surface)!important;color:var(--hub-err)!important;border:1px solid var(--hub-line)!important;border-radius:7px!important}.btn-danger:hover{color:#8a0012!important;color:oklch(40% .18 25)!important;box-shadow:none!important;background:#fff1f0!important;background:oklch(97% .03 25)!important;border-color:#ffbab3!important;border-color:oklch(85% .1 25)!important;transform:none!important}.dark .btn-danger{background:var(--hub-surface)!important;color:#ff958d!important;color:oklch(78% .15 25)!important;border-color:var(--hub-line)!important}.dark .btn-danger:hover{background:#4f1a18!important;border-color:#972527!important}.form-input,input.form-input,select.form-input,textarea.form-input{background:var(--hub-surface)!important;border:1px solid var(--hub-line)!important;color:var(--hub-ink)!important;box-shadow:none!important;border-radius:7px!important;transition:border-color .15s!important}.form-input:focus,input.form-input:focus,select.form-input:focus,textarea.form-input:focus{border-color:var(--hub-ink-2)!important;box-shadow:none!important;outline:none!important}.dark .form-input,.dark input.form-input,.dark select.form-input,.dark textarea.form-input{background:var(--hub-surface)!important;border-color:var(--hub-line)!important;color:var(--hub-ink)!important}.dark .form-input::-moz-placeholder{color:var(--hub-ink-3)!important}.dark .form-input::placeholder{color:var(--hub-ink-3)!important}.status-badge-online,.status-badge-offline,.status-badge-connecting,.status-badge-oauth-required{background:0 0!important;border:0!important;border-radius:0!important;align-items:center!important;gap:6px!important;padding:0!important;font-size:12px!important;font-weight:500!important;line-height:1.4!important;display:inline-flex!important}.status-badge-online:before,.status-badge-offline:before,.status-badge-connecting:before,.status-badge-oauth-required:before{content:"";border-radius:50%;flex-shrink:0;width:6px;height:6px}.status-badge-online{color:#005813!important;color:oklch(40% .13 145)!important}.status-badge-online:before{background:var(--hub-ok);box-shadow:0 0 0 3px #4ea95426}.status-badge-offline{color:#a20519!important}.status-badge-offline:before{background:var(--hub-err);box-shadow:0 0 0 3px #de4e4b26}.status-badge-connecting{color:#704e00!important;color:oklch(45% .13 80)!important}.status-badge-connecting:before{background:var(--hub-warn);box-shadow:0 0 0 3px #e3ad4b2e}.status-badge-oauth-required{color:var(--hub-accent)!important}.status-badge-oauth-required:before{background:var(--hub-accent);box-shadow:0 0 0 3px #0f74c52e}.dark .status-badge-online,.dark .status-badge-offline,.dark .status-badge-connecting,.dark .status-badge-oauth-required{background:0 0!important;border:0!important}.dark .status-badge-online{color:#80cd82!important}.dark .status-badge-offline{color:#ff958d!important;color:oklch(78% .15 25)!important}.dark .status-badge-connecting{color:#edbb64!important}.status-icon-blue{background:var(--hub-accent-soft)!important;color:var(--hub-accent)!important}.status-icon-green{color:#005813!important;color:oklch(40% .13 145)!important;background:#dbf8da!important}.status-icon-red{color:#a20519!important;background:#ffedeb!important;background:oklch(96% .04 25)!important}.status-icon-yellow{color:#704e00!important;color:oklch(45% .13 80)!important;background:#fff0d7!important;background:oklch(96% .06 80)!important}.dark .status-icon-blue{color:#95c9ff!important;color:oklch(82% .1 250)!important;background:#193550!important}.dark .status-icon-green{color:#9bd69c!important;background:#1d341e!important}.dark .status-icon-red{color:#ff958d!important;color:oklch(78% .15 25)!important;background:#4f1a18!important}.dark .status-icon-yellow{color:#edbb64!important;background:#3d2a02!important}.table-container{overflow:hidden;box-shadow:none!important;border:1px solid var(--hub-line)!important;border-radius:10px!important}.dark .table-container{background:var(--hub-surface)!important;border-color:var(--hub-line)!important;box-shadow:none!important}.dark thead{background:var(--hub-bg-2)!important}.login-card{box-shadow:none!important}.hub-topbar{border-bottom:1px solid var(--hub-line);background:var(--hub-bg);align-items:center;gap:14px;height:48px;padding:0 22px;display:flex}.hub-crumb{color:var(--hub-ink-3);font-size:13px}.hub-crumb b{color:var(--hub-ink);font-weight:500}.hub-crumb .sep{color:var(--hub-ink-3);opacity:.5;margin:0 6px}body{background:var(--hub-bg);color:var(--hub-ink);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;margin:0;font-family:system-ui,PingFang SC,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.dark .text-gray-900,.dark .text-gray-800,.dark .dark\:text-gray-100,.dark .dark\:text-gray-200{color:var(--hub-ink)!important}.dark .text-gray-700,.dark .text-gray-600,.dark .dark\:text-gray-300{color:var(--hub-ink-2)!important}.dark .text-gray-500,.dark .text-gray-400,.dark .dark\:text-gray-400,.dark .dark\:text-gray-500{color:var(--hub-ink-3)!important}.dark .border-gray-100,.dark .border-gray-200,.dark .border-gray-300,.dark .dark\:border-gray-600,.dark .dark\:border-gray-700{border-color:var(--hub-line)!important}.dark .divide-gray-200>:not([hidden])~:not([hidden]),.dark .dark\:divide-gray-700>:not([hidden])~:not([hidden]){border-color:var(--hub-line-2)!important}.dark .bg-gray-50,.dark .bg-gray-100,.dark .dark\:bg-gray-700{background:var(--hub-bg-2)!important}.dark .dark\:bg-gray-800\/60{background:var(--hub-surface)!important}@supports (color:color-mix(in lab,red,red)){.dark .dark\:bg-gray-800\/60{background:color-mix(in oklab,var(--hub-surface)60%,transparent)!important}}.dark .dark\:bg-gray-900{background:var(--hub-bg)!important}.dark .hover\:bg-gray-50:hover,.dark .hover\:bg-gray-100:hover,.dark .hover\:bg-gray-200:hover,.dark .dark\:hover\:bg-gray-600:hover,.dark .dark\:hover\:bg-gray-700:hover,.dark .dark\:hover\:bg-gray-800:hover{background:var(--hub-surface-hover)!important}.dark .hover\:text-gray-900:hover{color:var(--hub-ink)!important}.dark :is(input,select,textarea):not([type=checkbox],[type=radio],[type=range],[type=file],[type=submit],[type=button],[type=reset],[type=color]){background:var(--hub-surface)!important;border-color:var(--hub-line)!important;color:var(--hub-ink)!important}.dark :is(input,select,textarea):focus{border-color:var(--hub-ink-2)!important}.dark input::-moz-placeholder,.dark textarea::-moz-placeholder{color:var(--hub-ink-3)!important}.dark input::placeholder,.dark textarea::placeholder{color:var(--hub-ink-3)!important}.bg-blue-300{background-color:var(--color-blue-300)}.bg-custom-blue{background-color:#4a90e2}.text-custom-white{color:#fff}.icon-container{transition:all .3s}.icon-container:hover{filter:brightness(1.1);transform:scale(1.05)}.progress-bar-online{background:linear-gradient(90deg,#4caf50cc,#81c78499)}.progress-bar-offline{background:linear-gradient(90deg,#f44336cc,#ef9a9a99)}.progress-bar-connecting{background:linear-gradient(90deg,#ffc107cc,#ffd54f99)}.dark tbody tr{border-bottom:1px solid var(--hub-line-2)}tbody tr:hover{transition:background-color .2s;background-color:var(--hub-surface-hover)!important}.dark .error-box h3{color:#ef9a9ae6!important}.dark .error-box p{color:var(--hub-ink-2)!important}.label-primary{background-color:var(--color-blue-50)!important;color:var(--color-blue-500)!important}.dark .label-primary{color:#60a5fae6!important;background-color:#3b82f626!important}.label-secondary{background-color:var(--color-green-50)!important;color:var(--color-green-500)!important}.dark .label-secondary{color:#81c784e6!important;background-color:#4caf5026!important}.dark .btn-warning:hover{transform:translateY(-1px);color:#facc15!important;background-color:#eab30840!important}.text-status-red{color:#991b1b}.dark .text-status-red{color:#ef9a9ae6!important}.external-link{cursor:pointer;border-bottom:1px solid #0000;text-decoration:none;transition:all .2s ease-in-out;color:#2563eb!important}.external-link:hover{border-bottom-color:#1d4ed8;text-decoration:none;color:#1d4ed8!important}.dark .external-link{color:#60a5fa!important}.dark .external-link:hover{border-bottom-color:#93c5fd;color:#93c5fd!important}.border-red{border-color:#937d7d}.dark .border-red{border-color:#bca1a1e6!important}.dark .text-status-green{color:#81c784e6!important}.dark .login-container{background-color:var(--hub-bg)!important}.dark .login-card{border:1px solid var(--hub-line);border-radius:12px;box-shadow:0 8px 25px #0003,0 4px 12px #00000026;background-color:var(--hub-surface)!important}button{transition:transform .15s,opacity .15s}button:not(:disabled):active{transform:scale(.96)}button.is-loading,button.is-loading:hover,.dark button.is-loading,.dark button.is-loading:hover{color:#0000!important;pointer-events:none!important;position:relative!important}button.is-loading>*{opacity:0!important}button.is-loading:after{content:"";border:2px solid #80808066;border-top-color:#666;border-radius:50%;width:1.2rem;height:1.2rem;margin-top:-.6rem;margin-left:-.6rem;animation:.6s linear infinite button-spinner;position:absolute;top:50%;left:50%;visibility:visible!important}button.bg-blue-600.is-loading:after,button.bg-blue-500.is-loading:after,button.bg-red-500.is-loading:after,button.bg-red-600.is-loading:after,button.text-white.is-loading:after{border:2px solid #ffffff4d!important;border-top-color:#fff!important}button.btn-primary.is-loading:after,button.hub-btn.primary.is-loading:after{border-color:var(--hub-bg)!important}@supports (color:color-mix(in lab,red,red)){button.btn-primary.is-loading:after,button.hub-btn.primary.is-loading:after{border-color:color-mix(in oklab,var(--hub-bg)35%,transparent)!important}}button.btn-primary.is-loading:after,button.hub-btn.primary.is-loading:after{border-top-color:var(--hub-bg)!important}@keyframes button-spinner{to{transform:rotate(360deg)}}@media(max-width:1200px){.hub-server-card-row{grid-template-columns:minmax(120px,1.4fr) minmax(72px,.4fr) minmax(max-content,.4fr) minmax(80px,.45fr) repeat(3,minmax(58px,.3fr)) minmax(92px,.42fr) 40px 24px;gap:8px}.hub-server-capability-stat{gap:4px;padding:0 5px}}.hub-server-card-transport-cell{flex-direction:column;justify-content:center;align-items:flex-start;gap:3px;height:auto;min-height:30px}.hub-server-card-protocol{color:var(--hub-ink-3);white-space:nowrap;font-size:10.5px;line-height:1.4}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-space-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-space-x-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-divide-y-reverse{syntax:"*";inherits:false;initial-value:0}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-gradient-position{syntax:"*";inherits:false}@property --tw-gradient-from{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-via{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-to{syntax:"<color>";inherits:false;initial-value:#0000}@property --tw-gradient-stops{syntax:"*";inherits:false}@property --tw-gradient-via-stops{syntax:"*";inherits:false}@property --tw-gradient-from-position{syntax:"<length-percentage>";inherits:false;initial-value:0%}@property --tw-gradient-via-position{syntax:"<length-percentage>";inherits:false;initial-value:50%}@property --tw-gradient-to-position{syntax:"<length-percentage>";inherits:false;initial-value:100%}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@property --tw-scale-x{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-y{syntax:"*";inherits:false;initial-value:1}@property --tw-scale-z{syntax:"*";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}