From efd0385167a77c736ca656a2368e43a03dbedb87 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 12:46:40 -0700 Subject: [PATCH 01/11] Add Vega.js script to resource links in webview content --- packages/vscode/src/web/command-preview.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vscode/src/web/command-preview.ts b/packages/vscode/src/web/command-preview.ts index 9467ba38..d40cf5a9 100644 --- a/packages/vscode/src/web/command-preview.ts +++ b/packages/vscode/src/web/command-preview.ts @@ -216,6 +216,7 @@ function getWebviewContent(webView: vscode.Webview, context: vscode.ExtensionCon // Build the resource links block const resourceLinks = [ + script(resourceUrl('vega.min.js')), script(resourceUrl('chartifact.host.umd.js')), script(resourceUrl('preview.js')), ].join('\n '); From 8124d3e6f5f38d81ee3d73fb0dfa64dc50ecf2b9 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 13:21:32 -0700 Subject: [PATCH 02/11] Update package.json: set version to 1.0.0, add description, categories, and keywords --- packages/vscode/package.json | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 966d4ada..1ae57333 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -1,15 +1,13 @@ { "name": "chartifact", "displayName": "Chartifact", - "private": true, - "description": "", - "version": "0.0.3", + "description": "Declarative, interactive data documents", + "version": "1.0.0", "publisher": "msrvida", "repository": { "type": "git", "url": "git+https://github.com/microsoft/chartifact.git" }, - "author": "Dan Marshall", "license": "MIT", "bugs": { "url": "https://github.com/microsoft/chartifact/issues" @@ -19,7 +17,12 @@ "vscode": "^1.101.0" }, "categories": [ - "Other" + "Other", + "Visualization" + ], + "keywords": [ + "data visualization", + "dataviz" ], "activationEvents": [], "browser": "./dist/web/extension.js", @@ -179,4 +182,4 @@ "devDependencies": { "@vscode/vsce": "^3.6.0" } -} +} \ No newline at end of file From 10a9daab925a7467ccfc77c1fae61d925fa21480 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 13:35:22 -0700 Subject: [PATCH 03/11] remove Edit command for now --- packages/vscode/package.json | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 1ae57333..3ecb9770 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -53,11 +53,6 @@ "title": "Convert to Markdown", "category": "Chartifact Interactive Documents" }, - { - "command": "chartifact.editIdoc", - "title": "Edit Chartifact Interactive Document", - "category": "Chartifact Interactive Documents" - }, { "command": "chartifact.previewIdocSplit", "title": "Preview Chartifact Interactive Document (Split View)", @@ -101,11 +96,6 @@ "command": "chartifact.convertToMarkdown", "when": "resourceExtname == .json && resourceFilename =~ /\\.idoc( copy( \\d+)?)?\\.json$/", "group": "chartifact" - }, - { - "command": "chartifact.editIdoc", - "when": "resourceExtname == .json && resourceFilename =~ /\\.idoc( copy( \\d+)?)?\\.json$/", - "group": "chartifact" } ], "editor/title": [ @@ -145,16 +135,6 @@ "command": "chartifact.convertToMarkdown", "when": "resourceExtname == .json && resourceFilename =~ /\\.idoc( copy( \\d+)?)?\\.json$/", "group": "chartifact" - }, - { - "command": "chartifact.editIdoc", - "when": "resourceExtname == .md && resourceFilename =~ /\\.idoc( copy( \\d+)?)?\\.md$/", - "group": "chartifact" - }, - { - "command": "chartifact.editIdoc", - "when": "resourceExtname == .json && resourceFilename =~ /\\.idoc( copy( \\d+)?)?\\.json$/", - "group": "chartifact" } ] } From c760e6e7b06306520c0f64c8847512f21a7538d1 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 13:55:40 -0700 Subject: [PATCH 04/11] Add adm-zip and @types/adm-zip to dependencies --- package-lock.json | 24 +++++++++++++++++++++++- package.json | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 57ebead4..131fba82 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@rollup/plugin-commonjs": "^28.0.5", "@rollup/plugin-node-resolve": "^16.0.1", + "@types/adm-zip": "^0.5.7", "@types/assert": "^1.5.11", "@types/jsdom": "^21.1.7", "@types/mocha": "^10.0.10", @@ -33,6 +34,7 @@ "@typescript-eslint/parser": "^8.31.1", "@vitejs/plugin-react": "^4.6.0", "@vscode/test-web": "^0.0.69", + "adm-zip": "^0.5.16", "assert": "^2.1.0", "concurrently": "^9.2.0", "css-tree": "^3.1.0", @@ -4182,6 +4184,16 @@ "@textlint/ast-node-types": "15.2.1" } }, + "node_modules/@types/adm-zip": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.7.tgz", + "integrity": "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/assert": { "version": "1.5.11", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.11.tgz", @@ -5296,6 +5308,16 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -15378,7 +15400,7 @@ }, "packages/vscode": { "name": "chartifact", - "version": "0.0.3", + "version": "1.0.0", "license": "MIT", "devDependencies": { "@vscode/vsce": "^3.6.0" diff --git a/package.json b/package.json index a9612743..71deb35f 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@rollup/plugin-commonjs": "^28.0.5", "@rollup/plugin-node-resolve": "^16.0.1", + "@types/adm-zip": "^0.5.7", "@types/assert": "^1.5.11", "@types/jsdom": "^21.1.7", "@types/mocha": "^10.0.10", @@ -38,6 +39,7 @@ "@typescript-eslint/parser": "^8.31.1", "@vitejs/plugin-react": "^4.6.0", "@vscode/test-web": "^0.0.69", + "adm-zip": "^0.5.16", "assert": "^2.1.0", "concurrently": "^9.2.0", "css-tree": "^3.1.0", From ba59387724b5b82fc17eacc3f2771c04ce13a281 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 14:18:53 -0700 Subject: [PATCH 05/11] Add zip-examples.mts to create a zip file of example assets --- packages/web-deploy/package.json | 4 ++-- packages/web-deploy/src/zip-examples.mts | 28 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 packages/web-deploy/src/zip-examples.mts diff --git a/packages/web-deploy/package.json b/packages/web-deploy/package.json index d4921f8c..aad86c17 100644 --- a/packages/web-deploy/package.json +++ b/packages/web-deploy/package.json @@ -9,8 +9,8 @@ "readme": "node ./dist/readme.mjs", "clean": "rimraf dist && rimraf ../../docs/assets/examples/json && rimraf ../../docs/assets/examples/markdown", "build": "tsc -p .", - "deploy": "npm run clean && npm run build && npm run readme && npm run convert && npm run example-folders" - + "deploy": "npm run clean && npm run build && npm run readme && npm run convert && npm run example-folders && npm run zip-examples", + "zip-examples": "node ./dist/zip-examples.mjs" }, "author": "Dan Marshall", "license": "MIT", diff --git a/packages/web-deploy/src/zip-examples.mts b/packages/web-deploy/src/zip-examples.mts new file mode 100644 index 00000000..be42d8f1 --- /dev/null +++ b/packages/web-deploy/src/zip-examples.mts @@ -0,0 +1,28 @@ +import { fileURLToPath } from 'url'; +import { dirname, join, resolve } from 'path'; +import { existsSync, mkdirSync } from 'fs'; +import AdmZip from 'adm-zip'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const outputZip = resolve(__dirname, '../../../docs/assets/chartifact-examples.zip'); +const zip = new AdmZip(); + +// Add folders +zip.addLocalFolder(resolve(__dirname, '../../../docs/assets/examples/json'), 'json'); +zip.addLocalFolder(resolve(__dirname, '../../../docs/assets/examples/markdown'), 'markdown'); + +// Add files to schema folder +zip.addLocalFile(resolve(__dirname, '../../../docs/schema/idoc_v1.d.ts'), 'schema'); +zip.addLocalFile(resolve(__dirname, '../../../docs/schema/idoc_v1.json'), 'schema'); + +// Ensure output directory exists +const outputDir = resolve(__dirname, '../../../docs/assets'); +if (!existsSync(outputDir)) { + mkdirSync(outputDir, { recursive: true }); +} + +// Write zip file +zip.writeZip(outputZip); +console.log(`Zip file created: ${outputZip}`); From 8a9a82d9b53034c007cfd9ccea0a87132bf09d95 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 21:48:26 -0700 Subject: [PATCH 06/11] Add chartifact-examples.zip to sample docs resources --- packages/vscode/scripts/resources.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vscode/scripts/resources.mjs b/packages/vscode/scripts/resources.mjs index c8c1aae8..316fe283 100644 --- a/packages/vscode/scripts/resources.mjs +++ b/packages/vscode/scripts/resources.mjs @@ -32,6 +32,7 @@ const resources = [ //sample docs '../../docs/assets/examples/json/grocery-list.idoc.json', '../../docs/assets/examples/markdown/seattle-weather/1.idoc.md', + '../../docs/assets/chartifact-examples.zip', ]; const errors = []; From 6ec5f42ba6ec8e32a5a7494ef02c0fb72dff0823 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 21:48:42 -0700 Subject: [PATCH 07/11] Remove adm-zip and @types/adm-zip from devDependencies; add fflate to dependencies --- package-lock.json | 29 +++++++---------------------- package.json | 3 +-- 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/package-lock.json b/package-lock.json index 131fba82..6151e571 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "dependencies": { "@mdit/plugin-attrs": "^0.22.0", "@mdit/plugin-container": "^0.22.0", + "fflate": "^0.8.2", "markdown-it": "^14.1.0", "tabulator-tables": "^6.3.1", "vega": "^6.1.2", @@ -23,7 +24,6 @@ "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@rollup/plugin-commonjs": "^28.0.5", "@rollup/plugin-node-resolve": "^16.0.1", - "@types/adm-zip": "^0.5.7", "@types/assert": "^1.5.11", "@types/jsdom": "^21.1.7", "@types/mocha": "^10.0.10", @@ -34,7 +34,6 @@ "@typescript-eslint/parser": "^8.31.1", "@vitejs/plugin-react": "^4.6.0", "@vscode/test-web": "^0.0.69", - "adm-zip": "^0.5.16", "assert": "^2.1.0", "concurrently": "^9.2.0", "css-tree": "^3.1.0", @@ -4184,16 +4183,6 @@ "@textlint/ast-node-types": "15.2.1" } }, - "node_modules/@types/adm-zip": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@types/adm-zip/-/adm-zip-0.5.7.tgz", - "integrity": "sha512-DNEs/QvmyRLurdQPChqq0Md4zGvPwHerAJYWk9l2jCbD1VPpnzRJorOdiq4zsw09NFbYnhfsoEhWtxIzXpn2yw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/assert": { "version": "1.5.11", "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.11.tgz", @@ -5308,16 +5297,6 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/adm-zip": { - "version": "0.5.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", - "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0" - } - }, "node_modules/agent-base": { "version": "7.1.4", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", @@ -8114,6 +8093,12 @@ "node": "^12.20 || >= 14.13" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "license": "MIT" + }, "node_modules/file-entry-cache": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", diff --git a/package.json b/package.json index 71deb35f..d0a34f94 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "@esbuild-plugins/node-globals-polyfill": "^0.2.3", "@rollup/plugin-commonjs": "^28.0.5", "@rollup/plugin-node-resolve": "^16.0.1", - "@types/adm-zip": "^0.5.7", "@types/assert": "^1.5.11", "@types/jsdom": "^21.1.7", "@types/mocha": "^10.0.10", @@ -39,7 +38,6 @@ "@typescript-eslint/parser": "^8.31.1", "@vitejs/plugin-react": "^4.6.0", "@vscode/test-web": "^0.0.69", - "adm-zip": "^0.5.16", "assert": "^2.1.0", "concurrently": "^9.2.0", "css-tree": "^3.1.0", @@ -60,6 +58,7 @@ "dependencies": { "@mdit/plugin-attrs": "^0.22.0", "@mdit/plugin-container": "^0.22.0", + "fflate": "^0.8.2", "markdown-it": "^14.1.0", "tabulator-tables": "^6.3.1", "vega": "^6.1.2", From 9d1cea920c97c5a2d2f288bd7ac82a98a5370721 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 21:50:01 -0700 Subject: [PATCH 08/11] Add command to create Chartifact examples folder --- packages/vscode/package.json | 10 ++ .../vscode/src/web/command-create-examples.ts | 108 ++++++++++++++++++ packages/vscode/src/web/extension.ts | 12 ++ packages/vscode/src/web/resources.ts | 43 ++++++- packages/web-deploy/agent-instructions.md | 33 ++++++ packages/web-deploy/src/zip-examples.mts | 47 ++++++-- 6 files changed, 241 insertions(+), 12 deletions(-) create mode 100644 packages/vscode/src/web/command-create-examples.ts create mode 100644 packages/web-deploy/agent-instructions.md diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 3ecb9770..63a5d8af 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -53,6 +53,11 @@ "title": "Convert to Markdown", "category": "Chartifact Interactive Documents" }, + { + "command": "chartifact.createExamplesFolder", + "title": "Create Chartifact Examples Folder", + "category": "Chartifact Interactive Documents" + }, { "command": "chartifact.previewIdocSplit", "title": "Preview Chartifact Interactive Document (Split View)", @@ -96,6 +101,11 @@ "command": "chartifact.convertToMarkdown", "when": "resourceExtname == .json && resourceFilename =~ /\\.idoc( copy( \\d+)?)?\\.json$/", "group": "chartifact" + }, + { + "command": "chartifact.createExamplesFolder", + "when": "explorerResourceIsFolder", + "group": "chartifact" } ], "editor/title": [ diff --git a/packages/vscode/src/web/command-create-examples.ts b/packages/vscode/src/web/command-create-examples.ts new file mode 100644 index 00000000..bc093ea8 --- /dev/null +++ b/packages/vscode/src/web/command-create-examples.ts @@ -0,0 +1,108 @@ +/** +* Copyright (c) Microsoft Corporation. +* Licensed under the MIT License. +*/ +import * as vscode from 'vscode'; +import { unzipSync } from 'fflate'; +import { getBinaryResourceContent } from './resources'; + +/** + * Creates a chartifact-examples folder and extracts the examples ZIP file into it + * @param uri The URI where to create the folder (usually a workspace folder or selected folder) + */ +export async function createExamplesFolder(uri?: vscode.Uri): Promise { + // Determine the target directory + let targetDir: vscode.Uri; + + if (uri && uri.scheme === 'file') { + // Check if the URI is a directory + try { + const stat = await vscode.workspace.fs.stat(uri); + if (stat.type === vscode.FileType.Directory) { + targetDir = uri; + } else { + // It's a file, use its parent directory + const pathParts = uri.path.split('/'); + pathParts.pop(); // Remove the filename + targetDir = uri.with({ path: pathParts.join('/') }); + } + } catch { + // If stat fails, assume it's a directory + targetDir = uri; + } + } else { + // No URI provided, use the first workspace folder + const workspaceFolders = vscode.workspace.workspaceFolders; + if (!workspaceFolders || workspaceFolders.length === 0) { + throw new Error('No workspace folder available. Please open a folder first.'); + } + targetDir = workspaceFolders[0].uri; + } + + // Find an available folder name + const baseFolderUri = vscode.Uri.joinPath(targetDir, 'chartifact-examples'); + let availableFolderUri = baseFolderUri; + + // Check if folder exists and find an available name + let counter = 1; + while (true) { + try { + await vscode.workspace.fs.stat(availableFolderUri); + // Folder exists, try next number + availableFolderUri = vscode.Uri.joinPath(targetDir, `chartifact-examples-${counter}`); + counter++; + } catch { + // Folder doesn't exist, we can use this name + break; + } + } + + try { + // Get the examples ZIP file from the cached resources + const zipData = getBinaryResourceContent('chartifact-examples.zip'); + + // Create the examples folder + await vscode.workspace.fs.createDirectory(availableFolderUri); + + // Extract the ZIP file + const unzipped = unzipSync(zipData); + + for (const [filePath, fileData] of Object.entries(unzipped)) { + const targetPath = vscode.Uri.joinPath(availableFolderUri, filePath); + + // Create parent directories if they don't exist + const pathParts = filePath.split('/'); + if (pathParts.length > 1) { + const parentParts = pathParts.slice(0, -1); + const parentDir = vscode.Uri.joinPath(availableFolderUri, ...parentParts); + try { + await vscode.workspace.fs.createDirectory(parentDir); + } catch { + // Directory might already exist, ignore error + } + } + + // Write the file + await vscode.workspace.fs.writeFile(targetPath, fileData); + } + + // Show success message and offer to open the folder + const folderName = availableFolderUri.path.split('/').pop(); + const action = await vscode.window.showInformationMessage( + `Successfully created and extracted chartifact-examples to "${folderName}"`, + 'Open Folder', + 'Show in Explorer' + ); + + if (action === 'Open Folder') { + // Open the examples folder in the explorer + vscode.commands.executeCommand('revealInExplorer', availableFolderUri); + } else if (action === 'Show in Explorer') { + // Reveal in VS Code explorer + vscode.commands.executeCommand('revealInExplorer', availableFolderUri); + } + + } catch (error) { + throw new Error(`Failed to create examples folder: ${error instanceof Error ? error.message : error}`); + } +} diff --git a/packages/vscode/src/web/extension.ts b/packages/vscode/src/web/extension.ts index 08023d9d..9b1420e3 100644 --- a/packages/vscode/src/web/extension.ts +++ b/packages/vscode/src/web/extension.ts @@ -85,6 +85,18 @@ export async function activate(context: vscode.ExtensionContext) { context.subscriptions.push(convertToMarkdownDisposable); + // Register the create examples folder command + const createExamplesFolderDisposable = vscode.commands.registerCommand('chartifact.createExamplesFolder', async (uri?: vscode.Uri) => { + try { + const { createExamplesFolder } = await import('./command-create-examples.js'); + await createExamplesFolder(uri); + } catch (error) { + vscode.window.showErrorMessage(`Failed to create examples folder: ${error}`); + } + }); + + context.subscriptions.push(createExamplesFolderDisposable); + // Ensure preview manager is disposed when extension deactivates context.subscriptions.push({ dispose: () => previewManager.dispose() diff --git a/packages/vscode/src/web/resources.ts b/packages/vscode/src/web/resources.ts index 5bd20254..0720ea2e 100644 --- a/packages/vscode/src/web/resources.ts +++ b/packages/vscode/src/web/resources.ts @@ -4,8 +4,8 @@ */ import * as vscode from 'vscode'; -// Cache for resource contents - can be string content or Error object -const cachedResources: Record = {}; +// Cache for resource contents - can be string content, Uint8Array (binary), or Error object +const cachedResources: Record = {}; // Initialize resource contents (call this during extension activation) export const initializeResources = async (context: vscode.ExtensionContext): Promise => { @@ -41,6 +41,10 @@ export const initializeResources = async (context: vscode.ExtensionContext): Pro 'html-json.js', 'html-markdown.js', ]; + + const binaryResourcesToLoad: string[] = [ + 'chartifact-examples.zip', + ]; for (const filename of resourcesToLoad) { try { @@ -54,6 +58,18 @@ export const initializeResources = async (context: vscode.ExtensionContext): Pro cachedResources[filename] = error instanceof Error ? error : new Error(`Failed to load ${filename}`); } } + + for (const filename of binaryResourcesToLoad) { + try { + const resourceUri = vscode.Uri.joinPath(context.extensionUri, 'resources', filename); + const fileData = await vscode.workspace.fs.readFile(resourceUri); + + cachedResources[filename] = fileData; + } catch (error) { + console.error(`Failed to read ${filename}:`, error); + cachedResources[filename] = error instanceof Error ? error : new Error(`Failed to load ${filename}`); + } + } }; // Get a cached resource by name @@ -68,5 +84,28 @@ export const getResourceContent = (resourceName: string): string => { throw resource; } + if (typeof resource !== 'string') { + throw new Error(`Resource ${resourceName} is not a text resource`); + } + + return resource; +}; + +// Get a cached binary resource by name +export const getBinaryResourceContent = (resourceName: string): Uint8Array => { + const resource = cachedResources[resourceName]; + + if (!resource) { + throw new Error(`Resource not found: ${resourceName}`); + } + + if (resource instanceof Error) { + throw resource; + } + + if (typeof resource === 'string') { + throw new Error(`Resource ${resourceName} is not a binary resource`); + } + return resource; }; diff --git a/packages/web-deploy/agent-instructions.md b/packages/web-deploy/agent-instructions.md new file mode 100644 index 00000000..19d9c11b --- /dev/null +++ b/packages/web-deploy/agent-instructions.md @@ -0,0 +1,33 @@ +# Agent Instructions for Chartifact Examples + +## Overview + +This folder is a collection of data-driven documentation and visualization examples, organized for use with the Chartifact system. The files are structured to demonstrate features, data sources, and visualization patterns using both JSON and Markdown formats. + +## Key Directories + +- `chartifact-examples/json/`: Source data and configuration files for Chartifact, using `.idoc.json` format. +- `chartifact-examples/markdown/`: Human-readable documentation and examples, mirroring the JSON files, using `.idoc.md` format. +- `chartifact-examples/schema/`: Contains the JSON schema (`idoc_v1.json`) and TypeScript definitions (`idoc_v1.d.ts`) for the `.idoc` document format. + +## Patterns and Conventions + +- Each example or feature is represented in both JSON and Markdown, with matching filenames and directory structure. +- Features are grouped under `features/`, and scenario-based examples (e.g., `seattle-weather/`) are grouped by topic. +- The `.idoc.json` files conform to the schema in `schema/idoc_v1.json`. Validate new or edited JSON files against this schema. +- Markdown files (`.idoc.md`) are intended for human consumption and may include narrative, code snippets, and visualization descriptions. + +## Developer Workflows + +- The `chartifact-examples` directory is intended to be a read-only reference for developers working with the Chartifact system. +- Developers should not modify files directly in this directory; instead, they should use these as examples to give to the agent. + +## Key tips + +Plugins: these are markdown blocks denoted by triple backticks. In Chartifact, some of these these have both a serialization format (like json or yaml) followed by a plugin name. For example: + +```json vega +{ + "description": "Having 'vega' in the plugin block is critical, otherwise it is simply json which will not be interactive." +} +``` diff --git a/packages/web-deploy/src/zip-examples.mts b/packages/web-deploy/src/zip-examples.mts index be42d8f1..50e4d457 100644 --- a/packages/web-deploy/src/zip-examples.mts +++ b/packages/web-deploy/src/zip-examples.mts @@ -1,21 +1,47 @@ import { fileURLToPath } from 'url'; import { dirname, join, resolve } from 'path'; -import { existsSync, mkdirSync } from 'fs'; -import AdmZip from 'adm-zip'; +import { existsSync, mkdirSync, readFileSync, writeFileSync, readdirSync, statSync } from 'fs'; +import { zipSync } from 'fflate'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); const outputZip = resolve(__dirname, '../../../docs/assets/chartifact-examples.zip'); -const zip = new AdmZip(); + +// Helper function to recursively read directory and create file entries +function addDirectoryToZip(dirPath: string, zipPath: string = ''): Record { + const files: Record = {}; + const items = readdirSync(dirPath); + + for (const item of items) { + const fullPath = join(dirPath, item); + const zipFilePath = zipPath ? `${zipPath}/${item}` : item; + + if (statSync(fullPath).isDirectory()) { + // Recursively add directory contents + Object.assign(files, addDirectoryToZip(fullPath, zipFilePath)); + } else { + // Add file + files[zipFilePath] = readFileSync(fullPath); + } + } + + return files; +} + +// Collect all files for the ZIP +const zipFiles: Record = {}; // Add folders -zip.addLocalFolder(resolve(__dirname, '../../../docs/assets/examples/json'), 'json'); -zip.addLocalFolder(resolve(__dirname, '../../../docs/assets/examples/markdown'), 'markdown'); +Object.assign(zipFiles, addDirectoryToZip(resolve(__dirname, '../../../docs/assets/examples/json'), 'json')); +Object.assign(zipFiles, addDirectoryToZip(resolve(__dirname, '../../../docs/assets/examples/markdown'), 'markdown')); + +// Add schema files +zipFiles['schema/idoc_v1.d.ts'] = readFileSync(resolve(__dirname, '../../../docs/schema/idoc_v1.d.ts')); +zipFiles['schema/idoc_v1.json'] = readFileSync(resolve(__dirname, '../../../docs/schema/idoc_v1.json')); -// Add files to schema folder -zip.addLocalFile(resolve(__dirname, '../../../docs/schema/idoc_v1.d.ts'), 'schema'); -zip.addLocalFile(resolve(__dirname, '../../../docs/schema/idoc_v1.json'), 'schema'); +// Add agent instructions file +zipFiles['agent-instructions.md'] = readFileSync(resolve(__dirname, '../agent-instructions.md')); // Ensure output directory exists const outputDir = resolve(__dirname, '../../../docs/assets'); @@ -23,6 +49,7 @@ if (!existsSync(outputDir)) { mkdirSync(outputDir, { recursive: true }); } -// Write zip file -zip.writeZip(outputZip); +// Create and write ZIP file +const zipped = zipSync(zipFiles); +writeFileSync(outputZip, zipped); console.log(`Zip file created: ${outputZip}`); From 02e342b4178b3f5a76846e36c95aed8b743d61ff Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Thu, 28 Aug 2025 21:50:50 -0700 Subject: [PATCH 09/11] Add chartifact-examples.zip to assets --- docs/assets/chartifact-examples.zip | Bin 0 -> 75581 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/assets/chartifact-examples.zip diff --git a/docs/assets/chartifact-examples.zip b/docs/assets/chartifact-examples.zip new file mode 100644 index 0000000000000000000000000000000000000000..a5b5bb910760b26e1b2e1183c15d0a3cf983465a GIT binary patch literal 75581 zcmZsiW0r1q3IK412mnCv_g70NJ6n2F69Z=#M-wM{Mml>(3mX$hItybv zBf9_kR;{LEyUBszdrMg|1C$97v1R<3+{(6D0QwPTgQcGU#z;Glh8>9_J`urwm;D0c z)sRhS648J3>BvaD%eu@+cU<~+U zv0>+wL{H0>uRhU>an@~e!m4Ekg7x-H2$DR#OTXdeOHI+(`>4Ir{tOT~HVu`1YT2|e zvSQNW@F_ke37s1Q;U%U(@4e-td?m3lzKQV9%#t@abgEPiXHKp~IkB0W%yKecuKo#c z$<&ShNDoseZ6*U=176Lple&t*auqz0!34@TYz?6H^Jol;wC<-^_(a$DY&6Ne$E1MjvqyC8l>l9AR52 z+V^DAsLqtfu!=1|a(kzV@f>M$Z|#8yJQymEw~%^!P5E|>UrD20&szk5(I7V%R)hc$ zIrjd+kFGZhdq)kJ{NkeUlS)`)PKb<_<1rVZ+;)(Gx$W8+ju0fcnti&%ZE6T*+6P+t z1fc|4;BMe@^SFDW|Drx;7|=Q?GkbfFN?i*y%rimkX&Fp+7J7&4n~HkbT2^WOa$#ZN z+v&~@p11YV@Y9%+mRbs%c@Zo3V(53u6sI+_{nrexP`^fO?-ilA0j{q+0x4MfK<8r| zeqX)EostE(v|&2Wtw${@cbF%VCTBetHSI0Vok=qIWRzLx-shleP*YrnTS?lz6dX?(&IPC)mI~3p&X4aqP0G zUX^7pi~)fY&M}N7hoQQ3d`+co5)>mSj48g2)-!B5ZjCyx>a6PThA~Ck-ySmfVHiP$BcI<9v00 z8qQCQDJyFD6Z1G{)}Hw>UGk8pK#iDwIN!PWS!BmHlHvoB(1viQO=&*J!DY+-TfoGv zn{^bq`Vdty&dn7c-+z6YSYp%n=V=>$>-l%R*M(zYWz4evXqv*VFMjk#nDa5Uxlz9` znC$J2L~oG8j$3FB!@cYFTq+BvZKuGhT&5nb^H25){72N7ErPIRK-9i1qFv9-0s01* z3by6S^%p}lVQhz9e6w?)^wVxsKHV_C$d3_)j4*>UoxQ}({x$oiAWQ&s;824wOdx45 z1ysuTZ`EN}lPB|o))80`d>ne0khbxFW!Xb8DufV(Vq55%-x0_;Fm2Ninu|OoHf4XR z=nCA@)JApv~tXp>As#;eFKrX&3GjtJVReylx|AF-K!t{9EzeqPi1ppxYPoy)@ zS=bnunK=E6>C@^ucAIP{KDV`PE@9J*NZjKKX#j(G9k!EoCc;^07z=&*q@o9830NM- zYtT=-ZW59WM`ICLChE`}&1Ij0x;akp=bvf-LG;oHkIAsI1_;EaC(cX~zw%NPS~+4t zM&7+?mPo=gL>(r9vfRTWAXFH%aAJNKB;j6cC{WVvvCq6_7*@YfW)#sJejNLo^dEz< znc4~f0Wx>KEA_HNRy2y{X-irWQF@FC7R$p;En#C2n^7eB3$gZ=viS z#3Q*84ZFNTlfE$>vw5QJ%gCy_+V6#_cHPtJKpP=5$Kv1ETxVOmL23lK!A_gEq&3YO zv5D7mapd5qXDg^sMQ+6HO^=hbJ9Rf!_+o*xsUaivxN`>!0af-0u!_NIUs*m_>=8KN zTKW;q68cILUar-SgVqi=9ITytHNx-P#?hFfm>6xV3p0v6@WGMH4X_C~3CF{W&FYgj z&ll`%Te%kN16>0Z6(`h_nUDivd;d#;?;Y0%jajker)fC{lOzDvGyX7bp^)b$-dt|8 z#+VINHl}iqlz2*#Nb7?+&guTJgw(FK)|=yQ@`Y@(Xo`(*L;Q_}BHLWw0z7NAR4}S6 zjqyHOBy2cAZ(}ayI$CHU;c1u9RV>6ie67Tk4^r7m z`;xTZAxe56UMr(2LDI}+u{;K~Mh|6}8*)lm+66)yT$-C@^x%ubX#l zQF+KFyT^1v^IcQQqTXuJ{eA9DAwa#c>bG?Hq7f0bNl7AJJLO#3A?yk3K{j>K?id>+ z0@XX}3c3jUU_>q&LlM6H2`87(`el6g&=<>}=dLUC78Q=Zv{s_f!|e<@W1=HXsSo=t z4;J66%eJ=a;vH=EHCc8I>dNX|2H&F>Iy3rST5xxtWBk_sy&+w(vYq2(S-3RvFlARS zt&&P&+MwUUpB+3dVQ?GsrAjR(e#9rHa>c!?wUK@R|AccqW{r&=2mpXC5&!_%f54fE z&e*`&fY!;*#nI>=gjU;C`oFGQFJIy|KYN^$gcSVfe!*x07F=3sqn(qht{zn@?AnEt zlQe1kXD0>6h82k`Y+#wE>oQKi`Y{mivb~np?*y8I9}cBu@#BE5&ftLc6@!^$Dvs532OVKOX=?ujp>zG??3W=e5!|n-sAtRx27?#^@`wCpbs-%+`SQ{5X7b<;VEGlpYdHI$mVCdub_49iK*DAeG7<3DMqg7ay*+_1BJn<~yyGu*Lmmp3_?x#jp^qa{w>|2fr?#`*xT_@>%Q> zQ8?cXF)i8NZ2rK1R&Gk71)om(hNC=Jv$z7|XYmYeZu*uU=5z>AY^!8=E#$En&H95x zUCr;);z}V zJ|xg8SM7|PnZMFJXc3d->(?@2-xE88rjwpI)5QaHQZC0xEpt&uVCM;3&nX`*5ziuh zgkn5~o>8_9a3&>fvBE28wkkC@#R&?A_Ye-GeAQSviicVs9T8-B*A60~~x@I5p{tyfo0KNPYr7#kSeevXME* zdrHy%&-a%^V03*}QHJ|o&b@cf(NWj(M@*{+Q6>)>@rCO2G_v}P_*DvJ$LjIuPZXsS zp=tR+2}}9v7;SGDqA&xly{H<*cw-_fWB$Dr{7HQj-nD@cqj;jc{1nRutNnHPp-M=^_HUvo;UDWShDYPWrxqq|tIzu>F0J3| zI0znMBuJ+NlioC_9!pL&aOf~)oew)xUv;HGf#%U6H7cr5y=FvXChqcVnq%^KGT?ZBwVLPs zS`|!}d$U^9l=iJNa$GCVT6aw!`;;{q!qfA&_S3NUL)j3T?r;M2OZ3IK+uWQTgmH`- zf1%zo?25gs3}A|0ehKKXF9+AS=K8st5e?z)wOZaQg&HI6_j;o+J>3ajqKF~J4l&cT z?g)Ba9IkQaYn^>`4r_gFLoZGX-DV!{PIyMQ4i>ggR^aE1h1;H^D9eVb@x^FWFCJi5 zKyVC<^JUf-QX@873n}oluKVLC}O^zv#7H?YAk@a`cKa8V|4DH z&nJ=ce&||grGEViFi@xK(nE)kjf7IvILD&`joA2+4uH`%py@-`ehlV?-CNxlU-yQf zG=-=HDdglD82iI1WuL&}sU~wUm{pJr2VD-m!7N1wEo3azRMI2F)$Wt|#w%~t4Js*&TkO;@$= za=BtGdg9ewsSkQ?bEP+=d`r>B!nt0$gg~&1(Gw++6rCeaB*BERrDQv6s1LE8;uU+o zwhZ({x7JMMx4H6PJ;3-Df3h+PpSOZXPtR3foy|mnza3^qc(5xz#T8{^cmC72Y}&iy#$ngT^}-NpnZaF^iZ)# zR4cpFoK{<*mMDMJqCXm$Q)-(72O~U1U%c6dpV+GpKs6D?3A z;I`gB<72joP8(5ySt@2OFB#pY%WOoX zl~fgF)p2d@3+uG+Cw3e93i9@a5_2CwG4wt#Xc3x9Yhe8t1V$b4DBHvicW7f;0(PAU zqpJBYZj7);wub?zKR&Yo=RN0*XIFLAi#d7q_DHmFYb+5nTGU@ZPnXx2Z;CrD`z_Yy zKQf}<$#e-k_R2hXG?{}=~ip2QvHfT(01Q^&!`^_GOf zfk4L5NRIPc03Q$WUZ9X6b!y8|JEx4BK~>RS>Od47=%cljAofMe9bZ^7IB6J?G>TIk zNG}Ol$5A;l>^6HrTu7b%ARo$<(88H7n%D9@fuJMUzECjoJZgL$87SBWI~l(0IFM$fFO0QWQD;q%{bqc}+SdnE2l!T#F!d<%Gt)_2ppOZpN* zBG@FIN(JChL)iY=i~$(tf+7Qeb<7}Kkv!yn;3DarBVi1ra2*WW%-Nwsgi;owR~ll> zhO<~Wh~F>j`}nC+aY6g6J3;(3!k(vhsd^5Oi+nQpLsKthUjXJkz*qy|JvF4vc;d@= z_N87`L4G9xsvO)ap(>ypzK3-&>6>;mP#IjrRB4IMev8F4?D(o(&d)>BGUG=S63@bk4KPL=?X}vQBM?$IA^O~a zmsEl!4g3AdSs1H~kmoZ|771v{&?BC_c$#!fvtC10OhHVET6V{w+5)CsdSl6>{$n6# zWYb#Fr5b?v4ogivj?ZUlmCIB>8ds#tA3aY;`3%VmZv3LeR%ur_-Fr)e2#jtHY6-|CJ-P16SxRc4%QU*zj{bHWb^TB<9Q>t) zByIM1_B3UL$FCuBimZ8~!V5OIp9fgQ1O2upa4~uc(v!fHaGK79;<52kc$WFEPj*#B`EWT=(nhrfX<-7XIcN{GUAkle@7s{MQsL zLIMEL{fAFv`|l|0>}X)?WNPPVW8iFIXZvrDj@7E0|K$;UZq?K+R05PqDGP*R_VU#r zA?1sK=t1)%R@d8}H>kZ@iYguezrgiI()K2IvTjONyI8U@b2)P|m}joR2!m*aPicbs zgJDj>+cTm?F-tWuSqBX!9CW3_v}4Y2SROFtaYBHJb0|J8J>A?bl5ws$D2^!7fw@fl zLrjq!VIYnw!7NNA&HS|`kPVS9--`$gHr9~QS46@O5BYXHYM^A+(Z_fSLU-XNbDs&_ zlf1yw0;N{ggz-+xJv_KokTRTO<14dg!N-^uGgKu66L6Ny20a8)seBHFWI+ncQjS=( zOW-D0OW}^DzkQ8QA8=5+8}ODuD|si$%xO~w&E(gwi#`>y#UhfHL7W8boPx=l-H? zFpvnewoB5#GamnhCkYzPAooqn___Rk!~tK;Ql4f5bG-eb%A5;ZYr=iW&qa=vie==r*{!m0*?Yh8(iD%!UC$d zuH~Rt)v0ONTpj9d?sWLlasy&fp<#K8`@9BLq>1{zq*D`vBxiMG?(m>MrB^I}vp8V8 z$g%R98O)J)Cz?6IS;*62TM(u|0~#{U0Alrgf`h#fhi}=PeMR2_Y#Y7VXrj9t%VEdU zCtW|o$Hy=yXnJ}E{2}biG+l{sEg+f)1Qk+ohtOs8S}j98MKY%|ABH@vI?Bx!gt*Pe z>oCSXPTVKjpAvcI4<;H9H51Z{h(2qC5wlhxB<3iay87l0M+=s5dz#xSSc}UBNhu$o zlz6)*tj91ZqpjI>GS2s(cc~UzJL;Xu^2!-x?j~G z&Sm>k^M*amW35#6)jQ!JT5wwoRY*8bOrrutiXj5OUL_iEH!U_upNHA_cM6BZYUD7m zyBvtrNb#lD2*{ainefsGXt<`#n*b*Mc!O}DakheBqO;T>jSwh&>E^_Ib1Vh5B1ZZ{ zp$62TlG`l@%g|y)#5Lf<@u`^myCWg9RXq?{uwbNE3*oB-{KRAh|ckd;-cbT}5O+vEz72G{jA1KrCF!p%xU zL;yCH&RX4YQ&D9rKG^n)#oQYai-db^=T{2fn93P#IM%VjLjO5sUi*B> zx33etl@t{1n>MOME2m*wyyvA$#G&g|3hF@TFisb5rVeC9yo`3DGdMU-JF^xMl_Un?`ug{7b4H`~i zj>FhAN}gXZ`clE26Y4|H9dhsF>fPFq5n-itlKb4z(fi~q(^9(gIn&N zit5EX3#rT%lZVTeKEcgbKbNGEH9Z7va-PLxIt>(`-6hthTBS5swK-l_}<=A@HOt5Q;l|JIeS>oNAQR6OE%MjxhEYu?wBBaCpw;bY6-coW! zragiZB1eh$em#nyU$|DM-Zb~LgM9mNuS-Yqq+7(V97~fbS6~d9YSM-NqD2_FOyNaS zt0;$fQ6v#d!3w6-OF)*Hh>(W>Qr!+iUxr$TNpM4>5BmP(B=U#CkeCd%n)5uG(<(u~ zxi3EDdB_(R?dF_t-@~ZqDmqu{Z39Gj4GLnAGWgS;GmKj z1r2le_w+&gHI!WO*tQZilck>W6QnZ0xLIC>$5kkeJ-1TO#xwWwLhiApiT9O#YI01=PwjUqk+3Dvkp~dA0 zrq@ky4_JaYDn*jtnM1g|yunurjg(D@^FF30JS`6&;*VaC)OlkYk?K`vq;>sP5q3Lo zCeH_?;H(x}v=UFHH=jC_Cvr4$5*y({a(}U)sWRcYg_HgYu<74Fpre(B)NCDY2U5s{spgbb% z+*CvX)k}6CPWa&R*y;cjdi6kfyQi|Fy3s4-Qb9viXb1 z!40;%I8u*Uy)aPPg#Qv2H3Om6m(-bU)vz0X_AsToaIH5&^$G+-<1R+B)RBGKQy65P zQz7kuN%h2qpW-`C0XOdd8W;5_qs*Yn3OxGQ0M}*OdnJUm2B92O{L`{@vK`BA6Pl=Yl9+0 z7JB@`2W~5o){IMYlTUrE@$jjZu(!@er}UiLE<4-7iGv%;!ENxN`hbIGRWHZSPhC%a zW$K=8u7&gGyMEd1M=b11#na+bDderMfBhQdr>Za&utz82mlbYBQynmhK1bJfpr4P& zPFvM0BLdq9mpkNB{RQ+QAy2_q)G!_mQP_zf*t84VK9~VPBXY|Iuo^XgPCAtgki@f6 zz2FKM_q_a1U!d)hM)~f`auNcgF>nN@78HnIym6#VI0?yz3q|LbmbXMktnxQPP95m{ zSCDWYWLPPD9tF+=PF0+jEhh)&M#M(a3W_^Qh|S)!q{q!Zh8%&eW6Xx9uE2BN=|jGk zD5DwUKEcsG#B@I`Dmt>@2;vD&?R4leI^7$$Z`wEXKcSu$Fa;U>w@jq{d(Zcm>;HYc zXXa>UWa8*SYi;55@2~XgT6RkuD88p^>Pkg{L#A|-J0A^}(Ax!|nvAGOmX#Ap?np}H zaIwsb`M-Z=>a(MgGKwSs@VM&ZX5DU1*WzXouz2OR{Da+{gGB?99UNKk!j@2Z_NC6> zl)=si^1ZLX)Wti7YH%`vjV>HsZCPD<$at{26{|>6qA5h32EwW5xg`cbBw}S3V)F0m zhHg1u!o~e>uu>5e70diQoo1Bw6XQ6Ryvq#lz*3(rWJuWS*CR1v#M^t0h=vreQ6A1* z(!>%)EC=(}!+#4Hlo^dWOo=Pvu!Pl<@S$Tj`;jS9S$)>$)g+o;Ohq2sNYtaBf{5Mu z5zGy}7c$R<^d;~s7e+j~ndP;kxOWo>&E=an;#vM7x97nr4a)`T*JYl9>>U1^orTEoXfS^WP-)mcA~CGz9p7sbE#xk(R$Keg;8wSwV&6>iOhcx zHQFyCBNDK3X4W;b81KbL(A!>U_)4JfkPEyUCY5TqEW&WaQ8K;twT#jJ(jYzY)yQ@6m5z|zBm#-SM%}O0G;PH2I zoTlWS@`KXMg1p_vdNv{h4A%wrY2rjygDCRCS(ZHioN?ngiSJr|AH1AAhD-`9-@Qu^ zOig!aw+SZ$-@svh)t!Iz_W z!G^eDFRO{{=Gt~25~_HL)Wx{Y6DKL4wpztZ(_U|}{1An75<@M^#GOJb#8BGFc%=pk z#&v$*A4ekw3{&D^eezeW>7{gb?rXzO>(Br1ObzNIp1u(n06^mJB?Q6$!0Z3nP+B`j zGur>JXY5v!`me0q^Qwk$4u@Sw=Cc)02OVhyFl4q>IXKuuFS?A zAtCPzm=2JF?V^xfj0csjn>fE^G^BR=*p}HDV8N>n@xu28g@4FBb470rPQ>8#*)idRGT;c@K{A zJ`exhJPK+$kH3%sjl?p&&jA(?+RMLf_Kw;H%r0>}}mNk~`qQ{B9!f98KmIyNrsqJ|hatq-VlMdu(lO?PJ zg2Mr*FufxhgoaU}FY~p>GKjSM_Wjo~TZ-15y^Ti-54~?E;6Pw2HUW)2EU*f8FyI2I zjhgr&>TlkQ1ba~s;v@j@a5Z3q z9+zt9cw_(@Exn;;bId&?F+|K%@QC5r8P_yYQ6 zVq-D;Wl83VBLb`yGBnQQpZZ8fJqbWBQ*H=#-v|*Zh((UR$QFxMR~>E^jn8}vAk6|&w!|`pcq6hWLzalG3cujS(#NTKZODQJmkZsaA%5b?(GZ(nKN874O5KmL&nxi6HPuR>Fx z*#>e~m%yJ(W;@5;Yd@*=MUCVdkW@rOnAwNn#%FQ^X3?V@_Yhoz8XP9+pPpu9w#%}V zfIOZWVDNfNz&x@Ueo;4b(WC|JgN!k@5qT8abZCP}a z*e3x|jG`RgGZN}U&86QBc}`0yk`cuX1V3EAA!hgZs>gEhceZCo_!t9%k5 zsODC5^>Jw`UUzRORK-LZ-zxSP*(9P^$#De3${;d=NJ#}oHb;L8`!DemIS96su|N!i z1n8}QiGuZl;SrDL*B!3(_XqgA^`U_I{tjlqj2=A%QtKxiFj36NEWubvGX)$f=itJMigoud?&zyK$Y&;>>L}{nyx-kdvE#IHE6#jvDFJzx zWchDlegqwB&=#PT+LO26s)+FPYY25u?F>l>2!fA8i8QXFkO0&vBe8W2LkgZUDg%3I z<;W8f@~P+PmSlM%4a_Sv7ezO+u@$DQad5*}^G%uBb9-VMPHZN4WIM&PoWi-Y($(HU zY3tTedQJ`uJ%K`}8*noWCMA83kB9EzRDq1H8~8uMl?E1{Y43@o9m;H<@E+C(bG-4y zHDQWF^Ax(e!^M4Mdd|#C+QVt}a}uwkdXjV6-mt~%sO|y9juT7HLC@6S-*C#YKmWd$ z)WM2wC=_yab~4XYu9Gx}DWG-JRmH0o-Ox@#OTC#R>9k!~b=k8-0;gLJ%r z4Jtb?+clJsCagq;s$Pa-{Q;|7bI#&5!gEcG&-Q-$Xt<75cma!@EQ;=d3pibIWkuEL31Mf9Oa89n_nj!~E zn4`3=s|lnrb>-neRl**@|JFaMU0dVgqQGF>=n)DUMQ4IC;%lT37Ksi|ZGr{|ReEoX z)0|2(v+S*e5)^>;rZnAmNvK;D45esh3sop%Z*CD2&%9I9%uD}?+Gd6gJX$ZnCBL5H zps92F7r(F_+3j}1PLop44#xf5_8+FV$ei+-Mwjkd6v4Tt>--yCKbFgzRQYPyLGa}) zdaB%``{bqO9TnfYh!aE!AVf4SHG`FHpZFzrSq`}HL@lYtfc=jkvAS&|Ogr@JLfk=& zGxW3lT*4%vV=Fge>@?P*yBB|pBv7wojwdX=*znyz{)-!9eDHU z+sZ8JnINRA8KzpLQCSmDss*H=RJI?sp71sT=66!Ic!tsR65XZYaCLUr;qs;5V-SyA zeP~J`S+;H*-{Zom(l;vf#XNO4uU!+&5%+I#$nEi!Ki>~>6k~ztn;Laogrf?|98M2| z5(Gz;erktlaycNCosMY6#OE8`!%}p)@bG2t$7(WMmsu`L-n+k4%WXox+>TFW2yJkx zN9HCwI~$gjY49tpdXxtN6g!BMneRNX zC{U+Vuei}>nxV02%EC(*L^C*C`vR2agj%z1)*@eyN#jm*_#AzmH4XyYgO+xsY|xj@ zn+i#bK1#FiNx6uLjoXL{FPuSVcBS9c!DZ@%mqp(^v1mU+M{F^~7-d2QmJmNVHnryd z_LdGxrRq6?CtbQ|op5&M!sGUia6k}?eb~*z@$swF{It4DIMpH&jjYg>+#^A1h zKFMB}w!@OCp6!E8Mv`Is>u^8G(>Dw?RcISxPzwfQ6>MryAIrPfqR)NM-(u6h+^%m4 zlY!3~i-DJegDZHlE8wIaYQ}Fe1rcNJ^#&M`Ml`B^6d+8#hZjj?zCF};NDi~%p^TVWco(Wqx)uKr5}UeE9n9@Q{wLNl<+!V!Gu7z?{_3Qf_> z6hVZk1o0Y(4%&BC1;>_a>9h^jB0UEywr?)=T1I5U|09o{;}5OOO;fXa%t`(f^JQQt zAYIQ^bn(xhv-e~(`7GAwdL6#KU8_n0LiVqe1B|XzxKgs=K{u+^0QYHRYB9|5c}QEY zwQ9AO1ZfGBi%-=$7~XQ@=?D~gAqFoYmDw{ek`N{y4Tartb4LygUd-r`Wr&u9;lo0h z^6AXQBtVWO%lZYXDPXHUuX50&aLp`1uM%}BD8>csuaN$>!M*rLs%9R zX)C_Q_$vQgt2<^nP_HzB>&)o~WvoE=4u{u6$w_~LEF9IiDyJT-%<<~ACQbLXE)5z6 zZZABC^3Md13@i2DmuP?YBK;d}8;_FHOJk&BE;OwE$e+IGxY$rJF*gu1Pil^8G(3*l zw}~=TFEe+nZ^Df((Ft3`f{@w8wRXX$KIZeV(>;54wG*5js2M?e4ss%Hvs&|^&PA{b zM`${NlGtMX*`|&!*At$0YAd{5C~0Ue_;fP|x@bi*!yhyr?O#-=w1!{n1x|BubFb5L zRK5y<_GyAEprgAK&Az=!g z6m~;15=VcI{gX_r>gt@W39fub&p}2{f7fv|l5$Y8Rd0Cq*;YlM zR=c`w^Ok`&CsSoz-!zoIBas`h;qmMY3VJ(+hsN;PHLE+&3bE-aIkC?#CXZSLU1M@1 z^H{h6&W5l*9reXru|N3nyZ7m8M-Z?-0CBhQ^q2c=ufBl0qK!xQlhFh_Fde$B84X4m zJgU*+^QTAL@h>y16(gKV(^5t0PsewUH)9hv66-?XnaPG-p=wL%xVrKC-AL!JuBsE2 zYLX39SRbKWePDS83W)M16}Y>(!MosI`FKn~37WaSPSJ@QOlYt*<(Og^_77N6PZGIA z6fcapud7!|Un_R&FjEIXA&W7ELoh&aGmf&!ypb0dYb-7yR9ki%$hL#X_(PZi{0e1v zzvegG&fB5~Dle-yv3tr3p^@)XOml_Px)b^u*rwPvS&0>}nAg;#s7DK_lJ{JC&k40h zoB25TRKytSVSpz8TyW>2_)g~kEw`RQDzxtmGd~%)Qg_w7ErrnVi>vZO^~n6$UDJMm zkKX22DV&hCGw2|NCC!iA^?5iM4}j$Gt?6g$jrd3ox3Boq#{e0r&ebt29Q}OVzMKLx zIN)#M7g4%jS`GxpM*<9j6$`8JY4UVvLP7cW9nn;?6>x?deRV3LZ0H22NeWdm}H%mIY}dJurfeayF9hC&a5t28dCv*S4dDjh|Xm?&5j3S#@k$|gf1A3;pz zvloaUwV0I^NH2_eSVN*SAT+En>mf)F022q>8DQ*0k<3-$AP;7!eI2gJ92}DQfQbhp z?R=)?I1CyxK(Y)wcnhK-mj*wwLQ`L0x9YFC zkyM9dGFI^hU1L7_rSG%Cb<0f86Im(v-owP>r zB4I0wBv*zr8p@Cb*^pB}-8NI`BGig$p{o;N9o2zt4aXw-Dnl@s*JTYcFa{4``5l{br^*1+Z~JW~rySSgZ{$*=XFfW|R3CRSy^Obzq} zB18g7gVyDVEL#aOJuz7c8}$Mb*wD2QojSmJ(U2_aTU&Ztku>-t@@(}%rye|1E=(~a zbvpSKM~@Q&m8-*DP^_&+MY_6yl!Oa(i5`n2bLqxu6VScTnTvqyGvBqqYV(o5kiAF!XqSw{i~qG`Xt%Q9H0gErV0FV#Sqf{J8*+9-QZ3S=wbM@>3p zC7*xTTjiK1sVw+)C? zvDWLZ?N_jGp=zYPH3+36Ypr6=#TreNiZ$C_8>;oP%%O54ros#7wvCSdqLS~2T~Q^D zvk|J@Y@199wAQmAu^DU9XAQD#MUz4vz$b`0q~?TPeb>V{-71>lg1){A2rQZ z%=>@%dZ+M8A0}Trb~?6g+qP}nwz^~6wr$&3>9Awlb~-!nyT5N{_Wzohb+V4u*>l~i z>i1OLb?E-N>#ioY&N|XN)EA)0eADq4Zj7Pp#?>myx&|`2ZlevQrr`UPdW2BZ@_cpc z%Om=i$7_{#Yv27_(rJLqU2B58w!6z_-F)nO_0>{K<&5OTMguFqUA=-j49H4l2{*H# z*6heTu|GwQ4MWlU%@^9{qs$CG`F=TwSszhvMXg&~dT*Sidswyr@`8JxkVwiecb9I} ziNm+9^RIv8O;JHkQ8M4-Sd`zH(|-iaF5hYkS6eeWkMD0wGv{x^#eb+R{8VRRzb9jQ zuT`S8V>iXcrXai}K#1gja{fkh&XF=^Z-}~Vc2(NW!J@FsW+h8G^Yrh1eJ2mN1~RY9 zrfooPVw;w}_OQ<(ZAo0_OnNsf@Ljb{ndJ}hefNX}E z`~`Fz;yVi0Iw(AjCF_67*^GZ4X58;6^aE2NK0~&q5 zGAKHsD};R3(A|7guU-LUHtI7CDkfF}bvXZS!cx_$n9JE#?%+gQ86#@tCaXFzM+f{I z@qS4N$&+SyI4z!trndoA+{E98GO4gc=vl;|PHde|NVJMyqvRLq?e2xodOm6M zmqo@!j4k!E(NayZMMbIPMHMkDFD%Gl>VID3Xb7Mt_X$|D;haO%@)^uRO%Alhe{4_gdyue#qv>DXx`zv1o-?LN zceQTA6w2|bRVNXn@`#$zr`NyU=03~I$!77RsmMlj$z>|v+RIINE$qqPpro1{)W8D# zh=;gJb#9LyQJ-{6KeAMzlc{=hRBP^7H~D2NxA=HV*Dt8I2mBbP(oHupSbP^DhWg&* zn<>8XuH?V|vGbV^xLaQOe$&AN_rE-d%>VfyE~(GNen+3Z$5aqo=$62BdSzA{S9F#z ztd!1Y=sx8^hO{xJ=2Xf=RF~dCe$Ug2jdD}Y@p&p2K{Z%_Z4MTK$6e_D1IRqP^1%r- zS$3kuzt;S9sz=prV(BT=wwaHzt6r@_7^=Ut(mfztQr0i*y3%{@mt{-$sLS)Ea6e@* zUl=xSu0wUp=yL3=XV1P~p#=k{%98pfM{0$aIwE1_RTH2glPG(B{(4T)%IKRwqC|k= zH*}Zbs-6>?#IjINKFkK*a@R z1ZU;)G`TkSq5a_~21iOYK!cu+YpjO)DWapqK<+cMzx(^Zdq~o2k`zagoHL693nQX_ z*OaEZK&@A(2A>f>VGleDI5OTuP@zD=#A2$~<*t%-BiIl;M|+>08?iWBn`5pDbz)$` z6Rj0`FD;f8g57?OO4sIYA!Stvy}WY5$PzbbBxXvrMtIs8CfjWH#7~4=<`cMOUQb*t zRC}$(Motk8xJ!lo**M2(Wu99sSH>G{rOyuS&tQdgDSTVq;aLeLY&Byyf=)RWs&gnP z*i)tqVJ%!t4W^Mo*R|Y7N*RaKtY@~}etUs$FYKHbCvTH!0&jGZ zpbQ!L`!++5Btr`ft3w_Ed*3rL8~&@A*8T%UH}Z9`n+sF+yL~tPd+!YMcI>P}$d$V9 z-COBg$2I%07_Paa0HSDN<%vL%@B!}X2}%E}V1cBB_};W-`9{km_m8kQ(H@h5KYLo_ zN^gB+0Cui))M57db)i_z)YyT&8)h_Nnd3XpZNj+1Y9X0p5z$s|_@=t%uuomY+~Wpg zztDyilR9Qt-Y?lBDmQ}YOjp|<6)VoN8%g`=(kITc^amNlM0xGFpf)PfS0q^aznx?H z`0(!i66g+jDupLgAKuHYm1xt>Es81ya`_Bu?~{Dva^t)+erN?ikNTXIzf$lvcnpx< zebRsR-lUa3pzH7R=@QU`BM5xHHYwT%XvpmziDi;*4~B3Xg{#kPo|@n2nK_(_AIc(V z+)O#%fG*MMe|Wp^-sqPk^K3+cw3OY3#yH{`xSjqDfL`^>oI)o5K(FLuiV?0gIkjSH~H}lNG$U9{>< z|8*8uC`F#6F-QROmN>qK5adVcvkSDasWQY1zC%n| zQi@O#OQvzS&>aM9((fLA((lr`Y$A%&Ze=W+KkzIQ$vF70XCah^G_ZLyaYfuTnH}3i ztzAYZ&lSWy51d4N^&!}$E;q{+4iN?<$y{JB{b9 z;5B_k8OEj!RRpYp%lp<^tNunY%|0-yY%(E*ZHQ)Cx-?M20Y0z|>;XYa-!kXVqH}s~ zsDpJ*r~#nSYn^lwy?YkTG!q*jb1L`Cp0>n~G6bzX6r|kto=ljcI#B21S7!yE0+I!G z`yrq8z6u-#Tw7EE1urgM4O3`fMRPWCkne>ZP5uW*d{T*g>F4}bX7^0HR4_b-jtOXv zGoAVw6C4XG!%DOw7*;RIc2UFg;R+X*nl*kPN1(jQE;|@vakX|EQ6=ldgcQ$V8`54{ zD)qy~MuA#;?YNwVH$p~PCs9;y3miHEy-Lho!6cPqN=OL;-6?G>P zcO^7uHggBcb@W2&D7Ev(JkIQ`Tv&m zf)PyU*WeZcuXAN<1yxU>DK`ISUbJ^&ok;`bkYu{k_u_xE1Vd^GfkB`C&#P3A#H>V9 zbXs-a)*!qq>jw%1XRx97iva$)h)kW5nvQ1_f+HVdM^K&rhqh&7pFyePJ+=HShed%r zz`yL|uj}!vKa+=Rku(2`#?6dp2_GA+zOT;{wkxO(h-kz_rlfx_*?UsUXO zkJL!cD;LcRHv6$o(=XaON4X^$J%}-+Y6*uh1N<86=-(2E`w|{GrcVmQ*I$6rI~Zr3 z{UK;qrYedDDS3ibRn(4nq@g{HE93MEkeI}8cGNumJ%zZ4g& z|CJ<4|02ovTa|-nf(>BmpGwnL!@**9G=W~Dfkp1$>yciyNcv~S_$iIWn;DI=&Q}QJA@}#a zLi^q|-Rh@(Bz^!(dZL@{Jp}`>B*b0Diyj)UjSkp(JtcyYHvA!`nP|n`C;;63>Irz( z;ThN>!iF2O!PCJy>-V*0C}qv7o6S~+`Dp6N$N|`{#S|b7y=5JTsz?NnAaD-!>kDym zx~8Hk0cPlJUA10D)n{}N0!=mXDMv<=F9`w zBC6<7*6CUu)n6!LXLlZwWJV*VXEN!gkp85@|y zI?z&7NnPopPxsd4w1HN}WueM!4eq)W6Vbai(ab-M(JIE}pz_A7vq7xjx-@F!?EnZ9}XR*Zd9J^KtQi3n3rX&;+;?p#Ls^L}E>p|vIEuH4(Kf?9<^UxK!mbdEft`Z-&M>vUObTY zk5fJAza!5o)8q};8iZsoYMRCqn<-PLePlH%g2rqRiwvzd%_Mna-hA=Ssp?2e$*vzY zx0R%ZoMy@tThL)MF=_|x#cjE_az*Xv@@mXA9e(f{3?rC3@H5^`L6K75boptqs0!j_ zRxURI*Vr`wzNXX2-%!F(l-k-C3Yk5|g-gg)|BmPre3hYrJ~z}p{$sHkO-+lBA-T-! zzEfrS&MuC-kd!;C*>Zj`&>OT z<2OF(!*eLsy;8t91{-?4;Kn^R6vL{H{Mg#X({&fV+NmPwL(j0iPNUN8i5R+{$*4$b z+NSK}%kk*So4c3viHr5_ zkrK&zrJ{NP;xW`S_vY2p50B>HijND~{G>0_cM)Sf{Tn6tc0w(V`n_rR{i~{?J5V>x z(?eLV`i$hgD3iaQit<<^ya58Y@sFDlul!8~GwwD#zCQ2AKZdl5nWKStzv)uiG=0dOiQdk`n#GATIWM_V~iUbc2aQP6TqcRXx>gxHn zrZLF}@E_0*GJSiwZ5U3C^lih*Bf(8b%3MVY+y%r!wp6Rg)N_(LB1G38$!~iZSx8ZV zK4x=nwz$5~JYqC1Vseg|s}(RSK0xM^<8qfu9g;AylhSPnm;xMgCi;A^1o<{zr z5(a#M9ag|!pxa+|BF#{rEH$)&VeR2@i;XCD`g{zZw z!rBL1B{agr1qF_Wb+Jz(-EAPopys~M1l}v+6WHVv?E^d9>>}!i$q(Vu;B6}x5wcb^ z7~6sLt`JdsWRPcFh25~9s*;Kw2la4>R4#OW$eTeyeG6xay?6iTC{KU zdoUQUSWG1L&C&InMr=#8p|3i3cwue6?H*PglJiY?-0+^5ahh)SoH^tR-7BE(KndO5 z1n@48CDIF```rF;-)qEhrs;jVwMm`0^3RB@;xO{;C>vktt5VH($}2L)s3*7hQpw@~#m?A1ThyTA;gf}n5m^ncqT{>Su={lAb$Dm zA7EC0a|M>=?IreVSaQtc@_yJ8N}Nj`J8&ZhlI+Zm*Ht+-wNhJ#iTH;PTG#)iB%Ute zaGx|Uv){jYao=}L>?ma!!ago-#rg|ub~9gT&~}z{Hot<*TXmuJGBSS%3%h2QTs)_T z??m6@o2vXeE)>73XQt&|%A$7csc&;zbki!%gmF+oPhqFK*F-SvqH%s)wD}nJ^k@BM zM!^BJ9bOX}HU!$Tt+1*4x>?2n=VA~u1QEJ8RX^|zR&@pjcfa4kNKTI|JM=zg4B6Ba z87;NkkDzldL9%7q$FT%`+8+I=Hm*7lJT%p+2{rksyUrOg=Et6VfU9%}M((2t%S5hrVbJsI9tBzlM|Nbr69rXfALp%|vHQ7TWfHqJfGCyQxSzDYyl38t|SaYBZ6 z7|nX_o@Y)zKKi)Ecl~7TT*44o%e)++%gx}XBqM=7w@qx#twT>m%G}bDge3<$u0p6Q z7y7gBF`X8}Btge3pw5w&7A=5Q@OaS5g~zMAI@yq*-|+#bR?9aL;@ntFl53h1o2aFY zypBa0c{nnVt^hg4m5tJiV3eJ7b_GuHU>7v3SIopG&Gz`jw4efNi;+7e(2cQQQmdmp zNKHO5yU2aMj$}BFPTAo1;bwGf-2*yvoLNX}=oYf3YP+oZd>G|eV4<$IuSOBT*arls zmcC$;cII#`b#w|DJR^zR!K1+oqGPpVg~$UcI#tC!D%cU3>?^RpF*}M!f6e=Cc!28 z{(=b^pL~|aCUsP3n?)MnL1nZZ%m*bM%~%^#NlZ?jguU61gAe_=?SNGnr}2kk3}m6Y8L#&87s}b9Y9oD6yzMr%Mh175x@vcPr_5Y#vfS$j!O za(D!z8=x7JWFYVNQ_y;EH6~q;tA@pS4iSa(fe^qQ##?^7d>)# zzQSh*DA~yR6yLk_pIz{0;_#$$!T#uY@m`t7r{U&*J=&oh$ceUcUb&S~w7-{b(})C% zn)8mNc&B20^8Z(FW}^eHqH=YvwoojB{EYM+4esiF8>(6)HEblJ2~ zoq1T8Uk=-h$t~DWC-9SQW#nvs!jo%}WtDCG#^; ztCD9tY~ZykbPF+bDDdv zS+T)}@GmTmQz3m?>C-OnBK}Z|)J!3QB+=ic)3oteD+q6QEs#V49S+m9Qzb0Q?sdFR za^`2Fxq~K(owMU~BhhY7!IT9=a!q=%dJJ9x9i0zyMh8&;!i~96x_e<^b@*+w;-18= z>@Q<#sETok7X5$WOGc+WE$H#FOMJd;uV>+uy<4>GeT0Yo?kP3V2-aM;;R53sAzla1 zCcM{RSf!+{Ej00j$oTU-=zlbH+3n^gz96i(P~9vl%G*-ARG)j7W9D_F@1hFB60q(k@+YDb_Jg|Y zxdw#dmi~o*^%)+p+M}}40rS=mImRjr4vuMtg=L_?SPwR~I4!sRY`B)sKc_1-=)F^SN$)G97|VRGwF*{wITah%!S zQ_qBBLQU5e4s{PH_h|Lf$iN*|AB%*6d00aQEH0XERrbVwC9TucUt9@1K_!$KrkjkT=l0420DR=E&;quBLXiLq;cX!6TBmTYY(m zS5$E#Qf0ZFNDa~wZHd&h76Jz~5+7}&(M1)T*%?LxvjfGEev(u$fhL&cyUODiPc>J0 zuG?7fF%{S0Z!uHm_yONmmlIM$&#>g+f+Kuh!{n57`*Z9p49Rlira5F{1m}C|IG@V$ zl}5WTYWNolub@MqD&eU_xS4Ic{`km}jt!W9c|=LJX*rbkM~Y8>H5Z>`=aHg-T0_KT zWuUd$eYE-QlRC{cnxIE)g~JE|F^3ncEg>PPB4SVK8OyQx2}FiP;fXb!NgsSI zlEr8v)5Rcyhd8;&Z(;|wwbH5@%WTFjm*tXN3@#kV9*AG2 zA=h!Z?(}>*-UnC&)+X{xS}I#PcX{5F!u$?s8N57QG9S^!d5Uc6DW-5h?vZTez29o9yGX-K63?NTzdh<{#3hK#7Oa)jne^dY}Wh@vG+H3i| zjPH{+Z&QdjyQW>A9jPDfmQIfSpp0v$PPYk(gFPh{yWuF=l)cjzP{&+D=t-9tuiBfp z31vht$*^?0YQxKJizmerS0BHhcG2CRXVIVFC?L~kmpxyHbwiJd`AE{lU#DmgM4awO+xhdACUGE#kQp*KK# zCB4YQyESki>5`rcoAg(LHYjnlc4a!BFzC}aKCBTm4CSK!bF~-5H|ODku%w)+u5OEtk>^&x)~8TTlhF4$(_Ls#n#&)CS*MH?J4u zqGgZfPQP6uF|9Z{Q0m5{i(tNpWOOYMM>vo0ndpN!Yb+?BY<2O81N*-_TG977;*UznC+5 z&L3w=$*JL;Fc3A=NfgfGlSGYI>e1awk$uzHz+ovooh>{h+sYVG8S)&?#JXcu+XKw& z(!fCuit|-Wy72rH^fpu$XBccTpxEM3IMLK!^ITr>>?#Pitr~#0;duVO0H6}rC-C7i zCuk*U%U-KP!k3f2PWP+uCAAcdXO>e(-hibIji5cdi4wNQcxJ$W?yC{(U@K#O_*uGi zHBHvKO8X82fa|Z+eoUTHySh&8fltNobeoWJE0zY2(C^Tl{0@P-V2!pr584cuXp%0` zd3HlMxI#YMme|<%($Edb8(ar_PLI>u0w8H-`5Q0COb;So0_`v@t+k#kk1`RtnSf1A zoL?NRbSXu$8J7xC=8HD$;At6(DLWv@(r3EZAjlkpy>9kV1r#s0R@(2{0dvbcM%Di12Rt-rxTEM}!`fE49B~@c*enKz8{MClk zjL3hw37|bsks2dxA~Pr%(OMXI*2gWf&;2DJ9&ESY}YF>emT8_cYk zY{)j2Md0e;NKOeDELQ7;{U}BJ>RoCZdSouW_?U|3DuR_sR+sAUeg2XtyrD*!^On9` z#_jS&hl}=>$Jt&6?Fwvf%c#-zmZhGYPobIj{Vu9F!ZcoN4?PU`M|^Jwh3gyB^m(W` zjGx**YNo53KlHERs#bTNCNBRWoKX~W%+pykMKo|G6?voS% zX-JK~6(p7nSumHi9cu;S^;Q9iMeed)K^)1Tmj&s&-zZW&V4%4RbuE^STPQh~gIT8+^`2$o-F{JkdQcWRsUK1A6c{{cHjZEQ;TF<;t5(t*0*J;V zy5-4!&*6M1XMw$2y?RCSbq-EJ26N&+wfuZ`zvk;O_&L)yp!idMBV|4=FEn2^%Xuz> zD72*Z2f-Hvqv-yfF%tqSPDgGlUV;DR@4bMSVzb2x=d~wi5`VpkDSl{>^`VxaF!X`d z@KuR$JtBqzFjI8Isabv{S28-x4s3vCJ4M1pFq;ke@SGAQVv&sXMg~L zmUF5-S+h^0(@?%iwkhOSk!dX*WovP^Nlrr1x5!9z$+ zM*_A>rw(xiAE>Xe?>Ol)t4{MHuqT6ePG>gkaV$sLzn%gPq3}>6#4S44jvy)!;dIQ; zE!r~lw{VJB!qEY!D@t|RoD#XQ@|9G3*ELF9b{c&=e8GTC6tEhvwvb3v1U>q@Oxt;G z?r#{3etnH#-vdpx<$Jr1*0IZCa!7Eok??mMOgtdt%r0T%(rYMV1WP}nBY<+BMzJZX zT|59bR;XiD#2?kIQctX633kz`$OAi}kqc}!8E&=PF;9ksn~Y|UX8AD=^ahTvkH8o@ zt5(Ad`3eH}Llll07CtRJq`zFuUnEo+0M|_~NJb<8A=5~2og$uZTD!(7f6yPF^Sh#C z0eaAU4XWO=r0mD*IT?FLIc8lc$V}Vt`hpqj5PZnO0-8>~az7=Q<2V}`VKs2 z(Z%NHCXJb2zSQ*Y zlmYBZH42!=8@g{qkO&KdKy;NVa1H4ke6VX1*pSOyA0Z~-0yz1aG4s5!JA!Y=kTC1f z5yT{xL5|%SI&~Qu3pWw z;q>R2f@i<`g!3$S57Ze|@%YqIcov`Ns$3WCR8%akC5y_BfWaD zhAucg=;N?X8>8E_Ny2I{!&(rl?)>8 zx17OalUyh`4SlGBcnSying$PKy5Xpx0Y&Rtvv5~-@MQjEgREFS-PePia&rkI^}Hbo zemShIJTl;1S0aroR0bnHInQ+zJaKAA2==TA0|AYGTh2@Fv+W#APrYsy=6&jS{$IAz zbmKDEQX`eHP2OYv7V>eHq^2vvu2}i0`e@4b8aL+Vn$Hl|{9e!hP+I-29W%-Jc281% zt53dHivO?u#KY3-|B3^w%#BR`tN%o6Gj@Fxt#?)hw=SzzPO?$`y-qB_{zHYK^Bj9C zCMF*`5{V0$LdIDWps2m1nU8TPH&;52;GIy)2+}MVRY>Wqk?*jNQBF{>jis!em}qAg zpVcy+!6mTGb?2fjuDpJI&t6T%hxm|NqMO75v+g$ zNr~QY0Ocqw=ZpWATjV@W3~R67{Cvqp%rNcv(VYP=?HZtW?U2Jp8qvofeyBPF(5x1xS$4M~wAtOk^} zfaWNb-ZwjmidusOM1zMqDv(`94w-n?Pw&fNsVIy>_Ma5mE!J&J{Q`hwwA`Nk1TmYJ z>>n^9y&Vr&|20|ckP=F3AmNpb`3u_q@v9es6ce~ zl;ri;gL=f_K^lsjH}G*99Dm#?LFi7jsHi7VaQ2IZD}cVY6VCAwypjAxeGYpzj5d_R zYbR1JvJ@??Ae@P(5tgJ3;o4r03n8{YM&j1R^0NN3n?2VC(Cn7;ANC_ySOC#xDv!os z!*GYaML>j4mV={%y(UQ}E_^IGu7`g>bYGgiKUS1%gb-=nXsU5y1uY&pF98+3j;y#f zZC)fL!ze*poCWw+!ojVexyH3xVKuT+!@3->UfTg`pL!evu|QmK$^c8ws-sd&0~W4- zO(xs2OA9wjn3WNK37Yny-seYaqXIz%l_Sd=aLMiL7(0uW;7# z^J3*$`p;Wuk8<9RdvyWMqm4KU2bdxx6ks9=(fMEe5W^MlRaR=mce1q>$V;rF*t%|- zP%9N-4$k?+#d2fi!j_?>*$TNQg5sgJp<3Ba1&Rum#1oK~=z~c>dTdNUKi*(=I0bBo z1GH5rSVZoKMNY&tKN@m(_7Wu?hAMl>U`R0~R;j+-dHruP-;xZiN)`Yki`e97 zC`7{3tklw7fz?XHH~^GS2;sK73+W}AoLUOgoH;WT%|8q0^LIg*>5tU>FgIQC3`afo zyF(|g(J|^#Ni5Zm(11Tvtu<(kmxmhLs5=Xw^4DR^3#M#*Vt9lysUZ>MgYgp!syOLk zJ)ozRg%fUsQ2v(}3Z_LT@km%ckV-o;Xl0TL!I!vA;;j47@@E-}Dgu9dAHYur?yHxR zQ>6mqn-d~YL|t=6_S8g)BAb=UBC@W##2qUDk55b+s?L;afentLHE-oM_u%6tQ zOtwN?SChue`L(X{au6M2BxcXm-41|@#*uBXpu8*pHPVD=$yDBe`V%1>f_a($z!;*C zl|XcokpGIoD2EZjhtTgXR1 zcDO^@-nZFZj(c4{0?_-Bjc>s{lPvnX%vJjdUxZ>ZAHF|z3|p&F(QEDJd#r+DSx00% zwUxDYI78>jU9sTMlMS887LIP>8}`af0t@3sQ$Y8}BY}R;%SYc#sAKr>FFh4e@YVA~ z-rw}18PQAN#QiELw2s#HtW?janbnaAd@qhBtJ&-pK{V#rQ>22%L)n3$XA*hi21hTg zL8;;D!SOCE(MsW#I>fg&tPQ`*^{|Qfe6ymUtP&)#7CD#h{Zl84Ljoso8``W%`6bY5 zMUdB6@`d*WBz&*1Q#)Ggf`C&nojqDE}XhrTb#V!k8b#RxrtGS6jD)yOTxEw*v{$@ z1FKy(tC8x#?<_^+?pCxWE-?^{EUCen4zK?J{kyRfNewYa8E>FM-z$^qk?>~Yq||Fq zODMH)c36UZ%Ei1P1`syf#T9bf2{KVyqe^4<^n$r^D!t8ypcZ5#;}Byw1S)rYK+|l!QPml2T%2?vks>n;>qOeEy(yhFQrEPRGHg?q(5v%PYAJ?0N{ zUVR6drmT?ToRkjjn-|}&#>;JEo^rUhHD{J_5vFDtc9Kk6?aRQaJc$80UJ|14M-e&I zTt|Gzr=ph7_KE4*kSlgQDT)V0#>*wh(5b0sY@>r~h-=-y|ETG{%Q&F#m7RZo{^f|V zGjg{1mok~b%+}1r)!E8~&cw+1|FhZJnS%af(IU7@9h~+%IJW&S0Bm~A6-2!R}gjzTM9iVvrlYeZ8i6IQgejs8{XD==98 zuKp(U$Lvtn3n>9N(>K#t=wi27{Cl7zLS zCGZ{)M&!S37N$WLRre?SH|c3(3^Wy8FQ*~uWLG1na&Mg`c=c9u6TdqkakKgT7S&%h z!~tyTU8w_ZFXc57F=qW|)7IzsKlzW31MY58g>Sm>m0S0cZFTs>B~V@?KxP>zPn6hvajm&50gxKs zd`J^psDK|1fbG5@!Zhg62H@gS%KAyM)Sl+f$wrcK)p*r5R%&S-qXb-COS9UK!vR9x z80wrycci;{_OK4m)Sm1)<#Q#^CZ4NSF~HhYviW~@&w1se>gK8F z%@ImigQs+)oupHk_0^y%3s48rwzs`FDRXrtJ6Vd3K3-`{?547<(?f=+So1}-|ZfCV=Z3sbv(_M zmBocWTDDFOot@_DD5Y>p5eMB4u6I?WjzIIT3;7R=E$P; zK~5`K*fl#&N+jF6y^}(7U=R3mOEsH#o&pQ6(Wlr0C7;L<>#6~{=btzLC$R{c?cpEY zf42I>o58i?AEn%wQ3nRKIFTU|s~U~1OaWrzB{RW5Ma#8k0g zpg^;C2P4^^bnG1x(FXMLE1duYOvF2 zeV`~x5irtLM(rbuAb+xtiyS(nLQ5O!)>*p(TSRiVPjU*wAZbJJUkVuBY`oAQ;*50 zP_bttJp(3cU|Ng<)(V&G-UHA|w^9R`<+XUrouTfkVXy#9c zgQsR_?=W0{s#Ex&$i^xKWR7^vAS^TghV>!zhQF}j5jl|XhgAM5Hcu)OQo}Xn^iy`~ z`lt1!BJ1Sz&daLG+&GSX(;%d+#m&W*xN93t-Id6e`cA!4_v?dBiGs*%=W(rbYYd(F z*_C_=9Q`XjYkRkj{@^H0NuCk{UujYKp35ns9IluQezjI+?H58IB@$oY3Gr58;vY{x zY(zihL$tXrm4WS$CX;@V^K?-@+0{ZzZah@F3zp-hJl2mA32ww!-ImQBDM8=}AGvq=7X*8abjX6;N{ z)b$+p*%5vJ)UCWka(~~M^^nttL-lLNUqiLi9_|1MK^krzmb4{PBBL6!&;QyYqM9H` zzyrMmPoPWenmPnHb~mkFDA2iR-=u>x04rV7;F0s1^e{alo51kl$6V|&qLWh{ix5d{ z_0Pnj{}DOg=4q=%`cr@$f|UOA-H(`ccbha@I2UI`Ig^ImIZ?sB(U9pmS9_RChON64 z6M0qk!hpd7tF1v4U4UG7IKt_Nz1_h4Je|Lb*Q!fWioyAVKYD@`cXnN@6TRBn?%HA* zVgY@VQGz7NBNVWNgL$%8oB{Jy?-2fZU)v(V8qkX`R3#7?OyJHYPo`tb&e-3UJ#(a`$aZeLEQdxUUJz}S6#Y>o$_^FelP|$z_ zP14UgG3pq6xRXF;^9w?>dzWA%mx?==wrIYW#`sCgW6w4e0M}SU%ZH=9ODWf;QnhA6 z{uyBZ9j%gB7zX7)Z@sNUD=a)-N|PGgS!Ec`#hyUM&U87{`THuQU5?U9A?sYc9HOsw zW3{B0ofvN%43#rW>1sHdaj|E0`!Zt-bbv*AWXJ2%;Yi;HAldLfS!3x>Mzm)n__JRh z^#$&g_9zp^q-v!PPdRnII!V#gpn62%+qci(fB7MLT|OX97nrhC@W&9E;4}%0mb{C+ zWO)s^ee)h|4e=7GfkL8Gfz3Q$4<+t0&7rv|VlXV7FY%@aK&SIM?{@MAAZ5)3p6+DKJG z9g>_llD~*>kh2=JGE~Zq;Ri1Gth)|{Ov0U2(OjBwr#qkU#VC@$GX$gU7oHhMT>3$t zfAd4q)~Br7_lYI_HiG4SBy*77fx+DAHaY9-UbLvI^zT=`af59|2faG&Nrmm=-gSad zd@xcJL7ggRX0s`+MbRb3SlK(R2ha5n%OLRY?P{=^#1(HU z`u!NV0<;{@CZmHxwV_XCw8w|**1pX-_sgjYez^136JuvgRVDr_ ziAGA;(wQ#yna{gcz7#Cyz%179T3)oF70N`{8qk34_>`alT~KPRS;MZ!=w0~DH*NaqZ{U(cO8Gvl@zEhwcoXF^4CYon4gb zaNS7N%wuH!Ps!7D40MU!Hz*swJ*SlaEhzuHtFPa*)L6IwzWM6+M+0sVJQJt}x9gVt zcE1ycHOdxwQ7USLxZWzFwLL+UPO5_m?#m~v_)x}Juew!eC+cXBWr$@zW6ts+?*MxG zB$*Qyvj0==jVLB!9h5_rI;BTl2DXPv#fbe0(?JXTzM1XZdu_|FOb(RVZ$NqE1~_v& zOcvyCReYcV3YjFBiI66UuQ7h9sdP<==|Zq5a?Rh7Iw0(bzb+`qDwi?@&I+RmOB{u? z@ZrqDz7!G;f2bYe^op9AD}DU=jK~XP+OQ&+NvOw(;M4aCOX93!BEnBL zjvDUL<1CeaXxpd)KOI(Y%t;qaB8+bEoWh5BfrJkE(f>KEaG^5@H*B#d*Qg#GPYfq( zHbA?LU0b8*<=3{i*%$Uk&obPEFUuUT9^*@VVmQtHBA|7<)e(VPmu1|pXi-X zV&`iBu0oq}CGi4mQwy{Q7H|v0v@GE{gofwxS2eJnG)V8dS_($teE(hY5T)CmeEo%< zC4n&|LQZ96z;aCvH2(N8qZ|e7GrWXMtGYHL_K&?X6UAfFE8DPwiM%LK0LrbXn2LU` z*KuEJY8q{!<3v$DDhWRI9n}rmsLFLSG{@|jN4~&FG6kD0@v(= z=AnH0B%69;I&VOsEjG5(`vIxnvP$X%Y^ZG*pvsVgVqNJO(!e$uA+OGE=WW9M2IWZ> zl#ZYB#J6#SD{720kE$|9h#zSvLH@kq9$~hh0@^h3EZPKCLJJ>w$J8p-Lbp64|B0NH z)D~_ON6r^NKW3|2DpMSeh{j%adc-I8ijZ$yVIXjC$K;J^rgxscIEDj2Jc39j$sKdc z3N5ji<$Z0~tQou#ojSE_oPdl*pH^goP|Ju$q;!G;i%NMrw4q4CRE{WBI`k{y^X=wU znj(;*oK^eKRelc&WMJWEfK2vG&m-YB@C{MuT+k4^O_)yN<4xigfwj)UFom!-sLvea z(#X`(Nm?r8{~_$1!ZdA{E#0(j+qO}awr$(CZQHhORNAhzZ98-4?6t1md;UFp?bGk{ zdt=0icp~DC!8tsvx8Yc?>Sofcp@d$*b$}`km{HRMEztooDyc2tL^#l!)+532;V5%* zS+RgVfTSOpBK(gM^>5TyYolyMdD($~L1b#%V31i5O;8wirTf|O zlhFkS7{^s`FReN$vA#N2R9Y~PfN3U{H(j?^&No|!3~nom{Srtqyubl=(_<7{`t4x! zEu?BjL2^Xu7-ckt@ z!#yY1IeyZj@~S;`ZV%e&M}rCSyA&9iJ9S4r(epxLP=l(jFeu?1i1{mc*#e7iG=qVd z`w6dIKhF{Ep0!kiW{teQWWp2kFiX#QBywDS;d)D@2bk8Spv_XL?f0WeJ}K3V5m5>? zT|&mEI_;_9lzNMU#=DQoG|T$NCDB310{sF&+ZYbhs-u^xw}6?bL)mqx1HqS09s#d~ z-m1_u_ax4FtQQS)xeSj0>t}ZE*FShvH4+CN|LUel{j@~>^WXY!;(UCorl@P&cJo*0D)Ln;^R(|nHPc%>N)7QD+Y3cvwQ4c!=#!6()` zWG9BDlJhkBU)Ckvd!bB9jA#daWzE3a6rGR*ND5YEI;Ef(GfmfbwMt&gE+-v7XvCPgs z_B7F~yb$|fu4kFf{F!QkUARWQnbe(E&UZFz*G4&~7z&;Vv78*1Z`~iJ)VWovslpK< zj?NLKmVeKR_|5U(cxe&CU|hPJa$Pqw;K92b65+ueVnxo-mcc>;Yw=LWN>#DXl?uGg zcYdRn2N2135I7+ueq6VmgKA*v;j|8^T|_OSy5Y7S9oUGL4<|TZ@<5uKQ={)s_3}P( z^u=p9yzL>ZPgJka_8xn|1yXu%ED{DpTx?`e!7DhRvc1M|;IxhC-4|9e%yQ=%HQES10~u z^U7aq&ymoyz-B1gD=1mH)ZI z`v?`zUgyYaEOAbmJ zhMQR-6RUSllz9y@R1joStnQXgMY|6#PGsoW76(C#)wv5%yvhUBPP`g_5v-QldoO`% z$-_2@N*wrT?d{dP)H|Uo@H$< zHPkzqESj2}Z&p{L%;HFT>vtlV136)r30Zu6+%Tf=iqNB<+|4TmQQYqC6_nPjbbMG0 z8d26RdzX6p-F=!hLUm(C_R(iX_VHUqj$53I*L)3&*S=4zZ11aD-F3m0_$^9i>z;~M zd>Sa4Hu>2N>al;9)X{$?n}LDDlpsk5qJu*XgY^%L!x}~)7QhBs9@0Q}ewb(a){Ypi zP|vVYa@gOUcZ>VnG2|9<@3KYO^SzT@ zaqu6CsXss5zh<={GgbxF*fv^m6tN#4JK?c``83kwsqbNP@Cro~(XLDEKAuX1vL;uH z<|0!WX^slfLOQDqgm)-$cEO%zcSq2D)m;sk62B=Yom(#^?{O;?ebJY(47@YTQzFrB zMC3{8Paf4vvZ4yoLc;{BCd~HeS10s)LcXgixU}0_Wj_dyGmDm@Epn_=p#SAARQ}Vf zG>yN3&GHpi7z}K9A5GCtQ+R?Z7Oj#K8OWmOv^{hNH6*-6$s%h+^`MzE<){p1eSUGT z;dyr&xICa(FMRLN#|{SiH`Gb&26{7+vli)5t?WUFsapyW7}edyL|!B~tLK(JE?$9A z9Yt$}4}gD_lvb(|fIT45sa&{1`wrdT(|BjJ;{&kmorLKu{tIsirJQ77D|jL#>{@8Y zg6MCIx1omIS<7}1z2OLQD8Ny3+v0NZh?th1%#WSoleLpV#>zq=TxTAy8qJUwfx z;}H+GbZ~x7t_1Zz2qQwopH_%a`87sz3Z^f~rujf`Q99v9PR(SrN&R6~8%;sK=NQ;S zQoMFTZWtU~RFyw1A969+z7-$|x}-3gXpvbgs1aVmcsw|5Id3ajF5CFKl-SR09L2jc zWpn@^SW4fqwF~||X?@s;4Z>orynwigOa5su!M-|ma&?U#a{-#a6Zk@f|MT0pXj&KQ z@7YR<*pZdb+o@%e?rhW7Iin2xT%knM8PnHOj*LGpAj5uBf+ujYYHoTWR_s;!<*Aa3 zcom}#@%!vuJsv~2;Q@Q^ys^dMt*d=8>ln$x*j%W!N#=le%zx0!<~sT4LVEvkAglta z#xd$AKgvM>05JSV+w(s`Os$Qom47NU1{m)jB8B)|)35lZ!HE3fr#c<53w=R<7ui8S zhL%0EWKzL|Mv&ipdf)Z*>#0!*IOH;Ck60k#(sy#9=<$QQH>L7OB{YL(h(C!;ibFl)EIdY zK*usUB|JEmb+J7#!5A0xR@sev^zPKEy5RI-wDK6Pc@>>{b-BYGLGnGi z9H)6PQwg0rS8AjS9lF3OWa{dt&{mIy1YNG={$}NTn?73}Gn zB(n;a?X>|nJx@O)ddlh1t(D5jnNG5MFBj_5Ga&>Ix7#=18DPESA?JR7nZkSBO49lI zYXSn}1k03k25K|~bM?5vfkfRfdt@VF4g3>Yh1ql{fMRh|G_hD3bJC^Ha8~#Oo+_Wb zW{!YtQ^&vv(|~!4a+7lVhH0grO^C=u7@G=;@FrcGM&BjX<4H?Qcn{_g7jQW>HdGyy zfG6&6ZD5ZiO6QmZVak(D;`f8>=`=&SK8PG9Txoen9LOim=yN_|!sw$qACQ=|u>5CG zQyzLp2x-iiNKg4`W0(;{LPHKxM?>{pKW7T`Z94oF8=s$_;7@3g zORp1$`UGbytwZsVzfS80wQ<;c0()(&Q=&m!b_*=%?51X-i`_p^a;GYhdA|R#wr_rK zj!XLUWv~7?Ka&6WW&e{#`s3-9v~AZIP`saO+a$>A^I@ATcvxZsr88P;68|=ZmLrk5 zAlZ_&e8fW$e!bUR0{Ev?&j$|2(Ib2{qM_ZKTfl+ZX5}NLghc$1R_Ix) z-2^n`S(P+|KKqG(g^_qQgw(k0G-%xo*gp+Y96_VY&*c}-i^ke2aTf#PHkhrGrFu$n zF;12hf}_=9I?qLYKm4$?SlkwFcdxA_n19WPyb<_D-NotPyMbJh)(?t!`p+qkR|U?L z%0U)l$^SJZw-!QF+tSt1zP#>a%2NKIg-Kb~Xj9oLvFVa}99&?v9Y)KG=wM&@4*s$F@IHeVm0me^u zyo(3pt8iIWJkPO#x8+?$+CUD9i-b#bGCYC<0Y*D=b-0b?(%>VS`8 zUXJKQ`HG%0IQI1m8_ozW)SWniu6$)$cTUxoGBLl!vXVbZPUqwj8jJwpM2d!@n zSLS=U`f42=xRUlvX7bHaa~^H6c9UTX4Z~MuE96V2X8`Ui&fIV0IS&X=RMCsFxG@(z zZG$s-T_7=}S0y}fq*^2V33+8xr^Hcg)EHskp^E_MTUI632DAj!@atXj zW-rBJ%PE2>i16idX8v04?QKK6K@!5|?g4tEJ~V@3||uoksg zVF~t-|GgD}g0HqL{G%E;Kf71|`7iwkE7aO(Q%%!yUj)Tx<>#VMa1#Re*g#KOgRx<$ zwV6#7Y;n*pk@>$lD)V7;qv$xF&pDihmBb_UiJ``Ux5m?-PgC+aIXPd_Mj(!S#?xzn zCm%^}%yB{KU$ zPwvml8F6eUC(p+%q>A~xe4A+Xgj!YVmHCC$lY8jI9)1aVO%8I5c8e*vR;ck%v$9BS zP@k6KHS38_4{lbcS8}RKcMq^9fx6DDUw%$$V>FKqg?RWZbDw8FPtWkpWBO*&lhx8m zR+RXhj+FxQ?8f{0z1OOkj~?^H*@u(c50^v{n~jLj)|jpI(-#d z(%b(U9ErT}ZDHb@nAQzV9}-Fn&u{cT+)F+RhqEV`o_EqNYWDCDSS@^KF2iqM)ZvkPhm(@6Fm6KB3>ZQxt-vVozOG zARiIcqxP@#Re>1{@OTICcN07cvw#kv>(Ncs)c(m5CGR7`|3K}a;en{PO~8Az z2icDEjM}gZG@Ta1V9(p&CXj|o4t_O4HE+2vM8S~sIZ*=ICmecz^cOis?AWBYtM3^I zmi{)ewAY```Q9C4hQYh~YIv;=ZN0+`f&W|lWcO=+kjPwAFQk{d$giqbIM!+EG3XXD zBvlYX5zk%>x?^&ut zCpJ@wv_@)&QlL>Jpj+>ufjmD{(c{2b(bFTNr+gIAwJ7G?N*~w)2>Y|fBn(`DlG}H? zE*)t83A|;?vqTzC9>l>@mcErziFr>})QJl?%3ja*O)u>LL5Rn=|z#p8EQy zM#}L)p)}FFpz@sqNxxK=%>`{e(HMJ{R;sSS1?9JPU&0RJRzuv z7M?@Ni4)=1`no{k?qL8ku`?)g)O zsQniy>q_@G1?W6r_J!M}&YiK@yfbAT+izSLj0l2!V~st5a4g}qu^*27R(t~qcYWi7ezr(F$)LT?*eBXoY)aD7{eN5X83j-ZZJ&ZOxVfZ!x*BzjuEGo*bg4SA#$ePY9x`1y>-HUfZ}*p^=bO+zCVnnV_{)`G@mj|r zV%OiYSsG`YLbR-?&1a~nU^C>jdXnV|6}oSFKIvNV+u`J5XpxlqYunsLa(DT01F z&!d5usOFqp4??d)+s;aq?d$Rx1ip=F=3Ksam-5f^+a6B1n8FG-yJn)i7LW8L&E}Kj zpZ#6=bfi)Q4!Zk3TMXYl9)OK=t@+Xd-!Scd2^Hiq?d@A)s}+<{>7 zvdP_YCA>Xx)1bPH4%6TQtXR6QSL0LRTMO>%et%U(*MoG$3NKL4?Hgge9nU4;Ove2HKRUu|W78yCtU{DqAFs}6gPW|H;BT%0 z_&wxnlPb~G;b`$II;B)0Z4uAHIIWQh0cEFoGqY{WE~zQW^asxtPAW^D_)$|Z+X)u| z&GnQqQF2M>!125zp;ZdK6433NLtj5`igc7_*bwyD22vwt zdiUK5q++V%kIhC=$@w(9?3IsP^+z04L6bvHCZez!9}PEn1?GeFs_p;?*_6fO_D0Wj zZA7#PH%@T{Mz7NB4?aHT2gR>TKT%i}o36L^*RKBRL}Q5ybM$0yO6As3=F(|wzzL%E z9d)hB_H`&SwDiZFlGdf)G|*g$aVk^VTOun{c*RnU%%Feqs6U8!M{o*(FYfH+x~jkRo>A<_5{5t5t7c6n<~5YQHusFh<)!q;xai^UTD!n403_8PG9SN71HzaJdK`saBLJLHC*OYMh%hugQe);ae>`Ux}o!^5{lZ^D&R4tnKt=UJ#+_k z1#z5^z|q`t*ZW}_b|>h#Cg^C+GfKn{RF6`2dn3JP|LGyk*+~$+;h%Xc%HHb!E)8@Y zW(Y9HLq313*^v(Q1HQ7{`vl9a%xR~W-Swf5M|+8S=DMxCZKJ+d)u*V? z(yxK}1W%bj-9R>2YxJv`#D{ECuhGk@(k51+vBeZ)7#HY+4EeT zPYvuNKhUK|IFgjg2HkY;Q@bV?oFg*zyUp1nfyk1!R>CS`+dZsoCp$C@N^3@F1U!h8 ziS$xS%659#X_bB9R@^jQN}UT`@p_e;Plz_Lob}jXEm!gWa`yo3w(Ne>*&a6N3Nm{w zzhuikOZ6sx45pm2O_rLgM(-_(B)1>I3sZ53OwN?Ka2H4t4KV(987x9$7iA-!KH?r! zBMMXGNg3HBvB;+Hv@ofli)aFGv^_%@6<(8~3PFq+RDtf1lHD9^qDlV-CVKvG^G!WRim*Zn#L#lN@}-h^;PYKBSl?p-l^SNB{s>Y z6&!DHX&!mO(d-SD@OV~Qvxgft8Lf@j6IGzN^mQS4m`&{~KMW_X`*hE>yVx`_FGzdkw-V64MpJzIH$-aO}F z#e&`?7vYm44)0FH;A6Zi0*qKoJ}8VC77M4mst(^nH5Q5IQCU<_AP9Ug<-&J#K|$Js zDE$SSkkXj`tb||~<`yL+yupMb74h}S1~rks)y~)nHPQWM3nD$hgxe(fV**BN=9chx zaNMq+d<&n=Jrvw~&?|MErHQ)6?u8B2vtKwUnMjARA1pL{cinN#1osMduGP%?;Hgvk zWyecsyU=rFWEi1IXqpfUFQ)Vy9P>-WO=z^FT_&=cP`?MNDj6wMC}(hGw?D>R3*ouF ztscYKP}gw7n12faP+X74&2-WR*!$vQ_%j#i3jjC&6RGNi`@qjBy+J535PXvY-umSpZ<-1&Gu|+O z`}hqKa{wLD-_Qyx$U+HjUQ0Rtp@0sos#6~PhI|hKwuS7!iyRU^tgKpnmj{|YB`4y0 zB1AoNB8wf=Hl7h~JNI$b6H<7!7I=2QbSGeDPF~#H96qG1RT(=A98x=-UA0>bZHmc= z>?cO^`;15rfyJ9wLaD)DTs!G5gN{7-{A`X#-2I$aAjesw)DIGtUS4ZjH%8!eacM+F zAiSs_ZxhVNV}^|;^~h;hPNaG{179T^s(^3ddh~D{ftOeOn@%yEh+O4#wC|Vu-JttD ze4=+k7(+u>I#fXEZ&|o+v}DfCU8Q&%e@s-SKo^vGN!Hc=G9?Qc?$f`Cq{_cfys5|c zV2 zoUS?bMHkn-A<;P%Rv+Zht;vpm#Y)&w%rsMFI(e#gT?tH7t}V^2N$N&@wwa}UsE~?Y z<|x>mLV~65a}4l#cXtb;v+pDJ3iBa}vf8=FMZ`0?5f(TQO@Qd&6GTMgGoCHX=^q=r zr?}5|;kCv;JX9q0JNP)J|qYLY`NOq55-G!UQ%ISf*l zi{wv*{{v^77`>QB+Kq<)Lt`ceIneb0X|!3B!M4s5@|doLM}`>KPG%Y3?GHYZj*hq$ zQ&V0Fq{rz(Gu9DhSJ3ukZlwU(MfL85D<_;$hEXUAOp}S5 z%A$rrX&h)TQQ{BBfIv>!hro&H__j*SNNF%Zq=U&u%w+aY7gGtP2Spk{H?1u>0--bm zwZJ?-WZbYLlKMDnzE56W2Uj1kMF}Y@ZGj@K*)9I02{SP>wJdCH3+04E==2H zj!#X(KoloWEsp|wS2g(*Qvne<4{;g_iAWkjgrrpm@TZJC$-+kjIaFp@Gn$J=?gq}q z991^6%#yOM{U0gjC*#c zI}~H8{2fO=a>y1 zN%Pk^L1I6gvm!euU)!$KQ2@}0yYXEiJQc{2lyLGMg1Ne{Ky9*Z9kJkM;84e@y=kH- zRcDlzEce+uByGyEHQ6pFSuZZ}qBU1J-Jb`se6rbn^a%cXp#XF9+V86bx1CWYjL!DAzccj`Q}lG9^Vhb&LM*Celq*=-vnl0N{|| zAGPTJ399@_GU`9I=qTckf2^0&;;^Sxr+1-C@u$99`{7&wjhOM_1Q-d|{D~H)vlSm- zCjGkhHc63;_XzjyDWIJtu_JMC**Z>Ny*-}E?L8nvg=S67uEizn@N`Eg7jhvlz(y5L zk&THtG4`#AEX#Uo=5zr0crde{FTLLsTRX;=B<9axh~`kNf#1RuIWnV{)5yyr-qvNk z2m+PP%j?_{GVX>tlBQeZjEeFi&+s*Lc3D@PxX7_+;GDSaO%XfBGECZNTyn0H7>n(U z?n6kRbHrpu9SjuFOI~#VR{P6p(kqpR)RCkAiOw(;MU}X7orDrugN0825O~?L&j^}{ zT|4oMc!@-pte>ED1Je>HChwNp8)YLGfoZhNnW}Qx)k)@Db&q>srmQAL(Vkj_E{F|&y0=EL={82 zo9?JnaMQDRCi`#=`JW8moMAc`i%?II&P_+J`Ci+jtc|m*{p@M?{5#3p42~^+>#fW? zv|a*6>#Afolc}ZanJn_>sf>|UE|V!|*byG!9@Jr!_?OHCeYA8GyJua{?EOu=w|s4l zrPA1KYmDtoM+Zd>lP-a05#*Z-ONU8KbD7Os?oYk+dZmJZwwB;Cu14idszknZYPhm! zm2E0+O;eKgKiIpWnsjC+JNzhIUf~v9YT0jfPg> z>}PCoU$gr+I9Wfpg&l09)1}KPR=l)Q&!gl#!}5W5LM&p7SqF=D?H-o@5=ymp7C?T`~D2e{0Y2u^8#~zyYLc|J#fC32o(mo z!DHyuh>J7U597cJsFPa}mK|^thbOeKHxq21NSbgVvsGE$046sXcNz^HI^OH z&+($Kcr`nLTRVZvei)Ozu`8~5_44xa0J7V5DrNX{l13v#z+aYG4_=7@domXZXa4o@`BElHvP@&`V4@pbhLK=w*q6qe<;uMy|Fw?~EYyRps5AXoNu>EG6 zgP4{8O|Mhhg2BY}7WX-5B3xwR<-3aUiSqElDGWk(;7I}wV2umVq(d5O&CaW;5<%01 zFAvaG3zbtF!F`u+>lT~VG;0-faF+<>SeB^z*F(eZBkcsgscdP2s(i&VD?BED>+&WW$MB!P9 z9Yk;6rN+ z_0`5hn_=56l*M2l1y-Fji8^~x-xbjPQ=sr%!;2Iw~gj4Z0fZ4?aLMPN^B*do+UO2?*UqR+BrQlz8 z`Vzk=ztf^LTfw*m2c}0U*SX|lY2^Sj|zBTGJJ7Ank6g9=Ek&k04qtzNp5hNrC zGZ3t_agwAFN8zu&UGtjgqN@9u=)+v)@wr{~0Yu@vicOQBF6BF#s5Q8Hf?7}YMa*us%G0%ENLh|=n={(0{Ku@eKGf^wgd z2(jqgetA1q+c@(?>M!b7j0wwBFqrzmFiNU+h*b31BNgc5#*SI**ziAZKSdot;c*f3 zH|pb@1zc!!?k+pRy?7+zogD01HcFS7gP5vIIqRaxVs6?d%Ou#z(@<>=zWH{}Vg2_8 ztm05q;K%8GB!oc^cFgE!MvR!5AA0a|`#lyIA307pgV^zwt}OmPn6Z z00=bW_oMdE@ly*m$YacFR>PJNio^I;u_W*YSUefw5bvC^!c3G+L#81{(3+vb`cySW zN#?XbhlTUdS&hoD-Jg_q@XM@9|JJ#xN&tfMaST*p8)&KUN|qD>jCB15lyFGp$+LoK zJw;Yl!Fof5i|givMzs>kkEu5~OsmT2PwU^cAA*Q5RS6()1cM@if5Olhf{Tu^sA!_2C1nPiiLUWyr#^N6-JTwcq<q%pidOJeLstf1gVJFQi9nBX7n2e~oQ* zzf(h)jw}v`)NDE6*GECn)2`H7kvrv;0>XG<`fOn*a>6Ah|qHxjCN#LF)$ahX~2y!boI<(Nzi zOrcSg;^T3x1qe=IWI%P*m(qwQeENK^Xab8`+>|W%Cyam)cpocE@|JLmts}tsq#h59 zV&SgkPc}`73J4kM_;gJOQEp231piJDj_d_n>CP9j+UU?yaNvKsHQ`bz`Cv4TE~Qv2 z>_o@4IadpgYCwHHQaJto7{~wp{IGCBz*%3*NF8GFa}%CJwHTUa5MhxkWyl6`_CkVa zTS)YXe2@p3J3PrO&i&Zf+X`z$^bjZu1N^&Vz84TS(r{K(LvrYr{?KGb(NQN7bG_Eu zGkESPGDK?lsS70PGl!87Zhyzb@7V-ain|HSICnYhV#y8e^|Sp?nkCk4Lq%tP!JkbqL{7@IwE!J2pyrDCIE(uFJZt^M4 z5IIRob*`8?CD$C{zqis!h2zIl9iyD$IJobR43Bwr`tXAou>!DPtH(@NZ4V$h00hF) zw&ejmAL3R{h}#_QdhtJM8*~|K6C+EP6$!9`M=P2uSq3v73f|`kq4O!la9|~#l z)7$(cn`l^HU-u1coK*}?4IwuEHU_Ay70^)(tfW?3Vr<#9=v0oC9;&~3!gg8jCsbG5 zXz{I=FIv*rhmOLkQoCDpzeglV7|7nX7-fTT?7~@JJIL3C99{=m%j;Fd!90%(wz`5! zpQ2nCd{D(BVt*(-EMqjUp`^l1mMW3!G%8M1rx&cAhNj6_1(a0wxYMwI_oG6TgSer^hqSm6)Nw7?6!r%Q95YPg6qqnxZEu7zk8V*4vFlP@?J>kznCz_UEXu>d@K2!{f0fG-Hzk=K`u${H>czJvGxMO7p5D={mrdsH_1S|rfnMhUIsfNy#I!$S%3 z+vKjFM>6GH=tgJWfFlYfDG~%uCy|*GojUb#`T*HGFI3mLI#;|v^R$dpS?Y2#D!2my zv<_Zga(G;806u8bEYCdp`1JS-N!sP?tG$A53Y#?cBh)I+4l7^Z<0%x7*ZoB6+HM=V zWt%%E3UP<_om8Jk$vfw%G3*BJrXAs#Gw6198g4o2U?V9xcW$RAKvExpLsR-N z@*c<>s#S>*Uo5XQR&HNT8kwzki!>Qn<$;{Tv>4Xa>9j)z8G|SOe^=^@qr;VspO9q! zX(s%SA^G3jLu;cc6=~a_>m1$Zst68|Bz+#O=80D4nzJZo@SID*@WO~Q5{*cf;Ywl> zPaQYD*Vt!<#m@5`oJ(vp7j{SXqwd${wY9b156fjS&=Ow~NfNzx>SL_M=v1_VW*4Y8G9yAm8L{T8fwF#BrV;zn1|20v|`HKUlfh%TqRk^v;3MeOSi$YwPJIbQs#?mD*Z6HTLw(2SPc*nZMf616Y0jm z$bOhSVO|*Y@}+_b4Sco;BlhlE7)gQYqdbX8m9wvNY%4z&)xhYFs!p|jk1|+ib~tVs zb|deP4!7n{pac-10S4wy`K>?BL==T7%uL}m&T5yM=sn}sS-7%I$2i?k{gDF_-bm}~ zi{#b5ZR1)i6Tsi)(YSfoNGF2Gk9VB6QC3^X$SZ{vn{vvDJVgOJ(d3@_JG@9jX?d|s z<~@bVI~I~i7=>z*L%sv4#1pRDXhh-HVE%5?O}L)$fV6O^8oh&y$BKxYJkgWMzB9+9 z*6xNqsLNpmajCg#y)J2C74QlyH&k_C-Y#vr4bcQmQZ(Lk41Y`9433OFIT*;H>9j|E z(j1?V7?j=Gkxm8kg@#(`YHgw}(2jMfJrWC*cZ*#boM>vHS}-Vrmv7$$DToW$3t(RR zMW7=hN94I6qmJP1!M^mTu9oTEIQRV0@9t7=XZJ3x+MMqf0S|n#9tBm~ck7*IPu|87 znfptvX^gt=UFz(?RJuiW(J3$+1h?1C0oW6niFLP%9HXug%Z%7bZ4A=kEzRj(&covi zJCnTcC5r92T@2n+y!Z$gt!`FfsT??dU&2yd_=v2np4_{?YpRx}xr5W`Qmx9u+ zjf2zHzV&zF3%M%Pba|19wM2rlCDj$8y24irCKDK5;>3J`w!wxlO|_G;V)>fU?ezznad@ z%zcmN?Ckv5+A7kVrFbV>u(*evi>5WVCq)~9VBy=MGqFpxl5f^RZM~8$*i^H=LLIJ4 zL&{>9%cTtt3p_v%b&2{V&`)KIjFW6}E{1LFI;W;MtzERzo&)gmh=4bt*T10(L)kT{k<>2vC!YqtXJz9wt#1l z{PqOU*jQ5lP(;XVrLQ}(vG-TAc%$d!fUiF;frL~3n%l^Em5_Xl^RE2Ydcw>O!z5Bj z3CZFDtWt!BEq3bNbu0^K$xAZs#2>NOU#G057Lqc>pzQ?A*muwNrepL;XmdmMmwye1 zKbx!#4TP@Ci-c=uy9^-9t00G{+QVv!opp@Yz^(5@JOLcq^x5hzT__;LfTb*8>9EcZ zlWqNebU_l}STdQ@+g0^WVJw0cHC@Wx&{iceGrl}Kh3f{r$|Fj%)wbk)t6G75TvQdJ z^m(qE$dwkZt&T27+Jf21yRR+VYMAIG;+sLE#Te1nszD@UqDuEIMxar;0j^F-29AX) zA<;E}`NnpptZ2Py+Oah$s1F)GoC zxc3Kb>@>)ahpBtTmU&r8yf0h3W!17;6!9AcFQ!p7V6--Hb~8382I+zmb(#VevPC^H zAiM}lNJXhq`HsWtNN z;PBC@;q$uOvVn5LQIr5p2MwV~`b7U_|H=&9;9>vS*%YM}`w5z~Xe`$lezv?B6d8MJ zAdsWdX^;4%-+V#;5(X2U0!5>#>V*r{FzJTi|H}&AY zX#jozmPDSD$hyWhK9K!pG;VyGGfVkwd(~<2RL{p4o28*$hi;Frd+74++!qDyp3C`P zmaZN|($zQq@fpppB*Kk>|T7x%tq3Kw&)hVs-7`*dtp(}j&Y_4QU7@p*u z-=#^hW4l7X_*E%p%zf+dl;I`CHR-l9c(`JxWOZ*MZ9PR|Z0}{wFOaGD6TZkTJ`{)4 z!k+RA*2NnYS97zy6dpzv5*%;#PAa8!6V1o(`c*S^O1}OvpW@bdFbDKgx4r%U>B4^# z2LIg=K$HKMBd{b0&7+&eo0rsjkpp2=#S*U~{b8fKul!3GplbY^o|(-l=um1>MnauKJi?8%IB8P&uG9|Hq~15XO(C?({{T% zo?&@&SuIP4^5d7N3qK>aAqvlhyKUo&X*n;+JNX+z(Yumn6YJ+807+9ahQx^SL_U|) zLw9-))0>&BJ_5j`S zBK<*}UP)*`nmkE}WkdZSPCeK#$tKjxdA$7x1U5^&c~jL#c4B~Inb0f!h3!c%VafIM zw0Tee6mdKT)#oBIJyjI&HyI=h>l-jXQBf`A$YeX9gRr30HDu9JIQ^l%#xRZh^q&>vv4^3kP%!U{od%>|jk+e_N&rTK!{TAwK-#JeI8(ys=Nwus)j;M|30+99QTnE} z52Ta+MTyWfN6k#r6b`K7Rc2LpD-Qng7U31Z6EHvCf>|;bYt$5uyv!Il;11amM{`^c zpN0hR2iQ8Y1nKfGVC(Xn?a%owWe!NJLq2Q{smQ{6`KUf1h#cITs0RjTSTFe5r04#2 z5{}5*d<@wIyE}aa-N^GOt@gMIo-kJjdb-kGuG@>_;|)*WeQNv1mUS?l%<^>B<_Mc( zhhfl6><$G=uTw2AcJpP$=)OpNG#i5F2wke-Gx=f6EjBZQs{so8%k0CCR7F0MP-fuI zUJ-Xfc*Tb@Pa%o+!n^8e!8^B?S5M&&>)O%X@-OvRZ-HacN3q}jAf*YRNLd%h|gRL_6 z8JCO2os;L3m#k2|n-@{J11l-k@UT}B^<h7-NX><7Y~h{bll`$s3iKQ;s@sfkS~JZ3>>SU;P@51qt|MC?`km=&3R=@r6U>Fn zoJSPb0q=-6Vw(aNj8YW;Qi7eX=Y>&4vkIi4I>J4(@i95wg_4DJeX-A@~oGY_|5Z=5FWZAg|pT|uVhIrxC)+|y4P08ihNCtIE;)I0@>b#%>R zvq}D-S@{~=c~+=qedYWy zTFbWKit`91m@UX5foyS>#R)fY>3{WSxG|Ma*`47TvZuX^%YlBHpg8IyQL_<*6J<9i z*(@5f94`Z^ocRk95NYRzujR?1aWbTg?C4lWPm1PXe)z=HQ z2~Nu<6#_H2V3b}eVlLo`{WgJaaussc;fR}55x%R>&yJ~&CpWg*4L^OweY~k#{xur= z#9Mf%(er8&WuHR#dOS)&sXgy1I;@&`=tVSd}&oodRLixI|7`) ze|bP@JPi@NK4zi}MJ7=%Y(yw2PpvCnjW_$7MnB}v2!}B{SnmHJ?3|iJjhZxDw(UA) z+qP}nwr$(CZQHhS$~Wk=$>5h(>U+`YN&(6%9do52WSd%V!{zJy$60jVIR0?g& zj<`E%v$9nc5ED{EJ4W4*FMiZnT!B)A?TY+765JYKR1%KyI^co=nhMIpWDR<34qF_b zO8z{8?EFknh-tZ;Cu)iuZ~6p~z2q5gv9fiRHra$cvb5h?MwJ~B>6n{}Tsr1Ah^qa8 zfqOR&@!;FJU~Yl=nRdZX6Vo-4;Ro994kx-Kzx0$(>8a2a&wJeI+zvYFYSHO@JtsQa zaPuOv+-6wkH)F8Gm1@p>#m$)4cNbzN^QEZnT;?|TNnq-FaVrA0DSTgX3gMY|_e7R? zt#ctrHh0Bm`6!MlIB+1&`cNmKJ8o*kHinSwj@?M(qTs{udG$#3TB85`@@7`n&5V7C zzvh--Pa_$SuZ#%Xf`;Hs{EptL&+xl59e--&%r@#Bp-KFyS!|G6fFcRYwU)yk<-2YRAPg=oTU+~KFA@>S`1iGiT=>%>g{D0It^A0-OSj|9 zZF)?uRS4OTKj&5&2u3-V#B@rXT)~bRlK9fM6nZeOFyM3_EVSQ0@_jVZ z&wO*=?5uq963LWy|I!=AV23S$86>q=2Bu?Zioq4JF&X=GL)Wd>#j~vROHwu))<{p; zZ)koxCVi3}=NBw3+NNYbacs4uK^tkJ6p~6`FUT0|OYoX0ge7qB;Zr=xcejn_u(Goe`a*++z4qe5>eGy0F39WO%kB# zjUAbos&q+e5}UGTmnzO8Aq|=Bm-;%g6?jpDL}~K#;4(4d280@LhJ(H(++`SWhOMo0 zgQwzr5RzeYgU91MUMUUg1-OByAm$L3u=rqjAttp0LoUw8l${MEv*z)=%55IL`;tiT z>=fDQlCUL5q&1JIYEA*y(8LbeuD&RfMCcoun~&%bvKGuGak)1+j~rcrj!43Fpo+c> zm%Cs}I~rt*Cp}7<6gdDA`$!h!XHLZ-#A&1rna@z0)*;n^#O}-RfY`AkOLM{kwXDgD zWkJ)v$vZJmE|#=CI1T9_d=D>dx^b3)i*2`if`B*YkG}*rv03{=R=$golMa?~M=3MG zed?gzrKoZdzwC_`Zsn89X3C?$+^4WcfmBZt1PO>%f8)+oLj##HBFx4QcPvfA)Zx~% zG?dH-<6Mb?rN2ZC)kY{JEM}jTgD<_DCY^P}b(1!M;L2RMv~;hA2rs}IgGOP-`3kLQ z)6Q%IQm{7J2J)BnlVTvZzHV9V%H<$u&X{D^yEV!#LHg+?Moy7256?BI_VBB{^AvkM zylhL-z%seBM>WrDDmb6l+wpYjvpB1-q1dkL%G1qkewe136YbhewePP`MxKLDCULxOK>OzaEpE?smV*Yxh(Q`CFY*7M4mb*lf?b>pKal zQG(LRjI`;@d1?yYUVPB7##4>xg|O~svF09fDK_2m{gLGMlHvFnOa3^cC!8-sI?m8` zTg>@K0BQ7=GaGn!a(k!w_owuH-1YdKdW@Iw0r$d>c#JPKx?_PC%@Gxswe*W-#!SMm zXof;a@1J*ph2x@0uAQE!n9~1zsI=c9KaTSITvQtI|C4+FrR)1|xhIKD=1)B`6Q)^U zfw)X_A>>uA^Pdi`MXE;qCJ|~vM~e3I??>p=PKmKp3MjrIb}G-12NSW`E=*l*?RSG_ zgQRiyi(Op9_Zn+PRNxC)HJ_WU0a+0uMOcROgCl3Mr!w8`qQaA_`12QFM(H4_C~bBy zzzMpO1*Y$|cD*pUnfq*MsMN^gG&DLla!W}{#z9BO%HP*ChRERF_ek`>`dQ_~vYrUyKdqVrjpynF3pyiSG62mTW`ywD;wP~FNFTQ_1FE?Q^~(L`d?kjX^JH;GnmlW%tnO8nj(D8kj|Um||vajYdnO*hAf>yoqfQ0DpAVSY*p}g1UHy{GR?;w4|K>}E}vcZq8}eWqGZ4yto1{D5U<==vFL0N))9Z|gh1%-j^ zM1X%4-3kI-55rjDg-AiRA}6D9LnR=YzbF_E@Cav3p`@W6h6J0}>$dRA(=P%P^V`p( zc%NtNayF#bC-Kx@W?R-9Yz96Y>+Y518=pYfDR$ipL4ugf3T!+X3wHa|N+pH!wLS*0 zI`|=r&YulrxNvu%{c4hef=)&kZWoMQ>a!kw_b0aL7z_=9N9vJA(R3*77EowZ3QhDq zNym%lCuhQXp!=BDMjMqi$y8J&q51c1gXQCAOd%k|VWkUEJrPfcr>r4yWb-Tm_N;&5 zps*Ns3;qr$w0FbwoS2r@V;#;1{uwh{F_mt2d#Y|*nNF>)8s}~s z6s|i4)I}#7ZjA_j6cVs4H*(Y$&5B1B`E};)mJo8-{rB98;=)H_D1#PY6Dj<}cgBl) zBi|mWnAY8R{GTbiFOMBZPu<48A&+OJ&_V}*Ma>bqb5%js} z<_64rp$f&=npRyg0?W`8N~{qf>9w?V3ORW&YGp=BeG`< zG;TqwifKG(e+6Xff~b-i4GQPWFdeA1v>T%+^X{E{kU+WinUd}a4=HVBj;xNFp7NE# zuV|B!ZISBx>k#uO(b$U3LApw-vMA67^MSBXSlfx?A#;o|lcLc~M7(L_c^I(~kq{6m zc^EbkidgUYf`VPX24Cz^+gEF2J=} zV_}&T6gCHr!@#GO_GAioNZiUQ4QFx)S>3t@Ks`y%($-ZQ%(+`%*tiBS;RvfbiqoHT zM{HbCkazV$?&B)iPDCE!UL`;I483hzUSHs+K1kG!=}36Te|QOY@;|vaeRP;g1wMn$ zh&I2W$}$sF{MXVcp@5cE*N=cy<>c+%z?u08|G(FgHrH~Li@%wA^DB=2fA+NhW!d}9 zRCOCCWHyBFYrTTZ)P8BhBth{@imUljI&br`rTK|4IN|NtUH}+b*Os|j)sG9eo82Ba(WVY^_nW_XMqhL~tf(Y6aq4~-U(+$6LWXcq=VdGI ze`e}=5z2?&HvEr1#)vba(=<39kU+xwawW%Z=j1@Af}c~VSX;F%O-TdT4@1gHa;TZr z;1qxM)JDgV-j~+8QG%Z&%_=8HOjN3%x;fNP8G34j^L;8cwu1c_M)n8MRee9pEuG+j zUZK(XwBHr8vVe>I(%vO6yp`@JY#Dmnb^e{(a*(yZNOt!OoGP!&_GTV$hY`IV#l^0| z;qhFrwZHzz;7YQ$@?f=IHdu=7MQVE*g$46OBak5)#&>vtGcmLt;fcqX&VM?hIWG-} z$JqWUJ>E=EwsNw3iTo6%%uB~{H)Lq4QkeCHh?^3HSyes$lR44rJ`k&25{HG1L1yDI`?5w*tqeMyuK7O1QOY7ywIsjdq3YA6s7on zz(uET=FGk>WzhnA<$0b#_vqdLc2zG0>#T?dfz2kSMHWCBuNgI+&2*%AR}WWt4|f89 zVUiG~l8=lD#;hwCGu?`bDU9jdBII-3_5X#Y1KX3Gb~mNdhN{oWch;v9hRWZm9S(pM zE;EiDle{zJXI7Wf{6ml70H8R?ZZFvjk+SQ-fZedfrN73oqA%18dK$$Q@M95zyvtCF zf@Eqzc>+rXlcnL1C=-L6E)TICgCx~YT(ApS)Jt#3=Sar%T*X)_jKUQc%LFB`BXS%r zLvOmw(-c)xoKOokPD;eRM=I_f5{%Qc^SE)AkH}>e1KV1c*&##Dy7P#3X^QI@;bQ3% z#%~iXT(%%Js=&cm>&pJ5>cpD8yxBC+!B)rl_~JNW7_q|!)vDFq2Cg>Ev*kWFy8Dvy z5S`iomC>2!#P&R5-_*zf-bEjnPLl2oRPm z_;Q~0z=@?a#2zntR76Q~0zml@$?G_BWc2^}!$P02fPvmH$zBX-&+c#VdC7HQ@0M0aY4O37^vwYJ&aK)|fOnNLt+%9YH1KuqLkE2+7;n2-xc z%4NQd*4fjTspV?Dg}njD1Zr?*`ykd!M)Q}86g-k_oiJZclaU=l&NObl&fah!6!IvspPsG+ zD0pJF%1%ik^Oi6CdmNCu5$6b48C0X#&U+mL+MT55?WOD$L7|$)RxPQ(00RT^Y8*r% z#&PHY{{?0y<7r11n;!H*7#&Bm-F3fks^GM#*0!%mT^3%yob8C^c|T{^z|;Fo*XgNV z$zPQ|6D*@Kq&OWd+(gXP9UFMKUoFx<38 za{5Dg-0GN)GVcR@465h4%yKCJIrJ!{6FhWvyi`Z=t~U~Gz1pE=^$(X?kLt^<`p%7J zG}+v)0f0D7X6hU2bhYrWV+wgZx|QC%aF%n)awStI}`wtLc%NBbA@mFfHEV(g`7tbtmAxW@q?h_Fr9&2D>LmdcUJIl<`bCHqjJQr^W z1Lz^H8)zKV^9Mc)HX0P^j{pM52ihOML;P?)f-+B2^T=Wo67`|{@!abrm9k1%wYi7W zIX(x{k_McJ(I~Km%@=KqDdFlT3!2%7>8G3R{jjTq$wR|=)e~8cfw)~vyEcz6&7?HZ z#Sm4KjzNIbypc)7@6(22`O*&5Ofc2*O`wQE$E}t*Uf+4{uZPB^t znM0Fc7S_EP`vj5n=|dqSP;2;aW19OMQ?; zY~jq!7rR+dA{H?=*;9y!&Wnm-NOL0Ai3=t85-V^HZ}wxISKuwFI@wwbMOZ0(*v<)*l0MPZ3t zmq}B?p1IHuruHg?xULmBJkJ&BjBLK=)wA!P*0XMLsV(TAA#JX1%{P*Uq67ALKsU9i zSvzcy=Rb%VeJwUgeramLO+7_>Y}{tiG`MfP8W0kZoT(DhY9gZ^JLI{#JvT;erSmEs zWE2kaZ$A1rqm)~^2i!%HaH|)>v)%@&NLTL}M4irV>)tjBYo5=n>Ym!{x;yfZ?pnsN zn!%@f3m#NIR~QQ-v@f^C^e7)HO0}2eaOQE&&5TH05MLZ#cVczgSf=9=M8}d%`bG6s~cxN5e|d6Qa=nc898OfjbceV*?C2puL0!A_F6=#2ics z12k&bG4%fDwSK$-*$a?jITLEEmRkPO++0SHwO6$jE)HT|pgwa#cjgGa?_PSBCQI#^ z)v;ilz4`L-bvKANCtUp998@3_94(&4^XaMX97XicpzK8fx|#DXj#>$c-0PCvdBOw* z?R;H}yg5hN&~^~V8U<))3N5hDtA-5cjDY^QY3##PZ1Rdu}-UnSr;b76~EldwD@ zdjq%8aG4Ndwd0J30CAAO=SF?%_A5H$H+hn?WC&Ip#MNRYmBc~_1IrxL3oeaL-B!e5 zEclZM=&1Hd*g_hpfc8s*|49Eh1U1kXOBiRU7R>pK`!8cv@kzRf1ay=})1TxZx$~xO{%O-9T~Vs0@0^ZYqvQJm2erb_0(uI&e^8sjh(3(X zIEZvfk911uZF^3o+^VhmH#K+Oz>=YYv@LhutVk_JHkpFHJ_d$J$+W<}ynhGD*es9r zyP&lOGBZEh;m;pGL?y_CjGhNo5MadAh9mv@&+Zq<)AjqMpEk8*Az`R3*#Tsvp;I|y zZVOe?3!rR%p*_;Ie2KpgEPhba+9VL@*8&`N+Xv#WN28#8G4V|6?bUSCeuRFyd%hq! z!IlBGs^cIOFdE1fT1KT*!d{BUif|?Z`B)ye0jx}bNYjm%~QR=O@(sp{JlYK86h)e-yt^;ma5Px z(ZCq9n)^C~ZoqL&ZTl(jS@yi&3)AG-zrl0dM|?nW-V=YdaAS8kaq_;KreQ)kE4!kG zIK}V?#I#omiya$_J$R{-50Qx=5Vq_TbWQL)CMX|3$LL=mlhUEPW^*h@()18c@fCad zGgLU!lv1wA(Gp~h+Z=F;JU%UL}=;JGc$6 z$PU7xz=UiOV8yWwY6y5gr(KX^F;*nxdKSNDn^aeQ!3gJTM(je`z~|{7XHwx}x+xQN zXBspFm)4(0Pt+)rgzJ6blE>-eS5^{lW_HIA`KX?@R)3U#wH9tY;FiJP`;gky-c?Hh z+1bpe(Xer-amwQ;fA@dB*U_Kn!nEi&jYSy}IFftUVANM!dj;-QO9m^FnkJb#^^V}6 z;A(DKf=LQBoIb(WPjKm3SiDI_y&nugqZpRHoI^g$WB_Z#EQqe`6x}4B8iG=YO!RrA zxO=<-BESBRM+BMWtku@P(ztEXUzp)&YfS6xl%uKTw%v;O zOS$9UVNTpxxp-8GO#Iad6|J@*Ph1CGb*dwEO{GiSA`~CR6n{VaGPNg0wfJ0sL*oDh zWejXLkjdrZa3i93?zpa4?nD(GG`Q=c=CFEh0PnVRCi#?PaisE8L9Jk@L>5q}kiEAc z&C%8IU{J}zRl>499>{9DH8M!;*hIS{Ov%~}@5g9P3^f6BDsm&*8LLf*)X?S~L;;K) zU_lV6D~pbcDwkNkTWaj{=OZg_x1&0BomZgI>FP!ekQZoy8a9-xPsyV7Ttt^+l`<9P zKr*3N5yY@}_`O{3>=*q^pO}^X@bLaz!u!2{-OwM7Zup;$Q66$d&@B`9#q~Q>lBc>vUim znaA8=D5r3)&~;l02~}lbhCh&l3m-{-aWZ&^6V8q?t35x|#?kzSAL;o$ecapUJ5?L^ z8+1QwBk?LZHh)5kUn;9uRrGccNV~AHsYPLMkfNz0aYFIC;4=5z`h4)8ALb4A8b0*w)4^@z@1z^kn zvEpU5J(TOpk9T2M{>NMYLg<@=%N>u6pr%e>Q0owC(+xY_0G8F^4%kwRNkwQ*IS!bP zBdfnmC?)HFvm{`*=NbGCg3K6dYPnGj))83JFD$ii$q!5oQ95ussBMlk#iFl+ki(N6 z0@=(5UR@>tPva(MLg#m`ugL`?yMDV3+A9~08g1q`Y{s8umO|}iE)bEJwIDEfRxsq7 zp4)w}5B-OOF)qU>ka2ad9kT(k#8O2GE1aO7XB1!#0X3p|jc%fVO9lwI#;3kBx6v`T zW8#B)4M%D?&hYFaqukTABgEEI!dAmZvv=0sYL=?@qnD+OjO-$57>b4N@#N^bwtq3@ zx)mP&^-td8ErRw;i;zn1^~LZ;wB7LJA(^?fBl?kAh%Ojl7ge|>cv|fqQULH#m;U{` zBkAgGPbdpG<0TjU@(^FyH@hEt7psi%S!yu}L9rsuvHT%95u6_z*7aOL0~-hx?!!HF z5T9SkdUDSa4(a_^NQXh4)!bM<_#f2Mxt7iT4K58{WA6=6+Kwd_>Q1vAoSWCgEGZEn zxqA7Q@_)D^I>ZE#Atj6=Y6cA136_ubnqCoiqPKW9yo+y(20wmhpp(gaC|7os_?@AL znL90W2FPLaq!4=PH36)1@ruoj6a|9LF;dTxtbL8WfRdIzA$Ol9*}l$JyJ-l3-9e<^ z4o~+XDi64RCQo~f6;)u4&WhuiF(&8r2PN{*u|x>?!!B5a#LcGvEcLKoPYY^Vs3+>< z^ZF-tSyMAjLeAR4it}3g=Krn53!CEzFcWXZw($`%32D(gk8`{H{@$o{eqO9be_H?u z#t-YaAM0xb|BxnY;RNsNzUOU%^53gy_p5P|(gz-s_Ra)$Bt;OWu)b6uhR!u>CfyiHw8(iWnUx zf!s2yVeQ&mNzm&XAb{pP-ml}_$!tJ?VgnT@-nHx=I?U)4cD#*UwW^j77ikc|QnDiu z$_5Eo#kd6fK}6?K9hztn;@j^p$Y7)gGh6=?-1SSnxH=u78obhMz;y~gHN?zSW1Jxm zAU+FKOC6_4O9ib%!v;BxeDut;LRQ4EELiP4+01GOcTL};$qD7mxZ@8qSom5cl75!9 zi9hmIDeAs97hWOZzytfU)#VW8?}pY^qd~4AQUa!zwL(HkD@MU#l(jnyk=X$uHFSi> zn8oV{n*{~gQL-6nPsA4k*dE9#7$}_!}c9(u(j%}7)$aX5rXVb+fCZ30BA52NLj`+`RDUZ^;HpkuFpi*z2?5^yHjZyduJ(}nOEx`nlv*-bRWM2*=`j|;r zGZ94#F6|GjF!BOvq(eu5D5N?vLwco{24?k6qOWpuC@dZYbK&frB+K%?NaT+Om;QEM zL(qn~h^XA_UPS7@twyq#)FeO2jDoX2#P}fGTu&1U*%(@BjF+2;>`;ESt8a@{(>nQ!sg_@n3NO*zH(rDBC2LagiTvY;_^dM2%^%)aCCMfpKdxT zi5t-rRJ%!$k$$J}NHN|(C+LBLiqtKmLH`%57{VCOauyycf8!5c#50J-7zG|Q)$3Za zCsO%*V-W%=?>n1ztjRm`tI#wu)YQJ02Z!RGzZ9AB^)ia(9}P;Kd7% zOGP__VmSsu;4q+=;nbPVA?Xn5HGzPY_@37tMwI&cH{@2NoC=v5u8y)BQwpJQZTO($o=eeG11455{ZN3j*3J2p9hTP!J3y|2-&$Ri& zc&RIxJ4thT2S~b7N57lYI8&}%5 zL1F6vV65)!ips^RL*3RF*8-_-+=i5ia#}4rh4XSY-|c1W=}4%98N4k=Y6E0e8n*Z1 zx@K}w63|MFcXe5*?+| zt6ZXKGdNSnKHrq{xI80}hlOIh%z@RQUGSnSz$@f0;mq-0L2n~!1X{GTm{1J0xuXOd zJyzshpQAVQXRhSajq%5t!`+;OReLjVcau`Re){{aM*}C;Nvt!gWM*N2Q~#!aQDq^T zb=k2tYU_g5lBuyax_Mr4*aAtaZy2&VPbh|3H~!H{*|`2@#9M|LF;%h5+;gR_jI`^F z$JqQ`FUg>zQ@AqV%gFFx{p1Q+zFkXXF4xw2C$Sfl$3*RXdM+|mb=EAbQn@CkU2(?% zB^ifDO9ttrNnHqi^cB|UR5I*ke{G{qIbwlc&f!ZI&8A*Q`0z8l?}d&)(0l=a-C4za z*gyWqePBU{8Fuxrzloh6@PBJgES>CZuXMbOwpks2et1Evx|W|+Qt=}WS6|F=xq9CZ z)M&`gS!7Kt(Kk(|Nmz;18WWxPy!?O@y8s{@0pqvBX5Wa=I)?S>F<|^XzTdO{u)pd| z&cfk=fcN#Vn3^dd9V5y$YRM&Km+X_r&2AX+YEG*s`r#ih9WEr#3Uh!MVTLGfHd_Pj5`U-IM4x88Zw$ zz#lX12A>Qy19BN1ihC73b44{$ zOOoDKc}$K$x1{CWkjv#!nTxiqh#hZH<2Ny{{LNm|olarP&wq5s8(mQMYS7PkCmmrI zgZip;gED_Mm_@c1MHz*ylY^gJ<5TU!KT2~Fb5!-BFo5ReHnCvA zf;7A8qL&$(S}|J`11~Vjqbk*#t;tW{u5-_$K2RTpS-uWDB|p}HU8&rmIAx%LHkx8E zzgfAZHoRL;C=e|jM9xz~P8SzEXM;Jt-PJARQeciI^JgG4 zHA0rA!{jYy(H3Ocalt4gmk>X5Kh=+BAHVqDsYr5TL+4K9a|~m4-uG~QM+GCd$$ryq z^2nS9?=eWN37ecC4*gLNFa))zwKtQI0cYl9U-n3L++5*GW7C#mZ)74MYmzbZvBeV3 zg_p<&ss2gp4Zm9M?$^Huv5|b?72a1EYLCqq-abyANHj^P`SX%elqQ04+ImDF0M8^oF187QZll*DZSy1{ecOI z+w0jYH`7roqEU9vxKWmWYly}E;vfo~%V0j-P)5;+V(Pi30?E-uh@mOcf%LI&BJPp+ zO(PTr@ra*A{^iOs>d{f7Uqd}Zd)IMc10&2>GF0T$(DxSU&_Jod6z5r>Yfg|bU+#wp z_)YqxXhQVRbikU87_M01`^b{QAJp%l_HuMVUIOXSc7TsNMSGCn2Ka*;+@@h8-X#1$ zD3FJLrZ%*jp+E)bbzdg?ZVv4FdzE-~`(8e} z*laj7j9$zY3!=dd&i^K(Yg_G-&YmV1njAfE}w78dfz zGUw1;=`XuVVIY7_DMHU&CI_B?oD`4&unu|Q`GlKBsx=$ZnJkyZkLmtGj=HDaN4bR! zbRou}Hyz>L$=}jug*rXMWh0P6Mm6z;n^5wercXM*3E4zK0PZ=id59Fz+#P2U@Par+ z@E(n{8=qdX=L-?i9MH$mNhs#f7zQvS`T;dZVNb;nxdkKzH)XarYSWj(v=zmYlUpF-3;~ z65mX!d#g{wm~kq#(1vU<8@~s~M5F&7CP+$hN{HW3RXvH5U@TIkwy>S3CeGbrh|{ z{%Ddj8rLztXVwhRwxgg_hTe7bB^h(+$42G`H8D9{=7ABX_#!hD&!6CpB?jC$ekE-SnIM~W4TcCh5oA=$!-~;yY^015H>px{4%dQ^%u}*j?t@Rz=xoGo&nZ;>STksSj_Uu^TLz&T5LpJVQT*zIlbjQPgIDSprRF|s@{H|DG$-lq zXtOAspdk)a@&h_^wh&Vi$bkC%8AE6ARlT+gZb>m#_U-!ASkLZ@BERySX8*G_(0`Jh7zyRuPo zayU;z09K*09~Lk_pf!Uj-!l{47stGW3n`X;-- zmd8}5{lC&xFR!S!oA%+QYSv8D20IZt- z{)rACb@`;xbV;>91IGkz{01v6m3nT2)bXn5kheS640^ATJD@!OR)e?3F_Bc~y-WPe zJ~S(%A02}cFnTMIkv{hJE_J6qTqvvJkq1zM3uETgF|V9wz5CNfKZry84YNQtT8~&2 zPw6wc6BRP<9|6u-bQF`V0ODs2H!tSDWSG+HY7eW6T<;>xP{r4BSu-F;TIfW*;~I;jvOqbTB-Bp$FA zD@{{yHIX18${oy`90h?~h6c!mpi8K~QfRhZa3UID&q=x>U#|!Chvu-vOm6)&nQ{yO zD~S0OU3?K(ubE`$oUW?XM9>e0!3QjKU6r3Hq;1Ao!IA3`Op%l)0vLlV!(#U4n*pn4 z?RK?lDjF5XUz{G>jYt{t7H7iE@jVyH$3_w6O-kbI9QTrK@^3-2&|Oz(dN9B%*D9Y7 zVwx4!RSq8upEuW>2&n4n+PcsyR^VH(wx`#sgTG!`37QP1XZ?GMV&EGKS^)jBEz` zxOULT3XfS?)ZcxxT@&f)itH67krkWb_F35Q1lK1>WRqFHbzB|Z^(1`W z6ujOz{L4`o-Er8*{ZQW|{EzF0EAmD$!-}N1`HPp0+M%rjEo`)eJl_8Ha=vIiSiq5E zGHo|>w3)(vFS0+n-d%&o)woYN-LRZ^R{wTPnv-LtoQ|8!Iyn<4L8>>-x z1BWC|1U8%SVI!Lvp%JviOh7B^vh0vUb9sw%v#i$9PDP80xJcVBwM;?h#PC3!nf@xG zV7Xixm_oJ199c!q52DM{ZqVDu#M@sBNW_!Y(JWQFN>bY0s0ciF5!5cnzfw>s7~ZDd z8`}dXwmk@mN>~*SlIvC{2{&X)V8Da1<9C49DRv>^NNKWeCXg>_ zhRHDBjMeyhTG%36No0vbuC4t6mHImer-rn%z0|DK6qtBOcq zsU4+JiTEPwm{y8Jt6t?rZ5C9YtKh2zfGEq--o`_I3MeFk7jDmUxF)>8(xI z;bcExw))k%hD85dGg)7{R!2gxHHcVB7^~vxD?Lpq8;)x%x*Jk@y5oH-*SYZVvmxTx zhW<0nC0wCF^?HHQzEYXdf{(pS*AM0QoJoS!&Wq3hZu=TnsL8O&Vr;c$J?;ea24 zEapZ0$fVqZD>>%AF?Wa%wqa#j0Gu$y-x3o8eRJCb2V|)U_Lzi_ik55$Ndiy#zWO z7OZmG5ZT2J;FQblUByWS! z%$+7732HvBeIqnu-9Q!*K<=o+#1^BMwcubs5+flKNWdDQ*f$K=h7()5l6H-HA@BY> zyEjmv4fls9$K4`DATgZ$YBL##3OVz7lTKG$uH+A&9)f7q0`AV4{GoUy{4xip&rUGP8>phO8hO!d70jCWt%FTy@#Y#QjPL}& zya{>wbf%&LzC=P45Qny?x9W6GIu(|Fdq0c?_`tpp!Fi~_Im*Rox~`;bc#FXz9;^Ra zpVfk`^dNF>?tGsz-nlR>+p@ihmXcgqk)|fJmsZk7LHO@eJPrlju%pDPk}P2J6n*1* zWuN23x|nshA4VNzZ^J`8#HQ6>V75?O;DG3j+*??z{v)$$u70vtHd*v3OhVd1J5jP) zJQMXCryxgZdsQ=0Jlj6S)mb;wFJ~}@=_>sckE7XslK%>8LvZAv~JW=!=I|oIvR7kv8Q`Gsr=f{>NxPc7?FC#cawX|oo{Dw#5ucKzcAE`0^O`JosXk@%13P2>IqE|(yi;%2uL65T>(!WE) z$5_G(RR?=xzgOUyQb`)qhRwd!LaUuz&2fztP_f2!0JXz+83^^o8AqpwrIi!z@5Nbj zadL+;#6hQBcdZUI?8)+`%e*scGgDIG6c2>%xw1&*kSvfFRz-UL@SP>E_(oTing6x& zc%9I34;X5+NAcpOwe!W}pyAGSyHkWip2A9C*hF}=c8wvWsaYfNmH=g|wa1yZEAx=% zq!WsS5?_0TP=OnZxX99G+wtY*X_Gm(Et7IOaS6sVK%*j=v79D86Z(`>S<8k$VR^&L zlNfXx&GGj;4GH(@LORqOFT4_mLwb)hIzssq8q!}vK(s2F0oKVwFQO+Ej_h8)&D4q3 zy2wg+B{V4OO&r(P4a}9#bu*W88)F$EWx|ORPyghNL?zdKlL>|$sIE}sJ~b8HLrnsuhxzjUlfbnKrUxXZ8##&PfK zBa)y#s1!F8#riYv1g*D^8-LMid|H^9>9BmbPD%=*tb_t&c4lA;be&mHSRN?#SSb;} z%WSgom)ZzIa+8|bN^bkN{lNXOcX_N>I6_{lH6Bxv6i8ZUl{i^&`5 zbmM(+VZ!V~c|b_L?@wzgAp>#v6+*(K!>!i!L3b&Ckz`5 zsfEF<(b+<|B734jmA(Z|w39L>VJa%qgf11zC`*M%27p1{ST1O5w;Z$qQRwi&r=D24 zXX79o0*-MEG(wyIiupIpP{G$U;Tx(UH4bpMJ^mEZ*v2Z+qhvEsAza@ZtNv*KPhr_v z?GWACz4vHK?QV`*MG+vwqd5oCfE{PuEjY}*&N?Z^F($f~b$SD$NcrFcS25_+m6ZP{ z%w=zDp|cKI-g@P=R%QR_yR}y9l_~+`B>}fq+4V>scaTQzLidy@?rorzYQ*o$ateD3 zIkq5|NgBC6+`kMQ@(#H|A7=Kuz4WeGL!|w}c7tzZ0NLPdX4MibE@$}}z={|b8|P3B zs-aeDS_nAkEW!#E zdHCl7oI1oY{V-qsQ-0WZ(ICr~lKn#F_C+D+-8>~@+P30S10`pT%pvsf9>h=KbZb|s zcRPs(l$Jjx#BEKvaD9oV*f_q%j(9=T5R0=i%K_CdT_4sf#qzwSyETCBpL_Cj`0i`l zgF>^5*}K{T$KT`1GcF?=dUBnYi67Mt!a2e^X4zY^2YIq;4M6=qxC{eU3zG_yB#L@_ zEnC9=Ep&8B0BiQ_I&_aq*^Fk=67|j1yFz6&iup|uq6-`_UF!`m4J6^M-kDt zD{PJz!cQly%;84a{#7|)%QwIXmCb66pB9LOBFFITjV=0Oy`Dqta<9&iVc^p4jhs4I zzO?RErv~UcOu^uSm%|8|O-aU;;K(~LlPMG}IJL=dqxH!bDXe@Gt#|KdN*?0Ni&U^Cw4`Z34NMKl=I-rs;eLYtbI zx|+QtAv~@3^j&ZUsrmW=CyIryyT?p{Hgux=*hR^I!Gcgm$(iJe1FqdYXaEVAE|3b^ zhNl$g;o}k2&gX^QH3w-xRe=g7a&@H>9Ac9QmDs9K70)Ju8kE45I-1_FW39%G{w25Z zwrk?>Q)%Ih`wArSLp7Pc!>8lYpj*p}JvJdabWLS3!#2AB2?f31wZkIKt8jKT6o($U zA*#hcPWGybE_*7KVTch8?J_@=ow3I*iZc7_E(y^3#lf6JZDMyIBq-fdAwL9-Opzrz z)4(+@>mExbf>ql#7qdAs)EdIEEp?BBeF#wWcMQi4w5v|Xmue=VsolE3skbA;tfN9x zJ~soN$wYoZRK+<8*Z=)y>!n4+xlFgzLxPy;#wL5 zdC&FnV3s-_vtq{E-LvTr3vQE@kDRrmaq}rX6GZ(w$c00qmTic=z;e#aVS&a1^TYZq zLx_OtZ6uS?Pgw8@slZfNU{!4Gevu0X@@)ZY^3m?{LHkF1SSG$RlN{u|Nz0y`m~AXl zYagMC;W7N7-&7H(()z&ioQ|(tLKQR+QM34ov|Hfovan`6%hg~xH@0Ls=}74ZVkZ8y z9HhZ-rK+q)!eK8F>uwfIO|U8KvZ}3O02)cBRj45(e)MuJ59N)zf9M}@!OiZBW~64{ zcrQ)s;Mp1W;(Pn3NXoZmc|Z3_wpG3)b~Wo6^QsL^o($%DmVs+Gs6HQ83M{5;>yUos zZLvD06VhWz=@UA`XycXmI$ZQD>Bcvj4dGBy#rn^0&HC$_D2Me9#|LL|KZ+9V`hX@G zK|D5NGEqApksrR6_10X(i0o9hL9OLK>QcTgaq-#9c3I}0U53W66TG}Uc zI76eOa*6I`?=)ucBVtTP)^;}8%EP6!E8hk*d-+@fr-bpz2p{m0UXG)JW2QFaESy_z z%_iLcv7Twn=&bm}1ll!iV2PlYq0%EA%Y(+|{?>h!63Mlx&d$M{+o?8_VYYfN6e?HuTx3dQ(~bJWevG1?wF;qm`?@jA(D$)r8_{Rj)z>ui0o5 zBW;sW?muZ>F(wD}8R1MV(TNTuK}oZ!hBiY2Ms?=*JeATJD9GinY#vSUXOM@>4`0c@ z`ogE~>^I{ak>E2EWTFMVv6AU5LAL8>d=AtfG;_Fk%QPYDf|oZ`{--UriY<^Yqh>)l zUAXiHd{ip&y?Y9q5ruJGF@jCi^Hz6~J5Bym zd`-2)W-YDi?Le8<@25J8lU$#x<~&T;=I0G*xwTG385LcIfrg>0TIcPfn;j2lb!FDr z+>oqWI=!02-klkF#6I&|5vE!BphnS2r}{f99crD*NJ&dlWV3`q-mNc3+!E6S8a_{0 za8Ob@{4`)N%`q`w$>oAE3tkJHn~!nN;pbu5XK}dem@-yzeo}ZpKZOWa8Jqe%3H@O@Gs!gdZJ*K(S zYtN1*NQR~zCmeY3H!m>yLdnV=1&B{NkW@SPNcT7m1=4$&eoUZMagx6lSbow;!U%qH)#F{f1Kf zS59-yIqxzJmi_91?=`5|^+rY2S{fTlud;nw$~7JhHCT$ zR3Dl@@tWoRRG+MX6J3a8fbI7hOnz05hh0H6OhKmJKt%oNh5JesBUwi?%J15xusEnEH#g^;2s_7<1GlO^44R zxs#5KjX5z@Q1y*D-=Nk(QPbuarKXXmt*YH&=_Kzj80$3o8zSDAPES7spDRF9JUrE{ zrav&z!|&!T%thTWF&J!i4O>?-Hmk(=S*YC0HR~A`G_0F!W)t%C+!x%zzMj1h2KwJN zm52;X@?!jsBpFM7e6WDn6bW!T=d_3t*ZjSz_M`I8zc5ZZGDM@NH$LcaW>_#=zTtpP z!7H`_{TBoOqN^T!q5RR4KQL|u@5ucDm84!1Rci9JJQf`w$wW18U|hv9BPLoU^3=x} z(X6}}95Kmrx_vO%T$J$@mS=4IQv=kX(Ufca=1WHR2bUtu)N89LLmi2co5li)JPd6yNcd!@Ef2a+4z4R_u z2E^HHsE|A>RITtp>1!8%FW%<|U&W}xUdsdxQ&(MInPd&&`JmO*`2EmGD#nm6r;w_z z_!Khfxj)o?K3?&JhV`+Z166{(p%xSqI&lGg_Q{xv<~e!IjF-uxNQb zi@xY4b8Q{>tJmdETfL68{T4sgHap#YcE-ufhcmK)q5cZ=o%4n{SBuN6_26#`67#&k z(Q|nZtHWp~bQyp8!H@q42o>rr*#E3X%~r2WVeDPf#_FjQ{!0Q20UzFdEbd?XkXD)% zI(3hB1N%!|CAxrHV|Mda)$-CN?!(^gx*oGZpfsvG6$ApF?t{P`5J< ztwwz-6S?Orj(G^zTYC7|>z%vv*+Pt}il^)A$|B6W?oPgARyg8q8KtR~ zJ0bRQt+_B^veDN5-bLQx-v`O81$^$xORcbnWi4BgX3hBMlWu+{(K_Gh(&T?@=BN{P zb*xXmL+)l%r}Vt-^x{D{Jg=Z7wcjO8nzAcWx#PG@ZlR%t&rLaAxziY#t9;Q=+Y^EP2;nZtD`X!i!%Ekuz6DvN`vBIqSC8Ap1m%PS6KkXIACFsbt)(uN?|DMHSYX(&dy8L5} zO$#|G8Vi}X^P|+uJ_p~->wd$&k+dMjMp1@%E+1vr?-=iRi{^=LdaNTAhX-@bpq#ML zz_e6j`iY!yYM)8Jn|bbZoyRR@{&`G+C`sk47L%Mr4Usj@p1!CM%T-m{&JdAwQ}O>CD$gy2eGMG=nL-lY0#Ej#23ca{XBm4Sx)lTOupoc^~QZuCaZn;9)sMqh4n6 z3GS{wf0KFI-u*8gt5MIlYjc|^y56e8OlxN)URmV$N+0af!6(%-o-^UmRcbOEGe1mD zhpfI`;__qhy{p?vEm?XlnA5DGFe$_G~^vS>ZZ^cHw@*e)^7YdE$DaBMgJpg zhMXZ^h&kOa=9gX1JHb9i293z~v-;()MK{y`AiNJv>ApdJGRv=b=gGH($4m75Go zG>n6?H+5}Upca`WXdVupXW4PNgDQ!*oV0`;91R!uaPvgj?qzZ@ z)0Xy-Kp@#5pg&I_Z(q!yw=k|LBVp?ZN1=BQ(0C3iPfZGf1Kmq;u_GX4TufF14YzSc z?2d^Jm`KEfsC4(?51tE{FI?<|ga_Kk)d}gaJGXxSbALUEtrI+MEwO!<;JeeD_}t0= z1`mybBR%ZhP?zEVt&Ni!g|xechfL-^b{&~dp_5?d{# zcaQE)&yBT@q_4!#`>1mb&a3)%`s+zsU* z{{Jk#lV2pDJzxSd!I1OdXfDUMG@=c3iADC%*`Y@W?5SpOL%6pXActe25bkb!?TDz5 zD^XftWr%>laBs2i-2Xu!pP*e4;@;q^BLW4|%C74yvt_=g8w}WK@I)J~W~Z`?w$%lN z*iBvyNo1r4^Vmb6d28&V$?P5*OJJEbAJFs|@MEjd*+ttb3QsJy9O-C?JkXvJXuJly zXj`SEiD|*9XR|_pRt-`K?zp8I@1kv$l_jRtI6++3fW`*aKdxqGzKgb19FmyU3{$JK z0-F=VhOZ@A@1kv$TqCCGomULk25XHQ>;T-@r0jRmwu%iA)7lE(+opniDFXHY*i}2O z3fC=-SfL7H)Sur4``~{s+}(N03j+Du;u_(KutlSsY{hNisI824*$zM5hE^C;90Nm! z1Pd28-8S#Eb~&gCy^FNWMdM&XqrvhxycOerUrzb&h;7@$J*o-8pD{ET3jjU`iA@9t zvIP5cU)_+#K64{Z9?7YmlL-T&_98@ z7u;ckbQn)e$3M0S#f@J3!wFz|m_dTZ9RP(SVj|wbO$f5^UhGi;;c#)>^=i2LB1DZ6JG&03i0V0{>mMZQwdH3Gw&b^tC9!3nU0c7X0}I Ms(Q<^gQN}lA0J$xv;Y7A literal 0 HcmV?d00001 From ea4dbef93cf288be928736d327303d2158321f05 Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Fri, 29 Aug 2025 15:04:27 -0700 Subject: [PATCH 10/11] Add prebuild script to run resources before build --- packages/vscode/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vscode/package.json b/packages/vscode/package.json index 63a5d8af..199c1acc 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -155,6 +155,7 @@ "test": "vscode-test-web --browserType=chromium --extensionDevelopmentPath=. --extensionTestsPath=dist/web/test/suite/extensionTests.js", "pretest": "npm run compile-web", "vscode:prepublish": "npm run package-web", + "prebuild": "npm run resources", "build": "npm run resources && npm run compile-web", "build:08": "npm run build", "compile-web": "npm run check-types && npm run lint && npm run resources && node esbuild.js", From bd0741aba60da12422e76cef31c55956999dc8bd Mon Sep 17 00:00:00 2001 From: Dan Marshall Date: Fri, 29 Aug 2025 15:04:36 -0700 Subject: [PATCH 11/11] Update README.md to enhance description and clarify example folder creation --- packages/vscode/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/vscode/README.md b/packages/vscode/README.md index d1df8ba7..8fabff67 100644 --- a/packages/vscode/README.md +++ b/packages/vscode/README.md @@ -2,13 +2,15 @@ **Declarative, interactive data documents** -Chartifact is a low-code document format for creating interactive, data-driven pages such as reports, dashboards, and presentations. It travels like a document and works like an app. Easily editable and remixable, it’s a file type for an AI-native world. +Chartifact is a low-code document format for creating interactive, data-driven pages such as reports, dashboards, and presentations. It travels like a document and works like an app. Designed for use with your LLM to produce a shareable artifact of your analytic conversations. ## Features - This extension works with two file formats: `*.idoc.md` and `*.idoc.json`. +### Unzip samples +- **Explorer View**: Right-click on a folder and select "NewCreate Chartifact Examples Folder". This will create a folder of examples that you and your agent can use for refernce when creating your own document. + ### Create Documents - **Explorer View**: Right-click on a folder and select "New Chartifact Interactive Document (JSON)" or "New Chartifact Interactive Document (Markdown)". @@ -16,9 +18,6 @@ This extension works with two file formats: `*.idoc.md` and `*.idoc.json`. - **Explorer View**: Right-click on a `*.idoc.md` or `*.idoc.json` file and select "Preview Chartifact Interactive Document". - **Editor Title Bar**: Open a document and select "Preview Chartifact Interactive Document (Split View)" for side-by-side editing and previewing. -### Edit Documents -- **Explorer View**: Right-click on a `*.idoc.md` or `*.idoc.json` file and select "Edit Chartifact Interactive Document". - ### Convert Documents - **Explorer View**: Convert between formats: - "Convert to HTML" for sharing standalone files.