{
  "site": {
    "name": "Mijiao Notes",
    "alias": "静态 Markdown 博客",
    "description": "Markdown first, theme driven, base-path agnostic static blog.",
    "author": "MijiaoGame",
    "email": "",
    "favicon": "assets/favicon.svg",
    "logo": ""
  },
  "deployment": {
    "basePath": "auto",
    "siteUrl": ""
  },
  "theme": {
    "active": "graphite",
    "available": [
      {
        "id": "aurora",
        "name": "Aurora",
        "version": "1.0.0",
        "author": "MijiaoGame",
        "description": "Brand-display theme inspired by Stripe.",
        "references": [
          "stripe"
        ],
        "source": "system",
        "path": "themes/aurora"
      },
      {
        "id": "graphite",
        "name": "Graphite",
        "version": "1.0.0",
        "author": "MijiaoGame",
        "description": "Default theme inspired by Linear and Vercel.",
        "references": [
          "linear.app",
          "vercel"
        ],
        "source": "system",
        "path": "themes/graphite"
      },
      {
        "id": "mono",
        "name": "Mono",
        "version": "1.0.0",
        "author": "MijiaoGame",
        "description": "Compact monochrome developer theme.",
        "references": [
          "vercel"
        ],
        "source": "system",
        "path": "themes/mono"
      },
      {
        "id": "paper",
        "name": "Paper",
        "version": "1.0.0",
        "author": "MijiaoGame",
        "description": "Reading-first theme inspired by Notion and Claude.",
        "references": [
          "notion",
          "claude"
        ],
        "source": "system",
        "path": "themes/paper"
      },
      {
        "id": "terminal",
        "name": "Terminal",
        "version": "1.0.0",
        "author": "MijiaoGame",
        "description": "Hacker terminal inspired by DiskScope cyber-tech and classic CRT monitors. Neon green on dark, scanline overlay, hex logo.",
        "source": "system",
        "path": "themes/terminal"
      }
    ]
  },
  "pages": [
    {
      "id": "about",
      "name": "关于",
      "icon": "i",
      "type": "markdown",
      "source": "content/pages/about.md",
      "content": "<h1>关于这个博客</h1>\n<p>这是一个以 Markdown 为唯一正文来源的静态博客平台。</p>\n<h2>设计理念</h2>\n<ul>\n<li><strong>少量配置</strong> — 一个 <code>site/config.yml</code> 管理所有设置</li>\n<li><strong>高度自定义</strong> — Token 驱动主题，45+ CSS 变量，覆盖即生效</li>\n<li><strong>可扩展</strong> — 插件架构，theme.js 生命周期，模板覆盖</li>\n<li><strong>美观</strong> — 5 个内置主题，每个风格完全不同</li>\n<li><strong>高性能</strong> — 零依赖构建，增量构建，SSG</li>\n<li><strong>Markdown 优先</strong> — 内容只写 Markdown，构建时渲染为 HTML</li>\n</ul>\n<h2>快速上手</h2>\n<ol>\n<li>编辑 <code>site/config.yml</code> 修改站点信息</li>\n<li>在 <code>site/content/posts/</code> 下写 Markdown 文章</li>\n<li>运行 <code>node build.js</code> 构建</li>\n<li>运行 <code>node serve.js</code> 预览</li>\n</ol>\n<h2>内置主题</h2>\n<table>\n<thead>\n<tr>\n<th>主题</th>\n<th>风格</th>\n<th>设计参考</th>\n</tr>\n</thead>\n<tbody><tr>\n<td>graphite</td>\n<td>工业蓝图</td>\n<td>Linear + Vercel</td>\n</tr>\n<tr>\n<td>aurora</td>\n<td>品牌展示</td>\n<td>Stripe</td>\n</tr>\n<tr>\n<td>paper</td>\n<td>阅读优先</td>\n<td>Notion + Claude</td>\n</tr>\n<tr>\n<td>mono</td>\n<td>黑白极简</td>\n<td>Vercel</td>\n</tr>\n<tr>\n<td>terminal</td>\n<td>CRT 赛博</td>\n<td>DiskScope</td>\n</tr>\n</tbody></table>\n<p>切换主题：修改 <code>site/config.yml</code> 中的 <code>theme.active</code>。</p>\n<h2>高级功能</h2>\n<ul>\n<li><strong>自定义页面</strong> — 支持 HTML/CSS/JS，可嵌入数据文件</li>\n<li><strong>独立页面</strong> — <code>standalone: true</code> 隐藏平台导航栏</li>\n<li><strong>数学公式</strong> — <code>$E=mc^2$</code> 或 <code>$$\\int_0^1$$</code></li>\n<li><strong>流程图</strong> — <code>```mermaid</code> 代码块</li>\n<li><strong>评论</strong> — Giscus 可选集成</li>\n<li><strong>备案</strong> — ICP + 公安备案支持</li>\n</ul>\n<h2>更多信息</h2>\n<ul>\n<li>主题开发：<code>docs/architecture/theme-engine-reference.md</code></li>\n<li>使用教程：首页「快速开始」分类下的文章</li>\n</ul>\n",
      "renderedToHtml": true
    },
    {
      "id": "skills",
      "name": "技能矩阵",
      "icon": "+",
      "type": "custom",
      "source": "content/pages/skills.html",
      "scripts": true,
      "content": "<style>@keyframes mesh-drift {\n  0%   { background-position: 0% 0%, 100% 0%, 50% 100%, 90% 90%; }\n  50%  { background-position: 30% 20%, 70% 50%, 20% 60%, 60% 30%; }\n  100% { background-position: 60% 40%, 40% 80%, 80% 20%, 30% 70%; }\n}\n #page-custom /* ── Mesh Gradient Background ───────────────────────── */\n.skills-section{\n  --c1: #667eea; --c2: #764ba2; --c3: #f093fb; --c4: #4facfe;\n  background:\n    radial-gradient(ellipse at 20% 50%, var(--c1) 0%, transparent 50%),\n    radial-gradient(ellipse at 80% 20%, var(--c2) 0%, transparent 50%),\n    radial-gradient(ellipse at 40% 80%, var(--c3) 0%, transparent 50%),\n    radial-gradient(ellipse at 90% 90%, var(--c4) 0%, transparent 50%),\n    #0a0a1a;\n  animation: mesh-drift 20s ease-in-out infinite alternate;\n  padding: 80px 20px;\n  min-height: 100%;\n} #page-custom /* ── Noise Overlay ──────────────────────────────────── */\n.skills-section::after{\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  opacity: 0.03;\n  pointer-events: none;\n  background-image: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E\");\n  background-repeat: repeat;\n  background-size: 256px;\n} #page-custom /* ── Glass Cards ────────────────────────────────────── */\n.skills-container{ max-width: 900px; margin: 0 auto; position: relative; z-index: 1; } #page-custom .skills-hero{ text-align: center; margin-bottom: 48px; } #page-custom .skills-hero h2{ font-size: 36px; font-weight: 700; color: #fff; margin-bottom: 8px; } #page-custom .skills-hero p{ color: rgba(255,255,255,0.6); font-size: 15px; } #page-custom .stats-row{\n  display: flex;\n  justify-content: center;\n  gap: 32px;\n  margin-bottom: 48px;\n} #page-custom .stat-item{ text-align: center; } #page-custom .stat-number{\n  font-size: 42px;\n  font-weight: 700;\n  color: #fff;\n  font-variant-numeric: tabular-nums;\n} #page-custom .stat-label{ font-size: 12px; color: rgba(255,255,255,0.5); text-transform: uppercase; letter-spacing: 0.1em; margin-top: 4px; } #page-custom .glass-card{\n  background: rgba(255, 255, 255, 0.08);\n  backdrop-filter: blur(16px) saturate(180%);\n  -webkit-backdrop-filter: blur(16px) saturate(180%);\n  border: 1px solid rgba(255, 255, 255, 0.12);\n  border-radius: 16px;\n  padding: 28px;\n  margin-bottom: 20px;\n} #page-custom .glass-card-title{\n  font-size: 12px;\n  text-transform: uppercase;\n  letter-spacing: 0.12em;\n  color: rgba(255,255,255,0.4);\n  margin-bottom: 20px;\n} #page-custom /* ── Skill Bars ─────────────────────────────────────── */\n.skill-row{ display: flex; align-items: center; gap: 16px; margin-bottom: 14px; } #page-custom .skill-name{ width: 120px; font-size: 14px; color: rgba(255,255,255,0.7); flex-shrink: 0; } #page-custom .skill-track{ flex: 1; height: 8px; background: rgba(255,255,255,0.08); border-radius: 4px; overflow: hidden; } #page-custom .skill-fill{\n  height: 100%;\n  border-radius: 4px;\n  width: 0;\n  transition: width 1.2s cubic-bezier(0.16, 1, 0.3, 1);\n} #page-custom .skill-fill.animated{ /* set via JS */ } #page-custom .skill-val{ width: 36px; font-size: 14px; color: rgba(255,255,255,0.9); text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; } #page-custom .fill-1{ background: linear-gradient(90deg, #667eea, #8b9cf7); } #page-custom .fill-2{ background: linear-gradient(90deg, #f093fb, #f5a8e8); } #page-custom .fill-3{ background: linear-gradient(90deg, #4facfe, #7ec8fe); } #page-custom .fill-4{ background: linear-gradient(90deg, #43e97b, #72f0a0); } #page-custom /* ── Scroll Reveal ──────────────────────────────────── */\n.reveal{\n  opacity: 0;\n  transform: translateY(40px);\n  transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1), transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);\n} #page-custom .reveal.visible{ opacity: 1; transform: translateY(0); } #page-custom .reveal-delay-1{ transition-delay: 0.1s; } #page-custom .reveal-delay-2{ transition-delay: 0.2s; } #page-custom .reveal-delay-3{ transition-delay: 0.3s; }</style>\n<div class=\"custom-page\"><style>\n/* ── Mesh Gradient Background ───────────────────────── */\n.skills-section {\n  --c1: #667eea; --c2: #764ba2; --c3: #f093fb; --c4: #4facfe;\n  background:\n    radial-gradient(ellipse at 20% 50%, var(--c1) 0%, transparent 50%),\n    radial-gradient(ellipse at 80% 20%, var(--c2) 0%, transparent 50%),\n    radial-gradient(ellipse at 40% 80%, var(--c3) 0%, transparent 50%),\n    radial-gradient(ellipse at 90% 90%, var(--c4) 0%, transparent 50%),\n    #0a0a1a;\n  animation: mesh-drift 20s ease-in-out infinite alternate;\n  padding: 80px 20px;\n  min-height: 100%;\n}\n@keyframes mesh-drift {\n  0%   { background-position: 0% 0%, 100% 0%, 50% 100%, 90% 90%; }\n  50%  { background-position: 30% 20%, 70% 50%, 20% 60%, 60% 30%; }\n  100% { background-position: 60% 40%, 40% 80%, 80% 20%, 30% 70%; }\n}\n\n/* ── Noise Overlay ──────────────────────────────────── */\n.skills-section::after {\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  opacity: 0.03;\n  pointer-events: none;\n  background-image: url(\"data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E\");\n  background-repeat: repeat;\n  background-size: 256px;\n}\n\n/* ── Glass Cards ────────────────────────────────────── */\n.skills-container { max-width: 900px; margin: 0 auto; position: relative; z-index: 1; }\n.skills-hero { text-align: center; margin-bottom: 48px; }\n.skills-hero h2 { font-size: 36px; font-weight: 700; color: #fff; margin-bottom: 8px; }\n.skills-hero p { color: rgba(255,255,255,0.6); font-size: 15px; }\n\n.stats-row {\n  display: flex;\n  justify-content: center;\n  gap: 32px;\n  margin-bottom: 48px;\n}\n.stat-item { text-align: center; }\n.stat-number {\n  font-size: 42px;\n  font-weight: 700;\n  color: #fff;\n  font-variant-numeric: tabular-nums;\n}\n.stat-label { font-size: 12px; color: rgba(255,255,255,0.5); text-transform: uppercase; letter-spacing: 0.1em; margin-top: 4px; }\n\n.glass-card {\n  background: rgba(255, 255, 255, 0.08);\n  backdrop-filter: blur(16px) saturate(180%);\n  -webkit-backdrop-filter: blur(16px) saturate(180%);\n  border: 1px solid rgba(255, 255, 255, 0.12);\n  border-radius: 16px;\n  padding: 28px;\n  margin-bottom: 20px;\n}\n.glass-card-title {\n  font-size: 12px;\n  text-transform: uppercase;\n  letter-spacing: 0.12em;\n  color: rgba(255,255,255,0.4);\n  margin-bottom: 20px;\n}\n\n/* ── Skill Bars ─────────────────────────────────────── */\n.skill-row { display: flex; align-items: center; gap: 16px; margin-bottom: 14px; }\n.skill-name { width: 120px; font-size: 14px; color: rgba(255,255,255,0.7); flex-shrink: 0; }\n.skill-track { flex: 1; height: 8px; background: rgba(255,255,255,0.08); border-radius: 4px; overflow: hidden; }\n.skill-fill {\n  height: 100%;\n  border-radius: 4px;\n  width: 0;\n  transition: width 1.2s cubic-bezier(0.16, 1, 0.3, 1);\n}\n.skill-fill.animated { /* set via JS */ }\n.skill-val { width: 36px; font-size: 14px; color: rgba(255,255,255,0.9); text-align: right; font-weight: 600; font-variant-numeric: tabular-nums; }\n\n.fill-1 { background: linear-gradient(90deg, #667eea, #8b9cf7); }\n.fill-2 { background: linear-gradient(90deg, #f093fb, #f5a8e8); }\n.fill-3 { background: linear-gradient(90deg, #4facfe, #7ec8fe); }\n.fill-4 { background: linear-gradient(90deg, #43e97b, #72f0a0); }\n\n/* ── Scroll Reveal ──────────────────────────────────── */\n.reveal {\n  opacity: 0;\n  transform: translateY(40px);\n  transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1), transform 0.8s cubic-bezier(0.16, 1, 0.3, 1);\n}\n.reveal.visible { opacity: 1; transform: translateY(0); }\n.reveal-delay-1 { transition-delay: 0.1s; }\n.reveal-delay-2 { transition-delay: 0.2s; }\n.reveal-delay-3 { transition-delay: 0.3s; }\n</style>\n\n<div class=\"skills-section\">\n  <div class=\"skills-container\">\n    <div class=\"skills-hero reveal\">\n      <h2>技能矩阵</h2>\n      <p>Skills Matrix — 网格渐变背景 + 毛玻璃卡片 + 滚动动画 + 数字计数器</p>\n    </div>\n\n    <div class=\"stats-row\">\n      <div class=\"stat-item reveal reveal-delay-1\">\n        <div class=\"stat-number\"><span class=\"counter\" data-target=\"5\">0</span></div>\n        <div class=\"stat-label\">内置主题</div>\n      </div>\n      <div class=\"stat-item reveal reveal-delay-2\">\n        <div class=\"stat-number\"><span class=\"counter\" data-target=\"45\">0</span>+</div>\n        <div class=\"stat-label\">CSS Token</div>\n      </div>\n      <div class=\"stat-item reveal reveal-delay-3\">\n        <div class=\"stat-number\"><span class=\"counter\" data-target=\"212\">0</span></div>\n        <div class=\"stat-label\">自动化测试</div>\n      </div>\n    </div>\n\n    <div class=\"glass-card reveal\">\n      <div class=\"glass-card-title\">前端开发</div>\n      <div class=\"skill-row\"><span class=\"skill-name\">JavaScript</span><div class=\"skill-track\"><div class=\"skill-fill fill-1\" data-width=\"90%\"></div></div><span class=\"skill-val\">90</span></div>\n      <div class=\"skill-row\"><span class=\"skill-name\">CSS</span><div class=\"skill-track\"><div class=\"skill-fill fill-1\" data-width=\"95%\"></div></div><span class=\"skill-val\">95</span></div>\n      <div class=\"skill-row\"><span class=\"skill-name\">HTML</span><div class=\"skill-track\"><div class=\"skill-fill fill-1\" data-width=\"95%\"></div></div><span class=\"skill-val\">95</span></div>\n      <div class=\"skill-row\"><span class=\"skill-name\">TypeScript</span><div class=\"skill-track\"><div class=\"skill-fill fill-1\" data-width=\"70%\"></div></div><span class=\"skill-val\">70</span></div>\n    </div>\n\n    <div class=\"glass-card reveal\">\n      <div class=\"glass-card-title\">设计系统</div>\n      <div class=\"skill-row\"><span class=\"skill-name\">Token 设计</span><div class=\"skill-track\"><div class=\"skill-fill fill-2\" data-width=\"90%\"></div></div><span class=\"skill-val\">90</span></div>\n      <div class=\"skill-row\"><span class=\"skill-name\">排版</span><div class=\"skill-track\"><div class=\"skill-fill fill-2\" data-width=\"80%\"></div></div><span class=\"skill-val\">80</span></div>\n      <div class=\"skill-row\"><span class=\"skill-name\">响应式</span><div class=\"skill-track\"><div class=\"skill-fill fill-2\" data-width=\"85%\"></div></div><span class=\"skill-val\">85</span></div>\n    </div>\n\n    <div class=\"glass-card reveal\">\n      <div class=\"glass-card-title\">工程能力</div>\n      <div class=\"skill-row\"><span class=\"skill-name\">Node.js</span><div class=\"skill-track\"><div class=\"skill-fill fill-3\" data-width=\"80%\"></div></div><span class=\"skill-val\">80</span></div>\n      <div class=\"skill-row\"><span class=\"skill-name\">Docker</span><div class=\"skill-track\"><div class=\"skill-fill fill-3\" data-width=\"70%\"></div></div><span class=\"skill-val\">70</span></div>\n      <div class=\"skill-row\"><span class=\"skill-name\">CI/CD</span><div class=\"skill-track\"><div class=\"skill-fill fill-3\" data-width=\"65%\"></div></div><span class=\"skill-val\">65</span></div>\n    </div>\n  </div>\n</div>\n\n<script>\n(function() {\n  // Scroll reveal\n  var observer = new IntersectionObserver(function(entries) {\n    entries.forEach(function(entry) {\n      if (entry.isIntersecting) {\n        entry.target.classList.add('visible');\n        // Animate skill bars inside this card\n        entry.target.querySelectorAll('.skill-fill').forEach(function(bar) {\n          bar.style.width = bar.dataset.width;\n        });\n        observer.unobserve(entry.target);\n      }\n    });\n  }, { threshold: 0.15 });\n\n  document.querySelectorAll('.reveal').forEach(function(el) { observer.observe(el); });\n\n  // Number counter animation\n  function animateCounter(el) {\n    var target = parseInt(el.dataset.target);\n    var duration = 1500;\n    var start = performance.now();\n    function update(now) {\n      var progress = Math.min((now - start) / duration, 1);\n      var eased = 1 - Math.pow(1 - progress, 4);\n      el.textContent = Math.floor(target * eased);\n      if (progress < 1) requestAnimationFrame(update);\n    }\n    requestAnimationFrame(update);\n  }\n\n  var counterObserver = new IntersectionObserver(function(entries) {\n    entries.forEach(function(entry) {\n      if (entry.isIntersecting) {\n        animateCounter(entry.target);\n        counterObserver.unobserve(entry.target);\n      }\n    });\n  }, { threshold: 0.5 });\n\n  document.querySelectorAll('.counter').forEach(function(el) { counterObserver.observe(el); });\n})();\n</script></div>",
      "_isCustom": true,
      "_isStandalone": false
    },
    {
      "id": "portfolio",
      "name": "作品集",
      "icon": "*",
      "type": "custom",
      "source": "content/pages/portfolio.html",
      "data": "# 数据文件（构建时嵌入为 JSON）",
      "projects": "content/data/projects.yml",
      "scripts": true,
      "content": "<style>@keyframes border-spin { to { --border-angle: 360deg; } }\n #page-custom /* ── Dark Grid Background ───────────────────────────── */\n.portfolio-section{\n  background: #0a0a0f;\n  background-image:\n    radial-gradient(circle, rgba(100,126,234,0.12) 1px, transparent 1px);\n  background-size: 32px 32px;\n  padding: 80px 20px;\n  min-height: 100%;\n} #page-custom .portfolio-container{ max-width: 960px; margin: 0 auto; position: relative; z-index: 1; } #page-custom .portfolio-header{ text-align: center; margin-bottom: 48px; } #page-custom .portfolio-header h2{ font-size: 36px; font-weight: 700; color: #fff; margin-bottom: 8px; } #page-custom .portfolio-header p{ color: rgba(255,255,255,0.5); font-size: 15px; } #page-custom /* ── Card Grid ──────────────────────────────────────── */\n.card-grid{\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n  gap: 20px;\n} #page-custom /* ── 3D Tilt Card ───────────────────────────────────── */\n.tilt-card{\n  perspective: 1000px;\n} #page-custom .tilt-card-inner{\n  position: relative;\n  background: #14141f;\n  border: 1px solid rgba(255,255,255,0.06);\n  border-radius: 16px;\n  padding: 28px;\n  transition: transform 0.15s ease, box-shadow 0.3s ease;\n  will-change: transform;\n  overflow: hidden;\n}\n\n/* ── Gradient Border (on hover) ─────────────────────── */\n@ #page-custom property --border-angle{ syntax: \"<angle>\"; inherits: false; initial-value: 0deg; } #page-custom .tilt-card-inner::before{\n  content: \"\";\n  position: absolute;\n  inset: -2px;\n  border-radius: 18px;\n  background: conic-gradient(from var(--border-angle), #667eea, #764ba2, #f093fb, #4facfe, #667eea);\n  z-index: -1;\n  opacity: 0;\n  transition: opacity 0.4s;\n} #page-custom .tilt-card:hover .tilt-card-inner::before{\n  opacity: 1;\n  animation: border-spin 3s linear infinite;\n} #page-custom /* ── Mouse Spotlight ────────────────────────────────── */\n.tilt-card-inner::after{\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  border-radius: 16px;\n  background: radial-gradient(400px circle at var(--mx, 50%) var(--my, 50%), rgba(255,255,255,0.06), transparent 40%);\n  opacity: 0;\n  transition: opacity 0.3s;\n  pointer-events: none;\n} #page-custom .tilt-card:hover .tilt-card-inner::after{ opacity: 1; } #page-custom /* ── Card Content ───────────────────────────────────── */\n.card-icon{\n  width: 48px;\n  height: 48px;\n  border-radius: 12px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 20px;\n  font-weight: 700;\n  margin-bottom: 16px;\n  color: #fff;\n} #page-custom .card-title{ font-size: 18px; font-weight: 600; color: #fff; margin-bottom: 8px; } #page-custom .card-desc{ font-size: 13px; color: rgba(255,255,255,0.5); line-height: 1.6; margin-bottom: 16px; } #page-custom .card-tags{ display: flex; flex-wrap: wrap; gap: 6px; } #page-custom .card-tag{\n  font-size: 11px;\n  padding: 3px 10px;\n  background: rgba(102,126,234,0.12);\n  color: #8b9cf7;\n  border-radius: 999px;\n  font-family: monospace;\n} #page-custom /* ── Scroll Reveal ──────────────────────────────────── */\n.reveal{\n  opacity: 0;\n  transform: translateY(30px);\n  transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);\n} #page-custom .reveal.visible{ opacity: 1; transform: translateY(0); } #page-custom .reveal-d1{ transition-delay: 0.1s; } #page-custom .reveal-d2{ transition-delay: 0.2s; } #page-custom .reveal-d3{ transition-delay: 0.3s; }</style>\n<div class=\"custom-page\"><style>\n/* ── Dark Grid Background ───────────────────────────── */\n.portfolio-section {\n  background: #0a0a0f;\n  background-image:\n    radial-gradient(circle, rgba(100,126,234,0.12) 1px, transparent 1px);\n  background-size: 32px 32px;\n  padding: 80px 20px;\n  min-height: 100%;\n}\n.portfolio-container { max-width: 960px; margin: 0 auto; position: relative; z-index: 1; }\n.portfolio-header { text-align: center; margin-bottom: 48px; }\n.portfolio-header h2 { font-size: 36px; font-weight: 700; color: #fff; margin-bottom: 8px; }\n.portfolio-header p { color: rgba(255,255,255,0.5); font-size: 15px; }\n\n/* ── Card Grid ──────────────────────────────────────── */\n.card-grid {\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));\n  gap: 20px;\n}\n\n/* ── 3D Tilt Card ───────────────────────────────────── */\n.tilt-card {\n  perspective: 1000px;\n}\n.tilt-card-inner {\n  position: relative;\n  background: #14141f;\n  border: 1px solid rgba(255,255,255,0.06);\n  border-radius: 16px;\n  padding: 28px;\n  transition: transform 0.15s ease, box-shadow 0.3s ease;\n  will-change: transform;\n  overflow: hidden;\n}\n\n/* ── Gradient Border (on hover) ─────────────────────── */\n@property --border-angle { syntax: \"<angle>\"; inherits: false; initial-value: 0deg; }\n.tilt-card-inner::before {\n  content: \"\";\n  position: absolute;\n  inset: -2px;\n  border-radius: 18px;\n  background: conic-gradient(from var(--border-angle), #667eea, #764ba2, #f093fb, #4facfe, #667eea);\n  z-index: -1;\n  opacity: 0;\n  transition: opacity 0.4s;\n}\n.tilt-card:hover .tilt-card-inner::before {\n  opacity: 1;\n  animation: border-spin 3s linear infinite;\n}\n@keyframes border-spin { to { --border-angle: 360deg; } }\n\n/* ── Mouse Spotlight ────────────────────────────────── */\n.tilt-card-inner::after {\n  content: \"\";\n  position: absolute;\n  inset: 0;\n  border-radius: 16px;\n  background: radial-gradient(400px circle at var(--mx, 50%) var(--my, 50%), rgba(255,255,255,0.06), transparent 40%);\n  opacity: 0;\n  transition: opacity 0.3s;\n  pointer-events: none;\n}\n.tilt-card:hover .tilt-card-inner::after { opacity: 1; }\n\n/* ── Card Content ───────────────────────────────────── */\n.card-icon {\n  width: 48px;\n  height: 48px;\n  border-radius: 12px;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  font-size: 20px;\n  font-weight: 700;\n  margin-bottom: 16px;\n  color: #fff;\n}\n.card-title { font-size: 18px; font-weight: 600; color: #fff; margin-bottom: 8px; }\n.card-desc { font-size: 13px; color: rgba(255,255,255,0.5); line-height: 1.6; margin-bottom: 16px; }\n.card-tags { display: flex; flex-wrap: wrap; gap: 6px; }\n.card-tag {\n  font-size: 11px;\n  padding: 3px 10px;\n  background: rgba(102,126,234,0.12);\n  color: #8b9cf7;\n  border-radius: 999px;\n  font-family: monospace;\n}\n\n/* ── Scroll Reveal ──────────────────────────────────── */\n.reveal {\n  opacity: 0;\n  transform: translateY(30px);\n  transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1), transform 0.6s cubic-bezier(0.16, 1, 0.3, 1);\n}\n.reveal.visible { opacity: 1; transform: translateY(0); }\n.reveal-d1 { transition-delay: 0.1s; }\n.reveal-d2 { transition-delay: 0.2s; }\n.reveal-d3 { transition-delay: 0.3s; }\n</style>\n\n<div class=\"portfolio-section\">\n  <div class=\"portfolio-container\">\n    <div class=\"portfolio-header reveal\">\n      <h2>作品集</h2>\n      <p>Portfolio — 3D 倾斜卡片 + 渐变旋转边框 + 鼠标光斑 + 滚动揭示</p>\n    </div>\n\n    <div class=\"card-grid\">\n      <div class=\"tilt-card reveal reveal-d1\">\n        <div class=\"tilt-card-inner\">\n          <div class=\"card-icon\" style=\"background: linear-gradient(135deg, #667eea, #764ba2);\">S</div>\n          <div class=\"card-title\">Static Blog</div>\n          <div class=\"card-desc\">零依赖、Token 驱动主题的静态博客平台。支持 Markdown 渲染、暗色模式、i18n、增量构建。</div>\n          <div class=\"card-tags\">\n            <span class=\"card-tag\">Node.js</span>\n            <span class=\"card-tag\">CSS</span>\n            <span class=\"card-tag\">Markdown</span>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"tilt-card reveal reveal-d2\">\n        <div class=\"tilt-card-inner\">\n          <div class=\"card-icon\" style=\"background: linear-gradient(135deg, #f093fb, #f5576c);\">T</div>\n          <div class=\"card-title\">Theme Engine</div>\n          <div class=\"card-desc\">45+ CSS Token 驱动的主题引擎。支持三态亮暗切换、布局控制、自定义字体、模板覆盖。</div>\n          <div class=\"card-tags\">\n            <span class=\"card-tag\">CSS</span>\n            <span class=\"card-tag\">Design Tokens</span>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"tilt-card reveal reveal-d3\">\n        <div class=\"tilt-card-inner\">\n          <div class=\"card-icon\" style=\"background: linear-gradient(135deg, #4facfe, #00f2fe);\">P</div>\n          <div class=\"card-title\">Plugin System</div>\n          <div class=\"card-desc\">可插拔的构建插件架构。RSS、Sitemap、搜索索引、SSG 各自独立，互不影响。</div>\n          <div class=\"card-tags\">\n            <span class=\"card-tag\">Architecture</span>\n            <span class=\"card-tag\">Plugins</span>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"tilt-card reveal reveal-d1\">\n        <div class=\"tilt-card-inner\">\n          <div class=\"card-icon\" style=\"background: linear-gradient(135deg, #43e97b, #38f9d7);\">D</div>\n          <div class=\"card-title\">Docker Deploy</div>\n          <div class=\"card-desc\">原生 Docker 支持。挂载用户工作区、自动初始化、健康检查、128MB 内存限制。</div>\n          <div class=\"card-tags\">\n            <span class=\"card-tag\">Docker</span>\n            <span class=\"card-tag\">Nginx</span>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"tilt-card reveal reveal-d2\">\n        <div class=\"tilt-card-inner\">\n          <div class=\"card-icon\" style=\"background: linear-gradient(135deg, #fa709a, #fee140);\">I</div>\n          <div class=\"card-title\">i18n System</div>\n          <div class=\"card-desc\">中英双语完整支持。语言切换面板、自动检测可用语言、locale 文件自描述。</div>\n          <div class=\"card-tags\">\n            <span class=\"card-tag\">i18n</span>\n            <span class=\"card-tag\">JSON</span>\n          </div>\n        </div>\n      </div>\n\n      <div class=\"tilt-card reveal reveal-d3\">\n        <div class=\"tilt-card-inner\">\n          <div class=\"card-icon\" style=\"background: linear-gradient(135deg, #a18cd1, #fbc2eb);\">C</div>\n          <div class=\"card-title\">Custom Pages</div>\n          <div class=\"card-desc\">高级自定义页面系统。支持 standalone 独立模式、CSS 隔离、数据嵌入、JS 执行控制。</div>\n          <div class=\"card-tags\">\n            <span class=\"card-tag\">HTML</span>\n            <span class=\"card-tag\">CSS</span>\n            <span class=\"card-tag\">JS</span>\n          </div>\n        </div>\n      </div>\n    </div>\n  </div>\n</div>\n\n<script>\n(function() {\n  // 3D Tilt + Spotlight\n  document.querySelectorAll('.tilt-card').forEach(function(card) {\n    var inner = card.querySelector('.tilt-card-inner');\n    card.addEventListener('mousemove', function(e) {\n      var rect = card.getBoundingClientRect();\n      var x = (e.clientX - rect.left) / rect.width - 0.5;\n      var y = (e.clientY - rect.top) / rect.height - 0.5;\n      inner.style.transform = 'perspective(1000px) rotateY(' + (x * 12) + 'deg) rotateX(' + (-y * 12) + 'deg) scale3d(1.02, 1.02, 1.02)';\n      inner.style.setProperty('--mx', (e.clientX - rect.left) + 'px');\n      inner.style.setProperty('--my', (e.clientY - rect.top) + 'px');\n    });\n    card.addEventListener('mouseleave', function() {\n      inner.style.transform = 'perspective(1000px) rotateY(0) rotateX(0) scale3d(1,1,1)';\n    });\n  });\n\n  // Scroll reveal\n  var observer = new IntersectionObserver(function(entries) {\n    entries.forEach(function(entry) {\n      if (entry.isIntersecting) {\n        entry.target.classList.add('visible');\n        observer.unobserve(entry.target);\n      }\n    });\n  }, { threshold: 0.15 });\n  document.querySelectorAll('.reveal').forEach(function(el) { observer.observe(el); });\n})();\n</script></div>",
      "_isCustom": true,
      "_isStandalone": false
    },
    {
      "id": "playground",
      "name": "工具箱",
      "icon": ">",
      "type": "custom",
      "source": "content/pages/playground.html",
      "standalone": true,
      "scripts": true,
      "content": "<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>工具箱</title>\n  <style>\n    * { margin: 0; padding: 0; box-sizing: border-box; }\n    body {\n      font-family: -apple-system, \"Segoe UI\", \"PingFang SC\", sans-serif;\n      background: #0a0a0f;\n      color: #e8eaf0;\n      min-height: 100vh;\n      overflow-x: hidden;\n    }\n\n    /* ── Animated Border ──────────────────────────────── */\n    @property --border-angle { syntax: \"<angle>\"; inherits: false; initial-value: 0deg; }\n\n    .magic-border {\n      --border-angle: 0deg;\n      border: 2px solid transparent;\n      border-radius: 16px;\n      padding: 32px;\n      background:\n        linear-gradient(#14141f, #14141f) padding-box,\n        conic-gradient(from var(--border-angle), #667eea, #764ba2, #f093fb, #4facfe, #667eea) border-box;\n      animation: rotate-border 4s linear infinite;\n    }\n    @keyframes rotate-border { to { --border-angle: 360deg; } }\n\n    /* ── Particles ────────────────────────────────────── */\n    .particles {\n      position: fixed;\n      inset: 0;\n      pointer-events: none;\n      z-index: 0;\n      overflow: hidden;\n    }\n    .particles span {\n      position: absolute;\n      width: 4px;\n      height: 4px;\n      border-radius: 50%;\n      background: rgba(102,126,234,0.6);\n      opacity: 0;\n      animation: float-up linear infinite;\n    }\n    @keyframes float-up {\n      0%   { transform: translateY(100vh) scale(0); opacity: 0; }\n      10%  { opacity: 0.7; }\n      90%  { opacity: 0.7; }\n      100% { transform: translateY(-10vh) scale(1); opacity: 0; }\n    }\n    .particles span:nth-child(1) { left: 8%; animation-duration: 10s; animation-delay: 0s; }\n    .particles span:nth-child(2) { left: 22%; animation-duration: 14s; animation-delay: 2s; }\n    .particles span:nth-child(3) { left: 38%; animation-duration: 11s; animation-delay: 4s; }\n    .particles span:nth-child(4) { left: 55%; animation-duration: 13s; animation-delay: 1s; }\n    .particles span:nth-child(5) { left: 70%; animation-duration: 9s; animation-delay: 3s; }\n    .particles span:nth-child(6) { left: 85%; animation-duration: 12s; animation-delay: 5s; }\n    .particles span:nth-child(7) { left: 15%; animation-duration: 15s; animation-delay: 6s; }\n    .particles span:nth-child(8) { left: 92%; animation-duration: 10s; animation-delay: 2.5s; }\n\n    /* ── Layout ───────────────────────────────────────── */\n    .page-wrap { position: relative; z-index: 1; max-width: 800px; margin: 0 auto; padding: 80px 20px; }\n\n    .back-link {\n      display: inline-flex;\n      align-items: center;\n      gap: 6px;\n      font-size: 13px;\n      color: rgba(255,255,255,0.4);\n      text-decoration: none;\n      margin-bottom: 40px;\n      transition: color 0.2s;\n    }\n    .back-link:hover { color: #fff; }\n\n    h1 { font-size: 36px; font-weight: 700; color: #fff; margin-bottom: 8px; }\n    .subtitle { color: rgba(255,255,255,0.5); font-size: 15px; margin-bottom: 48px; }\n\n    /* ── Typewriter ───────────────────────────────────── */\n    .typewriter-wrap { margin-bottom: 48px; }\n    .typewriter-text {\n      font-size: 20px;\n      color: #8b9cf7;\n      font-family: \"JetBrains Mono\", monospace;\n      min-height: 32px;\n    }\n    .typewriter-text::after {\n      content: \"|\";\n      animation: blink 1s step-end infinite;\n      color: #667eea;\n    }\n    @keyframes blink { 50% { opacity: 0; } }\n\n    /* ── Theme Preview ────────────────────────────────── */\n    .section-title {\n      font-size: 12px;\n      text-transform: uppercase;\n      letter-spacing: 0.12em;\n      color: rgba(255,255,255,0.3);\n      margin-bottom: 16px;\n    }\n    .theme-grid {\n      display: flex;\n      gap: 12px;\n      flex-wrap: wrap;\n      margin-bottom: 48px;\n    }\n    .theme-chip {\n      display: flex;\n      align-items: center;\n      gap: 10px;\n      padding: 12px 20px;\n      background: rgba(255,255,255,0.04);\n      border: 1px solid rgba(255,255,255,0.08);\n      border-radius: 12px;\n      cursor: pointer;\n      transition: all 0.2s;\n    }\n    .theme-chip:hover { background: rgba(255,255,255,0.08); border-color: rgba(255,255,255,0.15); }\n    .theme-chip.active { border-color: #667eea; background: rgba(102,126,234,0.1); }\n    .theme-dot { width: 16px; height: 16px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.15); }\n    .theme-chip-name { font-size: 13px; color: rgba(255,255,255,0.7); }\n\n    /* ── Info Box ─────────────────────────────────────── */\n    .info-box {\n      padding: 20px;\n      background: rgba(255,255,255,0.03);\n      border: 1px solid rgba(255,255,255,0.06);\n      border-radius: 12px;\n      font-size: 13px;\n      color: rgba(255,255,255,0.4);\n      line-height: 1.8;\n    }\n    .info-box strong { color: rgba(255,255,255,0.7); }\n    .info-box code {\n      background: rgba(102,126,234,0.12);\n      color: #8b9cf7;\n      padding: 2px 6px;\n      border-radius: 4px;\n      font-size: 12px;\n    }\n  </style>\n</head>\n<body>\n  <!-- Particles -->\n  <div class=\"particles\">\n    <span></span><span></span><span></span><span></span>\n    <span></span><span></span><span></span><span></span>\n  </div>\n\n  <div class=\"page-wrap\">\n    <a class=\"back-link\" href=\"./index.html\" target=\"_top\">← 返回首页</a>\n\n    <h1>工具箱</h1>\n    <p class=\"subtitle\">Playground — standalone 独立页面 + 打字机 + 粒子背景 + 动画边框 + 主题预览</p>\n\n    <!-- Typewriter -->\n    <div class=\"typewriter-wrap\">\n      <div class=\"typewriter-text\" id=\"typewriter\"></div>\n    </div>\n\n    <!-- Animated Border Card -->\n    <div class=\"magic-border\" style=\"margin-bottom: 48px;\">\n      <div class=\"section-title\">动画渐变边框</div>\n      <p style=\"font-size: 14px; color: rgba(255,255,255,0.6); line-height: 1.7;\">\n        这个卡片的边框使用 <code>@property</code> 注册的 CSS 自定义属性驱动 <code>conic-gradient</code> 旋转。\n        纯 CSS 实现，零 JavaScript。这是 2024-2025 年最流行的 CSS 技巧之一。\n      </p>\n    </div>\n\n    <!-- Theme Preview -->\n    <div class=\"section-title\">主题预览（点击切换 CSS 变量）</div>\n    <div class=\"theme-grid\">\n      <div class=\"theme-chip active\" data-accent=\"#667eea\" data-bg=\"#0a0a0f\" data-text=\"#e8eaf0\">\n        <div class=\"theme-dot\" style=\"background: #667eea;\"></div>\n        <span class=\"theme-chip-name\">Midnight</span>\n      </div>\n      <div class=\"theme-chip\" data-accent=\"#0ea5e9\" data-bg=\"#0c1929\" data-text=\"#e0f2fe\">\n        <div class=\"theme-dot\" style=\"background: #0ea5e9;\"></div>\n        <span class=\"theme-chip-name\">Ocean</span>\n      </div>\n      <div class=\"theme-chip\" data-accent=\"#f97316\" data-bg=\"#1a0f0a\" data-text=\"#ffedd5\">\n        <div class=\"theme-dot\" style=\"background: #f97316;\"></div>\n        <span class=\"theme-chip-name\">Sunset</span>\n      </div>\n      <div class=\"theme-chip\" data-accent=\"#22c55e\" data-bg=\"#0a1a0f\" data-text=\"#dcfce7\">\n        <div class=\"theme-dot\" style=\"background: #22c55e;\"></div>\n        <span class=\"theme-chip-name\">Forest</span>\n      </div>\n      <div class=\"theme-chip\" data-accent=\"#e879f9\" data-bg=\"#1a0a1f\" data-text=\"#fae8ff\">\n        <div class=\"theme-dot\" style=\"background: #e879f9;\"></div>\n        <span class=\"theme-chip-name\">Neon</span>\n      </div>\n    </div>\n\n    <!-- Info -->\n    <div class=\"info-box\">\n      <strong>standalone 模式：</strong>这个页面隐藏了平台导航栏和页脚，完全独立运行。\n      页面底部有\"返回首页\"链接。所有样式和脚本都在页面内部，不影响平台其他页面。<br><br>\n      <strong>scripts: true</strong> — 页面 JS 仅做 DOM 操作（打字机、主题切换）。\n      无网络请求、无 eval、无外部依赖、无 localStorage 读写。\n    </div>\n  </div>\n\n  <script>\n  (function() {\n    // Typewriter\n    var texts = [\n      '零依赖静态博客平台',\n      'Token 驱动主题系统',\n      'Markdown 优先，构建时渲染',\n      '支持 Docker / GitHub Pages / npm'\n    ];\n    var tw = document.getElementById('typewriter');\n    var ti = 0, ci = 0, del = false;\n    function tick() {\n      var cur = texts[ti];\n      if (!del) {\n        tw.textContent = cur.slice(0, ++ci);\n        if (ci === cur.length) { setTimeout(function() { del = true; tick(); }, 2000); return; }\n      } else {\n        tw.textContent = cur.slice(0, --ci);\n        if (ci === 0) { del = false; ti = (ti + 1) % texts.length; }\n      }\n      setTimeout(tick, del ? 40 : 80);\n    }\n    tick();\n\n    // Theme preview\n    document.querySelectorAll('.theme-chip').forEach(function(chip) {\n      chip.addEventListener('click', function() {\n        document.querySelectorAll('.theme-chip').forEach(function(c) { c.classList.remove('active'); });\n        chip.classList.add('active');\n        var accent = chip.dataset.accent;\n        var bg = chip.dataset.bg;\n        var text = chip.dataset.text;\n        document.documentElement.style.setProperty('--accent', accent);\n        document.body.style.background = bg;\n        document.body.style.color = text;\n      });\n    });\n  })();\n  </script>\n</body>\n</html>\n",
      "_isCustom": true,
      "_isStandalone": true
    }
  ],
  "nav": [
    {
      "name": "首页",
      "page": "index"
    },
    {
      "name": "关于",
      "page": "about"
    },
    {
      "name": "技能",
      "page": "skills"
    },
    {
      "name": "作品",
      "page": "portfolio"
    },
    {
      "name": "工具",
      "page": "playground"
    },
    {
      "name": "瞬间",
      "url": "./moments.html"
    },
    {
      "name": "参考",
      "url": "./links.html"
    },
    {
      "name": "图库",
      "url": "./gallery.html"
    }
  ],
  "navActions": [
    {
      "type": "link",
      "icon": "RSS",
      "url": "./feed.xml",
      "title": "RSS 订阅"
    }
  ],
  "features": {
    "moments": {
      "enabled": true,
      "source": "content/data/moments.yml",
      "moments": [
        {
          "date": "2026-06-29",
          "mood": "Ship",
          "content": "5 个内置主题全部支持亮暗切换，导航栏新增语言切换按钮。",
          "tags": [
            "theme",
            "i18n"
          ]
        },
        {
          "date": "2026-06-20",
          "mood": "Note",
          "content": "图库功能上线，支持目录扫描、文件夹导航和灯箱查看器。",
          "tags": [
            "gallery",
            "feature"
          ]
        }
      ]
    },
    "links": {
      "enabled": true,
      "source": "content/data/links.yml",
      "groups": [
        {
          "id": "references",
          "name": "设计参考",
          "icon": "Ref"
        },
        {
          "id": "reading",
          "name": "长期阅读",
          "icon": "Read"
        },
        {
          "id": "tools",
          "name": "常用工具",
          "icon": "Tool"
        }
      ],
      "links": [
        {
          "name": "UI Patterns",
          "url": "https://ui-patterns.com/",
          "description": "交互模式、信息层级和常见流程的参考入口。",
          "icon": "UI",
          "label": "模式",
          "group": "references"
        },
        {
          "name": "Smashing Magazine",
          "url": "https://www.smashingmagazine.com/",
          "description": "前端体验、设计系统和内容表达的长期阅读来源。",
          "icon": "SM",
          "label": "阅读",
          "group": "reading"
        },
        {
          "name": "A List Apart",
          "url": "https://alistapart.com/",
          "description": "方法论和长期写作，适合沉淀内容结构与编辑感。",
          "icon": "AL",
          "label": "文章",
          "group": "reading"
        },
        {
          "name": "MDN Web Docs",
          "url": "https://developer.mozilla.org/",
          "description": "Web 技术参考，HTML/CSS/JS 标准文档。",
          "icon": "MD",
          "label": "文档",
          "group": "tools"
        }
      ]
    },
    "gallery": {
      "enabled": true,
      "source": "content/data/gallery.yml",
      "settings": {
        "maxDepth": 2,
        "formats": [
          "jpg",
          "jpeg",
          "png",
          "gif",
          "webp",
          "svg"
        ]
      },
      "groups": [
        {
          "id": "identity",
          "name": "品牌资产",
          "icon": "ID",
          "path": "assets/gallery/identity",
          "maxDepth": 1
        },
        {
          "id": "posters",
          "name": "视觉基线",
          "icon": "DS",
          "path": "assets/gallery/posters",
          "maxDepth": 1
        }
      ],
      "images": {
        "identity": {
          "images": [
            "assets/gallery/identity/brand-mark.svg"
          ],
          "subfolders": {}
        },
        "posters": {
          "images": [
            "assets/gallery/posters/theme-board.svg"
          ],
          "subfolders": {}
        }
      }
    }
  },
  "display": {
    "postsPerPage": 6,
    "summaryLength": 140,
    "heroBadge": "Markdown First",
    "heroSubtitle": "少配置、强主题、可部署到任意子路径。",
    "showSiteInfo": true,
    "siteType": "静态博客",
    "contentDirection": "Markdown / Themes / Notes",
    "hero": {
      "immersive": false,
      "background": {
        "enabled": false,
        "image": "",
        "focalPoint": "center center",
        "fit": "cover",
        "dimming": 0.42,
        "blur": 0
      }
    }
  },
  "beian": {
    "enabled": false,
    "displayName": "",
    "icp": {
      "enabled": false,
      "number": "",
      "url": "https://beian.miit.gov.cn/"
    },
    "police": {
      "enabled": false,
      "number": "",
      "url": "",
      "statusText": ""
    }
  },
  "comments": {
    "enabled": false,
    "provider": "giscus",
    "giscus": {
      "repo": "",
      "repoId": "",
      "category": "",
      "categoryId": "",
      "mapping": "pathname",
      "reactionsEnabled": true,
      "emitMetadata": false
    }
  }
}