@palate/cli 0.0.0-stage → 0.0.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 (1222) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +151 -2
  3. package/bin/palate.mjs +894 -0
  4. package/kb/anatomy/data-table.md +24 -0
  5. package/kb/anatomy/empty-state.md +16 -0
  6. package/kb/anatomy/filter-toolbar.md +19 -0
  7. package/kb/anatomy/meter.md +16 -0
  8. package/kb/anatomy/product-window.md +18 -0
  9. package/kb/anatomy/settings-page.md +18 -0
  10. package/kb/anatomy/status-indicator.md +17 -0
  11. package/kb/anatomy/toast-undo.md +16 -0
  12. package/kb/bench/briefs.json +618 -0
  13. package/kb/craft/SOURCES.md +48 -0
  14. package/kb/craft/creativity.md +55 -0
  15. package/kb/craft/details.md +75 -0
  16. package/kb/craft/landing-demos.md +46 -0
  17. package/kb/craft/mistakes.md +73 -0
  18. package/kb/craft/motion.md +53 -0
  19. package/kb/craft/principles.md +68 -0
  20. package/kb/index/discovery.json +1 -0
  21. package/kb/inspiration/index.json +79 -0
  22. package/kb/moves/animated-comparison-table.md +58 -0
  23. package/kb/moves/before-after-slider.md +58 -0
  24. package/kb/moves/bento-live-tiles.md +57 -0
  25. package/kb/moves/calm-motion-system.md +63 -0
  26. package/kb/moves/canvas-grain.md +58 -0
  27. package/kb/moves/changelog-as-magazine.md +56 -0
  28. package/kb/moves/code-drawn-diagram.md +56 -0
  29. package/kb/moves/colophon.md +54 -0
  30. package/kb/moves/command-palette-site-nav.md +58 -0
  31. package/kb/moves/confetti-free-celebration.md +58 -0
  32. package/kb/moves/console-easter-egg.md +57 -0
  33. package/kb/moves/copy-confirmation.md +57 -0
  34. package/kb/moves/cursor-reactive-light.md +57 -0
  35. package/kb/moves/dark-band-contrast-section.md +55 -0
  36. package/kb/moves/designed-dark-mode.md +58 -0
  37. package/kb/moves/duotone-photography.md +55 -0
  38. package/kb/moves/editorial-drop-cap.md +58 -0
  39. package/kb/moves/editorial-grid-pull-quotes.md +55 -0
  40. package/kb/moves/engraving-colour-lens.md +64 -0
  41. package/kb/moves/explorable-control.md +57 -0
  42. package/kb/moves/feature-films-on-painted-stages.md +58 -0
  43. package/kb/moves/first-win-onboarding.md +59 -0
  44. package/kb/moves/footer-live-status.md +56 -0
  45. package/kb/moves/footer-rewards-the-end.md +58 -0
  46. package/kb/moves/generative-brand-pattern.md +55 -0
  47. package/kb/moves/gentle-error-nudge.md +59 -0
  48. package/kb/moves/halftone-dot-imagery.md +55 -0
  49. package/kb/moves/hand-drawn-annotations.md +55 -0
  50. package/kb/moves/hero-paints-itself-in.md +65 -0
  51. package/kb/moves/honest-progress-narration.md +58 -0
  52. package/kb/moves/honest-testimonial-wall.md +57 -0
  53. package/kb/moves/inline-sparklines-in-copy.md +57 -0
  54. package/kb/moves/inspect-our-taste.md +58 -0
  55. package/kb/moves/interactive-pricing-calculator.md +59 -0
  56. package/kb/moves/isometric-illustration-system.md +56 -0
  57. package/kb/moves/kinetic-variable-type.md +57 -0
  58. package/kb/moves/konami-secret.md +59 -0
  59. package/kb/moves/layered-paper-depth.md +56 -0
  60. package/kb/moves/lightweight-3d-object-hero.md +59 -0
  61. package/kb/moves/line-engraving-from-image.md +63 -0
  62. package/kb/moves/link-preview-peek.md +57 -0
  63. package/kb/moves/live-data-ticker.md +61 -0
  64. package/kb/moves/made-with-proof.md +51 -0
  65. package/kb/moves/magnetic-buttons.md +55 -0
  66. package/kb/moves/marquee-done-right.md +58 -0
  67. package/kb/moves/moves.yaml +450 -0
  68. package/kb/moves/museum-painting-backdrop.md +59 -0
  69. package/kb/moves/one-colour-brand-world.md +56 -0
  70. package/kb/moves/playful-404.md +58 -0
  71. package/kb/moves/pointer-highlight-word.md +56 -0
  72. package/kb/moves/product-in-context.md +56 -0
  73. package/kb/moves/real-world-data.md +58 -0
  74. package/kb/moves/referral-reward-reveal.md +59 -0
  75. package/kb/moves/riso-print-texture.md +57 -0
  76. package/kb/moves/screenshot-detail-crops.md +56 -0
  77. package/kb/moves/scroll-progress-chapters.md +57 -0
  78. package/kb/moves/scroll-scrubbed-product-film.md +62 -0
  79. package/kb/moves/self-playing-product-demo.md +61 -0
  80. package/kb/moves/shape-continuity-morph.md +58 -0
  81. package/kb/moves/sliding-nav-indicator.md +58 -0
  82. package/kb/moves/sticky-scroll-story.md +56 -0
  83. package/kb/moves/story-led-long-scroll.md +56 -0
  84. package/kb/moves/tactile-button.md +63 -0
  85. package/kb/moves/technical-drawing-lines.md +57 -0
  86. package/kb/moves/time-of-day-theming.md +56 -0
  87. package/kb/moves/tiny-game-easter-egg.md +60 -0
  88. package/kb/moves/type-decode-reveal.md +57 -0
  89. package/kb/moves/typographic-numeral-hero.md +58 -0
  90. package/kb/moves/view-transitions-between-pages.md +57 -0
  91. package/kb/moves/waitlist-position-live.md +60 -0
  92. package/kb/patterns/app-team-members.md +27 -0
  93. package/kb/patterns/chat-agent-approvals.md +31 -0
  94. package/kb/patterns/commerce-product-page.md +34 -0
  95. package/kb/patterns/dashboard-entity-table.md +37 -0
  96. package/kb/patterns/dashboard-home-today.md +24 -0
  97. package/kb/patterns/docs-api-reference.md +31 -0
  98. package/kb/patterns/marketing-product-led-landing.md +30 -0
  99. package/kb/patterns/mobile-daily-checklist.md +26 -0
  100. package/kb/references/index.json +1 -0
  101. package/kb/references/thumbs/004c5e9072.jpg +0 -0
  102. package/kb/references/thumbs/008915eb21.jpg +0 -0
  103. package/kb/references/thumbs/0098cf66c2.jpg +0 -0
  104. package/kb/references/thumbs/012e61b31f.jpg +0 -0
  105. package/kb/references/thumbs/014d4e46fc.jpg +0 -0
  106. package/kb/references/thumbs/01e54f394a.jpg +0 -0
  107. package/kb/references/thumbs/01e99a579c.jpg +0 -0
  108. package/kb/references/thumbs/01fd014575.jpg +0 -0
  109. package/kb/references/thumbs/022778ca72.jpg +0 -0
  110. package/kb/references/thumbs/02717bf1e1.jpg +0 -0
  111. package/kb/references/thumbs/02a5cfdbe9.jpg +0 -0
  112. package/kb/references/thumbs/02c9823f8d.jpg +0 -0
  113. package/kb/references/thumbs/02f3974613.jpg +0 -0
  114. package/kb/references/thumbs/032427f1ce.jpg +0 -0
  115. package/kb/references/thumbs/03ba677d07.jpg +0 -0
  116. package/kb/references/thumbs/04f2476cfe.jpg +0 -0
  117. package/kb/references/thumbs/0563e7c52e.jpg +0 -0
  118. package/kb/references/thumbs/05fa6b8eef.jpg +0 -0
  119. package/kb/references/thumbs/065bce1517.jpg +0 -0
  120. package/kb/references/thumbs/06c017f113.jpg +0 -0
  121. package/kb/references/thumbs/0770e2d8d3.jpg +0 -0
  122. package/kb/references/thumbs/078a26c4cb.jpg +0 -0
  123. package/kb/references/thumbs/08679b6e84.jpg +0 -0
  124. package/kb/references/thumbs/088c45a34c.jpg +0 -0
  125. package/kb/references/thumbs/089e9fd4e4.jpg +0 -0
  126. package/kb/references/thumbs/08f773231e.jpg +0 -0
  127. package/kb/references/thumbs/093ca3e2e3.jpg +0 -0
  128. package/kb/references/thumbs/0963320f74.jpg +0 -0
  129. package/kb/references/thumbs/09fc1ded85.jpg +0 -0
  130. package/kb/references/thumbs/0a368f3963.jpg +0 -0
  131. package/kb/references/thumbs/0a9e0e5201.jpg +0 -0
  132. package/kb/references/thumbs/0aace67ee7.jpg +0 -0
  133. package/kb/references/thumbs/0b61ecf793.jpg +0 -0
  134. package/kb/references/thumbs/0bde18ae09.jpg +0 -0
  135. package/kb/references/thumbs/0bf7ee8143.jpg +0 -0
  136. package/kb/references/thumbs/0ca20a13e0.jpg +0 -0
  137. package/kb/references/thumbs/0cdc0198c4.jpg +0 -0
  138. package/kb/references/thumbs/0cf9790b28.jpg +0 -0
  139. package/kb/references/thumbs/0d0202904b.jpg +0 -0
  140. package/kb/references/thumbs/0d053aba18.jpg +0 -0
  141. package/kb/references/thumbs/0d0c2c13d2.jpg +0 -0
  142. package/kb/references/thumbs/0d30be99b0.jpg +0 -0
  143. package/kb/references/thumbs/0d503da1b7.jpg +0 -0
  144. package/kb/references/thumbs/0ddad7b740.jpg +0 -0
  145. package/kb/references/thumbs/0e0a148101.jpg +0 -0
  146. package/kb/references/thumbs/0e401b6b75.jpg +0 -0
  147. package/kb/references/thumbs/0e8f32ba0f.jpg +0 -0
  148. package/kb/references/thumbs/0ef1966a7d.jpg +0 -0
  149. package/kb/references/thumbs/0efd416d11.jpg +0 -0
  150. package/kb/references/thumbs/0f3af263ae.jpg +0 -0
  151. package/kb/references/thumbs/0f9644c3a5.jpg +0 -0
  152. package/kb/references/thumbs/1020552737.jpg +0 -0
  153. package/kb/references/thumbs/1037626587.jpg +0 -0
  154. package/kb/references/thumbs/10512b7e94.jpg +0 -0
  155. package/kb/references/thumbs/106dc4a7b5.jpg +0 -0
  156. package/kb/references/thumbs/108943f6f7.jpg +0 -0
  157. package/kb/references/thumbs/10a5551d51.jpg +0 -0
  158. package/kb/references/thumbs/10dd01076c.jpg +0 -0
  159. package/kb/references/thumbs/11b06e39da.jpg +0 -0
  160. package/kb/references/thumbs/11baa1ec83.jpg +0 -0
  161. package/kb/references/thumbs/11bbe12167.jpg +0 -0
  162. package/kb/references/thumbs/11ca37feb8.jpg +0 -0
  163. package/kb/references/thumbs/11f14d3f12.jpg +0 -0
  164. package/kb/references/thumbs/124530ceb5.jpg +0 -0
  165. package/kb/references/thumbs/1276402336.jpg +0 -0
  166. package/kb/references/thumbs/1280e5c9d6.jpg +0 -0
  167. package/kb/references/thumbs/12cac0d172.jpg +0 -0
  168. package/kb/references/thumbs/138be6623a.jpg +0 -0
  169. package/kb/references/thumbs/13a0c544d1.jpg +0 -0
  170. package/kb/references/thumbs/13a32cb94c.jpg +0 -0
  171. package/kb/references/thumbs/144035d641.jpg +0 -0
  172. package/kb/references/thumbs/1457e41924.jpg +0 -0
  173. package/kb/references/thumbs/14972e3a86.jpg +0 -0
  174. package/kb/references/thumbs/15a47f2e4c.jpg +0 -0
  175. package/kb/references/thumbs/15aa15d22e.jpg +0 -0
  176. package/kb/references/thumbs/160dcd24b7.jpg +0 -0
  177. package/kb/references/thumbs/1610978529.jpg +0 -0
  178. package/kb/references/thumbs/16db30ba37.jpg +0 -0
  179. package/kb/references/thumbs/16f19ae4f3.jpg +0 -0
  180. package/kb/references/thumbs/16f758b03f.jpg +0 -0
  181. package/kb/references/thumbs/1748e5b751.jpg +0 -0
  182. package/kb/references/thumbs/175d0b0e69.jpg +0 -0
  183. package/kb/references/thumbs/178f571a36.jpg +0 -0
  184. package/kb/references/thumbs/17c43dc025.jpg +0 -0
  185. package/kb/references/thumbs/17c7f05b50.jpg +0 -0
  186. package/kb/references/thumbs/17f97e61dd.jpg +0 -0
  187. package/kb/references/thumbs/1804e17365.jpg +0 -0
  188. package/kb/references/thumbs/195c162ed1.jpg +0 -0
  189. package/kb/references/thumbs/19e3699c29.jpg +0 -0
  190. package/kb/references/thumbs/1a48e0a4d5.jpg +0 -0
  191. package/kb/references/thumbs/1a6cda265e.jpg +0 -0
  192. package/kb/references/thumbs/1a7e012091.jpg +0 -0
  193. package/kb/references/thumbs/1a9173a172.jpg +0 -0
  194. package/kb/references/thumbs/1b34a6b4d2.jpg +0 -0
  195. package/kb/references/thumbs/1b5284f3b2.jpg +0 -0
  196. package/kb/references/thumbs/1b93fbd6d3.jpg +0 -0
  197. package/kb/references/thumbs/1c6728fef6.jpg +0 -0
  198. package/kb/references/thumbs/1c6f101618.jpg +0 -0
  199. package/kb/references/thumbs/1cf7011a94.jpg +0 -0
  200. package/kb/references/thumbs/1d1769e539.jpg +0 -0
  201. package/kb/references/thumbs/1d1fd23199.jpg +0 -0
  202. package/kb/references/thumbs/1d7b6602ac.jpg +0 -0
  203. package/kb/references/thumbs/1dbbc61b9e.jpg +0 -0
  204. package/kb/references/thumbs/1dbdd6d21d.jpg +0 -0
  205. package/kb/references/thumbs/1dd873744b.jpg +0 -0
  206. package/kb/references/thumbs/1df4dd7cf9.jpg +0 -0
  207. package/kb/references/thumbs/1ece8c35b8.jpg +0 -0
  208. package/kb/references/thumbs/1f0e5b9aa4.jpg +0 -0
  209. package/kb/references/thumbs/1f1419651b.jpg +0 -0
  210. package/kb/references/thumbs/1f2a6da92d.jpg +0 -0
  211. package/kb/references/thumbs/1f651f33c0.jpg +0 -0
  212. package/kb/references/thumbs/1f8b697d18.jpg +0 -0
  213. package/kb/references/thumbs/1fee3824cd.jpg +0 -0
  214. package/kb/references/thumbs/1ff7757853.jpg +0 -0
  215. package/kb/references/thumbs/2043182f01.jpg +0 -0
  216. package/kb/references/thumbs/2059dabcd5.jpg +0 -0
  217. package/kb/references/thumbs/209d9dbb95.jpg +0 -0
  218. package/kb/references/thumbs/20d8923554.jpg +0 -0
  219. package/kb/references/thumbs/210dd3b671.jpg +0 -0
  220. package/kb/references/thumbs/2120719116.jpg +0 -0
  221. package/kb/references/thumbs/21a7384429.jpg +0 -0
  222. package/kb/references/thumbs/225f187391.jpg +0 -0
  223. package/kb/references/thumbs/230caf7dd2.jpg +0 -0
  224. package/kb/references/thumbs/235afad355.jpg +0 -0
  225. package/kb/references/thumbs/2378066687.jpg +0 -0
  226. package/kb/references/thumbs/241faf68a1.jpg +0 -0
  227. package/kb/references/thumbs/24d9f1a9b9.jpg +0 -0
  228. package/kb/references/thumbs/2505c8b9a0.jpg +0 -0
  229. package/kb/references/thumbs/25593638ca.jpg +0 -0
  230. package/kb/references/thumbs/25dd454f18.jpg +0 -0
  231. package/kb/references/thumbs/2602e123e2.jpg +0 -0
  232. package/kb/references/thumbs/26095c0b11.jpg +0 -0
  233. package/kb/references/thumbs/26260d6238.jpg +0 -0
  234. package/kb/references/thumbs/26bba21836.jpg +0 -0
  235. package/kb/references/thumbs/26bde3520b.jpg +0 -0
  236. package/kb/references/thumbs/272e22067c.jpg +0 -0
  237. package/kb/references/thumbs/27421b3226.jpg +0 -0
  238. package/kb/references/thumbs/2769ebca41.jpg +0 -0
  239. package/kb/references/thumbs/27e2f6e8b0.jpg +0 -0
  240. package/kb/references/thumbs/28432ba373.jpg +0 -0
  241. package/kb/references/thumbs/2846626f19.jpg +0 -0
  242. package/kb/references/thumbs/28750e821e.jpg +0 -0
  243. package/kb/references/thumbs/289481230f.jpg +0 -0
  244. package/kb/references/thumbs/2897967408.jpg +0 -0
  245. package/kb/references/thumbs/28c0a5fa17.jpg +0 -0
  246. package/kb/references/thumbs/28c181fba5.jpg +0 -0
  247. package/kb/references/thumbs/29806f539f.jpg +0 -0
  248. package/kb/references/thumbs/2997f56ee7.jpg +0 -0
  249. package/kb/references/thumbs/29b34a10fb.jpg +0 -0
  250. package/kb/references/thumbs/29bd78cdb4.jpg +0 -0
  251. package/kb/references/thumbs/29c8c6c22a.jpg +0 -0
  252. package/kb/references/thumbs/2ac23f7fae.jpg +0 -0
  253. package/kb/references/thumbs/2b76e13f79.jpg +0 -0
  254. package/kb/references/thumbs/2b84226479.jpg +0 -0
  255. package/kb/references/thumbs/2bf2dbf737.jpg +0 -0
  256. package/kb/references/thumbs/2bf89abbf6.jpg +0 -0
  257. package/kb/references/thumbs/2c562cd534.jpg +0 -0
  258. package/kb/references/thumbs/2cfe9d48c4.jpg +0 -0
  259. package/kb/references/thumbs/2d49f19b27.jpg +0 -0
  260. package/kb/references/thumbs/2dc8670da7.jpg +0 -0
  261. package/kb/references/thumbs/2de947c469.jpg +0 -0
  262. package/kb/references/thumbs/2e075ca79f.jpg +0 -0
  263. package/kb/references/thumbs/2eb0820e6b.jpg +0 -0
  264. package/kb/references/thumbs/2ec56a9dc0.jpg +0 -0
  265. package/kb/references/thumbs/30bb4ad607.jpg +0 -0
  266. package/kb/references/thumbs/30d19b8444.jpg +0 -0
  267. package/kb/references/thumbs/3173c71d73.jpg +0 -0
  268. package/kb/references/thumbs/31e59e4518.jpg +0 -0
  269. package/kb/references/thumbs/322b8960e8.jpg +0 -0
  270. package/kb/references/thumbs/325c9be6f4.jpg +0 -0
  271. package/kb/references/thumbs/3273338982.jpg +0 -0
  272. package/kb/references/thumbs/32f8387f38.jpg +0 -0
  273. package/kb/references/thumbs/332f6b74c3.jpg +0 -0
  274. package/kb/references/thumbs/334b146b6a.jpg +0 -0
  275. package/kb/references/thumbs/339abd60e4.jpg +0 -0
  276. package/kb/references/thumbs/33e88ec295.jpg +0 -0
  277. package/kb/references/thumbs/340931b5d4.jpg +0 -0
  278. package/kb/references/thumbs/34165a93bd.jpg +0 -0
  279. package/kb/references/thumbs/34d0575dd7.jpg +0 -0
  280. package/kb/references/thumbs/3549e75f0a.jpg +0 -0
  281. package/kb/references/thumbs/35827f1561.jpg +0 -0
  282. package/kb/references/thumbs/37c50280ec.jpg +0 -0
  283. package/kb/references/thumbs/37e66ecf11.jpg +0 -0
  284. package/kb/references/thumbs/3841a04fdc.jpg +0 -0
  285. package/kb/references/thumbs/38490c088f.jpg +0 -0
  286. package/kb/references/thumbs/3850319e9f.jpg +0 -0
  287. package/kb/references/thumbs/3856a64166.jpg +0 -0
  288. package/kb/references/thumbs/3881f211c2.jpg +0 -0
  289. package/kb/references/thumbs/38c7dde2f3.jpg +0 -0
  290. package/kb/references/thumbs/38ce9e486c.jpg +0 -0
  291. package/kb/references/thumbs/390ea8e01b.jpg +0 -0
  292. package/kb/references/thumbs/391b7fc27c.jpg +0 -0
  293. package/kb/references/thumbs/395f7214dc.jpg +0 -0
  294. package/kb/references/thumbs/39e81a5db2.jpg +0 -0
  295. package/kb/references/thumbs/3a67c8d655.jpg +0 -0
  296. package/kb/references/thumbs/3a89c25e3b.jpg +0 -0
  297. package/kb/references/thumbs/3aa0837542.jpg +0 -0
  298. package/kb/references/thumbs/3aae18aa8a.jpg +0 -0
  299. package/kb/references/thumbs/3bdbe767db.jpg +0 -0
  300. package/kb/references/thumbs/3c0616fc7f.jpg +0 -0
  301. package/kb/references/thumbs/3c18e9db1d.jpg +0 -0
  302. package/kb/references/thumbs/3c5a14076c.jpg +0 -0
  303. package/kb/references/thumbs/3ca9ec15c6.jpg +0 -0
  304. package/kb/references/thumbs/3d7756fd35.jpg +0 -0
  305. package/kb/references/thumbs/3dd45bd33d.jpg +0 -0
  306. package/kb/references/thumbs/3de72d5414.jpg +0 -0
  307. package/kb/references/thumbs/3dede597af.jpg +0 -0
  308. package/kb/references/thumbs/3ea948619e.jpg +0 -0
  309. package/kb/references/thumbs/402c12054c.jpg +0 -0
  310. package/kb/references/thumbs/403ab4af90.jpg +0 -0
  311. package/kb/references/thumbs/40773a8c63.jpg +0 -0
  312. package/kb/references/thumbs/407d9583db.jpg +0 -0
  313. package/kb/references/thumbs/415dc1d84c.jpg +0 -0
  314. package/kb/references/thumbs/420b676a4f.jpg +0 -0
  315. package/kb/references/thumbs/42a1ee85eb.jpg +0 -0
  316. package/kb/references/thumbs/43059221aa.jpg +0 -0
  317. package/kb/references/thumbs/432fa0d22c.jpg +0 -0
  318. package/kb/references/thumbs/43826f20e3.jpg +0 -0
  319. package/kb/references/thumbs/43ac55c98a.jpg +0 -0
  320. package/kb/references/thumbs/43d098f3c3.jpg +0 -0
  321. package/kb/references/thumbs/4449d80c2c.jpg +0 -0
  322. package/kb/references/thumbs/44625727dc.jpg +0 -0
  323. package/kb/references/thumbs/4482bb87a1.jpg +0 -0
  324. package/kb/references/thumbs/44b078acdc.jpg +0 -0
  325. package/kb/references/thumbs/44d0305850.jpg +0 -0
  326. package/kb/references/thumbs/456bb6b59e.jpg +0 -0
  327. package/kb/references/thumbs/45df73ce48.jpg +0 -0
  328. package/kb/references/thumbs/45edb45d87.jpg +0 -0
  329. package/kb/references/thumbs/4671d57cd5.jpg +0 -0
  330. package/kb/references/thumbs/46cc108518.jpg +0 -0
  331. package/kb/references/thumbs/470022e614.jpg +0 -0
  332. package/kb/references/thumbs/4719a669ce.jpg +0 -0
  333. package/kb/references/thumbs/47404f5ad4.jpg +0 -0
  334. package/kb/references/thumbs/479d3eb977.jpg +0 -0
  335. package/kb/references/thumbs/479ed92ceb.jpg +0 -0
  336. package/kb/references/thumbs/47baed50c7.jpg +0 -0
  337. package/kb/references/thumbs/47fdcfd7b0.jpg +0 -0
  338. package/kb/references/thumbs/48fd5e94c5.jpg +0 -0
  339. package/kb/references/thumbs/493807917b.jpg +0 -0
  340. package/kb/references/thumbs/49a1c67293.jpg +0 -0
  341. package/kb/references/thumbs/49e2d7fafe.jpg +0 -0
  342. package/kb/references/thumbs/49f540fcb6.jpg +0 -0
  343. package/kb/references/thumbs/4a67ec4028.jpg +0 -0
  344. package/kb/references/thumbs/4a93275b04.jpg +0 -0
  345. package/kb/references/thumbs/4aae6f52da.jpg +0 -0
  346. package/kb/references/thumbs/4b1bae66bd.jpg +0 -0
  347. package/kb/references/thumbs/4b75da15a9.jpg +0 -0
  348. package/kb/references/thumbs/4b77789b88.jpg +0 -0
  349. package/kb/references/thumbs/4bc2f3f3a4.jpg +0 -0
  350. package/kb/references/thumbs/4c48f27b88.jpg +0 -0
  351. package/kb/references/thumbs/4c52bd8bfb.jpg +0 -0
  352. package/kb/references/thumbs/4c9b4acc60.jpg +0 -0
  353. package/kb/references/thumbs/4cbf0752d4.jpg +0 -0
  354. package/kb/references/thumbs/4cd2672517.jpg +0 -0
  355. package/kb/references/thumbs/4dd22a8181.jpg +0 -0
  356. package/kb/references/thumbs/4ee3447314.jpg +0 -0
  357. package/kb/references/thumbs/4ef29c8144.jpg +0 -0
  358. package/kb/references/thumbs/4f82fadfd6.jpg +0 -0
  359. package/kb/references/thumbs/4fc9b643d8.jpg +0 -0
  360. package/kb/references/thumbs/50549524b0.jpg +0 -0
  361. package/kb/references/thumbs/509a615883.jpg +0 -0
  362. package/kb/references/thumbs/50c03ef855.jpg +0 -0
  363. package/kb/references/thumbs/50cf9acad6.jpg +0 -0
  364. package/kb/references/thumbs/51131b025c.jpg +0 -0
  365. package/kb/references/thumbs/51da1124f0.jpg +0 -0
  366. package/kb/references/thumbs/524d5e7288.jpg +0 -0
  367. package/kb/references/thumbs/5251247c81.jpg +0 -0
  368. package/kb/references/thumbs/526b91b7ec.jpg +0 -0
  369. package/kb/references/thumbs/52f02f6c2e.jpg +0 -0
  370. package/kb/references/thumbs/530ab530dc.jpg +0 -0
  371. package/kb/references/thumbs/5335ee4404.jpg +0 -0
  372. package/kb/references/thumbs/5385b90939.jpg +0 -0
  373. package/kb/references/thumbs/53c54654cc.jpg +0 -0
  374. package/kb/references/thumbs/5420794c6c.jpg +0 -0
  375. package/kb/references/thumbs/542a9dce8b.jpg +0 -0
  376. package/kb/references/thumbs/5571530a5f.jpg +0 -0
  377. package/kb/references/thumbs/56cc68d804.jpg +0 -0
  378. package/kb/references/thumbs/577b7f7c44.jpg +0 -0
  379. package/kb/references/thumbs/57adf8f1bb.jpg +0 -0
  380. package/kb/references/thumbs/57c5f5e3a6.jpg +0 -0
  381. package/kb/references/thumbs/57ffe4e839.jpg +0 -0
  382. package/kb/references/thumbs/5817dfc7d6.jpg +0 -0
  383. package/kb/references/thumbs/581a182a7a.jpg +0 -0
  384. package/kb/references/thumbs/58807679c8.jpg +0 -0
  385. package/kb/references/thumbs/589a1d9111.jpg +0 -0
  386. package/kb/references/thumbs/59167391ab.jpg +0 -0
  387. package/kb/references/thumbs/5a70420166.jpg +0 -0
  388. package/kb/references/thumbs/5b10df1b8d.jpg +0 -0
  389. package/kb/references/thumbs/5b7a712fdb.jpg +0 -0
  390. package/kb/references/thumbs/5bc46b92ad.jpg +0 -0
  391. package/kb/references/thumbs/5c0546a120.jpg +0 -0
  392. package/kb/references/thumbs/5c2b6125a8.jpg +0 -0
  393. package/kb/references/thumbs/5c536b9e42.jpg +0 -0
  394. package/kb/references/thumbs/5c8e441d30.jpg +0 -0
  395. package/kb/references/thumbs/5cb6f1baa5.jpg +0 -0
  396. package/kb/references/thumbs/5ce6c1f21e.jpg +0 -0
  397. package/kb/references/thumbs/5cef052c0a.jpg +0 -0
  398. package/kb/references/thumbs/5d08438209.jpg +0 -0
  399. package/kb/references/thumbs/5d0f9af9b0.jpg +0 -0
  400. package/kb/references/thumbs/5d300ed332.jpg +0 -0
  401. package/kb/references/thumbs/5d708a4794.jpg +0 -0
  402. package/kb/references/thumbs/5de8826a98.jpg +0 -0
  403. package/kb/references/thumbs/5df7bff22c.jpg +0 -0
  404. package/kb/references/thumbs/5e087d0f00.jpg +0 -0
  405. package/kb/references/thumbs/5e44e70ca0.jpg +0 -0
  406. package/kb/references/thumbs/5eff5d80ce.jpg +0 -0
  407. package/kb/references/thumbs/5f015c96b1.jpg +0 -0
  408. package/kb/references/thumbs/5f3289b7c4.jpg +0 -0
  409. package/kb/references/thumbs/5f830c40eb.jpg +0 -0
  410. package/kb/references/thumbs/60c4c3527b.jpg +0 -0
  411. package/kb/references/thumbs/60e9e594dd.jpg +0 -0
  412. package/kb/references/thumbs/615421d7be.jpg +0 -0
  413. package/kb/references/thumbs/6176e4004f.jpg +0 -0
  414. package/kb/references/thumbs/61f0fe5e06.jpg +0 -0
  415. package/kb/references/thumbs/6213785db4.jpg +0 -0
  416. package/kb/references/thumbs/62a670ae09.jpg +0 -0
  417. package/kb/references/thumbs/63cc12981b.jpg +0 -0
  418. package/kb/references/thumbs/641f15cc71.jpg +0 -0
  419. package/kb/references/thumbs/642ab2081d.jpg +0 -0
  420. package/kb/references/thumbs/644a59bf6e.jpg +0 -0
  421. package/kb/references/thumbs/644da8a8e3.jpg +0 -0
  422. package/kb/references/thumbs/6458986897.jpg +0 -0
  423. package/kb/references/thumbs/64cfbd7b93.jpg +0 -0
  424. package/kb/references/thumbs/661a57686a.jpg +0 -0
  425. package/kb/references/thumbs/66355a813a.jpg +0 -0
  426. package/kb/references/thumbs/664396dd44.jpg +0 -0
  427. package/kb/references/thumbs/66d832d65f.jpg +0 -0
  428. package/kb/references/thumbs/66de9e9833.jpg +0 -0
  429. package/kb/references/thumbs/6750964fd9.jpg +0 -0
  430. package/kb/references/thumbs/67c7164832.jpg +0 -0
  431. package/kb/references/thumbs/681600b6cd.jpg +0 -0
  432. package/kb/references/thumbs/682e75afe4.jpg +0 -0
  433. package/kb/references/thumbs/69274bc952.jpg +0 -0
  434. package/kb/references/thumbs/696ec08c52.jpg +0 -0
  435. package/kb/references/thumbs/69760111cc.jpg +0 -0
  436. package/kb/references/thumbs/697e32664f.jpg +0 -0
  437. package/kb/references/thumbs/69df92544b.jpg +0 -0
  438. package/kb/references/thumbs/69e48c5229.jpg +0 -0
  439. package/kb/references/thumbs/6a5fb75de1.jpg +0 -0
  440. package/kb/references/thumbs/6a7389e472.jpg +0 -0
  441. package/kb/references/thumbs/6a9b041e02.jpg +0 -0
  442. package/kb/references/thumbs/6ab2fa93ee.jpg +0 -0
  443. package/kb/references/thumbs/6ae3400319.jpg +0 -0
  444. package/kb/references/thumbs/6b21344bf3.jpg +0 -0
  445. package/kb/references/thumbs/6bd1b67a8a.jpg +0 -0
  446. package/kb/references/thumbs/6c99156c4f.jpg +0 -0
  447. package/kb/references/thumbs/6cc9b65384.jpg +0 -0
  448. package/kb/references/thumbs/6d15830a73.jpg +0 -0
  449. package/kb/references/thumbs/6d4c33d180.jpg +0 -0
  450. package/kb/references/thumbs/6e36815799.jpg +0 -0
  451. package/kb/references/thumbs/6eddb9cbfc.jpg +0 -0
  452. package/kb/references/thumbs/6f97968a7c.jpg +0 -0
  453. package/kb/references/thumbs/6fa0716a7d.jpg +0 -0
  454. package/kb/references/thumbs/6facd57184.jpg +0 -0
  455. package/kb/references/thumbs/6fd57b785a.jpg +0 -0
  456. package/kb/references/thumbs/700b3cb185.jpg +0 -0
  457. package/kb/references/thumbs/71197443fa.jpg +0 -0
  458. package/kb/references/thumbs/72082bc9ee.jpg +0 -0
  459. package/kb/references/thumbs/72453db479.jpg +0 -0
  460. package/kb/references/thumbs/72cd64d500.jpg +0 -0
  461. package/kb/references/thumbs/72d1e75283.jpg +0 -0
  462. package/kb/references/thumbs/72e13f7f5b.jpg +0 -0
  463. package/kb/references/thumbs/7459f8e644.jpg +0 -0
  464. package/kb/references/thumbs/7470d55c79.jpg +0 -0
  465. package/kb/references/thumbs/74c468f02a.jpg +0 -0
  466. package/kb/references/thumbs/74fed6eb77.jpg +0 -0
  467. package/kb/references/thumbs/756e05080d.jpg +0 -0
  468. package/kb/references/thumbs/75df7e5f49.jpg +0 -0
  469. package/kb/references/thumbs/76226da6ef.jpg +0 -0
  470. package/kb/references/thumbs/76a34aa056.jpg +0 -0
  471. package/kb/references/thumbs/76c7076589.jpg +0 -0
  472. package/kb/references/thumbs/76cccc396c.jpg +0 -0
  473. package/kb/references/thumbs/774654789f.jpg +0 -0
  474. package/kb/references/thumbs/7746cc494d.jpg +0 -0
  475. package/kb/references/thumbs/7766e36aa3.jpg +0 -0
  476. package/kb/references/thumbs/78049331ef.jpg +0 -0
  477. package/kb/references/thumbs/78808a0ca5.jpg +0 -0
  478. package/kb/references/thumbs/7890b0a310.jpg +0 -0
  479. package/kb/references/thumbs/78911975e6.jpg +0 -0
  480. package/kb/references/thumbs/78d289d5a0.jpg +0 -0
  481. package/kb/references/thumbs/794126267e.jpg +0 -0
  482. package/kb/references/thumbs/7976eb9025.jpg +0 -0
  483. package/kb/references/thumbs/798519ec7c.jpg +0 -0
  484. package/kb/references/thumbs/7a6cc5eecc.jpg +0 -0
  485. package/kb/references/thumbs/7ac8a7cd4a.jpg +0 -0
  486. package/kb/references/thumbs/7b1341d61d.jpg +0 -0
  487. package/kb/references/thumbs/7b9c4031e3.jpg +0 -0
  488. package/kb/references/thumbs/7ba5ad3779.jpg +0 -0
  489. package/kb/references/thumbs/7be6eb2bd0.jpg +0 -0
  490. package/kb/references/thumbs/7c30864f5d.jpg +0 -0
  491. package/kb/references/thumbs/7c379b5e17.jpg +0 -0
  492. package/kb/references/thumbs/7c4050eb02.jpg +0 -0
  493. package/kb/references/thumbs/7ca47b3221.jpg +0 -0
  494. package/kb/references/thumbs/7d43516bd7.jpg +0 -0
  495. package/kb/references/thumbs/7da9dbb98a.jpg +0 -0
  496. package/kb/references/thumbs/7ddda8f57c.jpg +0 -0
  497. package/kb/references/thumbs/7ece6d215c.jpg +0 -0
  498. package/kb/references/thumbs/7eebf029de.jpg +0 -0
  499. package/kb/references/thumbs/7f45483c15.jpg +0 -0
  500. package/kb/references/thumbs/7fde06eaa5.jpg +0 -0
  501. package/kb/references/thumbs/80407b97e9.jpg +0 -0
  502. package/kb/references/thumbs/80f0a6cf4b.jpg +0 -0
  503. package/kb/references/thumbs/8118b451b8.jpg +0 -0
  504. package/kb/references/thumbs/816baed4a8.jpg +0 -0
  505. package/kb/references/thumbs/817d2d15d9.jpg +0 -0
  506. package/kb/references/thumbs/8260cb430d.jpg +0 -0
  507. package/kb/references/thumbs/827b562899.jpg +0 -0
  508. package/kb/references/thumbs/8293cf1e92.jpg +0 -0
  509. package/kb/references/thumbs/8294653169.jpg +0 -0
  510. package/kb/references/thumbs/83061f871f.jpg +0 -0
  511. package/kb/references/thumbs/833df778ca.jpg +0 -0
  512. package/kb/references/thumbs/83d3acaafc.jpg +0 -0
  513. package/kb/references/thumbs/844c6efeff.jpg +0 -0
  514. package/kb/references/thumbs/84563d482a.jpg +0 -0
  515. package/kb/references/thumbs/848082dd94.jpg +0 -0
  516. package/kb/references/thumbs/8494b1da94.jpg +0 -0
  517. package/kb/references/thumbs/84b71014be.jpg +0 -0
  518. package/kb/references/thumbs/84be4a5f3c.jpg +0 -0
  519. package/kb/references/thumbs/84fd0fd25a.jpg +0 -0
  520. package/kb/references/thumbs/853e488e22.jpg +0 -0
  521. package/kb/references/thumbs/858c91585d.jpg +0 -0
  522. package/kb/references/thumbs/85903e8fe9.jpg +0 -0
  523. package/kb/references/thumbs/86597d43fd.jpg +0 -0
  524. package/kb/references/thumbs/866eb99500.jpg +0 -0
  525. package/kb/references/thumbs/86ac050340.jpg +0 -0
  526. package/kb/references/thumbs/86afec7b64.jpg +0 -0
  527. package/kb/references/thumbs/87238127f5.jpg +0 -0
  528. package/kb/references/thumbs/87321df792.jpg +0 -0
  529. package/kb/references/thumbs/87460f70cd.jpg +0 -0
  530. package/kb/references/thumbs/8770dfeaec.jpg +0 -0
  531. package/kb/references/thumbs/8798451a8c.jpg +0 -0
  532. package/kb/references/thumbs/87da1f34a3.jpg +0 -0
  533. package/kb/references/thumbs/882cdf8c05.jpg +0 -0
  534. package/kb/references/thumbs/8839f4106f.jpg +0 -0
  535. package/kb/references/thumbs/8844455212.jpg +0 -0
  536. package/kb/references/thumbs/88abba0497.jpg +0 -0
  537. package/kb/references/thumbs/88b372435d.jpg +0 -0
  538. package/kb/references/thumbs/88bd4f35fa.jpg +0 -0
  539. package/kb/references/thumbs/88c71a075e.jpg +0 -0
  540. package/kb/references/thumbs/892e5f048e.jpg +0 -0
  541. package/kb/references/thumbs/893cc8e920.jpg +0 -0
  542. package/kb/references/thumbs/896c198814.jpg +0 -0
  543. package/kb/references/thumbs/8a8e22f756.jpg +0 -0
  544. package/kb/references/thumbs/8a9d8a35cb.jpg +0 -0
  545. package/kb/references/thumbs/8ab1d67fec.jpg +0 -0
  546. package/kb/references/thumbs/8ab201fe12.jpg +0 -0
  547. package/kb/references/thumbs/8ac372c102.jpg +0 -0
  548. package/kb/references/thumbs/8b15736d62.jpg +0 -0
  549. package/kb/references/thumbs/8b1d8d6a05.jpg +0 -0
  550. package/kb/references/thumbs/8bb6050e20.jpg +0 -0
  551. package/kb/references/thumbs/8c6c9d1577.jpg +0 -0
  552. package/kb/references/thumbs/8d337851e0.jpg +0 -0
  553. package/kb/references/thumbs/8d44b33cc5.jpg +0 -0
  554. package/kb/references/thumbs/8d4536ff3b.jpg +0 -0
  555. package/kb/references/thumbs/8d9b99454a.jpg +0 -0
  556. package/kb/references/thumbs/8dda2303ff.jpg +0 -0
  557. package/kb/references/thumbs/8dec722d62.jpg +0 -0
  558. package/kb/references/thumbs/8e0ea4ca74.jpg +0 -0
  559. package/kb/references/thumbs/8ebba84d69.jpg +0 -0
  560. package/kb/references/thumbs/8ef09140c0.jpg +0 -0
  561. package/kb/references/thumbs/8f2928a1b0.jpg +0 -0
  562. package/kb/references/thumbs/8f88f9ddba.jpg +0 -0
  563. package/kb/references/thumbs/8fa4451009.jpg +0 -0
  564. package/kb/references/thumbs/90109b0e02.jpg +0 -0
  565. package/kb/references/thumbs/90e854e5c9.jpg +0 -0
  566. package/kb/references/thumbs/914e79f893.jpg +0 -0
  567. package/kb/references/thumbs/9161369197.jpg +0 -0
  568. package/kb/references/thumbs/9165c87d6f.jpg +0 -0
  569. package/kb/references/thumbs/9193f6558a.jpg +0 -0
  570. package/kb/references/thumbs/91ac7df877.jpg +0 -0
  571. package/kb/references/thumbs/9216bd4931.jpg +0 -0
  572. package/kb/references/thumbs/922ae8a26a.jpg +0 -0
  573. package/kb/references/thumbs/92a70e6867.jpg +0 -0
  574. package/kb/references/thumbs/92c77ece22.jpg +0 -0
  575. package/kb/references/thumbs/92e5914fbf.jpg +0 -0
  576. package/kb/references/thumbs/92ee36419a.jpg +0 -0
  577. package/kb/references/thumbs/94153a60b0.jpg +0 -0
  578. package/kb/references/thumbs/9449666640.jpg +0 -0
  579. package/kb/references/thumbs/944be6a646.jpg +0 -0
  580. package/kb/references/thumbs/945831476e.jpg +0 -0
  581. package/kb/references/thumbs/94c1af82f4.jpg +0 -0
  582. package/kb/references/thumbs/9599d6d589.jpg +0 -0
  583. package/kb/references/thumbs/960710f4cf.jpg +0 -0
  584. package/kb/references/thumbs/9608f12d64.jpg +0 -0
  585. package/kb/references/thumbs/962dabfaa0.jpg +0 -0
  586. package/kb/references/thumbs/965a3a95c6.jpg +0 -0
  587. package/kb/references/thumbs/9672ed5ae4.jpg +0 -0
  588. package/kb/references/thumbs/96891ae9c1.jpg +0 -0
  589. package/kb/references/thumbs/96e1907c99.jpg +0 -0
  590. package/kb/references/thumbs/96f25b6578.jpg +0 -0
  591. package/kb/references/thumbs/97211df9ae.jpg +0 -0
  592. package/kb/references/thumbs/9769d763a5.jpg +0 -0
  593. package/kb/references/thumbs/9792bd6d05.jpg +0 -0
  594. package/kb/references/thumbs/97d2837e3e.jpg +0 -0
  595. package/kb/references/thumbs/97d90d1d85.jpg +0 -0
  596. package/kb/references/thumbs/97fcd5774a.jpg +0 -0
  597. package/kb/references/thumbs/980f68564e.jpg +0 -0
  598. package/kb/references/thumbs/98511fb393.jpg +0 -0
  599. package/kb/references/thumbs/98f8fa694d.jpg +0 -0
  600. package/kb/references/thumbs/9a42c6bb97.jpg +0 -0
  601. package/kb/references/thumbs/9ab3600a06.jpg +0 -0
  602. package/kb/references/thumbs/9ab48d9130.jpg +0 -0
  603. package/kb/references/thumbs/9ad519197d.jpg +0 -0
  604. package/kb/references/thumbs/9b1382c657.jpg +0 -0
  605. package/kb/references/thumbs/9b6cc1e077.jpg +0 -0
  606. package/kb/references/thumbs/9beede8480.jpg +0 -0
  607. package/kb/references/thumbs/9bf8976952.jpg +0 -0
  608. package/kb/references/thumbs/9cace7b75a.jpg +0 -0
  609. package/kb/references/thumbs/9cdcc5745e.jpg +0 -0
  610. package/kb/references/thumbs/9d0b269074.jpg +0 -0
  611. package/kb/references/thumbs/9d41788b48.jpg +0 -0
  612. package/kb/references/thumbs/9d475bd6af.jpg +0 -0
  613. package/kb/references/thumbs/9e6bc543d0.jpg +0 -0
  614. package/kb/references/thumbs/9ed0e0a206.jpg +0 -0
  615. package/kb/references/thumbs/9ef538de13.jpg +0 -0
  616. package/kb/references/thumbs/9efc373ab4.jpg +0 -0
  617. package/kb/references/thumbs/9f4a939fa5.jpg +0 -0
  618. package/kb/references/thumbs/9f8d12d7b9.jpg +0 -0
  619. package/kb/references/thumbs/9fd5e3efa7.jpg +0 -0
  620. package/kb/references/thumbs/a0a9b9c572.jpg +0 -0
  621. package/kb/references/thumbs/a29ca9b185.jpg +0 -0
  622. package/kb/references/thumbs/a2a42884af.jpg +0 -0
  623. package/kb/references/thumbs/a2f5064e34.jpg +0 -0
  624. package/kb/references/thumbs/a3112ce672.jpg +0 -0
  625. package/kb/references/thumbs/a3437736d1.jpg +0 -0
  626. package/kb/references/thumbs/a372667e76.jpg +0 -0
  627. package/kb/references/thumbs/a39bae94e9.jpg +0 -0
  628. package/kb/references/thumbs/a3fc75d94c.jpg +0 -0
  629. package/kb/references/thumbs/a440487631.jpg +0 -0
  630. package/kb/references/thumbs/a4993d5fb5.jpg +0 -0
  631. package/kb/references/thumbs/a500476a86.jpg +0 -0
  632. package/kb/references/thumbs/a55506bf46.jpg +0 -0
  633. package/kb/references/thumbs/a59a5f9843.jpg +0 -0
  634. package/kb/references/thumbs/a5bce0eede.jpg +0 -0
  635. package/kb/references/thumbs/a5d921e1f0.jpg +0 -0
  636. package/kb/references/thumbs/a5e19d4637.jpg +0 -0
  637. package/kb/references/thumbs/a5f92b97d5.jpg +0 -0
  638. package/kb/references/thumbs/a6562c210a.jpg +0 -0
  639. package/kb/references/thumbs/a6f61a8d09.jpg +0 -0
  640. package/kb/references/thumbs/a719fdf663.jpg +0 -0
  641. package/kb/references/thumbs/a724e5442f.jpg +0 -0
  642. package/kb/references/thumbs/a852b4319f.jpg +0 -0
  643. package/kb/references/thumbs/a896c08448.jpg +0 -0
  644. package/kb/references/thumbs/a8d190a4b8.jpg +0 -0
  645. package/kb/references/thumbs/a8dcdd57d7.jpg +0 -0
  646. package/kb/references/thumbs/a951347e18.jpg +0 -0
  647. package/kb/references/thumbs/a9a1a0bf7d.jpg +0 -0
  648. package/kb/references/thumbs/a9b72986a8.jpg +0 -0
  649. package/kb/references/thumbs/aa11555ba8.jpg +0 -0
  650. package/kb/references/thumbs/aa4aab9093.jpg +0 -0
  651. package/kb/references/thumbs/aa89b96658.jpg +0 -0
  652. package/kb/references/thumbs/aaeb3739b6.jpg +0 -0
  653. package/kb/references/thumbs/ab25a608ec.jpg +0 -0
  654. package/kb/references/thumbs/ab34b62268.jpg +0 -0
  655. package/kb/references/thumbs/ab3b0217bb.jpg +0 -0
  656. package/kb/references/thumbs/ac70c04afb.jpg +0 -0
  657. package/kb/references/thumbs/ace0879117.jpg +0 -0
  658. package/kb/references/thumbs/ad0515ae55.jpg +0 -0
  659. package/kb/references/thumbs/ad66b25b47.jpg +0 -0
  660. package/kb/references/thumbs/ad68229d2f.jpg +0 -0
  661. package/kb/references/thumbs/add6480693.jpg +0 -0
  662. package/kb/references/thumbs/ae5b8c3b8c.jpg +0 -0
  663. package/kb/references/thumbs/ae81247b47.jpg +0 -0
  664. package/kb/references/thumbs/af8aa54379.jpg +0 -0
  665. package/kb/references/thumbs/afa80dedd4.jpg +0 -0
  666. package/kb/references/thumbs/afe04d730f.jpg +0 -0
  667. package/kb/references/thumbs/b09a7dc315.jpg +0 -0
  668. package/kb/references/thumbs/b0c02629f6.jpg +0 -0
  669. package/kb/references/thumbs/b1cb4f91de.jpg +0 -0
  670. package/kb/references/thumbs/b1d4c13c92.jpg +0 -0
  671. package/kb/references/thumbs/b20eef86db.jpg +0 -0
  672. package/kb/references/thumbs/b3136ccdde.jpg +0 -0
  673. package/kb/references/thumbs/b3f5e8d7dd.jpg +0 -0
  674. package/kb/references/thumbs/b44adb81c9.jpg +0 -0
  675. package/kb/references/thumbs/b457a5894b.jpg +0 -0
  676. package/kb/references/thumbs/b461281e0f.jpg +0 -0
  677. package/kb/references/thumbs/b4942644f0.jpg +0 -0
  678. package/kb/references/thumbs/b49f8eccad.jpg +0 -0
  679. package/kb/references/thumbs/b56c69be23.jpg +0 -0
  680. package/kb/references/thumbs/b59786b33c.jpg +0 -0
  681. package/kb/references/thumbs/b5d368ce5a.jpg +0 -0
  682. package/kb/references/thumbs/b5eb442406.jpg +0 -0
  683. package/kb/references/thumbs/b7fdabf4ab.jpg +0 -0
  684. package/kb/references/thumbs/b88ee8d235.jpg +0 -0
  685. package/kb/references/thumbs/b8a4e5be8a.jpg +0 -0
  686. package/kb/references/thumbs/b8c85b661c.jpg +0 -0
  687. package/kb/references/thumbs/ba1b8e7435.jpg +0 -0
  688. package/kb/references/thumbs/ba9a593eed.jpg +0 -0
  689. package/kb/references/thumbs/baa7afc201.jpg +0 -0
  690. package/kb/references/thumbs/baf74398f7.jpg +0 -0
  691. package/kb/references/thumbs/bb3e947c10.jpg +0 -0
  692. package/kb/references/thumbs/bb4c1bb7c1.jpg +0 -0
  693. package/kb/references/thumbs/bbaa25cc8a.jpg +0 -0
  694. package/kb/references/thumbs/bc7e7f88cc.jpg +0 -0
  695. package/kb/references/thumbs/bc9d5b58f5.jpg +0 -0
  696. package/kb/references/thumbs/bcc99a51f7.jpg +0 -0
  697. package/kb/references/thumbs/bce13dd1c1.jpg +0 -0
  698. package/kb/references/thumbs/bd079a6130.jpg +0 -0
  699. package/kb/references/thumbs/bd2d70dda7.jpg +0 -0
  700. package/kb/references/thumbs/bd5895c5f2.jpg +0 -0
  701. package/kb/references/thumbs/bde8e31d62.jpg +0 -0
  702. package/kb/references/thumbs/be084e78f3.jpg +0 -0
  703. package/kb/references/thumbs/be94f170c8.jpg +0 -0
  704. package/kb/references/thumbs/bed33654f7.jpg +0 -0
  705. package/kb/references/thumbs/beeb9a0c18.jpg +0 -0
  706. package/kb/references/thumbs/bef42094dc.jpg +0 -0
  707. package/kb/references/thumbs/bf625496fa.jpg +0 -0
  708. package/kb/references/thumbs/bf771f1398.jpg +0 -0
  709. package/kb/references/thumbs/c0ddefa3d9.jpg +0 -0
  710. package/kb/references/thumbs/c0f01e536e.jpg +0 -0
  711. package/kb/references/thumbs/c1d592b678.jpg +0 -0
  712. package/kb/references/thumbs/c1e83e1b3e.jpg +0 -0
  713. package/kb/references/thumbs/c2168f8096.jpg +0 -0
  714. package/kb/references/thumbs/c249cd6b17.jpg +0 -0
  715. package/kb/references/thumbs/c2e3d4feed.jpg +0 -0
  716. package/kb/references/thumbs/c3cec01df1.jpg +0 -0
  717. package/kb/references/thumbs/c47bedb42d.jpg +0 -0
  718. package/kb/references/thumbs/c4b03b4680.jpg +0 -0
  719. package/kb/references/thumbs/c4e6d18ec3.jpg +0 -0
  720. package/kb/references/thumbs/c5477e2877.jpg +0 -0
  721. package/kb/references/thumbs/c566794674.jpg +0 -0
  722. package/kb/references/thumbs/c5b945afbb.jpg +0 -0
  723. package/kb/references/thumbs/c5e4659497.jpg +0 -0
  724. package/kb/references/thumbs/c622786702.jpg +0 -0
  725. package/kb/references/thumbs/c6250649ca.jpg +0 -0
  726. package/kb/references/thumbs/c6261a9526.jpg +0 -0
  727. package/kb/references/thumbs/c62e609076.jpg +0 -0
  728. package/kb/references/thumbs/c6602d3e85.jpg +0 -0
  729. package/kb/references/thumbs/c6c1a16e40.jpg +0 -0
  730. package/kb/references/thumbs/c77f932157.jpg +0 -0
  731. package/kb/references/thumbs/c79788f01e.jpg +0 -0
  732. package/kb/references/thumbs/c7a511ad1e.jpg +0 -0
  733. package/kb/references/thumbs/c7acfbc3c8.jpg +0 -0
  734. package/kb/references/thumbs/c7bb6d1bb8.jpg +0 -0
  735. package/kb/references/thumbs/c829eadcb9.jpg +0 -0
  736. package/kb/references/thumbs/c891fd9d85.jpg +0 -0
  737. package/kb/references/thumbs/c89f812ee3.jpg +0 -0
  738. package/kb/references/thumbs/c8a85b9f61.jpg +0 -0
  739. package/kb/references/thumbs/c8fdf85c9a.jpg +0 -0
  740. package/kb/references/thumbs/c961ac1031.jpg +0 -0
  741. package/kb/references/thumbs/c9fd3f88d8.jpg +0 -0
  742. package/kb/references/thumbs/ca0d6399c3.jpg +0 -0
  743. package/kb/references/thumbs/ca316c83e4.jpg +0 -0
  744. package/kb/references/thumbs/ca3b93aa0d.jpg +0 -0
  745. package/kb/references/thumbs/cb0596a85b.jpg +0 -0
  746. package/kb/references/thumbs/cb95a5c3ef.jpg +0 -0
  747. package/kb/references/thumbs/cbe238b656.jpg +0 -0
  748. package/kb/references/thumbs/cbf530e608.jpg +0 -0
  749. package/kb/references/thumbs/cc173494ec.jpg +0 -0
  750. package/kb/references/thumbs/ccb664bddf.jpg +0 -0
  751. package/kb/references/thumbs/ccf69d36cd.jpg +0 -0
  752. package/kb/references/thumbs/ccf759db42.jpg +0 -0
  753. package/kb/references/thumbs/cd2a285807.jpg +0 -0
  754. package/kb/references/thumbs/cd4a24a8ca.jpg +0 -0
  755. package/kb/references/thumbs/cdb3fe8938.jpg +0 -0
  756. package/kb/references/thumbs/cdce1b9bc6.jpg +0 -0
  757. package/kb/references/thumbs/cde3aa761a.jpg +0 -0
  758. package/kb/references/thumbs/ce9d5cd9c2.jpg +0 -0
  759. package/kb/references/thumbs/ceb01f8a34.jpg +0 -0
  760. package/kb/references/thumbs/cee15c98d0.jpg +0 -0
  761. package/kb/references/thumbs/cf6944ddae.jpg +0 -0
  762. package/kb/references/thumbs/d15dd21cd8.jpg +0 -0
  763. package/kb/references/thumbs/d1633bf2ed.jpg +0 -0
  764. package/kb/references/thumbs/d16a838000.jpg +0 -0
  765. package/kb/references/thumbs/d1cf87e9f0.jpg +0 -0
  766. package/kb/references/thumbs/d32511d913.jpg +0 -0
  767. package/kb/references/thumbs/d327e9dedd.jpg +0 -0
  768. package/kb/references/thumbs/d35bf6c85e.jpg +0 -0
  769. package/kb/references/thumbs/d37afc9d61.jpg +0 -0
  770. package/kb/references/thumbs/d3b66655c7.jpg +0 -0
  771. package/kb/references/thumbs/d40b4172b6.jpg +0 -0
  772. package/kb/references/thumbs/d4c40d1824.jpg +0 -0
  773. package/kb/references/thumbs/d4cb55a4b6.jpg +0 -0
  774. package/kb/references/thumbs/d4f0c30f7e.jpg +0 -0
  775. package/kb/references/thumbs/d51cce3ae5.jpg +0 -0
  776. package/kb/references/thumbs/d52948f9ba.jpg +0 -0
  777. package/kb/references/thumbs/d62bd3cba4.jpg +0 -0
  778. package/kb/references/thumbs/d668a21c92.jpg +0 -0
  779. package/kb/references/thumbs/d685072c52.jpg +0 -0
  780. package/kb/references/thumbs/d6d7b96093.jpg +0 -0
  781. package/kb/references/thumbs/d7cd874b21.jpg +0 -0
  782. package/kb/references/thumbs/d7e111736a.jpg +0 -0
  783. package/kb/references/thumbs/d88325f832.jpg +0 -0
  784. package/kb/references/thumbs/d9272ded76.jpg +0 -0
  785. package/kb/references/thumbs/d962e7c654.jpg +0 -0
  786. package/kb/references/thumbs/d97f000ee2.jpg +0 -0
  787. package/kb/references/thumbs/d9c1ae2543.jpg +0 -0
  788. package/kb/references/thumbs/d9ccb3cac8.jpg +0 -0
  789. package/kb/references/thumbs/da99019680.jpg +0 -0
  790. package/kb/references/thumbs/da9b8bc615.jpg +0 -0
  791. package/kb/references/thumbs/daafbee2c1.jpg +0 -0
  792. package/kb/references/thumbs/db0f11f143.jpg +0 -0
  793. package/kb/references/thumbs/db5dd367f5.jpg +0 -0
  794. package/kb/references/thumbs/db69677866.jpg +0 -0
  795. package/kb/references/thumbs/db87c1956e.jpg +0 -0
  796. package/kb/references/thumbs/dbb86d8bda.jpg +0 -0
  797. package/kb/references/thumbs/dbd3a8ff2a.jpg +0 -0
  798. package/kb/references/thumbs/dbdf4b2794.jpg +0 -0
  799. package/kb/references/thumbs/dd4c19b4b1.jpg +0 -0
  800. package/kb/references/thumbs/dd98d9f6fa.jpg +0 -0
  801. package/kb/references/thumbs/ddb00e3b6a.jpg +0 -0
  802. package/kb/references/thumbs/dde3541a5c.jpg +0 -0
  803. package/kb/references/thumbs/de2a4da502.jpg +0 -0
  804. package/kb/references/thumbs/de4c387a66.jpg +0 -0
  805. package/kb/references/thumbs/de5618fa82.jpg +0 -0
  806. package/kb/references/thumbs/de6bec2538.jpg +0 -0
  807. package/kb/references/thumbs/dea13cbb1f.jpg +0 -0
  808. package/kb/references/thumbs/deff9202aa.jpg +0 -0
  809. package/kb/references/thumbs/df12835f8d.jpg +0 -0
  810. package/kb/references/thumbs/df57acbb3d.jpg +0 -0
  811. package/kb/references/thumbs/df8265009e.jpg +0 -0
  812. package/kb/references/thumbs/dfc99a1e8e.jpg +0 -0
  813. package/kb/references/thumbs/dfc9fde460.jpg +0 -0
  814. package/kb/references/thumbs/e038348eee.jpg +0 -0
  815. package/kb/references/thumbs/e04c2ae1d5.jpg +0 -0
  816. package/kb/references/thumbs/e070345c43.jpg +0 -0
  817. package/kb/references/thumbs/e0a0c84d47.jpg +0 -0
  818. package/kb/references/thumbs/e0af1e6b9e.jpg +0 -0
  819. package/kb/references/thumbs/e1025942c4.jpg +0 -0
  820. package/kb/references/thumbs/e11b6f5b82.jpg +0 -0
  821. package/kb/references/thumbs/e1553de3fc.jpg +0 -0
  822. package/kb/references/thumbs/e162ebe7cd.jpg +0 -0
  823. package/kb/references/thumbs/e1f1e531d8.jpg +0 -0
  824. package/kb/references/thumbs/e20842e5c9.jpg +0 -0
  825. package/kb/references/thumbs/e24e7d949b.jpg +0 -0
  826. package/kb/references/thumbs/e2a3e5d10a.jpg +0 -0
  827. package/kb/references/thumbs/e2de02615a.jpg +0 -0
  828. package/kb/references/thumbs/e305dad7dd.jpg +0 -0
  829. package/kb/references/thumbs/e52e3ef97f.jpg +0 -0
  830. package/kb/references/thumbs/e570e92d06.jpg +0 -0
  831. package/kb/references/thumbs/e583932fb9.jpg +0 -0
  832. package/kb/references/thumbs/e5da3c038f.jpg +0 -0
  833. package/kb/references/thumbs/e657634af3.jpg +0 -0
  834. package/kb/references/thumbs/e67946e3e1.jpg +0 -0
  835. package/kb/references/thumbs/e69e0f3639.jpg +0 -0
  836. package/kb/references/thumbs/e6ebe66031.jpg +0 -0
  837. package/kb/references/thumbs/e7db9563c9.jpg +0 -0
  838. package/kb/references/thumbs/e84a4c3b7b.jpg +0 -0
  839. package/kb/references/thumbs/e84cf52c27.jpg +0 -0
  840. package/kb/references/thumbs/e8707cf6e8.jpg +0 -0
  841. package/kb/references/thumbs/e888890b40.jpg +0 -0
  842. package/kb/references/thumbs/e8a502b418.jpg +0 -0
  843. package/kb/references/thumbs/e8ba68371d.jpg +0 -0
  844. package/kb/references/thumbs/e9098f54cc.jpg +0 -0
  845. package/kb/references/thumbs/e9144deae9.jpg +0 -0
  846. package/kb/references/thumbs/e93e98d757.jpg +0 -0
  847. package/kb/references/thumbs/e9762dd435.jpg +0 -0
  848. package/kb/references/thumbs/e9db4544c8.jpg +0 -0
  849. package/kb/references/thumbs/e9ddffeacd.jpg +0 -0
  850. package/kb/references/thumbs/e9e2cf1d7e.jpg +0 -0
  851. package/kb/references/thumbs/ea1e23e623.jpg +0 -0
  852. package/kb/references/thumbs/ea41200f5e.jpg +0 -0
  853. package/kb/references/thumbs/eaf4916e1a.jpg +0 -0
  854. package/kb/references/thumbs/eb2c505fc8.jpg +0 -0
  855. package/kb/references/thumbs/eb47943693.jpg +0 -0
  856. package/kb/references/thumbs/eb4ffd6625.jpg +0 -0
  857. package/kb/references/thumbs/eb82ac0a4d.jpg +0 -0
  858. package/kb/references/thumbs/ebeb345ade.jpg +0 -0
  859. package/kb/references/thumbs/ec4e2aba0a.jpg +0 -0
  860. package/kb/references/thumbs/ed683bc9f7.jpg +0 -0
  861. package/kb/references/thumbs/ed9e236a84.jpg +0 -0
  862. package/kb/references/thumbs/ee45e1caea.jpg +0 -0
  863. package/kb/references/thumbs/ee50bbf2e7.jpg +0 -0
  864. package/kb/references/thumbs/eed6ad3b7b.jpg +0 -0
  865. package/kb/references/thumbs/eee247fd70.jpg +0 -0
  866. package/kb/references/thumbs/ef87b6cb99.jpg +0 -0
  867. package/kb/references/thumbs/ef87dccf04.jpg +0 -0
  868. package/kb/references/thumbs/ef941bba1e.jpg +0 -0
  869. package/kb/references/thumbs/effc14fb2c.jpg +0 -0
  870. package/kb/references/thumbs/f04aa5a191.jpg +0 -0
  871. package/kb/references/thumbs/f13f12485f.jpg +0 -0
  872. package/kb/references/thumbs/f16a5c0fd4.jpg +0 -0
  873. package/kb/references/thumbs/f1ba7a7a8f.jpg +0 -0
  874. package/kb/references/thumbs/f1bc4c9c19.jpg +0 -0
  875. package/kb/references/thumbs/f1ee827878.jpg +0 -0
  876. package/kb/references/thumbs/f21736aeff.jpg +0 -0
  877. package/kb/references/thumbs/f22bc41213.jpg +0 -0
  878. package/kb/references/thumbs/f266aaffcc.jpg +0 -0
  879. package/kb/references/thumbs/f2c0ed0d65.jpg +0 -0
  880. package/kb/references/thumbs/f32ac710fd.jpg +0 -0
  881. package/kb/references/thumbs/f32b697ff6.jpg +0 -0
  882. package/kb/references/thumbs/f39c883904.jpg +0 -0
  883. package/kb/references/thumbs/f3b9d55e6e.jpg +0 -0
  884. package/kb/references/thumbs/f3c1763e14.jpg +0 -0
  885. package/kb/references/thumbs/f40853fd43.jpg +0 -0
  886. package/kb/references/thumbs/f4fd07dc4d.jpg +0 -0
  887. package/kb/references/thumbs/f50b756ee5.jpg +0 -0
  888. package/kb/references/thumbs/f51272e9b3.jpg +0 -0
  889. package/kb/references/thumbs/f538895eee.jpg +0 -0
  890. package/kb/references/thumbs/f5d28081b5.jpg +0 -0
  891. package/kb/references/thumbs/f6046c9501.jpg +0 -0
  892. package/kb/references/thumbs/f62e4af316.jpg +0 -0
  893. package/kb/references/thumbs/f6f6bffeb8.jpg +0 -0
  894. package/kb/references/thumbs/f736e00af6.jpg +0 -0
  895. package/kb/references/thumbs/f7932da47d.jpg +0 -0
  896. package/kb/references/thumbs/f879e118ca.jpg +0 -0
  897. package/kb/references/thumbs/f88257215d.jpg +0 -0
  898. package/kb/references/thumbs/f88c45a6d7.jpg +0 -0
  899. package/kb/references/thumbs/f89a7b646e.jpg +0 -0
  900. package/kb/references/thumbs/f8a1e7a274.jpg +0 -0
  901. package/kb/references/thumbs/f9183cf2b6.jpg +0 -0
  902. package/kb/references/thumbs/f995de5ce9.jpg +0 -0
  903. package/kb/references/thumbs/f9ada2c3e1.jpg +0 -0
  904. package/kb/references/thumbs/f9d4616f89.jpg +0 -0
  905. package/kb/references/thumbs/f9f4307bb0.jpg +0 -0
  906. package/kb/references/thumbs/fa070122c7.jpg +0 -0
  907. package/kb/references/thumbs/fa29cc1369.jpg +0 -0
  908. package/kb/references/thumbs/fa791a4dab.jpg +0 -0
  909. package/kb/references/thumbs/fa8060509e.jpg +0 -0
  910. package/kb/references/thumbs/fafeed4003.jpg +0 -0
  911. package/kb/references/thumbs/fb1c024f38.jpg +0 -0
  912. package/kb/references/thumbs/fb77aa28b3.jpg +0 -0
  913. package/kb/references/thumbs/fb9f7f1966.jpg +0 -0
  914. package/kb/references/thumbs/fba8a8c2da.jpg +0 -0
  915. package/kb/references/thumbs/fce2754c36.jpg +0 -0
  916. package/kb/references/thumbs/fce2fb83df.jpg +0 -0
  917. package/kb/references/thumbs/fd4c51bb47.jpg +0 -0
  918. package/kb/references/thumbs/fd8c269817.jpg +0 -0
  919. package/kb/references/thumbs/fdb7b250ca.jpg +0 -0
  920. package/kb/references/thumbs/fe18088de8.jpg +0 -0
  921. package/kb/references/thumbs/fe4f742ba7.jpg +0 -0
  922. package/kb/references/thumbs/fe64742ce7.jpg +0 -0
  923. package/kb/references/thumbs/feb5d62161.jpg +0 -0
  924. package/kb/references/thumbs/fed21b3e98.jpg +0 -0
  925. package/kb/references/thumbs/fed2205951.jpg +0 -0
  926. package/kb/references/thumbs/ffdacf1715.jpg +0 -0
  927. package/kb/sections/_buttons.md +93 -0
  928. package/kb/sections/_finish.md +325 -0
  929. package/kb/sections/about-founder-note.md +85 -0
  930. package/kb/sections/about-team-roster.md +86 -0
  931. package/kb/sections/alternating-rows-live-tiles.md +110 -0
  932. package/kb/sections/annotated-product-shot.md +105 -0
  933. package/kb/sections/asymmetric-bento-dominant.md +114 -0
  934. package/kb/sections/before-after-features.md +104 -0
  935. package/kb/sections/before-after-repair.md +107 -0
  936. package/kb/sections/bento-lead-tile.md +112 -0
  937. package/kb/sections/book-a-slot-honest.md +116 -0
  938. package/kb/sections/capability-prompt-ledger.md +68 -0
  939. package/kb/sections/case-study-band.md +113 -0
  940. package/kb/sections/centred-stack-hero.md +107 -0
  941. package/kb/sections/closing-demo-final-state.md +81 -0
  942. package/kb/sections/closing-full-bleed-line-and-form.md +86 -0
  943. package/kb/sections/closing-result-previewed.md +88 -0
  944. package/kb/sections/closing-three-real-steps.md +87 -0
  945. package/kb/sections/command-reference-table.md +70 -0
  946. package/kb/sections/comparison-old-way-bars.md +88 -0
  947. package/kb/sections/comparison-same-task-two-ways.md +88 -0
  948. package/kb/sections/day-of-the-place.md +102 -0
  949. package/kb/sections/docs-reading-rail.md +88 -0
  950. package/kb/sections/editorial-columns-hero.md +107 -0
  951. package/kb/sections/editorial-essay-pull-quote.md +112 -0
  952. package/kb/sections/events-calendar-list.md +107 -0
  953. package/kb/sections/explorable-control-demo.md +102 -0
  954. package/kb/sections/faq-open-answers-editorial.md +85 -0
  955. package/kb/sections/faq-ruled-accordion-aside.md +87 -0
  956. package/kb/sections/footer-closing-scene.md +84 -0
  957. package/kb/sections/footer-editorial-sitemap.md +85 -0
  958. package/kb/sections/footer-minimal-credits.md +80 -0
  959. package/kb/sections/full-bleed-image-band.md +103 -0
  960. package/kb/sections/full-bleed-image-hero.md +105 -0
  961. package/kb/sections/gallery-first-hero.md +109 -0
  962. package/kb/sections/horizontal-scroll-strip.md +101 -0
  963. package/kb/sections/how-i-work-own-voice.md +111 -0
  964. package/kb/sections/how-it-works-in-place.md +109 -0
  965. package/kb/sections/impact-numbers-sourced.md +109 -0
  966. package/kb/sections/install-steps-per-agent.md +77 -0
  967. package/kb/sections/masonry-real-work.md +109 -0
  968. package/kb/sections/numbered-editorial-columns.md +105 -0
  969. package/kb/sections/object-first-hero.md +106 -0
  970. package/kb/sections/object-timeline.md +105 -0
  971. package/kb/sections/one-huge-number.md +100 -0
  972. package/kb/sections/one-person-story.md +103 -0
  973. package/kb/sections/order-ahead-ticket.md +119 -0
  974. package/kb/sections/press-strip-quoted.md +106 -0
  975. package/kb/sections/pricing-comparison-table-sticky.md +94 -0
  976. package/kb/sections/pricing-free-pro-upgrade-moment.md +85 -0
  977. package/kb/sections/pricing-plan-beside-product.md +88 -0
  978. package/kb/sections/pricing-plans-ledger.md +94 -0
  979. package/kb/sections/pricing-usage-calculator.md +93 -0
  980. package/kb/sections/printed-menu-card.md +110 -0
  981. package/kb/sections/process-happening.md +102 -0
  982. package/kb/sections/project-index-ruled.md +106 -0
  983. package/kb/sections/proof-logo-cloud-with-reasons.md +82 -0
  984. package/kb/sections/proof-measured-numbers.md +88 -0
  985. package/kb/sections/proof-output-wall.md +84 -0
  986. package/kb/sections/proof-single-honest-quote.md +81 -0
  987. package/kb/sections/resources-searchable-list.md +110 -0
  988. package/kb/sections/rooms-and-rates.md +107 -0
  989. package/kb/sections/ruled-facts-table.md +108 -0
  990. package/kb/sections/ruled-list-pinned-visual.md +107 -0
  991. package/kb/sections/scroll-scrubbed-product-demo.md +103 -0
  992. package/kb/sections/self-playing-run-demo.md +104 -0
  993. package/kb/sections/services-price-ledger.md +106 -0
  994. package/kb/sections/signup-form-with-next-steps.md +86 -0
  995. package/kb/sections/signup-waitlist-place-in-line.md +90 -0
  996. package/kb/sections/spec-sheet-features.md +108 -0
  997. package/kb/sections/split-hero-live-object.md +108 -0
  998. package/kb/sections/sticky-feature-narrative.md +104 -0
  999. package/kb/sections/todays-board-hero.md +112 -0
  1000. package/kb/sections/touchable-tool-hero.md +111 -0
  1001. package/kb/sections/typographic-statement-hero.md +99 -0
  1002. package/kb/sections/visit-hours-map.md +110 -0
  1003. package/kb/sections/ways-to-help-honest.md +115 -0
  1004. package/kb/sources/design-reference.md +991 -0
  1005. package/kb/sources/product-and-docs.md +37 -0
  1006. package/kb/systems/1win/DESIGN.md +463 -0
  1007. package/kb/systems/LICENSE-awesome-design-md +21 -0
  1008. package/kb/systems/README.md +7 -0
  1009. package/kb/systems/airbnb/DESIGN.md +545 -0
  1010. package/kb/systems/airtable/DESIGN.md +554 -0
  1011. package/kb/systems/aljazeera/DESIGN.md +594 -0
  1012. package/kb/systems/apple/DESIGN.md +562 -0
  1013. package/kb/systems/binance/DESIGN.md +634 -0
  1014. package/kb/systems/bmw/DESIGN.md +544 -0
  1015. package/kb/systems/bmw-m/DESIGN.md +503 -0
  1016. package/kb/systems/bugatti/DESIGN.md +454 -0
  1017. package/kb/systems/cal/DESIGN.md +542 -0
  1018. package/kb/systems/categories.json +87 -0
  1019. package/kb/systems/claude/DESIGN.md +589 -0
  1020. package/kb/systems/clay/DESIGN.md +541 -0
  1021. package/kb/systems/clickhouse/DESIGN.md +544 -0
  1022. package/kb/systems/cohere/DESIGN.md +451 -0
  1023. package/kb/systems/coinbase/DESIGN.md +570 -0
  1024. package/kb/systems/composio/DESIGN.md +506 -0
  1025. package/kb/systems/cursor/DESIGN.md +537 -0
  1026. package/kb/systems/dell-1996/DESIGN.md +632 -0
  1027. package/kb/systems/dji/DESIGN.md +882 -0
  1028. package/kb/systems/elevenlabs/DESIGN.md +504 -0
  1029. package/kb/systems/expo/DESIGN.md +526 -0
  1030. package/kb/systems/ferrari/DESIGN.md +531 -0
  1031. package/kb/systems/figma/DESIGN.md +578 -0
  1032. package/kb/systems/framer/DESIGN.md +544 -0
  1033. package/kb/systems/hashicorp/DESIGN.md +575 -0
  1034. package/kb/systems/hp/DESIGN.md +670 -0
  1035. package/kb/systems/ibm/DESIGN.md +550 -0
  1036. package/kb/systems/intercom/DESIGN.md +546 -0
  1037. package/kb/systems/jobright/DESIGN.md +525 -0
  1038. package/kb/systems/kraken/DESIGN.md +125 -0
  1039. package/kb/systems/lamborghini/DESIGN.md +288 -0
  1040. package/kb/systems/linear.app/DESIGN.md +548 -0
  1041. package/kb/systems/lovable/DESIGN.md +298 -0
  1042. package/kb/systems/mastercard/DESIGN.md +365 -0
  1043. package/kb/systems/mercury/DESIGN.md +568 -0
  1044. package/kb/systems/meta/DESIGN.md +683 -0
  1045. package/kb/systems/minimax/DESIGN.md +746 -0
  1046. package/kb/systems/mintlify/DESIGN.md +852 -0
  1047. package/kb/systems/miro/DESIGN.md +825 -0
  1048. package/kb/systems/mistral.ai/DESIGN.md +773 -0
  1049. package/kb/systems/mongodb/DESIGN.md +767 -0
  1050. package/kb/systems/mydealz/DESIGN.md +551 -0
  1051. package/kb/systems/nerdwallet/DESIGN.md +722 -0
  1052. package/kb/systems/nike/DESIGN.md +575 -0
  1053. package/kb/systems/nintendo-2001/DESIGN.md +649 -0
  1054. package/kb/systems/notion/DESIGN.md +821 -0
  1055. package/kb/systems/nvidia/DESIGN.md +640 -0
  1056. package/kb/systems/ollama/DESIGN.md +539 -0
  1057. package/kb/systems/opencode.ai/DESIGN.md +521 -0
  1058. package/kb/systems/oracle/DESIGN.md +778 -0
  1059. package/kb/systems/oura/DESIGN.md +616 -0
  1060. package/kb/systems/pinterest/DESIGN.md +597 -0
  1061. package/kb/systems/playstation/DESIGN.md +661 -0
  1062. package/kb/systems/posthog/DESIGN.md +690 -0
  1063. package/kb/systems/raycast/DESIGN.md +669 -0
  1064. package/kb/systems/renault/DESIGN.md +589 -0
  1065. package/kb/systems/replicate/DESIGN.md +616 -0
  1066. package/kb/systems/resend/DESIGN.md +585 -0
  1067. package/kb/systems/revolut/DESIGN.md +636 -0
  1068. package/kb/systems/runwayml/DESIGN.md +244 -0
  1069. package/kb/systems/sanity/DESIGN.md +357 -0
  1070. package/kb/systems/sap/DESIGN.md +639 -0
  1071. package/kb/systems/sentry/DESIGN.md +551 -0
  1072. package/kb/systems/shopify/DESIGN.md +516 -0
  1073. package/kb/systems/slack/DESIGN.md +482 -0
  1074. package/kb/systems/spacex/DESIGN.md +363 -0
  1075. package/kb/systems/spotify/DESIGN.md +246 -0
  1076. package/kb/systems/starbucks/DESIGN.md +580 -0
  1077. package/kb/systems/stripe/DESIGN.md +487 -0
  1078. package/kb/systems/supabase/DESIGN.md +462 -0
  1079. package/kb/systems/superhuman/DESIGN.md +448 -0
  1080. package/kb/systems/tesla/DESIGN.md +286 -0
  1081. package/kb/systems/theverge/DESIGN.md +339 -0
  1082. package/kb/systems/together.ai/DESIGN.md +633 -0
  1083. package/kb/systems/uber/DESIGN.md +636 -0
  1084. package/kb/systems/vercel/DESIGN.md +736 -0
  1085. package/kb/systems/vodafone/DESIGN.md +538 -0
  1086. package/kb/systems/voltagent/DESIGN.md +521 -0
  1087. package/kb/systems/warp/DESIGN.md +526 -0
  1088. package/kb/systems/webflow/DESIGN.md +588 -0
  1089. package/kb/systems/wired/DESIGN.md +497 -0
  1090. package/kb/systems/wise/DESIGN.md +544 -0
  1091. package/kb/systems/x.ai/DESIGN.md +465 -0
  1092. package/kb/systems/zapier/DESIGN.md +537 -0
  1093. package/kb/taste/garvit-by-job.md +46 -0
  1094. package/kb/taste/garvit-portfolio.md +94 -0
  1095. package/kb/universal/color-roles.md +26 -0
  1096. package/kb/universal/copy.md +16 -0
  1097. package/kb/universal/details.md +31 -0
  1098. package/kb/universal/first-screen.md +30 -0
  1099. package/kb/universal/fit-the-codebase.md +29 -0
  1100. package/kb/universal/layout-width.md +28 -0
  1101. package/kb/universal/motion-feedback.md +23 -0
  1102. package/kb/universal/signature.md +29 -0
  1103. package/kb/universal/states.md +17 -0
  1104. package/kb/universal/type-app.md +33 -0
  1105. package/kb/universal/type-marketing.md +28 -0
  1106. package/package.json +36 -4
  1107. package/scripts/pack-assets.mjs +48 -0
  1108. package/skill/palate/SKILL.md +261 -0
  1109. package/src/auth-recheck.mjs +4 -0
  1110. package/src/auth.mjs +416 -0
  1111. package/src/capture.mjs +182 -0
  1112. package/src/catalog/classify.mjs +96 -0
  1113. package/src/catalog/curated.mjs +128 -0
  1114. package/src/catalog/index-build.mjs +67 -0
  1115. package/src/catalog/literal.mjs +146 -0
  1116. package/src/catalog/store.mjs +40 -0
  1117. package/src/catalog/vibrant.mjs +126 -0
  1118. package/src/check.mjs +93 -0
  1119. package/src/concept.mjs +157 -0
  1120. package/src/context.mjs +226 -0
  1121. package/src/copy.mjs +188 -0
  1122. package/src/devserver.mjs +135 -0
  1123. package/src/fontgenre.mjs +44 -0
  1124. package/src/guard-agents.mjs +213 -0
  1125. package/src/guard.mjs +377 -0
  1126. package/src/kb.mjs +91 -0
  1127. package/src/look.mjs +312 -0
  1128. package/src/loop/ambition.mjs +620 -0
  1129. package/src/loop/animate.mjs +70 -0
  1130. package/src/loop/artdirection.mjs +264 -0
  1131. package/src/loop/bench.mjs +184 -0
  1132. package/src/loop/benchpick.mjs +155 -0
  1133. package/src/loop/blueprint.mjs +620 -0
  1134. package/src/loop/board.html +180 -0
  1135. package/src/loop/build.mjs +393 -0
  1136. package/src/loop/buttons.mjs +413 -0
  1137. package/src/loop/common.mjs +206 -0
  1138. package/src/loop/cost.mjs +63 -0
  1139. package/src/loop/craft.mjs +152 -0
  1140. package/src/loop/craftchecks.mjs +148 -0
  1141. package/src/loop/critique.mjs +393 -0
  1142. package/src/loop/details.mjs +225 -0
  1143. package/src/loop/direction.html +168 -0
  1144. package/src/loop/direction.mjs +256 -0
  1145. package/src/loop/directions.json +8 -0
  1146. package/src/loop/explore.mjs +219 -0
  1147. package/src/loop/fail.mjs +110 -0
  1148. package/src/loop/fix.mjs +194 -0
  1149. package/src/loop/floor.mjs +677 -0
  1150. package/src/loop/forget.mjs +52 -0
  1151. package/src/loop/gate.mjs +1053 -0
  1152. package/src/loop/grid.html +123 -0
  1153. package/src/loop/growth.mjs +118 -0
  1154. package/src/loop/icons.mjs +109 -0
  1155. package/src/loop/imagery.mjs +1280 -0
  1156. package/src/loop/judge-api.mjs +245 -0
  1157. package/src/loop/judge.mjs +167 -0
  1158. package/src/loop/layouts.mjs +492 -0
  1159. package/src/loop/library.mjs +82 -0
  1160. package/src/loop/lookplan.mjs +182 -0
  1161. package/src/loop/lookvec.mjs +645 -0
  1162. package/src/loop/match.mjs +923 -0
  1163. package/src/loop/matched.mjs +26 -0
  1164. package/src/loop/myrefs.mjs +151 -0
  1165. package/src/loop/pick.mjs +213 -0
  1166. package/src/loop/picker.html +118 -0
  1167. package/src/loop/plan.mjs +289 -0
  1168. package/src/loop/polish.mjs +39 -0
  1169. package/src/loop/research-learn.mjs +41 -0
  1170. package/src/loop/research.mjs +1130 -0
  1171. package/src/loop/rulereview.mjs +146 -0
  1172. package/src/loop/rules-board.html +199 -0
  1173. package/src/loop/rules.mjs +939 -0
  1174. package/src/loop/similar.mjs +276 -0
  1175. package/src/loop/states-source.mjs +258 -0
  1176. package/src/loop/states.mjs +1547 -0
  1177. package/src/loop/stats.mjs +78 -0
  1178. package/src/loop/taste.mjs +81 -0
  1179. package/src/loop/timeline.mjs +149 -0
  1180. package/src/loop/variants.mjs +228 -0
  1181. package/src/loop/vary.mjs +249 -0
  1182. package/src/mcp/server.mjs +1246 -0
  1183. package/src/motion.mjs +207 -0
  1184. package/src/moves.mjs +242 -0
  1185. package/src/novelty.mjs +116 -0
  1186. package/src/page-ambition.js +181 -0
  1187. package/src/page-craft.js +724 -0
  1188. package/src/page-details.js +415 -0
  1189. package/src/page-devices.js +365 -0
  1190. package/src/page-fingerprint.js +281 -0
  1191. package/src/page-gate.js +1307 -0
  1192. package/src/page-look.js +698 -0
  1193. package/src/page-metrics.js +78 -0
  1194. package/src/page-principles.js +1167 -0
  1195. package/src/page-rules.js +308 -0
  1196. package/src/page-sections.js +211 -0
  1197. package/src/page-states.js +703 -0
  1198. package/src/paths.mjs +13 -0
  1199. package/src/png.mjs +107 -0
  1200. package/src/point/auto.mjs +224 -0
  1201. package/src/point/locate.mjs +114 -0
  1202. package/src/point/overlay.js +1516 -0
  1203. package/src/point/server.mjs +1122 -0
  1204. package/src/point/trail.mjs +219 -0
  1205. package/src/pool.mjs +80 -0
  1206. package/src/principles.mjs +279 -0
  1207. package/src/refs.mjs +299 -0
  1208. package/src/robots.mjs +145 -0
  1209. package/src/sections.mjs +210 -0
  1210. package/src/shoot.mjs +235 -0
  1211. package/src/systems/apply.mjs +355 -0
  1212. package/src/systems/load.mjs +251 -0
  1213. package/src/systems/pick.mjs +213 -0
  1214. package/templates/vite-react-tw/index.html +12 -0
  1215. package/templates/vite-react-tw/package.json +25 -0
  1216. package/templates/vite-react-tw/src/App.tsx +3 -0
  1217. package/templates/vite-react-tw/src/index.css +1 -0
  1218. package/templates/vite-react-tw/src/main.tsx +10 -0
  1219. package/templates/vite-react-tw/tsconfig.app.json +26 -0
  1220. package/templates/vite-react-tw/tsconfig.json +7 -0
  1221. package/templates/vite-react-tw/tsconfig.node.json +23 -0
  1222. package/templates/vite-react-tw/vite.config.ts +8 -0
package/src/motion.mjs ADDED
@@ -0,0 +1,207 @@
1
+ // The motion check: lets the agent SEE motion as frame strips, and flags what motion must never do.
2
+ // - On load: frames at 0/150/400/800/1500ms after the HTML arrives.
3
+ // - Each section scrolled into view: frames at 0/150/400/800ms.
4
+ // - Content still invisible 1s after it should show, and layout shift (CLS) with its sources.
5
+ // - prefers-reduced-motion emulated: what still moves, and whether anything is left hidden.
6
+ // - JavaScript off: whether content is left at opacity 0 (e.g. entrance styles rendered into server HTML).
7
+ import fs from "node:fs";
8
+ import path from "node:path";
9
+ import { contactSheet, findSections, HIDE_DEV, MOTION_INIT, slugOf, stamp, withBrowser } from "./look.mjs";
10
+ import { normalizeRoute } from "./shoot.mjs";
11
+
12
+ const SHIFT_INIT = `window.__palateShifts = [];
13
+ try { new PerformanceObserver((l) => { for (const e of l.getEntries()) if (!e.hadRecentInput) window.__palateShifts.push({ value: e.value, t: Math.round(e.startTime), nodes: (e.sources || []).map((s) => { const n = s.node && (s.node.nodeType === 1 ? s.node : s.node.parentElement); return n ? (n.id ? "#" + n.id : n.tagName.toLowerCase() + (typeof n.className === "string" && n.className ? "." + n.className.trim().split(/\\s+/).slice(0, 2).join(".") : "")) : null; }).filter(Boolean) }); }).observe({ type: "layout-shift", buffered: true }); } catch {}`;
14
+
15
+ // Content inside the viewport that a reader can't see: opacity under 0.1 or visibility hidden, from itself
16
+ // or an ancestor. Skips things hidden on purpose: aria-hidden, closed popovers and menus, sr-only text, and
17
+ // stacked layers (a cross-fade's hidden layer sits under a visible sibling).
18
+ export const HIDDEN = `(() => {
19
+ const vh = innerHeight;
20
+ const out = new Map();
21
+ const clean = (s) => (s || "").replace(/\\s+/g, " ").trim();
22
+ const name = (e) => e.id ? "#" + e.id : e.tagName.toLowerCase() + (typeof e.className === "string" && e.className ? "." + e.className.trim().split(/\\s+/).slice(0, 2).join(".") : "");
23
+ for (const el of document.body.querySelectorAll("h1,h2,h3,h4,h5,h6,p,li,img,video,button,a,figure,blockquote,td,label,span,svg,input")) {
24
+ const r = el.getBoundingClientRect();
25
+ if (r.width < 4 || r.height < 4 || r.bottom < 0 || r.top > vh) continue;
26
+ if (el.closest("[aria-hidden=true], .sr-only, [hidden], template, noscript, dialog:not([open]), [role=menu], [role=tooltip], [role=listbox], [data-state=closed], [popover]:not(:popover-open)")) continue;
27
+ const media = ["IMG", "VIDEO", "svg", "INPUT"].includes(el.tagName);
28
+ if (!media && ![...el.childNodes].some((n) => n.nodeType === 3 && n.textContent.trim().length > 1)) continue;
29
+ let op = 1, by = null;
30
+ for (let e = el; e && e.nodeType === 1; e = e.parentElement) {
31
+ const cs = getComputedStyle(e);
32
+ op *= parseFloat(cs.opacity);
33
+ if (cs.visibility === "hidden") op = 0;
34
+ if (op < 0.1) { by = e; break; }
35
+ }
36
+ if (!by || out.has(by)) continue;
37
+ // A native control made transparent on purpose (a custom radio or checkbox) whose label shows: the label
38
+ // is what a reader sees, not hidden content.
39
+ if (by === el && el.matches("input[type=radio], input[type=checkbox], input[type=file], input[type=range], input[type=color], select")) {
40
+ const shown = (l) => { let o = 1; for (let e = l; e && e.nodeType === 1; e = e.parentElement) { const c = getComputedStyle(e); o *= parseFloat(c.opacity); if (c.visibility === "hidden") o = 0; } return o >= 0.1; };
41
+ const label = [...(el.labels || [])].concat(el.closest("label") || [], el.nextElementSibling || [], el.previousElementSibling || []).find((l) => { const lr = l.getBoundingClientRect(); return lr.width > 4 && lr.height > 4 && clean(l.textContent) && shown(l); });
42
+ if (label) continue;
43
+ }
44
+ const br = by.getBoundingClientRect();
45
+ const stacked = by.parentElement && [...by.parentElement.children].some((s) => {
46
+ if (s === by) return false;
47
+ const sr = s.getBoundingClientRect();
48
+ const ix = Math.max(0, Math.min(sr.right, br.right) - Math.max(sr.left, br.left)) * Math.max(0, Math.min(sr.bottom, br.bottom) - Math.max(sr.top, br.top));
49
+ return parseFloat(getComputedStyle(s).opacity) > 0.5 && ix > 0.8 * br.width * br.height;
50
+ });
51
+ if (stacked) continue;
52
+ out.set(by, { selector: name(by), text: clean(by.textContent).slice(0, 50) || el.tagName.toLowerCase(), opacity: Math.round(op * 100) / 100 });
53
+ }
54
+ return [...out.values()].slice(0, 12);
55
+ })()`;
56
+
57
+ const RUNNING = `document.getAnimations ? document.getAnimations().filter((a) => a.playState === "running").map((a) => { const t = a.effect && a.effect.target; const timing = a.effect && a.effect.getTiming ? a.effect.getTiming() : {}; return { target: t ? (t.id ? "#" + t.id : t.tagName.toLowerCase() + (typeof t.className === "string" && t.className ? "." + t.className.trim().split(/\\s+/)[0] : "")) : "?", name: a.animationName || a.transitionProperty || a.id || "script", duration: Number(timing.duration) || 0, infinite: timing.iterations === Infinity }; }).slice(0, 12) : []`;
58
+ // Transitions that change how something looks without moving it (allowed under prefers-reduced-motion).
59
+ const CHANGE_ONLY = /^(color|background-color|background|border-color|outline-color|text-decoration-color|fill|stroke|opacity|box-shadow|filter)$/;
60
+
61
+ const wait = (ms) => new Promise((r) => setTimeout(r, Math.max(0, ms)));
62
+ const same = (a, b) => a && b && Buffer.compare(a, b) === 0;
63
+
64
+ export async function motionCheck(dir, rawRoute, { url, out } = {}) {
65
+ const route = normalizeRoute(rawRoute);
66
+ const session = out ?? path.join(dir, ".palate", "motion", slugOf(route), stamp());
67
+ fs.mkdirSync(path.join(session, "frames"), { recursive: true });
68
+ fs.writeFileSync(path.join(dir, ".palate", ".gitignore"), "*\n");
69
+
70
+ return withBrowser(dir, { url }, async ({ base, browser }) => {
71
+ const target = base + route;
72
+ const shot = async (page, file) => {
73
+ const buf = await page.screenshot({ type: "jpeg", quality: 70 });
74
+ fs.writeFileSync(file, buf);
75
+ return buf;
76
+ };
77
+ // Warm up: the first request may compile the route.
78
+ {
79
+ const p = await browser.newPage();
80
+ await p.goto(target, { waitUntil: "networkidle", timeout: 90_000 }).catch(() => {});
81
+ await p.close();
82
+ }
83
+
84
+ // 1. Normal motion: load frames, then each section scrolled into view.
85
+ const ctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, reducedMotion: "no-preference" });
86
+ const page = await ctx.newPage();
87
+ await page.addInitScript(HIDE_DEV);
88
+ await page.addInitScript(MOTION_INIT);
89
+ await page.addInitScript(SHIFT_INIT);
90
+ // Frames count from the load event, so late images and fonts don't pass for an entrance.
91
+ await page.goto(target, { waitUntil: "load", timeout: 60_000 });
92
+ let t0 = Date.now();
93
+ const load = [];
94
+ for (const t of [0, 150, 400, 800, 1500]) {
95
+ await wait(t0 + t - Date.now());
96
+ const file = path.join(session, "frames", `load-${t}.jpg`);
97
+ load.push({ t, at: Date.now() - t0, file, buf: await shot(page, file) });
98
+ }
99
+ await page.waitForLoadState("networkidle").catch(() => {});
100
+ await page.waitForTimeout(1000);
101
+ const loadHidden = await page.evaluate(HIDDEN);
102
+ const sections = (await findSections(page)).slice(0, 10);
103
+ const vh = 900;
104
+ const perSection = [];
105
+ for (const s of sections) {
106
+ if (s.sticky && s.index === 1) continue;
107
+ await page.evaluate((y) => window.scrollTo({ top: y, behavior: "instant" }), Math.max(0, s.box.y - vh * 0.1));
108
+ t0 = Date.now();
109
+ const frames = [];
110
+ for (const t of [0, 150, 400, 800]) {
111
+ await wait(t0 + t - Date.now());
112
+ const file = path.join(session, "frames", `s${String(s.index).padStart(2, "0")}-${t}.jpg`);
113
+ frames.push({ t, at: Date.now() - t0, file, buf: await shot(page, file) });
114
+ }
115
+ await wait(t0 + 1100 - Date.now());
116
+ const hidden = await page.evaluate(HIDDEN);
117
+ perSection.push({ index: s.index, name: s.name, selector: s.selector, frames, moved: frames.some((f, i) => i && !same(f.buf, frames[0].buf)), hidden });
118
+ }
119
+ const shifts = await page.evaluate(() => window.__palateShifts ?? []);
120
+ const counters = await page.evaluate(() => ({ io: window.__palateMotion?.io ?? 0, waapi: window.__palateMotion?.waapi ?? 0, started: window.__palateMotion?.started ?? 0, styled: window.__palateMotion?.styled?.size ?? 0 }));
121
+ await ctx.close();
122
+
123
+ // 2. Reduced motion: nothing should travel, and nothing should be left hidden.
124
+ const rctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, reducedMotion: "reduce" });
125
+ const rpage = await rctx.newPage();
126
+ await rpage.addInitScript(HIDE_DEV);
127
+ await rpage.goto(target, { waitUntil: "networkidle", timeout: 60_000 }).catch(() => {});
128
+ await rpage.waitForTimeout(300);
129
+ const reduced = { hidden: await rpage.evaluate(HIDDEN), moving: [], running: [] };
130
+ for (const s of perSection) {
131
+ const box = sections.find((x) => x.index === s.index).box;
132
+ await rpage.evaluate((y) => window.scrollTo({ top: y, behavior: "instant" }), Math.max(0, box.y - vh * 0.1));
133
+ await rpage.waitForTimeout(80);
134
+ const a = await rpage.screenshot({ type: "jpeg", quality: 70 });
135
+ const running = await rpage.evaluate(RUNNING);
136
+ await rpage.waitForTimeout(400);
137
+ const b = await rpage.screenshot({ type: "jpeg", quality: 70 });
138
+ // Reduced motion forbids travel, not change: a colour or opacity transition (a scrollspy lighting the current
139
+ // link, a fade) is allowed. Frames that differ only while such transitions run don't count as moving.
140
+ const travel = running.filter((r) => !CHANGE_ONLY.test(String(r.name)));
141
+ let moved = !same(a, b) && (travel.length > 0 || !running.length);
142
+ // No animation running: a one-off state change after the scroll (a scrollspy, a sticky bar) settles; only
143
+ // a page that keeps changing (script-driven travel) is moving.
144
+ if (moved && !travel.length) {
145
+ await rpage.waitForTimeout(400);
146
+ moved = !same(b, await rpage.screenshot({ type: "jpeg", quality: 70 }));
147
+ }
148
+ if (moved) reduced.moving.push(s.index);
149
+ for (const r of travel) if ((r.duration > 20 || r.infinite) && !reduced.running.some((x) => x.target === r.target && x.name === r.name)) reduced.running.push({ ...r, section: s.index });
150
+ const h = await rpage.evaluate(HIDDEN);
151
+ for (const x of h) if (!reduced.hidden.some((y) => y.selector === x.selector)) reduced.hidden.push({ ...x, section: s.index });
152
+ }
153
+ await rctx.close();
154
+
155
+ // 3. JavaScript off: server-rendered content must not wait for a script to become visible.
156
+ const nctx = await browser.newContext({ viewport: { width: 1440, height: 900 }, javaScriptEnabled: false });
157
+ const npage = await nctx.newPage();
158
+ await npage.goto(target, { waitUntil: "load", timeout: 60_000 }).catch(() => {});
159
+ const textLen = await npage.evaluate(() => document.body.innerText.trim().length).catch(() => 0);
160
+ const noJs = { rendered: textLen > 80, hidden: [] };
161
+ if (noJs.rendered)
162
+ for (const s of perSection) {
163
+ const box = sections.find((x) => x.index === s.index).box;
164
+ await npage.evaluate((y) => window.scrollTo({ top: y, behavior: "instant" }), Math.max(0, box.y - vh * 0.1));
165
+ await npage.waitForTimeout(150);
166
+ for (const x of await npage.evaluate(HIDDEN)) if (!noJs.hidden.some((y) => y.selector === x.selector)) noJs.hidden.push({ ...x, section: s.index });
167
+ }
168
+ await nctx.close();
169
+
170
+ // Frame strips the agent can read in one look.
171
+ const loadStrip = await contactSheet(browser, [{ label: `On load (ms after the load event)`, cells: load.map((f) => ({ caption: `${f.t}ms (actual ${f.at})`, file: f.file })) }], path.join(session, "load-strip.png"), { cell: 340, maxCell: 220 });
172
+ const sectionStrip = perSection.length
173
+ ? await contactSheet(browser, perSection.map((s) => ({ label: `Section ${s.index} · ${s.name.slice(0, 60)}${s.moved ? " · moves" : " · still"}`, cells: s.frames.map((f) => ({ caption: `${f.t}ms`, file: f.file })) })), path.join(session, "sections-strip.png"), { cell: 300, maxCell: 190 })
174
+ : null;
175
+
176
+ const cls = Math.round(shifts.reduce((n, s) => n + s.value, 0) * 1000) / 1000;
177
+ const loadMoved = load.some((f, i) => i && !same(f.buf, load[0].buf));
178
+ const problems = [];
179
+ if (loadHidden.length) problems.push(`Still invisible 1s after load: ${loadHidden.map((h) => `${h.selector} "${h.text}"`).join(", ")}.`);
180
+ for (const s of perSection) if (s.hidden.length) problems.push(`Section ${s.index} (${s.name.slice(0, 40)}): still invisible 1.1s after scrolling into view: ${s.hidden.map((h) => `${h.selector} "${h.text}"`).join(", ")}.`);
181
+ if (cls > 0.05) problems.push(`Layout shift: CLS ${cls} (good is under 0.1, ideally 0). Sources: ${[...new Set(shifts.flatMap((s) => s.nodes))].slice(0, 6).join(", ") || "unknown"}.`);
182
+ if (reduced.moving.length) problems.push(`Under prefers-reduced-motion, something still moves in section(s) ${reduced.moving.join(", ")}${reduced.running.length ? `: ${reduced.running.slice(0, 5).map((r) => `${r.target} ${r.name} ${Math.round(r.duration)}ms${r.infinite ? " (infinite)" : ""}`).join(", ")}` : ""}. Replace travel with an opacity fade or nothing.`);
183
+ if (reduced.hidden.length) problems.push(`Under prefers-reduced-motion, content is left hidden: ${reduced.hidden.map((h) => `${h.selector} "${h.text}"`).join(", ")}.`);
184
+ if (noJs.hidden.length) problems.push(`With JavaScript off, content is left hidden (entrance styles rendered into the HTML): ${noJs.hidden.map((h) => `${h.selector} "${h.text}"`).join(", ")}. Start from visible, or hide only under a class a script sets.`);
185
+
186
+ const moving = perSection.filter((s) => s.moved).map((s) => s.index);
187
+ const still = perSection.filter((s) => !s.moved).map((s) => s.index);
188
+ const report = [
189
+ `## Motion check: ${route} at 1440`,
190
+ `- On load: ${slash(loadStrip)}: ${loadMoved ? "the first screen changes during the first 1.5s (an entrance runs)" : "nothing changes during the first 1.5s"}.`,
191
+ sectionStrip ? `- Sections scrolled into view: ${slash(sectionStrip)}: moving ${moving.length ? moving.join(", ") : "none"} · still ${still.length ? still.join(", ") : "none"}.` : "",
192
+ `- Scripted motion during the run: ${counters.started} CSS animation(s) or transition(s) started, ${counters.waapi} Web Animations, ${counters.styled} element(s) moved or faded by script.`,
193
+ `- Layout shift: CLS ${cls}${shifts.length ? ` over ${shifts.length} shift(s)` : ""}.`,
194
+ `- Reduced motion (emulated): ${reduced.moving.length ? `still moving in section(s) ${reduced.moving.join(", ")}` : "nothing moves"}; ${reduced.hidden.length ? `${reduced.hidden.length} hidden item(s)` : "nothing hidden"}.`,
195
+ `- JavaScript off: ${noJs.rendered ? (noJs.hidden.length ? `${noJs.hidden.length} hidden item(s)` : "all content visible") : "the page renders nothing without JavaScript (client-rendered), so this check doesn't apply"}.`,
196
+ !loadMoved && !moving.length ? "- Nothing moves on load or on scroll: the page is static." : "",
197
+ problems.length ? `\n### Problems\n${problems.map((p) => `- ⚠ ${p}`).join("\n")}` : "- No motion problems measured. Look at the strips: does the motion explain something?",
198
+ ]
199
+ .filter(Boolean)
200
+ .join("\n");
201
+ const data = { route, load: load.map(({ buf, ...f }) => f), sections: perSection.map((s) => ({ ...s, frames: s.frames.map(({ buf, ...f }) => f) })), cls, shifts, reduced, noJs, counters, problems, static: !loadMoved && !moving.length };
202
+ fs.writeFileSync(path.join(session, "motion.json"), JSON.stringify(data, null, 1));
203
+ return { report, problems, session, files: [loadStrip, sectionStrip].filter(Boolean), data };
204
+ });
205
+ }
206
+
207
+ const slash = (p) => String(p).replace(/\\/g, "/");
package/src/moves.mjs ADDED
@@ -0,0 +1,242 @@
1
+ // The moves library: named creative techniques ("moves") with palate's own recipes, one Markdown file each in
2
+ // kb/moves/*.md (YAML frontmatter + body). A move is the craft knowledge behind a memorable page: which technique
3
+ // fits which product, and how to execute it well. Research, ideation and the ambition pass read it through this API:
4
+ // loadMoves() every move, frontmatter + body + sections
5
+ // matchMoves({ tags, kind, signature, exclude, limit, history, screen })
6
+ // ranked by fits overlap minus avoid overlap, plus the user's own history
7
+ // (moves they kept on this kind of screen rise, reverted ones sink)
8
+ // moveBrief(ids) the chosen moves' recipes as compact Markdown for a build brief
9
+ // (kb/moves/moves.yaml is the older, shorter list palate concept uses; it is not read here.)
10
+ import fs from "node:fs";
11
+ import path from "node:path";
12
+ import { fileURLToPath } from "node:url";
13
+ import YAML from "yaml";
14
+ import { KB_ROOT } from "./paths.mjs";
15
+
16
+ const KB_DIR = process.env.PALATE_KB ?? KB_ROOT;
17
+ export const MOVES_DIR = path.join(KB_DIR, "moves");
18
+
19
+ export const KINDS = ["hero", "texture", "motion", "interaction", "type", "layout", "imagery", "footer", "easter-egg", "navigation", "data", "sound-free-feedback"];
20
+ export const EFFORTS = ["s", "m", "l"];
21
+ export const REQUIRED = ["id", "name", "kind", "fits", "avoid", "signature", "effort", "perf", "a11y", "pairs_with"];
22
+ export const SECTIONS = ["What it is", "Why it works", "When to use / when not", "Recipe", "Pitfalls", "How to verify", "Examples"];
23
+
24
+ // The words fits/avoid may use, so a search for "calm" finds every calm move. Mood first, then the kind of product
25
+ // or audience, then contexts that are mostly worth avoiding. Add a word here before using it in a move.
26
+ export const TAGS = [
27
+ // mood and brand
28
+ "calm", "crafted", "editorial", "heritage", "nature", "playful", "bold", "technical", "minimal", "premium", "luxury",
29
+ "warm", "friendly", "energetic", "serious", "trustworthy", "data-rich", "scientific", "retro", "experimental", "artsy",
30
+ "cultural", "community", "honest", "cinematic", "tactile", "quiet",
31
+ // product, audience, moment
32
+ "developer", "saas", "ai", "finance", "health", "education", "kids", "gaming", "music", "fashion", "food", "travel",
33
+ "nonprofit", "ecommerce", "portfolio", "agency", "media", "publishing", "sustainability", "hardware", "productivity",
34
+ "consumer", "b2b", "enterprise", "launch", "waitlist", "docs", "local", "events",
35
+ // contexts where a move tends to hurt
36
+ "playful-kids", "finance-trust-first", "enterprise-compliance", "clinical", "data-dense-tool", "low-bandwidth",
37
+ "accessibility-first", "government", "serious-news", "crisis", "daily-tool",
38
+ ];
39
+
40
+ const list = (v) => (Array.isArray(v) ? v : v == null || v === "" ? [] : [v]).map((x) => String(x).trim()).filter(Boolean);
41
+
42
+ // The body's "## Heading" sections, by heading.
43
+ export function sectionsOf(body) {
44
+ const out = {};
45
+ let cur = null;
46
+ for (const line of body.split("\n")) {
47
+ const h = line.match(/^##\s+(.+?)\s*$/);
48
+ if (h) {
49
+ cur = h[1];
50
+ out[cur] = [];
51
+ } else if (cur) out[cur].push(line);
52
+ }
53
+ for (const k of Object.keys(out)) out[k] = out[k].join("\n").trim();
54
+ return out;
55
+ }
56
+
57
+ export function parseMove(src, file = "") {
58
+ const m = src.replace(/\r\n/g, "\n").match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
59
+ if (!m) throw new Error(`${path.basename(file)}: no frontmatter`);
60
+ const meta = YAML.parse(m[1]) ?? {};
61
+ const body = m[2].trim();
62
+ return {
63
+ ...meta,
64
+ fits: list(meta.fits),
65
+ avoid: list(meta.avoid),
66
+ pairs_with: list(meta.pairs_with),
67
+ signature: meta.signature === true,
68
+ body,
69
+ sections: sectionsOf(body),
70
+ file,
71
+ };
72
+ }
73
+
74
+ let cache = null;
75
+ export function loadMoves({ fresh = false } = {}) {
76
+ if (cache && !fresh) return cache;
77
+ if (!fs.existsSync(MOVES_DIR)) return (cache = []);
78
+ cache = fs
79
+ .readdirSync(MOVES_DIR)
80
+ .filter((f) => f.endsWith(".md"))
81
+ .sort()
82
+ .map((f) => {
83
+ const file = path.join(MOVES_DIR, f);
84
+ return parseMove(fs.readFileSync(file, "utf8"), file);
85
+ });
86
+ return cache;
87
+ }
88
+
89
+ // Problems with one move (missing fields, unknown words, missing sections); [] when it is sound.
90
+ export function lintMove(mv, known = new Set(loadMoves().map((x) => x.id))) {
91
+ const p = [];
92
+ for (const k of REQUIRED) if (mv[k] == null || mv[k] === "") p.push(`missing ${k}`);
93
+ if (mv.file && mv.id && path.basename(mv.file, ".md") !== mv.id) p.push(`file name should be ${mv.id}.md`);
94
+ if (mv.kind && !KINDS.includes(mv.kind)) p.push(`unknown kind ${mv.kind}`);
95
+ if (mv.effort && !EFFORTS.includes(mv.effort)) p.push(`effort must be s, m or l`);
96
+ if (!mv.fits.length) p.push("fits is empty");
97
+ for (const t of [...mv.fits, ...mv.avoid]) if (!TAGS.includes(t)) p.push(`unknown tag ${t}`);
98
+ for (const id of mv.pairs_with) if (!known.has(id)) p.push(`pairs_with ${id} does not exist`);
99
+ for (const s of SECTIONS) if (!mv.sections?.[s]) p.push(`missing section "${s}"`);
100
+ return p;
101
+ }
102
+
103
+ // A query tag matches a move's tag exactly, or as a family ("playful" ~ "playful-kids") at half weight.
104
+ const near = (q, t) => q !== t && (t.startsWith(`${q}-`) || q.startsWith(`${t}-`));
105
+ const hits = (query, tags) => {
106
+ const exact = query.filter((q) => tags.includes(q));
107
+ const partial = query.filter((q) => !exact.includes(q) && tags.some((t) => near(q, t)));
108
+ return { exact, partial };
109
+ };
110
+
111
+ // The user's history with a move: palate grows with each user, so a move they kept on this kind of screen rises
112
+ // and one they reverted sinks. history is [{ id, outcome: "kept" | "reverted", kind }], where kind is the kind of
113
+ // screen it was used on (landing, pricing, app…), read from ~/.palate by the caller. An entry for the same kind of
114
+ // screen as `screen` (or with no kind, or when no screen is given) counts in full; one from another kind of screen
115
+ // counts a quarter. Kept: +0.75 each, up to +2. Reverted: −1.5 each, down to −4.
116
+ export const HISTORY = { kept: 0.75, keptMax: 2, reverted: -1.5, revertedMin: -4, otherScreen: 0.25 };
117
+ function historyFor(id, history, screen) {
118
+ let kept = 0, reverted = 0;
119
+ const notes = [];
120
+ for (const h of history) {
121
+ if (!h || h.id !== id || (h.outcome !== "kept" && h.outcome !== "reverted")) continue;
122
+ const w = !screen || !h.kind || h.kind === screen ? 1 : HISTORY.otherScreen;
123
+ if (h.outcome === "kept") kept += w;
124
+ else reverted += w;
125
+ }
126
+ const adj = Math.min(HISTORY.keptMax, kept * HISTORY.kept) + Math.max(HISTORY.revertedMin, reverted * HISTORY.reverted);
127
+ const n = (x) => (Number.isInteger(x) ? x : x.toFixed(2));
128
+ if (kept) notes.push(`you kept it ${n(kept)}×${screen ? ` (weighted to ${screen})` : ""}`);
129
+ if (reverted) notes.push(`you reverted it ${n(reverted)}×${screen ? ` (weighted to ${screen})` : ""}`);
130
+ return { adj, notes };
131
+ }
132
+
133
+ /**
134
+ * Ranks moves for a brief. Score = fits overlap (1 per exact tag, 0.5 per family match) minus avoid overlap
135
+ * (1.5 per exact tag, 0.75 per family match), plus a little for a focused move (its fits mostly matched), plus the
136
+ * user's history with it (see HISTORY: kept moves rise, reverted ones sink, weighted to `screen`, the kind of screen
137
+ * being built). Filters by kind (the move's kind; one or several) and signature; drops excluded ids (e.g. moves this
138
+ * project used recently). With no tags, every move that passes the filters comes back, ranked by history alone, then
139
+ * signature moves first.
140
+ */
141
+ export function matchMoves({ tags = [], kind, signature, exclude = [], limit = 8, history = [], screen } = {}) {
142
+ const q = [...new Set(list(tags).flatMap((t) => t.split(",")).map((t) => t.trim().toLowerCase()).filter(Boolean))];
143
+ const kinds = list(kind).flatMap((k) => k.split(",")).map((k) => k.trim()).filter(Boolean);
144
+ const skip = new Set(list(exclude));
145
+ const past = Array.isArray(history) ? history : [];
146
+ const rows = loadMoves()
147
+ .filter((mv) => !skip.has(mv.id))
148
+ .filter((mv) => !kinds.length || kinds.includes(mv.kind))
149
+ .filter((mv) => signature == null || mv.signature === Boolean(signature))
150
+ .map((mv) => {
151
+ const f = hits(q, mv.fits);
152
+ const a = hits(q, mv.avoid);
153
+ const fit = f.exact.length + 0.5 * f.partial.length;
154
+ const focus = mv.fits.length ? (f.exact.length + 0.5 * f.partial.length) / mv.fits.length : 0;
155
+ const base = q.length ? fit - 1.5 * a.exact.length - 0.75 * a.partial.length + 0.25 * focus : 0;
156
+ const h = historyFor(mv.id, past, screen);
157
+ const score = Math.round((base + h.adj) * 100) / 100;
158
+ const parts = [];
159
+ if (f.exact.length || f.partial.length) parts.push(`fits ${[...f.exact, ...f.partial.map((t) => `~${t}`)].join(", ")}`);
160
+ if (a.exact.length || a.partial.length) parts.push(`but avoid ${[...a.exact, ...a.partial.map((t) => `~${t}`)].join(", ")}`);
161
+ parts.push(...h.notes);
162
+ parts.push(`${mv.signature ? "signature " : ""}${mv.kind}, effort ${mv.effort}`);
163
+ return { id: mv.id, name: mv.name, kind: mv.kind, signature: mv.signature, effort: mv.effort, score, base, reason: parts.join("; "), move: mv };
164
+ })
165
+ // With tags, only moves that fit (before history: a kept move still has to suit this brief).
166
+ .filter((r) => !q.length || (r.base > 0 && r.score > 0));
167
+ rows.sort((a, b) => b.score - a.score || Number(b.signature) - Number(a.signature) || a.id.localeCompare(b.id));
168
+ return rows.slice(0, Math.max(0, Number(limit) || 0) || rows.length).map(({ base, ...r }) => r);
169
+ }
170
+
171
+ export function getMove(id) {
172
+ return loadMoves().find((mv) => mv.id === id) ?? null;
173
+ }
174
+
175
+ // One move in full, for `palate moves show`.
176
+ export function showMove(id) {
177
+ const mv = getMove(id);
178
+ if (!mv) return `No move "${id}". Run palate moves to list them.`;
179
+ return [
180
+ `# ${mv.name} (${mv.id})`,
181
+ `kind: ${mv.kind} · effort: ${mv.effort}${mv.signature ? " · signature" : ""}${mv.deps && mv.deps !== "none" ? ` · deps: ${mv.deps}` : ""}`,
182
+ `fits: ${mv.fits.join(", ")}`,
183
+ `avoid: ${mv.avoid.join(", ") || "-"}`,
184
+ `perf: ${mv.perf}`,
185
+ `a11y: ${mv.a11y}`,
186
+ mv.pairs_with.length ? `pairs with: ${mv.pairs_with.join(", ")}` : null,
187
+ "",
188
+ mv.body,
189
+ ]
190
+ .filter((l) => l != null)
191
+ .join("\n");
192
+ }
193
+
194
+ const firstPara = (s = "") => s.split(/\n\s*\n/)[0].replace(/\s+/g, " ").trim();
195
+
196
+ /** The chosen moves' recipes as compact Markdown, for a build brief: what it is, the recipe, pitfalls, how to verify. */
197
+ export function moveBrief(ids) {
198
+ const all = loadMoves();
199
+ const out = [];
200
+ for (const id of list(ids).flatMap((x) => x.split(","))) {
201
+ const mv = all.find((x) => x.id === id.trim());
202
+ if (!mv) {
203
+ out.push(`### ${id}\n(no such move)`);
204
+ continue;
205
+ }
206
+ const s = mv.sections;
207
+ out.push(
208
+ [
209
+ `### ${mv.name} (${mv.id}) · ${mv.kind}, effort ${mv.effort}${mv.signature ? ", signature" : ""}`,
210
+ firstPara(s["What it is"]),
211
+ `- perf: ${mv.perf}`,
212
+ `- a11y: ${mv.a11y}`,
213
+ mv.deps && mv.deps !== "none" ? `- deps: ${mv.deps}` : null,
214
+ "",
215
+ "**Recipe**",
216
+ s["Recipe"],
217
+ "",
218
+ "**Pitfalls**",
219
+ s["Pitfalls"],
220
+ "",
221
+ "**Verify**",
222
+ s["How to verify"],
223
+ ]
224
+ .filter((l) => l != null)
225
+ .join("\n"),
226
+ );
227
+ }
228
+ return out.join("\n\n");
229
+ }
230
+
231
+ // The ranked list as text, for `palate moves` and the MCP tool.
232
+ export function movesReport(rows, { tags = [], kind, signature } = {}) {
233
+ if (!rows.length) return "No moves match. Try other tags, or palate moves with no filters.";
234
+ const head = [tags.length ? `tags ${list(tags).join(", ")}` : null, kind ? `kind ${list(kind).join(", ")}` : null, signature ? "signature only" : null].filter(Boolean).join(" · ");
235
+ return [
236
+ head ? `Moves for ${head}:` : `All moves (${rows.length}):`,
237
+ "",
238
+ ...rows.map((r) => `${r.id.padEnd(36)} ${String(r.kind).padEnd(20)} ${tags.length ? String(r.score).padStart(5) + " " : ""}${r.reason}`),
239
+ "",
240
+ "Read one in full: palate moves show <id>",
241
+ ].join("\n");
242
+ }
@@ -0,0 +1,116 @@
1
+ // Originality check for `palate shoot`: compares a page with the screens built before (its skeleton in this
2
+ // project; skeleton, first-screen shape, type, colour and picture against the layout memory of every project
3
+ // on this machine) and names any AI defaults found on it. Every shot joins the layout memory.
4
+ import crypto from "node:crypto";
5
+ import fs from "node:fs";
6
+ import path from "node:path";
7
+ import { PALATE_HOME } from "./catalog/store.mjs";
8
+ import { loadMoves } from "./concept.mjs";
9
+ import { DUPLICATE, SIMILAR, compare, layoutRecord, appendLayouts, isProjectDir, readLayouts, sameScreen, skeletonSimilarity, whereOf } from "./loop/layouts.mjs";
10
+ import { gateLines, saveGate, similarityGate } from "./loop/similar.mjs";
11
+ import { REF_CLOSE, REF_TOO_CLOSE, referenceMatches } from "./loop/research.mjs";
12
+
13
+ // ---- palate research: ideas, never the expression. A page too close to a captured reference fails; a build
14
+ // from a research direction is reminded of the signature moment it promised.
15
+ export function referenceLines(dir, route, rec) {
16
+ const out = [];
17
+ const refs = referenceMatches(dir, rec);
18
+ const fail = refs.filter((m) => m.total >= REF_TOO_CLOSE);
19
+ const close = refs.filter((m) => m.total >= REF_CLOSE && m.total < REF_TOO_CLOSE);
20
+ for (const m of fail.slice(0, 2)) out.push(`- ✗ Originality FAILS: too close to the research reference ${m.name} (${m.url}), ${Math.round(m.total * 100)}% (structure ${Math.round(m.structure * 100)}%). Use the ideas, never the expression: change the first screen's structure and the signature moves so it looks like this product, not that site.`);
21
+ for (const m of close.slice(0, 2)) out.push(`- ⚠ Close to the research reference ${m.name} (${Math.round(m.total * 100)}%): make sure nothing looks lifted from it.`);
22
+ if (refs.length && !fail.length && !close.length) out.push(`- Distinct from all ${refs.length} research references (closest ${refs[0].name}, ${Math.round(refs[0].total * 100)}%).`);
23
+ try {
24
+ const root = path.join(dir, ".palate", "variants");
25
+ for (const n of fs.existsSync(root) ? fs.readdirSync(root) : []) {
26
+ const meta = readJson(path.join(root, n, "loop.json"), null);
27
+ const sig = meta?.mode === "build" && meta.route === route ? meta.direction?.signature : null;
28
+ if (sig) out.push(`- Signature moment promised by the direction "${meta.direction.idea}": ${sig.move}: ${sig.moment}. Open the screenshot and confirm it is on the page and works; it is the point of this build.`);
29
+ }
30
+ } catch {}
31
+ return out;
32
+ }
33
+
34
+ const GLOBAL = path.join(PALATE_HOME, "fingerprints.json");
35
+ const readJson = (f, fallback) => {
36
+ try {
37
+ return JSON.parse(fs.readFileSync(f, "utf8"));
38
+ } catch {
39
+ return fallback;
40
+ }
41
+ };
42
+
43
+ export const similarity = skeletonSimilarity;
44
+
45
+ // The newest first-screen shot of this route at desktop width, as shoot just wrote it.
46
+ function latestFold(dir, route) {
47
+ const slug = route.replace(/[^a-z0-9]+/gi, "-").replace(/^-|-$/g, "") || "home";
48
+ const d = path.join(dir, ".palate", "shots", slug);
49
+ if (!fs.existsSync(d)) return null;
50
+ const shots = fs.readdirSync(d).map((f) => f.match(/^r(\d+)-w(\d+)-fold\.png$/)).filter((m) => m && Number(m[2]) >= 1000).sort((x, y) => Number(y[1]) - Number(x[1]));
51
+ return shots.length ? path.join(d, shots[0][0]) : null;
52
+ }
53
+
54
+ // Which loop a route belongs to (pricing-a1 → pricing), if that loop exists here.
55
+ function loopOf(dir, route) {
56
+ const m = route.match(/^\/(.+)-[a-z]\d+$/);
57
+ const meta = m && readJson(path.join(dir, ".palate", "variants", m[1], "loop.json"), null);
58
+ return meta ? { loop: m[1], meta } : null;
59
+ }
60
+
61
+ // like: projects the user asked to match (the similarity gate lets their look through). The returned lines carry
62
+ // the gate's result as .gate.
63
+ // The record palate compares a shot page by, built one way for palate shoot and the quality gate (the gate built a
64
+ // bare one, so the same Moveday page was 40% like another project at the shoot and 48% at the gate).
65
+ export function shotRecord(dir, route, fp) {
66
+ const owner = loopOf(dir, route);
67
+ return layoutRecord(dir, route, fp, { file: latestFold(dir, route), loop: owner?.loop, meta: owner?.meta, source: owner ? "variant" : "screen" });
68
+ }
69
+
70
+ export function noveltyReport(dir, route, fp, { like = [] } = {}) {
71
+ const project = crypto.createHash("sha1").update(path.resolve(dir).toLowerCase()).digest("hex").slice(0, 12);
72
+ const localFile = path.join(dir, ".palate", "fingerprints.json");
73
+ const local = readJson(localFile, {});
74
+ const global = readJson(GLOBAL, []);
75
+ const what = Object.fromEntries((loadMoves().cliches ?? []).map((c) => [c.id, c.what]));
76
+ const cliches = fp.cliches.includes("centred-hero") && fp.cliches.includes("glow") ? [...fp.cliches.filter((c) => c !== "centred-hero" && c !== "glow"), "centred-hero-glow"] : fp.cliches.filter((c) => c !== "glow");
77
+
78
+ const out = ["## Originality", `- Skeleton: ${fp.skeleton.join(" · ") || "(no bands found)"} (C/L centred or left-led, digit = layout columns, w framed panel, m big media, gN grid of N equal items, b own background)`];
79
+ if (cliches.length) out.push(`- ⚠ AI defaults on this page: ${cliches.map((c) => `${c}${what[c] ? ` (${what[c]})` : ""}`).join("; ")}. Keep one only if the concept needs it, and then change it in a way the concept explains; otherwise replace it with a move from palate concept.`);
80
+ const siblings = Object.entries(local)
81
+ .filter(([r]) => r !== route)
82
+ .map(([r, f]) => [r, similarity(fp.skeleton, f.skeleton)])
83
+ .filter(([, s]) => s >= 0.6)
84
+ .sort((a, b) => b[1] - a[1]);
85
+ if (siblings.length) out.push(`- Same skeleton as ${siblings.slice(0, 3).map(([r, s]) => `${r} (${Math.round(s * 100)}%)`).join(", ")} in this project. Expected for sibling screens of one tool; a problem for pages meant to stand apart.`);
86
+ // The layout memory, across every project on this machine.
87
+ const owner = loopOf(dir, route);
88
+ const rec = shotRecord(dir, route, fp);
89
+ const matches = readLayouts()
90
+ .filter((h) => !(h.pid === rec.pid && h.route === route) && !(owner && h.pid === rec.pid && h.loop === owner.loop && h.run === rec.run))
91
+ .map((h) => ({ ...h, samePlace: h.pid === rec.pid, total: compare(rec, h).total }))
92
+ .sort((a, b) => b.total - a.total);
93
+ // Only screens of the same kind (a landing page against a pricing variant tells nobody much).
94
+ const elsewhere = matches.filter((m) => !m.samePlace && m.total >= SIMILAR && sameScreen(rec, m));
95
+ const here = matches.filter((m) => m.samePlace && m.total >= DUPLICATE);
96
+ if (rec.moves) out.push(`- Signature: ${rec.moves.hero}; product: ${rec.moves.product}; type: ${rec.moves.type}; palette: ${rec.moves.palette}`);
97
+ // Other projects: the similarity gate decides (below); only matches it lets through are mentioned here.
98
+ const gate = similarityGate(dir, route, rec, { like });
99
+ const gated = new Set([...gate.hits, ...gate.matched].map((h) => h.project));
100
+ for (const m of elsewhere.filter((x) => !gated.has(x.project) && x.total > 0.5).slice(0, 3)) out.push(`- ⚠ ${m.total >= DUPLICATE ? "Repeats" : "Close to"} ${whereOf(m)}, made ${m.at.slice(0, 10)} in another project (${Math.round(m.total * 100)}%). ${m.total >= DUPLICATE ? "This is the same design again: change the structure of the first screen and the signature moves, so it belongs to this product, not the last one." : "Make sure it belongs to this product, not the last one."}`);
101
+ for (const m of here.slice(0, 2))
102
+ out.push(!owner && m.picked ? `- The shipped version of ${m.route}, the variant the user picked (${Math.round(m.total * 100)}%).` : `- ${owner && m.loop === owner.loop ? "Repeats an earlier run of this loop" : "Repeats"}: ${m.route}${m.picked ? " (picked)" : ""}, made ${m.at.slice(0, 10)} (${Math.round(m.total * 100)}%).`);
103
+ if (!cliches.length && !siblings.length && !here.length) out.push("- No AI defaults found and no repeat of earlier screens.");
104
+ // palate research: this page against every page the project's research looked at, and the promised signature.
105
+ out.push(...referenceLines(dir, route, rec));
106
+
107
+ local[route] = { skeleton: fp.skeleton, cliches, at: new Date().toISOString() };
108
+ fs.writeFileSync(localFile, JSON.stringify(local, null, 2));
109
+ fs.mkdirSync(PALATE_HOME, { recursive: true });
110
+ const kept = global.filter((g) => !(g.project === project && g.route === route));
111
+ kept.push({ project, route, skeleton: fp.skeleton, at: new Date().toISOString() });
112
+ fs.writeFileSync(GLOBAL, JSON.stringify(kept.slice(-300), null, 2));
113
+ if (isProjectDir(dir)) appendLayouts([rec]);
114
+ saveGate(dir, route, gate);
115
+ return Object.assign([...out, "", ...gateLines(gate, route)], { gate });
116
+ }