From a43553397a1b75de0bb919fb6b9e87b2424316ef Mon Sep 17 00:00:00 2001
From: huangruiteng
Date: Fri, 6 Nov 2026 16:41:46 +0800
Subject: [PATCH 1/3] feat(workspace): surface report materials for review on
Home
Signed-off-by: huangruiteng
---
.../smoke/attention-details-smoke.ts | 5 +
.../dashboard/src/data/report-reviews.ts | 22 ++
.../presentation/dashboard/src/data/status.ts | 1 +
.../personal-workspace/attention-actions.tsx | 9 +-
.../personal-workspace/attention-details.ts | 4 +
.../capability-localization.ts | 2 +
.../goal-report-reviews.tsx | 167 +++++++++++++
.../personal-workspace/manager-brief.tsx | 19 +-
.../personal-workspace-model.ts | 2 +-
.../personal-workspace-page.tsx | 45 +++-
.../personal-workspace/report-reviews.css | 22 ++
.../dashboard/src/views/dashboard-page.tsx | 6 +-
docs/guides/README.md | 1 +
docs/guides/assets/review-materials/home.png | Bin 0 -> 94711 bytes
.../assets/review-materials/reader-narrow.png | Bin 0 -> 59146 bytes
.../guides/assets/review-materials/reader.png | Bin 0 -> 97049 bytes
docs/guides/review-materials.md | 94 ++++++++
.../personal-workspace-browser/fixture.mjs | 4 +
loopx/capabilities/configuration_ui.py | 2 +
.../native_chat/steward_managed_mode.py | 31 ++-
.../native_chat/steward_reports.py | 7 +
loopx/capabilities/periodic_report/README.md | 6 +
loopx/capabilities/periodic_report/cli.py | 17 +-
.../periodic_report/goal_configuration.py | 8 +-
.../periodic_report/machine_defaults.py | 10 +
loopx/capabilities/periodic_report/review.py | 142 +++++++++++
loopx/chat/completed_todos.py | 19 +-
loopx/chat/goal_configuration_api.py | 2 +-
loopx/chat/machine_configuration_api.py | 5 +
loopx/chat_server.py | 6 +-
.../control_plane/effect_runtime_handlers.ts | 2 +
.../effect_runtime_snapshot_methods.json | 2 +
.../presentation/report_review.ts | 43 ++++
.../presentation/report_review_binding.ts | 8 +
loopx/control_plane/todos/authoring_scope.ts | 6 +-
.../control_plane/work_items/project_asset.py | 1 +
loopx/presentation/report_reviews_api.py | 33 +++
.../test_capability_configuration_ui.py | 1 +
.../test_periodic_report_review.py | 228 ++++++++++++++++++
tests/control_plane_ts/report_review.test.ts | 36 +++
.../todo_authoring_scope.test.ts | 11 +
tests/test_native_steward_reports.py | 53 +++-
42 files changed, 1042 insertions(+), 40 deletions(-)
create mode 100644 apps/presentation/dashboard/src/data/report-reviews.ts
create mode 100644 apps/presentation/dashboard/src/features/personal-workspace/goal-report-reviews.tsx
create mode 100644 apps/presentation/dashboard/src/features/personal-workspace/report-reviews.css
create mode 100644 docs/guides/assets/review-materials/home.png
create mode 100644 docs/guides/assets/review-materials/reader-narrow.png
create mode 100644 docs/guides/assets/review-materials/reader.png
create mode 100644 docs/guides/review-materials.md
create mode 100644 loopx/capabilities/periodic_report/review.py
create mode 100644 loopx/control_plane/presentation/report_review.ts
create mode 100644 loopx/control_plane/presentation/report_review_binding.ts
create mode 100644 loopx/presentation/report_reviews_api.py
create mode 100644 tests/capabilities/test_periodic_report_review.py
create mode 100644 tests/control_plane_ts/report_review.test.ts
diff --git a/apps/presentation/dashboard/smoke/attention-details-smoke.ts b/apps/presentation/dashboard/smoke/attention-details-smoke.ts
index 070ecab774..6ac93d6ae4 100644
--- a/apps/presentation/dashboard/smoke/attention-details-smoke.ts
+++ b/apps/presentation/dashboard/smoke/attention-details-smoke.ts
@@ -39,6 +39,11 @@ for (const task_class of ["user_action", undefined, "unknown_future_class"]) {
const action = { ...row, details: attentionDetails({ ...source, task_class: "user_action" }) };
const boundAction = attentionDetails(todoItemSchema.parse({ ...source, task_class: "user_action", bound_agent: "codex-delivery" }));
assert(boundAction.boundAgent === "codex-delivery", "canonical User action actor survives schema and projection");
+const reviewSource = {...source, role: "user", task_class: "user_action", action_kind: "review_periodic_report",
+ capability_binding_ref: `periodic-report-review:r${"a".repeat(64)}`};
+assert(attentionDetails(todoItemSchema.parse(reviewSource)).reportReview, "native report edition survives the production schema");
+for (const changed of [{role: "agent"}, {task_class: "user_gate"}, {capability_binding_ref: "periodic-report-review:r../other"}])
+ assert(!attentionDetails(todoItemSchema.parse({...reviewSource, ...changed})).reportReview, "prose or another role cannot select report review");
assert(!canHandleUserAction({ ...row, details: attentionDetails(source) }), "a User gate is decided, not marked done");
const { todo_id: _omitted, ...idless } = source;
assert(!canHandleUserAction({ ...action, details: attentionDetails({ ...idless, task_class: "user_action" }) }), "missing todo_id cannot be written");
diff --git a/apps/presentation/dashboard/src/data/report-reviews.ts b/apps/presentation/dashboard/src/data/report-reviews.ts
new file mode 100644
index 0000000000..b321a80435
--- /dev/null
+++ b/apps/presentation/dashboard/src/data/report-reviews.ts
@@ -0,0 +1,22 @@
+import {requestJson} from "./chat";
+import {z} from "zod";
+
+const row = z.object({todo_id: z.string(), bundle_sha256: z.string().regex(/^[a-f0-9]{64}$/),
+ title: z.string(), status: z.string(), created_by: z.string().nullable(), bound_agent: z.string().nullable(),
+ created_at: z.string().nullable(), updated_at: z.string().nullable(), completed_at: z.string().nullable(),
+ superseded_by: z.string().nullable()});
+export type ReportReviewRow = z.infer;
+const page = z.object({ok: z.literal(true), available: z.boolean().default(true),
+ reason_code: z.string().optional(), items: z.array(row), total: z.number().int().nonnegative(), next_cursor: z.string().nullable()});
+const read = z.object({ok: z.literal(true), goal_id: z.string(), review: row,
+ source_session_id: z.string().regex(/^[a-f0-9]{32}$/).nullable(),
+ todo: z.record(z.string(), z.unknown()), document: z.object({title: z.string(), generated_at: z.string()}).passthrough(),
+ generation_id: z.string(), artifacts: z.array(z.object({renderer_id: z.string(), content: z.string(), content_digest: z.string()}))});
+export type ReportReviewRead = z.infer;
+export async function fetchReportReviews(goalId: string, cursor?: string) {
+ const query = new URLSearchParams({goal_id: goalId}); if (cursor) query.set("cursor", cursor);
+ return page.parse(await requestJson(`/api/chat/report-reviews?${query}`));
+}
+export async function readReportReview(goalId: string, todoId: string) {
+ return read.parse(await requestJson(`/api/chat/report-reviews/${encodeURIComponent(todoId)}?${new URLSearchParams({goal_id: goalId})}`));
+}
diff --git a/apps/presentation/dashboard/src/data/status.ts b/apps/presentation/dashboard/src/data/status.ts
index 457e83f617..6efa49ca87 100644
--- a/apps/presentation/dashboard/src/data/status.ts
+++ b/apps/presentation/dashboard/src/data/status.ts
@@ -88,6 +88,7 @@ export const todoItemSchema = z.object({
watch_only: z.union([z.boolean(), z.string()]).optional().nullable(),
task_domain: z.string().optional().nullable(),
action_kind: z.string().optional().nullable(),
+ capability_binding_ref: z.string().optional().nullable(),
// Canonical author provenance, distinct from the Agent authorized to reply.
created_by: z.string().optional().nullable(),
claimed_by: z.string().optional().nullable(),
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/attention-actions.tsx b/apps/presentation/dashboard/src/features/personal-workspace/attention-actions.tsx
index 6b2dd06766..599817ceaa 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/attention-actions.tsx
+++ b/apps/presentation/dashboard/src/features/personal-workspace/attention-actions.tsx
@@ -15,7 +15,8 @@ export function AttentionActions({ item, readOnly, callbacks, fallbackAgentId }:
callbacks: PersonalWorkspaceCallbacks;
fallbackAgentId: string;
}) {
- const { t } = useWorkspaceI18n();
+ const { t, locale } = useWorkspaceI18n();
+ const reportReview = item.details?.reportReview === true;
const [preview, setPreview] = useState({ status: "idle" });
const scope = JSON.stringify([item.sourceId ?? "", item.goalId, item.todoId]);
const pendingRequest = useRef<{scope: string; token: object | null}>({scope, token: null});
@@ -83,7 +84,7 @@ export function AttentionActions({ item, readOnly, callbacks, fallbackAgentId }:
? {t("drawer.attentionPreviewFailed", { error: preview.message })}
: pending ? {t("drawer.attentionPreparing")}
: null;
const reply = callbacks.onReplyToAttention
- ? callbacks.onReplyToAttention?.(item, "reply")} type="button"> {t("drawer.attentionReply")}
+ ? callbacks.onReplyToAttention?.(item, "reply")} type="button"> {reportReview ? (locale === "zh-CN" ? "提出反馈" : "Give feedback") : t("drawer.attentionReply")}
: null;
const explain = (label: string) => callbacks.onExplainDecision
? void callbacks.onExplainDecision?.(item)} type="button"> {label}
@@ -110,9 +111,9 @@ export function AttentionActions({ item, readOnly, callbacks, fallbackAgentId }:
}
if (canHandleUserAction(item)) {
return <>
- {t(item.details?.unblocksTodoId ? "drawer.userActionUnblocks" : "drawer.userActionReminder")}
+ {!reportReview ? {t(item.details?.unblocksTodoId ? "drawer.userActionUnblocks" : "drawer.userActionReminder")}
: null}
- previewUserAction(item, "complete")} type="button"> {t("drawer.userActionComplete")}
+ previewUserAction(item, "complete")} type="button"> {reportReview ? (locale === "zh-CN" ? "验收这份材料" : "Accept this material") : t("drawer.userActionComplete")}
{reply}
{feedback}
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/attention-details.ts b/apps/presentation/dashboard/src/features/personal-workspace/attention-details.ts
index a71ea84da3..146ba5e09f 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/attention-details.ts
+++ b/apps/presentation/dashboard/src/features/personal-workspace/attention-details.ts
@@ -1,5 +1,6 @@
import type { WorkspaceAttention } from "./personal-workspace-model";
import { todoRequestContent } from "../../../../../../loopx/control_plane/presentation/todo_request_content.js";
+import {reportReviewDigest} from "../../../../../../loopx/control_plane/presentation/report_review_binding.js";
/** A display of existing Todo facts, never a gate or dependency evaluator. */
export type AttentionDetails = {
@@ -18,6 +19,8 @@ export type AttentionDetails = {
unblocksTodoId: string | null;
decisionScope: { kind: string; granularity: string; scopeKey: string } | null;
supersededBy: string | null;
+ reportReview?: boolean;
+ reportSessionId?: string;
};
const text = (value: unknown): string | null => typeof value === "string" && value.trim() ? value.trim() : null;
@@ -47,6 +50,7 @@ export function attentionDetails(todo: Record): AttentionDetail
unblocksTodoId: text(todo.unblocks_todo_id),
decisionScope: kind && granularity && scopeKey ? { kind, granularity, scopeKey } : null,
supersededBy,
+ ...(reportReviewDigest(todo) ? {reportReview: true} : {}),
};
}
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
index 3ceeed9f20..c344ded2c2 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
+++ b/apps/presentation/dashboard/src/features/personal-workspace/capability-localization.ts
@@ -178,6 +178,7 @@ const fieldCopy: Record = {
composition_mode: { label: "Composition policy", description: "Replan requires an exact experiment successor or typed result; it grants no execution authority.", options: {disabled: "Off", explicit_only: "Explicit candidates"} },
composition_scope_id: { label: "Research coverage scope", description: "An opaque scope id required by the explicit-only composition policy." },
profile_preset: { label: "Report profile", description: "Capability-owned report profile, such as weekly-progress." },
+ review_required: { label: "Request review when ready", description: "For reports returned to this Goal's original conversation. Each edition stays on Home until you handle its review." },
wait_for_ci: { label: "Wait for CI", description: "Disable to use local validation without querying or waiting for CI. Merge authority is unchanged." },
review_order: { label: "Review direction", description: "Forward visits other authors first and oldest first. Reverse inverts the whole actionable queue." },
agent_orders: { label: "Agent review directions", description: "Use the Goal default or choose a direction for each registered Agent." },
@@ -214,6 +215,7 @@ const fieldCopy: Record = {
composition_mode: { label: "组合策略", description: "重新规划需要精确的实验后继或类型化结果;它不授予执行权限。", options: {disabled: "关闭", explicit_only: "仅显式候选"} },
composition_scope_id: { label: "研究覆盖范围", description: "显式组合策略要求填写不含私有内容的范围标识。" },
profile_preset: { label: "报告 Profile", description: "由该能力管理的报告 profile,例如 weekly-progress。" },
+ review_required: { label: "材料就绪后请求验收", description: "适用于回到本 Goal 原工作对话的报告。每个版本独立提醒,处理审阅后从首页移除。" },
wait_for_ci: { label: "等待 CI", description: "关闭后使用本地验证,不查询或等待 CI;不改变合并权限。" },
review_order: { label: "审阅方向", description: "正向先审其他作者,同层先审较早就绪的 PR;反向将整个可执行队列倒序。" },
agent_orders: { label: "Agent 审阅方向", description: "每个注册 Agent 可继承 Goal,或单独选择正向、反向。" },
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/goal-report-reviews.tsx b/apps/presentation/dashboard/src/features/personal-workspace/goal-report-reviews.tsx
new file mode 100644
index 0000000000..0be61949ba
--- /dev/null
+++ b/apps/presentation/dashboard/src/features/personal-workspace/goal-report-reviews.tsx
@@ -0,0 +1,167 @@
+import {useEffect, useMemo, useRef, useState} from "react";
+import {RefreshCw} from "lucide-react";
+import {fetchReportReviews, readReportReview, type ReportReviewRead, type ReportReviewRow} from "../../data/report-reviews";
+import type {PersonalWorkspaceCallbacks, WorkspaceAttention} from "./personal-workspace-model";
+import {attentionDetails} from "./attention-details";
+import {AttentionActions} from "./attention-actions";
+import {ContextHelp} from "./context-help";
+import {MarkdownText} from "./markdown";
+import {ResultCatalogReturn, ResultCatalogRow, useResultCatalogFocus} from "./result-catalog";
+import "./report-reviews.css";
+
+/** Generated HTML gets no scripts, forms, same-origin access or host functions.
+ * Review controls stay in the trusted host; the exact Markdown remains readable. */
+function inertReportHtml(content: string, zh: boolean): string {
+ const document = new DOMParser().parseFromString(content, "text/html");
+ // The built-in standalone renderer has script-driven search/copy/print.
+ // Its static embedded reading view keeps the content and navigation, without
+ // presenting controls that cannot run in the scriptless frame.
+ document.querySelectorAll("script, .tools, [data-report-search]").forEach(node => node.remove());
+ for (const anchor of document.querySelectorAll("a[href]")) {
+ const href = anchor.getAttribute("href")!;
+ if (href.startsWith("#")) anchor.setAttribute("href", `about:srcdoc${href}`);
+ else {
+ anchor.removeAttribute("href");
+ anchor.setAttribute("aria-disabled", "true");
+ anchor.setAttribute("title", document.documentElement.lang.startsWith("zh") ? "请在文字版打开来源链接" : "Open source links in text view");
+ }
+ }
+ // The host already supplies the exact title and edition. Keep every summary,
+ // period, highlight and source inside the reading view without a second hero.
+ document.querySelector(".masthead h1")?.remove();
+ const metadata = document.querySelector(".supporting-body");
+ // Counts and the reporting window remain available with the other report
+ // facts. The reading viewport starts with editorial summaries and content.
+ for (const node of document.querySelectorAll(".masthead .eyebrow, .masthead .period, .report-facts.fallback")) {
+ if (metadata) metadata.append(node);
+ }
+ const mast = document.querySelector(".masthead");
+ if (mast && !mast.textContent?.trim()) mast.remove();
+ const rail = document.querySelector(".rail");
+ if (rail) {
+ const index = document.createElement("details");
+ index.className = "embedded-index";
+ const summary = document.createElement("summary");
+ summary.textContent = zh ? "目录" : "Contents";
+ index.append(summary);
+ const nav = rail.querySelector("nav");
+ if (nav) index.append(nav);
+ rail.replaceWith(index);
+ }
+ const embedded = document.createElement("style");
+ embedded.textContent = ".shell{width:100%;max-width:none;margin:0;padding:24px;box-sizing:border-box}.masthead{padding:0 0 16px;border-top:0}.mast-grid{gap:16px}.layout{grid-template-columns:minmax(0,1fr);margin-top:0;gap:16px}.masthead+.layout{margin-top:16px}.embedded-index summary{cursor:pointer;min-height:32px}.section-heading h2{font-size:24px}.report-row{padding:16px 0}.report-facts.fallback{grid-template-columns:repeat(3,minmax(0,1fr))}.report-facts.fallback .fact{min-width:0}a[aria-disabled=true]{color:inherit;text-decoration:none;cursor:help}@media(max-width:640px){.shell{padding:16px}}";
+ document.head.append(embedded);
+ const policy = document.createElement("meta");
+ policy.httpEquiv = "Content-Security-Policy";
+ policy.content = "default-src 'none'; style-src 'unsafe-inline'; img-src data:; form-action 'none'; base-uri 'none'";
+ document.head.prepend(policy);
+ return "" + document.documentElement.outerHTML;
+}
+
+export function GoalReportReviews({goalId, sourceId, zh, focusTodoId, refreshKey, callbacks, readOnly = false}: {
+ goalId: string; sourceId?: string; zh: boolean; focusTodoId?: string; refreshKey: string;
+ callbacks: PersonalWorkspaceCallbacks; readOnly?: boolean;
+}) {
+ const [rows, setRows] = useState([]);
+ const [selected, setSelected] = useState(null);
+ const [reading, setReading] = useState(focusTodoId ?? null);
+ const [cursor, setCursor] = useState(null);
+ const [busy, setBusy] = useState(false);
+ const [loaded, setLoaded] = useState(false);
+ const [error, setError] = useState("");
+ const [textOnly, setTextOnly] = useState(false);
+ const generation = useRef(0);
+ const navigation = useRef("");
+ const selectedId = useRef(focusTodoId ?? null);
+ const focus = useResultCatalogFocus();
+ const storageKey = JSON.stringify(["loopx-report-reading", sourceId ?? location.origin, goalId]);
+ useEffect(() => {
+ const destination = JSON.stringify([storageKey, focusTodoId]);
+ if (navigation.current !== destination) {
+ navigation.current = destination;
+ let saved: string | null = null;
+ try {saved = sessionStorage.getItem(storageKey);} catch { /* Reading works without storage. */ }
+ selectedId.current = focusTodoId ?? saved;
+ setReading(selectedId.current); setRows([]); setLoaded(false); setTextOnly(false);
+ }
+ void load();
+ return () => {generation.current++; focus.cancel();};
+ }, [goalId, sourceId, focusTodoId, refreshKey]);
+
+ async function read(todoId: string, current: number) {
+ const value = await readReportReview(goalId, todoId);
+ if (current !== generation.current) return;
+ if (value.goal_id !== goalId || value.review.todo_id !== todoId || value.todo.todo_id !== todoId)
+ throw Error(zh ? "材料来源已变化" : "Material source changed");
+ setSelected(value);
+ try {sessionStorage.setItem(storageKey, todoId);} catch { /* Reading works without storage. */ }
+ }
+ async function load(next?: string) {
+ const current = ++generation.current;
+ setBusy(true); setError(""); setSelected(null);
+ try {
+ const page = await fetchReportReviews(goalId, next);
+ if (current !== generation.current) return;
+ if (!page.available) {
+ setRows([]); setCursor(null); setLoaded(true);
+ if (selectedId.current) setError(zh ? "请先按 Goal 的提示完成权威存储迁移,再刷新原材料。" : "Complete the Goal's authority migration, then refresh the original material.");
+ return;
+ }
+ setRows(previous => next ? [...previous, ...page.items] : page.items);
+ setCursor(page.next_cursor); setLoaded(true);
+ if (selectedId.current) await read(selectedId.current, current);
+ } catch {
+ if (current === generation.current) setError(zh ? "材料或审阅状态暂不可读,请重试。" : "Material or review state is unavailable. Retry the read.");
+ } finally {if (current === generation.current) setBusy(false);}
+ }
+ async function select(row: ReportReviewRow) {
+ const current = ++generation.current;
+ selectedId.current = row.todo_id; setReading(row.todo_id); setSelected(null); setTextOnly(false);
+ try {sessionStorage.setItem(storageKey, row.todo_id);} catch { /* Selection is optional. */ }
+ setBusy(true); setError(""); focus.reader();
+ try {await read(row.todo_id, current);}
+ catch {if (current === generation.current) setError(zh ? "原版本已不可读取,请重试。" : "The original edition cannot be read. Retry.");}
+ finally {if (current === generation.current) setBusy(false);}
+ }
+ const label = (row: ReportReviewRow) => row.superseded_by ? (zh ? "已有修订" : "Superseded")
+ : row.status === "done" ? (zh ? "审阅已处理" : "Review handled")
+ : row.status === "deferred" ? (zh ? "稍后审阅" : "Review deferred")
+ : ["open", "blocked"].includes(row.status) ? (zh ? "待验收与反馈" : "Awaiting review") : row.status;
+ const markdown = selected?.artifacts.find(item => item.renderer_id === "markdown_v0");
+ const html = selected?.artifacts.find(item => item.renderer_id === "html_artifact_v0");
+ const htmlView = useMemo(() => html ? inertReportHtml(html.content, zh) : "", [html?.content, zh]);
+ function returnToCatalog() {
+ generation.current++; selectedId.current = null; setReading(null); setSelected(null); setBusy(false); setError("");
+ try {sessionStorage.removeItem(storageKey);} catch { /* Optional selection. */ }
+ if (reading) focus.row(reading);
+ }
+ const attention: WorkspaceAttention | null = selected ? {goalId, sourceId, todoId: selected.review.todo_id,
+ text: selected.review.title, blocking: false, decisionSource: "todo", details: {...attentionDetails(selected.todo),
+ ...(selected.source_session_id ? {reportSessionId: selected.source_session_id} : {})}} : null;
+ if (loaded && !rows.length && !reading && !error) return null;
+ return
+ {reading ? : {zh ? "审阅材料" : "Review materials"} }
+
+ {zh ? "阅读不会完成验收。每份材料的审阅分别记录;处理材料不等于整个 Goal 验收通过。反馈回到负责 Agent 的原工作对话。页面版保留静态目录;外部来源可从文字版打开。" : "Reading does not accept a result. Each edition has its own review; handling it does not accept the entire Goal. Feedback returns to its responsible Agent's work conversation. Page view keeps the static index; open external sources from text view."}
+ void load()}>{zh ? "刷新" : "Refresh"}
+ {busy ? {zh ? "正在读取材料…" : "Reading material…"}
: null}
+ {error ? {error}
: null}
+
+ {rows.map(row => void select(row)}/>)}
+ {cursor ? void load(cursor)}>{zh ? "更多材料" : "More materials"} : null}
+
+ {reading ?
+ {selected ? <>{selected.document.title}
+
{label(selected.review)} {new Date(selected.document.generated_at).toLocaleString(zh ? "zh-CN" : "en")}
+ {html && markdown ? setTextOnly(value => !value)}>{textOnly ? (zh ? "页面版" : "Page view") : (zh ? "文字版" : "Text view")} : null}
+ {attention ? : null}
+ {html && !textOnly ? : null}
+ ;
+}
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/manager-brief.tsx b/apps/presentation/dashboard/src/features/personal-workspace/manager-brief.tsx
index 2390d4a316..f264dde9aa 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/manager-brief.tsx
+++ b/apps/presentation/dashboard/src/features/personal-workspace/manager-brief.tsx
@@ -1,5 +1,5 @@
import {ContextHelp} from "./context-help";
-import {ArrowRight, Check, CircleHelp, Hand} from "lucide-react";
+import {ArrowRight, Check, CircleHelp, FileText, Hand} from "lucide-react";
import {useState, type ReactNode} from "react";
import { useWorkspaceI18n } from "./i18n";
import type { WorkspaceActionPreview, WorkspaceAttention, WorkspaceGoal } from "./personal-workspace-model";
@@ -21,7 +21,7 @@ function RunningMeta({ goal }: { goal: WorkspaceGoal }) {
function BriefTile({ count, empty, kind, live = false, onSelectGoal, onSelectOperation, onSelectAttention, rows, title, total }: {
count: number;
empty: string;
- kind: "needs" | "needs-goals" | "confirmations" | "operations" | "running" | "claimed" | "completed";
+ kind: "needs" | "needs-goals" | "reviews" | "confirmations" | "operations" | "running" | "claimed" | "completed";
live?: boolean;
onSelectGoal: (goalId: string) => void;
onSelectOperation?: (proposal: WorkspaceActionPreview) => void;
@@ -41,7 +41,7 @@ function BriefTile({ count, empty, kind, live = false, onSelectGoal, onSelectOpe
data-attention-id={row.attention?.todoId} data-attention-source={row.attention?.sourceId}
onClick={() => row.proposal ? onSelectOperation?.(row.proposal)
: row.attention && onSelectAttention ? onSelectAttention(row.attention) : onSelectGoal(row.goal.goalId)} type="button">
- {kind === "completed" ?
+ {kind === "reviews" ? : kind === "completed" ?
: row.attention ? : }
{row.text} {row.meta ?? row.goal.title}
@@ -61,7 +61,7 @@ export function ManagerBrief({ goals, onSelectGoal, attention = [], onSelectAtte
operations?: WorkspaceActionPreview[]; onSelectOperation?: (proposal: WorkspaceActionPreview) => void;
onViewAllOperations?: () => void;
}) {
- const { t } = useWorkspaceI18n();
+ const { t, locale } = useWorkspaceI18n();
const active = goals.filter((goal) => goal.activationState === "active" && !goal.loadState);
const needs = active.filter((goal) => workspaceHomeLaneForGoal(goal) === "needs_you");
// Count only observed native items. A Goal digest is a different unit, and
@@ -80,6 +80,9 @@ export function ManagerBrief({ goals, onSelectGoal, attention = [], onSelectAtte
].join(" · ")}];
});
const summarizedGoals = needs.filter(goal => !attentionRows.some(row => row.goal === goal));
+ const reviews = attentionRows.filter(row => row.attention?.details?.reportReview === true)
+ .map(row => ({...row, meta: [row.goal.title, row.attention?.details?.createdBy ?? row.attention?.details?.boundAgent].filter(Boolean).join(" · ")}));
+ const otherAttention = attentionRows.filter(row => row.attention?.details?.reportReview !== true);
const incomplete = goals.some(goal => goal.loadState);
const operationRows: BriefRow[] = operations.flatMap(proposal => {
const goal = goals.find(goal => goal.goalId === proposal.goalId && !goal.loadState);
@@ -103,9 +106,11 @@ export function ManagerBrief({ goals, onSelectGoal, attention = [], onSelectAtte
: executionPending ? t("brief.runningReading") : t("activity.executionUnknown");
return (
- row.goal.goalId)).size}) : null} />
+ {reviews.length ? : null}
+ row.goal.goalId)).size}) : null} />
{summarizedGoals.length ? ({goal, key: goal.goalId, meta: goal.title, text: goal.needsYou ?? goal.nextSentence}))}
title={t("brief.needsGoals")} /> : null}
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-model.ts b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-model.ts
index 15af4c9f5c..2322d3b9f1 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-model.ts
+++ b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-model.ts
@@ -636,7 +636,7 @@ export type PersonalWorkspaceCallbacks = {
onSelectGoal?: (goalId: string | null, view: WorkspaceGoalTab) => void;
onSelectTodo?: (todoId: string | null) => void;
onSelectView?: (view: WorkspaceGoalTab) => void;
- onSelectWorkAgent?: (agentId: string | null) => void;
+ onSelectWorkAgent?: (agentId: string | null, sessionId?: string) => void;
onSelectWorkSession?: (sessionId: string, replace?: boolean) => void;
onOpenNotificationSettings?: (goalId?: string) => void;
onFetchNotificationTargets?: () => Promise>;
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx
index a76e7e66e2..23f7e85792 100644
--- a/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx
+++ b/apps/presentation/dashboard/src/features/personal-workspace/personal-workspace-page.tsx
@@ -94,6 +94,7 @@ import { ManagerBrief } from "./manager-brief";
// Loaded on demand: settings and their editors are a separate chunk that
// arrives when the owner first opens Settings, not on every workspace visit.
const ContentProductionResults = lazy(() => import("./content-production-results").then(module => ({default: module.ContentProductionResults})));
+const GoalReportReviews = lazy(() => import("./goal-report-reviews").then(module => ({default: module.GoalReportReviews})));
const WorkspaceSettingsPage = lazy(() => import("./workspace-settings-page").then((module) => ({ default: module.WorkspaceSettingsPage })));
import { UsageStatisticsNotice } from "./usage-statistics-notice";
@@ -325,6 +326,7 @@ function GoalOutputsView({
localResults,
researchApi,
production,
+ reviewMaterials,
}: {
active: boolean;
items: Array>;
@@ -335,6 +337,7 @@ function GoalOutputsView({
localResults: boolean;
researchApi?: GoalResearchApi;
production?: ReactNode;
+ reviewMaterials?: ReactNode;
}) {
const { locale, t } = useWorkspaceI18n();
const [teamSnapshot, setTeamSnapshot] = useState(null);
@@ -360,6 +363,7 @@ function GoalOutputsView({
&& teamSnapshot?.settings.agent_id && teamSnapshot?.settings.execution_config);
return (
<>
+ {reviewMaterials}
{items.length > 0 || reportState?.loading || reportState?.error || !production ?
{t("files.title")} {!teamConfigured && !production ? {items.length} : null}
{reportState?.loading ? (
@@ -978,6 +982,7 @@ export function PersonalWorkspacePage({
setLocalView(view);
callbacks.onSelectView?.(view);
}
+ const [selectedReportReview, setSelectedReportReview] = useState<{goalId: string; todoId: string} | null>(null);
const [actionDraft, setActionDraft] = useState(null);
const [loopxMode, setLoopxMode] = useState(null);
const [loopxDelivery, setLoopxDelivery] = useState<"queue" | "inbox" | "steer">("queue");
@@ -1097,22 +1102,38 @@ export function PersonalWorkspacePage({
composerRef.current?.focus();
}
// A draft for another Goal waits until that Goal's composer is the visible one.
- const [composerPrefill, setComposerPrefill] = useState<{ goalId: string; text: string } | null>(null);
+ const [composerPrefill, setComposerPrefill] = useState<{ goalId: string; text: string; workAgentId?: string; workSessionId?: string; statusUrl?: string } | null>(null);
useEffect(() => {
if (!composerPrefill || composerPrefill.goalId !== selectedGoalId) return;
+ if (composerPrefill.statusUrl && composerPrefill.statusUrl !== (statusSourceControl?.activeSource.statusUrl ?? "/status.json")) {
+ setComposerPrefill(null); return;
+ }
+ if (composerPrefill.workAgentId && (selectedWorkAgentId !== composerPrefill.workAgentId || !selectedWorkSessionId)) return;
+ if (composerPrefill.workSessionId && (selectedWorkSessionId !== composerPrefill.workSessionId
+ || !workspaceConversations?.managed || `managed:${workspaceConversations.managed.target.sessionId}` !== composerPrefill.workSessionId)) return;
setComposerPrefill(null);
suggestReply(composerPrefill.text);
- }, [composerPrefill, selectedGoalId]);
+ }, [composerPrefill, selectedGoalId, selectedWorkAgentId, selectedWorkSessionId, conversationKey, statusSourceControl?.activeSource.statusUrl]);
function draftAttentionMessage(attention: WorkspaceAttention, intent: "reply" | "explain") {
// A display summary is not a usable reply context: it may cut through a URL.
const task = attention.details?.requestText ?? attention.text;
const key = intent === "reply" ? "drawer.attentionReplyPrefill"
: attention.details?.interaction === "decision" ? "drawer.decisionExplainPrefill" : "drawer.attentionExplainPrefill";
+ const reportAgent = attention.details?.reportReview ? attention.details.createdBy ?? attention.details.boundAgent : null;
if (attention.goalId !== selectedGoalId) selectGoal(attention.goalId, "chat");
- openGoalConversation();
+ if (reportAgent && callbacks.onSelectWorkAgent) {
+ setLocalView("chat"); setActiveSessionRun(null);
+ callbacks.onSelectWorkAgent(reportAgent,
+ attention.details?.reportSessionId ? `managed:${attention.details.reportSessionId}` : undefined);
+ } else openGoalConversation();
setSelection(null);
const reference = attention.details?.todoIdentified ? `\n\nTodo: ${attention.todoId}` : "";
- setComposerPrefill({ goalId: attention.goalId, text: t(key, { task }) + reference });
+ setComposerPrefill({ goalId: attention.goalId, text: t(key, { task }) + reference,
+ ...(reportAgent && callbacks.onSelectWorkAgent ? {
+ workAgentId: reportAgent,
+ workSessionId: attention.details?.reportSessionId ? `managed:${attention.details.reportSessionId}` : undefined,
+ statusUrl: statusSourceControl?.activeSource.statusUrl ?? "/status.json",
+ } : {}) });
}
// The steward prompt set is owned by the client model; the quick-prompt row
// reuses it so one affordance answers "what now / what blocks / what is proven".
@@ -2308,6 +2329,13 @@ export function PersonalWorkspacePage({
callbacks.onSelectGoal?.(goalId, view);
}
+ function openAttention(item: WorkspaceAttention) {
+ if (item.details?.reportReview) {
+ setSelectedReportReview({goalId: item.goalId, todoId: item.todoId});
+ selectGoal(item.goalId, "files");
+ } else setSelection({kind: "attention", item});
+ }
+
function selectAgent(agentId: string) {
setLocalAgentId(agentId);
callbacks.onSelectAgent?.(agentId);
@@ -2359,6 +2387,7 @@ export function PersonalWorkspacePage({
}, [pendingNotificationItem, selectedGoalId]);
function openAttentionFromNotification(item: WorkspaceAttention) {
window.focus();
+ if (item.details?.reportReview) {openAttention(item); return;}
if (item.goalId === selectedGoalId) { setSelection({ kind: "attention", item }); return; }
setPendingNotificationItem(item);
selectGoal(item.goalId, "overview");
@@ -2744,6 +2773,12 @@ export function PersonalWorkspacePage({
teamSessionId={!readOnly && selectedAgentId === "codex" ? conversationSessionId : undefined}
goalId={selectedGoal.goalId}
localResults={!readOnly && active}
+ reviewMaterials={!readOnly && active ? {locale === "zh-CN" ? "正在读取审阅材料…" : "Loading review materials…"}
}>
+ item.goalId === selectedGoal.goalId))}/>
+ : undefined}
researchApi={researchApi}
production={active && !readOnly && selectedGoalTab === "files" ? {locale === "zh-CN" ? "正在读取作品…" : "Loading artifacts…"}}>
) : !managerChatOpen ? (
- setSelection({kind: "attention", item})}
+ void callbacks.onRefresh?.("missing")} onRetrySource={() => void refreshWorkspace()} onSelectGoal={selectGoal} systemHealth={model.systemHealth}
onboarding={model.onboarding} onRequestGoalCreate={readOnly ? undefined : requestGoalCreate} onSuggestRequest={readOnly ? undefined : suggestReply}
runtimeReadiness={readOnly ? undefined : runtimeReadiness} recheckingRuntimes={recheckingRuntimes} onRecheckRuntimes={callbacks.onRecheckRuntimes ? recheckRuntimes : undefined}
diff --git a/apps/presentation/dashboard/src/features/personal-workspace/report-reviews.css b/apps/presentation/dashboard/src/features/personal-workspace/report-reviews.css
new file mode 100644
index 0000000000..134dc56504
--- /dev/null
+++ b/apps/presentation/dashboard/src/features/personal-workspace/report-reviews.css
@@ -0,0 +1,22 @@
+.goal-report-reviews { min-width: 0; margin-bottom: 24px; }
+.goal-report-reviews > header, .report-review-masthead > div { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
+.goal-report-reviews h3 { display: flex; align-items: center; gap: 8px; margin: 0; font-size: var(--text-heading); line-height: var(--leading-heading); }
+.goal-report-reviews button { min-height: 44px; font: inherit; }
+.goal-report-reviews [data-result-catalog] { display: flex; flex-direction: column; gap: 8px; margin-top: 16px; }
+.goal-report-reviews [data-result-catalog][hidden] { display: none; }
+.goal-report-reviews .result-catalog-row { display: flex; align-items: start; gap: 16px; width: 100%; padding: 16px; text-align: start; }
+.goal-report-reviews .result-catalog-row > span { flex: 1; min-width: 0; }
+.goal-report-reviews .result-catalog-row strong { display: block; overflow-wrap: anywhere; }
+.goal-report-reviews :is([data-result-catalog], [data-result-reader]):focus { outline: 2px solid var(--pw-blue-ink); outline-offset: 4px; }
+.report-review-tools, .report-review-tools > button, .goal-report-reviews .result-catalog-return { display: inline-flex; align-items: center; gap: 8px; }
+.report-review-reader { min-width: 0; margin-top: 8px; }
+.report-review-masthead { padding: 8px 0; border-bottom: 1px solid var(--pw-border); }
+.report-review-masthead h2 { margin: 8px 0; font-size: var(--text-title); line-height: var(--leading-title); overflow-wrap: anywhere; }
+.report-review-masthead time, .report-review-masthead span { font-size: var(--text-caption); line-height: var(--leading-caption); color: var(--pw-muted); }
+.report-review-actions { display: flex; flex-wrap: wrap; align-items: start; gap: 8px; padding: 8px 0 16px; }
+.report-review-actions .personal-decision-bar { flex: 1; }
+.report-review-actions .personal-compact-menu { flex: 0 0 auto; }
+.report-review-reader iframe { display: block; width: 100%; height: min(1000px, 80vh); min-height: 560px; border: 1px solid var(--pw-border); border-radius: 6px; background: var(--pw-surface); }
+.report-review-prose { font-size: var(--text-lead); line-height: var(--leading-prose); }
+.report-review-reader > details { padding: 16px 0; overflow-wrap: anywhere; }
+@media (max-width: 640px) { .report-review-masthead > div { flex-wrap: wrap; } .report-review-reader iframe { min-height: 640px; } .report-review-actions .personal-decision-bar { flex-basis: 100%; } }
diff --git a/apps/presentation/dashboard/src/views/dashboard-page.tsx b/apps/presentation/dashboard/src/views/dashboard-page.tsx
index 7409796e97..ee0b920175 100644
--- a/apps/presentation/dashboard/src/views/dashboard-page.tsx
+++ b/apps/presentation/dashboard/src/views/dashboard-page.tsx
@@ -1283,7 +1283,7 @@ function PersonalGoalHome({
workBrowseSearch?: Record;
onWorkBrowseChange?: (patch: Partial, source: string, replace?: boolean) => void;
onSelectWorkSession: (sessionId: string, replace?: boolean) => void;
- onSelectWorkAgent: (agentId: string | null) => void;
+ onSelectWorkAgent: (agentId: string | null, sessionId?: string) => void;
onSelectTodo: (todoId: string | null) => void;
onSelectView: (view: WorkspaceGoalTab) => void;
onGoalActivationStateChange: (goalId: string, activationState: "active" | "stopped") => void;
@@ -3941,10 +3941,10 @@ export function DashboardPage() {
message: current.workSession === sessionId ? current.message : undefined} : current});
}}
selectedWorkAgentId={search.workAgent ?? null}
- onSelectWorkAgent={(agentId) => {
+ onSelectWorkAgent={(agentId, sessionId) => {
const goalId = search.goalId, statusUrl = search.statusUrl;
void navigate({search: current => "goalId" in current && current.goalId === goalId && current.statusUrl === statusUrl
- ? {...current, todo: undefined, workAgent: agentId ?? undefined, workSession: undefined, messageSession: undefined, message: undefined, view: agentId === null ? "overview" : "conversation"} : current});
+ ? {...current, todo: undefined, workAgent: agentId ?? undefined, workSession: sessionId, messageSession: undefined, message: undefined, view: agentId === null ? "overview" : "conversation"} : current});
}}
onSelectTodo={(todoId) => {
const goalId = search.goalId, statusUrl = search.statusUrl;
diff --git a/docs/guides/README.md b/docs/guides/README.md
index b8afd04f32..2ab66e5931 100644
--- a/docs/guides/README.md
+++ b/docs/guides/README.md
@@ -8,6 +8,7 @@ Guides are task-oriented paths for people starting or operating LoopX.
- [Codex App 自动续跑体验指南](codex-app-autonomous-goal-experience.md)
- [Understand, use and evaluate context delivery](context-delivery.md)
- [理解、使用和验收上下文交付](context-delivery.zh-CN.md)
+- [审阅工作成果 / Review work materials](review-materials.md)
- [Minimal custom runtime example](minimal-custom-runtime-example.md)
- [Minimal custom runtime example (中文)](minimal-custom-runtime-example.zh-CN.md)
- [Custom Agent runner integration](custom-agent-runner-integration.md)
diff --git a/docs/guides/assets/review-materials/home.png b/docs/guides/assets/review-materials/home.png
new file mode 100644
index 0000000000000000000000000000000000000000..f57cc5d74c942d35571bae0243133cc535e2f814
GIT binary patch
literal 94711
zcmc$`^;eW@)IW?!D=pHEgh+Qw8-SoFAPrJVgLDWEFtjLA(kP%PsW3=4(k&&ON_X?!
zqvv_n`v*L0y+0k7M~3^pV((Aw3Dwk4B_yCBz`(#DynRdQJ_ZI>AqK|9M|haQU(
zp%@q!IBXOZHH|SaJd)qOlDpe*ld9Q2F3>;s<}V1j<;c1}}Vf}>9lXAe
zEWdtX_Wk-r*uLfOw{RkTemGI#tv769YTVr-yC>kjmRKodHBqqtr$fTY;n(+hJW^H(
zfn0b3f>r5hMzD%x2e%{`(VxM1Txm;osjPkQui~2>$(9>9TU5CfA$@X=TPuRgkrLtNZrxX|?3&wPve
z#k{xNI$g;U+dIqsrbdYkUcr~Cx4Pxd#s5CcOe)z=QU&Cg!1Lb&`;-21w_mf(Hb;ij
z?w=3R-hRX0`HH#WPeDz!|M?jay`-@1a8KO51b)-Kl@Ue#vCn!XM?1?8N-R6iPLHMj
zecS};pP?`MQ6vJd-*DVxzn3~5`lPT6ezZ|3-=LiA+MT&^sZ#r2UbD@F>{|<+v~qqv
z>pIC{tg2D`G3@Fz!l~VX^78T`PX~sJEyBA`!YH^|eouHV(x2PO94%$_=iIZ(^gBJW
z>@>i72zQTRoesQwWvqU-k>N_!qg`o!g
z9ZE!+|Cz*7e&w($L6<0vP>!Z6!$q*Lo&M6bjQ%GvnD9SLubrPAJABgqnCdZuzwo3j
z_QwtHm0^LbkkfK%I=UI1cs^sdzniQSOTxP>V%CVq(j?{OzEn!0N%pDKcBGF~L5Y*E
z=0xzfD=hv++{-t6^`1+b)M5-Uk*7$x^J=EQ=)ONb^&nf#6jR`K^}-L1wDEEmtB?0T
zB&f_V$hk#$yB%yy|I9a3BuJHVU+WZ`?09`Gy!(!>;@QceLq*8y=r{dBlK|Gg&yX2b
zL5UE*Xza5YMBYo{OQxAB`8;fR03LzPX{Pb;?0EgzKyEydO4WYd)XorKr8x)L^3
z)?BegyQG2=jn+2N^m@%XLmYb+d_;mS{#sl-lM@)617HPqC*n6hrn_$Hct%R-XSE8i~0qcR2TEYrb7-jVXlgZZv}o
z6qc6;YOptd4;SgHKfGcN6Rs>o3ZD;nO^w--R#ZGtcja%5!}@6z;xlJnWL1ekJ^yoc
z|75D}Wn{EYwi>n4DBRA2He^*{Y|+l2p9QyKSfaSQ&kh&UzUY^+%vB%ETpIItn5guu
za9uX@qKhP#+9Q@bxmiVSLR_@f_x`q`y8Br61vp^}QCF{Pb6T{;S`x*Xz?t7)pLEa}
z{PZx7R?Ob#WV6Mga>w#rQLcn0T`?^uJa-;o7@qd;30@GWc-QN$L$D!(dQ;%f9
zQn)hY17`$*PhRY|=rk#&Iqfr{6Bo3Quh!=1OqUnI-7i@M;)>Ueqo7-wv><&32x|Fc%O%P&$+;D8)B7_mO7K>3_muxlhE
zXBSZg?13q1*B^drVf6Ru%~TdK?8~_qeb)GWF7G8SaUAc%-`UToSXg^=328+y-%$VC
zJk(sTP&Y`mxRg836TG{XEMDXyx1w?Y4QIwEP{?g_M!AK;d*aYXX~ndSc@b`=+n6Af
zH4&i_tL`Cb*%k3mrCJl}SoA0Pf(h4ET<
z|NOjtPc`^*Nue_)o9LDFUQ6MTNIdyKO{6z|lwR_1QLi#ojJ>WhMj?wfCCjB!iZ4Ea+#R0#zuf%~=P5aCv6i?8YpjxBDW-5W(qvEP
ze!TIS(;Ys##8=60T90+#Sj>KWX}o+JPSsUj193PH-=F`H{M#EcUf#TuB>a*52b)^L
zD_0*Ac`AB0Rt2Q1ytQPc<2b`MJ#*tZc0eqj|C#zbQ68hp1L$SqHkN0wd~`Y`iKMLc
z_nQkHCS`Zt(rYxtn#NRmZYN0`II9R};&4CuJPg0bv>~`NLBJf2B`iSADpAQNcJ(AI
z&JCzyS8wR{_*J?t_aRAH6F47z)@=wT{4?;=M?*iJK(QTT8rlf5#-*
zki#=Ko_2M<6Jy;Asv%4DWv?J*R?27c>2Ff=|1+Z`+?gZ-t;#4();AUQh+}K{
zXTc;#n$K%qL&=>lodlN|Wh?c|?4eb#9F+Rn;7wn2Ci=LLLJn&LrBrsaksMhCZIzf#
zywLY}k24>(mdYx+Km)q_TdVBq0lAOO^h1)6)Aq|`QUqD1^0dJ{vfyVq5-r(b)eG#nBut;N-
zo3Fq^Y5r?MxQxVdk+$`vc4JTgw@0kfP7h|Ip`S^3?|q)V
z!!`GYi#krwEoIm@h=77c(KNXh8q?0&uQ4a@HD5Sc^krF;F1whXk$g~Ypz>G+Ar-gl
zO)+{h6@xG1Z{~45$fo+Xte7Z>zOb!2*^%6bvHKI=#A3zX`)g5SvZ?23en&P{Uc2Z`
z{%Z3;@WzkV*IfQ}w>fgXUkPO0Z`}nL-&DlzlVC^MvtGPGKgTE_Alsa8Sdq}5r&9oE
zDURm>yQ7pOv%<^pr?oFGbj$1;05)jlW9on!9s~nBU61bPXc!imHEE#9mia^EpC
zyV0+8YbA`7yaop|;e0~?Qk`a-E!yKg)Y}Yx8iWo_L?`ZexMe}6_-yEN(J9vhlxj4?
zY)f>seN8wTlxO0zrB_vPC@}O58x9qWy7dgI6A5l1YnjhY+CddxI
zrmO(FSbU!~k>+;~ER++sr|QoPe)qT^?SDB1l9TB^CZAg9B}!hbwMVg-q)Uc~*1LRF
z2%5$v@A>2J?|+D}%eEJfJ_
zR-GJf!)6VKUgtHcy!HDHUVroV1nG?O+kn?3eUDt%#>-QdR2>~RJmazO$%a+jIxZ6s
z5Nt~LZ7*~hR=8PoBy7t1irm<$b(uMjqL(^I8~dOVNwb#+t1Go1dn>w1(;^T0R*5BH
zKLAxu!|$$8hLT&YCaZlH=s!^!c?6upIkkhX7U&4L%%`1qvj!l@c%GUxY&UQx6_Twl
z6bOJn%7l_@w2z?QDk$0y7uJ2}JqWW56j9w9W>P=|9d0j5#oPvNp!g;*n2on<6&Wa-
z1S=rzVNmYek*boheB3eY+b^E8@~thuuicFu2}cI{{axKHD55K
zA!E4iCGKIg&&*AdG7S{7(Y2=*lY3`kBt;)?^=1ad&%ghoTZF0Q4%F++xWcXTuz>NE
z?MU&%yhoi^^vj*EUDyuit8U#it75Xg_ucUmsWjB}{QDmWj;EA3K9jj*(uvv)FzKrv
zB+49)VXL>Q2`x^L)dglQK-i+{N}g$!>jVv)gn(ilLn7@#1iOnlaCuwf#djeqW}-f
zx#|AVX#Di_9u6hri#V5abqW}QDP~9rgYQVJbrvrDj}`#M$Tu+%FEYCH85k&$9Xo0nTJl(rceeZbkat@+K?yV-$o6?O{i}I98W(xJzQkIX#i~_IEhCmKY7`h
z=R^&9DFE_h>dSrbHVuno?n0KAE1Bzm0UV4upI0K?frBdE7?9l-$J6f6TjTFfL@?+(
z*Gih{HDvHfn`@jhFD&aKGM}E;Eh<`y5?cyGg0k8#yRr>=?%Q~%yP=Id~$q8
zn=SwKiK>KA%K}YTx9UTO1**zPnkYs&`yBO<%w~Sq@l@sVkn&Z)Ng7+r+ud@Dd+e+;
z|E@a{XL%Pe7ppQ}*@XAHjL@6HFM1`GtqPcbNaD?8-Nu3N1pDs-QG8X+VH=(sY}n`r
zdxO#&(=ql9iaG+=)}e!ycA|Pl!Si^4>KQaPuhZS1G2fuk*$#esJBw4RYbWl2eCTt9
zwIR78P~;tseXhKa)<}~+ySR9QI+iZ}rymDmFP>P$Lo42BqBJgC%(fv8&)TOei~K`=
zPddO=c(lN>GwC28gqYEi%SS6&KdK0*J2VLAHF~-zt(Phh)W0kmGs+)ls*uyr_W0{R
z%2L7g?g@32NB(SC4O_PgA)VbDD>QwXXjE#ONH1h}es;Rpot9HbF5#HSekT^mMzT!U
zANS(fz+pFs@Oe=a^p1AlTd55@FB}$V7rIiyCs?tYcI}K(+S24|X1|96(Rq+8?&K)j
zi-@EVp%JsE>skb;_TL$kU@G#N8;>{kD|eh$I4%N`isc7XfJZYO<9D9h>L?ytNh@o#
z^wx4t8jCi|9g@syH1%m!5-;LGJOJ|1p@WE8(G9=KBWT&-vDCwiX)bgQO?vfbLE6t(
zg~mk(v<{Wi;}mqPQs(Tben-nB?O2aqcKHvD%(ut)@&h5}(<^4@epC?47zutwSvP!hBz9Po!(3RN2bl#)4^w8e5+OKfNUsyRQq
z>$ol?>p0UGiq8%-y~=I%am%1>_QgwP?WC+K+Fu?I3JY9{Mhdd<$A`O=tw4)i?)v~G
zGf%gO#jIOgXX$3tGx%WuPP|al;Q+r11f&dndJ4b=R5hLok5p+-yf03gg@jJ5=H=r1
zcv+1R6N-d;0Q>MBvv>4h_yoD}@1>C2I1(x9`^SFMBV>(X!TS;WD!3@CF9c7Fjfc)$m!7Y%%Tz$&E`deV}zALa5-{bL~z4vp?Wxh}u1
zA*e^0XY1szOxC2;5@*aP(G6eb(Jxh^VNP^p50z+%qz&N+=%3<=6STN3C?-Xvc974BD9Lm9}DyZCQtM)yP
zz`d1A2Rs0ZA6f!(Kx?0;%6%X1y6-G$VXhNUT-O{fr%X`Ec;qx~l!+7LuSVXy-D`b8
zIKzpQwL858R1+5c_~4*hqzDfSa&|SQ6cSW|oh%K5kF%U?yB1Y?-Uhg
zo#+{*JxCNM&xx2PU!MCxwOn(lu;rjkd#!Hxzg0eK!gt^BcoUji>GtcdHvLEOe46Pu
zp?l+8rg~wvGWv}h6JLHwNtlyR`eH1Zlbqm3s3->{*7ddYc}!J!vYp<++&cN=Ro-Il
zDy3{F=lMHRm{c6e+&&5|zCSKih3WnRRgp&%D9JN(=NHX*GVW`1PJ)~SE;_s?yc^X%1X+av6r&LYbq(;ci!VEM2M`7)y`H;eM*z_
zp9m$xygaA=h}F@Gzm%2wU&q>gRXtf~st6FJ^N-xpRXQ|>&IM=H
zOZmn%42i!{s)(`M8@9nE_4e~@?{vSz1#f1RH!{ns1R8LFI3ci%X~ogPKv>4PeuLkHSa_SRJArum>9
z#aMyrsnYDT^@Br$&E&DA=+gmf0G2CH;HCmo9f7`E(o52wmG#O$D(`}AOV|xy>Q^}E
zs7PBIK{<;Mt*#Km|EsfNJuNV*0<9sQ>j8U<@1@HYyMXJDhB=bA0Xdr6I=`-3S2MeQ
z26~wIhYLrAb(UX0-FSU7G_m(Qq4f<%_p^ekJ@`QWwAC$vHc1)_+|R_+N%~auEAku!
zl5fiyxfW;eNSzGandcYqnCs=CL(Ei&DcRqN@Dm@i(|PbBK3vWg{45lD^CmvTS!0Zb5xt
z^tTQqA$^8;gcV4mge$u{@W3+SYmXOo)oLNRn;l*yRPlxOcs>xia;3EM{ms7v1_yyK
zdixyuj>lroowuJHr|WYINC?Mr-vjZ<=GHR5m~=rX;?7rdE%BHL9l~Jiiz@RNQ~{s?
zu{dWCRD11S|KU@tQ7I-y&O&>m
z02)N0&oKHOTv&7jgo@T)W{1e2LoxE3)Pe+111c#LTn0HmI(g*N`gIx!=O=Z6*bRJm
zACbX?v}k!~yExhXGS1Bu$u;lWZe4Jh=zr4X>6I+Jzx}3ActmD);fV
znYTJd0z!I+ps+7LAX6N4t)O}_!@JT4jKQ)yi9$*v8P3_-SQ#HMwbBkS86Lr3=^&Bv#=k`L1tnX2xRjNSBHzkvheD@I2$3w)z2{<3Lvg?MEV}i~Cdv5hx_x;KR
z`z7YmTXwD=OZ@E7B*Yk-26!apB|hH?$Q7htG36x*+w|odN@Z(#=>{4#5GY23tbkmq
zR(lFfoEiHgKk?V$PvLXNVni!~jq2wL^ied~Us%sc3<
ze#XaQ&fyDLx9s{gg$Oc77=_d_$qA7`*-+j5{CFuj1gE<;-R#(u5Q=Z@lH8OSeij(F
zFjp?#7G!3SR@=xZ%~EI-#v_X1wv+^b0inyc{WpdhMXi8iD~);XTzFD$E6B-J
zC3euy_Wk8_k$7wb_WWB`Pr0ruJ#hr`;^Hp>EZvN3Kb$Ed=@*h@Z3{bMG1a>(^hu@(
zxq^}?+mH7+LCDLfl7YK#&>o!M+I^BZ9{nLHX=_A7+X#Xcfg}qw#EdVW2Pn;Qr60Qp
zEnSbZu2nyG06GSD;uHj+vAA(k1#on}gC%tInoL3I0+cgR-)cvia}v&dc$Ra
zDkQfAGTh8UI!rMK3=q^5+w2GLZw1K5@)=hvh7er?tp&V^(qWJxKscQ?_-JgGFwIp6f+m5Kzw8h1l6^aoD>-AJg@~1(9A>E6LaC%
z)g$l~Z`|&n+4CmnIsm&YMcPwPBUv0?xj-``aJKqSjr}i41yhF~(C2`NH2ZZVOO)JO
z{AC2F^#Q0@AiH-Z3WdyR!JpYddj*+MA&9_9gCtKSQyUnlRUN#z6e&T5bcNTL5icnB
z=U_XskcoG%4BAx~Wbvke#t9Zl3i8F%k%*>bFd3lONVvBGj%+XJFEUp>F923{09*(y
z{002nfOa5e)7Lnr=ZQSnQK=Pbata}KtCx0sBtG3H;kC20G2H;~70IwIy1i$#y+S4R
z2B;6nK*uX@%QrMb4d#;R`pCgzQhUvYFI4{MFhR!KZM)a$+tW&H
zAQ43iGxf9Wd^K}rd(^Vx(&-3vD^tQ6uAE36YNbpME3+L@@T%{ScYFQFvAz!E6MFaD
zd<=`8G^+CCJZ;{If(TA!UbD-uzc76acn6F}^8Bs#$NNDJ@NSkk!Oe{e^@=R7rN4!|
zXi_&a2QQB8X1Nr98CUn!as|{2);%jSSf%>FN^#~jYT$AHpt{0;?l~R~={qEfMxrFa
z&8h>BI+WDdV>;+6&*OyGfa~FKFcZ8PVcXLjDH_I?To%^Qxpmf`cy
zH+enuLpFf;By*bWV`39HF6eROvo4l`vv{iqe9E_c#;GpKKfuf+tsrmo-|iGk*1Z!v
z)JXsE4YMMSpP(Pp%vmh~0VBn=LQs|9E=!cnf`Y1YQ*!OkI4WwPG9!Sr8L9?=hI{?l
z>R-Hnl-Z{E;-w3#L^E^}YXf}EF83g~dIPCHk9v%}idAk?<>oo_tou%!S_(21)9G!$S+otf$9Jtp?S|(EI*DSkJp~?S&f~=k-{Nr+AxaKmb
z(OD{yec9^AaE?L2pF=w)5BJt5(+)iz$iS^0F3PH*aUIW&NMO!Y?`Mg!9`3Mu2o{N=
zZ92DY?r)TUnYJ~kcE)yasif_p
z&7VYV$`Mj?5Pdg8=Hb)I9)CWciIR%tZZ-vtc&Cg(vhrQ(S+nG#dhLOdG2eA>9~tuNmi6hO5wW7>bRw&dAJ
zd&aXxQ4+6clI9N_5sdX8_(C2fAW_L=x`HGR67~G6PM^vl=%TZuFg|?Jh7WZAVJV&^rHV87|LgqT=yGq$tz-&Ql?Ck
zW!^A=eFJb-UO)0M>QYt9?h6MS?M$u)hZgmK-P5B#1!!Md1;c;``oBO^&)`B(Es$&X
z)zP|9qo6ZKUYq%rW}tWAe2%JykqrrJEkH1|U)tzomMIce3UG
zzpmfKI!IP*BV~JSvC?&e5byBnL&-TZg*S{i6)|KWZ-d2LBracWa~2Z%Wa#GY%5*4X
zu{PRR3Z(M4Fd~DRSO5>Skb13t`>8PQ#T!pjqtKxJS-01UomsX>RxrBf>YomLyop{r
zfK>zS}I)>ivf(6PG3|tr!o!8
zg6kg$?~995l_#$y8fkEOGNC`anz>wdetI@P}wy&zTiT$k_YfA+KbM(^-MG`JY^ix!e)Sz!twCf;)fe*O)~*f9#lok9Bg>BeYq2XK%Tl
z`1fGQG_E>wsY!0XtsZcq)1$+H4pl#E^H*qXrr(TLlovyoCnx3E*dMtPg+D&di(7AP
z1jF#7Z>XkaeQe7;Pgc&8XVZu{cTxu`ug)#0B
zi-=oxP<^h)yKSIFT||qP%hj2sitb>(Lm+monK?42ht*$S_T7cack)EwsWLH*A
z*)@rBM`|64gDk#1xo~h^hs#)a_uzT6yTUU)Rmw}T4bzVaw0whboTFrvy3ui*E~VDQ
zP;iuRsb~Voky^I2rs(Z%y9xKE%()Ny`PbvSP{T7
z(?74Miq3r#9^ni)1`5V+!qx2OtUyqXC{?g!R8!U#D-L;@(r+)5w!PT>4u6MYGPo3{
z>qOt7YF>!EKVndFnyGP+rQ_+({7BX?KFE34Hc~Nay(letw1vq=TBwpDWePMaIRxZ4
zm-oz~LPQvpW8gn_2wNR%s16D-q}vHTC1;6|e<6lXn2ft(VQ|NF6o{Ib-Kch!3ZZ>I
zv>T@nLCPd7T!%Kdu6gj?<(2cJJiaq0Pub!-H-hB=AjMw|HrD8;89n$d?pNY_@Xd36-OH*-9
zh#t1L4hG~b17387jl#kMTPWQRKWPIDZi5c=Ib%`id)2aKLl=H~k6U&Hr3SL-IM+Y4
zSD>@f0$C`bWv%nH?+Vv_rVLUEAZkQk%q(PyCO~uOkT587`%*R>c(@%-!L6bkJ-$Ui
z@hE(WV7#4EKUv611Ij|=WAkf6#fp#9b@WP>CkIopuwKe2XQUAL#nhY~UCLOPc$N{
zh+LqoY{EYwY0tFkXh*<1|4I7x3|LNhpGgYzHqtgiiKvl|nP>oweOW7m~Ku&WQN#YWnH+?aBl&1y=#XX?cMr)1AEgM^9Q|S#_M3b3cgjL6~wIA7M4wv
z<5PvTB#iq#PR4yx1Dk&wUB|s9QWpCNlXrI6#rY}9x60WtSNORX<3+Nf>12JVxF#U`
z0T!(DZ`3_pBDz*XMr=hsbd)tt_h}Z3*$sr*1)2*gc(4nX?8YS=5<$B;s+@3}uE###
zTS7ztQQ8q8QF~M37-eO5bg7Pbvuhl#2{1UVM`v-^yEqI)mMPI9ix-_l<=vE?$4C4L
zRDYWN#i>#024xEcne88dH9T6Gh-GD*noHMAg7rtR86V#FeUDk3M2hv8f48gf+IH
z$X5Bjn!q-7#bf<_RmC$ix9Gx%CogSjt6R$XW&N&2z>O=Y?@3<+6Bp*9sfBP%?_I$1
zdGYp5F*;x5Ygs(?idhj=CqOnLtn;fUL-8Xw>egDWw=S#=3)J2}C-B^A*KV`bAP1L)3QoMU|zBRO2k6
z)A$}9N2dKW|6Xetp6b!4y)*FWI-Xi=@&lDx(aW2*>G)N@D6uOL=aI(DN>t2E&g;I;UA4~-i~f!-nURPZ_i{tZdYEs$kJhQE@;TyP&co#-qhnPFfN
z;Y2_#4tWdlLPT7A*mZ;jf#gKxpi2G*mysJ;M4bqv0U5g*@-69=D|2!Y0QNP?on~>w
zt~`B3+lG#SDWU$#kOCJ!8iU^s`x2mvx~ec92lA@Ph
zSO230C~|uJgtt4wvBOZeV{pNkGdY9a1fQA4t;6fe
z#6ArW2R=LyQ|Xh0Y4c|~`gVD{U*Eq$lPi16I96sC&L}4v;t3{J2}eM5*L{$^yMhy|
zvr-}wnQ~VB(dPs%K%=u*U=LnSebA*@f-M2q4L~PKy8^gx9QW6Lfy@B%vI;nq9c8hL
z`U6?tNEp4AGQeudtotk+ILE7IJ6t%8jvqd^thT{Rf;6)bZm2k{FsO>u)MzmY)VyMe
zlIz*35mcKXAH?w)Pv8r=&4Z471lF*wr-{4=C<4C6`z}gwM1EEKRzx#h-dwt2%h`DN
z@4(`bHjPIL)?IKh(CO>~Nd?`kBEccuk^}vBPyY@ME^eCS^R_N7!|yvy;go-Kl@d_Z
z7W~7maMAsYlm@s6d;GakVbruD(HC_|m-ZYE1PzL+ltUFUGtWX!!Ok`mKp6pe(lZ`J|k(Vme?m}APU$nOw~|u
z-G2hM6A06e_014iF0=dPb=n*WXFirwiv?1NQQWk2HNo+=T`Q);@&g&nTJ+Y2Y6@c-
zA~z2KG61o7{R^TX+%&t8RVkXpk^K%H?#MD&{Spv$iaMxadRue!n|nQ(LB?x%xopyp
zc5LKth!x^X?X4D7P!N}&OGr8RA10@O+}a|M?c&cwgw=xwfy87
zM(&Lv|Lq0!0Zf|Da0_m6&5|eW>K`EQEsf*DTmumKyRXFs@^~J7POuxLVS$@%$vE5y
zF)}rmM>`ohB=Br-4qL(~+SR-*N($5Wz4lgYiZAE74ou-P`n+PhO(yGnA=mw%$;iwS
z22Yo5-T~Nr%q;^_yyy@Yunqcs9@(=jd^^>2wRaQpRou5>VgmpztW;=<#~6FkD;|B(
z?Z-@R>a82(0OMoBtDebdqQkUGJyD1w
z%n1VAU}h*|&7?BZJ9V5$g*Arj*Z9cguszGj(QeP$Bo
zcKxq6%osVwH)x4FFdbV%48OYtz0Q?aWzbn@xe
zGF>>Be$$ox%05IAhi(~^*`xD_q>rt8A)|eed!qt>yj_X{F=p7|3Ov5(0w|G?OXSjL
z0@cpiuP(ohg5RH$ES1ezf=U@g_8o
z20C_7bX$UDVW0snPFUOaeCXwsqv!HpH3h8y~O=*v6M&GpF$->|9@trtIfQ3u?mEuOENFOdC-9q9U;a+)zL%7KA_
znr5xc<^`vlEsRTwPlj`2Si`S!$1%wVf{hGuQ~ELz5o-!<3|(55H|qTKbac{wCmxmR
zY{~ZoV!ycCA@8l1-H-)73I-d~Z<2WCU?gai>B?mkisFPvG9Plf3=Z*
zexr)x{fqF~r#3_90}t+Hy!ksKi1cou$5VK{Puk~r7kMjin1)*=kU#meVZ|QEHZ3jQ
zFfRo8{%zoo4`F{H>;(#U!`d-e%0=t^`}M`wpI$Z)8K5bhhSb7PnS*ii&7pM^K0Bx_
zd#j1f-^ReQ0fHjwzFchDfKy@%Noojm?QXU6h0Hf8`0b!w#$VsxD%0sCSac;H0)bh`
znunAGNaGt_o2BkI+vg!xeGnI2F78g$63#M@Wk#HdBSEm&re8~ynyf1t`AC>?zhseY*!@@?RZn~;8-OIlXidJu1zU;(8;|J&Bq5=2FUmeQTdMWZ12HiTIr06=Lo8`z3AVSC0RvC!mwRPwfnJL2!
zs!V-?Oc2}YXb<7!P8PfJ69$cZ!-{^vv`>#;qc#`>?@v*n9}xI}cK~4ONq90smBF*o
z4}ZZG9{bO0QI5~3?#0rx%=O4=66G1AM^78FQ!uo3bWMn-*bNp
zj*`Uh07bk_|66e9U`I%7-MY}}#RCDCjh@Q<$B+hrTR&q+N8EEv`i|%WqV)t8J5pHT
zMir#XCjCig*n0NLY-*hRaA%BAOg^qh0MC0Aq@=I`BB~@LgJosmr9l7Xs(v1
z4E!|jwek=~KdQSffRS@m^>M_y7jL<*PpqCIhi5TX$D(mo)SqOWB25oKh?lY_7N!=m
z6#hi}Aa?d&E`JRhJz;7LvoA9KXFh3((7Qa`(I{Gng#FeljQwu?6^N%X=aZ)uf^MP)
z&Ty^NIaC-JQQ)ckz(fc{{wf&8PDRxLIX0PogT?o!Cx|KTo_Egq>wFmH{t;$?lkq-;a)x%3pGIWE-0
zCCKQb;FjGWb{NR@4iaI^Kz`!wu_k2K;Ej0>dSyj7?Yp
zA=x4mTsZ9Z%;Z*Q4t&{H5!P^G25NHAojda)>=g1Q({spT!k?-jj!L!(oUC`R3|b(LFu6z)}dj
zb)En6TyJS%@Lqw8v>c3DKusSpg91@Sc*lKZc-rN?5hd`sNN6i{(>ES|y3*F4&ktiP
zrIXr3hakO(iGJ@{FRhhp@9l!
zz(d)`>J4zSv;D3E$x<4Xyh8$c>m2&B78==Np??F~NHep;=wEa+03Mi|30B9@AzR2f
ze0w_Nin;Z3;3L>J%mXg;cH2y@m|~ClM%ILseTV>DakT2zHHV)42#Q=r
zvBY6ojs{}R-5Rk*K7NcYWh{~;rbN@<@^s8w!X9SZj=&XO03rA*#uBW4wdNKj_Ox%7?f9UFYUF&hcI^pfVa^
zYe7_kXm2vlAGgK7^Sg(4fyC)dd%Q9VTyF8ed`trro%y
zYdJy5)a@A7W2vD{+C3i@9?ir4k3_`dks~CW7o?vb?WjW8Mp0Qfd%ZWbhPVPQU*$&N
za!LVs`0LfjYp{fs*p7zi5izW$Y>kxPNL(b0GZh7gr)-zqg^X$PF(I$^Atqf6%Tn9a6Isd;+LHibQNTbj7dHSC-?F8EnILft
z(pbJuK`M`s-KcQ?qEx50kgfaSEbkj4U?kNI62s;#QKcVg<#}8tphZ4BkF;?Dd8Cm;AqLHdE1+O?
zlz-{EvVRHbGdDTOaNvk4ZR?22VpE=HYszY@|x|^e0WCp)h9pnoU%EcPe8-6g?
zst;qy0+uWg4|8KzC<0`T{$2q|(1uSY;c>xIYk$kV`0wB|Bk+RYNZx+UPFVf?S<}|M
zn!`w?#8}F>R+%gs-5O%_|thGOo%;e(}5v2;-kOljI
zTo%nJR}I=G!1s_3s*_NpG~S6u3U@xZCo@0J3Q?{4e9Nw6PtXp)tpUYe2|@!vHrD&6
z3_K2jA4$l;66{ddZ2{1P`BxJ^5QFMbpP=$UL^)N>7$%wj_7x=^*e@X6j*v^SE~#yT
zK|T7tsdQ+g7pgnq1VRcK&W$WYQ=#j>ON1nBDv%A}fDol4g_y;0nnEKd_~Fq1;~|`C
z3TqA%2WJcK9N>_cNFL*NK(YX4Dsq5J>dT9pH6lT&3(`IK5N{NgTUrN@17J2c1*x+u
z%#c8=@&GVgOGPDAKd7r6A0Oro0US$UlE+N57#W0z$2O9CdmlQv
zPidz?m^LjceXwe3lyoQQfAZmPku4pg@&s~lKCtLs`7k}04-nYnDwR7)+?(L_>
z2l%#|@Z|YWVAZa0YSu1t6Us9yA^5?!I@1Bh2Ak}ms%F(5*SWJdrwDSZkY$IpTxQ$B
zx^Ia)Uulzk?|;SW<%t+&okPnNQx
zJ8ov7?tq+R?*n-6bryJL
zP(TH}W(U17F}o{mE|_b{dG|lGLB%kFFFC+6g`gAV
z4c)1JezL-==p%8izVmzVQq>hlzGMgnf@-}2vrlw_PmnIrQ$AaY@cj(0Y~DKngjm(V
zC1z0Sa$-Oa)%q@$Fnx;NQcLgGbb?4BOt_oDj95$yOnUHGQPf2T-cd3q$19qk}$mJ$`vmHs8a>sXd$%@Ut`lncid$K
z^0EYes{~usIsX@syk`A@a2lTj~HA
zV91J4ymsQsP3u?2Q@GB5X`sw22$XvTT(Rv*57-A;hCGE67x%|kvc{(kdI~&DYzOCX
z0FGjnXqoWRJQt{2?BYV>t!qZh9MTd^s@+M2pTL0?*wLgp`#!^aGn3AB1ahvB{h|9g
zku2-`{m>0AWz-nUK$odQ(U$Hfz=X1S@TCoLHM)ZDhUvWA^?C_DR}#w}U}&{?HuIbS
z^rO@HV!9>}K*pB|(q;bX8##
z?KIOmB-nfwP5uDdmiZ>N2ny6n0D(LZ^MvjXL(rrO+<P>+`xgcEQiQTN*;wlE8-6ws2hT_2&@d$!qyPiDFJ0a0-Q0W3p`UHB;;pb1F45-W<
zyePZM97wW>j(lt%XYz0M^Rr15$wq1)UL}sKA|xP~@$!I9QVj74@*VeAT^MN1_yaQ%=fQx=JFkx)b2&b+&yLO&_RNL3p?KCO`o
zeEAZ-bjAnm`IF9zLS6u1u6}4M11J%LmC|wGsO*H&w+8%DoJ*j@gB#zq1C>2-j}*~d
ztjHZaBtM^WALTfWj;GkD@rZ_zTZpx(TAH~$%+;*3;yQo$e06j%R9HMuJoA?IwiC1p
zxcao>j!c%e5Mk_86Mjpt+TxUQo51zYP^a5YF>I@?t_Jj8~z*ex+qK_$xpn5M;|N
z09mqoqrcnTzlbV3zz@o!!XtNTgWbtP4TW=2lULbP+!g~0YwcJ%;<@kTTTEI~I
zk8>a*xZHhCs^R#H@4UOq6PBT(nI?S$IR(r!OQNtNC~Z%;v-<~N?l!ATOIDWK6HX~<
zLx32f*m>=$!6P?(k=EM{t~`3hbLgpcU`xQpfm2`Mi5IrHf94Os^-42^4~&IF#chxU
z?eo&}5JKd-)z4tAkeO2e`uwLV6--3sh>mxOQQTF!gOC^cHWnlSrHThMm8lflzW4ZY
zVd}UDJfiD=HYpJxm`;>AFvhoyetWi>IQO_|&UIYr;+hlOFg*!3d!)=h8oIFjF25+B
zAnob=x)bc|(fZxx$v0=G^#G9rXl%z(ML#j50k}iQscP!cxuSR%9ry^P>yf@C9*Yy$
z*uk|FsC~0Gf=;3@uJO9C0uf*9&}H3+OEMi|Ea>m+$iN2+B#a_>VRNJhN~t~jtIY{9
zVpbAis&`OUIga*VPvF~aRIj=%_XXJqhmLqkOFkR<6*tJM<|tn3Ye^-KVZJXAU>+>$
zVh~P7PW7X48bbVZgJJD3+|Q%Y3T!*_ZOG0HrD@1v8#i7C;Bb}nI8H50&)~HbfY&f3
zZ{MMBJ@lEHpnpfaEeJ6~Sm=F)Q#+UBemQvHd-L5SKN19H0pKf`dOKxqLgvaY!nox*
zHZWgxg=wh7%}yzREI_Q(EIqjzHD>!93g=(0sw6y3gvC7a2S6QJ{CJH(na7LiHl>hZ
zB8qh>wJ|wisyf#fW>}}3)MJ|bf;Si8OFzb~R#1ScGIdF=uQ2phCWe~TRVitLQqb*s
zeHMk2HCugs0rj}u$vdTv8LjFX()QuibH_#(M3!yjO+&%i-<@k34qfC|F3UYrv
z+)`skn@O)zQ}1KC&v3qHe73M#w!}Wmz0Sx`lUu%B=-%gkT?&n{=X<zBD?rq3@_y9c|BS0X0B+$UnIbKU(u{)-K9is|pPP
zqsNCQG{_d)RvssJG&XHHXVZ7ZoJmMuA?!ldXQ$3=veTsdh5Yr~M>lY3W>f59knj=#DaWC!x>WpSJ&$
zh*ldF8hMUt`J5mv97;EomsHQ71vuF_WB7r#*7No98(Fq9dE9+)5KDnRk$hd&i&^ku
zufti(Xtbf>a&}oyV*tgbbTRb*8_DyOb)7VE;|5??!GF8a7-g1-dMbcSqV|dqCOz$B
z7T~<(t`mK6BPjfmZ-eR?bz66|+*`vNeu_`R<`Dc)XjboxqHzP>&68p!80zh8V2fYb)wPVW6&}kCtgnF
z$C*FnkAAMYSXD+=WyW}gJ-G8vXv$00KchDeAI_KeVr6{~+ie^5Qwo{!wZ5;yD<
zgm0`xe^EvPUE|E1XAnl?x~@qbRY~_3;W_yPVBdC)KM2oRV9~z&S)2e0s=w(lkY=SK
zKBLJdiEv3(7MDmSR&1`|I~0m1koP)Qmp+W+U^Ye@(rfiNpZ#uz8A>0hH5=UzSf66b
zZZl=FYx#2G2i5lX80vs7foLx%{nS}>q^`kmAp}Mp5fM`)c2J
z;lw<98#PDh$}t+cE0!S+xDQyG)4+W{>&D9u`5kBn-BsD{Ct_i}72SX8Sq}44dtXY0
zfH9bocdAbz!isFX{N(2Aj0a`V*kQbFSo0mQasfO{5@EXFuuDQ*P_S6Fm=*%6mZR+c
zW$p^Gr#Zi#iYW8H*b~^2=gj;PEuLPOkJ_@F)a7G$4>atpH9J3^>R4`4^h!}8-YD
zWQ^(flKYtW%UvSoNEgmpXfz2JC0$ZTRrD443-Zp2x_A@kme11Q&ivk;
zWelgYA1K9RzKRJ2%<=ubCN=J-*s>#;ZaL5cZ={*H(xP7jjAson)%f!__p&YofvrHp
z?tyD1EWz^;)vI&gPjug)b)g+f63~f7XOQ|tVak6nu<->8lcig&qX_2%+|tw|7=`Bs
zUXQ!(dL92~h{%N2q^H3Y7Bn{y+D!;1VX0TskSi<%h6rhBbk+vhd|gnt~DwxCWo8jB@pQk-2;q@)k`_V_ZudFjUy!C_!&0
zdhC*yWr@SpveSG7Xg8oW%0$a7&VRsf{d=_Zru<90xX;`%Ox@Pt1M&%U0901?Z%Uqi
zwp8-iC+T!-ik{G36POf$YqvV3U%e78(76EhK`N!W4q0NyDi-8tua(SMJ08$a0O;%9z1`Sz;Y+AQ*8I|-W)h$Ib&I!Kl7C-C$!bqLl01<
zmRk?U1*?#S1|}-;fmi-ds!nJR=O)a!h9dn$vk^E8(+Au?&h15IT)ea+NxE;o-uMSR
zp|fRHSJbT6M|Z{1>nR0fOkz4u5aA3ipc?WO&p3Uh&)rg|CKMD9&n!L)V18y+T8zDU
z)H5V<^X-@Dn@A+Ymt9fjSyEM@q@ud)efIUY{oo_Lc0du~X7xVKtK4aMb7CWjf$!Sx
z@!I|En@>!$jtu$uCx`ySRw3J#**C@`Oj0^J%r0(!Jh$RgRH-yM*MD`G0tcdX4Hi0e
zUy26Ktr7aU35FMA+lEgH)t>*zcL|f7l4i8NAmEOp|Kha92KJR&3Z8>1{lO88$aIwy
z??kN8aWs&N7noNu69L{>;wzlC+rgUQTrH2FDNGMspM>MCw)AkUpL}q%VWR-kY&tu-
ztm{B@fX+mw5;26RRqyW!DR%+|gN$G$ZnD+J2o^D#43w6rlHVc3+d>R%TLlg>;r3X>
z5VXFS=u7l#lh?@P6u@EO2LZ@(8uLJ7q0IRjE~T^IzPe9=hgn9sJdIw@?oAv(GDXZI
z5CWQ)x^WEmABx`hB+=>3ucg1i1dU@hk3kn|yCCqVP;!Cswh^R;MM@4Kgr~*{dS&&;
z75^ulm$@HsFt6b1g5YO?kGHzY^Zb8*KnCqw{MsIysi^SI^*g>Ub5yLTA#`cz@-V6s
zDLpviPcbK=)c1510BgV)*$N#0=iHYn45(1Ew4%3R4%Oc)GTqd*Zc!27jq~U57o$#+
z<3)^o_RqPW&S1Xp2?sb~a9cr&OVcWMphwn&_h~n))^sIcsQ7}d#wlQet%Fc~dQt{o
z6G5}im$qodEYoSy{iQV+
zFX!n5>&_$`@3*>-N;LAA(=)QnxTpcJIye8dhCSU$
z-&0CkQ12N?pT)#FSOXkTb^oK1jflQAaFt)1e*MMDMzg34bFK*CY=)flyo11vR?0q_
zn~@rya&_q3o)MtVUmmrP0ALFDHCD^es`lQ+HIjt~4+Rs>-xwg?rOoQf)5o3o-!WZw
z2#_+Y#rX|tT-UUDI*!(cioNNIC)}l7FVDGtKQ+Aa;l42i)ekgNzv45_iQE?w(SY#5Yb09D)=JENe_9JqJWAu3qig;I#lHzl_n2i0yQKAgd@_|v
zw4b9-On2Yw0Hzcxco|OVUk{&;lQZ(LadWR?__W>rG->4Z)1D`%t00x=$tm^{A*{nA
z``}Xs=e^>;7G|MM4>_+hZc3os_~|8NL=UAU;h3P0_yw>Qlc;Xe(=4?-p9}?W#N85A
z7dnuPm_mPQve1aXFWsf=`>R7K+I}L10k6=RAe)-Ven^6G-k2khgYyw=10i;&OD1VW
zp?*P=C5uvr$Fmo0t5X4w(pe|;%2!pX(VG+LVrfM<#!j_RUG)!fJH}~7W
z4>>zaxvC`g8ihLj8c}yYr8>8kfgk4NiB!=lLTIiXVK2EpjqC`GOdCeqpJ1KYia+7I
zcglylaY@@#yY5dE_<);ctUT?i9IKdV5hi|kTHb-PGKF)efcy7(&8&UAiN3J?x84%x
zN*@>8z*QE=Rsqdq&^v`2rOXdTmRy6zTDFfCEVEBYnayX;2;OrRkq~EhWIIq0`(vx18xl{YP-M7g1~|+{jZe
z&z%Io55lP=X|fVEPG;5f(_a1S=dFrPFTnrJ
zety;VHUM}8!XLiWP*4%wv`nlPM&(t#87--_7{D6Rhci`>(Pk~I|8&!vgJ6w-bhkxt
zq}8(f`&s`*ZT=hJ@1*W#&|l6vgfJ)J649O2c;8#I)cLOd1|=io3kqyn(RB|pxAZP^
zHQW51u7;@uFos9elW0&?9R^HNRNXe)PS(0B?~nEB*}22<&t{U9Qf~sn1QeO+_x->H
zf-}#&exn5XC>KWQ1MRA|zzad5jNC>_V;R6@vID$IXLq8!m(u255De8hKlUhT^`^@A
z4kQ*l%By8`jC;=&Y&!v;ObXviB(CI$YpOPHY&x&^h39?o?ND@Ce?p78ghZ%V
zlIBRee5B$cCb>^62O#8BNc_cM140RW4#7Mww~DF}EoTSGwg#>*2u*J?xj>)L^r)xU
zcJr5)&!M*y5F+n|)^EPPc3A6_?U=atkVgL<0~YeVtbM>eKO+_)>#@c97vl!{vli>(
zioM5O6@M7=$h)!onwNRBSrMf*;tcu
z&9Q=>SEC{p3#
zwbMb9!WV~P6-dk5`i3F#0^^slrf~l6Sr5~x%aAex7wo?`-+fr!{my$(!kT2tSzH4v
z(TmB7NMkj7`jAqi
zVj^^eW^?;8P~wcv9FMYna=!`75GE0$;p^eUjkLy0*Rw}IZ7pginsZ1bsJhABVB-DodIZloZUq(G4tJFZAZ)
z7`Y{iJW*@3Rkx+hTQA1ks~hBQS7BWstyO6zU*|rvR;XBia=n!yqTKv>0wpmK3tMf0tCbC_RC0x8^|p>|7Z@x_e``Nh)n6I$O-
z#vBXf6q-7Z0&;|$7~MK^!aEoQw*hQHWbna_2ED7C4K0=7uM>DRnFK7lNTaSHEhVI9
zQolC2v?+h7Fq+P&R_;O5nlpqbRP$v0+@H{ECbk@+d;`$__t{J`|e_r0I2N&C%F--3for;t==Z`^~t`rPV25E8}upO4ASGxhGS;noA#Ko;gXo5(_18=^Q?!s!oAe<
zOT4@m%ik*L&dOka35t#BHvo0Yx9moHJW;fzeRo*wB+&Q93BNo^b>ZI*ogms-lD6&Myt1*NTacr=#&4LNAHQ_7Zr-0
z_7+UEiue@&o$AL%;gylWc2j#{O9fd!H4qs2%EN%UtXY`d^O7MoW|TH-Y6m9JRme6J
zI~49zbHnB`aXsE>&h69iB>MjoL)P@hJ>J2s!wHBP*WG`O-|TyBJC}Q13t*QI@KVxx
zo&84DIJ5H#Pl}>%zS(w-s!tqr%5Giv4^WCePW;q5D$A?vx7E^pqUZ(=S#em6>6H_$
zUgm!)k7y76y1XX+^_if)f(|;*vFkF|%OU@6VjnHL)~@|_`DDXwFXc9~;h(dCm#mq*hs6^&E8gU
zBD^w}xUj@>vt8FX{LZ-^rh8%Ev)=NqC{+tW*i;|hQppO<;J26s3dgpzNL~fNwVBs`
zpVCgg`0T3B3gFIGSt;QIc4$=9&QPaG4Va4dG4@8W6PkuE*pwkl@^M0gZOQ?P_c;UC
zUm_x7{)_4p_lC@DRe(Z`2ck=;=s6=ez8}j>*pV?_Za1{)z#H#KGBTx>*fTsQ?*#T|
zu}H9l<&6;rs7EH?K@GPHc=|DZ-;!t-%WRdGddR9-R?S{`=Nm%ugg0EzFqdk2sOM7(
z&&jVgT}N80xJ)A`$y5`SjFM&^#-97JN7kvcIz~Zqtb*Q2OSbh2>#nd;sqXvAjoatP
z1EX{c=SyCQBEfF3|5W`y9cc=MlKdVGo`8~Rfhf-LF*
zi06aOy(0;QRjl;SyU1V%9X@?Gd8kM$ow~!o=8)cq1
z?&`Qr&o}p}`a@(G{lXr)9mjFo@{|=j5g8^2=?A0-m?4j>JSk}x>%*H8Q+jq_AAb)^
z$U&p9#V^gpbDMnMyJZ|qTWnQodwXL#1clAO#!Gen3bFabmYooKGVvGIyYuJod-B1o
zXvaK@=BZc(EX3`Z;+xXyK6_IB)zp}|P>Y{mVmsb8
zE9g+Rh`oKB3z%e-CI51a2mYl3sn%hgNaOh}yub1M&8`sp4w~UgiP^Btbdod+GR0Ie
zMM!V24i)sQxO_O^>K6W52UWMf5L7J09)EV3Id`4^E_JUKH!Gkb>GJ(xinY+A2!431
z;U4sb@6>ab?dG3jsL4-nVRypKbpf29;c46WJqdAfdM~Z7`iv*;T>V+Pxe-X@)WzLL
z4h&vfHN0PlDKtUwYnl9@bQLFgzr64BHsxX|<2X|_@9=`$?CB^t}_8vdWe;Joe
z$eq{BZUY(!Op!fKxomTU))rh(B?DMHg>SY~$Q?IuJetez9OMN4{b?&9J
zFIA_|8Tme3jt&WJ5m0$&9R7&=k+%o*bv;Cl~7xDR&MU0n1#95#1=zdbXUk+Pui*?t0@p1YQib%Ue#*ReRdLRojy*_RUNN|HrIlUTPwXX~>O2%L>7L9Ktdeydt+3qm
zzY@%iEbqNXcLRf?Ek};PL#T7#`P)p{&{4d*
zWq;Y52f)qTOcy0f^DH9^x7t%bDCtWt{W^$C_17lP*OAOBNBg^?M@sp1^8Y4jSf&s8
zUdr$u*pf9aI3fS+JRW_-U1e@Qxu$F1HrnNrb7xqo7V5@(_=GsBs9#-WbXGp2V}j)-
zX_h_~$#GeeP>JTLB){w!o7rw`(-`M7TJBjHlx{(68}WK|gyL5I#l!b3tSP7%w2%6b
zY`!N>d#$^Qx##ngElcc9{vP4l{Hl=oTq{y>o=+OTNg0JcZmGqx;#m6lB?KploqlaW
zOxm{mLudm3rXTacc`#TomQznrId6tI8ZFikc_GL1)Ta;U`YhC51J>+jc}VBWN_8$l1$rrpy-
z@r?4XFGh*@Jx7YW;wHiqTmhTztI*9ll2YP$$Vgxs!#Ssh>Bk1Pbue9u2hpHtq$-eV
z)Ux$^D*@#yKGy1iC=qk{N1A=QCi7WYZHrKy95tu!8S${PPTb0qao|*j)_Ggr5VLdi&O9NoHSX6pv-y_h
zQQX<)#dGyhn@4)GbDMGmqEmla1#m}pcyY4bt^-nH+B;_%%g32IGxIsg)_y1X*7-d!
zp=%J^Tox|!cb1Ku&Wj{+Zr0e2H8Au|Znn|ocK)?JD2AGsPfX6nFh?oUGX6dDo&yJ(`l#fpzmKTYLlc%v`%WN(^$aI4;>A?Z|a
z?PUch{m7kMsg|qLj4ur;>gx&J-RP8~9RBtWc=rOUtb-&H#|a>@zv4Y2Xi>_|bG
zO0^N?E(`w%0O2pIb^b{Ft}vHcwcS|nRLLHqbW_9a&+jiR9LZ#|koC?hM@$PPO?m58Z9b%#DyF%*_30mFWoh@X4JR`Au)_kr#_xP_KM+
zQGAq{Ad!89Q6iU$*Na{k^HuWf@*WWsd!bozzQd=N>c~1#Nw*R&c#fw242xdWQaqoA
zXg=FIyOgjJnazF$SNhvcb;?ZuNju?_R7N
zlt-N073df$=%o2dydh+aHXNnAz?$goX{vRF6vnqT9DG|4;ozdqv
z#^|r_mkZh4V=P&$E4b;dzX>SCJ5t&rzG<3q{7&i{KP|5GVtR!TqiFZ7ZuW*wuWyj*
znKfoVocTJl#6}<9?)mRE65w`Q>$BT%>Yr{!pQ*}Due&J&TI
zgft^9byO3WZ3P!1^N2lFlkV(p&_;z`bf8*0tXoa3xs8L^P~`W^<-xnV?xzp^bJzU)
zguEu7({Y~+jWE4_WCeEsmetfV2nZa;k~CudQhTXm{>j4|%W9s6X7G?1Keac=%bPCn
z(5@@2j|&XYvleEyPbZrtLPRe{^J|;%Yph*%{Mu98-WoC&@U7=WspxT$=vta`D63qb
zv2E#t`P^zPk1u4Y>NDgrO`o~=
zVZV*9acbRyd}`@;$6W)#7tEe+E!%#hyk)2T%FDc&%%rT$>6lb2M2HT`ok6Qwr~OA+
z3ITx3?ns5ujEEtEi^_}M0^J_o5TDAuMMoy#?G+K1ynkzuUdGpx;2ZBTl+dOA!~m8y
zo?mXIHW#xT&U@;aQzDOKf*jiO`Z)Pe2JQC%78x^Q-hG`%?DkE0cXPg>B!o_fIhZhI
z_Q25NcCcbVB7ToE05T$l5=?*KFChUU8&dDG_4cP5_vvhdup#L~{eQ6l`CFQmguAR%
z$Rl&D$ttyL5MYJp--k6xzO|cjHl9?i$I6Z+|0sRb(4ORw4YAWB#
z{kuVDV-M-X&O;oE+flK`rm-x|2a>fnTDnxyGM8k>$R!y{Zkpcq>gVh|0*&s*=DBa$
zq%zEgF8N*aey{!0(Br&oc=aA8Kc-*@B@9(d(qEONRL9uiJZU2N-aNYHI~Tpd-#7iP
ziT+tv&6GgIy&p$CX_adx^&9ysURC%IzsL11c5e*Vh}`mjFGjLuCB@f^i}f%!?RFK+
z_B(Rmn}E!nS1ca)LzrX$b~1Ro6Oh8isGbQ@@J%?wpY-$~G9oiws*Tz!CUg1B`5>lq
z7QrleG%JyIHs6~b0_`0Zwte9xl^q?&E@^qtj7>>(U6=|O4z;PbVY@EhU;N|)$P@1sjo?Q47GB7F7rh~FWo<&7X!H(tQH~ETr<#4-
zeUI}O)$M$=W(JmK%k$5N8DftIo__a=PC@s=uw+mb8=I6f`31d=rI$i-v25ZlOBlMj
zX&qZP9J~iuu*S}q_VV3})H5mNcl*Bn{gqx*1EX=A0)`=ERlt<}
z-?#<0h~rEUS7QN)I5z4q3z%zW4uie0$VD#~&2#Ew*}p$~nP{Q6Z^9Kp?VnKvNv)Cp
z@vc)-*lde(&>T=7D8KOe|Np-$weDNl*RMrB
zCK7b;qt}N09sKt@AYuD|dLt%HclFPI9*-K4ZU~wJcA*yZm0%1BLg+Wim_&UN{{y-3
zB39>r9iJdOgYF2_8zDo_kO4vm8VF#MYV}bJcXkf|BoWL){rOsG4uXEqwrvpJY$AyS
z0@lO$7ML)Ilru=Iv{Mv=-F{zRP;EOqcI&i|QD%FLxqu~8?iRoj&i9beF{I*k8$=R@
zacTwzD@3iNb_4Q4L4q^E6*2<{BSe$n+pF8X*-G2LnNS#E!5QV|&4Dcc?C(sG%Jbz5
z+az-8wtx;TzF~cM6CnXQH)YS~ehWDJBVP_V7ZaFRw=i(0>^{Dm_?g%hUR>-BZM)KX
zw)0nkQ4-5!SOQfY2!WKMr;_9k5Tb>P8|K1q+6<;?;3kO#BrZ7@`*A{>j<@^*u4{~h
z9#_soy+BP8`U3nDL|ht%KcMn3b*P#At
z3MKSQaL>q)jke?b+Ph$j;OS8|Osr&-*0d;NSwKthVEDfDS+(YPG
zK0-(Gm23j@k!H2q5RvhHYe^3
zwX_l-#i(xWX>xm_c*(ChdkP+Qs|ISYFkb-LtGlTRypUalJV02$^-wh%AtNJv3%%*>
z+SR@IRKZbU)EKT({PBRWWx~vUd*vzsiN%#|JL|7<`6GGYn^l2NUEN^`#ybUKI9xm?
zO;&PEG6m?3Fz6$bx39#Ju|v-%Z@d7sCt#q5|?g9$=rj_31lXAp1lI4l@fqK
zDfwDBK_cNUu7|L+K4Ww%%7QzLO}Ck3CU8fpBgYLg6mPm^Q}D{#f-GCNg<{~Q`3%clR<|F%Zg=91$q!6C_Zc=)^?+&YeD
ziRB=0_t7jSPEX)u5k{enU;KgTej<ftg1$wXHh`v4?d<$pr#>Z8dyxa7)MG_TSJuKXVyYF>tjFHNvIwK6o
zbO`2h?goph@R;ZFy)xK5kT;zD6ZsV~V5J9C^40%*4F?NYwKDt4p$598qW3s$#4b9v
z8X?)fxx8y?<~WTW@6hVT%rAZsScGH~1e1D56}s-8_C}-n0QXV&O_mW_6
z5go4nK2qf#>^#a=di=-{CcZr;_pSTVS$!f)L8LUMNd8t5Wqiin76c8kHA6VOFaSH>Jf|Nh54jgDQYnsi}Mqhw`7}H(Y=4$b8Jk#repu
zU(*@$`Rn&U7_*ZhMXH;~*}}$|#p9Uj4h3s2ZujfODWB8c`N#9y4Fs-m9&WB^Yih;m
z?73DH^vlJbcX1|+J^hUke33VM-5YNff_`y<6D5sa-52;Y<~xQ*#~mRt`t#9o90s0%
zqiOzArdsd|;i2(SbpTJ*(DuRPXY>*!Pjd$ZnU;fDt
zUfVK_&Y;22-Yq0W*tkV7fz_0Jc&)>SyJ+8FK%L5AG-cWsaT
zp@yB)5#dnOe0|h=jap^&1iEzs9_NbD=0G6zx;^$q_OP+BF^X?hYAwKFX}q!nbX1UE
zFH$K8?ZT*naa5rwuK7O!C^mveuR5NBXd(FLw@_(&UkGW2@;2J1Kfl@`K9zySHWgCN
zr%B8am|L=7I76iN{1yV{e;rSq$I`+lbqhUTgtEqi{?y`9H=MG;eIbf&PC&bwN5!*+<+Rqgi|LR~z=
znvdTR^n$M*c06)v1w{uO%UJnG;dew(5pI>XOjYFr&!Kej>xHsIimJZ|LQqsy)ol!s
zQ4aw++~Wufs|7Q<|HsgeoWRxJ5$?q
z3?~#?!Ds`}Hx3umrP6MowzOIyMfuC^DQdD^f2=E%nsg%j4Q|!Ez7#7H0twX*)-uam
z1!EwJhExLjc~3#)-$65xmIGNtKU`7U`{qU2#9WW^LR-&TAZ~I$p+l9uPeFEy55GJc
zq$kzkb07;U-7U{P0pI)+?w$MMZH>wgvpyA?-4H&=wn96G#!1o2rwtu1wY%^7O&6yR
zyUs~(+`SvgWPI43M$_#j>T)ob{a>w6Na_@a@aAkLwRa$72gXEwD}kwsHQT)JOx8V7
zn8C5}<9WwXNO@i1;=`dndPm=8obX@VYfY9g+KD&N9&4)x71a)hp%cBXN@Qpx#;e1>
zXLn5%r?eOal~bL*fQf4nuAZ~AhYcMmjOrJv&kAWh3oW<}Wo_IUdl_FQPbbBn?A;c3
zqbpH8gHKmMBYX%!OD`_y@BFGVA`^T$;LR(eS!v&K!yh}SYjHIVDJF}bS}Il6%C0+#
zH3mZBVK(hiZUefrBj5o^5;x%&K=+AM!v#JN*n5w?lx4YRl$CEQWl15ap?eP2PJ0LU
z-(<|>yEISm_Lbq6kfAZ-T>xHC+EIqH?*%a>c!x_z@2+#pIK*v_uz8Sm$YAsft~NB)
zzI&*M?u4Ty&-We5w|+TU}U
zo0W;pjMGIUdN}qEde9b>`$EPiP#M6>l#?c5zgm;LpL+Rs4@YRkN0-F;Pp9cQw;|0&
z2hdaC=${I?Vmujqz^7R9!>*)0HY*W%rSZ6H%L427zUKvkykcO0+v{FI_--1A7FRc_
z_lcqF6jr}{)w#ikchI!j#XY0+ipqQ
zx7#=cjXNqgi<#Zo2P1zY(BUpfxcUs_)19SjI8uc6t<0D3)h;fz;V^6lG=or6#85VuGU*no8zzH>CiA@V!)R63dRnZgpvb^ci;ceor^
zQ>&=RS3Bsnxc6Q18dy1l7o=X|&B?}m`9RmFU1%zw9J|*J^fDdHt1WdHN4#~NpW1}x
zXib!%1d&>yy;WZ=olk1y36qL<4J<%OKOEvi=f9x}8S-l{qcJ_ZK5{tf&$~hn)jpskLb#$I{>wR8Y%MeH}{tGjU-lLXkLzo~RJOA(79R8|6WgH;!yOnq+%nlu|}P67THu(Tg8yhpf~qGo&p
zA$n_J3Mo?f+qp7aU;`cZs%Ka3X0mz|5$uzf2;1Trio%Gzr(Q#rWTZxh3dxeF<<%}^
zKc@-}XrlCT*aT#(FXdM{yABkG30S1^?(otFn(G$KJE^Visxj
z-}5Uw{OHmRNpp7iadTH)h;)>?103h;|?@YB(}F
z!d|{Wn1AQ7{H-3D2J*px`Qp8)4Q{00k2H}TCvD;1^OIKdS(f+aUa55!om6Kz-E9I<
z816$JW+MXh*f}`xH`$5T+m^fgajK4M%Q|Up%(|ct8P15Y>Vskm?5IJ6O*Y2VtCdRU
z|32$D>TjZsu8k(rfipi>-mK(22a&Z3q1*mFxUok7gRfyJr0Fe6zWy;W(gYaJs}f_=
zQlW)%nVDp#-ktcNOPglYx9k~ILPzg64Z*V8ca*;P1dqx{CMgaYO_IQlpC4eC@3d5z
zEOZh=`^;^sd`CHwwyYkJIc$$s6HfMLw?0D(<(ib4jPa*p
zsn1oLu{PaL`9adY8
z(CNH-_w(#=aW@HwxX}#}rgI43?px!+eoJ{Fd-C+AlBC_AWV4@t{Ic=V`Ir7{0>{~i
z*{{-pXf;JLsV5g*4f#phME1SFHWG_r>sidJ@bCU8MzEmvLByoUPP+W$TF^sHm9cNS
zG%pi=O4<=ib}41+*&M2?F|mzILuX69=J3fdjXTmoiR3jvskqRBUM>U9sV5$?l??3L
z9fOSo4x~%jZRsvmR(}1|l1IU#V=}*aXFC5253Ia3N3tG9=n98&;5I!jWE~_mDgD-%!XguK+6V*;V4?JLu6vw
zAqV?q6vJ-0Sj^}|md}-Y&-@rJ&g#2XvoE~jOFP%P-_vIs7r*@qDB<-U*8N-b_@BB$
zDXhII|Au$t^KmFnZ=u?$s5V~R{>PKkeYU4KT;UQ`2wwK4727dVKLjKPytIUhp`=_-
zH=3aiN(cnpj{txg@f{^T0^5J4A5PIUSgQGXe7~fP)efQlHlmfXr-J*aMMU3$XuIS4
zhg|`Jd0TRyB)hH#^f2>!r)Is^Hc=zI!|Hf3-v6x7Z2!iX+}V=Xf{30m?d{Va0DB>P
zVec43|E6B=bIT*4jw_>}`OCEQw>K;bS?aE)x*=ztB2KAEJ@dRaZC;nP_Q!OD
zQJ6Y1Ae(=|FfBDZmcMSoozUIR7XjjuCaWh%jUGYqt1p#cV;cu20J~)|&9J!pn=070e$o+e==&?ha}C))}eKJ`oQ1@20Pb
z(6y1$o79i4rFKp^svXq=B6{V}v6DASw6^DUqQ$&4JEn3ZQsDXnNvvo+|Fa7$?$ACZ
zkB9ArlpM|N{o9XbUKd)gXz_(JhC8f^tqnSNrGeQ+v|LR;b0|vAv>lM}1RQ13g%MMO
z4S2aX5wpkq0aM21d%?hR6u&~D+_PNI4Q+-T?bUKBoqaIXWNpUy8>cNRb@dF!1Tjrn
z>nM{qc0wNf4z=p`!lQ3v%v0?CHgdr&a&CtvOYM%;{p8s|tWr9u=o0NqE{bWs*Q|%R
zQCh|+2c|G7?!rfCo5#Z$)p|DgOyum7nS@OEqq#+WvTe29ub1VD{M=xxdW^Xi?X6xW
z>BNIx{n+J-)B9kA!zauRi)O`H&%f?aDE}wrum=qS;qe=K09~x
zNiNNUgAYgskC#n84@!NjJn}uL;Mh`VOX^v!S3~M8xgF!gF2S~G8CE7a`L})H+ccw<
z1q{RH(F=emITulW_^ScOpH!D@0#9Wtp-cIf0{b5iY!(jNJcJ&CSl_I^k#>cJ
z!E^>afEL0`{~^OPqhIkqW?_aO5DlU~x?3U#9F#984p_;Z2%qc*E^!Q)HD@tgphwOE
z3;gOUqLwf=nBWousF$J$#tVfo5cZPF@0d)MQP9G|Ja7)m&BXBVg
zHWA4C*KmF0ZNey&iY^u3C65Bg$KiS_;F~)MA2bFGEC${QKr?=iAZE6h0|dysJz||3
zx?T-a{4tPb+)8Jox9^5{RHP0
z+4WPHjD&q{1W=q>W$AKBct{O~vZH|Cv`%ecazOsc4JLugrpN+*m;Z2=)XZw<
z87Xr9ivF$ldl{D?g27eWwGfc*Z@zW-*EBVL}`i@GC2JqtPZhANF80%R;uet%UxY0n6T
zDXt=Nxyeuj*>iq#gBbwM@|UXs)OLQn_Phs36uKlLI}M06a77zp_1eEL;GgJCM8?Vw
ze2`p;Y>3*fAHuI&=HB1Zh^*GzSXg~3OqT{}!E%YguvM9+#0QAd1nUp8c04PB=hZh<7P|~oa5qu691uG%|
zZ+;83U}>NvO0EN?@a!+8*NApfnYA5<;7}b8nhr5`rEX^EG>ot9CmSMF2R({VL@s0se<%Kq8ewXQJnPemZO8dKr
z56ambFZfS^h~{UjZH?hK{eZdwjC9;nE7e#yPT_?s;@qP%X(kTXat1sKczC}CZl7Db
zj=g!I1(rFQ|7TEmdF1_i3|Y#F)kqxnrY2Z5Z5qs-hM6ia{{1+#4TZ^-ZWd=#&^*y{
zOG@c%py5Naa+9;-SkbAC2oCO|}*
zoOIe;uK75!7N1XrFwz25-FhS^th_K65wyVBW84Bn)!OHo$+AUZI}tyfrH&HHmM#c?G@$IH!#U;J@KWV|D*%CUoY?&O^gd5?kn
z>sb-h)u8=R;3hKaEEgf@Q?Q9@{EkC9onhzcG8?p;!}pUf5i@+b^g6z0$#r}#5htn#
zKi~QM;=zov9H?_#&Z{`YS{AVnS9&%Ys(5AM{At|3qa5b^eY$<`9@4StM{VSi*n6JE
z`N0e5XQ|UkO;ugFV3egz1%1E-E|F1?Cl8Gtd!E+)3&`pgg`K1bM&@pN6YW#67$wd0qL?36quDh)eZssYAnc7{fMjs+K=XL*-tWh@?%1(*xX>VCnavQq2?iG$4qlO)MCum>I;2iz3XilnLBRe;{G3g!S0TPY;A
zoe~Q8RFTrJ*;a6fWl7ho5~ggkTVAv@oM3H{@|KOdhPV9@MiUM;l|_^+!`liAU=~`v
zYd76HgEkw7Odm#Oz5$*K4O`>iu1@+HDXD0F=n5
zm$@w=vj9h`%&L4Z`fG=G<1}gLXpyys9`z8_KK^q6Gq0BS8o+n`J7C}#;>{(m>a`}A
z4;-Ure`Nxcy-nd%{K{jshjZ9hUi<}lsq`6IhcxL2aES1Jdec<_oxsI7@|d9cH$0A{
z1S>vE^Tmw>3CDC-9@X=G+sU`@Q0@eJ`uZ8ollhosM0P0nwG>OavlUq2>-AHy*mY
z)4%tn*#OO$SSp1S-vjGj51iS`Ge;h(O^P2oL*h~N+UQHkW5?2U$S(tTdzU`we^8Hd
zc3_b2CK#tKz(hfB7g?~V`*zkYNE?>gcI$#yOeElp60UWV;X9<5uNh9dxb~;dvhL%koU0~beeSL|yVO*=E+UaB
zL3g!qRGY>&TD{X;czG}Hfye39hJv**yIWtqM!A*wo3)I-x!0L@S?r97
zQpbglt&K#MLa{w9)6a;8I=w^0der(SrsA=)AU;N4j@euUM73=KFz$0bZ=DS^9`
z;;c1_c0cyja^Y6KxR}`*gT`#FwxGt*^xHR?Qiqo#@sLqaQ
zciavD$iYuN#*xj3a)eoPfWf1A-W{&9ob79o(!ZSF0
zRgb6XfPQGI#FwoBwix{{!rlT?oz8)#vwe-EBV{t7++#L22dVU&L;{R**p0hd
z=Q?vJULD%H|5tub7_VIY3#H%SHkKTngDzaC
zMp3{v6Ym_cj?eGa9qF|jnVQt$ltUDBa_c|Nymk5TxGnDr75j4+g;Q6-N;bbXbo$HR
zaLh-WRrBRbd{#(4IEb6wJq$bJB6pJg$R5pXUJqi){U*ShrA>niC~)NJz64!`&}*to
z?2Oj$BTr5%KIYJO`RI6Ma48im{=`rlcjj{o8r1iPBT?jc&Utr4GX~rO*82Gc&*7Ks
zbZ={K48}RdQfltvn7Demj3%nEebfsx^Ag0+Dc9^j9vbH@nFWF{oF??;nwy}_;h$O#
z8BKB4VSBP}IIwBRu!zIqPEH@QP4Mjgz_diS6fNE$uyMFYCe$^PBsaG?$7l2i;KHx>
zWhbwkP_Y+~2qg9=;#BRmcy}6-D2;gK)v`?|aJZug!WEIIjOzP9e!ErxO
zb?atyxrys7xY0#dm-Ap--1-^*#Kv$6OGh=%7jM;4u9<|J9LO)tu@b&!xV>f9aK!vq
zYpVM#gG5R_y-b2V76
zdcbQo51qnzKlU2O=u!Blc)FB;fAqR!@=4`W(*v`6i6-V~DGC02F|m;2S`<(=ez`!G
zd6u6u{mCQGAB$X*&tw?PmjGiXM9pVP-HmJNki|jEX1l0+iRWJq@HlOHXyPV(;w_65
zt!@s}dZGDq+Fd&2H#;de8il;ID2tzAZN!~ugD0Gc`%OYqg!K0Bw_e--m`RhCw{Crp
z)HTO$GuD%=&eplyyp`i)vgsjXWQGD9UEAJ>B*mwP|CX1s)tW9k%yIOy{YU21!Rr#K&Sx$}^X2Z*+@mRw#1-_e|KnTlbRDu@`r&QwGxl{~+oGkl%_vn!RX4Hw9kcuXqsy>R$yvkT<1DSa&FaozaxfABq42}R`(ajyYdw0-3jPf6(36q(!H@u
zYvr8HdXQDQVi49^F=GMaGa{`>@4JxyOR!((FtB69a{GLaEC*iayrY=}>t&Na;q6dhpS?9?a}
zw^gI5q^7^#_|GDMSeEP*>tSf1NGbd$gK*EN?6KXPOC|z%wOWQtNBdcg%uUff=3)0Y
z(;tHbu9j!pGnIxw!ygrAEsBTEmv!=;Abjz2+=ZguucI$j%WAb;7p9|)%^*FWj-cnA
zD(p3+oZWqizxqDU((SnCfl?y%XZJE2fQ2ZJZCwea)Yay7QuO5b@e%0q#7F*V{-;t_
zdP)$)_bui>mLb
zgkCAr6F$1>n^JoF@374^9gg{JiuIwRpN8fQI6{7XI7xPNi)Ow3{XP1dq(ZCrJ7+fr
zY?3;({lIpOHr=TkhDj8jW;epOxw+u?=NQDwM?n57-n{B-M=F4TW&L>
zH#G`!d^~p-{~tbF
zRx0aQS>f1Z@3J{&vdfkcSrM|z&N%kS-i}QP$&PGMnH3S4Q3%N%_w)4meSi1;@9pvV
z=d(I*@AG;+$8}xL>ltdf5PYA*=NxNZztuAn@t4bc>r-Fs{D7($7)vG#{ZZ+?B(1tm
zA1-T|Ik`&D4~fVKLeTy`6#DtN@BBQ9x7IkTwh^KC$Ov(qAKfu^yY)XTU_R_JH<%pR
zrQuvwq$DwQn=b3rI(ii7i2PoCQf}RM@G>JIL{#pEIH)@aIqxx2EVd_3+Ewf0vSjRt
zHw6w*lt0uEnnl}4s!+T=P|6ksXShy*Ba7k!h-tFhpPp#^SsMHiN|MT}KrTGG{G0E6
z%&+;zfnf#*fR+P}w^VntEAi#-;#LwOSkj-2Q;nw*z5>i6$r-~aFU)thE&E3BG`05$
z6x_Z+7@0EH5&CIckVoQ|H-PN3hWA}L*%!@Rpr+i8@4uco0K_+OYrd?nv3&A;9hUpQ
z41s*r3e))RZ2@`&bdX~Qkq
zTu$4vh7Of1a5^MK#kdKO6;kpTU`LXR)^AbhbdtDAqp0)pu!~Y;LlOwdg&a(pS-xIB*gprB
z(L%GCW-W4|3O=oP7TLG0g##nVtYSDs=a{)4*5BNWc(_!01_nO~^H$zYVQAflzjdBj
zwpkT{mK|{t9`Lq_#Z9TU1eCvMc{7D9Eq|!3$f5woz@#e0=C_nhDz>!uk7X2n0+Vrv
z0UZZ@s%QB^_!DI0l~5-DPFH#;c8f;ynXZ1#e!GFQT9!DUr`TjARDb%X3~nJucTP=VjSnq9t&Spz7o27*MI;OW-^wGr*HiL51V^Q
zP`;2cE|YFT)EG>TyvPO&OO&fTi0Xh4u1JNn%cS{)k_;I{w^~VG%84ncUKBaIht#eQ|B{sMM-Dqeb<&6=~;ckNm40ghR
z^=9lNnEw=;dA_PSRM(2n(gWtQ>AhMO{eBe5WOmo9m>-#$|Kxjny1&!cCD4*
zj;xTMNL@>czl`=`>}=xSe33~eX}oN_m%7Z|xZ&l7;u}SsMDfn_3NXt8otOH#
zt&uigwU8KF0R7ZmnbNK1U~z&YXiT2OF&;rjGwieLDI2KCuEeL{_|A=!LHzDjMOk;|#`1|ri~Yk6cNUBjJl3W>hGZg^HPZ!=>Y_j76zqQqB{`KKe*vJj
zelEr*s0_t=CMi1bFjXxST;b4NMVLRU;*+^D0kU|=RS~^s(rZ`?kBkOmwK&RP85oEF
zIt~YGv|r@$XI$ln9KL;1?b6vB6k^vtytI6X0TD7;>1Eqtsc6YqoDa|d#
zdqK>i`2GA@xpr#ZwI+)!UbC>+BCH>)>!h_W0U0s+y@>Ht1%F_(kHiizf!Hl&pD;ux
zANZ#{a^$+tFUQj1#b_VhW+J@olP%>^7K|8Jm~}fcl6aZsVC5L?{#+yJ?<*c%-^tDex{+gcaa)kffaji?IX=o?i}$FVwZ&u#t1q+zP*
zZ3AWtbJU57Z5R&nAVfJ_gBJF-)3OK3gg?YQ7OI@5cKK96<;_BmVXQ9~;?TUS~q7%+V4$@rszSxU(SdKHS%Q}fA3JlHac>t6JYGjZrajsB;g9F
zFF@SBvI(vR?x8oZ-w#ivET(USI)
zbCilcSgFLQ!V$aw+D+G1Mft8X)PX6Du}>+j3*$46)oANE1$qp#C|M?U{ToW~^mo!$
z>oMdNrYCDc&)G!Decfs+(DHg;ee@d>VT59tR$F!=@SL|mH&?Q1_+-^Y7fzF7-59Ke
zL!@@9sm>GirD)Tn*nPdva1XcR!blA5LU003!Oi3@>L$W8}yMV(T#K(z2
zvB_|gNZqyD;fbyU*^KYhiu>*Kpm&e*5@2go6|v`YPDa5hmy>UHV`YX1@yw!U{uPtw
zz@@cgI%#>~AH;y_35hWV?d3d9is^DL%KP1(wE&Me~wvRlD_iv|(87^!)53=&YG
zTPDN}Je!rB)Oh4S6Bpx#t_7BHP-1tBAyOq{XY8(U8I7u|jQ{l%`cqEU`Yq~ljlX;N
zl4-86LHHfb8!lo_CQRwU4;UKQITcCNRm7uOkz#@>v+zAW?=LEX)qA1W?tgNd+W0zm
z`<+_mBI~Sf%Yn+2i1Zzug#G=ag*vR`c(o>S~5gIM2qpXRFC
zLkdpM0x1pGEb6T86A=86*1RZO$aFwo+MevbBx}RA>8zqnezMtUOZVd^OgmUV(6q5S
z0kT|r(6}CW7ZhjXgOUcBSI-d`3odQNoQNAp9F|bkmlOo8b74JF!nOGLw*hQQ+KQv^
zMObEV6hh0trR%oFcf$)js!IAiwpXxOUKeNn14-EmYXbU=ELPGdZc5`15Fp~CipWAt
zY=q^euZUnwHEiCBQ~px34Ra+h^rY(y##-E2W(*Bfson?!mawbZm!`i{g{Gea0JD1C
zZsc9jJE0rHWhHX{ilSAqpm|U}89-kka=ckLo1uQz?)y;{uRu4P?W;?cb@aNmoV7&;
zQl*?cc2-M9DKq>Mh%1UgECa!;XloM`5F6&$A)vL#WxhAOH)5F7GB18p`zD3e1KXmr
zq1o1X^6-r1ry|4mK1FkdlLQa~xz-Xz$2f*M<~ibBiFVw)f2W=o3AFT?#?k&N#3bj(Tyk_(A63vy4nB
z@2abwxH>V}5BsQs)yzc33?7ev!X_3#g8T^vFv1O^BbLo`=RNlCkR|=SW?Ii{EImb&
za!W)co7MH=mL)61`Ej>D$Fiq=>bqx*l^lM-PE#u3x@6l4teQxU?{Yswj6!#+1BFJb
zx+(ky^|31s??`URFBO~uI7ddC@bbem&Uo7E*v)kSmx!7hQ+v)KZjuGr&()lOrz8ax
z7#w2&@$D6cMcqWG#1?kJ%*9CbOw8DzKo7Ng7lrwCMQJX)oN1b`hT|BhX`06<
z>D|MUDaxw=71o_fr_XEI2A8a!$6!)5jYhEgncVf*1C%s&Z4^c!Vwc^fi-@e_@o4{g
z0ED^OsFUvV)Sw=)-lFE-eZ>*oF}nB>HxXIcSdn*LHS`lH7F#OHx4zx%jT%T5qd7{<
zjPlHkb9}FF36z7R&GKz|4L!N^0Ba-8dd>?pU!QzA|9v$`p8bRBZEb(sAB8LZv*y5&
z8ijG2tu?$a;%5<2c8TU3@w{Sl@sNQxmq+Zn=atg9XW;?^Lmk@R&p5>Y+>*H7!2a^`
z5GAk19ov~#gqumNWH{FNF5LXxxI{x0WkTBh_s(8AjK%)BV(9m=ugJE!Z*YI&(~Gk+
zc}bBPSXB-mtJ-}*uEKuC0aZ1F0WjomWRgmg~
z6OAnR_DvL7`uaTMRQa8OA3;Q`m>(2qPtSq)m2TCzLHUULJl>^xNHyY9>q8*fO^7~S
z&nN6bcm4eG^7k!8)9R1ILx7ak2~oRWK5+>55M_||Nq87RHc%>}?fxFz7cZ!L=gqK6
zek$v$7WHKh)8?33uD?EH?|jb@U3wT-?HbGvo<$Rs7oO&2Reo(Ok2|`9G$lO?hwUNh
z(wT0A51#4%)XqDwLWKIP8Ay%OkIUT~@FOZ)pK6$@3OZ3(e~62@S4R54M$O}<``8?D
zQt}pU()r&oT=1aaQvyf`S%ntYXT~nvxoN)sBEKvHrtVbM*Jm4upVY$C(6bqqtG!lw
zSa&3(m$t3+4XKY$jJ_{cJABkeuj`kIUoTcs7O-ed*LVq>z4&@q{k^?}0cnAw{`Ml^njV{AASV&_rk~s
z{uu^aE2ss{FObneWp0T>hn+l?KgOT?pifV+?9|~mwqQSjUjSN!ryz$wC{H&({@FX%
zqnUmdjyIX>1)TLX$ygKDS?t6sb7Jcgbga77v-8iv-!>cwy<$mJV<*w2am9WPoBB)W_}~S_ZPh=YI|;z
zC@Ooms1^e6z3=3TI34W4@}WLx&e_4-CqJfI5IDLMdwbLO^Po7jyWf!Z&UYx#OQo-b
z{4}lAd^#iqjn-q0d)DjuBWg;k-&2u=Wk51cD`Vh)SO9?{#+m%rZ|bAPv87J-tuFH(
ze61Y~&lDph8;iy>bl|+*Q-|r>ie}HFjT6x;(e@gsWWGn5mmPj^pRERdrmCY#Q$5>}
z8&f1lApA)%`HgsnbpAThqFjG6vd99ikyB7C^-;2O_iIy-lNS-8gPDsTHLS#)$OoT2K6chvm1i(@>a33BW8A14OK7y(ZYM2Dq
zg7aQpUU$6(p0FG)3zCuBUMDgW)KlM2*gi>Kz?B)5E0%%j(CTVI-j$y}=U>Jv=>?nZZak^_bj?N-Bo%$Hqon*xv8isfh_@1|Vx^XJ_y32#JVLNEGyV
zRR?_pIZ_X&|LL(W(CUzP_1gpduM=Zc&oD*;kmcW<9ZJ5H@UIJvZVNPok>hx{NZnM5
zD~e=kG`A8{Z~Jn8gRRf^Y;CEis60WChBYUF)`+J;j)Ube?wy$Y($k-Y(@zAyFy2J;
z!hGKdEE`C^kT`q8YYm-)iX=t2Ksts-ULg-`Q$Zpi$i{XLRC}PfYJ+KWkjrdxanG9p
zbPL+(w1k9*Ff|DcAhX2Rsi_5aymlZizJC2W@cS)hnCE210)$f)X&0k?4IXjXTt*ESZ=Er+!=V7m0_eb?4rQ{DnUR%09{bG&N-2`
zbUT-^65`YMHs7Gt&w-T$EG#%SA<)MbvWtsjjh53LddbeyW2cnN%oqrWX*A8C0ReV*
z>(8IAR9IRQyZQ%8M62V_*NRF?*o8)EKmoF78EM20e1