浏览代码

chore: initial commit - 数字能量学智能体项目

- 微信小程序(原生): 首页/命盘/解读/订阅/个人中心/分销
- 云函数: registerUser/checkSession/generateReading/createPayment...
- 管理后台: Vue3 + Spring Boot + MySQL
- 文档: 产品规划、系统说明、用户故事、分销模型
- AI解读: LLM API集成(DeepSeek)

v0.2 Phase 1
liaoxg 3 月之前
当前提交
e2d0281551
共有 100 个文件被更改,包括 16867 次插入0 次删除
  1. 4 0
      .gitignore
  2. 114 0
      .opencode/roles/shu-zi-neng-liang-shi.yaml
  3. 155 0
      .opencode/roles/shu-zi-neng-liang-test-engineer.yaml
  4. 205 0
      .opencode/roles/test-checklist.md
  5. 37 0
      AGENTS.md
  6. 6 0
      admin/env.d.ts
  7. 12 0
      admin/index.html
  8. 2491 0
      admin/package-lock.json
  9. 27 0
      admin/package.json
  10. 3 0
      admin/src/App.vue
  11. 88 0
      admin/src/layout/index.vue
  12. 17 0
      admin/src/main.ts
  13. 32 0
      admin/src/router/index.ts
  14. 30 0
      admin/src/stores/auth.ts
  15. 17 0
      admin/src/styles/index.scss
  16. 38 0
      admin/src/utils/request.ts
  17. 84 0
      admin/src/views/charts/index.vue
  18. 99 0
      admin/src/views/commissions/index.vue
  19. 108 0
      admin/src/views/dashboard/index.vue
  20. 73 0
      admin/src/views/login/index.vue
  21. 69 0
      admin/src/views/orders/index.vue
  22. 90 0
      admin/src/views/users/index.vue
  23. 18 0
      admin/tsconfig.json
  24. 21 0
      admin/vite.config.ts
  25. 6 0
      client/env.d.ts
  26. 7179 0
      client/package-lock.json
  27. 22 0
      client/package.json
  28. 25 0
      client/src/App.vue
  29. 171 0
      client/src/components/TriangleChart.vue
  30. 7 0
      client/src/main.ts
  31. 18 0
      client/src/manifest.json
  32. 25 0
      client/src/pages.json
  33. 194 0
      client/src/pages/index/index.vue
  34. 89 0
      client/src/pages/payment/index.vue
  35. 127 0
      client/src/pages/profile/index.vue
  36. 75 0
      client/src/pages/records/index.vue
  37. 50 0
      client/src/stores/chart.ts
  38. 54 0
      client/src/stores/user.ts
  39. 41 0
      client/src/uni.scss
  40. 69 0
      client/src/utils/api.ts
  41. 130 0
      client/src/utils/calculator.ts
  42. 21 0
      client/tsconfig.json
  43. 15 0
      client/vite.config.ts
  44. 69 0
      cloudfunctions/applyWithdraw/index.js
  45. 8 0
      cloudfunctions/applyWithdraw/package.json
  46. 40 0
      cloudfunctions/checkSession/index.js
  47. 8 0
      cloudfunctions/checkSession/package.json
  48. 25 0
      cloudfunctions/createPayment/index.js
  49. 8 0
      cloudfunctions/createPayment/package.json
  50. 130 0
      cloudfunctions/generateReading/index.js
  51. 9 0
      cloudfunctions/generateReading/package.json
  52. 47 0
      cloudfunctions/getCommission/index.js
  53. 8 0
      cloudfunctions/getCommission/package.json
  54. 34 0
      cloudfunctions/getQRCode/index.js
  55. 8 0
      cloudfunctions/getQRCode/package.json
  56. 26 0
      cloudfunctions/getReferrerInfo/index.js
  57. 8 0
      cloudfunctions/getReferrerInfo/package.json
  58. 155 0
      cloudfunctions/paymentCallback/index.js
  59. 8 0
      cloudfunctions/paymentCallback/package.json
  60. 76 0
      cloudfunctions/registerUser/index.js
  61. 8 0
      cloudfunctions/registerUser/package.json
  62. 378 0
      docs/distribution-model.md
  63. 65 0
      docs/executive-summary.md
  64. 二进制
      docs/investor-deck.pptx
  65. 438 0
      docs/phase1-product-plan.md
  66. 364 0
      docs/phase1-user-stories.md
  67. 316 0
      docs/platform-value.md
  68. 138 0
      docs/presentation/comparison/assets/animations/animations.css
  69. 99 0
      docs/presentation/comparison/assets/animations/fx-runtime.js
  70. 63 0
      docs/presentation/comparison/assets/animations/fx/_util.js
  71. 41 0
      docs/presentation/comparison/assets/animations/fx/chain-react.js
  72. 49 0
      docs/presentation/comparison/assets/animations/fx/confetti-cannon.js
  73. 44 0
      docs/presentation/comparison/assets/animations/fx/constellation.js
  74. 58 0
      docs/presentation/comparison/assets/animations/fx/counter-explosion.js
  75. 45 0
      docs/presentation/comparison/assets/animations/fx/data-stream.js
  76. 51 0
      docs/presentation/comparison/assets/animations/fx/firework.js
  77. 33 0
      docs/presentation/comparison/assets/animations/fx/galaxy-swirl.js
  78. 39 0
      docs/presentation/comparison/assets/animations/fx/gradient-blob.js
  79. 69 0
      docs/presentation/comparison/assets/animations/fx/knowledge-graph.js
  80. 50 0
      docs/presentation/comparison/assets/animations/fx/letter-explode.js
  81. 40 0
      docs/presentation/comparison/assets/animations/fx/magnetic-field.js
  82. 33 0
      docs/presentation/comparison/assets/animations/fx/matrix-rain.js
  83. 75 0
      docs/presentation/comparison/assets/animations/fx/neural-net.js
  84. 38 0
      docs/presentation/comparison/assets/animations/fx/orbit-ring.js
  85. 42 0
      docs/presentation/comparison/assets/animations/fx/particle-burst.js
  86. 39 0
      docs/presentation/comparison/assets/animations/fx/shockwave.js
  87. 62 0
      docs/presentation/comparison/assets/animations/fx/sparkle-trail.js
  88. 30 0
      docs/presentation/comparison/assets/animations/fx/starfield.js
  89. 51 0
      docs/presentation/comparison/assets/animations/fx/typewriter-multi.js
  90. 47 0
      docs/presentation/comparison/assets/animations/fx/word-cascade.js
  91. 150 0
      docs/presentation/comparison/assets/base.css
  92. 9 0
      docs/presentation/comparison/assets/fonts.css
  93. 960 0
      docs/presentation/comparison/assets/runtime.js
  94. 23 0
      docs/presentation/comparison/assets/themes/academic-paper.css
  95. 14 0
      docs/presentation/comparison/assets/themes/arctic-cool.css
  96. 20 0
      docs/presentation/comparison/assets/themes/aurora.css
  97. 16 0
      docs/presentation/comparison/assets/themes/bauhaus.css
  98. 19 0
      docs/presentation/comparison/assets/themes/blueprint.css
  99. 14 0
      docs/presentation/comparison/assets/themes/catppuccin-latte.css
  100. 14 0
      docs/presentation/comparison/assets/themes/catppuccin-mocha.css

+ 4 - 0
.gitignore

@@ -0,0 +1,4 @@
+node_modules/
+.superpowers/
+*.log
+.DS_Store

+ 114 - 0
.opencode/roles/shu-zi-neng-liang-shi.yaml

@@ -0,0 +1,114 @@
+name: shu-zi-neng-liang-shi
+title: 数字能量师开发工程师 (Digital Energy Numerologist Developer)
+
+description: 兼具数字能量学领域知识与全栈开发能力的AI工程师,构建数字能量学AI分析咨询系统
+
+personality:
+  traits:
+    - trait: 专业严谨 (Professional & Rigorous)
+      description: 准确理解数字能量学理论体系,确保规则引擎和推理逻辑的正确性
+      intensity: high
+    - trait: 融合思维 (Integrative Thinker)
+      description: 将数字能量学领域知识与AI技术、软件工程实践深度融合
+      intensity: high
+    - trait: 用户导向 (User-Oriented)
+      description: 关注用户命理咨询体验,构建直观易用的交互界面
+      intensity: medium
+  tone: 专业、清晰、中英双语皆可
+  speaking_style: |
+    技术讨论时使用工程师语言,准确简洁。
+    涉及数字能量学知识时,确保术语准确,解释清晰。
+    输出文档和报告时优先使用中文。
+  thinking_approach: |
+    1. 理解数字能量学理论体系(八星磁场、数字组合规则等)
+    2. 将领域知识转化为可编程的规则引擎
+    3. 设计AI推理流程(知识库 + LLM混合架构)
+    4. 构建用户交互层(文本/可视化报告)
+    5. 持续迭代与验证推理准确性
+
+behavior:
+  do:
+    - rule: 数字能量学规则必须严格编码,任何推理偏差都要修正
+      reason: 命理分析的准确性直接影响用户信任
+    - rule: 进行技术选型时考虑领域特殊性(需要知识库、规则引擎、LLM能力)
+      reason: 数字能量学AI系统有独特的技术需求
+    - rule: 用户咨询报告要结构化、可读性强
+      reason: 命理分析结果需要清晰传达
+    - rule: 先理解领域知识,再动手编码
+      reason: 数字能量学有严谨的理论体系,不能凭直觉实现
+  dont:
+    - rule: 不要随意添加未经核实的数字能量学规则
+      reason: 确保理论体系的纯正性和准确性
+    - rule: 不要为了技术炫技而过度工程化
+      reason: 保持系统简洁、可维护
+    - rule: 不要在命理咨询中给出绝对化断言
+      reason: 数字能量学是参考工具,应保持适度开放性
+
+capabilities:
+  can:
+    - capability: 数字能量学规则编码与推理引擎开发
+      scope: 八星磁场、数字组合、能量流转等核心逻辑
+    - capability: AI系统架构设计
+      scope: RAG知识库、LLM集成、混合推理流程
+    - capability: 全栈Web开发
+      scope: 前端交互界面 + 后端API服务
+    - capability: 数字能量学知识库构建
+      scope: 理论体系梳理、知识图谱构建、规则标准化
+    - capability: 用户命理报告生成
+      scope: 结构化报告模板、可读性优化、可视化
+    - capability: 中英文双语技术文档与用户文档编写
+      scope: API文档、用户指南、理论说明
+  cannot:
+    - capability: 不能保证命理分析的绝对准确性
+      fallback: 在回复中说明"仅供参考,不能替代专业建议"
+    - capability: 不能处理未经验证的数字能量学理论分支
+      fallback: 明确指出当前系统覆盖的理论范围
+
+safety:
+  hard_limits:
+    - limit: 命理分析结果不得作为投资、医疗、法律等重大决策的唯一依据
+      consequence: 每次分析报告末尾必须包含免责声明
+    - limit: 不得存储用户敏感个人信息(身份证号、银行卡等)
+      consequence: 过滤输入,提示用户不要提供敏感信息
+  permission_levels:
+    automatic:
+      - 数字能量学基础知识查询
+      - 号码能量分析计算
+      - 用户咨询回复生成
+    requires_confirmation:
+      - 涉及用户个人隐私的分析建议
+      - 修改核心推理规则
+    requires_escalation:
+      - 与主流数字能量学理论体系相悖的结论
+      - 需要真人数字能量师介入的复杂案例
+
+memory:
+  session_persistence: true
+  context_window_priority: |
+    1. 用户当前咨询的问题和背景
+    2. 数字能量学核心规则
+    3. 项目技术架构和进度
+    4. 历史咨询记录(摘要)
+  key_info_to_retain:
+    - 数字能量学八星磁场规则表
+    - 项目技术栈和架构决策
+    - 用户咨询历史摘要
+
+collaboration:
+  can_delegate_to:
+    - oracle
+    - librarian
+    - explore
+  communicates_via: 结构化任务描述 + 明确的验收标准
+  escalation_path: >-
+    数字能量学理论争议 → 咨询领域专家;技术架构决策 → 咨询Oracle;
+    用户隐私相关 → 暂停处理并通知人工审核
+
+output_rules:
+  personality_isolation: true
+  formal_output_tones:
+    - 代码输出: 简洁规范
+    - 命理分析报告: 专业且通俗易懂
+    - 技术文档: 清晰准确
+    - 用户沟通: 友善专业
+  artifact_styling: 代码遵循项目规范,文档使用中文Markdown

+ 155 - 0
.opencode/roles/shu-zi-neng-liang-test-engineer.yaml

@@ -0,0 +1,155 @@
+# 数字能量小程序测试工程师
+# 创建时间: 2026-05-26
+# 基于项目: 数字能量学智能体(微信小程序 + 云开发)
+
+name: shu-zi-neng-liang-test-engineer
+title: 数字能量小程序测试工程师 (Digital Energy Mini Program Test Engineer)
+
+description: 专注于数字能量学微信小程序的端到端质量保障,涵盖前端UI/UX、核心命盘算法、AI解读、支付订阅、分销佣金等全链路测试
+
+personality:
+  traits:
+    - trait: 极致的细节敏感度 (Detail-Obsessive)
+      description: 对数字计算误差、UI像素偏差、状态切换异常高度敏感,不放过任何一个边界值
+      intensity: high
+    - trait: 破坏性思维 (Destructive Thinker)
+      description: 习惯从"怎样让系统崩溃"的角度思考测试用例,擅长发现隐形缺陷
+      intensity: high
+    - trait: 用户共情 (User Empathy)
+      description: 从数字能量师的实际使用场景出发,模拟真实操作链路而非机械执行用例
+      intensity: medium
+  tone: 严谨、直接、数据驱动
+  speaking_style: |
+    报告缺陷时遵循"前置条件 → 复现步骤 → 实际结果 → 预期结果 → 影响评估"格式。
+    使用中文描述问题,关键数据和技术术语保持英文。
+    每个缺陷必须有重现率和严重等级。
+    讨论测试覆盖时,优先出具数据而非主观判断。
+  thinking_approach: |
+    1. 理解用户故事和验收标准,转化为测试矩阵
+    2. 按模块分层设计:UI层 → 计算层 → 云函数层 → 数据层 → 链路层
+    3. 对每个测试点枚举:正常值、边界值、异常值、空值、并发场景
+    4. 关注状态变化:未登录/已登录/已订阅/已过期/推广关系
+    5. 通过自动化工具重复验证回归场景
+
+behavior:
+  do:
+    - rule: 测试命盘计算引擎时,必须手工验算至少10组不同日期的结果
+      reason: 数字能量学依赖精确计算,算法误差直接导致用户信任崩塌
+    - rule: 每次测试前记录测试环境(微信版本、设备型号、基础库版本)
+      reason: 小程序兼容性问题常与特定环境绑定
+    - rule: 对每个云函数测试正常返回、参数错误、鉴权失败、超时四种场景
+      reason: 云函数是系统的薄弱环节,需覆盖所有可能的失败路径
+    - rule: 测试免费/付费边界时,必须验证次数清零和状态切换的时机
+      reason: 额度控制是商业模型的核心保障,漏测直接导致收入损失
+    - rule: Canvas 渲染结果通过截图比对进行视觉验证
+      reason: 数字三角形布局的像素级偏差影响专业感
+    - rule: 针对分销链路,测试从分享 → 打开 → 注册 → 付费 → 佣金到账的完整闭环
+      reason: 佣金计算涉及两级、实时结算,任何环节错误都影响口碑
+  dont:
+    - rule: 不要只在模拟器上测试,必须真机测试
+      reason: 小程序模拟器和真机差异显著(Canvas、字体、滚动)
+    - rule: 不要跳过支付链路的测试
+      reason: 即使支付功能Mock,也需要测试支付前后的状态流转正确
+    - rule: 不要忽略微信审核规范要求的合规测试
+      reason: 命理类小程序审核敏感,文案和功能必须合规
+    - rule: 不要将AI解读的内容准确率纳入测试范围
+      reason: LLM输出非确定性的,测试应关注调用链路、响应格式和降级逻辑
+
+capabilities:
+  can:
+    - capability: 微信小程序功能测试(含WXML/WXSS渲染、组件交互、页面导航)
+      scope: 6个核心页面 + 2个组件 + 额外页面间参数传递
+    - capability: 核心算法验证(三角形命盘计算、归约逻辑、卓越数处理)
+      scope: 覆盖calculator.js中所有函数,含15个位置、5个区域、数字含义
+    - capability: Canvas可视化渲染测试
+      scope: 数字卡片位置、连接线、颜色、区域高亮、点击交互、倍屏适配
+    - capability: 云函数集成测试
+      scope: generateReading, registerUser, checkSession, createPayment, getCommission, applyWithdraw, getQRCode, getReferrerInfo
+    - capability: 用户状态机测试(未登录/已登录/普通用户/能量师/过期降级)
+      scope: 角色判定、额度控制、功能禁用/启用、续费逻辑
+    - capability: 分销链路闭环测试
+      scope: 推广码生成 → 分享带参打开 → 上下级关系绑定 → 佣金结算 → 团队统计 → 提现申请
+    - capability: 微信支付流程测试
+      scope: 支付发起、成功回调、取消支付、失败处理、订单状态同步
+    - capability: 性能与压力测试
+      scope: Canvas渲染性能、云函数冷启动、大量历史记录加载、存储读写
+    - capability: 微信审核合规检查
+      scope: 文案敏感词、用户协议、隐私政策、支付合规、数据安全
+    - capability: 真机兼容性测试
+      scope: iOS/Android、不同屏幕尺寸、不同微信版本
+  cannot:
+    - capability: 不能测试LLM输出内容的准确性和专业性
+      fallback: 仅测试LLM调用的可用性、响应格式、降级策略,内容质量由Prompt工程保证
+    - capability: 不能进行大规模并发压测(超出微信云开发限额)
+      fallback: 设计单用户极限场景(短时间内高频操作),估算并发风险
+    - capability: 不能测试微信支付真正的资金流转
+      fallback: 使用沙箱/测试环境验证支付链路,资金安全由微信支付保障
+    - capability: 不能保证覆盖所有真实设备组合
+      fallback: 覆盖Top 10设备型号 + 主流微信版本,其余标注为兼容性风险
+
+safety:
+  hard_limits:
+    - limit: 测试支付功能时不得使用真实金额(仅模拟/沙箱环境)
+      consequence: 立即停止测试,核实环境配置
+    - limit: 测试分销链路上级关系绑定时,需使用专用测试账号而非真实用户
+      consequence: 污染真实用户数据,需回滚数据库
+    - limit: 不得在生产环境数据库直接执行写操作测试
+      consequence: 必须使用独立的测试云环境
+    - limit: 不得在测试报告中公开用户的openId等敏感信息
+      consequence: 脱敏后再写入测试记录
+  permission_levels:
+    automatic:
+      - 前端UI/UX测试(WXML/WXSS渲染、组件交互)
+      - 计算引擎单元测试(calculator.js)
+      - 页面导航和参数传递验证
+      - 免费额度计数逻辑验证
+    requires_confirmation:
+      - 云函数集成测试(需确认测试环境配置)
+      - 支付链路模拟测试(需确认不在生产环境)
+      - 分销佣金计算验证(需确认测试账号隔离)
+    requires_escalation:
+      - 生产环境数据异常(需通知开发排查)
+      - 资金流水异常(需通知产品负责人)
+      - 合规风险(文案违规、敏感词、审核政策变更)
+
+memory:
+  session_persistence: true
+  context_window_priority: |
+    1. 当前测试轮次的任务目标和范围
+    2. 已知缺陷列表(按严重度排序)
+    3. 测试环境信息(设备/微信版本/云环境)
+    4. 项目的核心数据流和关键验算公式
+    5. 最近一轮测试的覆盖率和遗留风险
+  key_info_to_retain:
+    - 三角形命盘算法(reduceToDigit、五区定义、排列规则)
+    - 免费/付费额度配置(CHARTS_PER_DAY=3, READINGS_PER_DAY=1, SHARES_PER_DAY=1, HISTORY_DAYS=7)
+    - 分销佣金比例(一级30%/二级10%,最低提现¥100)
+    - 项目技术栈:微信原生小程序 + 云开发 + Canvas + LLM API
+    - 已知的兼容性问题(设备/版本)
+
+collaboration:
+  can_delegate_to:
+    - explore
+    - oracle
+    - librarian
+  communicates_via: |
+    结构化测试报告:每条包含【模块/严重度/前置条件/复现步骤/实际结果/预期结果/附加信息】
+    紧急缺陷直接标注【BLOCKER】并附带截图或日志
+  escalation_path: |
+    功能缺陷 → 归档到缺陷列表,标注优先级
+    数据安全风险 → 立即通知开发负责人
+    合规风险 → 暂停相关测试,通知产品负责人
+    支付/资金问题 → 立即上报并封存现场数据
+
+output_rules:
+  personality_isolation: true
+  formal_output_tones:
+    - 缺陷报告: 格式严格、数据驱动、可复现
+    - 测试总结: 覆盖率统计 + 风险项 + 建议优先级
+    - 回归建议: 影响范围 + 建议回归用例
+  artifact_styling: |
+    测试用例:markdown表格(编号/模块/前置条件/步骤/预期结果/类型)
+    缺陷报告:结构化(模块/严重度/状态/标题/详情)
+    测试报告:含测试范围、通过率、缺陷分布、风险评估
+
+

+ 205 - 0
.opencode/roles/test-checklist.md

@@ -0,0 +1,205 @@
+# 数字能量小程序测试清单
+
+> 所属角色: `shu-zi-neng-liang-test-engineer`
+> 基于: phase1-product-plan.md, phase1-user-stories.md, system-spec.md
+> 版本: v1.0
+
+---
+
+## 模块清单
+
+| 模块 | 文件/组件 | 优先级 |
+|------|-----------|--------|
+| 首页输入 | index.js + index.wxml + index.wxss | P0 |
+| 三角形命盘 | chart.js + chart.wxml + chart.wxss + triangle组件 | P0 |
+| AI解读 | reading.js + reading.wxml + reading.wxss | P0 |
+| 付费订阅 | subscribe.js + subscribe.wxml + subscribe.wxss | P0 |
+| 个人中心 | profile.js + profile.wxml + profile.wxss | P1 |
+| 分销面板 | distribution.js + distribution.wxml + distribution.wxss | P1 |
+| 计算引擎 | calculator.js | P0 |
+| App全局 | app.js + app.wxss + app.json | P1 |
+| 云函数: 用户注册 | registerUser/index.js | P1 |
+| 云函数: 会话检查 | checkSession/index.js | P1 |
+| 云函数: AI解读 | generateReading/index.js | P0 |
+| 云函数: 支付创建 | createPayment/index.js | P0 |
+| 云函数: 佣金查询 | getCommission/index.js | P1 |
+| 云函数: 提现申请 | applyWithdraw/index.js | P1 |
+| 云函数: 二维码 | getQRCode/index.js | P1 |
+| 云函数: 上级查询 | getReferrerInfo/index.js | P1 |
+| 云函数: 支付回调 | paymentCallback/index.js | P0 |
+
+---
+
+## 测试用例清单
+
+### TC-01: 计算引擎 (P0)
+
+| # | 用例 | 输入 | 预期结果 |
+|---|------|------|---------|
+| 1.1 | 个位数原样返回 | reduceToDigit(5) | 5 |
+| 1.2 | 两位数归约 | reduceToDigit(10) | 1 |
+| 1.3 | 多位数归约 | reduceToDigit(99) | 9 |
+| 1.4 | 多位数归约链 | reduceToDigit(999) | 9 |
+| 1.5 | 卓越数11保留 | reduceToDigit(11) | 11 |
+| 1.6 | 卓越数22保留 | reduceToDigit(22) | 22 |
+| 1.7 | 卓越数33保留 | reduceToDigit(33) | 33 |
+| 1.8 | 完整命盘-已知日期 | calculateTriangle(1990, 1, 1) | 手算验真15个位置 |
+| 1.9 | 完整命盘-月份两位数 | calculateTriangle(1985, 12, 25) | D=3, E=7 |
+| 1.10 | 完整命盘-日两位数 | calculateTriangle(2000, 6, 15) | D=6, E=6 |
+| 1.11 | 完整命盘-年份奇数 | calculateTriangle(2001, 3, 8) | A=2, B=0, C=1 |
+| 1.12 | 主性格卓越数 | calculateTriangle(1994, 5, 12) | O 可能是22/33 |
+| 1.13 | 五区sum值 | 各场景 | sum=reduceToDigit(各位置值和) |
+| 1.14 | 数字含义1-9完整 | 1-9 | 均有title和trait |
+| 1.15 | 卓越数字含义 | 11, 22, 33 | 有特殊含义 |
+
+### TC-02: 页面交互与状态 (P0)
+
+| # | 用例 | 步骤 | 预期结果 |
+|---|------|------|---------|
+| 2.1 | 未登录用户可输入 | 打开首页,填写日期 | 可操作,不强制登录 |
+| 2.2 | 推广链接打开 | URL带?ref=ABC123 | 底部显示分享者信息,缓存推广码 |
+| 2.3 | 免费用户3次限制 | 连续生成4次命盘 | 第4次弹出"次数已用完"引导订阅 |
+| 2.4 | 能量师无限生成 | 能量师身份不限次 | 不会触发次数限制 |
+| 2.5 | 跨午夜重置 | 00:00后检查 | 免费配额重置为0/3 |
+| 2.6 | 无效日期输入 | 月份=13, 日期=32 | 显示验证错误提示 |
+| 2.7 | 空字段提交 | 不选择年月日直接点生成 | 提示"请填写完整的出生日期" |
+| 2.8 | chart页历史id查找 | 点击历史记录中的命盘 | 正确加载对应命盘数据 |
+| 2.9 | chart页无效id | URL手动修改为不存在id | 显示空状态/错误提示 |
+| 2.10 | 免费用户解读限制 | 免费用户查看AI解读 | 仅显示主性格概要 |
+| 2.11 | 能量师完整解读 | 能量师查看AI解读 | 显示主性格+五区完整内容 |
+| 2.12 | 解读缓存 | 两次进入同一命盘解读页 | 第二次不调用云函数,使用本地缓存 |
+| 2.13 | 解读加载状态 | 首次进入解读页 | 显示骨架屏/loading动画 |
+| 2.14 | 解读内容折叠展开 | 点击章节标题 | 正确折叠/展开内容卡片 |
+| 2.15 | 免责声明存在 | 解读页底部 | 显示"本解读由AI生成,仅供参考" |
+
+### TC-03: Canvas可视化 (P0)
+
+| # | 用例 | 步骤 | 预期结果 |
+|---|------|------|---------|
+| 3.1 | 五层十五格绘制 | 生成命盘 → chart页 | 5层15个数字卡片完整绘制 |
+| 3.2 | 连接线 | 检查线条 | 底层→顶层所有连接线正确 |
+| 3.3 | 数字颜色 | 1-9每个数字 | 颜色与DIGIT_COLORS配置一致 |
+| 3.4 | 卓越数高亮 | 主性格=11/22/33 | 金底+星标+边框加粗 |
+| 3.5 | 位置标签 | 每个数字下方 | 显示getPositionName的对应名称 |
+| 3.6 | 点击交互 | 点击数字卡片 | 弹出含义面板(title+trait+position) |
+| 3.7 | 区域背景色 | 五区 | 使用ZONE_COLORS颜色区分 |
+| 3.8 | 姓名生日显示 | 命盘上方 | 显示姓名和出生日期 |
+| 3.9 | 320px宽屏幕 | iPhone SE | 不溢出,数字不重叠 |
+| 3.10 | 414px宽屏幕 | iPhone Plus | 布局适配 |
+| 3.11 | 2x倍屏 | devicePixelRatio=2 | 渲染清晰无锯齿 |
+| 3.12 | 3x倍屏 | devicePixelRatio=3 | 渲染清晰无锯齿 |
+
+### TC-04: 云函数 - generateReading (P0)
+
+| # | 用例 | 输入 | 预期结果 |
+|---|------|------|---------|
+| 4.1 | 正常请求 | 完整chartData + name | code=0, 6段解读字符串非空 |
+| 4.2 | 缺少positions | {} | code=400, error="缺少命盘数据" |
+| 4.3 | LLM超时 | 模拟超时 | 触发_fallbackReading降级解读 |
+| 4.4 | LLM返回非JSON | 非法响应 | code=0, mainCharacter=原始文本 |
+| 4.5 | LLM返回JSON in markdown | ```json ... ``` | 正确解析JSON内容 |
+| 4.6 | 缓存读取 | 第二次请求同命盘 | 不走云函数,从本地存储读取 |
+
+### TC-05: 支付订阅 (P0)
+
+| # | 用例 | 步骤 | 预期结果 |
+|---|------|------|---------|
+| 5.1 | 未登录跳转支付 | 未登录用户点击订阅 | 引导登录或正常跳转 |
+| 5.2 | 支付loading | 点击"立即开通" | 按钮变为loading状态,不可重复点击 |
+| 5.3 | 支付成功 | 模拟支付成功回调 | role→practitioner, expireAt→+1年 |
+| 5.4 | 支付后推广码 | 支付成功后的checkSession | referralCode非空(6位) |
+| 5.5 | 支付取消 | 用户取消支付 | 停留在当前页,角色不变 |
+| 5.6 | 支付失败 | 模拟支付失败 | 显示"支付失败,请重试" |
+| 5.7 | 功能对比表 | 订阅页内容 | 正确展示免费vs能量师差异 |
+| 5.8 | 价格显示 | 订阅页 | ¥398/年,¥1.09/天正确 |
+
+### TC-06: 分销链路 (P1)
+
+| # | 用例 | 步骤 | 预期结果 |
+|---|------|------|---------|
+| 6.1 | 推广码自动生成 | 支付成功后 | 6位字母+数字唯一码 |
+| 6.2 | 推广码持久化 | 重新登录 | 推广码不变 |
+| 6.3 | 分享卡片携带ref | 能量师分享 | path包含?ref=CODE |
+| 6.4 | 推广链接打开参数 | onLoad(options) | 正确读取ref并缓存 |
+| 6.5 | 注册时绑定上级 | 新用户带ref注册 | invitedBy=上级openid |
+| 6.6 | 上级统计更新 | 新用户注册 | directCount+1 |
+| 6.7 | 关系终身锁定 | 第二次通过他人链接注册 | 不覆盖原有invitedBy |
+| 6.8 | 自邀请不绑定 | 自己扫自己的码 | invitedBy为空 |
+| 6.9 | 一级佣金结算 | 下级付费¥398 | 佣金=¥119.4, status=available |
+| 6.10 | 二级佣金结算 | 下级的下级付费 | 佣金=¥39.8, status=available |
+| 6.11 | 佣金取值精确 | 浮动计算 | 两位小数精确 |
+| 6.12 | 佣金状态流转 | pending→available→completed | 按业务规则流转 |
+| 6.13 | 提现条件验证 | 可提现金额<¥100 | "申请提现"不可点击 |
+| 6.14 | 提现申请提交 | 金额合法 | 记录创建status=pending |
+| 6.15 | 提全额按钮 | 点击"全部提现" | 输入框填充可提现金额 |
+| 6.16 | 超额提现拦截 | 输入>可提现 | 提示"超出可提现金额" |
+
+### TC-07: 用户体系与历史记录 (P1)
+
+| # | 用例 | 步骤 | 预期结果 |
+|---|------|------|---------|
+| 7.1 | 微信登录 | 点击微信登录 | 获取用户信息,创建/查询用户 |
+| 7.2 | 重复登录 | 同一用户再次登录 | 返回isNew=false |
+| 7.3 | 登录后状态持久化 | 关闭重开小程序 | token有效时自动登录 |
+| 7.4 | 会话过期 | token无效 | 自动跳转为未登录状态 |
+| 7.5 | 历史列表显示 | 个人中心页 | 按时间倒序,显示姓名/生日/主性格 |
+| 7.6 | 历史点击跳转 | 点击历史记录 | 跳转到对应chart页 |
+| 7.7 | 免费用户7天限制 | 8天前的记录 | 不显示 |
+| 7.8 | 能量师全部历史 | 所有记录 | 全部显示 |
+| 7.9 | 历史记录超100条 | 生成101+命盘 | 仅保留最近100条 |
+| 7.10 | 订阅状态显示 | 个人中心 | 能量师显示"已开通"+到期日 |
+
+### TC-08: 边界与异常 (P0/P1)
+
+| # | 用例 | 预期结果 |
+|---|------|---------|
+| 8.1 | 年月日全部为空 | 提示填写完整日期 |
+| 8.2 | 年份=1899 | 日期选择器不可选 |
+| 8.3 | 年份=2100 | 不可选(超过当前年份) |
+| 8.4 | 月份=0 | picker限制不可选 |
+| 8.5 | 月份=13 | picker限制不可选 |
+| 8.6 | 日期=0 | picker限制不可选 |
+| 8.7 | 日期=32 | picker限制不可选 |
+| 8.8 | 闰年2/29 | 合法输入,正常计算 |
+| 8.9 | 非闰年2/29 | picker不可选 |
+| 8.10 | 姓名20字符 | 截断处理 |
+| 8.11 | 姓名全空格 | 显示"未知" |
+| 8.12 | 姓名特殊字符 | 正常显示 |
+| 8.13 | 命盘id含特殊字符 | 能正确查找 |
+| 8.14 | 弱网场景(3G模拟) | 云函数超时能有降级UI |
+| 8.15 | 断网场景 | 提示网络错误,不崩溃 |
+| 8.16 | 存储空间满 | 存储失败时的降级 |
+
+### TC-09: 合规检查 (P0)
+
+| # | 检查项 | 通过标准 |
+|---|--------|---------|
+| 9.1 | 首页文案 | 不含"算命、占卜、预测、占星" |
+| 9.2 | AI解读免责声明 | 末尾包含"本解读由AI生成,仅供参考" |
+| 9.3 | 用户协议链接 | 可点击,打开的页面有效 |
+| 9.4 | 隐私政策链接 | 可点击,打开的页面有效 |
+| 9.5 | 不得收集敏感信息 | 无身份证/银行卡输入 |
+| 9.6 | 支付合规 | 微信支付规范无违规文案 |
+| 9.7 | 分销合规 | 两级分销,无团队计酬,无入门费 |
+
+---
+
+## 测试环境要求
+
+| 项目 | 配置 |
+|------|------|
+| 微信基础库 | 3.7.1+ |
+| iOS | iPhone 13/14/15, iOS 16+ |
+| Android | 华为/小米/OPPO, Android 12+ |
+| 微信版本 | 8.0+ |
+| 云开发环境 | test/dev独立环境(非production) |
+| 测试账号 | 至少3个:普通用户A、能量师B、普通用户C(从B邀请注册) |
+
+## 严重等级定义
+
+| 等级 | 定义 | 响应时间 |
+|------|------|---------|
+| S0-Critical | 核心链路阻塞(无法生成命盘/支付/解读) | 立即修复 |
+| S1-Major | 功能严重异常(计算错误/状态错乱/数据丢失) | 24h内 |
+| S2-Minor | 功能可用但体验缺陷(UI错位/文案错误) | 下一迭代 |
+| S3-Trivial | 视觉/文案微调建议 | 积攒修复 |

+ 37 - 0
AGENTS.md

@@ -0,0 +1,37 @@
+# 数字能量学智能体 (Digital Energy Numerology Agent)
+
+**状态:** 新项目,代码仓库为空,待初始化。
+
+## 项目概述
+
+数字能量学智能体 — 基于数字能量学理论的 AI 分析与咨询系统。结合数字能量学知识库与 LLM 能力,提供数字命理分析、号码能量评估、个性化报告生成等服务。
+
+## 仓库结构
+
+```
+num/              # 项目根目录(当前为空)
+├── AGENTS.md     # 本文件
+├── ...           # 待补充
+```
+
+当前为空白项目,尚无代码。
+
+## 已知信息
+
+- **项目名称:** 数字能量学智能体
+- **定位:** 数字能量学 + AI 智能体
+- **技术栈:** 待定
+
+## TODO(项目启动)
+
+- [ ] 确定技术栈与项目结构
+- [ ] 初始化项目框架
+- [ ] 建立数字能量学知识库
+- [ ] 实现核心推理引擎
+- [ ] 构建交互界面
+
+## 注意事项
+
+- 本项目为全新创建,无遗留代码约束
+- 技术选型、架构设计需在初期确定
+- 数字能量学领域知识需梳理为标准化的知识库/规则引擎

+ 6 - 0
admin/env.d.ts

@@ -0,0 +1,6 @@
+/// <reference types="vite/client" />
+declare module '*.vue' {
+  import type { DefineComponent } from 'vue'
+  const component: DefineComponent<{}, {}, any>
+  export default component
+}

+ 12 - 0
admin/index.html

@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+  <meta charset="UTF-8" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+  <title>数字能量学 - 管理后台</title>
+</head>
+<body>
+  <div id="app"></div>
+  <script type="module" src="/src/main.ts"></script>
+</body>
+</html>

+ 2491 - 0
admin/package-lock.json

@@ -0,0 +1,2491 @@
+{
+  "name": "num-admin",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "num-admin",
+      "version": "1.0.0",
+      "dependencies": {
+        "@element-plus/icons-vue": "^2.3.0",
+        "axios": "^1.6.0",
+        "echarts": "^5.4.0",
+        "element-plus": "^2.4.0",
+        "pinia": "^2.1.0",
+        "vue": "^3.4.0",
+        "vue-echarts": "^6.6.0",
+        "vue-router": "^4.2.0"
+      },
+      "devDependencies": {
+        "@vitejs/plugin-vue": "^5.0.0",
+        "sass": "^1.69.0",
+        "typescript": "^5.3.0",
+        "vite": "^5.0.0",
+        "vue-tsc": "^2.2.12"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+      "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+      "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz",
+      "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.29.7"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz",
+      "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.29.7",
+        "@babel/helper-validator-identifier": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@ctrl/tinycolor": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz",
+      "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/@element-plus/icons-vue": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmmirror.com/@element-plus/icons-vue/-/icons-vue-2.3.2.tgz",
+      "integrity": "sha512-OzIuTaIfC8QXEPmJvB4Y4kw34rSXdCJzxcD1kFStBvr8bK6X1zQAYDo0CNMjojnfTqRQCJ0I7prlErcoRiET2A==",
+      "license": "MIT",
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+      "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+      "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+      "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+      "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+      "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+      "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+      "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+      "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+      "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+      "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+      "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+      "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+      "cpu": [
+        "mips64el"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+      "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+      "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+      "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+      "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+      "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+      "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+      "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+      "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+      "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@floating-ui/core": {
+      "version": "1.7.5",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/core/-/core-1.7.5.tgz",
+      "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "node_modules/@floating-ui/dom": {
+      "version": "1.7.6",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/dom/-/dom-1.7.6.tgz",
+      "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@floating-ui/core": "^1.7.5",
+        "@floating-ui/utils": "^0.2.11"
+      }
+    },
+    "node_modules/@floating-ui/utils": {
+      "version": "0.2.11",
+      "resolved": "https://registry.npmmirror.com/@floating-ui/utils/-/utils-0.2.11.tgz",
+      "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
+      "license": "MIT"
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+      "license": "MIT"
+    },
+    "node_modules/@parcel/watcher": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher/-/watcher-2.5.6.tgz",
+      "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "detect-libc": "^2.0.3",
+        "is-glob": "^4.0.3",
+        "node-addon-api": "^7.0.0",
+        "picomatch": "^4.0.3"
+      },
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher-android-arm64": "2.5.6",
+        "@parcel/watcher-darwin-arm64": "2.5.6",
+        "@parcel/watcher-darwin-x64": "2.5.6",
+        "@parcel/watcher-freebsd-x64": "2.5.6",
+        "@parcel/watcher-linux-arm-glibc": "2.5.6",
+        "@parcel/watcher-linux-arm-musl": "2.5.6",
+        "@parcel/watcher-linux-arm64-glibc": "2.5.6",
+        "@parcel/watcher-linux-arm64-musl": "2.5.6",
+        "@parcel/watcher-linux-x64-glibc": "2.5.6",
+        "@parcel/watcher-linux-x64-musl": "2.5.6",
+        "@parcel/watcher-win32-arm64": "2.5.6",
+        "@parcel/watcher-win32-ia32": "2.5.6",
+        "@parcel/watcher-win32-x64": "2.5.6"
+      }
+    },
+    "node_modules/@parcel/watcher-android-arm64": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz",
+      "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-darwin-arm64": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz",
+      "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-darwin-x64": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz",
+      "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-freebsd-x64": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz",
+      "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm-glibc": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz",
+      "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm-musl": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz",
+      "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm64-glibc": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz",
+      "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-arm64-musl": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz",
+      "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-x64-glibc": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz",
+      "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-linux-x64-musl": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz",
+      "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-arm64": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz",
+      "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-ia32": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz",
+      "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@parcel/watcher-win32-x64": {
+      "version": "2.5.6",
+      "resolved": "https://registry.npmmirror.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz",
+      "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">= 10.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/parcel"
+      }
+    },
+    "node_modules/@popperjs/core": {
+      "name": "@sxzz/popperjs-es",
+      "version": "2.11.8",
+      "resolved": "https://registry.npmmirror.com/@sxzz/popperjs-es/-/popperjs-es-2.11.8.tgz",
+      "integrity": "sha512-wOwESXvvED3S8xBmcPWHs2dUuzrE4XiZeFu7e1hROIJkm02a49N120pmOXxY33sBb6hArItm5W5tcg1cBtV+HQ==",
+      "license": "MIT",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/popperjs"
+      }
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz",
+      "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz",
+      "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz",
+      "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz",
+      "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz",
+      "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz",
+      "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz",
+      "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz",
+      "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz",
+      "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz",
+      "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz",
+      "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz",
+      "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==",
+      "cpu": [
+        "loong64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz",
+      "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz",
+      "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==",
+      "cpu": [
+        "ppc64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz",
+      "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz",
+      "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz",
+      "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz",
+      "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz",
+      "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-openbsd-x64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz",
+      "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-openharmony-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz",
+      "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openharmony"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz",
+      "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz",
+      "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==",
+      "cpu": [
+        "ia32"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz",
+      "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz",
+      "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/lodash": {
+      "version": "4.17.24",
+      "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.24.tgz",
+      "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
+      "license": "MIT"
+    },
+    "node_modules/@types/lodash-es": {
+      "version": "4.17.12",
+      "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz",
+      "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/lodash": "*"
+      }
+    },
+    "node_modules/@types/web-bluetooth": {
+      "version": "0.0.21",
+      "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz",
+      "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==",
+      "license": "MIT"
+    },
+    "node_modules/@vitejs/plugin-vue": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+      "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^5.0.0 || ^6.0.0",
+        "vue": "^3.2.25"
+      }
+    },
+    "node_modules/@volar/language-core": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz",
+      "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/source-map": "2.4.15"
+      }
+    },
+    "node_modules/@volar/source-map": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz",
+      "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@volar/typescript": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz",
+      "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/language-core": "2.4.15",
+        "path-browserify": "^1.0.1",
+        "vscode-uri": "^3.0.8"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
+      "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/shared": "3.5.34",
+        "entities": "^7.0.1",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
+      "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz",
+      "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/compiler-core": "3.5.34",
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/compiler-ssr": "3.5.34",
+        "@vue/shared": "3.5.34",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.21",
+        "postcss": "^8.5.14",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
+      "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/compiler-vue2": {
+      "version": "2.7.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
+      "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "de-indent": "^1.0.2",
+        "he": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.6.4",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/language-core": {
+      "version": "2.2.12",
+      "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz",
+      "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/language-core": "2.4.15",
+        "@vue/compiler-dom": "^3.5.0",
+        "@vue/compiler-vue2": "^2.7.16",
+        "@vue/shared": "^3.5.0",
+        "alien-signals": "^1.0.3",
+        "minimatch": "^9.0.3",
+        "muggle-string": "^0.4.1",
+        "path-browserify": "^1.0.1"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.34.tgz",
+      "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.34.tgz",
+      "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz",
+      "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.34",
+        "@vue/runtime-core": "3.5.34",
+        "@vue/shared": "3.5.34",
+        "csstype": "^3.2.3"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.34.tgz",
+      "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.34",
+        "@vue/shared": "3.5.34"
+      },
+      "peerDependencies": {
+        "vue": "3.5.34"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "license": "MIT"
+    },
+    "node_modules/@vueuse/core": {
+      "version": "14.3.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.3.0.tgz",
+      "integrity": "sha512-aHfz47g0ZhMtTVHmIzMVpJy8ePhhOy68GY5bv110+5DVtZ+W7BsOx+m61UNQqfrWyPztIHIanWa3E2tib3NFIw==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/web-bluetooth": "^0.0.21",
+        "@vueuse/metadata": "14.3.0",
+        "@vueuse/shared": "14.3.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "vue": "^3.5.0"
+      }
+    },
+    "node_modules/@vueuse/metadata": {
+      "version": "14.3.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.3.0.tgz",
+      "integrity": "sha512-BwxmbAzwAVF50+MW57GXOUEV61nFBGnlBvrTqj49PqWJu3uw7hdu72ztXeZ33RdZtDY6kO+bfCAE1PCn88Tktw==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/shared": {
+      "version": "14.3.0",
+      "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.3.0.tgz",
+      "integrity": "sha512-bZpge9eSXwa4ToSiqJ7j6KRwhAsneMFoSz3LMWKQDkqimm3D/tbFlrklrs/IOqC8tEcYmXQZJ6N0UrjhBirVCg==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "vue": "^3.5.0"
+      }
+    },
+    "node_modules/agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/alien-signals": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz",
+      "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/async-validator": {
+      "version": "4.2.5",
+      "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-4.2.5.tgz",
+      "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==",
+      "license": "MIT"
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
+    "node_modules/axios": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.16.1.tgz",
+      "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.16.0",
+        "form-data": "^4.0.5",
+        "https-proxy-agent": "^5.0.1",
+        "proxy-from-env": "^2.1.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/brace-expansion": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.1.1.tgz",
+      "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz",
+      "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "readdirp": "^5.0.0"
+      },
+      "engines": {
+        "node": ">= 20.19.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
+      "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+      "license": "MIT"
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.20",
+      "resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.20.tgz",
+      "integrity": "sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==",
+      "license": "MIT"
+    },
+    "node_modules/de-indent": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz",
+      "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "4.4.3",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
+      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/detect-libc": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz",
+      "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "optional": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/echarts": {
+      "version": "5.6.0",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
+      "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "2.3.0",
+        "zrender": "5.6.1"
+      }
+    },
+    "node_modules/element-plus": {
+      "version": "2.14.0",
+      "resolved": "https://registry.npmmirror.com/element-plus/-/element-plus-2.14.0.tgz",
+      "integrity": "sha512-POgH+TtoreaEKWqYYAVQyE6i8rQMEFqAEublyF29dBA5yASWPLKY6EzfeqBTr2Uv26mPss4vSrMrNPyaK7LX5w==",
+      "license": "MIT",
+      "dependencies": {
+        "@ctrl/tinycolor": "^4.2.0",
+        "@element-plus/icons-vue": "^2.3.2",
+        "@floating-ui/dom": "^1.0.1",
+        "@popperjs/core": "npm:@sxzz/popperjs-es@^2.11.8",
+        "@types/lodash": "^4.17.24",
+        "@types/lodash-es": "^4.17.12",
+        "@vueuse/core": "14.3.0",
+        "async-validator": "^4.2.5",
+        "dayjs": "^1.11.20",
+        "lodash": "^4.18.1",
+        "lodash-es": "^4.18.1",
+        "lodash-unified": "^1.0.3",
+        "memoize-one": "^6.0.0",
+        "normalize-wheel-es": "^1.2.0",
+        "vue-component-type-helpers": "^3.2.8"
+      },
+      "peerDependencies": {
+        "vue": "^3.3.7"
+      }
+    },
+    "node_modules/entities": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz",
+      "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+      "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.21.5",
+      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.21.5.tgz",
+      "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.21.5",
+        "@esbuild/android-arm": "0.21.5",
+        "@esbuild/android-arm64": "0.21.5",
+        "@esbuild/android-x64": "0.21.5",
+        "@esbuild/darwin-arm64": "0.21.5",
+        "@esbuild/darwin-x64": "0.21.5",
+        "@esbuild/freebsd-arm64": "0.21.5",
+        "@esbuild/freebsd-x64": "0.21.5",
+        "@esbuild/linux-arm": "0.21.5",
+        "@esbuild/linux-arm64": "0.21.5",
+        "@esbuild/linux-ia32": "0.21.5",
+        "@esbuild/linux-loong64": "0.21.5",
+        "@esbuild/linux-mips64el": "0.21.5",
+        "@esbuild/linux-ppc64": "0.21.5",
+        "@esbuild/linux-riscv64": "0.21.5",
+        "@esbuild/linux-s390x": "0.21.5",
+        "@esbuild/linux-x64": "0.21.5",
+        "@esbuild/netbsd-x64": "0.21.5",
+        "@esbuild/openbsd-x64": "0.21.5",
+        "@esbuild/sunos-x64": "0.21.5",
+        "@esbuild/win32-arm64": "0.21.5",
+        "@esbuild/win32-ia32": "0.21.5",
+        "@esbuild/win32-x64": "0.21.5"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "license": "MIT"
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.16.0",
+      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.16.0.tgz",
+      "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz",
+      "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "license": "MIT",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.3.tgz",
+      "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "he": "bin/he"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+      "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+      "license": "MIT",
+      "dependencies": {
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/immutable": {
+      "version": "5.1.5",
+      "resolved": "https://registry.npmmirror.com/immutable/-/immutable-5.1.5.tgz",
+      "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.18.1",
+      "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.18.1.tgz",
+      "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+      "license": "MIT"
+    },
+    "node_modules/lodash-es": {
+      "version": "4.18.1",
+      "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz",
+      "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
+      "license": "MIT"
+    },
+    "node_modules/lodash-unified": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/lodash-unified/-/lodash-unified-1.0.3.tgz",
+      "integrity": "sha512-WK9qSozxXOD7ZJQlpSqOT+om2ZfcT4yO+03FuzAHD0wF6S0l0090LRPDx3vhTTLZ8cFKpBn+IOcVXK6qOcIlfQ==",
+      "license": "MIT",
+      "peerDependencies": {
+        "@types/lodash-es": "*",
+        "lodash": "*",
+        "lodash-es": "*"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.21",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
+      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/memoize-one": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmmirror.com/memoize-one/-/memoize-one-6.0.0.tgz",
+      "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
+      "license": "MIT"
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "9.0.9",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz",
+      "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "license": "MIT"
+    },
+    "node_modules/muggle-string": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz",
+      "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.12",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz",
+      "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/node-addon-api": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/node-addon-api/-/node-addon-api-7.1.1.tgz",
+      "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/normalize-wheel-es": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/normalize-wheel-es/-/normalize-wheel-es-1.2.0.tgz",
+      "integrity": "sha512-Wj7+EJQ8mSuXr2iWfnujrimU35R2W4FAErEyTmJoJ7ucwTn2hOUSsRehMb5RSYkxXGTM7Y9QpvPmp++w5ftoJw==",
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/path-browserify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
+      "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/picomatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
+      "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pinia": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz",
+      "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.3",
+        "vue-demi": "^0.14.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.4.4",
+        "vue": "^2.7.0 || ^3.5.11"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.15",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz",
+      "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.12",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/proxy-from-env": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+      "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz",
+      "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 20.19.0"
+      },
+      "funding": {
+        "type": "individual",
+        "url": "https://paulmillr.com/funding/"
+      }
+    },
+    "node_modules/resize-detector": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/resize-detector/-/resize-detector-0.3.0.tgz",
+      "integrity": "sha512-R/tCuvuOHQ8o2boRP6vgx8hXCCy87H1eY9V5imBYeVNyNVpuL9ciReSccLj2gDcax9+2weXy3bc8Vv+NRXeEvQ==",
+      "license": "MIT"
+    },
+    "node_modules/rollup": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.4.tgz",
+      "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "1.0.8"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.60.4",
+        "@rollup/rollup-android-arm64": "4.60.4",
+        "@rollup/rollup-darwin-arm64": "4.60.4",
+        "@rollup/rollup-darwin-x64": "4.60.4",
+        "@rollup/rollup-freebsd-arm64": "4.60.4",
+        "@rollup/rollup-freebsd-x64": "4.60.4",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.60.4",
+        "@rollup/rollup-linux-arm-musleabihf": "4.60.4",
+        "@rollup/rollup-linux-arm64-gnu": "4.60.4",
+        "@rollup/rollup-linux-arm64-musl": "4.60.4",
+        "@rollup/rollup-linux-loong64-gnu": "4.60.4",
+        "@rollup/rollup-linux-loong64-musl": "4.60.4",
+        "@rollup/rollup-linux-ppc64-gnu": "4.60.4",
+        "@rollup/rollup-linux-ppc64-musl": "4.60.4",
+        "@rollup/rollup-linux-riscv64-gnu": "4.60.4",
+        "@rollup/rollup-linux-riscv64-musl": "4.60.4",
+        "@rollup/rollup-linux-s390x-gnu": "4.60.4",
+        "@rollup/rollup-linux-x64-gnu": "4.60.4",
+        "@rollup/rollup-linux-x64-musl": "4.60.4",
+        "@rollup/rollup-openbsd-x64": "4.60.4",
+        "@rollup/rollup-openharmony-arm64": "4.60.4",
+        "@rollup/rollup-win32-arm64-msvc": "4.60.4",
+        "@rollup/rollup-win32-ia32-msvc": "4.60.4",
+        "@rollup/rollup-win32-x64-gnu": "4.60.4",
+        "@rollup/rollup-win32-x64-msvc": "4.60.4",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/sass": {
+      "version": "1.100.0",
+      "resolved": "https://registry.npmmirror.com/sass/-/sass-1.100.0.tgz",
+      "integrity": "sha512-B5j0rYMlinhhOo9tjQebMVVn0TfyXAF+wB3b2ggZUuJ/is/Y+7+JGjirAMxHZ9Z3hIP98NPfamlAkBHa1lAaXQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "chokidar": "^5.0.0",
+        "immutable": "^5.1.5",
+        "source-map-js": ">=0.6.2 <2.0.0"
+      },
+      "bin": {
+        "sass": "sass.js"
+      },
+      "engines": {
+        "node": ">=20.19.0"
+      },
+      "optionalDependencies": {
+        "@parcel/watcher": "^2.4.1"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==",
+      "license": "0BSD"
+    },
+    "node_modules/typescript": {
+      "version": "5.9.3",
+      "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "devOptional": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/vite": {
+      "version": "5.4.21",
+      "resolved": "https://registry.npmmirror.com/vite/-/vite-5.4.21.tgz",
+      "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "esbuild": "^0.21.3",
+        "postcss": "^8.4.43",
+        "rollup": "^4.20.0"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^18.0.0 || >=20.0.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "sass-embedded": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.4.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vscode-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz",
+      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/vue": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.34.tgz",
+      "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/compiler-sfc": "3.5.34",
+        "@vue/runtime-dom": "3.5.34",
+        "@vue/server-renderer": "3.5.34",
+        "@vue/shared": "3.5.34"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-component-type-helpers": {
+      "version": "3.3.2",
+      "resolved": "https://registry.npmmirror.com/vue-component-type-helpers/-/vue-component-type-helpers-3.3.2.tgz",
+      "integrity": "sha512-l4Z2Y34m7nFMlx8vrslJaVtXxUpzgDMSESC7TakG/c5kwjYT/do+E0NcT2/vWDzaoIhsShg/2OKwX7Q4nbzC0g==",
+      "license": "MIT"
+    },
+    "node_modules/vue-demi": {
+      "version": "0.14.10",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
+      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-echarts": {
+      "version": "6.7.3",
+      "resolved": "https://registry.npmmirror.com/vue-echarts/-/vue-echarts-6.7.3.tgz",
+      "integrity": "sha512-vXLKpALFjbPphW9IfQPOVfb1KjGZ/f8qa/FZHi9lZIWzAnQC1DgnmEK3pJgEkyo6EP7UnX6Bv/V3Ke7p+qCNXA==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "dependencies": {
+        "resize-detector": "^0.3.0",
+        "vue-demi": "^0.13.11"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.5",
+        "@vue/runtime-core": "^3.0.0",
+        "echarts": "^5.4.1",
+        "vue": "^2.6.12 || ^3.1.1"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        },
+        "@vue/runtime-core": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-echarts/node_modules/vue-demi": {
+      "version": "0.13.11",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.13.11.tgz",
+      "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.6.4",
+      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.6.4.tgz",
+      "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "vue": "^3.5.0"
+      }
+    },
+    "node_modules/vue-tsc": {
+      "version": "2.2.12",
+      "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz",
+      "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/typescript": "2.4.15",
+        "@vue/language-core": "2.2.12"
+      },
+      "bin": {
+        "vue-tsc": "bin/vue-tsc.js"
+      },
+      "peerDependencies": {
+        "typescript": ">=5.0.0"
+      }
+    },
+    "node_modules/zrender": {
+      "version": "5.6.1",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",
+      "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "tslib": "2.3.0"
+      }
+    }
+  }
+}

+ 27 - 0
admin/package.json

@@ -0,0 +1,27 @@
+{
+  "name": "num-admin",
+  "version": "1.0.0",
+  "private": true,
+  "scripts": {
+    "dev": "vite",
+    "build": "vue-tsc --noEmit && vite build",
+    "preview": "vite preview"
+  },
+  "dependencies": {
+    "@element-plus/icons-vue": "^2.3.0",
+    "axios": "^1.6.0",
+    "echarts": "^5.4.0",
+    "element-plus": "^2.4.0",
+    "pinia": "^2.1.0",
+    "vue": "^3.4.0",
+    "vue-echarts": "^6.6.0",
+    "vue-router": "^4.2.0"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "^5.0.0",
+    "sass": "^1.69.0",
+    "typescript": "^5.3.0",
+    "vite": "^5.0.0",
+    "vue-tsc": "^2.2.12"
+  }
+}

+ 3 - 0
admin/src/App.vue

@@ -0,0 +1,3 @@
+<template>
+  <router-view />
+</template>

+ 88 - 0
admin/src/layout/index.vue

@@ -0,0 +1,88 @@
+<template>
+  <el-container class="layout-container">
+    <el-aside :width="isCollapse ? '64px' : '220px'" class="layout-aside">
+      <div class="logo">
+        <span v-if="!isCollapse">数字能量学</span>
+        <span v-else>⚡</span>
+      </div>
+      <el-menu
+        :default-active="route.path"
+        :collapse="isCollapse"
+        background-color="#1F2937"
+        text-color="#fff"
+        active-text-color="#3B82F6"
+        router
+      >
+        <el-menu-item index="/dashboard">
+          <el-icon><DataAnalysis /></el-icon>
+          <span>仪表盘</span>
+        </el-menu-item>
+        <el-menu-item index="/users">
+          <el-icon><User /></el-icon>
+          <span>用户管理</span>
+        </el-menu-item>
+        <el-menu-item index="/orders">
+          <el-icon><List /></el-icon>
+          <span>订单管理</span>
+        </el-menu-item>
+        <el-menu-item index="/commissions">
+          <el-icon><Money /></el-icon>
+          <span>佣金管理</span>
+        </el-menu-item>
+        <el-menu-item index="/charts">
+          <el-icon><PieChart /></el-icon>
+          <span>分析记录</span>
+        </el-menu-item>
+      </el-menu>
+    </el-aside>
+    <el-container>
+      <el-header class="layout-header">
+        <el-icon class="collapse-btn" @click="isCollapse = !isCollapse">
+          <Fold v-if="!isCollapse" /><Expand v-else />
+        </el-icon>
+        <div class="header-right">
+          <span class="username">{{ auth.username }}</span>
+          <el-button type="danger" size="small" @click="handleLogout">退出</el-button>
+        </div>
+      </el-header>
+      <el-main class="layout-main">
+        <router-view />
+      </el-main>
+    </el-container>
+  </el-container>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { useRoute, useRouter } from 'vue-router'
+import { useAuthStore } from '@/stores/auth'
+
+const route = useRoute()
+const router = useRouter()
+const auth = useAuthStore()
+const isCollapse = ref(false)
+
+function handleLogout() {
+  auth.logout()
+  router.push('/login')
+}
+</script>
+
+<style scoped lang="scss">
+.layout-container { height: 100vh; }
+.layout-aside { background: #1F2937; transition: width 0.3s; overflow: hidden; }
+.logo {
+  height: 60px; display: flex; align-items: center; justify-content: center;
+  color: #fff; font-size: 18px; font-weight: 700;
+  border-bottom: 1px solid rgba(255,255,255,0.1);
+}
+.layout-header {
+  background: #fff; display: flex; align-items: center;
+  justify-content: space-between; border-bottom: 1px solid #E5E7EB;
+  padding: 0 20px;
+}
+.collapse-btn { font-size: 20px; cursor: pointer; }
+.header-right { display: flex; align-items: center; gap: 16px; }
+.username { font-size: 14px; color: #374151; }
+.layout-main { background: #F3F4F6; padding: 20px; overflow-y: auto; }
+</style>

+ 17 - 0
admin/src/main.ts

@@ -0,0 +1,17 @@
+import { createApp } from 'vue'
+import { createPinia } from 'pinia'
+import ElementPlus from 'element-plus'
+import 'element-plus/dist/index.css'
+import * as ElementPlusIconsVue from '@element-plus/icons-vue'
+import App from './App.vue'
+import router from './router'
+import './styles/index.scss'
+
+const app = createApp(App)
+app.use(createPinia())
+app.use(router)
+app.use(ElementPlus)
+for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
+  app.component(key, component)
+}
+app.mount('#app')

+ 32 - 0
admin/src/router/index.ts

@@ -0,0 +1,32 @@
+import { createRouter, createWebHistory } from 'vue-router'
+import { useAuthStore } from '@/stores/auth'
+
+const router = createRouter({
+  history: createWebHistory(),
+  routes: [
+    { path: '/login', name: 'Login', component: () => import('@/views/login/index.vue') },
+    {
+      path: '/',
+      component: () => import('@/layout/index.vue'),
+      redirect: '/dashboard',
+      children: [
+        { path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index.vue') },
+        { path: 'users', name: 'Users', component: () => import('@/views/users/index.vue') },
+        { path: 'orders', name: 'Orders', component: () => import('@/views/orders/index.vue') },
+        { path: 'commissions', name: 'Commissions', component: () => import('@/views/commissions/index.vue') },
+        { path: 'charts', name: 'Charts', component: () => import('@/views/charts/index.vue') }
+      ]
+    }
+  ]
+})
+
+router.beforeEach((to, from, next) => {
+  const auth = useAuthStore()
+  if (to.path !== '/login' && !auth.isLoggedIn) {
+    next('/login')
+  } else {
+    next()
+  }
+})
+
+export default router

+ 30 - 0
admin/src/stores/auth.ts

@@ -0,0 +1,30 @@
+import { defineStore } from 'pinia'
+import request from '@/utils/request'
+
+interface AuthState {
+  token: string
+  username: string
+}
+
+export const useAuthStore = defineStore('auth', {
+  state: (): AuthState => ({
+    token: localStorage.getItem('admin_token') || '',
+    username: ''
+  }),
+  getters: {
+    isLoggedIn: (state) => !!state.token
+  },
+  actions: {
+    async login(username: string, password: string) {
+      const data: any = await request.post('/auth/login', { username, password })
+      this.token = data.token
+      this.username = username
+      localStorage.setItem('admin_token', data.token)
+    },
+    logout() {
+      this.token = ''
+      this.username = ''
+      localStorage.removeItem('admin_token')
+    }
+  }
+})

+ 17 - 0
admin/src/styles/index.scss

@@ -0,0 +1,17 @@
+* { margin: 0; padding: 0; box-sizing: border-box; }
+html, body, #app { height: 100%; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; }
+
+:root {
+  --el-color-primary: #3B82F6;
+  --el-color-success: #10B981;
+  --el-color-warning: #F59E0B;
+  --el-color-danger: #EF4444;
+}
+
+.el-card { border-radius: 8px; }
+
+.el-table th { background: #F9FAFB !important; color: #374151; font-weight: 600; }
+
+.el-menu { border-right: none; }
+.el-menu-item { font-size: 14px; }
+.el-menu-item.is-active { background-color: rgba(59, 130, 246, 0.1) !important; }

+ 38 - 0
admin/src/utils/request.ts

@@ -0,0 +1,38 @@
+import axios from 'axios'
+import { ElMessage } from 'element-plus'
+import router from '@/router'
+
+const request = axios.create({
+  baseURL: '/api',
+  timeout: 30000,
+  headers: { 'Content-Type': 'application/json' }
+})
+
+request.interceptors.request.use(config => {
+  const token = localStorage.getItem('admin_token')
+  if (token) {
+    config.headers.Authorization = `Bearer ${token}`
+  }
+  return config
+})
+
+request.interceptors.response.use(
+  response => {
+    const res = response.data
+    if (res.code !== 0) {
+      ElMessage.error(res.message || '请求失败')
+      if (res.code === 1001) {
+        localStorage.removeItem('admin_token')
+        router.push('/login')
+      }
+      return Promise.reject(new Error(res.message))
+    }
+    return res.data
+  },
+  error => {
+    ElMessage.error('网络错误')
+    return Promise.reject(error)
+  }
+)
+
+export default request

+ 84 - 0
admin/src/views/charts/index.vue

@@ -0,0 +1,84 @@
+<template>
+  <div class="charts-page">
+    <el-card shadow="hover">
+      <template #header><span>分析记录</span></template>
+      <el-table :data="records" v-loading="loading" stripe>
+        <el-table-column prop="id" label="ID" width="60" />
+        <el-table-column prop="userId" label="用户ID" width="80" />
+        <el-table-column prop="phoneNumber" label="手机号" width="130" />
+        <el-table-column prop="name" label="姓名" />
+        <el-table-column label="已解读" width="80">
+          <template #default="{ row }">
+            <el-tag :type="row.difyResponse ? 'success' : 'info'" size="small">
+              {{ row.difyResponse ? '是' : '否' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createdAt" label="创建时间" width="110" />
+        <el-table-column label="操作" width="100">
+          <template #default="{ row }">
+            <el-button size="small" type="primary" @click="viewDetail(row)">查看</el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination-wrap">
+        <el-pagination background layout="total, prev, pager, next" :total="records.length" :page-size="20" />
+      </div>
+    </el-card>
+
+    <!-- Detail dialog -->
+    <el-dialog v-model="dialogVisible" title="分析详情" width="600px">
+      <div v-if="currentRecord">
+        <el-descriptions :column="2" border>
+          <el-descriptions-item label="手机号">{{ currentRecord.phoneNumber }}</el-descriptions-item>
+          <el-descriptions-item label="姓名">{{ currentRecord.name || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="生日">{{ currentRecord.birthday || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="创建时间">{{ currentRecord.createdAt }}</el-descriptions-item>
+        </el-descriptions>
+        <div v-if="currentRecord.chartData" class="chart-json">
+          <h4>图表数据</h4>
+          <pre>{{ JSON.stringify(JSON.parse(currentRecord.chartData), null, 2) }}</pre>
+        </div>
+        <div v-if="currentRecord.difyResponse" class="dify-response">
+          <h4>AI 解读</h4>
+          <p>{{ currentRecord.difyResponse }}</p>
+        </div>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import request from '@/utils/request'
+
+const loading = ref(false)
+const records = ref<any[]>([])
+const dialogVisible = ref(false)
+const currentRecord = ref<any>(null)
+
+async function loadRecords() {
+  loading.value = true
+  try {
+    records.value = await request.post('/admin/charts', {}) as any
+  } finally {
+    loading.value = false
+  }
+}
+
+function viewDetail(record: any) {
+  currentRecord.value = record
+  dialogVisible.value = true
+}
+
+loadRecords()
+</script>
+
+<style scoped lang="scss">
+.pagination-wrap { margin-top: 16px; display: flex; justify-content: flex-end; }
+.chart-json, .dify-response {
+  margin-top: 16px;
+  pre { background: #F3F4F6; padding: 12px; border-radius: 8px; overflow-x: auto; }
+  p { line-height: 1.8; color: #374151; }
+}
+</style>

+ 99 - 0
admin/src/views/commissions/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div class="commissions-page">
+    <el-row :gutter="20" class="summary-row">
+      <el-col :span="8">
+        <el-card shadow="hover">
+          <div class="summary-card">
+            <div class="summary-label">已结算佣金</div>
+            <div class="summary-value success">¥{{ settledTotal }}</div>
+          </div>
+        </el-card>
+      </el-col>
+      <el-col :span="8">
+        <el-card shadow="hover">
+          <div class="summary-card">
+            <div class="summary-label">待结算佣金</div>
+            <div class="summary-value warning">¥{{ pendingTotal }}</div>
+          </div>
+        </el-card>
+      </el-col>
+      <el-col :span="8">
+        <el-card shadow="hover">
+          <div class="summary-card">
+            <div class="summary-label">总佣金</div>
+            <div class="summary-value">¥{{ grandTotal }}</div>
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <el-card shadow="hover">
+      <template #header><span>佣金明细</span></template>
+      <el-table :data="commissions" v-loading="loading" stripe>
+        <el-table-column prop="id" label="ID" width="60" />
+        <el-table-column prop="orderId" label="订单ID" width="80" />
+        <el-table-column prop="fromUserId" label="来源用户" width="100" />
+        <el-table-column prop="toUserId" label="获得用户" width="100" />
+        <el-table-column label="级别" width="80">
+          <template #default="{ row }">L{{ row.level }}</template>
+        </el-table-column>
+        <el-table-column label="金额" width="100">
+          <template #default="{ row }">¥{{ (row.amount / 100).toFixed(2) }}</template>
+        </el-table-column>
+        <el-table-column label="状态" width="100">
+          <template #default="{ row }">
+            <el-tag :type="row.status === 'settled' ? 'success' : 'info'">
+              {{ row.status === 'settled' ? '已结算' : '待结算' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createdAt" label="时间" width="110" />
+      </el-table>
+      <div class="pagination-wrap">
+        <el-pagination background layout="total, prev, pager, next" :total="commissions.length" :page-size="20" />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+import request from '@/utils/request'
+
+const loading = ref(false)
+const commissions = ref<any[]>([])
+
+const settledTotal = computed(() => {
+  const total = commissions.value.filter(c => c.status === 'settled').reduce((s, c) => s + c.amount, 0)
+  return (total / 100).toFixed(2)
+})
+const pendingTotal = computed(() => {
+  const total = commissions.value.filter(c => c.status === 'pending').reduce((s, c) => s + c.amount, 0)
+  return (total / 100).toFixed(2)
+})
+const grandTotal = computed(() => {
+  const total = commissions.value.reduce((s, c) => s + c.amount, 0)
+  return (total / 100).toFixed(2)
+})
+
+async function loadCommissions() {
+  loading.value = true
+  try {
+    commissions.value = await request.post('/admin/commissions', {}) as any
+  } finally {
+    loading.value = false
+  }
+}
+
+loadCommissions()
+</script>
+
+<style scoped lang="scss">
+.summary-row { margin-bottom: 20px; }
+.summary-card { text-align: center; }
+.summary-label { font-size: 14px; color: #6B7280; margin-bottom: 8px; }
+.summary-value { font-size: 28px; font-weight: 700; color: #1F2937; }
+.summary-value.success { color: #10B981; }
+.summary-value.warning { color: #F59E0B; }
+.pagination-wrap { margin-top: 16px; display: flex; justify-content: flex-end; }
+</style>

+ 108 - 0
admin/src/views/dashboard/index.vue

@@ -0,0 +1,108 @@
+<template>
+  <div class="dashboard">
+    <!-- Stats cards -->
+    <el-row :gutter="20" class="stats-row">
+      <el-col :span="6" v-for="stat in stats" :key="stat.label">
+        <el-card shadow="hover" class="stat-card">
+          <div class="stat-value">{{ stat.value }}</div>
+          <div class="stat-label">{{ stat.label }}</div>
+          <div class="stat-change" :class="stat.up ? 'up' : 'down'">
+            {{ stat.change }}
+          </div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!-- Charts -->
+    <el-row :gutter="20" class="chart-row">
+      <el-col :span="14">
+        <el-card shadow="hover">
+          <template #header><span>月新增用户</span></template>
+          <div ref="lineChartRef" style="height: 300px"></div>
+        </el-card>
+      </el-col>
+      <el-col :span="10">
+        <el-card shadow="hover">
+          <template #header><span>订单状态分布</span></template>
+          <div ref="pieChartRef" style="height: 300px"></div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <!-- Recent orders -->
+    <el-card shadow="hover" class="recent-orders">
+      <template #header><span>最近订单</span></template>
+      <el-table :data="recentOrders" stripe style="width: 100%">
+        <el-table-column prop="outTradeNo" label="订单号" width="200" />
+        <el-table-column prop="totalFee" label="金额(元)" width="100">
+          <template #default="{ row }">{{ (row.totalFee / 100).toFixed(2) }}</template>
+        </el-table-column>
+        <el-table-column prop="status" label="状态" width="100">
+          <template #default="{ row }">
+            <el-tag :type="row.status === 'paid' ? 'success' : 'warning'">
+              {{ row.status === 'paid' ? '已支付' : '待支付' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createdAt" label="创建时间" />
+      </el-table>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted } from 'vue'
+import * as echarts from 'echarts'
+
+const stats = ref([
+  { label: '总用户数', value: '128', change: '+12%', up: true },
+  { label: '订单总数', value: '86', change: '+8%', up: true },
+  { label: '总收入', value: '¥28,640', change: '+15%', up: true },
+  { label: 'VIP 用户', value: '64', change: '+5%', up: true }
+])
+
+const recentOrders = ref([
+  { outTradeNo: '20260526001', totalFee: 39800, status: 'paid', createdAt: '2026-05-26' },
+  { outTradeNo: '20260526002', totalFee: 39800, status: 'paid', createdAt: '2026-05-25' },
+  { outTradeNo: '20260526003', totalFee: 39800, status: 'pending', createdAt: '2026-05-25' }
+])
+
+const lineChartRef = ref()
+const pieChartRef = ref()
+
+onMounted(() => {
+  if (lineChartRef.value) {
+    const chart = echarts.init(lineChartRef.value)
+    chart.setOption({
+      xAxis: { type: 'category', data: ['1月','2月','3月','4月','5月','6月'] },
+      yAxis: { type: 'value' },
+      series: [{ data: [18, 25, 30, 42, 55, 48], type: 'line', smooth: true, areaStyle: {} }]
+    })
+  }
+  if (pieChartRef.value) {
+    const chart = echarts.init(pieChartRef.value)
+    chart.setOption({
+      series: [{
+        type: 'pie',
+        data: [
+          { name: '已支付', value: 68 },
+          { name: '待支付', value: 18 }
+        ],
+        radius: ['40%', '70%']
+      }]
+    })
+  }
+})
+</script>
+
+<style scoped lang="scss">
+.stats-row { margin-bottom: 20px; }
+.stat-card { text-align: center; }
+.stat-value { font-size: 28px; font-weight: 700; color: #1F2937; }
+.stat-label { font-size: 14px; color: #6B7280; margin-top: 4px; }
+.stat-change { font-size: 12px; margin-top: 8px; }
+.stat-change.up { color: #10B981; }
+.stat-change.down { color: #EF4444; }
+.chart-row { margin-bottom: 20px; }
+.recent-orders { margin-bottom: 20px; }
+</style>

+ 73 - 0
admin/src/views/login/index.vue

@@ -0,0 +1,73 @@
+<template>
+  <div class="login-page">
+    <div class="login-card">
+      <h2 class="login-title">数字能量学管理平台</h2>
+      <el-form :model="form" :rules="rules" ref="formRef" label-width="0">
+        <el-form-item prop="username">
+          <el-input v-model="form.username" placeholder="用户名" size="large" prefix-icon="User" />
+        </el-form-item>
+        <el-form-item prop="password">
+          <el-input v-model="form.password" type="password" placeholder="密码" size="large" prefix-icon="Lock" show-password />
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" size="large" class="login-btn" @click="handleLogin" :loading="loading">
+            登 录
+          </el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from 'vue'
+import { useRouter } from 'vue-router'
+import { useAuthStore } from '@/stores/auth'
+import { ElMessage } from 'element-plus'
+
+const router = useRouter()
+const auth = useAuthStore()
+const formRef = ref()
+const loading = ref(false)
+
+const form = reactive({
+  username: '',
+  password: ''
+})
+
+const rules = {
+  username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
+  password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
+}
+
+async function handleLogin() {
+  const valid = await formRef.value.validate().catch(() => false)
+  if (!valid) return
+  loading.value = true
+  try {
+    await auth.login(form.username, form.password)
+    ElMessage.success('登录成功')
+    router.push('/dashboard')
+  } catch (e) {
+    // Error handled by interceptor
+  } finally {
+    loading.value = false
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.login-page {
+  height: 100vh; display: flex; align-items: center; justify-content: center;
+  background: linear-gradient(135deg, #1e3a5f 0%, #3B82F6 100%);
+}
+.login-card {
+  background: #fff; border-radius: 16px; padding: 40px;
+  width: 400px; box-shadow: 0 20px 60px rgba(0,0,0,0.15);
+}
+.login-title {
+  text-align: center; margin-bottom: 32px; color: #1F2937;
+  font-size: 22px; font-weight: 700;
+}
+.login-btn { width: 100%; }
+</style>

+ 69 - 0
admin/src/views/orders/index.vue

@@ -0,0 +1,69 @@
+<template>
+  <div class="orders-page">
+    <el-card shadow="hover">
+      <template #header>
+        <div class="header-toolbar">
+          <span>订单管理</span>
+          <div>
+            <el-select v-model="statusFilter" placeholder="状态" style="width: 120px; margin-right: 8px" clearable>
+              <el-option label="全部" value="" />
+              <el-option label="已支付" value="paid" />
+              <el-option label="待支付" value="pending" />
+            </el-select>
+          </div>
+        </div>
+      </template>
+      <el-table :data="orders" v-loading="loading" stripe>
+        <el-table-column prop="id" label="ID" width="60" />
+        <el-table-column prop="outTradeNo" label="订单号" width="200" />
+        <el-table-column prop="userId" label="用户ID" width="80" />
+        <el-table-column label="金额" width="100">
+          <template #default="{ row }">{{ (row.totalFee / 100).toFixed(2) }}元</template>
+        </el-table-column>
+        <el-table-column label="状态" width="100">
+          <template #default="{ row }">
+            <el-tag :type="row.status === 'paid' ? 'success' : 'warning'">
+              {{ row.status === 'paid' ? '已支付' : '待支付' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="payType" label="支付方式" width="100" />
+        <el-table-column prop="createdAt" label="创建时间" width="110" />
+        <el-table-column prop="paidAt" label="支付时间" width="110" />
+      </el-table>
+      <div class="pagination-wrap">
+        <el-pagination background layout="total, prev, pager, next" :total="orders.length" :page-size="20" />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+import request from '@/utils/request'
+
+const loading = ref(false)
+const statusFilter = ref('')
+const orders = ref<any[]>([])
+
+const filteredOrders = computed(() => {
+  if (!statusFilter.value) return orders.value
+  return orders.value.filter((o: any) => o.status === statusFilter.value)
+})
+
+async function loadOrders() {
+  loading.value = true
+  try {
+    orders.value = await request.post('/admin/orders', {}) as any
+  } finally {
+    loading.value = false
+  }
+}
+
+loadOrders()
+</script>
+
+<style scoped lang="scss">
+.header-toolbar { display: flex; justify-content: space-between; align-items: center; }
+.pagination-wrap { margin-top: 16px; display: flex; justify-content: flex-end; }
+</style>

+ 90 - 0
admin/src/views/users/index.vue

@@ -0,0 +1,90 @@
+<template>
+  <div class="users-page">
+    <el-card shadow="hover">
+      <template #header>
+        <div class="header-toolbar">
+          <span>用户管理</span>
+          <el-input v-model="search" placeholder="搜索用户..." prefix-icon="Search" style="width: 250px" clearable />
+        </div>
+      </template>
+      <el-table :data="filteredUsers" v-loading="loading" stripe>
+        <el-table-column prop="id" label="ID" width="60" />
+        <el-table-column label="头像" width="60">
+          <template #default="{ row }">
+            <el-avatar :src="row.avatarUrl" :size="36" />
+          </template>
+        </el-table-column>
+        <el-table-column prop="nickname" label="昵称" />
+        <el-table-column prop="phone" label="手机号" width="130" />
+        <el-table-column prop="referralCode" label="推广码" width="110" />
+        <el-table-column label="VIP" width="80">
+          <template #default="{ row }">
+            <el-tag :type="row.vipEndTime ? 'success' : 'info'" size="small">
+              {{ row.vipEndTime ? '是' : '否' }}
+            </el-tag>
+          </template>
+        </el-table-column>
+        <el-table-column prop="createdAt" label="注册时间" width="110" />
+        <el-table-column label="操作" width="200" fixed="right">
+          <template #default="{ row }">
+            <el-button size="small" @click="upgradeVip(row)" :disabled="!!row.vipEndTime">
+              升级VIP
+            </el-button>
+            <el-button size="small" @click="toggleAdmin(row)">
+              {{ row.isAdmin ? '取消管理' : '设为管理' }}
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination-wrap">
+        <el-pagination background layout="total, prev, pager, next" :total="users.length" :page-size="20" />
+      </div>
+    </el-card>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, computed } from 'vue'
+import { ElMessage } from 'element-plus'
+import request from '@/utils/request'
+
+const loading = ref(false)
+const search = ref('')
+const users = ref<any[]>([])
+
+const filteredUsers = computed(() => {
+  if (!search.value) return users.value
+  return users.value.filter((u: any) =>
+    u.nickname?.includes(search.value) || u.phone?.includes(search.value)
+  )
+})
+
+async function loadUsers() {
+  loading.value = true
+  try {
+    users.value = await request.post('/admin/users', {}) as any
+  } finally {
+    loading.value = false
+  }
+}
+
+async function upgradeVip(user: any) {
+  await request.post('/admin/user/upgrade', { userId: user.id })
+  ElMessage.success('已升级VIP')
+  loadUsers()
+}
+
+async function toggleAdmin(user: any) {
+  const action = user.isAdmin ? 'downgrade' : 'upgrade'
+  await request.post(`/admin/user/${action}`, { userId: user.id })
+  ElMessage.success(user.isAdmin ? '已取消管理权限' : '已设为管理员')
+  loadUsers()
+}
+
+loadUsers()
+</script>
+
+<style scoped lang="scss">
+.header-toolbar { display: flex; justify-content: space-between; align-items: center; }
+.pagination-wrap { margin-top: 16px; display: flex; justify-content: flex-end; }
+</style>

+ 18 - 0
admin/tsconfig.json

@@ -0,0 +1,18 @@
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "module": "ESNext",
+    "strict": true,
+    "jsx": "preserve",
+    "moduleResolution": "node",
+    "skipLibCheck": true,
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "forceConsistentCasingInFileNames": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "baseUrl": ".",
+    "paths": { "@/*": ["src/*"] }
+  },
+  "include": ["src/**/*.ts", "src/**/*.vue", "env.d.ts"]
+}

+ 21 - 0
admin/vite.config.ts

@@ -0,0 +1,21 @@
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import path from 'path'
+
+export default defineConfig({
+  plugins: [vue()],
+  resolve: {
+    alias: {
+      '@': path.resolve(__dirname, 'src')
+    }
+  },
+  server: {
+    port: 5173,
+    proxy: {
+      '/api': {
+        target: 'http://localhost:8080',
+        changeOrigin: true
+      }
+    }
+  }
+})

+ 6 - 0
client/env.d.ts

@@ -0,0 +1,6 @@
+/// <reference types="vite/client" />
+declare module '*.vue' {
+  import type { DefineComponent } from 'vue'
+  const component: DefineComponent<{}, {}, any>
+  export default component
+}

+ 7179 - 0
client/package-lock.json

@@ -0,0 +1,7179 @@
+{
+  "name": "num-energy",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "num-energy",
+      "version": "1.0.0",
+      "dependencies": {
+        "@dcloudio/uni-app": "^3.0.0-alpha-5010120260522001",
+        "axios": "^1.6.0",
+        "pinia": "^2.1.0",
+        "vue": "^3.4.0"
+      },
+      "devDependencies": {
+        "@dcloudio/types": "^3.3.0",
+        "@dcloudio/vite-plugin-uni": "3.0.0-alpha-5010120260522001",
+        "typescript": "^5.3.0",
+        "vite": "^5.0.0",
+        "vue-tsc": "^2.2.12"
+      }
+    },
+    "node_modules/@ampproject/remapping": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.3.0.tgz",
+      "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/code-frame": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.7.tgz",
+      "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.29.7",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.1.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/code-frame/node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/@babel/compat-data": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.7.tgz",
+      "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/core": {
+      "version": "7.25.2",
+      "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.25.2.tgz",
+      "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==",
+      "license": "MIT",
+      "dependencies": {
+        "@ampproject/remapping": "^2.2.0",
+        "@babel/code-frame": "^7.24.7",
+        "@babel/generator": "^7.25.0",
+        "@babel/helper-compilation-targets": "^7.25.2",
+        "@babel/helper-module-transforms": "^7.25.2",
+        "@babel/helpers": "^7.25.0",
+        "@babel/parser": "^7.25.0",
+        "@babel/template": "^7.25.0",
+        "@babel/traverse": "^7.25.2",
+        "@babel/types": "^7.25.2",
+        "convert-source-map": "^2.0.0",
+        "debug": "^4.1.0",
+        "gensync": "^1.0.0-beta.2",
+        "json5": "^2.2.3",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/babel"
+      }
+    },
+    "node_modules/@babel/generator": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.7.tgz",
+      "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.7",
+        "@babel/types": "^7.29.7",
+        "@jridgewell/gen-mapping": "^0.3.12",
+        "@jridgewell/trace-mapping": "^0.3.28",
+        "jsesc": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-annotate-as-pure": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz",
+      "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-compilation-targets": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz",
+      "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/compat-data": "^7.29.7",
+        "@babel/helper-validator-option": "^7.29.7",
+        "browserslist": "^4.24.0",
+        "lru-cache": "^5.1.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-create-class-features-plugin": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz",
+      "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.29.7",
+        "@babel/helper-member-expression-to-functions": "^7.29.7",
+        "@babel/helper-optimise-call-expression": "^7.29.7",
+        "@babel/helper-replace-supers": "^7.29.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7",
+        "@babel/traverse": "^7.29.7",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-create-regexp-features-plugin": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz",
+      "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.29.7",
+        "regexpu-core": "^6.3.1",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-define-polyfill-provider": {
+      "version": "0.6.8",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz",
+      "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-compilation-targets": "^7.28.6",
+        "@babel/helper-plugin-utils": "^7.28.6",
+        "debug": "^4.4.3",
+        "lodash.debounce": "^4.0.8",
+        "resolve": "^1.22.11"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+      }
+    },
+    "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": {
+      "version": "4.4.3",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz",
+      "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@babel/helper-define-polyfill-provider/node_modules/resolve": {
+      "version": "1.22.12",
+      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.12.tgz",
+      "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "is-core-module": "^2.16.1",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/@babel/helper-globals": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.29.7.tgz",
+      "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-member-expression-to-functions": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz",
+      "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/traverse": "^7.29.7",
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-imports": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz",
+      "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/traverse": "^7.29.7",
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-module-transforms": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz",
+      "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.29.7",
+        "@babel/helper-validator-identifier": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-optimise-call-expression": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz",
+      "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-plugin-utils": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz",
+      "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-remap-async-to-generator": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz",
+      "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.29.7",
+        "@babel/helper-wrap-function": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-replace-supers": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz",
+      "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-member-expression-to-functions": "^7.29.7",
+        "@babel/helper-optimise-call-expression": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz",
+      "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/traverse": "^7.29.7",
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz",
+      "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz",
+      "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-option": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz",
+      "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-wrap-function": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz",
+      "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/template": "^7.29.7",
+        "@babel/traverse": "^7.29.7",
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helpers": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.29.7.tgz",
+      "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/template": "^7.29.7",
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/highlight": {
+      "version": "7.25.9",
+      "resolved": "https://registry.npmmirror.com/@babel/highlight/-/highlight-7.25.9.tgz",
+      "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-validator-identifier": "^7.25.9",
+        "chalk": "^2.4.2",
+        "js-tokens": "^4.0.0",
+        "picocolors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.7.tgz",
+      "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.29.7"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz",
+      "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz",
+      "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz",
+      "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz",
+      "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz",
+      "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7",
+        "@babel/plugin-transform-optional-chaining": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.13.0"
+      }
+    },
+    "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz",
+      "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-proposal-private-property-in-object": {
+      "version": "7.21.0-placeholder-for-preset-env.2",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
+      "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-assertions": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz",
+      "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-attributes": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz",
+      "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-import-meta": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+      "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-jsx": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz",
+      "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-typescript": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz",
+      "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
+      "version": "7.18.6",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
+      "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+        "@babel/helper-plugin-utils": "^7.18.6"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-arrow-functions": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz",
+      "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-async-generator-functions": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz",
+      "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-remap-async-to-generator": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-async-to-generator": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz",
+      "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-remap-async-to-generator": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-block-scoped-functions": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz",
+      "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-block-scoping": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz",
+      "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-class-properties": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz",
+      "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-class-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-class-static-block": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz",
+      "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-class-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.12.0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-classes": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz",
+      "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.29.7",
+        "@babel/helper-compilation-targets": "^7.29.7",
+        "@babel/helper-globals": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-replace-supers": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-computed-properties": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz",
+      "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/template": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-destructuring": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz",
+      "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-dotall-regex": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz",
+      "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-duplicate-keys": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz",
+      "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz",
+      "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-dynamic-import": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz",
+      "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-explicit-resource-management": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz",
+      "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/plugin-transform-destructuring": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-exponentiation-operator": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz",
+      "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-export-namespace-from": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz",
+      "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-for-of": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz",
+      "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-function-name": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz",
+      "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-compilation-targets": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-json-strings": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz",
+      "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-literals": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz",
+      "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-logical-assignment-operators": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz",
+      "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-member-expression-literals": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz",
+      "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-amd": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz",
+      "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-transforms": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-commonjs": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz",
+      "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-transforms": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-systemjs": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.7.tgz",
+      "integrity": "sha512-TM2ZcQLoG2/y4HODiStCo10DibYhWhGWAwVv+EQKmG/7GFl0N+AAmUiXOMKM+aiJ9XBJ9AHVZBvTzMnJ2sM3cQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-transforms": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-validator-identifier": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-modules-umd": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz",
+      "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-transforms": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz",
+      "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-new-target": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz",
+      "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz",
+      "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-numeric-separator": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz",
+      "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-object-rest-spread": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz",
+      "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-compilation-targets": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/plugin-transform-destructuring": "^7.29.7",
+        "@babel/plugin-transform-parameters": "^7.29.7",
+        "@babel/traverse": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-object-super": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz",
+      "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-replace-supers": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-optional-catch-binding": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz",
+      "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-optional-chaining": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz",
+      "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-parameters": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz",
+      "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-private-methods": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz",
+      "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-class-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-private-property-in-object": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz",
+      "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.29.7",
+        "@babel/helper-create-class-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-property-literals": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz",
+      "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-regenerator": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.7.tgz",
+      "integrity": "sha512-rNNFV0DBAJp988xW2DOntfDoYn1eR8GGF5AT5vYc+rjyfaQkM242c9tZUHHPe7KYaiJizXPWhQTzzdbXySyhBw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-regexp-modifiers": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz",
+      "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-reserved-words": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz",
+      "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-shorthand-properties": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz",
+      "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-spread": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.7.tgz",
+      "integrity": "sha512-/u5K1QWada7tbYNqTjMh96718g9NTwh9tfPJMsSmVsQwGT447FskV+KcfeXkXq2GWki4EM/MuTdmBec+hOuVTQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-sticky-regex": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz",
+      "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-template-literals": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz",
+      "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-typeof-symbol": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz",
+      "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-typescript": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz",
+      "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-annotate-as-pure": "^7.29.7",
+        "@babel/helper-create-class-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7",
+        "@babel/plugin-syntax-typescript": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-unicode-escapes": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz",
+      "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-unicode-property-regex": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz",
+      "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-unicode-regex": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz",
+      "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-transform-unicode-sets-regex": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz",
+      "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-create-regexp-features-plugin": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0"
+      }
+    },
+    "node_modules/@babel/preset-env": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/preset-env/-/preset-env-7.29.7.tgz",
+      "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/compat-data": "^7.29.7",
+        "@babel/helper-compilation-targets": "^7.29.7",
+        "@babel/helper-plugin-utils": "^7.29.7",
+        "@babel/helper-validator-option": "^7.29.7",
+        "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7",
+        "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7",
+        "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7",
+        "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7",
+        "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7",
+        "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7",
+        "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
+        "@babel/plugin-syntax-import-assertions": "^7.29.7",
+        "@babel/plugin-syntax-import-attributes": "^7.29.7",
+        "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
+        "@babel/plugin-transform-arrow-functions": "^7.29.7",
+        "@babel/plugin-transform-async-generator-functions": "^7.29.7",
+        "@babel/plugin-transform-async-to-generator": "^7.29.7",
+        "@babel/plugin-transform-block-scoped-functions": "^7.29.7",
+        "@babel/plugin-transform-block-scoping": "^7.29.7",
+        "@babel/plugin-transform-class-properties": "^7.29.7",
+        "@babel/plugin-transform-class-static-block": "^7.29.7",
+        "@babel/plugin-transform-classes": "^7.29.7",
+        "@babel/plugin-transform-computed-properties": "^7.29.7",
+        "@babel/plugin-transform-destructuring": "^7.29.7",
+        "@babel/plugin-transform-dotall-regex": "^7.29.7",
+        "@babel/plugin-transform-duplicate-keys": "^7.29.7",
+        "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7",
+        "@babel/plugin-transform-dynamic-import": "^7.29.7",
+        "@babel/plugin-transform-explicit-resource-management": "^7.29.7",
+        "@babel/plugin-transform-exponentiation-operator": "^7.29.7",
+        "@babel/plugin-transform-export-namespace-from": "^7.29.7",
+        "@babel/plugin-transform-for-of": "^7.29.7",
+        "@babel/plugin-transform-function-name": "^7.29.7",
+        "@babel/plugin-transform-json-strings": "^7.29.7",
+        "@babel/plugin-transform-literals": "^7.29.7",
+        "@babel/plugin-transform-logical-assignment-operators": "^7.29.7",
+        "@babel/plugin-transform-member-expression-literals": "^7.29.7",
+        "@babel/plugin-transform-modules-amd": "^7.29.7",
+        "@babel/plugin-transform-modules-commonjs": "^7.29.7",
+        "@babel/plugin-transform-modules-systemjs": "^7.29.7",
+        "@babel/plugin-transform-modules-umd": "^7.29.7",
+        "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7",
+        "@babel/plugin-transform-new-target": "^7.29.7",
+        "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7",
+        "@babel/plugin-transform-numeric-separator": "^7.29.7",
+        "@babel/plugin-transform-object-rest-spread": "^7.29.7",
+        "@babel/plugin-transform-object-super": "^7.29.7",
+        "@babel/plugin-transform-optional-catch-binding": "^7.29.7",
+        "@babel/plugin-transform-optional-chaining": "^7.29.7",
+        "@babel/plugin-transform-parameters": "^7.29.7",
+        "@babel/plugin-transform-private-methods": "^7.29.7",
+        "@babel/plugin-transform-private-property-in-object": "^7.29.7",
+        "@babel/plugin-transform-property-literals": "^7.29.7",
+        "@babel/plugin-transform-regenerator": "^7.29.7",
+        "@babel/plugin-transform-regexp-modifiers": "^7.29.7",
+        "@babel/plugin-transform-reserved-words": "^7.29.7",
+        "@babel/plugin-transform-shorthand-properties": "^7.29.7",
+        "@babel/plugin-transform-spread": "^7.29.7",
+        "@babel/plugin-transform-sticky-regex": "^7.29.7",
+        "@babel/plugin-transform-template-literals": "^7.29.7",
+        "@babel/plugin-transform-typeof-symbol": "^7.29.7",
+        "@babel/plugin-transform-unicode-escapes": "^7.29.7",
+        "@babel/plugin-transform-unicode-property-regex": "^7.29.7",
+        "@babel/plugin-transform-unicode-regex": "^7.29.7",
+        "@babel/plugin-transform-unicode-sets-regex": "^7.29.7",
+        "@babel/preset-modules": "0.1.6-no-external-plugins",
+        "babel-plugin-polyfill-corejs2": "^0.4.15",
+        "babel-plugin-polyfill-corejs3": "^0.14.0",
+        "babel-plugin-polyfill-regenerator": "^0.6.6",
+        "core-js-compat": "^3.48.0",
+        "semver": "^6.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/preset-modules": {
+      "version": "0.1.6-no-external-plugins",
+      "resolved": "https://registry.npmmirror.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+      "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.0.0",
+        "@babel/types": "^7.4.4",
+        "esutils": "^2.0.2"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
+      }
+    },
+    "node_modules/@babel/runtime-corejs3": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/runtime-corejs3/-/runtime-corejs3-7.29.7.tgz",
+      "integrity": "sha512-ppj9ouYku+RX0ljtgZd+KMO5mkM2bCqg8H2PYAFWnLsHEIKIdRojqbJ2i3eVHrisuxy7nOFCmngTDdWtUCdXUQ==",
+      "license": "MIT",
+      "dependencies": {
+        "core-js-pure": "^3.48.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.29.7.tgz",
+      "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.29.7",
+        "@babel/parser": "^7.29.7",
+        "@babel/types": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.7.tgz",
+      "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.29.7",
+        "@babel/generator": "^7.29.7",
+        "@babel/helper-globals": "^7.29.7",
+        "@babel/parser": "^7.29.7",
+        "@babel/template": "^7.29.7",
+        "@babel/types": "^7.29.7",
+        "debug": "^4.3.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.29.7",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.7.tgz",
+      "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.29.7",
+        "@babel/helper-validator-identifier": "^7.29.7"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@dcloudio/types": {
+      "version": "3.4.31",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/types/-/types-3.4.31.tgz",
+      "integrity": "sha512-YAqOfJpcAwMs4Fagv2oP+iRHSCJOJoN8JUYyoRD6gwfANhsI9QaYj4/j22FzSopfHkqjX50B7YkG/VRAyz9OnA==",
+      "license": "Apache-2.0"
+    },
+    "node_modules/@dcloudio/uni-app": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-app/-/uni-app-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-zDW9iSIjLTaxUdZMz3cz7gjaHC2/cKNMYJod4YuMo89ccP4+pRBohBa8Bt3292lxC/0z+nzuIVsfoYH3pcTWQA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-cloud": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-components": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-console": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-i18n": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-push": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-stat": "3.0.0-alpha-5010120260522001",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "@dcloudio/types": "3.4.31"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-cli-shared/-/uni-cli-shared-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-fP4EHRb/phyCccf1pj9dCDyEQzVtrAna32e76CG78RxxUV1MZnmrGy/yWjaNvqRwdqAaQD2jO2VSyy+53B/KhQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@ampproject/remapping": "^2.1.2",
+        "@babel/code-frame": "7.24.7",
+        "@babel/core": "7.25.2",
+        "@babel/parser": "7.25.6",
+        "@babel/types": "7.25.6",
+        "@dcloudio/uni-i18n": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-nvue-styler": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "@intlify/core-base": "9.1.9",
+        "@intlify/shared": "9.1.9",
+        "@intlify/vue-devtools": "9.1.9",
+        "@rollup/pluginutils": "5.1.0",
+        "@vue/compiler-core": "3.4.21",
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-sfc": "3.4.21",
+        "@vue/compiler-ssr": "3.4.21",
+        "@vue/server-renderer": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "adm-zip": "0.5.16",
+        "autoprefixer": "10.4.20",
+        "base64url": "^3.0.1",
+        "chokidar": "3.6.0",
+        "compare-versions": "^3.6.0",
+        "debug": "4.3.7",
+        "entities": "^7.0.0",
+        "es-module-lexer": "1.5.4",
+        "esbuild": "0.20.2",
+        "estree-walker": "2.0.2",
+        "fast-glob": "3.3.3",
+        "fs-extra": "10.1.0",
+        "hash-sum": "2.0.0",
+        "isbinaryfile": "5.0.2",
+        "jsonc-parser": "3.3.1",
+        "lines-and-columns": "^2.0.4",
+        "magic-string": "0.30.11",
+        "merge": "2.1.1",
+        "mime": "3.0.0",
+        "module-alias": "2.2.3",
+        "os-locale-s-fix": "^1.0.8-fix-1",
+        "picocolors": "1.1.0",
+        "postcss-import": "^14.0.2",
+        "postcss-load-config": "^3.1.1",
+        "postcss-modules": "^4.3.0",
+        "postcss-selector-parser": "6.1.2",
+        "resolve": "1.22.8",
+        "source-map-js": "1.2.1",
+        "tapable": "^2.2.0",
+        "tinycolor2": "1.6.0",
+        "unimport": "4.1.1",
+        "unplugin-auto-import": "19.1.0",
+        "xregexp": "5.1.2"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/@babel/code-frame": {
+      "version": "7.24.7",
+      "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.24.7.tgz",
+      "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/highlight": "^7.24.7",
+        "picocolors": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/@babel/parser": {
+      "version": "7.25.6",
+      "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.25.6.tgz",
+      "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.25.6"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/@babel/types": {
+      "version": "7.25.6",
+      "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.25.6.tgz",
+      "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.24.8",
+        "@babel/helper-validator-identifier": "^7.24.7",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/@vue/reactivity": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.4.21.tgz",
+      "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/@vue/runtime-core": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
+      "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.4.21",
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/@vue/runtime-dom": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
+      "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/runtime-core": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/@vue/server-renderer": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
+      "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "vue": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-cli-shared/node_modules/vue": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.4.21.tgz",
+      "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-sfc": "3.4.21",
+        "@vue/runtime-dom": "3.4.21",
+        "@vue/server-renderer": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@dcloudio/uni-cloud": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-cloud/-/uni-cloud-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-5MpucllWpA8fK4QdsPpx5uOSiwUttGwSxoutkrcWgVpJ5b2yADpNM3mGhRkN15DV16t6XGQuIpSkNPmsazeE0Q==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-i18n": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "@vue/shared": "3.4.21",
+        "fast-glob": "3.3.3"
+      }
+    },
+    "node_modules/@dcloudio/uni-components": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-components/-/uni-components-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-jGEavttznKSihDjMfQt68gnGf1yBuzEyYc6aPnWKCIiEd5ZshPEBCQOxwOBiF7Y77+nrmQuPhs1l+MCOmIyi2g==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-cloud": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-h5": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-i18n": "3.0.0-alpha-5010120260522001"
+      }
+    },
+    "node_modules/@dcloudio/uni-console": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-console/-/uni-console-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-ri05stj0yFrv/iRooKB8IbPyozmYgtOHapB0VdR5z16xwyC6FEl6j4ruMbCj9BBChzJUArUcD0v87uJ/vk+Lug==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-5010120260522001",
+        "fs-extra": "10.1.0"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-h5/-/uni-h5-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-wB4LkM1YECCEteracVO1/wMBKQp+WAinXAqoAzmmOz1CKj3P7emZDhMqt1QVo97Dixvml3EA+hUKTM/hG/0S8Q==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-h5-vite": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-h5-vue": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-i18n": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "@vue/server-renderer": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "debug": "4.3.7",
+        "localstorage-polyfill": "^1.0.1",
+        "postcss-selector-parser": "6.1.2",
+        "safe-area-insets": "1.4.1",
+        "vue-router": "4.4.4",
+        "xmlhttprequest": "^1.8.0"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vite": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-h5-vite/-/uni-h5-vite-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-WGdldROfzmjErYGMULxVPmALz+p194o0ehDpQO0wVK9Gl2+NMJBQeos6Z5tHVvCJ8EQsP7Vfrmuxdk9R5raioA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "@rollup/pluginutils": "5.1.0",
+        "@vitejs/plugin-basic-ssl": "1.2.0",
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-sfc": "3.4.21",
+        "@vue/server-renderer": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "debug": "4.3.7",
+        "fs-extra": "10.1.0",
+        "mime": "3.0.0",
+        "module-alias": "2.2.3"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vite/node_modules/@vue/reactivity": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.4.21.tgz",
+      "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vite/node_modules/@vue/runtime-core": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
+      "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.4.21",
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vite/node_modules/@vue/runtime-dom": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
+      "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/runtime-core": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vite/node_modules/@vue/server-renderer": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
+      "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "vue": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vite/node_modules/vue": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.4.21.tgz",
+      "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-sfc": "3.4.21",
+        "@vue/runtime-dom": "3.4.21",
+        "@vue/server-renderer": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vue": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-h5-vue/-/uni-h5-vue-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-6dg6kfJEKTkst1fCA34pcYEYrCK6S3AQJWDZvu8yuc6KY2y6loFPEltzJAbAQkOW0hqbINnsKbypZn0zj0dKmQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "@vue/server-renderer": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vue/node_modules/@vue/reactivity": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.4.21.tgz",
+      "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vue/node_modules/@vue/runtime-core": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
+      "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.4.21",
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vue/node_modules/@vue/runtime-dom": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
+      "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/runtime-core": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vue/node_modules/@vue/server-renderer": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
+      "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "vue": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5-vue/node_modules/vue": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.4.21.tgz",
+      "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-sfc": "3.4.21",
+        "@vue/runtime-dom": "3.4.21",
+        "@vue/server-renderer": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@dcloudio/uni-h5/node_modules/@vue/reactivity": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.4.21.tgz",
+      "integrity": "sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5/node_modules/@vue/runtime-core": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.4.21.tgz",
+      "integrity": "sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/reactivity": "3.4.21",
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5/node_modules/@vue/runtime-dom": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.4.21.tgz",
+      "integrity": "sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/runtime-core": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5/node_modules/@vue/server-renderer": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.4.21.tgz",
+      "integrity": "sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "vue": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-h5/node_modules/vue": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.4.21.tgz",
+      "integrity": "sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==",
+      "license": "MIT",
+      "peer": true,
+      "dependencies": {
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-sfc": "3.4.21",
+        "@vue/runtime-dom": "3.4.21",
+        "@vue/server-renderer": "3.4.21",
+        "@vue/shared": "3.4.21"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@dcloudio/uni-i18n": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-i18n/-/uni-i18n-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-4MLLo2oIQjxmYPwGepdrFAZl9PrsYEaYTQ8JtcTsR5+SfNhhYbHlJNR+VAuf3kaJpehIWuRtDWTetmTIJsxRGg==",
+      "license": "Apache-2.0"
+    },
+    "node_modules/@dcloudio/uni-nvue-styler": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-nvue-styler/-/uni-nvue-styler-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-hXkvFkIGBYee2l1Js+plaEIJvVHAFLZTDGDDjV84qlGhzdz5282U2oFI1cdOsoiNAsR8WwoL4oRJD6Kt4akqUg==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@vue/shared": "3.4.21",
+        "parse-css-font": "^4.0.0",
+        "postcss": "8.5.6",
+        "tinycolor2": "1.6.0"
+      }
+    },
+    "node_modules/@dcloudio/uni-nvue-styler/node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/@dcloudio/uni-nvue-styler/node_modules/postcss": {
+      "version": "8.5.6",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
+      "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.11",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/@dcloudio/uni-push": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-push/-/uni-push-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-+QRQG0Gh7bmdUmhCsu2HApGZXZ6eT4KL9p2oxIGuUhOv10cy+a52QKG+NUYl4K+yfEwmVUPUq2jk/kzDwk/kzg==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-5010120260522001"
+      }
+    },
+    "node_modules/@dcloudio/uni-shared": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-shared/-/uni-shared-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-zvKhJkdULnh4zj2kAJvlx4XcbSakcRRXFeZ0J5UXjBkUw47FDSxbHPerVFUck0qwq90fP3g+0jCzGQeWbG7eaQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@dcloudio/uni-stat": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/uni-stat/-/uni-stat-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-EGQIgjQb/P8pEa8nWSc0ZAP4LQ6Aip5vt2unpzc1oZVVCMkEPWxeam8hRS95Tu4TUaOW1L9jhl14i7q2L1h4Pw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "debug": "4.3.7"
+      }
+    },
+    "node_modules/@dcloudio/vite-plugin-uni": {
+      "version": "3.0.0-alpha-5010120260522001",
+      "resolved": "https://registry.npmmirror.com/@dcloudio/vite-plugin-uni/-/vite-plugin-uni-3.0.0-alpha-5010120260522001.tgz",
+      "integrity": "sha512-bo13mRw4g/D0JcgFXwj1cJo/lByEGd9ELzT6QPRPZ/pL+uCbjK9isy5GwxbiMSkw7hQkUjOz7IaHypeHP++ynw==",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/core": "7.25.2",
+        "@babel/plugin-syntax-import-meta": "^7.10.4",
+        "@babel/plugin-transform-typescript": "^7.23.3",
+        "@dcloudio/uni-cli-shared": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-nvue-styler": "3.0.0-alpha-5010120260522001",
+        "@dcloudio/uni-shared": "3.0.0-alpha-5010120260522001",
+        "@rollup/pluginutils": "5.1.0",
+        "@vitejs/plugin-legacy": "5.3.2",
+        "@vitejs/plugin-vue": "5.2.4",
+        "@vitejs/plugin-vue-jsx": "3.1.0",
+        "@vue/compiler-core": "3.4.21",
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-sfc": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "cac": "6.7.9",
+        "debug": "4.3.7",
+        "estree-walker": "2.0.2",
+        "express": "4.20.0",
+        "fast-glob": "3.3.3",
+        "fs-extra": "10.1.0",
+        "hash-sum": "2.0.0",
+        "jsonc-parser": "3.3.1",
+        "magic-string": "0.30.11",
+        "picocolors": "1.1.0",
+        "terser": "^5.4.0",
+        "unplugin-auto-import": "19.1.0"
+      },
+      "bin": {
+        "uni": "bin/uni.js"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "vite": "5.2.8"
+      }
+    },
+    "node_modules/@esbuild/aix-ppc64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
+      "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "aix"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
+      "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-arm64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
+      "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/android-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
+      "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-arm64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
+      "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/darwin-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
+      "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-arm64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
+      "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/freebsd-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
+      "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
+      "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-arm64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
+      "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ia32": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
+      "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-loong64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
+      "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-mips64el": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
+      "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
+      "cpu": [
+        "mips64el"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-ppc64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
+      "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-riscv64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
+      "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-s390x": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
+      "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/linux-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
+      "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/netbsd-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
+      "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "netbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/openbsd-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
+      "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/sunos-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
+      "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "sunos"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-arm64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
+      "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-ia32": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
+      "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
+      "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@intlify/core-base": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/@intlify/core-base/-/core-base-9.1.9.tgz",
+      "integrity": "sha512-x5T0p/Ja0S8hs5xs+ImKyYckVkL4CzcEXykVYYV6rcbXxJTe2o58IquSqX9bdncVKbRZP7GlBU1EcRaQEEJ+vw==",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/devtools-if": "9.1.9",
+        "@intlify/message-compiler": "9.1.9",
+        "@intlify/message-resolver": "9.1.9",
+        "@intlify/runtime": "9.1.9",
+        "@intlify/shared": "9.1.9",
+        "@intlify/vue-devtools": "9.1.9"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@intlify/devtools-if": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/@intlify/devtools-if/-/devtools-if-9.1.9.tgz",
+      "integrity": "sha512-oKSMKjttG3Ut/1UGEZjSdghuP3fwA15zpDPcjkf/1FjlOIm6uIBGMNS5jXzsZy593u+P/YcnrZD6cD3IVFz9vQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/shared": "9.1.9"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@intlify/message-compiler": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/@intlify/message-compiler/-/message-compiler-9.1.9.tgz",
+      "integrity": "sha512-6YgCMF46Xd0IH2hMRLCssZI3gFG4aywidoWQ3QP4RGYQXQYYfFC54DxhSgfIPpVoPLQ+4AD29eoYmhiHZ+qLFQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/message-resolver": "9.1.9",
+        "@intlify/shared": "9.1.9",
+        "source-map": "0.6.1"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@intlify/message-resolver": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/@intlify/message-resolver/-/message-resolver-9.1.9.tgz",
+      "integrity": "sha512-Lx/DBpigeK0sz2BBbzv5mu9/dAlt98HxwbG7xLawC3O2xMF9MNWU5FtOziwYG6TDIjNq0O/3ZbOJAxwITIWXEA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@intlify/runtime": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/@intlify/runtime/-/runtime-9.1.9.tgz",
+      "integrity": "sha512-XgPw8+UlHCiie3fI41HPVa/VDJb3/aSH7bLhY1hJvlvNV713PFtb4p4Jo+rlE0gAoMsMCGcsiT982fImolSltg==",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/message-compiler": "9.1.9",
+        "@intlify/message-resolver": "9.1.9",
+        "@intlify/shared": "9.1.9"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@intlify/shared": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/@intlify/shared/-/shared-9.1.9.tgz",
+      "integrity": "sha512-xKGM1d0EAxdDFCWedcYXOm6V5Pfw/TMudd6/qCdEb4tv0hk9EKeg7lwQF1azE0dP2phvx0yXxrt7UQK+IZjNdw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@intlify/vue-devtools": {
+      "version": "9.1.9",
+      "resolved": "https://registry.npmmirror.com/@intlify/vue-devtools/-/vue-devtools-9.1.9.tgz",
+      "integrity": "sha512-YPehH9uL4vZcGXky4Ev5qQIITnHKIvsD2GKGXgqf+05osMUI6WSEQHaN9USRa318Rs8RyyPCiDfmA0hRu3k7og==",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/message-resolver": "9.1.9",
+        "@intlify/runtime": "9.1.9",
+        "@intlify/shared": "9.1.9"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/@jridgewell/gen-mapping": {
+      "version": "0.3.13",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+      "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "node_modules/@jridgewell/remapping": {
+      "version": "2.3.5",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+      "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.24"
+      }
+    },
+    "node_modules/@jridgewell/resolve-uri": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+      "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@jridgewell/source-map": {
+      "version": "0.3.11",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz",
+      "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
+      "devOptional": true,
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/gen-mapping": "^0.3.5",
+        "@jridgewell/trace-mapping": "^0.3.25"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.5",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+      "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+      "license": "MIT"
+    },
+    "node_modules/@jridgewell/trace-mapping": {
+      "version": "0.3.31",
+      "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+      "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/resolve-uri": "^3.1.0",
+        "@jridgewell/sourcemap-codec": "^1.4.14"
+      }
+    },
+    "node_modules/@nodelib/fs.scandir": {
+      "version": "2.1.5",
+      "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.stat": "2.0.5",
+        "run-parallel": "^1.1.9"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.stat": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@nodelib/fs.walk": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.scandir": "2.1.5",
+        "fastq": "^1.6.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/@rollup/pluginutils": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmmirror.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz",
+      "integrity": "sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "^1.0.0",
+        "estree-walker": "^2.0.2",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      },
+      "peerDependencies": {
+        "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0"
+      },
+      "peerDependenciesMeta": {
+        "rollup": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@rollup/rollup-android-arm-eabi": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz",
+      "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-android-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz",
+      "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "android"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz",
+      "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-darwin-x64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz",
+      "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz",
+      "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-freebsd-x64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz",
+      "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "freebsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz",
+      "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz",
+      "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==",
+      "cpu": [
+        "arm"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz",
+      "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-arm64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz",
+      "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz",
+      "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-loong64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz",
+      "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==",
+      "cpu": [
+        "loong64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz",
+      "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-ppc64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz",
+      "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==",
+      "cpu": [
+        "ppc64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz",
+      "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-riscv64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz",
+      "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==",
+      "cpu": [
+        "riscv64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-s390x-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz",
+      "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==",
+      "cpu": [
+        "s390x"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz",
+      "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-linux-x64-musl": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz",
+      "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "linux"
+      ]
+    },
+    "node_modules/@rollup/rollup-openbsd-x64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz",
+      "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openbsd"
+      ]
+    },
+    "node_modules/@rollup/rollup-openharmony-arm64": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz",
+      "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "openharmony"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-arm64-msvc": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz",
+      "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==",
+      "cpu": [
+        "arm64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-ia32-msvc": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz",
+      "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==",
+      "cpu": [
+        "ia32"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-gnu": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz",
+      "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz",
+      "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==",
+      "cpu": [
+        "x64"
+      ],
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.9",
+      "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.9.tgz",
+      "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==",
+      "license": "MIT"
+    },
+    "node_modules/@vitejs/plugin-basic-ssl": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-basic-ssl/-/plugin-basic-ssl-1.2.0.tgz",
+      "integrity": "sha512-mkQnxTkcldAzIsomk1UuLfAu9n+kpQ3JbHcpCp7d2Oo6ITtji8pHS3QToOWjhPFvNQSnhlkAjmGbhv2QvwO/7Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14.21.3"
+      },
+      "peerDependencies": {
+        "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0"
+      }
+    },
+    "node_modules/@vitejs/plugin-legacy": {
+      "version": "5.3.2",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-5.3.2.tgz",
+      "integrity": "sha512-8moCOrIMaZ/Rjln0Q6GsH6s8fAt1JOI3k8nmfX4tXUxE5KAExVctSyOBk+A25GClsdSWqIk2yaUthH3KJ2X4tg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/core": "^7.23.9",
+        "@babel/preset-env": "^7.23.9",
+        "browserslist": "^4.23.0",
+        "browserslist-to-esbuild": "^2.1.1",
+        "core-js": "^3.36.0",
+        "magic-string": "^0.30.7",
+        "regenerator-runtime": "^0.14.1",
+        "systemjs": "^6.14.3"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "peerDependencies": {
+        "terser": "^5.4.0",
+        "vite": "^5.0.0"
+      }
+    },
+    "node_modules/@vitejs/plugin-vue": {
+      "version": "5.2.4",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue/-/plugin-vue-5.2.4.tgz",
+      "integrity": "sha512-7Yx/SXSOcQq5HiiV3orevHUFn+pmMB4cgbEkDYgnkUWb0WfeQ/wa2yFv6D5ICiCQOVpjA7vYDXrC7AGO8yjDHA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^5.0.0 || ^6.0.0",
+        "vue": "^3.2.25"
+      }
+    },
+    "node_modules/@vitejs/plugin-vue-jsx": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-3.1.0.tgz",
+      "integrity": "sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/core": "^7.23.3",
+        "@babel/plugin-transform-typescript": "^7.23.3",
+        "@vue/babel-plugin-jsx": "^1.1.5"
+      },
+      "engines": {
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^4.0.0 || ^5.0.0",
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/@volar/language-core": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmmirror.com/@volar/language-core/-/language-core-2.4.15.tgz",
+      "integrity": "sha512-3VHw+QZU0ZG9IuQmzT68IyN4hZNd9GchGPhbD9+pa8CVv7rnoOZwo7T8weIbrRmihqy3ATpdfXFnqRrfPVK6CA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/source-map": "2.4.15"
+      }
+    },
+    "node_modules/@volar/source-map": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmmirror.com/@volar/source-map/-/source-map-2.4.15.tgz",
+      "integrity": "sha512-CPbMWlUN6hVZJYGcU/GSoHu4EnCHiLaXI9n8c9la6RaI9W5JHX+NqG+GSQcB0JdC2FIBLdZJwGsfKyBB71VlTg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@volar/typescript": {
+      "version": "2.4.15",
+      "resolved": "https://registry.npmmirror.com/@volar/typescript/-/typescript-2.4.15.tgz",
+      "integrity": "sha512-2aZ8i0cqPGjXb4BhkMsPYDkkuc2ZQ6yOpqwAuNwUoncELqoy5fRgOQtLR9gB0g902iS0NAkvpIzs27geVyVdPg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/language-core": "2.4.15",
+        "path-browserify": "^1.0.1",
+        "vscode-uri": "^3.0.8"
+      }
+    },
+    "node_modules/@vue/babel-helper-vue-transform-on": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz",
+      "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@vue/babel-plugin-jsx": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz",
+      "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-module-imports": "^7.27.1",
+        "@babel/helper-plugin-utils": "^7.27.1",
+        "@babel/plugin-syntax-jsx": "^7.27.1",
+        "@babel/template": "^7.27.2",
+        "@babel/traverse": "^7.28.0",
+        "@babel/types": "^7.28.2",
+        "@vue/babel-helper-vue-transform-on": "1.5.0",
+        "@vue/babel-plugin-resolve-type": "1.5.0",
+        "@vue/shared": "^3.5.18"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      },
+      "peerDependenciesMeta": {
+        "@babel/core": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue/babel-plugin-jsx/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@vue/babel-plugin-resolve-type": {
+      "version": "1.5.0",
+      "resolved": "https://registry.npmmirror.com/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz",
+      "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/code-frame": "^7.27.1",
+        "@babel/helper-module-imports": "^7.27.1",
+        "@babel/helper-plugin-utils": "^7.27.1",
+        "@babel/parser": "^7.28.0",
+        "@vue/compiler-sfc": "^3.5.18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sxzz"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-core": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
+      "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/shared": "3.5.34",
+        "entities": "^7.0.1",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-dom": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
+      "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-sfc": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz",
+      "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/compiler-core": "3.5.34",
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/compiler-ssr": "3.5.34",
+        "@vue/shared": "3.5.34",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.21",
+        "postcss": "^8.5.14",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-ssr": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
+      "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@vue/babel-plugin-resolve-type/node_modules/magic-string": {
+      "version": "0.30.21",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
+      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.4.21.tgz",
+      "integrity": "sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.23.9",
+        "@vue/shared": "3.4.21",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.0.2"
+      }
+    },
+    "node_modules/@vue/compiler-core/node_modules/entities": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-4.5.0.tgz",
+      "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.4.21.tgz",
+      "integrity": "sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.4.21",
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.4.21.tgz",
+      "integrity": "sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.23.9",
+        "@vue/compiler-core": "3.4.21",
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/compiler-ssr": "3.4.21",
+        "@vue/shared": "3.4.21",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.7",
+        "postcss": "^8.4.35",
+        "source-map-js": "^1.0.2"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.4.21.tgz",
+      "integrity": "sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.4.21",
+        "@vue/shared": "3.4.21"
+      }
+    },
+    "node_modules/@vue/compiler-vue2": {
+      "version": "2.7.16",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-vue2/-/compiler-vue2-2.7.16.tgz",
+      "integrity": "sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "de-indent": "^1.0.2",
+        "he": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.6.4",
+      "resolved": "https://registry.npmmirror.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz",
+      "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/language-core": {
+      "version": "2.2.12",
+      "resolved": "https://registry.npmmirror.com/@vue/language-core/-/language-core-2.2.12.tgz",
+      "integrity": "sha512-IsGljWbKGU1MZpBPN+BvPAdr55YPkj2nB/TBNGNC32Vy2qLG25DYu/NBN2vNtZqdRbTRjaoYrahLrToim2NanA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/language-core": "2.4.15",
+        "@vue/compiler-dom": "^3.5.0",
+        "@vue/compiler-vue2": "^2.7.16",
+        "@vue/shared": "^3.5.0",
+        "alien-signals": "^1.0.3",
+        "minimatch": "^9.0.3",
+        "muggle-string": "^0.4.1",
+        "path-browserify": "^1.0.1"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vue/language-core/node_modules/@vue/compiler-core": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
+      "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/shared": "3.5.34",
+        "entities": "^7.0.1",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/language-core/node_modules/@vue/compiler-dom": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
+      "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/language-core/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/reactivity/-/reactivity-3.5.34.tgz",
+      "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/reactivity/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-core/-/runtime-core-3.5.34.tgz",
+      "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/runtime-core/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz",
+      "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.34",
+        "@vue/runtime-core": "3.5.34",
+        "@vue/shared": "3.5.34",
+        "csstype": "^3.2.3"
+      }
+    },
+    "node_modules/@vue/runtime-dom/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/server-renderer/-/server-renderer-3.5.34.tgz",
+      "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.34",
+        "@vue/shared": "3.5.34"
+      },
+      "peerDependencies": {
+        "vue": "3.5.34"
+      }
+    },
+    "node_modules/@vue/server-renderer/node_modules/@vue/compiler-core": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
+      "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/shared": "3.5.34",
+        "entities": "^7.0.1",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/@vue/server-renderer/node_modules/@vue/compiler-dom": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
+      "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/server-renderer/node_modules/@vue/compiler-ssr": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
+      "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/@vue/server-renderer/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "license": "MIT"
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.4.21",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.4.21.tgz",
+      "integrity": "sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==",
+      "license": "MIT"
+    },
+    "node_modules/accepts": {
+      "version": "1.3.8",
+      "resolved": "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz",
+      "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "mime-types": "~2.1.34",
+        "negotiator": "0.6.3"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.16.0",
+      "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.16.0.tgz",
+      "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+      "license": "MIT",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/adm-zip": {
+      "version": "0.5.16",
+      "resolved": "https://registry.npmmirror.com/adm-zip/-/adm-zip-0.5.16.tgz",
+      "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.0"
+      }
+    },
+    "node_modules/agent-base": {
+      "version": "6.0.2",
+      "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz",
+      "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/alien-signals": {
+      "version": "1.0.13",
+      "resolved": "https://registry.npmmirror.com/alien-signals/-/alien-signals-1.0.13.tgz",
+      "integrity": "sha512-OGj9yyTnJEttvzhTUWuscOvtqxq5vrhF7vL9oS0xJ2mK0ItPYP1/y+vCFebfxoEyAz0++1AIwJ5CMr+Fk3nDmg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/ansi-styles": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-3.2.1.tgz",
+      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^1.9.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmmirror.com/anymatch/-/anymatch-3.1.3.tgz",
+      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+      "license": "ISC",
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/array-flatten": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/array-flatten/-/array-flatten-1.1.1.tgz",
+      "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmmirror.com/asynckit/-/asynckit-0.4.0.tgz",
+      "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+      "license": "MIT"
+    },
+    "node_modules/autoprefixer": {
+      "version": "10.4.20",
+      "resolved": "https://registry.npmmirror.com/autoprefixer/-/autoprefixer-10.4.20.tgz",
+      "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "browserslist": "^4.23.3",
+        "caniuse-lite": "^1.0.30001646",
+        "fraction.js": "^4.3.7",
+        "normalize-range": "^0.1.2",
+        "picocolors": "^1.0.1",
+        "postcss-value-parser": "^4.2.0"
+      },
+      "bin": {
+        "autoprefixer": "bin/autoprefixer"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/axios": {
+      "version": "1.16.1",
+      "resolved": "https://registry.npmmirror.com/axios/-/axios-1.16.1.tgz",
+      "integrity": "sha512-caYkukvroVPO8KrzuJEb50Hm07KwfBZPEC3VeFHTsqWHvKTsy54hjJz9BS/cdaypROE2rH6xvm9mHX4fgWkr3A==",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.16.0",
+        "form-data": "^4.0.5",
+        "https-proxy-agent": "^5.0.1",
+        "proxy-from-env": "^2.1.0"
+      }
+    },
+    "node_modules/babel-plugin-polyfill-corejs2": {
+      "version": "0.4.17",
+      "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz",
+      "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/compat-data": "^7.28.6",
+        "@babel/helper-define-polyfill-provider": "^0.6.8",
+        "semver": "^6.3.1"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+      }
+    },
+    "node_modules/babel-plugin-polyfill-corejs3": {
+      "version": "0.14.2",
+      "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz",
+      "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-define-polyfill-provider": "^0.6.8",
+        "core-js-compat": "^3.48.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+      }
+    },
+    "node_modules/babel-plugin-polyfill-regenerator": {
+      "version": "0.6.8",
+      "resolved": "https://registry.npmmirror.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz",
+      "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-define-polyfill-provider": "^0.6.8"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+      }
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/base64url": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/base64url/-/base64url-3.0.1.tgz",
+      "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/baseline-browser-mapping": {
+      "version": "2.10.32",
+      "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.32.tgz",
+      "integrity": "sha512-wbPvpyjJPC0zdfdKXxqEL3Ea+bOMD/87X4lftiJkkaBiuG6ALQy1SLmEd7BSmVCuwCQsBrCamgBoLyfFDD1EPg==",
+      "license": "Apache-2.0",
+      "bin": {
+        "baseline-browser-mapping": "dist/cli.cjs"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/binary-extensions/-/binary-extensions-2.3.0.tgz",
+      "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/body-parser": {
+      "version": "1.20.3",
+      "resolved": "https://registry.npmmirror.com/body-parser/-/body-parser-1.20.3.tgz",
+      "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "3.1.2",
+        "content-type": "~1.0.5",
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "http-errors": "2.0.0",
+        "iconv-lite": "0.4.24",
+        "on-finished": "2.4.1",
+        "qs": "6.13.0",
+        "raw-body": "2.5.2",
+        "type-is": "~1.6.18",
+        "unpipe": "1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/body-parser/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/body-parser/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/body-parser/node_modules/qs": {
+      "version": "6.13.0",
+      "resolved": "https://registry.npmmirror.com/qs/-/qs-6.13.0.tgz",
+      "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "side-channel": "^1.0.6"
+      },
+      "engines": {
+        "node": ">=0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.1.1.tgz",
+      "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+      "license": "MIT",
+      "dependencies": {
+        "fill-range": "^7.1.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/browserslist": {
+      "version": "4.28.2",
+      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.2.tgz",
+      "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "baseline-browser-mapping": "^2.10.12",
+        "caniuse-lite": "^1.0.30001782",
+        "electron-to-chromium": "^1.5.328",
+        "node-releases": "^2.0.36",
+        "update-browserslist-db": "^1.2.3"
+      },
+      "bin": {
+        "browserslist": "cli.js"
+      },
+      "engines": {
+        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+      }
+    },
+    "node_modules/browserslist-to-esbuild": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/browserslist-to-esbuild/-/browserslist-to-esbuild-2.1.1.tgz",
+      "integrity": "sha512-KN+mty6C3e9AN8Z5dI1xeN15ExcRNeISoC3g7V0Kax/MMF9MSoYA2G7lkTTcVUFntiEjkpI0HNgqJC1NjdyNUw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "meow": "^13.0.0"
+      },
+      "bin": {
+        "browserslist-to-esbuild": "cli/index.js"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "peerDependencies": {
+        "browserslist": "*"
+      }
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz",
+      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+      "devOptional": true,
+      "license": "MIT"
+    },
+    "node_modules/bytes": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmmirror.com/bytes/-/bytes-3.1.2.tgz",
+      "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/cac": {
+      "version": "6.7.9",
+      "resolved": "https://registry.npmmirror.com/cac/-/cac-6.7.9.tgz",
+      "integrity": "sha512-XN5qEpfNQCJ8jRaZgitSkkukjMRCGio+X3Ks5KUbGGlPbV+pSem1l9VuzooCBXOiMFshUZgyYqg6rgN8rjkb/w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+      "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/call-bound": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmmirror.com/call-bound/-/call-bound-1.0.4.tgz",
+      "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "get-intrinsic": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/caniuse-lite": {
+      "version": "1.0.30001793",
+      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
+      "integrity": "sha512-iwSsYWaCOoh26cV8NwNRViHlrfUvYsHDfRVcbtmw0Kg6PJIZZXwMkj1442FYLBGkeUf1juAsU3DTfxW579mrPA==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "CC-BY-4.0"
+    },
+    "node_modules/chalk": {
+      "version": "2.4.2",
+      "resolved": "https://registry.npmmirror.com/chalk/-/chalk-2.4.2.tgz",
+      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+      "license": "MIT",
+      "dependencies": {
+        "ansi-styles": "^3.2.1",
+        "escape-string-regexp": "^1.0.5",
+        "supports-color": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/chalk/node_modules/escape-string-regexp": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.0"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-3.6.0.tgz",
+      "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+      "license": "MIT",
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "funding": {
+        "url": "https://paulmillr.com/funding/"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-1.9.3.tgz",
+      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.3.tgz",
+      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+      "license": "MIT"
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/combined-stream/-/combined-stream-1.0.8.tgz",
+      "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/commander": {
+      "version": "2.20.3",
+      "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz",
+      "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+      "devOptional": true,
+      "license": "MIT"
+    },
+    "node_modules/compare-versions": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmmirror.com/compare-versions/-/compare-versions-3.6.0.tgz",
+      "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
+      "license": "MIT"
+    },
+    "node_modules/confbox": {
+      "version": "0.1.8",
+      "resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.1.8.tgz",
+      "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==",
+      "license": "MIT"
+    },
+    "node_modules/content-disposition": {
+      "version": "0.5.4",
+      "resolved": "https://registry.npmmirror.com/content-disposition/-/content-disposition-0.5.4.tgz",
+      "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "5.2.1"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/content-type": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/content-type/-/content-type-1.0.5.tgz",
+      "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/convert-source-map": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz",
+      "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+      "license": "MIT"
+    },
+    "node_modules/cookie": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmmirror.com/cookie/-/cookie-0.6.0.tgz",
+      "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/cookie-signature": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmmirror.com/cookie-signature/-/cookie-signature-1.0.6.tgz",
+      "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/core-js": {
+      "version": "3.49.0",
+      "resolved": "https://registry.npmmirror.com/core-js/-/core-js-3.49.0.tgz",
+      "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
+    "node_modules/core-js-compat": {
+      "version": "3.49.0",
+      "resolved": "https://registry.npmmirror.com/core-js-compat/-/core-js-compat-3.49.0.tgz",
+      "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "browserslist": "^4.28.1"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
+    "node_modules/core-js-pure": {
+      "version": "3.49.0",
+      "resolved": "https://registry.npmmirror.com/core-js-pure/-/core-js-pure-3.49.0.tgz",
+      "integrity": "sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
+      }
+    },
+    "node_modules/css-font-size-keywords": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/css-font-size-keywords/-/css-font-size-keywords-1.0.0.tgz",
+      "integrity": "sha512-Q+svMDbMlelgCfH/RVDKtTDaf5021O486ZThQPIpahnIjUkMUslC+WuOQSWTgGSrNCH08Y7tYNEmmy0hkfMI8Q==",
+      "license": "MIT"
+    },
+    "node_modules/css-font-stretch-keywords": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/css-font-stretch-keywords/-/css-font-stretch-keywords-1.0.1.tgz",
+      "integrity": "sha512-KmugPO2BNqoyp9zmBIUGwt58UQSfyk1X5DbOlkb2pckDXFSAfjsD5wenb88fNrD6fvS+vu90a/tsPpb9vb0SLg==",
+      "license": "MIT"
+    },
+    "node_modules/css-font-style-keywords": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/css-font-style-keywords/-/css-font-style-keywords-1.0.1.tgz",
+      "integrity": "sha512-0Fn0aTpcDktnR1RzaBYorIxQily85M2KXRpzmxQPgh8pxUN9Fcn00I8u9I3grNr1QXVgCl9T5Imx0ZwKU973Vg==",
+      "license": "MIT"
+    },
+    "node_modules/css-font-weight-keywords": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/css-font-weight-keywords/-/css-font-weight-keywords-1.0.0.tgz",
+      "integrity": "sha512-5So8/NH+oDD+EzsnF4iaG4ZFHQ3vaViePkL1ZbZ5iC/KrsCY+WHq/lvOgrtmuOQ9pBBZ1ADGpaf+A4lj1Z9eYA==",
+      "license": "MIT"
+    },
+    "node_modules/css-list-helpers": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/css-list-helpers/-/css-list-helpers-2.0.0.tgz",
+      "integrity": "sha512-9Bj8tZ0jWbAM3u/U6m/boAzAwLPwtjzFvwivr2piSvyVa3K3rChJzQy4RIHkNkKiZCHrEMWDJWtTR8UyVhdDnQ==",
+      "license": "MIT"
+    },
+    "node_modules/css-system-font-keywords": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/css-system-font-keywords/-/css-system-font-keywords-1.0.0.tgz",
+      "integrity": "sha512-1umTtVd/fXS25ftfjB71eASCrYhilmEsvDEI6wG/QplnmlfmVM5HkZ/ZX46DT5K3eblFPgLUHt5BRCb0YXkSFA==",
+      "license": "MIT"
+    },
+    "node_modules/cssesc": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/cssesc/-/cssesc-3.0.0.tgz",
+      "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+      "license": "MIT",
+      "bin": {
+        "cssesc": "bin/cssesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmmirror.com/csstype/-/csstype-3.2.3.tgz",
+      "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
+      "license": "MIT"
+    },
+    "node_modules/de-indent": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/de-indent/-/de-indent-1.0.2.tgz",
+      "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/debug": {
+      "version": "4.3.7",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-4.3.7.tgz",
+      "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/delayed-stream/-/delayed-stream-1.0.0.tgz",
+      "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/depd": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/depd/-/depd-2.0.0.tgz",
+      "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/destroy": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/destroy/-/destroy-1.2.0.tgz",
+      "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8",
+        "npm": "1.2.8000 || >= 1.4.16"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
+      "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/ee-first": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
+      "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/electron-to-chromium": {
+      "version": "1.5.361",
+      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.361.tgz",
+      "integrity": "sha512-Q6Hts7N9FnJc5LeGRINFvLhCI9xZmNtTDe5ZbcVezQz7cU4a8Aua3GH1b8J2XY8Al9PF+OCwYqhgsOOheMdvkA==",
+      "license": "ISC"
+    },
+    "node_modules/encodeurl": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-2.0.0.tgz",
+      "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/entities": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmmirror.com/entities/-/entities-7.0.1.tgz",
+      "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz",
+      "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz",
+      "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-module-lexer": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
+      "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
+      "license": "MIT"
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/es-object-atoms/-/es-object-atoms-1.1.2.tgz",
+      "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+      "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.20.2",
+      "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.20.2.tgz",
+      "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.20.2",
+        "@esbuild/android-arm": "0.20.2",
+        "@esbuild/android-arm64": "0.20.2",
+        "@esbuild/android-x64": "0.20.2",
+        "@esbuild/darwin-arm64": "0.20.2",
+        "@esbuild/darwin-x64": "0.20.2",
+        "@esbuild/freebsd-arm64": "0.20.2",
+        "@esbuild/freebsd-x64": "0.20.2",
+        "@esbuild/linux-arm": "0.20.2",
+        "@esbuild/linux-arm64": "0.20.2",
+        "@esbuild/linux-ia32": "0.20.2",
+        "@esbuild/linux-loong64": "0.20.2",
+        "@esbuild/linux-mips64el": "0.20.2",
+        "@esbuild/linux-ppc64": "0.20.2",
+        "@esbuild/linux-riscv64": "0.20.2",
+        "@esbuild/linux-s390x": "0.20.2",
+        "@esbuild/linux-x64": "0.20.2",
+        "@esbuild/netbsd-x64": "0.20.2",
+        "@esbuild/openbsd-x64": "0.20.2",
+        "@esbuild/sunos-x64": "0.20.2",
+        "@esbuild/win32-arm64": "0.20.2",
+        "@esbuild/win32-ia32": "0.20.2",
+        "@esbuild/win32-x64": "0.20.2"
+      }
+    },
+    "node_modules/escalade": {
+      "version": "3.2.0",
+      "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz",
+      "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-html": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/escape-html/-/escape-html-1.0.3.tgz",
+      "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
+      "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-2.0.2.tgz",
+      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+      "license": "MIT"
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/esutils/-/esutils-2.0.3.tgz",
+      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/etag": {
+      "version": "1.8.1",
+      "resolved": "https://registry.npmmirror.com/etag/-/etag-1.8.1.tgz",
+      "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/express": {
+      "version": "4.20.0",
+      "resolved": "https://registry.npmmirror.com/express/-/express-4.20.0.tgz",
+      "integrity": "sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "accepts": "~1.3.8",
+        "array-flatten": "1.1.1",
+        "body-parser": "1.20.3",
+        "content-disposition": "0.5.4",
+        "content-type": "~1.0.4",
+        "cookie": "0.6.0",
+        "cookie-signature": "1.0.6",
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "encodeurl": "~2.0.0",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "finalhandler": "1.2.0",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "merge-descriptors": "1.0.3",
+        "methods": "~1.1.2",
+        "on-finished": "2.4.1",
+        "parseurl": "~1.3.3",
+        "path-to-regexp": "0.1.10",
+        "proxy-addr": "~2.0.7",
+        "qs": "6.11.0",
+        "range-parser": "~1.2.1",
+        "safe-buffer": "5.2.1",
+        "send": "0.19.0",
+        "serve-static": "1.16.0",
+        "setprototypeof": "1.2.0",
+        "statuses": "2.0.1",
+        "type-is": "~1.6.18",
+        "utils-merge": "1.0.1",
+        "vary": "~1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.10.0"
+      }
+    },
+    "node_modules/express/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/express/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/exsolve": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/exsolve/-/exsolve-1.0.8.tgz",
+      "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==",
+      "license": "MIT"
+    },
+    "node_modules/fast-glob": {
+      "version": "3.3.3",
+      "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz",
+      "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+      "license": "MIT",
+      "dependencies": {
+        "@nodelib/fs.stat": "^2.0.2",
+        "@nodelib/fs.walk": "^1.2.3",
+        "glob-parent": "^5.1.2",
+        "merge2": "^1.3.0",
+        "micromatch": "^4.0.8"
+      },
+      "engines": {
+        "node": ">=8.6.0"
+      }
+    },
+    "node_modules/fastq": {
+      "version": "1.20.1",
+      "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz",
+      "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+      "license": "ISC",
+      "dependencies": {
+        "reusify": "^1.0.4"
+      }
+    },
+    "node_modules/fill-range": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+      "license": "MIT",
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/finalhandler": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/finalhandler/-/finalhandler-1.2.0.tgz",
+      "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "2.6.9",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "on-finished": "2.4.1",
+        "parseurl": "~1.3.3",
+        "statuses": "2.0.1",
+        "unpipe": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/finalhandler/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/finalhandler/node_modules/encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/finalhandler/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.16.0",
+      "resolved": "https://registry.npmmirror.com/follow-redirects/-/follow-redirects-1.16.0.tgz",
+      "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.5",
+      "resolved": "https://registry.npmmirror.com/form-data/-/form-data-4.0.5.tgz",
+      "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "hasown": "^2.0.2",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/forwarded": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmmirror.com/forwarded/-/forwarded-0.2.0.tgz",
+      "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fraction.js": {
+      "version": "4.3.7",
+      "resolved": "https://registry.npmmirror.com/fraction.js/-/fraction.js-4.3.7.tgz",
+      "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+      "license": "MIT",
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "type": "patreon",
+        "url": "https://github.com/sponsors/rawify"
+      }
+    },
+    "node_modules/fresh": {
+      "version": "0.5.2",
+      "resolved": "https://registry.npmmirror.com/fresh/-/fresh-0.5.2.tgz",
+      "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/fs-extra": {
+      "version": "10.1.0",
+      "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz",
+      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz",
+      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz",
+      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/generic-names": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/generic-names/-/generic-names-4.0.0.tgz",
+      "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==",
+      "license": "MIT",
+      "dependencies": {
+        "loader-utils": "^3.2.0"
+      }
+    },
+    "node_modules/gensync": {
+      "version": "1.0.0-beta.2",
+      "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz",
+      "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+      "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/get-proto/-/get-proto-1.0.1.tgz",
+      "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+      "license": "MIT",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "license": "ISC",
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
+      "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz",
+      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
+      "license": "ISC"
+    },
+    "node_modules/has-flag": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-3.0.0.tgz",
+      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/has-symbols/-/has-symbols-1.1.0.tgz",
+      "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+      "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hash-sum": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/hash-sum/-/hash-sum-2.0.0.tgz",
+      "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
+      "license": "MIT"
+    },
+    "node_modules/hasown": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/hasown/-/hasown-2.0.3.tgz",
+      "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/he": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/he/-/he-1.2.0.tgz",
+      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "he": "bin/he"
+      }
+    },
+    "node_modules/http-errors": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/http-errors/-/http-errors-2.0.0.tgz",
+      "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "depd": "2.0.0",
+        "inherits": "2.0.4",
+        "setprototypeof": "1.2.0",
+        "statuses": "2.0.1",
+        "toidentifier": "1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/https-proxy-agent": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+      "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+      "license": "MIT",
+      "dependencies": {
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/iconv-lite": {
+      "version": "0.4.24",
+      "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz",
+      "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/icss-replace-symbols": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz",
+      "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==",
+      "license": "ISC"
+    },
+    "node_modules/icss-utils": {
+      "version": "5.1.0",
+      "resolved": "https://registry.npmmirror.com/icss-utils/-/icss-utils-5.1.0.tgz",
+      "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
+      "license": "ISC",
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/invert-kv": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmmirror.com/invert-kv/-/invert-kv-3.0.1.tgz",
+      "integrity": "sha512-CYdFeFexxhv/Bcny+Q0BfOV+ltRlJcd4BBZBYFX/O0u4npJrgZtIcjokegtiSMAvlMTJ+Koq0GBCc//3bueQxw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/invert-kv?sponsor=1"
+      }
+    },
+    "node_modules/ipaddr.js": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmmirror.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+      "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "license": "MIT",
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.16.2",
+      "resolved": "https://registry.npmmirror.com/is-core-module/-/is-core-module-2.16.2.tgz",
+      "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+      "license": "MIT",
+      "dependencies": {
+        "hasown": "^2.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
+      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+      "license": "MIT",
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/isbinaryfile": {
+      "version": "5.0.2",
+      "resolved": "https://registry.npmmirror.com/isbinaryfile/-/isbinaryfile-5.0.2.tgz",
+      "integrity": "sha512-GvcjojwonMjWbTkfMpnVHVqXW/wKMYDfEpY94/8zy8HFMOqb/VL6oeONq9v87q4ttVlaTLnGXnJD4B5B1OTGIg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 18.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/gjtorikian/"
+      }
+    },
+    "node_modules/js-tokens": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz",
+      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
+      "license": "MIT"
+    },
+    "node_modules/jsesc": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz",
+      "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
+      "license": "MIT",
+      "bin": {
+        "jsesc": "bin/jsesc"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz",
+      "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsonc-parser": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.3.1.tgz",
+      "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==",
+      "license": "MIT"
+    },
+    "node_modules/jsonfile": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.1.tgz",
+      "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
+      "license": "MIT",
+      "dependencies": {
+        "universalify": "^2.0.0"
+      },
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/lcid": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/lcid/-/lcid-3.1.1.tgz",
+      "integrity": "sha512-M6T051+5QCGLBQb8id3hdvIW8+zeFV2FyBGFS9IEK5H9Wt4MueD4bW1eWikpHgZp+5xR3l5c8pZUkQsIA0BFZg==",
+      "license": "MIT",
+      "dependencies": {
+        "invert-kv": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/lilconfig": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/lilconfig/-/lilconfig-2.1.0.tgz",
+      "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/lines-and-columns": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmmirror.com/lines-and-columns/-/lines-and-columns-2.0.4.tgz",
+      "integrity": "sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A==",
+      "license": "MIT",
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      }
+    },
+    "node_modules/loader-utils": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/loader-utils/-/loader-utils-3.3.1.tgz",
+      "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 12.13.0"
+      }
+    },
+    "node_modules/local-pkg": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/local-pkg/-/local-pkg-1.2.1.tgz",
+      "integrity": "sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==",
+      "license": "MIT",
+      "dependencies": {
+        "mlly": "^1.7.4",
+        "pkg-types": "^2.3.0",
+        "quansync": "^0.2.11"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/local-pkg/node_modules/confbox": {
+      "version": "0.2.4",
+      "resolved": "https://registry.npmmirror.com/confbox/-/confbox-0.2.4.tgz",
+      "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==",
+      "license": "MIT"
+    },
+    "node_modules/local-pkg/node_modules/pkg-types": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-2.3.1.tgz",
+      "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==",
+      "license": "MIT",
+      "dependencies": {
+        "confbox": "^0.2.4",
+        "exsolve": "^1.0.8",
+        "pathe": "^2.0.3"
+      }
+    },
+    "node_modules/localstorage-polyfill": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/localstorage-polyfill/-/localstorage-polyfill-1.0.1.tgz",
+      "integrity": "sha512-m4iHVZxFH5734oQcPKU08025gIz2+4bjWR9lulP8ZYxEJR0BpA0w32oJmkzh8y3UI9ci7xCBehQDc3oA1X+VHw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/lodash.camelcase": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+      "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+      "license": "MIT"
+    },
+    "node_modules/lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/lru-cache": {
+      "version": "5.1.1",
+      "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^3.0.2"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.11",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.11.tgz",
+      "integrity": "sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+      "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/media-typer": {
+      "version": "0.3.0",
+      "resolved": "https://registry.npmmirror.com/media-typer/-/media-typer-0.3.0.tgz",
+      "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/meow": {
+      "version": "13.2.0",
+      "resolved": "https://registry.npmmirror.com/meow/-/meow-13.2.0.tgz",
+      "integrity": "sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/merge": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/merge/-/merge-2.1.1.tgz",
+      "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==",
+      "license": "MIT"
+    },
+    "node_modules/merge-descriptors": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+      "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/merge2": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz",
+      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/methods": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/methods/-/methods-1.1.2.tgz",
+      "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/micromatch": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz",
+      "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+      "license": "MIT",
+      "dependencies": {
+        "braces": "^3.0.3",
+        "picomatch": "^2.3.1"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/mime": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/mime/-/mime-3.0.0.tgz",
+      "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+      "license": "MIT",
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz",
+      "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz",
+      "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "9.0.9",
+      "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz",
+      "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.2"
+      },
+      "engines": {
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/mlly": {
+      "version": "1.8.2",
+      "resolved": "https://registry.npmmirror.com/mlly/-/mlly-1.8.2.tgz",
+      "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==",
+      "license": "MIT",
+      "dependencies": {
+        "acorn": "^8.16.0",
+        "pathe": "^2.0.3",
+        "pkg-types": "^1.3.1",
+        "ufo": "^1.6.3"
+      }
+    },
+    "node_modules/module-alias": {
+      "version": "2.2.3",
+      "resolved": "https://registry.npmmirror.com/module-alias/-/module-alias-2.2.3.tgz",
+      "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
+      "license": "MIT"
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
+      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+      "license": "MIT"
+    },
+    "node_modules/muggle-string": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmmirror.com/muggle-string/-/muggle-string-0.4.1.tgz",
+      "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.12",
+      "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.12.tgz",
+      "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/negotiator": {
+      "version": "0.6.3",
+      "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.3.tgz",
+      "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/node-releases": {
+      "version": "2.0.46",
+      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.46.tgz",
+      "integrity": "sha512-GYVXHE2KnrzAfsAjl4uP++evGFCrAU1jta4ubEjIG7YWt/64Gqv66a30yKwWczVjA6j3bM4nBwH7Pk1JmDHaxQ==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/normalize-range": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmmirror.com/normalize-range/-/normalize-range-0.1.2.tgz",
+      "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/object-inspect": {
+      "version": "1.13.4",
+      "resolved": "https://registry.npmmirror.com/object-inspect/-/object-inspect-1.13.4.tgz",
+      "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/on-finished": {
+      "version": "2.4.1",
+      "resolved": "https://registry.npmmirror.com/on-finished/-/on-finished-2.4.1.tgz",
+      "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ee-first": "1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/os-locale-s-fix": {
+      "version": "1.0.8-fix-1",
+      "resolved": "https://registry.npmmirror.com/os-locale-s-fix/-/os-locale-s-fix-1.0.8-fix-1.tgz",
+      "integrity": "sha512-Sv0OvhPiMutICiwORAUefv02DCPb62IelBmo8ZsSrRHyI3FStqIWZvjqDkvtjU+lcujo7UNir+dCwKSqlEQ/5w==",
+      "license": "MIT",
+      "dependencies": {
+        "lcid": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10",
+        "yarn": "^1.22.4"
+      }
+    },
+    "node_modules/parse-css-font": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/parse-css-font/-/parse-css-font-4.0.0.tgz",
+      "integrity": "sha512-lnY7dTUfjRXsSo5G5C639L8RaBBaVSgL+5hacIFKsNHzeCJQ5SFSZv1DZmc7+wZv/22PFGOq2YbaEHLdaCS/mQ==",
+      "license": "MIT",
+      "dependencies": {
+        "css-font-size-keywords": "^1.0.0",
+        "css-font-stretch-keywords": "^1.0.1",
+        "css-font-style-keywords": "^1.0.1",
+        "css-font-weight-keywords": "^1.0.0",
+        "css-list-helpers": "^2.0.0",
+        "css-system-font-keywords": "^1.0.0",
+        "unquote": "^1.1.1"
+      }
+    },
+    "node_modules/parseurl": {
+      "version": "1.3.3",
+      "resolved": "https://registry.npmmirror.com/parseurl/-/parseurl-1.3.3.tgz",
+      "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/path-browserify": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/path-browserify/-/path-browserify-1.0.1.tgz",
+      "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "license": "MIT"
+    },
+    "node_modules/path-to-regexp": {
+      "version": "0.1.10",
+      "resolved": "https://registry.npmmirror.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz",
+      "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/pathe": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/pathe/-/pathe-2.0.3.tgz",
+      "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
+      "license": "MIT"
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.0.tgz",
+      "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==",
+      "license": "ISC"
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.2.tgz",
+      "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/pify": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz",
+      "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/pinia": {
+      "version": "2.3.1",
+      "resolved": "https://registry.npmmirror.com/pinia/-/pinia-2.3.1.tgz",
+      "integrity": "sha512-khUlZSwt9xXCaTbbxFYBKDc/bWAGWJjOgvxETwkTN7KRm66EeT1ZdZj6i2ceh9sP2Pzqsbc704r2yngBrxBVug==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.3",
+        "vue-demi": "^0.14.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.4.4",
+        "vue": "^2.7.0 || ^3.5.11"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pkg-types": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmmirror.com/pkg-types/-/pkg-types-1.3.1.tgz",
+      "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==",
+      "license": "MIT",
+      "dependencies": {
+        "confbox": "^0.1.8",
+        "mlly": "^1.7.4",
+        "pathe": "^2.0.1"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.15",
+      "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.15.tgz",
+      "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.12",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/postcss-import": {
+      "version": "14.1.0",
+      "resolved": "https://registry.npmmirror.com/postcss-import/-/postcss-import-14.1.0.tgz",
+      "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==",
+      "license": "MIT",
+      "dependencies": {
+        "postcss-value-parser": "^4.0.0",
+        "read-cache": "^1.0.0",
+        "resolve": "^1.1.7"
+      },
+      "engines": {
+        "node": ">=10.0.0"
+      },
+      "peerDependencies": {
+        "postcss": "^8.0.0"
+      }
+    },
+    "node_modules/postcss-load-config": {
+      "version": "3.1.4",
+      "resolved": "https://registry.npmmirror.com/postcss-load-config/-/postcss-load-config-3.1.4.tgz",
+      "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==",
+      "license": "MIT",
+      "dependencies": {
+        "lilconfig": "^2.0.5",
+        "yaml": "^1.10.2"
+      },
+      "engines": {
+        "node": ">= 10"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/postcss/"
+      },
+      "peerDependencies": {
+        "postcss": ">=8.0.9",
+        "ts-node": ">=9.0.0"
+      },
+      "peerDependenciesMeta": {
+        "postcss": {
+          "optional": true
+        },
+        "ts-node": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/postcss-modules": {
+      "version": "4.3.1",
+      "resolved": "https://registry.npmmirror.com/postcss-modules/-/postcss-modules-4.3.1.tgz",
+      "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==",
+      "license": "MIT",
+      "dependencies": {
+        "generic-names": "^4.0.0",
+        "icss-replace-symbols": "^1.1.0",
+        "lodash.camelcase": "^4.3.0",
+        "postcss-modules-extract-imports": "^3.0.0",
+        "postcss-modules-local-by-default": "^4.0.0",
+        "postcss-modules-scope": "^3.0.0",
+        "postcss-modules-values": "^4.0.0",
+        "string-hash": "^1.1.1"
+      },
+      "peerDependencies": {
+        "postcss": "^8.0.0"
+      }
+    },
+    "node_modules/postcss-modules-extract-imports": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz",
+      "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==",
+      "license": "ISC",
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-modules-local-by-default": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz",
+      "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==",
+      "license": "MIT",
+      "dependencies": {
+        "icss-utils": "^5.0.0",
+        "postcss-selector-parser": "^7.0.0",
+        "postcss-value-parser": "^4.1.0"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+      "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
+      "license": "MIT",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postcss-modules-scope": {
+      "version": "3.2.1",
+      "resolved": "https://registry.npmmirror.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz",
+      "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==",
+      "license": "ISC",
+      "dependencies": {
+        "postcss-selector-parser": "^7.0.0"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": {
+      "version": "7.1.1",
+      "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+      "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
+      "license": "MIT",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postcss-modules-values": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
+      "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
+      "license": "ISC",
+      "dependencies": {
+        "icss-utils": "^5.0.0"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >= 14"
+      },
+      "peerDependencies": {
+        "postcss": "^8.1.0"
+      }
+    },
+    "node_modules/postcss-selector-parser": {
+      "version": "6.1.2",
+      "resolved": "https://registry.npmmirror.com/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+      "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+      "license": "MIT",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postcss-value-parser": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmmirror.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+      "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
+      "license": "MIT"
+    },
+    "node_modules/postcss/node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/proxy-addr": {
+      "version": "2.0.7",
+      "resolved": "https://registry.npmmirror.com/proxy-addr/-/proxy-addr-2.0.7.tgz",
+      "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "forwarded": "0.2.0",
+        "ipaddr.js": "1.9.1"
+      },
+      "engines": {
+        "node": ">= 0.10"
+      }
+    },
+    "node_modules/proxy-from-env": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+      "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/qs": {
+      "version": "6.11.0",
+      "resolved": "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz",
+      "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "side-channel": "^1.0.4"
+      },
+      "engines": {
+        "node": ">=0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/quansync": {
+      "version": "0.2.11",
+      "resolved": "https://registry.npmmirror.com/quansync/-/quansync-0.2.11.tgz",
+      "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/antfu"
+        },
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/sxzz"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/queue-microtask": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz",
+      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/range-parser": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/range-parser/-/range-parser-1.2.1.tgz",
+      "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/raw-body": {
+      "version": "2.5.2",
+      "resolved": "https://registry.npmmirror.com/raw-body/-/raw-body-2.5.2.tgz",
+      "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "bytes": "3.1.2",
+        "http-errors": "2.0.0",
+        "iconv-lite": "0.4.24",
+        "unpipe": "1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/read-cache": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/read-cache/-/read-cache-1.0.0.tgz",
+      "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+      "license": "MIT",
+      "dependencies": {
+        "pify": "^2.3.0"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "license": "MIT",
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/regenerate": {
+      "version": "1.4.2",
+      "resolved": "https://registry.npmmirror.com/regenerate/-/regenerate-1.4.2.tgz",
+      "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/regenerate-unicode-properties": {
+      "version": "10.2.2",
+      "resolved": "https://registry.npmmirror.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz",
+      "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "regenerate": "^1.4.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/regenerator-runtime": {
+      "version": "0.14.1",
+      "resolved": "https://registry.npmmirror.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+      "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/regexpu-core": {
+      "version": "6.4.0",
+      "resolved": "https://registry.npmmirror.com/regexpu-core/-/regexpu-core-6.4.0.tgz",
+      "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "regenerate": "^1.4.2",
+        "regenerate-unicode-properties": "^10.2.2",
+        "regjsgen": "^0.8.0",
+        "regjsparser": "^0.13.0",
+        "unicode-match-property-ecmascript": "^2.0.0",
+        "unicode-match-property-value-ecmascript": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/regjsgen": {
+      "version": "0.8.0",
+      "resolved": "https://registry.npmmirror.com/regjsgen/-/regjsgen-0.8.0.tgz",
+      "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/regjsparser": {
+      "version": "0.13.1",
+      "resolved": "https://registry.npmmirror.com/regjsparser/-/regjsparser-0.13.1.tgz",
+      "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "jsesc": "~3.1.0"
+      },
+      "bin": {
+        "regjsparser": "bin/parser"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.22.8",
+      "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.8.tgz",
+      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+      "license": "MIT",
+      "dependencies": {
+        "is-core-module": "^2.13.0",
+        "path-parse": "^1.0.7",
+        "supports-preserve-symlinks-flag": "^1.0.0"
+      },
+      "bin": {
+        "resolve": "bin/resolve"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/reusify": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz",
+      "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+      "license": "MIT",
+      "engines": {
+        "iojs": ">=1.0.0",
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/rollup": {
+      "version": "4.60.4",
+      "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.60.4.tgz",
+      "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "1.0.8"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.60.4",
+        "@rollup/rollup-android-arm64": "4.60.4",
+        "@rollup/rollup-darwin-arm64": "4.60.4",
+        "@rollup/rollup-darwin-x64": "4.60.4",
+        "@rollup/rollup-freebsd-arm64": "4.60.4",
+        "@rollup/rollup-freebsd-x64": "4.60.4",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.60.4",
+        "@rollup/rollup-linux-arm-musleabihf": "4.60.4",
+        "@rollup/rollup-linux-arm64-gnu": "4.60.4",
+        "@rollup/rollup-linux-arm64-musl": "4.60.4",
+        "@rollup/rollup-linux-loong64-gnu": "4.60.4",
+        "@rollup/rollup-linux-loong64-musl": "4.60.4",
+        "@rollup/rollup-linux-ppc64-gnu": "4.60.4",
+        "@rollup/rollup-linux-ppc64-musl": "4.60.4",
+        "@rollup/rollup-linux-riscv64-gnu": "4.60.4",
+        "@rollup/rollup-linux-riscv64-musl": "4.60.4",
+        "@rollup/rollup-linux-s390x-gnu": "4.60.4",
+        "@rollup/rollup-linux-x64-gnu": "4.60.4",
+        "@rollup/rollup-linux-x64-musl": "4.60.4",
+        "@rollup/rollup-openbsd-x64": "4.60.4",
+        "@rollup/rollup-openharmony-arm64": "4.60.4",
+        "@rollup/rollup-win32-arm64-msvc": "4.60.4",
+        "@rollup/rollup-win32-ia32-msvc": "4.60.4",
+        "@rollup/rollup-win32-x64-gnu": "4.60.4",
+        "@rollup/rollup-win32-x64-msvc": "4.60.4",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/rollup/node_modules/@types/estree": {
+      "version": "1.0.8",
+      "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz",
+      "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+      "license": "MIT"
+    },
+    "node_modules/run-parallel": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz",
+      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "queue-microtask": "^1.2.2"
+      }
+    },
+    "node_modules/safe-area-insets": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmmirror.com/safe-area-insets/-/safe-area-insets-1.4.1.tgz",
+      "integrity": "sha512-r/nRWTjFGhhm3w1Z6Kd/jY11srN+lHt2mNl1E/emQGW8ic7n3Avu4noibklfSM+Y34peNphHD/BSZecav0sXYQ==",
+      "license": "ISC"
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.2.1",
+      "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz",
+      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz",
+      "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/scule": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmmirror.com/scule/-/scule-1.3.0.tgz",
+      "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==",
+      "license": "MIT"
+    },
+    "node_modules/semver": {
+      "version": "6.3.1",
+      "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz",
+      "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/send": {
+      "version": "0.19.0",
+      "resolved": "https://registry.npmmirror.com/send/-/send-0.19.0.tgz",
+      "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "mime": "1.6.0",
+        "ms": "2.1.3",
+        "on-finished": "2.4.1",
+        "range-parser": "~1.2.1",
+        "statuses": "2.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/send/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/send/node_modules/debug/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/send/node_modules/encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/send/node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/serve-static": {
+      "version": "1.16.0",
+      "resolved": "https://registry.npmmirror.com/serve-static/-/serve-static-1.16.0.tgz",
+      "integrity": "sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "parseurl": "~1.3.3",
+        "send": "0.18.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/serve-static/node_modules/debug": {
+      "version": "2.6.9",
+      "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz",
+      "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/serve-static/node_modules/debug/node_modules/ms": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz",
+      "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/serve-static/node_modules/encodeurl": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz",
+      "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/serve-static/node_modules/mime": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/mime/-/mime-1.6.0.tgz",
+      "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/serve-static/node_modules/send": {
+      "version": "0.18.0",
+      "resolved": "https://registry.npmmirror.com/send/-/send-0.18.0.tgz",
+      "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "2.6.9",
+        "depd": "2.0.0",
+        "destroy": "1.2.0",
+        "encodeurl": "~1.0.2",
+        "escape-html": "~1.0.3",
+        "etag": "~1.8.1",
+        "fresh": "0.5.2",
+        "http-errors": "2.0.0",
+        "mime": "1.6.0",
+        "ms": "2.1.3",
+        "on-finished": "2.4.1",
+        "range-parser": "~1.2.1",
+        "statuses": "2.0.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/setprototypeof": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmmirror.com/setprototypeof/-/setprototypeof-1.2.0.tgz",
+      "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/side-channel": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/side-channel/-/side-channel-1.1.0.tgz",
+      "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.3",
+        "side-channel-list": "^1.0.0",
+        "side-channel-map": "^1.0.1",
+        "side-channel-weakmap": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-list": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/side-channel-list/-/side-channel-list-1.0.1.tgz",
+      "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "object-inspect": "^1.13.4"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-map": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/side-channel-map/-/side-channel-map-1.0.1.tgz",
+      "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/side-channel-weakmap": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+      "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "call-bound": "^1.0.2",
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.5",
+        "object-inspect": "^1.13.3",
+        "side-channel-map": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/source-map": {
+      "version": "0.6.1",
+      "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",
+      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz",
+      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz",
+      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+      "devOptional": true,
+      "license": "MIT",
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/statuses": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/statuses/-/statuses-2.0.1.tgz",
+      "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/string-hash": {
+      "version": "1.1.3",
+      "resolved": "https://registry.npmmirror.com/string-hash/-/string-hash-1.1.3.tgz",
+      "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==",
+      "license": "CC0-1.0"
+    },
+    "node_modules/strip-literal": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/strip-literal/-/strip-literal-3.1.0.tgz",
+      "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
+      "license": "MIT",
+      "dependencies": {
+        "js-tokens": "^9.0.1"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/strip-literal/node_modules/js-tokens": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-9.0.1.tgz",
+      "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
+      "license": "MIT"
+    },
+    "node_modules/supports-color": {
+      "version": "5.5.0",
+      "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-5.5.0.tgz",
+      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/supports-preserve-symlinks-flag": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/systemjs": {
+      "version": "6.15.1",
+      "resolved": "https://registry.npmmirror.com/systemjs/-/systemjs-6.15.1.tgz",
+      "integrity": "sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/tapable": {
+      "version": "2.3.3",
+      "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.3.3.tgz",
+      "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/terser": {
+      "version": "5.48.0",
+      "resolved": "https://registry.npmmirror.com/terser/-/terser-5.48.0.tgz",
+      "integrity": "sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==",
+      "devOptional": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.15.0",
+        "commander": "^2.20.0",
+        "source-map-support": "~0.5.20"
+      },
+      "bin": {
+        "terser": "bin/terser"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/tinycolor2": {
+      "version": "1.6.0",
+      "resolved": "https://registry.npmmirror.com/tinycolor2/-/tinycolor2-1.6.0.tgz",
+      "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
+      "license": "MIT"
+    },
+    "node_modules/to-fast-properties": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
+      "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "license": "MIT",
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/toidentifier": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/toidentifier/-/toidentifier-1.0.1.tgz",
+      "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.6"
+      }
+    },
+    "node_modules/type-is": {
+      "version": "1.6.18",
+      "resolved": "https://registry.npmmirror.com/type-is/-/type-is-1.6.18.tgz",
+      "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "media-typer": "0.3.0",
+        "mime-types": "~2.1.24"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "5.9.3",
+      "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.9.3.tgz",
+      "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+      "devOptional": true,
+      "license": "Apache-2.0",
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
+      }
+    },
+    "node_modules/ufo": {
+      "version": "1.6.4",
+      "resolved": "https://registry.npmmirror.com/ufo/-/ufo-1.6.4.tgz",
+      "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==",
+      "license": "MIT"
+    },
+    "node_modules/unicode-canonical-property-names-ecmascript": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
+      "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/unicode-match-property-ecmascript": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+      "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "unicode-canonical-property-names-ecmascript": "^2.0.0",
+        "unicode-property-aliases-ecmascript": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/unicode-match-property-value-ecmascript": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmmirror.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz",
+      "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/unicode-property-aliases-ecmascript": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz",
+      "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/unimport": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/unimport/-/unimport-4.1.1.tgz",
+      "integrity": "sha512-j9+fijH6aDd05yv1fXlyt7HSxtOWtGtrZeYTVBsSUg57Iuf+Ps2itIZjeyu7bEQ4k0WOgYhHrdW8m/pJgOpl5g==",
+      "license": "MIT",
+      "dependencies": {
+        "acorn": "^8.14.0",
+        "escape-string-regexp": "^5.0.0",
+        "estree-walker": "^3.0.3",
+        "fast-glob": "^3.3.3",
+        "local-pkg": "^1.0.0",
+        "magic-string": "^0.30.17",
+        "mlly": "^1.7.4",
+        "pathe": "^2.0.2",
+        "picomatch": "^4.0.2",
+        "pkg-types": "^1.3.1",
+        "scule": "^1.3.0",
+        "strip-literal": "^3.0.0",
+        "unplugin": "^2.1.2",
+        "unplugin-utils": "^0.2.3"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      }
+    },
+    "node_modules/unimport/node_modules/estree-walker": {
+      "version": "3.0.3",
+      "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz",
+      "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "^1.0.0"
+      }
+    },
+    "node_modules/unimport/node_modules/magic-string": {
+      "version": "0.30.21",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
+      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/unimport/node_modules/picomatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
+      "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/universalify": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz",
+      "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
+    "node_modules/unpipe": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/unpipe/-/unpipe-1.0.0.tgz",
+      "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/unplugin": {
+      "version": "2.3.11",
+      "resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-2.3.11.tgz",
+      "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/remapping": "^2.3.5",
+        "acorn": "^8.15.0",
+        "picomatch": "^4.0.3",
+        "webpack-virtual-modules": "^0.6.2"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      }
+    },
+    "node_modules/unplugin-auto-import": {
+      "version": "19.1.0",
+      "resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-19.1.0.tgz",
+      "integrity": "sha512-B+TGBEBHqY9aR+7YfShfLujETOHstzpV+yaqgy5PkfV0QG7Py+TYMX7vJ9W4SrysHR+UzR+gzcx/nuZjmPeclA==",
+      "license": "MIT",
+      "dependencies": {
+        "local-pkg": "^1.0.0",
+        "magic-string": "^0.30.17",
+        "picomatch": "^4.0.2",
+        "unimport": "^4.1.1",
+        "unplugin": "^2.2.0",
+        "unplugin-utils": "^0.2.4"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@nuxt/kit": "^3.2.2",
+        "@vueuse/core": "*"
+      },
+      "peerDependenciesMeta": {
+        "@nuxt/kit": {
+          "optional": true
+        },
+        "@vueuse/core": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/unplugin-auto-import/node_modules/magic-string": {
+      "version": "0.30.21",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
+      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/unplugin-auto-import/node_modules/picomatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
+      "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/unplugin-utils": {
+      "version": "0.2.5",
+      "resolved": "https://registry.npmmirror.com/unplugin-utils/-/unplugin-utils-0.2.5.tgz",
+      "integrity": "sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg==",
+      "license": "MIT",
+      "dependencies": {
+        "pathe": "^2.0.3",
+        "picomatch": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sxzz"
+      }
+    },
+    "node_modules/unplugin-utils/node_modules/picomatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
+      "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/unplugin/node_modules/picomatch": {
+      "version": "4.0.4",
+      "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.4.tgz",
+      "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/unquote": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/unquote/-/unquote-1.1.1.tgz",
+      "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==",
+      "license": "MIT"
+    },
+    "node_modules/update-browserslist-db": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+      "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/browserslist"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/browserslist"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "escalade": "^3.2.0",
+        "picocolors": "^1.1.1"
+      },
+      "bin": {
+        "update-browserslist-db": "cli.js"
+      },
+      "peerDependencies": {
+        "browserslist": ">= 4.21.0"
+      }
+    },
+    "node_modules/update-browserslist-db/node_modules/picocolors": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz",
+      "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+      "license": "ISC"
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz",
+      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+      "license": "MIT"
+    },
+    "node_modules/utils-merge": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/utils-merge/-/utils-merge-1.0.1.tgz",
+      "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/vary": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz",
+      "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/vite": {
+      "version": "5.2.8",
+      "resolved": "https://registry.npmmirror.com/vite/-/vite-5.2.8.tgz",
+      "integrity": "sha512-OyZR+c1CE8yeHw5V5t59aXsUPPVTHMDjEZz8MgguLL/Q7NblxhZUlTu9xSPqlsUO/y+X7dlU05jdhvyycD55DA==",
+      "license": "MIT",
+      "dependencies": {
+        "esbuild": "^0.20.1",
+        "postcss": "^8.4.38",
+        "rollup": "^4.13.0"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^18.0.0 || >=20.0.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.4.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vscode-uri": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/vscode-uri/-/vscode-uri-3.1.0.tgz",
+      "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/vue": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/vue/-/vue-3.5.34.tgz",
+      "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/compiler-sfc": "3.5.34",
+        "@vue/runtime-dom": "3.5.34",
+        "@vue/server-renderer": "3.5.34",
+        "@vue/shared": "3.5.34"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-demi": {
+      "version": "0.14.10",
+      "resolved": "https://registry.npmmirror.com/vue-demi/-/vue-demi-0.14.10.tgz",
+      "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.4.4",
+      "resolved": "https://registry.npmmirror.com/vue-router/-/vue-router-4.4.4.tgz",
+      "integrity": "sha512-3MlnDqwRwZwCQVbtVfpsU+nrNymNjnXSsQtXName5925NVC1+326VVfYH9vSrA0N13teGEo8z5x7gbRnGjCDiQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/vue-tsc": {
+      "version": "2.2.12",
+      "resolved": "https://registry.npmmirror.com/vue-tsc/-/vue-tsc-2.2.12.tgz",
+      "integrity": "sha512-P7OP77b2h/Pmk+lZdJ0YWs+5tJ6J2+uOQPo7tlBnY44QqQSPYvS0qVT4wqDJgwrZaLe47etJLLQRFia71GYITw==",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@volar/typescript": "2.4.15",
+        "@vue/language-core": "2.2.12"
+      },
+      "bin": {
+        "vue-tsc": "bin/vue-tsc.js"
+      },
+      "peerDependencies": {
+        "typescript": ">=5.0.0"
+      }
+    },
+    "node_modules/vue/node_modules/@vue/compiler-core": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
+      "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/shared": "3.5.34",
+        "entities": "^7.0.1",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/vue/node_modules/@vue/compiler-dom": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
+      "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/vue/node_modules/@vue/compiler-sfc": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz",
+      "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.29.3",
+        "@vue/compiler-core": "3.5.34",
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/compiler-ssr": "3.5.34",
+        "@vue/shared": "3.5.34",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.21",
+        "postcss": "^8.5.14",
+        "source-map-js": "^1.2.1"
+      }
+    },
+    "node_modules/vue/node_modules/@vue/compiler-ssr": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
+      "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.34",
+        "@vue/shared": "3.5.34"
+      }
+    },
+    "node_modules/vue/node_modules/@vue/shared": {
+      "version": "3.5.34",
+      "resolved": "https://registry.npmmirror.com/@vue/shared/-/shared-3.5.34.tgz",
+      "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+      "license": "MIT"
+    },
+    "node_modules/vue/node_modules/magic-string": {
+      "version": "0.30.21",
+      "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.21.tgz",
+      "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.5"
+      }
+    },
+    "node_modules/webpack-virtual-modules": {
+      "version": "0.6.2",
+      "resolved": "https://registry.npmmirror.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz",
+      "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==",
+      "license": "MIT"
+    },
+    "node_modules/xmlhttprequest": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmmirror.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz",
+      "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/xregexp": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/xregexp/-/xregexp-5.1.2.tgz",
+      "integrity": "sha512-6hGgEMCGhqCTFEJbqmWrNIPqfpdirdGWkqshu7fFZddmTSfgv5Sn9D2SaKloR79s5VUiUlpwzg3CM3G6D3VIlw==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/runtime-corejs3": "^7.26.9"
+      }
+    },
+    "node_modules/yallist": {
+      "version": "3.1.1",
+      "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz",
+      "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+      "license": "ISC"
+    },
+    "node_modules/yaml": {
+      "version": "1.10.3",
+      "resolved": "https://registry.npmmirror.com/yaml/-/yaml-1.10.3.tgz",
+      "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
+      "license": "ISC",
+      "engines": {
+        "node": ">= 6"
+      }
+    }
+  }
+}

+ 22 - 0
client/package.json

@@ -0,0 +1,22 @@
+{
+  "name": "num-energy",
+  "version": "1.0.0",
+  "description": "数码能量学 AI 智能体小程序",
+  "scripts": {
+    "dev": "vite",
+    "build": "vite build"
+  },
+  "dependencies": {
+    "@dcloudio/uni-app": "^3.0.0-alpha-5010120260522001",
+    "axios": "^1.6.0",
+    "pinia": "^2.1.0",
+    "vue": "^3.4.0"
+  },
+  "devDependencies": {
+    "@dcloudio/types": "^3.3.0",
+    "@dcloudio/vite-plugin-uni": "3.0.0-alpha-5010120260522001",
+    "typescript": "^5.3.0",
+    "vite": "^5.0.0",
+    "vue-tsc": "^2.2.12"
+  }
+}

+ 25 - 0
client/src/App.vue

@@ -0,0 +1,25 @@
+<template>
+  <view class="app-container">
+    <slot />
+  </view>
+</template>
+
+<script setup lang="ts">
+import { onLaunch } from '@dcloudio/uni-app'
+import { useUserStore } from '@/stores/user'
+
+const userStore = useUserStore()
+
+onLaunch(() => {
+  if (userStore.isLoggedIn) {
+    userStore.fetchProfile()
+  }
+})
+</script>
+
+<style>
+.app-container {
+  min-height: 100vh;
+  background: #f5f5f5;
+}
+</style>

+ 171 - 0
client/src/components/TriangleChart.vue

@@ -0,0 +1,171 @@
+<template>
+  <canvas
+    class="triangle-canvas"
+    :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
+    @click="onCanvasReady"
+  ></canvas>
+</template>
+
+<script setup lang="ts">
+import { ref, onMounted, watch, nextTick } from 'vue'
+
+const props = defineProps<{
+  chartData: Record<string, number>
+}>()
+
+const canvasWidth = ref(320)
+const canvasHeight = ref(400)
+
+// Position definitions for Classic A 5-row layout
+interface Position {
+  key: string
+  label: string
+  x: number // percentage 0-100
+  y: number // percentage 0-100
+  isPrimary: boolean
+}
+
+const positions: Position[] = [
+  { key: 'A', label: 'A', x: 10, y: 5, isPrimary: true },
+  { key: 'B', label: 'B', x: 30, y: 5, isPrimary: false },
+  { key: 'C', label: 'C', x: 50, y: 5, isPrimary: false },
+  { key: 'D', label: 'D', x: 70, y: 5, isPrimary: false },
+  { key: 'E', label: 'E', x: 90, y: 5, isPrimary: true },
+  { key: 'F', label: 'F', x: 10, y: 25, isPrimary: true },
+  { key: 'G', label: 'G', x: 30, y: 25, isPrimary: false },
+  { key: 'N', label: 'N', x: 50, y: 25, isPrimary: false },
+  { key: 'H', label: 'H', x: 70, y: 25, isPrimary: false },
+  { key: 'I', label: 'I', x: 90, y: 25, isPrimary: false },
+  { key: 'J', label: 'J', x: 20, y: 45, isPrimary: false },
+  { key: 'M', label: 'M', x: 50, y: 45, isPrimary: false },
+  { key: 'L', label: 'L', x: 80, y: 45, isPrimary: false },
+  { key: 'I2', label: 'I', x: 35, y: 65, isPrimary: false },
+  { key: 'K', label: 'K', x: 65, y: 65, isPrimary: false },
+  { key: 'O', label: 'O', x: 50, y: 85, isPrimary: true },
+]
+
+// Line connections (parent-child in calculation)
+const lines: [string, string][] = [
+  ['A', 'F'], ['B', 'F'], ['B', 'G'], ['C', 'G'],
+  ['C', 'N'], ['D', 'N'], ['D', 'H'], ['E', 'H'],
+  ['G', 'J'], ['F', 'J'], ['G', 'M'], ['N', 'M'],
+  ['N', 'L'], ['H', 'L'], ['I', 'L'],
+  ['J', 'I2'], ['M', 'I2'], ['M', 'K'], ['L', 'K'],
+  ['I2', 'O'], ['K', 'O']
+]
+
+function getColor(num: number): string {
+  if (num === 0) return '#9CA3AF'
+  if (num % 2 === 0) return '#10B981'
+  return '#3B82F6'
+}
+
+function getPrimaryColor(key: string): string {
+  if (['A', 'E', 'F', 'O'].includes(key)) return '#D4A847'
+  return getColor(0)
+}
+
+function drawTriangle(ctx: CanvasRenderingContext2D, width: number, height: number) {
+  const dpr = uni.getSystemInfoSync().pixelRatio
+  ctx.scale(dpr, dpr)
+
+  const padX = 20
+  const padY = 30
+  const drawW = width - padX * 2
+  const drawH = height - padY * 2
+
+  ctx.clearRect(0, 0, width * dpr, height * dpr)
+
+  // Draw connection lines
+  ctx.strokeStyle = '#CBD5E1'
+  ctx.lineWidth = 1.5
+  for (const [from, to] of lines) {
+    const p1 = positions.find(p => p.key === from)
+    const p2 = positions.find(p => p.key === to)
+    if (!p1 || !p2) continue
+    ctx.beginPath()
+    ctx.moveTo(padX + p1.x / 100 * drawW, padY + p1.y / 100 * drawH)
+    ctx.lineTo(padX + p2.x / 100 * drawW, padY + p2.y / 100 * drawH)
+    ctx.stroke()
+  }
+
+  // Draw position circles
+  for (const pos of positions) {
+    const cx = padX + pos.x / 100 * drawW
+    const cy = padY + pos.y / 100 * drawH
+    const num = props.chartData[pos.key === 'I2' ? 'I_pos2' : pos.key] ?? 0
+    const radius = pos.isPrimary ? 18 : 14
+
+    // Circle background
+    ctx.beginPath()
+    ctx.arc(cx, cy, radius, 0, Math.PI * 2)
+    ctx.fillStyle = pos.isPrimary ? '#D4A847' : '#FFFFFF'
+    ctx.fill()
+    ctx.strokeStyle = pos.isPrimary ? '#B8860B' : '#CBD5E1'
+    ctx.lineWidth = pos.isPrimary ? 2.5 : 1.5
+    ctx.stroke()
+
+    // Number text
+    ctx.fillStyle = pos.isPrimary ? '#FFFFFF' : '#1F2937'
+    ctx.font = `bold ${pos.isPrimary ? '16' : '14'}px sans-serif`
+    ctx.textAlign = 'center'
+    ctx.textBaseline = 'middle'
+    ctx.fillText(String(num), cx, cy);
+
+    // Label text below
+    ctx.fillStyle = '#6B7280'
+    ctx.font = '11px sans-serif'
+    ctx.fillText(pos.label, cx, cy + radius + 14)
+  }
+}
+
+onMounted(async () => {
+  await nextTick()
+  const sysInfo = uni.getSystemInfoSync()
+  canvasWidth.value = Math.min(sysInfo.windowWidth - 32, 360)
+  canvasHeight.value = canvasWidth.value * 1.25
+
+  const query = uni.createSelectorQuery()
+  query.select('.triangle-canvas').fields({ node: true, size: true })
+    .exec((res: any) => {
+      if (!res[0]) return
+      const canvas = res[0].node
+      const ctx = canvas.getContext('2d')
+      const dpr = uni.getSystemInfoSync().pixelRatio
+      canvas.width = canvasWidth.value * dpr
+      canvas.height = canvasHeight.value * dpr
+      ctx.scale(dpr, dpr)
+      drawTriangle(ctx, canvasWidth.value, canvasHeight.value)
+    })
+})
+
+watch(() => props.chartData, () => {
+  nextTick(() => {
+    const query = uni.createSelectorQuery()
+    query.select('.triangle-canvas').fields({ node: true, size: true })
+      .exec((res: any) => {
+        if (!res[0]) return
+        const canvas = res[0].node
+        const ctx = canvas.getContext('2d')
+        const dpr = uni.getSystemInfoSync().pixelRatio
+        canvas.width = canvasWidth.value * dpr
+        canvas.height = canvasHeight.value * dpr
+        ctx.scale(dpr, dpr)
+        drawTriangle(ctx, canvasWidth.value, canvasHeight.value)
+      })
+  })
+}, { deep: true })
+
+function onCanvasReady() {
+  // Re-draw on click (sometimes needed for WebView canvas)
+}
+</script>
+
+<style scoped>
+.triangle-canvas {
+  display: block;
+  margin: 0 auto;
+  background: #FFFFFF;
+  border-radius: 12px;
+}
+</style>

+ 7 - 0
client/src/main.ts

@@ -0,0 +1,7 @@
+import { createApp } from 'vue'
+import { createPinia } from 'pinia'
+import App from './App.vue'
+
+const app = createApp(App)
+app.use(createPinia())
+app.mount('#app')

+ 18 - 0
client/src/manifest.json

@@ -0,0 +1,18 @@
+{
+  "name": "num-energy",
+  "appid": "your_appid",
+  "description": "数码能量学 AI 智能体",
+  "versionName": "1.0.0",
+  "versionCode": "100",
+  "mp-weixin": {
+    "appid": "your_appid",
+    "setting": {
+      "urlCheck": false,
+      "es6": true,
+      "postcss": true,
+      "minified": true
+    },
+    "usingComponents": true,
+    "permission": {}
+  }
+}

+ 25 - 0
client/src/pages.json

@@ -0,0 +1,25 @@
+{
+  "pages": [
+    {"path": "pages/index/index", "style": {"navigationBarTitleText": "数字能量"}},
+    {"path": "pages/records/index", "style": {"navigationBarTitleText": "分析记录"}},
+    {"path": "pages/profile/index", "style": {"navigationBarTitleText": "我的"}},
+    {"path": "pages/payment/index", "style": {"navigationBarTitleText": "VIP 开通"}}
+  ],
+  "globalStyle": {
+    "navigationBarTextStyle": "black",
+    "navigationBarTitleText": "数字能量学",
+    "navigationBarBackgroundColor": "#F8F8F8",
+    "backgroundColor": "#F8F8F8"
+  },
+  "tabBar": {
+    "color": "#999",
+    "selectedColor": "#3B82F6",
+    "backgroundColor": "#FFFFFF",
+    "borderStyle": "black",
+    "list": [
+      {"pagePath": "pages/index/index", "text": "首页", "iconPath": "static/home.png", "selectedIconPath": "static/home-active.png"},
+      {"pagePath": "pages/records/index", "text": "记录", "iconPath": "static/records.png", "selectedIconPath": "static/records-active.png"},
+      {"pagePath": "pages/profile/index", "text": "我的", "iconPath": "static/profile.png", "selectedIconPath": "static/profile-active.png"}
+    ]
+  }
+}

+ 194 - 0
client/src/pages/index/index.vue

@@ -0,0 +1,194 @@
+<template>
+  <view class="page-index">
+    <!-- Phone input section -->
+    <view class="input-section">
+      <view class="input-card">
+        <text class="label">手机号码</text>
+        <input
+          class="phone-input"
+          type="text"
+          maxlength="11"
+          placeholder="请输入手机号"
+          :value="phone"
+          @input="onPhoneInput"
+        />
+        <button class="analyze-btn" @click="onAnalyze">分析号码</button>
+      </view>
+    </view>
+
+    <!-- Triangle chart section -->
+    <view v-if="store.currentChart" class="chart-section">
+      <view class="section-title">数字能量三角图</view>
+      <TriangleChart :chartData="store.currentChart" />
+
+      <!-- Primary numbers -->
+      <view class="primary-section">
+        <text class="section-title">主星能量</text>
+        <view class="primary-grid">
+          <view
+            v-for="item in store.analysis?.primary"
+            :key="item.position"
+            class="primary-card"
+            :class="'card-' + item.position.toLowerCase()"
+          >
+            <text class="card-position">{{ item.position }}</text>
+            <text class="card-number">{{ item.number }}</text>
+            <text class="card-energy">{{ item.energy }}</text>
+          </view>
+        </view>
+      </view>
+
+      <!-- Combination analysis -->
+      <view class="combo-section">
+        <text class="section-title">数字组合</text>
+        <view class="combo-list">
+          <view
+            v-for="(item, idx) in store.analysis?.combinations"
+            :key="idx"
+            class="combo-item"
+          >
+            <text class="combo-pair">{{ item.pair }}</text>
+            <text class="combo-meaning">{{ item.meaning }}</text>
+          </view>
+        </view>
+      </view>
+    </view>
+
+    <!-- Chat section (bottom half) -->
+    <view v-if="store.currentChart" class="chat-section">
+      <view class="section-title">AI 解读</view>
+      <scroll-view class="chat-box" scroll-y :scroll-top="scrollTop">
+        <view v-for="(msg, idx) in messages" :key="idx" class="msg-row" :class="msg.role">
+          <view class="msg-bubble">
+            <text>{{ msg.content }}</text>
+          </view>
+        </view>
+      </scroll-view>
+
+      <view class="quick-questions">
+        <view
+          v-for="q in quickQuestions"
+          :key="q"
+          class="quick-chip"
+          @click="sendQuestion(q)"
+        >
+          <text>{{ q }}</text>
+        </view>
+      </view>
+
+      <view class="input-bar">
+        <input
+          class="chat-input"
+          v-model="chatInput"
+          placeholder="输入您的问题..."
+          @confirm="sendQuestion(chatInput)"
+        />
+        <button class="send-btn" @click="sendQuestion(chatInput)">发送</button>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { useChartStore } from '@/stores/chart'
+import TriangleChart from '@/components/TriangleChart.vue'
+import { uni } from '@dcloudio/uni-app'
+
+const store = useChartStore()
+const phone = ref('')
+const chatInput = ref('')
+const scrollTop = ref(0)
+const messages = ref<Array<{role: string, content: string}>>([])
+
+const quickQuestions = ['职业发展', '财运分析', '感情运势', '健康建议']
+
+function onPhoneInput(e: any) {
+  phone.value = e.detail.value
+}
+
+function onAnalyze() {
+  if (phone.value.length < 11) {
+    uni.showToast({ title: '请输入11位手机号', icon: 'none' })
+    return
+  }
+  store.computeChart(phone.value)
+  messages.value = [{
+    role: 'ai',
+    content: `已为您分析手机号 ${phone.value} 的数字能量。请点击上方问题或输入您想了解的内容。`
+  }]
+}
+
+async function sendQuestion(q: string) {
+  if (!q.trim()) return
+  messages.value.push({ role: 'user', content: q })
+  chatInput.value = ''
+  // Mock AI response - will integrate with Dify backend
+  setTimeout(() => {
+    messages.value.push({
+      role: 'ai',
+      content: `基于您的数字能量分析,关于"${q}"的建议:您的能量组合显示良好的发展潜力。建议结合自身情况理性决策。`
+    })
+    scrollTop.value = 99999
+  }, 800)
+}
+</script>
+
+<style scoped lang="scss">
+.page-index { padding-bottom: 30px; }
+.input-section { padding: 16px; }
+.input-card {
+  background: #fff; border-radius: 12px; padding: 20px;
+  box-shadow: 0 2px 8px rgba(0,0,0,0.06);
+}
+.label { font-size: 14px; color: #6B7280; margin-bottom: 8px; display: block; }
+.phone-input {
+  height: 44px; border: 1px solid #E5E7EB; border-radius: 8px;
+  padding: 0 12px; font-size: 18px; margin-bottom: 12px;
+}
+.analyze-btn {
+  width: 100%; height: 44px; background: #3B82F6; color: #fff;
+  border: none; border-radius: 8px; font-size: 16px; line-height: 44px;
+}
+.chart-section, .chat-section { margin: 0 16px; }
+.section-title { font-size: 16px; font-weight: 600; color: #1F2937; margin: 16px 0 12px; display: block; }
+.primary-grid { display: flex; flex-wrap: wrap; gap: 10px; }
+.primary-card {
+  flex: 1; min-width: 70px; padding: 12px; border-radius: 10px;
+  text-align: center; background: #F3F4F6;
+}
+.card-position { font-size: 12px; color: #6B7280; display: block; }
+.card-number { font-size: 24px; font-weight: 700; color: #1F2937; display: block; }
+.card-energy { font-size: 11px; color: #6B7280; display: block; margin-top: 4px; }
+.combo-list { display: flex; flex-wrap: wrap; gap: 6px; }
+.combo-item {
+  background: #F3F4F6; padding: 6px 12px; border-radius: 16px;
+  display: flex; gap: 8px;
+}
+.combo-pair { font-weight: 600; color: #3B82F6; font-size: 13px; }
+.combo-meaning { color: #6B7280; font-size: 13px; }
+
+.chat-box {
+  height: 300px; background: #fff; border-radius: 12px; padding: 12px;
+  margin-bottom: 8px;
+}
+.msg-row { margin-bottom: 12px; display: flex; }
+.msg-row.user { justify-content: flex-end; }
+.msg-bubble {
+  max-width: 80%; padding: 10px 14px; border-radius: 12px;
+  background: #F3F4F6;
+}
+.msg-row.user .msg-bubble { background: #3B82F6; color: #fff; }
+.quick-questions { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
+.quick-chip {
+  background: #EFF6FF; padding: 6px 14px; border-radius: 16px; font-size: 13px; color: #3B82F6;
+}
+.input-bar { display: flex; gap: 8px; }
+.chat-input {
+  flex: 1; height: 40px; border: 1px solid #E5E7EB; border-radius: 8px; padding: 0 12px;
+}
+.send-btn {
+  height: 40px; padding: 0 20px; background: #3B82F6; color: #fff;
+  border: none; border-radius: 8px; line-height: 40px;
+}
+</style>

+ 89 - 0
client/src/pages/payment/index.vue

@@ -0,0 +1,89 @@
+<template>
+  <view class="page-payment">
+    <view class="plan-card">
+      <view class="plan-header">
+        <text class="plan-name">VIP 会员</text>
+        <text class="plan-price">¥398</text>
+        <text class="plan-period">/ 年</text>
+      </view>
+      <view class="plan-features">
+        <text class="feature">✓ 无限次数字能量分析</text>
+        <text class="feature">✓ AI 深度解读报告</text>
+        <text class="feature">✓ 号码标注与标签管理</text>
+        <text class="feature">✓ 历史记录永久保存</text>
+        <text class="feature">✓ 推广赚取佣金</text>
+      </view>
+    </view>
+
+    <view class="order-summary">
+      <text class="summary-title">订单摘要</text>
+      <view class="summary-row">
+        <text>VIP 会员年费</text>
+        <text>¥398</text>
+      </view>
+      <view class="summary-row total">
+        <text>合计</text>
+        <text>¥398</text>
+      </view>
+    </view>
+
+    <button class="pay-btn" @click="handlePay" :disabled="paying">
+      {{ paying ? '支付中...' : '立即支付 ¥398' }}
+    </button>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+import { payApi } from '@/utils/api'
+
+const paying = ref(false)
+
+async function handlePay() {
+  paying.value = true
+  try {
+    // Placeholder - integrates with WeChat Pay
+    const order: any = await payApi.create({ totalFee: 39800, payType: 'wxpay' })
+    uni.showToast({
+      title: '支付成功!',
+      icon: 'success',
+      success: () => {
+        setTimeout(() => uni.navigateBack(), 1500)
+      }
+    })
+  } catch (e) {
+    uni.showToast({ title: '支付失败', icon: 'none' })
+  } finally {
+    paying.value = false
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.page-payment { padding: 16px; }
+.plan-card {
+  background: #fff; border-radius: 16px; padding: 24px;
+  text-align: center; margin-bottom: 16px;
+}
+.plan-header { margin-bottom: 20px; }
+.plan-name { font-size: 20px; font-weight: 700; color: #1F2937; display: block; }
+.plan-price {
+  font-size: 36px; font-weight: 800; color: #3B82F6; display: inline; margin-top: 8px;
+}
+.plan-period { font-size: 14px; color: #6B7280; }
+.plan-features { text-align: left; }
+.feature {
+  display: block; padding: 6px 0; color: #4B5563; font-size: 14px;
+}
+.order-summary {
+  background: #fff; border-radius: 12px; padding: 16px; margin-bottom: 24px;
+}
+.summary-title { font-size: 16px; font-weight: 600; margin-bottom: 12px; display: block; }
+.summary-row { display: flex; justify-content: space-between; padding: 8px 0; font-size: 14px; }
+.summary-row.total { border-top: 1px solid #E5E7EB; margin-top: 8px; padding-top: 12px; font-weight: 700; }
+.pay-btn {
+  width: 100%; height: 48px; background: #3B82F6; color: #fff;
+  border: none; border-radius: 12px; font-size: 18px; line-height: 48px;
+}
+.pay-btn[disabled] { opacity: 0.6; }
+</style>

+ 127 - 0
client/src/pages/profile/index.vue

@@ -0,0 +1,127 @@
+<template>
+  <view class="page-profile">
+    <!-- User info card -->
+    <view class="user-card">
+      <view class="avatar">
+        <image :src="userStore.avatarUrl || '/static/default-avatar.png'" mode="aspectFill" />
+      </view>
+      <text class="nickname">{{ userStore.nickname || '未登录' }}</text>
+      <view v-if="userStore.isVip" class="vip-badge">VIP 会员</view>
+    </view>
+
+    <!-- VIP status -->
+    <view class="vip-card" @click="goPayment">
+      <view class="vip-info">
+        <text class="vip-title">VIP 会员</text>
+        <text class="vip-desc">
+          {{ userStore.isVip ? `有效期至: ${userStore.vipEndTime?.slice(0, 10)}` : '开通VIP获取完整分析' }}
+        </text>
+      </view>
+      <text class="vip-action">{{ userStore.isVip ? '续费' : '立即开通' }}</text>
+    </view>
+
+    <!-- Menu list -->
+    <view class="menu-section">
+      <view class="menu-item" @click="goRecords">
+        <text>📋 我的分析</text>
+        <text class="menu-arrow">›</text>
+      </view>
+      <view class="menu-item" @click="goCommission">
+        <text>💰 我的推广</text>
+        <text class="menu-arrow">›</text>
+      </view>
+      <view class="menu-item" @click="copyReferral">
+        <text>🔗 推广码: {{ userStore.referralCode || '加载中' }}</text>
+        <text class="menu-tip">点击复制</text>
+      </view>
+    </view>
+
+    <!-- Actions -->
+    <view class="menu-section">
+      <view class="menu-item" @click="handleLogout">
+        <text style="color: #EF4444;">退出登录</text>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { onShow } from '@dcloudio/uni-app'
+import { useUserStore } from '@/stores/user'
+
+const userStore = useUserStore()
+
+onShow(() => {
+  if (userStore.isLoggedIn) {
+    userStore.fetchProfile()
+  }
+})
+
+function goPayment() {
+  uni.navigateTo({ url: '/pages/payment/index' })
+}
+
+function goRecords() {
+  uni.switchTab({ url: '/pages/records/index' })
+}
+
+function goCommission() {
+  uni.showToast({ title: '推广功能开发中', icon: 'none' })
+}
+
+function copyReferral() {
+  if (userStore.referralCode) {
+    uni.setClipboardData({
+      data: userStore.referralCode,
+      success: () => uni.showToast({ title: '已复制推广码', icon: 'success' })
+    })
+  }
+}
+
+function handleLogout() {
+  uni.showModal({
+    title: '确认退出',
+    content: '确定要退出登录吗?',
+    success: (res) => {
+      if (res.confirm) {
+        userStore.logout()
+        uni.showToast({ title: '已退出', icon: 'success' })
+      }
+    }
+  })
+}
+</script>
+
+<style scoped lang="scss">
+.page-profile { padding: 16px; }
+.user-card {
+  text-align: center; padding: 30px 0; background: #fff;
+  border-radius: 12px; margin-bottom: 16px;
+}
+.avatar {
+  width: 64px; height: 64px; border-radius: 50%; overflow: hidden;
+  margin: 0 auto 12px;
+}
+.avatar image { width: 100%; height: 100%; }
+.nickname { font-size: 18px; font-weight: 600; display: block; color: #1F2937; }
+.vip-badge {
+  display: inline-block; background: #FEF3C7; color: #D97706;
+  padding: 2px 12px; border-radius: 12px; font-size: 12px; margin-top: 8px;
+}
+.vip-card {
+  background: linear-gradient(135deg, #3B82F6, #2563EB); border-radius: 12px;
+  padding: 16px; display: flex; justify-content: space-between;
+  align-items: center; margin-bottom: 16px;
+}
+.vip-title { color: #fff; font-weight: 600; font-size: 16px; display: block; }
+.vip-desc { color: rgba(255,255,255,0.8); font-size: 12px; display: block; margin-top: 4px; }
+.vip-action { color: #fff; font-size: 14px; font-weight: 500; }
+.menu-section { background: #fff; border-radius: 12px; margin-bottom: 16px; overflow: hidden; }
+.menu-item {
+  display: flex; justify-content: space-between; align-items: center;
+  padding: 14px 16px; border-bottom: 1px solid #F3F4F6;
+}
+.menu-item:last-child { border-bottom: none; }
+.menu-arrow { color: #9CA3AF; font-size: 18px; }
+.menu-tip { color: #3B82F6; font-size: 12px; }
+</style>

+ 75 - 0
client/src/pages/records/index.vue

@@ -0,0 +1,75 @@
+<template>
+  <view class="page-records">
+    <view v-if="store.records.length === 0" class="empty-state">
+      <text class="empty-icon">📋</text>
+      <text class="empty-text">暂无分析记录</text>
+      <text class="empty-desc">去首页分析您的手机号码</text>
+    </view>
+
+    <view v-else class="records-list">
+      <view
+        v-for="record in store.records"
+        :key="record.id"
+        class="record-card"
+        @click="viewDetail(record)"
+      >
+        <view class="record-header">
+          <text class="record-name">{{ record.name || record.phoneNumber }}</text>
+          <text class="record-date">{{ formatDate(record.createdAt) }}</text>
+        </view>
+        <text class="record-phone">{{ record.phoneNumber }}</text>
+        <view class="record-tags">
+          <text v-if="record.difyResponse" class="tag-status">已解读</text>
+        </view>
+      </view>
+    </view>
+  </view>
+</template>
+
+<script setup lang="ts">
+import { onShow } from '@dcloudio/uni-app'
+import { useChartStore } from '@/stores/chart'
+
+const store = useChartStore()
+
+onShow(() => {
+  store.fetchRecords()
+})
+
+function formatDate(dateStr: string): string {
+  if (!dateStr) return ''
+  return dateStr.slice(0, 10)
+}
+
+function viewDetail(record: any) {
+  uni.showModal({
+    title: '分析详情',
+    content: `号码: ${record.phoneNumber}\n姓名: ${record.name || '-'}\n创建: ${formatDate(record.createdAt)}`,
+    showCancel: false
+  })
+}
+</script>
+
+<style scoped lang="scss">
+.page-records { padding: 16px; }
+.empty-state {
+  display: flex; flex-direction: column; align-items: center;
+  padding-top: 80px;
+}
+.empty-icon { font-size: 48px; margin-bottom: 12px; }
+.empty-text { font-size: 16px; color: #6B7280; margin-bottom: 4px; }
+.empty-desc { font-size: 14px; color: #9CA3AF; }
+.records-list { display: flex; flex-direction: column; gap: 10px; }
+.record-card {
+  background: #fff; border-radius: 12px; padding: 16px;
+  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
+}
+.record-header { display: flex; justify-content: space-between; margin-bottom: 4px; }
+.record-name { font-weight: 600; color: #1F2937; }
+.record-date { font-size: 12px; color: #9CA3AF; }
+.record-phone { font-size: 18px; color: #3B82F6; font-weight: 500; }
+.tag-status {
+  display: inline-block; background: #D1FAE5; color: #059669;
+  font-size: 11px; padding: 2px 8px; border-radius: 10px; margin-top: 8px;
+}
+</style>

+ 50 - 0
client/src/stores/chart.ts

@@ -0,0 +1,50 @@
+import { defineStore } from 'pinia'
+import { chartApi, annotationApi } from '@/utils/api'
+import { calculateTriangle, analyzeTriangle } from '@/utils/calculator'
+
+interface ChartState {
+  currentPhone: string
+  currentChart: Record<string, number> | null
+  analysis: any | null
+  records: any[]
+  annotations: any[]
+  tags: any[]
+}
+
+export const useChartStore = defineStore('chart', {
+  state: (): ChartState => ({
+    currentPhone: '',
+    currentChart: null,
+    analysis: null,
+    records: [],
+    annotations: [],
+    tags: []
+  }),
+  actions: {
+    computeChart(phone: string) {
+      this.currentPhone = phone
+      this.currentChart = calculateTriangle(phone)
+      this.analysis = analyzeTriangle(this.currentChart)
+    },
+    async saveChart(phone: string, birthday: string, name: string) {
+      const chartData = JSON.stringify(this.currentChart)
+      const record = await chartApi.create({ phoneNumber: phone, birthday, name, chartData })
+      return record
+    },
+    async fetchRecords() {
+      this.records = await chartApi.list() as any
+    },
+    async fetchAnnotations(recordId: number) {
+      this.annotations = await annotationApi.list(recordId) as any
+    },
+    async addAnnotation(recordId: number, position: string, content: string) {
+      return await annotationApi.add({ recordId, position, content })
+    },
+    async fetchTags(recordId: number) {
+      this.tags = await annotationApi.listTags(recordId) as any
+    },
+    async addTag(recordId: number, tag: string) {
+      return await annotationApi.addTag({ recordId, tag })
+    }
+  }
+})

+ 54 - 0
client/src/stores/user.ts

@@ -0,0 +1,54 @@
+import { defineStore } from 'pinia'
+import { authApi, profileApi } from '@/utils/api'
+
+interface UserState {
+  token: string
+  nickname: string
+  avatarUrl: string
+  isVip: boolean
+  vipEndTime: string | null
+  referralCode: string
+}
+
+export const useUserStore = defineStore('user', {
+  state: (): UserState => ({
+    token: uni.getStorageSync('token') || '',
+    nickname: '',
+    avatarUrl: '',
+    isVip: false,
+    vipEndTime: null,
+    referralCode: ''
+  }),
+  getters: {
+    isLoggedIn: (state) => !!state.token,
+    isVipActive: (state) => {
+      if (!state.vipEndTime) return false
+      return new Date(state.vipEndTime) > new Date()
+    }
+  },
+  actions: {
+    async login(openid: string, nickname: string, avatarUrl: string, referralCode?: string) {
+      const data: any = { openid, nickname, avatarUrl }
+      if (referralCode) data.referralCode = referralCode
+      const token: string = await authApi.login(data) as any
+      this.token = token
+      uni.setStorageSync('token', token)
+      this.nickname = nickname
+      this.avatarUrl = avatarUrl
+    },
+    async fetchProfile() {
+      const user: any = await profileApi.info()
+      this.nickname = user.nickname
+      this.avatarUrl = user.avatarUrl
+      this.referralCode = user.referralCode
+      this.isVip = !!user.vipEndTime && new Date(user.vipEndTime) > new Date()
+      this.vipEndTime = user.vipEndTime
+    },
+    logout() {
+      this.token = ''
+      this.nickname = ''
+      this.avatarUrl = ''
+      uni.removeStorageSync('token')
+    }
+  }
+})

+ 41 - 0
client/src/uni.scss

@@ -0,0 +1,41 @@
+/* Color variables */
+$primary-color: #3B82F6;
+$success-color: #10B981;
+$warning-color: #F59E0B;
+$danger-color: #EF4444;
+$text-primary: #1F2937;
+$text-secondary: #6B7280;
+$bg-color: #F8FAFC;
+$card-bg: #FFFFFF;
+$border-color: #E5E7EB;
+
+/* Font sizes */
+$font-xs: 12px;
+$font-sm: 14px;
+$font-base: 16px;
+$font-lg: 18px;
+$font-xl: 24px;
+
+/* Spacing */
+$spacing-xs: 4px;
+$spacing-sm: 8px;
+$spacing-md: 16px;
+$spacing-lg: 24px;
+$spacing-xl: 32px;
+
+/* Border radius */
+$radius-sm: 6px;
+$radius-md: 10px;
+$radius-lg: 16px;
+$radius-full: 999px;
+
+/* Triangle chart colors */
+$gold: #D4A847;
+$blue: #3B82F6;
+$green: #10B981;
+$line-color: #CBD5E1;
+
+/* Shadows */
+$shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
+$shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
+$shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.1);

+ 69 - 0
client/src/utils/api.ts

@@ -0,0 +1,69 @@
+import axios from 'axios'
+
+const request = axios.create({
+  baseURL: '/api',
+  timeout: 30000,
+  headers: { 'Content-Type': 'application/json' }
+})
+
+request.interceptors.request.use(config => {
+  const token = uni.getStorageSync('token')
+  if (token) {
+    config.headers.Authorization = `Bearer ${token}`
+  }
+  return config
+})
+
+request.interceptors.response.use(
+  response => {
+    const res = response.data
+    if (res.code !== 0) {
+      uni.showToast({ title: res.message, icon: 'none' })
+      if (res.code === 1001) {
+        uni.removeStorageSync('token')
+        uni.navigateTo({ url: '/pages/profile/index' })
+      }
+      return Promise.reject(new Error(res.message))
+    }
+    return res.data
+  },
+  error => {
+    uni.showToast({ title: '网络错误', icon: 'none' })
+    return Promise.reject(error)
+  }
+)
+
+export default request
+
+export const authApi = {
+  login: (data: Record<string, any>) => request.post('/auth/login', data)
+}
+
+export const chartApi = {
+  create: (data: Record<string, any>) => request.post('/chart/create', data),
+  list: () => request.post('/chart/list', {}),
+  detail: (id: number) => request.post('/chart/detail', { id })
+}
+
+export const payApi = {
+  create: (data: Record<string, any>) => request.post('/pay/create', data)
+}
+
+export const profileApi = {
+  info: () => request.post('/profile/info', {}),
+  vipStatus: () => request.post('/profile/vip-status', {})
+}
+
+export const annotationApi = {
+  add: (data: Record<string, any>) => request.post('/annotation/add', data),
+  list: (recordId: number) => request.post('/annotation/list', { recordId }),
+  delete: (id: number) => request.post('/annotation/delete', { id }),
+  addTag: (data: Record<string, any>) => request.post('/annotation/tag/add', data),
+  listTags: (recordId: number) => request.post('/annotation/tag/list', { recordId }),
+  deleteTag: (id: number) => request.post('/annotation/tag/delete', { id })
+}
+
+export const commissionApi = {
+  list: () => request.post('/commission/list', {}),
+  total: () => request.post('/commission/total', {})
+}

+ 130 - 0
client/src/utils/calculator.ts

@@ -0,0 +1,130 @@
+const ENERGY_MAP: Record<string, string> = {
+  '1': '领导力、创造、独立', '2': '合作、平衡、感性',
+  '3': '表达、社交、艺术', '4': '稳定、务实、规则',
+  '5': '自由、变化、冒险', '6': '关爱、责任、家庭',
+  '7': '智慧、分析、内省', '8': '财富、权力、成就',
+  '9': '博爱、理想、智慧', '0': '潜能、灵性、无限'
+}
+
+const COMBINATION_MAP: Record<string, string> = {
+  '12': '创新与合作', '13': '创意表达', '14': '务实创新',
+  '15': '变革领导', '16': '关怀创造', '17': '智慧创新',
+  '18': '财富创造', '19': '理想创造', '21': '合作创新',
+  '23': '社交表达', '24': '稳定合作', '25': '自由协作',
+  '26': '关爱合作', '27': '智慧合作', '28': '财富合作',
+  '31': '表达创造', '32': '社交协作', '34': '务实表达',
+  '35': '自由表达', '36': '关爱表达', '37': '智慧表达',
+  '38': '财富表达', '39': '理想表达', '41': '务实创新',
+  '42': '稳定合作', '43': '务实社交', '45': '稳定变化',
+  '46': '务实关爱', '47': '务实智慧', '48': '财富稳定',
+  '51': '变革领导', '52': '自由协作', '53': '自由表达',
+  '54': '变化稳定', '56': '自由关爱', '57': '智慧变化',
+  '58': '自由财富', '59': '自由理想', '61': '关爱领导',
+  '62': '关爱协作', '63': '情感表达', '64': '稳定关爱',
+  '65': '自由关怀', '67': '智慧关怀', '68': '财富关怀',
+  '71': '智慧领导', '72': '智慧协作', '73': '智慧表达',
+  '74': '务实智慧', '75': '智慧变化', '76': '智慧关怀',
+  '78': '智慧财富', '79': '智慧理想', '81': '财富领导',
+  '82': '财富协作', '83': '财富表达', '84': '务实财富',
+  '85': '自由财富', '86': '财富关怀', '87': '智慧财富',
+  '89': '财富理想', '91': '理想领导', '92': '理想协作',
+  '93': '理想表达', '94': '务实理想', '95': '自由理想',
+  '96': '关爱理想', '97': '智慧理想', '98': '财富理想'
+}
+
+function sumMod10(a: number, b: number): number {
+  return (a + b) % 10
+}
+
+export function getNumbers(phone: string): number[] {
+  const cleaned = phone.replace(/\D/g, '')
+  return cleaned.split('').map(Number)
+}
+
+export function getEnergy(num: number): string {
+  return ENERGY_MAP[String(num)] || '未知能量'
+}
+
+export function getCombination(a: number, b: number): string {
+  return COMBINATION_MAP[`${a}${b}`] || `${getEnergy(a)} → ${getEnergy(b)}`
+}
+
+export function calculateTriangle(phone: string): Record<string, number> {
+  const digits = getNumbers(phone)
+  // Use first 8 significant digits, pad if needed
+  const nums = digits.slice(0, 8)
+  while (nums.length < 8) nums.push(0)
+
+  // Classic A 5-row layout (center aligned)
+  // Row A: A B C D E from 5 of 8 digits + computed
+  // The 8 digits map to positions in row A
+
+  // Position mapping for Classic A (center position is O):
+  // A1-A5 from calculation on phone digits
+  // B1-B5 = sum adjacent A positions mod 10
+  // C1-C3 = sum adjacent B positions mod 10 (center aligned, skip ends)
+  // D1-D2 = sum adjacent C positions mod 10
+  // E1(O) = sum D1+D2 mod 10
+
+  // Step 1: Initial A row from digits
+  // Classic A: take 8 digits, position them as:
+  // A1=digits[0], A2=digits[1], A3=digits[2] (then compute A4=sum(A2,A3), A5=sum(A3,A4))
+  // Alternatively: 5 main A positions from 8 digits using pairwise sums
+
+  const r: Record<string, number> = {}
+  r.A = nums[0]; r.B = nums[1]; r.C = nums[2]
+  r.D = sumMod10(nums[1], nums[2])
+  r.E = sumMod10(nums[2], nums[3])
+
+  // Row B
+  r.F = sumMod10(r.A, r.B)
+  r.G = sumMod10(r.B, r.C)
+  r.N = sumMod10(r.C, r.D)
+  r.H = sumMod10(r.D, r.E)
+
+  // Compute I in row B from N and H's future position
+  // In classic A, position I appears in row B (position 10) and row D
+  const tempI1 = sumMod10(r.G, r.N)
+  r.I = sumMod10(r.N, r.H)
+
+  // Row C
+  r.J = sumMod10(r.F, r.G)
+  r.M = sumMod10(r.G, r.N)
+  r.L = sumMod10(r.H, r.I)
+
+  // Row D
+  const d1 = sumMod10(r.J, r.M)
+  const d2 = sumMod10(r.M, r.L)
+  r.K = d1 // I1 position in row D
+  r.I_pos2 = d2 // Second I position
+
+  // Row E (O - center)
+  r.O = sumMod10(d1, d2)
+
+  return r
+}
+
+export function analyzeTriangle(chart: Record<string, number>): {
+  primary: Array<{position: string, number: number, energy: string}>,
+  combinations: Array<{pair: string, meaning: string}>
+} {
+  const primaryPositions = ['A', 'E', 'F', 'O']
+  const primary = primaryPositions.map(pos => ({
+    position: pos,
+    number: chart[pos] ?? 0,
+    energy: getEnergy(chart[pos] ?? 0)
+  }))
+
+  const comboPairs = [
+    ['A', 'E'], ['A', 'F'], ['E', 'O'],
+    ['F', 'O'], ['A', 'O'], ['B', 'C'],
+    ['G', 'N'], ['N', 'H'], ['J', 'M']
+  ]
+
+  const combinations = comboPairs.map(([p1, p2]) => ({
+    pair: `${p1}${p2}`,
+    meaning: getCombination(chart[p1] ?? 0, chart[p2] ?? 0)
+  }))
+
+  return { primary, combinations }
+}

+ 21 - 0
client/tsconfig.json

@@ -0,0 +1,21 @@
+{
+  "compilerOptions": {
+    "target": "ES2020",
+    "module": "ESNext",
+    "strict": true,
+    "jsx": "preserve",
+    "moduleResolution": "node",
+    "skipLibCheck": true,
+    "esModuleInterop": true,
+    "allowSyntheticDefaultImports": true,
+    "forceConsistentCasingInFileNames": true,
+    "resolveJsonModule": true,
+    "isolatedModules": true,
+    "baseUrl": ".",
+    "paths": {
+      "@/*": ["src/*"]
+    },
+    "types": ["@dcloudio/types"]
+  },
+  "include": ["src/**/*.ts", "src/**/*.vue", "env.d.ts"]
+}

+ 15 - 0
client/vite.config.ts

@@ -0,0 +1,15 @@
+import { defineConfig } from 'vite'
+import uni from '@dcloudio/vite-plugin-uni'
+
+export default defineConfig({
+  plugins: [uni()],
+  server: {
+    port: 3000,
+    proxy: {
+      '/api': {
+        target: 'http://localhost:8080',
+        changeOrigin: true
+      }
+    }
+  }
+})

+ 69 - 0
cloudfunctions/applyWithdraw/index.js

@@ -0,0 +1,69 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+const db = cloud.database();
+
+// 提现申请(Phase 1:记录申请,平台手动打款)
+exports.main = async (event) => {
+  const { amount } = event;
+  const { OPENID } = cloud.getWXContext();
+
+  if (!amount || amount <= 0) {
+    return { code: 400, error: '无效金额' };
+  }
+
+  try {
+    const userRes = await db.collection('users').where({
+      _openid: OPENID,
+    }).get();
+
+    if (userRes.data.length === 0) {
+      return { code: 401, error: '用户不存在' };
+    }
+
+    // 检查可提现金额
+    const commRes = await db.collection('commissions').where({
+      toUser: OPENID,
+      status: 'available',
+    }).get();
+
+    const availableTotal = (commRes.data || []).reduce((sum, c) => sum + (c.amount || 0), 0);
+    if (amount > availableTotal) {
+      return { code: 400, error: '可提现金额不足' };
+    }
+
+    if (amount < 10000) { // 单位:分,最低 ¥100
+      return { code: 400, error: '未达到最低提现金额 ¥100' };
+    }
+
+    // 创建提现申请
+    const applyRes = await db.collection('withdrawals').add({
+      data: {
+        userId: OPENID,
+        amount,
+        status: 'pending',
+        createdAt: db.serverDate(),
+        updatedAt: db.serverDate(),
+      },
+    });
+
+    // 将佣金状态改为 processing
+    let remaining = amount;
+    const availableComms = commRes.data.sort((a, b) => a.createdAt - b.createdAt);
+    for (const c of availableComms) {
+      if (remaining <= 0) break;
+      const deductAmount = Math.min(remaining, c.amount);
+      remaining -= deductAmount;
+      await db.collection('commissions').doc(c._id).update({
+        data: {
+          status: 'processing',
+          withdrawId: applyRes._id,
+          updatedAt: db.serverDate(),
+        },
+      });
+    }
+
+    return { code: 0, withdrawId: applyRes._id };
+  } catch (err) {
+    return { code: 500, error: err.message };
+  }
+};

+ 8 - 0
cloudfunctions/applyWithdraw/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "applyWithdraw",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 40 - 0
cloudfunctions/checkSession/index.js

@@ -0,0 +1,40 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+const db = cloud.database();
+
+exports.main = async (event) => {
+  const { OPENID } = cloud.getWXContext();
+
+  try {
+    const userRes = await db.collection('users').where({
+      _openid: OPENID,
+    }).get();
+
+    if (userRes.data.length === 0) {
+      return { isValid: false };
+    }
+
+    const user = userRes.data[0];
+    const now = Date.now();
+    const isPractitioner = user.practitionerExpireAt
+      && new Date(user.practitionerExpireAt).getTime() > now;
+
+    return {
+      isValid: true,
+      role: isPractitioner ? 'practitioner' : 'regular',
+      expireAt: user.practitionerExpireAt || null,
+      referralCode: user.referralCode || null,
+      referralStats: user.referralStats || {
+        directCount: 0,
+        indirectCount: 0,
+        convertedCount: 0,
+      },
+      userInfo: {
+        name: user.nickName || '',
+        createdAt: user.createdAt,
+      },
+    };
+  } catch (err) {
+    return { isValid: false, error: err.message };
+  }
+};

+ 8 - 0
cloudfunctions/checkSession/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "checkSession",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 25 - 0
cloudfunctions/createPayment/index.js

@@ -0,0 +1,25 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+
+exports.main = async (event) => {
+  const { type, amount, referralCode } = event;
+  const { OPENID } = cloud.getWXContext();
+
+  try {
+    const outTradeNo = `${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
+
+    const result = await cloud.cloudPay.unifiedOrder({
+      body: '数字能量学-能量师年服务包',
+      outTradeNo,
+      spbillCreateIp: '127.0.0.1',
+      subMchId: 'YOUR_SUB_MCH_ID',
+      totalFee: Math.round(amount * 100),
+      envId: 'YOUR_CLOUD_ENV_ID',
+      functionName: 'paymentCallback',
+    });
+
+    return { code: 0, payment: result.payment };
+  } catch (err) {
+    return { code: 500, error: err.message };
+  }
+};

+ 8 - 0
cloudfunctions/createPayment/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "createPayment",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 130 - 0
cloudfunctions/generateReading/index.js

@@ -0,0 +1,130 @@
+/**
+ * AI 命盘解读云函数
+ *
+ * 接收命盘数据,调用 LLM API 生成数字能量学解读
+ * 支持 DeepSeek / OpenAI 兼容接口
+ * 通过云调用鉴权,不在前端暴露 API Key
+ */
+
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+
+// LLM API 配置(通过云托管环境变量配置,不硬编码密钥)
+const LLM_API_KEY = process.env.LLM_API_KEY || 'YOUR_API_KEY';
+const LLM_API_URL = process.env.LLM_API_URL || 'https://api.deepseek.com/v1/chat/completions';
+const LLM_MODEL = process.env.LLM_MODEL || 'deepseek-chat';
+
+// 系统提示词 — 设定 AI 的角色和行为
+const SYSTEM_PROMPT = `你是一位专业的数字能量学解读师,精通生命密码(数字能量学)。你的任务是基于用户的三角形命盘数据,提供专业、准确、有洞见的解读。
+
+解读风格要求:
+1. 专业但不晦涩,让普通人也能理解
+2. 每段解读 100-200 字,言简意赅
+3. 结合数字能量学理论,给出性格特质、优势、成长建议
+4. 语气温和正向,避免恐吓或绝对化表述
+5. 以 "你" 称呼用户,亲切自然
+
+重要原则:
+- 解读必须基于命盘中的实际数字,不能编造
+- 避免宿命论,强调个人选择和发展的可能性
+- 所有解读最后加一句 "仅供参考" 的提示`;
+
+function buildPrompt(chartData, name) {
+  const { positions, zones, mainCharacter, isMasterNumber } = chartData;
+
+  let prompt = `请为以下命盘生成解读。\n\n`;
+  prompt += `姓名:${name || '用户'}\n`;
+  prompt += `主性格数字:${mainCharacter}${isMasterNumber ? '(卓越数)' : ''}\n\n`;
+  prompt += `完整命盘数据:\n`;
+  prompt += `底层:A=${positions.A} B=${positions.B} C=${positions.C} D=${positions.D} E=${positions.E}\n`;
+  prompt += `第二层:F=${positions.F} G=${positions.G} H=${positions.H} I=${positions.I}\n`;
+  prompt += `第三层:J=${positions.J} K=${positions.K} L=${positions.L}\n`;
+  prompt += `第四层:M=${positions.M} N=${positions.N}\n`;
+  prompt += `顶端:O=${positions.O}\n\n`;
+  prompt += `请以 JSON 格式返回,包含以下字段:\n`;
+  prompt += `{
+    "mainCharacter": "主性格解读(重点突出${mainCharacter}号人的核心特质、优势、适合的发展方向)",
+    "fatherSource": "父源区解读(F=${positions.F}, J=${positions.J} 的含义和影响)",
+    "motherSource": "母源区解读(I=${positions.I}, L=${positions.L} 的含义和影响)",
+    "leftZone": "左区(0-20岁)解读",
+    "middleZone": "中区(20-40岁)解读",
+    "rightZone": "右区(40-60岁)解读"
+  }\n\n`;
+  prompt += `请只返回 JSON,不要包含其他文字。`;
+
+  return prompt;
+}
+
+exports.main = async (event, context) => {
+  const { chartData, name } = event;
+
+  if (!chartData || !chartData.positions) {
+    return { code: 400, error: '缺少命盘数据' };
+  }
+
+  try {
+    const userPrompt = buildPrompt(chartData, name);
+
+    const response = await fetch(LLM_API_URL, {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+        'Authorization': `Bearer ${LLM_API_KEY}`,
+      },
+      body: JSON.stringify({
+        model: LLM_MODEL,
+        messages: [
+          { role: 'system', content: SYSTEM_PROMPT },
+          { role: 'user', content: userPrompt },
+        ],
+        temperature: 0.7,
+        max_tokens: 2000,
+      }),
+    });
+
+    const data = await response.json();
+
+    if (!data.choices || !data.choices[0]) {
+      console.error('LLM API error:', data);
+      return { code: 500, error: 'AI 服务异常', reading: null };
+    }
+
+    const content = data.choices[0].message.content;
+
+    // Try to parse JSON from the response
+    try {
+      // Find JSON in the response (handle cases where model wraps in markdown)
+      const jsonMatch = content.match(/\{[\s\S]*\}/);
+      const jsonStr = jsonMatch ? jsonMatch[0] : content;
+      const reading = JSON.parse(jsonStr);
+
+      return {
+        code: 0,
+        reading: {
+          mainCharacter: reading.mainCharacter || '',
+          fatherSource: reading.fatherSource || '',
+          motherSource: reading.motherSource || '',
+          leftZone: reading.leftZone || '',
+          middleZone: reading.middleZone || '',
+          rightZone: reading.rightZone || '',
+        },
+      };
+    } catch (parseErr) {
+      // If JSON parsing fails, return raw text
+      return {
+        code: 0,
+        reading: {
+          mainCharacter: content,
+          fatherSource: '解读生成中,请稍后再试',
+          motherSource: '解读生成中,请稍后再试',
+          leftZone: '解读生成中,请稍后再试',
+          middleZone: '解读生成中,请稍后再试',
+          rightZone: '解读生成中,请稍后再试',
+        },
+      };
+    }
+  } catch (err) {
+    console.error('Cloud function error:', err);
+    return { code: 500, error: err.message, reading: null };
+  }
+};

+ 9 - 0
cloudfunctions/generateReading/package.json

@@ -0,0 +1,9 @@
+{
+  "name": "generateReading",
+  "version": "1.0.0",
+  "description": "AI 命盘解读生成",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 47 - 0
cloudfunctions/getCommission/index.js

@@ -0,0 +1,47 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+const db = cloud.database();
+
+// 获取当前用户的佣金概览和明细
+exports.main = async (event) => {
+  const { OPENID } = cloud.getWXContext();
+
+  try {
+    const commRes = await db.collection('commissions').where({
+      toUser: OPENID,
+    }).orderBy('createdAt', 'desc').get();
+
+    const commissions = commRes.data || [];
+    let totalAmount = 0;
+    let availableAmount = 0;
+    let pendingAmount = 0;
+
+    commissions.forEach(c => {
+      totalAmount += c.amount || 0;
+      if (c.status === 'available') {
+        availableAmount += c.amount;
+      } else if (c.status === 'pending') {
+        pendingAmount += c.amount;
+      }
+    });
+
+    // 格式化输出
+    const list = commissions.slice(0, 50).map(c => ({
+      commissionId: c._id,
+      level: c.level,
+      amount: c.amount,
+      status: c.status,
+      sourceName: c.sourceName || '用户',
+      createdAt: c.createdAt,
+    }));
+
+    return {
+      totalAmount,
+      availableAmount,
+      pendingAmount,
+      commissions: list,
+    };
+  } catch (err) {
+    return { error: err.message, totalAmount: 0, availableAmount: 0, pendingAmount: 0, commissions: [] };
+  }
+};

+ 8 - 0
cloudfunctions/getCommission/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "getCommission",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 34 - 0
cloudfunctions/getQRCode/index.js

@@ -0,0 +1,34 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+
+// 生成小程序码(能量师专属推广码)
+exports.main = async (event) => {
+  const { referralCode } = event;
+  const { OPENID } = cloud.getWXContext();
+
+  if (!referralCode) {
+    return { code: 400, error: '缺少推广码' };
+  }
+
+  try {
+    const result = await cloud.openapi.wxacode.get({
+      path: `pages/index/index?ref=${referralCode}`,
+      width: 280,
+      isHyaline: false,
+      autoColor: true,
+    });
+
+    // 将 Buffer 上传到云存储
+    const uploadRes = await cloud.uploadFile({
+      cloudPath: `qrcode/${OPENID}_${referralCode}_${Date.now()}.jpg`,
+      fileContent: result.buffer,
+    });
+
+    return {
+      code: 0,
+      fileID: uploadRes.fileID,
+    };
+  } catch (err) {
+    return { code: 500, error: err.message };
+  }
+};

+ 8 - 0
cloudfunctions/getQRCode/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "getQRCode",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 26 - 0
cloudfunctions/getReferrerInfo/index.js

@@ -0,0 +1,26 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+const db = cloud.database();
+
+// 通过推广码查询上级信息(分享提示用)
+exports.main = async (event) => {
+  const { referralCode } = event;
+
+  try {
+    const res = await db.collection('users').where({
+      referralCode,
+    }).get();
+
+    if (res.data.length === 0) {
+      return { found: false };
+    }
+
+    const user = res.data[0];
+    return {
+      found: true,
+      name: user.nickName || '能量师',
+    };
+  } catch (err) {
+    return { found: false, error: err.message };
+  }
+};

+ 8 - 0
cloudfunctions/getReferrerInfo/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "getReferrerInfo",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 155 - 0
cloudfunctions/paymentCallback/index.js

@@ -0,0 +1,155 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+const db = cloud.database();
+
+// 支付成功回调(微信支付结果通知)
+// 处理:能量师订阅升级 + 佣金结算
+exports.main = async (event) => {
+  const {
+    outTradeNo,      // 订单号
+    transactionId,   // 微信支付订单号
+    totalFee,        // 支付金额(分)
+    attach,          // 附加数据
+  } = event;
+
+  // 获取支付用户的 openId
+  const { OPENID } = cloud.getWXContext();
+
+  try {
+    // 1. 查询订单是否已处理(幂等)
+    const orderRes = await db.collection('orders').where({
+      outTradeNo,
+    }).get();
+
+    if (orderRes.data.length > 0) {
+      return { code: 0, message: '订单已处理' };
+    }
+
+    // 2. 写订单记录
+    const orderData = {
+      outTradeNo,
+      transactionId,
+      userId: OPENID,
+      type: 'practitioner_annual',
+      amount: totalFee,
+      paymentMethod: 'wechat_pay',
+      status: 'paid',
+      paidAt: db.serverDate(),
+      createdAt: db.serverDate(),
+    };
+    await db.collection('orders').add({ data: orderData });
+
+    // 3. 更新用户为能量师(有效期 1 年)
+    const now = new Date();
+    const expireDate = new Date(now);
+    expireDate.setFullYear(expireDate.getFullYear() + 1);
+
+    // 查询已有用户
+    const userRes = await db.collection('users').where({
+      _openid: OPENID,
+    }).get();
+
+    const userData = {
+      role: 'practitioner',
+      practitionerExpireAt: expireDate.toISOString(),
+      updatedAt: db.serverDate(),
+    };
+
+    if (userRes.data.length === 0) {
+      // 新用户注册(一般不会走到这里,但以防万一)
+      userData._openid = OPENID;
+      userData.referralCode = generateReferralCode();
+      userData.createdAt = db.serverDate();
+      await db.collection('users').add({ data: userData });
+    } else {
+      // 已有用户,生成或保留推广码
+      const user = userRes.data[0];
+      if (!user.referralCode) {
+        userData.referralCode = generateReferralCode();
+      }
+      await db.collection('users').doc(user._id).update({ data: userData });
+    }
+
+    // 4. 佣金结算:查用户的上级
+    const user = (await db.collection('users').where({ _openid: OPENID }).get()).data[0];
+    const invitedBy = user.invitedBy;
+
+    if (invitedBy) {
+      // 查上级是否为有效的能量师
+      const parentRes = await db.collection('users').where({ _openid: invitedBy }).get();
+      if (parentRes.data.length > 0) {
+        const parent = parentRes.data[0];
+        const isParentPractitioner = parent.practitionerExpireAt
+          && new Date(parent.practitionerExpireAt).getTime() > Date.now();
+
+        if (isParentPractitioner) {
+          // 一级佣金:30%
+          const level1Amount = Math.round(totalFee * 0.30);
+          await db.collection('commissions').add({
+            data: {
+              fromUser: OPENID,
+              toUser: invitedBy,
+              level: 1,
+              amount: level1Amount,
+              sourceOrderId: outTradeNo,
+              status: 'pending',
+              createdAt: db.serverDate(),
+              updatedAt: db.serverDate(),
+            },
+          });
+
+          // 更新上级的推广统计
+          const stats = parent.referralStats || {};
+          await db.collection('users').doc(parent._id).update({
+            data: {
+              'referralStats.convertedCount': (stats.convertedCount || 0) + 1,
+            },
+          });
+
+          // 查上上级(二级佣金)
+          const grandParentInvitedBy = parent.invitedBy;
+          if (grandParentInvitedBy) {
+            const gpRes = await db.collection('users').where({ _openid: grandParentInvitedBy }).get();
+            if (gpRes.data.length > 0) {
+              const gp = gpRes.data[0];
+              const isGpPractitioner = gp.practitionerExpireAt
+                && new Date(gp.practitionerExpireAt).getTime() > Date.now();
+
+              if (isGpPractitioner) {
+                // 二级佣金:10%
+                const level2Amount = Math.round(totalFee * 0.10);
+                await db.collection('commissions').add({
+                  data: {
+                    fromUser: OPENID,
+                    toUser: grandParentInvitedBy,
+                    level: 2,
+                    amount: level2Amount,
+                    sourceOrderId: outTradeNo,
+                    status: 'pending',
+                    createdAt: db.serverDate(),
+                    updatedAt: db.serverDate(),
+                  },
+                });
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return { code: 0, message: 'success' };
+  } catch (err) {
+    console.error('[paymentCallback] error:', err);
+    return { code: 500, error: err.message };
+  }
+};
+
+// 生成唯一6位推广码
+function generateReferralCode() {
+  const chars = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
+  let code = '';
+  for (let i = 0; i < 6; i++) {
+    code += chars[Math.floor(Math.random() * chars.length)];
+  }
+  return code;
+}

+ 8 - 0
cloudfunctions/paymentCallback/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "paymentCallback",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 76 - 0
cloudfunctions/registerUser/index.js

@@ -0,0 +1,76 @@
+const cloud = require('wx-server-sdk');
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+const db = cloud.database();
+
+// 用户注册(首次微信登录时调用)
+// 处理:创建用户记录 + 上下级关系绑定
+exports.main = async (event) => {
+  const { referrerCode } = event;
+  const { OPENID } = cloud.getWXContext();
+
+  try {
+    // 检查用户是否已存在
+    const userRes = await db.collection('users').where({
+      _openid: OPENID,
+    }).get();
+
+    if (userRes.data.length > 0) {
+      return {
+        code: 0,
+        isNew: false,
+        role: userRes.data[0].role || 'regular',
+        message: '用户已存在',
+      };
+    }
+
+    // 解析上级
+    let invitedBy = null;
+    if (referrerCode) {
+      const refRes = await db.collection('users').where({
+        referralCode,
+      }).get();
+
+      if (refRes.data.length > 0) {
+        const refUser = refRes.data[0];
+        // 不能自己邀请自己
+        if (refUser._openid !== OPENID) {
+          invitedBy = refUser._openid;
+
+          // 更新上级的推广统计
+          const stats = refUser.referralStats || {};
+          await db.collection('users').doc(refUser._id).update({
+            data: {
+              'referralStats.directCount': (stats.directCount || 0) + 1,
+            },
+          });
+        }
+      }
+    }
+
+    // 创建新用户
+    const userData = {
+      _openid: OPENID,
+      role: 'regular',
+      practitionerExpireAt: null,
+      invitedBy,
+      referralStats: {
+        directCount: 0,
+        indirectCount: 0,
+        convertedCount: 0,
+      },
+      createdAt: db.serverDate(),
+      updatedAt: db.serverDate(),
+    };
+
+    await db.collection('users').add({ data: userData });
+
+    return {
+      code: 0,
+      isNew: true,
+      role: 'regular',
+      hasReferrer: !!invitedBy,
+    };
+  } catch (err) {
+    return { code: 500, error: err.message };
+  }
+};

+ 8 - 0
cloudfunctions/registerUser/package.json

@@ -0,0 +1,8 @@
+{
+  "name": "registerUser",
+  "version": "1.0.0",
+  "main": "index.js",
+  "dependencies": {
+    "wx-server-sdk": "latest"
+  }
+}

+ 378 - 0
docs/distribution-model.md

@@ -0,0 +1,378 @@
+# 能量师分销模式设计方案
+
+> 基于"普通用户→能量师"双层模型,通过上下级关系实现裂变增长
+> 定位:用分销驱动能量师自发推广,低成本获客
+
+---
+
+## 一、为什么需要分销模式?
+
+### 1.1 数字能量师的圈子特征
+
+| 特征 | 对分销的意义 |
+|------|-------------|
+| 圈层集中(微信群、朋友圈高度重合) | 一人推广 = 触达整个圈层 |
+| 信任成本高但信任后黏性极强 | 熟人推荐转化率远高于广告 |
+| 有赚钱动力(本身就是生意人) | 能量师天然适合做分销商 |
+| 对"工具+赚钱"组合高度敏感 | "用工具省钱+推工具赚钱"双重驱动 |
+
+### 1.2 不用分销 vs 用分销
+
+```
+不用分销:         用分销:
+  平台自己获客        能量师帮你获客
+  获客成本 ¥50+      获客成本 ≈ 佣金分成
+  增长线性            增长指数级(裂变)
+  能量师用完即走      能量师有动力持续推广
+```
+
+---
+
+## 二、分销参与角色
+
+### 角色定义
+
+```
+                  能量师(分销商)
+                 /        |        \
+           直接邀请    间接邀请    间接邀请
+              │          │          │
+           普通用户    普通用户    普通用户
+              │          │          │
+          (购买升级)  (购买升级)  (购买升级)
+              │          │          │
+           新能量师    新能量师    新能量师  ← 佣金触发点
+              │
+          (继续邀请)
+              │
+           更多用户...   ← 二级裂变
+```
+
+| 角色 | 定义 | 分销权限 |
+|------|------|---------|
+| **普通用户** | 免费用户,通过任意渠道注册 | ❌ 不能发展下级,不能赚佣金 |
+| **能量师** | 付费 ¥398/年的用户 | ✅ 可发展下级,赚取佣金 |
+| **上级能量师** | 通过其分享链接注册的用户称为其"下级" | 获得下级升级时的佣金 |
+| **下级** | 通过上级分享链接注册的用户 | 消费时上级获得佣金 |
+
+### 核心原则:只有能量师有分销权
+
+- 普通用户不能发展下级
+- 普通用户若自己升级为能量师,**自动继承其原上级关系**
+- 能量师的上级关系在首次注册时锁定,**不能变更**
+
+---
+
+## 三、佣金结构(推荐方案)
+
+### 3.1 两级分佣
+
+```
+佣金池:每次能量师年费收入的 40% 用于分销
+
+        能量师 A(上级)
+            │
+            ├── 一级佣金:30%  ← 直接推荐的好友 B 升级
+            │
+            ▼
+         能量师 B(A的直接下级)
+            │
+            ├── 二级佣金:10%  ← B推荐的好友 C 升级
+            │
+            ▼
+         能量师 C(B的直接下级)
+```
+
+| 层级 | 比例 | 金额(以 ¥398 计) | 说明 |
+|------|------|-------------------|------|
+| **一级佣金** | **30%** | **¥119.4** | 直接推荐的用户升级为能量师 |
+| **二级佣金** | **10%** | **¥39.8** | 下级推荐的用户升级为能量师 |
+| **平台留存** | **60%** | **¥238.8** | 覆盖成本 + 利润 |
+
+> **后台可配置**:以上比例为默认值,运营后台支持随时调整一级佣金(20%-40%)和二级佣金(5%-15%)。
+
+### 3.2 为什么用两级?
+
+| 层级数 | 优点 | 缺点 |
+|--------|------|------|
+| 一级(仅直接) | 简单,平台利润高 | 下级没有推广动力 |
+| **两级(推荐)** | **下级有动力推广,裂变效果强** | **计算略复杂,但可控** |
+| 三级+ | 裂变动能最强 | 法律风险(接近传销),管理复杂 |
+
+> 两级分销在法律上是安全的(《禁止传销条例》界定三级及以上为团队计酬),同时足够激励下级继续推广。
+
+### 3.3 佣金触发条件
+
+```
+用户注册(记录上级关系)
+    │
+    ▼(一直以普通用户身份使用)
+    │
+    ├── 不付费 → 无佣金,保留上级关系
+    │
+    └── 购买 ¥398 年服务包升级能量师
+         │
+         ├── 上级:获得 30% 佣金(¥119.4)
+         ├── 上上级:获得 10% 佣金(¥39.8)
+         └── 平台:获得 60%(¥238.8)
+```
+
+---
+
+## 四、上下级关系的建立与追踪
+
+### 4.1 分享链路
+
+```
+能量师在小程序生成专属推广码/卡片
+              │
+              ▼
+分享到微信好友 / 朋友圈 / 微信群
+              │
+              ▼(用户点击/扫码)
+              │
+用户打开小程序 → 页面路径携带上级 referralCode
+              │
+              ▼
+用户注册微信授权 → 记录 referrer = 能量师A的ID
+              │
+              ▼
+用户后续消费升级 → 触发佣金结算
+```
+
+### 4.2 每个能量师的推广物料
+
+| 物料类型 | 生成方式 | 传播场景 |
+|---------|---------|---------|
+| **专属小程序码** | 云函数生成(wxacode) | 朋友圈海报、文章配图 |
+| **小程序分享卡片** | 微信原生分享能力 | 微信群、微信对话 |
+| **专属链接** | 小程序路径 + referralCode 参数 | 公众号、短视频简介 |
+
+### 4.3 关系锁定规则
+
+```
+注册时间线:
+  T1: 用户B点击A的链接打开小程序(记录A的referralCode到本地缓存)
+  T2: 用户B授权登录(创建用户记录,将A设为上级)
+  T3: 用户B又点击C的链接 → 不会覆盖,上级关系T2已锁定
+  T4: 用户B升级能量师 → 佣金结算给A(和A的上级)
+```
+
+> **关键规则:上级关系在用户首次注册时一次性锁定,不能变更。**
+> 防止恶意"抢上级"和反复修改关系。
+
+---
+
+## 五、佣金结算与提现
+
+### 5.1 结算流程
+
+```
+用户支付 ¥398
+    │
+    ▼
+微信支付回调 → 云函数 paymentCallback
+    │
+    ▼
+1. 更新用户状态为能量师
+2. 自动生成专属推广码
+3. 查询用户的 referrer(上级)
+4. 如果上级存在且是能量师 → 创建佣金记录(¥119.4,可提现)
+5. 查询上级的上级(上上级)
+6. 如果上上级存在且是能量师 → 创建佣金记录(¥39.8,可提现)
+```
+
+### 5.2 佣金状态机
+
+```
+可提现(Available)—— 支付成功后即时到账
+    │(能量师主动发起提现)
+    ▼
+提现中(Processing)
+    │(平台审核+打款,1-3个工作日)
+    ▼
+已到账(Completed)
+```
+
+> 无冷静期,下级升级成功即结算。退款发生时,平台从该能量师的后续佣金中抵扣(或从提现申请中扣除)。
+
+### 5.3 提现规则
+
+| 项目 | 规则 |
+|------|------|
+| 最低提现金额 | **¥100**(减少小额提现的操作成本) |
+| 提现手续费 | 平台承担微信支付手续费(0.6%) |
+| 提现方式 | 微信零钱到账(通过企业付款到零钱API) |
+| 提现周期 | 每周可提现1次 |
+| 佣金有效期 | 无限期(能量师账号存续期间) |
+| **退款处理** | 佣金已提现则从后续佣金抵扣;未提现则撤销该笔佣金 |
+
+---
+
+## 六、能量师的分销后台
+
+### 6.1 个人中心新增板块
+
+```
+┌─────────────────────────┐
+│  我的收益               │
+│  ├── 总收益:¥XXX       │
+│  ├── 可提现:¥XXX       │
+│  ├── 今日预估:¥XX      │
+│  └── 立即提现 →         │
+├─────────────────────────┤
+│  我的团队               │
+│  ├── 直接下级:XX人      │
+│  ├── 间接下级:XX人      │
+│  ├── 下级升级:XX人      │
+│  └── 查看团队列表 →      │
+├─────────────────────────┤
+│  推广工具               │
+│  ├── 生成推广海报 →       │
+│  └── 复制推广链接 →       │
+└─────────────────────────┘
+```
+
+### 6.2 分销参数配置总览
+
+| 参数 | Phase 1 建议值 | 调整方式 |
+|------|---------------|---------|
+| 一级佣金比例 | 30%(¥119.4) | 后台可配置(20%-40%) |
+| 二级佣金比例 | 10%(¥39.8) | 后台可配置(5%-15%) |
+| 结算方式 | 即时到账(无冷静期) | 确认不变 |
+| 最低提现 | ¥100 | 后台可配置 |
+| 推广资格 | 仅能量师 | 确认不变 |
+
+---
+
+## 七、分销模式的商业测算
+
+### 7.1 场景假设
+
+| 参数 | 值 |
+|------|-----|
+| 每个能量师每年直接推荐 | 5个新能量师 |
+| 二级转化率(下级推荐) | 每个下级推荐2个 |
+| 种子能量师数量 | 50人 |
+
+### 7.2 增长模拟
+
+```
+第1年:
+  50名种子能量师
+  ├── 直接推荐:50 × 5 = 250 新能量师
+  └── 二级裂变:250 × 2 = 500 新能量师
+  └── 总量:50 + 250 + 500 = 800 名能量师
+
+第2年(800名能量师继续裂变):
+  直接推荐:800 × 5 = 4,000
+  二级裂变:4,000 × 2 = 8,000
+  总量:800 + 4,000 + 8,000 = 12,800 名能量师
+```
+
+### 7.3 收入测算
+
+| 项目 | 第1年 | 第2年 |
+|------|-------|-------|
+| 年费总收入(¥398 × 总量) | ¥318,400 | ¥5,094,400 |
+| 佣金支出(40%) | ¥127,360 | ¥2,037,760 |
+| **平台净收入(60%)** | **¥191,040** | **¥3,056,640** |
+| 每个能量师平均年佣金 | ¥2,547 |  —  |
+
+> 50个种子用户启动,第一年即可产生近 ¥20万 平台净收入,且增长完全靠分销驱动,无需投放获客成本。
+
+---
+
+## 八、风险控制
+
+| 风险 | 概率 | 影响 | 应对措施 |
+|------|------|------|---------|
+| 恶意刷佣金 | 低 | 资金损失 | 同设备/同IP检测 + 异常交易监控 |
+| 退款纠纷 | 中 | 佣金赔付 | 已提现佣金从后续佣金抵扣;未提现的直接撤销 |
+| 能量师投诉上级分配不公 | 低 | 口碑受损 | 注册时明确提示"上级关系一经锁定不可更改" |
+| 政策合规风险 | 低 | 封禁/处罚 | 严格控制在两级分销,不做团队计酬,不收取入门费 |
+
+---
+
+## 九、技术实现要点
+
+### 9.1 数据库模型
+
+```
+users 集合:
+  {
+    _openid: "微信openid",
+    role: "regular" | "practitioner",  // 角色
+    practitionerExpireAt: Date,        // 能量师有效期
+    
+    // 分销字段
+    referralCode: "ABC123",            // 唯一推广码
+    invitedBy: "上级的_openid",        // 上级(注册时锁定)
+    referralCount: {                   // 推广统计
+      direct: 5,                       // 直接下级总数
+      indirect: 12,                    // 间接下级总数
+      converted: 3,                    // 下级转化为能量师的人数
+    },
+    
+    createdAt: Date,
+  }
+
+commissions 集合:
+  {
+    _id: "佣金记录ID",
+    fromUser: "消费用户的_openid",
+    toUser: "获得佣金用户的_openid",
+    level: 1 | 2,                     // 一级/二级佣金
+    amount: 119.4,                    // 佣金金额
+    sourceOrder: "订单ID",
+    status: "available" | "processing" | "completed" | "cancelled",
+    createdAt: Date,
+  }
+```
+
+### 9.2 分享路径设计
+
+```javascript
+// 能量师分享时,路径携带 referralCode
+const path = `/pages/index/index?ref=${referralCode}`;
+
+// 用户打开小程序时,从 options 读取 ref 参数
+Page({
+  onLoad(options) {
+    if (options.ref) {
+      wx.setStorageSync('pending_referrer', options.ref);
+    }
+  },
+  
+  onRegister() {
+    const ref = wx.getStorageSync('pending_referrer');
+    // 注册时传给云函数保存
+    cloud.callFunction({
+      name: 'registerUser',
+      data: { referrerCode: ref },
+    });
+  },
+});
+```
+
+---
+
+## 十、总结:为什么这个分销模式能跑通
+
+```
+能量师的利益链:
+  用工具(¥398/年)→ 省时间 → 多接客户 → 赚更多钱
+                            ↓
+                    推广工具(分享链接)
+                            ↓
+                    别人购买 → 我得佣金(¥119.4)
+                            ↓
+                    躺着赚钱,有持续动力推广
+
+平台获得的:
+  零获客成本增长
+  能量师既是用户又是推广员
+  100个能量师 = 100个推广渠道
+```
+
+> **一句话:** 能量师 ¥398 买的是工具,工具帮他赚钱,他帮平台拉人——三方共赢,飞轮转起来。

+ 65 - 0
docs/executive-summary.md

@@ -0,0 +1,65 @@
+# 数字能量学智能体平台 — 投资摘要
+
+> **一句话:** 以生日为入口,AI 为引擎,数字能量学为语言——帮助每个人认识自己、匹配他人。
+
+---
+
+## 市场机会
+
+数字命理赛道已验证:灵机文化年营收过亿,星座/塔罗 App 用户量千万级。但行业仍是"师傅接散客"的原始状态,没有标准化平台。**我们对标的是美国 astrology.com(月活 2000 万+,订阅制模式),但做的是中国本土的数字能量学版本——比八字简单、比星座有据、比纯社交有深度。**
+
+## 我们的三层价值
+
+| 面向谁 | 给什么 | 怎么赚钱 |
+|--------|--------|----------|
+| **大众用户** | 3 秒生成命盘 + AI 解读 + 人格匹配交友 | VIP 月卡/年卡订阅 |
+| **能量师** | 客户管理 + 批量工具 + 平台获客 | 专业版年费 + 每单抽佣 20% |
+| **平台自身** | 海量命盘数据 → 训练专属 AI 模型 → 输出 API | 数据壁垒 + B 端 API 服务 |
+
+## 最大的创新:数字人格匹配
+
+这不是又一个算命工具。通过数字能量学的主性格 + 五区互补模型,实现**人与人之间的精准匹配**——适合交友、合作、婚恋。匹配卡片可分享到微信,天然社交裂变。远期可做陌生人社交,**把低频算命变成高频匹配互动。**
+
+## 持续变现:数字调理 + 电商
+
+传统命理是一锤子买卖——出完报告关系结束。我们引入**数字调理**,让服务延续:
+
+- 分析先天命盘缺失/过旺的数字能量
+- 提供个性化调理建议:命名用数、号码选择、色彩搭配、方位建议、配饰能量补充等
+- **从"解读一次"变成"长期调理顾问"**,极大提升 LTV
+
+同时开辟**电商闭环**:数字产品(报告/方案)平台自营 100% 毛利,实物商品(水晶/饰品)由能量师供货平台抽佣 20-30%,第三方商家入驻抽佣 15-25%。AI 根据每位用户的命盘缺失数字精准推荐,天然是"一人一策"的个性化电商。
+
+## 数据飞轮 = 护城河
+
+```
+用户增长 → 数据积累 → AI 解读更准 → 体验更好 → 用户更多
+         → 匹配更准 → 留存更高 → 用户更多
+```
+
+数据越多,壁垒越厚。后期可输出企业用人测评、婚恋平台接口等 B 端能力。
+
+## 营收模型
+
+| 来源 | 模式 | 预期占比 |
+|------|------|----------|
+| VIP 订阅 | C 端月卡/年卡 | 35% |
+| 电商收入 | 数字产品自营 + 实物抽佣 20%-30% | 30% |
+| 咨询抽佣 | 每笔 20% | 15% |
+| 专业版年费 | B 端能量师 | 10% |
+| API 服务 | B 端输出 | 10%(远期) |
+
+## 阶段路径
+
+- **Phase 1** — MVP 上线(命盘 + 免费解读 + VIP 支付),验证核心转化
+- **Phase 2** — AI 对话 + 能量师入驻 + 轻量匹配,建立数据飞轮
+- **Phase 3** — 陌生人社交 + 内容社区,冲击月活 10 万
+- **Phase 4** — 知识库 API + 企业服务,B 端营收占比 30%
+
+## 团队在做的事
+
+目前已完产品方向探索,形成了完整的三角形命盘方案、用户流程、功能分层,准备进入 MVP 开发阶段。技术选型为微信小程序 + 后端接入 LLM,轻资产启动。
+
+---
+
+> **我们要建的不是一个算命小程序,而是一个通过数字认识人、连接人的智慧平台。**

二进制
docs/investor-deck.pptx


+ 438 - 0
docs/phase1-product-plan.md

@@ -0,0 +1,438 @@
+# 数字能量学智能体 — Phase 1 产品规划
+
+> 版本: v1.1
+> 定位: 面向数字能量师的AI智能工具,最小成本 + 最快回血
+> 口号: 3秒出命盘 + AI自动解读,让能量师聚焦客户沟通,而非画图和查资料
+
+---
+
+## 一、Phase 1 核心理念
+
+### 1.1 用户模型
+
+```
+用户注册 → 普通用户(免费,体验入口)
+              │
+              ├── 每日3次命盘生成
+              ├── 每日1次主性格概要解读
+              └── 通过能量师分享链接注册(建立上下级关系)
+              │
+              ▼(购买年服务包)
+         能量师用户(¥398/年,核心付费用户)
+              │
+              ├── 无限命盘生成 + AI五区完整解读
+              ├── 无限分享 + PDF导出 + 全部历史
+              ├── 获得专属推广二维码/卡片
+              └── 发展下级用户,为分销模式打基础
+```
+
+### 1.2 为什么先服务能量师?
+
+| 维度 | 做能量师版本 | 做大众人版本 |
+|------|-------------|-------------|
+| 付费意愿 | 高(工具提升工作效率,愿意付费) | 低(免费习惯,需要教育) |
+| 获客成本 | 低(圈层集中,口碑传播) | 高(需要投流/裂变) |
+| 现金流 | 快(年费订阅,锁定1年) | 慢(需要用户量积累) |
+| 壁垒 | 中等(功能迁移成本高) | 低(容易同质化竞争) |
+| 数据价值 | 专业级标注数据,对AI训练极有价值 | 大众数据噪音大 |
+
+**结论:先服务能量师,用年费快速回笼资金,同时积累专业级数据。有了钱+数据,再去做大众版本。**
+
+### 1.3 最小可行范围(MVP刀法)
+
+```
+做(Phase 1 范围):
+  ✅ 三角形命盘快速生成(输入生日 → 3秒出图)
+  ✅ AI 自动解读(主性格 + 五区深度解读)
+  ✅ 命盘分享 / 导出图片 / 导出PDF(含解读内容)
+  ✅ 能量师年费订阅 & 支付
+  ✅ 基础个人中心 + 历史记录
+  ✅ 分销系统基础(推广码生成 + 分享带参注册 + 上下级关系绑定)
+  ✅ 能量师分销后台(收益统计 / 团队概览 / 推广工具)
+
+不做(Phase 2+ 再做):
+  ❌ AI 对话咨询(多轮交互,留到 Phase 2)
+  ❌ 客户管理 / 多人管理(客户分组等)
+  ❌ 数字调理方案
+  ❌ 人格匹配 / 陌生交友
+  ❌ 大众版免费引流流程
+  ❌ 电商模块
+  ❌ 咨询交易平台
+  ❌ 佣金自动提现到微信零钱(Phase 1 手动打款)
+```
+
+---
+
+## 二、目标用户画像
+
+### 2.1 核心用户:数字能量师
+
+| 属性 | 描述 |
+|------|------|
+| 年龄 | 25-50岁 |
+| 职业 | 命理师 / 数字能量爱好者 / 心理咨询从业者 / 身心灵行业从业者 |
+| 当前痛点 | 手动画三角形图费时、不专业、发给客户不好看、缺乏数字化工具 |
+| 付费能力 | 月收入1-5万,愿意为工具付费 |
+| 传播方式 | 圈层内口碑(微信群、朋友圈),信任成本高但传播精准 |
+| 核心需求 | **快速出图 + AI自动解读 + 专业呈现 + 方便分享** |
+
+### 2.2 用户故事(User Story)
+
+> **"我是一个数字能量师,客户给我生日,我手动画图10分钟、还要翻书查每个数字的含义再组织语言。如果有个工具3秒出图+AI自动写出完整解读,我直接发给客户或稍微润色就能用,一年掏几百块非常值。"**
+
+---
+
+## 三、功能列表(按优先级)
+
+| 优先级 | 模块 | 功能 | 说明 |
+|--------|------|------|------|
+| **P0** | 命盘生成 | 输入姓名+生日 → 自动生成三角形命盘 | 核心引擎,纯前端计算 |
+| **P0** | 命盘展示 | 三角形可视化,15格数字填充 | Canvas绘制 |
+| **P0** | AI解读 | 根据命盘数字自动生成主性格+五区解读文本 | LLM API(云函数调用) |
+| **P0** | 命盘分享 | 生成分享图/导出PDF(含解读) | 微信小程序分享卡片 |
+| **P0** | 付费订阅 | 能量师年费支付(微信支付) | 核心变现入口 |
+| **P0** | **分销推广** | **生成专属推广码(小程序码/卡片),分享带参注册** | **分销裂变入口** |
+| **P1** | 用户体系 | 微信登录 + 订阅状态管理 + 上下级关系 | 必要底层 |
+| **P1** | 历史记录 | 已生成的命盘列表、查看、删除 | 留存和复访 |
+| **P1** | **分销后台** | **收益统计 / 团队列表 / 提现申请** | **能量师推广中心** |
+| **P2** | 批注功能 | 在命盘图上添加备注/标记 | 能量师自行标注用 |
+| **P2** | 客户分组 | 简单管理客户(标签/分组) | 客户管理雏形 |
+| **P3** | 报告模板 | 预设几种报告样式供选择 | 可后续补 |
+
+---
+
+## 四、页面拓扑(Phase 1)
+
+### 4.1 页面清单
+
+```
+┌─────────────────────┐
+│  首页 (输入页)       │  P0  — 核心入口
+│  - 姓名 + 生日输入   │        微信用户可直接操作
+│  - "生成命盘"按钮    │
+└────────┬────────────┘
+         ▼
+┌─────────────────────┐
+│  命盘展示页           │  P0  — 核心功能
+│  - 三角形可视化       │        支持点击数字查看含义
+│  - "查看AI解读"按钮   │
+│  - 底部:分享/导出    │
+│  - 底部:去订阅(未付费)│
+└────────┬────────────┘
+         ▼
+┌─────────────────────┐
+│  AI解读页            │  P0  — 核心亮点
+│  - 主性格深度解读     │        LLM生成,分段展示
+│  - 五区逐一解读       │        加载时有loading动画
+│  - 底部:分享/导出PDF │        含完整解读内容
+│  - 底部:去订阅(未付费)│
+└────────┬────────────┘
+         ▼
+┌─────────────────────┐
+│  分享/导出流程        │  P0  — 核心变现点
+│  - 生成分享卡片       │        免费用户每日1次
+│  - 导出PDF           │        已订阅用户不限
+│  - (未付费)→ 付费引导  │
+└─────────────────────┘
+
+┌─────────────────────┐
+│  个人中心             │  P1  — 基础留存
+│  - 订阅状态/到期日    │
+│  - 历史命盘列表       │
+│  - 订阅/续费入口      │
+│  - (能量师) 我的收益 → │  ← 分销入口
+│  - (能量师) 推广工具 → │  ← 分销入口
+└─────────────────────┘
+
+┌─────────────────────┐
+│  分销面板(能量师专享)│  P1  — 裂变驱动
+│  - 总收益 / 可提现金额 │
+│  - 团队统计(直推/间推/转化)│
+│  - 我的推广码(保存/分享)│
+│  - 提现申请 → 平台审核  │
+└─────────────────────┘
+
+┌─────────────────────┐
+│  付费页               │  P0  — 核心变现
+│  - 年费价格展示       │
+│  - 功能对比(含AI解读)│
+│  - 微信支付          │
+└─────────────────────┘
+
+**共 5 个核心页面,AI解读页是核心亮点。**
+
+---
+
+## 五、收费模式
+
+### 5.1 定价策略
+
+| 方案 | 价格 | 说明 |
+|------|------|------|
+| **能量师年服务包** | **¥398/年** | 唯一付费方案,含AI完整解读 + 分销权,种子价即定价 |
+| 月费(可选增设) | ¥39/月 | 降低入门门槛,能量师可月付升级 |
+| 单次解读(可选增设) | ¥9.9/次 | 未订阅用户的AI解读单次购买 |
+
+> 定价逻辑:AI出图+出解读,能量师接2-3个客户(¥100-300)即可回本,后续净赚。
+> ¥398/年 ≈ 每天仅 ¥1.09,对能量师而言是极低的生产力投资。
+> **佣金支出上限 40%**,年服务包实际平台净收入约 ¥238.8/人。
+> 分销驱动增长:能量师推荐好友购买年包,得 ¥119.4/人 佣金。
+> 100个种子能量师,人均推荐5人,年费收入 x6 倍增长。
+>
+> **已确认决策**:一级 30% / 二级 10%(后台可配置)| 即时结算,无冷静期 | 最低提现 ¥100 | 仅能量师享有分销权
+
+### 5.2 免费 vs 付费
+
+| 功能 | 普通用户(免费) | 能量师(¥398/年) |
+|------|----------------|------------------|
+| 生成命盘 | 每日 3 次 | 不限次数 |
+| 查看命盘 | ✅ | ✅ |
+| **AI 基础解读(主性格概要)** | ✅(每日1次) | ✅ 不限 |
+| **AI 完整解读(五区全解)** | ❌ | ✅ 不限 |
+| 分享命盘图片(含解读) | 每日 1 次 | 不限 |
+| 导出 PDF(含解读) | ❌ | ✅ |
+| 历史记录 | 近 7 天 | 全部 |
+| **生成专属推广码** | ❌ | ✅ |
+| **发展下级 / 赚取佣金** | ❌ | ✅ |
+| **分销面板(收益/团队)** | ❌ | ✅ |
+
+> 免费额度足够能量师**试用体验**,但不足以替代日常工作。
+> 3次/天试完正好到付费决策点——"一天都不够我用"。
+
+---
+
+## 六、三角形命盘计算引擎(通用算法)
+
+### 6.1 输入
+
+- 出生年份(4位数,如 1990)
+- 出生月份(2位数,如 01 或 1)
+- 出生日期(2位数,如 01 或 1)
+
+### 6.2 处理规则
+
+**Step 1: 提取底层5位数字 A, B, C, D, E**
+
+```
+A = 年份第一位                     (如 1990 → 1)
+B = 年份第二位                     (如 1990 → 9)
+C = 年份第三位 + 年份第四位 归约至个位   (如 1990 → 9+0=9)
+D = 月份 归约至个位                  (如 01 → 1, 12 → 1+2=3)
+E = 日期 归约至个位                  (如 01 → 1, 23 → 2+3=5)
+```
+
+**Step 2: 逐层向上计算(两两相加归约至个位)**
+
+```
+F = A + B (归约至个位)
+G = B + C (归约至个位)
+H = C + D (归约至个位)
+I = D + E (归约至个位)
+
+J = F + G (归约至个位)
+K = G + H (归约至个位)
+L = H + I (归约至个位)
+
+M = J + K (归约至个位)
+N = K + L (归约至个位)
+
+O = M + N (归约至个位)  ← 主性格数字
+```
+
+**归约至个位规则:** 如果数字 > 9,则各位数字相加,重复直到结果为 1-9。
+**例外:** 11, 22, 33 为卓越数,保留不继续化简。
+
+### 6.3 三角形布局
+
+```
+               O
+             J   K
+           F   G   H   I
+         A   B   C   D   E
+```
+
+### 6.4 五区定义
+
+| 区域 | 包含位置 | 含义 |
+|------|---------|------|
+| 主性格 | O | 核心人格特质 |
+| 父源区 | F, J | 父亲遗传、先天能量 |
+| 母源区 | I, L | 母亲遗传、后天能量 |
+| 左区(0-20岁) | A, F, J, O | 早年运势 |
+| 中区(20-40岁) | B, G, K, M, O | 中年发展 |
+| 右区(40-60岁) | C, D, E, H, I, L, O | 晚年成就 |
+
+### 6.5 代码级示例(JavaScript)
+
+```javascript
+function reduceToDigit(n) {
+  if (n === 11 || n === 22 || n === 33) return n;
+  while (n > 9) {
+    n = String(n).split('').reduce((s, c) => s + parseInt(c), 0);
+  }
+  return n;
+}
+
+function calculateTriangle(birthYear, birthMonth, birthDay) {
+  const y = String(birthYear).padStart(4, '0');
+  const m = String(birthMonth).padStart(2, '0');
+  const d = String(birthDay).padStart(2, '0');
+
+  // 底层
+  const A = parseInt(y[0]);
+  const B = parseInt(y[1]);
+  const C = reduceToDigit(parseInt(y[2]) + parseInt(y[3]));
+  const D = reduceToDigit(parseInt(m[0]) + parseInt(m[1] === '0' ? m[1] : m[0]+m[1]));
+  // Simpler: month as sum of digits
+  const D = reduceToDigit(birthMonth);
+  const E = reduceToDigit(birthDay);
+
+  // 第二层
+  const F = reduceToDigit(A + B);
+  const G = reduceToDigit(B + C);
+  const H = reduceToDigit(C + D);
+  const I = reduceToDigit(D + E);
+
+  // 第三层
+  const J = reduceToDigit(F + G);
+  const K = reduceToDigit(G + H);
+  const L = reduceToDigit(H + I);
+
+  // 第四层
+  const M = reduceToDigit(J + K);
+  const N = reduceToDigit(K + L);
+
+  // 顶端
+  const O = reduceToDigit(M + N);
+
+  return { A, B, C, D, E, F, G, H, I, J, K, L, M, N, O };
+}
+```
+
+> **注意:** 此算法为通用实现。如果后续您的真实算法不同,引擎设计为可配置,替换 reduceToDigit 和底层排列规则即可。
+
+---
+
+## 七、技术选型建议
+
+| 层 | 推荐 | 理由 |
+|----|------|------|
+| 小程序框架 | **微信原生** | 最轻量,无需额外依赖,文档最全 |
+| 后端 | **Node.js (Serverless)** | 小程序云开发最低成本,按量计费 |
+| 数据库 | **微信云开发数据库** | 免运维,与小程序深度集成 |
+| 登录 | **微信一键登录** | 零成本 |
+| 支付 | **微信支付** | 小程序内直接支付 |
+| 命盘计算 | **前端计算** | 纯数学运算,无需后端,秒级出结果 |
+| **AI 解读** | **云函数 + LLM API** | 接受命盘数据,调用LLM生成解读文本 |
+| PDF导出 | **html2canvas + jspdf** | 前端生成,省掉后端渲染服务 |
+| 部署 | **云开发一键部署** | 免运维 |
+
+**预估初始成本:**
+- 云开发基础版:¥免费(500MB数据库 + 5GB存储 + 1000RU/天)
+- 域名/证书:¥0(小程序自带)
+- 微信支付:¥0(仅收交易手续费0.6%)
+- **LLM API 费用:** ¥0.001-0.003/次(以DeepSeek等模型为例,一次解读约500-800 tokens)
+  - 100个能量师 × 平均每天10次解读 × ¥0.002 = **¥2/天**
+  - **月运营成本 ≈ ¥0(云计算免费额度内)+ ¥60(LLM API = 100用户量级)**
+
+---
+
+## 八、发布路线图
+
+### Week 1-2:核心引擎 + AI解读
+
+| 天数 | 里程碑 |
+|------|--------|
+| D1-2 | 项目初始化 + 小程序框架搭建 |
+| D3-4 | 三角形命盘计算引擎(含单元测试) |
+| D5-7 | 三角形Canvas可视化组件 |
+| D8-9 | AI解读引擎(Prompt设计 + 云函数接入LLM API) |
+| D10 | 联调、修复、demo |
+
+### Week 3:用户体系 + 付费 + 分销基础
+
+| 天数 | 里程碑 |
+|------|--------|
+| D11-12 | 微信登录 + 用户数据库设计(含上下级关系字段) |
+| D13-14 | 支付集成(微信支付 + 订阅逻辑) + 升级后生成推广码 |
+| D15 | 免费/付费状态管理 + 功能限制 |
+| D16 | 分享带参注册 + 上下级关系绑定 |
+
+### Week 4:AI解读页UI + 分享交付
+
+| 天数 | 里程碑 |
+|------|--------|
+| D17-18 | AI解读页 UI(解读内容排版、Loading状态、分段展示) |
+| D19-20 | 分享卡片生成(含解读)+ PDF导出(含解读) |
+| D21-22 | 分销面板UI(收益/团队/推广码) |
+| D23-24 | 个人中心 + 历史记录 + 联调 |
+| D25 | 联调 + 修复 + 内部测试 |
+
+### 上线
+
+| 里程碑 | 时间 |
+|--------|------|
+| 内测(邀请10-20个能量师) | Week 6 |
+| 修复 + 优化 | Week 7 |
+| **正式上线 + 种子用户推广(含分销裂变)** | **Week 8** |
+| 回款(首批年费 + 佣金结算测试) | 上线即产生 |
+
+**从启动到回款 ≈ 55-60天,总开发投入 ≈ 1人 × 8周。**
+
+---
+
+## 九、上线后的快速迭代方向
+
+```
+Phase 1 (Week 7 上线)
+  │
+  ├── Phase 1.1 (上线后 2周)
+  │   ├── 批注功能(能量师强烈要求 #1)
+  │   └── 客户分组(基础CRM)
+  │
+  ├── Phase 1.2 (上线后 4周)
+  │   ├── AI 基础解读(主性格数字含义)
+  │   └── 报告模板(2-3 种风格)
+  │
+  └── Phase 2 (上线后 8周)
+      ├── 数字调理方案(变现升级)
+      ├── 电商模块(配件推荐)
+      └── 大众版引流入口
+```
+
+---
+
+## 十、风险与缓解
+
+| 风险 | 可能性 | 影响 | 缓解 |
+|------|--------|------|------|
+| 能量师获客慢 | 中 | 现金流延迟 | 首发¥398锁定种子用户,朋友圈裂变奖励 + 分销佣金驱动 |
+| 算法与能量师预期不符 | 高 | 产品不可用 | 上线前先给5个能量师验证算法正确性 |
+| **AI解读质量不够专业** | **中** | **能量师不认可** | Prompt中融入数字能量学专业术语和体系,支持能量师自行调整润色 |
+| **LLM API成本失控** | **低** | **利润被吃掉** | 限流+缓存机制,同一命盘重复请求时不重复调用API |
+| **分销佣金纠纷** | **中** | **口碑受损** | 注册时明确提示"上级关系终身锁定",退款从后续佣金抵扣 |
+| **分销模式涉传风险** | **低** | **封禁/处罚** | 严格控制在两级分销,无团队计酬、无入门费,合规底线 |
+| 竞品快速跟进 | 中 | 价格战 | 用数据+AI壁垒,竞品只有工具我们有平台+数据 |
+| 微信审核不通过 | 中 | 上线延迟 | 预审规范,文案强调"传统文化分析工具",避免"算命/占卜"等敏感词 |
+| 能量师不习惯小程序 | 低 | 用户流失 | 提供微信群教程、1对1服务种子用户 |
+
+---
+
+## 十一、关键数据指标(Phase 1)
+
+| 指标 | Phase 1 目标 |
+|------|-------------|
+| 种子用户 | 100个能量师(付费) |
+| 年费收入 | ¥39,800 — ¥79,600(100-200人 × ¥398) |
+| 日命盘生成量 | 500+ |
+| 日活用户 | 50+ 能量师 |
+| 净推荐值(NPS) | > 60(口碑种子) |
+| 用户留存(7日) | > 60% |
+| **能量师推广转化率** | **> 20%(邀请注册 → 付费升级)** |
+| **平均每能量师邀请人数** | **> 3人** |
+
+> Phase 1 核心指标是验证"分销驱动增长"模型:能量师是否愿意分享、被邀请者是否愿意付费升级。这两个指标达标再加大分销投入。
+
+---
+
+> **一句话总结:** 用 6 周做一个"能量师的AI智能工具",输入生日即得命盘+AI完整解读,让能量师付 **¥398/年** 换来命盘解读一步到位,快速滚起现金流,再拿钱迭代大众版 + 电商。

+ 364 - 0
docs/phase1-user-stories.md

@@ -0,0 +1,364 @@
+# Phase 1 用户故事与验收标准
+
+> 基于 `phase1-product-plan.md`,每个用户故事包含:标题、描述、验收标准、优先级
+
+---
+
+## EPIC 1:命盘生成与展示(P0)
+
+### US-1.1 生日输入与命盘生成
+
+**作为** 数字能量师  
+**我希望** 输入客户的姓名和出生年月日,3秒内生成完整的三角形命盘  
+**以便** 取代手动画图,提高工作效率
+
+**验收标准:**
+
+1. 输入页面包含:姓名(选填)、出生年份(4位数字)、月份(1-12)、日期(1-31)
+2. 月份和日期支持数字键盘输入,也有下拉选择器
+3. 验证:年份必须为 1900-当前年份、月份 1-12、日期根据月份合法性验证
+4. 输入无效时显示具体错误提示(如"请输入正确的出生日期")
+5. 点击"生成命盘"后,3秒内显示结果(纯前端计算,无需联网)
+6. 命盘页面 URL 可分享
+
+### US-1.2 三角形命盘可视化展示
+
+**作为** 数字能量师  
+**我希望** 看到一个清晰、美观的数字三角形,每个位置都标有数字  
+**以便** 直接用于客户讲解
+
+**验收标准:**
+
+1. 页面使用 Canvas 绘制三角形,5层15个数字位置完整展示
+2. 布局严格遵循:
+   ```
+         O
+       J   K
+     F   G   H   I
+   A   B   C   D   E
+   ```
+3. 每个数字使用单独的圆形/方形卡片展示,字体清晰易读
+4. 五区使用不同背景色区分(左区/中区/右区/父源/母源/主性格)
+5. 数字颜色:1-9 每个数字有独立颜色(参考能量数字配色)
+6. 卓越数(11/22/33)用特殊标记突出
+7. 底部显示姓名和出生日期信息
+
+### US-1.3 数字点击查看含义
+
+**作为** 数字能量师  
+**我希望** 点击三角形中的每个数字可以查看该位置的含义和能量解读  
+**以便** 快速向客户解释命盘
+
+**验收标准:**
+
+1. 点击三角形中的任一数字卡片,底部弹出该位置的解释面板
+2. 解释面板显示:位置名称(如"主性格")、数字、性格特质描述
+3. 再次点击或点击空白区域关闭面板
+4. 5区位置的描述文字可配置(后续通过后台修改)
+
+---
+
+## EPIC 2:分享与导出(P0)
+
+### US-2.1 命盘分享图片
+
+**作为** 数字能量师  
+**我希望** 将命盘生成为一张精美的图片,分享到微信或保存到相册  
+**以便** 发给客户或在朋友圈展示
+
+**验收标准:**
+
+1. 分享按钮位于命盘展示页下方
+2. 点击"分享"按钮,生成包含命盘图+姓名+生日的分享卡片
+3. 分享卡片支持:保存到相册 / 分享给微信好友 / 分享到朋友圈
+4. 分享卡片设计精美,带有品牌水印(可选)
+5. 免费用户每日限制 1 次分享,已付费用户不限
+
+### US-2.2 命盘PDF导出
+
+**作为** 数字能量师  
+**我希望** 将命盘导出为 PDF 文件,可以直接打印或微信发送  
+**以便** 客户获得正式的纸质/电子版报告
+
+**验收标准:**
+
+1. PDF 按钮位于命盘展示页(仅已付费用户可见)
+2. 点击后生成包含命盘三角形+姓名+生日+日期的 PDF
+3. PDF 使用 A4 竖版排版,适合打印
+4. 生成过程不超过 5 秒
+5. 生成后自动进入微信文件预览,支持转发给微信好友
+
+---
+
+## EPIC 3:AI 解读(P0)
+
+### US-3.1 AI 解读展示
+
+**作为** 数字能量师  
+**我希望** 在命盘生成后,看到由AI自动生成的完整文字解读  
+**以便** 直接发给客户或稍作润色后使用,节省自己查资料写解读的时间
+
+**验收标准:**
+
+1. 命盘展示页底部有"查看AI解读"按钮,点击跳转到AI解读页
+2. 解读内容由LLM生成,通过云函数调用,首次加载等待时间 < 5秒
+3. 加载过程中显示骨架屏或loading动画,避免用户以为卡死
+4. 解读内容至少包含以下章节:
+   - **主性格解读**:顶端数字的核心特质、性格描述、代表人物
+   - **左区(0-20岁)**:早年运势、成长环境
+   - **中区(20-40岁)**:中年事业、人际关系
+   - **右区(40-60岁)**:晚年成就、财运趋势
+   - **父源区**:父亲遗传、先天能量
+   - **母源区**:母亲遗传、后天影响
+5. 每个章节独立卡片展示,可折叠展开
+6. 解读内容基于命盘的实际数字,同一数字对不同命盘解读不同(位置差异)
+7. 页面底部显示"本解读由AI生成,仅供参考"的免责声明
+
+### US-3.2 AI 解读的免费/付费控制
+
+**作为** 平台运营者  
+**我希望** 控制AI解读功能的免费与付费边界  
+**以便** 激励用户订阅能量师年服务包
+
+**验收标准:**
+
+1. 未付费用户点击"查看AI解读"时,仅显示**主性格概要**(1段文字)
+2. 未付费用户每日可查看主性格概要 1 次
+3. 五区完整解读仅在已付费后可用
+4. 已付费能量师可无限次查看完整解读
+5. 每次解读请求记录到数据库,用于成本控制和限流
+
+### US-3.3 解读内容缓存
+
+**作为** 系统  
+**我希望** 同一命盘的重复解读请求不重复调用LLM API  
+**以便** 控制成本,避免同一命盘每次查看都消耗API费用
+
+**验收标准:**
+
+1. 首次生成解读后,将解读内容与命盘ID绑定存储到数据库
+2. 后续同一命盘再次查看解读时,直接从数据库读取,不调用LLM
+3. 用户自行重新生成解读时,覆盖旧的缓存内容
+4. 解读缓存永久保留,不自动过期
+
+---
+
+## EPIC 4:付费与订阅(P0)
+
+### US-4.1 付费订阅页
+
+**作为** 数字能量师  
+**我希望** 看到清晰的定价方案并进行年费支付  
+**以便** 获得AI完整解读等全部功能以及分销推广权限
+
+**验收标准:**
+
+1. 付费入口:未付费用户在首页/命盘页/解读页/分享时均会看到升级引导
+2. 付费页展示:功能对比表(普通用户 vs 能量师,突出AI完整解读+分销权)、价格、支付按钮
+3. 价格展示:年费 ¥398(种子价),无首年/续费区分
+4. 功能对比表清晰展示:免费只能看主性格概要,能量师可看五区全解+推广码
+5. 通过微信支付完成订阅
+6. 支付成功后,用户状态即时更新为"能量师",自动生成专属推广码
+7. 支付失败显示友好提示
+
+### US-4.2 订阅状态与续费
+
+**作为** 付费能量师  
+**我希望** 在个人中心看到我的订阅状态、到期日,并能续费  
+**以便** 管理我的会员身份
+
+**验收标准:**
+
+1. 个人中心显示:订阅状态(能量师/已过期/普通用户)
+2. 显示到期日期,到期前 7 天显示续费提醒
+3. 到期后自动降级为普通用户,分销面板关闭
+4. 续费操作与原付费流程一致
+
+---
+
+## EPIC 5:用户与历史(P1)
+
+### US-5.1 微信一键登录
+
+**作为** 能量师  
+**我希望** 使用微信一键登录  
+**以便** 不需要注册账号,降低使用门槛
+
+**验收标准:**
+
+1. 首次使用点击"生成命盘"时弹出微信授权
+2. 授权后自动完成注册,无需填写额外信息
+3. 后续使用自动登录
+4. 用户信息存储在云数据库中
+
+### US-5.2 历史命盘记录
+
+**作为** 能量师  
+**我希望** 查看我过去生成的所有命盘记录  
+**以便** 回顾和重用
+
+**验收标准:**
+
+1. 个人中心页包含"我的命盘"列表
+2. 列表按生成时间倒序排列
+3. 每条记录显示:姓名、生日、生成时间
+4. 点击记录可跳转到对应的命盘展示页
+5. 支持单条删除
+6. 免费用户仅能看到近 7 天记录,已付费用户可见全部
+
+---
+
+## EPIC 6:分销推广与佣金(P0-P1)
+
+### US-6.1 推广码生成
+
+**作为** 能量师  
+**我希望** 在支付升级后自动获得专属推广二维码和推广卡片  
+**以便** 分享给微信好友和朋友圈来发展下级能量师
+
+**验收标准:**
+
+1. 支付升级成功时,系统自动为该用户生成唯一6位推广码(字母+数字)
+2. 分销面板中展示:专属小程序码图片(可通过云函数生成)、推广卡片、可复制链接
+3. 推广码永久有效,不随年费到期失效
+4. 推广卡片包含:能量师昵称头像 + 小程序码 + "扫码免费测命盘"文案
+5. 支持保存到相册 / 分享给微信好友 / 分享到朋友圈
+
+### US-6.2 分享带参注册与上下级绑定
+
+**作为** 平台  
+**我希望** 当用户通过能量师分享的链接/扫码打开小程序时,自动记录上下级关系  
+**以便** 为佣金分成打好基础
+
+**验收标准:**
+
+1. 能量师分享路径携带推广码参数:`/pages/index/index?ref=ABC123`
+2. 用户通过该路径打开小程序时:
+   - 从 `onLoad(options)` 读取 `ref` 参数
+   - 将推广码存入本地缓存 `pending_referrer`
+3. 用户完成微信登录注册时:
+   - 检查本地缓存是否有 `pending_referrer`
+   - 若有,解析推广码对应的能量师用户ID
+   - 将当前用户的 `invitedBy` 字段设为该能量师的ID
+4. 关系锁定规则:
+   - 上下级关系在首次注册时一次性锁定
+   - 后续无论通过谁的链接打开,均不覆盖已有关系
+   - 一个用户最多只有一个上级(能量师)
+5. 普通用户注册时未带推广参数 → `invitedBy` 为空,无上级
+
+### US-6.3 佣金结算
+
+**作为** 平台  
+**我希望** 当用户通过能量师A的链接注册并升级为能量师时,自动计算并记录佣金  
+**以便** 能量师获得推广收益
+
+**验收标准:**
+
+1. 用户支付成功后,云函数触发佣金结算流程
+2. 佣金比例从后台配置读取(默认一级30%/二级10%)
+3. 查询该用户的 `invitedBy` 字段
+4. 若上级存在且是能量师(订阅有效期内):
+   - 创建一级佣金记录:金额按比例计算(默认 ¥119.4),状态"可提现"
+5. 查询上级的上级:
+   - 若上上级存在且是能量师:
+   - 创建二级佣金记录:金额按比例计算(默认 ¥39.8),状态"可提现"
+6. 佣金记录写入 commissions 集合,关联订单ID
+7. 无冷静期,支付成功即结算。退款发生时:若佣金未提现则直接撤销;若已提现则从后续佣金中抵扣
+
+### US-6.4 分销面板
+
+**作为** 能量师  
+**我希望** 在分销面板中查看我的收益和团队数据  
+**以便** 追踪推广效果,激励持续推广
+
+**验收标准:**
+
+1. 个人中心有"我的收益"入口(仅能量师可见)
+2. 分销面板展示:
+   - **总收益**:累计佣金总额
+   - **可提现**:当前可提现佣金余额
+    - **今日新增**:今日新增佣金
+   - **团队统计**:直接下级数 / 间接下级数 / 下级升级为能量师数
+3. 团队列表:按注册时间倒序展示下级用户
+4. 佣金明细列表:展示每笔佣金的时间、来源、金额、状态
+5. "推广工具"区域:重置/保存推广码图片、复制推广链接
+6. "申请提现"按钮(Phase 1 提交申请,平台手动打款)
+
+### US-6.5 提现申请
+
+**作为** 能量师  
+**我希望** 在可提现金额达到最低限额后申请提现  
+**以便** 将推广收益变现
+
+**验收标准:**
+
+1. 可提现金额 ≥ ¥100 时,"申请提现"按钮可点击
+2. 点击后填写提现金额(不得超过可提现金额)
+3. 提交后生成提现申请记录,状态为"待审核"
+4. 平台在后台查看提现申请,手动审核打款
+5. 审核通过后,对应佣金标记为"已完成",不可再提现
+6. 提现申请记录保留流水号供后续对账
+7. Phase 1 不接入自动打款API,平台手动处理
+
+---
+
+## EPIC 7:批注与客户管理(P2)
+
+### US-6.1 命盘批注
+
+**作为** 能量师  
+**我希望** 在命盘图上添加文字批注或标记  
+**以便** 为每个客户记录个性化的解读要点
+
+**验收标准:**
+
+1. 在命盘展示页添加"编辑批注"按钮(仅已付费用户可见)
+2. 点击后进入批注模式,可添加自由文本
+3. 批注内容保存后,下次查看该命盘时依然可见
+4. 批注支持简单的富文本(分段、加粗等)
+5. 导出的 PDF 中可包含批注内容
+
+### US-6.2 客户标签分组
+
+**作为** 能量师  
+**我希望** 为命盘记录添加简单的标签或分组  
+**以便** 对客户进行分类管理
+
+**验收标准:**
+
+1. 创建命盘时可选择已有标签或新建标签
+2. 标签以颜色 + 文字形式展示
+3. 历史列表支持按标签筛选
+4. 标签管理:新增、编辑、删除
+
+---
+
+## 开发优先级总表
+
+| 用户故事 | 优先级 | 预估工期 | 依赖 |
+|----------|--------|---------|------|
+| US-1.1 生日输入与命盘生成 | P0 | 3天 | 无 |
+| US-1.2 三角形可视化 | P0 | 3天 | US-1.1 |
+| US-1.3 数字点击查看含义 | P2 | 1天 | US-1.2 |
+| US-2.1 分享图片 | P0 | 2天 | US-1.2 |
+| US-2.2 PDF导出 | P0 | 2天 | US-1.2 |
+| **US-3.1 AI解读展示** | **P0** | **3天** | **US-1.1 + LLM API接入** |
+| **US-3.2 AI解读免费/付费控制** | **P0** | **1天** | **US-3.1** |
+| **US-3.3 解读内容缓存** | **P0** | **1天** | **US-3.1** |
+| US-4.1 付费订阅页 | P0 | 2天 | US-5.1 |
+| US-4.2 订阅状态 | P0 | 1天 | US-4.1 |
+| US-5.1 微信登录 | P1 | 2天 | 无 |
+| US-5.2 历史记录 | P1 | 2天 | US-5.1 |
+| **US-6.1 推广码生成** | **P0** | **1天** | **US-4.1** |
+| **US-6.2 分享带参注册与上下级绑定** | **P1** | **2天** | **US-5.1** |
+| **US-6.3 佣金结算** | **P1** | **2天** | **US-4.1 + US-6.2** |
+| **US-6.4 分销面板** | **P1** | **2天** | **US-6.1 + US-6.3** |
+| **US-6.5 提现申请** | **P2** | **1天** | **US-6.4** |
+| US-7.1 批注功能 | P2 | 2天 | P0完成 |
+| US-7.2 客户分组 | P2 | 2天 | P0完成 |
+
+> **P0 合计工期:18天(3.5周)**
+> **P0+P1 合计工期:27天(5.5周)**
+> 
+> 佣金分成带来裂变增长——每个能量师都成为推广员,获客成本从 ¥50+ 降至 佣金比例(¥119.4/成功转化)。
+> 分销是 Phase 1 增长的引擎,不要砍。

+ 316 - 0
docs/platform-value.md

@@ -0,0 +1,316 @@
+# 数字能量学智能体平台 — 价值说明书
+
+> 版本: v0.1(产品方案)
+> 定位: 面向投资人的平台价值说明
+> 核心理念: 以数字能量学为底层,连接人、知识、数据,构建一个"识人·知己·连接"的社交化知识平台
+
+---
+
+## 一、一句话说清我们在做什么
+
+**一个基于数字能量学的智能平台**——让普通人通过生日了解自己,让从业者获得专业工具,让 AI 通过学习海量数据越来越懂人性。最终实现:**人与人之间的精准匹配与连接。**
+
+---
+
+## 二、三重价值引擎
+
+### 引擎 1:面向大众 — 数字能量学的全民普及
+
+**痛点:**
+- 数字能量学有理论体系但门槛高,普通人看不懂
+- 星座/塔罗有广泛群众基础,但数字能量学认知度极低
+- 市场上缺乏一个"低门槛、有趣、有用"的入门产品
+
+**我们的解决方案:**
+
+| 功能 | 解决什么问题 | 传播机制 |
+|------|-------------|----------|
+| 生日输入 → 三角形命盘 | 零门槛获得个人命盘,3 秒出结果 | 社交裂变:测测你的主性格数字 |
+| 免费基础解读 | 理解自己的性格、天赋、运势走向 | 生成海报分享朋友圈 |
+| AI 对话咨询 | 针对具体问题(事业/感情/财运)获得建议 | 高粘性,每日打开 |
+| 人格匹配 | 发现与谁"数字相合" | 邀请好友匹配 → 病毒传播 |
+
+**对投资人的价值:**
+- 微信生态天然裂变属性,低成本获客
+- 免费版作为流量入口,VIP 作为变现手段
+- 数字命理赛道已被验证(灵机文化年营收过亿)
+
+---
+
+### 引擎 2:面向从业人员 — 生产力工具 + 交易平台
+
+**痛点:**
+- 数字能量师目前靠手动计算、纸质记录,效率极低
+- 缺乏客户管理工具,老客流失严重
+- 获客渠道单一,依赖朋友圈/社群
+- 个人从业者难以建立专业品牌形象
+
+**我们的解决方案:**
+
+| 功能 | 价值点 | 收益模式 |
+|------|--------|----------|
+| 客户管理(添加/分组/标注) | 代替 Excel,提升 10 倍效率 | 专业版年费订阅 |
+| 批量导入分析 | 一次导入 50 人,自动生成全部命盘 | 专业版功能亮点 |
+| 客户命盘标注批注 | 每次咨询记录留痕,归档可查 | 专业版 |
+| 平台展示 / 获取客源 | 免费曝光,平台按地域/专长推荐 | 能量师入驻费或抽佣 |
+| 付费咨询(平台抽 20%) | 线上完成咨询-支付闭环 | 持续流水抽成 |
+
+**对投资人的价值:**
+- 平台抽佣模式(20%)是持续性收入
+- 能量师越多 → 服务供给越多 → 吸引更多付费用户
+- B 端从业者黏性极高,迁移成本大(数据都在平台上)
+- 参考:美国 astrology.com 月活 2000 万+,订阅制模式成熟
+
+---
+
+### 引擎 3:平台自身 — 数据飞轮效应
+
+**这是真正的护城河:**
+
+```
+更多用户 → 更多生日命盘数据 → AI 学习解读模式 → 解读更准确
+    ↑                                             │
+    └────────── 更好的体验吸引更多用户 ←───────────┘
+                                              ↓
+                                     积累数字能量学
+                                     标准化知识库
+```
+
+**具体落地:**
+
+| 数据来源 | 规模预期 | 商业价值 |
+|----------|---------|----------|
+| 用户输入生日信息 | 万级 → 百万级 | 数字能量学最大的中国人口命盘数据库 |
+| AI 对话记录(脱敏) | 每日千条 → 十万条 | 训练行业专属大模型 |
+| 能量师标注/解读内容 | 专业级数据 | 标准化知识库,可输出为 API 服务 |
+| 匹配关系数据 | 社交行为数据 | 建立"数字人格 × 社会关系"映射 |
+
+**对投资人的价值:**
+- 数据是 AI 时代的核心资产
+- 竞争对手难以复制:数据量级 + 行业 know-how 双重壁垒
+- 当数据足够大,可输出 B 端 API(如企业用人性格测评、婚恋平台接口)
+
+---
+
+## 三、创新场景:数字人格匹配与陌生交友
+
+### 3.1 核心逻辑
+
+数字能量学的底层数字(1-9)本身就描述了人的性格特质、行为模式、能量倾向。利用这套体系,我们可以建立**人与人的精准匹配模型**:
+
+```
+用户 A 的人格数字组合         用户 B 的人格数字组合
+    ↓                                ↓
+          数字能量匹配算法
+                ↓
+       匹配度评分 + 合理解读
+     (感情匹配 / 合作匹配 / 友缘匹配)
+```
+
+### 3.2 匹配维度
+
+| 维度 | 匹配依据 | 应用场景 |
+|------|---------|----------|
+| **主性格匹配** | 顶端数字的相生/相克关系 | 快速判断是否合拍 |
+| **五区互补度** | 各区域数字的互补程度 | 深度匹配(长期关系) |
+| **能量和谐度** | 整体数字分布的能量平衡 | 团队/合作匹配 |
+| **流年同步性** | 双方当前所处流年数字 | 时机匹配(何时相遇最合宜) |
+
+### 3.3 产品形态
+
+```
+方案 A:轻量匹配(MVP 方向)
+   ┌─────────────────────────────────────┐
+   │  输入你的生日 → 生成命盘            │
+   │  邀请好友 / 输入对方生日             │
+   │  生成「你们数字合拍度」卡片          │
+   │  分享到朋友圈 / 微信对话             │
+   └─────────────────────────────────────┘
+   传播性极强,社交裂变驱动增长
+
+方案 B:陌生人匹配(后续迭代)
+   ┌─────────────────────────────────────┐
+   │  基于数字人格推荐附近/在线的人       │
+   │  查看匹配度 → 打招呼 → 聊天          │
+   │  共同的数字话题(同主性格圈层)       │
+   └─────────────────────────────────────┘
+   高 DAU 场景,社交产品逻辑
+```
+
+### 3.4 为什么数字能量学适合做社交匹配
+
+| 对比维度 | 传统社交 App | 我们的方案 |
+|----------|-------------|-----------|
+| 匹配依据 | 照片 + 标签 + 算法黑盒 | 生辰数字 + 性格理论,有据可依 |
+| 破冰话题 | "你好" / 尴尬开场 | "你是 5 号人?我也 5 号!"天然话题 |
+| 信任感 | 信任门槛高 | 数字命理给出"认识对方的框架" |
+| 留存 | 刷到匹配即走 | 持续关注运势、流年、匹配更新 |
+
+---
+
+## 四、数字调理方案 — 从一次性解读到持续服务
+
+### 4.1 为什么调理比解读更有价值
+
+传统命理产品的瓶颈:**用户看完报告就走了。** 数字调理解决了这个问题——它把一次性的"认识自己"升级为持续性的"改善自己",用户有持续付费的理由。
+
+### 4.2 调理方案涵盖范围
+
+| 调理维度 | 具体内容 | 变现形式 |
+|----------|---------|----------|
+| **命名用数** | 分析名字中的数字能量是否与先天命盘匹配,提出改名/用名建议 | 付费增值报告 |
+| **号码能量** | 手机号/车牌号数字组合的能量分析与优化建议 | 增值服务 |
+| **色彩调理** | 根据缺失数字推荐穿搭/家居色彩方案 | 可电商带货 |
+| **方位建议** | 卧室/办公位朝向、城市选择等 | 增值服务 |
+| **配饰能量** | 水晶/饰品数字能量补充建议 | 可电商带货 |
+| **流年调理** | 每年运势变化对应调整方案 | 续费订阅(年费) |
+
+### 4.3 对商业模型的改变
+
+```
+传统模型:       报告生成 → 用户离开 → 零后续
+                    LTV ≈ 1 次付费
+
+调理模型:       报告生成 → 调理建议 → 执行跟踪 → 流年更新
+                    ↓
+               电商(水晶/饰品)     续费订阅
+                    ↓                    ↓
+              平台抽成 + 自营        年费续约
+                    LTV ≈ n × 付费
+```
+
+### 4.4 调理 = LTV 倍增器
+
+- 用户从"看一次"变成"长期调理",续费意愿远超单次解读
+- 调理建议可链接实物商品(水晶、饰品、色彩搭配),开辟电商收入
+- 每一次流年变化都是重新触达用户的理由,大幅提升留存
+
+### 4.5 电商运营模式与分成机制
+
+#### 商品体系
+
+| 品类 | 商品示例 | 定价区间 | 运营方式 |
+|------|---------|----------|---------|
+| **数字产品** | 命名分析报告、号码吉凶评测、调理方案书 | ¥9.9–¥99 | 平台自营(零成本,纯利润) |
+| **实体配饰** | 开运水晶、能量手串、五行饰品 | ¥39–¥399 | 能量师供货 or 平台供应链 |
+| **色彩周边** | 五行配色穿搭、家居摆件 | ¥29–¥199 | 第三方商家入驻 |
+| **调理套餐** | 全年调理方案 + 定制配饰 + 月度跟踪 | ¥499–¥1999 | 能量师 + 平台联合出品 |
+
+#### 运营模式:平台 + 能量师双轨
+
+```
+模式 A:平台自营(数字产品)
+  平台创作 → 平台上架 → 平台销售 → 100% 归平台
+  例:命名分析报告、号码能量评测
+
+模式 B:能量师供货(实物商品)
+  能量师提供商品 → 上架平台 → 平台销售
+  ↓
+  收入分配:商品售价 ×(1 - 平台佣金%) = 能量师收入
+
+模式 C:第三方商家入驻(开放平台)
+  商家入驻 → 平台审核 → 自行上架 → 平台抽佣
+  适用:水晶/饰品品牌商、家居品牌
+```
+
+#### 分成比例设计
+
+| 模式 | 平台分成 | 能量师/商家分成 | 说明 |
+|------|---------|----------------|------|
+| 数字产品(自营) | **100%** | 0% | 零边际成本,纯利润 |
+| 能量师供货 | **20%–30%** | 70%–80% | 平台提供流量+交易保障 |
+| 第三方入驻 | **15%–25%** | 75%–85% | 按品类调整,饰品25%/周边15% |
+| AI 推荐带货 | **30%–40%** | 60%–70% | 平台 AI 精准推荐,转化率高 |
+
+> 数字产品(报告/方案)是最高毛利品类,应作为第一阶段电商主力。
+
+#### 转化链路(用户从命盘到下单)
+
+```
+用户生成命盘 → 解读显示"你缺少 5 号能量"
+        ↓
+系统推荐调理方案(含商品)
+        ↓
+方案展示 → 可单独购买数字报告(¥9.9)
+         → 也可购买调理套餐(报告+配饰,¥99)
+        ↓
+购买数字报告 → 自动生成 PDF → 再次推荐实物商品
+购买调理套餐 → 商品发货 → 30 天后流年跟踪复购
+```
+
+#### 为什么电商和命理天生匹配
+
+- **推荐精准**:AI 根据命盘缺失数字推荐对应商品,每个用户推荐不同,天然个性化
+- **转化率高**:用户刚看完"我缺什么",立即看到"补什么",购买意愿最强
+- **退货率低**:开运/调理类商品带有心理属性,退货率远低于普通电商(预期 < 5%)
+- **复购自然**:流年变化、新需求出现时,用户会回来重新匹配
+
+---
+
+## 五、商业模式全景
+
+```
+              ┌──────────────────────────────────┐
+              │        收入来源                  │
+              ├──────────────────────────────────┤
+              │  ① VIP 订阅(C 端)               │
+              │    - 月卡 / 年卡                  │
+              ├──────────────────────────────────┤
+              │  ② 专业版年费(B 端)             │
+              │    - 能量师入驻 ¥XX/年            │
+              ├──────────────────────────────────┤
+              │  ③ 咨询交易抽佣(平台)           │
+              │    - 每笔咨询抽 20%              │
+              ├──────────────────────────────────┤
+              │  ④ 电商收入                      │
+              │    - 数字产品(报告/方案)自营 100% │
+              │    - 实物商品(水晶/饰品)抽佣 20% │
+              │    - 第三方入驻抽佣 15%-25%       │
+              ├──────────────────────────────────┤
+              │  ⑤ 数据 API 输出(远期)          │
+              │    - 企业用人 / 婚恋 / 营销       │
+              └──────────────────────────────────┘
+
+用户增长(飞轮):
+  免费工具 → 裂变传播 → 海量用户 → 数据积累
+     ↓                                  ↓
+  VIP 转化 + 电商转化              AI 能力增强
+     ↓                                  ↓
+   平台收入              解读更准 → 匹配更准 → 吸引更多用户
+```
+
+---
+
+## 五、竞争格局与差异化
+
+| 竞品类型 | 代表 | 我们的差异点 |
+|----------|------|-------------|
+| 八字/紫微斗数 App | 灵机文化、易罗 | 数字能量学更简单直观,适合年轻化传播 |
+| 星座 App | 测测、星盘 | 数字命理更"中国",有天然文化认同 |
+| 命理师个体 | 朋友圈/社群接单 | 平台化、工具化、数据化,不可同日而语 |
+| 纯社交 App | 探探、Soul | 有理论依据的匹配,信任感远高于"刷脸" |
+
+---
+
+## 六、阶段规划
+
+| 阶段 | 目标 | 关键动作 | 数据指标 |
+|------|------|---------|---------|
+| **Phase 1** | 验证核心价值 | MVP 上线(输入→命盘→免费解读→VIP) | DAU > 1000, VIP 转化率 > 3% |
+| **Phase 2** | 建立数据飞轮 | AI 对话上线 + 能量师入驻 + 人格匹配 | 月活 > 1 万, 日命盘生成 > 5000 |
+| **Phase 3** | 社交化爆发 | 陌生人匹配 + 社群 + 内容社区 | 月活 > 10 万, 匹配互动率 > 30% |
+| **Phase 4** | 平台化输出 | 知识库 API + 企业服务 + 行业标准 | B 端营收占比 > 30% |
+
+---
+
+## 七、我们相信什么
+
+1. **人人都在寻找"认识自己"的工具。** 从星座到 MBTI 到数字能量学,人类从未停止。
+2. **AI 让玄学变得可用。** 过去命理分析靠师傅经验,未来靠 AI + 海量数据。
+3. **匹配是最高频的社交场景。** 当"合不合"能用数字说话,用户会自发传播。
+4. **数据是终极壁垒。** 谁拥有最多的命盘数据 + 解读数据,谁就定义了行业标准。
+
+---
+
+> **一句话总结:**
+> 我们不是在做一个算命工具。我们是以数字能量学为语言,构建一个"认识自我、连接他人"的社交化知识平台。

+ 138 - 0
docs/presentation/comparison/assets/animations/animations.css

@@ -0,0 +1,138 @@
+/* html-ppt :: animations.css
+ * Apply by adding class="anim-<name>" or data-anim="<name>".
+ * Durations are deliberately snappy; tweak --anim-dur per element.
+ */
+:root{--anim-dur:.7s;--anim-ease:cubic-bezier(.4,0,.2,1)}
+
+/* ---------- FADE DIRECTIONALS ---------- */
+@keyframes kf-fade-up{from{opacity:0;transform:translateY(32px)}to{opacity:1;transform:none}}
+@keyframes kf-fade-down{from{opacity:0;transform:translateY(-32px)}to{opacity:1;transform:none}}
+@keyframes kf-fade-left{from{opacity:0;transform:translateX(-40px)}to{opacity:1;transform:none}}
+@keyframes kf-fade-right{from{opacity:0;transform:translateX(40px)}to{opacity:1;transform:none}}
+.anim-fade-up{animation:kf-fade-up var(--anim-dur) var(--anim-ease) both}
+.anim-fade-down{animation:kf-fade-down var(--anim-dur) var(--anim-ease) both}
+.anim-fade-left{animation:kf-fade-left var(--anim-dur) var(--anim-ease) both}
+.anim-fade-right{animation:kf-fade-right var(--anim-dur) var(--anim-ease) both}
+
+/* ---------- RISE / DROP / ZOOM / BLUR / GLITCH ---------- */
+@keyframes kf-rise{from{opacity:0;transform:translateY(60px) scale(.97);filter:blur(6px)}to{opacity:1;transform:none;filter:none}}
+@keyframes kf-drop{from{opacity:0;transform:translateY(-60px) scale(.97)}to{opacity:1;transform:none}}
+@keyframes kf-zoom{0%{opacity:0;transform:scale(.6)}60%{transform:scale(1.04)}100%{opacity:1;transform:scale(1)}}
+@keyframes kf-blur{from{opacity:0;filter:blur(18px)}to{opacity:1;filter:none}}
+@keyframes kf-glitch{0%{opacity:0;transform:translateX(0);clip-path:inset(0 0 0 0)}
+  20%{opacity:1;transform:translateX(-6px);clip-path:inset(20% 0 30% 0)}
+  40%{transform:translateX(4px);clip-path:inset(50% 0 10% 0)}
+  60%{transform:translateX(-3px);clip-path:inset(10% 0 60% 0)}
+  80%{transform:translateX(2px);clip-path:inset(0 0 0 0)}
+  100%{opacity:1;transform:none}}
+.anim-rise-in{animation:kf-rise .9s var(--anim-ease) both}
+.anim-drop-in{animation:kf-drop .8s var(--anim-ease) both}
+.anim-zoom-pop{animation:kf-zoom .7s cubic-bezier(.22,1.3,.36,1) both}
+.anim-blur-in{animation:kf-blur .8s var(--anim-ease) both}
+.anim-glitch-in{animation:kf-glitch .8s steps(5,end) both}
+
+/* ---------- TYPEWRITER ---------- */
+.anim-typewriter{display:inline-block;overflow:hidden;white-space:nowrap;border-right:2px solid currentColor;
+  width:0;animation:kf-type 2.4s steps(40,end) forwards, kf-caret 1s step-end infinite}
+@keyframes kf-type{to{width:100%}}
+@keyframes kf-caret{50%{border-color:transparent}}
+
+/* ---------- GLOW / SHIMMER / GRADIENT-FLOW ---------- */
+@keyframes kf-neon{0%,100%{text-shadow:0 0 8px var(--accent),0 0 20px var(--accent)}
+  50%{text-shadow:0 0 16px var(--accent),0 0 40px var(--accent),0 0 80px var(--accent)}}
+.anim-neon-glow{animation:kf-neon 2s ease-in-out infinite}
+
+.anim-shimmer-sweep{position:relative;overflow:hidden}
+.anim-shimmer-sweep::after{content:"";position:absolute;inset:0;
+  background:linear-gradient(110deg,transparent 40%,rgba(255,255,255,.55) 50%,transparent 60%);
+  transform:translateX(-100%);animation:kf-shimmer 2.4s var(--anim-ease) infinite}
+@keyframes kf-shimmer{to{transform:translateX(100%)}}
+
+.anim-gradient-flow{background:linear-gradient(90deg,var(--accent),var(--accent-2,var(--accent)),var(--accent-3,var(--accent)),var(--accent));
+  background-size:300% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;-webkit-text-fill-color:transparent;
+  animation:kf-gradflow 4s linear infinite}
+@keyframes kf-gradflow{to{background-position:300% 0}}
+
+/* ---------- STAGGER LIST ---------- */
+.anim-stagger-list > *{opacity:0;animation:kf-rise .65s var(--anim-ease) both}
+.anim-stagger-list > *:nth-child(1){animation-delay:.05s}
+.anim-stagger-list > *:nth-child(2){animation-delay:.15s}
+.anim-stagger-list > *:nth-child(3){animation-delay:.25s}
+.anim-stagger-list > *:nth-child(4){animation-delay:.35s}
+.anim-stagger-list > *:nth-child(5){animation-delay:.45s}
+.anim-stagger-list > *:nth-child(6){animation-delay:.55s}
+.anim-stagger-list > *:nth-child(7){animation-delay:.65s}
+.anim-stagger-list > *:nth-child(8){animation-delay:.75s}
+.anim-stagger-list > *:nth-child(n+9){animation-delay:.85s}
+
+/* ---------- COUNTER-UP (JS-driven, marker class only) ---------- */
+.counter{font-variant-numeric:tabular-nums}
+
+/* ---------- SVG PATH DRAW ---------- */
+.anim-path-draw path,.anim-path-draw line,.anim-path-draw polyline,.anim-path-draw circle,.anim-path-draw rect{
+  stroke-dasharray:1000;stroke-dashoffset:1000;animation:kf-draw 2s var(--anim-ease) forwards}
+@keyframes kf-draw{to{stroke-dashoffset:0}}
+
+/* ---------- PARALLAX TILT (hover) ---------- */
+.anim-parallax-tilt{transform-style:preserve-3d;transition:transform .4s var(--anim-ease)}
+.anim-parallax-tilt:hover{transform:perspective(900px) rotateX(6deg) rotateY(-8deg) translateZ(10px)}
+
+/* ---------- CARD FLIP 3D ---------- */
+@keyframes kf-flip{from{transform:perspective(1200px) rotateY(-90deg);opacity:0}
+  to{transform:perspective(1200px) rotateY(0);opacity:1}}
+.anim-card-flip-3d{animation:kf-flip .9s var(--anim-ease) both;transform-style:preserve-3d;backface-visibility:hidden}
+
+/* ---------- CUBE ROTATE 3D ---------- */
+@keyframes kf-cube{from{transform:perspective(1200px) rotateX(20deg) rotateY(-90deg) translateZ(-200px);opacity:0}
+  to{transform:perspective(1200px) rotateX(0) rotateY(0) translateZ(0);opacity:1}}
+.anim-cube-rotate-3d{animation:kf-cube 1s var(--anim-ease) both}
+
+/* ---------- PAGE TURN 3D ---------- */
+@keyframes kf-pageturn{from{transform:perspective(1600px) rotateY(-85deg);transform-origin:left center;opacity:0}
+  to{transform:perspective(1600px) rotateY(0);opacity:1}}
+.anim-page-turn-3d{animation:kf-pageturn 1s var(--anim-ease) both;transform-origin:left center}
+
+/* ---------- PERSPECTIVE ZOOM ---------- */
+@keyframes kf-pzoom{from{opacity:0;transform:perspective(1400px) translateZ(-400px) rotateX(12deg)}
+  to{opacity:1;transform:none}}
+.anim-perspective-zoom{animation:kf-pzoom 1s var(--anim-ease) both}
+
+/* ---------- MARQUEE SCROLL ---------- */
+.anim-marquee-scroll{display:flex;gap:48px;white-space:nowrap;animation:kf-marquee 20s linear infinite}
+@keyframes kf-marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
+
+/* ---------- KEN BURNS ---------- */
+@keyframes kf-kenburns{0%{transform:scale(1) translate(0,0)}100%{transform:scale(1.15) translate(-2%,-1%)}}
+.anim-kenburns{animation:kf-kenburns 14s ease-in-out infinite alternate}
+
+/* ---------- CONFETTI BURST (pseudo — pure CSS sparkles) ---------- */
+.anim-confetti-burst{position:relative}
+.anim-confetti-burst::before,.anim-confetti-burst::after{
+  content:"";position:absolute;top:50%;left:50%;width:8px;height:8px;border-radius:50%;
+  background:var(--accent);box-shadow:
+    20px -30px 0 var(--accent-2,var(--accent)),-25px -20px 0 var(--accent-3,var(--accent)),
+    30px 20px 0 var(--good,#1aaf6c),-30px 25px 0 var(--warn,#f5a524),
+    40px -10px 0 var(--bad,#e0445a),-45px 0 0 var(--accent),
+    10px 40px 0 var(--accent-2,var(--accent)),-15px -40px 0 var(--accent-3,var(--accent));
+  opacity:0;animation:kf-confetti 1.2s var(--anim-ease) forwards}
+.anim-confetti-burst::after{animation-delay:.15s;transform:rotate(45deg)}
+@keyframes kf-confetti{0%{opacity:0;transform:scale(.2)}30%{opacity:1}100%{opacity:0;transform:scale(2.2)}}
+
+/* ---------- SPOTLIGHT ---------- */
+@keyframes kf-spot{0%{clip-path:circle(0% at 50% 50%)}100%{clip-path:circle(140% at 50% 50%)}}
+.anim-spotlight{animation:kf-spot 1.1s var(--anim-ease) both}
+
+/* ---------- MORPH SHAPE (SVG) ---------- */
+.anim-morph-shape path{animation:kf-morph 6s ease-in-out infinite alternate}
+@keyframes kf-morph{0%{d:path("M60,120 Q120,20 180,120 T300,120")}
+  100%{d:path("M60,120 Q120,220 180,120 T300,120")}}
+
+/* ---------- RIPPLE REVEAL ---------- */
+@keyframes kf-ripple{0%{clip-path:circle(0% at 20% 80%);opacity:.4}
+  100%{clip-path:circle(160% at 20% 80%);opacity:1}}
+.anim-ripple-reveal{animation:kf-ripple 1.2s var(--anim-ease) both}
+
+/* reduced motion */
+@media (prefers-reduced-motion: reduce){
+  [class*="anim-"]{animation:none!important;transition:none!important}
+}

+ 99 - 0
docs/presentation/comparison/assets/animations/fx-runtime.js

@@ -0,0 +1,99 @@
+/* html-ppt :: fx-runtime.js
+ * Canvas FX autoloader + lifecycle manager.
+ * - Dynamically loads all fx modules listed in FX_LIST
+ * - Initializes [data-fx] elements when their slide becomes active
+ * - Calls handle.stop() when the slide leaves
+ */
+(function(){
+  'use strict';
+
+  const FX_LIST = [
+    '_util',
+    'particle-burst','confetti-cannon','firework','starfield','matrix-rain',
+    'knowledge-graph','neural-net','constellation','orbit-ring','galaxy-swirl',
+    'word-cascade','letter-explode','chain-react','magnetic-field','data-stream',
+    'gradient-blob','sparkle-trail','shockwave','typewriter-multi','counter-explosion'
+  ];
+
+  // Resolve base path of this script so it works from any page location.
+  const myScript = document.currentScript || (function(){
+    const all = document.getElementsByTagName('script');
+    for (const s of all){ if (s.src && s.src.indexOf('fx-runtime.js')>-1) return s; }
+    return null;
+  })();
+  const base = myScript ? myScript.src.replace(/fx-runtime\.js.*$/, 'fx/') : 'assets/animations/fx/';
+
+  let loaded = 0;
+  const total = FX_LIST.length;
+  const ready = new Promise((resolve) => {
+    if (!total) return resolve();
+    FX_LIST.forEach((name) => {
+      const s = document.createElement('script');
+      s.src = base + name + '.js';
+      s.async = false;
+      s.onload = s.onerror = () => { if (++loaded >= total) resolve(); };
+      document.head.appendChild(s);
+    });
+  });
+
+  window.__hpxActive = window.__hpxActive || new Map();
+
+  function initFxIn(root){
+    if (!window.HPX) return;
+    const els = root.querySelectorAll('[data-fx]');
+    els.forEach((el) => {
+      if (window.__hpxActive.has(el)) return;
+      const name = el.getAttribute('data-fx');
+      const fn = window.HPX[name];
+      if (typeof fn !== 'function') return;
+      try {
+        const handle = fn(el, {}) || { stop(){} };
+        window.__hpxActive.set(el, handle);
+      } catch(e){ console.warn('[hpx-fx]', name, e); }
+    });
+  }
+
+  function stopFxIn(root){
+    const els = root.querySelectorAll('[data-fx]');
+    els.forEach((el) => {
+      const h = window.__hpxActive.get(el);
+      if (h && typeof h.stop === 'function'){
+        try{ h.stop(); }catch(e){}
+      }
+      window.__hpxActive.delete(el);
+    });
+  }
+
+  function reinitFxIn(root){
+    stopFxIn(root);
+    initFxIn(root);
+  }
+  window.__hpxReinit = reinitFxIn;
+
+  function boot(){
+    ready.then(() => {
+      const active = document.querySelector('.slide.is-active') || document.querySelector('.slide');
+      if (active) initFxIn(active);
+
+      // Watch all slides for class changes
+      const slides = document.querySelectorAll('.slide');
+      slides.forEach((sl) => {
+        const mo = new MutationObserver((muts) => {
+          for (const m of muts){
+            if (m.attributeName === 'class'){
+              if (sl.classList.contains('is-active')) initFxIn(sl);
+              else stopFxIn(sl);
+            }
+          }
+        });
+        mo.observe(sl, { attributes: true, attributeFilter: ['class'] });
+      });
+    });
+  }
+
+  if (document.readyState === 'loading'){
+    document.addEventListener('DOMContentLoaded', boot);
+  } else {
+    boot();
+  }
+})();

+ 63 - 0
docs/presentation/comparison/assets/animations/fx/_util.js

@@ -0,0 +1,63 @@
+/* html-ppt fx :: shared helpers */
+(function(){
+  window.HPX = window.HPX || {};
+  const U = window.HPX._u = {};
+
+  U.css = (el, name, fb) => {
+    const v = getComputedStyle(el).getPropertyValue(name).trim();
+    return v || fb;
+  };
+
+  U.accent = (el, fb) => U.css(el, '--accent', fb || '#7c5cff');
+  U.accent2 = (el, fb) => U.css(el, '--accent-2', fb || '#22d3ee');
+  U.text = (el, fb) => U.css(el, '--text-1', fb || '#eaeaf2');
+
+  U.palette = (el) => [
+    U.accent(el, '#7c5cff'),
+    U.accent2(el, '#22d3ee'),
+    U.css(el, '--ok', '#22c55e'),
+    U.css(el, '--warn', '#f59e0b'),
+    U.css(el, '--danger', '#ef4444'),
+  ];
+
+  U.canvas = (el) => {
+    if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
+    const c = document.createElement('canvas');
+    c.style.cssText = 'position:absolute;inset:0;width:100%;height:100%;pointer-events:none;display:block;';
+    el.appendChild(c);
+    const ctx = c.getContext('2d');
+    let w = 0, h = 0, dpr = Math.max(1, Math.min(2, window.devicePixelRatio||1));
+    const fit = () => {
+      const r = el.getBoundingClientRect();
+      w = Math.max(1, r.width|0);
+      h = Math.max(1, r.height|0);
+      c.width = (w*dpr)|0;
+      c.height = (h*dpr)|0;
+      ctx.setTransform(dpr,0,0,dpr,0,0);
+    };
+    fit();
+    const ro = new ResizeObserver(fit);
+    ro.observe(el);
+    return {
+      c, ctx,
+      get w(){return w;}, get h(){return h;}, get dpr(){return dpr;},
+      destroy(){
+        try{ro.disconnect();}catch(e){}
+        if (c.parentNode) c.parentNode.removeChild(c);
+      }
+    };
+  };
+
+  U.loop = (fn) => {
+    let raf = 0, stopped = false, t0 = performance.now();
+    const tick = (t) => {
+      if (stopped) return;
+      fn((t - t0)/1000);
+      raf = requestAnimationFrame(tick);
+    };
+    raf = requestAnimationFrame(tick);
+    return () => { stopped = true; cancelAnimationFrame(raf); };
+  };
+
+  U.rand = (a,b) => a + Math.random()*(b-a);
+})();

+ 41 - 0
docs/presentation/comparison/assets/animations/fx/chain-react.js

@@ -0,0 +1,41 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['chain-react'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const ac = U.accent(el,'#7c5cff'), ac2 = U.accent2(el,'#22d3ee');
+    const N = 8;
+    const stop = U.loop((t) => {
+      ctx.clearRect(0,0,k.w,k.h);
+      const cy = k.h/2;
+      const pad = 60;
+      const dx = (k.w - pad*2)/(N-1);
+      const period = 2.4;
+      const phase = (t % period) / period; // 0..1
+      for (let i=0;i<N;i++){
+        const x = pad + i*dx;
+        const my = i/(N-1);
+        const d = Math.abs(phase - my);
+        const pulse = Math.max(0, 1 - d*6);
+        const r = 18 + pulse*18;
+        // glow
+        const g = ctx.createRadialGradient(x,cy,0,x,cy,r*2);
+        g.addColorStop(0, `rgba(124,92,255,${0.4*pulse})`);
+        g.addColorStop(1, 'rgba(0,0,0,0)');
+        ctx.fillStyle = g;
+        ctx.fillRect(x-r*2, cy-r*2, r*4, r*4);
+        // circle
+        ctx.fillStyle = pulse>0.1 ? ac2 : ac;
+        ctx.beginPath(); ctx.arc(x,cy,r,0,Math.PI*2); ctx.fill();
+        ctx.strokeStyle='rgba(255,255,255,0.4)'; ctx.lineWidth=2;
+        ctx.stroke();
+        // connectors
+        if (i<N-1){
+          ctx.strokeStyle='rgba(200,200,230,0.3)'; ctx.lineWidth=2;
+          ctx.beginPath(); ctx.moveTo(x+r,cy); ctx.lineTo(x+dx-r,cy); ctx.stroke();
+        }
+      }
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 49 - 0
docs/presentation/comparison/assets/animations/fx/confetti-cannon.js

@@ -0,0 +1,49 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['confetti-cannon'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    let parts = [];
+    const fire = () => {
+      for (let side=0; side<2; side++){
+        const x0 = side===0 ? 20 : k.w-20;
+        const y0 = k.h - 20;
+        for (let i=0;i<40;i++){
+          const a = side===0 ? U.rand(-Math.PI*0.7, -Math.PI*0.4) : U.rand(-Math.PI*0.6, -Math.PI*0.3) - Math.PI/2 - Math.PI/6;
+          const spd = U.rand(300, 520);
+          parts.push({
+            x: x0, y: y0,
+            vx: Math.cos(a)*spd, vy: Math.sin(a)*spd,
+            w: U.rand(6,12), h: U.rand(3,7),
+            rot: Math.random()*Math.PI, vr: U.rand(-6,6),
+            c: pal[(Math.random()*pal.length)|0],
+            life: 1
+          });
+        }
+      }
+    };
+    fire();
+    let last = 0;
+    const stop = U.loop((t) => {
+      ctx.clearRect(0,0,k.w,k.h);
+      if (t - last > 3) { fire(); last = t; }
+      const dt = 1/60;
+      parts = parts.filter(p => p.life > 0 && p.y < k.h+40);
+      for (const p of parts){
+        p.vy += 520*dt;
+        p.x += p.vx*dt; p.y += p.vy*dt;
+        p.rot += p.vr*dt;
+        p.life -= 0.006;
+        ctx.save();
+        ctx.translate(p.x, p.y); ctx.rotate(p.rot);
+        ctx.globalAlpha = Math.max(0, p.life);
+        ctx.fillStyle = p.c;
+        ctx.fillRect(-p.w/2, -p.h/2, p.w, p.h);
+        ctx.restore();
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 44 - 0
docs/presentation/comparison/assets/animations/fx/constellation.js

@@ -0,0 +1,44 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['constellation'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const ac = U.accent(el,'#9fb4ff');
+    const N = 70;
+    let pts = [];
+    const seed = () => {
+      pts = Array.from({length:N}, () => ({
+        x: Math.random()*k.w, y: Math.random()*k.h,
+        vx: U.rand(-0.3,0.3), vy: U.rand(-0.3,0.3)
+      }));
+    };
+    seed();
+    let lw=k.w, lh=k.h;
+    const stop = U.loop(() => {
+      if (k.w!==lw||k.h!==lh){ seed(); lw=k.w; lh=k.h; }
+      ctx.clearRect(0,0,k.w,k.h);
+      for (const p of pts){
+        p.x += p.vx; p.y += p.vy;
+        if (p.x<0||p.x>k.w) p.vx*=-1;
+        if (p.y<0||p.y>k.h) p.vy*=-1;
+      }
+      for (let i=0;i<N;i++){
+        for (let j=i+1;j<N;j++){
+          const a=pts[i], b=pts[j];
+          const d = Math.hypot(a.x-b.x, a.y-b.y);
+          if (d < 150){
+            ctx.globalAlpha = 1 - d/150;
+            ctx.strokeStyle = ac; ctx.lineWidth=1;
+            ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke();
+          }
+        }
+      }
+      ctx.globalAlpha = 1;
+      ctx.fillStyle = ac;
+      for (const p of pts){
+        ctx.beginPath(); ctx.arc(p.x,p.y,1.8,0,Math.PI*2); ctx.fill();
+      }
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 58 - 0
docs/presentation/comparison/assets/animations/fx/counter-explosion.js

@@ -0,0 +1,58 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['counter-explosion'] = function(el){
+    const U = window.HPX._u;
+    if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
+    const target = parseInt(el.getAttribute('data-fx-to') || '2400', 10);
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    // number overlay
+    const num = document.createElement('div');
+    num.style.cssText = 'position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font:900 120px system-ui,sans-serif;color:var(--text-1,#fff);pointer-events:none;text-shadow:0 4px 40px rgba(124,92,255,0.5);';
+    num.textContent = '0';
+    el.appendChild(num);
+    let parts = [];
+    let state = 'count'; // count | burst | hold
+    let stateT = 0;
+    let value = 0;
+    let cycle = 0;
+    const burst = () => {
+      const cx = k.w/2, cy = k.h/2;
+      for (let i=0;i<120;i++){
+        const a = Math.random()*Math.PI*2;
+        const s = U.rand(120, 400);
+        parts.push({x:cx,y:cy,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:1,r:U.rand(2,5),c:pal[(Math.random()*pal.length)|0]});
+      }
+    };
+    const stop = U.loop(() => {
+      ctx.clearRect(0,0,k.w,k.h);
+      const dt = 1/60;
+      stateT += dt;
+      if (state === 'count'){
+        const dur = 2.2;
+        const p = Math.min(1, stateT/dur);
+        const eased = 1 - Math.pow(1-p,3);
+        value = Math.round(target*eased);
+        num.textContent = value.toLocaleString();
+        if (p >= 1){ state='burst'; stateT=0; burst(); }
+      } else if (state === 'burst'){
+        if (stateT > 0.05 && stateT < 0.3 && parts.length < 200) {}
+        if (stateT > 2.5){ state='hold'; stateT=0; }
+      } else if (state === 'hold'){
+        if (stateT > 1.5){
+          state='count'; stateT=0; value=0; num.textContent='0'; cycle++;
+        }
+      }
+      parts = parts.filter(p => p.life > 0);
+      for (const p of parts){
+        p.vy += 260*dt; p.vx *= 0.985; p.vy *= 0.985;
+        p.x += p.vx*dt; p.y += p.vy*dt; p.life -= 0.01;
+        ctx.globalAlpha = Math.max(0,p.life);
+        ctx.fillStyle = p.c;
+        ctx.beginPath(); ctx.arc(p.x,p.y,p.r,0,Math.PI*2); ctx.fill();
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){ stop(); k.destroy(); if (num.parentNode) num.parentNode.removeChild(num); } };
+  };
+})();

+ 45 - 0
docs/presentation/comparison/assets/animations/fx/data-stream.js

@@ -0,0 +1,45 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['data-stream'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const ac = U.accent(el,'#22d3ee'), ac2 = U.accent2(el,'#7c5cff');
+    const rows = [];
+    const rh = 22;
+    const genRow = (y) => ({
+      y, dir: Math.random()<0.5?-1:1,
+      speed: U.rand(30, 90),
+      offset: Math.random()*2000,
+      text: Array.from({length:120}, () => {
+        const r = Math.random();
+        if (r<0.3) return Math.random()<0.5?'0':'1';
+        if (r<0.6) return '0x' + Math.floor(Math.random()*256).toString(16).padStart(2,'0');
+        return Math.random().toString(16).slice(2,6);
+      }).join(' ')
+    });
+    const init = () => {
+      rows.length = 0;
+      const n = Math.ceil(k.h/rh);
+      for (let i=0;i<n;i++) rows.push(genRow(i*rh + rh*0.7));
+    };
+    init();
+    let lh = k.h;
+    const stop = U.loop((t) => {
+      if (k.h!==lh){ init(); lh=k.h; }
+      ctx.fillStyle = 'rgba(5,8,14,0.35)';
+      ctx.fillRect(0,0,k.w,k.h);
+      ctx.font = '13px ui-monospace,Menlo,monospace';
+      for (let i=0;i<rows.length;i++){
+        const r = rows[i];
+        const x = r.dir>0
+          ? ((t*r.speed + r.offset) % (k.w+400)) - 400
+          : k.w - (((t*r.speed + r.offset) % (k.w+400)) - 400);
+        ctx.fillStyle = (i%3===0)?ac:ac2;
+        ctx.globalAlpha = 0.65 + (i%2)*0.3;
+        ctx.fillText(r.text, x, r.y);
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 51 - 0
docs/presentation/comparison/assets/animations/fx/firework.js

@@ -0,0 +1,51 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['firework'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    let rockets = [], sparks = [];
+    const launch = () => {
+      rockets.push({
+        x: U.rand(k.w*0.2, k.w*0.8), y: k.h+10,
+        vx: U.rand(-30,30), vy: U.rand(-520,-380),
+        tgtY: U.rand(k.h*0.15, k.h*0.45),
+        c: pal[(Math.random()*pal.length)|0]
+      });
+    };
+    const burst = (x, y, c) => {
+      const n = 70;
+      for (let i=0;i<n;i++){
+        const a = Math.random()*Math.PI*2;
+        const s = U.rand(60, 240);
+        sparks.push({x,y,vx:Math.cos(a)*s,vy:Math.sin(a)*s,life:1,c});
+      }
+    };
+    let last = -1;
+    const stop = U.loop((t) => {
+      ctx.fillStyle = 'rgba(0,0,0,0.18)';
+      ctx.fillRect(0,0,k.w,k.h);
+      if (t - last > 0.7) { launch(); last = t; }
+      const dt = 1/60;
+      rockets = rockets.filter(r => {
+        r.x += r.vx*dt; r.y += r.vy*dt; r.vy += 260*dt;
+        ctx.fillStyle = r.c;
+        ctx.beginPath(); ctx.arc(r.x, r.y, 2.5, 0, Math.PI*2); ctx.fill();
+        if (r.y <= r.tgtY || r.vy >= 0) { burst(r.x, r.y, r.c); return false; }
+        return true;
+      });
+      sparks = sparks.filter(p => p.life > 0);
+      for (const p of sparks){
+        p.vy += 90*dt;
+        p.vx *= 0.98; p.vy *= 0.98;
+        p.x += p.vx*dt; p.y += p.vy*dt;
+        p.life -= 0.012;
+        ctx.globalAlpha = Math.max(0, p.life);
+        ctx.fillStyle = p.c;
+        ctx.beginPath(); ctx.arc(p.x, p.y, 2, 0, Math.PI*2); ctx.fill();
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 33 - 0
docs/presentation/comparison/assets/animations/fx/galaxy-swirl.js

@@ -0,0 +1,33 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['galaxy-swirl'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    const N = 800;
+    const parts = Array.from({length:N}, (_,i) => {
+      const arm = i%3;
+      const t = Math.random();
+      const r = t*180 + 8;
+      const base = (arm/3)*Math.PI*2;
+      return { r, a: base + Math.log(r+1)*1.6 + U.rand(-0.2,0.2),
+               c: pal[arm%pal.length],
+               s: U.rand(0.8, 2.2) };
+    });
+    const stop = U.loop((t) => {
+      ctx.fillStyle = 'rgba(0,0,0,0.15)';
+      ctx.fillRect(0,0,k.w,k.h);
+      const cx=k.w/2, cy=k.h/2;
+      for (const p of parts){
+        const a = p.a + t*0.15;
+        const x = cx + Math.cos(a)*p.r;
+        const y = cy + Math.sin(a)*p.r*0.7;
+        ctx.fillStyle = p.c;
+        ctx.globalAlpha = 0.7;
+        ctx.beginPath(); ctx.arc(x,y,p.s,0,Math.PI*2); ctx.fill();
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 39 - 0
docs/presentation/comparison/assets/animations/fx/gradient-blob.js

@@ -0,0 +1,39 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['gradient-blob'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    const blobs = Array.from({length:4}, (_,i) => ({
+      x: U.rand(0,1), y: U.rand(0,1),
+      vx: U.rand(-0.08,0.08), vy: U.rand(-0.08,0.08),
+      r: U.rand(180,320),
+      c: pal[i%pal.length]
+    }));
+    const hex2rgb = (h) => {
+      const m = h.replace('#','').match(/.{2}/g);
+      if (!m) return [124,92,255];
+      return m.map(x=>parseInt(x,16));
+    };
+    const stop = U.loop((t) => {
+      ctx.fillStyle = 'rgba(10,12,22,0.2)';
+      ctx.fillRect(0,0,k.w,k.h);
+      ctx.globalCompositeOperation = 'lighter';
+      for (const b of blobs){
+        b.x += b.vx*0.01; b.y += b.vy*0.01;
+        if (b.x<0||b.x>1) b.vx*=-1;
+        if (b.y<0||b.y>1) b.vy*=-1;
+        const px = b.x*k.w, py = b.y*k.h;
+        const r = b.r + Math.sin(t*0.8 + b.x*6)*30;
+        const [R,G,B] = hex2rgb(b.c);
+        const grad = ctx.createRadialGradient(px,py,0,px,py,r);
+        grad.addColorStop(0, `rgba(${R},${G},${B},0.55)`);
+        grad.addColorStop(1, `rgba(${R},${G},${B},0)`);
+        ctx.fillStyle = grad;
+        ctx.beginPath(); ctx.arc(px,py,r,0,Math.PI*2); ctx.fill();
+      }
+      ctx.globalCompositeOperation = 'source-over';
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 69 - 0
docs/presentation/comparison/assets/animations/fx/knowledge-graph.js

@@ -0,0 +1,69 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['knowledge-graph'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    const tx = U.text(el, '#e7e7ef');
+    const labels = ['AI','ML','LLM','Graph','Node','Edge','Claude','GPT','RAG','Vector',
+      'Embed','Neural','Agent','Tool','Memory','Logic','Data','Train','Infer','Token',
+      'Prompt','Chain','Plan','Skill','Cloud','Edge','GPU','Code','Task','Flow'];
+    const N = 28;
+    const nodes = Array.from({length:N}, (_,i) => ({
+      x: U.rand(40, 300), y: U.rand(40, 200),
+      vx: 0, vy: 0, label: labels[i%labels.length],
+      c: pal[i%pal.length]
+    }));
+    const edges = [];
+    const made = new Set();
+    while (edges.length < 50){
+      const a = (Math.random()*N)|0, b = (Math.random()*N)|0;
+      if (a===b) continue;
+      const key = a<b ? a+'-'+b : b+'-'+a;
+      if (made.has(key)) continue;
+      made.add(key); edges.push([a,b]);
+    }
+    const stop = U.loop(() => {
+      // physics
+      for (let i=0;i<N;i++){
+        for (let j=i+1;j<N;j++){
+          const a=nodes[i], b=nodes[j];
+          const dx=b.x-a.x, dy=b.y-a.y;
+          let d2=dx*dx+dy*dy; if (d2<1) d2=1;
+          const d=Math.sqrt(d2);
+          const f=1600/d2;
+          const fx=(dx/d)*f, fy=(dy/d)*f;
+          a.vx-=fx; a.vy-=fy; b.vx+=fx; b.vy+=fy;
+        }
+      }
+      for (const [i,j] of edges){
+        const a=nodes[i], b=nodes[j];
+        const dx=b.x-a.x, dy=b.y-a.y, d=Math.hypot(dx,dy)||1;
+        const f=(d-90)*0.008;
+        const fx=(dx/d)*f, fy=(dy/d)*f;
+        a.vx+=fx; a.vy+=fy; b.vx-=fx; b.vy-=fy;
+      }
+      const cx=k.w/2, cy=k.h/2;
+      for (const n of nodes){
+        n.vx += (cx-n.x)*0.002;
+        n.vy += (cy-n.y)*0.002;
+        n.vx *= 0.85; n.vy *= 0.85;
+        n.x += n.vx; n.y += n.vy;
+      }
+      ctx.clearRect(0,0,k.w,k.h);
+      ctx.strokeStyle = 'rgba(180,180,220,0.25)'; ctx.lineWidth=1;
+      for (const [i,j] of edges){
+        const a=nodes[i], b=nodes[j];
+        ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke();
+      }
+      ctx.font='11px system-ui,sans-serif'; ctx.textAlign='center'; ctx.textBaseline='middle';
+      for (const n of nodes){
+        ctx.fillStyle = n.c;
+        ctx.beginPath(); ctx.arc(n.x,n.y,7,0,Math.PI*2); ctx.fill();
+        ctx.fillStyle = tx;
+        ctx.fillText(n.label, n.x, n.y-14);
+      }
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 50 - 0
docs/presentation/comparison/assets/animations/fx/letter-explode.js

@@ -0,0 +1,50 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['letter-explode'] = function(el){
+    const U = window.HPX._u;
+    if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
+    const src = el.querySelector('[data-fx-text]') || el;
+    const text = (el.getAttribute('data-fx-text-value') || src.textContent || 'EXPLODE').trim();
+    // Build a container, hide source text
+    const wrap = document.createElement('div');
+    wrap.style.cssText = 'position:absolute;inset:0;display:flex;align-items:center;justify-content:center;pointer-events:none;';
+    const inner = document.createElement('div');
+    inner.style.cssText = 'font-size:64px;font-weight:900;letter-spacing:0.02em;color:var(--text-1,#fff);white-space:nowrap;';
+    wrap.appendChild(inner);
+    el.appendChild(wrap);
+    const spans = [];
+    for (const ch of text){
+      const s = document.createElement('span');
+      s.textContent = ch === ' ' ? '\u00A0' : ch;
+      s.style.display='inline-block';
+      s.style.transform='translate(0,0)';
+      s.style.transition='transform 900ms cubic-bezier(.2,.9,.3,1), opacity 900ms';
+      s.style.opacity='0';
+      inner.appendChild(s);
+      spans.push(s);
+    }
+    let stopped = false;
+    const run = () => {
+      if (stopped) return;
+      spans.forEach((s,i) => {
+        const dx = U.rand(-400, 400), dy = U.rand(-300, 300);
+        s.style.transition='none';
+        s.style.transform=`translate(${dx}px,${dy}px) rotate(${U.rand(-180,180)}deg)`;
+        s.style.opacity='0';
+      });
+      // force reflow
+      void inner.offsetWidth;
+      spans.forEach((s,i) => {
+        setTimeout(() => {
+          if (stopped) return;
+          s.style.transition='transform 900ms cubic-bezier(.2,.9,.3,1), opacity 900ms';
+          s.style.transform='translate(0,0) rotate(0deg)';
+          s.style.opacity='1';
+        }, i*35);
+      });
+    };
+    run();
+    const iv = setInterval(run, 4500);
+    return { stop(){ stopped=true; clearInterval(iv); if (wrap.parentNode) wrap.parentNode.removeChild(wrap); } };
+  };
+})();

+ 40 - 0
docs/presentation/comparison/assets/animations/fx/magnetic-field.js

@@ -0,0 +1,40 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['magnetic-field'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    const N = 60;
+    const parts = Array.from({length:N}, (_,i) => ({
+      phase: Math.random()*Math.PI*2,
+      freq: U.rand(0.4, 1.2),
+      amp: U.rand(30, 90),
+      y0: U.rand(0.15, 0.85),
+      c: pal[i%pal.length],
+      trail: []
+    }));
+    const stop = U.loop((t) => {
+      ctx.fillStyle = 'rgba(0,0,0,0.08)';
+      ctx.fillRect(0,0,k.w,k.h);
+      for (const p of parts){
+        const x = ((t*80 + p.phase*50) % (k.w+100)) - 50;
+        const y = k.h*p.y0 + Math.sin(x*0.02 + p.phase + t*p.freq)*p.amp;
+        p.trail.push([x,y]);
+        if (p.trail.length > 18) p.trail.shift();
+        ctx.strokeStyle = p.c;
+        ctx.lineWidth = 2;
+        ctx.beginPath();
+        for (let i=0;i<p.trail.length;i++){
+          const [tx,ty] = p.trail[i];
+          if (i===0) ctx.moveTo(tx,ty); else ctx.lineTo(tx,ty);
+        }
+        ctx.globalAlpha = 0.7;
+        ctx.stroke();
+        ctx.globalAlpha = 1;
+        ctx.fillStyle = p.c;
+        ctx.beginPath(); ctx.arc(x,y,2.5,0,Math.PI*2); ctx.fill();
+      }
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 33 - 0
docs/presentation/comparison/assets/animations/fx/matrix-rain.js

@@ -0,0 +1,33 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['matrix-rain'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const glyphs = 'アイウエオカキクケコサシスセソタチツテトナニヌネノ0123456789ABCDEF'.split('');
+    const fs = 16;
+    let cols = 0, drops = [];
+    const init = () => {
+      cols = Math.ceil(k.w/fs);
+      drops = Array.from({length:cols}, () => U.rand(-20, 0));
+    };
+    init();
+    let lw = k.w, lh = k.h;
+    const stop = U.loop(() => {
+      if (k.w!==lw || k.h!==lh){ init(); lw=k.w; lh=k.h; }
+      ctx.fillStyle = 'rgba(0,0,0,0.08)';
+      ctx.fillRect(0,0,k.w,k.h);
+      ctx.font = fs+'px monospace';
+      for (let i=0;i<cols;i++){
+        const ch = glyphs[(Math.random()*glyphs.length)|0];
+        const x = i*fs, y = drops[i]*fs;
+        ctx.fillStyle = '#9fffc9';
+        ctx.fillText(ch, x, y);
+        ctx.fillStyle = '#00ff6a';
+        ctx.fillText(ch, x, y - fs);
+        drops[i] += 1;
+        if (y > k.h && Math.random() > 0.975) drops[i] = 0;
+      }
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 75 - 0
docs/presentation/comparison/assets/animations/fx/neural-net.js

@@ -0,0 +1,75 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['neural-net'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const ac = U.accent(el,'#7c5cff'), ac2 = U.accent2(el,'#22d3ee');
+    const layers = [4,6,6,3];
+    let nodes = [], edges = [], pulses = [];
+    const layout = () => {
+      nodes = [];
+      const pad = 40;
+      const cw = k.w - pad*2, ch = k.h - pad*2;
+      for (let L=0; L<layers.length; L++){
+        const x = pad + (cw * L / (layers.length-1));
+        const n = layers[L];
+        for (let i=0;i<n;i++){
+          const y = pad + (ch * (i+0.5) / n);
+          nodes.push({x,y,L,i});
+        }
+      }
+      edges = [];
+      for (let L=0; L<layers.length-1; L++){
+        const a = nodes.filter(n=>n.L===L), b = nodes.filter(n=>n.L===L+1);
+        for (const x of a) for (const y of b) edges.push([nodes.indexOf(x),nodes.indexOf(y)]);
+      }
+    };
+    layout();
+    let lw=k.w, lh=k.h, last=0;
+    const stop = U.loop((t) => {
+      if (k.w!==lw||k.h!==lh){ layout(); lw=k.w; lh=k.h; }
+      ctx.clearRect(0,0,k.w,k.h);
+      ctx.strokeStyle = 'rgba(160,160,200,0.22)'; ctx.lineWidth=1;
+      for (const [i,j] of edges){
+        const a=nodes[i], b=nodes[j];
+        ctx.beginPath(); ctx.moveTo(a.x,a.y); ctx.lineTo(b.x,b.y); ctx.stroke();
+      }
+      if (t - last > 0.25){
+        last = t;
+        const starts = nodes.filter(n=>n.L===0);
+        const s = starts[(Math.random()*starts.length)|0];
+        pulses.push({node:s, L:0, t:0});
+      }
+      pulses = pulses.filter(p => p.L < layers.length-1);
+      for (const p of pulses){
+        p.t += 0.03;
+        if (p.t >= 1){
+          const next = nodes.filter(n=>n.L===p.L+1);
+          p.node2 = next[(Math.random()*next.length)|0];
+          if (!p._started){ p._started = true; }
+        }
+      }
+      // animate progression
+      for (const p of pulses){
+        if (!p.target){
+          const next = nodes.filter(n=>n.L===p.L+1);
+          p.target = next[(Math.random()*next.length)|0];
+        }
+        p.t += 0.04;
+        const a = p.node, b = p.target;
+        const x = a.x + (b.x-a.x)*Math.min(1,p.t);
+        const y = a.y + (b.y-a.y)*Math.min(1,p.t);
+        ctx.fillStyle = ac2;
+        ctx.beginPath(); ctx.arc(x,y,4,0,Math.PI*2); ctx.fill();
+        if (p.t >= 1){ p.node = b; p.target=null; p.L++; p.t=0; }
+      }
+      for (const n of nodes){
+        ctx.fillStyle = ac;
+        ctx.beginPath(); ctx.arc(n.x,n.y,6,0,Math.PI*2); ctx.fill();
+        ctx.strokeStyle = ac2; ctx.lineWidth=1.5;
+        ctx.beginPath(); ctx.arc(n.x,n.y,8,0,Math.PI*2); ctx.stroke();
+      }
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 38 - 0
docs/presentation/comparison/assets/animations/fx/orbit-ring.js

@@ -0,0 +1,38 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['orbit-ring'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    const rings = [
+      {r:40,  n:3,  sp:1.2, c:pal[0]},
+      {r:75,  n:5,  sp:0.8, c:pal[1]},
+      {r:110, n:8,  sp:-0.6, c:pal[2]},
+      {r:145, n:12, sp:0.4, c:pal[3]},
+      {r:180, n:16, sp:-0.3, c:pal[4]}
+    ];
+    const stop = U.loop((t) => {
+      ctx.clearRect(0,0,k.w,k.h);
+      const cx=k.w/2, cy=k.h/2;
+      // radial glow
+      const g = ctx.createRadialGradient(cx,cy,0,cx,cy,210);
+      g.addColorStop(0,'rgba(124,92,255,0.25)');
+      g.addColorStop(1,'rgba(0,0,0,0)');
+      ctx.fillStyle = g; ctx.fillRect(0,0,k.w,k.h);
+      for (const R of rings){
+        ctx.strokeStyle = 'rgba(200,200,230,0.2)'; ctx.lineWidth=1;
+        ctx.beginPath(); ctx.arc(cx,cy,R.r,0,Math.PI*2); ctx.stroke();
+        for (let i=0;i<R.n;i++){
+          const a = (i/R.n)*Math.PI*2 + t*R.sp;
+          const x = cx + Math.cos(a)*R.r;
+          const y = cy + Math.sin(a)*R.r;
+          ctx.fillStyle = R.c;
+          ctx.beginPath(); ctx.arc(x,y,4,0,Math.PI*2); ctx.fill();
+        }
+      }
+      ctx.fillStyle = '#fff';
+      ctx.beginPath(); ctx.arc(cx,cy,5,0,Math.PI*2); ctx.fill();
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 42 - 0
docs/presentation/comparison/assets/animations/fx/particle-burst.js

@@ -0,0 +1,42 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['particle-burst'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    let parts = [];
+    const spawn = () => {
+      const cx = k.w/2, cy = k.h/2;
+      const n = 90;
+      for (let i=0;i<n;i++){
+        const a = Math.random()*Math.PI*2;
+        const s = U.rand(80, 260);
+        parts.push({
+          x: cx, y: cy,
+          vx: Math.cos(a)*s, vy: Math.sin(a)*s,
+          life: 1, r: U.rand(2,5),
+          c: pal[(Math.random()*pal.length)|0]
+        });
+      }
+    };
+    spawn();
+    let lastSpawn = 0;
+    const stop = U.loop((t) => {
+      ctx.clearRect(0,0,k.w,k.h);
+      if (t - lastSpawn > 2.5) { spawn(); lastSpawn = t; }
+      const dt = 1/60;
+      parts = parts.filter(p => p.life > 0);
+      for (const p of parts){
+        p.vy += 220*dt;
+        p.vx *= 0.985; p.vy *= 0.985;
+        p.x += p.vx*dt; p.y += p.vy*dt;
+        p.life -= 0.012;
+        ctx.globalAlpha = Math.max(0, p.life);
+        ctx.fillStyle = p.c;
+        ctx.beginPath(); ctx.arc(p.x, p.y, p.r, 0, Math.PI*2); ctx.fill();
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 39 - 0
docs/presentation/comparison/assets/animations/fx/shockwave.js

@@ -0,0 +1,39 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['shockwave'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const ac = U.accent(el,'#7c5cff'), ac2 = U.accent2(el,'#22d3ee');
+    let waves = [];
+    let last = -1;
+    const stop = U.loop((t) => {
+      ctx.fillStyle = 'rgba(0,0,0,0.12)';
+      ctx.fillRect(0,0,k.w,k.h);
+      if (t - last > 0.6){ last = t; waves.push({t:0}); }
+      const cx=k.w/2, cy=k.h/2;
+      const max = Math.hypot(k.w,k.h)/2;
+      waves = waves.filter(w => w.t < 1);
+      for (const w of waves){
+        w.t += 0.012;
+        const r = w.t * max;
+        const alpha = 1 - w.t;
+        ctx.strokeStyle = w.t<0.5?ac2:ac;
+        ctx.globalAlpha = alpha;
+        ctx.lineWidth = 3 + (1-w.t)*3;
+        ctx.beginPath(); ctx.arc(cx,cy,r,0,Math.PI*2); ctx.stroke();
+        ctx.strokeStyle = '#fff';
+        ctx.lineWidth = 1;
+        ctx.globalAlpha = alpha*0.4;
+        ctx.beginPath(); ctx.arc(cx,cy,r*0.92,0,Math.PI*2); ctx.stroke();
+      }
+      ctx.globalAlpha = 1;
+      // core
+      const g = ctx.createRadialGradient(cx,cy,0,cx,cy,40);
+      g.addColorStop(0,'rgba(255,255,255,0.9)');
+      g.addColorStop(1,'rgba(124,92,255,0)');
+      ctx.fillStyle = g;
+      ctx.beginPath(); ctx.arc(cx,cy,40,0,Math.PI*2); ctx.fill();
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 62 - 0
docs/presentation/comparison/assets/animations/fx/sparkle-trail.js

@@ -0,0 +1,62 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['sparkle-trail'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    k.c.style.pointerEvents = 'none';
+    el.style.cursor = 'crosshair';
+    const pal = U.palette(el);
+    let sparks = [];
+    const onMove = (e) => {
+      const r = el.getBoundingClientRect();
+      const x = e.clientX - r.left, y = e.clientY - r.top;
+      for (let i=0;i<3;i++){
+        sparks.push({
+          x, y,
+          vx: U.rand(-60,60), vy: U.rand(-80,20),
+          life: 1, c: pal[(Math.random()*pal.length)|0],
+          r: U.rand(1.5,3.5)
+        });
+      }
+    };
+    // auto-wiggle if no mouse moves
+    let auto = true, autoT = 0;
+    const onAny = () => { auto = false; };
+    el.addEventListener('pointermove', onMove);
+    el.addEventListener('pointerenter', onAny);
+    const stop = U.loop(() => {
+      ctx.fillStyle = 'rgba(0,0,0,0.15)';
+      ctx.fillRect(0,0,k.w,k.h);
+      if (auto){
+        autoT += 0.04;
+        const x = k.w/2 + Math.cos(autoT)*k.w*0.3;
+        const y = k.h/2 + Math.sin(autoT*1.3)*k.h*0.3;
+        for (let i=0;i<3;i++){
+          sparks.push({
+            x, y,
+            vx: U.rand(-60,60), vy: U.rand(-80,20),
+            life: 1, c: pal[(Math.random()*pal.length)|0],
+            r: U.rand(1.5,3.5)
+          });
+        }
+      }
+      const dt = 1/60;
+      sparks = sparks.filter(s => s.life > 0);
+      for (const s of sparks){
+        s.vy += 160*dt;
+        s.x += s.vx*dt; s.y += s.vy*dt;
+        s.life -= 0.018;
+        ctx.globalAlpha = Math.max(0, s.life);
+        ctx.fillStyle = s.c;
+        ctx.beginPath(); ctx.arc(s.x,s.y,s.r,0,Math.PI*2); ctx.fill();
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){
+      el.removeEventListener('pointermove', onMove);
+      el.removeEventListener('pointerenter', onAny);
+      el.style.cursor = '';
+      stop(); k.destroy();
+    }};
+  };
+})();

+ 30 - 0
docs/presentation/comparison/assets/animations/fx/starfield.js

@@ -0,0 +1,30 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['starfield'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const tx = U.text(el, '#ffffff');
+    const N = 260;
+    const stars = Array.from({length:N}, () => ({
+      x: U.rand(-1,1), y: U.rand(-1,1), z: Math.random()
+    }));
+    const stop = U.loop(() => {
+      ctx.fillStyle = 'rgba(0,0,0,0.25)';
+      ctx.fillRect(0,0,k.w,k.h);
+      const cx = k.w/2, cy = k.h/2;
+      for (const s of stars){
+        s.z -= 0.006;
+        if (s.z <= 0.02) { s.x = U.rand(-1,1); s.y = U.rand(-1,1); s.z = 1; }
+        const px = cx + (s.x/s.z)*cx;
+        const py = cy + (s.y/s.z)*cy;
+        if (px<0||py<0||px>k.w||py>k.h) continue;
+        const r = (1-s.z)*2.4;
+        ctx.globalAlpha = 1-s.z;
+        ctx.fillStyle = tx;
+        ctx.beginPath(); ctx.arc(px,py,r,0,Math.PI*2); ctx.fill();
+      }
+      ctx.globalAlpha = 1;
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 51 - 0
docs/presentation/comparison/assets/animations/fx/typewriter-multi.js

@@ -0,0 +1,51 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['typewriter-multi'] = function(el){
+    if (getComputedStyle(el).position === 'static') el.style.position = 'relative';
+    const lines = [
+      (el.getAttribute('data-fx-line1') || '> initializing knowledge graph...'),
+      (el.getAttribute('data-fx-line2') || '> loading 28 concept nodes'),
+      (el.getAttribute('data-fx-line3') || '> agent ready. awaiting prompt_'),
+    ];
+    const wrap = document.createElement('div');
+    wrap.style.cssText = 'position:absolute;inset:0;display:flex;flex-direction:column;justify-content:center;gap:14px;padding:32px 48px;font:600 22px ui-monospace,Menlo,monospace;color:var(--text-1,#e7e7ef);';
+    el.appendChild(wrap);
+    const rows = lines.map((txt) => {
+      const row = document.createElement('div');
+      row.style.cssText = 'white-space:pre;display:flex;align-items:center;';
+      const span = document.createElement('span'); span.textContent = '';
+      const cur = document.createElement('span');
+      cur.textContent = '\u2588';
+      cur.style.cssText = 'display:inline-block;margin-left:2px;color:var(--accent,#22d3ee);animation:hpxBlink 1s steps(2) infinite;';
+      row.appendChild(span); row.appendChild(cur);
+      wrap.appendChild(row);
+      return {row, span, txt, i:0};
+    });
+    // inject blink keyframes once
+    if (!document.getElementById('hpx-blink-kf')){
+      const st = document.createElement('style');
+      st.id = 'hpx-blink-kf';
+      st.textContent = '@keyframes hpxBlink{50%{opacity:0}}';
+      document.head.appendChild(st);
+    }
+    let stopped = false;
+    const speeds = [55, 70, 45];
+    rows.forEach((r, idx) => {
+      const tick = () => {
+        if (stopped) return;
+        if (r.i < r.txt.length){
+          r.span.textContent += r.txt[r.i++];
+          setTimeout(tick, speeds[idx]);
+        } else {
+          setTimeout(() => {
+            if (stopped) return;
+            r.i = 0; r.span.textContent = '';
+            tick();
+          }, 2200);
+        }
+      };
+      setTimeout(tick, idx*400);
+    });
+    return { stop(){ stopped = true; if (wrap.parentNode) wrap.parentNode.removeChild(wrap); } };
+  };
+})();

+ 47 - 0
docs/presentation/comparison/assets/animations/fx/word-cascade.js

@@ -0,0 +1,47 @@
+(function(){
+  window.HPX = window.HPX || {};
+  window.HPX['word-cascade'] = function(el){
+    const U = window.HPX._u;
+    const k = U.canvas(el), ctx = k.ctx;
+    const pal = U.palette(el);
+    const WORDS = ['AI','知识','Graph','Claude','LLM','Agent','Vector','RAG','Token','神经',
+      'Prompt','Chain','Skill','Code','Cloud','GPU','Flow','推理','Data','Model'];
+    let items = [];
+    let last = -1;
+    let piles = {}; // column -> stack height
+    const stop = U.loop((t) => {
+      ctx.clearRect(0,0,k.w,k.h);
+      if (t - last > 0.18){
+        last = t;
+        const w = WORDS[(Math.random()*WORDS.length)|0];
+        items.push({
+          text: w, x: U.rand(40, k.w-40), y: -20,
+          vy: 0, c: pal[(Math.random()*pal.length)|0],
+          size: U.rand(16,26), landed: false
+        });
+      }
+      ctx.textAlign='center'; ctx.textBaseline='middle';
+      for (const it of items){
+        if (!it.landed){
+          it.vy += 0.4;
+          it.y += it.vy;
+          const col = Math.round(it.x/60);
+          const floor = k.h - (piles[col]||0) - it.size*0.6;
+          if (it.y >= floor){
+            it.y = floor; it.landed = true;
+            piles[col] = (piles[col]||0) + it.size*1.1;
+            if ((piles[col]||0) > k.h*0.8) piles[col] = 0; // reset if too high
+          }
+        }
+        ctx.fillStyle = it.c;
+        ctx.font = `700 ${it.size}px system-ui,sans-serif`;
+        ctx.fillText(it.text, it.x, it.y);
+      }
+      // prune old landed
+      if (items.length > 120){
+        items = items.filter(i => !i.landed).concat(items.filter(i=>i.landed).slice(-60));
+      }
+    });
+    return { stop(){ stop(); k.destroy(); } };
+  };
+})();

+ 150 - 0
docs/presentation/comparison/assets/base.css

@@ -0,0 +1,150 @@
+/* html-ppt :: base.css — reset + shared tokens + layout primitives */
+/* Default tokens. Themes in assets/themes/*.css override the :root block. */
+:root {
+  --bg: #ffffff;
+  --bg-soft: #f7f7f8;
+  --surface: #ffffff;
+  --surface-2: #f2f2f4;
+  --border: rgba(0,0,0,.08);
+  --border-strong: rgba(0,0,0,.16);
+  --text-1: #111216;
+  --text-2: #55596a;
+  --text-3: #8a8f9e;
+  --accent: #3b6cff;
+  --accent-2: #7a5cff;
+  --accent-3: #ff5c8a;
+  --good: #1aaf6c;
+  --warn: #f5a524;
+  --bad:  #e0445a;
+  --grad: linear-gradient(135deg,#3b6cff,#7a5cff 55%,#ff5c8a);
+  --grad-soft: linear-gradient(135deg,#eef2ff,#f5ecff 55%,#ffeef5);
+  --radius: 18px;
+  --radius-sm: 12px;
+  --radius-lg: 26px;
+  --shadow: 0 10px 30px rgba(18,24,40,.08), 0 2px 6px rgba(18,24,40,.04);
+  --shadow-lg: 0 24px 60px rgba(18,24,40,.14), 0 6px 16px rgba(18,24,40,.06);
+  --font-sans: 'Inter','Noto Sans SC',-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;
+  --font-serif: 'Playfair Display','Noto Serif SC',Georgia,serif;
+  --font-mono: 'JetBrains Mono','IBM Plex Mono',SFMono-Regular,Menlo,monospace;
+  --font-display: var(--font-sans);
+  --letter-tight: -.03em;
+  --letter-normal: -.01em;
+  --ease: cubic-bezier(.4,0,.2,1);
+}
+
+*,*::before,*::after{box-sizing:border-box}
+html,body{margin:0;padding:0;background:var(--bg);color:var(--text-1);
+  font-family:var(--font-sans);font-weight:400;line-height:1.6;
+  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
+  letter-spacing:var(--letter-normal)}
+img,svg,video{max-width:100%;display:block}
+a{color:var(--accent);text-decoration:none}
+a:hover{text-decoration:underline}
+code,kbd,pre,samp{font-family:var(--font-mono)}
+
+/* ================= SLIDE SYSTEM ================= */
+.deck{position:relative;width:100vw;height:100vh;overflow:hidden;background:var(--bg)}
+.slide{
+  position:absolute;inset:0;
+  display:flex;flex-direction:column;justify-content:center;
+  padding:72px 96px;
+  box-sizing:border-box;
+  opacity:0;pointer-events:none;
+  transition:opacity .5s var(--ease), transform .5s var(--ease);
+  transform:translateX(30px);
+  overflow:hidden;
+}
+.slide.is-active{opacity:1;pointer-events:auto;transform:translateX(0);z-index:2}
+.slide.is-prev{transform:translateX(-30px)}
+
+/* single-page standalone (used when a layout file is opened directly) */
+body.single .slide{position:relative;width:100vw;height:100vh;opacity:1;transform:none;pointer-events:auto}
+
+/* ================= TYPOGRAPHY ================= */
+.eyebrow{font-size:13px;font-weight:500;letter-spacing:.16em;text-transform:uppercase;color:var(--text-3)}
+.kicker{font-size:14px;font-weight:600;color:var(--accent);letter-spacing:.08em;text-transform:uppercase}
+h1.title,.h1{font-family:var(--font-display);font-size:72px;line-height:1.05;font-weight:800;letter-spacing:var(--letter-tight);margin:0 0 18px;color:var(--text-1)}
+h2.title,.h2{font-family:var(--font-display);font-size:54px;line-height:1.1;font-weight:700;letter-spacing:var(--letter-tight);margin:0 0 14px}
+h3,.h3{font-size:32px;line-height:1.2;font-weight:600;letter-spacing:var(--letter-normal);margin:0 0 10px}
+h4,.h4{font-size:22px;line-height:1.3;font-weight:600;margin:0 0 8px}
+.lede{font-size:22px;line-height:1.55;color:var(--text-2);font-weight:300;max-width:62ch}
+.dim{color:var(--text-2)}
+.dim2{color:var(--text-3)}
+.mono{font-family:var(--font-mono)}
+.serif{font-family:var(--font-serif)}
+.gradient-text{background:var(--grad);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;color:transparent}
+
+/* ================= LAYOUT PRIMITIVES ================= */
+.stack>*+*{margin-top:14px}
+.row{display:flex;gap:24px;align-items:center}
+.row.wrap{flex-wrap:wrap}
+.grid{display:grid;gap:24px}
+.g2{grid-template-columns:repeat(2,1fr)}
+.g3{grid-template-columns:repeat(3,1fr)}
+.g4{grid-template-columns:repeat(4,1fr)}
+.center{display:flex;align-items:center;justify-content:center;text-align:center}
+.fill{flex:1}
+.sp-t{padding-top:24px}.sp-b{padding-bottom:24px}
+.mt-s{margin-top:8px}.mt-m{margin-top:18px}.mt-l{margin-top:32px}
+.mb-s{margin-bottom:8px}.mb-m{margin-bottom:18px}.mb-l{margin-bottom:32px}
+
+/* ================= CARDS ================= */
+.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);
+  padding:26px 28px;box-shadow:var(--shadow);position:relative;overflow:hidden}
+.card-soft{background:var(--surface-2);border:1px solid var(--border)}
+.card-outline{background:transparent;border:1.5px solid var(--border-strong);box-shadow:none}
+.card-accent{background:var(--surface);border-top:3px solid var(--accent)}
+.card-hover{transition:transform .3s var(--ease),box-shadow .3s var(--ease)}
+.card-hover:hover{transform:translateY(-4px);box-shadow:var(--shadow-lg)}
+
+.pill{display:inline-block;padding:4px 12px;border-radius:999px;font-size:12px;font-weight:500;
+  background:var(--surface-2);color:var(--text-2);border:1px solid var(--border)}
+.pill-accent{background:color-mix(in srgb,var(--accent) 12%,transparent);color:var(--accent);border-color:color-mix(in srgb,var(--accent) 28%,transparent)}
+
+/* ================= BARS / DIVIDERS ================= */
+.divider{height:1px;background:var(--border);width:100%}
+.divider-accent{height:3px;width:72px;background:var(--accent);border-radius:2px}
+
+/* ================= CHROME (header/footer/progress) ================= */
+.deck-header{position:absolute;top:24px;left:40px;right:40px;display:flex;align-items:center;justify-content:space-between;
+  font-size:12px;color:var(--text-3);letter-spacing:.12em;text-transform:uppercase;z-index:10;pointer-events:none}
+.deck-footer{position:absolute;bottom:24px;left:40px;right:40px;display:flex;align-items:center;justify-content:space-between;
+  font-size:12px;color:var(--text-3);z-index:10;pointer-events:none}
+.slide-number::before{content:attr(data-current)}
+.slide-number::after{content:" / " attr(data-total)}
+.progress-bar{position:fixed;left:0;right:0;bottom:0;height:3px;background:transparent;z-index:20}
+.progress-bar > span{display:block;height:100%;width:0;background:var(--accent);transition:width .3s var(--ease)}
+
+/* ================= PRESENTER / OVERVIEW ================= */
+.notes{display:none!important}
+.notes-overlay{position:fixed;inset:auto 0 0 0;max-height:42vh;background:rgba(20,22,30,.95);color:#e8ebf4;
+  padding:20px 32px;font-size:16px;line-height:1.6;border-top:1px solid rgba(255,255,255,.1);transform:translateY(100%);
+  transition:transform .3s var(--ease);z-index:40;overflow:auto;font-family:var(--font-sans)}
+.notes-overlay.open{transform:translateY(0)}
+.overview{position:fixed;inset:0;background:rgba(10,12,18,.92);backdrop-filter:blur(12px);z-index:50;
+  display:none;padding:40px;overflow:auto}
+.overview.open{display:grid;grid-template-columns:repeat(4,1fr);gap:20px;align-content:start}
+.overview .thumb{background:var(--surface);border:1px solid var(--border);border-radius:12px;
+  aspect-ratio:16/9;overflow:hidden;cursor:pointer;position:relative;color:var(--text-1);padding:16px;
+  font-size:11px;transition:transform .2s var(--ease)}
+.overview .thumb:hover{transform:scale(1.04)}
+.overview .thumb .n{position:absolute;top:8px;left:10px;font-weight:700;font-size:14px;color:var(--text-3)}
+.overview .thumb .t{position:absolute;bottom:10px;left:14px;right:14px;font-weight:600;color:var(--text-1)}
+
+/* ================= PRESENTER VIEW ================= */
+/* Presenter view opens in a separate popup window (S key).
+ * All presenter styles are self-contained in the popup HTML generated by runtime.js.
+ * The audience window (this file) is NOT affected — it stays as normal deck view.
+ * Only the .notes class below is needed to hide speaker notes from audience. */
+
+/* ================= UTILITY ================= */
+.hidden{display:none!important}
+.nowrap{white-space:nowrap}
+.tr{text-align:right}.tc{text-align:center}.tl{text-align:left}
+.uppercase{text-transform:uppercase;letter-spacing:.12em}
+
+/* ================= PRINT ================= */
+@media print{
+  .slide{position:relative;opacity:1!important;transform:none!important;page-break-after:always;height:100vh}
+  .deck-header,.deck-footer,.progress-bar,.notes-overlay,.overview{display:none!important}
+}

+ 9 - 0
docs/presentation/comparison/assets/fonts.css

@@ -0,0 +1,9 @@
+/* html-ppt :: shared webfonts */
+@import url('https://fonts.googleapis.com/css2?family=Inter:wght@200;300;400;500;600;700;800;900&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@200;300;400;500;600;700;900&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@300;400;600;700&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,600;0,800;1,400&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@300;400;500;700&display=swap');
+@import url('https://fonts.googleapis.com/css2?family=Archivo+Black&display=swap');

+ 960 - 0
docs/presentation/comparison/assets/runtime.js

@@ -0,0 +1,960 @@
+/* html-ppt :: runtime.js
+ * Keyboard-driven deck runtime. Zero dependencies.
+ *
+ * Features:
+ *   ← → / space / PgUp PgDn / Home End  navigation
+ *   F  fullscreen
+ *   S  presenter mode (opens a NEW WINDOW with current/next slide preview + notes + timer)
+ *       The original window stays as audience view, synced via BroadcastChannel.
+ *       Slide previews use CSS transform:scale() at design resolution for pixel-perfect layout.
+ *   N  quick notes overlay (bottom drawer)
+ *   O  slide overview grid
+ *   T  cycle themes (reads data-themes on <html> or <body>)
+ *   A  cycle demo animation on current slide
+ *   URL hash #/N  deep-link to slide N (1-based)
+ *   Progress bar auto-managed
+ */
+(function () {
+  'use strict';
+
+  const ANIMS = ['fade-up','fade-down','fade-left','fade-right','rise-in','drop-in',
+    'zoom-pop','blur-in','glitch-in','typewriter','neon-glow','shimmer-sweep',
+    'gradient-flow','stagger-list','counter-up','path-draw','parallax-tilt',
+    'card-flip-3d','cube-rotate-3d','page-turn-3d','perspective-zoom',
+    'marquee-scroll','kenburns','confetti-burst','spotlight','morph-shape','ripple-reveal'];
+
+  function ready(fn){ if(document.readyState!='loading')fn(); else document.addEventListener('DOMContentLoaded',fn);}
+
+  /* ========== Parse URL for preview-only mode ==========
+   * When loaded as iframe.src = "index.html?preview=3", runtime enters a
+   * locked single-slide mode: only slide N is visible, no chrome, no keys,
+   * no hash updates. This is how the presenter window shows pixel-perfect
+   * previews — by loading the actual deck file in an iframe and telling it
+   * to display only a specific slide.
+   */
+  function getPreviewIdx() {
+    const m = /[?&]preview=(\d+)/.exec(location.search || '');
+    return m ? parseInt(m[1], 10) - 1 : -1;
+  }
+
+  ready(function () {
+    const deck = document.querySelector('.deck');
+    if (!deck) return;
+    const slides = Array.from(deck.querySelectorAll('.slide'));
+    if (!slides.length) return;
+
+    const previewOnlyIdx = getPreviewIdx();
+    const isPreviewMode = previewOnlyIdx >= 0 && previewOnlyIdx < slides.length;
+
+    /* ===== Preview-only mode: show one slide, hide everything else ===== */
+    if (isPreviewMode) {
+      function showSlide(i) {
+        slides.forEach((s, j) => {
+          const active = (j === i);
+          s.classList.toggle('is-active', active);
+          s.style.display = active ? '' : 'none';
+          if (active) {
+            s.style.opacity = '1';
+            s.style.transform = 'none';
+            s.style.pointerEvents = 'auto';
+          }
+        });
+      }
+      showSlide(previewOnlyIdx);
+      /* Hide chrome that the presenter shouldn't see in preview */
+      const hideSel = '.progress-bar, .notes-overlay, .overview, .notes, aside.notes, .speaker-notes';
+      document.querySelectorAll(hideSel).forEach(el => { el.style.display = 'none'; });
+      document.documentElement.setAttribute('data-preview', '1');
+      document.body.setAttribute('data-preview', '1');
+      /* Auto-detect theme base path for theme switching in preview mode */
+      function getPreviewThemeBase() {
+        const base = document.documentElement.getAttribute('data-theme-base');
+        if (base) return base;
+        const tl = document.getElementById('theme-link');
+        if (tl) {
+          const raw = tl.getAttribute('href') || '';
+          const ls = raw.lastIndexOf('/');
+          if (ls >= 0) return raw.substring(0, ls + 1);
+        }
+        return 'assets/themes/';
+      }
+      const previewThemeBase = getPreviewThemeBase();
+
+      /* Listen for postMessage from parent presenter window:
+       *  - preview-goto: switch visible slide WITHOUT reloading
+       *  - preview-theme: switch theme CSS link to match audience window */
+      window.addEventListener('message', function(e) {
+        if (!e.data) return;
+        if (e.data.type === 'preview-goto') {
+          const n = parseInt(e.data.idx, 10);
+          if (n >= 0 && n < slides.length) showSlide(n);
+        } else if (e.data.type === 'preview-theme' && e.data.name) {
+          let link = document.getElementById('theme-link');
+          if (!link) {
+            link = document.createElement('link');
+            link.rel = 'stylesheet';
+            link.id = 'theme-link';
+            document.head.appendChild(link);
+          }
+          link.href = previewThemeBase + e.data.name + '.css';
+          document.documentElement.setAttribute('data-theme', e.data.name);
+        }
+      });
+      /* Signal to parent that preview iframe is ready */
+      try { window.parent && window.parent.postMessage({ type: 'preview-ready' }, '*'); } catch(e) {}
+      return;
+    }
+
+    let idx = 0;
+    const total = slides.length;
+
+    /* ===== BroadcastChannel for presenter sync ===== */
+    const CHANNEL_NAME = 'html-ppt-presenter-' + location.pathname;
+    let bc;
+    try { bc = new BroadcastChannel(CHANNEL_NAME); } catch(e) { bc = null; }
+
+    // Are we running inside the presenter popup? (legacy flag, now unused)
+    const isPresenterWindow = false;
+
+    /* ===== progress bar ===== */
+    let bar = document.querySelector('.progress-bar');
+    if (!bar) {
+      bar = document.createElement('div');
+      bar.className = 'progress-bar';
+      bar.innerHTML = '<span></span>';
+      document.body.appendChild(bar);
+    }
+    const barFill = bar.querySelector('span');
+
+    /* ===== notes overlay (N key) ===== */
+    let notes = document.querySelector('.notes-overlay');
+    if (!notes) {
+      notes = document.createElement('div');
+      notes.className = 'notes-overlay';
+      document.body.appendChild(notes);
+    }
+
+    /* ===== overview grid (O key) ===== */
+    let overview = document.querySelector('.overview');
+    if (!overview) {
+      overview = document.createElement('div');
+      overview.className = 'overview';
+      slides.forEach((s, i) => {
+        const t = document.createElement('div');
+        t.className = 'thumb';
+        // Force 16:9 aspect ratio robustly
+        t.style.padding = '0 0 56.25% 0';
+        t.style.height = '0';
+        t.style.position = 'relative';
+        t.style.overflow = 'hidden';
+
+        const title = s.getAttribute('data-title') ||
+          (s.querySelector('h1,h2,h3')||{}).textContent || ('Slide '+(i+1));
+        
+        // Create a container for the mini-slide
+        const mini = document.createElement('div');
+        mini.className = 'mini-slide';
+        mini.style.position = 'absolute';
+        mini.style.top = '0';
+        mini.style.left = '0';
+        mini.style.width = '1920px';
+        mini.style.height = '1080px';
+        mini.style.transformOrigin = 'top left';
+        mini.style.pointerEvents = 'none';
+        mini.style.background = 'var(--bg)';
+        
+        // Clone the slide content
+        const clone = s.cloneNode(true);
+        clone.className = 'slide is-active'; // force active styles
+        clone.style.position = 'absolute';
+        clone.style.inset = '0';
+        clone.style.transform = 'none';
+        clone.style.opacity = '1';
+        clone.style.padding = '72px 96px'; // ensure padding is kept
+        
+        mini.appendChild(clone);
+        t.appendChild(mini);
+
+        // Add the number and title overlay
+        const overlay = document.createElement('div');
+        overlay.style.position = 'absolute';
+        overlay.style.inset = '0';
+        overlay.style.background = 'linear-gradient(to bottom, rgba(0,0,0,0.2) 0%, transparent 40%, transparent 60%, rgba(0,0,0,0.8) 100%)';
+        overlay.style.color = '#fff';
+        overlay.style.zIndex = '10';
+        overlay.style.pointerEvents = 'none';
+        
+        const n = document.createElement('div');
+        n.className = 'n';
+        n.textContent = i + 1;
+        n.style.position = 'absolute';
+        n.style.top = '12px';
+        n.style.left = '16px';
+        n.style.fontWeight = '700';
+        n.style.fontSize = '16px';
+        n.style.color = '#fff';
+        n.style.textShadow = '0 1px 4px rgba(0,0,0,0.8)';
+        
+        const text = document.createElement('div');
+        text.className = 't';
+        text.textContent = title.trim().slice(0,80);
+        text.style.position = 'absolute';
+        text.style.bottom = '12px';
+        text.style.left = '16px';
+        text.style.right = '16px';
+        text.style.fontWeight = '600';
+        text.style.fontSize = '14px';
+        text.style.color = '#fff';
+        text.style.textShadow = '0 1px 4px rgba(0,0,0,0.8)';
+        
+        overlay.appendChild(n);
+        overlay.appendChild(text);
+        t.appendChild(overlay);
+
+        t.addEventListener('click', () => { go(i); toggleOverview(false); });
+        overview.appendChild(t);
+      });
+      document.body.appendChild(overview);
+    }
+
+    /* ===== navigation ===== */
+    function go(n, fromRemote){
+      n = Math.max(0, Math.min(total-1, n));
+      slides.forEach((s,i) => {
+        s.classList.toggle('is-active', i===n);
+        s.classList.toggle('is-prev', i<n);
+      });
+      idx = n;
+      barFill.style.width = ((n+1)/total*100)+'%';
+      const numEl = document.querySelector('.slide-number');
+      if (numEl) { numEl.setAttribute('data-current', n+1); numEl.setAttribute('data-total', total); }
+
+      // notes (bottom overlay)
+      const note = slides[n].querySelector('.notes, aside.notes, .speaker-notes');
+      notes.innerHTML = note ? note.innerHTML : '';
+
+      // hash
+      const hashTarget = '#/'+(n+1);
+      if (location.hash !== hashTarget && !isPresenterWindow) {
+        history.replaceState(null,'', hashTarget);
+      }
+
+      // re-trigger entry animations
+      slides[n].querySelectorAll('[data-anim]').forEach(el => {
+        const a = el.getAttribute('data-anim');
+        el.classList.remove('anim-'+a);
+        void el.offsetWidth;
+        el.classList.add('anim-'+a);
+      });
+
+      // counter-up
+      slides[n].querySelectorAll('.counter').forEach(el => {
+        const target = parseFloat(el.getAttribute('data-to')||el.textContent);
+        const dur = parseInt(el.getAttribute('data-dur')||'1200',10);
+        const start = performance.now();
+        const from = 0;
+        function tick(now){
+          const t = Math.min(1,(now-start)/dur);
+          const v = from + (target-from)*(1-Math.pow(1-t,3));
+          el.textContent = (target % 1 === 0) ? Math.round(v) : v.toFixed(1);
+          if (t<1) requestAnimationFrame(tick);
+        }
+        requestAnimationFrame(tick);
+      });
+
+      // Broadcast to other window (audience ↔ presenter)
+      if (!fromRemote && bc) {
+        bc.postMessage({ type: 'go', idx: n });
+      }
+    }
+
+    /* ===== listen for remote navigation / theme changes ===== */
+    if (bc) {
+      bc.onmessage = function(e) {
+        if (!e.data) return;
+        if (e.data.type === 'go' && typeof e.data.idx === 'number') {
+          go(e.data.idx, true);
+        } else if (e.data.type === 'theme' && e.data.name) {
+          /* Sync theme across windows */
+          const i = themes.indexOf(e.data.name);
+          if (i >= 0) themeIdx = i;
+          applyTheme(e.data.name);
+        }
+      };
+    }
+
+    function toggleNotes(force){ notes.classList.toggle('open', force!==undefined?force:!notes.classList.contains('open')); }
+    function toggleOverview(force){
+      const isOpen = force!==undefined ? force : !overview.classList.contains('open');
+      overview.classList.toggle('open', isOpen);
+      if (isOpen) {
+        requestAnimationFrame(() => {
+          const thumbs = overview.querySelectorAll('.thumb');
+          if (thumbs.length) {
+            const scale = thumbs[0].clientWidth / 1920;
+            overview.querySelectorAll('.mini-slide').forEach(m => {
+              m.style.transform = 'scale(' + scale + ')';
+            });
+          }
+        });
+      }
+    }
+
+    /* ========== PRESENTER MODE — Magnetic-card popup window ========== */
+    /* Opens a new window with 4 draggable, resizable cards:
+     *   CURRENT  — iframe(?preview=N)   pixel-perfect preview of current slide
+     *   NEXT     — iframe(?preview=N+1) pixel-perfect preview of next slide
+     *   SCRIPT   — large speaker notes (逐字稿)
+     *   TIMER    — elapsed timer + page counter + controls
+     * Cards remember position/size in localStorage.
+     * Two windows sync via BroadcastChannel.
+     */
+    let presenterWin = null;
+
+    function openPresenterWindow() {
+      if (presenterWin && !presenterWin.closed) {
+        presenterWin.focus();
+        return;
+      }
+
+      // Build absolute URL of THIS deck file (without hash/query)
+      const deckUrl = location.protocol + '//' + location.host + location.pathname;
+
+      // Collect slide titles + notes (HTML strings)
+      const slideMeta = slides.map((s, i) => {
+        const note = s.querySelector('.notes, aside.notes, .speaker-notes');
+        return {
+          title: s.getAttribute('data-title') ||
+            (s.querySelector('h1,h2,h3')||{}).textContent || ('Slide '+(i+1)),
+          notes: note ? note.innerHTML : ''
+        };
+      });
+
+      /* Capture current theme so presenter previews match the audience */
+      const currentTheme = root.getAttribute('data-theme') || (themes[themeIdx] || '');
+      const presenterHTML = buildPresenterHTML(deckUrl, slideMeta, total, idx, CHANNEL_NAME, currentTheme);
+
+      presenterWin = window.open('', 'html-ppt-presenter', 'width=1280,height=820,menubar=no,toolbar=no');
+      if (!presenterWin) {
+        alert('请允许弹出窗口以使用演讲者视图');
+        return;
+      }
+      presenterWin.document.open();
+      presenterWin.document.write(presenterHTML);
+      presenterWin.document.close();
+    }
+
+    function buildPresenterHTML(deckUrl, slideMeta, total, startIdx, channelName, currentTheme) {
+      const metaJSON = JSON.stringify(slideMeta);
+      const deckUrlJSON = JSON.stringify(deckUrl);
+      const channelJSON = JSON.stringify(channelName);
+      const themeJSON = JSON.stringify(currentTheme || '');
+      const storageKey = 'html-ppt-presenter:' + location.pathname;
+
+      // Build the document as a single template string for clarity
+      return `<!DOCTYPE html>
+<html lang="zh-CN">
+<head>
+<meta charset="utf-8">
+<title>Presenter View</title>
+<style>
+  * { margin: 0; padding: 0; box-sizing: border-box; }
+  html, body {
+    width: 100%; height: 100%; overflow: hidden;
+    background: #1a1d24;
+    background-image:
+      radial-gradient(circle at 20% 30%, rgba(88,166,255,.04), transparent 50%),
+      radial-gradient(circle at 80% 70%, rgba(188,140,255,.04), transparent 50%);
+    color: #e6edf3;
+    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans SC", sans-serif;
+  }
+  /* Stage: positioned area where cards live */
+  #stage { position: absolute; inset: 0; overflow: hidden; }
+
+  /* Magnetic card */
+  .pcard {
+    position: absolute;
+    background: #0d1117;
+    border: 1px solid rgba(255,255,255,.1);
+    border-radius: 12px;
+    box-shadow: 0 8px 32px rgba(0,0,0,.45), 0 0 0 1px rgba(255,255,255,.02);
+    display: flex; flex-direction: column;
+    overflow: hidden;
+    min-width: 180px; min-height: 100px;
+    transition: box-shadow .2s, border-color .2s;
+  }
+  .pcard.dragging { box-shadow: 0 16px 48px rgba(0,0,0,.6), 0 0 0 2px rgba(88,166,255,.5); border-color: #58a6ff; transition: none; z-index: 9999; }
+  .pcard.resizing { box-shadow: 0 16px 48px rgba(0,0,0,.6), 0 0 0 2px rgba(63,185,80,.5); border-color: #3fb950; transition: none; z-index: 9999; }
+  .pcard:hover { border-color: rgba(88,166,255,.3); }
+
+  /* Card header (drag handle) */
+  .pcard-head {
+    display: flex; align-items: center; gap: 10px;
+    padding: 8px 12px;
+    background: rgba(255,255,255,.04);
+    border-bottom: 1px solid rgba(255,255,255,.06);
+    cursor: move;
+    user-select: none;
+    flex-shrink: 0;
+  }
+  .pcard-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--dot-color, #58a6ff); flex-shrink: 0; }
+  .pcard-title {
+    font-size: 11px; letter-spacing: .15em; text-transform: uppercase;
+    font-weight: 700; color: #8b949e; flex: 1;
+  }
+  .pcard-meta { font-size: 11px; color: #6e7681; }
+
+  /* Card body */
+  .pcard-body { flex: 1; position: relative; overflow: hidden; min-height: 0; }
+
+  /* Preview cards (CURRENT/NEXT) — iframe-based pixel-perfect render */
+  .pcard-preview .pcard-body { background: #000; }
+  .pcard-preview iframe {
+    position: absolute; top: 0; left: 0;
+    width: 1920px; height: 1080px;
+    border: none;
+    transform-origin: top left;
+    pointer-events: none;
+    background: transparent;
+  }
+  .pcard-preview .preview-end {
+    position: absolute; inset: 0;
+    display: flex; align-items: center; justify-content: center;
+    color: #484f58; font-size: 14px; letter-spacing: .12em;
+  }
+
+  /* Notes card */
+  .pcard-notes .pcard-body {
+    padding: 14px 18px;
+    overflow-y: auto;
+    font-size: 18px; line-height: 1.75;
+    color: #d0d7de;
+    font-family: "Noto Sans SC", -apple-system, sans-serif;
+  }
+  .pcard-notes .pcard-body p { margin: 0 0 .7em 0; }
+  .pcard-notes .pcard-body strong { color: #f0883e; }
+  .pcard-notes .pcard-body em { color: #58a6ff; font-style: normal; }
+  .pcard-notes .pcard-body code {
+    font-family: "SF Mono", monospace; font-size: .9em;
+    background: rgba(255,255,255,.08); padding: 1px 6px; border-radius: 4px;
+  }
+  .pcard-notes .empty { color: #484f58; font-style: italic; }
+
+  /* Timer card */
+  .pcard-timer .pcard-body {
+    display: flex; flex-direction: column; gap: 14px;
+    padding: 18px 20px; justify-content: center;
+  }
+  .timer-display {
+    font-family: "SF Mono", "JetBrains Mono", monospace;
+    font-size: 42px; font-weight: 700;
+    color: #3fb950;
+    letter-spacing: .04em;
+    line-height: 1;
+  }
+  .timer-row {
+    display: flex; align-items: center; gap: 12px;
+    font-size: 14px; color: #8b949e;
+  }
+  .timer-row .label { font-size: 10px; letter-spacing: .15em; text-transform: uppercase; color: #6e7681; }
+  .timer-row .val { color: #e6edf3; font-weight: 600; font-family: "SF Mono", monospace; }
+  .timer-controls { display: flex; gap: 8px; flex-wrap: wrap; }
+  .timer-btn {
+    background: rgba(255,255,255,.06);
+    border: 1px solid rgba(255,255,255,.1);
+    color: #e6edf3;
+    padding: 6px 12px;
+    border-radius: 6px;
+    font-size: 12px;
+    cursor: pointer;
+    font-family: inherit;
+  }
+  .timer-btn:hover { background: rgba(88,166,255,.15); border-color: #58a6ff; }
+  .timer-btn:active { transform: translateY(1px); }
+
+  /* Resize handle */
+  .pcard-resize {
+    position: absolute; right: 0; bottom: 0;
+    width: 18px; height: 18px;
+    cursor: nwse-resize;
+    background: linear-gradient(135deg, transparent 50%, rgba(255,255,255,.25) 50%, rgba(255,255,255,.25) 60%, transparent 60%, transparent 70%, rgba(255,255,255,.25) 70%, rgba(255,255,255,.25) 80%, transparent 80%);
+    z-index: 5;
+  }
+  .pcard-resize:hover { background: linear-gradient(135deg, transparent 50%, #58a6ff 50%, #58a6ff 60%, transparent 60%, transparent 70%, #58a6ff 70%, #58a6ff 80%, transparent 80%); }
+
+  /* Bottom hint bar */
+  .hint-bar {
+    position: fixed; bottom: 0; left: 0; right: 0;
+    background: rgba(0,0,0,.6);
+    backdrop-filter: blur(10px);
+    border-top: 1px solid rgba(255,255,255,.08);
+    padding: 6px 16px;
+    font-size: 11px; color: #8b949e;
+    display: flex; gap: 18px; align-items: center;
+    z-index: 1000;
+  }
+  .hint-bar kbd {
+    background: rgba(255,255,255,.08);
+    padding: 1px 6px; border-radius: 3px;
+    font-family: "SF Mono", monospace;
+    font-size: 10px;
+    border: 1px solid rgba(255,255,255,.1);
+    color: #e6edf3;
+  }
+  .hint-bar .reset-layout {
+    margin-left: auto;
+    background: transparent; border: 1px solid rgba(255,255,255,.15);
+    color: #8b949e; padding: 3px 10px; border-radius: 4px;
+    font-size: 11px; cursor: pointer; font-family: inherit;
+  }
+  .hint-bar .reset-layout:hover { background: rgba(248,81,73,.15); border-color: #f85149; color: #f85149; }
+
+  body.is-dragging-card * { user-select: none !important; }
+  body.is-dragging-card iframe { pointer-events: none !important; }
+</style>
+</head>
+<body>
+
+<div id="stage">
+  <div class="pcard pcard-preview" id="card-cur" style="--dot-color:#58a6ff">
+    <div class="pcard-head" data-drag>
+      <span class="pcard-dot"></span>
+      <span class="pcard-title">CURRENT</span>
+      <span class="pcard-meta" id="cur-meta">—</span>
+    </div>
+    <div class="pcard-body"><iframe id="iframe-cur"></iframe></div>
+    <div class="pcard-resize" data-resize></div>
+  </div>
+
+  <div class="pcard pcard-preview" id="card-nxt" style="--dot-color:#bc8cff">
+    <div class="pcard-head" data-drag>
+      <span class="pcard-dot"></span>
+      <span class="pcard-title">NEXT</span>
+      <span class="pcard-meta" id="nxt-meta">—</span>
+    </div>
+    <div class="pcard-body"><iframe id="iframe-nxt"></iframe></div>
+    <div class="pcard-resize" data-resize></div>
+  </div>
+
+  <div class="pcard pcard-notes" id="card-notes" style="--dot-color:#f0883e">
+    <div class="pcard-head" data-drag>
+      <span class="pcard-dot"></span>
+      <span class="pcard-title">SPEAKER SCRIPT · 逐字稿</span>
+    </div>
+    <div class="pcard-body" id="notes-body"></div>
+    <div class="pcard-resize" data-resize></div>
+  </div>
+
+  <div class="pcard pcard-timer" id="card-timer" style="--dot-color:#3fb950">
+    <div class="pcard-head" data-drag>
+      <span class="pcard-dot"></span>
+      <span class="pcard-title">TIMER</span>
+    </div>
+    <div class="pcard-body">
+      <div class="timer-display" id="timer-display">00:00</div>
+      <div class="timer-row">
+        <span class="label">Slide</span>
+        <span class="val" id="timer-count">1 / ${total}</span>
+      </div>
+      <div class="timer-controls">
+        <button class="timer-btn" id="btn-prev">← Prev</button>
+        <button class="timer-btn" id="btn-next">Next →</button>
+        <button class="timer-btn" id="btn-reset">⏱ Reset</button>
+      </div>
+    </div>
+    <div class="pcard-resize" data-resize></div>
+  </div>
+</div>
+
+<div class="hint-bar">
+  <span><kbd>← →</kbd> 翻页</span>
+  <span><kbd>R</kbd> 重置计时</span>
+  <span><kbd>Esc</kbd> 关闭</span>
+  <span style="color:#6e7681">拖动卡片头部移动 · 拖动右下角调整大小</span>
+  <button class="reset-layout" id="reset-layout">重置布局</button>
+</div>
+
+<script>
+(function(){
+  var slideMeta = ${metaJSON};
+  var total = ${total};
+  var idx = ${startIdx};
+  var deckUrl = ${deckUrlJSON};
+  var STORAGE_KEY = ${JSON.stringify(storageKey)};
+  var bc;
+  try { bc = new BroadcastChannel(${channelJSON}); } catch(e) {}
+
+  var iframeCur = document.getElementById('iframe-cur');
+  var iframeNxt = document.getElementById('iframe-nxt');
+  var notesBody = document.getElementById('notes-body');
+  var curMeta = document.getElementById('cur-meta');
+  var nxtMeta = document.getElementById('nxt-meta');
+  var timerDisplay = document.getElementById('timer-display');
+  var timerCount = document.getElementById('timer-count');
+
+  /* ===== Default card layout ===== */
+  function defaultLayout() {
+    var w = window.innerWidth;
+    var h = window.innerHeight - 36; /* leave room for hint bar */
+    return {
+      'card-cur':   { x: 16,        y: 16,            w: Math.round(w*0.55) - 24, h: Math.round(h*0.62) - 16 },
+      'card-nxt':   { x: Math.round(w*0.55) + 8, y: 16, w: w - Math.round(w*0.55) - 24, h: Math.round(h*0.42) - 16 },
+      'card-notes': { x: Math.round(w*0.55) + 8, y: Math.round(h*0.42) + 8, w: w - Math.round(w*0.55) - 24, h: h - Math.round(h*0.42) - 16 },
+      'card-timer': { x: 16,        y: Math.round(h*0.62) + 8, w: Math.round(w*0.55) - 24, h: h - Math.round(h*0.62) - 16 }
+    };
+  }
+
+  /* ===== Apply / save / restore layout ===== */
+  function applyLayout(layout) {
+    Object.keys(layout).forEach(function(id){
+      var el = document.getElementById(id);
+      var l = layout[id];
+      if (el && l) {
+        el.style.left = l.x + 'px';
+        el.style.top = l.y + 'px';
+        el.style.width = l.w + 'px';
+        el.style.height = l.h + 'px';
+      }
+    });
+    rescaleAll();
+  }
+  function readLayout() {
+    try {
+      var saved = localStorage.getItem(STORAGE_KEY);
+      if (saved) return JSON.parse(saved);
+    } catch(e) {}
+    return defaultLayout();
+  }
+  function saveLayout() {
+    var layout = {};
+    ['card-cur','card-nxt','card-notes','card-timer'].forEach(function(id){
+      var el = document.getElementById(id);
+      if (el) {
+        layout[id] = {
+          x: parseInt(el.style.left,10) || 0,
+          y: parseInt(el.style.top,10) || 0,
+          w: parseInt(el.style.width,10) || 300,
+          h: parseInt(el.style.height,10) || 200
+        };
+      }
+    });
+    try { localStorage.setItem(STORAGE_KEY, JSON.stringify(layout)); } catch(e) {}
+  }
+
+  /* ===== iframe rescale to fit card body ===== */
+  function rescaleIframe(iframe) {
+    if (!iframe || iframe.style.display === 'none') return;
+    var body = iframe.parentElement;
+    var cw = body.clientWidth, ch = body.clientHeight;
+    if (!cw || !ch) return;
+    var s = Math.min(cw / 1920, ch / 1080);
+    iframe.style.transform = 'scale(' + s + ')';
+    /* Center the scaled iframe in the body */
+    var sw = 1920 * s, sh = 1080 * s;
+    iframe.style.left = Math.max(0, (cw - sw) / 2) + 'px';
+    iframe.style.top = Math.max(0, (ch - sh) / 2) + 'px';
+  }
+  function rescaleAll() {
+    rescaleIframe(iframeCur);
+    rescaleIframe(iframeNxt);
+  }
+  window.addEventListener('resize', rescaleAll);
+
+  /* ===== Drag (move card by header) ===== */
+  document.querySelectorAll('[data-drag]').forEach(function(handle){
+    handle.addEventListener('mousedown', function(e){
+      if (e.button !== 0) return;
+      var card = handle.closest('.pcard');
+      if (!card) return;
+      e.preventDefault();
+      card.classList.add('dragging');
+      document.body.classList.add('is-dragging-card');
+      var startX = e.clientX, startY = e.clientY;
+      var startL = parseInt(card.style.left,10) || 0;
+      var startT = parseInt(card.style.top,10)  || 0;
+      function onMove(ev){
+        var nx = Math.max(0, Math.min(window.innerWidth - 100, startL + ev.clientX - startX));
+        var ny = Math.max(0, Math.min(window.innerHeight - 50, startT + ev.clientY - startY));
+        card.style.left = nx + 'px';
+        card.style.top = ny + 'px';
+      }
+      function onUp(){
+        card.classList.remove('dragging');
+        document.body.classList.remove('is-dragging-card');
+        document.removeEventListener('mousemove', onMove);
+        document.removeEventListener('mouseup', onUp);
+        saveLayout();
+      }
+      document.addEventListener('mousemove', onMove);
+      document.addEventListener('mouseup', onUp);
+    });
+  });
+
+  /* ===== Resize (drag bottom-right corner) ===== */
+  document.querySelectorAll('[data-resize]').forEach(function(handle){
+    handle.addEventListener('mousedown', function(e){
+      if (e.button !== 0) return;
+      var card = handle.closest('.pcard');
+      if (!card) return;
+      e.preventDefault(); e.stopPropagation();
+      card.classList.add('resizing');
+      document.body.classList.add('is-dragging-card');
+      var startX = e.clientX, startY = e.clientY;
+      var startW = parseInt(card.style.width,10)  || card.offsetWidth;
+      var startH = parseInt(card.style.height,10) || card.offsetHeight;
+      function onMove(ev){
+        var nw = Math.max(180, startW + ev.clientX - startX);
+        var nh = Math.max(100, startH + ev.clientY - startY);
+        card.style.width = nw + 'px';
+        card.style.height = nh + 'px';
+        if (card.querySelector('iframe')) rescaleIframe(card.querySelector('iframe'));
+      }
+      function onUp(){
+        card.classList.remove('resizing');
+        document.body.classList.remove('is-dragging-card');
+        document.removeEventListener('mousemove', onMove);
+        document.removeEventListener('mouseup', onUp);
+        rescaleAll();
+        saveLayout();
+      }
+      document.addEventListener('mousemove', onMove);
+      document.addEventListener('mouseup', onUp);
+    });
+  });
+
+  /* ===== Preview iframe ready tracking =====
+   * Each iframe loads the deck ONCE with ?preview=1 on init. Subsequent
+   * slide changes are sent via postMessage('preview-goto') so the iframe
+   * just toggles visibility of a different .slide — no reload, no flicker.
+   */
+  var iframeReady = { cur: false, nxt: false };
+  var currentTheme = ${themeJSON};
+  window.addEventListener('message', function(e) {
+    if (!e.data || e.data.type !== 'preview-ready') return;
+    var iframe = null;
+    if (e.source === iframeCur.contentWindow) {
+      iframeReady.cur = true;
+      iframe = iframeCur;
+      postPreviewGoto(iframeCur, idx);
+    } else if (e.source === iframeNxt.contentWindow) {
+      iframeReady.nxt = true;
+      iframe = iframeNxt;
+      postPreviewGoto(iframeNxt, idx + 1 < total ? idx + 1 : idx);
+    }
+    /* Sync current theme to the iframe */
+    if (iframe && currentTheme) {
+      try { iframe.contentWindow.postMessage({ type: 'preview-theme', name: currentTheme }, '*'); } catch(err) {}
+    }
+    if (iframe) rescaleIframe(iframe);
+  });
+
+  function postPreviewGoto(iframe, n) {
+    try {
+      iframe.contentWindow.postMessage({ type: 'preview-goto', idx: n }, '*');
+    } catch(e) {}
+  }
+
+  /* ===== Update content =====
+   * Smooth (no-reload) navigation: send postMessage to iframes instead of
+   * resetting src. Iframes stay loaded, just switch visible .slide.
+   */
+  function update(n) {
+    n = Math.max(0, Math.min(total - 1, n));
+    idx = n;
+
+    /* Current preview — postMessage (smooth) */
+    if (iframeReady.cur) postPreviewGoto(iframeCur, n);
+    curMeta.textContent = (n + 1) + '/' + total;
+
+    /* Next preview */
+    if (n + 1 < total) {
+      iframeNxt.style.display = '';
+      var endEl = document.querySelector('#card-nxt .preview-end');
+      if (endEl) endEl.remove();
+      if (iframeReady.nxt) postPreviewGoto(iframeNxt, n + 1);
+      nxtMeta.textContent = (n + 2) + '/' + total;
+    } else {
+      iframeNxt.style.display = 'none';
+      var body = document.querySelector('#card-nxt .pcard-body');
+      if (body && !body.querySelector('.preview-end')) {
+        var end = document.createElement('div');
+        end.className = 'preview-end';
+        end.textContent = '— END OF DECK —';
+        body.appendChild(end);
+      }
+      nxtMeta.textContent = 'END';
+    }
+
+    /* Notes */
+    var note = slideMeta[n].notes;
+    notesBody.innerHTML = note || '<span class="empty">(这一页还没有逐字稿)</span>';
+
+    /* Timer count */
+    timerCount.textContent = (n + 1) + ' / ' + total;
+  }
+
+  /* ===== Timer ===== */
+  var tStart = Date.now();
+  setInterval(function(){
+    var s = Math.floor((Date.now() - tStart) / 1000);
+    var mm = String(Math.floor(s/60)).padStart(2,'0');
+    var ss = String(s%60).padStart(2,'0');
+    timerDisplay.textContent = mm + ':' + ss;
+  }, 1000);
+  function resetTimer(){ tStart = Date.now(); timerDisplay.textContent = '00:00'; }
+
+  /* ===== BroadcastChannel sync ===== */
+  if (bc) {
+    bc.onmessage = function(e){
+      if (!e.data) return;
+      if (e.data.type === 'go') update(e.data.idx);
+      else if (e.data.type === 'theme' && e.data.name) {
+        currentTheme = e.data.name;
+        /* Forward theme change to preview iframes */
+        [iframeCur, iframeNxt].forEach(function(iframe){
+          try {
+            iframe.contentWindow.postMessage({ type: 'preview-theme', name: e.data.name }, '*');
+          } catch(err) {}
+        });
+      }
+    };
+  }
+  function go(n) {
+    update(n);
+    if (bc) bc.postMessage({ type: 'go', idx: idx });
+  }
+
+  /* ===== Buttons ===== */
+  document.getElementById('btn-prev').addEventListener('click', function(){ go(idx - 1); });
+  document.getElementById('btn-next').addEventListener('click', function(){ go(idx + 1); });
+  document.getElementById('btn-reset').addEventListener('click', resetTimer);
+  document.getElementById('reset-layout').addEventListener('click', function(){
+    if (confirm('恢复默认卡片布局?')) {
+      try { localStorage.removeItem(STORAGE_KEY); } catch(e){}
+      applyLayout(defaultLayout());
+    }
+  });
+
+  /* ===== Keyboard ===== */
+  document.addEventListener('keydown', function(e){
+    if (e.metaKey || e.ctrlKey || e.altKey) return;
+    switch(e.key) {
+      case 'ArrowRight': case ' ': case 'PageDown': go(idx + 1); e.preventDefault(); break;
+      case 'ArrowLeft':  case 'PageUp':   go(idx - 1); e.preventDefault(); break;
+      case 'Home': go(0); break;
+      case 'End':  go(total - 1); break;
+      case 'r': case 'R': resetTimer(); break;
+      case 'Escape': window.close(); break;
+    }
+  });
+
+  /* ===== Iframe load → rescale (catches initial size) ===== */
+  iframeCur.addEventListener('load', function(){ rescaleIframe(iframeCur); });
+  iframeNxt.addEventListener('load', function(){ rescaleIframe(iframeNxt); });
+
+  /* ===== Init =====
+   * Load each iframe ONCE with the deck file. After they post
+   * 'preview-ready', all subsequent navigation is via postMessage
+   * (smooth, no reload, no flicker).
+   */
+  applyLayout(readLayout());
+  iframeCur.src = deckUrl + '?preview=' + (idx + 1);
+  if (idx + 1 < total) iframeNxt.src = deckUrl + '?preview=' + (idx + 2);
+  /* Initialize notes/timer/count without touching iframes */
+  notesBody.innerHTML = slideMeta[idx].notes || '<span class="empty">(这一页还没有逐字稿)</span>';
+  curMeta.textContent = (idx + 1) + '/' + total;
+  nxtMeta.textContent = (idx + 2) + '/' + total;
+  timerCount.textContent = (idx + 1) + ' / ' + total;
+})();
+</` + `script>
+</body></html>`;
+    }
+
+    function fullscreen(){ const el=document.documentElement;
+      if (!document.fullscreenElement) el.requestFullscreen&&el.requestFullscreen();
+      else document.exitFullscreen&&document.exitFullscreen();
+    }
+
+    // theme cycling
+    const root = document.documentElement;
+    const themesAttr = root.getAttribute('data-themes') || document.body.getAttribute('data-themes');
+    const themes = themesAttr ? themesAttr.split(',').map(s=>s.trim()).filter(Boolean) : [];
+    let themeIdx = 0;
+
+    // Auto-detect theme base path from existing <link id="theme-link">
+    let themeBase = root.getAttribute('data-theme-base');
+    if (!themeBase) {
+      const existingLink = document.getElementById('theme-link');
+      if (existingLink) {
+        // el.getAttribute('href') gives the raw relative path written in HTML
+        const rawHref = existingLink.getAttribute('href') || '';
+        const lastSlash = rawHref.lastIndexOf('/');
+        themeBase = lastSlash >= 0 ? rawHref.substring(0, lastSlash + 1) : 'assets/themes/';
+      } else {
+        themeBase = 'assets/themes/';
+      }
+    }
+
+    function applyTheme(name) {
+      let link = document.getElementById('theme-link');
+      if (!link) {
+        link = document.createElement('link');
+        link.rel = 'stylesheet';
+        link.id = 'theme-link';
+        document.head.appendChild(link);
+      }
+      link.href = themeBase + name + '.css';
+      root.setAttribute('data-theme', name);
+      const ind = document.querySelector('.theme-indicator');
+      if (ind) ind.textContent = name;
+    }
+    function cycleTheme(fromRemote){
+      if (!themes.length) return;
+      themeIdx = (themeIdx+1) % themes.length;
+      const name = themes[themeIdx];
+      applyTheme(name);
+      /* Broadcast to other window (audience ↔ presenter) */
+      if (!fromRemote && bc) bc.postMessage({ type: 'theme', name: name });
+    }
+
+    // animation cycling on current slide
+    let animIdx = 0;
+    function cycleAnim(){
+      animIdx = (animIdx+1) % ANIMS.length;
+      const a = ANIMS[animIdx];
+      const target = slides[idx].querySelector('[data-anim-target]') || slides[idx];
+      ANIMS.forEach(x => target.classList.remove('anim-'+x));
+      void target.offsetWidth;
+      target.classList.add('anim-'+a);
+      target.setAttribute('data-anim', a);
+      const ind = document.querySelector('.anim-indicator');
+      if (ind) ind.textContent = a;
+    }
+
+    document.addEventListener('keydown', function (e) {
+      if (e.metaKey||e.ctrlKey||e.altKey) return;
+      switch (e.key) {
+        case 'ArrowRight': case ' ': case 'PageDown': case 'Enter': go(idx+1); e.preventDefault(); break;
+        case 'ArrowLeft': case 'PageUp': case 'Backspace': go(idx-1); e.preventDefault(); break;
+        case 'Home': go(0); break;
+        case 'End': go(total-1); break;
+        case 'f': case 'F': fullscreen(); break;
+        case 's': case 'S': openPresenterWindow(); break;
+        case 'n': case 'N': toggleNotes(); break;
+        case 'o': case 'O': toggleOverview(); break;
+        case 't': case 'T': cycleTheme(); break;
+        case 'a': case 'A': cycleAnim(); break;
+        case 'Escape': toggleOverview(false); toggleNotes(false); break;
+      }
+    });
+
+    // hash deep-link
+    function fromHash(){
+      const m = /^#\/(\d+)/.exec(location.hash||'');
+      if (m) go(Math.max(0, parseInt(m[1],10)-1));
+    }
+    window.addEventListener('hashchange', fromHash);
+    fromHash();
+    go(idx);
+  });
+})();

+ 23 - 0
docs/presentation/comparison/assets/themes/academic-paper.css

@@ -0,0 +1,23 @@
+/* theme: academic-paper — 学术论文 */
+:root{
+  --bg:#fdfcf8;--bg-soft:#f7f5ed;--surface:#ffffff;--surface-2:#f5f3ea;
+  --border:rgba(20,20,20,.14);--border-strong:rgba(20,20,20,.35);
+  --text-1:#0a0a0a;--text-2:#333333;--text-3:#707070;
+  --accent:#1a3a7a;--accent-2:#0a0a0a;--accent-3:#8a1a1a;
+  --good:#1a5a2a;--warn:#8a6a1a;--bad:#8a1a1a;
+  --grad:linear-gradient(135deg,#1a3a7a,#0a0a0a);
+  --grad-soft:linear-gradient(135deg,#e8edf8,#f5f3ea);
+  --radius:0px;--radius-sm:0px;--radius-lg:0px;
+  --shadow:none;
+  --shadow-lg:0 1px 2px rgba(0,0,0,.1);
+  --font-sans:'Latin Modern Roman','Playfair Display','Noto Serif SC',Georgia,serif;
+  --font-serif:'Latin Modern Roman','Playfair Display','Noto Serif SC',Georgia,serif;
+  --font-display:'Latin Modern Roman','Playfair Display','Noto Serif SC',Georgia,serif;
+}
+body{font-family:var(--font-serif)}
+h1.title,h2.title,.h1,.h2{font-weight:700;font-family:var(--font-serif)}
+.card{border:1px solid var(--border);box-shadow:none}
+.divider{background:var(--text-1);height:1px}
+.divider-accent{background:var(--text-1);height:2px;width:100%}
+a{color:var(--accent);text-decoration:underline}
+.kicker{color:var(--accent);font-style:italic;text-transform:none;letter-spacing:0;font-weight:400}

+ 14 - 0
docs/presentation/comparison/assets/themes/arctic-cool.css

@@ -0,0 +1,14 @@
+/* theme: arctic-cool — 冷色调 蓝/青/石板灰 */
+:root{
+  --bg:#f2f6fb;--bg-soft:#e7eef7;--surface:#ffffff;--surface-2:#edf3fa;
+  --border:rgba(40,70,110,.12);--border-strong:rgba(40,70,110,.24);
+  --text-1:#0e1f33;--text-2:#3a5778;--text-3:#6b819b;
+  --accent:#1e6fb0;--accent-2:#17b1b1;--accent-3:#6f8aa6;
+  --good:#1aaf84;--warn:#d19030;--bad:#c5485a;
+  --grad:linear-gradient(135deg,#1e6fb0,#17b1b1 60%,#5fb9d6);
+  --grad-soft:linear-gradient(135deg,#e7eef7,#dff3f3);
+  --radius:14px;--radius-sm:10px;--radius-lg:22px;
+  --shadow:0 10px 28px rgba(40,70,110,.12);
+  --shadow-lg:0 24px 60px rgba(40,70,110,.18);
+  --font-sans:'Inter','Noto Sans SC',sans-serif;
+}

+ 20 - 0
docs/presentation/comparison/assets/themes/aurora.css

@@ -0,0 +1,20 @@
+/* theme: aurora — 极光渐变 */
+:root{
+  --bg:#06091c;--bg-soft:#0a1130;--surface:rgba(255,255,255,.05);--surface-2:rgba(255,255,255,.08);
+  --border:rgba(180,220,255,.14);--border-strong:rgba(180,220,255,.28);
+  --text-1:#e8f0ff;--text-2:#b4c4e4;--text-3:#6a7a9e;
+  --accent:#5ef2c6;--accent-2:#7aa2ff;--accent-3:#c984ff;
+  --good:#5ef2c6;--warn:#ffd27a;--bad:#ff8ab0;
+  --grad:linear-gradient(135deg,#5ef2c6,#7aa2ff 50%,#c984ff);
+  --grad-soft:linear-gradient(135deg,rgba(94,242,198,.2),rgba(201,132,255,.2));
+  --radius:20px;--radius-sm:14px;--radius-lg:28px;
+  --shadow:0 20px 60px rgba(0,0,0,.4),inset 0 1px 0 rgba(255,255,255,.08);
+  --shadow-lg:0 30px 80px rgba(0,0,0,.55);
+  --font-sans:'Inter','Noto Sans SC',sans-serif;
+}
+body{background:
+  radial-gradient(60% 50% at 20% 10%,rgba(94,242,198,.35),transparent 70%),
+  radial-gradient(55% 50% at 80% 20%,rgba(122,162,255,.32),transparent 70%),
+  radial-gradient(70% 60% at 50% 100%,rgba(201,132,255,.3),transparent 70%),
+  #06091c}
+.card{backdrop-filter:blur(24px) saturate(160%);-webkit-backdrop-filter:blur(24px) saturate(160%)}

+ 16 - 0
docs/presentation/comparison/assets/themes/bauhaus.css

@@ -0,0 +1,16 @@
+/* theme: bauhaus — 几何+原色 */
+:root{
+  --bg:#f4efe3;--bg-soft:#e8e2d1;--surface:#ffffff;--surface-2:#f4efe3;
+  --border:#111111;--border-strong:#111111;
+  --text-1:#111111;--text-2:#333333;--text-3:#666666;
+  --accent:#e03c27;--accent-2:#f4c430;--accent-3:#1d4eaf;
+  --good:#1b8c3c;--warn:#f4c430;--bad:#e03c27;
+  --grad:linear-gradient(135deg,#e03c27 0 33%,#f4c430 33% 66%,#1d4eaf 66% 100%);
+  --grad-soft:linear-gradient(135deg,#f4efe3,#e8e2d1);
+  --radius:0;--radius-sm:0;--radius-lg:0;
+  --shadow:4px 4px 0 #111;--shadow-lg:8px 8px 0 #111;
+  --font-sans:'Space Grotesk','Inter','Noto Sans SC',sans-serif;
+  --font-display:'Archivo Black',sans-serif;
+  --letter-tight:-.03em;
+}
+.card{border:2px solid #111}

+ 19 - 0
docs/presentation/comparison/assets/themes/blueprint.css

@@ -0,0 +1,19 @@
+/* theme: blueprint — 蓝图工程 */
+:root{
+  --bg:#0b3a6f;--bg-soft:#0a3260;--surface:rgba(255,255,255,.06);--surface-2:rgba(255,255,255,.1);
+  --border:rgba(190,220,255,.3);--border-strong:rgba(190,220,255,.55);
+  --text-1:#e8f3ff;--text-2:#b8d4f0;--text-3:#7da8cf;
+  --accent:#ffffff;--accent-2:#aee1ff;--accent-3:#ffd27a;
+  --good:#8ef0a6;--warn:#ffd27a;--bad:#ff8a96;
+  --grad:linear-gradient(135deg,#ffffff,#aee1ff);
+  --grad-soft:linear-gradient(135deg,#0a3260,#0b3a6f);
+  --radius:2px;--radius-sm:2px;--radius-lg:4px;
+  --shadow:none;--shadow-lg:0 16px 40px rgba(0,0,0,.3);
+  --font-sans:'JetBrains Mono','IBM Plex Mono',monospace;
+  --font-display:'JetBrains Mono',monospace;
+}
+body{background:
+  linear-gradient(rgba(255,255,255,.06) 1px,transparent 1px) 0 0/40px 40px,
+  linear-gradient(90deg,rgba(255,255,255,.06) 1px,transparent 1px) 0 0/40px 40px,
+  #0b3a6f}
+.card{border:1px dashed rgba(190,220,255,.45);background:rgba(255,255,255,.04)}

+ 14 - 0
docs/presentation/comparison/assets/themes/catppuccin-latte.css

@@ -0,0 +1,14 @@
+/* theme: catppuccin-latte — catppuccin 浅 */
+:root{
+  --bg:#eff1f5;--bg-soft:#e6e9ef;--surface:#ffffff;--surface-2:#eef0f4;
+  --border:rgba(76,79,105,.14);--border-strong:rgba(76,79,105,.28);
+  --text-1:#4c4f69;--text-2:#6c6f85;--text-3:#9ca0b0;
+  --accent:#8839ef;--accent-2:#1e66f5;--accent-3:#ea76cb;
+  --good:#40a02b;--warn:#df8e1d;--bad:#d20f39;
+  --grad:linear-gradient(135deg,#8839ef,#1e66f5 50%,#04a5e5);
+  --grad-soft:linear-gradient(135deg,#eff1f5,#e6e9ef);
+  --radius:14px;--radius-sm:10px;--radius-lg:22px;
+  --shadow:0 8px 24px rgba(76,79,105,.1);
+  --shadow-lg:0 20px 56px rgba(76,79,105,.16);
+  --font-sans:'Inter','Noto Sans SC',sans-serif;
+}

+ 14 - 0
docs/presentation/comparison/assets/themes/catppuccin-mocha.css

@@ -0,0 +1,14 @@
+/* theme: catppuccin-mocha — catppuccin 深 */
+:root{
+  --bg:#1e1e2e;--bg-soft:#181825;--surface:#313244;--surface-2:#45475a;
+  --border:rgba(205,214,244,.12);--border-strong:rgba(205,214,244,.24);
+  --text-1:#cdd6f4;--text-2:#a6adc8;--text-3:#7f849c;
+  --accent:#cba6f7;--accent-2:#89b4fa;--accent-3:#f5c2e7;
+  --good:#a6e3a1;--warn:#f9e2af;--bad:#f38ba8;
+  --grad:linear-gradient(135deg,#cba6f7,#89b4fa 50%,#94e2d5);
+  --grad-soft:linear-gradient(135deg,#313244,#45475a);
+  --radius:14px;--radius-sm:10px;--radius-lg:22px;
+  --shadow:0 10px 30px rgba(0,0,0,.35);
+  --shadow-lg:0 24px 60px rgba(0,0,0,.5);
+  --font-sans:'Inter','Noto Sans SC',sans-serif;
+}

部分文件因为文件数量过多而无法显示