voxflow 1.16.0 → 1.17.1

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 (573) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/remotion-bundle/bundle.js +0 -1
  3. package/dist/remotion-bundle/bundle.js.map +1 -1
  4. package/lib/commands/_registry.js +1 -0
  5. package/lib/commands/card-render.js +632 -0
  6. package/lib/commands/card.js +57 -0
  7. package/lib/core/ffmpeg.js +74 -11
  8. package/package.json +5 -2
  9. package/skills/.claude-plugin/marketplace.json +1 -1
  10. package/skills/.claude-plugin/plugin.json +2 -2
  11. package/skills/README.md +2 -2
  12. package/skills/card/SKILL.md +97 -5
  13. package/skills/card/assets/fonts/MANIFEST.md +29 -0
  14. package/skills/card/assets/fonts/css/cabinet-grotesk.css +2 -0
  15. package/skills/card/assets/fonts/css/geist-mono.css +29 -0
  16. package/skills/card/assets/fonts/css/geist.css +29 -0
  17. package/skills/card/assets/fonts/css/general-sans.css +2 -0
  18. package/skills/card/assets/fonts/css/ibm-plex-mono-500.css +49 -0
  19. package/skills/card/assets/fonts/css/ibm-plex-mono-600.css +49 -0
  20. package/skills/card/assets/fonts/css/ibm-plex-mono.css +49 -0
  21. package/skills/card/assets/fonts/css/libre-caslon-display.css +19 -0
  22. package/skills/card/assets/fonts/css/newsreader.css +29 -0
  23. package/skills/card/assets/fonts/css/noto-sans-sc.css +1009 -0
  24. package/skills/card/assets/fonts/css/noto-serif-sc.css +1009 -0
  25. package/skills/card/assets/fonts/css/satoshi.css +2 -0
  26. package/skills/card/assets/fonts/css/source-serif-4.css +59 -0
  27. package/skills/card/assets/fonts/css/space-grotesk.css +29 -0
  28. package/skills/card/assets/fonts/css/spectral-600.css +49 -0
  29. package/skills/card/assets/fonts/css/spectral-800.css +49 -0
  30. package/skills/card/assets/fonts/css/spectral.css +49 -0
  31. package/skills/card/assets/fonts/fonts.css +25 -0
  32. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-100.woff2 +0 -0
  33. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-101.woff2 +0 -0
  34. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-102.woff2 +0 -0
  35. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-103.woff2 +0 -0
  36. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-104.woff2 +0 -0
  37. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-105.woff2 +0 -0
  38. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-106.woff2 +0 -0
  39. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-107.woff2 +0 -0
  40. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-108.woff2 +0 -0
  41. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-109.woff2 +0 -0
  42. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-110.woff2 +0 -0
  43. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-111.woff2 +0 -0
  44. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-112.woff2 +0 -0
  45. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-113.woff2 +0 -0
  46. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-114.woff2 +0 -0
  47. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-115.woff2 +0 -0
  48. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-116.woff2 +0 -0
  49. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-117.woff2 +0 -0
  50. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-118.woff2 +0 -0
  51. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-119.woff2 +0 -0
  52. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-21.woff2 +0 -0
  53. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-22.woff2 +0 -0
  54. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-23.woff2 +0 -0
  55. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-24.woff2 +0 -0
  56. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-25.woff2 +0 -0
  57. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-26.woff2 +0 -0
  58. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-27.woff2 +0 -0
  59. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-28.woff2 +0 -0
  60. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-29.woff2 +0 -0
  61. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-30.woff2 +0 -0
  62. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-31.woff2 +0 -0
  63. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-32.woff2 +0 -0
  64. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-33.woff2 +0 -0
  65. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-34.woff2 +0 -0
  66. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-35.woff2 +0 -0
  67. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-36.woff2 +0 -0
  68. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-37.woff2 +0 -0
  69. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-38.woff2 +0 -0
  70. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-39.woff2 +0 -0
  71. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-4.woff2 +0 -0
  72. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-40.woff2 +0 -0
  73. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-41.woff2 +0 -0
  74. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-42.woff2 +0 -0
  75. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-43.woff2 +0 -0
  76. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-44.woff2 +0 -0
  77. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-45.woff2 +0 -0
  78. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-46.woff2 +0 -0
  79. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-47.woff2 +0 -0
  80. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-48.woff2 +0 -0
  81. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-49.woff2 +0 -0
  82. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-5.woff2 +0 -0
  83. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-50.woff2 +0 -0
  84. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-51.woff2 +0 -0
  85. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-52.woff2 +0 -0
  86. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-53.woff2 +0 -0
  87. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-54.woff2 +0 -0
  88. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-55.woff2 +0 -0
  89. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-56.woff2 +0 -0
  90. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-57.woff2 +0 -0
  91. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-58.woff2 +0 -0
  92. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-59.woff2 +0 -0
  93. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-6.woff2 +0 -0
  94. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-60.woff2 +0 -0
  95. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-61.woff2 +0 -0
  96. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-62.woff2 +0 -0
  97. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-63.woff2 +0 -0
  98. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-64.woff2 +0 -0
  99. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-65.woff2 +0 -0
  100. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-66.woff2 +0 -0
  101. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-67.woff2 +0 -0
  102. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-68.woff2 +0 -0
  103. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-69.woff2 +0 -0
  104. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-70.woff2 +0 -0
  105. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-71.woff2 +0 -0
  106. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-72.woff2 +0 -0
  107. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-73.woff2 +0 -0
  108. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-74.woff2 +0 -0
  109. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-75.woff2 +0 -0
  110. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-76.woff2 +0 -0
  111. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-77.woff2 +0 -0
  112. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-78.woff2 +0 -0
  113. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-79.woff2 +0 -0
  114. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-80.woff2 +0 -0
  115. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-81.woff2 +0 -0
  116. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-82.woff2 +0 -0
  117. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-83.woff2 +0 -0
  118. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-84.woff2 +0 -0
  119. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-85.woff2 +0 -0
  120. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-86.woff2 +0 -0
  121. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-87.woff2 +0 -0
  122. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-88.woff2 +0 -0
  123. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-89.woff2 +0 -0
  124. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-90.woff2 +0 -0
  125. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-91.woff2 +0 -0
  126. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-97.woff2 +0 -0
  127. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-98.woff2 +0 -0
  128. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-bold-subset-99.woff2 +0 -0
  129. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-100.woff2 +0 -0
  130. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-101.woff2 +0 -0
  131. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-102.woff2 +0 -0
  132. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-103.woff2 +0 -0
  133. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-104.woff2 +0 -0
  134. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-105.woff2 +0 -0
  135. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-106.woff2 +0 -0
  136. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-107.woff2 +0 -0
  137. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-108.woff2 +0 -0
  138. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-109.woff2 +0 -0
  139. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-110.woff2 +0 -0
  140. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-111.woff2 +0 -0
  141. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-112.woff2 +0 -0
  142. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-113.woff2 +0 -0
  143. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-114.woff2 +0 -0
  144. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-115.woff2 +0 -0
  145. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-116.woff2 +0 -0
  146. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-117.woff2 +0 -0
  147. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-118.woff2 +0 -0
  148. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-119.woff2 +0 -0
  149. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-21.woff2 +0 -0
  150. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-22.woff2 +0 -0
  151. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-23.woff2 +0 -0
  152. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-24.woff2 +0 -0
  153. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-25.woff2 +0 -0
  154. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-26.woff2 +0 -0
  155. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-27.woff2 +0 -0
  156. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-28.woff2 +0 -0
  157. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-29.woff2 +0 -0
  158. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-30.woff2 +0 -0
  159. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-31.woff2 +0 -0
  160. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-32.woff2 +0 -0
  161. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-33.woff2 +0 -0
  162. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-34.woff2 +0 -0
  163. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-35.woff2 +0 -0
  164. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-36.woff2 +0 -0
  165. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-37.woff2 +0 -0
  166. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-38.woff2 +0 -0
  167. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-39.woff2 +0 -0
  168. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-4.woff2 +0 -0
  169. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-40.woff2 +0 -0
  170. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-41.woff2 +0 -0
  171. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-42.woff2 +0 -0
  172. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-43.woff2 +0 -0
  173. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-44.woff2 +0 -0
  174. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-45.woff2 +0 -0
  175. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-46.woff2 +0 -0
  176. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-47.woff2 +0 -0
  177. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-48.woff2 +0 -0
  178. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-49.woff2 +0 -0
  179. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-5.woff2 +0 -0
  180. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-50.woff2 +0 -0
  181. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-51.woff2 +0 -0
  182. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-52.woff2 +0 -0
  183. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-53.woff2 +0 -0
  184. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-54.woff2 +0 -0
  185. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-55.woff2 +0 -0
  186. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-56.woff2 +0 -0
  187. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-57.woff2 +0 -0
  188. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-58.woff2 +0 -0
  189. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-59.woff2 +0 -0
  190. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-6.woff2 +0 -0
  191. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-60.woff2 +0 -0
  192. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-61.woff2 +0 -0
  193. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-62.woff2 +0 -0
  194. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-63.woff2 +0 -0
  195. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-64.woff2 +0 -0
  196. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-65.woff2 +0 -0
  197. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-66.woff2 +0 -0
  198. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-67.woff2 +0 -0
  199. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-68.woff2 +0 -0
  200. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-69.woff2 +0 -0
  201. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-70.woff2 +0 -0
  202. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-71.woff2 +0 -0
  203. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-72.woff2 +0 -0
  204. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-73.woff2 +0 -0
  205. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-74.woff2 +0 -0
  206. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-75.woff2 +0 -0
  207. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-76.woff2 +0 -0
  208. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-77.woff2 +0 -0
  209. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-78.woff2 +0 -0
  210. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-79.woff2 +0 -0
  211. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-80.woff2 +0 -0
  212. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-81.woff2 +0 -0
  213. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-82.woff2 +0 -0
  214. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-83.woff2 +0 -0
  215. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-84.woff2 +0 -0
  216. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-85.woff2 +0 -0
  217. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-86.woff2 +0 -0
  218. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-87.woff2 +0 -0
  219. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-88.woff2 +0 -0
  220. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-89.woff2 +0 -0
  221. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-90.woff2 +0 -0
  222. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-91.woff2 +0 -0
  223. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-97.woff2 +0 -0
  224. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-98.woff2 +0 -0
  225. package/skills/card/assets/fonts/packages/lxgw-wenkai/files/lxgwwenkailite-regular-subset-99.woff2 +0 -0
  226. package/skills/card/assets/fonts/packages/lxgw-wenkai/lxgwwenkailite-bold.css +873 -0
  227. package/skills/card/assets/fonts/packages/lxgw-wenkai/lxgwwenkailite-regular.css +873 -0
  228. package/skills/card/assets/fonts/packages/lxgw-wenkai/style.css +2 -0
  229. package/skills/card/assets/fonts/packages/smiley-sans/L1_4e00_192.woff2 +0 -0
  230. package/skills/card/assets/fonts/packages/smiley-sans/L1_4fea_192.woff2 +0 -0
  231. package/skills/card/assets/fonts/packages/smiley-sans/L1_5268_192.woff2 +0 -0
  232. package/skills/card/assets/fonts/packages/smiley-sans/L1_543c_192.woff2 +0 -0
  233. package/skills/card/assets/fonts/packages/smiley-sans/L1_5784_192.woff2 +0 -0
  234. package/skills/card/assets/fonts/packages/smiley-sans/L1_5b6c_192.woff2 +0 -0
  235. package/skills/card/assets/fonts/packages/smiley-sans/L1_5e37_192.woff2 +0 -0
  236. package/skills/card/assets/fonts/packages/smiley-sans/L1_60d2_192.woff2 +0 -0
  237. package/skills/card/assets/fonts/packages/smiley-sans/L1_6326_192.woff2 +0 -0
  238. package/skills/card/assets/fonts/packages/smiley-sans/L1_65b1_192.woff2 +0 -0
  239. package/skills/card/assets/fonts/packages/smiley-sans/L1_68a8_192.woff2 +0 -0
  240. package/skills/card/assets/fonts/packages/smiley-sans/L1_6cba_192.woff2 +0 -0
  241. package/skills/card/assets/fonts/packages/smiley-sans/L1_6fa2_192.woff2 +0 -0
  242. package/skills/card/assets/fonts/packages/smiley-sans/L1_73ce_192.woff2 +0 -0
  243. package/skills/card/assets/fonts/packages/smiley-sans/L1_77e4_192.woff2 +0 -0
  244. package/skills/card/assets/fonts/packages/smiley-sans/L1_7b78_192.woff2 +0 -0
  245. package/skills/card/assets/fonts/packages/smiley-sans/L1_7eee_192.woff2 +0 -0
  246. package/skills/card/assets/fonts/packages/smiley-sans/L1_81c1_192.woff2 +0 -0
  247. package/skills/card/assets/fonts/packages/smiley-sans/L1_8608_192.woff2 +0 -0
  248. package/skills/card/assets/fonts/packages/smiley-sans/L1_8aa4_192.woff2 +0 -0
  249. package/skills/card/assets/fonts/packages/smiley-sans/L1_8d20_192.woff2 +0 -0
  250. package/skills/card/assets/fonts/packages/smiley-sans/L1_8feb_192.woff2 +0 -0
  251. package/skills/card/assets/fonts/packages/smiley-sans/L1_94aa_192.woff2 +0 -0
  252. package/skills/card/assets/fonts/packages/smiley-sans/L1_97cd_266.woff2 +0 -0
  253. package/skills/card/assets/fonts/packages/smiley-sans/L2_3918_96.woff2 +0 -0
  254. package/skills/card/assets/fonts/packages/smiley-sans/L2_5081_96.woff2 +0 -0
  255. package/skills/card/assets/fonts/packages/smiley-sans/L2_5467_96.woff2 +0 -0
  256. package/skills/card/assets/fonts/packages/smiley-sans/L2_55ed_96.woff2 +0 -0
  257. package/skills/card/assets/fonts/packages/smiley-sans/L2_57f0_96.woff2 +0 -0
  258. package/skills/card/assets/fonts/packages/smiley-sans/L2_5ae4_96.woff2 +0 -0
  259. package/skills/card/assets/fonts/packages/smiley-sans/L2_5e15_96.woff2 +0 -0
  260. package/skills/card/assets/fonts/packages/smiley-sans/L2_609b_96.woff2 +0 -0
  261. package/skills/card/assets/fonts/packages/smiley-sans/L2_63e1_96.woff2 +0 -0
  262. package/skills/card/assets/fonts/packages/smiley-sans/L2_66dd_96.woff2 +0 -0
  263. package/skills/card/assets/fonts/packages/smiley-sans/L2_696c_96.woff2 +0 -0
  264. package/skills/card/assets/fonts/packages/smiley-sans/L2_6c75_96.woff2 +0 -0
  265. package/skills/card/assets/fonts/packages/smiley-sans/L2_6e73_96.woff2 +0 -0
  266. package/skills/card/assets/fonts/packages/smiley-sans/L2_7114_96.woff2 +0 -0
  267. package/skills/card/assets/fonts/packages/smiley-sans/L2_7392_96.woff2 +0 -0
  268. package/skills/card/assets/fonts/packages/smiley-sans/L2_7580_96.woff2 +0 -0
  269. package/skills/card/assets/fonts/packages/smiley-sans/L2_7769_96.woff2 +0 -0
  270. package/skills/card/assets/fonts/packages/smiley-sans/L2_7a71_96.woff2 +0 -0
  271. package/skills/card/assets/fonts/packages/smiley-sans/L2_7e21_96.woff2 +0 -0
  272. package/skills/card/assets/fonts/packages/smiley-sans/L2_7fcd_96.woff2 +0 -0
  273. package/skills/card/assets/fonts/packages/smiley-sans/L2_8203_96.woff2 +0 -0
  274. package/skills/card/assets/fonts/packages/smiley-sans/L2_8393_96.woff2 +0 -0
  275. package/skills/card/assets/fonts/packages/smiley-sans/L2_85b8_96.woff2 +0 -0
  276. package/skills/card/assets/fonts/packages/smiley-sans/L2_87cb_96.woff2 +0 -0
  277. package/skills/card/assets/fonts/packages/smiley-sans/L2_8bb5_96.woff2 +0 -0
  278. package/skills/card/assets/fonts/packages/smiley-sans/L2_8db6_96.woff2 +0 -0
  279. package/skills/card/assets/fonts/packages/smiley-sans/L2_9022_96.woff2 +0 -0
  280. package/skills/card/assets/fonts/packages/smiley-sans/L2_91ea_96.woff2 +0 -0
  281. package/skills/card/assets/fonts/packages/smiley-sans/L2_9504_96.woff2 +0 -0
  282. package/skills/card/assets/fonts/packages/smiley-sans/L2_9655_96.woff2 +0 -0
  283. package/skills/card/assets/fonts/packages/smiley-sans/L2_996a_96.woff2 +0 -0
  284. package/skills/card/assets/fonts/packages/smiley-sans/L2_9c95_133.woff2 +0 -0
  285. package/skills/card/assets/fonts/packages/smiley-sans/L3_101_64.woff2 +0 -0
  286. package/skills/card/assets/fonts/packages/smiley-sans/L3_148_64.woff2 +0 -0
  287. package/skills/card/assets/fonts/packages/smiley-sans/L3_1d4_64.woff2 +0 -0
  288. package/skills/card/assets/fonts/packages/smiley-sans/L3_1e86_64.woff2 +0 -0
  289. package/skills/card/assets/fonts/packages/smiley-sans/L3_1edf_64.woff2 +0 -0
  290. package/skills/card/assets/fonts/packages/smiley-sans/L3_20_64.woff2 +0 -0
  291. package/skills/card/assets/fonts/packages/smiley-sans/L3_2172_64.woff2 +0 -0
  292. package/skills/card/assets/fonts/packages/smiley-sans/L3_2495_64.woff2 +0 -0
  293. package/skills/card/assets/fonts/packages/smiley-sans/L3_3067_64.woff2 +0 -0
  294. package/skills/card/assets/fonts/packages/smiley-sans/L3_30b3_64.woff2 +0 -0
  295. package/skills/card/assets/fonts/packages/smiley-sans/L3_30f3_64.woff2 +0 -0
  296. package/skills/card/assets/fonts/packages/smiley-sans/L3_3a9_64.woff2 +0 -0
  297. package/skills/card/assets/fonts/packages/smiley-sans/L3_421_64.woff2 +0 -0
  298. package/skills/card/assets/fonts/packages/smiley-sans/L3_536a_64.woff2 +0 -0
  299. package/skills/card/assets/fonts/packages/smiley-sans/L3_60_64.woff2 +0 -0
  300. package/skills/card/assets/fonts/packages/smiley-sans/L3_61b8_64.woff2 +0 -0
  301. package/skills/card/assets/fonts/packages/smiley-sans/L3_706d_64.woff2 +0 -0
  302. package/skills/card/assets/fonts/packages/smiley-sans/L3_7b7c_64.woff2 +0 -0
  303. package/skills/card/assets/fonts/packages/smiley-sans/L3_836e_64.woff2 +0 -0
  304. package/skills/card/assets/fonts/packages/smiley-sans/L3_9124_64.woff2 +0 -0
  305. package/skills/card/assets/fonts/packages/smiley-sans/L3_9795_64.woff2 +0 -0
  306. package/skills/card/assets/fonts/packages/smiley-sans/L3_c1_64.woff2 +0 -0
  307. package/skills/card/assets/fonts/packages/smiley-sans/L3_fe3a_64.woff2 +0 -0
  308. package/skills/card/assets/fonts/packages/smiley-sans/L3_ff16_79.woff2 +0 -0
  309. package/skills/card/assets/fonts/packages/smiley-sans/font.css +80 -0
  310. package/skills/card/assets/fonts/woff2/fontshare/cabinet-grotesk.woff2 +0 -0
  311. package/skills/card/assets/fonts/woff2/fontshare/general-sans.woff2 +0 -0
  312. package/skills/card/assets/fonts/woff2/fontshare/satoshi.woff2 +0 -0
  313. package/skills/card/assets/fonts/woff2/geist/geist-cyrillic-wght-normal.woff2 +0 -0
  314. package/skills/card/assets/fonts/woff2/geist/geist-latin-ext-wght-normal.woff2 +0 -0
  315. package/skills/card/assets/fonts/woff2/geist/geist-latin-wght-normal.woff2 +0 -0
  316. package/skills/card/assets/fonts/woff2/geist-mono/geist-mono-cyrillic-wght-normal.woff2 +0 -0
  317. package/skills/card/assets/fonts/woff2/geist-mono/geist-mono-latin-ext-wght-normal.woff2 +0 -0
  318. package/skills/card/assets/fonts/woff2/geist-mono/geist-mono-latin-wght-normal.woff2 +0 -0
  319. package/skills/card/assets/fonts/woff2/ibm-plex-mono/ibm-plex-mono-cyrillic-400-normal.woff2 +0 -0
  320. package/skills/card/assets/fonts/woff2/ibm-plex-mono/ibm-plex-mono-cyrillic-ext-400-normal.woff2 +0 -0
  321. package/skills/card/assets/fonts/woff2/ibm-plex-mono/ibm-plex-mono-latin-400-normal.woff2 +0 -0
  322. package/skills/card/assets/fonts/woff2/ibm-plex-mono/ibm-plex-mono-latin-ext-400-normal.woff2 +0 -0
  323. package/skills/card/assets/fonts/woff2/ibm-plex-mono/ibm-plex-mono-vietnamese-400-normal.woff2 +0 -0
  324. package/skills/card/assets/fonts/woff2/ibm-plex-mono-500/ibm-plex-mono-cyrillic-500-normal.woff2 +0 -0
  325. package/skills/card/assets/fonts/woff2/ibm-plex-mono-500/ibm-plex-mono-cyrillic-ext-500-normal.woff2 +0 -0
  326. package/skills/card/assets/fonts/woff2/ibm-plex-mono-500/ibm-plex-mono-latin-500-normal.woff2 +0 -0
  327. package/skills/card/assets/fonts/woff2/ibm-plex-mono-500/ibm-plex-mono-latin-ext-500-normal.woff2 +0 -0
  328. package/skills/card/assets/fonts/woff2/ibm-plex-mono-500/ibm-plex-mono-vietnamese-500-normal.woff2 +0 -0
  329. package/skills/card/assets/fonts/woff2/ibm-plex-mono-600/ibm-plex-mono-cyrillic-600-normal.woff2 +0 -0
  330. package/skills/card/assets/fonts/woff2/ibm-plex-mono-600/ibm-plex-mono-cyrillic-ext-600-normal.woff2 +0 -0
  331. package/skills/card/assets/fonts/woff2/ibm-plex-mono-600/ibm-plex-mono-latin-600-normal.woff2 +0 -0
  332. package/skills/card/assets/fonts/woff2/ibm-plex-mono-600/ibm-plex-mono-latin-ext-600-normal.woff2 +0 -0
  333. package/skills/card/assets/fonts/woff2/ibm-plex-mono-600/ibm-plex-mono-vietnamese-600-normal.woff2 +0 -0
  334. package/skills/card/assets/fonts/woff2/libre-caslon-display/libre-caslon-display-latin-400-normal.woff2 +0 -0
  335. package/skills/card/assets/fonts/woff2/libre-caslon-display/libre-caslon-display-latin-ext-400-normal.woff2 +0 -0
  336. package/skills/card/assets/fonts/woff2/newsreader/newsreader-latin-ext-wght-normal.woff2 +0 -0
  337. package/skills/card/assets/fonts/woff2/newsreader/newsreader-latin-wght-normal.woff2 +0 -0
  338. package/skills/card/assets/fonts/woff2/newsreader/newsreader-vietnamese-wght-normal.woff2 +0 -0
  339. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-100-wght-normal.woff2 +0 -0
  340. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-101-wght-normal.woff2 +0 -0
  341. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-102-wght-normal.woff2 +0 -0
  342. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-103-wght-normal.woff2 +0 -0
  343. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-104-wght-normal.woff2 +0 -0
  344. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-105-wght-normal.woff2 +0 -0
  345. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-106-wght-normal.woff2 +0 -0
  346. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-107-wght-normal.woff2 +0 -0
  347. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-108-wght-normal.woff2 +0 -0
  348. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-109-wght-normal.woff2 +0 -0
  349. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-110-wght-normal.woff2 +0 -0
  350. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-111-wght-normal.woff2 +0 -0
  351. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-112-wght-normal.woff2 +0 -0
  352. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-113-wght-normal.woff2 +0 -0
  353. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-114-wght-normal.woff2 +0 -0
  354. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-115-wght-normal.woff2 +0 -0
  355. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-116-wght-normal.woff2 +0 -0
  356. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-117-wght-normal.woff2 +0 -0
  357. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-118-wght-normal.woff2 +0 -0
  358. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-119-wght-normal.woff2 +0 -0
  359. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-21-wght-normal.woff2 +0 -0
  360. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-22-wght-normal.woff2 +0 -0
  361. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-23-wght-normal.woff2 +0 -0
  362. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-24-wght-normal.woff2 +0 -0
  363. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-25-wght-normal.woff2 +0 -0
  364. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-26-wght-normal.woff2 +0 -0
  365. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-27-wght-normal.woff2 +0 -0
  366. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-28-wght-normal.woff2 +0 -0
  367. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-29-wght-normal.woff2 +0 -0
  368. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-30-wght-normal.woff2 +0 -0
  369. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-31-wght-normal.woff2 +0 -0
  370. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-32-wght-normal.woff2 +0 -0
  371. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-33-wght-normal.woff2 +0 -0
  372. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-34-wght-normal.woff2 +0 -0
  373. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-35-wght-normal.woff2 +0 -0
  374. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-36-wght-normal.woff2 +0 -0
  375. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-37-wght-normal.woff2 +0 -0
  376. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-38-wght-normal.woff2 +0 -0
  377. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-39-wght-normal.woff2 +0 -0
  378. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-4-wght-normal.woff2 +0 -0
  379. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-40-wght-normal.woff2 +0 -0
  380. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-41-wght-normal.woff2 +0 -0
  381. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-42-wght-normal.woff2 +0 -0
  382. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-43-wght-normal.woff2 +0 -0
  383. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-44-wght-normal.woff2 +0 -0
  384. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-45-wght-normal.woff2 +0 -0
  385. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-46-wght-normal.woff2 +0 -0
  386. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-47-wght-normal.woff2 +0 -0
  387. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-48-wght-normal.woff2 +0 -0
  388. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-49-wght-normal.woff2 +0 -0
  389. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-5-wght-normal.woff2 +0 -0
  390. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-50-wght-normal.woff2 +0 -0
  391. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-51-wght-normal.woff2 +0 -0
  392. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-52-wght-normal.woff2 +0 -0
  393. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-53-wght-normal.woff2 +0 -0
  394. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-54-wght-normal.woff2 +0 -0
  395. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-55-wght-normal.woff2 +0 -0
  396. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-56-wght-normal.woff2 +0 -0
  397. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-57-wght-normal.woff2 +0 -0
  398. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-58-wght-normal.woff2 +0 -0
  399. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-59-wght-normal.woff2 +0 -0
  400. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-6-wght-normal.woff2 +0 -0
  401. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-60-wght-normal.woff2 +0 -0
  402. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-61-wght-normal.woff2 +0 -0
  403. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-62-wght-normal.woff2 +0 -0
  404. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-63-wght-normal.woff2 +0 -0
  405. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-64-wght-normal.woff2 +0 -0
  406. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-65-wght-normal.woff2 +0 -0
  407. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-66-wght-normal.woff2 +0 -0
  408. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-67-wght-normal.woff2 +0 -0
  409. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-68-wght-normal.woff2 +0 -0
  410. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-69-wght-normal.woff2 +0 -0
  411. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-70-wght-normal.woff2 +0 -0
  412. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-71-wght-normal.woff2 +0 -0
  413. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-72-wght-normal.woff2 +0 -0
  414. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-73-wght-normal.woff2 +0 -0
  415. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-74-wght-normal.woff2 +0 -0
  416. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-75-wght-normal.woff2 +0 -0
  417. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-76-wght-normal.woff2 +0 -0
  418. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-77-wght-normal.woff2 +0 -0
  419. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-78-wght-normal.woff2 +0 -0
  420. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-79-wght-normal.woff2 +0 -0
  421. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-80-wght-normal.woff2 +0 -0
  422. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-81-wght-normal.woff2 +0 -0
  423. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-82-wght-normal.woff2 +0 -0
  424. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-83-wght-normal.woff2 +0 -0
  425. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-84-wght-normal.woff2 +0 -0
  426. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-85-wght-normal.woff2 +0 -0
  427. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-86-wght-normal.woff2 +0 -0
  428. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-87-wght-normal.woff2 +0 -0
  429. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-88-wght-normal.woff2 +0 -0
  430. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-89-wght-normal.woff2 +0 -0
  431. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-90-wght-normal.woff2 +0 -0
  432. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-91-wght-normal.woff2 +0 -0
  433. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-97-wght-normal.woff2 +0 -0
  434. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-98-wght-normal.woff2 +0 -0
  435. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-99-wght-normal.woff2 +0 -0
  436. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-cyrillic-wght-normal.woff2 +0 -0
  437. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-latin-ext-wght-normal.woff2 +0 -0
  438. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-latin-wght-normal.woff2 +0 -0
  439. package/skills/card/assets/fonts/woff2/noto-sans-sc/noto-sans-sc-vietnamese-wght-normal.woff2 +0 -0
  440. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-100-wght-normal.woff2 +0 -0
  441. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-101-wght-normal.woff2 +0 -0
  442. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-102-wght-normal.woff2 +0 -0
  443. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-103-wght-normal.woff2 +0 -0
  444. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-104-wght-normal.woff2 +0 -0
  445. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-105-wght-normal.woff2 +0 -0
  446. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-106-wght-normal.woff2 +0 -0
  447. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-107-wght-normal.woff2 +0 -0
  448. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-108-wght-normal.woff2 +0 -0
  449. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-109-wght-normal.woff2 +0 -0
  450. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-110-wght-normal.woff2 +0 -0
  451. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-111-wght-normal.woff2 +0 -0
  452. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-112-wght-normal.woff2 +0 -0
  453. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-113-wght-normal.woff2 +0 -0
  454. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-114-wght-normal.woff2 +0 -0
  455. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-115-wght-normal.woff2 +0 -0
  456. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-116-wght-normal.woff2 +0 -0
  457. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-117-wght-normal.woff2 +0 -0
  458. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-118-wght-normal.woff2 +0 -0
  459. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-119-wght-normal.woff2 +0 -0
  460. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-21-wght-normal.woff2 +0 -0
  461. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-22-wght-normal.woff2 +0 -0
  462. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-23-wght-normal.woff2 +0 -0
  463. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-24-wght-normal.woff2 +0 -0
  464. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-25-wght-normal.woff2 +0 -0
  465. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-26-wght-normal.woff2 +0 -0
  466. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-27-wght-normal.woff2 +0 -0
  467. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-28-wght-normal.woff2 +0 -0
  468. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-29-wght-normal.woff2 +0 -0
  469. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-30-wght-normal.woff2 +0 -0
  470. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-31-wght-normal.woff2 +0 -0
  471. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-32-wght-normal.woff2 +0 -0
  472. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-33-wght-normal.woff2 +0 -0
  473. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-34-wght-normal.woff2 +0 -0
  474. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-35-wght-normal.woff2 +0 -0
  475. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-36-wght-normal.woff2 +0 -0
  476. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-37-wght-normal.woff2 +0 -0
  477. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-38-wght-normal.woff2 +0 -0
  478. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-39-wght-normal.woff2 +0 -0
  479. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-4-wght-normal.woff2 +0 -0
  480. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-40-wght-normal.woff2 +0 -0
  481. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-41-wght-normal.woff2 +0 -0
  482. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-42-wght-normal.woff2 +0 -0
  483. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-43-wght-normal.woff2 +0 -0
  484. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-44-wght-normal.woff2 +0 -0
  485. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-45-wght-normal.woff2 +0 -0
  486. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-46-wght-normal.woff2 +0 -0
  487. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-47-wght-normal.woff2 +0 -0
  488. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-48-wght-normal.woff2 +0 -0
  489. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-49-wght-normal.woff2 +0 -0
  490. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-5-wght-normal.woff2 +0 -0
  491. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-50-wght-normal.woff2 +0 -0
  492. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-51-wght-normal.woff2 +0 -0
  493. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-52-wght-normal.woff2 +0 -0
  494. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-53-wght-normal.woff2 +0 -0
  495. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-54-wght-normal.woff2 +0 -0
  496. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-55-wght-normal.woff2 +0 -0
  497. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-56-wght-normal.woff2 +0 -0
  498. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-57-wght-normal.woff2 +0 -0
  499. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-58-wght-normal.woff2 +0 -0
  500. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-59-wght-normal.woff2 +0 -0
  501. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-6-wght-normal.woff2 +0 -0
  502. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-60-wght-normal.woff2 +0 -0
  503. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-61-wght-normal.woff2 +0 -0
  504. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-62-wght-normal.woff2 +0 -0
  505. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-63-wght-normal.woff2 +0 -0
  506. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-64-wght-normal.woff2 +0 -0
  507. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-65-wght-normal.woff2 +0 -0
  508. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-66-wght-normal.woff2 +0 -0
  509. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-67-wght-normal.woff2 +0 -0
  510. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-68-wght-normal.woff2 +0 -0
  511. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-69-wght-normal.woff2 +0 -0
  512. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-70-wght-normal.woff2 +0 -0
  513. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-71-wght-normal.woff2 +0 -0
  514. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-72-wght-normal.woff2 +0 -0
  515. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-73-wght-normal.woff2 +0 -0
  516. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-74-wght-normal.woff2 +0 -0
  517. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-75-wght-normal.woff2 +0 -0
  518. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-76-wght-normal.woff2 +0 -0
  519. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-77-wght-normal.woff2 +0 -0
  520. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-78-wght-normal.woff2 +0 -0
  521. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-79-wght-normal.woff2 +0 -0
  522. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-80-wght-normal.woff2 +0 -0
  523. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-81-wght-normal.woff2 +0 -0
  524. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-82-wght-normal.woff2 +0 -0
  525. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-83-wght-normal.woff2 +0 -0
  526. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-84-wght-normal.woff2 +0 -0
  527. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-85-wght-normal.woff2 +0 -0
  528. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-86-wght-normal.woff2 +0 -0
  529. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-87-wght-normal.woff2 +0 -0
  530. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-88-wght-normal.woff2 +0 -0
  531. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-89-wght-normal.woff2 +0 -0
  532. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-90-wght-normal.woff2 +0 -0
  533. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-91-wght-normal.woff2 +0 -0
  534. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-97-wght-normal.woff2 +0 -0
  535. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-98-wght-normal.woff2 +0 -0
  536. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-99-wght-normal.woff2 +0 -0
  537. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-cyrillic-wght-normal.woff2 +0 -0
  538. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-latin-ext-wght-normal.woff2 +0 -0
  539. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-latin-wght-normal.woff2 +0 -0
  540. package/skills/card/assets/fonts/woff2/noto-serif-sc/noto-serif-sc-vietnamese-wght-normal.woff2 +0 -0
  541. package/skills/card/assets/fonts/woff2/source-serif-4/source-serif-4-cyrillic-ext-wght-normal.woff2 +0 -0
  542. package/skills/card/assets/fonts/woff2/source-serif-4/source-serif-4-cyrillic-wght-normal.woff2 +0 -0
  543. package/skills/card/assets/fonts/woff2/source-serif-4/source-serif-4-greek-wght-normal.woff2 +0 -0
  544. package/skills/card/assets/fonts/woff2/source-serif-4/source-serif-4-latin-ext-wght-normal.woff2 +0 -0
  545. package/skills/card/assets/fonts/woff2/source-serif-4/source-serif-4-latin-wght-normal.woff2 +0 -0
  546. package/skills/card/assets/fonts/woff2/source-serif-4/source-serif-4-vietnamese-wght-normal.woff2 +0 -0
  547. package/skills/card/assets/fonts/woff2/space-grotesk/space-grotesk-latin-ext-wght-normal.woff2 +0 -0
  548. package/skills/card/assets/fonts/woff2/space-grotesk/space-grotesk-latin-wght-normal.woff2 +0 -0
  549. package/skills/card/assets/fonts/woff2/space-grotesk/space-grotesk-vietnamese-wght-normal.woff2 +0 -0
  550. package/skills/card/assets/fonts/woff2/spectral/spectral-cyrillic-400-normal.woff2 +0 -0
  551. package/skills/card/assets/fonts/woff2/spectral/spectral-cyrillic-ext-400-normal.woff2 +0 -0
  552. package/skills/card/assets/fonts/woff2/spectral/spectral-latin-400-normal.woff2 +0 -0
  553. package/skills/card/assets/fonts/woff2/spectral/spectral-latin-ext-400-normal.woff2 +0 -0
  554. package/skills/card/assets/fonts/woff2/spectral/spectral-vietnamese-400-normal.woff2 +0 -0
  555. package/skills/card/assets/fonts/woff2/spectral-600/spectral-cyrillic-600-normal.woff2 +0 -0
  556. package/skills/card/assets/fonts/woff2/spectral-600/spectral-cyrillic-ext-600-normal.woff2 +0 -0
  557. package/skills/card/assets/fonts/woff2/spectral-600/spectral-latin-600-normal.woff2 +0 -0
  558. package/skills/card/assets/fonts/woff2/spectral-600/spectral-latin-ext-600-normal.woff2 +0 -0
  559. package/skills/card/assets/fonts/woff2/spectral-600/spectral-vietnamese-600-normal.woff2 +0 -0
  560. package/skills/card/assets/fonts/woff2/spectral-800/spectral-cyrillic-800-normal.woff2 +0 -0
  561. package/skills/card/assets/fonts/woff2/spectral-800/spectral-cyrillic-ext-800-normal.woff2 +0 -0
  562. package/skills/card/assets/fonts/woff2/spectral-800/spectral-latin-800-normal.woff2 +0 -0
  563. package/skills/card/assets/fonts/woff2/spectral-800/spectral-latin-ext-800-normal.woff2 +0 -0
  564. package/skills/card/assets/fonts/woff2/spectral-800/spectral-vietnamese-800-normal.woff2 +0 -0
  565. package/skills/card/references/design-languages.md +2 -0
  566. package/skills/card/references/fonts-preview.html +450 -0
  567. package/skills/card/references/fonts.md +151 -0
  568. package/skills/card/references/taste.md +2 -2
  569. package/skills/card/references/themes/presets.md +1 -1
  570. package/skills/card/scripts/download-fonts.sh +240 -0
  571. package/skills/card/scripts/render-cards.mjs +3 -0
  572. package/skills/hub/SKILL.md +3 -2
  573. package/skills/video/SKILL.md +2 -2
@@ -25,6 +25,7 @@ module.exports = {
25
25
  asr: () => require('./asr'),
26
26
  'asr-jobs': () => require('./asr-jobs'),
27
27
  'auth-cmds': () => require('./auth-cmds'),
28
+ card: () => require('./card'),
28
29
  dub: () => require('./dub'),
29
30
  explain: () => require('./explain'),
30
31
  feedback: () => require('./feedback'),
@@ -0,0 +1,632 @@
1
+ /**
2
+ * VoxFlow CLI — card render subcommand
3
+ *
4
+ * Renders a card-skill output directory into a polished narrated MP4:
5
+ * 1. Read deck.json (narration text per card)
6
+ * 2. Ensure PNGs exist
7
+ * 3. Synthesize TTS per card → WAV
8
+ * 4. Render per-card clip: PNG + subtle zoom + subtitle bar + fade
9
+ * 5. Render intro title card + outro branding card
10
+ * 6. Concat all clips (intro + cards + outro)
11
+ * 7. Mix background music (optional)
12
+ *
13
+ * Features:
14
+ * - Subtle center zoom (2%) — content stays readable
15
+ * - Bottom subtitle bar with narration text
16
+ * - Auto intro card (series title) + outro card (branding)
17
+ * - Crossfade via per-clip fade-in/fade-out
18
+ * - Background music loop at low volume
19
+ * - ffmpeg-static fallback (no system FFmpeg required)
20
+ */
21
+
22
+ 'use strict';
23
+
24
+ const fs = require('fs');
25
+ const path = require('path');
26
+
27
+ const { parseFlag, runWithRetry } = require('../core/args');
28
+ const { getToken, getTokenInfo } = require('../core/auth');
29
+ const { API_BASE } = require('../core/config');
30
+ const { buildWav, createSilence, PCM_SAMPLE_RATE } = require('../core/audio');
31
+ const { BYTES_PER_MS } = require('../core/timeline');
32
+ const { synthesizeTTS } = require('../core/tts-synthesizer');
33
+ const { runCommand, checkFfmpeg, concatVideos } = require('../core/ffmpeg');
34
+
35
+ // ── Constants ─────────────────────────────────────────────────────────────────
36
+
37
+ const RATIO_DIMS = {
38
+ '1:1': { w: 1080, h: 1080 },
39
+ '3:4': { w: 1080, h: 1440 },
40
+ '4:5': { w: 1080, h: 1350 },
41
+ '9:16': { w: 1080, h: 1920 },
42
+ '16:9': { w: 1920, h: 1080 },
43
+ };
44
+
45
+ // Subtitle styling
46
+ const SUB_FONT_SIZE = 36;
47
+ const SUB_BOX_OPACITY = 0.6;
48
+ const SUB_MARGIN_BOTTOM = 80;
49
+ const SUB_PADDING = 20;
50
+
51
+ // ── Helpers ───────────────────────────────────────────────────────────────────
52
+
53
+ function readDeckJson(dir) {
54
+ const p = path.join(dir, 'deck.json');
55
+ if (!fs.existsSync(p)) {
56
+ throw new Error(
57
+ `No deck.json found in ${dir}.\n` +
58
+ ` The card SKILL.md workflow must produce a deck.json alongside the HTML files.\n` +
59
+ ` See: cli/skills/card/SKILL.md — Step 9.`,
60
+ );
61
+ }
62
+ return JSON.parse(fs.readFileSync(p, 'utf8'));
63
+ }
64
+
65
+ function resolveCardPng(dir, cardFile) {
66
+ const base = path.basename(cardFile, path.extname(cardFile));
67
+ const candidates = [
68
+ path.join(dir, 'exports', `${base}.png`),
69
+ path.join(dir, `${base}.png`),
70
+ ];
71
+ for (const c of candidates) {
72
+ if (fs.existsSync(c)) return c;
73
+ }
74
+ return null;
75
+ }
76
+
77
+ function writePcmAsWav(pcmBuffer, dest, trailingSilenceSec = 0) {
78
+ // Append silence to the PCM itself so the WAV's natural duration includes
79
+ // the post-narration "reading time" pause. Using `-shortest` in ffmpeg
80
+ // would otherwise truncate the clip back to the narration-only length.
81
+ const totalPcm = trailingSilenceSec > 0
82
+ ? Buffer.concat([pcmBuffer, createSilence(trailingSilenceSec, PCM_SAMPLE_RATE)])
83
+ : pcmBuffer;
84
+ const { wav } = buildWav([totalPcm], { silenceSec: 0 });
85
+ fs.writeFileSync(dest, wav);
86
+ return dest;
87
+ }
88
+
89
+ function pcmToDurationMs(buf) {
90
+ return Math.round(buf.length / BYTES_PER_MS);
91
+ }
92
+
93
+ /**
94
+ * Escape text for an FFmpeg drawtext `text='...'` value.
95
+ *
96
+ * FFmpeg filtergraph parsing has two layers of escaping:
97
+ * 1. The filter argument splitter (`,` and `;` separate filters/chains).
98
+ * 2. The drawtext text= value, single-quoted; `\` and `:` are special.
99
+ *
100
+ * For each special char we therefore emit `\\<char>` \u2014 a single literal
101
+ * backslash plus the char \u2014 so JS source `'\\\\'` (4 chars) = 2-char string `\\`,
102
+ * which ffmpeg parses as one literal backslash.
103
+ *
104
+ * Apostrophes inside a single-quoted text= value cannot be escaped reliably
105
+ * across ffmpeg versions, so we substitute the typographic right single quote
106
+ * (U+2019) which renders identically for human readers.
107
+ */
108
+ function escapeDrawtext(text) {
109
+ return text
110
+ .replace(/\\/g, '\\\\') // \ \u2192 \\ (one literal backslash)
111
+ .replace(/'/g, '\u2019') // ' \u2192 \u2019 (avoid breaking the surrounding quotes)
112
+ .replace(/;/g, '\\;') // ; \u2192 \; (filter chain separator)
113
+ .replace(/,/g, '\\,') // , \u2192 \, (filter argument separator)
114
+ .replace(/:/g, '\\:') // : \u2192 \: (option separator inside drawtext)
115
+ .replace(/\[/g, '\\[')
116
+ .replace(/\]/g, '\\]')
117
+ .replace(/%/g, '%%') // drawtext format-string escape
118
+ .replace(/\n/g, ' ');
119
+ }
120
+
121
+ /**
122
+ * Detect whether a string contains CJK characters that need a CJK fontfile.
123
+ * Covers Han (CJK Unified), Hiragana, Katakana, Hangul, and full-width punctuation.
124
+ */
125
+ function containsCjk(text) {
126
+ if (!text) return false;
127
+ // U+3001–303F CJK symbols & punctuation (skip U+3000 IDEOGRAPHIC SPACE — eslint flags it)
128
+ // U+3040–30FF Hiragana + Katakana
129
+ // U+3400–9FFF CJK Ext A + CJK Unified
130
+ // U+AC00–D7AF Hangul; U+FF00–FFEF Halfwidth/Fullwidth forms
131
+ return /[、-ヿ㐀-鿿가-힯＀-￯]/.test(text);
132
+ }
133
+
134
+ /**
135
+ * Locate a fontfile that supports CJK glyphs on the host platform.
136
+ *
137
+ * ffmpeg's `drawtext` filter, when no `fontfile=` is given, falls back to a
138
+ * built-in default that ships only Latin-1. CJK content rendered without an
139
+ * explicit CJK fontfile shows as `□` tofu boxes (issue #3592).
140
+ *
141
+ * Returns an absolute path to a known CJK-capable font, or null if none of
142
+ * the platform-specific candidates exist. Cached for the process lifetime.
143
+ * Override the search via `VOXFLOW_CJK_FONT=/path/to/font.ttc`.
144
+ *
145
+ * @returns {string|null}
146
+ */
147
+ let _cjkFontPathCache; // undefined = unknown, null = absent, string = found
148
+ function findCjkFontFile() {
149
+ if (_cjkFontPathCache !== undefined) return _cjkFontPathCache;
150
+
151
+ // User override wins over platform autodetect
152
+ if (process.env.VOXFLOW_CJK_FONT && fs.existsSync(process.env.VOXFLOW_CJK_FONT)) {
153
+ _cjkFontPathCache = process.env.VOXFLOW_CJK_FONT;
154
+ return _cjkFontPathCache;
155
+ }
156
+
157
+ const candidates = [];
158
+ if (process.platform === 'darwin') {
159
+ candidates.push(
160
+ '/System/Library/Fonts/PingFang.ttc',
161
+ '/System/Library/Fonts/Hiragino Sans GB.ttc',
162
+ '/System/Library/Fonts/STHeiti Medium.ttc',
163
+ '/System/Library/Fonts/STHeiti Light.ttc',
164
+ '/Library/Fonts/Songti.ttc',
165
+ );
166
+ } else if (process.platform === 'linux') {
167
+ candidates.push(
168
+ '/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc',
169
+ '/usr/share/fonts/opentype/noto/NotoSansCJK.ttc',
170
+ '/usr/share/fonts/truetype/noto/NotoSansCJK-Regular.ttc',
171
+ '/usr/share/fonts/wqy-microhei/wqy-microhei.ttc',
172
+ '/usr/share/fonts/wqy-zenhei/wqy-zenhei.ttc',
173
+ '/usr/share/fonts/google-noto-cjk/NotoSansCJK-Regular.ttc',
174
+ );
175
+ } else if (process.platform === 'win32') {
176
+ candidates.push(
177
+ 'C:/Windows/Fonts/msyh.ttc',
178
+ 'C:/Windows/Fonts/msyhbd.ttc',
179
+ 'C:/Windows/Fonts/simsun.ttc',
180
+ 'C:/Windows/Fonts/yugothic.ttf',
181
+ );
182
+ }
183
+
184
+ for (const p of candidates) {
185
+ if (fs.existsSync(p)) {
186
+ _cjkFontPathCache = p;
187
+ return _cjkFontPathCache;
188
+ }
189
+ }
190
+ _cjkFontPathCache = null;
191
+ return null;
192
+ }
193
+
194
+ /**
195
+ * Build the drawtext fontfile= clause when the text contains CJK and a
196
+ * suitable font is available on the host. Returns either ":fontfile=…" (with
197
+ * leading colon, ready to splice into a drawtext arg list) or "" when no
198
+ * font override is needed (ASCII-only text or no CJK font on host).
199
+ */
200
+ function drawtextFontfileClause(text, cjkFontPath) {
201
+ if (!text || !cjkFontPath) return '';
202
+ if (!containsCjk(text)) return '';
203
+ // ffmpeg fontfile= path needs `:` and `\` escaped inside a filter arg.
204
+ const escaped = cjkFontPath.replace(/\\/g, '/').replace(/:/g, '\\:');
205
+ return `:fontfile='${escaped}'`;
206
+ }
207
+
208
+ // ── Render functions ──────────────────────────────────────────────────────────
209
+
210
+ /**
211
+ * Render a single card: PNG + optional WAV → MP4 clip with subtitle overlay.
212
+ */
213
+ async function renderCardClip({ pngPath, wavPath, outPath, durationMs, ratio, subtitle, hasDrawtext = false, cjkFontPath = null }) {
214
+ const { w, h } = RATIO_DIMS[ratio] || RATIO_DIMS['9:16'];
215
+ const durationSec = Math.max(3, durationMs / 1000);
216
+
217
+ // No fade between clips — hard cut. Fade-to-black causes visible
218
+ // black frames at transitions since clips are concatenated, not overlaid.
219
+ const vfParts = [
220
+ `scale=${w}:${h}:force_original_aspect_ratio=increase`,
221
+ `crop=${w}:${h}`,
222
+ ];
223
+
224
+ // Subtitle bar overlay (only if drawtext is available — checked at pipeline level)
225
+ if (subtitle && hasDrawtext) {
226
+ const escaped = escapeDrawtext(subtitle);
227
+ const fontSize = Math.round(SUB_FONT_SIZE * (w / 1080));
228
+ const boxY = h - SUB_MARGIN_BOTTOM - fontSize - SUB_PADDING * 2;
229
+ const fontfile = drawtextFontfileClause(subtitle, cjkFontPath);
230
+ vfParts.push(
231
+ `drawtext=text='${escaped}'${fontfile}:fontsize=${fontSize}:fontcolor=white:` +
232
+ `x=(w-text_w)/2:y=${boxY + SUB_PADDING}:` +
233
+ `box=1:boxcolor=black@${SUB_BOX_OPACITY}:boxborderw=${SUB_PADDING}`,
234
+ );
235
+ }
236
+
237
+ vfParts.push('format=yuv420p');
238
+
239
+ const args = ['-loop', '1', '-t', String(durationSec + 0.1), '-i', path.resolve(pngPath)];
240
+
241
+ if (wavPath) {
242
+ args.push('-i', path.resolve(wavPath));
243
+ args.push('-vf', vfParts.join(','));
244
+ args.push(
245
+ '-c:v', 'libx264', '-preset', 'fast', '-crf', '22', '-bf', '0',
246
+ '-c:a', 'aac', '-b:a', '128k', '-ar', '24000', '-ac', '1',
247
+ '-shortest',
248
+ );
249
+ } else {
250
+ args.push(
251
+ '-f', 'lavfi', '-t', String(durationSec), '-i', 'anullsrc=channel_layout=mono:sample_rate=24000',
252
+ '-vf', vfParts.join(','),
253
+ '-c:v', 'libx264', '-preset', 'fast', '-crf', '22', '-bf', '0',
254
+ '-c:a', 'aac', '-b:a', '128k',
255
+ '-t', String(durationSec),
256
+ '-shortest',
257
+ );
258
+ }
259
+
260
+ args.push('-movflags', '+faststart', '-y', path.resolve(outPath));
261
+ await runCommand('ffmpeg', args);
262
+ }
263
+
264
+ /**
265
+ * Generate an intro or outro card via FFmpeg color source (simple solid + no text).
266
+ * Text overlay requires drawtext (libfreetype); if unavailable, renders a plain color card.
267
+ */
268
+ async function renderTitleCard({ outPath, ratio, title, subtitle, durationSec = 3, bgColor = '1a1520', textColor = 'f4efe6', fadeSeconds = 0.4, isFirst = false, isLast = false, hasDrawtext = false, cjkFontPath = null }) {
269
+ const { w, h } = RATIO_DIMS[ratio] || RATIO_DIMS['9:16'];
270
+ const fd = fadeSeconds;
271
+
272
+ const titleSize = Math.round(72 * (w / 1080));
273
+ const subSize = Math.round(32 * (w / 1080));
274
+ const escapedTitle = escapeDrawtext(title || '');
275
+ const escapedSub = escapeDrawtext(subtitle || '');
276
+ const titleFontfile = drawtextFontfileClause(title, cjkFontPath);
277
+ const subFontfile = drawtextFontfileClause(subtitle, cjkFontPath);
278
+
279
+ const vfParts = [`color=c=0x${bgColor}:s=${w}x${h}:d=${durationSec}:r=30`];
280
+
281
+ if (hasDrawtext) {
282
+ if (escapedTitle) {
283
+ vfParts.push(
284
+ `drawtext=text='${escapedTitle}'${titleFontfile}:fontsize=${titleSize}:fontcolor=0x${textColor}:` +
285
+ `x=(w-text_w)/2:y=(h-text_h)/2-${Math.round(subSize * 1.5)}`,
286
+ );
287
+ }
288
+ if (escapedSub) {
289
+ vfParts.push(
290
+ `drawtext=text='${escapedSub}'${subFontfile}:fontsize=${subSize}:fontcolor=0x${textColor}@0.6:` +
291
+ `x=(w-text_w)/2:y=(h-text_h)/2+${Math.round(titleSize * 0.8)}`,
292
+ );
293
+ }
294
+ }
295
+
296
+ if (fd > 0) {
297
+ const fadeOutStart = (durationSec - fd).toFixed(3);
298
+ if (!isFirst) vfParts.push(`fade=t=in:st=0:d=${fd}`);
299
+ if (!isLast) vfParts.push(`fade=t=out:st=${fadeOutStart}:d=${fd}`);
300
+ }
301
+ vfParts.push('format=yuv420p');
302
+
303
+ const args = [
304
+ '-f', 'lavfi', '-i', vfParts.join(','),
305
+ '-f', 'lavfi', '-t', String(durationSec), '-i', 'anullsrc=channel_layout=mono:sample_rate=24000',
306
+ '-c:v', 'libx264', '-preset', 'fast', '-crf', '22',
307
+ '-c:a', 'aac', '-b:a', '128k',
308
+ '-t', String(durationSec),
309
+ '-shortest',
310
+ '-movflags', '+faststart', '-y', path.resolve(outPath),
311
+ ];
312
+
313
+ await runCommand('ffmpeg', args);
314
+ }
315
+
316
+ /**
317
+ * Mix background music into a video at low volume.
318
+ */
319
+ async function mixBgm(videoPath, bgmPath, outputPath, { volume = 0.08, fadeIn = 1.5 } = {}) {
320
+ await runCommand('ffmpeg', [
321
+ '-i', path.resolve(videoPath),
322
+ '-stream_loop', '-1',
323
+ '-i', path.resolve(bgmPath),
324
+ '-filter_complex',
325
+ `[1:a]volume=${volume},afade=t=in:st=0:d=${fadeIn}[bgm];[0:a][bgm]amix=inputs=2:duration=first:dropout_transition=2[out]`,
326
+ '-map', '0:v', '-map', '[out]',
327
+ '-c:v', 'copy', '-c:a', 'aac', '-b:a', '128k',
328
+ '-movflags', '+faststart', '-y', path.resolve(outputPath),
329
+ ]);
330
+ }
331
+
332
+ // ── Main pipeline ─────────────────────────────────────────────────────────────
333
+
334
+ async function cardRender(opts) {
335
+ const {
336
+ token, api: apiBase, dir,
337
+ noAudio = false,
338
+ noSubtitle = false, noIntro = false, noOutro = false,
339
+ bgm, bgmVolume,
340
+ pause = 2.5, // seconds of silence after narration ends (reading time)
341
+ hold = 5, // seconds to hold each card when --no-audio (no narration)
342
+ introDuration = 2.5,
343
+ outroDuration = 2,
344
+ } = opts;
345
+ const voice = opts.voice || 'female-kefu-xiaoyue';
346
+ const speed = Number(opts.speed) || 1.0;
347
+
348
+ const deck = readDeckJson(dir);
349
+ const cards = deck.cards || [];
350
+ const ratio = deck.meta?.ratio || '9:16';
351
+ const title = deck.meta?.title || '';
352
+
353
+ if (cards.length === 0) throw new Error('deck.json has no cards array entries.');
354
+
355
+ console.log(`\n=== VoxFlow Card Render ===`);
356
+ console.log(`Cards: ${cards.length} | Ratio: ${ratio} | Audio: ${!noAudio}`);
357
+ if (!noAudio) console.log(`Voice: ${voice} | Speed: ${speed}`);
358
+ console.log(`Subtitle: ${!noSubtitle} | Intro: ${!noIntro} | Outro: ${!noOutro}`);
359
+ if (bgm) console.log(`BGM: ${path.basename(bgm)}`);
360
+
361
+ const ffmpegInfo = await checkFfmpeg();
362
+ if (!ffmpegInfo.available) {
363
+ throw new Error(
364
+ 'ffmpeg not found. Install: brew install ffmpeg (macOS) / sudo apt install ffmpeg (Linux)\n' +
365
+ ' Or: npm install ffmpeg-static',
366
+ );
367
+ }
368
+ if (ffmpegInfo.source === 'ffmpeg-static') {
369
+ let pkgVersion = '';
370
+ try { pkgVersion = require('ffmpeg-static/package.json').version; } catch { /* unknown */ }
371
+ console.log(` (using ffmpeg-static${pkgVersion ? ` v${pkgVersion}` : ''} — ffmpeg ${ffmpegInfo.version})`);
372
+ }
373
+
374
+ // Check drawtext filter availability (needs libfreetype)
375
+ let hasDrawtext = false;
376
+ let cjkFontPath = null;
377
+ if (!noSubtitle) {
378
+ try {
379
+ const { stdout } = await runCommand('ffmpeg', ['-hide_banner', '-filters']);
380
+ hasDrawtext = stdout.includes('drawtext');
381
+ } catch { /* unavailable */ }
382
+ if (!hasDrawtext) {
383
+ console.log(` (drawtext unavailable — subtitles disabled)`);
384
+ } else {
385
+ // Detect CJK content in titles/narrations and locate a CJK fontfile if needed.
386
+ // ffmpeg's default drawtext font is Latin-1 only; without an explicit fontfile
387
+ // CJK characters render as `□` tofu boxes (#3592).
388
+ const allText = [
389
+ deck.meta?.title || '',
390
+ ...cards.flatMap((c) => [c.title || '', c.narration || '']),
391
+ ].join('\n');
392
+ if (containsCjk(allText)) {
393
+ cjkFontPath = findCjkFontFile();
394
+ if (cjkFontPath) {
395
+ console.log(` (CJK detected — using ${path.basename(cjkFontPath)} for overlay text)`);
396
+ } else {
397
+ console.log(` (CJK detected but no CJK font found — overlay text will show as □.`);
398
+ console.log(` Install Noto Sans CJK or set VOXFLOW_CJK_FONT=/path/to/font.ttc,`);
399
+ console.log(` or rerun with --no-subtitle --no-intro --no-outro.)`);
400
+ }
401
+ }
402
+ }
403
+ }
404
+
405
+ // Working directory for intermediate files (WAVs, clips).
406
+ // Lives inside the card dir so user can inspect on failure.
407
+ // Cleaned up on success.
408
+ const workDir = path.join(dir, '.card-render-work');
409
+ if (fs.existsSync(workDir)) {
410
+ fs.rmSync(workDir, { recursive: true, force: true });
411
+ }
412
+ fs.mkdirSync(workDir, { recursive: true });
413
+ const clipPaths = [];
414
+ let totalQuota = 0;
415
+
416
+ try {
417
+ // ── Intro card (only if drawtext available — otherwise it's just a blank dark frame) ──
418
+ if (!noIntro && title && hasDrawtext) {
419
+ console.log(` Rendering intro...`);
420
+ const introPath = path.join(workDir, 'intro.mp4');
421
+ await renderTitleCard({
422
+ outPath: introPath, ratio, title,
423
+ subtitle: deck.meta?.language === 'zh' ? '知识卡片' : 'Card Series',
424
+ durationSec: introDuration, fadeSeconds: 0,
425
+ isFirst: true, isLast: false, hasDrawtext, cjkFontPath,
426
+ });
427
+ clipPaths.push(introPath);
428
+ }
429
+
430
+ // ── Per-card clips ──────────────────────────────────────────────────────
431
+ for (let i = 0; i < cards.length; i++) {
432
+ const card = cards[i];
433
+ const pngPath = resolveCardPng(dir, card.file);
434
+ if (!pngPath) {
435
+ throw new Error(
436
+ `PNG for ${card.file} not found. Run render-cards.mjs first:\n` +
437
+ ` node cli/skills/card/scripts/render-cards.mjs --input ${dir} --output ${dir}/exports --ratio ${ratio}`,
438
+ );
439
+ }
440
+
441
+ let wavPath = null;
442
+ let durationMs = hold * 1000; // silent card hold time
443
+
444
+ if (!noAudio && card.narration) {
445
+ const { audio: pcm, quota } = await synthesizeTTS({
446
+ apiBase, token,
447
+ text: card.narration,
448
+ voiceId: voice, speed,
449
+ format: 'pcm',
450
+ index: i, total: cards.length,
451
+ });
452
+ if (quota?.costDelta) totalQuota += quota.costDelta;
453
+ const wavDest = path.join(workDir, `card-${i}.wav`);
454
+ // Bake the post-narration pause into the WAV itself — otherwise
455
+ // ffmpeg's `-shortest` truncates the clip to the narration length
456
+ // and `--pause` becomes a no-op.
457
+ writePcmAsWav(pcm, wavDest, pause);
458
+ wavPath = wavDest;
459
+ durationMs = pcmToDurationMs(pcm) + Math.round(pause * 1000); // narration + reading time
460
+ }
461
+
462
+ const clipOut = path.join(workDir, `clip-${i}.mp4`);
463
+ console.log(` Rendering card ${i + 1}/${cards.length}...`);
464
+ await renderCardClip({
465
+ pngPath, wavPath, outPath: clipOut,
466
+ durationMs, ratio, hasDrawtext, cjkFontPath,
467
+ subtitle: noSubtitle ? null : (card.narration || card.title || null),
468
+ });
469
+ clipPaths.push(clipOut);
470
+ }
471
+
472
+ // ── Outro card (only if drawtext available) ───────────────────────────
473
+ if (!noOutro && hasDrawtext) {
474
+ console.log(` Rendering outro...`);
475
+ const outroPath = path.join(workDir, 'outro.mp4');
476
+ await renderTitleCard({
477
+ outPath: outroPath, ratio,
478
+ title: 'VoxFlow',
479
+ subtitle: 'voxflow.studio',
480
+ durationSec: outroDuration, fadeSeconds: 0,
481
+ bgColor: '0d0b14',
482
+ isFirst: false, isLast: true, hasDrawtext, cjkFontPath,
483
+ });
484
+ clipPaths.push(outroPath);
485
+ }
486
+
487
+ // ── Concat ──────────────────────────────────────────────────────────────
488
+ const slug = (title
489
+ ? title.replace(/[^a-z0-9一-鿿]/gi, '-').replace(/-+/g, '-').replace(/^-|-$/g, '').toLowerCase()
490
+ : '') || 'cards';
491
+ const outputPath = path.resolve(opts.output || path.join(dir, `${slug}.mp4`));
492
+
493
+ // Ensure output directory exists
494
+ const outputDir = path.dirname(outputPath);
495
+ if (!fs.existsSync(outputDir)) {
496
+ fs.mkdirSync(outputDir, { recursive: true });
497
+ }
498
+
499
+ console.log(`\n Concatenating ${clipPaths.length} clips...`);
500
+ await concatVideos(clipPaths, outputPath, { remux: true });
501
+
502
+ // ── BGM mix ─────────────────────────────────────────────────────────────
503
+ if (bgm && fs.existsSync(bgm)) {
504
+ console.log(` Mixing BGM...`);
505
+ const withBgmPath = outputPath.replace(/\.mp4$/, '-bgm.mp4');
506
+ await mixBgm(outputPath, bgm, withBgmPath, { volume: bgmVolume || 0.08 });
507
+ fs.renameSync(withBgmPath, outputPath);
508
+ }
509
+
510
+ console.log(`\n=== Done ===`);
511
+ console.log(`Output: ${outputPath}`);
512
+ if (totalQuota > 0) console.log(`Quota used: ${totalQuota}`);
513
+
514
+ // Success — clean up work directory
515
+ fs.rmSync(workDir, { recursive: true, force: true });
516
+
517
+ return { outputPath, cardCount: cards.length, quotaUsed: totalQuota };
518
+ } catch (err) {
519
+ // Failure — keep work directory for debugging
520
+ if (fs.existsSync(workDir)) {
521
+ console.error(`\n Work directory preserved for debugging: ${workDir}`);
522
+ }
523
+ throw err;
524
+ }
525
+ }
526
+
527
+ // ── CLI handler ───────────────────────────────────────────────────────────────
528
+
529
+ async function handle(args) {
530
+ if (args.length === 0 || args[0] === '--help' || args[0] === '-h') {
531
+ console.log(`Usage: voxflow card render <dir> [options]
532
+
533
+ Options:
534
+ <dir> Card output directory (must contain deck.json + exports/*.png)
535
+
536
+ Audio:
537
+ --voice <id> TTS voice ID (default: female-kefu-xiaoyue)
538
+ --speed <n> TTS speed, 0.5-2.0 (default: 1.0)
539
+ --no-audio Silent video — skip TTS synthesis
540
+
541
+ Timing:
542
+ --pause <sec> Silence after narration before next card (default: 2.5)
543
+ --hold <sec> Duration per card in --no-audio mode (default: 5)
544
+
545
+ Structure:
546
+ --no-intro Skip intro title card
547
+ --no-outro Skip outro branding card
548
+ --intro-dur <sec> Intro card duration (default: 2.5)
549
+ --outro-dur <sec> Outro card duration (default: 2)
550
+
551
+ Overlay:
552
+ --no-subtitle Disable subtitle overlay (requires FFmpeg with libfreetype)
553
+ --bgm <path> Background music file (loops at low volume)
554
+ --bgm-volume <n> BGM volume, 0-1 (default: 0.08)
555
+
556
+ Output:
557
+ -o, --output <path> Output MP4 path (default: <dir>/<title>.mp4)
558
+
559
+ Examples:
560
+ voxflow card render cards/fermentation/
561
+ voxflow card render cards/my-set/ --voice v-female-R2s4N9qJ --pause 3
562
+ voxflow card render cards/my-set/ --no-audio --hold 4
563
+ voxflow card render cards/my-set/ --bgm ~/music/ambient.mp3 --bgm-volume 0.1
564
+ voxflow card render cards/my-set/ --no-intro --no-outro`);
565
+ return;
566
+ }
567
+
568
+ // First positional arg = directory
569
+ const valuedFlags = new Set([
570
+ '--voice', '--speed', '--output', '-o',
571
+ '--pause', '--hold', '--intro-dur', '--outro-dur',
572
+ '--bgm', '--bgm-volume', '--token', '--api',
573
+ ]);
574
+ let dir;
575
+ for (let i = 0; i < args.length; i++) {
576
+ if (args[i].startsWith('-')) { if (valuedFlags.has(args[i])) i++; continue; }
577
+ dir = args[i]; break;
578
+ }
579
+ if (!dir) { console.error('Error: provide the card output directory'); process.exit(1); }
580
+
581
+ const voice = parseFlag(args, '--voice');
582
+ const speed = parseFlag(args, '--speed');
583
+ const output = parseFlag(args, '--output', '-o');
584
+ const pauseArg = parseFlag(args, '--pause');
585
+ const holdArg = parseFlag(args, '--hold');
586
+ const introDurArg = parseFlag(args, '--intro-dur');
587
+ const outroDurArg = parseFlag(args, '--outro-dur');
588
+ const bgm = parseFlag(args, '--bgm');
589
+ const bgmVolume = parseFlag(args, '--bgm-volume');
590
+ const noAudio = args.includes('--no-audio');
591
+ const noSubtitle = args.includes('--no-subtitle');
592
+ const noIntro = args.includes('--no-intro');
593
+ const noOutro = args.includes('--no-outro');
594
+ const explicitToken = parseFlag(args, '--token');
595
+ const api = parseFlag(args, '--api') || API_BASE;
596
+
597
+ let token = explicitToken;
598
+ if (!noAudio && !token) {
599
+ token = await getToken({ api });
600
+ const info = getTokenInfo();
601
+ if (info) console.log(`\x1b[32mLogged in as ${info.email}\x1b[0m`);
602
+ }
603
+
604
+ await runWithRetry(cardRender, {
605
+ token, api,
606
+ dir: path.resolve(dir),
607
+ voice: voice || undefined,
608
+ speed: speed ? Number(speed) : undefined,
609
+ output: output || undefined,
610
+ noAudio, noSubtitle, noIntro, noOutro,
611
+ pause: pauseArg ? Number(pauseArg) : undefined,
612
+ hold: holdArg ? Number(holdArg) : undefined,
613
+ introDuration: introDurArg ? Number(introDurArg) : undefined,
614
+ outroDuration: outroDurArg ? Number(outroDurArg) : undefined,
615
+ bgm: bgm ? path.resolve(bgm) : undefined,
616
+ bgmVolume: bgmVolume ? Number(bgmVolume) : undefined,
617
+ }, api, explicitToken);
618
+ }
619
+
620
+ module.exports = {
621
+ cardRender,
622
+ readDeckJson,
623
+ resolveCardPng,
624
+ renderCardClip,
625
+ renderTitleCard,
626
+ escapeDrawtext,
627
+ writePcmAsWav,
628
+ containsCjk,
629
+ findCjkFontFile,
630
+ drawtextFontfileClause,
631
+ handle,
632
+ };