-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
2101 lines (1936 loc) · 161 KB
/
Copy pathindex.html
File metadata and controls
2101 lines (1936 loc) · 161 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>guizang-ppt-skill 工作原理 · 交互式导读</title>
<!-- Google Fonts: Bricolage Grotesque · DM Sans · JetBrains Mono -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,400;12..96,600;12..96,700;12..96,800&family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400;1,9..40,500&family=JetBrains+Mono:wght@400;500;600&family=Noto+Sans+SC:wght@400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css">
<style>
:root {
--color-accent: #D94F30;
--color-accent-hover: #C4432A;
--color-accent-light: #FDEEE9;
--color-accent-muted: #E8836C;
/* CJK fallback so Chinese glyphs use the loaded Noto Sans SC webfont
instead of an unrelated system font (styles.css ships Latin-only stacks). */
--font-body: 'DM Sans', 'Noto Sans SC', -apple-system, sans-serif;
--font-display: 'Bricolage Grotesque', 'Noto Sans SC', Georgia, serif;
}
</style>
<script src="main.js" defer></script>
</head>
<body>
<nav class="nav" id="nav">
<div class="progress-bar" id="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
<div class="nav-inner">
<a class="nav-title" href="../" style="text-decoration: none;">← Code Course Atlas</a>
<div class="nav-dots" id="nav-dots" role="tablist">
<button class="nav-dot" data-target="module-1" data-tooltip="一句指令,一份 PPT" role="tab" aria-label="模块 1:一句指令,一份 PPT"></button>
<button class="nav-dot" data-target="module-2" data-tooltip="认识角色" role="tab" aria-label="模块 2:认识角色"></button>
<button class="nav-dot" data-target="module-3" data-tooltip="六步工作流" role="tab" aria-label="模块 3:六步工作流"></button>
<button class="nav-dot" data-target="module-4" data-tooltip="视觉引擎" role="tab" aria-label="模块 4:视觉引擎"></button>
<button class="nav-dot" data-target="module-5" data-tooltip="设计系统即接口" role="tab" aria-label="模块 5:设计系统即接口"></button>
<button class="nav-dot" data-target="module-6" data-tooltip="护栏与校验" role="tab" aria-label="模块 6:护栏与校验"></button>
</div>
<a class="language-switch" href="../guizang-ppt-skill-course-en/index.html">EN</a>
</div>
</nav>
<main id="main">
<!-- modules/*.html content is assembled here by build.sh -->
<section class="module" id="module-1" style="background: var(--color-bg-warm)">
<div class="module-content">
<header class="module-header animate-in">
<span class="module-number">01</span>
<h1 class="module-title">一句指令,一份 PPT</h1>
<p class="module-subtitle">你打了一句话,几秒后拿到一份能翻页的演示文稿——中间到底发生了什么?</p>
</header>
<div class="module-body">
<!-- SCREEN 1 — 钩子 + 菜谱卡比喻 -->
<section class="screen animate-in">
<h2 class="screen-heading">你打了一句话,然后呢?</h2>
<p>你打了一句"帮我做一份瑞士风 PPT",几秒后拿到一份能翻页、有动效、能在浏览器直接打开的精美演示文稿。中间到底发生了什么?</p>
<div style="background: var(--color-bg-code); color: #CDD6F4; padding: var(--space-5) var(--space-6); border-radius: var(--radius-md); font-family: var(--font-mono); font-size: var(--text-sm); line-height: 1.7; margin: var(--space-6) 0; box-shadow: var(--shadow-md);">
<div style="font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.1em; opacity: 0.5; margin-bottom: var(--space-3);">你输入的一句话</div>
<span class="code-string">帮我基于这篇文章做一份瑞士风 PPT,控制在 7 页左右,需要 2-3 张配图。</span>
</div>
<p style="margin-top: var(--space-6);">一个 <span class="term" data-definition="skill 技能:教 AI 应对某类任务的预制操作手册;安装后 AI 会在合适时机自动调用它。">skill</span> 就像一张留在灶台上的<strong>菜谱卡</strong>:</p>
<div class="icon-rows">
<div class="icon-row">
<div class="icon-circle" style="background: var(--color-actor-2)">🗂️</div>
<div>
<strong>菜谱卡 = <span class="term" data-definition="SKILL.md:一份留给 AI 的操作手册,告诉它遇到'做 PPT'这类任务时该按什么顺序、用什么素材去做。">SKILL.md</span></strong>
<p>只写"做什么、按什么顺序",本身不含答案。</p>
</div>
</div>
<div class="icon-row">
<div class="icon-circle" style="background: var(--color-actor-4)">🧂</div>
<div>
<strong>备好的食材与工具 = <code>assets/</code> + <code>references/</code></strong>
<p>模板、配色、版式规则,已经量好分装、摆上台面。</p>
</div>
</div>
<div class="icon-row">
<div class="icon-circle" style="background: var(--color-actor-1)">👨🍳</div>
<div>
<strong>你不用从零开火——照着卡片做</strong>
<p>这就是 guizang-ppt-skill 这类技能的工作方式。</p>
</div>
</div>
</div>
</section>
<!-- SCREEN 2 — 这是什么 + 两种风格 -->
<section class="screen animate-in">
<h2 class="screen-heading">这是什么?一个会做 PPT 的 <span class="term" data-definition="Claude Code:Anthropic 出品的命令行 AI 编程助手,能直接读写你电脑里的文件、运行命令。">Claude Code</span> 技能</h2>
<p>guizang-ppt-skill 把你的一句话,变成一个<strong>单文件 <span class="term" data-definition="HTML:网页的骨架语言,用一对对尖括号标签描述页面的结构和内容。">HTML</span></strong>——浏览器双击就能打开、能左右翻页的"网页 PPT"。</p>
<div class="pattern-cards">
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-3)">
<div class="pattern-icon" style="background: var(--color-actor-3)">📖</div>
<h4 class="pattern-title">A · 电子杂志 × 电子墨水</h4>
<p class="pattern-desc">衬线标题、<span class="term" data-definition="WebGL:让浏览器渲染 3D 与流体图形的技术,电子墨水风格的流动背景就靠它。">WebGL</span> 流体背景、暖纸色。适合叙事、演讲、个人风格。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-2)">
<div class="pattern-icon" style="background: var(--color-actor-2)">▦</div>
<h4 class="pattern-title">B · <span class="term" data-definition="瑞士国际主义(Swiss Style):1950 年代发源于瑞士的设计流派,强调网格、无衬线字体、大量留白和一个强烈的强调色。">瑞士国际主义</span></h4>
<p class="pattern-desc">全无衬线、网格 + 点阵、单一高饱和强调色(克莱因蓝 / 柠檬黄)。适合数据、产品、工程。</p>
</div>
</div>
<div class="badge-list" style="margin-top: var(--space-6);">
<div class="badge-item">
<code class="badge-code">← → · scroll · ESC</code>
<span class="badge-desc">键盘、滚轮、触屏、圆点都能翻页;ESC 看全部缩略图</span>
</div>
<div class="badge-item">
<code class="badge-code">Lucide · Motion One</code>
<span class="badge-desc">统一图标库 + 入场动效,两种风格共用这条"脊椎"</span>
</div>
</div>
</section>
<!-- SCREEN 3 — 代码↔大白话(一页 PPT 的最小单位) -->
<section class="screen animate-in">
<h2 class="screen-heading">一份 PPT 的最小单位:一个 <code><section></code></h2>
<p>整份 PPT,就是许多个这样的 section 叠在一起。左右对照看——左边真实代码,右边大白话。</p>
<div class="translation-block animate-in">
<div class="translation-code">
<span class="translation-label">代码</span>
<pre><code><span class="code-line"><span class="code-tag"><section</span> <span class="code-attr">class</span>=<span class="code-string">"slide [light|dark|hero light|hero dark]"</span><span class="code-tag">></span></span>
<span class="code-line"> <span class="code-tag"><div</span> <span class="code-attr">class</span>=<span class="code-string">"chrome"</span><span class="code-tag">></span></span>
<span class="code-line"> <span class="code-tag"><div></span>上下文标签 · 子标签<span class="code-tag"></div></span></span>
<span class="code-line"> <span class="code-tag"><div></span>ACT · 页号 / 总页数<span class="code-tag"></div></span></span>
<span class="code-line"> <span class="code-tag"></div></span></span>
<span class="code-line"> <span class="code-comment"><!-- 主内容 --></span></span>
<span class="code-line"> <span class="code-tag"><div</span> <span class="code-attr">class</span>=<span class="code-string">"foot"</span><span class="code-tag">></span></span>
<span class="code-line"> <span class="code-tag"><div></span>页码说明 · Page Description<span class="code-tag"></div></span></span>
<span class="code-line"> <span class="code-tag"><div></span>— · —<span class="code-tag"></div></span></span>
<span class="code-line"> <span class="code-tag"></div></span></span>
<span class="code-line"><span class="code-tag"></section></span></span></code></pre>
</div>
<div class="translation-english">
<span class="translation-label">大白话</span>
<div class="translation-lines">
<p class="tl">每一页就是这样一个 <code><section></code>——整份 PPT 是许多个 section 叠起来。括号里的词选一个当这页主题(亮 / 暗 / 大图)。</p>
<p class="tl"><code>chrome</code> 是顶部页眉 / 导航条,像杂志的刊头。</p>
<p class="tl">左:上下文标签,告诉读者"现在第几章第几节"。右:<code>ACT · 页号</code>,像"第 2 幕 · 05 / 12"。</p>
<p class="tl">页眉到此结束。</p>
<p class="tl"><code>主内容</code> 这块留给你真正要讲的——标题、正文、图。</p>
<p class="tl"><code>foot</code> 是底部页脚。左:这页的一句话说明(中英对照);右:装饰分隔符 <code>— · —</code>。</p>
<p class="tl">这一页的 section 完整收尾。</p>
</div>
</div>
</div>
<div style="display: flex; align-items: center; gap: var(--space-4); margin-top: var(--space-8); padding: var(--space-4) var(--space-5); background: var(--color-surface-warm); border-radius: var(--radius-md); border-left: 3px solid var(--color-actor-3); flex-wrap: wrap;">
<span style="font-family: var(--font-mono); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.05em; color: var(--color-text-muted); white-space: nowrap;">template 里唯一的注入点</span>
<code style="background: var(--color-bg-code); color: #6C7086; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); font-family: var(--font-mono); font-size: var(--text-sm);"><!-- SLIDES_HERE --></code>
</div>
<p style="margin-top: var(--space-3);">整个 <span class="term" data-definition="template 模板:一份已做好样式、只等填内容的半成品文件,复制即可用,不用从零搭。">template</span> 开箱即跑,只有这一个占位符等着被填满。</p>
</section>
<!-- SCREEN 4 — 群聊动画 -->
<section class="screen animate-in">
<h2 class="screen-heading">中间发生了什么:一场三方对话</h2>
<p>点"下一条"——看用户、技能大脑、画布三方怎么把一句话变成一份 PPT。</p>
<div class="chat-window" id="chat-intro">
<div class="chat-messages">
<div class="chat-message" data-msg="0" data-sender="actor-1" style="display:none">
<div class="chat-avatar" style="background: var(--color-actor-1)">你</div>
<div class="chat-bubble">
<span class="chat-sender" style="color: var(--color-actor-1)">用户</span>
<p>帮我做一份瑞士风 PPT,7 页左右。</p>
</div>
</div>
<div class="chat-message" data-msg="1" data-sender="actor-2" style="display:none">
<div class="chat-avatar" style="background: var(--color-actor-2)">脑</div>
<div class="chat-bubble">
<span class="chat-sender" style="color: var(--color-actor-2)">SKILL.md(大脑)</span>
<p>收到。先确认:风格 B 瑞士风、受众、时长、有没有素材和截图、主题色、硬约束——7 个问题对齐后我才动手。</p>
</div>
</div>
<div class="chat-message" data-msg="2" data-sender="actor-1" style="display:none">
<div class="chat-avatar" style="background: var(--color-actor-1)">你</div>
<div class="chat-bubble">
<span class="chat-sender" style="color: var(--color-actor-1)">用户</span>
<p>克莱因蓝,科技产品发布,20 分钟。</p>
</div>
</div>
<div class="chat-message" data-msg="3" data-sender="actor-2" style="display:none">
<div class="chat-avatar" style="background: var(--color-actor-2)">脑</div>
<div class="chat-bubble">
<span class="chat-sender" style="color: var(--color-actor-2)">SKILL.md(大脑)</span>
<p>明白。我拷贝 template-swiss.html,按 S01–S22 填内容,套克莱因蓝主题,跑<span class="term" data-definition="validator 校验器:一段自动检查输出是否合规的程序,相当于出厂前的质检员;AI 改完会自己跑一遍确认没改坏。">校验器</span>,你在浏览器打开就行。</p>
</div>
</div>
<div class="chat-message" data-msg="4" data-sender="actor-3" style="display:none">
<div class="chat-avatar" style="background: var(--color-actor-3)">画</div>
<div class="chat-bubble">
<span class="chat-sender" style="color: var(--color-actor-3)">浏览器 / 画布</span>
<p>index.html 就绪——← → 翻页,ESC 看全部缩略图。</p>
</div>
</div>
</div>
<div class="chat-typing" style="display:none">
<div class="chat-avatar" id="chat-intro-typing-avatar">?</div>
<div class="chat-typing-dots">
<span class="typing-dot"></span>
<span class="typing-dot"></span>
<span class="typing-dot"></span>
</div>
</div>
<div class="chat-controls">
<button class="btn chat-next-btn">下一条</button>
<button class="btn chat-all-btn">全部播放</button>
<button class="btn chat-reset-btn">重播</button>
<span class="chat-progress"></span>
</div>
</div>
</section>
<!-- SCREEN 5 — 为什么是 HTML + 关键洞察 -->
<section class="screen animate-in">
<h2 class="screen-heading">为什么是 HTML?因为 AI 只懂文本</h2>
<p>这份 PPT 本质上就是一个文本文件——AI 在编辑文本,不是在变魔术。</p>
<div class="pattern-cards">
<div class="pattern-card" style="border-top: 3px solid var(--color-success)">
<div class="pattern-icon" style="background: var(--color-success)">✓</div>
<h4 class="pattern-title">HTML / <span class="term" data-definition="CSS:网页的化妆师语言,负责颜色、字号、间距这些外观样式。">CSS</span>(纯文本)</h4>
<p class="pattern-desc">AI 能逐行读、能精准改、能自己跑一遍校验器确认没改坏。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-error)">
<div class="pattern-icon" style="background: var(--color-error)">✕</div>
<h4 class="pattern-title">.pptx(<span class="term" data-definition="binary 二进制:不是人能直接读懂的文本,而是只有专门软件才能解码的 0/1 编码;.pptx 本质是一个 zip 压缩包。">二进制</span>压缩包)</h4>
<p class="pattern-desc">里面是打包好的二进制资源,AI 看不懂、改不动、没法自检。</p>
</div>
</div>
<div class="callout callout-accent">
<div class="callout-icon">💡</div>
<div class="callout-content">
<strong class="callout-title">关键洞察:薄指令,厚技能(Thin Harness, Fat Skills)</strong>
<p>一份薄薄的指令(skill),驱动一堆厚实的素材与能力。既然 PPT 只是文本,你就能让 AI 微调一段话、修一页版式、或换掉整套配色——而你会清楚知道,它只是在编辑文本。</p>
</div>
</div>
</section>
<!-- SCREEN 6 — 小测 + 交接 -->
<section class="screen animate-in">
<h2 class="screen-heading">小测一下,然后认识角色</h2>
<div class="quiz-container" id="quiz-intro">
<div class="quiz-question-block"
data-correct="option-b"
data-explanation-right="没错。AI 只是在那个 HTML 文件里改几行 CSS 文本,把标题字号调大——这就是在'编辑文本',不是重新生成。"
data-explanation-wrong="再想想:这份 PPT 是一个文本文件。调字号不需要重跑生成器,也不用导出 pptx,只需改几行 CSS 文本。">
<h3 class="quiz-question">1. 如果想让 AI 把某页的标题字号调大,本质上是让它在做什么?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>重新运行一遍生成器,换一个更大字号的模板</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>在那份 HTML 文件里改几行 CSS,把标题字号调大</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>先导出成 .pptx,再用 PowerPoint 手动调</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="option-c"
data-explanation-right="正是。HTML/CSS 是纯文本,AI 能读、能改、能自检;pptx 是二进制压缩包,AI 看不懂。这就是'薄指令,厚技能'的根基。"
data-explanation-wrong="提示:想想 AI 能不能直接读懂文件内容。HTML 是纯文本,pptx 是打包好的二进制——后者 AI 看不懂、改不动。">
<h3 class="quiz-question">2. 为什么这个 skill 选择输出 HTML 而不是 .pptx?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>因为浏览器比 PowerPoint 更普及</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>因为 HTML 文件更小、加载更快</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>因为 HTML/CSS 是纯文本,AI 能读、能改、能自检;pptx 是二进制压缩包</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="option-b"
data-explanation-right="对。带大量 KPI 数据的工程汇报,正是瑞士风(网格 + 点阵 + 强调色)的主场。"
data-explanation-wrong="想想两种风格的定位:杂志风偏叙事,瑞士风偏数据与工程。带大量 KPI 数据的汇报,瑞士风更合适。">
<h3 class="quiz-question">3. 你要做一份 AI 产品发布、带大量 <span class="term" data-definition="KPI(关键绩效指标):衡量业务成效的核心数字,如日活、转化率、营收。">KPI</span> 数据的汇报,该选哪个风格?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>A · 电子杂志 × 电子墨水(衬线标题、流体背景)</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>B · 瑞士国际主义(全无衬线、网格 + 点阵、单一强调色)</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>两个都行,随便选</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<button class="quiz-check-btn" onclick="checkQuiz('quiz-intro')">查看答案</button>
<button class="quiz-reset-btn" onclick="resetQuiz('quiz-intro')">再做一遍</button>
</div>
<div class="callout callout-info" style="margin-top: var(--space-10);">
<div class="callout-icon">👉</div>
<div class="callout-content">
<p>那这份会做 PPT 的技能,肚子里到底装了哪些角色?<strong>下一幕,认识它们。</strong></p>
</div>
</div>
</section>
</div>
</div>
</section>
<section class="module" id="module-2" style="background: var(--color-bg)">
<div class="module-content">
<header class="module-header animate-in">
<span class="module-number">02</span>
<h1 class="module-title">认识角色</h1>
<p class="module-subtitle">一份会做 PPT 的技能,其实就是一个小剧组——每个文件都有自己的戏份。</p>
</header>
<div class="module-body">
<!-- ───────── SCREEN 1 — 开场:剧组隐喻 + Thin Harness ───────── -->
<section class="screen animate-in">
<h2 class="screen-heading">把这份技能想成一个小剧组</h2>
<p>541 行的 <code>SKILL.md</code> 是导演的拍摄清单——它从不上镜,只负责调度。两个 <code>template*.html</code> 是搭好的摄影棚,<code>references/</code> 是剧组的活页夹,<code>assets/</code> 是道具车。</p>
<div class="icon-rows">
<div class="icon-row">
<div class="icon-circle" style="background: var(--color-actor-2)">🎬</div>
<div>
<strong>SKILL.md · 导演</strong>
<p>写好拍摄清单(六步流程),自己不上镜,只调度</p>
</div>
</div>
<div class="icon-row">
<div class="icon-circle" style="background: var(--color-actor-3)">🎥</div>
<div>
<strong>template*.html · 摄影棚</strong>
<p>灯光、机位、字体都搭好的现成片场,开机即拍</p>
</div>
</div>
<div class="icon-row">
<div class="icon-circle" style="background: var(--color-actor-5)">🧐</div>
<div>
<strong>validate-swiss-deck.mjs · 场记</strong>
<p>逐镜头核对,违反版式规则的镜头一律打回</p>
</div>
</div>
</div>
<div class="callout callout-accent">
<div class="callout-icon">💡</div>
<div class="callout-content">
<strong class="callout-title">Aha — Thin Harness, Fat Skills(薄指令,厚素材)</strong>
<p>指令(SKILL.md)故意写得很"薄",只说"做什么";真正的素材(CSS、版式、组件)全部"厚厚地"放在 <code>assets/</code> 和 <code>references/</code>。把指令和素材分开,AI 不用每次重造轮子,只需从现成零件拼装——这就是稳定输出的来源。</p>
</div>
</div>
</section>
<!-- ───────── SCREEN 2 — 主视觉:完整目录树(Snippet 2A verbatim) ───────── -->
<section class="screen animate-in">
<h2 class="screen-heading">全体演员一张图:<code>guizang-ppt-skill/</code> 目录</h2>
<p>这就是整个剧组的演员表。每个文件、每个文件夹后面跟着它的角色——记住这些名字,你就能精确指挥 AI。</p>
<div class="file-tree">
<div class="ft-folder open">
<span class="ft-name">guizang-ppt-skill/</span>
<span class="ft-desc">整个剧组</span>
<div class="ft-children">
<div class="ft-file">
<span class="ft-name">SKILL.md</span>
<span class="ft-desc">← 你正在读(the director,541 行指令)</span>
</div>
<div class="ft-folder open">
<span class="ft-name">assets/</span>
<span class="ft-desc">← 道具车:预先做好的素材</span>
<div class="ft-children">
<div class="ft-file">
<span class="ft-name">template.html</span>
<span class="ft-desc">← 风格 A · 电子杂志风<span class="term" data-definition="Seed file(种子文件)就像一颗已经发芽的种子——它不是空白模板,而是一份完整、可直接运行的作品,AI 只要在指定位置追加新内容就能生成最终成品。">模板(种子文件)</span></span>
</div>
<div class="ft-file">
<span class="ft-name">template-swiss.html</span>
<span class="ft-desc">← 风格 B · 瑞士国际主义风模板(种子文件)</span>
</div>
<div class="ft-folder">
<span class="ft-name">screenshot-backgrounds/</span>
<span class="ft-desc">← 截图美化内置背景(<span class="term" data-definition="WebP 是 Google 推出的一种现代图片格式,文件比 JPG/PNG 小很多但画质相同——非常适合做截图美化的背景图。">WebP</span>)</span>
</div>
<div class="ft-file">
<span class="ft-name">motion.min.js</span>
<span class="ft-desc">← Motion One 库的本地副本(<span class="term" data-definition="Library(代码库)是别人写好的、可复用的功能集合。Motion One 是一个让 HTML 元素平滑动画的库,你不用自己写动画代码。">library</span> 离线<span class="term" data-definition="Fallback(兜底方案)是当主路径失败时的备用方案。比如 motion.min.js 是 Motion One 动画库的本地副本——联网时用在线版,断网时自动回退到本地,确保动画永远不会失效。">兜底</span>,约 64KB)</span>
</div>
</div>
</div>
<div class="ft-folder open">
<span class="ft-name">scripts/</span>
<span class="ft-desc">← 质检流程</span>
<div class="ft-children">
<div class="ft-file">
<span class="ft-name">validate-swiss-deck.mjs</span>
<span class="ft-desc">← 风格 B 静态校验:<span class="term" data-definition="Validator(校验器)是一个自动检查代码是否符合规则的小程序——它会拒绝任何违反版式规则的 Swiss 风格 deck。">validator</span> 跑在 <span class="term" data-definition="Node.js 是一种让 JavaScript 能在电脑上直接运行的环境(而不只是在浏览器里)。这个 validator 是一个 Node 脚本,意味着你需要先装好 Node 才能运行它。">Node</span> 上,登记版式、图片槽位</span>
</div>
</div>
</div>
<div class="ft-folder open">
<span class="ft-name">references/</span>
<span class="ft-desc">← 剧组活页夹:规则与手册</span>
<div class="ft-children">
<div class="ft-file">
<span class="ft-name">components.md</span>
<span class="ft-desc">← 组件手册</span>
</div>
<div class="ft-file">
<span class="ft-name">layouts.md</span>
<span class="ft-desc">← 风格 A · 10 种页面布局骨架</span>
</div>
<div class="ft-file">
<span class="ft-name">layouts-swiss.md</span>
<span class="ft-desc">← 风格 B · 原始 22P 骨架说明</span>
</div>
<div class="ft-file">
<span class="ft-name">themes.md</span>
<span class="ft-desc">← 风格 A · 5 套主题色预设(只能选不能自定义)</span>
</div>
<div class="ft-file">
<span class="ft-name">themes-swiss.md</span>
<span class="ft-desc">← 风格 B · 4 套瑞士风主题色预设</span>
</div>
<div class="ft-file">
<span class="ft-name">checklist.md</span>
<span class="ft-desc">← 质量检查清单(P0/P1/P2/P3 分级)</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- ───────── SCREEN 3 — 五位主要角色(pattern cards + actor colors) ───────── -->
<section class="screen animate-in">
<h2 class="screen-heading">五位主要角色</h2>
<p>每个角色用一种颜色代表——这套配色在本课程后续模块中会一直保持一致。</p>
<div class="pattern-cards">
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-2)">
<div class="pattern-icon" style="background: var(--color-actor-2)">🎬</div>
<h4 class="pattern-title">SKILL.md</h4>
<p class="pattern-desc">导演。541 行的<span class="term" data-definition="Template(模板)是一份预先做好的「半成品」——结构、样式、字体、动画都已就位,你只要把内容填进去就能得到成品。">调度手册</span>:六步流程、两种风格的区别、易错点。AI 第一个读的就是它。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-3)">
<div class="pattern-icon" style="background: var(--color-actor-3)">🎥</div>
<h4 class="pattern-title">template.html / template-swiss.html</h4>
<p class="pattern-desc">两座<span class="term" data-definition="摄影棚——灯光、机位、字体、动画全都搭好的现成片场,开机即拍,不用临时搭景。">摄影棚</span>。CSS、<span class="term" data-definition="WebGL 是浏览器内置的 3D/2D 渲染引擎,可让网页直接调用显卡做出复杂视觉效果。Shader(着色器)是它内部逐像素计算颜色的小程序。">WebGL shader</span>、分页 JS 都已就位,只留一个 <code><!-- SLIDES_HERE --></code> <span class="term" data-definition="Placeholder(占位符)是模板里标记好的「洞」,告诉 AI 在这里插入内容。比如 <!-- SLIDES_HERE --> 就是「在这里放生成的幻灯片」。">占位符</span>等 AI 填内容。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-4)">
<div class="pattern-icon" style="background: var(--color-actor-4)">📚</div>
<h4 class="pattern-title">references/</h4>
<p class="pattern-desc">剧组活页夹:版式骨架(layouts)、主题色预设(themes)、组件手册(components)、质量清单(checklist)。需要时翻一翻。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">🚚</div>
<h4 class="pattern-title">assets/</h4>
<p class="pattern-desc">道具车:两个种子模板、Motion One 动画库的本地副本、9 套截图美化背景。开拍前把道具搬到片场。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-5)">
<div class="pattern-icon" style="background: var(--color-actor-5)">🧐</div>
<h4 class="pattern-title">scripts/validate-swiss-deck.mjs</h4>
<p class="pattern-desc">场记/质检员。用 <span class="term" data-definition="Regex(正则表达式)是一种描述文本模式的微型语言,比如「找到所有以 .h- 开头的单词」。Validator 用它扫描 HTML,确认版式 class 是否符合规则——模块 6 会深入讲。">regex</span> 扫描 deck,任何违反版式规则的 Swiss 幻灯片都会被打回。</p>
</div>
</div>
</section>
<!-- ───────── SCREEN 4 — 两种风格不能混用(Snippet 2B verbatim) ───────── -->
<section class="screen animate-in">
<h2 class="screen-heading">为什么有两个 template?因为风格 A 和 B 不能混用</h2>
<p>下面这段是 <code>SKILL.md</code> 原文,逐句解读在右边:</p>
<div class="translation-block animate-in">
<div class="translation-code">
<span class="translation-label">SKILL.md 原文</span>
<pre><code>注意:风格 A 和 B 不能混用。layouts.md 里的类(如 .h-hero 衬线大标题)
只在 template.html 有定义;layouts-swiss.md 里的类(如 .kpi-hero、
.span-N、.dots 等)只在 template-swiss.html 有定义。一份 deck 只能选一套。</code></pre>
</div>
<div class="translation-english">
<span class="translation-label">逐句解读</span>
<div class="translation-lines">
<p class="tl"><strong>两种风格不能混用</strong>——同一份 deck(演示文稿)只能选风格 A 或风格 B 中的一个。</p>
<p class="tl"><strong>为什么?</strong>每个 <span class="term" data-definition="Class(类名)是 HTML 元素的「标签」,CSS 通过它知道「这个元素长什么样」。比如 <div class='h-hero'> 表示这是一个英雄大标题。">class</span> 只在对应模板的 <code><style></code> 块里定义过。</p>
<p class="tl">如果你在风格 A 的 deck 里用 <code>.kpi-hero</code>,浏览器找不到它的样式定义——元素就会"裸奔"。</p>
<p class="tl"><strong>实操结论</strong>:加新版式时,必须同步改"模板 + 对应 layouts 文件",两边都要更新。</p>
</div>
</div>
</div>
<div class="callout callout-warning">
<div class="callout-icon">⚠️</div>
<div class="callout-content">
<strong class="callout-title">常见踩坑</strong>
<p>很多人以为"在 layouts.md 里写一段说明就够了"。不够。如果对应的 <code>template.html</code> 的 <code><style></code> 块里没有这个 class 的定义,AI 写出来的 <code><div class="h-timeline"></code> 就是没样式的空壳。</p>
</div>
</div>
</section>
<!-- ───────── SCREEN 5 — 拖拽匹配 ───────── -->
<section class="screen animate-in">
<h2 class="screen-heading">把文件和它的角色配对</h2>
<p>把左侧的演员卡拖到右侧对应的角色描述上(手机端可以点按拖动)。</p>
<div class="dnd-container" id="dnd-cast">
<div class="dnd-chips">
<div class="dnd-chip" draggable="true" data-answer="skill-md">SKILL.md</div>
<div class="dnd-chip" draggable="true" data-answer="template-html">template.html</div>
<div class="dnd-chip" draggable="true" data-answer="references">references/</div>
<div class="dnd-chip" draggable="true" data-answer="validator-mjs">validate-swiss-deck.mjs</div>
<div class="dnd-chip" draggable="true" data-answer="motion-min-js">assets/motion.min.js</div>
</div>
<div class="dnd-zones">
<div class="dnd-zone" data-correct="skill-md">
<p class="dnd-zone-label">调度整个工作流,自己从不上镜</p>
<div class="dnd-zone-target">Drop here</div>
</div>
<div class="dnd-zone" data-correct="template-html">
<p class="dnd-zone-label">一份完整可运行的风格 A 画布,留了 SLIDES_HERE 的洞</p>
<div class="dnd-zone-target">Drop here</div>
</div>
<div class="dnd-zone" data-correct="references">
<p class="dnd-zone-label">装着版式、主题、组件、清单的活页夹</p>
<div class="dnd-zone-target">Drop here</div>
</div>
<div class="dnd-zone" data-correct="validator-mjs">
<p class="dnd-zone-label">驳回任何违反版式规则的 Swiss 幻灯片的质检员</p>
<div class="dnd-zone-target">Drop here</div>
</div>
<div class="dnd-zone" data-correct="motion-min-js">
<p class="dnd-zone-label">断网也能让幻灯片动起来的离线动画兜底</p>
<div class="dnd-zone-target">Drop here</div>
</div>
</div>
<button class="btn" onclick="checkDnD('dnd-cast')">检查匹配</button>
<button class="btn" onclick="resetDnD('dnd-cast')">重置</button>
</div>
</section>
<!-- ───────── SCREEN 6 — 小测验 + 收尾 ───────── -->
<section class="screen animate-in">
<h2 class="screen-heading">小测验:你能像导演一样调度吗?</h2>
<div class="quiz-container" id="quiz-cast">
<div class="quiz-question-block"
data-correct="q1-b"
data-explanation-right="对。SKILL.md 是 AI 的「入口手册」——六步流程、两种风格、易错点都在这里。读完它,AI 才知道该去翻哪些文件。"
data-explanation-wrong="再想想:AI 需要先知道「整套流程怎么走、有哪些风格可选」,然后才能开始。这份总览写在哪里?">
<h3 class="quiz-question">用户说「生成一份风格 A 的 deck」。AI 拿到指令后,第一个要打开的文件是哪个?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="q1-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>template.html——它是种子文件,必须先看</span>
</button>
<button class="quiz-option" data-value="q1-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>SKILL.md——它告诉 AI 整个六步流程、两种风格的区别、易错点</span>
</button>
<button class="quiz-option" data-value="q1-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>checklist.md——必须先看质量标准</span>
</button>
<button class="quiz-option" data-value="q1-d" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>validate-swiss-deck.mjs——必须先跑校验</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="q2-b"
data-explanation-right="完全正确。这正是「class 必须在 template 里定义过」的意思——layouts.md 是说明书,template.html 的 <style> 块才是 class 真正生效的地方。两个文件缺一不可。"
data-explanation-wrong="差一步。layouts.md 里写的只是「说明」,而真正让 .h-timeline 在浏览器里长出样子的,是 template.html 里 <style> 块的 CSS 定义。说明书和样式表必须同步。">
<h3 class="quiz-question">你想给风格 A 加一种全新的版式(叫 <code>.h-timeline</code>)。光在 layouts.md 里写说明够不够?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="q2-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>够了——layouts.md 是 AI 唯一读的文件</span>
</button>
<button class="quiz-option" data-value="q2-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>不够——必须同时在 template.html 的 <style> 块里定义这个 class,否则渲染时找不到样式</span>
</button>
<button class="quiz-option" data-value="q2-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>不够——必须把整个 SKILL.md 重写一遍</span>
</button>
<button class="quiz-option" data-value="q2-d" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>够了——AI 会根据 layouts.md 的描述自己推断出 CSS</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="q3-b"
data-explanation-right="对。这就是「Thin Harness, Fat Skills」——指令薄、素材厚。AI 编辑文字很容易,但要它每次从零生成一套设计系统却很难。把设计系统放进模板里复用,比让 AI 重新发明可靠得多。"
data-explanation-wrong="换个角度:AI 写文字(说明书)很在行,但每次让它从头生成一套完整 CSS + 字体 + 动画的设计系统,结果会很不可靠。把这部分「厚素材」放进模板,让 AI 只做它擅长的「调度」工作——这才是稳定的来源。">
<h3 class="quiz-question">为什么 SKILL.md 不直接把所有 CSS、所有布局代码都写在里面,而要让 template.html 和 references/ 去分担?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="q3-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>因为 SKILL.md 装不下那么多内容</span>
</button>
<button class="quiz-option" data-value="q3-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>因为这是「薄指令、厚素材」的架构——把"怎么做"和"用什么"分开,AI 只需调度,不用每次重造,输出才稳定</span>
</button>
<button class="quiz-option" data-value="q3-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>因为 Claude 不能读超过 500 行的文件</span>
</button>
<button class="quiz-option" data-value="q3-d" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>因为 references/ 文件夹是后来加的,还没合并进 SKILL.md</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<button class="quiz-check-btn" onclick="checkQuiz('quiz-cast')">检查答案</button>
<button class="quiz-reset-btn" onclick="resetQuiz('quiz-cast')">再做一次</button>
</div>
<p style="margin-top: var(--space-8); padding: var(--space-5) var(--space-6); background: var(--color-info-light); border-left: 3px solid var(--color-info); border-radius: var(--radius-sm); font-size: var(--text-lg);">
🎬 <strong>下一幕:</strong>认识了角色,下一幕看它们怎么按六步顺序配合——也就是 <code>SKILL.md</code> 里写好的整套工作流。
</p>
</section>
</div>
</div>
</section>
<section class="module" id="module-3" style="background: var(--color-bg-warm)">
<div class="module-content">
<header class="module-header animate-in">
<span class="module-number">03</span>
<h1 class="module-title">六步工作流</h1>
<p class="module-subtitle">从一句需求到一份可翻页的单文件 HTML,这套 skill 用一条流水线把每一步都卡死</p>
</header>
<div class="module-body">
<!-- ════════ SCREEN 1 · 开场钩子 + 裁缝隐喻 ════════ -->
<section class="screen animate-in">
<h2 class="screen-heading">为什么动手前一定要问 7 个问题?</h2>
<p>因为布料一旦剪错,整件西装就废了。这套 skill 把自己当成一位 <strong>定制裁缝</strong>——量体、裁样、缝合、染色、质检、试穿,六道工序一道都不能跳。</p>
<p>它拒绝猜测。你给它的需求先过一道 <span class="term" data-definition="关卡:流水线上的一道必经检查点——通不过就不能往下走。这里的关卡是动手前的 7 个澄清问题。">关卡</span>,然后才进入一条固定的 <span class="term" data-definition="流水线(pipeline):数据像工厂传送带一样,按固定顺序一步步流过每个工位,每一步只做一件事,上一步的输出是下一步的输入。">流水线</span>。</p>
<div class="flow-steps" style="margin-top: var(--space-8)">
<div class="flow-step">
<div class="flow-step-num" style="background: var(--color-actor-1)">1</div>
<p>澄清<br><span style="font-size:var(--text-xs);color:var(--color-text-muted)">量体</span></p>
</div>
<div class="flow-arrow">→</div>
<div class="flow-step">
<div class="flow-step-num" style="background: var(--color-actor-2)">2</div>
<p>拷贝<br><span style="font-size:var(--text-xs);color:var(--color-text-muted)">裁样</span></p>
</div>
<div class="flow-arrow">→</div>
<div class="flow-step">
<div class="flow-step-num" style="background: var(--color-actor-3)">3</div>
<p>填充<br><span style="font-size:var(--text-xs);color:var(--color-text-muted)">缝合</span></p>
</div>
<div class="flow-arrow">→</div>
<div class="flow-step">
<div class="flow-step-num" style="background: var(--color-actor-4)">4</div>
<p>主题<br><span style="font-size:var(--text-xs);color:var(--color-text-muted)">染色</span></p>
</div>
<div class="flow-arrow">→</div>
<div class="flow-step">
<div class="flow-step-num" style="background: var(--color-actor-5)">5</div>
<p>校验<br><span style="font-size:var(--text-xs);color:var(--color-text-muted)">质检</span></p>
</div>
<div class="flow-arrow">→</div>
<div class="flow-step">
<div class="flow-step-num" style="background: var(--color-actor-1)">6</div>
<p>预览<br><span style="font-size:var(--text-xs);color:var(--color-text-muted)">试穿</span></p>
</div>
</div>
</section>
<!-- ════════ SCREEN 2 · 关卡:7 个问题 + 启发式 ════════ -->
<section class="screen animate-in">
<h2 class="screen-heading">第一关:动手前先对齐 7 件事</h2>
<p>AI 最常见的翻车,是用户没说清就让它"先写写看"。这套 skill 偏不——它先把 7 个问题摆出来,逼着双方对齐。</p>
<div class="pattern-cards" style="margin-top: var(--space-6)">
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">①</div>
<h4 class="pattern-title">风格 A 还是 B?</h4>
<p class="pattern-desc">决定用哪套 template、哪些 layouts、哪些主题文件。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">②</div>
<h4 class="pattern-title">受众与场景?</h4>
<p class="pattern-desc">决定语气和讲解深度——给工程师看还是给老板看。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">③</div>
<h4 class="pattern-title">讲多长?</h4>
<p class="pattern-desc">套用 <span class="term" data-definition="启发式(heuristic):一条凭经验总结的快速估算规则——不精确,但够用。比如 15 分钟约 10 页就是一条启发式。">启发式</span>:15 分钟 ≈ 10 页。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">④</div>
<h4 class="pattern-title">有现成素材吗?</h4>
<p class="pattern-desc">有素材就基于素材搭建,没有就从零搭骨架。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">⑤</div>
<h4 class="pattern-title">图片怎么处理?</h4>
<p class="pattern-desc">决定用哪种图片版式、是否需要截图美化或重画。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">⑥</div>
<h4 class="pattern-title">哪套主题色?</h4>
<p class="pattern-desc">风格 A 有 5 套预设、风格 B 有 4 套——不准自定义颜色。</p>
</div>
<div class="pattern-card" style="border-top: 3px solid var(--color-actor-1)">
<div class="pattern-icon" style="background: var(--color-actor-1)">⑦</div>
<h4 class="pattern-title">有硬约束吗?</h4>
<p class="pattern-desc">必须包含 X、绝不能出现 Y——先讲清楚,避免返工。</p>
</div>
</div>
<div class="callout callout-accent" style="margin-top: var(--space-8)">
<div class="callout-icon">💡</div>
<div class="callout-content">
<strong class="callout-title">先对齐,再动手</strong>
<p>结构一旦定下,事后改要花 10 倍的力气。这条 skill 把"澄清"设成不可跳过的第一关,正是它产出稳定的关键——你不是在碰运气,你在导演整个过程。</p>
</div>
</div>
</section>
<!-- ════════ SCREEN 3 · 主视觉:六步流水线动画 ════════ -->
<section class="screen animate-in">
<h2 class="screen-heading">点 Next,走完整条流水线</h2>
<p>六个工位一字排开,数据包从左流到右。每个亮起的节点就是当前正在干活的工位。</p>
<div class="flow-animation" id="flow-workflow" data-steps='[
{"highlight":"flow-actor-1","label":"Step 1 · 澄清:7 个问题对齐,动手前必做"},
{"highlight":"flow-actor-1","label":"用户回答风格/受众/时长/素材/图/色/约束","packet":true,"from":"actor-1","to":"actor-2"},
{"highlight":"flow-actor-2","label":"Step 2 · 拷贝对应 template.html → index.html","packet":true,"from":"actor-2","to":"actor-3"},
{"highlight":"flow-actor-3","label":"Step 3 · 按 layouts 骨架填内容(先做预检+主题节奏)","packet":true,"from":"actor-3","to":"actor-4"},
{"highlight":"flow-actor-4","label":"Step 4 · 套一套锁定的主题色(换 6 行变量)"},
{"highlight":"flow-actor-4","label":"Step 5 · 交给校验器/检查清单","packet":true,"from":"actor-4","to":"actor-5"},
{"highlight":"flow-actor-5","label":"Step 5 · 校验通过:版式登记、左对齐、图片槽位都对"},
{"highlight":"flow-actor-5","label":"Step 6 · 浏览器打开 index.html 预览","packet":true,"from":"actor-5","to":"actor-6"},
{"highlight":"flow-actor-6","label":"完成:一份可翻页、有动效的单文件 HTML"}
]'>
<div class="flow-actors">
<div class="flow-actor" id="flow-actor-1">
<div class="flow-actor-icon" style="background: var(--color-actor-1)">1</div>
<span>澄清</span>
</div>
<div class="flow-actor" id="flow-actor-2">
<div class="flow-actor-icon" style="background: var(--color-actor-2)">2</div>
<span>拷贝</span>
</div>
<div class="flow-actor" id="flow-actor-3">
<div class="flow-actor-icon" style="background: var(--color-actor-3)">3</div>
<span>填充</span>
</div>
<div class="flow-actor" id="flow-actor-4">
<div class="flow-actor-icon" style="background: var(--color-actor-4)">4</div>
<span>主题</span>
</div>
<div class="flow-actor" id="flow-actor-5">
<div class="flow-actor-icon" style="background: var(--color-actor-5)">5</div>
<span>校验</span>
</div>
<div class="flow-actor" id="flow-actor-6">
<div class="flow-actor-icon" style="background: var(--color-actor-1)">6</div>
<span>预览</span>
</div>
</div>
<div class="flow-packet" id="flow-packet"></div>
<div class="flow-step-label" id="flow-label">点 "Next Step" 开始走流水线</div>
<div class="flow-controls">
<button class="btn flow-next-btn">Next Step</button>
<button class="btn flow-reset-btn">重新开始</button>
<span class="flow-progress"></span>
</div>
</div>
<p style="margin-top: var(--space-6); font-size: var(--text-sm); color: var(--color-text-secondary)">注意 Step 2 真正执行的命令——就是下面这一行 <code>cp</code>:</p>
<div class="translation-block animate-in" style="margin-top: var(--space-4)">
<div class="translation-code">
<span class="translation-label">SHELL</span>
<pre><code><span class="code-line"><span class="code-comment"># 风格 A · 电子杂志风</span></span><span class="code-line"><span class="code-function">cp</span> <span class="code-string">"<SKILL_ROOT>/assets/template.html"</span> <span class="code-string">"项目/XXX/ppt/index.html"</span></span><span class="code-line"></span><span class="code-line"><span class="code-comment"># 或 风格 B · 瑞士国际主义风</span></span><span class="code-line"><span class="code-function">cp</span> <span class="code-string">"<SKILL_ROOT>/assets/template-swiss.html"</span> <span class="code-string">"项目/XXX/ppt/index.html"</span></span></code></pre>
</div>
<div class="translation-english">
<span class="translation-label">解读</span>
<div class="translation-lines">
<p class="tl">选定风格后,把对应的模板文件原封不动拷一份,重命名成 <code>index.html</code>——这就是你的裁样。</p>
<p class="tl">之后所有填充、染色都在这份拷贝上做,绝不碰原始模板。</p>
</div>
</div>
</div>
</section>
<!-- ════════ SCREEN 4 · 六步卡片(每步的 WHY) ════════ -->
<section class="screen animate-in">
<h2 class="screen-heading">六道工序,每步都在防一种翻车</h2>
<p>对照裁缝的隐喻看,每一步的存在都是为了堵住一个具体漏洞。</p>
<div class="step-cards" style="margin-top: var(--space-6)">
<div class="step-card">
<div class="step-num" style="background: var(--color-actor-1)">1</div>
<div class="step-body">
<strong>澄清 · 量体</strong>
<p>动手前必问 7 个问题。量错一寸,整件西装报废——这是不可跳过的关卡。</p>
</div>
</div>
<div class="step-card">
<div class="step-num" style="background: var(--color-actor-2)">2</div>
<div class="step-body">
<strong>拷贝 · 裁样</strong>
<p>选定风格 A 或 B,把对应 <code>template.html</code> 拷成 <code>index.html</code>,再建 <code>images/</code> 文件夹。</p>
</div>
</div>
<div class="step-card">
<div class="step-num" style="background: var(--color-actor-3)">3</div>
<div class="step-body">
<strong>填充 · 缝合</strong>
<p>先排主题节奏,再按 layouts 骨架粘贴改写。每个 class 都得在登记表里——没登记的版式不许用。</p>
</div>
</div>
<div class="step-card">
<div class="step-num" style="background: var(--color-actor-4)">4</div>
<div class="step-body">
<strong>主题 · 染色</strong>
<p>从锁定预设里选一套,整体替换 6 行 <span class="term" data-definition="CSS 变量(CSS variable):给一个值起名字(如 --ink),之后整份样式表都引用这个名字;改一处,所有引用它的地方一起变。">CSS 变量</span>——一桶染料染遍全身。</p>
</div>
</div>
<div class="step-card">
<div class="step-num" style="background: var(--color-actor-5)">5</div>
<div class="step-body">
<strong>校验 · 质检</strong>
<p>跑检查清单:版式是否登记、是否左对齐、图片槽位是否对齐。任何一条不过就回去修。</p>
</div>
</div>
<div class="step-card">
<div class="step-num" style="background: var(--color-actor-1)">6</div>
<div class="step-body">
<strong>预览 · 试穿</strong>
<p>浏览器打开 <code>index.html</code>。要微调就用 <span class="term" data-definition="内联样式(inline style):直接写在 HTML 标签 style 属性里的样式,优先级最高,只影响这一个元素——适合临时微调。">inline style</span>,图片靠 <span class="term" data-definition="aspect-ratio:CSS 属性,用一个比例(如 16/9)锁定元素的宽高比,图片因此不会变形。">aspect-ratio</span> 锁比不变形。</p>
</div>
</div>
</div>
</section>
<!-- ════════ SCREEN 5 · 主题换色:代码 ↔ 解读 ════════ -->
<section class="screen animate-in">
<h2 class="screen-heading">换主题=换 6 行变量</h2>
<p>整份演示文稿的 mood,全压在这 6 行里。改这里,其他 CSS 自动跟着变——这就是"一桶染料染遍全身"。</p>
<div class="translation-block animate-in" style="margin-top: var(--space-6)">
<div class="translation-code">
<span class="translation-label">CSS</span>
<pre><code><span class="code-line"><span class="code-tag">:root</span>{</span><span class="code-line"> <span class="code-property">--ink</span>:<span class="code-string">#0a0a0b</span>;</span><span class="code-line"> <span class="code-property">--ink-rgb</span>:<span class="code-number">10,10,11</span>;</span><span class="code-line"> <span class="code-property">--paper</span>:<span class="code-string">#f1efea</span>;</span><span class="code-line"> <span class="code-property">--paper-rgb</span>:<span class="code-number">241,239,234</span>;</span><span class="code-line"> <span class="code-property">--paper-tint</span>:<span class="code-string">#e8e5de</span>;</span><span class="code-line"> <span class="code-property">--ink-tint</span>:<span class="code-string">#18181a</span>;</span><span class="code-line">}</span></code></pre>
</div>
<div class="translation-english">
<span class="translation-label">解读</span>
<div class="translation-lines">
<p class="tl"><code>--ink</code> 是墨水色(文字 / 深底),<code>--paper</code> 是纸色(浅底 / 背景)。</p>
<p class="tl"><code>--ink-rgb</code> 是同一颜色的 RGB 版,给半透明遮罩用。</p>
<p class="tl">换主题就是整体替换这几行;其他 CSS 全走 <code>var(--...)</code> 自动跟着变。</p>
<p class="tl">这里的 <span class="term" data-definition="十六进制色值(hex):用 # 开头的 6 位数字表示一个颜色,比如 #0a0a0b 是近黑色。浏览器靠它精确还原颜色。">hex</span> 值都是预先调过的——所以 skill 不让你自定义颜色。</p>
</div>
</div>
</div>
</section>
<!-- ════════ SCREEN 6 · 测验 + 收尾交接 ════════ -->
<section class="screen animate-in">
<h2 class="screen-heading">走一遍,看看你能不能导演这条流水线</h2>
<div class="quiz-container" id="quiz-workflow" style="margin-top: var(--space-6)">
<div class="quiz-question-block"
data-correct="option-b"
data-explanation-right="完全正确。风格、篇幅、受众全靠猜,返工成本极高——这正是 skill 用 7 个问题关卡拦住的原因。"
data-explanation-wrong="不太对。想想如果连受众和时长都没定,AI 会朝哪个方向猜?这套 skill 明令禁止跳过澄清直接开写。">
<h3 class="quiz-question">用户只丢一句"做个 PPT"就跑了,AI 直接开写。最可能出什么问题?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>没问题,AI 最擅长即兴发挥</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>风格 / 篇幅 / 受众全可能猜错,返工成本极高</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>只会慢一点,结果差不多</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="option-b"
data-explanation-right="没错!因为所有颜色都走 CSS 变量,换 6 行 :root 就能把整套演示换一种 mood。这就是变量系统的威力。"
data-explanation-wrong="再想想。整套演示的颜色并不是逐页写死的——它们都引用同一组变量。改源头,还是改每一处?">
<h3 class="quiz-question">想把主题从"墨水经典"换成"靛蓝瓷",要改多少处颜色?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>每一页都要手动改</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>改 6 行 :root 变量就够了</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>要重写整个 CSS 文件</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="option-c"
data-explanation-right="对。按启发式 30 分钟 ≈ 20 页,正好落在中段。这种经验法则让你快速估出骨架规模。"
data-explanation-wrong="差一点。回忆那条启发式:15 分钟 ≈ 10 页,30 分钟 ≈ 20 页,45 分钟 ≈ 25–30 页——30 分钟对应哪个区间?">
<h3 class="quiz-question">一场 30 分钟的分享,按启发式大约该做多少页?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>约 10 页</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>约 15 页</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>约 20 页</span>
</button>
<button class="quiz-option" data-value="option-d" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>
<span>约 40 页</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<div class="quiz-question-block"
data-correct="option-b"
data-explanation-right="正是如此。预设的 hex 都是精心调过的搭配;放开自定义就会破坏整套视觉系统。约束即质量。"
data-explanation-wrong="不完全是。技术上当然能写任意颜色——但这条限制是有意为之。想想不受约束的自定义色会怎样冲击一套调好的视觉系统?">
<h3 class="quiz-question">为什么这套 skill 不允许自定义主题颜色?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div>