chem-pdf2ppt 2.0.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.
package/SKILL_EN.md ADDED
@@ -0,0 +1,473 @@
1
+ ---
2
+ name: pdf-to-ppt
3
+ description: Convert chemistry (experimental or theoretical/computational) academic paper PDFs into professional academic PowerPoint presentations. Automatically identifies paper type (experimental/theoretical/hybrid), extracts key information, and generates structured PPTX files ready for group meetings, defenses, and academic reports. Trigger when the user mentions "paper to PPT", "PDF to PPT", "group meeting slides", "journal club", "academic presentation", "chemistry paper PPT", or provides a chemistry-related PDF/arXiv paper asking for presentation generation.
4
+ ---
5
+
6
+ # PDF → Chemistry Academic PPT Generator
7
+
8
+ Convert chemistry academic paper PDFs into professional, ready-to-use academic PowerPoint presentations.
9
+
10
+ ## Core Principles
11
+
12
+ **Let the paper's scientific argument drive the PPT structure, not a fixed template.**
13
+
14
+ Chemistry papers fall into two primary paradigms with fundamentally different narrative logic:
15
+
16
+ - **Experimental Chemistry**: Problem → Design Strategy → Synthesis/Preparation → Characterization → Performance → Mechanism → Conclusions
17
+ - **Theoretical/Computational Chemistry**: Problem → Methods → Model Validation → Electronic Structure/Energy Analysis → Mechanism → Experimental Comparison → Conclusions
18
+ - **Experimental + Theoretical Hybrid**: Problem → Experimental Part → Computational Part → Cross-Validation → Unified Mechanism → Conclusions
19
+
20
+ The generated PPT should guide the audience through:
21
+ 1. Why is this chemistry problem important?
22
+ 2. What has been achieved, what is the bottleneck?
23
+ 3. What is the design strategy / computational approach?
24
+ 4. What is the key experimental evidence / computational result?
25
+ 5. Is the mechanistic explanation self-consistent?
26
+ 6. What new understanding has been gained? Is it generalizable?
27
+ 7. What are the limitations and open questions?
28
+
29
+ ## Input Formats
30
+
31
+ Any of the following are accepted:
32
+ - Full paper PDF
33
+ - arXiv / chemRxiv preprint PDF
34
+ - Abstract + figures + results text
35
+ - Structured reading notes
36
+ - User-pasted paper content
37
+
38
+ Default output language is Chinese; preserve key chemical terminology, abbreviations, compound names, and method names in English.
39
+
40
+ ## Workflow
41
+
42
+ ### Step 0: Install Dependencies (first use)
43
+
44
+ ```bash
45
+ pip install -r <SKILL_ROOT>/requirements.txt
46
+ ```
47
+
48
+ ### Step 1: Read and Understand the Paper
49
+
50
+ Use PyMuPDF (fitz) to extract full text:
51
+
52
+ ```python
53
+ import fitz
54
+ doc = fitz.open("paper.pdf")
55
+ full_text = ""
56
+ for page in doc:
57
+ full_text += page.get_text()
58
+ ```
59
+
60
+ Identify the following key information from the full text:
61
+ - **Title, authors, journal, year, DOI**
62
+ - **Paper chemistry type**: Experimental / Computational / Hybrid
63
+ - **Core chemistry problem**: catalysis, synthesis, materials, energy, environment, pharmaceuticals, mechanism, etc.
64
+ - **Research gap**: limitations of prior work
65
+ - **Core claim/hypothesis**
66
+ - **Key methods**:
67
+ - Experimental: synthesis routes, catalyst preparation, characterization techniques (XRD, TEM, SEM, XPS, BET, NMR, IR, Raman, EPR, XAS, etc.), performance testing conditions
68
+ - Computational: level of theory (DFT functional, basis set), software (VASP, Gaussian, CP2K, QE, etc.), model systems, free energy methods
69
+ - **Key results**: performance data, characterization conclusions, energy data, selectivity/conversion/yield, TOF, stability
70
+ - **Key figures**: Figure numbers and content summaries
71
+ - **Mechanism / structure-property relationships**
72
+ - **Innovations and limitations**
73
+
74
+ **Important**: Do not fabricate data, mechanisms, or figure details not present in the paper. Mark uncertain information as "[TBD]".
75
+
76
+ ### Step 2: Classify Paper Type and Select Narrative Arc
77
+
78
+ #### Type A: Experimental Chemistry
79
+ **Signals**: synthesis steps, wet chemistry methods, materials preparation, catalyst testing, characterization data (XRD/TEM/SEM/XPS), performance metrics (conversion/selectivity/yield/stability)
80
+
81
+ **Narrative arc** (question-to-evidence):
82
+ 1. Chemical problem and significance
83
+ 2. Prior strategy limitations → This work's design rationale
84
+ 3. Synthesis/preparation route
85
+ 4. Structure and composition characterization
86
+ 5. Catalytic/performance evaluation
87
+ 6. Mechanistic investigation (in-situ characterization, control experiments, kinetics)
88
+ 7. Structure-activity relationships
89
+ 8. Conclusions and outlook
90
+
91
+ **PPT structure** (12–16 slides):
92
+ ```
93
+ Slide 1: Title
94
+ Slide 2: Background & chemical problem
95
+ Slide 3: Prior work & bottlenecks
96
+ Slide 4: Design strategy
97
+ Slide 5: Synthesis/preparation route
98
+ Slide 6: Structure & composition (XRD/TEM/XPS...)
99
+ Slide 7: Morphology & microstructure (SEM/TEM/HRTEM...)
100
+ Slide 8: Performance evaluation
101
+ Slide 9: Key control experiments or comparison table
102
+ Slide 10: Mechanism (in-situ / kinetics / poisoning...)
103
+ Slide 11: Structure-activity / active site discussion
104
+ Slide 12: Benchmark comparison
105
+ Slide 13: Summary & innovations
106
+ Slide 14: Limitations & outlook
107
+ ```
108
+
109
+ #### Type B: Theoretical/Computational Chemistry
110
+ **Signals**: DFT calculations, molecular dynamics, Monte Carlo, electronic structure, reaction path search, free energy calculations, software names (VASP/Gaussian/CP2K/QE/GROMACS), k-point/cutoff energy
111
+
112
+ **Narrative arc** (method-to-mechanism):
113
+ 1. Chemical problem and need for computation
114
+ 2. Limitations of prior computational studies
115
+ 3. Computational methods and model systems
116
+ 4. Method validation / benchmarking
117
+ 5. Electronic structure / adsorption / reaction intermediates
118
+ 6. Energy profiles and reaction pathways
119
+ 7. Selectivity origins / rate-determining step analysis
120
+ 8. Comparison with experiment (if available)
121
+ 9. Conclusions and outlook
122
+
123
+ **PPT structure** (12–16 slides):
124
+ ```
125
+ Slide 1: Title
126
+ Slide 2: Background & chemical problem
127
+ Slide 3: Prior computational studies
128
+ Slide 4: Computational methods & models
129
+ Slide 5: Method validation / benchmarking
130
+ Slide 6: Key intermediate / transition state structures
131
+ Slide 7: Energy profiles / free energy diagrams
132
+ Slide 8: Electronic structure analysis (PDOS/Bader/COHP...)
133
+ Slide 9: Selectivity analysis
134
+ Slide 10: Microkinetics / volcano plot (if applicable)
135
+ Slide 11: Comparison with experiment (if applicable)
136
+ Slide 12: Summary & innovations
137
+ Slide 13: Limitations & outlook
138
+ ```
139
+
140
+ #### Type C: Experimental + Theoretical Hybrid
141
+ **Narrative arc** (experiment-theory-unified):
142
+ 1. Chemical problem and joint strategy
143
+ 2. Experimental: synthesis + characterization + performance
144
+ 3. Computational: model + method + results
145
+ 4. Experiment-theory cross-validation
146
+ 5. Unified mechanistic model
147
+ 6. Conclusions
148
+
149
+ **PPT structure** (14–18 slides):
150
+ ```
151
+ Slide 1: Title
152
+ Slide 2: Background & chemical problem
153
+ Slide 3: Research strategy (experimental + computational)
154
+ Slide 4: Experimental: synthesis & characterization
155
+ Slide 5: Experimental: performance / catalytic results
156
+ Slide 6: Experimental: key characterization evidence
157
+ Slide 7: Computational: methods & models
158
+ Slide 8: Computational: energetics & electronic structure
159
+ Slide 9: Computational: reaction pathways / mechanism
160
+ Slide 10: Experiment-theory cross-validation
161
+ Slide 11: Unified mechanism model
162
+ Slide 12: Summary & outlook
163
+ ```
164
+
165
+ ### Step 3: Extract Figures
166
+
167
+ Use `scripts/extract_charts.py` for multi-strategy figure extraction:
168
+
169
+ ```bash
170
+ python <SKILL_ROOT>/scripts/extract_charts.py paper.pdf output/figures 300 --report
171
+ ```
172
+
173
+ This automatically:
174
+ 1. Extracts vector graphics using `cluster_drawings()` (PyMuPDF ≥1.23) or `get_drawings()` with manual clustering (PyMuPDF 1.19+)
175
+ 2. Extracts embedded bitmap images
176
+ 3. Falls back to full-page rendering if insufficient figures found
177
+ 4. Tries multiple tolerance parameters when default clustering fails
178
+ 5. Generates `extraction_report.json` summarizing all extraction results
179
+
180
+ Then map extracted figures to paper Figure numbers by checking page numbers and order.
181
+
182
+ **Figure selection principles**:
183
+ - Select only figures that support the paper's argument (typically 4–8)
184
+ - Priority: strategy/scheme diagram → core results → mechanism → validation/controls
185
+ - Fewer, clearer figures are better than many crowded ones
186
+
187
+ ### Step 4: Write Slide-by-Slide Content
188
+
189
+ For each slide, prepare:
190
+ - **Title** (conclusion-style: "Ru SAs achieve 98% CO conversion at 300°C" not just "Catalytic Performance")
191
+ - **3–4 bullet points** (concise)
192
+ - **Associated figure** (Figure number and file path)
193
+ - **Figure caption** (short interpretation)
194
+ - **One core takeaway**
195
+ - **Speaker notes** (optional oral commentary)
196
+
197
+ Each slide should convey ONE core message. Result slides should prioritize figures — let the data speak.
198
+
199
+ ### Step 5: Build PPTX
200
+
201
+ Use `scripts/create_ppt.py`:
202
+
203
+ ```python
204
+ import sys
205
+ sys.path.insert(0, '<SKILL_ROOT>/scripts')
206
+ from create_ppt import ChemistryPPT
207
+
208
+ ppt = ChemistryPPT(theme="academic") # "academic" | "dark" | "nature"
209
+
210
+ ppt.add_title_slide(
211
+ title_cn="中文标题",
212
+ title_en="English Title",
213
+ authors="Authors et al.",
214
+ journal="J. Am. Chem. Soc., 2024, 146, xxx",
215
+ doi="10.xxxx/xxxx"
216
+ )
217
+
218
+ ppt.add_section_slide("Part 1: Research Background")
219
+
220
+ ppt.add_content_slide(
221
+ title="Core Challenge in Electrocatalytic CO₂ Reduction",
222
+ bullets=[
223
+ "CO₂RR produces a wide range of products (CO, HCOOH, CH₄, C₂H₄, EtOH...) — selectivity control is difficult",
224
+ "Cu-based catalysts are the only metals capable of C₂₊ products, but FE is typically < 50%",
225
+ "Key bottleneck: simultaneous optimization of *CO binding energy and C-C coupling kinetics"
226
+ ],
227
+ notes="Emphasize the uniqueness of Cu and the selectivity challenge"
228
+ )
229
+
230
+ ppt.add_figure_slide(
231
+ title="HAADF-STEM Confirms Single-Atom Ru Dispersion on Cu Surface",
232
+ figure_path="output/figures/p3_fig1.png",
233
+ figure_label="Figure 1",
234
+ bullets=[
235
+ "HAADF-STEM shows Ru atoms (bright dots) uniformly dispersed — no NPs or clusters",
236
+ "EDS elemental mapping confirms uniform Ru distribution on Cu matrix",
237
+ "XANES indicates Ruᵟ⁺ oxidation state (0 < δ < 3)"
238
+ ],
239
+ caption="Source: Fig. 1a-c, adapted from original paper",
240
+ layout="figure_right" # "figure_right" | "figure_top" | "figure_full"
241
+ )
242
+
243
+ ppt.add_table_slide(
244
+ title="Catalytic Performance Comparison",
245
+ headers=["Catalyst", "FE(C₂₊)%", "j (mA/cm²)", "Stability (h)", "Ref"],
246
+ rows=[
247
+ ["Ru₁/Cu", "82%", "300", "100", "This work"],
248
+ ["Cu NPs", "45%", "150", "20", "Nat. Catal. 2020"],
249
+ ["Ag/Cu", "60%", "200", "50", "JACS 2022"],
250
+ ]
251
+ )
252
+
253
+ ppt.add_summary_slide(
254
+ title="Summary & Outlook",
255
+ bullets=[
256
+ "First demonstration of Ru SAC alloy for highly selective CO₂-to-C₂₊ conversion (FE 82%)",
257
+ "Operando XAS + DFT reveal Ru sites promote *CO enrichment and C-C coupling",
258
+ "Design strategy extensible to other SAC systems (Pt/Cu, Pd/Cu)",
259
+ "Future: MEA testing under practical conditions"
260
+ ]
261
+ )
262
+
263
+ ppt.save("output/presentation.pptx")
264
+ ppt.save_report("output/presentation.pptx") # JSON build report
265
+ ```
266
+
267
+ **Slide type reference**:
268
+
269
+ | Method | Purpose |
270
+ |--------|---------|
271
+ | `add_title_slide()` | Cover: bilingual title, authors, journal info |
272
+ | `add_section_slide()` | Section divider |
273
+ | `add_content_slide()` | Text content with bullets and optional subtitle |
274
+ | `add_figure_slide()` | Figure + explanation (4 layout options) |
275
+ | `add_table_slide()` | Data comparison table |
276
+ | `add_summary_slide()` | Summary/conclusions |
277
+ | `add_thankyou_slide()` | Thank you / Q&A |
278
+
279
+ ### Step 6: (Optional) Generate HTML Version
280
+
281
+ In addition to PPTX, generate a single-file HTML presentation with embedded figures (horizontal-slide style):
282
+
283
+ ```python
284
+ import sys
285
+ sys.path.insert(0, '<SKILL_ROOT>/scripts')
286
+ from generate_html import HtmlPPT
287
+
288
+ html = HtmlPPT(title="Academic Report", theme="molecular")
289
+
290
+ # API identical to ChemistryPPT
291
+ html.add_title_slide("Title CN", title_en="Title EN", authors="...", journal="...")
292
+ html.add_section_slide("Part 1")
293
+ html.add_content_slide("Key Point", ["bullet 1", "bullet 2"])
294
+ html.add_figure_slide("Figure Title", figure_path="figures/p3_fig1.png",
295
+ bullets=["description"], figure_label="Figure 1",
296
+ layout="figure_right")
297
+ html.add_summary_slide("Summary", ["finding 1", "finding 2"])
298
+ html.add_thankyou_slide()
299
+
300
+ html.save("output/presentation.html")
301
+ ```
302
+
303
+ **HTML features**:
304
+ - Single self-contained file, figures embedded as base64
305
+ - Horizontal slide navigation: keyboard ← → Home End, scroll wheel, touch swipe, dot navigation
306
+ - 4 academic color themes (academic / molecular / green / nature)
307
+ - Responsive design for projectors and mobile
308
+ - No local server or dependencies needed
309
+
310
+ ### Step 7: Verify and Review Reports
311
+
312
+ After generating PPTX, run verification:
313
+
314
+ ```python
315
+ from pptx import Presentation
316
+
317
+ prs = Presentation("output/presentation.pptx")
318
+ print(f"Slide count: {len(prs.slides)}")
319
+
320
+ # Check all images are present
321
+ for i, slide in enumerate(prs.slides):
322
+ for shape in slide.shapes:
323
+ if shape.shape_type == 13: # Picture
324
+ print(f" Slide {i+1}: image {shape.image.content_type}")
325
+ ```
326
+
327
+ The `ChemistryPPT` class includes built-in error tracking:
328
+
329
+ ```python
330
+ ppt.save("output/presentation.pptx")
331
+ ppt.save_report("output/presentation.pptx") # generates JSON report
332
+
333
+ # Or access directly
334
+ report = ppt.get_report()
335
+ print(report["missing_images"]) # list of image paths not found
336
+ print(report["warnings"]) # non-fatal issues
337
+ print(report["errors"]) # actual errors
338
+ ```
339
+
340
+ **Report fields**:
341
+ - `missing_images`: all paths passed to `add_figure_slide()` that don't exist
342
+ - `errors`: actual image insertion failures
343
+ - `warnings`: non-fatal issues
344
+ - `slide_types`: slide type statistics
345
+
346
+ ### Error Handling & Fallback Mechanisms
347
+
348
+ **Figure extraction** (`extract_charts.py`):
349
+ 1. Multi-strategy: vector graphics → embedded images → page rendering fallback
350
+ 2. Compatible with PyMuPDF 1.19+ and 1.23+ (auto-switch `cluster_drawings` / `get_drawings` with manual clustering)
351
+ 3. Multi-tolerance retry (3→6→10→15→20) when default clustering finds too few figures
352
+ 4. Auto-generated JSON extraction report via `--report` flag
353
+
354
+ **Paper analysis** (`analyze_paper.py`):
355
+ 1. Encoding-safe: Windows GBK/ASCII fallback to prevent Unicode crashes
356
+ 2. Confidence-annotated paper classification (high/medium/low)
357
+ 3. Structured JSON output: `--json report.json` for workflow integration
358
+ 4. Weighted keyword detection: ×3 weight in first 1/3 of text (methods/results), ×1 in references
359
+
360
+ **PPT building** (`create_ppt.py`):
361
+ 1. Missing images auto-recorded (build continues), summarized on `save()`
362
+ 2. Image insertion exceptions caught (corrupt/unsupported formats)
363
+ 3. `save_report()` exports complete build log
364
+
365
+ **Common issues and resolutions**:
366
+
367
+ | Issue | Cause | Resolution |
368
+ |-------|-------|------------|
369
+ | `cluster_drawings` not found | PyMuPDF < 1.23 | Auto-fallback to `get_drawings()` manual clustering |
370
+ | 0 vector figures extracted | Special PDF rendering | Multi-tolerance retry, ultimately page rendering |
371
+ | Windows encoding crash | Unicode chars (e.g. `−`, `₂`) | `_safe_print()` auto-fallback to ASCII |
372
+ | Paper type misclassification | Characterization keywords in references | Weighted detection (body ×3), confidence annotation |
373
+ | Missing image files | Incorrect extraction or path | Recorded in `missing_images`, slide shows placeholder |
374
+
375
+ ---
376
+
377
+ ## Chemistry Academic Visual Standards
378
+
379
+ See `references/visual_style.md` for full details. Summary below:
380
+
381
+ ### Color Schemes
382
+
383
+ | Name | Primary | Accent | Best for |
384
+ |------|---------|--------|----------|
385
+ | **Academic Classic** (default) | `#003366` deep blue | `#B41E1E` dark red | General chemistry |
386
+ | **Molecular Tech** | `#1A5276` steel blue | `#E74C3C` bright red | Computational/materials |
387
+ | **Green Chemistry** | `#1E5631` deep green | `#D4A017` gold | Catalysis/energy/environment |
388
+ | **Nature Style** | `#222222` near-black | `#0066CC` blue | CNS journal presentations |
389
+
390
+ ### Typography
391
+
392
+ - Title: Bold sans-serif, 28–36pt
393
+ - Body: Regular sans-serif, 16–20pt
394
+ - English/numbers: Arial / Helvetica
395
+ - Chemistry formulas: monospace or appropriate serif
396
+
397
+ ### Slide Layout
398
+
399
+ - 16:9 widescreen (13.333" × 7.5")
400
+ - Margins ≥ 0.5"
401
+ - Left-aligned body text; titles may be centered
402
+ - Figures get priority space; explanatory text is concise
403
+
404
+ ### Chemistry-Specific Elements
405
+
406
+ - **Reaction schemes**: structure images or text-based with → connectors
407
+ - **Data tables**: comparison tables for catalyst performance / computational parameters
408
+ - **Mechanism diagrams**: keep originals, annotate key steps (i, ii, iii...)
409
+ - **Energy diagrams**: label key TS and intermediate energies on free energy profiles
410
+ - **Characterization data**: label key peaks (XRD), valence states (XPS), lattice spacings (TEM)
411
+
412
+ ---
413
+
414
+ ## Output Files
415
+
416
+ Default output in `output/`:
417
+
418
+ ```
419
+ output/
420
+ ├── presentation.pptx # Final PPTX
421
+ ├── presentation.html # (optional) Single-file HTML deck
422
+ ├── presentation_report.json # PPTX build report
423
+ ├── figures/ # Extracted figures
424
+ │ ├── p2_fig1.png
425
+ │ ├── p4_fig2.png
426
+ │ └── ...
427
+ └── qa_report.md # Quality check report (optional)
428
+ ```
429
+
430
+ ---
431
+
432
+ ## Scripts
433
+
434
+ | Script | Function |
435
+ |--------|----------|
436
+ | `scripts/extract_charts.py` | Multi-strategy figure extraction (vector + embedded + fallback) |
437
+ | `scripts/analyze_paper.py` | PDF structure analysis, paper type classification, JSON output |
438
+ | `scripts/convert_to_images.py` | PDF page to high-res image conversion |
439
+ | `scripts/create_ppt.py` | Main script: ChemistryPPT class for academic PPTX creation |
440
+ | `scripts/generate_html.py` | HTML generator: single-file horizontal-slide web deck |
441
+
442
+ ---
443
+
444
+ ## Chemistry Paper Type Adaptations
445
+
446
+ ### Catalysis Chemistry
447
+ Focus: preparation methods, characterization (XRD/TEM/XPS/BET), activity/selectivity/stability data, TOF, activation energy, in-situ characterization, DFT-assisted mechanism
448
+
449
+ ### Materials Chemistry
450
+ Focus: synthesis strategy, morphology control, structure characterization, physicochemical properties, application performance, structure-property relationships
451
+
452
+ ### Organic Synthesis Chemistry
453
+ Focus: synthetic route, substrate scope, condition optimization, mechanistic probe experiments, selectivity control
454
+
455
+ ### Computational/Theoretical Chemistry
456
+ Focus: computational methods and parameters, model validity, energy/structure data, comparison with experiment/benchmarks, atomic-level mechanism
457
+
458
+ ### Energy/Battery Chemistry
459
+ Focus: materials design, electrochemical performance (capacity/rate/cycling), in-situ characterization, interface chemistry, degradation mechanisms
460
+
461
+ ### Environmental/Atmospheric Chemistry
462
+ Focus: reaction kinetics, product analysis, mechanistic pathways, environmental implications, model calculations
463
+
464
+ ---
465
+
466
+ ## Prohibitions
467
+
468
+ - Do not generate placeholder content ("Please manually add XX", "Fill in XX here")
469
+ - Do not force all papers into the same template — adapt structure to actual paper content
470
+ - Do not ignore correct formatting of chemical formulas / element symbols (subscripts, italics, etc.)
471
+ - Do not create text-only result slides when figures are available
472
+ - Do not fabricate data or conclusions not present in the paper
473
+ - Do not produce a text-only outline instead of a usable presentation
@@ -0,0 +1,197 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>__TITLE__</title>
7
+ <style>
8
+ :root {
9
+ --primary: __PRIMARY__;
10
+ --primary-rgb: __PRIMARY_RGB__;
11
+ --accent: __ACCENT__;
12
+ --bg: __BG__;
13
+ --bg-light: __BG_LIGHT__;
14
+ --text: __TEXT__;
15
+ --muted: __MUTED__;
16
+ --section-bg: __SECTION_BG__;
17
+ --section-text: __SECTION_TEXT__;
18
+ --table-stripe: __TABLE_STRIPE__;
19
+ --slide-width: 100vw;
20
+ --slide-height: 100vh;
21
+ }
22
+
23
+ * { box-sizing: border-box; margin: 0; padding: 0; }
24
+
25
+ html, body {
26
+ width: 100%; height: 100%; overflow: hidden;
27
+ background: var(--bg); color: var(--text);
28
+ font-family: "Segoe UI", "Noto Sans SC", "Microsoft YaHei", Arial, sans-serif;
29
+ -webkit-font-smoothing: antialiased;
30
+ }
31
+
32
+ /* Slide container */
33
+ #deck {
34
+ position: fixed; inset: 0;
35
+ display: flex; flex-wrap: nowrap;
36
+ transition: transform 0.55s cubic-bezier(0.4, 0, 0.2, 1);
37
+ z-index: 10; will-change: transform;
38
+ width: __NSLIDES__vw;
39
+ }
40
+
41
+ /* Single slide */
42
+ .slide {
43
+ width: 100vw; height: 100vh;
44
+ flex: 0 0 100vw; position: relative;
45
+ padding: 5vh 5vw 7vh 5vw;
46
+ display: flex; flex-direction: column;
47
+ overflow-y: auto; overflow-x: hidden;
48
+ }
49
+ .slide.light { background: var(--bg); color: var(--text); }
50
+ .slide.dark { background: var(--section-bg); color: var(--section-text); }
51
+ .slide.accent-bg { background: var(--bg-light); color: var(--text); }
52
+
53
+ /* Title slide */
54
+ .slide-title { justify-content: center; align-items: flex-start; padding-top: 12vh; }
55
+ .slide-title .accent-line { width: 8vw; min-width: 80px; height: 3px; background: var(--accent); margin-bottom: 3vh; }
56
+ .slide-title h1 { font-size: clamp(24px, 3.2vw, 44px); font-weight: 700; line-height: 1.25; max-width: 85vw; }
57
+ .slide-title .en-title { font-size: clamp(14px, 1.5vw, 22px); color: var(--muted); margin-top: 1.5vh; max-width: 85vw; }
58
+ .slide-title .meta { margin-top: 6vh; font-size: clamp(12px, 1.1vw, 16px); color: var(--muted); }
59
+ .slide-title .meta span { display: block; margin-bottom: 0.4vh; }
60
+ .slide-title .page-num { position: absolute; bottom: 3vh; right: 3vw; font-size: 12px; color: var(--muted); }
61
+
62
+ /* Section divider */
63
+ .slide-section { justify-content: center; align-items: flex-start; padding-top: 20vh; }
64
+ .slide-section .accent-bar { width: 3px; height: 12vh; min-height: 60px; background: var(--accent); position: absolute; left: 3vw; top: 50%; transform: translateY(-50%); }
65
+ .slide-section h2 { font-size: clamp(22px, 3.6vw, 48px); font-weight: 700; margin-left: 2vw; line-height: 1.2; }
66
+ .slide-section .sub { font-size: clamp(12px, 1.3vw, 18px); opacity: 0.7; margin-left: 2vw; margin-top: 1.5vh; }
67
+
68
+ /* Content slide */
69
+ .slide-content { padding-top: 8vh; }
70
+ .slide-content h3 { font-size: clamp(16px, 2.2vw, 32px); font-weight: 700; color: var(--primary); margin-bottom: 0.8vh; }
71
+ .slide-content .title-line { width: 5vw; min-width: 40px; height: 2px; background: var(--accent); margin-bottom: 2.5vh; }
72
+ .slide-content .subtitle { font-size: clamp(11px, 1vw, 14px); color: var(--muted); margin-bottom: 2vh; }
73
+ .slide-content .bullets { list-style: none; max-width: 90%; }
74
+ .slide-content .bullets li {
75
+ font-size: clamp(13px, 1.35vw, 18px); line-height: 1.6;
76
+ padding: 0.8vh 0; border-bottom: 1px solid rgba(var(--muted), 0.12);
77
+ }
78
+ .slide-content .notes { position: absolute; bottom: 2.5vh; font-size: 10px; color: var(--muted); max-width: 85%; }
79
+ .slide-content .page-num { position: absolute; bottom: 3vh; right: 3vw; font-size: 12px; color: var(--muted); }
80
+
81
+ /* Figure slide */
82
+ .slide-figure { padding-top: 6vh; }
83
+ .slide-figure h3 { font-size: clamp(16px, 2.2vw, 32px); font-weight: 700; color: var(--primary); margin-bottom: 0.5vh; }
84
+ .slide-figure .title-line { width: 5vw; min-width: 40px; height: 2px; background: var(--accent); margin-bottom: 2vh; }
85
+ .slide-figure .fig-area { display: flex; gap: 2vw; flex: 1; min-height: 0; align-items: flex-start; }
86
+ .slide-figure .fig-area.top { flex-direction: column; }
87
+ .slide-figure .fig-area img { max-width: 100%; max-height: 55vh; object-fit: contain; border-radius: 2px; }
88
+ .slide-figure .fig-text { flex: 1; font-size: clamp(12px, 1.25vw, 16px); line-height: 1.6; min-width: 220px; }
89
+ .slide-figure .fig-text li { padding: 0.6vh 0; list-style: none; border-bottom: 1px solid rgba(var(--muted), 0.10); }
90
+ .slide-figure .fig-caption { font-size: 10px; color: var(--muted); margin-top: 0.8vh; }
91
+ .slide-figure .page-num { position: absolute; bottom: 3vh; right: 3vw; font-size: 12px; color: var(--muted); }
92
+
93
+ /* Table slide */
94
+ .slide-table { padding-top: 8vh; }
95
+ .slide-table h3 { font-size: clamp(16px, 2.2vw, 32px); font-weight: 700; color: var(--primary); margin-bottom: 0.5vh; }
96
+ .slide-table .title-line { width: 5vw; height: 2px; background: var(--accent); margin-bottom: 2.5vh; }
97
+ .slide-table table { width: 100%; border-collapse: collapse; font-size: clamp(11px, 1.1vw, 15px); }
98
+ .slide-table th { background: var(--primary); color: #fff; padding: 1.2vh 1vw; text-align: center; font-weight: 600; }
99
+ .slide-table td { padding: 0.9vh 1vw; text-align: center; border-bottom: 1px solid rgba(var(--muted), 0.15); }
100
+ .slide-table tr:nth-child(even) td { background: var(--table-stripe); }
101
+ .slide-table .page-num { position: absolute; bottom: 3vh; right: 3vw; font-size: 12px; color: var(--muted); }
102
+
103
+ /* Summary slide */
104
+ .slide-summary { background: var(--bg-light); padding-top: 10vh; }
105
+ .slide-summary .top-bar { width: 100%; height: 4px; background: var(--primary); position: absolute; top: 0; left: 0; }
106
+ .slide-summary h3 { font-size: clamp(18px, 2.6vw, 36px); font-weight: 700; color: var(--primary); margin-bottom: 3vh; }
107
+ .slide-summary .bullets { list-style: none; max-width: 88%; }
108
+ .slide-summary .bullets li { font-size: clamp(13px, 1.4vw, 18px); line-height: 1.55; padding: 1.2vh 0; }
109
+ .slide-summary .page-num { position: absolute; bottom: 3vh; right: 3vw; font-size: 12px; color: var(--muted); }
110
+
111
+ /* Thank you slide */
112
+ .slide-thanks { justify-content: center; align-items: center; text-align: center; background: var(--section-bg); color: var(--section-text); }
113
+ .slide-thanks h2 { font-size: clamp(28px, 4.5vw, 56px); font-weight: 700; }
114
+ .slide-thanks .sub { font-size: clamp(14px, 1.6vw, 22px); opacity: 0.65; margin-top: 2vh; }
115
+
116
+ /* Navigation dots */
117
+ #nav-dots { position: fixed; bottom: 2.5vh; left: 50%; transform: translateX(-50%); display: flex; gap: 8px; z-index: 100; }
118
+ #nav-dots .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--muted); opacity: 0.35; cursor: pointer; transition: all 0.2s; }
119
+ #nav-dots .dot.active { opacity: 1; background: var(--accent); transform: scale(1.3); }
120
+
121
+ /* Page counter */
122
+ #page-counter { position: fixed; bottom: 2.8vh; right: 2.5vw; font-size: 11px; color: var(--muted); z-index: 100; font-family: monospace; }
123
+
124
+ /* Keyboard hint */
125
+ .kb-hint { position: fixed; bottom: 2.5vh; left: 2.5vw; font-size: 10px; color: var(--muted); z-index: 100; opacity: 0.5; }
126
+
127
+ /* Responsive */
128
+ @media (max-width: 768px) {
129
+ .slide { padding: 4vh 4vw 8vh 4vw; }
130
+ .slide-figure .fig-area { flex-direction: column !important; }
131
+ .slide-figure .fig-area img { max-height: 35vh; }
132
+ }
133
+ </style>
134
+ </head>
135
+ <body>
136
+
137
+ <div id="deck">
138
+ __SLIDES__
139
+ </div>
140
+
141
+ <div id="nav-dots">__NAV_DOTS__</div>
142
+ <div id="page-counter">1 / __TOTAL__</div>
143
+ <div class="kb-hint">← → 翻页 · Click dots · Scroll</div>
144
+
145
+ <script>
146
+ (function(){
147
+ var total = __TOTAL__;
148
+ var deck = document.getElementById('deck');
149
+ var dots = document.querySelectorAll('#nav-dots .dot');
150
+ var counter = document.getElementById('page-counter');
151
+ var current = 0;
152
+
153
+ deck.style.width = (total * 100) + 'vw';
154
+
155
+ function goTo(idx) {
156
+ if (idx < 0 || idx >= total) return;
157
+ current = idx;
158
+ deck.style.transform = 'translateX(' + (-current * 100) + 'vw)';
159
+ dots.forEach(function(d, i) { d.classList.toggle('active', i === current); });
160
+ counter.textContent = (current + 1) + ' / ' + total;
161
+ }
162
+
163
+ // Keyboard
164
+ document.addEventListener('keydown', function(e) {
165
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown' || e.key === ' ') { e.preventDefault(); goTo(current + 1); }
166
+ if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') { e.preventDefault(); goTo(current - 1); }
167
+ if (e.key === 'Home') { e.preventDefault(); goTo(0); }
168
+ if (e.key === 'End') { e.preventDefault(); goTo(total - 1); }
169
+ });
170
+
171
+ // Dot clicks
172
+ dots.forEach(function(d) { d.addEventListener('click', function() { goTo(parseInt(this.dataset.idx)); }); });
173
+
174
+ // Touch swipe
175
+ var touchStartX = 0;
176
+ document.addEventListener('touchstart', function(e) { touchStartX = e.touches[0].clientX; });
177
+ document.addEventListener('touchend', function(e) {
178
+ var dx = e.changedTouches[0].clientX - touchStartX;
179
+ if (Math.abs(dx) > 50) { goTo(current + (dx < 0 ? 1 : -1)); }
180
+ });
181
+
182
+ // Scroll wheel
183
+ var wheelTimeout;
184
+ document.addEventListener('wheel', function(e) {
185
+ e.preventDefault();
186
+ if (wheelTimeout) return;
187
+ wheelTimeout = setTimeout(function() { wheelTimeout = null; }, 900);
188
+ goTo(current + (e.deltaY > 0 ? 1 : -1));
189
+ }, { passive: false });
190
+
191
+ // Initial
192
+ goTo(0);
193
+ })();
194
+ </script>
195
+
196
+ </body>
197
+ </html>