From 5b38ddc41d1f9b8209cf4530e694280620e69989 Mon Sep 17 00:00:00 2001 From: luciano Date: Wed, 29 Apr 2026 14:25:08 +0200 Subject: [PATCH] feat: wire Sentry, conditional on DSN env var apps/web (@sentry/nextjs): - sentry.client.config.ts / sentry.server.config.ts / sentry.edge.config.ts initialize Sentry only when NEXT_PUBLIC_SENTRY_DSN (or SENTRY_DSN on the server) is set; tracesSampleRate 0.1 - next.config.mjs wraps the existing config with withSentryConfig only when a DSN is present; source-map upload stays disabled until SENTRY_AUTH_TOKEN is provided - .env.example documents NEXT_PUBLIC_SENTRY_DSN and the optional auth token apps/api (@sentry/node): - src/lib/sentry.ts initializes Sentry at module load when SENTRY_DSN is set - server.ts imports sentry.ts as the very first side-effect so early-boot errors (env validation, plugin registration) reach Sentry - env schema gains optional SENTRY_DSN (URL) - app.ts registers an errorHandler that captures the exception with the authenticated user when SENTRY_DSN is set; logs and re-sends as before Build-time housekeeping: - profile route: targetDate ?? null on create to satisfy Prisma's input shape under exactOptionalPropertyTypes - profile form: useForm receives defaultValues only when initial is provided (spread instead of `defaultValues: undefined`); Field error prop typed `string | undefined` for exactOptionalPropertyTypes Without a DSN both apps run unchanged (Sentry is inert). Co-Authored-By: Claude Opus 4.7 (1M context) --- apps/api/.env.example | 3 +++ apps/api/package.json | 1 + apps/api/src/app.ts | 15 ++++++++++++ apps/api/src/config/env.ts | 1 + apps/api/src/lib/sentry.ts | 13 +++++++++++ .../api/src/modules/profile/profile.routes.ts | 2 +- apps/api/src/server.ts | 4 ++++ apps/web/.env.example | 6 ++++- apps/web/next.config.mjs | 16 ++++++++++++- apps/web/package.json | 1 + apps/web/sentry.client.config.ts | 10 ++++++++ apps/web/sentry.edge.config.ts | 10 ++++++++ apps/web/sentry.server.config.ts | 10 ++++++++ .../src/app/[locale]/profile/profile-form.tsx | 22 ++++++++++-------- pnpm-lock.yaml | Bin 223766 -> 291046 bytes 15 files changed, 101 insertions(+), 13 deletions(-) create mode 100644 apps/api/src/lib/sentry.ts create mode 100644 apps/web/sentry.client.config.ts create mode 100644 apps/web/sentry.edge.config.ts create mode 100644 apps/web/sentry.server.config.ts diff --git a/apps/api/.env.example b/apps/api/.env.example index 3bd8fbb..523b11f 100644 --- a/apps/api/.env.example +++ b/apps/api/.env.example @@ -15,3 +15,6 @@ BETTER_AUTH_URL=http://localhost:3000 # Google OAuth (configurato a fine progetto) # GOOGLE_CLIENT_ID= # GOOGLE_CLIENT_SECRET= + +# Sentry — error tracking (lascia vuoto per disabilitare) +# SENTRY_DSN= diff --git a/apps/api/package.json b/apps/api/package.json index 440bdc6..cc3f2ea 100644 --- a/apps/api/package.json +++ b/apps/api/package.json @@ -18,6 +18,7 @@ "@ketopath/auth": "workspace:*", "@ketopath/db": "workspace:*", "@ketopath/shared": "workspace:*", + "@sentry/node": "^8.30.0", "better-auth": "^1.0.21", "fastify": "^4.28.1", "fastify-plugin": "^4.5.1", diff --git a/apps/api/src/app.ts b/apps/api/src/app.ts index a11c472..58d805b 100644 --- a/apps/api/src/app.ts +++ b/apps/api/src/app.ts @@ -5,6 +5,7 @@ import sensible from '@fastify/sensible'; import Fastify, { type FastifyInstance } from 'fastify'; import { env } from './config/env.js'; +import { Sentry } from './lib/sentry.js'; import { dbRoutes } from './modules/db/db.routes.js'; import { healthRoutes } from './modules/health/health.routes.js'; import { meRoutes } from './modules/me/me.routes.js'; @@ -46,5 +47,19 @@ export async function buildApp(): Promise { await app.register(meRoutes); await app.register(profileRoutes); + if (env.SENTRY_DSN) { + app.setErrorHandler((err, request, reply) => { + if (request.user) { + Sentry.captureException(err, { + user: { id: request.user.id, email: request.user.email }, + }); + } else { + Sentry.captureException(err); + } + app.log.error({ err }, 'unhandled error'); + reply.send(err); + }); + } + return app; } diff --git a/apps/api/src/config/env.ts b/apps/api/src/config/env.ts index 52adf2f..2d125ab 100644 --- a/apps/api/src/config/env.ts +++ b/apps/api/src/config/env.ts @@ -17,6 +17,7 @@ const envSchema = z.object({ DATABASE_URL: z.string().url(), BETTER_AUTH_SECRET: z.string().min(32), BETTER_AUTH_URL: z.string().url(), + SENTRY_DSN: z.string().url().optional(), }); export type Env = z.infer; diff --git a/apps/api/src/lib/sentry.ts b/apps/api/src/lib/sentry.ts new file mode 100644 index 0000000..914d729 --- /dev/null +++ b/apps/api/src/lib/sentry.ts @@ -0,0 +1,13 @@ +import * as Sentry from '@sentry/node'; + +import { env } from '../config/env.js'; + +if (env.SENTRY_DSN) { + Sentry.init({ + dsn: env.SENTRY_DSN, + environment: env.NODE_ENV, + tracesSampleRate: 0.1, + }); +} + +export { Sentry }; diff --git a/apps/api/src/modules/profile/profile.routes.ts b/apps/api/src/modules/profile/profile.routes.ts index e878ad0..55475ba 100644 --- a/apps/api/src/modules/profile/profile.routes.ts +++ b/apps/api/src/modules/profile/profile.routes.ts @@ -78,7 +78,7 @@ export const profileRoutes: FastifyPluginAsync = async (fastify) => { weightCurrentKg: data.weightCurrentKg, weightGoalKg: data.weightGoalKg, activityLevel: data.activityLevel, - targetDate: data.targetDate, + targetDate: data.targetDate ?? null, }, update: { age: data.age, diff --git a/apps/api/src/server.ts b/apps/api/src/server.ts index ebcc6f9..31540df 100644 --- a/apps/api/src/server.ts +++ b/apps/api/src/server.ts @@ -1,3 +1,7 @@ +// Side-effect import: initializes Sentry before any other module is evaluated. +// Must stay first — moving it later means errors thrown during early boot +// (env validation, Prisma adapter, etc.) wouldn't reach Sentry. +import './lib/sentry.js'; import { buildApp } from './app.js'; import { env } from './config/env.js'; diff --git a/apps/web/.env.example b/apps/web/.env.example index ae0e216..096a9a4 100644 --- a/apps/web/.env.example +++ b/apps/web/.env.example @@ -16,5 +16,9 @@ DATABASE_URL=postgresql://luciano:luciano%40@localhost:5432/ketopath?schema=publ # GOOGLE_CLIENT_ID= # GOOGLE_CLIENT_SECRET= -# Sentry (verrà configurato in uno step dedicato) +# Sentry — error tracking (lascia vuoto per disabilitare) # NEXT_PUBLIC_SENTRY_DSN= +# Per il source-map upload in produzione (opzionale): +# SENTRY_AUTH_TOKEN= +# SENTRY_ORG= +# SENTRY_PROJECT= diff --git a/apps/web/next.config.mjs b/apps/web/next.config.mjs index caa3379..b04baf7 100644 --- a/apps/web/next.config.mjs +++ b/apps/web/next.config.mjs @@ -1,3 +1,4 @@ +import { withSentryConfig } from '@sentry/nextjs'; import createNextIntlPlugin from 'next-intl/plugin'; const withNextIntl = createNextIntlPlugin('./src/i18n.ts'); @@ -20,4 +21,17 @@ const nextConfig = { }, }; -export default withNextIntl(nextConfig); +const isSentryEnabled = Boolean(process.env.NEXT_PUBLIC_SENTRY_DSN); + +const sentryWebpackPluginOptions = { + silent: true, + org: process.env.SENTRY_ORG, + project: process.env.SENTRY_PROJECT, + // Source map upload requires SENTRY_AUTH_TOKEN — disabled until configured. + disableServerWebpackPlugin: !process.env.SENTRY_AUTH_TOKEN, + disableClientWebpackPlugin: !process.env.SENTRY_AUTH_TOKEN, +}; + +const composed = withNextIntl(nextConfig); + +export default isSentryEnabled ? withSentryConfig(composed, sentryWebpackPluginOptions) : composed; diff --git a/apps/web/package.json b/apps/web/package.json index 8b1b9f1..b6a4553 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -17,6 +17,7 @@ "@ketopath/ui": "workspace:*", "@radix-ui/react-label": "^2.1.0", "@radix-ui/react-slot": "^1.1.0", + "@sentry/nextjs": "^8.30.0", "better-auth": "^1.0.21", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", diff --git a/apps/web/sentry.client.config.ts b/apps/web/sentry.client.config.ts new file mode 100644 index 0000000..30b0ed3 --- /dev/null +++ b/apps/web/sentry.client.config.ts @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/nextjs'; + +const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn, + enabled: Boolean(dsn), + tracesSampleRate: 0.1, + environment: process.env.NODE_ENV, +}); diff --git a/apps/web/sentry.edge.config.ts b/apps/web/sentry.edge.config.ts new file mode 100644 index 0000000..30b0ed3 --- /dev/null +++ b/apps/web/sentry.edge.config.ts @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/nextjs'; + +const dsn = process.env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn, + enabled: Boolean(dsn), + tracesSampleRate: 0.1, + environment: process.env.NODE_ENV, +}); diff --git a/apps/web/sentry.server.config.ts b/apps/web/sentry.server.config.ts new file mode 100644 index 0000000..12435d5 --- /dev/null +++ b/apps/web/sentry.server.config.ts @@ -0,0 +1,10 @@ +import * as Sentry from '@sentry/nextjs'; + +const dsn = process.env.SENTRY_DSN ?? process.env.NEXT_PUBLIC_SENTRY_DSN; + +Sentry.init({ + dsn, + enabled: Boolean(dsn), + tracesSampleRate: 0.1, + environment: process.env.NODE_ENV, +}); diff --git a/apps/web/src/app/[locale]/profile/profile-form.tsx b/apps/web/src/app/[locale]/profile/profile-form.tsx index 4e77f4f..88cede7 100644 --- a/apps/web/src/app/[locale]/profile/profile-form.tsx +++ b/apps/web/src/app/[locale]/profile/profile-form.tsx @@ -28,17 +28,19 @@ export function ProfileForm({ initial }: { initial: Profile | null }) { formState: { errors, isSubmitting }, } = useForm({ resolver: zodResolver(profileInputSchema), - defaultValues: initial + ...(initial ? { - age: initial.age, - gender: initial.gender, - heightCm: initial.heightCm, - weightStartKg: initial.weightStartKg, - weightCurrentKg: initial.weightCurrentKg, - weightGoalKg: initial.weightGoalKg, - activityLevel: initial.activityLevel, + defaultValues: { + age: initial.age, + gender: initial.gender, + heightCm: initial.heightCm, + weightStartKg: initial.weightStartKg, + weightCurrentKg: initial.weightCurrentKg, + weightGoalKg: initial.weightGoalKg, + activityLevel: initial.activityLevel, + }, } - : undefined, + : {}), }); const onSubmit = handleSubmit(async (input) => { @@ -142,7 +144,7 @@ function Field({ children, }: { label: string; - error?: string; + error?: string | undefined; children: React.ReactNode; }) { return ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 74459b838b96fac1f420140d3bc08416403cd622..29dcf4c3c6e4eee50e2c6e08165a394a50538843 100644 GIT binary patch delta 45293 zcmb@udC(+jdKVU7&$T&VQith|$0LEf2F zdEZ$`8df%86F6*^&*;N)fCWeh;V?omhL#PswP14-uz($sfB=ON*vPiL1i}F(WWQD2 zGqW?jE43W_Gu=~P*O$M1-sgUP&-=rF_x=Cm7hm{O&8_EOt-Z4H%GbvCaN-_%=g#%l zzjOA+&)oXuTi^MvpFI2Q%P(7bUO`qK-F)@6Tc3L4uRXQB^`6_WRbE<`!&krhsVB*M z7<~Qw)kmHt?~TXz(CeT40Q>PQ2S4^=FY&-XI)C>y53MlpZ`cPfJ^7O~wLi73q zH1GbcP6lxG^el1F?x@;048LN)6 z^fmb27`*#$;<=T3yjz!+7}wz8`((`QEt$^zP-CudjaflW+WQAAHZ%Z&qK}>z{i5 zxohf$k zNxwbTlSAFv+|1|Z5HcXnM5yPU&g_E|D_52u5hTBF$>DS~BrBh#3`KC5f~t}OqfSJh zGHM;JZ@%#hS1(@w-j_f0-nY#C@~}C(^|$LnI|OKGdJ5AfstV&Kc_{`z;{mW?{D zu&{`bvG4R_){+EnBF*JB$_vS%JTCPBXQX^fK|$GX$W1qxW4p1J)x01XeST~#q7NI( znnm>pvnM0f-22YMm;L1Xf;h9S_`&lovK?uJvyzTFV<88YH z=``>2Fs@BUwVEKW#+baEdyz(wQqc5$F6CIT*+q@vOIns6IS~)veASO8ncKwP-6+Yk z^6j@o@XsmnSU;MZNjd4PDc3k`H|08W80Jdl*m#dk)|$LKO{%VA77)zvBE{yBrkE+& zOzG26nrRDXgN_eL+t_~Ip>9g?uKnh7zvJO^feTD4KP!{B1blupG0Aj>GD_5;Ia*~o zU0zVLgF9QBgj+6RMOsa?O+JBzG9Ok_m0@|zP9=(6FvKu9*`Wn>+mkXIG)-Q&3tAOc z3j3yn-*fZX7jBK7{=UgQ_#XVm*I)XBSJ(gGrDtv+>ejPQXZhKgUw`AJyRy+9)>$`Y zdOKv84J|cHs?I%B>-8gY(i{}^8E>Zw3rkxs8gf;dYV2Bs05{9-WR?n#MDawJPx&~< zd24OhhC5wfze2wV4E7UGUtV^4{nP%d@-kx^rNXPZDR?J!v2j(WD-u&6*=!k=oZ@hn zp$fANx`t`XWoy?df)bm}?RH6ybS1+D_8`QVx~-+dVk4Xip9!vCNME}C@+-ga0WZmc z7GM0(S$AJ>Z_5^ns8jY)2&>N839YZb) zY+goLT^|$@hgRXfgHRgTR>%wrqSI)0{nKB(80!1MX}0HNt|K5xKMgoSb48W6cPWF7%uwPhvYz+CBwM=fdNK7wVKEuSy_?2^ zmu&p?zIoFx-29E#ZhiRri!Z(OM)+G^-aMCp+$Ktc*Fb!{F3?w1ZZ&P7QEVA3PFILb zZ=|(`8oP28JF2nmBGgyrL_fo^xbfzPpjYwO_qTI%UK>obBxGT$k7{wF_tS}tuQp3N z9F`05x=eoI*}LFbAmn5Bkn30A+ltBOh)SA_vt!5ZN=rqq!~|)D@X=hEC=1z@APQzl z71Fh3yKXVFVv43-r-(7$?-FXK6AU(s7T9#MEm}{3roy~gT^GqmZ+_(iPkitVC4Kh! z_kk4VZkz?xIn%g?U%I1^OR79<`qAE^R%EkS1c=LO}De`&4EmGhIDl}9DHhE{lPiGw9VXn?e(h{pTckdz_ZU@|LA8v`pm;e zUjLylkCYX@TRJDNIfNo5wuCu56-#5GL_uJ3_{x>|sIOHTTNs7ymWSrBm>l>1YAj~q zA>L){gq*crnrUOhl6h@k+IdzJ^|iJArsqBT)+7- zludCoCw!??Cpoc(d^v0Iaw25@DV0)j@2^LV;?cE8ABc|h7&aJhW*kj*)b4~_|Md62 zc>UXd=d;&8_L&!+Jg2hPAfCtpH>~5`a%UPYbwt(+ftqsO(mR+QB1e-6l*=BIKq;>$ z;u2aiX6#7N7S-3Y5l8w*yA-4%bnCc1%+y2QDTb8_%j>Jfi`V(zd+ycS?@EWiUE+F1 zqEzFy?e(4N9tsIN%G`$cW_+9F)6mwA-D#FLqeR)F{G>AL_&CsOwqraD>-L+}whTHW z7yVwHtyXTgV#^}$m(8ZGfyumh3%`By)vsQC`o{aQtB>8g{XJho&K~gP??yl_cn`jP zt_~gr3Uc~$a(qFy-OhP*4v8yeAFlakV|m9NChuqcY}2!ltZ5W1bLg5#b)}}$W?nna zfKNGP&5-?$(RqCYbG*|t`8*@}slytGMwGyJyc5}LkA>`A`S)EbDe^e7fpy^5U-=7n z6l&1bG@koVuVNdh6q@9;>CK{2xM3x)m&8`(B8`|}@Orl|G-_fxQ@b@XRmcS*+UBxC z&aG;R;gSL!D|MZ0Z6>ncjr9{Kb`Snma(g#AaNw!u)E9JT+ZD%?HJbw;gS$s#nN91B zz7+zl?oU;Sm;xW;k^Ts%{Tu?)T+KIR%9V9s_=1X%9qfJiky3O(kE8>RZ3YJy&CkYD~ac0gZ zyOizrUXyJOOI<=Tbh;dq(nvh&>-;E}C`--lo;(nVl7T3-djui&m-&^oLM}#(CJpF)taE_#UbhIff_sp9hH%PB%9gVJ|dh24=dGQ!F0A! z_N;9!Xj$-LOJ}Ds6br&5$NRYOe5e>lU#FP5^;RF7vjj!@Tvuk%t&Xt-Y)*_<+V zNE;C*rLEX-W{k4Qermv$Pfh&kdd;46OJW~6ck?WZ&(gaDHmfFC$CGQJrxC$t zHZ0Y2b;09ERzq^`aN)?PSPyqYe-gAUveY0`a|KD6Kp!F6bVp-rON2-XEo0k;8sOW>lJG!ou%NjY&^@G+WNugl3E)2@bm< z9=IeTF?%FLa#}&xD4x0m zwuTu6wUNEu&R2GwU*J$*!uWJD!3(YS$RU@UD3PuvHdMQt6*g1R(O`8A15XbOf*@O_ z%GyFk!~;f??V;Pux-f!DdNJ<3I_y%smUK|ztf%3uQmI&DM00Y^9^N6f$34{uG^^a` zp+mXksl{%(n$1aXl55j^3h%H2&wAirY>rJlVrqq7Gxbfm>`A6$;hW9|{xY-EnBjM!07=Bv%^E#;Tm8^vY zp|@^E+Ep>Jl07^o4`%G6mafyKFqKriitrOUSW{8Q>l0Dpp1JPmqrS}%9HJgEiN{sB zBj`k(RSv&+6e*VBk1^L*HOV{tWGXYzL0Ck~Murtyh5(T{?BT+2wZG|1d@A~i-X=j-qr zO6uo2ZZW-AWd}^#kWD7ShEnd^)bFkB1QoRv+H=j=tOFeqTbG^13bqK{EOp18J;5Ec zLY!hRDyzJnr5lihzuR!}$CTj(UIr>maL5lbm84c%Lh&q1vNYK$(qX#}M@2st9Nfex=aHj*++-m2 zD$w}9duc4bcmtxt?|nGns`<)g`2| zs!IA0g4%HA(YlMzxMV?wDBnk=u=F}^4Xe^rQCxSkS%4miJ(d!*VAMmgKRC*WTy;3J z#{U1C?IoPu#osmyOI9@dWHUVD?YDG_O;A`iw{TsB5I&X3B^HvcnyQ=iXjotb_sd z9yysu(W$Xmi}1?h)cIl3L1A%PHMN_Mg+fBqLZ+SW>m4iTMuB*o@@Hq>(dSi}DbM~m%J`cK&k5M>YwC!9l z(tHZvhbc1 zYZ?>$fKuq8a2ZCLY6ydxs%;(%dhQOqBeF2MJ>qVou-tO3F9Z7#Oryue1O{;Do{=(h zXKW~fcG2o!qSq;n76hRgj?ji+Zw zpS^VI9_`zJVmWI{$9pgjy;KHc1++gRD&P#3IY>D0g~>RXsTq!8&B&E@3aF?xJ>e)C z?`Fg}tp0&HE+Jf?DK;0pzea1 zy+nfffO7UkhbdJgb;=I{IA7yw8x7DtdM(~MWTZ~kpajkpsnwXPrad6Un zC{_Z!289qjYPRn_x{tl^2*&Hp4~}l34|2wevIb;d&PH2d>m~5kv{Gu1m@DWw8R$IS zijtVfe8a91MYPd@T-cH|Ur%vHj2nJ}_n87?ZET}1s!ZX~1VsUnif0U0`1R@s@7_Ym zOI`rR0tFTEGL2V)rs1@`;buoa;!XTuQ+Bpqv0Jem)2$Qn`xQRLx1h}PRv>_F>3mzm z`m98_!-^h|o?@v~t;SW8UtHkjF@O8Tch28I)CY0(p-$otx_PNY$LUfkPID~RQ>Zf+ zrph%`vqpG>*LSn7Zqb6W=N3ld6UkbxYIiY_PD%l-Ya8B}Nr;?$$`&GwqWHt9mStQC z-Yx7GZ~n{UtxvuIzy8~v{#af{RboN!>Wy80?^o^`T<9CyTYeGl*dgFr4PjbYAbLMuSB0$Mzx^1v9_`E8Kwm@VGL zPCFbHL0IELvK;%AG8&zH@kFhOu1Pp)FMTqL<0k*&%io9IBglL3_kaKQ0bg?Y6TePA|JkR@%g?WW z@%Mc8{SPoVbp+;t<7?=p&nx4F8?t7dHkeA1z`!S9*cXQWX1tLoDP5Z_$u)8Az__Dr zvHfBpmDySkCK%0B+a$0RbQX3hyg*^QL07bCW9ml3&-u{J`Y&F6=DQv|8(>53p${;j z53zkKjBotn@A>dYU%8M+?nZ!%QKnW5*=5!NI?CM#sL#xei(6*XP3DdQ4l+gvqwvt4 zRmp;gJ!GB@5o^mh%t!TNGx5|;0~Mq%?+YXVr;#=Juw-};wf3=iq(vO67D5tbP?L4z zv;VmRBukzL7H2p3fXVVU7~k_;`%HLvh~thd4iF@0HU}ph$B#R*6KIVWa{Yu&Rb|jn zFobcH63o^{$31~*p`uc)ysbGngIQj+T!}ixhz*n3ayLCmiol57CFQ;M>%k~JFozrN zI#$|R)tgveRd&#Ujhg+$-E-`8b)q4hz2QoP6=vHf_tY)ta_m$}!=X`2Gq`<`$?e}5%-bkN8jhL7bh1!AXdC3L22W;_307HT zzeN-~Pc?X6jus<~;c1&NZ9TSTN@fK+SvelXo!iYkY%I|sQIZ47V~g#MwfnOpm^_LC zy3khczHN(nmID2`Yo%!hm^2<3-l6EVh`p*<)lj3 z8a5}eHidB@vK+#=u_Qk_i~Oyd{OK5yNp+ zI5V=X*5n||9$fmP$Wo47;wdpJFcCIh9p{W9#@ZT13yIkJt#H^D%nF%$gvToSv4R~4 zjXY+KkEY#vgxpXczIqXOq<0z(LOscOLOP? z`Inx&dH%CkPhS7h7eDl!4-evuAdb?eziX8Vfxiu7tlH|D1`LpxF12l7`Jfo!C#UoP zUTsg>%X&I1;6$oCSO$S_?nm?*RkiJax52zSZtYT`2|+w(<*z)z z@K?)^U4QTQK6U2{FZ-qE*_Hd{Z+0ga$-IT@ZB+DeA=v$}@0HT$(luZyP&7u8)Vs5Xns*x9~vO?jc4tI@WHI#n~6XEu8z* zCqDlhf&$DP;sL7Sr|-zRre+&`zAuf5K(@|wIY}0Bq)yHGX>^iOofxmh`N`}9qqGKb zx0aoeu-m7m>>BQIypO3S*DWS;W-FBKw)1_V?vH0{ehbudPTqX+<=@(q#1~$^&gUQb zjiuIq^I5JsYY@y~6x9<(V{v}US;L?tEMh_AQJ#*V)gmD#l{_9z+#|o@ojh661xJ>e zv&#-!y^%N8b~Za4Raf9=vOd6x9-jljTL7(wbU@89^zPfDJC9z4AWns> zSW3xaM4zB;>8;d#s-iZ>_mg^+Vk?nsb#^;mY82{|Cu7YXYx~F*2p6E(&Jq*Pgx%{opsrF0wH6diMuE{)unW{s*YuA+NrL_voDWAsu0A4|8}e@(@99 zmWcw6kDmGSVO0}HV!vZ{J!L2XAc*k0Q)+Z7-)Rd90q%WgZI4olxuiM76>Tl#Z_<4r ztm`jp@B84}DBjla^~%P)X&b_$Z6d;(KJj{952l$}?ICuu}M(#>gtO!PR$ z7qTwz)4ej2vC5w;a)G515V()}45PJrK8a6%3lIE&ar(CVAIx+g;^HP6u+?C0@=_HS=+x{RNZLs9Ox%n7 zv>#15qg$Qi5$1rh4GD>QN{G=W-7uCFPMsPjgK)h+PFKqaWTOJ0lU8pAEI%hyI*z{b>7_-MMYVaIQZc0ZqC-Y8Sk+FXixs%IstK*4^ta#{3{^}I)cf7MCeb<+-f7=g!SiJ7^R0A)!^Dk%4};U4d~gI1mw!a!L6DG)dE(IVt!G28n|k+`S8!_z5X463p5%XFTU%! z!8a*RW|uTQ^H$6%)V9=~YCwIE?nMdl4RP64jv&wW%M&ld{$7F8U2RsCfIEt5)Vyj| zHFjWp>*#yanKXop**+<4O@uCr^SN)KI1d@e57QgqS{~+ihjBRO%%w)hpf4lN=LsmY z#3^$!^v*Zkc z@pD%%J^?bD3(@7n51;+TmqEpk-@}1X-G1Z$_|XqO0Tko`9|HqfI|jxG_~%~V5t!*h zYlSUFJGbN!5SX=gEX@p$LPzuMzO_r;PJ=Qs4ES*36wMcTQS7(jVJj>^tcaIes^7ZC zWNr}SG7w$)P@o+sK_47QJ>*^mc@+pt_1($==JXnNZ*p&P`->NHbb0+-u}>%biDzPo zn-v0s2F_C3!YtD6AVVDdw(L#VW=72Y>>*+$ub2B>A8#t{}RR!1a8njvy5 zT9s$GXxob;Wdz?6!)w!P@y~x=Ve}r&H^It7-vN35U)G1o5`!$tH z%xM{eKCFZpsY6I@U{C@C#$!9+LQ=IkWqbo1^RU^VU?^@~|L=eFzjzM3WauSlJ~Dj$ z^&h{Zjz|8E+>tyZ%tzE<&gs6Kq508dcI>GTHRY5`Uel;tn~*9G3|KI%c2;DJ0~oZn zc*4cXPVr1xEW8BoXwG+rid|CI|K5-NvG-qQEU_bkb!hI+|vo1|SOc+eJVa z*Ps0HpL}2NfU9t>iZ73fWQ$T3>?&hW!lXF55_{4 zFpsq1fR$myAL5aRM$04%2ELmdOa^Dl1>vogVZ1!IF1}fBz}$g6pO=Ab96Y1g6BSRI zLXm19$JXMQ!Ys9Ep-BgQo6LMS7-qXMXHArf-~*hUwfk7gERzpK20BRxWKPcO4L>_( zkxY6VdDhaK@BaQ&YAYmzUc zlb`sRPkqPj*MQHks>)03csPJfnF_3206^#VKp@59+ppN{EaI3Y+Wp>K(dE2vDm}Rr)zbxp+RP#oS1JXn1?v*#`iBe`tWcL!*bHq&NA9m635oSSJ^F$hpgeMw~iUlidyv5fOa@qlE!)UTD3t7(BMLPBp z3Rlpu?bb=l?C0=uOG_in@CYr+=wlqXMCGh8pf~B_H$c%@RdUxJYR}1@0SV$;+JT8S zw;84w123qR&V_ImEYv+wZX27LQkgl@_C_e!%+Smx@Bwr8ZnvBUqe2fkY6~ADgN*}B z?rC+j!b?#uAw$rQkAtNGRL3ZLI(^e}?z~=&6Ma$0Ya;9SS#bz8S|PD*aH5PuSIt$D z%OGKt?JI#!ddQ^n!itl!4z~Pp+4U6*M=J=zW}QYYzyN<)2Py2DZ^zbm>S^S8-einl zv)hQJRtZ0+vnqFFf`|Cs< zi=Se)gb$D;XmL5|v385Z^rC9KU0XY}Fh71f5V2CDX?77!?GYGIB1V>!1+{+^Lzh^WMG zhoPzccOU>OSpSXx((9NYYV2VHg1Le8>NuG!OE}tjIz1ij>CEQh7?YmUE}XI|e6 zYh?w9)N3-LAVfID3tX6N>cJG25!OwtdJ@uyb}uC3(ou8^hEGVlKVd;^W(w!8$4TBA zAvf3wSe9@OY&l2refjHR08GP+I-Vgsd;Q10{9Uh8NtQ?};Dk)uXT`8djsj>8VHjmh zikhG6sX*8q+Mw$S57c=;`uPMKTZ@R7W;VT_DB|icg;TuSP>doiTv!xP<@k13d#6%f zRlpbD`V+wN9$BpwuKJ7|}bv@sPp%MC&%M6pX7Ola!uxSCnPLDfD(idP!0nxX65{2hec)!ZfEND%32{AUh0&9$l zsK!M@hWM2sZ{?l$ws*WdG6r0#*TBN&IasSgvn*x?vYSCP*(*c^)!{7IQW3SAEVl+N zV(4hbm@5w0M0-?@)KW|}KP9w~n@qRe0VxtC%>>BUg~!@mWsMW%M@oF-=6^7+KKfvL z>#kMTWn?$?W$rt@dEpDUZYwE_s>87zHx%YASspS`S1cWROdL5<9%viQkr50c@opaT z=^RR(k(JuwK3r|JR4VX|2W?tt}mq6}D2NT#z0t|Hr&t%O$q8l+W`wd6M;-SP2 z?7;OSd~-aGNo6~sQPB;6jm@*Rks5O$r5>?o3H{v5dWJZ+Yi|F*8=w8lzk2oD-J>^j zS?Qh!c3=CIJBl%vptZnI%21A5stJz>ttH5O*6)|vl(W}pcG5gADOW`fXq`{Ot9uk6i!!-+Ac` z=C8J|JOwsSv*hN3`H ztEpnvWx!t+8j^>Xgt0KWB@vszMD<%}~HzS#imBgdM0jBz3%?Yqt*Od(7`^ zn_KWFsYijd!<2T`ZG$$5uXdpS{Hg1o{b$d-q5Sioy7fW`-q3rvJney*ax94P^Qp9*gBy~;vMK*l@uKB z#n~jA%jBU1Gw~9%3_tZEINt}O5(m)J9_}s1UVrgm_{}$d_tkBEdLm`hVtFL@tIqKB zQpr!d^4OC~su^y$cH$~B_=M=8Zahkb5h?o+mr{YxvEn=#PYY_>E2P#f7X{i19YaL; zVFX0|#;^U0zwy))plNbLrB|=&Y_1*?o@^Pk6_w)w{2_>Xx>s}0tMtr z%cniDO(#Lo_{NB_YTBM-V4oKR$2X$?=hds{Q_zXkWDk<4eSUuageFZ3`hBd_FBSw1z{giLBVvr1-o7%fh2H$thKHlAxp{d zv9(#rNrhSab@0Z2@Na(K^Ur3rm$t7V1Ss0S_786>&8)z^KwHX=Tw|CuLEBtn;S;t@ zcg-p$gaR-k%grJ{El>vxF&YBK{;7z2K%WHdlIb$0SIc2JSVzyWj8vjJm$b8+Z~TF) z&)odK_iug2&ENRY)k{CId;isw9}2D1@!Y#-LQdRzVDBEic|p2*RnF>O5_cUQAGfA< zTmtgJ$y$gN5opGuN_4yz8G>BI`W)<4wP2FQOYFAI1l!{Dgn+>EnJ@Xvx>~s16dq7` zH+M(i&IIk#&z!v?(AWE`7p{Ky6CZeowxVZ;WTfciBpdtz5Gt($&L8I5N!m@=X*n4; zb!BA^nGi_lZAKco=4UJ`4z`P9Y*o*76Vrr5Vro{Nb`eloQPzkgl=oxq>=kbQ=GSh$ zbn|_G?&_uc@BQf2>4lr$`TVWVE2z+SHUotwyve=X5MW2Jvk@Z@dbXLc)-o2upohYh z8561nI$Zd8FK)M8$gKu47HPYgM_}mA&1dNnorATCCaTBwP4Q>0UVQq2+r9aF|KQfA z?*B)hyZTp8Ug0-Cdk?sJY?`JU-`7rLFCa4oLY>Jpou;$t60EVqX=ErxPxM2fqyt#r z5Qjm_x3X(4ylC!(=4uur%uZFdtR-uqBW zm+2%I%lUi|A&|1%{L}yC)~9d2vj9?bzHs&0hu`y{>VFOB&G_n$ZpAWVnj*d7!M^rv zIhl}SBG-dcxHwsgns9UaIPwB6SOrVas+IH9J)KBC-FPDw6y1BjRo#@BE`dT%oJ2ph zHP@~w@Ywsm|9h{#@bvTP`6>;Nn4RYjwpUv>U;Wjq+X@y66Tt%fmX@bE(HM_|R0Czi zDDkQV<>hh_2P1W1A10?$vEXN_5T3wxpWziu2FbB;0>yB|I61O(z?$=Rl(K3$-_>~?4Az6b~hl^{MwIPedzx0;;x>&y8rp@)!%*ZC$p%k z@1|J_-V)3W?pEjPL!1iqg0YLJRVZMiwvWj5ZUbx$(%^%XoE(0a`}vM@FxP+xwhwg_ z^vWalfLXMEj8!mnn+S(ZE=4Jqug9(BTY#Cst`=s1z+fWO-T#;R6@T?S*v6?q_MP>^ zUF)15-TcnGS0lw`9O{tEA`@gBf10Cer;O&%+?FQIo`Yj8>FJf66v<>hnlSLzO%6mg zjR`9@9fDeLdRV4G02V_%P12X_*40s??k=79E8_lln^(X6iI1P}767E2yLIT@O(GZY z9nQ)B_(uFUSFdWhIE?0HwNH#B+wl~*On}9(sM{BvhG$LT?gR1=*h|dXfR)m%L&klO z7O}`-t5U1iYwc&X6o2PgU}{WPwEd{_p?t)o=O8GoVT20T=wke-dbuLZW=7 z>k+dm5AzM4)to%aP=P|{E*gw^F59ZQVjfo8kZa0v-{%Ycv?8~F?6xei)q!hcYKa`> zogp=a2g2UeRA(FD`hNd!d*Tx}@B5R$WPho+y8FKO10wrfkOLk;h5%TF|NTF_qfFW+ zB**I5ap}z84ShN$({gv19cwd#n`w^(q*foqEFK+9FrOWPt@n|$YUKlhu&Fys`E>A0 zWy>O!DfV;sun9->=ECE61}yKMJ^uaYe(>rKJ@JHBIXAC-;?_ukDjsvUD6>83hm9Dn zn+z6_3DyDn!8Rjnd_}g)fry!Do+k}uVqm`4l@$$__ z$Xg$||K;CxHGk%V=QY*4Wdr6nB`B>PSdBt6i$cVr(3hrmY+EqtaK7Oq0$AT!BqNtT zL=Fr%aC_Rppmmk6AhI)(ny!|ei;eKGYu#SjOm?ibhIo_r73-*GH3*0_27`CA}g$pvaJQrN0%M+cdLn_5v-y9`I`xGWK-g+0&~1+98! z3kV?Y5n|fNqBXGKnQX==9Xm^0+o35DfRhjq%d2L<0H@vkfAxE>{{5?)fA-a@_g{bY z=Rc>cBvJOpV;QxwiC)K)R5vbBbjHp+EO2&%NYKnvcMTYTl?CX#Zc`D4jSX0}B9Xlo z?hzE#CP`(gD1mKGs>fwTforaCeTs0U1Apy_#)}nN5N&n8EI)XQh`V<>m}D` zP(-mRmR*0Hd+{d!%&lkd|IE$RpSX2J-u&$6Zrzd95z>f)dm8NCLU0etVR&h#q98c( zA>FSJbRVE9*#WK$;+p6wMA(WrA~*m^VS;E?30z4=E!az)<% z@{e3?ubwzp-oN+fZ!5lVYSba}Gca3YI9xd8%&1#1cu@w0Wo^J62$sGR7p^!FHk2^Z zKqGa-FI9MII1LBU%O2b_V2Ild#zzh9PgbBV(*1K~a4t#i|Iz>K>gTUM{@@lB7lcf} z)x6YTAa2*;xiV1~thNbyievfU)b=1)C<7}G@KV`PRmoucvI^Zn#VU&BbyZ1n z-q>~{m&?KK9Pp>?AG!LqC!X@X+6ixd>Kj)h*}<8;uOyIbJDNFBMu=9xR5u?OZiJ;Z zYA-r?-1)t98qpe<{6uw-NP&?IpabD*!)A^UQ+&bg3ciAjlOhS(iK}n^aCP;`_u>!c z+28Y}>;L?>e&+otxKRmALM{_~SnGKmQ$1eDuEZ$FBaxN1qPP z%uldP`ymk4w0UjW5>aDdU-y{PGbOf><6&D(VuAoYWp|UWc4ige-F`H~M$J^Angq>U zsbZ#e+V%knhq&2u8b9Fq9(<2k72+ic{N#B?^{^t$!F;C7>dXQA%OIlNeC^)VtI_G? zwz@A7EjcZTcCvMt`O;s;0}FL+IUp3*n;8!7a8j~iqD}j7M)Ov&1zR=@RxDI}tQM6( zly2;J;j#oXk$ApyEu(U+i^C}*DE5fLI=zl0?HtZc8zXRC?Cyr17^>T{wDvW zt7mThr0Hoqqt;ftr(BS%4(r*C#ePQ50Dqm(nn6s&e%d#!L~}P5okaXd)>U;?{azg z2l6)`c^+?A56%_*o@Jq@mAP9Go(^PB{7gl!`Uz#AVP^Z;di>`nBUwZETfBJJ*i>nV@63=sc z>h8H1zxnD8lu`8PblmReU?SxswX5wn@ZJKwAa>V|VTbRX@`UT;am>k*LL>CC!zamR zy)Z?gNmun=K5AW1TZ)t+dzIO**r^G!yEEnC{?GmV)jxms}YrKyO&MBi)(OGFF#f%)lzDdUs(6GHvqwX|<>r=i-S;9CX1Uak* z;Fqtje(_`X|K>lrlAnAMaLFEaeOa}l-O65{P6IAME#?;5ZarD}pjGbAml0ifB)l3* zW(-(t&2Hoo3c{^3rSO_!Z+DcI@j|9YEiZTiwe`mf6jdqU-N5BQPo6nGH-F)muSWMj z{mWNh0oUD~X&w*R{^x}3+z*pIKi-htq8_#jViZ=^UfuPrvN7g4xNeRsXxS!@WlL52 zRkvm1Wd`B`7tHjmvDtugQD4RpXsZ~mjgu{Y#5HXxHrHRJUVQfDhw1L^AGrCRf9Hu$ z-TyP+xcclfPd^|mTyp$MltE+xd%Pu2=mP^b%vTh<-0xJj9dti9t?2fY6$DJS{OI5f zDhkycVk}w=G(3IOn-g(4!^TqFZ;5`70K|n9@^;@0Jn=z4OF0Bq-Xt1e zAcV(RaFQp+(HR@ydpN2_oH1cmS}J`i5IE)FNevTrD}KD z7DPM-W55bMXuAGs_|`wV`iOG`7kh!5DjyDyK*0e*-B+Kzx-A`IE98S^GGFJ#Ng?gk zY`}}UGF@dF?_vRzTX0L-j+dQsY)}(G z%l_%r)r&X(@K1x}^!>MP{qPIVfY=Jy2IS3Gp1*ZR;d5mnpxex?l~dnt#CQT$xub!smd6x|2vno~`mYjZbDIH0qe>Moc6016B`UK6Bw* zKXda9y#+Tt zC29igI8WZq_F;(h^T5?CaRl0!O60Nm%1_XxTUSaB{K^vWYpiO`iTd3 zxZVX*!}I-|Z?fgaVA=Q_;}s(Wi}PKmwf^d`aUrE)GJ+S9kfFTZf>yKcVccieiK zzAz_mfByD`miF??US&6c!~rODZ++ARF}UpJ?xFhT4<7;tIU2ZH^qix;7chG}=S=Ip z`C0hZE6+UqMc33Xz4V?pf5Xkyhi<+2+&5ic`@k z&ucnuN8>`5L}xtOL}THg3Y8HN#7ancW_Iw2hB<-evyPy7v=(;^zRC}4S@>qgGvFQH z|4%-4>#sfYREZO>!RHCa9bLdQzG@1UAYvH<3op80FAhD^81a{BfwFE;p3`RI)3^Gk-s6Lw05I3drTr{; zr~&#j0%<2@vi|?7yYkpLkL!+|k0Pmyr+A1K#T65aq9`r*&9*1 zqV1dGyT9G#N{!?Y`bYcC@#f8&H*em&`8~i792yJX~I{JKTZf7_e*{JW^bVZh21L7SC9vTu3B;NiU zs?5%2Z%U}$H0EDkY4?x#Mn`R(BVE4sP}`EjG2|MG2D`1xqubLP^P@}fG@{+xI5{5b zbq9N4vppXTbGU>s?tI*a9j>qu^)3p)sKf_xu37AI{@w zLdafUp9_FvZTZ96vB^3c+)OO44m5Uo+B+kFr+9wBF+B%5X0T(bV|#2Vu(4rX>7O3~ z&r5G)v?mgswrx)IM%J8Ljk7lEQlPna1+K;;w)4L2frYiH1$b(-3Vo72?};y;L^*r> za2lbAwsz`gf!%U_EHKsD+u^m<+0M zca81gKwKxofw{p8eQJ-lIXuMPAC+9sSGw&wXj zYu!12Pj_fM>TBN`Tkq=jI2(iOQ+=(o8@{Dz&+7Ez^m*7Mqy8ZAtrN>%)D2Ak6Q3a* zL==H?>ud41UoRh?Y2WM!+NNfF8ynNz!FAjCc0Diz9#KqpwTwi;>)lbeu)Q2wk4~Ix z@z}QQ&9hN>Fx%%Jo$6hlo9Wxyob{hu2)e!VgKabZx`ill_s$ayS)*YARa9^@xwh_K zt!H+i0C|PxM%QBj<y^iIn z6<>cxYpB0|%Icjv@9p<(tW3BTL*t%}$;qA#XHOLN|K&ivuc59nG6p~)ZpY~Qpe+D< zV~?wUeB3cR5$>4Wh}L!4qS0VO>lUczN_x#4FL8>4tI4~>zn7-R)#lQz0nqry*|`DI=R-p+BVUFL|7F zr~t4z*mdX@JVXR{HulEg_RjAdZtM4t_O-hjL+8ha$HU$>dvG&6)j#N*bGAAiLmQ6H zC2vpNs(qxz8yalvUG4I;MOu2gSDM@V7FJt_+_R3ZhN1II!@Xg9WYRsbG!}KvBrK=V zCxRAI8UMj;aMM)nMRlbFS=wxdd)c+6gzn?PS z$zyCaP};QhnE0cJ;S<iN)!9)uP&p5_;ML^X1)&{IKVhB z@s(o9;&*OAmDrvy+=T!BEb1;2rybngr_2DuN`lO*ic{b=W7F-ZvO=6xNf_k89`qt} zKEwZIKf1xjt-V#K&Lgl*)a`r947Lsa;bl}7f32!0PYKivV?Nu2%8k*KY2WxSnov#w z$H$es1s+%9Cw`6^;{RBcU#pvOGI$UW-F)MM7IfsSgu5@brGjgCq%c(a9zG|x*Ue1C5(v!Q2=)&t*qgKBuXNik}Od^p(1~*ga(V@h(3>_ z_o71l{g)AwS^PIm=(lAWlve`GM=~YgBi}-OiTyrQYr;Q%0#)Og$4m#nF92U2?nTA8 ztr-PU)m^~b9cVFCi9T%Z2K)Vk7POYC*dqSPIdo^L611Uae7P0fm#Wx~Df&h`TK#`% z2!>XOpMMPH;gM!EoT|x-IJAgzaJUNvQx&5l{UB9|5Pql`Rp5Bf4tQS^-#Xch|L8VU zn)pdCy18sWSD57Z2;L^5d$2W2*o*(^ENa0O)5xQMkj5W9gbra#mat#?yq5w$CvKib zwq5&4#J!08>|k3Tk)RwRK{kfdtiVlXnvy{LCM!S}tF}Nt6;%k1m3Bqdi$6HWWtwXP zKimVGG@%p_hAE|boEkVCrb&GPYeZ~j7j1^V@FNfM27y*^u1W9l)bwhe`zi5(;Yu%A zo({v#Y6z9IGxEYPSyfvtrOdAB80yhyhAC2mNF&Ojoj9#j>9%UIm^BTP(}##D4A;NO z$hy8G!WVp~sFb~Z19+)cl@^0Q>TF^&Ty<(G9eOWEvYF}!V+gl)@M|x zlt{+OW&QdJm1>!I(=8JYe*9UR9!bPHQi~Y1T@(n(nJ)F;rT8nMku&7)RgvXQ%`yoQ z`S(JAo6`yKEX7a;bi3;@oOIhA*@%zQZHsQi>?{H4TsHkH0SJ4g7Y5{*2OBkh@Yit6 zlT79`s#OWld<|razy_2kvHR%0?SK?n#=G;mbhD;FaK1+5lc`Xt#2(jc;(+U4YImUmKyhNLPFKr&M4e93I_rQU-XBm;Pg0m>$$qsdi|s)U_3C;>1c zjtU_kHri7Yt_7jKhUBZ1cUrraK~aOVH6!+3vsJL083lm;K{wDqMq(!U@7P>MW}q?f zSAw@gbXJNVC>jTyW(b9lCpnF>V;j8_E~_A8YGw?)Qu)lpxJY~S7r`=Mt%Ca_BLTQl z`iZhup5{3Tz#Ha@kxW(#f zV8Q-+6<2#s?kE--@DN!b=Da&MN}OFn`*u}J;JDi;5urV=%yaL$Fqe1R}A`5T1m;h>mzfC~ZO^{v|4~v3ED#hK<`kIIvkx?Y>LB`7tX)wg0Ux+KQTS)v5`I8t7FohjeX7z{W|N5J83w zn$Tb)8#JNDDdq*V5W@5-I!650s#nKECCkc|fZCp5J%KOu-)pajq2vrI5%Nvb&Nj|G zGQd__D;@k|!BB8*Ws53|Gy9# z0O3Uwzzo5ByL4e$7OOlmUFY#5`5p0B3ilTtQ^l`Z?6oXFL}PYIC+?WaYLF6`km(1j zQf&pvwv8x)vgW>$jg4r@m_mh;)e0SRz0P!~*i*gg{2-M|J{#IENhB#o#+W3w%3w-& z5L04MD}^MDLgdS$ZZ>rjt+sY|Aj|Q-yN_3irl`b3iVGnzFaFJfl7RG00p~20;L1-b zBL*n5eF=)Oy-+7}yx!C-Sh*0Afz1bmiW6c)9q0nK_3B0`uO$%Yw)j%fZoGX|*yj>A zM78b7I{}mn^%ElE2O)2WUInFOR*8*4pb<7diEhXu(~6Hgi7N6nQ$>HYsJSn`UO8zN zUkYr%Ek^pvAQhz1qlWqt+%7zUA420ymz<3Be zriImq*NbWDyR<`?US*^=rtSKywyH9EgY}=Dg}U+cFpHgz->oHr#6z&k5Wbvd@cPPN zz0u04;t!I|9KXchDdmk?%K0Tat)G74b+nWFZPqvVsM8F*LD%<^f2VZord@f_yHf&m z)6Q>XX?+)1xoHM)lXd{&Who;d{krq$8X(DHS?v_Jczo`4bH^?=cUt|7wsXZj9BU)} z6zUc(y*C1rFvTTVGRfsPL_6i3Zt~>o5!mR!N=q|&I_|Ms652gH&`ei7bARO(_~ul1 z$1&q%en2pIiR3E`$tqF%1Fqg~j70#xO0vofcI6$|UmBA#BfBvs^{o-yD>#B=dIBMI z$A|7dS}od+$uEj%B(db{Hp2`l!^D<0WK!aJvL%B&>L5bi#X=Wtvj*>@QK_+rHqFK#1~CT9(P z_%3+ybI%<@0bpVPbJ%60KEDhtm&bkwQX7ez6Tj&Y4wvYvHNi*rdc^vN@PdZiKvavo zWX+RTdpxfTv;`I!+(pMfe6#}p!=0!YLW!h|F9h4~wL6hTotj0aIbQXxDx7;eI)IPe zg^s9_s?b7*6d@l9I!PK76^${#7OVk8BoTv&It0PQ<~)WklyEvl_|#qKwMWxxlNq%=i#XBi-OAgIv~N zaz!G^!T>3TlpFY8Zb9X`)x2|2r!DGLoblMXTrv_B+H*>?mYEFdifKv_iIdAD8!fP! zj`rF}o5)~!7F3+@N(rnCXE)gx6v;uZb{Hx2Y;xVGo!?lpeJ|MrYi90h=eJzeCz9M} zI>|=63M^`+nuI3Rwun@xiK;=EWM-xKCkc)+IfoH9d;F=t&ciod0wZel0%|Jbr$BWM z5O{oi@d7$q%s;Zc9MB&)bLj_+FQ5ymTp5>63ue51FUpsm>J;H)arBJ}MPdtb>3YmR zzX8@5$r6vfHNp+}{##HHem4%tz%Rtn^LxwGZhh%!hHYKwSUi@Sm+580w{=Dq?bgzQ z`cpmQrVqVKaLqT-bgE(t_&blGl1I+L3-djXqR~`E=`;F#{I7q8wo?^jE#mLCqy6~3 zG)>a7Nn1+*fIx{URbQdR#mCV-rc7Dd7JsH72QPjbt>}15BC!%VPof+lpI)~UvA5WX zASSY&LLLEblx>&bY<%-G$dfqz40_b$(WT{JawZC|QSuCn1HQ)p=Ra!k7pnlowd@jF zFlB?~1u+&l@+>;Cm*u1&se-Kd{%28RsWx>4oZ3JF6W@Clb?+*WvpiUAl+;fX=$xro zpM$}M{ZGN0`>&P=6?tn6>5ZHb;KZ3Y^#kee~@Oz)2M3FXhqsfII`W`x5NYUeIcAZmZ@GQgW z6%b#_6&k}gVLE`H`%m;}Qs{R&0WV#E_4ZbwkR4N{50Z5lIsZWP+%ftY)D5{m65U=} zfg)vL5@2&9e|!dYh|HuEFqN33bD{MW_y@U)W)uGZLb27(XOQ?!pd?1^gz)SJrUjb0W16ij0Y%`Du2kg7Dg(m<7ehMNJMbW9u5zMCj z6fT{_4p2cEzaNkekG~HZ-28Qvoe1X&Raqq(fOEd+9@r3{SabT|ej36eDvR`C=l zp&?TMW}>h_^>J~RzEPy)B=rcUG5aK{3aOfiK1@E_EhcN?RkQGB?vw~lOnYRyRw7ya zMtjr@RQyJIq@UcnYGRN0gWn+YK8jt&;%DuNCu@b*OnYhg7wr=^gF4~$GBtiM*^ro4 zK666I-IWyTm+Ccu>nW~EqZ07)Q3%+3_GNU8Jc}s8EjHmT3g3&Z1t6nu{1jCter6Ni zGclaq$d4gZ`so{mJp8;z$Voi!5bn#-f#JR|1T~2!DXBMdp5eQ1L1(JKl9G%o>JL;| zSG5TMx<$f1DJd^(BMJ8z;SC`f1npOsg&R&Y-vHga$(+Kha!HZlV@XT^iF$+&@{h3N zG~g_s&~J$PN}7(}^K{le2-#bO{PnQu05!cnVI;RmzoZ^15o+<@bqY23!6j5(EJv4s zMa$w#5+8L6c2kZB@k*3hBBxt;S2!!$lDlkK{1CV!!9PW2m3!~66=Xf2D}gxImf$@T(&Yv5XJ3mz*N#Gjt}VD?ENIO z6$}(?8OR}lU$}ru=vHSZQRn_Jq_LoGN%*Xr7!gsJREGOB8-A!1_U03nfa_V&C%DmW zidzb+-;rn^5DL*A5nUAKqI*ax7{xMrM5Jkr^-8oFP5`?Tf=#v zD_*#}+Nf6IS9b_MGHJg&J}Fo_zhQV=ieJ*~~@Ue-^r=;|GArKxavJA>I5QM8u{PI(90AqSX z>C*>sqFLjK2fv!e9UJ2l)sClZ0Fs+#GO%!a;5$5mIC=l0xaIP9nS&QRj`S zkfF&KNKl4GghbPLQI^#5tRK=Jxd7WkkxLVRT>8Q;GY2h&5A<|N+U8a*HJ)ww I$vGkPe-2co&;S4c delta 1712 zcmZvcd2r2F6vyYDbKjD@Ebrw#NhHrpqD@J&394e~1QRCc)RMH6lEqSyT7%jqL|U{} zX?{3EMluZv2DSXiv6YajXk&{dYUv=#R80lx1QqQ~)T5pL_q*qud*+_=`+mMRuh~|f z_1-oe^gM_`{g7cMXb*!Dw86ohG(EUXzvnT}@UOs8zxG0_b0pH;)o9YjI|k@=juhkb zdJ#btiNc{R^IWZExhCkjZM=-yz(^DAs{w!gazwV!PDLHlEwO|8Q%n=sG_N_jo;ufV z)hf0IXcM-V>K=Nwk&eV+n4YlrT_e?ZM-y$1lU6;xveu#Z{mqP;v%XMEzNcw9_gCq? z8vy9XO!TJugXpd2Hy(6yY={^lIHs+L2Xf@0l_SE%Rl!HviIOmWoFs~k+;foF2=v-I ze1%7(h;;@k7%ob=YJ>|j@c z$h31vnQ$5T{$^n}LP8uB&lizgrHc;8J9dlX9_*?ViGl-IBzSb4+H0$p%l2@0{sO4;ti(+r&ysz z^6pm9h!k#@R;~+zhF1JtN6@Ss)dwmpTsRnd37(b=cRV>b6}*9urNaQpH^;$TBYhMv z12}dPgqyf-2Be#~AP3F}4$1}1#-o{f#d}{+l8F}qi_zKsb z*1<%1nKG0L3q=UeItU+{IH(HlBJHe!QMBa@^w%u0ezfW=IH|*NRjoAOO?V!*k>h80 zn}cd0LQu{HnBH=xZObv3zPtii&Bp~a?;>Ql6OlCa(zC>5%D)bwwD>aQxw9{>)%{Ow z0nNYqQY$B&BBJoYg1qLJ8ID82enO)A>SoQAC_D-Dyh-VJv8BNcr~ zOUJ4g`qlCqO?)#0zp>JkOW@)|*+_z>)IbkjHv>BXDQPqIQqXawMCzQ zcWGJWMt9w_-Ld~F9P74-S#-}PBe|py4M>VTFRm`aw#bPkxK^+NaIG+Rj){wj>lQkP z4vi50+f5&oG zfZEJ_q7eg)l<^cxIPfnF61x)RKuL;BJ0-0{2iHouQ#3QWo)n(GbnzNGw4w+zxz0fd zy>%M=*kzWl3L5Gm_fWE@97=~hBpf~NkY3AV58eM`GghczGhO0TRFrjtIRwnTpkxRvYo8rUhO3s=xMaPLW*)f zT9hpPX;h5t$opeeKTeF3IVM)nHvuW$o%E!;bnw>hvKZ-Tg6zXXddhdqG{9T7qbo_W z9e3*|;{bEq(C5 z+-IQIQ{|hKTZuvRS*o1cA_nS`CigbSoU|rc{ig7AIS)NUL$wNzwk@S>$dHExogXcu T*>8+A3sydJ&Oi$$%Q1fg4(*M1