From 09c106e020c216722145b9d905ddacf58e5769dd Mon Sep 17 00:00:00 2001 From: admin123 Date: Thu, 7 May 2026 18:48:42 +0800 Subject: [PATCH] docs: add distribution build and simplified user guide - Include dist-release/ and release/ for direct colleague use - Add beginner-friendly installation guide - Update .gitignore to track distribution builds --- .gitignore | 4 +- dist-release/assets/icons/icon-128.png | Bin 0 -> 15279 bytes dist-release/assets/icons/icon-16.png | Bin 0 -> 777 bytes dist-release/assets/icons/icon-32.png | Bin 0 -> 1859 bytes dist-release/assets/icons/icon-48.png | Bin 0 -> 3302 bytes dist-release/assets/icons/icon-source.svg | 13 + dist-release/background/index.js | 3335 +++++++++++++ dist-release/content/index.js | 4446 +++++++++++++++++ dist-release/content/market-page-bridge.js | 583 +++ dist-release/manifest.json | 58 + dist-release/popup/index.html | 12 + dist-release/popup/index.js | 219 + docs/【超简单版】插件安装使用指南.md | 132 + ...chart-search-enhancer-chrome-web-store.zip | Bin 0 -> 85680 bytes .../star-chart-search-enhancer-internal.zip | Bin 0 -> 88024 bytes 15 files changed, 8800 insertions(+), 2 deletions(-) create mode 100644 dist-release/assets/icons/icon-128.png create mode 100644 dist-release/assets/icons/icon-16.png create mode 100644 dist-release/assets/icons/icon-32.png create mode 100644 dist-release/assets/icons/icon-48.png create mode 100644 dist-release/assets/icons/icon-source.svg create mode 100644 dist-release/background/index.js create mode 100644 dist-release/content/index.js create mode 100644 dist-release/content/market-page-bridge.js create mode 100644 dist-release/manifest.json create mode 100644 dist-release/popup/index.html create mode 100644 dist-release/popup/index.js create mode 100644 docs/【超简单版】插件安装使用指南.md create mode 100644 release/star-chart-search-enhancer-chrome-web-store.zip create mode 100644 release/star-chart-search-enhancer-internal.zip diff --git a/.gitignore b/.gitignore index 65ceac2..b625a63 100644 --- a/.gitignore +++ b/.gitignore @@ -2,8 +2,8 @@ .old-reference/ .local/ dist/ -dist-release/ -release/ +# dist-release/ +# release/ node_modules/ # Local debug captures diff --git a/dist-release/assets/icons/icon-128.png b/dist-release/assets/icons/icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..8cc212df24b0bd77fc9a1ad8f74a78fe74955b48 GIT binary patch literal 15279 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 literal 0 HcmV?d00001 diff --git a/dist-release/assets/icons/icon-16.png b/dist-release/assets/icons/icon-16.png new file mode 100644 index 0000000000000000000000000000000000000000..b2d62c6b63dc42f64a5c68d4ead0d02c463b1c9d GIT binary patch literal 777 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 literal 0 HcmV?d00001 diff --git a/dist-release/assets/icons/icon-48.png b/dist-release/assets/icons/icon-48.png new file mode 100644 index 0000000000000000000000000000000000000000..ed5f38f2c26de7401bf08cb7def8fc1ec0d9b0a7 GIT binary patch literal 3302 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 literal 0 HcmV?d00001 diff --git a/dist-release/assets/icons/icon-source.svg b/dist-release/assets/icons/icon-source.svg new file mode 100644 index 0000000..4c81685 --- /dev/null +++ b/dist-release/assets/icons/icon-source.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/dist-release/background/index.js b/dist-release/background/index.js new file mode 100644 index 0000000..89db7fb --- /dev/null +++ b/dist-release/background/index.js @@ -0,0 +1,3335 @@ +"use strict"; +(() => { + // src/shared/auth-config.ts + var defaultAuthConfig = { + apiResource: "https://talent-search.intelligrow.cn", + appId: "i4jkllbvih0554r4n0fd3", + enableDevAuthPanel: false, + logtoEndpoint: "https://login-api.intelligrow.cn", + scopes: ["openid", "profile", "offline_access", "talent-search:read"] + }; + function readAuthConfig(overrides = {}) { + const nextConfig = { + ...defaultAuthConfig, + ...overrides + }; + if (!nextConfig.logtoEndpoint.trim()) { + throw new Error("auth config logtoEndpoint is required"); + } + if (!nextConfig.appId.trim()) { + throw new Error("auth config appId is required"); + } + if (!nextConfig.apiResource.trim()) { + throw new Error("auth config apiResource is required"); + } + return nextConfig; + } + + // src/background/auth/state.ts + function createLoggedOutAuthState(config) { + return { + isAuthenticated: false, + resource: config?.apiResource ?? null + }; + } + function createLoggedInAuthState(claims, config) { + return { + accessTokenExpiresAt: null, + isAuthenticated: true, + resource: config?.apiResource ?? null, + scopes: config?.scopes ?? [], + tokenAvailable: true, + userInfo: { + email: readStringClaim(claims, "email"), + name: readStringClaim(claims, "name"), + sub: readStringClaim(claims, "sub"), + username: readStringClaim(claims, "username") + } + }; + } + function readStringClaim(claims, key) { + const value = claims?.[key]; + return typeof value === "string" ? value : void 0; + } + + // src/background/auth/controller.ts + function createAuthController(options) { + const config = options.config ?? readAuthConfig(); + return { + async getAccessToken() { + return options.authClient.getAccessToken(config.apiResource); + }, + async getAuthState() { + const isAuthenticated = await options.authClient.isAuthenticated(); + if (!isAuthenticated) { + return createLoggedOutAuthState(config); + } + const claims = await options.authClient.getIdTokenClaims(); + return createLoggedInAuthState(claims, config); + }, + async signIn() { + await options.authClient.signIn(); + }, + async signOut() { + await options.authClient.signOut(); + } + }; + } + + // node_modules/map-obj/index.js + var isObject = (value) => typeof value === "object" && value !== null; + var isObjectCustom = (value) => isObject(value) && !(value instanceof RegExp) && !(value instanceof Error) && !(value instanceof Date); + var mapObjectSkip = /* @__PURE__ */ Symbol("mapObjectSkip"); + var _mapObject = (object, mapper, options, isSeen = /* @__PURE__ */ new WeakMap()) => { + options = { + deep: false, + target: {}, + ...options + }; + if (isSeen.has(object)) { + return isSeen.get(object); + } + isSeen.set(object, options.target); + const { target } = options; + delete options.target; + const mapArray = (array) => array.map((element) => isObjectCustom(element) ? _mapObject(element, mapper, options, isSeen) : element); + if (Array.isArray(object)) { + return mapArray(object); + } + for (const [key, value] of Object.entries(object)) { + const mapResult = mapper(key, value, object); + if (mapResult === mapObjectSkip) { + continue; + } + let [newKey, newValue, { shouldRecurse = true } = {}] = mapResult; + if (newKey === "__proto__") { + continue; + } + if (options.deep && shouldRecurse && isObjectCustom(newValue)) { + newValue = Array.isArray(newValue) ? mapArray(newValue) : _mapObject(newValue, mapper, options, isSeen); + } + target[newKey] = newValue; + } + return target; + }; + function mapObject(object, mapper, options) { + if (!isObject(object)) { + throw new TypeError(`Expected an object, got \`${object}\` (${typeof object})`); + } + return _mapObject(object, mapper, options); + } + + // node_modules/camelcase/index.js + var UPPERCASE = /[\p{Lu}]/u; + var LOWERCASE = /[\p{Ll}]/u; + var LEADING_CAPITAL = /^[\p{Lu}](?![\p{Lu}])/gu; + var IDENTIFIER = /([\p{Alpha}\p{N}_]|$)/u; + var SEPARATORS = /[_.\- ]+/; + var LEADING_SEPARATORS = new RegExp("^" + SEPARATORS.source); + var SEPARATORS_AND_IDENTIFIER = new RegExp(SEPARATORS.source + IDENTIFIER.source, "gu"); + var NUMBERS_AND_IDENTIFIER = new RegExp("\\d+" + IDENTIFIER.source, "gu"); + var preserveCamelCase = (string, toLowerCase, toUpperCase, preserveConsecutiveUppercase2) => { + let isLastCharLower = false; + let isLastCharUpper = false; + let isLastLastCharUpper = false; + let isLastLastCharPreserved = false; + for (let index = 0; index < string.length; index++) { + const character = string[index]; + isLastLastCharPreserved = index > 2 ? string[index - 3] === "-" : true; + if (isLastCharLower && UPPERCASE.test(character)) { + string = string.slice(0, index) + "-" + string.slice(index); + isLastCharLower = false; + isLastLastCharUpper = isLastCharUpper; + isLastCharUpper = true; + index++; + } else if (isLastCharUpper && isLastLastCharUpper && LOWERCASE.test(character) && (!isLastLastCharPreserved || preserveConsecutiveUppercase2)) { + string = string.slice(0, index - 1) + "-" + string.slice(index - 1); + isLastLastCharUpper = isLastCharUpper; + isLastCharUpper = false; + isLastCharLower = true; + } else { + isLastCharLower = toLowerCase(character) === character && toUpperCase(character) !== character; + isLastLastCharUpper = isLastCharUpper; + isLastCharUpper = toUpperCase(character) === character && toLowerCase(character) !== character; + } + } + return string; + }; + var preserveConsecutiveUppercase = (input, toLowerCase) => { + LEADING_CAPITAL.lastIndex = 0; + return input.replaceAll(LEADING_CAPITAL, (match) => toLowerCase(match)); + }; + var postProcess = (input, toUpperCase) => { + SEPARATORS_AND_IDENTIFIER.lastIndex = 0; + NUMBERS_AND_IDENTIFIER.lastIndex = 0; + return input.replaceAll(NUMBERS_AND_IDENTIFIER, (match, pattern, offset) => ["_", "-"].includes(input.charAt(offset + match.length)) ? match : toUpperCase(match)).replaceAll(SEPARATORS_AND_IDENTIFIER, (_, identifier) => toUpperCase(identifier)); + }; + function camelCase(input, options) { + if (!(typeof input === "string" || Array.isArray(input))) { + throw new TypeError("Expected the input to be `string | string[]`"); + } + options = { + pascalCase: false, + preserveConsecutiveUppercase: false, + ...options + }; + if (Array.isArray(input)) { + input = input.map((x) => x.trim()).filter((x) => x.length).join("-"); + } else { + input = input.trim(); + } + if (input.length === 0) { + return ""; + } + const toLowerCase = options.locale === false ? (string) => string.toLowerCase() : (string) => string.toLocaleLowerCase(options.locale); + const toUpperCase = options.locale === false ? (string) => string.toUpperCase() : (string) => string.toLocaleUpperCase(options.locale); + if (input.length === 1) { + if (SEPARATORS.test(input)) { + return ""; + } + return options.pascalCase ? toUpperCase(input) : toLowerCase(input); + } + const hasUpperCase = input !== toLowerCase(input); + if (hasUpperCase) { + input = preserveCamelCase(input, toLowerCase, toUpperCase, options.preserveConsecutiveUppercase); + } + input = input.replace(LEADING_SEPARATORS, ""); + input = options.preserveConsecutiveUppercase ? preserveConsecutiveUppercase(input, toLowerCase) : toLowerCase(input); + if (options.pascalCase) { + input = toUpperCase(input.charAt(0)) + input.slice(1); + } + return postProcess(input, toUpperCase); + } + + // node_modules/quick-lru/index.js + var QuickLRU = class extends Map { + constructor(options = {}) { + super(); + if (!(options.maxSize && options.maxSize > 0)) { + throw new TypeError("`maxSize` must be a number greater than 0"); + } + if (typeof options.maxAge === "number" && options.maxAge === 0) { + throw new TypeError("`maxAge` must be a number greater than 0"); + } + this.maxSize = options.maxSize; + this.maxAge = options.maxAge || Number.POSITIVE_INFINITY; + this.onEviction = options.onEviction; + this.cache = /* @__PURE__ */ new Map(); + this.oldCache = /* @__PURE__ */ new Map(); + this._size = 0; + } + // TODO: Use private class methods when targeting Node.js 16. + _emitEvictions(cache2) { + if (typeof this.onEviction !== "function") { + return; + } + for (const [key, item] of cache2) { + this.onEviction(key, item.value); + } + } + _deleteIfExpired(key, item) { + if (typeof item.expiry === "number" && item.expiry <= Date.now()) { + if (typeof this.onEviction === "function") { + this.onEviction(key, item.value); + } + return this.delete(key); + } + return false; + } + _getOrDeleteIfExpired(key, item) { + const deleted = this._deleteIfExpired(key, item); + if (deleted === false) { + return item.value; + } + } + _getItemValue(key, item) { + return item.expiry ? this._getOrDeleteIfExpired(key, item) : item.value; + } + _peek(key, cache2) { + const item = cache2.get(key); + return this._getItemValue(key, item); + } + _set(key, value) { + this.cache.set(key, value); + this._size++; + if (this._size >= this.maxSize) { + this._size = 0; + this._emitEvictions(this.oldCache); + this.oldCache = this.cache; + this.cache = /* @__PURE__ */ new Map(); + } + } + _moveToRecent(key, item) { + this.oldCache.delete(key); + this._set(key, item); + } + *_entriesAscending() { + for (const item of this.oldCache) { + const [key, value] = item; + if (!this.cache.has(key)) { + const deleted = this._deleteIfExpired(key, value); + if (deleted === false) { + yield item; + } + } + } + for (const item of this.cache) { + const [key, value] = item; + const deleted = this._deleteIfExpired(key, value); + if (deleted === false) { + yield item; + } + } + } + get(key) { + if (this.cache.has(key)) { + const item = this.cache.get(key); + return this._getItemValue(key, item); + } + if (this.oldCache.has(key)) { + const item = this.oldCache.get(key); + if (this._deleteIfExpired(key, item) === false) { + this._moveToRecent(key, item); + return item.value; + } + } + } + set(key, value, { maxAge = this.maxAge } = {}) { + const expiry = typeof maxAge === "number" && maxAge !== Number.POSITIVE_INFINITY ? Date.now() + maxAge : void 0; + if (this.cache.has(key)) { + this.cache.set(key, { + value, + expiry + }); + } else { + this._set(key, { value, expiry }); + } + return this; + } + has(key) { + if (this.cache.has(key)) { + return !this._deleteIfExpired(key, this.cache.get(key)); + } + if (this.oldCache.has(key)) { + return !this._deleteIfExpired(key, this.oldCache.get(key)); + } + return false; + } + peek(key) { + if (this.cache.has(key)) { + return this._peek(key, this.cache); + } + if (this.oldCache.has(key)) { + return this._peek(key, this.oldCache); + } + } + delete(key) { + const deleted = this.cache.delete(key); + if (deleted) { + this._size--; + } + return this.oldCache.delete(key) || deleted; + } + clear() { + this.cache.clear(); + this.oldCache.clear(); + this._size = 0; + } + resize(newSize) { + if (!(newSize && newSize > 0)) { + throw new TypeError("`maxSize` must be a number greater than 0"); + } + const items = [...this._entriesAscending()]; + const removeCount = items.length - newSize; + if (removeCount < 0) { + this.cache = new Map(items); + this.oldCache = /* @__PURE__ */ new Map(); + this._size = items.length; + } else { + if (removeCount > 0) { + this._emitEvictions(items.slice(0, removeCount)); + } + this.oldCache = new Map(items.slice(removeCount)); + this.cache = /* @__PURE__ */ new Map(); + this._size = 0; + } + this.maxSize = newSize; + } + *keys() { + for (const [key] of this) { + yield key; + } + } + *values() { + for (const [, value] of this) { + yield value; + } + } + *[Symbol.iterator]() { + for (const item of this.cache) { + const [key, value] = item; + const deleted = this._deleteIfExpired(key, value); + if (deleted === false) { + yield [key, value.value]; + } + } + for (const item of this.oldCache) { + const [key, value] = item; + if (!this.cache.has(key)) { + const deleted = this._deleteIfExpired(key, value); + if (deleted === false) { + yield [key, value.value]; + } + } + } + } + *entriesDescending() { + let items = [...this.cache]; + for (let i = items.length - 1; i >= 0; --i) { + const item = items[i]; + const [key, value] = item; + const deleted = this._deleteIfExpired(key, value); + if (deleted === false) { + yield [key, value.value]; + } + } + items = [...this.oldCache]; + for (let i = items.length - 1; i >= 0; --i) { + const item = items[i]; + const [key, value] = item; + if (!this.cache.has(key)) { + const deleted = this._deleteIfExpired(key, value); + if (deleted === false) { + yield [key, value.value]; + } + } + } + } + *entriesAscending() { + for (const [key, value] of this._entriesAscending()) { + yield [key, value.value]; + } + } + get size() { + if (!this._size) { + return this.oldCache.size; + } + let oldCacheSize = 0; + for (const key of this.oldCache.keys()) { + if (!this.cache.has(key)) { + oldCacheSize++; + } + } + return Math.min(this._size + oldCacheSize, this.maxSize); + } + entries() { + return this.entriesAscending(); + } + forEach(callbackFunction, thisArgument = this) { + for (const [key, value] of this.entriesAscending()) { + callbackFunction.call(thisArgument, value, key, this); + } + } + get [Symbol.toStringTag]() { + return JSON.stringify([...this.entriesAscending()]); + } + }; + + // node_modules/camelcase-keys/index.js + var has = (array, key) => array.some((element) => { + if (typeof element === "string") { + return element === key; + } + element.lastIndex = 0; + return element.test(key); + }); + var cache = new QuickLRU({ maxSize: 1e5 }); + var isObject2 = (value) => typeof value === "object" && value !== null && !(value instanceof RegExp) && !(value instanceof Error) && !(value instanceof Date); + var transform = (input, options = {}) => { + if (!isObject2(input)) { + return input; + } + const { + exclude, + pascalCase = false, + stopPaths, + deep = false, + preserveConsecutiveUppercase: preserveConsecutiveUppercase2 = false + } = options; + const stopPathsSet = new Set(stopPaths); + const makeMapper = (parentPath) => (key, value) => { + if (deep && isObject2(value)) { + const path = parentPath === void 0 ? key : `${parentPath}.${key}`; + if (!stopPathsSet.has(path)) { + value = mapObject(value, makeMapper(path)); + } + } + if (!(exclude && has(exclude, key))) { + const cacheKey = pascalCase ? `${key}_` : key; + if (cache.has(cacheKey)) { + key = cache.get(cacheKey); + } else { + const returnValue = camelCase(key, { pascalCase, locale: false, preserveConsecutiveUppercase: preserveConsecutiveUppercase2 }); + if (key.length < 100) { + cache.set(cacheKey, returnValue); + } + key = returnValue; + } + } + return [key, value]; + }; + return mapObject(input, makeMapper(void 0)); + }; + function camelcaseKeys(input, options) { + if (Array.isArray(input)) { + return Object.keys(input).map((key) => transform(input[key], options)); + } + return transform(input, options); + } + + // node_modules/@logto/js/lib/consts/openid.js + var ReservedScope; + (function(ReservedScope2) { + ReservedScope2["OpenId"] = "openid"; + ReservedScope2["OfflineAccess"] = "offline_access"; + })(ReservedScope || (ReservedScope = {})); + var ReservedResource; + (function(ReservedResource2) { + ReservedResource2["Organization"] = "urn:logto:resource:organizations"; + })(ReservedResource || (ReservedResource = {})); + var UserScope; + (function(UserScope2) { + UserScope2["Profile"] = "profile"; + UserScope2["Email"] = "email"; + UserScope2["Phone"] = "phone"; + UserScope2["Address"] = "address"; + UserScope2["CustomData"] = "custom_data"; + UserScope2["Identities"] = "identities"; + UserScope2["Roles"] = "roles"; + UserScope2["Organizations"] = "urn:logto:scope:organizations"; + UserScope2["OrganizationRoles"] = "urn:logto:scope:organization_roles"; + UserScope2["Sessions"] = "urn:logto:scope:sessions"; + })(UserScope || (UserScope = {})); + var idTokenClaims = Object.freeze({ + [UserScope.Profile]: ["name", "picture", "username"], + [UserScope.Email]: ["email", "email_verified"], + [UserScope.Phone]: ["phone_number", "phone_number_verified"], + [UserScope.Address]: [], + [UserScope.Roles]: ["roles"], + [UserScope.Organizations]: ["organizations"], + [UserScope.OrganizationRoles]: ["organization_roles"], + [UserScope.CustomData]: [], + [UserScope.Identities]: [], + [UserScope.Sessions]: [] + }); + var userinfoClaims = Object.freeze({ + [UserScope.Profile]: [], + [UserScope.Email]: [], + [UserScope.Phone]: [], + [UserScope.Address]: [], + [UserScope.Roles]: [], + [UserScope.Organizations]: [], + [UserScope.OrganizationRoles]: [], + [UserScope.CustomData]: ["custom_data"], + [UserScope.Identities]: ["identities"], + [UserScope.Sessions]: [] + }); + var userClaims = Object.freeze( + // Hard to infer type directly, use `as` for a workaround. + // eslint-disable-next-line no-restricted-syntax + Object.fromEntries(Object.values(UserScope).map((current) => [ + current, + [...idTokenClaims[current], ...userinfoClaims[current]] + ])) + ); + + // node_modules/@logto/js/lib/consts/index.js + var ContentType = { + formUrlEncoded: { "Content-Type": "application/x-www-form-urlencoded" } + }; + var TokenGrantType; + (function(TokenGrantType2) { + TokenGrantType2["AuthorizationCode"] = "authorization_code"; + TokenGrantType2["RefreshToken"] = "refresh_token"; + })(TokenGrantType || (TokenGrantType = {})); + var QueryKey; + (function(QueryKey2) { + QueryKey2["ClientId"] = "client_id"; + QueryKey2["Code"] = "code"; + QueryKey2["CodeChallenge"] = "code_challenge"; + QueryKey2["CodeChallengeMethod"] = "code_challenge_method"; + QueryKey2["CodeVerifier"] = "code_verifier"; + QueryKey2["Error"] = "error"; + QueryKey2["ErrorDescription"] = "error_description"; + QueryKey2["GrantType"] = "grant_type"; + QueryKey2["IdToken"] = "id_token"; + QueryKey2["IdTokenHint"] = "id_token_hint"; + QueryKey2["LoginHint"] = "login_hint"; + QueryKey2["PostLogoutRedirectUri"] = "post_logout_redirect_uri"; + QueryKey2["Prompt"] = "prompt"; + QueryKey2["RedirectUri"] = "redirect_uri"; + QueryKey2["RefreshToken"] = "refresh_token"; + QueryKey2["Resource"] = "resource"; + QueryKey2["ResponseType"] = "response_type"; + QueryKey2["Scope"] = "scope"; + QueryKey2["State"] = "state"; + QueryKey2["Token"] = "token"; + QueryKey2["InteractionMode"] = "interaction_mode"; + QueryKey2["OrganizationId"] = "organization_id"; + QueryKey2["FirstScreen"] = "first_screen"; + QueryKey2["Identifier"] = "identifier"; + QueryKey2["DirectSignIn"] = "direct_sign_in"; + QueryKey2["OneTimeToken"] = "one_time_token"; + })(QueryKey || (QueryKey = {})); + var Prompt; + (function(Prompt2) { + Prompt2["None"] = "none"; + Prompt2["Consent"] = "consent"; + Prompt2["Login"] = "login"; + })(Prompt || (Prompt = {})); + + // node_modules/@logto/js/lib/core/fetch-token.js + var fetchTokenByAuthorizationCode = async ({ clientId, tokenEndpoint, redirectUri, codeVerifier, code, resource }, requester) => { + const parameters = new URLSearchParams(); + parameters.append(QueryKey.ClientId, clientId); + parameters.append(QueryKey.Code, code); + parameters.append(QueryKey.CodeVerifier, codeVerifier); + parameters.append(QueryKey.RedirectUri, redirectUri); + parameters.append(QueryKey.GrantType, TokenGrantType.AuthorizationCode); + if (resource) { + parameters.append(QueryKey.Resource, resource); + } + const snakeCaseCodeTokenResponse = await requester(tokenEndpoint, { + method: "POST", + headers: ContentType.formUrlEncoded, + body: parameters.toString() + }); + return camelcaseKeys(snakeCaseCodeTokenResponse); + }; + var fetchTokenByRefreshToken = async (params, requester) => { + const { clientId, tokenEndpoint, refreshToken, resource, organizationId, scopes } = params; + const parameters = new URLSearchParams(); + parameters.append(QueryKey.ClientId, clientId); + parameters.append(QueryKey.RefreshToken, refreshToken); + parameters.append(QueryKey.GrantType, TokenGrantType.RefreshToken); + if (resource) { + parameters.append(QueryKey.Resource, resource); + } + if (organizationId) { + parameters.append(QueryKey.OrganizationId, organizationId); + } + if (scopes?.length) { + parameters.append(QueryKey.Scope, scopes.join(" ")); + } + const snakeCaseRefreshTokenTokenResponse = await requester(tokenEndpoint, { + method: "POST", + headers: ContentType.formUrlEncoded, + body: parameters.toString() + }); + return camelcaseKeys(snakeCaseRefreshTokenTokenResponse); + }; + + // node_modules/@logto/js/lib/core/oidc-config.js + var discoveryPath = "/oidc/.well-known/openid-configuration"; + var fetchOidcConfig = async (endpoint, requester) => camelcaseKeys(await requester(endpoint)); + + // node_modules/@logto/js/lib/core/revoke.js + var revoke = async (revocationEndpoint, clientId, token, requester) => requester(revocationEndpoint, { + method: "POST", + headers: ContentType.formUrlEncoded, + body: new URLSearchParams({ + [QueryKey.ClientId]: clientId, + [QueryKey.Token]: token + }).toString() + }); + + // node_modules/@logto/js/lib/utils/scopes.js + var withReservedScopes = (originalScopes) => { + const reservedScopes = Object.values(ReservedScope); + const uniqueScopes = /* @__PURE__ */ new Set([...reservedScopes, UserScope.Profile, ...originalScopes ?? []]); + return Array.from(uniqueScopes).join(" "); + }; + + // node_modules/@logto/js/lib/core/sign-in.js + var codeChallengeMethod = "S256"; + var responseType = "code"; + var buildPrompt = (prompt) => { + if (Array.isArray(prompt)) { + return prompt.join(" "); + } + return prompt ?? Prompt.Consent; + }; + var generateSignInUri = ({ authorizationEndpoint, clientId, redirectUri, codeChallenge, state, scopes, resources, prompt, firstScreen, identifiers: identifier, interactionMode, loginHint, directSignIn, oneTimeToken, extraParams, includeReservedScopes = true }) => { + const urlSearchParameters = new URLSearchParams({ + [QueryKey.ClientId]: clientId, + [QueryKey.RedirectUri]: redirectUri, + [QueryKey.CodeChallenge]: codeChallenge, + [QueryKey.CodeChallengeMethod]: codeChallengeMethod, + [QueryKey.State]: state, + [QueryKey.ResponseType]: responseType, + [QueryKey.Prompt]: buildPrompt(prompt) + }); + const computedScopes = includeReservedScopes ? withReservedScopes(scopes) : scopes?.join(" "); + if (computedScopes) { + urlSearchParameters.append(QueryKey.Scope, computedScopes); + } + if (loginHint) { + urlSearchParameters.append(QueryKey.LoginHint, loginHint); + } + if (directSignIn) { + urlSearchParameters.append(QueryKey.DirectSignIn, `${directSignIn.method}:${directSignIn.target}`); + } + for (const resource of resources ?? []) { + urlSearchParameters.append(QueryKey.Resource, resource); + } + if (firstScreen) { + urlSearchParameters.append(QueryKey.FirstScreen, firstScreen); + } else if (interactionMode) { + urlSearchParameters.append(QueryKey.InteractionMode, interactionMode); + } + if (identifier && identifier.length > 0) { + urlSearchParameters.append(QueryKey.Identifier, identifier.join(" ")); + } + if (oneTimeToken) { + urlSearchParameters.append(QueryKey.OneTimeToken, oneTimeToken); + } + if (extraParams) { + for (const [key, value] of Object.entries(extraParams)) { + urlSearchParameters.append(key, value); + } + } + return `${authorizationEndpoint}?${urlSearchParameters.toString()}`; + }; + + // node_modules/@logto/js/lib/core/sign-out.js + var generateSignOutUri = ({ endSessionEndpoint, clientId, postLogoutRedirectUri }) => { + const urlSearchParameters = new URLSearchParams({ [QueryKey.ClientId]: clientId }); + if (postLogoutRedirectUri) { + urlSearchParameters.append(QueryKey.PostLogoutRedirectUri, postLogoutRedirectUri); + } + return `${endSessionEndpoint}?${urlSearchParameters.toString()}`; + }; + + // node_modules/@logto/js/lib/core/user-info.js + var fetchUserInfo = async (userInfoEndpoint, accessToken, requester) => requester(userInfoEndpoint, { + headers: { Authorization: `Bearer ${accessToken}` } + }); + + // node_modules/@silverhand/essentials/lib/utilities/array.js + var deduplicate = (array) => [...new Set(array)]; + + // node_modules/@silverhand/essentials/lib/utilities/assertions.js + var notFalsy = (value) => Boolean(value); + + // node_modules/@silverhand/essentials/lib/utilities/conditional.js + var conditional = (exp) => notFalsy(exp) ? exp : void 0; + var conditionalString = (exp) => notFalsy(exp) ? String(exp) : ""; + + // node_modules/@silverhand/essentials/lib/utilities/function.js + var isPromise = (value) => value !== null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function"; + var trySafe = (exec, onError) => { + try { + const unwrapped = typeof exec === "function" ? exec() : exec; + return isPromise(unwrapped) ? ( + // eslint-disable-next-line promise/prefer-await-to-then + unwrapped.catch((error) => { + onError?.(error); + }) + ) : unwrapped; + } catch (error) { + onError?.(error); + } + }; + + // node_modules/@silverhand/essentials/lib/utilities/string.js + var replaceNonUrlSafeCharacters = (base64String) => base64String.replaceAll("+", "-").replaceAll("/", "_").replaceAll(/=+$/g, ""); + var restoreNonUrlSafeCharacters = (base64String) => base64String.replaceAll("-", "+").replaceAll("_", "/"); + var urlSafeBase64 = { + isSafe: (input) => /^[\w-]*$/.test(input), + encode: (rawString) => { + const encodedString = btoa(unescape(encodeURIComponent(rawString))); + return replaceNonUrlSafeCharacters(encodedString); + }, + decode: (encodedString) => { + const nonUrlSafeEncodedString = restoreNonUrlSafeCharacters(encodedString); + return decodeURIComponent(escape(atob(nonUrlSafeEncodedString))); + }, + replaceNonUrlSafeCharacters, + restoreNonUrlSafeCharacters + }; + + // node_modules/@silverhand/essentials/lib/utilities/url.js + var joinPath = (...segments) => { + const result = []; + for (const segment of segments.join("/").split("/")) { + if (!segment || segment === ".") { + continue; + } + if ([...segment].every((char) => char === ".")) { + result.pop(); + continue; + } + result.push(segment); + } + return "/" + result.join("/"); + }; + var appendPath = (baseUrl, ...pathnames) => new URL(joinPath(baseUrl.pathname, ...pathnames), baseUrl); + + // node_modules/@logto/js/lib/utils/arbitrary-object.js + var isArbitraryObject = (data) => typeof data === "object" && data !== null; + + // node_modules/@logto/js/lib/utils/errors.js + var logtoErrorCodes = Object.freeze({ + "id_token.invalid_iat": "Invalid issued at time in the ID token", + "id_token.invalid_token": "Invalid ID token", + "callback_uri_verification.redirect_uri_mismatched": "The callback URI mismatches the redirect URI.", + "callback_uri_verification.error_found": "Error found in the callback URI", + "callback_uri_verification.missing_state": "Missing state in the callback URI", + "callback_uri_verification.state_mismatched": "State mismatched in the callback URI", + "callback_uri_verification.missing_code": "Missing code in the callback URI", + crypto_subtle_unavailable: "Crypto.subtle is unavailable in insecure contexts (non-HTTPS).", + unexpected_response_error: "Unexpected response error from the server." + }); + var LogtoError = class extends Error { + constructor(code, data) { + super(logtoErrorCodes[code]); + this.code = code; + this.data = data; + this.name = "LogtoError"; + } + }; + var isLogtoRequestErrorJson = (data) => { + if (!isArbitraryObject(data)) { + return false; + } + return typeof data.code === "string" && typeof data.message === "string"; + }; + var LogtoRequestError = class extends Error { + constructor(code, message2, cause) { + super(message2); + this.code = code; + this.cause = cause; + this.name = "LogtoRequestError"; + } + }; + var OidcError = class { + constructor(error, errorDescription) { + this.error = error; + this.errorDescription = errorDescription; + this.name = "OidcError"; + } + }; + + // node_modules/@logto/js/lib/utils/callback-uri.js + var parseUriParameters = (uri) => { + const [, queryString = ""] = uri.split("?"); + return new URLSearchParams(queryString); + }; + var verifyAndParseCodeFromCallbackUri = (callbackUri, redirectUri, state) => { + if (!callbackUri.startsWith(redirectUri)) { + throw new LogtoError("callback_uri_verification.redirect_uri_mismatched"); + } + const uriParameters = parseUriParameters(callbackUri); + const error = conditional(uriParameters.get(QueryKey.Error)); + const errorDescription = conditional(uriParameters.get(QueryKey.ErrorDescription)); + if (error) { + throw new LogtoError("callback_uri_verification.error_found", new OidcError(error, errorDescription)); + } + const stateFromCallbackUri = uriParameters.get(QueryKey.State); + if (!stateFromCallbackUri) { + throw new LogtoError("callback_uri_verification.missing_state"); + } + if (stateFromCallbackUri !== state) { + throw new LogtoError("callback_uri_verification.state_mismatched"); + } + const code = uriParameters.get(QueryKey.Code); + if (!code) { + throw new LogtoError("callback_uri_verification.missing_code"); + } + return code; + }; + + // node_modules/@logto/js/lib/utils/id-token.js + function assertIdTokenClaims(data) { + if (!isArbitraryObject(data)) { + throw new TypeError("IdToken is expected to be an object"); + } + for (const key of ["iss", "sub", "aud"]) { + if (typeof data[key] !== "string") { + throw new TypeError(`At path: IdToken.${key}: expected a string`); + } + } + for (const key of ["exp", "iat"]) { + if (typeof data[key] !== "number") { + throw new TypeError(`At path: IdToken.${key}: expected a number`); + } + } + for (const key of ["at_hash", "name", "username", "picture", "email", "phone_number"]) { + if (data[key] === void 0) { + continue; + } + if (typeof data[key] !== "string" && data[key] !== null) { + throw new TypeError(`At path: IdToken.${key}: expected null or a string`); + } + } + for (const key of ["email_verified", "phone_number_verified"]) { + if (data[key] === void 0) { + continue; + } + if (typeof data[key] !== "boolean") { + throw new TypeError(`At path: IdToken.${key}: expected a boolean`); + } + } + } + var decodeIdToken = (token) => { + const { 1: encodedPayload } = token.split("."); + if (!encodedPayload) { + throw new LogtoError("id_token.invalid_token"); + } + const json = urlSafeBase64.decode(encodedPayload); + const idTokenClaims2 = JSON.parse(json); + assertIdTokenClaims(idTokenClaims2); + return idTokenClaims2; + }; + + // node_modules/@logto/js/lib/utils/access-token.js + function assertAccessTokenClaims(data) { + if (!isArbitraryObject(data)) { + throw new TypeError("AccessToken is expected to be an object"); + } + for (const key of ["jti", "iss", "sub", "aud", "client_id", "scope"]) { + if (data[key] === void 0) { + continue; + } + if (typeof data[key] !== "string" && data[key] !== null) { + throw new TypeError(`At path: AccessToken.${key}: expected null or a string`); + } + } + for (const key of ["exp", "iat"]) { + if (data[key] === void 0) { + continue; + } + if (typeof data[key] !== "number" && data[key] !== null) { + throw new TypeError(`At path: AccessToken.${key}: expected null or a number`); + } + } + } + var decodeAccessToken = (accessToken) => { + const { 1: encodedPayload } = accessToken.split("."); + if (!encodedPayload) { + return {}; + } + const json = urlSafeBase64.decode(encodedPayload); + const accessTokenClaims = JSON.parse(json); + assertAccessTokenClaims(accessTokenClaims); + return accessTokenClaims; + }; + + // node_modules/jose/dist/browser/runtime/webcrypto.js + var webcrypto_default = crypto; + var isCryptoKey = (key) => key instanceof CryptoKey; + + // node_modules/jose/dist/browser/lib/buffer_utils.js + var encoder = new TextEncoder(); + var decoder = new TextDecoder(); + var MAX_INT32 = 2 ** 32; + function concat(...buffers) { + const size = buffers.reduce((acc, { length }) => acc + length, 0); + const buf = new Uint8Array(size); + let i = 0; + for (const buffer of buffers) { + buf.set(buffer, i); + i += buffer.length; + } + return buf; + } + + // node_modules/jose/dist/browser/runtime/base64url.js + var decodeBase64 = (encoded) => { + const binary = atob(encoded); + const bytes = new Uint8Array(binary.length); + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i); + } + return bytes; + }; + var decode = (input) => { + let encoded = input; + if (encoded instanceof Uint8Array) { + encoded = decoder.decode(encoded); + } + encoded = encoded.replace(/-/g, "+").replace(/_/g, "/").replace(/\s/g, ""); + try { + return decodeBase64(encoded); + } catch { + throw new TypeError("The input to be decoded is not correctly encoded."); + } + }; + + // node_modules/jose/dist/browser/util/errors.js + var JOSEError = class extends Error { + constructor(message2, options) { + super(message2, options); + this.code = "ERR_JOSE_GENERIC"; + this.name = this.constructor.name; + Error.captureStackTrace?.(this, this.constructor); + } + }; + JOSEError.code = "ERR_JOSE_GENERIC"; + var JWTClaimValidationFailed = class extends JOSEError { + constructor(message2, payload, claim = "unspecified", reason = "unspecified") { + super(message2, { cause: { claim, reason, payload } }); + this.code = "ERR_JWT_CLAIM_VALIDATION_FAILED"; + this.claim = claim; + this.reason = reason; + this.payload = payload; + } + }; + JWTClaimValidationFailed.code = "ERR_JWT_CLAIM_VALIDATION_FAILED"; + var JWTExpired = class extends JOSEError { + constructor(message2, payload, claim = "unspecified", reason = "unspecified") { + super(message2, { cause: { claim, reason, payload } }); + this.code = "ERR_JWT_EXPIRED"; + this.claim = claim; + this.reason = reason; + this.payload = payload; + } + }; + JWTExpired.code = "ERR_JWT_EXPIRED"; + var JOSEAlgNotAllowed = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JOSE_ALG_NOT_ALLOWED"; + } + }; + JOSEAlgNotAllowed.code = "ERR_JOSE_ALG_NOT_ALLOWED"; + var JOSENotSupported = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JOSE_NOT_SUPPORTED"; + } + }; + JOSENotSupported.code = "ERR_JOSE_NOT_SUPPORTED"; + var JWEDecryptionFailed = class extends JOSEError { + constructor(message2 = "decryption operation failed", options) { + super(message2, options); + this.code = "ERR_JWE_DECRYPTION_FAILED"; + } + }; + JWEDecryptionFailed.code = "ERR_JWE_DECRYPTION_FAILED"; + var JWEInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWE_INVALID"; + } + }; + JWEInvalid.code = "ERR_JWE_INVALID"; + var JWSInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWS_INVALID"; + } + }; + JWSInvalid.code = "ERR_JWS_INVALID"; + var JWTInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWT_INVALID"; + } + }; + JWTInvalid.code = "ERR_JWT_INVALID"; + var JWKInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWK_INVALID"; + } + }; + JWKInvalid.code = "ERR_JWK_INVALID"; + var JWKSInvalid = class extends JOSEError { + constructor() { + super(...arguments); + this.code = "ERR_JWKS_INVALID"; + } + }; + JWKSInvalid.code = "ERR_JWKS_INVALID"; + var JWKSNoMatchingKey = class extends JOSEError { + constructor(message2 = "no applicable key found in the JSON Web Key Set", options) { + super(message2, options); + this.code = "ERR_JWKS_NO_MATCHING_KEY"; + } + }; + JWKSNoMatchingKey.code = "ERR_JWKS_NO_MATCHING_KEY"; + var JWKSMultipleMatchingKeys = class extends JOSEError { + constructor(message2 = "multiple matching keys found in the JSON Web Key Set", options) { + super(message2, options); + this.code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; + } + }; + JWKSMultipleMatchingKeys.code = "ERR_JWKS_MULTIPLE_MATCHING_KEYS"; + var JWKSTimeout = class extends JOSEError { + constructor(message2 = "request timed out", options) { + super(message2, options); + this.code = "ERR_JWKS_TIMEOUT"; + } + }; + JWKSTimeout.code = "ERR_JWKS_TIMEOUT"; + var JWSSignatureVerificationFailed = class extends JOSEError { + constructor(message2 = "signature verification failed", options) { + super(message2, options); + this.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; + } + }; + JWSSignatureVerificationFailed.code = "ERR_JWS_SIGNATURE_VERIFICATION_FAILED"; + + // node_modules/jose/dist/browser/lib/crypto_key.js + function unusable(name, prop = "algorithm.name") { + return new TypeError(`CryptoKey does not support this operation, its ${prop} must be ${name}`); + } + function isAlgorithm(algorithm, name) { + return algorithm.name === name; + } + function getHashLength(hash) { + return parseInt(hash.name.slice(4), 10); + } + function getNamedCurve(alg) { + switch (alg) { + case "ES256": + return "P-256"; + case "ES384": + return "P-384"; + case "ES512": + return "P-521"; + default: + throw new Error("unreachable"); + } + } + function checkUsage(key, usages) { + if (usages.length && !usages.some((expected) => key.usages.includes(expected))) { + let msg = "CryptoKey does not support this operation, its usages must include "; + if (usages.length > 2) { + const last = usages.pop(); + msg += `one of ${usages.join(", ")}, or ${last}.`; + } else if (usages.length === 2) { + msg += `one of ${usages[0]} or ${usages[1]}.`; + } else { + msg += `${usages[0]}.`; + } + throw new TypeError(msg); + } + } + function checkSigCryptoKey(key, alg, ...usages) { + switch (alg) { + case "HS256": + case "HS384": + case "HS512": { + if (!isAlgorithm(key.algorithm, "HMAC")) + throw unusable("HMAC"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "RS256": + case "RS384": + case "RS512": { + if (!isAlgorithm(key.algorithm, "RSASSA-PKCS1-v1_5")) + throw unusable("RSASSA-PKCS1-v1_5"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "PS256": + case "PS384": + case "PS512": { + if (!isAlgorithm(key.algorithm, "RSA-PSS")) + throw unusable("RSA-PSS"); + const expected = parseInt(alg.slice(2), 10); + const actual = getHashLength(key.algorithm.hash); + if (actual !== expected) + throw unusable(`SHA-${expected}`, "algorithm.hash"); + break; + } + case "EdDSA": { + if (key.algorithm.name !== "Ed25519" && key.algorithm.name !== "Ed448") { + throw unusable("Ed25519 or Ed448"); + } + break; + } + case "Ed25519": { + if (!isAlgorithm(key.algorithm, "Ed25519")) + throw unusable("Ed25519"); + break; + } + case "ES256": + case "ES384": + case "ES512": { + if (!isAlgorithm(key.algorithm, "ECDSA")) + throw unusable("ECDSA"); + const expected = getNamedCurve(alg); + const actual = key.algorithm.namedCurve; + if (actual !== expected) + throw unusable(expected, "algorithm.namedCurve"); + break; + } + default: + throw new TypeError("CryptoKey does not support this operation"); + } + checkUsage(key, usages); + } + + // node_modules/jose/dist/browser/lib/invalid_key_input.js + function message(msg, actual, ...types2) { + types2 = types2.filter(Boolean); + if (types2.length > 2) { + const last = types2.pop(); + msg += `one of type ${types2.join(", ")}, or ${last}.`; + } else if (types2.length === 2) { + msg += `one of type ${types2[0]} or ${types2[1]}.`; + } else { + msg += `of type ${types2[0]}.`; + } + if (actual == null) { + msg += ` Received ${actual}`; + } else if (typeof actual === "function" && actual.name) { + msg += ` Received function ${actual.name}`; + } else if (typeof actual === "object" && actual != null) { + if (actual.constructor?.name) { + msg += ` Received an instance of ${actual.constructor.name}`; + } + } + return msg; + } + var invalid_key_input_default = (actual, ...types2) => { + return message("Key must be ", actual, ...types2); + }; + function withAlg(alg, actual, ...types2) { + return message(`Key for the ${alg} algorithm must be `, actual, ...types2); + } + + // node_modules/jose/dist/browser/runtime/is_key_like.js + var is_key_like_default = (key) => { + if (isCryptoKey(key)) { + return true; + } + return key?.[Symbol.toStringTag] === "KeyObject"; + }; + var types = ["CryptoKey"]; + + // node_modules/jose/dist/browser/lib/is_disjoint.js + var isDisjoint = (...headers) => { + const sources = headers.filter(Boolean); + if (sources.length === 0 || sources.length === 1) { + return true; + } + let acc; + for (const header of sources) { + const parameters = Object.keys(header); + if (!acc || acc.size === 0) { + acc = new Set(parameters); + continue; + } + for (const parameter of parameters) { + if (acc.has(parameter)) { + return false; + } + acc.add(parameter); + } + } + return true; + }; + var is_disjoint_default = isDisjoint; + + // node_modules/jose/dist/browser/lib/is_object.js + function isObjectLike(value) { + return typeof value === "object" && value !== null; + } + function isObject4(input) { + if (!isObjectLike(input) || Object.prototype.toString.call(input) !== "[object Object]") { + return false; + } + if (Object.getPrototypeOf(input) === null) { + return true; + } + let proto = input; + while (Object.getPrototypeOf(proto) !== null) { + proto = Object.getPrototypeOf(proto); + } + return Object.getPrototypeOf(input) === proto; + } + + // node_modules/jose/dist/browser/runtime/check_key_length.js + var check_key_length_default = (alg, key) => { + if (alg.startsWith("RS") || alg.startsWith("PS")) { + const { modulusLength } = key.algorithm; + if (typeof modulusLength !== "number" || modulusLength < 2048) { + throw new TypeError(`${alg} requires key modulusLength to be 2048 bits or larger`); + } + } + }; + + // node_modules/jose/dist/browser/lib/is_jwk.js + function isJWK(key) { + return isObject4(key) && typeof key.kty === "string"; + } + function isPrivateJWK(key) { + return key.kty !== "oct" && typeof key.d === "string"; + } + function isPublicJWK(key) { + return key.kty !== "oct" && typeof key.d === "undefined"; + } + function isSecretJWK(key) { + return isJWK(key) && key.kty === "oct" && typeof key.k === "string"; + } + + // node_modules/jose/dist/browser/runtime/jwk_to_key.js + function subtleMapping(jwk) { + let algorithm; + let keyUsages; + switch (jwk.kty) { + case "RSA": { + switch (jwk.alg) { + case "PS256": + case "PS384": + case "PS512": + algorithm = { name: "RSA-PSS", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "RS256": + case "RS384": + case "RS512": + algorithm = { name: "RSASSA-PKCS1-v1_5", hash: `SHA-${jwk.alg.slice(-3)}` }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "RSA-OAEP": + case "RSA-OAEP-256": + case "RSA-OAEP-384": + case "RSA-OAEP-512": + algorithm = { + name: "RSA-OAEP", + hash: `SHA-${parseInt(jwk.alg.slice(-3), 10) || 1}` + }; + keyUsages = jwk.d ? ["decrypt", "unwrapKey"] : ["encrypt", "wrapKey"]; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "EC": { + switch (jwk.alg) { + case "ES256": + algorithm = { name: "ECDSA", namedCurve: "P-256" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ES384": + algorithm = { name: "ECDSA", namedCurve: "P-384" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ES512": + algorithm = { name: "ECDSA", namedCurve: "P-521" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": + algorithm = { name: "ECDH", namedCurve: jwk.crv }; + keyUsages = jwk.d ? ["deriveBits"] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + case "OKP": { + switch (jwk.alg) { + case "Ed25519": + algorithm = { name: "Ed25519" }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "EdDSA": + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ["sign"] : ["verify"]; + break; + case "ECDH-ES": + case "ECDH-ES+A128KW": + case "ECDH-ES+A192KW": + case "ECDH-ES+A256KW": + algorithm = { name: jwk.crv }; + keyUsages = jwk.d ? ["deriveBits"] : []; + break; + default: + throw new JOSENotSupported('Invalid or unsupported JWK "alg" (Algorithm) Parameter value'); + } + break; + } + default: + throw new JOSENotSupported('Invalid or unsupported JWK "kty" (Key Type) Parameter value'); + } + return { algorithm, keyUsages }; + } + var parse = async (jwk) => { + if (!jwk.alg) { + throw new TypeError('"alg" argument is required when "jwk.alg" is not present'); + } + const { algorithm, keyUsages } = subtleMapping(jwk); + const rest = [ + algorithm, + jwk.ext ?? false, + jwk.key_ops ?? keyUsages + ]; + const keyData = { ...jwk }; + delete keyData.alg; + delete keyData.use; + return webcrypto_default.subtle.importKey("jwk", keyData, ...rest); + }; + var jwk_to_key_default = parse; + + // node_modules/jose/dist/browser/runtime/normalize_key.js + var exportKeyValue = (k) => decode(k); + var privCache; + var pubCache; + var isKeyObject = (key) => { + return key?.[Symbol.toStringTag] === "KeyObject"; + }; + var importAndCache = async (cache2, key, jwk, alg, freeze = false) => { + let cached = cache2.get(key); + if (cached?.[alg]) { + return cached[alg]; + } + const cryptoKey = await jwk_to_key_default({ ...jwk, alg }); + if (freeze) + Object.freeze(key); + if (!cached) { + cache2.set(key, { [alg]: cryptoKey }); + } else { + cached[alg] = cryptoKey; + } + return cryptoKey; + }; + var normalizePublicKey = (key, alg) => { + if (isKeyObject(key)) { + let jwk = key.export({ format: "jwk" }); + delete jwk.d; + delete jwk.dp; + delete jwk.dq; + delete jwk.p; + delete jwk.q; + delete jwk.qi; + if (jwk.k) { + return exportKeyValue(jwk.k); + } + pubCache || (pubCache = /* @__PURE__ */ new WeakMap()); + return importAndCache(pubCache, key, jwk, alg); + } + if (isJWK(key)) { + if (key.k) + return decode(key.k); + pubCache || (pubCache = /* @__PURE__ */ new WeakMap()); + const cryptoKey = importAndCache(pubCache, key, key, alg, true); + return cryptoKey; + } + return key; + }; + var normalizePrivateKey = (key, alg) => { + if (isKeyObject(key)) { + let jwk = key.export({ format: "jwk" }); + if (jwk.k) { + return exportKeyValue(jwk.k); + } + privCache || (privCache = /* @__PURE__ */ new WeakMap()); + return importAndCache(privCache, key, jwk, alg); + } + if (isJWK(key)) { + if (key.k) + return decode(key.k); + privCache || (privCache = /* @__PURE__ */ new WeakMap()); + const cryptoKey = importAndCache(privCache, key, key, alg, true); + return cryptoKey; + } + return key; + }; + var normalize_key_default = { normalizePublicKey, normalizePrivateKey }; + + // node_modules/jose/dist/browser/key/import.js + async function importJWK(jwk, alg) { + if (!isObject4(jwk)) { + throw new TypeError("JWK must be an object"); + } + alg || (alg = jwk.alg); + switch (jwk.kty) { + case "oct": + if (typeof jwk.k !== "string" || !jwk.k) { + throw new TypeError('missing "k" (Key Value) Parameter value'); + } + return decode(jwk.k); + case "RSA": + if ("oth" in jwk && jwk.oth !== void 0) { + throw new JOSENotSupported('RSA JWK "oth" (Other Primes Info) Parameter value is not supported'); + } + case "EC": + case "OKP": + return jwk_to_key_default({ ...jwk, alg }); + default: + throw new JOSENotSupported('Unsupported "kty" (Key Type) Parameter value'); + } + } + + // node_modules/jose/dist/browser/lib/check_key_type.js + var tag = (key) => key?.[Symbol.toStringTag]; + var jwkMatchesOp = (alg, key, usage) => { + if (key.use !== void 0 && key.use !== "sig") { + throw new TypeError("Invalid key for this operation, when present its use must be sig"); + } + if (key.key_ops !== void 0 && key.key_ops.includes?.(usage) !== true) { + throw new TypeError(`Invalid key for this operation, when present its key_ops must include ${usage}`); + } + if (key.alg !== void 0 && key.alg !== alg) { + throw new TypeError(`Invalid key for this operation, when present its alg must be ${alg}`); + } + return true; + }; + var symmetricTypeCheck = (alg, key, usage, allowJwk) => { + if (key instanceof Uint8Array) + return; + if (allowJwk && isJWK(key)) { + if (isSecretJWK(key) && jwkMatchesOp(alg, key, usage)) + return; + throw new TypeError(`JSON Web Key for symmetric algorithms must have JWK "kty" (Key Type) equal to "oct" and the JWK "k" (Key Value) present`); + } + if (!is_key_like_default(key)) { + throw new TypeError(withAlg(alg, key, ...types, "Uint8Array", allowJwk ? "JSON Web Key" : null)); + } + if (key.type !== "secret") { + throw new TypeError(`${tag(key)} instances for symmetric algorithms must be of type "secret"`); + } + }; + var asymmetricTypeCheck = (alg, key, usage, allowJwk) => { + if (allowJwk && isJWK(key)) { + switch (usage) { + case "sign": + if (isPrivateJWK(key) && jwkMatchesOp(alg, key, usage)) + return; + throw new TypeError(`JSON Web Key for this operation be a private JWK`); + case "verify": + if (isPublicJWK(key) && jwkMatchesOp(alg, key, usage)) + return; + throw new TypeError(`JSON Web Key for this operation be a public JWK`); + } + } + if (!is_key_like_default(key)) { + throw new TypeError(withAlg(alg, key, ...types, allowJwk ? "JSON Web Key" : null)); + } + if (key.type === "secret") { + throw new TypeError(`${tag(key)} instances for asymmetric algorithms must not be of type "secret"`); + } + if (usage === "sign" && key.type === "public") { + throw new TypeError(`${tag(key)} instances for asymmetric algorithm signing must be of type "private"`); + } + if (usage === "decrypt" && key.type === "public") { + throw new TypeError(`${tag(key)} instances for asymmetric algorithm decryption must be of type "private"`); + } + if (key.algorithm && usage === "verify" && key.type === "private") { + throw new TypeError(`${tag(key)} instances for asymmetric algorithm verifying must be of type "public"`); + } + if (key.algorithm && usage === "encrypt" && key.type === "private") { + throw new TypeError(`${tag(key)} instances for asymmetric algorithm encryption must be of type "public"`); + } + }; + function checkKeyType(allowJwk, alg, key, usage) { + const symmetric = alg.startsWith("HS") || alg === "dir" || alg.startsWith("PBES2") || /^A\d{3}(?:GCM)?KW$/.test(alg); + if (symmetric) { + symmetricTypeCheck(alg, key, usage, allowJwk); + } else { + asymmetricTypeCheck(alg, key, usage, allowJwk); + } + } + var check_key_type_default = checkKeyType.bind(void 0, false); + var checkKeyTypeWithJwk = checkKeyType.bind(void 0, true); + + // node_modules/jose/dist/browser/lib/validate_crit.js + function validateCrit(Err, recognizedDefault, recognizedOption, protectedHeader, joseHeader) { + if (joseHeader.crit !== void 0 && protectedHeader?.crit === void 0) { + throw new Err('"crit" (Critical) Header Parameter MUST be integrity protected'); + } + if (!protectedHeader || protectedHeader.crit === void 0) { + return /* @__PURE__ */ new Set(); + } + if (!Array.isArray(protectedHeader.crit) || protectedHeader.crit.length === 0 || protectedHeader.crit.some((input) => typeof input !== "string" || input.length === 0)) { + throw new Err('"crit" (Critical) Header Parameter MUST be an array of non-empty strings when present'); + } + let recognized; + if (recognizedOption !== void 0) { + recognized = new Map([...Object.entries(recognizedOption), ...recognizedDefault.entries()]); + } else { + recognized = recognizedDefault; + } + for (const parameter of protectedHeader.crit) { + if (!recognized.has(parameter)) { + throw new JOSENotSupported(`Extension Header Parameter "${parameter}" is not recognized`); + } + if (joseHeader[parameter] === void 0) { + throw new Err(`Extension Header Parameter "${parameter}" is missing`); + } + if (recognized.get(parameter) && protectedHeader[parameter] === void 0) { + throw new Err(`Extension Header Parameter "${parameter}" MUST be integrity protected`); + } + } + return new Set(protectedHeader.crit); + } + var validate_crit_default = validateCrit; + + // node_modules/jose/dist/browser/lib/validate_algorithms.js + var validateAlgorithms = (option, algorithms) => { + if (algorithms !== void 0 && (!Array.isArray(algorithms) || algorithms.some((s) => typeof s !== "string"))) { + throw new TypeError(`"${option}" option must be an array of strings`); + } + if (!algorithms) { + return void 0; + } + return new Set(algorithms); + }; + var validate_algorithms_default = validateAlgorithms; + + // node_modules/jose/dist/browser/runtime/subtle_dsa.js + function subtleDsa(alg, algorithm) { + const hash = `SHA-${alg.slice(-3)}`; + switch (alg) { + case "HS256": + case "HS384": + case "HS512": + return { hash, name: "HMAC" }; + case "PS256": + case "PS384": + case "PS512": + return { hash, name: "RSA-PSS", saltLength: alg.slice(-3) >> 3 }; + case "RS256": + case "RS384": + case "RS512": + return { hash, name: "RSASSA-PKCS1-v1_5" }; + case "ES256": + case "ES384": + case "ES512": + return { hash, name: "ECDSA", namedCurve: algorithm.namedCurve }; + case "Ed25519": + return { name: "Ed25519" }; + case "EdDSA": + return { name: algorithm.name }; + default: + throw new JOSENotSupported(`alg ${alg} is not supported either by JOSE or your javascript runtime`); + } + } + + // node_modules/jose/dist/browser/runtime/get_sign_verify_key.js + async function getCryptoKey(alg, key, usage) { + if (usage === "sign") { + key = await normalize_key_default.normalizePrivateKey(key, alg); + } + if (usage === "verify") { + key = await normalize_key_default.normalizePublicKey(key, alg); + } + if (isCryptoKey(key)) { + checkSigCryptoKey(key, alg, usage); + return key; + } + if (key instanceof Uint8Array) { + if (!alg.startsWith("HS")) { + throw new TypeError(invalid_key_input_default(key, ...types)); + } + return webcrypto_default.subtle.importKey("raw", key, { hash: `SHA-${alg.slice(-3)}`, name: "HMAC" }, false, [usage]); + } + throw new TypeError(invalid_key_input_default(key, ...types, "Uint8Array", "JSON Web Key")); + } + + // node_modules/jose/dist/browser/runtime/verify.js + var verify = async (alg, key, signature, data) => { + const cryptoKey = await getCryptoKey(alg, key, "verify"); + check_key_length_default(alg, cryptoKey); + const algorithm = subtleDsa(alg, cryptoKey.algorithm); + try { + return await webcrypto_default.subtle.verify(algorithm, cryptoKey, signature, data); + } catch { + return false; + } + }; + var verify_default = verify; + + // node_modules/jose/dist/browser/jws/flattened/verify.js + async function flattenedVerify(jws, key, options) { + if (!isObject4(jws)) { + throw new JWSInvalid("Flattened JWS must be an object"); + } + if (jws.protected === void 0 && jws.header === void 0) { + throw new JWSInvalid('Flattened JWS must have either of the "protected" or "header" members'); + } + if (jws.protected !== void 0 && typeof jws.protected !== "string") { + throw new JWSInvalid("JWS Protected Header incorrect type"); + } + if (jws.payload === void 0) { + throw new JWSInvalid("JWS Payload missing"); + } + if (typeof jws.signature !== "string") { + throw new JWSInvalid("JWS Signature missing or incorrect type"); + } + if (jws.header !== void 0 && !isObject4(jws.header)) { + throw new JWSInvalid("JWS Unprotected Header incorrect type"); + } + let parsedProt = {}; + if (jws.protected) { + try { + const protectedHeader = decode(jws.protected); + parsedProt = JSON.parse(decoder.decode(protectedHeader)); + } catch { + throw new JWSInvalid("JWS Protected Header is invalid"); + } + } + if (!is_disjoint_default(parsedProt, jws.header)) { + throw new JWSInvalid("JWS Protected and JWS Unprotected Header Parameter names must be disjoint"); + } + const joseHeader = { + ...parsedProt, + ...jws.header + }; + const extensions = validate_crit_default(JWSInvalid, /* @__PURE__ */ new Map([["b64", true]]), options?.crit, parsedProt, joseHeader); + let b64 = true; + if (extensions.has("b64")) { + b64 = parsedProt.b64; + if (typeof b64 !== "boolean") { + throw new JWSInvalid('The "b64" (base64url-encode payload) Header Parameter must be a boolean'); + } + } + const { alg } = joseHeader; + if (typeof alg !== "string" || !alg) { + throw new JWSInvalid('JWS "alg" (Algorithm) Header Parameter missing or invalid'); + } + const algorithms = options && validate_algorithms_default("algorithms", options.algorithms); + if (algorithms && !algorithms.has(alg)) { + throw new JOSEAlgNotAllowed('"alg" (Algorithm) Header Parameter value not allowed'); + } + if (b64) { + if (typeof jws.payload !== "string") { + throw new JWSInvalid("JWS Payload must be a string"); + } + } else if (typeof jws.payload !== "string" && !(jws.payload instanceof Uint8Array)) { + throw new JWSInvalid("JWS Payload must be a string or an Uint8Array instance"); + } + let resolvedKey = false; + if (typeof key === "function") { + key = await key(parsedProt, jws); + resolvedKey = true; + checkKeyTypeWithJwk(alg, key, "verify"); + if (isJWK(key)) { + key = await importJWK(key, alg); + } + } else { + checkKeyTypeWithJwk(alg, key, "verify"); + } + const data = concat(encoder.encode(jws.protected ?? ""), encoder.encode("."), typeof jws.payload === "string" ? encoder.encode(jws.payload) : jws.payload); + let signature; + try { + signature = decode(jws.signature); + } catch { + throw new JWSInvalid("Failed to base64url decode the signature"); + } + const verified = await verify_default(alg, key, signature, data); + if (!verified) { + throw new JWSSignatureVerificationFailed(); + } + let payload; + if (b64) { + try { + payload = decode(jws.payload); + } catch { + throw new JWSInvalid("Failed to base64url decode the payload"); + } + } else if (typeof jws.payload === "string") { + payload = encoder.encode(jws.payload); + } else { + payload = jws.payload; + } + const result = { payload }; + if (jws.protected !== void 0) { + result.protectedHeader = parsedProt; + } + if (jws.header !== void 0) { + result.unprotectedHeader = jws.header; + } + if (resolvedKey) { + return { ...result, key }; + } + return result; + } + + // node_modules/jose/dist/browser/jws/compact/verify.js + async function compactVerify(jws, key, options) { + if (jws instanceof Uint8Array) { + jws = decoder.decode(jws); + } + if (typeof jws !== "string") { + throw new JWSInvalid("Compact JWS must be a string or Uint8Array"); + } + const { 0: protectedHeader, 1: payload, 2: signature, length } = jws.split("."); + if (length !== 3) { + throw new JWSInvalid("Invalid Compact JWS"); + } + const verified = await flattenedVerify({ payload, protected: protectedHeader, signature }, key, options); + const result = { payload: verified.payload, protectedHeader: verified.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: verified.key }; + } + return result; + } + + // node_modules/jose/dist/browser/lib/epoch.js + var epoch_default = (date) => Math.floor(date.getTime() / 1e3); + + // node_modules/jose/dist/browser/lib/secs.js + var minute = 60; + var hour = minute * 60; + var day = hour * 24; + var week = day * 7; + var year = day * 365.25; + var REGEX = /^(\+|\-)? ?(\d+|\d+\.\d+) ?(seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)(?: (ago|from now))?$/i; + var secs_default = (str) => { + const matched = REGEX.exec(str); + if (!matched || matched[4] && matched[1]) { + throw new TypeError("Invalid time period format"); + } + const value = parseFloat(matched[2]); + const unit = matched[3].toLowerCase(); + let numericDate; + switch (unit) { + case "sec": + case "secs": + case "second": + case "seconds": + case "s": + numericDate = Math.round(value); + break; + case "minute": + case "minutes": + case "min": + case "mins": + case "m": + numericDate = Math.round(value * minute); + break; + case "hour": + case "hours": + case "hr": + case "hrs": + case "h": + numericDate = Math.round(value * hour); + break; + case "day": + case "days": + case "d": + numericDate = Math.round(value * day); + break; + case "week": + case "weeks": + case "w": + numericDate = Math.round(value * week); + break; + default: + numericDate = Math.round(value * year); + break; + } + if (matched[1] === "-" || matched[4] === "ago") { + return -numericDate; + } + return numericDate; + }; + + // node_modules/jose/dist/browser/lib/jwt_claims_set.js + var normalizeTyp = (value) => value.toLowerCase().replace(/^application\//, ""); + var checkAudiencePresence = (audPayload, audOption) => { + if (typeof audPayload === "string") { + return audOption.includes(audPayload); + } + if (Array.isArray(audPayload)) { + return audOption.some(Set.prototype.has.bind(new Set(audPayload))); + } + return false; + }; + var jwt_claims_set_default = (protectedHeader, encodedPayload, options = {}) => { + let payload; + try { + payload = JSON.parse(decoder.decode(encodedPayload)); + } catch { + } + if (!isObject4(payload)) { + throw new JWTInvalid("JWT Claims Set must be a top-level JSON object"); + } + const { typ } = options; + if (typ && (typeof protectedHeader.typ !== "string" || normalizeTyp(protectedHeader.typ) !== normalizeTyp(typ))) { + throw new JWTClaimValidationFailed('unexpected "typ" JWT header value', payload, "typ", "check_failed"); + } + const { requiredClaims = [], issuer, subject, audience, maxTokenAge } = options; + const presenceCheck = [...requiredClaims]; + if (maxTokenAge !== void 0) + presenceCheck.push("iat"); + if (audience !== void 0) + presenceCheck.push("aud"); + if (subject !== void 0) + presenceCheck.push("sub"); + if (issuer !== void 0) + presenceCheck.push("iss"); + for (const claim of new Set(presenceCheck.reverse())) { + if (!(claim in payload)) { + throw new JWTClaimValidationFailed(`missing required "${claim}" claim`, payload, claim, "missing"); + } + } + if (issuer && !(Array.isArray(issuer) ? issuer : [issuer]).includes(payload.iss)) { + throw new JWTClaimValidationFailed('unexpected "iss" claim value', payload, "iss", "check_failed"); + } + if (subject && payload.sub !== subject) { + throw new JWTClaimValidationFailed('unexpected "sub" claim value', payload, "sub", "check_failed"); + } + if (audience && !checkAudiencePresence(payload.aud, typeof audience === "string" ? [audience] : audience)) { + throw new JWTClaimValidationFailed('unexpected "aud" claim value', payload, "aud", "check_failed"); + } + let tolerance; + switch (typeof options.clockTolerance) { + case "string": + tolerance = secs_default(options.clockTolerance); + break; + case "number": + tolerance = options.clockTolerance; + break; + case "undefined": + tolerance = 0; + break; + default: + throw new TypeError("Invalid clockTolerance option type"); + } + const { currentDate } = options; + const now = epoch_default(currentDate || /* @__PURE__ */ new Date()); + if ((payload.iat !== void 0 || maxTokenAge) && typeof payload.iat !== "number") { + throw new JWTClaimValidationFailed('"iat" claim must be a number', payload, "iat", "invalid"); + } + if (payload.nbf !== void 0) { + if (typeof payload.nbf !== "number") { + throw new JWTClaimValidationFailed('"nbf" claim must be a number', payload, "nbf", "invalid"); + } + if (payload.nbf > now + tolerance) { + throw new JWTClaimValidationFailed('"nbf" claim timestamp check failed', payload, "nbf", "check_failed"); + } + } + if (payload.exp !== void 0) { + if (typeof payload.exp !== "number") { + throw new JWTClaimValidationFailed('"exp" claim must be a number', payload, "exp", "invalid"); + } + if (payload.exp <= now - tolerance) { + throw new JWTExpired('"exp" claim timestamp check failed', payload, "exp", "check_failed"); + } + } + if (maxTokenAge) { + const age = now - payload.iat; + const max = typeof maxTokenAge === "number" ? maxTokenAge : secs_default(maxTokenAge); + if (age - tolerance > max) { + throw new JWTExpired('"iat" claim timestamp check failed (too far in the past)', payload, "iat", "check_failed"); + } + if (age < 0 - tolerance) { + throw new JWTClaimValidationFailed('"iat" claim timestamp check failed (it should be in the past)', payload, "iat", "check_failed"); + } + } + return payload; + }; + + // node_modules/jose/dist/browser/jwt/verify.js + async function jwtVerify(jwt, key, options) { + const verified = await compactVerify(jwt, key, options); + if (verified.protectedHeader.crit?.includes("b64") && verified.protectedHeader.b64 === false) { + throw new JWTInvalid("JWTs MUST NOT use unencoded payload"); + } + const payload = jwt_claims_set_default(verified.protectedHeader, verified.payload, options); + const result = { payload, protectedHeader: verified.protectedHeader }; + if (typeof key === "function") { + return { ...result, key: verified.key }; + } + return result; + } + + // node_modules/jose/dist/browser/jwks/local.js + function getKtyFromAlg(alg) { + switch (typeof alg === "string" && alg.slice(0, 2)) { + case "RS": + case "PS": + return "RSA"; + case "ES": + return "EC"; + case "Ed": + return "OKP"; + default: + throw new JOSENotSupported('Unsupported "alg" value for a JSON Web Key Set'); + } + } + function isJWKSLike(jwks) { + return jwks && typeof jwks === "object" && Array.isArray(jwks.keys) && jwks.keys.every(isJWKLike); + } + function isJWKLike(key) { + return isObject4(key); + } + function clone(obj) { + if (typeof structuredClone === "function") { + return structuredClone(obj); + } + return JSON.parse(JSON.stringify(obj)); + } + var LocalJWKSet = class { + constructor(jwks) { + this._cached = /* @__PURE__ */ new WeakMap(); + if (!isJWKSLike(jwks)) { + throw new JWKSInvalid("JSON Web Key Set malformed"); + } + this._jwks = clone(jwks); + } + async getKey(protectedHeader, token) { + const { alg, kid } = { ...protectedHeader, ...token?.header }; + const kty = getKtyFromAlg(alg); + const candidates = this._jwks.keys.filter((jwk2) => { + let candidate = kty === jwk2.kty; + if (candidate && typeof kid === "string") { + candidate = kid === jwk2.kid; + } + if (candidate && typeof jwk2.alg === "string") { + candidate = alg === jwk2.alg; + } + if (candidate && typeof jwk2.use === "string") { + candidate = jwk2.use === "sig"; + } + if (candidate && Array.isArray(jwk2.key_ops)) { + candidate = jwk2.key_ops.includes("verify"); + } + if (candidate) { + switch (alg) { + case "ES256": + candidate = jwk2.crv === "P-256"; + break; + case "ES256K": + candidate = jwk2.crv === "secp256k1"; + break; + case "ES384": + candidate = jwk2.crv === "P-384"; + break; + case "ES512": + candidate = jwk2.crv === "P-521"; + break; + case "Ed25519": + candidate = jwk2.crv === "Ed25519"; + break; + case "EdDSA": + candidate = jwk2.crv === "Ed25519" || jwk2.crv === "Ed448"; + break; + } + } + return candidate; + }); + const { 0: jwk, length } = candidates; + if (length === 0) { + throw new JWKSNoMatchingKey(); + } + if (length !== 1) { + const error = new JWKSMultipleMatchingKeys(); + const { _cached } = this; + error[Symbol.asyncIterator] = async function* () { + for (const jwk2 of candidates) { + try { + yield await importWithAlgCache(_cached, jwk2, alg); + } catch { + } + } + }; + throw error; + } + return importWithAlgCache(this._cached, jwk, alg); + } + }; + async function importWithAlgCache(cache2, jwk, alg) { + const cached = cache2.get(jwk) || cache2.set(jwk, {}).get(jwk); + if (cached[alg] === void 0) { + const key = await importJWK({ ...jwk, ext: true }, alg); + if (key instanceof Uint8Array || key.type !== "public") { + throw new JWKSInvalid("JSON Web Key Set members must be public keys"); + } + cached[alg] = key; + } + return cached[alg]; + } + function createLocalJWKSet(jwks) { + const set = new LocalJWKSet(jwks); + const localJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token); + Object.defineProperties(localJWKSet, { + jwks: { + value: () => clone(set._jwks), + enumerable: true, + configurable: false, + writable: false + } + }); + return localJWKSet; + } + + // node_modules/jose/dist/browser/runtime/fetch_jwks.js + var fetchJwks = async (url, timeout, options) => { + let controller; + let id; + let timedOut = false; + if (typeof AbortController === "function") { + controller = new AbortController(); + id = setTimeout(() => { + timedOut = true; + controller.abort(); + }, timeout); + } + const response = await fetch(url.href, { + signal: controller ? controller.signal : void 0, + redirect: "manual", + headers: options.headers + }).catch((err) => { + if (timedOut) + throw new JWKSTimeout(); + throw err; + }); + if (id !== void 0) + clearTimeout(id); + if (response.status !== 200) { + throw new JOSEError("Expected 200 OK from the JSON Web Key Set HTTP response"); + } + try { + return await response.json(); + } catch { + throw new JOSEError("Failed to parse the JSON Web Key Set HTTP response as JSON"); + } + }; + var fetch_jwks_default = fetchJwks; + + // node_modules/jose/dist/browser/jwks/remote.js + function isCloudflareWorkers() { + return typeof WebSocketPair !== "undefined" || typeof navigator !== "undefined" && navigator.userAgent === "Cloudflare-Workers" || typeof EdgeRuntime !== "undefined" && EdgeRuntime === "vercel"; + } + var USER_AGENT; + if (typeof navigator === "undefined" || !navigator.userAgent?.startsWith?.("Mozilla/5.0 ")) { + const NAME = "jose"; + const VERSION = "v5.10.0"; + USER_AGENT = `${NAME}/${VERSION}`; + } + var jwksCache = /* @__PURE__ */ Symbol(); + function isFreshJwksCache(input, cacheMaxAge) { + if (typeof input !== "object" || input === null) { + return false; + } + if (!("uat" in input) || typeof input.uat !== "number" || Date.now() - input.uat >= cacheMaxAge) { + return false; + } + if (!("jwks" in input) || !isObject4(input.jwks) || !Array.isArray(input.jwks.keys) || !Array.prototype.every.call(input.jwks.keys, isObject4)) { + return false; + } + return true; + } + var RemoteJWKSet = class { + constructor(url, options) { + if (!(url instanceof URL)) { + throw new TypeError("url must be an instance of URL"); + } + this._url = new URL(url.href); + this._options = { agent: options?.agent, headers: options?.headers }; + this._timeoutDuration = typeof options?.timeoutDuration === "number" ? options?.timeoutDuration : 5e3; + this._cooldownDuration = typeof options?.cooldownDuration === "number" ? options?.cooldownDuration : 3e4; + this._cacheMaxAge = typeof options?.cacheMaxAge === "number" ? options?.cacheMaxAge : 6e5; + if (options?.[jwksCache] !== void 0) { + this._cache = options?.[jwksCache]; + if (isFreshJwksCache(options?.[jwksCache], this._cacheMaxAge)) { + this._jwksTimestamp = this._cache.uat; + this._local = createLocalJWKSet(this._cache.jwks); + } + } + } + coolingDown() { + return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cooldownDuration : false; + } + fresh() { + return typeof this._jwksTimestamp === "number" ? Date.now() < this._jwksTimestamp + this._cacheMaxAge : false; + } + async getKey(protectedHeader, token) { + if (!this._local || !this.fresh()) { + await this.reload(); + } + try { + return await this._local(protectedHeader, token); + } catch (err) { + if (err instanceof JWKSNoMatchingKey) { + if (this.coolingDown() === false) { + await this.reload(); + return this._local(protectedHeader, token); + } + } + throw err; + } + } + async reload() { + if (this._pendingFetch && isCloudflareWorkers()) { + this._pendingFetch = void 0; + } + const headers = new Headers(this._options.headers); + if (USER_AGENT && !headers.has("User-Agent")) { + headers.set("User-Agent", USER_AGENT); + this._options.headers = Object.fromEntries(headers.entries()); + } + this._pendingFetch || (this._pendingFetch = fetch_jwks_default(this._url, this._timeoutDuration, this._options).then((json) => { + this._local = createLocalJWKSet(json); + if (this._cache) { + this._cache.uat = Date.now(); + this._cache.jwks = json; + } + this._jwksTimestamp = Date.now(); + this._pendingFetch = void 0; + }).catch((err) => { + this._pendingFetch = void 0; + throw err; + })); + await this._pendingFetch; + } + }; + function createRemoteJWKSet(url, options) { + const set = new RemoteJWKSet(url, options); + const remoteJWKSet = async (protectedHeader, token) => set.getKey(protectedHeader, token); + Object.defineProperties(remoteJWKSet, { + coolingDown: { + get: () => set.coolingDown(), + enumerable: true, + configurable: false + }, + fresh: { + get: () => set.fresh(), + enumerable: true, + configurable: false + }, + reload: { + value: () => set.reload(), + enumerable: true, + configurable: false, + writable: false + }, + reloading: { + get: () => !!set._pendingFetch, + enumerable: true, + configurable: false + }, + jwks: { + value: () => set._local?.jwks(), + enumerable: true, + configurable: false, + writable: false + } + }); + return remoteJWKSet; + } + + // node_modules/@logto/client/lib/adapter/defaults.js + var defaultClockTolerance = 300; + var verifyIdToken = async (idToken, clientId, issuer, jwks, clockTolerance = defaultClockTolerance) => { + const result = await jwtVerify(idToken, jwks, { audience: clientId, issuer, clockTolerance }); + if (Math.abs((result.payload.iat ?? 0) - Date.now() / 1e3) > clockTolerance) { + throw new LogtoError("id_token.invalid_iat"); + } + }; + var DefaultJwtVerifier = class { + constructor(client, clockTolerance = defaultClockTolerance) { + this.client = client; + this.clockTolerance = clockTolerance; + } + async verifyIdToken(idToken) { + const { appId } = this.client.logtoConfig; + const { issuer, jwksUri } = await this.client.getOidcConfig(); + this.getJwtVerifyGetKey ||= createRemoteJWKSet(new URL(jwksUri)); + await verifyIdToken(idToken, appId, issuer, this.getJwtVerifyGetKey, this.clockTolerance); + } + }; + + // node_modules/@logto/client/lib/adapter/types.js + var PersistKey; + (function(PersistKey2) { + PersistKey2["IdToken"] = "idToken"; + PersistKey2["RefreshToken"] = "refreshToken"; + PersistKey2["AccessToken"] = "accessToken"; + PersistKey2["SignInSession"] = "signInSession"; + })(PersistKey || (PersistKey = {})); + var CacheKey; + (function(CacheKey2) { + CacheKey2["OpenidConfig"] = "openidConfiguration"; + CacheKey2["Jwks"] = "jwks"; + })(CacheKey || (CacheKey = {})); + + // node_modules/@logto/client/lib/adapter/index.js + var ClientAdapterInstance = class { + /* END OF IMPLEMENTATION */ + constructor(adapter) { + Object.assign(this, adapter); + } + async setStorageItem(key, value) { + if (!value) { + await this.storage.removeItem(key); + return; + } + await this.storage.setItem(key, value); + } + /** + * Try to get the string value from the cache and parse as JSON. + * Return the parsed value if it is an object, return `undefined` otherwise. + * + * @param key The cache key to get value from. + */ + async getCachedObject(key) { + const cached = await trySafe(async () => { + const data = await this.unstable_cache?.getItem(key); + return conditional(data && JSON.parse(data)); + }); + if (cached && typeof cached === "object") { + return cached; + } + } + /** + * Try to get the value from the cache first, if it doesn't exist in cache, + * run the getter function and store the result into cache. + * + * @param key The cache key to get value from. + */ + async getWithCache(key, getter) { + const cached = await this.getCachedObject(key); + if (cached) { + return cached; + } + const result = await getter(); + await this.unstable_cache?.setItem(key, JSON.stringify(result)); + return result; + } + }; + + // node_modules/@logto/client/lib/errors.js + var logtoClientErrorCodes = Object.freeze({ + "sign_in_session.invalid": "Invalid sign-in session.", + "sign_in_session.not_found": "Sign-in session not found.", + not_authenticated: "Not authenticated.", + fetch_user_info_failed: "Unable to fetch user info. The access token may be invalid.", + user_cancelled: "The user cancelled the action.", + missing_scope_organizations: `The \`${UserScope.Organizations}\` scope is required` + }); + var LogtoClientError = class extends Error { + constructor(code, data) { + super(logtoClientErrorCodes[code]); + this.name = "LogtoClientError"; + this.code = code; + this.data = data; + } + }; + + // node_modules/@logto/client/lib/types/index.js + var normalizeLogtoConfig = (config) => { + const { prompt = Prompt.Consent, scopes = [], resources, ...rest } = config; + const includeReservedScopes = config.includeReservedScopes ?? true; + return { + ...rest, + prompt, + scopes: includeReservedScopes ? withReservedScopes(scopes).split(" ") : scopes, + resources: scopes.includes(UserScope.Organizations) ? deduplicate([...resources ?? [], ReservedResource.Organization]) : resources, + includeReservedScopes + }; + }; + var isLogtoSignInSessionItem = (data) => { + if (!isArbitraryObject(data)) { + return false; + } + return ["redirectUri", "codeVerifier", "state"].every((key) => typeof data[key] === "string"); + }; + var isLogtoAccessTokenMap = (data) => { + if (!isArbitraryObject(data)) { + return false; + } + return Object.values(data).every((value) => { + if (!isArbitraryObject(value)) { + return false; + } + return typeof value.token === "string" && typeof value.scope === "string" && typeof value.expiresAt === "number"; + }); + }; + + // node_modules/@logto/client/lib/utils/index.js + var buildAccessTokenKey = (resource = "", organizationId, scopes = []) => `${scopes.slice().sort().join(" ")}@${resource}${conditionalString(organizationId && `#${organizationId}`)}`; + var getDiscoveryEndpoint = (endpoint) => appendPath(new URL(endpoint), discoveryPath).toString(); + + // node_modules/@logto/client/lib/utils/memoize.js + function memoize(run) { + const promiseCache = /* @__PURE__ */ new Map(); + const memoized = async function(...args) { + const promiseKey = JSON.stringify(args); + const cachedPromise = promiseCache.get(promiseKey); + if (cachedPromise) { + return cachedPromise; + } + const promise = (async () => { + try { + return await run.apply(this, args); + } finally { + promiseCache.delete(promiseKey); + } + })(); + promiseCache.set(promiseKey, promise); + return promise; + }; + return memoized; + } + + // node_modules/@logto/client/lib/utils/once.js + function once2(function_) { + let called = false; + let result; + return function(...args) { + if (!called) { + called = true; + result = function_.apply(this, args); + } + return result; + }; + } + + // node_modules/@logto/client/lib/client.js + var StandardLogtoClient = class { + get jwtVerifier() { + return this.jwtVerifierInstance; + } + constructor(logtoConfig, adapter, buildJwtVerifier) { + this.getOidcConfig = once2(this.#getOidcConfig); + this.getAccessToken = memoize(this.#getAccessToken); + this.getOrganizationToken = memoize(this.#getOrganizationToken); + this.clearAccessToken = memoize(this.#clearAccessToken); + this.clearAllTokens = memoize(this.#clearAllTokens); + this.handleSignInCallback = memoize(this.#handleSignInCallback); + this.accessTokenMap = /* @__PURE__ */ new Map(); + this.logtoConfig = normalizeLogtoConfig(logtoConfig); + this.adapter = new ClientAdapterInstance(adapter); + this.jwtVerifierInstance = buildJwtVerifier(this); + void this.loadAccessTokenMap(); + } + /** + * Set the JWT verifier for the client. + * @param buildJwtVerifier The JWT verifier instance or a function that returns the JWT verifier instance. + */ + setJwtVerifier(buildJwtVerifier) { + this.jwtVerifierInstance = typeof buildJwtVerifier === "function" ? buildJwtVerifier(this) : buildJwtVerifier; + } + /** + * Check if the user is authenticated by checking if the ID token exists. + */ + async isAuthenticated() { + return Boolean(await this.getIdToken()); + } + /** + * Get the Refresh Token from the storage. + */ + async getRefreshToken() { + return this.adapter.storage.getItem("refreshToken"); + } + /** + * Get the ID Token from the storage. If you want to get the ID Token claims, + * use {@link getIdTokenClaims} instead. + */ + async getIdToken() { + return this.adapter.storage.getItem("idToken"); + } + /** + * Get the ID Token claims. + */ + async getIdTokenClaims() { + const idToken = await this.getIdToken(); + if (!idToken) { + throw new LogtoClientError("not_authenticated", "ID token not found"); + } + return decodeIdToken(idToken); + } + /** + * Get the access token claims for the specified resource. + * + * @param resource The resource that the access token is granted for. If not + * specified, the access token will be used for OpenID Connect or the default + * resource, as specified in the Logto Console. + */ + async getAccessTokenClaims(resource) { + const accessToken = await this.getAccessToken(resource); + return decodeAccessToken(accessToken); + } + /** + * Get the organization token claims for the specified organization. + * + * @param organizationId The ID of the organization that the access token is granted for. + */ + async getOrganizationTokenClaims(organizationId) { + const accessToken = await this.getOrganizationToken(organizationId); + return decodeAccessToken(accessToken); + } + /** + * Get the user information from the Userinfo Endpoint. + * + * Note the Userinfo Endpoint will return more claims than the ID Token. See + * {@link https://docs.logto.io/docs/recipes/integrate-logto/vanilla-js/#fetch-user-information | Fetch user information} + * for more information. + * + * @returns The user information. + * @throws LogtoClientError if the user is not authenticated. + */ + async fetchUserInfo() { + const { userinfoEndpoint } = await this.getOidcConfig(); + const accessToken = await this.getAccessToken(); + if (!accessToken) { + throw new LogtoClientError("fetch_user_info_failed"); + } + return fetchUserInfo(userinfoEndpoint, accessToken, this.adapter.requester); + } + async signIn(options, mode, hint) { + const { redirectUri: redirectUriUrl, postRedirectUri: postRedirectUriUrl, firstScreen, identifiers, interactionMode, loginHint, directSignIn, extraParams, prompt, clearTokens } = typeof options === "string" || options instanceof URL ? { + redirectUri: options, + postRedirectUri: void 0, + firstScreen: void 0, + identifiers: void 0, + interactionMode: mode, + loginHint: hint, + directSignIn: void 0, + extraParams: void 0, + prompt: void 0, + clearTokens: true + } : options; + const redirectUri = redirectUriUrl.toString(); + const postRedirectUri = postRedirectUriUrl?.toString(); + const { appId: clientId, prompt: promptViaConfig, resources, scopes, includeReservedScopes } = this.logtoConfig; + const { authorizationEndpoint } = await this.getOidcConfig(); + const [codeVerifier, state] = await Promise.all([ + this.adapter.generateCodeVerifier(), + this.adapter.generateState() + ]); + const codeChallenge = await this.adapter.generateCodeChallenge(codeVerifier); + const signInUri = generateSignInUri({ + authorizationEndpoint, + clientId, + redirectUri: redirectUri.toString(), + codeChallenge, + state, + scopes, + resources, + prompt: prompt ?? promptViaConfig, + firstScreen, + identifiers, + interactionMode, + loginHint, + directSignIn, + extraParams, + includeReservedScopes + }); + await Promise.all([ + this.setSignInSession({ redirectUri, postRedirectUri, codeVerifier, state }), + clearTokens === false ? void 0 : this.clearAllTokens() + ]); + await this.adapter.navigate(signInUri, { redirectUri, for: "sign-in" }); + } + /** + * Check if the user is redirected from the sign-in page by checking if the + * current URL matches the redirect URI in the sign-in session. + * + * If there's no sign-in session, it will return `false`. + * + * @param url The current URL. + */ + async isSignInRedirected(url) { + const signInSession = await this.getSignInSession(); + if (!signInSession) { + return false; + } + const { redirectUri } = signInSession; + const { origin, pathname } = new URL(url); + return `${origin}${pathname}` === redirectUri; + } + /** + * Start the sign-out flow with the specified redirect URI. The URI must be + * registered in the Logto Console. + * + * It will also revoke all the tokens and clean up the storage. + * + * The user will be redirected that URI after the sign-out flow is completed. + * If the `postLogoutRedirectUri` is not specified, the user will be redirected + * to a default page. + */ + async signOut(postLogoutRedirectUri) { + const { appId: clientId } = this.logtoConfig; + const { endSessionEndpoint, revocationEndpoint } = await this.getOidcConfig(); + const refreshToken = await this.getRefreshToken(); + if (refreshToken) { + try { + await revoke(revocationEndpoint, clientId, refreshToken, this.adapter.requester); + } catch { + } + } + const url = generateSignOutUri({ + endSessionEndpoint, + postLogoutRedirectUri, + clientId + }); + await this.clearAllTokens(); + await this.adapter.navigate(url, { redirectUri: postLogoutRedirectUri, for: "sign-out" }); + } + async getSignInSession() { + const jsonItem = await this.adapter.storage.getItem("signInSession"); + if (!jsonItem) { + return null; + } + const item = JSON.parse(jsonItem); + if (!isLogtoSignInSessionItem(item)) { + throw new LogtoClientError("sign_in_session.invalid"); + } + return item; + } + async setSignInSession(value) { + return this.adapter.setStorageItem(PersistKey.SignInSession, value && JSON.stringify(value)); + } + async setIdToken(value) { + return this.adapter.setStorageItem(PersistKey.IdToken, value); + } + async setRefreshToken(value) { + return this.adapter.setStorageItem(PersistKey.RefreshToken, value); + } + async getAccessTokenByRefreshToken(resource, organizationId) { + const currentRefreshToken = await this.getRefreshToken(); + if (!currentRefreshToken) { + throw new LogtoClientError("not_authenticated", "Refresh token not found"); + } + const accessTokenKey = buildAccessTokenKey(resource, organizationId); + const { appId: clientId } = this.logtoConfig; + const { tokenEndpoint } = await this.getOidcConfig(); + const requestedAt = Math.round(Date.now() / 1e3); + const { accessToken, refreshToken, idToken, scope, expiresIn } = await fetchTokenByRefreshToken({ + clientId, + tokenEndpoint, + refreshToken: currentRefreshToken, + resource, + organizationId + }, this.adapter.requester); + this.accessTokenMap.set(accessTokenKey, { + token: accessToken, + scope, + /** The `expiresAt` variable provides an approximate estimation of the actual `exp` property + * in the token claims. It is utilized by the client to determine if the cached access token + * has expired and when a new access token should be requested. + */ + expiresAt: requestedAt + expiresIn + }); + await this.saveAccessTokenMap(); + if (refreshToken) { + await this.setRefreshToken(refreshToken); + } + if (idToken) { + await this.jwtVerifier.verifyIdToken(idToken); + await this.setIdToken(idToken); + } + return accessToken; + } + async saveAccessTokenMap() { + const data = {}; + for (const [key, accessToken] of this.accessTokenMap.entries()) { + data[key] = accessToken; + } + await this.adapter.storage.setItem("accessToken", JSON.stringify(data)); + } + async loadAccessTokenMap() { + const raw = await this.adapter.storage.getItem("accessToken"); + if (!raw) { + return; + } + try { + const json = JSON.parse(raw); + if (!isLogtoAccessTokenMap(json)) { + return; + } + this.accessTokenMap.clear(); + for (const [key, accessToken] of Object.entries(json)) { + this.accessTokenMap.set(key, accessToken); + } + } catch (error) { + console.warn(error); + } + } + async #getOidcConfig() { + return this.adapter.getWithCache(CacheKey.OpenidConfig, async () => { + return fetchOidcConfig(getDiscoveryEndpoint(this.logtoConfig.endpoint), this.adapter.requester); + }); + } + async #getAccessToken(resource, organizationId) { + if (!await this.isAuthenticated()) { + throw new LogtoClientError("not_authenticated"); + } + const accessTokenKey = buildAccessTokenKey(resource, organizationId); + const accessToken = this.accessTokenMap.get(accessTokenKey); + if (accessToken && accessToken.expiresAt > Date.now() / 1e3) { + return accessToken.token; + } + if (accessToken) { + this.accessTokenMap.delete(accessTokenKey); + } + return this.getAccessTokenByRefreshToken(resource, organizationId); + } + async #getOrganizationToken(organizationId) { + if (!this.logtoConfig.scopes?.includes(UserScope.Organizations)) { + throw new LogtoClientError("missing_scope_organizations"); + } + return this.getAccessToken(void 0, organizationId); + } + async #clearAccessToken() { + this.accessTokenMap.clear(); + await this.adapter.storage.removeItem("accessToken"); + } + async #clearAllTokens() { + await Promise.all([this.setRefreshToken(null), this.setIdToken(null), this.clearAccessToken()]); + } + async #handleSignInCallback(callbackUri) { + const signInSession = await this.getSignInSession(); + if (!signInSession) { + throw new LogtoClientError("sign_in_session.not_found"); + } + const { redirectUri, postRedirectUri, state, codeVerifier } = signInSession; + const code = verifyAndParseCodeFromCallbackUri(callbackUri, redirectUri, state); + const accessTokenKey = buildAccessTokenKey(); + const { appId: clientId } = this.logtoConfig; + const { tokenEndpoint } = await this.getOidcConfig(); + const requestedAt = Math.round(Date.now() / 1e3); + const { idToken, refreshToken, accessToken, scope, expiresIn } = await fetchTokenByAuthorizationCode({ + clientId, + tokenEndpoint, + redirectUri, + codeVerifier, + code + }, this.adapter.requester); + await this.jwtVerifier.verifyIdToken(idToken); + await this.setRefreshToken(refreshToken ?? null); + await this.setIdToken(idToken); + this.accessTokenMap.set(accessTokenKey, { + token: accessToken, + scope, + /** The `expiresAt` variable provides an approximate estimation of the actual `exp` property + * in the token claims. It is utilized by the client to determine if the cached access token + * has expired and when a new access token should be requested. + */ + expiresAt: requestedAt + expiresIn + }); + await this.saveAccessTokenMap(); + await this.setSignInSession(null); + if (postRedirectUri) { + await this.adapter.navigate(postRedirectUri, { for: "post-sign-in" }); + } + } + }; + + // node_modules/@logto/client/lib/utils/requester.js + var createRequester = (fetchFunction) => { + return async (...args) => { + const response = await fetchFunction(...args); + if (!response.ok) { + const cloned = response.clone(); + const responseJson = await response.json(); + console.error(`Logto requester error: [status=${response.status}]`, responseJson); + if (!isLogtoRequestErrorJson(responseJson)) { + throw new LogtoError("unexpected_response_error", responseJson); + } + const { code, message: message2 } = responseJson; + throw new LogtoRequestError(code, message2, cloned); + } + return response.json(); + }; + }; + + // node_modules/@logto/client/lib/index.js + var LogtoClient = class extends StandardLogtoClient { + constructor(logtoConfig, adapter, buildJwtVerifier) { + super(logtoConfig, adapter, buildJwtVerifier ?? ((client) => new DefaultJwtVerifier(client))); + } + }; + + // node_modules/js-base64/base64.mjs + var _hasBuffer = typeof Buffer === "function"; + var _TD = typeof TextDecoder === "function" ? new TextDecoder() : void 0; + var _TE = typeof TextEncoder === "function" ? new TextEncoder() : void 0; + var b64ch = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + var b64chs = Array.prototype.slice.call(b64ch); + var b64tab = ((a) => { + let tab = {}; + a.forEach((c, i) => tab[c] = i); + return tab; + })(b64chs); + var _fromCC = String.fromCharCode.bind(String); + var _U8Afrom = typeof Uint8Array.from === "function" ? Uint8Array.from.bind(Uint8Array) : (it) => new Uint8Array(Array.prototype.slice.call(it, 0)); + var _mkUriSafe = (src) => src.replace(/=/g, "").replace(/[+\/]/g, (m0) => m0 == "+" ? "-" : "_"); + var btoaPolyfill = (bin) => { + let u32, c0, c1, c2, asc = ""; + const pad = bin.length % 3; + for (let i = 0; i < bin.length; ) { + if ((c0 = bin.charCodeAt(i++)) > 255 || (c1 = bin.charCodeAt(i++)) > 255 || (c2 = bin.charCodeAt(i++)) > 255) + throw new TypeError("invalid character found"); + u32 = c0 << 16 | c1 << 8 | c2; + asc += b64chs[u32 >> 18 & 63] + b64chs[u32 >> 12 & 63] + b64chs[u32 >> 6 & 63] + b64chs[u32 & 63]; + } + return pad ? asc.slice(0, pad - 3) + "===".substring(pad) : asc; + }; + var _btoa = typeof btoa === "function" ? (bin) => btoa(bin) : _hasBuffer ? (bin) => Buffer.from(bin, "binary").toString("base64") : btoaPolyfill; + var _fromUint8Array = _hasBuffer ? (u8a) => Buffer.from(u8a).toString("base64") : (u8a) => { + const maxargs = 4096; + let strs = []; + for (let i = 0, l = u8a.length; i < l; i += maxargs) { + strs.push(_fromCC.apply(null, u8a.subarray(i, i + maxargs))); + } + return _btoa(strs.join("")); + }; + var fromUint8Array = (u8a, urlsafe = false) => urlsafe ? _mkUriSafe(_fromUint8Array(u8a)) : _fromUint8Array(u8a); + + // node_modules/@logto/browser/lib/utils/generators.js + var generateRandomString = (length = 64) => fromUint8Array(crypto.getRandomValues(new Uint8Array(length)), true); + var generateState = () => generateRandomString(); + var generateCodeVerifier = () => generateRandomString(); + var generateCodeChallenge = async (codeVerifier) => { + if (crypto.subtle === void 0) { + throw new LogtoError("crypto_subtle_unavailable"); + } + const encodedCodeVerifier = new TextEncoder().encode(codeVerifier); + const codeChallenge = new Uint8Array(await crypto.subtle.digest("SHA-256", encodedCodeVerifier)); + return fromUint8Array(codeChallenge, true); + }; + + // node_modules/@logto/chrome-extension/lib/storage.js + var keyPrefix = `logto`; + var ChromeExtensionStorage = class { + constructor(appId) { + this.appId = appId; + } + getKey(item) { + if (item === void 0) { + return `${keyPrefix}:${this.appId}`; + } + return `${keyPrefix}:${this.appId}:${item}`; + } + // eslint-disable-next-line @typescript-eslint/ban-types + async getItem(key) { + const storageKey = this.getKey(key); + const object = await chrome.storage.local.get(storageKey); + return object[storageKey] ? String(object[storageKey]) : null; + } + async setItem(key, value) { + await chrome.storage.local.set({ [this.getKey(key)]: value }); + } + async removeItem(key) { + await chrome.storage.local.remove(this.getKey(key)); + } + }; + + // node_modules/@logto/chrome-extension/lib/index.js + var LogtoClient2 = class extends LogtoClient { + /** + * @param config The configuration object for the client. + */ + constructor(config) { + const requester = createRequester(fetch); + const navigate = async (url, params) => { + switch (params.for) { + case "sign-in": { + const responseUrl = await chrome.identity.launchWebAuthFlow({ url, interactive: true }); + if (!responseUrl) { + throw new LogtoClientError("user_cancelled"); + } + await this.handleSignInCallback(responseUrl); + break; + } + case "sign-out": { + await chrome.identity.launchWebAuthFlow({ + url, + interactive: false, + abortOnLoadForNonInteractive: false, + timeoutMsForNonInteractive: 1e4 + }); + break; + } + default: { + throw new Error(`Unsupported navigation for ${params.for}`); + } + } + }; + super(config, { + requester, + navigate, + storage: new ChromeExtensionStorage(config.appId), + generateCodeChallenge, + generateCodeVerifier, + generateState + }); + } + }; + + // src/background/auth/client.ts + function createLogtoAuthClient() { + const config = readAuthConfig(); + const client = new LogtoClient2({ + appId: config.appId, + endpoint: config.logtoEndpoint, + resources: [config.apiResource], + scopes: config.scopes + }); + return { + getAccessToken(resource) { + return client.getAccessToken(resource); + }, + getIdTokenClaims() { + return client.getIdTokenClaims(); + }, + isAuthenticated() { + return client.isAuthenticated(); + }, + signIn() { + return client.signIn(readChromeIdentity().getRedirectURL("/callback")); + }, + signOut() { + return client.signOut(readChromeIdentity().getRedirectURL()); + } + }; + } + function readChromeIdentity() { + const identity = globalThis.chrome?.identity; + if (typeof identity?.getRedirectURL !== "function") { + throw new Error("chrome.identity.getRedirectURL is unavailable"); + } + return { + getRedirectURL: identity.getRedirectURL.bind(identity) + }; + } + + // src/shared/auth-messages.ts + var authRequestTypes = /* @__PURE__ */ new Set([ + "auth:get-state", + "auth:sign-in", + "auth:sign-out", + "auth:get-access-token" + ]); + function isAuthRequestMessage(value) { + if (!value || typeof value !== "object") { + return false; + } + const candidate = value; + return typeof candidate.type === "string" && authRequestTypes.has(candidate.type); + } + function isAuthResponseMessage(value) { + if (!value || typeof value !== "object") { + return false; + } + const candidate = value; + if (candidate.ok === false) { + return candidate.type === "auth:error" && typeof candidate.error === "string"; + } + if (candidate.ok !== true || typeof candidate.type !== "string") { + return false; + } + if (candidate.type === "auth:ack") { + return true; + } + if (candidate.type === "auth:token") { + return Boolean( + candidate.value && typeof candidate.value === "object" && typeof candidate.value.accessToken === "string" + ); + } + if (candidate.type === "auth:state") { + return Boolean( + candidate.value && typeof candidate.value === "object" && typeof candidate.value.isAuthenticated === "boolean" + ); + } + return false; + } + + // src/shared/batch-submit-config.ts + var DEFAULT_BATCH_SUBMIT_BASE_URL = "http://192.168.31.21:8083"; + + // src/shared/batch-submit-client.ts + function createBatchSubmitClient(options) { + const baseUrl = options.baseUrl ?? DEFAULT_BATCH_SUBMIT_BASE_URL; + const fetchImpl = options.fetchImpl ?? fetch; + const getAccessToken = options.getAccessToken ?? (() => readAccessToken(options.sendMessage)); + return { + async submitBatch(payload) { + const token = await getAccessToken(); + const response = await fetchImpl( + buildBatchSubmitUrl(baseUrl), + { + body: JSON.stringify(payload), + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json" + }, + method: "POST" + } + ); + if (response.status === 401 || response.status === 403) { + throw new Error("batch submit unauthorized"); + } + if (!response.ok) { + throw new Error(`batch submit failed: ${response.status}`); + } + return readBatchSubmitResponse(await response.json()); + } + }; + } + function buildBatchSubmitUrl(baseUrl) { + return new URL("/api/v1/batch-status/batches", baseUrl).toString(); + } + async function readAccessToken(sendMessage) { + const response = await sendMessage({ type: "auth:get-access-token" }); + if (!isAuthResponseMessage(response) || !response.ok || response.type !== "auth:token" || !response.value.accessToken.trim()) { + throw new Error("batch submit token unavailable"); + } + return response.value.accessToken; + } + function readBatchSubmitResponse(payload) { + if (!isRecord(payload)) { + throw new Error("batch submit response is invalid"); + } + if (payload.success !== true) { + const message2 = typeof payload.msg === "string" && payload.msg.trim() ? payload.msg : "batch submit failed"; + throw new Error(message2); + } + return "data" in payload ? payload.data : payload; + } + function isRecord(value) { + return typeof value === "object" && value !== null; + } + + // src/shared/backend-metrics-config.ts + var DEFAULT_BACKEND_METRICS_BASE_URL = "https://talent-search.intelligrow.cn"; + + // src/shared/backend-metrics-client.ts + function createBackendMetricsClient(options) { + const baseUrl = options.baseUrl ?? DEFAULT_BACKEND_METRICS_BASE_URL; + const fetchImpl = options.fetchImpl ?? defaultFetch; + return { + async searchByStarIds(starIds) { + const response = await fetchImpl(buildBackendMetricsSearchUrl(baseUrl), { + body: JSON.stringify(buildBackendMetricsSearchRequestBody(starIds)), + headers: { + Authorization: `Bearer ${await options.getAccessToken()}`, + "Content-Type": "application/json" + }, + method: "POST" + }); + if (!response.ok) { + throw new Error("backend metrics request failed"); + } + return mapBackendMetricsSearchResponse(await response.json()); + } + }; + } + function buildBackendMetricsSearchUrl(baseUrl) { + return new URL("/api/v1/history/talents/search", baseUrl).toString(); + } + function buildBackendMetricsSearchRequestBody(starIds) { + return { + page: 1, + size: Math.max(20, starIds.length), + type: "star_id", + values: starIds + }; + } + function mapBackendMetricsSearchResponse(payload) { + const rows = readResponseRows(payload); + if (!rows) { + throw new Error("backend metrics response is invalid"); + } + return rows.flatMap((row) => { + if (!isRecord2(row) || typeof row.star_id !== "string") { + return []; + } + return [ + { + a3IncreaseCount: formatDecimalValue( + readAverageA3IncreaseCount(row) + ), + afterViewSearchCount: formatDecimalValue(row.avg_after_view_search_cnt), + afterViewSearchRate: formatRateValue(row.avg_after_view_search_rate), + cpSearch: formatDecimalValue(row.cp_search), + cpa3: formatDecimalValue(readCpa3Value(row)), + newA3Rate: formatRateValue(row.avg_new_a3_rate), + starId: row.star_id + } + ]; + }); + } + function readAverageA3IncreaseCount(row) { + const directAverage = readFiniteNumber(row.avg_a3_increase_cnt); + if (directAverage !== null) { + return directAverage; + } + const totalNewA3 = readTotalNewA3Value(row); + const videoCount = readFiniteNumber(row.video_count) ?? readNestedVideoCount(row.videos); + if (totalNewA3 === null || videoCount === null || videoCount <= 0) { + return null; + } + return totalNewA3 / videoCount; + } + function readCpa3Value(row) { + const directCpa3 = readFiniteNumber(row.cpa3); + if (directCpa3 !== null) { + return directCpa3; + } + const totalCost = readFiniteNumber(row.total_estimated_video_cost); + const totalNewA3 = readTotalNewA3Value(row); + if (totalCost === null || totalNewA3 === null || totalNewA3 <= 0) { + return null; + } + return totalCost / totalNewA3; + } + function readTotalNewA3Value(row) { + const derivedFromTotals = deriveTotalNewA3FromTotals(row); + if (derivedFromTotals !== null) { + return derivedFromTotals; + } + return deriveTotalNewA3FromVideos(row.videos); + } + function deriveTotalNewA3FromTotals(row) { + const totalPlayCount = readFiniteNumber(row.total_play_cnt); + const averageNewA3Rate = readFiniteNumber(row.avg_new_a3_rate); + if (totalPlayCount === null || averageNewA3Rate === null) { + return null; + } + return totalPlayCount * averageNewA3Rate; + } + function deriveTotalNewA3FromVideos(value) { + if (!Array.isArray(value)) { + return null; + } + let total = 0; + let hasFiniteValue = false; + value.forEach((video) => { + if (!isRecord2(video)) { + return; + } + const newA3 = readFiniteNumber(video.new_a3); + if (newA3 === null) { + return; + } + hasFiniteValue = true; + total += newA3; + }); + return hasFiniteValue ? total : null; + } + function readNestedVideoCount(value) { + return Array.isArray(value) ? value.length : null; + } + function readResponseRows(payload) { + if (!isRecord2(payload) || payload.success !== true) { + return null; + } + const topLevelData = isRecord2(payload.data) ? payload.data : null; + return Array.isArray(topLevelData?.data) ? topLevelData.data : null; + } + function formatRateValue(value) { + const number = typeof value === "number" ? value : Number(value); + if (Number.isFinite(number)) { + const percentage = number * 100; + const formatted = new Intl.NumberFormat("en-US", { + maximumFractionDigits: 2, + minimumFractionDigits: percentage % 1 === 0 ? 0 : 2 + }).format(percentage); + return `${formatted}%`; + } + return ""; + } + function formatDecimalValue(value) { + const number = typeof value === "number" ? value : Number(value); + if (!Number.isFinite(number)) { + return ""; + } + return new Intl.NumberFormat("en-US", { + maximumFractionDigits: 2, + minimumFractionDigits: 2 + }).format(number); + } + async function defaultFetch(input, init) { + return fetch(input, init); + } + function isRecord2(value) { + return typeof value === "object" && value !== null; + } + function readFiniteNumber(value) { + const number = typeof value === "number" ? value : Number(value); + return Number.isFinite(number) ? number : null; + } + + // src/shared/backend-metrics-messages.ts + function isBackendMetricsSearchRequestMessage(value) { + if (!value || typeof value !== "object") { + return false; + } + const candidate = value; + return candidate.type === "backend-metrics:search" && Boolean( + candidate.value && typeof candidate.value === "object" && Array.isArray(candidate.value.starIds) && candidate.value.starIds.every( + (starId) => typeof starId === "string" + ) + ); + } + + // src/background/index.ts + function registerBackgroundMessageHandler(chromeLike = readChromeLike(), dependencies = {}) { + let authController = dependencies.authController; + let searchBackendMetrics = dependencies.searchBackendMetrics; + let submitBatch = dependencies.submitBatch; + chromeLike.runtime?.onMessage?.addListener((message2, _sender, sendResponse) => { + if (isDownloadMarketCsvMessage(message2)) { + void triggerCsvDownload(chromeLike, message2).then(() => { + sendResponse({ ok: true }); + }).catch((error) => { + sendResponse({ + error: error instanceof Error ? error.message : String(error), + ok: false + }); + }); + return true; + } + if (isBatchSubmitMessage(message2)) { + authController ??= createAuthController({ + authClient: createLogtoAuthClient() + }); + submitBatch ??= createBatchSubmitClient({ + baseUrl: DEFAULT_BATCH_SUBMIT_BASE_URL, + getAccessToken: () => authController.getAccessToken(), + sendMessage: () => Promise.reject(new Error("background batch submit does not use sendMessage")) + }).submitBatch; + void submitBatch(message2.payload).then((value) => { + sendResponse({ + ok: true, + type: "batch:ack", + value + }); + }).catch((error) => { + sendResponse({ + error: error instanceof Error ? error.message : String(error), + ok: false, + type: "batch:error" + }); + }); + return true; + } + if (isBackendMetricsSearchRequestMessage(message2)) { + authController ??= createAuthController({ + authClient: createLogtoAuthClient() + }); + searchBackendMetrics ??= createBackendMetricsClient({ + baseUrl: DEFAULT_BACKEND_METRICS_BASE_URL, + getAccessToken: () => authController.getAccessToken() + }).searchByStarIds; + void searchBackendMetrics(message2.value.starIds).then((rows) => { + sendResponse({ + ok: true, + type: "backend-metrics:result", + value: { + rows + } + }); + }).catch((error) => { + sendResponse({ + error: error instanceof Error ? error.message : String(error), + ok: false, + type: "backend-metrics:error" + }); + }); + return true; + } + if (!isAuthRequestMessage(message2)) { + return; + } + authController ??= createAuthController({ + authClient: createLogtoAuthClient() + }); + void handleAuthMessage(authController, message2).then((response) => { + sendResponse(response); + }).catch((error) => { + sendResponse({ + error: error instanceof Error ? error.message : String(error), + ok: false, + type: "auth:error" + }); + }); + return true; + }); + } + async function handleAuthMessage(authController, message2) { + if (message2.type === "auth:get-state") { + return { + ok: true, + type: "auth:state", + value: await authController.getAuthState() + }; + } + if (message2.type === "auth:get-access-token") { + return { + ok: true, + type: "auth:token", + value: { + accessToken: await authController.getAccessToken() + } + }; + } + if (message2.type === "auth:sign-in") { + await authController.signIn(); + return { + ok: true, + type: "auth:ack" + }; + } + await authController.signOut(); + return { + ok: true, + type: "auth:ack" + }; + } + function readChromeLike() { + return globalThis.chrome ?? {}; + } + async function triggerCsvDownload(chromeLike, message2) { + if (!chromeLike.downloads?.download) { + throw new Error("chrome.downloads.download is unavailable"); + } + const csvUrl = `data:text/csv;charset=utf-8,${encodeURIComponent(`\uFEFF${message2.csv}`)}`; + await Promise.resolve( + chromeLike.downloads.download({ + filename: message2.filename, + saveAs: false, + url: csvUrl + }) + ); + } + function isDownloadMarketCsvMessage(message2) { + if (!message2 || typeof message2 !== "object") { + return false; + } + const candidate = message2; + return candidate.type === "download-market-csv" && typeof candidate.csv === "string" && typeof candidate.filename === "string"; + } + function isBatchSubmitMessage(message2) { + if (!message2 || typeof message2 !== "object") { + return false; + } + const candidate = message2; + return candidate.type === "batch:submit" && "payload" in candidate; + } + registerBackgroundMessageHandler(); +})(); +/*! Bundled license information: + +@silverhand/essentials/lib/utilities/assertions.js: + (*! + * is-plain-object + * + * Copyright (c) 2014-2017, Jon Schlinkert. + * Released under the MIT License. + *) +*/ diff --git a/dist-release/content/index.js b/dist-release/content/index.js new file mode 100644 index 0000000..db7cf3a --- /dev/null +++ b/dist-release/content/index.js @@ -0,0 +1,4446 @@ +"use strict"; +(() => { + // src/shared/rate-normalizer.ts + function normalizeRateDisplay(value) { + const trimmedValue = value.trim(); + const rangeMatch = trimmedValue.match( + /^([0-9]+(?:\.[0-9]+)?)\s*%?\s*-\s*([0-9]+(?:\.[0-9]+)?)\s*%$/ + ); + if (rangeMatch) { + const [, lowerBound, upperBound] = rangeMatch; + return `${lowerBound}% - ${upperBound}%`; + } + return trimmedValue.replace(/\s+/g, ""); + } + function normalizeFractionRateDisplay(value) { + const numericValue = Number(value); + if (!Number.isFinite(numericValue)) { + return null; + } + const percentageValue = numericValue * 100; + return `${trimTrailingZeros(percentageValue.toFixed(6))}%`; + } + function parseRateLowerBound(value) { + const comparableRate = toComparableRate(value); + return comparableRate?.numeric ?? null; + } + function compareRateValues(leftValue, rightValue) { + const leftComparable = toComparableRate(leftValue); + const rightComparable = toComparableRate(rightValue); + if (!leftComparable && !rightComparable) { + return 0; + } + if (!leftComparable) { + return 1; + } + if (!rightComparable) { + return -1; + } + if (leftComparable.numeric !== rightComparable.numeric) { + return leftComparable.numeric - rightComparable.numeric; + } + if (leftComparable.isLessThan === rightComparable.isLessThan) { + return 0; + } + return leftComparable.isLessThan ? -1 : 1; + } + function toComparableRate(value) { + if (!value) { + return null; + } + const normalizedValue = normalizeRateDisplay(value); + const lessThanMatch = normalizedValue.match(/^<\s*([0-9]+(?:\.[0-9]+)?)%$/); + if (lessThanMatch) { + return { + isLessThan: true, + numeric: Number(lessThanMatch[1]) + }; + } + const rangeMatch = normalizedValue.match( + /^([0-9]+(?:\.[0-9]+)?)%\s*-\s*([0-9]+(?:\.[0-9]+)?)%$/ + ); + if (rangeMatch) { + return { + isLessThan: false, + numeric: Number(rangeMatch[1]) + }; + } + const exactMatch = normalizedValue.match(/^([0-9]+(?:\.[0-9]+)?)%$/); + if (exactMatch) { + return { + isLessThan: false, + numeric: Number(exactMatch[1]) + }; + } + return null; + } + function trimTrailingZeros(value) { + return value.replace(/\.?0+$/, ""); + } + + // src/shared/csv.ts + function escapeCsvCell(value) { + if (/[",\n]/.test(value)) { + return `"${value.replace(/"/g, '""')}"`; + } + return value; + } + + // src/content/market/csv-exporter.ts + var FALLBACK_BASE_COLUMNS = [ + { + header: "\u8FBE\u4EBAID", + readValue: (record) => record.authorId + }, + { + header: "\u8FBE\u4EBA\u540D\u79F0", + readValue: (record) => record.authorName + }, + { + header: "\u5730\u533A", + readValue: (record) => record.location ?? "" + }, + { + header: "21-60s\u62A5\u4EF7", + readValue: (record) => record.price21To60s ?? "" + } + ]; + var RATE_COLUMNS = [ + { + header: "\u5355\u89C6\u9891\u770B\u540E\u641C\u7387", + readValue: (record) => record.rates?.singleVideoAfterSearchRate ? normalizeRateDisplay(record.rates.singleVideoAfterSearchRate) : "" + }, + { + header: "\u4E2A\u4EBA\u89C6\u9891\u770B\u540E\u641C\u7387", + readValue: (record) => record.rates?.personalVideoAfterSearchRate ? normalizeRateDisplay(record.rates.personalVideoAfterSearchRate) : "" + } + ]; + var BACKEND_METRIC_COLUMNS = [ + { + header: "\u770B\u540E\u641C\u7387", + readValue: (record) => record.backendMetrics?.afterViewSearchRate ?? "" + }, + { + header: "\u770B\u540E\u641C\u6570", + readValue: (record) => record.backendMetrics?.afterViewSearchCount ?? "" + }, + { + header: "\u65B0\u589EA3\u6570", + readValue: (record) => record.backendMetrics?.a3IncreaseCount ?? "" + }, + { + header: "\u65B0\u589EA3\u7387", + readValue: (record) => record.backendMetrics?.newA3Rate ?? "" + }, + { + header: "CPA3", + readValue: (record) => record.backendMetrics?.cpa3 ?? "" + }, + { + header: "cp_search", + readValue: (record) => record.backendMetrics?.cpSearch ?? "" + } + ]; + function buildMarketCsv(records) { + const baseColumns = buildBaseColumns(records); + const csvColumns = [...baseColumns, ...RATE_COLUMNS, ...BACKEND_METRIC_COLUMNS]; + const headerLine = csvColumns.map((column) => column.header).join(","); + const rowLines = records.map( + (record) => csvColumns.map((column) => escapeCsvCell(column.readValue(record))).join(",") + ); + return [headerLine, ...rowLines].join("\n"); + } + function buildBaseColumns(records) { + const orderedHeaders = []; + const seenHeaders = /* @__PURE__ */ new Set(); + const excludedHeaders = /* @__PURE__ */ new Set(["\u4EE3\u8868\u89C6\u9891"]); + records.forEach((record) => { + Object.keys(record.exportFields ?? {}).forEach((header) => { + if (seenHeaders.has(header) || excludedHeaders.has(header)) { + return; + } + seenHeaders.add(header); + orderedHeaders.push(header); + }); + }); + if (orderedHeaders.length === 0) { + return FALLBACK_BASE_COLUMNS; + } + return orderedHeaders.map((header) => ({ + header, + readValue: (record) => record.exportFields?.[header] ?? "" + })); + } + + // src/content/market/batch-name-dialog.ts + var DIALOG_STYLE_ID = "sces-batch-name-dialog-style"; + var activeDialogs = /* @__PURE__ */ new WeakMap(); + function promptForBatchName(document2) { + const existingDialog = activeDialogs.get(document2); + if (existingDialog) { + existingDialog.input.focus(); + existingDialog.input.select(); + return existingDialog.promise; + } + ensureDialogStyles(document2); + const dialogRoot = document2.createElement("div"); + dialogRoot.dataset.pluginBatchNameDialog = "root"; + dialogRoot.setAttribute("role", "dialog"); + dialogRoot.setAttribute("aria-modal", "true"); + dialogRoot.setAttribute("aria-labelledby", "sces-batch-name-title"); + applyOverlayStyles(dialogRoot); + const dialogPanel = document2.createElement("div"); + applyPanelStyles(dialogPanel); + const title = document2.createElement("h2"); + title.id = "sces-batch-name-title"; + title.textContent = "\u63D0\u4EA4\u6279\u6B21"; + applyTitleStyles(title); + const description = document2.createElement("p"); + description.textContent = "\u8BF7\u8F93\u5165\u6279\u6B21\u540D\u79F0\uFF0C\u4FBF\u4E8E\u540E\u7EED\u5728\u7CFB\u7EDF\u4E2D\u8BC6\u522B\u548C\u8FFD\u8E2A\u3002"; + applyDescriptionStyles(description); + const input = document2.createElement("input"); + input.type = "text"; + input.dataset.pluginBatchNameInput = "input"; + input.placeholder = "\u4F8B\u5982\uFF1A618\u8FBE\u4EBA\u7B5B\u9009\u7B2C\u4E00\u6279"; + input.maxLength = 60; + applyInputStyles(input); + const errorText = document2.createElement("p"); + errorText.dataset.pluginBatchNameError = "text"; + applyErrorStyles(errorText); + const buttonRow = document2.createElement("div"); + applyButtonRowStyles(buttonRow); + const cancelButton = document2.createElement("button"); + cancelButton.type = "button"; + cancelButton.dataset.pluginBatchNameCancel = "button"; + cancelButton.textContent = "\u53D6\u6D88"; + applySecondaryButtonStyles(cancelButton); + const confirmButton = document2.createElement("button"); + confirmButton.type = "button"; + confirmButton.dataset.pluginBatchNameConfirm = "button"; + confirmButton.textContent = "\u786E\u8BA4\u63D0\u4EA4"; + applyPrimaryButtonStyles(confirmButton); + buttonRow.append(cancelButton, confirmButton); + dialogPanel.append(title, description, input, errorText, buttonRow); + dialogRoot.appendChild(dialogPanel); + document2.body.appendChild(dialogRoot); + const dialogPromise = new Promise((resolve) => { + const closeDialog = (value) => { + activeDialogs.delete(document2); + dialogRoot.remove(); + document2.removeEventListener("keydown", handleDocumentKeydown, true); + resolve(value); + }; + const submitValue = () => { + const value = input.value.trim(); + if (!value) { + errorText.textContent = "\u8BF7\u8F93\u5165\u6279\u6B21\u540D\u79F0"; + input.setAttribute("aria-invalid", "true"); + input.focus(); + return; + } + closeDialog(value); + }; + const handleDocumentKeydown = (event) => { + if (event.key === "Escape") { + event.preventDefault(); + closeDialog(null); + return; + } + if (event.key === "Enter") { + event.preventDefault(); + submitValue(); + } + }; + input.addEventListener("input", () => { + if (!input.value.trim()) { + return; + } + errorText.textContent = ""; + input.removeAttribute("aria-invalid"); + }); + cancelButton.addEventListener("click", () => { + closeDialog(null); + }); + confirmButton.addEventListener("click", () => { + submitValue(); + }); + dialogRoot.addEventListener("click", (event) => { + if (event.target === dialogRoot) { + closeDialog(null); + } + }); + document2.addEventListener("keydown", handleDocumentKeydown, true); + }); + activeDialogs.set(document2, { + input, + promise: dialogPromise + }); + input.focus(); + return dialogPromise; + } + function ensureDialogStyles(document2) { + if (document2.getElementById(DIALOG_STYLE_ID)) { + return; + } + const style = document2.createElement("style"); + style.id = DIALOG_STYLE_ID; + style.textContent = ` + [data-plugin-batch-name-dialog="root"] { + animation: sces-batch-name-fade-in 0.16s ease; + } + + @keyframes sces-batch-name-fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + `; + document2.head.appendChild(style); + } + function applyOverlayStyles(root) { + root.style.position = "fixed"; + root.style.inset = "0"; + root.style.background = "rgba(15, 23, 42, 0.38)"; + root.style.display = "flex"; + root.style.alignItems = "center"; + root.style.justifyContent = "center"; + root.style.padding = "24px"; + root.style.zIndex = "2147483647"; + } + function applyPanelStyles(panel) { + panel.style.width = "min(420px, calc(100vw - 32px))"; + panel.style.background = "#fffaf9"; + panel.style.border = "1px solid rgba(127, 29, 45, 0.14)"; + panel.style.borderRadius = "18px"; + panel.style.boxShadow = "0 28px 70px rgba(15, 23, 42, 0.22)"; + panel.style.padding = "24px"; + panel.style.boxSizing = "border-box"; + } + function applyTitleStyles(title) { + title.style.margin = "0"; + title.style.color = "#4c0519"; + title.style.fontSize = "20px"; + title.style.fontWeight = "700"; + title.style.lineHeight = "28px"; + } + function applyDescriptionStyles(description) { + description.style.margin = "10px 0 0"; + description.style.color = "#64748b"; + description.style.fontSize = "13px"; + description.style.lineHeight = "20px"; + } + function applyInputStyles(input) { + input.style.width = "100%"; + input.style.height = "42px"; + input.style.marginTop = "18px"; + input.style.padding = "0 14px"; + input.style.boxSizing = "border-box"; + input.style.border = "1px solid #d8c1c6"; + input.style.borderRadius = "12px"; + input.style.background = "#ffffff"; + input.style.color = "#1f2937"; + input.style.fontSize = "14px"; + input.style.outline = "none"; + } + function applyErrorStyles(errorText) { + errorText.style.minHeight = "20px"; + errorText.style.margin = "8px 0 0"; + errorText.style.color = "#b91c1c"; + errorText.style.fontSize = "12px"; + errorText.style.lineHeight = "18px"; + } + function applyButtonRowStyles(buttonRow) { + buttonRow.style.display = "flex"; + buttonRow.style.justifyContent = "flex-end"; + buttonRow.style.gap = "10px"; + buttonRow.style.marginTop = "18px"; + } + function applySecondaryButtonStyles(button) { + button.style.height = "36px"; + button.style.padding = "0 16px"; + button.style.border = "1px solid #d7dde6"; + button.style.borderRadius = "10px"; + button.style.background = "#ffffff"; + button.style.color = "#334155"; + button.style.fontWeight = "600"; + button.style.cursor = "pointer"; + } + function applyPrimaryButtonStyles(button) { + button.style.height = "36px"; + button.style.padding = "0 16px"; + button.style.border = "1px solid #7f1d2d"; + button.style.borderRadius = "10px"; + button.style.background = "#7f1d2d"; + button.style.color = "#ffffff"; + button.style.fontWeight = "600"; + button.style.cursor = "pointer"; + } + + // src/content/market/batch-payload.ts + function createBatchPayload(options) { + const logtoUserId = options.authState.userInfo?.sub?.trim(); + if (!logtoUserId) { + throw new Error("batch submit user id unavailable"); + } + const resource = options.authState.resource?.trim(); + if (!resource) { + throw new Error("batch submit resource unavailable"); + } + const batchName = options.batchName.trim(); + if (!batchName) { + throw new Error("batch submit batch name is required"); + } + return { + authors: options.records.map((record) => ({ + authorId: record.authorId, + authorName: record.authorName + })), + batchName, + createdAt: options.createdAt, + creatorName: options.authState.userInfo?.name ?? options.authState.userInfo?.username ?? logtoUserId, + logtoUserId, + resource + }; + } + + // src/content/market/market-list-row.ts + var PAGE_NUMBER_KEYS = [ + "currentPage", + "page", + "pageNo", + "pageNum", + "page_no", + "page_num" + ]; + var PAGE_SIZE_KEYS = [ + "limit", + "pageSize", + "page_size", + "size" + ]; + var TOTAL_COUNT_KEYS = [ + "total", + "totalCount", + "total_count" + ]; + var TOTAL_PAGE_KEYS = [ + "pageCount", + "page_count", + "totalPage", + "totalPages", + "total_page", + "total_pages" + ]; + function mapMarketListRow(row) { + const attributeDatas = readMarketAttributeDatas(row); + const singleVideoAfterSearchRate = normalizeMarketListRate( + readMarketFieldValue(row, attributeDatas, "avg_search_after_view_rate_30d") + ); + return { + authorId: readString(readMarketFieldValue(row, attributeDatas, "star_id")) ?? readString(readMarketFieldValue(row, attributeDatas, "id")) ?? "", + authorName: readString(readMarketFieldValue(row, attributeDatas, "nickname")) ?? readString(readMarketFieldValue(row, attributeDatas, "nick_name")) ?? "", + exportFields: buildMarketExportFieldFallbacks(row, attributeDatas), + hasDirectRatesSource: true, + location: readMarketLocation(row, attributeDatas), + price21To60s: readMarketPrice21To60s(row, attributeDatas), + rates: singleVideoAfterSearchRate ? { + singleVideoAfterSearchRate + } : void 0 + }; + } + function parseMarketListResponse(payload) { + const container = findMarketListContainer(payload); + if (!container) { + return null; + } + const marketList = readMarketListArray(container); + if (!marketList) { + return null; + } + return { + currentPage: readKnownNumberDeep(container, PAGE_NUMBER_KEYS) ?? void 0, + pageSize: readKnownNumberDeep(container, PAGE_SIZE_KEYS) ?? void 0, + records: marketList.map((row) => isRecord(row) ? mapMarketListRow(row) : null).filter( + (row) => row !== null && Boolean(row.authorId || row.authorName) + ), + totalCount: readKnownNumberDeep(container, TOTAL_COUNT_KEYS) ?? void 0, + totalPages: readKnownNumberDeep(container, TOTAL_PAGE_KEYS) ?? void 0 + }; + } + function readKnownPaginationNumber(value, kind) { + if (!isRecord(value)) { + return null; + } + return readKnownNumberDeep(value, kind === "page" ? PAGE_NUMBER_KEYS : PAGE_SIZE_KEYS); + } + function findMarketListContainer(value) { + const queue = [value]; + while (queue.length > 0) { + const current = queue.shift(); + if (!isRecord(current)) { + continue; + } + if (readMarketListArray(current)) { + return current; + } + Object.values(current).forEach((entry) => { + queue.push(unwrapVueRef(entry)); + }); + } + return null; + } + function readMarketListArray(record) { + const marketList = unwrapVueRef(record.marketList); + if (Array.isArray(marketList)) { + return marketList; + } + const authors = unwrapVueRef(record.authors); + if (Array.isArray(authors)) { + return authors; + } + return null; + } + function unwrapVueRef(value) { + if (isRecord(value) && "value" in value) { + return value.value; + } + return value; + } + function isRecord(value) { + return typeof value === "object" && value !== null; + } + function readMarketAttributeDatas(record) { + return isRecord(record.attribute_datas) ? record.attribute_datas : {}; + } + function readMarketFieldValue(record, attributeDatas, field) { + return record[field] ?? attributeDatas[field]; + } + function readString(value) { + return typeof value === "string" ? value : null; + } + function normalizeMarketListRate(value) { + if (typeof value === "number") { + return normalizeFractionRateDisplay(String(value)); + } + return typeof value === "string" ? normalizeFractionRateDisplay(value) : null; + } + function normalizeExportCellText(value) { + return value?.replace(/\s+/g, " ").trim() ?? ""; + } + function buildMarketExportFieldFallbacks(record, attributeDatas) { + const exportFields = {}; + const authorInfo = buildMarketAuthorInfo(record, attributeDatas); + const authorType = buildMarketAuthorType(record, attributeDatas); + const contentTheme = buildMarketContentTheme(record, attributeDatas); + const connectedUsers = formatWanValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "link_link_cnt_by_industry")) + ); + const followerCount = formatWanValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "follower")) + ); + const expectedCpm = formatDecimalDisplay( + readNumericValue(readMarketFieldValue(record, attributeDatas, "prospective_20_60_cpm")) + ); + const expectedPlayCount = formatWanValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "expected_play_num")) + ); + const interactionRate = formatFractionPercent( + readNumericValue(readMarketFieldValue(record, attributeDatas, "interact_rate_within_30d")) + ); + const finishRate = formatFractionPercent( + readNumericValue(readMarketFieldValue(record, attributeDatas, "play_over_rate_within_30d")) + ); + const burstRate = readBurstRateDisplay( + readNumericValue(readMarketFieldValue(record, attributeDatas, "burst_text_rate")) + ); + const price21To60s = readMarketPrice21To60s(record, attributeDatas); + const representativeVideo = readMarketRepresentativeVideo(record, attributeDatas); + assignExportField(exportFields, "\u8FBE\u4EBA\u4FE1\u606F", authorInfo); + assignExportField(exportFields, "\u4EE3\u8868\u89C6\u9891", representativeVideo); + assignExportField(exportFields, "\u8FBE\u4EBA\u7C7B\u578B", authorType); + assignExportField(exportFields, "\u5185\u5BB9\u4E3B\u9898", contentTheme); + assignExportField(exportFields, "\u8FDE\u63A5\u7528\u6237\u6570", connectedUsers); + assignExportField(exportFields, "\u7C89\u4E1D\u6570", followerCount); + assignExportField(exportFields, "\u9884\u671FCPM", expectedCpm); + assignExportField(exportFields, "\u9884\u671F\u64AD\u653E\u91CF", expectedPlayCount); + assignExportField(exportFields, "\u4E92\u52A8\u7387", interactionRate); + assignExportField(exportFields, "\u5B8C\u64AD\u7387", finishRate); + assignExportField(exportFields, "\u7206\u6587\u7387", burstRate); + assignExportField(exportFields, "21-60s\u62A5\u4EF7", price21To60s); + return Object.keys(exportFields).length > 0 ? exportFields : void 0; + } + function assignExportField(exportFields, key, value) { + if (hasTextValue(value)) { + exportFields[key] = value; + } + } + function hasTextValue(value) { + return Boolean(value && value.trim().length > 0); + } + function buildMarketAuthorInfo(record, attributeDatas) { + const nickname = readString(readMarketFieldValue(record, attributeDatas, "nickname")) ?? readString(readMarketFieldValue(record, attributeDatas, "nick_name")) ?? ""; + const parts = [ + nickname, + readMarketGenderLabel(readMarketFieldValue(record, attributeDatas, "gender")), + readString(readMarketFieldValue(record, attributeDatas, "city")) ?? "" + ].filter((value) => Boolean(value)); + return parts.length > 0 ? parts.join(" ") : void 0; + } + function buildMarketAuthorType(record, attributeDatas) { + const tagsRelation = readRecordLike( + readMarketFieldValue(record, attributeDatas, "tags_relation") + ); + if (tagsRelation) { + const primaryTag = Object.keys(tagsRelation)[0]; + if (hasTextValue(primaryTag)) { + return primaryTag; + } + } + return void 0; + } + function buildMarketContentTheme(record, attributeDatas) { + const themes = readStringArray( + readMarketFieldValue(record, attributeDatas, "content_theme_labels_180d") + ); + if (themes.length === 0) { + return void 0; + } + if (themes.length <= 2) { + return themes.join(" "); + } + return `${themes.slice(0, 2).join(" ")} ${themes.length - 2}+`; + } + function readMarketLocation(record, attributeDatas) { + return readString(readMarketFieldValue(record, attributeDatas, "city")) ?? void 0; + } + function readMarketPrice21To60s(record, attributeDatas) { + return formatCurrencyValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "price_20_60")) + ); + } + function readMarketRepresentativeVideo(record, attributeDatas) { + const items = readArrayLike(readMarketFieldValue(record, attributeDatas, "items")); + for (const item of items) { + if (!isRecord(item)) { + continue; + } + const title = readString(item.title); + if (hasTextValue(title)) { + return normalizeExportCellText(title); + } + } + return void 0; + } + function readMarketGenderLabel(value) { + const rawValue = typeof value === "number" ? String(value) : readString(value); + if (rawValue === "1") { + return "\u7537"; + } + if (rawValue === "2") { + return "\u5973"; + } + return void 0; + } + function readBurstRateDisplay(value) { + if (value === null) { + return void 0; + } + if (value <= 0) { + return "-"; + } + return formatFractionPercent(value); + } + function formatCurrencyValue(value) { + if (value === null) { + return void 0; + } + return `\xA5${value.toLocaleString("en-US", { + maximumFractionDigits: 0 + })}`; + } + function formatWanValue(value) { + if (value === null) { + return void 0; + } + return `${formatDecimalWithGrouping(value / 1e4)}w`; + } + function formatFractionPercent(value) { + if (value === null) { + return void 0; + } + return `${formatDecimalDisplay(value * 100)}%`; + } + function formatDecimalDisplay(value) { + if (value === null) { + return void 0; + } + return value.toLocaleString("en-US", { + maximumFractionDigits: 1, + minimumFractionDigits: 0, + useGrouping: false + }); + } + function formatDecimalWithGrouping(value) { + return value.toLocaleString("en-US", { + maximumFractionDigits: 1, + minimumFractionDigits: 0 + }); + } + function readNumericValue(value) { + if (typeof value === "number" && Number.isFinite(value)) { + return value; + } + if (typeof value === "string") { + const trimmedValue = value.trim(); + if (!trimmedValue) { + return null; + } + const parsedValue = Number(trimmedValue); + return Number.isFinite(parsedValue) ? parsedValue : null; + } + return null; + } + function readStringArray(value) { + if (Array.isArray(value)) { + return value.filter((item) => typeof item === "string"); + } + if (typeof value === "string") { + try { + const parsedValue = JSON.parse(value); + return Array.isArray(parsedValue) ? parsedValue.filter((item) => typeof item === "string") : []; + } catch { + return []; + } + } + return []; + } + function readArrayLike(value) { + if (Array.isArray(value)) { + return value; + } + if (typeof value === "string") { + try { + const parsedValue = JSON.parse(value); + return Array.isArray(parsedValue) ? parsedValue : []; + } catch { + return []; + } + } + return []; + } + function readRecordLike(value) { + if (isRecord(value)) { + return value; + } + if (typeof value === "string") { + try { + const parsedValue = JSON.parse(value); + return isRecord(parsedValue) ? parsedValue : null; + } catch { + return null; + } + } + return null; + } + function readKnownNumber(record, keys) { + for (const key of keys) { + const value = readNumericValue(record[key]); + if (value !== null) { + return value; + } + } + return void 0; + } + function readKnownNumberDeep(value, keys) { + if (!isRecord(value)) { + return null; + } + const directValue = readKnownNumber(value, keys); + if (typeof directValue === "number") { + return directValue; + } + for (const nestedValue of Object.values(value)) { + const candidate = readKnownNumberDeep(unwrapVueRef(nestedValue), keys); + if (typeof candidate === "number") { + return candidate; + } + } + return null; + } + + // src/content/market/dom-sync.ts + var BACKEND_COLUMN_KEY = "backendMetrics"; + var SELECTION_COLUMN_KEY = "selection"; + var SINGLE_COLUMN_KEY = "singleVideoAfterSearchRate"; + var PERSONAL_COLUMN_KEY = "personalVideoAfterSearchRate"; + var ACTION_HEADER_TEXT = "\u64CD\u4F5C"; + var AUTHOR_HEADER_TEXT = "\u8FBE\u4EBA\u4FE1\u606F"; + var BACKEND_HEADER_TEXT = "\u79D2\u63A2\u6307\u6807"; + var MARKET_SCROLL_HINT_TEXT = "\u6A2A\u5411\u6EDA\u52A8\u53EF\u67E5\u770B\u770B\u540E\u641C\u7387\u3001\u79D2\u63A2\u6307\u6807"; + var MARKET_SCROLLBAR_STYLE_ID = "sces-market-scrollbar-style"; + var UNAVAILABLE_RATE_TEXT = "\u6682\u65E0\u6765\u6E90"; + var UNAVAILABLE_BACKEND_METRICS_TEXT = "\u6682\u65E0\u6570\u636E"; + var SERIALIZED_MARKET_ROWS_ATTRIBUTE = "data-sces-market-rows"; + var SORTABLE_RATE_FIELDS = [SINGLE_COLUMN_KEY, PERSONAL_COLUMN_KEY]; + var BACKEND_METRIC_COLUMNS2 = [ + { + field: "afterViewSearchRate", + label: "\u770B\u540E\u641C\u7387" + }, + { + field: "afterViewSearchCount", + label: "\u770B\u540E\u641C\u6570" + }, + { + field: "a3IncreaseCount", + label: "\u65B0\u589EA3\u6570" + }, + { + field: "newA3Rate", + label: "\u65B0\u589EA3\u7387" + }, + { + field: "cpa3", + label: "CPA3" + }, + { + field: "cpSearch", + label: "cp_search" + } + ]; + var SORTABLE_MARKET_FIELDS = [ + ...SORTABLE_RATE_FIELDS, + ...BACKEND_METRIC_COLUMNS2.map((column) => column.field) + ]; + function syncMarketTable(root) { + return syncSyntheticMarketTable(root) ?? syncDivGridMarketTable(root); + } + function readMarketPageSignature(root) { + const document2 = getOwnerDocument(root); + const explicitPageIndex = document2?.documentElement.getAttribute("data-test-page-index") ?? ""; + const activePageIndex = document2?.querySelector(".el-pagination .number.active, .xt-pagination .number.active")?.textContent?.trim() ?? ""; + const authorIds = readRawAuthorIds(root).join("|"); + return `${explicitPageIndex || activePageIndex}::${authorIds}`; + } + function findNextPageControl(root) { + const document2 = getOwnerDocument(root); + if (!document2) { + return null; + } + const explicitControl = document2.querySelector('[data-testid="next-page"]'); + if (explicitControl instanceof document2.defaultView.HTMLElement) { + return explicitControl; + } + const paginationNextControl = document2.querySelector( + ".el-pagination .btn-next, .xt-pagination .btn-next" + ); + if (paginationNextControl instanceof document2.defaultView.HTMLElement) { + return paginationNextControl; + } + const candidates = Array.from( + document2.querySelectorAll("button, a, [role='button']") + ).filter( + (element) => element instanceof document2.defaultView.HTMLElement + ); + return candidates.find( + (element) => /下一页|next/i.test(normalizeExportCellText2(element.textContent)) + ) ?? null; + } + function isPageControlDisabled(control) { + if (!control) { + return true; + } + if (control instanceof HTMLButtonElement) { + return control.disabled; + } + return control.getAttribute("aria-disabled") === "true"; + } + function renderMarketRowState(rowDom, record) { + renderBackendMetricsCells(rowDom.backendMetricsCells, record); + if (record.status === "success" && record.rates) { + rowDom.singleCell.textContent = readRateCellText( + record.rates.singleVideoAfterSearchRate + ); + rowDom.personalCell.textContent = readRateCellText( + record.rates.personalVideoAfterSearchRate + ); + return; + } + if (record.status === "loading") { + rowDom.singleCell.textContent = "\u52A0\u8F7D\u4E2D..."; + rowDom.personalCell.textContent = "\u52A0\u8F7D\u4E2D..."; + return; + } + if (record.status === "failed") { + rowDom.singleCell.textContent = "\u52A0\u8F7D\u5931\u8D25"; + rowDom.personalCell.textContent = "\u52A0\u8F7D\u5931\u8D25"; + return; + } + rowDom.singleCell.textContent = ""; + rowDom.personalCell.textContent = ""; + } + function applyRowVisibility(table, visibleAuthorIds) { + table.rows.forEach((rowDom) => { + const isVisible = visibleAuthorIds.has(rowDom.authorId); + rowDom.visibilityTargets.forEach((target) => { + target.hidden = !isVisible; + }); + }); + } + function applyRowOrder(table, orderedAuthorIds) { + const rowById = new Map(table.rows.map((rowDom) => [rowDom.authorId, rowDom])); + const orderByAuthorId = new Map( + orderedAuthorIds.map((authorId, index) => [authorId, index]) + ); + orderedAuthorIds.forEach((authorId) => { + const rowDom = rowById.get(authorId); + if (!rowDom) { + return; + } + rowDom.orderTargets.forEach(({ container, mode, node }) => { + const visualOrder = orderByAuthorId.get(authorId) ?? orderedAuthorIds.length; + if (mode === "css") { + container.dataset.marketOrderMode = "css"; + container.style.display = "flex"; + container.style.flexDirection = "column"; + node.style.order = String(visualOrder); + return; + } + container.dataset.marketOrderMode = "dom"; + container.appendChild(node); + }); + }); + } + function syncPluginSortHeaders(root, options) { + SORTABLE_MARKET_FIELDS.forEach((field) => { + const cell = root.querySelector( + `[data-market-header-cell="${field}"]` + ); + if (!cell) { + return; + } + syncSortableHeaderCell(cell, { + direction: options.activeSort?.field === field ? options.activeSort.direction : "none", + field, + onToggleSort: options.onToggleSort + }); + }); + } + function syncMarketSelectionState(table, selectedAuthorIds) { + table.rows.forEach((rowDom) => { + rowDom.selectionCheckbox.dataset.marketSelectionAuthorId = rowDom.authorId; + rowDom.selectionCheckbox.checked = selectedAuthorIds.has(rowDom.authorId); + }); + if (!table.headerSelectionCheckbox) { + return; + } + const visibleRows = table.rows.filter( + (rowDom) => rowDom.visibilityTargets.some((target) => !target.hidden) + ); + const scopedRows = visibleRows.length > 0 ? visibleRows : table.rows; + const selectedCount = scopedRows.filter( + (rowDom) => selectedAuthorIds.has(rowDom.authorId) + ).length; + table.headerSelectionCheckbox.indeterminate = selectedCount > 0 && selectedCount < scopedRows.length; + table.headerSelectionCheckbox.checked = scopedRows.length > 0 && selectedCount === scopedRows.length; + table.headerSelectionCheckbox.disabled = scopedRows.length === 0; + } + function syncSyntheticMarketTable(root) { + const header = root.querySelector("[data-market-header]"); + const body = root.querySelector("[data-market-body]"); + if (!header || !body) { + return null; + } + const selectionHeader = ensureSyntheticHeaderCell(header, SELECTION_COLUMN_KEY, ""); + const headerSelectionCheckbox = ensureSelectionHeaderControl(selectionHeader); + ensureSyntheticHeaderCell(header, SINGLE_COLUMN_KEY, "\u5355\u89C6\u9891\u770B\u540E\u641C\u7387"); + ensureSyntheticHeaderCell(header, PERSONAL_COLUMN_KEY, "\u4E2A\u4EBA\u89C6\u9891\u770B\u540E\u641C\u7387"); + BACKEND_METRIC_COLUMNS2.forEach(({ field, label }) => { + ensureSyntheticHeaderCell(header, field, label); + }); + const headerLabelsByField = readSyntheticHeaderLabels(header); + const rows = Array.from(body.querySelectorAll("[data-market-row]")).map( + (rowElement) => { + const row = rowElement; + const selectionCell = ensureSyntheticRowCell(row, SELECTION_COLUMN_KEY); + const selectionCheckbox = ensureSelectionRowControl(selectionCell); + const singleCell = ensureSyntheticRowCell(row, SINGLE_COLUMN_KEY); + const personalCell = ensureSyntheticRowCell(row, PERSONAL_COLUMN_KEY); + const backendMetricsCells = Object.fromEntries( + BACKEND_METRIC_COLUMNS2.map(({ field }) => [field, ensureSyntheticRowCell(row, field)]) + ); + const authorId = row.dataset.authorId ?? ""; + selectionCheckbox.dataset.marketSelectionAuthorId = authorId; + return { + authorId, + authorName: row.querySelector('[data-market-field="authorName"]')?.textContent?.trim() ?? "", + backendMetricsCells, + exportFields: readSyntheticExportFields(row, headerLabelsByField), + hasDirectRatesSource: false, + location: row.querySelector('[data-market-field="location"]')?.textContent?.trim() ?? "", + orderTargets: [ + { + container: body, + mode: "dom", + node: row + } + ], + personalCell, + price21To60s: row.querySelector('[data-market-field="price21To60s"]')?.textContent?.trim() ?? "", + rates: void 0, + row, + selectionCheckbox, + singleCell, + visibilityTargets: [row] + }; + } + ); + return { + headerSelectionCheckbox, + rows + }; + } + function syncDivGridMarketTable(root) { + const document2 = getOwnerDocument(root); + if (!document2) { + return null; + } + for (const marketRoot of document2.querySelectorAll(".base-author-list")) { + if (!(marketRoot instanceof document2.defaultView.HTMLElement)) { + continue; + } + const syncedTable = syncDivGridRoot(marketRoot); + if (syncedTable) { + return syncedTable; + } + } + return null; + } + function readRawAuthorIds(root) { + const document2 = getOwnerDocument(root); + const syntheticAuthorIds = readSyntheticAuthorIds(root); + if (syntheticAuthorIds && syntheticAuthorIds.length > 0) { + return syntheticAuthorIds; + } + const divGridAuthorIds = readDivGridAuthorIds(root); + if (divGridAuthorIds && divGridAuthorIds.length > 0) { + return divGridAuthorIds; + } + if (!document2) { + return []; + } + return readSerializedMarketRows(document2).map((row) => row.authorId).filter((authorId) => Boolean(authorId)); + } + function readSyntheticAuthorIds(root) { + const body = root.querySelector("[data-market-body]"); + if (!body) { + return null; + } + return Array.from(body.querySelectorAll("[data-market-row]")).map( + (row) => row instanceof HTMLElement ? row.dataset.authorId ?? "" : "" + ).filter((authorId) => Boolean(authorId)); + } + function readDivGridAuthorIds(root) { + const document2 = getOwnerDocument(root); + if (!document2) { + return null; + } + const marketRoot = document2.querySelector(".base-author-list"); + if (!(marketRoot instanceof document2.defaultView.HTMLElement)) { + return null; + } + const bodySection = Array.from(marketRoot.querySelectorAll(".section-wrapper")).find( + (section) => section instanceof document2.defaultView.HTMLElement && !section.classList.contains("sticky-header") + ); + const authorSection = bodySection ? Array.from(bodySection.children).find( + (child) => child instanceof document2.defaultView.HTMLElement && child.querySelector(".content-column .content-cell") + ) ?? null : null; + const authorColumn = authorSection ? getNativeAuthorColumn(authorSection) : null; + if (!authorColumn) { + return null; + } + return getDirectContentCells(authorColumn).map((cell) => extractAuthorId(cell)).filter((authorId) => Boolean(authorId)); + } + function syncDivGridRoot(root) { + const headerSection = root.querySelector( + ".section-wrapper.sticky-header" + ); + const bodySection = Array.from(root.querySelectorAll(".section-wrapper")).find( + (section) => section instanceof root.ownerDocument.defaultView.HTMLElement && !section.classList.contains("sticky-header") + ); + if (!headerSection || !bodySection) { + return null; + } + const authorHeader = findCellByText(getDirectHeaderCells(headerSection), AUTHOR_HEADER_TEXT); + const actionHeader = findCellByText(getDirectHeaderCells(headerSection), ACTION_HEADER_TEXT); + if (!authorHeader || !actionHeader) { + return null; + } + const rightHeaderSection = actionHeader.parentElement; + if (!(rightHeaderSection instanceof root.ownerDocument.defaultView.HTMLElement)) { + return null; + } + const middleHeaderSection = findPreviousNativeSection(rightHeaderSection) ?? rightHeaderSection; + const authorSection = getIndexedChild( + bodySection, + getDirectChildIndex(headerSection, authorHeader) + ); + const authorHeaderSection = getIndexedChild( + headerSection, + getDirectChildIndex(headerSection, authorHeader) + ); + const rightSection = getIndexedChild( + bodySection, + getDirectChildIndex(headerSection, actionHeader) + ); + if (!authorSection || !authorHeaderSection || !rightSection) { + return null; + } + const middleBodySection = findPreviousNativeSection(rightSection) ?? rightSection; + const pluginHeaderSection = ensurePluginSection(headerSection, rightHeaderSection, { + testId: "plugin-header", + type: "header" + }); + const pluginBodySection = ensurePluginSection(bodySection, rightSection, { + testId: "plugin-section", + type: "body" + }); + const authorColumn = getNativeAuthorColumn(authorSection); + const actionColumn = getActionColumn(rightSection); + if (!authorColumn || !actionColumn) { + return null; + } + const rowCount = getDirectContentCells(authorColumn).length; + const selectionHeaderCell = ensureDivHeaderCell( + authorHeaderSection, + authorHeader, + SELECTION_COLUMN_KEY, + "" + ); + const headerSelectionCheckbox = ensureSelectionHeaderControl(selectionHeaderCell); + const selectionColumn = ensureDivBodyColumn( + authorSection, + authorColumn, + SELECTION_COLUMN_KEY, + rowCount + ); + const headerTemplateCell = getDirectHeaderCells(middleHeaderSection).at(-1) ?? findPreviousHeaderCell(actionHeader) ?? actionHeader; + const bodyTemplateColumn = getDirectContentColumns(middleBodySection).at(-1) ?? findPreviousColumn(actionColumn) ?? actionColumn; + ensureDivHeaderCell( + pluginHeaderSection, + headerTemplateCell, + SINGLE_COLUMN_KEY, + "\u5355\u89C6\u9891\u770B\u540E\u641C\u7387" + ); + ensureDivHeaderCell( + pluginHeaderSection, + headerTemplateCell, + PERSONAL_COLUMN_KEY, + "\u4E2A\u4EBA\u89C6\u9891\u770B\u540E\u641C\u7387" + ); + const singleColumn = ensureDivBodyColumn( + pluginBodySection, + bodyTemplateColumn, + SINGLE_COLUMN_KEY, + rowCount + ); + const personalColumn = ensureDivBodyColumn( + pluginBodySection, + bodyTemplateColumn, + PERSONAL_COLUMN_KEY, + rowCount + ); + const backendMetricColumns = Object.fromEntries( + BACKEND_METRIC_COLUMNS2.map(({ field, label }) => { + ensureDivHeaderCell(pluginHeaderSection, headerTemplateCell, field, label); + return [ + field, + ensureDivBodyColumn( + pluginBodySection, + bodyTemplateColumn, + field, + rowCount + ) + ]; + }) + ); + syncContainerWidth(pluginHeaderSection); + syncContainerWidth(pluginBodySection); + syncContainerWidth(authorHeaderSection); + syncContainerWidth(authorSection); + ensureVisibleHorizontalScroll(headerSection); + ensureVisibleHorizontalScroll(bodySection); + ensureScrollHint(root, headerSection); + const allBodyColumns = Array.from(bodySection.children).flatMap( + (section) => section instanceof root.ownerDocument.defaultView.HTMLElement ? getDirectContentColumns(section) : [] + ); + const allHeaderCells = Array.from(headerSection.children).flatMap( + (section) => section instanceof root.ownerDocument.defaultView.HTMLElement ? getDirectHeaderCells(section) : [] + ); + const authorCells = getDirectContentCells(authorColumn); + const selectionCells = getDirectContentCells(selectionColumn); + const singleCells = getDirectContentCells(singleColumn); + const personalCells = getDirectContentCells(personalColumn); + const backendMetricCellsByField = Object.fromEntries( + BACKEND_METRIC_COLUMNS2.map(({ field }) => [ + field, + getDirectContentCells(backendMetricColumns[field]) + ]) + ); + const priceColumn = findPreviousColumn(actionColumn); + const priceCells = priceColumn ? getDirectContentCells(priceColumn) : []; + const remainingVueMarketRows = [...readVueMarketRows(root)]; + const remainingSerializedMarketRows = [...readSerializedMarketRows(root.ownerDocument)]; + const rows = authorCells.flatMap((authorCell, index) => { + const selectionCell = selectionCells[index] ?? null; + const singleCell = singleCells[index] ?? null; + const personalCell = personalCells[index] ?? null; + const backendMetricsCells = Object.fromEntries( + BACKEND_METRIC_COLUMNS2.map(({ field }) => [ + field, + backendMetricCellsByField[field][index] ?? null + ]) + ); + if (!selectionCell || !singleCell || !personalCell || Object.values(backendMetricsCells).some((cell) => cell === null)) { + return []; + } + const selectionCheckbox = ensureSelectionRowControl(selectionCell); + const alignedRowCells = allBodyColumns.map( + (column) => getDirectContentCells(column)[index] ?? null + ); + const rowCells = alignedRowCells.filter( + (cell) => cell !== null + ); + const directAuthorId = extractAuthorId(authorCell) || ""; + const directAuthorName = extractAuthorName(authorCell) || ""; + const vueMarketRow = takeMatchedMarketDataRow( + remainingVueMarketRows, + directAuthorId, + directAuthorName + ); + const serializedMarketRow = takeMatchedMarketDataRow( + remainingSerializedMarketRows, + directAuthorId, + directAuthorName + ); + const fallbackMarketRow = mergeMarketDataRows(serializedMarketRow, vueMarketRow); + const exportFields = mergeExportFieldMaps( + readExportFieldsForDivGridRow(allHeaderCells, alignedRowCells), + fallbackMarketRow?.exportFields + ); + const authorId = directAuthorId || fallbackMarketRow?.authorId || ""; + const authorName = directAuthorName || fallbackMarketRow?.authorName || ""; + const price21To60s = mergeNonEmptyString( + readDivGridPriceDisplay(priceCells[index]?.textContent), + fallbackMarketRow?.price21To60s + ); + selectionCheckbox.dataset.marketSelectionAuthorId = authorId; + return [ + { + authorId, + authorName, + backendMetricsCells, + exportFields, + hasDirectRatesSource: fallbackMarketRow?.hasDirectRatesSource ?? false, + location: fallbackMarketRow?.location, + orderTargets: rowCells.map((cell) => { + const container = cell.parentElement; + if (!(container instanceof root.ownerDocument.defaultView.HTMLElement)) { + return null; + } + return { + container, + mode: "css", + node: cell + }; + }).filter((target) => target !== null), + personalCell, + price21To60s, + rates: fallbackMarketRow?.rates, + row: authorCell, + selectionCheckbox, + singleCell, + visibilityTargets: rowCells + } + ]; + }); + return { + headerSelectionCheckbox, + rows + }; + } + function ensureSyntheticHeaderCell(header, field, label) { + const existingCell = header.querySelector( + `[data-market-header-cell="${field}"]` + ); + if (existingCell) { + existingCell.textContent = label; + return existingCell; + } + const nextCell = header.ownerDocument.createElement("div"); + nextCell.dataset.marketHeaderCell = field; + nextCell.textContent = label; + if (field === SELECTION_COLUMN_KEY) { + header.insertBefore(nextCell, header.firstChild); + } else { + header.appendChild(nextCell); + } + return nextCell; + } + function ensureSyntheticRowCell(row, field) { + const existingCell = row.querySelector( + `[data-market-row-cell="${field}"]` + ); + if (existingCell) { + return existingCell; + } + const nextCell = row.ownerDocument.createElement(field === BACKEND_COLUMN_KEY ? "div" : "span"); + nextCell.dataset.marketRowCell = field; + if (field === SELECTION_COLUMN_KEY) { + row.insertBefore(nextCell, row.firstChild); + } else { + row.appendChild(nextCell); + } + return nextCell; + } + function ensureDivHeaderCell(container, templateCell, field, label) { + const existingCell = container.querySelector( + `[data-market-header-cell="${field}"]` + ); + if (existingCell) { + existingCell.textContent = label; + applyPluginHeaderCellStyles(existingCell); + return existingCell; + } + const nextCell = cloneElementShallow(templateCell); + nextCell.dataset.marketHeaderCell = field; + nextCell.textContent = label; + applyColumnWidth(nextCell, field); + applyPluginHeaderCellStyles(nextCell); + if (field === SELECTION_COLUMN_KEY) { + container.insertBefore(nextCell, templateCell); + } else { + container.appendChild(nextCell); + } + return nextCell; + } + function ensureDivBodyColumn(container, templateColumn, field, rowCount) { + const existingColumn = container.querySelector( + `[data-market-column-group="${field}"]` + ); + if (existingColumn) { + syncDivColumnCells(existingColumn, templateColumn, field, rowCount); + return existingColumn; + } + const nextColumn = cloneElementShallow(templateColumn); + nextColumn.dataset.marketColumnGroup = field; + applyColumnWidth(nextColumn, field); + syncDivColumnCells(nextColumn, templateColumn, field, rowCount); + if (field === SELECTION_COLUMN_KEY) { + container.insertBefore(nextColumn, templateColumn); + } else { + container.appendChild(nextColumn); + } + return nextColumn; + } + function syncDivColumnCells(column, templateColumn, field, rowCount) { + const currentCells = getDirectContentCells(column); + while (currentCells.length > rowCount) { + currentCells.pop()?.remove(); + } + const templateCells = getDirectContentCells(templateColumn); + for (let index = 0; index < rowCount; index += 1) { + const existingCell = getDirectContentCells(column)[index] ?? null; + if (existingCell) { + existingCell.dataset.marketRowCell = field; + applyPluginContentCellStyles(existingCell); + continue; + } + const templateCell = templateCells[index] ?? templateCells[templateCells.length - 1] ?? null; + const nextCell = field === SELECTION_COLUMN_KEY ? templateCell ? createSelectionContentCell(templateCell) : createBareContentCell(column.ownerDocument) : templateCell ? cloneElementShallow(templateCell) : createBareContentCell(column.ownerDocument); + nextCell.dataset.marketRowCell = field; + applyColumnWidth(nextCell, field); + applyPluginContentCellStyles(nextCell); + nextCell.textContent = ""; + column.appendChild(nextCell); + } + } + function applyPluginHeaderCellStyles(cell) { + cell.style.display = "flex"; + cell.style.alignItems = "center"; + cell.style.justifyContent = "normal"; + cell.style.cursor = "pointer"; + cell.style.whiteSpace = "nowrap"; + } + function applyPluginContentCellStyles(cell) { + cell.style.display = "flex"; + cell.style.alignItems = "center"; + cell.style.justifyContent = "normal"; + cell.style.paddingTop = "12px"; + cell.style.paddingBottom = "12px"; + cell.style.boxSizing = "border-box"; + cell.style.whiteSpace = "nowrap"; + } + function ensureSelectionHeaderControl(cell) { + cell.textContent = ""; + cell.style.gap = "6px"; + cell.style.justifyContent = "center"; + const checkbox = ensureSelectionCheckbox(cell, "header"); + const label = cell.querySelector( + '[data-market-selection-label="header"]' + ); + if (label) { + label.textContent = "\u5168\u9009"; + return checkbox; + } + const nextLabel = cell.ownerDocument.createElement("span"); + nextLabel.dataset.marketSelectionLabel = "header"; + nextLabel.textContent = "\u5168\u9009"; + nextLabel.style.fontSize = "12px"; + cell.appendChild(nextLabel); + return checkbox; + } + function ensureSelectionRowControl(cell) { + cell.textContent = ""; + cell.style.justifyContent = "center"; + return ensureSelectionCheckbox(cell, "row"); + } + function ensureSelectionCheckbox(container, kind) { + const existingCheckbox = container.querySelector( + `[data-market-selection-checkbox="${kind}"]` + ); + if (existingCheckbox) { + existingCheckbox.type = "checkbox"; + return existingCheckbox; + } + const checkbox = container.ownerDocument.createElement("input"); + checkbox.type = "checkbox"; + checkbox.dataset.marketSelectionCheckbox = kind; + checkbox.style.cursor = "pointer"; + container.appendChild(checkbox); + return checkbox; + } + function getOwnerDocument(root) { + if ("ownerDocument" in root && root.ownerDocument) { + return root.ownerDocument; + } + return "nodeType" in root && root.nodeType === 9 ? root : null; + } + function readSyntheticHeaderLabels(header) { + return Array.from(header.querySelectorAll("[data-market-header-cell]")).reduce((labels, cell) => { + if (!(cell instanceof header.ownerDocument.defaultView.HTMLElement)) { + return labels; + } + const field = cell.dataset.marketHeaderCell; + if (!field) { + return labels; + } + labels[field] = normalizeExportCellText2(cell.textContent); + return labels; + }, {}); + } + function readSyntheticExportFields(row, headerLabelsByField) { + const exportFields = {}; + for (const cell of row.querySelectorAll("[data-market-field]")) { + if (!(cell instanceof row.ownerDocument.defaultView.HTMLElement)) { + continue; + } + const field = cell.dataset.marketField; + const headerLabel = field ? headerLabelsByField[field] : ""; + if (!shouldExportColumn(headerLabel)) { + continue; + } + exportFields[headerLabel] = normalizeExportCellText2(cell.textContent); + } + return exportFields; + } + function readExportFieldsForDivGridRow(headerCells, rowCells) { + const exportFields = {}; + rowCells.forEach((cell, index) => { + const headerLabel = normalizeExportCellText2(headerCells[index]?.textContent); + if (!shouldExportColumn(headerLabel)) { + return; + } + exportFields[headerLabel] = headerLabel === "21-60s\u62A5\u4EF7" ? readDivGridPriceDisplay(cell?.textContent) ?? "" : normalizeExportCellText2(cell?.textContent); + }); + return exportFields; + } + function findPreviousHeaderCell(cell) { + let current = cell.previousElementSibling; + while (current) { + if (current instanceof cell.ownerDocument.defaultView.HTMLElement && current.classList.contains("header-cell")) { + return current; + } + current = current.previousElementSibling; + } + return null; + } + function findPreviousColumn(column) { + let current = column.previousElementSibling; + while (current) { + if (current instanceof column.ownerDocument.defaultView.HTMLElement && current.classList.contains("content-column")) { + return current; + } + current = current.previousElementSibling; + } + return null; + } + function ensurePluginSection(rootSection, referenceSection, options) { + const existingSection = rootSection.querySelector( + `[data-market-plugin-section="${options.type}"]` + ); + if (existingSection) { + existingSection.dataset.testid = options.testId; + existingSection.setAttribute("data-testid", options.testId); + return existingSection; + } + const templateSection = findPreviousSection(referenceSection) ?? referenceSection; + const nextSection = cloneElementShallow(templateSection); + nextSection.dataset.marketPluginSection = options.type; + nextSection.dataset.testid = options.testId; + nextSection.setAttribute("data-testid", options.testId); + resetStickySectionStyles(nextSection); + rootSection.insertBefore(nextSection, referenceSection); + return nextSection; + } + function ensureVisibleHorizontalScroll(section) { + ensureVisibleScrollbarStyles(section.ownerDocument); + section.classList.remove("hide-scrollbar"); + section.dataset.marketScrollbar = "visible"; + section.style.overflowX = "auto"; + section.style.scrollbarWidth = "thin"; + section.style.scrollbarColor = "rgba(148, 163, 184, 0.95) rgba(226, 232, 240, 0.9)"; + } + function ensureVisibleScrollbarStyles(document2) { + if (document2.getElementById(MARKET_SCROLLBAR_STYLE_ID)) { + return; + } + const style = document2.createElement("style"); + style.id = MARKET_SCROLLBAR_STYLE_ID; + style.textContent = ` + [data-market-scrollbar="visible"]::-webkit-scrollbar { + display: block !important; + height: 10px !important; + } + + [data-market-scrollbar="visible"]::-webkit-scrollbar-track { + background: rgba(226, 232, 240, 0.9) !important; + border-radius: 999px; + } + + [data-market-scrollbar="visible"]::-webkit-scrollbar-thumb { + background: rgba(148, 163, 184, 0.95) !important; + border: 2px solid rgba(226, 232, 240, 0.9); + border-radius: 999px; + } + `; + document2.head.appendChild(style); + } + function ensureScrollHint(root, headerSection) { + const existingHint = root.querySelector( + '[data-testid="market-scroll-hint"]' + ); + if (existingHint) { + existingHint.textContent = MARKET_SCROLL_HINT_TEXT; + return; + } + const hint = root.ownerDocument.createElement("div"); + hint.dataset.testid = "market-scroll-hint"; + hint.setAttribute("data-testid", "market-scroll-hint"); + hint.textContent = MARKET_SCROLL_HINT_TEXT; + hint.style.color = "#64748b"; + hint.style.display = "flex"; + hint.style.fontSize = "12px"; + hint.style.justifyContent = "flex-end"; + hint.style.lineHeight = "18px"; + hint.style.padding = "0 12px 8px"; + root.insertBefore(hint, headerSection); + } + function findPreviousSection(section) { + let current = section.previousElementSibling; + while (current) { + if (current instanceof section.ownerDocument.defaultView.HTMLElement) { + return current; + } + current = current.previousElementSibling; + } + return null; + } + function findPreviousNativeSection(section) { + let current = section.previousElementSibling; + while (current) { + if (current instanceof section.ownerDocument.defaultView.HTMLElement && !current.hasAttribute("data-market-plugin-section")) { + return current; + } + current = current.previousElementSibling; + } + return null; + } + function resetStickySectionStyles(section) { + section.style.position = ""; + section.style.left = ""; + section.style.right = ""; + section.style.zIndex = ""; + section.style.width = ""; + section.style.minWidth = ""; + } + function getActionColumn(bodySection) { + const columns = getDirectContentColumns(bodySection); + return columns[columns.length - 1] ?? null; + } + function getNativeAuthorColumn(authorSection) { + return getDirectContentColumns(authorSection).find( + (column) => !column.dataset.marketColumnGroup && getDirectContentCells(column).some( + (cell) => cell.querySelector("a") || cell.querySelector(".author-nickname") || Boolean(cell.dataset.authorId) + ) + ) ?? null; + } + function getDirectHeaderCells(section) { + return Array.from(section.querySelectorAll(".header-cell")).filter( + (cell) => cell instanceof section.ownerDocument.defaultView.HTMLElement + ); + } + function getDirectContentColumns(section) { + return Array.from(section.children).filter( + (child) => child instanceof section.ownerDocument.defaultView.HTMLElement && child.classList.contains("content-column") + ); + } + function getDirectContentCells(column) { + return Array.from(column.children).filter( + (child) => child instanceof column.ownerDocument.defaultView.HTMLElement && child.classList.contains("content-cell") + ); + } + function getDirectChildIndex(root, descendant) { + const directChild = Array.from(root.children).find((child) => child.contains(descendant)); + return directChild ? Array.from(root.children).indexOf(directChild) : -1; + } + function getIndexedChild(root, index) { + if (index < 0) { + return null; + } + const child = root.children[index] ?? null; + return child instanceof root.ownerDocument.defaultView.HTMLElement ? child : null; + } + function findCellByText(cells, text) { + return cells.find((cell) => cell.textContent?.trim() === text) ?? null; + } + function cloneElementShallow(reference) { + const clone = reference.ownerDocument.createElement(reference.tagName); + Array.from(reference.attributes).forEach((attribute) => { + clone.setAttribute(attribute.name, attribute.value); + }); + return clone; + } + function createBareContentCell(document2) { + const cell = document2.createElement("div"); + cell.className = "content-cell"; + return cell; + } + function createSelectionContentCell(templateCell) { + const cell = cloneElementShallow(templateCell); + cell.removeAttribute("data-testid"); + cell.removeAttribute("data-author-id"); + return cell; + } + function extractAuthorId(authorCell) { + const explicitAuthorId = authorCell.dataset.authorId; + if (explicitAuthorId) { + return explicitAuthorId; + } + const linkedAuthorId = Array.from(authorCell.querySelectorAll("a")).map((link) => extractAuthorIdFromHref(link.href)).find((value) => Boolean(value)); + if (linkedAuthorId) { + return linkedAuthorId; + } + const fallbackAuthorId = authorCell.querySelector("[data-author-id]")?.getAttribute("data-author-id"); + return fallbackAuthorId ?? ""; + } + function extractAuthorName(authorCell) { + return authorCell.querySelector(".author-nickname")?.textContent?.trim() ?? authorCell.textContent?.trim() ?? ""; + } + function extractAuthorIdFromHref(href) { + const match = href.match(/\/author-homepage\/[^/]+\/(\d+)/); + return match?.[1] ?? null; + } + function readVueMarketRows(marketRoot) { + const vueRoot = marketRoot.__vue__; + const setupStates = collectVueSetupStates(vueRoot); + for (const setupState of setupStates) { + for (const value of Object.values(setupState)) { + const candidate = unwrapVueRef2(value); + if (!candidate || typeof candidate !== "object") { + continue; + } + const marketList = unwrapVueRef2( + candidate.marketList + ); + if (!Array.isArray(marketList)) { + continue; + } + return marketList.map((row) => isRecord2(row) ? mapMarketListRow(row) : null).filter((row) => row !== null); + } + } + return []; + } + function collectVueSetupStates(vueRoot) { + if (!vueRoot) { + return []; + } + const queue = [vueRoot]; + const setupStates = []; + while (queue.length > 0) { + const current = queue.shift(); + if (!isRecord2(current)) { + continue; + } + if (isRecord2(current._setupState)) { + setupStates.push(current._setupState); + } + const children = Array.isArray(current.$children) ? current.$children : []; + queue.push(...children); + } + return setupStates; + } + function readSerializedMarketRows(document2) { + const serializedRows = document2.documentElement.getAttribute( + SERIALIZED_MARKET_ROWS_ATTRIBUTE + ); + if (!serializedRows) { + return []; + } + try { + const parsedRows = JSON.parse(serializedRows); + if (!Array.isArray(parsedRows)) { + return []; + } + return parsedRows.map((row) => { + const record = isRecord2(row) ? row : {}; + const singleVideoAfterSearchRate = readString2( + record.singleVideoAfterSearchRate + ); + return { + authorId: readString2(record.authorId) ?? "", + authorName: readString2(record.authorName) ?? "", + exportFields: readSerializedExportFields(record), + hasDirectRatesSource: Boolean(singleVideoAfterSearchRate), + location: readString2(record.location) ?? void 0, + price21To60s: readString2(record.price21To60s) ?? void 0, + rates: singleVideoAfterSearchRate ? { + singleVideoAfterSearchRate + } : void 0 + }; + }).filter((row) => Boolean(row.authorId || row.authorName)); + } catch { + return []; + } + } + function unwrapVueRef2(value) { + if (isRecord2(value) && "value" in value) { + return value.value; + } + return value; + } + function isRecord2(value) { + return typeof value === "object" && value !== null; + } + function readString2(value) { + return typeof value === "string" ? value : null; + } + function normalizeExportCellText2(value) { + return value?.replace(/\s+/g, " ").trim() ?? ""; + } + function readDivGridPriceDisplay(value) { + const normalizedValue = normalizeExportCellText2(value); + if (!normalizedValue) { + return void 0; + } + const match = normalizedValue.match(/^¥?\s*([\d,]+(?:\.\d+)?)$/); + if (!match) { + return void 0; + } + const numericValue = Number(match[1].replace(/,/g, "")); + if (!Number.isFinite(numericValue)) { + return void 0; + } + return formatCurrencyValue2(numericValue); + } + function shouldExportColumn(label) { + const excludedBackendLabels = new Set(BACKEND_METRIC_COLUMNS2.map((column) => column.label)); + return Boolean( + label && label !== ACTION_HEADER_TEXT && label !== BACKEND_HEADER_TEXT && !excludedBackendLabels.has(label) && label !== "\u5355\u89C6\u9891\u770B\u540E\u641C\u7387" && label !== "\u4E2A\u4EBA\u89C6\u9891\u770B\u540E\u641C\u7387" + ); + } + function syncSortableHeaderCell(cell, options) { + const label = readSortableHeaderLabel(cell); + const sorterRoot = ensureHeaderSorterRoot(cell); + const text = ensureHeaderSorterText(sorterRoot); + const icon = ensureHeaderSorterIcon(sorterRoot); + const upTriangle = ensureHeaderTriangle(icon, "up"); + const downTriangle = ensureHeaderTriangle(icon, "down"); + text.textContent = label; + cell.dataset.marketSortField = options.field; + cell.dataset.marketSortDirection = options.direction; + cell.setAttribute("role", "button"); + cell.tabIndex = 0; + cell.onclick = () => { + options.onToggleSort(options.field); + }; + cell.onkeydown = (event) => { + if (event.key !== "Enter" && event.key !== " ") { + return; + } + event.preventDefault(); + options.onToggleSort(options.field); + }; + syncTriangleStyles(upTriangle, { + active: options.direction === "asc", + direction: "up" + }); + syncTriangleStyles(downTriangle, { + active: options.direction === "desc", + direction: "down" + }); + } + function readSortableHeaderLabel(cell) { + return cell.dataset.marketHeaderLabel ?? normalizeExportCellText2(cell.textContent) ?? ""; + } + function ensureHeaderSorterRoot(cell) { + const existingRoot = cell.querySelector( + '[data-market-sorter="root"]' + ); + if (existingRoot) { + return existingRoot; + } + cell.dataset.marketHeaderLabel = normalizeExportCellText2(cell.textContent); + cell.replaceChildren(); + const root = cell.ownerDocument.createElement("span"); + root.dataset.marketSorter = "root"; + root.style.alignItems = "center"; + root.style.display = "inline-flex"; + root.style.gap = "4px"; + root.style.maxWidth = "100%"; + cell.appendChild(root); + return root; + } + function ensureHeaderSorterText(sorterRoot) { + const existingText = sorterRoot.querySelector( + '[data-market-sorter="text"]' + ); + if (existingText) { + return existingText; + } + const text = sorterRoot.ownerDocument.createElement("span"); + text.dataset.marketSorter = "text"; + text.style.display = "inline-block"; + text.style.lineHeight = "20px"; + text.style.whiteSpace = "nowrap"; + sorterRoot.appendChild(text); + return text; + } + function ensureHeaderSorterIcon(sorterRoot) { + const existingIcon = sorterRoot.querySelector( + '[data-market-sorter="icon"]' + ); + if (existingIcon) { + return existingIcon; + } + const icon = sorterRoot.ownerDocument.createElement("span"); + icon.dataset.marketSorter = "icon"; + icon.style.display = "inline-flex"; + icon.style.flexDirection = "column"; + icon.style.gap = "2px"; + icon.style.justifyContent = "center"; + icon.style.minWidth = "8px"; + sorterRoot.appendChild(icon); + return icon; + } + function ensureHeaderTriangle(iconRoot, direction) { + const existingTriangle = iconRoot.querySelector( + `[data-market-sorter-triangle="${direction}"]` + ); + if (existingTriangle) { + return existingTriangle; + } + const triangle = iconRoot.ownerDocument.createElement("span"); + triangle.dataset.marketSorterTriangle = direction; + triangle.style.display = "block"; + triangle.style.height = "0"; + triangle.style.width = "0"; + triangle.style.borderLeft = "4px solid transparent"; + triangle.style.borderRight = "4px solid transparent"; + iconRoot.appendChild(triangle); + return triangle; + } + function syncTriangleStyles(triangle, options) { + const activeColor = "#1f2329"; + const inactiveColor = "#c9cdd4"; + if (options.direction === "up") { + triangle.style.borderBottom = `5px solid ${options.active ? activeColor : inactiveColor}`; + triangle.style.borderTop = "0 solid transparent"; + } else { + triangle.style.borderTop = `5px solid ${options.active ? activeColor : inactiveColor}`; + triangle.style.borderBottom = "0 solid transparent"; + } + } + function readRateCellText(value) { + return value ? normalizeRateDisplay(value) : UNAVAILABLE_RATE_TEXT; + } + function applyColumnWidth(element, field) { + if (field === SELECTION_COLUMN_KEY) { + element.style.minWidth = "56px"; + element.style.width = "56px"; + } + if (field === BACKEND_COLUMN_KEY) { + element.style.minWidth = "240px"; + element.style.width = "240px"; + } + if (field === SINGLE_COLUMN_KEY || field === PERSONAL_COLUMN_KEY) { + element.style.minWidth = "160px"; + element.style.width = "160px"; + } + if (BACKEND_METRIC_COLUMNS2.some((column) => column.field === field)) { + element.style.minWidth = "120px"; + element.style.width = "120px"; + } + } + function syncContainerWidth(container) { + if (!(container instanceof HTMLElement)) { + return; + } + const directChildren = Array.from(container.children).filter( + (child) => child instanceof HTMLElement + ); + const totalWidth = directChildren.reduce((sum, child) => { + return sum + readElementWidth(child); + }, 0); + if (totalWidth <= 0) { + return; + } + container.style.width = `${totalWidth}px`; + container.style.minWidth = `${totalWidth}px`; + } + function readElementWidth(element) { + const styleWidth = Number.parseFloat(element.style.width || ""); + if (Number.isFinite(styleWidth) && styleWidth > 0) { + return styleWidth; + } + const minWidth = Number.parseFloat(element.style.minWidth || ""); + if (Number.isFinite(minWidth) && minWidth > 0) { + return minWidth; + } + return 0; + } + function mergeMarketDataRows(baseRow, preferredRow) { + if (!baseRow && !preferredRow) { + return null; + } + if (!baseRow) { + return preferredRow; + } + if (!preferredRow) { + return baseRow; + } + return { + authorId: preferredRow.authorId || baseRow.authorId, + authorName: preferredRow.authorName || baseRow.authorName, + exportFields: mergeExportFieldMaps(baseRow.exportFields, preferredRow.exportFields), + hasDirectRatesSource: preferredRow.hasDirectRatesSource || baseRow.hasDirectRatesSource, + location: mergeNonEmptyString(baseRow.location, preferredRow.location), + price21To60s: mergeNonEmptyString( + baseRow.price21To60s, + preferredRow.price21To60s + ), + rates: mergeRates(baseRow.rates, preferredRow.rates) + }; + } + function takeMatchedMarketDataRow(remainingRows, authorId, authorName) { + if (remainingRows.length === 0) { + return null; + } + const matchedIndex = remainingRows.findIndex((row) => { + if (authorId && row.authorId === authorId) { + return true; + } + if (authorName && row.authorName === authorName) { + return true; + } + return false; + }); + if (matchedIndex >= 0) { + return remainingRows.splice(matchedIndex, 1)[0] ?? null; + } + if (!authorId && !authorName) { + return remainingRows.shift() ?? null; + } + return null; + } + function mergeExportFieldMaps(current, fallback) { + if (!current && !fallback) { + return void 0; + } + const nextFields = { + ...current ?? {} + }; + Object.entries(fallback ?? {}).forEach(([key, value]) => { + if (!hasTextValue2(nextFields[key]) && hasTextValue2(value)) { + nextFields[key] = value; + } + }); + return nextFields; + } + function mergeRates(current, fallback) { + if (!current && !fallback) { + return void 0; + } + return { + singleVideoAfterSearchRate: current?.singleVideoAfterSearchRate ?? fallback?.singleVideoAfterSearchRate, + personalVideoAfterSearchRate: current?.personalVideoAfterSearchRate ?? fallback?.personalVideoAfterSearchRate + }; + } + function mergeNonEmptyString(current, fallback) { + return hasTextValue2(current) ? current : fallback; + } + function formatCurrencyValue2(value) { + if (value === null) { + return void 0; + } + return `\xA5${value.toLocaleString("en-US", { + maximumFractionDigits: 0 + })}`; + } + function readSerializedExportFields(record) { + if (!isRecord2(record.exportFields)) { + return void 0; + } + const entries = Object.entries(record.exportFields).flatMap( + ([key, value]) => typeof value === "string" ? [[key, value]] : [] + ); + return entries.length > 0 ? Object.fromEntries(entries) : void 0; + } + function hasTextValue2(value) { + return typeof value === "string" && value.trim().length > 0; + } + function renderBackendMetricsCells(cells, record) { + if (record.backendMetricsStatus === "loading" || record.status === "loading" && !record.backendMetricsStatus) { + fillBackendMetricCells(cells, "\u52A0\u8F7D\u4E2D..."); + return; + } + if (record.backendMetricsStatus === "failed") { + fillBackendMetricCells(cells, "\u52A0\u8F7D\u5931\u8D25"); + return; + } + if (record.backendMetricsStatus === "missing") { + fillBackendMetricCells(cells, UNAVAILABLE_BACKEND_METRICS_TEXT); + return; + } + if (record.backendMetricsStatus !== "success" || !record.backendMetrics) { + fillBackendMetricCells(cells, ""); + return; + } + BACKEND_METRIC_COLUMNS2.forEach(({ field }) => { + cells[field].textContent = record.backendMetrics?.[field] ?? ""; + }); + } + function fillBackendMetricCells(cells, value) { + BACKEND_METRIC_COLUMNS2.forEach(({ field }) => { + cells[field].textContent = value; + }); + } + + // src/content/market/filter-sort-controller.ts + function applyFilterAndSort(records, options = {}) { + const filteredRecords = records.filter( + (record) => matchesFilters(record, options.filters) + ); + if (!options.sort) { + return filteredRecords; + } + return [...filteredRecords].sort( + (leftRecord, rightRecord) => compareRecords(leftRecord, rightRecord, options.sort) + ); + } + function matchesFilters(record, filters) { + if (!filters) { + return true; + } + return meetsThreshold( + record.rates?.singleVideoAfterSearchRate, + filters.singleVideoAfterSearchRateMin + ) && meetsThreshold( + record.rates?.personalVideoAfterSearchRate, + filters.personalVideoAfterSearchRateMin + ); + } + function meetsThreshold(rateValue, minValue) { + if (minValue == null) { + return true; + } + const lowerBound = parseRateLowerBound(rateValue ?? null); + return lowerBound != null && lowerBound >= minValue; + } + function compareRecords(leftRecord, rightRecord, sort) { + if (isRateSortField(sort.field)) { + return compareRateSortRecords(leftRecord, rightRecord, sort); + } + return compareBackendMetricRecords(leftRecord, rightRecord, sort); + } + function compareRateSortRecords(leftRecord, rightRecord, sort) { + const field = sort.field; + const leftValue = leftRecord.rates?.[field]; + const rightValue = rightRecord.rates?.[field]; + const leftLowerBound = parseRateLowerBound(leftValue ?? null); + const rightLowerBound = parseRateLowerBound(rightValue ?? null); + if (leftLowerBound == null && rightLowerBound == null) { + return compareRecordIdentity(leftRecord, rightRecord); + } + if (leftLowerBound == null) { + return 1; + } + if (rightLowerBound == null) { + return -1; + } + if (leftLowerBound !== rightLowerBound) { + return sort.direction === "asc" ? leftLowerBound - rightLowerBound : rightLowerBound - leftLowerBound; + } + const tieBreak = compareRateValues(leftValue, rightValue); + if (tieBreak !== 0) { + return sort.direction === "asc" ? tieBreak : -tieBreak; + } + return compareRecordIdentity(leftRecord, rightRecord); + } + function compareBackendMetricRecords(leftRecord, rightRecord, sort) { + const field = sort.field; + const leftValue = parseBackendMetricValue(leftRecord.backendMetrics?.[field]); + const rightValue = parseBackendMetricValue(rightRecord.backendMetrics?.[field]); + if (leftValue == null && rightValue == null) { + return compareRecordIdentity(leftRecord, rightRecord); + } + if (leftValue == null) { + return 1; + } + if (rightValue == null) { + return -1; + } + if (leftValue !== rightValue) { + return sort.direction === "asc" ? leftValue - rightValue : rightValue - leftValue; + } + return compareRecordIdentity(leftRecord, rightRecord); + } + function parseBackendMetricValue(value) { + if (!value) { + return null; + } + const normalizedValue = value.replace(/,/g, "").replace(/%/g, "").trim(); + if (!normalizedValue) { + return null; + } + const numericValue = Number(normalizedValue); + return Number.isFinite(numericValue) ? numericValue : null; + } + function isRateSortField(field) { + return field === "singleVideoAfterSearchRate" || field === "personalVideoAfterSearchRate"; + } + function compareRecordIdentity(leftRecord, rightRecord) { + const authorIdCompare = leftRecord.authorId.localeCompare(rightRecord.authorId); + if (authorIdCompare !== 0) { + return authorIdCompare; + } + return leftRecord.authorName.localeCompare(rightRecord.authorName); + } + + // src/content/market/api-client.ts + function createMarketApiClient(options = {}) { + const baseUrl = options.baseUrl ?? resolveBaseUrl(); + const fetchImpl = options.fetchImpl ?? defaultFetch; + const timeoutMs = options.timeoutMs ?? 8e3; + return { + async loadAuthorAseInfo(authorId) { + const primaryResult = await loadAuthorMetricsFromUrl( + buildAuthorCommerceSeedBaseInfoUrl(authorId, baseUrl) + ); + if (primaryResult.success || primaryResult.reason === "timeout") { + return primaryResult; + } + return loadAuthorMetricsFromUrl(buildAuthorAseInfoUrl(authorId, baseUrl)); + } + }; + async function loadAuthorMetricsFromUrl(url) { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), timeoutMs); + try { + const response = await fetchImpl(url, { + credentials: "include", + method: "GET", + signal: controller.signal + }); + if (!response.ok) { + return { + success: false, + reason: "request-failed" + }; + } + return mapAuthorAseInfoResponse(await response.json()); + } catch (error) { + if (isAbortError(error) || controller.signal.aborted) { + return { + success: false, + reason: "timeout" + }; + } + return { + success: false, + reason: "request-failed" + }; + } finally { + clearTimeout(timeoutId); + } + } + } + function buildAuthorAseInfoUrl(authorId, baseUrl) { + const url = new URL("/gw/api/aggregator/get_author_ase_info", baseUrl); + url.searchParams.set("author_id", authorId); + url.searchParams.set("range", "30"); + return url.toString(); + } + function buildAuthorCommerceSeedBaseInfoUrl(authorId, baseUrl) { + const url = new URL( + "/gw/api/aggregator/get_author_commerce_seed_base_info", + baseUrl + ); + url.searchParams.set("o_author_id", authorId); + url.searchParams.set("range", "90"); + return url.toString(); + } + function mapAuthorAseInfoResponse(payload) { + const data = getPayloadData(payload); + if (!data) { + return { + success: false, + reason: "bad-response" + }; + } + const singleVideoAfterSearchRate = readNormalizedRate( + data.avg_search_after_view_rate + ); + const personalVideoAfterSearchRate = readNormalizedRate( + data.personal_avg_search_after_view_rate + ); + if (!singleVideoAfterSearchRate && !personalVideoAfterSearchRate) { + return { + success: false, + reason: "missing-rate" + }; + } + return { + success: true, + rates: { + ...singleVideoAfterSearchRate ? { singleVideoAfterSearchRate } : {}, + ...personalVideoAfterSearchRate ? { personalVideoAfterSearchRate } : {} + } + }; + } + function getPayloadData(payload) { + if (!isRecord3(payload)) { + return null; + } + return isRecord3(payload.data) ? payload.data : payload; + } + function readNormalizedRate(value) { + return typeof value === "string" ? normalizeRateDisplay(value) : null; + } + function resolveBaseUrl() { + if (typeof location !== "undefined" && location.origin) { + return location.origin; + } + return "https://xingtu.cn"; + } + async function defaultFetch(input, init) { + return fetch(input, init); + } + function isAbortError(error) { + return error instanceof Error && error.name === "AbortError"; + } + function isRecord3(value) { + return typeof value === "object" && value !== null; + } + + // src/content/market/export-range-controller.ts + function createExportRangeController(options) { + return { + async exportRecords(target) { + const mergedRecords = /* @__PURE__ */ new Map(); + let currentPage = 0; + let expectedMinimumRowCount; + while (true) { + currentPage += 1; + options.onProgress?.({ + currentPage, + totalPages: target.mode === "count" ? target.pageCount : void 0 + }); + const currentPageRecords = await preparePageRecords(expectedMinimumRowCount); + if (!currentPageRecords) { + throw new Error(`\u7B2C ${currentPage} \u9875\u52A0\u8F7D\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`); + } + currentPageRecords.forEach((record) => { + const existingRecord = mergedRecords.get(record.authorId); + mergedRecords.set(record.authorId, mergeMarketRecord(existingRecord, record)); + }); + expectedMinimumRowCount = Math.max( + expectedMinimumRowCount ?? 0, + currentPageRecords.length + ); + if (target.mode === "count" && currentPage >= target.pageCount) { + break; + } + const previousSignature = readMarketPageSignature(options.document); + const nextPageControl = findNextPageControl(options.document); + if (!nextPageControl || isPageControlDisabled(nextPageControl)) { + break; + } + nextPageControl.click(); + const pageChanged = await waitForPageChange(previousSignature); + if (!pageChanged) { + throw new Error(`\u7B2C ${currentPage + 1} \u9875\u5BFC\u51FA\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`); + } + } + return Array.from(mergedRecords.values()); + } + }; + async function preparePageRecords(expectedMinimumRowCount) { + for (let attempt = 0; attempt < 4; attempt += 1) { + const currentPageReady = await waitForCurrentPageReady(); + if (!currentPageReady) { + return null; + } + await options.prepareCurrentPageForExport(); + const currentPageRecords = options.readCurrentPageRecords(); + if (currentPageRecords.length > 0 && (typeof expectedMinimumRowCount !== "number" || expectedMinimumRowCount <= 0 || isCurrentPageTerminal() || currentPageRecords.length >= expectedMinimumRowCount)) { + return currentPageRecords; + } + } + return null; + } + async function waitForPageChange(previousSignature) { + const previousPageState = parsePageSignature(previousSignature); + for (let attempt = 0; attempt < 60; attempt += 1) { + await new Promise((resolve) => { + options.window.setTimeout(resolve, 50); + }); + await Promise.resolve(); + const nextSignature = readMarketPageSignature(options.document); + const nextPageState = parsePageSignature(nextSignature); + if (hasLoadedNextPage(previousPageState, nextPageState)) { + return true; + } + } + return false; + } + async function waitForCurrentPageReady() { + let stableAttemptCount = 0; + let lastReadyFingerprint = ""; + for (let attempt = 0; attempt < 80; attempt += 1) { + await new Promise((resolve) => { + options.window.setTimeout(resolve, 150); + }); + await Promise.resolve(); + const pageState = readCurrentPageState(); + if (!pageState.authorIds || pageState.rowCount <= 0) { + stableAttemptCount = 0; + lastReadyFingerprint = ""; + continue; + } + const readyFingerprint = [ + pageState.pageToken, + pageState.authorIds, + String(pageState.rowCount), + pageState.isTerminalPage ? "terminal" : "paged" + ].join("::"); + if (readyFingerprint === lastReadyFingerprint) { + stableAttemptCount += 1; + } else { + lastReadyFingerprint = readyFingerprint; + stableAttemptCount = 1; + } + if (stableAttemptCount >= 6) { + return true; + } + } + return false; + } + function readCurrentPageState() { + const pageSignature = parsePageSignature(readMarketPageSignature(options.document)); + const nextPageControl = findNextPageControl(options.document); + return { + authorIds: pageSignature.authorIds, + isTerminalPage: isPageControlDisabled(nextPageControl), + pageToken: pageSignature.pageToken, + rowCount: options.readCurrentPageRowCount() + }; + } + function isCurrentPageTerminal() { + return isPageControlDisabled(findNextPageControl(options.document)); + } + } + function parsePageSignature(signature) { + const separatorIndex = signature.indexOf("::"); + if (separatorIndex < 0) { + return { + authorIds: "", + pageToken: signature.trim() + }; + } + return { + authorIds: signature.slice(separatorIndex + 2).trim(), + pageToken: signature.slice(0, separatorIndex).trim() + }; + } + function hasLoadedNextPage(previousPageState, nextPageState) { + if (!nextPageState.authorIds) { + return false; + } + if (nextPageState.pageToken || previousPageState.pageToken) { + return nextPageState.pageToken !== previousPageState.pageToken; + } + return nextPageState.authorIds !== previousPageState.authorIds; + } + function mergeMarketRecord(existingRecord, incomingRecord) { + if (!existingRecord) { + return { + ...incomingRecord, + exportFields: mergeFieldMap(void 0, incomingRecord.exportFields), + rates: mergeFieldMap(void 0, incomingRecord.rates) + }; + } + return { + ...existingRecord, + ...incomingRecord, + authorName: mergeStringValue(existingRecord.authorName, incomingRecord.authorName) ?? "", + exportFields: mergeFieldMap( + existingRecord.exportFields, + incomingRecord.exportFields + ), + failureReason: incomingRecord.failureReason ?? existingRecord.failureReason, + hasDirectRatesSource: existingRecord.hasDirectRatesSource || incomingRecord.hasDirectRatesSource, + location: mergeStringValue(existingRecord.location, incomingRecord.location), + price21To60s: mergeStringValue( + existingRecord.price21To60s, + incomingRecord.price21To60s + ), + rates: mergeFieldMap(existingRecord.rates, incomingRecord.rates), + status: mergeStatus(existingRecord.status, incomingRecord.status) + }; + } + function mergeFieldMap(current, incoming) { + if (!current && !incoming) { + return void 0; + } + const merged = { + ...current ?? {} + }; + Object.entries(incoming ?? {}).forEach(([key, value]) => { + const currentValue = merged[key]; + if (hasTextValue3(value) || !hasTextValue3(currentValue)) { + merged[key] = value; + } + }); + return merged; + } + function mergeStatus(current, incoming) { + const priority = { + failed: 1, + idle: 0, + loading: 2, + missing: -1, + success: 3 + }; + return priority[incoming] >= priority[current] ? incoming : current; + } + function mergeStringValue(current, incoming) { + if (hasTextValue3(incoming) || !hasTextValue3(current)) { + return incoming ?? current; + } + return current; + } + function hasTextValue3(value) { + return typeof value === "string" && value.trim().length > 0; + } + + // src/content/market/plugin-toolbar.ts + var PLUGIN_ACTION_BUTTON_STYLE_ID = "sces-plugin-action-button-style"; + function isPluginToolbarMounted(root, document2) { + const actionRow = findNativeActionRow(document2); + return Boolean(actionRow && root.parentElement === actionRow && !root.hidden); + } + function ensurePluginToolbar(document2, handlers) { + ensurePluginActionButtonTheme(document2); + const existingRoot = document2.querySelector( + "[data-plugin-toolbar='root']" + ); + if (existingRoot) { + ensureToolbarMounted(existingRoot, document2); + return readToolbarDom(existingRoot); + } + const root = document2.createElement("section"); + root.dataset.pluginToolbar = "root"; + applyToolbarRootStyles(root); + const exportRangeSelect = document2.createElement("select"); + exportRangeSelect.dataset.pluginExportRange = "select"; + appendOption(exportRangeSelect, "current", "\u5F53\u524D\u9875"); + appendOption(exportRangeSelect, "first-5", "\u524D5\u9875"); + appendOption(exportRangeSelect, "first-10", "\u524D10\u9875"); + appendOption(exportRangeSelect, "all", "\u5168\u90E8"); + appendOption(exportRangeSelect, "custom", "\u81EA\u5B9A\u4E49"); + exportRangeSelect.value = "first-5"; + const exportCustomPagesInput = document2.createElement("input"); + exportCustomPagesInput.type = "number"; + exportCustomPagesInput.min = "1"; + exportCustomPagesInput.step = "1"; + exportCustomPagesInput.hidden = true; + exportCustomPagesInput.placeholder = "\u9875\u6570"; + exportCustomPagesInput.dataset.pluginExportCustomPages = "input"; + const exportButton = document2.createElement("button"); + exportButton.type = "button"; + exportButton.dataset.pluginExport = "button"; + exportButton.textContent = "\u5BFC\u51FACSV"; + const batchSubmitButton = document2.createElement("button"); + batchSubmitButton.type = "button"; + batchSubmitButton.dataset.pluginBatchSubmit = "button"; + batchSubmitButton.textContent = "\u63D0\u4EA4\u6279\u6B21"; + const exportStatusText = document2.createElement("span"); + exportStatusText.dataset.pluginExportStatus = "text"; + applyStatusStyles(exportStatusText); + root.append( + exportRangeSelect, + exportCustomPagesInput, + exportButton, + batchSubmitButton, + exportStatusText + ); + document2.body.appendChild(root); + applyNativeControlStyles(document2, { + batchSubmitButton, + exportButton, + exportCustomPagesInput, + exportRangeSelect + }); + ensureToolbarMounted(root, document2); + exportButton.addEventListener("click", () => { + void handlers.onExport(); + }); + batchSubmitButton.addEventListener("click", () => { + void handlers.onSubmitBatch(); + }); + exportRangeSelect.addEventListener("change", () => { + syncCustomPagesInputVisibility({ + batchSubmitButton, + exportButton, + exportCustomPagesInput, + exportRangeSelect, + exportStatusText, + root + }); + }); + const toolbarDom = { + batchSubmitButton, + exportButton, + exportCustomPagesInput, + exportRangeSelect, + exportStatusText, + root + }; + syncCustomPagesInputVisibility(toolbarDom); + return toolbarDom; + } + function appendOption(select, value, label) { + const option = select.ownerDocument.createElement("option"); + option.value = value; + option.textContent = label; + select.appendChild(option); + } + function readToolbarDom(root) { + const toolbarDom = { + batchSubmitButton: root.querySelector( + '[data-plugin-batch-submit="button"]' + ), + exportButton: root.querySelector( + '[data-plugin-export="button"]' + ), + exportCustomPagesInput: root.querySelector( + '[data-plugin-export-custom-pages="input"]' + ), + exportRangeSelect: root.querySelector( + '[data-plugin-export-range="select"]' + ), + exportStatusText: root.querySelector( + '[data-plugin-export-status="text"]' + ), + root + }; + syncCustomPagesInputVisibility(toolbarDom); + return toolbarDom; + } + function readToolbarExportTarget(toolbar) { + const scope = toolbar.exportRangeSelect.value; + if (scope === "all") { + return { + target: { + mode: "all" + } + }; + } + if (scope === "current") { + return { + target: { + mode: "count", + pageCount: 1 + } + }; + } + if (scope === "first-5") { + return { + target: { + mode: "count", + pageCount: 5 + } + }; + } + if (scope === "first-10") { + return { + target: { + mode: "count", + pageCount: 10 + } + }; + } + const pageCount = Number(toolbar.exportCustomPagesInput.value); + if (!Number.isInteger(pageCount) || pageCount < 1) { + return { + error: "\u8BF7\u8F93\u5165\u6709\u6548\u9875\u6570" + }; + } + return { + target: { + mode: "count", + pageCount + } + }; + } + function setToolbarBusyState(toolbar, isBusy) { + [ + toolbar.batchSubmitButton, + toolbar.exportButton, + toolbar.exportRangeSelect, + toolbar.exportCustomPagesInput + ].forEach((element) => { + element.disabled = isBusy; + }); + } + function setToolbarExportStatus(toolbar, text) { + toolbar.exportStatusText.textContent = text; + } + function syncCustomPagesInputVisibility(toolbar) { + toolbar.exportCustomPagesInput.hidden = toolbar.exportRangeSelect.value !== "custom"; + } + function ensureToolbarMounted(root, document2) { + const actionRow = findNativeActionRow(document2); + if (!actionRow) { + root.hidden = true; + return; + } + const customizeButton = findNativeActionButton(actionRow, "\u81EA\u5B9A\u4E49\u6307\u6807"); + const insertionAnchor = customizeButton ? findDirectChildAnchor(actionRow, customizeButton) : null; + if (insertionAnchor) { + actionRow.insertBefore(root, insertionAnchor); + } else if (root.parentElement !== actionRow) { + actionRow.prepend(root); + } + root.hidden = false; + } + function findNativeActionRow(document2) { + const customizeButton = findNativeActionButton(document2, "\u81EA\u5B9A\u4E49\u6307\u6807"); + const exportButton = findNativeActionButton(document2, "\u5BFC\u51FA"); + const header = findHeaderContainer(customizeButton, exportButton); + const sharedActionRow = customizeButton && exportButton ? findSmallestSharedActionRow(customizeButton, exportButton, header) : null; + if (sharedActionRow) { + return sharedActionRow; + } + const scope = header ?? document2; + const candidates = Array.from( + scope.querySelectorAll(".xt-space.xt-space--medium, .search-content--header") + ).filter( + (element) => element instanceof document2.defaultView.HTMLElement + ); + const rankedCandidates = candidates.filter( + (candidate) => isNativeActionRowCandidate(candidate, customizeButton, exportButton) + ).sort((left, right) => { + const depthDelta = getDepthWithinAncestor(right, header) - getDepthWithinAncestor(left, header); + if (depthDelta !== 0) { + return depthDelta; + } + return normalizeText(left.textContent).length - normalizeText(right.textContent).length; + }); + return rankedCandidates[0] ?? null; + } + function findHeaderContainer(customizeButton, exportButton) { + return customizeButton?.closest(".search-content--header") ?? exportButton?.closest(".search-content--header"); + } + function findSmallestSharedActionRow(customizeButton, exportButton, boundary) { + const exportAncestors = new Set(collectAncestorChain(exportButton, boundary)); + for (const candidate of collectAncestorChain(customizeButton, boundary)) { + if (exportAncestors.has(candidate) && isNativeActionRowCandidate(candidate, customizeButton, exportButton)) { + return candidate; + } + } + return null; + } + function collectAncestorChain(element, boundary) { + const ancestors = []; + let current = element.parentElement; + while (current) { + ancestors.push(current); + if (current === boundary) { + break; + } + current = current.parentElement; + } + return ancestors; + } + function isNativeActionRowCandidate(candidate, customizeButton, exportButton) { + if (customizeButton && !candidate.contains(customizeButton)) { + return false; + } + if (exportButton && !candidate.contains(exportButton)) { + return false; + } + const directChildLabels = Array.from(candidate.children).flatMap((child) => { + const buttons = []; + if (child instanceof candidate.ownerDocument.defaultView.HTMLButtonElement) { + buttons.push(child); + } + buttons.push(...Array.from(child.querySelectorAll("button"))); + return buttons; + }).map((button) => normalizeText(button.textContent)); + return directChildLabels.includes("\u5BFC\u51FA") && (directChildLabels.includes("\u81EA\u5B9A\u4E49\u6307\u6807") || Boolean(customizeButton)); + } + function getDepthWithinAncestor(element, boundary) { + let depth = 0; + let current = element.parentElement; + while (current && current !== boundary) { + depth += 1; + current = current.parentElement; + } + return depth; + } + function findNativeActionButton(root, text) { + const document2 = root instanceof Document ? root : root.ownerDocument; + if (!document2) { + return null; + } + const candidates = Array.from(root.querySelectorAll("button")).filter( + (element) => element instanceof document2.defaultView.HTMLElement + ); + return candidates.find((element) => normalizeText(element.textContent) === text) ?? null; + } + function applyToolbarRootStyles(root) { + root.style.display = "inline-flex"; + root.style.alignItems = "center"; + root.style.columnGap = "8px"; + root.style.flexWrap = "wrap"; + } + function applyNativeControlStyles(document2, controls) { + const primaryButton = findButtonContainingText(document2, "\u53D1\u5E03\u4EFB\u52A1") ?? findButtonContainingText(document2, "+\u53D1\u5E03\u4EFB\u52A1"); + const nativeButton = primaryButton ?? findNativeActionButton(document2, "\u81EA\u5B9A\u4E49\u6307\u6807") ?? findNativeActionButton(document2, "\u5BFC\u51FA"); + if (nativeButton) { + controls.exportButton.className = nativeButton.className; + controls.batchSubmitButton.className = nativeButton.className; + } + [controls.exportButton, controls.batchSubmitButton].forEach((button) => { + applyPrimaryButtonStyles2(button); + button.style.whiteSpace = "nowrap"; + }); + [controls.exportRangeSelect, controls.exportCustomPagesInput].forEach((element) => { + element.style.height = "32px"; + element.style.border = "1px solid #d0d7de"; + element.style.borderRadius = "6px"; + element.style.padding = "0 10px"; + element.style.background = "#fff"; + element.style.color = "#1f2329"; + element.style.boxSizing = "border-box"; + }); + controls.exportRangeSelect.style.minWidth = "104px"; + controls.exportCustomPagesInput.style.width = "72px"; + } + function applyPrimaryButtonStyles2(button) { + button.style.backgroundColor = "#7f1d2d"; + button.style.border = "1px solid #7f1d2d"; + button.style.borderRadius = "8px"; + button.style.color = "#ffffff"; + button.style.height = "32px"; + button.style.padding = "0 15px"; + button.style.boxSizing = "border-box"; + button.style.fontWeight = "600"; + button.style.transition = "background-color 0.16s ease, border-color 0.16s ease, box-shadow 0.16s ease, transform 0.16s ease"; + } + function applyStatusStyles(statusText) { + statusText.style.color = "#64748b"; + statusText.style.fontSize = "12px"; + statusText.style.lineHeight = "20px"; + statusText.style.marginLeft = "4px"; + statusText.style.whiteSpace = "nowrap"; + } + function ensurePluginActionButtonTheme(document2) { + if (document2.getElementById(PLUGIN_ACTION_BUTTON_STYLE_ID)) { + return; + } + const style = document2.createElement("style"); + style.id = PLUGIN_ACTION_BUTTON_STYLE_ID; + style.textContent = ` + [data-plugin-export="button"]:hover:not(:disabled), + [data-plugin-batch-submit="button"]:hover:not(:disabled) { + background-color: #6d1627 !important; + border-color: #6d1627 !important; + } + + [data-plugin-export="button"]:active:not(:disabled), + [data-plugin-batch-submit="button"]:active:not(:disabled) { + background-color: #58111f !important; + border-color: #58111f !important; + transform: translateY(1px); + } + + [data-plugin-export="button"]:focus-visible, + [data-plugin-batch-submit="button"]:focus-visible { + outline: none !important; + box-shadow: 0 0 0 3px rgba(127, 29, 45, 0.2) !important; + } + + [data-plugin-export="button"]:disabled, + [data-plugin-batch-submit="button"]:disabled { + background-color: #c89ca4 !important; + border-color: #c89ca4 !important; + color: rgba(255, 255, 255, 0.95) !important; + cursor: not-allowed !important; + opacity: 1 !important; + transform: none !important; + box-shadow: none !important; + } + `; + document2.head.appendChild(style); + } + function normalizeText(value) { + return value?.replace(/\s+/g, " ").trim() ?? ""; + } + function findButtonContainingText(root, text) { + const document2 = root instanceof Document ? root : root.ownerDocument; + if (!document2) { + return null; + } + const candidates = Array.from(root.querySelectorAll("button")).filter( + (element) => element instanceof document2.defaultView.HTMLElement + ); + return candidates.find((element) => normalizeText(element.textContent).includes(text)) ?? null; + } + function findDirectChildAnchor(ancestor, descendant) { + let current = descendant; + let previous = null; + while (current && current !== ancestor) { + previous = current; + current = current.parentElement; + } + return current === ancestor ? previous : null; + } + + // src/content/market/market-list-request-snapshot.ts + var MARKET_REQUEST_SNAPSHOT_ATTRIBUTE = "data-sces-market-request-snapshot"; + var MARKET_SEARCH_ENDPOINT_PATH = "/gw/api/gsearch/search_for_author_square"; + function readMarketListRequestSnapshot(document2) { + const serializedSnapshot = document2.documentElement.getAttribute( + MARKET_REQUEST_SNAPSHOT_ATTRIBUTE + ); + if (!serializedSnapshot) { + return readMarketListRequestSnapshotFromPageState(document2); + } + try { + const parsedSnapshot = normalizeMarketListRequestSnapshot( + JSON.parse(serializedSnapshot) + ); + if (!parsedSnapshot) { + return readMarketListRequestSnapshotFromPageState(document2); + } + return parsedSnapshot; + } catch { + return readMarketListRequestSnapshotFromPageState(document2); + } + } + function isMarketListRequestSnapshot(value) { + if (!value || typeof value !== "object") { + return false; + } + const candidate = value; + return typeof candidate.method === "string" && typeof candidate.url === "string" && (!("body" in candidate) || typeof candidate.body === "string") && (!("headers" in candidate) || isStringRecord(candidate.headers)); + } + function normalizeMarketListRequestSnapshot(value) { + if (!value || typeof value !== "object") { + return null; + } + const candidate = value; + const normalizedSnapshot = { + body: typeof candidate.body === "string" ? candidate.body : void 0, + method: typeof candidate.method === "string" ? candidate.method : void 0, + url: typeof candidate.url === "string" ? candidate.url : void 0 + }; + if (candidate.headers && typeof candidate.headers === "object") { + normalizedSnapshot.headers = Object.fromEntries( + Object.entries(candidate.headers).filter( + ([, entry]) => ["string", "number", "boolean"].includes(typeof entry) + ).map(([key, entry]) => [key, String(entry)]) + ); + } + return isMarketListRequestSnapshot(normalizedSnapshot) ? normalizedSnapshot : null; + } + function isStringRecord(value) { + if (!value || typeof value !== "object") { + return false; + } + return Object.values(value).every((entry) => typeof entry === "string"); + } + function readMarketListRequestSnapshotFromPageState(document2) { + const reqParams = findMarketReqParams(document2); + if (!reqParams) { + return null; + } + return { + body: JSON.stringify(reqParams), + method: "POST", + url: buildMarketSearchUrl(document2) + }; + } + function findMarketReqParams(document2) { + const marketRoot = document2.querySelector(".base-author-list"); + const setupState = marketRoot?.__vue__?._setupState; + if (!setupState) { + return null; + } + const queue = Object.values(setupState); + while (queue.length > 0) { + const current = unwrapVueRef3(queue.shift()); + if (!isRecord4(current)) { + continue; + } + const reqParams = unwrapVueRef3(current.reqParams); + if (isRecord4(reqParams)) { + return reqParams; + } + Object.values(current).forEach((value) => { + queue.push(value); + }); + } + return null; + } + function buildMarketSearchUrl(document2) { + if (document2.location?.origin && document2.location.origin !== "null" && document2.location.origin !== "about:blank") { + return document2.location.origin.includes("xingtu.cn") ? MARKET_SEARCH_ENDPOINT_PATH : new URL(MARKET_SEARCH_ENDPOINT_PATH, document2.location.origin).toString(); + } + return MARKET_SEARCH_ENDPOINT_PATH; + } + function unwrapVueRef3(value) { + if (isRecord4(value) && "value" in value) { + return value.value; + } + return value; + } + function isRecord4(value) { + return typeof value === "object" && value !== null; + } + + // src/content/market/silent-export-controller.ts + var PAGE_NUMBER_KEYS2 = [ + "currentPage", + "page", + "pageNo", + "pageNum", + "page_no", + "page_num" + ]; + function createSilentExportController(options) { + const fetchImpl = options.fetchImpl ?? defaultFetch2; + return { + async exportRecords(target) { + const snapshot = readMarketListRequestSnapshot(options.document); + if (!snapshot) { + return null; + } + const baseRequest = createPagedRequest(snapshot); + if (!baseRequest) { + return null; + } + const mergedRecords = /* @__PURE__ */ new Map(); + const maxPageCount = target.mode === "count" ? target.pageCount : 200; + let totalPagesHint; + for (let offset = 0; offset < maxPageCount; offset += 1) { + const pageNumber = baseRequest.initialPage + offset; + options.onProgress?.({ + currentPage: offset + 1, + totalPages: target.mode === "count" ? target.pageCount : totalPagesHint + }); + const payload = await fetchPagePayload(fetchImpl, baseRequest, pageNumber); + const parsedResponse = parseMarketListResponse(payload); + if (!parsedResponse) { + return null; + } + totalPagesHint = parsedResponse.totalPages ?? totalPagesHint; + if (parsedResponse.records.length === 0) { + break; + } + parsedResponse.records.forEach((record) => { + const existingRecord = mergedRecords.get(record.authorId); + mergedRecords.set(record.authorId, mergeMarketRecord2(existingRecord, record)); + }); + if (target.mode === "count" && offset + 1 >= target.pageCount) { + break; + } + if (target.mode === "all") { + if (typeof parsedResponse.totalPages === "number" && pageNumber >= parsedResponse.totalPages) { + break; + } + if (typeof parsedResponse.pageSize === "number" && parsedResponse.records.length < parsedResponse.pageSize) { + break; + } + } + } + return Array.from(mergedRecords.values()); + } + }; + } + function createPagedRequest(snapshot) { + const bodyPage = readPageFromBody(snapshot.body); + if (bodyPage !== null) { + return { + initialPage: bodyPage, + pageSource: "body", + snapshot + }; + } + const urlPage = readPageFromUrl(snapshot.url); + if (urlPage !== null) { + return { + initialPage: urlPage, + pageSource: "url", + snapshot + }; + } + return { + initialPage: 1, + pageSource: "none", + snapshot + }; + } + async function fetchPagePayload(fetchImpl, request, pageNumber) { + const nextUrl = request.pageSource === "url" ? mutateUrlPage(request.snapshot.url, pageNumber) : request.snapshot.url; + const nextBody = mutateBodyPage(request.snapshot.body, pageNumber); + const response = await fetchImpl(nextUrl, { + body: nextBody, + credentials: "include", + headers: filterReplayHeaders(request.snapshot.headers, nextBody), + method: request.snapshot.method + }); + if (!response.ok) { + throw new Error("\u9759\u9ED8\u5BFC\u51FA\u8BF7\u6C42\u5931\u8D25"); + } + return response.json(); + } + function readPageFromUrl(url) { + try { + const parsedUrl = new URL(url); + for (const key of PAGE_NUMBER_KEYS2) { + const value = readNumericString(parsedUrl.searchParams.get(key)); + if (value !== null) { + return value; + } + } + } catch { + return null; + } + return null; + } + function mutateUrlPage(url, pageNumber) { + try { + const parsedUrl = new URL(url); + for (const key of PAGE_NUMBER_KEYS2) { + if (!parsedUrl.searchParams.has(key)) { + continue; + } + parsedUrl.searchParams.set(key, String(pageNumber)); + return parsedUrl.toString(); + } + parsedUrl.searchParams.set("page", String(pageNumber)); + return parsedUrl.toString(); + } catch { + return url; + } + } + function readPageFromBody(body) { + const parsedBody = parseBody(body); + if (!parsedBody) { + return null; + } + return readKnownPaginationNumber(parsedBody, "page"); + } + function mutateBodyPage(body, pageNumber) { + if (!body) { + return body; + } + const trimmedBody = body.trim(); + if (!trimmedBody) { + return body; + } + try { + const parsedJson = JSON.parse(trimmedBody); + if (!replacePageNumberInValue(parsedJson, pageNumber) && isRecord5(parsedJson)) { + parsedJson.page = pageNumber; + } + return JSON.stringify(parsedJson); + } catch { + const searchParams = new URLSearchParams(trimmedBody); + for (const key of PAGE_NUMBER_KEYS2) { + if (!searchParams.has(key)) { + continue; + } + searchParams.set(key, String(pageNumber)); + return searchParams.toString(); + } + searchParams.set("page", String(pageNumber)); + return searchParams.toString(); + } + } + function parseBody(body) { + if (!body) { + return null; + } + const trimmedBody = body.trim(); + if (!trimmedBody) { + return null; + } + try { + const parsedBody = JSON.parse(trimmedBody); + return isRecord5(parsedBody) ? parsedBody : null; + } catch { + const searchParams = new URLSearchParams(trimmedBody); + const payload = {}; + searchParams.forEach((value, key) => { + payload[key] = value; + }); + return payload; + } + } + function replacePageNumberInValue(value, pageNumber) { + if (!isRecord5(value)) { + return false; + } + let replaced = false; + PAGE_NUMBER_KEYS2.forEach((key) => { + if (!(key in value)) { + return; + } + value[key] = pageNumber; + replaced = true; + }); + if (replaced) { + return true; + } + return Object.values(value).some((entry) => replacePageNumberInValue(entry, pageNumber)); + } + function filterReplayHeaders(headers, body) { + const filteredHeaders = Object.fromEntries( + Object.entries(headers ?? {}).filter(([key]) => { + const normalizedKey = key.toLowerCase(); + return normalizedKey !== "content-length" && normalizedKey !== "host"; + }) + ); + if (body) { + if (!hasHeader(filteredHeaders, "accept")) { + filteredHeaders.Accept = "application/json, text/plain, */*"; + } + if (!hasHeader(filteredHeaders, "content-type")) { + filteredHeaders["Content-Type"] = "application/json"; + } + if (!hasHeader(filteredHeaders, "x-login-source")) { + filteredHeaders["x-login-source"] = "1"; + } + if (!hasHeader(filteredHeaders, "agw-js-conv")) { + filteredHeaders["Agw-Js-Conv"] = "str"; + } + } + return Object.keys(filteredHeaders).length > 0 ? filteredHeaders : void 0; + } + function hasHeader(headers, key) { + return Object.keys(headers).some((headerKey) => headerKey.toLowerCase() === key); + } + function readNumericString(value) { + if (!value) { + return null; + } + const parsedValue = Number(value); + return Number.isFinite(parsedValue) ? parsedValue : null; + } + async function defaultFetch2(input, init) { + return fetch(input, init); + } + function isRecord5(value) { + return typeof value === "object" && value !== null; + } + function mergeMarketRecord2(existingRecord, incomingRecord) { + if (!existingRecord) { + return { + ...incomingRecord, + exportFields: mergeFieldMap2(void 0, incomingRecord.exportFields), + rates: mergeFieldMap2(void 0, incomingRecord.rates), + status: incomingRecord.status ?? "idle" + }; + } + return { + ...existingRecord, + ...incomingRecord, + authorName: mergeStringValue2(existingRecord.authorName, incomingRecord.authorName) ?? "", + exportFields: mergeFieldMap2( + existingRecord.exportFields, + incomingRecord.exportFields + ), + failureReason: incomingRecord.failureReason ?? existingRecord.failureReason, + hasDirectRatesSource: existingRecord.hasDirectRatesSource || incomingRecord.hasDirectRatesSource, + location: mergeStringValue2(existingRecord.location, incomingRecord.location), + price21To60s: mergeStringValue2( + existingRecord.price21To60s, + incomingRecord.price21To60s + ), + rates: mergeFieldMap2(existingRecord.rates, incomingRecord.rates), + status: incomingRecord.status ?? existingRecord.status + }; + } + function mergeFieldMap2(current, incoming) { + if (!current && !incoming) { + return void 0; + } + const merged = { + ...current ?? {} + }; + Object.entries(incoming ?? {}).forEach(([key, value]) => { + const currentValue = merged[key]; + if (hasTextValue4(value) || !hasTextValue4(currentValue)) { + merged[key] = value; + } + }); + return merged; + } + function mergeStringValue2(current, incoming) { + return hasTextValue4(incoming) ? incoming : current; + } + function hasTextValue4(value) { + return Boolean(value && value.trim().length > 0); + } + + // src/content/market/result-store.ts + function createMarketResultStore() { + const records = /* @__PURE__ */ new Map(); + return { + getRecord(authorId) { + return records.get(authorId) ?? null; + }, + listRecords() { + return Array.from(records.values()); + }, + setAuthorFailed(authorId, reason) { + const existingRecord = ensureRecord(authorId); + existingRecord.status = "failed"; + existingRecord.failureReason = reason; + }, + setAuthorLoading(authorId) { + const existingRecord = ensureRecord(authorId); + existingRecord.status = "loading"; + delete existingRecord.failureReason; + }, + setBackendMetricsFailed(authorId) { + const existingRecord = ensureRecord(authorId); + existingRecord.backendMetricsStatus = "failed"; + }, + setBackendMetricsLoading(authorId) { + const existingRecord = ensureRecord(authorId); + existingRecord.backendMetricsStatus = "loading"; + }, + setBackendMetricsMissing(authorId) { + const existingRecord = ensureRecord(authorId); + existingRecord.backendMetricsStatus = "missing"; + }, + setBackendMetricsSuccess(authorId, backendMetrics) { + const existingRecord = ensureRecord(authorId); + existingRecord.backendMetricsStatus = "success"; + existingRecord.backendMetrics = { + ...existingRecord.backendMetrics, + ...backendMetrics + }; + }, + setAuthorSuccess(authorId, rates) { + const existingRecord = ensureRecord(authorId); + existingRecord.status = "success"; + existingRecord.rates = { + ...existingRecord.rates, + ...rates + }; + delete existingRecord.failureReason; + }, + upsertMarketRow(row) { + const existingRecord = records.get(row.authorId); + if (existingRecord) { + existingRecord.authorName = mergeStringValue3(existingRecord.authorName, row.authorName) ?? existingRecord.authorName; + existingRecord.location = mergeStringValue3( + existingRecord.location, + row.location + ); + existingRecord.price21To60s = mergeStringValue3( + existingRecord.price21To60s, + row.price21To60s + ); + existingRecord.exportFields = mergeFieldMap3( + existingRecord.exportFields, + row.exportFields + ); + existingRecord.backendMetrics = mergeFieldMap3( + existingRecord.backendMetrics, + row.backendMetrics + ); + existingRecord.hasDirectRatesSource = existingRecord.hasDirectRatesSource || row.hasDirectRatesSource; + existingRecord.rates = mergeFieldMap3(existingRecord.rates, row.rates); + return existingRecord; + } + const nextRecord = { + ...row, + backendMetricsStatus: "idle", + status: "idle" + }; + records.set(row.authorId, nextRecord); + return nextRecord; + } + }; + function ensureRecord(authorId) { + const existingRecord = records.get(authorId); + if (existingRecord) { + return existingRecord; + } + const nextRecord = { + authorId, + authorName: authorId, + backendMetricsStatus: "idle", + status: "idle" + }; + records.set(authorId, nextRecord); + return nextRecord; + } + } + function mergeFieldMap3(current, incoming) { + if (!current && !incoming) { + return void 0; + } + const merged = { + ...current ?? {} + }; + Object.entries(incoming ?? {}).forEach(([key, value]) => { + const currentValue = merged[key]; + if (!hasTextValue5(currentValue)) { + merged[key] = value; + } + }); + return merged; + } + function mergeStringValue3(current, incoming) { + if (!hasTextValue5(current)) { + return incoming ?? current; + } + return current; + } + function hasTextValue5(value) { + return typeof value === "string" && value.trim().length > 0; + } + + // src/shared/auth-messages.ts + function isAuthResponseMessage(value) { + if (!value || typeof value !== "object") { + return false; + } + const candidate = value; + if (candidate.ok === false) { + return candidate.type === "auth:error" && typeof candidate.error === "string"; + } + if (candidate.ok !== true || typeof candidate.type !== "string") { + return false; + } + if (candidate.type === "auth:ack") { + return true; + } + if (candidate.type === "auth:token") { + return Boolean( + candidate.value && typeof candidate.value === "object" && typeof candidate.value.accessToken === "string" + ); + } + if (candidate.type === "auth:state") { + return Boolean( + candidate.value && typeof candidate.value === "object" && typeof candidate.value.isAuthenticated === "boolean" + ); + } + return false; + } + + // src/shared/backend-metrics-messages.ts + function isBackendMetricsResponseMessage(value) { + if (!value || typeof value !== "object") { + return false; + } + const candidate = value; + if (candidate.ok === false) { + return candidate.type === "backend-metrics:error" && typeof candidate.error === "string"; + } + return Boolean( + candidate.ok === true && candidate.type === "backend-metrics:result" && candidate.value && typeof candidate.value === "object" && Array.isArray(candidate.value.rows) + ); + } + + // src/content/market/index.ts + function createMarketController(options) { + const marketApiClient = createMarketApiClient(); + const sendRuntimeMessage = createRuntimeMessageSender(); + const resultStore = options.resultStore ?? createMarketResultStore(); + const loadAuthorMetrics = options.loadAuthorMetrics ?? marketApiClient.loadAuthorAseInfo; + const searchBackendMetrics = options.searchBackendMetrics ?? (hasRuntimeMessageSender() ? (starIds) => readBackendMetrics(sendRuntimeMessage, starIds) : null); + const buildCsv = options.buildCsv ?? buildMarketCsv; + const getAuthState = options.getAuthState ?? (() => readAuthState(sendRuntimeMessage)); + const mutationObserverFactory = options.mutationObserverFactory ?? ((callback) => new MutationObserver(callback)); + const promptBatchName = options.promptBatchName ?? (() => promptForBatchName(options.document)); + const submitBatch = options.submitBatch ?? ((payload) => readBatchSubmitAck(sendRuntimeMessage, payload)); + let activeProgressLabel = "\u5BFC\u51FA\u4E2D"; + let shouldShowDetailedProgress = true; + const exportRangeController = createExportRangeController({ + document: options.document, + onProgress: ({ currentPage, totalPages }) => { + updateToolbarProgress(currentPage, totalPages); + }, + prepareCurrentPageForExport, + readCurrentPageRecords: () => getVisibleOrderedRecords(), + readCurrentPageRowCount: () => countCurrentPageRows(options.document), + window: options.window + }); + const silentExportController = createSilentExportController({ + document: options.document, + onProgress: ({ currentPage, totalPages }) => { + updateToolbarProgress(currentPage, totalPages); + } + }); + let activeSort; + let isDisposed = false; + let isSyncRunning = false; + let isSyncScheduled = false; + let lastKnownPageSignature = ""; + let needsResync = false; + let scheduledSyncTimeoutId = null; + const selectedAuthorIds = /* @__PURE__ */ new Set(); + let toolbar; + const observer = mutationObserverFactory(() => { + if (isDisposed) { + return; + } + let nextPageSignature = lastKnownPageSignature; + try { + nextPageSignature = readMarketPageSignature(options.document); + } catch { + return; + } + const toolbarNeedsRemount = !toolbar || !isPluginToolbarMounted(toolbar.root, options.document); + const selectionControlsMissing = !options.document.querySelector('[data-market-selection-checkbox="row"]') || !options.document.querySelector('[data-market-selection-checkbox="header"]'); + if (nextPageSignature === lastKnownPageSignature && !toolbarNeedsRemount && !selectionControlsMissing) { + return; + } + scheduleSync(); + }); + const observationRoot = options.document.body ?? options.document.documentElement; + startObserving(); + const toolbarHandlers = { + onExport: async () => { + syncSelectionStateFromDom(); + const exportTarget = readToolbarExportTarget(toolbar); + if (!exportTarget.target) { + setToolbarExportStatus(toolbar, exportTarget.error ?? "\u5BFC\u51FA\u914D\u7F6E\u65E0\u6548"); + return; + } + setToolbarBusyState(toolbar, true); + try { + const records = filterRecordsBySelection( + await exportRecords(exportTarget.target, "\u5BFC\u51FA\u4E2D", { + showDetailedProgress: selectedAuthorIds.size === 0 + }) + ); + options.onCsvReady?.(buildCsv(records)); + setToolbarExportStatus(toolbar, ""); + } catch (error) { + setToolbarExportStatus( + toolbar, + error instanceof Error ? error.message : "\u5BFC\u51FA\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5" + ); + } finally { + setToolbarBusyState(toolbar, false); + } + }, + onSubmitBatch: async () => { + syncSelectionStateFromDom(); + const exportTarget = readToolbarExportTarget(toolbar); + if (!exportTarget.target) { + setToolbarExportStatus(toolbar, exportTarget.error ?? "\u5BFC\u51FA\u914D\u7F6E\u65E0\u6548"); + return; + } + const batchName = await promptBatchName(); + if (batchName === null) { + return; + } + if (!batchName.trim()) { + setToolbarExportStatus(toolbar, "\u8BF7\u8F93\u5165\u6279\u6B21\u540D\u79F0"); + return; + } + setToolbarBusyState(toolbar, true); + try { + const hasSelectedAuthors = selectedAuthorIds.size > 0; + const records = filterRecordsBySelection( + await exportRecords( + exportTarget.target, + hasSelectedAuthors ? "\u63D0\u4EA4\u5DF2\u9009\u8FBE\u4EBA\u4E2D" : "\u63D0\u4EA4\u4E2D", + { + showDetailedProgress: !hasSelectedAuthors + } + ) + ); + const authState = await getAuthState(); + if (!authState.isAuthenticated) { + throw new Error("\u8BF7\u5148\u767B\u5F55\u63D2\u4EF6"); + } + const payload = createBatchPayload({ + authState, + batchName, + createdAt: (/* @__PURE__ */ new Date()).toISOString(), + records + }); + await submitBatch(payload); + setToolbarExportStatus(toolbar, "\u6279\u6B21\u63D0\u4EA4\u6210\u529F"); + } catch (error) { + setToolbarExportStatus( + toolbar, + error instanceof Error ? error.message : "\u6279\u6B21\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5" + ); + } finally { + setToolbarBusyState(toolbar, false); + } + } + }; + toolbar = ensurePluginToolbar(options.document, toolbarHandlers); + const ready = runSyncCycle(); + return { + dispose() { + isDisposed = true; + observer.disconnect(); + if (scheduledSyncTimeoutId !== null) { + options.window.clearTimeout(scheduledSyncTimeoutId); + scheduledSyncTimeoutId = null; + } + }, + ready + }; + async function hydrateCurrentPage() { + const table = syncMarketTable(options.document); + if (!table) { + return; + } + const pageRows = []; + for (const rowDom of table.rows) { + const rowSnapshot = readRowSnapshot(rowDom); + if (!rowSnapshot.authorId || !hasTextValue6(rowSnapshot.authorName)) { + continue; + } + pageRows.push({ + rowDom, + rowSnapshot + }); + resultStore.upsertMarketRow(rowSnapshot); + } + const pendingRateRows = []; + const rowsNeedingBackendMetrics = []; + pageRows.forEach(({ rowDom, rowSnapshot }) => { + if (rowSnapshot.hasDirectRatesSource) { + resultStore.setAuthorSuccess(rowSnapshot.authorId, rowSnapshot.rates ?? {}); + } + const existingRecord = resultStore.getRecord(rowSnapshot.authorId); + const needsRateFetch = !hasSettledRateState(existingRecord) && !hasCompleteRates(existingRecord?.rates); + const needsBackendMetrics = Boolean(searchBackendMetrics) && !hasSettledBackendMetricsState(existingRecord); + if (needsRateFetch) { + resultStore.setAuthorLoading(rowSnapshot.authorId); + pendingRateRows.push({ + rowDom, + rowSnapshot + }); + } + if (needsBackendMetrics) { + resultStore.setBackendMetricsLoading(rowSnapshot.authorId); + rowsNeedingBackendMetrics.push({ + rowDom, + rowSnapshot + }); + } + if (needsRateFetch || needsBackendMetrics) { + renderMarketRowState(rowDom, { + ...existingRecord ?? { + authorId: rowSnapshot.authorId, + authorName: rowSnapshot.authorName, + status: "idle" + }, + ...rowSnapshot, + backendMetricsStatus: needsBackendMetrics ? "loading" : existingRecord?.backendMetricsStatus, + rates: existingRecord?.rates, + status: needsRateFetch || needsBackendMetrics ? "loading" : existingRecord?.status ?? "idle" + }); + return; + } + if (existingRecord) { + renderMarketRowState(rowDom, existingRecord); + } + }); + await Promise.all([ + hydrateRatesForRows(pendingRateRows), + hydrateBackendMetricsForPage(rowsNeedingBackendMetrics) + ]); + pageRows.forEach(({ rowDom, rowSnapshot }) => { + const record = resultStore.getRecord(rowSnapshot.authorId); + if (!record) { + return; + } + renderMarketRowState(rowDom, record); + }); + } + async function hydrateRatesForRows(pageRows) { + if (pageRows.length === 0) { + return; + } + await Promise.all( + pageRows.map(async ({ rowSnapshot }) => { + const metricsResult = await loadAuthorMetrics(rowSnapshot.authorId); + if (metricsResult.success) { + resultStore.setAuthorSuccess(rowSnapshot.authorId, metricsResult.rates); + return; + } + resultStore.setAuthorFailed(rowSnapshot.authorId, metricsResult.reason); + }) + ); + } + async function hydrateBackendMetricsForPage(pageRows) { + if (!searchBackendMetrics || pageRows.length === 0) { + return; + } + try { + const rows = await searchBackendMetrics( + pageRows.map(({ rowSnapshot }) => rowSnapshot.authorId) + ); + const rowMap = new Map(rows.map((row) => [row.starId, row])); + pageRows.forEach(({ rowSnapshot }) => { + const backendMetrics = rowMap.get(rowSnapshot.authorId); + if (backendMetrics) { + resultStore.setBackendMetricsSuccess(rowSnapshot.authorId, backendMetrics); + } else { + resultStore.setBackendMetricsMissing(rowSnapshot.authorId); + } + }); + } catch { + pageRows.forEach(({ rowSnapshot }) => { + resultStore.setBackendMetricsFailed(rowSnapshot.authorId); + }); + } + } + function applyCurrentView() { + runWithoutMutationSync(() => { + toolbar = ensurePluginToolbar(options.document, toolbarHandlers); + const table = syncMarketTable(options.document); + if (!table) { + return; + } + syncPluginSortHeaders(options.document, { + activeSort, + onToggleSort: toggleSortFromHeader + }); + const records = getVisibleOrderedRecords(table); + applyRowVisibility(table, new Set(records.map((record) => record.authorId))); + applyRowOrder(table, records.map((record) => record.authorId)); + bindSelectionControls(table); + syncMarketSelectionState(table, selectedAuthorIds); + lastKnownPageSignature = readMarketPageSignature(options.document); + }); + } + function bindSelectionControls(table) { + if (!table) { + return; + } + table.rows.forEach((rowDom) => { + rowDom.selectionCheckbox.dataset.marketSelectionAuthorId = rowDom.authorId; + if (rowDom.selectionCheckbox.dataset.marketSelectionBound === "true") { + return; + } + rowDom.selectionCheckbox.dataset.marketSelectionBound = "true"; + rowDom.selectionCheckbox.addEventListener("change", () => { + if (rowDom.selectionCheckbox.checked) { + selectedAuthorIds.add(rowDom.authorId); + } else { + selectedAuthorIds.delete(rowDom.authorId); + } + refreshSelectionControls(); + }); + }); + if (!table.headerSelectionCheckbox) { + return; + } + if (table.headerSelectionCheckbox.dataset.marketSelectionBound === "true") { + return; + } + table.headerSelectionCheckbox.dataset.marketSelectionBound = "true"; + table.headerSelectionCheckbox.addEventListener("change", () => { + const currentTable = syncMarketTable(options.document); + if (!currentTable) { + return; + } + const visibleRows = currentTable.rows.filter( + (rowDom) => rowDom.visibilityTargets.some((target) => !target.hidden) + ); + const scopedRows = visibleRows.length > 0 ? visibleRows : currentTable.rows; + if (table.headerSelectionCheckbox?.checked) { + scopedRows.forEach((rowDom) => { + selectedAuthorIds.add(rowDom.authorId); + }); + } else { + scopedRows.forEach((rowDom) => { + selectedAuthorIds.delete(rowDom.authorId); + }); + } + refreshSelectionControls(); + }); + } + function refreshSelectionControls() { + const table = syncMarketTable(options.document); + if (!table) { + return; + } + bindSelectionControls(table); + syncMarketSelectionState(table, selectedAuthorIds); + } + function syncSelectionStateFromDom() { + const rowSelectionCheckboxes = Array.from( + options.document.querySelectorAll('[data-market-selection-checkbox="row"]') + ).filter( + (element) => element instanceof HTMLInputElement + ); + if (rowSelectionCheckboxes.length === 0) { + return; + } + rowSelectionCheckboxes.forEach((checkbox) => { + const authorId = checkbox.dataset.marketSelectionAuthorId?.trim(); + if (!authorId) { + return; + } + if (checkbox.checked) { + selectedAuthorIds.add(authorId); + } else { + selectedAuthorIds.delete(authorId); + } + }); + refreshSelectionControls(); + } + function toggleSortFromHeader(field) { + activeSort = getNextSortState(activeSort, field); + applyCurrentView(); + } + function getVisibleOrderedRecords(table = syncMarketTable(options.document)) { + const currentPageRecords = readCurrentPageRecords(table); + return applyFilterAndSort(currentPageRecords, { + sort: activeSort + }); + } + async function exportRecords(target, inProgressLabel = "\u5BFC\u51FA\u4E2D", progressOptions = {}) { + activeProgressLabel = inProgressLabel; + shouldShowDetailedProgress = progressOptions.showDetailedProgress ?? true; + setToolbarExportStatus(toolbar, `${inProgressLabel}...`); + if (target.mode === "count" && target.pageCount <= 1) { + await prepareCurrentPageForExport(); + return getVisibleOrderedRecords(); + } + const silentExportRecords = await silentExportController.exportRecords(target); + if (silentExportRecords) { + return hydrateExportRecords( + silentExportRecords.map((record) => ({ + ...record, + status: record.status ?? "idle" + })) + ); + } + return exportRangeController.exportRecords(target); + } + function updateToolbarProgress(currentPage, totalPages) { + if (!shouldShowDetailedProgress) { + setToolbarExportStatus(toolbar, `${activeProgressLabel}...`); + return; + } + setToolbarExportStatus( + toolbar, + totalPages ? `${activeProgressLabel} ${currentPage}/${totalPages} \u9875...` : `${activeProgressLabel} \u7B2C${currentPage}\u9875...` + ); + } + function filterRecordsBySelection(records) { + if (selectedAuthorIds.size === 0) { + return records; + } + const selectedRecords = records.filter( + (record) => selectedAuthorIds.has(record.authorId) + ); + return selectedRecords.length > 0 ? selectedRecords : records; + } + async function prepareCurrentPageForExport() { + await runSyncCycle(); + await harvestCurrentPageForExport(); + await runSyncCycle(); + } + async function hydrateExportRecords(records) { + for (const record of records) { + resultStore.upsertMarketRow(record); + const existingRecord = resultStore.getRecord(record.authorId); + if (existingRecord?.status === "success" && existingRecord.rates) { + continue; + } + if (record.hasDirectRatesSource) { + const directRates = record.rates ?? {}; + const hasAllRates = Boolean(directRates.singleVideoAfterSearchRate) && Boolean(directRates.personalVideoAfterSearchRate); + resultStore.setAuthorSuccess(record.authorId, directRates); + if (hasAllRates) { + continue; + } + } else { + resultStore.setAuthorLoading(record.authorId); + } + const metricsResult = await loadAuthorMetrics(record.authorId); + if (metricsResult.success) { + resultStore.setAuthorSuccess(record.authorId, metricsResult.rates); + } else { + resultStore.setAuthorFailed(record.authorId, metricsResult.reason); + } + } + if (searchBackendMetrics) { + const backendTargetRecords = records.filter((record) => { + const existingRecord = resultStore.getRecord(record.authorId); + return !(existingRecord?.backendMetricsStatus === "success" || existingRecord?.backendMetricsStatus === "missing"); + }); + if (backendTargetRecords.length > 0) { + backendTargetRecords.forEach((record) => { + resultStore.setBackendMetricsLoading(record.authorId); + }); + try { + const backendRows = await searchBackendMetrics( + backendTargetRecords.map((record) => record.authorId) + ); + const backendRowMap = new Map(backendRows.map((row) => [row.starId, row])); + backendTargetRecords.forEach((record) => { + const backendMetrics = backendRowMap.get(record.authorId); + if (backendMetrics) { + resultStore.setBackendMetricsSuccess(record.authorId, backendMetrics); + } else { + resultStore.setBackendMetricsMissing(record.authorId); + } + }); + } catch { + backendTargetRecords.forEach((record) => { + resultStore.setBackendMetricsFailed(record.authorId); + }); + } + } + } + return records.map((record) => toMarketRecord(record)); + } + async function harvestCurrentPageForExport() { + let hydrationSnapshot = await collectCurrentPageSnapshotsUntilSettled(); + if (hydrationSnapshot.missingDefaultFieldCount === 0 && hydrationSnapshot.blankExportFieldCount === 0) { + return; + } + const table = syncMarketTable(options.document); + const scrollContainer = findCurrentPageScrollContainer(table); + if (!scrollContainer) { + return; + } + const originalScrollTop = scrollContainer.scrollTop; + const maxScrollTop = Math.max( + 0, + scrollContainer.scrollHeight - scrollContainer.clientHeight + ); + if (maxScrollTop <= 0) { + return; + } + const step = Math.max(scrollContainer.clientHeight, 240); + for (let nextScrollTop = Math.min(originalScrollTop + step, maxScrollTop); nextScrollTop > originalScrollTop && nextScrollTop <= maxScrollTop; nextScrollTop = Math.min(nextScrollTop + step, maxScrollTop)) { + setScrollTop(scrollContainer, nextScrollTop); + hydrationSnapshot = await collectCurrentPageSnapshotsUntilSettled(); + if (hydrationSnapshot.missingDefaultFieldCount === 0 && hydrationSnapshot.blankExportFieldCount === 0) { + break; + } + if (nextScrollTop === maxScrollTop) { + break; + } + } + if (scrollContainer.scrollTop !== originalScrollTop) { + setScrollTop(scrollContainer, originalScrollTop); + } + } + function readCurrentPageRecords(table) { + if (!table) { + return []; + } + return table.rows.map((rowDom) => { + const rowSnapshot = readRowSnapshot(rowDom); + if (!rowSnapshot.authorId || !hasTextValue6(rowSnapshot.authorName)) { + return null; + } + return toMarketRecord(rowSnapshot); + }).filter((record) => record !== null); + } + function toMarketRecord(rowSnapshot) { + const existingRecord = resultStore.getRecord(rowSnapshot.authorId); + const authorName = mergeStringValue4(existingRecord?.authorName, rowSnapshot.authorName) ?? ""; + const location2 = mergeStringValue4(existingRecord?.location, rowSnapshot.location); + const price21To60s = mergeStringValue4( + existingRecord?.price21To60s, + rowSnapshot.price21To60s + ); + return { + ...existingRecord, + ...rowSnapshot, + authorName, + backendMetrics: mergeFieldMap4( + existingRecord?.backendMetrics, + rowSnapshot.backendMetrics + ), + backendMetricsStatus: existingRecord?.backendMetricsStatus ?? "idle", + exportFields: withExportFieldFallbacks( + mergeFieldMap4(existingRecord?.exportFields, rowSnapshot.exportFields), + { + authorName, + location: location2, + price21To60s + } + ), + location: location2, + price21To60s, + rates: mergeFieldMap4(existingRecord?.rates, rowSnapshot.rates), + status: existingRecord?.status ?? "idle" + }; + } + function collectCurrentPageSnapshots() { + readCurrentPageRows(options.document).forEach((rowSnapshot) => { + resultStore.upsertMarketRow(rowSnapshot); + }); + } + function findCurrentPageScrollContainer(table) { + if (!table) { + return null; + } + const candidateScores = /* @__PURE__ */ new Map(); + const candidateRoots = table.rows.map((rowDom) => rowDom.row).filter((row) => row instanceof options.window.HTMLElement); + for (const rootElement of candidateRoots) { + let currentElement = rootElement.parentElement; + let depth = 0; + while (currentElement) { + if (isScrollableContainer(currentElement)) { + const scrollRange = currentElement.scrollHeight - currentElement.clientHeight; + const existingScore = candidateScores.get(currentElement); + if (!existingScore || depth < existingScore.depth) { + candidateScores.set(currentElement, { + depth, + scrollRange + }); + } + } + depth += 1; + currentElement = currentElement.parentElement; + } + } + const rankedCandidates = Array.from(candidateScores.entries()).sort((left, right) => { + const [, leftScore] = left; + const [, rightScore] = right; + if (rightScore.scrollRange !== leftScore.scrollRange) { + return rightScore.scrollRange - leftScore.scrollRange; + } + return leftScore.depth - rightScore.depth; + }); + return rankedCandidates[0]?.[0] ?? null; + } + function isScrollableContainer(element) { + const computedStyle = options.window.getComputedStyle(element); + return /auto|scroll|overlay/.test(computedStyle.overflowY) && element.scrollHeight > element.clientHeight; + } + async function waitForDomSettled() { + await new Promise((resolve) => { + options.window.setTimeout(resolve, 0); + }); + await Promise.resolve(); + } + async function collectCurrentPageSnapshotsUntilSettled() { + let previousFingerprint = ""; + let stablePassCount = 0; + let fingerprintStableSince = 0; + let lastSnapshot = { + blankExportFieldCount: 0, + fingerprint: "", + missingDefaultFieldCount: 0 + }; + for (let attempt = 0; attempt < 16; attempt += 1) { + await waitForDomSettled(); + if (attempt > 0) { + await new Promise((resolve) => { + options.window.setTimeout( + resolve, + previousFingerprint.includes("|missing:0") ? 25 : 50 + ); + }); + await Promise.resolve(); + } + collectCurrentPageSnapshots(); + const hydrationSnapshot = readVisibleRowHydrationSnapshot(); + lastSnapshot = hydrationSnapshot; + if (!hydrationSnapshot.fingerprint) { + stablePassCount = 0; + previousFingerprint = ""; + continue; + } + if (hydrationSnapshot.fingerprint === previousFingerprint) { + stablePassCount += 1; + } else { + previousFingerprint = hydrationSnapshot.fingerprint; + stablePassCount = 1; + fingerprintStableSince = options.window.Date.now(); + } + const stableForMs = options.window.Date.now() - fingerprintStableSince; + if (hydrationSnapshot.missingDefaultFieldCount === 0 && hydrationSnapshot.blankExportFieldCount === 0 && stablePassCount >= 2) { + return hydrationSnapshot; + } + if (hydrationSnapshot.missingDefaultFieldCount === 0 && hydrationSnapshot.blankExportFieldCount > 0 && stablePassCount >= 2 && stableForMs >= 500) { + return hydrationSnapshot; + } + } + return lastSnapshot; + } + function readVisibleRowHydrationSnapshot() { + const table = syncMarketTable(options.document); + if (!table || table.rows.length === 0) { + return { + blankExportFieldCount: 0, + fingerprint: "", + missingDefaultFieldCount: 0 + }; + } + const parts = table.rows.map((rowDom) => { + const rowSnapshot = readRowSnapshot(rowDom); + const populatedFieldCount = Object.values(rowSnapshot.exportFields ?? {}).filter( + (value) => typeof value === "string" && value.trim().length > 0 + ).length; + const blankExportFieldCount = Object.values(rowSnapshot.exportFields ?? {}).filter( + (value) => typeof value !== "string" || value.trim().length === 0 + ).length; + const hasAuthorField = hasTextValue6(rowSnapshot.exportFields?.["\u8FBE\u4EBA\u4FE1\u606F"]); + const hasRepresentativeVideo = hasTextValue6( + rowSnapshot.exportFields?.["\u4EE3\u8868\u89C6\u9891"] + ); + const hasPriceField = hasTextValue6(rowSnapshot.price21To60s) || hasTextValue6(rowSnapshot.exportFields?.["21-60s\u62A5\u4EF7"]); + const missingDefaultFieldCount = Number(!hasAuthorField) + Number(!hasRepresentativeVideo) + Number(!hasPriceField); + return [ + rowSnapshot.authorId, + populatedFieldCount, + `blank:${blankExportFieldCount}`, + hasAuthorField ? "author" : "no-author", + hasRepresentativeVideo ? "video" : "no-video", + hasPriceField ? "price" : "no-price", + `missing:${missingDefaultFieldCount}` + ].join(":"); + }); + return { + blankExportFieldCount: parts.reduce((count, part) => { + const match = part.match(/:blank:(\d+):/); + return count + Number(match?.[1] ?? 0); + }, 0), + fingerprint: parts.join("|"), + missingDefaultFieldCount: parts.reduce((count, part) => { + const match = part.match(/missing:(\d+)$/); + return count + Number(match?.[1] ?? 0); + }, 0) + }; + } + function scheduleSync() { + if (isDisposed) { + return; + } + if (isSyncRunning) { + needsResync = true; + return; + } + if (isSyncScheduled) { + return; + } + isSyncScheduled = true; + scheduledSyncTimeoutId = options.window.setTimeout(() => { + scheduledSyncTimeoutId = null; + isSyncScheduled = false; + if (isDisposed) { + return; + } + void runSyncCycle(); + }, 0); + } + function runWithoutMutationSync(callback) { + if (isDisposed) { + return; + } + observer.disconnect(); + try { + callback(); + } finally { + startObserving(); + } + } + function startObserving() { + if (isDisposed || !observationRoot) { + return; + } + observer.observe(observationRoot, { + childList: true, + subtree: true + }); + } + async function runSyncCycle() { + if (isDisposed) { + return; + } + if (isSyncRunning) { + needsResync = true; + return; + } + isSyncRunning = true; + try { + toolbar = ensurePluginToolbar(options.document, toolbarHandlers); + await hydrateCurrentPage(); + applyCurrentView(); + lastKnownPageSignature = readMarketPageSignature(options.document); + } finally { + isSyncRunning = false; + if (isDisposed) { + return; + } + if (needsResync) { + needsResync = false; + scheduleSync(); + } + } + } + } + function setScrollTop(element, top) { + element.scrollTop = top; + element.dispatchEvent(new Event("scroll")); + } + function readCurrentPageRows(document2) { + const table = syncMarketTable(document2); + if (!table) { + return []; + } + return table.rows.map((rowDom) => readRowSnapshot(rowDom)).filter( + (row) => Boolean(row.authorId) && hasTextValue6(row.authorName) + ); + } + function countCurrentPageRows(document2) { + const table = syncMarketTable(document2); + if (!table) { + return 0; + } + return table.rows.filter((rowDom) => Boolean(rowDom.authorId)).length; + } + function readRowSnapshot(rowDom) { + return { + authorId: rowDom.authorId, + authorName: rowDom.authorName, + exportFields: rowDom.exportFields, + hasDirectRatesSource: rowDom.hasDirectRatesSource, + location: rowDom.location, + price21To60s: rowDom.price21To60s, + rates: rowDom.rates + }; + } + function getNextSortState(currentSort, field) { + if (!currentSort || currentSort.field !== field) { + return { + direction: "desc", + field + }; + } + if (currentSort.direction === "desc") { + return { + direction: "asc", + field + }; + } + return void 0; + } + function hasCompleteRates(rates) { + return Boolean( + rates?.singleVideoAfterSearchRate && rates?.personalVideoAfterSearchRate + ); + } + function hasSettledRateState(record) { + if (!record) { + return false; + } + return record.status === "failed" || hasCompleteRates(record.rates); + } + function hasSettledBackendMetricsState(record) { + if (!record) { + return false; + } + return record.backendMetricsStatus === "success" || record.backendMetricsStatus === "missing" || record.backendMetricsStatus === "failed"; + } + function mergeFieldMap4(current, incoming) { + if (!current && !incoming) { + return void 0; + } + const merged = { + ...current ?? {} + }; + Object.entries(incoming ?? {}).forEach(([key, value]) => { + const currentValue = merged[key]; + if (hasTextValue6(value) || !hasTextValue6(currentValue)) { + merged[key] = value; + } + }); + return merged; + } + function createRuntimeMessageSender() { + return (message) => Promise.resolve( + globalThis.chrome?.runtime?.sendMessage?.(message) + ); + } + async function readAuthState(sendMessage) { + const response = await sendMessage({ type: "auth:get-state" }); + if (!isAuthResponseMessage(response) || !response.ok || response.type !== "auth:state") { + throw new Error("\u8BF7\u5148\u767B\u5F55\u63D2\u4EF6"); + } + return response.value; + } + async function readBatchSubmitAck(sendMessage, payload) { + const response = await sendMessage({ + payload, + type: "batch:submit" + }); + if (response && typeof response === "object" && response.ok === true) { + return response.value; + } + if (response && typeof response === "object" && response.ok === false && typeof response.error === "string") { + throw new Error(response.error); + } + throw new Error("\u6279\u6B21\u63D0\u4EA4\u5931\u8D25\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"); + } + async function readBackendMetrics(sendMessage, starIds) { + const response = await sendMessage({ + type: "backend-metrics:search", + value: { + starIds + } + }); + if (isBackendMetricsResponseMessage(response) && response.ok && response.type === "backend-metrics:result") { + return response.value.rows; + } + throw new Error("\u540E\u7AEF\u6307\u6807\u52A0\u8F7D\u5931\u8D25"); + } + function mergeStringValue4(current, incoming) { + if (hasTextValue6(incoming) || !hasTextValue6(current)) { + return incoming ?? current; + } + return current; + } + function withExportFieldFallbacks(exportFields, fallbackValues) { + if (!exportFields) { + return void 0; + } + const nextExportFields = { + ...exportFields + }; + if ("\u8FBE\u4EBA\u4FE1\u606F" in nextExportFields && !hasTextValue6(nextExportFields["\u8FBE\u4EBA\u4FE1\u606F"]) && hasTextValue6(fallbackValues.authorName)) { + nextExportFields["\u8FBE\u4EBA\u4FE1\u606F"] = fallbackValues.authorName; + } + if ("\u5730\u533A" in nextExportFields && !hasTextValue6(nextExportFields["\u5730\u533A"]) && hasTextValue6(fallbackValues.location)) { + nextExportFields["\u5730\u533A"] = fallbackValues.location; + } + if ("21-60s\u62A5\u4EF7" in nextExportFields && !hasTextValue6(nextExportFields["21-60s\u62A5\u4EF7"]) && hasTextValue6(fallbackValues.price21To60s)) { + nextExportFields["21-60s\u62A5\u4EF7"] = fallbackValues.price21To60s; + } + return nextExportFields; + } + function hasTextValue6(value) { + return typeof value === "string" && value.trim().length > 0; + } + function hasRuntimeMessageSender() { + return Boolean( + globalThis.chrome?.runtime?.sendMessage + ); + } + + // src/content/market/auth-gate.ts + function renderMarketAuthGate(document2, currentWindow) { + const existingGate = document2.querySelector( + '[data-market-auth-gate="root"]' + ); + if (existingGate) { + return existingGate; + } + const root = document2.createElement("section"); + root.dataset.marketAuthGate = "root"; + root.innerHTML = ` + \u8BF7\u5148\u767B\u5F55\u63D2\u4EF6 +

\u6253\u5F00\u6269\u5C55\u5F39\u7A97\u5B8C\u6210\u767B\u5F55\u540E\u5237\u65B0\u672C\u9875

+ + `; + root.querySelector('[data-market-auth-help="button"]')?.addEventListener("click", () => { + currentWindow.alert("\u8BF7\u70B9\u51FB\u6D4F\u89C8\u5668\u5DE5\u5177\u680F\u4E2D\u7684\u6269\u5C55\u56FE\u6807\u5B8C\u6210\u767B\u5F55"); + }); + document2.body.prepend(root); + return root; + } + + // src/content/index.ts + var DOWNLOAD_MARKET_CSV_MESSAGE = "download-market-csv"; + async function bootContentScript(options = {}) { + const currentWindow = options.window ?? window; + const currentDocument = options.document ?? document; + const controllerFactory = options.createMarketController ?? createMarketController; + const sendAuthMessage = options.sendAuthMessage ?? createRuntimeMessageSender2(); + if (!isMarketPage(currentWindow.location.href)) { + return null; + } + installMarketPageBridge(currentDocument); + const authState = await readAuthState2(sendAuthMessage); + if (!authState?.isAuthenticated) { + await waitForBodyReady(currentDocument, currentWindow); + renderMarketAuthGate(currentDocument, currentWindow); + return { + ready: Promise.resolve() + }; + } + await waitForBodyReady(currentDocument, currentWindow); + return controllerFactory({ + document: currentDocument, + onCsvReady: (csv) => { + if (requestCsvDownload(csv)) { + return; + } + downloadCsv(currentDocument, currentWindow, csv); + }, + window: currentWindow + }); + } + async function readAuthState2(sendMessage) { + const response = await sendMessage({ type: "auth:get-state" }); + if (!isAuthResponseMessage(response) || !response.ok || response.type !== "auth:state") { + return null; + } + return response.value; + } + function isMarketPage(url) { + const parsedUrl = new URL(url); + const isXingtuHost = parsedUrl.hostname === "xingtu.cn" || parsedUrl.hostname.endsWith(".xingtu.cn"); + return isXingtuHost && parsedUrl.pathname.startsWith("/ad/creator/market"); + } + function bootstrapContentScript() { + const runtime = globalThis.chrome?.runtime; + if (!runtime || typeof window === "undefined" || typeof document === "undefined") { + return; + } + const marker = "__starChartSearchEnhancerContentController"; + const scopedWindow = window; + if (scopedWindow[marker]) { + return; + } + scopedWindow[marker] = true; + void bootContentScript().then((controller) => { + scopedWindow[marker] = controller; + }); + } + bootstrapContentScript(); + function requestCsvDownload(csv) { + const runtime = globalThis.chrome?.runtime; + if (!runtime?.id || typeof runtime.sendMessage !== "function") { + return false; + } + runtime.sendMessage({ + csv, + filename: `star-chart-search-enhancer-${formatTimestampForFilename()}.csv`, + type: DOWNLOAD_MARKET_CSV_MESSAGE + }); + return true; + } + function createRuntimeMessageSender2() { + return async (message) => { + const runtime = globalThis.chrome?.runtime; + if (typeof runtime?.sendMessage !== "function") { + return null; + } + return runtime.sendMessage(message); + }; + } + async function waitForBodyReady(document2, currentWindow) { + if (document2.body) { + return; + } + await new Promise((resolve) => { + const handleReady = () => { + if (document2.body) { + document2.removeEventListener("DOMContentLoaded", handleReady); + resolve(); + } + }; + document2.addEventListener("DOMContentLoaded", handleReady); + currentWindow.setTimeout(handleReady, 0); + }); + } + function downloadCsv(document2, window2, csv) { + const blob = new Blob(["\uFEFF", csv], { + type: "text/csv;charset=utf-8" + }); + const objectUrl = window2.URL.createObjectURL(blob); + const link = document2.createElement("a"); + link.href = objectUrl; + link.download = `star-chart-search-enhancer-${formatTimestampForFilename()}.csv`; + document2.body.appendChild(link); + link.click(); + link.remove(); + window2.URL.revokeObjectURL(objectUrl); + } + function formatTimestampForFilename() { + return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-"); + } + function installMarketPageBridge(document2) { + if (document2.documentElement.querySelector( + '[data-sces-market-bridge="script"]' + )) { + return; + } + const script = document2.createElement("script"); + script.dataset.scesMarketBridge = "script"; + const runtime = globalThis.chrome?.runtime; + const bridgeUrl = runtime?.getURL?.("content/market-page-bridge.js"); + if (bridgeUrl) { + script.src = bridgeUrl; + } else { + script.textContent = ""; + } + (document2.head ?? document2.documentElement).appendChild(script); + } +})(); diff --git a/dist-release/content/market-page-bridge.js b/dist-release/content/market-page-bridge.js new file mode 100644 index 0000000..f09d29c --- /dev/null +++ b/dist-release/content/market-page-bridge.js @@ -0,0 +1,583 @@ +"use strict"; +(() => { + // src/shared/rate-normalizer.ts + function normalizeFractionRateDisplay(value) { + const numericValue = Number(value); + if (!Number.isFinite(numericValue)) { + return null; + } + const percentageValue = numericValue * 100; + return `${trimTrailingZeros(percentageValue.toFixed(6))}%`; + } + function trimTrailingZeros(value) { + return value.replace(/\.?0+$/, ""); + } + + // src/content/market/market-list-request-snapshot.ts + var MARKET_REQUEST_SNAPSHOT_ATTRIBUTE = "data-sces-market-request-snapshot"; + function writeMarketListRequestSnapshot(document2, snapshot) { + document2.documentElement.setAttribute( + MARKET_REQUEST_SNAPSHOT_ATTRIBUTE, + JSON.stringify(snapshot) + ); + } + + // src/content/market/market-list-row.ts + var PAGE_NUMBER_KEYS = [ + "currentPage", + "page", + "pageNo", + "pageNum", + "page_no", + "page_num" + ]; + var PAGE_SIZE_KEYS = [ + "limit", + "pageSize", + "page_size", + "size" + ]; + var TOTAL_COUNT_KEYS = [ + "total", + "totalCount", + "total_count" + ]; + var TOTAL_PAGE_KEYS = [ + "pageCount", + "page_count", + "totalPage", + "totalPages", + "total_page", + "total_pages" + ]; + function mapMarketListRow(row) { + const attributeDatas = readMarketAttributeDatas(row); + const singleVideoAfterSearchRate = normalizeMarketListRate( + readMarketFieldValue(row, attributeDatas, "avg_search_after_view_rate_30d") + ); + return { + authorId: readString(readMarketFieldValue(row, attributeDatas, "star_id")) ?? readString(readMarketFieldValue(row, attributeDatas, "id")) ?? "", + authorName: readString(readMarketFieldValue(row, attributeDatas, "nickname")) ?? readString(readMarketFieldValue(row, attributeDatas, "nick_name")) ?? "", + exportFields: buildMarketExportFieldFallbacks(row, attributeDatas), + hasDirectRatesSource: true, + location: readMarketLocation(row, attributeDatas), + price21To60s: readMarketPrice21To60s(row, attributeDatas), + rates: singleVideoAfterSearchRate ? { + singleVideoAfterSearchRate + } : void 0 + }; + } + function parseMarketListResponse(payload) { + const container = findMarketListContainer(payload); + if (!container) { + return null; + } + const marketList = readMarketListArray(container); + if (!marketList) { + return null; + } + return { + currentPage: readKnownNumberDeep(container, PAGE_NUMBER_KEYS) ?? void 0, + pageSize: readKnownNumberDeep(container, PAGE_SIZE_KEYS) ?? void 0, + records: marketList.map((row) => isRecord(row) ? mapMarketListRow(row) : null).filter( + (row) => row !== null && Boolean(row.authorId || row.authorName) + ), + totalCount: readKnownNumberDeep(container, TOTAL_COUNT_KEYS) ?? void 0, + totalPages: readKnownNumberDeep(container, TOTAL_PAGE_KEYS) ?? void 0 + }; + } + function findMarketListContainer(value) { + const queue = [value]; + while (queue.length > 0) { + const current = queue.shift(); + if (!isRecord(current)) { + continue; + } + if (readMarketListArray(current)) { + return current; + } + Object.values(current).forEach((entry) => { + queue.push(unwrapVueRef(entry)); + }); + } + return null; + } + function readMarketListArray(record) { + const marketList = unwrapVueRef(record.marketList); + if (Array.isArray(marketList)) { + return marketList; + } + const authors = unwrapVueRef(record.authors); + if (Array.isArray(authors)) { + return authors; + } + return null; + } + function unwrapVueRef(value) { + if (isRecord(value) && "value" in value) { + return value.value; + } + return value; + } + function isRecord(value) { + return typeof value === "object" && value !== null; + } + function readMarketAttributeDatas(record) { + return isRecord(record.attribute_datas) ? record.attribute_datas : {}; + } + function readMarketFieldValue(record, attributeDatas, field) { + return record[field] ?? attributeDatas[field]; + } + function readString(value) { + return typeof value === "string" ? value : null; + } + function normalizeMarketListRate(value) { + if (typeof value === "number") { + return normalizeFractionRateDisplay(String(value)); + } + return typeof value === "string" ? normalizeFractionRateDisplay(value) : null; + } + function normalizeExportCellText(value) { + return value?.replace(/\s+/g, " ").trim() ?? ""; + } + function buildMarketExportFieldFallbacks(record, attributeDatas) { + const exportFields = {}; + const authorInfo = buildMarketAuthorInfo(record, attributeDatas); + const authorType = buildMarketAuthorType(record, attributeDatas); + const contentTheme = buildMarketContentTheme(record, attributeDatas); + const connectedUsers = formatWanValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "link_link_cnt_by_industry")) + ); + const followerCount = formatWanValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "follower")) + ); + const expectedCpm = formatDecimalDisplay( + readNumericValue(readMarketFieldValue(record, attributeDatas, "prospective_20_60_cpm")) + ); + const expectedPlayCount = formatWanValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "expected_play_num")) + ); + const interactionRate = formatFractionPercent( + readNumericValue(readMarketFieldValue(record, attributeDatas, "interact_rate_within_30d")) + ); + const finishRate = formatFractionPercent( + readNumericValue(readMarketFieldValue(record, attributeDatas, "play_over_rate_within_30d")) + ); + const burstRate = readBurstRateDisplay( + readNumericValue(readMarketFieldValue(record, attributeDatas, "burst_text_rate")) + ); + const price21To60s = readMarketPrice21To60s(record, attributeDatas); + const representativeVideo = readMarketRepresentativeVideo(record, attributeDatas); + assignExportField(exportFields, "\u8FBE\u4EBA\u4FE1\u606F", authorInfo); + assignExportField(exportFields, "\u4EE3\u8868\u89C6\u9891", representativeVideo); + assignExportField(exportFields, "\u8FBE\u4EBA\u7C7B\u578B", authorType); + assignExportField(exportFields, "\u5185\u5BB9\u4E3B\u9898", contentTheme); + assignExportField(exportFields, "\u8FDE\u63A5\u7528\u6237\u6570", connectedUsers); + assignExportField(exportFields, "\u7C89\u4E1D\u6570", followerCount); + assignExportField(exportFields, "\u9884\u671FCPM", expectedCpm); + assignExportField(exportFields, "\u9884\u671F\u64AD\u653E\u91CF", expectedPlayCount); + assignExportField(exportFields, "\u4E92\u52A8\u7387", interactionRate); + assignExportField(exportFields, "\u5B8C\u64AD\u7387", finishRate); + assignExportField(exportFields, "\u7206\u6587\u7387", burstRate); + assignExportField(exportFields, "21-60s\u62A5\u4EF7", price21To60s); + return Object.keys(exportFields).length > 0 ? exportFields : void 0; + } + function assignExportField(exportFields, key, value) { + if (hasTextValue(value)) { + exportFields[key] = value; + } + } + function hasTextValue(value) { + return Boolean(value && value.trim().length > 0); + } + function buildMarketAuthorInfo(record, attributeDatas) { + const nickname = readString(readMarketFieldValue(record, attributeDatas, "nickname")) ?? readString(readMarketFieldValue(record, attributeDatas, "nick_name")) ?? ""; + const parts = [ + nickname, + readMarketGenderLabel(readMarketFieldValue(record, attributeDatas, "gender")), + readString(readMarketFieldValue(record, attributeDatas, "city")) ?? "" + ].filter((value) => Boolean(value)); + return parts.length > 0 ? parts.join(" ") : void 0; + } + function buildMarketAuthorType(record, attributeDatas) { + const tagsRelation = readRecordLike( + readMarketFieldValue(record, attributeDatas, "tags_relation") + ); + if (tagsRelation) { + const primaryTag = Object.keys(tagsRelation)[0]; + if (hasTextValue(primaryTag)) { + return primaryTag; + } + } + return void 0; + } + function buildMarketContentTheme(record, attributeDatas) { + const themes = readStringArray( + readMarketFieldValue(record, attributeDatas, "content_theme_labels_180d") + ); + if (themes.length === 0) { + return void 0; + } + if (themes.length <= 2) { + return themes.join(" "); + } + return `${themes.slice(0, 2).join(" ")} ${themes.length - 2}+`; + } + function readMarketLocation(record, attributeDatas) { + return readString(readMarketFieldValue(record, attributeDatas, "city")) ?? void 0; + } + function readMarketPrice21To60s(record, attributeDatas) { + return formatCurrencyValue( + readNumericValue(readMarketFieldValue(record, attributeDatas, "price_20_60")) + ); + } + function readMarketRepresentativeVideo(record, attributeDatas) { + const items = readArrayLike(readMarketFieldValue(record, attributeDatas, "items")); + for (const item of items) { + if (!isRecord(item)) { + continue; + } + const title = readString(item.title); + if (hasTextValue(title)) { + return normalizeExportCellText(title); + } + } + return void 0; + } + function readMarketGenderLabel(value) { + const rawValue = typeof value === "number" ? String(value) : readString(value); + if (rawValue === "1") { + return "\u7537"; + } + if (rawValue === "2") { + return "\u5973"; + } + return void 0; + } + function readBurstRateDisplay(value) { + if (value === null) { + return void 0; + } + if (value <= 0) { + return "-"; + } + return formatFractionPercent(value); + } + function formatCurrencyValue(value) { + if (value === null) { + return void 0; + } + return `\xA5${value.toLocaleString("en-US", { + maximumFractionDigits: 0 + })}`; + } + function formatWanValue(value) { + if (value === null) { + return void 0; + } + return `${formatDecimalWithGrouping(value / 1e4)}w`; + } + function formatFractionPercent(value) { + if (value === null) { + return void 0; + } + return `${formatDecimalDisplay(value * 100)}%`; + } + function formatDecimalDisplay(value) { + if (value === null) { + return void 0; + } + return value.toLocaleString("en-US", { + maximumFractionDigits: 1, + minimumFractionDigits: 0, + useGrouping: false + }); + } + function formatDecimalWithGrouping(value) { + return value.toLocaleString("en-US", { + maximumFractionDigits: 1, + minimumFractionDigits: 0 + }); + } + function readNumericValue(value) { + if (typeof value === "number" && Number.isFinite(value)) { + return value; + } + if (typeof value === "string") { + const trimmedValue = value.trim(); + if (!trimmedValue) { + return null; + } + const parsedValue = Number(trimmedValue); + return Number.isFinite(parsedValue) ? parsedValue : null; + } + return null; + } + function readStringArray(value) { + if (Array.isArray(value)) { + return value.filter((item) => typeof item === "string"); + } + if (typeof value === "string") { + try { + const parsedValue = JSON.parse(value); + return Array.isArray(parsedValue) ? parsedValue.filter((item) => typeof item === "string") : []; + } catch { + return []; + } + } + return []; + } + function readArrayLike(value) { + if (Array.isArray(value)) { + return value; + } + if (typeof value === "string") { + try { + const parsedValue = JSON.parse(value); + return Array.isArray(parsedValue) ? parsedValue : []; + } catch { + return []; + } + } + return []; + } + function readRecordLike(value) { + if (isRecord(value)) { + return value; + } + if (typeof value === "string") { + try { + const parsedValue = JSON.parse(value); + return isRecord(parsedValue) ? parsedValue : null; + } catch { + return null; + } + } + return null; + } + function readKnownNumber(record, keys) { + for (const key of keys) { + const value = readNumericValue(record[key]); + if (value !== null) { + return value; + } + } + return void 0; + } + function readKnownNumberDeep(value, keys) { + if (!isRecord(value)) { + return null; + } + const directValue = readKnownNumber(value, keys); + if (typeof directValue === "number") { + return directValue; + } + for (const nestedValue of Object.values(value)) { + const candidate = readKnownNumberDeep(unwrapVueRef(nestedValue), keys); + if (typeof candidate === "number") { + return candidate; + } + } + return null; + } + + // src/content/market/page-bridge.ts + var BRIDGE_MARKER = "__SCES_MARKET_PAGE_BRIDGE_INSTALLED__"; + var MARKET_SEARCH_REQUEST_PATH = "/gw/api/gsearch/search_for_author_square"; + var SERIALIZED_MARKET_ROWS_ATTRIBUTE = "data-sces-market-rows"; + installMarketPageBridge(); + function installMarketPageBridge() { + if (window[BRIDGE_MARKER]) { + syncSerializedMarketRows(); + return; + } + window[BRIDGE_MARKER] = true; + installMarketRequestSnapshotBridge(); + syncSerializedMarketRows(); + const observer = new MutationObserver(() => { + syncSerializedMarketRows(); + }); + observer.observe(document.documentElement, { + childList: true, + subtree: true + }); + window.setInterval(() => { + syncSerializedMarketRows(); + }, 1e3); + } + function installMarketRequestSnapshotBridge() { + installFetchSnapshotBridge(); + installXmlHttpRequestSnapshotBridge(); + } + function syncSerializedMarketRows() { + if (typeof document === "undefined") { + return; + } + const nextSerializedRows = JSON.stringify(readSerializedMarketRows()); + if (document.documentElement.getAttribute(SERIALIZED_MARKET_ROWS_ATTRIBUTE) !== nextSerializedRows) { + document.documentElement.setAttribute( + SERIALIZED_MARKET_ROWS_ATTRIBUTE, + nextSerializedRows + ); + } + } + function installFetchSnapshotBridge() { + if (typeof window.fetch !== "function") { + return; + } + const originalFetch = window.fetch.bind(window); + window.fetch = async (input, init) => { + const requestSnapshot = readFetchSnapshot(input, init); + const response = await originalFetch(input, init); + if (requestSnapshot) { + const clonedResponse = response.clone(); + void captureMarketSnapshotFromResponse( + requestSnapshot, + () => clonedResponse.json() + ); + } + return response; + }; + } + function installXmlHttpRequestSnapshotBridge() { + const OriginalXmlHttpRequest = window.XMLHttpRequest; + if (!OriginalXmlHttpRequest) { + return; + } + const originalOpen = OriginalXmlHttpRequest.prototype.open; + const originalSend = OriginalXmlHttpRequest.prototype.send; + const originalSetRequestHeader = OriginalXmlHttpRequest.prototype.setRequestHeader; + OriginalXmlHttpRequest.prototype.open = function(method, url, ...rest) { + this.__scesMarketSnapshot = { + headers: {}, + method, + url: String(url) + }; + return originalOpen.call(this, method, url, ...rest); + }; + OriginalXmlHttpRequest.prototype.setRequestHeader = function(name, value) { + this.__scesMarketSnapshot?.headers && (this.__scesMarketSnapshot.headers[name] = value); + return originalSetRequestHeader.call(this, name, value); + }; + OriginalXmlHttpRequest.prototype.send = function(body) { + const snapshotState = this.__scesMarketSnapshot; + if (snapshotState) { + snapshotState.body = typeof body === "string" ? body : void 0; + this.addEventListener("load", () => { + if (this.status < 200 || this.status >= 300 || typeof this.responseText !== "string") { + return; + } + void captureMarketSnapshotFromResponse( + snapshotState, + async () => JSON.parse(this.responseText) + ); + }); + } + return originalSend.call(this, body); + }; + } + async function captureMarketSnapshotFromResponse(snapshot, readPayload) { + if (!isMarketSearchRequest(snapshot.url)) { + return; + } + try { + const payload = await readPayload(); + if (!parseMarketListResponse(payload)) { + return; + } + writeMarketListRequestSnapshot(document, { + body: snapshot.body, + headers: snapshot.headers, + method: snapshot.method, + url: snapshot.url + }); + } catch { + } + } + function readSerializedMarketRows() { + const marketList = readMarketList(); + return marketList.map((row) => { + const attributeDatas = isRecord2(row.attribute_datas) ? row.attribute_datas : {}; + const singleVideoAfterSearchRate = readNormalizedFractionRate( + attributeDatas.avg_search_after_view_rate_30d + ); + return { + authorId: readString2(row.star_id) ?? readString2(attributeDatas.id) ?? "", + authorName: readString2(attributeDatas.nickname) ?? readString2(row.nick_name) ?? "", + singleVideoAfterSearchRate + }; + }).filter((row) => Boolean(row.authorId || row.authorName)); + } + function readFetchSnapshot(input, init) { + const request = input instanceof Request ? input : null; + const method = init?.method ?? request?.method ?? "GET"; + const url = request?.url ?? String(input); + const body = typeof init?.body === "string" ? init.body : typeof request?.bodyUsed === "boolean" && request.bodyUsed ? void 0 : void 0; + const headers = serializeHeaders(init?.headers ?? request?.headers); + return { + body, + headers, + method, + url + }; + } + function serializeHeaders(headers) { + if (!headers) { + return void 0; + } + if (headers instanceof Headers) { + return Object.fromEntries(headers.entries()); + } + if (Array.isArray(headers)) { + return Object.fromEntries(headers); + } + return Object.fromEntries( + Object.entries(headers).map(([key, value]) => [key, String(value)]) + ); + } + function readMarketList() { + if (typeof document === "undefined") { + return []; + } + const marketRoot = document.querySelector(".base-author-list"); + const setupState = marketRoot?.__vue__?._setupState; + if (!setupState) { + return []; + } + for (const value of Object.values(setupState)) { + const candidate = unwrapVueRef2(value); + if (Array.isArray(candidate) && looksLikeMarketList(candidate)) { + return candidate; + } + if (!isRecord2(candidate) || !Array.isArray(candidate.marketList)) { + continue; + } + if (looksLikeMarketList(candidate.marketList)) { + return candidate.marketList; + } + } + return []; + } + function isMarketSearchRequest(url) { + return url === MARKET_SEARCH_REQUEST_PATH || url.startsWith(`${MARKET_SEARCH_REQUEST_PATH}?`) || url.includes(`${MARKET_SEARCH_REQUEST_PATH}?`) || url.endsWith(MARKET_SEARCH_REQUEST_PATH); + } + function looksLikeMarketList(value) { + const firstRow = value[0]; + return isRecord2(firstRow) && ("star_id" in firstRow || "attribute_datas" in firstRow); + } + function unwrapVueRef2(value) { + if (isRecord2(value) && "value" in value) { + return value.value; + } + return value; + } + function isRecord2(value) { + return typeof value === "object" && value !== null; + } + function readString2(value) { + return typeof value === "string" ? value : null; + } + function readNormalizedFractionRate(value) { + return typeof value === "string" ? normalizeFractionRateDisplay(value) ?? void 0 : void 0; + } +})(); diff --git a/dist-release/manifest.json b/dist-release/manifest.json new file mode 100644 index 0000000..9df1c42 --- /dev/null +++ b/dist-release/manifest.json @@ -0,0 +1,58 @@ +{ + "action": { + "default_icon": { + "16": "assets/icons/icon-16.png", + "32": "assets/icons/icon-32.png" + }, + "default_popup": "popup/index.html" + }, + "background": { + "service_worker": "background/index.js" + }, + "content_scripts": [ + { + "js": [ + "content/index.js" + ], + "matches": [ + "https://xingtu.cn/ad/creator/market*", + "https://*.xingtu.cn/ad/creator/market*" + ], + "run_at": "document_start" + } + ], + "description": "Bootstraps the Xingtu creator market content script.", + "icons": { + "16": "assets/icons/icon-16.png", + "32": "assets/icons/icon-32.png", + "48": "assets/icons/icon-48.png", + "128": "assets/icons/icon-128.png" + }, + "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0CaZJxcX97TbRXCR08L10t9EZFV31+wPnUgDf21j2f0qYaWdblzWXfVkeU9jGb2Hr2Etpp7F/XuBa6pcipUXkzMMBkJ42KOkciAwbuzTBoAtGB8o9aoWigtax+gGfSz+T3BjqxKBJtXqeqbIAKCDIlxRKIrY+KcY1Z+mD5BKcBHKsUDQPlHsrjc1g0wIBD5doz9LoOk1Wso6gK5cSeOp9lw5YHcu4TImR4yqxGiL6pZwnpciuX/g7qjWBZXn5gf0YBlDsBDDTt5upbP3NguUKgO2qA9M77LyeUwXl3aqbIxYi/VwsQ2t5w9PGWtnOUQQDWUcEg/9dfTb89esZXKATwIDAQAB", + "manifest_version": 3, + "name": "Star Chart Search Enhancer", + "permissions": [ + "downloads", + "identity", + "storage" + ], + "version": "0.2.0421.2", + "web_accessible_resources": [ + { + "matches": [ + "https://xingtu.cn/*", + "https://*.xingtu.cn/*" + ], + "resources": [ + "content/market-page-bridge.js" + ] + } + ], + "host_permissions": [ + "https://xingtu.cn/ad/creator/market*", + "https://*.xingtu.cn/ad/creator/market*", + "https://login-api.intelligrow.cn/*", + "https://talent-search.intelligrow.cn/*", + "http://192.168.31.21:8083/*" + ] +} diff --git a/dist-release/popup/index.html b/dist-release/popup/index.html new file mode 100644 index 0000000..6e17f31 --- /dev/null +++ b/dist-release/popup/index.html @@ -0,0 +1,12 @@ + + + + + + Star Chart Search Enhancer + + +
+ + + diff --git a/dist-release/popup/index.js b/dist-release/popup/index.js new file mode 100644 index 0000000..2003be9 --- /dev/null +++ b/dist-release/popup/index.js @@ -0,0 +1,219 @@ +"use strict"; +(() => { + // src/popup/view.ts + function renderLoggedOut(root, error) { + root.innerHTML = ` +
+

Star Chart Search Enhancer

+

\u767B\u5F55\u540E\u624D\u80FD\u4F7F\u7528\u661F\u56FE\u589E\u5F3A\u529F\u80FD

+ ${error ? `

${error}

` : ""} + +
+ `; + } + function renderLoggedIn(root, authState) { + const userInfo = authState.userInfo; + root.innerHTML = ` +
+

Star Chart Search Enhancer

+

\u5DF2\u767B\u5F55

+

${userInfo?.name ?? userInfo?.username ?? "\u672A\u77E5\u7528\u6237"}

+

${userInfo?.email ?? ""}

+ +
+ `; + } + function renderDevPanel(root, authState) { + const panel = root.ownerDocument.createElement("section"); + panel.dataset.popupDevPanel = "root"; + panel.innerHTML = ` +

dev auth panel

+

resource: ${authState.resource ?? ""}

+

scopes: ${(authState.scopes ?? []).join(", ")}

+

token: ${authState.tokenAvailable ? "available" : "missing"}

+

expires: ${authState.accessTokenExpiresAt ?? "unknown"}

+

error: ${authState.lastError ?? ""}

+ +

+  `;
+    root.appendChild(panel);
+  }
+  function setProtectedApiResult(root, value) {
+    const output = root.querySelector(
+      '[data-popup-protected-api-result="output"]'
+    );
+    if (!output) {
+      return;
+    }
+    output.textContent = value;
+  }
+
+  // src/shared/auth-config.ts
+  var defaultAuthConfig = {
+    apiResource: "https://talent-search.intelligrow.cn",
+    appId: "i4jkllbvih0554r4n0fd3",
+    enableDevAuthPanel: false,
+    logtoEndpoint: "https://login-api.intelligrow.cn",
+    scopes: ["openid", "profile", "offline_access", "talent-search:read"]
+  };
+  function readAuthConfig(overrides = {}) {
+    const nextConfig = {
+      ...defaultAuthConfig,
+      ...overrides
+    };
+    if (!nextConfig.logtoEndpoint.trim()) {
+      throw new Error("auth config logtoEndpoint is required");
+    }
+    if (!nextConfig.appId.trim()) {
+      throw new Error("auth config appId is required");
+    }
+    if (!nextConfig.apiResource.trim()) {
+      throw new Error("auth config apiResource is required");
+    }
+    return nextConfig;
+  }
+
+  // src/shared/auth-messages.ts
+  function isAuthResponseMessage(value) {
+    if (!value || typeof value !== "object") {
+      return false;
+    }
+    const candidate = value;
+    if (candidate.ok === false) {
+      return candidate.type === "auth:error" && typeof candidate.error === "string";
+    }
+    if (candidate.ok !== true || typeof candidate.type !== "string") {
+      return false;
+    }
+    if (candidate.type === "auth:ack") {
+      return true;
+    }
+    if (candidate.type === "auth:token") {
+      return Boolean(
+        candidate.value && typeof candidate.value === "object" && typeof candidate.value.accessToken === "string"
+      );
+    }
+    if (candidate.type === "auth:state") {
+      return Boolean(
+        candidate.value && typeof candidate.value === "object" && typeof candidate.value.isAuthenticated === "boolean"
+      );
+    }
+    return false;
+  }
+
+  // src/shared/protected-api-client.ts
+  function createProtectedApiClient(options) {
+    const fetchImpl = options.fetchImpl ?? fetch;
+    return {
+      async loadProtectedMockData() {
+        const token = await readAccessToken(options.sendMessage);
+        const response = await fetchImpl(
+          new URL("/api/mock/protected", options.baseUrl).toString(),
+          {
+            headers: {
+              Authorization: `Bearer ${token}`
+            },
+            method: "GET"
+          }
+        );
+        if (response.status === 401 || response.status === 403) {
+          throw new Error("protected api unauthorized");
+        }
+        if (!response.ok) {
+          throw new Error(`protected api request failed: ${response.status}`);
+        }
+        return response.json();
+      }
+    };
+  }
+  async function readAccessToken(sendMessage) {
+    const response = await sendMessage({ type: "auth:get-access-token" });
+    if (!isAuthResponseMessage(response) || !response.ok || response.type !== "auth:token" || !response.value.accessToken.trim()) {
+      throw new Error("protected api token unavailable");
+    }
+    return response.value.accessToken;
+  }
+
+  // src/popup/index.ts
+  async function bootPopup(options = {}) {
+    const currentDocument = options.document ?? document;
+    const popupConfig = readAuthConfig(options.config);
+    const root = currentDocument.querySelector("#app");
+    const HTMLElementCtor = currentDocument.defaultView?.HTMLElement;
+    if (!root || HTMLElementCtor && !(root instanceof HTMLElementCtor)) {
+      throw new Error("popup root #app is required");
+    }
+    const sendMessage = options.sendMessage ?? ((message) => Promise.resolve(
+      globalThis.chrome?.runtime?.sendMessage?.(message)
+    ));
+    const fetchProtectedApi = options.fetchProtectedApi ?? createProtectedApiClient({
+      baseUrl: "http://127.0.0.1:4319",
+      sendMessage
+    }).loadProtectedMockData;
+    await renderCurrentAuthState(root, popupConfig, sendMessage, fetchProtectedApi);
+  }
+  async function renderCurrentAuthState(root, popupConfig, sendMessage, fetchProtectedApi) {
+    const response = await sendMessage({ type: "auth:get-state" });
+    if (!isAuthResponseMessage(response) || !response.ok || response.type !== "auth:state") {
+      renderLoggedOut(root, "\u8BA4\u8BC1\u72B6\u6001\u8BFB\u53D6\u5931\u8D25");
+      return;
+    }
+    if (!response.value.isAuthenticated) {
+      renderLoggedOut(root, response.value.lastError);
+      root.querySelector('[data-popup-sign-in="button"]')?.addEventListener("click", () => {
+        void runAuthAction(root, popupConfig, sendMessage, {
+          actionMessage: { type: "auth:sign-in" },
+          fetchProtectedApi
+        });
+      });
+      return;
+    }
+    renderLoggedIn(root, response.value);
+    root.querySelector('[data-popup-sign-out="button"]')?.addEventListener("click", () => {
+      void runAuthAction(root, popupConfig, sendMessage, {
+        actionMessage: { type: "auth:sign-out" },
+        fetchProtectedApi
+      });
+    });
+    if (popupConfig.enableDevAuthPanel) {
+      renderDevPanel(root, response.value);
+      root.querySelector('[data-popup-test-protected-api="button"]')?.addEventListener("click", () => {
+        void runProtectedApiProbe(root, fetchProtectedApi);
+      });
+    }
+  }
+  async function runAuthAction(root, popupConfig, sendMessage, options) {
+    const response = await sendMessage(options.actionMessage);
+    if (isActionError(response)) {
+      renderLoggedOut(root, response.error);
+      root.querySelector('[data-popup-sign-in="button"]')?.addEventListener("click", () => {
+        void runAuthAction(root, popupConfig, sendMessage, options);
+      });
+      return;
+    }
+    await renderCurrentAuthState(
+      root,
+      popupConfig,
+      sendMessage,
+      options.fetchProtectedApi
+    );
+  }
+  function isActionError(response) {
+    return isAuthResponseMessage(response) && !response.ok && response.type === "auth:error";
+  }
+  async function runProtectedApiProbe(root, fetchProtectedApi) {
+    setProtectedApiResult(root, "\u8BF7\u6C42\u4E2D...");
+    try {
+      const result = await fetchProtectedApi();
+      setProtectedApiResult(root, JSON.stringify(result, null, 2));
+    } catch (error) {
+      setProtectedApiResult(
+        root,
+        error instanceof Error ? error.message : String(error)
+      );
+    }
+  }
+  if (typeof document !== "undefined") {
+    void bootPopup();
+  }
+})();
diff --git a/docs/【超简单版】插件安装使用指南.md b/docs/【超简单版】插件安装使用指南.md
new file mode 100644
index 0000000..52634a3
--- /dev/null
+++ b/docs/【超简单版】插件安装使用指南.md
@@ -0,0 +1,132 @@
+# 🌟 星图增强插件 - 超简单使用指南
+
+> 适合:完全没用过插件的新手 | 阅读时间:3分钟
+
+---
+
+## 📦 第一步:拿到压缩包
+
+你会从同事那里收到一个文件:
+
+**`star-chart-search-enhancer-internal.zip`**
+
+把它保存在桌面上,不要删掉。
+
+---
+
+## 📂 第二步:解压(右键就行)
+
+1. 在桌面上找到这个压缩包
+2. **右键** → 选择"解压到当前文件夹"(或"Extract Here")
+3. 会多出一个文件夹,名字类似 `star-chart-search-enhancer-internal`
+
+⚠️ **重要**:这个文件夹要一直放在桌面,不要删、不要改名
+
+---
+
+## 🔧 第三步:安装到 Chrome(只需做一次)
+
+1. 打开 **Chrome 浏览器**
+2. 在地址栏输入:
+   ```
+   chrome://extensions
+   ```
+   然后按回车
+
+3. 右上角找到 **"开发者模式"** → 打开开关(点一下变蓝色)
+
+4. 点击左上角出现的 **"加载已解压的扩展程序"**
+
+5. 选择刚才解压出来的那个文件夹
+
+6. 看到绿色的插件卡片出现,就装好了!
+
+✅ **检查**:点击"详情",确认 ID 是 `pkjopdibdnomhogjheclhnknmejccffg`
+
+---
+
+## 🔑 第四步:登录(只用登录一次)
+
+1. 点击 Chrome 右上角的 **拼图图标** 🧩
+2. 找到 **Star Chart Search Enhancer**
+3. 点击 **图钉** 📌 把它固定到工具栏
+4. 点击插件图标,然后点 **"登录"**
+5. 按提示完成公司账号登录
+
+---
+
+## 🚀 第五步:开始使用
+
+### 打开星图页面
+
+访问:
+```
+https://xingtu.cn/ad/creator/market
+```
+
+等待页面加载,你会看到页面上多了一排新按钮。
+
+---
+
+## 📝 主要功能
+
+### 1️⃣ 导出 Excel 表格
+
+- 勾选你想导出的达人(不勾就选全部)
+- 选择范围:当前页 / 前5页 / 全部
+- 点击 **"导出CSV"**
+- 文件自动下载到电脑的"下载"文件夹
+
+### 2️⃣ 提交批次
+
+- 勾选你想提交的达人
+- 点击 **"提交批次"**
+- 输入批次名称(例如:`5月母婴达人第一批`)
+- 点击确认
+
+---
+
+## 🔄 如何更新插件
+
+收到新版本压缩包时:
+
+1. 删掉桌面上的旧文件夹
+2. 解压新的压缩包
+3. 打开 `chrome://extensions`
+4. 找到插件卡片,点击 **"重新加载"** 🔄
+
+---
+
+## ❓ 常见问题
+
+### Q: 页面没有多出按钮?
+A: 先点击插件图标确认已登录,然后刷新页面(按 F5)
+
+### Q: 提示登录失败?
+A: 关闭弹窗再试一次,或检查网络连接
+
+### Q: 导出没反应?
+A: 检查浏览器的下载列表,文件可能已经下好了
+
+### Q: 不小心把文件夹删了?
+A: 重新解压压缩包,然后到 `chrome://extensions` 点"重新加载"
+
+---
+
+## ✅ 每日使用 checklist
+
+- [ ] 打开 Chrome,确认插件图标在
+- [ ] 点击图标,确认显示"已登录"
+- [ ] 打开星图页面
+- [ ] 正常使用导出/提交功能
+
+---
+
+## 🆘 还是不行?
+
+把下面信息发给同事:
+1. 你在哪一步卡住了
+2. 页面截图
+3. 扩展 ID(从 chrome://extensions 里看)
+
+**记住正确的 ID:`**pkjopdibdnomhogjheclhnknmejccffg**`
diff --git a/release/star-chart-search-enhancer-chrome-web-store.zip b/release/star-chart-search-enhancer-chrome-web-store.zip
new file mode 100644
index 0000000000000000000000000000000000000000..6397d89ecf946442470e08896faabd6e1182f2b3
GIT binary patch
literal 85680
zcmV)NK)1h8O9KQ7000000EB^^TmS$7000000000001E&B0AgWdYiDwAb#7!YP)h>@
z6aWAK2mpkEom>DAiGxgK002nQ0RR&K003fPV{2z}Z*^{DFKKRMWq2-XbM3wTUmHh~
zIQ)D5im}djJFcM6tE;Q4tE;N3s~giYPs(ai^s2_@7iro|w!Ta5zetkx^`xBi*2}AGlK0oM
zX?3;M8x1dt%XU>l@ohFq`uRmR9aK9|wo66H7Bx+hY+M}XbrZlZ*Z{
zRVN>2=Y#xtev2I+WW#*WNiMQMnRD@AbXkq|hW+sfdJw(C_hPsPn8kZ8d!un)c9N3@
z{5vfAjaJeaPevETAjdyP7Z-zKn0K>YFE2~{;*6#<$+Ldr6d=tu;XfDCVXrDi!vsHD
z`lO@Vd@?Eed5M&oH5Ijhu4R=B^AD9r#w2OC+X0nZw#>kzPt7lv;GC=3=lfB7gG)Wsc)d^3vOUtAvVLX4G7QhgVCigXq_DHk1T2Itul^zU(
zt=f-iSl`&kj1>Z<%3Yn`0xIu&BFbDI?dlm%{Q
zAkilK!;4YJU=K3m2C8;wIUWJO3@>+a)Mo4rDsMDfrok|~$>-F^Vp+YMp3kWbrLr<2
zxB$Mc(rBtyvzl40gK(YSx#HzE8%%SMEL>r`eF8O3H|1PccjJ6?p(}1}0p0|-k!-7v
zo#b{@^phuxmIL%yO-6%3K8dagCCXHlbTr1Y(nYtYC7~*9s}H~ho=k0SMj5ue8}^dR
zyxOsxn>GbUsQMZ_;=Ma4fPdRwqh26!RF6P|R?wSSRawzZ-@CMi0ryj+9K-;
zpTmSTH6}1p?(XQi7y}~fkCH!ky9e(M_qyHW(Ry-pcXK`(qz$KD!!+-j?>Gn^cME}z
z^GQojMGMAsl;^_;c-+r_&a>;+*%&u_rKKjirO=uBc|P{`%_^G!%ff~*lgbmf^i?Ou
zpna8<3QM6{DBf080Hm(s=qg-Vno={oHshgc^J2SK$R#r??6|z25ArJa+RCOtyq(D;
zyF-Fz_y>`N{%S*6ngW0u;A)3in2~JJwwM|HwRT>bum$LrmSThi$}If1mS`H=7|AY1
zlO*Lq;l9-3#c-Mc4>D$L=y6iykts2x0O<^BGSGr?Pc0l6hU}7&7A>~6T;}#fcU26h
zxhoIA%77U=0iJw`y}-XeaYy$_c{Q32`iFUMIw^6#Ma_if_I`HC$Z@w47ly+Uq1y$k
zqZ)O)jb+fl)|x?(?{Oi!7{CW_>NU1a*@6BDD7w>WY6GX3DYPFul6@>4>iEaUpP5<_
z66vEsMAUJ+09+f(_Fp4a^f=Yl=~Rx|4aXp-*>*Ss(FwI+x6X!%27fuKl3&gq-t+I-
zFK0>m@LtJw^{sgpGbp-?QLWu*dY}ysdRdwKTg|(JgT2GuoufSznkT=E?_W)4r|VNK
zcVE5z*()A6#d|x?_uu@`-Q79ZKi+wTmHtNqNw**9Kbz~9rpf;Ey*J1EFZTBiv3818
zb_V0CYzBY4nRQQpd)Tz_kM<6B4tI{<9v)Hu-S#hQ$?4;Dzk8<|P66*)Y2$wy$zuVe
zEi^C}e0S%~^R9!M022TJpti3125R@^)NWXB-o5^QZvouKFTeC3H$xg!b1FqX*bti_N~5BDm6g@*RW>1L
z&;f0Mn~@3xqpreAl@1hweYYaXbE=KJ3T00=)t}!cJnHr!A6`~h>ht5rzCiB*@C+6n
zV!$mT0d|0!tv_K@#ZuJPgj-0O*Gk!Jcex@n9?N!x1>EBC(c)7F3sKU>XXv-z7V!1*#Dyt+I*-6q{uyZ)ofA1}lE{jt_w%aTl`qMMJZcvJ
z5K{;RS?__Y_c>W5-dzN(DEd*fX5n_o^JO-4M@~i<14U*r98W7pVhSnf?Pcu&3~S#A
zAlWm4X;1R;AnWBjgF)&wZJ~Zx^{&`z6Qks>O&8};SshG9=rM3mG&B?_*6vp^WaB%~
zD#MCH(4&L>C97bHhM<02T!6hoh@LdM=-ysyoVJT$Z!qnH*3E!%PIo|cp}Mf%2#6Bo
zP1XrGKZ;@!t6CxeVqI9-eROPG6vT4hIlx4bodfG#(wnQEgP8u8Dn*T|xNa^G
zOs?)rb(#xQ#D-B3tE*grtwzato}4M+^_$*?PS0FFb7;Gcv$B`b7(5Gh-oo&z)|*(rtlRGMnFXNun=W{HI=eOc&mLvu4^=8YN{Y8ThZ;pvE&7#egrO-$rs>a
zD@JjN67#8;WhfWwFzwtvCj=z72Ak(LwfqX>a#kvVBw1jI#~;I4yvj;RI_4MLMd}*k
zAY`MEi35c@vUPaMwi(l$rRMUj!`Di{rJ+d!(p0Yu-DH`*fTHt?qkCaJy``tX&RR&g
zU=p?1f6_!vi$Af7^)zPVirp}_71r9ff1MV+>$SmT>f5*fi3P6?-|^W6?6LWWDj)XC
z-+WH`M!2PNr}yx-7yEDakN?|gKN{}c7QBO781|!6x0m&<
z@*3|jd4^rcgZ}PH4Z0-{_laa|;MC){&);^Ecd#bMlj0T#r&#eOudYVGitn#-?VrL8
z{|zuUFmUqp>o!5?<~K#9$5W;>hz(aHD<<#>f-;f{G?=&EO
zYU;Q7JRzpJciAbuf5E4~ecLEH9D2Il_lNPkxxypu8><6XRprElF*s`o6&84JUYyK
zU`NGf-|0TK4AdC&s)qQFy6U86r-VNGAPvRAtB_7KdJx@)|)RJmRNN7zq=wI^gZ09WSM>8{#!?e-bc{j6Gpeh*kU7_MfgfDS$7YZ
zKQqqK7j^yRzls3x6f1|Bm&3tS57DrKV9q93Lr88{v-%|0)C%!9;axd~=Z{7kle*c=
zQ-^undSljc2{oFh`i!bbojwO!gx$Z%Gek{fywH+d5tGr9kUUQDfd^rUWI4fizj~tU
zUeipGVOF=*V>>D0G}@~$y8`uK4*x`!z(;cRvYiFIzO=HVH}sF80b^xV0wMZ7X}D3i
z!44}IkJ#SkYiGT>-B5_oxFWE&HixOA8!ehm3Z&yG8RXd{jp{P0C~Emc3!_%fB*(9K
zgzu^~Y$~hIC=T?Wzqe^@WiuM{C+&7y=~01xVa^1($s|WPyE~c=E45vg+84H_v6mAl
z>woJT)k4$KniWBuqp~g3$h>Kg7}g3eAJOkzMB_>(LpDcdqJ1-J0{J6xMy%k}09j2Z
zt<#ljybsQ#DLoU`N*PxzDY8{7Rgy@o%|K~P7(Algpbn&rNQ#54wYVOgaAaH?s5r^0
z(d2Xqjrf17Dkuyh&e%!Kq4
zPcgCENS#J#G@(*#`!b4CS2*(aA~8BZF_2zu-hg~(<>FbF{aG(l$lYoXue0i^eNzmj
z59+Z4q~$uK)4N1GX7W;Q&{KPRv3u8d=F`I*J*%Xiofyu0e;w+RmAo
zAV#SO>r=UuJPycso#bi$m8h))Z8tvp4#e+#p`n^&!xGr_Mnvtnr-#lgn8@Lc;JjRh
z-#A7aNBFB+`3H)oF%cd1=zPl!;3%un_yCrDsXtI;_tq)_A#(%lG$_W@zjnY#8yt@E
zN=-TZm732^dE2ra8Hs2F?a63;SZz2RIFK?}o<5pi6^cm;yj>a+wW_zh!is
zP51%bJ4D2exj#J;l>&^-g=&ek`RL;P4oV|LH=hlr_RC4*K;=Uq>~wO3&7j&IU8bf=
ze6KpJa&R>oYB=;~SY@Z*pO~r2)Q_+lUuuGlJ>!}^`rYm0hp_fO1&~&t*KzH_{thc2
zjt08kg#HYxymjWon>D()9+|Rw5TeIl`Ii-*neW6Ur
zmWxTAgFVJfa$*{{6_1=^CJnm5j(IeS9taWo(_Cyy4SV;3h;F;oK4Tk}!raRyBTUhv!=?$A&UXP<|xjSC2
z*@H?Q)gGs%7+#D%VwUGjJR`F^OWuzr*BK>ZXzS*A342_%)-OuTl(B|6P1bPN
zgUxyk=uMe_^8Q+RH>|P`)X1PQy4h3y1NBL{$j!i%R?(YICfaH}QHqHArmYpUsvSXc
zqAGye0YxtRnX*%AecHq%7|p1`9aSAAt$C!wQxB64ifP4;0;h{g{HPGKbDaKa8qsraB_#8AeGr}z{@n;u>Kv-2}cOb2p!#T99p)^f-c1Un2XIvQ_6aNnC1mNd`TxL~x4OnT`mDR6Uy)oLac7i7AOU)dS*yNg|lSOJ^mK0Tk
z{tRk}Vbo3W5RV#Zk-j#|tFRwYd`1AvZPM6OQZI?E-xtNCtd4rHXDOU6@I$xcFA?t3
zH@Kt%9$!|^X-bbMy$jb?lZ;tfxkQVc$$zd)J_-kzJwANn6*>#TIJ?x1v(IPL=>7mT*
zrXG)I9C(`rjq2d-(Q!j-gjadi2edj;J!`vanXY<1>fd$bQ1pRL%GuGhvruQAay)7E
zBXDo=$~7VP3%eW$fpQ)@&s{JUq@{Q(896eyrIO!~SDyRZ{QEDLLl1ZR>r)u{Fog5D
zd6@3JIRst`>RWG4JP>{lJZ0PZGVC%vkQ$&TTiu>b8qIkNP?GB(dm+}2L@&tYcD7N`
z@9C7ZW@iI4w}(kl@A!x)X;8KG_WOJ=Si2sM-Vc=vTD6=`GNX4JDexAWm`to{@#kVC
z%jNHm(Vqz2YWe+olHUSJ?11>U#RGq{QEKPc6FNSM7M)mQW{wzZEX^3q7BP9GIqxKp
zKc^jwc2J49;O&3R+h-;4gt>pZE=2
zkB9@$IU1b~3!uJf7K@C;b5-<@xP7#ez}rTy5*Ja9=GTY27byL-;1sssmJ{M{Xxe<7Ls
z0YY()ZKaMoyZ>cA#Nf=FjSW!I5U=~halFJ9T%ZRVx`1>?^GyqRyF-;Ng;FcIu(p#-
zdjU(%{=iH(jx~qptjZ#9DNi6{4I7m(fAC&IHOUT?(xOs%1dPw==>mSAP6lEj&r>-*
za)}Go__X7YF@z_{ia;GQ&#%th={Mr9VNpRF;uE$V5noCH!TXn574g;s1qnDE*o73C={j}A1L5mIhAmeE{>pN*h2X=M
ze7+j^=gtZ_dw4HFwRzv0b-d4fm3!tU@e`44#=0F{*mcdacs1;nP+*0SSPk|IDP1HK
z)q_a+R4&
z2=TjAbflN)R5q8fE_1MqL<&c;Zov|WZfmpchxakyR`23as@3#{(X_IPgWP4`PAjv`
z0`lsJEVjpvV_xM?+q35HRz@`AG)8-0jcKB8@tSePG#Hq%kV2n*y6_Bc4G-ZwKjAx-
zPT$%fI>El3Eb%-*z4Z|`yLau3`^0f>b&|91VRRrSfMab3vok(-tFZveVgUBvRW|Ie
zLkkoJ*}$3ubV9q%A-C3O%==S5>&p`-l`?AOT0`frr=QR%6ihg|iRpPbs$M|NJ2yo3
z`_X8SXTwx4<&W(VmPNn790DAGYyQtaE+WYkH*9GS&i6Tu8q<
zlt}7hhoQaiGP^qJQw664v~&xjhtv9Kw+dH?@^jC{6mX+lbc-8
zCN&abJO+lB)UX3!~(Y)+s
z<2>ckcZd7CU}S(^HLL_M8)mJTe9lCrPCuGY7|(vL@O0~hxDE~AJrC8o``_>k75_ecD<9MzIS8Rcqy8O<|8L^Gm!p5_Ow#PW}@WDJ}G0
z)d*Ez-Cn8ez@F_AHsp%_^lp6VW+1=ypCljKOXtf!u^6AWb95G`l)aYyx$uVp=-w&A
zp|r;%=NfZeKf3m`yh>GHG0hIfmps;$&EOr+6f2XO*tpnXV#yPT7Z5O%lF6?0+*D7E
zu4<}zZCZ({u)HTVo17P5luYi{coUTy@{TUEZ+u|joV@abzk?e;^wB4gSUo?>}?P3T!IQ%NI3PZj2`6mpcoMNi~D#4He-1sr2>;7|gL@T#=2!%@p
z9KVIW)rQe2DvXHT@NF5l(uJ*;vgPJ|1a=Hv>xMA1`-v$o2`$|e%i4>3;#i{#j15HS
zM685<>T$}>7Q+KYHXLnEixet9Wb=`#{iUQ7kyfzS(}D+q
z1mar3fkBYU#(n$@8>s=w%+OZzrwSlH%k0vv;|T2l^%ZAAb+Ca6^QQ7zH&2Q#UTz);
z1l`@5mU;b5NOWTpf~TVHSVHWHJzLDBBHGbQTazm&^zUX+A{y#S;!|`01~(V+C3h3O
z@Yg_W*ga*OO>loK9B)!OMdy#F<(#yVzoM_lD2WXU(KxS0SyOXg&MWJC!1#>Ms{j9i{H1Dt|6OXOJ;Uv8?BI$)+E%sYSvY
zrXGDmqRWvvCnlPUgjXVUz|mDlsLb$AcJ%j~|z-FN8rfF?>-kRP6h)-3BT}gjPy$&Y_JLXZN7zoRWMj
zDM%TKnFU&eFE7H1zKroSmrB{^=swjbclqVE&S+*Y1r!w@qo(k)2j-H*u`h+2&!SUY~OJcdnyhP7F!}
zLkdWWAXVj<2z8sfs-0W5niS_#t~ruiyi5FfrMUq7X%hX{svz+g2=*np$mshAP@;aTas`cKJUn}~KbICcqRnc8M?V=p`)o2L^VjDBu@bK5
z0D>!Bg5r7s^XsV0*ZW0Tt)IhuLT~Gn=@9*z>+kb(c5I2DSpBKn&o46e+4BeMk70)w
zUz9SLM39w5f+bUDNt96bolh?=U`r(tXfa|cPgDfQasHv=gAtX?)^d=n@;vvdyx#e*
z?*5zOXDHt{l1Gn{XC#ts)|Jr^lyW@7U@W{>=v97FRfdM`w3nwiNtpXa#Vc_n3Vcf*
zt4}RhtCB6Cy^cgFhSfJ5(puVNZ8}5Yli-kqdq!d5;g{eCN_WErt)wt(twouMi}%WP^Xc
zO`Ll0Nj@q{pic^P%cyF2(1T{(PL)Q3Zm5Ohhv9)HTk=%&-prpGP_iY{fRR5y6^K=0
z2WK&~?G;;l;>OGCrz@+!%c>k77P`E8J}uc%*pt2^5v!oromV=;&1nrKd*kqKfhe7(gJsWj
z3?4z7+KJ3T7eexLex6_-M|t&`WE2eP&D-wlo#Wjf@xj`cd;c9Hhcm+EAZX&eo(`&F
zJjexr@}p^Vqk!=%<9N`H=}rGALcMUjU))t)ohqZqwngI)=qrXF4`8qu4)A4f2C
z^MYd8`Uyb#eAGDJf4%qi-EnOA3hVi8)NX+HfHJgneiFx{pSZP`8fGHTTtDyTe$+kM
z|KZKfF<#^T35=>2`@0bXL+&?oM!GWWr7UB**25k>%$)2VCQOG@iu_MGE_6H@VS4dK
zHn<#3it6fyOj2V5h?o`O5VqdH{wQagzGRh-C}#C4eB`c79^PXwGxH48!+Y#Q-LRZV
zLo{s#M)}E^P&IVukLto00;nR^&Q{&P=DeNDN6rbiYeByfYSP
zhtDP8Q2^KU;=d8C$6LwSXh?T~AKt5K9LwEG8qFEzkAVUNGi#e<^y2odivx18gGEgj
zCr?gi3|aktdK!Wcp~&W%OhfcaHcPstr~md20H($L@J642j>
z)y1&%k*ARu$WuaUG=6-&v)gDkO#?kfBLY>8O>frCk=B-#4ggolg$*kgWTUKCP3c;l
zD{&m0+9ZEAoe`*Zco=8+zaHbWqaSzH9^UJkv$K{I-4yU4;Ge^)zV_#t$$1zd`(cFa
zhpUtQ@M!1gXlL!<0Od5I4H?gb&Kq5IkXv(mAFAS
zn#&EQ(sJaB@a|rOclTE3-Mw9$nfbVKl{tJHs%*9V8qO!T`V=N!1_TtC|aRH=((?D0rINygsb*rhW_M%~RbBm~Q6Q=(dMe46$rz4&zy)4#7C6M$@POSZx+kc#O~dB9JDHFuREz(BRbKXyD@2
zMsg#zPByh$!O#~|LV@&5N$;**SYAhGFUiX|A-@@rU~oCJ2DQQ9tQLdS;zo*+C^INz
zZbR`=QcH&xS))?K9(fNcn%9Y@u}fW0ce@>X1(2Bxz;TFV!_bs+H{5Xst`jRx8}Ym!
zHFB`*!Z(y6&JEe;>RZBhrd8IHAWTLlliJdGQR*e2sw(Br6S@~2et)`u$oQ1u_ooj)#X@__V
zAfDENXz&Ygs)qM&T6kwr_D9IJvwmN+pCd3d!NmmWnaK#W_Xoj(Y|upe-w%#tHU%BeOUO>kS1OLuSG}d=P>kxf
zaN?SwSGV-rWaG(~-ztDd{FN8il9~8Y$
z0zMrAzZJv0AA^6C_W)WQWz2VFjT>@Adb^GcWu*lKQ`U_ht8gj+eCZK0UqLmEC+)2+
zSK}vuKt`9!@va@D$PzFB-${Dtc_(Cb$ERwW9C$|#ai5a>?j9x39%ppIEm*Or7I&;S
zsfCZ4UUd@Xgi)v{x6snVj*6N6%itA{iiWiW^DM=(J5Lzv-+@Y3n8U|z|
z&mqe0r?WE$!cxRkaa?q_who;CBEFg5?W5NH~J;M)NOaG)}R$xPz4oeed
z2hxbVJdGqZPOWBQ?iRCN^{15`eY>kJfB(cWm{L87>^)#v0B_&1;hIj`1J7c)}{KvJuqsYouC69NWZhZ6d=eZUBV`F{=UUQ6(V(W}--DXPwD`wfvu|G>th{KoKYs~Y>obVom%sR2WFa~$P4hnmv;UuD>^TP!
ztKkGHF5rY-NHoT3QF4spdpi#;LFbwD#FDO&m}JGIhP%mcg4GwZ3;)DK)A6KuZ%LVm
z{p39+er+f)4Sl7FUbG)pF5=qMjpGeyhDO7tXo%??(G~fH$AwzkLLBlB^tuK4L*#cf
zL(t@|c-?h4n%n>v{w=pA8(lE{pwRh=onJ}HjH0gHU7I_k
zV_3MmS??-0AExKd@1iuG!n+0L*}{aL2&;m-}CU<(PQVs1FwAygw?@GdA)
z8;Yx>#+2X&QMLYLt^sHQu+zXv#-&siGI&qi4dzFX!s$yjgAuk)l66L0AD_Cp8(kb9
zFdEW0rqPr<8oZxGD0T!&x+m{sO$;d6vehGE$0;+DWB7`FANFE2jW0ODFjMRuVc^{0
zs$=IDb0v@pA6m+)4vCqDxKX86A8jnLZ{yg#hj{##;O*mQjFYE7?
zHx_tk(b;VEVsUCg_1%0l(8Ysbanxv{DqkF^%t~SYiBIyDQsQ0qbQhX%EIVj7M%5L)
zdw{F`-~Ns8AF1<}Fcr;w69AyIzE3dIx7AgSZ!3dhRwnowNH7eoP8)L}HZJQD3+-)x
z=u2xND;hWNghjK8HM2rUl|7N8(^8|mR@r6ZCSi#ymqM3*&8ef`j^$~d3ia}KfNP4&
z&&71>a~1s+?f1rlwWe*qYZGVU#^;j}rEDe@te>03N$`DvOtMuOH6d=Q#9SrVZl`K+
zSeL}%T!hb7Mp)zGTrW@o_TJlJB9t_Oy8gP*C|w;#1a0r!;7O;8SY2>Jd3OWsJ1KhD
z`7W|ygl};93`Xz&5}4T6ZdM?X@5I@VtXi+((2HO-`)+Uu$dbu0cEHvC9=$n_vd+~(
zB(0%+=r3>6+_jkkve$HhJC)4NOfJ|ttKgClLwKoD32Pk0XRWmL`up<4EZjlUyhm6KVM&-J3|g#o=aT;Kza>notQKqP&pHOCu6VN
ztr7g)6a2p;`hwm!$Q$m-VxszVFbhPckA&_OQM8;r%0iTio6#NB#`
z3Tm*36(`QeR3GC0LCA{SA1mN{Ed!GfQ!xOwq$2n$aG!So++CdBOt96^*C*wF6#lBe
z_ymLlaATcGBZgIp-5Wu!OkSzbGQujP)*!JJ1g8CH1J)Eb792|!M6i9oceKHE*Z*hd
zm;U{;S-Rc%VfS@&`{mF2Q7mgJQhcuNS8Of8#x-Zxih3<0d*5OZU)bXj*QAi?9tCCF
z=f$v}vXa_T-sDXQK-ELi{DnM1^{tg7VriS_mQ!Zs-5#)u7h$E#cA+Q*?!)9$y%7kX
zzvcbsJQDfo?U=P<43(tYH$PHHax1}}`ETh>)xRcI}6@n5Bh1=
zArJ(nM=SBgaGO$5`Aj%>pzkx`dqom%bjM$n?%6P*_dQV%;Uhiy%^2o@`z;-#%AF4M
zh+1~DE8l0qsOQ91QW5Xy`@_e{yqAD|U`=&k<}tph-#m>=4yV7Mxg1t)Bz<)DrH%H$
z!krUYKgX+bwukvX@S)pqwi*;j#y@7}*wyyvtBd}sJ~6H9vMReAv>GnTOBY8%kmXX|
zYiLF!%kPNh961x$wMFg^x{ncKfK9QxIKo?OE>duR%wAwMV(SFcg*#ST1|x8!WWH??
zhOF!Au7LMtorJ&&fkuHvRw>0*>Ap;{zz#Wsd0|9hQbw*WBxRA3KoKW_M9!1#_R-#&
zSrly@pHGC^ktwv~Uhy1Wy`t7HvuND(^D!1Jh6cfG=
z`JTFO>BuX}8DZmoKI-=Vf-Y=`b(sw+zKPIDoM9*5eV07*u~;#w!(uGFIB37W74Lm7
z=r0yU8M`kXU=c*k8Thrqa`Essubp?V-!xw3q~HvV3w6!JKio+2f=)!v@2DL{O5Kg7
zljPUzHsc4L619HLRzE_}D-X7uF52k)Y{{LCgYk~qpq{;GSz}Vg+zfWHU5f~i=m}yw
za#CndqUU%Cl#%^$UFn0$`kv~qn9fUb!<6w(S+Cvm)%pH#S9^+Cr;9Ey)!sZ#9S2u4
z&`VZ`*P3MS8;Tk3-N=4V4*L>P8IP^xgh+Mj(ESreVM!h1*Z1Z6#UQId5zhP0RC*%LRQicW1P#?>c!>dn;DR!$
z)7f0IY2$^4jb9hV8E|w=*)}S*(Dm8*UaC9d3w#U$gFi(upu;M)$)KCAE}pK|Y(gCTD&Z?_ajGGv2d1U6V2Yu7Ab{Z4P)_ImUY0!Em1?ET
zwGgxzkj*8z>VQnXN8Jw+dYM6~DR*h?@}a7;kR1_^cf;{2q@|0`7-HMU8Nq0u*=C#z
zMCU@7n4AEfhic2lpGX+?yvXTPyqM#?h2g;!dzvR~R%5nOr|)P)jbMG?QN+z)=A_1>n|JZ2R=P*8bQkr)K=mU(fVaK4MU#OyE68UK0T^pkRvw}bs^}^O)TU#
ze9$v1);LyM;*mWmVewfL>McplTR3a{go%EFAmV23LDpsuD-kITBKv{;IUuc&&z_6McA|8We)U
z0fTdngN=^Xe=k8_<(NBQ4n0HDEaO(;E(o*ks_Sy=Q@hII=Sge#Bf}!PxyKt`6c_Y
z@*;^HS=DRd^})X`DmE_FGb+6qyZ;y@C{TRO86dL
zD~Yg;^T_?S-%QkOCLP&ONN1xXg{Fm7pPc>Qe6BGRYLshE3y!%swA|G%a-mLZfW|1O
zUu!jU=NcPxOgqb{4>XXPWiuzkcN)>L#A7vqY;iRz`^1gZp`3YGUjJD@MFn;>*|Qau
zc^2(CTopa1vMoi`a8hBp>xgvo@=%SkT66q{?c1TMYURsP3VHx>It*djmOe}&wE|E6
zy}B7k$J*B%Qg2(UN?g8z!vk&Q-sonW^{RQ6vZ}I-oeYJG+*?>Bc-qcN@0j_ulF_xx
z*t(Xt*sO%ND0)BhNhgdFc-pbAXKi$(Y#7*#MI_N8uZ|9EilS$Wkk?VYVh~G-G2fYS
zZ}ByQiHyt2<(W69n{(G!$6(M7`(fa+inj>F;#^|WuUP>C{%2bcc+i-SM?H}Vi+;-V
zSE$XBpYL^6U9~R;qtS%E;b|_uc#$@f_2g;(Y?VNlGVh7g%$s63t#GIO`iXXlUEx8%
zmM(cDO8Ob=mzNYzS-P5{G702)n|0ds%CEQh>gK2nzR`wP4M;5fpCeD!KlCeP4CyZOgJ-<{~kyIiv*1
zgYr&g=>&;Kf4Q>3KH&R5>b)@BHh)=PH*fix2+f^ozW|LpKcKj^9wj))rux-#uve!#
zoXic6(f%bS<6e#h$5@eOoV97{o!j2K@=@#9aY*YkfpI`Ysb(Gvht6@L
zo~1v+Cv}XPT#d$SgZwrh@B?bG<0`Eu1N}+uRYY)fItrpv{NqQ8VX^P8l&l|wmO%rR
zO;y&yuXW>$KDe9yX*x8o05qU^1FPz+#(XzZJd#T_;2%DURgZ>6389n0D1vS!C#S8X
zD9b5n*i#}Qtuk7LEf7B+jz`z|aOW})38+s^c&X|OO(&%L%5F|Kg^;uGgfXi5O@eBV
zr{z`JD6HZ_-c^O#lC7b-Y^_GPWMil;8#9@fMY}9@TM?Ja&jn++t_e+)O(($3xWt;?
z9l{4GH!OxpxN4T-r!(yuH`#z15AO-+tif2F`HwEQP?2#?8^iM@MG|t|x>Ax$KoM8m
zg~_A%uhXU#x~fNLRd-Ik%=$oDE7FEb0}JOa4apZ6)~Zl~Pc+r4=;N_NE~>>23m0N%
zcpm8--6jnop{jA2nr5EA^h6h6Mlb#MCy*c4SnU9@aP9zc1FA-Ye1dKm*I-cN(5EfE
z!KinAtg8l=1dmUIw&|J}V6;q{ajzfe9<{7Jq@XBh8K+@XR26cGK3&c+ohj5S5`>nHG70i80|OE
zbFv!a(te`2)v6K<%9R@#WnuM>*zKa!=nT&+fGr(
zmBtc0#LrmQcZ1F`MvA3(}YRUQk*Z1>vnv?9kA%N=<9
zQyg#n`u@6H2lXWzc-L+&^Xg@F_hK@-Q7I8LdY;y3u11Ua5*zmYq?K$meHHTX$nzK;
z9EDdbDDjl5%Zb2F+3KU{rBi&yQUX*teIr-0a9MO9>NOA9p
z3jE|m%fe6pxgFQ+!z%QSl1|0JzuIWn-f?&ec4lthxrh)R*9+bd37UeIJIqr+NgnR%
z3vTo>+LT-o_@vze&i1Mk&7R33;OaCtEEA}Ty4iLIbRR9q=z#fDh{R7@Ax^U8RrkMT_}E!1^nI51*r$4;~+&SRQ=z@qu|A=oTw<
z5k4odOb6)C@JsN$Qd
zj#52p35md=rxK8g%16JH$`^qEUxS`gj4^?{0b8bGVd`<{O>m~fwXH!Ab@E8sboMLE
z$2G$A1D;*-C`sLwD?IWzIp~nL1!Q0I(xgH&sOiOVV-t+!~hn6NOn$*
z?`KU@ZtV{zv3bPLV-o*IVwr7b)cix$p(tvM5|f0Vd!ZGvbkhX}NxW9jp!hzXEpg1-HQwP{7|>15C%
zFVJXO3D=4HBEo1`O-6%(4$8%ET1%wE6lmUmJFRMOE$p1bs@XMAYHgyPs6yQ1H5A52
zpUzk)rVubsQ%`*sD9H;BvWs?xz{TET=n!$LO!9IJf8;i#6iJEHYhO+B3(HLuGdk$V
zp=`@exjgA8VWSxX?7sr<8g`P#O*Win1M^Otdfm8V&V1Ad#W8IX>uCxi+93f^UlGBk
zpmYU_CY~XIk@lMoKhn8tKXMG+8|2wULn->Ax~3Q2(yyi*qP+1We)06}(VjX*+S4a|
zP&Ik`GNH&vN(}2uydRH`56q;vUa;Cr+Xkm!%hAx>HK@N-VezuJ0r=6J#VEn@q8bf<
z*E7qImZpfOF>7;a$LMvrKFM!D331h%#_Q4FioqaT|Em2YvG*le
z6ujAay$AEvz$t0S-R!5m!=rs*3Pkp+_R}ZrC#u-uiFtV*-XnzB`onwGfV1-GLE*gC
zJ$}H-C$p}Y?iavy#5$}tQ96hg@8Per4?Av7k}z$YcCG2OarN&%N1u{@kT#}xpim4G
z`+&9Vr9Jh|Pq6|X&$fr7_rRHJqS|*`F}xQdfJE~!c;G#|-DWKXOT4%dQ>xsEwu+6U
zBX6R3eB0JjLnnQN~(hVUYQ9fhRqcsFNpj<&rbH$`#4%1AX@oP3LGwLa|GC7+3bueo*uv4?OE^Gw1xIxAL5&dlk_xHw{c~(HsnqJYDI+OE_*P4KnAPE{BMl
zRw{lJN$l6;;+8JlspJwx8yS!b?@Xu<#w@goAm_TDNDz!@$fEV+cqzpeY*vzjr0Wj5
zyY-(7YgDZd?jPiQE<=ifih*{Toq(4Xv5U;iFKKn5+t{ilq=+;Ea}-E{rLG$Ge~kc4
zV^)(y!4}g{XNaI!647(i48Zbr1MU0j+GC?l>mX7l8D$o8Z(#R;xFWI|9&{i=vixWo
zFn6`C;J|e#y(dLs_WH%xwz=2<-M`D0)qBMmqiV6)nv`}V7_&8xTgFQHkrg&Qxm7&@
zER19|Id7j{QzoG+&L2G;EY1G
zDt`201kq6m%%=D7c?ighkLG4Yg4=%-FOrI;*l6E(V-dQxbl}U6X0*`HbHNKIEt__*
zQ3zVjBQ#fLM^yPV)s@saB$iWk*&{rtJzj=%C{LKTzxhHCHdr<8z`Mr%|4mV^Nzsd>
zCu5^_B3@B-_F4PYKAJUf>rJ^#?q11idXNSCFLk(H&Tb4`^-9X+o(KwZT3hEuG!idJ
z^mpZYq%Q&wtBc>EAZul&3wB987FWWlpnT6(YU+y^im20$@oMr
zjPC{jp)%@2KDt@a>D*L>KlUqop^`bNZs3%Y*J5L0Fox+U(Kx|$?)wLNF~n0MY9O@i0ecG3UT09v;B
zm5gGXoqez61@xkfpvi7KZo8->j6M%vPUVoW^#e!zP3$bZB9dP=y;(<)^JEl!qGZB1
zr?P&qE?lb2<_1}yw+9V~m(T0VNp{O(j7(uA$0gPvv?AVTc^UAc=bYpmisb~kSSR56
z{a5Y?hCGtIj(u=^BbV{goU_W&DJ|ZYEt!G?Kv)FDYJ~8BNKb;FO;S^a$+v1j=Vu4r
zlZ5jkwV-6+ifj|G(FJ@APOK+sw`$@TA&Xv5i{krT3F!~Fiul<
zAHNyKB(Icj8`IoK`5}0BPb77;LzcQ;
z_l9lLWZ;xd81^4pK_T)bgjLh-1XiQ|43cG7f|`CK-=|O{JRF$Y>D*Of5=M(Y*%xbp
z=Ag-C({;x3fR88sZ4
z-~e@{tuYaFix}|aB_4hAR+Pgs-W>k5F3-BSQ&3oq6Q+St$9Yj``^$TR)bM<)P_~&r
z72O*{=z7=mr#KeGs`Y4OKTsne%?DdlLE?p6=1f%0&oGCprRTQXUAX+K@q}y!m#p?e
zpLNRDdsXSKe4XzSX?RKG87%S;8hi}nqSd~
zj2?$7x(bYTiIvs3+}r_nrM5|4))E5)?%C0Pwf7Vj^4PZHHmnzHps|JLe|a5;$8spS
zV1cAj1)W{-A6nd7E3>F*AWzlC&u2{Al{rWMWDYbpRr#l@4HFmWys1b`&x-z12(nMwE=j&b@@bAk(PbcU%$#2ue!I=F%
z-0ggGaVyUX5}xG6@zCd~XRUS{`b9}DB0lSU%Z3Hy!}r2BTuit_$#_6JRXcfA%>_d$
zx6xQ#Gm6^v0Rcf?i?Wp0Qc|SW{Njk>rNO)0GjX+c915%VeF)CELM2dU>ZJ6flyU8^
zKdCTO+Xr!fmF}UdnBD
zIa<5NK&ff7VYDG+%|Aa1>K)euMijo5EPG{-6bomh&^_$8yIG+oJ9o;VBJ`1=Y-x^TI9*Rj-Yn
zs;Fs@s%~bwQek(*CHq4ctF-_cNiE0rEfp5qihTm_Dv;HaxBUsqI&>6l2iiL`MCN&p
z_3_3>P+TZrR#MUStAlxS)IennN35Vpnxx?DGdmk!R8uIC8^UsF`U}qbdGSWDA7Zm*
zwPA(rW;o6qie*^gzS-v248Fjdtr3iiPzF|S@(Yx!DYIiXDAfTe3oS=)*yZQG{qi##
zWaOT$@nA2-=lj4n`@ves+N5KX_c3L9&d4Y>lE&Nl6%?#E
z2VS*03CW-=M_CZwYhaF*ciw>7;;jz@cIKLyvc=YaNRJ(PCw@2Ym`09n^iBhFlVqx2zD
zF?rOADc33pY*u=S1t>c-hQun!Hr~o#>P$~{x$UZ|_Ens>Sfe=-@mnjm@2XK5C6@&p
zuyKUymp0CfVQj^hcJ(*Jd)JDihLy8sHvzpySqF8>`F6}GxRL?}LzJ+ww-Zkmd5fG&~5Gq
zK^y5drL*+_Qb=zl%Q11MmiSAXVbh(*UbKcVw`$;bJ)VEZQ035FCD4eN${oK936}%!
znT+#5^3Et_8Lna9c^7G19X*E
z=XBq$H~sde8%x2Y*hwr(G;uTutkA{Ihs?3aFdxICXs%c!v~&msyTjQ$#X6u!2|`tY
zmd1qY?=Gk+=YqVG>4F2Y=fO60a5DrS)oyTE03Hha7z9?|1oF
zQ>9?mS=nN2hB6BBC@Z-?bn(B93fH{Y1QzlK5I}{2#~|fJJx-8Kch+kW2$cFd`bR>t
ziZM4(9LzGzYHt-qAXU}#r9nu=jcy^c9)?eO9?Bk;e0pol0q-aIk=PTtT&@9Qn}!G|uT`
z%XwKTlX#S3D#%Fva18p6K~Vv$A@6dP)DeHu+E?{_j1OR9*XqWv_PcGFxruvFzgONN
z?|<5}7v@p)X@Rp5V$Xq{wjKaOO9_O_yt-EIx@iKqvusqu(0ll2@N9RD5wivcEw
zAaE|8_@DBW2?`E^D4A?%3P3ZBOonZ4S|p2c*FfI1V2vnU2=ZM~zcf;DE%d(Le*`{#
zgHG#|7U*a;XgbZL=gXA@@Fe^#o4`guIs!5dLKBTEv_#V#^#;_ffMAfUi9sN&EKCA#
z#JqrK-PCs;)if>4m)6a3K@k_d;ZZoU;~nuk2$zh-zrVR7`Ec2CxNw*o31%
zjjn2+5u*6@C1Op)s0N8dt$zDxQc
zcMD=rj~MF^LWc{nx`qd}Jlcu4j|$6&fDtguS};>}WSF`-c1=Dc3h6o4bZFW`~Nf0lR!`>4UJH+w<2XD}*10-O%>e&&TPW
z=!JhdX2C{CVz&O98gN?$b|+z#^pKVxO+{jEgrOijuWGQnMr^Cn`jNLNYa3x$BTI_v
zLq7{^Lawe^&XFhIaq6XE{YC~>C4O4g-=l1h)r27)P)W*uhw^f#&Y?JN>?rn_q|BBU#YSR6kR;9iV>e22c=Qxawi
z7s?=*E0teDU9fc`x6+%CViI2I@nJ+Top1{T!M0Zr58Q4*f-{8@2TiUsf^mfzw?9wL
z`eV-sFqG(ba%>!6QMu*rUpGdjn9k-n>Nm0#e`Yx*3tHmi#aLUf&YJWdLe?XKxFZtu
ztmNlq2W`I%x+OnN^q!vebm>_O1K&au4t~I#PcQoe*qQ7Vgnq;@wSVM_MjjGi_oI$q
zwCLR}e)6&3d9p-RCeC9UwB4O&NR_}A_Qp5Q$KA5MiVx4MAf)szK1wkmdcD1;`^|E^
z;fnP%MYTErgL_gHTwhwDKXw`A!3Z**(`*qzJ=pkD3PZWBs<^B!^
zAAP;KD8a<4-CUveS*b?P=x0zXam2)#R&sPqXCY%Nel$YjHI|vu7*Et=;@Dev!}^P&
z*-vs2IF`&pa&&W9@b{N?-A_n*CEHVdhKon&R;EL#c0>jiXFs5>OC8RRMgw|AyO^nG
zWUUE`&kTiPnI$PkX|LJV{W9`a>TNuy^px**`s`4|Bc;Gr&F$!2wyi;K6Ne=
z*as>~vH1-Z$Z)fb_qQ0u%Y#cm!}IDNp!)pNzs
zv#Op9)yBej*s^?ar1iq6yx>ZDR(HEadX3c*G0h{XUHXY9HSQ)ULtS99`LSxM_s22&*J2k#%2_bQm%qC$ueh?{^~vtEWxT}J{%dQ62dsd%
zG;Vk77-b^bhPp`hQ6ea$`E+0do6f(OO2i=B@0+x^!1~I&_tX1!7@q&;_xQMS^a
z>vVtqzBAYNr}p>fx8YHbzqhT6%C{SD3r75~S8l@6^YdqLdpCz?+x_KOUH|u!{rBG8
zr*hwaC{y3}!LdVpYJ9R>PPwV9!3ibM;-ve%f4BLP&MGK)XOdyqv^E*V+mM%=|2+S<
zS^>ENw)84XqkB9%xulg2Y~bof2s);tV5y>09rI6|c`op5sg8km*QaS{ff>y5H87VA
z-5uqvszKcgv7CsO23s@fIZg$tDz%4^vXzUS!s|$|phSn`!l6o7A|8e9q2S8o;&Zi&
z24l3?qA#b%*W?GKudH2;!gnS)B+)NMy=@gMK)qP2VQC50AMnEdZBQ`=0eS{FyT2u~
z3J3wL8(vVqqvE*}c)E!_si-@CzY?x;au2GmqR&Jh>(}i-%~s+VB0Y@3!G|L2%w}#
ziAS6N2r&BOy?_pPvvzm2u!Tne`FM8a&yInzJ)d+QAF>a2X=fcId;i9_M<@YB3Nm8{(XDtU8K)XR~SF9KPq
zx@m!c8x!w?5NU%A1=>b|Ejuhqlz=8Iu(4#>L&XJHaXg@fwWU(1sR}vbg#0$q0?D7p
zUOoTKMqXR!~e@E@gnei9U(xo%}|MwY|m_RII>
zvqXlFyI_jK@ruJEP~&`*2$)>Oc!wAygV>lB-ib4~;-{;Axg92LBT!kT_F^sL#PJg%
zFWa|jCa*h`>tY*>{K0ImRPCPcTG{IaX3d?tHPT#o>^C!^pV>Na6g%~G0*SKNVtlvq
z-9)q*O)_eb_Lu{aRcuZ@diY>eI>%Qf=0$;%+*LjWVXgE|-M|yS3f=&MI1B%hRgTjE
zt}R}xc1bDa%B6Ja^^~SCwb<5+%gjVdRqAp$C^}n82guKpvso9F33{z~xZ80bB+(#d
z8p$EQh3Hda&X2CPF2u(m;KrxamOWCQf@Ks8Op3k_)
zcN$@LYrZW%OnSdbaYOOFkRjb&F1y(Xf?=tz%zbovBJ0J7+5x^qP&+vov8mCAM*V@N
z<-!Z&`&tz_$u(#@2gk;{N`I8*I4wA3LV`q}$r2C3#WGr|kRK|BJc-5{KlO18J1>q^
z&)(mRu?wvg)BGJae=r3Z)Ls(dZNBe_VsX##J6~`@?I@#g%EfbK^MIP&f&DjX+D)DQ
z%xFDVW2B+#Qpm$}b6tsgH37nNX5@D8obV%dBW$jsfqc?RK+loja^Yx{awb>J^T0-G
zbuFk+>Ehr)b6DczEl5KF@$$l5e@=*rSYh-QAg8U!Qjz<(M}~0;km|CYvM5uF{0Dt3
z+bq?Z5lnWSqJqzA1!0Goy)b4LMCWC~%`}vfwEZNPAnH8`4^TR53M=(>9L?cj_!UZ+
zkVe%^4J1e~oia(v&1~%BfoCMQ5(6nwXZ2Uh4I2hWTY@nt=bn5fPyx+yG`;g7OSBRZ#B<-<8C3^d-Z8T{$Q|f2s
z{IU8bw5x$a?{%ZGq{qBtYuz(VLyxz8vEW=IV^=wKaWY40A5PJZYvX*Ws$me2Oy_XoA$3
z=Y)fC9^pEqR|{{Fuofch#(g(OwvHykn!yq*EnvV`GoAfMq!84gW(cJ45Gj4Xr$=iu
z{0JFEk(VtM53u&McMzg$J1R5Vsde7)O&JH#?G)psLrrehF2YjQ0!r+Rch{@_@n+fK
z_47X^%TDpz9>4Bb{+O2ziqd>18PY{feZLQU?CVl}zeV4drtbTu$LU1799A}T7uDKe
zpV;S^vJ9ocg4u$6;k0U+Z<^enhHhSbr}CQk={7&+6#FZ7e`mv8heI?$B#G@Q>O5fi
z1_nu86wd@(g}{!|Ar0o5c*C
zkpOTXLG`(GN0DFtE*hM)^p5AV%Z&Qny_{*RG`S|CkL~g6#!BB$lFKWCjYj6Qr+DTe
z&mSl-M_hb4q;ob#+W8e2X6
z`558C;Jj>=Z^j`^dKcGY)6&9Y>As>{tIQnW)QEM&7E-mN0E#(cn
zq{HIlC#Ne}+$Zh~jf7pYLA
zfm|{5j9|L2dDyVg=~Ype4HJgP%M$iw&sTQrzeW6sn=v?
z*!GILg6+~5fnTkJ6H#~eswngmQ!y3Q5|@rSnt@kAsARF?_fYXT>pyz!*8#$Mn&A8x
zyqWA~pY5!Dje&o4iv>ajYMfVH2RL?v4D4}R7CYTGP|yKN-sm>e$-Mi>DOFHdUe$SI
zK0~>muPRcb@XK{4W$SrH=IrSmoWlS7X8L#iW&fGmm`|-pZDIc}nO$$K3lwO()8hOY
z_koXw37iqrZ=7DWec%af(@SRi-u5f*-d%sUdihRoU8nDzXG2jZi=b{sXT5*C7kydH
zw8kO7IbAb5mH!EZeXS7Szs=SvIObwL{-Skb1Y)dlK%7s)ON@LkcPaXY^<4n<&%6@u
zxDUQzG4MhiHguP_nbX(^=@#@mF_YrzP=!54n+|PFF8>qeLAfqiMU6K=uB=%GqTzBQ
zcj~kdI4x(l0MO#YI7S7tF1N3Kb&a}%%GS2_0jsboqLPmKO(a;Z9OjxP9UtSa;Y$S|q9~zMwFXmmBfLE3f8b#<6tu
z(jX1n(K=T!X}x{DzdYs{7h0EZ9`^Q1WbZDs-**{}sX(jMU2l2GI+-(^nU{+W1q-15
z0wjISlNrmRa&9^+B;(=ZOri~PARSsC0`1oi!!`Mrx4EK4i=RHiQ1RIA>>XEn*KAuT
zpdh^AavU@tHMLLrPz9RTcNrph3!5Z;;9$+W?kO3YcZU&kzU*SI1Zx{l&EjAtHhE{x
zCMs7(Te}`bIAN^pe$OabcZA=slayF0kc20u3n9A-8sq*DBy^gHISlpU%pV443Y}Gh
zK~tmDw8T~X5AAljkh<>c_@^!}{GVf)Jt$_|li*I&rrLDMdyiwve7+UXu(PP4IG0n>
zT$EN1{914&-L34mOdCt+?*6~gm!%W6SeWWn`dYxnv%fPO=y{hgsbek-V>c&slBUs&
zD#$`2+rcK|cVg1h9s?2+va!M-P=WYDdoD*=qnKzfg#ZUiL&_}h@^TyJ?Yvk>p4Y9anK5q%DY(8n=|G19@_NPyXsv5>I
z8L-+=GTm$aN`oAp!!i2Dt?zrBrvZ>3=8s+>0h5D5kuiFK+iVO+>iBWO@cOEbW7TU>
zX%iih!T6%xm}M65+2(L4;WKeXUzl;Gt`hBri?6cLkCN~-^efRSy|D@Zn2Oe1%NQ11
zm_*V>ej2bFTf@*)QrPeI*V~H1Sf2($sO*cG=v0Pxj|UB9eQXvp>%?L{D!GQYM}_tZ!}^`QXr{WBm)lKI57i
zEa0rnb@w6CCLvnUtJHq6
zfF*n4C-n=+zn|s+n&x;3@fhG7bmJ
z-s{vA?&iK_deG7x7z|l4VZnwr8(cSOo2gP9;ka>5TBDZ{5w6A^=jPBTzt><&c>!UI
z`UvXh6%Y+Ov!6d};{=2WL@ntB-R{St9$E%_Lr=Q?{Z~aiyq|p|w7#ycA92;XPHJ~^
zO^t`COui*|OFDR@%jebD(wy|^4cWFZni4%bnUlhao%=9##0=>K*%uEPl*_@eq5q|j
zc+&NVIYEpKx>IJ|)R|M$2y9ZsQ@I&^wkNi1>Kj%^m;Q7^NIX0V6$&?rIX+ofI~>2Z
z!L{!_MByl$kvX$2r7K{IXgU(!RK$Qd$Wp9(Y-i?Q5k^|zl{hQI*1zEhTKt>BzFF(i
z0$^MHNG$8+RwN
z*lKy>hAGcE2k95_?HE~}s+IGl-|To26)AkrH@l$Kw*LE_s%5Y;osO;DM6{roz|A5=VI`I7VP)9e5tTIxBk^8Sh#{TSk*$`QFxd(-a*}4
zXwLpfcTh)r)*&5O$?h)Z&R?ksKDoiOkVyd3+GD9=o5_#9yT}+lrSDXGMlmYvF&Us@
zc4m65@*Zl5+hb#-l)_ZoQnEa}!CoEunnk*YYYtb49j8X2KI@y_v*vYwu-|QnW6r^C
zbRk!Jt4Rr?2=K?0w*kC7Khs5Tm0lTk-`^}cr*FfCQog_YOt
zRgC?zSEzFbl@AR@V5J*v7ZC@ng&S)(K%}E0p=niyEr;jZ5%%Ztw)%*kp;#PDB-0B2
z1Q=%PEa>X2GPJu-MPBcop7GPBGGrWryRBNgPVQUC3R2M`1zAzjaO-7p!5>l^HpACp3kLPA51)hy*-
za|O=U&pX9OuxwRC^17yoS}5x#e496fq@h>7U_??vF}^r_^Kti!{nl499W@-wfEaba
zUM%nXlI1ldcol@0_xM1gZ{hhso6r5Lks$Hr0jD@Yi#puSv%)
zJfDch>=?1Vs-DZL(Ye@vtAgExV(Ms<6c;b7%ye$UfZOLho3dLd+%a%X#B)Qt!=Vv_
z_Q!mQG5jurz8x$C?SqMxe{-78?Q3*vh`Tepme~Kf*Od56H-D{J#7vhmON&;z)-jgX
z^0h~cMLfAdwR591B4F}@5|H*V$b=$rV-Y#$J&OPukfG_mlH!$6+UQy$_T%9N6?;wh
z*j1SBvXxX_(_WGs(iKMr697GQd&UF;eT)#J#q-UljPzkf%b7*%*@47j)%O!S8__Qv
z+F=z%N3U2vu)9w_L8o*&A)IAop*VBP3&y@`qHm55i
zC}Y*{KnJwHQB;o9ccJ^{PRx-gV6d!5X6TG~NFrklA4`}8C9Yig$7V2K2%0#{-oDd6
zH4^9JG4<~wE6Gwz#+W4rx#pXHxuiIaESrJ)D;371dDC3F+#+f#OE|x!kkg_-rEpRR4OgGCU
zj4et)sGK^j;jS_czwRM`TxfkZ=;1$p
z)}N0_Z3mJ^rv{N1?Dj(QK#a6v#$*5{3u%bZeLHI`B``$bEeN?{Ytd*Kf?UJi>FZ6P
zo75w{l?m7*E_`}jgFirC%JrZUB(mxhgwPOH!x~9Zn>Ht40_DkJM-YS~_6TvG9Nx}6
zmaL6I^W69`as8{I1Z|sfs%9KGL%O1A>TROdS
zvADJbMq%)Ta2XpJdV0s+&ECRfTB
zO1T0XeV#PZRPQOse0ffNvcj589vx0XkLwSQU*ET&tH-wma2my0WL~
zg~A@2qEPqOD+A3p{Lquc0Rm7axYwOc8oMP}S7ZD^UIoe0gzWaeo0*N`UI)K8cBksQ
zVmSB=Pj^mD^Qd&Y408*>^jEGD1SjT`bNNXk+CB>Rj3dMQIG{;Bl5pgMCMJr1@%?=6wrLg=zGh`mp@6MOA#w)y
zxwCVa^Pjob;z-#xx75gKb_-VPqm9XD%b0|401jn*Po0d9nZHI|62cMYrYPFp!P?s_
zxo;n_Pf7jAJcDxkLQ>)m-9mH8?UhPp$%LPt
zbiQRO$UD%&D*C1Y^3Ezw^qSIQVsAFF718c~uB!Ef@(aS2R?j!=BKou{U*%C8j}DFO
zwE)BXYjEk!Qz0$bd7k{3&?Q8~(C?e*QDy=(=5|FKsz|7}_~u~&!_1(ZSd|j)-3$^g
z(Vcs7$S|7q8g;D4EKG!*``0&S7S}#cq>Uw9!!ICbifQIPfFrZ6G)ny&DxymB8@xX@
zH3qDvJ&XWOjg~k_>OpKuCJcbq*A7Uu7^G=+P6tzoW#;|nMsA{@y{*K-2Q|rd(+ZXT
z6dmG$2WG*s0-jByc>9x}%PB~n8mI%TWaVukT$#e_OLWlf{AlcG$h1t2#Hrgd89JdJ
zyz08jNlH*NVwQ{m!@r|DelehT`#x`%w_b&7MI%YdlA~Ev*0J&ey|*!4>QH{^Dp$5E
zL!Hg#YPupWIy?Q6Kls;cA?qsZ$LhU$BW+oiOZ#gkXxAP`U$&F|yv)tTIT6o=OSh+?
z4atqLj)~{|FG>JZ_x64L{tLAo=y>HMf
zfkB2*g!##Ju8UpK!GiwRTIhfnf_~;ngkw^$cCNCCI>tnMZVp3iR-
zW=4D6PKs1&#Srw!g!5!SH`vMKj48apjLdbkI_-fCop#U=*Nc+;Ec?0sNbTi*a15cz
zwGM9zH^%~zT~e0aKofL%QX6CQ1=$H{PupRM6?gzQ>F%8NC6C9JTfr@0oDg%Atn^eJ
z_`QFdqSJez6nsLXbU#Z_*m*M5i5Q~*i=V1&f&F>0`~T<0e<2CL*v{7ZkFE3nNRDYq
zTJPu%0050rK>sT_{`aZ>_WDinZYp7qC*1x-xQ3o;WW)ypI3W+3yBJTwjesQZdVz5`
z5~I$IR@=(DK~EVGz4-JR@f#7(fM=(EM^<~8>2@spn;mcrG^nV0lvh<%O;ts1iw0(q
zM1M%xFxTeSdYD(gSOm3@}QfJD7Way5I})e48ofuDxNN3%%v5e}Sh5
zh+0_1Fl3Zd_;XD2Zg^aA(nfdu(ogmFy;evn4Mw0dg@9+t2p}H04jSPxD1$<;=`kq(
z@;xW72pXu$d~aVfD2mWG!=Thwii}dSgNn3-ai7wZzXr7uiJP_WmY6P5)sWDE|SdzqR&V`0Qpyo_${@UgPv7q
z#GQTLKsyctpc1T)3CRUmgp@Gk*U?V?wzG^m?j*15lu%ApO8buKrTaKsP1Qx$HrOpm&WO4bC%I@6&N>J1D3YSvPr-xe0LyC?&M7R4X
zuqdwZ)IvRzPvX%|xY23%9_WmFt`KS4^r-rYM4L*Qv
zHGPOU<3QB$&&hDEqEuRSA^jtTTu7no;qZ*_>0RCC`8U&z>)#-U+wc8QH*sN}mr|7O
zy(=saWt3K&SL^!jUED0%9hi>npdRhSEH4>xEe)4>l8DkJLlb@M9ir}-gCNSo&K8`<
zb)!SsM!%M|jdeS|h>>`9Vd*k!>uUD<(+|&5k`saqcW3MSh?|a(wNugn;k!sV_2$V>-
z$7xIW)GE8wKhbS(lAZB;<;Z!lKPaNv(p7^0qE4dK1$px|HBc};K<$C3b+|@2#VVH&
zYmdup9euh;J~~gkohXFC?VdpbB|FDO>@KVrIe0hI;73)Bo_pdfMOKe6Nx`7c3q&fu
zk27>W15AE>qiCC)4{&lvX*|!JIzp^tjOhR5MlHUkM@L5Zv
zp3+12;mil}xXj6pCnQwjJ4gQDoe7gQip`32O$<6Te_BuBB%&S>=ZXld3*DJHNTg=k
z-njr_hh}_mKn|JSI#bx9SRtVO63!QPhMbl`uJ0)VW#UvmK2j=sp?`LsM=?`Ae;Lo(
zDwvg?%@^;(V1%~QG6PKqX&8i8mS4nQXe_B#|F{b+`v%82kOV3NK(6F1MULqXQBXn-
z?o$P`eA4VVZitD#eWc**g4QGeTu9LzNTGjzq=)WDyTkkY(8PZCe|r@Nd*gdBiWOwu
zbE%SbX+lXJ2Bpr?7<-WI-QDf5s}Qd`Q2vlVOcCICuEzOG!`AM8_iq23ow@VbXU0Ju
zGM{`2z2cPKSSYHdn?It_W>p3yld;083$O|tTfk!^JNs2XaI|tN
z_Uo-??m!_)FPv`a!n(>&1`|;UMRgYr(pbwxoRkVFy%BVa=R-jZXVEIj?1XUV4I>a)
z(2A(KqUs)-+RUjTWmE9R_n7ZXR^6qPy77h_P}FrM%7YlEzLp3naQ!Z5gl@q?nMsDw
zQ^X+E6_IEUAR8J;sc3P+D;lmOxTN3m1%}wcVaAyfVKr4#;9rPIK)yhno<9dhxk?=i
zM008MB(xIn&C~K{R2w)c57JWb)|Q&cg59d)qh!ilp#avE75kj+HYAxxOyU>B5Ga+n
zsStRmBR1mf3UC!91Sge9z_Q0($9ar@mw@>tFWo^J+aB8<9}T>p_I2ItnSTD~)#Jgt-vsqj4(-{m4Q~fE><4lh88FJD_hguL}WC7Pu*5sSTE=^UKu8
z$6jkjHdy_gjHUj=6)g>pBK^=Km})C~p1pZsX^_r0>U5zPUyivgr!3yz05-*dv=!16
zsha6gQjk2RyHn~fg2H%SO2WJ;i3aIf+BcF|E8!&CD`JM(ljVq(aB`BQ#sxs@>#_a#
z@?c>2Cn7BY;*BywP&h6WKWDzIh9LK7LrWQeebqj=hB%dy7YWt@e7p_aLe$l)OCf~-
z-m>#~YMeXqrz|g3jKqa)3m)xtN6&yJS1v6xY5n*yEWzZwXE^-ft1wsfzL?AOdsMUb
z`bk2dN6ls5<*&8FRu4q)u(X`NH%+oEjNb8oI1#WDqUF|mjC#n{C
zU{kI^*a$gaCLu;fvrNsmG^W8N(m`}GLJ~|0euGbljD)w}1lu4j#}FB35
zAm}%mo{`=IZrU!>?0mv&qOR!f_fb$T!PKs5%-w?G`v+(i-P;XjhqFl3~0pw_mE_|*SCpr=KSdJbK?-&PKL)VS793&
zC_>iG8jG4pIaW%ay6NwNoFq>A=BnJOLelni#E*m%JBHS2WSto8V@ZS)-c95>(U?Y6
zd6mav5~kNSsEU^m6A+P^YIKK
zVCPSym{m{e^d^hY!Exey2wHMyiOlHReenFT=c6Ptqv&qNU0w8bw%hyW5Py@RN+&7u
zPJh?_F5(X*5EvZ;Py?Y#+3_VleVQK_v!YS`+O(yODhf%wvzvFV;MlQ^Ccan26&uTZ
z!J|eIu#jyRr4wRv^Qkc#K#(vGaN#sAhVF)u3r7DTvi*MAfY%fnDB<%xBVY9cQdbd}
zhmDY~cc~9c_c`s?SO5BH!4e&hQnuEoR990=DnwyGQ5}3gUIETL#~?jQqMSFts-=FD
zoBA+n(o1+#CuG<|HBYqqKulx*3|ej+Hg$5^tp)_v#nYVmt1-ROSX$qu*HZ0{vq5I<5vgSJ^uGb~posow?-!>B4)
z7o9COoR5UbJ?Nr6f>Wa81XKF9AsvQ3K9!%-?GGWx_|@LV9PiN$1&wA>p--hGKE;j}
zfaE4=_&0xyQTK+bLLJWiAU$(wpvY;*@ow$N1rd+cubPHJFN@6abvQn2u-j7X(hMb`
z5p@R?3U9n0HN?3wx}W^@&q1kM12)Qf`xs$F{qCnE?tMkYPg8G2MI(``5C}N+`^FDN
zseU)`k?y`fmjO9#x?J7c$J}q1Nh7&D3dk|X3CHp^E|xn`gy#(mc4#{KZgdy*6m%0f
z)SSg5j_G2OM~Y$H@nC}%D``myf67Fgj6ji8dXr2N=ctm1JQ9O`(J0C#2Z3j9lzQuP
zHw%@uRNI?`lGVfCqAUZpvBi7LieP0>I|CRO8=!69o8}s?*?$nTw1U+apc;>PCHDC`QzjepNPzy!4Kjr3(@>v?(O?
zzeNYscDh%U>3^(1XkWea3f#TYNurIZ1Y>8C*SgH3$
zW>z|^7-2w-7y>m0WhXsl*e@qAS-_qOr-3?Lup?g>_!DzF+D+2uXHT^?<{Rm=VI4S0
zqr)I!5b$NuL!RMszn?x%
zIkcvV(YUB*s63T@+NO;s=)U>=*+o~^Tr@6|SG@D=`j;EU+*LX1nQ?B{Sp=5okx2dq
z=mQ*fC~j#xy;Y&N|4`gKy0f57J!s>SoGj3*pI&KVd;M`8^0pIxwMyM-I<3UEHq&-K
z8fow8nlGe8;@{0xue+}Jp6`T3P|-Xhyl;MByK-`S%nP-O`r9F{MPiF7FyEXrB(Jl#
zB&cxo9UL!t$i3{vF!Xji_$m&oRaBMkFWXH2&g3m3U)Lu8$Nh0n<_u9=7+C<>Nk{H_
zGdex@C5rJK9sLQPoEHI=elzelH6iP$`Ur*|A=AQlA|2SiOk50@qyilmw1%IKEQh}e
z756l-0aU^nJjdh+#i|02yDm+cfhN{v`EiC4uqW3UCBnr;N?yko1otmdaFeTxi;_U3
z>$9Nn7yw2j0%`diLX;*iOVMlS?U(2NQm*NzVnUqopq5r~0_ElA)xrUUe
z{!w;Tu2`d|Bf4Az@#Db)R;RTvT1REVUtbRC8;PoS!`t9_){?h`_k3V6D7s51XgvB79-%
zt^8C8r}m%Dj5?UM>g*q^ZQ_Dl*#_>W?X3j+TQ2fm7_mdc+oSLO{kQA>d5DHp%|f?D
zb;xGHUg8%iwiR#_dQ+=9!kV!SyUQHfmCWho(fhgUtf-gE{
zX~4Pe#Gsk|emh{8$qvVdpVj>~<^lH(d@do@x2)HUYu5B^RLgNK*P`W7cADNSx{1wZd94g$czdH5Gu>`1#H?On
zwjj0KmM%gluO%-al@^US%$Z8mbqO1!Q(bSsK)HLt(hWWhz74HX03^O4USV
zj-upU_GRbqUg&pZh`DCDvk|!oSBax2)k0I!WOx^**C_QZZQE_yqVM1Q9Q#wFz9{!g
z53pZ_9wwtw=1X}r!M;kE66L=_>HFIdFNM4;LkXzB3SNEpGzJAqv_|R&-
zx|c+32{0_HBh2YBz2Oz6*t$PsD5>Ko8<%wXL_aurI4Ihfygro!?N9fx-C$#Y-1FDU
zLqIA%9~1Gy33U-A;wifH7C}l3WaI7V-67X2gJlhw$$h2+M|{AG`@qo~>UEKZb2MOgWdZ7C9L+@Ma{As0f{KeLY#N0%$E!J~7&qE`%}QRM
zi!D6u0!jr5Udf9D?E9lS3B{&6%t?bx04u4LfBxgY|M`#q`oI7A->*daD?WQcDQEX%
zO~Ar=FLt4FU*_`@Fz@<)LhSC8URlAvm1s&U%QhloGrXRdnn1+SrE<<2c@ET=axN@M
zFVRG`yNz<+pX%JZ_yuJ1s
z2(6MhvMIvP!(%z5i-e~d78C3PCNu*IAJqX8VH8+ELNLQIm4-S+a_0-gW2GJ-;_b7<
zBqJ!|n5UC0ii8ZJ;IW5?B7u>6dTMfJnSfjxr8G&zwAH6iDfO|(-bG*3d7RkB}7nqCGt
zI4NpN8nBz^>|~nDVn79k$cHzNxFp0GhfF+G2$BD|PpJ-0qZwcz1HlstFT=fSKbTes
zQ#sH5D3g!`oX5ceyP8AnLh*-sXdF>blO;$QyT%SPRxk_Kp_*r~%-q7;5me3XS3j
zY@0>?R5#hTwxv}=;vkRzg;AKLQh1gl`x%9!=nAhg1TLcpOUn%)bK{00xyzh6Zctgu
z*J4piE-Yd>6v%tmX!7|Y`l2bQBo6GTW`B2=VVsaJh(H=l7c5@z4Xc-|Q%r$|Isx6$
zHiId?X5vMOL{m^gY8(XQl)G{!(F`fe=1XO@v|L_ECea*CIdQ;>dK?$>*aAE%n7I7J
zb*c<=K~KsFod<@{au*7{K~_RcaYlk!1jd%}M*4)kf3@&O$Z&Z|K!0>_I~_8UpF~N-
zSXNT>e5-Yy7Uce*m&2&qO{QzHl;`SugBQ{Ct_(0~Cqe1#;e@|_bzYLnl1U>uk>3iw
zQJ5@ZBzp@CE`R9Fx5*9f#jUSG(1W)Gn!ebuPEltO=XHk2?Gq;>x
zUh*1vbZpgOnRLyOTh1*6)-0~_R3<(D-M!mqOC&phqoQR^)TaogldEN~i27MFR*L>&
zD6GC!^)b!pb^sDby1z=EO`+=&Z?vn`XKNDkSv2wBSx#j`p98X~a5W!cuJRJ3y5kHliF$sYDS&ieWHHzfAb+0X@aUe7@oo|MV?G`X&v*y~l+S8uyxfuvaxfkql
zKsvTe9jI0x>{6yMxWmSu!?Mi#Dnw>~vrBvFUwOEzT*n2#Bf1Sk-Ilz{#s1tYzd$(E
zq6=wFt0vKDi-ll%RY2J@ar6cz&WUts}GWu6AA=+gkbpFW$H6dv;vPX_-RZA
zrBd1@SZX-LEt-%y&w^exMzcS?m*WD+i*k73cp;G){#M>j>YuTp297Yzc$Pg%9c7cm
zT;J&1)pa(t>9d(GINU@Tr~qV-+FmMuNrgxbO-KB{3<7c_L;-yz4hKM%Q&FH+rCILi
zp1BqKjNR=-m^6t}cULr8+3;IHNlamsTHoc$M4`1dJ?bfwx6WW+E7sXFz%X-qSrKb`
zTRp2^p#9=3tMQcD5XC_ey&$5U;Wc|68ZEd?@i@8HQE0{@jRj0_3zI+od8T<{-(aoh60-3z
zX!K{}QU!l4Jrdn2ns@6$+c75kM)<8XlP0_VC(h=0fF{X-*X6?q6*s@q&r`Qiy%wpp
zLZE7P!$9i_4AqlSoUQt1?%D|?>zbxb-{6YzX%6p{+`=>kw_odg%THOT0yCs-`w?q*
zDW}DZmRvz`CwH=TG}tK?R9|BeA^VyeoHMg|?x`hU%)EJ18;lefWanD@B6!{jmK#(r*ffiB3Z|)2g#0^x`jp%%~
z3C|_B20p+91{Cz2;h?GWwT6$`Gg{P?@|v9mdcb##<5Ik{LquW)=R`asaLbjx@#QmS
z>}&Qm*n(uFh?y{4pMp;w1j%n2=uQm!=+M_!U^&5ZpBj=)GdflYB|M2_glSZ)(B`-R
zBncCy3e?&9V*!erZ=)}CmJ+%G5{osJ2XEkZcYbx$2z=uuUgi)3vC;|91%X9JVD`39
zP~uE-tUe)~yiF9^Ph!
zon)okpSL>edbMN0fF_FWt`Hj-ec+mxM+0#$Wh0vfERswqOx$uI%Zg*Ny)0hu2of;Rx>2E&aOX9XQRJEoAHr;lgZ9Q
zby}Q8Slj(g7ymG_=CgJ~0&Ud}bw=~^E8M3GMj17s$kFuatD;+B?t7>uwe3^79;9C*cQ^u?tTMQXNwUKHU9
zrD0Ot>P(sVyRp^D0HmuJ1V_B7iPs7PZeSpe_p7lLK4Kqvw;Re1H75N6LdT;9dyRvaztrOEYVnV6v+Hd&wT3E$J+qZEf@CL$#KBqUNFXv7VH
z4lCBx)tjS@!?%lgB3uXa$TxTCE#?ryuU0)9)_4
z52KSIc6G~pA>Ptwu$KEDCxcW`+mO6K8gCsQ@v#EyzX)&SWdB7NFYOO^e-mz%(aRR|X9#k(ted0Y
zk|<2EE@4iJJ*0Zxy~Cno8DGoM-g!ISwbSB~?)c`L-fxFrH2vn;l*BA?H&I
zlkaPZ9z8H~P&EeVz(r;OqiTuqGtOCthr>)KI9VV8UU{OoQY
z5-jbkdP_02F#&YWA@+DZu4Wha)~(KbHf9A{wR$)yPDYog5ik3}=C~PKF+(fH(dMHL
zzD`+MW>`E1bh*MvfUDLU{#`M%*y+*?Ok?)3~lys
z+%UWd;GHx`2i>dbRci$j*j`RQ6s?t*-LPOt<0H~rzm^#nb7LrOzyoUg=XV}0_vPDX
zjddRKm+e-|81b-mRNj!-mQ+J$VB#5Jk=vgtv&T>u5khV>DEgiJ3i*xJ6LxO2{pHtK
zgLb5T8nrAOd%~dUuBntUQ*}q3s&OqFUz1)pK#T*{Pt~@(TnBFa%jkr)_vi{XU|V8R
zIl!hXJ%oyVHIB2C&=UrT(Y2)`7a|8$(1yb2HvLi)lA;u|xYpkmipkHe(Kt-VzPP3m
zH02b`EzPUxNCu`vm*TFg{-7{`z}-6$U@JxL-^*yP`a=lgc07fBw7I@`do#
z9sem&?R5I-X!Lhg5vrVOi&sZ|yDj;$PIVFaWF|$Op7-?#A4-_V|6;tvzA!=KQ#1
zo$Uq2J8J>qhg#h-Wh-`I-LQDGYWzc88y-v5R_s?u{K-Ys3*@*YP$9>L=+bX_9<1Oq
zr%LC!OX(oZ_@PX)Q8=KySNn3}6cSi_sdGqRQb#^GjX*!y!$=eZiI;T2DO!`qe&9UI
z8^pXjkcO1y-_hi1;UDM?Dli#T+=U>D0y$Wtij79p@Ll7YY%9NbM6qL=gcwbw(CSM9
z9se};wBRPQxQcM>Xo49Z60gS4U5VD|p6Dl|s#P_q21UzA*0SA*E@c-#ZV!9aHD|l-H0~gqBz}=J8Vi|uA>myW|JvQYcMyDV-UWAZ%6@S}Fk>g3`ri37@bCSjx=o?!}
zmja*$Mcu#R&rY^9Ty{a3o$ti!5v*{5fySDI{LQ#+;m+fu)3H(!Bx4g@><$cC?Si(O
zdjoC&i0^RG-qMtWzHJ)`h%ht@JU6=P&?SP?=z!RS89mL>{w^sh*gI}Z(*b#1|IZ|=
z^d=BAneZmCI4d9lZsEVMNVZfFr_b1(dwC5_oIWlDE!>501qC*zjYp3_S%Ke}Onwc8
znun}kHa<->E9F!yqhYhnAf&Dm$YW8-xGTRy_4B|;Z(gCYkNAiVC&K_TXWFAr9#A{B
zixbAclv8t(Zkr`EZm=|oA+!1XNJj>+Fp%+&4hr*MbYGEVZz|(a)x^q4JwYicQa$aws|IH^8}qhF8`zlJABx$TVw8V_iv7iW
zD%SG7YHKZ2onMS5`Kn50o1^0F{IuU%fAF~7Sbun5{paz6c4MvkWOJpVOExwhwi_Gw
zH`IR~tm%@Klw~bJ&L|R&4(H@Up{R4ET@(-kzLm@n7eyq9m$4pV1BcJy7A2ia&P|Ob
zh+Y@TPH|0Yj4|Sm8ZX?ypZPg`*XwmY7N_q=sMHU`nr3^A)A4lhzHx7K2^vg4Y%&)G
zyr%9o*4M5+Ma4S7;_Wc#fMfJ~j|aG-!Oibv*h|j2fSonS&icdAqU<%EJb7~U=?+l4
zSX`c_Q4<+8g}Myx5CN0L^w{6jZ!=Z4yiT=W^1
zrHatGqt^diFzsUC@dgcF8Jj1PMn0`ri5Cd@x?XP3Cf>57aiRLT9ZPD8`&we8rY~b;
zbAt1a4<9^w@c6VD)sU}TP=$nL8P$mGx&W!8xGk=$)XU-rEh#j-#}Yhy;Q|%b8qj4U
zRMV40c4TNMJ;qEP0Gx)zc3FA^a2wGbo&m(2x;hEjKl7|agPQ!V38q6rISO3#OTN&=
zlfpmq@RZa>8JVd{bTutUR-JB&I@7o~nHS{UlU6&N0VPj1#XWg
zkynIhTh8I%y_rruTaMpn`%G-+MXCM&l!pb!t2&k(F|Vi4qHS1|z3`~*-k{2#OYw2m
zX~w+q^Gr)0uJKTO{ic3ACKcH?Ih~2(zzGDe)-_#FI%1TiDJNX~fOH1G{8R1JZH40}
zA+Q`ZBk{}`gaWq~AVK?($C7$IUo{*Yd6A->j=i|FsX8G4imFna*URlZ!^TD
zEn?LpEJAe2%=kiZF{9lMi*le;l|Far8;0tQIQk)rr^!be&_m#<=5C`Vg
z19W4?qyuxYVdjQNNGTjUTn-o@DUl}G!@T*2ZDCLq=;eyDhl)^Z-am&If0j!yL-;Cv
zr__`yC}*AfNUv-F3wq-46}uqs+l}yBKPi`QDm0v!9HLiWWIRFlkr_h=I#%f!(u>@_
zFQu#dDWBp5Vl`YJ1q5rpGSE00Lt5fAS6$KWy`gSyOu5(P^e}GHGDj~_ccsl7pR;MZ
zWWMKZ(iF=GrTD%N`KqYAL^#A-d*4OaZUG1>hVFra@q=0dx|o3r-jMyU|g?J8YaBz`wwzW&~muFu_;o_LXHMq{Q80-xB#B
z%p|DAzW`2nV;j9obFyo0O*Oiun5lxidr=Kd&GKS&HgEYsYfJ+*o#CgBtBuxFdCTre
zg6q*Bx>t+xLTnIObb@+2D?*5K$5{@T
z?4I|ZLNk!eYTvLKZFCe9BJ*5k_GD8@0A{k7^+-n+I!XFWGft6AXQ`I@KoYkV(v$hg
zqb`jaSdDCCPJv64V?~ZYBB1UHHR5qbEtb|RZjUP@VA$9gnR(wLlhnvmMb&N^E(KWF
zv^+D%8;v6x&ej7vc=)a7&%dM`Xk9C_T!|Qx^agB3@QcG1{kQ+tXzD+;zcZ=tJJVl{
z1|tYX|DE6wbwqSrtF0I%=^4^g03Y+!?ZvX7wR2w&cByNF)1dj7FjFMm1EpT{H+apd
z4w{2PX}{&StLN=Tv(a41E7>W(Mbe3N?r{hWe>Q`uLJ^63);69~&9Jf7;WT^J-YNP2
z>;L@kt+(Z$TW{VD+wZ<@ZS~%ELAl>r`DPXOu4~usbE0-TMG7~_SBuM2wO}+1bv_6*
zZfgoR@k#NXsjN1cgVAK9wnq#r&M*;U;Er)H-1)B769(71^#+9%O{CxiE5?Bsj2FXV
zxMRXV8K-BUZ}G9Aw8d67%ptmhu$EWT13gMPfntYhUTvv$Wd4A46z3D6uB9^mgrQTdeMu~y>Zi0g|yV8HD*Ynd8BIC6Rhau!5SgA*-`@Fb2>Smo-0xSPA!7I+ph_*_r*033&0g03YJw_Tk+s)S5-6XU|&C}
zg2llK8qHW|<_fcE0{7eM|M!fkKAh^79RVyQH}Uq4JMdOW6#`*=KPXi&niRA3_RE3S
zL48qAbD!yKCD|Kh$lCqE#f{jZ=2_HbtWu;Fe|$wDK4vlx7QmKO`$mYM9TOaKV#t;1UfLxR7k*d9p13(8ikK_0GR*kK`>Pux4n~wIBKFORZSE6vj^#
z2!iTWzFtSQkVn>N0{&7Rrqh*|{Z3#msV*K%Cjw*Y
zrl?+x1&ZpySFCL`tq(?2(XQm+T#3pm9?heg*aIs#OeWX^+EMlx4U+E^1l{e>_)fUd
zCDwmX0$rP0@9H(mow;od&v|@Dxwky7yR=xa6$H^BU|L@|*v29oAsR3((>IH_iU%t3)HMxTK(o2*Z*YOwDOYnhrIiJt^lhQ=j%{4r9-RD|*5)y&rW`_zTG$qmbi>YyQ
zufmDvFQd=-ry_q`Kijy!;o@ajIWggt22TdV;e%#iri3;KXB^K~B4vDhm|r(NX~H`+
z({E#oVA-Px-TeAA*MSXEvz8<~3ze1u^0iP5F>*3kN-FcAb+OQDMbb#tKq@h`UyDJ*HLaU9pBv-3yHq!ptk<725PucKrLnDvWYJuD_6kP%xx|7HtL|a
zLD7qZ*Dg(6<-?kgTUpV@ETJgAXB6
zE-u@R&;i?)RcYf}6WzdcVkw2g^0pgmXs1Vge)lYPU}UthBc~Jh>o=bRl$)zhzdjYK
zBYqHD!~q)c5DNN;13mb2K&`P^Ur8Q}r~P?L;xnBq0ga!Vr~^oCKt(-#FSvJxV!>D+
z##@D&uUdtjtEh4Ftt8A`pNJS?l@I?m(JF4rJW^b`kI%lG+RR(qoqnoCs^D%
zs*E8;jk4WXh{A}yeac_#VnF1g&jRt^Xi8Lbw<|Puc{pfuoNj_%@QR5|Tw{`Ug7$`s
z{PnGT|4Z75i6{`hQn>>kZib~aA`XI2Qb9ZRH^&Ydy(`WpCUKzUbPA*!Dc^|CNnmc4
zbys?L9%qwvfkM*XjL&;P+
zuAIgnKXS-`&ON*9*jb4E0fBzx*NF}mvQH6O0R*D)H})_w4Jx1p_s!CsERj$oWB*>F
z86`&vuC@hf)^4n?yjf$u_DIfP65W%~mpd}9S`yUUvo%o`Sg)wI_hBWX*Exv+db~pQ
zjjlQogvdp<4LDa>pbGuZH(>!ZoR?%_v%t9yO-1B3|K@#h-8ScncX4<#C1T(#;;wH!
z642_M-q2``5A2q>(O_*9_Q>tQ`vb-yBN9P@kU;n<)MlGc+FhmReBib+zDqW3knTKJ
z&&yexo2H_}Ts7Kdu4Y19O42<^YD+H41pZ;G_Y-V{{5es7qN70MW)qxGv^#0-iTw5L
zr|r#eJ{yOd`SgX_*}#yZN7XDQou7`H;VSI1|7mo&xICDdRGNFE^ATj-S+hKPBdff5
zpD)al$dS&tSP{*jwk)t~y77!JatUgbj5b>EIrpA7xc0j!y{wN_s{2O{vZ|?&iqh6w
z@$Ov_Jtb*U*BQwKV|(rG;_<P?V*fUU~j%(=11ulwrs3
z*ECV9>rsQYAs?CZh=}V}*TskQH|F9!etslmecnCh*gw*urv9_K+9+p(Rr?@r)m$>H
z8f%WeGwBRWXy&mxgwM-AaEs@GuDLzY{t0&8OK(dD?dpaaEDUIM&@fd!NqP2EFY(pr
zjNV$BzMNogBljHron(2|JA|tMz#(>afG-ChZY+h2H`LuJ(ymC
ziP|kLB@Dl6!Y@O3j=rpHm@osZ^-kFa%hAtVWpdvdDW!=M*!u5HKf(>hVgmkT
z+WG}Zz3^W{x9-eDl>yZLp6OV-CWf!-^yg5EMp%~x@%pe{*zn%fsXhAQzROMBK0t=)
z!#1ebm%xY?4iS&_fr-Oj3MD3_j00d8I5tuPAmr4}X`=W|>
z0wR=mP_LCR5N;HRe(1`u2pkvzPpk^Ug3pI)j~UIclX8>m5pw@gC+m^^Q4_mP)ROfG
z$_fJ(Tfl)y1iwP1wKHg)h-|&+ONTXzMaq0s?5LB{d;LVzbNbKb0jFn)HsU&b+2I=B
z6HRTIvG|s~M#ue~UdKyJxU_a}AqH-_fc2Un-RTn4SxVW97h4rfy!7)x9V?P8$FIBm
zM)c)NE)QQ`ZTU9xLi^djq(Qv8+>>7}$(HT-U5z=3
zM-NTHmw$0z%xN9zz*P@z5-5mIUN|hGsbpWefRhCVnRw#F6%XP%;q`WR`QA*cn@#Fc
z(9CIwv4`_=TtWSXtl50mfS?+JE7Vs)ZNgel}8Wy#HI3A`R50`~k$RDAT9
z%yF@QHR=q;Be>0_M?~Y_X6}i$uSUDNPAh#lgj=bfW@Ge-!hO+krpxL0gIaF-3w5?W
zE7Sq$`Q;UE8osH0_Q^W$TGG)EBZRsdlwV0^xHqj9W4eQze|1DMuI
zJ200AgdeVlm*M4=`lIkH;Tac@ZWEfT1*OGNe_Zy!QCPo!Bd@403pMzmD*Vg-F)1iV
z=Sl$fFrwyDm@*y|!(rB)z89w+e^MP7R_d8c%Qh)9+@!FY75|~s)Op8RMp31k4DVd_
zuLy%2TEtq0U>?uEsZLsmQS9U7Rxz7RXLtzal&j}^AIe+}2y4jcW9G9M-W3VlYN|PQ
z+(R0EC4s|}Z-{r+ACCzmj@54H_}R0$5N3pIlXVv^5%CKx-eI-Ul9gF+ffffRmAe+YG=AP6|r5)I0d={;Ypl!o#{&)3(x~kJ&~lH<Cnk^Yq(_w?lUq
zsgi5=s(%gAngvMg&-*4$>uXaC?j^n|(rck&qyz9oUPiF42m?$vWOX$j;T5*x7whTgF
zLU(%;)d8GDx^tfa2N3M5%%3TA+wErk1{$Ap6M3VrT}%W)wg7V&wwaniuo=RoPoz{iMb)Uvvi(e>h}%CO%KJbec;DiaO#E
zL(ige;mjMWAq0m0hCQftRs9GX{?KtZ4ebM<_)Hr(;!XmdB+r7zU81A6i}c;0efXs7
z9zs>5b+dOk;Yp3`{p95JPlx*_CyhU^>fINdIgs9q
z;?KYCpBLfzy(?5bE4mcJmufaI7ng@Fd%dq@gPei5VzJ{8SV(gJ6qSY7@2_W5we^?f
zR<}iUOVpeymfDXTK7)|dl;~bghjtnVfSfkpni2?ns1c5X0?`8i3&sZU10jvteKjk<
zXn=}Z3F;8I*r5!yU17TP`~m`F!4#RL@$1{gqn(Z2#y6i)+nWXi;&`-49VZ^|Jyu^H
zZXP^*yEr&l+f`q74j!rY+iQC+SjUs~U8uRUxA`l-_T7d3
zBD@G8)1qivPYD=Wzl`g*vCq1x*P^|8#~V68@+&c63gMUi`2{@rZV|Ln^|!WYEGv9Tmhrd{pj)l=#ltz$?r<=Nu_el}o?S!WS5i>a%iW#il&P4yiZ6_#mX
zP{r5}*V3GAxC(@X(vj3LvVcukpBJKC*fGpUC4i?NyU18;TeKUSYlv;|o@lzUU36{z
zm{D~i#xL7A=(dreC+UlE`$fNep$>3`-)LIVB(-TDGJoMmC`pdO&rvcg6-yW2Bg}oN
z0~u|bX?E&{SF@qUxL?k7%LAp%6tkyr;Az#|
zu1iw{V-aerE$QJM$_8Rfin*F^Em-2oVz9P|W%qVpsF+7KPS2A)inYY7l=XTwHF@;J
z(=89)m#}W!D(EE@CR?H9E{AW#`AX?C%$z0ltC8;PQcx7Q_ZUFw&a47qO`8_t!-KW3A
zp<+ll-hjr%Z2QK;j>5vh1~`VvnDaS;A*zyoNL+#-x4qUa8uJDheKeU)eVT?C!KX-LnDX`@8Fm>
zi5_$K!NHg+5ghY5C88-}{=u+=k$juYD^$LIHHNL*y@Ge0)qe#~Y&_1n)S#f>vpbc`
z9&G*NRexy(&jo1#21ZV{2yCrq@}|B#6Lw~k^WYu)rnAxf8d1}D;q)5oj$uZ_v09vK
zVNL0Gti8sD`(p3MAs3@(GIs@jA5TVbztf$*aX7sLJ>Gw{D8EyO9zR_@oQ+r-Y*>I<
z&Z83%Y9uEqzP`pRL{cPEFYN@nB8ybqYu0_={D;&9r%m=epH9c8eS5F@p+9T9e(}>^
zp1(S=vFvw#IzCqacXa&kFZNHK@4*SWRFmjZMVlw_9TWJwqeCF+12)pZU+bF3rkj_b
zwihn@W+G*e0SfVm>Cb-T$UFl*p92P=$
zbQ9&1j3QvrR&zH|OCdZ|#MKSTJDNDh7pnINbuqwn$WSE41GTC2==?qV6Aa={?@+}4
zT$pKtC7Tpn6;BR3K*C|nw%nUu(hg$5JmX{Hu|i$4aXXhdaP$=>I*S~wU+vl==-P(C
zL@}EkZT;Q6A!HtzvCiXW07Ok0V(8jmuM5-IqgPCZKk5TxD+1JRG_5RXn%D9NoA=@B
z_radI7IGL=LOC1F%6VtgLQ(BEZv|j|EkIabTM|TnJhrXZA3j!X*Y+RRZaY|%^Xa8&
z{&;;K?!b1Q=mZrHo}{P2ior1ac*1uzVC_xt9K2R?v##A*Xm7lE7X)x4T&HB~s*OMg
zLCn`G=fzcxYDO%niotl5sHvaOz!P8-p4nY6KHPk?mhVF1YE;RDat0E`WHz!bM_if{
z0=M!swN-=~5@z`pG*&>c-{Y*x13O?0Gi_^=|(!+?F%43PE(E;s*@)~WUp*_66
zw+2gP`+@p<AX9Lcsg&&IA%-e}G;R17zAn#f(n-VLMIV>#cjeu}F
zTPz_+0cTuVYN!-kh#C24<$w*|F9T^#r^D-1E&x43qmx*}pwFb?wSv#}(2&06M~R3-
zlz(wU=USGqUi!n~KIAch+?~awn6;YPfkH`SnwUkOyPU4molfYz_f2wL+!nqCqO)PK
zPU8JQ=;Xq>dDC8W=vhYJpGW2BbTo#SapBOFoHu#qs^%`k+A&9BL-^EXdc9#paA9Vh
z8ivklUz6ujtH|3U9L6ZSO@`nBe-`-Me~;90qEeJrkN99-iVJzcjLBXs5iwuBTmKhg3mNzPYk+or_`;VxlPAr
zoIs`}%q`1+H|;6`bFNsvi;htqJ75(rpIH?p)g9vDTlA#8fS)-HKh;NA4!7vS*wJWa
z7i{SJ>I(~Tq7m-L+B4CCV%JuKsn&O#^&p|6qgyM}KtFm{=Y`DGfN_Y#k0Kfk@T2UR
zmj0{1zU5als4I8Kx?Ok1XOmyW+pEd-r4Vrkm9K!v<}DCW=e@5%lC?Z4$Pd%r>f87D
zl#8PCNtATcKhb}#gzvcmfV^j|2Z?nY!5%ZwIQ6rGo<4eNH_OKdPwwkeES#Dit${wh
z`QR}*M@hqCaAWEvXy?&%K*Rbb3lqF`41snQ<+brTuoP=IMkRc7gM8y~umnx20+iyp
zGGX)2PnWLrE*Q~$xOb$7xtQrgd)p3~W%NL>l9M0;K6?Z@%u&WGiXS?}&<$Hm`BYD?
z$~|Sy?s+k3JTL3ng&!8DA^UG6%*{D!~l^_w_wIF`g`F|)VzOF5R9~<=?BiX
zYidP4e7yFErq3Kr%3=mhw8@!bzk8z69epj(E`W`k$OZ|Y?F&vR++`LLB$2%#oK#jS{Cp=So=Flm3shML2
zqgv2|@rJ^>&^fm(6q|t7<)~<}k+ezA1Wb9M=3=;wRtu*BJWj)S8|FH?RGLUp&W~vO
ze9vu*bv(PoRa`^vZtvc^>U>ks70DawZWueP
zqQ+gSNevh75{b#yy*y=gx4MJzv{Zyttes+C-t%y}HtST$tHs_IqK78g
zw-b;PT$KVFr4-Xym)UNLx(QjuY_$DWobJosMQIc;KUoU#tYZN>wPf-Q(~N1KrrOdx
zVtTSnhO&tTjv-aL-7X#+G!S$IcRdzd)?Fqi1Iz6J-AkatspSMk2D*owMmJq6blZq%
z-?g!$$`(@>^#i$l^}Oy1mIUWg5^-R(G7=kgQjmbS&^vK>w{lAfg5DJCJwFxG92vaung-)EvyCN
z+cXS(dYR}kdF&{*wy!Tdg4YHUpSATn2ZSMc>ZFNH?1xH4?w6%W6-GuD3ZC-z@r7|+
zAZBsD5ix0JIzX05v<-PB3^?sIo(9Wlr`USnwn&$bGM#_koq9N)#0!d*aWi5~TPjb1
zeSagFr`6;m*3L&h)$t#PYr{vwBHQAyuTK4XwWss;UiF9I3Ea?Wj@Q$?~1nAm^-(G5mBi`n&DfpxaU3*gT}CK}vPI_Q0cGF-JTB?juM1SdL}5%g!lb
zu0W@dm;2G#`fy|D9EC`2X=bachiMJ+nN$l?aHjuBbwtJ^H7I9n%9ZldNUENxDfz|s
z`fzPcs-#nFkE{$UHk`6DwLc#s;OA>d^CAcoVh&q
zsftOVmvo-ac|)T^VNjuzPHnZOo$KerR@O1SMk;8Hch&(;yRWaf0mCRqAf2)uu@9}`rK2yQMu6t^Cd*gQ9;&ByEO>u1$tO4jqsxM%)UNA=?0TS|PcEHUac#ZzVH
z16&l2i~6G_&HN~*i#aUVo>KlNg*Y-Nk9v(Y{lEK4*w4;S`>pkjNA1SOlXm05W?P9R
zwXkkAiH`F1N8)dCGgCEq{AAF7P(4-2dbWZd>BgoSVffEl_sM2FSbfqhp^ajwPJayf
zhK53|sgh%(`E{?co@bC66CzdtF=TV82k8TLW8x#Gg-C2#phrOIb&&qH6|yM2Ex*-y
z6dFE}LP+Qqo!`Z?%>O^Z|Ar^{V3g7XPoLux7u(j@)NUvc>KH!k2a6xIDTVT2adL0N
z8_y8k^A;x8VVF1sguH&cjim`2xm`~X@6~nDs}sG`{9k80D(4*+NxYo&ugZ(*JUn%K
zxqbN8{o|9v{r~aP{?YNt(W~v(M?d^{e6oFfeE3}L^ZTIMXyK>dyjh?eo?cc6+|mB_
z;qDJ7`>*z1|M>jX@yYA$;~xN!i-~=1E|6AjeB(2S4{oAZm;bR)#Gw!9La-3`{y~q7!Cjk_#?YR;ZYR&k!%9XUi>%atJjyjE2c6Kn3;UL6S;XW#c
zM{wQ&=T0^&$uRwTOH<7PXf*!y=*L%G4WT7qZ>y0jn0vH8;U?+}#u#12(#|X)Y%+km
zB`v$=Nz*Qo5(up2{Mg3O2*7L;;R>M!<#q=Eb*Lu^|S-7uF^ny2T#BKkMu?&htv=oR}z|{{5$6I
z&ICokVD$$Z%gnTS$7Cmq>7Hirm^>>u0()S;Wa2Hd?7oh$vfu5D*dVH=t8SrA{W-0<72%7r!z
z5VyJ~Cm$BY$%*%~$^a4(
z(~v;>H{izw=$RencTv(*u&!v(bYX+GY~}{oKjKnXXv6o8$ITk``lr*yymvb8Pu|B8
zEZG*hLxfBbAaQd?nV!$~ld08Cce=u|>@aF)fJT!*`7Dz5fwgRrqGMD4sWmn^m!*lO
zg0sv=rWRq_VI2|k%-toWDAmHB%>DZ}mX$(BZ`uCK{>iJKUheE4p8R$H-;XwYz*6@Z
z3N{fdg>}SG{P(LV`L(#jKTjr8`coCFpYOMOPgJ~Jsk1Y?I^@$qZqT5@f5plcdr`PD!
z)>6qiHr80;k&x!&2NL+zheDp7ovAHP`$f6GzauF4&paYBeqv_ch$$$DW?jf!GqTZh
zzqL@FqUOt`FX?$aLR>8K@7AeIC~*)>DW!?cdDI~J7NN1t$JFx6sEw)6M)VP(g3aMD
zBy-ds@H%06&oBsNB60P2js%faF|#%p6&wm4VmFk7d`K~rO%qC+&S>=dXWU61{$=w`
zB;ft7^QmmyBB4q}7L&mFU!255?1?@SMitFonr4V+IO%~x6v=|`GmOOh5^$zi=g=_`
zj{jZ=$mE#uyA+(Ik-O_;AkDn6VQIrSzd(P4l@&W7s3t@q1YtFwpF_U8?#biuxektT)<)XCqtK(tBlD`
zJLxr~I!{^GJK7#;f$vyuiJ=3d2s@-Z<0exa+tIa|b;R}T$ed4nY;AeHhOy-x!iDa&
zdHPhwsM^|X-$`V0iJF)KGsn~hBxFeD*^D5h*rUxS>c9JYk7?#2^ML;0?t=}S#i%Kr
z?^u#!(F%r_8%lVcy8ZcyHf3Pz-MZ(-O|nrC*fRC*aSm1`KBjfl@qNLbSXtE=QkoN(h4Km!3!}>JFdqk6LTa0
zm1Yv!IID&oCz=;>vG!Ax@fY`$>Bk5rde4z}u{mLgT(~JKLmVCAcIaNrsoYPA|
zzB%~PrNE)4mV)h|VkxlX&6_POaJDcg917u1d6HX5KHof*W|rO(w1I!w(cOZOp5D*
zQVJmzqRC)I)K!Sah^pg#NxXwCrR&GJ~pT
zzPd%F(cI#!$w9xBu7eJ^4NdVbTM<@O&j#>2)(@1u1h2Tb7l*#(cQyS;SFAWJ)x5q!!!l*2F*>kWVvJ_HLj({cwC
zP;TgtB3HZSPLnTmUqh3srz$8H@i+XBX@YO34cN_XuLCW`IRC^ItS^2gn6*+s=I5Zsu~(h~gss!6E$WQq2h
zuNk~js5cfmV}w#~MOLm!=moOclrkbZe}qT*om<@pK`?~NCfhrePn`XTOWj9Q4U;VH
zM(Z!FnSl8RxsNn9&W+Mb_4x#9Q_>_2KC4C_^sk%_(Dn#BVAj&5A^Z;t2CnsoquDP>
zXFq5v8yH@zy`D!&MPg`13ROvR)io%*UWlvl6^FqO<6NtR^gnP47~!oQapMV@U5yfP
z>nMKSOh;KQ4O_}#D7(eLa)K@($Oo~uqnPtwe|a(znO~0Vd?2dx+QK%Mr6aVL-#WY$
zjZw6G(Kwo&N?90hz)g!E6`(D1oyNQ^s6Uyvdgs|k=AS(#u!X@ml$pb+8l@VsMdXe<
z;xND2dn{~N*;a4ZUwIa|2XO%uHyVeldc;TE(?fxQ&FZTPn@PY9V=Uw}Vc_98s1c(Ypl
z>0$C{uoWGC6}K)j#F3?!^0;{RNv@%ktn;ywSUCg2($f|_J};-bl_Ks~Tr5UC%v;&J
ziya6k#>>t4df+oLMhkfp_l*woZ^BI!X}s3%-UN4{lJn?JQ*$LU8dzC
zljVOL8N0&NTyJ)WBtC`LQiVSpHcx~Ns~e2Is}WS)*eC4D>6bxs99~uBHcsa=O>O_o
z27@)cAk{o)uWFF+zJ;YWoHGJxn>rp}ta4MZD+Vk+((NAl#t@Ll*;z$4^<9mD`pBGNDCrRN+
z(uVhZ5}uA6ge97cbdquHi@Ci50K=&C^C#?>O%H`$NeufRurO$b(1i_!ji1Ovj;75MV01G7f!jt
zMVmG7i{)52zVuMji2XEVg>L|pknHpXWCNBfxaRSlt-!;i=zNZErrV7F{QN_~qK}~-
zEPxg7m~Ew?5>v)zbN$JisHfE7ck=oKczGlRAu$;x92?~x
zVlM2O9KFfOU%wd;q4qy=7Vc|rm0UnmWus^>HLCkkPCT`9P-jynoksIdMW%T-+Hl0q
z%$18g$$%y}p*yBZLT-#dfhn0G5uS-WufNhqkJnKzHWCcDGh8rGVZcJi{8#+@Ipfc_
zxl^(i0dwt8_XSBIOh}ZA=&ZSHzXcEkW`aFxrLR)13g57S?dt=4kkf-Hu_T}Ql$m`y
z7i~B%H{AVZRzOtlR|o3%g!QH5tm%dbQ@KkH@(qwtPh7X{qp40b--Ysr!*O)$yL51I
zD=xX<-e%d%$0YT(AVt?V1FtR!UVVI1zz#0!Je+u<3Vw6Xg
zqr`|`m@gRS3#u?*I~7)06XLILXr}%p8BrXr`Nk+%?0@&PA}nqqP`5}8gJQKI6nNiyNk~oWbmlxQ9xm*k(
zX7n|9|7maJ4dObcz3FMbn7GR*SNE%a9k
z&BIug+_;os*i~qPumaq~hvanO&-S>5?n;gK?05iM?&~lRL*9i}wxqjsXp(OQV&#S}
zOR!l)t7Z6b<}o>zbO;T-RPBtr4D4SqX=0$=UEYbNcg6_DW(lEKtn}%C
zcmih~$v5OvJICO|DILu+-!ZQ`yQEG=@WN*0R4=R?8HIMnoJ?+4NxTyDaz(Gq8i^zq
zjH|-s8p1|7;>n?*T-gC&S7TaCj+BQ~Wn{PkWm2XojC^e*=S$ERRdZGKcuA%#Vp3`Q
zyAv6jZdaN_7#viUW1w?4a0@YFS98fkvWa2%ADopPaFEj#R_=&w
z?^GW)2}3%t1s{E;wxn20A{!~NhNHQW{nK^4D&-8u7wgO<9jZu?P&pS^mV4xvnloCm*Ne&)3IiL^?HlShwTKVe{%}oQ8E0R25dEm
zEh4xcFh&HWD7p}A7r44wdRgwj?AS+FD9)>|ke&dDDmRxS)4hW3Ff3K`5(;UD_$prP
z*rVkl$#uQ2b}=wfz{;goJ7O+|MueCuSV@}`WDQ#m(D5G@Ec{!mO>=;OrMHe%4>O+F
zvSo?Q+`ggvF;LxRkTz)=(adFGkp)$1guK3!5m+A0sMke^m4heJcChCgGO>qJI_Dkc
zE3C|B(oA73?FL?=IKH+*FZyal<;P|f!TR{TCCBHk{dZuxU|6P}G-^H@B*u>VlC_wt
zGaAVEv(svR{G<~bC4U+){wz*b&b
z8&U?>?F!4SdI=DE(S8G_(UR1|pAs|xIzA|F>?lC~X5?(q!RXXtN(UP#HkzQanywF4
z;(L*~gs;K1vud}wSa}L)xD4&)O>>8GX+GSBDuzC23TpKd7LOOe90GibQoA}r?w-Vx
zOtT@*W0?`IQ-yLaUIg`yS{o1heiTdiYEX4L{4)kiwI7FRJuS&u?YtzX=6Es(Z9j8qwJ7pg
zz3pXMvhk;VQ*Tsrw7@%D@y89Q$cR-gIE0}SCYkQSb6n2s0)-%LdWn_C?xr>Y7cxxS
zgSus^6$xJ&!p;UP`3KeD8C~C$0_l~O)N1nIEu&e$Z_O1L4G#O;PN5h|X<6Fi^C?s@aRJY(qh?-
z>&{=P@y(<9*8DfeJ;BKilg8Q@eg1gCgoS4S6H_`c1m`V1R?*T?6(*YE#4mO0AcqmXlo?L*{aKMG
zD;9WLp)d>Si~ieP;_Je=1AvcXh4*vPVI%fm*>MFX-*x4`xKm3yz`Si5$ksS@7%=QW
zE1qCZKC%(V$^m`cnjgC6+mXh8xNtGzLB1dPDUp5_hs4|A5af<#LgK`x6Cu8ahi4rz
zk6t>z!1D3IH#jpUuXca^bsbeuNgIX+xXh2u<~F-SO_I?+cKLmbzVikcL=U7p+rCmC
zb5kk(`s7ZK%(Fz<${LGIbqEp1<^{hprQ%tH@X<(3Dwttc0tzm2Avf
zoym3#34xn>gDf}Z*-Q`JLe9s?bOETj
zDbXBovfjP#h2gR@^r7C1}VGo7=kCau>#wAa*?s;0Z$kr3FJ_
z{`Qzqu$qL1JrfXJeoFZ=p1%zb;g_%Z4Zy`#eOpmzh%T8W-!%QguF^DR-fBfzo*yYF
zY$e_K+VDqK;;eKWNg%zNLUYb-i|YrTNxNf1kqw_7aQGCvUL_cCR0~l2S;=2qIl?0&
zN&mRu*kdq&_C@v>_iRJXY6OaWB%fH$CC%t+Lv2NCW(7Uqw7_P21_o3?Ex!{c2N=;H
zm1DS4k?rWSHS`FL;xbwMwHwXKq;81UUBz1sj$!NlLI6#0r;O0_@hP<0$M@nq!PsSl9eu|91
zFN{%C9Ujyn#@cypCv1?kT3c(RkJ>68CM`@q7AT$%FE`FdD7AWRMLF{5!kSPM7=}yW
zc`ZKMSQ0NzY6;~a{^z6O0m6b8Y$ug~4b}5V?K@U)zs@z2AGh1fU_V)&b@8%631h0j
zzaQQ*lMzp#yitv^>Wg^;8#(!IhO%n2rUk^z5(5wO%ezB9bU`#yuppxbn%Kfg(_jnSe!TYTD0j$-NrfK9zyW3bQBG~Lo-Pkc~Xw7
zmm8^pn8b@f@HZ^o4CJRwK>VzNkT4jY7g)PcJx3?@2KTwY_&dvPVU?1r$Clr~48vK_5$;qp@^cUA$hTYq}yMwz4
z#ICQ`vbry(k2g)*0n~;-VW1WMX5_+AGEX<-?d3|SH##}$FSQs9Au^_n?;6tcN>-wi
ziy_ne<&^@1@?UB+8bu3>@$!@A$=XknN2Kx`zEAi?{5RN`P)3zd*!AQCE+hl`6QHb<
zuh5!_gGOShoj%is`IT~l4DPh2s&pGsBW`9)?&*avvw(y^
zUHe}Xc)zvx16^Mu8WNVBh1V|)BOzt5UtXGn#IB)F&lUy!u0p<#HcmE|O+p6fLLH_e
zHu;X9+gVEW@Gb=K=C6=>3m;mot|l(kT<;iby>1KX8jHPmuyoZ;*{6$!0HOxQ#8z#3
zHZhYimVKr6folxwHQ*N04iWeS{m@zh&ZTg&x5b;Ga4x?L(hdv15!9m{W8)4zAhftK
z2^4lw4U22UuuFY2g3Jonp2atP0uZN4ULNzVNcIgMcl8pT9A(%%gqY;D=$|s`3=h`B
z2v5(~$RK?rUiiBPJ|Dfkx{zZD*sso-)J_n?ZN%wQrJxG{s%6~4-ir(>X;J>e;lWe^dB4e_$L^l?w?<>X-
z|DNKsO!U{+vWT8w@=!J@@|K!Ra^dsgnSKyrPT25asa<;Rqh7iYO_%8F`3?7?Rzav{
znD$to@6EZ|h(|q{`7zTYB0Q<*jF`Kxmw)^gA!iUcr*rX~b8*7Pt=xjIHAAtKUt2Ss
zsj0i#vum_H&Sn=gxw!)cNcD4GylWMQ5`k6Xc+NBCqgqy8LlNX!gvEnFRMDh4gdyAH
zXkLI`d2mmB`D-XGnXwJp&i-4t0>NcQ4&s$D9tAc&@mI-&(11rddyIL$&sQ1Yk(1wz
zonQkDWpqRiQDC3AT9*MQW@>6nkQPq?+;h8=IC#8sM>Uj?G8I(iMG2;*PVjkKJOCrd
z8GTEa)#_!VB(A@R^bw7c__m{I(9X$~6Gl|(J57pL?#hN~QU-<=gaS-#`qbd0xAYX#
z%To;~p7Z#JSXejAO@Ii+kri&CrY-J_v9T+6naZ&g%GtQI#2MdFuB8pZ8W2
z?o%eU1+dK~poiy3_vgRX?_b?K)(8mnqQJR@31yE)&EzgTFr)5sA0<)p)`}~Ginf!b*8?mG%
zKlsesK(;1Z$N#jZFeg7yi$bQM|NXmpF+IgLqsDlVliGt^NjQ=5pL?hkaHw=`E<*}2
z`uy@?Ni@2LG-wBokA$nH4-8yzQ2XgSOBeZtFCcBZ`BRitcd@{_4kWc5-+WjT_9MyQFMpT7cO4J0zonm8B&7{Ez#t#
zx25g+9->C`{(>B7eSk^2HJsc1Fc_aF3|Jnz5(_#|sZ&$9rAks1^l7b?#u&mS3OrCm
z#C(|b7O!^t{(AZwh4H(TN%VVwh+h!Ef}aeE94*oE)b=%jy|kzdR{QiEsyybZ|1i}$r64!gwU2n2)AFNuUpJO2Vm1pG5s1OQkAb
z#Rn?L_S{el+>~C(SzmFcS|M)7I8
zsLDoH-31B19VG1xX%&}hx1XzM%I2Cod(`_$QNzy%9LF8&s?)^)Sh>i}zcQK?EkDqrvQ{$qG@tuG
zMSe7GyHZEW^ux7$=lGqnU+^{`W{vPvtEEI8`|Jp6cF
zGs!m|c*);If8t;FLM=Gir&J-cY
zb*R8u1X|Cg8CXy+t@L**o5%?)Kfn*z24)Y14R1H7?CA=qCh6Hzcfe{wzjS{GNcwR>Pk)9^G`
z1k;TXW`VOlMZ=nTQHqIByP2{&#|_99DY~HE3h?a~X><^mcR~+qNCnA(U3!`ZYnGHy
z-jncwgmaxC6RTZvh|=}m(XzEC5?o3KV7a=Y!wuY^t7=>VZUBaZXIjg8{sdg0`e89l
z70xi@$XRxL*)nE-y)XF+%XD<{{O0p5RyA8ssr|YYxot$nNZxX}xu(Dz5>i28WkcKJV|vDk=u*ka-Zhs7%m7P#PSD)=__#5vda+RrRFZ-eu*mdj2=%H6A|
z+@UU23*M|6`YgFiUyE5+PhbnLgSeurYxdAr!|GK7F{Qb@;Z+#0;$D-6Vv{oBSZ
zx=^im0dZdZUToo~)GW92*mV7`aw;Sxq@_wq2U@~vh415?EYnzdW4{&J`X5R|z5tm$
z3lOK#3XAEX7IBTNSaB}o6AX6NAh;8llP?0nwQ!7yOBnYqSr+=HtZo|B3y!SYTAQkg
znh@NG_FIZM@6C1L$}R|I;HQKhK!*VBcdu45fVZr9c^`4p9#p3vi?FZ~4yrswn<<9~ywPqblUg^_@Oe5HYa@ctjDMH>T0E0aHT_6BAqbcT)=#%3n;
zKU`{UE!TB6WS{A3eYZN^1=S)G&aUO#cpJ{!rP|Jv1ef!dng%cpYf42jahfgVZ*NF7
z5K>Bo)(Z=KW9Ywj5P`k=ra%KzjCJIlCTv
z#pZMoiQxng-y-1|hUUM<@_u6v#FNoXA!ny-2;9#D$q9XrxH}Wo+aJvGe3y2E-rom>t^sO$Shl$LG6PK?#pb%BPd{2&0Eo+-noDii`q@
zlz#hxu|~h}S4OKwKJGDgcfSDUQXf$Gp#o2K*^>rVsB&5?ywJS_h0NM#Q@{6J=X|Ti
z@&P%}{z`c!wgCc?pa&Jc_OY7$UFvq4O`G~*ue3etiaFhUw~4Xh9~!WrnN?&b(|}$*
z+*c)@7$r8=SRcdA%Z-nXOHcMq-|q9LH{I(xr%g|%#b>V1ugTZjb{~u&1BA~7y?)T3
zWe#(sX+C)|HYt7Lt+^BofzJ@utJ|h2Mtr|N`3;*5!oE!A8ix^fn~3rJ^r99N;PIPg
zjKf~CfA6*q;Jz2z+x~=qi6Zo#jK(WlJW4u7nYEr&aaXr*9kw?QZ{l1ZU-^0vmTEkUS)kR(apdGO2n1%de&^PkXE41
zTvJY1-lQSv~zpd27*WXGtAwBu9qGL@)?Z9xj5x{6Xs
zdW^_H7#Z${F(IYM5nUf!W}^Ygi-3VQMp?ejvIA0f4$+cbqV
z<;~3bL4lr_opQ)dg}x{0#?nKWfzNR~qA&nq!=0a;z%m)TuG?B#>%5^n6h?{k?ihi6
zc1JLS{FI>K3_O`C%%9z0cvAEcuC;Sb{_1c1AR-<##
z&lX2COB@Bsr?BWPLP77gDtJP5p;FR08{4di(
zE7pOrLDRaL&c;WHzjqDYzqlqQj`=aWZ-wA&JOR^~KTICP$^uomzhgVRBpwfKTEM0J
z6kM9LqUr93LMG88F$#=E?Ot7I3`3*1O16^ui91*y_R3rgCFA5VIj8$S6tc&fgDV38
z5WHxVyvx@WZN`7_%&9wX;4dL;KW;3v6z6Q1oZXlJ#6JV^Ya|9c)sG)HacuQIFTGqb
z`-rc~^Ew7q72RKTciRK9EF5tQn_m2yTn~HjW|&@GlMBL$>lq-bxsNJiRyRJqCV4R@
zbd~K!mMl1sM0L2D$03v+;=@Zc<;gVodJNLFIqX*9!@ZQwEpv{I$x0(QG*!QXB?2jh
z@`klfEwnKq096+qWnq7uzacRN|H8wMe_c_^wteYeaNN+iCm2Ay4?{3d-mHw~Y3#{u
zo1H*JyJ>NDxcAo_4Ja-Y^|PQBy}xOjhx{g))NGG{8=(Uo3~UM7rIwL&A+DyuAuD=r
z31FhA7lHp)B=vxmju+bg!o{m#vNi~h;V7;$CAJ$5pJ??9J2!r)6e&oq$+kRCW#sAtL+QaJYR=HKMKmRaY~D%ab}18D9o-`
z1_|pDRGMR}HqS5Iqgdk)bT;fQLcocsGK2bC>T9}DVNUy*vFDA
zDZcAeM;4C4^&^(g&6K7{_@crF%NY_p?1sabCmjk>z6tAa8DF<`4?Hy{l3Et{XonF+
zyc=P(5F8wk1+px{1R0I0fnTN_e2#WQUQh?(hn;gktmW7$;QNibbNlU2L!I-2MAo>{
zHjQk$?LP5`*2h;XI?uQR^@8SbY$O63%nB(JADp2XU%veoyc>Q_p0Yu!*yS%X>*OQJ|n`v3gM}4eG_bC^HS$!gM0NW
z?(*`=1}N3QSZ`==YIN#0)Y{7IS-noY!ppm+GJ2Elg@+T)w8n7!QJWu%NRlT
zg^c*(wVEq!)7SFMCOd^HZ6U2To7%}HE!Ga2u)eyn3EU7sr)^*v>naE4i%Y|n+_OZVFET8>&v-L-)`PTCWV1%YqKjZ_}gxMgQN#vPD2Y@$jG4@{;WH
zTQ55HQdp-(mG#~-&TSD6k2SS*`47^;yP3X(O!j2n=vj~GJR(W@4^PypkzUYC=mV7*
z2JCS{@$3Ue%9Skf&hS=#ufl0JAvIqvU7baZSpo+{PEz&KrKjXf9~lD0Z(xwKIP%uk
z|1islUs?{L3M5g%=A<}^e5eIM<$?{FTp@-G_9*1Mzk%HpF8!BIo1BYH=Np_;NK)?%
z+$;Yf&(9M`nP^iG&J{{)8rn?OqRwJKr`pZoi#!VEJ+G{<(Bc19Fi`3fEEj*-q^1Zw
za0@0J>j8dF!!e&O2uYO=h=frejF#$c6>cjFqUByYLTvjDUcB>~Q3JNAMUj|#m
z($-^7ExJC+w-VzhdBFAj4w3k67YCZv#Q0ES+}*2-b@xj}VXF`H-0eB(RFNWVrLz@i
zr}c!Higa4xH=f)4pXg0a<}IA^s|UK4w=%3PMA-|lJ>Eo!ur~k+6WsgK2m;eyTdiBe
z;VJW0%De7{+O7H;<2iwITxz*nU@hh&+VlVmLFt)w{>gGeoNYizpMAN*zqUsnwe>VM
zJom!fmd;rmJml={rG**zhg;OpN+1^XAB5Rcd6lB_zoSxoTMM=a<~fnQ6kycNbBT`u
za9KPsnJqm=W{bN5PXscixyZ-{@pWc2w#QoKar@wSzZN?aH|FM^RlKP2^c)td>G8_f
z7N+Oi2Lz;|ik0XKB0g`-RMDLzlxe+6
zG|=OKU*O^oU_S&i7OOHnZpKt46HQg;#mMIb$|OE&UhUEuz`afjQD@1EE>;b-VDi#$
zg{+1jaO7ih2sP-KwlGw&pb(HoH;XbZ0{`n{z5(OJbbf^4oNXQD3!Dwdnjfn8zWrUh
zY@PufnzyR+Zl?BuR=ZrlF6bCT2Ele_cGs21!`M4qYvQ$gXQJ)&zU$5@8OzquN8R$Z
zw)P)6-dG5+OV5J)oC38lN_-3r*
zgBmE+gR%)WqPI0#&jn{;+66yWUZEO;R5SnP7iZ)yiTTq2=y~-L)6R=!*zjMV@ghPj
zFvKjhX&rT0(KE#?#ez43De3%bxnC9WD1$GmlU46Ie3=?ewm8=H)J(|;1qm^y{xOXU
z@+>CfzZ7%}-ImDlm}I@&BU;L0#I3l*wSX2=3pxA|8Sk*@QVG!}IztII5KqSq2ejUW
zlY2xWi!>x-R05T?NcN`ui&DIv=OBuSa8W(#-|vIgCJ0>2N%2?mtThjOfaWE{kwJ1ksVOl3ZD3uGlpvXL=S^W0Z7%qlbN7Mv
z8RzH?yCm#iMF4%rb2c@4cv@djfA9G6kZZy2qhRY`F0w12hhZWf7CMsbh_gjZ4+XWpyJW-y&CBFZDPvLpe#&athsz@joLNDl&p?1-)ox8hZ)
zG=4o!!o?zsEak`|m6jk~AHUw8wR3?Mt6eEn$$ihE{Z}Lx9s?SJ2jHPH_ynsm<5V3Q
zh!klvkQK7&2Imyzo0jovbe6m2LRN`?e}$MA))*hChhAzFzI0fN{mBsjsIYTPHVBe$iyvpp2KFuE2N{1!*z&7eO|vSfY8+>N6QDHqqVnDJ7b!
z;^G*2zGlR}JRCWmJXiQ2r2>)uK>IIm2u*0Z2-1?5!=|!dnELY}&-`QDbbUi+i~g?&
z7i9|rmWr|uuxZ0zjihp;o#js+<=aOm2p&O6Qq|TE!`5#V$^U>NKO{1ErInm4FZX4J53KrP1m_4b_BO{D6U9gG4yG1Hq@w}P7L?J8%eXsi}a39RBxy-t1@b|
zc_TlS;1VRMBY`b$=E*l5?C1f66e8HsfOv*E118IHdW{JswnaXgzeY;E+=$(@fY<*x
zjLoF?-(oBG=$k&WbuW8}sS(i3*!pbHb^k0gd-+?ec>pc-8vHCHy$_Z)3e+k2&x10E
zX>ez>^_fr9YJz^|`>}s%3Bm1rRoSh8a|el|C>HCE=Ouw%!LYZ(9=cre>wPx!RW%2_
zuzOM2wcVaWX$gBZv1=Q!|3X48CNpMzKzDZB1sjTJlMGPbIY#3tVX!>slhz$^MAMJ=
zEZhtr?b`L5y5K{uR_M+ZsAMg<3JBsE0oR<3<`_H}3%q}ioL;;<7VBmg&L+eTT18YY
za6zzd!iqjSIyA9FZrsgVp%g#yg(M`FcDHJ>XIya+mMZg%`REoMxi^3Y0jz`bOIgYP
ze8B(#%!=yHJiE1Qajq-8F8fV(`4;=DUc+4d#oDN|xa6#3qip*=Ry%%YzI+4!Z}$tk
z?Nr?fFc1(QI1murkNd^Oz}CXl#OcqEv&GIfSy{#|pAoV1SWO+b+z>=qfo-_*4c0@$
zLWO8px|eQc1V6p1?CTj10Gv=~!xlR7L<}*}`hVW>uFgb1ZmtMqJ*I8M;=I_%-sv5NU4Jm<
zu(g{kn6irvj`HjOad1@YKG!sV1cR?vtEr;+_XbO6d1A>Er+86C+PVS?MI+@>EtO05
zI!np)%=WVn@*1X)C6Lh$(S7g>7GZEVo+I-Z<`)vZtSR$*sYYCa_W!7&{tQC>*Y#xMsx2Tv
zfqs)
zWC7<>qa9$5+KMDR^IqOq4Sv?}5JOMW5a@BpgeitVz(?RwfC+u1oD~rAmWmz_Q!t!@
z8PbLu6i`s5+Tuu~u;87!o%<~!f8y`C7&;41(r-1Qw+N~Gg8~cUyf!gaTJz2}>3_jW
z4?|_@o4Eb3a@t9mxFin?s^$}ISiM+78AkD_=cXiCIWAP!O_KZ9_fr~O&!5|b
zUsZ3PU3cEsR##elW(P5=6voXAr!6_nBcko-tJXypPsox;AkWU%{FAqxZWe>XJq*9M
zEd$xy=)|GyE%y>;9rQOw`wr(yI1fjPEgOsJuiDwi<*KAI-9nNp8Kb|!GhA0?mS#dx
zBA=kF|1HEbHtrtncEGVx$#!I@;=wATahLm8_5bT=wFLgX8v5mQMoHc>QAW*rrA_+h
zR^#rv4{q9|D>=DRUeUzFMq?*`8NFLWhgilu;AyhbA4jcL5dm{LB64Pzg7}?o}IU0v?vUQl+{$;@(+w;z>_ot$6
z4C6|hrp-6aVW3Jz5qA4+$oGSp^L=MH4SS+bH8PbCucl3vVv~dZ{uO%_>b{~%gc(v!C?Q#is2;0g%y8V
z#{UQu#Lrd@wbV1Gt_#&SUZ=O|+i=>OgSkK#JJ_0PQl5T%MFAQH+0
z+x&JwjUaB!gA&oMQLX_mjD`oSDPnNV-f-IXBr2Kz8vnfO^t{&aId+}ueD3@kbYje{;s0F@(#wAP
zPv_(Fe(p5td`>uUF6j!rX#N#dKF$<4Hhg$M%_21e;Ef3OE0oWerq+nlBVOdo0)MII
z`6=&55ti~)&UX$O!JK5P*7Y{YY1nR+E(
z9V$IQKlnfW+0jiGVO0&GW6Adm%sSQwP@2qERmtDdNX
z2}CDH0f~zdcDxk5VWoa^Lg`X_Enqb^*z>y{Pt*d0>)XH3<)s8hYeo`9C=*46YY!(x
z8x4msh~Nm6)A^yuN5Q%JQ(gVcU$m7&f6u({lCM(*b|P2C_gMg_)*%jn^A7MR`y~*M
z$<{$lcB<6}M$#u3X-ktxD#B|pK2}$1)T4C@%;0WGP1WPzl_uy`2Ns1})`L!Wy!D_9
zNiAXNe`~~$|5~{bm{-CYx+P`8&?2I*y3)?s^AJRhhlS7zg-r9x%H9dtePxcdes(P$
zfGJSyb@szR#8Cd76riJW-2|T3`b)jg!PITEuvhPhrw4N~L5j(}(P=%X7ObBlH~2SC
zB$lx$jF$f#GaZ0Xn&Jw8<5`G57H1Emk31kMTkT++T(Z}Mposx
z1nW*Jo|K#+vl*%@>TUyLah&dY%71M)Z>(X)5i#QQ6nXPXN4S(uj@W}pH@OaS!T2cP
zkVgoZ2jloq$4rF&M`A1NxQ0HHN+u`2PM<}F{xmQLiJ#vn$AFrL$TkQJ8DzwnFGA-4
zF(42nfUS2-y6=W2UA@S{-(!fY0?Rt%7SAICIu!kIup8*|IG{yUT$3!kaGxB7_gdbm
zg95$7NR){Lf<$7}2}A@y7>I!+X4X<(XUvqg-|2TGUDzM~tL3%bY@Q}!)8_KjrT$6T
zb?4_$_a$>BsO||DqmM3cgh}ORnNaa;tU+UxGAJ(Q(J!vFT}!r5)*=pGYh~mO>fLrv
z5^Xo=w>2oRx8wJ6yL15X^HW811*_o0oj~$dEP94{bZ`;R{M;e+N!{;HtornvPkxRL
zAAa6nrkKtn$yR%B^$-bS5@XRH(jo>PO`(foDT9V|0J+Bu1Ez9sylvu%V@jIpu5p5V
zJDo>R6g4dxvFE(0)_K^F>0l$2=&yd^r$20`mr0yy)W*``nA})}fDyc~WCw9S4
zR=|u$!vRHI18(B<@xpMSnK_prc_dx5kq0u6^t8GadperitaQ1{@MoQ~HSVC+K!CQ^
zu)Q};a+ws^B~g&Zf@7?VF_W(cGin$Ff1TWBiYv<_8dorzx%82Nw(!l!SrEqMhJfpn
z{%qymnxJ{t9B;Dyl#gs$u{Ke+wvi)F$mn=(V^Z@t94yAkUZWp1hmWW^%8#0>9wpl6
z(V-Q*?`ls=bS7d{ZgyzUH~9u*^8uwze_&DmRn_HKd9B+a)EcYTSVmPBzHx##*s`pQ
zDofH`D;$>eRUt%o6m(&>8A}91+=H=Sptlvo+Qb!OW$TAMe)-TVv%UkIMxE;pIXSrYKx`bG
z(~I%1NAbIs;YHVE=MmrSy$lc{tOT+b)A)7-a&_XQd@ktPSVFmI7i
z{5+b*b78HCC=9i4)q0qj;O@|mMH`XK-HPi_Hd3joO^dWU()bRNuAA@
z6{CzNds0Jp^bVGW`J0z3adCopw_SEHri1tsF_KP)Hg~jOxbM4`1J?Y4kbx&ChKkx5Vnyge2
z@3|4+>(P8xq}i!jk`J{vLf6a8~nd0^LQ2zA%E@-GWZYG@!Ncrbl6z4-=Mu?J6J2Cay%0I40
zj!3?>79D#YAcPn#U`o1Fp72eVu@PGdHJLWvD=DqN)wzSue8dK126(MB3cLheZEN{;
zzBbP5nGWg0D@{d$h6YyT&2*!`w{H=?9yc0Ywy%;}F4KA1y2FK=q2X!E{K+NkW2FND
zL32+EgXHPHwmvaWwe8*Jf2ogW;HJ2rDyQ86sGz4<|qtFvheTZ^4Z(3>{uVAX?cFH<7i;$voJsVq3p^9s#>BR5+qRR5
zZQHhO+qN^YZ9DmbJ$s+4|EYcMPFJn2>Z-o$>Q%koUhnU@pMNjkQM;b+jkBB!tyywX
z;GaBDw_*8|%E(Ehrlt*CJKmD+8{@Ft=yc`fShkj2<}tY-gF;0(t(^3k9S;m38T{Qi
z){&ORDbOhQ+BY~brUvWCa&IbJm-L7|qbc3`R5OYzdpTJ~WARg>
zJZ_#Wg4dP9@OYJ`PhO3uwd?D0u)2WxNp2E~TqqvAl`~63VJ#15VHkfvRVTb2O(O-KABJZ#7=}(4oq2Z1lxW#qRjCV)o+*bvL8<;
z_v?B{X<(DbHTsq|#cB;pT;5SfG|5Noxv^|;Ia(G!u1De**NfnKpc%rY4<(2Tj_1f-
zS%#=e@75x&0N0DDV2>_>qh1A8`W+dvOXaCab`$tPy5UpP**AS^k{%!phBaMTDN-aw
zG*e!gzJHh~zQ`knI3Kx5NYR|=A59QpzfaD%j%8QWQ+pw_!MVzp{k4wNBpE9vHUDVAdL1uTVeFh^&-jp9pOPpSZT#
zu1)HlGyPdjkcs$-ihwj7s#~cn$l)!y9bon|v1$zr4iTb;t9{d>7{(&b=lI%KA|H)ihARgVg?
z)_5`KEuFU87xDk0O&6j7n*Is-3_}z8*=-95
zVfcyrVakM0P;Uz?jm`
z4mDafrWt+WiqCBHZ2u#T{f^kH`DYA(z%j9J;h=L&U;0G2CT?A?uq5bzG%x(q@uB)t
z78_gUjh}ty51`KLs3i|7DE&+o|HaoXeWT{|z{)DZz}%!P#6i!J~4D
zheG%8A?LHfq1p)I9a0gb2Th)D>RV5BNNccfGt~WT6!v7C-fzl?EWKYfb>v$v0&S`~
ztAZo9k?~x^02OgT*NHKiE)nxqaLRs0Pde*QaY$4}f5ZfVds_36zOo#Kei*C3iuGx{
zo)6%{?~W}&0&zxiv0$uTde2T;Bwl-*LheX-C5Fy5+9hPA=%TssF%KD&I*WB&aT@5M
z-1YwvY<^ler)D>v&bFHXdmy9BbgC)T>hoIIkAG8W-GCuW{4w@0+CAq#xuG954w9$$
zJ2a^dQ}r0I2xMz;&U==?5|NaPwWZ80)qO?X!ccL>%iR{!+ZaSIi!n1c;Uzz}_dv)7
zUg6g-Er8y5rR%jid(fxyb1CYdoy9h%l)n}4m(9b(fu+vmN;EBK)<62VE)mAUiGX7O)Quu_5uQr=7y*0-n2osK*_V;u0Di7J7Aa*
zSC-=1{PSLSV%yOc+rej6t)KSjp(!%L!J58fC}NU0w5Bwky3v%eD^j4YUad;3I>zW-
z92L98%v-rct@q)CHCDwKNe_~rt0FH#hQ5jV-P~!}W<-V)@A+%Hg?MpRBLE#V?Ww&n
z8}g3zF!%0ipTfo~mrii*QSM<3Z=dqSDs?%1o0zYxzdDIx=b>?W=6k?!@CA@;L9E-@Kq6EhtnG
ziQN2ZO{L^TkKMrJGd+C?e#b7wqeYL5
zf^z>v#ve~RgR@)jW9`q=vMEKE{6nKt{jQyvrOD{MnuYm@Qc1o_7EcrQRBQ*QSUVL<
zm?sx3a8AMsYt-#lfe_0cVXIr$Lry$a8{Q1lND9q*9>xnOY|tw#jTAVG76Ei1yrP%
zr&oJH1s&W;?JkYBK-ad?Q`o!d(Ifd$*uVIVl9DylnIQ8Kf_@8n;m)*<^|2ZF1uHDp
zdfL`!+Dvn{Y@CX53I`;yI=HhqpbbA-($XKsIe8tMGe6BgU$`Ki%bylI-b`5KHPeE@
znn;f+dHHzs@V;#wv#Wl*q^XGaWe)EH=UD%0zmHs2B>
zpeY{4)b6Ne8?VR^xE@*TPa}HI@;%UlZ;DCSZUr}alE)k1z?4DOlzWJE)!ffqg=i3a
zbp1lNw6Eb%CNtyqGBz<0bp@ro8Ek`HK-o>|*n^y8ZM|8o_vp0m
zi45Ini3?nQ=&`<>$J+}nuJu{MZ(|~|C6r&_UeH<`nnchG7`v7x3JKZ6<~5^ztGd%}_P9Po21f_KEp}
zi(hO?*``}$h{t1f`k0zB&Ez_MV#hmhc3rzkPf9>EbK(k*;qo555TxlqINNY|_T&)l
z$BJ-<(ailXoSWma(@=R?7ECAFlV0QR8HK?eBzTmWP&YlWKKfUiqeIa$1hDLeKAUN=
z_BOtZ@O=rn;~{ege3opvRZhj|BBk*hY8cEjV%KOJjl$0mC=vyOOjLzv`N^wqD@9M%
z*pVP>Eyv6IN;|i7@w`6Ua$Ffn_V)X0@bqs3oiyYNZ|U5b!w2#zIwu_h+%X(Zr@on>
zu+$9kqEyFd!PiNP+2!Psw%%Uomzr;Xu@>V*kQ}AhxQ>fe`;vwQd(M0?Cq+ua2Ce4Z
zWv8Xjj!00uvB6zXB>b|!hj9wg?uq6M**8AFCl|PZ+!j5qr~y`%#}r;U=qs2aZdP6@
z5ffg1zcm@Y!#WjtW5zpO%g&Gbw%HzWGmehd3|;=#Nd`yse$gpx)b!%FG|xIlgEAoD
ztAU9mWz_mcT7+SrYd$)sDGC?mmR!<1YCFMpfA%1JHXC;-ZS3t$Op6_^xg$B9vi0GJ
zkQjh%XjsCw(`pAfCLH7lbI@*|!>dZX$yW}Z;Vc<>;q3|Y5{gN-uz(r62CW*!OyIZE
zN4y{2iaC|B84aJsl10i=jXa#B@RLH{6rU;W&yhg;*$}>C3#43@CfSLS&T31-*mDrwESQ
z&Cy+iLL5!LpqoT|>>iXdH|orvH&(q1a%04r*-t{D%Zdsm=P^D%kQ91s-?AQ(Ss`sz
zo|zk1C7VPC2YpQ%NMtK|jBkE`5B4`^
zUQh|Oz;v%wMMJF5tJ^N`oeiy|bkfVzsmT+L%rSz2yRan
zC)*0}G4Ju?XvT~*HT7H+eXMv~x(tsQf5IddV6YqjZP!X!nx3EL)hG5BGgK1ajdJx^
zdfOpvfXK5TEBtaTqk@(ZIpMS?92S#SNh1p#{2Mk2OnbTn=JdO>c7PSlsy-6U=yXn6
zgs`AN+6;rnhgQ2~fRXO~>>km)PJ9zsV1A;3{jb#WIZpnSY#8;uf+3b~>mEJJer#g}
zcL>YfZHDZyoXN(H{w9-bjK;4dQNUP;TbRg&@T#OMBXQr~U!2pN(1)XDL!j5bqz?51
zxwFS-Su~=Ee)wH(9|Y$NC?{R9iUdhvw`tHL#}WM|ql9ik!OuSRyNV&VIfu@{NJo6P
z+xZrU;7khRWQAr^fwf0(HN_q3MefSb4uzvDy73OF?LjCqVB0u9HT)ljs&q}MgNsy9
zf2-J&zgG^%<&w=PUFf7h<6;ft@XQN8JqcIN<@FUdUGb$3Ol(Rb#U!=&_m<<$yHPRh
zQ{&@=s1}VkO?mYs_z~>}U>Yp9i6zm_?^#n*0ho_;_aE01sSvcRh
z*fmbvZd(Wq<+#Kc-d*}G%)))>M~JMVFz>;#%h`#NOrOBOH2G~$IWMt{A_6k`+Cq~?)I
z6@*@K3dj#(a*yiNpxaUhv8{jf(dwB(n=ShRN+bRgNjY`|q(0ddT4rZK&l%cv%k%oD
zRy=)PVRE^X=D&8o0y>2V02*7|pp0Zpt~qgDSolfcnYTCu8ul?@93fxG9DXWT?8PnF
zNBXN~saS3Ad8eBQtredCbZOs|&tT@&U1`g?=wy1c&33m9`kr{>HrC8Ui&1FOS9v4E
zNoqOaLI-BmX$W$O6%xhN)obGB->ZAygiL$VV{4c|Pa{&Bw(arn7vAAuV;!bOQ1PTg
znxqQaIE1E++7TF^Y*AnC$He@Tvb@`2kV)@=@1zE<_w?VPi$FeFf_10
zDII2p9+DK2a!e|e_NRuD)M8;X(e_lm-^hWkSB)e=(qh7Kx}0XBfA*PZ5AaTS!x1^v
z42jeAqc1t_XIiqMjj8?NP|qz}O>9wUzcVP>F$0k1c!V5=z!864e0#t>KDthP$6|C_
zO(~#E)z~t86`Hn1!Gxdx6+m)H&FMQOaptpaYoMZkVUWxyIzaBNE7G*c!<)YU#wAz1
z#!TebrE+t8aFMhf6F!N)W;9R_{gMV;9#e+q16Om-nD&CCf?w6Ousiya{W)4!1CufS
zb0V@DgdgY}?Br1_0bPYtQ`Pcm&EhwM`Sp4+xUpCF4JFyeqemTzjY`${e!rj;!E=A_
zAh%NS%E02tQ$jJF{0@du1ERP=H}X)wWV0`o(jjF1`{$RX3Hnu-x3n?<+_W!l9kKUc
zZtm&2@I>9f?mALZ@6^l4!H*uzDnATb*Dhn!!@~A6LwN`oygK<4l>TBEgXU?RSP$MzicdAkZ438fnPCf(Q-RJMJ4v1ItnK*
zq7ofN*j#}91M=B%Wi!c~_3;;B#i~B?vbkp<(J9u(!9ixfyn8vGjGw4rFj@c%4oP{t
zeN!iHvBMJOI=`)GBI4EIy%p0{;FmMRsB8EYPZR&tWQ9D%H&FKfJjlqldm=B
z@rCZJRoc9QrCBCu*yJdUa~I{1{nD<@Jn`%I*&H$;<*aP5w5=UV`9XMWlF1jm0wy(9Nfuy`yran>klkx)
z&tU48>Zziw&OY_$<|TB%@!{cGA1u=V@YN<(v=yf3=7J{N8YUQ0Uk{9fu+MLY*-Sq?
zQv4ptL9JD%KPt7A`b?Wp@MMXTg_#6$~Cg|z2_ycD;JS-J;1ch?AIc>4_
zv33eksIkLHXx{~4$jD!tHya_)7-
zU%gs)B8yu;2d<#txg}{Pec#C?mQ?%)kMgzsVMyHvsYpj^k;+cNqlmpKAyy_=5CIYH
z-Ju&BqK;Zl4};RIMDYHcpK9K+m;i4ti}&UXSvEW=aE+ja5N(d{Ya
zFx*+R&f_xbq3sY9j8BI~YXxEhJ^ntj;8((ue!L9Pq#GVPkJ0C)5LxMB_;cSiMvcF7
zzY0_R;)ule;g&h~N)+7U5WlhO5t_vk9h9O*Coj6~vVG<7te|Q?y?p?tU2wxn5gO#z
z`)kJBe`~D;q|j=dKhcLdec4|h>fkRXg<3buC0
zS~iUEEY@3Na6Gik+@2?9t+Q^B!oQ9K{a1i8TqkF(XX!#cgAZyGG(!w`f?7?w|vbmM(^9
zba>>i?I0>J;EYQM^-Hp%uQdhhm*0-?*dN$KhPI@4d+{`fW0q2JwI-!p;_x19?HUYB
zzSrCsw=H3JphrayLEeOYF|n<<;7Q*)rZU5Sp;&?*Ytno{_XAjp;whp5{z`L7RMB!`PP~Q0@St@`TxGB%+Uy)K#GcpP(Gu9h0<3
z6Sd|z9Zyk56l}Tbl2yIWIr|SilB-+SzjBOMmf_o<9TnE+l(!e$5o9;x<$&2;Xg)pK
zClh6F{8Z>y=skID8Ijxs(Fsm5gJOpalbS=Qav>AV$RhLjZ#c2~;~;@^5&gq|j@T=d
zYv_8f8?H5C_#OsJyqQG=DRn&4Xd#L%inwJk!ZQFL4$|=h1+|y9MfXp;FoW03Mj<^p
z-c$4VhG0{mSG(qLC!Xyqv81$8=~1}3ro+zR9i+<{$-rz23~CMoPeAx{S8x6Lc)>;!
zY?Vqu$yxzF+bVljE&5-!;{@H_S!FzPGb$o_ll#dex|EAIaaE`y`p*21Ui@zl>)BLYfZPp^-A<
z!n;aWCGnd`;EZ?TP#|UnFtMlpm<9e+=GkQrJ%U;p4p=F
zf@V^%CEvn0UW4qa?#>#wm`6d3v;{D5Lx=DRdYtcdyMCUkAfK0rUG#kPsd$UatvSgp
z;*3IP=1(MknPqVX2h|d8Q89d!6-hyO{l{E4A5pM1$F`rWP`&hz^e3cVZmrkxW=S{h-
zNubd$a=(MSRl9B5S_O`uzmH!^g7}}w*$Xh*VqFrd7xL<9v58HMQL8l3PZ>FYSt=#E
znlS+Bd;vaJQrJLL0shev5r1kp)BD729nDKV-QfS6NBhCr6-W*Mxsq7zt0H-w(
zek~&m^Z7bJf1&$7m5ls_N-)czeZUoBQf919f)B=U^SZ*$?zdi%N)j()t2|P9C*t&>U2mTUk5L*v%<-r%J%bDHZB*3@&b^
zNV+v&nUK(vN^rdW3~oXS36VYLrQcWISo~y4EIc)c%obU<&t4C;s#zi&MiqgsxTPuT
z@RAz7T@2N*QeUB;1Rj~&0h>@wBnmcPCShe`vzoxs;F8s!=pIzm;b`)Vpy~U}_P-f_
zwKsgup%Sd9sa{oXIwvP2%vDgy*ncp-lX$u_HBb;>N?0=$JePRQ$h^*n>Buey6*&vK
z3iDnG0prOAPbbYe+;^v#Kn%o|LHe-f>>VK~LSH+C^wXTR{5-`o_-D#QmS;d*|~}E-nMeYsd!J0T5wk~hHHzhA<=U}=ln(`K#a@j^_
z(F=m&9)BaE0z@j4;IZDE%}7A^rL^*KUC8UY^XwIq7vkklVX3lwNyNU@FmZL!suM@T
z#y&Sb3H66G{UrI(i=iZPu@w`?lyUa*Ka@J_8L@HXTPeYt=Xxo}>StPTB645H(gQ?W983(Hv6m(*ZX@QWUa&XxWl$)bA5I_<{bnq^7MDj
ztbp**xhJi2z#)AwQODGIl?34{cm<=Ko&GX1;7
z2pIB5#Rqkk!H~@FW8$dc>k8#PWK!pz%2H%oOV6(Mb5s9B-I+TSCg
zdw6d!nae`)&feKK)LI0(RTDhIvKr4peUKLCUaB5CAMpv7B7?`wOeP&o>X7ii%Of*+*#LN6d-BdkF1RlSVQobtC3?#}R^MjL@gEXqxLMa6-n?ds?VOwBIXxtYGE
zPm^0q^!tX1Avg16B8&t{#9Wt4Qu|(z3bSbEKba|Ey=nSm1u(i7S;Doo+(#$3$pKHb
zGbaJp1)B>vTp)9N?R#;Lw*u^pmnEt-xluU3^P;D6!e9}%{MPjitwn>cE6}}Hm&){~
zyvnRxy%6nDaBUl~TU8##BWC^?#Qq%j4WB-7U~}df0Jp{gbB3bwHc{gn2Xy9|v%wtk
zB*gZjNWTbpk9M=aPs5+gFARNcnyY1?HV-xO`Q4?a`J?R+YQb9*yRv4$%%JC*SWc$qB4&sEC`H(Nw1`c_h4|#^bBNoVgsM
zU|BipS^H34IHTuHw$aJFCSM?*`EngADTY*hp9@cxvYf8Fm3EuP^4HKDebYp_9(|@cM($qZZAlIcCDOswUp@GY02x7Z(wqAoS`L*+9rS|?
zGrHHF42Zc?Ue#xHN``v~**KDw$n?}$q8txv@Kgx!d(Z-6XkT2pT&H+PnN}Wlqtf=>
z+|>A8eg?{S&_yVW`1?%xl<(Zxr8QSu4U!KUP{&IajJA*B|
zVPfTsivUX%k~yQ#NbILC!OiU_Yr^>y=8WA>p5AGPlOPB)sD<4AyEat2AAtU9p*!PkSSKK`ZP>u2OqE
znIE1G0>R+`WlA1+uI&>IiB+TnYCwT!JHtVH1FpN&sl$7}15|eW8B*j&Owc`_*|twM
zJkl!&{`grcdh_U>c{p&-gljg5F
z_sv${>#58wtPLgZb4+da;-?#a`eL$nFPk~^B#;7v>rnS^(MI*8+&Ngs$yRpmS^K=Zc@UQg8>EJVA
zuheq}@wVL(l+*<*173g$AY2O#36Zes!_FCNiNA8kiuU+r*pBb=dn@lRTl?G2^uqIL
zqa|)!vxji|K5pxhM{n?@!}IAMU#eQn+hYYyqIVA8*tNzjPO&M=UZ#JPi1RVdTqw6v
z5}rRh_d6(un@X^Mww_FuhBt=QUy~xDDGEldv*=#g3aw;r3C@_`=X*PE!9)6(;14}8
z!_yV;Vx;(0%scBz7O|&~G%2nWhlu$V@|njD2>u18uyx=reZu*O=g!p%P}-cPhA=?t
zmv<@L&Jq%%4HOh@w7wH=Ulo{Mp=>i~aAb}NIi!z~?`B;Td8hQ|x{Wh|9BQrR+l=)~
zt##h^I)b7Krd5@mJxW4(_Iy*IIpd)Kt4dK_=VkHWfNy)|ZZFD)x?7)b^ubTdW~AVt
zOW6*b5IxzS1A^OS_p7VCFxy!&RO*n^Il~to?Z6?Qw}y|%-`MJ+AE#afy`S^TZ$PuY
zzoqN0!=IFFDx<=rrVGLgMb#tS8LaCcHY|(0k_XS2AGna;Xf~i7-=tBQ*~Ph!{Z_0^
zQxooPPFxhe$0sd+`}w@;c9;?#_Bo<5sJ$l0MRodz8$|?*OU*UA@
zsE$GCX^{*VQj*U?c5#9|o3n@Ul4Px0o>9VW#k}yb^WLCwIqzxKOWV#DRlo&on;}=d
z1WpwEU7PdL{D!FRxqkiSjz=;Y4Qb5E*{$HX$wZIXn0$t0P}d(Zp#J++b!WNr$pH;Y
zBVf~RiEp`X!`Rq$ROA_Q8;alJ07immOP_2GABz>n+jg^#L4)8mlXtFO40oqg&=F@e
zkJp%XE)*w?A^&=Az$bkVAm)YVX?%e9y_T3!i|~7XqR&RRv0DDvq9Urr&$!)oG5=)ZXD`yU|+M-XvOc2j+a^%TBR(k@XvdDX01#p9HcK{sa
zs_dITSuv{p$_hJoReP{(AJiakleh+B9eggACf^%XoL!pb-`9o>)MsMHL
z*MA~us$m=B7dojQY^)fI<4i&O5kA%?EBHnm(s?zkGYRaUCZ(At9(DHGd);k$<@WYT
zQHA`;zui)?akc!J&))Lc1`rn~-G5aFEsEexRsF^v4@0zsTXo2je=}%Kgu=1z^b9hl
z%VfRt#c$w**W!Z!*C8Rq>F29Mbik4!m)p{{^+^l4Mis~a^R04{N4RaAFkQ}T`|N59
zZiaH7ggPh40lmmmbm8bg`#)a)`z+&7m6Mo$IyWwdn__
zBzYJ7Xzvy8PAf%T0}}F>v|ih)?z!k1#$RGCO~i))#GEnN^#?Q
zQnNxlgZx;6pHoTDG9Ww0r`4)B>E?+1MGUt{ONg7?n=ela!sX?BoC7IKr?gkDP#-ZY
zZRtG``DtBCm~Ia}PnCT9r+=)gz$jumLH#F6*Q?_vQc!s$wiiJ(z12<#78So_mtKW)
z^i3Mqen=9v%X0pkh`g&{II?@Hl~eiP8vWV?0x0XSp*~}3YTT9Td8rvetCVh@3$f%r
zwDWtL+F?BXemMM}6Nsg=ZS=!>^5fbiV`_(NmZgMt{wZRB%PELyczB**RUC
zj1_u6TS(xdIPXl-mqtVM-HuF&tcI);Q=^#g1HyXs9uIK-)30k
z@FiQ`=VL$elrHXr5-s)$`?UxQ3<5Zc%!E7Fm>PkSRfYmD
z=z$6y5LEf3q`z_^@u)&W>jOS{C>{~=kw|KrHH_I;T_-+t{<<{Zu;b=*K#VF4K0vHhSa(lG;_Az2I2L7O*?QVEk3fQQ^5x$e_|=HO;=HTwjy6KTF$x4a
zZzP2<3ns*`EQj0MIhD|q21jOrXw^Flng?s#qUG`Zz#gw}kT;ybKChfp3zqrh>O(Qb
zsSmp}(+aL8`-#$geu0pJmH?Ay%$oNr<#_K^94fE9o?J$hp9ozktVjka$jDpE?5P72
zcyyOaB(;FHW3#6LJSsTvGzP*67OU8ahu>A2cxNuKV(`A+MXan~J(E^LM_sz#@#Phw
zd)+t=#&TfC{F;q@((@G)aN5;>`>mQOm-+SkL5{_VrZ=|ceU;+yZt=xnrUzHi0A}!!
z_2Vrbyns-=Gl;^08@1H{79%2&Qq4qO5Q-c%(WT*vC32QzwC2Q3-zLs@tHmdsqcd#V
zy!3u2n2mn0<#yKP>aD+c&na#5rwy#iMdclL>#C
zln1T-IiYpbls42K%5{c8hND()TFPF9exGjXjp164Zy4=z#uemO5VZU2rbV5fu;~qq
z`9xDp;msw
zG9uF^&htH=7etGiOAyB0Ku?28s9lTGcR~LLPUxrpaKpZ()Yw^gZj4Qu<4$Q0%k_rS
z7z4v8%}PS+3|?Md|S2t8zu*_*9=%%i+b>CHOmZ234lCmd7R
zUDnR0uJ=ps@3HExPa6O@icXrl3Drbp;jm-5J~rk>G)x2n11t|;Ue}=M?quEzY(!V?
z%0@XWNoi&in0^S0
zbJSOXPaF3|FqfL1mAzWTAd6S
z^M=^{7*+g3FC;Iy!$~`bAk)>y)*F1+bO)$
zeILWq=1PIc=5OB
z&cEp~?EqN~9dP)Mi$s~8=#;T_)5j{fvqtAHJH75P^sJ@iO6Kg;S>ZIAbryT-K)QRt
z$wn)BvVr=gWCM+agD~y}jciRhNLMxNLZ}tm2C=6|ynvqh9ej;@8;A9@c%L3WlI7zb
zVRxF3B&JYsnvNH|j0rX4@?m7b5J~B$Cxlk15B`M59TGfyH&{g7cx2KuPO%}hXKu;o
z({%1nf+ul?uii*-68I|PwUl~l7}<)m_tA`%Nq^a^8z4Y9A&YCZ<)KS;`B->$X~O1J
zjjNI6;GB&y<(qDrAQ56~ciY|Nloe8nhj3pUSsx0uAJsSIY>Zke#SDgh9vWFV66QrN
zSrUSY$-1P_dVzS2)=9>
z6puAKF8lbI7lxV6(=y^y&UPC(yEH%gENw`inKN&Jx+VG^ZpJ8jrc^ta=dLR8G}vYN
zCH;59_$H4jr`XX*^)}sv2%;>U#_ATvGk81CR)M=ba0tOcB@&?eW^QrV=>|ggSKhV!
zqH?j-roKWgfowAhlAGHbH?X(}X79MaqIK$4I^%+f%yK%YVb1T1V0eAyM7oreAYu`q
zs7vR@Q@JeSkSe{K9bTo0uUrlBu`T8j(7>(mutdn$;k#H9l*%WLzE3ix_-9=Mf}GZ-
z*NN&m5|DQ*S$uZsmJt`;K88IP>{-)?*InCXe2+g<$*I?o2ab1eBG(H3C-)tFGzpAf
zaAThWFBNpOZm-&g
zW66_=9w9mdQod7Bc*axcnT!;Mn{UQ1+JI98#528!BVkXF)=i@{*RR53VVVcxYuj#s
zga{t}MFs&;IA;BTl&S@uMy1UYUQH8aqaxlD9B5A>0u1p-%LwzQt#cZ?m|%P)F|M|Nw_=u?=Z^W
zfkv~oa@;RZidy-gWkc9phBMUOetBsKRZ~xtbsNfaq^W6lHp%cNmm#<-#5i?foh
z8a@cXN{?2A2YBS2Pew<i
z{8Aar;Zgx9Clxyfb_-2!b%1ZmzN=r=F8jn0OWz+RfLZb-7?Kr3yGBA;TH&kIixc*7
z{i5zJakU-IRs+sExutHiibaEls(1!|1=C=Gwp9{xdG(8-GFc5B32N%eXp#!38;QftHLqQH5c0NXr)vpP?eA@gITBg6qYX1%Gkj
z+kS9=qJ#7cX-gee;tp{HO%}~gg
zU3YkqQJ-`8t!`}ZbD(IYzT84S^aXn78PFJC^-V2f
zZAAwXOQS?qWH!dJ!v{t{rvHwvgGM}V>344?m(jFUufDN`sG~2TlB8QjUfl)2?~C;H
zIBB?RIkV?juu4)bJq3`6ct5_^z3LWoCw80rjbo*}C{Coo?TFLM?+W=2QyhaMMZvqj
zvP_%>PfpsU8%iuPYtyiGtsFCeA|No;s}qpQX6qGOnX%M0rf(H0`iw={dYhHik}2G?
z@L^g~8^5sP^)I7ch>1M*fSAj2`(Kbd+ex~v1&!Dt53R@4Js*%f+s0gW6nf~ZGlquI
z!mE*FU2KnolkMSj?KU})CBe5E03vp=Si_7vtQKs)Lung?R0kDh<5UQcLS4+iP|=AC
zO&T>Orf{LaNj`{Xoeo92qANR9dS_L}eb9Y1dkD(G@!a92YX9}dZda=e^=%x5AsoT^
zIuIe6RBO{sLbj7jDiXxDGu|yF(PT~N^k|;?Vnxoai#CU#>q%?0{H&D^RatSvPKAG6
z197c^&X=qg-`=j7h4ILv6R2Y7g{#NMTyh^}lg5hVSoqzKe*PvdN|ROT$L|XyL6jqt
zlavCcn~Ef}OoyMs%C+LqWP@{v4DyVc#p1v+bW?7#4acb?QLb&1F!a6N`Eem6rR~4=
zq52|pF*4H0nwZ{h(%Ggs@{ayU8i0?VW~Boh!|9D_SK{KA*%
zQ!f)EVXBn_Rga85x)H-Vb(R;DXn9Fn-?2LZz&)zwc0q0{YcOio8(~Q!J0-RSpLDf+
z4Y4@O&p?CPCH9t;G48{8d-oXrtRX77op|*d+sws6B~;fIjZ{#&I*#+kLYVxNj|C8d4^qvz2*-rNd~y-}<#;{yX&i0{
z@_WL
z$d0;9)fKk?3my0rZV_TP?P
zduXQlIUoal@uGMX;{XG6>+7S}z*PUqz^M60i_tj7*P8be)Q~z1fdb+l$=jBuFsCWG
z2xX9AeBRmB-T%x8=Jk>Z`ysYX8yojRfotLuscHWp%XzCDV;~88Z>8^^q+CW|;?8NM
ze?Z9uw%l`RHwwd;Iw*7An)xNl3ud51HNpE(yt6prZ(8`>^zq(Aus6u@pF>*pNq~h~XmQ5_yBy0UHG-bGdr#p{q4fa)OVSZh-K3-9hbB
zEd@cNV?0I@KY?Qrm0h!o!(@5@QF9$^l`rk-jpGqr!I_p3GYdZUrqeIX$B15acGmRh
zaQ;rw=X&alnPDS!#sRGI5oB)hyF&DiO3Ltma=?_jae(8xC7p?Qf|+;qIr-2@3jzM5
z_d|E`scp(cA;LuKny3&^ue1(3D?A$W+YnyMSiwJK7=?xUD9PnL>X*hV!!hWP&i8ek
zN|K+h|A>KgK%}{iF{^vG-Ib!=>tv$2tJ#p7Qo;J;)(Pk`5!;fyb@l^GLpiTkYPzdk
z;Sm&0{kp?#R0L8`()FLo9x7T0*;h66F^+ddp(STsJ8pOQzpKV*(buK#GA4sf-XNx9
zv&BxNxCH&vH%L(X-MM~4YMYNMf8^^-s!I03zQjzo{5Sc=_gAFlk;-A-rd_i`*3wwp
zvq#B}O=m0WC#vdvga$BBgl4VlZ8=9sDNi@+Y;oM;&%P22pYaw_7{KIW-AP&uh90Oq
z6;CdX7d$*QEM5GNA3FxhYI=V7KF!x^Ejb4aCA;cVJ(dJ5fqqF)O<=x3*xX?%p(^^`
zZkxLMtvQKz#|D?4!~F}wLp0vqe@U`WVxXZ1DOuUD*d-};#LcD43yp~R2bQPwn>9wf
z#8=stL^q@D+_K~nhFZp4f6B=j9Ff5!Ja!pksnWyI``uc(MaM(e4>g7xVw(@
zIq@s(?qI;wF#3|;N~@hQ+uxD6?or&te<26TC7sBFyj_-%o!UnS_6dJakaX4lBVNOu
zQ0<
z9p{uQN$4r?eGmztKzjJdB~#THrZVP@7&@;ZLm_;HjTwOht_+f+>|fl=~7;u
zd``iA&2P?)k2@u}bA
z2P)iya00CgT|OC%hC80`m`Aq{e-DpNh2=pH=eHdxmHwe2ZO#OAqto>ChH1X~y=AyM
zB8%rkWo_wWHjFAnA8X8jVf-H1qomD8tNF)YsbVyvyLCs)nbg1V(CNa&!wO`C0X^_Y
zMt45~4XItJ>sPwQg#98fR@gw?8v%ul@r`#ZX}(PaB&7u|@7ga2j4j9~4@<#h*i2sj
z6%fZU5C@vmQ3seq9)SsaI__=tB4;7m+$-}-zkP1`w2}qSa_2h@RF>nSb5*0v(qxHy
zF1cvc`6r+Is=X6c01ihQL`p^d)whgfr*Fjhd>cs_tAI&G2;_L*B%)%@`me(inaGv}
z(%zXmz|o0}QVl$(P5D3)DbOw74YuWQ9kaY6s4!G&5(Y)*BKpLodKrxwWcVB7Y3xMF
zj86|9gwj-E+1t4t{xSY*R%eW)0&N=EpHvB-KX~FPq%lp{;lT4)R}pcCZnl9bI2)8D
zfD~^FO4bY0HtyVO3FL6Ju(Cs4->94D+W=HqhYDi4ywOCe~d
znQe86^r~IqmKZ5VUI8s^P_i@izDB~+(MOaC+w?mU%idT2A}G*KGLVwKPS~PBgZ4Kd
zhcnV^e#h6$;p`&Q9FNFr_*!1XdRn-ksrI!
zj$KcVEA6g*oqY|$D2#USX#B}j{QH9dI_3Td^-LVPDJA6>c;GkG*q9iJ++rj)@B{IG
zHTJr<#HajYhuHoBM7aNJW3Q8)i=(kAos+A1iZZYK5Ch`&I~sXYzku;6H-%xoLMjpX
z@E|%eJ0mFfKP>E<*SyWrk`z3(>+$`4$E%D4zZZMW+tram!b-;P+T)O8cGRHM`S3ki
z2>}UIOfjpKU|JrkS%;-&9j_M@-)^~-0F}Z3LdT7?vz9g{
zrlVS^+(~e{9{4UO)@>ZFRReCT8*l8)QHHcxNrCUV)2{SuZ!b)LTl}I
z;x|hne3s_r&B13)$JXMJkEK?>C=WPcu``xp_?IcJkWiW>kfAl{pXUL^9is+`o7>XS
z6jk*UAHim=sgLrn+F+h*`G>REcI3_r4wV()MimR9;T)?|Q)(9@9>q+Pa_3k^!=_+S
zsNw~-F(ebhQO=_8X?Yu{=->9OqiJ*{=!pHn(_4ROGUc1<6L1Y;AD(Y@uck}Nl(0q$
ztRwVMm>T?UA70nCzTw!-`Tx_fVlqcl5&kF1{rC9a4J&4*|A%2k@bBpp{EuPfpZZ(|;(w5Vq>Omaw8Y4H#-L^dismJ&M9mNRJ%VcJFqLgbWV
zPBA%U4ym4MI$%s8^%NpZO3Wb(Nq$><%CFV$cRk;~?mzDL`~CUc_xHZ;@AtZ|>vjJZ
z!-|&xl$~|`005%pJciW)@$voQe%O7hzu>#y?K&etNwJ8;LRR^_j5L9O1}O+|O(MiU
zy1_&&MqOEqNF
zDd=0D;$Xv(@c#M7#Nb2ZrBKOUG-*Y8WY4XRW+oM;s0gMxE4wr%Y|XEbG)S*hdrgJYbl5#e(bW@ZguWV&YsGsPdKdcayVSvkU=lJOdZph{e$
ztFm5RiZdTJez#RLt+4W>a7ZX)IL2m3PW7RU82eTS=me%JUi1)Mm5RcfWLN3A)y{U>
zAw?YEpGr>CsM}81T4fekaG<4#iV+ZXY_D6bh<8cDoiU#xl>*f_)}^N6qq0+tHF=v(
z6Rwzxw3Q`BJ3$Gs>eMr(wF;)KQM%Bx8x36!SmT=zHTyBRrdF%!SmA-Jwy6!e94M-B
zNQ0Cb*ASKNi8vh&iiZ)My^2k7=jhKd(z#h$*@kwN6@5AD+$l*E&N`BkbCo@Eu+mGV
zMD~&UHes1@lTVuoA0wNaX5Eo#@q)c|}C^?Bz
zUZv=CDgQuk4%#N=lFU|*MHMEhR`S$*W$TW@;iuCOXIl@As?N+++CXD7vY4RIa}#{y
zj`)VtcU~{%$X!&rxWXdff=;g%F^Da8MU_|v59|3XGnWZEZe!erCf`vq|0u;Om!r_O
zh&HewqGIGZe9OAb*~U9kK&FIm|gXWXLn&E
z9HTlZ*`t<}r5V3nbot2ycYNp0_uklCka4}a&MfHf{M?!CvhdE!&n(VOMz9e^=gagm
z8&eNGE090N(&c{XtdE#Upn4+xM#GzO4}}a4slDBPwD42~?w7%TH~VeteDpScRP3^}oruy0Z>XtDDL+Yg
z*)p^(O~IGlEA%v|%;I3ClviI_KhjIn>c*IP->vz#*f-$VC_AcAplDBDs7uyKos
zx;v%D_t`1);n&(}I}LZ}he@c!NgF#|m-p2s>6P9!`SSv{tSvj*ZNZu&wH1G39dT-~
zF0fwdZj7AcgAV24Zo(qL9_+q$3(8vibL|LmlGb)5?DdzlDzz^%G>D!+IWwUQej^7S$c(*=a2o|Ol2fewTQEi6OeTE8ckD{;{F>>j|IQX`>FbQ|xh-Zn9&wOwwz#>um?cy5I
z50~yAg`7N`P*g9Tm*J+d&lUe75Dmv-#F?|;_F$%eTaFrayTiEF9;Gj^j_b)zP>&;y
zI>b+nP51k1nqvkI
z#T_2#+N3Tt;M+auU{r}#pPt6d$9b#k52vhI$S+yQ`75VfO<^~h-W3eZzn3)!t1S&Y
zicmx;qS8{%Nsd10Glv}}=ar-I0A1
zT=t-vf|haACciRM<+bK%SxRfQgH&5))3QFXcXJG6&MTVf8?uyfJ*3bVYq5|1Fv1*Q
z5U+|j`k>pj_RQx9&z-QTvWb6hc`ObG(-}A_l{5F2G5qNEdAL?X?@U%*!;#3PKd%Ai
zs{w-ys5qtB5{Y{v*&43NxIm4aFIX7E`KGYs3$9OOJvI9Leirr0k#vx#$+5QWvJK;q
zlY=x^wc+{N(i?yVU2Rhw)3ROC8~sQuV=R+0I<%3_G+Side%E=E`}ru)vlSiPra{Np
zEuOhX#@tX?(_}Z8JBxUwTTgLPk!g1t8Su`JuXq|S7xtQI4522m)cySQXD5~}pWhM#
z+w8!>v^1|&4si*1oG>AMS4&+pSHnnH)?~>hp=uq*)?Qw?LiIk)=^X%%lFwpHrOUow
z+6De1YUqT#xP3)i5bp)H3`h|IDGC3YKVeUEYJt~}u~
zv=x9vNAAV}0J=j6kmaj*AV{E)toftR!}l02gi8zN8~i$%$Drg7UUCuF*5A)R(Eq2<
z2y0WFX6}gyZW81l1wXXqyM~|VPVn&-EZJg0JabwM0M^3+K>7zY9se!y-&D)B_-F8{
z?ehZwE~A!!^CkRL@8#r!^UxCjP;CVgs8_^)S@mP)@+B7h^A#_Y-z{cfS^dlZU#H0Q42e0!U?t1Gx`}coOD<1uKSp;yti+BVc9t-%#i6uw_{w6LY
zYY9sE2%oQPV8N;dv8c-~?sEbKe0AYNQUz-f1PCp=M1h6A_0DgDUke{6^plOic7xKds&2(j~5PW*MVtu^@T69(Z@
z6aWAK2mlY3r(6IKiGxgK002nQ0RR&K003fPV{2z}Z*^{DFKKRMWq2-XbM3wTUmHh~
zIQ)D5im}djJFcM6tE;Q4tE;N3s~giYPs(ai^s2_@7iro|w!Ta5zetkx^`xBi*2}AGlK0oM
zX?3;M8x1dt%XU>l@ohFq`uRmR9aK9|wo66H7Bx+hY+M}XbrZlZ*Z{
zRVN>2=Y#xtev2I+WW#*WNiMQMnRD@AbXkq|hW+sfdJw(C_hPsPn8kZ8d!un)c9N3@
z{5vfAjaJeaPevETAjdyP7Z-zKn0K>YFE2~{;*6#<$+Ldr6d=tu;XfDCVXrDi!vsHD
z`lO@Vd@?Eed5M&oH5Ijhu4R=B^AD9r#w2OC+X0nZw#>kzPt7lv;GC=3=lfB7gG)Wsc)d^3vOUtAvVLX4G7QhgVCigXq_DHk1T2Itul^zU(
zt=f-iSl`&kj1>Z<%3Yn`0xIu&BFbDI?dlm%{Q
zAkilK!;4YJU=K3m2C8;wIUWJO3@>+a)Mo4rDsMDfrok|~$>-F^Vp+YMp3kWbrLr<2
zxB$Mc(rBtyvzl40gK(YSx#HzE8%%SMEL>r`eF8O3H|1PccjJ6?p(}1}0p0|-k!-7v
zo#b{@^phuxmIL%yO-6%3K8dagCCXHlbTr1Y(nYtYC7~*9s}H~ho=k0SMj5ue8}^dR
zyxOsxn>GbUsQMZ_;=Ma4fPdRwqh26!RF6P|R?wSSRawzZ-@CMi0ryj+9K-;
zpTmSTH6}1p?(XQi7y}~fkCH!ky9e(M_qyHW(Ry-pcXK`(qz$KD!!+-j?>Gn^cME}z
z^GQojMGMAsl;^_;c-+r_&a>;+*%&u_rKKjirO=uBc|P{`%_^G!%ff~*lgbmf^i?Ou
zpna8<3QM6{DBf080Hm(s=qg-Vno={oHshgc^J2SK$R#r??6|z25ArJa+RCOtyq(D;
zyF-Fz_y>`N{%S*6ngW0u;A)3in2~JJwwM|HwRT>bum$LrmSThi$}If1mS`H=7|AY1
zlO*Lq;l9-3#c-Mc4>D$L=y6iykts2x0O<^BGSGr?Pc0l6hU}7&7A>~6T;}#fcU26h
zxhoIA%77U=0iJw`y}-XeaYy$_c{Q32`iFUMIw^6#Ma_if_I`HC$Z@w47ly+Uq1y$k
zqZ)O)jb+fl)|x?(?{Oi!7{CW_>NU1a*@6BDD7w>WY6GX3DYPFul6@>4>iEaUpP5<_
z66vEsMAUJ+09+f(_Fp4a^f=Yl=~Rx|4aXp-*>*Ss(FwI+x6X!%27fuKl3&gq-t+I-
zFK0>m@LtJw^{sgpGbp-?QLWu*dY}ysdRdwKTg|(JgT2GuoufSznkT=E?_W)4r|VNK
zcVE5z*()A6#d|x?_uu@`-Q79ZKi+wTmHtNqNw**9Kbz~9rpf;Ey*J1EFZTBiv3818
zb_V0CYzBY4nRQQpd)Tz_kM<6B4tI{<9v)Hu-S#hQ$?4;Dzk8<|P66*)Y2$wy$zuVe
zEi^C}e0S%~^R9!M022TJpti3125R@^)NWXB-o5^QZvouKFTeC3H$xg!b1FqX*bti_N~5BDm6g@*RW>1L
z&;f0Mn~@3xqpreAl@1hweYYaXbE=KJ3T00=)t}!cJnHr!A6`~h>ht5rzCiB*@C+6n
zV!$mT0d|0!tv_K@#ZuJPgj-0O*Gk!Jcex@n9?N!x1>EBC(c)7F3sKU>XXv-z7V!1*#Dyt+I*-6q{uyZ)ofA1}lE{jt_w%aTl`qMMJZcvJ
z5K{;RS?__Y_c>W5-dzN(DEd*fX5n_o^JO-4M@~i<14U*r98W7pVhSnf?Pcu&3~S#A
zAlWm4X;1R;AnWBjgF)&wZJ~Zx^{&`z6Qks>O&8};SshG9=rM3mG&B?_*6vp^WaB%~
zD#MCH(4&L>C97bHhM<02T!6hoh@LdM=-ysyoVJT$Z!qnH*3E!%PIo|cp}Mf%2#6Bo
zP1XrGKZ;@!t6CxeVqI9-eROPG6vT4hIlx4bodfG#(wnQEgP8u8Dn*T|xNa^G
zOs?)rb(#xQ#D-B3tE*grtwzato}4M+^_$*?PS0FFb7;Gcv$B`b7(5Gh-oo&z)|*(rtlRGMnFXNun=W{HI=eOc&mLvu4^=8YN{Y8ThZ;pvE&7#egrO-$rs>a
zD@JjN67#8;WhfWwFzwtvCj=z72Ak(LwfqX>a#kvVBw1jI#~;I4yvj;RI_4MLMd}*k
zAY`MEi35c@vUPaMwi(l$rRMUj!`Di{rJ+d!(p0Yu-DH`*fTHt?qkCaJy``tX&RR&g
zU=p?1f6_!vi$Af7^)zPVirp}_71r9ff1MV+>$SmT>f5*fi3P6?-|^W6?6LWWDj)XC
z-+WH`M!2PNr}yx-7yEDakN?|gKN{}c7QBO781|!6x0m&<
z@*3|jd4^rcgZ}PH4Z0-{_laa|;MC){&);^Ecd#bMlj0T#r&#eOudYVGitn#-?VrL8
z{|zuUFmUqp>o!5?<~K#9$5W;>hz(aHD<<#>f-;f{G?=&EO
zYU;Q7JRzpJciAbuf5E4~ecLEH9D2Il_lNPkxxypu8><6XRprElF*s`o6&84JUYyK
zU`NGf-|0TK4AdC&s)qQFy6U86r-VNGAPvRAtB_7KdJx@)|)RJmRNN7zq=wI^gZ09WSM>8{#!?e-bc{j6Gpeh*kU7_MfgfDS$7YZ
zKQqqK7j^yRzls3x6f1|Bm&3tS57DrKV9q93Lr88{v-%|0)C%!9;axd~=Z{7kle*c=
zQ-^undSljc2{oFh`i!bbojwO!gx$Z%Gek{fywH+d5tGr9kUUQDfd^rUWI4fizj~tU
zUeipGVOF=*V>>D0G}@~$y8`uK4*x`!z(;cRvYiFIzO=HVH}sF80b^xV0wMZ7X}D3i
z!44}IkJ#SkYiGT>-B5_oxFWE&HixOA8!ehm3Z&yG8RXd{jp{P0C~Emc3!_%fB*(9K
zgzu^~Y$~hIC=T?Wzqe^@WiuM{C+&7y=~01xVa^1($s|WPyE~c=E45vg+84H_v6mAl
z>woJT)k4$KniWBuqp~g3$h>Kg7}g3eAJOkzMB_>(LpDcdqJ1-J0{J6xMy%k}09j2Z
zt<#ljybsQ#DLoU`N*PxzDY8{7Rgy@o%|K~P7(Algpbn&rNQ#54wYVOgaAaH?s5r^0
z(d2Xqjrf17Dkuyh&e%!Kq4
zPcgCENS#J#G@(*#`!b4CS2*(aA~8BZF_2zu-hg~(<>FbF{aG(l$lYoXue0i^eNzmj
z59+Z4q~$uK)4N1GX7W;Q&{KPRv3u8d=F`I*J*%Xiofyu0e;w+RmAo
zAV#SO>r=UuJPycso#bi$m8h))Z8tvp4#e+#p`n^&!xGr_Mnvtnr-#lgn8@Lc;JjRh
z-#A7aNBFB+`3H)oF%cd1=zPl!;3%un_yCrDsXtI;_tq)_A#(%lG$_W@zjnY#8yt@E
zN=-TZm732^dE2ra8Hs2F?a63;SZz2RIFK?}o<5pi6^cm;yj>a+wW_zh!is
zP51%bJ4D2exj#J;l>&^-g=&ek`RL;P4oV|LH=hlr_RC4*K;=Uq>~wO3&7j&IU8bf=
ze6KpJa&R>oYB=;~SY@Z*pO~r2)Q_+lUuuGlJ>!}^`rYm0hp_fO1&~&t*KzH_{thc2
zjt08kg#HYxymjWon>D()9+|Rw5TeIl`Ii-*neW6Ur
zmWxTAgFVJfa$*{{6_1=^CJnm5j(IeS9taWo(_Cyy4SV;3h;F;oK4Tk}!raRyBTUhv!=?$A&UXP<|xjSC2
z*@H?Q)gGs%7+#D%VwUGjJR`F^OWuzr*BK>ZXzS*A342_%)-OuTl(B|6P1bPN
zgUxyk=uMe_^8Q+RH>|P`)X1PQy4h3y1NBL{$j!i%R?(YICfaH}QHqHArmYpUsvSXc
zqAGye0YxtRnX*%AecHq%7|p1`9aSAAt$C!wQxB64ifP4;0;h{g{HPGKbDaKa8qsraB_#8AeGr}z{@n;u>Kv-2}cOb2p!#T99p)^f-c1Un2XIvQ_6aNnC1mNd`TxL~x4OnT`mDR6Uy)oLac7i7AOU)dS*yNg|lSOJ^mK0Tk
z{tRk}Vbo3W5RV#Zk-j#|tFRwYd`1AvZPM6OQZI?E-xtNCtd4rHXDOU6@I$xcFA?t3
zH@Kt%9$!|^X-bbMy$jb?lZ;tfxkQVc$$zd)J_-kzJwANn6*>#TIJ?x1v(IPL=>7mT*
zrXG)I9C(`rjq2d-(Q!j-gjadi2edj;J!`vanXY<1>fd$bQ1pRL%GuGhvruQAay)7E
zBXDo=$~7VP3%eW$fpQ)@&s{JUq@{Q(896eyrIO!~SDyRZ{QEDLLl1ZR>r)u{Fog5D
zd6@3JIRst`>RWG4JP>{lJZ0PZGVC%vkQ$&TTiu>b8qIkNP?GB(dm+}2L@&tYcD7N`
z@9C7ZW@iI4w}(kl@A!x)X;8KG_WOJ=Si2sM-Vc=vTD6=`GNX4JDexAWm`to{@#kVC
z%jNHm(Vqz2YWe+olHUSJ?11>U#RGq{QEKPc6FNSM7M)mQW{wzZEX^3q7BP9GIqxKp
zKc^jwc2J49;O&3R+h-;4gt>pZE=2
zkB9@$IU1b~3!uJf7K@C;b5-<@xP7#ez}rTy5*Ja9=GTY27byL-;1sssmJ{M{Xxe<7Ls
z0YY()ZKaMoyZ>cA#Nf=FjSW!I5U=~halFJ9T%ZRVx`1>?^GyqRyF-;Ng;FcIu(p#-
zdjU(%{=iH(jx~qptjZ#9DNi6{4I7m(fAC&IHOUT?(xOs%1dPw==>mSAP6lEj&r>-*
za)}Go__X7YF@z_{ia;GQ&#%th={Mr9VNpRF;uE$V5noCH!TXn574g;s1qnDE*o73C={j}A1L5mIhAmeE{>pN*h2X=M
ze7+j^=gtZ_dw4HFwRzv0b-d4fm3!tU@e`44#=0F{*mcdacs1;nP+*0SSPk|IDP1HK
z)q_a+R4&
z2=TjAbflN)R5q8fE_1MqL<&c;Zov|WZfmpchxakyR`23as@3#{(X_IPgWP4`PAjv`
z0`lsJEVjpvV_xM?+q35HRz@`AG)8-0jcKB8@tSePG#Hq%kV2n*y6_Bc4G-ZwKjAx-
zPT$%fI>El3Eb%-*z4Z|`yLau3`^0f>b&|91VRRrSfMab3vok(-tFZveVgUBvRW|Ie
zLkkoJ*}$3ubV9q%A-C3O%==S5>&p`-l`?AOT0`frr=QR%6ihg|iRpPbs$M|NJ2yo3
z`_X8SXTwx4<&W(VmPNn790DAGYyQtaE+WYkH*9GS&i6Tu8q<
zlt}7hhoQaiGP^qJQw664v~&xjhtv9Kw+dH?@^jC{6mX+lbc-8
zCN&abJO+lB)UX3!~(Y)+s
z<2>ckcZd7CU}S(^HLL_M8)mJTe9lCrPCuGY7|(vL@O0~hxDE~AJrC8o``_>k75_ecD<9MzIS8Rcqy8O<|8L^Gm!p5_Ow#PW}@WDJ}G0
z)d*Ez-Cn8ez@F_AHsp%_^lp6VW+1=ypCljKOXtf!u^6AWb95G`l)aYyx$uVp=-w&A
zp|r;%=NfZeKf3m`yh>GHG0hIfmps;$&EOr+6f2XO*tpnXV#yPT7Z5O%lF6?0+*D7E
zu4<}zZCZ({u)HTVo17P5luYi{coUTy@{TUEZ+u|joV@abzk?e;^wB4gSUo?>}?P3T!IQ%NI3PZj2`6mpcoMNi~D#4He-1sr2>;7|gL@T#=2!%@p
z9KVIW)rQe2DvXHT@NF5l(uJ*;vgPJ|1a=Hv>xMA1`-v$o2`$|e%i4>3;#i{#j15HS
zM685<>T$}>7Q+KYHXLnEixet9Wb=`#{iUQ7kyfzS(}D+q
z1mar3fkBYU#(n$@8>s=w%+OZzrwSlH%k0vv;|T2l^%ZAAb+Ca6^QQ7zH&2Q#UTz);
z1l`@5mU;b5NOWTpf~TVHSVHWHJzLDBBHGbQTazm&^zUX+A{y#S;!|`01~(V+C3h3O
z@Yg_W*ga*OO>loK9B)!OMdy#F<(#yVzoM_lD2WXU(KxS0SyOXg&MWJC!1#>Ms{j9i{H1Dt|6OXOJ;Uv8?BI$)+E%sYSvY
zrXGDmqRWvvCnlPUgjXVUz|mDlsLb$AcJ%j~|z-FN8rfF?>-kRP6h)-3BT}gjPy$&Y_JLXZN7zoRWMj
zDM%TKnFU&eFE7H1zKroSmrB{^=swjbclqVE&S+*Y1r!w@qo(k)2j-H*u`h+2&!SUY~OJcdnyhP7F!}
zLkdWWAXVj<2z8sfs-0W5niS_#t~ruiyi5FfrMUq7X%hX{svz+g2=*np$mshAP@;aTas`cKJUn}~KbICcqRnc8M?V=p`)o2L^VjDBu@bK5
z0D>!Bg5r7s^XsV0*ZW0Tt)IhuLT~Gn=@9*z>+kb(c5I2DSpBKn&o46e+4BeMk70)w
zUz9SLM39w5f+bUDNt96bolh?=U`r(tXfa|cPgDfQasHv=gAtX?)^d=n@;vvdyx#e*
z?*5zOXDHt{l1Gn{XC#ts)|Jr^lyW@7U@W{>=v97FRfdM`w3nwiNtpXa#Vc_n3Vcf*
zt4}RhtCB6Cy^cgFhSfJ5(puVNZ8}5Yli-kqdq!d5;g{eCN_WErt)wt(twouMi}%WP^Xc
zO`Ll0Nj@q{pic^P%cyF2(1T{(PL)Q3Zm5Ohhv9)HTk=%&-prpGP_iY{fRR5y6^K=0
z2WK&~?G;;l;>OGCrz@+!%c>k77P`E8J}uc%*pt2^5v!oromV=;&1nrKd*kqKfhe7(gJsWj
z3?4z7+KJ3T7eexLex6_-M|t&`WE2eP&D-wlo#Wjf@xj`cd;c9Hhcm+EAZX&eo(`&F
zJjexr@}p^Vqk!=%<9N`H=}rGALcMUjU))t)ohqZqwngI)=qrXF4`8qu4)A4f2C
z^MYd8`Uyb#eAGDJf4%qi-EnOA3hVi8)NX+HfHJgneiFx{pSZP`8fGHTTtDyTe$+kM
z|KZKfF<#^T35=>2`@0bXL+&?oM!GWWr7UB**25k>%$)2VCQOG@iu_MGE_6H@VS4dK
zHn<#3it6fyOj2V5h?o`O5VqdH{wQagzGRh-C}#C4eB`c79^PXwGxH48!+Y#Q-LRZV
zLo{s#M)}E^P&IVukLto00;nR^&Q{&P=DeNDN6rbiYeByfYSP
zhtDP8Q2^KU;=d8C$6LwSXh?T~AKt5K9LwEG8qFEzkAVUNGi#e<^y2odivx18gGEgj
zCr?gi3|aktdK!Wcp~&W%OhfcaHcPstr~md20H($L@J642j>
z)y1&%k*ARu$WuaUG=6-&v)gDkO#?kfBLY>8O>frCk=B-#4ggolg$*kgWTUKCP3c;l
zD{&m0+9ZEAoe`*Zco=8+zaHbWqaSzH9^UJkv$K{I-4yU4;Ge^)zV_#t$$1zd`(cFa
zhpUtQ@M!1gXlL!<0Od5I4H?gb&Kq5IkXv(mAFAS
zn#&EQ(sJaB@a|rOclTE3-Mw9$nfbVKl{tJHs%*9V8qO!T`V=N!1_TtC|aRH=((?D0rINygsb*rhW_M%~RbBm~Q6Q=(dMe46$rz4&zy)4#7C6M$@POSZx+kc#O~dB9JDHFuREz(BRbKXyD@2
zMsg#zPByh$!O#~|LV@&5N$;**SYAhGFUiX|A-@@rU~oCJ2DQQ9tQLdS;zo*+C^INz
zZbR`=QcH&xS))?K9(fNcn%9Y@u}fW0ce@>X1(2Bxz;TFV!_bs+H{5Xst`jRx8}Ym!
zHFB`*!Z(y6&JEe;>RZBhrd8IHAWTLlliJdGQR*e2sw(Br6S@~2et)`u$oQ1u_ooj)#X@__V
zAfDENXz&Ygs)qM&T6kwr_D9IJvwmN+pCd3d!NmmWnaK#W_Xoj(Y|upe-w%#tHU%BeOUO>kS1OLuSG}d=P>kxf
zaN?SwSGV-rWaG(~-ztDd{FN8il9~8Y$
z0zMrAzZJv0AA^6C_W)WQWz2VFjT>@Adb^GcWu*lKQ`U_ht8gj+eCZK0UqLmEC+)2+
zSK}vuKt`9!@va@D$PzFB-${Dtc_(Cb$ERwW9C$|#ai5a>?j9x39%ppIEm*Or7I&;S
zsfCZ4UUd@Xgi)v{x6snVj*6N6%itA{iiWiW^DM=(J5Lzv-+@Y3n8U|z|
z&mqe0r?WE$!cxRkaa?q_who;CBEFg5?W5NH~J;M)NOaG)}R$xPz4oeed
z2hxbVJdGqZPOWBQ?iRCN^{15`eY>kJfB(cWm{L87>^)#v0B_&1;hIj`1J7c)}{KvJuqsYouC69NWZhZ6d=eZUBV`F{=UUQ6(V(W}--DXPwD`wfvu|G>th{KoKYs~Y>obVom%sR2WFa~$P4hnmv;UuD>^TP!
ztKkGHF5rY-NHoT3QF4spdpi#;LFbwD#FDO&m}JGIhP%mcg4GwZ3;)DK)A6KuZ%LVm
z{p39+er+f)4Sl7FUbG)pF5=qMjpGeyhDO7tXo%??(G~fH$AwzkLLBlB^tuK4L*#cf
zL(t@|c-?h4n%n>v{w=pA8(lE{pwRh=onJ}HjH0gHU7I_k
zV_3MmS??-0AExKd@1iuG!n+0L*}{aL2&;m-}CU<(PQVs1FwAygw?@GdA)
z8;Yx>#+2X&QMLYLt^sHQu+zXv#-&siGI&qi4dzFX!s$yjgAuk)l66L0AD_Cp8(kb9
zFdEW0rqPr<8oZxGD0T!&x+m{sO$;d6vehGE$0;+DWB7`FANFE2jW0ODFjMRuVc^{0
zs$=IDb0v@pA6m+)4vCqDxKX86A8jnLZ{yg#hj{##;O*mQjFYE7?
zHx_tk(b;VEVsUCg_1%0l(8Ysbanxv{DqkF^%t~SYiBIyDQsQ0qbQhX%EIVj7M%5L)
zdw{F`-~Ns8AF1<}Fcr;w69AyIzE3dIx7AgSZ!3dhRwnowNH7eoP8)L}HZJQD3+-)x
z=u2xND;hWNghjK8HM2rUl|7N8(^8|mR@r6ZCSi#ymqM3*&8ef`j^$~d3ia}KfNP4&
z&&71>a~1s+?f1rlwWe*qYZGVU#^;j}rEDe@te>03N$`DvOtMuOH6d=Q#9SrVZl`K+
zSeL}%T!hb7Mp)zGTrW@o_TJlJB9t_Oy8gP*C|w;#1a0r!;7O;8SY2>Jd3OWsJ1KhD
z`7W|ygl};93`Xz&5}4T6ZdM?X@5I@VtXi+((2HO-`)+Uu$dbu0cEHvC9=$n_vd+~(
zB(0%+=r3>6+_jkkve$HhJC)4NOfJ|ttKgClLwKoD32Pk0XRWmL`up<4EZjlUyhm6KVM&-J3|g#o=aT;Kza>notQKqP&pHOCu6VN
ztr7g)6a2p;`hwm!$Q$m-VxszVFbhPckA&_OQM8;r%0iTio6#NB#`
z3Tm*36(`QeR3GC0LCA{SA1mN{Ed!GfQ!xOwq$2n$aG!So++CdBOt96^*C*wF6#lBe
z_ymLlaATcGBZgIp-5Wu!OkSzbGQujP)*!JJ1g8CH1J)Eb792|!M6i9oceKHE*Z*hd
zm;U{;S-Rc%VfS@&`{mF2Q7mgJQhcuNS8Of8#x-Zxih3<0d*5OZU)bXj*QAi?9tCCF
z=f$v}vXa_T-sDXQK-ELi{DnM1^{tg7VriS_mQ!Zs-5#)u7h$E#cA+Q*?!)9$y%7kX
zzvcbsJQDfo?U=P<43(tYH$PHHax1}}`ETh>)xRcI}6@n5Bh1=
zArJ(nM=SBgaGO$5`Aj%>pzkx`dqom%bjM$n?%6P*_dQV%;Uhiy%^2o@`z;-#%AF4M
zh+1~DE8l0qsOQ91QW5Xy`@_e{yqAD|U`=&k<}tph-#m>=4yV7Mxg1t)Bz<)DrH%H$
z!krUYKgX+bwukvX@S)pqwi*;j#y@7}*wyyvtBd}sJ~6H9vMReAv>GnTOBY8%kmXX|
zYiLF!%kPNh961x$wMFg^x{ncKfK9QxIKo?OE>duR%wAwMV(SFcg*#ST1|x8!WWH??
zhOF!Au7LMtorJ&&fkuHvRw>0*>Ap;{zz#Wsd0|9hQbw*WBxRA3KoKW_M9!1#_R-#&
zSrly@pHGC^ktwv~Uhy1Wy`t7HvuND(^D!1Jh6cfG=
z`JTFO>BuX}8DZmoKI-=Vf-Y=`b(sw+zKPIDoM9*5eV07*u~;#w!(uGFIB37W74Lm7
z=r0yU8M`kXU=c*k8Thrqa`Essubp?V-!xw3q~HvV3w6!JKio+2f=)!v@2DL{O5Kg7
zljPUzHsc4L619HLRzE_}D-X7uF52k)Y{{LCgYk~qpq{;GSz}Vg+zfWHU5f~i=m}yw
za#CndqUU%Cl#%^$UFn0$`kv~qn9fUb!<6w(S+Cvm)%pH#S9^+Cr;9Ey)!sZ#9S2u4
z&`VZ`*P3MS8;Tk3-N=4V4*L>P8IP^xgh+Mj(ESreVM!h1*Z1Z6#UQId5zhP0RC*%LRQicW1P#?>c!>dn;DR!$
z)7f0IY2$^4jb9hV8E|w=*)}S*(Dm8*UaC9d3w#U$gFi(upu;M)$)KCAE}pK|Y(gCTD&Z?_ajGGv2d1U6V2Yu7Ab{Z4P)_ImUY0!Em1?ET
zwGgxzkj*8z>VQnXN8Jw+dYM6~DR*h?@}a7;kR1_^cf;{2q@|0`7-HMU8Nq0u*=C#z
zMCU@7n4AEfhic2lpGX+?yvXTPyqM#?h2g;!dzvR~R%5nOr|)P)jbMG?QN+z)=A_1>n|JZ2R=P*8bQkr)K=mU(fVaK4MU#OyE68UK0T^pkRvw}bs^}^O)TU#
ze9$v1);LyM;*mWmVewfL>McplTR3a{go%EFAmV23LDpsuD-kITBKv{;IUuc&&z_6McA|8We)U
z0fTdngN=^Xe=k8_<(NBQ4n0HDEaO(;E(o*ks_Sy=Q@hII=Sge#Bf}!PxyKt`6c_Y
z@*;^HS=DRd^})X`DmE_FGb+6qyZ;y@C{TRO86dL
zD~Yg;^T_?S-%QkOCLP&ONN1xXg{Fm7pPc>Qe6BGRYLshE3y!%swA|G%a-mLZfW|1O
zUu!jU=NcPxOgqb{4>XXPWiuzkcN)>L#A7vqY;iRz`^1gZp`3YGUjJD@MFn;>*|Qau
zc^2(CTopa1vMoi`a8hBp>xgvo@=%SkT66q{?c1TMYURsP3VHx>It*djmOe}&wE|E6
zy}B7k$J*B%Qg2(UN?g8z!vk&Q-sonW^{RQ6vZ}I-oeYJG+*?>Bc-qcN@0j_ulF_xx
z*t(Xt*sO%ND0)BhNhgdFc-pbAXKi$(Y#7*#MI_N8uZ|9EilS$Wkk?VYVh~G-G2fYS
zZ}ByQiHyt2<(W69n{(G!$6(M7`(fa+inj>F;#^|WuUP>C{%2bcc+i-SM?H}Vi+;-V
zSE$XBpYL^6U9~R;qtS%E;b|_uc#$@f_2g;(Y?VNlGVh7g%$s63t#GIO`iXXlUEx8%
zmM(cDO8Ob=mzNYzS-P5{G702)n|0ds%CEQh>gK2nzR`wP4M;5fpCeD!KlCeP4CyZOgJ-<{~kyIiv*1
zgYr&g=>&;Kf4Q>3KH&R5>b)@BHh)=PH*fix2+f^ozW|LpKcKj^9wj))rux-#uve!#
zoXic6(f%bS<6e#h$5@eOoV97{o!j2K@=@#9aY*YkfpI`Ysb(Gvht6@L
zo~1v+Cv}XPT#d$SgZwrh@B?bG<0`Eu1N}+uRYY)fItrpv{NqQ8VX^P8l&l|wmO%rR
zO;y&yuXW>$KDe9yX*x8o05qU^1FPz+#(XzZJd#T_;2%DURgZ>6389n0D1vS!C#S8X
zD9b5n*i#}Qtuk7LEf7B+jz`z|aOW})38+s^c&X|OO(&%L%5F|Kg^;uGgfXi5O@eBV
zr{z`JD6HZ_-c^O#lC7b-Y^_GPWMil;8#9@fMY}9@TM?Ja&jn++t_e+)O(($3xWt;?
z9l{4GH!OxpxN4T-r!(yuH`#z15AO-+tif2F`HwEQP?2#?8^iM@MG|t|x>Ax$KoM8m
zg~_A%uhXU#x~fNLRd-Ik%=$oDE7FEb0}JOa4apZ6)~Zl~Pc+r4=;N_NE~>>23m0N%
zcpm8--6jnop{jA2nr5EA^h6h6Mlb#MCy*c4SnU9@aP9zc1FA-Ye1dKm*I-cN(5EfE
z!KinAtg8l=1dmUIw&|J}V6;q{ajzfe9<{7Jq@XBh8K+@XR26cGK3&c+ohj5S5`>nHG70i80|OE
zbFv!a(te`2)v6K<%9R@#WnuM>*zKa!=nT&+fGr(
zmBtc0#LrmQcZ1F`MvA3(}YRUQk*Z1>vnv?9kA%N=<9
zQyg#n`u@6H2lXWzc-L+&^Xg@F_hK@-Q7I8LdY;y3u11Ua5*zmYq?K$meHHTX$nzK;
z9EDdbDDjl5%Zb2F+3KU{rBi&yQUX*teIr-0a9MO9>NOA9p
z3jE|m%fe6pxgFQ+!z%QSl1|0JzuIWn-f?&ec4lthxrh)R*9+bd37UeIJIqr+NgnR%
z3vTo>+LT-o_@vze&i1Mk&7R33;OaCtEEA}Ty4iLIbRR9q=z#fDh{R7@Ax^U8RrkMT_}E!1^nI51*r$4;~+&SRQ=z@qu|A=oTw<
z5k4odOb6)C@JsN$Qd
zj#52p35md=rxK8g%16JH$`^qEUxS`gj4^?{0b8bGVd`<{O>m~fwXH!Ab@E8sboMLE
z$2G$A1D;*-C`sLwD?IWzIp~nL1!Q0I(xgH&sOiOVV-t+!~hn6NOn$*
z?`KU@ZtV{zv3bPLV-o*IVwr7b)cix$p(tvM5|f0Vd!ZGvbkhX}NxW9jp!hzXEpg1-HQwP{7|>15C%
zFVJXO3D=4HBEo1`O-6%(4$8%ET1%wE6lmUmJFRMOE$p1bs@XMAYHgyPs6yQ1H5A52
zpUzk)rVubsQ%`*sD9H;BvWs?xz{TET=n!$LO!9IJf8;i#6iJEHYhO+B3(HLuGdk$V
zp=`@exjgA8VWSxX?7sr<8g`P#O*Win1M^Otdfm8V&V1Ad#W8IX>uCxi+93f^UlGBk
zpmYU_CY~XIk@lMoKhn8tKXMG+8|2wULn->Ax~3Q2(yyi*qP+1We)06}(VjX*+S4a|
zP&Ik`GNH&vN(}2uydRH`56q;vUa;Cr+Xkm!%hAx>HK@N-VezuJ0r=6J#VEn@q8bf<
z*E7qImZpfOF>7;a$LMvrKFM!D331h%#_Q4FioqaT|Em2YvG*le
z6ujAay$AEvz$t0S-R!5m!=rs*3Pkp+_R}ZrC#u-uiFtV*-XnzB`onwGfV1-GLE*gC
zJ$}H-C$p}Y?iavy#5$}tQ96hg@8Per4?Av7k}z$YcCG2OarN&%N1u{@kT#}xpim4G
z`+&9Vr9Jh|Pq6|X&$fr7_rRHJqS|*`F}xQdfJE~!c;G#|-DWKXOT4%dQ>xsEwu+6U
zBX6R3eB0Jp;U~fyu&m_;^>al`-A3(!E;!GbOk-#jN}oDH|!daw;!IPCsT?V60n%eH)(H
zN0ndcn;Ld3SWjZNp-!IAl}pa(%2y<_5A@wXG@YXz3B@kmVO-fqmtWKt{%M-zqIFp-
zU2=qX_3;?8LaXN(5IO3JsvOd@v8LGtqbCfGQZ0i0b(ky!*BGmk`Y~fA14nUDSGr{Q
zuo3&mPHCkq>V1}f3OG6z2|+em=RaaEF{+Rw!l6m7@PncUc>sy1IaehR#@7WTBzu?L
zkA@m$MT--0;1PxBV=uuSoH^$wy_M!H-K&UpxoKc>i{@Z>Ho+Q@)hcxOU=FlM2Z1vuCJgo9v2LKdwj$4e=;V6&3sC0uvd
z-K|Y7tWh;TxPOrIxeO=@DhAqVb^=~nL@zQkzogUzZ)2;LkRs9u%uyium%3`$|0M!2
zjaZEn1zJo)ogso^Nkq<3GXTri^|kJ+YmW^#t%FFJq?K6Ay@A~W;)=*>c+i0e$?~IV
zz}!{4f&v~1eJ
zMj>c9kI-0|9Z~tCp{A(DA-g@K(G)J^W}#s12}^?9or$ufY%Ku=01?0sGwcQ%fYD~n~x0?PwsRYpizo2_)qP?{~GoHIrrkH+1ttD90FK=w!Y
z!bmskdmmA`pBd3ofh$+Mk99aqyb*=(Jg2yQOY+2xAO3q;e$bo4qAO&&@QfLr5s3I+
z#3B#MWgh0*uSQmvBc!B;UpxaJYdE>21LNfp-nGK5d;|{t#ws;hNN3A`M!Pwk0b)qGb(lzzmaF^)Ylra2>#9LJKRr0>)|T
z?&CMZnB)}mZDX1nDL(}6?ujIimfVBRDUaE8(sk(EufTD2qn5H!&F^i)gvD+OsN6S!
zc!SUj+3xXgx2+k;+1GJ*Bk~O_=0KW4z2^M|47q`f{vchNHQ_l^yX>}Wz3A6o$B?D2
z*S%reH0e8K6NdeVR#1q131QW=JAu`xH-lsumY}NF_~%nF5*`lB?R4%cF$tqZkL-)J
zKx5GOvgtZwdGZ{ijco#rT>W=Rh3A|QB2NAf9Be7t@zP*b^!L_#%@FNRBNug|>lrm1
znZN*brL7SWbc-nPagtYEg8
zKNZ~@L+E|MCrtI>o^2A7Q1
zLZ5ZY*L(-zlDdG-79&|4HGD+rEIj(=}iAk)h92Qp!xHLrvE_hXijK)_q
zBBRHlvW`5XU1DW5E;o08U8!x7m$mr7fO~edU+q1Gg&el+xDD$C8)$6d`Cneg;jtV_
zE?6KbQ~_sK{D&6z*2*j@8pu=C@$(teb|ubHlgxqUrYiq*)nNhzhSNpEIrPQ>G`R{5
zbQ8i7N3^Qwzl{iF!cuXsmKOKJjOwu{r7I)KCrwmle!lLt0sl@8dOAU`Np71i4#w>F
z;cn-fi(6?{fbb+Qj)y)^Eo-&gz%NQ-5%F33TP7?ZAHEm9;bOuaO4x+}gjW=SAKYsp<-lg1>(YwhuZ
zt42P`C_lWYz|Uaadn2O2@>(a3G
z9Chl7zzo&`9pjFtut}57U!4?P`s9)rdZ^x#&A#bAErAZR|1u$6FgstAH>muwL&~xp
z!T+sFM2H>sd`Ue&>sjZTy4tA`mvR(}OsR7j9LpU$Y>T>Ugr_t#7E~io)(g8VRIN68
zs-mVrvbve+N}1gem&}ANR&xO~l3JGSTQV%R75fCh|KdG
z>*MVYL2)6!SxH6PuQuk*Q3I6`9I?CxX_CCN&+Ke`QB9$EZV1bz=`T3z=fxYreu&MM
z)rJ+eo5479D3(Em`(~S8Gx!2;wt6rwLK#@S@h?!WhV+ivpkxQ6474o0L6@KV_RG&~
zkfD3F`h&gXAK!;RvmdO5tWDZBc^^}z=Zs7vkMa6ZN_vPiSNV2Xuti+21RTIHF`^-I
zBsL(vG)<_mmsqW87)h05L*tC!z+<4w4quwmn8aBV4m*cQlp8B$4hvYHCuzK$UqQhN
zbKq60laLHbvXlkkz53=@dFKtNE#7)CU}vtGDO+s)hg5m+*3d%IMWuDB;JsJ{qNO2X
z=&r(4g|O2=f)oZWt98L~j}f#iQv`nTjc%PZM0sm3ne~`Std07Owb>FDTeKN+8m*?X
zywDG6YH^4v=*W)Z@&xHcB5d
z6_Q7-m~yRxz-FbESb(xaV@RxmY~!u`CC_wKmfNnXYG1{8i`APW5x+Ha`>q<5P;yzo
z0UJlCere;(7{*q7X;*(kymzfQYFIgIb`#KRl(bQ&oNvbrgDWXuFr=u-MiCb@P{V|c
zF+ZxiW&AMQ--u~M2L+&Rh2#QQddc;}g7d#=jLXE8hb=3&w^2yEXxkZwW@#*60o~?)
z5VVkPQ#xA@AO&?-vK$k4YKgzJ7&hH`>_ut_bE^h^*W>wi43rPul>-flsoe3)kZ?Kh
zp2;{5)Sny@6sU(f*@U{B+7u6d_dP
zX=#k9{_cXRa4yI>nJzdWdu|-c3n8U}q>A9o=35`lBk@`RURtlVsOGCNamd1l{(hH_
zHB|~^os})dW+sBq1TO<*B^00ERAcnnfn)a3-(bZ5O5hCr#WqkkkM
zs~B?w#lbAYtoBw`08&voUmAo|*yt8CTfSp*8%4TYR+c$d=Sib6a<_y<`_Q5SGBZR;
z-YO&G=n)-;@26p6Q^~X9LtY-1J5`p>iVUd~$tJS31CK&W1e#yg>%1VoPm=9!KWr;e;FhY`(Unn@JG#+hHxj)JwiOMoakgu<&#o#L)
zQtEt-yeIKPzLfSgK?`#le{q5t|5`Od(r1;65@|Fa*{PTY3I_{##}!md%8?%(K;xV~
zww#xhGKohis*H@(567VA7!(!28uBh%NgZL5*1oFiV{`x$yH+=Twcl;a%uU>b`n~cF
zdH>U%y)ciWM+=;d5PJ^nwDkZOT1p^P=GC=w*G(gzs-=I0C904GFoZ3zsiiLQ)f7?7vmjZ+t8D`@eV7qDGR_DmTNR3B~nXK#J;Q03dSQIch
z1c7t$#Q&71Oh8}|MA3LdgCCk{WHM}X(;``vy9V;61#3j{Lg3F8^-Cia*Fx{>{YT)_
zH|Vr>X@RyzgND;gdcJH)08hf-vI%Siq$41sAT*J$eJ8aOOL;_x
zNDrceg_gY@k*G?*!w(57AZJAo`NTnjri9A__{%9{5IjaFp8`*XO@-7ZYyex}hfO#N
z)EJuqUmKW!h?sE0!teIn;L)C*3PiBr%ov>ZJBe;wuE?Gmsa2_m@9f3i=ZzURP%4$9
zyF-wjAn`}Jhm}jEoDjOtzM!Fc()hQ0PemFAyVMPDi22wpBX#dr#uUjOKJ+aV=)0sJ
za3#d2pE2|tOfJNYi>qUsB7-e;cPhGerUJ$F$qqQ
zp0=sE1naRgiH>&DvTw)_l5#yWvbk#*BX+0=8?ejAmOcpExjlakvO@S_*bOazy?mVR
ziC*}ZV-{?LBxdWssR6fDV0YqHNe^lH(NrYnh8Xff^D6qgYs9w7tsi-dGPV&0H8P~A
zKJ>G&#^h=mw?>m@k1bzJozsVA
zKab1gkOPULvdDU(_6yA(dqW1^+`ixTjbM=-o;!Gy>U0fe!e{&8W~c)`b_?%eG-c$@
z`2tV&8D~>uI~R51XdsxvY1Uz;Pk)nY-_9aYXS%!gB0{=Sh{f@n@D}vY^F3UW~MK>#RxdA!Ixvh&v)d
z&q{t?cF^|Qpj-0OMDFQXPnVuGG4L%k;NS<$|LA6a06UYtg3yl`r1pgSNZ#45<*3*{u
zZ@6MTO;M>1z~G)#0oRj~?~h$Zc`$^G=QLYHPzyHt6a|62EM}k(#(7r&4N2f{0csZT
zg#-7*5+X(8&3IYDM>N~G-NV-%_R_B1db)MkQm)u7Wn<8UH21|TFLfQo8jUSyp`@ytR0bt#n}(2>r#WWqfv*R(JE%@
z*?8t@jJl#l%YGI`-IJkA0Hjw=>X;j8wj8nSXzwF#diE&a*L!34)9#clCBoMUl}nw=
z1onZ7QfPid1v1!dN5L`?HYYL|Qa`GBpXGnc{r9t9isg&Z2V
zi;F)L$2G^MWfgI%(H23PwyWvu-5Fk3%ck}T;B%#qwD_V_D?d{C6{)uW6<496)5L%J
za*P|1T8+C&%24Biu!d{9fs$-`8__aT>Tf1
z`8wU7zwgZT{i*%^`E7XA-<9R@3|aWdFT)
z_o>|XAIjA8eQ@j$n;M@imsM&iYj8pdv^eR0@84~{q_YYN-kD?=HmyxY@iyS)<~z^-
zt(HfwfGxesQtuwmPA+Ms0~@%y5rmHEC|IiKRKqlhGtUK{E!Ec7>iRSdEii*wz6R#9
zp}V8JRnf0|A(j=^RA*}@J;$j)RiXAURI+lhlYbov77*`nTsTw?OT?qFJrr1(Tzsx}
zQD=-6UG(Mj_?rBn^p&y8k^jylha~#NsJE?R1*jKoH7G5?G665_-v$+B;HPJRv-?{z
zD~}Msy5R-&J1Uktfv3Z`+f>PixhPaO*H)b~`LQZ|%uQa3(|we%cX)d@+gh+=dVqCq
zaT^}EsD#|2R6Kk*Dl-MrcE7BabW-{19L|O9bUBnmg$Q{G{XNCQ0=6Afv%sl}g#b!=
zlz6oHj{u`b-V5k(H*0rS3tM;ukdJ3q{_Gei)ALE^@gehIH@-S6D-ihr#bycB6XR1V
zw*bH?j
z`7S0lA)^q~J15w0*H?eHYwfs-@cN2P6GVv~W-Mu@66sdm($!P4Yb>DmM!OSKPS?WV
z{TEw>0^s{N@%PPhu?m0y?Nlbr!I`?>1$Ylej5rkj4nNHcRMFZUpprKyMXel3=^~Jo
zs+$%FxH0iQ2$43}fWK`N*s{Z-L=kAh0vk()JyeXJ6~_ZwNJ}z>nyQc^PS9@?Es*?q
zOxC$DJjOe>)cNexxN4>9z%ol&o@?azh9O2zK^u9dxxf7aZoTRqK%$9^*t`kAc*N1;klDqP!0IZensT+9WSHT-V5NF|EvdVEf
zz_rC|l`cueT-lT^-Ja4ErWV_JG3l8|$x0m#2L)$KsQ|foayILtG6Am@4|hB6gCrWn
zOhZ}Zw-B9+5~?O=-f@FcOjWDz0^t%(;K~Y3?7Y>3*(AJ5cFK`uEHxkzuQpM=kVVxJ
z=BMpOX-QWK%U?W2A=AmjimcqZv{Ih(k?iT)>O;;*(DTt{reI{PeH7vR8E53Ae1s+e
z3ttWuoroFEv3$A9Kb-es9vcdPI`xGt^zo-m+xCe|x2E~^EOzxvneo^GxR@KUL|hsn
z{!S%KF+iyj2G1m;k66K!YAz$JyYYtIOgXuKvsv)WEJ71d7f=i(%2IafD|{8xq31L1
z@tsE4-I{O950l<+Qru8{FQiF#m&;IpizII
zX}R#i{(P+ppXBPdor7cJU8O%tahw*MG9f{t&t!=O;bIvsRmcq$L!Lxqji35BhMgD3
zs%7tQ#@L0{ifa50n?IO>3~DV2^ETgiM6tMM_?<5}p>~u}IOXEGvUxzw?!f-Dns!sC
zKQmg-RT*ihy5#dP-CS3qUX6k9oEfWWj@D`+@fOvV~u0JQlM657+^OMt7WGTyj+#|!d1W0ySPg#_yM*f37
zmTi`5&IlyCPEo;UwSut2%w8BV3!w8d;bt00O4xpqixc%8ga;^|HHDS>I*#V>F#HN8
zOh}<>qy`csm`)idDIyZ+K$T1c50nBcvHebbUVd(=}?uOwTrNnv49diVlO$g)%Hw#TnKmM`X|gQ7IwNt$#~L(lI6AN#sg&u`K9rK$VA>2W&IE{By3-9@D~
z*eCWmrYu8ouwb?zUns4b=9?z>r=gn{->JMNe!9(%ImP~p-QU?@*WnON07-m%iaHNi
zu7N>92gNhNRz9$!bV!}KCY~}EWIk{#p&~SOz~6tOeN8!4&(xO(C}#b^ZXmSHkjuZV
zoXAm0Q?zE<@ju|4FAR_9RxA1RRUaR(nefI760_aYK0)(?IR-Pc9-S2c6`ZRWOW0Oq
zZzKTRM^HU3ol)eMzl-`OExqIU?9!utcQ0q^D^0G6=wo|)IZApxo^pmAN~PtTx23#c
zmvmTv_{ix>7WaueLnC3AY!I*PZSwk}VXAXy?P++>EViGwMWSOd8r=`1=1&-Iqse^!
zIgl%+o)JvIx;|+1A{!{`5qVHT4?I
z4BK8&SFl}r!tkq=aKdWNUKNFYqROTsnqpEhM>Fus2$d{Wd>+akXZ=U7{n|iSPZOLU
zgEy1i?6aMj1}YkbymJ%c7^-`tsU9$s64U+L?DBIi>RQ%d6Ut
z%x5U~^HoKv6n?qxq-;IU$ecaBgH!mQ-%S6WzwAGA8}q3Zs4eXODYNUXb^Zb^cUl~i
zaUb|-n7|oPy~gQP+XtS&Hr-^l?`^;0?%nlwtC#Qe)^+;cc{UU^vIy#Cbk_UFdy$vb
zOlutSo6|M3Q@Ni&*w+evzT0fgf@3b`<1bn_Mj*x-2gLa#yu`@&a+jiSSlqE3kZu9L6EjJ!4i(sAwCT{+1#-&famQcFnd0
z0}8?$F2_OhQB(V*4wa#KeU~AEx3Edl2M*S}>zVv~2~
zY@%|dwY2I{gc8Qe?)MCnbw>F7I!TEo14(#dx)8FfpfT&ww^Z%@XhMh$X#kri4
z=AyKE;MamH>TG4dW!hLmclZB|zAT-n#llpp($fSkp8cKSK+n5`NgZ=x7`r*4lQ4~D
zR7MsQ-VQb%zY~?3_81VKkckxnfeOSI+;cg~8pT9=DFirB98zL|my_k_z|A!sbm#dM
zXu(=KBLWyGMR0gLr=m_b=d1UjgvVO*)3=458=6&8Y8yBpL8m$rqcJtxfsoELn{Kyc
zbymGO@C~dV4^2x$i*3b#Z|B8A^1NR^7#X7*xXs3Jq=p|S1h1#!I99zD
zl{V248H_K|jag;^pKT6@5MGuDu=pwy{U`xXL%$NO+#8$lkEv+QwTxlG
zg-Il3=%)_5u{8`$C5ioRf4!|Bg!QQ}h|0d0iB4s3_ju4y*2lI{7qJJshgMD)_py3J
z3Ht>Zg@Jryd-l9w%`979eFbit!`sE~KKt`bL-h34AZhH0!}{iykq-`CI@Z4+!0mo4>Y-(@H}s_I-@Pj0;r;9zq4jlj{fMj9byBOF
zYic}9dGal}Tf)I3T`sT2mgb~ScgVJd(Uj=f$($5U^xTK3BW6fD$i8?;zg!lE4gD{L
z_>+!D%n4#_(47+NruLkwdSH_Rp7PD;vpun8Q{S)}y40r|LgL{`s9?Bp%<;*>+Tr-M
z4X%CfAqq#~jP#jxDO~|uMAMPbrUC}UL6$<@V>>h7iV)HQulQLRw%!d#(Bj_|_RU(C
z769AoM`9UA&!G*cy@ovTti*qmfm7|HH@F=CHFL?0;7j;lF>m@ofv2hFX3?57UT+sK
zz*fr}H%vLsIY_^VZ^y{;RLz_(y=KRgs7RsvKeG#(ZR@|^shZY{aaMGWsvY|4!?8kq
z9><)O{k-7MYQo0St`=>YA({l<9}nv*p_R<{P80RRNTOVXL^Gx9d{2RnkoWB=D?#Q-
zPR_K$ylj=Vb;qlzxZsS$yD0;nSaPk8^33T&OGI{pGPukQ?N{=XFuBpF1yKaV1zqjv
z=^5VW{$cnv%(`j>6%0jD5O+lGHp;&GVj7wu)VeXUV9$$7j~6FGA7T1I^fyKt%obI&
zf-B)PpXOQZ9{!DumEx2-+-Yq|x-R-3Xu*Du%a`)IbL(Gi0);C`gHAguUVvfxaM$$*m0^9YO}uSJ!@X~2m9RyIOZJO
zRu`R@wuXvb&TMV0^T74}8NIABQzRl0%4&8`}d&vP=nFSw%z$`@3KVj_?
zXxJ@|HPR>rEZTk9btbSZ>x{!8H&Zggfp%1
zPk>>z&VsJaDnq;bl;w2q8QK*eBgHQDzWDxAzViQWX#x9JzG81@?_&Qy3R--n1X#xY
zt+R|wn)52-9?fLTuDtLQco*BtStHnFI
z$|zHIVY;gE8_CQvBba6gWsFpSvqtT=8y-Lah=g=K({;mmAg*t)Q*KNWISL64IaZ^T
zZ_O1rTQBbvAHlL!0m4FhS5yj}@@Xg2FFZNqc(R9>cECXWH
z0fQX`DEKWwh+_C&kI%{f|_g@P6l%4J1%?a63${RsjDhl#;0qgu1`33w=#G
zcH#L%G-k($?N#+$R*m+>{#zC7CKOXgn}nEHVP&Rs8wT7y=h>9qLg9|SYa*T-+8qv!
zD6~K3ON_yH8T9R7A!r{=tlXQ^d~RQ(TSMHP*|qro&%K8DU%L5gjUr~clv!G|(zTAU
zyq2#$S}fwp4XT|R#Swnv7nFdshe0M3{u_(PIqz8n(0~jL_mvc{gwjUW644(IFR0jS
zy2q}YDbF9goHiF$_QF}cdxN=zuFAkJu`X6JFNH+2^}Z|=k#iTwJ@x?~22L
z^ZSlG@njR^aCWtCt(<-*+=?)+SYVuK5$Is~^93o1@z4U-GR}0f
zOv2cr1cb_}k=)rByowHo^q2mj8cGcNqM9?!>2e5aIvP&May;Bs!r{|71dt7_&jvmG
z$ImkPnACD0d30(Je!*@pG!Mi`D`rdvV6u>c2;H}{#!>`B1m1#>Ew&bkmL|wG=$*da
z1iDE*(p{N=J>tTr*U>it@=~e?6(^BVqacKauo_lRirTa}0pl-E4m*M%9I;1;`{eL;
z=CNdL44UW0kBRGF4JByXj8ie=z!?JG(D?X<0aLnJMd-<@gV<-(><|b%cI~?y&-y?V
zhF>fjx{!O~?SA($_iSzNkgjU-rPv6q+
zor}e_B`^$wCxpw`$j}uiW^`sHI^vKOnVdGHA0@Y`eCH3CW<)vQ=Wc4j4sohOEdvbW
zBSLI$Aw|k!X)c!%Mv6OqMM(&(eYj{zDX2TRqzEUj&5z?=vpPQlcT-9PEYvX8Q?BaA
z-}1^z@)S?7j|8lSsEXthC)gYV6QrmQ{CN{P8n&k_MCj%Wtw7oF38`zH2%yQGnNU#|o--|$0E5(fxCnc!Y`HfiLRU|o%2g1icnr2*OPe>XE5#k~%GaqLdj
zcg1k<8J_N(n&wgIb{Xatfa$MPB>+zRN7m&hiD>&M+%t|)hmZV)@CnaUzV%vgI|3mw
zMfj#rDvbs@Bm~t?7ARXZg^Fnz1>=Aw`AFRH4>U1R{EP4BbGJ>ifY3E7gE9qdMGBEK
zxX+!P!<_%jy(UM>wz;KxPP1FEY9DP(K3m2lgadFW<9q64e9Zhc>XIOi5I059_72wG
zX32f~hAn-!8Gcjy+HOKz`ZDoZB(
z^rZ7GQ$gN=CRWim4Ul(MaiZ6hCKG$Jv8}LH_j6UPCzM|hwv<}FK^M`dRrxB9!gzFO
zWUmDn=3o6wZ=MP%fzI>f$Am6HB8Gn7M2|9KpfR^A;!p)b-NiQ#3m9ewrNpX~aPMZ2
zaPjWki$jLdtkN4b)`{i-%t@%8sFgk
zv8gd&HSJ*paH_P#L6Q%mQ_^7ow7zygBE=w0t8?0ziYznlH#f2q1?_Dm4nC+!wwqR{
z^rz?$4?Hjnjur51>c!ii1YJ%+a@0T_U?nSW3*kx>USA@EZs$j1M?>5_+XOINuv
zT^VX@E?3hPanaf7mwds$UJF@QSwB|q)f;KcI$T;`GeNudIC?Uj?B``}F3yQ~E?hc2
z4Q)tngmp|j=a0!6cIrzt7i)H^bsKEg2z2G*&7P$O+NMeLLA_lz+FUiav+R9?
zUI`4+jKa)Mu5(@N3Jww)W$|A{h
z7k7BYt2?Thme%I0GNH<)dVM{TZo9?pgPw=IR%a2L#cah?yj3i4Sr^x`>!ea@!_5^u
zRa3mJ(S8f0E(ZJGvd5JlRc2>~VrbsU^_HiZ-IQ|6=!0z;8U(CixElJ8B(Dc30l%}z
zK?`eA1@3m+izLc`c}mr2n$1m(1Cwz1j`LlEL>KH5>)m)23SILHRw&+?tQFq3|Ack#
z$T2h8>vmG4Vk?G#M<$#n`?>y3CTC3H1!iQfqt$5-Z0NLux|nX1#An&h^+#$i_k&{y
zO|Er#Q@A-6h|H3b%m$i(%aiIDn=i;tNPF52ODz8bxN&#qv@dx)w(JUS0pob^WI#B$Hf|dQ(|}N
zg@OfA!pk=S
zIN9Lp3d7;(YDkJ3=tkCYS*`FYuy*B
zA}z&$!vKLC%(zh#@Rit-aR&pVAV62O;uA>S7`%0_JDWoag5-cj^~?k`ND%T@rM>AQ
z=rWfI+)EAiq0v*mJHqd4AK<5a@E00T_g0@Msk)Vc3R8)U8Tquq^lhIvOw<6Yjg?rZ
z_Wah0LicZrTs%=+k%GRr=Qrt~=SP1Tc5Sb5nH--t(Vbi^2#&-m1V1xZUV{_rZP9pE7ud>>6J)ZSD3`gsOH>fBEuaJ%P;5Z`mBTQ2B*
zyZrCg(SuCk`vwo4;yAeq#G-PsTJiU*N1^qp#^WZXii?4lLnIw$&*O+da1I0Oi+Wm5
z>cU5xquDdm@mwcE4{-|QFcu(+3mscu8yt1M?j1x^b<%H#gHG)UV8c<}AO~-Du%6nO
zu577BS5)m=79<4nCJn|p^2g`YEE=+m^Iyvhzv@5f9Wa1Fry;?-8GRCtW+q~}0)fHR
zL7^@fq%;bhjl@Q5JX~0?qrFpNgOBIl-i}ZE-}jtXpHk8}5-lJt&;`7MU6P-T^G{UU
z*)e}ZksC)yTf<|o1Xe+1G1@r{NcgZ_GiV0S=13h^*_3)DxjR>msIFm6R~p@MHmU0Z
zq)Jy?_I6#p+DJ|KoUON7?M2zA6)&nyyRC-RELvHw2xLsVX+5g)YlBoDiGt6F@ZVlN
zb6=L$?+h#9E}FRGJp34Lbc=(2@*tZiE(yvrU`Ilv{rJIk*
z#F9V0E=D#E-m`6gs8sB%&6pvy-2zse<;}1qJQRZ8h^Vl4w91CrmbP9aY!eJ&lpK$%
zDmrr$vjl$zo!5Q4AT_}QgBJ|#6;JgRzysOyS=(8>-~U?>WSiNrwd?QKm^Iphr8gDw
zR6y^3yK+zT?D@o#6SI#fQZ{N|YVYsfFRdi_I|yhL)u4tWHpQ|(m13aHh6NiSI_*De
zcs4};GBC29=twxrQL!U=`tlYMz1&#Vv5b@dnmcbcSo{?;`=^`XEr7`K@ByegHUs(f725hEC07e_!j%05uKxHNXFJ%w?aAuCydi4SG3oqIo*Or9IJ
zh4y|-K}dK2Jh&v7FgG`NIuw>LCYe1~rv$Qm07IRf!Mzv&i?*>n
z_rui(m9q^#VSY&HwY>Ky*k7l;9Uh{tu0m4X11G^3&uhM%tpEtqyeZeLmJ#<-SAZ|t
z>QDkn;`kAyWJH}73>lb>JMC=cGC|xv%96z^SK;^}%V(&
z+Zj=25^ukWh2tG(E`en;Xj!@Ld+XpGX$EPlz_UWg%0rw10h0aY;t72Oal!o>?!Q@tT!!LFEaXJwL#}%OxqT@LLw~=f-p^H9y8;Hvp6*P(o&2T{>=+!yZEn%v8
ztssg;9Dp1CRb@MuZl&g5{{*v8j``okF)d0_gm6WXHhLBUtg2}esbv`42!vxyB)B40
zMy!>wuu7A{eAAx}{>lZ0*aA6<@K~W=IB`mj
zXE45~M#@~;VafE4ES`3TQVIWrn4_l1KB_KY)cSZU;f)fvyL|{UK>`4U;o#w5>>Y4>
zSG|pZ%OFV5-;l1_eHo|#oMrJ1`F*MFt~5zIRowwLV=B&Wh$&nf(tX8k<)ZfTLp_SXdm(A$)V%c5*rJ2c*APbmlr#
z`xKK}#jNFZ9;ujs8!2SSg`+~P30jQuu1`ZiX(M(+B{U+0QqaoKU;I$zIMnqzc$~TR
zlcWnXB*k{6cl>!U*)W
z!^YES^w}YDFluZ@rSM+Y?n9@(6Xd~HlKSU%<=&Tosv#uGL0jTF>dMQ@hzNc`OeVC<(Fme`s!eX;YM#N6NaUq)(JxLFIAYcM~LEXcPnmbn*{{4{l
z{lK<%H!rTA*EhDaOPMO#(&~pGahj-n@}93bkjk^?XwY7abN&0E;vkFKd>9PPfrDXdy~{zk4F0%t0=RQq%Z~kPW-XV+
zYeUn2S|eay?0cGYv?tP2<^$zL;i-(wJv){c7#Fnu%np7A4Is2%-01{7FBcb3gBrNh7=e%xdlP3bG9~NnwX>Wue<|s5_acgEUxk(FE7TbHZ-L>G_7Bn{)I$xF#
z<@=HYPJK3Wn#XGL!a^t~f1dbjagZ3z&kO-9KNs*pioX%A@mK1zADTrsKj5%uGgX@%
zK9$mw*<5fF&0k`o1*&~Qc9RA#e)v*B`PN#Yz*=@vs9XsRsAllJ3t)dmxA9&FAm7bf
zh4{MwIiHNW7^dBoeN=}#2g?6xu;{cSPYZ@FDzWQC3kC&}!70zxt9AYSO#euK=eS>+
zEJ>6xzX^^v$IKiFWV&JHH!Z?WH2qM9hYsaUw{(kV|WiF)VPbKR=pH?
z(-y<*D7WKwSOWJ&-?eVf`OTG!@8`~!g*Wq;>D$b8V>Z}`GZ01gT8lqcFa2`s_E6qa
zQtjZ72jW<4?MsrwCX6!||A%e*{+ahol88(amPE4t4(JzcTsKP_Cidho5q=b%b3h_3
zFWP<|5Wg;QXA1XAk~FM1`J7OL1WKJlET2*{t~bo2<&p=+7uiX`T|Rg)FiS1x3FK(?aP+)z20D23?Zc3A*fC1d8iPlcEnnT0ls1SXSq5+>8
zQy@UTcIeg7^}DIP9n@>lg;a`KArLf_S)-JYyO&CYceXZma{fVxFO
zX-kv0^#xvW9E2mkS;|;qj!DL-ekNYR0udAUSym>?Ll($G>GH+Mwl2GrsNY8Dn4+`pC;Yy)lc@
zcExQ}4gn6krW&rxKI9{(&5
zF>%)VN&d9FaChSkbwN44pcMgj&4>;J{=SHZO67ta8dRvD_uEjRD+m`$u*%UH3oTnx
z3gFlWE?U4qN-t1nCBNDM8D2sOc`ST)qoDLD7>lOw1)t~mj}s*Go5wkv-c#sXkFXjN
zOG+ZsBJ}YmPskm+KS?CUL@NPw1ZF
zSEVAILgs&}VHl%1QWLKX>BPY+$XOuZ!m#LYN9Y4JB=&)?RgFq=6#+k>UjiXz<}7fVsOoZlQhV3>|Tj6SS`
zJQ&yO61_9Ey_~Ea$KGuq1n`O&lWX}~|GTqk^D6CH-I-Yv0`&I83hn^bbeg?P#NN1v
zE->`^BQ7F}^4k;ZH2WR+cQhIxlI;-|v2WI-N#HrMP0(HJHu~T|uY)d^bX)BnyA_?A
z54I=U8~3q%%?T$Zh4Jkv4f=g_vc1=wjZfc0GD0kV2@!Pfe29f=L%j#h@l2q}gXwcT
zX3#lj>lwChS?DrEr{Cjbc(B=)itbAkQk;+%eZ`Bf
zBBiQOY{R5cN~qY1ow~cbK{&{zW++MV(vDFUNy1@%^+F_Y3GvY<)^a73B!Y&RoR_kt
zBa$1lLW!oN;tE4qV!An1l+sbQ@JvH$>7sMdbnx88>oPj>`n5En*ijPm-4}yPE?&3^#Y(Za
zKP%~%{2{S#VL|QN^js-Yn$*`v-scUQJw>KKB>R5w~r
zKdB#2)NL)5+Fe*v{@U?e;1AEsaAmPb1u@18ug>GQthDg-O3FSdO)n7r8OgNd&>lVS
zjVNJH#^K_b1sI}XvM2~mVpKBXMz|nMGOv?Y&Qar5%jWWxals)Fg@$-#TN6%5vnG-h
ztv|{1wvR6Q*-W!F5!v_b%3a|S9-KPlwMA*0I{!)4j3Oe@R2KkII@saIR-XzGTUx}<
zpw~7vfuY0}&vu?Y9Mv#8iML@Hz6H#C0XV#N9moy{#>*Z!q^y*>QVc+9R
zLKFhg!Ft@ACJ5>u&duz`(#n4DR_Th#J@Ib6B;I4&d(|g3xaO98zMa^wzevkmzk12?
zZ4{C9Vu`5{b={$h7r!ipN
zK)-oOeWP4kwfnT+uKcs4FOpH2Ft^|8Ks8tXd(s7a*2-R)o-p0p$mg{iKQ2yZHxW)Z
z>F|y7{Pc#8rf~Xne_o=tFYA+6TOd#+l?SJ{SF~YYxSJd<>rwqg
z4UQ88$=)yMnIw9Yvj@eD|2RK6Zs1qBYusE+S(joPK0^~|?n_?YJQ)r?Vyk$90HXHG
zrGC3H%hSH1PyWjd{pVRvsERjj!T(oTj?1>?2rn_48h*A52g0EqUJanCo+&D%{^-jB
z&?sVS{!PQL+B(>^fXPp?}
zRxbLg=;XW`uIlk);ABVU*>^h0_XW}6GJM@o`t~TU9}w{Q^k_Q1I6OJdfs>EbdGv!k
z81nG=?a?$3R(MF2
zH*De0aW@gS>14?EN;>T++KcH;JM62#`VSQ2kC!!{C&OrXrha~rUaN?mC`4yKqTJUP
zKO7G~4iArpBZ!4R_bRB+MPD21cBbevVm7l>v?o{x-v%}%h
z;crujOH?^K`SpDMzwN!-c3U~JAoyNiL9?iI{ApW_w~V1z<&Sv-iuxR03zbmw#0@Nfu+|QJhHU*jp{a<
zLL_MK%C60ux!}`gmAC5v#;-T>ko9$A7BY?6EC3Y(MCSndNX(U>Dn|{`mLn)SdUL+j
zA&tH4T8601UZ5UF3}YECu#B$T>2xHPYP-S&qom>+8~?jM@i#Icu8r;N2wuX`@EJz%
zLzTnp@$90Q4TZX!o4UsC@WYSO;UFr{*?zSH`}w%1x}iPWt=z=}Q8YO(X0Jbv)mCV~
z1>ndbXEf{&HB=Yn!b8~XxIb-#76<`@f)MGY4LKc_!AW{~2<@A~#hQtGlj!2#=Ed~-
zP;XZ7+^H$_KrVTkeygk-aha
ztx2!U-hJ~qrr2-4@e$s1yWf2Fok#{SMXOf|(>MBs*LbF+`xi{5R{WyiJrydS8;9+l
zgyo@g^6gtc(Zj(rB{$3*6wTvrNwi%GZ>TzfAXK0tdcXq{oeKnH=cl8WFDze0C^KL&
z_JIdp*$K~&!Ge$2>vT3=9_!eCoU>eskwIvna@SupToGhEXs>Vr-8em7z%*leqm@cWv>ycehZYx)Gk`k1f<@Y?
zA)M_$c(jgm*hJK)iKED#W0{Ygi{W5UfaA_RkAOFSkZ^}0EnY)h5l04_Bq1V0-(?Sh
zFoO*f`WDg$Ao93(mX0)U*%<1p^qKe_cIezDMJ-W&t~EN*G=C0HhTDzH$v{oXSp8ScpBPwo
zSk8N+*EWs}qa;ODhoayVFzzU6mI$kWDtpfPx<8=7WM#YVZf
zOLASPU|ycvh==A3NZJ5>Ty!i;3FqSw$Wu3HZ=C@SCYK0-&;*Bh1f=5Ukntjf1LqqZ
z6!TE2P&PM-K1Z}0Ebfhb$_}h!-=)RjrwS%!Acn%{iZ
zaBrH&@A$T9w6Q|6s&k&#CvP=CkQQc;CUubdPa8EJxT!{=RrDzi+HRVYzvfNz*QQXb
z<6%I)GaVx>1c=ei!q3V0XmYN08E6-J#9!-8pi$!vopIMFb5@`lldm9AYi=xVJ9NNz
zE{gv9)5#~spuTe?N16P6S_QEWe-zL%LOQc~;j}&X%%BVd9r6yUgVEYOQ*BCcn!*&K
z=O9F<BsLe!u5MX{KK2e{lH4TRZs4WC3dC#Tg7#nvHf8!
z$Mh4E+%6N@5I#I{8
zmpD{<%F4r@WONor9<|CfZFD#wiG`Qa0F%rMKso0^FEK2CBCW!VGjaq9A6hGb3EUci
z6AVD%9GXV?^!c!nmdNeS2
z0RK=C%qDVf(g?H=u!XLd
z>OWEe$`u1mF3@iS9idayKRJh^MuJxqDy4nabKQ%tV!z;ayL2MWgXHQ8>nlvZ&=k%T
z(N{4pS0Dwe9c$DBLvN1YF8j>Ui<&9q__rKtye_xuXSm<_vPPlQ4vXnf-_Z^HT@%hJ
zLxbbt=ym??ky=OH+g1Njc8f^OCE=UfACzjHj)>Fnmuj^>>L0sFw96afO(m5YFhtoK
z>n|dz%zwY1cLEZ9=}Ub{hN3?2Kz?R%gegAs=3+GWp^(ExCf?PVQvwXs{D3sJ_M`LiRN`IA><_+*3=yn0fQ2HW(=|$o94NMew{6EIH2N
z;<{-IPStd!Q)Aw(dWbx{m!d`SQ!qB-9&3_e3OONuVr+=vzBsVr4cN)Ou)|sIEg;z#Iu?v?R8k#`#_5*;x~7O3gQMT>PB=v
z+l1$mTLT|p0s{*A&T!Dw`C7xr>=`X;N_oxB0zKe6#&IFu*(M^ff^#CC5xB*qLF6-L
z>}&Qm*n(uFh?y{4pMp;w1j%pOB#TxI`smQtS7158a-SNKZ4zlRRtY6MiDZOnRIJeE
zxBw&x6Q&B(+4^GvikoktFLag?x&ji5HI)Z%;C6R@b<_xa<0W3^5CgH&3D5xcU8~GL65~iLBVEMmp;-f*{}6c@HF9*Wpmr6_6CE;&
zn}6YMEJ*$icii>M-yprGM4hV2SR^H@3cFTSWm?UU)H=KVG?@{
zVaKC`AVdGXhk^IusxcVVzz(2>9wuuh+4f9q~9J=z;&A)RebMR`V|Lhaxc@?~Px
zxdV7P!sL#OswClUJ_IL`j#H7O{Z3V-(8Mh*`7jt^Q5a%|Iymr()#!^$C5qH+{W34Y
z6$-pk(>k@`R*
zZU}T(vaYV)9BmxFUBnaNI+#bkxl3;;w~Y+X$J#B^O%>f8@%0*9NQ6h;@)ETbWLmSn
zr?^vsMx4)!(#%DPk>MK0a^!Br&HiD*Ey2VEZ>G4tO~*JlF+*=G;1F4^2u;UVlkwi=)$H0n;2~tRbklKmUChO>*IUs*9Ix{9!~Jvm
z-G%pIbTY)QZh0@nTlx&va{uFGkSb~$Qrc5cfZ__%ZhuZJv%6DF6r6;}WzB?&(p{4K
zXYQ0ji!Z%O3LFg(=o0%t^6}RL{G2SadAoYdP9GZ>PIf>QFQ!(H^@K?4G!TQc1a=MRs{7&ld)s7!;2o|
zd}?9xeJ#iZZ&
zn>`#i3@-wBCk@g;=W24*T7m?&my-`gYbjXP4fZG1~y+_M^
z`R-X`jfebYyVW8_JZv46Hzc+t)zBH3ct%*{_NU71G1NtbkQ)t(ekZ>|extR7of~a`
z`8C#{9jTv2Eepq?Y&W6{8hg
z%vbBiq54V2Gv1$G;7_hhwL#^1yG2vuf}O}U8CDM*eNAtYYK-*!^uc#^p(AqeZ7q;UrN
z#%9u`0H{Gx_pkV~lPwLGT~KD{JMnr1D_mfpu_hsZGj3bB^Z4*|q*MgS*hCk*1A|t(
zpzY?~fExhfJ6yE4G$o;L+eQK+49x=1jjlR$iQqKaCpKY5Pjj@tONt8ij@#0-PhQvm
zGs!Bw2?R|hya_DM3P^xk_%AGyEmg$nGj``*UPBY7j|)KycOhIsfz4^-(IZe+;5R0d
zUqhkhA?ufoPZP~bITg!r&}=gZsjCF?SX46Z%I{G9JTTImSE%eGKBB|PFo4XN_UMxb
z)Q;`qgfTGX)SRT-W(kcOEKFj^Y(6{GkpV0WWc;Ip!u%KAS0ve+%6L>Yv2s#RP)f>_
zr1GK5HD+;lQ4l0kY8)ZKUKunmhJzxcEo-v+>{REf!CB45ylv73Hs+28O
zjrIHM>OT)wb;(l7vX&rc6bVO%bMm23)Vb0w3J3w;N@j?QA`-;QSP!v*!{=~|lFlXP
zrbZJ)uZv`-xF$8m81YAq7jEFs{G1+lyUQPo)AvJE>W5)Xv)#t&XwrY*xHr564W<`1
znTrBmQ+FF{t5=_*Vx3^|b{H&!WAuBE2e_ia&F^^7P0qQ1oi)f#dxPP;>^7b}d2;pX
z4p6(8U!JB>6B#vyTeq>U2v<%
z^cj|=iqLskt^b)|+Qq=*4H~{OHcuptd|I&*FA(x|z1*Npyk$w_LiKYymedsYwZKSC
zU&hGh1m~Y0K6v!t@o6)vAz!(m3JJ?HsuA0D0n)PKwz#fRFN>eFq|oplOYrQ43shKb
zK$neBO-~Zpk)fgV7&CbQa2gWZW$6*XZA5o?1`v1Z>Lg_U%(D^=YVwCBm<|c$C~(m$
z`9c#<3jfT*Q&JmcWTq<7)ubF+b-F3)Orzp#mMomQg(sH&!{vXJi$6MjO)R|}j{im~
zaCB(ANN4cNKh;j%
zRyckV0?Sb|63?7LC~#{560{F_EUDM?Rl~uN7b)85*ozBGJ`;zrj2a67L8#t{qaU((ntY@IJp`VLD-3@#17Dla
zU!S#5eekPVUX#X1LamwcS!;ec%{p(sIP9<-$*ONjK=2Y>_x!Cao9l(*JebyryHFMa
zv2SiYKsRPg+BX*)W^Ratl)|yY<$wW_5^0h>%$tAM76w&;UamNMs0g)Yy>oc+XSoD3
zgs;+bN=>SpCK(OX31C66Gq$N&s)fMgD8|vo9lzUxH591~+bMz8*N7~Hs
zIh(di=6l{EO|gtnitqc7uZqe`ghRZw_gsYS7J!gq=)^Yk
z6-qbVXtVP+qvpraSy1u>g3gC|VZ)lEFySXB>hsA7zAaHJX?~^C`<3Rx5Gbp~NAyG3#@R98m;
zxSjz8&3}W}#LbEBT*v~7{Uq?4Xg9q;MbOwHOfVeRS0~i>#T;29T85?m|5j+QR3A6b
zIj$|uelRQ#blT)~^JP<2yn5;Dg42cmZgiCJ4jU&2@Gr2b8G)DuOz;)DePtO5DRKAM
zw?zI2GYM+(&w&%(+D6A|PIk?$sYbUHGgXjxFRG!bSzZj!W-UKxjcK5!GyK$Xwb7a?
zZ`nCXa6KAC=W1SFhz%l(PEc>BMF?^3ILm?f#_Qsso$`+;OjN@XK_k%V1RY*52_b|<
zX;qP}gUGB9w!{XKLZSQZUskK3+mS{3aPQ#x){E!==iaW%CwuVvZ-*yaM@I+Gw|_p`
z3nwZcxCr-G!GW{sHRGA9-n8_n{>$O(R~`MO#lR9CqB9d9)Qf3k3qmux+_~^HInxz#
zksN@P-Sz%cXazCGGw+*Zk{X$+sM<}#
zr2q??mS^U8qj5yT*?M3H55M*N`InS^t!rhLD-lDI-hj;resS2M|NNgDP5r0#cP90H
zXZowrU<9G)zY{#7j);zHwH2czJwuub;A6hJy;v5scJAxJE_H2i8Z;jhW{RYHpwx^0
z2Cq5QL9<^d?YI1H<-FZ!HkwO$B|GJ}NIJ33Jr1G4FJ>@RC?avs+QxIL88+5BoMzA3
zJ0<_W{lEYB=C9>nT5o?Hw2!}QZFYa{fO5aN^vw$HUDvMN=UDA_iWF{;ujZGhYQbn2
z>Uvak%nn=M3R*VDD
zAI%5FVB3U&GEUDx-{NCKX^X9Fm_u|0VJ)ww2YQrp0>uv1yxLOh$ov88D9$HB%N-J|
z!aWgroz~iplt5V|EO^xN*3r7-EYYbv^`aM}d*i013TdfFYs`>D^H!CLsXcBQ-wPWD
z*%!o(;0!KS*9Or5k~A9jQ4R;(=y@ORb>&9$t0T3i!>+}ey3Z{DtCrFHiaz!mOg@fl
zHifFLF^nu7ibHrMaOm_5SfxlU{`iVQe9UAXEPySm_LGv787?DK
zL_aPojA}pA)i9qm;esdQz$F?ga3R^q^JH24p^Y`e>z#kc9?4roU`^4eYd`YUms+uS
zDU6>g5Cqk$e7%lpA&;!#82qJ{kz*FBXPn>h~l@nuLssE%u7(8eOW=d#-aK`a$B~r%6hk3W*
zNfX|onSL9a1j{Z(=;qziTn9Et&1#bDEL2(s$k#$K#K_5DDXGi{*2O}r6-gsm1F6K&
zf*HKJjh|m_{j&A^#n$$Vy_18jqdo5wA4ev_5u*yTs##RlMWWkT2!bTu2qAZPwU0ub
z8=>nsnrfYn*B`7__lzq^T}QdabbNPTEF}7>gWB4|8mQq)0kxEo%O<{vtXu(CGq<(S
zTd#xOIz=xMUOO~(l@Dt|ZgJ&s<+;?h@!o|T1MxMcb1yKg=RC^uK1
z-aQqoBYqHD!~q)c5DNN;13mb2K&`P^UrFwdCcRlp;xnBq0ga!Vr~^oCKt(si
zV!>D+##@D&uUdtjtEh4Ftt8A`p>kZib~aA`XI2Qb9ZRH^&Ydy(`WpCUKzUbPA*!Dc^|C
zNnmc4bys?L9%qwvfkM*XjL&;P+uAIgnKXS-`&ON*9*jb4E0fAoR*NF}mvQH6O0R*D)H})_w4Jx1p_s!CsERj$o
zWB);-86`&vuC@hf)^4mVypbGuZH(>!ZoR?%_v%t9yO-1B3|Mq=x-8Scn<2byT5;1TV
zao4vV321e!H#Az~1G^<|G*}yjJ#u^S{(y1Fh(u5zBoMv|wb|yAc30^-AGpno?~+X$
zq&v^m^K#barm5&KSB-X=tCCgmFY9BK>i&^~tZFKx
zqO|pvyn9zfPf428bw+ZIPS#rpVIxf27|b+rA~E-rDxN$`Tbg_fJXhzXK|>u81{x3W
zJhM)XQZWdm3^3&TJ{*mkUW6
zpm|FyHlEyHQ-ANSZ+tN#m%|d|Wo=Bb&5K$`4z>B~3-HnY0_D8lFUnF+uRMRXX_li+
z%CO`2YnrIl^{7GHkdMrHM8tKo>p`SQ~z06X_V9cihU5b
zVlEk0j5SB!nJo8BXy%bRgwM)9af|1^uDLbV{t0&8OK(dD?dpaaEDUIM&@fd!NqP2E
zFY(prjNV$BzMNogBljHron(2|JA|tMsZ6`I6_>61B;CggK!X#
z?oTekL~R?Us)kW$B*PG>79kVB4IJ-^?3-}NAY;5NidlJdF)hlA$;by6uw1SWf^{@4
z+i9le%i-9JO`C0Mbehw(c(=K_zGFc(BUnJcdZ%oI<>(i#GP!S!l+wfrZ2k8pAK?aL
zJ_dg>ZT$kIUihz}TX$xn$^dGA&vdL^6T??^`g5p7Bdp7UczsweY+>5Cia-dqdRb*2fx
zeNn|b0TIeOsMksu2sa8uKXheS1P+XVCsqYv!RG_D#|&rJNx8}O2)X~LleI|ysEOTj
z)ROfG$_fJ(Tfl)y1iwP1wKHhT5!t%Ymu1!{7Adn~v8_%@@AVT=&*{II2b`WI+KB7$
zWru5gPc*e<#^PIc8_VwR^g3Q(!lku)3o&rZ1+3Qu=}woR&Qi)=yx6K>;-#Ml>R6F%
zIey*cH=-|Ja(VdjYRk8g7uqlWB@N=$1(%nBv5X1R#Xpuqt-I&e)I>)HmwWQdCE2na
zzpF7P@#vvR`0}6J7js%iI&jrPn*<8tlNSz)Xe!y4F5qN=K_;F!am9nUPI$fDUA{Nd
z>SmL=6f|=hV(j6(7*|k#A!|0@F(9ah;0pDX(5SF=h*}h=4u6
z5)~gkCUacuT@9D}qaobp(j%hrZ!`BqTUWy!U8j{k9Kx;C&(jflMB%>ZIMd~1^g%5*
z{e?PPpB3tW^!)M)Hx1uZV;dT1AHLy+v*Beina^I9sA2e~8a^)W6E=5b?}0l;1ME;H
z9>rE!JRhG;TGH*2eWI+EW^a0ZP?QQ0i23ocH=H2|b}N9e7BD{Fy3shD4@UzROzu)G
zBM1%+&z?-5P&-_=S&A+B_AJx^L8D_0F|b@{fttC}iCaq$7N^1AR-bG+4Yj~VOctrW`PpjOLEs5dIR;3%x$zmZqemxUVqKo$PD
zcSH)x;kgokU5u#t6sC*^#c-H)Chx_m$DdROhLyVJ(y~p;3^ysPrp3Q0HFdUZEu*N?
zO@?y1W)5l3n_bo}huTnIBlw#m8+mx%be7Vogyem;27YOb7r
zgzaOccYZ!C&U>@TbmhF5ofse|3c$%w!EFX$1}6ojQ|cZ3O>f$}Ea72Yt7%*5(8p{e
zl^aZZ<8%E2@BS)_n*{Y|6MMB4D}J|<$Qe3VLRXNZZ@W4vRbMBkfjYLi?MVO1j(c))
zds01FkW|UFd)2!JY0Uy8_GUd3r}d2~2KN$Q73sB5F;ap8N2gYbUni%%!LpMZZk61`
zig0BRj#pkMhL3I{0lQA`!}*CJ};E9sGG
zceV^dUqW|#6SWLDiFD^a0}deASD8Ok=(f|z`VBNb=O*$-hhJ%9V0oVa1uk2`0F1R2
z9#~Uiap{KpzAvpjzPWcdyk*C%m(2$Lt#F(@HvFOEZW`JLK=GM2aKxPiJV~Afjl0CM-Y(L2
zhxXx;rPzd}~S|@S#RH4hlpM04x|Azz>8p
zYWLN&0HXmaY9**c;9`d|)OLyK(z6Q)j0ICK$+B0Lib!geiny_GTCGy@GRnI&OWE%enOa7Yml+IJK&h7gp53LDsFe%ht(XV+x#$wChs59xXL?6^v3V|R@+HLfGX(1A@#vL73q$LbX
zQ}_a8^uVut_|N`i`o+_lELK(0=2?!)0;u8=$YPz{EzP&55f=FNrX_Xc=7cH*L>!7Sb2+^emDTp
z_z{#(N~%y#1-!Q$MBDsbGBf=9bjDoNsW$&@V9s^wT;XXtx`
zR6TetW>zOc>Zq7rf_$H)RUVSQeRc45abAC&-}eC!}&t!>e6Y^)--!F!_V
z#&*%M^MU&K~eaQTUAE6{U3O`55uv9Ev
ze2*~qr4D4YWv1Dw8(z(Z8lzr0(=GRvGE+>irY4zM$h}>~M~{CuK3e-yM!G_C&jg(Q
z9EoP%z^j7h`o@2rVgW@bJ5PE|{wmU2%qv24Ph${o5rBX!{B<;WUyR#gu^%EXwzkH2
z#7i=eVdGX4h)iBKGyy%S(Sb
zuP|o>`BTM^aJ&JHi`n*#haH85gAH&DlQHLW1VdCM{gAi>LCB}cYU_CF!nOPyT+7UL
z7;8yN0bABRDbL3~U@cS84;TUq1VPBmMhJw!z}E?dfZ?X5K@Nw&I;$HH!B0Bt#D+!?
z8Q#G$ZxTJ`@PmUfRU$a%b4o;0#QcL{2P645n^&lO{b~$bw|fQeI;;N*p4fPtbE!c=
zzh`$Ump$0}$E*I*3Z4tn0t}3tY!TR6&*V*gc_!@4Cg;IB_)Vt6*)^i3@xtjg)*QnO
z2P3sOSHqgp?^wHyb@#>Ik3%j-&t&cj{63zH;C`n&ed};K20h+?wJ0B}Lyw=XF3v_Q
z4K^&mEa%aQ2sM(E6klIs79uHx;dU=eux%F4ZKuRMF;1{IUuBy{tnZ=>s;>!Qbeb
zN2Z&Xptct-`(`3#j{yqti0lc+Bq4TRQKlclK`uUjXs%QbjVO7#sjsf^yvIO`xXZA
z?Juw;{htK!LF2S_-K*_OMLOWHv!n5TS9JXWYnHg4w<2adkNL}!ts^{ZW5
z1YO%Om?&nmqpiQ2H-yY1Gtzn741lO9LkwN}>vdrod-RI&;I%$5wjx07M$^iIrg<&D
zzi}U~ejn_bYaxe0C6u$_w45z(SSYIf#;pLXtp*5ds|$kYjYhWh+QY}H?dsm++HL#u
zayGd%%^$Dr!5!H46P=*q!IShfSTPueA5Zv>2CTgao`cs)Zq~J13+;_J?|=YqgzJ=S
zU9}PDAc*-|<*c}>QO$@YRWTT^5;gS`8h8S1!ZW)I#)lh^R`Xp*T#YK3P|iT2n9N4D
z<%mmjLf}@OrnZVuL&7ZIg2oDH;``N|!(Ye11%7$_1cDXmk>581$JmyjJkJ9vafO
z{3sD|i1IIP=v>PZ)=O_N*n>PKkh`-O7t>Z#J5VTzOcS%{bC=U~I+HQI_r6K4i`&At
zKy)@N)=9h{2%TJ5H*eaD4n520`^&H#o(@OwGAJcBzOK~ADm@(PwhfbPR
zvT^H8WhVp8FRyH%leaBNrem^wVfkU2#HS0UOi!bv67{CIYs9H|UhtVF?1@1)UM_X(
zXKvH687Giw33JOL;7z+qz?>@_yH^GTF+(?8LFu7vNo0)V_{tp|y99Kjwl(Kz+9gRVY$YB$Tr`%mucQ!JdC
z9<72tz472NIY&vuVsK;XC1~f-bU?%UCJPh1bqs;F=jFBWIllv6Q*K_RljEHfSfIw-vB}I*ht!>X9A|YP;)WZLaT*S0UoDeybW_5UMfwb
zC})SXeZJ?m#X9CThDIDYh?d8z&S_(oED$Edkr5BKua4Kl0o?o2JSes|4Tb8gTcc5{
z+4-cjQ^>C8|5#qWECxeJUt%9vFWbAN|2CXm3_)HfZc;Kzw+)Q4oT_JfveleS23A6yu<$ybn?e=Wkh|Nv_pUnM6m&)M
zhPoTZWmZw+F4d%l3wMdc=8c8$kEGaQi=1Abvbvj{{%BGvLMqlyv9Ix22@vbF5%IpI
zs5pg?dA;d1mC>e-;{u%Cybn)K`@U%BLQ$!e0BI*eyPh+_&`^s|1Qnqhpm`26w~Yit
zox>chIwel;V$}&;?b}kOu1?t?Q_kf)ljos_X5g)L_CODA)mNwBlFi;!wC`$tIDEh5
zd!k*<%L`wQSGR|+mNv%>{*i}rZdC`Q>|YX6giaolh*)8#6aH$~lqtYS9Wek)G*W$&Ui3YecPg?QGn0G(Pg`G#r6
zv`15IX&x~>Stdi-!~(~VDxFRT4-Og#I)b|%3oh#}laqnv_JGbMP~p^af+7RmLr$Zc
zt|hu{M6~bN*imJRsf+r7T)ui38q~1pGn}V>?b(Dz+}NCRD=Z=(HN0Vk!bb
zrgY!fPD}auYih83>oVz{sKtb?562WFyFKg%hSn(sD(5TXRHemJtk+A}ZcV;%KXU3cKddTg^P%%|=l$I^_20eK`yd(iw{=*C
zHKP{R0`XlM20p!v^_V<%6kFTZ7aqZDgNe`D`ke#9kUVwL#3uGbr6Tvr(xeI_BMSvj
zdHeXnxGoU0xZjGHv@;zb%Ou){yb=bS_6ARb;k0#E*^R*NRFw(n-LZ!wO5C7W8Mh_vW9^&dw4Q`*PCi7{gD8!++SG4Z6$f8=HspG)TE_S08xvE9Qu2zud}>D))dLbJa%sV{7RVmegMIubPb!q2IjX66^L#jd
zQJlF<_Nj_Vsh4!0&iO;5V_{IDlvZu^rtRzJgI3lxy+$%chUuLV{W6EmuPr4$mlhcH
znc}H(`2$=Pj*9xDCC&UOC-WIB*sfCl$AvgDCy%;~RsFyFO4v`&PkXJk^+)Z-`jd9!
z!A4t&CAF|_HHnV$^+)3Gax+uafBdB1dr&=9$$GYe9_jjq8e#a)YUjyDJXn3!EuoEK
zsO8=WG7b%dS`#J5hO_H#V=d1hH6}!?0%FK!QxDPyEXTx4Obe0NxIhnq()%F&Z8PLi
z__h2_XHsbRR0<)bTXcdKPc#2G>!Xvcqoaf8YMn%++3!u^Xm&4buIvPStz}{9PmoRj_W2`7$6sCD>oA=nZ
zZQHhO+vYvCZSx-6wr#u5*VCDvp3MAMwRi1Wl~huBQ-si>K@1M>hdNe~vbaA$Z
z;Hoo#o0O*OTvCY+AqB$f#2C|(7x|~{R%ePmvII`e8P%#ixM8BOFuY-*C#N`1d@RmZTLGZJD9Duqb!sL-11psF1FIZwh%vVsmt?-R+5+m$r>i5)2kLX1NYz?H0
z0vPV&_vv7fKK&k~avjoIIjFjqq6Cb6M6HQjhv}MdQ9+~n`
zpQAu*u<*?6q$K!<{X^j|#0rFvQJ*S`AXLrwdc-4YkWllJ4%Wz51d`DEiWhH~<#xT}
zApr;1ofay(P%|c!&%Z^M?)ZZp;Rht!@z?Y>b8y+mcV5bYUA7hJ_rCd6O9>@7ipiFHac1A3I1^I&2d%%=8@K!OlfN5Y;ADPVA1ebc
zcnym@VSzG(k_Na;C_i78g1%F9cQZ+M!QaY5=O+vtHCRdS`NIptNaDwXr*t`w_Ssnw
zo0Bw&GKDZu*5BsYkRH}Wo%SGA(G=H)@W~-pa4sNkR)({6eKM58gW>}2ZYQmnCY6nn9U5R>*2hF
z%5@w#!OpSoz`A7A513#9(!@1?W)krmC{35a3Im1ug)V~~!wEHRg+deD^?;^P
zE^s(Whwu2H0Ml`pd~*XE=^fp&;ey{M&7P?m8VBCwqcj_r&a*Hpc5I&3T4zJ?ow1&5
zvP6?T`lE_GR@_AORy)`WhL_RDwO?$@?lh#cz(mzgH_YcMyu5v6$38XDHKl+q47SS{i=5i-0u^4%J
zHMWce$(xrJ#6DT7I}m;lq+Rxnb^PAXVf0qNe
zdyJDutbUfSt{Fpr|Gsd)cc?T6*sAwdWa4?}*Pl4^j86s~
zk?Q10G0Fz6*MY*mxTsi%t4s}=+T&3e0y<3!77|3TNg?M5J$8~=IzKtD707x^$JL>Q
z;0W@pzW%|zSO6dg0lwiONC?L0tG~CWgr2M~(wGfv?;J1MMGp-6I_t7?%aS&JV1?OZ
z?aU)qsV+%SB*=|f72W|ghoRuoMHk^#cXZg$r&cG?aX}e;JSgEL@e1AN2XvDB}mO^}l1%I8VmDVQ28Xr(E
zU``bxe_^QDfly0t@DA^4S(*=k@7$9w5S0L8DEjg-v{WVW8nJY4ea5-V22MvFdJJZ9
zbmIvO$~K0|LLl_?qNn;jf2ge<;g8LnX4hceWur+pbwpI=Nxj$T{*s$2hJ0I0`>P@#
zKvj*xx)%4`?uWPuKf1l?Qz4Nst%~E`=0jG4qs{LrX
z92+aVHCwzYHdza134zZZi$3`ubkh<7Hd7j0tj20s!RWwsPl0hF#oMV9XggM?@)AR;
zCqBBB#dlodOv!(FV{U@)xD2ha&zoW1R4xVZ+cut*yaaC9xt3piNXj(Hd6XG(o#XN;
zIpMX51(aALgd7!#QNq&dPh`D@hHJ>PZ*IBi=K_>WOF=tSOsM-qht}%+D82IKsvpzOs
zzM(W6OQF%H^RYbLi_B&xh<$GC9u`OXZmp^gZ3^^8hpeUC+G-mkoBwq`DNk&y{=wTy
z&r}=oj^Aq{iUgW9mLY63Z6Mvk$kB+N7jid1%8dx_vD&mrWC{MvlL!AISSo)=EO+oaf7tm!wrkFGwbXYvOS~%t9sBR|
z%f6)?VBsR3Rk)MvGb&kIwOi(5UQo|9Nq31MKbrC$72Sd{eB5zjBAPC+F4!czUL?L0u6ApDRUM)nD
zm>Z3sltu!E6Vf12Oq?5qx6;cw*tWPqI!so*E?}aR*5B?BJJg(oYhAb_0ve9hx19;I
zn6oc9nKh(_#bMWzgdzbX4Vj7rnaUpNxPD5b|EE)i~PXM<-`$4Ac9-jW0+|L1*yVszjv5%14)*
zrXixH7bvUKyPTQ+7Sy!#$pF$a-)Y>(g7S-LyMKXgH0i~25=$6_U74wzqFJgLOGM4A
zJ0W-Mf>2N_T4Rv|2FBK8i0q+b#p`g)dui4J9L9#E%n;#ImL1xFRiS`3bgzoXfbRjI
z3y>Tu+k1yV?c%Y?)DL6}d4K)SU&}avL;JfKi~tRQ-R26E#ecj5ZZpHh2DcPwXjxmH
zix~@Ea-LUnOqW03mGQ8j&(MlF-w;gQ!UX@e@tRw0yH^k5)iE{R<3$&0T_H
z5pPvn7&}TC3$>#8Q^Tc;^xKE`Os1rV!Dn8ag{OFJsLQX%V*heVC*2rV*R|wFC);Rc
z*a>{XjC?fLUBB4>hE1)ibO1iekz4evZ_Q8Q}4OPg8f;`pDl$
z83~7wumkFtjU!ck8CfstV@;Bq^rui39aCTbSt!Kkm6h5pOfre0-LHg#tLx9p5+zn9
z{ixxc!A}9kq?qD|LTwg@o{vb^Lp^8D1#WqS>OvbiSe{J4jyy=db6NU?l&GAXRF9wd!FGR+;)$x+U0`#c%|n(nRyH
z?<{P+4+J5<Gj<4|V9DFELva
z)C?^f>cms19i`whQ~FkO{i)lcr?e3-Qjf$~enbVKFcBqe8|6MhR;;=_{;5eu0XZ0m
zgU_PJn*;}8SKzeh80ss{)_$}kuiLxX1OY11+kJ@pB(VSjsAS6Znh!qyl@sFEA@dw)E$g#_$qmE1~(y+2F;y>i6ozIG1*H2YTcrrAMN{p}I3AE&1J+Vv$@F$Xe
zRQBfTcb=w%2}k=!OF^XKVO7cz0k{!hrZ**lkW>=pRdZbKeQl}47ihtwaJap!pypN!
zqP>oMYcTB;o7?pd1~-!Ba{l?bz=}LCx+rmKp6`y{$cdR2sBs_i)x}z@72L<
zeYh_p5@ZJ$NXE8;|3h``^$O9TePw5DzF&3Gr3O#IwJm%aitc$_SGtlLMJw>}60Ruu
zks`u}Z68F#-X$rPs3QX#F7onu+w4_1M*9gHXYe^@4&#v!Aq*3tY-Dqg68(0*_r6X^
z4CmGG6Sj__bo#x=Dp44e3FKzzDe5?{o;PPvJ@sT}dU|zcR=4nm(e#yl@m(g)egHQK
znBqQ_IN(>O-OuL+6UyveQCpt~$l9e1zLEatdMVAI5D=Q0T${rlxtT7b$*yrvA@CdnvMpR8WVH@W%dbEhc0Vgzflj
zWGFl^q)J?io697B+xSWgnL-gl6=1(`6Cw2Tk$pF(pK6de>+_?;*L35W4dPV
z?V7mEwI7Hmyo#L|Meim6ShS#PNG*uz
zoLP5WTE->BoK1M8Qk4z&ficH~7BLPI3(Y!?4oG5UW#UYBQ!?uSa4?vkc^k$1aw7$^
z+|6LKv{fobRE0!UAJv^@ij&+@0LKY*j!9P0>#bzukLjbE3sNUeYW%GGqUVK`7OY6r
zz}J}ajxz&dfGl(itCt2-dIo}1dGo2P^$f4r`{$~mM14D4Ox`QpTxLU2?t
z#FwnnjMjylNf5Xsyy~&4VF2VmwkU-S>P1v9p|y_UmBF11g&^CSuW7lQr)D-=P;CMzUG&;0r5GA8
zH10O~Iu-??p1!>EI|Q1YAK2GQFxq#QlUG|3ayU#?v+{Cj`-D1P>{!z^GAS)?mG(Du
z(HM0bt*+C8acd}X)R6KnCvf^U{D9ME_T21;=*M#y{}$)D$X6VkP5jqMeKgSAI`KDT
z#19fNfwpulGg1S~A%=q4MDaTkCr4!M+3RTGaBuy|2{1T|(~05|dS@49Aa$^!{%wWg
zbPq?NTPIAdkMCT)*LQPQhb~~lJoA=O1Q!7hsWVtM`T^2`K4
z1d0~=V}iToNcV5*qUH~_#kw`nGGXMNIwVr*qfo=({R((5TbkF*JeYvf%T2{GPp019
zf1C9O(UBU@WNJfw`$2Vu4x9ArTNpNyIhWct<5o<03IxI~M?-%Z+U+7!AJLz6&7PuM
zn=CovR|n@|{br<6IM@4ZTmV^jqlKWc8BQm%&fLKq_-eYG2#Zi_uP#rg+vbpJ#`)mV
zhjWF5d9!S@NC;BFn|I$>0SBGDcWwv*2QNWQiu9E1)`$@!c$_2S(|afBx8_f+mIT+Qj8QC0Wi=jma)ZJ0REBFGQn
z30;Um_3Xb+-vXAF58NQ7SywZiV%~amS+pec%Icd9(_X7ovGi2spcGUYKN6Fv;Qnx}
zcqGn)sWIqWG!ulv(M^>`3mMjR^G|kL8hkkugA-;0Lcbv>w`X>J95V?Wl`Ncf5#5s{
zy-wx4;rEAL-k`;={V9I1(EVc
z!2JS>VQHhp#bu$#w#TGBvV`_DMdVM_c>(Ttlw--IWvQRhLf1@^sAD0ugX}^=L_FBe
zGW7OPQ9XqBK%B~Ruz&m24th1-j-AY17G7Px5AO!nX8!$~-=g;{I>#@GWAHD6-)tF7!Oc|&aF&24!pWr-(L?#s
zxI+PHM%Q%#e%1>ZV*P
zr45}qa>=@ic}b=yUGV-bLu$g$=&cAM9%G9@>9IUC%_&!i2GyYWr2~Dk9k}bfyRNVN
z$%uoJRNaV)$=eN16)#U6DB{F;h$s31{H1Jb#sT_G)v^h-#?*B3&q7
zi+-b5-6*QFqq53hZV<2s^xe~0E{ot}AhiWO{_jH?mi{_X(=AT7rId&4WQz1k%PHXb
zDM1sv@9_>p{YOy9qt@5s_bAfBWfE63olspx`UdgktYS0dEbV_O#w@j2tS8`5@MAHt
zU@arNZ#JsNc(STKFas(SeyU!Vqntf0qiak+EA<67E2Q@T3$ar@aFkr+s1BJ63U;5q
zbb}MZu;-qGbk=yTtzhFv1B(b0hcOhN|juP+we7{wPh(Fl!q1>-hEd
zfuuAB?q*!HZK?a!op&yQgQ0^E{CTn8jFfoGzOI!aZ+=V`coj$k7AF*;EN3vp#{v5n
zh!&1P-xxr*yJ)_k8?W9z@bn?4-mma(cO5As{t=zngN9$=Ric{Y>xeSt^EDQcshAT-
z+s?>(s9A$`iV3+P6u%IFmf@+NWPlv;!wz(V@EVjK|_MeO`*
z5P*K8bsM8Zxc?G#TGcP;E9K1M5ou0G3-;n!Ei3qqyBQ+aBP5_Uc;OpA-rtxGu^iKx
z%y>(Wt+|_ToLKfa0D7hXqGGNQnG61klE^nlvYl5fXhT;_Z!bq-nT^+t%aa0od0_7v
zKz!E&J1HuwWrPNP6v;4K@1Y%92FnM82xjr6y_<%|isE&w_7mrWy=rA_?^34=r!3>bbv4K#z-+&%5QAI-
zY~K6~HMHaxswGrn_=j_>85>1ymoZ>K$-7HFY*92yuqd+*lGl_JmK>QhwiyYg`n#*h
z?jUgEuTUy3jXH(uElFdvmZaw}AiD{m4VVGDB0X_uK|ldBs!+)d#cS+0R;IXnuF0Yq
zPDzE)3W@Y^n4Q-O}~9c=H0&2FV`pc#=>tQY(jB6qxoGhU6u~VUb_IOyFnt7W~2(8{N^%z#J@7-zD
zsco-iUJqoc&84PS`m9L;qiYWamG?;934!XBJ?f|HrxLZ)XMWrw9+cdWlCX~BJ^L!;
zrg+U;BtYCxpnyRkFLdlUd2pR%OcjcFNNj->aD#`Hgl+GI%&Eu;Dkg}ZgOB0$f!hnN
zITEp5FiKqQhg01m*4o3jkO;dG-pfY%{P+%6W<2tUwa=-778|Q`y
zd*0DjU-?_BR;Yoy-Z
zY8R3HlzSAha6g<8pJNrW)MMpd4AT<;n}qwqY8}O7|JbN|F90QeN)oAUbi@31CiUX}
z_n+XuzYcyo+_7w%x*qanI(f>_1>mtM>oJt)uyl{sBk<49*Ok|JeBM>xAI2vH>;}9V
zR)50wpfI`s57eLN>tSU^`fB77o|;XTAb_rIY)QP+9)T7#7vyb1e*>Xj$dp*J~7+E)%DH8D$ViOe(#u~ncGQ_zH
zGkpE|w51+`ScH|T&o3}to~Ga#;YtgAA2?Xp*lxVP4yJd=1{^BaY@kZZ#Er>7T2f0S
z^KmCXBso^L-)+7aP}>Jf-ux+XzY3e@Sq|;KIA3kcI|)6UpJH5()rDG>tUF5Lwkp-3
z1DOo=KaJ#BjJ~Vel~3rM(F>iN3c_BdaAD&9%)WjwBSGh+IiQbe=ubrxV1w8SGO^Fn
zC#vjvKZj$n3!jmWS|us_k3KTcL&@sU4I8swiR84kpBQtp6IcCN{wx+
z{w1-g${Y-dbEaOi;U0b6@%YWdEWxtQ7ZW)Z5u`&nxdq=F#Na7>cISIBFbs|DH*5G`
zOt0quauFnmOsn5Ln>419z;qHg&-3OI!vSBTQDs{AWuqXKuq4!_VR~gKU&Yh%p`N+(
zwh>!0k~?%f!w#^;Luw4{h3itf-D0Z!;T3xl5A*fEkT-{zKN*#f5E(t?ZRh~+qAaDv
zan6MJMpQfT-`D0+o&++wcVnI1A4J9CnmEYEeUYukE6R&B&ed+p*x(1!aG29Fbe_+j
zFpj24gQEz+lESncEfsZ4m>$%j(Auh#z5b-AA1l@wVNEMW+oz8MN_9<)Jv1|24Q@Ay
zd5D62M$-fppuE0L$5+2hmozkZ=_*w=kVrBc9}_>`FlKUXHB~{9Q^Eze$a)qPLmy~Z=#^KAoSI(rSC!I!2nVZQyX!mcIEwU44qr0SC;50-
zJoXc%%k!REHnUm0Tz6hOLC6y+oqT?rlO`>7a`T@WY}1Pu)^O_m!ko{D!ffv)7lP6n
zYZ2qyfXsk=Q!5;-gqEMRX)Y<=Af?uDDM_grbDJlQHrw9Q>?2TdK8-pGAAWR^s3;8i
zvjA`tsyCmVnky(oaNz3cXhFmn0fe`yFrB=4kH|F>V&c~sM9C4r-lN^D-Bjr*>*&C`jIbP3}dOn0fY!ts81q95;881@eZom(fe?kmQ57Wn_Ce^Ry_iz%Gov?
zRlJ~n>ljV*yd>6jG}eU$RiNst{HLmldECMev@0qZL6d>upik@G@C|3v(3FJ5Jy;kx
zulox^vY>UWDVzEuv&T9wGwVV9d#-5kAx3@QfC~d_XQmL?;ES~J_^#Ceg?Vx;j&m6t
z*`?n78FVq?93Ld42sS!Aq&E<|C(8mEXK>L^bh)MN;|J0w3
zdS5)(nHU@YTXUZgVa|8oqw!})&fF=|(3D)3sW?-jjMykc=c6b;fU}0~7_SfCp=7{W
zw{ZM+?gfV31G~Sh#q14*20uP1qN(vd7|b
zl^jv9AOcIZaRdnlErg(YjVcCVS=V4tlJK2pRF3gLw^S5k{)QG8`occ-GD3S?mv12x
z7O4Hkud_J7Rd=mP6e%!<52)!%sP0S)I|M?Zjj$
zXSM;GD~@X^w)8lizy=o~J?Uc@!$^b9^gaP@lhp8*P1E9eQo}B)BuXliirq?$s!siN
zafa4@{2><~`IA!rQz~UxfkusvCOTvd<-zRxPt9`v;QEB7_v`^`)AGpzBJQh-ohDjP
zZYdFV_{m8SdIyqj?ZAC6rH(P{kA>oNv{SUje7ii}Fm1idLsHG+SzIQm8(i&@0x?bh
zNB+`fa7S{0gqkEEtbC1UBQ&hY2bMZJRd;`6sz*|}3P^|%^ChMv#hK1rOb~;ALOKE^
zTX{;snCnu%-!l2EtJ++08Wp4?D~^^@Z}l!4f@+9dqke8^Lcfgf!y$-huTws`zAel1
zF#4^aqh%OcOFZeCkh8jDFXFz<%%BCtke!U#2uD@X`yjeN?&3kUXF2db)@L0~s_-ar
z-}71v#~(qU!E)8;tCzztDuEKi#5%TGjji%vTWAELd36GT-?&Y
zwy_HQM|N|il07P5PYFdoUF$~!M&!)q62cFRbqRF?P1*?CeY)_YFlPg{T29Y@^kwha
zS`jQeY8)d*_E#Krm}TuuIyFYG=;I|rM~6cF(`=o!dh03>4j0MlRtMki+T)8C6gT&H
zo>6g%ES&|GG>$~VDG9l{U3U6DpfZ^WITxa01cryo4CPy*txLHy^u|{=S2t`fTL-(P
zrb`hTcNQ%Lk~#n0RUmjXXQor}7CsQMDa+ae8Oc
zp*(GWLLxPf!hl0BU{N^?{S|hhO=8`LFLnA6oxnF=G-nA!rE;^iUZV^IULci>HNDfi
z#8B>xB2L)CC_0yt1M&K>soleQGP(J@ZK@tE!<5916l(RFRJUEZMyO7%M4dF`B@|0b
zMq9&cBwzk|S>!MYr+gJShn*?GeqsI+C1K~W3oBUQ7x1mD81b*9)AY7iLDze`$
zPSZEoXMhAP^12_h!(QB`JiVoxRM%>;V^$s1=jQEs?w6X=L?%Vxf&GX?WEz??ju!}E
z4JMFKO(W%|Zt_1Y0LTgbjCni`z_5^)n85Bsl&U7nAjo^mSyl;MFlKHR2D5SJT?Hl_
zaho04`p*QCizgJiT0sa;NXloB^a-PdRy}AFu!xKSh?M{MgRsQB@>R#EMm_D*_x8TR
z%%?pf^Faii?y)5gu2ST+S$Ly)3ksQa&ZYevxXt_3j2FV>K?W!lnAisLO9CHO`Ps*5
z^7W|OX|`*2g9amOmLvc&lsc3*9NZeDq@
zZTaH3|DMm}?wG+HD~u@X?A|kbx#_nbD7U%l^IJK7{>Q>g;fi_!fol
zKOIX@ws?|sj5cdOt>LQe+&=1T9ofRZIl1=p#4p#1G>2~>1`M{62hF_GmxJD+GrCe^
zRq*pvsQL-EeD!e4Q@qapS*DqV4U&kj;PI;4WG1dcnZ2R3{;Ak$zm=`o)_I2Rv&eeS
zKNa)K8q`R(B-!>yO97;4<@~cJB9u1?E16aSVgk54CL3jA4w)J)-kkNSBtmhJ4%}Ft
ziKAz}NuaO(8D$@CfoQI)IHGCUf2*pj5Leg_o4$R1KFPs4}RgU21#4-z+
z16rQFXgCPL9PKqg401Niw^c0%G*loks(pu*o`LQ@!q<_~4rodoHe3Oa02bI++dxpAv)zz3eVwk=ROrY1`QLN-NHRzDd)%md3_ciLZYhEuge6
zHlFDz_unes`9vayF<-bmkd+0B@Icp2L|FnZ>I}bY-H=icw<35}jhIh}@qHxkiCXj0WlghZ&t#7|cLF_3_b*GUfGd4Iu1CHiN
zD7mNj$TC%B3e_JyI_dg6Hmit{esY(#dB^4yrBQ6E8paTbAabFC5$!VzZ45A&n#-<=
zaA%hva16n}aBvgf*W|Jt-};yAw^Sa924Ei}U`$iDt78Qk`*J&Gr(iMeS{z*-19iuP
zii;%!%qS%v@7m^}0z^}qosqDkG{C=Z48ePpGLo)@wN%(7B`gki#_j+0h3_|j6yz44OBfkNt!8?!pqW|C$P^776Vwp7S{Ec6FDU!Ob(1=
zcOjt$c;Ay%#qPu;G2;BR{Qz1Q8n9`{fY~?Cs1Y^J?XaGN+4L&Fp@L+cggkw&^rB&af@am6>g?0Z*
zmXs12mZ?V}*oxutyfcI=-h7V*UGV^Kc?RMO#tdS}6|%z|U`m#i-gm1b2}k4j6Uygj
zNs}dhQ(%GQ4GSLi!lEw_4+ksXhIhIC`Ve^pof#8It?++#LWv^WkJ4KR4h_lzSe9S_
zjYZeNtxylW#JD3Zssr#r&pRO0vu_vi3ZU%X{RB`^=Di}4G_Q8dAeruXOgdBh`f0@!
z7`_H
z<+AOAz-x`?y6;58?LeqyYn`_-GcuqC{<&de3uJWbO6PTxYwbJ!>gw7CAkDy7Z+L%t
zZ2B(D+RE%jy+ORn+o!HNW{c*Pn|GTiK64~_NC!ZPEkMPc3v|1MjSHZoaVgZnu9eMg
z*U74Mh(F~kkN0wVjP}UxKv~ejw2OCs`}$g{Z*`5GtKAoxK9c4e3E|ayEnnK^U)u|-
z>@Y|8+
zT~&Vu**HJSfyqmBUYV=lOv-)PBa!DnEJY#6mVS#x9Lj`K%68j{G+;`Z%0rYmAL%Y}
zQ#d^6Fm=j4n#W$?MrDY6W;7W64n0an+DSIF03GvfPV1ZyL68Xs2eC
zjs6Ob9T9fVb+rxoPvW8b*?);yY$-f3bDl8;1d_C$UMMxA{lHg{hbpslSQGf-xrg-R
ztJ&h+5$$~5#WU_gYJQx$I!hXJcn%00#OmeC&na2HGI)wVfI#Q*r0wmpb+7M)uWg6X
zMUp5W^HS_3zLbK%av_EcZeYU(`($!HKY;EER{_gsEiR>|3r#MmL}~X19@RNW3k!Hs
zCfa29^TpDdhBj06D0AqLX?F8}M4ki-URF0&Y5oW(7%2S{tQ3FUq9hACbPvHF=keog
zS}%_6idd8rdX$Sj*Py})+;Y>D=^OK!q|umxtk$@Ci#s~-T!@$yY@fKCT&X>Q@=>1}
zSXwhg9E6nVg3IYKDH3T_LwmNc^#r}3VqeG*1gFS=@F~fVo*Ie-#OSXJK?O-rmxZ$(
zA`&HD;pB0WrL-!ZdV_+Qud6#l1o@lFMmYsp$*P`M@tG8>w$qX3#xyV|ygxI@l0J^|
z#~RnuR)K4aMt6S<5pqzJ15kXkzj_L{)12@z*2ZY0x;tBDLmvYzJRfB+b+gHP@G-hF
zN5ClCmr;Y?Yih87V{)dr6z|uU=yBzNrs_0IF1s2%x7`Z^85x6+HkS{{GF?y7#rJxZM|W{_cW!xKCRL{s2<}9b!Lzmul(G)@N^|H-Zn7wpM9l6PRA3s+D1Anu19fxTlX9`
zE>iB!^5QJq;~h#^H2|~vA;H~qWsRb8&T;u4TMO1lrg@S5R6vxi3yIG`P+43MnQc9K
zCX4$bFL)A$`KYKS@eL+a)~9;q3Hy))|28`lcc#|9HQeZlj67zFnThJRHinml9z)sh
z609_{j3mxXT!>kwzjhzPaGKP
zILnW2tCQ2c=yqD~_2Ujg)l=A72OsP*-s;xAi|-JI=|3Ygu0P*Q56HxOo?Dp@(?f4|
z{6gCQdf$s%FX#BV2T%z7Bkl*{OKJ6+Mx5&=k;m*ll$#ZsywHRP++8anPiS*7KT%*k
z>!dBxsPAF>LX>Vrl%JRc6Xn?uEh`vQ-8b`MjX8Wu8t!;R$B4SOu=3NNSfwmH&mz&O
zW^B&&BQNZLmX7oe8>99YA~)&&LE&PSt$m@n&hX*kW5ZQZl5#7bV7?1;jQl$}^ixFe>O4
zyDyXCGRS&+M7CALid%7tYXK~!6|)B*(BEUyq~W7Zc8B3@BAiVa4r+Y}r}T+Lm1s!D
zsst%(5$#V0l%#sU%!8E@;GlRmemn%PPr^gtU~@Hec45tljxAvaGo0SZ#L_~vHw`Of
z@tjw{d{T(V?|dTHnMrUbpnsZpRk9zJC=OMH%Wi!Ek0dO_S3^X&_qoI
zq~3Pz|6A-l^t`>;fG+0NOPZO&y|~y|LP;QEV2b9F*=Hs_zZ#ys?wjomD=^6Z##m4P
zfd1`?Ois9#XQ_MSg=t+z7#$+zm6`?#*a6h_ObwQqaM=<@*5-t(yYLw7oOOxWv`fZf
zEP>H?ykJ$Mg`@TZ4)95+480NTJr1!B;Uu{RcpM?%W~L#^jXYn%@Ki9Yz&Leqx`T2#
zI*rrjHBMA@q|A&^Z3WTUCLljHt4QX@?H=E*2r8+d0Qba$&yDQqaxYzzO6Sw#z+Wn{
z$X1RjQE3a-_4V)fJyQ#^SnElpNcr~?HgHXJ={cw&cnBIM^9OHDW`d$i1A#1k7Q9L}
z!{CCfa?3J7jmC1XQphUlFJq{Aah>s@df1gl@oSg0m~*E1ceQOg^gl~W6>qLWV3oih
zq!HNSzYTJem6t7+P0F~184C2r(cl*If8k}LOC?&DtiDn(OBesxD8E7V1Xr
zDzeY54HdDgi?iNh#)R|J8UWYhpWFFaW6c@&onk=wdpfPx++^3FjrN4
zg3K5)HWSN@byq%nR_+|1!g~fMOVwIGj#$4}rQ`raeM)5VNHKLik)uz9{o%O&2mX&a
zpE%Yj>|80>Tje~uJxUMgqQ>d$DF2Ox{@0i9M5|40$rb9+BkD8TdP!+pQO+T%LO4MF
zFM5OI>BLS}
z_5LRrD*ROi+FEU=&s8c`6?KJR7s;CkvD^-Y$k)G?mOF;PlB>AIHgEXD7!p{;Pq;#Y
z3#XYushI}%q^^**F2z*|OuBzs98GoVXOkm+a7NP1@*@2cleL>FOse!69X?3UWjJ`r
z>WCmqTLtnhhr4<(LJE;=r~up}9D!4n*!{-%5<4QFt>2^N-tL6%T7VnQ4&$>K19w=;
zefp+Pti3CqVrqC)v$npQG`(npFt2}0H4h=B-a=kvqz^#S#{jw|b3Dm|8HRSp+Fy7@
zttM$_f1U=Gm*L$n)|B0gICc@)OX4u^xnC366b$>j>>(>9zdz=(-c<9@ihGxo-8${r
zm6oyAl6rPv4qk~!#bm~<4{6R%dZ5D)Y*Jvf%tK{ORe&G0o(jHbV_VlZ+!crApv7f!7qYnm~HzS#=zFX)Wpg8x7cE5o1(noSRjewGovQY9ZSS!7te-Z1T%(#9CKPuQE8!R
zEzoyuN-sOrn+q155p6~~0v@&1?ON-j;q}vn1cJyPnxx)^=Ia=>!K)caZ3qoBBm36A
zew+$HE)qRHWb&k^wxNgxzQ4kzEz}upWlmBP{Pq5xLnSj$O|v-;k2%7-ENx@=dn5m%zfq(_g4hZVC+rDT{gZ>NoBdOHm_dR_tT%
z{-S*M;VbP5jG>(mZ%Z|-=t(odg#%8Vq)!d37YYKHir@k4UUfN9uWR;7H;>2TOGKv8
z1yCivA*bI$p=9J=Clpf)r>=WMc~CJ`kU|{I2&70^hl;eBsKj0eiJECIu2aTc%&1*|
zd0hUPt2nsxXwT2`G*MRK8>`s-<9`>$=AzOKH)j>#jR8~Dzy4_oy61|z-;+R<%5lDx
zc3fu_>)hCO1NQ4bpDu|$dE+|E!fA9fcEwBa-d#ao$kyv&QP%v)kOT6psI;=KxHjFl
z_)_q-sM8Z{Zdmn^<0{qkM`~d@=F$|+ycD4nnQfDgTYXPQ$tjdz(Dd5mqdq0A%I+)z
zFp&ZdV|6L;``$wjo2}}}^+erma;u=4jXt}EC)`zT+JDj#F01@ueb`n5uE`dcvtBH2
zj)ugl3`~-@?lLv^GUme=qe3a83AhwAcaEN=po^t5M8k=Dm77JcwUf8UuJnQXc+aE;
z$GPRAoW<=xwNBYo)mUkwWuz*lc-!beD_$l`zsyGFAb+9VPb6tG2FqWpCDY)Iq?9P8
z+3}#B&*aXY5o>J$@)ERRk8UK#7N64%*C`9$+R0cm#g`R-SW0+pADpmB(WtO1ydMnp
z%JcXhwS%h0U=I@zNKKGVHvr>)kJf>L5L+60Wnt9e?!+M(Ah)L+
zoEvU1LRXnsMlmCU(gIZ|whPoB!2yX*5IWF25iy*WI!Z3~TaWB({?~ir-4<7cNK?*3
z)+J7#kN>3eY~Z#QN%tno;mT2>EtMJ-%wwF
z_vz6d5@;R>f3hEp_=xXE4n#3}NZ?u)=3;uR3&c@dk%)W2+Xu7B-x>~V_*ohZEglI!
z)er#i7&IDYQXesI6^OL0st?E%1iNUKxak%d7+9&kG|DJEWOsh|VVfX;@Mk`j#)5Cq(ISxI%pkX8>AGJ2?x7=y6fie6jaN?}VrZm~PGH9}h}E4&9KzmmKXJ}Me{<~L(R>-l(P*hv_N
z%`g+IT0^PDmK5zM=xx1U`b!16Ef&VNvW?mkFzVci%U@q_`m{Htd*$rI{qPYFO}}rB
zp1+MsoGI`72MSk-)H9HkxuUuVA8m8y;94ICeLS7KjIU%rI`y;}T3`c&4PB{X}RGiD^2%|%jzm+>Z0hCSAFL$)8kyRU$Qcn
ziHr94U6*0n~ur!hQ!pCq*$qfSPHXv)>b86Lkqw
z85sb|-#G*TV3-8}$bTunf%O{z0Kj>G0KbC$UHM(h1Ny(O(&qvH@A-d;8*J9U&juqe
zAuOP54tk~GVXwM`%11|#CX$GNFAr!V;D8cI*jxZ1qFtw42U;8h2eYn-&N*KYgiX}q
zj3Lmcj;;+A?jnr8j!&M~lsdGIgqTuIZIVzR9G*xXK)v(f>3g#2^gjS_K##xQdm*UP
z{>%OHy?gIje&=`2z4yJBgy>{DS%Lqn0>L-&o?ZO?^U~>z>(WGn(v^N;
zkBP^`S814=41Ev;GKW57E3soadXYu`X&%}C8Q_L;d#MMN&+l1-heP0QsBx(yTL0OI_GT87y(^DD7@gy-9TOls4
z?p&badO{SD3kF+<2bp}GpWue!`7@7f_jjkn3ZzoOb$}NT7gRx%f?ZYbwgsZOGFYW?
zW_Zb^!C&S)z!=SvOEG!1bK8Wm1j8qxg+V-v8DwS(M@1q^BoJiK)fNQ35cb)-YOoah
z(g0xxB5KbzoDBSs6M7?SdLaxO2)MycS3%2TGP`M*Kjav5tU(xCYheTQY;aZ-NQv^}
z%98+q-S#Y;$#l+F29R_B1a?9eT9D@6&5?+bHyz?f_O^m7K_y&aB=K${bC*N{Y?p5V
zq{;{=A7ChXlc*h&03rS$5h2OIa_5L8u5#83c_c`bm77i7hh9c`Z3=1Uns@0x?{Cv&
zS!Xzk$aD6K@cAtu)|w^|zz{9X+XCz`^+0i=APmz4IQ&=`lL?+9ZbWk07SNa_Pf*(~
zoh26b#L@>IqqR>j6rvC|#Q_I|V>zQmEpZ0KK#V{dU*{y_coj^q)igiAVjNWqHPCpG
zJWT_}jr8Q
zPu!j{#sjukcS*`&LWY(|K%baOS}P4l>^~)>GaV~92r94zWpn)aFYH>J(vnK%Os3qT
z0>qT|+1`)o$)UGX?cpzU+c~+AIb?@E6_m6S`o;
z)lm6XcIQ;uzj23b8Np;tR$dOZ%squ_s;ViSN_ks}3nckbhF-}7)X}#YMHfhVFvCE>
zxdLoucNfU*Am_DjLpLvdf(kmd_ZT+V^Un`y!@}h>^r7*TnHAM(?X!!h{QgqG%WKz~
z28_LddR==tweHkGTyZzr@%Q&=)gQ~~gJr9P2V&}1dCjif<$3!7ypezrHwVZ~Cff-s
z!7@~A^x{8Ihwf*>4ZDLH8yo5D%lpu%XMRUH`KO-Hcf-=RX!dOnP+jdY
zPMFP@Es8q#=x)zD@gVc0S#67Dr9>mA3T^6}HCwErk7pD>+{R2@#}ur21@d_UD3{ERYB$)X!)P4e67
z5bj1L_YF~W8lTqfAlcNNtk#Y28jfksx2YSS|9BL@BbzB
z9DZd2*}e2???;AO`*N(H_NK_zJ3rDo>naW
zHI-E~bMP42^yb@?=6f~bR97CNm+qNPOQt>RV+{WFXwgNtbFWH12ejh4eYoIycy;4z
z@X^;&-(QtP-aK0OTsi&i(HBIIC?PLXZOxaoWYS}_e5#T-#@oZN&%NqW@BhZ5&(q-p
zhg=+-ElmQe{o0H<^n;s*Q+~T5D(cvtI`ue
zqaL>L!wEac^r0!Jkui^~pmE`GD?%pTK>Fc8xC(nRY
z52R3Q%xxtw-u&8X+QeT}LTq8gW34pzGUi_>Wi`~sFcA{CIIukj_s5h5jT=Q38O%9Co&9km8mn0vWp%<8i9Kp61*(iN?MBIJMwy((a6oG;YD8
zga_HNBeha>6f53NZPQxt5r@fXP-hUmoU>p+cKhG3MK;KwNv(l}gz)7dzNoZ?kOYBg
zcF?=O6YLv*k59g}Nea^^&fh58nvd6iXmpMSPPWQjU!N*n%ay0Q}L$8zb5zv8M`)JJz
zi#hLrT6Zj_-27HzkEizL)fF^njj1<`qYW$90#Y7|h2JWAStjm+
z`X$5;c;B**LK}G{slj2Z
z@~DbJ9#TH2QgKgSeLx1ugOK^6$4ruT3Bd#{CQF4uSkja{Y!Y`N2+-El9o*R`ySRdf
z*Dz+bhOkhu&@mEHop6#0Vh)nn*SK3He4WhvtRR{Y{1gun%!Xa6Q$aXE
z0swf2ljxgMxF`%WI`KI;M~GlW9I03U2`hT`vtDksJOL$@;Tp|_EMuvi*{HwRX`ELm
zXt@5>y2^Fp+{}f|zP^pm>vmo$2(Dw&gZPEC8}F@rCV=p=%wU1-<}1itZ4BB-RuXqB
z1|4Maw@#MfEueP$bR|HaNKZ;tq=~E{ogZEG~=t;O_43?yie2?(Xgm%i@FU;4r}Z
z``?GVy1MJCbka|!s;iPtQu&Z5WkqQ;WFlk$0DvYdBcb{q5Bwh?!vD7q2^&xS$DmwP
zrNscXvm~eg9VE=OWX%;60N?(T5dlyURsh)lsr*Mofd4I+LMQ;t|AqXA6+-{tw}FK)
z|Bw7XMVWY54*)=bP*&oHx+m17pI3L@FSkcwB-zlwLSto#fnbVajYx_TaTJ*s%Uhg=
zV%1|T#`HRnnzDMhYD*gV5WZPz$NLXB$>C^mT;(sO^dZ%79+tOqmDszwt
z7I}RqK5ZK++JimAR6#EUl+d%k*_Lsav2eFxUHq~`dNIu5vzdyf@z-T?KGmZHv#aQ<
z4JU0(de|2PM0FNijbzNFMto3nob?uy=)je6l2sP-7y}LT*nLavX~YWh$Eg{PeX{M)
zfjS?&j-?R;bP;uEF|5@2oRiWc*z?O0xsmrH3Z7!$AvGwwEb4t{g~v+hj&jy>!M!Qp
zfd4_X^wH@nH)G74Z^;GnCN7$Dt)g1Ld(q*L_)xam3nr5PV|ilV=|AS~FUDhoPcMJt
zWUPl(dBJFcHnDV{^+*{+NluP#DW0ZX_Y~Y0RCFDl-9}#8!WO5EW@BVMC+To`51azl
zKVPPy3flKBzH8|6Un+lfqrlG28fPg_??=E*pBNhqE1EizWudfK5kZrBC=XJTBY(Ri
zfO}F#AsOoQ{1*&cSD{*C0itB0^b{Xf&XLUA&p1H~h#Z&G{L1W~5^yB(K_(J^)xJGV
zDD7wb@m9kE^5!*;RAUid2tPWhpNUK_vn%;$bJcCdOgSC({oS=A(#}|c76g~{xU!rG
z@HOL}@a*9zZF`$s*0iow+{qvK;Foa0WX)l>GE
zrUJ07;?8nocV}*ua=R?G=(AhKnuH^zpI1bi!hv&a7&QEQ)NGDWUKoLmu?!&kp0e2M
z=?s)hn>tm%dpJk}4>3+rLI7ik+(vpfyKv@vxh-z-)@R?Xmnf0C`gZs^@z$u0
z32JoYbzUhFKmKOwBly}j3yr;ePZ&Hgf?h5rD}7t+oF%-H<=!WceBK^C1bMX+Dv6Ru
zicXKoZ8e6An@aT6xBcrAG9ko``qELUnV6|IuY$9tC!_Pc0w>MAzmb3Cb)?3l^D#kA
zyT+{ldT(Ip?|kK3{O703QFWl>V&`AG-p$m?jNq-&(21r=KB_c&WH*)?adVDuRA~$J
zbr}-rRA}lonKv~kl7n5Ad3v`&S?-}q^a%n=cs&Bd;$$&EJ#W-I3*X<^M^k*HLDVZ7
z!(qaX@&?WkHP^_LDB|U$J>Sv~riqDkdIjt;9m?#@a!zV$?g+IYWjzd<08=4c64W$I
zzyg!fJT3_8jdpABJ@EJbchMu
z#4efZ8)f&{jO6hFw00y3VCe*$8{@Zve`Ed`4I_U*&c9usqOu#3jThIgyWJuj)8cG6
zSdPld7+ibV1+!8i9LJ}o{BZ`CR9In$G5rG1$!?k`cFfh%E-b^WD}Ap=aa-nR@^ycX
zm8aWxiiLUeteD4EQ!L8aACkHG0-Ue7WWAMvj5CtfJYm(~4nhcJ!H71*h@8s9E&A3&
znPScH0UPe+r{{)GO*9yDE#|&s{>@Or-VqKH&4zbg1-~!%ZRF!crw;|3vA=E1M!2^=
znTX*?PUXXAaUV3CPS-h6jH6P>ohu6%=p%NFZCIlGg$X23V44(Aj8Dq!{%cWsHIBuD
zY+7>b@v3ikm`9(#Zm1kgNjJFh?FN|sU|g3H>U>L{&ExVXt1fd~ARNaVIdi|wgNK%x
zN28W)}
z{JDw*Z^y#l1Q8#n)8mg&jChh~Fr4mv9?H=>0C&=P>?`|gY2_$;ofg&@M0aa@REf!Z
ze;!#d{)f6zJ&nk^cBkp&zuh+T9GT?g*kN_kuStZ7zWpvx+O57HwY1K1j07+dA65lK
zlbNo5ifD%#=~?r1mr+Bbo~7$Aa$9o@y!^cn{Ip}cQrh6)$;?LM*mx0h=Qh6^L?mDZ
z+E{4}xGh_Qa*^VlLpUwn=?+y$_)n_B=o{2xdmZ3IJt0O(wKN4|c7xYqjmaOlFNyi%
z??!W{He$r+jwXstD#h~Vm!NY_ij=x~6;!c>d4=v%j1Pvn?JYgU(P=GL{7^^*k0^Lh
zekPv`hZA4s+4zv)aHl19hc!%iLMjd^DR+w+J}g#}mt>u|tLMqI<^Sr`JXJWdb&|_8bgLg3*&Eb<1E}M&nCp=^6;z>gDxZG^ROx7i~Q_au8
z*Cxsq1_bw$!IClNy*H&!z6C~lngIVSm|ZPjlAN!SGUYP!Q=|;qnAm=-k?$FAHOZV4
zRo*J|n2iJk9O`l99U{OnIv}^in2Ih5BfYfzi#YbtFp+-Dk5;(;d5p<3q9-&b{%ybZHzdGGQw!>*WdN$Sq
zPd`XK2r6Xv^)Q6Q6t@0SY2<%z&##vyk?g!O%}-%*9{o#S+b5#&Da-JodW
z1~O2{CZcA`g0AHFt)#hEqj*yaaiYf7U665>xPuc+1>GC}tv~u
z{?_8iPLyUTbuLN-kB(uF9cQBadLh>7PhU{mb{|UOWNoF2MoC-Y;MI_4yc8F3mXMD^
zD$--yWj$U9t-%DxFjFc~C+qieyFTIdsw>6rQXvPX9_fKLF$}3Jo
zqH!}-%m*h()+AAu*X<*;9@pUhAu`}g$JiJE^uU@X=$GK%<36LejStU?g
z8zE(~TZtF^HjDju3yA5{KoND8oxkTKbUtpku_`b2FiDxC;u5~EqgiO59nA6m94A%n7?M9-
zDtB`7bxCf=L*|U_F<@7Q{Y(4nWxtQv5WXxWH|NG?Pw8jV#-z&6GK?km`q|ReeuQp6CONm26{#gJuDIzBu$_^ePJ%wfit}lb_$e%jS2E
z#7L-I9&0R#kJvG)Qw~L7VoeUMyjAAMH`jI9cy{*9)d)hJPSf2ptOovo`1a@L0nD>#
z1;thOMu{&w{gZ;G{{Z*K&^BlHR%QvT{>8R$+dWfXAT8%Ib}wKMD5E@}TF-g?7Ia#s
zwAL9}r$J$}a!VWVi*cOxxLY&H0Uqej68n|tr^e*1(pD9s6@NFmFC1b*t!@9gq$eJ2
zw0y5!>DSa@{VhO95$0jRVcZICZxg8Eh>nwF{SHtVD;cGm`@$!=vvGnqd&}Tp%K=sA
zQEpt}EBxE*3W4S0U3f
z#1R$#p@$L@{oC%!(MyuzG~1Nd!!{1Fvcp?4z28Z2n4MeF@w_Q5Zi-HLucZCHTJS{D
z-2dWs1O}d^mt?>Gl%;7ZKjQOGuE2*8yyBJ-ouvb`CnF%~vFH@W6IDP!Kmr`
zDW@JN^Ce20pr!Szh42LO?BNsyDHmnnZFyOeX7Z%@8sZ5TV
zYy6C`puAu>f{*9=GgRmwOdvn<{B#hIN#%Lnkm_Y2)g6qE=p|08L|mc49@-@HE#nYi
z%z?Rm;qg(YQgCM_pmVS^(AutT>N;|Vc%&kdEavInfyHTvm8iH~AD9+!DNYx7G+OD8
znXn3P4^U(0!^W;aj)Hm9^E4l-3?=&Z!z`F#<#fj{pOqqOT^E2m@Un}@`8)SRDgii(
zAALJa>3fnv+&D+>Z@og!8AZZMD;6iC@4IgIIC`lnxaaTk0xi*Z8I?l9KVH*jGr;d`
zS^!YCW1z{u7|iRyu!eDfMoJW|A)MN{tg*jP7EIQI4HwEWCpiuzmPLNjFqWsp5A{aA
ztzhND)ib!CMr>T!V3j}F8w%4vDTrL1*uB*1SD8Ku+XR_L9LXqJ-g|w}J`Yu-*`9Y>
z!W09_D{;T>lfH14XKOmTF7Cl>VA_xN{CMR%er={ZuvAAdfFck$KV?s_9KsuJi9-G%
zv=vdBiiwjUf?+QeTDMgsUH7%HF#bUP=iONZp`8`Yj`Dnj$dBT=2rVv+BF4nU({92P
z0{iGXLKOW;slT?B83BLZL&s_i<1n|A`EW;{^o+F688e6Rw7(Vx&jd$Eb
zcmVTJc|kpq;YLQ>kA%v8uQI1$Pi#CvdDu(Bj^H{IhWKPF-(4w{S3VKepZO0gUov>V
zu}@34b2T;r_|6%*k4_csAD!Yk*L?gpuA8a5f|uNb?e^X=ynkTvYID#DVJ7&hCf&~P
zkeC|1Y30U?xPq}nixU(bci}1GkzP24#IU&WDNo#Ei&nyAiRIND9w}2qM!Dp3i6Wf2
zUQ6TsUg`7ejYRFC>Au`Dr}SBj4zlALJc3K=@75$%V-L+Q&^;zoD?y}m0Yx?MgAa?Q
zWv?Bc9&8<8QejAPVZHOgw*X6CkLZo1^zKu!tZoM97^qvdjH>@)>8B-c&X9mH74?#S(X8)q&363O-&f^kh?fAC?OD
z3gAy$OhlfMMaelvV5D)GWUb=~s6u2}ilb+c{tZU3<%2-!L|@}eEPwY2c81x$cN}aG
zh~O7AkY;F!B`c6J#-bB$6Gv%;5B2*W4G41j6BNEJwOwksLoj>I+M+Kf9rU!w+Cj5|
zd$?J|x*cx!BS}kArsRlcS#jRu@CbG2B*D(L3lyC&Jb{SyyS}j5$f4S^469V3rP!fA
zHrF?st`^fa<&j;!&Ql#{W-1~tWbw+AE|u!|M^y=;
z-UhiFKyOAK`^(bzThDdfX+VUNlg{p}LZcjt@l&cd(=q5kLRoPdhKfwcL*G*DrI6bZ
z1~KqQ2?J)K3y$Z27@>eFXPhpwiGA@s-H)oKavZ-+NvqN3rUV?&dYnbjL1sz}rT#-3
zd%`zWcyw6r803R7Eujky!{ZK6UOD-%-+y{l1N`d{yDvU3mL1a7ww;u`NxsXPpfk>yIh`IIqs-#WP)M=Cx7Db
z*Kgf!u24At)ARjOK_C2-oY4zgM!QH=>Q7gfj*_#oi`OiS^qHOe&MHzat;hQ%(4ikX
zlZU~Jp&#VbB0rXh8PTz)Q3`dM$79`u)P|YCvK!_rUe7GAWld^8fpgeIKU!iJXV9_DnXlZxWRS@%1p;x}bv!)E1T??~%f$Y0A#n|P
z1x%Qe#yyIAu3_celiAS^T%RjdgU<=4cc-{K$L{Alx>SMs=PDHCjT{`RM3`(or$R#X
zRD_Ul%^Z=HBqDG*>wo>f$B@dEjt(mWOxz~Cec-(-Rc4Y67pov$M`>jg#MD+FZ;dL%
zQoo{qNF643;xnjxyPv{pdm!qjVOjJ*^T#Ed7IgUs=oxYL=_TiSi;36X0n
zD)&_Gy2{B&XH*m>H~$y@lRUhdSQ8Hmr8SyRdel8;CVT0`E+*>2Q8}TzqM!F6`^c1F
z^yajkJMiZi05BtIgI^41H@StCLjB$$FU&cvKRl$(ALvseY3N20YIsxstz<*Eqmlrv
zoed^Nf7T{0w6Zbn)JCwpo0!Lsb5*b8mcWPi^Y`D$7like*zt;~88{ckq`FjsF=sw&
z-*aBl67)1fR1RGw_9Z|>jqc&9zR;i(>g$0guBZl6J^ur;s4~3Nny@YLsgvaTe8)+H
zGA2#SeOZ=iR_xH^8ov)FoigQP1+zJ^-0SXq+ezvz&kMU~v!Bwlo;JqL7NLWW^Bxcs
z`$Vdf4jK4#W+VjRN?M>CbtkX9pKwu>(U4E)3@V#`Bu4&L7#v*{tdhlt$Nbv-Az#B;
ze@Q6{$Efvc+rMn%Huop+KQ*kM%Kc)KLa;d5aoqjzzG}0-Nn*X8
zeHlNVx<39_kXoYAKSkt4&!%c5n=0~}JEe_tZkf9!w2CUe8ce`HN&-}bkr&@^`yTGT
z%q)30~aPfirD~uMw(^R;WaW=8thGweh)2M&-;D?
zwEEfISqUrjr3l{2Wi^d*Irg8^KxFAS-NVUDdZrV0WS?D>9R4Y<6|^zDA^fi81$TTo
zAh?JjbD$YBh?oXf`&xcOu*ly4;N45q~fn>
zga|YF$43;1*-)sxCQ9jgQ%WY>)b)07&&xCKbItG*656}xvP6@SMo#MU+Zk7wJq_g!
z4jA`$oZZ|P-EF)a<&7;M+O0fcyDf#Q>`VN!8EIIYaa;(y?&^g1^Sr+(@eX_i5~U}g
zDv{mXD9H}m{jg#L10{I0fw(~xJ_>vec=au2yY~UB1;m60MhSKeC$oD|8zRy3?+J~V*_gAMrXDJ?H9NxrgvTZ=~87bRvQBlE@-K>m>7+Jdv&&|KH{ABNG7V)vk
z!*^$tA{UWK5T14GC2+n2sb-9HYMPaYzL#Iep$lE=n?tUyJLKl?l!5fF&E|paq1(|L
zIs?x>xZscT??5*(>!nq#o{JkEpNz|$hYS$hf7xGQY(<3asTO?K)Tdv|d#7u5dk}CF
z9B#21wp8;+iOnH6wtzVCvHX3H1xlMuM0ihqd?
zdAMfN^u+u#_AtMsDpia5gm0>DA{L%DjO*wYos&Ct4Pwj{=Frw!v+%v6ZF$4aHQKUat
z+->o~zsw?@dB0_yVt9Kex07)&rAvgY{kiSj-Q&r>9kF0G
z2u5=oPnct>+p?n*f>T@lN8a*1=3#tukmY5;qWQlPKA%MVU)8XnH!yBDVUnuNbwD($
z5oa-d#g6=bAnxz{HIeDd7|n10pI+y=b7>j2Pv1^IwIa$qBd+hC$W%Y-9h02R6=$dB
zx|*K+T)cJ&rR%^w6Iw4q2o7=q7d5OIYnNRS-$u>W{BUA$L2DZGI;L_lu^f0x=W+SKaS5D|=n;zgjf3$%X5D?94iWbQAIQ@|
zk3TnPpxQ9DZ7}OI{s291-Y+yzW53@g?J3_;%WLIIASB{CYdi$x>ZflpxxQ7sju-1p
z(hl{FqNErpIila)vC?sl6sC^nwK;V-!q)Wv(meqs2|ubZrf<-;UKs&@M2J4)-tRmU&f^W?
zeRtVOkOdu3`;BcK=Pbt&AHk@ft#;khZq
zv!xpU-1KDB#M;DH_mhc?D51t|n=bb@qH9d=Am}ss(7w9w28F*e4&!+kh?r0vjY>aM
zXS%Q?(i+UHn|+s{0)6ap3km8DQ)MLg)j(TsJl?_&LJZe
z!J(ttw)r95?4f1s6WuUaIGV>oahS&^-<#^Ae3ibQcgQjW<676CZO6b$*t+k&as(7X
zm#e1e^GOMMz5XZ_bR81{RZ1%DpPM`z2Hkp|-O^2lcx>s~zYfeznUxzBN^ZgCBJ^>Ih>RmTTjS|q_?
zDJRYdyEz5*XE%pEB%9f3=qU}{jrKk_J?<4cbl_RAOK#AksSSbMW)iFRg2|!N*w1@e
z{s*kR?e_tA9VEt#2xB!lyiju6GA|Ial;{y)ufU1HS049O-qpJFaTN(zf!lA?KGm<<
zV`Fy4MD+;W2|sA!3rIZNUnb8V88r)hZriUgSRnVBJ@AZMZ==_7k#Lh82A<4Y&9e14Yq&5l2oVYe~;
z7A1cSjz%8uQNBn)b^QqA-{S2wQlUENPpxVXwiP@u}wyh@Ib
zu0NXfd{3NU2kPd$(^bM~qYhil4K?1q!ZDakoB2MF+8cq&ZZ5aKOG0*wp-cik*EuJNciQGM>(E<$-&;Z3hCAklbdgQ~
z_D?9g8(a#2^X*2pV~tKMmnIWQcBYlC-|3Hlb;!ui?gh^4D&i?Ga)B+R#zZU;FUx@m
z{O9NrvBOMcooqjvpSs@yrOztU^yPVv=4hMRia`}|tPlA*_o4T*{{W?w-v;F1_Z{$B
zgH`*kPCti%2^og|cW))5B_>UF?}}EnZpz#T;{i;8LBte!`p~OU+U?3&sYjV7T6$Gf3oiOi8#|BGFFx&MkmQ^k(H4@H=^Z$bs0B|25|ScDqbvZxU^DHlKqaR~sbR2)H$6+hT7?LQHr>?d3+6>Yk@%&wFfhVjm#AazmD
zbR@r*EF%865+IS_zqiX6m~64ZjyZrhXt^kP`{wiu@kN=e)eC3cFw!`FCe`6SH{^Ot
zq`wJ3U;w#dDrUf0qq4yo%IeM@)RX~>rYKs-<1Xt>^UZn_MIc3lWPA0Sg*{`^lbOIs
zxI^h#aVX+RbsU;1s~@MdDA?|HDi-^Ls`OG{
z*5*j_R4grh2Fl|{iG})-C2pI<7{9EqN5kp&)X=fscXQ$+6iWuhA@N-f|1-PG3@2qV
zg9z_x#a&-E5oY9!$5o`iFqvVwu)LkYBpAnhZW-@bqmOUCLpjjdTn83xaFR>U_7Wwq
z5wt^H;7myD{bIz96UEhR%w?Y-NGZzp^Y`EPVjyVgyRYyqi9m9T0}7wTl_8r8g@31=
zJA8DOA!RHZOwl6Oe47e98OUh0^ZDX%9lydoh#+vEs5x2;Gv@62QI&JQ8m5|S4XvE?
zDQD2pAt)^%7(B;pJ^hvC;P*!fpSZ9mOhrE;7E*_!Oc8@(d|GDoxflY*-zr3wp)I-F
zy|D(1grDb)2XhP=q;ot!c1t7P&w{DK@vwD9r=i)JEm&MvOTcpW_XoV$V~-1I!QN->
zHaE(8_Za)cynAxFA{
zC~-R!wqOhwiIOQ+WKTf}Clr!(vFtR8&LqaI=67Fhk7L}meV919huvqU@!o_sFT%C&
z&UNhgp>aKA1b=1r9~1ZQt8=88qKs{d#(3Yq$Kg^r%x>&FROc+34(F4f3S0ciTI92r
z!@!0*=ocm%R;XpBH>(!$m}z_$cCa5|jCJTbgMXoe-vREmS3e=M_ys%lAnz(Jckx{4
z3=+6dcHj8s;IA7W$Z<`CD)$^yAqW^C9qpGW^AoPM{=pDOT+%m$Sg+j-&QC<3syVrm
z^EaB51*h!G9W~8Dl2Zn!{H~PhG(~|*#yq0$Tv9+GNE@D&#O++sFIPbka_*wPZM)Aigkn+9=
zJtuMIxHv&F?E2jJ4!g?JPy30g-w$h0ifF|$`fSW{hsjWYH}ICoN`5>^)b
z<5dU$6U@oFOm25y8KLlO7C)!w?Y&`ot|>Z{Il5fdIbzOqM)bK6@bVj+6{GZR2?0`V
z3K1I*$ae}7Y$?JntHgC7T86g=;87#d7MlKq?Huoq8T8Wen2^PreRzp)=b#ZrP@(6T
z9fZ{w3C(r-VrVdmDSuu<6{=qb^c_2egwF87qbsuHWWC5J+Ct!GX+C|k>3}31Na!C|
zvLNPy_e^`#mgixLwj1F3v>BQ&>%LuqKq1LZ9BbTpT`KGIqU`HrHhZibSetQloEOV}
zm}QYjg>G-}yt{Log{B=3@uZ5dh6&+|zsq!E6sAfu1sdswilW7bdnZYyg%}t=HI{EK
zhpcKHe3Swloy(~`r1Fwt7sXi+Zl36FYzv^qK=rq{T@n%04``gKI(!_J_2VDW5?N8EEq-)z>P_7_N
zv=b3`clbL3M?@ID$beC7mfV;z(L_wum;_;+9_oY+UsIAUm6d}dL;#EHbh778n1p_*2;=X?4ex%9447T)|3y
z%ZnXj%NCk3C}G?9WAqu
zu)#`IXdPIpZS)z)|Jbi?dgGHE-e36(Q~rWt&TdXS_ViI&
zpaiGG8aiRkD|~;Smk+DUDs_5jLnG?NgOM?xl+xdd;^X_K#OPjlg=36BZ<;8AqO@Nz
zd%Wh9!tC;IM6k}`tJI-fXfEx^-;YTXN+)AE;$Q2N#62;O!{zGerMs;@2m98&T8ViE
zitv4zxuNc+r~6CS4h*MaH{cDSyv1F9QLjWHe5r!p`^HzudPlG%u}=^Y=>5&|-wO`&
z5$Tt&>25L9NppIr?*`C!a)RekY0SWrBX-`bp_}K9doD4Qzp=(e2@~b^s)RUosR&L=
zj?V?}3NLHoA7wY+U#qxH^f-<$z=uE>rTsyLn~g2lBq^q;ep0?0hx+aIS9nP5-HbM^
z20hB$S8dlBEEN<{=mzWyv1k?CrGXsL9O&qq24?*4fRiE0dqqT?XG_ZJC^UX@6NKN8
z>LTS|krN(nAhZs0ZPol)=6cCp`3R`Z@h4FIOUu
zgTGz)q%JyHcS+(?EuT)>9WRa5|Ha(KpBvKA2BHUn{;S_pbu1`HA_Rxt#~~JSba#v^Mhw
zM`O4x?I2T5kD+4s=MOD*`a$vTN@*OtFd|06v9^j^h1A)IT>8r?5l8M#>n3nCPj{_t
zbimhW!`(xVXHWdO(F_*|3Po>i-}@Qyq=HCK)n|`iAhrkRvp@XYgWwWE3muuhy72pN
zk8}h_Ng|!?zgNL!Pw_8E8l{5#7rkaXmAbX>IdJPwHWo-}j-Fx$tP|gg<${2CRr-)C
zc%~Ku*I9mn#!Byar0J#wsH)mc8Ha-AvLxO>i}o=z@+gmsFVzEdznLqX4yKfktZer;
ze%^+WKZ&sMI0wYCVSKVAL}S3%k$KYvDLYSkZox+Q-q{>%!uCOC6DBiu-aQf&^_@R!
z?r!m&2`x(fcZK?2K)%qB`G9*Y%+5#liI1muKUv!$*Rts_6*2c;WoeFXMZuD$i$vB;
z+Q=G+!Nmj2)5h5ZiSyiFyxWwgEVr!J_%?-C7St3Zm}`pc@PQ8DM8CarSa@1=H=SrT
zNh;Lzfh0tH^ZBp$U8Fmbyk~#N8I|@?$(Ie@M=wv`LVm<3@a2%5Ruq
zNYXP~EH=B=GVA
z)fMVSMDx7^XH7eR>L+w>Np{$S#cvYB*^RID;w1HMjqAChd0$sChKDTG(Qf{REwMsX!ck3+R3H(Cb!Yt)79*l$vRKK>90>*_
z`XbJA<3+oSs=8FZ&Q!>K7Jga1AgBf%cn!<0_v6>ytW?9l+T@21y+YdZ|fi2dyVI@kozrP-wK
z@7QLCJWm!NRTo}}SCEbCJLH@tjzpbkfAPlr9wVcdO;o@izk(zXP9{!CN&+s+iY958
z4$B#yYdBdp4RMNtdW+5(I2mDgQ@3u28?Pi&uD3{Ge(m1>bs;4!!0ml1{ULQ?VqBZa
z%-yqJ+JEwB_^*O-Kqe=UT+q*FR=eDB=Hzd%$CD
z&yER^tgfTQsVR1H$UTk+WdEqgfguLMD$R96jfM;SIwI3J_vd}G#Ib{a_+0#(-47F6
zryZ(A0~6YEfyQ-^ts(P*U?b+Scy{oH#TaGnpcY(m_*z9lvJ95{b
z_Cb1slym_8E7c15p$*?1*@Kz)jCqe_v^Kc1IIJy~G#DVm{f;P>`2=2~!Brd&=8AS4
zuqZ$u$U(He(<9x~VMl5)`k!x;nK*J5=(^*zol&5!;16L<_Xxx$rcp2%2fKQBkIQsG
zHs+Xcp5qpK336fb?az27Z|S*aQMLD19|XRm7+TBi0?q@`C(nMi8kxV?H!`Wdc*<`Y
z1%
z1`SZ4#;lg9Jq!U4<12}i2oHGXcA)stI;@l+GfE7VBf^9Q4=;4jB)lW%ZXU?!5N59-
zV5weC)xI&R$jb2ZNArn%PuYCwekmJ6rArJjUYfxrhr_Yj&AIn&AY*kIUXdU73eshf
zC+quD6G0(*stH$=+k4@yPeg^^Mutf@Djt+`zU%KWdBP8)gm#ihC~ap`H2lFHc1aHC
zdtw^sGG@(VrW9-8TfEBJzFfmV-|M^EoUr1M2+t;j*N!U60a{fJMTH5-1&`WkYr3;8
z5zeGSoQv^p$FEWJ4*8bQ+YQe*-{{2qKMUwIvI~r`v^N#@YXOrniNI8|%^GV~TFEV@B~h2`*~GKd@uNGkWquG~SqlbL;GqRfHX
zBj)>AtnmTuU?LxedbB4~jZyn9hqvbP+R~txx1P0|KgnJLte~XjLh96VwA5N0W~|aw
zp5!$wYYjkA=78Tm!m{7KtwpBkw>4$%=|AeK)Epg>zlz^3(m-T7GxsCjDV~pu7cFmO
z+-im?*M%m7=l#p@D9y(9#5Rk{@EUpsZmUT8h@%5BHloRdsY@0x*bsPJrR4}vn
zz=K$quU)J>WmJ))%*D`ou+D6aP<#Xa0E@_+xuhx#f7AIKt5nBlSY<&-$D_BokN{i*
z;WQd4t3yzVe3XLxTKv)FTL_nL>E43&hLF?rWV*cPnIqUCpx~hN;>Gu$
zig@_;r=F^%003!NwSRQm^4s~O@wd)Lv=9zEYluY$nH+DlDId`EIHE<%K#E)6CP1sO
z>s@p0^iwc%K=y*`nwgg^S|=Yx(4yM2xo~pgdaWjuw|a1=AxX+tus25xZ1$!|-)QDc
z`*3V_D;mjB6fEE*_P&?3Yyw`2r1S`yOE;P`*GiW&?!tW;xD$`W)RP>r9CyZs<+}fz
z1SmOg&>ITg)*};I%30MlNy$%8-npk9sXMR_*(sV`);*yXOU6npEZ;a+Q)%=IUmd7p
zDiD@2D-6Z%`Or(GnLdWHu&fqQGsxW9Uv{#%tfo~$AZ`zZ#WMr8q>xnB9c6+b7j$`?
zq1{US8%lINWVmXnA#YnqQRZaVw0o{v7uE;
zWR9w$3PT;B+z5ZO;NcLINIlM;carF9#V)*NUMG>UsZ0_^{;FVsag5$2@B7)Ek4yG>
zbU@=wLa}9GT+1GHR-Ijyj^R-9m6W=&I9}bRFl%7qqEBFr2+pJaaz7J!MC2lS>=f^`
z@>k!DZetJf<#)vKXUigy=)rU2*d6cQme9qNe5RfwI%%~ZGdRN&aZEXfHh+W0-l3eN
z68{=2qQIA#dYaI4i%hzu!2YmS+8ays@bkARS)cZz?5IUSeFTc)nM+7U<5n##p}vL{
zkKP-!3GnB<4(C>USKk5C5g9p8%ffp0kD(YfGt3=P83KwZ${W=ht6e-H+^3Qe!>iG+
zo9aw6{4O4^?vC+1cUi0L{`>>fjWmcJOL&vtTzdHFFc_E}>FiZ`@m}-G1tEH$=N`_%
z-Io&&ANmK)`?ptC#zm0Sm^^@8VBPqz*Rv)j@e(^EatR=!`R#|ju8wXlrsh1Z?v{z#
zlAv}zqN!tY)~Yrc(-jFe<4lbtM$C?n6eObj=n|K(uyaYvI%{iY%%rBh}X7*L(&tHX|%U
z59Y>F1}znJhfjdrlrl^MqcI$~>RD#rQzvVgVGJ+%ApG_~{y@i6$o-SI`eFD_W*=4g
z>@tSR)~pAvue25)#rsm$3OSq`=@5z->i(hK$gnaNbS(Rz*);5F38urd7*nuV0r5nR
z>y}=b>%t>`ofCb3QU)6p$BolrJGs{T51{;+Fn(P4pm?c*XD?OaeCpeBe
zx@6}T#|-3JPmZqdab9Sv(;!*#rSp`<4DZ-<8%A3!5F_cl!bli51_O<4+Ke=YbdAxRc5O
z`0s)z8V7q2P-XI(M;*`>Jm-c{(wL+W?iC10Hc21MsLwO8tHwoPf$s~A>s
z`5px!QmZY{cPH=>iB8l^da9TS41P{QDYK|t&|81BF)fb8MJX&vt@2|g=a#vmd3wW_
zB0vk2OdTL>WaA*Jvr0uY=JPftsI-MldWEQI&Eb%y0QzJ4pN0OFP(f#nhp9P=2f!k(
z(iK$bhPr7Dx?LfxWy3z7F^6ecwMZ6cjdZ80I*Z#M{9XaQzc@DB00^e8N(wEip^@zi
z5eB~Gka(u2YSGPA{Y1sQyYFFDB-&hB{|=k*0Z_VYfi)m03KsIthRfdp_
z{;F+6g&;GHGhITntaLi#j#W^6(7~MmI>QQWf%!69#zN9gD?v1pO_`rO;2*&~J<$t3
z82cL=_s%xpmRTF5riV3_+=Uq|L0qq?3j$J+eQSa7K_wNm265SXlNrjO#5fXu>oZ1#
zbPcZ8aarH}+@&wOM1~sHtQAA4#C(9R9)SWd%|ru6T?-DIf6MGy2IU*NH~5M!uZ1Q#
zA?`@*_e_vtdY_3?lA}~qOORB*a$pOc!VkQ~63U=TUQE~`5hixvkwx#F)P$+7ozs$M
zkpaaW0eIMwZjaLJwy=f*426a1o7T+Dz=+}c*q0A<{PaVHg3{NNf-d$QAGA?z$5>em
z$*7bm43diz!J)wUm!OERojG_@<~`PUpOvqj;{H=Xr<`!P@(
z0mn7p?#$<&^9#)1#f@{lO3goLe>mChnWv;eeoomN-JeADLLlthRN*Yk(v%q~bbcHB
zk?AOeI(VkGJOWi)UGdb(3<*g=rFStOjx1~+tUbD2WkNtA7ale&YP3-8RqwJx2!@nP
zS9TL96-|uK?>5Y6)Y^-3{Gc6H(%1?S!(gkfO)PN*kM%AHCet_|CsDq*7b`wZ#j~9*
zo)NHRe^|GnFx`0kJ>9mK*imN}&Qtupl}K}o@nn0PH)4}sE_;G%Z+sY6zD;|)T5fuI
zNy>Ass3>-%ksR|w%qtC>N)wvVdRi<|pvfZVXAaM^7vHwON>DrhbYgb+jEvT-D#)G*
z(S%C6VNOhYgZfP1$G5nE7&PsC+K8bPVwKFF{%4n6~GV_4nh
zl~(0DtyzI=SN6a6nO&}E0@qSt@Rsng8n~=^`in9Z6lCRBQgt6DTPKNFEQvCUX?vlj
zBO7oxn>=8vcM}mxsV`75fa+^ZqOnQx$`!OT&muQnAFshZ&?*bum&;SC!Ol^ny`7x2zoezQ%qE-Fuv)BOv`mGpb9uIyeL|s$lX3Rw^O)H(8_zHLJ^Rxo>i@>bH
zck$@=<7ZzgXcNKW#=8ZcNDRWp1xZQHvYhDE6O!7kBQufn%ru-*A>59|vJAHslGEsJ
z^SLwi9ww*#M5-O!BMGCG6O&kEFrNtU9=)y8DI%$&2Z!XL>)R_2a6UTDKs#~(?WPp1qK%Af+B?0r#xP89t@Ym4D
zxa@)`T<6kE!x}yZfeG%ci#5L4d<1L&m@uELIYMaw
z*G{<;J7ps^Xl;R`4Iy{7*t9y-aQXVk&8AN|yq~pAMe{85k3f|=8uD(<`OHJEDdGAc
z14fbogOxeE?C8=j(Ud;32q_|H{345^quAlr#oI962x^|k2P(Zigbbd~Tt3BY5wvo$
zuxGMLqLIp6fMP1{sAyV<@4-JSOY019nUZ`6zK^h@>k%wK=;&1J=|La%#Eb_wYGEAzLDjNR<|O+@xDtN5Qc
zfZ6|ToUUlU*X^q3Xy^Yy>ijp+75(>@i0zl?iokQl0{;7nb(04CmpC_2`=<07;qxaO
z_+|k&v8caXVo*?i0|L5+q~5IMCP3(yOEJOkT==hXLjSP2F$&
kt(#BEzY5Y(`<>JEbF+pj#-CRh(d9{aa5-h_*S<>s7q^0tEC2ui

literal 0
HcmV?d00001