htmlgen-mcp 0.2.0__py3-none-any.whl

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.

Potentially problematic release.


This version of htmlgen-mcp might be problematic. Click here for more details.

@@ -0,0 +1,1473 @@
1
+ """CSS 样式生成相关工具"""
2
+ from __future__ import annotations
3
+
4
+ import json
5
+ from pathlib import Path
6
+
7
+ from .colors import (
8
+ _hex_to_rgb_string,
9
+ _normalize_hex_color,
10
+ _shift_hue,
11
+ _shift_lightness,
12
+ )
13
+
14
+
15
+ def create_css_file(file_path: str, content: str = "", palette: dict | str | None = None):
16
+ """创建CSS文件,包含现代化设计系统,可传入自定义调色板"""
17
+
18
+ palette_dict: dict | None = None
19
+ if palette:
20
+ if isinstance(palette, str):
21
+ try:
22
+ palette_dict = json.loads(palette)
23
+ except json.JSONDecodeError:
24
+ palette_dict = None
25
+ elif isinstance(palette, dict):
26
+ palette_dict = palette
27
+
28
+ primary = _normalize_hex_color(palette_dict["primary"]) if palette_dict and palette_dict.get("primary") else "#0d6efd"
29
+ accent = _normalize_hex_color(palette_dict["accent"]) if palette_dict and palette_dict.get("accent") else _shift_hue(primary, 0.12, 1.05, 0.02)
30
+ secondary = _normalize_hex_color(palette_dict["secondary"]) if palette_dict and palette_dict.get("secondary") else _shift_hue(primary, 0.52, 0.75, 0.04)
31
+ primary_light = _normalize_hex_color(palette_dict["primary_light"]) if palette_dict and palette_dict.get("primary_light") else _shift_lightness(primary, 0.18)
32
+ primary_dark = _normalize_hex_color(palette_dict["primary_dark"]) if palette_dict and palette_dict.get("primary_dark") else _shift_lightness(primary, -0.18)
33
+ accent_light = _normalize_hex_color(palette_dict["accent_light"]) if palette_dict and palette_dict.get("accent_light") else _shift_lightness(accent, 0.15)
34
+ neutral_light = _normalize_hex_color(palette_dict["neutral_light"]) if palette_dict and palette_dict.get("neutral_light") else "#f8f9fa"
35
+ neutral_dark = _normalize_hex_color(palette_dict["neutral_dark"]) if palette_dict and palette_dict.get("neutral_dark") else "#212529"
36
+ dark_primary = _normalize_hex_color(palette_dict["dark_primary"]) if palette_dict and palette_dict.get("dark_primary") else _shift_lightness(primary, -0.1)
37
+ dark_accent = _normalize_hex_color(palette_dict["dark_accent"]) if palette_dict and palette_dict.get("dark_accent") else _shift_lightness(accent, 0.1)
38
+
39
+ support_colors: dict[str, str] = {}
40
+ if isinstance(palette_dict, dict):
41
+ maybe_support = palette_dict.get("support")
42
+ if isinstance(maybe_support, dict):
43
+ support_colors = maybe_support
44
+
45
+ success_color = _normalize_hex_color(support_colors["success"]) if support_colors.get("success") else _shift_hue(primary, 0.33, 0.6, 0.08)
46
+ warning_color = _normalize_hex_color(support_colors["warning"]) if support_colors.get("warning") else _shift_hue(primary, -0.18, 0.55, 0.18)
47
+ danger_color = _normalize_hex_color(support_colors["danger"]) if support_colors.get("danger") else _shift_hue(primary, -0.08, 0.8, -0.22)
48
+ info_color = _normalize_hex_color(support_colors["info"]) if support_colors.get("info") else _shift_hue(primary, 0.18, 0.75, 0.05)
49
+
50
+ palette_block = ""
51
+ if palette_dict:
52
+ palette_block = f"""
53
+ /* 🎨 自定义配色覆盖 */
54
+ :root {{
55
+ --primary: {primary};
56
+ --primary-rgb: {_hex_to_rgb_string(primary)};
57
+ --primary-dark: {primary_dark};
58
+ --primary-light: {primary_light};
59
+ --secondary: {secondary};
60
+ --secondary-rgb: {_hex_to_rgb_string(secondary)};
61
+ --accent: {accent};
62
+ --accent-rgb: {_hex_to_rgb_string(accent)};
63
+ --success: {success_color};
64
+ --warning: {warning_color};
65
+ --danger: {danger_color};
66
+ --info: {info_color};
67
+ --gray-50: {neutral_light};
68
+ --gray-100: {neutral_light};
69
+ --gray-900: {neutral_dark};
70
+ --gradient-primary: linear-gradient(135deg, {primary} 0%, {accent_light} 100%);
71
+ --gradient-secondary: linear-gradient(135deg, {accent} 0%, {primary_light} 100%);
72
+ --gradient-cool: linear-gradient(135deg, {primary} 0%, {accent} 100%);
73
+ --glass-bg: rgba(255, 255, 255, 0.78);
74
+ --glass-border: rgba(255, 255, 255, 0.22);
75
+ }}
76
+
77
+ :root[data-theme='dark'] {{
78
+ --primary: {dark_primary};
79
+ --primary-rgb: {_hex_to_rgb_string(dark_primary)};
80
+ --primary-light: {primary};
81
+ --accent: {dark_accent};
82
+ --accent-rgb: {_hex_to_rgb_string(dark_accent)};
83
+ --gray-50: #0f1115;
84
+ --gray-900: #eef1f6;
85
+ --gradient-primary: linear-gradient(135deg, {dark_primary} 0%, {dark_accent} 100%);
86
+ --gradient-cool: linear-gradient(135deg, {dark_primary} 0%, {accent} 100%);
87
+ --glass-bg: rgba(20, 24, 32, 0.55);
88
+ --glass-border: rgba(255, 255, 255, 0.14);
89
+ }}
90
+ """
91
+
92
+ css_template = f"""/* 🎨 现代化设计系统 - Design System v2.0 */
93
+
94
+ /* ==================== 设计变量系统 ==================== */
95
+ :root {{
96
+ /* 色彩系统 - Color System */
97
+ --primary: #0d6efd;
98
+ --primary-rgb: 13, 110, 253;
99
+ --primary-dark: #0b5ed7;
100
+ --primary-light: #3d8bfd;
101
+ --secondary: #6c757d;
102
+ --secondary-rgb: 108, 117, 125;
103
+ --accent: #6610f2;
104
+ --accent-rgb: 102, 16, 242;
105
+ --success: #198754;
106
+ --warning: #ffc107;
107
+ --danger: #dc3545;
108
+ --info: #0dcaf0;
109
+
110
+ /* 中性色 - Neutral Colors */
111
+ --white: #ffffff;
112
+ --gray-50: #f8f9fa;
113
+ --gray-100: #f1f3f5;
114
+ --gray-200: #e9ecef;
115
+ --gray-300: #dee2e6;
116
+ --gray-400: #ced4da;
117
+ --gray-500: #adb5bd;
118
+ --gray-600: #6c757d;
119
+ --gray-700: #495057;
120
+ --gray-800: #343a40;
121
+ --gray-900: #212529;
122
+ --black: #000000;
123
+
124
+ /* 渐变系统 - Gradients */
125
+ --gradient-primary: linear-gradient(135deg, var(--primary) 0%, #5a8bff 50%, var(--accent) 100%);
126
+ --gradient-secondary: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
127
+ --gradient-success: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
128
+ --gradient-warm: linear-gradient(135deg, #fa709a 0%, #fee140 100%);
129
+ --gradient-cool: linear-gradient(135deg, #30cfd0 0%, #330867 100%);
130
+ --gradient-mesh: radial-gradient(at 40% 20%, hsla(28,100%,74%,1) 0px, transparent 50%),
131
+ radial-gradient(at 80% 0%, hsla(189,100%,56%,1) 0px, transparent 50%),
132
+ radial-gradient(at 0% 50%, hsla(355,100%,93%,1) 0px, transparent 50%);
133
+
134
+ /* 间距系统 - Spacing System */
135
+ --space-xxs: 0.25rem;
136
+ --space-xs: 0.5rem;
137
+ --space-sm: 1rem;
138
+ --space-md: 1.5rem;
139
+ --space-lg: 2rem;
140
+ --space-xl: 3rem;
141
+ --space-xxl: 5rem;
142
+ --space-xxxl: 8rem;
143
+
144
+ /* 字体系统 - Typography System */
145
+ --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue',
146
+ Arial, 'Noto Sans', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
147
+ --font-mono: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, 'Courier New', monospace;
148
+ --font-size-xs: 0.75rem;
149
+ --font-size-sm: 0.875rem;
150
+ --font-size-base: 1rem;
151
+ --font-size-lg: 1.125rem;
152
+ --font-size-xl: 1.25rem;
153
+ --font-size-2xl: 1.5rem;
154
+ --font-size-3xl: 1.875rem;
155
+ --font-size-4xl: 2.25rem;
156
+ --font-size-5xl: 3rem;
157
+ --font-weight-light: 300;
158
+ --font-weight-normal: 400;
159
+ --font-weight-medium: 500;
160
+ --font-weight-semibold: 600;
161
+ --font-weight-bold: 700;
162
+ --line-height-tight: 1.25;
163
+ --line-height-normal: 1.5;
164
+ --line-height-relaxed: 1.75;
165
+
166
+ /* 圆角系统 - Border Radius */
167
+ --radius-sm: 0.25rem;
168
+ --radius-md: 0.5rem;
169
+ --radius-lg: 1rem;
170
+ --radius-xl: 1.5rem;
171
+ --radius-2xl: 2rem;
172
+ --radius-full: 9999px;
173
+
174
+ /* 阴影系统 - Shadow System */
175
+ --shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
176
+ --shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06);
177
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
178
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
179
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
180
+ --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
181
+ --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);
182
+ --shadow-colored: 0 10px 40px -10px rgba(var(--primary-rgb), 0.3);
183
+ --shadow-glass: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
184
+
185
+ /* 动画时长 - Animation Duration */
186
+ --duration-fast: 150ms;
187
+ --duration-base: 250ms;
188
+ --duration-slow: 400ms;
189
+ --duration-slower: 600ms;
190
+
191
+ /* 动画缓动 - Animation Easing */
192
+ --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
193
+ --ease-out: cubic-bezier(0, 0, 0.2, 1);
194
+ --ease-in: cubic-bezier(0.4, 0, 1, 1);
195
+ --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
196
+
197
+ /* 毛玻璃效果 - Glassmorphism */
198
+ --glass-bg: rgba(255, 255, 255, 0.75);
199
+ --glass-border: rgba(255, 255, 255, 0.18);
200
+ --glass-blur: blur(10px);
201
+ --glass-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
202
+ }}
203
+
204
+ /* 暗色主题变量覆盖(高端深色质感) */
205
+ :root[data-theme='dark'] {{
206
+ --white: #0f1115;
207
+ --gray-50: #0f1115;
208
+ --gray-100: #12151c;
209
+ --gray-200: #161a22;
210
+ --gray-300: #1b202a;
211
+ --gray-400: #242b38;
212
+ --gray-500: #5a667a;
213
+ --gray-600: #7e8aa3;
214
+ --gray-700: #a5b1c7;
215
+ --gray-800: #d2d7e1;
216
+ --gray-900: #eef1f6;
217
+ --black: #ffffff;
218
+
219
+ --primary: #5a8bff;
220
+ --primary-rgb: 90, 139, 255;
221
+ --primary-dark: #3c66d7;
222
+ --primary-light: #8bb0ff;
223
+ --accent: #8b5cf6;
224
+ --accent-rgb: 139, 92, 246;
225
+ --gradient-primary: linear-gradient(135deg, #3b82f6 0%, #8b5cf6 100%);
226
+ --gradient-mesh: radial-gradient(at 30% 20%, rgba(99,102,241,.35) 0px, transparent 50%),
227
+ radial-gradient(at 80% 10%, rgba(56,189,248,.25) 0px, transparent 50%),
228
+ radial-gradient(at 10% 60%, rgba(139,92,246,.25) 0px, transparent 50%);
229
+
230
+ --glass-bg: rgba(20, 24, 32, 0.55);
231
+ --glass-border: rgba(255, 255, 255, 0.08);
232
+ --glass-blur: blur(12px);
233
+ --glass-shadow: 0 8px 32px rgba(0,0,0,.45);
234
+ }}
235
+
236
+ {palette_block}
237
+
238
+ /* ==================== 基础重置 ==================== */
239
+ *, *::before, *::after {{
240
+ box-sizing: border-box;
241
+ margin: 0;
242
+ padding: 0;
243
+ }}
244
+
245
+ html {{
246
+ scroll-behavior: smooth;
247
+ font-size: 16px;
248
+ -webkit-text-size-adjust: 100%;
249
+ }}
250
+
251
+ body {{
252
+ font-family: var(--font-sans);
253
+ font-size: var(--font-size-base);
254
+ line-height: var(--line-height-relaxed);
255
+ color: var(--gray-900);
256
+ background: var(--gray-50);
257
+ -webkit-font-smoothing: antialiased;
258
+ -moz-osx-font-smoothing: grayscale;
259
+ overflow-x: hidden;
260
+ position: relative;
261
+ }}
262
+
263
+ /* 响应式字体大小 */
264
+ @media (max-width: 768px) {{
265
+ html {{ font-size: 14px; }}
266
+ }}
267
+
268
+ /* ==================== 媒体元素 ==================== */
269
+ img, picture, video, canvas, svg {{
270
+ display: block;
271
+ max-width: 100%;
272
+ height: auto;
273
+ }}
274
+
275
+ img {{
276
+ object-fit: cover;
277
+ font-style: italic;
278
+ }}
279
+
280
+ /* 图片加载优化 */
281
+ img[loading="lazy"] {{
282
+ background: linear-gradient(135deg, var(--gray-100) 0%, var(--gray-200) 100%);
283
+ }}
284
+
285
+ /* ==================== 布局系统 ==================== */
286
+ .section {{
287
+ padding: var(--space-xxl) 0;
288
+ position: relative;
289
+ overflow: hidden;
290
+ }}
291
+
292
+ .section-sm {{
293
+ padding: var(--space-xl) 0;
294
+ }}
295
+
296
+ .section-lg {{
297
+ padding: var(--space-xxxl) 0;
298
+ }}
299
+
300
+ /* 标题系统 */
301
+ .section-title {{
302
+ font-size: clamp(var(--font-size-2xl), 5vw, var(--font-size-4xl));
303
+ font-weight: var(--font-weight-bold);
304
+ line-height: var(--line-height-tight);
305
+ margin-bottom: var(--space-md);
306
+ background: var(--gradient-primary);
307
+ -webkit-background-clip: text;
308
+ -webkit-text-fill-color: transparent;
309
+ background-clip: text;
310
+ text-align: center;
311
+ }}
312
+
313
+ .section-lead {{
314
+ font-size: var(--font-size-lg);
315
+ color: var(--gray-600);
316
+ max-width: 720px;
317
+ margin: 0 auto var(--space-xl);
318
+ text-align: center;
319
+ line-height: var(--line-height-relaxed);
320
+ }}
321
+
322
+ /* 容器系统 */
323
+ .container {{
324
+ width: 100%;
325
+ max-width: 1200px;
326
+ margin: 0 auto;
327
+ padding: 0 var(--space-md);
328
+ }}
329
+
330
+ @media (min-width: 768px) {{
331
+ .container {{
332
+ padding: 0 var(--space-lg);
333
+ }}
334
+ }}
335
+
336
+ /* ==================== Hero 区域 ==================== */
337
+ .hero {{
338
+ position: relative;
339
+ min-height: 100vh;
340
+ display: flex;
341
+ align-items: center;
342
+ justify-content: center;
343
+ background: var(--gradient-primary);
344
+ color: var(--white);
345
+ overflow: hidden;
346
+ }}
347
+
348
+ /* 动态背景效果 */
349
+ .hero::before {{
350
+ content: '';
351
+ position: absolute;
352
+ top: -50%;
353
+ left: -50%;
354
+ width: 200%;
355
+ height: 200%;
356
+ background: var(--gradient-mesh);
357
+ opacity: 0.3;
358
+ animation: heroFloat 20s ease-in-out infinite;
359
+ }}
360
+
361
+ @keyframes heroFloat {{
362
+ 0%, 100% {{ transform: rotate(0deg) scale(1); }}
363
+ 33% {{ transform: rotate(10deg) scale(1.1); }}
364
+ 66% {{ transform: rotate(-10deg) scale(0.95); }}
365
+ }}
366
+
367
+ .hero-inner {{
368
+ position: relative;
369
+ z-index: 1;
370
+ padding: var(--space-xxl) 0;
371
+ text-align: center;
372
+ }}
373
+
374
+ .hero h1 {{
375
+ font-size: clamp(var(--font-size-3xl), 7vw, var(--font-size-5xl));
376
+ font-weight: var(--font-weight-bold);
377
+ margin-bottom: var(--space-md);
378
+ animation: fadeInUp 0.8s ease-out;
379
+ }}
380
+
381
+ .hero .lead {{
382
+ font-size: clamp(var(--font-size-lg), 3vw, var(--font-size-xl));
383
+ opacity: 0.9;
384
+ max-width: 600px;
385
+ margin: 0 auto var(--space-lg);
386
+ animation: fadeInUp 0.8s ease-out 0.2s both;
387
+ }}
388
+
389
+ /* 波浪分割 */
390
+ .shape-bottom {{
391
+ position: absolute;
392
+ left: 0;
393
+ right: 0;
394
+ bottom: -1px;
395
+ line-height: 0;
396
+ z-index: 1;
397
+ }}
398
+
399
+ .shape-bottom svg {{
400
+ display: block;
401
+ width: calc(100% + 1.3px);
402
+ height: clamp(30px, 10vw, 120px);
403
+ }}
404
+
405
+ /* ==================== 扩展风格布局 ==================== */
406
+ .badge-soft {{
407
+ display: inline-flex;
408
+ align-items: center;
409
+ justify-content: center;
410
+ padding: 0.4rem 1rem;
411
+ border-radius: var(--radius-full);
412
+ background: rgba(var(--primary-rgb), 0.12);
413
+ color: var(--primary);
414
+ font-weight: var(--font-weight-medium);
415
+ letter-spacing: 0.08em;
416
+ text-transform: uppercase;
417
+ }}
418
+
419
+ .hero-floating {{
420
+ position: absolute;
421
+ inset: -10%;
422
+ pointer-events: none;
423
+ overflow: hidden;
424
+ }}
425
+
426
+ .floating-shape {{
427
+ position: absolute;
428
+ border-radius: 50%;
429
+ width: clamp(180px, 22vw, 320px);
430
+ height: clamp(180px, 22vw, 320px);
431
+ background: var(--gradient-primary);
432
+ filter: blur(50px);
433
+ opacity: 0.35;
434
+ animation: float-large 12s ease-in-out infinite;
435
+ }}
436
+
437
+ .floating-shape.shape-one {{ top: 10%; left: -4%; }}
438
+ .floating-shape.shape-two {{ bottom: -6%; right: -2%; animation-delay: 4s; }}
439
+
440
+ @keyframes float-large {{
441
+ 0%, 100% {{ transform: translate3d(0, 0, 0) scale(1); }}
442
+ 50% {{ transform: translate3d(20px, -20px, 0) scale(1.05); }}
443
+ }}
444
+
445
+ [data-parallax] {{
446
+ --parallax-offset: 0px;
447
+ will-change: transform;
448
+ }}
449
+
450
+ [data-parallax]:not([data-tilt]) {{
451
+ transform: translate3d(0, var(--parallax-offset), 0);
452
+ }}
453
+
454
+ [data-tilt] {{
455
+ --tilt-rotate-x: 0deg;
456
+ --tilt-rotate-y: 0deg;
457
+ --tilt-translate-z: 0px;
458
+ transform-style: preserve-3d;
459
+ transition: transform var(--duration-base) var(--ease-out);
460
+ will-change: transform;
461
+ transform: translate3d(0, var(--parallax-offset, 0px), 0) rotateX(var(--tilt-rotate-x)) rotateY(var(--tilt-rotate-y)) translateZ(var(--tilt-translate-z));
462
+ }}
463
+
464
+ .marquee-clients {{
465
+ gap: clamp(1.5rem, 4vw, 3rem) !important;
466
+ font-size: 1.05rem;
467
+ letter-spacing: 0.18em;
468
+ text-transform: uppercase;
469
+ }}
470
+
471
+ .form-floating-cards {{
472
+ background: rgba(var(--primary-rgb), 0.04);
473
+ border-radius: var(--radius-2xl);
474
+ padding: var(--space-xl);
475
+ backdrop-filter: blur(14px);
476
+ -webkit-backdrop-filter: blur(14px);
477
+ border: 1px solid rgba(var(--primary-rgb), 0.08);
478
+ }}
479
+
480
+ .hero-minimal {{
481
+ min-height: 100vh;
482
+ display: flex;
483
+ align-items: center;
484
+ background: radial-gradient(circle at 0 0, rgba(var(--primary-rgb), 0.14) 0%, transparent 55%),
485
+ radial-gradient(circle at 100% 100%, rgba(var(--accent-rgb), 0.18) 0%, transparent 45%),
486
+ var(--gradient-primary);
487
+ color: var(--white);
488
+ position: relative;
489
+ overflow: hidden;
490
+ }}
491
+
492
+ .hero-minimal .container {{ position: relative; z-index: 2; }}
493
+
494
+ .minimal-grid {{
495
+ display: grid;
496
+ grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
497
+ gap: clamp(2rem, 6vw, 6rem);
498
+ align-items: center;
499
+ }}
500
+
501
+ .hero-minimal__content {{
502
+ text-align: left;
503
+ color: rgba(255, 255, 255, 0.92);
504
+ max-width: 540px;
505
+ }}
506
+
507
+ .hero-minimal__content .display-4 {{
508
+ font-weight: var(--font-weight-semibold);
509
+ letter-spacing: -0.01em;
510
+ margin-bottom: var(--space-md);
511
+ }}
512
+
513
+ .hero-minimal__cta {{
514
+ display: flex;
515
+ gap: var(--space-sm);
516
+ flex-wrap: wrap;
517
+ }}
518
+
519
+ .tagline {{
520
+ display: inline-block;
521
+ font-size: var(--font-size-sm);
522
+ letter-spacing: 0.22em;
523
+ text-transform: uppercase;
524
+ opacity: 0.7;
525
+ margin-bottom: var(--space-xs);
526
+ }}
527
+
528
+ .hero-minimal__gallery {{
529
+ display: grid;
530
+ grid-template-columns: repeat(2, minmax(0, 1fr));
531
+ gap: var(--space-md);
532
+ }}
533
+
534
+ .hero-minimal__gallery .gallery-card {{
535
+ aspect-ratio: 4 / 3;
536
+ border-radius: var(--radius-2xl);
537
+ background: rgba(255, 255, 255, 0.15);
538
+ overflow: hidden;
539
+ position: relative;
540
+ box-shadow: var(--shadow-xl);
541
+ }}
542
+
543
+ .hero-minimal__gallery .gallery-card::after {{
544
+ content: '';
545
+ position: absolute;
546
+ inset: 0;
547
+ background: linear-gradient(180deg, transparent, rgba(0,0,0,0.45));
548
+ }}
549
+
550
+ .hero-minimal__gallery .gallery-card.tall {{ grid-row: span 2; aspect-ratio: 3 / 5; }}
551
+
552
+ .section-alt {{
553
+ background: var(--gray-50);
554
+ color: var(--gray-900);
555
+ padding-top: var(--space-xxl);
556
+ padding-bottom: var(--space-xxl);
557
+ }}
558
+
559
+ :root[data-theme='dark'] .section-alt {{
560
+ background: rgba(18, 22, 30, 0.75);
561
+ color: var(--gray-100);
562
+ }}
563
+
564
+ .section-heading {{
565
+ display: flex;
566
+ flex-direction: column;
567
+ gap: var(--space-xs);
568
+ margin-bottom: var(--space-xl);
569
+ max-width: 720px;
570
+ }}
571
+
572
+ .section-heading .eyebrow {{
573
+ font-size: var(--font-size-sm);
574
+ letter-spacing: 0.24em;
575
+ text-transform: uppercase;
576
+ color: rgba(var(--primary-rgb), 0.65);
577
+ }}
578
+
579
+ .brand-grid {{
580
+ display: grid;
581
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
582
+ gap: var(--space-lg);
583
+ text-align: center;
584
+ font-weight: var(--font-weight-semibold);
585
+ letter-spacing: 0.12em;
586
+ text-transform: uppercase;
587
+ opacity: 0.7;
588
+ }}
589
+
590
+ .service-columns {{
591
+ display: grid;
592
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
593
+ gap: var(--space-lg);
594
+ }}
595
+
596
+ .service-card {{
597
+ padding: var(--space-xl);
598
+ border-radius: var(--radius-2xl);
599
+ background: var(--white);
600
+ border: 1px solid rgba(0,0,0,0.05);
601
+ box-shadow: var(--shadow-sm);
602
+ }}
603
+
604
+ :root[data-theme='dark'] .service-card {{
605
+ background: rgba(20, 24, 32, 0.9);
606
+ border-color: rgba(255,255,255,0.06);
607
+ }}
608
+
609
+ .case-grid {{
610
+ display: grid;
611
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
612
+ gap: var(--space-lg);
613
+ }}
614
+
615
+ .case-card {{
616
+ border-radius: var(--radius-2xl);
617
+ overflow: hidden;
618
+ background: var(--white);
619
+ box-shadow: var(--shadow-xl);
620
+ display: grid;
621
+ grid-template-rows: auto 1fr;
622
+ }}
623
+
624
+ .case-card.tall {{ grid-row: span 2; }}
625
+
626
+ .case-image {{
627
+ aspect-ratio: 4 / 3;
628
+ background: rgba(var(--primary-rgb), 0.12);
629
+ }}
630
+
631
+ .case-meta {{
632
+ padding: var(--space-lg);
633
+ }}
634
+
635
+ .testimonial-spotlight {{
636
+ display: grid;
637
+ gap: var(--space-xl);
638
+ grid-template-columns: minmax(0, 1fr) minmax(0, 420px);
639
+ align-items: center;
640
+ }}
641
+
642
+ .testimonial-copy blockquote {{
643
+ font-size: var(--font-size-xl);
644
+ line-height: 1.75;
645
+ margin: var(--space-md) 0;
646
+ }}
647
+
648
+ .testimonial-portrait {{
649
+ aspect-ratio: 3 / 4;
650
+ border-radius: var(--radius-2xl);
651
+ overflow: hidden;
652
+ box-shadow: var(--shadow-2xl);
653
+ }}
654
+
655
+ .pricing-stack {{
656
+ display: grid;
657
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
658
+ gap: var(--space-lg);
659
+ }}
660
+
661
+ .pricing-card {{
662
+ background: var(--white);
663
+ border-radius: var(--radius-2xl);
664
+ padding: var(--space-xl);
665
+ box-shadow: var(--shadow-md);
666
+ border: 1px solid rgba(0,0,0,0.04);
667
+ }}
668
+
669
+ .pricing-card.featured {{
670
+ background: var(--gradient-primary);
671
+ color: var(--white);
672
+ box-shadow: var(--shadow-xl);
673
+ }}
674
+
675
+ .pricing-card ul {{
676
+ list-style: none;
677
+ margin: var(--space-md) 0 0;
678
+ padding: 0;
679
+ }}
680
+
681
+ .pricing-card li {{
682
+ margin-bottom: var(--space-xs);
683
+ opacity: 0.8;
684
+ }}
685
+
686
+ .faq-accordion details {{
687
+ border-bottom: 1px solid rgba(0,0,0,0.1);
688
+ padding: var(--space-md) 0;
689
+ }}
690
+
691
+ .faq-accordion summary {{
692
+ font-weight: var(--font-weight-semibold);
693
+ cursor: pointer;
694
+ }}
695
+
696
+ .contact-intro {{
697
+ max-width: 520px;
698
+ margin-bottom: var(--space-lg);
699
+ }}
700
+
701
+ .contact-form {{
702
+ display: grid;
703
+ gap: var(--space-md);
704
+ background: var(--white);
705
+ border-radius: var(--radius-xl);
706
+ padding: var(--space-xl);
707
+ box-shadow: var(--shadow-lg);
708
+ }}
709
+
710
+ .contact-form .field-pair {{
711
+ display: flex;
712
+ flex-direction: column;
713
+ gap: var(--space-xs);
714
+ }}
715
+
716
+ .footer-minimal {{
717
+ background: var(--gray-900);
718
+ color: var(--white);
719
+ padding: var(--space-xl) 0;
720
+ }}
721
+
722
+ .footer-minimal .container {{
723
+ display: flex;
724
+ align-items: center;
725
+ justify-content: space-between;
726
+ gap: var(--space-lg);
727
+ }}
728
+
729
+ .footer-minimal .footer-brand {{
730
+ display: flex;
731
+ flex-direction: column;
732
+ gap: 0.4rem;
733
+ font-size: var(--font-size-lg);
734
+ }}
735
+
736
+ .footer-minimal .footer-meta {{
737
+ display: flex;
738
+ align-items: center;
739
+ gap: var(--space-sm);
740
+ opacity: 0.7;
741
+ }}
742
+
743
+ .hero-creative {{
744
+ position: relative;
745
+ min-height: 90vh;
746
+ color: var(--white);
747
+ background: radial-gradient(circle at 20% 20%, rgba(255,255,255,0.18), transparent 55%),
748
+ radial-gradient(circle at 80% 0%, rgba(255,255,255,0.18), transparent 45%),
749
+ var(--gradient-cool);
750
+ overflow: hidden;
751
+ }}
752
+
753
+ .hero-noise {{
754
+ position: absolute;
755
+ inset: 0;
756
+ opacity: 0.15;
757
+ }}
758
+
759
+ .hero-creative__orbit {{
760
+ position: absolute;
761
+ inset: 0;
762
+ display: flex;
763
+ align-items: center;
764
+ justify-content: center;
765
+ pointer-events: none;
766
+ }}
767
+
768
+ .orbit {{
769
+ position: absolute;
770
+ border-radius: 50%;
771
+ border: 1px solid rgba(255,255,255,0.35);
772
+ animation: orbit-rotate 24s linear infinite;
773
+ }}
774
+
775
+ .orbit-primary {{ width: 60vw; height: 60vw; }}
776
+ .orbit-accent {{ width: 40vw; height: 40vw; animation-duration: 18s; }}
777
+
778
+ @keyframes orbit-rotate {{
779
+ 0% {{ transform: rotate(0deg); }}
780
+ 100% {{ transform: rotate(360deg); }}
781
+ }}
782
+
783
+ .timeline {{
784
+ display: grid;
785
+ gap: var(--space-lg);
786
+ position: relative;
787
+ padding-left: 1.5rem;
788
+ }}
789
+
790
+ .timeline::before {{
791
+ content: '';
792
+ position: absolute;
793
+ left: 0.4rem;
794
+ top: 0;
795
+ bottom: 0;
796
+ width: 2px;
797
+ background: linear-gradient(180deg, rgba(var(--primary-rgb), 0.2), rgba(var(--accent-rgb), 0.4));
798
+ }}
799
+
800
+ .timeline-item {{
801
+ display: grid;
802
+ gap: var(--space-xs);
803
+ grid-template-columns: auto minmax(0, 1fr);
804
+ align-items: start;
805
+ }}
806
+
807
+ .timeline-dot {{
808
+ width: 14px;
809
+ height: 14px;
810
+ border-radius: 50%;
811
+ background: var(--primary);
812
+ margin-top: 6px;
813
+ box-shadow: 0 0 0 6px rgba(var(--primary-rgb), 0.15);
814
+ }}
815
+
816
+ .ability-grid {{
817
+ display: grid;
818
+ grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
819
+ gap: var(--space-lg);
820
+ }}
821
+
822
+ .ability-card {{
823
+ padding: var(--space-xl);
824
+ border-radius: var(--radius-2xl);
825
+ color: var(--white);
826
+ position: relative;
827
+ overflow: hidden;
828
+ min-height: 320px;
829
+ }}
830
+
831
+ .ability-card::after {{
832
+ content: '';
833
+ position: absolute;
834
+ inset: 0;
835
+ background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.55) 100%);
836
+ }}
837
+
838
+ .ability-card h3,
839
+ .ability-card p {{
840
+ position: relative;
841
+ z-index: 2;
842
+ }}
843
+
844
+ .nebula-grid {{
845
+ display: grid;
846
+ gap: var(--space-lg);
847
+ grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
848
+ }}
849
+
850
+ .nebula-card {{
851
+ padding: var(--space-lg);
852
+ border-radius: var(--radius-2xl);
853
+ background: rgba(255,255,255,0.08);
854
+ backdrop-filter: blur(18px);
855
+ -webkit-backdrop-filter: blur(18px);
856
+ border: 1px solid rgba(255,255,255,0.12);
857
+ box-shadow: var(--glass-shadow);
858
+ }}
859
+
860
+ .nebula-card__media {{
861
+ border-radius: var(--radius-xl);
862
+ aspect-ratio: 16 / 10;
863
+ margin-bottom: var(--space-md);
864
+ background: rgba(255,255,255,0.18);
865
+ }}
866
+
867
+ .gradient-panels {{
868
+ display: grid;
869
+ gap: var(--space-lg);
870
+ grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
871
+ }}
872
+
873
+ .panel-card {{
874
+ padding: var(--space-xl);
875
+ border-radius: var(--radius-2xl);
876
+ background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.12), rgba(var(--accent-rgb), 0.2));
877
+ color: var(--gray-900);
878
+ min-height: 220px;
879
+ }}
880
+
881
+ .pricing-orbits {{
882
+ display: grid;
883
+ gap: var(--space-lg);
884
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
885
+ }}
886
+
887
+ .orbit-card {{
888
+ border-radius: var(--radius-2xl);
889
+ padding: var(--space-xl);
890
+ background: rgba(255,255,255,0.08);
891
+ border: 1px solid rgba(255,255,255,0.12);
892
+ backdrop-filter: blur(16px);
893
+ -webkit-backdrop-filter: blur(16px);
894
+ color: var(--white);
895
+ }}
896
+
897
+ .orbit-card ul {{
898
+ list-style: none;
899
+ margin: var(--space-md) 0 0;
900
+ padding: 0;
901
+ opacity: 0.8;
902
+ }}
903
+
904
+ .contact-capsule {{
905
+ padding: var(--space-xxl) var(--space-xl);
906
+ border-radius: var(--radius-2xl);
907
+ background: linear-gradient(135deg, rgba(var(--primary-rgb), 0.3), rgba(var(--accent-rgb), 0.3));
908
+ color: var(--white);
909
+ box-shadow: var(--shadow-2xl);
910
+ position: relative;
911
+ overflow: hidden;
912
+ }}
913
+
914
+ .capsule-form {{
915
+ display: grid;
916
+ gap: var(--space-sm);
917
+ margin-top: var(--space-lg);
918
+ }}
919
+
920
+ .capsule-form input,
921
+ .capsule-form textarea {{
922
+ background: rgba(255,255,255,0.12);
923
+ border: 1px solid rgba(255,255,255,0.2);
924
+ color: var(--white);
925
+ }}
926
+
927
+ .footer-creative {{
928
+ background: radial-gradient(circle at top, rgba(var(--primary-rgb), 0.18), transparent 70%), #040510;
929
+ color: rgba(255,255,255,0.85);
930
+ padding: var(--space-xl) 0;
931
+ }}
932
+
933
+ .footer-creative .container {{
934
+ display: flex;
935
+ align-items: center;
936
+ justify-content: space-between;
937
+ gap: var(--space-lg);
938
+ }}
939
+
940
+ .footer-creative__links {{
941
+ display: flex;
942
+ gap: var(--space-md);
943
+ }}
944
+
945
+ .footer-creative__links a {{
946
+ color: inherit;
947
+ text-decoration: none;
948
+ opacity: 0.7;
949
+ }}
950
+
951
+ .footer-creative__links a:hover {{
952
+ opacity: 1;
953
+ }}
954
+
955
+ @media (max-width: 991px) {{
956
+ .minimal-grid {{ grid-template-columns: 1fr; }}
957
+ .hero-minimal__content {{ text-align: center; margin: 0 auto; }}
958
+ .hero-minimal__cta {{ justify-content: center; }}
959
+ .hero-minimal__gallery {{ grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }}
960
+ .testimonial-spotlight {{ grid-template-columns: 1fr; }}
961
+ .footer-minimal .container,
962
+ .footer-creative .container {{ flex-direction: column; text-align: center; }}
963
+ }}
964
+
965
+ /* ==================== 玻璃态导航 ==================== */
966
+ .navbar-glass {{
967
+ position: sticky;
968
+ top: 0;
969
+ z-index: 1000;
970
+ background: linear-gradient(to bottom, rgba(255,255,255,0.72), rgba(255,255,255,0.42));
971
+ backdrop-filter: blur(12px);
972
+ -webkit-backdrop-filter: blur(12px);
973
+ border-bottom: 1px solid rgba(255,255,255,0.25);
974
+ transition: all var(--duration-base) var(--ease-out);
975
+ }}
976
+
977
+ :root[data-theme='dark'] .navbar-glass {{
978
+ background: linear-gradient(to bottom, rgba(16,18,24,0.65), rgba(16,18,24,0.35));
979
+ border-bottom-color: rgba(255,255,255,0.06);
980
+ }}
981
+
982
+ .navbar-glass.scrolled {{
983
+ box-shadow: 0 10px 30px -10px rgba(0,0,0,.2);
984
+ background: linear-gradient(to bottom, rgba(255,255,255,0.82), rgba(255,255,255,0.52));
985
+ }}
986
+
987
+ :root[data-theme='dark'] .navbar-glass.scrolled {{
988
+ background: linear-gradient(to bottom, rgba(16,18,24,0.75), rgba(16,18,24,0.45));
989
+ }}
990
+
991
+ .navbar-brand {{
992
+ font-weight: 700;
993
+ letter-spacing: .2px;
994
+ }}
995
+
996
+ .theme-toggle-btn {{
997
+ border: 2px solid var(--gray-300);
998
+ background: transparent;
999
+ color: var(--gray-900);
1000
+ border-radius: var(--radius-full);
1001
+ padding: .4rem .8rem;
1002
+ }}
1003
+
1004
+ :root[data-theme='dark'] .theme-toggle-btn {{
1005
+ color: var(--gray-800);
1006
+ border-color: var(--gray-400);
1007
+ }}
1008
+
1009
+ /* ==================== 卡片系统 ==================== */
1010
+ .feature-card {{
1011
+ background: var(--white);
1012
+ border-radius: var(--radius-xl);
1013
+ padding: var(--space-lg);
1014
+ height: 100%;
1015
+ position: relative;
1016
+ overflow: hidden;
1017
+ transition: all var(--duration-base) var(--ease-out);
1018
+ box-shadow: var(--shadow-sm);
1019
+ --card-translate-y: 0px;
1020
+ --card-scale: 1;
1021
+ transform: translate3d(0, var(--parallax-offset, 0px), 0)
1022
+ translateY(var(--card-translate-y))
1023
+ scale(var(--card-scale))
1024
+ rotateX(var(--tilt-rotate-x, 0deg))
1025
+ rotateY(var(--tilt-rotate-y, 0deg))
1026
+ translateZ(var(--tilt-translate-z, 0px));
1027
+ transform-style: preserve-3d;
1028
+ }}
1029
+
1030
+ /* 新拟态效果 */
1031
+ .feature-card.neumorphic {{
1032
+ background: linear-gradient(145deg, #f0f0f0, #ffffff);
1033
+ box-shadow: 20px 20px 60px #d9d9d9, -20px -20px 60px #ffffff;
1034
+ }}
1035
+
1036
+ /* 毛玻璃效果 */
1037
+ .feature-card.glass {{
1038
+ background: var(--glass-bg);
1039
+ backdrop-filter: var(--glass-blur);
1040
+ -webkit-backdrop-filter: var(--glass-blur);
1041
+ border: 1px solid var(--glass-border);
1042
+ box-shadow: var(--glass-shadow);
1043
+ }}
1044
+
1045
+ .feature-card:hover {{
1046
+ --card-translate-y: -8px;
1047
+ --card-scale: 1.02;
1048
+ box-shadow: var(--shadow-2xl);
1049
+ }}
1050
+
1051
+ /* 卡片悬停光效 */
1052
+ .feature-card::before {{
1053
+ content: '';
1054
+ position: absolute;
1055
+ top: 0;
1056
+ left: -100%;
1057
+ width: 100%;
1058
+ height: 100%;
1059
+ background: linear-gradient(90deg, transparent, rgba(var(--primary-rgb), 0.1), transparent);
1060
+ transition: left var(--duration-slow) var(--ease-out);
1061
+ }}
1062
+
1063
+ .feature-card:hover::before {{
1064
+ left: 100%;
1065
+ }}
1066
+
1067
+ /* 图标系统 */
1068
+ .feature-icon {{
1069
+ width: 60px;
1070
+ height: 60px;
1071
+ border-radius: var(--radius-lg);
1072
+ display: inline-flex;
1073
+ align-items: center;
1074
+ justify-content: center;
1075
+ background: var(--gradient-primary);
1076
+ color: var(--white);
1077
+ font-size: 24px;
1078
+ margin-bottom: var(--space-md);
1079
+ position: relative;
1080
+ overflow: hidden;
1081
+ box-shadow: var(--shadow-colored);
1082
+ }}
1083
+
1084
+ .feature-icon::after {{
1085
+ content: '';
1086
+ position: absolute;
1087
+ top: 50%;
1088
+ left: 50%;
1089
+ width: 100%;
1090
+ height: 100%;
1091
+ background: radial-gradient(circle, rgba(255,255,255,0.3) 0%, transparent 70%);
1092
+ transform: translate(-50%, -50%) scale(0);
1093
+ transition: transform var(--duration-base) var(--ease-out);
1094
+ }}
1095
+
1096
+ .feature-card:hover .feature-icon::after {{
1097
+ transform: translate(-50%, -50%) scale(2);
1098
+ }}
1099
+
1100
+ .feature-card h3 {{
1101
+ font-size: var(--font-size-xl);
1102
+ font-weight: var(--font-weight-semibold);
1103
+ margin-bottom: var(--space-sm);
1104
+ color: var(--gray-900);
1105
+ }}
1106
+
1107
+ .feature-card p {{
1108
+ font-size: var(--font-size-base);
1109
+ color: var(--gray-600);
1110
+ line-height: var(--line-height-relaxed);
1111
+ }}
1112
+
1113
+ /* ==================== CTA 区域 ==================== */
1114
+ .cta {{
1115
+ background: var(--gradient-primary);
1116
+ color: var(--white);
1117
+ border-radius: var(--radius-2xl);
1118
+ padding: var(--space-xxl) var(--space-xl);
1119
+ text-align: center;
1120
+ position: relative;
1121
+ overflow: hidden;
1122
+ box-shadow: var(--shadow-xl);
1123
+ }}
1124
+
1125
+ /* 动态背景粒子 */
1126
+ .cta::before,
1127
+ .cta::after {{
1128
+ content: '';
1129
+ position: absolute;
1130
+ border-radius: 50%;
1131
+ background: rgba(255, 255, 255, 0.1);
1132
+ animation: float 6s ease-in-out infinite;
1133
+ }}
1134
+
1135
+ .cta::before {{
1136
+ width: 100px;
1137
+ height: 100px;
1138
+ top: -50px;
1139
+ left: -50px;
1140
+ }}
1141
+
1142
+ .cta::after {{
1143
+ width: 150px;
1144
+ height: 150px;
1145
+ bottom: -75px;
1146
+ right: -75px;
1147
+ animation-delay: 3s;
1148
+ }}
1149
+
1150
+ @keyframes float {{
1151
+ 0%, 100% {{ transform: translateY(0) rotate(0deg); }}
1152
+ 50% {{ transform: translateY(-20px) rotate(180deg); }}
1153
+ }}
1154
+
1155
+ .cta h2 {{
1156
+ font-size: var(--font-size-3xl);
1157
+ margin-bottom: var(--space-md);
1158
+ position: relative;
1159
+ z-index: 1;
1160
+ }}
1161
+
1162
+ .cta p {{
1163
+ font-size: var(--font-size-lg);
1164
+ margin-bottom: var(--space-lg);
1165
+ opacity: 0.95;
1166
+ position: relative;
1167
+ z-index: 1;
1168
+ }}
1169
+
1170
+ /* ==================== 表单样式 ==================== */
1171
+ .form-control {{
1172
+ width: 100%;
1173
+ padding: var(--space-sm) var(--space-md);
1174
+ font-size: var(--font-size-base);
1175
+ line-height: var(--line-height-normal);
1176
+ color: var(--gray-900);
1177
+ background: var(--white);
1178
+ border: 2px solid var(--gray-200);
1179
+ border-radius: var(--radius-lg);
1180
+ transition: all var(--duration-base) var(--ease-out);
1181
+ }}
1182
+
1183
+ .form-control:hover {{
1184
+ border-color: var(--gray-300);
1185
+ }}
1186
+
1187
+ .form-control:focus {{
1188
+ outline: none;
1189
+ border-color: var(--primary);
1190
+ box-shadow: 0 0 0 3px rgba(var(--primary-rgb), 0.1);
1191
+ }}
1192
+
1193
+ .form-control::placeholder {{
1194
+ color: var(--gray-500);
1195
+ }}
1196
+
1197
+ /* 表单标签 */
1198
+ .form-label {{
1199
+ display: block;
1200
+ margin-bottom: var(--space-xs);
1201
+ font-size: var(--font-size-sm);
1202
+ font-weight: var(--font-weight-medium);
1203
+ color: var(--gray-700);
1204
+ text-transform: uppercase;
1205
+ letter-spacing: 0.05em;
1206
+ }}
1207
+
1208
+ /* ==================== 动画系统 ==================== */
1209
+ /* 滚动显示动画 */
1210
+ .reveal {{
1211
+ opacity: 0;
1212
+ transform: translateY(30px);
1213
+ transition: all var(--duration-slower) var(--ease-out);
1214
+ }}
1215
+
1216
+ .reveal.revealed {{
1217
+ opacity: 1;
1218
+ transform: translateY(0);
1219
+ }}
1220
+
1221
+ /* 渐入动画变体 */
1222
+ .fade-in-up {{
1223
+ animation: fadeInUp 0.8s ease-out both;
1224
+ }}
1225
+
1226
+ .fade-in-left {{
1227
+ animation: fadeInLeft 0.8s ease-out both;
1228
+ }}
1229
+
1230
+ .fade-in-right {{
1231
+ animation: fadeInRight 0.8s ease-out both;
1232
+ }}
1233
+
1234
+ .fade-in-scale {{
1235
+ animation: fadeInScale 0.8s ease-out both;
1236
+ }}
1237
+
1238
+ @keyframes fadeInUp {{
1239
+ from {{
1240
+ opacity: 0;
1241
+ transform: translateY(30px);
1242
+ }}
1243
+ to {{
1244
+ opacity: 1;
1245
+ transform: translateY(0);
1246
+ }}
1247
+ }}
1248
+
1249
+ @keyframes fadeInLeft {{
1250
+ from {{
1251
+ opacity: 0;
1252
+ transform: translateX(-30px);
1253
+ }}
1254
+ to {{
1255
+ opacity: 1;
1256
+ transform: translateX(0);
1257
+ }}
1258
+ }}
1259
+
1260
+ @keyframes fadeInRight {{
1261
+ from {{
1262
+ opacity: 0;
1263
+ transform: translateX(30px);
1264
+ }}
1265
+ to {{
1266
+ opacity: 1;
1267
+ transform: translateX(0);
1268
+ }}
1269
+ }}
1270
+
1271
+ @keyframes fadeInScale {{
1272
+ from {{
1273
+ opacity: 0;
1274
+ transform: scale(0.9);
1275
+ }}
1276
+ to {{
1277
+ opacity: 1;
1278
+ transform: scale(1);
1279
+ }}
1280
+ }}
1281
+
1282
+ /* 打字机效果 */
1283
+ .typewriter {{
1284
+ overflow: hidden;
1285
+ border-right: 3px solid var(--primary);
1286
+ white-space: nowrap;
1287
+ animation: typewriter 3s steps(40, end), blink 0.75s step-end infinite;
1288
+ }}
1289
+
1290
+ @keyframes typewriter {{
1291
+ from {{ width: 0; }}
1292
+ to {{ width: 100%; }}
1293
+ }}
1294
+
1295
+ @keyframes blink {{
1296
+ from, to {{ border-color: transparent; }}
1297
+ 50% {{ border-color: var(--primary); }}
1298
+ }}
1299
+
1300
+ /* 脉冲动画 */
1301
+ .pulse {{
1302
+ animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
1303
+ }}
1304
+
1305
+ @keyframes pulse {{
1306
+ 0%, 100% {{ opacity: 1; }}
1307
+ 50% {{ opacity: 0.5; }}
1308
+ }}
1309
+
1310
+ /* 弹跳动画 */
1311
+ .bounce {{
1312
+ animation: bounce 1s infinite;
1313
+ }}
1314
+
1315
+ @keyframes bounce {{
1316
+ 0%, 100% {{
1317
+ transform: translateY(-25%);
1318
+ animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
1319
+ }}
1320
+ 50% {{
1321
+ transform: translateY(0);
1322
+ animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
1323
+ }}
1324
+ }}
1325
+
1326
+ /* ==================== 按钮系统 ==================== */
1327
+ .btn {{
1328
+ display: inline-flex;
1329
+ align-items: center;
1330
+ justify-content: center;
1331
+ padding: var(--space-sm) var(--space-lg);
1332
+ font-size: var(--font-size-base);
1333
+ font-weight: var(--font-weight-medium);
1334
+ line-height: var(--line-height-normal);
1335
+ border-radius: var(--radius-lg);
1336
+ border: none;
1337
+ cursor: pointer;
1338
+ transition: all var(--duration-base) var(--ease-out);
1339
+ position: relative;
1340
+ overflow: hidden;
1341
+ text-decoration: none;
1342
+ white-space: nowrap;
1343
+ }}
1344
+
1345
+ /* 主按钮 */
1346
+ .btn-primary {{
1347
+ background: var(--gradient-primary);
1348
+ color: var(--white);
1349
+ box-shadow: var(--shadow-colored);
1350
+ }}
1351
+
1352
+ .btn-primary:hover {{
1353
+ transform: translateY(-2px);
1354
+ box-shadow: 0 15px 40px -5px rgba(var(--primary-rgb), 0.4);
1355
+ }}
1356
+
1357
+ .btn-primary:active {{
1358
+ transform: translateY(0);
1359
+ }}
1360
+
1361
+ /* 次要按钮 */
1362
+ .btn-secondary {{
1363
+ background: var(--white);
1364
+ color: var(--gray-900);
1365
+ border: 2px solid var(--gray-200);
1366
+ box-shadow: var(--shadow-sm);
1367
+ }}
1368
+
1369
+ .btn-secondary:hover {{
1370
+ background: var(--gray-50);
1371
+ border-color: var(--gray-300);
1372
+ transform: translateY(-2px);
1373
+ box-shadow: var(--shadow-md);
1374
+ }}
1375
+
1376
+ /* 大按钮 */
1377
+ .btn-lg {{
1378
+ padding: var(--space-md) var(--space-xl);
1379
+ font-size: var(--font-size-lg);
1380
+ border-radius: var(--radius-xl);
1381
+ }}
1382
+
1383
+ /* 按钮涟漪效果 */
1384
+ .btn::before {{
1385
+ content: '';
1386
+ position: absolute;
1387
+ top: 50%;
1388
+ left: 50%;
1389
+ width: 0;
1390
+ height: 0;
1391
+ border-radius: 50%;
1392
+ background: rgba(255, 255, 255, 0.5);
1393
+ transform: translate(-50%, -50%);
1394
+ transition: width 0.6s, height 0.6s;
1395
+ }}
1396
+
1397
+ .btn:active::before {{
1398
+ width: 300px;
1399
+ height: 300px;
1400
+ }}
1401
+
1402
+ /* ==================== 工具类 ==================== */
1403
+ .text-center {{ text-align: center !important; }}
1404
+ .text-left {{ text-align: left !important; }}
1405
+ .text-right {{ text-align: right !important; }}
1406
+
1407
+ .text-primary {{ color: var(--primary) !important; }}
1408
+ .text-secondary {{ color: var(--secondary) !important; }}
1409
+ .text-muted {{ color: var(--gray-600) !important; }}
1410
+
1411
+ .bg-primary {{ background-color: var(--primary) !important; }}
1412
+ .bg-secondary {{ background-color: var(--secondary) !important; }}
1413
+ .bg-light {{ background-color: var(--gray-50) !important; }}
1414
+ .bg-dark {{ background-color: var(--gray-900) !important; }}
1415
+
1416
+ .img-fluid {{ max-width: 100%; height: auto; }}
1417
+
1418
+ .mt-1 {{ margin-top: var(--space-xs) !important; }}
1419
+ .mt-2 {{ margin-top: var(--space-sm) !important; }}
1420
+ .mt-3 {{ margin-top: var(--space-md) !important; }}
1421
+ .mt-4 {{ margin-top: var(--space-lg) !important; }}
1422
+ .mt-5 {{ margin-top: var(--space-xl) !important; }}
1423
+
1424
+ .mb-1 {{ margin-bottom: var(--space-xs) !important; }}
1425
+ .mb-2 {{ margin-bottom: var(--space-sm) !important; }}
1426
+ .mb-3 {{ margin-bottom: var(--space-md) !important; }}
1427
+ .mb-4 {{ margin-bottom: var(--space-lg) !important; }}
1428
+ .mb-5 {{ margin-bottom: var(--space-xl) !important; }}
1429
+
1430
+ .py-3 {{ padding-top: var(--space-md) !important; padding-bottom: var(--space-md) !important; }}
1431
+ .py-4 {{ padding-top: var(--space-lg) !important; padding-bottom: var(--space-lg) !important; }}
1432
+ .py-5 {{ padding-top: var(--space-xl) !important; padding-bottom: var(--space-xl) !important; }}
1433
+
1434
+ /* ==================== 响应式网格 ==================== */
1435
+ .row {{
1436
+ display: flex;
1437
+ flex-wrap: wrap;
1438
+ margin: 0 calc(var(--space-md) * -1);
1439
+ }}
1440
+
1441
+ .col {{
1442
+ flex: 1;
1443
+ padding: 0 var(--space-md);
1444
+ }}
1445
+
1446
+ .col-12 {{ flex: 0 0 100%; max-width: 100%; }}
1447
+ .col-md-6 {{ flex: 0 0 100%; max-width: 100%; }}
1448
+ .col-md-4 {{ flex: 0 0 100%; max-width: 100%; }}
1449
+ .col-md-3 {{ flex: 0 0 100%; max-width: 100%; }}
1450
+
1451
+ @media (min-width: 768px) {{
1452
+ .col-md-6 {{ flex: 0 0 50%; max-width: 50%; }}
1453
+ .col-md-4 {{ flex: 0 0 33.333333%; max-width: 33.333333%; }}
1454
+ .col-md-3 {{ flex: 0 0 25%; max-width: 25%; }}
1455
+ }}
1456
+
1457
+ .g-4 > * {{ padding: var(--space-md); }}
1458
+
1459
+ {content}
1460
+ """
1461
+
1462
+ try:
1463
+ # 确保父目录存在
1464
+ Path(file_path).parent.mkdir(parents=True, exist_ok=True)
1465
+ with open(file_path, "w", encoding="utf-8") as f:
1466
+ f.write(css_template)
1467
+ return f"CSS文件创建成功: {file_path}"
1468
+ except Exception as e:
1469
+ raise RuntimeError(f"创建CSS文件失败: {str(e)}")
1470
+
1471
+
1472
+
1473
+ __all__ = ["create_css_file"]