From b63e4c714b0e5c12b75bc282f45a86d97e9cb9c4 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Sun, 21 Jun 2026 23:47:37 +0200 Subject: [PATCH 1/7] perf: paginate list endpoints, signed-JWT tokens, keyset cursor pagination - Add server-side pagination (skip/take, default 30) to all unbounded getall endpoints: users, files, tenants, settings, rate-limiting rules; defensive Take caps on wholesale config/tree endpoints (feature flags, menus, folders, recurring jobs). - Disable OpenIddict access-token encryption (signed JWT instead of JWE) to cut per-request token-validation CPU. - Add opt-in keyset (cursor) pagination via ?before= to the audit-logs and email-messages lists, skipping the per-request COUNT(*) and deep-OFFSET skip. - Convert the audit Browse and email History React pages to keyset cursor pagination (Newest/Prev/Next with a sessionStorage cursor trail). --- .../AuditQueryRequest.cs | 9 ++ .../SimpleModule.AuditLogs/AuditLogService.cs | 38 +++++- .../SimpleModule.AuditLogs/Locales/en.json | 3 + .../SimpleModule.AuditLogs/Locales/keys.ts | 3 + .../SimpleModule.AuditLogs/Pages/Browse.tsx | 122 +++++++++++++----- .../Pages/components/BrowsePagination.tsx | 90 ++++++------- .../src/SimpleModule.AuditLogs/types.ts | 2 + .../BackgroundJobsContractsService.cs | 1 + .../QueryEmailMessagesRequest.cs | 8 ++ .../src/SimpleModule.Email/EmailService.cs | 37 +++++- .../src/SimpleModule.Email/Locales/en.json | 1 + .../src/SimpleModule.Email/Locales/keys.ts | 1 + .../src/SimpleModule.Email/Pages/History.tsx | 109 ++++++++++++---- .../Pages/components/HistoryPagination.tsx | 93 ++++++------- modules/Email/src/SimpleModule.Email/types.ts | 1 + .../FeatureFlagService.cs | 7 +- .../IFileStorageContracts.cs | 7 +- .../Endpoints/Files/GetAllEndpoint.cs | 17 ++- .../FileStorageService.cs | 9 +- .../Pages/BrowseEndpoint.cs | 2 +- .../OpenIddictModule.cs | 7 + .../IRateLimitingContracts.cs | 2 +- .../Endpoints/Policies/GetAllEndpoint.cs | 9 +- .../Pages/AdminEndpoint.cs | 2 +- .../RateLimitingService.cs | 9 +- .../ISettingsContracts.cs | 6 +- .../Endpoints/Settings/GetSettingsEndpoint.cs | 14 +- .../Pages/AdminSettingsEndpoint.cs | 2 +- .../Services/PublicMenuService.cs | 4 +- .../SimpleModule.Settings/SettingsService.cs | 7 +- .../ITenantContracts.cs | 2 +- .../Endpoints/Tenants/GetAllEndpoint.cs | 8 +- .../Pages/BrowseEndpoint.cs | 2 +- .../Pages/ManageEndpoint.cs | 2 +- .../src/SimpleModule.Tenants/TenantService.cs | 5 +- .../IUserContracts.cs | 2 +- .../Endpoints/Users/GetAllEndpoint.cs | 9 +- .../Services/ExternalUserService.cs | 10 +- .../src/SimpleModule.Users/UserService.cs | 9 +- .../Fakes/FakeUserContracts.cs | 4 +- 40 files changed, 464 insertions(+), 211 deletions(-) diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs.Contracts/AuditQueryRequest.cs b/modules/AuditLogs/src/SimpleModule.AuditLogs.Contracts/AuditQueryRequest.cs index c994b8e1..de971dec 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs.Contracts/AuditQueryRequest.cs +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs.Contracts/AuditQueryRequest.cs @@ -14,6 +14,15 @@ public class AuditQueryRequest public string? SearchText { get; set; } public int? Page { get; set; } public int? PageSize { get; set; } + + /// + /// Opt-in keyset cursor. When set (and the default Timestamp-descending ordering + /// is used), the page is fetched via WHERE Timestamp < Before instead of + /// OFFSET, skipping the per-request COUNT(*) and the O(offset) row-skip that + /// make deep pages slow. Pass the Timestamp of the last item from the + /// previous page to fetch the next one. + /// + public DateTimeOffset? Before { get; set; } public string? SortBy { get; set; } public bool? SortDescending { get; set; } diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs b/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs index eb39a65c..b45774f2 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs @@ -13,17 +13,51 @@ public sealed partial class AuditLogService( ILogger logger ) : IAuditLogContracts { + private static readonly string[] CustomSortColumns = + [ + "UserId", + "Module", + "Path", + "StatusCode", + "DurationMs", + ]; + public async Task> QueryAsync(AuditQueryRequest request) { var query = BuildQuery(request); - var totalCount = await query.CountAsync(); - var sortBy = request.EffectiveSortBy; var sortDesc = request.EffectiveSortDescending; var page = request.EffectivePage; var pageSize = request.EffectivePageSize; + // Keyset (cursor) pagination: when the caller supplies a cursor and uses the + // default Timestamp-descending ordering, page via WHERE Timestamp < cursor + // instead of OFFSET. This avoids both the per-request COUNT(*) and the O(offset) + // row-skip that make deep pages slow, using the IX_AuditEntries_Timestamp index. + // TotalCount is reported as -1 (not computed) in cursor mode. (Entries sharing + // the exact boundary timestamp could be skipped, negligible at this resolution.) + if (request.Before.HasValue && sortDesc && !CustomSortColumns.Contains(sortBy)) + { + var cursor = request.Before.Value; + var keysetItems = await query + .Where(e => e.Timestamp < cursor) + .OrderByDescending(e => e.Timestamp) + .Take(pageSize) + .AsNoTracking() + .ToListAsync(); + + return new PagedResult + { + Items = keysetItems, + TotalCount = -1, + Page = page, + PageSize = pageSize, + }; + } + + var totalCount = await query.CountAsync(); + // Apply sorting query = sortBy switch { diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json index 8f5f1df4..73b2cdb6 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json @@ -1,6 +1,9 @@ { "Browse.Title": "Audit Logs", "Browse.TotalEntries": "{count} total entries", + "Browse.Newest": "Newest", + "Browse.NextPage": "Next page", + "Browse.PrevPage": "Previous page", "Browse.ExportCsv": "Export CSV", "Browse.ExportJson": "Export JSON", "Browse.QuickRange": "Quick range:", diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts index 6d9a2cf0..485ef2a3 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts @@ -28,6 +28,9 @@ export const AuditLogsKeys = { FilterSourceAll: 'Browse.FilterSourceAll', FilterSourcePlaceholder: 'Browse.FilterSourcePlaceholder', FilterTo: 'Browse.FilterTo', + Newest: 'Browse.Newest', + NextPage: 'Browse.NextPage', + PrevPage: 'Browse.PrevPage', QuickRange: 'Browse.QuickRange', Showing: 'Browse.Showing', Title: 'Browse.Title', diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/Pages/Browse.tsx b/modules/AuditLogs/src/SimpleModule.AuditLogs/Pages/Browse.tsx index 8f3b7e4b..6017921e 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/Pages/Browse.tsx +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/Pages/Browse.tsx @@ -27,7 +27,25 @@ interface Props { filters: AuditQueryRequest; } -function buildFilterParams(f: Partial, page?: number): Record { +// Cursor trail persisted across Inertia (server-rendered) navigations within the +// same browser session, so "Previous" can return to an already-visited cursor. +const CURSOR_STACK_KEY = 'auditlogs-browse-cursors'; +function readCursorStack(): string[] { + if (typeof window === 'undefined') return []; + try { + const raw = window.sessionStorage.getItem(CURSOR_STACK_KEY); + return raw ? (JSON.parse(raw) as string[]) : []; + } catch { + return []; + } +} +function writeCursorStack(stack: string[]): void { + if (typeof window !== 'undefined') { + window.sessionStorage.setItem(CURSOR_STACK_KEY, JSON.stringify(stack)); + } +} + +function buildFilterParams(f: Partial, before?: string): Record { const params: Record = {}; if (f.from) params.from = String(f.from); if (f.to) params.to = String(f.to); @@ -36,7 +54,8 @@ function buildFilterParams(f: Partial, page?: number): Record if (f.module) params.module = f.module; if (f.searchText) params.searchText = f.searchText; - if (page && page > 1) params.page = String(page); + // Keyset cursor: fetch the page of entries older than `before`. + if (before) params.before = before; return params; } @@ -49,8 +68,14 @@ export default function Browse({ result, filters }: Props) { const [module, setModule] = useState(filters.module ?? ''); const [searchText, setSearchText] = useState(filters.searchText ?? ''); - const totalPages = Math.max(1, Math.ceil(result.totalCount / result.pageSize)); - const currentPage = result.page; + const before = filters.before ? String(filters.before) : undefined; + const isFirstPage = !before; + // Total is only computed for the first page (offset); keyset pages report -1. + const knownTotal = result.totalCount >= 0; + const items = result.items; + // A full page implies more (older) rows likely exist. + const canNext = items.length >= result.pageSize; + const nextCursor = items.length > 0 ? String(items[items.length - 1].timestamp) : undefined; function currentFilters() { return { @@ -63,36 +88,56 @@ export default function Browse({ result, filters }: Props) { }; } + // Any change of filter set resets the cursor trail and returns to the newest page. + function navigateNewest(f: Partial) { + writeCursorStack([]); + router.get('/audit-logs/browse', buildFilterParams(f)); + } + function applyFilters(e?: FormEvent) { e?.preventDefault(); - router.get('/audit-logs/browse', buildFilterParams(currentFilters())); + navigateNewest(currentFilters()); } function clearFilters() { + writeCursorStack([]); router.get('/audit-logs/browse'); } function applyDatePreset(hours: number) { const now = new Date(); const past = new Date(now.getTime() - hours * 60 * 60 * 1000); - const toLocal = now.toISOString().slice(0, 16); - const fromLocal = past.toISOString().slice(0, 16); - router.get( - '/audit-logs/browse', - buildFilterParams({ - ...currentFilters(), - from: fromLocal, - to: toLocal, - }), - ); + navigateNewest({ + ...currentFilters(), + from: past.toISOString().slice(0, 16), + to: now.toISOString().slice(0, 16), + }); } - function goToPage(page: number) { - router.get('/audit-logs/browse', buildFilterParams(currentFilters(), page), { - preserveState: true, + function goNext() { + if (!nextCursor) return; + const stack = readCursorStack(); + stack.push(before ?? ''); // remember current cursor ('' marks the first page) + writeCursorStack(stack); + router.get('/audit-logs/browse', buildFilterParams(currentFilters(), nextCursor), { + preserveScroll: true, }); } + function goPrev() { + const stack = readCursorStack(); + const prev = stack.pop(); + writeCursorStack(stack); + const target = prev && prev.length > 0 ? prev : undefined; + router.get('/audit-logs/browse', buildFilterParams(currentFilters(), target), { + preserveScroll: true, + }); + } + + function goNewest() { + navigateNewest(currentFilters()); + } + function exportLogs(format: string) { const query = new URLSearchParams({ ...buildFilterParams(currentFilters()), @@ -105,17 +150,18 @@ export default function Browse({ result, filters }: Props) { from || to || source !== '__all__' || action !== '__all__' || module || searchText, ); - const startItem = (currentPage - 1) * result.pageSize + 1; - const endItem = Math.min(currentPage * result.pageSize, result.totalCount); - return ( + )} + - {paginationRange(currentPage, totalPages).map((p) => - p === 'ellipsis-start' || p === 'ellipsis-end' ? ( - - ... - - ) : ( - - ), - )} - diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/types.ts b/modules/AuditLogs/src/SimpleModule.AuditLogs/types.ts index e729ea2d..1ce2816e 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/types.ts +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/types.ts @@ -65,6 +65,7 @@ export interface AuditExportRequest { searchText: string; page: number | null; pageSize: number | null; + before: string | null; sortBy: string; sortDescending: boolean | null; effectivePage: number; @@ -86,6 +87,7 @@ export interface AuditQueryRequest { searchText: string; page: number | null; pageSize: number | null; + before: string | null; sortBy: string; sortDescending: boolean | null; effectivePage: number; diff --git a/modules/BackgroundJobs/src/SimpleModule.BackgroundJobs/Services/BackgroundJobsContractsService.cs b/modules/BackgroundJobs/src/SimpleModule.BackgroundJobs/Services/BackgroundJobsContractsService.cs index 9f4bf44e..222ab1ff 100644 --- a/modules/BackgroundJobs/src/SimpleModule.BackgroundJobs/Services/BackgroundJobsContractsService.cs +++ b/modules/BackgroundJobs/src/SimpleModule.BackgroundJobs/Services/BackgroundJobsContractsService.cs @@ -100,6 +100,7 @@ public async Task> GetRecurringJobsAsync(Cancella .JobQueueEntries.AsNoTracking() .Where(e => e.RecurringName != null) .OrderByDescending(e => e.CreatedAt) + .Take(500) // recurring-jobs dashboard is consumed wholesale; bound defensively .ToListAsync(ct); var now = DateTime.UtcNow; diff --git a/modules/Email/src/SimpleModule.Email.Contracts/QueryEmailMessagesRequest.cs b/modules/Email/src/SimpleModule.Email.Contracts/QueryEmailMessagesRequest.cs index b3d911c9..6c8f1769 100644 --- a/modules/Email/src/SimpleModule.Email.Contracts/QueryEmailMessagesRequest.cs +++ b/modules/Email/src/SimpleModule.Email.Contracts/QueryEmailMessagesRequest.cs @@ -12,6 +12,14 @@ public class QueryEmailMessagesRequest public string? Subject { get; set; } public DateTimeOffset? DateFrom { get; set; } public DateTimeOffset? DateTo { get; set; } + + /// + /// Opt-in keyset cursor. When set (with the default CreatedAt-descending ordering), + /// the page is fetched via WHERE CreatedAt < Before instead of OFFSET, + /// skipping the per-request COUNT(*) and the O(offset) row-skip. Pass the + /// CreatedAt of the last item from the previous page to fetch the next one. + /// + public DateTimeOffset? Before { get; set; } public string? SortBy { get; set; } public bool? SortDescending { get; set; } diff --git a/modules/Email/src/SimpleModule.Email/EmailService.cs b/modules/Email/src/SimpleModule.Email/EmailService.cs index 03dd53b3..f5009feb 100644 --- a/modules/Email/src/SimpleModule.Email/EmailService.cs +++ b/modules/Email/src/SimpleModule.Email/EmailService.cs @@ -110,10 +110,40 @@ QueryEmailMessagesRequest request if (request.DateTo.HasValue) query = query.Where(m => m.CreatedAt <= request.DateTo.Value); + var sortDescending = request.EffectiveSortDescending; + var sortBy = request.EffectiveSortBy; + var page = request.EffectivePage; + var pageSize = request.EffectivePageSize; + + // Keyset (cursor) pagination on CreatedAt (indexed): opt-in via request.Before + // for the default CreatedAt-descending ordering. Skips the per-request COUNT(*) + // and the OFFSET row-skip (see AuditLogService for rationale). Non-cursor + // requests keep the exact prior behavior; TotalCount is -1 in cursor mode. + if ( + request.Before.HasValue + && sortDescending + && sortBy is not ("To" or "Subject" or "Status") + ) + { + var cursor = request.Before.Value; + var keysetItems = await query + .Where(m => m.CreatedAt < cursor) + .OrderByDescending(m => m.CreatedAt) + .Take(pageSize) + .ToListAsync(); + + return new PagedResult + { + Items = keysetItems, + TotalCount = -1, + Page = page, + PageSize = pageSize, + }; + } + var totalCount = await query.CountAsync(); - var sortDescending = request.EffectiveSortDescending; - query = request.EffectiveSortBy switch + query = sortBy switch { "To" => sortDescending ? query.OrderByDescending(m => m.To) : query.OrderBy(m => m.To), "Subject" => sortDescending @@ -127,9 +157,6 @@ QueryEmailMessagesRequest request : query.OrderBy(m => m.CreatedAt), }; - var page = request.EffectivePage; - var pageSize = request.EffectivePageSize; - var items = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync(); return new PagedResult diff --git a/modules/Email/src/SimpleModule.Email/Locales/en.json b/modules/Email/src/SimpleModule.Email/Locales/en.json index 9209ba52..a50f1ef4 100644 --- a/modules/Email/src/SimpleModule.Email/Locales/en.json +++ b/modules/Email/src/SimpleModule.Email/Locales/en.json @@ -69,6 +69,7 @@ "History.Of": "of", "History.Previous": "Previous", "History.Next": "Next", + "History.Newest": "Newest", "History.FilterApply": "Apply", "History.FilterClear": "Clear", "History.EmptyWithFilters": "No emails match the current filters.", diff --git a/modules/Email/src/SimpleModule.Email/Locales/keys.ts b/modules/Email/src/SimpleModule.Email/Locales/keys.ts index 181f9fb9..8b71af04 100644 --- a/modules/Email/src/SimpleModule.Email/Locales/keys.ts +++ b/modules/Email/src/SimpleModule.Email/Locales/keys.ts @@ -73,6 +73,7 @@ export const EmailKeys = { FilterStatus: 'History.FilterStatus', FilterSubject: 'History.FilterSubject', FilterTo: 'History.FilterTo', + Newest: 'History.Newest', Next: 'History.Next', Of: 'History.Of', Previous: 'History.Previous', diff --git a/modules/Email/src/SimpleModule.Email/Pages/History.tsx b/modules/Email/src/SimpleModule.Email/Pages/History.tsx index 94dce3f2..8d8311d9 100644 --- a/modules/Email/src/SimpleModule.Email/Pages/History.tsx +++ b/modules/Email/src/SimpleModule.Email/Pages/History.tsx @@ -43,25 +43,47 @@ interface PagedResult { pageSize: number; } +interface Filters { + status?: string; + to?: string; + subject?: string; + dateFrom?: string; + dateTo?: string; + before?: string; +} + interface Props { result: PagedResult; - filters: { - status?: string; - to?: string; - subject?: string; - dateFrom?: string; - dateTo?: string; - }; + filters: Filters; +} + +// Cursor trail persisted across Inertia navigations within the browser session, so +// "Previous" can return to an already-visited cursor. +const CURSOR_STACK_KEY = 'email-history-cursors'; +function readCursorStack(): string[] { + if (typeof window === 'undefined') return []; + try { + const raw = window.sessionStorage.getItem(CURSOR_STACK_KEY); + return raw ? (JSON.parse(raw) as string[]) : []; + } catch { + return []; + } +} +function writeCursorStack(stack: string[]): void { + if (typeof window !== 'undefined') { + window.sessionStorage.setItem(CURSOR_STACK_KEY, JSON.stringify(stack)); + } } -function buildFilterParams(f: Props['filters'], page?: number): Record { +function buildFilterParams(f: Filters, before?: string): Record { const params: Record = {}; if (f.status) params.status = f.status; if (f.to) params.to = f.to; if (f.subject) params.subject = f.subject; if (f.dateFrom) params.dateFrom = f.dateFrom; if (f.dateTo) params.dateTo = f.dateTo; - if (page && page > 1) params.page = String(page); + // Keyset cursor: fetch the page of messages older than `before`. + if (before) params.before = before; return params; } @@ -73,10 +95,15 @@ export default function History({ result, filters }: Props) { const [dateFrom, setDateFrom] = useState(filters.dateFrom ?? ''); const [dateTo, setDateTo] = useState(filters.dateTo ?? ''); - const totalPages = Math.max(1, Math.ceil(result.totalCount / result.pageSize)); - const currentPage = result.page; + const before = filters.before ? String(filters.before) : undefined; + const isFirstPage = !before; + // Total is only computed for the first page (offset); keyset pages report -1. + const knownTotal = result.totalCount >= 0; + const items = result.items; + const canNext = items.length >= result.pageSize; + const nextCursor = items.length > 0 ? String(items[items.length - 1].createdAt) : undefined; - function currentFilters(): Props['filters'] { + function currentFilters(): Filters { return { status: status !== '__all__' ? status : undefined, to: to || undefined, @@ -86,25 +113,46 @@ export default function History({ result, filters }: Props) { }; } + function navigateNewest(f: Filters) { + writeCursorStack([]); + router.get('/email/history', buildFilterParams(f)); + } + function applyFilters(e?: FormEvent) { e?.preventDefault(); - router.get('/email/history', buildFilterParams(currentFilters())); + navigateNewest(currentFilters()); } function clearFilters() { + writeCursorStack([]); router.get('/email/history'); } - function goToPage(page: number) { - router.get('/email/history', buildFilterParams(currentFilters(), page), { - preserveState: true, + function goNext() { + if (!nextCursor) return; + const stack = readCursorStack(); + stack.push(before ?? ''); // remember current cursor ('' marks the first page) + writeCursorStack(stack); + router.get('/email/history', buildFilterParams(currentFilters(), nextCursor), { + preserveScroll: true, }); } - const hasActiveFilters = Boolean(status !== '__all__' || to || subject || dateFrom || dateTo); + function goPrev() { + const stack = readCursorStack(); + const prev = stack.pop(); + writeCursorStack(stack); + const target = prev && prev.length > 0 ? prev : undefined; + router.get('/email/history', buildFilterParams(currentFilters(), target), { + preserveScroll: true, + }); + } - const startItem = (currentPage - 1) * result.pageSize + 1; - const endItem = Math.min(currentPage * result.pageSize, result.totalCount); + function goNewest() { + navigateNewest(currentFilters()); + } + + const hasActiveFilters = Boolean(status !== '__all__' || to || subject || dateFrom || dateTo); return ( - {result.items.length === 0 ? ( + {items.length === 0 ? ( - {result.items.map((m) => ( + {items.map((m) => ( {m.to} {m.subject} @@ -203,16 +251,23 @@ export default function History({ result, filters }: Props) { )} - {result.totalCount > 0 && ( + {items.length > 0 && (
- {t(EmailKeys.History.Showing)} {startItem}-{endItem} {t(EmailKeys.History.Of)}{' '} - {result.totalCount.toLocaleString()} + {knownTotal + ? `${t(EmailKeys.History.Showing)} ${result.totalCount.toLocaleString()}` + : null}
)} diff --git a/modules/Email/src/SimpleModule.Email/Pages/components/HistoryPagination.tsx b/modules/Email/src/SimpleModule.Email/Pages/components/HistoryPagination.tsx index 60a2e4a7..6c0c6291 100644 --- a/modules/Email/src/SimpleModule.Email/Pages/components/HistoryPagination.tsx +++ b/modules/Email/src/SimpleModule.Email/Pages/components/HistoryPagination.tsx @@ -30,68 +30,51 @@ function ChevronRight() { ); } -/** Build a compact pagination range: 1 ... 4 5 [6] 7 8 ... 20 */ -function paginationRange( - current: number, - total: number, -): (number | 'ellipsis-start' | 'ellipsis-end')[] { - if (total <= 7) { - return Array.from({ length: total }, (_, i) => i + 1); - } - const pages: (number | 'ellipsis-start' | 'ellipsis-end')[] = []; - pages.push(1); - if (current > 3) pages.push('ellipsis-start'); - const start = Math.max(2, current - 1); - const end = Math.min(total - 1, current + 1); - for (let i = start; i <= end; i++) pages.push(i); - if (current < total - 2) pages.push('ellipsis-end'); - pages.push(total); - return pages; +interface Props { + /** Whether a previous (newer) page exists in the cursor trail. */ + canPrev: boolean; + /** Whether the current page is full, implying more (older) rows exist. */ + canNext: boolean; + /** Show the "jump to newest" reset action (hidden on the first page). */ + showNewest: boolean; + newestLabel: string; + prevLabel: string; + nextLabel: string; + onPrev: () => void; + onNext: () => void; + onNewest: () => void; } +/** + * Keyset (cursor) pagination control. Keyset paging is sequential — it walks + * newest → older via a `before` cursor — so the UI exposes Newest / Previous / Next + * rather than arbitrary page jumps. This avoids the per-request COUNT(*) and + * deep-OFFSET row-skip on large tables. + */ export function HistoryPagination({ - currentPage, - totalPages, - onGoToPage, -}: { - currentPage: number; - totalPages: number; - onGoToPage: (page: number) => void; -}) { - if (totalPages <= 1) return null; + canPrev, + canNext, + showNewest, + newestLabel, + prevLabel, + nextLabel, + onPrev, + onNext, + onNewest, +}: Props) { + if (!canPrev && !canNext) return null; + return (
- + )} + - {paginationRange(currentPage, totalPages).map((p) => - p === 'ellipsis-start' || p === 'ellipsis-end' ? ( - - ... - - ) : ( - - ), - )} -
diff --git a/modules/Email/src/SimpleModule.Email/types.ts b/modules/Email/src/SimpleModule.Email/types.ts index 2fb76a76..748b41f1 100644 --- a/modules/Email/src/SimpleModule.Email/types.ts +++ b/modules/Email/src/SimpleModule.Email/types.ts @@ -72,6 +72,7 @@ export interface QueryEmailMessagesRequest { subject: string; dateFrom: string | null; dateTo: string | null; + before: string | null; sortBy: string; sortDescending: boolean | null; effectivePage: number; diff --git a/modules/FeatureFlags/src/SimpleModule.FeatureFlags/FeatureFlagService.cs b/modules/FeatureFlags/src/SimpleModule.FeatureFlags/FeatureFlagService.cs index ea431ccd..956c7a05 100644 --- a/modules/FeatureFlags/src/SimpleModule.FeatureFlags/FeatureFlagService.cs +++ b/modules/FeatureFlags/src/SimpleModule.FeatureFlags/FeatureFlagService.cs @@ -65,7 +65,12 @@ public async Task> GetAllEnabledAsync( public async Task> GetAllFlagsAsync() { var definitions = registry.GetAllDefinitions(); - var dbFlags = await db.FeatureFlags.AsNoTracking().ToListAsync(); + // Feature flags are a small, code-defined config set consumed wholesale; bound defensively. + var dbFlags = await db + .FeatureFlags.AsNoTracking() + .OrderBy(f => f.Name) + .Take(500) + .ToListAsync(); var dbMap = dbFlags.ToDictionary(f => f.Name); var result = new List(); diff --git a/modules/FileStorage/src/SimpleModule.FileStorage.Contracts/IFileStorageContracts.cs b/modules/FileStorage/src/SimpleModule.FileStorage.Contracts/IFileStorageContracts.cs index d5dd11c9..2394c991 100644 --- a/modules/FileStorage/src/SimpleModule.FileStorage.Contracts/IFileStorageContracts.cs +++ b/modules/FileStorage/src/SimpleModule.FileStorage.Contracts/IFileStorageContracts.cs @@ -2,7 +2,12 @@ namespace SimpleModule.FileStorage.Contracts; public interface IFileStorageContracts { - Task> GetFilesAsync(string? folder = null, string? userId = null); + Task> GetFilesAsync( + string? folder = null, + string? userId = null, + int skip = 0, + int take = 30 + ); Task GetFileByIdAsync(FileStorageId id); Task UploadFileAsync( Stream content, diff --git a/modules/FileStorage/src/SimpleModule.FileStorage/Endpoints/Files/GetAllEndpoint.cs b/modules/FileStorage/src/SimpleModule.FileStorage/Endpoints/Files/GetAllEndpoint.cs index 54c6eed1..001350ae 100644 --- a/modules/FileStorage/src/SimpleModule.FileStorage/Endpoints/Files/GetAllEndpoint.cs +++ b/modules/FileStorage/src/SimpleModule.FileStorage/Endpoints/Files/GetAllEndpoint.cs @@ -17,10 +17,23 @@ public class GetAllEndpoint : IEndpoint public void Map(IEndpointRouteBuilder app) => app.MapGet( Route, - (string? folder, HttpContext context, IFileStorageContracts files) => + ( + string? folder, + int? skip, + int? take, + HttpContext context, + IFileStorageContracts files + ) => { var userId = context.User.GetScopedUserId(); - return CrudEndpoints.GetAll(() => files.GetFilesAsync(folder, userId)); + return CrudEndpoints.GetAll(() => + files.GetFilesAsync( + folder, + userId, + Math.Max(0, skip ?? 0), + Math.Clamp(take ?? 30, 1, 200) + ) + ); } ) .RequirePermission(FileStoragePermissions.View); diff --git a/modules/FileStorage/src/SimpleModule.FileStorage/FileStorageService.cs b/modules/FileStorage/src/SimpleModule.FileStorage/FileStorageService.cs index 56bf075f..101f8222 100644 --- a/modules/FileStorage/src/SimpleModule.FileStorage/FileStorageService.cs +++ b/modules/FileStorage/src/SimpleModule.FileStorage/FileStorageService.cs @@ -16,7 +16,9 @@ ILogger logger { public async Task> GetFilesAsync( string? folder = null, - string? userId = null + string? userId = null, + int skip = 0, + int take = 30 ) { var query = db.StoredFiles.AsNoTracking(); @@ -36,7 +38,7 @@ public async Task> GetFilesAsync( query = query.Where(f => f.CreatedByUserId == userId); } - return await query.OrderBy(f => f.FileName).ToListAsync(); + return await query.OrderBy(f => f.FileName).Skip(skip).Take(take).ToListAsync(); } public async Task GetFileByIdAsync(FileStorageId id) @@ -188,7 +190,8 @@ public async Task> GetFoldersAsync( query = query.Where(f => f.Folder!.StartsWith(normalizedParent + "/")); } - var allFolders = await query.Select(f => f.Folder!).Distinct().ToListAsync(); + // Distinct folder paths build a folder tree consumed wholesale; bound defensively. + var allFolders = await query.Select(f => f.Folder!).Distinct().Take(1000).ToListAsync(); return allFolders .Select(f => normalizedParent is not null ? f[(normalizedParent.Length + 1)..] : f) diff --git a/modules/FileStorage/src/SimpleModule.FileStorage/Pages/BrowseEndpoint.cs b/modules/FileStorage/src/SimpleModule.FileStorage/Pages/BrowseEndpoint.cs index 1fc7fb67..b6f91423 100644 --- a/modules/FileStorage/src/SimpleModule.FileStorage/Pages/BrowseEndpoint.cs +++ b/modules/FileStorage/src/SimpleModule.FileStorage/Pages/BrowseEndpoint.cs @@ -22,7 +22,7 @@ public void Map(IEndpointRouteBuilder app) { var userId = context.User.GetScopedUserId(); - var files = await fileStorage.GetFilesAsync(folder, userId); + var files = await fileStorage.GetFilesAsync(folder, userId, skip: 0, take: 200); var folders = await fileStorage.GetFoldersAsync(folder, userId); var parentFolder = folder is not null diff --git a/modules/OpenIddict/src/SimpleModule.OpenIddict/OpenIddictModule.cs b/modules/OpenIddict/src/SimpleModule.OpenIddict/OpenIddictModule.cs index 7e44da80..776d4e9f 100644 --- a/modules/OpenIddict/src/SimpleModule.OpenIddict/OpenIddictModule.cs +++ b/modules/OpenIddict/src/SimpleModule.OpenIddict/OpenIddictModule.cs @@ -74,6 +74,13 @@ public void ConfigureServices(IServiceCollection services, IConfiguration config options.AllowPasswordFlow(); } + // Issue access tokens as signed JWTs rather than encrypted JWE. + // Resource-server validation then verifies a signature (cheap, cached + // public key) instead of an RSA-OAEP private-key decrypt on every + // request — a large per-request CPU saving under load. Authorization + // codes and refresh tokens remain encrypted. + options.DisableAccessTokenEncryption(); + options .SetAuthorizationEndpointUris(ConnectRouteConstants.ConnectAuthorize) .SetTokenEndpointUris(ConnectRouteConstants.ConnectToken) diff --git a/modules/RateLimiting/src/SimpleModule.RateLimiting.Contracts/IRateLimitingContracts.cs b/modules/RateLimiting/src/SimpleModule.RateLimiting.Contracts/IRateLimitingContracts.cs index 0fe75c6a..fb3408fe 100644 --- a/modules/RateLimiting/src/SimpleModule.RateLimiting.Contracts/IRateLimitingContracts.cs +++ b/modules/RateLimiting/src/SimpleModule.RateLimiting.Contracts/IRateLimitingContracts.cs @@ -2,7 +2,7 @@ namespace SimpleModule.RateLimiting.Contracts; public interface IRateLimitingContracts { - Task> GetAllRulesAsync(); + Task> GetAllRulesAsync(int skip = 0, int take = 30); Task GetRuleByIdAsync(RateLimitRuleId id); Task CreateRuleAsync(CreateRateLimitRuleRequest request); Task UpdateRuleAsync(RateLimitRuleId id, UpdateRateLimitRuleRequest request); diff --git a/modules/RateLimiting/src/SimpleModule.RateLimiting/Endpoints/Policies/GetAllEndpoint.cs b/modules/RateLimiting/src/SimpleModule.RateLimiting/Endpoints/Policies/GetAllEndpoint.cs index 27a0899c..b9118096 100644 --- a/modules/RateLimiting/src/SimpleModule.RateLimiting/Endpoints/Policies/GetAllEndpoint.cs +++ b/modules/RateLimiting/src/SimpleModule.RateLimiting/Endpoints/Policies/GetAllEndpoint.cs @@ -14,8 +14,13 @@ public class GetAllEndpoint : IEndpoint public void Map(IEndpointRouteBuilder app) => app.MapGet( Route, - (IRateLimitingContracts contracts) => - CrudEndpoints.GetAll(contracts.GetAllRulesAsync) + (IRateLimitingContracts contracts, int? skip, int? take) => + CrudEndpoints.GetAll(() => + contracts.GetAllRulesAsync( + Math.Max(0, skip ?? 0), + Math.Clamp(take ?? 30, 1, 500) + ) + ) ) .RequirePermission(RateLimitingPermissions.View); } diff --git a/modules/RateLimiting/src/SimpleModule.RateLimiting/Pages/AdminEndpoint.cs b/modules/RateLimiting/src/SimpleModule.RateLimiting/Pages/AdminEndpoint.cs index e725d94d..8bec634e 100644 --- a/modules/RateLimiting/src/SimpleModule.RateLimiting/Pages/AdminEndpoint.cs +++ b/modules/RateLimiting/src/SimpleModule.RateLimiting/Pages/AdminEndpoint.cs @@ -18,7 +18,7 @@ public void Map(IEndpointRouteBuilder app) Route, async (IRateLimitingContracts contracts, IRateLimitPolicyRegistry policyRegistry) => { - var rules = await contracts.GetAllRulesAsync(); + var rules = await contracts.GetAllRulesAsync(take: 500); var activePolicies = policyRegistry.GetPolicies(); return Inertia.Render( "RateLimiting/Admin", diff --git a/modules/RateLimiting/src/SimpleModule.RateLimiting/RateLimitingService.cs b/modules/RateLimiting/src/SimpleModule.RateLimiting/RateLimitingService.cs index 1199dd35..00dff120 100644 --- a/modules/RateLimiting/src/SimpleModule.RateLimiting/RateLimitingService.cs +++ b/modules/RateLimiting/src/SimpleModule.RateLimiting/RateLimitingService.cs @@ -11,8 +11,13 @@ public partial class RateLimitingService( ILogger logger ) : IRateLimitingContracts { - public async Task> GetAllRulesAsync() => - await db.Rules.AsNoTracking().OrderBy(r => r.PolicyName).ToListAsync(); + public async Task> GetAllRulesAsync(int skip = 0, int take = 30) => + await db + .Rules.AsNoTracking() + .OrderBy(r => r.PolicyName) + .Skip(skip) + .Take(take) + .ToListAsync(); public async Task GetRuleByIdAsync(RateLimitRuleId id) { diff --git a/modules/Settings/src/SimpleModule.Settings.Contracts/ISettingsContracts.cs b/modules/Settings/src/SimpleModule.Settings.Contracts/ISettingsContracts.cs index 3ab41777..c96528da 100644 --- a/modules/Settings/src/SimpleModule.Settings.Contracts/ISettingsContracts.cs +++ b/modules/Settings/src/SimpleModule.Settings.Contracts/ISettingsContracts.cs @@ -13,7 +13,11 @@ public interface ISettingsContracts Task SetManyAsync(IReadOnlyList updates); Task DeleteSettingAsync(string key, SettingScope scope, string? userId = null); Task ResetToDefaultAsync(string key, SettingScope scope, string? userId = null); - Task> GetSettingValuesAsync(SettingsFilter? filter = null); + Task> GetSettingValuesAsync( + SettingsFilter? filter = null, + int skip = 0, + int take = 30 + ); Task GetSettingValueAsync( string key, SettingScope scope, diff --git a/modules/Settings/src/SimpleModule.Settings/Endpoints/Settings/GetSettingsEndpoint.cs b/modules/Settings/src/SimpleModule.Settings/Endpoints/Settings/GetSettingsEndpoint.cs index 94e8af63..f37f2955 100644 --- a/modules/Settings/src/SimpleModule.Settings/Endpoints/Settings/GetSettingsEndpoint.cs +++ b/modules/Settings/src/SimpleModule.Settings/Endpoints/Settings/GetSettingsEndpoint.cs @@ -15,7 +15,13 @@ public class GetSettingsEndpoint : IEndpoint public void Map(IEndpointRouteBuilder app) => app.MapGet( Route, - async (ISettingsContracts settings, SettingScope? scope, string? group) => + async ( + ISettingsContracts settings, + SettingScope? scope, + string? group, + int? skip, + int? take + ) => { SettingsFilter? filter = null; if (scope is not null || group is not null) @@ -23,7 +29,11 @@ public void Map(IEndpointRouteBuilder app) => filter = new SettingsFilter { Scope = scope, Group = group }; } - var results = await settings.GetSettingValuesAsync(filter); + var results = await settings.GetSettingValuesAsync( + filter, + Math.Max(0, skip ?? 0), + Math.Clamp(take ?? 30, 1, 500) + ); // This admin list serves global (System/Application) configuration. // User-scoped values are per-user and must not be enumerable here — diff --git a/modules/Settings/src/SimpleModule.Settings/Pages/AdminSettingsEndpoint.cs b/modules/Settings/src/SimpleModule.Settings/Pages/AdminSettingsEndpoint.cs index fc165d81..d8f4cf0f 100644 --- a/modules/Settings/src/SimpleModule.Settings/Pages/AdminSettingsEndpoint.cs +++ b/modules/Settings/src/SimpleModule.Settings/Pages/AdminSettingsEndpoint.cs @@ -19,7 +19,7 @@ public void Map(IEndpointRouteBuilder app) async (ISettingsContracts settings, ISettingsDefinitionRegistry registry) => { var definitions = registry.GetDefinitions(); - var settingValues = await settings.GetSettingValuesAsync(); + var settingValues = await settings.GetSettingValuesAsync(take: 500); return Inertia.Render( "Settings/AdminSettings", new { definitions, settings = settingValues } diff --git a/modules/Settings/src/SimpleModule.Settings/Services/PublicMenuService.cs b/modules/Settings/src/SimpleModule.Settings/Services/PublicMenuService.cs index 8f9fd1ee..e7fc3c48 100644 --- a/modules/Settings/src/SimpleModule.Settings/Services/PublicMenuService.cs +++ b/modules/Settings/src/SimpleModule.Settings/Services/PublicMenuService.cs @@ -29,6 +29,7 @@ public async Task> GetMenuTreeAsync() var entities = await db .PublicMenuItems.Where(e => e.IsVisible) .OrderBy(e => e.SortOrder) + .Take(1000) // navigation tree is consumed wholesale; bound defensively .ToListAsync(ct); return BuildPublicTree(entities, parentId: null); }, @@ -59,7 +60,8 @@ public async Task> GetMenuTreeAsync() public async Task> GetAllAsync() { - var entities = await db.PublicMenuItems.OrderBy(e => e.SortOrder).ToListAsync(); + // Menu items form a navigation tree consumed wholesale; bound defensively. + var entities = await db.PublicMenuItems.OrderBy(e => e.SortOrder).Take(1000).ToListAsync(); return BuildDtoTree(entities, parentId: null); } diff --git a/modules/Settings/src/SimpleModule.Settings/SettingsService.cs b/modules/Settings/src/SimpleModule.Settings/SettingsService.cs index eefb23a7..0b490712 100644 --- a/modules/Settings/src/SimpleModule.Settings/SettingsService.cs +++ b/modules/Settings/src/SimpleModule.Settings/SettingsService.cs @@ -232,7 +232,9 @@ public Task ResetToDefaultAsync(string key, SettingScope scope, string? userId = DeleteSettingAsync(key, scope, userId); public async Task> GetSettingValuesAsync( - SettingsFilter? filter = null + SettingsFilter? filter = null, + int skip = 0, + int take = 30 ) { var query = db.Settings.AsQueryable(); @@ -252,6 +254,9 @@ public async Task> GetSettingValuesAsync( var entities = await query .AsNoTracking() + .OrderBy(e => e.Key) + .Skip(skip) + .Take(take) .Select(e => new { e.Key, diff --git a/modules/Tenants/src/SimpleModule.Tenants.Contracts/ITenantContracts.cs b/modules/Tenants/src/SimpleModule.Tenants.Contracts/ITenantContracts.cs index 34dd4645..8d7adbd9 100644 --- a/modules/Tenants/src/SimpleModule.Tenants.Contracts/ITenantContracts.cs +++ b/modules/Tenants/src/SimpleModule.Tenants.Contracts/ITenantContracts.cs @@ -2,7 +2,7 @@ namespace SimpleModule.Tenants.Contracts; public interface ITenantContracts { - Task> GetAllTenantsAsync(); + Task> GetAllTenantsAsync(int skip = 0, int take = 30); Task GetTenantByIdAsync(TenantId id); Task GetTenantBySlugAsync(string slug); Task GetTenantByHostNameAsync(string hostName); diff --git a/modules/Tenants/src/SimpleModule.Tenants/Endpoints/Tenants/GetAllEndpoint.cs b/modules/Tenants/src/SimpleModule.Tenants/Endpoints/Tenants/GetAllEndpoint.cs index 64e80196..49b7c516 100644 --- a/modules/Tenants/src/SimpleModule.Tenants/Endpoints/Tenants/GetAllEndpoint.cs +++ b/modules/Tenants/src/SimpleModule.Tenants/Endpoints/Tenants/GetAllEndpoint.cs @@ -14,7 +14,13 @@ public class GetAllEndpoint : IEndpoint public void Map(IEndpointRouteBuilder app) => app.MapGet( Route, - (ITenantContracts contracts) => CrudEndpoints.GetAll(contracts.GetAllTenantsAsync) + (ITenantContracts contracts, int? skip, int? take) => + CrudEndpoints.GetAll(() => + contracts.GetAllTenantsAsync( + Math.Max(0, skip ?? 0), + Math.Clamp(take ?? 30, 1, 500) + ) + ) ) .RequirePermission(TenantsPermissions.View); } diff --git a/modules/Tenants/src/SimpleModule.Tenants/Pages/BrowseEndpoint.cs b/modules/Tenants/src/SimpleModule.Tenants/Pages/BrowseEndpoint.cs index 16793eb2..0a8fc053 100644 --- a/modules/Tenants/src/SimpleModule.Tenants/Pages/BrowseEndpoint.cs +++ b/modules/Tenants/src/SimpleModule.Tenants/Pages/BrowseEndpoint.cs @@ -16,7 +16,7 @@ public void Map(IEndpointRouteBuilder app) Route, async (ITenantContracts contracts) => { - var tenants = (await contracts.GetAllTenantsAsync()).Select(t => new + var tenants = (await contracts.GetAllTenantsAsync(take: 500)).Select(t => new { t.Id, t.Name, diff --git a/modules/Tenants/src/SimpleModule.Tenants/Pages/ManageEndpoint.cs b/modules/Tenants/src/SimpleModule.Tenants/Pages/ManageEndpoint.cs index 089491fe..168e32eb 100644 --- a/modules/Tenants/src/SimpleModule.Tenants/Pages/ManageEndpoint.cs +++ b/modules/Tenants/src/SimpleModule.Tenants/Pages/ManageEndpoint.cs @@ -18,7 +18,7 @@ public void Map(IEndpointRouteBuilder app) async (ITenantContracts contracts) => Inertia.Render( "Tenants/Manage", - new { tenants = await contracts.GetAllTenantsAsync() } + new { tenants = await contracts.GetAllTenantsAsync(take: 500) } ) ) .RequirePermission(TenantsPermissions.View); diff --git a/modules/Tenants/src/SimpleModule.Tenants/TenantService.cs b/modules/Tenants/src/SimpleModule.Tenants/TenantService.cs index b5509436..9469130a 100644 --- a/modules/Tenants/src/SimpleModule.Tenants/TenantService.cs +++ b/modules/Tenants/src/SimpleModule.Tenants/TenantService.cs @@ -13,10 +13,13 @@ public sealed partial class TenantService( ILogger logger ) : ITenantContracts { - public async Task> GetAllTenantsAsync() => + public async Task> GetAllTenantsAsync(int skip = 0, int take = 30) => await db .Tenants.AsNoTracking() .Include(t => t.Hosts) + .OrderBy(t => t.Id) + .Skip(skip) + .Take(take) .Select(t => MapToDto(t)) .ToListAsync(); diff --git a/modules/Users/src/SimpleModule.Users.Contracts/IUserContracts.cs b/modules/Users/src/SimpleModule.Users.Contracts/IUserContracts.cs index 8684a02c..d43f5894 100644 --- a/modules/Users/src/SimpleModule.Users.Contracts/IUserContracts.cs +++ b/modules/Users/src/SimpleModule.Users.Contracts/IUserContracts.cs @@ -2,7 +2,7 @@ namespace SimpleModule.Users.Contracts; public interface IUserContracts { - Task> GetAllUsersAsync(); + Task> GetAllUsersAsync(int skip = 0, int take = 30); Task GetUserByIdAsync(UserId id); Task GetCurrentUserAsync(UserId userId); Task CreateUserAsync(CreateUserRequest request); diff --git a/modules/Users/src/SimpleModule.Users/Endpoints/Users/GetAllEndpoint.cs b/modules/Users/src/SimpleModule.Users/Endpoints/Users/GetAllEndpoint.cs index e747ee06..d5279834 100644 --- a/modules/Users/src/SimpleModule.Users/Endpoints/Users/GetAllEndpoint.cs +++ b/modules/Users/src/SimpleModule.Users/Endpoints/Users/GetAllEndpoint.cs @@ -15,8 +15,13 @@ public void Map(IEndpointRouteBuilder app) { app.MapGet( Route, - (IUserContracts userContracts) => - CrudEndpoints.GetAll(userContracts.GetAllUsersAsync) + (IUserContracts userContracts, int? skip, int? take) => + CrudEndpoints.GetAll(() => + userContracts.GetAllUsersAsync( + Math.Max(0, skip ?? 0), + Math.Clamp(take ?? 30, 1, 200) + ) + ) ) .WithTags(UsersConstants.ModuleName) .RequireAuthorization(); diff --git a/modules/Users/src/SimpleModule.Users/Services/ExternalUserService.cs b/modules/Users/src/SimpleModule.Users/Services/ExternalUserService.cs index c9c881d3..be39a9f1 100644 --- a/modules/Users/src/SimpleModule.Users/Services/ExternalUserService.cs +++ b/modules/Users/src/SimpleModule.Users/Services/ExternalUserService.cs @@ -15,9 +15,15 @@ internal sealed partial class ExternalUserService( ILogger logger ) : IUserContracts { - public async Task> GetAllUsersAsync() + public async Task> GetAllUsersAsync(int skip = 0, int take = 30) { - return await db.Set().Select(u => MapToDto(u)).ToListAsync(); + return await db.Set() + .AsNoTracking() + .OrderBy(u => u.Id) + .Skip(skip) + .Take(take) + .Select(u => MapToDto(u)) + .ToListAsync(); } public async Task GetUserByIdAsync(UserId id) diff --git a/modules/Users/src/SimpleModule.Users/UserService.cs b/modules/Users/src/SimpleModule.Users/UserService.cs index 234ac2c5..b6ff14ee 100644 --- a/modules/Users/src/SimpleModule.Users/UserService.cs +++ b/modules/Users/src/SimpleModule.Users/UserService.cs @@ -18,9 +18,14 @@ internal sealed partial class UserService( ILogger logger ) : IUserContracts { - public async Task> GetAllUsersAsync() + public async Task> GetAllUsersAsync(int skip = 0, int take = 30) { - var users = await userManager.Users.ToListAsync(); + var users = await userManager + .Users.AsNoTracking() + .OrderBy(u => u.Id) + .Skip(skip) + .Take(take) + .ToListAsync(); return users.Select(MapToDto); } diff --git a/tests/SimpleModule.Tests.Shared/Fakes/FakeUserContracts.cs b/tests/SimpleModule.Tests.Shared/Fakes/FakeUserContracts.cs index d76afac7..fa4a0fbc 100644 --- a/tests/SimpleModule.Tests.Shared/Fakes/FakeUserContracts.cs +++ b/tests/SimpleModule.Tests.Shared/Fakes/FakeUserContracts.cs @@ -7,8 +7,8 @@ public class FakeUserContracts : IUserContracts { public List Users { get; set; } = FakeDataGenerators.UserFaker.Generate(3); - public Task> GetAllUsersAsync() => - Task.FromResult>(Users); + public Task> GetAllUsersAsync(int skip = 0, int take = 30) => + Task.FromResult>(Users.Skip(skip).Take(take).ToList()); public Task GetUserByIdAsync(UserId id) => Task.FromResult(Users.FirstOrDefault(u => u.Id == id)); From b7f7e0a60b38659f2438762a776658a719e961cc Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Sun, 21 Jun 2026 23:59:50 +0200 Subject: [PATCH 2/7] fix: address code review findings (round 1, pass 1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - AuditLogService: align offset default sort with keyset (Timestamp DESC, Id DESC tiebreaker) on managed providers so a cursor page is a true continuation of the offset first page; keep Id fallback and skip keyset on SQLite (no DateTimeOffset ORDER BY). EmailService: add Id tiebreaker to CreatedAt ordering (offset + keyset). - SettingsService: order by (Key, Scope, UserId) — Key is non-unique, so paging was nondeterministic. - Remove dead locale keys (AuditLogs Browse.Showing, Email History.Of). --- .../SimpleModule.AuditLogs/AuditLogService.cs | 29 +++++++++++++++---- .../SimpleModule.AuditLogs/Locales/en.json | 1 - .../SimpleModule.AuditLogs/Locales/keys.ts | 1 - .../src/SimpleModule.Email/EmailService.cs | 7 +++-- .../src/SimpleModule.Email/Locales/en.json | 1 - .../src/SimpleModule.Email/Locales/keys.ts | 1 - .../SimpleModule.Settings/SettingsService.cs | 4 +++ 7 files changed, 32 insertions(+), 12 deletions(-) diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs b/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs index b45774f2..5d651f70 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/AuditLogService.cs @@ -30,19 +30,29 @@ public async Task> QueryAsync(AuditQueryRequest request) var sortDesc = request.EffectiveSortDescending; var page = request.EffectivePage; var pageSize = request.EffectivePageSize; + var provider = DatabaseProviderDetector.Detect( + dbOptions.Value.DefaultConnection, + dbOptions.Value.Provider + ); + var isDefaultSort = sortDesc && !CustomSortColumns.Contains(sortBy); // Keyset (cursor) pagination: when the caller supplies a cursor and uses the // default Timestamp-descending ordering, page via WHERE Timestamp < cursor // instead of OFFSET. This avoids both the per-request COUNT(*) and the O(offset) // row-skip that make deep pages slow, using the IX_AuditEntries_Timestamp index. - // TotalCount is reported as -1 (not computed) in cursor mode. (Entries sharing - // the exact boundary timestamp could be skipped, negligible at this resolution.) - if (request.Before.HasValue && sortDesc && !CustomSortColumns.Contains(sortBy)) + // The ordering (Timestamp DESC, Id DESC) matches the offset default below, so a + // cursor page is a true continuation of the offset first page. SQLite cannot + // ORDER BY DateTimeOffset, so keyset only applies on managed providers (SQLite + // requests fall through to Id-ordered offset paging). TotalCount is -1 (not + // computed) in cursor mode. Note: rows sharing the exact boundary Timestamp can + // be skipped (strict <); with microsecond-resolution UtcNow this is rare. + if (request.Before.HasValue && isDefaultSort && provider != DatabaseProvider.Sqlite) { var cursor = request.Before.Value; var keysetItems = await query .Where(e => e.Timestamp < cursor) .OrderByDescending(e => e.Timestamp) + .ThenByDescending(e => e.Id) .Take(pageSize) .AsNoTracking() .ToListAsync(); @@ -74,9 +84,16 @@ public async Task> QueryAsync(AuditQueryRequest request) "DurationMs" => sortDesc ? query.OrderByDescending(e => e.DurationMs) : query.OrderBy(e => e.DurationMs), - // SQLite does not support DateTimeOffset in ORDER BY, so sort by Id - // (auto-increment, correlates with insertion order) as a fallback. - _ => sortDesc ? query.OrderByDescending(e => e.Id) : query.OrderBy(e => e.Id), + // Default (Timestamp) sort. SQLite cannot ORDER BY DateTimeOffset, so it + // falls back to Id (auto-increment, insertion order). Managed providers order + // by Timestamp with Id as a tiebreaker — this is the ordering keyset cursor + // pagination continues, so the offset first page and cursor pages agree. + _ when provider == DatabaseProvider.Sqlite => sortDesc + ? query.OrderByDescending(e => e.Id) + : query.OrderBy(e => e.Id), + _ => sortDesc + ? query.OrderByDescending(e => e.Timestamp).ThenByDescending(e => e.Id) + : query.OrderBy(e => e.Timestamp).ThenBy(e => e.Id), }; var items = await query diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json index 73b2cdb6..0055e837 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/en.json @@ -33,7 +33,6 @@ "Browse.ColPath": "Path", "Browse.ColStatus": "Status", "Browse.ColDuration": "Duration", - "Browse.Showing": "Showing {start}\u2013{end} of {total} entries", "Dashboard.Title": "Audit Dashboard", "Dashboard.Description": "System activity overview and metrics", "Dashboard.FilterFrom": "From", diff --git a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts index 485ef2a3..d896e591 100644 --- a/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts +++ b/modules/AuditLogs/src/SimpleModule.AuditLogs/Locales/keys.ts @@ -32,7 +32,6 @@ export const AuditLogsKeys = { NextPage: 'Browse.NextPage', PrevPage: 'Browse.PrevPage', QuickRange: 'Browse.QuickRange', - Showing: 'Browse.Showing', Title: 'Browse.Title', TotalEntries: 'Browse.TotalEntries', }, diff --git a/modules/Email/src/SimpleModule.Email/EmailService.cs b/modules/Email/src/SimpleModule.Email/EmailService.cs index f5009feb..7815dc04 100644 --- a/modules/Email/src/SimpleModule.Email/EmailService.cs +++ b/modules/Email/src/SimpleModule.Email/EmailService.cs @@ -129,6 +129,7 @@ QueryEmailMessagesRequest request var keysetItems = await query .Where(m => m.CreatedAt < cursor) .OrderByDescending(m => m.CreatedAt) + .ThenByDescending(m => m.Id) .Take(pageSize) .ToListAsync(); @@ -152,9 +153,11 @@ QueryEmailMessagesRequest request "Status" => sortDescending ? query.OrderByDescending(m => m.Status) : query.OrderBy(m => m.Status), + // Default (CreatedAt) sort with Id tiebreaker — matches the keyset cursor + // ordering above so the offset first page and cursor pages agree. "CreatedAt" or _ => sortDescending - ? query.OrderByDescending(m => m.CreatedAt) - : query.OrderBy(m => m.CreatedAt), + ? query.OrderByDescending(m => m.CreatedAt).ThenByDescending(m => m.Id) + : query.OrderBy(m => m.CreatedAt).ThenBy(m => m.Id), }; var items = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync(); diff --git a/modules/Email/src/SimpleModule.Email/Locales/en.json b/modules/Email/src/SimpleModule.Email/Locales/en.json index a50f1ef4..aec29dd7 100644 --- a/modules/Email/src/SimpleModule.Email/Locales/en.json +++ b/modules/Email/src/SimpleModule.Email/Locales/en.json @@ -66,7 +66,6 @@ "History.FilterDateTo": "To Date", "History.AllStatuses": "All Statuses", "History.Showing": "Showing", - "History.Of": "of", "History.Previous": "Previous", "History.Next": "Next", "History.Newest": "Newest", diff --git a/modules/Email/src/SimpleModule.Email/Locales/keys.ts b/modules/Email/src/SimpleModule.Email/Locales/keys.ts index 8b71af04..26c7d062 100644 --- a/modules/Email/src/SimpleModule.Email/Locales/keys.ts +++ b/modules/Email/src/SimpleModule.Email/Locales/keys.ts @@ -75,7 +75,6 @@ export const EmailKeys = { FilterTo: 'History.FilterTo', Newest: 'History.Newest', Next: 'History.Next', - Of: 'History.Of', Previous: 'History.Previous', Showing: 'History.Showing', Title: 'History.Title', diff --git a/modules/Settings/src/SimpleModule.Settings/SettingsService.cs b/modules/Settings/src/SimpleModule.Settings/SettingsService.cs index 0b490712..8864f721 100644 --- a/modules/Settings/src/SimpleModule.Settings/SettingsService.cs +++ b/modules/Settings/src/SimpleModule.Settings/SettingsService.cs @@ -254,7 +254,11 @@ public async Task> GetSettingValuesAsync( var entities = await query .AsNoTracking() + // Key is not unique (a key can exist at multiple scopes/users); order by the + // full identity so skip/take paging is deterministic across requests. .OrderBy(e => e.Key) + .ThenBy(e => e.Scope) + .ThenBy(e => e.UserId) .Skip(skip) .Take(take) .Select(e => new From 54a0b3f9621dbdf8f5c407c012566592c816feb8 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 22 Jun 2026 00:26:25 +0200 Subject: [PATCH 3/7] fix(ci): unblock pre-existing CI failures on main MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - app.tsx: narrow resolveLayout(page).default to React.ComponentType so the Inertia ComponentResolver union type-checks (the persistent layout is read at runtime, unaffected). Fixes the typecheck error at app.tsx:226. - Directory.Build.props: demote NU1903 to a warning (not error). It flags a high-severity advisory in the transitive native lib SQLitePCLRaw.lib.e_sqlite3 pulled by Microsoft.Data.Sqlite/EFCore.Sqlite 10.0.3 — not directly referenced, so it can't be bumped here; kept visible as a warning until a patched transitive ships. --- Directory.Build.props | 5 ++++- template/SimpleModule.Host/ClientApp/app.tsx | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index 6a74e506..869a1b4c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,7 +7,10 @@ - $(WarningsNotAsErrors);SM0012;SM0039;NU5104 + + $(WarningsNotAsErrors);SM0012;SM0039;NU5104;NU1903 true true diff --git a/template/SimpleModule.Host/ClientApp/app.tsx b/template/SimpleModule.Host/ClientApp/app.tsx index 93b80714..e72bd249 100644 --- a/template/SimpleModule.Host/ClientApp/app.tsx +++ b/template/SimpleModule.Host/ClientApp/app.tsx @@ -230,7 +230,10 @@ createInertiaApp({ try { const page = await resolvePage(name); - return resolveLayout(page).default; + // resolveLayout attaches a persistent `layout` to the component (read by Inertia + // at runtime); narrow to ComponentType so the resolver's union matches the + // error-page branch and satisfies Inertia's ComponentResolver type. + return resolveLayout(page).default as React.ComponentType; } catch (err) { showToast({ variant: 'error', From c234191df1a882d556d95d4607cb78e22e3be666 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 22 Jun 2026 00:29:39 +0200 Subject: [PATCH 4/7] chore: add verification screenshot (audit cursor pagination) --- .verify/screenshot.png | Bin 77595 -> 51459 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/.verify/screenshot.png b/.verify/screenshot.png index 1e42c599239f02d8b448283027e631f89af95442..a249441d8712475ded8f5753bdb816b750cb862f 100644 GIT binary patch literal 51459 zcmbsQWl&tr_XP?kxC96g+=9Ei2WN11cLsNd;1(pfySux)ySux)b0^QQ{#9?ipKjIt zGIgp?cc0z6r@Pl)dv&Osj2HqOHr$slUl0J|!U|u$fPee)R6e}AFL z&nKx_w)Fch2s4}`4EiMun1W^?Aq@Ce@S70!--9^RHvp*oyC9RE_`eF@W4;QZ{CkN0 zh8go;6Qi!^e+>vpz=KHsd%*gC-vyPhOn{(%`9a~d8N|Pj6cv}KinqigH{R~wo4T1# zyA|6s2iCWg<16<1T7Bb3)o^oWt0Vl+9% zw>fJDp=6owz+dK+p_Xi^KS4d$%yE%)zeU-ji0N$J@$jb)$#Ub>rfU~8%rXvIbIj@e zXLE_@Ih3_x=t);8%rhCu6$Lpgx+IXl;eU=m1|r84J=rreJ4@fW<$S49E0RYZ`_DH( zFrXLQ@AYeTh%i{jswL@3A=rN&l0%i7jTTmR=>w063F-MopRpGS^I!RH@jc}igPYlq z9ty|p{|3XVnkx~L*FyXq=H`i1SbxLzW}B`m>7O^VMT2!E|IH8~iBS0<2{NQbk8$2x zAN42Qw==U{uIpd8i7a7lM-D!d=cm9;?}y_*DP#B;HP;qCV$hYG7%~4@0?b_~{8EI~ z5?Fod!&f>xaQ-9Vv+R9RFjKu2$7e5+V>o*?Q3i9%*l=Z}YNznB1lld9lu76_W2wL1 zaI-Q>cpv#$f~VP_XD+_g+IZiTZ16x8Cx+vi8~l8fAhkC-qVZ-^JN{A6P_Ol-wCr6~ z_#ifASNQVHWT0=}^uqLpiHZ4^gCLdHdUK7ESry+qAvrTSZuoua?BCekCkKTT&cnGJ z;cKTc+#@oIQXj>Jz~;SX&nmUu)Cx8S*IJBexgU+zSOfmpwTsaq!R@zH@Ho+)EKH|M zdRoFX6L|hmKqkLEN$9NXH#S-4Z`=OmXmulokc6bcvM5_CT3ezayVl{;;_u4!xt+kP zib`EE+*I#2S`K!d_Yrc=o!D&tH$~A2v)M=?5t~dpY29RLrWl_!1MlA-^0IgotC7D! z+__N2`hh_{=7E7eoO+Aj2an~(nM7=KBSU_(btwGXic>f=>Ur?wH(O>_7Kii4{sHYy z7v`ZhJnYO$;FQ+@2A{T;wtHkc`%E_5v(Q(PV-jW>inx;uf9$30)nv5u5(w~bpeden zq%_)UphEUhrfoe8?FeVDud&YV^T}{DxDHRcV^WaSvgVt&a=d*+)3hNCFHCL##~61a zwzGQ{jyK=k(l1T%Cfu5*}Q`+adfhT8^a^65-hQIhk6{h`NZcJRUaa%yC({xPJI zJ&+90vVC()%03dsfr&egO#5--d&3lS)ZiAw$uZ3SK$DKYv^w2_wr03V3E!v{;ZgL5r&N3LUNid<@J%o0nQA|3AlZH}g@ zFXQsLM;8hIEfp%ot|Srxou$zb%FR zvQ+K^$Zxnz`qx3b`t;1V@EK5*>QArpJTY$8&wa3?BE;S?e(bnoEcX|duYa3w282aJVnqRpHtJXZqIhz zVzIcvGPe0A=HFxbb^|zu4->xm-Z^aQ9dvJH1x6-MIW<|HL^lWTh%B0DX>&Q><+Lwm z#9UB2Tc+&-uPR>p;<0n$($W$WJw1nu{z^t}NF5lPaS&f7F4~ zzDPmFt)sA=tAS7cZ#N~76DAG){2%7_L+D3fMh>J&+AaK8Yol0FqE@n z{OnFP-u1N9e#giN5btIos59ICC0(2xO#AMK9oK8d?=<=xeVXm_DpxErZ?{nqeflU% zYf0b1b!_elHJG)@9{!>b?u=P$@SM}!Y5B}7r|ZbbX{5RYjh6T)nzd7Rlq6-t7o00e zom(KsZ$PRDE%ab-&-B0!VdW9)+=?oLlg~)?Y91Ve$qEY5%0_e_SEs}E&PB&@Dy3IF zz^s8_X??h0Hh?r1Ph=52?bGA-oyU4^d(&B@S7iJ*=_r}A^F98BAvFLn_83gTC=E@o zKG&GSCo1!Hy~(~dM$YD)+m0t~wZ_wjM6$oOy~@fdhX`8NFKcr>2!R1~0#m!~iNIo(&emVW>GMGV{5fNjarU zK~R>(Y|6CYwAZvvQ&Hr+%v$L0xyA=3v>h3VcPz~c=4AAIL=sAVlubUayP^(k?nb5-%;h&fV-vqphNe260&$%( zcgFe}9SJqP(=yb``UQR{eiLYbJb;ut88GZel(rOJx*Hpf`MH=4|c#rx-D}iv@RJ`XIo8e?@krlfiR04tT%9BUjmq>rll@1&wq6nD|Ime;5VIwZjFz%R-1U)Nxo%Vs5` zd~*i8qr||(=|s|K%OFUZtURbU+&_NogvBIeC#)fv?jH1q2K%7KA|e))TN~oNhr)~d-FUZ zVsSVnxzHuHL&7%-v9K;t!mqv9TOU|jh;vs+1^}3#qnL|lkP~~~T~lUitm!Xaclnm8 zY@a)D0MEEGH|;`_h4e_>7i^%T<46dOvxT;jfiFl*BL!juzlKnMXh+wv#(CpCe{g+h z5llh1M9xhAAh-#sR+@2hfb{)hHV&OyF5-uv+&DY?bVxYIRy(n2??2j7O zCsM5%SS^;qT7mr4l9i_k1WVEk&i%d{fHvN0QtN%DUDE0X!j6*n!0aAR1xHhn#v|Sy zkp$Dix>y)`j}b5)sbgZ&71oK|`7n93pw18dqI?{uH->-ORG%Poero*2(uP5g+Dh$c^{* zQ79K@#>V4?%hd1ANQR|s4G!jaB-Hx`PTDX1{KHm3h^=EUjT-mp$r@kmzI?Irb zDnhn5BNY|-@c~v^2kc*{{^r90KhR>(Tj*(cZ=d76G(U81UoT*Grd)>R;ztXdn3MoK z&9);iru{j~_W1p_-0Gbg9eSVC@_H1KVbl*-%n@qsJ4e*hZZJ2yu@UYrv>UZX=T>%u zDlhG72`;}4Kc3r74Z=k56ql!=Rq6SEBv&pQj|||Az9yH3O*Fla^CQ)YG)@4-XD>G< zYyD+^=~~37roFS#7B>Ac<9wodHy!`uyf)SE4|VCPp5}Smr5#kMTgYZ|!l?h~80^E| zJ4*36GD9gT(}BV-+%yZ0gb5Die7QBdD0J$iWHcAwD;9~%?e2f4(c$#Yt}T2mHecrN zB9`8^_Y?sAI0+%f>=E@q(PGEnUPi;owK}s}=%pFuoC1i#?=wQ*`@2Al;l)0{#7A=G zWOvYuIWxX^bW%g=VQ^Dim}x!V+h`%S*`2PLVDE5KGh4gOh*_6hWj{KSy@0*PtgIGY zSW+VK4@Rn+5#Ys18xtpe4`D=-ArI@rt5yd58A1ev#UV4T+Z@1BNU6(mc>~o|aZ7HC zB_#nywRX(JAlzRrx^9J#qJ(`fgZ%Gkrl`k{o%1X1LZ*S!cC{M1&0_ioS6RjCVE{_z zh2;&D@|eKw2qmEro<{d$*psu_YXNxGT}Iu1dy;AS!XW@yYUO+_%_9Fzjl-M;>V08z zSWWhyfdS%Ht*coB%+n>*LIC8#ED~(0F+h3Cj@*CI1uG;05@4nnvOu#|lg{ai9Ik3i z|982{sDz8ye~qz)v}MSiBiePj8`8wc>Wx#qr&m%_1}y)FrBy+IJT@mM4|m03d$HUr z&fK0upPgpUVs%5+oi3nXB2zTxU$6kfnh}*L6%#T^4xpN#f`ve{HXS(k!b4V!erVg0 zX6p=@3!+OmE?n-Bsom!Ymr4I-8Am0agV|ja@Z*~-Stuxu!DfX62&>4%$Vl3fz9o!3 z{B8XqMqr0eG_wqYiUQR8FLYAQr5h}k_k~jUyEiKI6Gxz@SbZ%g;aAbBgx_ByzyI0s zl@$S?gpwopjrD7FP)f9CbE+fOac|5_aB%tbhUziZf04nQD^ME{GXcmW;z2G}Qu2yQ z9b+I#PyS!9fhrdsO)@ORlq+?==*>}kC!BwREK2&{AX`?HWB5{H#UrQzGZ^NsV1WNh z8J#YziRVT0HE7Eb*@Z##@m-;a%Nu@GEEmPCGf&CuOONY+&MYX<(N(6#vo7IJD}Pxf z3iu9W5X{c1tNR9{Cvj(kB~U{_O-_Y zi^|Q4R4j}n~j)n#_Gv7^7{jOG>Vwvve=ci$nh~4uq_|4>4lEpy(QOCk$ z%#Z{z4<1{*GP6|ovokA5*MmwzJTQ>6#i6pu=0@5XlNj~T{5L4%R7jC0kg+NAa<#e7=;k@{Uta5t?2-# zU#wBmsyHv71SKH4O+bE7rxsEhz}d_JO{Y^#@i2rZeJ4b$K#Z=7Zaf~gMv$J#wN}>K z(ja8fLBU+_Vslh*(gMNilb@dtF*%uod9|HaR#sLLd$*NhLo;uaxT3(w#0YX(!jBhN zLY7@Oc5qG22=rCdo^1nz>(wJa7HDbW99N(Iz(CXf?!JR33u0;Rrc;gYcg=nVQ0bBW z^=N(*dT}?;%G%);9o0&m+Ccc$)$a-+4(9USw74%goB$1(LOwzS8RWsf9Fx4VIw`xu z<=3&|DJ)|-x)QL8=K+Ox=VDqAGeRjW{6MX0#cU(wA?^NLHGX?63-EuMDF`N1L?wg5 zWCwF^H}z?9kh)~QOuh0-dV{Oh62SOYjjO*;SrLtg}XJX?@(XL%jR6^$*)tz z#9B_&V+-_kchZj^ALVC1!?{><<1qx_B&SB3~GFiC?G0P(kcqH1Eqj1PP=s&~(aAC=8UrpP(Eb7tWReWM%{v+f|H+!WX9{fGZT=9AJYFWZ)y zJ|CB}+|kTAKDtSffwmG%5EVpXDw5x(kR6?`z=!KAt?IB?AMow#tSVE617yBb{!M2q z)?a~Foz3i>aOPE|ngHr#`T^m$#6kK3x&sxdHSbggs-4Ym)*p8&I=N$9OJ1!*!IUsQ;>4P&&9 zJ4~@qp}{q@f789&!{qtx*04d13r!UsiPn)8*r^Wq(!1;I+67L#4+mt}$J9^oK3V^m;#HkiwOA`vN-*7*&gj z{@uc4C>DJEozW)bmJ~>%ORHvSwo)=9tE0mwpU3~Xd~;dB%Ty^LA){Vrlq}mRpyE8S z?tZUceX^L7bHm&ZAJ}t`^LcW-id1pJtalYft!ipwEbw}RR=Ukd!09aL&bjJ*7BCRu z!=5dKMRk33Q&G3#^$s3FWNc(q@wz)1o+!l6g~OBd*N|KRgFZm(gx%IGwE=I9r>!H2 z{qs7O;yBsma-H9LhNWp_qxt=6dRHI(+Lh;|1UxvZ$NnsBt!ASme#}OHcd9-Z$(-rG ze^<9n#=X@s$vV^0k}?y*KI(C4TxrE$3hMSm%L9HsI4pRwj=BrNbwox%PbR>zG1c1- zXV8-Q5uYe1oIIx7;`KKj>HZJffR0;C;tdHu8rXNOx@m^!4BD=xz?7v#SMqSxI}+8p zB1ai-z_N!ayDxAJZt!a(BMIwQyfv*>H|O}bq9O`s@te)mhKm){JADtJMoOkn*97mY zf`Y>Nx#jMTu3#EAkEfJ;b6!QsN@C{Q#rjkFV4d=3=?gJFTzFjgTsM^v}zi_)=_a8V85kRhNq%s1y#XggX>_dxvcqfMOtsjOO%6 zik-W7x4Eram};yLhsD?sj$QHS9Y+FStjnclALLj`V58kdp1V55x-*FGTnnMlCTVEj zYlI#mUx+ukW$%Q72Fx ztT($5EX)*L#}?1Su%?!;e)@yqlx=7Fs1rXsBT^uCKlr6cZ~6-T{41Ayqw$2$G<=Ek z;g`x?=Mdb2Sl^Hx1bzPbx?PyU(=)2tv-NmmELow$g%o9bS`gvM_gU%F@XPRR6e6UG zRs&NsK)2cXS#W3>RsOF_S~@Phb_Wrj+OZ=S#7@zXX&wLsm!f%i$E0Pp_wHI6vS(zi z`#U}n$Uk*t$|vveVm|(0yBd{F`?0W5Aj@yo=VTM@rgC#Dr6p665Oet}{*qRGIngR| zk~g&ngUnxhK-(Rp?+i8fu@t~om=JwzV7+-iX*+^7^Ut53N^n$O& z!aV8~apk$Mt8%j5OH<1|0Ln{%O8(lgigi%0u$m1-!R zTICat+Gu+xf9mG7vb4y85C)&u4tRmVoNZaVT`7(8xdIU(cYwvLPgS;^?GFtHA$TO` zuL(eh`75pta67o8ltHv2lf@M4Qx;Oo-&k**-@86K32T|wPZ!c9m-=S)ao%_rchWcf^zjs`_JMf2Or-FTn5ea)s zHifOINI+i9-mb5T(C4GNp*8Vvs4Khm@q(UmyDLn)-hgwiSEBzgNkv(i*V&f7kL=Ui zYsJIWYP0#Zv{|=nB%rjx=A%`NU6$hZmkXvPJxt;pQ}$Sc%OM-k{p<)iIyozUCZ%#< zNuIbOKzp_3d~-Bg|EkB<**S&7x-PW(=xJfkNS?hVTvGG+d0lG-`MQe<5FVJk{HHjU z{iFSPEil^KD@AJ=6NKJ}XZzVFUmBvTbuX>;s5$Q+0#`EKTdQ))1XY21NNjRjoOJjm z!hMItTVA#o`3WT&bHc?{Wj6hdHNyM(!Wemg14@ehy%3~jhZ&}z3IJNlOmanSa7QK$ za}#8*wN+pYih%U*yQI7a>wQh&-O#oz@~1ok@4(c zBgXv2>?)48V!Kn8G!FOiks?Bg0by)@;Pd?y{2=1R?ddu-J^yELrpo;V^H0KUG%aIG zBM6bmQ+8`X1hVb<(?Qvsm-}mf27#0Y3B#DI*=V5d$GgjSg=~q#>1nT#KD(G_ytDHn za!Bggi3xNCN}kQuMPs$7fW|LjTJbg3AI2PHH2$P#sPq!eRt-{=uWM!ac9 zqU^#)WTh#GN$ay^>3!IPT?Mew^3eCgzKVinU#SbY=VRSr?jzL)mL#MHZDYbCo$P$( z$N=aA=qYA%NX3i+b9H~Yo;gl7Yxb~fBmJ5lwd3>H6ex3~VlFk) z#<^dp;2+5bl!nXxlmezp$R;KvR6aAQoBoaerdl$b;*%Wxg&IqR-svwjA5X;a4==CF z>0R>d&xxfavy;4Q?navqFW$I*g-qT@oFdEQFpp(?UU!=IqM_iZE%y1Zs@E~!OG=Ar zHE(DwC6+w%Lc2lR|5}=)2NCD=LvWr)q)Z+kQN6yV9n)}Mj^#{ILr2?%&7N>NCC=KU zo3=UBFftH-ryG!}B{p7vUM!p&m?tLN(#T!S!A)^J@hB^cQ(QyuI&Mylzm3SAU1E`b zukn7&wd0ma@M#M>XA*MZM^2G1T9!)&(_&)1)`sBq3o>L+Q*atfXySHC5XLqcaYc^PKl6E;-S)A1^*@ja&2H zr(-Ef$f-F=_osIUr!Zh4$&1j?(9w0;>9}^JYDA1MqWgT0ds&gZ5*vvwa5+5dJo_45 z<(-|&w_WaP$&KDj|Bnku(p{`56a|6{frG<1gP@2OU1MeDk+}EKO{`;uz-!8;2yAPV z&8373qvw(y(j#JY%h5lX9ogp zp#p)>xtKe?tLt2!F#L3Lf4q6!yv$cR%UWf|L)35wleNu7iQX;x#lKY$^?*lyEm1>o?v!<*sD3DqjU3{%1;aL4RFr+)T-|Xds8OwE4o=G zUs@Zpz=QP~rN^&kCp-CkkX?A+pd2j)aLuhOz;AImo!=f2eA;ECc5FFJC!t##U2s(T zk)J?_C^tj&v&p_bFz~t0?sDSwe!UT%E?7G-W*~nw+r7p8`;Ux%9uQh(agRIlCXXZl zZx>fI^*r9l=GFS+b`9qJs(cnzU%%|l*Iv9^l6CeKPd0COl%C=@O5|QnLc&3(<|n83 z4GT{=V0ZAN<%FCf{=LDv-Nwd-3Ym(US~`gdT;-`6wJ>Xg&1nXL2*1Q>SEVlwOZOWA z*VBi;Se1y0bSBW)I5{px;rQaGV)vy(H{sOt{>(yiq6<=qwxS|x!`z2|@cSFMMuVB% ztuutKZ!e|La%{$r9YbM#RVO zcL(frc*Ni9$>%R)U}t{+@X7hRh_mnx*4g<6{Hpw6etED`8Fl&aDcp~v)~h>_f*4U{ z{&2amy_|nLy;~R;XC{g6b=y1B&vYrHD{C`QH;jdqQ%f4C(@y3!U&;S@2ST8%ENamb z@2@ZE95tIGGkzf>PAZ_lz+W>y;l^gIB|RpE&G{~*91X9g>O-|stD-#D>wQ4l^)25x zzlziOe2J(w3JHvTErErRWqWW#2l++me-a=fBrqbayQimur&9g(PP@hWB49(mY~&{v zhN!fSJr1u9j}H0O!-K;PeMcadVrD{Qw4e@J`}=gY&my(O?KA0=ckwC@Md>dAccqd(dxR>v1W5*0(-6 z7*rqCHK5b1)44BHhSvzSjF;bu)^i>7jF|2Zif3NG78N;z8F%Gd=rIgm zH8X2|e%Mb$Lj0v)>|fCjqL<8y7>Wlv7C*7|H@4XiyI0V(?N`VJcWOq=zdKo9bnaAmzwRwjI6R)8527fky1BWDlHI=tb!cGmc(UAe z=Xbb&-469UDRDzG-(p3w8(FGxTBJ*lB!DBzeTcJiPSAe&S!+y70!gsFXy(_eYJS(%Q5o_;njk)YZLdXO{r&7gb?WK-}Y6ECKVv_<>fL z_Qb$sEUjrkR6|n)mc{g6;E%9Qd85@)TM8zD7vHovg&6pDoA`;!by~~y_s3F|t0KJ* zouCK0m4dm)8mo|Y6xAfgjhtE8$%$_FDud%*Y#hBkp6Qy}9$A79KyP%O9A-=k8HgJl z_Qm~-mSdgaeD1Zj@rsVU+g5h}wxDaB3x&;znum!%5W`0;O-@2+ZtrO`=(`F-C<20> zG!a~QHwVk=lgm(25!A`m)6d0>&&S*9*XFp>7{b5Kfg|nf)871;3@o7Z1}o#gL`oRb z{>DbFx$MU|Lk1Tv5|yaZG)&9PM`Y`Z!`O3T=S zDMsS;TpU&dHdG2#4$-WfqH1fHgEM`iFh-jN7^ z2vhN+Z%~<&`}Uj=!?20H+t!`aaHhQdUboDu1ieGTK-JCzO4H>$Pn4s@3h5n`2 zpjegb(;C%jBcx$tg452Vq@~AG#zHMR2F+#^v3Yqq=0uASnj;L2sb ztk$v7&z-r26KgGdm(OZ+hRpCe)9E)PZ-;eqO-^1uEX&i0Kt03k!rr4>$I;lFx4| z7oqWS!m#xW{82*m1J{5sxyEw^p&KMXVuhB!IEzvAXHi$T(&*E4@3ZHJZmLU{S;8!^cu=jO-)rcpY7hKzHbksWP3J;$0Aq7ZQ@z*XPxW*i z>3ODx|ZTPqv2} zGXbr;aZ^b_D8LY7oynyCEusK|6V`nbxs53|Re_adx{Qh0Zskl2b4iYRNRJ1fMnj&^Eipz`6_4Yw~p`6C5T=OrN z!I4^u#qF*`n45^FQ`B^ATT3{+i1rzR&)dGcCHiCnk1QqI*$#hJFr>fZjcpZDgmU48 z`-mQQRO;5Dk$8we*YEJo0RE93&M?H!0-VP*Zks=-aiJ|-I5(=6ZP>}v{lwb_Mt^&c zbPq#Ml=H%C&8NfGF$_gpIBt(8giN_#n{k9{UAP~j_|qe#C~v9)@~hIJq?2~Q&)fDK zwqYHknm5NEP!I&|8+OXo++%-&1hj-yCR5dI>o9R~R1ZgvXgOg*aVcNjg7Ov`7C;~< zjnk*P1S^XMogqt?7iGr7(X#!eh(D5}k(r5$aa-9y0)KNVVbTWM)Zym6bg*vd!(A>E|t6tn2o)pPo{EtK})%tl_@uJme2I`X@?r)a``xKc-G zl$RSnp8xtve~8u}S;~{Wxq5PHHYV4@<)NjgfJO6W&jwRQ){3+V1yzhmoivnGvBooV zRX(Xy<0G>Qhp7KV4Rd8f&8_7T+7k!ObrHvg zY%c#ql$M9VtRJXIQO@`>+B~Qec#$aDllG|%)|**PAs)!v7>$?9GHIgYx+r=&>nQpB za-sa%p{NMy@^1L@4g(SAl8u9At*)+)_xC4%q40c^X;AqKKY2J@X-ZIVBiFyN7)Pd2y3+ak%M2pnZ7GAl2+PHk0fiVNxmWd-}j4+ah{Lhd12- zgYET*n_!Ftj^|^|k%()F$$PCD6Mfq#NYur$aNC@jW#Ey(%U6qdMhD4Xq z6g^^!MQ(BxfkFqR-I>bf9bL=DPff%YZiZ7`Qhsu!D8%;Bi@zwu|7bnrTk1xJ$|J?{ zO|3m0$#U&uH>L0E#g6YPd+4f`siLSIMJLDhK)kJ?>G@jUR;;P+k6SECbxy>YQA0JS zYX(ji*L$juA#ePG{=cpC`PcIi|LH7J&>%DHG-aN!9{p4{a|@1x&fV$MzaQxnoxnL@ z|2TRFzE(%bMj|&TZgxRl$T~v=2AI&`H0lATgS2r}gF~$K&KQkTf+_t;RO?-XT9jRM zOXF%!7tm)B&f3Yw2o_ht60Db;dL(i>4;5Zn@&Att(CUkn&QbhwmyE+uQ~Gs`Pp{5q zE~qvquvF6{Due5Bej6`QP{;A?d4q`73xg)>k`LEjPZ2_QeZ?k;e3vQ`@K0`&g2n06 zZFN_BxJj$KzcheY5UV&_$HJnQlT|g;*F-7>BCS2|WhGaamQeyyzP$Nqf@W+!`ZkHg zgL}2B8@%Y)t+w#^HF&f+yCVJ!?6yeu-PVglu9wKL|W6IxOBma z3L0U&wJ_O}iD7Ws%F5Ep@c>hXq;JzUGes#MNhAS$(#tlR2mAXJ;hV^FbLtwF+N@4a zTzH*v-$7^T&aE41e?RG!kKOcYqfMY6lQgXrFE8(mcvVaQpKgRQVCVMvxR`RKduAp%e$oLp)CnqOYe^R)h|616&m2hB# zE$--Hzf5vEaYg$l((hC3dM8F^a>7NJ#{=Zxu`Ty_2Kc}OW7L;^(V*@Vx%|X-O z_ncg^i>Z2YhPQOY=hrK`eE#L7Q4@}Ig%zOo{&W7kiee+g={br{|9lZo(URI2{*|VT z;$dorm2rcg24BxlcPsE8QYE)X1c3SK9d7t%>o3BGhi&B)6o^*h>+FglsVbB>42M}S z5!!}DafbgmG%65T|Hj$QJ33{5{biIal`{;rM^MHh)gx30WxZ>ezH3MV2le0GnYpnc zW|IB={Ys76Z8uA;LBxs+>xwD+!w-Md!pY7Mk7m~oTv};q1q{c8(E8GFgm@+%OF&PQ zYD{=mgOaCLFa6-rgbF3{;_VqmS=zZo1|)QPlPx=+|IupmBQ9r4VJt_=6%#(ek`u?B zyaC<%P`yW2+;qB>$awQ4ea4al9T8Q$&C%9zG3_(ic1{3}DbjyHkI2%Ya$2!aPPsH^ z?ljmRQOhf)$5gZa7LUDqQCi8-FK0RwPe3(?DKxu$aBA9j1Kq9A=gnITm*zZ?F)>7c z)41~?1c~pluQELtFWkK=qe28ZJ8C8*aCIs)7kUY(7IO9d{=!L~_Dx?} zn{8CSqMvEbvKu;Ts&t!Pm(-+voQ-9w*4%i$w^UM@dDG{K<4Ix31^&R>RaroP`=zr% zCX=PX7+z>*%^FPI?N^$YUrEqX? zrW2ZKN=k2&1fAG8^*k7!=BJ$=Y&Kf6YL%rSt$#}wt)I4AAuG<)0Ox_)t@3J0Yn_!* zd5|hYQKbtKlf6bvh!-0V+g7^mGB3dCndaI;H zunV>p?0mR4YaXY9`OY(bGBD!35mhRODtgaD965>??m|`li5U-s6rJw2M``*{#luFSI8+(W3F4 zjZeAGR)&kCkQ@X}E5$|Eiu9nu9j}-y-evCR&RS@Qlv^3~T`>oa=kY@NYZWy1)S{TK z>f=hpYGQANDr>ELIJ!1>GpZ6R3?MivT|z>FFeEzZu)2zE3s0kkk(~XqP}yR3)9CKu z;$mgu*x+d1kbFYCV!g>6hlJ#&xCz_)w5NY`hW4rvox><=FF3zq14NT$O~&(3176%) zPJP~C`Kmsy9~UgP8)?SIXExi+_01Se50sk1=H%^qhS7Ru6Lhn1nj$jUSA;Y@eFfMZ zkE!b>DB7XHLtB84O*;W#nY4C&uhDtV}S2n|$B&6N>BI~g2v*Jc(b z=9_I-B|Z#OR}dMBOGV%N|lG@onI(wswh_4zh7^tt{GzI-bv6 zyJ>k|HybUHkxFEH)!!m*>TX*D$kMPPPRR9sM89plo{!H`dq^bfaPlpLUt91>bZpfE=dZxzu_~_ouq^#Pqs)a5{^rtEbN`xhqmFy&J zbiu2+niwwZ7$+4rn-P1r&mdC-`%lAg83QHQSJUQm4}n2R}-F6umbXk%?hS_pXy5+v_~YXX|ik z<6Q1<3=QG7^3Gd7e_mexX_U;CadZoYm!8#GY;Q=pkK=jTJZs0k7N3-Lk_8m8)T=$7gna zAl480yi3HDZG1?u?L0f;_7-QNhzRT_yU%Xop}y$b0vTL*`q90(I_+0PVSbNnLDlNo zdY!xbME=hQ=(z~JkKf3sU{H7YY+P+h1Aj0jXb<<2;jajNHZW%MF}(Ml%w203ri%@s z0fzZ#8#7aSGh=R7F*v-QFj}vtpu2vNVH?%QQC6Q9e>WfwOvoTut#0^R5cuNq^4onS zXdnuBxjz^g+1z830Vk2xOZs;)q~WUG{652Fzij;bz%AG^B5A2QWzwacdiOiRhV|7w z)DkeP)yO8C%i03s41)Am`PR!FF7a3D^zRpS>7E`u4XmvhD=Fv+<85}VbwMFex3yI% zy?Y_eh&$oBOx?QZq~_FQP(Q=N(YbySR>x~5f+WWHr@fP_sI?AqR25CSbT|=v`AQWf z#gn^bb$V20qH(>K(KoKq-`b49T;UV+RCIJB<2%)N2-Hxt)k~r)1dt*N=8KV|C(@lYQ(Z1OtHh|dpH#Xy=_(jg~%uf69N0{2f=B>Saq)_>v@ z9ZeSyAc#<7+E{@)@W(Yh3D@z6A`dH5Cx_zsoZUfBW_bMF(>;TuDO^H)Dmgwq9ef?g zke-^@xWBoMXmzINpxPpqgrHI!gJQMn;{iamrF*(5uEl6^bH?ZOwB73+^s(ANi~vz{ zJ%d5RsG_|RO%9jcf#IqHQCQX%>u?IJZJ1m88s>yk)i4(3S3iA@Gy1MHkv))beSfk# zD{al1GAiu`Q>W#3*EH6)dt81+?&Kigi#*xe;M-GB%a{Ho7fb$`yP9QocRFHx)r`tj zV$Q%^4QY3lwE|pDcFwkU543;SZKV~(>+iJNhl|-e8Xb*a@s|28 zn0wGYd#4PFz3d;yXQs2I%Eu+7jXD^FUNloM^W`S7yfPAt%ltGdDlG6V4;D3JKnTp=Eu82zwJ1SUf~{+_o=UCz2pESfpE1y4qX#{YsQeOqdG`DpN3|bVGje=wSDS-rnt+>gsel4Mc?7_q9nFRjF?#6EteH6?79I;K@s1 z?>5xst;`$LAQOo?82MBBcR~T#*}avOhQNe>52g~Ig5qp(p2hk|iN7W{G&HxXxd6xS z4|TJEwcdpi9+Mwoe}f~_SA32z113P=DtkYwv!N$Jo55xwLeqtMoX24WLLA5K84{#l z^W8y+vl7n*9-dVJpIyo|SB;E}Hhiu)*ywyic3V?QQtIPLmDstRZD;kWv!ZjeyQ#M0 zJf94{m`()4K=yQB+FW0yB40gkuRc3$At_47!`4$M^ut~5OmAZU} zhRC`~Z)`$9u)2kDL4NTZ@x-Q;SYGqx8GkV%QQuNTzI;bd@Z~F|;G?P?l1{}oNq-_r z+*tXYj_O6!v}E;xG`l8zdDV;@B@<#TZVI9}D*2_y&P{2;h}+sQs?|LQpwFWt{G0=U zud?Qeu4l;WudV%xmg+hB3;M`8zPmd@?*vz8?XB(+F4x$cM=vb|NV*{tcMN6PgyMq> zxva~Mdatm(#T^CxvWS*QvfH)kFoHxUC%}GE(kpm zk-4TkO_kpyEdv58iMKiB8Ib?d_5Zj4e4~x9?(d{dFzm-z$-%N|zTAFzB*xFw2`X8B#meE@A_iQ+VDDosrHUjY$All{EkE{uvo^4y) zGfg3ak!n;^nKZ7$y(JU5&yG3Nvao`u^0530(LQ3DZT;SW`23;`sLZ>c3PvW%s<4U} zn^ly*@jl~AxA{L?bO7q=nr}?M>lv#u3GT!zG;W~-Odb&{eEp%7Y9T`UaXvP%ADO-q zfvtV#a_g;F|7}0iwmj?TWCZc^B-Zx1WS9M;NJ3e8UV7C8O~xrg^Hkri`chY^~IXm)!BX=9Xftwqq|ntR$?9Q~plUnk!Gj7cez z&5q}n8{)jC*nrImQ&5oz@S69oWQO8ig)8h3@a%**|Exett`e?;+ z)CIF%ZZCt|d1ipOO=CCRJM&dlx20#GbQ~Jwobq^~14u;7a6m{_O^V1o`O;9BOxB#s5RyTSiqGwf%#lNT-y7fJjMqcL_+Rba!`$w1NnN zNOyN18l<}q-67rG%*J<~ch$z8wvxOo2xIBix#pB`&@$?GC2??RN>#-Qi5#r6!R=Sq7 z<%pIVmGh$k>F{)2^giXXwMOSnq6vg*`e`w`8w+-G!4V#azmH+z48hH2^hcn3OvGs<tMig2g9wqqwLg~#>bgt!~G{|20Z4q()W^b^$c38E4bY?%-nfvT&`gF~Bqk?y%1YHlu7^nPu zHA_J3Vz~aYc}(PMFTum**@LZKmZ2Zk8W2Wa;#WxFN8hkLet}=Ud_r%$ZMTtTE>V5% z@%3QQ7lFg?yEFY&MRY(@(PI4bFGNCqT#v9N6mLnL$*{t&C_K3#K*umEco5Z|w$8x22@9=US67`qS5IwZa2wk~zw zZOq!7uwl`2N$mS8^;;~}efMU-b87kTVroL!X?*RNX-1Z}Stn{yJ(})V_1GJ6H5V9U z7dQ#FTGxd44^xbKt&`6bulcQ;@a{I6((a-LZ(8y^jT$e%RL>1*x5%>oyuCUL4p-=E zUb~qQ>D_6ot3;%&`3dJ1MW$R5AtxtHdP&S1oCG80vt=2~%#Vp@>3O;5a{n&Deeq#=6ie5ei?G1VltGKv z<%D)Ga$_JVBM0sg@+IOnaz*d2GIxFPt7-3tDkp`J^tD9DVO0g=<3%DDRBhwh(bVSN zbyz_2F_BvzWnE$nwu3h!h}fb&Rre6H{W++=i8&o!)f>0OF(JMpT2BFgFJymQI>_^m zL&SG{AU^|UkBD&LU_N60VrfxT6*nq#PA4>E2;4G?fO1%JF=~fp?*e(KT$%kE#Mlk-leZq5Z+0IgiVM=Jl>e9K6nOdqiZ2LsS~U@bnMtPUDdFl~S=>BEL@)zh40S^`P;5F-ZzV-yd=tmThb&l!IhcbH;LaJNn)?>6#2B1F-71p z10!EMsXvsRaO6EaRAkWS28+wUsz!}$7ILXR1r90Tr$v!HMoR+2sW5`~^MAQL|6j!w z{ZGvK|3>1`|2#whk`Mx$FFARV0+uPtn{@%7Gdo4kQ6>f=UJqv0v=-`Uss*2`t8E@v zQe8?4K(lc2K;oI4{X;95t5UfMyx8tcK3RAW@FeO7z;i>&3oUv9GU;~CZQh@12?7<^ zI2=mIVt)VrDBwwSe)i@(`iT4IyTF7-fT#g<70vEvg==$sC>vebyIJe1 zzj4>PzndAF_OG4RSS_6c)&1Sw^Zzr@!mB?U%RZ@U`I#=)W_PCZg-_o0oa^CZg$t>Y zmMOQxofGJn1Rl!*KW3utEV*vX2jvcjNPI4fic)ep;5#~-LFUo4lr#j6o0f)4fp4Lz zs;b+wGu~}+n3|6ZST6S_Bfg2s%F3^z6*uUwY)-BeZ0Pr0_IWVw_kxhLU)nTp?J}%r z0B$B+DCLlU%61;Y%JF#JeVFIZTkG|AHrN-^itdcLs5r;X<;7%Jk?!Xc9{Y)74}-I_ zJ4vjx)=FTR?`f#N(B|>_E5XTHyNly3nMyG0~S~Dp>7wObE&ZXiB3p0dh6EitQ zvL`l~KCYyRi04Ybj=tC!1a6_0dy^l2%{tjZfTCd)q4tFfVFa7a={ikQXV z!yQ+9^-+zLzRktfu@dvmf{f4YeJMx0dZb&0qeH}79^-cpo*@$0=d31e)0l{*ujEpZ z{X7rHdI_25o8Tk3>uN&M;7;9~x2w!=hw`@K^0B&w$GGip?m$z2b9oN3wxF-q-$Xe$ zoSvOKlOrOY?aUO%#E2;c>ypZ@lrGZNwt78gE%xo_rm#bZ zyW5+_$7cp2=x@=!eH~gQnD)Fte!Xp&`J(uL(WPjLzzJ1b&w!=Z1jt)b!_it|&`Qu}}V^58B063u3`ZDg_@$1BYP z6HmZRPXJfyerQ1gK@x0l{_lVP_`x31uA-z;38?_DL7^c$2P$qD&?S)mG?jRT6d0&l zH`+HQeDl6hpw07xLg4qg#3@)lj-%I%t+5>+lNPJ#gIe}(eRk0QuM{Ubl!X2xxpE=_ zFH;}hc*@klP^Nf7I=*==T1QXaZSM!s}!3cUuNzMc8< z_I;kq6$QR9cP1C*cLVI!C!Be1-qmJQ(7eWa7kuWC)TbLWze&FDM5O$TB0yD_cTlHy z{yYRktB?!SN9kc4wWHq`r^&CcZJXTnN9eCmE%2t~ViUL=6OXj}3vs)1PKR_AoVo|< zF(G=x`7;CsX}540_PK4@G}tjY0U63jTmt|zt#%>I@0x!)IrAdh+s&uPrd_u{C;&#B-;KOU`Zjw?CP0C>N}Jz7Zn*Y|Cm)9$64 z`g$Jrdl(k!B>q^7K%yF{&m}JjxhXJ^@{i?aX1D~rYQFUUC2#b&-`pSsE9`c3Hzpt- zQDg+jRPdukryzkf%T?$mG_v1h`@e==d(5x6TJP+ASM;XTJRcWle>j^RoM>IlPo8^5 zJRrUmjYD{9u+*9ftx7I-mXt)4wyT>5D8zpX%2geTz@=I~%Nw#SbtP5R4DO*cE!Y;@ z#pV~)I$IYY)`2{Z*jMMpf*pgwTIHh2<;4No{?YAGxson}#$;FXIlxHLI%__o_ZpTl zvaqo*@q67><>bKq`U;AS?d@%(AmI;$F^GMyqLnW81d;*~v z#x;rQeOCD&EC4Fs*-~>Sl{uOtgO6PP?d#2X+>`K4k_ADsqKiz0DL4FZK#(Ijlw>im z6*6X0o>M%>@qvC-NA#+5-xGqBt8f|%JH5;ZeAbmWSGw;CO=;;2?eUJ6yzO}J230M8#VD^5IIaUCJ zHkZfhcd&2KM(!kHg;QZ8MWk}WYj4WqYVi7&RL5kWwX3oE4*f{Jg*-HL&y>qhMxd43 zGmu<*F?o;mvf%xGY|Lr+j91$W)=U_e5f`JCsXH)`_o-E z)7>5~Foh-T`Qr^OCs662y)+qyb6t|ZzPPdUUp9x;DY^&SI0H zu=FF@?ew(%C*f3FHns^YcvtV~=HU}t@@7|eO`>2Xq;f}ILCCNM^f!4Yl@|*#x1mM!~uL+(WZUeAZgV(wKwTJU` z9M!}CAR=>m?O#*$_YD4S_PD*2x)vzj+vI!XaacZzk+H-It151KzA1ZL{zbOl9ytfs zdb--)8DT({1F(aG?bzbvBv4i_wQ-O`m=i#O9r5EAULKARlcW>&cUr*B6^S z{~$Q>f0j}IFH~ax%OTQ0Eh{tKxAcI402>uXs5N(fx+^9h{VO)MMSuL_Q#k+P0*|W| zkarDY0AWM|_wW!Q-QZxJIlE?9T25%EA~BD_2Wj5WP+4i&HzVEfIp^n2h#>j{SYYLq zOw&r2`uc<&FkSv|*esM+Faq>*r{Sfe()d_u@KUgLMZSH%O-k~h^mk+=h6vc3VDod{T^G zT#)kJnc~8zS3evD^W6Wms01dY0!#WU+1?|P7qwak%>mtM*{QY++{r{vTWa?9h-`9z zD%r;BE+{PA=W&A0&pVAx{{)C6IhX6L)gQxx;z?1X zFh4i4!BHth;#o3)1fK_@Ey zv{MibjE7m~7G~HuI0`)4>GE;0sipb7@AIfe^~z69PV&vSC_%B&83@fv;>7}V;^tI? zxViZ@*ld@KjD8SueSb%m6B&8N&D7hI_xGW_o0OOz_Z5lP?_@4(0}YLOvCdq5ppM~$ zn0r(0-CT#ITWid9HA#O-f=-UY^oz-aTJq#JToOa9^bxX~f$(5oI|nQ@Sshoz0J!H{?Ny7xOpWpLR&*L)$CMYqC>!xhdSZ2z8;^EvAVdpu-H7v@3<26J157_Pe%pW{o#FyZ|b7msYth6 zYcZ&z|Kec>Yqyx2>vyG%%O%w;XE?z!Eo!bWrx@TL(94F)EOD7F=fN=WqM`ktPs z7{E_KRDWmi`!D%kBYyfM|MBL!=KPx^)lo+N_NrTcIsyCsH{*s2qJ3kjVRvjFr~S~p z{IJbS#u9Ey9Lm6;q)GP64B=M-baz?^a&sbYqh51EQbe|If}Q;39m}0YKgVb+lQNv= z$G-3TxaxQ+AxNCG9=-@z@jLl(H{3qB@%BPw@Z*ua!p(aN3qXzYefv@8etR&394jsJ z9W?&aRTTrhgPx%MYuj4E-N<2-Gf}-*=n0v)d+C08RK>_r>_o$+qSDiSNz4zaU_4~t zH^&t%U&|dv-}{_XR3t6$_--@O$k-e$*)lQ{;3r>(7BVS^gbhK12g>I!2CrZ(Sd`W@ zXiGScg^(7UckYNizJ{yt7CQ`PxvZtjse z+%OP(2;CFfggb8~WuxO`=U@5r6N`l+B2zXyJ+nP$V{~-#ldMds2?^Bx6|hf^)i~H5 zK5qe_@gq0Wb*`>Y>_Aei?w4E|OM0-ErV+b>nlIbf81x+PVjdw640(LQ@LB+1%3kuZ zwy^40JAIsQe4z-DMb#yCa>mW%^5O~PKa@qQgXGf z#@z+ZTuXz*pNy3G{}q(_griYrRm;%S;!=x@^i!ntOzD;9 zouH@cBDIiHl11laXH$6>f~7|oc^>08yMx*@p}|OAk+HgEsgYucTdS7lu4*e@so=gn zDB{z-LF*0dd4oyZ`lB4WHZ#rrBZ9tXMI8T=SZlC@W~6V-9z%!&Ssgl1?QwfG znp&DuG=2gS6cdUr?pZ4-NYrxK4XFY;&xAI4XUF z=~JP+WSGu`5RdC=3fx4olTbIWsBTm9UCY=SW;Hk~+yI99#j%;H4`$;9s6Xj}em!Zy z>#po8sHRe%E$Q&p^6K>bWt`?Hhfai`op7*Q!0flfoueZ*d7Q1QvuhUm>JnQXn{&cl z9(qz-DLQ=8$o*jh@FjjNeCI+^%3DH+NWq@`k`1UGko z=K&h7>;C%imixPaM5(#3^v}7zT)OWt1Ucq^AsQN_bU$3&>Mro|T%HymZ;fUQZ02_c zhJx70YBV`u2s8u^%5k&Hf7%Ms||MWQ& zwtd?AOaF{>;^eXJttU^Jq|HDODM{}vpD8|zTF3bKa;)K;zZ#59Fd5C=(aMKtM53l| zdH5avNXn`}KO;Kv&KWm3H7UNEbe4_F6R)31?_jIQStzlYADyH6V)r1)Q_f3lG&*yx zly?~Uj6DahDOCDHPJ=}u)_-5+Gh|1WXq;6;!u)8--@jw%9^J#&XJ?b067`qaoSE9$ z$WQwv=|4+$9bh(tYGtqd}N0j z+xcn*Ct2x?#rngdpY)v6h-_$AZ`(HQuf2%8cD_(;jZ);v0zcoDQ!r98jF=5~Kz^<5 zUYiUB9x9{>BPwr#aR;A@mfGW-dbF?40Kg9*@uPKhuG%??-MlDobj-igV(evH#pZNlS6pREUzsS&Whf+P9Q|!s_p(0e%z@Y&F?h#dS*qkg)$?)%gv6>e3SG)={scBu$EQvgjBj`8Cem-=IMfaE*Dl(ajKZ@X+I#Tfo;pSPEl78J1OaltHk!6{=!a3EzgNaZ|>e>!HK z4LIiOCthT55n?@OU}%`Fx%{5>6_kuEc|XXo2VY?!_$M1<5gAFK#k#f2#bR23V@sU+ zqhE=G7B&Jp`s4lOQe|Z&A1^OiI3^}0kL!Wecush3F6FgWGQa2Ih~QFYCQm*G7d=u9 zc%YxS7K`=0x@8{M!~XAVV88$VnuY0MCKJ81qRgJt{p^cW1B6XW**clmo%!9nXB4;$ zI(IA8IyyS0LrKS%mz1f*>GHK!*M0k%4^i&>sgG85t^y8IKj_%ZOMMio{pXO`7@qEy z?UmPYMXDUbdvpgaWdJjrvyf3xL=BIDET$D#&(C;@w&3b*7@&>IPks?0BArF?AIYy7 z-D)$Xy4{y(`+5cvPA8u8P;v~XG=DD9DZS=>6%-V-!eMi9yiaFd=X^Uf{cYUp?d&-r zCmA>Q$FY>C1SF{dW0&p4+mWAZpfvsz2C~o25|%iCvKVBlya@hYi|fRe>YPNjA@y@wj?es#SWp@0xTFRc0kuq@{6qJNPJcri4M$f~CZ=|=r zI?a0^q{F*-f1(J$6m+5BLr@L5r*b& zpbmLVDqzBa=+0M zwN@V`2Hac*ylJyt?CbgPC`>>7qq)iR{NjMBiLjTls!7nsCZ*hX7edJ09v#K%Q>}L_ zC-5lT(K#7``%}s4gxNQb{Kti74so-)Pr_FZ=yXWM0b1iz?k!QY2SXdzN<^Il#^k6<( z2fwJx-@lDMc`5umzt@?Yu0SeV;b&p-%~0as9<>dhmvja*-k~S+djFWMC^HALQ*JJ9 zF!)4AYSX`;W2O!{LrcY+$H(ADGVeroG(5B`Yu9263#?A*a?vR^*Ha4HW|h^|)%oVy zgrlP16(8IrskoU1VJe3ke|wF7r|NYz1rV@d-qUvVBaGTl1vv`;+c_TASvli!-&X*JCTccY{*3n45nvhCPyb~G6m4H0YkQul9Fbw z7tvQ4_v`Diu$!_{RCbxt6h1OM^2D5i3k%$rINhsJQFE9XTeuEXPDg1l%D0hU{5FTe z*ijpK0jzZOt%kXpus3(BBfs+g{#MXSz~fGN(Ds~}M1QPG9rA;IgvXs^{nf-3JCEl~ z1Wm)mk>8MN+?TNR01a%XHre>&mlFr;8^=orP5bi=R&(W88bc}Q!Lo8&Zu=|ahtuCq z;7_+eydF!7li4N_1}F8_ACle|(;&$!rTIQ-&h_S^;qdh2#PXphI!ei6`ics;zc6mT zej+py^>TSbPX4AlN2sCi)-*Za31KcI?EPwA$INMlfk;nhf0Rw~P%^iLxp}ZooyX<@ zpD_-OB)JGPOF>_Vw{_NCpdj<&QK3btiGuuy|0))CxEt>x;0=S71G8FR-0C*@ym+tu zmGg6}Rh9uyl-y9^)Hh7mgNxm@sg}~EnNvK@w>GG@ocevz?1}f6!Okh#JaktV4QrHg zB5U)dcOOwK2tb%*@txi)u$CK$*B1c*&;jsHeG+}|CD@qd9DTUb4;qLhoAHSWF_9Cj(sn(Mr%7TM~CBStN$h;E!)-op^9P|Cf9x2>3aTo9{nsB*M1 zwB@jv&nn#*uo=zh1nXT!L0^%Ng6O;^w9>OiY{~m@qMAm!r6CsPUQYodiv8|EGdmu! zU^ax%NN;P|kEJ=TTiN*La^LZC(K~PWeCt3(#*;1V`66F^`;goIjQ|Z!{PJo^)2(ic z?B4!@$QZ)hPcMgeWC|k3dVgV2w$NXuCj^pxRkA7B-|%WmD@`rU6iH0stIsdYPv&&a z5knTCCV^>~gyc|ATpozKm>sGPW;oGsYZCK&@S3+ZtRdm~u%P>h1U5O}qMc1j&gOgQ zP)7WCJeX&(eW-%cJnmTG_F0H?2~^0$ z#>7MKaHxgDHj!`Bvex3f@9z@r&5y4wrg}>y`z^)yhJSb1-qK&*K6*D8&$Uc2gsv`4 zT^7C!%WlWmTHYwgEJi)2j>}`MG{XO+uArdMAIm^l!RvhkotldEGD)l14at_GW^1E= zySnEmB7V8Y^DHLa7SBf}{Jf-~DM1YLIPHT#stz!n-Mj8CjqQs(hbvM$-_67HL+NT@ z5RG2+O6|I+C%$H+fA|Z+u$DtCz&Uyc2cv&nsnprsaQ<>kBfj3$ofMp!Zf$BvYY!_q zS&ZE)$m_Xk{(&Chm-h9xR)yc{>|oS-XfHkrmwLNRHO$9}gLQBAdO1ws{%$u7=0Se) zJsaFli4Pd^T)l;sn{xaln7~x(9reDXg=foS@+|*IM5bNS{o_f0!mvokk~q`Ry#>t6 z#dj;>4w#G9`G_C-rA!G6%5?8Do0T`Oz1nHsuwR*dSs)f88kd_(;{#)7(xF#lL`U1>&#Qa05u zYM|z{C928`6c&b*axy85B{u~8VeV+eI2!{gD|_plmR(RpB~v0U7X#7d$X`&`WGE=j zfJVfsNE5IIU$>kH>g0X>zg0QSi1>ny@Z)?PkBif_hvw-m93P)HGIC|ZC251IRRgHN zC@8Z95guHpQXoUJ@<#!wOr#;`MEp0o#1DYdk+Udrq(t`L5Gsls(_O4s!%adDy;Q9Ktt9SVugRHN30x ztgNg)OGlp-6n=sLS+Kd5m)oakb2n63&XtRJZmB;wOrmgW8@KBw&NbA_FRia_>G|$m z_0F*55_0*x+Tn;=`#mi=3Jd%{%MGV=10zN@5O-X4U=p6L z#^UtvY0hB;CPY2S&~DfM9^ZWR#vC6iK1i)u#>9`0!-7iels(u-vt019yd&r>8H-2y?E7zv3-(y6*D?kAc(4*5V)*{lWB!tAV0J z$k4*86oH?-Un(~PF8AhqcP|KKWWrN@)VRs?-m$ikUR#b&5^&fOys1uNa#ma(X%*#N zy`6jXM*mB*)d|EWN0&>g*Jmdb;khZk3=!{1tu*Jb#G)J}sHy1}n;nV0jA&`F$a1r6 z?kx#fWs~o#gX*Z}@w}vynB0>r#1^VIm~E`CJPgUqIh^lZb%L2UdzzX&wh{N$`%Sni zEXsIwPU@V0&AKN32MdsDABeqU>?)zC%#_0pCR64^ksL&}DK*L64k6=8r8EbgpS4x2 zcj#hb-O{OAi#$BuCs&kmh5%++UDatr$%44WD|}v4XP+#Be$7K6`uQUGNAadSF^32@ z2m%70aLE+IC?KY4D_OX5{>#jxsW3bXh_I=LV|2{q@2#gJL<&>R|CKbrW)#`-tz2Oc zufN~xRYJi56Umpii$pgc`p3KDc1Sj}=LImF-UItG=E8h&gEwZxS5H;PQroM)aUOEH z1ChuPCr(zp!QU^~yqw%l>nPudF6A!;UT4njVCW1L9%bScC)d}EQh7kOyS3}IdAD6f z-s_yo%w2;dlUZ@MEbYR?eI$etcEJJwL z82FB-C;GwADvoM(YKAoh(Te)Y+<@v_WS;Ad=o1aa(cN(ZcEYe6&+jSRu2p=8Iugo6 zEvvYly{@Svw}VSJn_dE{>l+gU5y!l-chwhDh#PP4!p8dGNpc@Bt)*lt1Q?9FV&F>U;S4X$W+U9hNt5C~17~-bF#LUk?Q2K?B znUH_TVf#?z1M<@iH)M}~9q<^=c%a!aO)^=n?XMNdOkJMYSB|ll?XDi`N8+4Qm!4>k zOcZ-PzZX57bGx2qQ3Pl_qOc51^3d`rQzZwQ+G*K?F?oGGd-743fY%G9DgDCON9*!w+BSx^8crx{-pHHm+HPyIvJDlB zmhsO2!codjroJYK9m|0S5h&R04%#|{bbZtF(^odeE`VEjTXzT#0ao3%5=iVav-9hY z3K=GCuDY{}9RV%Erb))IV$u=TScNAr$WLd!CQgP@F+zgieY54n9ik*GZwPX+3U;db z?{J=Ao!yI9Di6P6CJ-#_1~aZGha;gC#>ja@+dE&MOPfZZg>4Quxvc#Tt#EKHEm5W( zo0#xZRP4uvW79TJFt}=`ZKub|apExewks-@ztRx!zFqe^0y=4m-6?L2TW22jK<%Jt zs2F-344W>8l-x>7)wQ_P1!Jq~ylvC|U*J<8jc>v0D14!XP+wH(6q4S7j#}}Wl1Hoi znxOQRu-Yp`!;iF2Aal!G7w@(+u8U%8Ma6NC%RSXok-1PEF;SBpPubI>vf?W*y~32Y z7gAe;9X~Vqw5m(rKAB!droxkP>IHZMbi=R;NujiPd3lT~DyI&WGqYec$2+x6X%#lL z$E@FW(QKjIwhTpgY#H@9kN9y(4KH$K@aOvaUe!+*71LfG2ne$s@Y!|b#2A~K#{N>uso4Q1?XzZCENkR)jtskvsE632&DlnxlAeN2;Tl` z_zBrw{IUHcdFggsNn?uqMed4}0H;&)hTthb1U?V)+K0W#dpf_4M9JE{gH{6QI4>f!Dzn#XsCHcIW`KIhvRV;6BC125DnmF z{?yNXAVmu#W%VelMB65`%24Qr&gn$;rIs|4M62(X>WQ<#vt=di4cy>a5}-WcjaVP# z+nfCu7Ui(yM z2O9bRH(53{pqC<($S896<~>K+2AtaBR-(F)@k;0G9@9!oYZ?;!#bfREpz3~toU~~z z1D22TC${iYF3CI)N(tFesZT#r`BS43hKxoC_cSl}CRN15QaroF6-I$4i}q#***}2< zl-OXb2u2JDqp+|jfOc+eG9XwK$fh6;4Gw}F?98gFvy0?gTW03&A8$WmyaJdz$aVpw z{2keidiO;MWAd*g4K+0~Dp_p2SgmFcz76*z2>aYZak7*qrP;txFJhe++lq6P0#R2*oPz~fYP#zCkr#>4fe>YGA; z@#FrWM`CelF0$qhSSj)B8P1)Y>s=1aOf6AafbtIwxdqXf(rj;`y}v%j_`kw9E)Hhs z?k1C00^nccZ|OEV?2B3PCes&40g;mILjS~(X3gQp3g`rIVjy1%%d_|y0(4ix#_Wig zq}W_L|Xa|P0YR{Ngs`HLJW`JCYpPz3~I$XE; zQ&BHrt1QQ=PFA9n<}{XWgFVm5D3-7c0c4ts(&a* zThjsA2O$xuK8eX9qRHu-ubn&uANety(1>_c+E(QMTNUCs-JEZ}4Mbh@T1ih9vNy;j zf9-04y5qs8iB)X}#PX5mUH|z60$h6ID-9C^#N`zEY~(UiT~GJk`mj8ob#yq@X_8G~ z^r!_zn%2NTUo*kAyrw42y-ZgiQ#;*&XgH&Y%)u&%WuPZIP=@)|{#K3G9aEFHTDa!*@^#{z(PW(az40&%KtC`rCMK$_%P%IwE4<{R(oDswC< zs|ylx%ks8{n&6N4hx8bi>4>;3!HQ*UVI?Xbz{0|0QdvzTCI%Gc&k(z2T2qiDfk@&= zQ#?dwFekG(CMiKjUY;z4-qz@I)3;7bnSv9LhY1arko)PKnh`%PlO&ng7UvEz>KmX zM09qp9wOvf*0(u_WlR4*#1UN|=~gyPI{3DZtEwUXmbr5H$b4o|@#)>DJAytx`i=VXPF!v=i0leV;Br5?n`M+o=e$2Z znisS(`FJ6G3nFart6AT2(LQ?~9pG*0Rte&xH-_%v0SeDvTm(c(tvYY`XBTUobF0Ih z*E73!EI6Z-QvyXL?p@4xoz^ZEifU%Oy*xgZ1f2wA2hC)USn@SEgD9&AIX5_uOfr&!ZI;U*i0QC&v#bMUx(ZcY16!{5n*Yh~E6xWN8-e z;tY1;)h`!rh-)3TOH)_#$2J@;GvSA`m!&dzjq!P|WQ2xRwCLK_TJ#7$`m7>;GH~bv`n-29uH9Ti z5{Y>oqAWuGj%-s`=E|^+Of_M=`UGZ*dHHRD2WdyolxBh7O5T@`4``K!7sI@uEv4vL zx@K?rjh-n7`#+`oTvh<%uZ8Ti(a1N)Jt)^#A*j5;Gw1wW4$=bwula?_%77+o5Q!o# zn`CZowme=*AmqF{R|sF!3$$jy((b>yG$Ql>9*Z>Zt7SiFiqoFn%Ce|*`nj$l+}Q>f zhX}7LSoTm6f(CjbLLza#!YbD3W{@78p{b2_xJFT#G*d z#Nbe755nB!h3L<+2Gn#4I%@9VVTOD6LAagw&?6Eup#%MLHE6!;J6;e_6!;Aod5IU_ zZa^ogi4lr&X}D1+<#-|3eGkp7k|+tK||k|8}nv*GhMNmo+h zwj{h#EjA_#D!w6XpbKI9N6`uqG26`ex28#HXsB!O`rLd6TEaI>tdtxe`U{JRVf7;_ zK~Z|^*!YCK^={SXpHXX`%TF5|9BglR)0Q$R4A*#yQDg>{(Z607Cc;Jpfuxg~j_&Vitrvg9@Min3XDv;I|1C-of=8in zMnVz$vro=|3hBj$2S_9WmAryJsARK8&B|g&M&yGC;m);l^B{eFeLz8Pv10e>Q)t*f zCBd~X3%(5lmqnaR4hU2RA3F)Gu`$<-dRgqmMEf{>k6*=Cd<8H}( ztvB@I!vP}M!o==RVB-gyKd?|TW|pz<-v<#C$taX2dOCRd*m}#dCA~wjYMb!CH?pe- zJZ&wG{x2xjCG1~Nq)ov!SmC2MEv+{WLRrj&c93d5zbJg9_(xz{5P_r4QW=Dqm?gM}(c|AJx}BEQo<2>qisXU|3M zJZ%TgDwWKk{^Fk+0gQJyGq(yQcEJh9XZ#uSQ+4yFj#o+^%da#z_(DQ%Ina+@Scp2$ z8KFMmzcPeqab|kZFNlhiM>%r2ETCg^f(sZf^p`lzSKf@?U6gRTD%#GJVt@Y5~@w< zN97us$v^*|#+5JMz;7^E&;6ds^^JVctDe#)d-K2i1(X&}`duJ4($huafr}I!H24E6 zERlX>6otU1&8e4x$rc8Kg+LPYPpt5CR)xyfjD8r3ANHP}KJXpGJUy3Z-z21EXX-BB zu@z@!WtHac?oH=}iHC3#lh&Qo2vGbW)VHuwF4WA<%FfNnZfK~Bl!N+_QaU+Td3&Bm zR?UZdxiOrK7Ug3}WFoaV=K^(JO379h2~dd!hp-x+aK5*VfgH}FCf<2mI=NJZxL{@e zULW^=5-RXh8H%F>Exo1ZIQUyww#yMDoNl`LBMYXL=xk*zPmYs}P2Kf?kCAmGQ#fi> zdA6D8z{W0Dnde{6;P5*t!DauWsDVQTU^#hALp~j66cz1(C@{IyCJcm^U=;dS&v-op ztM!Rak&TQrGiYC*e}YSyZE>q&ggYiO3E~dYux^K?MH!KRH@o?s1iL2I30BqzKf#gN zdX)$pZMB^pyJ%4M^y^QhYsd5+?aY4Dkd>7^NY#AMz8j213EpD#2j=u`TV`=|VrkLa zPL3&?d5`2@ZE53#d)Dc-4s3V0yc)GTKolCHz3~e%6Bu{kb5dro&~k;aPhlF5my;kY!9YJ6xT>L3mpeQ9<9(rD zSBIvc;BN^v6%l(X99Ej&p;F>h2hUEA1cbNLU z+`46xC&r)y{S04jZT0`{REmVefESzb{<6LOyzc@&zk*yP$$qwDK$5z+s5pU(~3#nap4GVn)n zSo#zo=4km|kbUn~7zNo5jSbF03o44AEC%t=;=gsTDUFw91|^#TZ`zFqx42x2Hxa>7 zZxdf&G2SslL<*O<*)ScYXY&->b>=V&_7k2k&?HcMY4*va&7M z%g;Xktos90obz)H1Bq;dlQ|RVhPi-ZO+WUM*aG0kfle~mo@AwbU*M(N&(!EzmZ_13 zp!&1P8B=}D1;g6LDSmA4jjmj6JA$v@Xix-MVNqfspugeD! zH$Hie{H%l!koYz^)C)tA2K%Apok<+j;fsbN2pCP5!+^~MgScXcQbBxMXMW`-@b0O$ z6A;?{8T(YoR*6C`NC_mQ#ILrQu=9LSC4K#b4d%J8mv985NbWx)*#@ zWre{X$?;{hWn`F(I>zRIDI?#Q(GE!G1;Qr1-CNEb;~f!!Z?Xa}Y9)w+^EBg`Q%$|N zRv@t#t}}KW(RXCQa@%)ya1D@g*?ed(U@teyRPGei)n!Jd!Jrml94)rY%^gk=aKnC? zPfkjM{7LBOy@F!FJX_Y_WRw+Q+=d+|^I=B9=QQ99WP=$Nj_IY%H$Y5fe4_9CWmEVq z&Gnxqp$N9{Q_7~4=u2=rZ_Gy-_v0}nm6ql<*gmFjS8gsgdLX)(gSn4tx3|Hi8$%C3 z-2-Tocdr+k+}X}2!qAc%!1%*#SM*W-*UT8z7(J$p0ouEhEhRTp{11O`!hL}! z7Sh7=^=bSfRv-8IAv(v5^tN=bKvNO$*Myzl;>efF1gUFX|e zGqB=W>#6&9$Ms4zeQ0_*S>nIf38=Bdsg7U7RlqUU)>Z8WTms^&e6C@XLe69eJ08a9 za)12kpFJaGY6TzWgoOo#=DIpL4O{6x@o$%#3|Yn6Qc?MT0s#}1xYRGzEG!acGFslM zfDWCG@`1trga=XmXqAA9%WVd-cO%oo(^J((_F1K_bpl&I5}Y=Nv-pwc0H3v=V?Z3% zLZ9@-bFH|#_ta!{w83vHG{Te#@){Zq(2~1JW;8%xla$@Fu|5#QF zTJE+(d3hkGk%o>%4IiI0q*Ae$qz@$a@jDnNFe);N*7GNlApjJGcqe~p&rzoVxUtg@ z;5X?RCOU@u%wUdu6i2|9Cq=@=2ylp?l5#9m^&%s@r&x3P@wt8M61ga5v-)^ZOoW`g z{%mKh`f_Cyz*{nW6aweoX}f-P9VqJtSqDd?5jz`FVYigp>+3<`C>$S5t|1hWQL6pU zwq{O9BzQRz@Fj(-*v$i6BEXZv&)Yrh0>F7Xmj-@)_jzm=msiWWcN%^^I;e_O%(xK* z0rAA?2V&s6F6=D@km$zM)M#D}iG0K*%P)BLD%hPFELjjDDMuKY=cM{p9@V`!&gIGF zG zg|HnUWy+VE;k5&%Vn-m(^IxYds>o=(cbpNPF@q{$tXU|=I56fRTfEpJ9P0n`?_)Cn zdI6$fZh>lEg}1;)7jtV@T9!KEcbFPYt!?cru(bQrH)MA>rfYbE3s|o;Jqbag3~(>s zHvpg@W3SwiM{0KB+xs91K<|46QahxQ)T#V|P;gpS-2a>S9~Ky9Qv8ZoUE*6#Xp|&P zDO3Ri^E*ehqI|0Y89FmK17Wno^DLns;>DdwRRW@cj+V?@M3I{ko z{*OPm07J@-|8BffGN3gT>)=Bb?yoA&6ud~<4Tjbp@ zWcZ6y)tIgns3z?%nsN9^zv1xUYs@PDV@%Oie}}d~A>QGVjuZJ&y&p^%PH)`e^!4?< z9dowm;a|RpYx~h1EYuTGYrlSPQ(LTdTuK-CPET)d0Uzn`eBx>WaL!rz$Nn1A;*X)W zcAeLJ$GTi>@OvbQ-G{4B(>ZyT1w(aXL7nGFoT;0dWq64_Kgs4x+pbA@? z#=@c@l~_b5o=K6HJ_(tmDq>=$`2*@zykVApymsCP)f;n#F$2RIS?|lUz?|_6(N@}* z_eGo>X#!ChrFDKC4`wZ}Y+n~(vvvmcBBR77yx&`P$Yd)L<^z~40O#u@Ac`2l%(@v~ zcFYC%JA)#)3B+?f#Q&NB>%DM!AV0DgfgrnQE6%if8?K_1!V%`}4=@~QQz3`4;vZcI zC<(t66(y%7X>UJ&jY)EL8`>cklg(?>IdgTDO8z*@?YyvsXfJ-NqO!l&{0d+wsAP*i zN0>6nv2g7TFByC%6qnp zxwWaJKJ-NUO?0{Y%d%xv;~Ov||0C}qv+>~SU>+IJh6h|v`eKExZ_G0A@RUiX9>g9j zB@JF+)<%#04;FCm5d~zF{fxu?0MK99?<^hd4exq8_~bUp3iHk-Pa{?wkqa*Uo|p@s0Sn_ntZ;U9hYM9vK#|A#fvS;_EU62kK* zoCQE_UjGL+aRkTk8-x!fEo0{>Rf;!uO~GLBmQQ?=3Z$D}N9~j`*0ssTVHoKx|G5}bSNOF*`EBC=KEnQoipWR|Ege2i zfy_J}P45j`=ZhSBC z56r@{O-=?x!L5aAG0$lJPj$0}a={o=&N%bi&!=i2yeqaDQ<;PMQ$EII=kGc$3G7#2 zFkY}WRB;Vg6-CsD_SUal*giX1G{-EQ6;%%wH%N$WZn+6nE(S|syrlm0sfK6c{0%Wt zfz?PsX%)?_1EUIW=hu9Q)yVd1AdVo=79c@?9o|en@$#ioVFCXY}Psh z#4EtFv_&b6ZB|!X8;QzX{I2}zIdCPZnBxEX8|k05?7v_BL43#*`Rdhs$bSNHs*GrA zBtL5CSVb@rXhj1MoIGZ2-+yqHp_l%H$=^|K)5_?Ii;Gp&KYgBm1%0|fp`WqME@$Yz zgR*EW1nn#|6N4+i3;|CClBZ;_|L27QKK%cPEm-kNz_~d?k0=;H15{u&Psq?6GsoG4 zt^+lCC>W^B04Pd+amBVw!OiVa^Lu-Mm7@1_s|7nL(ZQX)!`i(1>xrz0L%FqhFvvxBr_DFfewgNp6&u2E>6`({MDM8mw(bx2+E(}f2V`Y z_*D^baCrHIGC}yzH;o$dphmujD7^3u-Y*9Ymynn$&C#ex`2@Li8}veeFUj&$d|598 zPbV><1BU>2$6cPp#qmauDiG{^(NUBj?1R2zq0%5Oi&RWY1niN}fFnmMTh_rTV*8;r zqdstjtLo9=$N@DSY#uPS^dUm=@WGFhU57fEiwW={!3CDpWaDA0MF>wBi^9vGc=K=A z@TLfLcPhxd?p(~mM_9No*D zKS08@o34%!H}M*hc{|5x6FB7Llmk~24VEw}=mgQ|HFWv#4 zjz*v!ALJ6}``|k|?(^DwPA3-?`7NfXO`MOj`_v4w5j4SMDc{zAnlr(;^Gg%Um1*7` zUv-DuJ@Q@#gPyCIPn-{x7kSOZVPwY<&c-9qp+FlnJG)SeZZ?#F^?7 zJt!<@k7WiOGT9CoC1WY{p2DoTSxfiah6IV$1x&1eAQn} z0u5qHGfcu%YfxS|yzs|Fj{@4DHyG%1y|lGowWSQ@=mLSKC{dlSKpn{B$+3Yes%HyI zF-HbGjA$pev;hSmVA=6z6tw(_k*q=`{3?%s^fT;3#N}_R75kIIKK{id;8rV?gVY=$ zbKi%Zc)w8quXj{re1wqHR_(-AE{-@eeZ(*_Ooi+BE@ z(^+KIsw$lv9u|G@;XQ5Fpa>3fUXIf>KGVi#N>UcGBsUu{^OE5`og>3FT80}9KE@K* zolJNQgGs*fI2QPwfSW=EgX0AZIp`H7%0jUaY)K+F70O-Mc0ut^TmHm=%}O{(}|m5^+P`G0lM^Ao{_;x>E#=!>PaLMQ;=4n zcJda(hXx}*eEbVWO9-nP1KGY|f1!}ag<=3-KeJLSO{Jd5T7^p6Ij5n0J|dZ@X;tcC z_rfYQu>}upAh+IHhdDX*Yw7rNoa4w&FfdrI0#Um8p+}>w(#fjeKO8DZE{OE6c9XIp z#lE7)4{#Xj4*2UE-Rz=DqiIuZL#f`DtylZ!Y}oFZ4h6+3^**F?n2lRa95=q28W)38 zOC3#^sqK@a-9EBKh7uo`cGlESvD7hwHWIy=1NtF!qzNIiK#wYXs)EqRxiUggKu|dr zjUbosEKNwB>@Q7IJ@w9gqvO@TK~#Lj z#{VY9BX~W{ZA{_g=hP(oD}q1ga=9I0WkSBOh+neWI7=6tf%J4*!KKIc2JDI3Tf<*< zJ1;u0TO;EfMNe)x?owWl7*o3Sstn`dX)>0)SHAjJmmrF`cUB#1{wt4P-u7Cj9;>ar z_H0$ddVw(DC0%NVjflXp=l(kM^7N_)%)2q(hYfAh$+9!h6^W;62NI_+QGt>ZA1*JQ z(ATKntFNHNOE;;)vGH}eRJp;_bmD4wcQO4?V{89zH>Pd)NR+ZN%DN@dY)COjNR%qjn=;``B}M(3aD`F5-_bE`?*)V%ZnjMqPn%ABU6OP2td$yOQUpjTgh&K7m%@`myC&+YIuf;-{&ph~bWHyBD26<^h%Q+|aMi08bB#t3YTj2Re*GK8z$(a}pYu7_`WskxQbii}c| z?&U9e9rE%zRRV~v>yp#`Ug=OA#QY6m6kaj8%dS{c!{(*Um)rb79iH&nlWgw(=8Wxn z;^(+_0j_87gkbr}GGT7zk_P zbW(Y7BQgED>i63}6N`EgQH8kLqe(D1YmM%%WSB0U98+*y0pG}veE?sS5O8=ZiA*1M z{800mb`Nlv`?+xv?)x#JYdFWR?~FwJ_*H<U{R`b?Gm?G=-13Q ztq$95wLhJ{p{nEvcP+DB_N}{OvG|g@pXs){#r`1e60s`@&27!pRUENG_|DWcjYlwo z%SQ4tV9HwhdlQfN;=PzTbDEpak9d2Ecx)+KB?19X1zGG1X}qv5A>X^R`1KMYLq``y zvfSZZLHA&I1n%8eazeCdAS7t)G){QkT-;C3c71zeEU?^RX{s_&cPjBpfYiBCu-Hgs zw$Z%Spuzo;i)b=f(8+>VF{$0}yl$k_$3tFA3`kb2ydWbT)`~>5zh%!7sr$E$x}mEwm;ErDWxZ!cyck;QWI{5cX#eIvlwKDqW`>tZe;i%`G02laU5hdoDt-4J+r7ODmPE zK-ldZ66{XNXc!Is*W`d=-v_{Xn!SMr%kZp$nJgaF7;gnbK?dMp{)`mpyB91(rpL_7(18xcZs7F&u z7$_W>P|UIa1(^}=X9J6vHZ{8;q5^yN!{-maj_S2M106VAUa|MN=&&nR;Wq9 z?*se3Xzcdv%0rv-An(OMvT0e>mYK%C zDfbbnjx6BFZs~W+<@!za3YrVnuV=c0lk~I06j>At^bV^+@PlV~-`plv4M>R$BS>aEPEPH*bXnNJ=5x_$ z>qWHQkzN||v5UmX>E?WhDz?`Hfmr)*Da8>|Om73klT3QKK`G?TSE1jem5gi4u31-A}Acv&can9i5x zqV`DzZIlW({Z_pHgWq|&_Jpg>5+bTuz++tyzg?g)Ur?gl-C+Z)95k1vb&d6J zRz~=N<-;@H?Nbw0i2a??b|O^MWTCjC7^MS%;DMl}4*gu^novQT)F9Q~x-HStLj-l|7X@kbKTpW-VeS8m;TQII?K{34Mu;|XrXU(x$QsM&^;S;@e0(ew9r=i! zrgID+^wTjDCLJTcXs`Op$+nS-eig`V&B74KeWfP)4N8NfZlmNY{+!m0cr0KY(p>!Y zQa<|?tM@PKgr7PE>yv088fJW!G8_g%1`FXkX4X*~uq&Bzl)iS}S5S@$m^}i^4PT9U zbji=oz)K;4tUns(Wb)EpW--(YEAj3N>%nmAT9i!i2I{_a(-)iLbXwW*f)Vvzl-aUfdUV}p)_ z2`^M&O@kYv!RJi=X0e5BlNHKGh0 zO=N;}YYRoNwmn`C{RxLMO8q(Ks*#5Cxl&LLBP!ZrN5=L}O0ONCH zydYIX>tdIARhp;tr zFZePcuDl^0o=0v3m9JN$zL#hL3;qtm0~zLFWG{0gGSBq{E~rR{fuvvh1&(Yg-aKnO z;T}Wn0lmrJYLzPZG7oV+OqTS0IqKB=Rm7XDkU?yj(bw6^(c|vf0muS@s1!B?0|qHMy%rU|FSPp3 z{1{_E$A+z_?uHvaAX`9XtAU+VS|x+YA2^G&R*)!2%hI8wK=|u7IzxWA?wfZ8E-kb| zMMal8(7H%X!t#P?<*SO0JtNfwvKaQ{XqZ3isP$otg;v5hBESeC?y5XlmEeh~hXL!? zW@q6juC)k*DfYl33x~VMC$6YWy{0o0uF4d_s#ubxybLkw1)d7hfj;4n2&n~t!@W3~>VFTu z`^^f#CoDKxI`uHvyQp$@n|vKTDzE8n#-!Iung!@c5N8OUEHxqxl%p0Q`~s^cMDnV_ z8w7*)(&CzWLBJA^2?gpQ;0##C83!0T*G*s6ZK~kn{tRvdh2Rkn2G?Dxvar1DWeCQ> z^~=?NWNG&^zAWAG%Yf7ru&u%vI{JVDU@tGp5YeN_ z^xx=SGww8}<@WLk=0XKJ5celdSvNU~G#Mi&?G0JpcM%A3^d3sLL$_+6_^l8vXZ!gp z?YC0OHYEi`nHx`mqR2X#9{S^a@4Cnjv;9tVth73T&gir53xF z%#4qQRIt8WrcM!n z6$g?uC;+!-4@r$j1NN2#D)MhRS&sP(4CGa^b%yM@KP9N&n2!@`L@)}y5l9X$)pF}F zh)bC8sME=EhvsiW5fhRY*^$l)gh7%0w{tN4U`^>{w5d42oJiZy5U>EYv$RwtzUS<#LsB@TMtZxi0wz)b=)xd|>w50! z;z=MR=n3_pt(u*Kv-CODaswIEMe`O@i3+k)@fj7R;I>=YL_Us8#@bZG^Y8OZizO35 zMgQ2STR3z`eJ&}=w#~YNgK-MXE!tUFIQaSb88M$wc+BpZZUPs))UG%Dew8^gi8?WG zFgX4)NV5lTX^2hh!`H)nKd!x-HhURcoLDqQU~`XLN}EhTOiG>^hZ4N#uyr~ax9EU3 za+s2t2)tztV}b{^4_Ff4Nc@hhloIt-*B@oamj?I`#d17M6|SVBzHZP2$63QJc2le8 zgj+BlW1^D*^pN1}JG`tG&!orBW)}#%2GSjh=Za9R-a>BQ&+w^$!xX^EV*@t!I;e$Y z=JbKbfB*~lla%-z{kU8^Guz^VF|-I|Rw!^S%*mjLtgNhs1$zbt20p%&j27YZOjTk( zLPwPcMvJ=*{(AG{)tBF-Dye(vgT<|U#VcV=O)wam_ms@?HVC9|-w+eSVFMz0iYalH z#tXrALKo!-(bCk^?@u+Bq&KR7L4W@+8h$A$r@ zCbrSnp0QHP9JSj|uPp(DFEQk)GIY>IGV1#QUycqa6^-H0Zg<^C_^&>LoNLT?Q1^s@ z@08@w{5lB;6KF`B6}^7KHRSOQ#fOyq2G|GJh&pfK;#$(N@YNsuSiByGc5^BD3%?hm z(fqKu`T?(h%HIJi{A^sAT20`c!KtRIPEAL?Pc_@NTHn6=ZBCfH)p=>BRJzI+@?{<< zd1bH(g@LegFQ-qH%5rl0Rtcw%7=>S-KMG-8jkODCA(ttZN&zGuG+J#;uTYqw<7ix! zM5TFm+#LD)wVLm{ybg>}G!yDi^EeJ7)E9!s_E*nwXQhnXgrJqy&7x%X#JZ7_(p9-? z7nAQbFh!PD zQ#$x{VBFo0-PUh)Nx#-lu0?;-75VOTPw@&HAwv>?YV4f_|402bmu68a?4_65-J6Np z`8-TVfLr|(9 z_UCLOsnVqtLaYE=}RL<;0aZo7+&Qp)REtO|JpbaosBt!GzoqY49HinErHW29ibLzVEJ zGog!R;eLlv$CJWWScqRjI0o+rl}=6r4iO!-p~36oDx^3x>h#U z)yGXpz~T5j19U&w{E$}}`@BP#02$9cMk?YTI#Qy-CHQtX&a)D+yA=m@4M7`H6q4Z9D9DaHrGEg(cX4g8Zs|!cKWyR zZYTA$QG#t#63+%L>x%v5o|(5{W&0!+uA zzQqW#U=Sc_DOG*PrsDZFtWj%Bedl4(q3RJ$)lak5Ytm>iYhM=Mb+kLGTb|D|u&zegDGxf-2x6l1*-H`}?n@xn-~1gTVdBDEjWSvg-t5 z^F%}JCu?mLP3}+gDOy?$8m2etw!Y%j!ap{+1<_B4*i;PO0^uDv2-GW_%=jESaZod@ z9Q$-x!kM5zvs~@i(95sU3VL&0kOIW+R9LxjBKgnGvTKTAXiJN8Lx9h&ZYY-VbCX9O z`XKP|NBm0r4E!yN4|Dya9=$0B*BcwyswZEn_bGloG*}!1VYG#Z-Gsyig{mBT^LTYsB?D z(v8EITT6eGUFDTLmij?3%K^@g{Z8EWkMr(EFE$-pafacZF{u7&Gvhj~j;Yk;P8($y za2uy9Us4MNz>BK#mId1LtLC^VD?$If#t+RAtGYPJ1e|K733ZNWsGtJ4CfZKIEhr2O zm=oK&zv4gyK3#APH6nxQLhQ`H#U^?W;G9Bxs*%o8Mkb-q5UoqP^_JFo))HlX(q4zh zp~&SIH5cLq9>g@nvrZKPoSs57!TRhDQu$iE$i0EDdR(NT-(PY$iDaNab?(b{M&vZO>Heb30vZ zE@kmHv&fD@>0j-&Z`mm4s|VKR5&k^431#1Dip>p;gnX91h)y?`3D{??#Zk9fa)`F} z4{$aGfSC(V2a}htxSf!PNJNf@&8I^Kh%fj&z09u1UaB=ueDG}f(1Y&S*j$#1$sZ-r zWZpaWDw)dap^cJC@% z@_Tq3-eB3aq3aK!i1}JlT39li`fHZbOSFP4DulisNd4g0dL4?$AWJPtQ#(2=d+RYz z?x+Gu@Mco-@zM09-R|3`xas1b;z)74;9R2@pIS$GRcWi%*S9(MTED6Kv?|^aCHQp} z!vlQ~{n`oY$F7*AzYXc9!@U-c`sP`cn55jtRTD$X-#LxM%UCn#b3~h}LGAZR7N2fO zJ__>`IIrR@$uQ%3;8ws z@*l_LdpVSH(PRrj1Ena3xuwvBugZVwBVvclXJRsWO`C$i+XsK$LA+W~zFft>@=jZm zO+V#~cRbPKft1@3w;3;mLs=d{!TvF>Vp~4z>JBi$=6_zaBGgU-U6|TCpHH$Sp zB#OUWS;_aTWfAeXpFy`wpDD!jSZRI9RLJD35wwvhM=g4$Y_}51zKfcM&s`J7Vzn}O z>f<WuMNF&f0Le>Mw1a$`2aapUBBc}u|hjpcp>lSe2x?> zr{)2%@>F@ElD6F1F(6i(q!>W)vfgYD0@MiKecX%nIYN!2eXebL|2ikD4)wg}>T!dQ zdFSAM9$2q+t185NVq+EMCnv}Enlt-eDK1KDs=)Q7x5MMsQhFZ-FemEszwA@|5GRk< zxqNx8J=CH`VMj*hYrcIEeyc_;(?k5Rp8K@vI;*75Fi6!%1+F25Lg_6?k`-CegqvtH z63Gt0Hw|B&8?Y`h@FDr%^Vuw(Td1wb9@kF~fHhC+^g9)ozD37D_#g zV{Rr={;Mz%>WYWneM`*w)5NJymWZhrK2Sv3)F7~Ne|@_^>fCO$Alh<4!t>UZU0~;a zqpJ(Y$=Fj=U-{)r9`@rP9^R0E0VT>K5(+VUcn$e{OI!56iY6@t?NDoqpfLk5U{u;v}9{4h+whSbl0hERh&SEESKGc}E`{XmXjxYB&r-S+$W zy{|=1YtoT+t68K+zt(MVToVq}Wj~EMim{Xa0La5!_edpF>n2 zr69xWKEE(t)H>7}n?A~^ckD%N;F&zVAvPoEHqkG*`}xbgyzi(4&0eF0>DtBI#leT8U!z?kVGdb-c$6UBCiY3tOF6&Ba^t4VF7@O3k36TZ!?@1?rV*} z$o@kd0&Brm0^?(l%#4NtMjdh`JOH{hX}8UumO-5vvTyd!9va!@$f>c&6W?G}aB*FW z4Fp70XWsu(&D0y}KcYbjNPBv4Csq+OZ$+nc)<`(9os zYY;NVvVzB|PN}m5-9+ASN`S9APLB&{#i6E|jpBSq2loAb-rm!zsP-Ke2G}NQ-rlY@ zRtL$_@)GWW&-9u=>oziYZe6Wcx6a7QwfvTvZ{#O`Oeja0|K)Ko6aggV@UkG?-f>jt zbQt3=*9fP9C`_L?sq>eX;%I*TK)2pWCsVBdlt8_pp!?o3Pys2Pf&R3-Db+zn3_s!O zOrZ!|13^E_*q;p$6yT&jP&H8_*6(y${1S(R4hM9$h!pgI;7$yfYF+|tY^5Yz7A;?m z%9RWa2}2^?Y>^c@60-8m!JG5a&5Z}15z9NpWbuZnrlyqA!Pxk3h-d(?+j+KFi|d5g zbq)%7JNxVTz*@WLj_qX~?Kg8mWAS~y8NLsPe5}|;SzK<` z#N}23Yo7Z21v%})GMEQJL-fU#e=zM6U2RXNJnwOpS~ANLm>JnvujOX;Ilg4eVcENx z{Tf4GZp|7^4?eiQl&R^8?D}9^XDz+cz-r0XmphW~^>`GDpMFFC;(O-&$Ctvpxe^SH z9s|N1e#^B^6sckiS$hjs_Ex^_iAv{$#qc@+m)sUKaSI#Ka-^lm#-?H z-ScJ-OUjk5IqRYwD>z<3jcp(5%jOb}Q&ea?T*7W6JD4w%=R=QB2mxun4XoiN1j_lr zajicMSi`zZaeDkQ%0DRJVb|teH+;N0oQ&T2w=SCQ>bnNoCi1^asKrl>izR=*5Yv*1 zUCF)o#!2t}U1yh7!xA087-RYDIHT+NSZ3o|`uabI*^1_q+&m+t3TKt?LwaM6cgxt} z6xEbB!U@|QPH1ihLRYD^L8%~l27DfQE&g;0E#Qn-n#@DW*Q=YA+^M+c zt2Rd3Lw*|aG(IN}(BmD$ja1^(Yx&}F?I6G@iafB_?t0t0?I+XKgIc-N$9Ls00O$LJ z%|r2WQ$=9G_nH2wiQJ-hnrU2m31Psau8e=|T@G|qz{z=NN1gWebA!7|jK?=pJukU4 zI>hOZ-5Wo37IxOI^*I0pIan#L|5hhgQd<$*67bVO5AgOgt(Z)AYJPDop%|KQk}0*z zH~9{r2g6uaK_P4uBBw~Tj~ON@$W5f-!VQAy8rTI9(jH9L`&+WykYemC(hXu)W8c4I zH_Wz@nvQ=ARM;C32>l|v{IoieEgXVG##nNeZO0%p&GSVE3RS3-BUTU)WUT?8pV@D1 z6{W}j1nd?Rmj2@_-*Z5_E6#|1LE3^KD;yHWLnis~FJI0Ie2_V_t2{Y)Ijki=-DFXL ze#Rx>V1XvVPerdw8LjA;R{dv-o<=A2#EZINd>gzjhYUD+09lu5=en+SUjXgxVvD;l zvCH+(b+DZ;ph_>E_-h;t?5D}(fKEH%5#Ii1=p)9%7y7tOVt6TdwD9)MyqEtor7`{> zl(31^`Iyv@UD{5oOW6MwIe}>hS?^sOCqdHo7U}P-uz?Lt)Fu@wiAdoeDlQn$(ovf> z%&m^S41tVx;SPf81V9{*F*d;p1q?_S$y)H)TX32)W)Ydyp^jq1D4VONp*FU*qFy&&ZI1yPoJ5~nAmxZ#f?X0)5MdIga$5vA3MtT9 zp9{H!-R$M)rS0N39N0*a#fM?d5p8}CC@Qa*ts77%WeFq(O+;dxe43pT{)!mx?q8L3 z4!`z)h1xHhY`K2iqz)}8E0qLN*OYJp_6jYG22&l1nC=6?%@Qgy{;mG0^)|T`OHNeU zDM@a5SpCDpm%gLY{xvv*`S+A^Fd7eo`hTc z#*N{Sgp2pVTI9}rnzJf2ct`ET*1Qz4vH5R;mPrcIKQKUqhWr}kC4eH+o(Yvrr-9IC z;?)Uh($dThbsEy2Jws!L%1CL?i~Z553YUf7Ec2zxXP5ORsZM;(|8;*cP-~Nc*Q}AC&X2e1BG%NBo z)?-mKn0^M9o?HkPPKic~kW}x*NgNn`c@CHdqdEczox?e4)8a&|<82%ahLn%Whyrgu z7qF4vuLhl}-%@R0D4HSBUgyhwlpe`vR7_6#^l1s=iWj|I9Cfo+dZ@L2>UE^mA7&!D zWrClCzH>Iw^Gj(3XOIx|OqSsY0vpe7L1$2X zo;tw75sFU7A^5ZYZcJ0d_HCeNciv8h=Y;~$Lu90ABk17Relvw(J~R{0VC#Y~>Mi8Z zNXEMq*oA;ipE|-K(q{@JtK#bnBpeqobAg~M#;AOB2&dG3C{6-wHv<8*tgWqfB;6H6 z7PzAJP&9yzB@BKhrJqn?rzkuP5Y1`Np1%fQO*+bmk9)X4o7=9KS^#6f|J%F*z;J>xn~4d+9?tKfAS4_JgosO$<_)eMfwsC7n?lqaSl=L9xIwjK{Y<(fK)z%g zJ6l!4HC;8^T`sHPz>bi(pAKBZ2%^0;Bba3iE|+N9&va#D;F8Ai>_GSU^PT)~=@Zqa z$FS+iP5bpRZ!o@m*|qOd^jyoo6!%9c)?t8jR+2&r!2<zfAW8b(at3&?Om_ujd|)fG}AqR_f-&c5P)cfsHn) zcqFPjG?OysUwqRxdbb;5_aM+vPeWX8 z{^eNW)lUn9lJ@p(jmMQZE?VOFDTG+aIx}Agmfe-pSmU^Qv~1-0uNXPv>SAcxjy{ zk3)@+k;G(H<&557>FsG{`>;Cfy=u$fJBp!(A@X#QV*yW$X0~fd9U(o__fWi7L<6Wo zWRu~;m#vi@W%Dp)CBp6_V0?S1EvcCAj)PrP9Hffa4~}v#*Y&Nt{MPIWDQg_m{Z1!~ zQL+RV(BF&s;M5`8))Qh^zn|?L!OY@gWa(t`7?k2(+1Ti9B1^N(hVcTVL=+tzoj%x* z>9G?MajaR5#sL@{bA*P4txjXMdX9dmo~Jmt#M(z*hZS;W(^RWaD??%t6R2XsL zJmYy-ahQM}vGw{-F{sSJ;6$*%_n0jE-v9 za}QeTQ}JXtJe1dxaiN@ej&h_n)=NMBwKwh;I`KNkjOh%rC zAVs)3tlw&9+i&W&?$XQm+q0Ubky95`B+dw5hK}jltyY(+zXdsRg*~9 zyZEfWCxF-ZC0o>Omiu5v55`XsL{A9*AQrP2cG=O) z$U&s?afZ)|v(e3s_}`<7^lFdRhUSUwkAJR(-7RLUmC0J^TX~n)n zzQRB!lEjrH!)f$6YFZrm5W=q^#Kq4)*7&c9>+ zGxKPCkPnL!e|kBeRpn>PeekT}?Pr4^)4!Y6+dO!_D!=EH~k;u0aP_}p9c$MiMo-dCS3B+$3lFuZ_WXYsVv-+>j<8U`WmQI>^^n=#a z)Tm1QI}b7n&~_)&m50xF*pgHmnc{42Z&7iXJ4=e{@l$=Nh>J$eUasc7MwfJV3efSI z(--n$h{vH0!;?yLEF?w9-)vufM}0wR-5^}`QAW@(rvyzq?tQ+N)iWXKP68IL-*sc} z8v;pev=zP4$IIE~jdhHL`T50ngTvctypxKw)k9^9wHalN$5#CzOkJ`1>3>$gwYxRO zv!VQGl|p3^*cl_o!(Xd*pW|hE`De=9l!ie5-5{|&C;~Z(Fl;1FT{iNYl9Nm?W{EOI z#)f9~(CW$I>1^sU_sK7&7#TUa1cs1)Baxj+IHyZNGcyNVI0DF@IE&VId*?S$-zFq1M!Rl0YXz z<^SFFgPGZjhpY1w%F(Pz<*;<^*dr1`Ny+r^0Z7olIoKL#ArvHpKJk2;DUQ5~qK+G? z%v~;z=+~2SqwLzed5dw?`tVcgA0D)=Ah2~nz|mk|70=ZiJgrZudZZy*!WiW@P)s4y zY(1X!nq(oqOApyn?cb~J(xZIt*Hp90HJwMq&z?Pde8fYnO#mNIp4JR6pMB9BP@bQc R9s$0229;Hnserr>{9lUpH#z_S literal 77595 zcmcfobyS<*6F!PUDbS)V+5&|dUZl87DW$l(7k77UDQ+$9!QCNP2vV$QaEIU!EVupOOKQr^p>`(!Wi)d~WO+vs)MVm6O z3B?i@IJn*=yWv?ED&FU3znIwKzyx1gXhZW0{WBFtuKflR;YS-si`0*s?*!f8^x>c1 zV!TdVS3eH2z5f$~tLu>8P|L+17OxHiZCy2N3MMp>fPxOKQWj2a8ExotI zR+$<7p=i-zg%cb71e*hvn!%@$)-gNn&foR+UaI9mx~gLQx*dkDxa4G7Y!74b56e}U z>?>1|6Y|^dP-aA9A$}4l^S)?342xP1wzucJ{C+?vLn4%3u58NFcU4X&&yi6AE$)lA z4o7s4(Y=V*RDBfw7Pk`gA8#sba3rNK>YKD3_tXWL7@F2?Op+!hxMya36?A=!D9CW{ zUjDamjY@T*mAMv|OW`29v5G?bD--y--U#g+_NL((-N$`{N?}GsW9P#VQSuanP(DQF zw}cw@qp=XB8;O?|&Q_dsReR(D_0RMcG)61u;YT^SJV7}BEirNCK%(d@p|3U_5!lZZ zE^+=g@NHC-Z|YBRacbj3!PBOXZNU$Fg`(m=ieX@(ny^pR5_L(p9wtM)r5<*09^gVR-pucr$d~A<<&Lc_x~eON!8y( zRWnN=DIxKAF$n??fY;lvFs+1`pV__A=p?9Svv^MT=s`t98X1py+o;pe83*f4c;V+a z4!O`l{p$H?Z7&j>y|JbYU0k$SvPoQRH>&#G&N1g+Cy$X}OpVlWR&&q?*2MV4`2uo2 zjS1FDvP$+36}guL74qhEdemsKO~QI#8OD8K5@r@&0Z-LqHD+?5DXXFtW$Y_5E3_Lj zeB9-zgPL~TryT#O5f#JUo8db(6BD4m+B`3~OCLEshwv@1C!2B{Q(+SJqXMWFTWL=n z>58O{pcP}ni`zfkt~qd^f9*T|;0Z;=iTaYwv<&rvAS^@}8>J4;S8M2`$kFS)qN#xD zZoP-Cq_Z>O!MuPP#Rz*WvebLFdZzmpD~=U~)iLx(dB+~G9&O|3-~DP{iAwaflPO&p zV^LK`!_&(>>9-L$zi9vMT09;@QfWHuABgJf2X7oRvS1G&X{EAkZ(+9S{&sEmGatyg zG?H`DW`+7OLh&`^K|xUtCcLknZQ(<@Zq`nHrC7d zsqnZemx)~#;lY~(iIwJ6C(ga?Ljrql)Os1m(Q`wKO?#Vy^)KN8Vwq6N*xipif6@b- zf`ImQWm6_6DcH*vp>D2n`? zsgKLda2>9UY-bJdMg8)mmjo^O9KTi70srE1OvczBuwARcEN~~ec}hIxuH~tZ!1nMD z8S5R69o{|rw$>h|0`$GK`Ou7NTP}my4F6g`C#S`muCgu(AACMCCYuo6S$S^?_Z{?G zn0TqF)^PhvL2_w)B0DaF$)bZJeg=yBeOQ`Pu5);E#rKVB(y?)3E>*>3cS3(t zy`Bf0(-TUJ%c28*MtH)SSj0f=wg_)M2fRQ?b#br? z?31zG!(MXG`H^@3Iz}_~4?X*_(W7RPTLI6l5DQRDtt?Q}b69wc)~*>qlcB6CV0P5o zh&{A91GH8Vqh^_Lo9ncY2zwG4s!n=B)qLo!kl}L7#Z-Efk)bE#d>!N`&#R{R(WPq4 zl*QYwXCq8rqh*zRs8%=4ruJ^{&7hy=olq-P)2jl@seFBY{)vNNkS`^xb2@m{!u?Opm%GoFQS8eaTqSz@OuDMiv)5A}pC46nG@xz~372zX{mKd=q;ILRrawX%P zu?KrK)`M?1^S3vDrV_p2ht!Kp`ud?@i}@=)vaz$xl9(k zLiGwSv3LL}@4LQd{?G~2@YcnOT51-@&GZsC$7GwbH~2keVN?RJ&n4wzvL(fF&Wja) z=EO1s0WByoqB&K;wosnK%_QGJt1W5L7rv|TLp0xc<@q-)al(5zD#^ulp+y(yT4#gl zxG$6^xU=4}_De@gLKry;YQ8tbl-i8VYwFKCDQqDyNjGWG-G$fL^UaJ*-exFHbhboM z5+_q#^zIbC8%Z!%OYx}4^QQjWQ5F4%5gD#xGBnYdO)j2l_1f|#h7)C zz;mm{z@c5)5S|HdXw5Ai^B~Zp?rL%&-MWb%nEbq<<|YtR5gkiB@*NZ9-K7lyGp=eZ zjZeW?h@$LeiJhX(>Gh&>Y?AAfOY%VPZvTshp=69$cH zSAX?}`~eCW=~YpDE8a6Q*y3!Sm!GF5k~Qs^PBS0YIx>MoN%*ifsMQi&%(!JUQJBHeRqxdb zv5`tJg_!+VTy^f@nzKmlb*SG;3v zBH?68_dP&cHdEjn*vv6^6=jX z0OiZEH+8atd(+ya0P2sn;OAprlccZ?4% z&Fe&=ibvO?d+MX_`QP&KTX&C4bX-$HJqE1@DdtjDm1V;PJiN>hHRqom2bP~B7B4#j z^QH4GxjlCd1Dpi;r(ufiTr^vn8cnY08(@-M-j@7|2~u@#Am4z_MUJZ8))=YGTtmlz zY^nsG-*`coER=II`a|ll9RJD5ZLIw9?wm*Y49GO;6f>A)XRe+QKPL}9+P%2c!HlEz zLBPXUwDn7O@;tJ&1=osYA&H>S4poHZ|_ zA6(ME^yni6VdZb1raY4>w9Zi3n%7n9qwUjX^ODjq>}j4Lnne=;a{$1 zYU+@|WvzuN-NkuXz<2ME=HsH}5Skg|d2e04qy8i>kA4{>= z$-f8(VV9+GQvM!cxOaZz6d>KQ2*=#KX_@M1#Ws0(5M@1gAizLXc}(i>&~^Q2Nv6U8 zFBs6YSn>75fvY_KGH;c~k4CQ}a7zD!@xvPj3k)4^hDT#cV_RT|%LE^Hap+si)<6Jp zJZq~m=ewX;mWSt5{Mi6#yBb|vIr9i=WT)J%Mx0{*xwi_aeI))xT>Rs8sOqAZx){v; z9<6_(hY&t~zOv=ptOcHQcmIM+WcVh2;f%tZ_SItcOOHX6b})X0fy(E-bLA<-jrnaO z)2xR21j4}Ke*u9&+zs2;2-)Jf@tL;T51Ti>#ewuZs@!C&+cbMrjie9b>eIDAtNiq) zFH9;C6rHYBkr#8Z4)6j)-HsXQ>EtZtPx^)x$IEK{{!ak2UN(&G8%~=paT0Zq4ywpL z555rgioN*2yX+!&2C}-Y_Jbg9ULTS)E!wGaM$TSMSeI<$JKI|tSQlSJeK2M3G$=GU zbQlq!d{6*?Z#q>JQ*o1}Kaxoqxn48Y0FB)DlTy{pjA>rKeV2uU9%9qi>T#Mgk{t}x zdQFK!x%1L6ptGXZELv=f8i}U~;s0j*D2@w7TDhDfQ;L?ZT8cK8)9}pq@_be4pr?bM zu^Apv@LzN*a!K!m-e8Ym3jgtuG0t6D2&?IDrZx{g`@@>}V<{k`y8b5d?(rDFjr+zQ zLMj!X=K&82n>im}_UO77XFy69mHGN$H7Do4*s5=8lj_l+RK(Ed@^}B^0@_Ws_t^EG zJcw1G0kC6nFpA@t!V`Z;{P+8a5Ic%AFOXM|v!v)tf1a8D*DIUy ze+q}-g!QeHs&A`5O^2Q7uog$0t$to0J+Ww-fnLN>4jCgE?qp znAF3PM8u6X@>Ep?v7fbC@)tU_`nxO#MrAiNm7N zr<;Ch+xNlMVGew^hrc!aQW_4nVNrjzm96Rw@7K@qX@CK$N@>}1q0y(fG$vTKemOMisk@45f=ClriA4G5c_BrSo{Sa@oIt_wfDpcP<^Rn79{Wg~MUDOCQl zGUSGbY3OJk9;n?!#@D1)mHE_4_GXzRQj?edS*Wj{XZP-Ig=~3wgJJ?F=D*G_v{;{z zh;%VLdzweMsfRvPHm0eWwFQ*pE?g- zB{fuzYLYm@q&^+=>;=I0-IHVc81xLTq+7Y4-^lJrQ>7Hb?r9)@DS6TNe>A_pE_k4e zN(_2d9tF)W(0fhKb()AT=w0ay#^}2UQ+s-ZsLKqcKFU&f&0t<^#=h9p7@2>YPs+WC zo-XaBz6zY;8eI#)ob()oMD%&SV|v2Kie6uwF!~ZBX_CrtX6kYkc_;tD1$cM zGEinMmcsW|b?NtuyLXXacz2S5Olg>&w%9MLK8w!bDpT8`S`=2|V+6GFZ_BlO{Yrnc zm|7UiLbY9FK3F)BKskz?Qv)6TZ2R3n@}O&{7otiOXAxhxfAircK0aShIQA;mTI;_F zA`ijZlpmqLl?x+GPGEt{NJD2VQ&+3j0M?Yd=6?^LW9ck4k`9Ap2)rXbBEuiOJ*q% z4}3s83f^~&Li=E{sL~Rnw_Zu<5GW;V$KIm7(hKy1oj@qb!*w|Mba@JqJPD_jY&A~u z=%7(8D{SJQyvua{%G8xD_g+m!;iBPpF^HBdvb=BN7m%aWQZiIU{P#Pb2By(Ow(YUH z8nHQu(}<6kVy%neR30HO`j7T=SB2?)lilo-@;fz*I;ImVEb(k!`8(bZjcucUGLJ(& zV1kk9Ca}a%32=FJ&FwJAF55Bi(Y^Unc#5PHRT?ZAv{cOVzR^o4N=|CLCZG&Gt?=`Z zyyMphXP#vdwf)Afbi}D~ zP48qmw}(fG*dQ08~u z6Ndg$NS#<}&CD(osF2(Ib>_4=3A4^Id2L1daU}VIHWHjjy%x$6tiGBNAF9~goVLaw)A z*O^Y}aDZynWTSqE8}0l1Ak!x1;$g{>EP+)Ct zg>{g8>A~D&8a=kMwM_Mf6u(EvT)WIQc-uuwwMNw#>mENdN0B`41=g%;ea>7rDR+Ue z5Hr(dMu=B!we4BSyfX}E)slnr7E;0V*)+5LJ?| zpV&rL3b*aYO=s))kB_Q2-jDTjgBv8dF*AD0F~lq_)c(^>w13*EvAKd~*Xpadrfg*C zuHYOer@U|~Dy1UVK6jX%EyM>nYc)J7uO(;F{2n#2^OY(i!b|01dSiN*2-YdmTR47F zOg>n^x06D$zb&a{eQZ@iDS32ncSTH)JhVa;(p+s|q%-Z$9I6eP6inq~Ii9F2>QP-N z{i%7onHV3!7!rErh1vj+yqVPsidoMu!#hqGtm9oFA*717;Q+ZxScC_DiBBCY*tdT* zJ2R|!x!}Y>EtKb)crd z8dFb-(tp>3E=q-8-K}v7d)bXIByiteF`jHIU^{%`QuiZQuAmOX?tklGa#8#{1y5a3 zp!5~G0nB_f)Fas|`&vUY3B04}O2Ag;RI=m8gx|<9o;?zuA1lX6c^oVjO>)JF9SxUJ zwQZexu1(z|-ajo>Jafg6GCF)8JswOL5}EsBZT@9%Njs1cmu$QQs#>L8^_7QvQGawF z5AeZ~F)URb8{rhljpXR)PgAk@0Zur%o&^~d;HrAirbZ~LuZ%jg5GL+OW^q)lG^(p0 z4VGrF@Jy|eG1fu^MReztGNKJM=S9Z5;6W&wr=?~-Y?@`moo(>WZKd! z*0sZH6_p<>855U8B^CSUzxzvxioU%qO{+?egmvZRMTUasEwISRAD$oEVPd) zvOUbTlr>M)=g$5a$lhm~XxDX;$Hk#d`x~AC&ODZ_LcH|SBc|J`NV@?#r%{^xl+IEO zpVf0rfHz*WT|$P0CBx%|#2bA?)5|%5I4L^1w?P0VZNXx8ZtlXFnc?=FVopIun_Vw6 zE4Q2`EG(=Nu?k0G;*yf1@pv8;j(n|;_c&Nc@yuV;_r?tMLfdWA<>%(Y-c#{N6Y$ zvrK@SI_pD+wX9eiC`5bTJ}JnYk)!8lBK936*pS|*RXRd4ICoM-Z9;j(;NS5?iKj&7 zyod&+!~pxp;^?5aa3bCS=MP)^-7ds0yFLC%^SAq#XCoREpQ?=x#g>)v^ZsT#JcHA_ zG@$s!@{KMhxYE@L_ukrQdUI0IGG6tol{W?WXk*c-bM*xHt5I&*Oh5#9_s69 zuz4B%61fV=DL4DJ$>nbDMvBJFNbXxY)u*Ya=0tJ^^oHjZajUcN6bd=c6wVU6y)~Nb zNRO>Ijn?29lKn3+)i$N{2KC}Pk8#co4xa*fRqUt33@HJv7IU_E!DCJ0%4((*0ard> zYCo<%86{Z#aZ|3JawmNe!mHe*5yy#kuPP}1I*fNH-k00BVIV<}3)yf%aIHy*nf`Z? zO4n7c6lO1s4f7Y;y!@Ks$K_TXXEyV7gW4YUt;X(yHLM*ZUOOyfife&n^&)(BoXKq+~*Y<4uU+29mRRprVd`s(A%1x<{!$O zrSp8QRP#-BI|Etdd7(%uALV7pCiMntxZ+I>TXnxYorMSoQ~$OzAU%)hh17KVb~O{9MW(8B$_zN z61ezh?_Chy?rf2upi6sys?Ss05?7m2joiCqmG0=~2IH>Y&#QGtJ$N=285>}ij`jjg zBEK6~n`y$LDciN_s)aHo7P}PyW>F5HkR%E9;O zi`{h?#|eu#vKw=izZ$Fqy3?CDxHqeVY+dUXv$h|#ti=liw~NiqkhA7P!QoR%0Eymf zz7^>u`v@(WG>+knK9DR0&SUIJopX8XU6SQ>fXU`%&wGdTWKLJsUaiVG#)j6|0RPot zt28lw^>>!Gnu*+Yx0-hiAGoo%1I?f|TOnNIL(zhpgzXNg7dt%ohmx&$3D@W~-v6B* zZ{78m{#LUZF8jk9fMdO`!Pf+#O>VFYblACI6Bp&)1QjBE4n{@v>iNr8i8QR0&!02| zopEiOMU^L0t*=;{S?N#ZNt2g1I7&ZP?HT^eheND>(XhSrKQ2I5T|XT{8q!~_6IC8q zb~qQ1;N%rPp6mPT99kDk@m2yr%T!Ca9a`{o!cy5G_qnj83~@UAP}>_)8PUG|DH zy1==$g-c>iRylLBAU`ulq|r$BT14m=(e?WS=c29Nu==;(D~|hn2h)N zEd06NM_jtwEY!r$;3u)wfHWlqNrZ$G-}%0lETPyBJ`PDGw6jSEa%%MS4wgx3M{gW1 zN?eD-VgqV?m&ZOw(6jpEFM0j*GZaMoE-9A&oW0^pNJ;rpk0v2kc@%THJ5WSB&^@^L zdgroH+JQ@qbm%2#wioEEJV-}UG%+v818|IIY)bhGb4aJ|n;|ARWXHEkv&-!-Y3@&q z9&q{_MlL$7%yP5LLH5b#okEdvKK#nApB0)#dSoPsT#j`rMFB6dX>oTas`5a%@>=4) zfTpOHrq|n&opYpS)X3+T*->boa=}IWzGwe!A$@yqD%OkA7~8Txky~qO&a8gHEl42t zE4y>UP}Hp7daUWNjEav=Mj<-cPrJBTewC*c`C>D(U*o5LbqO?3Tfoa!%YUjDn+2Wh z%Sh;>jwcm2-0&`Z*hc2NuV>h@rhGwU)M`fPEG%W35b}8)mea+&fT^*F;HH;W+g7!% zJPoEh&Fdq&I;R9wx_qnsIy8Jq_BCMindkN8S1)+Ca=+*cxSV;^`I9H6eN%4`E;lja zUUia4_&{<3-!hHaYehIVi!A&?eSPrhWoRoa9p*objRRmc;@LM6ykCU2uC+L)7%9|u z4HWszM|1_#&bjT3u{rJ>a>_@sXZQpQDeD5P=lpv456|0`B}~f}fu_CGhu9JGUm_gY zm#e2&nl_8IxvZ>Sy1A~0Sx2>$^$gPoXs0T}F=T_7jXk}FE^X#sx8NutLKhI+BLy=c z_c~l1AGP_$CRJ(3Z^C!c)*x?~M*s=j#bU&DTV-hfT_T?C0b!vwaA$7_9OdMn^~3~9 zrBXys_qtFO#k=qyhOSFwd2_c1WCULGxjCfI0?ql(Oq%QRX=II!O<$6$7K9c+J|zqQ zR6z;2XoZg-cn$<)geCn)c6K$Jx}u__qNJo^)g#E~3%e(hqNq14!T=TmtlvNXDP^W3 z!zPp6oEDdlr}J+)c{1)|DdL4<)e;#pVX4`bnfd}7Su2d!J#-8VPAcQ$zy^lmK8hi? zU%pSl*q$sWQCmJEpq%r+|AvXeKotnzeJ$fZiXbC4K<{gjl8V0@4`7J_uq@X=QsLvI3Umt~MLE*hE6fp@v!8y?XMPZqhnO!`z7I2Zyu!KT* z|DF!g54go9LXYRwxqSI5Y_X`Cjr4*2V<3KP;D7f+flfu~_7>ll8An3&-=^OSQ&|2? zaAbdGXL#b9XP5Ti?Bg8)#qkb+3V7E-fWX-3=|Oy%wn>uY<3@ z^k4g!n_2BC6p;K|5q~>O=77fvl1~FaRWPb!dY$Rl8Go-e8I9BDvR*tJ`{@u66wN^Q zEQ8ng>#SUn``F|jgmQrtOWdzi$E9~iO3IR{CF(-IJTb3?_)&wI8#QYK$P$k-(ldHMQ)pfiXq+^GFMtbgUwxL9Cfv?fSgD9Gllape5+}WX2 zY)?W?Khw*JaJ5IY{p7i(b_(#syf8CUp#gI7^K)NSq)xgy-$xjytVB<GjvF&h+ zD!ZyGGq49Nb8rZv0{kj1DzdfG?Eo7J!pZAzs4z#Ack1@@5TU|&cu&Ls4i4r`WCpiq zu}})*`o<^eh$pI#^^H!(XvoD>#8Lb9IQgkfa%TX*=l;n(ot;|wh2-y2W!3g1N9ywKUlgrV-iDFf9VT-;h z!h+nJ+`RmBJ}1|W6Z%OtPG3O%uhEK4{}!V!H}-o$kT6xN>8WQ#1o>H6dSiV*`syGV z!Nk7XdToS;-z!y*ySK?K7rFNpR1)fXI=fp#B3#`{Bw*Z24#O@`uP&FN&0~B3A1NSd zyjBv8UpqBqt6_|kSs9TU$ALAfsmaTf%EeKvw>NYXJRThzpsVYp?OCVYGYJOO72vB) z$`ABk_%Z95yq&BI1o_4@aC^f?ntC(9E>nQX&K$#=%8#ZoE_sQD=+0&FyG4oa-QF37^dyvvbtodrh&6qemY zT7@`lj7(fkuOidZbUdF1=jed7IAK=mx4`Z};B6EWdFPGuep1@CC*(Fj1v5XGx3N)$ zD*r?}J*{2mR86-=rxXjPZhixC^Lexf< zfmZ9HghbKYaK7uM!!a_Fd>O}a=R`av&hc?;8%txeO#v(%+sSF*-&+7i@cPD)pqEQt zHIv|)g@q8d&+pjO#Pn1#7hO^b{=UU1S71yG^mA7yFaIp;ptDAiNL^W#eqO#U=XLR? z^Zm(;GtCgvlvvV(HBB^930Tc(It5unNce%uv#5xu`{dlgDH5m@JUEZ-h5fEBW|Sp> zwH#BW3&WX`$C^%E!D8fFJBlgbC2D4MrCxRMKGo|xH6Vs?ex@}#Xfy9fuy`39}`r~pdR}&`sJNiM``JYGXS>lZFXj6 z+hli2{+^|lVl$5S8N8T`Ts2ls!OJC}*lsabl1hm+|AaA}i;d&ilgAdYWbrfPY0E9{ zi_h2p^n9vD-3+UqCTQZ7{` zy1VPPb9^R|nU$50+GF+)oFC>aN&Wu)zMy@fZmQau%Pz@4GN<2}-42&+a;rH#(4E6# zzR?Jw=|qA&eL9VvWj=FUmc_*T}Lwa!49yy&as=>Q3uYwEk1puRq7* z0Gd86M|+RahtxwW zN>n_w|N6wHB*Y)PHg6>!hEm`K7nEtPy>)hR_ZGTS{SoD*-^kb7lM`rTkn6_+u;u`ocK4H)h?hxTpwdu@DoAR&!OvZdMPUKVJR2%sk{m zCFJ>uU43LCtH51g5sZm%d%5_LjqTcSD-%`B_l1D>_|o?q7EfJX$KB3+mlDnOV-B8( zu)@={T^Dz)Q4*sL%X+wAuIoFo!*)o8vJ!qekCi^ibolsSptQ7(Ddn%8*V5KYb<&=- zDf%~t&rhk**cj=F@XShw?D!%``3kIrxcA%oM#!r{St}Z+K&*UEHR-;NvzGA!g9cGDI(OaK7qu{!yPeb=+ zYhx(yN^^5-{m$!V>wqLox{D>y*9?2MIv_1g&F0vhf~TvLf_S?lQ%;Z;v@$I&DA0y5 zu|HkF#?;t&yiRt<(|P9)17K;`9$c(y3`?}<=}R!BX*Xoal^~s)s8&)}=J&hAP}LD6 zn@EiE7e6_5w$hwx@El`Va`+{S>jZnEp;~g_>{5F}C5#&x65~>sS2WWqK`VxKLtekX zc?N%B{y;_3b?t@TaP_cY*g3lq^2=bOoeoC207j~{6Y zPbO@n&jAgvc1KkKYut7zT&^~=4MO)PqEA9pWu?&u1zL5{U``p`!$5hHpr|)mlnv>F ztkQnBQ&I|!rl@gPueiJz1EzquuQPA{!mt|~8v_uo_i%th z)&6D}1)2-p_;7%vU5pTQ@mx3el>sVTg(v~nSNV)>(4S!?4<+8-7-?w#x1L>_-)Gl! z4c<3)@cSA72H}66WQa(c+0p04MYtd8JFb69@0}b*hR%1Z`e=b%t)jc-@!fhLbqzNL z7_^w*l#v%0?^7dplbUK(>DU=P-D;p`9&W;}O=dqsy4te{BKzxL0n3$7HwmQ7017m$ zr@hpT=+CmcaHXfCBU&5d){N}M^=y4{i>!BAeT?kuf^D6`Kk(D?5IDHGVqsvQFFROE zE2S*O3+HgRr0`-U&ooN(M(Eval11fiT<(PkRNAbLhFoJ{>zks*v9W6>P}kC zP!o@G{{ki|EhNp4^6Xo8+|yYttz9R3j)=0f^wPYiqk}=>10b?g@%Y-^)RIKXO&*Qz z%LSR5^d|c>b}v_lyI$<`KZMD8Oj9H`g4)y4-)Myo58HJmnyJJK9C6Z9U8t64hCjEF zCt&}N3z$zMTXAuO@V2%kK0@Pnb4zy$VN7t$!f11MbIx z-|D_E32L$ha^y1Z?x(G9-q2+vgHFgcX1cyeGzFRAr8Qr$rc}U(^K!&Gi=@fk`B7;X z=!DN707ryghy8d7E1DJ1rNP`vA4S~!5Y+#t5h&{w0^IWGmzUn(4fgHEeACaAb$j@J zc#B4tzw!foq-J4>hLBdW^vGkK9EFcnx_nIdDdy|?v%)V-_PodlG*{Akq6ape6Z`H1 z$TC7qR|g{!OIyhL3zn{|Az`?SGiu;3Q4}K@EJ!QKnV3_^yFPhKt?i=}p%szLQ=9I4 zAr8Ix&`Y31NvT=Ap;Q_*7ZPeD!Lfn9uT_IEWXLmV)n(*fG_%ckM||@*GKp07=(QwRun|G4l6gws5RYH{zSD_V1EzAAloE=|;d46;oe&ExD(>HSJX+nz zU?=w)&ralUE9%v3S~GOFv^o`m8hlUR9FSz{nlMmjw4L7#SfNx#17Fwd3f%pw+uApLvp+xcsFJ#!xc9o^jugo%UDp{cX= z?3tbNod3sw4JJ!nAsAJnDm$WBzIY;p_nmf_Jb~?&X?rqoI=cP*^Lrr|Wi7mQdmj3V z*l~_p~gYhJRryQ z+m-4@uBg3K@X4`Y^BcNr4|C_wN?h!a4YNG)W}+AMRX+S{#KVb>0xqEV1VT0EpE6vf`4Xq%EjJdOs@K3{2LSt z$+mTPsS~P^w&v{amW~^@1ZA~@Vt;bF2k`-e@&A)!V2^FV)ZU;m(*@|Z%t z$iT8vUYyS=GEwsQk#CF0uh>}eH%a~Lqx@ZmkbehBVJ6NGCI1_o3fr%M?_guktMHoL zbWMRtR`%=?3t1+%H96g7-1~!FZ<)zvK+601s(ojop`oT>4^n$GY}Plnhs(=BOCvJ@ zp(nNe8+4``#c$`7Z`_!4Vf|HhyGxVZc_s_O>#NT zrzY1#&(lhZV00_|1c_qEWQl^fE=K5fn|#2JE<)W)E&Uk3@IQB3k8;SaJjpbdze{Q| z^NqeK$p#cST5caJ{gBfea7|`2iwnOfgsC7cZWqhiL4?a=ZoroUR}KORS>M^?VPn+u z9M?WD!p&pHnM{%U>f)VTzrI;S<;XL9O_xD=fhUP;juNQea|yBnK|CHOa95}G=69q& zV&-xB)Y>M14kf)@6!V^=2FBX4yR?|~SDjDY&v05KVvMr#Ffqmi#r1zbMlgSsXi8|| zr?|W~jq%Fj=my1T6?#=6@o1uII__;^-!J@^$KCIC5}N~fYzfPRUVK&W__H7j-Mm|Mnp2cihvor0+Bxm!cpZeinzPesVHTC<3B*)e>zj#rJ$^8^>%XxdzH4^&8~2ye z_SEU&O74t}hQt!XsD2MROe&IAL|_m*#&-35P25iVFhx$nYk1Om_%&O&n^ft zCbhf4bQ$7Iy5KZ7Qg6=hucc9|E21`BKOum_^&R#321hJrP;}a$+&-_H z%V1ayh12$hFzMdJ;Od*op0p$bT+seQtx8WKnXf#WE-}E zJ&{1+#(sp3d!oLCoa{o=mw8^riWx&|zr$xbrD~~iXWCKMJnkiHY{&u#zw2BT-1^Xx zCM#oVGm96n_qu5=EJ@-082y;&y?+0+59I)=a4}@50L>Whu`(@t%3;ahkW+@yk0(%n zClk{@z}unY{6eMn!SA|%K}6^^il2{W)*^Ww#bIb)zC|%>^b79Vyg-bAu;BmI7(V1C z|2c0ce~ER9|G6f}&;LJn;r<`LT=)O7z#nXA{(Z9V2{txKpNMDwxPJ7Oh=kQ&N=8yr z^7n0y7kV%F?O82S#Y9XLhfsNhh3`Df8x-i`gvN)*D>=B0P!1X|yj#9@5)l#cP!PMg zM6m@+hyFlS`Bt0y<@M5LxZMwd775J)6&eOJPa{-)9?zND$ii+A6jN)sHFf!Cw?3wXuP_dLo@0r7cr;R! zhjGa#qI&bkb&e+$r<@piYDu}e)}^F0{kXrG?BYJ<_Zn4^=HJ*8x{~ z-jFmQ19{^9kwx3g{Uo=jiBbDIH<#R+_#D^s%V8QTTEL#FYUZEjL@1STdX z+bScE@Vxz9;`NUhbYy<> z73kc~h>1BZFGzQ~^{&CrJ*+8NyGKZjkB`j$rHBcQTx)Xj1di;BHn;C*t18@V9;a+y zq@|@%1Mi38i5yD!&+KToeQm8IQeSf;)prau393Ik`NhViby4@tU@_%oDyZ+s?)7i+#U%rZkb^St4iK zNJ9{M;qB|&;_j@RVhY8c?J3L6%`Gie>BToFz0MIalStDVK9AeYYC?=tEAI(qL{cHP zEPwi*^E&ZqD}Aqz1ci@`dQ5q*q%;L~nviqskLNY=CUQF0)STj}k{-Mid;WrfQAodS zy?E)b*~RT}JzsRH*xi~_4O(1Fds^84`@@DDh#PrW`ZEmq(s9rCA0EcoRQVfhQ0nw&I+zQZ~W>-!eBS5s4M z4ytq9Kf1+uWUsi1Ldss?GWXF($Jqoy)*vAL3O7=b@!SRb7zE#31-d}gOoa{l2KFb( za5CBYAP_SiF@hGWlZtnHUD`dTKP^TI_;H%1(m222=9T!+IO_DNH_P#9<#?i_h|zM{66 zQ81tL^DQ7ppQ&O_&ce;DE-M>V{_WjR+ssVq5j_M&CofFS@yN>IX~~Nd6{Vvc@Y;|n&amvu=I@w0uuMX92SK7}n;Sh#bOn+aSc@nw*3#2sE-~&qer6s`g9~o1 zIH%;v{^^0_lyiJv4D^KuWrgFK^-j*zJU%9MwdP${cRlz!fy=p<`D@cj$4y8yomtKBjD#-d5e}3SFE~|Sp$(~trv4haR)X?#y!WoB(E%IV0rZO?_&klA<_e< zni?l3CskDkK^x@2-SL?}BgH~duxfS6vE=KE!-};WV2P3pZ5(J7QmV}AoGdIAYeMX7 zHIvr!9}Q=bfpk8zUgQ4NAb)j1LisGK)iRbEZyK-Pj8o_57Lm4FZOo_)O13Mr6!$ZM z2(>nNyI9H)3!Mho7lFT8pp3m|n;C7}KZKSCcN$tzJyAr~%K2A3CN@Cku67?k`i@Mf zDT8p#@Wuu#itH}Dg%Y)Q+Z=c5cCoz4R@Th*!CDh$Zt3K#0*W5CBsvgg1~ z{7Bl0W6$mG4fQfA7^Ibyid=8GRE`w&Ub%gw@t{L}#M;LFfq{=p;4Rxn81T0t=UmDp z#+4_|lGkTc4QcIw_~-FI*vFK^vD-fV-s&Cul`lL01^+y*u5_*%@n?NU5LBnGt{hvZ z@bsj+48$i;MyWf?U8t@;`}Gjs2h=uX$(D&I<}BPCud)gEmylO4UpPXr5L!*u=D+mS zt`rayJch3yoAbT-=y5b~*@1axF*YhzXU>q80dk*!+%5NCbf!#_l%;~E++2-gs%xra z*zyjw>)|_F+b3J|a&-zbS81)zE*<*e9OGT;F(-Z(#$8bDeA(-f#&WPV<@RUQKy7jL z%_}D1uu?%#Es}KP_g(=E43u77FW!{?j|*US@uT1p5p^V(?ScOo{Qw-J6=Cs?|7C8b ztz1!DUJI!`8Hl~psVy>;gPl(o9glJ@TUgj$SRLx`)N#6&2wNN2SvLDX?zUZ^l_6V5 zlAbb>jKj&zC}#9#M0xXiUzlKR(~HCQ-)U%Jpm>CPAS)#gnfAN5h%JDavrkRrl{Yob z0#jQGAbPo;qzD~e-p1gl^s8gItY4{?*V5l!(&vh$e+1kw+{exYORpbe1pWkv{1QBA z^f^CGC4$vLZ~R?S-B>RYh>4yEuVNWe;MF&j5U}?Cr9dL^VFf{Tbxj@<8p0W2a-=cy zn)>(ek5w%CxQDxvHDxoEg3LnS$;3YCm+G~qZ)8qen|^D)`&;CcSk5;)hm5L(eMtJ= zd$7D^3u^I2ih?bVEp0l(SB&-DM+zVwuXtQ%`~IY@n76#Xg8;Q*)T0HI=onxr8A`rN zd}3V_?0Ac{?HGLp5fAOF;kyxKTo+&yo-0)|Fmq{me!kfd4Pk6*QUPt+JW>U;2=dR( z%<7ysIw8va9N<4@;g|x8K1)gYO|ykrXh%m!bc4RbPGjA+WhvZQp+$tgX&krU5=snV ze1zAkoJrJC$eSA^%be=E3-aiXo{dfu@Y)~cq{RfGf}0k-4p`r^rJ$mS9436Y>;E&U z=~)78h~KQFQojLLWp*+?5%N8XGi~uzzLxOnj}qjNy~C$I|Q6*Ch|m>e(>Vqr`1 z!0UNVVq)rFbl{2=ZQZ7T`k5*L3ST^5s*Bvh*$pDTkuixbxE>qSH+Zu{;*^dTLK7S<^ z&b+TXe*%`?YrPhTLPm*Q4wFBK51&c~dQDE1D9P#rXtrvUl)daCKC;+RNn?+}V!MZ( z3F|#AU@!Hi>>9ak?RU-szToQ65i5giWJ@esSxk`z;q7b@pTj&|%2!EQ5d6;mv`JRA zWE<~rx2GkhJe}`v(8P3;kz4)Hs}v6oQ|JdIziJnKmqV*syhS9}s&tx0L4Tnb!pTtE zrQ^x+Hi!OjR{D{Dx{Yj>g7esU6bFiO=x!e;;DGcuGJnBknA*s_Vc+Q|SoqB6un%|; z@>NxJg0Bv!#pzaH63S}RjvKr5%EK_o@s&<0DNr}t=J3(5jv~T9zs1&++ z+)s#r?q_?V&B_%3?G$`FA-QA&5hm`J8LRzHr&>hl!4ieHF zy1TpK(Alr2rlu=wTAEVl zLEU+an1F1mD*dO(&U+iCJS|Zq8-33v_b`|1Ayhv{j^2uFzFw$OxvuRm{O}Owa=0zp z6$B#bEptuDu_j+5ZP%}12EOMSTGZI#A!V!_5m`1QblqS{<;rmGCjtV3gFnJ~KWMd0KUtk5 zGdb&aBM{-CZqW%bvmGPnOGwqq{IFwA6S5S7$V|05bydZI!Tz744}#nX2TGaD;}WIR zy*=ADhl|gJP#FIN=dSy<8X}(I8Zm5|nH?Jsv9MSc(q}S6%?j+5-~!&_!VlE_@IlB$ zKvR}t@czC8Ro<}@rQ=wP!{8N{^}*p$Z1HrhV_J=;-rshoJ&vfVdhFfVbhY)aN5|nE zRmqnP#X7+uK~}^44rfp03Ezotl-=mTSDKCX8gx7nyU9jJ`p0#`UVZfrR{A+9Jbcr2 zc1$y3;V-!DCgrzDd;wErCk?JvhIxLk#q8lT#Q|t_prm$z4U_&LRf+vjZJwLRl-B5A zPVRhCbo5NkCl8-jx3k{^@Mzo|wm$B-VZY4kJ!T}Egh@#>tlj=>A2L&rZ{U*K5_CzG z4`+-bwYs<%D3TNzGkbWE_KE3~l$YJ5;mn%bsJk_DS+V6IKaQ8pVh`7(SczV5>i)&H zfNgVYt}C){C-2CM(OIz~)l_Ra0h44r{0*I|_f(ac9FxUN`Ucd?dUHC>LDrm(ifg*= zYjs5mD~aU~D16!DV!G|7v0gc3&Tc-}Qg%yjM=K{g%f&^X$%X8NJ0W#|t8SyHgPgS8 z&;sh^4_-GY_nO1mnZSuIDH&z`7sKe0W=gfmYNc0K$Y1_w!jgWP)VBHN)wk<;^ZkS> zhn5qC@6qOy-EfpEQIji0WSAD!pH>W*n^E8AkwWgHkjmha_lvitSC^Ev6FWxbQ z&k2^1!)40K%EZF112cLi%1-4gktI)RT&9Xu%{j16w^{7J-U6yF*3GBw30!oB9@(+N zsRqbY@u%Ua}|82E8TywW(-Tx&Dwo*wg1W{ZO&$po+{^GLc z3*t}Tj`owoBlEE`8|z{3?v>Fz-C*`<{f{3dQGff_xsJ*0WX>psR@aJuNeGq1=)S}z z&w=O2*gBhmH6!GQW7Y#wVFO zZLlaCr0U4u!BYjbsIV}wv+(kJheih$Ha6F%Pu=zpRlj947Ga0SMkm|te&g_HF^5k@ zyv-^o$VhL-!g#zh4Wo<<*%Q^j!C9s8sm*)8155j6X`#cb`dxtkrj`{*^Zy!`1{Sg8VDXt6JkQ zz9w-IkuQ_-OFWg<%3WhpPML$ABaf9mLsPHZ4RU;ZJQs*ezpOSzEP+kS2am(s^-oi3 z48*LK9^1?D(05^c=ZJH?nfjhO5=L6%vq-QHK?`NQ3VR=KlD%6zGt!{n1JvcDfOuuX7E+q8l5I#zn62Dpf zSIl2!49oe7^+r`#_|3|XG5@{ih1<)5n+ziED4AK?eyEqHhQBaNT86TBzCb8s*H%{v zcA?FIKCsz?p|xCQ=|6E*`HZwBq6z`DmInW(Gc8*P6VjZTsFg zV?KY7-yDZ(IBXkt?E-=-M%n0dS59Zp^J!_ZPb;OJRWH?K)vp?j&h<$EJMa)>9`A%+ z>+)1Zge9&lYiRQtR$wDO9{N=>Wie8CP%AxFwZ{b*vv%j3y-7*a zpnx6oTVbQL%hTz4Mkjg0d}6%lhH`HUux_s1oQ$AZHBJiy9S+^asNFY{eo9SJAcpKQ|y>|Ij26gtY~Y6>A)c*Glro|Z{Fl3 zTgmM)(ixb2R@vg2(GUFBYsLmoiEo6plo>)6byVzibkW_^99>-8G3xM~Xvn!o^JJ^* zaqgeKFDf6?-A%2`o)eNo_Xjq<4Z@p6vGrA) zd1^W=7vEF(H-vbd@NTz7n{)If!8vpF_nwbt9`ozPWcwSd$P{kB_B($*>T|o=NbnNgfw_34t| zoKCuB^P$zrRtl$`&*;#u9fvHKV+;xGU7fx4E|K+*vfeFib9HNpDkxA0$=I>_U!HpNBt_~ zS&GW1Bw8(xC=S3TC+E(E`{<1{%Rd%f98&VfImnzWDU4_z>WjrBiD&9Cnd7<3t>pRM z1)$@Q&mEs+VA2QM-50u!R{3%Prr} z%q)nh^@56WWgzm^6T6|cPYZdF4FUNV47vg9<2B*+Sw-%QvAEChi_}jnWoDe#H6s0? zFoN|0-`1b~`^LMWA(#bjtd1EDPn=2DmBwHlY@hVA!3tKrHw$-NiqZCn?O2bS@)@g8OprD9kU;Hl8viSD93S92IHLwd{3jEc3N?9FUgGn)m7Y;#L zwef+aiV^0`ZzcV2ln7n9kg`(5bYxmk$0BV7>k4@ve)J3Ed>vwEarE_>OI*p^HOPqi z8`HlDw>&)QOG4UOFVm8JeUh54TMH`kXx1K$wB&1mfN{qE=m+TDdCCq3`QNt=hKR~}`OpoX3Zi)NI zL)xOEqxJs28+P(^+tAIIP{z!jc3zuBb^Q)P_|U?^qCO>F%GyTxQ>i_+S=|@@xp{y} zrsvWcvKFtSK($6aA5Nmd1!U}fV=mKv2Mt|O?$9(Zq~;#p#D zy>`1UspeRf<;Rs}WXGbMVeLrYdOK@!wfXqLx!ESM5!rrTYU(SFcZqc8*j^l@TjQsj zqiG_EtNBJmmskKeVVrzGy8`#%hgDQQ7knIPg?!1I*&CfQ!z~NF5}0I?zr~)Mnz)#) zt#@2fn{3$VuVS+l3MFO#LHjheWVUABq3v(J*h{F_(df=?D3K(ILpGI|;(MEVB~jdjYw;OM>nvwe3sF$6+7PH|{u2{Qq1;<}i&OgB$P5Dk>;E4f+@) zstdp7p?dxpAFs<1E#Ou#OZzp7OLlIqijMA+`AfmMuWg^h^uPzs^k`^k9$iDotYUIbK!r_J$z7Ed7ZA<8v_*GIw%K}-JQYFkyp48tGaIVQ;+hFd8(o)X=4D_8^Js#LW#P6{i&y~v#+}#Bu56t zJrKMB?3KK(Y$$mB4!R&e;OkO#eE8tox1{?6PEkJiczDrK8v>%P-wU4?{6rzeC;MWm zaorSwdxJwB94DbE3F*oGbZ}78(t!x2EV%bn9itxeYlryRFM8;Vjk4UpIQ?Bi=L7T^d(9l>d`NR+jRt%~Hat zeI#e(z6Vq}yniab8kIBa7N&RjM0TjuZf`{6>$d6XPrs#U``q8|wo^9+K9W66e~V&G zpfT*!Z$#SCD^jzwX`e2`CFL?9*s%rlFXg=pe4p8;+0s!{KYes|ejnzIAPoF?9GYeQ z;jTiT`v6on-@!f0_xek(zTFpTF@rhnGH6#;xw4^7K0mD8;n<4pq!ROY_nF@do$_}* z1=EK{HJsD|%gWKh)c*4q4@u4u8zOF_1!?2-*NoWu)4z?Kera}FrNm79nboUbrL>8W zH5)e?z(`(sg1s4{!=7KonTB1a!(vW2cZAF<=3W#@ZNzX$A=~rfbMNRUq6jGil1+{B z=xU4nfWGcvI`t%(Qky-2!JwnT+h)&O&Q-yq!+&(NcFSpxbgXxaHzSt8>e*M^S%e>$ zRd}%jPHAWe@E#q3>(Dmu7Zn}`ksu|AN4Y%<)HF2G;%x1zUSKw)9#SJv+;6~^Z_^k?wJUJz>P3ZFAY+N*f_)M8B)KP9R zBad%#{N>yxdBje--Hw^BVve6Ok9N>eRd8cpm%d!kT5r%3`DLxpomrq0cB!cw*GG0Y z+YImPE2_8?zUJ(b!H;GIy@ukAP)WI`AtWTEDC843D@O?XJpvc8q=|xzGZg!5HTe~z zo(C%W2+21fiY6N83cG6}u9J_Im(ssPrdV9L4FB~q84Z@e|2>FqkX_uZ?B&K-`cVFR zmeBzky=-b)M$S=HbU_+oXda^#q0Jd*xHI?Lxe^{(R>ihlr87@ zQKih=<29DFI(l+$Imzi+&`p!h!h*vQ5Ipmr8_uBd`CO()ETny;VW47&*GoS@vP8L}~6nao`!&v5X#X7t)CIlcaNIsU|a@dcuGqJP4JSV}BtG0DIP~e*vl5(lhB`_n7N<>K>!RfzeO?N%>+Ox;eQa~=-Z zO9`yxTx@G#Qg4v^!kg`=KB&xa-}Yboeg- zZ=dTfbpltdQc8y4f31n4q6J{bf7k!rJ3Q*h=qC!y8Ulg*H(+T4%EC6lUQprT3)X+6 z!1*aZkyH?(!1e#D)A;`fGE^5P$_*~?;j$9)1jbVw&v4&UlL0q~!c++kRZ64cH#dfN z-@9q8W%R9}U&immcql-L4HO(J$^~E1rfP>Nq!xD!Ea%eRqv86;KsjVu^TNNhGy;XA=45O%RnuVUa)9W;@EVJY(Nw(FTmD_}e7x$rGB4yb!;PEf=xIjO4Ly&6GVrq*2TyKg%eXj_b8Vq{`H zQ_IA{Ql2Vknp#rryjwENX*<14(Juc!JGH2Y?IPe0K(-1)o?92CH2j5*kkxLg<9vU! zCec`KI4YT33J)*JPz<^`D_v9Tt21V|>ub`=iYJ@5TPep7P*Uf|zd|32pmkQir$$YK zl9Od*F;n}F`mDA#-o|3Po21%mNDuDKGd4Uj{7=`e@?k~i-fYd`x6Qi+g*NID{(R8u zD;(OUH=;H>vAe-@ff2_S4zaVSH?zNuE)chge0Gzo4h4?Zy6^CUUOwRc*Vqc@Q6^}d zZ$4~JhH87!Up2;rvhg+8A^!xyM~6NJ8}9}nEz$y0Oq12A#U)T^FyF zW-LtsZ=e8~VTfcG(}B26fB$|d?LERfP1m`ypw>-WYvA0?Xc$ZwMLMQnl=wF@61&^JlSGMINEBwy!SGcq)e&a z4hf6S@`J(tohRTOq>_R^UlUsb9GGSsB(orMJjj@09o*A5Z{D(6{27c!UXv?*(Q_lIUf*;^4| zjY!`io32%OPQ}pvT#aF`4eYX~lJ4e(S(n@>pcE7YXuX7VWIM<`66#`ykq@pxEr_SDDY`nJ;Gx;zQ)v9f4 z^5p$MzdF-c>@}A)Fw|mtGV2yRpQ~N9G1Moiqj75b#m&9I>thwVSrf|P?#{US z8`=ki9Kq$vx*M&1jp*{pTmn`-KR^}C90FlGGMz4#CZD_(mk%Z4viLhJX~N_@P~6nH z)IMG7q_3zrFx|5}-A0$6ud`Mc#^bn`Gl5OcI~X7_A8qvh!hU%)tjvfC;@}E!%}uhu-%NPomY`s@4xdQnsQV+ zsQZN@6hL~WvA!*yZ%fUL7NIfGH@yTuhR0`G?U_luS8wTP(|kAE&XIyqp=mRq`Hz<0 z{(F$EnoZ5iNsQ@^F(3I*1F%Z`AI`iD=iKBbrRpGXSD8~CTgiiCH4yV+QFRCdvx>|m zfhYLVFVN~FTOQhZB^Cpae24}D3BEZicbT$64^Lud?$>ACuDVDeNTb< zJtdjb)fZ~Q$-_;bbh(ung_pqZws3fj zey@6Wy0@dtH9Bs*r|~hv5AKOFJ9)s$JbLi0TfKyw%O>b9ObXI~v=Fwj<+QuFqVJiK znw7V)xcmZ_1i5sZ9YV?xk3o2%n^aN3nsa*v2h+;k>N2`c+S9jW?x^C7<*40ZkE7xe z=Si5jk@z&&7k);Wi?kQo&Gc@0Ii@zLn>2QLx_a_y46WH+%@H~GvFOnOhLl&^d^bK` z-E*Y_f2@~Z&$kcA{arV=RI>tr!q51M|F+{`=vcg@ID@Z}l+!(F7m($gHpUtGMBF=$ z#~&+?SxrC3$GvQC=DKP?o>uS7dd2Pb_QDfew3NnT(x<_x?ViXrIKw$I_wIwVh`1i30n{O zdW)DWlIQG~n?Y2&yAaw3)8@bmvvB)L`O9d4K8{?t$^Hr$0Krn+=$u!g%iq1lss4(U zo5qB>Xy) zxJiK}=Ei{Ec`|IApZ?I^(s^i~s~0edXvDaJ-u@vsckcOZS^fIzZ(fbKB9}FAhvO#U zmMIun%?SvQhr7#^%X+wnSb1@s?3gV(v-9s89AAq=O4(RXv`EIoiWmA6RcJVT|GLQJpFhw>46_k+rn2c9~CDTo%VdjqRrci1RYQhBzID0(PjrgXvzRw1!(4Rk9T`sIaiAmgd|H4T zMZ%AeFwI(HR6lL6xdN-=lZr~VB8J{9U0vis`dz#2Wr1+i z??L*aYO+fA0$AbNCE>)MuHA(Oq{@xfBzgL-( z*P@sa&}eP#`HKMgySI?-lR72-{4Q$G=A0+l`+jTf#7)OUoz{1;RSmFBBRQ?Fm$ik1 z1=;Csw7>oa)h-T}WTGUo8CltsV-fRbr)l%~qzXz)4++digkhIh77+9%vPbYIUaf`# zY8*uXR{X^fC)G{MnS1jx5vae=KgB4S-6wi)uds$~$zd^Jvp76abEd9L6-G7=N5H;| zQ)A9~?JFosLRu9NLMa~Ya&eA(K3@1_$&EZ5S((|`r0fZGn-h&kP-()RGmo1;6pLg8 zbTK_!GZ}Pudm-=V(QB{!{YHw7hANfo0VPXDD9tT440xwdrY7v{5Da;C?-xOl?Gm_@ot<(NZU zkkT`8L0-vFx~GqI8wl{NFcC7p+pq>Q`;Ku)?X>eYI?*TST8jL^Bl$=H&t%3`mW?dNg! z$Z6~h=c<}A%t!~O z6W}`Np6*tRCqJvE_z=lM!gZrnFS0k42pqPztyGYrr&~`Be6D46@ipSN;twG);zxdC zB||q45)6zo!PaWGogABttJMB{lk&*qpJ~XQx8gk*%H#?3Z{nvU*rMfz5GDF_?@3p>W;-a=WIS#Wp#2OAx_7PEE82ZR4v zZ)x3t-~DmlC5i||g&D&_i&Paq&G!EVh|uKa+e~tp$orJw(Gyeh00j+&S3L;AM}ES0 zt+L;!41}?2s{q!ep{DJ>#fzrhDE&K5ijG1}?gDru{Lq_OI=e^es>#yGW5mBNel`nA zDUTjpx!==&^>q2MZJb1IVUMb6k-bRu-H~qYG_*&nhHJSH({&(BYI-yRp7P4;e{@i3 z5^sBYIy$<#fIUJ^0&@ZDox3FL(au_CbBUEIUq14m$)-Vw)P1c{{{`7 zNMcSwcABISs@mg!Uk;mJA6Q$7-HZE|W(TseRsct>it|<&JHVd2Kj32c-S-icCaJuW zPyF+C|Lv z^|3Q)RAgi~e{f8U8sJ^3)GVUf@0|;{9@6^?xd8rlR8-WzE^sH9j7rC%J&mSj0hJQ! zW2IwVRue553toI{ZC1;-mQZHPJ_Ur{NirGaLQ>(;NI-RwuGo~>aiyPaN)j*vOCg+uuFZz6ds+h}`$;)An3a}r4>=&-bug8*~~6@^#!dFFHF+JJXN zRXOxVF6G4aCBd$N$y9~S_Yo4OZ4LOhNpgNq*W=@JV9HWyu8G_k=$sz@HyTh>tU&Xr zV8A?aj`KGYh)8N{xfN+@mg52M7SzsL*PeKi?oMQ;ZKW;Ux-+*FLU42Art>_y0edEj z>iQRu9?T%U27$fQE&ItUAwMoX~z|Y2~E3RE%6TdfovSu6Q zmB^h!K@`UMjsrPOX?=HDj? zK+5TwK$X6vM@vI@vOVdOt(#018k&EE=Ke1@D%7Uk$J{?rOk?9@oo@W(k-%PP1&C(u zE$t<~=NX?DH^)bp8|q)kGb9pkcl-Ln`Ui)90%IXR)0C>yqu+#`)=HSi1zpAkRtB$< zf9HLQfa?D?T&cV3mB$#6vAX!$yvKJV6D4;VMCY>$t62i_BVLEmH=5lH5x>pb+1q-V zo(JLKciZhnOME1Qar}<__3I7W=3xbt4=0jMto^U#JA3Czo>3+oOxKtDoL^5acC@sJ zpLjv@|Hl~zh4wuNza@xvq+W1#C~;k#1i7)vTH);PCeBG%&oXv9?Npq$74&LXUkoc zy0Up_W@Pzo$j;RRHstTps^gRTxeCeez-f(12S(*l6;aTAFhoeecvGq@W8`@4)>P0s6I zR93|%Os;OH8?*Ip?M3z2H_TQE+1X;Zdb*C=Ji-VymVTg^8CN!8Dw?YkmsYkLZ{i0B zEncNgjrJyPPdZu5cSt5rRbLpqGL4Y*xRq<1hbjx+z^9E>ovc|l68M6WAxSQkBPWp$O7hUR2_u@S}D=Lu#7mtuWnJi_t5)u zJQ0cP3%>3BKriYGz{~>twu?^+Gbj5qlJrAUYJ}I}m zLqDRh!PA=5msSS`n=-}VJ|a&zU?Jfp#%7{BUWFQ}&E{)NT2e>AFs)7M7(Eqqsg|(COr&m&CQRDUD)c?fJ?9JlcSUUzn%lIcXZ` z_^-|$H8z%=NmLmap>e5lAYtE|EQfmV3=Xj{>RfP) z%pq|eVLdUqWrz@b)zf7>hpnZpWpX#pq2Iu|wjZrH&F8onwY?A+nIjPAld?0IQDVdp zP?cO~JzFO-c}Dws!5>k?3#&O69~lsn)h6S2ZO$;N_kUSbWi=-nI`FrZy&<8|ty8hCHI z;5SyIbs|{W?X%bDZu<4FEps+m8<(g3q$@rO^U14KdAuZMhjcM9TD^2gBF22d z%S(UdSHZ`;KGE7aM7qglF;GRpko$G@wyAUI7LSWTluYU}r)xh--!rS4#xf^~chyT^ zq|6C2nSYJHx8Bj6ZohBF(T`G!+w+m%i*}kQ%<{imfGd&NGl}y znbY195k48k&cb3AU4)`y@EQVWx?g-AL5YXKO>^l zrZ(ER@o>XhA4`0L{6^`eAZ=`HjPOLoA?02iP4y(>nW9rKaoU>^U|>kL^0>f(Ei6qH zN$1psg}LF7ZgPBmfwqU_$LhSyLV9kLIhmOe%M#+@kqX$_z(O`(Q~xI;lss9iktCdBGS&TMCauH@>fc5kO5G+Q;(fw z(r=Q#!istK77a1WSJ!E*prVj@=DOJ7!&Po9w zT<%+2GH>Gm7WH~WzO9bw(h zq_(7aD(P1xVQ>ADYNxI$<4OF;42>+ShwfIM#f)#-q=mG z>DJ6!X>=tkb@y`oidTR_x#kGwx4~V)tFMdL)m=~7ti$7!PvYItLbMGJ`$}SmW?#Y@ z-B_(ROFfrjUJG1}r}*fPTjp@ZD#vX8PckcUfn4h|g-y-qm-W{uq9+|q* z9+rrB%6c|zy{9@)*Ka-a;3#yRvE-)e6^M(LXhoQSwpVzg1DJI4bOowI*(t%eX!F^- zp?N7>uFE)n(8jMDA4K(a$&#^mruyP8jzCz%@DqhX^9u`GXUS-F-flbzz#;l*q^Fq? z7ACh4>($@#t<6ippsJ!`y}v57JaTEXk_3b4dMQ>y)#R~3UJLE7;>Uf!}u zf@&{j6sro&v2B5>Vl{i|g=O5x-Xb(su7w*SQTRo#*>bgNU6e0{ zdJolcpq9h_Mw~!?RlfX;fA17={W+d>hUMcesxEO533BbhE(ijl$)mA8w6%M1AGZHQ zPCYHTffQR^RW&q6+pm2n%j-Q+6dCQ^=nj=2U2pwVY*Jl}=RwG*SzK5+U1Xlqd_=EV zr6euAwb4?qB3q<6lo0()RCxkkS!q6&e(BrVN)<{nC<`0~lk1Uywix7Q38XJsbL>T0 z7c<8xmzOd?8YRyVI#OC7i;QK|kKj+L{`weSmu70L3ZIGl9fx?``t-Dp)-gKQ>CX7r z8%3thXY;sJ^4(p1yR(&ckFVWyPmLFaE0W{m^D<|&FN{lc8r9Ay!M0RcS)^{ge}BIo zxo2)_`g<{o^Fei4jQ`L;n^}z5>!HzEYrcc3sYj4cYVdOLzZt(9&X$LHhFY zd3ov1?rwa~2?MNS+fCm^RtJfhzinazZ(c+_``70BNULO%Ufr+AoA0AVTI*XI_@1-^ z0s<5iU;Y+y0kgYHY|?DJ3)b~`uci#8QwviKzJ173G(|hRa-dQ>-I_V-A6QcMJg-df z`LmGG&hp`do8y+!wD}X?MXhy9cztkek&K)iKP6FKFzsNAKPLSyWlI1yx9e3av|vmr zMP63Ae$gW|Xo`%dA|og4rNDW65PUW>b9Hrjcd{Ju_pj^V?O%e4Ko2q=TD+m0w4$Ps zV%dW2?W8xCId~qYSE6ICjE!!NIqN2$tXAEoO0-LELP^+ozn=ZrrYtv>J8E3waJ`cE zaCN}(dL~rx{xBeIkRnR}2Qd<6wJ5bWg1&H6ed(04x!E|Hnkc?*O%mBR*B2_MFsM>8 zSeEkb*ROM5{s=F!po_~NR>~$vrF?iJDj3L?a4%UTQY$33(lDS+1+pNFE48`!WgzQ_ z&OA48uaeC+L*L_bZxGWBASrv%^D(f|zLB9mk5x&`$tX_C%Pt0jDj^kE<*OLa1CD^!MKe6ZX9S0QQ2&rh`Zm zW0~9YaM7cvD7@*RM*IK80`fvMyHdOon8R8Y3a4uPTvG$+Vi{6+54>>5`6jBqRF^By zM2h2RXldagwX_)VJt2FC`sSl({2o%F2N468)Kg03EebmaD2BYW?yPCp~>w&Rp7SzC_%Ue5rzq zU3nxAx#ruR74+kC+5L;g&pczlX=lbJj)RXn1u{7z$?Hp*(tg}wJ~RzM;h~Rk(g0sq zP;)H*3q-X*%i)WqC7F>CFd-6gsYytC&o-#cih6m!;>VBuwZ|okFQO8@JrbAk0iOhi zi8^DZ(*I-2_r7q4`x0qVhJL4f&bNMMchRzDyyQw_8;y&Y?g|WXI+{s0R%39zF5O3) z68&~RUPPo50C04{wTIvpG=0I%p-wU)oVy8>u^FWMnzHI!0i}K9L+kC6wb7=zVSfzip6T|Ji#ku%yO{< z=6xSMhwUDUyHPyR#^ABGD#BZM;~kJcCF84=B2>0c<726r1-*Es`Xngx=0T6VQc_}?SMrC;?C7tZ zaaGW#F}aE!OYK42&O>=cWPRB1&~X3 z-Sczswyd9wA-dTE1Q25uX}VJ*(}DAEA22Z*UADr24{z?$aH?lUc8ho@-!-DP8NsMm zH8|VW+aa8kiwb>svdPiWKW%(6w>43X6Ce%RwLx4_r07+p1z}9TWAVs`^ZS>sc$D8o zK}b-KilLQ*ZxSaE6GLHN=g|S?x$ZZi8NdA`Gb=0V&~$TdjUf|dy4-E77LMrY>N~A- zcUX?Qy{`P6XL1WW-tIm-gO3*0+n;7C>mJl{@gTPgltejbk7;7Njpq1)^5XDGfMAPB z)9Zd);iz^(W8-pb-}LOdZ(YdWiuZxW;fdSJsOb1KYlWGP)}-i}?(y8rR(ain;*VOB z4aB2W&?JT{(T^F~MWaP}6FKTQnoGZoysTzQw*qgIYieR;6RIOXpCzzDIf6zSt)0GBk?G_jbQY zC#0Ne-iQq$XEE!o!-Bz_w5rW)wh{=9=GT9lsQk98WPRPu%g|0JZrMhFLy1 zAz_jGYZjjhI4(<4`unGS6ToyAdi%VrgxEWaZeNmVX=#g_+r2-xsL04tm4a&b5}wKY zum@yt)Cu=vGcq$&xtN$fnu~7v1E)fTydNLmv?0iT{nR`2Gs&T)c8AnN1`K_!vY|;S;&6f~Y9VTu z_Mw=+e>hmfQs49OQGji2Uf}!7*-r>irD=NiBe;pw2o19WV7YC|%D}B;WyR3M9J2Mh zEHXv-ic&>I`UFQcz|nG*Ny~M+HBS$0nTP?6qp-MmcOdieS4%57IV~-W%MV(US>UMkD=zrP)|TaT!wy*4kNXFk-Ipfe zu8wgRyNX~ z7yW4eQAMU;)f&fx=yIq;gx8J3Y+fmbzbhxQ3v&!Cawy)5z5)E*67tH5s^yhn630D@ z>i7ob@9M_YciSr$Pv~FW(9#+)ocmEyLl$V2jBZW34R%Ds=IN(4YxujaW=fuXQ8bz94I3S-KuSfan zxEnaEl}rN(R;f^3ohr*%1spG~N|o0(G=ZN4aFJNM=05+0lm(<4CRKTg01)+}`X#l*R)KPxobNF>siJPUa&Mvt zRbE>8;-Q-(WN*vqR#YXV{7drdl*S4+`0*R(yAh!87nGkL7;j{6=&ZCzm!=?*rlP2r z=X(yJqodjs?MgH}HInHy`^u^FFCGhK&2J$EOY#}fL^;&o(W1rj9^E1BYX5_@E4W9q z>($tLY~!Hj$dNj9Uiy!XBo6;djx0A^afNvcw3a)`(gpJc$muj5RIzV)EUD?D*Q-h! zD--C#jO{#ygi4CZ#4vZ&TLwceGUv6NZA|*~ft9#0(Cyk#1jG@8!y;?L5Nq$=QZe1w zHTuPOo{D)mQnLnzEV8Ut3gJPy zc^eztlaof9pCoSe2AeI0sIYP?rmBpFrkt)rF|j<8Kco=z5!W78R5Ix!BSvF@mKz9H zrEqt&Ie476Wq=SD-zRwMyvt#Ze}>y}V>}^SSC=$4%NjHI$09Wya%-X%=o<(B`uZ+6 zs1{p7%_hs;T;_&Y7yI*?%Bu_U>(Kty?ZB&sL957`sx9Q0jI|+viv^-3I>q)uQ2+h-3oL=>cq2F z)z5>(i}NR@E6sk>#&w`+t0?z06!Vj@9sx`n0PLwKDqe2Ot^`)9gq&JwMDYy*{_IJf zs$J1m%R>DPo8*xZQVw|@L3~bbu9(O-)Q8vWgZFdk3v#r-#7UQDpTi|K%f69IvNRgg`f<9D(72vW>86+s5D4mane8BRR%5o z#-V-ccvs-#bxPU;1kxt?%4Dpxld65FfuaTbm~wepVB@Y9D6kdk%+@)VMFUYFajJ^S ziX1L!ser%$kEox923G1?RBzIlD%jXFH)G^wv)E)k;E;PC#m;t~KZ(bOVLhQamni@3 z0*2}6Oy9AYdm3Y+PX#&As#KT|omzQ>SERj$4tPXZ@3%f9A`A84ifySJ3*jURVJUv1AV6U z%GbG%{ls*p-eVnuV~5Js&{Zi`hu}XY-q%zrOqy zwDqmY0LaN@CRvThUY@|bm&bQXa9;p?=*IVBHPi8H$Y;5f;c_4-52otT=Yvf~myOhi zTQYRqW>YqpouTQ2fzD!ps~oJVa{$NqDFEp}BX~wIlQK0r!g@-~_i}&#X-u!x-&CF3 zxmmOH{poCo5_Nxn|4FS^j6mBsLxR)hx$`_uV?FCSV@Iay?!VY^vUCl8}Lfg^%|L-8RM#cBY7i&*x)!vyu4Z ziFm7QbSkt`9hH*K!) z-|Z}|a5;_CfH@C^DT#;A<)8-$pG%S4@R%rky=0uNckCMIzBupInn9M5+8nP1RcN(* z71r33-WAO3L51oHg5JU=RQLuvJKHNEg$*f+mjSLkDwbQOe?-NA)zALXq0TyGgRJbi z9*6oRyy1{(RR@z*its{9mFpq?!dAVTrf1*Ln0gR(!3YB-M<_~bK`_?eX~Fn1!DQ03 zF2Gh=i##Zsj(jTEl#pG~)+~iFq;k1&j4jz-j$8N)Ei84!4y;U;6q+3EX+DnyxbBGp z%P@|I@b$gZ>r?Kj32)L#4and{_vq^>!ps^1B1|!cF>5O$i3HyfZXjp_tXFd8y)QPm zzxS>)X@C0lerBEiW5@cD82oK4>2cNURb!D>%z)>?p^79{!i~;wYVv5Spz3Nf?}BRH zH(bRh+3f12uDcsA-jCZ%-H-}5P#N`xHex{@A8#&BR^wV(SWnifjY9*WTLfb+#H{wF zj?&vpt3HzWPow^=1$f!2-;;cue={eZ>%E=xiB>DhEhrjbSF=yO{6kZ?U2=^a!t65q zfxhE?>fNKX*UZiU^)E@q6icL}?|59c z;0`1+JHRp*ehvZIsK}WcW_RZc-K}TGd9ulGvqV_WnmMgeQM`3l)>X5e3r~FD@8pQ) z>Z9fq7JpE0eVfDg(xX5Yd;0zt%>`Ss>tAC(#8sE7zD z5-bS&WdNJG{Ov{nYp3iDpyJ8@)P4REUzSx~IAa!XB#G%4#+z@a;ZUcN=_(5!N5`44 zHe?se`Kha^{*wfk$iroZ?Ms>Yl#W~R;dp0nIE#e44K+cGZJzz>sv6tKR zqr~gf+Y!u;4*nQnc|>q2PO}$va+Y3GT+^+srA*5J3MZ^k zyRRs4&L(-T6Lp=7bD=`B7;*8@&c+H55H~$UwnTk)Lz8$kUE!PcV!S4tMe1`cP@|K& zel?r(z6&Qy>{Ncqp|5gpJKgxp#foWw#$MUiSG_t3B42fN<>D;4d(huS(Z`F+ z*}so%IP$ft4i0h!-nX|b{CsQBWZOK08-hQifc8mZ;JSOA^o(rm9$s zicTiRO?kaT{)QQ0QnPHHMrdDA?6BFxJ{1VIELe4d1-}xeL12?{RtFX;(atSHLl_}P zj^E1Llj#20+;1WTpDNJI^)0z<#vRQw6@h+~%VL>Jf@=T9CvAV8e)9I|0ivnhIUjOT zmOR_Zl5eSKGoFV4yTL?%H+JtZL{6J@Smk^5r*T*BXZ$$-YpUw@!6UC~a&nx0(Sa^KA}EFiMUvNSMOBcUAt?}2NkL-VE!f|+@ruF-;@wy; z6(c*J!Y7at7$M>#-{kT^x?Hxp`k$p!-4iE6cK9_K26BsNU~NF2%h_~c}Xdf^SR z_q;|MQsN}-LAc=+=*RCf)u2Tx5yp%ShZLR--xc0wKrxF=zFvksNa2V&7M05OedqJs z^r)CEslp1Xb?GsjW|i+26ytL(5ses1B$#kjbi$!&WqS>Ou?W%Q`k_iC-oQ^4`bR#u z-{~%pfKFkqj*JK4Mnbc}sJR*cP?PKqUNci_F!{6xg-U*wQ~fvtxlQxjQHd>W$OuL} zF)+R^NLUH;S@tV>;1`-jlnRuuK$JcZf4~ZV@@L1oh^(WLNb$2X$~Bv}BY$_v58{wn zKR6fjfFI8AC{$`zSn1j$;B(Er$NA=5v}>LM%QG=I$Ph znwa^A*Tv&Mpbo5fLZ37=HZndmme&y+lvvnhmLm@udAjP#j@!LzPnD={#NAZJP0c>J zkDl$eH1S&&FnGatIju$(CXe<}zr)_ZVCDetaKcmQ3VM_;Z>N^pMFK!@7Di?VMVS1% z^#%!r79SNS*H?Sh+A9Ge*|R|aBpW=Hw`boTsC?_ zkt)y>;zo^8@PuGAEBSK-qM#__FdlwQS8>Ww(sZV;4pN%ksmEyWju4)Pd!JqB&fQS& z(|j)ic5GsDe=sA_G}zBlxwrm8dF(DNg%w}!L}iE{y<4DJTxO7V{+3r2oi$$nd#;iq ziu_6bf3{{=V9IcN4uyxQR+eruutj!Pioyh0~N3;U7oBEvp1HpV77!1iWZMBGAC z#-582zS|%npv}jGE68+p)>Rbo=^dMVfMh#LUXAGT^QC^I35kehGe@bcwp*(%nD2Iob=s zG0qxr+5x?vb|gu1w2HD<*WKKUf(YTKsM!Xuuynn}W2yL>+T_NKoylyEy^|&G8BNxWsL>KE*}&`1syu_hoM!hD+*x_t7lVWILHp9J;yw0m9Cv ztPmO0FlOr$pc@4(G)P$DiMtv7yPQ3cQtznZj7R=BSiz|=D?~+4{_P_@58i`|QlM8i zVKpVInQ|;=yja*qieZEMmi%BGRND&JXl$G*AGQ1xF;hz>cNvQx{ zf*Q&Hn;)3#eg#;xR_3PLFCIdH7>2+rr_BcyUZSP7yY=|nZJnQ=21tAli)W0%ReTpL zDViU{6iM9RUML^#&xh_w$^SE|r%w4be4)g7s<3Sx)eyDLaTVX{-pAO45!r~A?B8Iy z8o9~c9v5Ok88ZQQFWpMje6q=`(y=1h6Xg+SAVwpuZnlbIvZxtBKB&(Gc1IBPqt!c%)CCQh}CjbuB{A;z+RewLtq zcxN~w+X06$quJy5{U;=dZ>nbQ9SB{fqTA{C58f2FB~|WOpuZmnd+nlw2apD&XfAOZ zr3B`x>0eadPq^d7#Sv6*;|mxHnMHrh!X2Tkm#02HY|YbTjq9{jn4%<$th zS=r;(_E)RM5VF(uSb>`qkBccLF0PzJs`eJnNFZS$6-6{prG*`Nf%(TFK+kOFrBqf{ z@!XrqFt@E9*xB?_Fuiz9fOU2NXskvM)z-m{hz%)Hepo`({6u}%g%OEf47$~(hwN~L z)fNuu4bwC9#T08y7rVGzPHhW%&iwhiu`FySJ=5!yPz6ZbzTQnHOj^-67(f$eZ^lcA z_p7N2XiH1Yzs>XDop5@^X@1_rPT(C^>APkIO{alp0a;nhLQRh8rgbE^?*@VENk`$& z^-mQO8QdcSvQjM z`f@oUA)zzyf+gngYe+x{ugC8#|2N4Ms9}LEk#Rv+$w)#J2-~22_DN6x?PsEsLY+$d zRW(*x9ugQ36;%@Wo}ymF!5gw7@g{5*vYV$ij3|8^G+G9Qq%;<{Rc8A}X zc~1#bg}C&otsdn8x5KNmj>3wYNRr1VdkhTf^<3OHjdlc&Sf|dDubYQ)$z$}=gxL40 zH%Ia&K-r+8qGVW6@84Pgn;G5FP^l6_e63WNAo-h5i(k(CE3nVjw#BF8zlsJ|vvEe~ zJlA#Bl((lK> zOOpg-_tc$}Yl9*ls9bM!zVQ;*Z8o5~4cC#1KD9$+x;;>WHO7}=tRLD(;*_YO*Oqst za{1{hUwVtCcrrls0E}}q5WPs@kX~Jgi-TXefmFDR$tq&%<#Y$#A z_f|Cpbcf1n>rLj9Nt&ySSkGn}8r*`^hSnum#l>3EA-A>0WYCwJo$o@her+0n8Xl%f zVfGKE>kM(Ck)jYgL3ldp#noF+TOS~w2qrvJKX+LtGqoVcZ0V;d9qV4jlIMAmiXeZV zE7tL4b%z~C{95Y^hVk9@KatT8 z_E*JL2R%-o-@W;+$x~^=T_Wdl`l#dPcwl~>6)$;|P$!(quP(+L^|J)r_ z=ssYzDVuY8!KbRNtMrF$2pLVFbyj$B>b*EOl3vGitE)-<{ zH+M@`hu_Fk1{tT#Z&_JcWo0ao`DzSyHUQ`~OApX&T>tdKKkOFs1rY%@rr7FyMa47Y zp427sj;8-Q7LYrdR0G&|c^WJ?bX&8Bd?;GwX4xL^C+beC`uXv#C++^Z79j-$4aBN* zKJOwn>#f^&k9-vw!3x+CmzHLEn>*|?RMHw!g?=)_r%`6_wBN<7@pD^s zqLP{6SmeXQEBYf`28ir{?lJABVIzk=x@Y3_Bl0`|5aw(b$?y>~5ef>8pBe9oREs{`|6H<7cZxkcHNt~Hp`nZ@KsRwt@^IBY z$P&%dlbQ(Bkt%ivkowN8)0W%Cg~f~wh9L_dxRo>ETbw6u%Zp&VgQ{h`tp%B=w zeL|{Au8v6n->zCSM%Ial2zZf=*(|)3 zi~M!JV9@K4!%r0a|R#$-v>4s7IJ;RrGeHRxO z7kTkt^pF2gH{R~emj1?N(oVxL2S7?1n%p+AP&Ygh-5CO0jH^DT(s*t0D z*xd#2s$TQI{ub4qPo}0{o%Cr{reQ$%4Or!Tnfw$|?;+8W0m1@lxM^P)nHV~WFvci# zp0ObyN?T5s)+Yyze&*-RVdmr<%#xi=@;G(cnNhgR`~3h}nouyS3*D?LNJq`|i$1H0 z7qZ)_gL7WJ)w*@w(C&0)r3~FcKqruF=~caPn%=X1_jzCB!-rde#_<9T*&UNXT|xo# z?M|<`#@kf$C|cfX>rAt0U|6#|cgDx&Irifd_$|Ye*Ldv7g9l!dePvGdUhBJnk+3sU z>QxxeA+5;Vw7J}SM-pj`w&KlKEtJHRR-BD$JncG&2ndjfpt`YHJ5JeL>{E9z>j!uC zL(NmwlE#E^UNRrH>PiTfs6XniQ4i%}5s($?8bB91Rz_-wO+4 zNByDDr~NCbnF!;-0_C!0QL(U;?Je$a=3_Fm1SH%gn(yAF#jf7gTZiCtyk%j@JeOqu zMC&N_;Y0L3ZSEDu{f#ECY1I*b1giqcbMJFA8`AW6p2%hlr6Yw2rAej<)vfHlW~-H1FP~yUW*$g|&pCYmMWq{JFOqCE(D4Wy*LsHm?x&y?;I#cJ)Ew zdz(XL`8?n9LCHli(`*K=`&K1q%222Iz>hyloJ&2ITbp#z@8({4g%|5_AiQo3ndF{~ zlr?KDs@e&m!%%GRRn8V&ih?AtLaoc72JW&^Y6r zjp!l28vmpOzvB#BXC2SJD=*L(2BbP>W{#rtd;&Zo z?ZNiAp4Nc@r@fg*Tp|L^tktQHn(Wpa(J3h;m;`kE>YP-Z{_Yu?zzx(%oV(m9f33nj zp?WtJTI1GxHZkcSxakfla&G-Dp1oIkE^~XOkkdh$Zkp1YL0^kFa2u4kmIn zSWIW#gI|$TQ1m9J8JrWvPDC6(z5hK@Ol~7mn0^EWpm<)t=3(LEX8>0BYUf4|c!qj&F#|`(-Z&B95{Lxp z$%`Uj$e!$&ondgd%RY2%k8vm4=Yih@s;xo0BAAFl;59cuK!NptAi4Q(?)&Tc~LA{iZmxxdS^OEuh!!bDW zjY^(!t^3Yn_IP}PQLjq#$Bu#~zn9`U#z(4^K6-zyiLG54gkmkrCExfn)piUvJ@9{w zzF}heF-h^b;k#5{fB$2&4JwcB{j{%u$8oR@t5oLCij*Y@vfz)I7ksBC|>kt@F!@uLElOk1vuJA{G)Hz9>y8SxBcEE{8eHUMbjm7*yX~jm6O_9o zfy@I*_{KbyT;cpehzLZF7I$x^TQ+Hjr8(3*$!WattV8{5jsQ26`U%U2d!OH8vbf$Z zn(GAmKEq~j-t*6j>2-(@KdirGD^Kqpc-_2)~~-Q$xY;kW-&ZZgQE zRcC)S(5S;-UuiS#J_17PM|_z`eAdTZB%)#28ZIJoVKV^Frs*+w%HV)QU+2E#S5=j& zo06>LodhuK6m+`*zqPCvXK9cf&qW9?veuyNo^(pIBb2&6iI?JT?i`O6CZ=Wm2Iqfw zVXy7LhGPq=B~(uPqD>@6?zbg}>d?#eIwl;Yc(Pcc^=I(y71 z86L0WD){kfwhjL-?`V#yNZV9Y*~<^i31OON7OPFJ(pA#l(8hW`ex>3s1}CU=xvMfM zH(1%d{TJ_E#vEI2zwA7iP0D`u3}0Yx_WM;b9Tlu*GC-G#&-AujB*rgV8^1|oQI5NI ze766MV6k}ZS;gst)i+-Wbl`m&(vlu%^C|H-qYqSYtxYTV&9~X10acw92*dO3nX=!- z(R*Os%YB#>8(VQ)>^ARysWNijdq}f{{?dlo zT5oL6w23MHCM!kz@E<%N8$0h?F^0tfkB^O4qGsTOvv9*T6j;ssB4x+&_s5i9JP-lA zj~u}JNP9SzdH;I$7u`xXjr0NJ(RZb%oUUWKP1PJ5HB&6QgoEN;wsw8^fcJq*e99*h znF(oU+Ea+rTxp(05I?-N;vLfPR^y zDK+h(Ey}UWYt3H}@m{^A7h3#8=(ir{tw5t^7S)S5F*(}Y*xJl$s|9O*YXcMvZDJLN zaPhh7>wGHI|Mu={oZuI0RpnT$hvtPl;L^{PxNSxFYBDny!|~aS#HOYv$8&UcT7I`} zE2#)GHnLn3ha%*fa&UVhw7v_6zcFrd*CM(HN`fubq^$4V996Q<(ja|OPvfl(#666^n-lg*Eh4SL5zaQl;j7X2P?`m(AZNoUW zZhS^W=lT3-fo+SMTPz#bct9vQJgKk&>WTMQ&-sx6%*oO+swe6&7z^b@TRSmBUq5z_ zhzB8V|_@#A%>;ln{x8pg1_ zCZ5A+d>kM4%%!<$q5HQ*KGI;M%Jw(cz;uop+F=E=jTqUw=mS7qk`9P;6~^vQpWSSk z>VXX}Q@M!(3k^TN#)|UFPfaddi1BGIqyBJwY#}uRh?h|lSy|1}2avOpz1KDE!Xoi_ zYG=0pNaXUZ#bm=KiO;~1pkt;(=V@Lz-FU(1@Nn+ddZ*{!zg1I7DLGwgN!dPXvp1X> zW7v9W@4~-S2bGWhNc$=l8fUwC2=zmQK_HM60gs#Q3sfnb0hJT?6C#9*3Sy&XNE>?V z_et@C#8Th0&sDOeS=c7VfgdEKH#bm&+zrwMv*egrS+&cpm**ZJZ{|j1w8djf@j97y z=G>b>el>=>``{Uc?-f`Mk%Zp0>hQ_Pyf}C?wM!foG*|qPqRix782QUp_=V&Q!S|t- zu5Jk7Q3!S0-r|PAKV{Sf%#u>4%!g9g3xL~|E+-Pwz9gN6WtvuX8u|I!RrEt-`sfR- z%(&j%SPd;B=jNt=!5@`+7xv)gd^_vjpeN(x#UPFc6qOXIFS8(7;(y{238f|MYWa|RE+YSV3ef(rWeZ$hvjnbxzl zF7T`!u^Vo@E6Ra>sCvt~-1&*iCHYB#d@}w_RV1F;-_=9>n%l%H!}E8 zHHJ`FH?K3vj{vtu%hfv8b*4=i4D@xFxwG|l1RaCd8Z5w~++}J)CFY)6n{g`<~rT}&S>{3o&<=5^7XV+=PEzH+sUIO_h+e%Vn=D*F-+^`MrL;K zwIrv6>f-4NH~`x*G~vknGO<~Y^J&_89npPyNuu89-CK%j!p6=H>R9+Bw?$t(xNpfi zBSc8|@}dCc5<@MEnxG3Xeq8*~D(-*gP%$be*AMt0O;U!3XVxtdU}vK2IX_{x5O~obz!nbxIJy2#UPANUK^9sGm~@&hPm_EB z8^LjF=4Ka;d>koysa$wXzCkm+V5j$-U%>t49|6dLrCu+?hS?8N-m7A6RzHm0YV#dR zl)r4hM)m}$2FG&N*h_2%HzrDzOa>r?A7{ANw??A2zypNlxnXK(dA8Q4WM99N!tll~ zTiIieeChLw$G5mWvc(K~db@b~VyEyITEqfChTNUr7@;*gQG(Fb}jm(T0Zg-`ztv5#(x#J%$wVf#RH>W!NZSXp4 z@12NeFPhIbiSY$3ZUGO4NQRzr7LiFIFo85#XlQs+#T;6%@)s8DP!}kY1O98`t$tvH zN39lP3RCKX12ATaR{2cVYIdu^>cfU4q@F&cIWZXX7?1qD63^~B<#m={HivQ`=#Mv>}`J-;(L z+w~8+%W;9@*JQJc%j(j#r^&!YP|t8=5dH zVxN)ueDX-44SBevG79pwarPoejn~CA!UhO)C2wtQl>)xVaBMnD6#v#lVPS6WyCXZt zk|0;?O2^;ZPn&OK@uEh`ii$$>8Usti!_7a+sc|y!^V6tD#zwMP%%#utr>7h6R9UDL zaIfd5`(Ndj;sgwzMt&2|Ci6$O2n#$%Z!Mud!xe2$+_aV;_rGDq$|)niv2@VEw_1W{Y0* z^YQ)3rcbMIbr5CuTTN^>C{^DY(rwd(HHp$7tVkM zQ##R96U+WdF@pZ-rrE(Y&xtw*?!TpH`Z}{PG}NtM2PXZAi-)pGwDMLub`J;JXbmjj zIdL=0HK}TgsEC!6nl+|K%Vw&^J4u6mGJA6q4>h{L6&p_kvVcJV5Ly&LA0j&~tqL|a z6RPb3B)Y3O#@V#`^Lyd|ikrq`i7|=-I3Nl>^_;3TNJuYutn%xTXH%A+Xq05Kw5S@E_&F$=a?|A*Xp;coz|HKQy*v}KZ@3@Q&p3QH>9_V)ZL3nHudfzeDj z(?swZCn&c`1{E~8XE##3>q+)=euidHmm>3{nE_+tE4Fhp@kJt*^?Gy-4Rml*E&rA| zY*Q0q8Z0yLo*I%i-unDo3kYm?qwI4DI!vt5i9~ydgv9& zh-E8D>-(5rsb&jreea!!O}tN;KxO7@|2m4ax0Yu#f7E19(C(7(QJ$GkpM$ewYWSER ztb(bvl_vON#Zh`y1u`;wg^{7JgIk(H%NR4AsQ?FxS@U%cDaMCq@gZR4U}0sa8Bgr3 ztph}d!IvyA)<_?i_T?@XRs1OOv3X;$8>?Re0QTQ)eJ zh~}?_piaWRjDK1g`rIQ>oi%{ZV$YW{SiGRaIQZ?tS|K^=ZY(3U#Q1|aS7@@vb@g$( zTAt<_v3j%Y4&Yv)Z;XC@N%=?t<+HLoc7WpJuvhg?@W6R0xta3Yp>Q8rh48AnFg3uj znan*tIU(G(qKS=ST9=fgk!lVJa$#DJ&o;>tezrZ`CX~~>-ts1XDBC{ zpVe+#91+kqiETW*(|!dJ`+u60IsfT;%KxY9nTqpo04>DupQgUXf13K0|7q%*|3_i= ze|^CAmes=*d+xiKmO@w;Qo~2AB#JnG;JdG#5t8K~e*ls8i%Z(}LYV)UmWLzKhYTb6Ch%l^SoP`}AT za;W8c1ae%>78RYcUr9-YdSDNv)L1N(M_yrf>RQI8=H?)-yo;gbr2&&WKHf8H8*!~z z7%79eCdR2ureGIe{cvNW09MuuPlo^cG@&Zgd8FR;E)Z5ML(rBJ;;m@`uL8Mu3=W`mF+oF=D?a7yDW*+Wub>mS^#6MO`_QvAgC~p2hAKjhFc6aTbdo@}`etwi;ovVj6JfO$9!)=FnN+~Zn zJFiT1MNBXdM{a4YG)Mdd59a^R*X{qF1GXS8#h2&5J?s$5B?1d1a6RXJ8o%yj*l=FC zmCD_V+T?{Oov#=;FKn)-*Q}?XPkyGlbE!CIOa(ZlpBR$O&-{B0O$6m6^blXVP>&el zKS>^We0k=7H`?|dfhq}7SJ;<~z83p|EAne~Pz?YbILDU#;bZ})yD@xz2Ua?KU#s@+ zX%x$T=kzJ@+nM3nAn!z4*ZC%o6dINQ@-5)X0tBQY#L173fq#93cfyNP7Sj0+|4`y$ zo$ROesVUigK6Xy8q zO4aTq)jpdig-|%7_Js#r<7-RJ7E!0CS>rTY8-?kC5Fe*EF2}U zo3{w?JKVffQsm_*4sboy>+AZYjFwz(D=~P}ra#|cB=90vxlX_T(%f4Hq|^h5gXK^h z-$z6Gnd0NH*V)^Q%cPsHmK|MNtL{XySAX{4ON!rz&W5VW(kAb%fp7z=!Q}cH{mJ_n zXNTajxIK1%l}+T&Cd^Y%6l&BT^gw|)1v|Ry{*NRK8K;GzVIX3vdgwSYIy&88g&Q)n z?z1ui-2#G6?942*hD7!}qdceQ63=6L(Y#L^J~d8#y*zvITCyqce_~d&1N<;nSuVi{0rB=3*Kz&3>Gm|R6#3;q{qjPz&Y>l zAY#uhIp+ar^CU^_gVbq~|Pz}<2_3!6V#z{PI-m|XL|Lito0~t>^FS%tj1ogD&RH|Z9D|LX2sSyoZwdAae8S@6mC9$t>5W>;>WHFm_> zmHPN@+-7u1G;bT+Td{Zh+iRO9ugjjLzWjK*W%4Ly67yGg`A^(p(u|DsTeP?n*!T!k z0mr~*9+ld3ATP+9Nw@wTUIM9gQ-3R&4xGivcn2Q}xH1xQOj@eR?nx9XINqAorjjc2 z0C9J^JwDkn1yeEX6TIQY9f*6Uz)i|xK70r@5Jg9=u`4xpA_@F$oR#&@YrN1O%l!48 zyp&lk>1Ux9q!p8akltt5*5%yCToC847zET+Y0GPV16< z5Uw!X1Z@Ci(qw)Q;%oXp-NOP>zfQQ`#`dnV7pzYdn6>o<_Yu{fnwgqXQc}#Kx{5oD zPE0hr!&Nmjc)~g@X43<5b0s`ITifX-W_xSLPYY#_uGd%MypY2HrgvyRqw{lTXv$oL z6=#%lC!8x$vL1l&hlh)4Xh)Ty`EKyb(O2<<*CM?DiH8?j1)HO3V#o7#I!GjW_y^JfSf9zZ$OIn?Aa^d>kY=(+=fSrRfqTs#}cD) zHlqhhCO*k5to;1i>>b_1i+!c=ZJJTAD-!H+lHNU}6@T+)6v}mhmU);$Yd)v7Ow!GI z@I2+@)YLbz2KW7q?whY-rmra}Ib1LhRbwO=BBppvvieLqnTkU3QB7h1-jP+E+m+5Q z@yv{TrF>)d%S~wG5x7(>;=#GOXvESYFNFvVE@Cx`7q@$3a_;k0T6?Wcvz6$|m2x=% zfsL?~hj;{dPb)6KthYOn&FfK%c)NY^TiHP*Y>Vj5fPZPcBSQQH+y6QaMSS|dHPSEz z=d!;^y@KLaMXH(hvlp8sPB~5f?gZy~8DsL((z=%qxU|sWovU6Dh$0puN+Co}&z;o3#L`Ehhhy^`{UZ@C0luk-grf7fWa{GLeyez2Ld4 zBR_}JObkOY@n7A|GxA7jpTnz)h@;SAi;?akT|*;@i~Ck6E&nXOl4@$YK}@N|a?44(W)BR-_m=1;4TE`E6DWAOO9 z)^CN@fBXpam+fnx`De&e$Fh9cvjv&M>p@l1#T65$k@7}~%AR;F4+9DDY${5yQ)cBx(YXL?dzJhW&X-4zJ#x3GBQvYn^M`}?T z^Z++;Bq3&MEPLXxPVoOoLIFc+G?&8dkuMTKSa7%fcQPr&AO82>;CJ9;08WjJmzP&6 z?>f8}PlSWts0kP$FWPhQ5sOJhct;|e6u;V+?}>(R9@Q zqpYDqK^Y7SwsxZ6dHj|Mm-AwGwRhE;!+NQ>{&d^G-;FQ%Yok{`Ou*;n zpguX7SSjm9r&3i-%|!mTiKHo#28T(#>2SC4O78yG;Ad$0YDX7NBM&`zHM2e}EiF~= zO)1s>G8yd%i5+Cp{B=_JP-+!#ijUF1xE-9mXES2)YT}`!>^Om)4-4t*>+9_+QBjHU z5)inXn^-7S+EcJ9DdD5Lo>Mb0gjjV@^KvLU8yQ*~!*rTFot>RGdSj5$iJRQv9jgvh zAtAwsea-RJF`=QMaOU&x6NI^31*RLUS zYar_>e1BSih1MPPSNZeDH|FYZqbw%+t&#wSR(P34V&rYerv#Pbyv2!B8eXlT0$?)m z>axu=j23EU4Oo>=J@8~%v*XAqDHMzn9^HYc>NF)v&!3F4*n%K_h6b zrFDQtsy@LChU;IK1$oZFye21tTMjEf@kn8^$tbNF*GZe^!AvJpXwea9znNVp!*8~) zIjv@8(Xym(zuxCSbKD*eN+RG*X5l~^6_1ZbSyRcsDx9zR-XVX{IOv{#;Q&_+Ci zYc^LC_{5GT&(?{Gh}rxP*4{EIuCH73B@jpg0g_+=0wf`LaQEQB-7UDg1rH%W@Zj!J zxVsbF-QBHl*XqUpJ?|Z7^yu4tPT#w~*RGtNbOrJ6H)WO zdlqEwbBW|ds>yk#jvkM)WnlcjGy-2FpbRi%5C?zh9 z^8F|$F~KY_Taw58;&k1FgM)+V72#_>9fygNj(2EVEop6sZ!nxJ7h00>&CT>0zm1H7 z*g<1cW0{-6HRV3fAv9B^-1M#K6b}kFX5{!NpIT>gC}55~2W}%e#}WZVM;rFl1CKRc ztbml1lZ>E>DF z1ta2ZZu5P5Mqv`H-6wk~(r?IHxPOZJ@Y_PM!AWpS>I#a!iEhF}VQhL>gELN(HIC#% z4+338gcmzJa6E)N;(pv=$i*XbO>ZX^xEoy$dE}98j$fR$p-mMj+AZ{M`1&Fdv1EM7 z$Gf=5<9`x`M9AeP7z(W&p#1QGwxS|3Yl<`&uOtR{>NtPEO@gmHPqi^V!~6akCB`@S zoxu6Jr6$My-56W;^GrF4dOYW0iGspHsbn4j=0!3uzLk~NP_c)4VB1=P5JlxYx^{|_ zCUKmb*Zu^ZP)^P9v>^UgkrGi}k$vd}3N0+);3?ybgbx;mkK#hkD&DZ8+<3e|_JEmI z@%WsHoE0P`N`xNXuV1v`F7=?CJ1if)lb|l~flI8bW7dYB)+_0{F z$}As`E=T|LVCphS3`)!L=mInNCLA7 zIHjgg&pB;M)y^Cqa(#;Ei{sB_;iKuBlZ(p94bINqY)VqMYu=TyHX5HP`-`2owIUc= z9DPuFFd?yQyy1SgBp#3I&W$0plns|i9Ydy7W3*Ug>C&BFf{Q=EIbKdQL81#BxS9)d zogE~vn>}8})%@MrTJ)`?>Kp4o=a9x$iLV*JdvNLM5m|st)-`%1;b&>zj%aFA&j?Hy zMs!XXSEVts3KnzfmShjZeZK8JfQS2$F5kWJQC7}YE?qE@BFc~g6FEB*$aUG-(O*(6 zzUiBP`_?|N^MDY5f^!YFe2M@&U^F}2`etVMi1sF zZpfWlsTi7FB{0_~&!}O9R*JvaTB4Ly(WN7?(zK}#LbBXA^%+bg#`9acE{Tc%0;1%N ze+|=4OwaXEdYnvRHtwjoUb;506elNrv=knX&-J%C8hd4+>hNU=;Tif6%*;eru8d8- z!Qoblm369=_u-qFo@TiV*ibATwr9%?gLiK)h!iB%xgnICPOa(6#p&>bJaP+Gxv8oK zhK4lSr7owF`;D#_f4+Xwp>1<;um_gz#&4*o`T&6izDo|aY4q(m^~&D|nw+;p94^

N1t0mBO1{?85Kl*6YS};8<>XLzJBP0 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 NTI%=jmfx{@^R From 5955058dc2a470742774cea1a75f37a064d25f77 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 22 Jun 2026 11:30:24 +0200 Subject: [PATCH 5/7] perf(filestorage): add FileName index to avoid full table scan on root file listing GetFilesAsync lists root files with WHERE Folder IS NULL ORDER BY FileName. The composite (Folder, FileName) index cannot satisfy that ordering for an IS NULL leading predicate, so the query fell back to a bitmap scan of every root file plus a top-N sort on each request. A standalone FileName index makes it an ordered index scan (~15ms -> <0.1ms at 80k rows; files list p50 40ms -> 6ms under load). --- .../EntityConfigurations/StoredFileConfiguration.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/modules/FileStorage/src/SimpleModule.FileStorage/EntityConfigurations/StoredFileConfiguration.cs b/modules/FileStorage/src/SimpleModule.FileStorage/EntityConfigurations/StoredFileConfiguration.cs index 257e3490..309c4c24 100644 --- a/modules/FileStorage/src/SimpleModule.FileStorage/EntityConfigurations/StoredFileConfiguration.cs +++ b/modules/FileStorage/src/SimpleModule.FileStorage/EntityConfigurations/StoredFileConfiguration.cs @@ -19,5 +19,11 @@ public void Configure(EntityTypeBuilder builder) builder.HasIndex(f => f.Folder); builder.HasIndex(f => f.CreatedByUserId); builder.HasIndex(f => new { f.Folder, f.FileName }).IsUnique(); + // The default listing orders by FileName (GetFilesAsync). The composite + // (Folder, FileName) index above cannot satisfy that ordering when filtering + // by "Folder IS NULL" (root folder), so without this the query falls back to a + // bitmap scan of every root file + a top-N sort on each request. A standalone + // FileName index turns it into an ordered index scan (≈15ms → <0.1ms at 80k rows). + builder.HasIndex(f => f.FileName); } } From 744d931affbd18d70e717576dda82b517fa6fb97 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 22 Jun 2026 11:37:06 +0200 Subject: [PATCH 6/7] fix(test): conform Localization test fake to paginated GetSettingValuesAsync ISettingsContracts.GetSettingValuesAsync gained (int skip, int take) parameters in the list-pagination work, but the FakeSettingsContracts in the Localization middleware tests still declared the old single-parameter overload, breaking the full-solution build (CS0535). Add the matching skip/take parameters. --- .../Unit/LocaleResolutionMiddlewareTests.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/Localization/tests/SimpleModule.Localization.Tests/Unit/LocaleResolutionMiddlewareTests.cs b/modules/Localization/tests/SimpleModule.Localization.Tests/Unit/LocaleResolutionMiddlewareTests.cs index cefedd27..5116f341 100644 --- a/modules/Localization/tests/SimpleModule.Localization.Tests/Unit/LocaleResolutionMiddlewareTests.cs +++ b/modules/Localization/tests/SimpleModule.Localization.Tests/Unit/LocaleResolutionMiddlewareTests.cs @@ -271,7 +271,9 @@ public Task ResetToDefaultAsync(string key, SettingScope scope, string? userId = } public Task> GetSettingValuesAsync( - SettingsFilter? filter = null + SettingsFilter? filter = null, + int skip = 0, + int take = 30 ) { return Task.FromResult>([]); From b5f8d2749bc3bf89d2a2748b4cf3835a89fd09d1 Mon Sep 17 00:00:00 2001 From: Anto Subash Date: Mon, 22 Jun 2026 11:59:29 +0200 Subject: [PATCH 7/7] fix(deps): patch transitive vulnerable packages (MessagePack, SQLitePCLRaw) The CI vulnerable-packages gate (dotnet list package --vulnerable) flagged two High-severity transitive advisories on this branch and main: - GHSA-hv8m-jj95-wg3x: MessagePack < 2.5.301 (via Aspire/Wolverine) - GHSA-2m69-gcr7-jv3q: SQLite native lib bundled by SQLitePCLRaw 2.1.11 (via Microsoft.EntityFrameworkCore.Sqlite) Neither is a direct reference, so enable CentralPackageTransitivePinningEnabled and add patched PackageVersions: MessagePack 2.5.302 and the SQLitePCLRaw family (core/bundle/provider 3.0.3, native lib 3.50.3). Transitive pinning also requires the central Npgsql version to satisfy the graph, so bump the stale Npgsql 9.0.4 to 10.0.3 (matches Npgsql.EntityFrameworkCore.PostgreSQL 10). Verified: restore clean, build 0 errors, full test suite green (~1,800 tests), dotnet list package --vulnerable reports no vulnerable packages. --- Directory.Packages.props | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 76f08c71..3cc49ba0 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,6 +1,12 @@ true + + true @@ -22,7 +28,7 @@ - + @@ -97,5 +103,17 @@ Include="Microsoft.SemanticKernel.Connectors.Postgres" Version="1.51.0-preview" /> + + + + + + + +