@jakkrichm/create-nexus-devflow 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (431) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +82 -0
  3. package/bin/create-nexus-devflow.js +275 -0
  4. package/lib/update.js +379 -0
  5. package/package.json +53 -0
  6. package/template/.agents/skills/00-discover/SKILL.md +170 -0
  7. package/template/.agents/skills/10-define/SKILL.md +170 -0
  8. package/template/.agents/skills/20-spec/SKILL.md +156 -0
  9. package/template/.agents/skills/30-plan/SKILL.md +221 -0
  10. package/template/.agents/skills/40-implement/SKILL.md +166 -0
  11. package/template/.agents/skills/50-verify/SKILL.md +188 -0
  12. package/template/.agents/skills/60-report/SKILL.md +183 -0
  13. package/template/.agents/skills/70-release/SKILL.md +155 -0
  14. package/template/.agents/skills/9arm-skills/README.md +51 -0
  15. package/template/.agents/skills/9arm-skills/debug-mantra/SKILL.md +86 -0
  16. package/template/.agents/skills/9arm-skills/management-talk/SKILL.md +79 -0
  17. package/template/.agents/skills/9arm-skills/post-mortem/SKILL.md +71 -0
  18. package/template/.agents/skills/9arm-skills/scrutinize/SKILL.md +72 -0
  19. package/template/.agents/skills/agent/SKILL.md +165 -0
  20. package/template/.agents/skills/api-and-interface-design/SKILL.md +294 -0
  21. package/template/.agents/skills/app-builder/SKILL.md +75 -0
  22. package/template/.agents/skills/app-builder/agent-coordination.md +71 -0
  23. package/template/.agents/skills/app-builder/feature-building.md +53 -0
  24. package/template/.agents/skills/app-builder/project-detection.md +34 -0
  25. package/template/.agents/skills/app-builder/scaffolding.md +118 -0
  26. package/template/.agents/skills/app-builder/tech-stack.md +40 -0
  27. package/template/.agents/skills/app-builder/templates/SKILL.md +39 -0
  28. package/template/.agents/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  29. package/template/.agents/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  30. package/template/.agents/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  31. package/template/.agents/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  32. package/template/.agents/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  33. package/template/.agents/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  34. package/template/.agents/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  35. package/template/.agents/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  36. package/template/.agents/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  37. package/template/.agents/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  38. package/template/.agents/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  39. package/template/.agents/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  40. package/template/.agents/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  41. package/template/.agents/skills/architecture/SKILL.md +55 -0
  42. package/template/.agents/skills/architecture/context-discovery.md +43 -0
  43. package/template/.agents/skills/architecture/examples.md +94 -0
  44. package/template/.agents/skills/architecture/pattern-selection.md +68 -0
  45. package/template/.agents/skills/architecture/patterns-reference.md +50 -0
  46. package/template/.agents/skills/architecture/trade-off-analysis.md +77 -0
  47. package/template/.agents/skills/bash-linux/SKILL.md +199 -0
  48. package/template/.agents/skills/behavioral-modes/SKILL.md +242 -0
  49. package/template/.agents/skills/brainstorm/SKILL.md +168 -0
  50. package/template/.agents/skills/browser-testing-with-devtools/SKILL.md +302 -0
  51. package/template/.agents/skills/changelog/SKILL.md +109 -0
  52. package/template/.agents/skills/check-for-updates/SKILL.md +117 -0
  53. package/template/.agents/skills/ci-cd-and-automation/SKILL.md +390 -0
  54. package/template/.agents/skills/code-review-and-quality/SKILL.md +392 -0
  55. package/template/.agents/skills/code-simplification/SKILL.md +331 -0
  56. package/template/.agents/skills/codebase-design/DEEPENING.md +24 -0
  57. package/template/.agents/skills/codebase-design/DESIGN-IT-TWICE.md +28 -0
  58. package/template/.agents/skills/codebase-design/SKILL.md +58 -0
  59. package/template/.agents/skills/commit/SKILL.md +63 -0
  60. package/template/.agents/skills/competitor-analysis/SKILL.md +66 -0
  61. package/template/.agents/skills/context-engineering/SKILL.md +290 -0
  62. package/template/.agents/skills/database-design/SKILL.md +52 -0
  63. package/template/.agents/skills/database-design/database-selection.md +43 -0
  64. package/template/.agents/skills/database-design/indexing.md +39 -0
  65. package/template/.agents/skills/database-design/migrations.md +48 -0
  66. package/template/.agents/skills/database-design/optimization.md +36 -0
  67. package/template/.agents/skills/database-design/orm-selection.md +30 -0
  68. package/template/.agents/skills/database-design/schema-design.md +56 -0
  69. package/template/.agents/skills/database-design/scripts/schema_validator.py +172 -0
  70. package/template/.agents/skills/debug/SKILL.md +131 -0
  71. package/template/.agents/skills/debugging-and-error-recovery/SKILL.md +298 -0
  72. package/template/.agents/skills/deploy/SKILL.md +91 -0
  73. package/template/.agents/skills/deployment-procedures/SKILL.md +241 -0
  74. package/template/.agents/skills/deprecation-and-migration/SKILL.md +206 -0
  75. package/template/.agents/skills/devflow/SKILL.md +89 -0
  76. package/template/.agents/skills/devflow-concept-intake/SKILL.md +150 -0
  77. package/template/.agents/skills/devflow-concept-intake/agents/openai.yaml +4 -0
  78. package/template/.agents/skills/devflow-concept-intake/references/adoption-proposal-template.md +60 -0
  79. package/template/.agents/skills/devflow-concept-intake/references/concept-report-template.md +47 -0
  80. package/template/.agents/skills/devflow-concept-intake/references/upstream-tracking-template.md +51 -0
  81. package/template/.agents/skills/devflow-wiki/SKILL.md +75 -0
  82. package/template/.agents/skills/diagnosing-bugs/SKILL.md +93 -0
  83. package/template/.agents/skills/documentation-and-adrs/SKILL.md +278 -0
  84. package/template/.agents/skills/domain-modeling/ADR-FORMAT.md +47 -0
  85. package/template/.agents/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  86. package/template/.agents/skills/domain-modeling/SKILL.md +74 -0
  87. package/template/.agents/skills/english-to-thai-translator/SKILL.md +125 -0
  88. package/template/.agents/skills/followup/SKILL.md +83 -0
  89. package/template/.agents/skills/frontend-ui-engineering/SKILL.md +326 -0
  90. package/template/.agents/skills/frontend-ui-engineering/accessibility-checklist.md +159 -0
  91. package/template/.agents/skills/git-workflow-and-versioning/SKILL.md +300 -0
  92. package/template/.agents/skills/goal/SKILL.md +148 -0
  93. package/template/.agents/skills/handoff/SKILL.md +46 -0
  94. package/template/.agents/skills/help/SKILL.md +253 -0
  95. package/template/.agents/skills/human-review-decisions/SKILL.md +74 -0
  96. package/template/.agents/skills/i18n-localization/SKILL.md +154 -0
  97. package/template/.agents/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  98. package/template/.agents/skills/idea-refine/SKILL.md +178 -0
  99. package/template/.agents/skills/idea-refine/examples.md +238 -0
  100. package/template/.agents/skills/idea-refine/frameworks.md +99 -0
  101. package/template/.agents/skills/idea-refine/refinement-criteria.md +113 -0
  102. package/template/.agents/skills/idea-refine/scripts/idea-refine.sh +15 -0
  103. package/template/.agents/skills/incremental-implementation/SKILL.md +248 -0
  104. package/template/.agents/skills/insight/SKILL.md +131 -0
  105. package/template/.agents/skills/insight-capture/SKILL.md +84 -0
  106. package/template/.agents/skills/intelligent-routing/SKILL.md +176 -0
  107. package/template/.agents/skills/issue-triage/SKILL.md +115 -0
  108. package/template/.agents/skills/lint-and-validate/SKILL.md +45 -0
  109. package/template/.agents/skills/lint-and-validate/scripts/lint_runner.py +184 -0
  110. package/template/.agents/skills/lint-and-validate/scripts/type_coverage.py +173 -0
  111. package/template/.agents/skills/mcp-builder/SKILL.md +176 -0
  112. package/template/.agents/skills/md2html/SKILL.md +154 -0
  113. package/template/.agents/skills/md2html/components.md +505 -0
  114. package/template/.agents/skills/md2html/template.html +1152 -0
  115. package/template/.agents/skills/merge/SKILL.md +76 -0
  116. package/template/.agents/skills/mobile-design/SKILL.md +394 -0
  117. package/template/.agents/skills/mobile-design/decision-trees.md +516 -0
  118. package/template/.agents/skills/mobile-design/mobile-backend.md +491 -0
  119. package/template/.agents/skills/mobile-design/mobile-color-system.md +420 -0
  120. package/template/.agents/skills/mobile-design/mobile-debugging.md +122 -0
  121. package/template/.agents/skills/mobile-design/mobile-design-thinking.md +357 -0
  122. package/template/.agents/skills/mobile-design/mobile-navigation.md +458 -0
  123. package/template/.agents/skills/mobile-design/mobile-performance.md +767 -0
  124. package/template/.agents/skills/mobile-design/mobile-testing.md +356 -0
  125. package/template/.agents/skills/mobile-design/mobile-typography.md +433 -0
  126. package/template/.agents/skills/mobile-design/platform-android.md +666 -0
  127. package/template/.agents/skills/mobile-design/platform-ios.md +561 -0
  128. package/template/.agents/skills/mobile-design/scripts/mobile_audit.py +670 -0
  129. package/template/.agents/skills/mobile-design/touch-psychology.md +537 -0
  130. package/template/.agents/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +312 -0
  131. package/template/.agents/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +240 -0
  132. package/template/.agents/skills/nextjs-react-expert/3-server-server-side-performance.md +490 -0
  133. package/template/.agents/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +264 -0
  134. package/template/.agents/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +581 -0
  135. package/template/.agents/skills/nextjs-react-expert/6-rendering-rendering-performance.md +432 -0
  136. package/template/.agents/skills/nextjs-react-expert/7-js-javascript-performance.md +684 -0
  137. package/template/.agents/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +150 -0
  138. package/template/.agents/skills/nextjs-react-expert/SKILL.md +286 -0
  139. package/template/.agents/skills/nextjs-react-expert/scripts/convert_rules.py +222 -0
  140. package/template/.agents/skills/nextjs-react-expert/scripts/react_performance_checker.py +252 -0
  141. package/template/.agents/skills/nodejs-best-practices/SKILL.md +333 -0
  142. package/template/.agents/skills/obsidian-bases/SKILL.md +506 -0
  143. package/template/.agents/skills/obsidian-bases/references/FUNCTIONS_REFERENCE.md +173 -0
  144. package/template/.agents/skills/obsidian-cli/SKILL.md +115 -0
  145. package/template/.agents/skills/obsidian-clipper-template-creator/SKILL.md +73 -0
  146. package/template/.agents/skills/obsidian-clipper-template-creator/assets/clipping-template.json +51 -0
  147. package/template/.agents/skills/obsidian-clipper-template-creator/assets/recipe-template.json +48 -0
  148. package/template/.agents/skills/obsidian-clipper-template-creator/references/analysis-workflow.md +79 -0
  149. package/template/.agents/skills/obsidian-clipper-template-creator/references/bases-workflow.md +44 -0
  150. package/template/.agents/skills/obsidian-clipper-template-creator/references/filters.md +51 -0
  151. package/template/.agents/skills/obsidian-clipper-template-creator/references/json-schema.md +77 -0
  152. package/template/.agents/skills/obsidian-clipper-template-creator/references/logic.md +67 -0
  153. package/template/.agents/skills/obsidian-clipper-template-creator/references/variables.md +64 -0
  154. package/template/.agents/skills/obsidian-markdown/SKILL.md +205 -0
  155. package/template/.agents/skills/obsidian-markdown/references/CALLOUTS.md +58 -0
  156. package/template/.agents/skills/obsidian-markdown/references/EMBEDS.md +63 -0
  157. package/template/.agents/skills/obsidian-markdown/references/PROPERTIES.md +61 -0
  158. package/template/.agents/skills/package-json-generator/SKILL.md +60 -0
  159. package/template/.agents/skills/package-json-generator/scripts/generate.js +120 -0
  160. package/template/.agents/skills/package-json-generator/scripts/run.sh +19 -0
  161. package/template/.agents/skills/parallel-agents/SKILL.md +144 -0
  162. package/template/.agents/skills/performance-optimization/SKILL.md +299 -0
  163. package/template/.agents/skills/performance-optimization/performance-checklist.md +113 -0
  164. package/template/.agents/skills/planning-and-task-breakdown/SKILL.md +239 -0
  165. package/template/.agents/skills/powershell-windows/SKILL.md +167 -0
  166. package/template/.agents/skills/pr/SKILL.md +93 -0
  167. package/template/.agents/skills/pr-review/SKILL.md +143 -0
  168. package/template/.agents/skills/pr-review-analysis/SKILL.md +89 -0
  169. package/template/.agents/skills/prd/SKILL.md +127 -0
  170. package/template/.agents/skills/preview/SKILL.md +121 -0
  171. package/template/.agents/skills/preview-local-check/SKILL.md +59 -0
  172. package/template/.agents/skills/prompt-addons/SKILL.md +99 -0
  173. package/template/.agents/skills/prototype/SKILL.md +44 -0
  174. package/template/.agents/skills/prp-dev-fastapi/SKILL.md +114 -0
  175. package/template/.agents/skills/prp-dev-multiplatform/SKILL.md +36 -0
  176. package/template/.agents/skills/prp-dev-odoo/SKILL.md +71 -0
  177. package/template/.agents/skills/prp-dev-php/SKILL.md +63 -0
  178. package/template/.agents/skills/prp-sa-ba/SKILL.md +52 -0
  179. package/template/.agents/skills/python-patterns/SKILL.md +441 -0
  180. package/template/.agents/skills/red-team-tactics/SKILL.md +199 -0
  181. package/template/.agents/skills/release-git-operations/SKILL.md +97 -0
  182. package/template/.agents/skills/research/SKILL.md +143 -0
  183. package/template/.agents/skills/review/SKILL.md +55 -0
  184. package/template/.agents/skills/review-followup-routing/SKILL.md +98 -0
  185. package/template/.agents/skills/roadmap-strategy/SKILL.md +97 -0
  186. package/template/.agents/skills/security-and-hardening/SKILL.md +349 -0
  187. package/template/.agents/skills/security-and-hardening/security-checklist.md +134 -0
  188. package/template/.agents/skills/security-review/SKILL.md +166 -0
  189. package/template/.agents/skills/seo-fundamentals/SKILL.md +129 -0
  190. package/template/.agents/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
  191. package/template/.agents/skills/server-management/SKILL.md +161 -0
  192. package/template/.agents/skills/shipping-and-launch/SKILL.md +311 -0
  193. package/template/.agents/skills/silent-failure-audit/SKILL.md +73 -0
  194. package/template/.agents/skills/simplify/SKILL.md +79 -0
  195. package/template/.agents/skills/skill-development/SKILL.md +86 -0
  196. package/template/.agents/skills/spec-driven-development/SKILL.md +207 -0
  197. package/template/.agents/skills/spec-orchestration/SKILL.md +91 -0
  198. package/template/.agents/skills/specialist-agent-routing/SKILL.md +107 -0
  199. package/template/.agents/skills/tailwind-patterns/SKILL.md +269 -0
  200. package/template/.agents/skills/test/SKILL.md +82 -0
  201. package/template/.agents/skills/test-driven-development/SKILL.md +422 -0
  202. package/template/.agents/skills/test-driven-development/testing-patterns.md +236 -0
  203. package/template/.agents/skills/test-execution-and-coverage/SKILL.md +56 -0
  204. package/template/.agents/skills/type-design/SKILL.md +84 -0
  205. package/template/.agents/skills/ui-ux-pro-max/SKILL.md +75 -0
  206. package/template/.agents/skills/using-agent-skills/SKILL.md +171 -0
  207. package/template/.agents/skills/verification-orchestration/SKILL.md +68 -0
  208. package/template/.agents/skills/vulnerability-scanner/SKILL.md +276 -0
  209. package/template/.agents/skills/vulnerability-scanner/checklists.md +121 -0
  210. package/template/.agents/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
  211. package/template/.agents/skills/wiki/SKILL.md +149 -0
  212. package/template/.agents/skills/workflow-documentation-sync/SKILL.md +87 -0
  213. package/template/.agents/skills/writing-great-skills/SKILL.md +65 -0
  214. package/template/.claude/skills/00-discover/SKILL.md +170 -0
  215. package/template/.claude/skills/10-define/SKILL.md +170 -0
  216. package/template/.claude/skills/20-spec/SKILL.md +156 -0
  217. package/template/.claude/skills/30-plan/SKILL.md +221 -0
  218. package/template/.claude/skills/40-implement/SKILL.md +166 -0
  219. package/template/.claude/skills/50-verify/SKILL.md +188 -0
  220. package/template/.claude/skills/60-report/SKILL.md +183 -0
  221. package/template/.claude/skills/70-release/SKILL.md +155 -0
  222. package/template/.claude/skills/9arm-skills/README.md +51 -0
  223. package/template/.claude/skills/9arm-skills/debug-mantra/SKILL.md +86 -0
  224. package/template/.claude/skills/9arm-skills/management-talk/SKILL.md +79 -0
  225. package/template/.claude/skills/9arm-skills/post-mortem/SKILL.md +71 -0
  226. package/template/.claude/skills/9arm-skills/scrutinize/SKILL.md +72 -0
  227. package/template/.claude/skills/agent/SKILL.md +165 -0
  228. package/template/.claude/skills/api-and-interface-design/SKILL.md +294 -0
  229. package/template/.claude/skills/app-builder/SKILL.md +75 -0
  230. package/template/.claude/skills/app-builder/agent-coordination.md +71 -0
  231. package/template/.claude/skills/app-builder/feature-building.md +53 -0
  232. package/template/.claude/skills/app-builder/project-detection.md +34 -0
  233. package/template/.claude/skills/app-builder/scaffolding.md +118 -0
  234. package/template/.claude/skills/app-builder/tech-stack.md +40 -0
  235. package/template/.claude/skills/app-builder/templates/SKILL.md +39 -0
  236. package/template/.claude/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
  237. package/template/.claude/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
  238. package/template/.claude/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
  239. package/template/.claude/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
  240. package/template/.claude/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
  241. package/template/.claude/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
  242. package/template/.claude/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
  243. package/template/.claude/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +122 -0
  244. package/template/.claude/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +122 -0
  245. package/template/.claude/skills/app-builder/templates/nextjs-static/TEMPLATE.md +169 -0
  246. package/template/.claude/skills/app-builder/templates/nuxt-app/TEMPLATE.md +134 -0
  247. package/template/.claude/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
  248. package/template/.claude/skills/app-builder/templates/react-native-app/TEMPLATE.md +119 -0
  249. package/template/.claude/skills/architecture/SKILL.md +55 -0
  250. package/template/.claude/skills/architecture/context-discovery.md +43 -0
  251. package/template/.claude/skills/architecture/examples.md +94 -0
  252. package/template/.claude/skills/architecture/pattern-selection.md +68 -0
  253. package/template/.claude/skills/architecture/patterns-reference.md +50 -0
  254. package/template/.claude/skills/architecture/trade-off-analysis.md +77 -0
  255. package/template/.claude/skills/bash-linux/SKILL.md +199 -0
  256. package/template/.claude/skills/behavioral-modes/SKILL.md +242 -0
  257. package/template/.claude/skills/brainstorm/SKILL.md +168 -0
  258. package/template/.claude/skills/browser-testing-with-devtools/SKILL.md +302 -0
  259. package/template/.claude/skills/changelog/SKILL.md +109 -0
  260. package/template/.claude/skills/check-for-updates/SKILL.md +117 -0
  261. package/template/.claude/skills/ci-cd-and-automation/SKILL.md +390 -0
  262. package/template/.claude/skills/code-review-and-quality/SKILL.md +392 -0
  263. package/template/.claude/skills/code-simplification/SKILL.md +331 -0
  264. package/template/.claude/skills/codebase-design/DEEPENING.md +24 -0
  265. package/template/.claude/skills/codebase-design/DESIGN-IT-TWICE.md +28 -0
  266. package/template/.claude/skills/codebase-design/SKILL.md +58 -0
  267. package/template/.claude/skills/commit/SKILL.md +63 -0
  268. package/template/.claude/skills/competitor-analysis/SKILL.md +66 -0
  269. package/template/.claude/skills/context-engineering/SKILL.md +290 -0
  270. package/template/.claude/skills/database-design/SKILL.md +52 -0
  271. package/template/.claude/skills/database-design/database-selection.md +43 -0
  272. package/template/.claude/skills/database-design/indexing.md +39 -0
  273. package/template/.claude/skills/database-design/migrations.md +48 -0
  274. package/template/.claude/skills/database-design/optimization.md +36 -0
  275. package/template/.claude/skills/database-design/orm-selection.md +30 -0
  276. package/template/.claude/skills/database-design/schema-design.md +56 -0
  277. package/template/.claude/skills/database-design/scripts/schema_validator.py +172 -0
  278. package/template/.claude/skills/debug/SKILL.md +131 -0
  279. package/template/.claude/skills/debugging-and-error-recovery/SKILL.md +298 -0
  280. package/template/.claude/skills/deploy/SKILL.md +91 -0
  281. package/template/.claude/skills/deployment-procedures/SKILL.md +241 -0
  282. package/template/.claude/skills/deprecation-and-migration/SKILL.md +206 -0
  283. package/template/.claude/skills/devflow/SKILL.md +89 -0
  284. package/template/.claude/skills/devflow-concept-intake/SKILL.md +150 -0
  285. package/template/.claude/skills/devflow-concept-intake/agents/openai.yaml +4 -0
  286. package/template/.claude/skills/devflow-concept-intake/references/adoption-proposal-template.md +60 -0
  287. package/template/.claude/skills/devflow-concept-intake/references/concept-report-template.md +47 -0
  288. package/template/.claude/skills/devflow-concept-intake/references/upstream-tracking-template.md +51 -0
  289. package/template/.claude/skills/devflow-wiki/SKILL.md +75 -0
  290. package/template/.claude/skills/diagnosing-bugs/SKILL.md +93 -0
  291. package/template/.claude/skills/documentation-and-adrs/SKILL.md +278 -0
  292. package/template/.claude/skills/domain-modeling/ADR-FORMAT.md +47 -0
  293. package/template/.claude/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  294. package/template/.claude/skills/domain-modeling/SKILL.md +74 -0
  295. package/template/.claude/skills/english-to-thai-translator/SKILL.md +125 -0
  296. package/template/.claude/skills/followup/SKILL.md +83 -0
  297. package/template/.claude/skills/frontend-ui-engineering/SKILL.md +326 -0
  298. package/template/.claude/skills/frontend-ui-engineering/accessibility-checklist.md +159 -0
  299. package/template/.claude/skills/git-workflow-and-versioning/SKILL.md +300 -0
  300. package/template/.claude/skills/goal/SKILL.md +148 -0
  301. package/template/.claude/skills/handoff/SKILL.md +46 -0
  302. package/template/.claude/skills/help/SKILL.md +253 -0
  303. package/template/.claude/skills/human-review-decisions/SKILL.md +74 -0
  304. package/template/.claude/skills/i18n-localization/SKILL.md +154 -0
  305. package/template/.claude/skills/i18n-localization/scripts/i18n_checker.py +241 -0
  306. package/template/.claude/skills/idea-refine/SKILL.md +178 -0
  307. package/template/.claude/skills/idea-refine/examples.md +238 -0
  308. package/template/.claude/skills/idea-refine/frameworks.md +99 -0
  309. package/template/.claude/skills/idea-refine/refinement-criteria.md +113 -0
  310. package/template/.claude/skills/idea-refine/scripts/idea-refine.sh +15 -0
  311. package/template/.claude/skills/incremental-implementation/SKILL.md +248 -0
  312. package/template/.claude/skills/insight/SKILL.md +131 -0
  313. package/template/.claude/skills/insight-capture/SKILL.md +84 -0
  314. package/template/.claude/skills/intelligent-routing/SKILL.md +176 -0
  315. package/template/.claude/skills/issue-triage/SKILL.md +115 -0
  316. package/template/.claude/skills/lint-and-validate/SKILL.md +45 -0
  317. package/template/.claude/skills/lint-and-validate/scripts/lint_runner.py +184 -0
  318. package/template/.claude/skills/lint-and-validate/scripts/type_coverage.py +173 -0
  319. package/template/.claude/skills/mcp-builder/SKILL.md +176 -0
  320. package/template/.claude/skills/md2html/SKILL.md +154 -0
  321. package/template/.claude/skills/md2html/components.md +505 -0
  322. package/template/.claude/skills/md2html/template.html +1152 -0
  323. package/template/.claude/skills/merge/SKILL.md +76 -0
  324. package/template/.claude/skills/mobile-design/SKILL.md +394 -0
  325. package/template/.claude/skills/mobile-design/decision-trees.md +516 -0
  326. package/template/.claude/skills/mobile-design/mobile-backend.md +491 -0
  327. package/template/.claude/skills/mobile-design/mobile-color-system.md +420 -0
  328. package/template/.claude/skills/mobile-design/mobile-debugging.md +122 -0
  329. package/template/.claude/skills/mobile-design/mobile-design-thinking.md +357 -0
  330. package/template/.claude/skills/mobile-design/mobile-navigation.md +458 -0
  331. package/template/.claude/skills/mobile-design/mobile-performance.md +767 -0
  332. package/template/.claude/skills/mobile-design/mobile-testing.md +356 -0
  333. package/template/.claude/skills/mobile-design/mobile-typography.md +433 -0
  334. package/template/.claude/skills/mobile-design/platform-android.md +666 -0
  335. package/template/.claude/skills/mobile-design/platform-ios.md +561 -0
  336. package/template/.claude/skills/mobile-design/scripts/mobile_audit.py +670 -0
  337. package/template/.claude/skills/mobile-design/touch-psychology.md +537 -0
  338. package/template/.claude/skills/nextjs-react-expert/1-async-eliminating-waterfalls.md +312 -0
  339. package/template/.claude/skills/nextjs-react-expert/2-bundle-bundle-size-optimization.md +240 -0
  340. package/template/.claude/skills/nextjs-react-expert/3-server-server-side-performance.md +490 -0
  341. package/template/.claude/skills/nextjs-react-expert/4-client-client-side-data-fetching.md +264 -0
  342. package/template/.claude/skills/nextjs-react-expert/5-rerender-re-render-optimization.md +581 -0
  343. package/template/.claude/skills/nextjs-react-expert/6-rendering-rendering-performance.md +432 -0
  344. package/template/.claude/skills/nextjs-react-expert/7-js-javascript-performance.md +684 -0
  345. package/template/.claude/skills/nextjs-react-expert/8-advanced-advanced-patterns.md +150 -0
  346. package/template/.claude/skills/nextjs-react-expert/SKILL.md +286 -0
  347. package/template/.claude/skills/nextjs-react-expert/scripts/convert_rules.py +222 -0
  348. package/template/.claude/skills/nextjs-react-expert/scripts/react_performance_checker.py +252 -0
  349. package/template/.claude/skills/nodejs-best-practices/SKILL.md +333 -0
  350. package/template/.claude/skills/obsidian-bases/SKILL.md +506 -0
  351. package/template/.claude/skills/obsidian-bases/references/FUNCTIONS_REFERENCE.md +173 -0
  352. package/template/.claude/skills/obsidian-cli/SKILL.md +115 -0
  353. package/template/.claude/skills/obsidian-clipper-template-creator/SKILL.md +73 -0
  354. package/template/.claude/skills/obsidian-clipper-template-creator/assets/clipping-template.json +51 -0
  355. package/template/.claude/skills/obsidian-clipper-template-creator/assets/recipe-template.json +48 -0
  356. package/template/.claude/skills/obsidian-clipper-template-creator/references/analysis-workflow.md +79 -0
  357. package/template/.claude/skills/obsidian-clipper-template-creator/references/bases-workflow.md +44 -0
  358. package/template/.claude/skills/obsidian-clipper-template-creator/references/filters.md +51 -0
  359. package/template/.claude/skills/obsidian-clipper-template-creator/references/json-schema.md +77 -0
  360. package/template/.claude/skills/obsidian-clipper-template-creator/references/logic.md +67 -0
  361. package/template/.claude/skills/obsidian-clipper-template-creator/references/variables.md +64 -0
  362. package/template/.claude/skills/obsidian-markdown/SKILL.md +205 -0
  363. package/template/.claude/skills/obsidian-markdown/references/CALLOUTS.md +58 -0
  364. package/template/.claude/skills/obsidian-markdown/references/EMBEDS.md +63 -0
  365. package/template/.claude/skills/obsidian-markdown/references/PROPERTIES.md +61 -0
  366. package/template/.claude/skills/package-json-generator/SKILL.md +60 -0
  367. package/template/.claude/skills/package-json-generator/scripts/generate.js +120 -0
  368. package/template/.claude/skills/package-json-generator/scripts/run.sh +19 -0
  369. package/template/.claude/skills/parallel-agents/SKILL.md +144 -0
  370. package/template/.claude/skills/performance-optimization/SKILL.md +299 -0
  371. package/template/.claude/skills/performance-optimization/performance-checklist.md +113 -0
  372. package/template/.claude/skills/planning-and-task-breakdown/SKILL.md +239 -0
  373. package/template/.claude/skills/powershell-windows/SKILL.md +167 -0
  374. package/template/.claude/skills/pr/SKILL.md +93 -0
  375. package/template/.claude/skills/pr-review/SKILL.md +143 -0
  376. package/template/.claude/skills/pr-review-analysis/SKILL.md +89 -0
  377. package/template/.claude/skills/prd/SKILL.md +127 -0
  378. package/template/.claude/skills/preview/SKILL.md +121 -0
  379. package/template/.claude/skills/preview-local-check/SKILL.md +59 -0
  380. package/template/.claude/skills/prompt-addons/SKILL.md +99 -0
  381. package/template/.claude/skills/prototype/SKILL.md +44 -0
  382. package/template/.claude/skills/prp-dev-fastapi/SKILL.md +114 -0
  383. package/template/.claude/skills/prp-dev-multiplatform/SKILL.md +36 -0
  384. package/template/.claude/skills/prp-dev-odoo/SKILL.md +71 -0
  385. package/template/.claude/skills/prp-dev-php/SKILL.md +63 -0
  386. package/template/.claude/skills/prp-sa-ba/SKILL.md +52 -0
  387. package/template/.claude/skills/python-patterns/SKILL.md +441 -0
  388. package/template/.claude/skills/red-team-tactics/SKILL.md +199 -0
  389. package/template/.claude/skills/release-git-operations/SKILL.md +97 -0
  390. package/template/.claude/skills/research/SKILL.md +143 -0
  391. package/template/.claude/skills/review/SKILL.md +55 -0
  392. package/template/.claude/skills/review-followup-routing/SKILL.md +98 -0
  393. package/template/.claude/skills/roadmap-strategy/SKILL.md +97 -0
  394. package/template/.claude/skills/security-and-hardening/SKILL.md +349 -0
  395. package/template/.claude/skills/security-and-hardening/security-checklist.md +134 -0
  396. package/template/.claude/skills/security-review/SKILL.md +166 -0
  397. package/template/.claude/skills/seo-fundamentals/SKILL.md +129 -0
  398. package/template/.claude/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
  399. package/template/.claude/skills/server-management/SKILL.md +161 -0
  400. package/template/.claude/skills/shipping-and-launch/SKILL.md +311 -0
  401. package/template/.claude/skills/silent-failure-audit/SKILL.md +73 -0
  402. package/template/.claude/skills/simplify/SKILL.md +79 -0
  403. package/template/.claude/skills/skill-development/SKILL.md +86 -0
  404. package/template/.claude/skills/spec-driven-development/SKILL.md +207 -0
  405. package/template/.claude/skills/spec-orchestration/SKILL.md +91 -0
  406. package/template/.claude/skills/specialist-agent-routing/SKILL.md +107 -0
  407. package/template/.claude/skills/tailwind-patterns/SKILL.md +269 -0
  408. package/template/.claude/skills/test/SKILL.md +82 -0
  409. package/template/.claude/skills/test-driven-development/SKILL.md +422 -0
  410. package/template/.claude/skills/test-driven-development/testing-patterns.md +236 -0
  411. package/template/.claude/skills/test-execution-and-coverage/SKILL.md +56 -0
  412. package/template/.claude/skills/type-design/SKILL.md +84 -0
  413. package/template/.claude/skills/ui-ux-pro-max/SKILL.md +75 -0
  414. package/template/.claude/skills/using-agent-skills/SKILL.md +171 -0
  415. package/template/.claude/skills/verification-orchestration/SKILL.md +68 -0
  416. package/template/.claude/skills/vulnerability-scanner/SKILL.md +276 -0
  417. package/template/.claude/skills/vulnerability-scanner/checklists.md +121 -0
  418. package/template/.claude/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
  419. package/template/.claude/skills/wiki/SKILL.md +149 -0
  420. package/template/.claude/skills/workflow-documentation-sync/SKILL.md +87 -0
  421. package/template/.claude/skills/writing-great-skills/SKILL.md +65 -0
  422. package/template/.nexus/nexus-devflow.json +44 -0
  423. package/template/AGENTS.md +58 -0
  424. package/template/CLAUDE.md +5 -0
  425. package/template/LICENSE +21 -0
  426. package/template/devflow/context/ai-interaction.md +34 -0
  427. package/template/devflow/context/coding-standards.md +19 -0
  428. package/template/devflow/context/current-stage.md +6 -0
  429. package/template/devflow/context/findings.md +13 -0
  430. package/template/devflow/context/project-overview.md +20 -0
  431. package/template/devflow/reference/running-id-contract.md +39 -0
@@ -0,0 +1,1152 @@
1
+ <!DOCTYPE html>
2
+ <html lang="{{LANG}}" data-theme="light" style="--rec-label: '{{REC_LABEL}}'">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta name="color-scheme" content="light dark">
7
+ <title>{{TITLE}}</title>
8
+ <link rel="preconnect" href="https://fonts.googleapis.com">
9
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
11
+ <style>
12
+ /* ============================================================
13
+ TOKENS
14
+ ============================================================ */
15
+ :root {
16
+ --bg: #FAFAF7;
17
+ --surface: #FFFFFF;
18
+ --surface-2: #F5F5F0;
19
+ --surface-3: #EFEEE8;
20
+ --text: #1A1A1A;
21
+ --text-muted: #4A4A45;
22
+ --text-subtle: #6B6B66;
23
+ --accent: #D97757;
24
+ --accent-hover: #C56843;
25
+ --accent-soft: #FBEEE6;
26
+ --accent-border: #F0D5C4;
27
+ --accent-strong: #A85533;
28
+ --border: #E5E4DC;
29
+ --border-strong: #CDCDC4;
30
+ --code-bg: #F5F2EC;
31
+ --code-text: #2A2A2A;
32
+ --info: #2563EB;
33
+ --info-soft: #EFF6FF;
34
+ --info-border: #BFDBFE;
35
+ --warn: #B45309;
36
+ --warn-soft: #FFFBEB;
37
+ --warn-border: #FDE68A;
38
+ --danger: #B91C1C;
39
+ --danger-soft: #FEF2F2;
40
+ --danger-border: #FECACA;
41
+ --success: #047857;
42
+ --success-soft: #ECFDF5;
43
+ --success-border: #A7F3D0;
44
+ --decision: #6D28D9;
45
+ --decision-soft: #F5F3FF;
46
+ --decision-border: #DDD6FE;
47
+ --shadow-sm: 0 1px 2px rgba(20, 14, 8, 0.04);
48
+ --shadow: 0 1px 2px rgba(20, 14, 8, 0.04), 0 4px 12px rgba(20, 14, 8, 0.06);
49
+ --shadow-lg: 0 8px 24px rgba(20, 14, 8, 0.10);
50
+ --radius: 12px;
51
+ --radius-sm: 8px;
52
+ --radius-lg: 16px;
53
+ --font-sans: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'PingFang SC', 'Microsoft YaHei', 'Noto Sans CJK SC', 'Noto Sans CJK JP', 'Noto Sans CJK KR', sans-serif;
54
+ --font-mono: 'JetBrains Mono', 'SF Mono', Menlo, Consolas, monospace;
55
+ --z-progress: 200;
56
+ --z-topbar: 100;
57
+ --z-drawer: 300;
58
+ --z-backdrop: 250;
59
+ }
60
+
61
+ [data-theme="dark"] {
62
+ --bg: #1A1714;
63
+ --surface: #221E1A;
64
+ --surface-2: #2A2520;
65
+ --surface-3: #322C26;
66
+ --text: #F5F0E8;
67
+ --text-muted: #C8C0B6;
68
+ --text-subtle: #9A938A;
69
+ --accent: #E89572;
70
+ --accent-hover: #F2A87F;
71
+ --accent-soft: #3A2A22;
72
+ --accent-border: #5A3D2E;
73
+ --accent-strong: #F5B493;
74
+ --border: #2E2924;
75
+ --border-strong: #463F38;
76
+ --code-bg: #1E1B17;
77
+ --code-text: #E8E2D8;
78
+ --info: #93C5FD;
79
+ --info-soft: #1E2A3D;
80
+ --info-border: #2A4365;
81
+ --warn: #FBBF24;
82
+ --warn-soft: #332817;
83
+ --warn-border: #5C4520;
84
+ --danger: #FCA5A5;
85
+ --danger-soft: #3A1F1F;
86
+ --danger-border: #5C2A2A;
87
+ --success: #6EE7B7;
88
+ --success-soft: #1A3329;
89
+ --success-border: #1F5C45;
90
+ --decision: #C4B5FD;
91
+ --decision-soft: #2A1F40;
92
+ --decision-border: #4A3870;
93
+ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.25);
94
+ --shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 4px 12px rgba(0, 0, 0, 0.35);
95
+ --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.45);
96
+ }
97
+
98
+ /* ============================================================
99
+ BASE
100
+ ============================================================ */
101
+ * { box-sizing: border-box; }
102
+ html { scroll-behavior: smooth; scroll-padding-top: 80px; }
103
+ body {
104
+ margin: 0;
105
+ font-family: var(--font-sans);
106
+ background: var(--bg);
107
+ color: var(--text);
108
+ line-height: 1.65;
109
+ font-size: 16px;
110
+ -webkit-font-smoothing: antialiased;
111
+ transition: background-color 0.2s, color 0.2s;
112
+ }
113
+ ::selection { background: var(--accent-soft); color: var(--accent-strong); }
114
+
115
+ /* Skip link */
116
+ .skip-link {
117
+ position: absolute;
118
+ top: -100px; left: 8px;
119
+ padding: 10px 16px;
120
+ background: var(--accent);
121
+ color: #fff;
122
+ text-decoration: none;
123
+ border-radius: var(--radius-sm);
124
+ font-weight: 500;
125
+ z-index: 1000;
126
+ transition: top 0.15s;
127
+ }
128
+ .skip-link:focus { top: 8px; }
129
+
130
+ /* SVG sprite container (hidden) */
131
+ .icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
132
+ .icon { display: inline-block; flex-shrink: 0; vertical-align: middle; stroke: currentColor; fill: none; }
133
+
134
+ /* Scroll progress bar */
135
+ .scroll-progress {
136
+ position: fixed;
137
+ top: 0; left: 0;
138
+ height: 2px;
139
+ width: 0;
140
+ background: var(--accent);
141
+ z-index: var(--z-progress);
142
+ transition: width 0.05s linear;
143
+ }
144
+
145
+ /* ============================================================
146
+ TOPBAR
147
+ ============================================================ */
148
+ .topbar {
149
+ position: sticky;
150
+ top: 0;
151
+ z-index: var(--z-topbar);
152
+ background: rgba(250, 250, 247, 0.85);
153
+ backdrop-filter: saturate(180%) blur(12px);
154
+ -webkit-backdrop-filter: saturate(180%) blur(12px);
155
+ border-bottom: 1px solid var(--border);
156
+ }
157
+ [data-theme="dark"] .topbar { background: rgba(26, 23, 20, 0.85); }
158
+ .topbar-inner {
159
+ max-width: 1280px;
160
+ margin: 0 auto;
161
+ padding: 10px 20px;
162
+ display: flex;
163
+ align-items: center;
164
+ justify-content: space-between;
165
+ gap: 12px;
166
+ }
167
+ .brand {
168
+ display: flex;
169
+ align-items: center;
170
+ gap: 10px;
171
+ font-weight: 600;
172
+ color: var(--text);
173
+ font-size: 14px;
174
+ }
175
+ .brand-dot {
176
+ width: 10px; height: 10px; border-radius: 50%;
177
+ background: var(--accent);
178
+ box-shadow: 0 0 0 4px var(--accent-soft);
179
+ animation: brand-pulse 2.8s ease-in-out infinite;
180
+ }
181
+ @keyframes brand-pulse {
182
+ 0%, 100% { box-shadow: 0 0 0 4px var(--accent-soft); }
183
+ 50% { box-shadow: 0 0 0 7px transparent; }
184
+ }
185
+ .topbar-actions { display: flex; gap: 6px; align-items: center; }
186
+ .icon-btn {
187
+ width: 40px; height: 40px;
188
+ display: inline-flex; align-items: center; justify-content: center;
189
+ border: 1px solid var(--border);
190
+ background: var(--surface);
191
+ color: var(--text-muted);
192
+ border-radius: var(--radius-sm);
193
+ cursor: pointer;
194
+ transition: color 0.15s, border-color 0.15s, background-color 0.15s;
195
+ padding: 0;
196
+ }
197
+ .icon-btn .icon { width: 18px; height: 18px; stroke-width: 2; }
198
+ .icon-btn[hidden] { display: none; }
199
+
200
+ /* ============================================================
201
+ LAYOUT
202
+ ============================================================ */
203
+ .layout {
204
+ max-width: 1280px;
205
+ margin: 0 auto;
206
+ display: grid;
207
+ grid-template-columns: 260px 1fr;
208
+ gap: 48px;
209
+ padding: 32px 24px 96px;
210
+ }
211
+ .content { min-width: 0; }
212
+
213
+ /* ============================================================
214
+ TOC (desktop + mobile drawer)
215
+ ============================================================ */
216
+ .toc {
217
+ position: sticky;
218
+ top: 80px;
219
+ align-self: start;
220
+ max-height: calc(100vh - 100px);
221
+ overflow-y: auto;
222
+ padding-right: 8px;
223
+ }
224
+ .toc::-webkit-scrollbar { width: 6px; }
225
+ .toc::-webkit-scrollbar-track { background: transparent; }
226
+ .toc::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }
227
+ .toc-head {
228
+ display: flex; align-items: center; justify-content: space-between;
229
+ padding: 0 12px 12px;
230
+ }
231
+ .toc-title {
232
+ font-size: 11px;
233
+ font-weight: 600;
234
+ text-transform: uppercase;
235
+ letter-spacing: 0.06em;
236
+ color: var(--text-subtle);
237
+ margin: 0;
238
+ }
239
+ .toc-close { display: none; }
240
+ .toc-nav { display: flex; flex-direction: column; gap: 2px; }
241
+ .toc-nav a {
242
+ display: flex; align-items: center;
243
+ min-height: 36px;
244
+ padding: 8px 14px;
245
+ color: var(--text-muted);
246
+ text-decoration: none;
247
+ font-size: 13.5px;
248
+ border-left: 2px solid transparent;
249
+ border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
250
+ transition: color 0.15s, background-color 0.15s, border-color 0.15s;
251
+ line-height: 1.4;
252
+ }
253
+ .toc-nav a.active {
254
+ color: var(--accent);
255
+ border-left-color: var(--accent);
256
+ background: var(--accent-soft);
257
+ font-weight: 500;
258
+ }
259
+ .toc-nav a.lvl-3 { padding-left: 26px; font-size: 12.5px; }
260
+ .toc-backdrop {
261
+ display: none;
262
+ position: fixed; inset: 0;
263
+ background: rgba(0, 0, 0, 0.45);
264
+ z-index: var(--z-backdrop);
265
+ opacity: 0;
266
+ transition: opacity 0.2s;
267
+ }
268
+
269
+ /* ============================================================
270
+ DOC HEADER
271
+ ============================================================ */
272
+ .doc-header {
273
+ margin-bottom: 40px;
274
+ padding-bottom: 24px;
275
+ border-bottom: 1px solid var(--border);
276
+ }
277
+ .doc-eyebrow {
278
+ display: inline-flex; align-items: center;
279
+ gap: 6px;
280
+ padding: 4px 10px;
281
+ background: var(--accent-soft);
282
+ color: var(--accent-strong);
283
+ border: 1px solid var(--accent-border);
284
+ border-radius: 999px;
285
+ font-size: 12px;
286
+ font-weight: 500;
287
+ letter-spacing: 0.04em;
288
+ margin-bottom: 16px;
289
+ }
290
+ .doc-title {
291
+ font-size: clamp(28px, 3vw + 16px, 40px);
292
+ font-weight: 700;
293
+ line-height: 1.15;
294
+ letter-spacing: -0.02em;
295
+ margin: 0 0 12px;
296
+ color: var(--text);
297
+ text-wrap: balance;
298
+ }
299
+ .doc-subtitle {
300
+ font-size: clamp(15px, 0.6vw + 13px, 18px);
301
+ color: var(--text-muted);
302
+ line-height: 1.55;
303
+ margin: 0 0 20px;
304
+ max-width: 75ch;
305
+ text-wrap: pretty;
306
+ }
307
+ .doc-meta {
308
+ display: flex;
309
+ flex-wrap: wrap;
310
+ gap: 16px;
311
+ font-size: 13px;
312
+ color: var(--text-subtle);
313
+ }
314
+ .doc-meta-item { display: inline-flex; align-items: center; gap: 6px; }
315
+ .doc-meta .icon { width: 14px; height: 14px; stroke-width: 2; }
316
+
317
+ /* ============================================================
318
+ CONTENT (typography)
319
+ ============================================================ */
320
+ .content h1, .content h2, .content h3, .content h4 {
321
+ color: var(--text);
322
+ line-height: 1.3;
323
+ letter-spacing: -0.01em;
324
+ scroll-margin-top: 80px;
325
+ text-wrap: balance;
326
+ }
327
+ .content h2 {
328
+ font-size: 26px;
329
+ font-weight: 600;
330
+ margin: 56px 0 16px;
331
+ padding-top: 8px;
332
+ position: relative;
333
+ }
334
+ .content h3 {
335
+ font-size: 19px;
336
+ font-weight: 600;
337
+ margin: 36px 0 12px;
338
+ position: relative;
339
+ }
340
+ .content h4 {
341
+ font-size: 13px;
342
+ font-weight: 600;
343
+ margin: 24px 0 8px;
344
+ color: var(--text-muted);
345
+ text-transform: uppercase;
346
+ letter-spacing: 0.06em;
347
+ }
348
+ .content > p,
349
+ .content > ul,
350
+ .content > ol,
351
+ .content > blockquote { max-width: 75ch; }
352
+ .content p { margin: 0 0 16px; text-wrap: pretty; overflow-wrap: anywhere; }
353
+ .content a { color: var(--accent); text-decoration: none; border-bottom: 1px solid var(--accent-border); }
354
+ .content ul, .content ol { padding-left: 24px; margin: 0 0 16px; }
355
+ .content li { margin: 4px 0; }
356
+ .content strong { color: var(--text); font-weight: 600; }
357
+ .content em { color: var(--text-muted); }
358
+ .content hr { border: none; border-top: 1px solid var(--border); margin: 40px 0; }
359
+
360
+ /* Anchor links injected by JS on h2/h3 with id */
361
+ .anchor {
362
+ display: inline-flex; align-items: center; justify-content: center;
363
+ width: 24px; height: 24px;
364
+ margin-left: 6px;
365
+ color: var(--text-subtle);
366
+ opacity: 0;
367
+ transform: translateY(-1px);
368
+ transition: opacity 0.15s, color 0.15s;
369
+ border-bottom: none !important;
370
+ border-radius: var(--radius-sm);
371
+ }
372
+ .anchor .icon { width: 14px; height: 14px; stroke-width: 2; }
373
+
374
+ /* Images */
375
+ .content img {
376
+ max-width: 100%;
377
+ height: auto;
378
+ border-radius: var(--radius);
379
+ border: 1px solid var(--border);
380
+ margin: 20px 0;
381
+ display: block;
382
+ }
383
+ .content figure { margin: 20px 0; }
384
+ .content figure img { margin: 0; }
385
+ .content figcaption {
386
+ font-size: 13px;
387
+ color: var(--text-subtle);
388
+ margin-top: 8px;
389
+ text-align: center;
390
+ }
391
+
392
+ /* Task lists (- [ ] / - [x]) */
393
+ .content .task-list-item { list-style: none; margin-left: -22px; }
394
+ .content .task-list-item-checkbox {
395
+ margin-right: 8px;
396
+ vertical-align: -2px;
397
+ accent-color: var(--accent);
398
+ }
399
+
400
+ /* Footnotes */
401
+ .content .footnote-ref a,
402
+ .content sup a {
403
+ font-size: 0.75em;
404
+ vertical-align: super;
405
+ border-bottom: none;
406
+ padding: 0 2px;
407
+ }
408
+ .content .footnotes {
409
+ margin-top: 56px;
410
+ padding-top: 20px;
411
+ border-top: 1px solid var(--border);
412
+ font-size: 14px;
413
+ color: var(--text-muted);
414
+ }
415
+
416
+ /* ============================================================
417
+ CODE
418
+ ============================================================ */
419
+ .content code {
420
+ font-family: var(--font-mono);
421
+ background: var(--code-bg);
422
+ padding: 2px 6px;
423
+ border-radius: 4px;
424
+ font-size: 0.88em;
425
+ color: var(--code-text);
426
+ border: 1px solid var(--border);
427
+ overflow-wrap: anywhere;
428
+ }
429
+ .content pre {
430
+ background: var(--code-bg);
431
+ border: 1px solid var(--border);
432
+ border-radius: var(--radius);
433
+ padding: 16px 20px;
434
+ overflow-x: auto;
435
+ font-size: 13.5px;
436
+ line-height: 1.6;
437
+ margin: 16px 0;
438
+ position: relative;
439
+ }
440
+ .content pre code {
441
+ background: none; padding: 0; border: none;
442
+ color: var(--code-text);
443
+ font-size: inherit;
444
+ }
445
+ .copy-btn {
446
+ position: absolute;
447
+ top: 8px; right: 8px;
448
+ width: 32px; height: 32px;
449
+ display: inline-flex; align-items: center; justify-content: center;
450
+ background: var(--surface);
451
+ border: 1px solid var(--border);
452
+ border-radius: var(--radius-sm);
453
+ cursor: pointer;
454
+ color: var(--text-subtle);
455
+ opacity: 0;
456
+ transition: opacity 0.15s, color 0.15s, border-color 0.15s;
457
+ padding: 0;
458
+ }
459
+ .copy-btn .icon { width: 14px; height: 14px; stroke-width: 2; }
460
+ .copy-btn.copied { color: var(--success); border-color: var(--success-border); opacity: 1; }
461
+
462
+ /* ============================================================
463
+ TIMELINE / STEPS
464
+ ============================================================ */
465
+ .timeline {
466
+ display: flex;
467
+ flex-direction: column;
468
+ gap: 8px;
469
+ margin: 24px 0;
470
+ position: relative;
471
+ }
472
+ .timeline::before {
473
+ content: "";
474
+ position: absolute;
475
+ left: 19px;
476
+ top: 20px;
477
+ bottom: 20px;
478
+ width: 2px;
479
+ background: linear-gradient(180deg, var(--accent-border), var(--border));
480
+ }
481
+ .step {
482
+ display: grid;
483
+ grid-template-columns: 40px 1fr;
484
+ gap: 16px;
485
+ align-items: start;
486
+ padding: 16px 4px;
487
+ position: relative;
488
+ border-radius: var(--radius);
489
+ transition: background-color 0.15s;
490
+ }
491
+ .step-num {
492
+ width: 40px; height: 40px;
493
+ display: inline-flex; align-items: center; justify-content: center;
494
+ background: var(--surface);
495
+ border: 2px solid var(--accent);
496
+ color: var(--accent);
497
+ border-radius: 50%;
498
+ font-weight: 600;
499
+ font-size: 14px;
500
+ flex-shrink: 0;
501
+ box-shadow: var(--shadow-sm);
502
+ position: relative;
503
+ z-index: 1;
504
+ transition: background-color 0.15s, color 0.15s, transform 0.15s;
505
+ }
506
+ .step.done .step-num { background: var(--accent); color: #fff; }
507
+ .step-body { padding-top: 6px; min-width: 0; }
508
+ .step-body h3 {
509
+ margin: 0 0 6px;
510
+ font-size: 16px;
511
+ font-weight: 600;
512
+ }
513
+ .step-body p { margin: 0 0 8px; color: var(--text-muted); font-size: 14.5px; max-width: 75ch; }
514
+ .step-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
515
+ .tag {
516
+ display: inline-block;
517
+ padding: 2px 8px;
518
+ background: var(--surface-2);
519
+ border: 1px solid var(--border);
520
+ border-radius: 999px;
521
+ font-size: 11.5px;
522
+ color: var(--text-muted);
523
+ font-family: var(--font-mono);
524
+ }
525
+
526
+ /* ============================================================
527
+ CALLOUTS
528
+ ============================================================ */
529
+ .callout {
530
+ display: grid;
531
+ grid-template-columns: 24px 1fr;
532
+ gap: 14px;
533
+ padding: 14px 18px;
534
+ border-radius: var(--radius);
535
+ border: 1px solid;
536
+ margin: 20px 0;
537
+ font-size: 14.5px;
538
+ line-height: 1.6;
539
+ max-width: 75ch;
540
+ }
541
+ .callout-icon { width: 20px; height: 20px; margin-top: 2px; stroke-width: 2; }
542
+ .callout-body { min-width: 0; }
543
+ .callout-title { font-weight: 600; margin: 0 0 4px; font-size: 14px; }
544
+ .callout-body p:last-child { margin-bottom: 0; }
545
+ .callout-body code { background: rgba(0,0,0,0.04); }
546
+ [data-theme="dark"] .callout-body code { background: rgba(255,255,255,0.06); }
547
+
548
+ .callout-info { background: var(--info-soft); border-color: var(--info-border); color: var(--text); }
549
+ .callout-info .callout-title, .callout-info .callout-icon { color: var(--info); }
550
+ .callout-warn { background: var(--warn-soft); border-color: var(--warn-border); color: var(--text); }
551
+ .callout-warn .callout-title, .callout-warn .callout-icon { color: var(--warn); }
552
+ .callout-danger { background: var(--danger-soft); border-color: var(--danger-border); color: var(--text); }
553
+ .callout-danger .callout-title, .callout-danger .callout-icon { color: var(--danger); }
554
+ .callout-success { background: var(--success-soft); border-color: var(--success-border); color: var(--text); }
555
+ .callout-success .callout-title, .callout-success .callout-icon { color: var(--success); }
556
+ .callout-decision { background: var(--decision-soft); border-color: var(--decision-border); color: var(--text); }
557
+ .callout-decision .callout-title, .callout-decision .callout-icon { color: var(--decision); }
558
+ .callout-tip { background: var(--accent-soft); border-color: var(--accent-border); color: var(--text); }
559
+ .callout-tip .callout-title, .callout-tip .callout-icon { color: var(--accent-strong); }
560
+
561
+ /* ============================================================
562
+ KEY-POINT HIGHLIGHT
563
+ ============================================================ */
564
+ .highlight {
565
+ background: linear-gradient(135deg, var(--accent-soft), var(--surface-2));
566
+ border-left: 4px solid var(--accent);
567
+ padding: 18px 22px;
568
+ border-radius: 0 var(--radius) var(--radius) 0;
569
+ margin: 24px 0;
570
+ font-size: 16px;
571
+ line-height: 1.65;
572
+ max-width: 75ch;
573
+ }
574
+ .highlight-label {
575
+ display: inline-block;
576
+ font-size: 11px;
577
+ font-weight: 600;
578
+ text-transform: uppercase;
579
+ letter-spacing: 0.08em;
580
+ color: var(--accent-strong);
581
+ margin-bottom: 6px;
582
+ }
583
+
584
+ /* ============================================================
585
+ MERMAID
586
+ ============================================================ */
587
+ .diagram {
588
+ background: var(--surface);
589
+ border: 1px solid var(--border);
590
+ border-radius: var(--radius);
591
+ padding: 24px;
592
+ margin: 24px 0;
593
+ box-shadow: var(--shadow-sm);
594
+ overflow-x: auto;
595
+ }
596
+ .diagram-caption {
597
+ margin-top: 12px;
598
+ padding-top: 12px;
599
+ border-top: 1px dashed var(--border);
600
+ font-size: 13px;
601
+ color: var(--text-subtle);
602
+ text-align: center;
603
+ }
604
+ .mermaid { text-align: center; min-height: 80px; }
605
+ .mermaid svg { max-width: 100%; height: auto; }
606
+ .mermaid:not([data-processed]) {
607
+ opacity: 0.4;
608
+ font-family: var(--font-mono);
609
+ font-size: 12px;
610
+ color: var(--text-subtle);
611
+ white-space: pre-wrap;
612
+ text-align: left;
613
+ }
614
+
615
+ /* ============================================================
616
+ PROS / CONS
617
+ ============================================================ */
618
+ .proscons {
619
+ display: grid;
620
+ grid-template-columns: 1fr 1fr;
621
+ gap: 16px;
622
+ margin: 24px 0;
623
+ }
624
+ .proscons-col {
625
+ padding: 16px 20px;
626
+ border-radius: var(--radius);
627
+ border: 1px solid;
628
+ }
629
+ .proscons-col h4 {
630
+ margin: 0 0 12px;
631
+ font-size: 13px;
632
+ text-transform: uppercase;
633
+ letter-spacing: 0.06em;
634
+ display: flex; align-items: center; gap: 8px;
635
+ }
636
+ .proscons-col ul { margin: 0; padding-left: 18px; }
637
+ .proscons-col li { margin: 6px 0; }
638
+ .pros { background: var(--success-soft); border-color: var(--success-border); }
639
+ .pros h4 { color: var(--success); }
640
+ .cons { background: var(--danger-soft); border-color: var(--danger-border); }
641
+ .cons h4 { color: var(--danger); }
642
+
643
+ /* ============================================================
644
+ COMPARISON CARDS
645
+ ============================================================ */
646
+ .compare {
647
+ display: grid;
648
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
649
+ gap: 14px;
650
+ margin: 24px 0;
651
+ }
652
+ .compare-card {
653
+ padding: 18px;
654
+ background: var(--surface);
655
+ border: 1px solid var(--border);
656
+ border-radius: var(--radius);
657
+ transition: border-color 0.18s, box-shadow 0.18s;
658
+ position: relative;
659
+ }
660
+ .compare-card.recommended { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
661
+ .compare-card.recommended::before {
662
+ content: var(--rec-label, "★ Recommended");
663
+ position: absolute; top: -10px; right: 14px;
664
+ background: var(--accent); color: #fff;
665
+ padding: 2px 10px; border-radius: 999px;
666
+ font-size: 11px; font-weight: 600;
667
+ }
668
+ .compare-card h4 { margin: 0 0 8px; font-size: 15px; color: var(--text); text-transform: none; letter-spacing: normal; }
669
+ .compare-card p { margin: 0; color: var(--text-muted); font-size: 14px; }
670
+
671
+ /* ============================================================
672
+ COLLAPSIBLE
673
+ ============================================================ */
674
+ details.collapsible {
675
+ border: 1px solid var(--border);
676
+ border-radius: var(--radius);
677
+ margin: 16px 0;
678
+ background: var(--surface);
679
+ overflow: hidden;
680
+ }
681
+ details.collapsible[open] { box-shadow: var(--shadow-sm); }
682
+ details.collapsible > summary {
683
+ cursor: pointer;
684
+ padding: 14px 18px;
685
+ font-weight: 500;
686
+ color: var(--text);
687
+ list-style: none;
688
+ display: flex; align-items: center; gap: 10px;
689
+ user-select: none;
690
+ transition: background 0.15s;
691
+ min-height: 44px;
692
+ }
693
+ details.collapsible > summary::-webkit-details-marker { display: none; }
694
+ details.collapsible > summary::before {
695
+ content: "›";
696
+ display: inline-block;
697
+ transition: transform 0.18s;
698
+ color: var(--accent);
699
+ font-size: 18px;
700
+ font-weight: 700;
701
+ }
702
+ details.collapsible[open] > summary::before { transform: rotate(90deg); }
703
+ .collapsible-body { padding: 4px 18px 18px; border-top: 1px solid var(--border); }
704
+ .collapsible-body > *:first-child { margin-top: 12px; }
705
+
706
+ /* ============================================================
707
+ TABLES (wrapped via .table-wrap or naturally responsive)
708
+ ============================================================ */
709
+ .table-wrap {
710
+ overflow-x: auto;
711
+ margin: 20px 0;
712
+ border-radius: var(--radius);
713
+ border: 1px solid var(--border);
714
+ max-width: 100%;
715
+ }
716
+ .content table {
717
+ width: 100%;
718
+ border-collapse: collapse;
719
+ font-size: 14px;
720
+ background: var(--surface);
721
+ margin: 0;
722
+ }
723
+ /* Standalone tables (not inside .table-wrap) keep visual border */
724
+ .content > table {
725
+ border: 1px solid var(--border);
726
+ border-radius: var(--radius);
727
+ overflow: hidden;
728
+ margin: 20px 0;
729
+ display: block;
730
+ overflow-x: auto;
731
+ }
732
+ .content th {
733
+ background: var(--surface-2);
734
+ color: var(--text);
735
+ font-weight: 600;
736
+ text-align: left;
737
+ padding: 12px 14px;
738
+ border-bottom: 1px solid var(--border);
739
+ font-size: 13px;
740
+ text-transform: uppercase;
741
+ letter-spacing: 0.04em;
742
+ white-space: nowrap;
743
+ }
744
+ .content td {
745
+ padding: 12px 14px;
746
+ border-bottom: 1px solid var(--border);
747
+ color: var(--text-muted);
748
+ vertical-align: top;
749
+ }
750
+ .content tr:last-child td { border-bottom: none; }
751
+
752
+ /* ============================================================
753
+ BLOCKQUOTE
754
+ ============================================================ */
755
+ .content blockquote {
756
+ margin: 20px 0;
757
+ padding: 4px 20px;
758
+ border-left: 3px solid var(--accent-border);
759
+ color: var(--text-muted);
760
+ font-style: italic;
761
+ }
762
+
763
+ /* ============================================================
764
+ FOOTER
765
+ ============================================================ */
766
+ .doc-footer {
767
+ margin-top: 80px;
768
+ padding-top: 24px;
769
+ border-top: 1px solid var(--border);
770
+ font-size: 13px;
771
+ color: var(--text-subtle);
772
+ display: flex;
773
+ justify-content: space-between;
774
+ flex-wrap: wrap;
775
+ gap: 12px;
776
+ }
777
+ .doc-footer a { color: var(--accent); text-decoration: none; }
778
+
779
+ /* ============================================================
780
+ FOCUS-VISIBLE (a11y)
781
+ ============================================================ */
782
+ *:focus { outline: none; }
783
+ *:focus-visible {
784
+ outline: 2px solid var(--accent);
785
+ outline-offset: 3px;
786
+ border-radius: var(--radius-sm);
787
+ }
788
+ .toc-nav a:focus-visible { outline-offset: -2px; }
789
+ .icon-btn:focus-visible { outline-offset: 2px; }
790
+ .anchor:focus-visible { opacity: 1; outline-offset: 2px; }
791
+ details.collapsible > summary:focus-visible { outline-offset: -2px; }
792
+
793
+ /* ============================================================
794
+ HOVER (only on hover-capable devices to avoid sticky-tap on mobile)
795
+ ============================================================ */
796
+ @media (hover: hover) {
797
+ .icon-btn:hover { color: var(--accent); border-color: var(--accent-border); background: var(--accent-soft); }
798
+ .toc-nav a:hover { color: var(--accent); background: var(--accent-soft); }
799
+ .content a:hover { color: var(--accent-hover); border-bottom-color: var(--accent); }
800
+ .compare-card:hover { border-color: var(--accent-border); box-shadow: var(--shadow); }
801
+ .compare-card.recommended:hover { border-color: var(--accent); }
802
+ .content tr:hover td { background: var(--surface-2); }
803
+ details.collapsible > summary:hover { background: var(--surface-2); }
804
+ .step:hover { background: var(--surface-2); }
805
+ .step:hover .step-num { transform: scale(1.05); }
806
+ .anchor:hover { color: var(--accent); }
807
+ .content h2:hover .anchor,
808
+ .content h3:hover .anchor { opacity: 1; }
809
+ .copy-btn:hover { color: var(--accent); border-color: var(--accent-border); }
810
+ .content pre:hover .copy-btn { opacity: 1; }
811
+ }
812
+ /* On touch devices, copy-btn is always visible at low opacity */
813
+ @media (hover: none) {
814
+ .copy-btn { opacity: 0.6; }
815
+ .anchor { opacity: 0.4; }
816
+ }
817
+
818
+ /* ============================================================
819
+ MOBILE (≤900px) — TOC becomes off-canvas drawer
820
+ ============================================================ */
821
+ @media (max-width: 900px) {
822
+ .layout {
823
+ grid-template-columns: 1fr;
824
+ gap: 16px;
825
+ padding: 20px 16px 80px;
826
+ }
827
+ .topbar-inner { padding: 8px 12px; }
828
+ .doc-header { margin-bottom: 28px; padding-bottom: 20px; }
829
+
830
+ .toc-mobile-trigger { display: inline-flex !important; }
831
+
832
+ .toc {
833
+ position: fixed;
834
+ top: 0; left: 0;
835
+ width: min(300px, 82vw);
836
+ height: 100dvh;
837
+ max-height: 100dvh;
838
+ background: var(--surface);
839
+ z-index: var(--z-drawer);
840
+ padding: 16px 8px 24px 16px;
841
+ box-shadow: var(--shadow-lg);
842
+ transform: translateX(-105%);
843
+ transition: transform 0.25s ease;
844
+ }
845
+ .toc-head { padding: 4px 4px 12px 8px; }
846
+ .toc-close {
847
+ display: inline-flex !important;
848
+ width: 36px; height: 36px;
849
+ align-items: center; justify-content: center;
850
+ background: transparent;
851
+ border: 1px solid transparent;
852
+ border-radius: var(--radius-sm);
853
+ color: var(--text-muted);
854
+ cursor: pointer;
855
+ padding: 0;
856
+ }
857
+ .toc-close .icon { width: 18px; height: 18px; stroke-width: 2; }
858
+ body.toc-open .toc { transform: translateX(0); }
859
+ body.toc-open .toc-backdrop {
860
+ display: block;
861
+ opacity: 1;
862
+ }
863
+ .toc-backdrop {
864
+ display: block;
865
+ opacity: 0;
866
+ pointer-events: none;
867
+ }
868
+ body.toc-open .toc-backdrop { pointer-events: auto; }
869
+ body.toc-open { overflow: hidden; }
870
+ }
871
+ @media (min-width: 901px) {
872
+ .toc-mobile-trigger { display: none !important; }
873
+ }
874
+
875
+ /* ============================================================
876
+ REDUCED MOTION (a11y)
877
+ ============================================================ */
878
+ @media (prefers-reduced-motion: reduce) {
879
+ *, *::before, *::after {
880
+ animation-duration: 0.01ms !important;
881
+ animation-iteration-count: 1 !important;
882
+ transition-duration: 0.01ms !important;
883
+ scroll-behavior: auto !important;
884
+ }
885
+ html { scroll-behavior: auto; }
886
+ .brand-dot { animation: none; box-shadow: 0 0 0 4px var(--accent-soft); }
887
+ }
888
+
889
+ /* ============================================================
890
+ PRINT
891
+ ============================================================ */
892
+ @media print {
893
+ .topbar, .toc, .toc-backdrop, .icon-btn, .copy-btn, .anchor, .scroll-progress { display: none !important; }
894
+ .layout { grid-template-columns: 1fr; padding: 0; max-width: 100%; }
895
+ body { background: #fff; color: #000; }
896
+ a { color: #000; }
897
+ .content pre, .callout, .compare-card, .step, .diagram { break-inside: avoid; }
898
+ .doc-footer { break-before: avoid; }
899
+ }
900
+ </style>
901
+ </head>
902
+ <body>
903
+ <!-- Skip link for keyboard users -->
904
+ <a href="#main" class="skip-link">{{SKIP_LINK_LABEL}}</a>
905
+
906
+ <!-- Scroll progress -->
907
+ <div class="scroll-progress" id="scroll-progress" aria-hidden="true"></div>
908
+
909
+ <!-- SVG icon sprite (Lucide-style) -->
910
+ <svg class="icon-sprite" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
911
+ <symbol id="i-info" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></symbol>
912
+ <symbol id="i-warn" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></symbol>
913
+ <symbol id="i-danger" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><line x1="4.93" y1="4.93" x2="19.07" y2="19.07"/></symbol>
914
+ <symbol id="i-success" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><polyline points="22 4 12 14.01 9 11.01"/></symbol>
915
+ <symbol id="i-decision" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/></symbol>
916
+ <symbol id="i-tip" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M15.09 14a5 5 0 1 0-6.18 0 4 4 0 0 1 1.59 2h2.99a4 4 0 0 1 1.6-2Z"/></symbol>
917
+ <symbol id="i-lock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></symbol>
918
+ <symbol id="i-printer" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/></symbol>
919
+ <symbol id="i-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/></symbol>
920
+ <symbol id="i-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></symbol>
921
+ <symbol id="i-menu" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="18" y2="18"/></symbol>
922
+ <symbol id="i-x" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></symbol>
923
+ <symbol id="i-file" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/></symbol>
924
+ <symbol id="i-calendar" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></symbol>
925
+ <symbol id="i-clock" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></symbol>
926
+ <symbol id="i-copy" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></symbol>
927
+ <symbol id="i-check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></symbol>
928
+ <symbol id="i-link" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></symbol>
929
+ </svg>
930
+
931
+ <!-- Topbar -->
932
+ <header class="topbar">
933
+ <div class="topbar-inner">
934
+ <div class="brand">
935
+ <button class="icon-btn toc-mobile-trigger" id="toc-toggle" onclick="openToc()" aria-label="{{TOC_TITLE}}" title="{{TOC_TITLE}}">
936
+ <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-menu"/></svg>
937
+ </button>
938
+ <span class="brand-dot" aria-hidden="true"></span>
939
+ <span>{{BRAND_LABEL}}</span>
940
+ </div>
941
+ <div class="topbar-actions">
942
+ <button class="icon-btn" onclick="window.print()" title="{{PRINT_TOOLTIP}}" aria-label="{{PRINT_TOOLTIP}}">
943
+ <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-printer"/></svg>
944
+ </button>
945
+ <button class="icon-btn" id="theme-toggle" onclick="toggleTheme()" title="{{THEME_TOOLTIP}}" aria-label="{{THEME_TOOLTIP}}">
946
+ <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use id="theme-icon-use" href="#i-moon"/></svg>
947
+ </button>
948
+ </div>
949
+ </div>
950
+ </header>
951
+
952
+ <!-- TOC drawer backdrop (mobile) -->
953
+ <div class="toc-backdrop" onclick="closeToc()" aria-hidden="true"></div>
954
+
955
+ <div class="layout">
956
+ <aside class="toc" id="toc" aria-label="{{TOC_TITLE}}">
957
+ <div class="toc-head">
958
+ <p class="toc-title">{{TOC_TITLE}}</p>
959
+ <button class="toc-close" onclick="closeToc()" aria-label="{{CLOSE_LABEL}}">
960
+ <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-x"/></svg>
961
+ </button>
962
+ </div>
963
+ <nav class="toc-nav" id="toc-nav">
964
+ <!-- TOC_ENTRIES -->
965
+ </nav>
966
+ </aside>
967
+
968
+ <main class="content" id="main">
969
+ <header class="doc-header">
970
+ <span class="doc-eyebrow">{{DOC_TYPE}}</span>
971
+ <h1 class="doc-title">{{TITLE}}</h1>
972
+ <p class="doc-subtitle">{{SUBTITLE}}</p>
973
+ <div class="doc-meta">
974
+ <span class="doc-meta-item">
975
+ <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-file"/></svg>
976
+ {{SOURCE_FILE}}
977
+ </span>
978
+ <span class="doc-meta-item">
979
+ <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-calendar"/></svg>
980
+ {{DATE}}
981
+ </span>
982
+ <span class="doc-meta-item">
983
+ <svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-clock"/></svg>
984
+ {{READ_TIME}}
985
+ </span>
986
+ </div>
987
+ </header>
988
+
989
+ <!-- CONTENT_START -->
990
+
991
+ <!-- Inject components here. See components.md for the catalog. -->
992
+
993
+ <!-- CONTENT_END -->
994
+
995
+ <footer class="doc-footer">
996
+ <span>Generated by <a href="#">md2html</a></span>
997
+ <span>{{FOOTER_NOTE}}</span>
998
+ </footer>
999
+ </main>
1000
+ </div>
1001
+
1002
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.min.js"></script>
1003
+ <script>
1004
+ // ---------- Theme ----------
1005
+ const STORAGE_KEY = "md2html-theme";
1006
+ function currentTheme() { return document.documentElement.dataset.theme || "light"; }
1007
+ function applyThemeIcon() {
1008
+ const use = document.getElementById("theme-icon-use");
1009
+ if (use) use.setAttribute("href", currentTheme() === "dark" ? "#i-sun" : "#i-moon");
1010
+ }
1011
+ (function restoreTheme() {
1012
+ const saved = localStorage.getItem(STORAGE_KEY);
1013
+ if (saved) document.documentElement.dataset.theme = saved;
1014
+ })();
1015
+
1016
+ // ---------- Mermaid ----------
1017
+ const diagramSources = new Map();
1018
+ function initMermaid() {
1019
+ const isDark = currentTheme() === "dark";
1020
+ mermaid.initialize({
1021
+ startOnLoad: false,
1022
+ theme: isDark ? "dark" : "default",
1023
+ themeVariables: {
1024
+ primaryColor: isDark ? "#3A2A22" : "#FBEEE6",
1025
+ primaryTextColor: isDark ? "#F5F0E8" : "#1A1A1A",
1026
+ primaryBorderColor: isDark ? "#E89572" : "#D97757",
1027
+ lineColor: isDark ? "#9A938A" : "#6B6B66",
1028
+ secondaryColor: isDark ? "#2A2520" : "#F5F5F0",
1029
+ tertiaryColor: isDark ? "#221E1A" : "#FFFFFF",
1030
+ fontFamily: "Inter, system-ui, sans-serif",
1031
+ },
1032
+ });
1033
+ }
1034
+ async function renderMermaid() {
1035
+ initMermaid();
1036
+ const els = document.querySelectorAll(".mermaid");
1037
+ els.forEach(el => {
1038
+ if (!diagramSources.has(el)) diagramSources.set(el, el.textContent.trim());
1039
+ el.textContent = diagramSources.get(el);
1040
+ el.removeAttribute("data-processed");
1041
+ });
1042
+ try { await mermaid.run({ nodes: els }); } catch (e) { console.error(e); }
1043
+ }
1044
+ function toggleTheme() {
1045
+ const next = currentTheme() === "light" ? "dark" : "light";
1046
+ document.documentElement.dataset.theme = next;
1047
+ localStorage.setItem(STORAGE_KEY, next);
1048
+ applyThemeIcon();
1049
+ renderMermaid();
1050
+ }
1051
+
1052
+ // ---------- TOC drawer (mobile) ----------
1053
+ function openToc() { document.body.classList.add("toc-open"); }
1054
+ function closeToc() { document.body.classList.remove("toc-open"); }
1055
+ document.addEventListener("keydown", e => {
1056
+ if (e.key === "Escape" && document.body.classList.contains("toc-open")) closeToc();
1057
+ });
1058
+
1059
+ // ---------- TOC scrollspy ----------
1060
+ function setupTocSpy() {
1061
+ const links = document.querySelectorAll("#toc-nav a[href^='#']");
1062
+ if (!links.length) {
1063
+ const toc = document.getElementById("toc");
1064
+ if (toc) toc.style.display = "none";
1065
+ return;
1066
+ }
1067
+ const map = new Map();
1068
+ links.forEach(a => {
1069
+ const id = a.getAttribute("href").slice(1);
1070
+ const el = document.getElementById(id);
1071
+ if (el) map.set(el, a);
1072
+ a.addEventListener("click", () => {
1073
+ if (window.matchMedia("(max-width: 900px)").matches) closeToc();
1074
+ });
1075
+ });
1076
+ const obs = new IntersectionObserver((entries) => {
1077
+ entries.forEach(en => {
1078
+ const link = map.get(en.target);
1079
+ if (!link) return;
1080
+ if (en.isIntersecting) {
1081
+ links.forEach(l => l.classList.remove("active"));
1082
+ link.classList.add("active");
1083
+ }
1084
+ });
1085
+ }, { rootMargin: "-80px 0px -70% 0px", threshold: 0 });
1086
+ map.forEach((_, el) => obs.observe(el));
1087
+ }
1088
+
1089
+ // ---------- Anchor links on h2/h3 ----------
1090
+ function injectAnchors() {
1091
+ document.querySelectorAll(".content h2[id], .content h3[id]").forEach(h => {
1092
+ if (h.querySelector(".anchor")) return;
1093
+ const a = document.createElement("a");
1094
+ a.className = "anchor";
1095
+ a.href = "#" + h.id;
1096
+ a.setAttribute("aria-label", "Permalink");
1097
+ a.innerHTML = '<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-link"/></svg>';
1098
+ h.appendChild(a);
1099
+ });
1100
+ }
1101
+
1102
+ // ---------- Copy-to-clipboard on <pre> ----------
1103
+ function injectCopyButtons() {
1104
+ document.querySelectorAll(".content pre").forEach(pre => {
1105
+ if (pre.classList.contains("mermaid")) return;
1106
+ if (pre.querySelector(".copy-btn")) return;
1107
+ const btn = document.createElement("button");
1108
+ btn.type = "button";
1109
+ btn.className = "copy-btn";
1110
+ btn.setAttribute("aria-label", "Copy code");
1111
+ btn.innerHTML = '<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-copy"/></svg>';
1112
+ btn.addEventListener("click", async () => {
1113
+ const code = pre.querySelector("code")?.textContent ?? pre.textContent;
1114
+ try {
1115
+ await navigator.clipboard.writeText(code);
1116
+ btn.classList.add("copied");
1117
+ btn.innerHTML = '<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-check"/></svg>';
1118
+ setTimeout(() => {
1119
+ btn.classList.remove("copied");
1120
+ btn.innerHTML = '<svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><use href="#i-copy"/></svg>';
1121
+ }, 1500);
1122
+ } catch (e) { console.error(e); }
1123
+ });
1124
+ pre.appendChild(btn);
1125
+ });
1126
+ }
1127
+
1128
+ // ---------- Scroll progress ----------
1129
+ function setupScrollProgress() {
1130
+ const bar = document.getElementById("scroll-progress");
1131
+ if (!bar) return;
1132
+ const onScroll = () => {
1133
+ const h = document.documentElement.scrollHeight - document.documentElement.clientHeight;
1134
+ const p = h > 0 ? (document.documentElement.scrollTop / h * 100) : 0;
1135
+ bar.style.width = p + "%";
1136
+ };
1137
+ window.addEventListener("scroll", onScroll, { passive: true });
1138
+ onScroll();
1139
+ }
1140
+
1141
+ // ---------- Boot ----------
1142
+ document.addEventListener("DOMContentLoaded", () => {
1143
+ applyThemeIcon();
1144
+ injectAnchors();
1145
+ injectCopyButtons();
1146
+ renderMermaid();
1147
+ setupTocSpy();
1148
+ setupScrollProgress();
1149
+ });
1150
+ </script>
1151
+ </body>
1152
+ </html>