huhaa-myskills 0.2.6 → 0.2.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "huhaa-myskills",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "private": false,
5
5
  "description": "Local skill / plugin / MCP aggregation hub. Browse all your AI agent skills at http://localhost:11520.",
6
6
  "license": "MIT",
@@ -102,7 +102,7 @@ function parseSkillFile({ abs, root, source, limits }) {
102
102
  });
103
103
  }
104
104
 
105
- const { data: fm, body, parseError } = parseFrontmatter(text);
105
+ const { data: fm, body, i18n, parseError } = parseFrontmatter(text);
106
106
 
107
107
  const name = (fm.name || dirName).toString().trim();
108
108
  const title = (fm.title || fm.name || dirName).toString().trim();
@@ -140,6 +140,16 @@ function parseSkillFile({ abs, root, source, limits }) {
140
140
  updatedAt: new Date(mtime).toISOString(),
141
141
  product,
142
142
  };
143
+
144
+ // Include i18n translations if present
145
+ if (i18n) {
146
+ item.i18n = {
147
+ ...i18n,
148
+ translatedAt: new Date().toISOString(),
149
+ translationModel: 'frontmatter',
150
+ };
151
+ }
152
+
143
153
  item.brand = inferBrand({
144
154
  name: item.name,
145
155
  description: item.description,
@@ -132,6 +132,18 @@ export async function scan() {
132
132
 
133
133
  const out = dedupeSemantic(all);
134
134
 
135
+ // Optional: translate skills to Chinese via LLM
136
+ if (process.env.HUHAA_TRANSLATE === '1') {
137
+ console.log('[scan] translating skills to Chinese...');
138
+ try {
139
+ const { translateSkill } = await import('../../../packages/server/src/translator.mjs');
140
+ const translated = await Promise.all(out.map(s => translateSkill(s, 'zh')));
141
+ return translated;
142
+ } catch (e) {
143
+ console.warn('[scan] translation failed:', e.message);
144
+ }
145
+ }
146
+
135
147
  if (process.env.HUHAA_DEBUG) {
136
148
  console.error('[scan] stats:', JSON.stringify(stats, null, 2));
137
149
  }
@@ -82,7 +82,7 @@ const FM_RE = /^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/;
82
82
 
83
83
  /**
84
84
  * Parse YAML frontmatter at the very top of a markdown file.
85
- * Returns { data, body, parseError? }. `data` is always an object (possibly
85
+ * Returns { data, body, i18n?, parseError? }. `data` is always an object (possibly
86
86
  * empty). Body never has the frontmatter block.
87
87
  */
88
88
  export function parseFrontmatter(text) {
@@ -96,9 +96,17 @@ export function parseFrontmatter(text) {
96
96
  const [, yamlBlock, body] = m;
97
97
  try {
98
98
  const data = YAML.parse(yamlBlock) || {};
99
+
100
+ // Extract i18n fields if present
101
+ const i18n = {};
102
+ for (const key of ['name_zh', 'description_zh', 'category_zh']) {
103
+ if (data[key]) i18n[key] = data[key];
104
+ }
105
+
99
106
  return {
100
107
  data: typeof data === 'object' && !Array.isArray(data) ? data : {},
101
108
  body: body || '',
109
+ ...(Object.keys(i18n).length > 0 && { i18n }),
102
110
  };
103
111
  } catch (e) {
104
112
  return { data: {}, body: body || text, parseError: `frontmatter: ${e.message}` };
@@ -232,6 +232,24 @@ export async function startServer({ port = 11520 } = {}) {
232
232
  }
233
233
  });
234
234
 
235
+ app.post('/api/translate', async (req, reply) => {
236
+ const { id } = req.body || {};
237
+ const item = irById.get(id);
238
+ if (!item) {
239
+ reply.code(404);
240
+ return { error: 'not found' };
241
+ }
242
+
243
+ const { translateSkill } = await import('./translator.mjs');
244
+ try {
245
+ const translated = await translateSkill(item, 'zh');
246
+ return translated;
247
+ } catch (e) {
248
+ reply.code(500);
249
+ return { error: e.message };
250
+ }
251
+ });
252
+
235
253
  app.get('/assets/*', async (req, reply) => {
236
254
  if (!hasSpa) {
237
255
  reply.code(404);
@@ -0,0 +1,71 @@
1
+ export async function translateSkill(skill, targetLang = 'zh') {
2
+ if (targetLang !== 'zh' || skill.i18n?.name_zh) return skill;
3
+
4
+ const apiKey = process.env.ANTHROPIC_API_KEY;
5
+ if (!apiKey) {
6
+ console.warn('[translator] ANTHROPIC_API_KEY not set, skipping translation');
7
+ return skill;
8
+ }
9
+
10
+ const prompt = `Translate these skill metadata to Chinese (简体中文). Return JSON only, no markdown.
11
+
12
+ Current metadata:
13
+ - name: ${skill.name}
14
+ - description: ${skill.description || '(none)'}
15
+ - category: ${skill.category || '(none)'}
16
+
17
+ Return JSON format (translate only the values):
18
+ {
19
+ "name_zh": "中文名称",
20
+ "description_zh": "中文描述",
21
+ "category_zh": "中文分类"
22
+ }
23
+
24
+ Guidelines:
25
+ - Keep technical terms like "API", "MCP", "LLM" in English when appropriate
26
+ - Use common Chinese equivalents for concepts (e.g., "skill" → "技能", "rule" → "规则")
27
+ - Keep descriptions concise (under 100 chars)
28
+ - Preserve the technical meaning
29
+ - Return valid JSON only`;
30
+
31
+ try {
32
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
33
+ method: 'POST',
34
+ headers: {
35
+ 'Content-Type': 'application/json',
36
+ 'x-api-key': apiKey,
37
+ 'anthropic-version': '2023-06-01',
38
+ },
39
+ body: JSON.stringify({
40
+ model: 'claude-3-5-sonnet-20241022',
41
+ max_tokens: 500,
42
+ messages: [{
43
+ role: 'user',
44
+ content: prompt,
45
+ }],
46
+ }),
47
+ });
48
+
49
+ if (!response.ok) {
50
+ const error = await response.text();
51
+ throw new Error(`Claude API: ${response.status} ${error}`);
52
+ }
53
+
54
+ const data = await response.json();
55
+ const translated = JSON.parse(data.content[0].text);
56
+
57
+ return {
58
+ ...skill,
59
+ i18n: {
60
+ name_zh: translated.name_zh,
61
+ description_zh: translated.description_zh,
62
+ category_zh: translated.category_zh,
63
+ translatedAt: new Date().toISOString(),
64
+ translationModel: 'claude-3.5-sonnet',
65
+ },
66
+ };
67
+ } catch (e) {
68
+ console.error(`[translator] error: ${e.message}`);
69
+ return skill;
70
+ }
71
+ }
@@ -0,0 +1 @@
1
+ .skill-tree[data-v-1b7c4344]{display:flex;flex-direction:column;overflow-y:auto;font-size:13px;border-right:1px solid #ddd;-webkit-user-select:none;user-select:none}.tree-group[data-v-1b7c4344]{border-bottom:1px solid #f0f0f0}.tree-group-header[data-v-1b7c4344]{width:100%;padding:8px 10px;background:#f8f8f8;border:none;border-bottom:1px solid #e8e8e8;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:6px;font-size:12px;text-align:left;justify-content:flex-start;transition:all .15s ease}.tree-group-header[data-v-1b7c4344]:hover{background:#f0f0f0}.tree-group-header.expanded[data-v-1b7c4344]{background:#e8e8e8}.tree-arrow[data-v-1b7c4344]{width:16px;text-align:center;flex-shrink:0;font-size:11px;color:#666}.source-icon[data-v-1b7c4344]{width:16px;text-align:center;flex-shrink:0;font-size:14px}.source-name[data-v-1b7c4344]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.skill-count[data-v-1b7c4344]{margin-left:auto;color:#999;font-size:11px;font-weight:400;flex-shrink:0}.tree-group-items[data-v-1b7c4344]{background:#fafafa;display:flex;flex-direction:column}.skill-tree-item[data-v-1b7c4344]{display:flex;align-items:center;gap:6px;width:100%;padding:6px 16px;border:none;background:transparent;cursor:pointer;font-size:12px;transition:background-color .1s ease;text-align:left;color:inherit;justify-content:flex-start}.skill-tree-item[data-v-1b7c4344]:hover{background:#f0f0f0}.skill-tree-item.active[data-v-1b7c4344]{background:#e3f2fd;color:#1976d2;font-weight:500}.icon[data-v-1b7c4344]{width:16px;text-align:center;flex-shrink:0;font-size:12px}.name[data-v-1b7c4344]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.category-tag[data-v-1b7c4344]{margin-left:4px;padding:1px 4px;background:#f0f0f0;border-radius:2px;font-size:10px;color:#666;flex-shrink:0}.empty-tree[data-v-1b7c4344]{display:flex;align-items:center;justify-content:center;height:100px;color:#999;font-size:12px}.directory-tree[data-v-2adea2d7]{display:flex;flex-direction:column;overflow-y:auto;font-size:13px;-webkit-user-select:none;user-select:none}.tree-item[data-v-2adea2d7]{display:flex;flex-direction:column}.tree-dir[data-v-2adea2d7]{padding:6px 10px;background:transparent;border:none;cursor:pointer;display:flex;align-items:center;gap:6px;font-size:12px;text-align:left;color:inherit;transition:background-color .1s ease;width:100%;justify-content:flex-start}.tree-dir[data-v-2adea2d7]:hover{background:#f0f0f0}.tree-arrow[data-v-2adea2d7]{width:16px;text-align:center;flex-shrink:0;font-size:10px;color:#666}.tree-icon[data-v-2adea2d7]{width:16px;text-align:center;flex-shrink:0;font-size:12px}.tree-name[data-v-2adea2d7]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:500}.tree-count[data-v-2adea2d7]{margin-left:auto;padding:0 4px;background:#e8e8e8;border-radius:2px;font-size:10px;color:#666;flex-shrink:0}.tree-skills[data-v-2adea2d7]{display:flex;flex-direction:column}.tree-skill-item[data-v-2adea2d7]{padding:6px 10px;background:transparent;border:none;cursor:pointer;display:flex;align-items:center;gap:6px;font-size:12px;text-align:left;color:inherit;transition:background-color .1s ease;width:100%;justify-content:flex-start}.tree-skill-item[data-v-2adea2d7]:hover{background:#f5f5f5}.tree-skill-item.active[data-v-2adea2d7]{background:#e3f2fd;color:#1976d2;font-weight:500}.empty-tree[data-v-2adea2d7]{display:flex;align-items:center;justify-content:center;height:100px;color:#999;font-size:12px}.app-tree[data-v-450fa8e2]{display:flex;flex-direction:column;overflow-y:auto;font-size:13px;-webkit-user-select:none;user-select:none}.tree-group[data-v-450fa8e2]{border-bottom:1px solid #f0f0f0}.tree-group-header[data-v-450fa8e2]{width:100%;padding:8px 10px;background:#f8f8f8;border:none;border-bottom:1px solid #e8e8e8;font-weight:600;cursor:pointer;display:flex;align-items:center;gap:6px;font-size:12px;text-align:left;justify-content:flex-start;transition:all .15s ease}.tree-group-header[data-v-450fa8e2]:hover{background:#f0f0f0}.tree-group-header.expanded[data-v-450fa8e2]{background:#e8e8e8}.tree-arrow[data-v-450fa8e2]{width:16px;text-align:center;flex-shrink:0;font-size:11px;color:#666}.app-icon[data-v-450fa8e2]{width:16px;text-align:center;flex-shrink:0;font-size:14px}.app-name[data-v-450fa8e2]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.skill-count[data-v-450fa8e2]{margin-left:auto;color:#999;font-size:11px;font-weight:400;flex-shrink:0}.tree-group-items[data-v-450fa8e2]{background:#fafafa;display:flex;flex-direction:column}.skill-tree-item[data-v-450fa8e2]{display:flex;align-items:center;gap:6px;width:100%;padding:6px 16px;border:none;background:transparent;cursor:pointer;font-size:12px;text-align:left;transition:background-color .1s ease;color:inherit;justify-content:flex-start}.skill-tree-item[data-v-450fa8e2]:hover{background:#f0f0f0}.skill-tree-item.active[data-v-450fa8e2]{background:#e3f2fd;color:#1976d2;font-weight:500}.icon[data-v-450fa8e2]{width:16px;text-align:center;flex-shrink:0;font-size:12px}.name[data-v-450fa8e2]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.source-tag[data-v-450fa8e2]{margin-left:4px;padding:1px 4px;background:#f0f0f0;border-radius:2px;font-size:10px;color:#666;flex-shrink:0}.empty-tree[data-v-450fa8e2]{display:flex;align-items:center;justify-content:center;height:100px;color:#999;font-size:12px}:root{font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,PingFang SC,sans-serif;color:#182033;background:#eef1f6;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased}*{box-sizing:border-box}html,body,#app{height:100%;margin:0}button,input{font:inherit}button{cursor:pointer}.shell{height:100vh;display:grid;grid-template-columns:300px 1fr;overflow:hidden}.sidebar{background:#111827;color:#e5e7eb;padding:22px 16px;overflow:auto;border-right:1px solid rgba(255,255,255,.08)}.brand-block{display:flex;align-items:center;gap:12px;margin-bottom:20px}.logo{width:42px;height:42px;border-radius:12px;display:grid;place-items:center;background:linear-gradient(135deg,#7c3aed,#2563eb);font-weight:900;font-size:22px}.brand-block h1{margin:0;font-size:18px}.brand-block p{margin:2px 0 0;color:#9ca3af;font-size:12px}.lang-switch{display:flex;align-items:center;gap:6px;margin:-6px 0 16px;color:#9ca3af;font-size:12px}.lang-switch button{border:1px solid rgba(255,255,255,.12);background:#ffffff0a;color:#d1d5db;border-radius:999px;padding:3px 8px}.lang-switch button.active{background:#eef2ff;color:#3730a3;border-color:#eef2ff}.stats-card{background:#ffffff0f;border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:14px;margin-bottom:18px}.stat-main{font-size:34px;line-height:1;font-weight:800}.stat-label{color:#9ca3af;font-size:12px;margin-bottom:12px}.source-line{display:flex;justify-content:space-between;color:#cbd5e1;font-size:13px;padding:3px 0}.selected-editor-card{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 16px;padding:12px;border:1px solid rgba(167,139,250,.42);background:linear-gradient(135deg,#7c3aed42,#2563eb2e);border-radius:14px;box-shadow:inset 0 1px #ffffff14}.selected-editor-card span{display:block;color:#c4b5fd;font-size:11px;margin-bottom:3px}.selected-editor-card strong{color:#fff;font-size:15px}.selected-editor-card button{width:26px;height:26px;border-radius:999px;border:1px solid rgba(255,255,255,.18);background:#ffffff17;color:#fff;font-size:16px;line-height:1}.filter-section{margin-top:18px}.nav-section{padding-top:4px}.section-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}.section-head h2{margin:0;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:#9ca3af}.section-head small{color:#6b7280;font-size:11px}.scroll-small{max-height:280px;overflow:auto;padding-right:4px}.pill{width:100%;display:flex;align-items:center;justify-content:space-between;gap:8px;padding:9px 11px;margin:5px 0;border:1px solid rgba(255,255,255,.06);border-radius:11px;color:#d1d5db;background:transparent;text-align:left}.pill span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pill b{min-width:28px;text-align:center;color:#9ca3af;font-weight:700;background:#ffffff0f;border-radius:999px;padding:2px 7px}.pill:hover{background:#ffffff14;border-color:#ffffff1f}.pill.active{color:#fff;background:#7c3aed47;border-color:#a78bfa85;box-shadow:0 0 0 2px #7c3aed1f}.pill.active b{color:#ede9fe;background:#ffffff1f}.main{overflow:hidden;display:flex;flex-direction:column;background:#f3f5fa}.topbar{flex:0 0 auto;padding:14px 18px 12px;background:linear-gradient(180deg,#ffffffeb,#f8fafceb);-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border-bottom:1px solid #d9dee8}.toolbar-card{display:grid;gap:10px;padding:12px;background:#ffffffeb;border:1px solid rgba(209,213,219,.78);border-radius:18px;box-shadow:0 10px 30px #0f172a12}.toolbar-main{display:grid;grid-template-columns:minmax(260px,1fr) auto auto;gap:10px;align-items:center}.search-box{min-width:0;display:flex;align-items:center;gap:9px;padding:0 13px;border:1px solid #d4dbe8;border-radius:14px;background:#f8fafc;box-shadow:inset 0 1px #fffc}.search-icon{color:#7c3aed;font-size:18px;line-height:1}.search-box input{width:100%;height:44px;padding:0;border:0;outline:none;background:transparent;color:#111827}.search-box:focus-within{border-color:#8b5cf6;background:#fff;box-shadow:0 0 0 4px #7c3aed1c}.btn{height:44px;border:0;border-radius:14px;padding:0 16px;font-weight:700;color:#374151;background:#eef2ff;transition:transform .12s ease,box-shadow .12s ease,background .12s ease}.btn:hover{transform:translateY(-1px);box-shadow:0 8px 18px #0f172a1a}.btn:disabled{opacity:.58;cursor:wait;transform:none;box-shadow:none}.btn.soft{background:#f1f5f9;color:#475569}.btn.primary{color:#fff;background:linear-gradient(135deg,#7c3aed,#2563eb);box-shadow:0 10px 20px #4f46e52e}.toolbar-facets{display:grid;grid-template-columns:repeat(5,minmax(120px,1fr));gap:8px}.facet{min-width:0;display:flex;align-items:center;gap:8px;padding:7px 9px;border:1px solid #e2e8f0;border-radius:13px;background:#f8fafc}.facet span{flex:0 0 auto;color:#64748b;font-size:11px;font-weight:800;letter-spacing:.04em}.facet select{min-width:0;width:100%;border:0;outline:0;background:transparent;color:#111827;font-size:13px}.facet:focus-within{background:#fff;border-color:#a78bfa;box-shadow:0 0 0 3px #7c3aed1a}.toolbar-status{display:flex;align-items:center;gap:8px;min-width:0;color:#64748b;font-size:12px}.filter-chip{flex:0 0 auto;display:inline-flex;align-items:center;min-height:24px;padding:4px 9px;border-radius:999px;background:#f1f5f9;color:#64748b;font-weight:800}.filter-chip.active{background:#ede9fe;color:#5b21b6}.active-filter{flex:1;min-width:0;color:#64748b;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.active-chip-row{flex:1;min-width:0;display:flex;flex-wrap:wrap;gap:6px;align-items:center}.active-chip{max-width:240px;display:inline-flex;align-items:center;gap:5px;border:0;border-radius:999px;padding:4px 8px;color:#475569;background:#fff;box-shadow:inset 0 0 0 1px #dbe3ef;font-size:12px}.active-chip span{color:#7c3aed;font-weight:800}.active-chip strong{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:700}.active-chip b{color:#94a3b8;font-size:13px}.active-chip:hover{color:#5b21b6;box-shadow:inset 0 0 0 1px #a78bfa;background:#faf5ff}.reload-state{flex:0 0 auto;max-width:190px;color:#94a3b8;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.content{flex:1;min-height:0;display:grid;grid-template-columns:420px 1fr;gap:0}.list-panel{overflow:auto;padding:14px;border-right:1px solid #d9dee8}.list-head{display:flex;gap:10px;align-items:center;justify-content:flex-start;color:#6b7280;margin:0 0 10px 4px}.list-head>div:last-child{margin-left:auto}.list-view-label{font-weight:600;color:#111827;font-size:14px;min-width:60px}.list-head strong{color:#111827;font-size:20px;margin-right:4px}.list-view-controls{display:flex;gap:4px;border:1px solid #d9dee8;background:#fff;border-radius:8px;padding:2px}.view-btn{border:none;background:transparent;color:#6b7280;padding:5px 12px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;transition:all .15s ease}.view-btn:hover{background:#f3f4f6;color:#374151}.view-btn.active{background:#ede9fe;color:#5b21b6}.sort-select{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:#6b7280}.sort-select select{border:1px solid #d4dbe8;border-radius:9px;background:#fff;padding:5px 8px;color:#374151;max-width:118px}.skill-card{width:100%;text-align:left;border:1px solid #d9dee8;background:#fff;border-radius:14px;padding:12px;margin-bottom:10px;transition:.12s ease}.skill-card:hover{border-color:#a78bfa;transform:translateY(-1px)}.skill-card.selected{border-color:#7c3aed;box-shadow:0 0 0 3px #7c3aed1f}.skill-title{display:flex;align-items:center;gap:8px;min-width:0;text-align:left}.skill-title strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.skill-card mark{background:#fef08a;color:#713f12;border-radius:4px;padding:0 2px}.skill-chipline{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px;text-align:left}.skill-chipline span{max-width:160px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:3px 7px;border-radius:999px;background:#f1f5f9;color:#475569;font-size:11px;font-weight:700}.skill-meta{color:#6b7280;font-size:12px;margin-top:6px;text-align:left}.skill-card p{color:#374151;font-size:13px;margin:7px 0 0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.src{display:inline-block;flex:0 0 auto;font-size:10px;line-height:1;padding:4px 7px;border-radius:99px;color:#fff;font-weight:700}.src-hermes{background:#4f46e5}.src-claude-code{background:#d97706}.detail-panel{overflow:auto;padding:22px 28px 80px;background:#f8fafc}.detail-head{display:flex;justify-content:space-between;gap:20px}.detail-kicker{display:flex;align-items:center;flex-wrap:wrap;gap:8px;color:#6b7280;font-size:12px}.detail-head h2{margin:10px 0 6px;font-size:28px;letter-spacing:-.02em}.detail-head p{margin:0;color:#374151;max-width:980px}.badge-row{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 8px}.badge{display:inline-flex;align-items:center;max-width:190px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:4px 8px;border-radius:999px;background:#eef2ff;color:#3730a3;font-size:11px;font-weight:700}.badge.warn{background:#fef3c7;color:#92400e}.badge.danger{background:#fee2e2;color:#991b1b}.actions{display:flex;flex-wrap:wrap;gap:8px;margin:18px 0}.actions button{border:0;background:linear-gradient(180deg,#fff,#f8fafc);color:#334155;border-radius:999px;padding:8px 13px;font-size:13px;font-weight:700;box-shadow:inset 0 0 0 1px #dbe3ef,0 4px 10px #0f172a0a;transition:transform .12s ease,box-shadow .12s ease,color .12s ease}.actions button:hover{transform:translateY(-1px);color:#5b21b6;box-shadow:inset 0 0 0 1px #a78bfa,0 8px 18px #7c3aed1f}.notice{display:inline-block;margin-bottom:12px;padding:8px 10px;background:#dcfce7;border:1px solid #86efac;border-radius:10px;color:#166534;font-size:13px}.usage-card{margin:0 0 18px;padding:16px;border:1px solid #dbe3ef;border-radius:18px;background:linear-gradient(180deg,#fff,#f8fafc);box-shadow:0 10px 26px #0f172a0d}.usage-head{display:flex;justify-content:space-between;align-items:center;gap:14px;margin-bottom:12px}.usage-head span{color:#7c3aed;font-size:11px;font-weight:900;letter-spacing:.09em;text-transform:uppercase}.usage-head h3{margin:2px 0 0;font-size:18px}.usage-head button{border:0;border-radius:999px;padding:8px 12px;color:#fff;background:linear-gradient(135deg,#7c3aed,#2563eb);font-weight:800}.usage-prompt{padding:12px;border-radius:13px;background:#0f172a;color:#dbeafe;overflow:auto}.usage-prompt code{white-space:pre-wrap;word-break:break-word;font-size:12px}.usage-grid{display:grid;grid-template-columns:1.4fr 1fr;gap:12px;margin-top:12px}.usage-grid>div,.usage-block{border:1px solid #eef2f7;border-radius:14px;padding:12px;background:#fff}.usage-card strong{display:block;color:#334155;font-size:12px;margin-bottom:6px}.usage-card p{margin:0;color:#475569;font-size:13px;line-height:1.5}.usage-block{margin-top:10px}.param-table{display:grid;gap:8px}.param-table>div{display:grid;grid-template-columns:minmax(90px,.7fr) minmax(60px,.4fr) auto minmax(160px,1.4fr);gap:8px;align-items:start;font-size:12px}.param-table code{color:#5b21b6;background:#ede9fe;border-radius:6px;padding:2px 6px}.param-table b{color:#991b1b;background:#fee2e2;border-radius:999px;padding:2px 6px;font-size:11px}.param-table p{font-size:12px}.usage-link{display:inline-flex;margin:0 6px 6px 0;padding:4px 8px;border-radius:999px;color:#2563eb;background:#eff6ff;text-decoration:none;font-size:12px}.kv{margin:0 0 18px;background:#fff;border:1px solid #d9dee8;border-radius:14px;padding:10px 14px}.kv div{display:grid;grid-template-columns:90px 1fr;gap:12px;padding:7px 0;border-bottom:1px solid #eef2f7}.kv div:last-child{border-bottom:0}.kv dt{color:#6b7280;font-size:12px;text-transform:uppercase;letter-spacing:.05em}.kv dd{margin:0;min-width:0}.kv-error dt,.kv-error dd{color:#991b1b}.kv code{word-break:break-all;font-size:12px;color:#374151}.tag{display:inline-block;max-width:520px;overflow:hidden;text-overflow:ellipsis;vertical-align:middle;white-space:nowrap;margin:0 5px 5px 0;padding:4px 8px;background:#eef2ff;color:#3730a3;border-radius:999px;font-size:12px}.markdown{background:#fff;border:1px solid #d9dee8;border-radius:14px;padding:20px 24px;line-height:1.68}.markdown h1,.markdown h2,.markdown h3{line-height:1.25;margin-top:1.2em}.markdown h1:first-child,.markdown h2:first-child{margin-top:0}.markdown pre{background:#0f172a;color:#dbeafe;padding:14px;border-radius:12px;overflow:auto}.markdown code{background:#eef2ff;padding:2px 5px;border-radius:5px}.markdown pre code{background:transparent;padding:0}.markdown blockquote{margin:1em 0;padding:.1em 1em;border-left:4px solid #c4b5fd;background:#f5f3ff;color:#4c1d95}.markdown table{border-collapse:collapse;width:100%;overflow:auto}.markdown th,.markdown td{border:1px solid #d9dee8;padding:6px 8px}.error,.loading{margin:16px;padding:12px 14px;border-radius:12px}.error{background:#fee2e2;color:#991b1b}.loading{background:#e0f2fe;color:#075985}@media(max-width:1000px){.shell{grid-template-columns:1fr}.sidebar{display:none}.toolbar-main{grid-template-columns:1fr}.toolbar-facets{grid-template-columns:1fr 1fr}.usage-grid{grid-template-columns:1fr}.param-table>div{grid-template-columns:1fr}.content{grid-template-columns:1fr}.detail-panel{display:none}}