@aglyn/plugins-ai 1.0.0-beta.269 → 1.0.0-beta.271
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/package.json +17 -17
- package/src/lib/activity/ai-activity-actions.d.ts +1 -1
- package/src/lib/activity/ai-activity-actions.js +1 -0
- package/src/lib/activity/ai-activity-actions.js.map +1 -1
- package/src/lib/assets/site-styles/beauty.webp +0 -0
- package/src/lib/assets/site-styles/blog.webp +0 -0
- package/src/lib/assets/site-styles/business.webp +0 -0
- package/src/lib/assets/site-styles/coming-soon.webp +0 -0
- package/src/lib/assets/site-styles/education.webp +0 -0
- package/src/lib/assets/site-styles/events.webp +0 -0
- package/src/lib/assets/site-styles/fitness.webp +0 -0
- package/src/lib/assets/site-styles/landing.webp +0 -0
- package/src/lib/assets/site-styles/music.webp +0 -0
- package/src/lib/assets/site-styles/nonprofit.webp +0 -0
- package/src/lib/assets/site-styles/personal.webp +0 -0
- package/src/lib/assets/site-styles/photography.webp +0 -0
- package/src/lib/assets/site-styles/portfolio.webp +0 -0
- package/src/lib/assets/site-styles/professional.webp +0 -0
- package/src/lib/assets/site-styles/realestate.webp +0 -0
- package/src/lib/assets/site-styles/restaurant.webp +0 -0
- package/src/lib/assets/site-styles/store.webp +0 -0
- package/src/lib/assets/site-styles/studio.webp +0 -0
- package/src/lib/assets/site-styles/trades.webp +0 -0
- package/src/lib/assets/site-styles/wellness.webp +0 -0
- package/src/lib/assets/site-styles/yoga.webp +0 -0
- package/src/lib/components/ai-credits-card.component.d.ts +8 -6
- package/src/lib/components/ai-credits-card.component.js +39 -22
- package/src/lib/components/ai-credits-card.component.js.map +1 -1
- package/src/lib/components/ai-job-input-form.component.d.ts +36 -0
- package/src/lib/components/ai-job-input-form.component.js +100 -0
- package/src/lib/components/ai-job-input-form.component.js.map +1 -0
- package/src/lib/components/ai-job-links.d.ts +6 -0
- package/src/lib/components/ai-job-links.js +9 -0
- package/src/lib/components/ai-job-links.js.map +1 -1
- package/src/lib/components/ai-job-requests.d.ts +4 -0
- package/src/lib/components/ai-job-requests.js +4 -0
- package/src/lib/components/ai-job-requests.js.map +1 -1
- package/src/lib/components/ai-products-hub-card.component.d.ts +6 -0
- package/src/lib/components/ai-products-hub-card.component.js +21 -6
- package/src/lib/components/ai-products-hub-card.component.js.map +1 -1
- package/src/lib/components/ai-site-build-page.component.js +3 -2
- package/src/lib/components/ai-site-build-page.component.js.map +1 -1
- package/src/lib/components/ai-site-start-card.component.d.ts +1 -1
- package/src/lib/components/ai-site-start-card.component.js +99 -31
- package/src/lib/components/ai-site-start-card.component.js.map +1 -1
- package/src/lib/components/ai-site-start-steps.component.d.ts +43 -2
- package/src/lib/components/ai-site-start-steps.component.js +651 -15
- package/src/lib/components/ai-site-start-steps.component.js.map +1 -1
- package/src/lib/components/ai-site-start-tracking.d.ts +10 -0
- package/src/lib/components/ai-site-start-tracking.js +14 -0
- package/src/lib/components/ai-site-start-tracking.js.map +1 -1
- package/src/lib/components/ai-site-style-previews.js +26 -22
- package/src/lib/components/ai-site-style-previews.js.map +1 -1
- package/src/lib/components/ai-store-finish-card.component.d.ts +14 -3
- package/src/lib/components/ai-store-finish-card.component.js +67 -9
- package/src/lib/components/ai-store-finish-card.component.js.map +1 -1
- package/src/lib/components/ai-upsell-dialog.component.d.ts +7 -5
- package/src/lib/components/ai-upsell-dialog.component.js +8 -6
- package/src/lib/components/ai-upsell-dialog.component.js.map +1 -1
- package/src/lib/components/assist-build-card.component.js +14 -3
- package/src/lib/components/assist-build-card.component.js.map +1 -1
- package/src/lib/components/assist-jobs-drawer.component.js +9 -1
- package/src/lib/components/assist-jobs-drawer.component.js.map +1 -1
- package/src/lib/components/assist-panel.component.js +8 -4
- package/src/lib/components/assist-panel.component.js.map +1 -1
- package/src/lib/components/staff-org-ai-card.component.js +4 -7
- package/src/lib/components/staff-org-ai-card.component.js.map +1 -1
- package/src/lib/declarations.d.ts +2 -2
- package/src/lib/declarations.js +9 -5
- package/src/lib/declarations.js.map +1 -1
- package/src/lib/jobs/ai-build-capabilities.js +3 -1
- package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
- package/src/lib/jobs/ai-business-profile-prefill.d.ts +1 -1
- package/src/lib/jobs/ai-business-profile-prefill.js +14 -3
- package/src/lib/jobs/ai-business-profile-prefill.js.map +1 -1
- package/src/lib/jobs/ai-job-build-step.d.ts +3 -0
- package/src/lib/jobs/ai-job-build-step.js +13 -5
- package/src/lib/jobs/ai-job-build-step.js.map +1 -1
- package/src/lib/jobs/ai-job-form-step.d.ts +24 -1
- package/src/lib/jobs/ai-job-form-step.js +93 -7
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-language.d.ts +35 -11
- package/src/lib/jobs/ai-job-page-language.js +68 -2
- package/src/lib/jobs/ai-job-page-language.js.map +1 -1
- package/src/lib/jobs/ai-job-page-step.d.ts +17 -0
- package/src/lib/jobs/ai-job-page-step.js +40 -17
- package/src/lib/jobs/ai-job-page-step.js.map +1 -1
- package/src/lib/jobs/ai-job-plan-step.d.ts +25 -2
- package/src/lib/jobs/ai-job-plan-step.js +103 -29
- package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
- package/src/lib/jobs/ai-job-settings-step.js +4 -3
- package/src/lib/jobs/ai-job-settings-step.js.map +1 -1
- package/src/lib/jobs/ai-job-site-datasets.d.ts +27 -0
- package/src/lib/jobs/ai-job-site-datasets.js +140 -14
- package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
- package/src/lib/jobs/ai-job-site-look.js +18 -5
- package/src/lib/jobs/ai-job-site-look.js.map +1 -1
- package/src/lib/jobs/ai-job-site-step.d.ts +16 -1
- package/src/lib/jobs/ai-job-site-step.js +95 -22
- package/src/lib/jobs/ai-job-site-step.js.map +1 -1
- package/src/lib/jobs/ai-job-text-step.d.ts +8 -1
- package/src/lib/jobs/ai-job-text-step.js.map +1 -1
- package/src/lib/jobs/ai-job-tracking-step.d.ts +14 -3
- package/src/lib/jobs/ai-job-tracking-step.js +28 -5
- package/src/lib/jobs/ai-job-tracking-step.js.map +1 -1
- package/src/lib/jobs/ai-jobs.d.ts +8 -1
- package/src/lib/jobs/ai-jobs.js +63 -8
- package/src/lib/jobs/ai-jobs.js.map +1 -1
- package/src/lib/jobs/ai-layout-owner-photos.d.ts +57 -0
- package/src/lib/jobs/ai-layout-owner-photos.js +110 -0
- package/src/lib/jobs/ai-layout-owner-photos.js.map +1 -0
- package/src/lib/jobs/ai-layout-stock-photos.d.ts +62 -4
- package/src/lib/jobs/ai-layout-stock-photos.js +523 -72
- package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
- package/src/lib/jobs/ai-site-inspiration-signals.d.ts +98 -0
- package/src/lib/jobs/ai-site-inspiration-signals.js +585 -0
- package/src/lib/jobs/ai-site-inspiration-signals.js.map +1 -0
- package/src/lib/jobs/ai-site-inspiration.d.ts +157 -0
- package/src/lib/jobs/ai-site-inspiration.js +346 -0
- package/src/lib/jobs/ai-site-inspiration.js.map +1 -0
- package/src/lib/jobs/ai-site-publish.d.ts +26 -1
- package/src/lib/jobs/ai-site-publish.js +162 -13
- package/src/lib/jobs/ai-site-publish.js.map +1 -1
- package/src/lib/jobs/ai-theme-brand-inputs.d.ts +16 -0
- package/src/lib/jobs/ai-theme-brand-inputs.js +18 -4
- package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-candle-shop-free-plan-recording.d.ts +97 -0
- package/src/lib/jobs/fixtures/ai-candle-shop-free-plan-recording.js +137 -0
- package/src/lib/jobs/fixtures/ai-candle-shop-free-plan-recording.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-site-inspiration-pages.d.ts +38 -0
- package/src/lib/jobs/fixtures/ai-site-inspiration-pages.js +103 -0
- package/src/lib/jobs/fixtures/ai-site-inspiration-pages.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3942-recordings.d.ts +29 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3942-recordings.js +291 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3942-recordings.js.map +1 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3988-recordings.d.ts +25 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3988-recordings.js +174 -0
- package/src/lib/jobs/fixtures/ai-stock-photo-agl3988-recordings.js.map +1 -0
- package/src/lib/layout-language/ai-layout-compiler.d.ts +1 -1
- package/src/lib/layout-language/ai-layout-compiler.js +438 -25
- package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
- package/src/lib/layout-language/ai-layout-contact.d.ts +57 -0
- package/src/lib/layout-language/ai-layout-contact.js +137 -0
- package/src/lib/layout-language/ai-layout-contact.js.map +1 -0
- package/src/lib/layout-language/ai-layout-copy.d.ts +12 -0
- package/src/lib/layout-language/ai-layout-copy.js +34 -2
- package/src/lib/layout-language/ai-layout-copy.js.map +1 -1
- package/src/lib/layout-language/ai-layout-design.d.ts +65 -8
- package/src/lib/layout-language/ai-layout-design.js +411 -97
- package/src/lib/layout-language/ai-layout-design.js.map +1 -1
- package/src/lib/layout-language/ai-layout-frame.js +23 -0
- package/src/lib/layout-language/ai-layout-frame.js.map +1 -1
- package/src/lib/layout-language/ai-layout-labels.d.ts +2 -0
- package/src/lib/layout-language/ai-layout-labels.js +12 -6
- package/src/lib/layout-language/ai-layout-labels.js.map +1 -1
- package/src/lib/layout-language/ai-layout-language.d.ts +3 -2
- package/src/lib/layout-language/ai-layout-language.js +4 -3
- package/src/lib/layout-language/ai-layout-language.js.map +1 -1
- package/src/lib/layout-language/ai-layout-links.d.ts +13 -0
- package/src/lib/layout-language/ai-layout-links.js +30 -0
- package/src/lib/layout-language/ai-layout-links.js.map +1 -1
- package/src/lib/layout-language/ai-layout-pictures.d.ts +49 -6
- package/src/lib/layout-language/ai-layout-pictures.js +145 -22
- package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
- package/src/lib/model/ai-build-job.d.ts +16 -1
- package/src/lib/model/ai-build-job.js +40 -0
- package/src/lib/model/ai-build-job.js.map +1 -1
- package/src/lib/model/ai-job-input.d.ts +33 -0
- package/src/lib/model/ai-job-input.js +59 -0
- package/src/lib/model/ai-job-input.js.map +1 -0
- package/src/lib/model/ai-job-notice.d.ts +4 -0
- package/src/lib/model/ai-job-notice.js +11 -1
- package/src/lib/model/ai-job-notice.js.map +1 -1
- package/src/lib/model/ai-jobs.types.d.ts +40 -1
- package/src/lib/model/ai-jobs.types.js.map +1 -1
- package/src/lib/model/ai-site-details.d.ts +122 -0
- package/src/lib/model/ai-site-details.js +300 -0
- package/src/lib/model/ai-site-details.js.map +1 -0
- package/src/lib/model/ai-site-entity.d.ts +181 -0
- package/src/lib/model/ai-site-entity.js +390 -0
- package/src/lib/model/ai-site-entity.js.map +1 -0
- package/src/lib/model/ai-site-inspiration.d.ts +72 -0
- package/src/lib/model/ai-site-inspiration.js +109 -0
- package/src/lib/model/ai-site-inspiration.js.map +1 -0
- package/src/lib/model/ai-site-job.d.ts +13 -1
- package/src/lib/model/ai-site-job.js +15 -2
- package/src/lib/model/ai-site-job.js.map +1 -1
- package/src/lib/model/ai-site-kinds.js +109 -21
- package/src/lib/model/ai-site-kinds.js.map +1 -1
- package/src/lib/model/ai-site-look.d.ts +10 -0
- package/src/lib/model/ai-site-look.js +24 -0
- package/src/lib/model/ai-site-look.js.map +1 -1
- package/src/lib/model/ai-site-start-seo.d.ts +19 -5
- package/src/lib/model/ai-site-start-seo.js +25 -7
- package/src/lib/model/ai-site-start-seo.js.map +1 -1
- package/src/lib/model/ai-site-start-steps.d.ts +9 -3
- package/src/lib/model/ai-site-start-steps.js +67 -5
- package/src/lib/model/ai-site-start-steps.js.map +1 -1
- package/src/lib/model/ai-site-start.d.ts +68 -4
- package/src/lib/model/ai-site-start.js +166 -13
- package/src/lib/model/ai-site-start.js.map +1 -1
- package/src/lib/model/ai-upsell-copy.js +4 -1
- package/src/lib/model/ai-upsell-copy.js.map +1 -1
- package/src/lib/native-nav.d.ts +26 -0
- package/src/lib/native-nav.js +58 -0
- package/src/lib/native-nav.js.map +1 -0
- package/src/lib/plan-entitlements.d.ts +4 -3
- package/src/lib/plan-entitlements.js +3 -8
- package/src/lib/plan-entitlements.js.map +1 -1
- package/src/lib/runtime/ai-dataset-generation.d.ts +8 -1
- package/src/lib/runtime/ai-dataset-generation.js +12 -2
- package/src/lib/runtime/ai-dataset-generation.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +26 -33
- package/src/lib/runtime/ai-doctrine-validators.js +54 -44
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-doctrine.js +1 -1
- package/src/lib/runtime/ai-doctrine.js.map +1 -1
- package/src/lib/runtime/ai-node-tree.d.ts +7 -0
- package/src/lib/runtime/ai-node-tree.js +9 -1
- package/src/lib/runtime/ai-node-tree.js.map +1 -1
- package/src/lib/server/ai-create-route.d.ts +1 -1
- package/src/lib/server/ai-create-route.js +3 -4
- package/src/lib/server/ai-create-route.js.map +1 -1
- package/src/lib/server/ai-jobs-resume.js +27 -3
- package/src/lib/server/ai-jobs-resume.js.map +1 -1
- package/src/lib/server/ai-jobs-route.js +7 -0
- package/src/lib/server/ai-jobs-route.js.map +1 -1
- package/src/lib/usage/assist-credits.d.ts +4 -4
- package/src/lib/usage/assist-credits.js +4 -4
- package/src/lib/usage/assist-credits.js.map +1 -1
- package/src/lib/usage/staff-org-ai-view.js +6 -3
- package/src/lib/usage/staff-org-ai-view.js.map +1 -1
- package/src/lib/usage/staff-org-ai.d.ts +4 -2
- package/src/lib/usage/staff-org-ai.js +7 -7
- package/src/lib/usage/staff-org-ai.js.map +1 -1
- package/src/lib/usage/staff-org-usage-ai.js +2 -2
- package/src/lib/usage/staff-org-usage-ai.js.map +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-site-kinds.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The kinds of website a guided start offers (AGL-3660), and the style\n * direction each one sets.\n *\n * A kind is NOT a template. It is a direction in two halves:\n *\n * - a LOOK FAMILY the code applies — how saturated the palette is, the hues\n * that suit the kind, the page grounds, the font pairings, the corners,\n * the button style, the heading scale and the density — inside which the\n * model picks this business's own look and a per-job seed varies it\n * (`ai-site-look.ts`), so two sites of one kind never share a theme;\n * - GUIDANCE the model reads: how the kind's pages are usually arranged\n * (band rhythm, image share, density) and which pages it usually has.\n *\n * Every page a kind suggests is one the site job builds itself out of the\n * layout language: sections, cards, images, a form. The site job also writes\n * a blog's first posts into a content collection (one on the Free taste,\n * AGL-3798) and, on a paid plan, a store's first products as unpriced drafts\n * (AGL-3676, `jobs/ai-job-site-content.ts`), and the pages are told their\n * titles. No event records are created, and no\n * guidance here promises posts, products or events, since the plan reads it\n * on every plan (the owner adds more from the Content, Commerce and Events\n * sections afterward).\n *\n * Pure data and two small readers, safe for the console to import: no\n * theme compiler, no network.\n */\n\n/** A font pairing the look may choose: a heading family over a body family. */\nexport interface AiSiteFontPairing {\n id: string\n /** What the pairing reads like, as the model is told. */\n feel: string\n heading: { family: string; category: 'sans-serif' | 'serif'; weight: number; sub: number }\n body: { family: string; category: 'sans-serif' | 'serif'; weights: number[] }\n /** Letter spacing the headings carry, in em. */\n tracking?: number\n /** Headings set in capitals: a condensed display face. */\n caps?: boolean\n}\n\n/**\n * The pairings, every family from the Google Fonts catalog the fonts plugin\n * serves (`google-fonts.catalog.json`) and every weight one that family\n * has — `ai-site-look.spec.ts` holds both. The tenant loads them the way it\n * loads the starter theme's family, so nothing here adds a font host.\n */\nexport const AI_SITE_FONT_PAIRINGS: readonly AiSiteFontPairing[] = [\n { id: 'jakarta', feel: 'modern, friendly sans', heading: { family: 'Plus Jakarta Sans', category: 'sans-serif', weight: 800, sub: 700 }, body: { family: 'Plus Jakarta Sans', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'inter', feel: 'neutral, precise sans', heading: { family: 'Inter', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.025 },\n { id: 'grotesk', feel: 'designer grotesk', heading: { family: 'Space Grotesk', category: 'sans-serif', weight: 600, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.03 },\n { id: 'syne', feel: 'expressive, art-school display', heading: { family: 'Syne', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'bricolage', feel: 'contemporary, characterful sans', heading: { family: 'Bricolage Grotesque', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'DM Sans', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.025 },\n { id: 'editorial', feel: 'editorial serif over clean sans', heading: { family: 'Playfair Display', category: 'serif', weight: 700, sub: 600 }, body: { family: 'Source Sans 3', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n { id: 'fraunces', feel: 'warm, soft serif', heading: { family: 'Fraunces', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.015 },\n { id: 'instrument', feel: 'elegant, light serif headlines', heading: { family: 'Instrument Serif', category: 'serif', weight: 400, sub: 400 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n { id: 'reading', feel: 'reading-first serif, serif body', heading: { family: 'Newsreader', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Source Serif 4', category: 'serif', weights: [400, 600, 700] }, tracking: -0.01 },\n { id: 'garamond', feel: 'refined, classic serif', heading: { family: 'Cormorant Garamond', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Montserrat', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'baskerville', feel: 'established, trustworthy serif', heading: { family: 'Libre Baskerville', category: 'serif', weight: 700, sub: 700 }, body: { family: 'Source Sans 3', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'merriweather', feel: 'sturdy, readable serif', heading: { family: 'Merriweather', category: 'serif', weight: 700, sub: 700 }, body: { family: 'Lato', category: 'sans-serif', weights: [400, 700] } },\n { id: 'lora', feel: 'gentle, calm serif', heading: { family: 'Lora', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Open Sans', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'dmserif', feel: 'polished display serif', heading: { family: 'DM Serif Display', category: 'serif', weight: 400, sub: 400 }, body: { family: 'DM Sans', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'oswald', feel: 'bold, condensed, workmanlike', heading: { family: 'Oswald', category: 'sans-serif', weight: 600, sub: 500 }, body: { family: 'Roboto', category: 'sans-serif', weights: [400, 500, 700] }, caps: true, tracking: 0.01 },\n { id: 'archivo', feel: 'heavy, high-impact sans', heading: { family: 'Archivo Black', category: 'sans-serif', weight: 400, sub: 400 }, body: { family: 'Archivo', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n { id: 'barlow', feel: 'athletic, condensed sans', heading: { family: 'Barlow Condensed', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Barlow', category: 'sans-serif', weights: [400, 500, 600, 700] }, caps: true, tracking: 0.01 },\n { id: 'anton', feel: 'loud poster display', heading: { family: 'Anton', category: 'sans-serif', weight: 400, sub: 400 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, caps: true, tracking: 0.01 },\n { id: 'nunito', feel: 'rounded, approachable sans', heading: { family: 'Nunito', category: 'sans-serif', weight: 800, sub: 700 }, body: { family: 'Nunito Sans', category: 'sans-serif', weights: [400, 600, 700] } },\n { id: 'quicksand', feel: 'soft, airy rounded sans', heading: { family: 'Quicksand', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Nunito Sans', category: 'sans-serif', weights: [400, 600, 700] } },\n { id: 'manrope', feel: 'crisp, confident sans', heading: { family: 'Manrope', category: 'sans-serif', weight: 800, sub: 700 }, body: { family: 'Manrope', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'outfit', feel: 'geometric, upbeat sans', heading: { family: 'Outfit', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Outfit', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'plex', feel: 'technical, engineered sans', heading: { family: 'IBM Plex Sans', category: 'sans-serif', weight: 600, sub: 600 }, body: { family: 'IBM Plex Sans', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n]\n\nexport type AiSiteFontPairingId = string\n\n/**\n * The platform's built-in themes a site's look is layered on, by the short\n * name of the themes plugin's preset id (\\`theme-presets.<name>\\`), and\n * \\`starter\\`: the theme a new site is born with (AGL-3497).\n */\nexport const AI_SITE_BASES = [\n 'starter',\n 'material-ui',\n 'bootstrap',\n 'minimal',\n 'material3',\n 'ant-design',\n 'fluent',\n 'carbon',\n 'cupertino',\n] as const\nexport type AiSiteBase = (typeof AI_SITE_BASES)[number]\n\n/** How saturated a kind's palette runs. `neutral` is an ink-and-paper ground with one accent. */\nexport type AiSiteChroma = 'neutral' | 'muted' | 'balanced' | 'vivid'\n/** The page ground the light scheme sits on. */\nexport type AiSiteGround = 'white' | 'warm' | 'cool' | 'tinted'\nexport const AI_SITE_GROUNDS: readonly AiSiteGround[] = ['white', 'warm', 'cool', 'tinted']\n/** Corner rounding, cards and fields. */\nexport type AiSiteCorners = 'sharp' | 'soft' | 'round' | 'pill'\nexport const AI_SITE_CORNERS: readonly AiSiteCorners[] = ['sharp', 'soft', 'round', 'pill']\n/** How buttons are drawn: on the corner radius, as pills, square, in capitals, or with quiet buttons as underlined links. */\nexport type AiSiteButtons = 'rounded' | 'pill' | 'square' | 'caps' | 'link'\n/**\n * How a site's pages alternate their bands: calm (mostly plain, one soft),\n * alternating (plain and soft by turns), or bold (brand and dark bands for\n * its key moments).\n */\nexport type AiSiteRhythm = 'calm' | 'alternating' | 'bold'\nexport const AI_SITE_RHYTHMS: readonly AiSiteRhythm[] = ['calm', 'alternating', 'bold']\n\n/** Spacing: tighter, regular or airier than the platform's unit. */\nexport type AiSiteDensity = 'compact' | 'regular' | 'airy'\n\n/** What the code applies for a kind: the bounds a look is chosen and varied in. */\nexport interface AiSiteLookFamily {\n /** The platform's base themes that suit the kind, best first (`AI_SITE_BASES`). */\n bases: readonly AiSiteBase[]\n chroma: AiSiteChroma\n /** How the header is arranged: the brand at the start with the links after it, or both centered. */\n headerAligns?: readonly ('start' | 'center')[]\n /** The band rhythm its pages lean to (`AI_SITE_RHYTHMS`). */\n rhythms?: readonly AiSiteRhythm[]\n /** Hue ranges in degrees that suit the kind, `[from, to]`, wrapping past 360. */\n hues: ReadonlyArray<readonly [number, number]>\n grounds: readonly AiSiteGround[]\n fonts: readonly AiSiteFontPairingId[]\n corners: readonly AiSiteCorners[]\n buttons: AiSiteButtons\n /** Display and heading sizes against the platform's, 1 = as shipped. */\n headingScale: number\n density: AiSiteDensity\n}\n\nexport interface AiSiteKind {\n /** A persisted identifier: the guided start's answer and the job's `siteKind` input. */\n id: string\n /** The card's title, in customer copy. */\n label: string\n /** One line under it. */\n blurb: string\n /** A word from the icon set the card shows. */\n icon: string\n /**\n * Specific nouns and phrases that name this kind on their own (\"roofer\",\n * \"law firm\", \"food bank\"), matched whole and singular or plural. One is\n * enough to pick the kind ({@link aiSiteKindFor}).\n */\n keywords: readonly string[]\n /**\n * Generic words that only lean toward this kind (\"club\", \"studio\",\n * \"classes\", \"shop\"): they add a little weight, break a tie, and never pick\n * a narrow kind on their own.\n */\n hints: readonly string[]\n /** The starter whose shape this kind follows, where one fits (`STARTER_TEMPLATES`). */\n starter: string\n look: AiSiteLookFamily\n /** How its pages are arranged, as every page and the header and footer are told. */\n design: string\n /** The pages it usually has, as the plan is told. */\n pages: string\n}\n\nconst ALL_HUES: ReadonlyArray<readonly [number, number]> = [[0, 360]]\n\n/**\n * The kinds, in the order the guided start shows them. Drawn from the template\n * categories the large site builders offer, merged where two would build the\n * same site: designer and agency are one studio, law and accounting one\n * practice, health and therapy one wellness kind.\n */\nexport const AI_SITE_KINDS: readonly AiSiteKind[] = [\n {\n id: 'business',\n label: 'Business & services',\n blurb: 'Say what you do, why choose you, and how to reach you',\n icon: 'briefcase',\n keywords: ['cleaning service', 'cleaning company', 'house cleaning', 'cleaner', 'janitorial', 'maid', 'groomer', 'grooming', 'dog walker', 'dog walking', 'pet sitter', 'pet sitting', 'dog trainer', 'dog training', 'staffing', 'print shop', 'printing', 'courier', 'laundromat', 'dry cleaner', 'tailor', 'alterations', 'car wash', 'detailing', 'small business'],\n hints: ['business', 'company', 'service', 'local', 'pet', 'dog', 'cleaning', 'customers'],\n starter: 'business',\n look: { bases: ['starter', 'material3', 'fluent', 'minimal', 'ant-design'], chroma: 'balanced', hues: ALL_HUES, grounds: ['white', 'cool', 'warm', 'tinted'], fonts: ['jakarta', 'manrope', 'outfit', 'inter', 'bricolage', 'fraunces'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1, density: 'regular' },\n design: 'Clear and confident: say plainly what the business does and for whom, draw what it offers as cards or a ruled list, and let a photo carry a section that describes the place or the work. Mix plain and soft bands with one brand band where the page most needs it.',\n pages: 'Home, Services, About and Contact are typical; a pricing or booking page where the brief asks for one.',\n },\n {\n id: 'trades',\n label: 'Home services & trades',\n blurb: 'Roofers, plumbers, towing, landscaping: bold, direct, built on trust',\n icon: 'wrench',\n keywords: ['roofer', 'roofing', 'plumber', 'plumbing', 'electrician', 'electrical', 'hvac', 'heating and cooling', 'towing', 'tow truck', 'roadside assistance', 'landscaping', 'landscaper', 'lawn care', 'contractor', 'general contractor', 'construction', 'handyman', 'house painter', 'house painting', 'movers', 'moving company', 'exterminator', 'pest control', 'remodeling', 'renovation', 'mechanic', 'auto repair', 'auto body', 'locksmith', 'flooring', 'fencing', 'pool cleaning', 'pool service', 'welder', 'welding', 'carpenter', 'carpentry', 'masonry', 'concrete', 'drywall', 'gutter', 'siding', 'garage door', 'tree service', 'arborist', 'junk removal', 'septic', 'pressure washing', 'power washing', 'appliance repair'],\n hints: ['repair', 'auto', 'garage', 'painting', 'painter', 'pool', 'moving', 'trade', 'trades', 'homeowner', 'pest', 'installation', 'emergency'],\n starter: 'business',\n look: { bases: ['bootstrap', 'carbon', 'material-ui', 'fluent', 'starter'], chroma: 'vivid', hues: [[4, 18], [20, 38], [42, 56], [128, 158], [195, 212], [214, 240]], grounds: ['white', 'cool'], fonts: ['oswald', 'archivo', 'barlow', 'manrope'], corners: ['sharp', 'soft'], buttons: 'square', headingScale: 1.05, density: 'compact' },\n design: 'Direct and high-contrast: a big promise and a call-to-action button in the first section, services as a tight grid, trust only as the brief gives it (licensed, insured, years, guarantees), and short, practical copy. Use a dark band and a brand band.',\n pages: 'Home, Services, About or Why us, and a Quote or Contact page with the form.',\n },\n {\n id: 'professional',\n label: 'Law, finance & consulting',\n blurb: 'Law firms, accountants, advisers: calm, established, credible',\n icon: 'scale',\n keywords: ['law', 'law firm', 'lawyer', 'attorney', 'legal', 'paralegal', 'accountant', 'accounting', 'cpa', 'tax', 'bookkeeping', 'bookkeeper', 'financial', 'financial advisor', 'wealth management', 'advisor', 'adviser', 'advisory', 'consulting', 'consultant', 'insurance', 'notary', 'mediator', 'mediation', 'estate planning'],\n hints: ['firm', 'practice', 'clients', 'compliance'],\n starter: 'business',\n look: { bases: ['carbon', 'fluent', 'minimal', 'starter'], chroma: 'muted', hues: [[210, 250], [340, 360], [0, 15], [150, 175]], grounds: ['white', 'warm', 'cool'], fonts: ['baskerville', 'merriweather', 'editorial', 'plex', 'lora'], corners: ['sharp', 'soft'], buttons: 'rounded', headingScale: 0.95, density: 'airy' },\n design: 'Measured and credible: generous space, calm statements, practice areas with short plain explanations, and an unhurried tone with no hard sell. Prefer plain and soft bands, at most one dark band.',\n pages: 'Home, Practice areas or Services, About or Our team, and Contact with a consultation form.',\n },\n {\n id: 'wellness',\n label: 'Health & wellness',\n blurb: 'Therapists, clinics, dentists, coaches: warm, reassuring, clear',\n icon: 'heart',\n keywords: ['therapist', 'therapy', 'counselor', 'counseling', 'counselling', 'psychologist', 'psychiatrist', 'psychotherapy', 'dentist', 'dental', 'orthodontist', 'clinic', 'doctor', 'physician', 'pediatrician', 'optometrist', 'chiropractor', 'chiropractic', 'massage', 'wellness', 'nutrition', 'nutritionist', 'dietitian', 'acupuncture', 'physio', 'physiotherapy', 'physical therapy', 'mental health', 'medical', 'vet', 'veterinary', 'veterinarian', 'animal hospital', 'midwife', 'doula', 'naturopath', 'life coach', 'health coach', 'wellness coach', 'home care', 'senior care'],\n hints: ['health', 'healing', 'coach', 'coaching', 'patient', 'care', 'practice', 'mental', 'anxiety'],\n starter: 'business',\n look: { bases: ['material3', 'cupertino', 'starter', 'fluent'], chroma: 'muted', hues: [[150, 200], [250, 290], [20, 40], [90, 130]], grounds: ['warm', 'tinted', 'white'], fonts: ['lora', 'fraunces', 'quicksand', 'dmserif', 'nunito'], corners: ['round', 'pill'], buttons: 'pill', headingScale: 1, density: 'airy' },\n design: 'Reassuring and gentle: warm words that name who it helps, soft cards, answers in plain language, and a low-pressure tone in every call to action. Prefer soft bands, avoid dark ones.',\n pages: 'Home, Services or Approach, About, and Book or Contact with the form.',\n },\n {\n id: 'restaurant',\n label: 'Restaurant & café',\n blurb: 'Warm, photo-led pages for food, drink and a place to visit',\n icon: 'utensils',\n keywords: ['restaurant', 'cafe', 'coffee', 'coffee shop', 'coffee house', 'bakery', 'baker', 'pastry', 'cake', 'cupcake', 'bistro', 'diner', 'pizzeria', 'pizza', 'catering', 'caterer', 'brewery', 'winery', 'wine bar', 'distillery', 'taproom', 'food truck', 'deli', 'chef', 'personal chef', 'tavern', 'pub', 'eatery', 'tea room', 'tea house', 'ice cream', 'creamery', 'donut', 'bagel', 'taqueria', 'sushi', 'bbq', 'barbecue', 'ramen', 'cocktail', 'juice bar', 'brunch'],\n hints: ['food', 'kitchen', 'bar', 'tea', 'truck', 'breakfast', 'lunch', 'dinner', 'dining', 'menu', 'drinks', 'meal', 'wine', 'beer'],\n starter: 'business',\n look: { bases: ['material3', 'starter', 'cupertino'], chroma: 'balanced', hues: [[0, 45], [80, 150], [330, 360]], grounds: ['warm', 'tinted'], fonts: ['fraunces', 'editorial', 'dmserif', 'garamond', 'bricolage'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1.1, density: 'regular' },\n design: 'Photo-led and inviting: large images of the food and the room, the menu as lines rather than cards where it fits, and warm, sensory copy. Use images generously and a warm brand band.',\n pages: 'Home, Menu, About or Our story, and Visit or Reserve with the form.',\n },\n {\n id: 'store',\n label: 'Online store',\n blurb: 'Product-first pages for things you sell',\n icon: 'bag',\n keywords: ['online store', 'online shop', 'web shop', 'boutique', 'ecommerce', 'e-commerce', 'merch', 'merchandise', 'jewelry', 'jewellery', 'clothing', 'apparel', 'candle', 'soap', 'etsy', 'gift shop', 'bookstore', 'bookshop', 'florist', 'flower shop', 'plant shop', 'retail', 'wholesale', 'subscription box', 'thrift', 'sneakers'],\n hints: ['store', 'shop', 'market', 'product', 'sell', 'selling', 'buy', 'order', 'brand', 'handmade', 'goods', 'gifts', 'collection', 'shipping'],\n starter: 'physical-shop',\n look: { bases: ['minimal', 'cupertino', 'material3'], chroma: 'balanced', hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['inter', 'outfit', 'manrope', 'dmserif', 'syne'], corners: ['soft', 'sharp', 'round'], buttons: 'pill', headingScale: 1, density: 'regular' },\n design: 'A storefront, like a designer shop theme: a hero that sells, its picture the product itself and its first button Shop all; the bestsellers, which the platform lists with their photos, prices and add to cart; the range by collection as picture tiles; the brand story beside a photo; why buy here as three or four short items each with an icon (shipping, small batch, returns, only as the brief gives them); the store\\'s customer reviews, which the platform shows once shoppers leave them; and a newsletter sign-up. Keep copy short and let images lead; never draw the products themselves as cards of your own, and never a band of text alone.',\n pages: 'Home as a storefront: a hero, then sections named \"Bestsellers\", \"Shop by collection\" (3 or 4 items), the story, why buy here (3 or 4 items) and \"Customer reviews\", in the order given above, with \"Newsletter sign-up\" last. Shop at /shop: a short title section, then \"Product grid\" second (the platform lists the real products there, with sort, filters, photos, prices and the cart). About, and Contact. Plan no checkout or cart page.',\n },\n {\n id: 'portfolio',\n label: 'Portfolio',\n blurb: 'Minimal, image-led pages that put the work first',\n icon: 'grid',\n keywords: ['portfolio', 'illustrator', 'illustration', 'artist', 'visual artist', 'architect', 'architecture', 'software engineer', 'developer', 'copywriter', 'animator', 'freelance', 'freelancer', 'ceramics', 'ceramicist', 'potter', 'pottery', 'sculptor', 'sculpture', 'woodworker', 'woodworking', 'printmaker', 'textile artist'],\n hints: ['art', 'maker', 'work', 'gallery', 'painter', 'paintings', 'commissions', 'writer', 'engineer', 'projects'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'cupertino', 'carbon'], chroma: 'neutral', hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['inter', 'grotesk', 'syne', 'instrument'], corners: ['sharp', 'soft'], buttons: 'square', headingScale: 1.3, density: 'airy' },\n design: 'Minimal and image-led: a large, short statement as the title, the work as image cards with one-line captions, and very few words elsewhere. Mostly plain bands, lots of space, big type, one accent color.',\n pages: 'Home with selected work, Work or Projects, About, and Contact.',\n },\n {\n id: 'studio',\n label: 'Design studio & agency',\n blurb: 'Bold type and case studies for creative teams',\n icon: 'sparkle',\n keywords: ['design studio', 'creative studio', 'creative agency', 'design agency', 'marketing agency', 'digital agency', 'ad agency', 'branding agency', 'branding', 'brand identity', 'marketing', 'digital marketing', 'advertising', 'web design', 'web designer', 'web development', 'graphic design', 'graphic designer', 'motion design', 'video production', 'production company', 'animation', 'seo'],\n hints: ['agency', 'design', 'designer', 'creative', 'studio', 'digital', 'web', 'video', 'production', 'brand', 'campaign', 'case studies'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'carbon', 'cupertino'], chroma: 'neutral', hues: ALL_HUES, grounds: ['white', 'cool'], fonts: ['syne', 'grotesk', 'bricolage', 'inter'], corners: ['sharp', 'soft'], buttons: 'pill', headingScale: 1.3, density: 'airy' },\n design: 'Confident and editorial: oversized statements, case studies as large image cards with the outcome in a line, services as a short list, and a bold dark band where the page needs weight.',\n pages: 'Home, Work or Case studies, Services, About, and Contact or Start a project.',\n },\n {\n id: 'photography',\n label: 'Photography',\n blurb: 'Galleries first, words second',\n icon: 'camera',\n keywords: ['photographer', 'photography', 'videographer', 'videography', 'wedding photographer', 'wedding photography', 'portrait', 'headshot', 'photo studio', 'photo booth'],\n hints: ['photo', 'gallery', 'shoot', 'sessions', 'prints', 'camera'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'cupertino', 'carbon'], chroma: 'neutral', hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['instrument', 'garamond', 'inter', 'grotesk'], corners: ['sharp'], buttons: 'square', headingScale: 1.2, density: 'airy' },\n design: 'Gallery-first: full images, galleries as image cards by subject, few words, packages only as the brief gives them. Many images, mostly plain bands and one dark band.',\n pages: 'Home, Galleries or Portfolio, About, and Book or Contact with the form.',\n },\n {\n id: 'blog',\n label: 'Blog & writing',\n blurb: 'Reading-first pages with a calm serif voice',\n icon: 'book',\n keywords: ['blog', 'blogger', 'food blog', 'travel blog', 'journal', 'magazine', 'newsletter', 'podcast', 'podcaster', 'essays', 'author', 'novelist', 'poet', 'poetry', 'publication', 'zine', 'columnist', 'substack'],\n hints: ['writing', 'stories', 'reading', 'readers', 'articles', 'posts', 'recipes', 'reviews', 'guides', 'tips', 'writer', 'episodes', 'listeners'],\n starter: 'business',\n look: { bases: ['minimal', 'starter', 'cupertino'], chroma: 'muted', hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['reading', 'editorial', 'instrument', 'lora'], corners: ['sharp', 'soft'], buttons: 'rounded', headingScale: 1.05, density: 'airy' },\n design: 'Reading-first: a narrow, calm measure, writing as cards with a title and a one-line summary, topics as a list, and a quiet, personal voice. Mostly plain bands.',\n pages: 'Home, Articles presenting the writing as cards, About, and Subscribe or Contact. Posts themselves are added in Data as a collection, so plan the articles page as an introduction and a few featured cards.',\n },\n {\n id: 'events',\n label: 'Events & weddings',\n blurb: 'Dates, places and the details guests need',\n icon: 'calendar',\n keywords: ['wedding', 'conference', 'festival', 'gala', 'summit', 'event venue', 'wedding venue', 'venue', 'event planner', 'wedding planner', 'event planning', 'reunion', 'trade show', 'expo', 'hackathon', 'convention', 'birthday party', 'banquet', 'party rentals'],\n hints: ['event', 'party', 'meetup', 'retreat', 'workshop', 'planner', 'rsvp', 'tickets', 'celebration', 'guests', 'schedule', 'concert', 'fundraiser'],\n starter: 'landing',\n look: { bases: ['material3', 'cupertino', 'starter'], chroma: 'balanced', hues: [[320, 360], [0, 30], [250, 290], [140, 170], [40, 55]], grounds: ['warm', 'tinted', 'white'], fonts: ['garamond', 'editorial', 'dmserif', 'anton', 'syne'], corners: ['soft', 'round'], buttons: 'pill', headingScale: 1.2, density: 'regular' },\n design: 'Celebratory and clear: the name and what it is in big type, when and where only as the brief gives them, the schedule as steps, and the details guests ask about as an FAQ. One brand band.',\n pages: 'Home, Schedule or Details, Travel or Venue where the brief names one, and RSVP or Register with the form.',\n },\n {\n id: 'fitness',\n label: 'Fitness & sports',\n blurb: 'Gyms, trainers and studios with energy',\n icon: 'bolt',\n keywords: ['gym', 'fitness', 'personal trainer', 'personal training', 'trainer', 'crossfit', 'boxing', 'kickboxing', 'martial arts', 'martial', 'karate', 'judo', 'jiu jitsu', 'taekwondo', 'mma', 'pilates', 'bootcamp', 'boot camp', 'sports', 'sport', 'running', 'runner', 'marathon', 'triathlon', 'cycling', 'climbing', 'bouldering', 'dance', 'swim', 'swimming', 'soccer', 'football', 'basketball', 'baseball', 'softball', 'volleyball', 'tennis', 'pickleball', 'golf', 'hockey', 'rugby', 'lacrosse', 'wrestling', 'gymnastics', 'athletics', 'athlete', 'strength training', 'weightlifting', 'powerlifting', 'health club', 'league'],\n hints: ['training', 'team', 'workout', 'coach', 'coaching', 'studio', 'members', 'race', 'game', 'tournament'],\n starter: 'business',\n look: { bases: ['bootstrap', 'material-ui', 'carbon', 'material3'], chroma: 'vivid', hues: [[0, 30], [90, 140], [180, 210], [270, 300]], grounds: ['white', 'cool'], fonts: ['barlow', 'anton', 'archivo', 'outfit'], corners: ['sharp', 'soft'], buttons: 'caps', headingScale: 1.15, density: 'compact' },\n design: 'High-energy: punchy headlines, strong buttons, classes or programs as cards and short, motivating copy. Use a dark band and a brand band.',\n pages: 'Home, Classes or Programs, About or Coaches, and Join or Contact with the form.',\n },\n {\n id: 'yoga',\n label: 'Yoga & mindfulness',\n blurb: 'Calm, spacious pages for classes and retreats',\n icon: 'leaf',\n keywords: ['yoga', 'meditation', 'mindfulness', 'breathwork', 'reiki', 'sound bath', 'sound healing', 'tai chi', 'qigong'],\n hints: ['retreat', 'spa', 'calm', 'studio', 'healing', 'stillness'],\n starter: 'business',\n look: { bases: ['material3', 'cupertino', 'starter', 'fluent'], chroma: 'muted', hues: [[20, 50], [80, 150], [260, 300], [170, 200]], grounds: ['warm', 'tinted'], fonts: ['garamond', 'lora', 'quicksand', 'instrument', 'fraunces'], corners: ['round', 'pill'], buttons: 'pill', headingScale: 1.05, density: 'airy' },\n design: 'Calm and spacious: quiet headlines, classes as soft cards, gentle copy and lots of space. Soft bands, no dark band.',\n pages: 'Home, Classes or Schedule, About, and Book or Contact with the form.',\n },\n {\n id: 'beauty',\n label: 'Beauty & salon',\n blurb: 'Salons, barbers, spas and studios with style',\n icon: 'scissors',\n keywords: ['salon', 'hair salon', 'hair', 'hairdresser', 'hairstylist', 'barber', 'barbershop', 'nails', 'nail salon', 'beauty', 'makeup', 'lashes', 'brows', 'esthetician', 'aesthetician', 'skincare', 'skin care', 'facial', 'waxing', 'tattoo', 'piercing', 'stylist', 'spa', 'day spa', 'med spa', 'blowout'],\n hints: ['studio', 'glam', 'appointments', 'cosmetics'],\n starter: 'business',\n look: { bases: ['material3', 'cupertino', 'minimal'], chroma: 'balanced', hues: [[320, 360], [0, 25], [270, 300], [20, 45]], grounds: ['warm', 'tinted', 'white'], fonts: ['garamond', 'dmserif', 'instrument', 'outfit', 'syne'], corners: ['round', 'pill', 'sharp'], buttons: 'pill', headingScale: 1.1, density: 'regular' },\n design: 'Stylish and image-led: striking images, services as a menu or cards, the look and feel of the place in pictures, and booking made obvious. One brand band.',\n pages: 'Home, Services, About or The team, and Book or Contact with the form.',\n },\n {\n id: 'realestate',\n label: 'Real estate',\n blurb: 'Agents, brokers and property: polished and local',\n icon: 'home',\n keywords: ['real estate', 'realtor', 'realty', 'brokerage', 'broker', 'property', 'property management', 'rentals', 'apartment', 'mortgage', 'airbnb', 'vacation rental', 'short term rental', 'listings', 'condo', 'home builder', 'homebuilder'],\n hints: ['homes', 'house', 'buyers', 'sellers', 'vacation', 'cabin', 'neighborhoods', 'investors'],\n starter: 'business',\n look: { bases: ['fluent', 'minimal', 'carbon'], chroma: 'muted', hues: [[200, 240], [150, 180], [20, 45], [0, 360]], grounds: ['white', 'warm', 'cool'], fonts: ['dmserif', 'manrope', 'editorial', 'outfit'], corners: ['soft', 'sharp'], buttons: 'rounded', headingScale: 1.05, density: 'regular' },\n design: 'Polished and local: image-led sections, the areas served by name only as the brief gives them, listings only as image cards the owner fills in, and confident, local copy. One dark band.',\n pages: 'Home, Buy or Listings, Sell, About, and Contact with the form.',\n },\n {\n id: 'education',\n label: 'Courses & education',\n blurb: 'Tutors, schools and courses, clear and encouraging',\n icon: 'school',\n keywords: ['course', 'online course', 'school', 'tutoring', 'tutor', 'teacher', 'teaching', 'lessons', 'academy', 'education', 'educational', 'learning', 'daycare', 'day care', 'preschool', 'kindergarten', 'music lessons', 'piano lessons', 'driving school', 'driving lessons', 'language school', 'coding bootcamp', 'curriculum', 'homeschool', 'montessori', 'summer camp'],\n hints: ['classes', 'students', 'learn', 'kids', 'training', 'camp', 'workshop', 'beginners'],\n starter: 'business',\n look: { bases: ['material3', 'ant-design', 'material-ui'], chroma: 'balanced', hues: [[200, 240], [140, 170], [30, 50], [260, 290]], grounds: ['white', 'tinted', 'cool'], fonts: ['nunito', 'outfit', 'jakarta', 'lora', 'manrope'], corners: ['round', 'soft'], buttons: 'rounded', headingScale: 1, density: 'regular' },\n design: 'Clear and encouraging: who it is for and the result they get in plain words, courses or subjects as cards, steps where something happens in order, and an FAQ where people have questions.',\n pages: 'Home, Courses or Lessons, About or Teachers, and Enroll or Contact with the form.',\n },\n {\n id: 'nonprofit',\n label: 'Nonprofit & community',\n blurb: 'A cause, its impact and how to help',\n icon: 'hands',\n keywords: ['nonprofit', 'non-profit', 'charity', 'charitable', 'foundation', 'church', 'parish', 'congregation', 'mosque', 'synagogue', 'temple', 'ministry', 'food bank', 'food pantry', 'pantry', 'shelter', 'animal shelter', 'animal rescue', 'rescue', 'volunteer', 'association', 'homeowners association', 'neighborhood association', 'hoa', 'pta', 'pto', 'parent teacher association', 'ngo', 'donate', 'donation', 'fundraising', 'mutual aid', 'community center', 'senior center', 'makerspace', 'hackerspace', 'guild', 'rotary', 'advocacy', 'coalition', 'civic', 'veterans'],\n hints: ['community', 'club', 'group', 'troupe', 'circle', 'society', 'collective', 'members', 'neighbors', 'neighborhood', 'join', 'meetup', 'gathering', 'mission', 'cause', 'together', 'fellowship', 'faith', 'fundraiser', 'residents', 'families'],\n starter: 'business',\n look: { bases: ['material3', 'fluent', 'starter'], chroma: 'balanced', hues: [[130, 200], [20, 45], [200, 230], [340, 360]], grounds: ['white', 'warm'], fonts: ['merriweather', 'lora', 'jakarta', 'fraunces', 'nunito'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1.05, density: 'regular' },\n design: 'Mission-led: the cause in one strong line, what the organization does as cards, how to help as steps (volunteer, give, spread the word), and hopeful, concrete copy. A brand band for the call to help.',\n pages: 'Home, Our work or Programs, About, and Get involved or Contact with the form.',\n },\n {\n id: 'music',\n label: 'Music & bands',\n blurb: 'Artists, bands and DJs, loud and visual',\n icon: 'music',\n keywords: ['band', 'musician', 'music', 'dj', 'singer', 'songwriter', 'singer-songwriter', 'rapper', 'music producer', 'recording studio', 'record label', 'orchestra', 'choir', 'composer', 'jazz', 'ensemble', 'quartet', 'pianist', 'guitarist', 'drummer', 'violinist', 'tour dates', 'album', 'live music', 'music artist', 'folk band', 'rock band', 'punk band', 'metal band', 'country band', 'bluegrass band', 'cover band', 'wedding band', 'party band', 'duo', 'trio', 'hip hop', 'hip hop artist', 'rap', 'mixtape', 'ep', 'gig', 'discography', 'setlist', 'bandcamp'],\n hints: ['folk', 'indie', 'bluegrass', 'punk', 'metal', 'record', 'concert', 'tour', 'song', 'shows', 'tracks', 'producer', 'fans', 'listen'],\n starter: 'landing',\n look: { bases: ['carbon', 'minimal', 'material-ui'], chroma: 'vivid', hues: ALL_HUES, grounds: ['white', 'cool', 'tinted'], fonts: ['anton', 'syne', 'grotesk', 'archivo'], corners: ['sharp'], buttons: 'caps', headingScale: 1.3, density: 'regular' },\n design: 'Loud and visual: the name huge, image bands, a listen section where the platform places a music player for the artist’s own tracks, releases or shows as image cards only as the brief gives them, and a short bio. Dark bands are welcome. Never name or link songs by other artists.',\n pages: 'Home, Music or Shows, About, and Booking or Contact with the form.',\n },\n {\n id: 'personal',\n label: 'Personal & resume',\n blurb: 'A simple page about you and your work',\n icon: 'person',\n keywords: ['personal site', 'personal website', 'personal page', 'personal homepage', 'about me', 'resume', 'cv', 'online resume', 'job seeker', 'job search', 'candidate', 'speaker', 'public speaker', 'link in bio'],\n hints: ['me', 'myself', 'profile', 'job', 'career', 'hire', 'recruiters'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'cupertino', 'starter', 'fluent'], chroma: 'muted', hues: ALL_HUES, grounds: ['white', 'warm', 'cool'], fonts: ['inter', 'instrument', 'manrope', 'lora', 'grotesk'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1.1, density: 'airy' },\n design: 'Simple and personal: who the person is in one line, what they do in plain words, experience or highlights as a list or steps, selected work as cards where the brief names some. Mostly plain bands.',\n pages: 'Home, About or Experience, Work where the brief names some, and Contact.',\n },\n {\n id: 'landing',\n label: 'Landing page',\n blurb: 'One page that leads to one action',\n icon: 'rocket',\n keywords: ['landing page', 'landing', 'app', 'mobile app', 'startup', 'saas', 'software', 'waitlist', 'wait list', 'ebook', 'webinar', 'lead magnet', 'product launch', 'signup page', 'sign-up page'],\n hints: ['product', 'launch', 'campaign', 'offer', 'users', 'download', 'platform', 'tool', 'beta'],\n starter: 'landing',\n look: { bases: ['material3', 'minimal', 'ant-design'], chroma: 'vivid', hues: ALL_HUES, grounds: ['white', 'cool', 'tinted'], fonts: ['outfit', 'jakarta', 'manrope', 'bricolage', 'inter'], corners: ['round', 'soft'], buttons: 'pill', headingScale: 1.15, density: 'regular' },\n design: 'One action: a strong promise and the call to action in the first section, benefits as cards, how it works as steps, objections answered as an FAQ, and the call to action repeated. A brand band where the page asks.',\n pages: 'One long home page carries the story; a second page only for the form or details the brief asks for.',\n },\n {\n id: 'coming-soon',\n label: 'Coming soon',\n blurb: 'A placeholder that collects interest',\n icon: 'clock',\n keywords: ['coming soon', 'prelaunch', 'pre-launch', 'under construction', 'placeholder', 'opening soon', 'launching soon'],\n hints: ['soon'],\n starter: 'landing',\n look: { bases: ['minimal', 'material3', 'cupertino'], chroma: 'vivid', hues: ALL_HUES, grounds: ['white', 'tinted', 'cool'], fonts: ['syne', 'anton', 'outfit', 'instrument'], corners: ['round', 'pill'], buttons: 'pill', headingScale: 1.3, density: 'airy' },\n design: 'Short and striking: what is coming in one big line, two or three reasons to care, and a way to hear first through the form. Few sections, big type.',\n pages: 'A home page that says what is coming and invites people to sign up; nothing else unless the brief asks.',\n },\n]\n\n/** A kind by id, or `null`. */\nexport function aiSiteKind(id: unknown): AiSiteKind | null {\n if (typeof id !== 'string' || !id) return null\n return AI_SITE_KINDS.find((kind) => kind.id === id) ?? null\n}\n\n/** A pairing by id, or `null`. */\nexport function aiSiteFontPairing(id: unknown): AiSiteFontPairing | null {\n if (typeof id !== 'string' || !id) return null\n return AI_SITE_FONT_PAIRINGS.find((pairing) => pairing.id === id) ?? null\n}\n\n/** One word as the classifier compares it: lower case, unaccented, singular. */\nconst stem = (word: string): string => {\n if (word.length <= 3) return word\n if (word.endsWith('ies')) return `${word.slice(0, -3)}y`\n if (/(?:ss|x|ch|sh)es$/.test(word)) return word.slice(0, -2)\n if (word.endsWith('s') && !/(?:ss|us|is)$/.test(word)) return word.slice(0, -1)\n return word\n}\n\n/** A text as the classifier's words (\"Cafés & non-profits\" → cafe, &, non, profit). */\nconst tokens = (text: string): string[] =>\n text\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/'s\\b/g, '')\n .split(/[^a-z0-9&]+/)\n .filter(Boolean)\n .map(stem)\n\n/**\n * Where the head of an answer ends: at its first punctuation or the first\n * word that starts a modifier (\"a bookstore WITH author events\", \"a food blog\n * ABOUT cooking\", \"a pottery studio: stoneware…\"). What comes before is what\n * the site IS; what follows describes it.\n */\nconst HEAD_END = /[:;,.()—–]|\\s-\\s|\\b(?:with|for|about|that|who|which|where|in|on|at|of|offering|selling|serving|near|from|by|to|booking|touring|playing|performing)\\b/i\n\n/**\n * What a match is worth. A specific one-word keyword picks a kind alone; a\n * phrase is worth more than its words (it is the more specific reading, and\n * it claims its words so \"wedding photographer\" never also counts as a\n * wedding); a hint only leans. The last keyword in the head of the answer —\n * its noun — gets a bonus, so the thing the site is beats what it mentions.\n */\nconst KEYWORD_WEIGHT = 3\nconst PHRASE_WEIGHT_PER_WORD = 2\nconst HINT_WEIGHT = 1\nconst HEAD_NOUN_BONUS = 2\n/** A generic head noun with nothing specific said: enough to clear {@link MIN_SCORE} alone, never to beat a keyword. */\nconst HEAD_HINT_BONUS = 1\n/** \"Who it's for\" describes the people, not the site, so it counts half. */\nconst AUDIENCE_SHARE = 0.5\n/** Below this no kind is meant: one stray hint is not a reason to pick a narrow vertical. */\nconst MIN_SCORE = 1.5\n\ninterface AiSiteKindTerm {\n kind: AiSiteKind\n words: readonly string[]\n weight: number\n keyword: boolean\n}\n\n/**\n * Every keyword and hint once per kind (a plural and its singular are one\n * term), longest phrase first so a phrase claims its words before they count\n * alone.\n */\nconst TERMS: readonly AiSiteKindTerm[] = AI_SITE_KINDS.flatMap((kind) => {\n const seen = new Set<string>()\n const terms: AiSiteKindTerm[] = []\n const add = (term: string, keyword: boolean) => {\n const words = tokens(term)\n const key = words.join(' ')\n if (!words.length || seen.has(key)) return\n seen.add(key)\n const weight = !keyword ? HINT_WEIGHT : words.length > 1 ? PHRASE_WEIGHT_PER_WORD * words.length : KEYWORD_WEIGHT\n terms.push({ kind, words, weight, keyword })\n }\n for (const keyword of kind.keywords) add(keyword, true)\n for (const hint of kind.hints) add(hint, false)\n return terms\n}).sort((a, b) => b.words.length - a.words.length)\n\ninterface AiSiteKindScore {\n score: number\n /** Where the kind's last match in the answer ends, in words; -1 for none. */\n at: number\n}\n\n/** One term found in a text, by word position. */\ninterface AiSiteKindMatch {\n kind: AiSiteKind\n end: number\n keyword: boolean\n}\n\n/** Adds what one text says for each kind to `scores`; returns every term it found. */\nfunction aiSiteKindScores(text: string, share: number, scores: Map<AiSiteKind, AiSiteKindScore>): AiSiteKindMatch[] {\n const words = tokens(text)\n const matches: AiSiteKindMatch[] = []\n // Words a longer term has matched; terms of one length share their words\n // (two kinds may both have \"studio\"), and a shorter term never reuses them.\n const claimed = new Array<boolean>(words.length).fill(false)\n const pending = new Set<number>()\n const counted = new Set<AiSiteKindTerm>()\n let length = 0\n for (const term of TERMS) {\n if (term.words.length !== length) {\n length = term.words.length\n for (const index of pending) claimed[index] = true\n pending.clear()\n }\n for (let start = 0; start + term.words.length <= words.length; start++) {\n if (!term.words.every((word, offset) => words[start + offset] === word && !claimed[start + offset])) continue\n const end = start + term.words.length\n for (let index = start; index < end; index++) pending.add(index)\n const entry = scores.get(term.kind) ?? { score: 0, at: -1 }\n if (!counted.has(term)) {\n counted.add(term)\n entry.score += term.weight * share\n }\n entry.at = Math.max(entry.at, end)\n scores.set(term.kind, entry)\n matches.push({ kind: term.kind, end, keyword: term.keyword })\n }\n }\n return matches\n}\n\n/**\n * The kind the head of an answer names, if any. Its last keyword when it has\n * one. When nothing specific is said anywhere, its last generic word that\n * belongs to exactly one kind: \"a pet store\" is a store, \"a writers group\" a\n * community, \"a cooking class studio\" a class (studio says nothing, since\n * four kinds share it). A generic word outside the head never counts here.\n */\nfunction aiSiteHeadKind(head: readonly AiSiteKindMatch[], specific: boolean): AiSiteKind | null {\n const keywords = head.filter((match) => match.keyword)\n if (keywords.length) return keywords.reduce((last, match) => (match.end > last.end ? match : last)).kind\n if (specific) return null\n const ends = [...new Set(head.map((match) => match.end))].sort((a, b) => b - a)\n for (const end of ends) {\n const kinds = new Set(head.filter((match) => match.end === end).map((match) => match.kind))\n if (kinds.size === 1) return [...kinds][0] as AiSiteKind\n }\n return null\n}\n\n/**\n * The kind a \"what kind of site\" answer suggests, read with \"who it's for\"\n * when there is one: the card the guided start selects until the person\n * picks another. Deterministic and local, no model call (AGL-3660).\n *\n * Every kind scores what it finds. A specific keyword (\"roofer\", \"food bank\")\n * is enough alone; a phrase outweighs its words and claims them (\"wedding\n * photographer\" is photography, not events); a generic hint (\"club\",\n * \"studio\", \"classes\", \"shop\") only leans, so \"a neighborhood book club\" is\n * community, built from club + neighborhood + meetups + neighbors, and never\n * fitness on \"club\". The head noun — the last keyword before the answer's\n * first modifier — earns a bonus (\"a bookstore with author events\" is a\n * store); when the answer and audience name nothing specific, a generic head\n * noun that only one kind has may decide (\"a bike shop\" is a store, \"a hiking\n * group\" a community). The audience counts half. The highest score wins; of two equal,\n * the one named later, since English puts the noun last (\"a food blog\" is a\n * blog). Tricky ones, decided: a band that sells merch is music (the band is\n * the head and the merch only a mention); booking a DJ is music; a music\n * teacher or music lessons are education; a guitar shop or band merch store\n * is a store. A best score of no more than a stray hint, or a tie that order\n * cannot settle, is `business`, the most general kind.\n */\nexport function aiSiteKindFor(siteType: string, audience = ''): AiSiteKind {\n const general = AI_SITE_KINDS[0] as AiSiteKind\n const scores = new Map<AiSiteKind, AiSiteKindScore>()\n const found = aiSiteKindScores(siteType, 1, scores)\n const fromAudience = new Map<AiSiteKind, AiSiteKindScore>()\n if (audience) found.push(...aiSiteKindScores(audience, AUDIENCE_SHARE, fromAudience))\n const head = aiSiteKindScores(siteType.split(HEAD_END)[0] ?? '', 0, new Map())\n const headKind = aiSiteHeadKind(head, found.some((match) => match.keyword))\n const headEntry = headKind ? scores.get(headKind) : undefined\n if (headEntry) headEntry.score += head.some((match) => match.keyword) ? HEAD_NOUN_BONUS : HEAD_HINT_BONUS\n for (const [kind, { score }] of fromAudience) {\n const entry = scores.get(kind) ?? { score: 0, at: -1 }\n entry.score += score\n scores.set(kind, entry)\n }\n let best: { kind: AiSiteKind; score: number; at: number } | null = null\n let tied = false\n for (const [kind, { score, at }] of scores) {\n if (!best || score > best.score || (score === best.score && at > best.at)) {\n tied = false\n best = { kind, score, at }\n } else if (score === best.score && at === best.at) {\n tied = true\n }\n }\n if (!best || best.score < MIN_SCORE || tied) return general\n return best.kind\n}\n\n/** The kind a job's inputs name, else the one its business type and audience suggest; `null` for a job that names neither. */\nexport function aiSiteKindOfInputs(inputs: Readonly<Record<string, unknown>> | null | undefined): AiSiteKind | null {\n const named = aiSiteKind(inputs?.['siteKind'])\n if (named) return named\n const type = inputs?.['businessType']\n const audience = inputs?.['audience']\n return typeof type === 'string' && type.trim() ? aiSiteKindFor(type, typeof audience === 'string' ? audience : '') : null\n}\n\n/** What each band rhythm asks of a page's sections. */\nconst RHYTHM_WORDS: Record<AiSiteRhythm, string> = {\n calm: 'mostly plain bands with one soft band, and at most one brand or dark band, on whichever section most needs the weight',\n alternating: 'plain and soft bands by turns, with one brand band wherever the page needs emphasis',\n bold: 'a dark or brand band for one or two key moments anywhere on the page, and strong contrast between neighboring sections',\n}\n\n/** The site's own look tokens a unit is handed (AGL-3660), read defensively. */\nexport function aiSiteStyleTokens(\n inputs: Readonly<Record<string, unknown>> | null | undefined,\n): { headerAlign?: 'start' | 'center'; rhythm?: AiSiteRhythm } {\n const raw = inputs?.['siteStyle']\n if (!raw || typeof raw !== 'object') return {}\n const style = raw as Record<string, unknown>\n return {\n ...(style['headerAlign'] === 'start' || style['headerAlign'] === 'center' ? { headerAlign: style['headerAlign'] } : {}),\n ...(AI_SITE_RHYTHMS.includes(style['rhythm'] as AiSiteRhythm) ? { rhythm: style['rhythm'] as AiSiteRhythm } : {}),\n }\n}\n\n/** The style lines a page, the header and the footer are told for the job's kind and look; empty for none. */\nexport function aiSiteKindDesignLines(inputs: Readonly<Record<string, unknown>> | null | undefined): string[] {\n const kind = aiSiteKindOfInputs(inputs)\n const { rhythm } = aiSiteStyleTokens(inputs)\n return [\n ...(kind ? [`Style: a ${kind.label.toLowerCase()} site. ${kind.design}`] : []),\n ...(rhythm ? [`Band rhythm for this site: ${RHYTHM_WORDS[rhythm]}.`] : []),\n ]\n}\n"],"names":["AI_SITE_FONT_PAIRINGS","id","feel","heading","family","category","weight","sub","body","weights","tracking","caps","AI_SITE_BASES","AI_SITE_GROUNDS","AI_SITE_CORNERS","AI_SITE_RHYTHMS","ALL_HUES","AI_SITE_KINDS","label","blurb","icon","keywords","hints","starter","look","bases","chroma","hues","grounds","fonts","corners","buttons","headingScale","density","design","pages","aiSiteKind","find","kind","aiSiteFontPairing","pairing","stem","word","length","endsWith","slice","test","tokens","text","normalize","replace","toLowerCase","split","filter","Boolean","map","HEAD_END","KEYWORD_WEIGHT","PHRASE_WEIGHT_PER_WORD","HINT_WEIGHT","HEAD_NOUN_BONUS","HEAD_HINT_BONUS","AUDIENCE_SHARE","MIN_SCORE","TERMS","flatMap","seen","Set","terms","add","term","keyword","words","key","join","has","push","hint","sort","a","b","aiSiteKindScores","share","scores","matches","claimed","Array","fill","pending","counted","index","clear","start","every","offset","end","entry","get","score","at","Math","max","set","aiSiteHeadKind","head","specific","match","reduce","last","ends","kinds","size","aiSiteKindFor","siteType","audience","general","Map","found","fromAudience","headKind","some","headEntry","undefined","best","tied","aiSiteKindOfInputs","inputs","named","type","trim","RHYTHM_WORDS","calm","alternating","bold","aiSiteStyleTokens","raw","style","headerAlign","includes","rhythm","aiSiteKindDesignLines"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED;;;;;;;;;;;;;;;;;;;;;;;;;;CA0BC,GAED,6EAA6E;AAa7E;;;;;CAKC,GACD,OAAO,MAAMA,wBAAsD;IACjE;QAAEC,IAAI;QAAWC,MAAM;QAAyBC,SAAS;YAAEC,QAAQ;YAAqBC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAqBC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IACvP;QAAET,IAAI;QAASC,MAAM;QAAyBC,SAAS;YAAEC,QAAQ;YAASC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAASC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAM;IAC9N;QAAET,IAAI;QAAWC,MAAM;QAAoBC,SAAS;YAAEC,QAAQ;YAAiBC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAASC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IAClO;QAAET,IAAI;QAAQC,MAAM;QAAkCC,SAAS;YAAEC,QAAQ;YAAQC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAASC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IACpO;QAAET,IAAI;QAAaC,MAAM;QAAmCC,SAAS;YAAEC,QAAQ;YAAuBC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAWC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAM;IAC5P;QAAET,IAAI;QAAaC,MAAM;QAAmCC,SAAS;YAAEC,QAAQ;YAAoBC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAiBC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IACzP;QAAET,IAAI;QAAYC,MAAM;QAAoBC,SAAS;YAAEC,QAAQ;YAAYC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAASC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAM;IAC1N;QAAET,IAAI;QAAcC,MAAM;QAAkCC,SAAS;YAAEC,QAAQ;YAAoBC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAASC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IACjP;QAAET,IAAI;QAAWC,MAAM;QAAmCC,SAAS;YAAEC,QAAQ;YAAcC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAkBC,UAAU;YAASI,SAAS;gBAAC;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IACxO;QAAET,IAAI;QAAYC,MAAM;QAA0BC,SAAS;YAAEC,QAAQ;YAAsBC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAcC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;IAAE;IAC7N;QAAER,IAAI;QAAeC,MAAM;QAAkCC,SAAS;YAAEC,QAAQ;YAAqBC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAiBC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;IAAE;IAC1O;QAAER,IAAI;QAAgBC,MAAM;QAA0BC,SAAS;YAAEC,QAAQ;YAAgBC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAQC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;aAAI;QAAC;IAAE;IAC3M;QAAER,IAAI;QAAQC,MAAM;QAAsBC,SAAS;YAAEC,QAAQ;YAAQC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAaC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;IAAE;IACtM;QAAER,IAAI;QAAWC,MAAM;QAA0BC,SAAS;YAAEC,QAAQ;YAAoBC,UAAU;YAASC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAWC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;IAAE;IACvN;QAAER,IAAI;QAAUC,MAAM;QAAgCC,SAAS;YAAEC,QAAQ;YAAUC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAUC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;aAAI;QAAC;QAAGE,MAAM;QAAMD,UAAU;IAAK;IAC7O;QAAET,IAAI;QAAWC,MAAM;QAA2BC,SAAS;YAAEC,QAAQ;YAAiBC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAWC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IAC3O;QAAET,IAAI;QAAUC,MAAM;QAA4BC,SAAS;YAAEC,QAAQ;YAAoBC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAUC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGE,MAAM;QAAMD,UAAU;IAAK;IACxP;QAAET,IAAI;QAASC,MAAM;QAAuBC,SAAS;YAAEC,QAAQ;YAASC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAASC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGE,MAAM;QAAMD,UAAU;IAAK;IACtO;QAAET,IAAI;QAAUC,MAAM;QAA8BC,SAAS;YAAEC,QAAQ;YAAUC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAeC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;aAAI;QAAC;IAAE;IACpN;QAAER,IAAI;QAAaC,MAAM;QAA2BC,SAAS;YAAEC,QAAQ;YAAaC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAeC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;aAAI;QAAC;IAAE;IACvN;QAAER,IAAI;QAAWC,MAAM;QAAyBC,SAAS;YAAEC,QAAQ;YAAWC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAWC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IACnO;QAAET,IAAI;QAAUC,MAAM;QAA0BC,SAAS;YAAEC,QAAQ;YAAUC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAUC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;IACjO;QAAET,IAAI;QAAQC,MAAM;QAA8BC,SAAS;YAAEC,QAAQ;YAAiBC,UAAU;YAAcC,QAAQ;YAAKC,KAAK;QAAI;QAAGC,MAAM;YAAEJ,QAAQ;YAAiBC,UAAU;YAAcI,SAAS;gBAAC;gBAAK;gBAAK;gBAAK;aAAI;QAAC;QAAGC,UAAU,CAAC;IAAK;CAClP,CAAA;AAID;;;;CAIC,GACD,OAAO,MAAME,gBAAgB;IAC3B;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAS;AAOV,OAAO,MAAMC,kBAA2C;IAAC;IAAS;IAAQ;IAAQ;CAAS,CAAA;AAG3F,OAAO,MAAMC,kBAA4C;IAAC;IAAS;IAAQ;IAAS;CAAO,CAAA;AAS3F,OAAO,MAAMC,kBAA2C;IAAC;IAAQ;IAAe;CAAO,CAAA;AAuDvF,MAAMC,WAAqD;IAAC;QAAC;QAAG;KAAI;CAAC;AAErE;;;;;CAKC,GACD,OAAO,MAAMC,gBAAuC;IAClD;QACEhB,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAoB;YAAoB;YAAkB;YAAW;YAAc;YAAQ;YAAW;YAAY;YAAc;YAAe;YAAc;YAAe;YAAe;YAAgB;YAAY;YAAc;YAAY;YAAW;YAAc;YAAe;YAAU;YAAe;YAAY;YAAa;SAAiB;QACvWC,OAAO;YAAC;YAAY;YAAW;YAAW;YAAS;YAAO;YAAO;YAAY;SAAY;QACzFC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAa;gBAAU;gBAAW;aAAa;YAAEC,QAAQ;YAAYC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;gBAAQ;gBAAQ;aAAS;YAAEC,OAAO;gBAAC;gBAAW;gBAAW;gBAAU;gBAAS;gBAAa;aAAW;YAAEC,SAAS;gBAAC;gBAAQ;aAAQ;YAAEC,SAAS;YAAWC,cAAc;YAAGC,SAAS;QAAU;QAC7TC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAU;YAAW;YAAW;YAAY;YAAe;YAAc;YAAQ;YAAuB;YAAU;YAAa;YAAuB;YAAe;YAAc;YAAa;YAAc;YAAsB;YAAgB;YAAY;YAAiB;YAAkB;YAAU;YAAkB;YAAgB;YAAgB;YAAc;YAAc;YAAY;YAAe;YAAa;YAAa;YAAY;YAAW;YAAiB;YAAgB;YAAU;YAAW;YAAa;YAAa;YAAW;YAAY;YAAW;YAAU;YAAU;YAAe;YAAgB;YAAY;YAAgB;YAAU;YAAoB;YAAiB;SAAmB;QACrtBC,OAAO;YAAC;YAAU;YAAQ;YAAU;YAAY;YAAW;YAAQ;YAAU;YAAS;YAAU;YAAa;YAAQ;YAAgB;SAAY;QACjJC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAU;gBAAe;gBAAU;aAAU;YAAEC,QAAQ;YAASC,MAAM;gBAAC;oBAAC;oBAAG;iBAAG;gBAAE;oBAAC;oBAAI;iBAAG;gBAAE;oBAAC;oBAAI;iBAAG;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAU;gBAAW;gBAAU;aAAU;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAUC,cAAc;YAAMC,SAAS;QAAU;QAC3UC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAO;YAAY;YAAU;YAAY;YAAS;YAAa;YAAc;YAAc;YAAO;YAAO;YAAe;YAAc;YAAa;YAAqB;YAAqB;YAAW;YAAW;YAAY;YAAc;YAAc;YAAa;YAAU;YAAY;YAAa;SAAkB;QACxUC,OAAO;YAAC;YAAQ;YAAY;YAAW;SAAa;QACpDC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAU;gBAAU;gBAAW;aAAU;YAAEC,QAAQ;YAASC,MAAM;gBAAC;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAG;iBAAG;gBAAE;oBAAC;oBAAK;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAS;gBAAQ;aAAO;YAAEC,OAAO;gBAAC;gBAAe;gBAAgB;gBAAa;gBAAQ;aAAO;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAWC,cAAc;YAAMC,SAAS;QAAO;QAC9TC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAa;YAAW;YAAa;YAAc;YAAe;YAAgB;YAAgB;YAAiB;YAAW;YAAU;YAAgB;YAAU;YAAU;YAAa;YAAgB;YAAe;YAAgB;YAAgB;YAAW;YAAY;YAAa;YAAgB;YAAa;YAAe;YAAU;YAAiB;YAAoB;YAAiB;YAAW;YAAO;YAAc;YAAgB;YAAmB;YAAW;YAAS;YAAc;YAAc;YAAgB;YAAkB;YAAa;SAAc;QACnkBC,OAAO;YAAC;YAAU;YAAW;YAAS;YAAY;YAAW;YAAQ;YAAY;YAAU;SAAU;QACrGC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAa;gBAAW;aAAS;YAAEC,QAAQ;YAASC,MAAM;gBAAC;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAI;iBAAG;gBAAE;oBAAC;oBAAI;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAQ;gBAAU;aAAQ;YAAEC,OAAO;gBAAC;gBAAQ;gBAAY;gBAAa;gBAAW;aAAS;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAQC,cAAc;YAAGC,SAAS;QAAO;QACzTC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAc;YAAQ;YAAU;YAAe;YAAgB;YAAU;YAAS;YAAU;YAAQ;YAAW;YAAU;YAAS;YAAY;YAAS;YAAY;YAAW;YAAW;YAAU;YAAY;YAAc;YAAW;YAAc;YAAQ;YAAQ;YAAiB;YAAU;YAAO;YAAU;YAAY;YAAa;YAAa;YAAY;YAAS;YAAS;YAAY;YAAS;YAAO;YAAY;YAAS;YAAY;YAAa;SAAS;QACpdC,OAAO;YAAC;YAAQ;YAAW;YAAO;YAAO;YAAS;YAAa;YAAS;YAAU;YAAU;YAAQ;YAAU;YAAQ;YAAQ;SAAO;QACrIC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAW;aAAY;YAAEC,QAAQ;YAAYC,MAAM;gBAAC;oBAAC;oBAAG;iBAAG;gBAAE;oBAAC;oBAAI;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAQ;aAAS;YAAEC,OAAO;gBAAC;gBAAY;gBAAa;gBAAW;gBAAY;aAAY;YAAEC,SAAS;gBAAC;gBAAQ;aAAQ;YAAEC,SAAS;YAAWC,cAAc;YAAKC,SAAS;QAAU;QAC3SC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAgB;YAAe;YAAY;YAAY;YAAa;YAAc;YAAS;YAAe;YAAW;YAAa;YAAY;YAAW;YAAU;YAAQ;YAAQ;YAAa;YAAa;YAAY;YAAW;YAAe;YAAc;YAAU;YAAa;YAAoB;YAAU;SAAW;QAC5UC,OAAO;YAAC;YAAS;YAAQ;YAAU;YAAW;YAAQ;YAAW;YAAO;YAAS;YAAS;YAAY;YAAS;YAAS;YAAc;SAAW;QACjJC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAa;aAAY;YAAEC,QAAQ;YAAYC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAS;gBAAU;gBAAW;gBAAW;aAAO;YAAEC,SAAS;gBAAC;gBAAQ;gBAAS;aAAQ;YAAEC,SAAS;YAAQC,cAAc;YAAGC,SAAS;QAAU;QAC1QC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAa;YAAe;YAAgB;YAAU;YAAiB;YAAa;YAAgB;YAAqB;YAAa;YAAc;YAAY;YAAa;YAAc;YAAY;YAAc;YAAU;YAAW;YAAY;YAAa;YAAc;YAAe;YAAc;SAAiB;QAC1UC,OAAO;YAAC;YAAO;YAAS;YAAQ;YAAW;YAAW;YAAa;YAAe;YAAU;YAAY;SAAW;QACnHC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAa;aAAS;YAAEC,QAAQ;YAAWC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAS;gBAAW;gBAAQ;aAAa;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAUC,cAAc;YAAKC,SAAS;QAAO;QACvPC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAiB;YAAmB;YAAmB;YAAiB;YAAoB;YAAkB;YAAa;YAAmB;YAAY;YAAkB;YAAa;YAAqB;YAAe;YAAc;YAAgB;YAAmB;YAAkB;YAAoB;YAAiB;YAAoB;YAAsB;YAAa;SAAM;QAC7YC,OAAO;YAAC;YAAU;YAAU;YAAY;YAAY;YAAU;YAAW;YAAO;YAAS;YAAc;YAAS;YAAY;SAAe;QAC3IC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAU;aAAY;YAAEC,QAAQ;YAAWC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAQ;gBAAW;gBAAa;aAAQ;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAQC,cAAc;YAAKC,SAAS;QAAO;QACpPC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAgB;YAAe;YAAgB;YAAe;YAAwB;YAAuB;YAAY;YAAY;YAAgB;SAAc;QAC9KC,OAAO;YAAC;YAAS;YAAW;YAAS;YAAY;YAAU;SAAS;QACpEC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAa;aAAS;YAAEC,QAAQ;YAAWC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAc;gBAAY;gBAAS;aAAU;YAAEC,SAAS;gBAAC;aAAQ;YAAEC,SAAS;YAAUC,cAAc;YAAKC,SAAS;QAAO;QACnPC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAQ;YAAW;YAAa;YAAe;YAAW;YAAY;YAAc;YAAW;YAAa;YAAU;YAAU;YAAY;YAAQ;YAAU;YAAe;YAAQ;YAAa;SAAW;QACxNC,OAAO;YAAC;YAAW;YAAW;YAAW;YAAW;YAAY;YAAS;YAAW;YAAW;YAAU;YAAQ;YAAU;YAAY;SAAY;QACnJC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAW;aAAY;YAAEC,QAAQ;YAASC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAW;gBAAa;gBAAc;aAAO;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAWC,cAAc;YAAMC,SAAS;QAAO;QAC5PC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAW;YAAc;YAAY;YAAQ;YAAU;YAAe;YAAiB;YAAS;YAAiB;YAAmB;YAAkB;YAAW;YAAc;YAAQ;YAAa;YAAc;YAAkB;YAAW;SAAgB;QAC1QC,OAAO;YAAC;YAAS;YAAS;YAAU;YAAW;YAAY;YAAW;YAAQ;YAAW;YAAe;YAAU;YAAY;YAAW;SAAa;QACtJC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAa;aAAU;YAAEC,QAAQ;YAAYC,MAAM;gBAAC;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAG;iBAAG;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAI;iBAAG;aAAC;YAAEC,SAAS;gBAAC;gBAAQ;gBAAU;aAAQ;YAAEC,OAAO;gBAAC;gBAAY;gBAAa;gBAAW;gBAAS;aAAO;YAAEC,SAAS;gBAAC;gBAAQ;aAAQ;YAAEC,SAAS;YAAQC,cAAc;YAAKC,SAAS;QAAU;QAChUC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAO;YAAW;YAAoB;YAAqB;YAAW;YAAY;YAAU;YAAc;YAAgB;YAAW;YAAU;YAAQ;YAAa;YAAa;YAAO;YAAW;YAAY;YAAa;YAAU;YAAS;YAAW;YAAU;YAAY;YAAa;YAAW;YAAY;YAAc;YAAS;YAAQ;YAAY;YAAU;YAAY;YAAc;YAAY;YAAY;YAAc;YAAU;YAAc;YAAQ;YAAU;YAAS;YAAY;YAAa;YAAc;YAAa;YAAW;YAAqB;YAAiB;YAAgB;YAAe;SAAS;QACpnBC,OAAO;YAAC;YAAY;YAAQ;YAAW;YAAS;YAAY;YAAU;YAAW;YAAQ;YAAQ;SAAa;QAC9GC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAe;gBAAU;aAAY;YAAEC,QAAQ;YAASC,MAAM;gBAAC;oBAAC;oBAAG;iBAAG;gBAAE;oBAAC;oBAAI;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAU;gBAAS;gBAAW;aAAS;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAQC,cAAc;YAAMC,SAAS;QAAU;QAC1SC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAQ;YAAc;YAAe;YAAc;YAAS;YAAc;YAAiB;YAAW;SAAS;QAC1HC,OAAO;YAAC;YAAW;YAAO;YAAQ;YAAU;YAAW;SAAY;QACnEC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAa;gBAAW;aAAS;YAAEC,QAAQ;YAASC,MAAM;gBAAC;oBAAC;oBAAI;iBAAG;gBAAE;oBAAC;oBAAI;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAQ;aAAS;YAAEC,OAAO;gBAAC;gBAAY;gBAAQ;gBAAa;gBAAc;aAAW;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAQC,cAAc;YAAMC,SAAS;QAAO;QACxTC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAS;YAAc;YAAQ;YAAe;YAAe;YAAU;YAAc;YAAS;YAAc;YAAU;YAAU;YAAU;YAAS;YAAe;YAAgB;YAAY;YAAa;YAAU;YAAU;YAAU;YAAY;YAAW;YAAO;YAAW;YAAW;SAAU;QAClTC,OAAO;YAAC;YAAU;YAAQ;YAAgB;SAAY;QACtDC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAa;aAAU;YAAEC,QAAQ;YAAYC,MAAM;gBAAC;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAG;iBAAG;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAI;iBAAG;aAAC;YAAEC,SAAS;gBAAC;gBAAQ;gBAAU;aAAQ;YAAEC,OAAO;gBAAC;gBAAY;gBAAW;gBAAc;gBAAU;aAAO;YAAEC,SAAS;gBAAC;gBAAS;gBAAQ;aAAQ;YAAEC,SAAS;YAAQC,cAAc;YAAKC,SAAS;QAAU;QAC/TC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAe;YAAW;YAAU;YAAa;YAAU;YAAY;YAAuB;YAAW;YAAa;YAAY;YAAU;YAAmB;YAAqB;YAAY;YAAS;YAAgB;SAAc;QAClPC,OAAO;YAAC;YAAS;YAAS;YAAU;YAAW;YAAY;YAAS;YAAiB;SAAY;QACjGC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAU;gBAAW;aAAS;YAAEC,QAAQ;YAASC,MAAM;gBAAC;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAI;iBAAG;gBAAE;oBAAC;oBAAG;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAS;gBAAQ;aAAO;YAAEC,OAAO;gBAAC;gBAAW;gBAAW;gBAAa;aAAS;YAAEC,SAAS;gBAAC;gBAAQ;aAAQ;YAAEC,SAAS;YAAWC,cAAc;YAAMC,SAAS;QAAU;QACtSC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAU;YAAiB;YAAU;YAAY;YAAS;YAAW;YAAY;YAAW;YAAW;YAAa;YAAe;YAAY;YAAW;YAAY;YAAa;YAAgB;YAAiB;YAAiB;YAAkB;YAAmB;YAAmB;YAAmB;YAAc;YAAc;YAAc;SAAc;QACnXC,OAAO;YAAC;YAAW;YAAY;YAAS;YAAQ;YAAY;YAAQ;YAAY;SAAY;QAC5FC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAc;aAAc;YAAEC,QAAQ;YAAYC,MAAM;gBAAC;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAI;iBAAG;gBAAE;oBAAC;oBAAK;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAS;gBAAU;aAAO;YAAEC,OAAO;gBAAC;gBAAU;gBAAU;gBAAW;gBAAQ;aAAU;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAWC,cAAc;YAAGC,SAAS;QAAU;QAC1TC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAa;YAAc;YAAW;YAAc;YAAc;YAAU;YAAU;YAAgB;YAAU;YAAa;YAAU;YAAY;YAAa;YAAe;YAAU;YAAW;YAAkB;YAAiB;YAAU;YAAa;YAAe;YAA0B;YAA4B;YAAO;YAAO;YAAO;YAA8B;YAAO;YAAU;YAAY;YAAe;YAAc;YAAoB;YAAiB;YAAc;YAAe;YAAS;YAAU;YAAY;YAAa;YAAS;SAAW;QAC7jBC,OAAO;YAAC;YAAa;YAAQ;YAAS;YAAU;YAAU;YAAW;YAAc;YAAW;YAAa;YAAgB;YAAQ;YAAU;YAAa;YAAW;YAAS;YAAY;YAAc;YAAS;YAAc;YAAa;SAAW;QACvPC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAU;aAAU;YAAEC,QAAQ;YAAYC,MAAM;gBAAC;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAI;iBAAG;gBAAE;oBAAC;oBAAK;iBAAI;gBAAE;oBAAC;oBAAK;iBAAI;aAAC;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,OAAO;gBAAC;gBAAgB;gBAAQ;gBAAW;gBAAY;aAAS;YAAEC,SAAS;gBAAC;gBAAQ;aAAQ;YAAEC,SAAS;YAAWC,cAAc;YAAMC,SAAS;QAAU;QAClTC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAQ;YAAY;YAAS;YAAM;YAAU;YAAc;YAAqB;YAAU;YAAkB;YAAoB;YAAgB;YAAa;YAAS;YAAY;YAAQ;YAAY;YAAW;YAAW;YAAa;YAAW;YAAa;YAAc;YAAS;YAAc;YAAgB;YAAa;YAAa;YAAa;YAAc;YAAgB;YAAkB;YAAc;YAAgB;YAAc;YAAO;YAAQ;YAAW;YAAkB;YAAO;YAAW;YAAM;YAAO;YAAe;YAAW;SAAW;QACpjBC,OAAO;YAAC;YAAQ;YAAS;YAAa;YAAQ;YAAS;YAAU;YAAW;YAAQ;YAAQ;YAAS;YAAU;YAAY;YAAQ;SAAS;QAC5IC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAU;gBAAW;aAAc;YAAEC,QAAQ;YAASC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;gBAAQ;aAAS;YAAEC,OAAO;gBAAC;gBAAS;gBAAQ;gBAAW;aAAU;YAAEC,SAAS;gBAAC;aAAQ;YAAEC,SAAS;YAAQC,cAAc;YAAKC,SAAS;QAAU;QACvPC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAiB;YAAoB;YAAiB;YAAqB;YAAY;YAAU;YAAM;YAAiB;YAAc;YAAc;YAAa;YAAW;YAAkB;SAAc;QACvNC,OAAO;YAAC;YAAM;YAAU;YAAW;YAAO;YAAU;YAAQ;SAAa;QACzEC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAa;gBAAW;aAAS;YAAEC,QAAQ;YAASC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;gBAAQ;aAAO;YAAEC,OAAO;gBAAC;gBAAS;gBAAc;gBAAW;gBAAQ;aAAU;YAAEC,SAAS;gBAAC;gBAAQ;aAAQ;YAAEC,SAAS;YAAWC,cAAc;YAAKC,SAAS;QAAO;QACpRC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAgB;YAAW;YAAO;YAAc;YAAW;YAAQ;YAAY;YAAY;YAAa;YAAS;YAAW;YAAe;YAAkB;YAAe;SAAe;QACtMC,OAAO;YAAC;YAAW;YAAU;YAAY;YAAS;YAAS;YAAY;YAAY;YAAQ;SAAO;QAClGC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAa;gBAAW;aAAa;YAAEC,QAAQ;YAASC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;gBAAQ;aAAS;YAAEC,OAAO;gBAAC;gBAAU;gBAAW;gBAAW;gBAAa;aAAQ;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAQC,cAAc;YAAMC,SAAS;QAAU;QACjRC,QAAQ;QACRC,OAAO;IACT;IACA;QACElC,IAAI;QACJiB,OAAO;QACPC,OAAO;QACPC,MAAM;QACNC,UAAU;YAAC;YAAe;YAAa;YAAc;YAAsB;YAAe;YAAgB;SAAiB;QAC3HC,OAAO;YAAC;SAAO;QACfC,SAAS;QACTC,MAAM;YAAEC,OAAO;gBAAC;gBAAW;gBAAa;aAAY;YAAEC,QAAQ;YAASC,MAAMX;YAAUY,SAAS;gBAAC;gBAAS;gBAAU;aAAO;YAAEC,OAAO;gBAAC;gBAAQ;gBAAS;gBAAU;aAAa;YAAEC,SAAS;gBAAC;gBAAS;aAAO;YAAEC,SAAS;YAAQC,cAAc;YAAKC,SAAS;QAAO;QAC/PC,QAAQ;QACRC,OAAO;IACT;CACD,CAAA;AAED,6BAA6B,GAC7B,OAAO,SAASC,WAAWnC,EAAW;QAE7BgB;IADP,IAAI,OAAOhB,OAAO,YAAY,CAACA,IAAI,OAAO;IAC1C,QAAOgB,sBAAAA,cAAcoB,IAAI,CAAC,CAACC,OAASA,KAAKrC,EAAE,KAAKA,eAAzCgB,sBAAgD;AACzD;AAEA,gCAAgC,GAChC,OAAO,SAASsB,kBAAkBtC,EAAW;QAEpCD;IADP,IAAI,OAAOC,OAAO,YAAY,CAACA,IAAI,OAAO;IAC1C,QAAOD,8BAAAA,sBAAsBqC,IAAI,CAAC,CAACG,UAAYA,QAAQvC,EAAE,KAAKA,eAAvDD,8BAA8D;AACvE;AAEA,8EAA8E,GAC9E,MAAMyC,OAAO,CAACC;IACZ,IAAIA,KAAKC,MAAM,IAAI,GAAG,OAAOD;IAC7B,IAAIA,KAAKE,QAAQ,CAAC,QAAQ,OAAO,GAAGF,KAAKG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxD,IAAI,oBAAoBC,IAAI,CAACJ,OAAO,OAAOA,KAAKG,KAAK,CAAC,GAAG,CAAC;IAC1D,IAAIH,KAAKE,QAAQ,CAAC,QAAQ,CAAC,gBAAgBE,IAAI,CAACJ,OAAO,OAAOA,KAAKG,KAAK,CAAC,GAAG,CAAC;IAC7E,OAAOH;AACT;AAEA,qFAAqF,GACrF,MAAMK,SAAS,CAACC,OACdA,KACGC,SAAS,CAAC,OACVC,OAAO,CAAC,UAAU,IAClBC,WAAW,GACXD,OAAO,CAAC,SAAS,IACjBE,KAAK,CAAC,eACNC,MAAM,CAACC,SACPC,GAAG,CAACd;AAET;;;;;CAKC,GACD,MAAMe,WAAW;AAEjB;;;;;;CAMC,GACD,MAAMC,iBAAiB;AACvB,MAAMC,yBAAyB;AAC/B,MAAMC,cAAc;AACpB,MAAMC,kBAAkB;AACxB,sHAAsH,GACtH,MAAMC,kBAAkB;AACxB,0EAA0E,GAC1E,MAAMC,iBAAiB;AACvB,2FAA2F,GAC3F,MAAMC,YAAY;AASlB;;;;CAIC,GACD,MAAMC,QAAmC/C,cAAcgD,OAAO,CAAC,CAAC3B;IAC9D,MAAM4B,OAAO,IAAIC;IACjB,MAAMC,QAA0B,EAAE;IAClC,MAAMC,MAAM,CAACC,MAAcC;QACzB,MAAMC,QAAQzB,OAAOuB;QACrB,MAAMG,MAAMD,MAAME,IAAI,CAAC;QACvB,IAAI,CAACF,MAAM7B,MAAM,IAAIuB,KAAKS,GAAG,CAACF,MAAM;QACpCP,KAAKG,GAAG,CAACI;QACT,MAAMnE,SAAS,CAACiE,UAAUZ,cAAca,MAAM7B,MAAM,GAAG,IAAIe,yBAAyBc,MAAM7B,MAAM,GAAGc;QACnGW,MAAMQ,IAAI,CAAC;YAAEtC;YAAMkC;YAAOlE;YAAQiE;QAAQ;IAC5C;IACA,KAAK,MAAMA,WAAWjC,KAAKjB,QAAQ,CAAEgD,IAAIE,SAAS;IAClD,KAAK,MAAMM,QAAQvC,KAAKhB,KAAK,CAAE+C,IAAIQ,MAAM;IACzC,OAAOT;AACT,GAAGU,IAAI,CAAC,CAACC,GAAGC,IAAMA,EAAER,KAAK,CAAC7B,MAAM,GAAGoC,EAAEP,KAAK,CAAC7B,MAAM;AAejD,oFAAoF,GACpF,SAASsC,iBAAiBjC,IAAY,EAAEkC,KAAa,EAAEC,MAAwC;IAC7F,MAAMX,QAAQzB,OAAOC;IACrB,MAAMoC,UAA6B,EAAE;IACrC,yEAAyE;IACzE,4EAA4E;IAC5E,MAAMC,UAAU,IAAIC,MAAed,MAAM7B,MAAM,EAAE4C,IAAI,CAAC;IACtD,MAAMC,UAAU,IAAIrB;IACpB,MAAMsB,UAAU,IAAItB;IACpB,IAAIxB,SAAS;IACb,KAAK,MAAM2B,QAAQN,MAAO;QACxB,IAAIM,KAAKE,KAAK,CAAC7B,MAAM,KAAKA,QAAQ;YAChCA,SAAS2B,KAAKE,KAAK,CAAC7B,MAAM;YAC1B,KAAK,MAAM+C,SAASF,QAASH,OAAO,CAACK,MAAM,GAAG;YAC9CF,QAAQG,KAAK;QACf;QACA,IAAK,IAAIC,QAAQ,GAAGA,QAAQtB,KAAKE,KAAK,CAAC7B,MAAM,IAAI6B,MAAM7B,MAAM,EAAEiD,QAAS;gBAIxDT;YAHd,IAAI,CAACb,KAAKE,KAAK,CAACqB,KAAK,CAAC,CAACnD,MAAMoD,SAAWtB,KAAK,CAACoB,QAAQE,OAAO,KAAKpD,QAAQ,CAAC2C,OAAO,CAACO,QAAQE,OAAO,GAAG;YACrG,MAAMC,MAAMH,QAAQtB,KAAKE,KAAK,CAAC7B,MAAM;YACrC,IAAK,IAAI+C,QAAQE,OAAOF,QAAQK,KAAKL,QAASF,QAAQnB,GAAG,CAACqB;YAC1D,MAAMM,SAAQb,cAAAA,OAAOc,GAAG,CAAC3B,KAAKhC,IAAI,aAApB6C,cAAyB;gBAAEe,OAAO;gBAAGC,IAAI,CAAC;YAAE;YAC1D,IAAI,CAACV,QAAQd,GAAG,CAACL,OAAO;gBACtBmB,QAAQpB,GAAG,CAACC;gBACZ0B,MAAME,KAAK,IAAI5B,KAAKhE,MAAM,GAAG4E;YAC/B;YACAc,MAAMG,EAAE,GAAGC,KAAKC,GAAG,CAACL,MAAMG,EAAE,EAAEJ;YAC9BZ,OAAOmB,GAAG,CAAChC,KAAKhC,IAAI,EAAE0D;YACtBZ,QAAQR,IAAI,CAAC;gBAAEtC,MAAMgC,KAAKhC,IAAI;gBAAEyD;gBAAKxB,SAASD,KAAKC,OAAO;YAAC;QAC7D;IACF;IACA,OAAOa;AACT;AAEA;;;;;;CAMC,GACD,SAASmB,eAAeC,IAAgC,EAAEC,QAAiB;IACzE,MAAMpF,WAAWmF,KAAKnD,MAAM,CAAC,CAACqD,QAAUA,MAAMnC,OAAO;IACrD,IAAIlD,SAASsB,MAAM,EAAE,OAAOtB,SAASsF,MAAM,CAAC,CAACC,MAAMF,QAAWA,MAAMX,GAAG,GAAGa,KAAKb,GAAG,GAAGW,QAAQE,MAAOtE,IAAI;IACxG,IAAImE,UAAU,OAAO;IACrB,MAAMI,OAAO;WAAI,IAAI1C,IAAIqC,KAAKjD,GAAG,CAAC,CAACmD,QAAUA,MAAMX,GAAG;KAAG,CAACjB,IAAI,CAAC,CAACC,GAAGC,IAAMA,IAAID;IAC7E,KAAK,MAAMgB,OAAOc,KAAM;QACtB,MAAMC,QAAQ,IAAI3C,IAAIqC,KAAKnD,MAAM,CAAC,CAACqD,QAAUA,MAAMX,GAAG,KAAKA,KAAKxC,GAAG,CAAC,CAACmD,QAAUA,MAAMpE,IAAI;QACzF,IAAIwE,MAAMC,IAAI,KAAK,GAAG,OAAO;eAAID;SAAM,CAAC,EAAE;IAC5C;IACA,OAAO;AACT;AAEA;;;;;;;;;;;;;;;;;;;;;CAqBC,GACD,OAAO,SAASE,cAAcC,QAAgB,EAAEC,WAAW,EAAE;QAM7BD;IAL9B,MAAME,UAAUlG,aAAa,CAAC,EAAE;IAChC,MAAMkE,SAAS,IAAIiC;IACnB,MAAMC,QAAQpC,iBAAiBgC,UAAU,GAAG9B;IAC5C,MAAMmC,eAAe,IAAIF;IACzB,IAAIF,UAAUG,MAAMzC,IAAI,IAAIK,iBAAiBiC,UAAUpD,gBAAgBwD;IACvE,MAAMd,OAAOvB,kBAAiBgC,mBAAAA,SAAS7D,KAAK,CAACI,SAAS,CAAC,EAAE,YAA3ByD,mBAA+B,IAAI,GAAG,IAAIG;IACxE,MAAMG,WAAWhB,eAAeC,MAAMa,MAAMG,IAAI,CAAC,CAACd,QAAUA,MAAMnC,OAAO;IACzE,MAAMkD,YAAYF,WAAWpC,OAAOc,GAAG,CAACsB,YAAYG;IACpD,IAAID,WAAWA,UAAUvB,KAAK,IAAIM,KAAKgB,IAAI,CAAC,CAACd,QAAUA,MAAMnC,OAAO,IAAIX,kBAAkBC;IAC1F,KAAK,MAAM,CAACvB,MAAM,EAAE4D,KAAK,EAAE,CAAC,IAAIoB,aAAc;YAC9BnC;QAAd,MAAMa,SAAQb,cAAAA,OAAOc,GAAG,CAAC3D,iBAAX6C,cAAoB;YAAEe,OAAO;YAAGC,IAAI,CAAC;QAAE;QACrDH,MAAME,KAAK,IAAIA;QACff,OAAOmB,GAAG,CAAChE,MAAM0D;IACnB;IACA,IAAI2B,OAA+D;IACnE,IAAIC,OAAO;IACX,KAAK,MAAM,CAACtF,MAAM,EAAE4D,KAAK,EAAEC,EAAE,EAAE,CAAC,IAAIhB,OAAQ;QAC1C,IAAI,CAACwC,QAAQzB,QAAQyB,KAAKzB,KAAK,IAAKA,UAAUyB,KAAKzB,KAAK,IAAIC,KAAKwB,KAAKxB,EAAE,EAAG;YACzEyB,OAAO;YACPD,OAAO;gBAAErF;gBAAM4D;gBAAOC;YAAG;QAC3B,OAAO,IAAID,UAAUyB,KAAKzB,KAAK,IAAIC,OAAOwB,KAAKxB,EAAE,EAAE;YACjDyB,OAAO;QACT;IACF;IACA,IAAI,CAACD,QAAQA,KAAKzB,KAAK,GAAGnC,aAAa6D,MAAM,OAAOT;IACpD,OAAOQ,KAAKrF,IAAI;AAClB;AAEA,4HAA4H,GAC5H,OAAO,SAASuF,mBAAmBC,MAA4D;IAC7F,MAAMC,QAAQ3F,WAAW0F,0BAAAA,MAAQ,CAAC,WAAW;IAC7C,IAAIC,OAAO,OAAOA;IAClB,MAAMC,OAAOF,0BAAAA,MAAQ,CAAC,eAAe;IACrC,MAAMZ,WAAWY,0BAAAA,MAAQ,CAAC,WAAW;IACrC,OAAO,OAAOE,SAAS,YAAYA,KAAKC,IAAI,KAAKjB,cAAcgB,MAAM,OAAOd,aAAa,WAAWA,WAAW,MAAM;AACvH;AAEA,qDAAqD,GACrD,MAAMgB,eAA6C;IACjDC,MAAM;IACNC,aAAa;IACbC,MAAM;AACR;AAEA,8EAA8E,GAC9E,OAAO,SAASC,kBACdR,MAA4D;IAE5D,MAAMS,MAAMT,0BAAAA,MAAQ,CAAC,YAAY;IACjC,IAAI,CAACS,OAAO,OAAOA,QAAQ,UAAU,OAAO,CAAC;IAC7C,MAAMC,QAAQD;IACd,OAAO,aACDC,KAAK,CAAC,cAAc,KAAK,WAAWA,KAAK,CAAC,cAAc,KAAK,WAAW;QAAEC,aAAaD,KAAK,CAAC,cAAc;IAAC,IAAI,CAAC,GACjHzH,gBAAgB2H,QAAQ,CAACF,KAAK,CAAC,SAAS,IAAoB;QAAEG,QAAQH,KAAK,CAAC,SAAS;IAAiB,IAAI,CAAC;AAEnH;AAEA,4GAA4G,GAC5G,OAAO,SAASI,sBAAsBd,MAA4D;IAChG,MAAMxF,OAAOuF,mBAAmBC;IAChC,MAAM,EAAEa,MAAM,EAAE,GAAGL,kBAAkBR;IACrC,OAAO;WACDxF,OAAO;YAAC,CAAC,SAAS,EAAEA,KAAKpB,KAAK,CAACiC,WAAW,GAAG,OAAO,EAAEb,KAAKJ,MAAM,EAAE;SAAC,GAAG,EAAE;WACzEyG,SAAS;YAAC,CAAC,2BAA2B,EAAET,YAAY,CAACS,OAAO,CAAC,CAAC,CAAC;SAAC,GAAG,EAAE;KAC1E;AACH"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/model/ai-site-kinds.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * The kinds of website a guided start offers (AGL-3660), and the style\n * direction each one sets.\n *\n * A kind is NOT a template. It is a direction in two halves:\n *\n * - a LOOK FAMILY the code applies — how saturated the palette is, the hues\n * that suit the kind, the page grounds, the font pairings, the corners,\n * the button style, the heading scale and the density — inside which the\n * model picks this business's own look and a per-job seed varies it\n * (`ai-site-look.ts`), so two sites of one kind never share a theme;\n * - GUIDANCE the model reads: how the kind's pages are usually arranged\n * (band rhythm, image share, density) and which pages it usually has.\n *\n * Every page a kind suggests is one the site job builds itself out of the\n * layout language: sections, cards, images, a form. The site job also writes\n * a blog's first posts into a content collection (one on the Free taste,\n * AGL-3798) and, on a paid plan, a store's first products as unpriced drafts\n * (AGL-3676, `jobs/ai-job-site-content.ts`), and the pages are told their\n * titles. No event records are created, and no\n * guidance here promises posts, products or events, since the plan reads it\n * on every plan (the owner adds more from the Content, Commerce and Events\n * sections afterward).\n *\n * Pure data and two small readers, safe for the console to import: no\n * theme compiler, no network.\n */\n\n/** A font pairing the look may choose: a heading family over a body family. */\nexport interface AiSiteFontPairing {\n id: string\n /** What the pairing reads like, as the model is told. */\n feel: string\n heading: { family: string; category: 'sans-serif' | 'serif'; weight: number; sub: number }\n body: { family: string; category: 'sans-serif' | 'serif'; weights: number[] }\n /** Letter spacing the headings carry, in em. */\n tracking?: number\n /** Headings set in capitals: a condensed display face. */\n caps?: boolean\n}\n\n/**\n * The pairings, every family from the Google Fonts catalog the fonts plugin\n * serves (`google-fonts.catalog.json`) and every weight one that family\n * has — `ai-site-look.spec.ts` holds both. The tenant loads them the way it\n * loads the starter theme's family, so nothing here adds a font host.\n */\nexport const AI_SITE_FONT_PAIRINGS: readonly AiSiteFontPairing[] = [\n { id: 'jakarta', feel: 'modern, friendly sans', heading: { family: 'Plus Jakarta Sans', category: 'sans-serif', weight: 800, sub: 700 }, body: { family: 'Plus Jakarta Sans', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'inter', feel: 'neutral, precise sans', heading: { family: 'Inter', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.025 },\n { id: 'grotesk', feel: 'designer grotesk', heading: { family: 'Space Grotesk', category: 'sans-serif', weight: 600, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.03 },\n { id: 'syne', feel: 'expressive, art-school display', heading: { family: 'Syne', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'bricolage', feel: 'contemporary, characterful sans', heading: { family: 'Bricolage Grotesque', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'DM Sans', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.025 },\n { id: 'editorial', feel: 'editorial serif over clean sans', heading: { family: 'Playfair Display', category: 'serif', weight: 700, sub: 600 }, body: { family: 'Source Sans 3', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n { id: 'fraunces', feel: 'warm, soft serif', heading: { family: 'Fraunces', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.015 },\n { id: 'instrument', feel: 'elegant, light serif headlines', heading: { family: 'Instrument Serif', category: 'serif', weight: 400, sub: 400 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n { id: 'reading', feel: 'reading-first serif, serif body', heading: { family: 'Newsreader', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Source Serif 4', category: 'serif', weights: [400, 600, 700] }, tracking: -0.01 },\n { id: 'garamond', feel: 'refined, classic serif', heading: { family: 'Cormorant Garamond', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Montserrat', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'baskerville', feel: 'established, trustworthy serif', heading: { family: 'Libre Baskerville', category: 'serif', weight: 700, sub: 700 }, body: { family: 'Source Sans 3', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'merriweather', feel: 'sturdy, readable serif', heading: { family: 'Merriweather', category: 'serif', weight: 700, sub: 700 }, body: { family: 'Lato', category: 'sans-serif', weights: [400, 700] } },\n { id: 'lora', feel: 'gentle, calm serif', heading: { family: 'Lora', category: 'serif', weight: 600, sub: 600 }, body: { family: 'Open Sans', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'dmserif', feel: 'polished display serif', heading: { family: 'DM Serif Display', category: 'serif', weight: 400, sub: 400 }, body: { family: 'DM Sans', category: 'sans-serif', weights: [400, 500, 600, 700] } },\n { id: 'oswald', feel: 'bold, condensed, workmanlike', heading: { family: 'Oswald', category: 'sans-serif', weight: 600, sub: 500 }, body: { family: 'Roboto', category: 'sans-serif', weights: [400, 500, 700] }, caps: true, tracking: 0.01 },\n { id: 'archivo', feel: 'heavy, high-impact sans', heading: { family: 'Archivo Black', category: 'sans-serif', weight: 400, sub: 400 }, body: { family: 'Archivo', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n { id: 'barlow', feel: 'athletic, condensed sans', heading: { family: 'Barlow Condensed', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Barlow', category: 'sans-serif', weights: [400, 500, 600, 700] }, caps: true, tracking: 0.01 },\n { id: 'anton', feel: 'loud poster display', heading: { family: 'Anton', category: 'sans-serif', weight: 400, sub: 400 }, body: { family: 'Inter', category: 'sans-serif', weights: [400, 500, 600, 700] }, caps: true, tracking: 0.01 },\n { id: 'nunito', feel: 'rounded, approachable sans', heading: { family: 'Nunito', category: 'sans-serif', weight: 800, sub: 700 }, body: { family: 'Nunito Sans', category: 'sans-serif', weights: [400, 600, 700] } },\n { id: 'quicksand', feel: 'soft, airy rounded sans', heading: { family: 'Quicksand', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Nunito Sans', category: 'sans-serif', weights: [400, 600, 700] } },\n { id: 'manrope', feel: 'crisp, confident sans', heading: { family: 'Manrope', category: 'sans-serif', weight: 800, sub: 700 }, body: { family: 'Manrope', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'outfit', feel: 'geometric, upbeat sans', heading: { family: 'Outfit', category: 'sans-serif', weight: 700, sub: 600 }, body: { family: 'Outfit', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.02 },\n { id: 'plex', feel: 'technical, engineered sans', heading: { family: 'IBM Plex Sans', category: 'sans-serif', weight: 600, sub: 600 }, body: { family: 'IBM Plex Sans', category: 'sans-serif', weights: [400, 500, 600, 700] }, tracking: -0.01 },\n]\n\nexport type AiSiteFontPairingId = string\n\n/**\n * The platform's built-in themes a site's look is layered on, by the short\n * name of the themes plugin's preset id (\\`theme-presets.<name>\\`), and\n * \\`starter\\`: the theme a new site is born with (AGL-3497).\n */\nexport const AI_SITE_BASES = [\n 'starter',\n 'material-ui',\n 'bootstrap',\n 'minimal',\n 'material3',\n 'ant-design',\n 'fluent',\n 'carbon',\n 'cupertino',\n] as const\nexport type AiSiteBase = (typeof AI_SITE_BASES)[number]\n\n/** How saturated a kind's palette runs. `neutral` is an ink-and-paper ground with one accent. */\nexport type AiSiteChroma = 'neutral' | 'muted' | 'balanced' | 'vivid'\n/** The page ground the light scheme sits on. */\nexport type AiSiteGround = 'white' | 'warm' | 'cool' | 'tinted'\nexport const AI_SITE_GROUNDS: readonly AiSiteGround[] = ['white', 'warm', 'cool', 'tinted']\n/** Corner rounding, cards and fields. */\nexport type AiSiteCorners = 'sharp' | 'soft' | 'round' | 'pill'\nexport const AI_SITE_CORNERS: readonly AiSiteCorners[] = ['sharp', 'soft', 'round', 'pill']\n/** How buttons are drawn: on the corner radius, as pills, square, in capitals, or with quiet buttons as underlined links. */\nexport type AiSiteButtons = 'rounded' | 'pill' | 'square' | 'caps' | 'link'\n/**\n * How a site's pages alternate their bands: calm (mostly plain, one soft),\n * alternating (plain and soft by turns), or bold (brand and dark bands for\n * its key moments).\n */\nexport type AiSiteRhythm = 'calm' | 'alternating' | 'bold'\nexport const AI_SITE_RHYTHMS: readonly AiSiteRhythm[] = ['calm', 'alternating', 'bold']\n\n/** Spacing: tighter, regular or airier than the platform's unit. */\nexport type AiSiteDensity = 'compact' | 'regular' | 'airy'\n\n/** What the code applies for a kind: the bounds a look is chosen and varied in. */\nexport interface AiSiteLookFamily {\n /** The platform's base themes that suit the kind, best first (`AI_SITE_BASES`). */\n bases: readonly AiSiteBase[]\n chroma: AiSiteChroma\n /** How the header is arranged: the brand at the start with the links after it, or both centered. */\n headerAligns?: readonly ('start' | 'center')[]\n /** The band rhythm its pages lean to (`AI_SITE_RHYTHMS`). */\n rhythms?: readonly AiSiteRhythm[]\n /** Hue ranges in degrees that suit the kind, `[from, to]`, wrapping past 360. */\n hues: ReadonlyArray<readonly [number, number]>\n grounds: readonly AiSiteGround[]\n fonts: readonly AiSiteFontPairingId[]\n corners: readonly AiSiteCorners[]\n buttons: AiSiteButtons\n /** Display and heading sizes against the platform's, 1 = as shipped. */\n headingScale: number\n density: AiSiteDensity\n}\n\nexport interface AiSiteKind {\n /** A persisted identifier: the guided start's answer and the job's `siteKind` input. */\n id: string\n /** The card's title, in customer copy. */\n label: string\n /** One line under it. */\n blurb: string\n /** A word from the icon set the card shows. */\n icon: string\n /**\n * Specific nouns and phrases that name this kind on their own (\"roofer\",\n * \"law firm\", \"food bank\"), matched whole and singular or plural. One is\n * enough to pick the kind ({@link aiSiteKindFor}).\n */\n keywords: readonly string[]\n /**\n * Generic words that only lean toward this kind (\"club\", \"studio\",\n * \"classes\", \"shop\"): they add a little weight, break a tie, and never pick\n * a narrow kind on their own.\n */\n hints: readonly string[]\n /** The starter whose shape this kind follows, where one fits (`STARTER_TEMPLATES`). */\n starter: string\n look: AiSiteLookFamily\n /** How its pages are arranged, as every page and the header and footer are told. */\n design: string\n /** The pages it usually has, as the plan is told. */\n pages: string\n}\n\nconst ALL_HUES: ReadonlyArray<readonly [number, number]> = [[0, 360]]\n\n/**\n * The kinds, in the order the guided start shows them. Drawn from the template\n * categories the large site builders offer, merged where two would build the\n * same site: designer and agency are one studio, law and accounting one\n * practice, health and therapy one wellness kind.\n */\nexport const AI_SITE_KINDS: readonly AiSiteKind[] = [\n {\n id: 'business',\n label: 'Business & services',\n blurb: 'Say what you do, why choose you, and how to reach you',\n icon: 'briefcase',\n keywords: ['cleaning service', 'cleaning company', 'house cleaning', 'cleaner', 'janitorial', 'maid', 'groomer', 'grooming', 'dog walker', 'dog walking', 'pet sitter', 'pet sitting', 'dog trainer', 'dog training', 'staffing', 'print shop', 'printing', 'courier', 'laundromat', 'dry cleaner', 'tailor', 'alterations', 'car wash', 'detailing', 'small business'],\n hints: ['business', 'company', 'service', 'local', 'pet', 'dog', 'cleaning', 'customers'],\n starter: 'business',\n look: { bases: ['starter', 'material3', 'fluent', 'minimal', 'ant-design'], chroma: 'balanced', headerAligns: ['start', 'start', 'center'], hues: ALL_HUES, grounds: ['white', 'cool', 'warm', 'tinted'], fonts: ['jakarta', 'manrope', 'outfit', 'inter', 'bricolage', 'fraunces'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1, density: 'regular' },\n design: 'Clear and confident: say plainly what the business does and for whom, draw what it offers as cards or a ruled list, and let a photo carry a section that describes the place or the work. Mix plain and soft bands with one brand band where the page most needs it. The first section opens beside a photo of the work or on a card over it: an eyebrow, a heading that says what the business does, one line and one or two buttons.',\n pages: 'Home, Services, About and Contact are typical; a pricing or booking page where the brief asks for one.',\n },\n {\n id: 'trades',\n label: 'Home services & trades',\n blurb: 'Roofers, plumbers, towing, landscaping: bold, direct, built on trust',\n icon: 'wrench',\n keywords: ['roofer', 'roofing', 'plumber', 'plumbing', 'electrician', 'electrical', 'hvac', 'heating and cooling', 'towing', 'tow truck', 'roadside assistance', 'landscaping', 'landscaper', 'lawn care', 'contractor', 'general contractor', 'construction', 'handyman', 'house painter', 'house painting', 'movers', 'moving company', 'exterminator', 'pest control', 'remodeling', 'renovation', 'mechanic', 'auto repair', 'auto body', 'locksmith', 'flooring', 'fencing', 'pool cleaning', 'pool service', 'welder', 'welding', 'carpenter', 'carpentry', 'masonry', 'concrete', 'drywall', 'gutter', 'siding', 'garage door', 'tree service', 'arborist', 'junk removal', 'septic', 'pressure washing', 'power washing', 'appliance repair'],\n hints: ['repair', 'auto', 'garage', 'painting', 'painter', 'pool', 'moving', 'trade', 'trades', 'homeowner', 'pest', 'installation', 'emergency'],\n starter: 'business',\n look: { bases: ['bootstrap', 'carbon', 'material-ui', 'fluent', 'starter'], chroma: 'vivid', headerAligns: ['start'], hues: [[4, 18], [20, 38], [42, 56], [128, 158], [195, 212], [214, 240]], grounds: ['white', 'cool'], fonts: ['oswald', 'archivo', 'barlow', 'manrope'], corners: ['sharp', 'soft'], buttons: 'square', headingScale: 1.05, density: 'compact' },\n design: 'Direct and high-contrast: a big promise and a call-to-action button in the first section, services as a tight grid, trust only as the brief gives it (licensed, insured, years, guarantees), and short, practical copy. Use a dark band and a brand band. The first section opens over a full-bleed photo of the work, or beside one: a short promise as the heading, one practical line and the quote button first.',\n pages: 'Home, Services, About or Why us, and a Quote or Contact page with the form.',\n },\n {\n id: 'professional',\n label: 'Law, finance & consulting',\n blurb: 'Law firms, accountants, advisers: calm, established, credible',\n icon: 'scale',\n keywords: ['law', 'law firm', 'lawyer', 'attorney', 'legal', 'paralegal', 'accountant', 'accounting', 'cpa', 'tax', 'bookkeeping', 'bookkeeper', 'financial', 'financial advisor', 'wealth management', 'advisor', 'adviser', 'advisory', 'consulting', 'consultant', 'insurance', 'notary', 'mediator', 'mediation', 'estate planning'],\n hints: ['firm', 'practice', 'clients', 'compliance'],\n starter: 'business',\n look: { bases: ['carbon', 'fluent', 'minimal', 'starter'], chroma: 'muted', headerAligns: ['start', 'start', 'center'], hues: [[210, 250], [340, 360], [0, 15], [150, 175]], grounds: ['white', 'warm', 'cool'], fonts: ['baskerville', 'merriweather', 'editorial', 'plex', 'lora'], corners: ['sharp', 'soft'], buttons: 'rounded', headingScale: 0.95, density: 'airy' },\n design: 'Measured and credible: generous space, calm statements, practice areas with short plain explanations, and an unhurried tone with no hard sell. Prefer plain and soft bands, at most one dark band. The first section opens on a card over a photo of the office or the people, or as large type above a wide photo: a calm heading and one plain line.',\n pages: 'Home, Practice areas or Services, About or Our team, and Contact with a consultation form.',\n },\n {\n id: 'wellness',\n label: 'Health & wellness',\n blurb: 'Therapists, clinics, dentists, coaches: warm, reassuring, clear',\n icon: 'heart',\n keywords: ['therapist', 'therapy', 'counselor', 'counseling', 'counselling', 'psychologist', 'psychiatrist', 'psychotherapy', 'dentist', 'dental', 'orthodontist', 'clinic', 'doctor', 'physician', 'pediatrician', 'optometrist', 'chiropractor', 'chiropractic', 'massage', 'wellness', 'nutrition', 'nutritionist', 'dietitian', 'acupuncture', 'physio', 'physiotherapy', 'physical therapy', 'mental health', 'medical', 'vet', 'veterinary', 'veterinarian', 'animal hospital', 'midwife', 'doula', 'naturopath', 'life coach', 'health coach', 'wellness coach', 'home care', 'senior care'],\n hints: ['health', 'healing', 'coach', 'coaching', 'patient', 'care', 'practice', 'mental', 'anxiety'],\n starter: 'business',\n look: { bases: ['material3', 'cupertino', 'starter', 'fluent'], chroma: 'muted', headerAligns: ['center', 'start'], hues: [[150, 200], [250, 290], [20, 40], [90, 130]], grounds: ['warm', 'tinted', 'white'], fonts: ['lora', 'fraunces', 'quicksand', 'dmserif', 'nunito'], corners: ['round', 'pill'], buttons: 'pill', headingScale: 1, density: 'airy' },\n design: 'Reassuring and gentle: warm words that name who it helps, soft cards, answers in plain language, and a low-pressure tone in every call to action. Prefer soft bands, avoid dark ones. The first section opens with half the band a photo of a calm room, or as a centered heading above a wide photo: a gentle heading and one warm line.',\n pages: 'Home, Services or Approach, About, and Book or Contact with the form.',\n },\n {\n id: 'restaurant',\n label: 'Restaurant & café',\n blurb: 'Warm, photo-led pages for food, drink and a place to visit',\n icon: 'utensils',\n keywords: ['restaurant', 'cafe', 'coffee', 'coffee shop', 'coffee house', 'bakery', 'baker', 'pastry', 'cake', 'cupcake', 'bistro', 'diner', 'pizzeria', 'pizza', 'catering', 'caterer', 'brewery', 'winery', 'wine bar', 'distillery', 'taproom', 'food truck', 'deli', 'chef', 'personal chef', 'tavern', 'pub', 'eatery', 'tea room', 'tea house', 'ice cream', 'creamery', 'donut', 'bagel', 'taqueria', 'sushi', 'bbq', 'barbecue', 'ramen', 'cocktail', 'juice bar', 'brunch'],\n hints: ['food', 'kitchen', 'bar', 'tea', 'truck', 'breakfast', 'lunch', 'dinner', 'dining', 'menu', 'drinks', 'meal', 'wine', 'beer'],\n starter: 'business',\n look: { bases: ['material3', 'starter', 'cupertino'], chroma: 'balanced', headerAligns: ['center', 'center', 'start'], hues: [[0, 45], [80, 150], [330, 360]], grounds: ['warm', 'tinted'], fonts: ['fraunces', 'editorial', 'dmserif', 'garamond', 'bricolage'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1.1, density: 'regular' },\n design: 'Photo-led and inviting: large images of the food and the room, the menu as lines rather than cards where it fits, and warm, sensory copy. Use images generously and a warm brand band. The first section opens with the name or the promise centered over a full-bleed photo of the room or the food, or beside one filling half the band: a few words, one line, the menu and visit buttons.',\n pages: 'Home, Menu, About or Our story, and Visit or Reserve with the form.',\n },\n {\n id: 'store',\n label: 'Online store',\n blurb: 'Product-first pages for things you sell',\n icon: 'bag',\n keywords: ['online store', 'online shop', 'web shop', 'boutique', 'ecommerce', 'e-commerce', 'merch', 'merchandise', 'jewelry', 'jewellery', 'clothing', 'apparel', 'candle', 'soap', 'etsy', 'gift shop', 'bookstore', 'bookshop', 'florist', 'flower shop', 'plant shop', 'retail', 'wholesale', 'subscription box', 'thrift', 'sneakers'],\n hints: ['store', 'shop', 'market', 'product', 'sell', 'selling', 'buy', 'order', 'brand', 'handmade', 'goods', 'gifts', 'collection', 'shipping'],\n starter: 'physical-shop',\n look: { bases: ['minimal', 'cupertino', 'material3'], chroma: 'balanced', headerAligns: ['start'], hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['inter', 'outfit', 'manrope', 'dmserif', 'syne'], corners: ['soft', 'sharp', 'round'], buttons: 'pill', headingScale: 1, density: 'regular' },\n design: 'A storefront, like a designer shop theme: a hero that sells, its picture the product itself and its first button Shop all; the bestsellers, which the platform lists with their photos, prices and add to cart; the range by collection as picture tiles; the brand story beside a photo; why buy here as three or four short items each with an icon (shipping, small batch, returns, only as the brief gives them); the store\\'s customer reviews, which the platform shows once shoppers leave them; and a newsletter sign-up. Keep copy short and let images lead; never draw the products themselves as cards of your own, and never a band of text alone. The first section opens beside two pictures of the products, or one: what the shop sells in a short heading and its Shop all button first.',\n pages: 'Home as a storefront: a hero, then sections named \"Bestsellers\", \"Shop by collection\" (3 or 4 items), the story, why buy here (3 or 4 items) and \"Customer reviews\", in the order given above, with \"Newsletter sign-up\" last. Shop at /shop: a short title section, then \"Product grid\" second (the platform lists the real products there, with sort, filters, photos, prices and the cart). About, and Contact. Plan no checkout or cart page.',\n },\n {\n id: 'portfolio',\n label: 'Portfolio',\n blurb: 'Minimal, image-led pages that put the work first',\n icon: 'grid',\n keywords: ['portfolio', 'illustrator', 'illustration', 'artist', 'visual artist', 'architect', 'architecture', 'software engineer', 'developer', 'copywriter', 'animator', 'freelance', 'freelancer', 'ceramics', 'ceramicist', 'potter', 'pottery', 'sculptor', 'sculpture', 'woodworker', 'woodworking', 'printmaker', 'textile artist'],\n hints: ['art', 'maker', 'work', 'gallery', 'painter', 'paintings', 'commissions', 'writer', 'engineer', 'projects'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'cupertino', 'carbon'], chroma: 'neutral', headerAligns: ['start', 'center'], hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['inter', 'grotesk', 'syne', 'instrument'], corners: ['sharp', 'soft'], buttons: 'square', headingScale: 1.3, density: 'airy' },\n design: 'Minimal and image-led: a large, short statement as the title, the work as image cards with one-line captions, and very few words elsewhere. Mostly plain bands, lots of space, big type, one accent color. The first section opens as large type above a wide picture of the work, or beside two pieces: a short statement and a line about the work.',\n pages: 'Home with selected work, Work or Projects, About, and Contact.',\n },\n {\n id: 'studio',\n label: 'Design studio & agency',\n blurb: 'Bold type and case studies for creative teams',\n icon: 'sparkle',\n keywords: ['design studio', 'creative studio', 'creative agency', 'design agency', 'marketing agency', 'digital agency', 'ad agency', 'branding agency', 'branding', 'brand identity', 'marketing', 'digital marketing', 'advertising', 'web design', 'web designer', 'web development', 'graphic design', 'graphic designer', 'motion design', 'video production', 'production company', 'animation', 'seo'],\n hints: ['agency', 'design', 'designer', 'creative', 'studio', 'digital', 'web', 'video', 'production', 'brand', 'campaign', 'case studies'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'carbon', 'cupertino'], chroma: 'neutral', headerAligns: ['start'], hues: ALL_HUES, grounds: ['white', 'cool'], fonts: ['syne', 'grotesk', 'bricolage', 'inter'], corners: ['sharp', 'soft'], buttons: 'pill', headingScale: 1.3, density: 'airy' },\n design: 'Confident and editorial: oversized statements, case studies as large image cards with the outcome in a line, services as a short list, and a bold dark band where the page needs weight. The first section opens as an oversized statement above a wide picture of the work, or over a full-bleed one: a statement of a few words and a line about what the studio does.',\n pages: 'Home, Work or Case studies, Services, About, and Contact or Start a project.',\n },\n {\n id: 'photography',\n label: 'Photography',\n blurb: 'Galleries first, words second',\n icon: 'camera',\n keywords: ['photographer', 'photography', 'videographer', 'videography', 'wedding photographer', 'wedding photography', 'portrait', 'headshot', 'photo studio', 'photo booth'],\n hints: ['photo', 'gallery', 'shoot', 'sessions', 'prints', 'camera'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'cupertino', 'carbon'], chroma: 'neutral', headerAligns: ['center', 'start'], hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['instrument', 'garamond', 'inter', 'grotesk'], corners: ['sharp'], buttons: 'square', headingScale: 1.2, density: 'airy' },\n design: 'Gallery-first: full images, galleries as image cards by subject, few words, packages only as the brief gives them. Many images, mostly plain bands and one dark band. The first section opens as large type above a wide photo, or with the words centered over a full-bleed one: a few words, and the booking button.',\n pages: 'Home, Galleries or Portfolio, About, and Book or Contact with the form.',\n },\n {\n id: 'blog',\n label: 'Blog & writing',\n blurb: 'Reading-first pages with a calm serif voice',\n icon: 'book',\n keywords: ['blog', 'blogger', 'food blog', 'travel blog', 'journal', 'magazine', 'newsletter', 'podcast', 'podcaster', 'essays', 'author', 'novelist', 'poet', 'poetry', 'publication', 'zine', 'columnist', 'substack'],\n hints: ['writing', 'stories', 'reading', 'readers', 'articles', 'posts', 'recipes', 'reviews', 'guides', 'tips', 'writer', 'episodes', 'listeners'],\n starter: 'business',\n look: { bases: ['minimal', 'starter', 'cupertino'], chroma: 'muted', headerAligns: ['center', 'center', 'start'], hues: ALL_HUES, grounds: ['white', 'warm'], fonts: ['reading', 'editorial', 'instrument', 'lora'], corners: ['sharp', 'soft'], buttons: 'rounded', headingScale: 1.05, density: 'airy' },\n design: 'Reading-first: a narrow, calm measure, writing as cards with a title and a one-line summary, topics as a list, and a quiet, personal voice. Mostly plain bands. The first section opens as a centered masthead above the lead picture, or as large type above a wide one: the blog\\'s name or promise and one line about what it covers.',\n pages: 'Home, Articles presenting the writing as cards, About, and Subscribe or Contact. Posts themselves are added in Data as a collection, so plan the articles page as an introduction and a few featured cards.',\n },\n {\n id: 'events',\n label: 'Events & weddings',\n blurb: 'Dates, places and the details guests need',\n icon: 'calendar',\n keywords: ['wedding', 'conference', 'festival', 'gala', 'summit', 'event venue', 'wedding venue', 'venue', 'event planner', 'wedding planner', 'event planning', 'reunion', 'trade show', 'expo', 'hackathon', 'convention', 'birthday party', 'banquet', 'party rentals'],\n hints: ['event', 'party', 'meetup', 'retreat', 'workshop', 'planner', 'rsvp', 'tickets', 'celebration', 'guests', 'schedule', 'concert', 'fundraiser'],\n starter: 'landing',\n look: { bases: ['material3', 'cupertino', 'starter'], chroma: 'balanced', headerAligns: ['center', 'center', 'start'], hues: [[320, 360], [0, 30], [250, 290], [140, 170], [40, 55]], grounds: ['warm', 'tinted', 'white'], fonts: ['garamond', 'editorial', 'dmserif', 'anton', 'syne'], corners: ['soft', 'round'], buttons: 'pill', headingScale: 1.2, density: 'regular' },\n design: 'Celebratory and clear: the name and what it is in big type, when and where only as the brief gives them, the schedule as steps, and the details guests ask about as an FAQ. One brand band. The first section opens beside two pictures of the day, or with its name centered over a full-bleed photo: the name, what it is, and the main action.',\n pages: 'Home, Schedule or Details, Travel or Venue where the brief names one, and RSVP or Register with the form.',\n },\n {\n id: 'fitness',\n label: 'Fitness & sports',\n blurb: 'Gyms, trainers and studios with energy',\n icon: 'bolt',\n keywords: ['gym', 'fitness', 'personal trainer', 'personal training', 'trainer', 'crossfit', 'boxing', 'kickboxing', 'martial arts', 'martial', 'karate', 'judo', 'jiu jitsu', 'taekwondo', 'mma', 'pilates', 'bootcamp', 'boot camp', 'sports', 'sport', 'running', 'runner', 'marathon', 'triathlon', 'cycling', 'climbing', 'bouldering', 'dance', 'swim', 'swimming', 'soccer', 'football', 'basketball', 'baseball', 'softball', 'volleyball', 'tennis', 'pickleball', 'golf', 'hockey', 'rugby', 'lacrosse', 'wrestling', 'gymnastics', 'athletics', 'athlete', 'strength training', 'weightlifting', 'powerlifting', 'health club', 'league'],\n hints: ['training', 'team', 'workout', 'coach', 'coaching', 'studio', 'members', 'race', 'game', 'tournament'],\n starter: 'business',\n look: { bases: ['bootstrap', 'material-ui', 'carbon', 'material3'], chroma: 'vivid', headerAligns: ['start'], hues: [[0, 30], [90, 140], [180, 210], [270, 300]], grounds: ['white', 'cool'], fonts: ['barlow', 'anton', 'archivo', 'outfit'], corners: ['sharp', 'soft'], buttons: 'caps', headingScale: 1.15, density: 'compact' },\n design: 'High-energy: punchy headlines, strong buttons, classes or programs as cards and short, motivating copy. Use a dark band and a brand band. The first section opens with half the band a photo of training and a loud headline in the other, or over a full-bleed photo: a punchy heading, one line and the join button.',\n pages: 'Home, Classes or Programs, About or Coaches, and Join or Contact with the form.',\n },\n {\n id: 'yoga',\n label: 'Yoga & mindfulness',\n blurb: 'Calm, spacious pages for classes and retreats',\n icon: 'leaf',\n keywords: ['yoga', 'meditation', 'mindfulness', 'breathwork', 'reiki', 'sound bath', 'sound healing', 'tai chi', 'qigong'],\n hints: ['retreat', 'spa', 'calm', 'studio', 'healing', 'stillness'],\n starter: 'business',\n look: { bases: ['material3', 'cupertino', 'starter', 'fluent'], chroma: 'muted', headerAligns: ['center', 'center', 'start'], hues: [[20, 50], [80, 150], [260, 300], [170, 200]], grounds: ['warm', 'tinted'], fonts: ['garamond', 'lora', 'quicksand', 'instrument', 'fraunces'], corners: ['round', 'pill'], buttons: 'pill', headingScale: 1.05, density: 'airy' },\n design: 'Calm and spacious: quiet headlines, classes as soft cards, gentle copy and lots of space. Soft bands, no dark band. The first section opens as a quiet centered heading above a wide photo of the space, or beside one: a calm heading and one gentle line.',\n pages: 'Home, Classes or Schedule, About, and Book or Contact with the form.',\n },\n {\n id: 'beauty',\n label: 'Beauty & salon',\n blurb: 'Salons, barbers, spas and studios with style',\n icon: 'scissors',\n keywords: ['salon', 'hair salon', 'hair', 'hairdresser', 'hairstylist', 'barber', 'barbershop', 'nails', 'nail salon', 'beauty', 'makeup', 'lashes', 'brows', 'esthetician', 'aesthetician', 'skincare', 'skin care', 'facial', 'waxing', 'tattoo', 'piercing', 'stylist', 'spa', 'day spa', 'med spa', 'blowout'],\n hints: ['studio', 'glam', 'appointments', 'cosmetics'],\n starter: 'business',\n look: { bases: ['material3', 'cupertino', 'minimal'], chroma: 'balanced', headerAligns: ['center', 'start'], hues: [[320, 360], [0, 25], [270, 300], [20, 45]], grounds: ['warm', 'tinted', 'white'], fonts: ['garamond', 'dmserif', 'instrument', 'outfit', 'syne'], corners: ['round', 'pill', 'sharp'], buttons: 'pill', headingScale: 1.1, density: 'regular' },\n design: 'Stylish and image-led: striking images, services as a menu or cards, the look and feel of the place in pictures, and booking made obvious. One brand band. The first section opens beside two pictures of the work and the place, or with half the band one: a stylish heading, one line and the booking button.',\n pages: 'Home, Services, About or The team, and Book or Contact with the form.',\n },\n {\n id: 'realestate',\n label: 'Real estate',\n blurb: 'Agents, brokers and property: polished and local',\n icon: 'home',\n keywords: ['real estate', 'realtor', 'realty', 'brokerage', 'broker', 'property', 'property management', 'rentals', 'apartment', 'mortgage', 'airbnb', 'vacation rental', 'short term rental', 'listings', 'condo', 'home builder', 'homebuilder'],\n hints: ['homes', 'house', 'buyers', 'sellers', 'vacation', 'cabin', 'neighborhoods', 'investors'],\n starter: 'business',\n look: { bases: ['fluent', 'minimal', 'carbon'], chroma: 'muted', headerAligns: ['start', 'start', 'center'], hues: [[200, 240], [150, 180], [20, 45], [0, 360]], grounds: ['white', 'warm', 'cool'], fonts: ['dmserif', 'manrope', 'editorial', 'outfit'], corners: ['soft', 'sharp'], buttons: 'rounded', headingScale: 1.05, density: 'regular' },\n design: 'Polished and local: image-led sections, the areas served by name only as the brief gives them, listings only as image cards the owner fills in, and confident, local copy. One dark band. The first section opens on a card over a full-bleed photo of a home, or under a scrim over one: a confident local heading, one line and the main action.',\n pages: 'Home, Buy or Listings, Sell, About, and Contact with the form.',\n },\n {\n id: 'education',\n label: 'Courses & education',\n blurb: 'Tutors, schools and courses, clear and encouraging',\n icon: 'school',\n keywords: ['course', 'online course', 'school', 'tutoring', 'tutor', 'teacher', 'teaching', 'lessons', 'academy', 'education', 'educational', 'learning', 'daycare', 'day care', 'preschool', 'kindergarten', 'music lessons', 'piano lessons', 'driving school', 'driving lessons', 'language school', 'coding bootcamp', 'curriculum', 'homeschool', 'montessori', 'summer camp'],\n hints: ['classes', 'students', 'learn', 'kids', 'training', 'camp', 'workshop', 'beginners'],\n starter: 'business',\n look: { bases: ['material3', 'ant-design', 'material-ui'], chroma: 'balanced', headerAligns: ['start', 'start', 'center'], hues: [[200, 240], [140, 170], [30, 50], [260, 290]], grounds: ['white', 'tinted', 'cool'], fonts: ['nunito', 'outfit', 'jakarta', 'lora', 'manrope'], corners: ['round', 'soft'], buttons: 'rounded', headingScale: 1, density: 'regular' },\n design: 'Clear and encouraging: who it is for and the result they get in plain words, courses or subjects as cards, steps where something happens in order, and an FAQ where people have questions. The first section opens beside a photo of learning, or with a round photo of the teacher over the words: who it is for and the result, in a heading and one line.',\n pages: 'Home, Courses or Lessons, About or Teachers, and Enroll or Contact with the form.',\n },\n {\n id: 'nonprofit',\n label: 'Nonprofit & community',\n blurb: 'A cause, its impact and how to help',\n icon: 'hands',\n keywords: ['nonprofit', 'non-profit', 'charity', 'charitable', 'foundation', 'church', 'parish', 'congregation', 'mosque', 'synagogue', 'temple', 'ministry', 'food bank', 'food pantry', 'pantry', 'shelter', 'animal shelter', 'animal rescue', 'rescue', 'volunteer', 'association', 'homeowners association', 'neighborhood association', 'hoa', 'pta', 'pto', 'parent teacher association', 'ngo', 'donate', 'donation', 'fundraising', 'mutual aid', 'community center', 'senior center', 'makerspace', 'hackerspace', 'guild', 'rotary', 'advocacy', 'coalition', 'civic', 'veterans'],\n hints: ['community', 'club', 'group', 'troupe', 'circle', 'society', 'collective', 'members', 'neighbors', 'neighborhood', 'join', 'meetup', 'gathering', 'mission', 'cause', 'together', 'fellowship', 'faith', 'fundraiser', 'residents', 'families'],\n starter: 'business',\n look: { bases: ['material3', 'fluent', 'starter'], chroma: 'balanced', headerAligns: ['start', 'start', 'center'], hues: [[130, 200], [20, 45], [200, 230], [340, 360]], grounds: ['white', 'warm'], fonts: ['merriweather', 'lora', 'jakarta', 'fraunces', 'nunito'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1.05, density: 'regular' },\n design: 'Mission-led: the cause in one strong line, what the organization does as cards, how to help as steps (volunteer, give, spread the word), and hopeful, concrete copy. A brand band for the call to help. The first section opens over a full-bleed photo of the people it serves, or beside two pictures: the cause in one strong line and the help button first.',\n pages: 'Home, Our work or Programs, About, and Get involved or Contact with the form.',\n },\n {\n id: 'music',\n label: 'Music & bands',\n blurb: 'Artists, bands and DJs, loud and visual',\n icon: 'music',\n keywords: ['band', 'musician', 'music', 'dj', 'singer', 'songwriter', 'singer-songwriter', 'rapper', 'music producer', 'recording studio', 'record label', 'orchestra', 'choir', 'composer', 'jazz', 'ensemble', 'quartet', 'pianist', 'guitarist', 'drummer', 'violinist', 'tour dates', 'album', 'live music', 'music artist', 'folk band', 'rock band', 'punk band', 'metal band', 'country band', 'bluegrass band', 'cover band', 'wedding band', 'party band', 'duo', 'trio', 'hip hop', 'hip hop artist', 'rap', 'mixtape', 'ep', 'gig', 'discography', 'setlist', 'bandcamp'],\n hints: ['folk', 'indie', 'bluegrass', 'punk', 'metal', 'record', 'concert', 'tour', 'song', 'shows', 'tracks', 'producer', 'fans', 'listen'],\n starter: 'landing',\n look: { bases: ['carbon', 'minimal', 'material-ui'], chroma: 'vivid', headerAligns: ['center', 'start'], hues: ALL_HUES, grounds: ['white', 'cool', 'tinted'], fonts: ['anton', 'syne', 'grotesk', 'archivo'], corners: ['sharp'], buttons: 'caps', headingScale: 1.3, density: 'regular' },\n design: 'Loud and visual: the name huge, image bands, a listen section where the platform places a music player for the artist’s own tracks, releases or shows as image cards only as the brief gives them, and a short bio. Dark bands are welcome. Never name or link songs by other artists. The first section opens with the name huge over a full-bleed photo, set at the start or centered: the name, one line and the listen or shows button.',\n pages: 'Home, Music or Shows, About, and Booking or Contact with the form.',\n },\n {\n id: 'personal',\n label: 'Personal & resume',\n blurb: 'A simple page about you and your work',\n icon: 'person',\n keywords: ['personal site', 'personal website', 'personal page', 'personal homepage', 'about me', 'resume', 'cv', 'online resume', 'job seeker', 'job search', 'candidate', 'speaker', 'public speaker', 'link in bio'],\n hints: ['me', 'myself', 'profile', 'job', 'career', 'hire', 'recruiters'],\n starter: 'portfolio',\n look: { bases: ['minimal', 'cupertino', 'starter', 'fluent'], chroma: 'muted', headerAligns: ['center', 'start'], hues: ALL_HUES, grounds: ['white', 'warm', 'cool'], fonts: ['inter', 'instrument', 'manrope', 'lora', 'grotesk'], corners: ['soft', 'round'], buttons: 'rounded', headingScale: 1.1, density: 'airy' },\n design: 'Simple and personal: who the person is in one line, what they do in plain words, experience or highlights as a list or steps, selected work as cards where the brief names some. Mostly plain bands. The first section opens with a round portrait over the words, or as a centered heading above a wide photo: who the person is in one line and what they do.',\n pages: 'Home, About or Experience, Work where the brief names some, and Contact.',\n },\n {\n id: 'landing',\n label: 'Landing page',\n blurb: 'One page that leads to one action',\n icon: 'rocket',\n keywords: ['landing page', 'landing', 'app', 'mobile app', 'startup', 'saas', 'software', 'waitlist', 'wait list', 'ebook', 'webinar', 'lead magnet', 'product launch', 'signup page', 'sign-up page'],\n hints: ['product', 'launch', 'campaign', 'offer', 'users', 'download', 'platform', 'tool', 'beta'],\n starter: 'landing',\n look: { bases: ['material3', 'minimal', 'ant-design'], chroma: 'vivid', headerAligns: ['start', 'center'], hues: ALL_HUES, grounds: ['white', 'cool', 'tinted'], fonts: ['outfit', 'jakarta', 'manrope', 'bricolage', 'inter'], corners: ['round', 'soft'], buttons: 'pill', headingScale: 1.15, density: 'regular' },\n design: 'One action: a strong promise and the call to action in the first section, benefits as cards, how it works as steps, objections answered as an FAQ, and the call to action repeated. A brand band where the page asks. The first section opens with the promise centered above a wide picture of the offer, or over a full-bleed photo: a strong promise, one line and the call to action.',\n pages: 'One long home page carries the story; a second page only for the form or details the brief asks for.',\n },\n {\n id: 'coming-soon',\n label: 'Coming soon',\n blurb: 'A placeholder that collects interest',\n icon: 'clock',\n keywords: ['coming soon', 'prelaunch', 'pre-launch', 'under construction', 'placeholder', 'opening soon', 'launching soon'],\n hints: ['soon'],\n starter: 'landing',\n look: { bases: ['minimal', 'material3', 'cupertino'], chroma: 'vivid', headerAligns: ['center'], hues: ALL_HUES, grounds: ['white', 'tinted', 'cool'], fonts: ['syne', 'anton', 'outfit', 'instrument'], corners: ['round', 'pill'], buttons: 'pill', headingScale: 1.3, density: 'airy' },\n design: 'Short and striking: what is coming in one big line, two or three reasons to care, and a way to hear first through the form. Few sections, big type. The first section opens with one big line centered over a full-bleed photo, or on a card over one: what is coming and the sign-up button.',\n pages: 'A home page that says what is coming and invites people to sign up; nothing else unless the brief asks.',\n },\n]\n\n/** A kind by id, or `null`. */\nexport function aiSiteKind(id: unknown): AiSiteKind | null {\n if (typeof id !== 'string' || !id) return null\n return AI_SITE_KINDS.find((kind) => kind.id === id) ?? null\n}\n\n/** A pairing by id, or `null`. */\nexport function aiSiteFontPairing(id: unknown): AiSiteFontPairing | null {\n if (typeof id !== 'string' || !id) return null\n return AI_SITE_FONT_PAIRINGS.find((pairing) => pairing.id === id) ?? null\n}\n\n/** One word as the classifier compares it: lower case, unaccented, singular. */\nconst stem = (word: string): string => {\n if (word.length <= 3) return word\n if (word.endsWith('ies')) return `${word.slice(0, -3)}y`\n if (/(?:ss|x|ch|sh)es$/.test(word)) return word.slice(0, -2)\n if (word.endsWith('s') && !/(?:ss|us|is)$/.test(word)) return word.slice(0, -1)\n return word\n}\n\n/** A text as the classifier's words (\"Cafés & non-profits\" → cafe, &, non, profit). */\nconst tokens = (text: string): string[] =>\n text\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/'s\\b/g, '')\n .split(/[^a-z0-9&]+/)\n .filter(Boolean)\n .map(stem)\n\n/**\n * Where the head of an answer ends: at its first punctuation or the first\n * word that starts a modifier (\"a bookstore WITH author events\", \"a food blog\n * ABOUT cooking\", \"a pottery studio: stoneware…\"). What comes before is what\n * the site IS; what follows describes it.\n */\nconst HEAD_END = /[:;,.()—–]|\\s-\\s|\\b(?:with|for|about|that|who|which|where|in|on|at|of|offering|selling|serving|near|from|by|to|booking|touring|playing|performing)\\b/i\n\n/**\n * What a match is worth. A specific one-word keyword picks a kind alone; a\n * phrase is worth more than its words (it is the more specific reading, and\n * it claims its words so \"wedding photographer\" never also counts as a\n * wedding); a hint only leans. The last keyword in the head of the answer —\n * its noun — gets a bonus, so the thing the site is beats what it mentions.\n */\nconst KEYWORD_WEIGHT = 3\nconst PHRASE_WEIGHT_PER_WORD = 2\nconst HINT_WEIGHT = 1\nconst HEAD_NOUN_BONUS = 2\n/** A generic head noun with nothing specific said: enough to clear {@link MIN_SCORE} alone, never to beat a keyword. */\nconst HEAD_HINT_BONUS = 1\n/** \"Who it's for\" describes the people, not the site, so it counts half. */\nconst AUDIENCE_SHARE = 0.5\n/** Below this no kind is meant: one stray hint is not a reason to pick a narrow vertical. */\nconst MIN_SCORE = 1.5\n\ninterface AiSiteKindTerm {\n kind: AiSiteKind\n words: readonly string[]\n weight: number\n keyword: boolean\n}\n\n/**\n * Every keyword and hint once per kind (a plural and its singular are one\n * term), longest phrase first so a phrase claims its words before they count\n * alone.\n */\nconst TERMS: readonly AiSiteKindTerm[] = AI_SITE_KINDS.flatMap((kind) => {\n const seen = new Set<string>()\n const terms: AiSiteKindTerm[] = []\n const add = (term: string, keyword: boolean) => {\n const words = tokens(term)\n const key = words.join(' ')\n if (!words.length || seen.has(key)) return\n seen.add(key)\n const weight = !keyword ? HINT_WEIGHT : words.length > 1 ? PHRASE_WEIGHT_PER_WORD * words.length : KEYWORD_WEIGHT\n terms.push({ kind, words, weight, keyword })\n }\n for (const keyword of kind.keywords) add(keyword, true)\n for (const hint of kind.hints) add(hint, false)\n return terms\n}).sort((a, b) => b.words.length - a.words.length)\n\ninterface AiSiteKindScore {\n score: number\n /** Where the kind's last match in the answer ends, in words; -1 for none. */\n at: number\n}\n\n/** One term found in a text, by word position. */\ninterface AiSiteKindMatch {\n kind: AiSiteKind\n end: number\n keyword: boolean\n}\n\n/** Adds what one text says for each kind to `scores`; returns every term it found. */\nfunction aiSiteKindScores(text: string, share: number, scores: Map<AiSiteKind, AiSiteKindScore>): AiSiteKindMatch[] {\n const words = tokens(text)\n const matches: AiSiteKindMatch[] = []\n // Words a longer term has matched; terms of one length share their words\n // (two kinds may both have \"studio\"), and a shorter term never reuses them.\n const claimed = new Array<boolean>(words.length).fill(false)\n const pending = new Set<number>()\n const counted = new Set<AiSiteKindTerm>()\n let length = 0\n for (const term of TERMS) {\n if (term.words.length !== length) {\n length = term.words.length\n for (const index of pending) claimed[index] = true\n pending.clear()\n }\n for (let start = 0; start + term.words.length <= words.length; start++) {\n if (!term.words.every((word, offset) => words[start + offset] === word && !claimed[start + offset])) continue\n const end = start + term.words.length\n for (let index = start; index < end; index++) pending.add(index)\n const entry = scores.get(term.kind) ?? { score: 0, at: -1 }\n if (!counted.has(term)) {\n counted.add(term)\n entry.score += term.weight * share\n }\n entry.at = Math.max(entry.at, end)\n scores.set(term.kind, entry)\n matches.push({ kind: term.kind, end, keyword: term.keyword })\n }\n }\n return matches\n}\n\n/**\n * The kind the head of an answer names, if any. Its last keyword when it has\n * one. When nothing specific is said anywhere, its last generic word that\n * belongs to exactly one kind: \"a pet store\" is a store, \"a writers group\" a\n * community, \"a cooking class studio\" a class (studio says nothing, since\n * four kinds share it). A generic word outside the head never counts here.\n */\nfunction aiSiteHeadKind(head: readonly AiSiteKindMatch[], specific: boolean): AiSiteKind | null {\n const keywords = head.filter((match) => match.keyword)\n if (keywords.length) return keywords.reduce((last, match) => (match.end > last.end ? match : last)).kind\n if (specific) return null\n const ends = [...new Set(head.map((match) => match.end))].sort((a, b) => b - a)\n for (const end of ends) {\n const kinds = new Set(head.filter((match) => match.end === end).map((match) => match.kind))\n if (kinds.size === 1) return [...kinds][0] as AiSiteKind\n }\n return null\n}\n\n/**\n * The kind a \"what kind of site\" answer suggests, read with \"who it's for\"\n * when there is one: the card the guided start selects until the person\n * picks another. Deterministic and local, no model call (AGL-3660).\n *\n * Every kind scores what it finds. A specific keyword (\"roofer\", \"food bank\")\n * is enough alone; a phrase outweighs its words and claims them (\"wedding\n * photographer\" is photography, not events); a generic hint (\"club\",\n * \"studio\", \"classes\", \"shop\") only leans, so \"a neighborhood book club\" is\n * community, built from club + neighborhood + meetups + neighbors, and never\n * fitness on \"club\". The head noun — the last keyword before the answer's\n * first modifier — earns a bonus (\"a bookstore with author events\" is a\n * store); when the answer and audience name nothing specific, a generic head\n * noun that only one kind has may decide (\"a bike shop\" is a store, \"a hiking\n * group\" a community). The audience counts half. The highest score wins; of two equal,\n * the one named later, since English puts the noun last (\"a food blog\" is a\n * blog). Tricky ones, decided: a band that sells merch is music (the band is\n * the head and the merch only a mention); booking a DJ is music; a music\n * teacher or music lessons are education; a guitar shop or band merch store\n * is a store. A best score of no more than a stray hint, or a tie that order\n * cannot settle, is `business`, the most general kind.\n */\nexport function aiSiteKindFor(siteType: string, audience = ''): AiSiteKind {\n const general = AI_SITE_KINDS[0] as AiSiteKind\n const scores = new Map<AiSiteKind, AiSiteKindScore>()\n const found = aiSiteKindScores(siteType, 1, scores)\n const fromAudience = new Map<AiSiteKind, AiSiteKindScore>()\n if (audience) found.push(...aiSiteKindScores(audience, AUDIENCE_SHARE, fromAudience))\n const head = aiSiteKindScores(siteType.split(HEAD_END)[0] ?? '', 0, new Map())\n const headKind = aiSiteHeadKind(head, found.some((match) => match.keyword))\n const headEntry = headKind ? scores.get(headKind) : undefined\n if (headEntry) headEntry.score += head.some((match) => match.keyword) ? HEAD_NOUN_BONUS : HEAD_HINT_BONUS\n for (const [kind, { score }] of fromAudience) {\n const entry = scores.get(kind) ?? { score: 0, at: -1 }\n entry.score += score\n scores.set(kind, entry)\n }\n let best: { kind: AiSiteKind; score: number; at: number } | null = null\n let tied = false\n for (const [kind, { score, at }] of scores) {\n if (!best || score > best.score || (score === best.score && at > best.at)) {\n tied = false\n best = { kind, score, at }\n } else if (score === best.score && at === best.at) {\n tied = true\n }\n }\n if (!best || best.score < MIN_SCORE || tied) return general\n return best.kind\n}\n\n/** The kind a job's inputs name, else the one its business type and audience suggest; `null` for a job that names neither. */\nexport function aiSiteKindOfInputs(inputs: Readonly<Record<string, unknown>> | null | undefined): AiSiteKind | null {\n const named = aiSiteKind(inputs?.['siteKind'])\n if (named) return named\n const type = inputs?.['businessType']\n const audience = inputs?.['audience']\n return typeof type === 'string' && type.trim() ? aiSiteKindFor(type, typeof audience === 'string' ? audience : '') : null\n}\n\n/** What each band rhythm asks of a page's sections. */\nconst RHYTHM_WORDS: Record<AiSiteRhythm, string> = {\n calm: 'mostly plain bands with one soft band, and at most one brand or dark band, on whichever section most needs the weight',\n alternating: 'plain and soft bands by turns, with one brand band wherever the page needs emphasis',\n bold: 'a dark or brand band for one or two key moments anywhere on the page, and strong contrast between neighboring sections',\n}\n\n/** The site's own look tokens a unit is handed (AGL-3660), read defensively. */\nexport function aiSiteStyleTokens(\n inputs: Readonly<Record<string, unknown>> | null | undefined,\n): { headerAlign?: 'start' | 'center'; rhythm?: AiSiteRhythm } {\n const raw = inputs?.['siteStyle']\n if (!raw || typeof raw !== 'object') return {}\n const style = raw as Record<string, unknown>\n return {\n ...(style['headerAlign'] === 'start' || style['headerAlign'] === 'center' ? { headerAlign: style['headerAlign'] } : {}),\n ...(AI_SITE_RHYTHMS.includes(style['rhythm'] as AiSiteRhythm) ? { rhythm: style['rhythm'] as AiSiteRhythm } : {}),\n }\n}\n\n/** The style lines a page, the header and the footer are told for the job's kind and look; empty for none. */\nexport function aiSiteKindDesignLines(inputs: Readonly<Record<string, unknown>> | null | undefined): string[] {\n const kind = aiSiteKindOfInputs(inputs)\n const { rhythm } = aiSiteStyleTokens(inputs)\n return [\n ...(kind ? [`Style: a ${kind.label.toLowerCase()} site. ${kind.design}`] : []),\n ...(rhythm ? [`Band rhythm for this site: ${RHYTHM_WORDS[rhythm]}.`] : []),\n ]\n}\n"],"names":["AI_SITE_FONT_PAIRINGS","id","feel","heading","family","category","weight","sub","body","weights","tracking","caps","AI_SITE_BASES","AI_SITE_GROUNDS","AI_SITE_CORNERS","AI_SITE_RHYTHMS","ALL_HUES","AI_SITE_KINDS","label","blurb","icon","keywords","hints","starter","look","bases","chroma","headerAligns","hues","grounds","fonts","corners","buttons","headingScale","density","design","pages","aiSiteKind","find","kind","aiSiteFontPairing","pairing","stem","word","length","endsWith","slice","test","tokens","text","normalize","replace","toLowerCase","split","filter","Boolean","map","HEAD_END","KEYWORD_WEIGHT","PHRASE_WEIGHT_PER_WORD","HINT_WEIGHT","HEAD_NOUN_BONUS","HEAD_HINT_BONUS","AUDIENCE_SHARE","MIN_SCORE","TERMS","flatMap","seen","Set","terms","add","term","keyword","words","key","join","has","push","hint","sort","a","b","aiSiteKindScores","share","scores","matches","claimed","Array","fill","pending","counted","index","clear","start","every","offset","end","entry","get","score","at","Math","max","set","aiSiteHeadKind","head","specific","match","reduce","last","ends","kinds","size","aiSiteKindFor","siteType","audience","general","Map","found","fromAudience","headKind","some","headEntry","undefined","best","tied","aiSiteKindOfInputs","inputs","named","type","trim","RHYTHM_WORDS","calm","alternating","bold","aiSiteStyleTokens","raw","style","headerAlign","includes","rhythm","aiSiteKindDesignLines"],"mappings":"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"}
|
|
@@ -95,6 +95,14 @@ export interface AiSiteStyle {
|
|
|
95
95
|
}
|
|
96
96
|
/** What the model may choose, every field optional. */
|
|
97
97
|
export type AiSiteLookAnswer = Partial<Pick<AiSiteStyle, 'base' | 'hue' | 'accent' | 'ground' | 'fonts' | 'corners' | 'buttons' | 'cards' | 'fields' | 'eyebrow' | 'header' | 'brand' | 'motion'>>;
|
|
98
|
+
/**
|
|
99
|
+
* The dimensions the sites a person likes pin (AGL-3975,
|
|
100
|
+
* `jobs/ai-site-inspiration.ts`): each one present is KEPT, whatever the
|
|
101
|
+
* model or the seed would choose, and every other dimension is chosen as it
|
|
102
|
+
* always is. A brand the person gave in the brief still wins over a pinned
|
|
103
|
+
* brand color, and the hue pinned with it.
|
|
104
|
+
*/
|
|
105
|
+
export type AiSiteLookPins = Partial<Pick<AiSiteStyle, 'brand' | 'hue' | 'accent' | 'ground' | 'fonts' | 'corners' | 'buttons' | 'cards' | 'header' | 'headerAlign' | 'density' | 'motion'>>;
|
|
98
106
|
/** A job's seed: FNV-1a over its id. */
|
|
99
107
|
export declare function aiSiteSeed(jobId: string): number;
|
|
100
108
|
export declare const AI_SITE_LOOK_TOOL_NAME = "submit_site_look";
|
|
@@ -130,6 +138,8 @@ export declare function aiSiteStyleFor(input: {
|
|
|
130
138
|
* fewer than three tracked dimensions, is drawn again from the next seed.
|
|
131
139
|
*/
|
|
132
140
|
avoid?: readonly AiSiteStyle[];
|
|
141
|
+
/** What the sites the person likes pin (AGL-3975): kept on every draw. */
|
|
142
|
+
pins?: AiSiteLookPins;
|
|
133
143
|
}): AiSiteStyle;
|
|
134
144
|
/** How many seeds a look draws before it settles for the most different. */
|
|
135
145
|
export declare const AI_SITE_LOOK_DRAWS = 32;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
2
|
+
import { _ as _object_without_properties_loose } from "@swc/helpers/_/_object_without_properties_loose";
|
|
2
3
|
/**
|
|
3
4
|
* @license
|
|
4
5
|
* Copyright 2026 Aglyn LLC
|
|
@@ -557,6 +558,29 @@ const ANY_BLOCKS = {
|
|
|
557
558
|
'buttons'
|
|
558
559
|
];
|
|
559
560
|
function styleOnce(input, seed) {
|
|
561
|
+
return withPins(drawOnce(input, seed), input);
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* A drawn style with its pins laid over it (AGL-3975). Applied after the
|
|
565
|
+
* draw, so every dimension is drawn the same with or without pins and an
|
|
566
|
+
* unpinned job's look is exactly what it was.
|
|
567
|
+
*/ function withPins(style, input) {
|
|
568
|
+
const pins = input.pins;
|
|
569
|
+
if (!pins || !Object.keys(pins).length) return style;
|
|
570
|
+
// The person's own brand color outranks the one their sites suggest.
|
|
571
|
+
const own = aiSiteBrandHex(input.brand);
|
|
572
|
+
const { brand, hue } = pins, rest = _object_without_properties_loose(pins, [
|
|
573
|
+
"brand",
|
|
574
|
+
"hue"
|
|
575
|
+
]);
|
|
576
|
+
const pinned = Object.fromEntries(Object.entries(rest).filter(([, value])=>value !== undefined && value !== null));
|
|
577
|
+
return _extends({}, style, pinned, !own && aiSiteBrandHex(brand) ? {
|
|
578
|
+
brand: aiSiteBrandHex(brand)
|
|
579
|
+
} : {}, !own && typeof hue === 'number' && Number.isFinite(hue) ? {
|
|
580
|
+
hue: (Math.round(hue) % 360 + 360) % 360
|
|
581
|
+
} : {});
|
|
582
|
+
}
|
|
583
|
+
function drawOnce(input, seed) {
|
|
560
584
|
var _BLOCK_BIAS_kind_id, _family_headerAligns, _family_rhythms, _ref, _aiSiteBrandHex;
|
|
561
585
|
const { kind, answer } = input;
|
|
562
586
|
const next = random(seed);
|