@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.
- package/LICENSE +20 -0
- package/README.md +153 -2
- package/bin/palate.mjs +894 -0
- package/kb/anatomy/data-table.md +24 -0
- package/kb/anatomy/empty-state.md +16 -0
- package/kb/anatomy/filter-toolbar.md +19 -0
- package/kb/anatomy/meter.md +16 -0
- package/kb/anatomy/product-window.md +18 -0
- package/kb/anatomy/settings-page.md +18 -0
- package/kb/anatomy/status-indicator.md +17 -0
- package/kb/anatomy/toast-undo.md +16 -0
- package/kb/bench/briefs.json +618 -0
- package/kb/craft/SOURCES.md +48 -0
- package/kb/craft/creativity.md +55 -0
- package/kb/craft/details.md +75 -0
- package/kb/craft/landing-demos.md +46 -0
- package/kb/craft/mistakes.md +73 -0
- package/kb/craft/motion.md +53 -0
- package/kb/craft/principles.md +68 -0
- package/kb/index/discovery.json +1 -0
- package/kb/inspiration/index.json +79 -0
- package/kb/moves/animated-comparison-table.md +58 -0
- package/kb/moves/before-after-slider.md +58 -0
- package/kb/moves/bento-live-tiles.md +57 -0
- package/kb/moves/calm-motion-system.md +63 -0
- package/kb/moves/canvas-grain.md +58 -0
- package/kb/moves/changelog-as-magazine.md +56 -0
- package/kb/moves/code-drawn-diagram.md +56 -0
- package/kb/moves/colophon.md +54 -0
- package/kb/moves/command-palette-site-nav.md +58 -0
- package/kb/moves/confetti-free-celebration.md +58 -0
- package/kb/moves/console-easter-egg.md +57 -0
- package/kb/moves/copy-confirmation.md +57 -0
- package/kb/moves/cursor-reactive-light.md +57 -0
- package/kb/moves/dark-band-contrast-section.md +55 -0
- package/kb/moves/designed-dark-mode.md +58 -0
- package/kb/moves/duotone-photography.md +55 -0
- package/kb/moves/editorial-drop-cap.md +58 -0
- package/kb/moves/editorial-grid-pull-quotes.md +55 -0
- package/kb/moves/engraving-colour-lens.md +64 -0
- package/kb/moves/explorable-control.md +57 -0
- package/kb/moves/feature-films-on-painted-stages.md +58 -0
- package/kb/moves/first-win-onboarding.md +59 -0
- package/kb/moves/footer-live-status.md +56 -0
- package/kb/moves/footer-rewards-the-end.md +58 -0
- package/kb/moves/generative-brand-pattern.md +55 -0
- package/kb/moves/gentle-error-nudge.md +59 -0
- package/kb/moves/halftone-dot-imagery.md +55 -0
- package/kb/moves/hand-drawn-annotations.md +55 -0
- package/kb/moves/hero-paints-itself-in.md +65 -0
- package/kb/moves/honest-progress-narration.md +58 -0
- package/kb/moves/honest-testimonial-wall.md +57 -0
- package/kb/moves/inline-sparklines-in-copy.md +57 -0
- package/kb/moves/inspect-our-taste.md +58 -0
- package/kb/moves/interactive-pricing-calculator.md +59 -0
- package/kb/moves/isometric-illustration-system.md +56 -0
- package/kb/moves/kinetic-variable-type.md +57 -0
- package/kb/moves/konami-secret.md +59 -0
- package/kb/moves/layered-paper-depth.md +56 -0
- package/kb/moves/lightweight-3d-object-hero.md +59 -0
- package/kb/moves/line-engraving-from-image.md +63 -0
- package/kb/moves/link-preview-peek.md +57 -0
- package/kb/moves/live-data-ticker.md +61 -0
- package/kb/moves/made-with-proof.md +51 -0
- package/kb/moves/magnetic-buttons.md +55 -0
- package/kb/moves/marquee-done-right.md +58 -0
- package/kb/moves/moves.yaml +450 -0
- package/kb/moves/museum-painting-backdrop.md +59 -0
- package/kb/moves/one-colour-brand-world.md +56 -0
- package/kb/moves/playful-404.md +58 -0
- package/kb/moves/pointer-highlight-word.md +56 -0
- package/kb/moves/product-in-context.md +56 -0
- package/kb/moves/real-world-data.md +58 -0
- package/kb/moves/referral-reward-reveal.md +59 -0
- package/kb/moves/riso-print-texture.md +57 -0
- package/kb/moves/screenshot-detail-crops.md +56 -0
- package/kb/moves/scroll-progress-chapters.md +57 -0
- package/kb/moves/scroll-scrubbed-product-film.md +62 -0
- package/kb/moves/self-playing-product-demo.md +61 -0
- package/kb/moves/shape-continuity-morph.md +58 -0
- package/kb/moves/sliding-nav-indicator.md +58 -0
- package/kb/moves/sticky-scroll-story.md +56 -0
- package/kb/moves/story-led-long-scroll.md +56 -0
- package/kb/moves/tactile-button.md +63 -0
- package/kb/moves/technical-drawing-lines.md +57 -0
- package/kb/moves/time-of-day-theming.md +56 -0
- package/kb/moves/tiny-game-easter-egg.md +60 -0
- package/kb/moves/type-decode-reveal.md +57 -0
- package/kb/moves/typographic-numeral-hero.md +58 -0
- package/kb/moves/view-transitions-between-pages.md +57 -0
- package/kb/moves/waitlist-position-live.md +60 -0
- package/kb/patterns/app-team-members.md +27 -0
- package/kb/patterns/chat-agent-approvals.md +31 -0
- package/kb/patterns/commerce-product-page.md +34 -0
- package/kb/patterns/dashboard-entity-table.md +37 -0
- package/kb/patterns/dashboard-home-today.md +24 -0
- package/kb/patterns/docs-api-reference.md +31 -0
- package/kb/patterns/marketing-product-led-landing.md +30 -0
- package/kb/patterns/mobile-daily-checklist.md +26 -0
- package/kb/references/index.json +1 -0
- package/kb/references/thumbs/004c5e9072.jpg +0 -0
- package/kb/references/thumbs/008915eb21.jpg +0 -0
- package/kb/references/thumbs/0098cf66c2.jpg +0 -0
- package/kb/references/thumbs/012e61b31f.jpg +0 -0
- package/kb/references/thumbs/014d4e46fc.jpg +0 -0
- package/kb/references/thumbs/01e54f394a.jpg +0 -0
- package/kb/references/thumbs/01e99a579c.jpg +0 -0
- package/kb/references/thumbs/01fd014575.jpg +0 -0
- package/kb/references/thumbs/022778ca72.jpg +0 -0
- package/kb/references/thumbs/02717bf1e1.jpg +0 -0
- package/kb/references/thumbs/02a5cfdbe9.jpg +0 -0
- package/kb/references/thumbs/02c9823f8d.jpg +0 -0
- package/kb/references/thumbs/02f3974613.jpg +0 -0
- package/kb/references/thumbs/032427f1ce.jpg +0 -0
- package/kb/references/thumbs/03ba677d07.jpg +0 -0
- package/kb/references/thumbs/04f2476cfe.jpg +0 -0
- package/kb/references/thumbs/0563e7c52e.jpg +0 -0
- package/kb/references/thumbs/05fa6b8eef.jpg +0 -0
- package/kb/references/thumbs/065bce1517.jpg +0 -0
- package/kb/references/thumbs/06c017f113.jpg +0 -0
- package/kb/references/thumbs/0770e2d8d3.jpg +0 -0
- package/kb/references/thumbs/078a26c4cb.jpg +0 -0
- package/kb/references/thumbs/08679b6e84.jpg +0 -0
- package/kb/references/thumbs/088c45a34c.jpg +0 -0
- package/kb/references/thumbs/089e9fd4e4.jpg +0 -0
- package/kb/references/thumbs/08f773231e.jpg +0 -0
- package/kb/references/thumbs/093ca3e2e3.jpg +0 -0
- package/kb/references/thumbs/0963320f74.jpg +0 -0
- package/kb/references/thumbs/09fc1ded85.jpg +0 -0
- package/kb/references/thumbs/0a368f3963.jpg +0 -0
- package/kb/references/thumbs/0a9e0e5201.jpg +0 -0
- package/kb/references/thumbs/0aace67ee7.jpg +0 -0
- package/kb/references/thumbs/0b61ecf793.jpg +0 -0
- package/kb/references/thumbs/0bde18ae09.jpg +0 -0
- package/kb/references/thumbs/0bf7ee8143.jpg +0 -0
- package/kb/references/thumbs/0ca20a13e0.jpg +0 -0
- package/kb/references/thumbs/0cdc0198c4.jpg +0 -0
- package/kb/references/thumbs/0cf9790b28.jpg +0 -0
- package/kb/references/thumbs/0d0202904b.jpg +0 -0
- package/kb/references/thumbs/0d053aba18.jpg +0 -0
- package/kb/references/thumbs/0d0c2c13d2.jpg +0 -0
- package/kb/references/thumbs/0d30be99b0.jpg +0 -0
- package/kb/references/thumbs/0d503da1b7.jpg +0 -0
- package/kb/references/thumbs/0ddad7b740.jpg +0 -0
- package/kb/references/thumbs/0e0a148101.jpg +0 -0
- package/kb/references/thumbs/0e401b6b75.jpg +0 -0
- package/kb/references/thumbs/0e8f32ba0f.jpg +0 -0
- package/kb/references/thumbs/0ef1966a7d.jpg +0 -0
- package/kb/references/thumbs/0efd416d11.jpg +0 -0
- package/kb/references/thumbs/0f3af263ae.jpg +0 -0
- package/kb/references/thumbs/0f9644c3a5.jpg +0 -0
- package/kb/references/thumbs/1020552737.jpg +0 -0
- package/kb/references/thumbs/1037626587.jpg +0 -0
- package/kb/references/thumbs/10512b7e94.jpg +0 -0
- package/kb/references/thumbs/106dc4a7b5.jpg +0 -0
- package/kb/references/thumbs/108943f6f7.jpg +0 -0
- package/kb/references/thumbs/10a5551d51.jpg +0 -0
- package/kb/references/thumbs/10dd01076c.jpg +0 -0
- package/kb/references/thumbs/11b06e39da.jpg +0 -0
- package/kb/references/thumbs/11baa1ec83.jpg +0 -0
- package/kb/references/thumbs/11bbe12167.jpg +0 -0
- package/kb/references/thumbs/11ca37feb8.jpg +0 -0
- package/kb/references/thumbs/11f14d3f12.jpg +0 -0
- package/kb/references/thumbs/124530ceb5.jpg +0 -0
- package/kb/references/thumbs/1276402336.jpg +0 -0
- package/kb/references/thumbs/1280e5c9d6.jpg +0 -0
- package/kb/references/thumbs/12cac0d172.jpg +0 -0
- package/kb/references/thumbs/138be6623a.jpg +0 -0
- package/kb/references/thumbs/13a0c544d1.jpg +0 -0
- package/kb/references/thumbs/13a32cb94c.jpg +0 -0
- package/kb/references/thumbs/144035d641.jpg +0 -0
- package/kb/references/thumbs/1457e41924.jpg +0 -0
- package/kb/references/thumbs/14972e3a86.jpg +0 -0
- package/kb/references/thumbs/15a47f2e4c.jpg +0 -0
- package/kb/references/thumbs/15aa15d22e.jpg +0 -0
- package/kb/references/thumbs/160dcd24b7.jpg +0 -0
- package/kb/references/thumbs/1610978529.jpg +0 -0
- package/kb/references/thumbs/16db30ba37.jpg +0 -0
- package/kb/references/thumbs/16f19ae4f3.jpg +0 -0
- package/kb/references/thumbs/16f758b03f.jpg +0 -0
- package/kb/references/thumbs/1748e5b751.jpg +0 -0
- package/kb/references/thumbs/175d0b0e69.jpg +0 -0
- package/kb/references/thumbs/178f571a36.jpg +0 -0
- package/kb/references/thumbs/17c43dc025.jpg +0 -0
- package/kb/references/thumbs/17c7f05b50.jpg +0 -0
- package/kb/references/thumbs/17f97e61dd.jpg +0 -0
- package/kb/references/thumbs/1804e17365.jpg +0 -0
- package/kb/references/thumbs/195c162ed1.jpg +0 -0
- package/kb/references/thumbs/19e3699c29.jpg +0 -0
- package/kb/references/thumbs/1a48e0a4d5.jpg +0 -0
- package/kb/references/thumbs/1a6cda265e.jpg +0 -0
- package/kb/references/thumbs/1a7e012091.jpg +0 -0
- package/kb/references/thumbs/1a9173a172.jpg +0 -0
- package/kb/references/thumbs/1b34a6b4d2.jpg +0 -0
- package/kb/references/thumbs/1b5284f3b2.jpg +0 -0
- package/kb/references/thumbs/1b93fbd6d3.jpg +0 -0
- package/kb/references/thumbs/1c6728fef6.jpg +0 -0
- package/kb/references/thumbs/1c6f101618.jpg +0 -0
- package/kb/references/thumbs/1cf7011a94.jpg +0 -0
- package/kb/references/thumbs/1d1769e539.jpg +0 -0
- package/kb/references/thumbs/1d1fd23199.jpg +0 -0
- package/kb/references/thumbs/1d7b6602ac.jpg +0 -0
- package/kb/references/thumbs/1dbbc61b9e.jpg +0 -0
- package/kb/references/thumbs/1dbdd6d21d.jpg +0 -0
- package/kb/references/thumbs/1dd873744b.jpg +0 -0
- package/kb/references/thumbs/1df4dd7cf9.jpg +0 -0
- package/kb/references/thumbs/1ece8c35b8.jpg +0 -0
- package/kb/references/thumbs/1f0e5b9aa4.jpg +0 -0
- package/kb/references/thumbs/1f1419651b.jpg +0 -0
- package/kb/references/thumbs/1f2a6da92d.jpg +0 -0
- package/kb/references/thumbs/1f651f33c0.jpg +0 -0
- package/kb/references/thumbs/1f8b697d18.jpg +0 -0
- package/kb/references/thumbs/1fee3824cd.jpg +0 -0
- package/kb/references/thumbs/1ff7757853.jpg +0 -0
- package/kb/references/thumbs/2043182f01.jpg +0 -0
- package/kb/references/thumbs/2059dabcd5.jpg +0 -0
- package/kb/references/thumbs/209d9dbb95.jpg +0 -0
- package/kb/references/thumbs/20d8923554.jpg +0 -0
- package/kb/references/thumbs/210dd3b671.jpg +0 -0
- package/kb/references/thumbs/2120719116.jpg +0 -0
- package/kb/references/thumbs/21a7384429.jpg +0 -0
- package/kb/references/thumbs/225f187391.jpg +0 -0
- package/kb/references/thumbs/230caf7dd2.jpg +0 -0
- package/kb/references/thumbs/235afad355.jpg +0 -0
- package/kb/references/thumbs/2378066687.jpg +0 -0
- package/kb/references/thumbs/241faf68a1.jpg +0 -0
- package/kb/references/thumbs/24d9f1a9b9.jpg +0 -0
- package/kb/references/thumbs/2505c8b9a0.jpg +0 -0
- package/kb/references/thumbs/25593638ca.jpg +0 -0
- package/kb/references/thumbs/25dd454f18.jpg +0 -0
- package/kb/references/thumbs/2602e123e2.jpg +0 -0
- package/kb/references/thumbs/26095c0b11.jpg +0 -0
- package/kb/references/thumbs/26260d6238.jpg +0 -0
- package/kb/references/thumbs/26bba21836.jpg +0 -0
- package/kb/references/thumbs/26bde3520b.jpg +0 -0
- package/kb/references/thumbs/272e22067c.jpg +0 -0
- package/kb/references/thumbs/27421b3226.jpg +0 -0
- package/kb/references/thumbs/2769ebca41.jpg +0 -0
- package/kb/references/thumbs/27e2f6e8b0.jpg +0 -0
- package/kb/references/thumbs/28432ba373.jpg +0 -0
- package/kb/references/thumbs/2846626f19.jpg +0 -0
- package/kb/references/thumbs/28750e821e.jpg +0 -0
- package/kb/references/thumbs/289481230f.jpg +0 -0
- package/kb/references/thumbs/2897967408.jpg +0 -0
- package/kb/references/thumbs/28c0a5fa17.jpg +0 -0
- package/kb/references/thumbs/28c181fba5.jpg +0 -0
- package/kb/references/thumbs/29806f539f.jpg +0 -0
- package/kb/references/thumbs/2997f56ee7.jpg +0 -0
- package/kb/references/thumbs/29b34a10fb.jpg +0 -0
- package/kb/references/thumbs/29bd78cdb4.jpg +0 -0
- package/kb/references/thumbs/29c8c6c22a.jpg +0 -0
- package/kb/references/thumbs/2ac23f7fae.jpg +0 -0
- package/kb/references/thumbs/2b76e13f79.jpg +0 -0
- package/kb/references/thumbs/2b84226479.jpg +0 -0
- package/kb/references/thumbs/2bf2dbf737.jpg +0 -0
- package/kb/references/thumbs/2bf89abbf6.jpg +0 -0
- package/kb/references/thumbs/2c562cd534.jpg +0 -0
- package/kb/references/thumbs/2cfe9d48c4.jpg +0 -0
- package/kb/references/thumbs/2d49f19b27.jpg +0 -0
- package/kb/references/thumbs/2dc8670da7.jpg +0 -0
- package/kb/references/thumbs/2de947c469.jpg +0 -0
- package/kb/references/thumbs/2e075ca79f.jpg +0 -0
- package/kb/references/thumbs/2eb0820e6b.jpg +0 -0
- package/kb/references/thumbs/2ec56a9dc0.jpg +0 -0
- package/kb/references/thumbs/30bb4ad607.jpg +0 -0
- package/kb/references/thumbs/30d19b8444.jpg +0 -0
- package/kb/references/thumbs/3173c71d73.jpg +0 -0
- package/kb/references/thumbs/31e59e4518.jpg +0 -0
- package/kb/references/thumbs/322b8960e8.jpg +0 -0
- package/kb/references/thumbs/325c9be6f4.jpg +0 -0
- package/kb/references/thumbs/3273338982.jpg +0 -0
- package/kb/references/thumbs/32f8387f38.jpg +0 -0
- package/kb/references/thumbs/332f6b74c3.jpg +0 -0
- package/kb/references/thumbs/334b146b6a.jpg +0 -0
- package/kb/references/thumbs/339abd60e4.jpg +0 -0
- package/kb/references/thumbs/33e88ec295.jpg +0 -0
- package/kb/references/thumbs/340931b5d4.jpg +0 -0
- package/kb/references/thumbs/34165a93bd.jpg +0 -0
- package/kb/references/thumbs/34d0575dd7.jpg +0 -0
- package/kb/references/thumbs/3549e75f0a.jpg +0 -0
- package/kb/references/thumbs/35827f1561.jpg +0 -0
- package/kb/references/thumbs/37c50280ec.jpg +0 -0
- package/kb/references/thumbs/37e66ecf11.jpg +0 -0
- package/kb/references/thumbs/3841a04fdc.jpg +0 -0
- package/kb/references/thumbs/38490c088f.jpg +0 -0
- package/kb/references/thumbs/3850319e9f.jpg +0 -0
- package/kb/references/thumbs/3856a64166.jpg +0 -0
- package/kb/references/thumbs/3881f211c2.jpg +0 -0
- package/kb/references/thumbs/38c7dde2f3.jpg +0 -0
- package/kb/references/thumbs/38ce9e486c.jpg +0 -0
- package/kb/references/thumbs/390ea8e01b.jpg +0 -0
- package/kb/references/thumbs/391b7fc27c.jpg +0 -0
- package/kb/references/thumbs/395f7214dc.jpg +0 -0
- package/kb/references/thumbs/39e81a5db2.jpg +0 -0
- package/kb/references/thumbs/3a67c8d655.jpg +0 -0
- package/kb/references/thumbs/3a89c25e3b.jpg +0 -0
- package/kb/references/thumbs/3aa0837542.jpg +0 -0
- package/kb/references/thumbs/3aae18aa8a.jpg +0 -0
- package/kb/references/thumbs/3bdbe767db.jpg +0 -0
- package/kb/references/thumbs/3c0616fc7f.jpg +0 -0
- package/kb/references/thumbs/3c18e9db1d.jpg +0 -0
- package/kb/references/thumbs/3c5a14076c.jpg +0 -0
- package/kb/references/thumbs/3ca9ec15c6.jpg +0 -0
- package/kb/references/thumbs/3d7756fd35.jpg +0 -0
- package/kb/references/thumbs/3dd45bd33d.jpg +0 -0
- package/kb/references/thumbs/3de72d5414.jpg +0 -0
- package/kb/references/thumbs/3dede597af.jpg +0 -0
- package/kb/references/thumbs/3ea948619e.jpg +0 -0
- package/kb/references/thumbs/402c12054c.jpg +0 -0
- package/kb/references/thumbs/403ab4af90.jpg +0 -0
- package/kb/references/thumbs/40773a8c63.jpg +0 -0
- package/kb/references/thumbs/407d9583db.jpg +0 -0
- package/kb/references/thumbs/415dc1d84c.jpg +0 -0
- package/kb/references/thumbs/420b676a4f.jpg +0 -0
- package/kb/references/thumbs/42a1ee85eb.jpg +0 -0
- package/kb/references/thumbs/43059221aa.jpg +0 -0
- package/kb/references/thumbs/432fa0d22c.jpg +0 -0
- package/kb/references/thumbs/43826f20e3.jpg +0 -0
- package/kb/references/thumbs/43ac55c98a.jpg +0 -0
- package/kb/references/thumbs/43d098f3c3.jpg +0 -0
- package/kb/references/thumbs/4449d80c2c.jpg +0 -0
- package/kb/references/thumbs/44625727dc.jpg +0 -0
- package/kb/references/thumbs/4482bb87a1.jpg +0 -0
- package/kb/references/thumbs/44b078acdc.jpg +0 -0
- package/kb/references/thumbs/44d0305850.jpg +0 -0
- package/kb/references/thumbs/456bb6b59e.jpg +0 -0
- package/kb/references/thumbs/45df73ce48.jpg +0 -0
- package/kb/references/thumbs/45edb45d87.jpg +0 -0
- package/kb/references/thumbs/4671d57cd5.jpg +0 -0
- package/kb/references/thumbs/46cc108518.jpg +0 -0
- package/kb/references/thumbs/470022e614.jpg +0 -0
- package/kb/references/thumbs/4719a669ce.jpg +0 -0
- package/kb/references/thumbs/47404f5ad4.jpg +0 -0
- package/kb/references/thumbs/479d3eb977.jpg +0 -0
- package/kb/references/thumbs/479ed92ceb.jpg +0 -0
- package/kb/references/thumbs/47baed50c7.jpg +0 -0
- package/kb/references/thumbs/47fdcfd7b0.jpg +0 -0
- package/kb/references/thumbs/48fd5e94c5.jpg +0 -0
- package/kb/references/thumbs/493807917b.jpg +0 -0
- package/kb/references/thumbs/49a1c67293.jpg +0 -0
- package/kb/references/thumbs/49e2d7fafe.jpg +0 -0
- package/kb/references/thumbs/49f540fcb6.jpg +0 -0
- package/kb/references/thumbs/4a67ec4028.jpg +0 -0
- package/kb/references/thumbs/4a93275b04.jpg +0 -0
- package/kb/references/thumbs/4aae6f52da.jpg +0 -0
- package/kb/references/thumbs/4b1bae66bd.jpg +0 -0
- package/kb/references/thumbs/4b75da15a9.jpg +0 -0
- package/kb/references/thumbs/4b77789b88.jpg +0 -0
- package/kb/references/thumbs/4bc2f3f3a4.jpg +0 -0
- package/kb/references/thumbs/4c48f27b88.jpg +0 -0
- package/kb/references/thumbs/4c52bd8bfb.jpg +0 -0
- package/kb/references/thumbs/4c9b4acc60.jpg +0 -0
- package/kb/references/thumbs/4cbf0752d4.jpg +0 -0
- package/kb/references/thumbs/4cd2672517.jpg +0 -0
- package/kb/references/thumbs/4dd22a8181.jpg +0 -0
- package/kb/references/thumbs/4ee3447314.jpg +0 -0
- package/kb/references/thumbs/4ef29c8144.jpg +0 -0
- package/kb/references/thumbs/4f82fadfd6.jpg +0 -0
- package/kb/references/thumbs/4fc9b643d8.jpg +0 -0
- package/kb/references/thumbs/50549524b0.jpg +0 -0
- package/kb/references/thumbs/509a615883.jpg +0 -0
- package/kb/references/thumbs/50c03ef855.jpg +0 -0
- package/kb/references/thumbs/50cf9acad6.jpg +0 -0
- package/kb/references/thumbs/51131b025c.jpg +0 -0
- package/kb/references/thumbs/51da1124f0.jpg +0 -0
- package/kb/references/thumbs/524d5e7288.jpg +0 -0
- package/kb/references/thumbs/5251247c81.jpg +0 -0
- package/kb/references/thumbs/526b91b7ec.jpg +0 -0
- package/kb/references/thumbs/52f02f6c2e.jpg +0 -0
- package/kb/references/thumbs/530ab530dc.jpg +0 -0
- package/kb/references/thumbs/5335ee4404.jpg +0 -0
- package/kb/references/thumbs/5385b90939.jpg +0 -0
- package/kb/references/thumbs/53c54654cc.jpg +0 -0
- package/kb/references/thumbs/5420794c6c.jpg +0 -0
- package/kb/references/thumbs/542a9dce8b.jpg +0 -0
- package/kb/references/thumbs/5571530a5f.jpg +0 -0
- package/kb/references/thumbs/56cc68d804.jpg +0 -0
- package/kb/references/thumbs/577b7f7c44.jpg +0 -0
- package/kb/references/thumbs/57adf8f1bb.jpg +0 -0
- package/kb/references/thumbs/57c5f5e3a6.jpg +0 -0
- package/kb/references/thumbs/57ffe4e839.jpg +0 -0
- package/kb/references/thumbs/5817dfc7d6.jpg +0 -0
- package/kb/references/thumbs/581a182a7a.jpg +0 -0
- package/kb/references/thumbs/58807679c8.jpg +0 -0
- package/kb/references/thumbs/589a1d9111.jpg +0 -0
- package/kb/references/thumbs/59167391ab.jpg +0 -0
- package/kb/references/thumbs/5a70420166.jpg +0 -0
- package/kb/references/thumbs/5b10df1b8d.jpg +0 -0
- package/kb/references/thumbs/5b7a712fdb.jpg +0 -0
- package/kb/references/thumbs/5bc46b92ad.jpg +0 -0
- package/kb/references/thumbs/5c0546a120.jpg +0 -0
- package/kb/references/thumbs/5c2b6125a8.jpg +0 -0
- package/kb/references/thumbs/5c536b9e42.jpg +0 -0
- package/kb/references/thumbs/5c8e441d30.jpg +0 -0
- package/kb/references/thumbs/5cb6f1baa5.jpg +0 -0
- package/kb/references/thumbs/5ce6c1f21e.jpg +0 -0
- package/kb/references/thumbs/5cef052c0a.jpg +0 -0
- package/kb/references/thumbs/5d08438209.jpg +0 -0
- package/kb/references/thumbs/5d0f9af9b0.jpg +0 -0
- package/kb/references/thumbs/5d300ed332.jpg +0 -0
- package/kb/references/thumbs/5d708a4794.jpg +0 -0
- package/kb/references/thumbs/5de8826a98.jpg +0 -0
- package/kb/references/thumbs/5df7bff22c.jpg +0 -0
- package/kb/references/thumbs/5e087d0f00.jpg +0 -0
- package/kb/references/thumbs/5e44e70ca0.jpg +0 -0
- package/kb/references/thumbs/5eff5d80ce.jpg +0 -0
- package/kb/references/thumbs/5f015c96b1.jpg +0 -0
- package/kb/references/thumbs/5f3289b7c4.jpg +0 -0
- package/kb/references/thumbs/5f830c40eb.jpg +0 -0
- package/kb/references/thumbs/60c4c3527b.jpg +0 -0
- package/kb/references/thumbs/60e9e594dd.jpg +0 -0
- package/kb/references/thumbs/615421d7be.jpg +0 -0
- package/kb/references/thumbs/6176e4004f.jpg +0 -0
- package/kb/references/thumbs/61f0fe5e06.jpg +0 -0
- package/kb/references/thumbs/6213785db4.jpg +0 -0
- package/kb/references/thumbs/62a670ae09.jpg +0 -0
- package/kb/references/thumbs/63cc12981b.jpg +0 -0
- package/kb/references/thumbs/641f15cc71.jpg +0 -0
- package/kb/references/thumbs/642ab2081d.jpg +0 -0
- package/kb/references/thumbs/644a59bf6e.jpg +0 -0
- package/kb/references/thumbs/644da8a8e3.jpg +0 -0
- package/kb/references/thumbs/6458986897.jpg +0 -0
- package/kb/references/thumbs/64cfbd7b93.jpg +0 -0
- package/kb/references/thumbs/661a57686a.jpg +0 -0
- package/kb/references/thumbs/66355a813a.jpg +0 -0
- package/kb/references/thumbs/664396dd44.jpg +0 -0
- package/kb/references/thumbs/66d832d65f.jpg +0 -0
- package/kb/references/thumbs/66de9e9833.jpg +0 -0
- package/kb/references/thumbs/6750964fd9.jpg +0 -0
- package/kb/references/thumbs/67c7164832.jpg +0 -0
- package/kb/references/thumbs/681600b6cd.jpg +0 -0
- package/kb/references/thumbs/682e75afe4.jpg +0 -0
- package/kb/references/thumbs/69274bc952.jpg +0 -0
- package/kb/references/thumbs/696ec08c52.jpg +0 -0
- package/kb/references/thumbs/69760111cc.jpg +0 -0
- package/kb/references/thumbs/697e32664f.jpg +0 -0
- package/kb/references/thumbs/69df92544b.jpg +0 -0
- package/kb/references/thumbs/69e48c5229.jpg +0 -0
- package/kb/references/thumbs/6a5fb75de1.jpg +0 -0
- package/kb/references/thumbs/6a7389e472.jpg +0 -0
- package/kb/references/thumbs/6a9b041e02.jpg +0 -0
- package/kb/references/thumbs/6ab2fa93ee.jpg +0 -0
- package/kb/references/thumbs/6ae3400319.jpg +0 -0
- package/kb/references/thumbs/6b21344bf3.jpg +0 -0
- package/kb/references/thumbs/6bd1b67a8a.jpg +0 -0
- package/kb/references/thumbs/6c99156c4f.jpg +0 -0
- package/kb/references/thumbs/6cc9b65384.jpg +0 -0
- package/kb/references/thumbs/6d15830a73.jpg +0 -0
- package/kb/references/thumbs/6d4c33d180.jpg +0 -0
- package/kb/references/thumbs/6e36815799.jpg +0 -0
- package/kb/references/thumbs/6eddb9cbfc.jpg +0 -0
- package/kb/references/thumbs/6f97968a7c.jpg +0 -0
- package/kb/references/thumbs/6fa0716a7d.jpg +0 -0
- package/kb/references/thumbs/6facd57184.jpg +0 -0
- package/kb/references/thumbs/6fd57b785a.jpg +0 -0
- package/kb/references/thumbs/700b3cb185.jpg +0 -0
- package/kb/references/thumbs/71197443fa.jpg +0 -0
- package/kb/references/thumbs/72082bc9ee.jpg +0 -0
- package/kb/references/thumbs/72453db479.jpg +0 -0
- package/kb/references/thumbs/72cd64d500.jpg +0 -0
- package/kb/references/thumbs/72d1e75283.jpg +0 -0
- package/kb/references/thumbs/72e13f7f5b.jpg +0 -0
- package/kb/references/thumbs/7459f8e644.jpg +0 -0
- package/kb/references/thumbs/7470d55c79.jpg +0 -0
- package/kb/references/thumbs/74c468f02a.jpg +0 -0
- package/kb/references/thumbs/74fed6eb77.jpg +0 -0
- package/kb/references/thumbs/756e05080d.jpg +0 -0
- package/kb/references/thumbs/75df7e5f49.jpg +0 -0
- package/kb/references/thumbs/76226da6ef.jpg +0 -0
- package/kb/references/thumbs/76a34aa056.jpg +0 -0
- package/kb/references/thumbs/76c7076589.jpg +0 -0
- package/kb/references/thumbs/76cccc396c.jpg +0 -0
- package/kb/references/thumbs/774654789f.jpg +0 -0
- package/kb/references/thumbs/7746cc494d.jpg +0 -0
- package/kb/references/thumbs/7766e36aa3.jpg +0 -0
- package/kb/references/thumbs/78049331ef.jpg +0 -0
- package/kb/references/thumbs/78808a0ca5.jpg +0 -0
- package/kb/references/thumbs/7890b0a310.jpg +0 -0
- package/kb/references/thumbs/78911975e6.jpg +0 -0
- package/kb/references/thumbs/78d289d5a0.jpg +0 -0
- package/kb/references/thumbs/794126267e.jpg +0 -0
- package/kb/references/thumbs/7976eb9025.jpg +0 -0
- package/kb/references/thumbs/798519ec7c.jpg +0 -0
- package/kb/references/thumbs/7a6cc5eecc.jpg +0 -0
- package/kb/references/thumbs/7ac8a7cd4a.jpg +0 -0
- package/kb/references/thumbs/7b1341d61d.jpg +0 -0
- package/kb/references/thumbs/7b9c4031e3.jpg +0 -0
- package/kb/references/thumbs/7ba5ad3779.jpg +0 -0
- package/kb/references/thumbs/7be6eb2bd0.jpg +0 -0
- package/kb/references/thumbs/7c30864f5d.jpg +0 -0
- package/kb/references/thumbs/7c379b5e17.jpg +0 -0
- package/kb/references/thumbs/7c4050eb02.jpg +0 -0
- package/kb/references/thumbs/7ca47b3221.jpg +0 -0
- package/kb/references/thumbs/7d43516bd7.jpg +0 -0
- package/kb/references/thumbs/7da9dbb98a.jpg +0 -0
- package/kb/references/thumbs/7ddda8f57c.jpg +0 -0
- package/kb/references/thumbs/7ece6d215c.jpg +0 -0
- package/kb/references/thumbs/7eebf029de.jpg +0 -0
- package/kb/references/thumbs/7f45483c15.jpg +0 -0
- package/kb/references/thumbs/7fde06eaa5.jpg +0 -0
- package/kb/references/thumbs/80407b97e9.jpg +0 -0
- package/kb/references/thumbs/80f0a6cf4b.jpg +0 -0
- package/kb/references/thumbs/8118b451b8.jpg +0 -0
- package/kb/references/thumbs/816baed4a8.jpg +0 -0
- package/kb/references/thumbs/817d2d15d9.jpg +0 -0
- package/kb/references/thumbs/8260cb430d.jpg +0 -0
- package/kb/references/thumbs/827b562899.jpg +0 -0
- package/kb/references/thumbs/8293cf1e92.jpg +0 -0
- package/kb/references/thumbs/8294653169.jpg +0 -0
- package/kb/references/thumbs/83061f871f.jpg +0 -0
- package/kb/references/thumbs/833df778ca.jpg +0 -0
- package/kb/references/thumbs/83d3acaafc.jpg +0 -0
- package/kb/references/thumbs/844c6efeff.jpg +0 -0
- package/kb/references/thumbs/84563d482a.jpg +0 -0
- package/kb/references/thumbs/848082dd94.jpg +0 -0
- package/kb/references/thumbs/8494b1da94.jpg +0 -0
- package/kb/references/thumbs/84b71014be.jpg +0 -0
- package/kb/references/thumbs/84be4a5f3c.jpg +0 -0
- package/kb/references/thumbs/84fd0fd25a.jpg +0 -0
- package/kb/references/thumbs/853e488e22.jpg +0 -0
- package/kb/references/thumbs/858c91585d.jpg +0 -0
- package/kb/references/thumbs/85903e8fe9.jpg +0 -0
- package/kb/references/thumbs/86597d43fd.jpg +0 -0
- package/kb/references/thumbs/866eb99500.jpg +0 -0
- package/kb/references/thumbs/86ac050340.jpg +0 -0
- package/kb/references/thumbs/86afec7b64.jpg +0 -0
- package/kb/references/thumbs/87238127f5.jpg +0 -0
- package/kb/references/thumbs/87321df792.jpg +0 -0
- package/kb/references/thumbs/87460f70cd.jpg +0 -0
- package/kb/references/thumbs/8770dfeaec.jpg +0 -0
- package/kb/references/thumbs/8798451a8c.jpg +0 -0
- package/kb/references/thumbs/87da1f34a3.jpg +0 -0
- package/kb/references/thumbs/882cdf8c05.jpg +0 -0
- package/kb/references/thumbs/8839f4106f.jpg +0 -0
- package/kb/references/thumbs/8844455212.jpg +0 -0
- package/kb/references/thumbs/88abba0497.jpg +0 -0
- package/kb/references/thumbs/88b372435d.jpg +0 -0
- package/kb/references/thumbs/88bd4f35fa.jpg +0 -0
- package/kb/references/thumbs/88c71a075e.jpg +0 -0
- package/kb/references/thumbs/892e5f048e.jpg +0 -0
- package/kb/references/thumbs/893cc8e920.jpg +0 -0
- package/kb/references/thumbs/896c198814.jpg +0 -0
- package/kb/references/thumbs/8a8e22f756.jpg +0 -0
- package/kb/references/thumbs/8a9d8a35cb.jpg +0 -0
- package/kb/references/thumbs/8ab1d67fec.jpg +0 -0
- package/kb/references/thumbs/8ab201fe12.jpg +0 -0
- package/kb/references/thumbs/8ac372c102.jpg +0 -0
- package/kb/references/thumbs/8b15736d62.jpg +0 -0
- package/kb/references/thumbs/8b1d8d6a05.jpg +0 -0
- package/kb/references/thumbs/8bb6050e20.jpg +0 -0
- package/kb/references/thumbs/8c6c9d1577.jpg +0 -0
- package/kb/references/thumbs/8d337851e0.jpg +0 -0
- package/kb/references/thumbs/8d44b33cc5.jpg +0 -0
- package/kb/references/thumbs/8d4536ff3b.jpg +0 -0
- package/kb/references/thumbs/8d9b99454a.jpg +0 -0
- package/kb/references/thumbs/8dda2303ff.jpg +0 -0
- package/kb/references/thumbs/8dec722d62.jpg +0 -0
- package/kb/references/thumbs/8e0ea4ca74.jpg +0 -0
- package/kb/references/thumbs/8ebba84d69.jpg +0 -0
- package/kb/references/thumbs/8ef09140c0.jpg +0 -0
- package/kb/references/thumbs/8f2928a1b0.jpg +0 -0
- package/kb/references/thumbs/8f88f9ddba.jpg +0 -0
- package/kb/references/thumbs/8fa4451009.jpg +0 -0
- package/kb/references/thumbs/90109b0e02.jpg +0 -0
- package/kb/references/thumbs/90e854e5c9.jpg +0 -0
- package/kb/references/thumbs/914e79f893.jpg +0 -0
- package/kb/references/thumbs/9161369197.jpg +0 -0
- package/kb/references/thumbs/9165c87d6f.jpg +0 -0
- package/kb/references/thumbs/9193f6558a.jpg +0 -0
- package/kb/references/thumbs/91ac7df877.jpg +0 -0
- package/kb/references/thumbs/9216bd4931.jpg +0 -0
- package/kb/references/thumbs/922ae8a26a.jpg +0 -0
- package/kb/references/thumbs/92a70e6867.jpg +0 -0
- package/kb/references/thumbs/92c77ece22.jpg +0 -0
- package/kb/references/thumbs/92e5914fbf.jpg +0 -0
- package/kb/references/thumbs/92ee36419a.jpg +0 -0
- package/kb/references/thumbs/94153a60b0.jpg +0 -0
- package/kb/references/thumbs/9449666640.jpg +0 -0
- package/kb/references/thumbs/944be6a646.jpg +0 -0
- package/kb/references/thumbs/945831476e.jpg +0 -0
- package/kb/references/thumbs/94c1af82f4.jpg +0 -0
- package/kb/references/thumbs/9599d6d589.jpg +0 -0
- package/kb/references/thumbs/960710f4cf.jpg +0 -0
- package/kb/references/thumbs/9608f12d64.jpg +0 -0
- package/kb/references/thumbs/962dabfaa0.jpg +0 -0
- package/kb/references/thumbs/965a3a95c6.jpg +0 -0
- package/kb/references/thumbs/9672ed5ae4.jpg +0 -0
- package/kb/references/thumbs/96891ae9c1.jpg +0 -0
- package/kb/references/thumbs/96e1907c99.jpg +0 -0
- package/kb/references/thumbs/96f25b6578.jpg +0 -0
- package/kb/references/thumbs/97211df9ae.jpg +0 -0
- package/kb/references/thumbs/9769d763a5.jpg +0 -0
- package/kb/references/thumbs/9792bd6d05.jpg +0 -0
- package/kb/references/thumbs/97d2837e3e.jpg +0 -0
- package/kb/references/thumbs/97d90d1d85.jpg +0 -0
- package/kb/references/thumbs/97fcd5774a.jpg +0 -0
- package/kb/references/thumbs/980f68564e.jpg +0 -0
- package/kb/references/thumbs/98511fb393.jpg +0 -0
- package/kb/references/thumbs/98f8fa694d.jpg +0 -0
- package/kb/references/thumbs/9a42c6bb97.jpg +0 -0
- package/kb/references/thumbs/9ab3600a06.jpg +0 -0
- package/kb/references/thumbs/9ab48d9130.jpg +0 -0
- package/kb/references/thumbs/9ad519197d.jpg +0 -0
- package/kb/references/thumbs/9b1382c657.jpg +0 -0
- package/kb/references/thumbs/9b6cc1e077.jpg +0 -0
- package/kb/references/thumbs/9beede8480.jpg +0 -0
- package/kb/references/thumbs/9bf8976952.jpg +0 -0
- package/kb/references/thumbs/9cace7b75a.jpg +0 -0
- package/kb/references/thumbs/9cdcc5745e.jpg +0 -0
- package/kb/references/thumbs/9d0b269074.jpg +0 -0
- package/kb/references/thumbs/9d41788b48.jpg +0 -0
- package/kb/references/thumbs/9d475bd6af.jpg +0 -0
- package/kb/references/thumbs/9e6bc543d0.jpg +0 -0
- package/kb/references/thumbs/9ed0e0a206.jpg +0 -0
- package/kb/references/thumbs/9ef538de13.jpg +0 -0
- package/kb/references/thumbs/9efc373ab4.jpg +0 -0
- package/kb/references/thumbs/9f4a939fa5.jpg +0 -0
- package/kb/references/thumbs/9f8d12d7b9.jpg +0 -0
- package/kb/references/thumbs/9fd5e3efa7.jpg +0 -0
- package/kb/references/thumbs/a0a9b9c572.jpg +0 -0
- package/kb/references/thumbs/a29ca9b185.jpg +0 -0
- package/kb/references/thumbs/a2a42884af.jpg +0 -0
- package/kb/references/thumbs/a2f5064e34.jpg +0 -0
- package/kb/references/thumbs/a3112ce672.jpg +0 -0
- package/kb/references/thumbs/a3437736d1.jpg +0 -0
- package/kb/references/thumbs/a372667e76.jpg +0 -0
- package/kb/references/thumbs/a39bae94e9.jpg +0 -0
- package/kb/references/thumbs/a3fc75d94c.jpg +0 -0
- package/kb/references/thumbs/a440487631.jpg +0 -0
- package/kb/references/thumbs/a4993d5fb5.jpg +0 -0
- package/kb/references/thumbs/a500476a86.jpg +0 -0
- package/kb/references/thumbs/a55506bf46.jpg +0 -0
- package/kb/references/thumbs/a59a5f9843.jpg +0 -0
- package/kb/references/thumbs/a5bce0eede.jpg +0 -0
- package/kb/references/thumbs/a5d921e1f0.jpg +0 -0
- package/kb/references/thumbs/a5e19d4637.jpg +0 -0
- package/kb/references/thumbs/a5f92b97d5.jpg +0 -0
- package/kb/references/thumbs/a6562c210a.jpg +0 -0
- package/kb/references/thumbs/a6f61a8d09.jpg +0 -0
- package/kb/references/thumbs/a719fdf663.jpg +0 -0
- package/kb/references/thumbs/a724e5442f.jpg +0 -0
- package/kb/references/thumbs/a852b4319f.jpg +0 -0
- package/kb/references/thumbs/a896c08448.jpg +0 -0
- package/kb/references/thumbs/a8d190a4b8.jpg +0 -0
- package/kb/references/thumbs/a8dcdd57d7.jpg +0 -0
- package/kb/references/thumbs/a951347e18.jpg +0 -0
- package/kb/references/thumbs/a9a1a0bf7d.jpg +0 -0
- package/kb/references/thumbs/a9b72986a8.jpg +0 -0
- package/kb/references/thumbs/aa11555ba8.jpg +0 -0
- package/kb/references/thumbs/aa4aab9093.jpg +0 -0
- package/kb/references/thumbs/aa89b96658.jpg +0 -0
- package/kb/references/thumbs/aaeb3739b6.jpg +0 -0
- package/kb/references/thumbs/ab25a608ec.jpg +0 -0
- package/kb/references/thumbs/ab34b62268.jpg +0 -0
- package/kb/references/thumbs/ab3b0217bb.jpg +0 -0
- package/kb/references/thumbs/ac70c04afb.jpg +0 -0
- package/kb/references/thumbs/ace0879117.jpg +0 -0
- package/kb/references/thumbs/ad0515ae55.jpg +0 -0
- package/kb/references/thumbs/ad66b25b47.jpg +0 -0
- package/kb/references/thumbs/ad68229d2f.jpg +0 -0
- package/kb/references/thumbs/add6480693.jpg +0 -0
- package/kb/references/thumbs/ae5b8c3b8c.jpg +0 -0
- package/kb/references/thumbs/ae81247b47.jpg +0 -0
- package/kb/references/thumbs/af8aa54379.jpg +0 -0
- package/kb/references/thumbs/afa80dedd4.jpg +0 -0
- package/kb/references/thumbs/afe04d730f.jpg +0 -0
- package/kb/references/thumbs/b09a7dc315.jpg +0 -0
- package/kb/references/thumbs/b0c02629f6.jpg +0 -0
- package/kb/references/thumbs/b1cb4f91de.jpg +0 -0
- package/kb/references/thumbs/b1d4c13c92.jpg +0 -0
- package/kb/references/thumbs/b20eef86db.jpg +0 -0
- package/kb/references/thumbs/b3136ccdde.jpg +0 -0
- package/kb/references/thumbs/b3f5e8d7dd.jpg +0 -0
- package/kb/references/thumbs/b44adb81c9.jpg +0 -0
- package/kb/references/thumbs/b457a5894b.jpg +0 -0
- package/kb/references/thumbs/b461281e0f.jpg +0 -0
- package/kb/references/thumbs/b4942644f0.jpg +0 -0
- package/kb/references/thumbs/b49f8eccad.jpg +0 -0
- package/kb/references/thumbs/b56c69be23.jpg +0 -0
- package/kb/references/thumbs/b59786b33c.jpg +0 -0
- package/kb/references/thumbs/b5d368ce5a.jpg +0 -0
- package/kb/references/thumbs/b5eb442406.jpg +0 -0
- package/kb/references/thumbs/b7fdabf4ab.jpg +0 -0
- package/kb/references/thumbs/b88ee8d235.jpg +0 -0
- package/kb/references/thumbs/b8a4e5be8a.jpg +0 -0
- package/kb/references/thumbs/b8c85b661c.jpg +0 -0
- package/kb/references/thumbs/ba1b8e7435.jpg +0 -0
- package/kb/references/thumbs/ba9a593eed.jpg +0 -0
- package/kb/references/thumbs/baa7afc201.jpg +0 -0
- package/kb/references/thumbs/baf74398f7.jpg +0 -0
- package/kb/references/thumbs/bb3e947c10.jpg +0 -0
- package/kb/references/thumbs/bb4c1bb7c1.jpg +0 -0
- package/kb/references/thumbs/bbaa25cc8a.jpg +0 -0
- package/kb/references/thumbs/bc7e7f88cc.jpg +0 -0
- package/kb/references/thumbs/bc9d5b58f5.jpg +0 -0
- package/kb/references/thumbs/bcc99a51f7.jpg +0 -0
- package/kb/references/thumbs/bce13dd1c1.jpg +0 -0
- package/kb/references/thumbs/bd079a6130.jpg +0 -0
- package/kb/references/thumbs/bd2d70dda7.jpg +0 -0
- package/kb/references/thumbs/bd5895c5f2.jpg +0 -0
- package/kb/references/thumbs/bde8e31d62.jpg +0 -0
- package/kb/references/thumbs/be084e78f3.jpg +0 -0
- package/kb/references/thumbs/be94f170c8.jpg +0 -0
- package/kb/references/thumbs/bed33654f7.jpg +0 -0
- package/kb/references/thumbs/beeb9a0c18.jpg +0 -0
- package/kb/references/thumbs/bef42094dc.jpg +0 -0
- package/kb/references/thumbs/bf625496fa.jpg +0 -0
- package/kb/references/thumbs/bf771f1398.jpg +0 -0
- package/kb/references/thumbs/c0ddefa3d9.jpg +0 -0
- package/kb/references/thumbs/c0f01e536e.jpg +0 -0
- package/kb/references/thumbs/c1d592b678.jpg +0 -0
- package/kb/references/thumbs/c1e83e1b3e.jpg +0 -0
- package/kb/references/thumbs/c2168f8096.jpg +0 -0
- package/kb/references/thumbs/c249cd6b17.jpg +0 -0
- package/kb/references/thumbs/c2e3d4feed.jpg +0 -0
- package/kb/references/thumbs/c3cec01df1.jpg +0 -0
- package/kb/references/thumbs/c47bedb42d.jpg +0 -0
- package/kb/references/thumbs/c4b03b4680.jpg +0 -0
- package/kb/references/thumbs/c4e6d18ec3.jpg +0 -0
- package/kb/references/thumbs/c5477e2877.jpg +0 -0
- package/kb/references/thumbs/c566794674.jpg +0 -0
- package/kb/references/thumbs/c5b945afbb.jpg +0 -0
- package/kb/references/thumbs/c5e4659497.jpg +0 -0
- package/kb/references/thumbs/c622786702.jpg +0 -0
- package/kb/references/thumbs/c6250649ca.jpg +0 -0
- package/kb/references/thumbs/c6261a9526.jpg +0 -0
- package/kb/references/thumbs/c62e609076.jpg +0 -0
- package/kb/references/thumbs/c6602d3e85.jpg +0 -0
- package/kb/references/thumbs/c6c1a16e40.jpg +0 -0
- package/kb/references/thumbs/c77f932157.jpg +0 -0
- package/kb/references/thumbs/c79788f01e.jpg +0 -0
- package/kb/references/thumbs/c7a511ad1e.jpg +0 -0
- package/kb/references/thumbs/c7acfbc3c8.jpg +0 -0
- package/kb/references/thumbs/c7bb6d1bb8.jpg +0 -0
- package/kb/references/thumbs/c829eadcb9.jpg +0 -0
- package/kb/references/thumbs/c891fd9d85.jpg +0 -0
- package/kb/references/thumbs/c89f812ee3.jpg +0 -0
- package/kb/references/thumbs/c8a85b9f61.jpg +0 -0
- package/kb/references/thumbs/c8fdf85c9a.jpg +0 -0
- package/kb/references/thumbs/c961ac1031.jpg +0 -0
- package/kb/references/thumbs/c9fd3f88d8.jpg +0 -0
- package/kb/references/thumbs/ca0d6399c3.jpg +0 -0
- package/kb/references/thumbs/ca316c83e4.jpg +0 -0
- package/kb/references/thumbs/ca3b93aa0d.jpg +0 -0
- package/kb/references/thumbs/cb0596a85b.jpg +0 -0
- package/kb/references/thumbs/cb95a5c3ef.jpg +0 -0
- package/kb/references/thumbs/cbe238b656.jpg +0 -0
- package/kb/references/thumbs/cbf530e608.jpg +0 -0
- package/kb/references/thumbs/cc173494ec.jpg +0 -0
- package/kb/references/thumbs/ccb664bddf.jpg +0 -0
- package/kb/references/thumbs/ccf69d36cd.jpg +0 -0
- package/kb/references/thumbs/ccf759db42.jpg +0 -0
- package/kb/references/thumbs/cd2a285807.jpg +0 -0
- package/kb/references/thumbs/cd4a24a8ca.jpg +0 -0
- package/kb/references/thumbs/cdb3fe8938.jpg +0 -0
- package/kb/references/thumbs/cdce1b9bc6.jpg +0 -0
- package/kb/references/thumbs/cde3aa761a.jpg +0 -0
- package/kb/references/thumbs/ce9d5cd9c2.jpg +0 -0
- package/kb/references/thumbs/ceb01f8a34.jpg +0 -0
- package/kb/references/thumbs/cee15c98d0.jpg +0 -0
- package/kb/references/thumbs/cf6944ddae.jpg +0 -0
- package/kb/references/thumbs/d15dd21cd8.jpg +0 -0
- package/kb/references/thumbs/d1633bf2ed.jpg +0 -0
- package/kb/references/thumbs/d16a838000.jpg +0 -0
- package/kb/references/thumbs/d1cf87e9f0.jpg +0 -0
- package/kb/references/thumbs/d32511d913.jpg +0 -0
- package/kb/references/thumbs/d327e9dedd.jpg +0 -0
- package/kb/references/thumbs/d35bf6c85e.jpg +0 -0
- package/kb/references/thumbs/d37afc9d61.jpg +0 -0
- package/kb/references/thumbs/d3b66655c7.jpg +0 -0
- package/kb/references/thumbs/d40b4172b6.jpg +0 -0
- package/kb/references/thumbs/d4c40d1824.jpg +0 -0
- package/kb/references/thumbs/d4cb55a4b6.jpg +0 -0
- package/kb/references/thumbs/d4f0c30f7e.jpg +0 -0
- package/kb/references/thumbs/d51cce3ae5.jpg +0 -0
- package/kb/references/thumbs/d52948f9ba.jpg +0 -0
- package/kb/references/thumbs/d62bd3cba4.jpg +0 -0
- package/kb/references/thumbs/d668a21c92.jpg +0 -0
- package/kb/references/thumbs/d685072c52.jpg +0 -0
- package/kb/references/thumbs/d6d7b96093.jpg +0 -0
- package/kb/references/thumbs/d7cd874b21.jpg +0 -0
- package/kb/references/thumbs/d7e111736a.jpg +0 -0
- package/kb/references/thumbs/d88325f832.jpg +0 -0
- package/kb/references/thumbs/d9272ded76.jpg +0 -0
- package/kb/references/thumbs/d962e7c654.jpg +0 -0
- package/kb/references/thumbs/d97f000ee2.jpg +0 -0
- package/kb/references/thumbs/d9c1ae2543.jpg +0 -0
- package/kb/references/thumbs/d9ccb3cac8.jpg +0 -0
- package/kb/references/thumbs/da99019680.jpg +0 -0
- package/kb/references/thumbs/da9b8bc615.jpg +0 -0
- package/kb/references/thumbs/daafbee2c1.jpg +0 -0
- package/kb/references/thumbs/db0f11f143.jpg +0 -0
- package/kb/references/thumbs/db5dd367f5.jpg +0 -0
- package/kb/references/thumbs/db69677866.jpg +0 -0
- package/kb/references/thumbs/db87c1956e.jpg +0 -0
- package/kb/references/thumbs/dbb86d8bda.jpg +0 -0
- package/kb/references/thumbs/dbd3a8ff2a.jpg +0 -0
- package/kb/references/thumbs/dbdf4b2794.jpg +0 -0
- package/kb/references/thumbs/dd4c19b4b1.jpg +0 -0
- package/kb/references/thumbs/dd98d9f6fa.jpg +0 -0
- package/kb/references/thumbs/ddb00e3b6a.jpg +0 -0
- package/kb/references/thumbs/dde3541a5c.jpg +0 -0
- package/kb/references/thumbs/de2a4da502.jpg +0 -0
- package/kb/references/thumbs/de4c387a66.jpg +0 -0
- package/kb/references/thumbs/de5618fa82.jpg +0 -0
- package/kb/references/thumbs/de6bec2538.jpg +0 -0
- package/kb/references/thumbs/dea13cbb1f.jpg +0 -0
- package/kb/references/thumbs/deff9202aa.jpg +0 -0
- package/kb/references/thumbs/df12835f8d.jpg +0 -0
- package/kb/references/thumbs/df57acbb3d.jpg +0 -0
- package/kb/references/thumbs/df8265009e.jpg +0 -0
- package/kb/references/thumbs/dfc99a1e8e.jpg +0 -0
- package/kb/references/thumbs/dfc9fde460.jpg +0 -0
- package/kb/references/thumbs/e038348eee.jpg +0 -0
- package/kb/references/thumbs/e04c2ae1d5.jpg +0 -0
- package/kb/references/thumbs/e070345c43.jpg +0 -0
- package/kb/references/thumbs/e0a0c84d47.jpg +0 -0
- package/kb/references/thumbs/e0af1e6b9e.jpg +0 -0
- package/kb/references/thumbs/e1025942c4.jpg +0 -0
- package/kb/references/thumbs/e11b6f5b82.jpg +0 -0
- package/kb/references/thumbs/e1553de3fc.jpg +0 -0
- package/kb/references/thumbs/e162ebe7cd.jpg +0 -0
- package/kb/references/thumbs/e1f1e531d8.jpg +0 -0
- package/kb/references/thumbs/e20842e5c9.jpg +0 -0
- package/kb/references/thumbs/e24e7d949b.jpg +0 -0
- package/kb/references/thumbs/e2a3e5d10a.jpg +0 -0
- package/kb/references/thumbs/e2de02615a.jpg +0 -0
- package/kb/references/thumbs/e305dad7dd.jpg +0 -0
- package/kb/references/thumbs/e52e3ef97f.jpg +0 -0
- package/kb/references/thumbs/e570e92d06.jpg +0 -0
- package/kb/references/thumbs/e583932fb9.jpg +0 -0
- package/kb/references/thumbs/e5da3c038f.jpg +0 -0
- package/kb/references/thumbs/e657634af3.jpg +0 -0
- package/kb/references/thumbs/e67946e3e1.jpg +0 -0
- package/kb/references/thumbs/e69e0f3639.jpg +0 -0
- package/kb/references/thumbs/e6ebe66031.jpg +0 -0
- package/kb/references/thumbs/e7db9563c9.jpg +0 -0
- package/kb/references/thumbs/e84a4c3b7b.jpg +0 -0
- package/kb/references/thumbs/e84cf52c27.jpg +0 -0
- package/kb/references/thumbs/e8707cf6e8.jpg +0 -0
- package/kb/references/thumbs/e888890b40.jpg +0 -0
- package/kb/references/thumbs/e8a502b418.jpg +0 -0
- package/kb/references/thumbs/e8ba68371d.jpg +0 -0
- package/kb/references/thumbs/e9098f54cc.jpg +0 -0
- package/kb/references/thumbs/e9144deae9.jpg +0 -0
- package/kb/references/thumbs/e93e98d757.jpg +0 -0
- package/kb/references/thumbs/e9762dd435.jpg +0 -0
- package/kb/references/thumbs/e9db4544c8.jpg +0 -0
- package/kb/references/thumbs/e9ddffeacd.jpg +0 -0
- package/kb/references/thumbs/e9e2cf1d7e.jpg +0 -0
- package/kb/references/thumbs/ea1e23e623.jpg +0 -0
- package/kb/references/thumbs/ea41200f5e.jpg +0 -0
- package/kb/references/thumbs/eaf4916e1a.jpg +0 -0
- package/kb/references/thumbs/eb2c505fc8.jpg +0 -0
- package/kb/references/thumbs/eb47943693.jpg +0 -0
- package/kb/references/thumbs/eb4ffd6625.jpg +0 -0
- package/kb/references/thumbs/eb82ac0a4d.jpg +0 -0
- package/kb/references/thumbs/ebeb345ade.jpg +0 -0
- package/kb/references/thumbs/ec4e2aba0a.jpg +0 -0
- package/kb/references/thumbs/ed683bc9f7.jpg +0 -0
- package/kb/references/thumbs/ed9e236a84.jpg +0 -0
- package/kb/references/thumbs/ee45e1caea.jpg +0 -0
- package/kb/references/thumbs/ee50bbf2e7.jpg +0 -0
- package/kb/references/thumbs/eed6ad3b7b.jpg +0 -0
- package/kb/references/thumbs/eee247fd70.jpg +0 -0
- package/kb/references/thumbs/ef87b6cb99.jpg +0 -0
- package/kb/references/thumbs/ef87dccf04.jpg +0 -0
- package/kb/references/thumbs/ef941bba1e.jpg +0 -0
- package/kb/references/thumbs/effc14fb2c.jpg +0 -0
- package/kb/references/thumbs/f04aa5a191.jpg +0 -0
- package/kb/references/thumbs/f13f12485f.jpg +0 -0
- package/kb/references/thumbs/f16a5c0fd4.jpg +0 -0
- package/kb/references/thumbs/f1ba7a7a8f.jpg +0 -0
- package/kb/references/thumbs/f1bc4c9c19.jpg +0 -0
- package/kb/references/thumbs/f1ee827878.jpg +0 -0
- package/kb/references/thumbs/f21736aeff.jpg +0 -0
- package/kb/references/thumbs/f22bc41213.jpg +0 -0
- package/kb/references/thumbs/f266aaffcc.jpg +0 -0
- package/kb/references/thumbs/f2c0ed0d65.jpg +0 -0
- package/kb/references/thumbs/f32ac710fd.jpg +0 -0
- package/kb/references/thumbs/f32b697ff6.jpg +0 -0
- package/kb/references/thumbs/f39c883904.jpg +0 -0
- package/kb/references/thumbs/f3b9d55e6e.jpg +0 -0
- package/kb/references/thumbs/f3c1763e14.jpg +0 -0
- package/kb/references/thumbs/f40853fd43.jpg +0 -0
- package/kb/references/thumbs/f4fd07dc4d.jpg +0 -0
- package/kb/references/thumbs/f50b756ee5.jpg +0 -0
- package/kb/references/thumbs/f51272e9b3.jpg +0 -0
- package/kb/references/thumbs/f538895eee.jpg +0 -0
- package/kb/references/thumbs/f5d28081b5.jpg +0 -0
- package/kb/references/thumbs/f6046c9501.jpg +0 -0
- package/kb/references/thumbs/f62e4af316.jpg +0 -0
- package/kb/references/thumbs/f6f6bffeb8.jpg +0 -0
- package/kb/references/thumbs/f736e00af6.jpg +0 -0
- package/kb/references/thumbs/f7932da47d.jpg +0 -0
- package/kb/references/thumbs/f879e118ca.jpg +0 -0
- package/kb/references/thumbs/f88257215d.jpg +0 -0
- package/kb/references/thumbs/f88c45a6d7.jpg +0 -0
- package/kb/references/thumbs/f89a7b646e.jpg +0 -0
- package/kb/references/thumbs/f8a1e7a274.jpg +0 -0
- package/kb/references/thumbs/f9183cf2b6.jpg +0 -0
- package/kb/references/thumbs/f995de5ce9.jpg +0 -0
- package/kb/references/thumbs/f9ada2c3e1.jpg +0 -0
- package/kb/references/thumbs/f9d4616f89.jpg +0 -0
- package/kb/references/thumbs/f9f4307bb0.jpg +0 -0
- package/kb/references/thumbs/fa070122c7.jpg +0 -0
- package/kb/references/thumbs/fa29cc1369.jpg +0 -0
- package/kb/references/thumbs/fa791a4dab.jpg +0 -0
- package/kb/references/thumbs/fa8060509e.jpg +0 -0
- package/kb/references/thumbs/fafeed4003.jpg +0 -0
- package/kb/references/thumbs/fb1c024f38.jpg +0 -0
- package/kb/references/thumbs/fb77aa28b3.jpg +0 -0
- package/kb/references/thumbs/fb9f7f1966.jpg +0 -0
- package/kb/references/thumbs/fba8a8c2da.jpg +0 -0
- package/kb/references/thumbs/fce2754c36.jpg +0 -0
- package/kb/references/thumbs/fce2fb83df.jpg +0 -0
- package/kb/references/thumbs/fd4c51bb47.jpg +0 -0
- package/kb/references/thumbs/fd8c269817.jpg +0 -0
- package/kb/references/thumbs/fdb7b250ca.jpg +0 -0
- package/kb/references/thumbs/fe18088de8.jpg +0 -0
- package/kb/references/thumbs/fe4f742ba7.jpg +0 -0
- package/kb/references/thumbs/fe64742ce7.jpg +0 -0
- package/kb/references/thumbs/feb5d62161.jpg +0 -0
- package/kb/references/thumbs/fed21b3e98.jpg +0 -0
- package/kb/references/thumbs/fed2205951.jpg +0 -0
- package/kb/references/thumbs/ffdacf1715.jpg +0 -0
- package/kb/sections/_buttons.md +93 -0
- package/kb/sections/_finish.md +325 -0
- package/kb/sections/about-founder-note.md +85 -0
- package/kb/sections/about-team-roster.md +86 -0
- package/kb/sections/alternating-rows-live-tiles.md +110 -0
- package/kb/sections/annotated-product-shot.md +105 -0
- package/kb/sections/asymmetric-bento-dominant.md +114 -0
- package/kb/sections/before-after-features.md +104 -0
- package/kb/sections/before-after-repair.md +107 -0
- package/kb/sections/bento-lead-tile.md +112 -0
- package/kb/sections/book-a-slot-honest.md +116 -0
- package/kb/sections/capability-prompt-ledger.md +68 -0
- package/kb/sections/case-study-band.md +113 -0
- package/kb/sections/centred-stack-hero.md +107 -0
- package/kb/sections/closing-demo-final-state.md +81 -0
- package/kb/sections/closing-full-bleed-line-and-form.md +86 -0
- package/kb/sections/closing-result-previewed.md +88 -0
- package/kb/sections/closing-three-real-steps.md +87 -0
- package/kb/sections/command-reference-table.md +70 -0
- package/kb/sections/comparison-old-way-bars.md +88 -0
- package/kb/sections/comparison-same-task-two-ways.md +88 -0
- package/kb/sections/day-of-the-place.md +102 -0
- package/kb/sections/docs-reading-rail.md +88 -0
- package/kb/sections/editorial-columns-hero.md +107 -0
- package/kb/sections/editorial-essay-pull-quote.md +112 -0
- package/kb/sections/events-calendar-list.md +107 -0
- package/kb/sections/explorable-control-demo.md +102 -0
- package/kb/sections/faq-open-answers-editorial.md +85 -0
- package/kb/sections/faq-ruled-accordion-aside.md +87 -0
- package/kb/sections/footer-closing-scene.md +84 -0
- package/kb/sections/footer-editorial-sitemap.md +85 -0
- package/kb/sections/footer-minimal-credits.md +80 -0
- package/kb/sections/full-bleed-image-band.md +103 -0
- package/kb/sections/full-bleed-image-hero.md +105 -0
- package/kb/sections/gallery-first-hero.md +109 -0
- package/kb/sections/horizontal-scroll-strip.md +101 -0
- package/kb/sections/how-i-work-own-voice.md +111 -0
- package/kb/sections/how-it-works-in-place.md +109 -0
- package/kb/sections/impact-numbers-sourced.md +109 -0
- package/kb/sections/install-steps-per-agent.md +77 -0
- package/kb/sections/masonry-real-work.md +109 -0
- package/kb/sections/numbered-editorial-columns.md +105 -0
- package/kb/sections/object-first-hero.md +106 -0
- package/kb/sections/object-timeline.md +105 -0
- package/kb/sections/one-huge-number.md +100 -0
- package/kb/sections/one-person-story.md +103 -0
- package/kb/sections/order-ahead-ticket.md +119 -0
- package/kb/sections/press-strip-quoted.md +106 -0
- package/kb/sections/pricing-comparison-table-sticky.md +94 -0
- package/kb/sections/pricing-free-pro-upgrade-moment.md +85 -0
- package/kb/sections/pricing-plan-beside-product.md +88 -0
- package/kb/sections/pricing-plans-ledger.md +94 -0
- package/kb/sections/pricing-usage-calculator.md +93 -0
- package/kb/sections/printed-menu-card.md +110 -0
- package/kb/sections/process-happening.md +102 -0
- package/kb/sections/project-index-ruled.md +106 -0
- package/kb/sections/proof-logo-cloud-with-reasons.md +82 -0
- package/kb/sections/proof-measured-numbers.md +88 -0
- package/kb/sections/proof-output-wall.md +84 -0
- package/kb/sections/proof-single-honest-quote.md +81 -0
- package/kb/sections/resources-searchable-list.md +110 -0
- package/kb/sections/rooms-and-rates.md +107 -0
- package/kb/sections/ruled-facts-table.md +108 -0
- package/kb/sections/ruled-list-pinned-visual.md +107 -0
- package/kb/sections/scroll-scrubbed-product-demo.md +103 -0
- package/kb/sections/self-playing-run-demo.md +104 -0
- package/kb/sections/services-price-ledger.md +106 -0
- package/kb/sections/signup-form-with-next-steps.md +86 -0
- package/kb/sections/signup-waitlist-place-in-line.md +90 -0
- package/kb/sections/spec-sheet-features.md +108 -0
- package/kb/sections/split-hero-live-object.md +108 -0
- package/kb/sections/sticky-feature-narrative.md +104 -0
- package/kb/sections/todays-board-hero.md +112 -0
- package/kb/sections/touchable-tool-hero.md +111 -0
- package/kb/sections/typographic-statement-hero.md +99 -0
- package/kb/sections/visit-hours-map.md +110 -0
- package/kb/sections/ways-to-help-honest.md +115 -0
- package/kb/sources/design-reference.md +991 -0
- package/kb/sources/product-and-docs.md +37 -0
- package/kb/systems/1win/DESIGN.md +463 -0
- package/kb/systems/LICENSE-awesome-design-md +21 -0
- package/kb/systems/README.md +7 -0
- package/kb/systems/airbnb/DESIGN.md +545 -0
- package/kb/systems/airtable/DESIGN.md +554 -0
- package/kb/systems/aljazeera/DESIGN.md +594 -0
- package/kb/systems/apple/DESIGN.md +562 -0
- package/kb/systems/binance/DESIGN.md +634 -0
- package/kb/systems/bmw/DESIGN.md +544 -0
- package/kb/systems/bmw-m/DESIGN.md +503 -0
- package/kb/systems/bugatti/DESIGN.md +454 -0
- package/kb/systems/cal/DESIGN.md +542 -0
- package/kb/systems/categories.json +87 -0
- package/kb/systems/claude/DESIGN.md +589 -0
- package/kb/systems/clay/DESIGN.md +541 -0
- package/kb/systems/clickhouse/DESIGN.md +544 -0
- package/kb/systems/cohere/DESIGN.md +451 -0
- package/kb/systems/coinbase/DESIGN.md +570 -0
- package/kb/systems/composio/DESIGN.md +506 -0
- package/kb/systems/cursor/DESIGN.md +537 -0
- package/kb/systems/dell-1996/DESIGN.md +632 -0
- package/kb/systems/dji/DESIGN.md +882 -0
- package/kb/systems/elevenlabs/DESIGN.md +504 -0
- package/kb/systems/expo/DESIGN.md +526 -0
- package/kb/systems/ferrari/DESIGN.md +531 -0
- package/kb/systems/figma/DESIGN.md +578 -0
- package/kb/systems/framer/DESIGN.md +544 -0
- package/kb/systems/hashicorp/DESIGN.md +575 -0
- package/kb/systems/hp/DESIGN.md +670 -0
- package/kb/systems/ibm/DESIGN.md +550 -0
- package/kb/systems/intercom/DESIGN.md +546 -0
- package/kb/systems/jobright/DESIGN.md +525 -0
- package/kb/systems/kraken/DESIGN.md +125 -0
- package/kb/systems/lamborghini/DESIGN.md +288 -0
- package/kb/systems/linear.app/DESIGN.md +548 -0
- package/kb/systems/lovable/DESIGN.md +298 -0
- package/kb/systems/mastercard/DESIGN.md +365 -0
- package/kb/systems/mercury/DESIGN.md +568 -0
- package/kb/systems/meta/DESIGN.md +683 -0
- package/kb/systems/minimax/DESIGN.md +746 -0
- package/kb/systems/mintlify/DESIGN.md +852 -0
- package/kb/systems/miro/DESIGN.md +825 -0
- package/kb/systems/mistral.ai/DESIGN.md +773 -0
- package/kb/systems/mongodb/DESIGN.md +767 -0
- package/kb/systems/mydealz/DESIGN.md +551 -0
- package/kb/systems/nerdwallet/DESIGN.md +722 -0
- package/kb/systems/nike/DESIGN.md +575 -0
- package/kb/systems/nintendo-2001/DESIGN.md +649 -0
- package/kb/systems/notion/DESIGN.md +821 -0
- package/kb/systems/nvidia/DESIGN.md +640 -0
- package/kb/systems/ollama/DESIGN.md +539 -0
- package/kb/systems/opencode.ai/DESIGN.md +521 -0
- package/kb/systems/oracle/DESIGN.md +778 -0
- package/kb/systems/oura/DESIGN.md +616 -0
- package/kb/systems/pinterest/DESIGN.md +597 -0
- package/kb/systems/playstation/DESIGN.md +661 -0
- package/kb/systems/posthog/DESIGN.md +690 -0
- package/kb/systems/raycast/DESIGN.md +669 -0
- package/kb/systems/renault/DESIGN.md +589 -0
- package/kb/systems/replicate/DESIGN.md +616 -0
- package/kb/systems/resend/DESIGN.md +585 -0
- package/kb/systems/revolut/DESIGN.md +636 -0
- package/kb/systems/runwayml/DESIGN.md +244 -0
- package/kb/systems/sanity/DESIGN.md +357 -0
- package/kb/systems/sap/DESIGN.md +639 -0
- package/kb/systems/sentry/DESIGN.md +551 -0
- package/kb/systems/shopify/DESIGN.md +516 -0
- package/kb/systems/slack/DESIGN.md +482 -0
- package/kb/systems/spacex/DESIGN.md +363 -0
- package/kb/systems/spotify/DESIGN.md +246 -0
- package/kb/systems/starbucks/DESIGN.md +580 -0
- package/kb/systems/stripe/DESIGN.md +487 -0
- package/kb/systems/supabase/DESIGN.md +462 -0
- package/kb/systems/superhuman/DESIGN.md +448 -0
- package/kb/systems/tesla/DESIGN.md +286 -0
- package/kb/systems/theverge/DESIGN.md +339 -0
- package/kb/systems/together.ai/DESIGN.md +633 -0
- package/kb/systems/uber/DESIGN.md +636 -0
- package/kb/systems/vercel/DESIGN.md +736 -0
- package/kb/systems/vodafone/DESIGN.md +538 -0
- package/kb/systems/voltagent/DESIGN.md +521 -0
- package/kb/systems/warp/DESIGN.md +526 -0
- package/kb/systems/webflow/DESIGN.md +588 -0
- package/kb/systems/wired/DESIGN.md +497 -0
- package/kb/systems/wise/DESIGN.md +544 -0
- package/kb/systems/x.ai/DESIGN.md +465 -0
- package/kb/systems/zapier/DESIGN.md +537 -0
- package/kb/taste/garvit-by-job.md +46 -0
- package/kb/taste/garvit-portfolio.md +94 -0
- package/kb/universal/color-roles.md +26 -0
- package/kb/universal/copy.md +16 -0
- package/kb/universal/details.md +31 -0
- package/kb/universal/first-screen.md +30 -0
- package/kb/universal/fit-the-codebase.md +29 -0
- package/kb/universal/layout-width.md +28 -0
- package/kb/universal/motion-feedback.md +23 -0
- package/kb/universal/signature.md +29 -0
- package/kb/universal/states.md +17 -0
- package/kb/universal/type-app.md +33 -0
- package/kb/universal/type-marketing.md +28 -0
- package/package.json +37 -4
- package/scripts/pack-assets.mjs +58 -0
- package/skill/palate/SKILL.md +261 -0
- package/src/auth-recheck.mjs +4 -0
- package/src/auth.mjs +416 -0
- package/src/capture.mjs +182 -0
- package/src/catalog/classify.mjs +96 -0
- package/src/catalog/curated.mjs +128 -0
- package/src/catalog/index-build.mjs +67 -0
- package/src/catalog/literal.mjs +146 -0
- package/src/catalog/store.mjs +40 -0
- package/src/catalog/vibrant.mjs +126 -0
- package/src/check.mjs +93 -0
- package/src/concept.mjs +157 -0
- package/src/context.mjs +226 -0
- package/src/copy.mjs +188 -0
- package/src/devserver.mjs +135 -0
- package/src/fontgenre.mjs +44 -0
- package/src/guard-agents.mjs +213 -0
- package/src/guard.mjs +377 -0
- package/src/kb.mjs +91 -0
- package/src/look.mjs +312 -0
- package/src/loop/ambition.mjs +620 -0
- package/src/loop/animate.mjs +70 -0
- package/src/loop/artdirection.mjs +264 -0
- package/src/loop/bench.mjs +184 -0
- package/src/loop/benchpick.mjs +155 -0
- package/src/loop/blueprint.mjs +620 -0
- package/src/loop/board.html +180 -0
- package/src/loop/build.mjs +393 -0
- package/src/loop/buttons.mjs +413 -0
- package/src/loop/common.mjs +206 -0
- package/src/loop/cost.mjs +63 -0
- package/src/loop/craft.mjs +152 -0
- package/src/loop/craftchecks.mjs +148 -0
- package/src/loop/critique.mjs +393 -0
- package/src/loop/details.mjs +225 -0
- package/src/loop/direction.html +168 -0
- package/src/loop/direction.mjs +256 -0
- package/src/loop/directions.json +8 -0
- package/src/loop/explore.mjs +219 -0
- package/src/loop/fail.mjs +110 -0
- package/src/loop/fix.mjs +194 -0
- package/src/loop/floor.mjs +677 -0
- package/src/loop/forget.mjs +52 -0
- package/src/loop/gate.mjs +1053 -0
- package/src/loop/grid.html +123 -0
- package/src/loop/growth.mjs +118 -0
- package/src/loop/icons.mjs +109 -0
- package/src/loop/imagery.mjs +1280 -0
- package/src/loop/judge-api.mjs +245 -0
- package/src/loop/judge.mjs +167 -0
- package/src/loop/layouts.mjs +492 -0
- package/src/loop/library.mjs +82 -0
- package/src/loop/lookplan.mjs +182 -0
- package/src/loop/lookvec.mjs +645 -0
- package/src/loop/match.mjs +923 -0
- package/src/loop/matched.mjs +26 -0
- package/src/loop/myrefs.mjs +151 -0
- package/src/loop/pick.mjs +213 -0
- package/src/loop/picker.html +118 -0
- package/src/loop/plan.mjs +289 -0
- package/src/loop/polish.mjs +39 -0
- package/src/loop/research-learn.mjs +41 -0
- package/src/loop/research.mjs +1130 -0
- package/src/loop/rulereview.mjs +146 -0
- package/src/loop/rules-board.html +199 -0
- package/src/loop/rules.mjs +939 -0
- package/src/loop/similar.mjs +276 -0
- package/src/loop/states-source.mjs +258 -0
- package/src/loop/states.mjs +1547 -0
- package/src/loop/stats.mjs +78 -0
- package/src/loop/taste.mjs +81 -0
- package/src/loop/timeline.mjs +149 -0
- package/src/loop/variants.mjs +228 -0
- package/src/loop/vary.mjs +249 -0
- package/src/mcp/server.mjs +1246 -0
- package/src/motion.mjs +207 -0
- package/src/moves.mjs +242 -0
- package/src/novelty.mjs +116 -0
- package/src/page-ambition.js +181 -0
- package/src/page-craft.js +724 -0
- package/src/page-details.js +415 -0
- package/src/page-devices.js +365 -0
- package/src/page-fingerprint.js +281 -0
- package/src/page-gate.js +1307 -0
- package/src/page-look.js +698 -0
- package/src/page-metrics.js +78 -0
- package/src/page-principles.js +1167 -0
- package/src/page-rules.js +308 -0
- package/src/page-sections.js +211 -0
- package/src/page-states.js +703 -0
- package/src/paths.mjs +13 -0
- package/src/png.mjs +107 -0
- package/src/point/auto.mjs +224 -0
- package/src/point/locate.mjs +114 -0
- package/src/point/overlay.js +1516 -0
- package/src/point/server.mjs +1122 -0
- package/src/point/trail.mjs +219 -0
- package/src/pool.mjs +80 -0
- package/src/principles.mjs +279 -0
- package/src/refs.mjs +299 -0
- package/src/robots.mjs +145 -0
- package/src/sections.mjs +210 -0
- package/src/shoot.mjs +235 -0
- package/src/systems/apply.mjs +355 -0
- package/src/systems/load.mjs +251 -0
- package/src/systems/pick.mjs +213 -0
- package/templates/vite-react-tw/index.html +12 -0
- package/templates/vite-react-tw/package.json +25 -0
- package/templates/vite-react-tw/src/App.tsx +3 -0
- package/templates/vite-react-tw/src/index.css +1 -0
- package/templates/vite-react-tw/src/main.tsx +10 -0
- package/templates/vite-react-tw/tsconfig.app.json +26 -0
- package/templates/vite-react-tw/tsconfig.json +7 -0
- package/templates/vite-react-tw/tsconfig.node.json +23 -0
- package/templates/vite-react-tw/vite.config.ts +8 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// Runs inside the page (read as text and evaluated with the sections from page-sections.js). The whole-page
|
|
2
|
+
// facts a designer notices across sections: devices repeated in every section (kicker labels, numbers,
|
|
3
|
+
// framed screenshots, backdrops, rules), how the product is shown (static pictures or live UI), logo rows
|
|
4
|
+
// and how visible they are, and what moves.
|
|
5
|
+
(sections) => {
|
|
6
|
+
const vw = innerWidth;
|
|
7
|
+
const clean = (s) => (s ?? "").replace(/\s+/g, " ").trim();
|
|
8
|
+
const abs = (el) => {
|
|
9
|
+
const r = el.getBoundingClientRect();
|
|
10
|
+
return { x: r.left + scrollX, y: r.top + scrollY, w: r.width, h: r.height };
|
|
11
|
+
};
|
|
12
|
+
const visible = (el) => {
|
|
13
|
+
const r = el.getBoundingClientRect();
|
|
14
|
+
const cs = getComputedStyle(el);
|
|
15
|
+
return r.width > 1 && r.height > 1 && cs.display !== "none" && cs.visibility !== "hidden" && parseFloat(cs.opacity) > 0.01;
|
|
16
|
+
};
|
|
17
|
+
const sectionOf = (el) => {
|
|
18
|
+
const b = abs(el);
|
|
19
|
+
const s = sections.find((s) => b.y + b.h / 2 >= s.box.y && b.y + b.h / 2 <= s.box.y + s.box.height);
|
|
20
|
+
return s ? s.index : null;
|
|
21
|
+
};
|
|
22
|
+
const sel = (el) => {
|
|
23
|
+
const parts = [];
|
|
24
|
+
for (let e = el; e && e.nodeType === 1 && e !== document.body && parts.length < 4; e = e.parentElement) {
|
|
25
|
+
if (e.id) {
|
|
26
|
+
parts.unshift(`#${CSS.escape(e.id)}`);
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
parts.unshift(e.tagName.toLowerCase());
|
|
30
|
+
}
|
|
31
|
+
return parts.join(" > ");
|
|
32
|
+
};
|
|
33
|
+
// ---- colour: any computed CSS colour (rgb, hex, hsl, oklab, oklch, lab, lch, color(), color-mix(), which
|
|
34
|
+
// computes to oklab() or color(srgb …)) as [r, g, b, a(0–1)] in sRGB, or null when it can't be read. Never
|
|
35
|
+
// pull digits out of the string: "oklab(0.62 0.1 0.05)" read as rgb is near black. The same helper is in
|
|
36
|
+
// page-rules.js, page-devices.js, page-details.js and page-gate.js (test/colour.test.mjs keeps them identical).
|
|
37
|
+
const colourCtx = Object.assign(document.createElement("canvas"), { width: 1, height: 1 }).getContext("2d", { willReadFrequently: true });
|
|
38
|
+
const colourMemo = new Map();
|
|
39
|
+
const RGB_FN = /^rgba?\(\s*(-?[\d.]+)(%?)[,\s]+(-?[\d.]+)(%?)[,\s]+(-?[\d.]+)(%?)(?:\s*[,/]\s*([\d.]+)(%?))?\s*\)$/i;
|
|
40
|
+
const fromRgbFn = (m) => [1, 3, 5].map((i) => Math.max(0, Math.min(255, m[i + 1] ? (parseFloat(m[i]) * 255) / 100 : parseFloat(m[i])))).concat(m[7] === undefined ? 1 : m[8] ? parseFloat(m[7]) / 100 : parseFloat(m[7]));
|
|
41
|
+
const fromHex = (h) => {
|
|
42
|
+
const x = h.length <= 5 ? [...h.slice(1)].map((c) => c + c).join("") : h.slice(1);
|
|
43
|
+
return [0, 2, 4].map((i) => parseInt(x.slice(i, i + 2), 16)).concat(x.length === 8 ? parseInt(x.slice(6, 8), 16) / 255 : 1);
|
|
44
|
+
};
|
|
45
|
+
// The spaces Chrome computes to, converted by hand for when a canvas can't parse them.
|
|
46
|
+
const fromSpace = (c) => {
|
|
47
|
+
const m = c.match(/^(oklab|oklch|lab|lch|color)\(\s*([^)]*)\)$/i);
|
|
48
|
+
if (!m) return null;
|
|
49
|
+
const [body, alpha] = m[2].split("/");
|
|
50
|
+
const p = body.trim().split(/[\s,]+/);
|
|
51
|
+
const space = m[1].toLowerCase() === "color" ? (p.shift() ?? "").toLowerCase() : m[1].toLowerCase();
|
|
52
|
+
const n = (s, full = 1) => (s == null || s === "none" ? 0 : s.endsWith("%") ? (parseFloat(s) / 100) * full : parseFloat(s));
|
|
53
|
+
const a = alpha === undefined ? 1 : n(alpha.trim());
|
|
54
|
+
const enc = (v) => 255 * Math.max(0, Math.min(1, v <= 0.0031308 ? 12.92 * v : 1.055 * Math.pow(v, 1 / 2.4) - 0.055));
|
|
55
|
+
const polar = (C, h) => [C * Math.cos((h * Math.PI) / 180), C * Math.sin((h * Math.PI) / 180)];
|
|
56
|
+
let lin;
|
|
57
|
+
if (space === "oklab" || space === "oklch") {
|
|
58
|
+
const L = n(p[0]);
|
|
59
|
+
const [A, B] = space === "oklab" ? [n(p[1], 0.4), n(p[2], 0.4)] : polar(n(p[1], 0.4), n(p[2]));
|
|
60
|
+
const l = (L + 0.3963377774 * A + 0.2158037573 * B) ** 3, k = (L - 0.1055613458 * A - 0.0638541728 * B) ** 3, s = (L - 0.0894841775 * A - 1.291485548 * B) ** 3;
|
|
61
|
+
lin = [4.0767416621 * l - 3.3077115913 * k + 0.2309699292 * s, -1.2684380046 * l + 2.6097574011 * k - 0.3413193965 * s, -0.0041960863 * l - 0.7034186147 * k + 1.707614701 * s];
|
|
62
|
+
} else if (space === "lab" || space === "lch") {
|
|
63
|
+
const L = n(p[0], 100);
|
|
64
|
+
const [A, B] = space === "lab" ? [n(p[1], 125), n(p[2], 125)] : polar(n(p[1], 150), n(p[2]));
|
|
65
|
+
const fy = (L + 16) / 116, fx = fy + A / 500, fz = fy - B / 200, e = 216 / 24389, kk = 24389 / 27;
|
|
66
|
+
const X = 0.96422 * (fx ** 3 > e ? fx ** 3 : (116 * fx - 16) / kk), Y = L > kk * e ? fy ** 3 : L / kk, Z = 0.82521 * (fz ** 3 > e ? fz ** 3 : (116 * fz - 16) / kk);
|
|
67
|
+
lin = [3.1338561 * X - 1.6168667 * Y - 0.4906146 * Z, -0.9787684 * X + 1.9161415 * Y + 0.033454 * Z, 0.0719453 * X - 0.2289914 * Y + 1.4052427 * Z];
|
|
68
|
+
} else if (space === "srgb" || space === "display-p3" || space === "a98-rgb" || space === "rec2020") return p.slice(0, 3).map((v) => 255 * Math.max(0, Math.min(1, n(v)))).concat(a);
|
|
69
|
+
else if (space === "srgb-linear") lin = p.slice(0, 3).map((v) => n(v));
|
|
70
|
+
else return null;
|
|
71
|
+
return lin.map(enc).concat(a);
|
|
72
|
+
};
|
|
73
|
+
const toRgba = (c) => {
|
|
74
|
+
const s = String(c ?? "").trim();
|
|
75
|
+
if (!s || s === "none") return null;
|
|
76
|
+
if (colourMemo.has(s)) return colourMemo.get(s);
|
|
77
|
+
let v = null;
|
|
78
|
+
const m = s.match(RGB_FN);
|
|
79
|
+
if (m) v = fromRgbFn(m);
|
|
80
|
+
else if (/^transparent$/i.test(s)) v = [0, 0, 0, 0];
|
|
81
|
+
else if (/^#([0-9a-f]{3,4}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(s)) v = fromHex(s);
|
|
82
|
+
else {
|
|
83
|
+
// The canvas parses anything the browser does; a value it rejects leaves the sentinel in place.
|
|
84
|
+
colourCtx.fillStyle = "#010203";
|
|
85
|
+
colourCtx.fillStyle = s;
|
|
86
|
+
const got = String(colourCtx.fillStyle);
|
|
87
|
+
if (got !== "#010203") {
|
|
88
|
+
const g = got.match(RGB_FN);
|
|
89
|
+
if (g) v = fromRgbFn(g);
|
|
90
|
+
else if (/^#[0-9a-f]{6}$/i.test(got)) v = fromHex(got);
|
|
91
|
+
else {
|
|
92
|
+
colourCtx.clearRect(0, 0, 1, 1);
|
|
93
|
+
colourCtx.fillRect(0, 0, 1, 1);
|
|
94
|
+
const d = colourCtx.getImageData(0, 0, 1, 1).data;
|
|
95
|
+
// Alpha from the colour itself when it says (the canvas rounds translucent channels).
|
|
96
|
+
v = [d[0], d[1], d[2], fromSpace(got)?.[3] ?? d[3] / 255];
|
|
97
|
+
}
|
|
98
|
+
} else v = fromSpace(s);
|
|
99
|
+
}
|
|
100
|
+
colourMemo.set(s, v);
|
|
101
|
+
return v;
|
|
102
|
+
};
|
|
103
|
+
// Every colour named in a background-image (gradient stops), in order.
|
|
104
|
+
const colourStops = (bi) => (String(bi ?? "").match(/(?:rgba?|hsla?|oklab|oklch|lab|lch|color)\([^()]*\)|#[0-9a-f]{3,8}\b/gi) ?? []).map(toRgba).filter(Boolean);
|
|
105
|
+
const rgb = (c) => toRgba(c) ?? [];
|
|
106
|
+
const lum = ([r, g, b]) => {
|
|
107
|
+
const f = (v) => ((v /= 255) <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4);
|
|
108
|
+
return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
|
|
109
|
+
};
|
|
110
|
+
const contrast = (a, b) => {
|
|
111
|
+
const [x, y] = [lum(a), lum(b)].sort((p, q) => q - p);
|
|
112
|
+
return Math.round(((x + 0.05) / (y + 0.05)) * 10) / 10;
|
|
113
|
+
};
|
|
114
|
+
const bgOf = (el) => {
|
|
115
|
+
for (let e = el; e; e = e.parentElement) {
|
|
116
|
+
const c = rgb(getComputedStyle(e).backgroundColor);
|
|
117
|
+
if (c.length >= 3 && (c[3] ?? 1) > 0.5) return c.slice(0, 3);
|
|
118
|
+
}
|
|
119
|
+
return [255, 255, 255];
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
// Product UI shown on the page (a code-built app window, a demo, a figure): its small mono labels ("POST
|
|
123
|
+
// /checkout", a column count over "Shelf") are the product's own type, not the page's kicker labels. Marked
|
|
124
|
+
// ([data-product], a figure, role=img, an aria-hidden or inert miniature), or a framed object (its own ground,
|
|
125
|
+
// shadow or border all round) holding many small UI texts.
|
|
126
|
+
const surfaced = (e) => {
|
|
127
|
+
const cs = getComputedStyle(e);
|
|
128
|
+
const own = rgb(cs.backgroundColor);
|
|
129
|
+
const under = e.parentElement ? bgOf(e.parentElement) : [255, 255, 255];
|
|
130
|
+
const filled = own.length >= 3 && (own[3] ?? 1) > 0.5 && Math.hypot(own[0] - under[0], own[1] - under[1], own[2] - under[2]) > 6;
|
|
131
|
+
const sides = ["Top", "Right", "Bottom", "Left"].filter((s) => parseFloat(cs[`border${s}Width`]) > 0 && cs[`border${s}Style`] !== "none" && (rgb(cs[`border${s}Color`])[3] ?? 1) > 0.1).length;
|
|
132
|
+
return filled || (cs.boxShadow && cs.boxShadow !== "none") || sides >= 3;
|
|
133
|
+
};
|
|
134
|
+
const smallTexts = (e) => {
|
|
135
|
+
let n = 0;
|
|
136
|
+
for (const k of e.querySelectorAll("span, div, p, li, td, th, small, code, button, a, dt, dd, time")) {
|
|
137
|
+
if (n >= 8) break;
|
|
138
|
+
if (k.children.length || !clean(k.textContent) || parseFloat(getComputedStyle(k).fontSize) > 14.5) continue;
|
|
139
|
+
n++;
|
|
140
|
+
}
|
|
141
|
+
return n;
|
|
142
|
+
};
|
|
143
|
+
const productMemo = new Map();
|
|
144
|
+
const productOf = (el) => {
|
|
145
|
+
if (productMemo.has(el)) return productMemo.get(el);
|
|
146
|
+
let found = null;
|
|
147
|
+
for (let e = el.parentElement; e && e !== document.body && !found; e = e.parentElement) {
|
|
148
|
+
if (e.matches("section, main, [data-section]")) break;
|
|
149
|
+
const r = e.getBoundingClientRect();
|
|
150
|
+
if (e.matches("[data-product], figure, [role=img]") || (e.matches("[aria-hidden=true], [inert]") && r.width >= 120 && r.height >= 80)) found = e;
|
|
151
|
+
else if (r.width >= 240 && r.height >= 120 && surfaced(e) && smallTexts(e) >= 8) found = e;
|
|
152
|
+
}
|
|
153
|
+
productMemo.set(el, found);
|
|
154
|
+
return found;
|
|
155
|
+
};
|
|
156
|
+
// Kicker labels: small, uppercase / mono / tracked or numbered text sitting directly above a section's heading
|
|
157
|
+
// (an h1 or h2, or the first heading of its section), outside product UI.
|
|
158
|
+
const sectionHeads = new Set(
|
|
159
|
+
sections.map((s) => {
|
|
160
|
+
let root = null;
|
|
161
|
+
try {
|
|
162
|
+
root = document.querySelector(s.selector);
|
|
163
|
+
} catch {}
|
|
164
|
+
const hs = root ? [...root.querySelectorAll("h1, h2, h3")].filter((h) => visible(h) && !productOf(h)) : [];
|
|
165
|
+
return hs[0] ?? null;
|
|
166
|
+
}),
|
|
167
|
+
);
|
|
168
|
+
const headings = [...document.querySelectorAll("h1, h2, h3")].filter((h) => visible(h) && (h.tagName !== "H3" || sectionHeads.has(h)) && !productOf(h));
|
|
169
|
+
const kickers = [];
|
|
170
|
+
for (const el of document.body.querySelectorAll("p, span, div, small, strong, em, li")) {
|
|
171
|
+
const t = clean(el.textContent);
|
|
172
|
+
if (!t || t.length > 48 || el.querySelector("p, div, h1, h2, h3, li, ul, img, svg") || !visible(el)) continue;
|
|
173
|
+
if (el.parentElement && kickers.some((k) => k.el.contains(el) || el.contains(k.el))) continue;
|
|
174
|
+
const cs = getComputedStyle(el);
|
|
175
|
+
const size = parseFloat(cs.fontSize);
|
|
176
|
+
const styled = cs.textTransform === "uppercase" || /mono/i.test(cs.fontFamily) || parseFloat(cs.letterSpacing) / size > 0.04 || /^\d{1,2}(\s*[·.\-—|]|$)/.test(t);
|
|
177
|
+
if (size > 13.5 || !styled || productOf(el)) continue;
|
|
178
|
+
const b = abs(el);
|
|
179
|
+
const h = headings.find((h) => {
|
|
180
|
+
const hb = abs(h);
|
|
181
|
+
// Directly above: the next thing down, within a short gap, and over the heading (not off to one side). Or a
|
|
182
|
+
// section number on the heading's first line, just left of it ("01 Features").
|
|
183
|
+
const above = hb.y >= b.y + b.h - 4 && hb.y - (b.y + b.h) < 72 && Math.min(hb.x + hb.w, b.x + b.w) - Math.max(hb.x, b.x) > Math.min(b.w, hb.w) * 0.25;
|
|
184
|
+
const beside = b.y + b.h / 2 >= hb.y && b.y + b.h / 2 <= hb.y + Math.min(hb.h, 80) && b.x + b.w <= hb.x + 4 && hb.x - (b.x + b.w) < 120;
|
|
185
|
+
return above || beside;
|
|
186
|
+
});
|
|
187
|
+
if (h) kickers.push({ el, text: t, section: sectionOf(el), before: clean(h.textContent).slice(0, 50) });
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// How the product is shown: big static pictures vs live UI (video, canvas, iframes, real DOM).
|
|
191
|
+
const media = [];
|
|
192
|
+
for (const el of document.body.querySelectorAll("img, picture > img, video, canvas, iframe, svg")) {
|
|
193
|
+
if (!visible(el)) continue;
|
|
194
|
+
const r = el.getBoundingClientRect();
|
|
195
|
+
if (r.width < Math.min(400, vw * 0.35) || r.height < 160) continue;
|
|
196
|
+
let framed = false;
|
|
197
|
+
const frames = [];
|
|
198
|
+
for (let e = el.parentElement, k = 0; e && k < 4; e = e.parentElement, k++) {
|
|
199
|
+
const cs = getComputedStyle(e);
|
|
200
|
+
if (parseFloat(cs.borderTopLeftRadius) > 4 && (cs.backgroundImage.includes("gradient") || cs.boxShadow !== "none" || parseFloat(cs.paddingTop) >= 8 || cs.borderTopStyle !== "none")) (framed = true), frames.push(e);
|
|
201
|
+
}
|
|
202
|
+
const tag = el.tagName.toLowerCase();
|
|
203
|
+
// A decorative image laid behind content (empty alt, absolutely filling its frame, with content on top) is a
|
|
204
|
+
// backdrop, such as a painting under the hero or behind a feature: not the product shown as a picture.
|
|
205
|
+
const backdrop =
|
|
206
|
+
tag === "img" && el.getAttribute("alt") === "" && getComputedStyle(el).position === "absolute" && el.parentElement && [...el.parentElement.children].some((c) => c !== el && visible(c) && c.getBoundingClientRect().height > 40);
|
|
207
|
+
const src = el.getAttribute("src") ?? "";
|
|
208
|
+
const alt = clean(el.getAttribute("alt"));
|
|
209
|
+
let kind = backdrop ? "backdrop image" : tag === "img" ? "static picture" : tag === "svg" ? "svg illustration" : `live ${tag}`;
|
|
210
|
+
let screenshot = false;
|
|
211
|
+
if (kind === "static picture") {
|
|
212
|
+
// A photo or a painting (palate's own CC0 imagery, a credited picture, a JPEG, art) is material, not the
|
|
213
|
+
// product shown as a screenshot. A screenshot says so (src or alt), or is a PNG/WebP in UI proportions in a
|
|
214
|
+
// frame with browser-chrome dots.
|
|
215
|
+
const file = (el.currentSrc || src).toLowerCase();
|
|
216
|
+
const holder = el.closest("figure") ?? frames[frames.length - 1] ?? el.parentElement;
|
|
217
|
+
const credit = clean(`${el.closest("figure")?.querySelector("figcaption")?.textContent ?? ""} ${holder && holder.getBoundingClientRect().height < r.height + 160 ? holder.textContent : ""} ${el.getAttribute("title") ?? ""}`);
|
|
218
|
+
const uiWords = /screen ?shot|dashboard|\bapp\b|\bui\b|user interface|interface|console|admin|inbox|editor|product (shot|view|ui)|browser window/i;
|
|
219
|
+
const uiFile = /screen ?shot|dashboard|(^|[-_/.])(app|ui|screen|product)([-_/.]|$)/i;
|
|
220
|
+
const art = /\b(painting|painted|still life|portrait|landscape|engraving|etching|drawing|illustration|watercolou?r|photograph|photo of|lithograph|woodcut|sketch|museum|artwork)\b/i;
|
|
221
|
+
const credited = /\bCC0\b|\bmuseum\b|\bphoto(graph)?( by)?:|public domain|courtesy of|©|rijksmuseum|smithsonian|wikimedia|art institute|unsplash|\bthe met\b|metmuseum/i.test(credit);
|
|
222
|
+
const saysUi = uiWords.test(alt) || uiFile.test(file.replace(/^.*\/\/[^/]+/, ""));
|
|
223
|
+
const photo = !saysUi && (/\/images\/palate\//.test(file) || credited || art.test(alt) || /\.(jpe?g)(\?|#|$)/.test(file));
|
|
224
|
+
const dots = (f) => {
|
|
225
|
+
const fb = f.getBoundingClientRect();
|
|
226
|
+
const round = [...f.querySelectorAll("span, i, div, b, circle")].filter((d) => {
|
|
227
|
+
const db = d.getBoundingClientRect();
|
|
228
|
+
if (db.width < 5 || db.width > 16 || Math.abs(db.width - db.height) > 1.5 || db.top - fb.top > 56) return false;
|
|
229
|
+
return d.tagName === "circle" || parseFloat(getComputedStyle(d).borderTopLeftRadius) >= db.width * 0.4;
|
|
230
|
+
});
|
|
231
|
+
return round.length >= 3 && round.some((d, i) => i >= 2 && Math.abs(d.getBoundingClientRect().top - round[i - 2].getBoundingClientRect().top) < 3);
|
|
232
|
+
};
|
|
233
|
+
const ratio = r.width / Math.max(1, r.height);
|
|
234
|
+
screenshot = saysUi || (!photo && /\.(png|webp|avif)(\?|#|$)/.test(file) && ratio >= 1.2 && ratio <= 2.4 && frames.some(dots));
|
|
235
|
+
if (photo) kind = "photo or artwork";
|
|
236
|
+
}
|
|
237
|
+
media.push({ kind, section: sectionOf(el), size: `${Math.round(r.width)}×${Math.round(r.height)}`, framed, screenshot, alt: alt.slice(0, 80) || null, src: src.slice(0, 80) || null });
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Logo / brand rows: three or more siblings that each pair a small mark with a short name (or are a mark).
|
|
241
|
+
const markOf = (el) => {
|
|
242
|
+
const cands = [el, ...el.querySelectorAll("svg, img, span, div, i")].filter((m) => {
|
|
243
|
+
if (!visible(m)) return false;
|
|
244
|
+
const r = m.getBoundingClientRect();
|
|
245
|
+
const cs = getComputedStyle(m);
|
|
246
|
+
const isMark = m.tagName === "svg" || m.tagName === "IMG" || (cs.maskImage && cs.maskImage !== "none") || (cs.webkitMaskImage && cs.webkitMaskImage !== "none");
|
|
247
|
+
return isMark && r.height <= 64 && r.width <= 200 && r.height >= 6;
|
|
248
|
+
});
|
|
249
|
+
return cands[0] ?? null;
|
|
250
|
+
};
|
|
251
|
+
const rows = [];
|
|
252
|
+
const seen = new Set();
|
|
253
|
+
// Children of display:contents wrappers count as the parent's own.
|
|
254
|
+
const kidsOf = (p) => [...p.children].flatMap((k) => (getComputedStyle(k).display === "contents" ? kidsOf(k) : [k]));
|
|
255
|
+
for (const parent of document.body.querySelectorAll("ul, ol, div, nav, section, p")) {
|
|
256
|
+
const kids = kidsOf(parent).filter(visible);
|
|
257
|
+
if (kids.length < 3 || seen.has(parent) || !visible(parent)) continue;
|
|
258
|
+
const marks = kids.map((k) => ({ k, m: markOf(k) })).filter((x) => x.m);
|
|
259
|
+
if (marks.length < 3 || marks.length < kids.length * 0.6) continue;
|
|
260
|
+
const names = marks.map((x) => clean(x.k.textContent)).filter((t) => t && t.length < 32);
|
|
261
|
+
if (parent.closest("nav") && !names.length) continue;
|
|
262
|
+
seen.add(parent);
|
|
263
|
+
const m0 = marks[0].m;
|
|
264
|
+
const cs = getComputedStyle(m0);
|
|
265
|
+
const masked = (cs.maskImage && cs.maskImage !== "none") || (cs.webkitMaskImage && cs.webkitMaskImage !== "none");
|
|
266
|
+
const colours = new Set(
|
|
267
|
+
marks.map(({ m }) => {
|
|
268
|
+
const c = getComputedStyle(m);
|
|
269
|
+
if (m.tagName === "IMG") return `img:${m.getAttribute("src")}`;
|
|
270
|
+
// The colours the marks are painted in (computed, so classes and currentColor count), not their attributes.
|
|
271
|
+
if (m.tagName === "svg") return [...m.querySelectorAll("path, circle, rect, polygon, ellipse")].slice(0, 8).map((p) => { const pc = getComputedStyle(p); return `${pc.fill}/${pc.stroke}`; }).join(",") || c.color;
|
|
272
|
+
return c.backgroundColor;
|
|
273
|
+
}),
|
|
274
|
+
);
|
|
275
|
+
const markColour = m0.tagName === "IMG" ? null : rgb(masked ? cs.backgroundColor : cs.color).slice(0, 3);
|
|
276
|
+
const textEl = marks[0].k;
|
|
277
|
+
// A row inside a decorative miniature (an aria-hidden or inert preview of a page) is part of a picture.
|
|
278
|
+
const hidden = parent.closest("[aria-hidden=true], [inert]");
|
|
279
|
+
const hb = hidden?.getBoundingClientRect();
|
|
280
|
+
rows.push({
|
|
281
|
+
section: sectionOf(parent),
|
|
282
|
+
selector: sel(parent),
|
|
283
|
+
inPreview: Boolean(hb && hb.width >= 120 && hb.height >= 80),
|
|
284
|
+
// Outline icons (stroke only, like a feature list's icons) are not brand marks.
|
|
285
|
+
icons: marks.every(({ m }) => m.tagName === "svg" && [...m.querySelectorAll("path, circle, rect, polygon, line, polyline")].every((p) => { const pc = getComputedStyle(p); return pc.fill === "none" && pc.stroke !== "none"; })),
|
|
286
|
+
count: marks.length,
|
|
287
|
+
names: names.slice(0, 12),
|
|
288
|
+
markPx: Math.round(m0.getBoundingClientRect().height),
|
|
289
|
+
textPx: parseFloat(getComputedStyle(textEl).fontSize),
|
|
290
|
+
// One colour across the row: masks painted alike, or SVGs filled alike (a masked row in brand colours is not).
|
|
291
|
+
monochrome: (masked || m0.tagName === "svg") && colours.size <= 1,
|
|
292
|
+
// Marks that say what they are (alt, aria-label or title): a logo row without visible names.
|
|
293
|
+
labelled: marks.filter(({ m, k }) => clean(m.getAttribute("alt") ?? m.getAttribute("aria-label") ?? m.getAttribute("title") ?? k.getAttribute("aria-label") ?? m.querySelector?.("title")?.textContent)).length,
|
|
294
|
+
// Round marks without names are avatars, not logos.
|
|
295
|
+
avatars: !names.length && marks.every(({ m }) => { const r = parseFloat(getComputedStyle(m).borderTopLeftRadius); return /%/.test(getComputedStyle(m).borderTopLeftRadius) || r >= m.getBoundingClientRect().width * 0.4; }),
|
|
296
|
+
paintedByMask: Boolean(masked),
|
|
297
|
+
contrast: markColour ? contrast(markColour, bgOf(parent)) : null,
|
|
298
|
+
opacity: parseFloat(getComputedStyle(parent).opacity),
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// The page's ground: the median section background (an app often paints it on a wrapper, not the body).
|
|
303
|
+
const sectionLums = sections.map((s) => document.querySelector(s.selector)).filter(Boolean).map((r) => lum(bgOf(r))).sort((x, y) => x - y);
|
|
304
|
+
const ground = sectionLums.length ? sectionLums[Math.floor(sectionLums.length / 2)] : lum(bgOf(document.body));
|
|
305
|
+
// Devices per section, to spot the same move repeated in every section.
|
|
306
|
+
const devices = sections.map((s) => {
|
|
307
|
+
const inS = (el) => sectionOf(el) === s.index;
|
|
308
|
+
const set = [];
|
|
309
|
+
if (kickers.some((k) => k.section === s.index)) set.push("kicker label above the heading");
|
|
310
|
+
if (kickers.some((k) => k.section === s.index && /^\d{1,2}/.test(k.text))) set.push("section number");
|
|
311
|
+
if (media.some((m) => m.section === s.index && m.kind === "static picture" && m.framed && m.screenshot)) set.push("framed screenshot");
|
|
312
|
+
const els = [...document.querySelectorAll(s.selector + ", " + s.selector + " *")].slice(0, 600);
|
|
313
|
+
if (els.some((e) => getComputedStyle(e).backgroundImage.includes("gradient") && e.getBoundingClientRect().width > vw * 0.3)) set.push("gradient backdrop");
|
|
314
|
+
const root = document.querySelector(s.selector);
|
|
315
|
+
// A band is a device only against the page's own ground: a dark band on a light page, a light band on a dark
|
|
316
|
+
// one. On a dark page every section is dark, and that is the ground, not a device repeated in every section.
|
|
317
|
+
const band = root ? lum(bgOf(root)) : null;
|
|
318
|
+
if (band != null && ground >= 0.2 && band < 0.05) set.push("dark band");
|
|
319
|
+
if (band != null && ground < 0.05 && band > 0.4) set.push("light band");
|
|
320
|
+
const h = root?.querySelector("h2, h1");
|
|
321
|
+
if (h) {
|
|
322
|
+
const hb = abs(h);
|
|
323
|
+
const p = [...root.querySelectorAll("p")].find((p) => {
|
|
324
|
+
const pb = abs(p);
|
|
325
|
+
return pb.x > hb.x + hb.w - 4 && Math.abs(pb.y - hb.y) < 80;
|
|
326
|
+
});
|
|
327
|
+
if (p) set.push("two-column head (heading left, sentence right)");
|
|
328
|
+
if (getComputedStyle(h.parentElement).borderTopStyle !== "none" && parseFloat(getComputedStyle(h.parentElement).borderTopWidth) > 0) set.push("rule above the heading");
|
|
329
|
+
}
|
|
330
|
+
return { section: s.index, devices: set, inS };
|
|
331
|
+
});
|
|
332
|
+
const tally = {};
|
|
333
|
+
for (const d of devices) for (const x of d.devices) tally[x] = [...(tally[x] ?? []), d.section];
|
|
334
|
+
|
|
335
|
+
// What moves: CSS animations and transitions on the page, plus what scripts set up (counted by palate's init script).
|
|
336
|
+
const all = [...document.body.querySelectorAll("*")];
|
|
337
|
+
const animated = all.filter((e) => getComputedStyle(e).animationName !== "none" && visible(e));
|
|
338
|
+
const transitioned = all.filter((e) => {
|
|
339
|
+
const d = getComputedStyle(e).transitionDuration.split(",").map(parseFloat);
|
|
340
|
+
return d.some((x) => x > 0) && visible(e);
|
|
341
|
+
});
|
|
342
|
+
const props = {};
|
|
343
|
+
for (const e of transitioned) for (const p of getComputedStyle(e).transitionProperty.split(",").map((x) => x.trim())) props[p] = (props[p] ?? 0) + 1;
|
|
344
|
+
const counters = window.__palateMotion ?? {};
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
kickers: kickers.map(({ text, section, before }) => ({ text, section, before })),
|
|
348
|
+
media,
|
|
349
|
+
logoRows: rows.slice(0, 6),
|
|
350
|
+
repeated: Object.entries(tally).filter(([, s]) => s.length >= 3).map(([device, s]) => ({ device, sections: s })),
|
|
351
|
+
perSection: devices.map(({ section, devices }) => ({ section, devices })),
|
|
352
|
+
motion: {
|
|
353
|
+
cssAnimations: animated.length,
|
|
354
|
+
animationNames: [...new Set(animated.map((e) => getComputedStyle(e).animationName))].slice(0, 6),
|
|
355
|
+
transitions: transitioned.length,
|
|
356
|
+
transitionProps: Object.entries(props).sort((a, b) => b[1] - a[1]).slice(0, 6).map(([p, n]) => `${p}×${n}`),
|
|
357
|
+
scrollObservers: counters.io ?? null,
|
|
358
|
+
scriptedAnimations: counters.waapi ?? null,
|
|
359
|
+
started: counters.started ?? null,
|
|
360
|
+
entrances: counters.entrances ?? null,
|
|
361
|
+
startedProps: Object.entries(counters.props ?? {}).sort((a, b) => b[1] - a[1]).slice(0, 5).map(([p, n]) => `${p}×${n}`),
|
|
362
|
+
styled: counters.styled ? counters.styled.size : null,
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
};
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
// Runs inside the page (read as text and evaluated). Reduces a rendered page to its skeleton (one token per
|
|
2
|
+
// vertical band) and finds the AI-default patterns, so palate can tell when a screen looks generated or
|
|
3
|
+
// repeats one built before. Tokens: C/L = centred or left-led, digit = layout columns, w = a framed
|
|
4
|
+
// panel (product window, big card), m = big media, gN = a grid of N equal items, b = own background.
|
|
5
|
+
() => {
|
|
6
|
+
const vw = window.innerWidth;
|
|
7
|
+
const visible = (el) => {
|
|
8
|
+
const r = el.getBoundingClientRect();
|
|
9
|
+
if (r.width < 2 || r.height < 2) return false;
|
|
10
|
+
const cs = getComputedStyle(el);
|
|
11
|
+
return cs.visibility !== "hidden" && cs.display !== "none" && parseFloat(cs.opacity) > 0.01;
|
|
12
|
+
};
|
|
13
|
+
const kids = (el) => Array.from(el.children).filter(visible);
|
|
14
|
+
const ownText = (el) => Array.from(el.childNodes).filter((n) => n.nodeType === 3).map((n) => n.textContent).join("").trim();
|
|
15
|
+
const bgOf = (el) => getComputedStyle(el).backgroundColor;
|
|
16
|
+
const clear = (c) => !c || c === "transparent" || /rgba\([^)]*,\s*0\)$/.test(c);
|
|
17
|
+
const pageBg = clear(bgOf(document.body)) ? bgOf(document.documentElement) : bgOf(document.body);
|
|
18
|
+
const hue = (c) => {
|
|
19
|
+
const m = c.match(/[\d.]+/g);
|
|
20
|
+
if (!m) return null;
|
|
21
|
+
const [r, g, b] = m.slice(0, 3).map((v) => Number(v) / 255);
|
|
22
|
+
const max = Math.max(r, g, b);
|
|
23
|
+
const min = Math.min(r, g, b);
|
|
24
|
+
const d = max - min;
|
|
25
|
+
if (d < 0.12) return null;
|
|
26
|
+
const h = max === r ? ((g - b) / d) % 6 : max === g ? (b - r) / d + 2 : (r - g) / d + 4;
|
|
27
|
+
return (h * 60 + 360) % 360;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
// Rows: groups of 3+ siblings side by side (same top), the raw material of grids and strips.
|
|
31
|
+
const rows = [];
|
|
32
|
+
for (const el of document.body.querySelectorAll("*")) {
|
|
33
|
+
if (el.closest("svg")) continue;
|
|
34
|
+
const ks = kids(el);
|
|
35
|
+
if (ks.length < 3) continue;
|
|
36
|
+
const byTop = new Map();
|
|
37
|
+
for (const k of ks) {
|
|
38
|
+
const t = Math.round(k.getBoundingClientRect().top / 6);
|
|
39
|
+
byTop.set(t, [...(byTop.get(t) ?? []), k]);
|
|
40
|
+
}
|
|
41
|
+
for (const group of byTop.values()) {
|
|
42
|
+
if (group.length < 3) continue;
|
|
43
|
+
const ws = group.map((g) => g.getBoundingClientRect().width);
|
|
44
|
+
rows.push({ parent: el, items: group, equal: Math.max(...ws) / Math.max(1, Math.min(...ws)) < 1.15, top: group[0].getBoundingClientRect().top + scrollY });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Bands: the page's vertical sections, found by descending through single wrappers.
|
|
49
|
+
let root = document.querySelector("main") ?? document.body;
|
|
50
|
+
for (let i = 0; i < 6; i++) {
|
|
51
|
+
const ks = kids(root);
|
|
52
|
+
const tall = ks.filter((k) => k.getBoundingClientRect().height > 40);
|
|
53
|
+
if (tall.length === 1 && tall[0].getBoundingClientRect().height > root.getBoundingClientRect().height * 0.8) root = tall[0];
|
|
54
|
+
else break;
|
|
55
|
+
}
|
|
56
|
+
let bandEls = kids(root).filter((k) => k.getBoundingClientRect().height >= 40);
|
|
57
|
+
const header = document.querySelector("body header, [role=banner]");
|
|
58
|
+
if (header && !root.contains(header) && visible(header)) bandEls = [header, ...bandEls];
|
|
59
|
+
|
|
60
|
+
const info = [];
|
|
61
|
+
const bands = bandEls.slice(0, 24).map((band) => {
|
|
62
|
+
const br = band.getBoundingClientRect();
|
|
63
|
+
let focal = null;
|
|
64
|
+
let size = 0;
|
|
65
|
+
for (const el of band.querySelectorAll("*")) {
|
|
66
|
+
if (!ownText(el) || !visible(el)) continue;
|
|
67
|
+
const s = parseFloat(getComputedStyle(el).fontSize);
|
|
68
|
+
if (s > size) {
|
|
69
|
+
size = s;
|
|
70
|
+
focal = el;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const fr = focal?.getBoundingClientRect();
|
|
74
|
+
const centred = fr && Math.abs(fr.left + fr.width / 2 - (br.left + br.width / 2)) < br.width * 0.05 && getComputedStyle(focal).textAlign === "center";
|
|
75
|
+
// Layout columns: descend through wrappers until the band splits, then count what sits side by side.
|
|
76
|
+
let box = band;
|
|
77
|
+
for (let i = 0; i < 8; i++) {
|
|
78
|
+
const ks = kids(box);
|
|
79
|
+
if (ks.length === 1) box = ks[0];
|
|
80
|
+
else break;
|
|
81
|
+
}
|
|
82
|
+
const top = kids(box);
|
|
83
|
+
// Side by side = overlapping vertically with the first wide child (columns may be centred, not top-aligned).
|
|
84
|
+
const wide = top.filter((k) => k.getBoundingClientRect().width > 80);
|
|
85
|
+
const f0 = wide[0]?.getBoundingClientRect();
|
|
86
|
+
const across = f0 ? wide.filter((k) => {
|
|
87
|
+
const r = k.getBoundingClientRect();
|
|
88
|
+
return Math.min(r.bottom, f0.bottom) - Math.max(r.top, f0.top) > Math.min(r.height, f0.height) * 0.3;
|
|
89
|
+
}) : [];
|
|
90
|
+
const cols = Math.max(1, Math.min(across.length, 9));
|
|
91
|
+
// A framed panel (a product window, a big card): own surface or border, rounded, a real share of the band.
|
|
92
|
+
const panel = Array.from(band.querySelectorAll("div, section, figure, article, aside")).some((el) => {
|
|
93
|
+
const r = el.getBoundingClientRect();
|
|
94
|
+
if (r.width * r.height < br.width * br.height * 0.15 || r.width > br.width * 0.9) return false;
|
|
95
|
+
const cs = getComputedStyle(el);
|
|
96
|
+
return parseFloat(cs.borderTopLeftRadius) >= 6 && (parseFloat(cs.borderTopWidth) > 0 || (!clear(cs.backgroundColor) && cs.backgroundColor !== bgOf(band))) && el.querySelectorAll("*").length > 25;
|
|
97
|
+
});
|
|
98
|
+
// A grid of equal items anywhere in the band (cards, tiers, tiles).
|
|
99
|
+
const grid = rows.filter((r) => (band.contains(r.parent) || band === r.parent) && r.equal).sort((a, b) => b.items.length - a.items.length)[0];
|
|
100
|
+
const mediaShare = Math.max(0, ...Array.from(band.querySelectorAll("img, video, canvas, svg, picture")).map((m) => {
|
|
101
|
+
const r = m.getBoundingClientRect();
|
|
102
|
+
return (r.width * r.height) / Math.max(1, br.width * br.height);
|
|
103
|
+
}));
|
|
104
|
+
const media = mediaShare > 0.15;
|
|
105
|
+
const ownBg = !clear(bgOf(band)) && bgOf(band) !== pageBg;
|
|
106
|
+
// Kept for the layout memory: what the band holds and how its columns are proportioned.
|
|
107
|
+
const ws = across.map((k) => k.getBoundingClientRect().width);
|
|
108
|
+
info.push({ top: Math.round(br.top + scrollY), height: Math.round(br.height), focal: Math.round(size), centred: Boolean(centred), cols, ratio: ws.length > 1 ? +(Math.max(...ws) / Math.max(1, Math.min(...ws))).toFixed(2) : 1, media: +Math.min(1, mediaShare).toFixed(2), panel, grid: grid ? grid.items.length : 0, ownBg, header: band === header });
|
|
109
|
+
return `${centred ? "C" : "L"}${cols}${panel ? "w" : ""}${media ? "m" : ""}${grid ? `g${Math.min(grid.items.length, 9)}` : ""}${ownBg ? "b" : ""}`;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// The AI defaults, measured.
|
|
113
|
+
const found = new Set();
|
|
114
|
+
const textOf = (el) => (el.innerText || "").trim();
|
|
115
|
+
// A product drawn in HTML (a mock window, a picture of the app): its own stats, chips and icons are the
|
|
116
|
+
// product's, not the page's.
|
|
117
|
+
const MOCK = "[aria-hidden=true], [role=img], [inert], [data-product], [role=group][aria-label], [role=group][aria-labelledby], figure";
|
|
118
|
+
const mockOf = (el) => (el.nodeType === 1 ? el : el.parentElement)?.closest(MOCK) ?? null;
|
|
119
|
+
for (const r of rows) {
|
|
120
|
+
const items = r.items;
|
|
121
|
+
if (r.equal && items.length <= 4 && items.every((it) => {
|
|
122
|
+
const icon = Array.from(it.querySelectorAll("svg, img")).find((s) => s.getBoundingClientRect().width <= 56);
|
|
123
|
+
return icon && it.querySelector("h2, h3, h4, strong, [class*=title]") && textOf(it).length > 30 && it.getBoundingClientRect().height < 420;
|
|
124
|
+
})) found.add("icon-feature-trio");
|
|
125
|
+
// Logos: one row of 4 to 12 small pictures of a similar height with no text, outside a product mock. A
|
|
126
|
+
// grid of glyphs (many rows from one parent, a kiln shelf of pots) is a picture, not a logo row.
|
|
127
|
+
const logoish = (it) => {
|
|
128
|
+
const media = it.matches("img, svg") ? [it] : Array.from(it.querySelectorAll("img, svg")).filter((m) => !m.parentElement.closest("svg") && visible(m));
|
|
129
|
+
return media.length === 1 && textOf(it).length < 2;
|
|
130
|
+
};
|
|
131
|
+
const hs = items.map((it) => it.getBoundingClientRect().height);
|
|
132
|
+
const siblingRows = rows.filter((o) => o.parent === r.parent).length;
|
|
133
|
+
if (items.length >= 4 && items.length <= 12 && siblingRows <= 2 && items.every(logoish) && Math.max(...hs) <= 80 && Math.min(...hs) >= 12 && Math.max(...hs) / Math.min(...hs) <= 1.6 && !mockOf(r.parent)) found.add("logo-strip");
|
|
134
|
+
// Stats: 3 to 5 items, each a big numeral (not a price, a time or a date) with a short label and no
|
|
135
|
+
// action, outside a product mock. Price heads in a pricing ledger and a timeline of times are not stats.
|
|
136
|
+
const NUMERAL = /^[+~<>]?\s?\d[\d.,]*\s?(%|[kKmMbB]\+?|\+|×|x)?(\s?\/\s?\d[\d.,]*\s?[kKmMbB%]?)?$|^\d+(\.\d+)?×$|^24\/7$/;
|
|
137
|
+
const bigNumber = (it) => Array.from(it.querySelectorAll("*")).concat(it).some((el) => {
|
|
138
|
+
const t = ownText(el).replace(/\s+/g, " ");
|
|
139
|
+
return t && NUMERAL.test(t) && !/^(19|20)\d\d$/.test(t) && parseFloat(getComputedStyle(el).fontSize) >= 26;
|
|
140
|
+
});
|
|
141
|
+
const PLAN = /\b(free|starter|basic|pro|plus|premium|team|business|enterprise|standard|growth|scale)\b/i;
|
|
142
|
+
const statItem = (it) => {
|
|
143
|
+
const t = textOf(it).replace(/\s+/g, " ");
|
|
144
|
+
if (!bigNumber(it) || /[$€£¥₹]|\b(USD|EUR|GBP)\b|\/\s?(mo|month|yr|year)\b|per (month|year|seat|user)/i.test(t)) return false;
|
|
145
|
+
if (/\b\d{1,2}:\d{2}\b|\b\d{1,2}\s?(am|pm)\b/i.test(t)) return false;
|
|
146
|
+
const head = it.querySelector("h2, h3, h4, h5");
|
|
147
|
+
return t.length <= 90 && !it.querySelector("a[href], button, input, select") && !(head && PLAN.test(head.textContent));
|
|
148
|
+
};
|
|
149
|
+
if (items.length >= 3 && items.length <= 5 && items.every(statItem) && !mockOf(r.parent)) found.add("stat-row");
|
|
150
|
+
const priced = items.filter((it) => /[$€£₹]\s?\d/.test(textOf(it))).length;
|
|
151
|
+
if (r.equal && items.length >= 3 && items.length <= 4 && priced >= items.length - 1 && items.every((it) => it.querySelector("a, button") && it.getBoundingClientRect().height > 200)) found.add("three-tier-pricing");
|
|
152
|
+
if (items.length >= 3 && items.every((it) => /^[“"]/.test(textOf(it)) || it.querySelector("blockquote"))) found.add("quote-grid");
|
|
153
|
+
}
|
|
154
|
+
const first = bandEls.find((b) => b !== header) ?? bandEls[0];
|
|
155
|
+
if (first && bands[bandEls.indexOf(first)]?.startsWith("C")) {
|
|
156
|
+
const actions = Array.from(first.querySelectorAll("a, button")).filter((a) => visible(a) && a.getBoundingClientRect().height >= 32);
|
|
157
|
+
if (actions.length >= 2) found.add("centred-hero");
|
|
158
|
+
}
|
|
159
|
+
if (first) {
|
|
160
|
+
let focal = null;
|
|
161
|
+
let size = 0;
|
|
162
|
+
for (const el of first.querySelectorAll("*")) {
|
|
163
|
+
const s = parseFloat(getComputedStyle(el).fontSize);
|
|
164
|
+
if (ownText(el) && s > size) {
|
|
165
|
+
size = s;
|
|
166
|
+
focal = el;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const fRect = focal?.getBoundingClientRect();
|
|
170
|
+
const ft = fRect?.top ?? 0;
|
|
171
|
+
for (const el of first.querySelectorAll("*")) {
|
|
172
|
+
const r = el.getBoundingClientRect();
|
|
173
|
+
const cs = getComputedStyle(el);
|
|
174
|
+
if (r.height > 0 && r.height <= 36 && r.bottom <= ft && ft - r.bottom < 120 && fRect && r.left < fRect.right && r.right > fRect.left && parseFloat(cs.borderTopLeftRadius) >= r.height / 2 - 1 && textOf(el).length > 2 && textOf(el).length < 60 && (!clear(cs.backgroundColor) || parseFloat(cs.borderTopWidth) > 0)) {
|
|
175
|
+
found.add("eyebrow-pill");
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
let eyebrows = 0;
|
|
181
|
+
for (const h of document.querySelectorAll("h1, h2")) {
|
|
182
|
+
if (!visible(h)) continue;
|
|
183
|
+
const hr = h.getBoundingClientRect();
|
|
184
|
+
let prev = h.previousElementSibling;
|
|
185
|
+
if (!prev && h.parentElement) prev = h.parentElement.previousElementSibling;
|
|
186
|
+
if (!prev || !visible(prev)) continue;
|
|
187
|
+
const pr = prev.getBoundingClientRect();
|
|
188
|
+
const cs = getComputedStyle(prev);
|
|
189
|
+
const t = textOf(prev);
|
|
190
|
+
if (t.length > 1 && t.length < 50 && hr.top - pr.bottom < 32 && parseFloat(cs.fontSize) <= 14 && (cs.textTransform === "uppercase" || (t === t.toUpperCase() && /[A-Z]{3}/.test(t)))) eyebrows++;
|
|
191
|
+
}
|
|
192
|
+
if (eyebrows >= 2) found.add("eyebrow-label");
|
|
193
|
+
let pills = 0;
|
|
194
|
+
const pillHues = new Map();
|
|
195
|
+
let gradientHues = [];
|
|
196
|
+
for (const el of document.body.querySelectorAll("*")) {
|
|
197
|
+
if (!visible(el)) continue;
|
|
198
|
+
const cs = getComputedStyle(el);
|
|
199
|
+
const r = el.getBoundingClientRect();
|
|
200
|
+
if (r.height <= 28 && r.width < 160 && parseFloat(cs.borderTopLeftRadius) >= r.height / 2 - 1 && textOf(el).length > 1 && !mockOf(el)) {
|
|
201
|
+
const h = hue(cs.backgroundColor);
|
|
202
|
+
if (h !== null) {
|
|
203
|
+
pills++;
|
|
204
|
+
const k = Math.round(h / 40);
|
|
205
|
+
pillHues.set(k, (pillHues.get(k) ?? 0) + 1);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (/gradient/.test(cs.backgroundImage) && r.width * r.height > vw * 120) {
|
|
209
|
+
gradientHues.push(...(cs.backgroundImage.match(/rgba?\([^)]*\)/g) ?? []).map(hue).filter((h) => h !== null));
|
|
210
|
+
}
|
|
211
|
+
if (/blur\((\d+)/.test(cs.filter) && Number(cs.filter.match(/blur\((\d+)/)[1]) >= 40) found.add("glow");
|
|
212
|
+
}
|
|
213
|
+
// Confetti: many filled pills in three or more hues, each hue used more than once (a couple of status chips
|
|
214
|
+
// in a product mock are not it).
|
|
215
|
+
if (pills >= 8 && [...pillHues.values()].filter((n) => n >= 2).length >= 3) found.add("pill-rainbow");
|
|
216
|
+
if (gradientHues.some((h) => h >= 230 && h <= 300) && gradientHues.some((h) => h < 230 || h > 300 || h >= 260)) found.add("purple-blue-gradient");
|
|
217
|
+
if (/\b(John Doe|Jane Doe|Jane Smith|Acme|Lorem ipsum)\b/i.test(document.body.innerText)) found.add("generic-sample");
|
|
218
|
+
|
|
219
|
+
// Style, for the layout memory: what the type, colour and shapes are, measured from computed styles.
|
|
220
|
+
// Any CSS colour (rgb, oklch, lab, color()) to #rrggbb, through a 1×1 canvas; null when mostly transparent.
|
|
221
|
+
const ctx = Object.assign(document.createElement("canvas"), { width: 1, height: 1 }).getContext("2d", { willReadFrequently: true });
|
|
222
|
+
const seen = new Map();
|
|
223
|
+
const hex = (c) => {
|
|
224
|
+
if (!c || clear(c)) return null;
|
|
225
|
+
if (!seen.has(c)) {
|
|
226
|
+
ctx.clearRect(0, 0, 1, 1);
|
|
227
|
+
ctx.fillStyle = "#000";
|
|
228
|
+
ctx.fillStyle = c;
|
|
229
|
+
ctx.fillRect(0, 0, 1, 1);
|
|
230
|
+
const [r, g, b, a] = ctx.getImageData(0, 0, 1, 1).data;
|
|
231
|
+
seen.set(c, a < 128 ? null : "#" + [r, g, b].map((v) => v.toString(16).padStart(2, "0")).join(""));
|
|
232
|
+
}
|
|
233
|
+
return seen.get(c);
|
|
234
|
+
};
|
|
235
|
+
const fam = new Map();
|
|
236
|
+
const colors = new Map();
|
|
237
|
+
let head = null;
|
|
238
|
+
for (const el of document.body.querySelectorAll("*")) {
|
|
239
|
+
if (el.closest("svg") || !ownText(el) || !visible(el)) continue;
|
|
240
|
+
const cs = getComputedStyle(el);
|
|
241
|
+
const r = el.getBoundingClientRect();
|
|
242
|
+
const f = cs.fontFamily.split(",")[0].replace(/["']/g, "").trim();
|
|
243
|
+
fam.set(f, (fam.get(f) ?? 0) + r.width * r.height);
|
|
244
|
+
colors.set(hex(cs.color), (colors.get(hex(cs.color)) ?? 0) + r.width * r.height);
|
|
245
|
+
const size = parseFloat(cs.fontSize);
|
|
246
|
+
if (r.top + scrollY < innerHeight * 1.5 && (!head || size > head.size)) head = { size: Math.round(size), weight: Number(cs.fontWeight) || 400, family: f, tracking: cs.letterSpacing === "normal" ? 0 : +(parseFloat(cs.letterSpacing) / size).toFixed(3), align: cs.textAlign, upper: cs.textTransform === "uppercase", italic: cs.fontStyle === "italic", text: ownText(el).slice(0, 60) };
|
|
247
|
+
}
|
|
248
|
+
const radii = new Map();
|
|
249
|
+
const accents = new Map();
|
|
250
|
+
for (const el of document.body.querySelectorAll("*")) {
|
|
251
|
+
if (!visible(el)) continue;
|
|
252
|
+
const cs = getComputedStyle(el);
|
|
253
|
+
const r = el.getBoundingClientRect();
|
|
254
|
+
const hasSurface = !clear(cs.backgroundColor) || parseFloat(cs.borderTopWidth) > 0;
|
|
255
|
+
if (hasSurface && r.width > 40 && r.height > 24) {
|
|
256
|
+
const rad = Math.round(Math.min(parseFloat(cs.borderTopLeftRadius) || 0, r.height / 2));
|
|
257
|
+
const key = rad >= r.height / 2 - 1 && r.height < 64 ? "pill" : String(rad);
|
|
258
|
+
radii.set(key, (radii.get(key) ?? 0) + 1);
|
|
259
|
+
}
|
|
260
|
+
if (el.matches("a, button, [role=button]") && hue(hex(cs.backgroundColor)?.replace(/^#(..)(..)(..)$/, (_, r, g, b) => `rgb(${parseInt(r, 16)},${parseInt(g, 16)},${parseInt(b, 16)})`) ?? "") !== null) accents.set(hex(cs.backgroundColor), (accents.get(hex(cs.backgroundColor)) ?? 0) + 1);
|
|
261
|
+
}
|
|
262
|
+
// The canvas colour: the first real background from the content root outwards.
|
|
263
|
+
let canvas = null;
|
|
264
|
+
for (let el = root; el && !canvas; el = el.parentElement) canvas = hex(bgOf(el));
|
|
265
|
+
canvas = canvas ?? "#ffffff";
|
|
266
|
+
const top = (m, n) => [...m.entries()].filter(([k]) => k).sort((a, b) => b[1] - a[1]).slice(0, n).map(([k]) => k);
|
|
267
|
+
const bandBgs = [...new Set(bandEls.map((b) => hex(bgOf(b))).filter(Boolean))];
|
|
268
|
+
const style = {
|
|
269
|
+
fonts: top(fam, 3),
|
|
270
|
+
headline: head,
|
|
271
|
+
bg: canvas,
|
|
272
|
+
bands: bandBgs.slice(0, 5),
|
|
273
|
+
text: top(colors, 1)[0] ?? null,
|
|
274
|
+
accent: top(accents, 1)[0] ?? null,
|
|
275
|
+
radii: top(radii, 3),
|
|
276
|
+
height: document.documentElement.scrollHeight,
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
const firstScreen = bands.filter((_, i) => !info[i]?.header).slice(0, 3);
|
|
280
|
+
return { skeleton: bands, bands: info, firstScreen, style, cliches: [...found] };
|
|
281
|
+
};
|