@nextclaw/ui 0.5.9 → 0.5.10
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.
- package/CHANGELOG.md +6 -0
- package/dist/assets/index-BYV0BsFw.js +342 -0
- package/dist/assets/index-DrC_vHy_.css +1 -0
- package/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/components/common/MaskedInput.tsx +1 -1
- package/src/components/common/StatusBadge.tsx +3 -5
- package/src/components/common/TagInput.tsx +3 -2
- package/src/components/config/ChannelForm.tsx +106 -104
- package/src/components/config/ChannelsList.tsx +19 -19
- package/src/components/config/CronConfig.tsx +3 -14
- package/src/components/config/ModelConfig.tsx +9 -8
- package/src/components/config/ProviderForm.tsx +3 -3
- package/src/components/config/ProvidersList.tsx +10 -9
- package/src/components/config/RuntimeConfig.tsx +38 -37
- package/src/components/config/SessionsConfig.tsx +8 -15
- package/src/components/layout/Sidebar.tsx +70 -40
- package/src/components/marketplace/MarketplacePage.tsx +32 -31
- package/src/components/providers/I18nProvider.tsx +64 -0
- package/src/components/ui/confirm-dialog.tsx +3 -2
- package/src/components/ui/tabs-custom.tsx +2 -1
- package/src/hooks/useConfirmDialog.tsx +5 -4
- package/src/hooks/useMarketplace.ts +4 -3
- package/src/lib/i18n.ts +267 -5
- package/src/main.tsx +6 -3
- package/dist/assets/index-BtwwwWcv.css +0 -1
- package/dist/assets/index-STUSj6p9.js +0 -337
package/src/lib/i18n.ts
CHANGED
|
@@ -1,10 +1,134 @@
|
|
|
1
|
-
|
|
1
|
+
export type I18nLanguage = 'zh' | 'en';
|
|
2
|
+
|
|
3
|
+
const I18N_STORAGE_KEY = 'nextclaw.ui.language';
|
|
4
|
+
|
|
5
|
+
export const LANGUAGE_OPTIONS: Array<{ value: I18nLanguage; label: string }> = [
|
|
6
|
+
{ value: 'en', label: 'English' },
|
|
7
|
+
{ value: 'zh', label: '中文' }
|
|
8
|
+
];
|
|
9
|
+
|
|
10
|
+
const LANGUAGE_TO_LOCALE: Record<I18nLanguage, string> = {
|
|
11
|
+
en: 'en-US',
|
|
12
|
+
zh: 'zh-CN'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
let activeLanguage: I18nLanguage = 'en';
|
|
16
|
+
let initialized = false;
|
|
17
|
+
const listeners = new Set<(lang: I18nLanguage) => void>();
|
|
18
|
+
|
|
19
|
+
function isLanguage(value: unknown): value is I18nLanguage {
|
|
20
|
+
return value === 'en' || value === 'zh';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function detectBrowserLanguage(): I18nLanguage {
|
|
24
|
+
if (typeof navigator === 'undefined') {
|
|
25
|
+
return 'en';
|
|
26
|
+
}
|
|
27
|
+
const preferred = navigator.language?.toLowerCase() ?? 'en';
|
|
28
|
+
return preferred.startsWith('zh') ? 'zh' : 'en';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function resolveInitialLanguage(): I18nLanguage {
|
|
32
|
+
if (typeof window === 'undefined') {
|
|
33
|
+
return 'en';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
try {
|
|
37
|
+
const saved = window.localStorage.getItem(I18N_STORAGE_KEY);
|
|
38
|
+
if (isLanguage(saved)) {
|
|
39
|
+
return saved;
|
|
40
|
+
}
|
|
41
|
+
} catch {
|
|
42
|
+
// ignore storage failures
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return detectBrowserLanguage();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function initializeI18n(): I18nLanguage {
|
|
49
|
+
if (!initialized) {
|
|
50
|
+
activeLanguage = resolveInitialLanguage();
|
|
51
|
+
initialized = true;
|
|
52
|
+
}
|
|
53
|
+
return activeLanguage;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function getLanguage(): I18nLanguage {
|
|
57
|
+
return initialized ? activeLanguage : initializeI18n();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function setLanguage(lang: I18nLanguage): void {
|
|
61
|
+
initializeI18n();
|
|
62
|
+
if (activeLanguage === lang) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
activeLanguage = lang;
|
|
67
|
+
|
|
68
|
+
if (typeof window !== 'undefined') {
|
|
69
|
+
try {
|
|
70
|
+
window.localStorage.setItem(I18N_STORAGE_KEY, lang);
|
|
71
|
+
} catch {
|
|
72
|
+
// ignore storage failures
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
listeners.forEach((listener) => listener(lang));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function subscribeLanguageChange(listener: (lang: I18nLanguage) => void): () => void {
|
|
80
|
+
listeners.add(listener);
|
|
81
|
+
return () => {
|
|
82
|
+
listeners.delete(listener);
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function getLocale(lang: I18nLanguage = getLanguage()): string {
|
|
87
|
+
return LANGUAGE_TO_LOCALE[lang];
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function formatDateTime(value?: string | Date, lang: I18nLanguage = getLanguage()): string {
|
|
91
|
+
if (!value) {
|
|
92
|
+
return '-';
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
96
|
+
if (Number.isNaN(date.getTime())) {
|
|
97
|
+
return typeof value === 'string' ? value : '-';
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return date.toLocaleString(getLocale(lang));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function formatDateShort(value?: string | Date, lang: I18nLanguage = getLanguage()): string {
|
|
104
|
+
if (!value) {
|
|
105
|
+
return '-';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
109
|
+
if (Number.isNaN(date.getTime())) {
|
|
110
|
+
return typeof value === 'string' ? value : '-';
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return new Intl.DateTimeFormat(getLocale(lang), {
|
|
114
|
+
year: 'numeric',
|
|
115
|
+
month: '2-digit',
|
|
116
|
+
day: '2-digit'
|
|
117
|
+
}).format(date);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function formatNumber(value: number, lang: I18nLanguage = getLanguage()): string {
|
|
121
|
+
return new Intl.NumberFormat(getLocale(lang)).format(value);
|
|
122
|
+
}
|
|
123
|
+
|
|
2
124
|
export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
3
125
|
// Navigation
|
|
4
126
|
model: { zh: '模型', en: 'Model' },
|
|
5
127
|
providers: { zh: '提供商', en: 'Providers' },
|
|
6
128
|
channels: { zh: '渠道', en: 'Channels' },
|
|
7
129
|
cron: { zh: '定时任务', en: 'Cron Jobs' },
|
|
130
|
+
runtime: { zh: '路由与运行时', en: 'Routing & Runtime' },
|
|
131
|
+
marketplace: { zh: '市场', en: 'Marketplace' },
|
|
8
132
|
|
|
9
133
|
// Common
|
|
10
134
|
enabled: { zh: '启用', en: 'Enabled' },
|
|
@@ -17,14 +141,34 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
17
141
|
loading: { zh: '加载中...', en: 'Loading...' },
|
|
18
142
|
success: { zh: '成功', en: 'Success' },
|
|
19
143
|
error: { zh: '错误', en: 'Error' },
|
|
144
|
+
confirm: { zh: '确认', en: 'Confirm' },
|
|
145
|
+
unchanged: { zh: '未修改', en: 'Unchanged' },
|
|
146
|
+
saving: { zh: '保存中...', en: 'Saving...' },
|
|
147
|
+
remove: { zh: '移除', en: 'Remove' },
|
|
148
|
+
all: { zh: '全部', en: 'All' },
|
|
149
|
+
prev: { zh: '上一页', en: 'Prev' },
|
|
150
|
+
next: { zh: '下一页', en: 'Next' },
|
|
151
|
+
language: { zh: '语言', en: 'Language' },
|
|
20
152
|
|
|
21
153
|
// Model
|
|
22
|
-
|
|
154
|
+
modelPageTitle: { zh: '模型配置', en: 'Model Configuration' },
|
|
155
|
+
modelPageDescription: { zh: '配置默认 AI 模型和运行参数限制', en: 'Configure default AI model and runtime limits' },
|
|
156
|
+
defaultModel: { zh: '默认模型', en: 'Default Model' },
|
|
23
157
|
workspace: { zh: '工作空间', en: 'Workspace' },
|
|
158
|
+
generationParameters: { zh: '生成参数', en: 'Generation Parameters' },
|
|
159
|
+
modelName: { zh: '模型', en: 'Model' },
|
|
24
160
|
maxTokens: { zh: '最大 Token 数', en: 'Max Tokens' },
|
|
25
161
|
maxToolIterations: { zh: '最大工具迭代次数', en: 'Max Tool Iterations' },
|
|
162
|
+
saveChanges: { zh: '保存变更', en: 'Save Changes' },
|
|
26
163
|
|
|
27
164
|
// Provider
|
|
165
|
+
providersPageTitle: { zh: 'AI 提供商', en: 'AI Providers' },
|
|
166
|
+
providersLoading: { zh: '加载中...', en: 'Loading...' },
|
|
167
|
+
providersTabConfigured: { zh: '已配置', en: 'Configured' },
|
|
168
|
+
providersTabAll: { zh: '全部提供商', en: 'All Providers' },
|
|
169
|
+
providersDefaultDescription: { zh: '为你的 Agent 配置 AI 服务', en: 'Configure AI services for your agents' },
|
|
170
|
+
providersEmptyTitle: { zh: '尚未配置提供商', en: 'No providers configured' },
|
|
171
|
+
providersEmptyDescription: { zh: '添加一个 AI 提供商后即可开始使用。', en: 'Add an AI provider to start using the platform.' },
|
|
28
172
|
apiKey: { zh: 'API 密钥', en: 'API Key' },
|
|
29
173
|
apiBase: { zh: 'API Base', en: 'API Base' },
|
|
30
174
|
extraHeaders: { zh: '额外请求头', en: 'Extra Headers' },
|
|
@@ -36,8 +180,26 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
36
180
|
apiKeyNotSet: { zh: '未设置', en: 'Not Set' },
|
|
37
181
|
showKey: { zh: '显示密钥', en: 'Show Key' },
|
|
38
182
|
hideKey: { zh: '隐藏密钥', en: 'Hide Key' },
|
|
183
|
+
providerFormDescription: { zh: '配置 AI 提供商的 API 密钥与参数', en: 'Configure API keys and parameters for AI provider' },
|
|
184
|
+
enterApiKey: { zh: '请输入 API 密钥', en: 'Enter API Key' },
|
|
185
|
+
leaveBlankToKeepUnchanged: { zh: '留空则保持不变', en: 'Leave blank to keep unchanged' },
|
|
39
186
|
|
|
40
187
|
// Channel
|
|
188
|
+
channelsPageTitle: { zh: '消息渠道', en: 'Message Channels' },
|
|
189
|
+
channelsLoading: { zh: '加载渠道中...', en: 'Loading channels...' },
|
|
190
|
+
channelsTabEnabled: { zh: '已启用', en: 'Enabled' },
|
|
191
|
+
channelsTabAll: { zh: '全部渠道', en: 'All Channels' },
|
|
192
|
+
channelsEmptyTitle: { zh: '暂无启用渠道', en: 'No channels enabled' },
|
|
193
|
+
channelsEmptyDescription: { zh: '启用一个消息渠道以开始接收消息。', en: 'Enable a messaging channel to start receiving messages.' },
|
|
194
|
+
channelDescriptionDefault: { zh: '配置该通信渠道', en: 'Configure this communication channel' },
|
|
195
|
+
channelDescTelegram: { zh: '连接 Telegram 机器人以进行即时消息收发', en: 'Connect with Telegram bots for instant messaging' },
|
|
196
|
+
channelDescSlack: { zh: '接入 Slack 工作区进行团队协作消息处理', en: 'Integrate with Slack workspaces for team collaboration' },
|
|
197
|
+
channelDescEmail: { zh: '通过邮件协议收发消息', en: 'Send and receive messages via email protocols' },
|
|
198
|
+
channelDescWebhook: { zh: '接收 HTTP Webhook 以支持自定义集成', en: 'Receive HTTP webhooks for custom integrations' },
|
|
199
|
+
channelDescDiscord: { zh: '将 Discord 机器人连接到你的社区服务器', en: 'Connect Discord bots to your community servers' },
|
|
200
|
+
channelDescFeishu: { zh: '企业消息与协作平台接入', en: 'Enterprise messaging and collaboration platform' },
|
|
201
|
+
configureMessageChannelParameters: { zh: '配置消息渠道参数', en: 'Configure message channel parameters' },
|
|
202
|
+
channelsGuideTitle: { zh: '查看指南', en: 'View Guide' },
|
|
41
203
|
allowFrom: { zh: '允许来源', en: 'Allow From' },
|
|
42
204
|
token: { zh: 'Token', en: 'Token' },
|
|
43
205
|
botToken: { zh: 'Bot Token', en: 'Bot Token' },
|
|
@@ -100,6 +262,54 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
100
262
|
replyDelayMode: { zh: '回复延迟模式', en: 'Reply Delay Mode' },
|
|
101
263
|
replyDelayMs: { zh: '回复延迟(ms)', en: 'Reply Delay (ms)' },
|
|
102
264
|
secret: { zh: '密钥', en: 'Secret' },
|
|
265
|
+
accountId: { zh: '账号 ID', en: 'Account ID' },
|
|
266
|
+
dmPolicy: { zh: '私聊策略', en: 'DM Policy' },
|
|
267
|
+
groupAllowFrom: { zh: '群组允许来源', en: 'Group Allow From' },
|
|
268
|
+
requireMention: { zh: '需要 @ 提及', en: 'Require Mention' },
|
|
269
|
+
mentionPatterns: { zh: '提及匹配规则', en: 'Mention Patterns' },
|
|
270
|
+
groupRulesJson: { zh: '群组规则(JSON)', en: 'Group Rules (JSON)' },
|
|
271
|
+
allowBotMessages: { zh: '允许机器人消息', en: 'Allow Bot Messages' },
|
|
272
|
+
attachmentMaxSizeMb: { zh: '附件最大体积(MB)', en: 'Attachment Max Size (MB)' },
|
|
273
|
+
streamingMode: { zh: '流式模式', en: 'Streaming Mode' },
|
|
274
|
+
draftChunkingJson: { zh: '草稿分块(JSON)', en: 'Draft Chunking (JSON)' },
|
|
275
|
+
textChunkLimit: { zh: '文本分块上限', en: 'Text Chunk Limit' },
|
|
276
|
+
invalidJson: { zh: 'JSON 格式无效', en: 'Invalid JSON' },
|
|
277
|
+
|
|
278
|
+
// Runtime
|
|
279
|
+
runtimePageTitle: { zh: '路由与运行时', en: 'Routing & Runtime' },
|
|
280
|
+
runtimePageDescription: { zh: '对齐 OpenClaw 的多 Agent 路由:绑定规则、Agent 池、私聊范围。', en: 'Align multi-agent routing with OpenClaw: bindings, agent pool, and DM scope.' },
|
|
281
|
+
runtimeLoading: { zh: '加载运行时配置中...', en: 'Loading runtime settings...' },
|
|
282
|
+
dmScope: { zh: '私聊范围', en: 'DM Scope' },
|
|
283
|
+
dmScopeHelp: { zh: '控制私聊会话如何隔离。', en: 'Control how direct-message sessions are isolated.' },
|
|
284
|
+
defaultContextTokens: { zh: '默认上下文 Token', en: 'Default Context Tokens' },
|
|
285
|
+
defaultContextTokensHelp: { zh: '当 Agent 未设置单独值时使用该上下文预算。', en: 'Input context budget for agents when no per-agent override is set.' },
|
|
286
|
+
maxPingPongTurns: { zh: '最大乒乓轮次', en: 'Max Ping-Pong Turns' },
|
|
287
|
+
maxPingPongTurnsHelp: { zh: '设为 0 可阻止 Agent 间自动 ping-pong。', en: 'Set to 0 to block automatic agent-to-agent ping-pong loops.' },
|
|
288
|
+
agentList: { zh: 'Agent 列表', en: 'Agent List' },
|
|
289
|
+
agentListHelp: { zh: '在同一个网关进程中运行多个固定角色 Agent。', en: 'Run multiple fixed-role agents in one gateway process.' },
|
|
290
|
+
bindings: { zh: '绑定规则', en: 'Bindings' },
|
|
291
|
+
bindingsHelp: { zh: '根据渠道 + 账号 + 对端将入站消息路由到目标 Agent。', en: 'Route inbound message by channel + account + peer to target agent.' },
|
|
292
|
+
agentIdRequiredError: { zh: 'agents.list[{index}].id 必填', en: 'agents.list[{index}].id is required' },
|
|
293
|
+
duplicateAgentId: { zh: '重复的 agent id', en: 'Duplicate agent id' },
|
|
294
|
+
bindingAgentIdRequired: { zh: 'bindings[{index}].agentId 必填', en: 'bindings[{index}].agentId is required' },
|
|
295
|
+
bindingAgentIdNotFound: { zh: 'bindings[{index}].agentId 未在 agents.list/main 中找到', en: "bindings[{index}].agentId not found in agents.list/main" },
|
|
296
|
+
bindingChannelRequired: { zh: 'bindings[{index}].match.channel 必填', en: 'bindings[{index}].match.channel is required' },
|
|
297
|
+
bindingPeerIdRequired: { zh: '设置 peer.kind 时,bindings[{index}].match.peer.id 必填', en: 'bindings[{index}].match.peer.id is required when peer.kind is set' },
|
|
298
|
+
agentIdPlaceholder: { zh: 'Agent ID(例如 engineer)', en: 'Agent ID (e.g. engineer)' },
|
|
299
|
+
workspaceOverridePlaceholder: { zh: '工作空间覆盖(可选)', en: 'Workspace override (optional)' },
|
|
300
|
+
modelOverridePlaceholder: { zh: '模型覆盖(可选)', en: 'Model override (optional)' },
|
|
301
|
+
maxTokensPlaceholder: { zh: '最大 tokens', en: 'Max tokens' },
|
|
302
|
+
contextTokensPlaceholder: { zh: '上下文 tokens', en: 'Context tokens' },
|
|
303
|
+
maxToolsPlaceholder: { zh: '最大工具次数', en: 'Max tools' },
|
|
304
|
+
defaultAgent: { zh: '默认 Agent', en: 'Default agent' },
|
|
305
|
+
addAgent: { zh: '添加 Agent', en: 'Add Agent' },
|
|
306
|
+
targetAgentIdPlaceholder: { zh: '目标 Agent ID', en: 'Target agent ID' },
|
|
307
|
+
channelPlaceholder: { zh: '渠道(例如 discord)', en: 'Channel (e.g. discord)' },
|
|
308
|
+
accountIdOptionalPlaceholder: { zh: '账号 ID(可选)', en: 'Account ID (optional)' },
|
|
309
|
+
peerKindOptional: { zh: '对端类型(可选)', en: 'Peer kind (optional)' },
|
|
310
|
+
peerIdPlaceholder: { zh: '对端 ID(需先设置对端类型)', en: 'Peer ID (requires peer kind)' },
|
|
311
|
+
addBinding: { zh: '添加绑定', en: 'Add Binding' },
|
|
312
|
+
saveRuntimeSettings: { zh: '保存运行时设置', en: 'Save Runtime Settings' },
|
|
103
313
|
|
|
104
314
|
// Sessions
|
|
105
315
|
sessionsPageTitle: { zh: '会话管理', en: 'Sessions' },
|
|
@@ -137,6 +347,13 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
137
347
|
sessionsHistoryLoading: { zh: '加载历史中...', en: 'Loading history...' },
|
|
138
348
|
sessionsApplyingChanges: { zh: '正在应用会话变更...', en: 'Applying session changes...' },
|
|
139
349
|
sessionsUnknownChannel: { zh: '未知渠道', en: 'Unknown channel' },
|
|
350
|
+
sessionsAllChannels: { zh: '全部渠道', en: 'All Channels' },
|
|
351
|
+
sessionsMetadata: { zh: '元信息', en: 'Metadata' },
|
|
352
|
+
sessionsNoSelectionTitle: { zh: '未选择会话', en: 'No Session Selected' },
|
|
353
|
+
sessionsNoSelectionDescription: {
|
|
354
|
+
zh: '从左侧列表选择一个会话以查看聊天历史并配置其元信息。',
|
|
355
|
+
en: 'Select a session from the list on the left to view its chat history and configure its metadata.'
|
|
356
|
+
},
|
|
140
357
|
|
|
141
358
|
// Cron
|
|
142
359
|
cronPageTitle: { zh: '定时任务', en: 'Cron Jobs' },
|
|
@@ -164,14 +381,59 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
164
381
|
cronRunConfirm: { zh: '确认立即执行定时任务', en: 'Run cron job now' },
|
|
165
382
|
cronRunForceConfirm: { zh: '任务已禁用,仍要立即执行', en: 'Cron job disabled. Force run now' },
|
|
166
383
|
|
|
167
|
-
//
|
|
168
|
-
|
|
384
|
+
// Marketplace
|
|
385
|
+
marketplacePageTitle: { zh: '市场', en: 'Marketplace' },
|
|
386
|
+
marketplacePageDescription: { zh: '更清爽的扩展列表,聚焦安装/启用/禁用。', en: 'A cleaner extension list focused on install / enable / disable.' },
|
|
387
|
+
marketplaceTabMarketplace: { zh: '市场', en: 'Marketplace' },
|
|
388
|
+
marketplaceTabInstalled: { zh: '已安装', en: 'Installed' },
|
|
389
|
+
marketplaceSearchPlaceholder: { zh: '搜索扩展...', en: 'Search extensions...' },
|
|
390
|
+
marketplaceFilterAll: { zh: '全部', en: 'All' },
|
|
391
|
+
marketplaceFilterPlugins: { zh: '插件', en: 'Plugins' },
|
|
392
|
+
marketplaceFilterSkills: { zh: '技能', en: 'Skills' },
|
|
393
|
+
marketplaceSortRelevance: { zh: '相关性', en: 'Relevance' },
|
|
394
|
+
marketplaceSortUpdated: { zh: '最近更新', en: 'Recently Updated' },
|
|
395
|
+
marketplaceUnknownItem: { zh: '未知项目', en: 'Unknown Item' },
|
|
396
|
+
marketplaceInstalledLocalSummary: { zh: '已在本地安装,市场暂无详情。', en: 'Installed locally. Details are currently unavailable from marketplace.' },
|
|
397
|
+
marketplaceTypePlugin: { zh: '插件', en: 'Plugin' },
|
|
398
|
+
marketplaceTypeSkill: { zh: '技能', en: 'Skill' },
|
|
399
|
+
marketplaceTypeExtension: { zh: '扩展', en: 'Extension' },
|
|
400
|
+
marketplaceInstall: { zh: '安装', en: 'Install' },
|
|
401
|
+
marketplaceInstalling: { zh: '安装中...', en: 'Installing...' },
|
|
402
|
+
marketplaceEnable: { zh: '启用', en: 'Enable' },
|
|
403
|
+
marketplaceDisable: { zh: '禁用', en: 'Disable' },
|
|
404
|
+
marketplaceEnabling: { zh: '启用中...', en: 'Enabling...' },
|
|
405
|
+
marketplaceDisabling: { zh: '禁用中...', en: 'Disabling...' },
|
|
406
|
+
marketplaceUninstall: { zh: '卸载', en: 'Uninstall' },
|
|
407
|
+
marketplaceRemoving: { zh: '卸载中...', en: 'Removing...' },
|
|
408
|
+
marketplaceSectionInstalled: { zh: '已安装', en: 'Installed' },
|
|
409
|
+
marketplaceSectionExtensions: { zh: '扩展', en: 'Extensions' },
|
|
410
|
+
marketplaceErrorLoadingData: { zh: '加载市场数据失败', en: 'Failed to load marketplace data' },
|
|
411
|
+
marketplaceErrorLoadingInstalled: { zh: '加载已安装项目失败', en: 'Failed to load installed items' },
|
|
412
|
+
marketplaceNoItems: { zh: '未找到项目。', en: 'No items found.' },
|
|
413
|
+
marketplaceNoInstalledItems: { zh: '未找到已安装项目。', en: 'No installed items found.' },
|
|
414
|
+
marketplaceUninstallTitle: { zh: '确认卸载', en: 'Uninstall' },
|
|
415
|
+
marketplaceUninstallDescription: {
|
|
416
|
+
zh: '该操作会移除扩展,后续可在市场中重新安装。',
|
|
417
|
+
en: 'This will remove the extension. You can install it again from the marketplace.'
|
|
418
|
+
},
|
|
419
|
+
marketplaceInstallFailed: { zh: '安装失败', en: 'Install failed' },
|
|
420
|
+
marketplaceOperationFailed: { zh: '操作失败', en: 'Operation failed' },
|
|
421
|
+
marketplaceInstalledCountSuffix: { zh: '已安装', en: 'installed' },
|
|
169
422
|
|
|
170
423
|
// Status
|
|
171
424
|
connected: { zh: '已连接', en: 'Connected' },
|
|
172
425
|
disconnected: { zh: '未连接', en: 'Disconnected' },
|
|
173
426
|
connecting: { zh: '连接中...', en: 'Connecting...' },
|
|
174
427
|
feishuConnecting: { zh: '验证 / 连接中...', en: 'Verifying / connecting...' },
|
|
428
|
+
statusReady: { zh: '就绪', en: 'Ready' },
|
|
429
|
+
statusSetup: { zh: '待配置', en: 'Setup' },
|
|
430
|
+
statusActive: { zh: '活跃', en: 'Active' },
|
|
431
|
+
statusInactive: { zh: '未启用', en: 'Inactive' },
|
|
432
|
+
|
|
433
|
+
// Action labels
|
|
434
|
+
actionConfigure: { zh: '配置', en: 'Configure' },
|
|
435
|
+
actionAddProvider: { zh: '添加提供商', en: 'Add Provider' },
|
|
436
|
+
actionEnable: { zh: '启用', en: 'Enable' },
|
|
175
437
|
|
|
176
438
|
// Messages
|
|
177
439
|
configSaved: { zh: '配置已保存', en: 'Configuration saved' },
|
|
@@ -199,6 +461,6 @@ export const LABELS: Record<string, { zh: string; en: string }> = {
|
|
|
199
461
|
docBrowserHelp: { zh: '帮助文档', en: 'Help Docs' },
|
|
200
462
|
};
|
|
201
463
|
|
|
202
|
-
export function t(key: string, lang:
|
|
464
|
+
export function t(key: string, lang: I18nLanguage = getLanguage()): string {
|
|
203
465
|
return LABELS[key]?.[lang] || LABELS[key]?.en || key;
|
|
204
466
|
}
|
package/src/main.tsx
CHANGED
|
@@ -2,12 +2,15 @@ import { StrictMode } from 'react';
|
|
|
2
2
|
import { createRoot } from 'react-dom/client';
|
|
3
3
|
import { BrowserRouter } from 'react-router-dom';
|
|
4
4
|
import App from './App';
|
|
5
|
+
import { I18nProvider } from '@/components/providers/I18nProvider';
|
|
5
6
|
import './index.css';
|
|
6
7
|
|
|
7
8
|
createRoot(document.getElementById('root')!).render(
|
|
8
9
|
<StrictMode>
|
|
9
|
-
<
|
|
10
|
-
<
|
|
11
|
-
|
|
10
|
+
<I18nProvider>
|
|
11
|
+
<BrowserRouter>
|
|
12
|
+
<App />
|
|
13
|
+
</BrowserRouter>
|
|
14
|
+
</I18nProvider>
|
|
12
15
|
</StrictMode>
|
|
13
16
|
);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:hsl(var(--gray-200))}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:var(--font-sans);font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}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;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--font-mono);font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:hsl(var(--gray-400))}input::placeholder,textarea::placeholder{opacity:1;color:hsl(var(--gray-400))}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--brand-50: 217 100% 97%;--brand-100: 217 95% 92%;--brand-200: 217 90% 82%;--brand-300: 217 80% 68%;--brand-400: 217 72% 56%;--brand-500: 217 80% 55%;--brand-600: 217 70% 45%;--brand-700: 217 60% 35%;--brand-800: 217 55% 28%;--brand-900: 217 60% 25%;--gray-50: 210 20% 98%;--gray-100: 214 18% 96%;--gray-200: 213 14% 90%;--gray-300: 212 10% 83%;--gray-400: 215 8% 64%;--gray-500: 216 6% 46%;--gray-600: 215 10% 34%;--gray-700: 217 14% 26%;--gray-800: 219 18% 18%;--gray-900: 221 39% 11%;--background-secondary: 214 18% 96%;--background-tertiary: 213 14% 90%;--foreground-secondary: 219 18% 18%;--foreground-tertiary: 216 6% 46%;--foreground-muted: 215 8% 64%;--primary-hover: 217 70% 45%;--primary-active: 217 60% 35%;--secondary-hover: 213 14% 90%;--success: 142 76% 36%;--success-foreground: 0 0% 100%;--warning: 38 92% 50%;--warning-foreground: 0 0% 100%;--card-border: 213 14% 90%;--border-hover: 212 10% 83%;--border-active: 217 80% 55%;--input: 0 0% 100%;--input-border: 213 14% 90%;--input-focus: 217 80% 55%;--ring-offset: 0 0% 100%;--space-0: 0px;--space-1: 4px;--space-2: 8px;--space-3: 12px;--space-4: 16px;--space-5: 20px;--space-6: 24px;--space-8: 32px;--space-10: 40px;--space-12: 48px;--space-16: 64px;--space-20: 80px;--space-24: 96px;--radius-sm: 6px;--radius-md: 8px;--radius-lg: 12px;--radius-xl: 16px;--radius-2xl: 20px;--radius-3xl: 24px;--radius-full: 9999px;--shadow-xs: 0 1px 2px 0 rgb(30 20 10 / .04);--shadow-sm: 0 1px 3px 0 rgb(30 20 10 / .06), 0 1px 2px -1px rgb(30 20 10 / .04);--shadow-md: 0 4px 6px -1px rgb(30 20 10 / .06), 0 2px 4px -2px rgb(30 20 10 / .04);--shadow-lg: 0 10px 15px -3px rgb(30 20 10 / .06), 0 4px 6px -4px rgb(30 20 10 / .04);--shadow-xl: 0 20px 25px -5px rgb(30 20 10 / .08), 0 8px 10px -6px rgb(30 20 10 / .04);--shadow-2xl: 0 25px 50px -12px rgb(30 20 10 / .15);--shadow-card: 0 1px 3px -1px rgba(30, 20, 10, .03), 0 1px 2px -1px rgba(30, 20, 10, .02);--shadow-card-hover: 0 8px 20px -4px rgba(30, 20, 10, .06), 0 4px 8px -4px rgba(30, 20, 10, .03);--font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;--font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;--text-xs: 12px;--text-sm: 14px;--text-base: 16px;--text-lg: 18px;--text-xl: 20px;--text-2xl: 24px;--text-3xl: 30px;--text-4xl: 36px;--text-5xl: 48px;--font-normal: 400;--font-medium: 500;--font-semibold: 600;--font-bold: 700;--leading-tight: 1.25;--leading-snug: 1.375;--leading-normal: 1.5;--leading-relaxed: 1.625;--tracking-tight: -.025em;--tracking-normal: 0;--tracking-wide: .025em;--transition-fast: .15s ease;--transition-base: .2s ease;--transition-slow: .3s ease;--z-dropdown: 100;--z-sticky: 200;--z-fixed: 300;--z-modal-backdrop: 400;--z-modal: 500;--z-popover: 600;--z-tooltip: 700;--background: 210 20% 98%;--foreground: 221 39% 11%;--card: 0 0% 100%;--card-foreground: 221 39% 11%;--popover: 0 0% 100%;--popover-foreground: 221 39% 11%;--primary: 217 80% 55%;--primary-foreground: 0 0% 100%;--secondary: 214 18% 96%;--secondary-foreground: 219 18% 18%;--muted: 214 18% 96%;--muted-foreground: 216 6% 46%;--accent: 217 100% 97%;--accent-foreground: 217 60% 35%;--destructive: 0 84% 60%;--destructive-foreground: 0 0% 98%;--border: 213 14% 90%;--input: 213 14% 90%;--ring: 217 80% 55%;--radius: .75rem}*{border-color:hsl(var(--border))}html{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body{background-color:hsl(var(--background));color:hsl(var(--foreground));font-family:var(--font-sans);overflow:hidden}*{scrollbar-width:thin;scrollbar-color:hsl(var(--gray-300)) transparent}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-0{bottom:0}.left-0{left:0}.left-3{left:.75rem}.left-\[50\%\]{left:50%}.right-0{right:0}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-1\/2{top:50%}.top-2\.5{top:.625rem}.top-4{top:1rem}.top-\[50\%\]{top:50%}.z-10{z-index:10}.z-20{z-index:20}.z-30{z-index:30}.z-50{z-index:50}.z-\[var\(--z-tooltip\)\]{z-index:var(--z-tooltip)}.-mx-1{margin-left:-.25rem;margin-right:-.25rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.mb-0\.5{margin-bottom:.125rem}.mb-1\.5{margin-bottom:.375rem}.mb-10{margin-bottom:2.5rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mr-1\.5{margin-right:.375rem}.mr-2{margin-right:.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.mt-auto{margin-top:auto}.line-clamp-1{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}.line-clamp-2{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.h-1{height:.25rem}.h-1\.5{height:.375rem}.h-10{height:2.5rem}.h-11{height:2.75rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-20{height:5rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-\[17px\]{height:17px}.h-\[180px\]{height:180px}.h-\[22px\]{height:22px}.h-\[2px\]{height:2px}.h-\[calc\(100vh-80px\)\]{height:calc(100vh - 80px)}.h-\[var\(--radix-select-trigger-height\)\]{height:var(--radix-select-trigger-height)}.h-full{height:100%}.h-px{height:1px}.h-screen{height:100vh}.max-h-96{max-height:24rem}.max-h-\[60vh\]{max-height:60vh}.max-h-\[85vh\]{max-height:85vh}.min-h-0{min-height:0px}.min-h-\[120px\]{min-height:120px}.min-h-\[42px\]{min-height:42px}.w-1\.5{width:.375rem}.w-1\/3{width:33.333333%}.w-10{width:2.5rem}.w-11{width:2.75rem}.w-12{width:3rem}.w-14{width:3.5rem}.w-2\.5{width:.625rem}.w-20{width:5rem}.w-24{width:6rem}.w-28{width:7rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-32{width:8rem}.w-4{width:1rem}.w-40{width:10rem}.w-48{width:12rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[150px\]{width:150px}.w-\[160px\]{width:160px}.w-\[17px\]{width:17px}.w-\[240px\]{width:240px}.w-\[320px\]{width:320px}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-20{min-width:5rem}.min-w-\[100px\]{min-width:100px}.min-w-\[180px\]{min-width:180px}.min-w-\[220px\]{min-width:220px}.min-w-\[240px\]{min-width:240px}.min-w-\[8rem\]{min-width:8rem}.min-w-\[var\(--radix-select-trigger-width\)\]{min-width:var(--radix-select-trigger-width)}.max-w-2xl{max-width:42rem}.max-w-3xl{max-width:48rem}.max-w-4xl{max-width:56rem}.max-w-6xl{max-width:72rem}.max-w-\[100px\]{max-width:100px}.max-w-\[1200px\]{max-width:1200px}.max-w-\[1400px\]{max-width:1400px}.max-w-\[200px\]{max-width:200px}.max-w-\[280px\]{max-width:280px}.max-w-\[300px\]{max-width:300px}.max-w-\[400px\]{max-width:400px}.max-w-\[85\%\]{max-width:85%}.max-w-full{max-width:100%}.max-w-lg{max-width:32rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0,.shrink-0{flex-shrink:0}.-translate-y-1\/2{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x: 0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-5{--tw-translate-x: 1.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-\[-50\%\]{--tw-translate-x: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-y-\[-50\%\]{--tw-translate-y: -50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-rotate-3{--tw-rotate: -3deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-3{--tw-rotate: 3deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.rotate-\[-45deg\]{--tw-rotate: -45deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes fadeIn{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:translateY(0)}}.animate-fade-in{animation:fadeIn .4s cubic-bezier(.16,1,.3,1) forwards}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}@keyframes slideIn{0%{opacity:0;transform:translate(-12px)}to{opacity:1;transform:translate(0)}}.animate-slide-in{animation:slideIn .35s cubic-bezier(.16,1,.3,1) forwards}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}.cursor-default{cursor:default}.cursor-ew-resize{cursor:ew-resize}.cursor-grab{cursor:grab}.cursor-ns-resize{cursor:ns-resize}.cursor-pointer{cursor:pointer}.cursor-se-resize{cursor:se-resize}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.appearance-none{-webkit-appearance:none;-moz-appearance:none;appearance:none}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.items-baseline{align-items:baseline}.justify-start{justify-content:flex-start}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-12{gap:3rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-3\.5{gap:.875rem}.gap-4{gap:1rem}.gap-6{gap:1.5rem}.gap-8{gap:2rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-1\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.375rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.375rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.space-y-8>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(2rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(2rem * var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.overflow-x-hidden{overflow-x:hidden}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:calc(var(--radius) + 8px)}.rounded-3xl{border-radius:1.5rem}.rounded-\[1\.25rem\]{border-radius:1.25rem}.rounded-\[14px\]{border-radius:14px}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-r-full{border-top-right-radius:9999px;border-bottom-right-radius:9999px}.rounded-tl-sm{border-top-left-radius:calc(var(--radius) - 4px)}.rounded-tr-sm{border-top-right-radius:calc(var(--radius) - 4px)}.border{border-width:1px}.border-0{border-width:0px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-\[\#dde0ea\]{--tw-border-opacity: 1;border-color:rgb(221 224 234 / var(--tw-border-opacity, 1))}.border-gray-100{border-color:hsl(var(--gray-100))}.border-gray-100\/50{border-color:hsl(var(--gray-100) / .5)}.border-gray-200{border-color:hsl(var(--gray-200))}.border-gray-200\/40{border-color:hsl(var(--gray-200) / .4)}.border-gray-200\/50{border-color:hsl(var(--gray-200) / .5)}.border-gray-200\/60{border-color:hsl(var(--gray-200) / .6)}.border-gray-200\/80{border-color:hsl(var(--gray-200) / .8)}.border-primary\/30{border-color:hsl(var(--primary) / .3)}.border-red-100{--tw-border-opacity: 1;border-color:rgb(254 226 226 / var(--tw-border-opacity, 1))}.border-rose-100{--tw-border-opacity: 1;border-color:rgb(255 228 230 / var(--tw-border-opacity, 1))}.border-rose-200{--tw-border-opacity: 1;border-color:rgb(254 205 211 / var(--tw-border-opacity, 1))}.border-transparent{border-color:transparent}.bg-\[\#f0f2f7\]{--tw-bg-opacity: 1;background-color:rgb(240 242 247 / var(--tw-bg-opacity, 1))}.bg-amber-400{--tw-bg-opacity: 1;background-color:rgb(251 191 36 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-600{--tw-bg-opacity: 1;background-color:rgb(217 119 6 / var(--tw-bg-opacity, 1))}.bg-background{background-color:hsl(var(--background))}.bg-black\/40{background-color:#0006}.bg-cyan-600{--tw-bg-opacity: 1;background-color:rgb(8 145 178 / var(--tw-bg-opacity, 1))}.bg-destructive{background-color:hsl(var(--destructive))}.bg-emerald-50{--tw-bg-opacity: 1;background-color:rgb(236 253 245 / var(--tw-bg-opacity, 1))}.bg-emerald-500{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.bg-emerald-600{--tw-bg-opacity: 1;background-color:rgb(5 150 105 / var(--tw-bg-opacity, 1))}.bg-gray-100\/80{background-color:hsl(var(--gray-100) / .8)}.bg-gray-200{background-color:hsl(var(--gray-200))}.bg-gray-200\/80{background-color:hsl(var(--gray-200) / .8)}.bg-gray-300{background-color:hsl(var(--gray-300))}.bg-gray-50\/50{background-color:hsl(var(--gray-50) / .5)}.bg-muted{background-color:hsl(var(--muted))}.bg-orange-500{--tw-bg-opacity: 1;background-color:rgb(249 115 22 / var(--tw-bg-opacity, 1))}.bg-popover{background-color:hsl(var(--popover))}.bg-primary{background-color:hsl(var(--primary))}.bg-primary\/10{background-color:hsl(var(--primary) / .1)}.bg-primary\/20{background-color:hsl(var(--primary) / .2)}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-rose-50{--tw-bg-opacity: 1;background-color:rgb(255 241 242 / var(--tw-bg-opacity, 1))}.bg-rose-500{--tw-bg-opacity: 1;background-color:rgb(244 63 94 / var(--tw-bg-opacity, 1))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-stone-600{--tw-bg-opacity: 1;background-color:rgb(87 83 78 / var(--tw-bg-opacity, 1))}.bg-teal-600{--tw-bg-opacity: 1;background-color:rgb(13 148 136 / var(--tw-bg-opacity, 1))}.bg-transparent{background-color:transparent}.bg-violet-500{--tw-bg-opacity: 1;background-color:rgb(139 92 246 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/90{background-color:#ffffffe6}.bg-yellow-600{--tw-bg-opacity: 1;background-color:rgb(202 138 4 / var(--tw-bg-opacity, 1))}.bg-gradient-to-br{background-image:linear-gradient(to bottom right,var(--tw-gradient-stops))}.bg-gradient-to-l{background-image:linear-gradient(to left,var(--tw-gradient-stops))}.from-purple-400{--tw-gradient-from: #c084fc var(--tw-gradient-from-position);--tw-gradient-to: rgb(192 132 252 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-rose-400{--tw-gradient-from: #fb7185 var(--tw-gradient-from-position);--tw-gradient-to: rgb(251 113 133 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-sky-400{--tw-gradient-from: #38bdf8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(56 189 248 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-slate-400{--tw-gradient-from: #94a3b8 var(--tw-gradient-from-position);--tw-gradient-to: rgb(148 163 184 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-transparent{--tw-gradient-from: transparent var(--tw-gradient-from-position);--tw-gradient-to: rgb(0 0 0 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.to-blue-500{--tw-gradient-to: #3b82f6 var(--tw-gradient-to-position)}.to-gray-500{--tw-gradient-to: hsl(var(--gray-500)) var(--tw-gradient-to-position)}.to-indigo-500{--tw-gradient-to: #6366f1 var(--tw-gradient-to-position)}.to-pink-500{--tw-gradient-to: #ec4899 var(--tw-gradient-to-position)}.to-white\/10{--tw-gradient-to: rgb(255 255 255 / .1) var(--tw-gradient-to-position)}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-3\.5{padding:.875rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-6{padding:1.5rem}.p-8{padding:2rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-16{padding-top:4rem;padding-bottom:4rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-4{padding-top:1rem;padding-bottom:1rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.py-6{padding-top:1.5rem;padding-bottom:1.5rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pb-10{padding-bottom:2.5rem}.pb-2{padding-bottom:.5rem}.pb-20{padding-bottom:5rem}.pb-3{padding-bottom:.75rem}.pb-5{padding-bottom:1.25rem}.pl-2{padding-left:.5rem}.pl-8{padding-left:2rem}.pl-9{padding-left:2.25rem}.pr-1{padding-right:.25rem}.pr-2{padding-right:.5rem}.pr-20{padding-right:5rem}.pr-3{padding-right:.75rem}.pr-6{padding-right:1.5rem}.pr-8{padding-right:2rem}.pt-0{padding-top:0}.pt-0\.5{padding-top:.125rem}.pt-2{padding-top:.5rem}.pt-3{padding-top:.75rem}.pt-4{padding-top:1rem}.pt-5{padding-top:1.25rem}.pt-6{padding-top:1.5rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13px\]{font-size:13px}.text-\[14px\]{font-size:14px}.text-\[15px\]{font-size:15px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.leading-none{line-height:1}.leading-relaxed{line-height:1.625}.leading-tight{line-height:1.25}.tracking-\[-0\.01em\]{letter-spacing:-.01em}.tracking-tight{letter-spacing:-.025em}.tracking-wider{letter-spacing:.05em}.tracking-widest{letter-spacing:.1em}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-card-foreground{color:hsl(var(--card-foreground))}.text-destructive-foreground{color:hsl(var(--destructive-foreground))}.text-emerald-600{--tw-text-opacity: 1;color:rgb(5 150 105 / var(--tw-text-opacity, 1))}.text-emerald-700{--tw-text-opacity: 1;color:rgb(4 120 87 / var(--tw-text-opacity, 1))}.text-foreground{color:hsl(var(--foreground))}.text-gray-300{color:hsl(var(--gray-300))}.text-gray-400{color:hsl(var(--gray-400))}.text-gray-500\/90{color:hsl(var(--gray-500) / .9)}.text-gray-700{color:hsl(var(--gray-700))}.text-gray-800{color:hsl(var(--gray-800))}.text-popover-foreground{color:hsl(var(--popover-foreground))}.text-primary{color:hsl(var(--primary))}.text-primary-100{color:hsl(var(--brand-100))}.text-primary-200{color:hsl(var(--brand-200))}.text-primary-50{color:hsl(var(--brand-50))}.text-primary-foreground{color:hsl(var(--primary-foreground))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-rose-500{--tw-text-opacity: 1;color:rgb(244 63 94 / var(--tw-text-opacity, 1))}.text-rose-700{--tw-text-opacity: 1;color:rgb(190 18 60 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.underline-offset-4{text-underline-offset:4px}.accent-primary{accent-color:hsl(var(--primary))}.opacity-0{opacity:0}.opacity-50{opacity:.5}.opacity-70{opacity:.7}.opacity-90{opacity:.9}.mix-blend-multiply{mix-blend-mode:multiply}.shadow{--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_1px_2px_rgba\(0\,0\,0\,0\.02\)\]{--tw-shadow: 0 1px 2px rgba(0,0,0,.02);--tw-shadow-colored: 0 1px 2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-\[0_2px_8px_-2px_rgba\(0\,0\,0\,0\.02\)\]{--tw-shadow: 0 2px 8px -2px rgba(0,0,0,.02);--tw-shadow-colored: 0 2px 8px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-card{--tw-shadow: var(--shadow-card);--tw-shadow-colored: var(--shadow-card);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-md{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-none{--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-card{--tw-shadow-color: hsl(var(--card));--tw-shadow: var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.outline{outline-style:solid}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-offset-background{--tw-ring-offset-color: hsl(var(--background))}.ring-offset-white{--tw-ring-offset-color: #fff}.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)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.duration-200,.duration-base{transition-duration:.2s}.duration-fast{transition-duration:.15s}.duration-slow{transition-duration:.3s}@keyframes enter{0%{opacity:var(--tw-enter-opacity, 1);transform:translate3d(var(--tw-enter-translate-x, 0),var(--tw-enter-translate-y, 0),0) scale3d(var(--tw-enter-scale, 1),var(--tw-enter-scale, 1),var(--tw-enter-scale, 1)) rotate(var(--tw-enter-rotate, 0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity, 1);transform:translate3d(var(--tw-exit-translate-x, 0),var(--tw-exit-translate-y, 0),0) scale3d(var(--tw-exit-scale, 1),var(--tw-exit-scale, 1),var(--tw-exit-scale, 1)) rotate(var(--tw-exit-rotate, 0))}}.animate-in{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.fade-in-0{--tw-enter-opacity: 0}.zoom-in-95{--tw-enter-scale: .95}.duration-200,.duration-base{animation-duration:.2s}.duration-fast{animation-duration:.15s}.duration-slow{animation-duration:.3s}.bg-brand-50{background-color:hsl(var(--brand-50))}.text-brand-600{color:hsl(var(--brand-600))}.bg-gray-50{background-color:hsl(var(--gray-50))}.bg-gray-100{background-color:hsl(var(--gray-100))}.text-gray-500{color:hsl(var(--gray-500))}.text-gray-600{color:hsl(var(--gray-600))}.text-gray-900{color:hsl(var(--gray-900))}.shadow-card{box-shadow:var(--shadow-card)}.custom-scrollbar::-webkit-scrollbar{width:5px;height:5px}.custom-scrollbar::-webkit-scrollbar-track{background:transparent}.custom-scrollbar::-webkit-scrollbar-thumb{background:hsl(var(--gray-300));border-radius:6px}.custom-scrollbar::-webkit-scrollbar-thumb:hover{background:hsl(var(--gray-400))}.shadow-card{box-shadow:0 1px 3px -1px #1e140a08,0 1px 2px -1px #1e140a05}@keyframes fadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@keyframes slideIn{0%{opacity:0;transform:translate(-8px)}to{opacity:1;transform:translate(0)}}@keyframes scaleIn{0%{opacity:0;transform:scale(.98)}to{opacity:1;transform:scale(1)}}@keyframes pulse-soft{0%,to{opacity:1}50%{opacity:.85}}.animate-fade-in{animation:fadeIn .35s cubic-bezier(.16,1,.3,1) forwards}.animate-slide-in{animation:slideIn .3s cubic-bezier(.16,1,.3,1) forwards}.animate-scale-in{animation:scaleIn .3s cubic-bezier(.16,1,.3,1) forwards}.animate-pulse-soft{animation:pulse-soft 3s ease-in-out infinite}.file\:border-0::file-selector-button{border-width:0px}.file\:bg-transparent::file-selector-button{background-color:transparent}.file\:text-sm::file-selector-button{font-size:.875rem;line-height:1.25rem}.file\:font-medium::file-selector-button{font-weight:500}.placeholder\:text-gray-400::-moz-placeholder{color:hsl(var(--gray-400))}.placeholder\:text-gray-400::placeholder{color:hsl(var(--gray-400))}.placeholder\:text-muted-foreground::-moz-placeholder{color:hsl(var(--muted-foreground))}.placeholder\:text-muted-foreground::placeholder{color:hsl(var(--muted-foreground))}.hover\:border-gray-200:hover{border-color:hsl(var(--gray-200))}.hover\:border-gray-200\/80:hover{border-color:hsl(var(--gray-200) / .8)}.hover\:border-gray-300:hover{border-color:hsl(var(--gray-300))}.hover\:border-red-200:hover{--tw-border-opacity: 1;border-color:rgb(254 202 202 / var(--tw-border-opacity, 1))}.hover\:border-rose-200:hover{--tw-border-opacity: 1;border-color:rgb(254 205 211 / var(--tw-border-opacity, 1))}.hover\:bg-\[\#e4e7ef\]:hover{--tw-bg-opacity: 1;background-color:rgb(228 231 239 / var(--tw-bg-opacity, 1))}.hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive) / .9)}.hover\:bg-gray-100\/60:hover{background-color:hsl(var(--gray-100) / .6)}.hover\:bg-gray-100\/80:hover{background-color:hsl(var(--gray-100) / .8)}.hover\:bg-gray-200:hover{background-color:hsl(var(--gray-200))}.hover\:bg-gray-200\/80:hover{background-color:hsl(var(--gray-200) / .8)}.hover\:bg-gray-300\/80:hover{background-color:hsl(var(--gray-300) / .8)}.hover\:bg-gray-50\/80:hover{background-color:hsl(var(--gray-50) / .8)}.hover\:bg-primary:hover{background-color:hsl(var(--primary))}.hover\:bg-primary-600:hover{background-color:hsl(var(--brand-600))}.hover\:bg-primary\/10:hover{background-color:hsl(var(--primary) / .1)}.hover\:bg-red-50:hover{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.hover\:bg-rose-50:hover{--tw-bg-opacity: 1;background-color:rgb(255 241 242 / var(--tw-bg-opacity, 1))}.hover\:bg-white\/50:hover{background-color:#ffffff80}.hover\:text-gray-700:hover{color:hsl(var(--gray-700))}.hover\:text-gray-800:hover{color:hsl(var(--gray-800))}.hover\:text-primary:hover{color:hsl(var(--primary))}.hover\:text-primary-foreground:hover{color:hsl(var(--primary-foreground))}.hover\:text-red-300:hover{--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.hover\:text-red-600:hover{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-100:hover{opacity:1}.hover\:shadow-card-hover:hover{--tw-shadow: var(--shadow-card-hover);--tw-shadow-colored: var(--shadow-card-hover);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:shadow-md:hover{--tw-shadow: 0 4px 6px -1px rgb(0 0 0 / .1), 0 2px 4px -2px rgb(0 0 0 / .1);--tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.hover\:bg-gray-50:hover{background-color:hsl(var(--gray-50))}.hover\:bg-gray-100:hover{background-color:hsl(var(--gray-100))}.hover\:text-gray-500:hover{color:hsl(var(--gray-500))}.hover\:text-gray-900:hover{color:hsl(var(--gray-900))}.hover\:shadow-card-hover:hover{box-shadow:var(--shadow-card-hover);box-shadow:0 8px 20px -4px #1e140a0f,0 4px 8px -4px #1e140a08}.focus\:border-primary\/40:focus{border-color:hsl(var(--primary) / .4)}.focus\:text-accent-foreground:focus{color:hsl(var(--accent-foreground))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-0:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-1:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-primary\/30:focus{--tw-ring-color: hsl(var(--primary) / .3)}.focus\:ring-primary\/40:focus{--tw-ring-color: hsl(var(--primary) / .4)}.focus\:bg-gray-100:focus{background-color:hsl(var(--gray-100))}.focus-visible\:bg-white:focus-visible{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.focus-visible\:outline-none:focus-visible{outline:2px solid transparent;outline-offset:2px}.focus-visible\:ring-2:focus-visible{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus-visible\:ring-primary:focus-visible{--tw-ring-color: hsl(var(--primary))}.focus-visible\:ring-ring:focus-visible{--tw-ring-color: hsl(var(--ring))}.focus-visible\:ring-offset-2:focus-visible{--tw-ring-offset-width: 2px}.focus-visible\:ring-offset-white:focus-visible{--tw-ring-offset-color: #fff}.active\:cursor-grabbing:active{cursor:grabbing}.active\:bg-primary-700:active{background-color:hsl(var(--brand-700))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-30:disabled{opacity:.3}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.group\/action:hover .group-hover\/action\:translate-x-0\.5{--tw-translate-x: .125rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:scale-110{--tw-scale-x: 1.1;--tw-scale-y: 1.1;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:border-gray-300{border-color:hsl(var(--gray-300))}.group:hover .group-hover\:text-primary{color:hsl(var(--primary))}.group:hover .group-hover\:opacity-100{opacity:1}.peer:disabled~.peer-disabled\:cursor-not-allowed{cursor:not-allowed}.peer:disabled~.peer-disabled\:opacity-70{opacity:.7}.data-\[disabled\]\:pointer-events-none[data-disabled]{pointer-events:none}.data-\[side\=bottom\]\:translate-y-1[data-side=bottom]{--tw-translate-y: .25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=left\]\:-translate-x-1[data-side=left]{--tw-translate-x: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=right\]\:translate-x-1[data-side=right]{--tw-translate-x: .25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[side\=top\]\:-translate-y-1[data-side=top]{--tw-translate-y: -.25rem;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.data-\[state\=checked\]\:bg-emerald-500[data-state=checked]{--tw-bg-opacity: 1;background-color:rgb(16 185 129 / var(--tw-bg-opacity, 1))}.data-\[disabled\]\:opacity-50[data-disabled]{opacity:.5}.data-\[state\=open\]\:animate-in[data-state=open]{animation-name:enter;animation-duration:.15s;--tw-enter-opacity: initial;--tw-enter-scale: initial;--tw-enter-rotate: initial;--tw-enter-translate-x: initial;--tw-enter-translate-y: initial}.data-\[state\=closed\]\:animate-out[data-state=closed]{animation-name:exit;animation-duration:.15s;--tw-exit-opacity: initial;--tw-exit-scale: initial;--tw-exit-rotate: initial;--tw-exit-translate-x: initial;--tw-exit-translate-y: initial}.data-\[state\=closed\]\:fade-out-0[data-state=closed]{--tw-exit-opacity: 0}.data-\[state\=open\]\:fade-in-0[data-state=open]{--tw-enter-opacity: 0}.data-\[state\=closed\]\:zoom-out-95[data-state=closed]{--tw-exit-scale: .95}.data-\[state\=open\]\:zoom-in-95[data-state=open]{--tw-enter-scale: .95}.data-\[side\=bottom\]\:slide-in-from-top-2[data-side=bottom]{--tw-enter-translate-y: -.5rem}.data-\[side\=left\]\:slide-in-from-right-2[data-side=left]{--tw-enter-translate-x: .5rem}.data-\[side\=right\]\:slide-in-from-left-2[data-side=right]{--tw-enter-translate-x: -.5rem}.data-\[side\=top\]\:slide-in-from-bottom-2[data-side=top]{--tw-enter-translate-y: .5rem}.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed]{--tw-exit-translate-x: -50%}.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed]{--tw-exit-translate-y: -48%}.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open]{--tw-enter-translate-x: -50%}.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open]{--tw-enter-translate-y: -48%}@media(min-width:640px){.sm\:max-w-\[500px\]{max-width:500px}.sm\:max-w-\[550px\]{max-width:550px}.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:flex-row{flex-direction:row}.sm\:justify-end{justify-content:flex-end}.sm\:gap-0{gap:0px}.sm\:gap-3{gap:.75rem}.sm\:text-left{text-align:left}}@media(min-width:768px){.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.md\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:1024px){.lg\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media(min-width:1280px){.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}@media(min-width:1536px){.\32xl\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}.\[\&\:\:-webkit-scrollbar-thumb\]\:rounded-full::-webkit-scrollbar-thumb{border-radius:9999px}.\[\&\:\:-webkit-scrollbar-thumb\]\:bg-gray-300\/80::-webkit-scrollbar-thumb{background-color:hsl(var(--gray-300) / .8)}.\[\&\:\:-webkit-scrollbar\]\:w-2::-webkit-scrollbar{width:.5rem}.\[\&\>\:last-child\]\:hidden>:last-child{display:none}.\[\&\>span\]\:line-clamp-1>span{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1}
|