@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
@@ -0,0 +1,645 @@
1
+ // The look fingerprint: a page's visual language as a few measured categories (its ground, texture, faces,
2
+ // call to action, header, hero composition, how the hero's object is framed, imagery, density, accent), and the
3
+ // house-look check built on it. The similarity gate (similar.mjs) compares structure and colour numbers; it
4
+ // passed four of five benchmark pages that a person saw as one house style: warm off-white paper with grain,
5
+ // logo left with a light outlined CTA top right, a big headline left over a grey paragraph, a filled button and an
6
+ // underlined link, a framed product card with a soft shadow, muted neutrals and one accent. Those pages differ in
7
+ // skeleton and hue, and match in these categories.
8
+ //
9
+ // Calibration (Oct 29 2026): palate's pages (Kiln v2, Tracewell, Mabel's, Open Shelf, Mira: benchmark builds;
10
+ // palate-site live) and four real sites, each at 1440 with reduced motion, scrolled through. As measured:
11
+ // kiln2 warm off-white paper with grain · serif headline over sans body · split hero with a framed card with a
12
+ // soft shadow · solid rounded CTA + underlined link · logo-left nav, outline CTA top right · one mid blue
13
+ // accent · product-ui imagery · balanced
14
+ // tracewell warm off-white paper with grain · bold display-face headline over sans body · object-first hero with a
15
+ // framed card with a soft shadow · solid rounded CTA + ghost button · logo-left nav, outline CTA top
16
+ // right · one mid red-orange accent · mixed imagery · dense
17
+ // mabels warm off-white paper with grain · serif headline over sans body · split hero with a framed card with a
18
+ // soft shadow · solid rounded CTA + underlined link · logo-left nav, outline CTA top right · one muted
19
+ // green accent · mixed imagery · balanced
20
+ // open-shelf warm off-white paper with grain · bold sans headline, sans body · object-first hero with a framed card
21
+ // with a soft shadow · solid rounded CTA + underlined link · logo-left nav, outline CTA top right · one
22
+ // mid red-orange accent · mixed imagery · balanced
23
+ // mira dark ground with grain · serif headline over sans body · gallery hero with a framed card with a soft
24
+ // shadow · solid square CTA · logo-left nav, outline CTA top right · one mid red-orange accent · photo imagery
25
+ // site full-bleed photo ground with grain · sans headline, sans body · full-bleed media hero · solid rounded
26
+ // CTA · logo-left nav, solid CTA top right · one mid green accent · product-ui imagery
27
+ // linear dark ground with grain · sans · object-first hero, edge to edge · text-link CTA · solid pill CTA top right
28
+ // stripe white paper · light sans headline, sans body · full-bleed media hero (the canvas wave) · solid rounded CTA
29
+ // notion white paper · bold sans · centred hero with a framed card with a soft shadow · two solid CTAs · 3 colours
30
+ // raycast dark ground · bold sans · centred hero · solid rounded CTA · one vivid red accent
31
+ //
32
+ // lookSimilarity:
33
+ // kiln2 trace mabel shelf mira site linear stripe notion raycast
34
+ // kiln2 - 0.56 0.83 0.59 0.44 0.25 0.26 0.15 0.21 0.09
35
+ // tracewell 0.56 - 0.60 0.72 0.36 0.29 0.38 0.27 0.29 0.23
36
+ // mabels 0.83 0.60 - 0.63 0.48 0.25 0.30 0.17 0.21 0.13
37
+ // open-shelf 0.59 0.72 0.63 - 0.36 0.37 0.46 0.33 0.37 0.31
38
+ // mira 0.44 0.36 0.48 0.36 - 0.17 0.34 0.13 0.25 0.35
39
+ // palate-site 0.25 0.29 0.25 0.37 0.17 - 0.42 0.48 0.20 0.20
40
+ // linear 0.26 0.38 0.30 0.46 0.34 0.42 - 0.38 0.26 0.42
41
+ // stripe 0.15 0.27 0.17 0.33 0.13 0.48 0.38 - 0.46 0.28
42
+ // notion 0.21 0.29 0.21 0.37 0.25 0.20 0.26 0.46 - 0.48
43
+ // raycast 0.09 0.23 0.13 0.31 0.35 0.20 0.42 0.28 0.48 -
44
+ //
45
+ // The four house-look siblings score 0.56–0.83 against each other; every other pair is at most 0.48 (Mabel's vs
46
+ // Mira, two palate pages sharing a serif, grain and the outlined header button; Notion vs Raycast; palate-site vs
47
+ // Stripe). HOUSE_LOOK_FAIL 0.53 fails every sibling pair and no other; HOUSE_LOOK_WARN 0.50 says so a step before,
48
+ // above every independent pair. With the plain weights (every exact match full credit) the real sites converged on
49
+ // the choices nearly every site makes (Notion vs Raycast 0.72 against Kiln vs Tracewell 0.58), so a match on such
50
+ // a default counts half (COMMON), and the header's CTA and the action beside the primary button count inside their
51
+ // axes: then the groups separate.
52
+ import fs from "node:fs";
53
+ import path from "node:path";
54
+ import { fileURLToPath } from "node:url";
55
+ import { stackGenre, fontGenre, FONT_GENRES } from "../fontgenre.mjs";
56
+ import { PALATE_HOME } from "../catalog/store.mjs";
57
+ import { buttonSimilarity, comparableButtonAxes, describeButtons, otherLanguages, resolveButtons, BUTTON_LANGUAGES } from "./buttons.mjs";
58
+
59
+ const here = path.dirname(fileURLToPath(import.meta.url));
60
+ const lookScript = fs.readFileSync(path.join(here, "..", "page-look.js"), "utf8").trim().replace(/;\s*$/, "");
61
+
62
+ export const LOOKS = path.join(PALATE_HOME, "history", "looks.jsonl");
63
+ export const HOUSE_LOOK_FAIL = 0.53;
64
+ export const HOUSE_LOOK_WARN = 0.5;
65
+ export const RECENT = 12;
66
+
67
+ // The class names (shared with the blueprint's planned look).
68
+ export const AXES = {
69
+ ground: ["white", "light-warm", "light-cool", "light-neutral", "mid", "dark", "colour", "photo"],
70
+ header: ["logo-left-nav-cta", "centred-wordmark", "logo-cta", "split", "overlay", "side", "none"],
71
+ cta: ["solid-rounded", "solid-pill", "solid-square", "outline", "text-link", "gradient"],
72
+ hero: ["split", "split-reversed", "centred", "full-bleed", "type-only", "object-first", "editorial", "gallery"],
73
+ frame: ["shadow-card", "border-card", "flat", "bleed", "none"],
74
+ imagery: ["product-ui", "photo", "illustration", "type-only", "mixed"],
75
+ density: ["airy", "balanced", "dense"],
76
+ };
77
+ // buttons: the whole button language (shape, fill, size, label, adornment, the second action and, measured, the
78
+ // finish), next to cta's coarse fill-and-shape class. One axis among eleven: the same button on two pages adds to
79
+ // a shared look, it doesn't make one (the button check below says it on its own).
80
+ export const WEIGHTS = { ground: 2, texture: 1, display: 2, body: 0.5, header: 1, cta: 1, buttons: 1, hero: 2, frame: 1, imagery: 1, accent: 0.5, density: 0.5 };
81
+ // Pairs that are near each other: half a match.
82
+ const NEAR = [
83
+ ["ground", "light-warm", "light-neutral"],
84
+ ["ground", "light-neutral", "white"],
85
+ ["ground", "light-cool", "light-neutral"],
86
+ ["ground", "light-cool", "white"],
87
+ ["ground", "mid", "dark"],
88
+ ["header", "logo-left-nav-cta", "logo-cta"],
89
+ ["header", "centred-wordmark", "split"],
90
+ ["cta", "solid-rounded", "solid-pill"],
91
+ ["cta", "solid-rounded", "solid-square"],
92
+ ["cta", "solid-rounded", "gradient"],
93
+ ["cta", "solid-pill", "gradient"],
94
+ ["hero", "split", "split-reversed"],
95
+ // A headline beside or over a product object: Tracewell's text-over-a-wide-framed-board is Kiln's split recipe
96
+ // stacked, and a person reads them as one hero.
97
+ ["hero", "split", "object-first"],
98
+ ["hero", "centred", "object-first"],
99
+ ["hero", "type-only", "editorial"],
100
+ ["hero", "full-bleed", "object-first"],
101
+ ["hero", "centred", "type-only"],
102
+ ["frame", "shadow-card", "border-card"],
103
+ ["frame", "flat", "none"],
104
+ ["imagery", "mixed", "product-ui"],
105
+ ["imagery", "mixed", "photo"],
106
+ ["imagery", "mixed", "illustration"],
107
+ ["density", "airy", "balanced"],
108
+ ["density", "balanced", "dense"],
109
+ ];
110
+ const nearSet = new Set(NEAR.flatMap(([a, x, y]) => [`${a}:${x}:${y}`, `${a}:${y}:${x}`]));
111
+
112
+ // ---- colour: sRGB hex → OKLab lightness, chroma and hue
113
+ const hexRgb = (h) => (h && /^#[0-9a-f]{6}$/i.test(h) ? [1, 3, 5].map((i) => parseInt(h.slice(i, i + 2), 16)) : null);
114
+ export function oklch(hexColour) {
115
+ const rgb = hexRgb(hexColour);
116
+ if (!rgb) return null;
117
+ const lin = rgb.map((v) => {
118
+ const c = v / 255;
119
+ return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
120
+ });
121
+ const l = Math.cbrt(0.4122214708 * lin[0] + 0.5363325363 * lin[1] + 0.0514459929 * lin[2]);
122
+ const m = Math.cbrt(0.2119034982 * lin[0] + 0.6806995451 * lin[1] + 0.1073969566 * lin[2]);
123
+ const s = Math.cbrt(0.0883024619 * lin[0] + 0.2817188376 * lin[1] + 0.6299787005 * lin[2]);
124
+ const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;
125
+ const a = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;
126
+ const b = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;
127
+ const C = Math.hypot(a, b);
128
+ let H = (Math.atan2(b, a) * 180) / Math.PI;
129
+ if (H < 0) H += 360;
130
+ return { L, C, H };
131
+ }
132
+
133
+ // The class of a ground colour.
134
+ export function groundClass(hexColour) {
135
+ const c = oklch(hexColour);
136
+ if (!c) return null;
137
+ const { L, C, H } = c;
138
+ if (C >= 0.075 || (L < 0.86 && L > 0.3 && C >= 0.05)) return "colour";
139
+ if (L >= 0.86) {
140
+ if (L >= 0.985 && C < 0.006) return "white";
141
+ // Warm: cream, beige, paper (OKLab hue from red-orange through yellow). Cool: blue-grey, mint, ice.
142
+ if (C >= 0.006 && H >= 20 && H <= 125) return "light-warm";
143
+ if (C >= 0.006 && H >= 150 && H <= 290) return "light-cool";
144
+ return "light-neutral";
145
+ }
146
+ if (L <= 0.36) return "dark";
147
+ return "mid";
148
+ }
149
+ const CHROMA = (C) => (C < 0.09 ? "muted" : C < 0.16 ? "mid" : "vivid");
150
+ const SAT = 0.06; // a colour is "saturated" (an accent, not a neutral) from this OKLab chroma
151
+ const hueBucket = (H) => Math.floor(((H % 360) + 360) % 360 / 30);
152
+ // OKLab hue angles (not HSL): red sits near 25°, orange 55°, yellow 100°, green 145°, cyan 195°, blue 265°, violet 315°.
153
+ const HUE_NAMES = ["red", "red-orange", "orange", "yellow", "lime", "green", "teal", "sky", "blue", "indigo", "violet", "pink"];
154
+
155
+ // A family stack's genre, after removing what font loaders add (Next's "__Fraunces_6f2b1c", "Fraunces Variable",
156
+ // "Inter Fallback") and trying the known families by prefix ("Tiempos Headline" → tiempos → serif).
157
+ const KNOWN = Object.entries(FONT_GENRES).flatMap(([g, names]) => names.map((n) => [n, g])).sort((a, b) => b[0].length - a[0].length);
158
+ export function familyGenre(stack) {
159
+ const parts = String(stack ?? "")
160
+ .split(",")
161
+ .map((x) =>
162
+ x
163
+ .replace(/["']/g, "")
164
+ .trim()
165
+ .replace(/^_+/, "")
166
+ .replace(/_(fallback_)?[0-9a-f]{5,}$/i, "")
167
+ .replace(/_/g, " ")
168
+ .replace(/\b(variable|vf|fallback|web|webfont)\b/gi, "")
169
+ .trim(),
170
+ )
171
+ .filter(Boolean);
172
+ // Known families first, exact then by prefix ("SF Pro Display" is SF Pro, a sans, not a display face), then the
173
+ // name's own words (fontgenre.mjs).
174
+ for (const p of parts) {
175
+ const lower = p.toLowerCase();
176
+ const hit = KNOWN.find(([n]) => lower === n) ?? KNOWN.find(([n]) => n.length >= 4 && lower.startsWith(n + " "));
177
+ if (hit) return hit[1];
178
+ const g = fontGenre(p);
179
+ if (g !== "unknown") return g;
180
+ }
181
+ return stackGenre(parts.join(", "));
182
+ }
183
+ const firstFamily = (stack) => String(stack ?? "").split(",")[0].replace(/["']/g, "").trim().replace(/^_+/, "").replace(/_(fallback_)?[0-9a-f]{5,}$/i, "").replace(/_/g, " ");
184
+
185
+ // ---- raw page facts → the look vector
186
+ export function vectorFrom(raw) {
187
+ const area = raw.width * raw.pageH;
188
+ // Ground: band colours by height, photo bands left out; a picture that covers the first screen is the ground.
189
+ // The first screen counts three times over: a reader takes the page's ground from it (Mira's dark contact-sheet
190
+ // hero over a light page reads as a dark page).
191
+ const byClass = new Map();
192
+ const byHex = new Map();
193
+ const vh = raw.vh ?? 900;
194
+ for (const b of raw.bands ?? []) {
195
+ if (b.photo) continue;
196
+ const k = groundClass(b.bg);
197
+ if (!k) continue;
198
+ const h = b.h + 2 * Math.max(0, Math.min(b.y + b.h, vh) - Math.max(b.y, 0));
199
+ byClass.set(k, (byClass.get(k) ?? 0) + h);
200
+ byHex.set(b.bg, (byHex.get(b.bg) ?? 0) + h);
201
+ }
202
+ const top = (m) => [...m.entries()].sort((a, b) => b[1] - a[1])[0]?.[0] ?? null;
203
+ const groundHex = top(byHex) ?? raw.rootBg;
204
+ const ground = raw.firstScreenPhoto ? "photo" : top(byClass) ?? groundClass(raw.rootBg) ?? "white";
205
+ const groundBands = (raw.bands ?? []).map((b) => (b.photo ? "photo" : groundClass(b.bg) ?? "?"));
206
+
207
+ const d = raw.display;
208
+ const display = d
209
+ ? {
210
+ genre: familyGenre(d.family),
211
+ family: firstFamily(d.family),
212
+ weight: d.weight <= 350 ? "light" : d.weight >= 800 ? "black" : d.weight >= 600 ? "bold" : "regular",
213
+ case: d.upper ? "upper" : "normal",
214
+ italic: Boolean(d.italic),
215
+ size: d.size <= 48 ? "s" : d.size <= 80 ? "m" : "l",
216
+ px: d.size,
217
+ tracking: d.tracking < -0.01 ? "tight" : d.tracking > 0.04 ? "wide" : "normal",
218
+ }
219
+ : null;
220
+ const body = raw.body ? { genre: familyGenre(raw.body), family: firstFamily(raw.body) } : null;
221
+
222
+ // Accent: the primary CTA's fill when it is saturated, else the most used saturated colour (fills by area,
223
+ // text by its ink). Colourfulness: saturated hues that cover a large area (2% of the page or more).
224
+ const sat = (h) => {
225
+ const c = oklch(h);
226
+ return c && c.C >= SAT && c.L > 0.2 && c.L < 0.97 ? c : null;
227
+ };
228
+ let accentHex = raw.cta?.fill && sat(raw.cta.fill) ? raw.cta.fill : null;
229
+ if (!accentHex) {
230
+ const use = new Map();
231
+ for (const f of [...(raw.fills ?? []), ...(raw.textColours ?? [])]) if (sat(f.hex)) use.set(f.hex, (use.get(f.hex) ?? 0) + f.a);
232
+ accentHex = top(use);
233
+ }
234
+ const ac = accentHex ? oklch(accentHex) : null;
235
+ const hueArea = new Map();
236
+ for (const f of raw.fills ?? []) {
237
+ const c = sat(f.hex);
238
+ if (c) hueArea.set(hueBucket(c.H), (hueArea.get(hueBucket(c.H)) ?? 0) + f.a);
239
+ }
240
+ const colourful = [...hueArea.values()].filter((a) => a >= 0.02 * area).length;
241
+ const accent = ac ? { hex: accentHex, hue: hueBucket(ac.H), hueName: HUE_NAMES[hueBucket(ac.H)], chroma: CHROMA(ac.C), colourful } : { hex: null, hue: null, hueName: null, chroma: "none", colourful };
242
+
243
+ const hdrCta = raw.header?.cta ?? "none";
244
+ const header = { pattern: raw.header?.pattern ?? "none", cta: hdrCta };
245
+ const ctaStyle = (s) => (!s ? "text-link" : s === "text-link-underlined" ? "text-link" : s === "outline-pill" ? "outline" : s);
246
+ const cta = { style: ctaStyle(raw.cta?.style), secondary: raw.secondary ?? "none", text: raw.cta?.text ?? null };
247
+ const buttons = measuredButtons(raw);
248
+
249
+ // Imagery: by area; nothing much is type-only; two modes each a third or more is mixed.
250
+ const ia = raw.imagery?.area ?? {};
251
+ const total = Object.values(ia).reduce((x, y) => x + y, 0);
252
+ let imagery;
253
+ if (!total || (raw.imagery?.share ?? 0) < 0.03) imagery = "type-only";
254
+ else {
255
+ const ranked = Object.entries(ia).sort((a, b) => b[1] - a[1]);
256
+ imagery = ranked[1] && ranked[1][1] >= 0.33 * total ? "mixed" : ranked[0][0];
257
+ }
258
+ // Density: ink over the first three screens (calibrated: sparse statement pages ~0.25, product pages 0.35–0.5,
259
+ // packed catalogues above 0.55).
260
+ const density = raw.ink < 0.3 ? "airy" : raw.ink > 0.55 ? "dense" : "balanced";
261
+
262
+ return {
263
+ v: 1,
264
+ ground,
265
+ groundHex,
266
+ groundBands,
267
+ texture: Boolean(raw.texture),
268
+ display,
269
+ body,
270
+ accent,
271
+ header,
272
+ cta,
273
+ buttons,
274
+ hero: raw.hero,
275
+ frame: raw.frame,
276
+ imagery,
277
+ density,
278
+ ink: raw.ink,
279
+ };
280
+ }
281
+
282
+ // The button language a page shows: the six axes of buttons.mjs plus the finish they're measured with.
283
+ const SEC_OF = { "underlined-link": "text-link", "text-link": "text-link", ghost: "ghost", solid: "solid", none: "none" };
284
+ export function measuredButtons(raw) {
285
+ const p = raw?.buttons?.primary;
286
+ if (!p) return null;
287
+ const boxless = p.fill === "underline" || p.fill === "ghost";
288
+ const share = p.h ? Math.min(p.radius, p.h / 2) / p.h : 0;
289
+ const shape = boxless ? "none" : p.radius <= 3 || share <= 0.08 ? "square" : share >= 0.45 ? "pill" : "soft";
290
+ const size = boxless ? (p.px >= 19 ? "large" : p.px <= 14 ? "compact" : "standard") : p.h < 40 ? "compact" : p.h < 54 ? "standard" : "large";
291
+ const genre = familyGenre(p.family);
292
+ const [mine, body, disp] = [firstFamily(p.family), firstFamily(raw.body), firstFamily(raw.display?.family)].map((x) => String(x ?? "").toLowerCase());
293
+ const label = genre === "mono" ? "mono" : p.upper ? "upper-tracked" : mine && mine !== body && (mine === disp || genre !== familyGenre(raw.body)) ? "display" : "sentence";
294
+ const sec = raw.buttons.secondaryStyle ?? raw.secondary ?? "none";
295
+ return {
296
+ shape,
297
+ fill: p.fill,
298
+ size,
299
+ label,
300
+ adornment: p.adornment ?? "none",
301
+ secondary: SEC_OF[sec] ?? "none",
302
+ finish: { h: p.h, radiusShare: +share.toFixed(2), px: p.px, weight: p.weight, tracking: p.tracking, edge: p.edge ?? null, genre, contrast: p.contrast, secondaryUnderlined: sec === "underlined-link" },
303
+ text: p.text ?? null,
304
+ };
305
+ }
306
+
307
+ // ---- similarity: weighted exact matches, near categories half. Missing axes (a planned look may have no
308
+ // density, accent or body yet) are skipped and the weights renormalised.
309
+ const axisValue = (v, axis) => {
310
+ if (!v) return undefined;
311
+ switch (axis) {
312
+ case "ground":
313
+ return v.ground;
314
+ case "texture":
315
+ return v.texture;
316
+ case "display":
317
+ return v.display?.genre ?? (typeof v.display === "string" ? v.display : undefined);
318
+ case "body":
319
+ return v.body?.genre ?? (typeof v.body === "string" ? v.body : undefined);
320
+ case "header":
321
+ return v.header?.pattern ?? (typeof v.header === "string" ? v.header : undefined);
322
+ case "cta":
323
+ return v.cta?.style ?? (typeof v.cta === "string" ? v.cta : undefined);
324
+ case "buttons":
325
+ // A language says enough to compare when it states at least four axes (a coarse cta says two or three).
326
+ return v.buttons && typeof v.buttons === "object" && AXIS_COUNT(v.buttons) >= 4 ? v.buttons : undefined;
327
+ case "hero":
328
+ return v.hero;
329
+ case "frame":
330
+ return v.frame;
331
+ case "imagery":
332
+ return v.imagery;
333
+ case "accent":
334
+ return v.accent?.hue ?? (typeof v.accent === "number" ? v.accent : undefined);
335
+ case "density":
336
+ return v.density;
337
+ }
338
+ };
339
+ const AXIS_COUNT = (b) => comparableButtonAxes(b, b).length;
340
+ const known = (x) => x !== undefined && x !== null && x !== "unknown" && x !== "?";
341
+
342
+ // The choices nearly every site makes: two pages sharing one of them says little about a shared look, so such a
343
+ // match counts half (without this, Notion and Raycast, both a sans over a sans with a logo-left nav and a solid
344
+ // rounded button and no texture, scored 0.72 and outranked two pages of palate's house style).
345
+ export const COMMON = { texture: [false], display: ["sans"], body: ["sans"], density: ["balanced"], header: ["logo-left-nav-cta"], cta: ["solid-rounded"] };
346
+ export const COMMON_CREDIT = 0.5;
347
+ // Two button languages this close are the same button (the five Nov 6 benchmark pages score 0.8–0.97 with each
348
+ // other; see the calibration under BUTTON_REPEAT_FAIL).
349
+ export const BUTTON_SAME = 0.8;
350
+ const sub = (a, b, key) => {
351
+ const x = a?.[key], y = b?.[key];
352
+ return x != null && y != null ? (x === y && x !== "none" ? 1 : 0) : null;
353
+ };
354
+
355
+ // { score 0–1, same: axes that match exactly, near: axes that match in part, parts: { axis: credit } }.
356
+ export function lookSimilarity(a, b) {
357
+ let sum = 0, weight = 0;
358
+ const same = [], near = [], parts = {};
359
+ for (const [axis, w] of Object.entries(WEIGHTS)) {
360
+ const x = axisValue(a, axis), y = axisValue(b, axis);
361
+ if (!known(x) || !known(y)) continue;
362
+ weight += w;
363
+ let s = 0;
364
+ if (axis === "buttons") {
365
+ const m = buttonSimilarity(x, y);
366
+ s = m.score;
367
+ if (s >= BUTTON_SAME) same.push(axis);
368
+ else if (s > 0) near.push(axis);
369
+ parts[axis] = +s.toFixed(2);
370
+ sum += w * s;
371
+ continue;
372
+ }
373
+ if (axis === "accent") {
374
+ const d = Math.min(Math.abs(x - y), 12 - Math.abs(x - y));
375
+ s = d === 0 ? 1 : d === 1 ? 0.5 : 0;
376
+ } else if (x === y) s = COMMON[axis]?.includes(x) ? COMMON_CREDIT : 1;
377
+ else if (nearSet.has(`${axis}:${x}:${y}`)) s = 0.5;
378
+ // The header's own CTA (the house look's light outlined button top right) is part of the header; the action
379
+ // beside the primary button (the underlined link) is part of the CTA. Only when both looks say.
380
+ if (axis === "header") {
381
+ const c = sub(a.header, b.header, "cta");
382
+ if (c != null) s = 0.6 * s + 0.4 * c;
383
+ }
384
+ if (axis === "cta") {
385
+ const c = sub(a.cta, b.cta, "secondary");
386
+ if (c != null) s = 0.7 * s + 0.3 * c;
387
+ }
388
+ if (x === y) same.push(axis);
389
+ else if (s > 0) near.push(axis);
390
+ parts[axis] = +s.toFixed(2);
391
+ sum += w * s;
392
+ }
393
+ return { score: weight ? +(sum / weight).toFixed(3) : 0, same, near, parts, weight };
394
+ }
395
+
396
+ // ---- in words
397
+ const GROUND_WORDS = { white: "white", "light-warm": "warm off-white", "light-cool": "cool light", "light-neutral": "light grey", mid: "mid-tone", dark: "dark", colour: "colour-field", photo: "full-bleed photo" };
398
+ const HERO_WORDS = { split: "split hero", "split-reversed": "split hero (object left)", centred: "centred hero", "full-bleed": "full-bleed media hero", "type-only": "type-only statement hero", "object-first": "object-first hero", editorial: "editorial-column hero", gallery: "gallery hero" };
399
+ const FRAME_WORDS = { "shadow-card": "a framed card with a soft shadow", "border-card": "a bordered card", flat: "an unframed object", bleed: "edge to edge", none: "no object" };
400
+ const HEADER_WORDS = { "logo-left-nav-cta": "logo-left nav", "centred-wordmark": "centred wordmark", "logo-cta": "logo and one action", split: "split nav around a centred logo", overlay: "header over the image", side: "side navigation", none: "no header" };
401
+ const CTA_WORDS = { "solid-rounded": "solid rounded CTA", "solid-pill": "solid pill CTA", "solid-square": "solid square CTA", outline: "outline CTA", "text-link": "text-link CTA", gradient: "gradient CTA" };
402
+ const HDR_CTA_WORDS = { "outline-pill": "pill CTA top right", outline: "outline CTA top right", "solid-pill": "solid pill CTA top right", "solid-rounded": "solid CTA top right", "solid-square": "square CTA top right", gradient: "gradient CTA top right", "text-link": "text links only", "text-link-underlined": "text links only", none: "no CTA" };
403
+ const SEC_WORDS = { "underlined-link": " + underlined link", "text-link": " + text link", ghost: " + ghost button", solid: " + second solid button", none: "" };
404
+
405
+ export function describeLook(v) {
406
+ if (!v) return "no look measured";
407
+ const parts = [];
408
+ parts.push(`${GROUND_WORDS[v.ground] ?? v.ground ?? "?"} ${v.ground === "photo" ? "ground" : "paper"}${v.texture ? " with grain" : ""}`.replace("paper", v.ground === "dark" || v.ground === "colour" || v.ground === "mid" ? "ground" : "paper"));
409
+ const dg = v.display?.genre ?? v.display;
410
+ const bg = v.body?.genre ?? v.body;
411
+ if (dg) {
412
+ const mods = [v.display?.case === "upper" ? "uppercase" : null, v.display?.italic ? "italic" : null, v.display?.weight && v.display.weight !== "regular" ? v.display.weight : null].filter(Boolean).join(" ");
413
+ const g = (x) => (x === "display" ? "display-face" : x);
414
+ parts.push(`${mods ? mods + " " : ""}${g(dg)} headline${bg ? (bg === dg ? `, ${g(bg)} body` : ` over ${g(bg)} body`) : ""}`);
415
+ }
416
+ if (v.hero) parts.push(`${HERO_WORDS[v.hero] ?? v.hero}${v.frame && v.frame !== "none" && v.hero !== "full-bleed" ? ` with ${FRAME_WORDS[v.frame] ?? v.frame}` : ""}`);
417
+ const ctaStyle = v.cta?.style ?? v.cta;
418
+ if (v.buttons && AXIS_COUNT(v.buttons) >= 4) parts.push(`button: ${describeButtons(v.buttons)}`);
419
+ else if (ctaStyle) parts.push(`${CTA_WORDS[ctaStyle] ?? ctaStyle}${SEC_WORDS[v.cta?.secondary] ?? ""}`);
420
+ const hp = v.header?.pattern ?? v.header;
421
+ if (hp) parts.push(`${HEADER_WORDS[hp] ?? hp}${v.header?.cta && hp !== "none" && hp !== "side" ? `, ${HDR_CTA_WORDS[v.header.cta] ?? v.header.cta}` : ""}`);
422
+ if (v.accent && v.accent.chroma) {
423
+ const n = v.accent.colourful ?? 0;
424
+ parts.push(v.accent.chroma === "none" ? "no accent colour" : n >= 3 ? `${n} colours in large areas, ${v.accent.chroma} ${v.accent.hueName} lead` : `one ${v.accent.chroma} ${v.accent.hueName} accent`);
425
+ }
426
+ if (v.imagery) parts.push(v.imagery === "type-only" ? "type only" : `${v.imagery} imagery`);
427
+ if (v.density) parts.push(v.density);
428
+ return parts.join(" · ");
429
+ }
430
+
431
+ // ---- measuring
432
+ // On an open page (any width ≥ 1000, scrolled through so reveals fired).
433
+ export async function measureLook(page, { sections } = {}) {
434
+ const secs = sections ?? (await (await import("../look.mjs")).findSections(page));
435
+ const raw = await page.evaluate(`(${lookScript})(${JSON.stringify({ sections: secs })})`);
436
+ return { look: vectorFrom(raw), raw };
437
+ }
438
+
439
+ // Renders the route at 1440 with reduced motion, scrolled through, and measures its look.
440
+ export async function lookOf(dir, route, { url, raw: withRaw = false } = {}) {
441
+ const { withBrowser, openPage, findSections } = await import("../look.mjs");
442
+ return withBrowser(dir, { url }, async ({ base, browser }) => {
443
+ const { page, ctx } = await openPage(browser, base, route, { width: 1440, reducedMotion: true });
444
+ try {
445
+ const sections = await findSections(page);
446
+ const m = await measureLook(page, { sections });
447
+ return withRaw ? m : m.look;
448
+ } finally {
449
+ await ctx.close();
450
+ }
451
+ });
452
+ }
453
+
454
+ // ---- the record: ~/.palate/history/looks.jsonl, one latest look per project and route
455
+ const readLines = (f) => {
456
+ try {
457
+ return fs
458
+ .readFileSync(f, "utf8")
459
+ .split("\n")
460
+ .filter(Boolean)
461
+ .map((l) => {
462
+ try {
463
+ return JSON.parse(l);
464
+ } catch {
465
+ return null;
466
+ }
467
+ })
468
+ .filter(Boolean);
469
+ } catch {
470
+ return [];
471
+ }
472
+ };
473
+ // One record per project and route: the latest line wins. The file is append-only, so parallel runs (five benchmark
474
+ // builds at once) never drop each other's records the way a read-filter-rewrite did.
475
+ const latestLooks = (file) => {
476
+ const by = new Map();
477
+ for (const r of readLines(file)) {
478
+ const key = `${r.pid}|${r.route}`;
479
+ by.delete(key);
480
+ by.set(key, r);
481
+ }
482
+ return [...by.values()];
483
+ };
484
+ export const readLooks = (file = LOOKS) => latestLooks(file);
485
+
486
+ export async function recordLook(dir, route, look, { screen, file = LOOKS, project } = {}) {
487
+ if (!look) return null;
488
+ const { projectId, isBenchRecord, isProjectDir, screenKindOf } = await import("./layouts.mjs");
489
+ // A throwaway folder that only shot someone else's page isn't a project: its record would be a copy of that one.
490
+ if (!isProjectDir(dir)) return null;
491
+ const name = project ?? path.basename(path.resolve(dir));
492
+ const pid = projectId(dir);
493
+ const bench = fs.existsSync(path.join(dir, ".palate", "bench.json")) || isBenchRecord({ project: name });
494
+ const rec = { project: name, pid, route, at: new Date().toISOString(), look, bench, screen: screen ?? screenKindOf({ route }) ?? null };
495
+ fs.mkdirSync(path.dirname(file), { recursive: true });
496
+ fs.appendFileSync(file, JSON.stringify(rec) + "\n");
497
+ return rec;
498
+ }
499
+
500
+ // The latest looks palate measured, newest first, without one project (the page being checked). Benchmark
501
+ // pages count: the point is palate's own output.
502
+ export function recentLooks({ excludePid, limit = RECENT, file = LOOKS } = {}) {
503
+ return latestLooks(file)
504
+ .filter((r) => r.look && r.pid !== excludePid)
505
+ .sort((a, b) => String(b.at).localeCompare(String(a.at)))
506
+ .slice(0, limit);
507
+ }
508
+
509
+ // The closest recent look in another project: { record, score, same, near } or null.
510
+ export function closestLook(look, { excludePid, exclude = [], limit = RECENT, file } = {}) {
511
+ const skip = new Set(exclude.map((x) => String(x).toLowerCase()));
512
+ let best = null;
513
+ for (const r of recentLooks({ excludePid, limit, file })) {
514
+ if (skip.has(String(r.project).toLowerCase())) continue;
515
+ const s = lookSimilarity(look, r.look);
516
+ if (!best || s.score > best.score) best = { record: r, ...s };
517
+ }
518
+ return best;
519
+ }
520
+
521
+ // ---- the house-look check
522
+ const AXIS_WORDS = { ground: "the ground", texture: "the grain", display: "the display face's genre", body: "the body face's genre", header: "the header", cta: "the button style", buttons: "the button language", hero: "the hero composition", frame: "the hero object's frame", imagery: "the imagery", accent: "the accent hue", density: "the density" };
523
+ const CHANGE = {
524
+ ground: (v) => `a ground of this product's own (not ${GROUND_WORDS[v.ground] ?? v.ground} again)`,
525
+ texture: (v) => (v.texture ? "drop the grain, or use a material that belongs to this product" : "a material that belongs to this product"),
526
+ display: (v) => `a display face that isn't a ${v.display?.genre ?? v.display}, chosen for this product's character`,
527
+ header: (v) => `a header that isn't ${HEADER_WORDS[v.header?.pattern ?? v.header] ?? "the same"} with ${HDR_CTA_WORDS[v.header?.cta] ?? "the same CTA"} (a centred wordmark, a split nav, over the image, or none)`,
528
+ cta: (v) => `another button language than the ${CTA_WORDS[v.cta?.style ?? v.cta] ?? "the same CTA"}${SEC_WORDS[v.cta?.secondary] ?? ""}`,
529
+ buttons: (v) => buttonChange(v.buttons),
530
+ hero: (v) => `a hero other than the ${HERO_WORDS[v.hero] ?? v.hero} (${AXES.hero.filter((h) => h !== v.hero && !nearSet.has(`hero:${h}:${v.hero}`)).slice(0, 4).join(", ")} …)`,
531
+ frame: (v) => `present the object other than as ${FRAME_WORDS[v.frame] ?? v.frame} (bleed it, set it flat, or let it be the page)`,
532
+ imagery: (v) => `another kind of imagery than ${v.imagery}`,
533
+ };
534
+ // What to change about a button, in words: two library languages far from it.
535
+ function buttonChange(b, tags) {
536
+ const alt = otherLanguages(b, { tags });
537
+ return `a button language of this product's own, not ${b ? `"${describeButtons(b)}"` : "the same button"} again (from the research; e.g. ${alt.map((n) => `${n}: ${BUTTON_LANGUAGES[n].words}`).join("; or ")})`;
538
+ }
539
+
540
+ // The axes that carry a match, most weight first: exact or near, worth at least half their weight.
541
+ const repeated = (m) => Object.entries(m.parts ?? {}).filter(([a, c]) => WEIGHTS[a] >= 1 && c >= 0.5).sort((x, y) => WEIGHTS[y[0]] * y[1] - WEIGHTS[x[0]] * x[1]).map(([a]) => a);
542
+ const listWords = (xs) => (xs.length <= 1 ? xs.join("") : `${xs.slice(0, -1).join(", ")} and ${xs.at(-1)}`);
543
+
544
+ // One floor-style check ({ id, width, section, severity, what, fix }) or null. like: projects the user asked to
545
+ // match (their look is allowed). keep: an existing page whose blueprint kept the brand (exempt).
546
+ export function houseLookFinding(look, { excludePid, like = [], file, fail = HOUSE_LOOK_FAIL, warn = HOUSE_LOOK_WARN } = {}) {
547
+ const best = closestLook(look, { excludePid, exclude: like, file });
548
+ if (!best || best.score < warn) return { check: null, best };
549
+ const severity = best.score >= fail ? "fail" : "warn";
550
+ const strong = repeated(best);
551
+ const who = `${best.record.project} ${best.record.route}${best.record.bench ? " (a palate benchmark page)" : ""}`;
552
+ const sameButton = (best.parts?.buttons ?? 0) >= BUTTON_SAME ? `; the same button: ${describeButtons(look.buttons)}` : "";
553
+ const what = `the look is ${Math.round(best.score * 100)}% like ${who} (house-look gate ${Math.round(fail * 100)}%): ${listWords(strong.slice(0, 5).map((a) => AXIS_WORDS[a]))} all repeat ${best.record.project}'s ("${describeLook(best.record.look)}")${sameButton}`;
554
+ const fix = `Change at least two of ${listWords(strong.filter((a) => CHANGE[a]).slice(0, 3).map((a) => AXIS_WORDS[a]))}, from this product's own research: ${strong.filter((a) => CHANGE[a]).slice(0, 2).map((a) => CHANGE[a](look)).join("; ")}.`;
555
+ return { check: { id: "HOUSE_LOOK", width: 1440, section: null, severity, what, fix, score: best.score, against: `${best.record.project} ${best.record.route}` }, best };
556
+ }
557
+
558
+ // ---- the button check: the same button language as palate's recent pages, whatever else differs. The whole-look
559
+ // check above can't see it: five pages with five grounds, faces and heroes stay far apart as looks (0.29–0.42 with
560
+ // each other) while every one of them has the same button. It fails when the button repeats palate's recent pages
561
+ // as a habit (at BUTTON_REPEAT_FAIL against two of them, or at BUTTON_REPEAT_WARN against three), and warns on
562
+ // one. Older records that only know the coarse cta class aren't compared.
563
+ //
564
+ // Calibration (Nov 7 2026), measured at 1440 with reduced motion: the five r4 benchmark pages and palate-site
565
+ // (running locally), linear.app, apple.com and stripe.com live. buttonSimilarity:
566
+ // trace mabel shelf kiln mira site linear apple stripe
567
+ // tracewell - 0.68 0.78 0.77 0.84 0.75 0.45 0.62 0.71
568
+ // mabels 0.68 - 0.79 0.84 0.65 0.68 0.33 0.70 0.62
569
+ // open-shelf 0.78 0.79 - 0.87 0.75 0.75 0.39 0.58 0.74
570
+ // kiln 0.77 0.84 0.87 - 0.74 0.78 0.35 0.60 0.70
571
+ // mira 0.84 0.65 0.75 0.74 - 0.86 0.52 0.52 0.72
572
+ // palate-site 0.75 0.68 0.75 0.78 0.86 - 0.52 0.61 0.79
573
+ // linear 0.45 0.33 0.39 0.35 0.52 0.52 - 0.50 0.60
574
+ // apple 0.62 0.70 0.58 0.60 0.52 0.61 0.50 - 0.75
575
+ // stripe 0.71 0.62 0.74 0.70 0.72 0.79 0.60 0.75 -
576
+ // Each r4 page against the other four: tracewell, open-shelf, kiln and mira fail, mabels (a pill) warns. linear
577
+ // (a boxless text action) and apple (a regular-weight pill with no ring and a ghost partner) pass; stripe (a 48px
578
+ // solid box with a small radius, but regular weight and no ring) warns on two. palate-site fails: its button
579
+ // (52px solid, small radius, ring and contact shadow, medium label, an arrow) is palate's own, the same family.
580
+ export const BUTTON_REPEAT_FAIL = 0.8;
581
+ export const BUTTON_REPEAT_WARN = 0.72;
582
+ export const BUTTON_REPEAT_HABIT = 3;
583
+ const BUTTON_AXIS_WORDS = { shape: "the shape", fill: "the fill", size: "the size", label: "the label", adornment: "the adornment", secondary: "the second action" };
584
+ export function buttonRepeatFinding(look, { excludePid, like = [], file, planned = null, tags = [], fail = BUTTON_REPEAT_FAIL, warn = BUTTON_REPEAT_WARN, limit = RECENT } = {}) {
585
+ const mine = look?.buttons;
586
+ if (!mine || AXIS_COUNT(mine) < 4) return { check: null, matches: [] };
587
+ const skip = new Set(like.map((x) => String(x).toLowerCase()));
588
+ const matches = [];
589
+ for (const r of recentLooks({ excludePid, limit, file })) {
590
+ if (skip.has(String(r.project).toLowerCase())) continue;
591
+ const theirs = r.look?.buttons;
592
+ if (!theirs || AXIS_COUNT(theirs) < 4) continue;
593
+ const m = buttonSimilarity(mine, theirs);
594
+ if (m.score >= warn) matches.push({ record: r, ...m });
595
+ }
596
+ matches.sort((a, b) => b.score - a.score);
597
+ if (!matches.length) return { check: null, matches };
598
+ const severity = matches.filter((m) => m.score >= fail).length >= 2 || matches.length >= BUTTON_REPEAT_HABIT ? "fail" : "warn";
599
+ const who = listWords(matches.slice(0, 4).map((m) => `${m.record.project} (${Math.round(m.score * 100)}%)`));
600
+ const what = `the same button as ${who}: ${describeButtons(mine)}`;
601
+ const axes = matches[0].same.map((a) => BUTTON_AXIS_WORDS[a]).filter(Boolean);
602
+ const plan = planned && buttonSimilarity(planned, mine).score < 0.6 ? ` The blueprint planned "${describeButtons(planned)}": build that (.btn-primary and .btn-secondary in tokens.css carry it).` : "";
603
+ const fix = `Change at least three of ${listWords(axes.length ? axes : ["the shape", "the fill", "the label"])}, with ${buttonChange(mine, tags)}.${plan}`;
604
+ return { check: { id: "BUTTON_REPEAT", width: 1440, section: null, severity, what, fix, score: matches[0].score, against: matches.map((m) => m.record.project) }, matches };
605
+ }
606
+
607
+ // For the quality gate (gate.mjs prepare): measures the page's look, records it, and adds HOUSE_LOOK to the floor
608
+ // result. Exempt: projects the user asked to match (like/likeOf) and an existing page whose blueprint kept the
609
+ // brand. Never throws: a page that can't be measured just isn't checked.
610
+ export async function houseLookCheck(dir, route, floor, { url } = {}) {
611
+ try {
612
+ const { projectId } = await import("./layouts.mjs");
613
+ const { likeOf } = await import("./similar.mjs");
614
+ const { loadBlueprint } = await import("./blueprint.mjs");
615
+ const look = await lookOf(dir, route, { url });
616
+ await recordLook(dir, route, look);
617
+ const bp = loadBlueprint(dir, { route });
618
+ floor.look = { describe: describeLook(look) };
619
+ if (bp?.mode === "existing" && bp.system?.keep !== false) {
620
+ floor.look.exempt = "an existing page that keeps its brand";
621
+ return floor;
622
+ }
623
+ const { check, best } = houseLookFinding(look, { excludePid: projectId(dir), like: likeOf(dir, route) });
624
+ if (best) floor.look.closest = { where: `${best.record.project} ${best.record.route}`, score: best.score };
625
+ const research = await import("./research.mjs").then((R) => R.loadResearch(dir, "latest")).catch(() => null);
626
+ const tags = [...(research?.understanding?.tags ?? []), ...(research?.understanding?.mood ?? [])];
627
+ const btn = buttonRepeatFinding(look, { excludePid: projectId(dir), like: likeOf(dir, route), planned: resolveButtons(bp?.look?.buttons), tags });
628
+ if (look.buttons) floor.look.buttons = describeButtons(look.buttons);
629
+ for (const c of [check, btn.check].filter(Boolean)) {
630
+ floor.checks = [...(floor.checks ?? []), c];
631
+ if (c.severity === "fail") floor.pass = false;
632
+ }
633
+ } catch (e) {
634
+ floor.look = { error: String(e?.message ?? e).slice(0, 160) };
635
+ }
636
+ return floor;
637
+ }
638
+
639
+ // One line for palate shoot (and a second when the button repeats palate's recent pages).
640
+ export function lookLine(look, best, { buttons } = {}) {
641
+ const close = best ? `; closest recent look: ${best.record.project} ${best.record.route}, ${Math.round(best.score * 100)}%${best.score >= HOUSE_LOOK_FAIL ? ` (over the ${Math.round(HOUSE_LOOK_FAIL * 100)}% house-look gate: palate gate will fail it; change ${listWords(repeated(best).slice(0, 3).map((a) => AXIS_WORDS[a]))})` : best.score >= HOUSE_LOOK_WARN ? " (close to the house-look gate)" : ""}` : "";
642
+ const btn = buttons?.check ? `
643
+ - Button ${buttons.check.severity === "fail" ? "repeats (palate gate will fail it)" : "is close to a recent page's"}: ${buttons.check.what}. ${buttons.check.fix}` : "";
644
+ return `- Look: ${describeLook(look)}${close}${btn}`;
645
+ }