From d2b4457bd74fa74266e20837fdb759be0911b964 Mon Sep 17 00:00:00 2001 From: Ian Pascoe Date: Mon, 15 Jun 2026 16:18:16 -0400 Subject: [PATCH 01/10] feat: add docs site and refresh landing --- .changeset/config.json | 2 +- .github/workflows/deploy.yml | 1 + .github/workflows/pr-preview-deploy.yml | 1 + README.md | 6 + alchemy.run.ts | 26 +- apps/docs/.gitignore | 21 + apps/docs/README.md | 25 + apps/docs/astro.config.mjs | 61 + apps/docs/package.json | 28 + apps/docs/public/favicon.svg | 1 + apps/docs/src/assets/caplets-icon.png | Bin 0 -> 166667 bytes apps/docs/src/content.config.ts | 7 + .../src/content/docs/agent-integrations.mdx | 76 + apps/docs/src/content/docs/capabilities.mdx | 54 + apps/docs/src/content/docs/changelog.mdx | 118 + apps/docs/src/content/docs/code-mode.mdx | 64 + apps/docs/src/content/docs/configuration.mdx | 63 + apps/docs/src/content/docs/index.mdx | 41 + apps/docs/src/content/docs/install.mdx | 74 + .../content/docs/reference/caplet-files.mdx | 161 ++ .../content/docs/reference/code-mode-api.mdx | 99 + .../src/content/docs/reference/config.mdx | 200 ++ apps/docs/src/content/docs/remote-attach.mdx | 80 + .../docs/src/content/docs/troubleshooting.mdx | 78 + apps/docs/src/styles/global.css | 77 + apps/docs/tsconfig.json | 5 + apps/landing/package.json | 9 +- apps/landing/public/config.schema.json | 36 + apps/landing/public/favicon.svg | 5 +- apps/landing/src/components/HugeIcon.astro | 19 - .../src/components/landing/Activation.astro | 96 + .../src/components/landing/AgentTrace.astro | 32 + .../landing/CapabilityAperture.astro | 16 + .../src/components/landing/CommandBlock.astro | 31 + .../src/components/landing/Footer.astro | 23 + .../src/components/landing/Header.astro | 79 + .../landing/src/components/landing/Hero.astro | 71 + .../src/components/landing/Proof.astro | 106 + .../src/components/landing/RemoteStory.astro | 83 + .../src/components/landing/WhyCaplets.astro | 44 + .../src/components/starwind/badge/Badge.astro | 17 + .../src/components/starwind/badge/index.ts | 7 + .../src/components/starwind/badge/variants.ts | 41 + .../components/starwind/button/Button.astro | 20 + .../src/components/starwind/button/index.ts | 7 + .../components/starwind/button/variants.ts | 38 + .../src/components/starwind/card/Card.astro | 19 + .../components/starwind/card/CardAction.astro | 13 + .../starwind/card/CardContent.astro | 13 + .../starwind/card/CardDescription.astro | 13 + .../components/starwind/card/CardFooter.astro | 13 + .../components/starwind/card/CardHeader.astro | 13 + .../components/starwind/card/CardTitle.astro | 13 + .../src/components/starwind/card/index.ts | 46 + .../src/components/starwind/card/variants.ts | 45 + .../components/starwind/dialog/Dialog.astro | 396 +++ .../starwind/dialog/DialogClose.astro | 35 + .../starwind/dialog/DialogContent.astro | 50 + .../starwind/dialog/DialogDescription.astro | 13 + .../starwind/dialog/DialogFooter.astro | 13 + .../starwind/dialog/DialogHeader.astro | 13 + .../starwind/dialog/DialogTitle.astro | 19 + .../starwind/dialog/DialogTrigger.astro | 48 + .../src/components/starwind/dialog/index.ts | 50 + .../components/starwind/dialog/variants.ts | 41 + .../starwind/separator/Separator.astro | 24 + .../components/starwind/separator/index.ts | 7 + .../components/starwind/separator/variants.ts | 14 + .../src/components/starwind/sheet/Sheet.astro | 13 + .../starwind/sheet/SheetClose.astro | 13 + .../starwind/sheet/SheetContent.astro | 45 + .../starwind/sheet/SheetDescription.astro | 13 + .../starwind/sheet/SheetFooter.astro | 13 + .../starwind/sheet/SheetHeader.astro | 13 + .../starwind/sheet/SheetTitle.astro | 13 + .../starwind/sheet/SheetTrigger.astro | 13 + .../src/components/starwind/sheet/index.ts | 50 + .../src/components/starwind/sheet/variants.ts | 66 + .../src/components/starwind/table/Table.astro | 16 + .../components/starwind/table/TableBody.astro | 14 + .../starwind/table/TableCaption.astro | 14 + .../components/starwind/table/TableCell.astro | 14 + .../components/starwind/table/TableFoot.astro | 14 + .../components/starwind/table/TableHead.astro | 14 + .../starwind/table/TableHeader.astro | 14 + .../components/starwind/table/TableRow.astro | 14 + .../src/components/starwind/table/index.ts | 51 + .../src/components/starwind/table/variants.ts | 33 + .../src/components/starwind/tabs/Tabs.astro | 270 ++ .../starwind/tabs/TabsContent.astro | 25 + .../components/starwind/tabs/TabsList.astro | 19 + .../starwind/tabs/TabsTrigger.astro | 24 + .../src/components/starwind/tabs/index.ts | 20 + .../src/components/starwind/tabs/variants.ts | 22 + apps/landing/src/data/landing.ts | 191 ++ apps/landing/src/layouts/LandingLayout.astro | 38 + .../src/lib/utils/starwind/positioning.ts | 318 +++ apps/landing/src/pages/index.astro | 1598 +---------- apps/landing/src/scripts/agent-trace.ts | 70 + apps/landing/src/scripts/aperture-scene.ts | 536 ++++ .../src/scripts/capability-aperture.ts | 39 + apps/landing/src/scripts/copy.ts | 35 + apps/landing/src/scripts/header-collapse.ts | 40 + apps/landing/src/scripts/reveal.ts | 55 + apps/landing/src/styles/global.css | 2391 +++-------------- apps/landing/src/styles/starwind.css | 135 + apps/landing/starwind.config.json | 44 + apps/landing/test/campaign-copy.check.mjs | 212 -- apps/landing/tsconfig.json | 8 +- docs/plans/2026-06-15-docs-site.md | 871 ++++++ .../2026-06-15-landing-starwind-migration.md | 1638 +++++++++++ infra/alchemy-domains.ts | 6 + package.json | 4 +- packages/core/src/attach/api.ts | 53 +- packages/core/src/code-mode/types.ts | 1 + packages/core/src/config.ts | 19 + packages/core/src/native/remote.ts | 51 +- packages/core/src/native/service.ts | 9 +- packages/core/test/attach-api.test.ts | 38 + packages/core/test/config.test.ts | 26 + packages/core/test/native-remote.test.ts | 34 + pnpm-lock.yaml | 1076 +++++++- schemas/caplets-config.schema.json | 36 + scripts/check-public-docs.ts | 140 + scripts/generate-docs-reference.ts | 311 +++ 125 files changed, 10075 insertions(+), 3838 deletions(-) create mode 100644 apps/docs/.gitignore create mode 100644 apps/docs/README.md create mode 100644 apps/docs/astro.config.mjs create mode 100644 apps/docs/package.json create mode 100644 apps/docs/public/favicon.svg create mode 100644 apps/docs/src/assets/caplets-icon.png create mode 100644 apps/docs/src/content.config.ts create mode 100644 apps/docs/src/content/docs/agent-integrations.mdx create mode 100644 apps/docs/src/content/docs/capabilities.mdx create mode 100644 apps/docs/src/content/docs/changelog.mdx create mode 100644 apps/docs/src/content/docs/code-mode.mdx create mode 100644 apps/docs/src/content/docs/configuration.mdx create mode 100644 apps/docs/src/content/docs/index.mdx create mode 100644 apps/docs/src/content/docs/install.mdx create mode 100644 apps/docs/src/content/docs/reference/caplet-files.mdx create mode 100644 apps/docs/src/content/docs/reference/code-mode-api.mdx create mode 100644 apps/docs/src/content/docs/reference/config.mdx create mode 100644 apps/docs/src/content/docs/remote-attach.mdx create mode 100644 apps/docs/src/content/docs/troubleshooting.mdx create mode 100644 apps/docs/src/styles/global.css create mode 100644 apps/docs/tsconfig.json delete mode 100644 apps/landing/src/components/HugeIcon.astro create mode 100644 apps/landing/src/components/landing/Activation.astro create mode 100644 apps/landing/src/components/landing/AgentTrace.astro create mode 100644 apps/landing/src/components/landing/CapabilityAperture.astro create mode 100644 apps/landing/src/components/landing/CommandBlock.astro create mode 100644 apps/landing/src/components/landing/Footer.astro create mode 100644 apps/landing/src/components/landing/Header.astro create mode 100644 apps/landing/src/components/landing/Hero.astro create mode 100644 apps/landing/src/components/landing/Proof.astro create mode 100644 apps/landing/src/components/landing/RemoteStory.astro create mode 100644 apps/landing/src/components/landing/WhyCaplets.astro create mode 100644 apps/landing/src/components/starwind/badge/Badge.astro create mode 100644 apps/landing/src/components/starwind/badge/index.ts create mode 100644 apps/landing/src/components/starwind/badge/variants.ts create mode 100644 apps/landing/src/components/starwind/button/Button.astro create mode 100644 apps/landing/src/components/starwind/button/index.ts create mode 100644 apps/landing/src/components/starwind/button/variants.ts create mode 100644 apps/landing/src/components/starwind/card/Card.astro create mode 100644 apps/landing/src/components/starwind/card/CardAction.astro create mode 100644 apps/landing/src/components/starwind/card/CardContent.astro create mode 100644 apps/landing/src/components/starwind/card/CardDescription.astro create mode 100644 apps/landing/src/components/starwind/card/CardFooter.astro create mode 100644 apps/landing/src/components/starwind/card/CardHeader.astro create mode 100644 apps/landing/src/components/starwind/card/CardTitle.astro create mode 100644 apps/landing/src/components/starwind/card/index.ts create mode 100644 apps/landing/src/components/starwind/card/variants.ts create mode 100644 apps/landing/src/components/starwind/dialog/Dialog.astro create mode 100644 apps/landing/src/components/starwind/dialog/DialogClose.astro create mode 100644 apps/landing/src/components/starwind/dialog/DialogContent.astro create mode 100644 apps/landing/src/components/starwind/dialog/DialogDescription.astro create mode 100644 apps/landing/src/components/starwind/dialog/DialogFooter.astro create mode 100644 apps/landing/src/components/starwind/dialog/DialogHeader.astro create mode 100644 apps/landing/src/components/starwind/dialog/DialogTitle.astro create mode 100644 apps/landing/src/components/starwind/dialog/DialogTrigger.astro create mode 100644 apps/landing/src/components/starwind/dialog/index.ts create mode 100644 apps/landing/src/components/starwind/dialog/variants.ts create mode 100644 apps/landing/src/components/starwind/separator/Separator.astro create mode 100644 apps/landing/src/components/starwind/separator/index.ts create mode 100644 apps/landing/src/components/starwind/separator/variants.ts create mode 100644 apps/landing/src/components/starwind/sheet/Sheet.astro create mode 100644 apps/landing/src/components/starwind/sheet/SheetClose.astro create mode 100644 apps/landing/src/components/starwind/sheet/SheetContent.astro create mode 100644 apps/landing/src/components/starwind/sheet/SheetDescription.astro create mode 100644 apps/landing/src/components/starwind/sheet/SheetFooter.astro create mode 100644 apps/landing/src/components/starwind/sheet/SheetHeader.astro create mode 100644 apps/landing/src/components/starwind/sheet/SheetTitle.astro create mode 100644 apps/landing/src/components/starwind/sheet/SheetTrigger.astro create mode 100644 apps/landing/src/components/starwind/sheet/index.ts create mode 100644 apps/landing/src/components/starwind/sheet/variants.ts create mode 100644 apps/landing/src/components/starwind/table/Table.astro create mode 100644 apps/landing/src/components/starwind/table/TableBody.astro create mode 100644 apps/landing/src/components/starwind/table/TableCaption.astro create mode 100644 apps/landing/src/components/starwind/table/TableCell.astro create mode 100644 apps/landing/src/components/starwind/table/TableFoot.astro create mode 100644 apps/landing/src/components/starwind/table/TableHead.astro create mode 100644 apps/landing/src/components/starwind/table/TableHeader.astro create mode 100644 apps/landing/src/components/starwind/table/TableRow.astro create mode 100644 apps/landing/src/components/starwind/table/index.ts create mode 100644 apps/landing/src/components/starwind/table/variants.ts create mode 100644 apps/landing/src/components/starwind/tabs/Tabs.astro create mode 100644 apps/landing/src/components/starwind/tabs/TabsContent.astro create mode 100644 apps/landing/src/components/starwind/tabs/TabsList.astro create mode 100644 apps/landing/src/components/starwind/tabs/TabsTrigger.astro create mode 100644 apps/landing/src/components/starwind/tabs/index.ts create mode 100644 apps/landing/src/components/starwind/tabs/variants.ts create mode 100644 apps/landing/src/data/landing.ts create mode 100644 apps/landing/src/layouts/LandingLayout.astro create mode 100644 apps/landing/src/lib/utils/starwind/positioning.ts create mode 100644 apps/landing/src/scripts/agent-trace.ts create mode 100644 apps/landing/src/scripts/aperture-scene.ts create mode 100644 apps/landing/src/scripts/capability-aperture.ts create mode 100644 apps/landing/src/scripts/copy.ts create mode 100644 apps/landing/src/scripts/header-collapse.ts create mode 100644 apps/landing/src/scripts/reveal.ts create mode 100644 apps/landing/src/styles/starwind.css create mode 100644 apps/landing/starwind.config.json delete mode 100644 apps/landing/test/campaign-copy.check.mjs create mode 100644 docs/plans/2026-06-15-docs-site.md create mode 100644 docs/plans/2026-06-15-landing-starwind-migration.md create mode 100644 scripts/check-public-docs.ts create mode 100644 scripts/generate-docs-reference.ts diff --git a/.changeset/config.json b/.changeset/config.json index cd68275f..d94dbced 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -7,5 +7,5 @@ "access": "public", "baseBranch": "main", "updateInternalDependencies": "patch", - "ignore": ["@caplets/landing"] + "ignore": ["@caplets/landing", "@caplets/docs"] } diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9d82c4d7..8b924b56 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,6 +8,7 @@ on: - .github/workflows/deploy.yml - alchemy.run.ts - apps/** + - infra/** - package.json - pnpm-lock.yaml - pnpm-workspace.yaml diff --git a/.github/workflows/pr-preview-deploy.yml b/.github/workflows/pr-preview-deploy.yml index dc833ce5..caa2c344 100644 --- a/.github/workflows/pr-preview-deploy.yml +++ b/.github/workflows/pr-preview-deploy.yml @@ -8,6 +8,7 @@ on: - .github/workflows/pr-preview-deploy.yml - alchemy.run.ts - apps/** + - infra/** - package.json - pnpm-lock.yaml - pnpm-workspace.yaml diff --git a/README.md b/README.md index 304eb475..adf82fdd 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,8 @@

caplets.dev + ยท + docs.caplets.dev

@@ -38,6 +40,8 @@ Caplets can wrap: ## Quick Start +Full setup and configuration docs are available at [docs.caplets.dev](https://docs.caplets.dev/). + Install the CLI and wire it into your agent: ```sh @@ -170,6 +174,7 @@ tokens than direct vanilla MCP. Live runs are model- and environment-dependent; deterministic benchmark is the reproducible claim. See [docs/benchmarks/coding-agent.md](https://github.com/spiritledsoftware/caplets/blob/main/docs/benchmarks/coding-agent.md) for methodology and reproduction commands. +See [docs.caplets.dev/changelog](https://docs.caplets.dev/changelog/) for public release notes. ## Repository @@ -200,6 +205,7 @@ Package map: - `packages/pi` - native Pi extension - `packages/benchmarks` - deterministic and opt-in live benchmarks - `apps/landing` - public site at `caplets.dev` +- `apps/docs` - public docs site at `docs.caplets.dev` Long-lived docs: diff --git a/alchemy.run.ts b/alchemy.run.ts index efe5d07f..e1d5a405 100644 --- a/alchemy.run.ts +++ b/alchemy.run.ts @@ -10,7 +10,10 @@ const app = await alchemy("caplets", { password: process.env.ALCHEMY_PASSWORD!, }); -const { landingPageDomain, landingPageUrl } = buildAlchemyDomains(app.stage, { local: app.local }); +const { docsPageDomain, docsPageUrl, landingPageDomain, landingPageUrl } = buildAlchemyDomains( + app.stage, + { local: app.local }, +); export const landingPage = await Astro("landing-page", { cwd: "apps/landing", dev: { @@ -18,9 +21,17 @@ export const landingPage = await Astro("landing-page", { }, domains: [landingPageDomain, `www.${landingPageDomain}`], }); +export const docsPage = await Astro("docs-page", { + cwd: "apps/docs", + dev: { + command: "pnpm run dev -- --port 4322" + (process.env.SSH_CONNECTION ? " --host 0.0.0.0" : ""), + }, + domains: [docsPageDomain], +}); console.log({ "Landing Page URL": landingPageUrl, + "Docs Page URL": docsPageUrl, }); const [repositoryOwnerFromSlug, repositoryNameFromSlug] = @@ -35,20 +46,17 @@ if (pullRequestNumber) { throw new Error("Missing GitHub repository metadata for preview comment."); } + const shortSha = process.env.GITHUB_SHA?.slice(0, 7) ?? "unknown"; await GitHubComment("preview-comment", { owner: repositoryOwner, repository: repositoryName, issueNumber: pullRequestNumber, - body: `## ๐Ÿš€ Preview Deployed - -Your changes have been deployed to a preview environment: - -**๐ŸŒ Landing Page:** ${landingPageUrl} + body: `## Preview Deployed -Built from commit ${process.env.GITHUB_SHA?.slice(0, 7) ?? "unknown"} +Landing: ${landingPageUrl} +Docs: ${docsPageUrl} ---- -๐Ÿค– This comment updates automatically with each push.`, +Built from commit ${shortSha}`, }); } diff --git a/apps/docs/.gitignore b/apps/docs/.gitignore new file mode 100644 index 00000000..6240da8b --- /dev/null +++ b/apps/docs/.gitignore @@ -0,0 +1,21 @@ +# build output +dist/ +# generated types +.astro/ + +# dependencies +node_modules/ + +# logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + + +# environment variables +.env +.env.production + +# macOS-specific files +.DS_Store diff --git a/apps/docs/README.md b/apps/docs/README.md new file mode 100644 index 00000000..0882b8fd --- /dev/null +++ b/apps/docs/README.md @@ -0,0 +1,25 @@ +# Caplets Docs + +Astro Starlight documentation site for [docs.caplets.dev](https://docs.caplets.dev). + +Public docs live in `apps/docs/src/content/docs`. Root `docs/` is internal maintainer +documentation and is not routed into this site. + +Generated reference pages and the public changelog come from: + +- `schemas/caplets-config.schema.json` +- `schemas/caplet.schema.json` +- `packages/core/src/code-mode/runtime-api.d.ts` +- `CHANGELOG.md` + +## Commands + +Run from the repository root: + +```sh +pnpm docs:generate +pnpm docs:check +pnpm --filter @caplets/docs dev -- --port 4322 +pnpm --filter @caplets/docs typecheck +pnpm --filter @caplets/docs build +``` diff --git a/apps/docs/astro.config.mjs b/apps/docs/astro.config.mjs new file mode 100644 index 00000000..4ba82287 --- /dev/null +++ b/apps/docs/astro.config.mjs @@ -0,0 +1,61 @@ +// @ts-check +import starlight from "@astrojs/starlight"; +import tailwindcss from "@tailwindcss/vite"; +import { defineConfig } from "astro/config"; + +export default defineConfig({ + site: "https://docs.caplets.dev", + integrations: [ + starlight({ + title: "Caplets Docs", + logo: { + src: "./src/assets/caplets-icon.png", + alt: "Caplets", + }, + social: [ + { + icon: "github", + label: "GitHub", + href: "https://github.com/spiritledsoftware/caplets", + }, + ], + customCss: ["./src/styles/global.css"], + editLink: { + baseUrl: + "https://github.com/spiritledsoftware/caplets/edit/main/apps/docs/src/content/docs/", + }, + sidebar: [ + { + label: "Get Started", + items: [ + { label: "Start here", link: "/" }, + { label: "Install", link: "/install/" }, + { label: "Configuration", link: "/configuration/" }, + ], + }, + { + label: "Use Caplets", + items: [ + { label: "Code Mode", link: "/code-mode/" }, + { label: "Add capabilities", link: "/capabilities/" }, + { label: "Agent integrations", link: "/agent-integrations/" }, + { label: "Remote attach", link: "/remote-attach/" }, + { label: "Troubleshooting", link: "/troubleshooting/" }, + ], + }, + { + label: "Reference", + items: [ + { label: "Configuration schema", link: "/reference/config/" }, + { label: "Code Mode API", link: "/reference/code-mode-api/" }, + { label: "Caplet files", link: "/reference/caplet-files/" }, + { label: "Changelog", link: "/changelog/" }, + ], + }, + ], + }), + ], + vite: { + plugins: [tailwindcss()], + }, +}); diff --git a/apps/docs/package.json b/apps/docs/package.json new file mode 100644 index 00000000..adfeda51 --- /dev/null +++ b/apps/docs/package.json @@ -0,0 +1,28 @@ +{ + "name": "@caplets/docs", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "astro": "astro", + "build": "astro build", + "dev": "astro dev", + "preview": "astro preview", + "typecheck": "astro check" + }, + "dependencies": { + "@astrojs/check": "^0.9.9", + "@astrojs/starlight": "^0.40.0", + "@tailwindcss/vite": "^4.3.1", + "astro": "^6.4.6", + "sharp": "^0.34.5", + "tailwindcss": "^4.3.1", + "typescript": "^6.0.3" + }, + "devDependencies": { + "vite": "^7.3.5" + }, + "engines": { + "node": ">=22.12.0" + } +} diff --git a/apps/docs/public/favicon.svg b/apps/docs/public/favicon.svg new file mode 100644 index 00000000..cba5ac14 --- /dev/null +++ b/apps/docs/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/src/assets/caplets-icon.png b/apps/docs/src/assets/caplets-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4eebda4b695d4da4b27c3ab8a78ac27779353b97 GIT binary patch literal 166667 zcmeEt_dk{Y|Nm*c(l9Hjh-fH6C3{s!h$9?(W@V4#9Aq55Dti>kCNd8pdmpmbk$J4+ zSjWL}$UHcl^SzGO=YRPA@~&HTyIr}i>oM++`(r#GSE!bz3e)-P=RqJ4lj=()Z4l`6 zBK^?QdN4U>piiG^-AG4G+n3l z=Qd*H$hUkbkK>pr}B zGb}Lhc4+cgZ_sp#E!_6Nm_Sw;ks?4fQx5`A*h`Iaa>e}7bYr-2>DHhORHY#l@_BOpMFNDi+rQ>|MFK=zUw^Mcr|Wn`$ie( zuPN;bqY3%@F@$!iMQ?b~-=9#qaH(2uP$1h`pt5OtFDl@~xslX^f-c@g)ir%2mEa=A znmnGLHdXs0)}??-F&tHW^j(1DU{1C1lKjNKzii|}m58e(H&~Vbg~6Xvh+~_drvlO? zL~2Y-d53RRp8|1BA3u51p4X^ML3B2mX*8uwVqrYeCp$A!8zS(b`RN(R9Z}I!*Lr(9 zd%wptTfDHfJww8LsA=x)txbGZ0e_faD3gb*c?RiYvOPmYJ`+>OI|KdjOsrVogIdA0 z*8^&>7rFwF8woGMkh;#3E8a>Py{u;HEJGsN`Q1;ID>%bEYhT=6l~~PisLNO@nl%Am zj4kK2*S{nBNpHeA$Y1KwuUsr*`rGcF%p|l(6BTDEVY95x3Q@||W`pr*UWkODnXFJr zg38$!b76;-<3X-<#P(-7#Yyr^zqEaw1n?88w5|HcB3-`Gs(>Yhq4bcLS!;;hHy6cJ$l0O0N_>9$@Yfn$Ni7I2g8K%;8tf#w){IQJ z)=apVy_h(HSspNRcrgXW$9T)xzHX;xGGRj*A#{KTjE)bm&eTMe|g_NlEjgee^5XiA#%^-Wxka-=f1& zytx15op{YUa-ibq?KTr$yWPijMCAf3R|oubnyz*yv8gx(v<|3nZzTMPlARl%l{Fstk`~X+fL_J25X~AE z3t6T-dq_NH)ubr!v^xQtjv}V{29p&^)Pq`-*$7$4GujnA9~(C@BT<3Oppr~h`g^Zm z4$4BJZn3lTYp&EXw=^v-E?UpG?|2Mw}h?b#_S*7j!a=Q9Po_)p@*b>XK9N=Wx5@J4L0IQ~H<-qKVGYRTc#EKnOQHWpOjse!r8g?2Rj{TdrZ zsl-$}BD6l9gDN5i=({Me3IEU+h?#!E=0F6l;i+$R%vHEJe7+BMpd+hrM zHE|~cL4IyT?>V~^_zKHmbB>G||8r$7(5mYNnaUm!CUC$cMx<^o#<2*syh&L{JYA`E z;o+VoY*^`Be1IHsowXxiG@;X{5VFMOPjssT)(xwk7(Y`zC$ z`z;BQyy|xcyE`dCYmLKIFGjnXRr~iBrPe7aWh0*)o@}d0`V0Wii7qAA1Mvu*$gMUh zOfLsNpW`UH$6bYoH#f~=&MWm@cPQ>C*|+!|+cPfED}C?Z#NR zI0XuMasmsUZotQ-Q;LhJXrT*UVFix)$oC=T&0OrBAh$8P$t}3p2No4bQ|gR_5x{I&Co#NN4{We~kH_RpV%T+t-i!!9v;T1 zuFb6|IVdpP7=eOH1n5bF*|kzyGudY$sKrQ0N!-~;#4go+&rty>kRKNzX&`b%wMe?Tr8{0MJ;Kx^WJysu0 zE*x&5{o1lsrYU+rR5v|2>=i-nf8e1-_cv~L7Zjs>+}F)6{dq(K@OBq~QDBQYe>!c#yagL71r`9Ug**4m+P)Sz!l>GLI83XObs z5Fj`#rk@HN2?Xro=KWAnPq`vdtFFlAD5%1tJ)b`vHlWNxOT~@(w_P~908nNhQ1EPa zV>=p`W77`~`*EH<&U`=x3(*lHn8fzIeg^pcHsJRr-004iV7QCXl=^RH6X>DI}3YuN$cr*hh&cEZgMCU95;kW(gT#RbILF8o;n zXy)@XfSe3qbC>iW4g@6#e(6?K_bp+`b@q5}9~Kr*Ak&0BqL%!6yti6bmeG_i7R{}-M(6}f~=@&bJLi0!ZUX4UO z;Rg>TdcB64Too3k2C?6wePDF`Cy+gwZrry$X{AP(iV#VuH$+=0Lg7&Q4gy@DphWi$ ziHQjM(2(cQLKjITIHq$q`(oEyn;7JVVFo z=YewzCPJLzg>hwQSrXg2jPLFia3@HKZb2{epJ3V{!k=W$!NFmp1?h`5cKj^`GPqAS zpkP|MLJ?9oagqY3X_xDW~txnE~Wu8->bw7-BOcI$$pQLKT+x zgTqa}qH{|re=W{}5+2i0)jc9_Suv=VrA-eO83{qVRQP6Sw14j>*P}?Re&c5#!(rW=z;)ovY2u!+R?@vY9#SZ5V(-sphg z76kQY^7^5(0D$Q+3A!yVph}6n=F|g-zBIx5d)#nT#!t{gCVH^4^U9B9B&rno46eNM zS*l_2SxisYLnP28KeD4kIkc{Fb&m`V*cBq<$bpPN8yJhu2dL{qC?NYoQ)DJzW?Wc^ znjBa6;o)^D@~SBJZX?tVMaNOodpZJSw?w@PkJ>A6ekFryx>^1YPtO7{W~9G7{~XvD z5@#v*705TkvET&X?n^vJb~K^}>hGL=6$=1?W_m;_;!L*YzyXWlhzhTMvulh3`TlsW z6E{FyTJ(o}=vNqP?!Tpv@mTnhjQ_%sM*HEaa6qlnxdTYhOx{fQZ87(o;ZZndIYiOcS*M(?8#e}mF}o69E|K%nb% z<45BvXFC)&^7~Q#gb#JugK8$6=+^*-DI9bRHw`XUk&w=DCZ;{FRh;7Z<(4xsW~K01 z{k#|;1=`S45jR;xVnwJ5cmD(Oe2dXJ0#Jw@hu_s*`vRmkrlPkG-Bn|k?mmr6lb}FO z0%=aKkuLdodYv5+f~#J08Bo(r@L~q-^3zcpz>!vI1ktWS87fc{oHw)h&9*6sO$O9% z>@nODrsy`0aYWi35jYw*zs$~+_;|;r1Gkre>7hf3Lrfs`1X?VGh?wG76_dR`u9UJ% zUZ`jRdXr`7W7H!qp*=ITImt=vlyD4>$pZEofS7ad$sMHCyvL?fGvg zc<+{_9nPwoZHa=D;akACqtUlb5J3^ak>9f*Fmhfv!4Zo;K~ULW?4WPq^l)+YyP4}Q zTmy5&bl&3GcS8b>GWbLfvJTp$#=EV)s!(PDHhyPG6=?>Lx-y+?EAK`)rd6-BhK9sm z0!!+p9SwKTc6jPHI2!#YNWjd7p&iiJV}oN|W^GfjsHRQfZ)osyP}3kit$w?cs9scL zgRQOb82E=!|JRhCiS~`IsUC`MVoK4^G|F;60-p}_{`nK#J^;fcaM9JYpTLDVLPFn) zdg6iFIF2AkxKBI$hMU+}wU=N4N?sG(PO14mKKhV|s1E>IaT~4t;g;I`EPeoAzs?M~ zfIu^UGLYK&K-rfCr@Qz#OPr&5&K?j^Tam?bR{zP43rFoF_SYV)7;Dz-2657Mo3V8^ z5A!}=X9XoNrhfwnNLLw>g%oh-)5d5aQT?*w2Lz%Rf11^4_OAllsuQj9uYF?zzUU$I~6NC^|<4v~>N1G+h< z!vfzwo`6S|h1VxKUd>4y@f>`P8 zv69mBoBWw`tzGuHDfPSN++{xe5FpuDnA59Ik(w9jfFJz#Z^5vqJ;MO~YVpi)s6$(c9*9+75vag&NG2ji z`NJ?FPE2upt{namYBPnJ;xD3Uf_dflfg3Cdu~4AsVj|)b!TzfSxFeML zR>6=9;5|v%qpJ18{Pn%PT+|*g4fv|3kI_Y+kSql3-DG*Qmmed)FbhmLzJe9zPcOy- zv8qGHnH`Gab~gI`s3Jt(S)h@pH_wG0mhv^byezq?o^vxlqGjHE(E^ZDc$ovy0Y*&n zD{Os2!O)>VkCA$bH|3PuRiKd#gcP2`3%JiI6{v9sOdAqteKkJK9f&d1^{>PKipKH?)u`>sYr52OiqonlU*KA*zRI!{BZoHm+MkPM-(5sbRP%P zx<%Y$(qT2IBnb$iCWjvaeJHDBEtejk!buhJLr>Dy`f-Q+LoU}rpr`51@g@R1-g}2) zx#=ErCO|I9f82VZ3E4pal;WH1DwvR6m<0&r8(0=E$-N28otdxElgd18=WfIPx5=#Q zjNVsI1C2x&P}^^cRA_coY5+$&T(|^NC?aBmKGHG0Mo&6Z3qycdi3NW**dP} z0=K;h_T98HJLpFojgpH|d;c8k(o`z9ZU~kn65~zl@W_H<+Kiil#4R9+#R1tWP!S>% zpQ0Bh$z~{{AkvRm8=C$bzwUkH3a+yUl%lj$$`Q ztUi!y&u+5#>ap-mXmi{yeW9{pIqpAsPi*A!uOHQMO!+U`1I1AshWSj~a7EZ9 z6-kDf&nj&|G(CTF4oM2sZl%z`!&;KW0T^GbN@y3v@rcudcm9c)1AT znn2o10Mp$>*{?FoALq~F0Y0&`0w%NF9qAs0ljZIofQUAN^lftk>deow0Du2|pQ0Nl z$?wr_&+mM=WEDN8K_@R}exgXgdlPsYtixm@(vcb}7yuCL3u z_UT6{P~YYUx7apHt!RR{{sq{>;va|SHEK$NZ0?)YDyDx^5R_nrgYEK3z)U6DPIU{~ z`wKczUO<8F$bII~j3q0GS+4gHpu;OheA0UQW_7sPb~7q~NXf+t14|ZhwnuFupNmc5 z*ipga#@+OliE}kvfr?D@_`aMJ~*A6_JOz2lh~_dWL}=G^F4{Hx|=C>vKuJWx~Z!lu{`+<2;_F}n7lJoTx(pn z79)YAibT%61~fazX!B3tePH7Bo&|qqv))c&A2UtqDE2)%Hiz3iL&U~~g#vTbZf8$X z{UXoN+tVO}<-M$vf%mnY1@I|IMqAx9$~OPup)YPD2$u%0qsKa=pIWJJa@f`HxA6fu zm06k9N`cOCm7z}JJ+A^Y4kNmR9@(~CPH zS}`Xr+UDlZfpVIHJqD>qDY;S`XwQRnfk{rN- zVXa(HklW{cpvvVlQWewkSsO~*D?{v~F*NjlE;cFzVt@0Kh^e8e`-m9LXv0$vBzRTP z@Wjl`&5RTpB_Hg!s!rQXEv8}rdr?J=_0jL*^sUcBV6&;ZdytU`U9IQRAVJ1-HQ-HS zTABiJ{PJs=9JC={+~)NE-E&+5Q^EQ~e=_N-nwTu(Ns!+8pwg2~&sY^}7A;w#8j^cPGW zlA$^t$AYAZ?5vcC{}KnvZyaN5YiliO;)Go6Tmlt>=#XWIL576A%?7G%*@f*(Rdjv@ zYB&URdP-lyb^LZq?Kd^S*ABX%LRNq(-M*K{c|agtB}MqGOHpx%#vNB>ob;xs=X!CP(~*eyL;ju=wW~(|anWdmoC5lqwaGi?e|}9LH*6{X_OTe{XAQ8#a%PyR@Nyux7Pq_DafvQCEd1>3fbK+EWTIh zWlK{x(0URY%UxQG@+TRdg`CY61Tjm~ks?2+rd$y-G2*din9H*j%0k_U&%xdW0xY7E zp6oj0_xD{*pnXi{NLyQ_)<;P8re}2iUp+-D2?p-^?cUL;ApfRCXvpOfaMRtbjt=>~ zqWNeUqbp=#ap*tcT4D?{-!tC;qxr5N4`T_}Z~e0Kr#mhg0BSJbptHH(4iS^K8`o2G z$T=eZVmDW|GVGsEpn_z24Tbl%aZCfy38*mTnT{+==PnE zd`qX>P~DaxZtI7lpY7y!&J`cDNF4nRKju!*11vq)vzU}n4{F35Tcy4LaEy@xF`NVF z?13_8cRo^*y=Lk6R{919jZjgX2rmN^De;>WuF>T_3JI2Xl{ES4VEadYDjX>E-qR0j z)c-7a2mpB#kb-AFZD=L>RUNQW2O9G_9?&FLImK9-szaE5i&&kQc{&H=vxmHtlHmEu z8+T~Cdq3chi|HO&DWTh!(CD`Rw^Xok<5%MNH8w)4RNCniGfi}R-5sE|m%}y1T@3hf z9vh<6_w;0D0rTl;pEUEI+vw%FU_l*f?G=8YzlF%2Iob5S&5jWik$HVF4yw7}9v!eJs<2t*O8Hx!45X;Q zQv^%!VG$F?1Tl2#12U$qA)L|iAGangAl`31$uPMCBP~SefQ`t6T&ZK^L)H?(0dwY3 z8&F1_{*yCJvzN|*-hB*~8?NAjZhzTawo92w0IC(x%wIR^ym|fN1gFci4n&}(jTZt1 zF`osB`|kh)Yo<5>gHgJoGY_}E0!<56GbIlROc`y2zE%PO3OM@a4^j)alF}K`I9bYa zG(zkc7PEK>j^abKj;1u+*4_P{^wp4%^U?o;N>EHWz>1>5>j^15QmrjCHe6Ved~Th# zRaFn2=mWBRQ*#B~2^=U-yt_Gdg?*i;xA#el!L{!5779NAA271VA(7SwGE(@gc_c~} z`Zv_R>Kx$dp^b@^ARd|7J?GMDuh&SVLvWe47=r~Z1GvWsDKPT=B0;IrY5HFJyNL}k z#bd0SYm7`mRQ&Od@ieQ#q-1yjFcJnxH}IwC#|j7A?Hj#}3sU`ln>@$#IRh(`pf0=y zPI`QS(~WEZWG0et&YCnKw%MDjFiU&<5m?*+jnc#DLcao`1|Y)8;HUSxxB`!WVNuhp zx>zsUoYDd?U?Lx?BM2PkkB@1}0>59T6HL?X>wRg8=`(@y(e7Lhu{)sQy~=>>;u|io{*R5 zu}D7-Ns1UhQ-(g#%N3i@J~klv%L7avoDS4<$j36Gw~mW(FuimPbgwk^$WQSfweJuT z76t~5tUvP-PnEa=km7c4g0;jeXsroR&)ci-~F}{uFo>#5^piAI8Q^L4$P)&I;Q1(cNr$Ixz}N`H(1rM zOh7sQ-@^%!WfDid?LwT{@F=7di1HDzz2!3qK;J->W|sz^`=&6l+r$I@KiQpuBD3c2 zVQ~H1{_ve;C4}h965IDeL)gxH91XXNigjY_rvFZW-T@Ck2EdhGHUgp+N z8ae0hM?H`_kbo_A9JyNrGBvr6@`7m~dbojhN9a%hqAg%+y1|z|QZZm|@&FoBgONEM zgJAk`gsXSQBNpm%`Q&Lp(-EMRPoo{Yle`QO?dNJSJn`TJT?loEvS8c=~rykx1++Gkaj?fi!pQ9H@ zTZdH-k0HqLN40|o3gETUoeOYx7tq%lKy)W^OKOdP6U?_h}1QnT<8r zt((@7*Bb2lryIz^!puAdT%&akgdlWHhGc$QjgeBTs;E%RB|=iVy3kx}s3dzXJTa)4 z!TnPVYlV3baG*J*US#?l!cW1MK((vPvlS#1+%$u1*Bjj-1iQh*&Gzx1%J>WS4f#O;B0+VP%gboM@Uw{fE+8xx(AA&gr-S zifDXF{PQ<+S#YY+*`v!2X~XIBIj)|pl$Ru1qT2%!)udEzl7Z^hRO}avGz@0&$li-yd zJW+l77rw()amWzKQ0I~N_Slh+Ej+z%$CL$FaH@#SfNIxG zkSZ|gVR>&Mc#O;2cqoiCmAStDZV8U5nADMxaPrcjSQVMd6#^?yEfXa7ibGaH{R(&Y}A2GQSqpT8sJ{Be&}ws$Z@oZdSzNRcNsz!s)`-=l}KA!8Mq!X~d_5 zy!Cy6uFu=;sdtuNxPQZUIrzHyfOfp&o=@!y+$NUlg8oc=((L-Z49n(xZ^yajX&&@N zY{T2ZV7Sbu)k05~mc?+nZ(RBl@^(>*TajJf0xKeCcuec=%In76(N%|0S|g1{8=GYs zjF!xYB#OLxj1CI?i5%0n@ahfQ8dd#=+@8a8!bin|&TZN2`f+Rh($0?u(k|uu$qcJf z7dO-WsbvrSxGOPrQ1PhB6Irq1MpyJD(!2U{LKZ<0K;0QQlF=|*NHh|6ow|pBuF)e- z@n064Spe=e%5zAl%739!W}P~9L{^vq>d!D}g`|7t2S;F~=W!mebeA}wW;=>jukL|u z1dYVIX2afG96V2&x?1<3$qj!~b#AvERXLS?OJcV42OonzU2ePUoL)qk__4As8_{K%?)vGiyDz7Q zGJd6A{#n*wy(SjVGkIF&twLF^{VIx?B&zNILBJk)aq@~ioC{rn$|^zJHghHQw+4G= zlE{4(#u&}cInV=kIg4E%vuvl_V@NFGg3a|Lxf2KF>&4K&zXsfrVWpH!1A^vpa z#mdoT6`r7dwGyY0t?HAQf%rn=k*fJ?lhQ(|R?WR{VtKlW%M|-kNB*?GZ+6VU-I!zA}zdL%M`gxj}g>uro0t2hnmb$_I) z$rK$`{z-ZS(TVMzB)kw_t|jgxTg1!n@4R|sJ;dg_>==^6$#f)E`ti?`2D=E4U-u2) zWq!)8@Tw>@8PGjs$DD(P!qi62W1=+}WOm%~%x>dkczBn*y5e&tT6$6IQ^L<{|{GoQcShdOGW1WyKW$saEt)H@%k zqc$Rmw1u>~wJ*RCar0_KZ*O1Mga&7J(In?aEwke5~GFrU(J%pHU>r{n-q+1B3TdK!0#`=Qu|8cs=U|lwi!xi z!07~*%m-Ga)m-1XA%9h>RKicfN|yWb-<91I*kYllefHAW=gXjX4~X#@!0y3Y(e0kl zSdHY-9)zi1(0?;0_CSaeoku^l&C_NsnAdEI(brgi`jS__(7n*tuL|jV2@!i_xTV{; z7>$Ce2PuxTHp}0KsnQ+~J>l#Tl$ww+sSwp3f2cf|d}z%rrekXp78)ZCKmSV&BBsj6 z&ue+j(9McpNmNGl-}@Bpi`}Y&{Hn&KvvvNa*pDppLBsYJcelCK-5GY@Zi=Z}h6x53 zt`c99*x5!@1!BsX0yI!~erca67k7Po1FkEuTL)OD%G3qnqr|KXC_&n#ab@9W(H}D% zKK7IO=sh(ih_<^~)svU6P73o|?t8w!D%ti}Qgr(ll-01pq$aCq2)ExeFUX-B!{0nc zEPWCrerO_-{J>OuV(Wvf`l{YaXhi+X3w_;nS>#-wu`A3?Hdt59r<>}Le<2bnJpmbm zl$mRwd*9yxvvc)6g_}H-ykJ+tdlnG$N8o(ahLUO=umUx&+hkd*InvDE@kj*NL9DFo zah0V%6lz>i;nD(ksoq^QuQ=zE#OWJ%7$9=)#<#2|XNUC#_6--D?7!N|xKs^_|F%(x z{|%q7`XzqyxC|nPLkCzbDvon$PGJj$)eI z*MMNO>SJ1JgM6xeYJTR{Gq+ri2VAYEdEKXji~Jy={vsdSOfnD@Xm0)aa*134=O%Vx z^zCJ#j`tgKt1;xV9*z?8E2jpZ2b!M8XNlhQIsA3vDZPDCj77{Sn)c-9a*5C=c?{Fy zq`M~!AyU+amdtu=VzZfQbn3AWaxb{Of?)f8Ktd-wwr+)E3_F<_IA$YL=qNOp`|Grb%x6&MhBad~G zPMqfLcydr#fnD;dFI5n(iR;Rjy{Rd zR^+^}w~8(%rY6V1I7h`qq%rb^8O&Xp)%nG#k{a{D+wEn#YjKUphO%vNrb+GBUUs_x z;ftc5(9$s-(i1hs(Hf-D@Q?A*En2>Jk(kD~JLAP7T0^S@O9;$!Pmn+S5B@3hs#2DTmtwI1KS3N921N@53pR6Wb=xQuyJKOsAc@!z(Co6B4F1356N-Fx@ zF{}Akn3$^BmUZpTRXxm~^d?qb@YEqdVV+kpvYu^`MyEk1=_SNv=im}xqphVK2COm3 zu7Il=)==O&LlE<$f1XdyYxVE8%M_Fk zRlldkG>q9>lJ7FC6l$+*u>QH-6(J>^o0;9XuFIHca3{;($e@{A;~d@2NxuDR7(ME2 z-tkv3NSU`pJMOSBbll}<6>;A+)drKBrj$-T+JXPlSIBoEG`s9<> zZE*)pg}78)Z+Strzv^S53fE+G^OXQ=(aT%hjEaGMe@syDv*KGf`BVA}rv=Kp7^T3Y zus1Inb0%TbS4k~GcOY^xyz}GB>O8EsQpw-dz`=Fi%kgMs#vzRg<6rrPo1-+g`fs<295->QgnHi^TN+9<7ffJBG#SZ!j z_>{;rVk%Ms>lcpJeJon_!t)_(g}aLH{FK`->FyfVdMRTj+f8X5&&vS``sJ!q9=!(> zSv}L8GPKYCkf!go2je``my&c#Y+AYo|K4V?8~(_vs`@oQA$D7M3YUK>7@$QQVafi~arfkki?3Z2jF>USfc*ww~oz!Kbi?^eqOkdF# z`O3bHF=w?e&fv1fGAt)@`U%?Aw*ObFqsY1aO{k#!z2SwaCj=RVwd&OE+EUl^=0fpg zO<&Ej3%ap8bM|hk2y24&o08Op2tzUBvjrLub9;1^r=0QJsBX_E2XVshGOp*d`9Hg% zB(~9jbYN-4woXvzQG9NM&r{6((TU*iFV&O(pv~JNOy?*?UNx%g;ulUh7^xFq6v;F) zlv=nf%!ih(^bNM$lYVAV#pY5PbOOWfr0L;~mG(azXuKWongYw~qf<() zA4LqwloIr=&3%CoLoM=z7W4sM3^NR7m^(%a)_$RYOTsDMf6`TaST1KJFX}* zEob+W-H&Lye=#qdo|sigy9^9$7-?Uf3aVb_UnphH@bWUmL-UtJ4yUM#8D6de+ShBP z@9LZe(U<;%V|H=NaY&Qxkl;p-$vdtI@Ni%uf=&=DxO(6tH1B;pf;t0i;K6NQj5-1j@EcDKv zYh{$Em`$nS&>S7m5*rkfB?jGz`H4fc<_!Kp#C@A=yA%6LSZ=T}nPxEdMyGkLx>^%u z^L}V4&2V~X(+C+zvm(D% zZ|qsCDRGQ2Dk(A9)DhCv7|mHPwdz%2_JXG~Rk7#93&I_9%u7*qRVeBpNqGK`ZSp7>?|o>_Lc9IuIv=hjcOy_WprM%zF?^3AoBNc z^!n2*oyFdp4W2IJ zVVaMaO!$*!m`xPm$+?Ph4n{eoglm^yLpronX>lyoV%|u?HG;`GcIsuV&fBM$V#umS zo*d$+tOztbUg}e2K6Y%Z-r#(e8V^tQu*2ZV_G~UNZwgV?@y_9!%(~G%xtOLC2HXHZ z1=Gc|f#sGD@4KzIVYBNlbqknWtN=)`mrk>*v|8F8r)w=~vH5#U&G05n$PBQtm z1=3*Tt3k<2CI6(B^P06G0DK zUuTiIOQA%g>mv8F|uFaK^>|AEt#n&b#t*nkcS*!W-GlK^; zrMmGm@A9uSPN>*3^>1oB^1a_hN?rtPvNzEyU$ni_qYFn?C6HVRXB`22J?g z8KvrFG)yTan#li%tv#pM~C68zT3_|KeIm(<1O{qI*dw&v1mQ6-?ji*&Q4 zg}sF2GZHgW;Df4A*CfhfKm9~YFN(gGx}1)3B}%w9;@6s2pNIjgka5k!U;btDFQ<-Ewm`^Nss;x$k~!_rT7EHWuDh zf*XEHUeCS#v~*lqyZ!6h!*hM5nBhV$#p=SaA{4Q&#y#VPPqw+Xvn1d)c2S$=u-lV8 z-6O9E9XiB8ljrKQpSGuq`B{3e>b$xPHsowf3eYGLi(7ps(jk#;U;2B4|CwXWyT|gU zf4|Tp?bryEJTdu!Cu>1{+9j-|%WKA(s-NPx0_9vW3)YL6_xZc(`mTr^zM|cc;Qfk( z^ekXwNEBA9kgPV5y2zd(?Axbja%DS+6nnKy^L~oD0`1_ye}A_@UML*4h17rw*`!M@ zzl$yZ@J1SRi+-FnpbIH?5Lg7h_@KLCG9zKW)!E zM%ik32Y!IU>NCW>BKjIig66K8TgB=YB+PnEOv_F_4_oZD0sJ>9=;xFZ0K= zfNzC&Urcn2gOg(Vvjm@45%`DK-YU!Q;9Mrxy!yS=v#zx1$(VaTz5Xb6bHq+ zu$xt(Ztr@HPVJ?2GhE>~xl~wMQT8^^rEH7ou1I#roZpnQc6(v*<|y3kJSHH+79AIW zYygt|DLo6dnNP!3U>K}hYOii7oK&BOn9Fk%1aBg9 zSWjl1+8o>yxYmmCb6)EyyuH5EVAEFh#W$aw)yIdT#{xx?W4QBKZpy1YF?FW|9e;zr#P~_GoHpI*-5E zVSRCvKef_W5aNlq@*{bV$c77~_)N~b8;n@%#mpmVx}|dL(+oZ6`v-at_+8|5 z>e__ZTW$-vqV+p#*50WWyxYCQH}0ltJdkfG+_M(zVikzB*9Ut=kfzxzjSwgYayDLf zTF9p1(784OyHh+Yr;5cv7w}=(Xw8BZlXWe9vG>BDEc%hA38~(LkB|N}2EXiDCNPCI zmdOFwP-nZwTAWiBzmb4oRWfq7 zF|whBfd^ksU>Q}Od{K*;1ojToGF*AD-(J@VENnJY)RsbBA|o=_tC( zL~j}+mzu%SA!KHP;PDUaWuF8z&`k( zii|qKW;Z@Q1}E-#fiw> z(^tEACswNWN2m-zZ7inmc_vtcs{bj?Wa8~BoUQF<+pvZm?jw=``hy^ul>^6)4mctnXhF!T2|qtm>NH z)}x^5|3}hU_%-#uZyf7`k^+KA3J53&h;*x{Nax4_(w(Ezf)N5r*Fa))GZ>B19V53f zkQzBqVlYPh=J)q6oYy($xu5&GuJ=W`{9PUI1gEpm2Q313wbFz*%SzPP(_wHOiF6?= zt&oi$I5rnd*DI;B6(7D5@2bjOS0b7mK{&M)rPaFYMjXo)$`WN%X2*p&b&pjf0GC}X zxl-+;ouELkLVIbFtHZlUr2fQWigh$tXtu7GV*0K+m}|dQNcCE}*qjY9Cw8u=)7lN0 z6>DN%Tv1ESY3}GM#mk{TyxWf%>>=kw7)q<_^tIeiUCpwG zSPqM+XWe^`ay2@q+^=G&^AQpaVbcKIpay%+xbbC>O2)gL2&X~%${Z#aNVsL9eA zN@C;I`!l)*{-tDZZrGiNj@BSP@X!h)x-~cz5rMx|6P5ekI@OVLLf6ql z=<0~6-^%dwi^NBL%K?y!GF%Bv2mz8o9;RN(-|XvE=ZC<(e4sX{uSc#zlO;=@UqfmQ zCY!>AWNxc3o~_Oao7XeI%l&C&$-wo_C~DID6kgEoH1!{$KIy*FGaQ~wIw0q~D>qGAHzuH7eg(Q(x{nnH|34&RSG5xQ0}A4lhB`bSFJc9!9%4leadTv=oB2YTEQJ z3omxCtXj|O^Dy6(2}ql0HlIW8rC#Cs~x4@fxYyN9cntA*>jS4&DblXA-f#xJ!Vp@5cogP3Q5uX#Cf{4bVdqVZt`1*vhAf12o3oF z(Bba3>^(?ag@w8R-T4a@1~p#gWot$=@2Q=ZV}UUm8`eDO>a>=<@vcbCPk98`9#l;z zPHKu!8)ZxM+A8N$-_`iM0jBVq9W&G@^IqwDd&?WO)#PsJoCjKU9D%6~B5x&fOEA23 z_7nE`h@R+UZJOqvCH5E@%{C0KdH z&8@KO6g$pvPFXJFg>of?pFsGXmw+dBs;MHhAK2+8Gs)?DI_mU$*HtoEWy(CGftJ7Z z4dS_9p$}t4Iw!jLR<3tM)hYl(eFLdLV(y-idC|1y%U+M2 zXP>uqd%d|-ujhfir$oQ7shK(lOoaAXY*n+S{!ynRo2UIZSw2Q7{;@htjXTJhS}&M# zr~Po_pIs#IT*YG=z29nyovltmmN}Py*~Wriv`DyNbhI9|=QW7NRGLlt(6L&tzclq` zz*M$xt#Owjg}j>amB>$}g-$nqGRq&O70z!b<{g<9a9{Gg3|P&Q9~9?}{QX(xDSpCb%nm zVZF!Bhu;|G_e;92=wCcqQw$wPCG(AmWLOx=(3VH9DAg-*>m^Q->JCbv_O!(;WW zlQ6|(y}X0Vc~$rpx#K3u`W8(};0c0brpE@)sCU*BiU(DSFl=PRxqp}FsDy`asyo_L6#+zV|zJno7qmpl8xMa!y9QR|B z21IC^H2iF1gMpHB24_EF5I-d}Eoi=f7#d*xW$c!m25d;thU)ZW)1bAXm}HKl_mr=O zK%aUK*9!&^fuq{`K@>p#Z(rT&++r_WhznY?xnocVd`_jLYogbx(#QIh^c*Zejh%c^+Hbv!5G{DNNVg?!bTeAE2CLP~-2 zNlKa$s!YM5yVg}u)h@5kr6K(bmVcHPZM5{>OAj5>qeIOyUhD!M>AO_-eI;uYCUjXL z(vzz<1K7BK?>Ro`shf2^OY7Q=5GC<;x8V9KQM3(uN0y>U}RoP;iCGxS1UWU>}u zn&|_pmWYL;@>oEhhN>o2bl!=|UUcRj8$Q+wc7acCpf5<-(%0wBYcX67?&@Yv%q7J9FrL}akabj1ZyEE;CUn5Ur{3uc z6%$qal`&+!49I@MJ0pe1*MoRi{ytlHfUy6vSWxl>nTmH>CKfxN>a2l&}n_2VDiew_wl|;5r27ucc^? z)~pNAh~sCzk4dC>sODm!NzltJWX3-E)g%Mu;YdC-2I;OOceu2kDgI8t+#SN3YOFA4 z(&qEnDz9S|cKowZ`*mGsU3+t3?r^AlpeuY$O-5~p3`Tn6p7{#Yn(iG0ec*zO0ZV4gWi+0rS! z7Kyv%`ay5OLVG~p-Lf^#x*#(v_=-Oi`UldinsAE;n)$7xu~(sA1FiEe{8FhpoZ1?wHA%X+|V5jR#22_4t|PP=5bv@ zR_W?iX70o2XVhRU>D8pwpCERHT%UfkIj4S8Np8B=YCW{rCgh`a^DCYHj>eGT(TIg6 z&OPaL4#~((lBgHs?k>uFN1nOhS`2uOqT!!z3@Rk9bu))G;Zn66c8Na^@z12j>>zFU z9S724w3SB%KJV(~5&k|sTGUQJrzvTUakvmSZ|U<&xVJVo2hJFI(ZKcqOpW?1?WKg? zhkoIW>m7Tl-G2s}6f7&5%GrmHqyM&Ot&Fs#*H4QobmLqj3{Oo;V(Qf$B;NA8^|~Kx zSs&4Iv09FBRc6zq)QquGnm0MqpBp(I(7P$ z)Vu0)y-}-h8e{pWiSz>zncJj11376dES)M#Twck~CXmvTA(gF{tj|ebydhuNwd<lWTy+$yE-XKiba zy2vU*mzVa=VD)>=v;I_zYS%fV# zmQC-q#-rvE7q^Z;2OM|!TkifnItNlJ?NGZNj>d@%Mz-)f)wTO5vcUY~j&Mp<>q-6J z+y9#G7Ze-A?Pjop>Xoy@QTjl%tY7CfD zl{?Ak&_9ws^esuwI*OWNNwiJFr!3aCH!5I+e3f$$#>02aOa4%kJskiF;jK z;D47CGRFCp@9P}~^Ml^>xNAQHNVny57A5!sDfc>}AHRg(KHJ{UB6(q+jvscOY*?P< zTAo)cWso3e_E>w;oEYOWtPNwIW#lmaMxErNnm$=+9ov1`rBGd}7RyL8_VtirIf=Rg zMZs@&?LL^{t)%=Pso$D!QmCm=tR6;9NE*g)!iBkoC=<9jqQH>k+3e-RGSwO@W(wx0%cx!K?UKr|isN122aT zJ25K4aFY#tUg}$VPmjVEz4}qqE>OJ`QZ|yCdj*Jjs*|-X#Xku1=7u6axRRyDFR6RX z?bg)!bhk6|M7*eW7#ypq-8;7>Ei>JB*-=e-4kl+4NPsE#TzD3<;I7(m;baUZ0ZZxI z$`_tD&D*Z*Gj%IFc^_=nJ_oplSgT+au|+OvjUJmGrh1vw^GLnVi{17~QqcMW5C zjmkB7RPc^1`AMqa!LKYG4&zpf;ER;pUKcz1ttg{tWKlF;^EPivjNuJZCYp8^C3wui zzav@weJUYKX77_ewqqaO$ac{O-Mt*8T|7vw#=uVYJHoni!khncFg}>Avk!adVxL6@ z=a{Xv((3MX3aPQb@t*Z%KmTbe&)nLFdj8Iqn#-3l7}tQNvewE*;ajb>e)32JK5%q1pG3cfL_pw zZFYc#X4QJRnMSW>y3|;8hEW>9P6E@4n&7UOK!%rWtGf?~oAaXf z^n|DGOGdT4pd4SmQ;`(H{H=pA?Q#j_C2X^LYKt#%aIecEA#)cIEi(uCQ{)j`tAx`* zxhwugotT`3!MF<2FM9l(8a?zk9$;7MX*HbE=8Pkpm&oxfepZ`hQSXErTylPz0B#`L z;i=|w_ur6{riZBw?clz^`s%YQ`}k8jq;}X|B)XGWU?kLWGA8Fg_&#pnteNj28x5En zz}pcsLEvyxZa^6{${NA@t;Vbj8+Nvhk6k$ZY=VdP3(RV=(&+7f1>1+OzhuDZFbQIJ z$44T}&u+b}of&RQ86`R;0@SW7zq!>DT~aRrvVY}%v3bt(kfuOJQ;A>MB?FWsB7^1C zp;FN3)jv<4#vXat!AvKKOci$IK=PZ~g@wgUhmG-W+_(;s+w6n~>Kp>3Zj0Wc!uMGu z^}j3f_r>Iu+L<;XhdGBP?zJU%Rg9G(sVz>HudRow*L}Pj!FX20Hj>eMxH{;;;pPi? zjvxImXG>D8mz9vD85^1vy4qUgfmxGB7e%`8;vM*bNvA)-TGCuj6WAb+5OaUR#NFV^ zb@Ffg6fCpRnB2$@VMIwdMK|1>Wv|6&aPRM0-mCd`^)dhbwqraO<1!H4u_ijp?E{Pn;nmcpD`eT+S7oGkKv;KqEj%b?K z+ruwQd-q#c`pEA)%o^0W<6dO5#(+{B?VLFw>31ii%gw2lyF{M$Wb0E8H@NhGY!&sB zR3d#oHSdCjo1d$jH(RoOV;!oH6?gkfk2j{8;j56&ezGbup7|p%}@vxfII&Nd-e3@Cxb@Zg6`?Oo5eyPdilz zD8~+s-U#~Ce10xPB9rMk3FQl%DE|2&Z8S(Jyl`~U8GKGhF8*z}UD@NT93Jlaw^s_& zXeQ~JlkyS}UEVvAve7f6nF2gT^Ls_S7p4lRTn*g1OytJ@efvL+P__gM!P_s1*e!nHJggRwK5~go=zni_&V^06q zI%?;I%?KbMJ(7BCCG7CeON|I~Qwe*)gWc{&iS4$(9A(l442B6hy@sgcn>R8o50SG6 zW$MAMPQjW9PGRy@#W<7qY4^sEI6^3PMycZh=_~Pkb4qJ|Q}&LV>(}-oe1& z`i9_!fzT6$#|hG*hY|Y<4mhj#Igf%!Gda-r0S&NsAa^+;kSYPUbOT>*T5hC8Be|(ip;XQx7m%SR%X3qKck z*DV*S@9{%ie?@DJZF2dTTmS;1B&DHQp@e2g7a zzL5N=AI=rQSsEn?e_Agl5DZp+KyxxMZV_^nt0kArKo^K z1CY|<=Z!aUkXNyl#$m~r|F@plT(ZmycKNQEB}HN*lD<=qA5fa^C!sUO0q>Qq5Ow0o zI~hCuUvJkbKTT5IIJC0BM$Q>t_7FxwZW(5m3s#b-2a1fxllr7bq_+tOJ;c-iKY_hysFOF;*WdcC>aVz!^uV4dvHV24OfpQWo;B9FWzOK zkZE!PQ&625dEtj!6v~=2JljuDXijCsF6DT(5WjmY{DEl$n-7;}-Hb(MJar=p4)2+l zjcwV>W z_R|n;d(sCn9-(Ol&<%dhU%7xi0eEkX8%UUIPkFpLN+Wld{BzVlox>v*C7MIqiqT_5 zKT|^-d9SEgbx`!+hn?;coPi zIlRYwPpN>?q!lbW$(JVk)YobF#)~^7ToIdiSO+r+Ad21MH~*)GGUK31hbVaNrIh6y zvf=P~r+XaLPOsnH_{d-}xv#n!P4*t*hXO+3g2mV!>G%?z_M|M^5WD;~E_M(<5~5q- zKzQ`?F}417mw&C^{QCtsXIRY{7N$D2(t% z6$wzaSJEi|0=KjOo!u0;Xc3p0y|ib#?BYiL)3;B-W!xXjYGhgv5`r@H;seFSJ$=tY z_xp<$^?HyKsH>6k&cMy$X~wX-<+6t{YFD-!Ev1e}+Twr|XRoyER!yy|-#qcnZs!)o zJJkJd!TqruweCdEIbmI+=$7*f_b}1-vpW_P1=p*M0WIS}QUyt!DF-`FmgxHAi|w%a zc#UTvjAS$qNhlrZ093gA=*ZYmH)qh8hzAj3nN70O9tBLQTOJS5UhVLQJFFHR=g*K( zRnMrd&A6rm6_+wIMcoMBl$CZ7M$_}lzRQck1}laBz=9&*Dc&!>qS69iOmN*)h;=uD zvDbUsc~3=gDFZ5`Zk5$(4tv!DVi!j&ZO907Q-$mxteoL@^1g-yam-Mmw`Pzr&DZ3* zZTSj<+&%MK|9Z+td~{+#IcqoE8DGW2Byph^)Kyu{y*rX-h)VaU=ES;IrMZtR;Fjid ztLjyQEB#NZv1n|1`9$(7oJCVAtd&v8R_^>^?5B}nq|8*fVzJm#@n37X5i|3}Z>JE2 zujjUzHt+=LnhR{K{K+oI5K^U?;quI?KUA59t{UyPi)IpO@|sf$@fy!H{G5SB`HohL zXJ;OAaQK!F5{rXPj(}MRxZdJw0l2*KrRw7}eCfC{hn`+s)Gy{l-Ii z^C9UXE&cBNTSg1VkXJv4(3MTVvH!mu{ZI}8qI6NoNq}o#junlv+S)(+7GzwktXOYV z7-$tCxcHC}D;sO(6lrG%Fo!k_SC@Sa`_WCmKmCgFZTRNzy3YPRkJnZ}%Od7ikP3r} z;H&b%9a(D^^)2xCT7Zo27D;Q|^TcSq`G&FI4+(?*@T6C_?8ZLik{7niR+JfveBA1Z z?Ryi?)0dAoV2KxgLE6^iXai81&I`Uy7aURLVf6OMgtc(bWmdxP0^uHJKTg;w1xjOc>jUq_My>QnHh@>qb(zhB@~lI1Cb_63R5xV|sxhI#b- zE~$XU0M-5-2DcTak{kZ-gs|*Pc=mJGehGPnTK1`Gt^Q+b#cWja)9Y^nWJ=>zRQl57 z@xu4Uyx21Jjko$ji&S{9&(@#LkTAJcU`1i<=O>V|CcpH;$^|{82c4B2UIJRvuo(kf zMrdg@l@H2b7wP?43H+lEFBzdw)K&8haVi`?s+VNu)aq0pr{lT0AtyFiuywW(`) zQXEv*5T2cG^{J6wSetc(Y|<~o6BDT>uQ})IH_;FY;>7mX&!rWH@6JHN*hv#;-t9)y zI=Sj(!<>`TMbb^+W%!V*4(nMDSjVgR zC{sKw+rx-mN!<@em*Ew>u9Oon#FZ7+wzJD{c{pFGg{OfSxM569sTV9Ld-F<*ilm7p z6fQ28&90JY!oseF86Jw2CycvwR`0U-Vnd&7sSnO!hTDmaJ`vSZ-TRjI(~P3rC0Ww_ z!zb5*8Unyl+?Di|X8pJq{|as}rM?lI~J>+Nsks4Z=- zwXArf@xq3o;T$U)&TW&^>9bMmkL}Z*A}fIzpQ|3E-IGLz!>5$EzOw?n(_E((lFO(y z-&V@+?G5`9#fa76f0ThdoCcZUqTA`CqyF?UX8>zQor*axWKL{~Ei$kM6l0f>!628L z?qqFTBo`t^Fs+}fCm?pcP+{?)ekTVs)I}7TYFR=p#an)w4V04JjUin>$U$F)Err=$ z8GW4FhL)#C}B3%>ls$fPzsJcxX_+I zLfQFj#~gTQ%VS2VBJ298UklJx8o>0vJNI-0Wno9csR5}PN~vLV^ms9Ae&-W}rBK^a zO4lO7Vd#0>c*n?9@l!6cU4vn|x@+^~{~~45DOk?@D!+e_nQSG}iL@Cs4GLdt6Rc`F zi_L<&r?&X%wFY!=2tIL6TY?pbG^Ay%{nu+~Q)u%jcDRTunvz-&8;Z>a6K_crQ zT@ew|+8dT!h~oS5+N4cvYx+~@aA|zU2JJO-LxXf$OX^>#eFDF9bNXN0tkoYtO8eH@c3~4?!!Nyg z4w()0=HpT?>&?}I#j?kH(?W3FEKB4Vo~P8S4N|eSaO+S_X5nq%?eN_{qiaBZMl-&H zLAA4$aC3sTMQu?BRKcnoRY|<839rj5iRk)a&9NP_X-CVYR5f4Da=orXeWc^!n6uHk zTS>_PNt2tpcguyeQrVSEE3aG=qpr34j=#pkQr-Hkv^18-W~L#$>%|D(RDuh374oOs z0{ual!>mmbXc#}=#x~5%Ss{pQvslv!n(vmbRyaF_=Y%aRVB4SHEiJPTBC8y^yXHRQ zWqAu&Rva%*46xY#Trte$@fCm>@J-{=1W)O%%LWyMW-NW24&*-Y7CfWz6y^S){7cE$i_;Jb0HK{FCZ?;2M7yGztWPEFdE7p1fZEnR77&-Qe3j4CU36W4PMLEn#Q0<-U5v109AQjb=#+L{ zL5WqszMbBO`lFumM(*mexyBamPS-O#{D_B;hT8ga(RC*VfOn?7aBuqVk8o(kVh!PM zQ)Tm@Wh`$sA%5y@)`tb9kXcp#+DC??`>1Q3CVn@0^H*E2ajv(#Z}vt$1P@ z3L=P6GWS7X4pWj$|I42tozW2lwyC{X(4GIBezO`mDw-rURlpDX9|0lIsjE2CkU_%q z%{;TE19G`2RPib7dx~&36X{=oKkloXVIO=o;B|@0K`4l@tI&Ch+wOkhubdrF;{jOSDnrE$5 zoU+9c6F)#nNkx8s^OghL8ood$nl|P~ewOg=kymtyu+J~umWQIg^xItnY;O2zjWvbh zXhJ2dN<$~!$ahRk4!-1YRqSwkR3|9EO?%qPF$r2-a7JZkWpe5@@rLbo0mY*tFv=v;t zwYo=>B@E{(j{Bwg4!cpNp1CjU!L2D^(!ktuI{p#=3`L<3jA@!TbeL0d}HVeSu~|4xF9Lk-B{T^ej1sDET`+(+akx)U#_$p~`k7)qL5@ zUa-KU(wc~wmy_uO0Gq*Tf z&@2&kNc}RHx}HbkHH_Yks0o?~9IVBR+RmkB_rQ^Zm@`5Uq?zD;$;HLrh2Sw1f&afs%C{@pmz zCG64hiq3YgRi<-#E3Xn`Tgqk6Vj0w*1tODl-lM-#a5Gpc*O2J=RL~h)Sl7C_D?q(0 zn`eZWy%Z?&;SO@hoMi_AsJN4k)rp>vZ6Sy9a@4dSR>7*en1ct@tG@9 z^0HsYkgMh89jF!nug0t5Za}~l#D|qvSQoR&ffhX<=T|+a{rLD;yT~}>K_?sJa5H^> zxNkiy$rXBt6tjo^?YH)`I1R}PiCsN`RZQF^OC^;){rp%kNQxOehOVFtnZfSCBO8`+B)c9hkW2KJrca>HrV(`>$KX7D2#cJe|F7Ge+`U1^X%Fa z+s}esC1zxIjoTa>o})aBWYI#i9?j`RU%;f2E(rFd8ObE>7uhJ`M_{0e3HB>OA>4({ z$0F=Tk_74-(d5rgxjrmgQEv%CXG5 zMuWa|)eX!OPI#4;IbUf{YF?E*Vtvh=B1WtYtkLeG7maim%gJ?(a`&b|{gF_h`+KIV zZ!OS4KVmpgGzX8Q{n{8_u9h8@9eRM;7!WvVJDlsV*8-2;wF&1hLYfRH@~rY2#Qzvd zaIOJ{*NF3Zu`s$EHVJp7_E4WQyo%b4I*MqGPH@|*ttdAr*f zlI^)GN@^OQA^XnX{(D{f>}=i0Jh(^Ktf$#3TYpSm6DGPsqh=m-L(ytIg6Vp**BRJH z2uC9l?ffczKC~ftx2j3>K0{{CMURJTt>td)qJ@BK<#dPpyx3V2qENKe*z{jab6ss@|a)__M+?tRduu8pO+(|Sky5!??**1U9g?Al`z>)!Ll zm!OYoYg`UFX9ZL?w~BTGmoDl>2e6B7Y_P;^waI{$)C9>oakm!Yg|n)tK*1mji4&av@V#t3qO+BOjxOx}=sb}8QF zs>v@goLETZyFAsAli#L^NA%DT*5$%@EHaZ!diWl5BaTM6KL2x&Ycrii4h-eOR$uU15ax zWIJEIomb^`ypqWIuPL$ZzKSrr@Jffc$4$-4?Ft1#buM3xrPP1#B}jDInyZE@Q-6~G z&v$3dO=YpQY$NuXVaq=9lC}B*9)5LX>8j{l9wl1}R#uIK@xH|jG%eco&7gWU`V2!P zs*kA0D3sx{Zva(IAsdk%Jr~ApDRHbE3e!Udgk*tEpy7T#X2x8b+gOo&bcvvEuA;Cm z!AY6A?N0Iazq~fQwS$Yt;)-+CB9lN{^#ms615}$5tN*h0oAx=<`8$;pKMQL7oB&t z{gh!C9`T9Eaub^{WmIh!r)6qQ)E-WW&(uo4Kc*X|=?k{$Q_HV0Nsc#YR_EC48GgPFI6z0(`flL#~u7T6oMg)eg8$CIKPYOR(HE*77SG2 zH6BZCl`zxA`2=|9xIRu~ILnIG@eUdhkxH-{JgE z@>-iL(J7g426DF2p`)%6nhP!5(oWMAYFxN2sE$3mE|+%oP^sj`{XE=>kiG=@!~Y>R zjU!Ouo}_vv@7V{%9j<8J>MXz558a4=D`JQJ&K1Irl>4`g<_9JVt<0Y?p3ya+(5?)I zNZT^a$JTDIf_T<6gjYyiw)bNkHCj?<#hYE5@|eVOkF02fU4T|ETVwfXk{{^^Xq+?U z`fXbawwk<>o*lcv=W3OUsv4Gi9?7S5z*4>TJ}ADyMBl~2yhdQRhZ^DPg&ozb}9r5w2YJM|(*!QB_3 z@2yeytji<=wr{p$O?O(A6Wr8UAx76wC!Qk;^-YrZ8k=n;2FHpsPe2U9#WQ87|MtBY z=kVV%wZF|fE5Q^jdNHeR9BW*4eq)2tbJt$T6tI03`I& zE9yh9AP~2_LshY@AWSZDyc&_J;%1`*MaYhjt04#Mk|J+`VKqhfn21wA5&e`0m69D-!J*A zY}BqxsG<)1nyjTFuSNT{8A~f6%$JOKOMUX|=F?cRX77X_bZpa1y7t@0aK2q|S14^d zIF`b&noQllwBlkRKBacABaeIMKTudb{#3)9sSGRb6sW=Hy8b=%?HlhE^;>EAqm4Tg z)FyUueCTR5u7W_$BgmCc9Gz~(e$Z4nMu0PX*)~q~U?_yy-E?wuR|?gZW7{xx5}^hZ za|yR3Ob(nF9||+eekTyN9c4yb)2riswW=%8l#iaYjeLn2ctz$QveD*fthSTR@8Zx2 zidNc{sJgDjhkUoMn@YmcY^B=cg93&FS+~n$oFo|y!(AvH^lsk z8npQhXr*S=f!}$tE)aL zFG01$h?!~UQKUcAZOx;ft`&s4aTn`wR8yXgZtIZkHKN6KzJAx~Ru$#5<|S38d5EQJ z@67gb&QD1-)s!0aTezvj39sCPC&{xjk!C3hpr%Z*oQLP-sB3-4>RXvEBBx9?mkq>R5omInBu6e1eS=2e$L0*W&- zBAJ3=3If0Ou9l;6_sgTzPE+A_hnMhMYmx_o`@RG>C#-e0c*B35P5-8urTJf;8}e%~ zBNBXCleEb7G$xF35|1sf4(6)P$9dxCpLQ?n^eEi{Z2PLBRXo>V+m?_fZD*Xo!~M z+nD1D4zs7pEUcr;j`CaxNw<@jJp&`P2MBQoDPDJ3?nfDioEp zKia@mP~ubEH0L^uWz@V9KCxn=xF@)DAU1^~>^U7MCrEV6Wil9Ss#DMD!?SE!6Jw^v zYMnF19a~;g*}?Q1>=Fj=yBAs2MULN~rcC$GxRbOJJOgGJl^wksz+bjk!`fT#r~EvYDG?qIxctV;8u;C%mMYQq*IQkBdwx_j^H<~6n#0;Fi_Y^51L zsnBzY6isFO?O8|i=$;>ThOEqxfZrrYG{cChAIPYwdf-OhU#X`Z6+cSTz3{5Hk$zKd z8EWM@+jVtq&iUfWga45w(JDa-A3y4$>b1)DBA~=)oLEA7Qtt~`Q7{79<+6TvJc~Eg z;#~N)+n^OZOH#KA!of)+<7wiU86-nMy)unuGPu$iuWguiWZTj16JWVPwC+z8JW$Iz z5sBO8bW*8xUh++HGv)7aPE%}a2^@A>{ymjfFZ|`ejW?SwB4xSz(TM2QmEX1!J%X(M z$YNxv0~hke*L>f6#ftqvfNrL&y#p;^-H>bNw~Pp|quU~!##L+P8wa#ib4}}2BR&^| zlbzGY2Uya$g?~M|RU@EFIz>Bml)n0s?5_Rn^`si2Yc%}-j!>DafXXWK*0=Wd|B=e* z7aKi$sp1ZtG_1Z@TLh-c2jpF78%v(^8(yB~ecYN*ZGB_*cb3M*SJJWm<5zW5l9B`< zb~#QR{DP0y#p{nbcxTqpNt9KOL3%C4f#niyq5?#i3fXEPfP5oB8w9;s~Eb z)uaes%r*DA`IV-dtKrH*0K;D?QWzRH0K2dH0=wgVj)!{Nhkquhm6)V*`oDEMIkkF) zL%E6xH(q9|pO}=vb`0z7=G>oGzx|e}W*bh|0C$JfhB_n8~ zk|y|Fi=^e;TBe^{&04p=rCU~Rt9Wq&&aYu$vHiH+I~^(K)0!DB*UTJK#vq4Sz#Hi_ z8D`oAb#85b4H9y9w4^WGf@=3(pE^JFJ%1k2fFJ+6)lo_F-uGWnBy9Tp?PZ0SR^S8L zP%@evm5^O~-)-B`b619;27u5iSP}{VTnwiO#2x(Tr2*^+TfwEbLQXFjIicT1Jm3!b zg`z3yekll7V1eQ0QU&Ml&TRTvD5jY)w@=zRaMF__<|G>9>hT(lUl#@iuJijzyEOAE z808950U8e*nveF+ceb;g776USy zz`|#g#Gl6zT>q?qCs8t+E5k)A!x`*lk$L`JSN4yqdzNczOGYv%>Wzh%z^A?GQ{p0+ zFg;C2tj4f9{phyvUOTJbJ;8|(h(3q5Q!#~Te0sfa2*!oSK*^5U6R)&AZpA#znl{;# z7Vs7o8Ub1FcgUqO4I1U}DCO1+t}YLtmP%2RR7Je1`<|295rr6|bwDv8^y2spl>H+P zC#qUYDgj(be28`m9yFJg->8m^5W&rB-ac?wm)n;alG~?kb8Yew=kDF@FVUKU+Ft_ zit|)r@ExI$_Uyi>?u#lxigt;;&`a`?@-e-mEQX)5PwFR6fjMq-Y` z%l5DaY}>&lXP|-l(Mx^}8zv+2eE4%zfKBew--cgrf#R-@#|L8yE_R=xcK0Ui-;a7C zbL3QxKX0pb3s3zPkhhvzCyqB(L4(bx0WS-_@V<>_m`Zp4T4t=Sa>4}WEV=+NdzL}h zDPI~sFP!bYJMf>YR?9Dd(-dD|!wn&G57vV@V!Q}${jM}q*-r#{!o8hnzT1=`WM&kb zb;1)*YwCgpA7w)ROnq^bR8jA$)>}G?q=(W!xysR8nZsVJ9u7*rK3axhJY=_9+O>9B zdqwgTJ$DOZoq}Jb&)sY}*$1-uzcPdb`wdYqUmze(Ka!!El2p%!KN0Dh)|uSnhKAMl zla5}#QePOnG_9I=0~w|xJv37N7@kt8a2=+v9dw7}`Mt4UY(YXn5atp>w-KYPbFt+R zDzGo{OScc|%15U>Q^|Ty%k}iGU?Pl}LVA*}^sQZY#CMy+5f`3IiNrDUv_(aLN$ZOL zUzh)5=^Gd;>zZa~CY*3$CllMY?c~I^ZBK05wr$(CZQJ)e?|1*g-mBN@uIj47;&*Ib zulGPp*C~^vJS23!-n&zI@1liwSTqzZIxC+^oLrhKzEWQMAZKZQ0W4m;{|-`g7J)V4 zreB@W)457~5`!768p_>nAwrZIKk(gn)9b_hI{uQewD&6V%GOT_Ybm+NFO?E z5D)2dlIKuv{9KRfhN<=M4q9hP#J$M94BYL@erSW!33ig0O)HJDIIe(RcEaL2yjLsy zOx2O$K~}UgpK7c>=GxR=F;}Ir<^dp)SUu}SIoJKwA;rLJLf~b*=vQg*GGKqa-hS{( zZkQb0-NwI|WRR~$Oym}f-ClEhKR=|q>zUfUk}!ARUQ>~T=SlrLO93WQD6r*qIKeqz zxP8oft-<^1PVSRrzp=|$jnxFwBLU2C(anBICsKhw3@~WEWm4Yx>pJGMRqs5V#a-w9 z$x(`i)^AFdnM0tb*(;!aKJP{Bc|2wj)p0v+Jv0`7mK?;8=2qJ9$I_4&)9pJ6cKCu? z;*`B?YhOb`N#qz^!oSa5C2NP2u*IlyvAbWvq&U#PV2$C81IuM2lksG(WG*;s_b}_c z>A@?DK8h^_p}Ljch6AZ94d17#Ce;;2#CxL;Bi#8l*jF@@AI{7B!Yw*mU(>p3`RL#pUT%Mb&u1oAi}8 zMm)VM*gMEl#XvQm9B66EJkuNxAqFPO)_CDo0}R`yEtsNoKsj)Gqu1j81xA3EMh(}$%DA~o6=9l$TpHHtHN zByd&pp4<^md9HH4(gGoQ1sJxtsy6_ZkNbTEfZPe8C3 ziuUc9J?R>XM?SRRqUz7O_ijzDCGTyaHGZx>=qOr|Q836M-~jADae&lY@wncu!}6uu z@>Onp>sY9Rld|4v9jjS%LCF$IvQ-dv`_`gipUTtl-n-Ii@=q_Xqp|SlwT+WZYvsC7j3kpkM!|ulweVGpN)hScV$Lu)A{@@isT!!lg?fDWGmkMY;`6r z{4qQ%G79TZYhSt!ACKdcODkn>R2|##MGj*@eML&c+lvCQl=PISiJWwQTmKpu4d|cA zC@E=))nI}+fp3Pz5#6j=H*l`9f$vnAPWe-BQk|LD*uDjt7&>^P1ugHN)Rf-I&$;MS z)sf*gc_d0t_T0@Umx@!e;k3O4aY$#k8tL)Xg-Uvsu^?{0(1j*=Ht$Wzp$Q3E4|(L4`C zaDbNg6BB$v{ZHgUM9bg+v;yWK?@ zWveQThSZr5<%o+9+4!dyu87B#lyiL<8g`j;o&ru*WnF8|udlaZ9wW`W@LLZ>k|dK7 z#;OvnTPl6$rz@i$gBPSS0*5(Bq>beUU&dc(Q@KZpjITG1mYS(eChKN*VR$T;NQ*5+ z(C^VcP`QSrrZbk$Zdl`s@%yIJE^ePj%7)9_I^GekvM2^A%`_EDm9kLD(k6!G)gp}s zDi%oS3wsy)9Pw53yeAztnN0AYcBAH_?^^&t7L=yT*LXHo&FjL9!_n9G;V#;FgG5)Y z&@l6RjGV-=2}@#l7?VTR>+XFYDMvqeyXNgqGJiVq;?{@B-wv-f@C=22*t-rFG;ulf zKaGOyDfz!**QuRww{;}fR_B(0SyVtKq{edh)U6D-=~?{oN7eugE(1-o>3H{B<+(y+@=^`9a>mTcH32G{*b&g}%>x z92c_?y&#R(v{M)C5dp#wsF z!AUTQ#iA#pVksNOh>y3y^LLWc)uGDvM+QW&jPb|o)3U%vW#9vBe#881A^bYog_uXz zD8pu~{IkSVp1XH3U0G+m%1c$k9p8^&XyEeA`v5zs#q!kn_nP~3I#AZE+vvVJ-SHIN z>YKp-u7;lkJm26rz_Bi!@ zxv|-f=#Ix?cdwYgd@|;MmDtzexQnuV2qB9c&iVj^k5dbqK&u@pWsKVl;KqTGwA>^) zz3nZYS_+q(ukYB~6Mgv|e6d+2e>7@rnoX=Yg0ae^YUSDn8cx4o^zDXolGg)P;Pm4sb*BYh+ z=T$Z+C|Xx;Y2wR5ZT6#Hy;ZXDqtF5L`E6BjVRKu!l@}Mx|3{+RY7_}E}OKZD&BOO zyCYT1HKZu?1WUpbIsNd5=&Kv;O)jrkSWX=L9wZ|Kx6GxWBTBA9G8`n9o;l1YS+N~Z zwn+8OHU4T=-9)j7d9#6>-&b(jjXqcwTB3D(OhI*tSK3N=`9TKITdfm}T#o)Wfc_&m zXECib4^b;dugzb}Al<&~**qASz4k@(WDG+spdp1~t|5@dq*E8h$9TcCWOkJ3B2I4f z*2#YLuy#VSk^4(h+8|CkwWKqXan9&?A&BXTn|KXo)A@;P&EY)5OV&l1Q;$8MC%Zxu)09}?l| z|Ev>HLo4U{f7ylr)mk-F=3l-pccH`F*?JW{zPA_E7hF!j-0C`OZ|$?e!45tPH5ZIi zx)QGvyc@MtwGlWI7>tM%Y!WkvW}%U##RR;!nh(UlSgk^&j}>qwnr@9J$>TyRH&W@f zoC=+_sQK9O!fKhfngD%`JA~?86K`I%mNZ`Uf_Mxw6O?v2AC-b#`Bro?$(&4hCQ|k< zuFj}_s`q5t$ZL(Uly1B6RJdj(B|?|o<3AH+(D8;tDhox|ob6sXcCdxaHkoU3^*NL- zI-YHYj=+m%MqCbBNG`>N0PrHhu^;^VT_T8I4E?#u)? z@ojkDr1f*s>h{Z{68LIs?OGUR_EsuX?wBRH2!t7NjF<*Ka#;@3R49?mo$aW~tYdf& z6A$_Pv{Ul7&5@Fqo81z+c&_>hi6TB4#kl~!7J6Cw66I@Hrz&}3*6;R&&2J+ApB@yy zKw9j|Bc}@0L-QUTU%8iMOQ9&NOA7*N593V#=vHEw4|>Ti)B+sW<}`weg5fTYj0cgB_xUoL#E% z(oU?3RV~y*3SLGf!7W}dPRKv7|1i#512fj+%Oox{uxsr)JFIQ{$AOZ3-9|NFn)26e zKkLU%+ADi$neRe)xRqm4k%Qe%;XwMWOxA839l;mVSU=ZtD|H0xN!QuXvd2pvHXhsq zDigaR#vTzDITKK_B6tqv67LPi`R-*J4WA3(WUb1iQ{4L_wymrYcv#Tx$!JLXUYe9F zwQej6C{3%nAxxaQ9X60HhZ1zsuN@Rm4$t1;4SlpAr8%X?%-{Lx1)T z$*%^x@Ky2WKOhAnX?$GB@syG;li}>~Z}CK<>uyKwdE@(Eg~m2lV51LNG5oIyB!$cJ zDn~{emB&MjTaudAW9u>Jiv{`2VAe8{R4L2sBAvFYNuQFjdRS@9BdGHO-qUtT9JlaQ zDy`(@36Bg2PFGRx2=Ew$G)$_x1dS9g*GVwKD>dU^yQ zANZr)Ya%cX7O^XACHh2LV=WK2}xcW3ZS&<#n8F!?nNF zNl~9DmJ(f;X)`~FIN6l1d0Kbbaj&)QG*g;`b^8`#Q8dCs?7Emv$HhtY228pAFTpbP zKeK*C8LlslR2{gLZg0b3o6dbo6-}?jqe-j++#$P=uiamhww-+)LZkgKd$tot##@2H z3q>Hg8KtmZ6NVpO@*ph#LRcS+StyD}q3B!UDJ1;2VE@ozp zTXec=aDblhJ^DUJ^kP0_CO&I$+mb=@9P`68-1K>D5#^^r|M-(PjW#~v6SDiqw$CJNA- z(Kk7}*?ZvUZvGocH7H8{WWqyrn;Jt@Zsw9+7&_FJU)Oi{*~}N%(<9<4+3JF+(%CeS zK4G7bY+bz3CC^C#Ms!GB5UX7(Fa#&qNZSSs^TR!lv+0uru_SHB!1Yk)T%IUdePgl` zzdN#<8=X$F4hYURt^gSxbB+&caKOi)K_IV0ieCsYyC zC}90%`gBGcVLtno%}Y2j60)x!Ar6Y0zB=i;R}jpgj@H9@?GUJot+COF$lolhb8UJr zyN|0RRtl)PY_1_pzFc93rxst&RPGM63fxS?TWL-tXGkcR{?wpSmRjWwc*XqeC*fGu zXiZ}Xa#n*>BZF9wyEJ>J>QWJWR9?46Q(xwJEBplWb?Xw^;IGrrK~PWE+m`{>w)xIB zsZ)pZy4+Oba!6P_2F}>UL`TQ_e!KQ_@MGt7oZt)+k9Q|c8wLho4m74oeX6y{#_}wU zYh+Lb+nC<*HW_>W*YjPla!ERN>hkLJ1Om{6Eb5Hy$2>6YTUY!8HY;T0v^e8s6SyGu zl>Oge-rePVSj=jvY2ycn#}W8bX0@h9p;4}sg8)Z6m5M~)x-4C<&g@cw!;?J76!Ci4 zN>?89vS2WSuTJCL6+Wdi>03w|vgYn+HmiW5symLtQLmP22%g&d`-&(wP~${_UFECo z{EJLSGQ2v?DM>Dd(VKqxyIx`S5L80~{MF2@waa<1W~#u3n-Y18Ip6Gd`~ln0*Y*~O z*V^&gv#D*9B=BHgU#oB;a=W$J?6zDK3I4qVDofTL#5I`-pRd*kT{asPQ7vNiAdjK? z8OkL9LdM3zLH_J+=MdK)y}Vhi$Di@erxHME=BC_cr=pRwvhbNPT&E0~Wl%-Yrkv+} z_$T(XH}+TB!<$1q)xv%0rliMLg{q`?^AjE`FdP2AV?Dp6S)HmwXtUjP|1H(d-eZ3E zBD+<}z)0xeP_K|qT0xROs6JZoX7wnEsNiIMmu5uL=5x}DmVU8RSXp8AylmwgPz`V# z2wDV0uCljFC;{m0#mmE?)-y^V#`dx9Axw_eU1SQYM6If;+s1uNysOM~Ud@MUz~+Ax zPi=sZ7V6SV(W7WJp@oX3o{D2(YipY*vVeo?gles|=GagP4~wPd}n`wQOQ$a_9~b>zjvVUF#Oy74e!!<6K!(EL)6z=?0qKEdB|hu;E>p| zTZ2(X8K>M6c#ri?bv|lYUWM&_oNIiFMysGYkf?%JJ9Jk$^Uu2PTNK-7@Y5c$C)fDD zU3yzcv*4zM#`yf`6^8!+yRmTXC(3Tyd#mR0B;ZPSl?5Z3e155fWN`IRSfhgD@)uEg z(p~>f#%c@>IGRp+$JuzQ?yzh?wQ=jrlr3X*?pW2T4Qft8nDAUjPNY!AYLw12v8<;P z&1OoFt=_<_6Rx7Ub&B9%Y(V$ro!yC*w~R=Din)Ic6H~35bcnB1cj()0i8I>mSZzN; zzj5X?_uOAT>8HIup8a1k9|K?JQ=;Tt7R@{Thb({UOr|u6NZ_FjWTd%{;%XYJY1@;f zmRylwO2(b5><~PFM&Oa7wzD(9Yl-~m{XqQ^P>_bJaN5=VNw-wd$1LQQ`J)Pph~pS4 z*KXaJ*=K!bNyp|3@fHtsEt2NKW4gOj0)F$)GR*I74VAik-_5&`@9a+2=w|BDv;J<2 zYlmXiXRbMzpZowmP<~;AP&OhvDQtcH41LNxvq<^b5_(>UJb46B#9%fNY5fe?-(iAs z2r>Kwe_kGuFKRd7R$V*ysnv_ySyJSr!QTmwi?ToE6X~swYERC zlvpdYp0K97cCCN3T(duSJST74o|({cFX(Q$5UO!1i|lS2m$YBk){3w-F77CGzwelE zedJxLczv!V>V$iRp>=%0wLKFV7+C#1e6yC)yL@;2F1@T;{D;blb*rcfJ>237{_ktE zjx*yk@zy>=10@-4^7o>K zkM4fYS`8|K1Ccm^_%0YzMGCmeU}B*ZgQM4-W{be@Ax$%>vegw~`ceBDS;T+0@%Yf6 zADw>oW(>PC2>^3mz2!Yh?rOeTPOxtpsPy{sN)B;)efCh(WmGH)MdZcUzd8l(R2H(K zm24ClD{Fnu7o)!?3kBv(xJzv(iZ*C?+X~;H$^X%m>R}+b4J5#5#xikmSV$xV6x=Xz zqQu{&HJ)V@kIO>`-#C+>r5X7h4~ z$i8U+nf?HZu5ESL-no}G9~o)g&(`YkTmxpOlz;xglo()VJ{mf4uc&5TDM0x+z{`AX ztL}cU^6~Ww`fhRBF3);wTR-Vii~uPIy*fG>eo*Sn+H&n4JZ?{MBCZQ6K1xa7=YkbP z_nFx(Y`clYE$OTAaQSU~b*Eg>hVq$3IIRJ}@yyXYgQ+CN4eH zw>t;-%XNb&K!hQ4#2SNsX&du71u-CiYDY24>4v!b=HYzHym))s>%__CtAuo-%In54I5BaR z&3{;$^Y0m~!IF!r4sk`*)Xloh+DD+z$CE}@h?gIh4eys4@2zO@_u>*u4G+khbrjD9 z+c?bGAQ$8`!yxEAVnN2Ok0X5Ym2JY+CzxMbXuJu3x<=Dx`5pm5)6~gZ^Rj;X{iII}(qxm@oCEh2j5w>Le<6CA6n_6)aR}93tygAerXH?2pFXx4|EI2* zkG(%GhioPWiXV(UjrAM#{n3z{8LrsYG_}MAU@2au659IT8cbmSEM zC+RE9N$xMq@I4bhUQL0exU|VH|22#zjy_Kl2%Q%@(XOLK*^Vb>VxRBm=#Jf~VI8Q9 z)hoL6MnRliwcgxqZ1IJz>zX+_I6Te4b?ag3>F<4w(`_ExX;$6n8>CM!-tWEcmVCF# z^{J1gH>es81IK&zHr$=8;6{Od$*`=f=Feygh8W(AKc9utL5cGk@HTHSJc3&poVU|EnBY@AuMk4&#c7s+?=i zAKX2kE#Y`Ux^M!p%nam203-XzI-wKdI~mH_F<)H*F`=_9)!O7rR3!)g$NXQV1wohr z3I<`sfw~RBt9`$`L6eaFS;q`b8RbJ!y!1er@X|L%{8}egvH(-k>P?Nc$)Ex6wM3p1 z`iz3Bx)QzX6Y2uRXga1Tn8Euu`}aeQEK!@K?kM!N-<<2wyEpD7Baa~NEQW6ZrVDkf zu0dR=tB#;Pdyf3L;LddFui#Pm8DPF(Cw{Dx&6vLto!yexZq58!Q^)pfJZI?Of+gfI zA&q7gXGEJoWWM12Z-fhi8Rigs9Khc%MOn(7aSHbrGh@cq&ys7~eNx=dt?TxWF}(g? zAEVG&BUtsgoDKqv>1Ld4+oKKF9RED9d0PCCI0L@l(29Lt6t`W+bMe?5J|NHAF`{IgC*kp0WUR#Mg zG6E1x>|?J}qODj9+q0js zF|+8?M12=J!~(-AObQ5!*O+RrBT!DaESR-wyc{J#W-Nn%UKk*k*xNU!!(Z#HxNUof zs)#y|&(R-aQ=Sm%oS^1u4}QMnUPCp?>p2+)6YX#o)VnutFs$3-#b5JyJa>`VuSpu! zU(eASpPA!L?HV0*J}1XrH<`oPj}6OP;x?||OY2K2=)udF4-+TtcF@qq4;vu54_=1d*g5_h?(r3y|tzLf%?&y33(6lWZz`F9hXz;^78U_NhR%d%D^`X9KXxVW(`%= zb;BvUewjoGz=e9##_RTZJhcWcJ)e_4?G$4i5(^n83P#QfzNcunWy@9)l=0A1k$GDp z=8=F=LGhmO*>o`#hi^4?$L1a%Qeauv_9y-^c@?W#Ps^W5`9M;t`+yxWD)O|I>1t%u zO}GiCenN{%C9hs$+fQeICE`;mY^cIWNPv8zbYLFl09$-)LY_*&d|06nWV=UyU{0;| zzF2$NvO%28=MI;2(4=Yq*mX1KBlLGGwBPyMh{oCMtyWB=ys0pvj-nH%a?HoYdFBHN zyx#?N;h3@W_x@Z8Nr3ecddJ~WzU|gsBhijc}mPG^76ZS z-8^T&uI&jSWDe`XAAfwYl z)R2mVv>^J#MD|!t5OxvW+yn&;+q4Y{#GgK@5j?&^FxL8(xib2w1(`@zB~Gm*0Ef_$ z@lbZGht*7F;pD%i7?PqemobXLO-k~9z8i!Xko63V6`dGok>mlfWXxk!3Y|#%DsS;iA zifAMiBpnKqDo{pOqh5dj`;Ic2xFi}CdVww#G{ zeN(4#{UYjf6P3BmT{oL|9w#7!s5Q4Kq)*KAD=nyJLAU+9mL0DPPs_&ck$7@Z1#d7| z$En3_E!MwfcSgeDR6-KV)KrAK&22e*b*nd2QNwc^#N_4a9k+LT)4^}s?Yi`9H(2Iz zr)$_8+OmS#G<3!#q6#lc6zuAx{ef$yuB9L;{vea_w_m&3v>T_Mrl`ZMWGUwRfU0-R z6h!~QR=J7%5tr_=WgT_bKd1ZQ@;OHo6cmvE>(0sl{PbGh4;zoFylA9G0XFX+gIHU4 z-<1_r|3YRSwM52Waxrxs%}*`=uI^+hs~%Nqh6OqTh!&-G4Tvg)iLqYmd%M}2-m<<){y9-AXJggt`b+SlX`=*C;$_d*3B4n!{yGlEKz z7No_JGu6XWdu16M+S;zD%QiGgxF8}b!qdxY!sJKkKL=xzUE@V=Aqr^W@s!ETM%*l* zy!p0xm@oy{ySa+%u5*XwlX%?UZPx52Np|C2pXVm^B$uXTZ{Xarp|j7v6WA^}SHaAW zOKac|$`ArhTaPV=S+ASdtw=76Y0E*lBD-WrZMb}_JQFQ=S?ts`T>@-%zb4k4E1*}7 z>~Q3I+hG-}qnm2kMyGUT?bzIllEyROV=P7x+i0|_RD}hcRDkUpG6g-bd}@(R6B;yq zE|s#K4=H^-t0zlKT5@jTyH3)(_j-{?Z7){v9q(!CRN@9C%>EVDq$pBkz{I(#UjL@! z5-#BqqsMkq&)M?R50Sj^mBTA#s&}OpQG!Hqi*Bg5R7i6J)uw31&YU~9KIBx3LU5CN zef?=$4Z)uf(pOzlgf&&>^f}}?uoY)sAnhym6US07mjl{MCLd{$Uw}wtz#N@x_&|U| z{FBLm6}GpKMPcXS8}}0Zs7#DOO4Lmgo|=qDi8<6!j~XJJ*`zD{j_1^w*`HAY;Y4X# zd}5j@vXgyj7z9HNeJM5mtZs!*Zn4%bxk1XzpuXPzLs8v=BVjE*Ovr{>sFVeng6q&> zwlHT61xgyG-iS?I1<_3@P&Kxh;Hx@S^gtL z1Bu|lWgQK*c$}5%IG=qED8ipu1E;LVfU7`ifoSUz-F^nXKmOnkJK#A%vk}v|MHmcV zKmK_PInyS3^lnq(vaL1oIhC1|6n{*VeA1a<-(sC|-e~T0Q;~C@;|X(^rIz6>HdEFW ze_^Ibu6G8gSH%JEH56jN|0Yy=0jh15mR-ALuP5zvMR_~?{TFH0J!zZPPZO3U6@HoOk3!Z0)zG4l?lff{x%a)+C`&9fM9)Izffm4c8?k&Q_14#q}BJF@Jo0Ef`TRvqM?tCm4UpPZg zMxNv}aMQk?-~<4jJIMnMpI5QX#f|0ug0g9HXmF(H-#NhGX971X8V@jziVY6kNH)gk zTr*&74rX@Nx#hpjsNyt72RY5{aq zpfU99rLIrrvcDsW(y}*Px%oK)5+&kYtRJLpMmXW98KX7GM+kbrvU88lMhQJ{pI`D4 zCY?k`p2r3G@Q$&->vmSPHo-tKLZo3ZAQ9HxKtVFCEZS}e2wok6moFVI70;KkD{UKz zBsxq;?y_)W86{ucbkE;|1cibcLj1%8HI=VHWi~3+>HT4nA!OslpoVBwn8Oq&)cbdz zPb-xNWpu}prBdsp&?XE=BM_7PTG5>GmTp%np5<2)VcrPOGKSh^tieGaIzHY$KtvYi z6-MlQ(yURl1zxP=$EpmCT{Lh5hiS!l=i$_<mWDz znu!{&3QQrYXWzOg5AF4ZuJ{x^#H;XQV1(_t7OrokR~$uSC4;}Mee_jtYRfdh04Bm| z2wAx>0Si0(ihq@o(K>glqxs5{Oe)@z38$z3aQas|#~k5X!7rvG?EF-~!DW z3x<%K_oonD3}kCufOyfSS!nhlz5pNR4MB!H;nh?{*vb{W;jEBiO7QHlb<@_Hk$+&7Or@Ne1AGTUTbe*^@A3^V z=0uRptpl0gxUQ)F4AE34ZL_|*mLMHRKzmpFLT`Qn2bZv4|Mxba_v1O6EM_j5Vu+1=32A%hH=}?8O51sDkUdb87KV;)GbN7?9VH6rp zX%uPP7(by~?TE_u#d=C=Wua%-H_r)w#)K#MEPVvpUTR6`X!Z*d!JVjpd z<)x0Rl8%CK3|e{g3h4Lwq8>**n2_b}pJ-Zj75989Y#d@897goT9#h>w8X zY|^hrSX`au$3{oF!Yi`?UB&X&93@WJyY5S23Oq*aK+teL zua_wTFS)>%JZfAJ>0H*>K3pTn=)>jG-l#2XO&?rAWk z?ErV#R{YS&y--VOKI7OYN|ArLif{($?Q-{E&VBM)G!Gn2kq=NfRUj@oGekV38ekjp#Dw1^lO?olU_B+7$G}a=;gso zj&A)%2f*^|+AwPLT?noKn>d#v5{)jcskhWhBpmnqjyTxo4J%Eu+taL=?PczH^Ip8# z<9u`(hifM9Xa4zHu8-HuzaUsaKi(mEU59;-uHz4$Xi%T%k^Dd>;=u5H_zF7N<>5CT z__FaDGs&0i4Dj3Sf?&?|h?&m4LI%RAybw|9Y^C&Q{o{S`KgX?+U=J3+Pc8hvPmQXp zsbjt0!}0&otKz&pfkCv*+B-E;*6E#--TsqSNz%RT<0-te0uVEdhjJ~6;c06=Onuq* z%zW65z#7TU-DfubaPls(!4e}3r7mRLRv~pjPRdbu5s*Gs5;f+K)y{tJC)-~*bfzY6 zMpFe(SR_Hw5h*yP*N;6Mrcml{E&{Pzw+!3&6+rP#a8cs|a*mUuYFx**4zZDjvFAiwwZMlIA zgA$0Wv#_;Js#>7y+?x%19}is;e*ZcCH|??9IsI1dlI6L+3j+JkTl1P4!54dUm@m$( zFgJtpR9nnJInMZOi`A>ag-o7+&tT0a1zK+o@>g_9z;7b+$=#FFxXLNr1Cs|N^II5T zsyB3kQH{r(DQ%!59x|6Ym-^u`@cfGW?`qDApf{*I#!bfMY+GIe05ogRmy+5ao0U~m z_+fjv`4XJH6WY&NSz@rl+&%($n1aJ@)wos`Nr?_Uwg!=mhz!Ml+ zqU;>Vot%Fn6hs0l`L24%#>M-nWe;)uUQ3NP9hH|(|5cm;2APHlJhK$y*rN>>`yP=; z{m8C3@;;yGb>ntLDPXfbr z{7GD1Qn;crzAPSyJv_wj;VkAO2hsq$yF1SfSB0?kB+g3LWGC}-(Y)!@ud&ta_8#jG z`{u1`5I?AibJXOiEaYriL)#|CMcZrk+Q;@e`Vcwy!3gU0MgXWdGgO$BzxiuYj8;-{ z;C0#1NmQidd@K+tZv6c*Yte9Er!Dv84|l%vK|NJf_V@Xs>(mO^-ShA}TmgY~0GBiU zSMGE~d3DFft4i11qKB27@E}+yEvNU(I4*lPN6agF{#7V9z9DxzbZf> zK-%rO_N?IVwBIJzp%EUD=u~2p`5Ot3jev$dgu<#?tF?w;PEoI5F-9`BXwGI!Q8xwhFWKe_ zSx>_+>k8j-Eb4>s1Ng=u5AKS)gF#qf;!GIRMAwldS};%bOySiiFa>8LuOqNHa=W=W z2cb5pvtPgSVi*Q>{t8&?)J+m#J0&+wsO;aa$Q3Awfxh!s5iapTm%2(&3sFH*?3T+x zAbKG)D+qwa8EGZ85zT!PtRj6{EJ`%_Wk=s3)a5aeX*kY#defAec(QVmdgZ>=& zdi5mlXh2Qefq?BUHe*fFp^GaefMpoDPq6san>MMZ)-E$?_{lr4ig>Lkh!Rlk6t0nQ~1Ij^+E)x zsal+Cnz>zW>c2Bf6<+oqu|Q_<;cso^1Xj&ud)<89$c}=7M$ol0bp4S9f$Ii}g>}A9 zm9&$sG;KbFf13RwHcxO=re(u*iWa zPm)3Yq6}yl5Ixf5|5qv?@|YAUz7)eNqg^W=C{bl4g@-ejVL4ealBkJ+G(`Ua>9pj^ zGZ*WZF!_-b%UZ|Z8&Ga>@F`v@YxtfX@=}EV@Hd04HIP(CJa`I%9O#(c;&8YG(Z(nW z*R*o_9y?Je#FhqE=gG!ba<&jZieE$ILi^D-ckU}bB&6i+Nl*a@I7zt??ys$mU5m`~e9vd>PhWY^-E*JIHyZRL{|oCh6iKE&JB6}#6pGo?ofGY3OfM@k#=FF|42+AZZhe<%@~ElUDvhz1bps7*u3W>Tb{ol z+9MyGesE(Z9+9FD_OpJn3;&zo+a?5CL_X7KCo3Kt)4^IBgA+EBsFH5XL zo{$Rd@?Fu6C{=BezPuoT*KBzi5S6-9&WPb9d*Z=Q5M~#mMfS2))}`-m!zRK{iw1~g zGOQhUD_E1}saNcqk@9`>Mx26J2xB4Qz$1Z{>edv!-*oiPFf@-cHH1p zLv!#XjlzPMb1#b)kqs4K{;FW5NWLG#?`H~YS)eERbH7q3qG)lu$XN34{xC~rKWysZ znpuLMmE_75dU|p5ZJbGk&sjD1XPHYzc(Kl6=F2MH+cx}nd?x#T52l_;JJ!e;4{>4} zD0#grO_2u&iZtg8%^EdF3&sBIo|i_-jAAqy6(c9KW4g-5dZO_!3ExH{auvHL)s(3= z(1~~urwm{tRwSpW23%?&;fLK#E3fjL)m{fO9J#yy0Yyoi*Y3k-Z*PB`pZQ4>|IU{S z^kfuk9S%f{U?Q6(kkC4#t4Cxm zvJ5|^9CR%~HYvBB04IwSnh&8zUk9oh%MiJ))|n(l<39y}HtwrKPC70-Q`Q zq}1bS5L{pwICG&|t1uX}{63E3?QsAU!*L(I^gl!Z5pDviiS29-df~ zmz8IpGnPEhr?ba=`L5Evrl6xpljPgfB9{?``hQU>uD6S)2d3X1DNV~*ZPEA0ic_^( z%n1nE+S3fKgC!}6WJQ~kAGH*z^$hN~?9eqRP_l~`^-63Pek^9drJW&2dvkm6hFzke zvN^nx%oo9d;G>DLpTgVw%zX#i)5KM8ec)K!2Q*^DCQ1rc+6Slcle^fb*Vb?DXZuXd zCTCKTKU2eRc+C5}?FZ|0ZT+Bxt*PgRNSS@!BS8&FSpzkm8}}U=J|TPs*k>6?@TK#D z#fdo+;H1=1eAX5ELzB)z_?oW~vXr0ofzJ#y1IrZ(UgQIKK!&O4nTD*Z=9`Z#TVx24epXx*<1&Zv z)S5sd7?GZ#ILA}UmS_m8?}q3VDI}*HJzEv}E;nrvk2NJ{&VmSn$)Yny8n>yzj=in-iwQl5QBMF%is@VL{M>8VE*pJS%F= ziK$~-v}n~6CMTD6;A_>vBq$+hHHlR?2`KfGvw)H)-BPXoGz6&7Jr3Km*J5B2<_V1Z z=|T$mZC3QzozH0EosT@^a>Wr*ajWHs4~<$VMU~1f{mbYQQ(FO$#a0>7IF4N(ve7DF z(g?;ZdSOy!ZkDNyirvL+iuBb+v&Cxaqd#UCmXso7v3=@l%(Jl7t{NCD?VfAfU-)>t zxm?sIo!BDKb{<~&+^hlP8b13WRA&CoI&p^#O`0<($i!RL)sLM=#Z5u6bRMrhXql?% z(!=%L&Og_5M0n-b6SmDsHL_m;B;%cvj|T{tZI-_0^oABDbIY`XO!q_2odv5_>(Gjx zD(ZmRE|l>9A;wT>_}U$Nbq3R$78?JZ_>Ns^n^%sAbkLiQc|a8YC?cMy{AQwLTmgf0 zFsm}Y@o1f@bb>BI9c0BH)`Pr^-)BAL-WNLnxkP!&xO}Ezh(OgGhLLFI!P)|n`}2qQ z^8(GfQq9<4eLj@aw0N1W)Lgt=YEi4?V;YV}s6)+!Xtg5#l3-IgTK0OqG4|Ti86ov@ zD|uJ}gpH_}mauA{_6mg_RPMB8t9>1D&$%64LcFferfvSHW@mk(omagH!%yzLf(_Da6tU=SJ00n`Q?O z*YPk&&nFN0XL+JuoK62NynN&%{zrcBpyveH9-<`sYyd&YuKxoidvDXN2XI`rpKr$2 zfXiZdbIR`zqTHc5bc2Gv8~7s&LM#jjrP7j^&_UWJQHgh?6n%9ii3|b)_e98q+`Tvy zl8&@~leKTY3DBp;81#E&>3`Y}9?)j9n>?6sEtY%mEYvA*UMgeqOQK@F(iBJkDaZ3EYrFHFE zeEy+-BQrJaP9hiSnV@B5mU3mXs=4cDZDlfyS=T$V~#a8 zLxbC{axl3rBbOboc#E88Uk0{qoA(J=l3uI7PaB+j85q_)u`v@^^$E`xoTss^SJ|8@+{B3J* z3}^6DYDF78EF}enD|LZ??SN6XJ#9W1)Z!KH>c!JoN8?{$@n4+2*tWgVT2j-7eEV}p zS5P?5F8lfEN4^Nwd=y!_lO`@%8EJvn&FsaXp(KtdQ3i``8)9jQ3FlOFK6;vJUz}05n9AqbwUqLuM5*%*n*w3Dv%E$;zpqb{wTNPp&l1 z@Og3URlOxkVGf(8e{E|Sj%VKw59R#QIEuFk1VePwh_ab{t5)HknS@_g6RT&zqSIG; z>awPI-`O(l$7$Kc+7Ic^b07Gs1E`}a^*t@gpJWO=9B#3Kk)xyj;HG@vZ&o(Isxsn@ zKEJXtcYRK&LA4?%(dsgCZson5NZX>jnk?|Raen01vc~lGByaCXbLDNL;4DbjDy)1P z^d4|psAC$-Y5*k!bd>+<3PWiz4wuI%pO@9*Tm!uw(DKH&PBGc69-t&wVa@rzMOo%I z39vZ7y>J0HG+lI%ZKYLp%qVYSS*X&_nI6aLV5uZy7n*PdN?{*dy2ygoG6{~e8^!ZH zvoIDBq1+7x1mQ-74bH@pNHQ}-3vL~RP~`)`GygxiI*)7);F?Hx zTSO_2M7>qP>Ap#ad1lN=KPwe&&2tT|e0qg6UE**@TZz8r7ya6>BRN%WCHF&58&3Z5 zJ0tUQc;xG(_snzf>mW0p>!<;_%npRF3)I^CC5{@7#=yM`TQSK%fW*}l{|cCBO}-f%9cbuGMDm6w|Ff~;Sc{{tUQ-!Al|`mp=4u{V+0a& z0^~gF(`X?QEC{~>(@NPZ!vXPcSXre>VlTt3(B{MlGE4<8!egtOPCL;B!-z#gVax_3 z*adt}=EW}(s@?U!;_#Oo% zn?Rm?%>%KPXL;y2*!vb1w7(+Gg}K-tYUD3j9DDk|>$1zj!Nqm*U}dH%BOSq&DuZ`6 zPa0@e62mB^*O4}k^8n;f=_t+<`|?D9v~Fy-0!^m${K9P~uSDF5>7X=VKT+JTEg}*q z_$rhDt)}DtG^F2|PpO0AFEiH5I0 z$28G0`u2r7Fgf%Wa;RDqk@Pds(pE}Uf&+kdHjNLSD9yZgI<@v* zyd=1Nwm#}K#JD=NVASBpKnp3*P6Ah*eX!p=AaYY#!Y(3?+r(zjZHc@<$vm2ac8dOr zHCud+s)H)pGx)g)4$w-c!xgcWyiT)1N;HhXIMYF<_F-smYpEz-J698|5Ln2jWTw@d z!cpC_w#CeM+>QDAXQOR9+Wza~)q7`_@1W(nm=>;`nIUUoRg@z+4J{^A$gJ0wZ60a= zD_LK|kV&}xw-N-P_@Jq@C${mzJi2;-AU#%PK*OOdPzFAsU`P$#nSnxLwcQwCsV`eO;7_z2`B*=Z0 z>LpR6K48TN<_ZmBpsXg8pV($1zPMC;!qJII+8SuLV%Rem99Fqs<_t}|`Me4?5SO!V zOl_Rk{c~1Wu@Ax~bd0X%XAK9NNf4&=2}^@8xU?sip4{XRlO~SFd^awn!2r231O!Ah zd@`OG@krd5QaU0p%<+SfD~rI&9!v36Iwb6G=futoXP&i-r#n9nLji6ebp>II-YmeT zFSw8t#A)5X;pp6ag3`MOo>V?pwK)X!baj0^cD-M1c<)LTo7?L*4BRh#_4pLAep-M0 zy})e9aYE(x(c#EgjDu>3|A%(W>0T>ug@x9w+kQKdw<@oi1GeTA&p>PpW>szK4mKN#6r_Ok{fBuZiw;SGvOmc?f-c9FnL(iJm^aF-1| z*-MC^ut%10dZX@gcUr+$YZQ+A`N=Fpu?HMH%AsoeV|sEBgZ@aJZwb5EYqIE};5#sf zcH@%C+Wz$4K5Uw51o#~TmfwV8%p*JwDJ$#9lLDvi*opOM-Tu!-qzvNJNfq_Qs&O>Wi539DkHycqnngT-nO=}1zOEo0eScd_G0QIDJ z907pBR`qC>43FA&A(03BZiY(ww7s;yLHv#={)Cy^4>M+o32oVVVm;GI{L9(~UML=! z$TLlq=5BK(*JxLXcPI7r-*tm6Om3#;zdqX6BBvA5LGbtGe_aE@_xE~khsRA_EkyVF}qXYH>|FRIgMu#*`TYS%NFW{8F@^ zBlgwo+R?R!sjLQ8Vt_D~A^IL7uj#k(EE0H&gB5$jYe#ZnJ=;&Oz?}C=EV7D7skZmR zxm95jNTOD2t@LFBt1)Q3>)Zgox2l!VE-$rnhR3k9i}(J;_wge>4wn(CZhp3lPbedk z+xFd8`zWnCko*Q-MUNqYP0j7iEHf>M4SyC$3>z=62YTnOJ31K>8qGGYSc895O|FYQN|6TMPesH_V=G~=f@{7NuKup-q!~6NkrPK%Z`t?CW z7ST89Q27{3@z3(HnUYed78DgMBVckJA)V0C+6ik@#WJ+Yus;BnIuN4zhvDru1S{fI zEk-L;Lx0?hnM7b2>lDS0I17%$axI1cM)4w1O!A39`UOKlMG-PCVXTAW8L)VZiRcj+ z{Wmd54onyt5xZ2l`OS#_$P~Sqq3iT48;e5?l}c$&bL<}tQh7?V>ILqkLs+Q$NU@jB zhw2t$)+m0$FMHk#lB$K=5E;f6Oc0~971**+K2&Pf79VA;yKnKu%`ERV7_35!>QhL+ z3VTACap`nyFV(Vcn;oM*x*juJ`CjBU9QSFHbZcQVT@O9s;Wm;RNMIs#*Lj&5euT&+ z6mj!`>*XJOPI>Y_#hVu=AvN}ierQ5*mCQ;rMY7y0sA0P54LVI~LoT|~iYS1_<`_xL zb$v{irKjrDnu#Pkc5|9l-NEIYUReh2Pu$N)PJ(dn_?=J;mN_iGX*{?jtCyL z>7X(oxhcYl`hAKww=(hW_+q>HSi{h)do&HcUqS&ur7SScg!SeFn8%|Agl(b}t~m6B z5Q=y`PP>gccYA}^ zJJDLiWisOHDpB6X^E4mAR!$slCFjg00zJ2@;<@97%i_+4*XX`=60Vj2TUMT$qj*#r zNsi+2yFRl}k(s4Rfs?|FSS?*iVOwknpuOo=wRYn|Ucni5m?e8Hv!qgf`Zs)otNd#6 zH4)FPK7p)UpFmM+c}SD6oGwV-M)SLDAe zO$2^C$I^U#J<4lRbq0cTkp8itE<@wgb+BDPYdpoaFCMfFNuY^@44Q#(!K+Hw^^D)= zzt?^NF-cFqxKouXQo?*4J$aGu%%8b#Yr>8po>iU6lG%AP=Tk6|s&lxOKmhJAtqACTsfA&uqh^N#b8W(rkm$GmAT#&$w5DAb?>@QT#(JxgQCuni4Qpip= zj_EqYi=yzf({o0Rtj5NowLp7FW-K+5y>uj3qR6A{_><4vx8l(!^eI~i^zB>eea~{< zvl(I=UaO!3#n@x=aJqr}A`E+jl+jAK2+N&b3?XJgGB)Nsm1BWrcqg ze-mH+br3l{-N0j5UBh2H1eIyA7x>&%RjRbDo5LN!{r=L{?!V?1@MTy4rYk`+_Xi^#P`)AvwlWD9H zO9D(46U4gkSn(O#!coP614v3t6;(5PBTZpe*y!pC+#*j6N=8|1tV}u$@#m>tr1NGR zQu~vE1UbMqpo!Y7fKE{rzGu}dQ+k%Tq09F;ZyBF??>liZ@5szDaA_n!Q2U%LqYo0) zZpW5{PDLa)*&4vgvN_ZoXR(pciN|hx7e}tc=55n5)ALLsotXFPu4$GQal-y-TE)ut zBH~67Mba-~=hjLhjuyK_JA{OSS}j|=7hP25JFBL=G`ryyBz{Yogl1#EcR~Ta)Ln@? z-GTo|K6K(J^sk$g%{wkOxw4803rtm)GA6?<%q)wa8o4&56*?-_)l(YP#-sG>M{G^E z1#MK?pz;_whw3lU3B~Mj_PKj-<^P_yd#>~Mvjh!nFw+Vjq#g>w9Z&K8Mx2@5FJu@; zi&tQjDxdA2Qx`e}Rn-WH!i>P_@ryOm(?axHs;yI|MB_5|gsFf9K~k)(!g4$iF)j5h zbD{hso+C4tta}t^?`_$2QZAn9_PLQXQZ5n=y8r}1$TnTC3>0ifCRI;YK~f4Bw%Meg zd0=vqA|sgT`$?P4!eyCVB3fhW=HH$EZ1$IM@Lq?WM04Ti{~7u?I&+#7a@2M(f>>SU zV!Y#U3zpU+p)4An^U_Sqd^Fu=87X7(Ng{XgBxf*7S~TKG)?;mieHP8AK8-0}E53jf(X5uK>`6L?&5{~%TAuMs5sXOqP7ecTj7_Q_ znQ2q{IQrOCU6_JnDe;b#`@3S=g)ZTx7~-cx1;_Ux-KYThAqjLMg!mYh7|k@m4C{D_ z03~Y#2O~f2&obh4-j={8n+qsHuYWX6xh!sO=Ac{IObP(vPbi<_f=w0i z=PY)-E7*(~^NUGL@{&$H!sWf1@G~j&$mf8im6Y+& z*Q9fH2cFg(Wf|Tq#g$^wVVrV54p2=WOfD7lwmos^6SjCNT8!;X!cZ-l%@KYNblm5x?JFU zy=Eo(g7b%qjJcC1k)`tUfq?4-nS%H->4DU+QeFXgRHq+`1(+(a2%#@*>DHf!>gynN zpwc<&BITY#!035F6I${YDBr7+t{0yb$e(ZB@T;pjBzubZ!d>F+k}*f+g?iyn@GlW# zDnXTr!|wZswxbjy?IT;#ICr0jr(HlhCSOLaS4&K?LJRXRT=R|`Y`NBM>X;4i4Vz%c zrW$@r&Vo+X>>nBI3%^Gi0%Q~(?`u4$LOA}b6E)b_>9}Y+!z?!EAJ5*t`XWNTqOYi7 zO^KJjpBW=^XP)2zGAft==hB9jKMR6S71rd9f!>#`P&xoOG^U6r8@B}XuD6pHJSK$+ z=$#`L#BVd0NVq4?0tl5&Wo8DiHGv05>tP*8Z_1h34(z9KzUE#$4mOO5)8681GJgAY zI6(?n?m&)7`eoW~fgI7G{yOh$rw+r8a;_{xZj_u_I*hZ`^W)g4Jh^h^Ff^#ZPb~T@ z{BZSk7^}G5tE-PglRUTRd~f+>dTssu=vQl|cu(&im#c_AS5_50z+-r=RW4|1{jU#M z%6^f*%_cdXsL#P%z6O~_%>Q(7;j6AJ2Nyuu-{J7dO_!uqvyv1Z$YTj#+iowmh%Paf zV?I(pT4=%!vw}$%+a8_$vgOib&z$FT>a28!2oTnnndG{)Y?rs3(lU_PfR znUdnAi+`kpi%zKX)P@TAWixocMCiweVL_;R-S3eSs1Whbr4e5CxA6|FcaPPF zaVmU*k_2r=u_rq-#W8E$poN2h#)A7Sm2AZ$01rGQMx8S zf429!6>)SE1!|)3{){jXSq{oH?yBR&P!!)Wfqyq+e`xP;Eyw~e{w$iEDwsmIKw%UE zAJgm|u^uc>+sX2It-0`d%8}|qIQW&c@zA~azPQNuYAA+Sm23TtYn96^^=ch=wqceP z0UY*$1-bYj_EH+Q|B@lZ5Lfq`IDWY2qE4fX#~4TQcztEWIKD*~)N|ETg`R*(kbtlcd$Y_FIZEJ3bb1vL<3A@Cvk#G!*!Q42wv(<*C2^Z!N z<8__W%D)ie!Qic%YH2?ZqaJyHKRds5 zDm8_sc3t)>t8>enbfiOGA##0NwScZ!|UsqCXUuYGORI6f6cE znf(ADwI1S%AVuygZV^HpmzC`CZSS#}xpbjfQLQtc1P{Q(=xpFiN%5k~`3Qs9O{8?; zb6dY~DCCXC1SNAgifOS_$gN658+H@z)|_gziq#Iap4aU`S0Ts!fT^KCcVyEBNbl-? z)7RxZGOfb!u(bR$dm6SYI|i;YRQKFH8R+eELuoS*V^SW@xx*A$qR67*5&Db^aL@5j zrsC?@v1mJPuegyINFOE3m1?q2G{(mTnqR%O+B(_%Yi8Nu{^RO*KR)!7XKWqD3dyZm zI)YStTZFmw%W%e#$clYiGG6>ci(mQ;wUerdGTabE z0p4#!R!y<5qe1R(PujuqGM$N;XJjk{+G++$Dn6lG#kUp3bYS9sK(FpRTko)rco@P} zgjt77Py7;N^~6bccDsSY_nnA+;d^Oo%Y5+t0Bxz&adE=cSc}QIk`JjZh=ro)CHgG-UfM?tK z^^n=tGZf`SE}ZTf&dupH*WrFC@61|vTO1UP1L6Oov7aCyrKYhl%y!jlvFPkC>i7bh zk2z0jnOHNQW-dK!OT*SXI48k;rf4HM-a;eX=|1I4d9Sg`q(o=4B`9enP`Nl?-#Lk& zC`9I(GTBW|fJK1tR;1G|o|WGFn%6P}CPDV5t$Mj^Crf`^HG<6+b^BZ}n6q1E?8SKx zrI`@_V*5;BNKmMavJ_*<`37(V5&)F%TUmJhkfi#tC=I0Df8Dr~4;A-I8L?1Ew2fpe zQYbRQvjr>e9hlD?Sz-9l-v=nB+OMLlH1>>)b3|2u`99e%W;yP@%dOkLme{sGjcw?7 zSRt%Ucp-HlPlbDiD_gh{<@5<8mWQraVub3C>wzyxBwftV09QRz6FamLou_jhwBIef z>ayjLJUtZNhM@4|`B!ssxPPan zX6}(7Re_1|UoMt(_<)?8S9Rd2tIqjN@@2SqO*tL=H%BcmDK7Tnm?Af1IDvdvinxhE z>Q@?MdCZJC}4p77Dp;ERTtSK#FIE>}box_vrqVZqq?!A&sr82StWJu(%b@SM*`=j-QGL?8; zTN8y0le!tcO_SyM)Tzp@MI{R73l}DZ^g8iLaxPVhu`{-DLTU<1eNqSzo49R$hF;iw3Gnb)u-dT=>Oa5CCD8tQZqD)!4m zGKA84Aetn4mGhbs(MUH?DTI9V>EtU0XKo71!&8NBn31#WA15214~I=hcF)Gk%vTl# zo5k!B)Rm-gpOS%e)8y5{-LdG^Vhanc(i+jf%49GNMF`i;2<$-$=YrhGvtrM;w4My7sp5 z67^eS!BdO%TGT0yEvMo6*5B=y6JEagO}0DD}jAS%RhrR?e~|7^uU#hw8;I6Z?wq1=L+tRH)gozj?8J6G0JZLPU+HQw)@TpO*~} zr$LS~)1=x9tC>{XML34VXiTQ>NKzu_R!HmO%{Uki)KR;$RMa2o?~l=ff`?a;pzGx} zpF9U_0FFi@E8moiamon88f>FzxFEx8`gRMJ#5rw7!Bht18n_8`F_)}-YY6}XldAn)wnhtX=|PIKqA1jX<$ z<`eLA=i);JBEc4`|2H1YvAez8D$;%e;;&gUgHDC^@6C?d@chuBt|QwCHCidvw#mvX z7bsh={c+eYpk`&_FQFm|@maGV0jLN&SnyjU209ggdXKp$fRlg4Cy%W5Z46A$#ak$k zXdH4-BAygl)Xmz%NH@l(WrZg;?3*&HU^FJWu!#`Fw5iMrgRshqy4e+T8cQkAqaNYs#Bb)J1GoE~74p{=<|_>B2+4$*;I& z%5!XqOL`d>H0X{cOf>3xDmAufW^KyCDTkHHKNt^TOAGZr6KdFWF@qT*vU@fhg?qX# z>0ODF31D$uZ7v(LdrNPrK#-LJW8gm?w>-PY?Nso20|Mv`!rJgY?9+2SzQtH6#QI`g zBt2LHt$>KRK3ey%M!2VVY);w4h(=8QIlSRi!a>vu%wc2=y%$e_AL5#vGL9vb5M;7a z*-4FxN#dLl2urLBV2l`XefojdqgoHNH!@pNYoyGK4{PAapm4WuR-I`#9{8TdIs8hq zb~iShYXB^z-%Af2td&h;#pg(?AuaL@Q<^@gOE6LZ4gRsCC4sz1JAd-5e{rD7W~A=) zRqC~!FJ`*;al|_Ct!zB#@opoo%b7y6d*}ycj6d1YUstyX|M^5R)^p`}n@6%o!jV{) zLU)lj<3ql0EUCgPl_jQPL4>ZfIyyft<(tMy;L2AhEpXJ+Rgu)u1vE|4;+rX<^ZdjU z#%{^6k|$>@)7h*JtQ9;+?;Fk61=aW3>HqbkzZ30thhvM*8?gSK-$m<__lNsLL}a6Y zL8B;yyu5edUCNi$+%K97ezwRS$oc6z*yb?Xe!s)V5f()hBRT<2nL~rR>(uH9V;rhEKs9retxr75dt76ti81N9GQqUc)aZM4yWl#W;Jc7S zqRDfrD>I5*3PR2#&c(C>H-@W2t~I_~)MpMbkXO=tKYX^(EXz_R zm}%p_TaVIW){_*z$C(yrK)9~-;Ctcwo)_F@ZCx>tGY`3{+qwE^fsbChA8I`7HK1CHbc&GH&CtClL>aLHZx+|X6wOBCK^_(!(_U)#w<<0i zG?l<0Y$U8i0i$ypXV=r#f)zIEjMwlJ0jhuDIu|U-TM8M`9VoqN*b>Z$PsvLV-03iQ zE>(;(j0|+ohE9pkq#U9j?-dpge3rQN>#q;0_k{Ph#!1k=sVB1E_kbJ{O7T%J9xy1z1gXDXQI0NcV(iO z*I|wK)ZHeU;*(T;mvQBPJc$9YXbKHA6)>sIk8HRH;1Fd1?@_%nJpDRBf*{-&ooCwNDA7uoSg&-I|$$z#!?YoS6}0pRjT1Z?1H;?VvLZ zBUSk8eu576On7bF7lNU6Nv=uv!$C9-(%6kO3cx@z3dgDq5>pYHn;eGgMcfMhZ z!nNo*?7msI`_pSn^RXo$AgL&lG)Nv$bbtN2ZC{~DrP0i9#jr!*u!Jh~^GBJ!Q1 zFK37H)58=6Vlfg2mPTQKi4;wz#QuNGQUw%BeLH)RH4BLh8_90G46hkBGHJnMnSz~{ z8Rf49g5!xDv1E|Y;bV!|aKsm21%D{*9l7JUqSAgp#m;t(%K#LgGI>Xcf)*7LqG-Vg zuog`QmHhyVr3!tcEBul;tZ{NL9LB7P#Q6P_%3qZ3#9IUC1^`stT&VU|Hm@M#yZUUNknDZ{2y=>3w!s~+QY zvr5C&83SwTHZj*|V^gyy^B4=NN&zU8jPz_2=Ef_lkrqTEmpe>STHm8uV4H|-7(t0w zKFbkI?xVJRI{Aym)ZaoC_Fn_meOV+J9T3c#S-qI3tbA(v$LBz&YgIm=5R26(B#iiX z;1x#&HpaZTtUP`om4ga(3*)cCz%fA?Djo&f?+nGKAiE|7YECPHD71b!2<5Q1!B33f z48Y4`Z^xJ9IfW6vux$#6;{CSrq+J7j@m>FwP5%T@26D4*W&WoS3{9ei z|DJO<;nw%Ew|FkngOgGtJWS-xDrWMV3~vaBWHMP%y%Xg)@}ya`Un+@ZVj<#A*Hz}u z(eoEXx{cV~JKCAEJ(9g!V!*ib=(bgrXMGJEUG-d}1uBXiJNinwl@(p*Gml8qB_DUyz!ElN2aHA9B|M zk?SCGBL$%|Sk2@~;zCjDlzGV6@~H7}W^W9qgf){x_3HiD5s9n_!vJj&y{?_@MM- z$ZZXl0c&-XsddZt&HKB`$!AI^59E2GXDMUroc1KLA3-M5lb7}P7yAxk^K_H(L9#q2 zb8j6aIrYO$ZHhxr==9}+Yo+&`AIDBT$hGUEQcrXU1ttvTa=_L6PVgsi3J!i!gy$7(If~{N?m^1+r>IR+gTyvdpy4_1Oj%8)8inCwCQpQ|)u8x>$q@LWDY@@nmI4}GXz_#Z8xB&GWmxQMa;x}Y%ke zu5P;o%l=2g#_2*sP4{RBH1MWzuoQt~$qm%*>;SrJ$Yf}T-{W77&{8n%Rp zF!~txbJl6PcL86-i+y3k#&qtcig*Qe9CiB@alN23+GmhE2 z)CBgXp@4UXLZER#kTXaw?=3W^`&m%Iv z&~j2Yl{N0BwDauz$utvJ-ov3o{S{Ra*Kb^tn?BsOq)~Qc}FEwcFp)AgFpbHv%3_wI*MIVDfvDqwHD*X-o&hxSP4Q5lw zAHQ|WPe^n6)&0Up-~E#;M-nWm=jDE5QJNws`JN`3q1E11>k-fq*`5(~N2l*TyLSc= zqBsjeB)x9mresVqx#`8znI1zQGp17TM(QBpXh0Dx{niner651Q*4KPYp8JG;rn&A9 z0Kc+&Qz5XY$QbvOPc2t!tbOWAr%6vmo2MEu6Nm->gn-;V&i|YBw~r_4WJ`|sLJPp5 z%0~7TQDz?b)2CmbB!mT&A57o2pbmFcqXSNuLEbK6N*=~a&1_1pPEg4jd}OeO%y;0i z54(Z}^V$cKF`)}&MW=bfIFxjOz`2PzC%t`D>`~hG9gMjKt=JV5?t3VhR>N~tKWHN{ z0d6XxQaAZZF^HF9bzG2I+9Dkv<)ak8c&EqQ;$gqe{x#QJ^Xad;9r@p&`ST~URSZzg zQn_Zy_4g=kx^6NzAOw*n1|lRsS@=1@VW}2AT=^Hq*)D3#U~I|oh={}uw@U2gu9(x{ zW8afF#zVu@G3%>0Ns1Di*SHqh&OomDUys|3AsGYAV9m8j;;j@ADB1`*=tIzFQ>7Ua zj?4TP6jrUEzx(Dv33SRD-HxCi4OiN#oh!O<=eY+eNM^nAcJmEp8C4^2UFmDqc)fm>*#@Vg5w}E6z!1^G+aR z_A9|92o)r?Odn#yzmt;dxR-&$&gy>1@VI>OIggg}J{hE{Ze7v0w9Jh6;4Y^P=0#fl z*&ZnzAq5omcCA%_H|ax>xY!KWzAJt^=}aniMPegD=4;ZSD+aaqXc>2QTgj%`|1CRp-%xdoM~HHlkF#@p4L(#13m+9 zh}^e}v_HVyryPOWVQ{6vfZ5N(1oFm4aFRm0wgE8;sx`K17;FyC9>p?|yZ_1Py!v}OSjfDS1gXW85P# zhlwNq0*l)ai|t&NyKCoqE6sg>39Z|s+ReSn+V(a=kz%J752Pb4g!v%}lb%c;VQ2dKc|7X42n`w0?cOme>hx)k1#N+57jX*R!GHP#{T zofdp(pWYV3c6&C>F-dQa^TR-zkCbXQ9haoCipK4~?%aCsvCdlz+=ML$}CcPnMQ7Oz{2r2n4 z+8KKg(}J>{G82C156+2cp|nU58hMn3-9wAkibjo0$7Tv2T_qFHg1$)eCfxnV#>1?F z=Xz*D-W)$3@xVJcFWBU9Htk8S>vVyO_s)v@er6T_HC^wmtH|g267pB!(Ea_yl*I<( zWNfA%UY{Jn@>#w-&$rX)^(+G8L`=nmrHT?pqJtsxL6;HFLb~J|Qq+olXQBdn zLM+}U1W=0xMM@(z|srU5#U+=n-D-GV_BAgzyMK^fzE-yO0Sd(S{CqI2LrR*wWr8p?7klV)Vf%X*qavtG=-Ht|)wD=X-cG zoH}fE4YTO%sO{{AUgatGky_RD(V1j`3Gzl-e+ljS*hl@i8U8F7jCYgq^I@JhzjDy2 z?TW7ioa%~UnIEZ;N)TBKc zTc8$#$$BXn>QG=av*%C1P{X&rxQc_zmo~8t#6K>@P1b`4fnJ%h>OKVR?ToNI4$o{N z*Pv^r9RKf{(YZwU9$1&F{dF+>eWB@jd~xc;X6WtA`r5Pc&{sh`OoeA#_>+80=amsp z941!MWWdS&TA7pAXh4#5sQ5P%4jz<0Wnm2wCIn-)u;juoah4joxB=rCNr%Zp={aqY zgR;q8k<Y?}f-063JSMN;? z->0Uc4VOdxa6F#psQH^;gPw9{t*ui<>1$zmrgMrrNBpHlgJ4&SeE=B2f=t7~8Wxv23lm9(Kg1{B3xj0}Ge{p3tTiMojNE94F zjRYv=9-)@N#13sO#IijG9U@*xeFCJq9wCl41nWYo6szhHpaGq;c7_$IxTl=3e(aB} z^-Vxg(_^QS)|+?Q>KiCM+nEG2UiekwubA_j4X%}Y=Igold5a&ZWnUi0`0FK0oIZLt z(N%#~pi=yUJ;L$8?V>>jWux~ifUvN)FfH4z8@6YAo@}Hya)@~4sgZ1nUJp$w)p>s>h>*-ha->!AkN+ zpw9g^BP*fyA0(k$a@SS27S;C{B2ICNU3PNwVVKf(9sUTu-T`-SO1GxF<4DXIqJvN? z>Z&2pl96u=L5;gL_4c1q8gCTfO#wqVI?#K(;f|`!yf|C@R1Bexp-#}u`B*Bx!oM^9 zGB_A6UI^{ZeTJ%hx${H& zI0f2!(u|+Iy)o?Lz6f#6>8xloRF9YM9*bf#>$MA!`z(^pw)16p5Z-$O2Aza-2;!bs zR!u-4md_+#9EXzCu$nn#R9OC}Y|tWd*e&`b4*O*4BP2l@k#0$@ju9WbcZ%#y;v_Xk z-d$^=fJ|8_eTQqztcuA{3_n&^JaW9*|h~sz|{3EcV9?y9pbfA+yC-75q$oU z`0%IWE|n|Fw&U(yDPsH#F9MReMSR`LCP`a#Vt964*+5b7F19h9M|9RA~W5rDQd zJgfXm(LMuf4?K^UARGcT#`n*4*$%-m(=~Jrz3F<==AL~XElWRf7 zIw<>jB-9S}_n%(e&ua^P&NN@dx@0DEm`K@5x!`ui_phfX{mNs$$X5BAkQjL~xN!ES ze?G^ep4&P6Zg&*BJWU;4!Ml@6T!+~8Z1%FH*X2>4%=t_Va;SEkgz-7RMLcgmdKBWa z^*uED*d*3MkR6BOSSjDSir)5t?#JpoFOvy~QN~14l*Q$k%Fc2<%Z37r4Uy%&WY(Zbq;vO{ zzWxUdrd6M&E)~EL+WZK)*A5K*d@1YZ!M2)|9s_rie!Jy&TL3BDEi0#QVP_X;H*QQ# zE!SakHp_P%O09Rjw^opao_1)b`dDe0)bVBL5|$gmZGPXI?>XsW?X~3LPs3dkV*2Uy z9l{EvdWv(l?o`vhH`>D%8%qJyU4KAJ>0j)M12`wp~6B1k(`-gOn1FidHowNstID z<$wc9j8W!%2M(vFi^qdgMDwZw3#LEpEkfXkib#^V8&QexaD;zXnp%wqJI((%wjZd$ z;yF5=mwO*3FZaC~wYv=m83L=gZkukn-K1pw{l@E$-6?oFL+aL^w&sn%1&g~rSSZ8^waF>(PQY>V76aRvca86o?T%zSKYK_ zLHCJy(c@0TCs}n#Wl{`Gt})bhGC5zT(1*Rl9P{ms2RP$kz_uE4v5OF4{vF|GeN$yq ze0B57hsxFFV-b9pO)k(19)M28s#~MmQ--Ve)yanEGv+ zxvQ8HgppI|)x0g9qsjRi%@7AGgt}11vdN#z*{?0#GJa5TVlRT@=t5T~cFQ%bl8a+p z<3ZC$gJKj4C1?};nT5R`=(dl5optGtsL^pW`ka>)DF(CQ^5M<)wzrY-9?Nx}W>`jE zUV);z%INI+XS^Y&Fxdh3B5TUF2KC0OU|^(zgHA7P=fmeU?%Su#w^pvhU9z2F$m)&` z=5l)oJVo<822wWnK0etT?e`QpAy#JxZRXLePq{iAuJ9u}ldfS85td>(DT?^a-+0;d zZY*={gZcr#eJTNBi>Sv-6+?5ZIcd~-`gu>{{t8~QVRtTHh5pv#o?~2_Gd~80ydSr!-g`#rpJ2R@u24hlL)MuEQ9Na*L zV1R;!viOS9t^pi5O^NAV4QjvkyFWo(jzA_5CSzdgMm3Y*P(~@=7Mkj#HT%@jdn=|k zlZ&!VUeU$Bqtkc(nru?%$x)F{i&;PM>O@VQBTexYQ#kb&QfsfDI2q?N1L`^j;KAEl@bH*)%oBKSy{Z>KXM0w{aW<)N{gByZJ zA|EHLCIwyUNk`pZUk*R~2oOJfGE|h(JSa-EPQ=(b<%#J-?$*97R!utko*~Agv0yM_ zvruy$n{N(Iv9~~)W&$qnFrjl8$BrYeJcXL0Sp(aj?eYWvp&ES!RXlX^eaT&YnNf72 zGAAGr97XGsd2s#wIKhCB;kSccM8An&Rb9J&^tHFszhyWXe3oSd&Sz5IhK_awZUr{H z_w_eC0;Ve(HS{f}*#g)opq>TGDQo#rtnpRLK243`(Ah+sbwcM2O3S2PjHy7`rv?gf zr>qOmpPS|h6C8BzX+tq2K~Bm}7g>kO(Eie(Tno)?GSG*UR1P&^T@IAa;r>$kqmvN> z&yEKhsO88p(gb^*dLT9WiPCjM{Y7e?x>UDT>b0xgLDqf1!MSV9jPfdT_`9B{;#1-d z@5k2n{`m6??hADlz)&G$cnMxkhiD+Ji`N8K^PkNG{@dSX?Z;P(ubB5JdLHZSUEwE} zzj9vgwR0|;+?<=v$4oWSP~6uh8lZ#E@&+9unlPf^cxC2{w(J5yh(rYZxE`J&2!Rg4 z2KR3yu`aLB>-=lKaVp{M9KEfZY1 zkn->jOqNF>`>4yfro4>`=hF0ybPvm?P);7%`1}+El?ye8Ttbkna@fk9?Tx^9G|t%R z{}7&-@Td-5`5G+n{y2DJCeZe_9XO8I=!#7Ml_7*6SOM3A^XZ}6t{k1!zv{Tn7iK1H z+HGAj8CO3fw1fD%{((v^DiL5D4oNtRW=@VY?<05Ig2L#St@zFtPYq34_2Xt&`+iG_ zJc&NeT8i5vbIb*#oFho2Kn|nYl91;&y&5UFT}mjxd+HMot3`oK$$|tcWB5v)T$dNk zm`(je_81H^hnyZfHHK?H`@Q($vTs!TH3Jk{(sYkULv^|48&CqKL?$`pWbgWy>>cu#UaQk52^S1yWo7kuVrg%`$oJ3@-Q9~AN9yvm1PVy` zbzP-47-$>ooGm4YCK2pX2IVq)>7lVmuin#N!bn@*li`WD_FHhN6ahS7MkeT%#4^$c z-z_zQ95Z4fSgf+}GEDdz?Xmnvzo~d_!15OjwwAO7=UIWxU70l7QuF@iz#=By*Jf`a z{I7YhVVwoo))e!S#C-HtaGb<-C$xoD1eoIUSdt0`5r_Ucrs>aw=|(CknL}|hC`ElV z20_|!R^jjX2c7t{xs@y^?d0T8zQ4NDvhADK`viO^j+@@jLv&yCPFcM_*kfLvIJ+LD zUV$?9&Q{QeC1SHMJPg+8)6jzyEQoK1H&cFw&W9oW+doB8Y1Rh}z!A)JD5j6Ua$^r8 zxu6tYq4#S}bbogQh*6+2G^D{uX6WJQ!vNv7m+eyl6@;j1TOHUMW7L}IifFdzvy^8@ zQH+>SceMcLX?MGz11(3IQX(6&J^kTFW$&;_$&__mMq($jqUi}n`!%+^psP3QXG0lT zOq@X_OiFl^;#=+6+%)#XseI@iNCiEw0iw=LsaM9 z>6CbwK{LCMt`?`@HR-DZVb;jc1l;ds^->o}X(hzbv|JpG9*an`(NmF`oBOUYGG-Z% zvoT(%eg|>Cy6|4GyB;!62tBtFG8A&`CTnIn%_SheK9GGt2}Q>6W3vca+?Gl;VTQA} zv;@n4u=2A5Gu41U9p-FA1Ei2!NE#fM@PAt0k=@zCWWC1aBf$~&II83~8J<63dmokx zdOW)h@0uOyx14KwLkaOm)Qd>*EVIwlm%GYkcP4ARrp7t7k#(WAn7r=aHY=B&JM9L; zwd(+eAwQ5&Ky}0{TW+J+>crGEJZt(6D=5P*=lyjy=d#hMZZ|N(Zz9F#{zU)LxN{$- zx&yp^TyV)s8F5=L*XiEnZ=dlmaIX2V+dLhLQQ)nK@sE|v-xZS2=5exGWkZC`?}~tD zPz_K8L!$URphP!yT^ggQ3#1WF3O`IYbu?s6ux>7wB`6=iN@#bBEu%Qr*R7mW}lV6KS0vCVUr>d&ao@PM9L>d_{TZG4Plho7d{ zHcMwa?*3BYihIH&N2U!H5Uk410QrI2l_ucQrfijU z(d39cAGebr??3j$aKB!ExPz{n_MrY3)T)3y zjla4eAtWXSn~{-WhAXirrk24Xo-U2SAvqR&b0i#RI4qAmsJYI8jm%Bhe_T9?kqzgyyENOEkF&-`B?o?iq{*;?fCs=5GY)e z$O7~hqBJdP|C5Pgu;e@^>0R31)lI}Qt`;?R2z}I>w=v+5_D=mokDqMxiMYaTk}dj- zbl-oh+M^TA;zv(fGR)TDZ{NqJ3;$sIZP}1tNJe|?M0d?0_WoPi(Rxq1`fpctImZX9 zODj09qdvz*%HB$?DWAWHlgNFGic?;O?IJ6y-c3#LA}W3nt+G0ZS+Abz1o)zUn>Um6 zLOcVheA{c(*|JZayjdtvHE9R0|L`(W@rqv-*WQMcoHpz1j&P@uDJ-M|alyczl-9=UKx&V#N zO5p37c%04-KoA}H+ZSU+N3qRGC$@tWga6h2Rm)pwvm%G1G!+fV^BDyzl%Ces6t`nC z)%RZ3S+l5PWL;!0MrVCI-r|W4liOGY?=$dqVTRT#;o)EihL&NRX^-L|!9o(Y{S-Q* z%DRIX#sn1umD)CwWn;P9%x^c3@g>?wUFQ<0^IO03kfyzH#>k9tNQ2|X*Aq76@9zG0 zW$%9f2UP|AO{UDU&HgMxJi^)|ACex469`D7!U!-b$i+P-cG@fHB>pk16l9>NHk^e# zG!@9kLCKEakFCoPY#YE;C@7-*WDi3qHX<+oP; z)_j2Fgkr)5IM57z&qj(;&Ss1_oa+G^%t8d#imKSDK+*XXCov%TQCXT(suLxGO72kN zoUw4Bjvw7;C%b@Z>mEfQ z*c2OALrau``^dA?d+)sZ2RxyX`%y%62b^w5^gzR{I139(t&n(XWhtH@Xfy!vABtGF zY+WS>@~v(IWx`t%9I28O>mm1MZonmB9Qs8m#^<}xo1GG&PMtSVNz z@{ne6s?>|kBfz_Mj5%n{3oUL^$*aaROX}#o|KRh>3a`S=$o9q@){U5>(=?V8PO7zy z{j+RHv2KU!rdiH?Gv_vQXq9f)wUxk5ONw{*{XQa-mEc#wxxR+G)ALSHm4ku$_q1W*A4|0}|mPJMv4Y}Zebf5xN=pe6|Ps#qf@7E>XuH&tDcvkUj{2)EzUR3Zw?okLYE z16CIFZS}E(9D$4cu8%1m$xM9ZN92^keO1%0O-Teuh9NFa^YtFRq@FnrEPn%U$$Tu! zq)^aT-D9#8uItv8>ke@XDm8<;y@db)KZ=Al#;RS8;XAMUQ$99P=XDex(~9+Ou!vl3 z>U^I8(3ZIDUsz}*5E2a(G~Nn0HPt@Pn+}6;Y^6!M$5FCgU1Y4|bOc zL7*2UqHxfycC0-wq%^MK=~8mNn7-*IJK?UmY`jmcK82LXBZ!+gb`s1~Pth!vVf1tj zao&6VIr}(g4YSHifM~<^7#P#JHRoY}*x8Sy=eOtgb~$K=|7Xo`%#_YN9k?*D81+|E zBKaRBF7nDQFlo8`JxNh%Yg79$_+y6k#ja(rY2!E(eV~RikVP4kYQgj*9Q5sBZiLG5 zNp=VdZ@U0MX-h?dj?l8!w{bT&U3zpgmdmU zyYA_a!Tuj}veOhxwlV!hGvqJ_k|wX`eAr>KXX1?#!%XPuR3Ns^3g*qYocDDd;@g|uTJtU5C3fEh-$j@i zA`x-sGL$I-iFH@myqJ_t>MNdPqiAwpqRYaF%&%Pdom@9xpnDe$yRO3uPiX;iW4NJ% z2KV%$GzP7nG?0cvFIU-Jb9`4(A*?(U&m@%XF|p^o_`vh1Lcag!J@w19rvy@qqemLi z{K3!d%YZX%SYk~XU3PV zWmQREi-Dz4wO8&?-LAnzr!BjcJspo;?!>j$q7gQhNy1>DLC!j?BLOd(BaBd`_wf5R z6PvqO;6xox@v0PEZC;D10JozX$GJ70w;k_YYmiZ;hRx!LB>M}}#X(r)xAnsIty+u> zQq|_XLhJd*CUfMZ$9Z?v#XjHuTD}caQ6;;B`h?V^*k^`mq2ZK(F%;tn%JK$F1`AD( zXSEtynf+I8QambEC)DR6xb5`Bo>)LqmR|GI#}NCj{kKUrU-8lhQy8!m0n}>!x*@e_>qwO!wW}ab|0D6#U^_ zv&33pqTq{!+Z5*zWNrr=(;IZ#oK#^2zBK%*I|tkr{@0*Hahk$liqQB|d7I21=+^Np zLNXPAHI%bB7t46rfj1>$VJW$kVj!g{X&i=;ho<73*bkVcC{##C1fJlo%H%<3INjK? zRh4XtV)%Di@~ZX3o)7@s^9|i{qG|N#!ScSK>7UfT}@wvcOt{WpBS zcUT23qNg7(xEn6ZssguTgH^gd$76`;4k8q`J=LQKg2)*821YT}nv%-R7LdB)_F)Rj z!>Mpb&pSFInrWEXN}d{fHHoI| zKN@Wo9#(=uqtj3j`DB9!qJhVQikODk9iCst@B6IrrxaRznUsFBpEAx%SPGGGd3GHZ z_4dIgcr0?$Ck24^;duH2#gWSJihcq+aG`zZqZS_7@}z!`Gi5&@mbgOP1@QCNo1`NT zlBlL#^(uG;vBNT>2r4M75I{mbd>gheDGqc#Rn#^>3;#!b!tN9vn_S>u;uN!=-A+NW z{coesT~Bd~>kXaLhE9KSZ3el!6HW8n;hCIyYWtW9spf1AnMlFNuBF|u_P-?O_Dz>G zCcvJml8tbEO}$B%#N^YOu}x#)m*cfGTr0trx#kl4zIVZ9nBSsY`7;H=zqvMQ$O^ox z@FZ*y9n2Iy7pS4)Ls*3q9wCPf;a{Xr`xV=1p3zBzMK-SO3!W~MU{KcAO{1Ll`z^)- zx=!~nAs^W-A_22A0hdp>`ORPuxCeV6xD13~*D(G!o5tRX@zIg8^y)17bQAX7{>#q=ae$Am`_3q4Ma7D4+sz)>-wt`--jLG5vf~#c$5MhhsFN%tnlc1k_cB}|p2xG1ndk+x(*yw9u8R&a_dBQ0@w-FagqjVG1@fvJq;Ch;|F z!hN@e*m35K?4@{C4MUqkgDALgeXQg3(u;&oOP4~DsUcY1IvUFG>uL0|;0YK}_R25273p!Tnf&M&G} z1E4eIxZz{kFIEHR6USuG9F=4my-l}`Sv|*TB60E@Nx0Hm*Qh7q-exiZo!N7?*S1&{ z(?FQ2uzC)Q7?rr9^zvXy+rt{~(7raDU%EzRjy8ER`0_g03%KCba}%|-XzA1&+}6;)yNb`poDdmP{6TMs}T}B{@6fM+$Er{G~ z`F~1Plp7DMK!LU&jW9SU^U{uJ{<%EcxyB>i$zQ@YdV0?DOi?A|(hr-95|zz@MtbGL zY451ts$r@nz+%`9BnvR4o0oV)Hsj!`hzUq26%!A_=2v$}l&`Lwr70rA&EVmT8pszq zx6M_kGa?XN6bawQlb9`H0h@4AvBObh^cFN2_7;f4{ZABNDEu#-#FCEm3zerBRZhf*>3%<4TB|fSr4qvq@ZxawjU*;qm*YQv}Ad$bu*Qw-xgDMjFN&iWx}aZQ`pI~ zdAC^u(rJgfA=>fAP!*!y!+^%t-b;Hd{Ewf7I8FV-2ew(|CEo%1z?gY%pf9YcjyK3VeaCIszu`&IH7TKYU_3BqAhe{(XDXVWxmt+t7k(cti6l$f^PLQ+Q zY~#|(Iml*urI&GM^y5fxBgQN0fUoAQry`605802$4rLJWp7}pDW^R$@vK8K6$gj0> zG!Y)G#a1!_T}0LhGl}d<6Vut!NsWmPuXQu#wLWK>H-hffWR5dzg^lg_H0m}_ ztiyy8qcjzT(VC_zs<{7SXuA}t@@)}#at4``b$OT6-t^(gS)$yWoU-?xu~tHMl=Oa* z^~f--6{FlcTfn7s(De3+vF3V{@h`21QB-55-L&hU<;oO0Wk#ilThEd~dp0X~yDSZc zDhxRs}~^v3R2et^J{4vE#NV~~}8>A%_FMjnX%G=;6IiNAy-XfG(TYs1~_T>y=n zhU#!dZ4geIP;F9DPOn2WjPHtjm3K&`s$j{BAD&^4iWe=dgUt{}TR)5dFS}a9mX;fI zX9}I?>p^mas|=YuRgXsoV<`I+C0-lVPoj;Lb}_6#|D1Go2v?I}N6mQ9+iaS7oPEPB zn^L_~m2X!^aRZc=e-=Z0ElD?Wh)Pvg(hbS=g%A2AKWKWzX!u0JwQ-Dt2Yp;ysL<8; z5yH74@v$@I`DHAy3EM{?*3ki9ywnoAuEgCKx8GDQ^VmP0g1OTXd(T>KqgReUnxd~= zmR(SRT4fcTOm3gSS$R|j0)jgye0-?%SSOD@xhdNroClN3^56-G;ktl%at272-k|YI zMsH(W1as!WKb_}CAqe9vy{gWnB7go)^mL_sHA5PI`78!5f|}O5;$<>qy4~o>!t2qtuR%qD=(3@7p@v_-V8_fAPs3s${66p^^_WeAOikHuC zGAh#>iA1-kP|{9WtO~T6iK{0J|2fDNEh335&;Nz@V1Rz}J5or_v~XP9NkbCMXl!T3 zi%c2KJS8#x2})^kcQO-;lB`jK(-Z#CBn8V?PZG)fAoEdL?gYnJWj^7kSvG{m{Yaz^ z*S(|Wp{uPJ{WoDtJnIYio3xiJSY%s=w7@aGAB2v|Kj9TE14h1<91J)K{iFogS-8!z z4O|H}Q(8aM_zJ&Cmr_yTa?zgOB5e=A8Q3(4+ln%U7dv)m67P$&DG#eZ#<>_D;IhE| z_Ws(T14(IZoof?wAe+;FLqj_(I$~2#_M9#xH|)2=?bRuDrtkzd@TYn~N7gCHQl`-R zi!0d#32mejJzkE=3QXI+?kd~T5o}CXIYS)j6^VKS1X>c;3P{!+rIkz-HPXixO=BPZV1b4|TL*9wE72zky{N`bp>#rmt-n z+4h?M<``x$b%w`@R&4$?C6nY8xx@}Ny8%LN3BA8r4Amg*B9dtRBb3;^?y-uT8xI%V zGSChhitVul1<$^ZWv8az=;TtDo*sGl!#d=06DebXPQ^L{%3S*v{@Y&qy~@Kg;Tj0s zOB$#8IXU`zUkRdtKK{p|7n}q1>xlgfOuT1(jS0**fpXEQRA_Afp14slF!7>iD%~f>=j@zXBWiv%;Ln}Ur<2yC7jN)u* zAfZl6_HX42S@!0MV*EMpmKe5J;`NMsHJ0m_m%tM|$K;s?MikO)G|Mdgzmcc$Q_Xvj zq!Zrx)4Hflb}-j)q9QS$%{y~XV(p4Dz@*QLFPKH%gnN~) z;-9-smDGQZcaE-YI_jmQBSC0XcPba%S0Gc+jNa%~9Q`JpUudajMNro6;oy=g|NFND zPm`T_l;k4HVkp|t%9Rd{+1wv}=6TMpt56Y^mOyjgu^z>QJ3aMdvof4-q6VZYHh?+uOHX?NiCjqC9`Z#Nz!%tA{M3jHL`2ezekd-;UX0` z-ScXzJg-+}hqD1(jI>kCF2fN=?K%rX2&vp;r_OT9Ladekt{gpq>pBIYG{c0lw?1j^ zGQcYS6^$a;2HQ*^4(dkSB%IKQKkissb*CES64)YsFYE7Hj_z_K>EwnC#RsFWGB5=B@gBi@ zuB*|KoEJw@(=Agj)2K}bX0j=8XrqeS60+*_mU-TZ@oV3Nd@T76qfx-PauA`uk^aD6 zi9ttM z$^fV1ncEFcwQoK^V6a95`u{sj|5sHA%9&J@TnaJK(hHGBKq5-HrSrwy&(s+KENI1X`5$@y3ucz3|0(F+{43N!~Y9cDT8xLQV_^C zwM!)3pg08trYGf3taqr^lVMmEK5CRm1oT_zFH;0q7Q(^j)y+LqK#iUUj;4($PLRZ; zU7ljSZ1P0Bdcb{?I;AuzB!OJA-u``;GRcqm>qh?+ z$Gk)+##aN2{!c9YHYTsrz({%bO?LHtUWpa zI=;YZRu!V75@siqNPcfKvE{yu4m082UPN*}Y(9iBedO!Nf~*<5kdqFKFErL%JoFyo zB06!->6@K{@*6jen<(9Uu53q~yC>pj7)rd}F%QVh1$aFCw+NAh1);G3qQPtQyMBD1 zc+b9423zGA@sGov4tE_kQS-FD>$mb}6g_9l^;^kR6!tKUT?6)JsJgrjsh9!2i%4(N z4c7fFTQe0q^N65|H{!hW=^Ok{&&@83zayh@_)r@7rXKh%el%Oa*sxChUVEr#-B|Y6 z{VnZwo8@Nvv7mj?cSgWzKERILk|+5-GK{RO^%8Awykq?*`P;q2Q(jTa2g!NHa&^8j z#^0<)$$!;;PiI{PNVcD+iW#P1DD;_PW>mpyjAS6;c&Z|}ElnY;FN4*as z?Wa$i6*^CIxBHW(`TPjh^!IM8_r%(1`+Eye>ljvlb9NhB$a@m{~;w+ zmcIZh1_mUu)#u*#b^MuOh@@S*Dthi@p9!S4Framp{S}f2sT#gqymnB(zc5v@OfmhX zj6DKOsZwgLYmf$m0H?#ujeN2#t@2OS)mveyc+8u{@q|*#Y{sQGE{yN6JSZxmLRIzZ zLq_=HI?w7QOlXT7MG{!bS%I3qG@8MxZ-G@%hUZr)4U-aLeH166x&qdbLJ0mVrpTo+ zzaBUt%Igu*HP`!U4gC!2w7J0%yA9_g)0K~eram1$6AmsojO(p-5;-^rR)RCVKPOpU zbu^ZPWOD+!|7?Xp1umST7Kdq8XPJr85vg>axL!_@id_AO(bu46ji$~q+Br4~E^0@p z)%G!U6UI74?Vr69E27eA6rp$vaP^8D8;Qb8DJ~lt`k^1nTFJID7;y(0F$L%kafhsd zVwzHB6nAN6ZB2~;jV_vvHB!93F?EkmnGY&C51Hf%RtUpsHKVR?^vZ*?eNNXJ{Wzq# z7dR=_mv<$hOB!1Rd^>rR*3n>}#;X@;r@-aDSYo50u7-#63Dwm)mJ}2Gcma;=JEUwh zt1vkO=`pj0Clfy9ehD^4? zo0b$@AEm)dD_&(kC1l={g%T7+cL4_<(ZS=c%Z{CtPKuI6ZJFoQhNZ3C)Jk}O}1ffyW(jIF7^t5pN~ zx*+!X)4zCSrvL1XKphAqHiTiO>ve=(TmRFQ$`ZCvp-Q|OODX!4hC*zA;cap%E#3k! zoQ7$JBhHz60UJ*pFNCtTzCLoW^N?*7us}O)J!&8^EUI%{fvl{AG4Jtb{^Yi14jEWD zZPSo;4IlsME8|+Pfr)#wv!S#0(yi+Grg_R?1g{mX3o(tD{-w+A@1Q6PD$$u^-emIp zBK74 zo>&)~s9Cyu9Md38PdWo%fvebX1i?uQ)B3q4FPj(NzT-&5{w7s2Dg7kSnqh$b)7*mE zTBT1)237LioZsM8NxSnjj-p6&Df8eRU*YS?X|>uS(UU* zS8EmTh%0)j+~Qo4Fg0H+;0^JqXWhT#_vV$S(kZzd*5+&8j74ULtP|5gDFW@YYVh9p ztfjQTZ^Pey;#@_NKX4dobOEYDkYV<(+@vV>@!5i09UbODD;I(LZ;}{F5>RSeWdovo zS6wPA{-pfstB?UHI*#J3VJpd>{(RGJZ%Uq-xNWNw!BA*cE5C(qoTN~tsKv^_!nwDr zikgIr2%iqPSukcDA!*~teA=GPH|=2C0ko7fDwm|)PNx3A386VBQ-TM$IV+>vD7VhGn|2H?6YSh&kl729unW@3ouh*G_WFrxhjZNb!C05M zACOz|Cd{-McXvD;jykuz-sdX%^vkJ3c+m)PplpcIOp^tOKt42zQYtA@X`z^z1=u~T z;VV?DE2V*MNXRUF0XaKM{%9WxV{0eC^jDo~WZRbS&|&B%2Aa1i*Fv}U#XK*r(rXn>3bSOdN3e@DqSsW?32ufO8FPq?leF6ioEt5V1GZDkrL z@!s0PQ5XVIkt+FcJEYFBKOF;L`)~UVCt2B71H9$W8pGruuk*jOcKl`yV;UPMnJQM^ z(V-3LV`o^!x_<5YVx01eeRlv%tTdkYFZB0jC$tmNxtE~#c?*%`MW^W}^;1T+HC7U9fS|d#tftKvxOzG43hGvz z+*;jYf*ZTT-X&;^3U%vBya2`0b+iMZt!%8Gb)C<$WEes$&dPV!KXre4MxFerB z#`5HZLX$G`bFM!ZxT92!Ec(TO;G6K6A*8uR)mPwHVHVj8Vu2yTaW`T?Kx`YHJ>X%g z*+E!Kf%;ae3LGo6+*sl@%u^tZl6J9qcCW`}WJ8H*AU(rTIMcpV4v##3xIYg8vy9D5 z5vfr&)e-acFdkS zLHBIQ*2DSI|Q#GSiZ&R)by5C1Lj z=GgyAl>RwngFy%j_=Zn$|E$?{M`ajht?WiyxF!{HDIEpOvv70JEaaQVB=9IO^dRMa zk1)wdUY`3cNDskqCTpz9(5-Cs8#bpK5WrCmswWbg=lm@cPTs^r&U8LvRY3x^6K! zK_Rk!Oq@&Pcwp}6j^5O-WpQkO8QFEM2%z%HxklA5>MH2*=rEH7;9WB#Nu`c%8fFxsz;XoB?%TP|-$#B3_ zpOyPbPGM-6Xe@nTU+r@wh7|hk7Y`m;gE+RgZrx;hly5Y|Mc-#XtEK|OW?Z5DV~NEC z_iwfKy$h6OzC!#A#>c|wV{{aQ4|buo;4;HHpv;$yUEZw!ZNSZ+FFAw~0X3-i)HxRf zGABA5Mzg7fV8&v=+$Bnp=*?>Kw=fi+W9C?c8&vM<}$YQDlU?R$5vPAv4m&XMtg){0T!=JJZMHPz0#*j5x3m3Yb-*W`Y1qhuH ztow81pwX;vRHkpv;W{80)IkWW!#_v3c*n6D24Kg*LrPi`k0dVXT5d!~?n8hPa*%JXw zf;B_qR!&an)BWbd2f3M@aF+S=SZ)b=DfLI)PP+OSD&9{^h9z)&oe0^B^AQplW}%Wi z1h__%^P4+JG=^cepwrTsc7R6J49$j0GC!_%EO{VL!f_o#I{CZ3D=YEhXAkGGfFE&a z218@S=U}AXvwUto{SW#s;|e)HHDhSjuD-i*t_Wq#1%^Z!_i6bHxnO@=e}ESck+1NT zEXaZGsnbUuqC!PLQ{jn|kNc#uS4gQc5e}5YU>7PgH}Oh?o2XCIHA7J~R~gawTDyVy z+T3VAXK(jSNy1uajYE3)1i50X8NbfGg@ltYLK7XXD=j~seNN^{y2w8@P~$~~ZwKNk zZDD9mPZG!<*2~vyC-`+s_rduCZ!y=fuk9lJ1B?es4XQuW3rXDlM=Q*_-YR_(S4IYP?3M&4mIf1GM5QzYn4$>8 zaU#uomz#xS6r_Ki@IrwI2fwr%eG##^ecf;V5Vd@W#x&sMHI@GP^a=F??27O(PG^KX z8;wE*jvrE85!*a5pBH!kmXksM ztjlvRJj|+WKs3M@VpLJhSY~P|X=<1(Om@;T(x9P$Sie6V+fuPk48wq-RYzs!uZ}Zf z&VI1&8D!LW_~6M%^2wLz+1xKE)dvVITwp*}0 zJ=gHTOykd!k$3Z$O>1>dAS2lKaU0&Q;L1TuR^YwG9STB*_Q0wEx#F{6s!?V%-&9Ox zVrd{$0OrVqq<_M%Ki8FDaCb@4BFJL*LH?t-l#c2?3{6GR%Zr%L2dC)$W;=L(QeZ5L z77Y$SOrMF4Z4iR>WUljZStE zJ0EWOs<>h%y1rlCoLz0S-uM&NVHzDX6`4%^Ez~Ifg`N3#URZ(hAAW+93U54Y5?bcj z3R3e)nnO!M2{2_s?=7YPzt+5=H=iWtE82!G%y0j>GAy;2ZjA#5pyg$i=17=?#z7R# z6-rVk`Uw-Lu^;S3GLN2ceQ`8e8zMbK-w|cbWrJ%rZ?2?^^yefzx-pLtajgY>!yHgv zAyucTw~=6%Q(XO-Y@?sJ0aPAT;Sc5>ap?HX)G34`L9faZPma6q0)XW);sjM3CrcK)^)Yi4{5`KJ#!B zD^Gv!!Y~f+!#{bCkD-QhRd#+pmuwxxtqQ)X(H&1ynobfK97W#Ko&s0r4WAn9l~S;h zlKFgn^37HtE#a6LH|NRdgHlf-vaz;OWWBhBZvEkl5pSb_&@knoAgXEnBjD~!l8&cE z;;V%&kVv~UD{q)^&8@dJY|Q=Tt9Dl?T>IV|uRxbakqG#LMR`E(j`SQz`E&apU8nW$ zR&6#18Jn8(?ZKFqk))AG2IxqGHqEAH*@)w3S_td(pqhC2nP8vN%h;qN^Q-KQgC+ zLtmRAGr|bF?vDoiv}8|p7M-tO(F8@?tvA6!B^h@T^fr2OC<0tL*T_IO+6b{}d1b|B z%!bRpz$R(G8=v#*-b41G{r9XXkgwwkrSQmiq+?FyZ!p4I`Ld`{PGn}P$D+t((8}#mxoIgJj_(|mpv@< zZAr)BQ6qx1>YQl8uGt7v+Ko%Z__TJOBq>boz%~Aq&=0cl9cbtkpGp~FA4iiBhw1I8 zBr#d(O@Q202T8)cZKihS>y!g$~mlXE;=!7+ghr>nv z|6pkQ`{XiTbp=2SmkdD&@1W4#N>NGT0r3^T%iLz85rGFM6>4fWS^=_c3PLmPG(J{P@gyEU7ss zF(xD%7A1^garf&8*O8x$ZeA^a^d~XCIxEyp7mAQMLWI zdHweTe)3tgJNxIujZ&vcH}j(&iefa9lrvLy1gp?+7{eZ%JB33rR|?bODJh};$>f=- zy#xbo614@25<~tfpRHO45 z-KPSkc{FnO5z6oa&yerQqMIz~%65Wq9Z>n%lhK;W7yxIAc$6nqsg=K= z!6Agfd&+IDW>znrt#yna8OKGso}zbd(5#?Mna?s{1ZM?NoIgu7QF3Ti)0CQKF{wHI z2`x#@bPV#&Viv*t91b=Mr_5a(ITthY)^Ewf`_M5)W_F0jgOm4sE?nyzaH^=X%roH5 zS2{qCF7$pa*}%HuvB*}tUFOcuVfV}?U+r;{ zoGDZLS+P1vRV^QbzzXpT;m_syY*n9Fq=47rK9b@_0SW7VPnye@P|!a8rQa2(E+`KD*IZ4gomNhYN@f(# z2;K}TEe{6C?!pEui+MsJRs1JO*5K^OuTcpA{1t7sMS8MibFW zHtQ0n%x1S*K_2hFarGW1X1iK|O+>7Z8y|Kz8xElS5Q^Je|5&T^Y4*Tfn#H#Lhe$pZ z@gw;{Lpd#npXO13XbRGbu;E%q{-ANXIb4tM>Mxe8PrC1H`)v=(y#m>%vf)*8cmh{C zv^Q*0hxIaB*)ymDrO=TI=35eJjrzik5%;1`Kk@ELQo!V%T;#kbc!BNpeLh2p=44V- z2M7}f1c-L!o9k}2c77jeJ0B=mB)<7=4+no74(|D^wjhZpj&<{{|H5K_57z$vsH>Q2 zkHxIzf1ZA13yX`DqKa{8xe~PD#;v>d4AgYNB6_L#bYV2vT6=8xH~}iSNs^9v7l4rV z1t}ZlV^+CN3+-E)!q)GYzfkrTLx_`QH)%;%$fZdL?1MRO5ld_Bl(|VKJ*H(9Jtf&= z1sbLHxb#BMEsN%K`8bBvCKpKqWofsBqeec;yiEDy)PAM?Scy)-!eT_UZnk%E7{M<>k0gimW3&&~~V(%=R@1yfo{L*&y6W|hwg z*+x(V^2f`WS!WWD_^jaRK>8~vzFLXozf{k^4*t}eQ~ptdVzxbH1p{pKG63VUX8Wws zu^J75$X8(&(`bq%8ssS9sa*)X@R2Vq${w&nG)0K}5DJZS<=Z$axmF9j3ckYK6Nc}J zfzGAhLLJ zIPj(j=faU#(CDWybU|m`0Pg!KpSE9c1VqkFBht4{vw>qv)(MnC3iLU+U9w)=rSd1{ z{Yb6hLk$JO{cfXuWSApyY&1fSog4D6HOc%LdNt)L$j8ju82K?mJ`11B#W7n*?iks7 zCoc(>LDqlI?%!_xWuf;FOTwfR5aWzUzsZ#+1=a$&G8bAhn~NiNAoon57z<-p%<#f$ z!g=>iV=k;ojT1)xoJilLRG6euQii0+`2*>?=&(;Lrrh`ti8Q)5*4MAx_#XWu!ZW?* z@A(9t?s=Oo^t5fJ-QI?H+pZr$=QG@=e+s-$Q+K*=UqFppcOF?tHflheDLk@?q%}>A z>=0#FYU=Q6)OO!90NjPF;n{Id*yFg!L@USUfj*SFqQ{T>6r=NF&*_W~*Grz71z;oG1?Or1Di1 zd}-yk9INb6!tXby^KTQg_j^u2=No3}u!1n^L|?RUo4kAWmq74)tgv?eg`?GkfoTo2 z>_wwzSMY(6XI$ThDo(#oSSY?Pa>e>Q1qOfaebQB2>$Y2Y{|2H7{zDu<1V}F%VUT59 zUtDiUjxcFItRSj7%u|Y(e0M!>Vb-*WLz@XKeO->RPq5$fun``Dnw|pXdF3CJl6!II5`~@<5v~5m)HiSk*7nd&ZMRd~wr$(CZMRd~ zwr$(C-KlLGxAT7Yu655(cyf~L>?Aww!MpI?M3M7y8GZ`o1O6jn)MJzw;>4d^Vlxod zn)9W?{xuMX2UE=D?}PW`3X1Ymke`vTI+pX9zg_F!#4Ur|Pw&%b6K2FdH>r@$p4@Zi zr$)}*Kg3~6O4Sz5TH>-F=QYJwEw`Dv(;B#Mv3x6&F=nBwwSZ@-+(Z&mczr%LPjw^?tvZD zJR;*I@VW2(OrsFBT_6#cGDpv5(ysJatpa<-hjR7y()8f+IB?1~(2rz6*-5>zSwD?( zwuI>nisIv(!ix0snwhWET0B93a&1>+F7*^@Oa(yyWn3w=K)~zt@8xKm{+gcCMcQvt zpB>fd5YcB$o_pIX_dUXmz{f`vr!FG<_yB)VH3U5VDhhB+`5I!=3B9>^SCVZJ{+I;f zYqz-qnLi(fND`E3IN3a4`Lo?tH%D|o3Tqd&)G;|;w`=qMS}N1yIr?F%g%?_5v_cER zRIE6Ms1Pb)oez%HcyUwNr)QrMc%Yba8~GWoY)%(=UoS^r)ZbTqp12F-RlGx_K8MfS zU!yfORh4>M&p_TAP|aNrcNPDR{Qgg7#{>RI``^FKMOAUtemJK$ex#~DH=&0 z1S#R*)%GS?s5=Cg30T-lgLSGTnh|Awrffaf9{(HIy`tcZ3b-DNc7=0dts6=>Q!Foj zyj;pynXeF-oEM0cZTgc;iK3RtFngYOrM-bDL1iRPM$*Y=(hRLgQBLagR=ymwvw!1uWyZNDM( z_g(Y;_l@oKR@>ptFl4(sZ|w0RS&+O#GRYtqGtHp&b%lAp2a^p3-iX4aDI+)VCo>sd z9Oc~}m)uBZ8)*&9X`4$og?nvD;ZjB{{B7xEq5KfV29zUXOHkIE`5x(Yia80-?}b%1 z*^rBTJx@21gXVgVVe_P1weRUttAuvdul&)Rq}x+zf8gJo0&2<*wQ)mQO6h!#GT$^i z`UQyMd%>qzIUxo>h;yt20t4L9*ct;h-%Dd7P7>!c->09tgJ!=TPB@2eRAx@HC~5!w z!v6z$CmlZj+gD7TGC`X!8rDq{HePD1mr@YEJ1K;Zk&u8a8@vJJ)kzh=9AITVrXp89 zXcwagqPY=DLv0KfE>@z!jzH5jyPFQ4i0JIr!W`obE2W^e=`M{PiY3Z_Qk1F2;4I`I zJ4}HDOi0p>P+~a*IrGl&&PkGq>iZJgYowl?R=M5eZ9A;wZrQ%6x$gQNUg@$te}=7@ z`B|Up4G;)!ea<3qPv#3XE<2cOIAut~K{I<$Qym|hyxQx1E8}-qc80zrKg#7p(16vo zzoUBL7l*9D@RZAEN@-<^RjqDkihI}joEstg+w;mu$!n@Rmf8_l zd^O?Z_cxZL2|qmUS`i1#rk>ouRLsF3#eYg@ARAvgpc^+EfRd8ZZ7YYzB^v-S=Sj5% z>xZd_wWJL6;o*YwXj=rqoHEeX{b@J}{P(D+?BKnfHQ{aHkZ`KqcS}FAYWCjL;)p@c zE_Xx>f|(7=d& z#IRQGc_#t7u6^q0eaRm<;!ECXZK{iNSZ)aMgVHa&Y8I372;-@_R* zA0+{l)Tx|yyz%z_AIaY$RyGfg**8p#fw+e zj^E{vSDAGWi!tJEV{w71<2nq#D{gOec1B$eClSWk%1)pUGMy7jbtv-4uj(gqgJ&Nj zlbTR6*RywreBCu8M&Nm_v0J=HIj`4w8tPaCdm4bQ-V^)FL2Kgee-Jp&KVr$gF5urx zfdM3C1NvJnA_qJ~dRgNTfZt$kIU8m@T#g_Ha-5XsL8*rve@!U5AQigeMtm6oy-W$o zkVAq*sa`^@vYjc1B@=Mi!kCc-y(2`%l=1XPmbzdb+Q%uMR4OM*^TKpvtqnybat*6t>^Qn$j4`J3$(Mvb5oQeC69Kn0 zW!oOv;Gz(_co_Ik@!LC0aph6C_O{s5{i&dp`@;IX^{o7TIV1ZuJ3O9R&vN|;iV;5< zO70{5ffLG%(V{OSAuX*mWO&QKj_1!8#vJ@~Ul)?AO-1C3bqqgI1>0CXC8L_=jxGg` z8~jRCDmVw0G%w>K6MRf+Y+Zh=A%`_Q1@AU_hx!!5qlC##=AY=~o!=K3h|DdE$swjd zwLQfW`&G24x%R69F31!FNTEBk9EI88iWM%rB|=)AxH@ab#D=p+WUs+*$Sq*j)zJz| ztB;#BN6&e0S>=DA{QpXA23DWnc!TA9 zwRbfa{>;1>ID0ppzWEUGD)41d#v7$eD4>{GhrD0~xTzeb08E@g4(k23L+9*VEHX~g zh`y3;-=*4Ro$RoW#OqBSwz<%jOP<~%&`|SW2bz(FKo>hU_E5qwQV+=v5EozkbIi@M zykhq}Fcm=SvyTlnJ#^O9yW+L;g8K2?!}WUBgibdA`&KOohqD}imIbcGpc)6ga?Dty zt|cjh8=sjoD4?ApcV;BP2E7?pJQROgjw|!5kY{&I{FrIt9D&+yopj8I%0ug!8Xjr;uOn(6U5{02D-b3XpKnejJq|L5ZS=ucx1`M(CV#o}WR=;2~mXk)AI(FJ+ zlrd2B{@8c{T$msS7zk6&2D>dzd@C^HBQRzALgVXsB|Y#~`WRj0yt3+`2#jZ<>mOza z{VtuN_Xi{|ciTx$7}0v%2E?6^7FrEkC>D{T*uO{}`LY)qA~xPIs8*<;G~|v4rrUIo z>nDCRSVI>NWg?{D|huxs|~eN+_s z>`aK0%atfE>;YCt4>kq9B+ z@aL6SiFKIC47HnUGq?G~L3@cW>B?v{*f9|tWXS?#O1U>`U`O*mxJ9+tt*wIjQgfpl zSX}o}>x!`&YEM_qJUH{4of4?ZaNs;C5p{$wj?!9UEH7MZ5%7Cs(<8bQ%#@K_1OpbK zryj{~yQ-N(aCZ71_gwvcOYY#kIW#rD0RzdoL2X&k+;TnA#;k~JzMgf(A9Cspkv^-Q zytbMZYO|t z)sf(~hxoLh^xGzNQrZ7o4IUDXy0xZ!UftZ}>0Vj>CpV_$cxX&Z1loGdPoyL!{~8D8 z>k&mO?*qMf>A+VPDh-$K)ET=}7#T*vDifGPL%0Z=d`*8w(KcX7!6^0-eEvAp%((@d zpeUr`bWV01mx1>(-r;~Pu1=I`rg$vjLZz@dcrIM4BPUzzaDW&mAXX1NIH;(=nI{K% zAL6QLd*><9^>i99{0=Mnh>-Sb);<>#o>_f9_r%?t0rXPUa`kah(s|n)@T2P0*Vppb z^LirtcKvyQoAijSb=-`uu$nm_l#R`)6Pzh}@w>ti8IF}D|DOD@qtusXVZDg9cEjgnbY+-0U`XR=v z@*oC}pLK|N*$Uq?NAg`#LRYdz__MN-{2p9Qi;~1+?@M9h_EoQg$~R|~8B_d&FfrJ^ zOR@0XnM@FERmVNfT^>n%KX>aPr}&GeFZks?C@$YgBQF*~IB#DI*M%zU$AB!{?Jn3o z55rSAFOjT0-wYRqA06-4?<+HIm+z<5KP~qLQ19&m+)kVY)q-@4I~|klxu1lNLik@s zrzaG8n_S&oZ?~;!%=)4RsT`Bip44|qubCpR%2-5poL?|C*-igJQVRBjAJSPfDN5)tK8tZq$6 z0X_`dI_@m7TOsg|qAkJmD!g|PGS%IAthi}FO#<#}WSoq5lH(wj>v$25_`5*0u7c5+ zPZ3MhVIpLS{mhc=+H@>2FUVo>nZM4#W(s_q*zw+|_9NG(>ZY}!wR7+Wu9=MQ32tXd z_faz^FOp~EcOaP0^=+zV0yFg z3O$Z%A@5UV#i`(OT~rn}^l6nhE;d@C(;1JG3q^FcG0SODa6g=pAA0hrWzdvhB!`Uc zC!T3irk+E!S;t+L#^FaobJ2UqK@-6gi}f4g8&z3x->H4MDGr7rKOsN!lkAlI?Pk~> z&1dD8BbRHu?Eb!u*Ow@6m@j@irlsT7(Q4zPnh;EL!3Rho{S?-%%-y55^YOw1sk{@BVrwv=* zkD9L6ML6eF{UGoipHxDZl#ntI{7=DuM*km^)Z2S>WTO1jFF~$l$bcEdvV7#%m?)|2 z^(TYFleACsC(f(a`1?>$k8h6Mrtk_;FL4(>#6y$OkAh9Ftj}>h27=1OjQ?~qL5q=) z-%n3^Tp6d6Zo1X&*rbek>r^87!*9z&iSNyDn2p88$q`W-WtGWtq{f8DXM+tvJn#5` zRa|0OcLaamf4lg+qx-(_ydAwq`_3wE_*8qpw0!SwMC*PN`Zm4>x#k>9MWOUta2C5N zFn-DL;108opYfoB%UftzJ#(wnMQwkVV&Z%x#kg&D@Ls!z=+rGZpK$(SA`8veHNZCD zQ=en^eR=Ux*ZV`}W z1JZLt3isVh`myGD%Dca%tL=b>!|XNme*Jb}`n5~_Q0@7)@#BS;c<&$}5VTScDf zxj%ulG?wjsTj0kmF%V2scthW*$G(e_UpK72AI$%|cs$6A`&QPt=FDcNCw*Os>Y^R7 zaXjXPl9!0Nq${Y$OqI)XK6!(u-8f$SkL~$Z5GY^;VFT6%+pj^=vI83fW=Yq!L zgH>Q$c;+9~w#8pembD82pE5D7oi7}RRjQdEy{_MjmNQ=OeNB1WoAi89cEox3&?EWb z65BZr9}CnnV*MoKY;<9v(5%Jk0=BVR(#vY(1&vozd_%91? zS`Uhog?UzTfBmPblDCf&x#8{@92y|Ed5%lH0SJ^#%sn&aREJ~U%x%G?ASpWLP`x>> zt+OrO2{j31zK9?VnInUAdT8K#`1MPU+r8ZtB)%Vq3EH|uX9jvsJby*9&(w08HZqOu z)9Ci`dOY>1dVj7b=|;d2bYC2G@a#&rTzsrOxrDeZ=b8sc)7{qsQ9ci>H*mvca1YL4 z{qU8?9d*lp)qj?ax&H6!<)`1&)RgDbf2t4RQ9zb#-g^gVh74$17MfZw#XuukmdJn$ z^SWmpay~+NpzlyQv|RO`LN@Y+!bxY%UEt)3(OU z=k~RVXw{7LI>hU*Vib0CT5HfTx-@%sJ}AO|U~v5XYQbuM+MXxJqrf(vaSz&{!%Do|S+qi^cv17^2u zG$e>^=DMW#f5;^ zbJ%;&J+1B5Ti7%1cBif7wAltICG~8ssM?gjD5AYw8zhJw-tOY{ha+104`&|%`QQ3x zTtGVLBzN}HBB}2EitmRc?y9Bdza3?s52WssdClw2^FG25xbj}EBKl%q#n|!yHN@~L zC+%vt*gy>>j50G*CF(dl)=@<4^ou!{7f6IE|4|{6eR>H}yzzxqUYR~@dUR)DiED_$ zf!XStAcXU<;5gu*w)S9s4)oBRxLra*Pw{a695f}E2_K35gM68Mp56FP7GqG%?ZhRo zFTl5U8fF&*ogheYT{;T(cmu|;ScW#)dO@eja+<@YQ(bpkH=0F@8K%{~rZBy$vOX8l zlMZ&3bR0{{UX+w-?b|}i6`hB~ij5R6LC3L!>gw$d?=xlB&F!Au<@aVC-<40zmTWFY z(QP2>0X22=*~WnJDq?F1h5KKV-pi(VmAvew8{oh{6XVN(LT*NmNV@lXlD==nPik}B zxLcjaqCN-DIPIssZ;&R`vya$rTGk}hkD@TMg}~B9vrr@c2}7B%6oYoYb8M^jr_FZO zZuKD3RHf&`V4zXMgB!e+=fl&R=o_-9UdW_>y0@L$oMz6B^^h~eOoy%j(F!V&d}2qC zi-@dan!tm~?tIdFsix~KR8yWy3){J-hOM#h_U_a^%loIOJ@SycsYs^kK;(UcZ6cU@H^R}?Y2WaditQ<~U4FV+~mm2Z)_f`cXgMbt$!>JUTK}xW(^2j2GQy6kRCdG*Z2bomzDGa=H ze-c6Jozc%8V_`4LaLlcSXxveeX&Xfvgm*UlrCeNUf)9TljfBq*@*l8yD#;=0MaCPV zIOE9AgS|KV^&Fe;e9Lj)Wp(AGLZn45B`!fZn8yII>Xo5g+I6KzDrf{GEc} z-p$A-hIXG+TJLScWhS$*xn{nFNPS)e50eM%+65#RkKFT+pOIa&&=6ltoO$64&_yN< za}3*KpUv35hBQ%PX*>jo1{b2kW=^luh?uXFmZ|7&XsDa=%YEKg!JhjaN!1mVIu64J zZ?Js6X&4uK!ce?@M?NbvzPl^Q11TE0#PwpKD^lr#ELs6v^D%o8XIjmC2t~)yX$ZGL ztP)fBlD7EmdcV{}Q3Va^g`0=GO63*gQqOI3$}}VNqrZV_iYqrx+I~#U8FxZ9QOLR_ z)=5I;C(<;5lFxg9j);Axn)eGif0<@N#i#7&M}ZyIlv3md0Y@Ky(R?My-GnW9Q=dJbC{7D8m1(Dz=``3mIi-YI1s7 zi~qX_2D763o@V=U?)u>|!*^cfKURZ}7Ecw;Ax?5K6@a3xRf+??=By!;Oo})3+q{i$ zj!>>Jh&<5nKwbmK&ZrMtcE}m3pt}sK!ohw#=8}iWAcYyGFj>m?M+zOCK0T3U4a17c zR1l{!C+ctemNA!g87NJ1R9S>yXY8b0=eSyx80*N$tRwsM9lac!(MjzEM!<%j91wy> z<4O8lacvkN{d%`3riu~nO0C4fVC%}+s9Z6R_)y$+N#Q4SIo%(PAGLb6Hue!!pYdJX zuVrE}_FpgUOO!qBuc9!YBin7?6@Dm{RZInlHBsRr;$+kWg?F3_lO>s-vKH)Yu8#-a zqG5}Q6rJWLDZuNAV;FlHmcut|LR)E!{Vl zlSh8>Tr_7Dt4T}gdSYvCVmvnt5qBw6w}b$ENHNa^xZpp-*Ffpazf^jGGdD@N9C&eB zFS}nY!(N&Owx}X=ausj;HsG`{Jc{`NA|5hYt^FQJRtbH!$vcJ^{ebdD!@MGBG1S_a zaLXjde>kU?|ILhn_Z}@j>16!V^1SW(>-l|ZJ8h!7$XHPHJ9ip#8WEVE5bi9MG$wG> zOD{AEN$o@ax^yl72ERB=yeQH*0#d|quhSsKtjzMl|64JOxiM>U zG%0i|-NaqleY_Np!(XBQ+*@Rs8c#q_11+Hj61amxY-%c;Zw`B-5S9ojKsJt(fsTX_ z$jI*Mi|Vt6j^#EKzaw;Lm~=V1)?Y)RjQ-ad!VD~V5;r*Y>`kmcgoxBJQ7#zJU$N0B zb917#Vz-K$)(SI);%RxUTt1zFUpIeNHF?p*aI;Iqjkr%Tm+Hr(>kcmw3<*s0v$krO0`a{ zE)&y$7X1h;q*p1$PFug#DK>%vf`x?{&s35Q!mi=By#oiA$=N|&dG>QBev^^oW45HY zYFu<5h2@`peX;~iQxS&y1RZz$&R+~YJ7gFHkTK1}$7M@;=^+}8ed;|)jb~hM-N*PH zm;;?w>vJ2M;La^ulZC_|-xpo3nI>b(I9}7<9iIInMQceeO^}p+@Z#X`fJh($fKv4k zxM)@%`kid`XoiNEJajCu^?d=>eyDc6EPxwC2_T4}nO5Rte~1!Yo93sF!npr_Zry*{ zSDbMjFP6P`b2n6Eua%klcHKX9Ia6jr+U6Ydl!OOsb;*mlaTNLuHI2n}w+00Sm&v#% zGBBvOKxUqXNoaCw}5Za^S>j2UZAq-+BUvz~(>(G74r!}Z=}uniN2 zS!+K}PF#-J_F?xnN1Ip)oQ%xEF?DZ`73L-`bt)=?VMcUhPjGE4wUR>ANraJddI%I7 z)+Q1ZN~k?J5wmW<(K6O;HOjuky{+CB9UaZWLBBFL$3H2=+2IMM9TgodiJ_|P{5YIy zsAuAgcoJ#M43ywbPD=u^*7F%;wCvYF+7omj?NM-j-?UYM%qz-kCK<_?SOXz@=AT&~ zufwkq?Ct6h8Vet16yCQiEH3c9f0>!1>L3*46elpMQDY8t5^B(4AR~*Ar@fjzo+6H? znk}XhV8&;lB`aNH6dFf}jvJ@Irbm+^tt&t&R3$pLJkGrqj*M7olyr&x0JAE2PVy+L z0%6QhRa)@TT2Q!!NW6s?bRg8OPiV|uNN$TIt(K-|U=ofTRSvt*Jvofh2p~8Wl1aSa z&{kMcvz5QH-Szx*&E-DRG6%9(k;3ZJr`dC(?hyKXa^aq@@8}5GimmVp6#Kic!k=N= zewr~QfG8ZpG1xQel}b78)XBatj*fXXO1T5f0OQzPd-lwvUMWcJwBDh3X}$RM5J+^A z4cd(ei}G-d;A4Wa@(SDBS<|@jq=7>cu;R5Xvm0six~L1Vncf?tGRCA^@LQNx-2q7d zDwQ1Oatw%QMyaq`A_V#8#wSdCYPE~WoHKvJ!tGe^#BRG_I|*`{MtY8T7fbZ1X&P?~ z(S$iQnkc?HWE351ag)E;cpu4?vf!%@0^`%go)-xWu5FubruVhES-ouz#7O(`c=&2b0VVFi{a+10zYmaN*a{)`4}#8 zHClg}`p|muEdXw3|C@rT=5RhC!k?4W?E4>iBo0r<-j<0}a zNtgTYe)d?k@7?1wh5)m-(8j;~Vm?)6FlkbV&}zB?#+I>Y&lyB$LFbzg#@?Lt1XV`k z%eSEEHNdYDOK@f?2fJQr=55D)x&=i=M||eOemoDBz#!hfaKUuC^ElUXe$KvZ&zzO_ z5Gt*h_a-7>`%bQF#O7=1yy97wktwKS*z)uCx&kTAv6;LH6zsfrD~zVjE4JoXGJYNC z*)C#GbxSIJ zB0@OOvZ^jHMDyib1^eVa(cs3}Dmq+LvRG&zONPw`eZ7t&*ot94Dq`RIKzum3l!mBY zC>SHO1c}_tQEgsXl=am2W4CSJ_c`0M$0h2B^>#glOS1a!Pju-joEnHIqju{TXbz#5 zt;k__jwtU8jn^=j3RkXsMXW|;POv#v+SU62pUg=tt?O8`50FIJi8}htndg=`RX5m| zD)XJQ!WCBWNhPh`BJPjd|7i6#MRAZT%#Yhj*su$q>`vKeJv0TjqQgsxvQ<8lILeOq z8T)HypC!&la!mzo2dG zU?1x^P?55g`x`Ctr3t|NnJX2&FeqX11<96Dv_{d^g-}$6%MzP2B3KZt3`u;n;L)$d zm1MjVD;raN2>kmtY?`1f#Mxw>)|)%@_eN=;%P8@+Oso=jR+a+o6wvpQrHZ@zy3G^X z7eaDCiRwrlr>>dPiUyDZo&bgCHvMo;yT9jr6!%twrwl@==>l6FyDcNPb!6U$)}=!# zujE7Yw+RF?Iz?A-{^sU<7BGIFX7JiQ>lR1!;`$sd9EOF6a5&nCXN0hbi77BqLMKX? zYshn)s;CfnSO|s=z#DPfH%S$7;Y9o`fp-N!DL|grxlm&|qN+hFCZ&5&DV)@NvL3>f zx^hGEhUmNLNVRm&;kQOnO_u-6BRU5&Z;WmuG1E+`LEGQQ;~)PmqNb8&|JRSL1`7YQO+agfJi9`K*pw$A6mG5Ffm_!w z_1@}R+PPj6TZmSOKx{P#`{zUdFP`Oo91o5ym~OexGM}EbCfXZ08m{ZT<$w1lztz0# zX;o<8FJ?`a=g{Dwq#YzeO)0Fz7u>G9z9KjnJmpAt;8!WC?>9akzpeXN9Cs<5|E?}q zcexuPaWR*IqA4}8hb5P?t2&x4OZz|}dNzm-4=o2jWf)Q!!=N>ShZW+2kJ{&hBH(a% zp!?jzborjxZhNopsr{Zr?s+tqO)1glw#nw|kkr)7Kx*TxwX7vhYN|O$1;8`Q48^DI z6yW6KX(dYqj7##YWH@`MB(?&Vs&Xu}_Jpl*)85!TovzNeOlFt~t&t!<%5k=UKcYRK znKX+C5H-?1gnE4WquZ)pRWl9kK_CWKL z>MHExWaOQWB)>R_W=2mG&c-P1L6`^eX2TUSTfXGl~F4|*MP`&+v@pVE(DqAT^AA+~G zETQEXi+p2lZZ7V>91@MFVRyH9+LF`y*&I+UBRWDHLCUpjk4w1ku+D~2opHie^FVLA zT2Zo9v=Dq^~Xz)PD zsp?kyGo|iZF(+>z4IuBkzov}$!Tt+GiOluvQ7ymJz7W?eTO3bW)RG$u(r*<^5rO_^ z4!Npa1_Pt~J2YwvE!Q9=R8-(5n#`? zT_L|Ja4I0!{Vi`)rEM@9v10|}s7Ly}XA0(W#lkffzICbA>c%MA$}bdIlw|=XQ_B!1 zIT7{Wk48%jepU8b9d`1F&$c(3OL_M!S0^VYd`0oBq!2_!Nj z$7^45m^;s&ouUqeAa6EJ|9z!<7q_0H)I*}4u0-MI@EBP3ujt{-4~}EFKRx=-tmWA4 zTGigQN#;e|ckF31#g&y$`Msa|Vt|FeRLZ7Ao6KaL?g&(vS-C8rEQ~LV^MWr|xUc{j zk(79u(Z^jrNkH`XgJ06E$h5Ezy-tyb3kS<9D(rEz=GZL|WbuB&k;_o%C zs3Y1FD=2D6(~TE}JN1f~bWh!8C*;!*8@Isot^d>y#wpc2ox(NVGk3DQ-_F-<`pPpi zyCpnVWzXEtt9M5sGgouNM|t^5NN9w~bg{WT7=f7#c*D@IiocIghz%I9B7!LzR3+2> zhmsR=db_qDA^K>MfBpLNOI(Ow>D6EcyUF>%$dMcDECt35gA9jY2O5uVCvtVH27y2A zsG(6qZ<(Xh?8znZ1tiqumvd74pL{^6zv?~U^;NwCBp+M3j{tPeyvaNfiH;4l_(v1* z9ARrYa)lLUJRjDTz zZH{2t8UJdWZQrRdUmj>6>Jj61g5}dkid?KGBAUh|zkUZIH3)S;Ffc)yrMgLdT^8FO zUk-EWsC={WmMy8C7XrVOyhFQvFbRg13(!|Zwv?meK!U<`)R1vk#QOpD?g5V}U|Ewx zCCG?-{A}Zx{6v}XTUC0^EjbCYGV79vN6^cR)=VGw-3JTQiX z0rX9=z~fv*zRu;mKnv4@a|t)RTA)!@K_W}DNdc#1T)#6jwxTaHjx5RC#Ief|o*Xt< zzqd2A8_zz*MOAT*`N12)eWB>+g4j_UZEvH5Ew_}+m&k4J8R0QApAUE0p8EmYoeW&A zCcy!NgjR*YBy<3gCn4Kv){Jd?YXOH0Q39NjPNFG75($f;4|XKiHm}dT%26l6D&b}6 zzzRb_X#u=06VSMwe$7Npb83R-doeBTn;{9|NhT6scLFzlKW!yYRIh-Y3@{V5gnWA% zJYyqP@w010E(QQk;gw?}i@r{=H2jkgS;G;JjA!oU@TK zdH5MUXSV%kvpIrT`%mce;|;G)ovBW1{6e%hEOTE`O5aCC6lfTzkT0by1C>QDHnXrXUqYheI3a>Z4o@B9|tbag&v6ky! zX3?jo;eOB)(D^HAZv>st;6@VV=xyr~2N6j05($8Y)1L1M+)n8Rh-S0V=-?rZ-$1O~ zw7Yz#+l^VAhe)sy76DAuHsRIot2r8dVBskWsx+8iDc>n~P7SY>v!fogONs|medy~5 zn9|S?dIK#V`Vh?l2BI>;9!+;ZkBsHBvv)~K4q$?RHYDh(?IIgTJIyjz7rf{vr&h$@ zo7V;DHkeZYxY-|-tFrBx8I$Fi@k$|YF^;?E?a!B_rOYG6xSy<sMA6pC&J4)x`de2&LO7&$oDRW|BnBaK=zJ znLaSderN87pwP~shm*`~x2@<+WE50u90^zU??Mbu*O2Q=U3ROrw&7IhYK;o`8!%lh z2)!cZ*?J|uxi$dUK!YAUNr}edD_9sOK%_xDugur&WGSB` zIj;9vId7F!$2?Bk?iyA$8<-Y-Hrh?t_1omW`r+_2134ycAqOLi$ z%8}cy6Wx{T-M)94s#QY*+`?1^8&RX&iWcXYkJ^9FXU7~4MO)el2Y@Lv(uyvl-_M3R zca!feNvynikETg?jI)3M({_Yr91yZb=J`!#*ESTzQJUjq+5gZYt#1FlrC<`3z{8Fp zT+eB4#loCD`F`7s`_pBFey%+-v4}&fhCI32(n6w85-Q3~5Z8shN}S`NYfY z0vDj7xU)0xC6gf9oz-b&%{nK$dCCx$3RynsPyxz}8k=R^IJz5gsmg+e6vDW19kaRO zFX@8gcEC7ou}GJmT*PuNpmCCE&l_=V5861@5(Ah*hCrF|@RLq_1dJk) zOS;-pN<|!h7YakPRI3c^i!cp(@uPx0OS!A<&mwPELW)NydKj2P~sw;sNh;ewWxCzg;;4zj!XKg=bGoEdH`M?`829B?@K7D+Xasqdt|h9_9&G-$#1-x)-L8a^rx5#UXSrLca{*e z$pg%|KWpgB6!gWpTpwK|?a*W3kW!4GnS7I+bJh+~lDw3D`mEWsyR$#yN_JYRw$t9) zYFH~JtHK5&!eUoOS&=@~@7a>PC<-nhZK@Vo42)okMtkdGA;m7W=!9FIElxRS!3?`> z@V9(W>hp60QqP%KCkeXuR}loqS1+|0KHpF|t_KY`K6)7}EwFQPqwEX`1F&%T$yhRF zmWjB@9%e!~a^s5x0I2J{fSehDR;VC$FRx`Zn07E?+U|YjvQ^Q zM&?6{!oaWraaNR#+P$kg07QLiP$?Mi_5`b&6Toz=4iN`A(?VrAv@XlB(P1jBH3vMU zx<{!=vgnqoDQ(OxK0*GZ{YT6d8U%Qr-&rAf-I0brVA*<@Z}~`)&G|mI-pjB+QF>`j zr{<^IFgJ%#@So+7ghD}!Lu9jjp2Ie5IZxJqXvg}0`PyT1znZ%}k+^K7Jeu!Ium=%O zY-a$CVR(Du0)wq#=a;IPy=x!RWL4sMp3Aa^SAV;)5JiH@vI2X!j&+MK_-zn(t4c%L zExVP@0LKytDFHtqa3E#W?eDlSOBE6X?cuoWIzjf=xo3 zRJL49Kn4cRQ(@tW;J7*NlGNabi`@dK_UBC!?+?qX&QiaZu9@~%)vwL_n6EW394^V9 zYk`ewwRZ?igTUGfzr$7$;+X@Yo&lO*h;!D>QCyM>mBJaeSq~`7XCcG<53;KSJ9{)F z<{=m0+zXhODZ=8bpFsx`96Jf7e6H4l(Pf}R*Fiiy$rY)SY$WnST;5=c zJ-{_8rG_d#;XUI+1S>AxDD@3=8Cs3;YL(U9%+iYhjfW z5=P6;;!wLusAkZMGdN#)Wi4WHrN4;lf50%@@Z#gDc{pa%w2NcjqavUzKeJ7_4o!Q` z_EB}cuLY0Icc?Mkz{M$`hmcPcF=cS0;Bx6Fy<#2kpzA0un6OY*CMv_LMq=G};}RRn z7Z=(4uY`r~Z;~x8jTx0whoUN0RSv=4ycN{^)74OKm!6goEfdSTm8DGT zavwhXw5GslaUzZrG*KarpsUM#@FSIsunsW`vb~*2FzPX?{+dg*Uh|r;FlOFhbjQ)z zk|O45BP`42#XsiBkD^8RD16U9XxW%T^*0@f>KiJB>bMGiCN9Trb-+>6n0E-f>fcg9FEa+u4ZU^ci+xaWZ8nB$-n6P-M4UFH);#bq_<@m&oCjwwfFqfDq75yfuZDn4Ix(e}PK zi6#T-hHSFXMon2Eme7U@zN1@EhT}0H{@fW_qi%YPtP9IKIAZLHy!P(5!VI}?2$bb^ z_*1LKuK1C1`%$J%qGnl`ruZ7Kde2L5(*-8^V@zYq!B{EJNtqNP6y z4C=2)R{L3Pc!YBL1sn@jZFPC9M#!bHlSh|H8bFJprDPK@^z^1O)C5>BRZa9tivZ>E zLUME-`eY&Ym+@A-{9y5tUm7Ki*+>36&p({1lGD76&=c^ZxbpKuq}cjNmUTwmj2&&c zSeDuIgJP57RUsLN>_@im3sN?oTmn^l4FQu62{IiCjL9f_$;kwfl=qA-VS&W>eG$B3 zad|QsGAm6{X>ulW=St3dp472lGJ(^>4d~_QZ|-ka8k)*SPTST~Uaw11+OI7jxU3?5 z`q^5!Lpgkqg;j%+^rZwv^%1!=%R_KP?QwsbaY$i@Lc0Vj77Hf-w&ZujBnRNOP)`vp z?}tCYzVlJNc8kt%VuB4hdO~~a;*tDmna`6@jj4>4G)7PqJEI=8R7cLj$Al&z_kGsW zB>I|cFWM`d+n|Qe54Z(q^&0nW6n_3LNe!wMP2d zMx>WbU?KR$Bqn|jk%)I@;%^`RS#S@wWWs`+;9rl|v$ru#u414rD$Rd%K1R~UAdp0# z&z)Jnz}W+nY=$8_IxIXz5IUX}a=_sqfK9&dFR}B|5SaE9Q`h<88OJaZmua_6QB_D^ zKXec`0K%m6b1xvBVlxYBd7e(kn% z;J%Lbo5_j}A&L+8v{m$-5h}8+48L6jA3=~$2TgKgO)0dP@6TYZ4D!6Dlugr;7Y$EU zD*U>`FY$EV;92pN0d|97dnU$9jUb{#;%Pzx8Lh_+q84q`L6fmWSnpp3YpYvbcn}!| zVGCk7pk5|?(M!cp5r3{Z4TTxEtu)Ke>`p~SQ7x^lwUc2{8F)h+R>KTQYy$bicp!eHQOtEQ@#?4Vzjog-3LLwINJ(gHP)F=UE^~1Mx)T;&X}_$ ziUxGI_-JjGKa5(*#*=b8qQ?G_{j5UZE4}U*#r87&X1qcIu8e|0*HjSrMZy60y;P(u zqov=Cniwy%OJnLlrPzgL*#+v12{JBnP@qxkYHk-~PE7N`yT{>)QkQ4zeZa}@CE3#U z<;m9VwrS+r_k;=org2qGX^^yAX=iX)MM)t}uUTS`Zst_JdQ|Zpn6)820}M$$+*Syh z@;BGi~NvgDb92Ta#YQ_V!0l{YtS|=+Snh3Ac!n(Z%^WL;e zT_`zeGXQ2fE;QnaWSpP7^|sljGn%L%k)if-xb8P}S$*Y*5TseF4ZaD5Cp^081i7e% zLiPMSTE>od&F_r&x>E~<5|P=hBP9D#a+Wq|${Ia-BY24y2ifIM4 zb18K+5_GaP1Q-6d0O9m;abl^-l6h6q1nN{LAv)eqmffD$SJx#_gRD3{^Q<2Mv~Ke;S?mqc z1$G3-@h~uyA=pTcbh{@so|*P(`|%en*k*JjkHpmhCdJDxu8vfde)1dkXQbr&;oc%P z(h8U-?R1CdX=LOx`G|;$fv>8c(yPAtLZDGOy@I~A&`P<7Gp*68!c*}L zCj8A4vJDVu%@YoiW9QFWrON@PAU+{`>4QWw zEL}fl3kdzs9pYlg01b*mWU||jbI*V3zq0++Th0^v743lzPS3OA8Frk~o4k)Tch-~E z{CoIV&@C}4bO_Z(G;UFH=BM|4RziK5^k?RPlb;R-X(+zF2qps9qk6iH~70QN- zH|s~BNGRt*hcyD8Qj>|eXieS%wh@tl)P;-VB9a&@>l`^1fzqOYwbgKl@O9|1L1IKl z91^+e;KFCq5D|8^_J& z?1gFUnEY-54s6~KjF3Y14h#qX!|51|5QfnAg?t#zt?UL{2!LCfxV7Ji?&S~ z+qP}9u^Zb-W800*#pibzVEGhwO47 z0jExO_dw|p&f+TPebi{lQ-dRyhUsgl|6)QSf&&8qb3z;aDWI!$!yjr&mkBqxA+_BjDNHr4 zOo?F`_BK(+wG5L=@&@9rm?Ngpu$czSz!DsA;a3R*jwqMg=!Q|Y=3f@nnD>R0Fe>ix zMP$*SDE}5vNr&^r%Y#4pRK1u-!Q8Z7~6Y)ou$Q zuwJ%88T*+SrC~dX=5nR3OS~7_)T0Su4gJgtP);oqqP&ieJ@H_GSQ$F{CDBn*RkYD7 zEr+gL?FMu}K`39#p-pFQC_oY;^rWZrXv59>mfy{fUKf1prENN4@DD;XDTqD~2+_Hf zogkWxr=UCj99PY3p*^-*MMGC1r7}eKbttgBi0WcFEy%9$fDtF$(7F#tNm9?>YHhka zyCB!q(p$xL_cNOE+n~MP(eHE?lk(*LR-HUSI=O|f{g*bH2z5Unjy!jIVc^a>t22yl zNg0l_64jxiTliaJi}f=|zGi`nOA?7LrLg9oXCo=kZ$%S|{LviSkFE$L$^*)~5{Kg4 zb|L+116|~yeROc`k;Yq7TAN#Nk(U zoS}l0u;5D=56gl+)mkW$=GhJsXI;Buy@#G^t=1^bH=zgWz0}7HYXAH>qE>1~+-y=T zKicg26WmCy&Jt}HeVBNPWxl4G&@8$(yJT!P3H=tj=IiYc%82}6$}!O?p6$|P+&KN4 z3W+mxma9Rfq@=jR!Hh~M$Oe;vE3>wuH52=>wfb=<=hpMcSZUe_q4zPTZL0BSZi)bv zkt1wqR#p!+jyCOQg%`SeW-7c#Dqyb^mcs^=*(#(^OhO|z2^}xl zbeLHLY2FL}403Px>hpgbW8HVgrmGQyCGF)c?;d-|5EsKf<#)<5*gO{9C^|ly`Z1-j z-+W~)T;t2ECm#{d3_a5U5-E`S7c}85Ga+7HH9-fu>Mqqe_-f&-K68jRyO!e=k96hO zQ9pRJ?>{LUAv?a;KBx9K&2C~&@Uwd{D~nloHF3zh}aobCE5QbE9$4Ynpr zpF!Nynf4)sq?NK7NstqtBOxq>ic&;L&9eQWKfN-Nl0dYXQ+R!UR)39t+<1O=Mt0vc z6IAB#kXk=}G_PwDW=T-wpk}W8VQ9ry>SznKl4cEYgp5IgQbR7^bgu@AU42WVi1LS?r;O#V@22UYU=_N2J*wHt;p%FG&|>#L zFUvE(Hl(dqp{j3+0EzN8V3U8_D$f_RMF%kjMd9>e0888PPzs(igs3ia%EYf}xYtWW zX}7{!QFKiII;lSW+sCP>{K}(9vsypi1-VXMK$HeT>oYayYuaX4*Qv7_$+0(TnR3Lg z)V%)d7s`*Mg%c|>@~;JE)?w686>Lp=`OVb3B0{B1{k!n;rv~`HD{~BXbc>H2ORIQz zmOSEx7y==6-9>>2tF_-MIx^g4M!m-Sr&TzWlNl8f<0@YT`}5s-B&~IW0zDN@FDTBM zKgPJfuDTAXR0;+M|0)l2y!#aNBbh+lmEOg>*<-b4=4oz>j%g{-`VE$NH&Yefh80c) zDW88eMK`Q*Gfc3;?gr~;|2L?0EkV!$MtCNlG{G4~oYrggy7djM;G!0v*qQ zKI-uk#v_vPTf7q~^D-6>%xmOcR(G>#L`7P&|mYCqBLt+TmD_J_{^QI6GJ*W}_H~z|LIHCr5g2k_0g8 z6zfQuKf4S%NSj`VKA*IpN?PgUg zd#&$VO*8NdY~C49xZ?dbYCXD+k}4o_$b_;Z34U}5zWs^FCSyPVGe5?VLFMgaNYVN4 z^zZ+VrTX-S`t%MYeChuu;U50XX?3~Q&gc(tbxR@B@vB;*ly6Q{9<@ML)3=hZ5~BV* z`8IhOCYY_Dy9k?AeRRQ{qzBwG$!MC?!R(Y~P}@8{5=kS~2`5cc2jL`k^5^$FAu-Gh4Bg0S=sU>IjY*a0$>6CkWM4_Me1ZSAljJAPqMawbviOj|5C(h-2*uLxSLW~PtnACKPduXx8^VcftJE(5nQry z(>;oTZcZxEXq70@6(h7dW)#BK<%7EvNEs5Xgg69IeU;cyjI^ctu3zhuYHS~Wu#>qU zFF#x7s5dQS7wgGa!m zxVXY_m*?~?ImHa@6LtB?8t>-cec5%`x<7Kh5mv=NA*3LO+v8w5IJD8_t>#ElpM_e{ z7>=;jH6LYO_gmws=7r!;<*b@@6I4s$oNPV$%>7a(HRPM@xkvPS+O6epx{P^J3HvKuB@4?mPJpnvvW$cgk@HamF#Sp4*%EL!0 z#?(??jivCq@-Dg)qBPJEn{qzClaH7{%Do99$0*EQzPFtIfHJeOg&Q~7NQJm!xXn-= z7T873%*Dxxdu0Lb-)#o&W}6Z*hsS3|6*O+F?Z@dkyA9mh=tMuw(kQ0<{-B>39#+1* zqU+rRhqlW zE;T|se9yPNd@B~Zf9ipe5$@4C)VYoY35{2rI<2|^g-Nsy|Mo3;js-@ui4p;lTOE#0 zlEG}vu&)cgw{-({vnX7e&lkEvo7drI`B?euBpsGx_P3YBBy@|IZ?r^p1y=hXN&5$;>b_`mks> z;@%=_uzvfDC<2Eu?64g+<^2lmFuG|1j7Y^9CZ?8h4U29tw+(ufz6f1|W_>C(-|yU` z_8$-OLCtIS7r8^U;NccOil+aJlj{8zsjz3~^xnMC!cm8Op)2LmBGjh}VmAgVMQIyX zY8HUJ*D?QQyZeYU!*Us`8DcvHh$eyey;;TW=@}IT?H;xtI4Tjf4p*H>0}_VNPv}2l z@%;InaQt@7^c$(f0=jBtzsgYQ?s#*kIIm*&&1223#^5VLN7AQZ@Um&}yMnspp~nc+ zzy+||FI_9#tpVppN5!ab?8>Pfhm!SA;D}b)H>6wA!h34u^w3MT0W{nZt9+-6aJSMI z4#bsea^!OLOqB}6OJA^2uRVPdCCM5X4M`ltB08-5MJv4d%l4&(9KXz2JR?)HP3rR* zeM49Jd};>ubz`6Qjn@DIEc#nxoyJ@qDefJv-PYUS`j*F|*ai3FS4Q$k&d)NUrLUJ6a^$k7Sl2Rc|mCJ8F%N&o?mT2}u_;`kA%G<#$|3>^~y!3;8NE+dTyuEDNYM9zScXA9yGqFokV8m2w z6=aCjVkm(S&)gMFV+;R+NY)?6weo95{?oV%15PJKWAtG#BqPtNs^<`)*~8W_neWD7sMdjb+;Za+iM zP)^A1Q#J0y$Kb8zFL#8+HuawDT;*t&T4I z{-wi$zuokSJ>#!~eN6S{ zg{Yt!CEkB=hw-n|-b2cQer9bc4}s~*?2{kide>~wd``VwKcBVkQ3Tf-bD}II6=n+d z*ruR~mV8cg&eWl+gu?t0I(awdGp5JTN1jr4CaOylNhwGn=LCP>t|o4~7h4x|;g#pj zYHa_0CgsdDQ^Bqt*#KTT=;1h)1F5BwicRaxCp|AX*myya zceuog5hk()B`GA1q3j+4p}`NTm{pSa4bD$hGt(D(kSpwPqmdR+WG z!%#Hu4BGPv{$XJzA*G!yugi}t)Rt}68CAeZE8SH@$)DGW-72}Y^-b0iu%kE*)wp;X zf&k8ExE%gf|8kILMz0EIB&P6}br_>!ztA{_Qrd>})JNe{d_uF@JrWdl>pAMs=`hBK z+Se~MnJDj}QADMQVTzZBFfHMqa}%UKpyP1Ni9a%L2;2R=hb2ha~B*jZ?;tx4Be7duXPq zJPJE;w_Tl%*EPyVN|NrDW1q#mIKv7ZFNcpqnr>lJVzCGVSJBoWG3mw&hrnomC>OZ{ zUg~x4%51qGSAo2xWeTnLcM^iZIWNCQZyP;MzAGtd9;V$G`Myc}s2_P&+oqpYBS!Fy z+2e%2niA(Tzd?;cMKDaAMRQ8bOxJ#g$qdRkv*vi`q>*$0Xq}u{Rt;Tevm0pom=5Pf z00(@?PjFHv%^sE#^IK^53y?xj{iRi4tdJth>74`@Z+oY;8yQv9QmqX+s_+@^BdIUE zI3Z=};|!Vx%76db0}fNOKs)(Yp(b`(QEfx%qnO}YDe1hQ>p2O4ZViL>%Eteq2$3j9 ztTSDReBPJB>LmsHj=gpJZZq%-p0B%EUHtWwhJTJ-e4ft;e5a>Szj`>bejF`^RrUjZ zQYO8vWLnEZi!<1$rb)^+^(k1C+u+z#E`&(7vn?Q`JFBH*s%YSdyOviZgC`ti+Z5F_ z`6zP>ZSjzpt8!_nbzB@9ATd8LiHe$vkAdT=!3|*+BA#^z(A9=p=PU-vt;f(a9jUHX z+tSj&oGDwMwOx!tIQ@hJ)ngZs=8&{);9A7-w;!Egbp5Hm&eDH+>9E!6$ou@hd~54* zIV_lz9IvP6(`c%K?d6a_vnbh;n!6(4g6Izx~5oHnmYLnb=5$EK=-^$O_7mlcKA2UJt6 zYLrG)-&jJN$=2OlDc;9_&;k%bSgQ6!@(Jr*!W$JU6VjbGn`jT*qi8i9V+YWJA&|`0 zX@<4Ru*&wpA2Y@S8VXe>7-gdbDjc=wZ!I3cta(~;PpI#A^PO*KNbj!|$y0ArXkt%9 zbnr1c@a?|at#-CE{s0u*HKKTW z@-Q9|Mynsv2;=^Mfc{2jW0L5_wDM(cOy34QuWQ$9q$J}s7BC3DyYRSK9KGY&`-2z; z@nWP2iPaKrGU8TZ?6m6?2-f{0A0Sq8hM9Ahl)PPT

c;->vwF={ zM-{`Y9?iuaLpoCyB(Gd+BCf9WW8Ap8yFS-vNw;H4{ z{XgzDGW3CS+MEK<-N5M?5baN6SoB?;P};nMZQ2=O4WKF)=Wm}>Aj#i;k^S=?u2gj* z+dNy%m^{sezx3?vNLaciuZkQf8ZGtADQG7yF;C#T>00pXS|dIJB{-2wx+*JEg=sN# z{Ke#CSmPZkLd@}yn`K(yt7{`8hcmied|d6&F?UuAH`G|U9u@INPLC6=zG1O%IM#%I z$axhUqs>I{kD~>U?x;BPH&qowVS;xG_L%w96j%+iKOP1c4`1e%Y z$hgUv_Rufm5yQp%fqs_ct@J(Yz^ZAaV6@H<$BD$aB3pyGB`34%R241Sh)@x-#MMC6 zous$vcdHY`9{VqGjtYTeTK~@j$USYQBh+frHIfb?rqXXhFS_WCz4IaNRxQDS#}n># zlU97xy*^&ksCHF%o{U(pzCt1OSuRM_1$XJCjb^U=LgkcpK=N+``vkg9iKkhQ*IOlT zQ(g>~#jl}=ZJ`8)BORtffAGIZ)um)06E_q)V|-kTf>0jYk^g zV%HMq5NQOE)TB-%k2lk}*k+7|MC|)|e0dgkYJ6X46iKS4aGxlRA2Plk`}8nAy?EOO z;Tykb!7Z)s%UCa^al5{apqNE2eR7^;rG(tpIOPd@*6s1Ub5=~l?|7zMsdwSX^u2xL-^PmdeG-*%5+L?F&;c-ZG$!VeKqcAsmmRwM2$ax*W21ZB_LK5*a!b4!m$f*Qb^2jTMY*O81g_tpm2o`ONPA{7YOsTutb3;#pToV4UFz zuSSNG7|V8w&80ry^JTGc{ z^bU(Kh5zD*mHw-#^PN#0>H-VzoXWLH)ZKBD7|Z#&bMpvK zKFKVw<${$NawWuN*~{?%th^t0LOEAfm?fEB&sCgnW5<32OOb@`<{7D&;R1R%B->E+ zlI6tb$1W;%Nhg5lLxYAsY;82Y=Roqrdx>UCeTxZU*GHy#E|@# zt%YKGQyrOb2IX)9t7RpIO+yiZac1v}n^{F6{OD4s=!f4ZF1~|~K$6O(e_a`utnW`A z6?g&@%t=hm&IGsfKy|uAZV~7J!_M5u7eJl+$UxWgkSLP6AMV{;OL4NqZmpCiuBzD7 zMpzMXG6nO2*PtbEf+4*IKAi$+xlP*rttT(sGoow;!$BEb<9;dfR0dhi%JPL?N_ zn5TBUGMl`9h#on4YPcXH#M1j2x74z!>)>%UK}le3djc04@O`bL&?*LH(=X;E7_%%B z=++`|pVD*wjH`chRi=v*6b?ZgPkt94vX$<_P;nGhKDES2!X`VGPn2mrX02L_OifAT zQSs@Wa^QJuRhqF&R14j z;w6Sk`5p`#C30IYx;(G-6RIbXN!3o!Z6tP_GhgEj$(@{`06E`jsTp^fcC!V!d--N7 zR-FB0%kC$NLJHQVDTCh!3xbd}EC~5JPy9#!vd=cZrxoXv`d3X7*yY@ z@RCa|&l9AJKj+AZBG(LB8D^-O%izE+vb)L`Xu&}?KkKvwh|BHB{rNu&xdP}Vi|J>Uj_e;kfb4?5yb zF1Mgi?2Sfb~>4ke@t8W-u!$HDG6TILKSRK=L6ia&MlHC+^C~SV1tgntm4kIt}Mw8 zh_n(%MO!@Ah4vuD{}F~P!~zP(D?CSm(psY4`WWB%QU!gxwQZ60)>@gtC~uZHW&mO| zf zjUJ>qe&e^ua&!91;n-b!UKvm$0rG#ox?3!Xb|BbeCm^?C7R15q{^ek>6?#s;u6J}K zerPb-Em-x=jrGi@1<5iS=X%epZ#1ccyGp?HL@1~gGDUm5rVv8e9a@!ac zG64H1oIx&QBtcc2TgtVkH!H&S{X9FrhPpwO8GIV+FsR2#=!OcKm6xHf09=?LL52-{ zx6(|PTC=f)n>v^&+DvD?6y1W=Vlo|pd~-X$=3e5jL#D|Gw-7IymjWl}P2ulN3j5i2Dr4+ALvZ6C5zXTcW!V zXj*}r1qL-k4U0ACnNW5s^l3FKs5vl<=X#I4Cw@N> z9VLo3KgU~H6Nh}MD|&R=r2RG%P2QBJ{z?`Qm<9rpYyF}nZjheuAZIYu&<-JC$06{2 zEVBCT=vRrWITl7^9rJ>6feJjLA2Ru2r)A`Y8Ff_pM_G{Fi=OaG^5A}AimWI$ff6%* zE>W=#nci5s;*su#gzKuzLvpU17%VGWJLc#AwH^2yuwyE6R-x?nW{Y`g?wY);K|YY~4ks&LPuYo@}4)okuA_Po6RL zA|r~PW|y+Oh(I^2edU44PAHhz*g?0D^{kFyCk~RsF2<*ff0!<(V+2R>jyTKRumh$w zbGMed0TPiNmZm6Q7S9p@pi2||13;y#8Y|^iLCu#gmY-V<72&0ZwXQA+RX$53b!BNM@}$_kSk*< z2_%urmRhOqzK{H-8Kzf?cAN=v@5@tj!#W(29WhcglROYDGm=Zdk-&ntf)12bs&`E# zwQMA`rzO!_J~sM*eF!ZO4pvnTI1pExMo)_QHIF40MVnnm2aPU#4<+J*Ij8#FO=UHY z-<~c-noA5Z2!L@Y^S;a%McnL4S1Milr+_inywY$=HV%0n&WiA%xFeO?OI<-%VHYMHE#K>_Nb28E-snLAwFLYDw&LJsXu;OJM?tq^|VmI_! z31q)@&QwazS?U2nZt}IUL zM@$MQpnGGFi`451xem9dm@wx0d zPC;xJ0AVjufrGS`PIoh}P!my4DNe^6HpHt?j|-X8ZsX?|Ag?dknW*Tlq$nCqST4#E z?37o{u0k8t+E$otrQxZ8#y60t$n)v+xr(8*-%?~_B} zM~+pdIkG7$49>=6Pl}7_1>TV?NLYuZGfm;0ss`jk37O{frsSoEfXN4c1hK=|%LVI- z1;6=LseNNItv}HCTSja9^e>M!d~d4TT~3!hJu_^o6dm6FattZ>KjrgGZ~mNO(@Wo+GY0Qfioxp|NO=Q{@AeP|x$yw0oUn z?3AKP-1sEOS`g>Em({F8UkcO<>-|oD4JjqUS{@$(aJO7q%pNO(4kc36P4UH-5k%Rz zV!1qf(I?yIE;W55RnV$m-WK&1c*sGp>;Jt190teN9fJ0k75{#6z~NYapVz~J(B_lZ z=S?&SQxPM_foyUqvS8-;7eXv?mA0=~zGmp`?G_#ajd>KMH=p5J>03u>mtP->DFNoH2nTKSZd=G+CfQ$vuNqOp6nABsnb%JZ|Fj6f<+I z%qyPg&7Zo9Q7?_qcCu+ibw&toRIguff|7{Fjlphe^M2V>Nm13(Jt%jqu~LjiX|qKW zNcR3n6wk|i_#I@Ts&-ROl|zPVjr8Ya59aHO-moM^(`_Cyhdyp!@k5hQ3N@-%T)-Rg za<_X8Exx|%`=HCzZChqoh7H5RXF5StzqX!KRpAOlH=!}^VhbIH)01Q*dXAGA^_&;& zkDHBfKQYWOJ1)oli;ol7nAer(Ec~@~T@*$PvT^eGDD<|1*&`u)riT_S8AR~jq#zd< zZMBM(fl{czemge)v_W|db#T`Au^q2y(N508j#DXVBffo^#jWQqY_g=Q=yMTyo zR3!++HV^7r->>`V$CZ>5N*yeAQK26@#N6!6v1v^zKZPneHO17XRu8FI+cIY3d-^wc z494hmCzmkF>Sn!4S#14P6zKm6%~1cg{nX&F874UAX&*!aXH`(5Lgp_B;NL&x-1PJX z@Xa{^X8-JK$xX8rRvZgDpT|%LNX{yj{YKNw%LrHm- z9#6bA=2FsJ;;^L_A)lyu=hE-r!0%0s=BnaeqAu^I{6sJJe^hWVduW~^^zCl za3$YA7Tgc-W^6rdpR8E0T;*VD83YLcbPX3Jl6zxXZ zj2HjAErA4Lluk5!1?77h6jgG4D}!k@ZnjKY&Z4#EXnX;DWI&|kt*DC_aX_scy8~L5 zQQ1_Miba=}WjiE>t4F;tnb`SdGnUthzi%_byR%YNB72&$mq?RrE`*FWOn~PMYv0VH zJXpe6q7=RZ44LYQxuy#jaXEzQ=)y~Q9I&%pFEOrEXW;sBQ6@fM`q=o4m5`=-t0$~! zGqGFkEq4pnrsN_NOu&GuBLBNo+hSgX5@ytL?++5uj`8>yYa|;Rn>oL?i-zs{DoTN? zrCPC_qys$lzMV%=b z+7M5w4z*uXVz>2T8||NIWXOt z^SPb&ydM0^VM6`mFzYZ(&^)KTF5kodBZcs(_ehX1-Qj~=)8djO z@dYZkRu~MjC7%oQErK9}y+tWXe_GQ{!-{O$_&#G6B3<~n#74j_qBI2c@ER#r@K^?klofI8yDEt{)Fd{r-^2n`A3we8(S8K5sV42epyxAwzdUIQ!MzMq z#$z=6Xnol8ju=8)bMXrm{dDb(3{_Hpieq*7REwm|DdL`f=hAZs^x98|v4+9tZWI%I z@pJ9|AoSkJ?r~(k@EpeUOU1)~IJxu4AIuXWBSV!631EBN>+M7{zdW%6=z<%iF@5{C zROK)wZGcL?b?zRhToNq{I|@u)3O}k)S60hWyg1UcoIsdFmtKV358N4)C>7YRRdPL^ zSwyw0wgD==RI#BbI!*2$G1AJJ2(B|NOE&S1e{lstE5-kyl_lBf?<}{Rr@`)N9Z>ba zZc2{ZB9Id^(xRuxP?&8Y0{){}m(+-?H9b?<`6+@GW5W()luYH9BW%!9jKGB`n_b6cnWEwFOf8O zpo8T(_Oe>OXQZm9A#!YtSiVojyNyS^?>pv=&n@A(#!XkAdQ0iL^Bw{25q@yZCDgWS zLhnMq3N!Dha557zGut0}QljVfF8IEQxben*cBchv_tY>QKWs;Lde;`;j9`ayEjo4m z+ZCbhI4+lV$(cs6iZ`=r!UUK%n5ibpi$xG#+gV)8pN1}I#=xj#GE_dUk%EpAtnm{U z_+xx9F;G1zn2{5wDNH4swG8)^WUrz(l^cc4FEsj@KZy&sgHT4x3BZ}^B7cZUEkEfd zY+Mo6-Ui1|;zL2{Z zBu=hIq4Z>3wW(d@{3$lTd&H&IuS7uWdfe&~#YvUbvrxF2WMUm&g3wVq|5a}Z=Z{#f zU|BUZ5^+DrRBA;zD(UgdgWOjo3~sv>XQQItJ;#xdt+Y*N!E-+%3=Nwj5in*Qc6~;Z zD&VHy((!^?IiR8W_ThKjGT)a-c^OdA>Qgxdv^m^u@lDZITmv_=D74zendO0|b`_E6 zARI#Rp%N%CArXpTH#hx0yM^f24?1K33li&la&Czo&qpN9rlOsnW-ypp;lWUE4JgF1 z3G=JyV53P7r1g<1H9ho_w_SXcm7$=cUr3)>lj2@SVO-pKLXy*)#K4a}WdqJtyvjbf z@YGK)8FY*tS9s*%jjU+5Z-WcoS&vT$qZQtI1FIE4J4=MR;72+n23wYIs|MYe{>`~Y#sh)cf@|N-$9uctK@g(Z zWj{5m4uPsir9l0n&MKQ~NRY3A&X2;`gdboxZ>^QJqrj-+hzBdHgY!xzbxfCiEXj0f z7YWv$mJvS7MMWGzmvW}Nu{VOVn*7=+bXkMCejZnCc*5p2CG=*HkROTWQ3XbHbYr`= zlmB*`&cy5z4P&9g_lwDEJRXB@E^kuqrD*xGYtOFpaf-1s73clkY?DSo;M?8RDmiFy zU}SwmP;xSRr+@K+y&C;h1gVX>Wj>!nS~0HUt5RLyAff+^%pd?V3-at+WLO8 z1$h5s40m0D4I2bCm()g<(ofcsGFlPT>k_RN+_; z1ux}llT?}o0A|{Xc?Wj<-$cc7Nj{oy7f_mCg9<;Fs{!64*F;pe&3Rd+Sl&*cTjsl7 zt|B)~RCZQ9OkP@xR?@MJj24vFhRZ9JSdcxaIEJMii%zcB<&TKv>h zuLN18_!FBP|FpqeF35?sy@AvRTPi-y}-A~s}RH!xL}`O}M?}x&53Z>$D+(x! z#Sf{wLIH_CisPV{A2muZrWV|e9$+*6j7R9K^@_O))<*_2l236d`}`owm4pN|k8w~q zklR!&3e+JqxW>WP5HHa2plUN)@LV=FKgvZ}HxqO!m1VJ4%!+6Y2u=XYB|5$)6J-ME z49D0f>bvu#mkV>J9i(s@B|xEv8M{uGW4G=Xg{`+vSX&(Aw+&dk)%TN(Cz0vQO^^{X zvc6fC42Rkeg~NsnM}h=9+?38bUL2F;^H3s31L@vi;ncprJ65ru<_9^>mwPj{VQL^5 z6)MB-TGLp|HNxO#b{gHH45YWCAgL8TcL~r!c&W4b=DDq}@U4>gsvzaNRikpg8A*7- zCb6pBqUZQkg}bfIpI1;)7xF)%otBu4Y`<}OBOFM`=l7o!_%~s4H&McW->;Cfp1rkY zCXs<-_~Q_CgICUrc+u`T^2WbQ%RWH{XXjH!;WM{Ed(={KsHbxKwFaRSeLy%ap3_l>W3B{GyD1 z8D6I?QJy36TY8X#3>g5VAx#Z9V43Z4v_4fPf_kH_1FA4pt2}t0<`u-0fZqowp0O)P zzJ2*VfmIN}T463&(7d0j5yV`i=^*zIl2BxgnBQrqCN=a^atds2F3y>pgvSZ_YKouE^b2l& zMGsCkBl4?_4THIpv2ee5yW&{$Jrc_1vOJw`!8k8oqf%L`{T}oKOXIf*y^!bTa=fZJ z5#q+j^m~Oi0f$ECU$qzE9}>`rz6&Kloj+|bJI!#*zOnmH>|*tO z=;zpKG$_7Z?-*dCg5B#Yi*gc5rX#&9%?p$i#d%L3jcv?xhk>UV2$OVRVtE^a=T0p_ zQ$mm~52A*~Q*tlfkQK#j;$euiAgZVj<1;u8#JeKQzR^mi0Dbjvau8*qBVXZw3YMMx68_Svf z<%Cff!T|4W^sZcaoGAAMrbreRv`nC$woT1X& z1+yrOYb2$qV-Mdu#)Ww627Z_Gyh8)(fpicnr~wBdJuClt?c>ANLWP&0W50(A-xr{s z$BYZekePWMo^$Im?Ki)^b>Dtg%`ZLfkT$}?bv-Ew7j#n=nO19nDgx-YhQh;=A#zai z!=fCk;4pzvRW17d@KZ^zFZfBDvUnbdpX^*mHyTGG&`g znzkm_O|2qmL66I1NMkFZYiqsJE7SQk?78JkY2&4kL#C0)Pi&Qz%Cko(XfbpDl`O{p zTg^NT@#uYGTZa z?L{EweNh!yU?3rKe*S%5GIjz=c$1E)Le~Tl79MxhoQAN;+J1Ce5T-NWJVD@YX!nX% z-+sL99wy>i^W(8=x%*>bsjSLha>x|=nWIpGnCqrTMhgxM9=5oF_uKI_tPS2;{_#fb zb5N|u(%#wosEfkOF{W~fUkC6vV&`-9W{&q;hnt?q^eFjtz)3r)>|fKPd^ryRM83bp zClWqXTXRX`7J^Un=^hFSBhtp5IF1p3HvM}KW7|~`^CQWfhsb!(m9Pw64r7IhQ%^7# zw@IWYeP(*d+ii568u2vqhi%1XWOq4z*TYWMHyW+FPKNM`vs4jaxVf|8zR-l6sq5eR zQE9RNP|;8!frdOUM|22h1T5>Qck}5;3n{$_7o2})r*wm@aC5Ora`_((1-!) zwDo~Ab?ye4^;2y2@zJ-))4Q=YwT{~9Ax$HM`K1B8BA>7L%q4CWo*sQ$3pOE{w}l@U62t^yptt9$eUdgDQqXgA&G}bs%6Z;=ye`|6TZt`E%o9GD)p+(#wRGRV70fWrHK{Y2 zVao^CCT3Y{Z*F)Y6wytq5K~F1w>p{R)r~G~W9n@P;&7~*!O`xo9#-1rS zqXBi9{)x~RvTnS9p#LhLM1Ob3dEfky+8D8?D>0K6$eVsiA~EM-#1QY&hTpnvu09EB zUv4|``WxY`L`-{!;&FPw^T8F|@4YnGt{OoUA7fB} zieD4|F;?cSe`7*Y+Pm{J*n+W6DKDXBlb5pF|6UD?SWcJ*E8U@^vZJXwp94=K+i zhZjyfj+^NBn5vRCKsROO0R9vdEnO9udCNZUR;c1QbUpA(yPt_T(nN0!?>_x-1dp(d zLbSPhxb>=PvaWWS^S*2S{DctC(e% zkK8MutcUu@h9AKM2Uf=f&o;*{!Fj^}IKPVdv8$^-D{w6m+3*2;?s@kWXloF|wapRH z?Sa5i>OrJy)SxquO_R^w%Igp1IGOhA+pTe*H`}C&#h{iDy_;0uenQlLmTHOedxVYI zxZc1Gjs8`V;tc4V89Evg9dl5croW-CQQou?U|7vkBrTr6%7hj5?OcNFInn7QHM;R0 zHfBC=&)aXqNjV%07{%+>9$0`^pR6CSK*XTkp(K747zv_1Z7pm(Hr*m@s?>GW9j#hW zNcY1QRQzgKWx|y^w9YQ5oHGTZl7+^=(WS9RBUo|ebS9cI2I9r8|NHrN|CVKANV(g3 z?7pN#Y-a$8T)Z*(J%Iv%w(0jur{k%lp2y+W-k^S>HWP)S%J+Q6DRKFPMYD1Ys>iYL zw5KbWpr8eTE*J@&=M1L-twXLUm3ipX1$sJ^NG_y?B$sA=E5cf?b9C$$XPr+SY#~AI z8cjhLUV3R9sG=Hv>b*3mL~Z3f)70}v-_Kz7T|K_YJ*cYiACWvG&IjKGax*HK7hM%0 zT@7tqS6+=4rhkF=DIhMiVm8c*+w+UQ-2Y0MZ3(NA8mFG}5={`EjQ2G1j z0z^t@9`LX|LPxw;cQ4cgx_Co>&hdJfpYU!zYN42#uI*pQQba}gjf8dUP7X=cY+-j$ z^zve%bt7~AY@0FR<;YPaAE5)%iX*GZElJi~{ci)syW&_c$(EwktGs$Bk4(Y1J{GPHE(X41ZyI1EJ0VcT z&128a@^H{Za!i-bu{-QBV&1J~-z0<|#o&B>i)5F6Yf=8VzLdu1V;t9yLcUQXq>i`JA+MXOuDd^<91IZ-m+gqw zzmelh&TLG-56dr17W9>^P(;yz_>E>jLmN~}PAzcEvPu_vS*eyNmL6R&=-IY_F^Q~-C|mE+v~ z3lOh&zqVI}Suu^B1=Z7{SZpE=)6Bik@PZthYsDy&D={_)U}L&ZvQ1OQ39IkTQGDSd zSKS6Htk#PC>ja9T7cxwK;6(z0ruCtR`nl4PxcxQdrF%{{@7PO-2P&Zkxn#g$q7VuB zEs^#_7)IkNS5|XS5aKO;)*as-J%*%~U%xE^>t_9A!I|iPidhtwo@3_>o8kKDgoi7FHeOqimXKj9P zCvtWHLTf{b5&yx==a|nG=j@yJS)X3J4{PxM{cxb(4q>uctl&T{E-q&DYNj#!XvnaG z3K%d##s?oyw5yCzko9&>j9VG-6;N};My%kiaA%DPgP)GAnFR572#cl&m*_c@Gt%>F zL0SZr1Wpiw;k62Ut9LS`zV+@_itbV@Yv>EzD=CrKK_QHj59IJAkwQVrv}?_43%(m~ zFjnF8nGh>5<-&te?KENz4Eq@Dx`ap^9;Eti3Il0cAWVZjIO=zY{?cvgz~CQO9K-{!HU`yBf+)ztTZsqDJ2Ga@%HCYbAw?Q7)kmc9ZO zY`u?l0b6h1XT)|t#R5$U)WEoh9N#g`1b^JLMdot9C133l(E>Z;>c(2Sln(aL3Fw%u z#C}#3fb*w`v2pUpO|ho;TQ=u)=w}p_Zu`rgHP`F-&I8a?S~)Edjy>FCZxkllaw3^exp0Q_bLGmG!-YgVUA*kCT)ir1CD;PTS?{jR71@+ z4BDJ~iK8@U&XY^Awnkin=6;=fY2;e`2XPH?bAV@do zano~m141)7DryM&@1&9S7>oO|J9jiWQ>`*hBSC@#FA#N-@><8$MvoS62+4}?{(^lS zHeEpQOgo@Zh$*Xe_*HHh(S`Jq4BE5t9^YK6f|Hn7%|D_w27}bK=h93g{#oM)5~qVW z^343(FsqQL$U(PTq-HqYulsmOkIexxy|fGSphQ(ad83G0J9!U0)zrP!(Q*63JN=ub z^MadxgXKd7Osk;j$rNJ9gS!3TU)rjHRkG=0rqiK57>05{%AatnSvb(0VER`3UFt)a zWb^T!`mLhv`Fv7D7@ihbj*=I+L-kD>qj-k>eFCEwSzAR_&k1K;M_0J5517Yv-P9bP zMXy$^Rvhh~T$%0UzYeCAJke&;6bH&2A)fg;hND7TSi2^D3Dq88$qOmS)z<*(T$Br3 zZDHt-C;bOd;;1WC9NKVjkM|GN+Hn;v*o#zZ+sZ1og=Ih?@m`p~e~Z^cU_0+cw*-lF zW}!8kb6*$BF`J_UhteMa_xpR-TY!00?!^W6>hgNVyj@=oC~}N_1Ap&>k0PwF1v2`> zJ2&~Y-7G=t2y&=~l9FJ`H0}{c?hO^ilE4{RuCx5olxebw-Kyq0$ZT~UIr_QCK!Ou> z6=}z-g(U~=_gyA7VMDY&LGPTvC%zGiqi+BMLm2WBxgfdSGCEOAe2Og|O5vB5yBrad zz6LB&TEQMhKoB6bc7(Tbjq759Im*m`Ws(@b3qp~?Vxf2hA`9YB1 zA70Zjz+`9wID{n8O}7A>+074)SIRBBr!wn;G03Wqr{b(OBlCib4TJNy zPJEw-T`j|0%h}JRGFW#% zi&~ds8qpk{5qwjgsGkk`Qoks?Jf15U9NF8+2~i4|BvuZoUAF_yi?oiA(;{*$Q=)N_ z@EDM)K4d^(bJOKrP1n*f(9@IDb(g6McdqT!;Jxf#^RlLH$8R(S)+@_PH;|Dl9=Z`M zNrDzu5I0M*9@4hjw@AzQ(n(K_`-}iW$q!Gs=H8-VO?JJf%>{j!zciiE=4K@Eagt@c z^saLzf1{8!d0GW?-SanU-C-|je@>my_2YWI$Qy2Jt|B>s%G9!A&C8}C=#vs;G_cd{ z93m)^x#`SBYgAA(-5z(x#?|k4D{d{xnR52_VQDK24{C4(&45G5FZV(%fpBDyDt#+@ z=t(o~MDqJV);iza-(&6t(t3Qr{{_EHsZr&l z*_msVUIdS+rnf+2?pxC-PRB!7%I*7hWjnN-Q6M`OR^>fHas{$zR7%=bg>>9jEG}~} zRpScz`E!A-vq^P!p3U3?Th1bOz1hZ`}1=z=WPD(7oPH5UQDlAUCpy! zJ2FKFPm~eiN!X5!phAT$q%Z6JVyGskf-0-VTAi!pSW1AfpsdhuaiG}+jYf)shwNf5 zctIjIiuM@ZP>BRVmi1eQ=sPT$$uPOYIl*%#GIeKtsN|R(d_!Xd=dhy=ll`38`H{h_gW5p~2Y@-Hd2OKE%rXRBwO1!(=Lw`?81 zrp|KMd*nV6>hv;pR?8*-mbBN9HcWQQ7P14_v&| z{?fNk{$VL#_!Pz|5N?l|SD&f>(TskDe?Ht;cfBW(;Ite$rR!%iw zQ~?DiN^QBEr&E3JVT~z&xNpcx6bln~2T(qQMDW3)Wqbq(RJBkv+EDW8%^qSG!VE{P zCu3cJ1ebMw&-D%9ukf*5?DZS-32Sx2NdM-(3nCwLg_cM`8lqEGbHmDl{q0o<;U^D& zG1xB?A3`AxK%9~-JceJnqpaW&PyZa*JOgZf9bxOivdulW`}*D|BWKW`xM;SQhP|xm zI0y_AJgx4D-PpowA2E{#0$DkBGg1RFBJ|Dd&wF!mo=JKUDC- z06Bh?g6x~9_g7m4JXEM#03;i{y)jk&T+q_38u^O$QIrr;ryh=V3Szh!?8>@Q2X#@FWd^YlM1;i331}>b z%b669d27@?V&g3-6UI{zpdy{HIlrC)3=z^roLwSk(5m;d%>H!fBM{o`>wIvO zM8(LLoDEhBciq@BXRmf$Q(L|PFs+_)hqU?Y*^LG=viQOp1rG?nElscE&YTS398i3_ zg>GJDG^zr?F0M;4V4opRyUgrH75)m%8ZiQ7QEXvGOr7mnR;B>l>n`B662{XFC$1)4 zKRSV9CG@|sk_tWUfo)}lOWON&9;NI4FK6porSGpL2T8~Fug@)d66tt}V60h|D27oH z!hBl{A2spb5H%#h@c@WM@=U`8fnSoZB6$QpsteXk^-+=Ric%qtqd`pN?%D6&QE{}1 zE~Mba6>ctpYl>!3gc(-l1+PcBlJes7BuPd3=89UXa6u9ICkZ*7zKJP!)&3%-v8~nw zSuPmV`12!_@a~6_9_j_}EqNxeBW4R;&5~#^N8M5f z#2c$1YqKg5f&uz7ga;$|hZcT!z90z(SdfwGoDHJ63T8{rbew#bnP6?lS3Ev_WLY4E ztJqV(af22HL)2eks9u#!DWR_Ccj2Wm-1MvgcNRo zFvqPQ4U~W@O=ZfS(wBhxDW#56f73S!dn%^NXkhAZcHG>!-SbO~O5p)KpTEsy=1bK#qiZ?S| zX@?dflipq(@9G53jy-Hkzdh6B%eN&J*yOTwa{0-@AE4H zbp^nXupxaEP2dS^#IO>M5*}QFT;!eGsZZ+-5Yl8et#;;Hg^GLF0Z{q&$~&( z&?C-^=^v0phPTxsyHe~hA;VbTzO|G4_?tiAJ z<*IsD(9&-2{h2tS65R+kYPv>GWISN^b76Lv!aJ^D8_Wtv^t>_(xK#ZYdzio1`_;OC zDw9=w%jHmX%k{7Glgsb_NTq_=AH7|5o`+aSrO3h?TCnE7I!66B!76{nvpZQcEd(j1 zA3=1weh0~Iiys39X~(gF<|d8c>p`=^E)k+svXJ#9)YFhhWV9hpgd?<{OWh9d=w={* z`7p`RYr}@l1}AjSw9-#CEZ!5>Z?tx#vBt4+=)i}f#+GBvUw04sFGMjBlFaiyI*z*5 zQuHmQ>(j*m2qw5(m|)??nzB7rDjPs!IicyYLCXx*7=-frXjIU|<)RPE8OZGs3`@=} zvqxxs@p}%|gXlH{hA1X;+m-b#g~{}_biSWz`Orx9e{5^iX%-nolS$jLDMMBH1$NeJ z>Wacqh5^TDJ>=CKPPd-As*m(L^dSU}`_RwVVZGlwQ~fFNGvp75C*{yj@E+a$Yo#3pkfgYw;!78e&%Y%Hm}b}@f3 zY3gO2=`{nnJpZH|%`A|Tb{+(7x9Xc-?Ev6i0|)!<$=h|sdF!RTm~&?*SZYqMCKVF7 zcpD?ZgLEmgyN7)(Ri`Qg8K3{V0ZC;7jFv(!j!z+qFx`H~QIR_p7L{vgjTY~^Fs*XM z7I(3ek43LMEO`?k^yP$=QRouoPw(SNisIyJ*^%;7s+*sAjBVm0+b9=2qzsmPjxU+} zk4uuz5-CS_a&^Tp!FqAYhKa;{2kL6mAZ8uqte}%r5RwqHXwB8awK>*~4JDNkB-@H3 z7o$y=n-0UOv=IJ0f>mQW?NlwC-+{+3zr;T#`;wdd+LhsF8Z%N@#c=C74IvYWOY}A057zxui<+ zwNnHB3Sk%j;Q`@6!y>>&{ID!ry>fxAW?_kZUBGl5{HiE* zxBp5m=jU5T4*U2fS_UhY%f4*`1CzKB)L-TzLm6CLVYk{w2~kT{jNdRj5`eFEG#=z= zx*S{WSX;#ZC4&zd(yx~=?OSml@;F(O3>i|MtpP?|CUlJ*FGSp-?21pp#)7^qUX45V}4kEA?Yb)6|`W<3q4Ay4-wZ zj!7Z|Zg=~c4OfsF(mc@#3<&nF#%XI4q1*0WBUf4_BFAG=1@*6=rl=d@mEalmmRd3W zXGU2yl#rd(xgw@wMi;{z9hbgFR}0i%3Py`#l##K8byc;mS5jBgW?1>Faw)gNYeejB zjX6#d$=I-$FolXuVuS)r%KL4Vz*SbvISaM^0?z+Dtu;^uir_3#Qzx_6in?xme|ca3 zTTlo7PC94WHx4Tsn?<&w^~=i=`1FfAe7(ZVn@v(*Kyvv7$PA=MD0qKN^`n#JDxmV@ zNy%~P;KhTc%204&hZC{K&{GWXvXtnWm<>(2h1bYU=cC~@;QnFzX>(pT7#J?D1i-aa zOC1?+tpEVbQnF8_1ZFj3IKy}oL^8t0caqBkROk_)u-+Dc7oT6I4BFnN#@~?wZW*C& zZ|wCIG1VaKNuROC5z6yR{194nMFj-ks!2k04R}M$CYYHL1iICXplz`N1%z4;Le;bD z8=CB~^i+5bYl|oP$oJhVIH`Df6=Are&@Lkd%Y{sfgeng&jMjiR{bUwISTK904_HW@V^#2F^prgI#Y5>S z3_w7nrxjJjIj+HUj!p5Hp>_h{XV%?s9;q$etdh---D6C{`t8(6#^$=Y*Bn$^%}L zm!)=~9?Ov6s7x>+wr{bMD%kNjI?63H*>WN!w>vD)o*klev;QI0mxW z0;qyx#?;qR_NMq^#j=;iL^Hr98p?OHvgggaeddm_&hlGgX+%QBfRJQvQ z9M_=`UQRSlq!vNheH@E~Y2ClwYX{Kx=3TiG*?=mzrJ*L%Fw+BtPU| z{2`&7V02qd;{ozuNa})v89wC%B=uHKzdRIv)GCG|A!R*?MNONrT9B8PdG~9BpebNO ziUa}eu)Wdp{eNpT{z7(-oEBQ+Ds}@zNr64X12y=DHgEkQBiSXt8gyHoH8&E}G>@$? zIAeqK@^mI1gvBF zFvVDU6+>g^Pf1T5a-3*?2QDXU|DmbZA$Xs*0^@g+&Rti+?tg*q{P4fZHs+2yQ@f9I zRiGtj{s7Iu3?Y)(K|88(dIo8+9P~kYymRvHsB5_GDCQmNQ;h!@Hku2u5(VTC47o}r zgGn0OkI-z`GkB-5A2&j;E;#~~ZJa9K9v1!M6m$dj34a_RNVhYJAwKNXUBnxQFsgDsZmY^NPvRA@>*;263OrSbqFv3_WCd0D+CLb6JU zFf2G=EWfl-0<>Y0Q?u|i-UDh_yYvT6iN#OXrzj9DjB)H`9rcP|r3CRPl0&XMiR?_? z?gTBF;@_Y~VG~Uyj8u)yrG?9P9CQ#<>4LYBtc(|c&U3s1|J~kP3SvG=u)vERvzxtL z|I27Vw)xATH>LL2RL=JJql>oWLLC)&Ub$5gKwrak&{;ZzbIkv#+LBsaM-nyR|2!SSH!0~3h};vY)tJo%!!4wMjb`U# zKH_{RlIJvs7K=SRZZ-EIxh62oAJ+^y#Q$;N6p*&|0FpSU%5Z?KOee)>vhw* z%_j%~%B`P40vQvzFG?r@Z2G8sC}K5NvvUeEKb6UFX>aW~0fk>4XAvFuFkP&B2`Jf4 zFHP!pxAEoq8VyAk%KS6fOOkpdgiz9p=o@m%!&wc5g+#~=J!A!} zTxj~>9zO2`nu!95-_U}7*Xb7oMlk)0zPR@}BNzU>mzs9QFx*@X5e0_&+Tc<2*u@LE zScaAR?W3;EWDw}#2M~K#wVv}*Wo8EQ#3A_@I|-~iDq6=#NR~8~(`Z2egzNaxEcZPT zzI@HLP!o(NHlX|DngH5p4IHd_OmWm+8+Ef zMUF&3cWaM~#F)NJ3|5K)C9U4mtYiA%gR!p5fm#u^rcL0mHL#MQ+^^If&^ zg;QZt;1rkW#e_IoZ0*OWy-_-jRwgGa6Dj|Z3KwggTbU}pxXs~-4~2gcKJS5282g5c zhIctiP!zrKS!hJFrgUy)HmLEwQ{oda6+lKRcK##&1!SfKg)<;t^i0au@qpYU&9Qpm;6dO!Gu2MxY?0H+TU2y|2a$w!_!^F)BOf-ea&)r{#a4O z{Qy8{76L^UV4p|yR&o3wGcEQ+K7ql?MVwi5~#u0&JMz-IsYS!h2%FloO81!v{yXG}C zn3TdJhtJ-4gtUxB7h>UbHcO`ejsoR=uyjXX3_AWyFYc^A&Su3o}C*N+#Cxj_;^2$+eiAue6GQz}MoS%ur1F;p#2xR43cxJxlb@-x}N zYuALwipBhQgLl@qS_02>1F0^?gq*pCu+nI>JYSEhO&U2x;xAu(zK9C&D#XrL65bor z+e_9okIMb(dPx*9Kqq_xVQa6S!S&#C%A^kGsBe8P>PA|HOSJgQP(gbnS_UF zHcz?+>XyMZuNUqBl|G$BHPBa{k;Tbsa>JDD$pSLp+WJAm7ZutckgzSY3u)i&PcT1X z-kPx@<(GaP&M8?!O_!wVrMkhrlDz&ZSQjt^rK z{Tt$xR=7aFQ)K>`$VKXrY+p;KTOI|xEE+1zwE0;^(Q|bP{^})hWj)oB|J{jLuI>6Ry4Hzni7 zLjvnOf58st@LOc9-Ox8|N>eUPjf!1_29w+tnY@>79}#0;fpnMNXk+g};<0^sl^KC^ z3BjS?Oy!1f28pzaj7I#0hv-A_A9gl+&5t(AWaonsS3`5aRd8`FMtvik7?ee?((2c^5l^5t2XHb^4D(Zh5ajey2 zv*Hdkn+L{mB-vR>@^cy4xVg6nizH@zsQ8DlG!QiU1jIk%Z?67`S2aR&@dHbkO5NY8 zdJ!MJHFVgKiRNnh-m6C`&IJ?WBKxdGv{p;|08#nyz>{~ss$G1F3KYi$=lz#t98F3X zTt_$OiNGPzlwFK#V;disXpTrt3;8300 zW_6jBi8kHdO$OJz(iv(^o&pJ0x8v1G#3~@=ahGL(nP)?R`7P8KF9qZaw61(y@*lP& ztWgL{2(%ieSVA;R=w-Q^uRk~f{~Q`$Pk*(WEC7RW5a}jAYz=qBg5t_` zt-&tyP`IB<_};G6_%Q1)>d5a9yPuzKt2^ZLV8~N>2=e_-v=@H9Y@Y+fTrq;49l5U< z@LM3Emp@-dNqiE_GYK_uj-}3YU>vgn2_D4uxe*e?emYQoPuB$CO`KwLzZp?35Uo7C zgWn#{xmR4IBe(hnm2fTu~zc%B+h zj`H|^ckb~T*jwIPjTTV_$m3rIp$u&ew%TO{{D0$>?a z4xZlvVOn3+QdTcyJG(eVO;Q-5Thx_~1tn|Vm*|l#TDR#i3ebB< zQlK(R6jfx#>ruW?!L?zf)ls$ZyM=nu z433VvgvkSWc`PxCWM7PkfZpzaACRhbu|W}?<+6SE1W%ABNN@;_Q^ZUfUt^S|@Is=o z7vlF3QeaHKQsp=|x@t5~A`+K;FYCwg2$I#+XOMrLNzOVt*gi`$cGilLt2oA^>e0gr zv}54-{*M75jKxP6SO+fwjA_bx#C7llmaM?r_0`+d1&NkBWhRHK8^KZkDBL|LvE;*OxU8EV z)PEQ!bRf-(_fQ35Y+0sI}akX4cLwVDd|q zky9A2XgG0rf=a)(7^|B?uRxw!sJd*JWvYF(JZPm~aC!h~C#dh^r#a>9agdTWV>QYO zX*tN32GcfkInG$8|DEE}lQ7i@iGYevaKWvCfBMY&70QVUx?*fCRoU1bWd&oadbn7q`?I_f|3+PHFkkQnQ8b^ zGpG{}R$24ZFn_xG@+ax9))MaDHn1O?k?orzmCeQPeUJs{Jp8-v+7j&|a2=#zt!PY_ z#uuB~+si}c@f9G7t_o*}h6ouNOF&|=z+1G#z*)}Qa7!OUy%0^l-$FOoww^+j)HY=< zyrLTeM5RpJ@Zo49zebU<==E6A!56xfO!m|toK;adj5Scp(J#3DAgTGbTd|&P`$sZ3 zMdR@bb0P z4h3hWF)oo2bFCWK?qctMSEsKDDth76aI^SjfiB7#_K!Y56^-mD%qZu;C?UX=BdOZV z*51*G457i@*AK0w`K@}xy0WO7mL9ePF8=Sqzvkb;Ki}{C4F##={^IIm2WN71=DKI- zA3*33ZZQgs9?33@jD*7&GWCjL@C(Mv)mH?}n@J89yp6tqDPkk>K4`W2{A~941r045 zYpu)0s~;xAWT!8UZh)WYL2^;wk1Rzb~7r#9Q>P1;xoaM zH$PX&n|j+F`aL5t^E!nYfmvH{{|a4{9`bJViE}Td!K@>6RzXSoiU{P8f;gD1MxZOa zZBDcmSfd#KYIGhif4Um|_#L-7xl{jEmD}|{;WzSs!tbJ~7R852>$wwpW78URk--@| z+dsU7xO%`ge<%u?Pd0k^&`XA1a{f+?7&fpdxkKi;iKiahcf4-289<2jgKt1_`OS#m z^8N5G^bXJaiKmjnLPIO0kf&B*RG^oT1+Qm6n_KV*)QFBS2PF{CB5XLo7_E3dj-%rJ z3+q!AB2YF|<^gK<6YyGw)8cb1z!8#1pd-%xT1z*RG!#dUV;@3};dpNvLEFI;r4V8% zdfnG7+clLe+6P-~oG-87IfZZ{EV`#>d2EKpun@tY8lF3Mb;mKiATrUSCHkpSm=se` z(u4YCOpVHa)=7$zhz@y9q+h~$v+LIV6_+-dM9X>U@^f9kNRTaqL`xsCmnJt^KoJOE zb1>r;w)4!~*f?SGrX}S2ktTCFR>`!h#NvOEbju5pqc)*1#pYOQOluOe)NgbgcAyO! zN_RCwC@pEILD^d;ILd6UDzku^VV(-W=m6p%z_}Lv-`O8W6LMzrlB#1z()zj5zfuec zl!yI=Z<;)N>6G^9Zgv$9}Zaa1Z?I)7H#eR<&t9@|0Fwfi4Ur-98Fm!ZNJxcYt*h`l9 zf3Dzl2|oKoNcd?Cp%yGd7cV@7o;LBAQ7N>E6EH~lfZgLsV}Zqp0=U_ zr3BpOuqbfVB!3*U&n>%s?^bP}r&ukO<{V*LR4{Ga>j@Q@6{ighI&uz%Z{J7D< zU(`(P6jb=kEO2M)EB0At{Q@T=K|D9yw;o-AS4Zz02=BXbpuq~&pZ!w{X1d!lsEkue zMuHtI29!h_j$~Klfk=0>5?Sy)m4@2{U8|J_Tnd)bs?>^BWQ5#n!nz5;(b<%R<-@Ts z`DcqEcder`f9EjQqK0`dX9>&ib?~{G<;YkF>%-Ct8!e0C5q}>$uz!t2f!2~>+~IU5 z{w{g5>Any`GaLA~pIe_B-k)P#$1q&C>{FZ`VGmA^COur`j-XcgO8qK3ex3JK{$;~l zXDu<|-(xDKYbHu*_>jwYFe<)#;;Xa7yI>EE#hU(E&tNL36sIUuUN66bbu)|z=*mGl zy3P89ML14vg*EktgN=;w?o`t^b55_w_!{ff>~A|Lnen?3 z@-+`II$7U4yG7ge_Sw5Vo==eEhNLukq~mTlDE`ln4$x1Gw2pw-$$L}?aZierm9D30 z*C0@RaeXzf_!h?QIG5eZ3X>5op90R&RXZbOu9_RY;gch!5LIf6El0b*dfa~oaX5++ z-qsTP>*|{imAF@BK%)}>0Sd3}w$2M8>W_jhr-yyA)eUu^S)hRiAGH8RNl82D#uDf9 zY~g4)sOHxUmN4kR_d!(JdC^&EqA4!md*LkU5qf>0-i|Oc^+RB z(}y;BB5kTrQH23wjmBH#J?=6-(0XstYy8GH3&Op*A|+OM#YB3g_wRRpuOkGUP1cEs zJ4N>*DyoU0S50mjDaN-5bwosUvlXziq7R42V#befP;cQgqF&Wh(iCLqDZxsow3ssWZDVq~!lIabY3Cl-bjotXjC2n-`AhXfG zERp9*>m)w6I}zR_-C*}BuCzNH^?UmF>H~RPY2%*j*X^C2zX;})>4%fa_KUjoAX^=t zXU+z~>JOHsRLC*nye=G-ml-G~s#ai$?84RSUv<{UK2!qN6!$Cdn2(2260b8}FT+2>SbK|X|=9cdX5DdE*uV0Qi2dHs2Bg4_mnWt|4=%P;j4oyE_+(;E(Yl8 zI+sCQUsSmgG#A2y8NbbL9l|k*d~pl0OR*vX2dErmeucyW*oUAsC--2(9;pDKzGZrt z$plW_YOahsWpQI|$cNEFyom-JcO(=QmFa1(9y=x`L7mKk>!^DH8DFiLP)(CE(ZRRF zcK2EcQ65*~a75O1SE0{ej_DoufNNx@6iFSa`+f(JB7+4PJx|7Qcbl1>tQh*#lsA~K z=X~D+>oYXC#URXJ>kDjaM7ur?=ctQ^NIT!8FP}?p_e5Zb^+ZYZ!^scBGDlrR>MG=B z!y=^wU**hcPBp0Asd_h%&wtA;<&T&>+c>@%d{R%ae(xKP4{>48mVO8nxm|z`XvDxs zwP&C6tZ^(MrYu2hu;NKd`zYW1NJw4`cn&uG%K$|E#{l#Xvb7eq_B>TMVnCzV(saZ~Vi@vN`x|BX^o1azXqNB^w(`s>vhe z2~DN|A<3H}2Vh9IUe4Plvr?k$nb#zuS9{e=m7>_zM8zLn+7+{ za){2dmhm~c=+Jf&EZ}0Mk#z>EQwO51C^YYv2krQHA#)4&MG3YuokavAF_Mvns7}@9 zx9<1KE(=JechWy04`tkr?Wz@j+bHt?=CRn%Kfpp|-}>|ohX3n^i;d!S)Ae@ded|j7 zoY3X`w{xtatgf$TWZ>YG^+D4i#c~67MHi@5XXJZPpcqkJ^!c$DPU?E@k^($~nc}i2~!(5Jl!gL!Z0gl*e^dCmUefY4b~MEK`|C9w#li zYbYX zmEl9eO-|*cEt1kRwnvNVNKQW_E~4rQn)nOlP4M5BgJ7O-;Kj2U05~2J?M<-;{9)U02t_RosH)QyGS7ks|jmvtzy^N%Qm65JF$*DBaP%8 zNVg$feU7_EO30sSBZ3Ubb!%bOR{Q0|4SF%)1jIo0-E`>%*gG&{`~H~%&MS4>eR31{ z7~APx^)D{+fJBD=xf7uD#gM?T7ltZVGAJ46XdE1n%e;@%%K4opr~Y0SG_9U*I|3Pp zHYi!KX?8%$#F4$KMs_&Mm95w)B^fNXb!^KHkAP^Vt5#03>Q44+~ReY z2(Q;Us|4Wi%5wadyG^+MAo=+w{5d4uaYKQi?aqk3x?0e&!I=*`?9Pki3c-ivD>J0N zyXo*!WuGvvi_FWD)!#4cMqm;f@R;hUWf>TUI!ohJN0Tucq>1mVx+Hut0Cy9p$p#lm zuP03DnpCU&Y+!y|&LD z<+noW&tC0SF3+^d?5)Cy3Q5I!SbppZNRwcQLmRTIe0G+ z!AFf7OXyn4To1VwpT*Jq1$d68p0c^^&!U&41X@ph_!Jr{bNA1D!e{7!a22s-uIpFc z9eKSzE6-(Rf$d8DG209;n(RO8kktU0He~{X*>Xe&9;WhfegZ@3yYkhAATOh}7KiiO z6t8r&;pehI#<7(H^qzW(G@el!1$L`M@h{MtdH6`;=^V(E@G~Sphc0S&q@EvLA05n@ zD=RttFvPefRu{P>g0CW?pIkhUpvL8($pPz8p>{rIXi`i1P(jS(RE4*s83iHMerxMpmwv;ZALsO%~(G z&@OTWNdPkIv*j#_TaNvfh*Sr_e!|Sz(-irluqf0+G3etdm7tM#JU$41n}N9lDTJl` zG7lE;5NHo!=YSNg`+ad$igBR~VG)gMZy71=q0jGket99hQPhM9&VxVdIX5)68X~8I z6|eWl{Z)&rH+YA`pUA7WBZ^J8$D7NF310yr%<&Y3;gkEogAlcX`jxvX-|szOV~+S` z0*?oTa(-0Y!8^6ClB$XxLiSoh_~rdhmX=5kgYZ!n3<0^u$JOJ_4+~J+=*5xR&Up6U zk691kH=MIhQXa(qQ|te;f5+t@q&8CdeXM!qxz+Zc>KL2xuVi)e#hXw;a_4T$W&Mg-w>r3Sb)$FKmi-$2)a3CRLP!0hA>&R9K!`2S<-8^h}G z|G&4@(!#Q9)zZmYwr$(CZ7(g`wq47%&2zF{tNv&E{;vDFADsv1+53FXn=i;U>W~FC z+=p8@W#w~!`xcD-)KmawN5DTuHbp6>N*o@VdR_`!7!t1uEh`$SSw1dtY&SZlzYR>Q zTxSQO$kqHhA;yVNiO-}NK)+|Y4ONYO92(dE=Dd3RHAVqZ)$oh5DV2uxi5X?0&<`lX zFk?7MMCzC+(AKC}a+1MJ%#{oGE1U4Aq74Byy$`=Y2-kPRUyYgr>wU062xh=tp6fD& z;XtRwNEmAZ4k6p;-;Z70_xBH8P}(Ms#l`0@L)BgzD}-xo4Z;x6j*4}pB6E_&?o-TK zctp{^OhJ-F%a^}HZu=yDC)OrCOCnWXS(YS)hOYDBF)uh+WLEDqK??Jmtf^dCn4i^0 zMb7)i1+2cNjC<=mXS`RAf9PXM-+rlqfaEc*vqg~C|9e{dkNoW=M?`rGJUyzv1zr@4 zog3JtFqu5gX&AV;LU^$@Le{eRk6b!W^&yrDN@6FUn?$BSQ-h)7 z3s=gMvKzHRy5?7PB?Hify1Gjl99hIQ;- zVaL!(fn5MSh`X?LxR|JW&*RyR%keMHcG%)W)uWG}>a*@|1ypcpNu&duTkUd^Xcr2r z7|ZK2KLsY+TU*uL&^T*@W0e>(=CcL1xsM+EGA_j><$JE>d&Y9xmdw>j_z8SS58v%S zYo7VyvuD$Fu`_qua#97(5u{Oj4sGfg0Aq`yK&aURlyitsG&F21O;Z}qlxXzrjwfyo zKQQMl!69pUTL`kn?)x~Qt7RZp1&R4d&P&3A1*bBc@hk!<3LghB5M4t3jtqEQ?MTEO zWFR0iE3@xH$1dr(B1l(99FvP%xjR8n_5nyvVuv^euG@(dmhu6y1aU~@F_7&t7Ex-7Xzts>O_3GUTkd6^1=dFWWQ;Q-fLxi_ytS;WpW%4K z4qlyf4QvJLyd~|Z5jJX`5b~Y&l~PVt&ecDF3akrOp_jsBM@NMc>K}%Y?gSdAd>%*Q zzHX)SeOC0zqSgPC?udl{-dx@GjvJ%nobto0Kpw9$b*K{U2FC}tsEdc#;F(36I*78b z6e^Jb`B{1@2uo3I8T1d{KF_m=r<~e z?_4YchmH`&kuY*Gq-?!~9!Cb$J)s7a5{2wv9|1(0g3>EX%1e`%pLZq_k10s?%ODV? zU37=0lxoT2)TERN@_eNaF#@ATv209Mkug zg0hq`Cxh!I;)qXhnmP}Nr*zY3>dD;gxThJYVpCiYkM3it`$f`H$I0Fg*Mnf1*Vd1 z*BNNPxJ+TF>b_Wt?7~D@Tif0l9o0ip)t=M|@L|Jd^T;+x9AO*j<{1i>rma>H<*?jG z^xKmfEn`>y-0>Rm((kDlKKlZ|7=I7|2}^)i%HW;yKib6=|IjUzSB|_0hs$aB?MwDs zLRH$yVN3s2@6>Z7;dKbF&ssJ?=NkuDZH?yPJ}k5XcaO1}94%`7*4G>vA`34!FN>%Q zU0R4{KB-FblyeHr?LZJqv=ABTVdfzR$Em8TZkg($3B90 z`rCB0&bkDaypnt!e1tA_tt1obP0X~veJ?dp?}SpWMkubFwpT(;A=WFg+A4}bNEDW{ zYgkHDMX)~;&kvwO4Qt~~Y7!jbT)S|7Btz+9a#t)cX!xFME2wgolMps%s=RNv0R7YZ z!)UpdvG~m}PY6W16!aIygeqTn^R1LE_o;ylpJ%pd`kxKU>jj}Q)^i9;Utb5wHyy-h zaCGm69=vXCJ5SbetGYen&DdwzLZsU74L4ij&bY?BhmBz*kA|%BGd8KVPtAJ_WQA!7 z^}WMjOt8`o7CB!6da2uOJW`p^{a>q%;D?0@2{?#jx5LW#wLFP40L=2{k_0{B{KJf5uIh_ys+W%FF zJWLt7=sfQ3I%DDi?se~;1|rQ(K7oPoHYm@}5Toe7oXE?CMhABv4e?Y^onQ+^j3nOt zr*j>qpqY$mBdLnzyopcPnD7AlKM3iHKgeV|8#>F0hVh7AR>bhlfk?R{FxaiDs@fYh zHR(Bv5nXo_TN9c-Dr@pnsJ8vmwsLW%A`~Q5S)7FwGLEY*=q>kYezlE8@zb=>Ew`|G zscE8{p!}6PN|PK3NB3eVqcdS-cwTJ8ImwW_-BdzO`2_(yF*}vS;0wCY3ejm{B@Uh5$mMS@g%cnK zm9F6F1)h9-OL34eXgd3>Fv$ZMU$l(&%oVkB{TJ*KD)>)Y0ugGZmO#{FBYpE)R%YF2 zjen`+uP3q3o9~}?Rj(Dy&fE56u$)Kh-|omT5K5*W?&enY^D{lEQb`=qly1qrQkvlQ zRRb&CL$rRSg?Xq}Pk8B(Yj(QiM#%}6N^=_-eXD(EDiOtxRp5lON~v_A2M(F_(>|4> z&AKg$wWY=lvTHPrzMcN3lr*(X*^xIKLDLlZoz|-rM)tUvl-W4Ie2o`v;N_mHUvz5#df{xg}V@seRi#TaJV9w}QEA{!*Nb5~q#5-o3oee_)-oO0e zn%LtXf1GsZ+xUi?>(QmxMP`Nb4t=L}38uC1n@-Xmovv_ufDj_7ACy>8Wd)K%nhvt7h$>o-t*W0=#viOgm3Gnyn9HxuUnh{Bx(=Ukp3#N@jN}8 z1KT%!>9ifs78+V><$If#nXF4t>}14*U77KIr=^hGs7eWq18;FwhZ@U1iBpPZJ)(Y` z;m>f*$gdeV@`+z2`P56r8I|QcZ^tMp;vSgGkf@2bRCAS~CTOw;& z^Q-eJT)?_haf}+mADt+9KuB59-(te!E75mNsWO_4K#9NWcBjLRxw~x3H0pL5+Pt*7o9t8DpcJY3^pxUHZ6&R)vZ|VPs7q`#B z3h_77TU}kwss2+(_vgs>y{`Kv_#de?`tAx__x6tNt=so@Q5C=K_$xlUL&_j&1}q!O z4z@o^jXYV#FuM&rA{UH1+DCi2I2t}GbmQQ{-%d!R3JQ9F>|Ekj7<*E6Fq}1wNXBcA zoDkWJ_Fx=C0IgJ3hm9Hh>tOBOH9m% z_LQ!Ia;$DQsdR_!Jf#!-P$QP;Z@$&5*BfkOtFhhcLo^R6ER@K<-;6`T zd~_+AldP+4rH$sfKNT}D$lzs@SUYBc*OUJVKC#K6Ev#?;%DTzW%>E-e)&6|$BLD{e z1B0vILCLR=vhTgsK1b0o+KzWKM}EonQpX>NNv7z@k$!RTYI%w}m&7@1D9c01Xn=tz zso30_MDG#vC8ZIO=(_MSO$hJs9fHH(ekJkmX?|w)Zqa}PEvr`*@KC4{ z@wTw4%mQfT5$wQvX>OoyZYtvka@T-l1)@Dj0Sm~1al~=Kdfg>1w zzl9*?&d}0IF+>tPa^`s47C?u<-22#Q`%J9`ml*ok&8l11?Bg$ z6h~8?u%d+dE67+MboIgb&{?$9;%WTSmBTie3>x|?)cZfDJ7|O=b6tSR>blx=ve(tY z+W{fh8;!2x^a8j8TPFNhlb#8)I*wl-HeK(JEvvKemVul5VMg1qMWo|Yo*F5W0M3@3 z1e3%#=f_XYG@OQbtxl9k-|j#HRUjqJ#yq%)^5NFIFn0J(tMB2qA7Isu9I(!TO3s_? z6|#!d;KeZLy`cXRlqZN>TL8f}k%%(h+`!?Fsca=px505KockSQARROwr+HYQ+1pdz ze@w4hH5Xf!VG*pY-9-etW@DBTX`gFh__Ig?BA%TBE~~CsqKYKqV3l zj~yfDP8Jb2&(E4aMeiIe`?#Z7jjUX9UB&}&V9KnfXKH{i&ZA1+_6{Ju*sc9kNp$Mx z(SIe3>==B&ER-*)lscVBh`Uddm^m>{*EFaSt_KZ+IO9~3iej&>!b%DHHjj?J`tQ7w z^H1ka>l5F?dMNL~V)36pH&s5m|1^5D+-5M}qmsMMrET4TxnLsbP9@Fi+FE)>46=ZR zq#IHhN(QR%4D>`}yD(5MsAr~Qo0w7z&W z2jg&d-Q);0Kx!kNo{|sqDiH7XizB|}=QIS|xu2FVP=G!K=ZfaU-mnomVh||s+zY>4 zVYxVy(DzxY=3P05d3;}xn`c*U&U{%zA&}}5M^mMkl_9M;z13`Ucpz6t)cTudl0l61 zSAbC_&X8T^NL$J!X8vN0gxbhIQk~gIx@lFy6n12+trzW6CKCnx_G92$f z8l%J$o7Wbrh-=IlNr*SY)+wM?BCGeO1P$YvvN+nw+@CRo+F6jpO?Nv6`O z(r+cG+OjvKQYp_pn(;lPz*uDp82~zMQT(Omi)~CTL=(k$)(yD73~f9HW3}xE^jaSO zuA(_;5d{SHDEcG)H=nZF&v_1?!PeVaY(96zI&YG?_XF84sC^DGGTH2+xP5ZNwGH@9 z96v}Bz1?CHMkgf~YlGs#uY$3^o2paf^fH&PuFQEl)yv%Ar`6qguLCWjhwDOS&kp$+8 z1>Q>!)_>g3SJ&@Y;2TtWUyI=2f!Grk{3YV-PRWodscu+iV6#EP z?1vq~oAmBmLS4^)16qq+M$7Au=UZO4%gc?2E#J4pnLg%AzA>Phz?4}ABHee?2#W=C z75zAL0S~%Rrrk|5Y-O`0rv-{#YWBWkR!-y45ZUlArH;lEeCtF=PstU%C5YxFzF-u!`yx5R70@Wi5%ka9syd0;K43yljgj>ZdSr6%g+xgQ?WkJB|& zY-iurqt6N4;pi^~|0HA?|5GO$@r$nm9nO&47EO63-P$dJH-CiLPY3VM+1_WkTh}*S z@N=b=o_qT(`;Y@GO*ZTFYO_%=eP40YhmzZkTKoY*Ni#F^iYoZkLId&ffcRLmvVae% zqa!Kz-y*+RS*jpl1&c1;Up>GxVD1+{W5`LvBgb)LCu-q>zB%hm7JMbb2wPhQBFE{m z$g7|heVTgqT&~hc9H@#M92K!T&X)D0`JSi<_58=1P{<{!x0n=WAQYx$9aFIX~tZ%fhCw zc>rT=JLZb)_@ny-(Si@R;}+I@MR-u+936f_EH6KHB|}CTPpjs=ZNpR;nupKl%*7eD z9s2In#a&Iy3?96&kFh4cY`vblr;m1NhZiA%{53??xcRWjr?VxR%#l;)8(&7$4Pj2WehmUs z?oClh4}aeL!l$r5clmnW!htfmuUCL3u`Hdh`< zLDu0f_i>*%l?}|>l&B!>+5hBni>xNexN55bepNUl<_V5$u)IsW8iCgWqW=~+S_`+pYQ_-oBfOR?XRWGwjJ56yK~gYi9V-&uo7KY42gT`=X%bbn1mb! z=ZXEhB~z&FqZlCye1_wg(UI!DW;x{gUl9GMteI+tZPogDsbQ2XMrBIkKTfIac3WOW zwOZmlRh;=BbH`%|b;6Sqx$j_0;jOC|)E6jQor5$rpAKR0?C)>Q%Y1qnzHbUgqextO zYA%|cOx&qiF>|6YU@zxt=qFrNzgZF`X(ib|p7`|z=6Pw9#2Q!g z=3AFav#^oE1rS2PfKdz+j&KFP?2m$gHgQW?pnMO8c`_vFiC6iMa#O4Ck5?PorN{`t zm>QNIJAo)flOf*|e~ZPZIjYr#Pos!5FgJ z4YDgHPr`)&93exf|KxSd{Zm8G${iPG`fdlimcV|GhKT>>_=Bk8?6;=o?gQ?QT7FSP zYs!@*PXd$3wh*h3~PlN7*-eIR3Ra33k}j9sDy+v{m6LsHJfzE0ISbcd%J6mf$x`@81-AZgA)fI`|V%N-GV27qz=Q5EP_j50x6b1|FBEAy^J{HW9`gQ$@NS0 znF*EWh?gn-$~45{+f#TOSu!rMGzRm7#+l1Yg1WoH*TJYc=;xj$o?mvYWl#u}6)JHd zPcnKC^d*>A=nhfG?&wFPcY&m}!Q=)k>BBLI`!CkKt#^Z`uP`hyMXpAgrHipg-B9m3 zYa^s^rr(%?p&XGO?>wRtEE5w)7&8eBlAtGx@1P8^VfpQifeaQ_CfBv(A}1ZSFPRqE zz&>1*tB^>|u0|H3neDEz!~AWqkD!C4OMthl(MRIswsQt{E|>cS<#P5 zwAjDq_xR2Es|+vIi>Dl;45;ZLKlUrut>=Enk>OKtt{m`>sL@K;_b(%-$ht(SCqLiGAo>?e*9#9tpQ^wo8A-E z2t90EQ;(0Dq|S2okPjskTEr$mTt{$Xu;^WxEf0^uh!|0((`IH~vR}Wat#wnFaP+X< zPlF*+e~_WJpw0aDxAQOgN1aQiNJ$0LoWL(L=BWhfeR#_U=%OU-%44cL>?Ivu|I8*4gjMF$&&iOagg=f*nk zR_DyHyJ4KfEx1@W#&E|9uh$!iL065I4YiTS51V&g0-_;E3*Cyi8(%9Om_8SH2yoQ7 z604DpE+IQ&`Ba8drl66^W&-KWdW*g>0GIkaq(0JU9#9#nmW2h~f&84D(Qj}xVrI-P zguatcc>EeM8YkEI>UCGv$Z67kt(Cc1p%(uo)&w0EhV=Lm+46#V4mAzYXZSTCoL%7# zKeg^}pwYM!z$@>)UqJ=U(cr1u)_bUZ)9s&zy99Wuh#~$5r?`jarKEeFmwg0pNdhKq zvdNM21_q%J`U1kBaRu0FxZ%G=3|M`kvr@Q6l8fvq$!6(ZD9~0)k}nST9p{AUYcq^gWR)@{Xx>lWkbDvlYbFCW;-!nQ4MvDTi&QMP(K1 zggpF>yAb5Xu_*+JeYtflf9o=mEK}u|N>SH#mJlY3$ZvsOtsXwafr2YaN*b}Okka*@ z74p?9trC{R-+Fgz6s5ncj@?Pdh_Po33Vod6;AOb^Q%>x$WbH=QAyJt3V_@IeOw@ZQ zS2j6c=@mg0GS&g4-jYTJhX+0JLj@yODS&JS=N253wb(oP;@%Co`q>^+kHwzMy?*d@L}xLzKjwDd6$tV+ej$G_w+Bv z;m+BS3KTVh%XQd5eWBh2T2qVFZ*2h)te$Mc77nqkWH857WyWP2y+jAc^6+1t z*aRT^YEMGFr5i7fJ7@W3MtrDi#7FPR;DH(g!G^P|V<2|!4-(=iC^B#i0EweSgWNvUVWbvqP9bI)q!7_A!3E-DTXBT zXESBqK20CiG}yoOSne8eWW(Fi3UCQT0csv*}j% z-GUO)5^r5W9De~p0o%pwNM^yPx>1s@4UMj;x(r6MD*lbqH$2Ywu7ZV&ussNB6DFt? zT!6KkFd_oW@@K%k3VH0~Qbn3!=S-C#pGKVDuC(uJUOoC~OGsWl2Hx|!K8e@dLSx%P zd4~Wx6&WnFdAYHQ^Qdv1uyqDTLQR{(6r(Ng_vj83jSygV^gLr&Jo%Hm z#+B^L2Se{7G9U<4_G{^mi2F%Vx}*__cf@cpd4(9Rb9LsfZRew7`{c#b2Cv%&D|d%? z^pC$DZLKWqePeOoZ3&oX3ry@06<379m|FMmvB#$|cs@8MWmsc|lZmvgn^(fS{A915uF z>`)PPd+~i{T@D8T2CsS?fs~ZiZu+NKjZrC*>*q(!Tt+A_Iv!Y z3Cp<{uqLsg`CI)Ns~Ojhj)T}aW*busChQ=QaPD@`$;W)RaX3LGs|f6BWZlsPQpq94 z6?YQ5ffCud_lVi)adlBysCDdSn8rb^SU`7&$`qH9@rO+6HpYSstLz*Lh6e>Q;I-dO zX`xCWJm8x4j81h!uu*H`{BKY2RsP>?iWWl3QyigR>UM?hnaTHr{Ox4y?d-n_6&N%1 zo@VhVv)kMEXpc;t{qD4&BeWkVn2o)q#qynd6rl(ChA%=;IDmpVTV#3D(Y*PJlnjxG{k zO0`hCMZ4Y4=AT7|5=~i&@-%umhJd%BhKoHxhhA7zW0fqZ=obm7xsj zw9AlEE-Ug-7M!~aJBXDvv^nFsi?Ujfsu}iNY}lM6ak)DCSyoQ3hh?!yX(&=7IzOMJ zIm(jyZ%YYcc2@p;`|@@%uSm)yJ4&Hm<^78gGoVy}y^LEc!6f2qdN2`?y^-ll`*K4o z3vG^Aw_n>`kPAU zb)Rwa7c43IAHYoOS+7W64`(PY%d0Q`(3SU)iYlv3^oHrjyH=<1-0M3DzMMpM%(-N2g??rjIg4m8 zF6GfzFH3}wS0^GLEA5*Gg>BC;N`zW?&m@J^)U7hzbc}eW^^M|xR6ix7Jl7SWRQh3R zB_LnF`-OI;Z80cm=fi*w6J*x%kEbpbF!!O;8{qio4@bWiQ45wRA76Ab%WRxOky55D z(GlpmxWe}`(?FJH@d6wB#;v&^qteoH5FDMLO7W`v*tNwa?6!q!)^yT+4ya+g=S;?qPmmB;{3U1=(IH3J&E{JihEW1_^A(% z;=r%3-YB{>D#>_4qEcS3`V%%*1#6}KcOgp-zeeJQ(cfqU%k6c_(gKS+mnt_0C%C^> zO5_s7@JpruM2T|;5$w`IM^ZX}FK7R`;kHWUNvCSx4sQVVyn27{-?Sm@vH#e0mA7{A$H6Zlpw_IHJdI2Rim|Jq1E zzD+-4&|I|&BVXvm18G%q`efdC2S9;5CIHP>;|I=RttIzrgzKS9p?gKD^o+H+=gNL4 z*J{~jHXe;yV#~0pEP#0Xy@q71#^}Zb_y0d~vC58nY_r8aqvT#kbgxqvui5`yjU^%e z#!u%@TWGe^fi_`_t?4*i+r+-D3CQ3%dxo-5jnyPXj$L-zm>gmKtnR3TjQYjgd>khh zwI!~N$N2ao`*X)lu+&fe=e%$J@STnv-0@Z7RkCHdYkStKkh-&}A1Wl!ijDYl-e9P{ z87#;gqB)XUkHJw=d_q$egIoRKcAX>arO_*5ElazlA#JMcr}oqNooTGM^sI@iLhhOH zmVe=WQU=*y{^d!&#H8Xh145(xunn)>aGoEJ9i63>Nmgne5>p)i8ZSmL=kWV*^LS^k z0mmfyogRI)#InbmYFVoIYJ1kF`cZM;EciWm^pqUsbW2iIZbljlU>-?rpll+rqlD=u z0%5?eamr99N$x4kxnWj~7=~rh8<)YmTxPepS$&CZ1>)gy47NUT{LKg5p8SrRS~WH$ z(8IOyFStDIKia!-us)WU*x~a@RpCJM)=o$l2y{wmLnG zN7fI~TR8#}^*1GsQMve8Xh+T@RAu5OoI|cg&7rxko*wV=CRSHlK?(V8!K(Yv;&39J2L6Up|EsFR{ASl1ck9k1dE4CXCdR z`DdW_{?J5MFFdJ#sG~6nWABkO;*@Hz31OR?QcSn6^2?*1P<`c{SCS%12$%iDIFA;i zJm#%Yx`=b4QmZqmWTm;hI&m4h`|vP!Huxs(!V=V-v_J-`=$F=dV_?8+o+wj2yQ_oF ziA{gVa~D@ws>O$JhaY+0+RPkMcUg4aedjq)xyveymnr6?T7ePz@lidBc+D@b*N-^Q z@6Zh$`67lNKk1`57FLAnc#tMcZp+H+J-B)qT@5rW8&P(w2}in_%h z#xon)iR0G!w2@jZYcvR3#Qc{Dr5#8XID^Jr!H zGO4Xxi_)eI`!)bt{B?sfk~MuGqBZr^gB{pnnQ4s#;5{u3vZPZ7gi;ec8|b!eT1yv$ zZ;E4>R3@uK&Si$1>nhE?mCdgZRfQji4BGbQdFL!`!{`s)KpQMl_S9)ZEY9WmZJMX- zgXVlKT0FXeh#pr7`@o>$R^X;yMYnyYsMn=t4JU-)&XrBw;t`5Amx%XRl4_a;x{{(c zZXsW13Ug5hYE^RJMo+E{(K!{DGW>Kz{WAzcWx;V=(qB_Yhs;@5;}por#zkjUf+d83 zGYw1fWvmIw*zmXM#P3=nNq@Ii?um=F7j3Va&esmKXp9(Z+mg*Ec3WLh?mk4cPi+o| zDv0M$bR;PdCL;9E<6z_1;X1VV_$aqiU~H?k}v#rmPX!m`Tt@gvHhxfy# z;2vtNSqqAwpkSObAnw{MsuClvvHWlq%!>AF?4sM6msZACcC$Zd7Z{zv)wtcPNxn{S zI9=o=Im|grYTiP$i(p*G%%Lh0ku@uS<00xwQpqY&B1Oz2UaSi zFx7A#-j3l(<6H)8`dQ1RsIPClMU3n|7yDQZ_GnGzN|t{8ieA4pdzJF6=Cn4?aqM3H ztAQ6G@=c;cz*w(Voe2&!8fv%g%)Na!_s3q2UR5f^1838MPp7R84)-vl+d*zq(|hSi zWzA9ADQ{}>g}pJLRmIX1qLI?2O39ja+k>{5lkUvHmmaKZoH(Wb!f_l_7i`Qqg&@WY zEmMF3EbB6`*-R;GtE~^&Jn3>>@4t6mag>Q1s%9AxJXl6AM~;N9&m2fXS-5^7r|YyI z+tD$7Y|V;jbx2Wt`}rA52pn=rO363{4E3Y|+3wR|-&f^(mvq0U+`kXrO7{=b zLxtx1(JKjbK7&&DKw>VI4l^F5aiNXU27QGl|4eJ<`H{^EQ>!kT4}fR7G6&F5IXW3SoC#cXHhd;0s|3!=;S2&!wj1eT_m$b8qHWv@jKjoAr@p zk+hLDR@P-5JWsDevoGvz(!3}(@YCuN!39=zQ_@|S_;?SgNEj-rkre4G0D+J27eLlSOb z@4bX$s0g6(JHq3HJ>Rwx3}jIoK0ekZ0viu77_LW)#|)qQgm$yK*;i@~FSP4C_vzMO zlc<8jgMMjaGlwtVHDLAJ@7+A)nWbTN3DfAN{(oVr`=6z17} zQPRlMnn^6Snb8C^a9(uLy;L`{r+ZErT=Y1_S5 zg><^X>R`l}{WDiMakwsbI0UePTQ8FDEVx)1Wa;V&Q0YvhYRPN2Y6uLxp0M{62vh1v zr8*w@5TP&JZc)|zsTwclZb8UdRjUJ(mxlr?o zacx>f=j?9lQ4zQM%dnFKPP(%G+~$Y<(wc}KWtGgR2T1W?8WHy8)6z*mMkv2yYJv)< zFwo#B?XU|%fl?1Z_;Al|r8DiI{~?O4t3y;J5PEMnaQ|6 z4Lk9$Yj7^`HVd}GHMbKEJZQbV^akO&KWPA7fh0xCD#h?smtLFPb!XF+sIx4q3l8oN z<$8#0A_44rn-){kX`%$h*-gYY-Xo-CAV1N{zuDyoC|3r-@oEX@;`?IDn z>Nfclep+`&`M8&}Cerlj;2PvvZaONiLat`UJBO-~7_E(Cx3}4?=pBId5S6w3`Quz8k4B1Y7m8{$jZ^|i^%>U?|E z=4i(oeN{_u$JgkB9%D`JrTOg}=A1ZhWsTPtu0t+h9Baf-c}Hc(!*ZfPOD|HUZRD5R zqOJkAI;^mV0?$Iwy~^@k$UG49R^>a0`veb7Cvi0jQhIr}}BoNfz{0TG=H{uA&vThENKTCYF1#tG&#Fsy`) z+C@mHgj1I@V_JN6jM}tlLQBXkJ=(w~N8%PHqrbk$`VTxx{U6`4(mT=Vi#S~?Yuhw5&$BJ?sK zM>gddUv-@8VDi{aug6-h_5s^RDOqr7wWUl8Y&4|=sAJH19^LR>md12HoYiko>+O^- zm0f*V!vK2_Olb1fzyJ16v0_%NmMBD_B(6(nEF;xm4MLW$O0wAK#~@S3!s?QiXISzn z%kaG2TEQ4{#9>aD+m1q8<I2X&Ru$2D3^&@$(Q$Mw}XX3=SXaS zhLh5?S<%rJRk2pi>XHFB0f+$a+}>H{325RtDB!{u%=Ou;sr^_%9Jr2^J=2jdhS9)rPlg^lpf z==X;&>R}d8bWA|oK}9EM>sPI`ApL0`M6HLMvXQsr>dE**i(W6ju$lL?x7Rc62G&%{ zgfN74V3tj#`xM8s%#>3z4im)$mqd>iyYw-FC7fj9?99hA8d^0kYFi;9o(zzhY-4X} z7N9#GT8Ct=5@4$h?G0@t*PG!gJC|cINJ#*Yy`A>v$-ehzd-g23e40Pv*lepRK5xr- zj@G?e6Zpw_DEFXESV%iMz+12%$U2t+lUE!-J4J$n9Mv)N8Yo4TG8Sn#4bB4CU&lXw z5h#|l%o>W}ItbNyx_Eyi&(1pg@v%4roCz-Qy8aN_cHdMX*{rqQBn5^d4#ka(42LKf z#SO@jMp7G3R8?n2w2G9sm9Uq1ltNX|BhEW)yH($SN;#-PyP0UoowB%<0H8Z4OKwHeVU zHqeA#9d-TOwj{apxe!(&VyO1D&4pCu0neqn)u8?QqwbeV8c4d0CgN&c_6f1Qia;zRW+98zgcu2 zFDW~kZ)B2p1zcxj63@`?0?)jqHbzvQ+Y&Lh?t_uiO9hYaQ3t5HT~Av(YASbAPeaTL z7chCYICR%8otet$IneNm?OiUfLJ(tKK6s~(%u;VM6D-yk+^hyVfl;ePGyJA zHM(=>S`q_{!2HzBvKC4zmm-O0kKV-6C2rx8nHy_UUnu;Cti9ECt=33A{Z4KOzq`*d z!GJactsmaOYkoJr)CUdpDZaIz${*B{nrEziw;1T|h|VO%$H?oNA53{BJPS={gJ$|yeJulS zn1aQ4_{k0Qkd0+?bg>d>W6WfpV_DNY7l-pxryAQDf54$T4r!soXGB0c{tlQaO|xX) zwO7^hIPZSnj>zm~*K1m^TzH%iH0^fXc%JZ8uD)3DdK`B986zu{#o~)x4zElsnW%!f zjFu>I69Z3K*wgu$Gk-y}H7#GxTH!DQJucZ+u6@HOA8++`UHT!^7I-I2sdP-kbYxSE z_Ge!ntGe9um8q0E6~LG3^3>C#^^)3y|L&1R`B|V+)#Z97Uy1gv*aV_{)FW-ZeuMc? z>Q?ok;BAkC;_?)cK?PpJLnTS!CS_!f2V9B8B5OVvrH(GS~4(xSzoxeq8FV{H_b)OQl zvoX3{+A*(ke+f;?)iN%@o;OyvZ#^6Os1gO9;!{rM)5OdQFB7s ztDl5QbPqD3@utcYM$blTSLsm6g^sFanx9p zqo!l7c?!`gYA%YJhmg>aAP6GK-RZgau66HP_w)Vo?-y%zy?gIx{O#X<_Vd2c^lcSU zL|o~=%%0CZ!JY1^aqFPH`WuU+*1Bo;^OBCgOY?S2*eI*~kN;GxxVx_BdS(zU#`mVC z)5aCnyp#QAv*8>^K?-ROz9S1X<)QyyG8`~vn66)W;i{+=s!`>6)%jByQXg0-q`ziO&a{Ad37iQ)L2 z0?tBD>AQeby|Cpl^Nh8&$n_kzm%%Japn@0N8c#1Kl}?s&acvK6j2ft$ErbqsQupVY z0~S8dfmdOIwR^Pf?YwV@ie}pLuNDTc`=h=Re_|Iu!*lN?tn|r4({CQJ(b|X%xizJp zoa2J#`1zNH@KuvWRY!fy=yEJM=Ss<6eD!56MVF}0zHgTn2}-#-S#Pvpqx^Q-3~^uJ zsix)Ok~j0447%h;l{Q^fGF;V1!S7@Q-C4*im5sG=RBsmXlujldXr8FRrbq*#q+6mR7Z!7 zg2Iin zQbo&G*Q_`Thd=ML^Uqb5cf~e29a`n@O>A08&f#Zx1|c1A_PtP$;+SL@yR?)ScxceR zCPP0$p$U`Dtq&nFT~)MeaDe|vu{NjBl;6tdPxIT`F*NM?^CCLkJ(NU)M}mFikQ>AK zTu3pWHv{?BKaUD@RH|lS{Anc&FdQIywygoN}hLCgpmeUxD|hF?XHd#{O|FWR8J$B0AZ@53j#Tg!dIG$LScK z661ejG+5Yvqw%h4Ebm?CH{9mENGN;5ciQHxXBMe< zbfllGozvn2qhK^zCK(;%+#Uyt0Qbb`1C1vWDjshsPvv3>F9MNIsjS0()KJ6wI;x~O zx_{~rN-%z(AN?k(UL7x-s6C(Y8>VS|D5b{fafb0UzV;#~o(q{Thx~OoUvBDiqQXvy zFhW1U;L)Rm)%XyYs2GQVqG;kPp*PAfb#*>_orF(IBb{CjAy!=ip88C%24xNNSU`rS z$MK&6avM$3O&}_wLP>`HMr-G6HvI0D|zBA zL0B&`l{MiFNboN^Cg~HB{dSYYwry;qAo{T~8`QDA(@=dAb+FaWDreNIe*g){e-L=T zSl`*4;^;-9@i(?Ru4D%c`)5H=1_NO0tQRE|m3=1p7kqaHYr=C-O1QR?q!Sw*6BE<4 z->O7=UaA7@5ET!Qw>D2#;ZidaRNq81SRb9M*v3s;Tfn{hKVMoBfS|-~*G5TtNp*E+ z(sZr5<|%x*y)bx;51FIX*{pkkQn7HbD5KVNyjMF1esJPPwTStDGUjQ1VZ$lCEIqoi zY}pn&I25RBAIuLn(h$6s<>hn#@s4ax`Dr^e7iaK?zAf%0k~#Tn#ssL*NzO zx-s}ZQ}gPU%^^Rb0kKP5BgdD|FD3zQUYxxzSpllHxC&L#h4-PoWz1xS288x3ZW2+p zpT8NDMRl}*4R>}XGOhsR z*`6bK9FaRN|D_T04z{-YL&pUEptY6GDyC)|>w|NJ0RPmobiW=X_M8dm&z1B4sR| zCotuD?Hm-|{A)cOK_RMHdbGIHz75lN$#CT#;`%e`<5tBC>YdHP&DV}4e4kIRhGTEb zvV9RLjE?Emh8dyORA(AAjzt(tCx_7v4KpB>Hjq6^MC!-M%H}03($&-Mt=V(zwLyPY z2$z{+2#6KP*Dl`jc!avMaXU!5+)XDINS2*R8IFnDVxf$QR*zweWc7>~9%Y+Xa%^An z)#k0z4Bh4%Eai67CvSz#ZgEz)mTYxt;Mz*B(Fp2PN%xUeXH{5SIjzcDomLW5BZ z58501u}HQ6hFb5JOU2bI(bqpY__(R8dUtF)y;2E(s?d|AH{!BVeUzQ*)k&67m=}OL z#Qz4-gF-iM-&<&1-Osvie(h4cw$CWr5?E-x?~H6bF3<-F@am{C3VTwCX#IPYv2&|A z1ZDq3AkKI`(KQdKVapTn%m)5Tcz1cI@P4%yb|ONf@oI3MCkJHv2etX!JsFs?w`@(y zEi5Oi00IOAp9@_$O-E!HOKqIr8&@L1_xAtQR~zWtIx)u>m(=@1&}2~)WXizf;IxVA zPMzgU((G2=!oj8no$*6Y0aVqT!ZDUg5sFT!`OIIs8h*ZKg%j$zQphb{2oj}SCBWE< zf+p+#%mTd+|LQs(xQtgS00(15F*|n!fWxQr?Kl=M*7fi{5bqjd3+RgTm~R|qrU&~y zAcpCz8ohv(jYCscdnzKsp0QA0Q!B3CieInHbMs@``CYEIV^}2t4H4-@*^OI zYn*r|TsY*7FFP$1o_r6?oj)RokT!&& zNw;CtEY;V&R{%n$!)JVOmJJ>Ye5tyHDpTo(DvQ7VF3096P>>?*D1Hekm<|sbc?w4! zy`dTpu|NZ%0Mv4h3ge#+&$A{K7Fcj7mlzGO2(SVCnEx!ICq9Ar=Dk=w7s-ftzg z$(1<_F0AgzF0pzV8Z)iQ{!n-DFXD$I;+|3{V?I=a`oo$aeQ%qCH7E;Bhfx7)b-}`5 zoCedH$@;Qvo+k=Yv;eHR&jf%Ex`$etwjKANR``CvOH0_gP$i0bPHAC3UeeXLU+Xg% z^9YRjvmnLJ&Q4g-eSZI?AE6O`@IkR^<|DM7Y*dg5BT;+K+oPP&@* zG*;OpSJBscexzb?HsB7!ZACc^?hAb8*WyBIxR5K|X{=81u`1!`B@w1Wh1`|_U$MwZ zl1+g(2eh~X@O*pvVW&pBJ2m3>5{D!uumx;@QeE~>Oc%OD`tU2c^P@%vsU~Oe5cDW# zfxmrOUJ1n*k}2R$QnGlS{g@-e5hQYQ0W;&h7)OJ_sOA06^dC>7fi#mL)W}>R{>$+x zhQ&Ip9d69IHNo5~gBrv0p~G$bVYv3=sgEj9_<2ISYC2|vYo;~ zk7}HhCkOED0W;QBiq)*Bz)>GVZ%OQ zEltIgF8N&gO76i|t@Dg$4JJ@Hwiw_WxxH1weYQ@j288!ggmig_z&kq*Tg8QFbWPsO=UBn0-6A%33netFY# zaNuAS&`HstlCz@1?t+b8wtf;}c_dFk%%WxbL699YACB9J#*tnl_4W0;&ne9x9ZtFp z*hprxLTeQ87TR$Z0c?0c!!4$h@Kf?zpn4FB94e8&UL?7pD7ykohcZu|tX+bh{^8{q! zOarz6{)GhPxmo`nwMP2NWqZ?8cqse{6G$fA%FzdOHpR`GmH+eM7+i)pawR?*+hZ#G7>5;>&OeEKSo zzWazxk+!)>aZ|^uz>mJlr(ssaoLiqlP>&WE4lk)XSS29Pdkew{O~LL|)(by>5a>AZ zg#+K+&CwGXpQV8!Or>vx&>QLNjv&cx+sgppSc>4$c)~&pJs*ob&&8F5KbI%){>ob4 znfH)FPqwROZ1l)T^#ShYBI7t~^CY^VAv?e)tXq^!OxE*RsKlw~vLLnZE3gsp%8wq#j@fp+MYZ zW1)sw$SUUhG?GzeVn(8g8UuwabVnY^hWt_vnp8ZI;L@RW@kg z91zR~4Nj?&Ozq_{$93|83I72Gt}U}E z)Ak$Y!yMKlY$(p>vFDS7-zDLhIL4k0Li5qp&295b$?;7n8m?`)&B^(wW3(r7TzMwRA&O<{fH2hb%tn)s>$shJ%%y%UHV%iZZVC|BRY7y(Q6 zjLFb&RE_;ZnK0}_5fPEM8XRZ9GO4y4;g#G;!dik{alGex9Mf$=KHziFZh9}g0Nm)1 z{18DT9Xd^761}(hIq$wW07-FhS9v?vf6q!++$7h>1O{H6I-ZJ(Y@kH~MjiMo^UUGr zJIIDP7zh0iU-Ev>6Sy5Ghl4Jb?-gf7u<6+MPh8H$IIec7f_Op&y>zml97@tZ+i+db=Z;s#Nuox7waPiK9cU8g# z|5Skz9<&B|1P1;l-F)yd6&^JGH28%Nbel;gb7#zu+Yc97Y5mFP&vR7}%dV!du7N06 z%&0HJ3m2OC?e_%|Yjcj~6Q!##mbclU;sy|LG8pG&ab~mNgmyj`7Z{Qe36##pr@64K4zeN3fp$o&Lmzhl~YB`w00*oNwiNWv$9WM6av*b4I&*NVk8`J_t5 zjh79_;?)W3LiDZWO@=wps5k+vGz`vyUvN@0q9X59dn5EYY%PE~g7qGg6VW{V>0QaW zf#dz^$dM!z*APp`M~Wqa@tK#gw}9Dx{gzXmTfF{mbEGDRttePaKuBD;o^H-}sr1uJ z-t5M;LsJdH80l6GQS78I^nQzZsv&&KWbD@?!YG)H871Kq*1(^b<4iZdH^T~*L%V94 zzI&M-e_Mc0A6UGo#seP7yr_!Y)Uyeld)P?t{I<6A*#bL+>rQ4>7G+u;W3p!@h&*e2 z-3ycfK7qT&bs?&)V}I3YFgA>dYwRY#f7RFWUZFHf#7{iCS-G(cs_%LE#--K^gF_4(N01IGt`-8&vt)*lu%rd^_72 zwkm>ZatVG2yhUc7zXCpWp=gCwVfgq~|IMeg?ZJUEC@~E@Ly49fJG11TN7d1L#-r?yaGN&<{`Rk$8XuXPLRhJQ`R3F*XqaiaaBkD<1;Ap`Jt_?bJwVPF#v`A-8j` zpEhi-S7Xan2wu;yKXD7nPy>KHAG9`0K@q027V3kCJ1cbJ#n?QB!D1Q4;)T&BC+D_2 zuMJtY7VVT5s~zSGU7FueF-f4AK<7SPwBMe%;&!K9T^C)N5pv40aa^Nmtr?n^7m(oT+XoMWxcVLQZ z1jNM^I4Sdv(CuljyW&8{1OBYqp18&qol|D&P!(7yaD}-S?kABocHR;^!Uzd$LeB>4 zGBZ=XK_DfA9@UQ7iAyMH#9pC!yW3MMucm8DS4ag!2OehmZ54?t^oVz&Hm-^uJgYOZHCm;ZICUX{-To=&9)vN|L)f*}* zQ{|79KCpI_bAe%1fOiy2B*G%2BJBo2hMY$&#!kb_XDLb1r>R6}Tpx802zmxQrWT@G6hpzV9xf|Of4zT$<-?f^;FK9Z{fN6%M=^ib`w{4abV zNe2*!!op!kpaeD_!01-xxO^!-g-0~tKYc6%DnQ!{X%h!NgW=MN(cJy%QZeIMzPGryCxxyxk2O({? z)xu(3`zNuEr+<00$LgS|n6`-3I3S8}qOE}0LX1H6IunO;gDGl+s>>>Y|J-bj;4@{x zod=dHer0$&-B1$Vpdbw+%^I6pBd09s)SW20tLBTpIKrFD)e>e24QDaO04*4^Ic-$o zVM|7L32;{ckUZNvsI^Jj8YWO?S{2)4n`DkgOOJquy?l8N1z<#DlpC z%YcMIqT02#A)= z#tDu0UUPZ(>?^!h-kD!>7ElRC0`37xi5K1%*Ag5&^CB-VPuX>q&ujZ7UJc*ZW3yjG zxhWV}0dzmlZ1@X~lwlNGA~1MP!Ef&mCunRO+ABy0aV-xp6SJ-fsp+y<=jilhp4Tcj zZ+q5dU)8j0%2*yyLrMP4x){hzmCB78gSjB;9P0g3@`N87$E%EQEVj=!@b#htF3vw(2cC z+6Z$LjrZHC!4x9GI+LX`J0~Y9Rq!A6 z1bs$a=^L-+7*codv)xwuD;PVpifIb#EHY5v{X$e$2vQcdI5|}z@aPJg=QEIz9r-DS zl-x12if(|Ub>eP*(lzFqya<#2B&4#aC?GYKSH=Ef1@&~O$FjK0l{_RdoP|Ak?%cVq_2Q~%pJ5fk zEP2?H{JO^~q8XBD**xbc%ey) z$5+^HgG(XkQ9+6>`}+E?bTn^-0anY@viIwm?>o^$XG7xBC1X>aa|8i{!kMST{kLU8 zWoLHEPTUG_W)?HDIJ0R(eiV;`xXY@9U`{~+(D1V+6wD130p=QRJ}Qt{sdB|yaPTjW z_0cY`i9UHOx*l&s%ZQT>92eq1gzCM}1vC9UXT4{=oq@5&c#(@0-KURMt%LXd#C+~= z-qAkk4Gp{kx;dE#e~jMO=ts^+-xp7lwBdHnZWlIrTfg%WAfpE3BY6_Np?01C=ehb1 zt1{p89V<;ucZWTa`&>JjT~#n-Eiy`Io;TkpBd7|rCn;TzclZjH60mtNsJ?lo| zTq}mB`{uiwT?SF#l_5cK=6ru_{$2UxWs)JF0_A|Vo4gI37$r~UP?zJRt*ASct|BGP zQ|pjmJm3T*zV?k=MYnG|C4)2m#{{A^XQI%h%W=KE+M2$I9HVX)Pc$=$a@LH->Z4@) z$oEqv)1=IQanAO#$PONwGJqjAn`P7)Xdn1a!o2{D?A^y~vZ;1T;|p(_wuT$s7q(xz zs|p_N5a&3BR03TTM8(8JgqgE43-Y!(;y?S&dBta1+eAfPulDVItxVfpW%@{31HVz5 zQysKdTBcz%wc`pxaPh0r*(I=BIUoP2QK3;son|AnRv{0TqQFl^c*=Hj2qmCLz86{i z7T=%6V1>j$V*`Y1evTbo9og8wWfXHQju!-YMYOSV6&idu(gd?|OrAjRViM-4STMWo zAFgcPB)*mnp+?dy_!0>%&()ta6+B6&iOAhjyZ~w*BS#&QrroEpkn#htJG_VX;vY^L z@(ISS_NR6C$qz>ZaM{bQ$LEmk@j1c!iS6VsExcN%zK0)HnDJ5ekKZwxeROCNs)SYy z;EMB?!RfktsWU2n#3f8LEuu-*NdT$^4H*!-m2Sz*=1mLxU%_v)MMXy0O@XMLj^**f z^^M7x`%Ux}zpedV?i?1lozTcLdG$Rj?)7|S2^SYa)tj#4zd7wUS2-7q2nr;%vt=54 zMcLcg-T2w0>+~{|!3xCoEWKYbGkW(vFV{=C@4|*@U0Yj^nVi@}5-wQ$w!v=mjdQmD z_>{zONMC8~a8Nht;XI?Z%lOPjIM)5~n#peEu^g(6RQ9c~1AzMtI?fV(mCtxbsCkk zd?sLVF%%rq`S*n`Hj_G@N2qed3&w&QWpGa~EGj12pNe>3EC7+?Kn$!sDZR1&!f)hq zgm~dUM%SwYw><&!DyK=C3-qT+!JF;6YV?KxKjHx|M=kfs55Z_`VJN${Gpc{vKR!jF z#tBlJSw+}{zG--GJ!fUpCJOPXG%YQDxR=ElpAer=U%Hr}um9=OiUT>~x8Zy>_h*0X z7}1^QebCN{kr&nzINdpXAhvtcD>78)oxRxJpDkB){vnHWnrLCzsA{6?r{`8fv5m>B?wN_#=r*!N0GW#e_(k0aphsm{X z-y)*4d;DL;Cv3ue*S<_7-LtpU=8Pu_@~a9&CB6dn+@y=S8LvPpuOJ&$pCL~1UX5n8 zT>_qfdOU9Pe%lv85>Tp?fkF=_W^ZGmVNBoSYoL4gqTr=iKpo8LT$CfDq9j1!qsj{H zGSa6N7ilVOp%8-G+S*!=yKpX7MFHkJz4c`aJl(gmw6ru96&aakT2uFrA)m!9g%l~m z<|B56P|qpOkedh&(W&TYmz6^Y`NP=H4vwy%kaIO*_h`i z?hhh$lfaFmYiKTbQ%r&`ZV<6TgS|*enXQ7;>N;SX@(|G4MMrZYlw|+ zr!GAaObSRN9p|LHL)0Cl)ZF!X;segGh&GMYk^3(vhctuj68!(ULGwzy+iF2gH+1}& z|7qQcakPvWA3E>rGfT$(qnG{-krHmZLaAR{8}b{fn=8>FXU|Y)rlW}3LFw_)u*6>R z1doO7L6M#Po3frWp__yUe+Lgyxr4u6RN%Q|W2Q$+B2>!ARF(L=sl)X4S8XEOeTvxa zbuVCW@i1`X_irnJc0TgdrTG2fc%l!|=MY^VGH<`ar`>-Y0rr34lZLoGfSwmCUIgwciCw|`py^h*b^P4F<$7u|Nd)%|61U` z7Wl6P{(o7ZLtvl5`kfl{pVetn2oU0$ua=pw!ymqmx9q(g!5`>`>wibis> zw{9rjx^Y87R`!;xYz(hd|Nk+-9pUiQ3HkpXaG;wS00#W_zgO^m>h9>{`-i*d|2; literal 0 HcmV?d00001 diff --git a/apps/docs/src/content.config.ts b/apps/docs/src/content.config.ts new file mode 100644 index 00000000..7fbcf2c3 --- /dev/null +++ b/apps/docs/src/content.config.ts @@ -0,0 +1,7 @@ +import { defineCollection } from "astro:content"; +import { docsLoader } from "@astrojs/starlight/loaders"; +import { docsSchema } from "@astrojs/starlight/schema"; + +export const collections = { + docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }), +}; diff --git a/apps/docs/src/content/docs/agent-integrations.mdx b/apps/docs/src/content/docs/agent-integrations.mdx new file mode 100644 index 00000000..c2f2e345 --- /dev/null +++ b/apps/docs/src/content/docs/agent-integrations.mdx @@ -0,0 +1,76 @@ +--- +title: Agent Integrations +description: Use Caplets with Codex, Claude, OpenCode, and Pi. +--- + +Caplets works with Codex, Claude, OpenCode, Pi, and other MCP clients. Code Mode is the +default surface for configured capabilities. + +## Codex + +Run setup: + +```sh +caplets setup +``` + +Manual local MCP config: + +```toml +[mcp_servers.caplets] +command = "caplets" +args = ["serve"] +``` + +## Claude + +Run setup: + +```sh +caplets setup +``` + +Manual setup uses Claude's MCP command: + +```sh +claude mcp add --transport stdio --scope user caplets -- caplets serve +``` + +## OpenCode + +OpenCode can use Caplets through MCP or the native OpenCode integration. Native mode exposes +`caplets__code_mode` for Code Mode, plus progressive or direct tools only when configured. + +Remote native usage: + +```sh +CAPLETS_MODE=remote CAPLETS_REMOTE_URL=https://caplets.example.com/caplets opencode +``` + +## Pi + +Pi can use Caplets through MCP or the native Pi integration. Native mode uses the same local +and remote selection rules as OpenCode. + +Remote native usage: + +```sh +CAPLETS_MODE=remote CAPLETS_REMOTE_URL=https://caplets.example.com/caplets pi +``` + +## Other MCP clients + +Use: + +```json +{ + "mcpServers": { + "caplets": { + "command": "caplets", + "args": ["serve"] + } + } +} +``` + +For remote-backed MCP, use `caplets attach` instead of `caplets serve`. diff --git a/apps/docs/src/content/docs/capabilities.mdx b/apps/docs/src/content/docs/capabilities.mdx new file mode 100644 index 00000000..92ac61a6 --- /dev/null +++ b/apps/docs/src/content/docs/capabilities.mdx @@ -0,0 +1,54 @@ +--- +title: Capabilities +description: Add capability sources for agents. +--- + +Caplets can wrap MCP servers, OpenAPI specs, GraphQL endpoints, simple HTTP APIs, curated +CLI commands, and shared Markdown Caplet files such as `CAPLET.md`. + +## Start with OSV + +OSV is public and does not need auth: + +```sh +npx caplets install spiritledsoftware/caplets osv +``` + +With a global install: + +```sh +caplets install spiritledsoftware/caplets osv +``` + +After installation, Code Mode exposes OSV as a typed capability handle instead of a flat +set of visible tools. + +## Add local sources + +Examples: + +```sh +caplets add mcp docs --command npx --arg -y --arg @upstash/context7-mcp +caplets add openapi users --spec ./openapi.json --base-url https://api.example.com +caplets add graphql catalog --endpoint-url https://api.example.com/graphql --schema ./schema.graphql +caplets add http status-api --base-url https://api.example.com --action get_status:GET:/status/{service} +caplets add cli repo-tools --repo . --include git,gh,package +``` + +Inspect from the CLI: + +```sh +caplets list +caplets inspect osv +caplets search-tools osv vulnerability +caplets get-tool osv query_package_version +caplets call-tool osv query_package_version --args '{"ecosystem":"npm","name":"react","version":"18.2.0"}' +``` + +## Capability shape + +Good Caplets are narrow and named by the job they help an agent do. Prefer a few focused +capabilities over one broad catch-all backend. + +Use [Configuration](/configuration/) when a capability should be shared through +`.caplets/config.json`. diff --git a/apps/docs/src/content/docs/changelog.mdx b/apps/docs/src/content/docs/changelog.mdx new file mode 100644 index 00000000..f33fb136 --- /dev/null +++ b/apps/docs/src/content/docs/changelog.mdx @@ -0,0 +1,118 @@ +--- +title: "Changelog" +description: "Public release notes for Caplets." +--- + +{/* */} + +GitHub releases: [github.com/spiritledsoftware/caplets/releases](https://github.com/spiritledsoftware/caplets/releases) + +## Unreleased + +### Major Changes + +- Breaking: Caplet progressive wrapper operation names now use `check`, `tools`, `describe_tool`, resource/prompt operation names without `list_`, and `name`/`args` fields instead of `tool`/`prompt`/`arguments`. Code Mode declarations now expose comprehensive Caplet handles with paginated discovery, result envelopes, resource/prompt methods, loose TypeScript diagnostics, and schema-derived `callSignature`. + +## 0.12.0 + +### Minor Changes + +- 0168746: Add project-first Caplet authoring with `caplets add`, make `caplets install` write to `./.caplets` by default, and load project Caplets without an explicit trust gate. + + Project Caplets now override global Caplets with source and shadowing information surfaced through `caplets list`. Use `-g` or `--global` with `caplets add` and `caplets install` to write to the user Caplets root. + +## 0.11.0 + +### Minor Changes + +- aa0c0b3: Add `cliTools` Caplet backends for typed, shell-free CLI actions plus `caplets author cli` for generating reviewable CLI Caplet manifests. + +## 0.10.0 + +### Minor Changes + +- 957e528: Add reproducible coding-agent benchmarks comparing direct MCP exposure with Caplets, including deterministic report checks and opt-in live Pi/OpenCode harnesses. +- 957e528: Add schema-aware `call_tool.fields` projection for MCP, OpenAPI, and HTTP-backed tools that expose output schemas. + +## 0.9.0 + +### Minor Changes + +- 5657a01: Support configured OAuth/OIDC client metadata URLs for MCP, OpenAPI, GraphQL, and HTTP auth configs. +- 5657a01: Default user config and OAuth token state locations now follow XDG conventions on Unix-like platforms and Windows platform conventions on Windows. + +## 0.8.0 + +### Minor Changes + +- 349459a: Add native HTTP actions for explicitly configured non-OpenAPI APIs. + +## 0.7.0 + +### Minor Changes + +- 359eba4: # Hot reload serve config + + Add default hot reload for `caplets serve`, including live config and Caplet file reconciliation without restarting the MCP process. + +### Patch Changes + +- 85bfe0c: Use the MCP SDK OAuth auth provider for remote OAuth MCP transports instead of precomputing static bearer headers, allowing SDK-managed refresh, resource metadata, and auth challenge handling. + +## 0.6.0 + +### Minor Changes + +- ad63f47: # CLI inspection and Caplet installation + + Add CLI inspection commands for version, configured Caplets, resolved config paths, and installing Caplets from a repo. + +## 0.5.2 + +### Patch Changes + +- 99bce4a: Fix MCP OAuth/OIDC token exchange for dynamically registered clients. + +## 0.5.1 + +### Patch Changes + +- bcd0dde: Fix MCP OAuth/OIDC login for configured public clients by including the client ID in the token exchange. + +## 0.5.0 + +### Minor Changes + +- 6e5ec50: Add native GraphQL Caplets with configured or auto-generated operations, OAuth/OIDC discovery for OpenAPI and GraphQL backends, and safer credential handling for discovered auth flows. + +## 0.4.0 + +### Minor Changes + +- 9c9f3e2: Add native OpenAPI-backed Caplets alongside MCP server backends. + + OpenAPI endpoint configs can now expose one generated Caplet tool per API spec, progressively disclose operations as tools, and execute HTTP calls through the existing `call_tool` flow. The implementation includes explicit OpenAPI auth configuration, safe spec loading, guarded request construction, generated schema updates, and documentation for `openapiEndpoints`. + +## 0.3.0 + +### Minor Changes + +- b924a7b: Add MCP-backed Markdown Caplet files with Caplet-first discovery operations. + +## 0.2.1 + +### Patch Changes + +- f936020: Load project config from `./.caplets/config.json` alongside user config, with project values taking precedence while preserving user-only servers. Fix OAuth login token exchange for clients with secret authentication, and clarify generated Caplets tool descriptions so downstream tool inputs are passed under `call_tool.arguments`. + +## 0.2.0 + +### Minor Changes + +- 0d4c5df: Add the Caplets configuration quickstart, generated JSON Schema support, top-level config options, and Commander-based CLI commands for init and OAuth auth management. + +## 0.1.0 + +### Minor Changes + +- 34da37a: Set up release automation with Changesets, Husky hooks, and GitHub Actions CI/release workflows. diff --git a/apps/docs/src/content/docs/code-mode.mdx b/apps/docs/src/content/docs/code-mode.mdx new file mode 100644 index 00000000..b3aeec74 --- /dev/null +++ b/apps/docs/src/content/docs/code-mode.mdx @@ -0,0 +1,64 @@ +--- +title: Code Mode +description: Use Caplets through the default typed agent surface. +--- + +Code Mode is the default Caplets surface. Instead of showing an agent every downstream tool +up front, Caplets gives the agent typed `caplets.` handles inside one TypeScript run. + +Agents should use Code Mode to discover, call, filter, join, and summarize capability data +without filling the visible tool list. + +## What agents see + +A configured OSV Caplet appears as a handle such as: + +```ts +const h = caplets.osv; +``` + +The handle supports discovery and execution: + +```ts +const tools = await caplets.osv.searchTools("package version"); +const details = await h.describeTool("query_package_version"); +const result = await caplets.osv.callTool("query_package_version", { + ecosystem: "npm", + name: "react", + version: "18.2.0", +}); + +return { tools: tools.items.map((tool) => tool.name), result }; +``` + +In MCP clients the visible tool is `caplets__code_mode`; the TypeScript inside that tool +uses handles such as `caplets.osv.searchTools(...)` and `caplets.osv.callTool(...)`. + +For most tasks, keep bulky raw payloads inside the Code Mode script and return compact +JSON with the evidence the user needs. + +## Use it from the CLI + +Run inline TypeScript: + +```sh +caplets code-mode 'return Object.keys(caplets)' +``` + +Print the generated declarations: + +```sh +caplets code-mode types +``` + +If a run behaves unexpectedly, check config and runtime state: + +```sh +caplets doctor +``` + +## When not to use Code Mode + +Use progressive or direct exposure only when a client cannot run Code Mode or a workflow +needs a small visible tool surface. Code Mode is a context-management surface, not a +security boundary. diff --git a/apps/docs/src/content/docs/configuration.mdx b/apps/docs/src/content/docs/configuration.mdx new file mode 100644 index 00000000..536a1085 --- /dev/null +++ b/apps/docs/src/content/docs/configuration.mdx @@ -0,0 +1,63 @@ +--- +title: Configuration +description: Configure user and project Caplets. +--- + +Caplets loads user config plus project config. User config is for your personal agent setup. +Project config is for capabilities that belong with a repository. + +## User config + +The CLI manages your user config. To inspect or override the active path, use: + +```sh +caplets config path +CAPLETS_CONFIG=/path/to/caplets.json caplets doctor +``` + +`CAPLETS_CONFIG` is useful in CI, tests, or temporary sessions where you want a different +user config file. + +## Project config + +Project config lives at: + +```text +.caplets/config.json +``` + +Commit project config when the capability should travel with the repository. Project Markdown +Caplet files load by default from the project, while executable backend maps belong in user +config. + +## Schema + +Use the canonical public schema URL: + +```json +{ + "$schema": "https://caplets.dev/config.schema.json", + "mcpServers": {} +} +``` + +Editors can use `https://caplets.dev/config.schema.json` for validation and completion. + +## Exposure + +Code Mode is the default exposure. Keep it unless you specifically need visible wrapper +tools or direct operation tools for a client that cannot use Code Mode. + +```json +{ + "$schema": "https://caplets.dev/config.schema.json", + "exposure": "code_mode", + "mcpServers": {} +} +``` + +After changing config, run: + +```sh +caplets doctor +``` diff --git a/apps/docs/src/content/docs/index.mdx b/apps/docs/src/content/docs/index.mdx new file mode 100644 index 00000000..45050250 --- /dev/null +++ b/apps/docs/src/content/docs/index.mdx @@ -0,0 +1,41 @@ +--- +title: Caplets +description: Give coding agents Code Mode capabilities without a giant tool wall. +--- + +Caplets wraps MCP servers, APIs, and commands into focused capabilities for coding agents. +Code Mode is the default surface: each configured backend becomes a typed `caplets.` +handle that an agent can inspect, search, call, filter, and summarize in one workflow. + +Use Caplets with Codex, Claude, OpenCode, Pi, or any MCP client that can launch a local +stdio server. + +## Start here + +Run Caplets without a global install: + +```sh +npx caplets setup +npx caplets install spiritledsoftware/caplets osv +``` + +Or install it globally: + +```sh +npm install -g caplets +caplets setup +caplets install spiritledsoftware/caplets osv +``` + +OSV is the first recommended Caplet because it is public and does not need auth. +After setup, ask your agent to use the OSV capability to check a package version. + +## What to read next + +- [Install](/install/) - set up the CLI and agent connection. +- [Code Mode](/code-mode/) - learn the default agent workflow. +- [Configuration](/configuration/) - configure user and project Caplets. +- [Capabilities](/capabilities/) - add MCP, OpenAPI, GraphQL, HTTP, CLI, and shared Caplets. +- [Agent integrations](/agent-integrations/) - use Codex, Claude, OpenCode, and Pi. +- [Remote attach](/remote-attach/) - connect agents to a remote Caplets runtime. +- [Troubleshooting](/troubleshooting/) - check config, auth, and runtime issues. diff --git a/apps/docs/src/content/docs/install.mdx b/apps/docs/src/content/docs/install.mdx new file mode 100644 index 00000000..aa759444 --- /dev/null +++ b/apps/docs/src/content/docs/install.mdx @@ -0,0 +1,74 @@ +--- +title: Install +description: Install Caplets and wire it into your agent. +--- + +Caplets is pre-1.0. Use the latest CLI and latest docs together. + +## Requirements + +- Node.js 22 or newer for published packages. +- An agent that can use MCP, such as Codex or Claude, or a native integration such as + OpenCode or Pi. + +## One-off setup + +Use `npx` if you do not want a global install: + +```sh +npx caplets setup +npx caplets install spiritledsoftware/caplets osv +``` + +Use the global CLI if you want `caplets` on your PATH: + +```sh +npm install -g caplets +caplets setup +caplets install spiritledsoftware/caplets osv +``` + +`caplets setup` configures supported agent harnesses. The OSV Caplet is the recommended +first install because it is public and does not require credentials. + +## Manual MCP setup + +If your client does not support `caplets setup`, add Caplets as a stdio MCP server: + +```json +{ + "mcpServers": { + "caplets": { + "command": "caplets", + "args": ["serve"] + } + } +} +``` + +Use `npx` in the command if you did not install globally: + +```json +{ + "mcpServers": { + "caplets": { + "command": "npx", + "args": ["--yes", "caplets", "serve"] + } + } +} +``` + +## Check the install + +Run: + +```sh +caplets doctor +``` + +If you use `npx`, run: + +```sh +npx caplets doctor +``` diff --git a/apps/docs/src/content/docs/reference/caplet-files.mdx b/apps/docs/src/content/docs/reference/caplet-files.mdx new file mode 100644 index 00000000..09d2b889 --- /dev/null +++ b/apps/docs/src/content/docs/reference/caplet-files.mdx @@ -0,0 +1,161 @@ +--- +title: "Caplet files" +description: "Generated reference for Markdown Caplet file frontmatter." +--- + +{/* */} + +Caplet files are Markdown files with YAML frontmatter. Store a single-file Caplet as `osv.md`, or use a folder with `CAPLET.md` when the capability needs nearby assets. + +Canonical schema: [https://caplets.dev/caplet-frontmatter.schema.json](https://caplets.dev/caplet-frontmatter.schema.json) + +Status values are `Required` or `Optional` according to the schema's top-level `required` array. + +## Top-level fields + +| Field | Status | Type | Description | +| ----------------- | -------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| `$schema` | Optional | string | Optional JSON Schema URL for editor validation. | +| `name` | Required | string | Human-readable Caplet display name. | +| `description` | Required | string | Compact capability description shown before the full Caplet card is disclosed. | +| `tags` | Optional | array | Optional tags for grouping or searching Caplets. | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `useWhen` | Optional | string | When agents should prefer this Caplet or configured action. | +| `avoidWhen` | Optional | string | When agents should avoid this Caplet or configured action. | +| `setup` | Optional | object | Optional explicit setup and verification metadata for this Caplet. | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | +| `mcpServer` | Optional | object | MCP server backend configuration for this Caplet. | +| `openapiEndpoint` | Optional | object | OpenAPI endpoint backend configuration for this Caplet. | +| `graphqlEndpoint` | Optional | object | GraphQL endpoint backend configuration for this Caplet. | +| `httpApi` | Optional | object | HTTP API backend configuration for this Caplet. | +| `cliTools` | Optional | object | CLI tools backend configuration for this Caplet. | +| `capletSet` | Optional | object | Nested Caplet collection backend configuration for this Caplet. | + +## Major sections + +### `setup` + +Optional explicit setup and verification metadata for this Caplet. + +| Field | Status | Type | Description | +| ---------- | -------- | ----- | ----------- | +| `commands` | Optional | array | | +| `verify` | Optional | array | | + +### `projectBinding` + +Project Binding requirements for Caplets that need an attached project. + +| Field | Status | Type | Description | +| ---------- | -------- | ------- | ----------- | +| `required` | Required | boolean | | + +### `runtime` + +Runtime feature and resource requirements for hosted execution. + +| Field | Status | Type | Description | +| ----------- | -------- | ------ | ----------- | +| `features` | Optional | array | | +| `resources` | Optional | object | | + +### `mcpServer` + +MCP server backend configuration for this Caplet. + +| Field | Status | Type | Description | +| ------------------ | -------- | ---------------------------------------------- | ------------------------------------------------------------------------------- | +| `transport` | Optional | "stdio" \| "http" \| "sse" | Downstream MCP transport. Defaults to stdio when command is present. | +| `command` | Optional | string | Executable command for stdio servers. | +| `args` | Optional | array | Arguments passed to the stdio command. | +| `env` | Optional | object | Environment variables for stdio servers. Supports $\{VAR\} and $env:VAR. | +| `cwd` | Optional | string | Working directory for stdio servers. | +| `url` | Optional | string | Remote MCP server URL for http or sse transport. | +| `auth` | Optional | object \| object \| object \| object \| object | Authentication settings for a remote MCP server. | +| `startupTimeoutMs` | Optional | integer | Timeout in milliseconds for starting or checking a downstream server. | +| `callTimeoutMs` | Optional | integer | Timeout in milliseconds for downstream tool calls. | +| `toolCacheTtlMs` | Optional | integer | Milliseconds downstream tool metadata stays fresh. Set 0 to refresh every time. | +| `disabled` | Optional | boolean | When true, omit this Caplet from discovery and do not start its MCP server. | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | + +### `openapiEndpoint` + +OpenAPI endpoint backend configuration for this Caplet. + +| Field | Status | Type | Description | +| --------------------- | -------- | ---------------------------------------------- | --------------------------------------------------------------------------------- | +| `specPath` | Optional | string | Local OpenAPI specification path. | +| `specUrl` | Optional | string | Remote OpenAPI specification URL. | +| `baseUrl` | Optional | string | Override base URL for OpenAPI requests. | +| `auth` | Required | object \| object \| object \| object \| object | Explicit OpenAPI request auth config. Use \{"type":"none"\} for public APIs. | +| `requestTimeoutMs` | Optional | integer | Timeout in milliseconds for OpenAPI HTTP requests. | +| `operationCacheTtlMs` | Optional | integer | Milliseconds OpenAPI operation metadata stays fresh. Set 0 to refresh every time. | +| `disabled` | Optional | boolean | When true, omit this Caplet from discovery. | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | + +### `graphqlEndpoint` + +GraphQL endpoint backend configuration for this Caplet. + +| Field | Status | Type | Description | +| --------------------- | -------- | ---------------------------------------------- | --------------------------------------------------------------------------------- | +| `endpointUrl` | Required | string | GraphQL HTTP endpoint URL. | +| `schemaPath` | Optional | string | Local GraphQL SDL or introspection path. | +| `schemaUrl` | Optional | string | Remote GraphQL SDL or introspection URL. | +| `introspection` | Optional | boolean | Load schema through endpoint introspection. | +| `operations` | Optional | object | Configured GraphQL operations keyed by stable tool name. | +| `auth` | Required | object \| object \| object \| object \| object | Explicit GraphQL request auth config. Use \{"type":"none"\} for public APIs. | +| `requestTimeoutMs` | Optional | integer | Timeout in milliseconds for GraphQL HTTP requests. | +| `operationCacheTtlMs` | Optional | integer | Milliseconds GraphQL operation metadata stays fresh. Set 0 to refresh every time. | +| `selectionDepth` | Optional | integer | Maximum depth for auto-generated GraphQL selection sets. | +| `disabled` | Optional | boolean | When true, omit this Caplet from discovery. | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | + +### `httpApi` + +HTTP API backend configuration for this Caplet. + +| Field | Status | Type | Description | +| ------------------ | -------- | ---------------------------------------------- | ----------------------------------------------------------------------------- | +| `baseUrl` | Required | string | Base URL for HTTP action requests. | +| `auth` | Required | object \| object \| object \| object \| object | Explicit HTTP API request auth config. Use \{"type":"none"\} for public APIs. | +| `actions` | Required | object | Configured HTTP actions keyed by stable tool name. | +| `requestTimeoutMs` | Optional | integer | Timeout in milliseconds for HTTP action requests. | +| `maxResponseBytes` | Optional | integer | Maximum HTTP action response body bytes to read. | +| `disabled` | Optional | boolean | When true, omit this Caplet from discovery. | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | + +### `cliTools` + +CLI tools backend configuration for this Caplet. + +| Field | Status | Type | Description | +| ---------------- | -------- | ------- | ----------------------------------------------------------------------- | +| `actions` | Required | object | Configured CLI actions keyed by stable tool name. | +| `cwd` | Optional | string | Default working directory for CLI actions. | +| `env` | Optional | object | Default environment variables. | +| `timeoutMs` | Optional | integer | | +| `maxOutputBytes` | Optional | integer | | +| `disabled` | Optional | boolean | When true, omit this Caplet from discovery. | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | + +### `capletSet` + +Nested Caplet collection backend configuration for this Caplet. + +| Field | Status | Type | Description | +| -------------------- | -------- | ------- | ----------------------------------------------------------------------- | +| `configPath` | Optional | string | Child Caplets config.json path. | +| `capletsRoot` | Optional | string | Child Markdown Caplets root directory. | +| `defaultSearchLimit` | Optional | integer | | +| `maxSearchLimit` | Optional | integer | | +| `toolCacheTtlMs` | Optional | integer | | +| `disabled` | Optional | boolean | When true, omit this Caplet from discovery. | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | diff --git a/apps/docs/src/content/docs/reference/code-mode-api.mdx b/apps/docs/src/content/docs/reference/code-mode-api.mdx new file mode 100644 index 00000000..8e18ce0a --- /dev/null +++ b/apps/docs/src/content/docs/reference/code-mode-api.mdx @@ -0,0 +1,99 @@ +--- +title: "Code Mode API" +description: "Generated reference for the TypeScript surface available inside `caplets__code_mode`." +--- + +{/* */} + +Code Mode runs TypeScript with generated `caplets.` handles. Prefer discovery methods first, then call downstream tools with compact, decision-ready inputs and outputs. + +## Runtime handles + +```ts +interface CapletHandle { + readonly id: Id; + /** Show this Caplet card, without tool/resource/prompt schemas. */ + inspect(): Promise>; + /** Check backend readiness/auth; expected unavailable states return ok:false. */ + check(): Promise>; + /** List tool summaries for the discovery pass; may be empty. */ + tools(input?: PageInput): Promise>; + /** Search tool summaries for the discovery pass; may be empty. */ + searchTools(query: string, input?: PageInput): Promise>; + /** Get schema, callSignature, types, examples; prefer outputSchema/outputTypeScript over observed hints. */ + describeTool(name: string): Promise>; + /** Call one tool; expected failures return ok:false. Filter bulky data in script before returning. */ + callTool(name: string, args?: unknown): Promise>; + /** List readable resources for the discovery pass; many backends expose none. */ + resources(input?: PageInput): Promise>; + /** Search readable resources for the discovery pass; many backends expose none. */ + searchResources(query: string, input?: PageInput): Promise>; + /** List resource templates for the discovery pass; many backends expose none. */ + resourceTemplates(input?: PageInput): Promise>; + /** Read one resource by URI; unsupported/missing resources return ok:false. */ + readResource(uri: string): Promise>; + /** List reusable prompts for the discovery pass; many backends expose none. */ + prompts(input?: PageInput): Promise>; + /** Search reusable prompts for the discovery pass; many backends expose none. */ + searchPrompts(query: string, input?: PageInput): Promise>; + /** Get one prompt by name and args; unsupported/missing prompts return ok:false. */ + getPrompt(name: string, args?: unknown): Promise>; + /** Complete a prompt or resource-template argument. */ + complete(input: CompleteInput): Promise>; +} +``` + +```ts +interface DebugApi { + readLogs(input: ReadLogsInput): Promise; +} +``` + +```ts +type Page = { items: T[]; nextCursor?: string; truncated?: boolean }; +``` + +```ts +type CapletsResult = + | { ok: true; data: T; meta?: CapletsMeta } + | { ok: false; error: CapletsError; meta?: CapletsMeta }; +``` + +```ts +type ToolSummary = { + /** Exact downstream tool identifier for describeTool(name) and callTool(name,args). */ + name: string; + title?: string; + description?: string; + /** Optional author-supplied hint for when to prefer this tool. */ + useWhen?: string; + /** Optional author-supplied hint for when to avoid this tool. */ + avoidWhen?: string; + /** True when the tool declares that it only reads data. */ + readOnlyHint?: boolean; + /** True when the tool declares that it may perform destructive writes. */ + destructiveHint?: boolean; +}; +``` + +```ts +type ToolDescriptor = { + id?: string; + tool?: unknown; + inputSchema?: unknown; + outputSchema?: unknown; + callSignature?: string; + inputTypeScript?: string; + outputTypeScript?: string; + observedOutputShape?: ObservedOutputShape; + examples?: unknown[]; +}; +``` + +```ts +type ReadLogsInput = { logRef: string; cursor?: string; limit?: number }; +``` + +```ts +type ReadLogsResult = { entries: CodeModeLogEntry[]; nextCursor?: string }; +``` diff --git a/apps/docs/src/content/docs/reference/config.mdx b/apps/docs/src/content/docs/reference/config.mdx new file mode 100644 index 00000000..8eae5d6c --- /dev/null +++ b/apps/docs/src/content/docs/reference/config.mdx @@ -0,0 +1,200 @@ +--- +title: "Configuration schema" +description: "Generated reference for `caplets.json` and `.caplets/config.json`." +--- + +{/* */} + +Use this page to scan the public Caplets configuration shape. The linked JSON Schema remains the canonical editor integration target. + +Canonical schema: [https://caplets.dev/config.schema.json](https://caplets.dev/config.schema.json) + +Status values are `Required` or `Optional` according to the schema's top-level `required` array. + +## Top-level fields + +| Field | Status | Type | Description | +| -------------------- | -------- | ------- | ------------------------------------------------------ | +| `$schema` | Optional | string | Optional JSON Schema URL for editor validation. | +| `version` | Optional | number | Caplets config schema version. | +| `defaultSearchLimit` | Optional | integer | Default maximum number of same-server search results. | +| `maxSearchLimit` | Optional | integer | Maximum accepted search_tools limit. | +| `completion` | Optional | object | Shell completion discovery timeout and cache settings. | +| `options` | Optional | object | Global Caplets runtime options. | +| `mcpServers` | Optional | object | Downstream MCP servers keyed by stable server ID. | +| `openapiEndpoints` | Optional | object | OpenAPI endpoints keyed by stable Caplet ID. | +| `graphqlEndpoints` | Optional | object | GraphQL endpoints keyed by stable Caplet ID. | +| `httpApis` | Optional | object | HTTP APIs keyed by stable Caplet ID. | +| `cliTools` | Optional | object | CLI tools keyed by stable Caplet ID. | +| `capletSets` | Optional | object | Nested Caplet collections keyed by stable Caplet ID. | + +## Major sections + +### `completion` + +Shell completion discovery timeout and cache settings. + +| Field | Status | Type | Description | +| -------------------- | -------- | ------- | ----------- | +| `discoveryTimeoutMs` | Optional | integer | | +| `overallTimeoutMs` | Optional | integer | | +| `cacheTtlMs` | Optional | integer | | +| `negativeCacheTtlMs` | Optional | integer | | + +### `options` + +Global Caplets runtime options. + +| Field | Status | Type | Description | +| ------------------------------ | -------- | ------------------------------------------------------------------------------------------------- | ------------------------------------- | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `exposureDiscoveryTimeoutMs` | Optional | integer | | +| `exposureDiscoveryConcurrency` | Optional | integer | | + +### `mcpServers` + +Downstream MCP servers keyed by stable server ID. + +| Field | Status | Type | Description | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| `name` | Required | string | Human-readable server display name. | +| `description` | Required | string | Capability description shown to agents before downstream tools are disclosed. | +| `transport` | Optional | "stdio" \| "http" \| "sse" | Downstream MCP transport. Defaults to stdio when command is present. | +| `command` | Optional | string | Executable command for stdio servers. | +| `args` | Optional | array | Arguments passed to the stdio command. | +| `env` | Optional | object | Environment variables for stdio servers. Supports $\{VAR\} and $env:VAR. | +| `cwd` | Optional | string | Working directory for stdio servers. | +| `url` | Optional | string | Remote MCP server URL for http or sse transport. | +| `auth` | Optional | object \| object \| object \| object \| object | Authentication settings for a remote MCP server. | +| `tags` | Optional | array | | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `shadowing` | Optional | "forbid" \| "allow" | Whether attached local Caplets may shadow this remote Caplet ID. | +| `useWhen` | Optional | string | When agents should prefer this Caplet or configured action. | +| `avoidWhen` | Optional | string | When agents should avoid this Caplet or configured action. | +| `setup` | Optional | object | | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | +| `startupTimeoutMs` | Optional | integer | Timeout in milliseconds for starting or checking a downstream server. | +| `callTimeoutMs` | Optional | integer | Timeout in milliseconds for downstream tool calls. | +| `toolCacheTtlMs` | Optional | integer | Milliseconds downstream tool metadata stays fresh. Set 0 to refresh every time. | +| `disabled` | Optional | boolean | When true, omit this server from Caplets discovery and do not start it. | + +### `openapiEndpoints` + +OpenAPI endpoints keyed by stable Caplet ID. + +| Field | Status | Type | Description | +| --------------------- | -------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| `name` | Required | string | Human-readable OpenAPI display name. | +| `description` | Required | string | Capability description shown to agents before OpenAPI operations are disclosed. | +| `specPath` | Optional | string | Local OpenAPI specification path. | +| `specUrl` | Optional | string | Remote OpenAPI specification URL. | +| `baseUrl` | Optional | string | Override base URL for OpenAPI requests. | +| `auth` | Required | object \| object \| object \| object \| object | Explicit OpenAPI request auth config. Use \{"type":"none"\} for public APIs. | +| `tags` | Optional | array | | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `shadowing` | Optional | "forbid" \| "allow" | Whether attached local Caplets may shadow this remote Caplet ID. | +| `useWhen` | Optional | string | When agents should prefer this Caplet or configured action. | +| `avoidWhen` | Optional | string | When agents should avoid this Caplet or configured action. | +| `setup` | Optional | object | | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | +| `requestTimeoutMs` | Optional | integer | Timeout in milliseconds for OpenAPI HTTP requests. | +| `operationCacheTtlMs` | Optional | integer | Milliseconds OpenAPI operation metadata stays fresh. Set 0 to refresh every time. | +| `disabled` | Optional | boolean | When true, omit this OpenAPI Caplet from discovery. | + +### `graphqlEndpoints` + +GraphQL endpoints keyed by stable Caplet ID. + +| Field | Status | Type | Description | +| --------------------- | -------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| `name` | Required | string | Human-readable GraphQL display name. | +| `description` | Required | string | Capability description shown to agents before GraphQL operations are disclosed. | +| `endpointUrl` | Required | string | GraphQL HTTP endpoint URL. | +| `schemaPath` | Optional | string | Local GraphQL SDL or introspection path. | +| `schemaUrl` | Optional | string | Remote GraphQL SDL or introspection URL. | +| `introspection` | Optional | boolean | Load schema through endpoint introspection. | +| `operations` | Optional | object | Configured GraphQL operations keyed by stable tool name. | +| `auth` | Required | object \| object \| object \| object \| object | Explicit GraphQL request auth config. Use \{"type":"none"\} for public APIs. | +| `tags` | Optional | array | | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `shadowing` | Optional | "forbid" \| "allow" | Whether attached local Caplets may shadow this remote Caplet ID. | +| `useWhen` | Optional | string | When agents should prefer this Caplet or configured action. | +| `avoidWhen` | Optional | string | When agents should avoid this Caplet or configured action. | +| `setup` | Optional | object | | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | +| `requestTimeoutMs` | Optional | integer | Timeout in milliseconds for GraphQL HTTP requests. | +| `operationCacheTtlMs` | Optional | integer | Milliseconds GraphQL operation metadata stays fresh. Set 0 to refresh every time. | +| `selectionDepth` | Optional | integer | Maximum depth for auto-generated GraphQL selection sets. | +| `disabled` | Optional | boolean | When true, omit this GraphQL Caplet. | + +### `httpApis` + +HTTP APIs keyed by stable Caplet ID. + +| Field | Status | Type | Description | +| ------------------ | -------- | ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | +| `name` | Required | string | Human-readable HTTP API display name. | +| `description` | Required | string | Capability description shown to agents before HTTP actions are disclosed. | +| `baseUrl` | Required | string | Base URL for HTTP action requests. | +| `auth` | Required | object \| object \| object \| object \| object | Explicit HTTP API request auth config. Use \{"type":"none"\} for public APIs. | +| `actions` | Required | object | Configured HTTP actions keyed by stable tool name. | +| `tags` | Optional | array | | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `shadowing` | Optional | "forbid" \| "allow" | Whether attached local Caplets may shadow this remote Caplet ID. | +| `useWhen` | Optional | string | When agents should prefer this Caplet or configured action. | +| `avoidWhen` | Optional | string | When agents should avoid this Caplet or configured action. | +| `setup` | Optional | object | | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | +| `requestTimeoutMs` | Optional | integer | Timeout in milliseconds for HTTP action requests. | +| `maxResponseBytes` | Optional | integer | Maximum HTTP action response body bytes to read. | +| `disabled` | Optional | boolean | When true, omit this HTTP API Caplet. | + +### `cliTools` + +CLI tools keyed by stable Caplet ID. + +| Field | Status | Type | Description | +| ---------------- | -------- | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| `name` | Required | string | Human-readable CLI tools display name. | +| `description` | Required | string | Capability description shown to agents before CLI actions are disclosed. | +| `actions` | Required | object | Configured CLI actions keyed by stable tool name. | +| `cwd` | Optional | string | Default working directory for CLI actions. | +| `env` | Optional | object | Default environment variables for CLI actions. | +| `tags` | Optional | array | | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `shadowing` | Optional | "forbid" \| "allow" | Whether attached local Caplets may shadow this remote Caplet ID. | +| `useWhen` | Optional | string | When agents should prefer this Caplet or configured action. | +| `avoidWhen` | Optional | string | When agents should avoid this Caplet or configured action. | +| `setup` | Optional | object | | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | +| `timeoutMs` | Optional | integer | Default timeout in milliseconds for CLI actions. | +| `maxOutputBytes` | Optional | integer | Default maximum combined stdout and stderr bytes to keep. | +| `disabled` | Optional | boolean | When true, omit this CLI tools Caplet. | + +### `capletSets` + +Nested Caplet collections keyed by stable Caplet ID. + +| Field | Status | Type | Description | +| -------------------- | -------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| `name` | Required | string | Human-readable Caplet set display name. | +| `description` | Required | string | Capability description shown before child Caplets are disclosed. | +| `configPath` | Optional | string | Child Caplets config.json path. | +| `capletsRoot` | Optional | string | Child Markdown Caplets root directory. | +| `defaultSearchLimit` | Optional | integer | Default maximum number of child Caplet search results. | +| `maxSearchLimit` | Optional | integer | Maximum accepted child Caplet search result limit. | +| `toolCacheTtlMs` | Optional | integer | Milliseconds child Caplet metadata stays fresh. Set 0 to refresh every time. | +| `tags` | Optional | array | | +| `exposure` | Optional | "direct" \| "progressive" \| "code_mode" \| "direct_and_code_mode" \| "progressive_and_code_mode" | How this Caplet is exposed to agents. | +| `shadowing` | Optional | "forbid" \| "allow" | Whether attached local Caplets may shadow this remote Caplet ID. | +| `useWhen` | Optional | string | When agents should prefer this Caplet or configured action. | +| `avoidWhen` | Optional | string | When agents should avoid this Caplet or configured action. | +| `setup` | Optional | object | | +| `projectBinding` | Optional | object | Project Binding requirements for Caplets that need an attached project. | +| `runtime` | Optional | object | Runtime feature and resource requirements for hosted execution. | +| `disabled` | Optional | boolean | When true, omit this Caplet set. | diff --git a/apps/docs/src/content/docs/remote-attach.mdx b/apps/docs/src/content/docs/remote-attach.mdx new file mode 100644 index 00000000..eb022b62 --- /dev/null +++ b/apps/docs/src/content/docs/remote-attach.mdx @@ -0,0 +1,80 @@ +--- +title: Remote Attach +description: Connect an agent to a remote Caplets runtime. +--- + +Use `caplets attach` when the agent should connect to a remote or Cloud-backed Caplets +runtime instead of starting local backends. + +## Modes + +Caplets native integrations use the same mode resolver as `caplets attach`: + +| Mode | Use it when | +| -------- | ------------------------------------------------------------------------------------------------------------------------- | +| `local` | The agent should start Caplets against local user and project config. | +| `remote` | The agent should connect to a self-hosted Caplets service. | +| `cloud` | The agent should connect to Caplets Cloud with saved Cloud auth. | +| `auto` | Caplets should use Cloud for Cloud URLs, self-hosted remote for non-Cloud URLs, and local mode when no remote URL is set. | + +## MCP client config + +Codex: + +```toml +[mcp_servers.caplets] +command = "caplets" +args = ["attach"] +``` + +Generic MCP JSON: + +```json +{ + "mcpServers": { + "caplets": { + "command": "caplets", + "args": ["attach"] + } + } +} +``` + +## Environment + +For a self-hosted remote: + +```sh +export CAPLETS_MODE=remote +export CAPLETS_REMOTE_URL=https://caplets.example.com/caplets +export CAPLETS_REMOTE_TOKEN=... + +caplets attach +``` + +Use `CAPLETS_REMOTE_USER` and `CAPLETS_REMOTE_PASSWORD` instead of +`CAPLETS_REMOTE_TOKEN` when the remote uses Basic Auth. + +Run a finite preflight before wiring an agent: + +```sh +caplets attach --once +``` + +`caplets attach --once` validates credentials, checks the attach endpoint, and exits. + +## Project binding + +`caplets attach` can keep a local project bound to a remote runtime. Use this when the +remote capability needs project-local context while the agent still talks to one Caplets +MCP server. + +Attach connects to the runtime attach API at `/v1/attach`. Ordinary MCP clients that are +not using attach continue to connect to `/v1/mcp`, which still honors the configured +exposure mode for each Caplet. + +Check remote health and binding diagnostics with: + +```sh +caplets doctor +``` diff --git a/apps/docs/src/content/docs/troubleshooting.mdx b/apps/docs/src/content/docs/troubleshooting.mdx new file mode 100644 index 00000000..a55bd8bb --- /dev/null +++ b/apps/docs/src/content/docs/troubleshooting.mdx @@ -0,0 +1,78 @@ +--- +title: Troubleshooting +description: Diagnose Caplets config, agent setup, and remote attach issues. +--- + +Start with: + +```sh +caplets doctor +``` + +If you installed with `npx`, use: + +```sh +npx caplets doctor +``` + +## Agent cannot see Caplets + +Run setup again: + +```sh +caplets setup +``` + +Then restart the agent. Codex, Claude, OpenCode, and Pi usually read MCP or native plugin +configuration at startup. + +## Wrong config is loading + +Print the active user config path: + +```sh +caplets config path +``` + +Override it for one command: + +```sh +CAPLETS_CONFIG=/path/to/caplets.json caplets doctor +``` + +Project config should be in `.caplets/config.json`. + +## Remote attach fails + +Confirm the remote environment: + +```sh +export CAPLETS_MODE=remote +export CAPLETS_REMOTE_URL=https://caplets.example.com/caplets +caplets doctor +caplets attach +``` + +If the remote requires auth, set either `CAPLETS_REMOTE_TOKEN` or +`CAPLETS_REMOTE_USER` plus `CAPLETS_REMOTE_PASSWORD`. + +## Code Mode errors + +Check generated declarations: + +```sh +caplets code-mode types +``` + +Then rerun the smallest Code Mode script that reproduces the issue. Return compact JSON +from Code Mode so the agent can see the actual error envelope and repair the call. + +## OSV first check + +If you need a no-auth smoke test, install OSV: + +```sh +caplets install spiritledsoftware/caplets osv +``` + +Then ask your agent to query OSV from Code Mode. diff --git a/apps/docs/src/styles/global.css b/apps/docs/src/styles/global.css new file mode 100644 index 00000000..e52318cc --- /dev/null +++ b/apps/docs/src/styles/global.css @@ -0,0 +1,77 @@ +@import "tailwindcss"; + +:root { + --caplets-ember: oklch(62% 0.155 35); + --caplets-ember-deep: oklch(51% 0.145 35); + --caplets-ink: oklch(24% 0.018 100); + --caplets-linen: oklch(97% 0.012 85); + --caplets-paper: oklch(98% 0.014 82); + --caplets-parchment: oklch(91% 0.035 82); + --caplets-ash: oklch(86% 0.018 78); + --caplets-olive: oklch(48% 0.045 110); + + --sl-color-accent-low: var(--caplets-parchment); + --sl-color-accent: var(--caplets-ember); + --sl-color-accent-high: var(--caplets-ember-deep); + --sl-color-white: var(--caplets-paper); + --sl-color-gray-1: var(--caplets-ink); + --sl-color-gray-2: oklch(35% 0.02 100); + --sl-color-gray-3: var(--caplets-olive); + --sl-color-gray-4: oklch(68% 0.02 86); + --sl-color-gray-5: var(--caplets-ash); + --sl-color-gray-6: var(--caplets-parchment); + --sl-color-black: var(--caplets-linen); + --sl-font: + Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; + --sl-font-mono: + ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace; +} + +:root[data-theme="dark"] { + --sl-color-accent-low: oklch(31% 0.04 35); + --sl-color-accent: oklch(72% 0.12 35); + --sl-color-accent-high: oklch(84% 0.08 35); + --sl-color-white: oklch(94% 0.018 82); + --sl-color-gray-1: oklch(93% 0.018 82); + --sl-color-gray-2: oklch(84% 0.018 82); + --sl-color-gray-3: oklch(74% 0.02 82); + --sl-color-gray-4: oklch(54% 0.022 82); + --sl-color-gray-5: oklch(34% 0.018 100); + --sl-color-gray-6: oklch(25% 0.016 100); + --sl-color-black: oklch(18% 0.014 100); +} + +h1, +h2, +h3 { + color: var(--sl-color-gray-1); + letter-spacing: -0.025em; + text-wrap: balance; +} + +p, +li { + text-wrap: pretty; +} + +.hero { + border-bottom: 1px solid var(--sl-color-gray-5); +} + +.hero .tagline { + max-width: 60ch; +} + +.sl-markdown-content code:not(:where(pre code)) { + border: 1px solid color-mix(in oklch, var(--sl-color-gray-5), transparent 45%); + border-radius: 0.35rem; + background: color-mix(in oklch, var(--sl-color-accent-low), transparent 55%); +} + +.sl-markdown-content table { + font-size: 0.9rem; +} + +.sl-markdown-content th { + color: var(--sl-color-gray-1); +} diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json new file mode 100644 index 00000000..8bf91d3b --- /dev/null +++ b/apps/docs/tsconfig.json @@ -0,0 +1,5 @@ +{ + "extends": "astro/tsconfigs/strict", + "include": [".astro/types.d.ts", "**/*"], + "exclude": ["dist"] +} diff --git a/apps/landing/package.json b/apps/landing/package.json index 505fb306..b603d62c 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -8,16 +8,19 @@ "build": "astro build", "dev": "astro dev", "preview": "astro preview", - "typecheck": "astro check", - "campaign:check": "node test/campaign-copy.check.mjs" + "typecheck": "astro check" }, "dependencies": { "@astrojs/check": "^0.9.9", - "@hugeicons/core-free-icons": "4.2.0", + "@tabler/icons": "^3.44.0", + "@tailwindcss/forms": "^0.5.11", "@tailwindcss/vite": "^4.3.1", "astro": "^6.4.6", + "tailwind-merge": "^3.6.0", + "tailwind-variants": "^3.2.2", "tailwindcss": "^4.3.1", "three": "^0.184.0", + "tw-animate-css": "^1.4.0", "typescript": "^6.0.3" }, "devDependencies": { diff --git a/apps/landing/public/config.schema.json b/apps/landing/public/config.schema.json index 9cd1369a..3ec7d1ce 100644 --- a/apps/landing/public/config.schema.json +++ b/apps/landing/public/config.schema.json @@ -348,6 +348,12 @@ ], "description": "How this Caplet is exposed to agents." }, + "shadowing": { + "default": "forbid", + "description": "Whether attached local Caplets may shadow this remote Caplet ID.", + "type": "string", + "enum": ["forbid", "allow"] + }, "useWhen": { "description": "When agents should prefer this Caplet or configured action.", "type": "string", @@ -764,6 +770,12 @@ ], "description": "How this Caplet is exposed to agents." }, + "shadowing": { + "default": "forbid", + "description": "Whether attached local Caplets may shadow this remote Caplet ID.", + "type": "string", + "enum": ["forbid", "allow"] + }, "useWhen": { "description": "When agents should prefer this Caplet or configured action.", "type": "string", @@ -1224,6 +1236,12 @@ ], "description": "How this Caplet is exposed to agents." }, + "shadowing": { + "default": "forbid", + "description": "Whether attached local Caplets may shadow this remote Caplet ID.", + "type": "string", + "enum": ["forbid", "allow"] + }, "useWhen": { "description": "When agents should prefer this Caplet or configured action.", "type": "string", @@ -1734,6 +1752,12 @@ ], "description": "How this Caplet is exposed to agents." }, + "shadowing": { + "default": "forbid", + "description": "Whether attached local Caplets may shadow this remote Caplet ID.", + "type": "string", + "enum": ["forbid", "allow"] + }, "useWhen": { "description": "When agents should prefer this Caplet or configured action.", "type": "string", @@ -2093,6 +2117,12 @@ ], "description": "How this Caplet is exposed to agents." }, + "shadowing": { + "default": "forbid", + "description": "Whether attached local Caplets may shadow this remote Caplet ID.", + "type": "string", + "enum": ["forbid", "allow"] + }, "useWhen": { "description": "When agents should prefer this Caplet or configured action.", "type": "string", @@ -2350,6 +2380,12 @@ ], "description": "How this Caplet is exposed to agents." }, + "shadowing": { + "default": "forbid", + "description": "Whether attached local Caplets may shadow this remote Caplet ID.", + "type": "string", + "enum": ["forbid", "allow"] + }, "useWhen": { "description": "When agents should prefer this Caplet or configured action.", "type": "string", diff --git a/apps/landing/public/favicon.svg b/apps/landing/public/favicon.svg index f157bd1c..e3a62dff 100644 --- a/apps/landing/public/favicon.svg +++ b/apps/landing/public/favicon.svg @@ -1,9 +1,6 @@ diff --git a/apps/landing/src/components/HugeIcon.astro b/apps/landing/src/components/HugeIcon.astro deleted file mode 100644 index 061b7855..00000000 --- a/apps/landing/src/components/HugeIcon.astro +++ /dev/null @@ -1,19 +0,0 @@ ---- -type HugeIconNode = readonly [string, { readonly [key: string]: string | number }]; - -type Props = { - icon: readonly HugeIconNode[]; - class?: string; -}; - -const { icon, class: className } = Astro.props; ---- - - diff --git a/apps/landing/src/components/landing/Activation.astro b/apps/landing/src/components/landing/Activation.astro new file mode 100644 index 00000000..736ccc7d --- /dev/null +++ b/apps/landing/src/components/landing/Activation.astro @@ -0,0 +1,96 @@ +--- +import ArrowUpRight from "@tabler/icons/outline/arrow-up-right.svg"; +import Terminal from "@tabler/icons/outline/terminal-2.svg"; + +import { Badge } from "@/components/starwind/badge"; +import { Button } from "@/components/starwind/button"; +import { Card, CardContent } from "@/components/starwind/card"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/starwind/tabs"; + +import { exampleCaplets } from "../../data/landing"; +--- + +

+
+
+

Setup

+

+ Start with the smallest useful Caplet. +

+

+ caplets setup wires the agent integrations you choose. Add OSV first because it needs no auth; bring in GitHub or Sourcegraph after the discovery path feels right. +

+ +
+
+ discover + cards +
+
+ inspect + tools +
+
+ call + typed +
+
+
+ + + + {exampleCaplets.map((example) => {example.name})} + + { + exampleCaplets.map((example) => ( + + + +
+ {example.name} +

Add {example.name}

+

{example.summary}

+

{example.why}

+
+ {example.path.map((step, index) => ( + <> + {index > 0 && /} + {step} + + ))} +
+

+ {example.help.map((part) => + part === "GH_TOKEN" || part === "caplets setup" ? ( + {part} + ) : ( + part + ), + )} +

+
+
+
+
+
    + {example.steps.map((step, index) => ( +
  1. + {String(index + 1).padStart(2, "0")} + {step.command} +
  2. + ))} +
+
+
+
+
+ )) + } +
+
+
diff --git a/apps/landing/src/components/landing/AgentTrace.astro b/apps/landing/src/components/landing/AgentTrace.astro new file mode 100644 index 00000000..54734061 --- /dev/null +++ b/apps/landing/src/components/landing/AgentTrace.astro @@ -0,0 +1,32 @@ +--- +const traceSteps = [ + { href: "#trace", label: "How" }, + { href: "#why", label: "Why" }, + { href: "#install", label: "Setup" }, + { href: "#proof", label: "Benchmark" }, + { href: "#remote", label: "Remote" }, +] as const; +--- + + diff --git a/apps/landing/src/components/landing/CapabilityAperture.astro b/apps/landing/src/components/landing/CapabilityAperture.astro new file mode 100644 index 00000000..5560cd7f --- /dev/null +++ b/apps/landing/src/components/landing/CapabilityAperture.astro @@ -0,0 +1,16 @@ + diff --git a/apps/landing/src/components/landing/CommandBlock.astro b/apps/landing/src/components/landing/CommandBlock.astro new file mode 100644 index 00000000..7d25c8a6 --- /dev/null +++ b/apps/landing/src/components/landing/CommandBlock.astro @@ -0,0 +1,31 @@ +--- +import Check from "@tabler/icons/outline/check.svg"; +import Copy from "@tabler/icons/outline/copy.svg"; + +interface Props { + id: string; + label: string; + command: string; + copyLabel: string; +} + +const { id, label, command, copyLabel } = Astro.props; +--- + +
+
+ {label} + +
+
{command}
+
diff --git a/apps/landing/src/components/landing/Footer.astro b/apps/landing/src/components/landing/Footer.astro new file mode 100644 index 00000000..d8e1efd6 --- /dev/null +++ b/apps/landing/src/components/landing/Footer.astro @@ -0,0 +1,23 @@ +--- +import ArrowUpRight from "@tabler/icons/outline/arrow-up-right.svg"; +--- + + diff --git a/apps/landing/src/components/landing/Header.astro b/apps/landing/src/components/landing/Header.astro new file mode 100644 index 00000000..2a2c5256 --- /dev/null +++ b/apps/landing/src/components/landing/Header.astro @@ -0,0 +1,79 @@ +--- +import ArrowUpRight from "@tabler/icons/outline/arrow-up-right.svg"; +import BrandGithub from "@tabler/icons/outline/brand-github.svg"; +import BrandNpm from "@tabler/icons/outline/brand-npm.svg"; +import Menu from "@tabler/icons/outline/menu-2.svg"; + +import { Button } from "@/components/starwind/button"; +import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from "@/components/starwind/sheet"; +--- + + diff --git a/apps/landing/src/components/landing/Hero.astro b/apps/landing/src/components/landing/Hero.astro new file mode 100644 index 00000000..004a2375 --- /dev/null +++ b/apps/landing/src/components/landing/Hero.astro @@ -0,0 +1,71 @@ +--- +import Check from "@tabler/icons/outline/check.svg"; +import Copy from "@tabler/icons/outline/copy.svg"; + +import { Button } from "@/components/starwind/button"; + +import { heroCommands, quickstartCommand } from "../../data/landing"; +--- + +
+
+ +
+
+

+ Give your agent Capabilities, not a tool wall +

+

+ Turn sprawling MCP servers into focused capability cards. Your agent can start with one typed route, zoom into tools only when needed, and keep huge schemas out of the prompt until they matter. +

+
+
+
Tool wall
+
215 tools
+
+
+
Caplets
+
7 cards
+
+
+
Code Mode
+
72% fewer tokens
+
+
+
+ + +
+
+
+ Quick start +
+ + More setup options +
+
+
    + {heroCommands.map((item, index) => ( +
  1. + {String(index + 1).padStart(2, "0")} +
    + {item.label} + {item.command} +
    +
  2. + ))} +
+
+
+
+
diff --git a/apps/landing/src/components/landing/Proof.astro b/apps/landing/src/components/landing/Proof.astro new file mode 100644 index 00000000..1a48596b --- /dev/null +++ b/apps/landing/src/components/landing/Proof.astro @@ -0,0 +1,106 @@ +--- +import ArrowUpRight from "@tabler/icons/outline/arrow-up-right.svg"; + +import { Button } from "@/components/starwind/button"; +import { Card, CardContent } from "@/components/starwind/card"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/starwind/table"; + +import { benchmarkProvenance, benchmarkRows, deterministicSurface, proofStats } from "../../data/landing"; +--- + +
+
+
+ Benchmark proof +

+ The result survived the surface cut. +

+

+ Same task set, same 10/10 completion. Code Mode kept the agent focused by cutting the prompt surface instead of flattening every tool into view. +

+ {benchmarkProvenance} + +
+ +
+
+ {proofStats.map((stat) => ( +
+
{stat.label}
+
{stat.value}
+

{stat.detail}

+
+ ))} +
+ +
+ { + benchmarkRows.map((row) => ( + + +
+ Mode + {row.mode} +
+
+
+ Passed + {row.passed} +
+
+ Total Tokens + {row.tokens} +
+
+ Tool Surface Tokens + {row.surfaceTokens} +
+
+
+
+ )) + } +
+ + + +
+ {deterministicSurface.map((item) => ( +
+ {item.label} + {item.value} +
+ ))} +
+

+ Code Mode used 72.0% fewer request + output tokens than Direct vanilla MCP and 65.0% fewer than Executor.sh. Progressive disclosure also reduced tokens while every listed mode completed 10/10 tasks. +

+
+
+
diff --git a/apps/landing/src/components/landing/RemoteStory.astro b/apps/landing/src/components/landing/RemoteStory.astro new file mode 100644 index 00000000..af240e39 --- /dev/null +++ b/apps/landing/src/components/landing/RemoteStory.astro @@ -0,0 +1,83 @@ +--- +import Route from "@tabler/icons/outline/route.svg"; +import Server from "@tabler/icons/outline/server.svg"; + +import { Card, CardContent } from "@/components/starwind/card"; +import { Separator } from "@/components/starwind/separator"; + +import { remoteCommands, remoteComparison, remoteEndpoints } from "../../data/landing"; +import CommandBlock from "./CommandBlock.astro"; +--- + +
+
+
+

Remote Caplets server

+

+ One auth home. Every agent gets the same tools. +

+

+ Run Caplets as a small HTTP service. Provider tokens and OAuth state stay server-side; Codex, OpenCode, Pi, Claude Code, and any MCP client attach to the same capability surface. +

+
+ {remoteEndpoints.map((endpoint) => ( +
+
{endpoint.label}
+
{endpoint.value}
+
+ ))} +
+
+ +
+
+ {remoteComparison.map((item) => ( + + +

{item.label}

+

{item.detail}

+
    + {item.points.map((point) =>
  • {point}
  • )} +
+
+
+ ))} +
+ + + +
+
+
+ +
+
+ +
+
+
+
+
+
+
+ +
+ + +
+
diff --git a/apps/landing/src/components/landing/WhyCaplets.astro b/apps/landing/src/components/landing/WhyCaplets.astro new file mode 100644 index 00000000..8a1e5aaa --- /dev/null +++ b/apps/landing/src/components/landing/WhyCaplets.astro @@ -0,0 +1,44 @@ +--- +import Route from "@tabler/icons/outline/route.svg"; + +import { whyCapletsProblems } from "../../data/landing"; +--- + +
+
+
+

Why Caplets

+

+ Agents do not need every tool at once. +

+

+ Direct MCP flattens provider APIs into the prompt. The agent spends context reading tool names, giant schemas, and setup assumptions before it can do the work. +

+

+ Caplets keeps the first surface small, then opens the exact operation path when the agent asks. +

+
+ +
+
+ Direct MCP +
+
+ { + whyCapletsProblems.map((item) => ( +
+
+

{item.label}

+

{item.before}

+
+ +

{item.after}

+
+ )) + } +
+
+
+
diff --git a/apps/landing/src/components/starwind/badge/Badge.astro b/apps/landing/src/components/starwind/badge/Badge.astro new file mode 100644 index 00000000..dcdf7a2e --- /dev/null +++ b/apps/landing/src/components/starwind/badge/Badge.astro @@ -0,0 +1,17 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { badge } from "./variants"; + +interface Props + extends HTMLAttributes<"div">, Omit, "type">, VariantProps {} + +const { variant, size, class: className, ...rest } = Astro.props; +const isLink = Astro.props.href ? true : false; +const Tag = Astro.props.href ? "a" : "div"; +--- + + + + diff --git a/apps/landing/src/components/starwind/badge/index.ts b/apps/landing/src/components/starwind/badge/index.ts new file mode 100644 index 00000000..53fcc369 --- /dev/null +++ b/apps/landing/src/components/starwind/badge/index.ts @@ -0,0 +1,7 @@ +import Badge from "./Badge.astro"; +import { badge } from "./variants"; +const BadgeVariants = { badge }; + +export { Badge, BadgeVariants }; + +export default Badge; diff --git a/apps/landing/src/components/starwind/badge/variants.ts b/apps/landing/src/components/starwind/badge/variants.ts new file mode 100644 index 00000000..3a9358ce --- /dev/null +++ b/apps/landing/src/components/starwind/badge/variants.ts @@ -0,0 +1,41 @@ +import { tv } from "tailwind-variants"; + +export const badge = tv({ + base: [ + "starwind-badge inline-flex items-center gap-1.5 rounded-full font-medium whitespace-nowrap", + "[&_svg]:pointer-events-none [&_svg]:shrink-0", + "transition-all outline-none focus-visible:ring-3", + "aria-invalid:border-error aria-invalid:focus-visible:ring-error/40", + ], + variants: { + variant: { + default: "bg-foreground text-background focus-visible:ring-outline/50", + primary: "bg-primary text-primary-foreground focus-visible:ring-primary/50", + secondary: "bg-secondary text-secondary-foreground focus-visible:ring-secondary/50", + outline: "border-border focus-visible:border-outline focus-visible:ring-outline/50 border", + ghost: "bg-foreground/10 text-foreground focus-visible:ring-outline/50", + info: "bg-info text-info-foreground focus-visible:ring-info/50", + success: "bg-success text-success-foreground focus-visible:ring-success/50", + warning: "bg-warning text-warning-foreground focus-visible:ring-warning/50", + error: "bg-error text-error-foreground focus-visible:ring-error/50", + }, + size: { + sm: "px-2.5 py-0.5 text-xs [&_svg:not([class*='size-'])]:size-3", + md: "px-3 py-0.5 text-sm [&_svg:not([class*='size-'])]:size-4", + lg: "px-4 py-1 text-base [&_svg:not([class*='size-'])]:size-4.5", + }, + isLink: { true: "cursor-pointer", false: "" }, + }, + compoundVariants: [ + { isLink: true, variant: "default", className: "hover:bg-foreground/80" }, + { isLink: true, variant: "primary", className: "hover:bg-primary/80" }, + { isLink: true, variant: "secondary", className: "hover:bg-secondary/80" }, + { isLink: true, variant: "outline", className: "hover:border-border/80" }, + { isLink: true, variant: "ghost", className: "hover:bg-foreground/7" }, + { isLink: true, variant: "info", className: "hover:bg-info/80" }, + { isLink: true, variant: "success", className: "hover:bg-success/80" }, + { isLink: true, variant: "warning", className: "hover:bg-warning/80" }, + { isLink: true, variant: "error", className: "hover:bg-error/80" }, + ], + defaultVariants: { variant: "default", size: "md", isLink: false }, +}); diff --git a/apps/landing/src/components/starwind/button/Button.astro b/apps/landing/src/components/starwind/button/Button.astro new file mode 100644 index 00000000..9e0885ae --- /dev/null +++ b/apps/landing/src/components/starwind/button/Button.astro @@ -0,0 +1,20 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { button } from "./variants"; + +interface Props + extends + HTMLAttributes<"button">, + Omit, "type">, + VariantProps {} + +const { variant, size, class: className, ...rest } = Astro.props; + +const Tag = Astro.props.href ? "a" : "button"; +--- + + + + diff --git a/apps/landing/src/components/starwind/button/index.ts b/apps/landing/src/components/starwind/button/index.ts new file mode 100644 index 00000000..16de9b64 --- /dev/null +++ b/apps/landing/src/components/starwind/button/index.ts @@ -0,0 +1,7 @@ +import Button from "./Button.astro"; +import { button } from "./variants"; +const ButtonVariants = { button }; + +export { Button, ButtonVariants }; + +export default Button; diff --git a/apps/landing/src/components/starwind/button/variants.ts b/apps/landing/src/components/starwind/button/variants.ts new file mode 100644 index 00000000..23e8b831 --- /dev/null +++ b/apps/landing/src/components/starwind/button/variants.ts @@ -0,0 +1,38 @@ +import { tv } from "tailwind-variants"; + +export const button = tv({ + base: [ + "inline-flex items-center justify-center gap-1.5 rounded-md font-medium whitespace-nowrap", + "[&_svg]:pointer-events-none [&_svg]:shrink-0", + "transition-all outline-none focus-visible:ring-3", + "disabled:pointer-events-none disabled:opacity-50", + "aria-invalid:border-error aria-invalid:focus-visible:ring-error/40", + ], + variants: { + variant: { + default: "bg-foreground text-background hover:bg-foreground/90 focus-visible:ring-outline/50", + primary: + "bg-primary text-primary-foreground hover:bg-primary/90 focus-visible:ring-primary/50", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/90 focus-visible:ring-secondary/50", + outline: + "dark:border-input focus-visible:ring-outline/50 bg-background dark:bg-input/30 focus-visible:border-outline hover:bg-muted dark:hover:bg-input/50 hover:text-foreground border shadow-xs", + ghost: "hover:bg-muted hover:text-foreground focus-visible:ring-outline/50", + info: "bg-info text-info-foreground hover:bg-info/90 focus-visible:ring-info/50", + success: + "bg-success text-success-foreground hover:bg-success/90 focus-visible:ring-success/50", + warning: + "bg-warning text-warning-foreground hover:bg-warning/90 focus-visible:ring-warning/50", + error: "bg-error text-error-foreground hover:bg-error/90 focus-visible:ring-error/50", + }, + size: { + sm: "h-9 px-4 text-sm has-[>svg]:px-3 [&_svg:not([class*='size-'])]:size-3.5", + md: "h-11 px-5 text-base has-[>svg]:px-4 [&_svg:not([class*='size-'])]:size-4.5", + lg: "h-12 px-8 text-lg has-[>svg]:px-6 [&_svg:not([class*='size-'])]:size-5", + "icon-sm": "size-9 [&_svg:not([class*='size-'])]:size-3.5", + icon: "size-11 [&_svg:not([class*='size-'])]:size-4.5", + "icon-lg": "size-12 [&_svg:not([class*='size-'])]:size-5", + }, + }, + defaultVariants: { variant: "default", size: "md" }, +}); diff --git a/apps/landing/src/components/starwind/card/Card.astro b/apps/landing/src/components/starwind/card/Card.astro new file mode 100644 index 00000000..8af25541 --- /dev/null +++ b/apps/landing/src/components/starwind/card/Card.astro @@ -0,0 +1,19 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { card } from "./variants"; + +type Props = HTMLAttributes<"div"> & VariantProps; + +const { class: className, size, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/card/CardAction.astro b/apps/landing/src/components/starwind/card/CardAction.astro new file mode 100644 index 00000000..17965904 --- /dev/null +++ b/apps/landing/src/components/starwind/card/CardAction.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { cardAction } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/card/CardContent.astro b/apps/landing/src/components/starwind/card/CardContent.astro new file mode 100644 index 00000000..365e809c --- /dev/null +++ b/apps/landing/src/components/starwind/card/CardContent.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { cardContent } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/card/CardDescription.astro b/apps/landing/src/components/starwind/card/CardDescription.astro new file mode 100644 index 00000000..8b5079b3 --- /dev/null +++ b/apps/landing/src/components/starwind/card/CardDescription.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { cardDescription } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/card/CardFooter.astro b/apps/landing/src/components/starwind/card/CardFooter.astro new file mode 100644 index 00000000..1ba4323e --- /dev/null +++ b/apps/landing/src/components/starwind/card/CardFooter.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { cardFooter } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/card/CardHeader.astro b/apps/landing/src/components/starwind/card/CardHeader.astro new file mode 100644 index 00000000..011353be --- /dev/null +++ b/apps/landing/src/components/starwind/card/CardHeader.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { cardHeader } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/card/CardTitle.astro b/apps/landing/src/components/starwind/card/CardTitle.astro new file mode 100644 index 00000000..25f74e97 --- /dev/null +++ b/apps/landing/src/components/starwind/card/CardTitle.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { cardTitle } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/card/index.ts b/apps/landing/src/components/starwind/card/index.ts new file mode 100644 index 00000000..747f5313 --- /dev/null +++ b/apps/landing/src/components/starwind/card/index.ts @@ -0,0 +1,46 @@ +import Card from "./Card.astro"; +import CardAction from "./CardAction.astro"; +import CardContent from "./CardContent.astro"; +import CardDescription from "./CardDescription.astro"; +import CardFooter from "./CardFooter.astro"; +import CardHeader from "./CardHeader.astro"; +import CardTitle from "./CardTitle.astro"; +import { + card, + cardAction, + cardContent, + cardDescription, + cardFooter, + cardHeader, + cardTitle, +} from "./variants"; +const CardVariants = { + card, + cardAction, + cardContent, + cardDescription, + cardFooter, + cardHeader, + cardTitle, +}; + +export { + Card, + CardAction, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, + CardVariants, +}; + +export default { + Root: Card, + Header: CardHeader, + Footer: CardFooter, + Title: CardTitle, + Description: CardDescription, + Content: CardContent, + Action: CardAction, +}; diff --git a/apps/landing/src/components/starwind/card/variants.ts b/apps/landing/src/components/starwind/card/variants.ts new file mode 100644 index 00000000..74aba5b3 --- /dev/null +++ b/apps/landing/src/components/starwind/card/variants.ts @@ -0,0 +1,45 @@ +import { tv } from "tailwind-variants"; + +export const card = tv({ + base: [ + "bg-card text-card-foreground group/card ring-border flex flex-col rounded-xl ring-1", + "has-data-[slot=card-footer]:pb-0 has-[>img:first-child]:pt-0", + "*:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl", + ], + variants: { + size: { + default: "gap-6 py-6", + sm: "gap-4 py-4 text-sm", + }, + }, + defaultVariants: { + size: "default", + }, +}); + +export const cardAction = tv({ + base: "col-start-2 row-span-2 row-start-1 self-start justify-self-end", +}); + +export const cardContent = tv({ + base: "px-6 group-data-[size=sm]/card:px-4", +}); + +export const cardDescription = tv({ + base: "text-muted-foreground text-base group-data-[size=sm]/card:text-sm", +}); + +export const cardFooter = tv({ + base: "bg-muted/50 flex items-center rounded-b-xl border-t p-6 group-data-[size=sm]/card:p-4", +}); + +export const cardHeader = tv({ + base: [ + "@container/card-header grid auto-rows-min items-start gap-1 px-6 group-data-[size=sm]/card:px-4", + "has-data-[slot=card-action]:grid-cols-[1fr_auto] has-data-[slot=card-description]:grid-rows-[auto_auto]", + ], +}); + +export const cardTitle = tv({ + base: "font-heading text-xl leading-snug font-medium group-data-[size=sm]/card:text-base", +}); diff --git a/apps/landing/src/components/starwind/dialog/Dialog.astro b/apps/landing/src/components/starwind/dialog/Dialog.astro new file mode 100644 index 00000000..5398c62a --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/Dialog.astro @@ -0,0 +1,396 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
+ + + + diff --git a/apps/landing/src/components/starwind/dialog/DialogClose.astro b/apps/landing/src/components/starwind/dialog/DialogClose.astro new file mode 100644 index 00000000..49a24d83 --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/DialogClose.astro @@ -0,0 +1,35 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +type Props = HTMLAttributes<"button"> & { + /** + * When true, the component will render its child element instead of a button + */ + asChild?: boolean; +}; + +const { class: className, asChild = false, ...rest } = Astro.props; + +// Get the first child element if asChild is true +let hasChildren = false; +if (Astro.slots.has("default")) { + hasChildren = true; +} +--- + +{ + asChild && hasChildren ? ( +
+ +
+ ) : ( + + ) +} diff --git a/apps/landing/src/components/starwind/dialog/DialogContent.astro b/apps/landing/src/components/starwind/dialog/DialogContent.astro new file mode 100644 index 00000000..1a48dc0e --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/DialogContent.astro @@ -0,0 +1,50 @@ +--- +import X from "@tabler/icons/outline/x.svg"; +import type { HTMLAttributes } from "astro/types"; + +import { dialogBackdrop, dialogCloseButton, dialogContent } from "./variants"; + +type Props = HTMLAttributes<"dialog"> & { + /** + * Open and close animation duration in milliseconds + */ + animationDuration?: number; +}; + +const { class: className, animationDuration = 200, ...rest } = Astro.props; +--- + + + +
+
+
+ + + + +
+
+ + diff --git a/apps/landing/src/components/starwind/dialog/DialogDescription.astro b/apps/landing/src/components/starwind/dialog/DialogDescription.astro new file mode 100644 index 00000000..1a338e7c --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/DialogDescription.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { dialogDescription } from "./variants"; + +type Props = HTMLAttributes<"p">; + +const { class: className, ...rest } = Astro.props; +--- + +

+ +

diff --git a/apps/landing/src/components/starwind/dialog/DialogFooter.astro b/apps/landing/src/components/starwind/dialog/DialogFooter.astro new file mode 100644 index 00000000..a4dbdc82 --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/DialogFooter.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { dialogFooter } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/dialog/DialogHeader.astro b/apps/landing/src/components/starwind/dialog/DialogHeader.astro new file mode 100644 index 00000000..524bee75 --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/DialogHeader.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { dialogHeader } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/dialog/DialogTitle.astro b/apps/landing/src/components/starwind/dialog/DialogTitle.astro new file mode 100644 index 00000000..b27402bf --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/DialogTitle.astro @@ -0,0 +1,19 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { dialogTitle } from "./variants"; + +type Props = Omit, "id"> & { + /** + * The content to be rendered inside the dialog title + */ + + children: any; +}; + +const { class: className, ...rest } = Astro.props; +--- + +

+ +

diff --git a/apps/landing/src/components/starwind/dialog/DialogTrigger.astro b/apps/landing/src/components/starwind/dialog/DialogTrigger.astro new file mode 100644 index 00000000..6bdd4d53 --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/DialogTrigger.astro @@ -0,0 +1,48 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +type Props = HTMLAttributes<"button"> & { + /** + * When true, the component will render its child element with a simple wrapper instead of a button component + */ + asChild?: boolean; + /** + * Optional ID of the dialog to trigger. If not provided and the trigger is inside a Dialog component, + * it will automatically target that dialog. Required when used outside a Dialog component. + */ + for?: string; +}; + +const { class: className, asChild = false, for: dialogFor, ...rest } = Astro.props; + +// Get the first child element if asChild is true +let hasChildren = false; +if (Astro.slots.has("default")) { + hasChildren = true; +} +--- + +{ + asChild && hasChildren ? ( +
+ +
+ ) : ( + + ) +} diff --git a/apps/landing/src/components/starwind/dialog/index.ts b/apps/landing/src/components/starwind/dialog/index.ts new file mode 100644 index 00000000..31c3bfd7 --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/index.ts @@ -0,0 +1,50 @@ +import Dialog from "./Dialog.astro"; +import DialogClose from "./DialogClose.astro"; +import DialogContent from "./DialogContent.astro"; +import DialogDescription from "./DialogDescription.astro"; +import DialogFooter from "./DialogFooter.astro"; +import DialogHeader from "./DialogHeader.astro"; +import DialogTitle from "./DialogTitle.astro"; +import DialogTrigger from "./DialogTrigger.astro"; +import { + dialogBackdrop, + dialogCloseButton, + dialogContent, + dialogDescription, + dialogFooter, + dialogHeader, + dialogTitle, +} from "./variants"; + +const DialogVariants = { + dialogBackdrop, + dialogContent, + dialogCloseButton, + dialogDescription, + dialogFooter, + dialogHeader, + dialogTitle, +}; + +export { + Dialog, + DialogClose, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, + DialogVariants, +}; + +export default { + Root: Dialog, + Trigger: DialogTrigger, + Content: DialogContent, + Header: DialogHeader, + Footer: DialogFooter, + Title: DialogTitle, + Description: DialogDescription, + Close: DialogClose, +}; diff --git a/apps/landing/src/components/starwind/dialog/variants.ts b/apps/landing/src/components/starwind/dialog/variants.ts new file mode 100644 index 00000000..5e8c8f4c --- /dev/null +++ b/apps/landing/src/components/starwind/dialog/variants.ts @@ -0,0 +1,41 @@ +import { tv } from "tailwind-variants"; + +export const dialogBackdrop = tv({ + base: [ + "starwind-dialog-backdrop fixed inset-0 top-0 left-0 z-50 hidden h-screen w-screen bg-black/80", + "data-[state=open]:animate-in fade-in", + "data-[state=closed]:animate-out data-[state=closed]:fill-mode-forwards fade-out", + ], +}); + +export const dialogContent = tv({ + base: [ + "starwind-dialog-content", + "fixed top-16 left-[50%] z-50 translate-x-[-50%] sm:top-[50%] sm:translate-y-[-50%]", + "bg-background w-full max-w-md rounded-lg border p-8 shadow-lg", + "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fill-mode-forwards transition-[translate,scale,opacity]", + "fade-in zoom-in-95 slide-in-from-bottom-2", + "fade-out zoom-out-95 slide-out-to-bottom-2", + "data-[state=open]:data-[nested-dialog-open]:-translate-y-[calc(50%-var(--nested-offset)*var(--nested-dialogs,1))]", + "data-[state=open]:data-[nested-dialog-open]:scale-[calc(1-var(--nested-scale)*var(--nested-dialogs,1))]", + "max-sm:data-[state=open]:data-[nested-dialog-open]:translate-y-[calc(var(--nested-offset)*var(--nested-dialogs,1))]", + ], +}); + +export const dialogCloseButton = tv({ + base: [ + "starwind-dialog-close text-muted-foreground", + "absolute top-5.5 right-5.5 rounded-sm [&>svg]:opacity-70 hover:[&>svg]:opacity-100", + "focus-visible:ring-outline/50 transition-[color,box-shadow] outline-none focus-visible:ring-3", + ], +}); + +export const dialogDescription = tv({ base: "text-muted-foreground" }); + +export const dialogFooter = tv({ base: "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end" }); + +export const dialogHeader = tv({ base: "flex flex-col gap-2 text-center sm:text-left" }); + +export const dialogTitle = tv({ + base: "font-heading text-xl leading-none font-semibold tracking-tight", +}); diff --git a/apps/landing/src/components/starwind/separator/Separator.astro b/apps/landing/src/components/starwind/separator/Separator.astro new file mode 100644 index 00000000..01fe5d73 --- /dev/null +++ b/apps/landing/src/components/starwind/separator/Separator.astro @@ -0,0 +1,24 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { separator } from "./variants"; + +type Props = Omit, "role" | "aria-orientation"> & { + /** + * The orientation of the separator. + * @default "horizontal" + */ + orientation?: "horizontal" | "vertical"; +}; + +const { class: className, orientation = "horizontal", ...rest } = Astro.props; +--- + + diff --git a/apps/landing/src/components/starwind/separator/index.ts b/apps/landing/src/components/starwind/separator/index.ts new file mode 100644 index 00000000..5ed66113 --- /dev/null +++ b/apps/landing/src/components/starwind/separator/index.ts @@ -0,0 +1,7 @@ +import Separator from "./Separator.astro"; +import { separator } from "./variants"; +const SeparatorVariants = { separator }; + +export { Separator, SeparatorVariants }; + +export default Separator; diff --git a/apps/landing/src/components/starwind/separator/variants.ts b/apps/landing/src/components/starwind/separator/variants.ts new file mode 100644 index 00000000..d3c16b34 --- /dev/null +++ b/apps/landing/src/components/starwind/separator/variants.ts @@ -0,0 +1,14 @@ +import { tv } from "tailwind-variants"; + +export const separator = tv({ + base: "bg-border shrink-0", + variants: { + orientation: { + horizontal: "h-[1px] w-full", + vertical: "h-full w-[1px]", + }, + }, + defaultVariants: { + orientation: "horizontal", + }, +}); diff --git a/apps/landing/src/components/starwind/sheet/Sheet.astro b/apps/landing/src/components/starwind/sheet/Sheet.astro new file mode 100644 index 00000000..21a257cf --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/Sheet.astro @@ -0,0 +1,13 @@ +--- +import type { ComponentProps } from "astro/types"; + +import { Dialog } from "@/components/starwind/dialog"; + +type Props = ComponentProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/sheet/SheetClose.astro b/apps/landing/src/components/starwind/sheet/SheetClose.astro new file mode 100644 index 00000000..87d3402f --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/SheetClose.astro @@ -0,0 +1,13 @@ +--- +import type { ComponentProps } from "astro/types"; + +import { DialogClose } from "@/components/starwind/dialog"; + +type Props = ComponentProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/sheet/SheetContent.astro b/apps/landing/src/components/starwind/sheet/SheetContent.astro new file mode 100644 index 00000000..2c2128a7 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/SheetContent.astro @@ -0,0 +1,45 @@ +--- +import X from "@tabler/icons/outline/x.svg"; +import type { HTMLAttributes } from "astro/types"; + +import { dialogBackdrop, sheetCloseButton, sheetContent } from "./variants"; + +type Props = HTMLAttributes<"dialog"> & { + /** + * Side of the page the sheet opens from + */ + side?: "top" | "right" | "bottom" | "left"; +}; + +const { side = "right", class: className, ...rest } = Astro.props; +--- + + + +
+
+ + + + +
+
diff --git a/apps/landing/src/components/starwind/sheet/SheetDescription.astro b/apps/landing/src/components/starwind/sheet/SheetDescription.astro new file mode 100644 index 00000000..9c2f8076 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/SheetDescription.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { sheetDescription } from "./variants"; + +type Props = HTMLAttributes<"p">; + +const { class: className, ...rest } = Astro.props; +--- + +

+ +

diff --git a/apps/landing/src/components/starwind/sheet/SheetFooter.astro b/apps/landing/src/components/starwind/sheet/SheetFooter.astro new file mode 100644 index 00000000..0e903999 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/SheetFooter.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { sheetFooter } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/sheet/SheetHeader.astro b/apps/landing/src/components/starwind/sheet/SheetHeader.astro new file mode 100644 index 00000000..6c4b7da4 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/SheetHeader.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { sheetHeader } from "./variants"; + +type Props = HTMLAttributes<"div">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/sheet/SheetTitle.astro b/apps/landing/src/components/starwind/sheet/SheetTitle.astro new file mode 100644 index 00000000..23aca7a0 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/SheetTitle.astro @@ -0,0 +1,13 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { sheetTitle } from "./variants"; + +type Props = HTMLAttributes<"h2">; + +const { class: className, ...rest } = Astro.props; +--- + +

+ +

diff --git a/apps/landing/src/components/starwind/sheet/SheetTrigger.astro b/apps/landing/src/components/starwind/sheet/SheetTrigger.astro new file mode 100644 index 00000000..064ae190 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/SheetTrigger.astro @@ -0,0 +1,13 @@ +--- +import type { ComponentProps } from "astro/types"; + +import { DialogTrigger } from "@/components/starwind/dialog"; + +type Props = ComponentProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/sheet/index.ts b/apps/landing/src/components/starwind/sheet/index.ts new file mode 100644 index 00000000..50746836 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/index.ts @@ -0,0 +1,50 @@ +import Sheet from "./Sheet.astro"; +import SheetClose from "./SheetClose.astro"; +import SheetContent from "./SheetContent.astro"; +import SheetDescription from "./SheetDescription.astro"; +import SheetFooter from "./SheetFooter.astro"; +import SheetHeader from "./SheetHeader.astro"; +import SheetTitle from "./SheetTitle.astro"; +import SheetTrigger from "./SheetTrigger.astro"; +import { + dialogBackdrop, + sheetCloseButton, + sheetContent, + sheetDescription, + sheetFooter, + sheetHeader, + sheetTitle, +} from "./variants"; + +const SheetVariants = { + sheetCloseButton, + sheetDescription, + sheetFooter, + sheetHeader, + sheetTitle, + dialogBackdrop, + sheetContent, +}; + +export { + Sheet, + SheetClose, + SheetContent, + SheetDescription, + SheetFooter, + SheetHeader, + SheetTitle, + SheetTrigger, + SheetVariants, +}; + +export default { + Root: Sheet, + Trigger: SheetTrigger, + Content: SheetContent, + Header: SheetHeader, + Footer: SheetFooter, + Title: SheetTitle, + Description: SheetDescription, + Close: SheetClose, +}; diff --git a/apps/landing/src/components/starwind/sheet/variants.ts b/apps/landing/src/components/starwind/sheet/variants.ts new file mode 100644 index 00000000..37e593c5 --- /dev/null +++ b/apps/landing/src/components/starwind/sheet/variants.ts @@ -0,0 +1,66 @@ +import { tv } from "tailwind-variants"; + +export const dialogBackdrop = tv({ + base: [ + "starwind-dialog-backdrop fixed inset-0 top-0 left-0 z-50 hidden h-screen w-screen bg-black/80", + "data-[state=open]:animate-in fade-in", + "data-[state=closed]:animate-out data-[state=closed]:fill-mode-forwards fade-out", + "data-[state=closed]:duration-300 data-[state=open]:duration-500", + ], +}); + +export const sheetContent = tv({ + base: [ + "starwind-dialog-content", + "bg-background fixed z-50 flex-col gap-4 shadow-lg transition ease-in-out open:flex", + "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fill-mode-forwards", + "data-[state=closed]:duration-300 data-[state=open]:duration-500", + ], + variants: { + side: { + right: [ + "slide-out-to-right slide-in-from-right", + "inset-y-0 right-0 left-auto h-full max-h-[100dvh] w-3/4 border-l sm:max-w-sm", + ], + left: [ + "slide-out-to-left slide-in-from-left", + "inset-y-0 right-auto left-0 h-full max-h-[100dvh] w-3/4 border-r sm:max-w-sm", + ], + top: [ + "slide-out-to-top slide-in-from-top", + "inset-x-0 top-0 bottom-auto h-auto w-full max-w-screen border-b", + ], + bottom: [ + "slide-out-to-bottom slide-in-from-bottom", + "inset-x-0 top-auto bottom-0 h-auto w-full max-w-screen border-t", + ], + }, + }, + defaultVariants: { + side: "right", + }, +}); + +export const sheetCloseButton = tv({ + base: [ + "starwind-dialog-close", + "absolute top-4 right-4 rounded-xs [&>svg]:opacity-70 hover:[&>svg]:opacity-100", + "focus-visible:ring-outline/50 transition-[color,box-shadow] outline-none focus-visible:ring-3", + ], +}); + +export const sheetDescription = tv({ + base: ["text-muted-foreground text-sm"], +}); + +export const sheetFooter = tv({ + base: ["mt-auto flex flex-col gap-2 p-4"], +}); + +export const sheetHeader = tv({ + base: ["flex flex-col gap-1.5 p-4"], +}); + +export const sheetTitle = tv({ + base: ["starwind-sheet-title", "text-foreground font-heading font-semibold"], +}); diff --git a/apps/landing/src/components/starwind/table/Table.astro b/apps/landing/src/components/starwind/table/Table.astro new file mode 100644 index 00000000..3afe2506 --- /dev/null +++ b/apps/landing/src/components/starwind/table/Table.astro @@ -0,0 +1,16 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { table } from "./variants"; + +type Props = HTMLAttributes<"table"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + +
+ + +
+
diff --git a/apps/landing/src/components/starwind/table/TableBody.astro b/apps/landing/src/components/starwind/table/TableBody.astro new file mode 100644 index 00000000..8638ba56 --- /dev/null +++ b/apps/landing/src/components/starwind/table/TableBody.astro @@ -0,0 +1,14 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { tableBody } from "./variants"; + +type Props = HTMLAttributes<"tbody"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/table/TableCaption.astro b/apps/landing/src/components/starwind/table/TableCaption.astro new file mode 100644 index 00000000..6a49a3bc --- /dev/null +++ b/apps/landing/src/components/starwind/table/TableCaption.astro @@ -0,0 +1,14 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { tableCaption } from "./variants"; + +type Props = HTMLAttributes<"caption"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/table/TableCell.astro b/apps/landing/src/components/starwind/table/TableCell.astro new file mode 100644 index 00000000..e244f175 --- /dev/null +++ b/apps/landing/src/components/starwind/table/TableCell.astro @@ -0,0 +1,14 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { tableCell } from "./variants"; + +type Props = HTMLAttributes<"td"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/table/TableFoot.astro b/apps/landing/src/components/starwind/table/TableFoot.astro new file mode 100644 index 00000000..70e7ab10 --- /dev/null +++ b/apps/landing/src/components/starwind/table/TableFoot.astro @@ -0,0 +1,14 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { tableFoot } from "./variants"; + +type Props = HTMLAttributes<"tfoot"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/table/TableHead.astro b/apps/landing/src/components/starwind/table/TableHead.astro new file mode 100644 index 00000000..12a69f29 --- /dev/null +++ b/apps/landing/src/components/starwind/table/TableHead.astro @@ -0,0 +1,14 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { tableHead } from "./variants"; + +type Props = HTMLAttributes<"th"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/table/TableHeader.astro b/apps/landing/src/components/starwind/table/TableHeader.astro new file mode 100644 index 00000000..59bff533 --- /dev/null +++ b/apps/landing/src/components/starwind/table/TableHeader.astro @@ -0,0 +1,14 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { tableHeader } from "./variants"; + +type Props = HTMLAttributes<"thead"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/table/TableRow.astro b/apps/landing/src/components/starwind/table/TableRow.astro new file mode 100644 index 00000000..f98dd1ac --- /dev/null +++ b/apps/landing/src/components/starwind/table/TableRow.astro @@ -0,0 +1,14 @@ +--- +import type { HTMLAttributes } from "astro/types"; +import type { VariantProps } from "tailwind-variants"; + +import { tableRow } from "./variants"; + +type Props = HTMLAttributes<"tr"> & VariantProps; + +const { class: className, ...rest } = Astro.props; +--- + + + + diff --git a/apps/landing/src/components/starwind/table/index.ts b/apps/landing/src/components/starwind/table/index.ts new file mode 100644 index 00000000..8c021208 --- /dev/null +++ b/apps/landing/src/components/starwind/table/index.ts @@ -0,0 +1,51 @@ +import Table from "./Table.astro"; +import TableBody from "./TableBody.astro"; +import TableCaption from "./TableCaption.astro"; +import TableCell from "./TableCell.astro"; +import TableFoot from "./TableFoot.astro"; +import TableHead from "./TableHead.astro"; +import TableHeader from "./TableHeader.astro"; +import TableRow from "./TableRow.astro"; +import { + table, + tableBody, + tableCaption, + tableCell, + tableFoot, + tableHead, + tableHeader, + tableRow, +} from "./variants"; +const TableVariants = { + table, + tableBody, + tableCaption, + tableCell, + tableFoot, + tableHead, + tableHeader, + tableRow, +}; + +export { + Table, + TableBody, + TableCaption, + TableCell, + TableFoot, + TableHead, + TableHeader, + TableRow, + TableVariants, +}; + +export default { + Root: Table, + Body: TableBody, + Caption: TableCaption, + Cell: TableCell, + Foot: TableFoot, + Head: TableHead, + Header: TableHeader, + Row: TableRow, +}; diff --git a/apps/landing/src/components/starwind/table/variants.ts b/apps/landing/src/components/starwind/table/variants.ts new file mode 100644 index 00000000..9e80ed12 --- /dev/null +++ b/apps/landing/src/components/starwind/table/variants.ts @@ -0,0 +1,33 @@ +import { tv } from "tailwind-variants"; + +export const table = tv({ + base: "w-full caption-bottom text-sm", +}); + +export const tableBody = tv({ + base: "[&_tr:last-child]:border-0", +}); + +export const tableCaption = tv({ + base: "text-muted-foreground mt-4 text-sm", +}); + +export const tableCell = tv({ + base: "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", +}); + +export const tableFoot = tv({ + base: "bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", +}); + +export const tableHead = tv({ + base: "text-muted-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]", +}); + +export const tableHeader = tv({ + base: "[&_tr]:border-b", +}); + +export const tableRow = tv({ + base: "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors", +}); diff --git a/apps/landing/src/components/starwind/tabs/Tabs.astro b/apps/landing/src/components/starwind/tabs/Tabs.astro new file mode 100644 index 00000000..35f96bf2 --- /dev/null +++ b/apps/landing/src/components/starwind/tabs/Tabs.astro @@ -0,0 +1,270 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { tabs } from "./variants"; + +interface Props extends HTMLAttributes<"div"> { + defaultValue?: string; + syncKey?: string; +} + +const { defaultValue, syncKey, class: className, ...rest } = Astro.props; +--- + +
+ +
+ + diff --git a/apps/landing/src/components/starwind/tabs/TabsContent.astro b/apps/landing/src/components/starwind/tabs/TabsContent.astro new file mode 100644 index 00000000..e17f1ecb --- /dev/null +++ b/apps/landing/src/components/starwind/tabs/TabsContent.astro @@ -0,0 +1,25 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { tabsContent } from "./variants"; + +interface Props extends Omit, "id" | "role" | "tabindex" | "hidden"> { + value: string; +} + +const { value, class: className, ...rest } = Astro.props; +--- + + diff --git a/apps/landing/src/components/starwind/tabs/TabsList.astro b/apps/landing/src/components/starwind/tabs/TabsList.astro new file mode 100644 index 00000000..30ce2c0c --- /dev/null +++ b/apps/landing/src/components/starwind/tabs/TabsList.astro @@ -0,0 +1,19 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { tabsList } from "./variants"; + +type Props = Omit, "role">; + +const { class: className, ...rest } = Astro.props; +--- + +
+ +
diff --git a/apps/landing/src/components/starwind/tabs/TabsTrigger.astro b/apps/landing/src/components/starwind/tabs/TabsTrigger.astro new file mode 100644 index 00000000..396d2733 --- /dev/null +++ b/apps/landing/src/components/starwind/tabs/TabsTrigger.astro @@ -0,0 +1,24 @@ +--- +import type { HTMLAttributes } from "astro/types"; + +import { tabsTrigger } from "./variants"; + +interface Props extends Omit, "type" | "id" | "role"> { + value: string; +} + +const { value, class: className, ...rest } = Astro.props; +--- + + diff --git a/apps/landing/src/components/starwind/tabs/index.ts b/apps/landing/src/components/starwind/tabs/index.ts new file mode 100644 index 00000000..aa7c3c0a --- /dev/null +++ b/apps/landing/src/components/starwind/tabs/index.ts @@ -0,0 +1,20 @@ +import Tabs from "./Tabs.astro"; +import TabsContent from "./TabsContent.astro"; +import TabsList from "./TabsList.astro"; +import TabsTrigger from "./TabsTrigger.astro"; +import { tabs, tabsContent, tabsList, tabsTrigger } from "./variants"; +const TabsVariants = { + tabs, + tabsContent, + tabsList, + tabsTrigger, +}; + +export { Tabs, TabsContent, TabsList, TabsTrigger, TabsVariants }; + +export default { + Root: Tabs, + Content: TabsContent, + List: TabsList, + Trigger: TabsTrigger, +}; diff --git a/apps/landing/src/components/starwind/tabs/variants.ts b/apps/landing/src/components/starwind/tabs/variants.ts new file mode 100644 index 00000000..915b6c89 --- /dev/null +++ b/apps/landing/src/components/starwind/tabs/variants.ts @@ -0,0 +1,22 @@ +import { tv } from "tailwind-variants"; + +export const tabs = tv({ base: "starwind-tabs" }); + +export const tabsContent = tv({ + base: "mt-2 focus-visible:outline-2 focus-visible:outline-offset-2", +}); + +export const tabsList = tv({ + base: "bg-muted text-muted-foreground inline-flex w-fit items-center justify-center rounded-md p-1", +}); + +export const tabsTrigger = tv({ + base: [ + "inline-flex grow items-center justify-center gap-2 rounded-sm border border-transparent px-3 py-1.5 font-medium whitespace-nowrap transition-[color,box-shadow]", + "data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm", + "dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:text-muted-foreground", + "[&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", + "focus-visible:border-outline focus-visible:ring-outline/50 focus-visible:outline-outline focus-visible:ring-3 focus-visible:outline-1", + "disabled:pointer-events-none disabled:opacity-50", + ], +}); diff --git a/apps/landing/src/data/landing.ts b/apps/landing/src/data/landing.ts new file mode 100644 index 00000000..ad79737d --- /dev/null +++ b/apps/landing/src/data/landing.ts @@ -0,0 +1,191 @@ +export const heroCommands = [ + { + label: "Install Caplets", + command: "npm install -g caplets", + }, + { + label: "Wire up your agent", + command: "caplets setup", + }, +] as const; + +export const quickstartCommand = heroCommands.map((item) => item.command).join("\n"); + +export const proofStats = [ + { + value: "10/10", + label: "tasks cleared", + detail: + "Caplets Code Mode, progressive modes, direct MCP, and Executor.sh all completed the task set.", + }, + { + value: "236,803", + label: "avg tokens", + detail: "Request plus output estimate for the Code Mode run, averaged across live Pi evals.", + }, + { + value: "72.0% fewer", + label: "vs vanilla", + detail: "Reduction against direct vanilla MCP without giving up the completed-task result.", + }, +] as const; + +export const benchmarkProvenance = + "Run June 2026 with the real-world large MCP suite, openai-codex/gpt-5.5, 10 tasks, 2 runs per task, and a large no-fixture MCP stack."; + +export const benchmarkRows = [ + { + mode: "Caplets Code Mode", + passed: "10/10", + tokens: "236,803", + surfaceTokens: "31,166", + }, + { + mode: "Caplets progressive + Code Mode", + passed: "10/10", + tokens: "422,861", + surfaceTokens: "124,772", + }, + { + mode: "Caplets progressive", + passed: "10/10", + tokens: "461,171", + surfaceTokens: "103,776", + }, + { + mode: "Executor.sh", + passed: "10/10", + tokens: "675,842", + surfaceTokens: "24,570", + }, + { + mode: "Direct vanilla MCP", + passed: "10/10", + tokens: "846,048", + surfaceTokens: "457,818", + }, +] as const; + +export const deterministicSurface = [ + { label: "flat tool wall", value: "215" }, + { label: "first screen cards", value: "7" }, + { label: "surface cut", value: "79.9%" }, +] as const; + +export const whyCapletsProblems = [ + { + label: "Too many tools", + before: "Every downstream operation lands in the agent's first view.", + after: "The agent starts with a named capability and opens only the route it needs.", + }, + { + label: "Too much schema", + before: "Large tool definitions compete with the user's actual task for context.", + after: "Schemas stay behind inspect, search, and get_tool until they matter.", + }, + { + label: "Too much setup", + before: "Every agent repeats provider wiring, OAuth, secrets, and MCP config.", + after: "One Caplets surface can be reused locally or from a remote server.", + }, +] as const; + +export const remoteCommands = { + server: `CAPLETS_SERVER_URL=https://caplets.example.com/caplets +CAPLETS_SERVER_PASSWORD=... +caplets serve --transport http`, + client: `CAPLETS_REMOTE_PASSWORD=... +caplets attach --remote-url https://caplets.example.com/caplets`, +} as const; + +export const remoteEndpoints = [ + { label: "MCP", value: "/caplets/v1/mcp" }, + { label: "Attach", value: "/caplets/v1/attach" }, + { label: "Admin", value: "/caplets/v1/admin" }, + { label: "Health", value: "/caplets/v1/healthz" }, +] as const; + +export const remoteComparison = [ + { + label: "Client-by-client auth", + detail: "Every agent carries its own provider tokens, OAuth dance, and local MCP wiring.", + points: ["Repeat login flows", "Copy secrets around", "Debug each client separately"], + }, + { + label: "Server-held auth", + detail: "One Caplets server owns provider auth; each agent attaches to the shared surface.", + points: [ + "Keep tokens server-side", + "Reuse from Codex, OpenCode, Pi, Claude", + "Inspect, search, schema, and call from one place", + ], + }, +] as const; + +export const themeColor = "oklch(18% 0.014 100)"; + +export const exampleCaplets = [ + { + id: "osv", + name: "OSV", + summary: + "Vulnerability lookups by package, purl, commit, or batch query, with no auth ceremony.", + why: "Best first install: it proves the Caplet flow before OAuth or provider secrets enter the picture.", + path: ["osv", "inspect", "search_tools", "get_tool", "call_tool"], + steps: [ + { command: "caplets setup", label: "Caplets setup command" }, + { + command: "caplets install spiritledsoftware/caplets osv", + label: "OSV caplet install command", + }, + { command: 'codex "try using the osv caplet"', label: "Codex trial command" }, + ], + help: ["OSV is public. If the trial fails, check Node 24+ and rerun ", "caplets setup", "."], + }, + { + id: "github", + name: "GitHub", + summary: + "Repositories, issues, pull requests, branches, commits, and reviews behind one capability card.", + why: "This is the stress case: a valuable MCP server that is painful when every operation is exposed at once.", + path: ["github", "inspect", "search_tools", "get_tool", "call_tool"], + steps: [ + { command: "export GH_TOKEN=github_pat_...", label: "GitHub token export" }, + { command: "caplets setup", label: "Caplets setup command" }, + { + command: "caplets install spiritledsoftware/caplets github", + label: "GitHub caplet install command", + }, + { command: 'codex "try using the github caplet"', label: "Codex trial command" }, + ], + help: [ + "If setup fails, check Node 24+, rerun ", + "caplets setup", + ", and confirm ", + "GH_TOKEN", + ".", + ], + }, + { + id: "sourcegraph", + name: "Sourcegraph", + summary: + "Hosted code search for examples, references, and implementation patterns across repositories.", + why: "Good for search-first work: the agent asks for matches, then opens only the operations it needs.", + path: ["sourcegraph", "inspect", "search_tools", "get_tool", "call_tool"], + steps: [ + { command: "caplets setup", label: "Caplets setup command" }, + { + command: "caplets install spiritledsoftware/caplets sourcegraph", + label: "Sourcegraph caplet install command", + }, + { command: "caplets auth login sourcegraph", label: "Sourcegraph auth command" }, + { command: 'codex "try using the sourcegraph caplet"', label: "Codex trial command" }, + ], + help: [ + "If setup fails, check Node 24+, rerun ", + "caplets setup", + ", and finish Sourcegraph OAuth login.", + ], + }, +] as const; diff --git a/apps/landing/src/layouts/LandingLayout.astro b/apps/landing/src/layouts/LandingLayout.astro new file mode 100644 index 00000000..f36e6621 --- /dev/null +++ b/apps/landing/src/layouts/LandingLayout.astro @@ -0,0 +1,38 @@ +--- +import "../styles/starwind.css"; +import "../styles/global.css"; +import { themeColor } from "../data/landing"; + +interface Props { + title?: string; + description?: string; +} + +const { + title = "Caplets, capabilities instead of giant tool walls", + description = "Caplets gives coding agents focused capability modes instead of giant MCP tool walls.", +} = Astro.props; +--- + + + + + + + + + + + {title} + + + +
+ + +
+ +
+ + + diff --git a/apps/landing/src/lib/utils/starwind/positioning.ts b/apps/landing/src/lib/utils/starwind/positioning.ts new file mode 100644 index 00000000..af6bd6cc --- /dev/null +++ b/apps/landing/src/lib/utils/starwind/positioning.ts @@ -0,0 +1,318 @@ +export type FloatingSide = "top" | "bottom" | "left" | "right"; +export type FloatingAlign = "start" | "center" | "end"; + +interface Placement { + side: FloatingSide; + align: FloatingAlign; +} + +interface Position { + top: number; + left: number; +} + +interface OverflowAmount { + left: number; + right: number; + top: number; + bottom: number; +} + +export interface ResolvePlacementOptions { + side: FloatingSide; + align: FloatingAlign; + sideOffset: number; + triggerRect: DOMRect; + contentWidth: number; + contentHeight: number; + viewportWidth: number; + viewportHeight: number; + viewportPadding: number; + avoidCollisions?: boolean; +} + +export interface ResolvePlacementResult { + side: FloatingSide; + align: FloatingAlign; + top: number; + left: number; +} + +function getOppositeSide(side: FloatingSide): FloatingSide { + switch (side) { + case "top": + return "bottom"; + case "bottom": + return "top"; + case "left": + return "right"; + case "right": + return "left"; + } +} + +function getOppositeAlign(align: FloatingAlign): FloatingAlign { + switch (align) { + case "start": + return "end"; + case "end": + return "start"; + case "center": + return "center"; + } +} + +function getPlacementCandidates(side: FloatingSide, align: FloatingAlign): Placement[] { + const placements: Placement[] = []; + + const pushUnique = (candidate: Placement) => { + if ( + !placements.some( + (placement) => placement.side === candidate.side && placement.align === candidate.align, + ) + ) { + placements.push(candidate); + } + }; + + const oppositeSide = getOppositeSide(side); + const oppositeAlign = getOppositeAlign(align); + + pushUnique({ side, align }); + pushUnique({ side: oppositeSide, align }); + pushUnique({ side, align: "center" }); + pushUnique({ side: oppositeSide, align: "center" }); + pushUnique({ side, align: oppositeAlign }); + pushUnique({ side: oppositeSide, align: oppositeAlign }); + + if (side === "top" || side === "bottom") { + for (const fallbackAlign of ["start", "center", "end"] as const) { + pushUnique({ side: "right", align: fallbackAlign }); + pushUnique({ side: "left", align: fallbackAlign }); + } + } else { + for (const fallbackAlign of ["start", "center", "end"] as const) { + pushUnique({ side: "bottom", align: fallbackAlign }); + pushUnique({ side: "top", align: fallbackAlign }); + } + } + + return placements; +} + +function getPlacementPosition( + placement: Placement, + triggerRect: DOMRect, + contentWidth: number, + contentHeight: number, + sideOffset: number, +): Position { + let top = 0; + let left = 0; + + if (placement.side === "bottom" || placement.side === "top") { + top = + placement.side === "bottom" + ? triggerRect.bottom + sideOffset + : triggerRect.top - contentHeight - sideOffset; + + if (placement.align === "start") { + left = triggerRect.left; + } else if (placement.align === "end") { + left = triggerRect.right - contentWidth; + } else { + left = triggerRect.left + (triggerRect.width - contentWidth) / 2; + } + } else { + left = + placement.side === "right" + ? triggerRect.right + sideOffset + : triggerRect.left - contentWidth - sideOffset; + + if (placement.align === "start") { + top = triggerRect.top; + } else if (placement.align === "end") { + top = triggerRect.bottom - contentHeight; + } else { + top = triggerRect.top + (triggerRect.height - contentHeight) / 2; + } + } + + return { top, left }; +} + +function clampPositionToViewport( + position: Position, + contentWidth: number, + contentHeight: number, + viewportWidth: number, + viewportHeight: number, + viewportPadding: number, +): Position { + const maxLeft = Math.max(viewportPadding, viewportWidth - contentWidth - viewportPadding); + const maxTop = Math.max(viewportPadding, viewportHeight - contentHeight - viewportPadding); + + return { + left: Math.min(Math.max(viewportPadding, position.left), maxLeft), + top: Math.min(Math.max(viewportPadding, position.top), maxTop), + }; +} + +function getOverflowAmount( + position: Position, + contentWidth: number, + contentHeight: number, + viewportWidth: number, + viewportHeight: number, + viewportPadding: number, +): OverflowAmount { + const right = position.left + contentWidth; + const bottom = position.top + contentHeight; + + return { + left: Math.max(0, viewportPadding - position.left), + top: Math.max(0, viewportPadding - position.top), + right: Math.max(0, right - (viewportWidth - viewportPadding)), + bottom: Math.max(0, bottom - (viewportHeight - viewportPadding)), + }; +} + +function getMainAxisShift( + side: FloatingSide, + preferredPosition: Position, + clampedPosition: Position, +): number { + if (side === "top" || side === "bottom") { + return Math.abs(clampedPosition.top - preferredPosition.top); + } + + return Math.abs(clampedPosition.left - preferredPosition.left); +} + +function getCrossAxisShift( + side: FloatingSide, + preferredPosition: Position, + clampedPosition: Position, +): number { + if (side === "top" || side === "bottom") { + return Math.abs(clampedPosition.left - preferredPosition.left); + } + + return Math.abs(clampedPosition.top - preferredPosition.top); +} + +/** + * Resolves the best side/alignment placement for floating content. + */ +export function resolvePlacement(options: ResolvePlacementOptions): ResolvePlacementResult { + const { + side, + align, + sideOffset, + triggerRect, + contentWidth, + contentHeight, + viewportWidth, + viewportHeight, + viewportPadding, + avoidCollisions = true, + } = options; + + const preferredPlacement: Placement = { side, align }; + + if (!avoidCollisions) { + const preferredPosition = getPlacementPosition( + preferredPlacement, + triggerRect, + contentWidth, + contentHeight, + sideOffset, + ); + + return { + side, + align, + top: preferredPosition.top, + left: preferredPosition.left, + }; + } + + const candidates = getPlacementCandidates(side, align); + + let bestPlacement = candidates[0] ?? preferredPlacement; + let bestPosition = clampPositionToViewport( + getPlacementPosition(bestPlacement, triggerRect, contentWidth, contentHeight, sideOffset), + contentWidth, + contentHeight, + viewportWidth, + viewportHeight, + viewportPadding, + ); + let bestScore = Number.POSITIVE_INFINITY; + + for (const placement of candidates) { + const preferredPosition = getPlacementPosition( + placement, + triggerRect, + contentWidth, + contentHeight, + sideOffset, + ); + const clampedPosition = clampPositionToViewport( + preferredPosition, + contentWidth, + contentHeight, + viewportWidth, + viewportHeight, + viewportPadding, + ); + + const overflow = getOverflowAmount( + preferredPosition, + contentWidth, + contentHeight, + viewportWidth, + viewportHeight, + viewportPadding, + ); + + const overflowTotal = overflow.left + overflow.right + overflow.top + overflow.bottom; + const mainAxisShift = getMainAxisShift(placement.side, preferredPosition, clampedPosition); + const crossAxisShift = getCrossAxisShift(placement.side, preferredPosition, clampedPosition); + + const sidePenalty = placement.side === side ? 0 : 32; + const alignPenalty = placement.align === align ? 0 : 8; + const score = + overflowTotal * 24 + mainAxisShift * 8 + crossAxisShift * 3 + sidePenalty + alignPenalty; + + if (score < bestScore) { + bestScore = score; + bestPlacement = placement; + bestPosition = clampedPosition; + } + } + + return { + side: bestPlacement.side, + align: bestPlacement.align, + top: bestPosition.top, + left: bestPosition.left, + }; +} + +/** + * Returns a transform-origin value that matches the resolved placement. + */ +export function getTransformOrigin(side: FloatingSide, align: FloatingAlign): string { + if (side === "top" || side === "bottom") { + const vertical = side === "bottom" ? "top" : "bottom"; + const horizontal = align === "start" ? "left" : align === "end" ? "right" : "center"; + + return `${horizontal} ${vertical}`; + } + + const horizontal = side === "right" ? "left" : "right"; + const vertical = align === "start" ? "top" : align === "end" ? "bottom" : "center"; + + return `${horizontal} ${vertical}`; +} diff --git a/apps/landing/src/pages/index.astro b/apps/landing/src/pages/index.astro index ce2564ff..cae50101 100644 --- a/apps/landing/src/pages/index.astro +++ b/apps/landing/src/pages/index.astro @@ -1,1572 +1,32 @@ --- -import "../styles/global.css"; -import { Cancel01Icon, CheckIcon, Copy01Icon, Menu01Icon } from "@hugeicons/core-free-icons"; -import HugeIcon from "../components/HugeIcon.astro"; - -const mapModes = [ - { - value: "vanilla", - label: "Vanilla MCP", - shortLabel: "Vanilla", - exposed: "215 tools", - hidden: "0 grouped", - copy: "Every street, alley, and label is pushed into the agent's field of view.", - }, - { - value: "progressive", - label: "Progressive", - shortLabel: "Progressive", - exposed: "7 districts", - hidden: "full city below zoom", - copy: "The city becomes districts first, then reveals operations only when the agent asks.", - }, - { - value: "code_mode", - label: "Code Mode", - shortLabel: "Code Mode", - exposed: "1 route", - hidden: "same capability city", - copy: "The agent follows one typed route while the full tool city stays available behind it.", - default: true, - }, -]; - -const mapStackAccessibleLabel = "GitHub / Context7 / DeepWiki / Playwright / Git / LSP"; -const exposureSurfaces = [ - "direct: caplets__{capletId}__{operationName}", - "progressive: caplets__{capletId} / caplets__github / operation: search_tools", - "code_mode: caplets__code_mode / caplets.github.searchTools() / caplets.github.callTool()", - "mixed: direct_and_code_mode / progressive_and_code_mode", -]; - -const heroCommands = [ - { - label: "Install Caplets", - command: "npm install -g caplets", - }, - { - label: "Wire up your agent", - command: "caplets setup", - }, -]; - -const quickstartCommand = heroCommands.map((item) => item.command).join("\n"); - -const proofStats = [ - { - value: "10/10", - label: "passed", - detail: "Caplets Code Mode and progressive modes matched direct MCP and Executor.sh on the pass-rate baseline.", - }, - { - value: "236,803", - label: "avg tokens", - detail: "Average request + output token estimate across the live Pi eval runs.", - }, - { - value: "72.0% fewer", - label: "vs vanilla", - detail: "Request + output token reduction with the same pass rate.", - }, -]; - -const benchmarkProvenance = - "Run June 2026 with the real-world large MCP suite, openai-codex/gpt-5.5, 10 tasks, 2 runs per task, and a large no-fixture MCP stack."; - -const benchmarkRows = [ - { - mode: "Caplets Code Mode", - passed: "10/10", - tokens: "236,803", - surfaceTokens: "31,166", - }, - { - mode: "Caplets progressive + Code Mode", - passed: "10/10", - tokens: "422,861", - surfaceTokens: "124,772", - }, - { - mode: "Caplets progressive", - passed: "10/10", - tokens: "461,171", - surfaceTokens: "103,776", - }, - { - mode: "Executor.sh", - passed: "10/10", - tokens: "675,842", - surfaceTokens: "24,570", - }, - { - mode: "Direct vanilla MCP", - passed: "10/10", - tokens: "846,048", - surfaceTokens: "457,818", - }, -]; - -const deterministicSurface = [ - { label: "direct flat tools", value: "215" }, - { label: "Caplets cards", value: "7" }, - { label: "payload reduction", value: "79.9%" }, -]; - -const remoteCommands = { - server: `CAPLETS_SERVER_URL=https://caplets.example.com/caplets -CAPLETS_SERVER_PASSWORD=... -caplets serve --transport http`, - client: `CAPLETS_MODE=remote -CAPLETS_SERVER_URL=https://caplets.example.com/caplets -CAPLETS_SERVER_PASSWORD=... -opencode`, -}; - -const remoteEndpoints = [ - { label: "MCP", value: "/caplets/v1/mcp" }, - { label: "Admin", value: "/caplets/v1/admin" }, - { label: "Health", value: "/caplets/v1/healthz" }, -]; - -const remoteComparison = [ - { - label: "Without remote Caplets", - detail: "Each agent client needs its own provider tokens, OAuth login, and local MCP wiring.", - points: ["Repeat auth per client", "Duplicate secrets", "Debug setup in every agent"], - }, - { - label: "With remote Caplets", - detail: "One server holds provider auth; every agent connects to the same capability surface.", - points: ["Auth once on the server", "Reuse from Codex, OpenCode, Pi, Claude", "Inspect, search, schema, call everywhere"], - }, -]; - -const lightThemeColor = "oklch(97% 0.012 85)"; -const darkThemeColor = "oklch(18% 0.014 100)"; - -const exampleCaplets = [ - { - id: "osv", - name: "OSV", - summary: "A small explicit HTTP API for vulnerability lookups by package, purl, commit, or batch query.", - why: "Start here: OSV is public, no-auth, and shows the capability surface without OAuth friction.", - path: ["osv", "inspect", "search_tools", "get_tool", "call_tool"], - steps: [ - { command: "caplets setup", label: "Caplets setup command" }, - { - command: "caplets install spiritledsoftware/caplets osv", - label: "OSV caplet install command", - }, - { command: 'codex "try using the osv caplet"', label: "Codex trial command" }, - ], - help: ["OSV is public and does not need auth; check Node 24+ and ", "caplets setup", "."], - }, - { - id: "github", - name: "GitHub", - summary: "A huge hosted MCP surface for repositories, issues, pull requests, branches, commits, and reviews.", - why: "Use it when the value is avoiding a giant GitHub tool wall.", - path: ["github", "inspect", "search_tools", "get_tool", "call_tool"], - steps: [ - { command: "export GH_TOKEN=github_pat_...", label: "GitHub token export" }, - { command: "caplets setup", label: "Caplets setup command" }, - { - command: "caplets install spiritledsoftware/caplets github", - label: "GitHub caplet install command", - }, - { command: 'codex "try using the github caplet"', label: "Codex trial command" }, - ], - help: ["If setup fails, check Node 24+, ", "caplets setup", ", and ", "GH_TOKEN", "."], - }, - { - id: "sourcegraph", - name: "Sourcegraph", - summary: "Hosted code search for finding examples, references, and implementation patterns across repositories.", - why: "Use it when the agent should search code first, then inspect only the matching operations.", - path: ["sourcegraph", "inspect", "search_tools", "get_tool", "call_tool"], - steps: [ - { command: "caplets setup", label: "Caplets setup command" }, - { - command: "caplets install spiritledsoftware/caplets sourcegraph", - label: "Sourcegraph caplet install command", - }, - { command: "caplets auth login sourcegraph", label: "Sourcegraph auth command" }, - { command: 'codex "try using the sourcegraph caplet"', label: "Codex trial command" }, - ], - help: ["If setup fails, check Node 24+, ", "caplets setup", ", and Sourcegraph OAuth login."], - }, -]; +import Activation from "../components/landing/Activation.astro"; +import AgentTrace from "../components/landing/AgentTrace.astro"; +import CapabilityAperture from "../components/landing/CapabilityAperture.astro"; +import Footer from "../components/landing/Footer.astro"; +import Header from "../components/landing/Header.astro"; +import Hero from "../components/landing/Hero.astro"; +import Proof from "../components/landing/Proof.astro"; +import RemoteStory from "../components/landing/RemoteStory.astro"; +import WhyCaplets from "../components/landing/WhyCaplets.astro"; +import LandingLayout from "../layouts/LandingLayout.astro"; --- - - - - - - - - - - - Caplets, capabilities instead of giant tool walls - - - - -
- - -
-
-
-

Navigation

- Caplets -
- -
- - -
-
- -
-
-
-

Give your agent Capabilities, not a tool wall

-

- Turn sprawling MCP servers into focused capability cards. Your agent can start with one typed route, zoom into tools only when needed, and keep huge schemas out of the prompt until they matter. -

-
-
-
Tool wall
-
215 tools
-
-
-
Caplets
-
7 cards
-
-
-
Code Mode
-
72% fewer tokens
-
-
- -
-
- Quick start - - More setup options -
-
    - {heroCommands.map((item, index) => ( -
  1. - {String(index + 1).padStart(2, "0")} -
    - {item.label} - {item.command} -
    - -
  2. - ))} -
-
-
- - -
- -
-
-

Setup

-

Run setup, then add one Caplet.

-

- caplets setup lets you choose which agent integrations to wire up. Start with - the no-auth OSV Caplet, then add larger surfaces like GitHub once the flow is working. -

-
- -
-
-
- {exampleCaplets.map((example) => ( - - ))} -
- - Explore more Caplets - -
- -
- {exampleCaplets.map((example) => ( -
-
-

Add {example.name}

-

{example.summary}

-

{example.why}

-
- {example.path.map((step, index) => index === 0 ? {step} : {step})} -
-

- {example.help.map((part) => part === "GH_TOKEN" || part === "caplets setup" ? {part} : part)} -

-
-
- -
    - {example.steps.map((step, index) => ( -
  1. - {step.command} - -
  2. - ))} -
-
-
- ))} -
-
-
- -
-
- Benchmark proof -

- Real-world large MCP stack: GitHub, Context7, DeepWiki, Git, filesystem, Playwright, ast-grep, language-server, and web-search MCP servers. -

- {benchmarkProvenance} -
-
- {proofStats.map((stat) => ( -
-
{stat.label}
-
{stat.value}
-
- ))} -
-
- - - - - - - - - - - {benchmarkRows.map((row) => ( - - - - - - - ))} - -
ModePassedTotal TokensTool Surface Tokens
{row.mode}{row.passed}{row.tokens}{row.surfaceTokens}
-
-
- {deterministicSurface.map((item) => ( -
- {item.label} - {item.value} -
- ))} -
-

- Caplets Code Mode used 72.0% fewer request + output tokens than Direct vanilla MCP and 65.0% fewer than Executor.sh. Caplets progressive also used 45.5% fewer than Direct vanilla MCP and 31.8% fewer than Executor.sh, while all listed modes passed 10/10 tasks. -

- Read benchmark method -
- -
-
-

Remote Caplets server

-

Auth into tools once. Use them from every agent.

-

- Run Caplets as a small HTTP service. Provider tokens and OAuth state stay with that - server; Codex, OpenCode, Pi, Claude Code, and any MCP client connect to the same - capability surface. -

-
-
- {remoteComparison.map((item) => ( -
-

{item.label}

-

{item.detail}

-
    - {item.points.map((point) =>
  • {point}
  • )} -
-
- ))} -
-
-
-
- Server owns auth - GitHub, Sourcegraph, OSV -
- -
- Caplets exposes - inspect ยท search ยท schema ยท call -
- -
- Agents reuse it - Codex ยท OpenCode ยท Pi ยท Claude -
-
-
-
-
- Serve once - -
-
{remoteCommands.server}
-
-
-
- Use remotely - -
-
{remoteCommands.client}
-
-
-
-
- {remoteEndpoints.map((endpoint) => ( -
-
{endpoint.label}
-
{endpoint.value}
-
- ))} -
-
- -
- - - - - + + +
+ + + + + + +