← 返回
未分类

html-summary-generator

生成精美HTML文档。支持12种主题、毛玻璃卡片、11种背景动效、9种鼠标动效、10种边框样式、色相轮调色、PDF导出。触发词:项目总结、技术文档、工作汇报、教程、数据报告、对比分析、流程文档、会议纪要、HTML文档、生成报告、做个总结、生成文档、帮我做个汇报。
一句话介绍 让 AI 秒变「文档设计师」——一句话生成精美 HTML 文档,12 种主题、背景动效、SVG 图表全部内置,零配置开箱即用。 为什么这是你最该下载的 Skill ✅ 完全零配置,下载即用 不需要设置路径、不需要装依赖、不需要懂 HTML。解压到 skills 目录,说一句话就能生成文档。其他 AI 生成的文档是「能看」,这个 Skill 生成的是「好看」。 ✅ 12 套专业主题,覆盖所有场景 银河暗色系、莫兰迪柔和系、科技蓝、中国红、极简黑白……无论你是做技术总结、项目汇报、还是数据报告,总有一款配得上你的内容。 ✅ 背景动效,让文档活起来 粒子飘散、星空闪烁、雪花纷飞、萤火虫微光——5 种 SVG 背景动效,原本静态的文档瞬间有了呼吸感。 ✅ 交互式调色器(完整版专属) 生成文档后,读者可以实时拖拽调色,一键切换主题色——这个功能单独做出来都值回票价。 ✅ 内置 SVG 图表生成指南 时间线、流程图、雷达图、对比卡片——SKILL.md 里直接查表,AI 照着写就能出图,不需要额外工具。 ✅ 三种模板,按需选择 模板 大小 适合场景 完整版 75KB 正式汇报、对外展示(含调色器) 精简版 15KB 日常笔记、内部文档(含动效) 静态版 10KB 极简输出、打印/PDF 友好 ✅ 真正的「公用版」 专为分发设计——路径自动查找、主题色值内嵌、模板自文档化。你下载的这份,在任何机器上都能跑。 适用人群 开发者 — 项目总结、技术文档、复盘报告 产品经理 — 需求文档、竞品分析、功能说明 数据分析师 — 数据报告、可视化展示 学生/研究者 — 论文笔记、实验报告、学习总结 任何需要「把内容变成好看文档」的人 用户真实反馈 "之前用 AI 生成的文档像 PPT 导出的,现在这个像设计师做的。" "12 个主题够我用到明年,每次换一个不会审美疲劳。" "最爽的是不用配置,解压完直接说需求就出结果。"
half past nine
未分类 community v1.0.2 3 版本 96969.7 Key: 无需
★ 0
Stars
📥 32
下载
💾 0
安装
3
版本
#latest

概述

HTML 文档生成器

功能概述

生成精美的 HTML 文档,支持三种生成模式:

  • 完整版:含自定义面板(调色器+动效+字体),可事后调整
  • 精简版:固定样式,不可修改,生成快速
  • 纯静态:最简样式,无交互,生成最快

交互式文档创建流程(严格遵守)

核心原则

  1. 第一步问文档类型+生成模式:合并为一步,减少交互
  2. 第二步一次性问完所有选项:根据生成模式,一次性问完对应选项
  3. 自动提取内容:从文件/参考文献/对话上下文自动总结
  4. 选择题优先:除了自定义要求,其他都是序号选择
  5. ⚠️ 禁止使用选择对话框:不要调用AskUserQuestion工具,直接输出纯文本问题,让用户输入一串序号即可

第一步:确认文档类型和生成模式(必须先问)

请问您要创建哪种类型的文档?以及选择生成模式?

【文档类型】
1. 📋 项目总结 - 项目背景、目标完成情况、关键成果、问题与复盘
2. 📘 技术文档 - 架构设计、技术选型、接口说明、部署流程
3. 📊 汇报PPT - 封面、目录、核心内容、数据图表、总结
4. 📖 教程指南 - 前置条件、分步操作、注意事项、FAQ
5. 📈 数据报告 - 数据概览、趋势分析、对比分析、结论
6. ⚖️ 对比分析 - 对比维度、各方案详情、优劣评分、推荐
7. 🔄 流程文档 - 流程概述、流程图、角色职责、操作规范
8. 📝 会议纪要 - 会议信息、参会人员、议题讨论、待办跟踪

【生成模式】
A. 完整版(含自定义面板,可事后调整)- 生成较慢
B. 精简版(固定样式,不可修改)- 生成快速
C. 纯静态(最简样式,无交互)- 生成最快

请输入(如 "3A" 表示汇报PPT+完整版):

第二步:一次性问完所有选项

根据用户选择的生成模式,一次性问完对应的所有问题:

完整版(A)问法:

请回答以下问题(直接输入一串字符,不区分大小写,不需要空格,如 "33211117无"):

【通用设置】
详细程度(1.简洁版 2.标准版 3.详细版 4.超详细版)
目标字数/页数(1.500字/5页以内 2.500-1000字/5-10页 3.1000-2000字/10-20页 4.2000-5000字/20页以上)
目标读者(1.技术人员 2.管理层 3.客户 4.通用)
语言风格(1.正式严谨 2.简洁直接 3.生动活泼 4.学术规范)

【内容选项】
是否需要SVG流程图?(1.需要 2.不需要)
是否需要对比表格?(1.需要 2.不需要)
是否需要时间线展示?(1.需要 2.不需要)

【主题选择】
选择主题风格:
1.银河 2.深海 3.薰衣草 4.玫瑰 5.黄金
6.莫兰迪 7.雪白 8.奶油 9.薄荷 A.天空 B.洛可可 C.敦煌

【可选】
特殊要求(直接输入文字,没有则输入"无",不输入则默认为"无")

精简版(B)/ 纯静态(C)问法:

请回答以下问题(直接输入一串字符,不区分大小写,不需要空格,如 "332411179a1b无"):

【通用设置】
详细程度(1.简洁版 2.标准版 3.详细版 4.超详细版)
目标字数/页数(1.500字/5页以内 2.500-1000字/5-10页 3.1000-2000字/10-20页 4.2000-5000字/20页以上)
目标读者(1.技术人员 2.管理层 3.客户 4.通用)
语言风格(1.正式严谨 2.简洁直接 3.生动活泼 4.学术规范)

【内容选项】
是否需要SVG流程图?(1.需要 2.不需要)
是否需要对比表格?(1.需要 2.不需要)
是否需要时间线展示?(1.需要 2.不需要)

【主题选择】
选择主题风格:
1.银河 2.深海 3.薰衣草 4.玫瑰 5.黄金
6.莫兰迪 7.雪白 8.奶油 9.薄荷 A.天空 B.洛可可 C.敦煌

【动效设置】(精简版生效,纯静态跳过)
背景动效:
1.粒子飘浮 2.星空闪烁 3.雪花飘落 4.泡泡上升 5.网格连线
6.波浪流动 7.萤火虫 8.矩阵雨 9.星云漩涡 0.无动效

鼠标动效:
1.泛光跟随 2.拖尾光轨 3.星河轨迹 4.星星闪烁 5.彩虹光环
6.波纹扩散 7.磁性吸引 8.烟花点击 9.无动效

【卡片样式】(已设置默认值,无需提问)
默认:毛玻璃边框、小圆角、中等强度、半透明

【可选】
特殊要求(直接输入文字,没有则输入"无",不输入则默认为"无")

第三步:自动提取内容

根据用户提供的文件、参考文献、对话上下文,自动提取以下信息:

需要提取的信息来源
---------------------
项目名称文件标题、用户提及
项目背景文件开头、用户描述
技术栈文件内容、代码分析
开发时间文件中的日期信息
主要成果文件中的数据、结论
遇到的问题文件中的问题描述
解决方案文件中的解决方案

原则:能从上下文提取的就不要问用户,只有实在无法获取的关键信息才追问。


第四步:生成文档(强制使用内嵌模板)

⚠️ 必须严格遵守以下规则:

  1. 必须使用本文件末尾的内嵌模板:根据用户选择的生成模式,使用本 SKILL.md 文件中对应的 HTML 模板代码块:
    • 完整版(A):使用 ## 【模板A】完整版 HTML 模板 中的代码
    • 精简版(B):使用 ## 【模板B】精简版 HTML 模板 中的代码
    • 纯静态(C):使用 ## 【模板C】纯静态 HTML 模板 中的代码
  1. 禁止自己编写HTML结构:不得绕过模板自己编写HTML、CSS、JavaScript代码。只能:
    • 替换模板中的占位符(如 {{TITLE}}{{CONTENT}} 等)
    • 填充提取的内容到模板的相应位置
    • 保留模板的所有交互功能(调色器、动效等)
  1. 模板直接内嵌在本 SKILL.md 文件末尾,无需读取任何外部文件,任何环境下均可直接使用。
  1. 生成流程
    • 读取本文件末尾对应模板的完整 HTML 代码
    • 替换以下占位符:
    • {{TITLE}} - 页面标题
    • {{SUBTITLE}} - 副标题
    • {{META}} - 元信息(日期、技术栈等)
    • {{STAT1_NUMBER}} / {{STAT1_LABEL}} - 统计卡片1
    • {{STAT2_NUMBER}} / {{STAT2_LABEL}} - 统计卡片2
    • {{STAT3_NUMBER}} / {{STAT3_LABEL}} - 统计卡片3
    • {{STAT4_NUMBER}} / {{STAT4_LABEL}} - 统计卡片4
    • {{CONTENT}} - 主要内容区域(使用 glass-card 类的卡片)
    • {{FOOTER}} - 页脚文字
    • 精简版/纯静态还需替换主题色占位符(见模板内说明)
    • 将提取的内容填充到 {{CONTENT}} 占位符中
    • 保存到用户桌面或指定目录
    • 文件名:{项目名}_{文档类型}.html
用户选择使用模板交互功能
------------------------------
A 完整版模板A调色器+动效+字体+边框样式+自动保存
B 精简版模板B固定动效+固定样式+PDF导出+主题切换
C 纯静态模板C固定样式,无交互

⚠️ 内容生成强制要求(必须严格遵守)

字数要求

用户选择的字数要求必须严格遵守,不得缩水!

用户选择最低字数最低段落数每个章节至少
----------------------------------------------
1.500字以内300字3段50字
2.500-1000字800字5段100字
3.1000-2000字1500字8段150字
4.2000-5000字3000字12段200字

详细程度定义

用户选择内容要求
--------------------
1.简洁版核心要点,每个点1-2句话
2.标准版基本展开,每个点3-5句话,有简单例子
3.详细版充分展开,每个点5-10句话,有详细分析和案例
4.超详细版深度展开,每个点10-20句话,有数据支撑、案例分析、对比论证

常见错误(禁止)

❌ 只有标题没有内容

❌ 每个要点只有一句话

❌ 用"等"、"省略"代替详细内容

❌ 重复啰嗦凑字数

绕过内嵌模板自己编写HTML/CSS/JavaScript

从外部文件路径读取模板(不需要,模板就在本文件末尾)

忽略模板的交互功能(调色器、动效等)


预设主题颜色表(精简版/纯静态替换占位符时使用)

序号主题PRIMARY_COLORBG_COLORCARD_BG_COLORTEXT_PRIMARYTEXT_SECONDARYBORDER_COLOR场景
------------------------------------------------------------------------------------------------------
1银河#7c3aed#0d1117rgba(20,17,35,0.9)#e0e7ff#c7d2fergba(124,58,237,0.5)科技、商务
2深海#00e5ff#0a1929rgba(10,25,41,0.9)#e0f7fa#b2ebf2rgba(0,229,255,0.5)科技、金融
3薰衣草#e040fb#1a0e2ergba(26,14,46,0.9)#f3e8ff#e9d5ffrgba(224,64,251,0.5)时尚、美妆
4玫瑰#ff1744#2d0a1argba(45,10,26,0.9)#ffe4e6#fecdd3rgba(255,23,68,0.5)健康、公益
5黄金#f0c040#1a1508rgba(26,21,8,0.9)#fefce8#fef08argba(240,192,64,0.5)奢华、高贵
6莫兰迪#8b6f5e#e8e0d8rgba(248,244,240,0.95)#3d2e24#5a4a3ergba(139,111,94,0.4)高级、艺术
7雪白#2563eb#f0f4f8rgba(255,255,255,0.95)#0f172a#334155rgba(37,99,235,0.3)正式、学术
8奶油#b45309#fef7e7rgba(255,251,235,0.95)#451a03#78350frgba(180,83,9,0.3)温馨、生活
9薄荷#059669#ecfdf5rgba(240,253,244,0.95)#064e3b#065f46rgba(5,150,105,0.3)清新、自然
A天空#0369a1#eef6ffrgba(255,255,255,0.95)#0c4a6e#075985rgba(3,105,161,0.3)简洁、专业
B洛可可#be185d#fdf0f5rgba(255,240,249,0.95)#831843#9d174drgba(190,24,93,0.3)浪漫、古典
C敦煌#c23b22#faf5efrgba(255,250,245,0.95)#7c2d12#92400ergba(194,59,34,0.3)古朴、文化

完整版主题颜色(使用内嵌主题系统,SKILL.md末尾模板A已内置,选好主题后只需切换即可)

完整版(模板A)内置了色相轮调色器,用户可在生成后自由调整所有颜色,无需替换占位符,直接生成后使用调色器调整即可。


示例流程

示例1:完整版

用户:帮我生成一个项目总结

AI

请问您要创建哪种类型的文档?以及选择生成模式?
...
请输入(如 "3A" 表示汇报PPT+完整版):

用户:1A

AI:(询问选项)

用户:33211117无

AI:(从上下文提取项目信息,读取本文件末尾的模板A,替换占位符,生成完整版文档)


【模板A】完整版 HTML 模板

> ⚠️ AI 生成完整版文档时,必须复制以下完整 HTML 代码,替换 {{TITLE}} {{SUBTITLE}} {{META}} {{STAT1_NUMBER}} {{STAT1_LABEL}} {{STAT2_NUMBER}} {{STAT2_LABEL}} {{STAT3_NUMBER}} {{STAT3_LABEL}} {{STAT4_NUMBER}} {{STAT4_LABEL}} {{CONTENT}} {{FOOTER}} 占位符后输出。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{TITLE}}</title>
<style>
:root {
  --primary: #648cff;
  --primary-light: #8aabff;
  --primary-dark: #4070e0;
  --secondary: #3cb478;
  --accent: #e8a838;
  --error: #e85454;
  --bg-main: #0d1117;
  --bg-card: rgba(20, 25, 35, 0.7);
  --text-primary: #ffffff;
  --text-secondary: #e0e6ed;
  --text-muted: rgba(255,255,255,0.6);
  --border-color: rgba(100,140,255,0.5);
  --border-hover: rgba(100,140,255,0.9);
  --glow-color: rgba(100,140,255,0.4);
  --glass-blur: 20px;
  --glass-bg: rgba(20, 25, 35, 0.6);
  --card-radius: 20px;
  --card-opacity: 0.7;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
body { 
  font-family: -apple-system, "Microsoft YaHei", sans-serif; 
  color: var(--text-secondary); 
  background: var(--bg-main); 
  line-height: 1.8; 
  overflow-x: hidden; 
  min-height: 100vh; 
}
p, li, td { color: var(--text-secondary); }
h1, h2, h3, h4 { color: var(--text-primary); }

.galaxy-bg { 
  position: fixed; 
  top: 0; left: 0; 
  width: 100%; height: 100%; 
  background: linear-gradient(135deg, var(--bg-main) 0%, #161b22 50%, #1a1e2e 100%); 
  z-index: -2; 
}
.galaxy-bg::before { 
  content: ''; 
  position: absolute; 
  top: 0; left: 0; 
  width: 100%; height: 100%; 
  background: radial-gradient(ellipse at 20% 50%, rgba(100,140,255,0.1) 0%, transparent 50%),
              radial-gradient(ellipse at 80% 20%, rgba(120,80,200,0.08) 0%, transparent 40%),
              radial-gradient(ellipse at 50% 80%, rgba(60,180,120,0.06) 0%, transparent 40%); 
}
.galaxy-bg::after { 
  content: ''; 
  position: absolute; 
  top: 0; left: 0; 
  width: 100%; height: 100%; 
  background-image: 
    radial-gradient(1.5px 1.5px at 20px 30px, #fff, transparent),
    radial-gradient(1.5px 1.5px at 40px 70px, rgba(255,255,255,0.9), transparent),
    radial-gradient(2px 2px at 50px 160px, rgba(255,255,255,0.7), transparent),
    radial-gradient(1.5px 1.5px at 90px 40px, #fff, transparent),
    radial-gradient(2px 2px at 130px 80px, rgba(100,140,255,0.9), transparent),
    radial-gradient(1.5px 1.5px at 160px 120px, rgba(255,255,255,0.6), transparent),
    radial-gradient(2.5px 2.5px at 200px 50px, rgba(120,180,255,0.8), transparent),
    radial-gradient(1.5px 1.5px at 250px 180px, rgba(255,255,255,0.7), transparent),
    radial-gradient(2px 2px at 300px 100px, rgba(255,255,255,0.5), transparent),
    radial-gradient(2.5px 2.5px at 350px 200px, rgba(180,120,255,0.7), transparent); 
  background-size: 400px 300px; 
  animation: twinkle 6s ease-in-out infinite alternate; 
}
@keyframes twinkle { from { opacity: 0.7; } to { opacity: 1; } }

#effectCanvas { 
  position: fixed; 
  top: 0; left: 0; 
  width: 100%; height: 100%; 
  pointer-events: none; 
  z-index: 0; 
}

.container { 
  max-width: 1000px; 
  margin: 0 auto; 
  padding: 40px 20px; 
  position: relative; 
  z-index: 1; 
}

.glass-card { 
  background: rgba(20, 25, 35, var(--card-opacity, 0.7)); 
  backdrop-filter: blur(var(--glass-blur, 20px)); 
  -webkit-backdrop-filter: blur(var(--glass-blur, 20px));
  border-radius: var(--card-radius, 20px); 
  padding: 32px; 
  margin: 24px 0; 
  border: 1.5px solid var(--border-color); 
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); 
  position: relative; 
  overflow: hidden; 
  page-break-inside: avoid;
  box-shadow: 0 4px 30px rgba(0, 0, 0, 0.3);
}
.glass-card::before { 
  content: ''; 
  position: absolute; 
  top: 0; left: 0; right: 0; 
  height: 2px; 
  background: linear-gradient(90deg, transparent, var(--primary), var(--secondary), transparent); 
  opacity: 0;
  transition: opacity 0.4s ease; 
}
.glass-card::after {
  content: '';
  position: absolute;
  top: -50%; left: -50%;
  width: 200%; height: 200%;
  background: radial-gradient(circle, var(--glow-color) 0%, transparent 60%);
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
}
.glass-card:hover { 
  border-color: var(--border-hover); 
  box-shadow: 0 0 40px var(--glow-color), 0 20px 60px rgba(0,0,0,0.4); 
  transform: translateY(-8px); 
}
.glass-card:hover::before { opacity: 1; }
.glass-card:hover::after { opacity: 0.1; }

.card-success { border-left: 4px solid var(--secondary); }
.card-warning { border-left: 4px solid var(--accent); }
.card-error { border-left: 4px solid var(--error); }
.card-info { border-left: 4px solid #5890ff; }
.card-purple { border-left: 4px solid #7850c8; }

.glass-card p { color: var(--text-secondary); line-height: 1.9; margin-bottom: 12px; }
.glass-card li { color: var(--text-secondary); margin-bottom: 6px; }
.glass-card strong { color: var(--text-primary); }
.glass-card h3 { color: var(--text-primary); font-size: 20px; margin-bottom: 16px; }

.hero { 
  text-align: center; 
  padding: 80px 50px; 
  background: linear-gradient(135deg, rgba(100,140,255,0.12) 0%, rgba(120,80,200,0.12) 100%); 
  border-radius: 28px; 
  margin-bottom: 50px; 
  position: relative; 
  overflow: hidden; 
  border: 2px solid var(--border-color); 
  backdrop-filter: blur(25px); 
  -webkit-backdrop-filter: blur(25px);
  page-break-inside: avoid;
  box-shadow: 0 8px 40px rgba(0,0,0,0.4);
  animation: heroAppear 1s ease-out;
}
@keyframes heroAppear {
  from { opacity: 0; transform: translateY(30px); }
  to { opacity: 1; transform: translateY(0); }
}
.hero:hover { 
  border-color: var(--border-hover); 
  box-shadow: 0 0 60px var(--glow-color), 0 20px 60px rgba(0,0,0,0.5); 
}
.hero h1 { 
  font-size: 48px; 
  font-weight: 700; 
  color: var(--text-primary); 
  margin-bottom: 16px; 
  text-shadow: 0 0 30px var(--glow-color);
}
.hero .subtitle { font-size: 22px; color: var(--text-muted); margin-bottom: 24px; }
.hero .meta { font-size: 14px; color: var(--text-muted); }

.stats-grid { 
  display: grid; 
  grid-template-columns: repeat(4,1fr); 
  gap: 20px; 
  margin: 50px 0; 
  page-break-inside: avoid; 
}
.stat-card { 
  background: rgba(20, 25, 35, var(--card-opacity, 0.7)); 
  backdrop-filter: blur(var(--glass-blur, 20px)); 
  -webkit-backdrop-filter: blur(var(--glass-blur, 20px));
  border-radius: var(--card-radius, 20px); 
  padding: 30px; 
  text-align: center; 
  border: 1.5px solid var(--border-color); 
  transition: all 0.4s cubic-bezier(0.175,0.885,0.32,1.275); 
  cursor: pointer; 
  position: relative; 
  overflow: hidden; 
  box-shadow: 0 4px 20px rgba(0,0,0,0.2);
}
.stat-card:hover { 
  transform: translateY(-12px) scale(1.05); 
  box-shadow: 0 0 50px var(--glow-color), 0 25px 50px rgba(0,0,0,0.4); 
  border-color: var(--border-hover); 
}
.stat-card .number { 
  font-size: 52px; 
  font-weight: 700; 
  color: var(--text-primary); 
  text-shadow: 0 0 20px var(--glow-color);
}
.stat-card .label { font-size: 14px; color: var(--text-muted); margin-top: 12px; }

.section { 
  margin: 60px 0; 
  page-break-inside: avoid; 
}
.section h2 { 
  font-size: 30px; 
  font-weight: 700; 
  color: var(--text-primary); 
  margin-bottom: 28px; 
  padding-bottom: 14px; 
  border-bottom: 2px solid var(--border-color); 
  display: inline-block; 
  text-shadow: 0 0 20px var(--glow-color);
}
.section h3 { 
  font-size: 22px; 
  font-weight: 600; 
  color: var(--text-muted); 
  margin: 28px 0 14px; 
}

.timeline { position: relative; padding-left: 45px; margin: 40px 0; }
.timeline::before { 
  content: ''; 
  position: absolute; 
  left: 14px; top: 0; bottom: 0; 
  width: 3px; 
  background: linear-gradient(to bottom, var(--primary), #7850c8, var(--accent), var(--error)); 
  border-radius: 2px; 
}
.timeline-item { 
  position: relative; 
  margin-bottom: 30px; 
  padding: 24px; 
  background: rgba(20, 25, 35, var(--card-opacity, 0.7)); 
  backdrop-filter: blur(var(--glass-blur, 20px));
  -webkit-backdrop-filter: blur(var(--glass-blur, 20px));
  border-radius: var(--card-radius, 16px); 
  border: 1.5px solid var(--border-color); 
  transition: all 0.4s ease; 
  page-break-inside: avoid; 
  box-shadow: 0 4px 20px rgba(0,0,0,0.2);
}
.timeline-item:hover { 
  transform: translateX(15px); 
  box-shadow: 0 0 35px var(--glow-color), 0 15px 40px rgba(0,0,0,0.3); 
  border-color: var(--border-hover); 
}
.timeline-item::before { 
  content: ''; 
  position: absolute; 
  left: -38px; top: 28px; 
  width: 18px; height: 18px; 
  border-radius: 50%; 
  border: 3px solid var(--bg-main); 
}
.timeline-item.success::before { background: var(--secondary); box-shadow: 0 0 15px var(--secondary); }
.timeline-item.warning::before { background: var(--accent); box-shadow: 0 0 15px var(--accent); }
.timeline-item.error::before { background: var(--error); box-shadow: 0 0 15px var(--error); }
.timeline-item.info::before { background: #5890ff; box-shadow: 0 0 15px #5890ff; }
.timeline-item .time { font-size: 12px; color: var(--text-muted); margin-bottom: 10px; }
.timeline-item h4 { font-size: 18px; font-weight: 600; color: var(--text-primary); margin-bottom: 10px; }
.timeline-item p { font-size: 14px; color: var(--text-secondary); line-height: 1.8; }

.tag { 
  display: inline-block; 
  padding: 5px 16px; 
  border-radius: 20px; 
  font-size: 12px; 
  font-weight: 600; 
  margin-right: 10px; 
  color: #fff; 
}
.tag-success { background: rgba(60,180,120,0.5); border: 1px solid rgba(60,180,120,0.7); }
.tag-error { background: rgba(232,84,84,0.5); border: 1px solid rgba(232,84,84,0.7); }
.tag-warning { background: rgba(232,168,56,0.5); border: 1px solid rgba(232,168,56,0.7); }
.tag-info { background: rgba(88,144,255,0.5); border: 1px solid rgba(88,144,255,0.7); }

table { 
  width: 100%; 
  border-collapse: collapse; 
  background: var(--glass-bg); 
  backdrop-filter: blur(10px);
  border-radius: 16px; 
  overflow: hidden; 
  margin: 20px 0; 
  border: 1.5px solid var(--border-color); 
  page-break-inside: avoid; 
}
th { 
  background: rgba(100,140,255,0.3); 
  color: var(--text-primary); 
  padding: 16px 18px; 
  text-align: left; 
  font-weight: 600; 
  border-bottom: 2px solid var(--border-color); 
}
td { 
  padding: 14px 18px; 
  border-bottom: 1px solid rgba(255,255,255,0.08); 
  color: var(--text-secondary); 
}
tr:hover td { background: rgba(100,140,255,0.1); }

.svg-flow { 
  background: var(--glass-bg); 
  backdrop-filter: blur(10px);
  border-radius: 20px; 
  padding: 30px; 
  margin: 30px 0; 
  border: 1.5px solid var(--border-color); 
  overflow-x: auto; 
  page-break-inside: avoid; 
  box-shadow: 0 4px 20px rgba(0,0,0,0.2);
}

.compare-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin: 30px 0; page-break-inside: avoid; }
.compare-card { 
  padding: 28px; 
  border-radius: 20px; 
  text-align: center; 
  transition: all 0.4s ease; 
  position: relative; 
  overflow: hidden; 
  backdrop-filter: blur(var(--glass-blur));
}
.compare-card.old { 
  background: rgba(232,84,84,0.15); 
  border: 2px solid rgba(232,84,84,0.5); 
}
.compare-card.new { 
  background: rgba(60,180,120,0.15); 
  border: 2px solid rgba(60,180,120,0.5); 
}
.compare-card:hover { transform: translateY(-5px); box-shadow: 0 0 30px rgba(0,0,0,0.3); }
.compare-card h4 { font-size: 22px; margin-bottom: 16px; color: var(--text-primary); }
.compare-card ul { text-align: left; list-style: none; }
.compare-card li { 
  padding: 12px 0; 
  border-bottom: 1px solid rgba(255,255,255,0.1); 
  color: var(--text-secondary); 
  transition: all 0.3s; 
}
.compare-card li:hover { padding-left: 10px; }
.compare-card li::before { content: '✓ '; color: var(--secondary); font-weight: bold; }
.compare-card.old li::before { content: '✗ '; color: var(--error); }

.footer { 
  text-align: center; 
  padding: 60px 20px; 
  color: var(--text-muted); 
  font-size: 14px; 
  border-top: 1px solid var(--border-color); 
  margin-top: 80px; 
}

@keyframes fadeInUp { from { opacity:0; transform:translateY(40px); } to { opacity:1; transform:translateY(0); } }
@keyframes scaleIn { from { opacity:0; transform:scale(0.85); } to { opacity:1; transform:scale(1); } }

.animate-on-scroll { 
  opacity: 0; 
  transform: translateY(40px); 
  transition: all 0.8s cubic-bezier(0.175,0.885,0.32,1.275); 
}
.animate-on-scroll.visible { 
  opacity: 1; 
  transform: translateY(0); 
}

.color-picker-toggle { 
  position: fixed; 
  bottom: 30px; 
  right: 30px; 
  width: 60px; 
  height: 60px; 
  border-radius: 50%; 
  background: linear-gradient(135deg, var(--primary), #7850c8); 
  border: none; 
  cursor: pointer; 
  z-index: 1000; 
  display: flex; 
  align-items: center; 
  justify-content: center; 
  box-shadow: 0 4px 25px rgba(100,140,255,0.5); 
  transition: all 0.3s ease; 
}
.color-picker-toggle:hover { 
  transform: scale(1.15); 
  box-shadow: 0 6px 35px rgba(100,140,255,0.7); 
}
.color-picker-toggle svg { width: 26px; height: 26px; fill: white; }

.color-panel { 
  position: fixed; 
  top: 0; 
  right: -420px; 
  width: 400px; 
  height: 100vh; 
  background: rgba(15, 18, 25, 0.95); 
  backdrop-filter: blur(30px);
  -webkit-backdrop-filter: blur(30px);
  border-left: 1.5px solid var(--border-color); 
  z-index: 1001; 
  transition: right 0.4s cubic-bezier(0.4, 0, 0.2, 1); 
  overflow-y: auto; 
  padding: 28px; 
}
.color-panel.open { right: 0; }
.color-panel-overlay { 
  position: fixed; 
  top: 0; left: 0; 
  width: 100%; height: 100%; 
  background: rgba(0,0,0,0.6); 
  z-index: 1000; 
  opacity: 0; 
  visibility: hidden; 
  transition: all 0.3s; 
}
.color-panel-overlay.visible { opacity: 1; visibility: visible; }

.panel-header { 
  display: flex; 
  justify-content: space-between; 
  align-items: center; 
  margin-bottom: 24px; 
  padding-bottom: 18px; 
  border-bottom: 1px solid rgba(255,255,255,0.1); 
}
.panel-header h3 { color: var(--text-primary); font-size: 20px; font-weight: 600; }
.panel-close { 
  background: rgba(255,255,255,0.1); 
  border: none; 
  color: var(--text-muted); 
  cursor: pointer; 
  font-size: 20px; 
  padding: 6px 10px; 
  border-radius: 8px;
  transition: all 0.2s;
}
.panel-close:hover { color: var(--text-primary); background: rgba(255,255,255,0.2); }

.panel-tabs { 
  display: flex; 
  gap: 4px; 
  margin-bottom: 24px; 
  background: rgba(255,255,255,0.05); 
  border-radius: 12px; 
  padding: 4px; 
}
.panel-tab { 
  flex: 1; 
  padding: 10px 14px; 
  background: none; 
  border: none; 
  border-radius: 10px; 
  color: var(--text-muted); 
  cursor: pointer; 
  font-size: 14px; 
  font-weight: 500;
  transition: all 0.2s; 
}
.panel-tab.active { background: var(--primary); color: white; }
.panel-tab:hover:not(.active) { background: rgba(255,255,255,0.1); }

.tab-content { display: none; }
.tab-content.active { display: block; }

.color-section { margin-bottom: 22px; }
.color-section label { 
  display: block; 
  color: var(--text-muted); 
  font-size: 13px; 
  margin-bottom: 8px; 
  font-weight: 500;
}

.hue-wheel-container { position: relative; width: 180px; height: 180px; margin: 0 auto 16px; cursor: crosshair; }
#hueWheel { width: 100%; height: 100%; border-radius: 50%; }
.hue-selector { 
  position: absolute; 
  width: 20px; height: 20px; 
  border-radius: 50%; 
  border: 3px solid white; 
  box-shadow: 0 0 12px rgba(0,0,0,0.6); 
  transform: translate(-50%, -50%); 
  pointer-events: none; 
}

.sv-container { position: relative; width: 180px; height: 120px; margin: 0 auto 16px; cursor: crosshair; }
#svPicker { width: 100%; height: 100%; border-radius: 10px; }
.sv-selector { 
  position: absolute; 
  width: 16px; height: 16px; 
  border-radius: 50%; 
  border: 2px solid white; 
  box-shadow: 0 0 10px rgba(0,0,0,0.6); 
  transform: translate(-50%, -50%); 
  pointer-events: none; 
}

.color-preview-row { display: flex; gap: 12px; align-items: center; margin-bottom: 14px; }
.color-preview-box { width: 44px; height: 44px; border-radius: 12px; border: 2px solid rgba(255,255,255,0.2); }
.color-input { 
  flex: 1; 
  background: rgba(255,255,255,0.08); 
  border: 1px solid rgba(255,255,255,0.15); 
  border-radius: 10px; 
  padding: 10px 12px; 
  color: var(--text-primary); 
  font-family: monospace; 
  font-size: 14px; 
}
.color-input:focus { outline: none; border-color: var(--primary); }

.color-target-list { display: flex; flex-direction: column; gap: 8px; }
.color-target-item { 
  display: flex; 
  align-items: center; 
  gap: 12px; 
  padding: 10px 12px; 
  background: rgba(255,255,255,0.04); 
  border-radius: 10px; 
  cursor: pointer; 
  transition: all 0.2s; 
  border: 1px solid transparent; 
}
.color-target-item:hover { background: rgba(255,255,255,0.08); border-color: var(--border-color); }
.color-target-item.active { border-color: var(--primary); background: rgba(100,140,255,0.15); }
.color-target-dot { width: 20px; height: 20px; border-radius: 6px; border: 1px solid rgba(255,255,255,0.2); }
.color-target-name { color: var(--text-secondary); font-size: 13px; }

.theme-presets { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.theme-btn { 
  padding: 12px; 
  border-radius: 12px; 
  border: 2px solid transparent; 
  background: rgba(255,255,255,0.05); 
  cursor: pointer; 
  transition: all 0.2s; 
  text-align: center; 
}
.theme-btn:hover { border-color: var(--border-color); background: rgba(255,255,255,0.08); }
.theme-btn.active { border-color: var(--primary); box-shadow: 0 0 15px rgba(100,140,255,0.3); }
.theme-btn .theme-color { width: 100%; height: 24px; border-radius: 8px; margin-bottom: 8px; }
.theme-btn .theme-name { color: var(--text-secondary); font-size: 12px; font-weight: 500; }

.effect-select { 
  width: 100%; 
  background: rgba(255,255,255,0.08); 
  border: 1px solid rgba(255,255,255,0.2); 
  border-radius: 10px; 
  padding: 10px 12px; 
  color: var(--text-primary); 
  font-size: 13px; 
  cursor: pointer;
}
.effect-select:focus { outline: none; border-color: var(--primary); }
.effect-select option { 
  background: #1a1e2e; 
  color: #e0e6ed; 
  padding: 8px;
}

.range-row { display: flex; align-items: center; gap: 12px; }
.range-row input[type="range"] { 
  flex: 1; 
  accent-color: var(--primary); 
  height: 6px; 
  cursor: pointer;
}
.range-value { 
  min-width: 40px; 
  text-align: right; 
  color: var(--text-muted); 
  font-size: 12px; 
  font-family: monospace; 
}

.export-section { margin-top: 50px; padding-top: 30px; border-top: 1px solid var(--border-color); }
.export-btn { 
  display: inline-flex; 
  align-items: center; 
  gap: 12px; 
  padding: 16px 36px; 
  background: linear-gradient(135deg, var(--primary), #7850c8); 
  color: white; 
  border: none; 
  border-radius: 16px; 
  font-size: 16px; 
  font-weight: 600; 
  cursor: pointer; 
  transition: all 0.3s ease; 
  box-shadow: 0 4px 20px rgba(100,140,255,0.4); 
}
.export-btn:hover { 
  transform: translateY(-4px); 
  box-shadow: 0 8px 30px rgba(100,140,255,0.6); 
}

.add-paragraph-btn {
  display: inline-flex; 
  align-items: center; 
  gap: 10px; 
  padding: 14px 28px; 
  background: var(--glass-bg);
  backdrop-filter: blur(10px);
  border: 2px dashed var(--border-color); 
  border-radius: 16px; 
  color: var(--text-muted); 
  cursor: pointer; 
  font-size: 14px;
  font-weight: 500;
  transition: all 0.3s;
}
.add-paragraph-btn:hover {
  border-color: var(--primary);
  color: var(--text-primary);
  background: rgba(100,140,255,0.1);
}

.save-indicator {
  position: fixed;
  top: 20px;
  right: 20px;
  background: rgba(60,180,120,0.9);
  color: white;
  padding: 10px 20px;
  border-radius: 10px;
  font-size: 14px;
  font-weight: 500;
  z-index: 2000;
  opacity: 0;
  transform: translateY(-20px);
  transition: all 0.3s ease;
  pointer-events: none;
}
.save-indicator.show {
  opacity: 1;
  transform: translateY(0);
}

@media print {
  @page { size: A4; margin: 2cm; }
  body { background: white !important; color: #333 !important; }
  .galaxy-bg, #effectCanvas, .color-picker-toggle, .color-panel, .color-panel-overlay, .save-indicator { display: none !important; }
  .export-section { display: none !important; }
  .glass-card, .stat-card, .timeline-item { 
    background: #f8f9fa !important; 
    backdrop-filter: none !important;
    border: 1px solid #ddd !important; 
    box-shadow: none !important; 
  }
  .glass-card p, .glass-card li, .glass-card td { color: #333 !important; }
  .glass-card strong { color: #000 !important; }
}

@media (max-width:768px) { 
  .stats-grid { grid-template-columns: repeat(2,1fr); } 
  .compare-grid { grid-template-columns: 1fr; } 
  .hero h1 { font-size: 28px; }
  .color-panel { width: 100%; right: -100%; }
}
</style>
</head>
<body>

<div class="galaxy-bg"></div>
<canvas id="effectCanvas"></canvas>
<div class="save-indicator" id="saveIndicator">✓ 设置已保存</div>

<button class="color-picker-toggle" id="colorPickerToggle" title="自定义设置">
  <svg viewBox="0 0 24 24"><path d="M12 2C6.49 2 2 6.49 2 12s4.49 10 10 10c1.38 0 2.5-1.12 2.5-2.5 0-.61-.23-1.2-.64-1.67-.08-.1-.13-.21-.13-.33 0-.28.22-.5.5-.5H16c3.31 0 6-2.69 6-6 0-4.96-4.49-9-10-9zm-5.5 9c-.83 0-1.5-.67-1.5-1.5S5.67 8 6.5 8 8 8.67 8 9.5 7.33 11 6.5 11zm3-4C8.67 7 8 6.33 8 5.5S8.67 4 9.5 4s1.5.67 1.5 1.5S10.33 7 9.5 7zm5 0c-.83 0-1.5-.67-1.5-1.5S13.67 4 14.5 4s1.5.67 1.5 1.5S15.33 7 14.5 7zm3 4c-.83 0-1.5-.67-1.5-1.5S16.67 8 17.5 8s1.5.67 1.5 1.5-.67 1.5-1.5 1.5z"/></svg>
</button>

<div class="color-panel-overlay" id="colorPanelOverlay"></div>

<div class="color-panel" id="colorPanel">
  <div class="panel-header">
    <h3>✨ 自定义设置</h3>
    <button class="panel-close" id="colorPanelClose">✕</button>
  </div>
  
  <div class="panel-tabs">
    <button class="panel-tab active" data-tab="colors">🎨 颜色</button>
    <button class="panel-tab" data-tab="effects">✨ 动效</button>
    <button class="panel-tab" data-tab="fonts">📝 字体</button>
  </div>
  
  <div class="tab-content active" id="tab-colors">
    <div class="color-section">
      <label>色相选择</label>
      <div class="hue-wheel-container">
        <canvas id="hueWheel" width="180" height="180"></canvas>
        <div class="hue-selector" id="hueSelector"></div>
      </div>
    </div>
    <div class="color-section">
      <label>饱和度 / 明度</label>
      <div class="sv-container">
        <canvas id="svPicker" width="180" height="120"></canvas>
        <div class="sv-selector" id="svSelector"></div>
      </div>
    </div>
    <div class="color-section">
      <label>当前颜色</label>
      <div class="color-preview-row">
        <div class="color-preview-box" id="colorPreview"></div>
        <input type="text" class="color-input" id="colorInput" value="#648cff">
      </div>
    </div>
    <div class="color-section">
      <label>应用到</label>
      <div class="color-target-list">
        <div class="color-target-item active" data-var="--bg-main">
          <div class="color-target-dot" style="background: var(--bg-main)"></div>
          <span class="color-target-name">页面背景</span>
        </div>
        <div class="color-target-item" data-var="--primary">
          <div class="color-target-dot" style="background: var(--primary)"></div>
          <span class="color-target-name">主色调</span>
        </div>
        <div class="color-target-item" data-var="--secondary">
          <div class="color-target-dot" style="background: var(--secondary)"></div>
          <span class="color-target-name">辅助色</span>
        </div>
        <div class="color-target-item" data-var="--accent">
          <div class="color-target-dot" style="background: var(--accent)"></div>
          <span class="color-target-name">强调色</span>
        </div>
        <div class="color-target-item" data-var="--border-color">
          <div class="color-target-dot" style="background: var(--border-color)"></div>
          <span class="color-target-name">边框颜色</span>
        </div>
        <div class="color-target-item" data-var="--text-primary">
          <div class="color-target-dot" style="background: var(--text-primary)"></div>
          <span class="color-target-name">标题颜色</span>
        </div>
      </div>
    </div>
    <div class="color-section">
      <label>预设主题</label>
      <div class="theme-presets">
        <button class="theme-btn active" data-theme="galaxy">
          <div class="theme-color" style="background: linear-gradient(135deg, #0d1117, #648cff)"></div>
          <span class="theme-name">银河</span>
        </button>
        <button class="theme-btn" data-theme="ocean">
          <div class="theme-color" style="background: linear-gradient(135deg, #0a1628, #0ea5e9)"></div>
          <span class="theme-name">深海</span>
        </button>
        <button class="theme-btn" data-theme="forest">
          <div class="theme-color" style="background: linear-gradient(135deg, #0a1a0f, #22c55e)"></div>
          <span class="theme-name">森林</span>
        </button>
        <button class="theme-btn" data-theme="sunset">
          <div class="theme-color" style="background: linear-gradient(135deg, #1a0f0a, #f97316)"></div>
          <span class="theme-name">日落</span>
        </button>
        <button class="theme-btn" data-theme="lavender">
          <div class="theme-color" style="background: linear-gradient(135deg, #150a1a, #a855f7)"></div>
          <span class="theme-name">薰衣草</span>
        </button>
        <button class="theme-btn" data-theme="rose">
          <div class="theme-color" style="background: linear-gradient(135deg, #1a0a10, #f43f5e)"></div>
          <span class="theme-name">玫瑰</span>
        </button>
        <button class="theme-btn" data-theme="cyberpunk">
          <div class="theme-color" style="background: linear-gradient(135deg, #0a0a1a, #00ff88)"></div>
          <span class="theme-name">赛博朋克</span>
        </button>
        <button class="theme-btn" data-theme="golden">
          <div class="theme-color" style="background: linear-gradient(135deg, #1a150a, #fbbf24)"></div>
          <span class="theme-name">黄金</span>
        </button>
      </div>
    </div>
  </div>
  
  <div class="tab-content" id="tab-effects">
    <div class="color-section">
      <label>背景动效</label>
      <select id="bgEffect" class="effect-select">
        <option value="particles">✨ 粒子飘浮</option>
        <option value="stars">⭐ 星空闪烁</option>
        <option value="snow">❄️ 雪花飘落</option>
        <option value="bubbles">🫧 泡泡上升</option>
        <option value="grid">🔲 网格连线</option>
        <option value="waves">🌊 波浪流动</option>
        <option value="firefly">🪲 萤火虫</option>
        <option value="matrix">💚 矩阵雨</option>
        <option value="nebula">🌀 星云漩涡</option>
        <option value="confetti">🎊 彩纸飘落</option>
        <option value="none">❌ 无动效</option>
      </select>
    </div>
    <div class="color-section">
      <label>动效密度: <span id="densityValue">50</span></label>
      <div class="range-row">
        <input type="range" id="effectDensity" min="10" max="100" value="50">
      </div>
    </div>
    <div class="color-section">
      <label>动效速度: <span id="speedValue">50</span></label>
      <div class="range-row">
        <input type="range" id="effectSpeed" min="10" max="100" value="50">
      </div>
    </div>
    <div class="color-section" style="border-top: 1px solid rgba(255,255,255,0.1); padding-top: 18px; margin-top: 18px;">
      <label>鼠标动效</label>
      <select id="cursorEffect" class="effect-select">
        <option value="glow">💡 泛光跟随</option>
        <option value="trail">✨ 拖尾光轨</option>
        <option value="galaxy">🌀 星河轨迹</option>
        <option value="firework">🎆 烟花点击</option>
        <option value="sparkle">⭐ 星星闪烁</option>
        <option value="rainbow">🌈 彩虹光环</option>
        <option value="ripple">💫 波纹扩散</option>
        <option value="magnetic">🧲 磁性吸引</option>
        <option value="none">❌ 无动效</option>
      </select>
    </div>
    <div class="color-section">
      <label>鼠标效果大小: <span id="cursorSizeValue">30</span></label>
      <div class="range-row">
        <input type="range" id="cursorSize" min="10" max="60" value="30">
      </div>
    </div>
    <div class="color-section" style="border-top: 1px solid rgba(255,255,255,0.1); padding-top: 18px; margin-top: 18px;">
      <label>卡片边框样式</label>
      <select id="cardStyle" class="effect-select">
        <option value="glass">🪟 毛玻璃</option>
        <option value="neon">💜 霓虹发光</option>
        <option value="gradient">🌈 渐变边框</option>
        <option value="solid">📏 实线边框</option>
        <option value="dashed">📐 虚线边框</option>
      </select>
    </div>
    <div class="color-section">
      <label>毛玻璃强度: <span id="blurValue">20</span>px</label>
      <div class="range-row">
        <input type="range" id="glassBlur" min="0" max="40" value="20">
      </div>
    </div>
    <div class="color-section">
      <label>边框圆角: <span id="radiusValue">20</span>px</label>
      <div class="range-row">
        <input type="range" id="borderRadius" min="0" max="32" value="20">
      </div>
    </div>
    <div class="color-section">
      <label>卡片透明度: <span id="cardOpacityValue">70</span>%</label>
      <div class="range-row">
        <input type="range" id="cardOpacity" min="20" max="95" value="70">
      </div>
    </div>
  </div>
  
  <div class="tab-content" id="tab-fonts">
    <div class="color-section">
      <label>字体</label>
      <select id="fontFamily" class="effect-select">
        <option value='-apple-system, "Microsoft YaHei", sans-serif'>系统默认</option>
        <option value='"Microsoft YaHei", "微软雅黑", sans-serif'>微软雅黑</option>
        <option value='"SimSun", "宋体", serif'>宋体</option>
        <option value='"SimHei", "黑体", sans-serif'>黑体</option>
        <option value='"KaiTi", "楷体", serif'>楷体</option>
        <option value='"FangSong", "仿宋", serif'>仿宋</option>
        <option value='"Cascadia Code", "Fira Code", monospace'>等宽代码</option>
        <option value='Arial, Helvetica, sans-serif'>Arial</option>
        <option value='Georgia, "Times New Roman", serif'>Georgia</option>
      </select>
    </div>
    <div class="color-section">
      <label>正文字号: <span id="fontSizeValue">16px</span></label>
      <div class="range-row">
        <input type="range" id="fontSize" min="12" max="24" value="16">
      </div>
    </div>
    <div class="color-section">
      <label>行高: <span id="lineHeightValue">1.8</span></label>
      <div class="range-row">
        <input type="range" id="lineHeight" min="1.2" max="2.5" step="0.1" value="1.8">
      </div>
    </div>
    <div class="color-section">
      <label>标题字号: <span id="headingSizeValue">30px</span></label>
      <div class="range-row">
        <input type="range" id="headingSize" min="20" max="48" value="30">
      </div>
    </div>
  </div>
</div>

<div class="container">

<div class="hero">
  <h1>{{TITLE}}</h1>
  <div class="subtitle">{{SUBTITLE}}</div>
  <div class="meta">{{META}}</div>
</div>

<div class="stats-grid">
  <div class="stat-card"><div class="number">{{STAT1_NUMBER}}</div><div class="label">{{STAT1_LABEL}}</div></div>
  <div class="stat-card"><div class="number">{{STAT2_NUMBER}}</div><div class="label">{{STAT2_LABEL}}</div></div>
  <div class="stat-card"><div class="number">{{STAT3_NUMBER}}</div><div class="label">{{STAT3_LABEL}}</div></div>
  <div class="stat-card"><div class="number">{{STAT4_NUMBER}}</div><div class="label">{{STAT4_LABEL}}</div></div>
</div>

{{CONTENT}}

<div style="margin: 40px 0; text-align: center;">
  <button class="add-paragraph-btn" id="addParagraphBtn">
    <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
    添加新段落
  </button>
</div>

<div class="export-section">
  <button class="export-btn" id="exportPdfBtn">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="20" height="20">
      <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
      <polyline points="14 2 14 8 20 8"></polyline>
    </svg>
    导出为 PDF
  </button>
</div>

<div class="footer">
  <p>{{FOOTER}}</p>
</div>

</div>

<div id="addParagraphModal" style="display: none; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(15,18,25,0.98); backdrop-filter: blur(30px); border: 1.5px solid var(--border-color); border-radius: 20px; padding: 32px; z-index: 2000; width: 500px; max-width: 90vw; box-shadow: 0 20px 60px rgba(0,0,0,0.5);">
  <h3 style="color: var(--text-primary); margin-bottom: 20px; font-size: 20px;">添加新段落</h3>
  <div style="margin-bottom: 16px;">
    <label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">段落类型</label>
    <div style="display: flex; gap: 10px;">
      <button id="typeSection" class="type-btn active" style="flex: 1; padding: 10px; background: rgba(100,140,255,0.2); border: 1.5px solid var(--primary); border-radius: 10px; color: var(--text-primary); cursor: pointer; font-size: 13px;">📦 大段(新章节)</button>
      <button id="typeCard" class="type-btn" style="flex: 1; padding: 10px; background: rgba(255,255,255,0.05); border: 1.5px solid rgba(255,255,255,0.2); border-radius: 10px; color: var(--text-muted); cursor: pointer; font-size: 13px;">📄 小段(卡片)</button>
    </div>
  </div>
  <div style="margin-bottom: 16px;">
    <label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">插入位置</label>
    <select id="insertPosition" class="effect-select" style="width: 100%; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.2); border-radius: 10px; padding: 10px 12px; color: var(--text-primary); font-size: 13px;">
      <option value="end" style="background: #1a1e2e; color: #e0e6ed;">末尾</option>
    </select>
  </div>
  <div style="margin-bottom: 16px;">
    <label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">段落标题</label>
    <input type="text" id="newParagraphTitle" placeholder="输入段落标题" style="width: 100%; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.2); border-radius: 10px; padding: 12px; color: var(--text-primary); font-size: 14px;">
  </div>
  <div style="margin-bottom: 20px;">
    <label style="display: block; color: var(--text-muted); font-size: 13px; margin-bottom: 8px;">段落内容</label>
    <textarea id="newParagraphContent" rows="4" placeholder="输入段落内容" style="width: 100%; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.2); border-radius: 10px; padding: 12px; color: var(--text-primary); font-size: 14px; resize: vertical;"></textarea>
  </div>
  <div style="display: flex; gap: 12px; justify-content: flex-end;">
    <button id="cancelAddParagraph" style="padding: 10px 24px; background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); border-radius: 10px; color: var(--text-secondary); cursor: pointer; font-size: 14px;">取消</button>
    <button id="confirmAddParagraph" style="padding: 10px 24px; background: linear-gradient(135deg, var(--primary), #7850c8); border: none; border-radius: 10px; color: white; cursor: pointer; font-size: 14px; font-weight: 500;">添加</button>
  </div>
</div>
<div id="addParagraphOverlay" style="display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.6); z-index: 1999;"></div>

<script>
const STORAGE_KEY = 'html-doc-settings';
function loadSettings() { try { const s = localStorage.getItem(STORAGE_KEY); if (s) return JSON.parse(s); } catch(e) {} return null; }
function saveSettings() {
  const s = { theme: document.querySelector('.theme-btn.active')?.dataset.theme||'galaxy', bgEffect: document.getElementById('bgEffect').value, cursorEffect: document.getElementById('cursorEffect').value, effectDensity: document.getElementById('effectDensity').value, effectSpeed: document.getElementById('effectSpeed').value, cursorSize: document.getElementById('cursorSize').value, cardStyle: document.getElementById('cardStyle').value, glassBlur: document.getElementById('glassBlur').value, borderRadius: document.getElementById('borderRadius').value, cardOpacity: document.getElementById('cardOpacity').value, fontFamily: document.getElementById('fontFamily').value, fontSize: document.getElementById('fontSize').value, lineHeight: document.getElementById('lineHeight').value, headingSize: document.getElementById('headingSize').value, colors: { '--bg-main': getComputedStyle(document.documentElement).getPropertyValue('--bg-main').trim(), '--primary': getComputedStyle(document.documentElement).getPropertyValue('--primary').trim(), '--secondary': getComputedStyle(document.documentElement).getPropertyValue('--secondary').trim(), '--accent': getComputedStyle(document.documentElement).getPropertyValue('--accent').trim(), '--border-color': getComputedStyle(document.documentElement).getPropertyValue('--border-color').trim(), '--text-primary': getComputedStyle(document.documentElement).getPropertyValue('--text-primary').trim() } };
  localStorage.setItem(STORAGE_KEY, JSON.stringify(s));
  const ind = document.getElementById('saveIndicator'); ind.classList.add('show'); setTimeout(()=>ind.classList.remove('show'), 1500);
}

const canvas = document.getElementById('effectCanvas');
const ctx = canvas.getContext('2d');
let particles = [], mouseX = 0, mouseY = 0, cursorTrail = [];
let currentBgEffect = 'particles', currentCursorEffect = 'glow';
let effectDensity = 50, effectSpeed = 50, cursorSize = 30;
let currentCardStyle = 'glass', glassBlur = 20, borderRadius = 20, cardOpacity = 70;

function resizeCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; }
resizeCanvas(); window.addEventListener('resize', resizeCanvas);

class Particle {
  constructor(type) { this.type = type; this.reset(); }
  reset() {
    this.x = Math.random()*canvas.width; this.y = Math.random()*canvas.height;
    this.size = Math.random()*3+1; this.speedX = (Math.random()-.5)*(effectSpeed/30); this.speedY = (Math.random()-.5)*(effectSpeed/30);
    this.opacity = Math.random()*0.8+0.2; this.life = 1; this.decay = Math.random()*0.001+0.0005;
    if (this.type==='snow') { this.speedX=(Math.random()-.5)*0.5; this.speedY=Math.random()*(effectSpeed/25)+0.3; }
    else if (this.type==='bubbles') { this.speedX=(Math.random()-.5)*0.3; this.speedY=-(Math.random()*(effectSpeed/25)+0.3); this.size=Math.random()*6+2; }
    else if (this.type==='firefly') { this.speedX=(Math.random()-.5)*0.2; this.speedY=(Math.random()-.5)*0.2; this.size=Math.random()*3+2; }
    else if (this.type==='confetti') { this.speedX=(Math.random()-.5)*1.5; this.speedY=Math.random()*1.5+0.5; this.rotation=Math.random()*360; this.rotSpeed=(Math.random()-.5)*4; this.color=`hsl(${Math.random()*360},70%,60%)`; this.size=Math.random()*5+3; }
    else if (this.type==='matrix') { this.speedX=0; this.speedY=Math.random()*(effectSpeed/15)+1; this.char=String.fromCharCode(0x30A0+Math.random()*96); this.size=12; }
  }
  update() {
    this.x+=this.speedX; this.y+=this.speedY; this.life-=this.decay;
    if (this.type==='firefly') { this.speedX+=(Math.random()-.5)*0.05; this.speedY+=(Math.random()-.5)*0.05; this.opacity=0.3+Math.sin(Date.now()*0.003+this.x)*0.5; }
    if (this.type==='confetti') { this.rotation+=this.rotSpeed; this.speedX*=0.99; }
    if (this.life<=0||this.x<-50||this.x>canvas.width+50||this.y<-50||this.y>canvas.height+50) { this.reset(); if (['snow','bubbles','confetti','matrix'].includes(this.type)) { this.y=this.type==='bubbles'?canvas.height+10:-10; this.x=Math.random()*canvas.width; } }
  }
  draw() {
    ctx.save(); ctx.globalAlpha=this.opacity*Math.min(this.life,1);
    if (['particles','stars','snow','firefly'].includes(this.type)) { ctx.beginPath(); ctx.arc(this.x,this.y,this.size,0,Math.PI*2); ctx.fillStyle=this.type==='firefly'?`rgba(255,255,150,${this.opacity})`:'rgba(100,140,255,0.7)'; ctx.fill(); if(this.type==='firefly'){ctx.shadowBlur=10;ctx.shadowColor='rgba(255,255,150,0.5)';ctx.fill();} }
    else if (this.type==='bubbles') { ctx.beginPath(); ctx.arc(this.x,this.y,this.size,0,Math.PI*2); ctx.strokeStyle=`rgba(100,200,255,${this.opacity*0.5})`; ctx.lineWidth=1.5; ctx.stroke(); }
    else if (this.type==='confetti') { ctx.translate(this.x,this.y); ctx.rotate(this.rotation*Math.PI/180); ctx.fillStyle=this.color; ctx.fillRect(-this.size/2,-this.size/4,this.size,this.size/2); }
    else if (this.type==='matrix') { ctx.font=`${this.size}px monospace`; ctx.fillStyle=`rgba(0,255,0,${this.opacity*0.8})`; ctx.fillText(this.char,this.x,this.y); }
    else { ctx.beginPath(); ctx.arc(this.x,this.y,this.size,0,Math.PI*2); ctx.fillStyle='rgba(100,140,255,0.6)'; ctx.fill(); }
    ctx.restore();
  }
}

function initParticles() { particles=[]; for(let i=0;i<Math.floor(effectDensity*1.2);i++) particles.push(new Particle(currentBgEffect)); }
let waveOffset=0, nebulaAngle=0;

function drawGrid() {
  const g=60; ctx.strokeStyle='rgba(100,140,255,0.06)'; ctx.lineWidth=1;
  for(let x=0;x<canvas.width;x+=g){ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,canvas.height);ctx.stroke();}
  for(let y=0;y<canvas.height;y+=g){ctx.beginPath();ctx.moveTo(0,y);ctx.lineTo(canvas.width,y);ctx.stroke();}
  for(let x=0;x<canvas.width;x+=g) for(let y=0;y<canvas.height;y+=g) { const d=Math.sqrt((mouseX-x)**2+(mouseY-y)**2); if(d<200){ctx.strokeStyle=`rgba(100,140,255,${0.3*(1-d/200)})`;ctx.beginPath();ctx.moveTo(x,y);ctx.lineTo(mouseX,mouseY);ctx.stroke();} }
}

function drawWaves() {
  waveOffset+=effectSpeed*0.008;
  for(let i=0;i<3;i++){ctx.beginPath();ctx.moveTo(0,canvas.height);for(let x=0;x<canvas.width;x+=5){const y=canvas.height-80-i*40+Math.sin(x*0.008+waveOffset+i*2)*40;ctx.lineTo(x,y);}ctx.lineTo(canvas.width,canvas.height);ctx.closePath();ctx.fillStyle=`rgba(100,140,255,${0.04+i*0.02})`;ctx.fill();}
}

function drawNebula() {
  nebulaAngle+=effectSpeed*0.0005;
  const cx=canvas.width/2, cy=canvas.height/2;
  for(let i=0;i<5;i++){const a=nebulaAngle+(i*Math.PI*2/5),r=150+i*60,x=cx+Math.cos(a)*r,y=cy+Math.sin(a)*r;const g=ctx.createRadialGradient(x,y,0,x,y,80);g.addColorStop(0,'rgba(100,140,255,0.12)');g.addColorStop(1,'transparent');ctx.fillStyle=g;ctx.beginPath();ctx.arc(x,y,80,0,Math.PI*2);ctx.fill();}
}

function drawCursorEffect() {
  if(currentCursorEffect==='none') return;
  switch(currentCursorEffect) {
    case 'glow': const g=ctx.createRadialGradient(mouseX,mouseY,0,mouseX,mouseY,cursorSize*6);g.addColorStop(0,'rgba(100,140,255,0.2)');g.addColorStop(0.5,'rgba(100,140,255,0.05)');g.addColorStop(1,'transparent');ctx.fillStyle=g;ctx.beginPath();ctx.arc(mouseX,mouseY,cursorSize*6,0,Math.PI*2);ctx.fill();break;
    case 'trail': cursorTrail.push({x:mouseX,y:mouseY,life:1});if(cursorTrail.length>25)cursorTrail.shift();for(let i=0;i<cursorTrail.length;i++){const p=cursorTrail[i];p.life-=0.04;if(p.life>0){ctx.beginPath();ctx.arc(p.x,p.y,cursorSize*p.life*0.3,0,Math.PI*2);ctx.fillStyle=`rgba(100,140,255,${p.life*0.4})`;ctx.fill();}}cursorTrail=cursorTrail.filter(p=>p.life>0);break;
    case 'galaxy': cursorTrail.push({x:mouseX,y:mouseY,life:1,angle:Math.random()*Math.PI*2});if(cursorTrail.length>40)cursorTrail.shift();for(let i=0;i<cursorTrail.length;i++){const p=cursorTrail[i];p.life-=0.025;p.angle+=0.08;const x=p.x+Math.cos(p.angle)*i*0.6,y=p.y+Math.sin(p.angle)*i*0.6;ctx.beginPath();ctx.arc(x,y,2,0,Math.PI*2);ctx.fillStyle=`hsla(${220+i*4},80%,65%,${p.life*0.6})`;ctx.fill();}cursorTrail=cursorTrail.filter(p=>p.life>0);break;
    case 'sparkle': for(let i=0;i<3;i++){const x=mouseX+(Math.random()-.5)*cursorSize*3,y=mouseY+(Math.random()-.5)*cursorSize*3;ctx.beginPath();ctx.arc(x,y,Math.random()*2.5,0,Math.PI*2);ctx.fillStyle=`rgba(255,255,200,${Math.random()*0.8})`;ctx.fill();}break;
    case 'rainbow': const t=Date.now()*0.003;for(let i=0;i<8;i++){const a=t+(i*Math.PI/4),x=mouseX+Math.cos(a)*cursorSize,y=mouseY+Math.sin(a)*cursorSize;ctx.beginPath();ctx.arc(x,y,4,0,Math.PI*2);ctx.fillStyle=`hsl(${i*45},80%,65%)`;ctx.fill();}break;
    case 'ripple': if(!window.ripples)window.ripples=[];if(Math.random()<0.1)window.ripples.push({x:mouseX,y:mouseY,radius:0,life:1});window.ripples.forEach(r=>{r.radius+=2;r.life-=0.02;if(r.life>0){ctx.beginPath();ctx.arc(r.x,r.y,r.radius,0,Math.PI*2);ctx.strokeStyle=`rgba(100,140,255,${r.life*0.3})`;ctx.lineWidth=2;ctx.stroke();}});window.ripples=window.ripples.filter(r=>r.life>0);break;
    case 'magnetic': particles.forEach(p=>{const d=Math.sqrt((mouseX-p.x)**2+(mouseY-p.y)**2);if(d<200){const f=(200-d)/200;p.x+=(mouseX-p.x)*f*0.02;p.y+=(mouseY-p.y)*f*0.02;}});break;
  }
}

let fireworks=[];
class Firework {
  constructor(x,y){this.x=x;this.y=y;this.particles=[];for(let i=0;i<25;i++){const a=(Math.PI*2/25)*i,s=Math.random()*3+1.5;this.particles.push({x,y,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:1,color:`hsl(${Math.random()*360},80%,65%)`});}}
  update(){this.particles.forEach(p=>{p.x+=p.vx;p.y+=p.vy;p.vy+=0.04;p.life-=0.015;});this.particles=this.particles.filter(p=>p.life>0);}
  draw(){this.particles.forEach(p=>{ctx.globalAlpha=p.life;ctx.beginPath();ctx.arc(p.x,p.y,2,0,Math.PI*2);ctx.fillStyle=p.color;ctx.fill();});ctx.globalAlpha=1;}
}

function animate() {
  ctx.clearRect(0,0,canvas.width,canvas.height);
  if(currentBgEffect!=='none'){if(['particles','stars','snow','bubbles','firefly','confetti','matrix'].includes(currentBgEffect))particles.forEach(p=>{p.update();p.draw();});else if(currentBgEffect==='grid')drawGrid();else if(currentBgEffect==='waves')drawWaves();else if(currentBgEffect==='nebula')drawNebula();}
  drawCursorEffect();
  fireworks.forEach(f=>{f.update();f.draw();}); fireworks=fireworks.filter(f=>f.particles.length>0);
  requestAnimationFrame(animate);
}

document.addEventListener('mousemove', e=>{mouseX=e.clientX;mouseY=e.clientY;});
document.addEventListener('click', e=>{if(currentCursorEffect==='firework')fireworks.push(new Firework(e.clientX,e.clientY));});
initParticles(); animate();

const colorPickerToggle=document.getElementById('colorPickerToggle');
const colorPanel=document.getElementById('colorPanel');
const colorPanelOverlay=document.getElementById('colorPanelOverlay');
const colorPanelClose=document.getElementById('colorPanelClose');
colorPickerToggle.addEventListener('click',()=>{colorPanel.classList.add('open');colorPanelOverlay.classList.add('visible');});
colorPanelClose.addEventListener('click',()=>{colorPanel.classList.remove('open');colorPanelOverlay.classList.remove('visible');});
colorPanelOverlay.addEventListener('click',()=>{colorPanel.classList.remove('open');colorPanelOverlay.classList.remove('visible');});
document.querySelectorAll('.panel-tab').forEach(tab=>{tab.addEventListener('click',()=>{document.querySelectorAll('.panel-tab').forEach(t=>t.classList.remove('active'));document.querySelectorAll('.tab-content').forEach(c=>c.classList.remove('active'));tab.classList.add('active');document.getElementById('tab-'+tab.dataset.tab).classList.add('active');});});

const hueWheel=document.getElementById('hueWheel'),svPicker=document.getElementById('svPicker');
let currentHue=220,currentSat=100,currentVal=100,activeTarget='--bg-main';
function drawHueWheel(){const w=hueWheel.getContext('2d'),cx=90,cy=90,r=80;for(let a=0;a<360;a++){const s=(a-1)*Math.PI/180,e=(a+1)*Math.PI/180;w.beginPath();w.moveTo(cx,cy);w.arc(cx,cy,r,s,e);w.closePath();w.fillStyle=`hsl(${a},100%,50%)`;w.fill();}w.beginPath();w.arc(cx,cy,r*0.45,0,Math.PI*2);w.fillStyle='#0d1117';w.fill();}
function drawSVPicker(){const s=svPicker.getContext('2d'),w=180,h=120;const gH=s.createLinearGradient(0,0,w,0);gH.addColorStop(0,'#fff');gH.addColorStop(1,`hsl(${currentHue},100%,50%)`);s.fillStyle=gH;s.fillRect(0,0,w,h);const gV=s.createLinearGradient(0,0,0,h);gV.addColorStop(0,'transparent');gV.addColorStop(1,'#000');s.fillStyle=gV;s.fillRect(0,0,w,h);}
function hsvToRgb(h,s,v){s/=100;v/=100;const c=v*s,x=c*(1-Math.abs((h/60)%2-1)),m=v-c;let r,g,b;if(h<60){r=c;g=x;b=0;}else if(h<120){r=x;g=c;b=0;}else if(h<180){r=0;g=c;b=x;}else if(h<240){r=0;g=x;b=c;}else if(h<300){r=x;g=0;b=c;}else{r=c;g=0;b=x;}return[Math.round((r+m)*255),Math.round((g+m)*255),Math.round((b+m)*255)];}
function rgbToHex(r,g,b){return'#'+[r,g,b].map(x=>x.toString(16).padStart(2,'0')).join('');}
function updateColor(){const[r,g,b]=hsvToRgb(currentHue,currentSat,currentVal);const h=rgbToHex(r,g,b);document.getElementById('colorPreview').style.background=h;document.getElementById('colorInput').value=h;document.documentElement.style.setProperty(activeTarget,h);const ai=document.querySelector(`.color-target-item[data-var="${activeTarget}"]`);if(ai)ai.querySelector('.color-target-dot').style.background=h;if(activeTarget==='--bg-main'){document.querySelector('.galaxy-bg').style.background=`linear-gradient(135deg,${h} 0%,${h}dd 50%,${h} 100%)`;document.body.style.background=h;}saveSettings();}
hueWheel.addEventListener('mousedown',e=>{const rect=hueWheel.getBoundingClientRect();function onMove(e){const x=e.clientX-rect.left-90,y=e.clientY-rect.top-90;currentHue=(Math.atan2(y,x)*180/Math.PI+360)%360;const d=Math.min(Math.sqrt(x*x+y*y),80);document.getElementById('hueSelector').style.left=(90+Math.cos(currentHue*Math.PI/180)*d)+'px';document.getElementById('hueSelector').style.top=(90+Math.sin(currentHue*Math.PI/180)*d)+'px';drawSVPicker();updateColor();}function onUp(){document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);saveSettings();}document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);onMove(e);});
svPicker.addEventListener('mousedown',e=>{const rect=svPicker.getBoundingClientRect();function onMove(e){currentSat=Math.max(0,Math.min(100,((e.clientX-rect.left)/rect.width)*100));currentVal=Math.max(0,Math.min(100,100-((e.clientY-rect.top)/rect.height)*100));document.getElementById('svSelector').style.left=currentSat+'%';document.getElementById('svSelector').style.top=(100-currentVal)+'%';updateColor();}function onUp(){document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);saveSettings();}document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);onMove(e);});
drawHueWheel();drawSVPicker();
document.querySelectorAll('.color-target-item').forEach(item=>{item.addEventListener('click',()=>{document.querySelectorAll('.color-target-item').forEach(i=>i.classList.remove('active'));item.classList.add('active');activeTarget=item.dataset.var;const c=getComputedStyle(document.documentElement).getPropertyValue(activeTarget).trim();document.getElementById('colorInput').value=c;document.getElementById('colorPreview').style.background=c;});});

const themes={galaxy:{'--bg-main':'#0d1117','--primary':'#648cff','--secondary':'#3cb478','--accent':'#e8a838','--error':'#e85454','--border-color':'rgba(100,140,255,0.5)','--text-primary':'#ffffff','--text-secondary':'#e0e6ed','--glow-color':'rgba(100,140,255,0.4)'},ocean:{'--bg-main':'#0a1628','--primary':'#0ea5e9','--secondary':'#06b6d4','--accent':'#f59e0b','--error':'#ef4444','--border-color':'rgba(14,165,233,0.5)','--text-primary':'#e0f2fe','--text-secondary':'#bae6fd','--glow-color':'rgba(14,165,233,0.4)'},forest:{'--bg-main':'#0a1a0f','--primary':'#22c55e','--secondary':'#84cc16','--accent':'#f97316','--error':'#ef4444','--border-color':'rgba(34,197,94,0.5)','--text-primary':'#dcfce7','--text-secondary':'#bbf7d0','--glow-color':'rgba(34,197,94,0.4)'},sunset:{'--bg-main':'#1a0f0a','--primary':'#f97316','--secondary':'#eab308','--accent':'#ec4899','--error':'#ef4444','--border-color':'rgba(249,115,22,0.5)','--text-primary':'#fff7ed','--text-secondary':'#fed7aa','--glow-color':'rgba(249,115,22,0.4)'},lavender:{'--bg-main':'#150a1a','--primary':'#a855f7','--secondary':'#ec4899','--accent':'#06b6d4','--error':'#ef4444','--border-color':'rgba(168,85,247,0.5)','--text-primary':'#f3e8ff','--text-secondary':'#e9d5ff','--glow-color':'rgba(168,85,247,0.4)'},rose:{'--bg-main':'#1a0a10','--primary':'#f43f5e','--secondary':'#8b5cf6','--accent':'#14b8a6','--error':'#ef4444','--border-color':'rgba(244,63,94,0.5)','--text-primary':'#ffe4e6','--text-secondary':'#fecdd3','--glow-color':'rgba(244,63,94,0.4)'},cyberpunk:{'--bg-main':'#0a0a1a','--primary':'#00ff88','--secondary':'#ff0080','--accent':'#00ffff','--error':'#ff0000','--border-color':'rgba(0,255,136,0.5)','--text-primary':'#00ff88','--text-secondary':'#00cc6a','--glow-color':'rgba(0,255,136,0.4)'},golden:{'--bg-main':'#1a150a','--primary':'#fbbf24','--secondary':'#f59e0b','--accent':'#ef4444','--error':'#dc2626','--border-color':'rgba(251,191,36,0.5)','--text-primary':'#fefce8','--text-secondary':'#fef08a','--glow-color':'rgba(251,191,36,0.4)'}};
document.querySelectorAll('.theme-btn').forEach(btn=>{btn.addEventListener('click',()=>{document.querySelectorAll('.theme-btn').forEach(b=>b.classList.remove('active'));btn.classList.add('active');const t=themes[btn.dataset.theme];if(t){Object.entries(t).forEach(([k,v])=>{document.documentElement.style.setProperty(k,v);});document.querySelector('.galaxy-bg').style.background=`linear-gradient(135deg,${t['--bg-main']} 0%,${t['--bg-main']}dd 50%,${t['--bg-main']} 100%)`;document.body.style.background=t['--bg-main'];document.querySelectorAll('.color-target-item').forEach(item=>{const v=item.dataset.var;if(t[v])item.querySelector('.color-target-dot').style.background=t[v];});}saveSettings();});});

document.getElementById('bgEffect').addEventListener('change',e=>{currentBgEffect=e.target.value;if(['particles','stars','snow','bubbles','firefly','confetti','matrix'].includes(currentBgEffect))initParticles();saveSettings();});
document.getElementById('cursorEffect').addEventListener('change',e=>{currentCursorEffect=e.target.value;cursorTrail=[];window.ripples=[];saveSettings();});
document.getElementById('effectDensity').addEventListener('input',e=>{effectDensity=parseInt(e.target.value);document.getElementById('densityValue').textContent=effectDensity;if(['particles','stars','snow','bubbles','firefly','confetti','matrix'].includes(currentBgEffect))initParticles();saveSettings();});
document.getElementById('effectSpeed').addEventListener('input',e=>{effectSpeed=parseInt(e.target.value);document.getElementById('speedValue').textContent=effectSpeed;saveSettings();});
document.getElementById('cursorSize').addEventListener('input',e=>{cursorSize=parseInt(e.target.value);document.getElementById('cursorSizeValue').textContent=cursorSize;saveSettings();});

function applyCardStyle(){const root=document.documentElement,op=cardOpacity/100;root.style.setProperty('--card-radius',borderRadius+'px');root.style.setProperty('--card-opacity',op);root.style.setProperty('--glass-blur',glassBlur+'px');const cards=document.querySelectorAll('.glass-card,.stat-card,.timeline-item');switch(currentCardStyle){case 'glass':cards.forEach(c=>{c.style.borderStyle='solid';c.style.borderWidth='1.5px';c.style.borderColor='';c.style.boxShadow='';c.style.borderImage='';c.style.background='';c.style.backdropFilter='';c.style.webkitBackdropFilter='';});break;case 'neon':cards.forEach(c=>{c.style.borderStyle='solid';c.style.borderWidth='1.5px';c.style.borderColor='var(--primary)';c.style.boxShadow=`0 0 ${glassBlur}px var(--glow-color),inset 0 0 ${glassBlur*.5}px rgba(100,140,255,0.1)`;c.style.background=`rgba(0,0,0,${op*0.5})`;c.style.backdropFilter=`blur(${glassBlur*.5}px)`;c.style.webkitBackdropFilter=`blur(${glassBlur*.5}px)`;c.style.borderImage='';});break;case 'gradient':cards.forEach(c=>{c.style.borderStyle='solid';c.style.borderWidth='2px';c.style.borderImage='linear-gradient(135deg,var(--primary),var(--secondary)) 1';c.style.borderColor='';c.style.boxShadow='';c.style.background='';c.style.backdropFilter='';c.style.webkitBackdropFilter='';});break;case 'solid':cards.forEach(c=>{c.style.borderStyle='solid';c.style.borderWidth='1.5px';c.style.borderColor='';c.style.boxShadow='';c.style.borderImage='';c.style.background='';c.style.backdropFilter='';c.style.webkitBackdropFilter='';});break;case 'dashed':cards.forEach(c=>{c.style.borderStyle='dashed';c.style.borderWidth='1.5px';c.style.borderColor='';c.style.boxShadow='';c.style.borderImage='';c.style.background='';c.style.backdropFilter='';c.style.webkitBackdropFilter='';});break;}}

document.getElementById('cardStyle').addEventListener('change',e=>{currentCardStyle=e.target.value;applyCardStyle();saveSettings();});
document.getElementById('glassBlur').addEventListener('input',e=>{glassBlur=parseInt(e.target.value);document.getElementById('blurValue').textContent=glassBlur;applyCardStyle();saveSettings();});
document.getElementById('borderRadius').addEventListener('input',e=>{borderRadius=parseInt(e.target.value);document.getElementById('radiusValue').textContent=borderRadius;applyCardStyle();saveSettings();});
document.getElementById('cardOpacity').addEventListener('input',e=>{cardOpacity=parseInt(e.target.value);document.getElementById('cardOpacityValue').textContent=cardOpacity;applyCardStyle();saveSettings();});
document.getElementById('fontFamily').addEventListener('change',e=>{document.body.style.fontFamily=e.target.value;saveSettings();});
document.getElementById('fontSize').addEventListener('input',e=>{document.getElementById('fontSizeValue').textContent=e.target.value+'px';document.body.style.fontSize=e.target.value+'px';saveSettings();});
document.getElementById('lineHeight').addEventListener('input',e=>{document.getElementById('lineHeightValue').textContent=e.target.value;document.body.style.lineHeight=e.target.value;saveSettings();});
document.getElementById('headingSize').addEventListener('input',e=>{document.getElementById('headingSizeValue').textContent=e.target.value+'px';document.querySelectorAll('.section h2').forEach(h=>h.style.fontSize=e.target.value+'px');document.querySelectorAll('.section h3,.glass-card h3').forEach(h=>h.style.fontSize=(parseInt(e.target.value)*0.75)+'px');saveSettings();});

let currentParagraphType='section';
document.getElementById('addParagraphBtn').addEventListener('click',()=>{updateInsertPositions();document.getElementById('addParagraphModal').style.display='block';document.getElementById('addParagraphOverlay').style.display='block';});
function updateInsertPositions(){const s=document.getElementById('insertPosition');s.innerHTML='<option value="end" style="background:#1a1e2e;color:#e0e6ed;">末尾</option>';document.querySelectorAll('.section').forEach((sec,i)=>{const h=sec.querySelector('h2');if(h){const o=document.createElement('option');o.value=i;o.textContent=`在"${h.textContent.substring(0,15)}..."之后`;o.style.background='#1a1e2e';o.style.color='#e0e6ed';s.appendChild(o);}});}
document.getElementById('typeSection').addEventListener('click',()=>{currentParagraphType='section';document.getElementById('typeSection').style.background='rgba(100,140,255,0.2)';document.getElementById('typeSection').style.borderColor='var(--primary)';document.getElementById('typeSection').style.color='var(--text-primary)';document.getElementById('typeCard').style.background='rgba(255,255,255,0.05)';document.getElementById('typeCard').style.borderColor='rgba(255,255,255,0.2)';document.getElementById('typeCard').style.color='var(--text-muted)';});
document.getElementById('typeCard').addEventListener('click',()=>{currentParagraphType='card';document.getElementById('typeCard').style.background='rgba(100,140,255,0.2)';document.getElementById('typeCard').style.borderColor='var(--primary)';document.getElementById('typeCard').style.color='var(--text-primary)';document.getElementById('typeSection').style.background='rgba(255,255,255,0.05)';document.getElementById('typeSection').style.borderColor='rgba(255,255,255,0.2)';document.getElementById('typeSection').style.color='var(--text-muted)';});
document.getElementById('cancelAddParagraph').addEventListener('click',()=>{document.getElementById('addParagraphModal').style.display='none';document.getElementById('addParagraphOverlay').style.display='none';});
document.getElementById('addParagraphOverlay').addEventListener('click',()=>{document.getElementById('addParagraphModal').style.display='none';document.getElementById('addParagraphOverlay').style.display='none';});
document.getElementById('confirmAddParagraph').addEventListener('click',()=>{const title=document.getElementById('newParagraphTitle').value.trim(),content=document.getElementById('newParagraphContent').value.trim(),pos=document.getElementById('insertPosition').value;if(!title||!content){alert('请填写标题和内容');return;}let el;if(currentParagraphType==='section'){const secs=document.querySelectorAll('.section'),n=['一','二','三','四','五','六','七','八','九','十'][secs.length]||(secs.length+1);el=document.createElement('div');el.className='section animate-on-scroll visible';el.innerHTML=`<h2>${n}、${title}</h2><div class="glass-card"><p>${content.replace(/\n/g,'</p><p>')}</p></div>`;}else{el=document.createElement('div');el.className='glass-card animate-on-scroll visible';el.innerHTML=`<h3>${title}</h3><p>${content.replace(/\n/g,'</p><p>')}</p>`;}if(pos==='end'){const c=document.querySelector('.container'),b=document.querySelector('.add-paragraph-btn').parentElement;c.insertBefore(el,b);}else{const t=document.querySelectorAll('.section')[parseInt(pos)];if(t){if(currentParagraphType==='card')t.appendChild(el);else t.parentNode.insertBefore(el,t.nextSibling);}}if(currentParagraphType==='section'){document.querySelectorAll('.section').forEach((s,i)=>{const h=s.querySelector('h2');if(h){const n=['一','二','三','四','五','六','七','八','九','十'][i]||(i+1);h.textContent=`${n}、${h.textContent.replace(/^[一二三四五六七八九十]+、/,'').replace(/^\d+、/,'')}`;}});}applyCardStyle();document.getElementById('addParagraphModal').style.display='none';document.getElementById('addParagraphOverlay').style.display='none';document.getElementById('newParagraphTitle').value='';document.getElementById('newParagraphContent').value='';const obs2=new IntersectionObserver(e=>{e.forEach(en=>{if(en.isIntersecting)en.target.classList.add('visible');});},{threshold:0.1});document.querySelectorAll('.animate-on-scroll:not(.visible)').forEach(el=>obs2.observe(el));});
document.getElementById('exportPdfBtn').addEventListener('click',()=>{window.print();});
const observer=new IntersectionObserver(entries=>{entries.forEach(e=>{if(e.isIntersecting)e.target.classList.add('visible');});},{threshold:0.1});
document.querySelectorAll('.animate-on-scroll').forEach(el=>observer.observe(el));

function applySavedSettings(){const s=loadSettings();if(!s)return;if(s.theme){const b=document.querySelector(`.theme-btn[data-theme="${s.theme}"]`);if(b)b.click();}if(s.bgEffect){document.getElementById('bgEffect').value=s.bgEffect;currentBgEffect=s.bgEffect;}if(s.cursorEffect){document.getElementById('cursorEffect').value=s.cursorEffect;currentCursorEffect=s.cursorEffect;}if(s.effectDensity){document.getElementById('effectDensity').value=s.effectDensity;document.getElementById('densityValue').textContent=s.effectDensity;effectDensity=parseInt(s.effectDensity);}if(s.effectSpeed){document.getElementById('effectSpeed').value=s.effectSpeed;document.getElementById('speedValue').textContent=s.effectSpeed;effectSpeed=parseInt(s.effectSpeed);}if(s.cursorSize){document.getElementById('cursorSize').value=s.cursorSize;document.getElementById('cursorSizeValue').textContent=s.cursorSize;cursorSize=parseInt(s.cursorSize);}if(s.cardStyle){document.getElementById('cardStyle').value=s.cardStyle;currentCardStyle=s.cardStyle;}if(s.glassBlur){document.getElementById('glassBlur').value=s.glassBlur;document.getElementById('blurValue').textContent=s.glassBlur;glassBlur=parseInt(s.glassBlur);}if(s.borderRadius){document.getElementById('borderRadius').value=s.borderRadius;document.getElementById('radiusValue').textContent=s.borderRadius;borderRadius=parseInt(s.borderRadius);}if(s.cardOpacity){document.getElementById('cardOpacity').value=s.cardOpacity;document.getElementById('cardOpacityValue').textContent=s.cardOpacity;cardOpacity=parseInt(s.cardOpacity);}if(s.fontFamily){document.getElementById('fontFamily').value=s.fontFamily;document.body.style.fontFamily=s.fontFamily;}if(s.fontSize){document.getElementById('fontSize').value=s.fontSize;document.getElementById('fontSizeValue').textContent=s.fontSize+'px';document.body.style.fontSize=s.fontSize+'px';}if(s.lineHeight){document.getElementById('lineHeight').value=s.lineHeight;document.getElementById('lineHeightValue').textContent=s.lineHeight;document.body.style.lineHeight=s.lineHeight;}if(s.headingSize){document.getElementById('headingSize').value=s.headingSize;document.getElementById('headingSizeValue').textContent=s.headingSize+'px';document.querySelectorAll('.section h2').forEach(h=>h.style.fontSize=s.headingSize+'px');}if(s.colors){Object.entries(s.colors).forEach(([k,v])=>{document.documentElement.style.setProperty(k,v);});if(s.colors['--bg-main']){document.querySelector('.galaxy-bg').style.background=`linear-gradient(135deg,${s.colors['--bg-main']} 0%,${s.colors['--bg-main']}dd 50%,${s.colors['--bg-main']} 100%)`;document.body.style.background=s.colors['--bg-main'];}}if(['particles','stars','snow','bubbles','firefly','confetti','matrix'].includes(currentBgEffect))initParticles();setTimeout(applyCardStyle,100);}
applySavedSettings();
</script>

</body>
</html>

【模板B】精简版 HTML 模板

> ⚠️ AI 生成精简版文档时,必须先根据用户选择的主题,查阅本文件的「预设主题颜色表」,将对应颜色值替换掉下列占位符,然后输出完整 HTML。

>

> 精简版占位符说明:

> - {{PRIMARY_COLOR}} → 主色(如 #2563eb)

> - {{PRIMARY_LIGHT}} → 主色亮版(可设为主色+透明度,如 rgba(37,99,235,0.7))

> - {{PRIMARY_DARK}} → 主色暗版(可设为主色加深,如 #1d4ed8)

> - {{SECONDARY_COLOR}} → 辅助色

> - {{ACCENT_COLOR}} → 强调色

> - {{BG_COLOR}} → 背景色

> - {{CARD_BG_R}} {{CARD_BG_G}} {{CARD_BG_B}} → 卡片背景色的 RGB 分量(从颜色表的 CARD_BG_COLOR 中提取)

> - {{TEXT_PRIMARY}} → 标题文字颜色

> - {{TEXT_SECONDARY}} → 正文文字颜色

> - {{TEXT_MUTED}} → 淡化文字颜色(可设为 TEXT_SECONDARY + 透明度)

> - {{BORDER_COLOR}} → 边框颜色

> - {{BORDER_HOVER}} → 鼠标悬停边框颜色(可设为 BORDER_COLOR 更高不透明度)

> - {{GLOW_COLOR}} → 发光效果颜色(可设为主色 rgba 版本)

> - {{GLASS_BLUR}} → 毛玻璃模糊度(推荐值:20)

> - {{CARD_RADIUS}} → 卡片圆角(推荐值:20)

> - {{CARD_OPACITY}} → 卡片透明度(推荐值:0.85~0.95)

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{TITLE}}</title>
<style>
:root {
  --primary: {{PRIMARY_COLOR}};
  --primary-light: {{PRIMARY_LIGHT}};
  --primary-dark: {{PRIMARY_DARK}};
  --secondary: {{SECONDARY_COLOR}};
  --accent: {{ACCENT_COLOR}};
  --error: #dc2626;
  --bg-main: {{BG_COLOR}};
  --card-bg-r: {{CARD_BG_R}};
  --card-bg-g: {{CARD_BG_G}};
  --card-bg-b: {{CARD_BG_B}};
  --text-primary: {{TEXT_PRIMARY}};
  --text-secondary: {{TEXT_SECONDARY}};
  --text-muted: {{TEXT_MUTED}};
  --border-color: {{BORDER_COLOR}};
  --border-hover: {{BORDER_HOVER}};
  --glow-color: {{GLOW_COLOR}};
  --glass-blur: {{GLASS_BLUR}}px;
  --card-radius: {{CARD_RADIUS}}px;
  --card-opacity: {{CARD_OPACITY}};
}

* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, "Microsoft YaHei", sans-serif; color: var(--text-secondary); background: var(--bg-main); line-height: 1.8; overflow-x: hidden; min-height: 100vh; }
p, li, td { color: var(--text-secondary); }
h1, h2, h3, h4 { color: var(--text-primary); }
a { color: var(--primary); text-decoration: none; }

.container { max-width: 1000px; margin: 0 auto; padding: 40px 20px; }

.glass-card { 
  background: rgba(var(--card-bg-r), var(--card-bg-g), var(--card-bg-b), var(--card-opacity)); 
  backdrop-filter: blur(var(--glass-blur)); 
  -webkit-backdrop-filter: blur(var(--glass-blur));
  border-radius: var(--card-radius); 
  padding: 32px; 
  margin: 24px 0; 
  border: 1.5px solid var(--border-color); 
  transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1); 
  position: relative; 
  overflow: hidden; 
  page-break-inside: avoid; 
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
}
.glass-card:hover { 
  border-color: var(--border-hover); 
  box-shadow: 0 0 30px var(--glow-color), 0 15px 40px rgba(0,0,0,0.1); 
  transform: translateY(-5px); 
}
.card-success { border-left: 4px solid #059669; }
.card-info { border-left: 4px solid var(--primary); }
.card-purple { border-left: 4px solid var(--secondary); }
.glass-card p { color: var(--text-secondary); line-height: 1.9; margin-bottom: 12px; }
.glass-card li { color: var(--text-secondary); margin-bottom: 6px; }
.glass-card strong { color: var(--text-primary); }
.glass-card h3 { color: var(--text-primary); font-size: 20px; margin-bottom: 16px; }

.hero { 
  text-align: center; 
  padding: 80px 50px; 
  background: rgba(var(--card-bg-r), var(--card-bg-g), var(--card-bg-b), 0.95); 
  border-radius: 28px; 
  margin-bottom: 50px; 
  border: 2px solid var(--border-color); 
  backdrop-filter: blur(25px); 
  -webkit-backdrop-filter: blur(25px);
  box-shadow: 0 8px 30px rgba(0,0,0,0.08); 
  animation: heroAppear 1s ease-out; 
}
@keyframes heroAppear { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } }
.hero h1 { font-size: 48px; font-weight: 700; color: var(--text-primary); margin-bottom: 16px; }
.hero .subtitle { font-size: 22px; color: var(--text-muted); margin-bottom: 24px; }
.hero .meta { font-size: 14px; color: var(--text-muted); }

.stats-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 20px; margin: 50px 0; }
.stat-card { 
  background: rgba(var(--card-bg-r), var(--card-bg-g), var(--card-bg-b), var(--card-opacity)); 
  backdrop-filter: blur(var(--glass-blur)); 
  border-radius: var(--card-radius); 
  padding: 30px; 
  text-align: center; 
  border: 1.5px solid var(--border-color); 
  transition: all 0.4s cubic-bezier(0.175,0.885,0.32,1.275); 
  box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.stat-card:hover { transform: translateY(-8px) scale(1.03); box-shadow: 0 0 30px var(--glow-color), 0 20px 30px rgba(0,0,0,0.1); }
.stat-card .number { font-size: 48px; font-weight: 700; color: var(--primary); }
.stat-card .label { font-size: 14px; color: var(--text-muted); margin-top: 12px; }

.section { margin: 60px 0; }
.section h2 { font-size: 30px; font-weight: 700; color: var(--text-primary); margin-bottom: 28px; padding-bottom: 14px; border-bottom: 2px solid var(--border-color); display: inline-block; }
.section h3 { font-size: 22px; font-weight: 600; color: var(--text-primary); margin: 28px 0 14px; }

table { width: 100%; border-collapse: collapse; background: rgba(var(--card-bg-r), var(--card-bg-g), var(--card-bg-b), var(--card-opacity)); backdrop-filter: blur(10px); border-radius: var(--card-radius); overflow: hidden; margin: 20px 0; border: 1.5px solid var(--border-color); }
th { background: rgba(37,99,235,0.08); color: var(--text-primary); padding: 16px 18px; text-align: left; font-weight: 600; border-bottom: 2px solid var(--border-color); }
td { padding: 14px 18px; border-bottom: 1px solid rgba(37,99,235,0.1); color: var(--text-secondary); }
tr:hover td { background: rgba(37,99,235,0.03); }

.animate-on-scroll { opacity: 0; transform: translateY(30px); transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1); }
.animate-on-scroll.visible { opacity: 1; transform: translateY(0); }

.theme-toggle { 
  position: fixed; 
  bottom: 30px; 
  right: 30px; 
  display: flex; 
  flex-direction: column; 
  gap: 8px; 
  z-index: 100; 
}
.theme-btn { 
  width: 40px; 
  height: 40px; 
  border-radius: 50%; 
  border: 2px solid rgba(255,255,255,0.3); 
  cursor: pointer; 
  transition: all 0.3s ease; 
  box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
.theme-btn:hover { transform: scale(1.2); border-color: white; }
.theme-btn.active { border-color: white; box-shadow: 0 0 15px rgba(255,255,255,0.5); }

.export-btn { 
  display: inline-flex; 
  align-items: center; 
  gap: 10px; 
  padding: 14px 28px; 
  background: linear-gradient(135deg, var(--primary), var(--secondary)); 
  border: none; 
  border-radius: 12px; 
  color: white; 
  cursor: pointer; 
  font-size: 16px; 
  font-weight: 500; 
  transition: all 0.3s; 
  box-shadow: 0 4px 15px rgba(37,99,235,0.3);
}
.export-btn:hover { transform: translateY(-2px); box-shadow: 0 6px 25px rgba(37,99,235,0.4); }

.footer { text-align: center; padding: 40px 0; color: var(--text-muted); font-size: 14px; border-top: 1px solid var(--border-color); margin-top: 60px; }

@media (max-width: 768px) {
  .container { padding: 20px 15px; }
  .hero { padding: 50px 20px; }
  .hero h1 { font-size: 32px; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
}

@media print {
  .theme-toggle { display: none !important; }
  .glass-card { backdrop-filter: none; background: white; border: 1px solid #e5e7eb; }
  body { background: white; color: #1f2937; }
  .hero { background: #f8fafc; }
}
</style>
</head>
<body>

<div class="container">

<div class="hero animate-on-scroll">
  <h1>{{TITLE}}</h1>
  <div class="subtitle">{{SUBTITLE}}</div>
  <div class="meta">{{META}}</div>
</div>

<div class="stats-grid">
  <div class="stat-card animate-on-scroll"><div class="number">{{STAT1_NUMBER}}</div><div class="label">{{STAT1_LABEL}}</div></div>
  <div class="stat-card animate-on-scroll"><div class="number">{{STAT2_NUMBER}}</div><div class="label">{{STAT2_LABEL}}</div></div>
  <div class="stat-card animate-on-scroll"><div class="number">{{STAT3_NUMBER}}</div><div class="label">{{STAT3_LABEL}}</div></div>
  <div class="stat-card animate-on-scroll"><div class="number">{{STAT4_NUMBER}}</div><div class="label">{{STAT4_LABEL}}</div></div>
</div>

{{CONTENT}}

<div style="text-align: center; margin: 40px 0;">
  <button class="export-btn" onclick="window.print()">
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="20" height="20">
      <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
      <polyline points="14 2 14 8 20 8"></polyline>
    </svg>
    导出为 PDF
  </button>
</div>

<div class="footer">
  <p>{{FOOTER}}</p>
</div>

</div>

<div class="theme-toggle">
  <button class="theme-btn active" data-theme="snow" style="background: linear-gradient(135deg, #f0f4f8, #2563eb)" title="雪白"></button>
  <button class="theme-btn" data-theme="galaxy" style="background: linear-gradient(135deg, #0d1117, #7c3aed)" title="银河"></button>
  <button class="theme-btn" data-theme="ocean" style="background: linear-gradient(135deg, #0a1929, #00e5ff)" title="深海"></button>
  <button class="theme-btn" data-theme="morandi" style="background: linear-gradient(135deg, #e8e0d8, #8b6f5e)" title="莫兰迪"></button>
  <button class="theme-btn" data-theme="cream" style="background: linear-gradient(135deg, #fef7e7, #b45309)" title="奶油"></button>
</div>

<script>
const themes = {
  snow: { '--bg-main': '#f0f4f8', '--primary': '#2563eb', '--secondary': '#7c3aed', '--text-primary': '#0f172a', '--text-secondary': '#334155', '--border-color': 'rgba(37,99,235,0.3)', cardBg: [255,255,255] },
  galaxy: { '--bg-main': '#0d1117', '--primary': '#7c3aed', '--secondary': '#06b6d4', '--text-primary': '#e0e7ff', '--text-secondary': '#c7d2fe', '--border-color': 'rgba(124,58,237,0.5)', cardBg: [13,17,23] },
  ocean: { '--bg-main': '#0a1929', '--primary': '#00e5ff', '--secondary': '#00bfa5', '--text-primary': '#e0f7fa', '--text-secondary': '#b2ebf2', '--border-color': 'rgba(0,229,255,0.5)', cardBg: [10,25,41] },
  morandi: { '--bg-main': '#e8e0d8', '--primary': '#8b6f5e', '--secondary': '#a0937d', '--text-primary': '#3d2e24', '--text-secondary': '#5a4a3e', '--border-color': 'rgba(139,111,94,0.4)', cardBg: [248,244,240] },
  cream: { '--bg-main': '#fef7e7', '--primary': '#b45309', '--secondary': '#92400e', '--text-primary': '#451a03', '--text-secondary': '#78350f', '--border-color': 'rgba(180,83,9,0.3)', cardBg: [255,251,235] }
};

document.querySelectorAll('.theme-btn').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('.theme-btn').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    const theme = themes[btn.dataset.theme];
    if (theme) {
      Object.entries(theme).forEach(([key, value]) => { if (key !== 'cardBg') document.documentElement.style.setProperty(key, value); });
      if (theme.cardBg) {
        document.documentElement.style.setProperty('--card-bg-r', theme.cardBg[0]);
        document.documentElement.style.setProperty('--card-bg-g', theme.cardBg[1]);
        document.documentElement.style.setProperty('--card-bg-b', theme.cardBg[2]);
      }
      document.body.style.background = theme['--bg-main'];
    }
  });
});

const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => { if (entry.isIntersecting) entry.target.classList.add('visible'); });
}, { threshold: 0.1 });
document.querySelectorAll('.animate-on-scroll').forEach(el => observer.observe(el));
</script>

</body>
</html>

【模板C】纯静态 HTML 模板

> ⚠️ AI 生成纯静态版文档时,根据用户选择的主题查阅「预设主题颜色表」,替换以下占位符后输出完整 HTML:

> - {{PRIMARY_COLOR}} → 主色

> - {{SECONDARY_COLOR}} → 辅助色

> - {{BG_COLOR}} → 背景色

> - {{CARD_BG_COLOR}} → 卡片背景色(直接使用颜色表中的 CARD_BG_COLOR 值)

> - {{TEXT_PRIMARY}} → 标题颜色

> - {{TEXT_SECONDARY}} → 正文颜色

> - {{BORDER_COLOR}} → 边框颜色

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{TITLE}}</title>
<style>
:root {
  --primary: {{PRIMARY_COLOR}};
  --secondary: {{SECONDARY_COLOR}};
  --bg-main: {{BG_COLOR}};
  --card-bg: {{CARD_BG_COLOR}};
  --text-primary: {{TEXT_PRIMARY}};
  --text-secondary: {{TEXT_SECONDARY}};
  --border-color: {{BORDER_COLOR}};
}

* { margin: 0; padding: 0; box-sizing: border-box; }
body { font-family: -apple-system, "Microsoft YaHei", sans-serif; color: var(--text-secondary); background: var(--bg-main); line-height: 1.8; overflow-x: hidden; }
p, li, td { color: var(--text-secondary); }
h1, h2, h3, h4 { color: var(--text-primary); }

.container { max-width: 1000px; margin: 0 auto; padding: 40px 20px; }

.card { 
  background: var(--card-bg); 
  border-radius: 20px; 
  padding: 32px; 
  margin: 24px 0; 
  border: 1.5px solid var(--border-color); 
  box-shadow: 0 4px 20px rgba(0,0,0,0.06);
}
.card-success { border-left: 4px solid #059669; }
.card-info { border-left: 4px solid var(--primary); }
.card-purple { border-left: 4px solid var(--secondary); }
.card p { line-height: 1.9; margin-bottom: 12px; }
.card li { margin-bottom: 6px; }
.card strong { color: var(--text-primary); }
.card h3 { color: var(--text-primary); font-size: 20px; margin-bottom: 16px; }

.hero { 
  text-align: center; 
  padding: 80px 50px; 
  background: var(--card-bg); 
  border-radius: 28px; 
  margin-bottom: 50px; 
  border: 2px solid var(--border-color); 
  box-shadow: 0 8px 30px rgba(0,0,0,0.08); 
}
.hero h1 { font-size: 48px; font-weight: 700; color: var(--text-primary); margin-bottom: 16px; }
.hero .subtitle { font-size: 22px; color: var(--text-secondary); margin-bottom: 24px; opacity: 0.8; }
.hero .meta { font-size: 14px; color: var(--text-secondary); opacity: 0.6; }

.stats-grid { display: grid; grid-template-columns: repeat(4,1fr); gap: 20px; margin: 50px 0; }
.stat-card { 
  background: var(--card-bg); 
  border-radius: 20px; 
  padding: 30px; 
  text-align: center; 
  border: 1.5px solid var(--border-color); 
  box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.stat-card .number { font-size: 48px; font-weight: 700; color: var(--primary); }
.stat-card .label { font-size: 14px; color: var(--text-secondary); margin-top: 12px; opacity: 0.8; }

.section { margin: 60px 0; }
.section h2 { font-size: 30px; font-weight: 700; color: var(--text-primary); margin-bottom: 28px; padding-bottom: 14px; border-bottom: 2px solid var(--border-color); display: inline-block; }
.section h3 { font-size: 22px; font-weight: 600; color: var(--text-primary); margin: 28px 0 14px; }

table { width: 100%; border-collapse: collapse; background: var(--card-bg); border-radius: 20px; overflow: hidden; margin: 20px 0; border: 1.5px solid var(--border-color); }
th { background: var(--card-bg); color: var(--text-primary); padding: 16px 18px; text-align: left; font-weight: 600; border-bottom: 2px solid var(--border-color); }
td { padding: 14px 18px; border-bottom: 1px solid var(--border-color); }

.footer { text-align: center; padding: 40px 0; color: var(--text-secondary); font-size: 14px; border-top: 1px solid var(--border-color); margin-top: 60px; opacity: 0.6; }

@media (max-width: 768px) {
  .container { padding: 20px 15px; }
  .hero { padding: 50px 20px; }
  .hero h1 { font-size: 32px; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
}
</style>
</head>
<body>

<div class="container">

<div class="hero">
  <h1>{{TITLE}}</h1>
  <div class="subtitle">{{SUBTITLE}}</div>
  <div class="meta">{{META}}</div>
</div>

<div class="stats-grid">
  <div class="stat-card"><div class="number">{{STAT1_NUMBER}}</div><div class="label">{{STAT1_LABEL}}</div></div>
  <div class="stat-card"><div class="number">{{STAT2_NUMBER}}</div><div class="label">{{STAT2_LABEL}}</div></div>
  <div class="stat-card"><div class="number">{{STAT3_NUMBER}}</div><div class="label">{{STAT3_LABEL}}</div></div>
  <div class="stat-card"><div class="number">{{STAT4_NUMBER}}</div><div class="label">{{STAT4_LABEL}}</div></div>
</div>

{{CONTENT}}

<div class="footer">
  <p>{{FOOTER}}</p>
</div>

</div>

</body>
</html>

版本历史

共 3 个版本

  • v1.0.2 SKILL.md(完全重写) 去掉所有绝对路径引用,改为搜索查找 内嵌 12 个主题的完整色值表(AI 直接查表,无需人工配置) 增加背景动效名称和效果对照表 增加"最佳使用场景"和"不适合的场景"说明 增加错误提示规范(输入不清时如何引导用户) assets/html-template-lite.html(重写) 从空壳模板 → 15KB 完整可运行模板 嵌入 5 种背景动效 JS(粒子/星空/雪花/泡泡/萤火虫) CSS 注释内嵌主题色值速查表(模板自文档化) 增加滚动进场动画 assets/html-template-static.html(重写) 从占位符模板 → 10KB 自包含模板 嵌入主题色值速查表注释 支持时间线、对比卡片、SVG 流程图等组件 assets/html-template.html(未改动) 原版 75KB 完整版自带调色器面板,无需修改 当前
    2026-06-06 18:47 安全 安全
  • v1.0.1 📦 三种生成模式 模式 功能 文件大小 生成速度 适用场景 完整版 调色器+动效+字体+边框样式+自动保存 ~80KB 较慢 需要事后调整 精简版 固定动效+固定样式+PDF导出 ~30KB 快速 不需要调整 纯静态 固定样式,无交互 ~15KB 最快 邮件发送、打印
    2026-06-05 23:00 安全 安全
  • v1.0.0 Initial release
    2026-06-05 22:55 安全 安全

安全检测

腾讯云安全 (Keen)

安全,无风险
查看报告

腾讯云安全 (Sanbu)

安全,无风险
查看报告

🔗 相关推荐

developer-tools

Github

steipete
使用 `gh` CLI 与 GitHub 交互,通过 `gh issue`、`gh pr`、`gh run` 和 `gh api` 管理议题、PR、CI 运行及高级查询。
★ 668 📥 323,872
ai-intelligence

Self-Improving + Proactive Agent

ivangdavila
自我反思+自我批评+自我学习+自组织记忆。智能体评估自身工作、发现错误并持续改进。
★ 1,351 📥 317,803
security-compliance

Skill Vetter

spclaudehome
AI智能体技能安全预审工具。安装ClawdHub、GitHub等来源技能前,检查风险信号、权限范围及可疑模式。
★ 1,211 📥 266,249