@palate/cli 0.0.0-stage → 0.0.2

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 +153 -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 +37 -4
  1107. package/scripts/pack-assets.mjs +58 -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,1516 @@
1
+ // palate point: the overlay palate's proxy injects into the user's running app. Vanilla JS in a shadow root
2
+ // (nothing leaks into the page, nothing from the page leaks in), fixed-position only (no layout shift).
3
+ // Point mode: hover highlights an element (box, name, margin and padding), arrows walk up and down the
4
+ // tree, a click opens a small dialog anchored to it. Each request becomes a numbered pin whose status
5
+ // (queued, agent working, done, failed) updates live; a done pin shows before and after. Beside the palate
6
+ // button, a small status says whether an agent is listening, so the user knows their pins will be picked up.
7
+ (() => {
8
+ if (window.__palatePoint || window.top !== window) return;
9
+ window.__palatePoint = { version: 1 };
10
+ const API = "/__palate/api";
11
+ const isMac = /Mac|iPhone|iPad/.test(navigator.platform || navigator.userAgent);
12
+ const coarse = matchMedia("(pointer: coarse)").matches;
13
+ const CHIPS = ["Fix spacing", "Fix alignment", "Type hierarchy", "Make it premium", "Add motion", "Real content & avatars", "Variants of this"];
14
+ const STUCK = "couldn't reopen";
15
+ const STATUS = { queued: "Queued", working: "Agent working", done: "Done", canceled: "Canceled", failed: "Failed" };
16
+ const START_AGENT = "In Claude Code run <b>/mcp__palate__point</b>, or start <b>palate point --auto</b>.";
17
+ const S = { on: false, leaf: null, target: null, dialog: null, requests: [], pop: null, els: new Map(), route: location.pathname, sending: false, agent: null };
18
+
19
+ const ICON = {
20
+ mark: `<svg viewBox="0 0 16 16" aria-hidden="true"><rect x="1.5" y="1.5" width="5.6" height="5.6" rx="1.5" class="m1"/><rect x="8.9" y="1.5" width="5.6" height="5.6" rx="1.5" opacity=".42"/><rect x="1.5" y="8.9" width="5.6" height="5.6" rx="1.5" opacity=".42"/><rect x="8.9" y="8.9" width="5.6" height="5.6" rx="1.5" opacity=".42"/></svg>`,
21
+ x: `<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M4 4l8 8M12 4l-8 8"/></svg>`,
22
+ up: `<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 12.5V3.5M4 7.5l4-4 4 4"/></svg>`,
23
+ down: `<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 3.5v9M4 8.5l4 4 4-4"/></svg>`,
24
+ check: `<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M3.5 8.5l3 3 6-7"/></svg>`,
25
+ send: `<svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 13V3.5M4 7.5l4-4 4 4"/></svg>`,
26
+ };
27
+
28
+ const STYLES = `
29
+ :host { all: initial; }
30
+ * { box-sizing: border-box; }
31
+ [hidden] { display: none !important; }
32
+ .root {
33
+ --surface: #161615; --surface-2: #21211f; --surface-3: #2b2b28;
34
+ --line: rgba(255,255,255,.08); --line-2: rgba(255,255,255,.15);
35
+ --text: #f4f3ef; --muted: #a3a29b; --faint: #75746d;
36
+ --accent: #0f7a57; --accent-soft: rgba(15,122,87,.16); --accent-ring: rgba(15,122,87,.55);
37
+ --ok: #1f9e5a; --warn: #e0a43a; --margin: rgba(246,166,72,.30); --padding: rgba(72,196,128,.2);
38
+ --shadow: 0 1px 1px rgba(0,0,0,.12), 0 6px 16px -4px rgba(0,0,0,.28), 0 24px 48px -12px rgba(0,0,0,.32);
39
+ --ease: cubic-bezier(.2,.8,.2,1);
40
+ font: 500 12px/1.4 ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI Variable Text", "Segoe UI", Inter, Roboto, sans-serif;
41
+ color: var(--text); -webkit-font-smoothing: antialiased; letter-spacing: 0;
42
+ }
43
+ .mono { font-family: ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace; }
44
+ button { font: inherit; color: inherit; background: none; border: 0; padding: 0; margin: 0; cursor: pointer; -webkit-tap-highlight-color: transparent; }
45
+ button:focus-visible, textarea:focus-visible { outline: 2px solid var(--accent-ring); outline-offset: 2px; }
46
+ svg { width: 16px; height: 16px; display: block; fill: none; stroke: currentColor; stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
47
+
48
+ /* Highlight */
49
+ .hl { position: fixed; inset: 0; pointer-events: none; }
50
+ .box { position: fixed; top: 0; left: 0; border: 1.5px solid var(--accent); background: rgba(15,122,87,.07); border-radius: 2px; transition: transform .07s var(--ease), width .07s var(--ease), height .07s var(--ease); will-change: transform; }
51
+ .box.frozen { background: rgba(15,122,87,.1); box-shadow: 0 0 0 4px rgba(15,122,87,.14); }
52
+ .band { position: fixed; top: 0; left: 0; }
53
+ .band.m { background: repeating-linear-gradient(135deg, var(--margin) 0 3px, transparent 3px 6px); }
54
+ .band.p { background: var(--padding); }
55
+ .label { position: fixed; top: 0; left: 0; display: flex; flex-direction: column; gap: 1px; max-width: min(460px, calc(100vw - 16px)); padding: 4px 8px 5px; border-radius: 7px; background: var(--surface); box-shadow: var(--shadow); white-space: nowrap; }
56
+ .label .row { display: flex; align-items: baseline; gap: 6px; min-width: 0; }
57
+ .label b { font-weight: 600; color: var(--text); }
58
+ .label .tag { color: #86dcb8; font-size: 11px; }
59
+ .label .txt { color: var(--muted); overflow: hidden; text-overflow: ellipsis; min-width: 0; }
60
+ .label .dim { color: var(--faint); font-variant-numeric: tabular-nums; margin-left: auto; padding-left: 8px; }
61
+ .label .sp { color: var(--faint); font-size: 11px; font-variant-numeric: tabular-nums; }
62
+ .label .sp i { font-style: normal; color: var(--muted); }
63
+
64
+ /* Floating button */
65
+ .fab { position: fixed; right: 20px; bottom: 20px; height: 40px; min-width: 40px; padding: 0 12px; display: flex; align-items: center; gap: 8px; border-radius: 999px; background: var(--surface); color: var(--text); border: 1px solid var(--line-2); box-shadow: var(--shadow); pointer-events: auto; transition: background-color .15s ease-out, transform .15s var(--ease); }
66
+ .fab:hover { background: var(--surface-2); }
67
+ .fab:active { transform: scale(.96); }
68
+ .fab .m1 { fill: currentColor; transition: fill .15s ease-out; }
69
+ .fab rect { fill: currentColor; }
70
+ .fab .word { display: none; font-weight: 600; }
71
+ .fab kbd { display: none; }
72
+ .fab.on .m1 { fill: var(--accent); }
73
+ .fab.on .word { display: inline; }
74
+ .fab.on kbd { display: inline-block; }
75
+ .fab:not(.on) { padding: 0; justify-content: center; width: 40px; }
76
+ .badge { position: absolute; top: -4px; right: -4px; min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px; background: var(--accent); color: #fff; font-size: 11px; font-weight: 600; line-height: 18px; text-align: center; font-variant-numeric: tabular-nums; box-shadow: 0 0 0 2px var(--surface); }
77
+ kbd { font: 500 11px/1 ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace; color: var(--muted); padding: 3px 5px; border-radius: 5px; border: 1px solid var(--line-2); background: var(--surface-2); }
78
+
79
+ /* Agent status, beside the button */
80
+ .agent { position: fixed; right: 68px; bottom: 26px; height: 28px; display: flex; align-items: center; gap: 7px; padding: 0 10px; border-radius: 999px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow); color: var(--muted); font-size: 12px; white-space: nowrap; pointer-events: auto; }
81
+ .agent .ad { position: relative; width: 7px; height: 7px; border-radius: 50%; background: var(--faint); flex: none; }
82
+ .agent[data-state="listening"] .ad { background: #3ccf86; box-shadow: 0 0 0 3px rgba(60,207,134,.18); }
83
+ .agent[data-state="busy"] .ad { background: var(--accent); }
84
+ .agent[data-state="busy"] .ad::after { content: ""; position: absolute; inset: -4px; border-radius: 50%; border: 1.5px solid transparent; border-top-color: #3ccf86; animation: spin .9s linear infinite; }
85
+ .agent[data-state="none"].waiting .ad { background: #e0a43a; box-shadow: 0 0 0 3px rgba(224,164,58,.18); }
86
+ .agent[data-state="busy"] .at, .agent[data-state="listening"] .at { color: var(--text); }
87
+ .agent .at { font-variant-numeric: tabular-nums; }
88
+ .agent .stop { height: 20px; margin-right: -6px; padding: 0 8px; border-radius: 999px; color: var(--muted); font-size: 11px; font-weight: 600; border: 1px solid var(--line-2); transition: background-color .12s ease-out, color .12s ease-out; }
89
+ .agent .stop:hover { background: var(--surface-2); color: var(--text); }
90
+
91
+ /* Hint and toast */
92
+ .hint, .toast { position: fixed; left: 50%; bottom: 20px; transform: translateX(-50%); display: flex; align-items: center; gap: 8px; height: 34px; padding: 0 12px; border-radius: 999px; background: var(--surface); border: 1px solid var(--line); box-shadow: var(--shadow); color: var(--muted); white-space: nowrap; pointer-events: none; max-width: calc(100vw - 128px); overflow: hidden; }
93
+ .hint b, .toast b { color: var(--text); font-weight: 600; }
94
+ .hint .sep { width: 1px; height: 14px; background: var(--line-2); }
95
+ .hint .ext { display: contents; }
96
+ .toast { bottom: 64px; color: var(--text); animation: rise .18s var(--ease); }
97
+ .toast .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--accent); flex: none; }
98
+ .toast.ok .dot { background: #3ccf86; }
99
+ .toast.warn .dot { background: #e0a43a; }
100
+ .toast.long { height: auto; min-height: 34px; padding: 8px 14px; border-radius: 17px; white-space: normal; line-height: 1.4; width: max-content; max-width: min(520px, calc(100vw - 32px)); }
101
+
102
+ /* Dialog */
103
+ .dialog { position: fixed; top: 0; left: 0; width: 360px; border-radius: 14px; background: var(--surface); border: 1px solid var(--line-2); box-shadow: var(--shadow); pointer-events: auto; animation: pop .16s var(--ease); transform-origin: var(--ox, 0) var(--oy, 0); }
104
+ .dh { display: flex; align-items: center; gap: 6px; padding: 10px 8px 0 12px; min-width: 0; }
105
+ .dh .name { display: flex; align-items: baseline; gap: 6px; min-width: 0; flex: 1; white-space: nowrap; }
106
+ .dh .name b { font-weight: 600; }
107
+ .dh .name .tag { color: #86dcb8; font-size: 11px; }
108
+ .dh .name .txt { color: var(--muted); overflow: hidden; text-overflow: ellipsis; min-width: 0; }
109
+ .ib { width: 26px; height: 26px; display: grid; place-items: center; border-radius: 7px; color: var(--muted); flex: none; transition: background-color .12s ease-out, color .12s ease-out; }
110
+ .ib:hover { background: var(--surface-2); color: var(--text); }
111
+ .ib:disabled { opacity: .35; cursor: default; background: none; }
112
+ textarea { display: block; width: 100%; resize: none; border: 0; outline: 0; background: transparent; color: var(--text); font: 400 14px/1.45 inherit; font-family: inherit; padding: 8px 12px 6px; min-height: 52px; max-height: 160px; }
113
+ textarea:focus-visible { outline: 0; }
114
+ textarea::placeholder { color: var(--faint); }
115
+ .chips { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 12px 12px; }
116
+ .chip { height: 26px; padding: 0 10px; border-radius: 999px; border: 1px solid var(--line-2); color: var(--muted); font-size: 12px; transition: background-color .12s ease-out, border-color .12s ease-out, color .12s ease-out; }
117
+ .chip:hover { color: var(--text); border-color: rgba(255,255,255,.26); }
118
+ .chip[aria-pressed="true"] { background: var(--accent-soft); border-color: var(--accent); color: var(--text); }
119
+ .df { display: flex; align-items: center; gap: 8px; padding: 8px 8px 8px 12px; border-top: 1px solid var(--line); }
120
+ .df .note { color: var(--faint); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
121
+ .df .steps { color: var(--muted); white-space: nowrap; flex: none; cursor: help; }
122
+ .send { height: 30px; padding: 0 10px 0 12px; display: flex; align-items: center; gap: 8px; border-radius: 8px; background: var(--accent); color: #fff; font-weight: 600; transition: opacity .12s ease-out, transform .12s var(--ease); }
123
+ .send:active { transform: scale(.97); }
124
+ .send:disabled { opacity: .4; cursor: default; transform: none; }
125
+ .send kbd { color: rgba(255,255,255,.8); background: rgba(255,255,255,.12); border-color: rgba(255,255,255,.18); }
126
+
127
+ /* Pins */
128
+ .pins { position: fixed; inset: 0; pointer-events: none; }
129
+ .pin { position: fixed; top: 0; left: 0; width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; background: var(--surface); color: var(--text); font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; box-shadow: 0 0 0 2px #fff, 0 2px 8px rgba(0,0,0,.3); pointer-events: auto; transition: background-color .2s ease-out; }
130
+ .pin:hover { z-index: 2; }
131
+ .pin.working { background: var(--accent); }
132
+ .pin.working::after { content: ""; position: absolute; inset: -5px; border-radius: 50%; border: 2px solid transparent; border-top-color: var(--accent); border-right-color: var(--accent); animation: spin .9s linear infinite; }
133
+ .pin.done { background: var(--ok); animation: settle .32s var(--ease); }
134
+ .pin.done svg { width: 13px; height: 13px; stroke-width: 2.2; }
135
+ .pin.failed { background: #b7432f; }
136
+ .pin.broke::before { content: ""; position: absolute; top: -3px; right: -3px; width: 9px; height: 9px; border-radius: 50%; background: var(--warn); box-shadow: 0 0 0 2px var(--surface); }
137
+ .ghost { position: fixed; top: 0; left: 0; border: 1.5px dashed var(--accent); border-radius: 3px; pointer-events: none; }
138
+
139
+ /* Pin popover */
140
+ .pop { position: fixed; top: 0; left: 0; width: 300px; max-height: calc(100vh - 24px); border-radius: 12px; background: var(--surface); border: 1px solid var(--line-2); box-shadow: var(--shadow); pointer-events: auto; animation: pop .14s var(--ease); overflow: hidden auto; overscroll-behavior: contain; }
141
+ .ph { display: flex; align-items: center; gap: 8px; padding: 10px 6px 0 12px; }
142
+ .vpc { height: 20px; padding: 0 7px; border-radius: 999px; border: 1px solid var(--line-2); color: var(--muted); font-size: 11px; line-height: 18px; font-variant-numeric: tabular-nums; white-space: nowrap; flex: none; }
143
+ .dh .vp { color: var(--faint); font-size: 11px; font-variant-numeric: tabular-nums; white-space: nowrap; padding: 0 4px; flex: none; }
144
+ /* Before and after at both widths */
145
+ .bx { display: grid; gap: 6px; }
146
+ .bx .cols, .bx .pair2 { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
147
+ .bx .cols span { color: var(--faint); font-size: 11px; }
148
+ .bx .rl { display: flex; align-items: baseline; gap: 6px; margin-top: 2px; color: var(--muted); font-size: 11px; }
149
+ .bx .rl b { color: var(--text); font-weight: 600; }
150
+ .bx .rl .tg { margin-left: auto; color: var(--faint); }
151
+ .bx .rl .tg.broke { color: var(--warn); }
152
+ .cell { position: relative; height: 84px; border-radius: 7px; overflow: hidden; background: #fff; border: 1px solid var(--line); cursor: zoom-in; }
153
+ .cell img { display: block; width: 100%; height: 100%; object-fit: contain; object-position: top; user-select: none; -webkit-user-drag: none; }
154
+ .cell .cap { position: absolute; left: 4px; bottom: 4px; padding: 1px 5px; border-radius: 4px; background: rgba(22,22,21,.82); color: #fff; font-size: 10px; font-weight: 600; }
155
+ .cell.empty { display: grid; place-items: center; background: var(--surface-2); border-style: dashed; border-color: var(--line-2); color: var(--muted); font-size: 11px; }
156
+ .warnbox { display: flex; align-items: flex-start; gap: 8px; margin: 0; padding: 8px 10px; border-radius: 8px; background: rgba(224,164,58,.1); border: 1px solid rgba(224,164,58,.3); color: var(--text); line-height: 1.4; overflow-wrap: anywhere; }
157
+ .warnbox .wd { width: 7px; height: 7px; margin-top: 5px; border-radius: 50%; background: var(--warn); flex: none; }
158
+ .warnbox b { font-weight: 600; }
159
+ .onote { margin: 0; color: var(--faint); font-size: 11px; overflow-wrap: anywhere; }
160
+ .onote.stuck { color: var(--muted); }
161
+ .ph .st { display: flex; align-items: center; gap: 6px; flex: 1; color: var(--muted); }
162
+ .ph .st b { color: var(--text); font-weight: 600; }
163
+ .ph .st .d { width: 7px; height: 7px; border-radius: 50%; background: var(--faint); }
164
+ .ph .st .d.working { background: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
165
+ .ph .st .d.done { background: #3ccf86; }
166
+ .ph .st .d.failed { background: #e5664f; }
167
+ .pb { padding: 6px 12px 12px; display: grid; gap: 8px; }
168
+ .pb .ask { font-size: 13px; line-height: 1.45; color: var(--text); margin: 0; overflow-wrap: anywhere; }
169
+ .pb .tags { display: flex; flex-wrap: wrap; gap: 4px; }
170
+ .pb .tags span { height: 20px; line-height: 18px; padding: 0 7px; border-radius: 999px; border: 1px solid var(--line-2); color: var(--muted); font-size: 11px; }
171
+ .pb .sum { margin: 0; color: var(--muted); overflow-wrap: anywhere; }
172
+ .pb .sum b { color: var(--text); font-weight: 600; }
173
+ .pb .err { margin: 0; max-height: 120px; overflow: auto; padding: 6px 8px; border-radius: 7px; background: var(--surface-2); color: var(--muted); font-size: 11px; line-height: 1.45; white-space: pre-wrap; overflow-wrap: anywhere; }
174
+ .ba { display: grid; gap: 6px; }
175
+ .seg { display: inline-flex; padding: 2px; border-radius: 8px; background: var(--surface-2); justify-self: start; }
176
+ .seg button { height: 22px; padding: 0 9px; border-radius: 6px; color: var(--muted); font-size: 11px; font-weight: 600; }
177
+ .seg button[aria-pressed="true"] { background: var(--surface-3); color: var(--text); }
178
+ .shot { position: relative; border-radius: 8px; overflow: hidden; background: #fff; border: 1px solid var(--line); cursor: zoom-in; }
179
+ .shot img { display: block; width: 100%; max-height: 220px; object-fit: contain; object-position: top; user-select: none; -webkit-user-drag: none; }
180
+ .shot .cap { position: absolute; right: 6px; top: 6px; padding: 2px 6px; border-radius: 5px; background: rgba(22,22,21,.82); color: #fff; font-size: 10px; font-weight: 600; letter-spacing: .02em; }
181
+ .ba .hold { color: var(--faint); font-size: 11px; }
182
+ .ba .segs { display: flex; justify-content: space-between; gap: 6px; }
183
+ .gone { display: grid; place-items: center; gap: 2px; min-height: 96px; padding: 16px; border-radius: 8px; border: 1px dashed var(--line-2); color: var(--muted); text-align: center; }
184
+ .gone b { color: var(--text); font-weight: 600; }
185
+ .zoom .gone { min-width: 240px; min-height: 160px; background: var(--surface); }
186
+ .pa { display: flex; gap: 6px; }
187
+ .btn { height: 26px; padding: 0 10px; border-radius: 7px; border: 1px solid var(--line-2); color: var(--muted); font-size: 12px; }
188
+ .btn:hover { color: var(--text); background: var(--surface-2); }
189
+ .spin { width: 12px; height: 12px; border-radius: 50%; border: 2px solid var(--accent-soft); border-top-color: var(--accent); animation: spin .8s linear infinite; flex: none; }
190
+ .zoom { position: fixed; inset: 0; background: rgba(10,10,10,.72); display: grid; place-items: center; padding: 24px; pointer-events: auto; animation: fade .14s ease-out; cursor: zoom-out; }
191
+ .zoom .pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 16px; max-width: min(1400px, 100%); max-height: 100%; }
192
+ .zoom figure { margin: 0; display: grid; gap: 8px; min-width: 0; }
193
+ .zoom figcaption { color: #fff; font-weight: 600; }
194
+ .zoom img { max-width: 100%; max-height: calc(100vh - 96px); object-fit: contain; border-radius: 8px; background: #fff; }
195
+
196
+ @keyframes pop { from { opacity: 0; transform: translateY(4px) scale(.98); } }
197
+ @keyframes rise { from { opacity: 0; transform: translate(-50%, 6px); } }
198
+ @keyframes fade { from { opacity: 0; } }
199
+ @keyframes spin { to { transform: rotate(360deg); } }
200
+ @keyframes settle { 0% { transform: var(--t) scale(.6); } 60% { transform: var(--t) scale(1.12); } 100% { transform: var(--t) scale(1); } }
201
+
202
+ @media (max-width: 520px) {
203
+ .dialog { width: auto !important; left: 8px !important; right: 8px; top: auto !important; bottom: 8px; }
204
+ .pop { width: auto !important; left: 8px !important; right: 8px; top: auto !important; bottom: 8px; max-height: calc(100vh - 16px); }
205
+ .cell { height: 96px; }
206
+ .hint { bottom: 72px; max-width: calc(100vw - 32px); }
207
+ .toast { bottom: 112px; max-width: calc(100vw - 32px); width: max-content; height: auto; min-height: 34px; padding: 8px 14px; border-radius: 17px; white-space: normal; line-height: 1.35; }
208
+ .hint .ext { display: none; }
209
+ .fab { right: 16px; bottom: 16px; }
210
+ .agent { right: 64px; bottom: 22px; }
211
+ .label { max-width: calc(100vw - 16px); }
212
+ }
213
+ @media (min-width: 521px) and (max-width: 1000px) {
214
+ .hint { bottom: 64px; }
215
+ .toast { bottom: 108px; }
216
+ }
217
+ @media (prefers-reduced-motion: reduce) {
218
+ .box, .fab, .send, .chip { transition: none; }
219
+ .agent[data-state="busy"] .ad::after { animation-duration: 2.4s; }
220
+ .dialog, .pop, .toast, .zoom, .pin.done { animation: none; }
221
+ .pin.working::after, .spin { animation-duration: 2.4s; }
222
+ }`;
223
+
224
+ // The same names the server uses: every pin is checked at the width it was pinned at and the other one.
225
+ const wname = (w) => (w <= 500 ? "phone" : w < 1024 ? "tablet" : "desktop");
226
+ const otherOf = (w) => (w >= 768 ? 390 : 1440);
227
+ const esc = (s) => String(s ?? "").replace(/[<>&"']/g, (c) => ({ "<": "&lt;", ">": "&gt;", "&": "&amp;", '"': "&quot;", "'": "&#39;" })[c]);
228
+ const host = document.createElement("palate-point");
229
+ host.setAttribute("data-palate", "");
230
+ host.style.cssText = "all:initial;position:fixed;top:0;left:0;width:0;height:0;z-index:2147483647;pointer-events:none;";
231
+ const sr = host.attachShadow({ mode: "open" });
232
+ sr.innerHTML = `<style>${STYLES}</style><div class="root">
233
+ <div class="pins"></div>
234
+ <div class="hl" hidden><div class="band m"></div><div class="band m"></div><div class="band m"></div><div class="band m"></div><div class="band p"></div><div class="band p"></div><div class="band p"></div><div class="band p"></div><div class="box"></div><div class="label"></div></div>
235
+ <div class="hint" hidden></div>
236
+ <div class="toast" hidden role="status" aria-live="polite"></div>
237
+ <div class="agent" data-state="none" role="status" aria-live="polite" hidden><span class="ad" aria-hidden="true"></span><span class="at">No agent listening</span><button class="stop" type="button" hidden title="I'm done pointing: the agent finishes the pins already sent, then stops listening">Done</button></div>
238
+ <button class="fab" type="button" aria-pressed="false" title="Point at something to fix (${isMac ? "⌥" : "Alt+"}P)">${ICON.mark}<span class="word">Pointing</span><kbd>Esc</kbd><span class="badge" hidden></span></button>
239
+ <div class="dialog" role="dialog" aria-label="Ask the agent to change this element" hidden></div>
240
+ <div class="pop" role="dialog" hidden></div>
241
+ </div>`;
242
+ const $ = (s) => sr.querySelector(s);
243
+ const ui = { root: $(".root"), hl: $(".hl"), box: $(".box"), label: $(".label"), bands: [...sr.querySelectorAll(".band")], fab: $(".fab"), badge: $(".badge"), hint: $(".hint"), toast: $(".toast"), dialog: $(".dialog"), pins: $(".pins"), pop: $(".pop"), agent: $(".agent") };
244
+ const ours = (e) => e.composedPath().includes(host);
245
+
246
+ // ---------- What an element is ----------
247
+ const INTERNAL = /^(InnerLayoutRouter|OuterLayoutRouter|RedirectErrorBoundary|RedirectBoundary|HTTPAccessFallbackErrorBoundary|HTTPAccessFallbackBoundary|DevRootHTTPAccessFallbackBoundary|LoadingBoundary|ErrorBoundary|ErrorBoundaryHandler|GlobalError|ScrollAndFocusHandler|InnerScrollAndFocusHandler|RenderFromTemplateContext|AppRouter|Router|HotReload|ReactDevOverlay|AppDevOverlay|AppDevOverlayErrorBoundary|ServerRoot|Root|ClientPageRoot|ClientSegmentRoot|SegmentViewNode|SegmentViewStateNode|SegmentStateProvider|SegmentBoundaryTriggerNode|SegmentTrieNode|Suspense|Fragment|StrictMode|Profiler|Head|MetadataOutlet|MetadataBoundary|ViewportBoundary|OutletBoundary|RootLayoutBoundary|Link|LinkComponent|Image|ImageElement|Script|Portal|Presence|PresenceChild|AnimatePresence|LayoutGroup|MotionConfig|LazyMotion|PopChild|PopChildMeasure|Slot|SlotClone|Primitive|Provider|Consumer|ThemeProvider)$/;
248
+ const fiberName = (t) => {
249
+ if (!t) return null;
250
+ if (typeof t === "string") return null;
251
+ const n = t.displayName || t.name || t.render?.displayName || t.render?.name || t.type?.displayName || t.type?.name || null;
252
+ return n && /^[A-Z]/.test(n) && !/[.$]|^Motion|^Styled|(Context|Provider|Boundary|Handler|Router|Outlet|Root)$/.test(n) && !INTERNAL.test(n) ? n : null;
253
+ };
254
+ function framework(el) {
255
+ const out = {};
256
+ let node = el;
257
+ let key = null;
258
+ for (; node && node !== document.documentElement; node = node.parentElement) {
259
+ key = Object.keys(node).find((k) => k.startsWith("__reactFiber$") || k.startsWith("__reactInternalInstance$"));
260
+ if (key) break;
261
+ }
262
+ if (key) {
263
+ const f = node[key];
264
+ const components = [];
265
+ for (let x = f; x && components.length < 8; x = x.return) {
266
+ const n = fiberName(x.type);
267
+ if (n && components.at(-1) !== n) components.push(n);
268
+ }
269
+ // The owner chain: who rendered this element (includes server components in React 19 dev builds).
270
+ const owners = [];
271
+ const seen = new Set();
272
+ for (let o = f._debugOwner; o && owners.length < 8 && !seen.has(o); o = o._debugOwner || o.owner) {
273
+ seen.add(o);
274
+ const n = o.name ?? fiberName(o.type);
275
+ if (n && !INTERNAL.test(n) && owners.at(-1)?.name !== n) owners.push({ name: n, server: o.env ? o.env === "Server" : undefined });
276
+ }
277
+ const nearest = owners[0]?.name ?? components[0] ?? null;
278
+ out.react = { component: nearest, components, owners };
279
+ }
280
+ for (let e = el; e && !out.vue; e = e.parentElement) {
281
+ const c = e.__vueParentComponent;
282
+ if (c) {
283
+ const chain = [];
284
+ for (let x = c; x && chain.length < 6; x = x.parent) chain.push({ name: x.type?.__name || x.type?.name || null, file: x.type?.__file || null });
285
+ out.vue = { component: chain[0]?.name ?? null, file: chain[0]?.file ?? null, chain };
286
+ }
287
+ }
288
+ for (let e = el; e && !out.svelte; e = e.parentElement) {
289
+ const m = e.__svelte_meta;
290
+ if (m?.loc) out.svelte = { file: m.loc.file, line: m.loc.line, column: m.loc.column };
291
+ }
292
+ return out;
293
+ }
294
+ const componentOf = (el) => {
295
+ const f = framework(el);
296
+ return f.react?.component || f.vue?.component || null;
297
+ };
298
+
299
+ const stableId = (id) => id && /^[A-Za-z][\w-]*$/.test(id) && !/^(radix|headlessui|react-aria|mui|chakra)|\d{3,}/i.test(id);
300
+ const unique = (s) => {
301
+ try {
302
+ return document.querySelectorAll(s).length === 1;
303
+ } catch {
304
+ return false;
305
+ }
306
+ };
307
+ // The shortest child-combinator path that matches only this element, anchored at an id or test id when there is one.
308
+ function selectorOf(el) {
309
+ const parts = [];
310
+ for (let e = el; e && e.nodeType === 1 && e !== document.documentElement; e = e.parentElement) {
311
+ if (stableId(e.id)) {
312
+ parts.unshift(`#${CSS.escape(e.id)}`);
313
+ if (unique(parts.join(" > "))) return parts.join(" > ");
314
+ parts[0] = `${e.tagName.toLowerCase()}#${CSS.escape(e.id)}`;
315
+ continue;
316
+ }
317
+ const tid = ["data-testid", "data-test", "data-cy"].map((a) => [a, e.getAttribute(a)]).find(([, v]) => v);
318
+ let part = tid ? `[${tid[0]}="${CSS.escape(tid[1])}"]` : e.tagName.toLowerCase();
319
+ if (!tid && e.parentElement) {
320
+ const same = [...e.parentElement.children].filter((c) => c.tagName === e.tagName);
321
+ if (same.length > 1) part += `:nth-of-type(${same.indexOf(e) + 1})`;
322
+ }
323
+ parts.unshift(part);
324
+ const s = parts.join(" > ");
325
+ if ((parts.length >= 2 || tid) && unique(s)) return s;
326
+ if (e === document.body) break;
327
+ }
328
+ return parts.join(" > ");
329
+ }
330
+ function domPath(el) {
331
+ const out = [];
332
+ for (let e = el; e && e.nodeType === 1 && out.length < 12; e = e.parentElement) {
333
+ const cls = typeof e.className === "string" ? e.className.trim().split(/\s+/)[0] : "";
334
+ out.unshift(`${e.tagName.toLowerCase()}${e.id ? `#${e.id}` : ""}${cls ? `.${cls}` : ""}`);
335
+ if (e === document.body) break;
336
+ }
337
+ return out.join(" > ");
338
+ }
339
+ const shortText = (el, n = 34) => {
340
+ const t = (el.innerText || el.textContent || el.getAttribute("aria-label") || el.getAttribute("alt") || "").replace(/\s+/g, " ").trim();
341
+ return t.length > n ? `${t.slice(0, n - 1).trimEnd()}…` : t;
342
+ };
343
+ const textNodes = (el) => {
344
+ const out = [];
345
+ const w = document.createTreeWalker(el, NodeFilter.SHOW_TEXT);
346
+ for (let n = w.nextNode(); n && out.length < 40; n = w.nextNode()) {
347
+ const t = n.textContent.replace(/\s+/g, " ").trim();
348
+ if (t.length > 2 && !/^(script|style)$/i.test(n.parentElement?.tagName)) out.push(t.slice(0, 200));
349
+ }
350
+ for (const a of ["aria-label", "alt", "placeholder", "title"]) if (el.getAttribute?.(a)) out.push(el.getAttribute(a));
351
+ return out;
352
+ };
353
+ function trimHTML(el) {
354
+ const c = el.cloneNode(true);
355
+ // No values from private fields (some frameworks mirror a field's value into its attribute).
356
+ const live = [el, ...el.querySelectorAll("*")];
357
+ [c, ...c.querySelectorAll("*")].forEach((n, i) => {
358
+ if (/^(INPUT|TEXTAREA)$/.test(n.tagName) && live[i] && secret(live[i])) {
359
+ n.removeAttribute("value");
360
+ n.textContent = "";
361
+ }
362
+ });
363
+ c.querySelectorAll("script, style, noscript, template, palate-point").forEach((n) => n.remove());
364
+ c.querySelectorAll("svg").forEach((s) => s.replaceChildren(document.createTextNode("…")));
365
+ const walk = (n, d) => {
366
+ const kids = [...n.children];
367
+ if (d >= 5) return kids.length && n.replaceChildren(document.createTextNode(`…${kids.length} child${kids.length > 1 ? "ren" : ""}`));
368
+ kids.slice(12).forEach((k) => k.remove());
369
+ if (kids.length > 12) n.appendChild(document.createComment(` …${kids.length - 12} more `));
370
+ kids.slice(0, 12).forEach((k) => walk(k, d + 1));
371
+ };
372
+ walk(c, 0);
373
+ for (const n of [c, ...c.querySelectorAll("*")]) for (const a of [...n.attributes]) if (a.value.length > 180) n.setAttribute(a.name, `${a.value.slice(0, 180)}…`);
374
+ const tw = document.createTreeWalker(c, NodeFilter.SHOW_TEXT);
375
+ for (let t = tw.nextNode(); t; t = tw.nextNode()) if (t.textContent.length > 240) t.textContent = `${t.textContent.slice(0, 240)}…`;
376
+ const h = c.outerHTML;
377
+ return h.length > 6000 ? `${h.slice(0, 6000)}\n<!-- …trimmed -->` : h;
378
+ }
379
+ const STYLE_KEYS = ["display", "position", "width", "height", "max-width", "margin", "padding", "gap", "flex-direction", "justify-content", "align-items", "grid-template-columns", "font-family", "font-size", "font-weight", "line-height", "letter-spacing", "text-align", "color", "background-color", "background-image", "border", "border-radius", "box-shadow", "opacity", "transform", "transition"];
380
+ const DEFAULTS = /^(none|normal|auto|all|0px|0px 0px|0px 0px 0px 0px|rgba\(0, 0, 0, 0\)|static|visible|1|0s|all 0s ease 0s|start|stretch|0px (none|solid).*|row|matrix\(1, 0, 0, 1, 0, 0\))$/;
381
+ function keyStyles(el) {
382
+ const cs = getComputedStyle(el);
383
+ const out = {};
384
+ for (const k of STYLE_KEYS) {
385
+ let v = cs.getPropertyValue(k);
386
+ if (!v || (DEFAULTS.test(v) && !["display", "font-size", "color", "width", "height"].includes(k))) continue;
387
+ if (k === "font-family") v = v.split(",")[0].replace(/["']/g, "");
388
+ if (k === "background-image" && v.length > 120) v = `${v.slice(0, 120)}…`;
389
+ out[k] = v;
390
+ }
391
+ return out;
392
+ }
393
+ const px = (v) => Math.round(parseFloat(v) || 0);
394
+ const quad = (a) => (a.every((x) => x === a[0]) ? `${a[0]}` : a[0] === a[2] && a[1] === a[3] ? `${a[0]} ${a[1]}` : a.join(" "));
395
+ function spacing(cs) {
396
+ const m = [cs.marginTop, cs.marginRight, cs.marginBottom, cs.marginLeft].map(px);
397
+ const p = [cs.paddingTop, cs.paddingRight, cs.paddingBottom, cs.paddingLeft].map(px);
398
+ const g = /flex|grid/.test(cs.display) ? px(cs.rowGap === cs.columnGap ? cs.rowGap : cs.rowGap) : 0;
399
+ const out = [];
400
+ if (p.some(Boolean)) out.push(`<i>padding</i> ${quad(p)}`);
401
+ if (m.some(Boolean)) out.push(`<i>margin</i> ${quad(m)}`);
402
+ if (g) out.push(`<i>gap</i> ${g}`);
403
+ return out.join(" · ");
404
+ }
405
+ function describe(el) {
406
+ const comp = componentOf(el);
407
+ const tag = el.tagName.toLowerCase() + (stableId(el.id) ? `#${el.id}` : "");
408
+ return { comp, tag, text: shortText(el) };
409
+ }
410
+ const nameHTML = ({ comp, tag, text }) => `${comp ? `<b>${esc(comp)}</b>` : ""}<span class="tag mono">${esc(tag)}</span>${text ? `<span class="txt">${esc(text)}</span>` : ""}`;
411
+
412
+ // ---------- Highlight ----------
413
+ const visible = (el) => el && el.isConnected && el.getClientRects().length > 0;
414
+ function draw(el, { bands = true, frozen = false } = {}) {
415
+ if (!visible(el)) return void (ui.hl.hidden = true);
416
+ ui.hl.hidden = false;
417
+ const r = el.getBoundingClientRect();
418
+ const cs = getComputedStyle(el);
419
+ const b = ui.box.style;
420
+ b.transform = `translate(${r.left}px, ${r.top}px)`;
421
+ b.width = `${Math.max(r.width, 2)}px`;
422
+ b.height = `${Math.max(r.height, 2)}px`;
423
+ b.borderRadius = cs.borderRadius && cs.borderRadius !== "0px" ? cs.borderRadius : "2px";
424
+ ui.box.classList.toggle("frozen", frozen);
425
+ const m = [cs.marginTop, cs.marginRight, cs.marginBottom, cs.marginLeft].map((v) => Math.max(0, px(v)));
426
+ const bw = [cs.borderTopWidth, cs.borderRightWidth, cs.borderBottomWidth, cs.borderLeftWidth].map(px);
427
+ const p = [cs.paddingTop, cs.paddingRight, cs.paddingBottom, cs.paddingLeft].map((v) => Math.max(0, px(v)));
428
+ const rects = bands
429
+ ? [
430
+ [r.left, r.top - m[0], r.width, m[0]],
431
+ [r.right, r.top, m[1], r.height],
432
+ [r.left, r.bottom, r.width, m[2]],
433
+ [r.left - m[3], r.top, m[3], r.height],
434
+ [r.left + bw[3], r.top + bw[0], r.width - bw[1] - bw[3], p[0]],
435
+ [r.right - bw[1] - p[1], r.top + bw[0] + p[0], p[1], r.height - bw[0] - bw[2] - p[0] - p[2]],
436
+ [r.left + bw[3], r.bottom - bw[2] - p[2], r.width - bw[1] - bw[3], p[2]],
437
+ [r.left + bw[3], r.top + bw[0] + p[0], p[3], r.height - bw[0] - bw[2] - p[0] - p[2]],
438
+ ]
439
+ : [];
440
+ ui.bands.forEach((d, i) => {
441
+ const q = rects[i];
442
+ if (!q || q[2] <= 0 || q[3] <= 0) return void (d.style.display = "none");
443
+ d.style.display = "block";
444
+ d.style.transform = `translate(${q[0]}px, ${q[1]}px)`;
445
+ d.style.width = `${q[2]}px`;
446
+ d.style.height = `${q[3]}px`;
447
+ });
448
+ const d = describe(el);
449
+ const sp = bands ? spacing(cs) : "";
450
+ const key = `${d.comp}|${d.tag}|${d.text}|${Math.round(r.width)}|${Math.round(r.height)}|${sp}`;
451
+ if (ui.label.dataset.key !== key) {
452
+ ui.label.dataset.key = key;
453
+ ui.label.innerHTML = `<div class="row">${nameHTML(d)}<span class="dim">${Math.round(r.width)} × ${Math.round(r.height)}</span></div>${sp ? `<div class="sp">${sp}</div>` : ""}`;
454
+ }
455
+ const lh = ui.label.offsetHeight || 24;
456
+ const lw = ui.label.offsetWidth || 120;
457
+ let ly = r.top - lh - 6;
458
+ if (ly < 4) ly = r.bottom + 6 + lh < innerHeight ? r.bottom + 6 : Math.max(4, r.top + 4);
459
+ const lx = Math.min(Math.max(4, r.left), innerWidth - lw - 4);
460
+ ui.label.style.transform = `translate(${lx}px, ${ly}px)`;
461
+ ui.label.hidden = Boolean(S.dialog) && innerWidth <= 520;
462
+ }
463
+
464
+ function leafAt(x, y) {
465
+ for (const el of document.elementsFromPoint(x, y)) {
466
+ if (el === host || host.contains(el) || el === document.documentElement) continue;
467
+ return el;
468
+ }
469
+ return null;
470
+ }
471
+ function hoverAt(x, y) {
472
+ const leaf = leafAt(x, y);
473
+ if (!leaf) return;
474
+ // After walking up with the arrows, stay on that ancestor while the pointer is inside it.
475
+ if (S.target && S.target !== S.leaf && S.target.contains(leaf)) S.leaf = leaf;
476
+ else S.leaf = S.target = leaf;
477
+ draw(S.target);
478
+ }
479
+ function up() {
480
+ const el = S.dialog ? S.dialog.el : S.target;
481
+ const p = el?.parentElement;
482
+ if (!p || p === document.documentElement) return;
483
+ setTarget(p);
484
+ }
485
+ function down() {
486
+ const el = S.dialog ? S.dialog.el : S.target;
487
+ if (!el || !S.leaf || el === S.leaf || !el.contains(S.leaf)) {
488
+ const c = el && [...el.children].find(visible);
489
+ if (c) setTarget(c);
490
+ return;
491
+ }
492
+ let c = S.leaf;
493
+ while (c.parentElement && c.parentElement !== el) c = c.parentElement;
494
+ setTarget(c);
495
+ }
496
+ function setTarget(el) {
497
+ S.target = el;
498
+ if (S.dialog) {
499
+ S.dialog.el = el;
500
+ renderDialogHead();
501
+ draw(el, { bands: false, frozen: true });
502
+ } else draw(el);
503
+ }
504
+
505
+ // ---------- The trail: the steps that open a state ----------
506
+ // While palate's overlay is on the page (pointing on or off), the user's own steps since the last navigation
507
+ // are kept in a small in-memory list: clicks on controls, Enter/Space on a control, Esc, Tab, arrows in menus,
508
+ // typing (merged per field) and selects. Never a value from a private field (password, card, one-time code,
509
+ // token…), and never palate's own clicks or keys. A pin carries the few steps that lead to its element's
510
+ // state (trimTrail in trail.mjs explains which), and palate replays them before every crop.
511
+ // Form submits aren't recorded: replaying them would send the form again on every check.
512
+ const T = /*@trail*/ ({ trimTrail: () => [], stepShort: (s) => s.text || s.type, SECRET: /passw|card|cvc|token|secret|ssn/i, SECRET_AUTOCOMPLETE: /cc-|one-time-code|password/i, MAX: 10 }) /*@end*/;
513
+ const trail = { steps: [], base: null, url: location.pathname + location.search, down: null, born: new WeakMap(), secret: new WeakSet() };
514
+ const LAYER = 'dialog[open], [role="dialog"], [role="alertdialog"], [aria-modal="true"], [role="menu"], [role="listbox"], [role="tooltip"], [data-state="open"]:not([aria-expanded]):not(button), details[open]';
515
+ const ACTION = 'a[href], button, input, select, textarea, summary, label, [role="button"], [role="link"], [role="tab"], [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="option"], [role="switch"], [role="checkbox"], [role="radio"], [role="combobox"], [role="treeitem"], [aria-haspopup], [aria-expanded], [aria-controls], [onclick], [tabindex]:not([tabindex="-1"])';
516
+ const NAV_KEYS = '[role="menu"], [role="menubar"], [role="listbox"], [role="tablist"], [role="radiogroup"], [role="tree"], [role="grid"], [role="combobox"], select';
517
+ const shows = (el) => el.isConnected && (el.checkVisibility ? el.checkVisibility({ opacityProperty: true, visibilityProperty: true }) : el.getClientRects().length > 0);
518
+ const regionOf = (t) => {
519
+ const id = (t.getAttribute("aria-controls") || "").split(/\s+/)[0];
520
+ return (id && document.getElementById(id)) || t.parentElement;
521
+ };
522
+ const modal = (e) => {
523
+ try {
524
+ return e.matches(":modal");
525
+ } catch {
526
+ return false;
527
+ }
528
+ };
529
+ const kindOf = (e) => {
530
+ const role = e.getAttribute("role");
531
+ if (e.tagName === "DIALOG" || role === "dialog" || role === "alertdialog" || e.getAttribute("aria-modal") === "true") return e.getAttribute("aria-modal") === "true" || role === "alertdialog" || modal(e) ? "modal" : "dialog";
532
+ if (role === "menu" || role === "listbox" || role === "tooltip") return role;
533
+ return "expanded part";
534
+ };
535
+ // Open dialogs, menus, popovers, listboxes and expanded parts on the page now (element → kind).
536
+ function layers() {
537
+ const out = new Map();
538
+ for (const e of document.querySelectorAll(LAYER)) if (shows(e)) out.set(e, kindOf(e));
539
+ try {
540
+ for (const e of document.querySelectorAll(":popover-open")) out.set(e, out.get(e) ?? "popover");
541
+ } catch {}
542
+ for (const t of document.querySelectorAll('[aria-expanded="true"]')) {
543
+ const r = regionOf(t);
544
+ const pop = t.getAttribute("aria-haspopup");
545
+ if (r && shows(r) && !out.has(r)) out.set(r, pop && pop !== "false" ? (pop === "dialog" ? "dialog" : pop === "listbox" ? "listbox" : "menu") : "expanded part");
546
+ }
547
+ return out;
548
+ }
549
+ // What was already open when the user first did anything here (a banner, a menu bar) doesn't count.
550
+ const ensureBase = () => (trail.base ??= new Set(layers().keys()));
551
+ const atRest = () => {
552
+ if (!trail.base) return true;
553
+ for (const e of layers().keys()) if (!trail.base.has(e)) return false;
554
+ return true;
555
+ };
556
+ const resetTrail = () => {
557
+ trail.steps = [];
558
+ trail.base = null;
559
+ trail.down = null;
560
+ trail.url = location.pathname + location.search;
561
+ };
562
+ const onNav = () => location.pathname + location.search !== trail.url && resetTrail();
563
+ for (const k of ["pushState", "replaceState"]) {
564
+ const orig = history[k];
565
+ if (typeof orig === "function")
566
+ history[k] = function (...a) {
567
+ const r = orig.apply(this, a);
568
+ onNav();
569
+ return r;
570
+ };
571
+ }
572
+ addEventListener("popstate", onNav);
573
+ // When parts of the page appear (added, or unhidden): a panel rendered on click counts as opened by it.
574
+ new MutationObserver((list) => {
575
+ const now = Date.now();
576
+ for (const m of list) {
577
+ if (m.type === "childList") {
578
+ for (const n of m.addedNodes) if (n.nodeType === 1 && n !== host) trail.born.set(n, now);
579
+ } else {
580
+ const t = m.target;
581
+ const v = t.getAttribute(m.attributeName);
582
+ if (m.attributeName === "hidden" ? v === null : m.attributeName === "aria-hidden" ? v !== "true" : m.attributeName === "open" ? v !== null : v === "open" || v === "active") trail.born.set(t, now);
583
+ }
584
+ }
585
+ }).observe(document.documentElement, { childList: true, subtree: true, attributes: true, attributeFilter: ["hidden", "open", "aria-hidden", "data-state"] });
586
+
587
+ const labelOf = (el) => (el.getAttribute("aria-label") || (el.labels && el.labels[0]?.innerText) || el.getAttribute("placeholder") || el.getAttribute("name") || el.getAttribute("title") || "").replace(/\s+/g, " ").trim().slice(0, 80);
588
+ // A field whose value is never recorded.
589
+ function secret(el) {
590
+ if (trail.secret.has(el)) return true;
591
+ const hint = [el.getAttribute("name"), el.id, el.getAttribute("aria-label"), el.getAttribute("placeholder"), el.getAttribute("data-testid"), el.labels?.[0]?.innerText].filter(Boolean).join(" ");
592
+ const s = el.type === "password" || T.SECRET_AUTOCOMPLETE.test(el.getAttribute("autocomplete") || "") || T.SECRET.test(hint);
593
+ // Once private, always private (a "show password" toggle turns it into a text field).
594
+ if (s) trail.secret.add(el);
595
+ return s;
596
+ }
597
+ const isTextField = (el) => (el.tagName === "INPUT" && /^(text|search|email|url|tel|number|password|)$/i.test(el.getAttribute("type") || "")) || el.tagName === "TEXTAREA";
598
+ const submits = (el) => {
599
+ const b = el.closest?.('button, input[type="submit"], input[type="image"]');
600
+ return Boolean(b && b.form && (b.tagName === "INPUT" || (b.getAttribute("type") || "submit").toLowerCase() === "submit"));
601
+ };
602
+ const IMPLICIT = { A: "link", BUTTON: "button", SUMMARY: "button", SELECT: "combobox", TEXTAREA: "textbox" };
603
+ const roleOf = (el) => {
604
+ const r = el.getAttribute("role");
605
+ if (r) return r.split(/\s+/)[0];
606
+ if (el.tagName === "INPUT") {
607
+ const t = (el.getAttribute("type") || "text").toLowerCase();
608
+ return { checkbox: "checkbox", radio: "radio", button: "button", submit: "button", reset: "button", range: "slider", number: "spinbutton" }[t] ?? (el.hasAttribute("list") ? "combobox" : "textbox");
609
+ }
610
+ return el.tagName === "A" && !el.hasAttribute("href") ? null : (IMPLICIT[el.tagName] ?? null);
611
+ };
612
+ // How the server finds a step's target again: a robust selector (id, test id, aria-label, else a path),
613
+ // and its role and name, tag and words to fall back on.
614
+ function locateStep(el) {
615
+ const tag = el.tagName.toLowerCase();
616
+ const field = /^(INPUT|TEXTAREA|SELECT)$/.test(el.tagName);
617
+ const tidAttr = ["data-testid", "data-test", "data-cy"].find((a) => el.getAttribute(a));
618
+ const aria = el.getAttribute("aria-label");
619
+ let selector;
620
+ if (stableId(el.id) && unique(`#${CSS.escape(el.id)}`)) selector = `#${CSS.escape(el.id)}`;
621
+ else if (tidAttr && unique(`[${tidAttr}="${CSS.escape(el.getAttribute(tidAttr))}"]`)) selector = `[${tidAttr}="${CSS.escape(el.getAttribute(tidAttr))}"]`;
622
+ else if (aria && unique(`${tag}[aria-label="${CSS.escape(aria)}"]`)) selector = `${tag}[aria-label="${CSS.escape(aria)}"]`;
623
+ else selector = selectorOf(el);
624
+ const words = field ? labelOf(el) : (aria || (el.innerText || el.textContent || "").replace(/\s+/g, " ").trim() || el.getAttribute("title") || el.getAttribute("alt") || "").slice(0, 80);
625
+ return { selector, testid: el.getAttribute("data-testid") || undefined, role: roleOf(el) || undefined, name: words || undefined, tag, text: words || undefined };
626
+ }
627
+ function push(step, el, rest) {
628
+ trail.steps.push({ ...step, at: Date.now(), rest, _el: el });
629
+ if (trail.steps.length > 40) trail.steps.shift();
630
+ }
631
+ // The control a click was meant for: the nearest interactive ancestor, or something that looks clickable.
632
+ function actionOf(t) {
633
+ const a = t.closest?.(ACTION);
634
+ if (a && a !== document.body) return a;
635
+ for (let e = t, k = 0; e && e !== document.body && k < 4; e = e.parentElement, k++) if (getComputedStyle(e).cursor === "pointer") return e;
636
+ return null;
637
+ }
638
+ const quiet = (e) => S.on || S.dialog || S.zoom || ours(e) || !e.isTrusted;
639
+ addEventListener(
640
+ "pointerdown",
641
+ (e) => {
642
+ if (quiet(e)) return;
643
+ ensureBase();
644
+ // Some menus open on pointerdown, before the click: whether the page was at rest is read here.
645
+ trail.down = { t: Date.now(), rest: atRest() };
646
+ },
647
+ true,
648
+ );
649
+ addEventListener(
650
+ "click",
651
+ (e) => {
652
+ if (quiet(e)) return;
653
+ ensureBase();
654
+ const rest = trail.down && Date.now() - trail.down.t < 1500 ? trail.down.rest : atRest();
655
+ trail.down = null;
656
+ const el = actionOf(e.target);
657
+ if (!el || submits(el)) return;
658
+ // The click that follows Enter/Space on the same control, or a label's click passed to its field.
659
+ const prev = trail.steps.at(-1);
660
+ if (prev && Date.now() - prev.at < 800 && (prev._el === el ? e.detail === 0 || prev.type === "key" : prev._el?.control === el)) return;
661
+ push({ type: "click", ...locateStep(el) }, el, rest);
662
+ },
663
+ true,
664
+ );
665
+ addEventListener(
666
+ "keydown",
667
+ (e) => {
668
+ if (quiet(e) || S.pop || e.repeat || e.ctrlKey || e.metaKey || e.altKey) return;
669
+ const k = e.key;
670
+ const el = document.activeElement && document.activeElement !== document.body ? document.activeElement : null;
671
+ let ok = k === "Escape" || k === "Tab";
672
+ if (k === "Enter" || k === " ") ok = Boolean(el) && !(el.isContentEditable || (isTextField(el) && (k === " " || el.form))) && !submits(el);
673
+ else if (/^(Arrow(Up|Down|Left|Right)|Home|End)$/.test(k)) ok = Boolean(el?.closest?.(NAV_KEYS));
674
+ if (!ok) return;
675
+ ensureBase();
676
+ push({ type: "key", key: k, ...(k === "Tab" && e.shiftKey ? { shift: true } : {}), ...(el && k !== "Tab" ? locateStep(el) : {}) }, el, atRest());
677
+ },
678
+ true,
679
+ );
680
+ addEventListener(
681
+ "input",
682
+ (e) => {
683
+ const el = e.target;
684
+ if (quiet(e) || !el || !isTextField(el)) return;
685
+ ensureBase();
686
+ const priv = secret(el);
687
+ const prev = trail.steps.at(-1);
688
+ // Typing into the same field is one step that keeps its latest value.
689
+ if (prev?.type === "type" && prev._el === el) {
690
+ if (!priv) prev.value = el.value.slice(0, 200);
691
+ return;
692
+ }
693
+ push({ type: "type", ...locateStep(el), ...(priv ? { redacted: true } : { value: el.value.slice(0, 200) }) }, el, atRest());
694
+ },
695
+ true,
696
+ );
697
+ addEventListener(
698
+ "change",
699
+ (e) => {
700
+ const el = e.target;
701
+ if (quiet(e) || el?.tagName !== "SELECT") return;
702
+ ensureBase();
703
+ const priv = secret(el);
704
+ push({ type: "select", ...locateStep(el), ...(priv ? { redacted: true } : { value: el.value, label: el.selectedOptions?.[0]?.text?.trim().slice(0, 80) }) }, el, atRest());
705
+ },
706
+ true,
707
+ );
708
+
709
+ // A step clicked earlier that still holds over the element: a selected tab whose panel holds it, or an
710
+ // expander (aria-expanded, details) still open around it.
711
+ function holds(s, el) {
712
+ if (s.type !== "click" && s.type !== "key") return false;
713
+ let t = s._el;
714
+ if (!t?.isConnected) {
715
+ try {
716
+ t = document.querySelector(s.selector);
717
+ } catch {
718
+ t = null;
719
+ }
720
+ }
721
+ if (!t) return false;
722
+ const tab = t.closest('[role="tab"]');
723
+ if (tab) {
724
+ if (tab.getAttribute("aria-selected") !== "true" && tab.getAttribute("data-state") !== "active") return false;
725
+ const p = tab.getAttribute("aria-controls") && document.getElementById(tab.getAttribute("aria-controls"));
726
+ return p ? p.contains(el) : Boolean(el.closest('[role="tabpanel"]'));
727
+ }
728
+ const sum = t.closest("summary");
729
+ if (sum) return sum.parentElement?.tagName === "DETAILS" && sum.parentElement.open && sum.parentElement.contains(el);
730
+ const x = t.closest("[aria-expanded]");
731
+ return Boolean(x && x.getAttribute("aria-expanded") === "true" && regionOf(x)?.contains(el));
732
+ }
733
+ // An element that shows only while something is hovered: a CSS rule like ".nav li:hover > ul" (or Tailwind's
734
+ // group-hover) reveals the box it sits in. Read when the user clicks to pin, while the hover still holds.
735
+ function hoverOf(el) {
736
+ let n = 0;
737
+ const reveals = (st) => (st.display && st.display !== "none") || st.visibility === "visible" || (st.opacity && Number(st.opacity) > 0) || st.maxHeight || st.transform || st.clipPath || st.pointerEvents === "auto";
738
+ const walk = (rules) => {
739
+ for (const r of rules) {
740
+ if (++n > 6000) return null;
741
+ if (r.cssRules && !r.selectorText) {
742
+ const x = walk(r.cssRules);
743
+ if (x) return x;
744
+ continue;
745
+ }
746
+ if (!r.selectorText?.includes(":hover") || !reveals(r.style)) continue;
747
+ for (const part of r.selectorText.split(/,(?![^(]*\))/)) {
748
+ const i = part.lastIndexOf(":hover");
749
+ if (i < 0) continue;
750
+ const tail = part.slice(i + 6);
751
+ const own = /^[^\s>+~]*/.exec(tail)[0];
752
+ // :hover on the shown element itself isn't a reveal.
753
+ if (own.length === tail.length) continue;
754
+ const head = part.slice(0, i + 6) + own;
755
+ let shown = null;
756
+ try {
757
+ shown = el.closest(part.trim());
758
+ } catch {}
759
+ if (!shown) continue;
760
+ for (let a = shown; a && a !== document.documentElement; a = a.parentElement) {
761
+ const cands = a === shown ? [] : [a];
762
+ for (let s = a.previousElementSibling; s; s = s.previousElementSibling) cands.push(s);
763
+ for (const c of cands)
764
+ try {
765
+ if (c.matches(head)) return { trigger: c, shown };
766
+ } catch {}
767
+ }
768
+ }
769
+ }
770
+ return null;
771
+ };
772
+ for (const sh of document.styleSheets) {
773
+ let rules = null;
774
+ try {
775
+ rules = sh.cssRules;
776
+ } catch {}
777
+ const x = rules && walk(rules);
778
+ if (x) {
779
+ // The trigger's own words, without the menu it reveals: "Products", not "Products Analytics Billing".
780
+ const own = [...x.trigger.childNodes].filter((c) => !c.contains(x.shown)).map((c) => c.textContent).join(" ").replace(/\s+/g, " ").trim().slice(0, 80);
781
+ const at = locateStep(x.trigger);
782
+ return { ...x, step: { type: "hover", ...at, ...(own ? { name: own, text: own } : {}), at: Date.now(), rest: false, _el: x.trigger } };
783
+ }
784
+ if (n > 6000) break;
785
+ }
786
+ return null;
787
+ }
788
+ // The steps a pin carries (see trimTrail in trail.mjs), and what the element sits in: the modal, the menu…
789
+ function pinTrail(el, hover) {
790
+ const base = trail.base ?? new Set();
791
+ let layer = null;
792
+ for (const [e, kind] of layers()) {
793
+ if (base.has(e) || !e.contains(el)) continue;
794
+ // A layer the hover reveals is the hover's, not a click's.
795
+ if (hover && (hover.shown.contains(e) || e === hover.shown)) continue;
796
+ if (!layer || layer.el.contains(e)) layer = { el: e, kind };
797
+ }
798
+ const t0 = trail.steps[0]?.at ?? Infinity;
799
+ const revealedAt = [];
800
+ for (let a = el; a && a !== document.body; a = a.parentElement) {
801
+ const t = trail.born.get(a);
802
+ if (t >= t0) revealedAt.push(t);
803
+ }
804
+ let steps = T.trimTrail(
805
+ trail.steps.map((s) => ({ ...s, keep: holds(s, el) })),
806
+ { inOpen: Boolean(layer), revealedAt },
807
+ );
808
+ let kind = layer?.kind ?? null;
809
+ if (hover && hover.shown.contains(el)) {
810
+ steps = [...steps.filter((s) => s._el !== hover.trigger), hover.step].slice(-T.MAX);
811
+ kind ??= "hover menu";
812
+ }
813
+ if (!kind && steps.length) kind = el.closest('[role="tabpanel"]') ? "tab panel" : null;
814
+ return { steps: steps.map(({ _el, rest, keep, ...s }) => s), layer: kind };
815
+ }
816
+
817
+ // palate's own UI never tells the page that focus or a press went outside it, so an open modal or menu
818
+ // (focus traps, close on click outside) stays open while the user writes their pin.
819
+ for (const t of ["focusin", "focusout"])
820
+ addEventListener(
821
+ t,
822
+ (e) => {
823
+ if (e.target === host || e.relatedTarget === host) e.stopImmediatePropagation();
824
+ },
825
+ true,
826
+ );
827
+ for (const t of ["pointerdown", "mousedown", "touchstart", "focusin", "focusout"]) sr.addEventListener(t, (e) => e.stopPropagation());
828
+
829
+ // ---------- Point mode ----------
830
+ function setMode(on) {
831
+ S.on = on;
832
+ ui.fab.classList.toggle("on", on);
833
+ ui.fab.setAttribute("aria-pressed", String(on));
834
+ document.documentElement.classList.toggle("palate-pointing", on);
835
+ if (!on) {
836
+ closeDialog();
837
+ ui.hl.hidden = true;
838
+ ui.hint.hidden = true;
839
+ S.target = S.leaf = null;
840
+ } else {
841
+ closePop();
842
+ ui.hint.hidden = false;
843
+ ui.hint.innerHTML = coarse ? `<b>Tap</b> an element to point at it` : `<b>Click</b> to point at it<span class="ext"><span class="sep"></span><kbd>↑</kbd><kbd>↓</kbd> parent / child</span><span class="sep"></span><kbd>Esc</kbd> stop`;
844
+ }
845
+ loop();
846
+ }
847
+ const cursorStyle = document.createElement("style");
848
+ cursorStyle.textContent = "html.palate-pointing, html.palate-pointing * { cursor: crosshair !important; }";
849
+
850
+ for (const t of ["pointerdown", "mousedown", "pointerup", "mouseup", "dblclick", "contextmenu", "auxclick"])
851
+ window.addEventListener(
852
+ t,
853
+ (e) => {
854
+ if (!S.on || ours(e)) return;
855
+ e.preventDefault();
856
+ e.stopImmediatePropagation();
857
+ },
858
+ true,
859
+ );
860
+ window.addEventListener(
861
+ "click",
862
+ (e) => {
863
+ if (!S.on || ours(e)) return;
864
+ e.preventDefault();
865
+ e.stopImmediatePropagation();
866
+ if (S.dialog) {
867
+ // A click elsewhere moves the dialog (and its draft) to that element.
868
+ const leaf = leafAt(e.clientX, e.clientY);
869
+ if (!leaf) return;
870
+ S.leaf = S.target = leaf;
871
+ openDialog(leaf, { x: e.clientX, y: e.clientY });
872
+ return;
873
+ }
874
+ if (coarse || !S.target) hoverAt(e.clientX, e.clientY);
875
+ if (S.target) openDialog(S.target, { x: e.clientX, y: e.clientY });
876
+ },
877
+ true,
878
+ );
879
+ window.addEventListener(
880
+ "pointermove",
881
+ (e) => {
882
+ if (!S.on || S.dialog || e.pointerType === "touch") return;
883
+ if (ours(e)) return void (ui.hl.hidden = true);
884
+ hoverAt(e.clientX, e.clientY);
885
+ },
886
+ { capture: true, passive: true },
887
+ );
888
+ window.addEventListener(
889
+ "keydown",
890
+ (e) => {
891
+ if (e.altKey && !e.ctrlKey && !e.metaKey && e.code === "KeyP") {
892
+ e.preventDefault();
893
+ e.stopImmediatePropagation();
894
+ return setMode(!S.on);
895
+ }
896
+ if (e.key === "Escape") {
897
+ if (S.zoom) return void closeZoom();
898
+ if (S.pop) return void closePop();
899
+ if (!S.on) return;
900
+ e.preventDefault();
901
+ e.stopImmediatePropagation();
902
+ if (S.dialog) closeDialog();
903
+ else setMode(false);
904
+ return;
905
+ }
906
+ if (!S.on || ours(e)) return;
907
+ if (e.key === "ArrowUp" || e.key === "ArrowDown") {
908
+ e.preventDefault();
909
+ e.stopImmediatePropagation();
910
+ e.key === "ArrowUp" ? up() : down();
911
+ } else if (e.key === "Enter" && S.target && !S.dialog) {
912
+ e.preventDefault();
913
+ e.stopImmediatePropagation();
914
+ const r = S.target.getBoundingClientRect();
915
+ openDialog(S.target, { x: r.left + 12, y: r.top + 12 });
916
+ }
917
+ },
918
+ true,
919
+ );
920
+ // Keys typed in palate's own UI never reach the page's shortcuts.
921
+ for (const t of ["keydown", "keyup", "keypress"]) sr.addEventListener(t, (e) => e.stopPropagation());
922
+ ui.fab.addEventListener("click", () => setMode(!S.on));
923
+
924
+ // ---------- Dialog ----------
925
+ function renderDialogHead() {
926
+ const d = S.dialog;
927
+ const head = ui.dialog.querySelector(".name");
928
+ if (head) head.innerHTML = nameHTML(describe(d.el));
929
+ renderViewport();
930
+ const p = d.el.parentElement;
931
+ ui.dialog.querySelector('[data-a="up"]').disabled = !p || p === document.documentElement;
932
+ // The steps that opened the state this element sits in: "+2 steps to open", so the user knows.
933
+ d.trail = pinTrail(d.el, d.hover);
934
+ const k = d.trail.steps.length;
935
+ ui.dialog.querySelector(".note").textContent = `Pin ${d.n} · queued${k ? "" : " for the agent"}`;
936
+ const steps = ui.dialog.querySelector(".steps");
937
+ steps.hidden = !k;
938
+ steps.textContent = `+${k} step${k > 1 ? "s" : ""} to open`;
939
+ steps.title = k ? `palate reopens this for every check: ${d.trail.steps.map(T.stepShort).join(" → ")}${d.trail.layer ? ` → the ${d.trail.layer}` : ""}` : "";
940
+ }
941
+ // Which width the user is pinning at, small and muted in the dialog's header.
942
+ function renderViewport() {
943
+ const vp = ui.dialog.querySelector(".vp");
944
+ if (!vp) return;
945
+ vp.textContent = `${innerWidth} × ${innerHeight}`;
946
+ vp.title = `You're pinning at ${innerWidth} × ${innerHeight} (${wname(innerWidth)}). The fix is also checked at ${otherOf(innerWidth)} (${wname(otherOf(innerWidth))}).`;
947
+ }
948
+ function openDialog(el, at) {
949
+ closePop();
950
+ const draft = S.dialog ? { text: ui.dialog.querySelector("textarea").value, chips: [...S.dialog.chips] } : { text: "", chips: [] };
951
+ const n = (S.requests.reduce((a, r) => Math.max(a, r.n), 0) || 0) + 1;
952
+ // Read now, while the pointer still holds any hover that shows the element.
953
+ S.dialog = { el, at, chips: new Set(draft.chips), n, hover: hoverOf(el) };
954
+ ui.hint.hidden = true;
955
+ const mod = isMac ? "⌘" : "Ctrl";
956
+ ui.dialog.innerHTML = `
957
+ <div class="dh"><div class="name"></div><span class="vp"></span>
958
+ <button class="ib" type="button" data-a="up" title="Select the parent (↑)" aria-label="Select the parent element">${ICON.up}</button>
959
+ <button class="ib" type="button" data-a="down" title="Select a child (↓)" aria-label="Select a child element">${ICON.down}</button>
960
+ <button class="ib" type="button" data-a="close" title="Close (Esc)" aria-label="Close">${ICON.x}</button></div>
961
+ <textarea rows="2" placeholder="What should change?" aria-label="What should change?"></textarea>
962
+ <div class="chips" role="group" aria-label="Quick requests">${CHIPS.map((c) => `<button class="chip" type="button" aria-pressed="${S.dialog.chips.has(c)}">${esc(c)}</button>`).join("")}</div>
963
+ <div class="df"><span class="note">Pin ${n} · queued for the agent</span><span class="steps" hidden></span><button class="send" type="button" disabled>Send <kbd>${mod} ↵</kbd></button></div>`;
964
+ ui.dialog.hidden = false;
965
+ const ta = ui.dialog.querySelector("textarea");
966
+ ta.value = draft.text;
967
+ renderDialogHead();
968
+ draw(el, { bands: false, frozen: true });
969
+ placeDialog();
970
+ const sendBtn = ui.dialog.querySelector(".send");
971
+ const sync = () => {
972
+ sendBtn.disabled = S.sending || (!ta.value.trim() && !S.dialog.chips.size);
973
+ ta.style.height = "auto";
974
+ ta.style.height = `${Math.min(ta.scrollHeight, 160)}px`;
975
+ };
976
+ ta.addEventListener("input", sync);
977
+ ta.addEventListener("keydown", (e) => {
978
+ if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
979
+ e.preventDefault();
980
+ send();
981
+ } else if (e.key === "Escape") {
982
+ e.preventDefault();
983
+ closeDialog();
984
+ }
985
+ });
986
+ ui.dialog.querySelectorAll(".chip").forEach((b) =>
987
+ b.addEventListener("click", () => {
988
+ const c = b.textContent;
989
+ S.dialog.chips.has(c) ? S.dialog.chips.delete(c) : S.dialog.chips.add(c);
990
+ b.setAttribute("aria-pressed", String(S.dialog.chips.has(c)));
991
+ sync();
992
+ ta.focus();
993
+ }),
994
+ );
995
+ ui.dialog.querySelector('[data-a="up"]').addEventListener("click", up);
996
+ ui.dialog.querySelector('[data-a="down"]').addEventListener("click", down);
997
+ ui.dialog.querySelector('[data-a="close"]').addEventListener("click", closeDialog);
998
+ sendBtn.addEventListener("click", send);
999
+ sync();
1000
+ requestAnimationFrame(() => ta.focus({ preventScroll: true }));
1001
+ loop();
1002
+ }
1003
+ function placeDialog() {
1004
+ if (!S.dialog || innerWidth <= 520) return;
1005
+ const r = S.dialog.el.getBoundingClientRect();
1006
+ const w = ui.dialog.offsetWidth || 360;
1007
+ const h = ui.dialog.offsetHeight || 200;
1008
+ const big = r.height > innerHeight * 0.55 || r.width > innerWidth * 0.8;
1009
+ let x;
1010
+ let y;
1011
+ if (big) {
1012
+ // Sections: open by the pointer, not at an edge far away.
1013
+ x = S.dialog.at.x - 24;
1014
+ y = S.dialog.at.y + 16;
1015
+ if (y + h > innerHeight - 12) y = S.dialog.at.y - h - 16;
1016
+ } else {
1017
+ x = r.left;
1018
+ y = r.bottom + 10;
1019
+ if (y + h > innerHeight - 12) y = r.top - h - 10;
1020
+ if (y < 12) y = Math.min(innerHeight - h - 12, Math.max(12, r.top + 12));
1021
+ }
1022
+ x = Math.min(Math.max(12, x), innerWidth - w - 12);
1023
+ y = Math.min(Math.max(12, y), innerHeight - h - 12);
1024
+ ui.dialog.style.left = `${x}px`;
1025
+ ui.dialog.style.top = `${y}px`;
1026
+ ui.dialog.style.setProperty("--ox", `${Math.min(Math.max(0, S.dialog.at.x - x), w)}px`);
1027
+ ui.dialog.style.setProperty("--oy", `${y < r.top ? h : 0}px`);
1028
+ }
1029
+ function closeDialog() {
1030
+ if (!S.dialog) return;
1031
+ S.dialog = null;
1032
+ ui.dialog.hidden = true;
1033
+ ui.dialog.innerHTML = "";
1034
+ ui.hl.hidden = true;
1035
+ if (S.on) ui.hint.hidden = false;
1036
+ }
1037
+
1038
+ function payload(el) {
1039
+ const r = el.getBoundingClientRect();
1040
+ return {
1041
+ route: location.pathname + location.search,
1042
+ href: location.href,
1043
+ title: document.title,
1044
+ selector: selectorOf(el),
1045
+ path: domPath(el),
1046
+ tag: el.tagName.toLowerCase(),
1047
+ id: el.id || null,
1048
+ className: typeof el.className === "string" ? el.className : el.getAttribute("class") || "",
1049
+ label: describe(el),
1050
+ text: (el.innerText || el.textContent || "").replace(/\s+/g, " ").trim().slice(0, 600),
1051
+ textNodes: textNodes(el),
1052
+ outerHTML: trimHTML(el),
1053
+ styles: keyStyles(el),
1054
+ framework: framework(el),
1055
+ box: { x: Math.round(r.left), y: Math.round(r.top), width: Math.round(r.width), height: Math.round(r.height) },
1056
+ viewport: { width: innerWidth, height: innerHeight },
1057
+ dpr: devicePixelRatio || 1,
1058
+ scroll: { x: Math.round(scrollX), y: Math.round(scrollY) },
1059
+ colorScheme: matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light",
1060
+ };
1061
+ }
1062
+ async function send() {
1063
+ const d = S.dialog;
1064
+ if (!d || S.sending) return;
1065
+ const ta = ui.dialog.querySelector("textarea");
1066
+ const prompt = ta.value.trim();
1067
+ const chips = CHIPS.filter((c) => d.chips.has(c));
1068
+ if (!prompt && !chips.length) return;
1069
+ S.sending = true;
1070
+ const btn = ui.dialog.querySelector(".send");
1071
+ btn.disabled = true;
1072
+ try {
1073
+ const res = await fetch(`${API}/request`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ ...payload(d.el), prompt, chips, trail: d.trail?.steps ?? [], layer: d.trail?.layer ?? null }) });
1074
+ if (!res.ok) throw new Error(await res.text());
1075
+ const { agent, ...r } = await res.json();
1076
+ S.els.set(r.id, d.el);
1077
+ if (agent) setAgent(agent);
1078
+ upsert(r);
1079
+ closeDialog();
1080
+ // Nothing is lost without an agent: the pin waits in the queue and the next agent takes it in order.
1081
+ if (noAgent()) toast(`<b>Pin ${r.n} queued, but your agent isn't listening.</b> ${START_AGENT}`, "warn", 9000);
1082
+ else toast(`<b>Pin ${r.n} queued.</b> Point at another element, or ${coarse ? "tap the button" : "Esc"} when you're done.`);
1083
+ } catch (e) {
1084
+ console.warn("palate point:", e);
1085
+ toast(`<b>Couldn't send.</b> Is palate point still running?`);
1086
+ btn.disabled = false;
1087
+ } finally {
1088
+ S.sending = false;
1089
+ }
1090
+ }
1091
+
1092
+ // ---------- Pins ----------
1093
+ const here = (r) => r.route.split("?")[0] === location.pathname && r.status !== "canceled";
1094
+ function elementOf(r) {
1095
+ let el = S.els.get(r.id);
1096
+ if (el && el.isConnected) return el;
1097
+ try {
1098
+ el = document.querySelector(r.selector);
1099
+ } catch {
1100
+ el = null;
1101
+ }
1102
+ if (el) S.els.set(r.id, el);
1103
+ return el;
1104
+ }
1105
+ function upsert(r) {
1106
+ const i = S.requests.findIndex((x) => x.id === r.id);
1107
+ const before = i >= 0 ? S.requests[i] : null;
1108
+ if (i >= 0) S.requests[i] = r;
1109
+ else S.requests.push(r);
1110
+ if (before && before.status !== "done" && r.status === "done") {
1111
+ S.els.delete(r.id);
1112
+ if (here(r)) toast(`<b>Pin ${r.n} done.</b> ${esc(r.summary || "")}`, true);
1113
+ }
1114
+ if (before && before.status !== "failed" && r.status === "failed") toast(`<b>Pin ${r.n} failed.</b> Open the pin to see why, or retry.`, "warn", 6000);
1115
+ if (S.pop?.id === r.id) renderPop();
1116
+ renderPins();
1117
+ renderAgent();
1118
+ }
1119
+ function renderPins() {
1120
+ const list = S.requests.filter(here);
1121
+ const open = S.requests.filter((r) => r.status === "queued" || r.status === "working").length;
1122
+ ui.badge.hidden = !open;
1123
+ ui.badge.textContent = String(open);
1124
+ for (const p of [...ui.pins.children]) if (!list.some((r) => r.id === p.dataset.id)) p.remove();
1125
+ for (const r of list) {
1126
+ let p = ui.pins.querySelector(`[data-id="${CSS.escape(r.id)}"]`);
1127
+ if (!p) {
1128
+ p = document.createElement("button");
1129
+ p.type = "button";
1130
+ p.className = "pin";
1131
+ p.dataset.id = r.id;
1132
+ p.addEventListener("click", (e) => {
1133
+ e.stopPropagation();
1134
+ S.pop?.id === r.id ? closePop() : openPop(r.id);
1135
+ });
1136
+ p.addEventListener("pointerenter", () => ghost(r.id));
1137
+ p.addEventListener("pointerleave", () => ghost(null));
1138
+ ui.pins.appendChild(p);
1139
+ }
1140
+ if (p.dataset.status !== r.status) {
1141
+ p.dataset.status = r.status;
1142
+ p.className = `pin ${r.status}`;
1143
+ p.innerHTML = r.status === "done" ? ICON.check : String(r.n);
1144
+ }
1145
+ // The other width broke: a small amber dot on the pin.
1146
+ const broke = r.other?.verdict === "broke" && (r.status === "done" || r.status === "working");
1147
+ p.classList.toggle("broke", broke);
1148
+ p.setAttribute("aria-label", `Pin ${r.n}: ${STATUS[r.status] ?? r.status}${broke ? `, broke at ${r.other.width}` : ""}`);
1149
+ p.title = `${r.n}. ${r.prompt || r.chips.join(", ")} (${r.status === "failed" ? "Failed: retry" : (STATUS[r.status] ?? r.status)})${broke ? ` · Broke at ${r.other.width}` : ""}`;
1150
+ }
1151
+ loop();
1152
+ }
1153
+ // Where a pin sits: the element's top-right corner, or where the element was when it can't be found.
1154
+ function anchorOf(r) {
1155
+ const el = elementOf(r);
1156
+ if (visible(el)) return el.getBoundingClientRect();
1157
+ const x = r.box.x + r.scroll.x - scrollX;
1158
+ const y = r.box.y + r.scroll.y - scrollY;
1159
+ return { left: x, top: y, right: x + r.box.width, bottom: y + r.box.height, width: r.box.width, height: r.box.height };
1160
+ }
1161
+ function placePins() {
1162
+ const used = new Map();
1163
+ for (const p of ui.pins.children) {
1164
+ const r = S.requests.find((x) => x.id === p.dataset.id);
1165
+ if (!r) continue;
1166
+ const a = anchorOf(r);
1167
+ const key = `${Math.round(a.right)}|${Math.round(a.top)}`;
1168
+ const k = used.get(key) ?? 0;
1169
+ used.set(key, k + 1);
1170
+ const off = a.bottom < 0 || a.top > innerHeight || a.right < 0 || a.left > innerWidth;
1171
+ p.style.display = off ? "none" : "grid";
1172
+ const x = Math.min(Math.max(4, a.right - 12 - k * 28), innerWidth - 28);
1173
+ const y = Math.min(Math.max(4, a.top - 12), innerHeight - 28);
1174
+ const t = `translate(${x}px, ${y}px)`;
1175
+ p.style.transform = t;
1176
+ p.style.setProperty("--t", t);
1177
+ }
1178
+ if (S.ghost) {
1179
+ const r = S.requests.find((x) => x.id === S.ghost.id);
1180
+ const a = r && anchorOf(r);
1181
+ if (a) Object.assign(S.ghost.el.style, { transform: `translate(${a.left}px, ${a.top}px)`, width: `${a.width}px`, height: `${a.height}px` });
1182
+ }
1183
+ if (S.pop) placePop();
1184
+ }
1185
+ function ghost(id) {
1186
+ S.ghost?.el.remove();
1187
+ S.ghost = null;
1188
+ if (!id || S.on) return;
1189
+ const el = document.createElement("div");
1190
+ el.className = "ghost";
1191
+ ui.pins.prepend(el);
1192
+ S.ghost = { id, el };
1193
+ placePins();
1194
+ }
1195
+
1196
+ // ---------- Pin popover ----------
1197
+ function openPop(id) {
1198
+ if (S.dialog) closeDialog();
1199
+ S.pop = { id, view: "after" };
1200
+ ui.pop.hidden = false;
1201
+ renderPop();
1202
+ placePop();
1203
+ }
1204
+ function closePop() {
1205
+ S.pop = null;
1206
+ ui.pop.hidden = true;
1207
+ ui.pop.innerHTML = "";
1208
+ }
1209
+ function renderPop() {
1210
+ const r = S.requests.find((x) => x.id === S.pop?.id);
1211
+ if (!r) return closePop();
1212
+ const v = r.doneAt || r.created;
1213
+ const img = (k) => `/__palate/img/${encodeURIComponent(r.id)}/${k}.png?v=${encodeURIComponent(v)}`;
1214
+ const st = r.status === "working" ? `<span class="spin" aria-hidden="true"></span>` : `<span class="d ${r.status}"></span>`;
1215
+ const view = S.pop.view;
1216
+ // A request about another width ("on mobile") has crops at that width too; they show first.
1217
+ const alt = r.alt?.width ? r.alt : null;
1218
+ const size = alt && S.pop.size !== "main" ? "alt" : "main";
1219
+ const name = (k) => (size === "alt" ? `${k}-${alt.width}` : k);
1220
+ const hasBefore = size === "alt" ? alt.before : r.hasCrop;
1221
+ const gone = r.status === "done" && Boolean(size === "alt" ? alt.removed : r.removed);
1222
+ const hasAfter = r.status === "done" && (size === "alt" ? alt.after : r.hasAfter);
1223
+ const compare = hasAfter || gone;
1224
+ const goneHTML = `<div class="gone"><b>Removed</b><span>The element is gone, as asked.</span></div>`;
1225
+ const sizes = alt ? `<div class="seg" role="group" aria-label="Width"><button type="button" data-s="alt" aria-pressed="${size === "alt"}">${alt.width} wide</button><button type="button" data-s="main" aria-pressed="${size === "main"}">${r.viewport?.width ?? "Desktop"} wide</button></div>` : "";
1226
+ // Before and after at both widths, once done: rows for desktop and phone (widest first), the pinned one marked.
1227
+ const o = r.other?.width ? r.other : null;
1228
+ const vw = r.viewport?.width;
1229
+ const rows =
1230
+ r.status === "done" && o?.after && vw
1231
+ ? [
1232
+ { w: vw, pinned: true, before: r.hasCrop ? img("crop") : null, after: r.removed ? "gone" : r.hasAfter ? img("after") : null, bs: r.reopen?.before === STUCK ? STUCK : null, as: r.reopen?.after === STUCK ? STUCK : null },
1233
+ { w: o.width, pinned: false, before: o.before?.has ? img(`crop-${o.width}`) : null, after: o.after.removed ? "gone" : o.after.has ? img(`after-${o.width}`) : null, bs: o.before?.reopen === STUCK ? STUCK : o.before?.state, as: o.after.reopen === STUCK ? STUCK : o.after.state },
1234
+ ].sort((a, b) => b.w - a.w)
1235
+ : null;
1236
+ const where = (s) => (s === STUCK ? `<span class="cap">Couldn't reopen</span>` : s === "hidden" ? `<span class="cap">Hidden here</span>` : s === "missing" ? `<span class="cap">Not on the page</span>` : "");
1237
+ const cell = (src, i, state, label) =>
1238
+ src === "gone" ? `<button class="cell empty" type="button" data-z="${i}" aria-label="${label}: removed">Removed</button>` : src ? `<button class="cell" type="button" data-z="${i}" aria-label="${label}, enlarge"><img alt="" src="${src}">${where(state)}</button>` : `<div class="cell empty">No crop</div>`;
1239
+ const grid = rows
1240
+ ? `<div class="bx"><div class="cols"><span>Before</span><span>After</span></div>${rows
1241
+ .map((x, i) => {
1242
+ const name = wname(x.w);
1243
+ const tag = x.pinned ? "pinned" : o.verdict && o.verdict !== "unknown" ? o.verdict : "";
1244
+ return `<div class="rl"><b>${name[0].toUpperCase()}${name.slice(1)}</b><span>${x.w}</span><span class="tg ${x.pinned ? "" : esc(o.verdict ?? "")}">${tag}</span></div><div class="pair2">${cell(x.before, i, x.bs, `${name} before`)}${cell(x.after, i, x.as, `${name} after`)}</div>`;
1245
+ })
1246
+ .join("")}</div>`
1247
+ : "";
1248
+ // The other width's verdict: a calm warning when it broke, a quiet note otherwise.
1249
+ const verdict =
1250
+ o?.verdict === "broke" && (r.status === "done" || r.status === "working")
1251
+ ? `<p class="warnbox" role="note"><span class="wd" aria-hidden="true"></span><span>${r.status === "working" ? "The agent's last check: " : ""}<b>Broke at ${o.width}:</b> ${esc((o.problems ?? []).join("; "))}.</span></p>`
1252
+ : r.status === "done" && o?.verdict === "changed"
1253
+ ? `<p class="onote">Changed at ${o.width}: ${esc((o.changes ?? []).join("; "))}.</p>`
1254
+ : r.status === "done" && o?.verdict === "unchanged"
1255
+ ? `<p class="onote">Unchanged at ${o.width}.</p>`
1256
+ : "";
1257
+ // The state this pin sits in, and whether palate could open it again for the checks.
1258
+ const opened = r.trail?.length ? `<p class="onote">Opened by: ${esc(r.trail.map(T.stepShort).join(" → "))}${r.layer ? ` → the ${esc(r.layer)}` : ""}</p>` : "";
1259
+ const stuck = r.reopen?.fail ? `<p class="onote stuck">Couldn't reopen this state for the check${r.reopen.fail.width ? ` at ${r.reopen.fail.width}` : ""}: ${esc(r.reopen.fail.why)}</p>` : "";
1260
+ const vpc = vw ? `<span class="vpc" title="Pinned at ${vw} × ${r.viewport.height} (${wname(vw)})${o ? `; checked at ${o.width} too` : ""}">${vw} × ${r.viewport.height}</span>` : "";
1261
+ ui.pop.setAttribute("aria-label", `Pin ${r.n}`);
1262
+ ui.pop.innerHTML = `
1263
+ <div class="ph"><div class="st">${st}<b>Pin ${r.n}</b><span>${STATUS[r.status] ?? r.status}</span></div>${vpc}<button class="ib" type="button" data-a="close" aria-label="Close">${ICON.x}</button></div>
1264
+ <div class="pb">
1265
+ ${r.prompt ? `<p class="ask">${esc(r.prompt)}</p>` : ""}
1266
+ ${r.chips.length ? `<div class="tags">${r.chips.map((c) => `<span>${esc(c)}</span>`).join("")}</div>` : ""}
1267
+ ${opened}
1268
+ ${r.status === "done" && r.summary ? `<p class="sum"><b>Agent:</b> ${esc(r.summary)}</p>` : ""}
1269
+ ${verdict}
1270
+ ${stuck}
1271
+ ${r.status === "working" ? `<p class="sum">The agent is changing this element. The page reloads by itself when it saves.</p>` : ""}
1272
+ ${r.status === "queued" ? `<p class="sum">${noAgent() ? `Queued${r.position ? ` (${r.position} in line)` : ""}. No agent is listening: ${START_AGENT}` : `Waiting for the agent${r.position ? ` (${r.position} in line)` : ""}.`}</p>` : ""}
1273
+ ${r.status === "failed" ? `<p class="sum">The agent stopped without finishing this one. Its last lines:</p>${r.error ? `<pre class="err mono">${esc(r.error)}</pre>` : ""}` : ""}
1274
+ ${
1275
+ grid
1276
+ ? grid
1277
+ : compare
1278
+ ? `<div class="ba"><div class="segs"><div class="seg" role="group" aria-label="Compare"><button type="button" data-v="before" aria-pressed="${view === "before"}">Before</button><button type="button" data-v="after" aria-pressed="${view === "after"}">After</button></div>${sizes}</div>
1279
+ ${view === "after" && gone ? goneHTML : `<button class="shot" type="button" title="Hold to see before · click to enlarge"><img alt="${view === "after" ? "After" : "Before"} the change" src="${img(name(view === "after" ? "after" : "crop"))}"></button>${gone ? "" : `<span class="hold">Hold the picture to see before</span>`}`}</div>`
1280
+ : hasBefore
1281
+ ? `<div class="ba">${sizes ? `<div class="segs">${sizes}</div>` : ""}<button class="shot" type="button" title="Click to enlarge"><img alt="The element when you pointed at it" src="${img(name("crop"))}"><span class="cap">Before</span></button></div>`
1282
+ : sizes ? `<div class="ba"><div class="segs">${sizes}</div><span class="hold">No crop at this width.</span></div>` : ""
1283
+ }
1284
+ ${r.status === "queued" ? `<div class="pa"><button class="btn" type="button" data-a="cancel">Remove pin</button></div>` : ""}
1285
+ ${r.status === "failed" ? `<div class="pa"><button class="btn" type="button" data-a="retry">Retry</button><button class="btn" type="button" data-a="cancel">Remove pin</button></div>` : ""}
1286
+ ${r.status === "done" ? `<div class="pa"><button class="btn" type="button" data-a="again">Ask again</button></div>` : ""}
1287
+ </div>`;
1288
+ ui.pop.querySelector('[data-a="close"]').addEventListener("click", closePop);
1289
+ ui.pop.querySelectorAll("[data-v]").forEach((b) => b.addEventListener("click", () => ((S.pop.view = b.dataset.v), renderPop())));
1290
+ ui.pop.querySelectorAll("[data-s]").forEach((b) => b.addEventListener("click", () => ((S.pop.size = b.dataset.s), renderPop())));
1291
+ ui.pop.querySelectorAll("[data-z]").forEach((b) =>
1292
+ b.addEventListener("click", () => {
1293
+ const x = rows[Number(b.dataset.z)];
1294
+ const at = `${x.w}${x.pinned ? ", pinned" : ""}`;
1295
+ zoom([
1296
+ [`Before · ${at}`, x.before, "No crop"],
1297
+ [`After · ${at}`, x.after === "gone" ? null : x.after, x.after === "gone" ? null : "No crop"],
1298
+ ]);
1299
+ }),
1300
+ );
1301
+ const shot = ui.pop.querySelector(".shot");
1302
+ if (shot) {
1303
+ const im = shot.querySelector("img");
1304
+ const seg = ui.pop.querySelectorAll("[data-v]");
1305
+ const show = (v) => seg.forEach((b) => b.setAttribute("aria-pressed", String(b.dataset.v === v)));
1306
+ let held = false;
1307
+ let timer = 0;
1308
+ if (hasAfter && !gone) {
1309
+ shot.addEventListener("pointerdown", () => {
1310
+ timer = setTimeout(() => {
1311
+ held = true;
1312
+ im.src = img(name("crop"));
1313
+ show("before");
1314
+ }, 160);
1315
+ });
1316
+ const release = () => {
1317
+ clearTimeout(timer);
1318
+ if (!held) return;
1319
+ setTimeout(() => (held = false), 0);
1320
+ im.src = img(name(view === "after" ? "after" : "crop"));
1321
+ show(view);
1322
+ };
1323
+ shot.addEventListener("pointerup", release);
1324
+ shot.addEventListener("pointerleave", release);
1325
+ }
1326
+ shot.addEventListener("click", () => {
1327
+ if (held) return;
1328
+ zoom(compare ? [["Before", img(name("crop"))], ["After", gone ? null : img(name("after"))]] : [["Before", img(name("crop"))]]);
1329
+ });
1330
+ }
1331
+ ui.pop.querySelector('[data-a="cancel"]')?.addEventListener("click", async () => {
1332
+ await fetch(`${API}/cancel`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ id: r.id }) }).catch(() => {});
1333
+ closePop();
1334
+ });
1335
+ ui.pop.querySelector('[data-a="retry"]')?.addEventListener("click", async () => {
1336
+ const res = await fetch(`${API}/retry`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ id: r.id }) }).catch(() => null);
1337
+ const j = await res?.json().catch(() => null);
1338
+ if (j?.agent) setAgent(j.agent);
1339
+ if (noAgent()) toast(`<b>Pin ${r.n} is queued again, but your agent isn't listening.</b> ${START_AGENT}`, "warn", 9000);
1340
+ });
1341
+ ui.pop.querySelector('[data-a="again"]')?.addEventListener("click", () => {
1342
+ const el = elementOf(r);
1343
+ closePop();
1344
+ if (!el) return toast("<b>That element has changed.</b> Point at it again.");
1345
+ setMode(true);
1346
+ S.leaf = S.target = el;
1347
+ const a = el.getBoundingClientRect();
1348
+ openDialog(el, { x: a.left + 12, y: a.top + 12 });
1349
+ });
1350
+ placePop();
1351
+ }
1352
+ function placePop() {
1353
+ if (!S.pop || innerWidth <= 520) return;
1354
+ const p = ui.pins.querySelector(`[data-id="${CSS.escape(S.pop.id)}"]`);
1355
+ if (!p) return;
1356
+ const pr = p.getBoundingClientRect();
1357
+ const w = ui.pop.offsetWidth || 300;
1358
+ const h = ui.pop.offsetHeight || 160;
1359
+ // Beside the pin when there's room, otherwise under it (right edges aligned), so it covers less of the element.
1360
+ let x = pr.right + 8;
1361
+ let y = pr.top - 8;
1362
+ if (x + w > innerWidth - 12) {
1363
+ x = pr.right - w;
1364
+ y = pr.bottom + 8;
1365
+ if (y + h > innerHeight - 12) y = pr.top - h - 8;
1366
+ }
1367
+ x = Math.min(Math.max(12, x), innerWidth - w - 12);
1368
+ y = Math.min(Math.max(12, y), innerHeight - h - 12);
1369
+ ui.pop.style.left = `${x}px`;
1370
+ ui.pop.style.top = `${y}px`;
1371
+ }
1372
+ function zoom(images) {
1373
+ closeZoom();
1374
+ const z = document.createElement("div");
1375
+ z.className = "zoom";
1376
+ z.setAttribute("role", "dialog");
1377
+ z.setAttribute("aria-label", "Before and after");
1378
+ // [caption, src, text when there's no picture (default: removed, as asked)]
1379
+ z.innerHTML = `<div class="pair">${images.map(([c, src, none]) => `<figure><figcaption>${c}</figcaption>${src ? `<img src="${src}" alt="${c}">` : none ? `<div class="gone"><b>${none}</b></div>` : `<div class="gone"><b>Removed</b><span>The element is gone, as asked.</span></div>`}</figure>`).join("")}</div>`;
1380
+ z.addEventListener("click", closeZoom);
1381
+ ui.root.appendChild(z);
1382
+ S.zoom = z;
1383
+ }
1384
+ function closeZoom() {
1385
+ S.zoom?.remove();
1386
+ S.zoom = null;
1387
+ }
1388
+
1389
+ // ---------- Toast, frame loop, live status ----------
1390
+ let toastTimer = 0;
1391
+ // tone: true or "ok" (done), "warn" (needs the user); long messages wrap and stay longer.
1392
+ function toast(html, tone = false, ms = 3600) {
1393
+ ui.toast.innerHTML = `<span class="dot"></span><span>${html}</span>`;
1394
+ ui.toast.classList.toggle("ok", tone === true || tone === "ok");
1395
+ ui.toast.classList.toggle("warn", tone === "warn");
1396
+ ui.toast.classList.toggle("long", ms > 3600);
1397
+ ui.toast.hidden = false;
1398
+ clearTimeout(toastTimer);
1399
+ toastTimer = setTimeout(() => (ui.toast.hidden = true), ms);
1400
+ }
1401
+
1402
+ // ---------- Is an agent listening? ----------
1403
+ // Only what the server says: a point server without the heartbeat (an older palate) shows no status at all.
1404
+ const noAgent = () => Boolean(S.agent) && (S.agent.state === "none" || S.agent.state === "stopped");
1405
+ function setAgent(a) {
1406
+ if (!a) return;
1407
+ S.agent = a;
1408
+ renderAgent();
1409
+ if (S.pop) renderPop();
1410
+ }
1411
+ function renderAgent() {
1412
+ const a = S.agent;
1413
+ ui.agent.hidden = !a;
1414
+ if (!a) return;
1415
+ const queued = S.requests.filter((r) => r.status === "queued").length;
1416
+ const who = a.auto ? "palate point --auto" : a.label === "cli" ? "palate point next" : "your agent";
1417
+ const text = { listening: "Agent listening", busy: `Agent working · pin ${a.pin}`, stopped: "Agent stopped", none: "No agent listening" }[a.state] ?? "No agent listening";
1418
+ ui.agent.dataset.state = a.state;
1419
+ ui.agent.classList.toggle("waiting", a.state === "none" && queued > 0);
1420
+ ui.agent.querySelector(".at").textContent = text;
1421
+ ui.agent.title =
1422
+ a.state === "listening" ? `${who} is waiting for your pins.` : a.state === "busy" ? `${who} is working on pin ${a.pin}.` : a.state === "stopped" ? "You pressed Done. Send a pin to start again." : "Your pins wait in the queue until an agent takes them. In Claude Code run /mcp__palate__point, or start palate point --auto.";
1423
+ ui.agent.querySelector(".stop").hidden = !(a.state === "listening" || a.state === "busy");
1424
+ }
1425
+ ui.agent.querySelector(".stop").addEventListener("click", async () => {
1426
+ const res = await fetch(`${API}/stop`, { method: "POST", headers: { "content-type": "application/json" }, body: "{}" }).catch(() => null);
1427
+ const j = await res?.json().catch(() => null);
1428
+ if (j?.agent) setAgent(j.agent);
1429
+ const open = S.requests.filter((r) => r.status === "queued" || r.status === "working").length;
1430
+ toast(open ? `<b>Done.</b> The agent finishes the ${open} pin${open > 1 ? "s" : ""} you sent, then stops listening.` : "<b>Done.</b> The agent stops listening. Send a pin to start again.");
1431
+ });
1432
+ let raf = 0;
1433
+ function loop() {
1434
+ if (raf) return;
1435
+ const tick = () => {
1436
+ raf = 0;
1437
+ if (S.dialog) {
1438
+ draw(S.dialog.el, { bands: false, frozen: true });
1439
+ placeDialog();
1440
+ } else if (S.on && S.target) draw(S.target);
1441
+ if (ui.pins.children.length) placePins();
1442
+ if (S.on || S.dialog || ui.pins.children.length || S.pop) raf = requestAnimationFrame(tick);
1443
+ };
1444
+ raf = requestAnimationFrame(tick);
1445
+ }
1446
+ function setState(list, agent) {
1447
+ S.requests = list;
1448
+ if (agent) S.agent = agent;
1449
+ renderPins();
1450
+ renderAgent();
1451
+ if (S.pop) renderPop();
1452
+ }
1453
+ let polling = 0;
1454
+ async function poll() {
1455
+ try {
1456
+ const r = await fetch(`${API}/state`).then((x) => x.json());
1457
+ setState(r.requests ?? [], r.agent);
1458
+ } catch {}
1459
+ }
1460
+ function connect() {
1461
+ if (!window.EventSource) return void (polling ||= setInterval(poll, 2000), poll());
1462
+ const es = new EventSource("/__palate/events");
1463
+ es.onmessage = (m) => {
1464
+ try {
1465
+ const d = JSON.parse(m.data);
1466
+ if (d.type === "state") setState(d.requests ?? [], d.agent);
1467
+ else if (d.type === "update" && d.request) upsert(d.request);
1468
+ else if (d.type === "agent") setAgent(d.agent);
1469
+ } catch {}
1470
+ };
1471
+ es.onerror = () => {
1472
+ es.close();
1473
+ polling ||= setInterval(poll, 2500);
1474
+ setTimeout(() => {
1475
+ clearInterval(polling);
1476
+ polling = 0;
1477
+ connect();
1478
+ }, 4000);
1479
+ };
1480
+ }
1481
+ // Client-side navigation: pins belong to their route.
1482
+ setInterval(() => {
1483
+ // A router that kept history's own pushState still resets the trail here.
1484
+ onNav();
1485
+ if (S.route === location.pathname) return;
1486
+ S.route = location.pathname;
1487
+ closeDialog();
1488
+ closePop();
1489
+ S.els.clear();
1490
+ renderPins();
1491
+ }, 400);
1492
+ addEventListener("resize", () => {
1493
+ renderViewport();
1494
+ placeDialog();
1495
+ placePop();
1496
+ });
1497
+
1498
+ function mount() {
1499
+ if (!document.body) return;
1500
+ (document.head || document.documentElement).appendChild(cursorStyle);
1501
+ document.body.appendChild(host);
1502
+ // Some frameworks replace the body on navigation; come back if that happens.
1503
+ new MutationObserver(() => {
1504
+ if (!host.isConnected && document.body) document.body.appendChild(host);
1505
+ if (!cursorStyle.isConnected) (document.head || document.documentElement).appendChild(cursorStyle);
1506
+ }).observe(document.documentElement, { childList: true, subtree: false });
1507
+ new MutationObserver(() => {
1508
+ if (!host.isConnected && document.body) document.body.appendChild(host);
1509
+ }).observe(document.body, { childList: true });
1510
+ connect();
1511
+ }
1512
+ // After hydration, so the page's framework never sees palate's element.
1513
+ const later = () => (window.requestIdleCallback ? requestIdleCallback(mount, { timeout: 1200 }) : setTimeout(mount, 300));
1514
+ if (document.readyState === "complete") later();
1515
+ else addEventListener("load", later, { once: true });
1516
+ })();