@bytechain.cn/colamd-themes 0.3.2 → 0.5.1

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 (99) hide show
  1. package/.claude/skills/colamd-themes-preview.skill.md +333 -0
  2. package/.claude/skills/colamd-themes.skill.md +10 -0
  3. package/.dsh/skills/colamd-themes/SKILL.md +14 -0
  4. package/.github/supported-topics.yml +17 -0
  5. package/.hermes/skills/tools/colamd-themes/SKILL.md +14 -0
  6. package/.openclaw/skills/colamd-themes/SKILL.md +1 -37
  7. package/.opencode/skills/colamd-themes/SKILL.md +17 -0
  8. package/.trae/rules/colamd-themes.md +0 -36
  9. package/CHANGELOG.md +331 -241
  10. package/DSH_SUPPORT_SUMMARY.md +87 -0
  11. package/README.md +414 -384
  12. package/README_CN.md +412 -384
  13. package/RELEASENOTE.md +541 -389
  14. package/dist/cli.js +36 -55
  15. package/dist/cli.js.map +1 -1
  16. package/dist/color-utils.d.ts +1 -0
  17. package/dist/color-utils.js +25 -6
  18. package/dist/color-utils.js.map +1 -1
  19. package/dist/extractors/pdf-extractor.js +6 -1
  20. package/dist/extractors/pdf-extractor.js.map +1 -1
  21. package/dist/extractors/url-extractor.d.ts +0 -4
  22. package/dist/extractors/url-extractor.js +13 -126
  23. package/dist/extractors/url-extractor.js.map +1 -1
  24. package/dist/generator.d.ts +1 -1
  25. package/dist/generator.js +32 -11
  26. package/dist/generator.js.map +1 -1
  27. package/dist/models.d.ts +5 -4
  28. package/dist/models.js +2 -3
  29. package/dist/models.js.map +1 -1
  30. package/dist/renderer.d.ts +6 -3
  31. package/dist/renderer.js +54 -93
  32. package/dist/renderer.js.map +1 -1
  33. package/dist/templates/template.css +220 -498
  34. package/dist/templates/theme-paradigm.md +530 -658
  35. package/dist/templates/theme-template.hbs +256 -370
  36. package/dist/theme-store.js +19 -3
  37. package/dist/theme-store.js.map +1 -1
  38. package/dist/utils/document-paradigm.d.ts +12 -0
  39. package/dist/utils/document-paradigm.js +109 -0
  40. package/dist/utils/document-paradigm.js.map +1 -0
  41. package/dist/validators.d.ts +4 -1
  42. package/dist/validators.js +115 -1
  43. package/dist/validators.js.map +1 -1
  44. package/mcp-server/dist/index.d.ts +13 -0
  45. package/mcp-server/dist/index.d.ts.map +1 -0
  46. package/mcp-server/dist/index.js +0 -0
  47. package/mcp-server/dist/index.js.map +1 -0
  48. package/mcp-server/package-lock.json +1759 -0
  49. package/mcp-server/package.json +24 -0
  50. package/mcp-server/src/index.ts +0 -0
  51. package/mcp-server/tsconfig.json +19 -0
  52. package/package.json +54 -36
  53. package/skills/build-skills.sh +30 -5
  54. package/skills/colamd-themes/SKILL.md +180 -178
  55. package/src/cli.ts +474 -487
  56. package/src/color-systems.ts +289 -289
  57. package/src/color-utils.ts +137 -120
  58. package/src/contrast.ts +66 -66
  59. package/src/docx-style-paradigm.ts +811 -811
  60. package/src/export-cli.ts +356 -356
  61. package/src/extractors/base.ts +8 -8
  62. package/src/extractors/docx-extractor.ts +417 -417
  63. package/src/extractors/pdf-extractor.ts +533 -527
  64. package/src/extractors/url-extractor.ts +846 -981
  65. package/src/generator.ts +197 -169
  66. package/src/index.ts +29 -29
  67. package/src/models.ts +212 -212
  68. package/src/renderer.ts +310 -359
  69. package/src/templates/template.css +220 -498
  70. package/src/templates/theme-paradigm.md +530 -658
  71. package/src/templates/theme-template.hbs +256 -370
  72. package/src/theme-store.ts +185 -170
  73. package/src/types/pdf-parse.d.ts +12 -12
  74. package/src/utils/cli-utils.ts +84 -84
  75. package/src/utils/document-paradigm.ts +118 -0
  76. package/src/validators.ts +298 -176
  77. package/themes/academic-paper-pt.css +353 -1805
  78. package/themes/academic-paper.css +350 -1099
  79. package/themes/academic-style.css +342 -2430
  80. package/themes/colly.css +256 -370
  81. package/themes/elegant.css +288 -671
  82. package/themes/forest-ink.css +240 -664
  83. package/themes/guizang.css +250 -732
  84. package/themes/hermes-security.css +279 -0
  85. package/themes/meeting-minutes.css +256 -370
  86. package/themes/pixso-design.css +278 -1261
  87. package/themes/salvator-blog.css +256 -370
  88. package/themes/shimo-theme.css +256 -0
  89. package/themes/swiss-design.css +285 -746
  90. package/themes/template.css +220 -498
  91. package/themes/trae-blue.css +280 -737
  92. package/themes/word-contract.css +249 -0
  93. package/themes-preview/demo-content.md +187 -187
  94. package/tsconfig.json +18 -18
  95. package/src/mermaid-presets.ts +0 -142
  96. package/themes/swiss-design copy.css +0 -746
  97. package/themes-preview/colly-preview.html +0 -623
  98. package/themes-preview/meeting-minutes-preview.html +0 -625
  99. package/themes-preview/salvator-blog-preview.html +0 -623
@@ -1,289 +1,289 @@
1
- /**
2
- * Local color system library — predefined seed palettes for popular color schemes.
3
- * Each scheme provides a complete SeedPalette (5 seed colors + variants).
4
- */
5
-
6
- import type { SeedPalette } from "./validators.js";
7
- import { hslHue, hslSaturation, hslLightness } from "./contrast.js";
8
-
9
- export interface ColorSystem {
10
- id: string;
11
- name: string;
12
- nameCN: string;
13
- description: string;
14
- mode: "light" | "dark";
15
- palette: SeedPalette;
16
- }
17
-
18
- // ═══════════════════════════════════════════════════════════
19
- // 莫兰迪 (Morandi) — 低饱和度灰调
20
- // ═══════════════════════════════════════════════════════════
21
-
22
- const morandiPink: ColorSystem = {
23
- id: "morandi-pink",
24
- name: "Morandi Pink",
25
- nameCN: "莫兰迪 灰粉",
26
- description: "低饱和度灰粉基调,柔和慵懒",
27
- mode: "light",
28
- palette: {
29
- accent: "#b08a82", accentLight: "#e8ddd8", accentDark: "#8b6b63",
30
- surface: "#f5f2f0", panel: "#ece6e2", panelAlt: "#e2dad5",
31
- ink: "#3a3533", inkMuted: "#8a807c", inkDim: "#b0a8a4",
32
- border: "#d8d2ce", borderStrong: "#c0b8b4",
33
- },
34
- };
35
-
36
- const morandiGreen: ColorSystem = {
37
- id: "morandi-green",
38
- name: "Morandi Green",
39
- nameCN: "莫兰迪 灰绿",
40
- description: "低饱和度灰绿调,沉静淡雅",
41
- mode: "light",
42
- palette: {
43
- accent: "#8a9b7a", accentLight: "#e2e8dc", accentDark: "#6b7a5e",
44
- surface: "#f4f5f2", panel: "#e8ebe4", panelAlt: "#dce0d5",
45
- ink: "#3a3d35", inkMuted: "#8a8d82", inkDim: "#b0b4a8",
46
- border: "#d4d8ce", borderStrong: "#bcc0b4",
47
- },
48
- };
49
-
50
- const morandiBlue: ColorSystem = {
51
- id: "morandi-blue",
52
- name: "Morandi Blue",
53
- nameCN: "莫兰迪 灰蓝",
54
- description: "低饱和度灰蓝调,冷静克制",
55
- mode: "light",
56
- palette: {
57
- accent: "#7a8fa0", accentLight: "#dce4e8", accentDark: "#5e7080",
58
- surface: "#f2f4f6", panel: "#e6eaee", panelAlt: "#dae0e6",
59
- ink: "#353a3f", inkMuted: "#828a92", inkDim: "#a8b0b8",
60
- border: "#ced4dc", borderStrong: "#b4bcc4",
61
- },
62
- };
63
-
64
- // ═══════════════════════════════════════════════════════════
65
- // 马卡龙 (Macaron) — 粉彩糖果色
66
- // ═══════════════════════════════════════════════════════════
67
-
68
- const macaronStrawberry: ColorSystem = {
69
- id: "macaron-strawberry",
70
- name: "Macaron Strawberry",
71
- nameCN: "马卡龙 草莓",
72
- description: "柔粉奶油色,甜美活泼",
73
- mode: "light",
74
- palette: {
75
- accent: "#e893a6", accentLight: "#fde8ec", accentDark: "#c47082",
76
- surface: "#fefafb", panel: "#faf0f2", panelAlt: "#f4e4e8",
77
- ink: "#4a3035", inkMuted: "#9a8086", inkDim: "#c0a8ae",
78
- border: "#eed4d8", borderStrong: "#dab8be",
79
- },
80
- };
81
-
82
- const macaronMint: ColorSystem = {
83
- id: "macaron-mint",
84
- name: "Macaron Mint",
85
- nameCN: "马卡龙 薄荷",
86
- description: "清新薄荷绿,轻盈爽朗",
87
- mode: "light",
88
- palette: {
89
- accent: "#8cc9a8", accentLight: "#e6f6ee", accentDark: "#6aaa88",
90
- surface: "#f8fcfa", panel: "#eef6f2", panelAlt: "#e2f0e8",
91
- ink: "#304538", inkMuted: "#809588", inkDim: "#a8c0b0",
92
- border: "#cce8d6", borderStrong: "#b0d4bc",
93
- },
94
- };
95
-
96
- const macaronBlueberry: ColorSystem = {
97
- id: "macaron-blueberry",
98
- name: "Macaron Blueberry",
99
- nameCN: "马卡龙 蓝莓",
100
- description: "淡紫蓝调,温柔梦幻",
101
- mode: "light",
102
- palette: {
103
- accent: "#9aa8e0", accentLight: "#eaecf8", accentDark: "#7888c0",
104
- surface: "#f8f8fc", panel: "#f0f2f8", panelAlt: "#e6e8f4",
105
- ink: "#303548", inkMuted: "#808898", inkDim: "#a8b0c0",
106
- border: "#d0d4e8", borderStrong: "#b8bcd4",
107
- },
108
- };
109
-
110
- // ═══════════════════════════════════════════════════════════
111
- // 北欧 (Nordic) — 极简自然色
112
- // ═══════════════════════════════════════════════════════════
113
-
114
- const nordicWood: ColorSystem = {
115
- id: "nordic-wood",
116
- name: "Nordic Wood",
117
- nameCN: "北欧 原木",
118
- description: "浅木色与暖白搭配,自然温馨",
119
- mode: "light",
120
- palette: {
121
- accent: "#8b7355", accentLight: "#e8e0d4", accentDark: "#6b5a40",
122
- surface: "#faf8f4", panel: "#f2eeea", panelAlt: "#e8e2dc",
123
- ink: "#3a3530", inkMuted: "#8a8078", inkDim: "#b0a89e",
124
- border: "#d8d0c4", borderStrong: "#c0b8aa",
125
- },
126
- };
127
-
128
- const nordicMinimal: ColorSystem = {
129
- id: "nordic-minimal",
130
- name: "Nordic Minimal",
131
- nameCN: "北欧 极简白",
132
- description: "纯白基调,冷蓝点缀,极致简洁",
133
- mode: "light",
134
- palette: {
135
- accent: "#4a7c96", accentLight: "#dce6ec", accentDark: "#3a6078",
136
- surface: "#fefefe", panel: "#f6f8fa", panelAlt: "#eef2f6",
137
- ink: "#2a2a2a", inkMuted: "#7a7a7a", inkDim: "#aaaaaa",
138
- border: "#e0e0e0", borderStrong: "#c8c8c8",
139
- },
140
- };
141
-
142
- const nordicGray: ColorSystem = {
143
- id: "nordic-gray",
144
- name: "Nordic Gray",
145
- nameCN: "北欧 灰调",
146
- description: "中灰基调,森林绿点缀,沉稳自然",
147
- mode: "light",
148
- palette: {
149
- accent: "#6b8a7a", accentLight: "#dce6e0", accentDark: "#4e6b5c",
150
- surface: "#f6f5f4", panel: "#edebe8", panelAlt: "#e2e0dc",
151
- ink: "#3a3a3a", inkMuted: "#8a8a8a", inkDim: "#b0b0b0",
152
- border: "#d8d6d2", borderStrong: "#c0beb8",
153
- },
154
- };
155
-
156
- // ═══════════════════════════════════════════════════════════
157
- // 复古 (Vintage) — 暖棕岁月感
158
- // ═══════════════════════════════════════════════════════════
159
-
160
- const vintageWarmBrown: ColorSystem = {
161
- id: "vintage-brown",
162
- name: "Vintage Warm Brown",
163
- nameCN: "复古 暖棕",
164
- description: "暖棕纸色,旧时光氛围",
165
- mode: "light",
166
- palette: {
167
- accent: "#8b5e3c", accentLight: "#e8dcd0", accentDark: "#6b4428",
168
- surface: "#f8f2ea", panel: "#f0e8dc", panelAlt: "#e6dcc8",
169
- ink: "#3a3028", inkMuted: "#8a7a6a", inkDim: "#b0a090",
170
- border: "#d4c8b8", borderStrong: "#bca898",
171
- },
172
- };
173
-
174
- const vintageNewspaper: ColorSystem = {
175
- id: "vintage-newspaper",
176
- name: "Vintage Newspaper",
177
- nameCN: "复古 旧报纸",
178
- description: "泛黄纸色,怀旧阅读感",
179
- mode: "light",
180
- palette: {
181
- accent: "#7a5a3a", accentLight: "#e8dcc8", accentDark: "#5a4028",
182
- surface: "#f4f0e0", panel: "#ece4d0", panelAlt: "#e2d8c0",
183
- ink: "#3a3528", inkMuted: "#8a8070", inkDim: "#b0a898",
184
- border: "#c8c0a8", borderStrong: "#b0a890",
185
- },
186
- };
187
-
188
- const vintageWine: ColorSystem = {
189
- id: "vintage-wine",
190
- name: "Vintage Wine",
191
- nameCN: "复古 酒红",
192
- description: "暗酒红点缀,浓郁优雅",
193
- mode: "light",
194
- palette: {
195
- accent: "#8b3a3a", accentLight: "#e8d4d4", accentDark: "#6b2828",
196
- surface: "#f8f2f2", panel: "#f0e8e8", panelAlt: "#e6dcdc",
197
- ink: "#3a2a2a", inkMuted: "#8a7070", inkDim: "#b09898",
198
- border: "#d4c0c0", borderStrong: "#bca8a8",
199
- },
200
- };
201
-
202
- // ═══════════════════════════════════════════════════════════
203
- // 薄荷绿 (Mint) — 清新自然
204
- // ═══════════════════════════════════════════════════════════
205
-
206
- const mintFresh: ColorSystem = {
207
- id: "mint-fresh",
208
- name: "Mint Fresh",
209
- nameCN: "薄荷绿 清新",
210
- description: "鲜嫩薄荷叶色,清爽宜人",
211
- mode: "light",
212
- palette: {
213
- accent: "#5aaa80", accentLight: "#dceee4", accentDark: "#408860",
214
- surface: "#f8fcfa", panel: "#eef6f2", panelAlt: "#e2f0e8",
215
- ink: "#2a3a30", inkMuted: "#708a78", inkDim: "#98b0a0",
216
- border: "#c8e4d4", borderStrong: "#a8ccb8",
217
- },
218
- };
219
-
220
- const mintDeep: ColorSystem = {
221
- id: "mint-deep",
222
- name: "Mint Deep",
223
- nameCN: "薄荷绿 深薄荷",
224
- description: "深邃薄荷绿,沉稳清新",
225
- mode: "light",
226
- palette: {
227
- accent: "#3a8a60", accentLight: "#d4e8dc", accentDark: "#286a48",
228
- surface: "#f4f8f6", panel: "#e8f0ec", panelAlt: "#dce8e2",
229
- ink: "#283830", inkMuted: "#708878", inkDim: "#98b0a0",
230
- border: "#b8dcc8", borderStrong: "#98c4ac",
231
- },
232
- };
233
-
234
- const mintDew: ColorSystem = {
235
- id: "mint-dew",
236
- name: "Mint Dew",
237
- nameCN: "薄荷绿 晨露",
238
- description: "晨露般清透浅绿,轻柔温和",
239
- mode: "light",
240
- palette: {
241
- accent: "#7ab898", accentLight: "#e0f0e8", accentDark: "#5a9878",
242
- surface: "#fafdfc", panel: "#f2f8f4", panelAlt: "#e8f2ec",
243
- ink: "#2c3832", inkMuted: "#788880", inkDim: "#a0b0a8",
244
- border: "#d0e8dc", borderStrong: "#b8d4c4",
245
- },
246
- };
247
-
248
- // ── Registry ──
249
-
250
- export const COLOR_SYSTEMS: ColorSystem[] = [
251
- morandiPink, morandiGreen, morandiBlue,
252
- macaronStrawberry, macaronMint, macaronBlueberry,
253
- nordicWood, nordicMinimal, nordicGray,
254
- vintageWarmBrown, vintageNewspaper, vintageWine,
255
- mintFresh, mintDeep, mintDew,
256
- ];
257
-
258
- export function getColorSystem(id: string): ColorSystem | undefined {
259
- return COLOR_SYSTEMS.find((cs) => cs.id === id);
260
- }
261
-
262
- /** Match extracted accent/surface to the nearest color system by hue + saturation distance. */
263
- export function matchColorSystem(accent: string, surface: string): ColorSystem {
264
- const hAccent = hslHue(accent);
265
- const sAccent = hslSaturation(accent);
266
- const lSurface = hslLightness(surface);
267
-
268
- let best = COLOR_SYSTEMS[0];
269
- let bestDist = Infinity;
270
-
271
- for (const cs of COLOR_SYSTEMS) {
272
- const hCs = hslHue(cs.palette.accent);
273
- const sCs = hslSaturation(cs.palette.accent);
274
- const lCs = hslLightness(cs.palette.surface);
275
-
276
- // Weighted distance: hue 40%, saturation 30%, lightness 30%
277
- const dH = Math.abs(hAccent - hCs);
278
- const hueDist = Math.min(dH, 360 - dH) / 360; // wrap around
279
- const satDist = Math.abs(sAccent - sCs);
280
- const lumDist = Math.abs(lSurface - lCs);
281
- const dist = hueDist * 0.4 + satDist * 0.3 + lumDist * 0.3;
282
-
283
- if (dist < bestDist) {
284
- bestDist = dist;
285
- best = cs;
286
- }
287
- }
288
- return best;
289
- }
1
+ /**
2
+ * Local color system library — predefined seed palettes for popular color schemes.
3
+ * Each scheme provides a complete SeedPalette (5 seed colors + variants).
4
+ */
5
+
6
+ import type { SeedPalette } from "./validators.js";
7
+ import { hslHue, hslSaturation, hslLightness } from "./contrast.js";
8
+
9
+ export interface ColorSystem {
10
+ id: string;
11
+ name: string;
12
+ nameCN: string;
13
+ description: string;
14
+ mode: "light" | "dark";
15
+ palette: SeedPalette;
16
+ }
17
+
18
+ // ═══════════════════════════════════════════════════════════
19
+ // 莫兰迪 (Morandi) — 低饱和度灰调
20
+ // ═══════════════════════════════════════════════════════════
21
+
22
+ const morandiPink: ColorSystem = {
23
+ id: "morandi-pink",
24
+ name: "Morandi Pink",
25
+ nameCN: "莫兰迪 灰粉",
26
+ description: "低饱和度灰粉基调,柔和慵懒",
27
+ mode: "light",
28
+ palette: {
29
+ accent: "#b08a82", accentLight: "#e8ddd8", accentDark: "#8b6b63",
30
+ surface: "#f5f2f0", panel: "#ece6e2", panelAlt: "#e2dad5",
31
+ ink: "#3a3533", inkMuted: "#8a807c", inkDim: "#b0a8a4",
32
+ border: "#d8d2ce", borderStrong: "#c0b8b4",
33
+ },
34
+ };
35
+
36
+ const morandiGreen: ColorSystem = {
37
+ id: "morandi-green",
38
+ name: "Morandi Green",
39
+ nameCN: "莫兰迪 灰绿",
40
+ description: "低饱和度灰绿调,沉静淡雅",
41
+ mode: "light",
42
+ palette: {
43
+ accent: "#8a9b7a", accentLight: "#e2e8dc", accentDark: "#6b7a5e",
44
+ surface: "#f4f5f2", panel: "#e8ebe4", panelAlt: "#dce0d5",
45
+ ink: "#3a3d35", inkMuted: "#8a8d82", inkDim: "#b0b4a8",
46
+ border: "#d4d8ce", borderStrong: "#bcc0b4",
47
+ },
48
+ };
49
+
50
+ const morandiBlue: ColorSystem = {
51
+ id: "morandi-blue",
52
+ name: "Morandi Blue",
53
+ nameCN: "莫兰迪 灰蓝",
54
+ description: "低饱和度灰蓝调,冷静克制",
55
+ mode: "light",
56
+ palette: {
57
+ accent: "#7a8fa0", accentLight: "#dce4e8", accentDark: "#5e7080",
58
+ surface: "#f2f4f6", panel: "#e6eaee", panelAlt: "#dae0e6",
59
+ ink: "#353a3f", inkMuted: "#828a92", inkDim: "#a8b0b8",
60
+ border: "#ced4dc", borderStrong: "#b4bcc4",
61
+ },
62
+ };
63
+
64
+ // ═══════════════════════════════════════════════════════════
65
+ // 马卡龙 (Macaron) — 粉彩糖果色
66
+ // ═══════════════════════════════════════════════════════════
67
+
68
+ const macaronStrawberry: ColorSystem = {
69
+ id: "macaron-strawberry",
70
+ name: "Macaron Strawberry",
71
+ nameCN: "马卡龙 草莓",
72
+ description: "柔粉奶油色,甜美活泼",
73
+ mode: "light",
74
+ palette: {
75
+ accent: "#e893a6", accentLight: "#fde8ec", accentDark: "#c47082",
76
+ surface: "#fefafb", panel: "#faf0f2", panelAlt: "#f4e4e8",
77
+ ink: "#4a3035", inkMuted: "#9a8086", inkDim: "#c0a8ae",
78
+ border: "#eed4d8", borderStrong: "#dab8be",
79
+ },
80
+ };
81
+
82
+ const macaronMint: ColorSystem = {
83
+ id: "macaron-mint",
84
+ name: "Macaron Mint",
85
+ nameCN: "马卡龙 薄荷",
86
+ description: "清新薄荷绿,轻盈爽朗",
87
+ mode: "light",
88
+ palette: {
89
+ accent: "#8cc9a8", accentLight: "#e6f6ee", accentDark: "#6aaa88",
90
+ surface: "#f8fcfa", panel: "#eef6f2", panelAlt: "#e2f0e8",
91
+ ink: "#304538", inkMuted: "#809588", inkDim: "#a8c0b0",
92
+ border: "#cce8d6", borderStrong: "#b0d4bc",
93
+ },
94
+ };
95
+
96
+ const macaronBlueberry: ColorSystem = {
97
+ id: "macaron-blueberry",
98
+ name: "Macaron Blueberry",
99
+ nameCN: "马卡龙 蓝莓",
100
+ description: "淡紫蓝调,温柔梦幻",
101
+ mode: "light",
102
+ palette: {
103
+ accent: "#9aa8e0", accentLight: "#eaecf8", accentDark: "#7888c0",
104
+ surface: "#f8f8fc", panel: "#f0f2f8", panelAlt: "#e6e8f4",
105
+ ink: "#303548", inkMuted: "#808898", inkDim: "#a8b0c0",
106
+ border: "#d0d4e8", borderStrong: "#b8bcd4",
107
+ },
108
+ };
109
+
110
+ // ═══════════════════════════════════════════════════════════
111
+ // 北欧 (Nordic) — 极简自然色
112
+ // ═══════════════════════════════════════════════════════════
113
+
114
+ const nordicWood: ColorSystem = {
115
+ id: "nordic-wood",
116
+ name: "Nordic Wood",
117
+ nameCN: "北欧 原木",
118
+ description: "浅木色与暖白搭配,自然温馨",
119
+ mode: "light",
120
+ palette: {
121
+ accent: "#8b7355", accentLight: "#e8e0d4", accentDark: "#6b5a40",
122
+ surface: "#faf8f4", panel: "#f2eeea", panelAlt: "#e8e2dc",
123
+ ink: "#3a3530", inkMuted: "#8a8078", inkDim: "#b0a89e",
124
+ border: "#d8d0c4", borderStrong: "#c0b8aa",
125
+ },
126
+ };
127
+
128
+ const nordicMinimal: ColorSystem = {
129
+ id: "nordic-minimal",
130
+ name: "Nordic Minimal",
131
+ nameCN: "北欧 极简白",
132
+ description: "纯白基调,冷蓝点缀,极致简洁",
133
+ mode: "light",
134
+ palette: {
135
+ accent: "#4a7c96", accentLight: "#dce6ec", accentDark: "#3a6078",
136
+ surface: "#fefefe", panel: "#f6f8fa", panelAlt: "#eef2f6",
137
+ ink: "#2a2a2a", inkMuted: "#7a7a7a", inkDim: "#aaaaaa",
138
+ border: "#e0e0e0", borderStrong: "#c8c8c8",
139
+ },
140
+ };
141
+
142
+ const nordicGray: ColorSystem = {
143
+ id: "nordic-gray",
144
+ name: "Nordic Gray",
145
+ nameCN: "北欧 灰调",
146
+ description: "中灰基调,森林绿点缀,沉稳自然",
147
+ mode: "light",
148
+ palette: {
149
+ accent: "#6b8a7a", accentLight: "#dce6e0", accentDark: "#4e6b5c",
150
+ surface: "#f6f5f4", panel: "#edebe8", panelAlt: "#e2e0dc",
151
+ ink: "#3a3a3a", inkMuted: "#8a8a8a", inkDim: "#b0b0b0",
152
+ border: "#d8d6d2", borderStrong: "#c0beb8",
153
+ },
154
+ };
155
+
156
+ // ═══════════════════════════════════════════════════════════
157
+ // 复古 (Vintage) — 暖棕岁月感
158
+ // ═══════════════════════════════════════════════════════════
159
+
160
+ const vintageWarmBrown: ColorSystem = {
161
+ id: "vintage-brown",
162
+ name: "Vintage Warm Brown",
163
+ nameCN: "复古 暖棕",
164
+ description: "暖棕纸色,旧时光氛围",
165
+ mode: "light",
166
+ palette: {
167
+ accent: "#8b5e3c", accentLight: "#e8dcd0", accentDark: "#6b4428",
168
+ surface: "#f8f2ea", panel: "#f0e8dc", panelAlt: "#e6dcc8",
169
+ ink: "#3a3028", inkMuted: "#8a7a6a", inkDim: "#b0a090",
170
+ border: "#d4c8b8", borderStrong: "#bca898",
171
+ },
172
+ };
173
+
174
+ const vintageNewspaper: ColorSystem = {
175
+ id: "vintage-newspaper",
176
+ name: "Vintage Newspaper",
177
+ nameCN: "复古 旧报纸",
178
+ description: "泛黄纸色,怀旧阅读感",
179
+ mode: "light",
180
+ palette: {
181
+ accent: "#7a5a3a", accentLight: "#e8dcc8", accentDark: "#5a4028",
182
+ surface: "#f4f0e0", panel: "#ece4d0", panelAlt: "#e2d8c0",
183
+ ink: "#3a3528", inkMuted: "#8a8070", inkDim: "#b0a898",
184
+ border: "#c8c0a8", borderStrong: "#b0a890",
185
+ },
186
+ };
187
+
188
+ const vintageWine: ColorSystem = {
189
+ id: "vintage-wine",
190
+ name: "Vintage Wine",
191
+ nameCN: "复古 酒红",
192
+ description: "暗酒红点缀,浓郁优雅",
193
+ mode: "light",
194
+ palette: {
195
+ accent: "#8b3a3a", accentLight: "#e8d4d4", accentDark: "#6b2828",
196
+ surface: "#f8f2f2", panel: "#f0e8e8", panelAlt: "#e6dcdc",
197
+ ink: "#3a2a2a", inkMuted: "#8a7070", inkDim: "#b09898",
198
+ border: "#d4c0c0", borderStrong: "#bca8a8",
199
+ },
200
+ };
201
+
202
+ // ═══════════════════════════════════════════════════════════
203
+ // 薄荷绿 (Mint) — 清新自然
204
+ // ═══════════════════════════════════════════════════════════
205
+
206
+ const mintFresh: ColorSystem = {
207
+ id: "mint-fresh",
208
+ name: "Mint Fresh",
209
+ nameCN: "薄荷绿 清新",
210
+ description: "鲜嫩薄荷叶色,清爽宜人",
211
+ mode: "light",
212
+ palette: {
213
+ accent: "#5aaa80", accentLight: "#dceee4", accentDark: "#408860",
214
+ surface: "#f8fcfa", panel: "#eef6f2", panelAlt: "#e2f0e8",
215
+ ink: "#2a3a30", inkMuted: "#708a78", inkDim: "#98b0a0",
216
+ border: "#c8e4d4", borderStrong: "#a8ccb8",
217
+ },
218
+ };
219
+
220
+ const mintDeep: ColorSystem = {
221
+ id: "mint-deep",
222
+ name: "Mint Deep",
223
+ nameCN: "薄荷绿 深薄荷",
224
+ description: "深邃薄荷绿,沉稳清新",
225
+ mode: "light",
226
+ palette: {
227
+ accent: "#3a8a60", accentLight: "#d4e8dc", accentDark: "#286a48",
228
+ surface: "#f4f8f6", panel: "#e8f0ec", panelAlt: "#dce8e2",
229
+ ink: "#283830", inkMuted: "#708878", inkDim: "#98b0a0",
230
+ border: "#b8dcc8", borderStrong: "#98c4ac",
231
+ },
232
+ };
233
+
234
+ const mintDew: ColorSystem = {
235
+ id: "mint-dew",
236
+ name: "Mint Dew",
237
+ nameCN: "薄荷绿 晨露",
238
+ description: "晨露般清透浅绿,轻柔温和",
239
+ mode: "light",
240
+ palette: {
241
+ accent: "#7ab898", accentLight: "#e0f0e8", accentDark: "#5a9878",
242
+ surface: "#fafdfc", panel: "#f2f8f4", panelAlt: "#e8f2ec",
243
+ ink: "#2c3832", inkMuted: "#788880", inkDim: "#a0b0a8",
244
+ border: "#d0e8dc", borderStrong: "#b8d4c4",
245
+ },
246
+ };
247
+
248
+ // ── Registry ──
249
+
250
+ export const COLOR_SYSTEMS: ColorSystem[] = [
251
+ morandiPink, morandiGreen, morandiBlue,
252
+ macaronStrawberry, macaronMint, macaronBlueberry,
253
+ nordicWood, nordicMinimal, nordicGray,
254
+ vintageWarmBrown, vintageNewspaper, vintageWine,
255
+ mintFresh, mintDeep, mintDew,
256
+ ];
257
+
258
+ export function getColorSystem(id: string): ColorSystem | undefined {
259
+ return COLOR_SYSTEMS.find((cs) => cs.id === id);
260
+ }
261
+
262
+ /** Match extracted accent/surface to the nearest color system by hue + saturation distance. */
263
+ export function matchColorSystem(accent: string, surface: string): ColorSystem {
264
+ const hAccent = hslHue(accent);
265
+ const sAccent = hslSaturation(accent);
266
+ const lSurface = hslLightness(surface);
267
+
268
+ let best = COLOR_SYSTEMS[0];
269
+ let bestDist = Infinity;
270
+
271
+ for (const cs of COLOR_SYSTEMS) {
272
+ const hCs = hslHue(cs.palette.accent);
273
+ const sCs = hslSaturation(cs.palette.accent);
274
+ const lCs = hslLightness(cs.palette.surface);
275
+
276
+ // Weighted distance: hue 40%, saturation 30%, lightness 30%
277
+ const dH = Math.abs(hAccent - hCs);
278
+ const hueDist = Math.min(dH, 360 - dH) / 360; // wrap around
279
+ const satDist = Math.abs(sAccent - sCs);
280
+ const lumDist = Math.abs(lSurface - lCs);
281
+ const dist = hueDist * 0.4 + satDist * 0.3 + lumDist * 0.3;
282
+
283
+ if (dist < bestDist) {
284
+ bestDist = dist;
285
+ best = cs;
286
+ }
287
+ }
288
+ return best;
289
+ }