@zhang_jifan/fanui 2.1.0

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 (127) hide show
  1. package/ACCESSIBILITY.md +61 -0
  2. package/CHANGELOG.md +112 -0
  3. package/COMMERCIAL-LICENSE.md +71 -0
  4. package/DESIGN-SYSTEM.md +294 -0
  5. package/LICENSE +661 -0
  6. package/README.md +348 -0
  7. package/USAGE.md +1926 -0
  8. package/_index.scss +20 -0
  9. package/dist/fanui.cjs +15 -0
  10. package/dist/fanui.css +28209 -0
  11. package/dist/fanui.d.ts +353 -0
  12. package/dist/fanui.esm.js +71 -0
  13. package/dist/fanui.js +4782 -0
  14. package/dist/fanui.min.css +1 -0
  15. package/dist/fanui.mjs +71 -0
  16. package/dist/modules/fanui-advanced.css +830 -0
  17. package/dist/modules/fanui-advanced.min.css +129 -0
  18. package/dist/modules/fanui-alert.css +575 -0
  19. package/dist/modules/fanui-alert.min.css +122 -0
  20. package/dist/modules/fanui-badge.css +426 -0
  21. package/dist/modules/fanui-badge.min.css +77 -0
  22. package/dist/modules/fanui-base.css +1394 -0
  23. package/dist/modules/fanui-base.min.css +236 -0
  24. package/dist/modules/fanui-blog.css +762 -0
  25. package/dist/modules/fanui-blog.min.css +108 -0
  26. package/dist/modules/fanui-button.css +526 -0
  27. package/dist/modules/fanui-button.min.css +56 -0
  28. package/dist/modules/fanui-card.css +291 -0
  29. package/dist/modules/fanui-card.min.css +52 -0
  30. package/dist/modules/fanui-choice.css +539 -0
  31. package/dist/modules/fanui-choice.min.css +83 -0
  32. package/dist/modules/fanui-dashboard.css +1057 -0
  33. package/dist/modules/fanui-dashboard.min.css +160 -0
  34. package/dist/modules/fanui-data.css +687 -0
  35. package/dist/modules/fanui-data.min.css +125 -0
  36. package/dist/modules/fanui-feedback.css +432 -0
  37. package/dist/modules/fanui-feedback.min.css +79 -0
  38. package/dist/modules/fanui-form.css +779 -0
  39. package/dist/modules/fanui-form.min.css +123 -0
  40. package/dist/modules/fanui-glass.css +497 -0
  41. package/dist/modules/fanui-glass.min.css +46 -0
  42. package/dist/modules/fanui-input-plus.css +799 -0
  43. package/dist/modules/fanui-input-plus.min.css +124 -0
  44. package/dist/modules/fanui-interactive.css +960 -0
  45. package/dist/modules/fanui-interactive.min.css +138 -0
  46. package/dist/modules/fanui-layout.css +4399 -0
  47. package/dist/modules/fanui-layout.min.css +1172 -0
  48. package/dist/modules/fanui-marketing.css +1125 -0
  49. package/dist/modules/fanui-marketing.min.css +144 -0
  50. package/dist/modules/fanui-nav.css +458 -0
  51. package/dist/modules/fanui-nav.min.css +76 -0
  52. package/dist/modules/fanui-overlay.css +547 -0
  53. package/dist/modules/fanui-overlay.min.css +91 -0
  54. package/dist/modules/fanui-table.css +290 -0
  55. package/dist/modules/fanui-table.min.css +62 -0
  56. package/dist/modules/fanui-tabs.css +333 -0
  57. package/dist/modules/fanui-tabs.min.css +58 -0
  58. package/dist/modules/fanui-themes.css +2728 -0
  59. package/dist/modules/fanui-themes.min.css +40 -0
  60. package/dist/modules/fanui-tokens.css +587 -0
  61. package/dist/modules/fanui-tokens.min.css +3 -0
  62. package/dist/modules/fanui-utilities.css +6557 -0
  63. package/dist/modules/fanui-utilities.min.css +1762 -0
  64. package/dist/modules/sizes.json +103 -0
  65. package/docs/MIGRATION-v2.md +179 -0
  66. package/examples/01-script-tag.html +149 -0
  67. package/examples/02-react/README.md +39 -0
  68. package/examples/02-react/index.html +12 -0
  69. package/examples/02-react/package.json +20 -0
  70. package/examples/02-react/src/App.jsx +108 -0
  71. package/examples/02-react/src/main.jsx +13 -0
  72. package/examples/02-react/src/useFanUI.js +87 -0
  73. package/examples/02-react/vite.config.js +6 -0
  74. package/examples/03-vue3/README.md +67 -0
  75. package/examples/03-vue3/index.html +12 -0
  76. package/examples/03-vue3/package.json +19 -0
  77. package/examples/03-vue3/src/App.vue +93 -0
  78. package/examples/03-vue3/src/main.js +8 -0
  79. package/examples/03-vue3/src/useFanUI.js +85 -0
  80. package/examples/03-vue3/vite.config.js +6 -0
  81. package/examples/04-vue2-cdn.html +93 -0
  82. package/examples/README.md +34 -0
  83. package/package.json +127 -0
  84. package/src/_functions.scss +319 -0
  85. package/src/_mixins.scss +1202 -0
  86. package/src/_tokens.scss +180 -0
  87. package/src/_variables.scss +491 -0
  88. package/src/base/_animations.scss +210 -0
  89. package/src/base/_reset.scss +359 -0
  90. package/src/base/_rtl.scss +133 -0
  91. package/src/base/_typography.scss +353 -0
  92. package/src/components/_advanced.scss +763 -0
  93. package/src/components/_alert.scss +322 -0
  94. package/src/components/_badge.scss +279 -0
  95. package/src/components/_blog.scss +693 -0
  96. package/src/components/_button.scss +351 -0
  97. package/src/components/_capabilities.scss +463 -0
  98. package/src/components/_card.scss +281 -0
  99. package/src/components/_choice.scss +444 -0
  100. package/src/components/_dashboard.scss +950 -0
  101. package/src/components/_data.scss +618 -0
  102. package/src/components/_feedback.scss +403 -0
  103. package/src/components/_form.scss +408 -0
  104. package/src/components/_glass.scss +374 -0
  105. package/src/components/_input-plus.scss +730 -0
  106. package/src/components/_interactive.scss +885 -0
  107. package/src/components/_marketing.scss +982 -0
  108. package/src/components/_nav.scss +480 -0
  109. package/src/components/_overlay.scss +517 -0
  110. package/src/components/_table.scss +276 -0
  111. package/src/components/_tabs.scss +338 -0
  112. package/src/fanui.d.ts +353 -0
  113. package/src/fanui.js +4782 -0
  114. package/src/fanui.scss +79 -0
  115. package/src/glass/_switches.scss +36 -0
  116. package/src/glass/_tokens.scss +259 -0
  117. package/src/layout/_container.scss +111 -0
  118. package/src/layout/_flex.scss +164 -0
  119. package/src/layout/_grid.scss +180 -0
  120. package/src/themes/_accents.scss +201 -0
  121. package/src/themes/_palettes.scss +180 -0
  122. package/src/utilities/_borders.scss +104 -0
  123. package/src/utilities/_display.scss +145 -0
  124. package/src/utilities/_effects.scss +210 -0
  125. package/src/utilities/_sizing.scss +123 -0
  126. package/src/utilities/_spacing.scss +118 -0
  127. package/src/utilities/_texture.scss +323 -0
@@ -0,0 +1,982 @@
1
+ // =============================================================================
2
+ // fanUI · 官网 / 落地页组件 (Marketing)
3
+ // -----------------------------------------------------------------------------
4
+ // 面向企业官网、产品落地页、SaaS 首页的成套版式组件。
5
+ // 全部基于同一套主题色令牌与液态玻璃令牌,因此:
6
+ // · 换主题色 → 渐变、光斑、按钮、图表一起变
7
+ // · 关液态玻璃 → 所有玻璃卡片自动退回实体表面
8
+ //
9
+ // .fanui-announcement 顶部公告条
10
+ // .fanui-hero 首屏(极光背景 + 渐变标题 + 双 CTA + 信任背书)
11
+ // .fanui-section-head 区块标题组
12
+ // .fanui-feature 特性卡
13
+ // .fanui-bento Bento 网格
14
+ // .fanui-flow 三步/多步流程
15
+ // .fanui-marquee Logo 无缝滚动
16
+ // .fanui-stat-band 数据带(常用于"客户成果")
17
+ // .fanui-pricing 价格表(月付/年付切换)
18
+ // .fanui-testimonial 客户证言
19
+ // .fanui-cta 行动号召区块
20
+ // .fanui-faq 常见问题(原生 details 驱动,无 JS 可用)
21
+ // .fanui-footer 页脚(多列 + 订阅)
22
+ // =============================================================================
23
+
24
+ @use "sass:map";
25
+ @use "../functions" as fn;
26
+ @use "../variables" as v;
27
+ @use "../mixins" as mx;
28
+
29
+ // -----------------------------------------------------------------------------
30
+ // 1. 顶部公告条
31
+ // -----------------------------------------------------------------------------
32
+
33
+ .fanui-announcement {
34
+ display: flex;
35
+ align-items: center;
36
+ justify-content: center;
37
+ gap: fn.fanui-var("space-3");
38
+ padding: fn.fanui-var("space-2") fn.fanui-var("space-4");
39
+ font-size: fn.fanui-var("font-size-sm");
40
+ color: fn.fanui-var("primary-fg");
41
+ background-image: var(--fanui-brand-grad);
42
+ text-align: center;
43
+
44
+ a {
45
+ color: inherit;
46
+ text-decoration: underline;
47
+ text-underline-offset: 2px;
48
+ }
49
+
50
+ &__badge {
51
+ padding: 1px 8px;
52
+ font-size: fn.fanui-var("font-size-xs");
53
+ font-weight: fn.fanui-var("font-weight-semibold");
54
+ border-radius: fn.fanui-var("radius-full");
55
+ background-color: fn.fanui-alpha(#ffffff, 0.22);
56
+ color: #ffffff;
57
+ }
58
+
59
+ &__close {
60
+ margin-inline-start: fn.fanui-var("space-2");
61
+ border: 0;
62
+ background: transparent;
63
+ color: inherit;
64
+ opacity: 0.7;
65
+ cursor: pointer;
66
+
67
+ &:hover { opacity: 1; }
68
+ }
69
+
70
+ &--soft {
71
+ background-image: none;
72
+ background-color: fn.fanui-var("primary-soft");
73
+ color: fn.fanui-var("primary-ink");
74
+
75
+ .fanui-announcement__badge { background-color: fn.fanui-alpha(#ffffff, 0.7); color: fn.fanui-var("primary-ink"); }
76
+ }
77
+ }
78
+
79
+ // -----------------------------------------------------------------------------
80
+ // 2. 首屏 Hero
81
+ // -----------------------------------------------------------------------------
82
+
83
+ .fanui-hero {
84
+ position: relative;
85
+ isolation: isolate;
86
+ overflow: hidden;
87
+ padding-block: fn.fanui-var("space-24") fn.fanui-var("space-20");
88
+ text-align: center;
89
+
90
+ // 极光背景:两团品牌色光斑 + 网格
91
+ &__aurora {
92
+ position: absolute;
93
+ inset: -20% -10% auto -10%;
94
+ height: 140%;
95
+ z-index: -2;
96
+ pointer-events: none;
97
+ background:
98
+ radial-gradient(42% 46% at 24% 26%, var(--fanui-brand-aura-a), transparent 62%),
99
+ radial-gradient(38% 42% at 76% 22%, var(--fanui-brand-aura-b), transparent 60%),
100
+ radial-gradient(52% 48% at 50% 84%, fn.fanui-var("primary-soft"), transparent 68%);
101
+ filter: blur(28px);
102
+ opacity: 0.9;
103
+ }
104
+
105
+ &__grid {
106
+ position: absolute;
107
+ inset: 0;
108
+ z-index: -1;
109
+ pointer-events: none;
110
+ background-image:
111
+ linear-gradient(fn.fanui-alpha(#64748b, 0.10) 1px, transparent 1px),
112
+ linear-gradient(90deg, fn.fanui-alpha(#64748b, 0.10) 1px, transparent 1px);
113
+ background-size: 56px 56px;
114
+ -webkit-mask-image: radial-gradient(70% 60% at 50% 30%, #000 0%, transparent 100%);
115
+ mask-image: radial-gradient(70% 60% at 50% 30%, #000 0%, transparent 100%);
116
+ }
117
+
118
+ &__inner {
119
+ position: relative;
120
+ display: flex;
121
+ flex-direction: column;
122
+ align-items: center;
123
+ gap: fn.fanui-var("space-5");
124
+ max-width: 820px;
125
+ margin-inline: auto;
126
+ }
127
+
128
+ &__eyebrow {
129
+ display: inline-flex;
130
+ align-items: center;
131
+ gap: fn.fanui-var("space-2");
132
+ padding: 5px 12px 5px 6px;
133
+ font-size: fn.fanui-var("font-size-sm");
134
+ color: fn.fanui-var("color-text-muted");
135
+ border-radius: fn.fanui-var("radius-full");
136
+ @include mx.fanui-liquid-glass();
137
+ --fanui-glass-radius: 9999px;
138
+ --fanui-glass-intensity: 0.6;
139
+ }
140
+
141
+ &__eyebrow-tag {
142
+ padding: 1px 8px;
143
+ font-size: fn.fanui-var("font-size-xs");
144
+ font-weight: fn.fanui-var("font-weight-semibold");
145
+ color: fn.fanui-var("primary-fg");
146
+ background-color: fn.fanui-var("primary");
147
+ border-radius: fn.fanui-var("radius-full");
148
+ }
149
+
150
+ &__title {
151
+ margin: 0;
152
+ font-size: clamp(2.25rem, 5.2vw, 4rem);
153
+ font-weight: fn.fanui-var("font-weight-extrabold");
154
+ line-height: 1.1;
155
+ letter-spacing: fn.fanui-var("tracking-tight");
156
+ color: fn.fanui-var("color-text-strong");
157
+ text-wrap: balance;
158
+
159
+ em {
160
+ font-style: normal;
161
+ @include mx.fanui-text-gradient(var(--fanui-brand-grad-a), var(--fanui-brand-grad-b), 100deg);
162
+ }
163
+ }
164
+
165
+ &__lead {
166
+ max-width: 620px;
167
+ margin: 0;
168
+ font-size: clamp(1rem, 1.4vw, 1.1875rem);
169
+ line-height: fn.fanui-var("line-height-relaxed");
170
+ color: fn.fanui-var("color-text-muted");
171
+ text-wrap: pretty;
172
+ }
173
+
174
+ &__actions {
175
+ display: flex;
176
+ flex-wrap: wrap;
177
+ align-items: center;
178
+ justify-content: center;
179
+ gap: fn.fanui-var("space-3");
180
+ }
181
+
182
+ &__note {
183
+ font-size: fn.fanui-var("font-size-xs");
184
+ color: fn.fanui-var("color-text-subtle");
185
+ }
186
+
187
+ // 首屏内的产品截图 / 视频容器
188
+ &__media {
189
+ position: relative;
190
+ width: 100%;
191
+ max-width: 1080px;
192
+ margin-top: fn.fanui-var("space-10");
193
+ border-radius: fn.fanui-var("radius-2xl");
194
+ overflow: hidden;
195
+
196
+ img { display: block; width: 100%; height: auto; }
197
+
198
+ // 顶部高光边缘,呼应液态玻璃
199
+ &::after {
200
+ content: "";
201
+ position: absolute;
202
+ inset: 0;
203
+ border-radius: inherit;
204
+ pointer-events: none;
205
+ box-shadow: inset 0 1px 0 fn.fanui-alpha(#ffffff, 0.5);
206
+ }
207
+ }
208
+
209
+ // 左右分栏版(更适合 B 端产品页)
210
+ &--split {
211
+ text-align: start;
212
+
213
+ .fanui-hero__inner {
214
+ flex-direction: row;
215
+ align-items: center;
216
+ gap: fn.fanui-var("space-16");
217
+ max-width: 1200px;
218
+ text-align: start;
219
+ }
220
+
221
+ .fanui-hero__copy { flex: 1 1 46%; display: flex; flex-direction: column; gap: fn.fanui-var("space-5"); align-items: flex-start; }
222
+ .fanui-hero__media { flex: 1 1 54%; margin-top: 0; }
223
+ .fanui-hero__actions { justify-content: flex-start; }
224
+
225
+ @include mx.fanui-media-down("md") {
226
+ .fanui-hero__inner { flex-direction: column; gap: fn.fanui-var("space-10"); }
227
+ .fanui-hero__copy { align-items: center; text-align: center; }
228
+ .fanui-hero__actions { justify-content: center; }
229
+ }
230
+ }
231
+
232
+ &--compact { padding-block: fn.fanui-var("space-16") fn.fanui-var("space-12"); }
233
+ }
234
+
235
+ // -----------------------------------------------------------------------------
236
+ // 3. 区块标题组
237
+ // -----------------------------------------------------------------------------
238
+
239
+ .fanui-section-head {
240
+ display: flex;
241
+ flex-direction: column;
242
+ gap: fn.fanui-var("space-3");
243
+ max-width: 680px;
244
+ margin-bottom: fn.fanui-var("space-10");
245
+
246
+ &__eyebrow {
247
+ font-size: fn.fanui-var("font-size-sm");
248
+ font-weight: fn.fanui-var("font-weight-semibold");
249
+ letter-spacing: fn.fanui-var("tracking-wider");
250
+ text-transform: uppercase;
251
+ color: fn.fanui-var("primary");
252
+ }
253
+
254
+ &__title {
255
+ margin: 0;
256
+ font-size: clamp(1.5rem, 3vw, 2.25rem);
257
+ font-weight: fn.fanui-var("font-weight-bold");
258
+ line-height: 1.2;
259
+ letter-spacing: fn.fanui-var("tracking-tight");
260
+ color: fn.fanui-var("color-text-strong");
261
+ text-wrap: balance;
262
+ }
263
+
264
+ &__desc {
265
+ margin: 0;
266
+ font-size: fn.fanui-var("font-size-md");
267
+ line-height: fn.fanui-var("line-height-relaxed");
268
+ color: fn.fanui-var("color-text-muted");
269
+ }
270
+
271
+ &--center {
272
+ align-items: center;
273
+ margin-inline: auto;
274
+ text-align: center;
275
+ }
276
+ }
277
+
278
+ // -----------------------------------------------------------------------------
279
+ // 4. 特性卡
280
+ // -----------------------------------------------------------------------------
281
+
282
+ .fanui-feature {
283
+ display: flex;
284
+ flex-direction: column;
285
+ gap: fn.fanui-var("space-3");
286
+ padding: fn.fanui-var("space-5");
287
+ border-radius: fn.fanui-var("radius-xl");
288
+ @include mx.fanui-transition((transform, box-shadow, border-color), v.$fanui-duration-base);
289
+
290
+ &__icon {
291
+ display: grid;
292
+ place-items: center;
293
+ width: 40px;
294
+ height: 40px;
295
+ border-radius: fn.fanui-var("radius-lg");
296
+ color: fn.fanui-var("primary-fg");
297
+ background-image: var(--fanui-brand-grad);
298
+ font-size: fn.fanui-var("font-size-lg");
299
+ box-shadow: 0 6px 16px -8px fn.fanui-var("primary-glow");
300
+ }
301
+
302
+ &__title {
303
+ margin: 0;
304
+ font-size: fn.fanui-var("font-size-md");
305
+ font-weight: fn.fanui-var("font-weight-semibold");
306
+ color: fn.fanui-var("color-text-strong");
307
+ }
308
+
309
+ &__desc {
310
+ margin: 0;
311
+ font-size: fn.fanui-var("font-size-sm");
312
+ line-height: fn.fanui-var("line-height-relaxed");
313
+ color: fn.fanui-var("color-text-muted");
314
+ }
315
+
316
+ &__link {
317
+ margin-top: auto;
318
+ font-size: fn.fanui-var("font-size-sm");
319
+ color: fn.fanui-var("primary");
320
+ text-decoration: none;
321
+
322
+ &::after {
323
+ content: " →";
324
+ @include mx.fanui-transition(transform, v.$fanui-duration-fast);
325
+ display: inline-block;
326
+ }
327
+
328
+ &:hover::after { transform: translateX(3px); }
329
+ }
330
+
331
+ &--plain { padding: 0; }
332
+
333
+ &--glass { @include mx.fanui-liquid-glass(); }
334
+ }
335
+
336
+ // -----------------------------------------------------------------------------
337
+ // 5. Bento 网格
338
+ // -----------------------------------------------------------------------------
339
+ // 通过 --fanui-bento-* 变量声明跨列/跨行,实现富媒体版式。
340
+
341
+ .fanui-bento {
342
+ display: grid;
343
+ grid-template-columns: repeat(12, minmax(0, 1fr));
344
+ gap: fn.fanui-var("space-4");
345
+
346
+ > * {
347
+ grid-column: span var(--fanui-bento-cols, 4);
348
+ grid-row: span var(--fanui-bento-rows, 1);
349
+ min-width: 0;
350
+ }
351
+
352
+ &__cell {
353
+ position: relative;
354
+ overflow: hidden;
355
+ display: flex;
356
+ flex-direction: column;
357
+ gap: fn.fanui-var("space-2");
358
+ padding: fn.fanui-var("space-5");
359
+ border-radius: fn.fanui-var("radius-xl");
360
+ @include mx.fanui-liquid-glass();
361
+ @include mx.fanui-transition(transform, v.$fanui-duration-base);
362
+
363
+ &:hover { transform: translateY(-2px); }
364
+ }
365
+
366
+ &__title {
367
+ margin: 0;
368
+ font-size: fn.fanui-var("font-size-lg");
369
+ font-weight: fn.fanui-var("font-weight-semibold");
370
+ color: fn.fanui-var("color-text-strong");
371
+ }
372
+
373
+ &__desc {
374
+ margin: 0;
375
+ font-size: fn.fanui-var("font-size-sm");
376
+ color: fn.fanui-var("color-text-muted");
377
+ }
378
+
379
+ &__media {
380
+ margin-top: auto;
381
+ border-radius: fn.fanui-var("radius-lg");
382
+ overflow: hidden;
383
+
384
+ img { display: block; width: 100%; height: 100%; object-fit: cover; }
385
+ }
386
+
387
+ // 品牌渐变强调格
388
+ &__cell--brand {
389
+ background-image: var(--fanui-brand-grad);
390
+ color: fn.fanui-var("primary-fg");
391
+ border-color: transparent;
392
+
393
+ .fanui-bento__title,
394
+ .fanui-bento__desc { color: inherit; }
395
+ }
396
+
397
+ &__cell--span-6 { --fanui-bento-cols: 6; }
398
+ &__cell--span-8 { --fanui-bento-cols: 8; }
399
+ &__cell--span-12 { --fanui-bento-cols: 12; }
400
+ &__cell--tall { --fanui-bento-rows: 2; }
401
+
402
+ @include mx.fanui-media-down("lg") {
403
+ > * { --fanui-bento-cols: 6; }
404
+ }
405
+
406
+ @include mx.fanui-media-down("sm") {
407
+ > * { --fanui-bento-cols: 12; }
408
+ }
409
+ }
410
+
411
+ // -----------------------------------------------------------------------------
412
+ // 6. 流程步骤
413
+ // -----------------------------------------------------------------------------
414
+
415
+ .fanui-flow {
416
+ display: grid;
417
+ grid-template-columns: repeat(var(--fanui-flow-cols, 3), minmax(0, 1fr));
418
+ gap: fn.fanui-var("space-6");
419
+ counter-reset: fanui-flow;
420
+
421
+ @include mx.fanui-media-down("md") {
422
+ grid-template-columns: 1fr;
423
+ }
424
+
425
+ &__step {
426
+ position: relative;
427
+ counter-increment: fanui-flow;
428
+ display: flex;
429
+ flex-direction: column;
430
+ gap: fn.fanui-var("space-2");
431
+ padding-top: fn.fanui-var("space-4");
432
+
433
+ // 顶部进度线
434
+ &::before {
435
+ content: "";
436
+ position: absolute;
437
+ top: 0;
438
+ left: 0;
439
+ right: calc(#{fn.fanui-var("space-6")} * -1 + 1px);
440
+ height: 2px;
441
+ background-image: linear-gradient(to right, var(--fanui-primary), var(--fanui-primary-vivid));
442
+ border-radius: fn.fanui-var("radius-full");
443
+ }
444
+
445
+ &:last-child::before { right: 0; }
446
+ }
447
+
448
+ &__index {
449
+ display: grid;
450
+ place-items: center;
451
+ width: 30px;
452
+ height: 30px;
453
+ font-size: fn.fanui-var("font-size-sm");
454
+ font-weight: fn.fanui-var("font-weight-semibold");
455
+ color: fn.fanui-var("primary-ink");
456
+ background-color: fn.fanui-var("primary-soft-2");
457
+ border-radius: fn.fanui-var("radius-full");
458
+ }
459
+
460
+ &__title {
461
+ margin: 0;
462
+ font-size: fn.fanui-var("font-size-md");
463
+ font-weight: fn.fanui-var("font-weight-semibold");
464
+ color: fn.fanui-var("color-text-strong");
465
+ }
466
+
467
+ &__desc {
468
+ margin: 0;
469
+ font-size: fn.fanui-var("font-size-sm");
470
+ line-height: fn.fanui-var("line-height-relaxed");
471
+ color: fn.fanui-var("color-text-muted");
472
+ }
473
+ }
474
+
475
+ // -----------------------------------------------------------------------------
476
+ // 7. Logo 无缝滚动
477
+ // -----------------------------------------------------------------------------
478
+
479
+ .fanui-marquee {
480
+ display: flex;
481
+ overflow: hidden;
482
+ gap: var(--fanui-marquee-gap, #{fn.fanui-var("space-12")});
483
+ -webkit-mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
484
+ mask-image: linear-gradient(90deg, transparent, #000 10%, #000 90%, transparent);
485
+
486
+ &__track {
487
+ display: flex;
488
+ align-items: center;
489
+ gap: inherit;
490
+ flex: 0 0 auto;
491
+ min-width: 100%;
492
+ animation: fanui-marquee var(--fanui-marquee-duration, 36s) linear infinite;
493
+ }
494
+
495
+ &:hover &__track { animation-play-state: paused; }
496
+
497
+ &__item {
498
+ display: grid;
499
+ place-items: center;
500
+ flex: 0 0 auto;
501
+ height: 40px;
502
+ color: fn.fanui-var("color-text-subtle");
503
+ font-size: fn.fanui-var("font-size-lg");
504
+ font-weight: fn.fanui-var("font-weight-semibold");
505
+ letter-spacing: fn.fanui-var("tracking-tight");
506
+ filter: grayscale(1);
507
+ opacity: 0.72;
508
+ @include mx.fanui-transition((filter, opacity, color), v.$fanui-duration-base);
509
+
510
+ &:hover {
511
+ filter: none;
512
+ opacity: 1;
513
+ color: fn.fanui-var("color-text");
514
+ }
515
+
516
+ img { max-height: 32px; width: auto; }
517
+ }
518
+
519
+ &--reverse &__track { animation-direction: reverse; }
520
+
521
+ @media (prefers-reduced-motion: reduce) {
522
+ &__track { animation: none; }
523
+ }
524
+ }
525
+
526
+ @keyframes fanui-marquee {
527
+ from { transform: translateX(0); }
528
+ to { transform: translateX(calc(-100% - var(--fanui-marquee-gap, 48px))); }
529
+ }
530
+
531
+ // -----------------------------------------------------------------------------
532
+ // 8. 数据带
533
+ // -----------------------------------------------------------------------------
534
+
535
+ .fanui-stat-band {
536
+ display: grid;
537
+ grid-template-columns: repeat(var(--fanui-stat-cols, 4), minmax(0, 1fr));
538
+ gap: fn.fanui-var("space-6");
539
+ padding: fn.fanui-var("space-8");
540
+ border-radius: fn.fanui-var("radius-2xl");
541
+ @include mx.fanui-liquid-glass();
542
+
543
+ @include mx.fanui-media-down("md") {
544
+ grid-template-columns: repeat(2, minmax(0, 1fr));
545
+ }
546
+
547
+ &__item {
548
+ display: flex;
549
+ flex-direction: column;
550
+ gap: fn.fanui-var("space-1");
551
+ text-align: center;
552
+ }
553
+
554
+ &__value {
555
+ font-size: clamp(1.75rem, 3vw, 2.5rem);
556
+ font-weight: fn.fanui-var("font-weight-extrabold");
557
+ line-height: 1.1;
558
+ letter-spacing: fn.fanui-var("tracking-tight");
559
+ font-variant-numeric: tabular-nums;
560
+ @include mx.fanui-text-gradient(var(--fanui-brand-grad-a), var(--fanui-brand-grad-b), 120deg);
561
+ }
562
+
563
+ &__label {
564
+ font-size: fn.fanui-var("font-size-sm");
565
+ color: fn.fanui-var("color-text-muted");
566
+ }
567
+ }
568
+
569
+ // -----------------------------------------------------------------------------
570
+ // 9. 价格表
571
+ // -----------------------------------------------------------------------------
572
+
573
+ .fanui-pricing {
574
+ // 月付 / 年付切换:由 JS 或 .is-yearly 控制显隐
575
+ &__switch {
576
+ display: inline-flex;
577
+ align-items: center;
578
+ gap: fn.fanui-var("space-3");
579
+ margin: 0 auto fn.fanui-var("space-8");
580
+ }
581
+
582
+ &__save {
583
+ padding: 2px 8px;
584
+ font-size: fn.fanui-var("font-size-xs");
585
+ color: fn.fanui-var("success-ink");
586
+ background-color: fn.fanui-var("success-soft");
587
+ border-radius: fn.fanui-var("radius-full");
588
+ }
589
+
590
+ &__grid {
591
+ display: grid;
592
+ grid-template-columns: repeat(var(--fanui-pricing-cols, 3), minmax(0, 1fr));
593
+ gap: fn.fanui-var("space-5");
594
+ align-items: start;
595
+
596
+ @include mx.fanui-media-down("lg") {
597
+ grid-template-columns: 1fr;
598
+ max-width: 460px;
599
+ margin-inline: auto;
600
+ }
601
+ }
602
+
603
+ &__plan {
604
+ position: relative;
605
+ display: flex;
606
+ flex-direction: column;
607
+ gap: fn.fanui-var("space-4");
608
+ padding: fn.fanui-var("space-6");
609
+ border-radius: fn.fanui-var("radius-2xl");
610
+ @include mx.fanui-liquid-glass();
611
+ @include mx.fanui-transition((transform, box-shadow), v.$fanui-duration-base);
612
+
613
+ &:hover { transform: translateY(-3px); }
614
+ }
615
+
616
+ // 推荐方案:品牌渐变描边 + 高亮标签
617
+ &__plan--featured {
618
+ border-color: transparent;
619
+ box-shadow: 0 0 0 2px var(--fanui-primary), var(--fanui-glass-shadow);
620
+ @include mx.fanui-media("lg") { transform: scale(1.03); }
621
+
622
+ &:hover { transform: translateY(-3px) scale(1.03); }
623
+ }
624
+
625
+ &__tag {
626
+ position: absolute;
627
+ inset-block-start: -12px;
628
+ inset-inline-start: fn.fanui-var("space-6");
629
+ padding: 3px 10px;
630
+ font-size: fn.fanui-var("font-size-xs");
631
+ font-weight: fn.fanui-var("font-weight-semibold");
632
+ color: #fff;
633
+ background-image: var(--fanui-brand-grad);
634
+ border-radius: fn.fanui-var("radius-full");
635
+ }
636
+
637
+ &__name {
638
+ font-size: fn.fanui-var("font-size-md");
639
+ font-weight: fn.fanui-var("font-weight-semibold");
640
+ color: fn.fanui-var("color-text-strong");
641
+ }
642
+
643
+ &__desc {
644
+ font-size: fn.fanui-var("font-size-sm");
645
+ color: fn.fanui-var("color-text-muted");
646
+ }
647
+
648
+ &__price {
649
+ display: flex;
650
+ align-items: flex-end;
651
+ gap: fn.fanui-var("space-1");
652
+ font-variant-numeric: tabular-nums;
653
+
654
+ strong {
655
+ font-size: clamp(2rem, 3.4vw, 2.75rem);
656
+ font-weight: fn.fanui-var("font-weight-extrabold");
657
+ line-height: 1;
658
+ letter-spacing: fn.fanui-var("tracking-tight");
659
+ color: fn.fanui-var("color-text-strong");
660
+ }
661
+
662
+ span {
663
+ font-size: fn.fanui-var("font-size-sm");
664
+ color: fn.fanui-var("color-text-subtle");
665
+ padding-bottom: 4px;
666
+ }
667
+ }
668
+
669
+ &__features {
670
+ display: flex;
671
+ flex-direction: column;
672
+ gap: fn.fanui-var("space-2");
673
+ margin: 0;
674
+ padding: 0;
675
+ list-style: none;
676
+ font-size: fn.fanui-var("font-size-sm");
677
+ color: fn.fanui-var("color-text-muted");
678
+
679
+ li {
680
+ display: flex;
681
+ align-items: flex-start;
682
+ gap: fn.fanui-var("space-2");
683
+ }
684
+
685
+ li::before {
686
+ content: "✓";
687
+ flex: 0 0 auto;
688
+ font-size: fn.fanui-var("font-size-sm");
689
+ color: fn.fanui-var("primary");
690
+ font-weight: fn.fanui-var("font-weight-bold");
691
+ }
692
+
693
+ li.is-off { opacity: 0.5; text-decoration: line-through; }
694
+ li.is-off::before { content: "—"; color: fn.fanui-var("color-text-subtle"); }
695
+ }
696
+
697
+ &__foot { margin-top: auto; }
698
+
699
+ // 价格周期显隐
700
+ .fanui-price--yearly { display: none; }
701
+ &.is-yearly {
702
+ .fanui-price--monthly { display: none; }
703
+ .fanui-price--yearly { display: flex; }
704
+ }
705
+ }
706
+
707
+ // -----------------------------------------------------------------------------
708
+ // 10. 客户证言
709
+ // -----------------------------------------------------------------------------
710
+
711
+ .fanui-testimonial {
712
+ display: flex;
713
+ flex-direction: column;
714
+ gap: fn.fanui-var("space-4");
715
+ padding: fn.fanui-var("space-6");
716
+ border-radius: fn.fanui-var("radius-xl");
717
+ @include mx.fanui-liquid-glass();
718
+
719
+ &__quote {
720
+ margin: 0;
721
+ font-size: fn.fanui-var("font-size-md");
722
+ line-height: fn.fanui-var("line-height-relaxed");
723
+ color: fn.fanui-var("color-text");
724
+ text-wrap: pretty;
725
+
726
+ &::before {
727
+ content: "“";
728
+ display: block;
729
+ font-size: 40px;
730
+ line-height: 0.6;
731
+ color: fn.fanui-var("primary");
732
+ opacity: 0.5;
733
+ }
734
+ }
735
+
736
+ &__person {
737
+ display: flex;
738
+ align-items: center;
739
+ gap: fn.fanui-var("space-3");
740
+ margin-top: auto;
741
+ padding-top: fn.fanui-var("space-3");
742
+ border-top: 1px solid fn.fanui-var("glass-divider");
743
+ }
744
+
745
+ &__name {
746
+ font-size: fn.fanui-var("font-size-sm");
747
+ font-weight: fn.fanui-var("font-weight-semibold");
748
+ color: fn.fanui-var("color-text-strong");
749
+ }
750
+
751
+ &__role {
752
+ font-size: fn.fanui-var("font-size-xs");
753
+ color: fn.fanui-var("color-text-subtle");
754
+ }
755
+
756
+ &--brand {
757
+ background-image: var(--fanui-brand-grad);
758
+ color: fn.fanui-var("primary-fg");
759
+ border-color: transparent;
760
+
761
+ .fanui-testimonial__quote,
762
+ .fanui-testimonial__name,
763
+ .fanui-testimonial__role { color: inherit; }
764
+
765
+ .fanui-testimonial__quote::before { color: inherit; opacity: 0.4; }
766
+ .fanui-testimonial__person { border-top-color: fn.fanui-alpha(#ffffff, 0.25); }
767
+ }
768
+ }
769
+
770
+ // -----------------------------------------------------------------------------
771
+ // 11. 行动号召
772
+ // -----------------------------------------------------------------------------
773
+
774
+ .fanui-cta {
775
+ position: relative;
776
+ isolation: isolate;
777
+ overflow: hidden;
778
+ display: flex;
779
+ flex-direction: column;
780
+ align-items: center;
781
+ gap: fn.fanui-var("space-4");
782
+ padding: fn.fanui-var("space-16") fn.fanui-var("space-6");
783
+ text-align: center;
784
+ border-radius: fn.fanui-var("radius-2xl");
785
+ @include mx.fanui-liquid-glass();
786
+
787
+ &__glow {
788
+ position: absolute;
789
+ inset: -30% -10%;
790
+ z-index: -1;
791
+ pointer-events: none;
792
+ background:
793
+ radial-gradient(40% 44% at 20% 30%, var(--fanui-brand-aura-a), transparent 60%),
794
+ radial-gradient(36% 40% at 80% 70%, var(--fanui-brand-aura-b), transparent 58%);
795
+ filter: blur(30px);
796
+ }
797
+
798
+ &__title {
799
+ margin: 0;
800
+ max-width: 640px;
801
+ font-size: clamp(1.5rem, 3vw, 2.25rem);
802
+ font-weight: fn.fanui-var("font-weight-bold");
803
+ letter-spacing: fn.fanui-var("tracking-tight");
804
+ color: fn.fanui-var("color-text-strong");
805
+ text-wrap: balance;
806
+ }
807
+
808
+ &__desc {
809
+ margin: 0;
810
+ max-width: 520px;
811
+ font-size: fn.fanui-var("font-size-md");
812
+ color: fn.fanui-var("color-text-muted");
813
+ }
814
+
815
+ &__actions {
816
+ display: flex;
817
+ flex-wrap: wrap;
818
+ gap: fn.fanui-var("space-3");
819
+ justify-content: center;
820
+ }
821
+ }
822
+
823
+ // -----------------------------------------------------------------------------
824
+ // 12. 常见问题
825
+ // -----------------------------------------------------------------------------
826
+
827
+ .fanui-faq {
828
+ display: flex;
829
+ flex-direction: column;
830
+ gap: fn.fanui-var("space-2");
831
+
832
+ &__item {
833
+ border: 1px solid fn.fanui-var("color-border");
834
+ border-radius: fn.fanui-var("radius-lg");
835
+ background-color: fn.fanui-var("color-surface");
836
+ overflow: hidden;
837
+ @include mx.fanui-transition((border-color, background-color), v.$fanui-duration-fast);
838
+
839
+ &[open] {
840
+ border-color: fn.fanui-var("primary-border");
841
+ background-color: fn.fanui-var("primary-soft");
842
+ }
843
+ }
844
+
845
+ &__q {
846
+ display: flex;
847
+ align-items: center;
848
+ justify-content: space-between;
849
+ gap: fn.fanui-var("space-3");
850
+ padding: fn.fanui-var("space-4") fn.fanui-var("space-5");
851
+ font-size: fn.fanui-var("font-size-sm");
852
+ font-weight: fn.fanui-var("font-weight-semibold");
853
+ color: fn.fanui-var("color-text-strong");
854
+ cursor: pointer;
855
+ list-style: none;
856
+
857
+ &::-webkit-details-marker { display: none; }
858
+
859
+ &::after {
860
+ content: "+";
861
+ flex: 0 0 auto;
862
+ font-size: 18px;
863
+ font-weight: fn.fanui-var("font-weight-normal");
864
+ color: fn.fanui-var("color-text-muted");
865
+ @include mx.fanui-transition(transform, v.$fanui-duration-base);
866
+ }
867
+ }
868
+
869
+ &__item[open] &__q::after { transform: rotate(45deg); }
870
+
871
+ &__a {
872
+ padding: 0 fn.fanui-var("space-5") fn.fanui-var("space-4");
873
+ font-size: fn.fanui-var("font-size-sm");
874
+ line-height: fn.fanui-var("line-height-relaxed");
875
+ color: fn.fanui-var("color-text-muted");
876
+ }
877
+ }
878
+
879
+ // -----------------------------------------------------------------------------
880
+ // 13. 页脚
881
+ // -----------------------------------------------------------------------------
882
+
883
+ .fanui-footer {
884
+ padding-block: fn.fanui-var("space-16") fn.fanui-var("space-8");
885
+ border-top: 1px solid fn.fanui-var("color-border");
886
+ background-color: fn.fanui-var("color-bg-subtle");
887
+ font-size: fn.fanui-var("font-size-sm");
888
+
889
+ &__grid {
890
+ display: grid;
891
+ grid-template-columns: 1.6fr repeat(var(--fanui-footer-cols, 3), 1fr);
892
+ gap: fn.fanui-var("space-8");
893
+
894
+ @include mx.fanui-media-down("md") {
895
+ grid-template-columns: repeat(2, minmax(0, 1fr));
896
+ }
897
+ }
898
+
899
+ &__brand {
900
+ display: flex;
901
+ flex-direction: column;
902
+ gap: fn.fanui-var("space-3");
903
+ max-width: 320px;
904
+ }
905
+
906
+ &__logo {
907
+ display: inline-flex;
908
+ align-items: center;
909
+ gap: fn.fanui-var("space-2");
910
+ font-size: fn.fanui-var("font-size-lg");
911
+ font-weight: fn.fanui-var("font-weight-bold");
912
+ color: fn.fanui-var("color-text-strong");
913
+ text-decoration: none;
914
+ }
915
+
916
+ &__desc {
917
+ margin: 0;
918
+ line-height: fn.fanui-var("line-height-relaxed");
919
+ color: fn.fanui-var("color-text-muted");
920
+ }
921
+
922
+ &__title {
923
+ margin: 0 0 fn.fanui-var("space-3");
924
+ font-size: fn.fanui-var("font-size-sm");
925
+ font-weight: fn.fanui-var("font-weight-semibold");
926
+ color: fn.fanui-var("color-text-strong");
927
+ }
928
+
929
+ &__list {
930
+ display: flex;
931
+ flex-direction: column;
932
+ gap: fn.fanui-var("space-2");
933
+ margin: 0;
934
+ padding: 0;
935
+ list-style: none;
936
+
937
+ a {
938
+ color: fn.fanui-var("color-text-muted");
939
+ text-decoration: none;
940
+ @include mx.fanui-transition(color, v.$fanui-duration-fast);
941
+
942
+ &:hover { color: fn.fanui-var("primary"); }
943
+ }
944
+ }
945
+
946
+ &__bottom {
947
+ display: flex;
948
+ flex-wrap: wrap;
949
+ align-items: center;
950
+ justify-content: space-between;
951
+ gap: fn.fanui-var("space-3");
952
+ margin-top: fn.fanui-var("space-10");
953
+ padding-top: fn.fanui-var("space-5");
954
+ border-top: 1px solid fn.fanui-var("color-border-subtle");
955
+ font-size: fn.fanui-var("font-size-xs");
956
+ color: fn.fanui-var("color-text-subtle");
957
+ }
958
+
959
+ &__social {
960
+ display: flex;
961
+ gap: fn.fanui-var("space-2");
962
+
963
+ a {
964
+ display: grid;
965
+ place-items: center;
966
+ width: 32px;
967
+ height: 32px;
968
+ border-radius: fn.fanui-var("radius-full");
969
+ color: fn.fanui-var("color-text-muted");
970
+ background-color: fn.fanui-var("color-surface");
971
+ border: 1px solid fn.fanui-var("color-border");
972
+ text-decoration: none;
973
+ @include mx.fanui-transition((color, border-color, transform), v.$fanui-duration-fast);
974
+
975
+ &:hover {
976
+ color: fn.fanui-var("primary");
977
+ border-color: fn.fanui-var("primary-border");
978
+ transform: translateY(-2px);
979
+ }
980
+ }
981
+ }
982
+ }