From 202a263e250755d82e456a2028f3f6649ac1d9a8 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Thu, 4 Jun 2026 13:35:23 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20bot=20WhatsApp=20Business=20API=20?= =?UTF-8?q?=E2=80=94=20Palmas360=20inicial?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env.example | 24 + .gitignore | 4 + ...sApp Image 2026-06-04 at 10.04.54 (2).jpeg | Bin 0 -> 109926 bytes admin/DashboardController.php | 590 ++++++++++++++++++ admin/LoginController.php | 128 ++++ admin/v1/WpWebhook.php | 376 +++++++++++ config/db.php | 36 ++ config/env.php | 38 ++ middleware/Auth.php | 88 +++ middleware/SessionAuth.php | 75 +++ package.json | 22 + public/.htaccess | 9 + public/condiciones-servicio.html | 170 +++++ public/eliminacion-datos-usuario.html | 179 ++++++ public/index.php | 72 +++ public/politicas.html | 165 +++++ server.js | 30 + setup/migrate.php | 94 +++ 18 files changed, 2100 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 WhatsApp Image 2026-06-04 at 10.04.54 (2).jpeg create mode 100644 admin/DashboardController.php create mode 100644 admin/LoginController.php create mode 100644 admin/v1/WpWebhook.php create mode 100644 config/db.php create mode 100644 config/env.php create mode 100644 middleware/Auth.php create mode 100644 middleware/SessionAuth.php create mode 100644 package.json create mode 100644 public/.htaccess create mode 100644 public/condiciones-servicio.html create mode 100644 public/eliminacion-datos-usuario.html create mode 100644 public/index.php create mode 100644 public/politicas.html create mode 100644 server.js create mode 100644 setup/migrate.php diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..9385fe8 --- /dev/null +++ b/.env.example @@ -0,0 +1,24 @@ +# ─── Aplicación ─────────────────────────────────────────────────────────────── +APP_ENV=local +APP_URL=https://app.palmas360.com + +# ─── JWT ─────────────────────────────────────────────────────────────────────── +# Secreto usado para firmar y verificar los tokens Bearer +JWT_SECRET=cambia_esto_por_un_secreto_seguro_minimo_32_chars + +# ─── WhatsApp Business API (Meta) ──────────────────────────────────────────── +# Token de verificación del webhook (lo defines tú en Meta for Developers) +WHATSAPP_VERIFY_TOKEN=mi_token_de_verificacion_secreto + +# App Secret de la aplicación en Meta for Developers +# (Usado para validar la firma HMAC-SHA256 de cada POST entrante) +WHATSAPP_APP_SECRET=app_secret_de_meta_for_developers + +# Token de acceso permanente de WhatsApp Business API +WHATSAPP_ACCESS_TOKEN=EAAxxxxxxxxx... + +# ID del número de teléfono de WhatsApp Business +WHATSAPP_PHONE_NUMBER_ID=1234567890 + +# ID de la cuenta de WhatsApp Business +WHATSAPP_BUSINESS_ACCOUNT_ID=0987654321 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6d7a750 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.env +storage/ +*.log +.DS_Store diff --git a/WhatsApp Image 2026-06-04 at 10.04.54 (2).jpeg b/WhatsApp Image 2026-06-04 at 10.04.54 (2).jpeg new file mode 100644 index 0000000000000000000000000000000000000000..b868a8126cfdcb6f63f648c4310b9187b92ab53d GIT binary patch literal 109926 zcmY(q1yq|&us@t&#oes|f;$8)P~6?!-HJo7;_mJ)1&S3YPAO0vf=i*eL$TnL_T#o_MDxa-OSGZc4qQ#<=++nS5a0$761eS0KiuQ{96M=08rk%!9v5rd@Xob z*jRXYc(}NDcm%lkc=)&k1cU@cM6VSg0SO5S0U;3y85s!?2_*$32?ZG$1@$XY5Cc(A zP%uz2&@nL3vCuI7HV!T(HYP3(E-nrU z*(=-c{{{efsK@|>8AKp0009q(hzI;P1SA0f5P`1+@c$Pe0wNMJ%72ajPcz`Zc3c1u z5s35#2^HbZ8|44#0z|;WMZ-dRP+&t2*@L&5QAR!?mA|fII5s;Dpw?94-?kfY3ga#okkER8eq&u=@ zC>^i3x>jl_kyNv}mB;oaIPClE6#)PNhy+AJK=^Oc|0_S`;;Q%_GL@RItbNDD0jx)d1*UO8(wAVyP-yr(+;!HQ0R(CrlW5IY z1w}<9WFZizDM&}6%7QFWXe1EDxe>(yn93qAe}3N%t$z4Q_ohMl7$%G{KH@Pxs6JuX zk~7ciHt<+IpXQ(A<#`Q%S~>YJ=YZX_@ejbdRB$uY zJ=+84TNd-IruzivgP)3c-iy4oscsNDty=BN*`N3}(s4j>_=8?PqF;OnGYdi+fhqnI zhYsBJl!u{iPv0Q%)ju8DBE!azVrjQfp@-91Wg$JUCvi7$HeN$E&WaR_Nn*m=4(~8;lOic$y6(i{U6@o}2h}kRI=AvVPBnEv$_dTM>phZnJbXOi ziVL}8j%37>OP|Kpl&A3WW_a234Z)EmP4&2~au&l4x0?y7vEQklu04MFY{%!G3*tW& zsi2)+dyLmoj*YDCIeEr--GBhV7{g^y2a-3?1Cam#?8Ur4w3C%b7vQ9q%FekP(N5H* z*G8GuRXNOUu%wcAW>SRe$K!K2YlXNz&UqD#o(M@bJg^8)2dbXJpRkts)ZteUZ3Reozv+c!|ajhYQc-;UaJOgH)+Qs2Qe46VKXtP-I-rsYs;tG`TR;xDpD_n zYPv6eL2us+o>v=g=mb`)y;l>KIgZG6Sxr=9EX}(zEu0r)^SPW>mLA0AMpOvNK}7-C zQz%dTINLow5-7NxbL_&FnGXdjMoihX(78=OQ(bWLrp+OQ45Cf8_fw0!r?ROd6Ku@J zbw=65*UT5wBnGIx$u#X%e;lWt{16+U;WHBnrqlMC{uGb&%azqBr`;czlKL*ls2hSk zM5A{xPA|4JR*MxxU6BggZsi3}WD*Z}|te-3~fQcq3KZh)Wi)2_W8=CvE$0M+3={>E1n+MnLD?eMeH z*qbupn9HF#o{!h2#tKMYlC_#&5?Kpsn*0K4Q#Xt`8F1}Bo#N4)6N? zO?2Yd2o~qewKMdK&BDGZKb$H^6Cnf@2q;$u04#c~u=&T+k(SxrspP#ZzS03)^&v@_ zApnNIU#X0HuIYK^@i9n*R&zw-4vLy~gPeDQoZ-tQzu}vnYJxY&@Zz#0wimFQTm`ku z{Ts|D)NPZa?Vy+s{&b< zb~YGUlImAupIm19Hu3Us*@(o*6$YCFsi((U?&! z*dvY+j?-CWK~W0wX|r@Bjn&gPzdD|K{^ljJ7HtIo4Qdwo&2sJ!R(U-6TG092n0E@U z_5Aq$+%NwO*w<#j*E3A#tQa}d^F)?EZS8EG*jVtka{q-GY7~1oD8;XyQ#Hs}*Dmse znCJh?bN?qL!BKR6ySXPv7L0q2vaY_s&fG&R<@*VTYKkEKhWszfr0_zjH>|>{8vd&0 z$HqrT`YgZT<(1bh^9TD*bDisjD43gg`4-A52R8d&a%!>+tG^V@L-c0Ja$7m&L?glx zw#Y4?a1hrHN7Uq|Z-sswzE?85K3%N6%5K|l&Q`M!*r$f&x~Cp}?tw23ci^b1iTa=o z`?SRR8`n*{=8XARc5-Y;OW{EjK}`6iezs8tf zotR*qn@Fs#G1YQfh4W4yE+jGLudeP7H)@RU&LzEDToViKSmMq1-Pz0+y7k~*x`VE_ zUQbWex@wUxl{s-0IFtrbeW-%JsI*0@GhO*?INKLYC}xQe2Fm za`_Z0zRE_~{BS_AtuowoP_=AdPTTvn$8bBq81xu=T%=#r3(ZwH`-WBY+b@8z$qyk2 z@sd_7;wts5C`kF9Q$!UWN*%U^4Ua5LPAac7pSJ-nQ=V^>7i70!9-SYI>9|bF=?Vdl zpeGD@Ht?HA|7Fr;HI1+DNRw2W*KlpC-$^bW5W`n~l<<#OiSjJK4CEshq**z+D4kMg zBc06w5b{0L5Tv<_sD~2!nBxQ6R*Cwnn;f6*DwVzE@yz$b}a&!-LDXS8hFMr1?PDz~GaTI8?fpFvp7 zGqw^nMN$6y=D)z&_6{)3cl2Hp#;FU@QU|uFhNKhA% zH%%~A?ywAd0Ize!@?4mbok%UQE4P(IH+LxNB;oyJd&A?;J^lsXUi%ycLSKPaGP^SZ zau5bqi;^TQ6_jXJmKJyK1o-Vb7a2Q8dVhelHwqRSUXqynS$Ty<&UNoPyY_pa&yN*4 zv$+!#cZ_-6g1ME)3_XWXZt1&5R+Y@1rwxW@$7`dr89=VGv`f+<-*7wtN8ZX2Yx@AX zg%?U>$8bQ?V8yW{8?T&h7osVy-BO)zERDMOIjI1?K3L5{Y-FAZJy)}1Ab2m^qcrl? z0@|Ra;5Jownv_(Yt-#M+Hs;=$$oK6Xt7#EZ%gLjEp)vmaOt6zvpr+mIPDX7cH|)?C zS}01s`&IY|GM(^&rekHqSzp(X!={;hjMvQ}D>p%TUX+Y~YgW}Z?UrYWo-{|GCJCNf znwXoNgGFI}%cDnArR(sj3;Fan<%ONp4;mF4*5pybQ&FzSUCk;?g>Sh{L^1Pl2_ z)4z6T`;$YxigLflo?7&ye7TS>{8E7_{-c7<_-5t+sAG^kl%#91|A*V3amCVo_W z2-xL3qTHrM<-uu{vofN2-A=isb2?42&w)#bh0^Il_CY9r*u$w>n8SA<^hm+O^O(5S zQ7I9`V&I`51yo|uLbSD9Ppp-WauJ&Cu}+-CTj=~WkDj87*I-DLv{Fud${d^9Wa*5S zB5r`=C=?a$?A*P~o2@wIJzbDom=#-srJUG;Z;r~B$Q|9Fi=~kwyha74kburk8yOcW zRC!CkvsRKKE{V_@BhQVR5Dgg>U&H+%MbcqzjPfOhZ*;-q-R;fc;P>JZ1^Dts)`QRs z=39{ zwp~nUB{L>&8&145KNE6f*JKMzK_Kgs%1f6iDpmi^Z&Oj0mBAc}bu}|Rqw8#Pz2V_o9h%$IFEE}BYTClYuiYi_jzCstq{W_DHLj^ zWJ-FY`Pgz&d2P4KI#lduR=m9C^XGVTs-e>fznhdh-Z4@+6p6s8a8%124a))H(@Y|7 zQzFRF?o+w)6uk!aG0z&Y$qor3bI*ilj{R7%FFRdw`mCu_Z!cBgm(%%gtco{0y9=k+ zT}`&4X1snE#>@Uku@xs)%ttNx`Ey%Vx$z=EMEXj6LV9+5LXaiK*3p&kg8gPt0TNKn zSjs-6-u-v7fFwJM^XGGbKiM%VI}Hg+GAr|Bk`~iEfm}{FQ-^XsH0enoXM1FRazAMu zrVj6NAM~Dv3lp>RK^M7d@H_Em@f^@JoHHu)Xip;*pZ>H7G!*>w82dFc#}L@pn3FGh z`(e^VP-r@D?z*!|sHag1c6^Rak^y;8pTq3v2t5Wsq8Fp0UU;QBs+URpYk0 zulnmQhfl#a!};*zOuI#2<8IZ7XinE9zthD-D={-gcwoIK78|_trN}De#?vm=Uo3D! z(zXI+Mgz1SiBFhP7e4E2ijvdUm$oh2Syfs=13j}gVqJwl?>`<;I1yMDf)HXkP(W6n z;@!}<$XC=D@^mfuD>?uuMJK!G`v+lT1rw-NG&3qJSlo3cJF?H0@vB+9CT#;M{)T@0 zeGPpqqAGu!oLZ*(s)Vj@E`{tCH_Y&kXGUlZ!Bk{ysIm-@%l66Gwdy){8n~N z>5tBt2c#P_4o!c(y@R5~2M5vLVm|Y~8W9yl)5kSVVY#)wl)0i~z zaXCuG?>b59Gv`7X0nPS6og~^Q=hjKNEJ#Rcr3HtOBorw6D9ZcQp@J+7KHiKP8yxj-Dc>v$=lNaJ2a$v(xCPX3V*L7+djQ7ZtM@U9=a(u(e{5%)}Cz@Kmn~@szPO^!B;* zC*3~2fszyz{=py)ir?kv5?oj4wd*=8_7$~TE|y+StyWEV%zZkC(Ta|$Q3dcZCM9dy zO_>&p_Skq$dgR6D&9k!2=PWJ@)nK7k*-*q!iN^Zb&H6k}%#utGt~zbo+|c(?n@PNh zc!IVq0v*2U+P?Y-ME{t!I_w4%3#%7}17nl;CM$BrY$l^(nGD5^v&?FCyzGiAJdF2e ztQ2Ylrs%178R82gojmFU3Qe{QW{u~1{U3h^`1jax6jdiM_7*2NnFL2CYMd^o{r>%p zRsI&r`?brCqCJ}8s6a@!o00jebSJo!wtzc^DW#99C+PNTok^Vl!dDJ+-H;to*xOac z!&;rfLf)QmV!*xf= zIkduMkbh{}X=#JvpeNQYG2D?N$!c}k)x||-uAP0(&%yj9{&<`OJu6m|9cxMr%1?-| z_)ch9-J?)>&!lwd88NLrjm3PU6K};G|E@s9zY(+s*+wSq}S@^tI z>4M5EFTiGB#-TnOXH7nyV>wqTfEZHgM#PV&K$KzQM&j2z{l#CD^uq+~=*G|UL-XN| zTw7xl-|^v(MHAL|g+`_PBGx|M8V|;qMy?wVyAgr{!&G)qMQA6wyzYLIk%(e?V=ZJ7 zGD)I*E{;2I*Fx?omvZoVmd`;;Tm_5EJ}pdzHU*VM3nRoghg;A}a?Xoh-By#u5!WG; zKqm+^iI710}v<9Up8Pmka30CJ6-DHR$UD&;meGV2Lslq%V&2kuC3y#+V~_LI_$Xt>JS7&1onB7lK}CGzO<3IFDyuQAa&te%`)oPONGtzR56 zbc~*nr@XEtqaDIO@WoxryZ}*qI3t_BLVwKiZOy)a?&0jIU*4|R$om2(lb~QZXK(0} zdvy&)bK{$D>Fai5$yOMFe?NSH*(DGjj9C#x$!oA#>R59_O-GU&I_DC-n+@`H(fGuF zoI!(!JRklxrrR*+Kp>d7HRKga=23u|b!3s1Axs}zOc?}s86kI$xUewAo2tO}(?PLd z(~OZffy#x4^vYfwKKTVV&NiBwRSFV|NeV&ONXdGIN~X!|zj{crJ7Ciry_!(?1vKkA z&w+RHsZ;SP=p%&*1$9>qZa<)Ofp2YL>nw@$T{#9hmHK|wkfyv1SR7!0H9Bw3#gGz$ zp5l_qu0bbdXp5=);rKB)3rgYZlpXWZGd~*qH9F=6J$*VzkbrN|n71T{V=~FN+thnz zzTn7?^;j0NHP<=2@JO~Ai01DvGVCShl@Ik5KE-fuIMJ;V|KV;S`A+z9&WuV$KhIm$ zNGiplqy~j!VOO9Zu}@Y0R@Z$W_PK7NQBp6`r_OIv-lGt=Qy+~`$^KIf-_4(5U5`yu zI-#4ZU6PiW%hY3kGr{b&WP0l1zYKNf5B^uxZCMU}-JQLHdlR!un{SiXu8jM0^T13p z36kx!8Z-v;W{hHeD)-gIGjsSg6aWIz1h0KF;i}InJfW@WZ$R8*M>lT%t8&G^;-JCN z#p^KH=-z_BzkOL4`_%i45dpbH5+~5(V%tI$tEu^cPL8C2X`+r{f5dDP#}+;UmM;W3 z0{XmG#EvaknBkJ-hLo=W7bDSWZX~|4pLbyIx_ORF6y^xMAb%Uv=nXbri zz~2uTV$mP7PxFp%ggRYrAeYC*notMTB$tt>Mbr11x3+-=L05s8eep&SXpv&TT|>AoOI1y$+Xht;@&~8<$U=ix+ap=b!4CU^Gbl)iBrk#up67> zE71=$b+6+b4a+=>2yh zoJt8N*$#(YWVduv`PF0d!#$O%PwnjLKrJcC;i6;`$HzZw){%p6<=(sZ(=LTngvLe8 zks?Zxg3LiEED^N%d9n5!(&{+~9O5WH6lh*|M!|?&>ESaOlykB6@%E;OS7c}&R0@crBNEtK(skDrC37=iaX%HA zb@ib+mNZ4y(#%MiN8$J5qcC70)Rdxy=iwsaVTAw?rBvtuqMYx_>?(;0ghPcNk^JK) zN$Oh0aQy!U)C8?u!ds_%p~+ASou1d+FnTTEgdp zOqLO1&krjT_7i;%PC-b27o7h6Nn|tDel?6VG~{(yRC7Sie^I;FpU@HoliZ2`7)AlA zvTei6`X2kq+CEk{mi*N@OeZByQ@YUFo+kX3D-$%6U*k+)M$RPM*^L1Yddua4=&AGj zx#(js=TO?6ITnNq06>Busvs%@rKC!vxqxASeo`(JE`Y;-10t9+pqhuqkftMj0yV{~ za2rLTj855;WyMkuHW7gw!c9gv1@xH32Ll7t0vf5B8)I~zloO@s)Tib__SSS#T#L37 zAhwiJJOy_P z=3wS}VLRTVtL68ocY()!ZVXXj1+=3Wn#8u_S-ZUEW6osc5#&g%X{Rg@-m+1fG(wR1 z|M7l(p~ct(NJCx&tdJqp<)h9Qrbp7#y%Gc>T6}ZJ`>Mx_s_csF{HuJcWABkK#ra29 zPklDK^$$D2YWe`s|8NN{F~{O!G4RfZ&}2z5r7~lNtB)>{<)PSyB1=f4L|K&Pvnw&B zl)eUWk+`v5XF-5tH2WCp|A>?*h)c&3uYvVWEd0k^i_4E<8aG$}KY_{ZV(k+qotA?m z$Kp(Y|MUpJ1!|av4+IzIB#E> zWTPys`8>6ADNqU;D5k{?^Jb3vc z{K~eD-vG-#D?zdug2W22bjuk}4Oc#U`jF&)vP_~^4Ljh5J~#87E*IyC&W{Zp9m*si zBlZd6SQWq*RT7q);AWCS{Xlyu@gYR<^%Er?6Xl4RNr*w@=%^72!>5FK>TE&0jKJdPBh+P{ffsb`2jhV~7)<}xc3G0VbPLRrw5z!mfo z$VkMvT0~%-J(*8B4U$p$G>(%+X+(K^f!i~l7;~O2o(%T#>Y-`FU@l;ZC6><~-R!|3 z%B+;>XPb%h9cWMAKY(LkK>)Ndy|L^#}>RTIIxH1is1u7DWXm?sc&*_*lZgE(O?98NkyAf!AK$o0n6$z~eNw#Q#I?waYgI9IOh0U~^eg`u!e zPd4op4Zfp`3)mOb^D5x|l{+Gu;=z$?YBP%$wn~~;&NKVEEV!?!F0A{()qBT%pXKqH z$JzV8!fiS*+=$^e6+<<-c~MGUmba+vsCXwqIGLwAL+gr}v^sR7(8Kv+t!*5M%eM1C zT^}(;;Z4@0?j5@z=z_oRKJRiPZL(!gfT-`D!RdRRWEppZu2E{k13Pkwj13zplqkg+ z9wQW#?MW{>vhEvP{vIC3XEr;AsO^?X8k9rgD%ZDzL%?Mz^?h0Td zH-=G2&qtKF80!-|9b zHP!&iNU)3$${zC|yAt!L(NtcKl<_C7k+vc;fnJ^K+?Ql-IO|NeP;X+>aIze%Ge|~L zd5&IFp+x9a{&ufy7t@`9g2sSVzC9Kqot zKTb7vzvE$iv$j@ujNm~%PWHIp#r`iYz$Uz`Q#N`jM zXGWNbaG@_n7PP^i3J{rl*VAYNv&oB@C+ z84dv0qvQW%IQecqG$M zMp@*^LG!%0gU(5T!dF63?@Jan>1Y;3CTw}AnWffp)QbgxZ(IvrNKs#7N$;_ z_)~kkyn?NDh*$=sP!gABS&^}o&?uO2PJ}=XP{9HW0dN6WfSK1d005L-URjzmV7;yZ zIl%IDHNuy!MPr3q-ims1O#8$AUXs|={-4Y+8c5ISX4(njJhXBc;H5+7UVd<5?2cH@ zYw%b-dF@}^gEb`MeL>+ayHz%;2^tuaLP`ChnPTC!nZ5E(fo23?CB@%@1AUXKASZQmT4SkmMwgQ09`_pt|)miYl8C|s?Q>KmYw-YWlw>TG8GDCge`;%>Ilq+jSA3O&MC8i~%@gI@7T{aJs ztwfN9JlJMNX3NYvDw6Okt8ih~XxY5&6zXS)V6q`Kkt&28*O#%MrZFQ*P z^-2{(WAaABIpi2W(@MRNspf=@992bNS>B3f{JoC2-FNJ!A#_63Wh3jPQB;V1Hsu!% z{!c2x+H2Yq-sQF30%-*5uJU}itpPc}E44J6<`l9}2~bXBb9Qw9&!S(P9}LmNmK%hl ze$3jzx1WWfn?%4pR@n#!?9~9LotpJhTh1W$PO~9k#p!DS4yrH!C@6_r5as2%+WrS zOufFaQhD6PTvBxfkpVf#8U)hdhlwDW8l6eZ%0|B*k796&FTrus&jXeAPN;qic>P zTuf?h8F@lHRHS(n8a^T_2!Y5?+32?c*W`bmva0F=34?Cc2+cQ9B^5EnC&Aa_;K~dG zt1uqsUWce4pL?-lyXrYIC@I4u=~l5wlQgb|8e~`2n>Pzmca~nnuXl@m+wu8R#)ka0 zDwjkg>h36jD;kLlQ>B&IXU#UrMQC3Jt%Oee?yG{;c~TN$62w9}|5fUk#NF0m_-Ji5fsUh_cGaN<*{54CGL;M^tk!%=HzeqW!))U4F>3)BR zC&@Dg%G0O=<55cJ=$IP*o{pGN$s!vYR+!OBBIUWfH&;bsVN5eP0MDs;-{GsoC|}}D z+330=HveHP=Iv&(JXH=>PuuSzt?z;-WBRVzRJ^p>wd@e{n`RDb5h4G+Co;T+1=5L=ZHU~z~I2n3B(c3h-s z|FCH8%er7IgH%4XYMt?xMo~D%DW2yW^MQ=bx-!8&Iy$NHD4!4QEgIMDKKtK0DMN&- zX*+BieqB|5KaW}m^v{MDI=y6A0@!?D9dApYgB&R@kug!LYXbwjV40ddC*O@zg1O8n zztc=n!7$l^@?xC(J^FiQPLkP@L}z-8Y9br34YL%vI zYe7@Bm9ks!i5<*5xEAx!1Q6N!3c;WuWbiK+q(rdBaMs4k#9y0^UOmyNA4G)v638h& zEo{o-x3^mq1K7&_)84;9T8q!D35agce8)t!beQhz3Vmr=Z5Iluq!i2t;OR z{j##w`YADD1}4J-cY?Z}`u5ra0WYmn0vIfUm1Ov<-e~m6!*N0=DbloqxZk5$%3~`= zp9ByeJjwS`b-mxz`~xszUlr9CgYos;BNK7Uq_gZ@q!IlD-s&HhrW;XqyFH^WZGKyh zd$!-6AVPlgt0&2;vl-rTQ;&bAW_tFVV;z{C!R;ur2}5!~j3U&!tcfR#+6fUW$VE3e zO6wkp26XYi4Jr9reJpkiy&2+ejw{)z5rsmt!)&c7*6jK|E z@J^8(y!3lja1!d2y%*=%Xq7E$=^!wIMzaTo^60wuNyubKwBxCk>~EBBJ65BZz$+r*`6x2Y9~96U3TW+nsP z5b+5SbpOHe4*V_1x7hzl=Bh4ziWlq{NjcP8naJoi|DDpGv&ye7Etm1Sfq$SJaHR84 z=1Xm}gA2IQUk+|M!|lhF6h~F4tirt6<)2f@TnbXVhpqRP?k?nn9SmZ_z2V3Jb2-8? zTWm*>wQM{MZFLPj>etMN`3s+F=KVF5;K5qEoYG+tD;0hR&ci=BL4=zQL^&2Z22es0 zs2s5z_T4Dfnn`X87mCz!6QH*7Av76k zHrRBCm?t}C7!YTeB(G`g3%?i6U+1sUv^dODX)9t!UX;0sjj+U$7&i8fNSE=n+Dli1 zyi>o4W3SB%eGjIHn?DFzToHb+glZ9vZqu~jR-swq)j%9gtJEml58n<$W8j>}_=kPb~`es}(Z z$Q=$QC0#Pxr37Bta9Jr3_vyy=^a*;PgS4dz0>q z;ztkQMx&yL>=u<4b=h`UisO1nf~`*@{~vgYJ7wx{03s5#>O11ojCi~eTOipSFzZfR zDWkOCAnhD`o{F*gZkFm=_tqk5>$Hw-$AFj|+HQ;nCOR~}Cp(MNUB310`%R)3lyna~ zwY#``&R>x2^14A|xZJC^*ZPp9VscHzY<}-WZtxEfc;LjlnH;dBjV;=Tv*Eu4m|L|O z`uU5^ZmCAAh#I3;Rwv+aJ{Ey9iyas!^$*aO=X{GFT=7TuqEpBeGl8#h>> zM)lQCHR#F|p@5x-D@SPMwpd=Y;&6T#!c#(V7gSPmWmynB{9LLMVuPg~`>qXVl4+{! z5;J@JnDn8J(QxR_YJwcKCW(rXD*g>PB+BeBPYUrPo9)B%W4~f-i|KYyv|2j<+5**| zF`A)WN&-n@_H@;{n5GHcuqE2o%l%3M_ui*s51AE4(9fz;wgZ?6ES30dT1v9tt;!-tLTV^Cevbsn)g97NRslaPFK|1q5& z+w_em3s1=dC}#8p*Xd8Ghy4*q)51MNwK9s3=^ua@-7ovSNO3CFgO8py$6ReA(dRHH z$_-B1LffBE^hfFRT|2v`ym#Cpg1-TeIVw~~=$ZnUFVlaSOKU8DUZS}yLjSl&|1C)& zN7%vt#NX{+Z&!BcV~!YxYMPXn*Y_CSy{M-k?@GVq&?XQavZYa|A+Q@)kt6y21i5Ky z`sXLuw7@?A1FSA&_E6P_Lc3S%ZE#CtQr6=ERz&sJ?g3P?^I8?YwHox&j;cdX8J|3O zv}bE3x#uN}HV3rWcR7HBD-PNX-U$dmc!DP&>Zdgmacp3zOjzzx-Cs&b#i7$BIhM1~ zNL#oC2R)k)Lk;Ob_6NrlzB*Za7LeuWF-`tT*HdYSMP5JV8RGHMU{D;6{ncU*NO&`(s z!+pt@Iq%PVa2{QbK6S|EF3gz)9tNdDYcu-oRg>+#AkCoZblgX!#qQT)T@s`8XC!)K zj&RzkF_di6fj;K@6b;l zKj%wsPL$J3%e$4W*rWHXAe@ebNGW%4pX2u3XJ%T<6#7>R;2k zQLgAyu16c{lR5cwIDXktcZ;r{5T1WVd&#^p^RH-+!T~f88Q5F|P;icDN9b=G@J?8D zH3|=Irh-F>W$wKe}Qbw)~pp-)1cRN?5}BZ`7K=8AA>(zlR7*%Nnf?l z=VJ?%R?Qpe;_$a%67>GK^jywFqaiv6y|FO)F_sp8Ea7d#ZT9F& znR*zdjYfdHG@4s1Jq$Yw9n`*5>C+sxxPi#&Yf8F+k(H5w-_wzVhVRUGhHCc@z@@qWDt8uIH|=_oW235|5X+K%>9#@Bm`aYW|DAGum|yVajp$hzCkZ;Kb1uL(u}|< zIv=UqJ7qr>TJzBS19-0yE=rf!QtRK{Zho8p_66oBIPS+xDiJ054!Mv zSNnrjkIW|NYD zh2I5Yb6fF>X$W_gJ`Mm<7j``7{&X09Q(4_>cus)0{xqqILeakzw}i2fRh?|bFi~?~ zgtixHp3Q$Fa22agM}_VqrAz2?HU6F*_1($utox!=U5#N+8ShYVH`;ID4V8j?e%_nA z$rC(>PQ>HSIUs?xutfZAb`8ZV-dVqH)uW_^9hrDLl4!lWzOfVZE-u?$7Ws5h|7`6OqQTKH@+d-(usXtxOVw-Rk zW&HR0mC@0@bl|`>FF0}+sQ4e*I zG5ku};#W$vEF9d<2>$?MD*^7ZtALn&UH%p9Rb#x|t+Gwu(}Wk_T{i z*FQj(3?UKqx0)tUsGAOe+2-rCud0iY*>`LwGNliPzhR!5zz>%0!Y6kKlz&!>W)|l z(!Hzjnv+yl4Q(XDI<-9e?uvK$@h+w0=WLU9SfOQRvFF?>SMlmOu>n&OQWBH%?XLdO z#XHutP|KFY$K?yR25{2cDa|u!cb}qd!*OOuq0l|hVkF_b%6?ebwdWteEcm)gp5+y; zq5=_cf$st56-7I9zn~=3lYKrm&++%i_b0&&NY6UcB!_RqBr zxR(_99JfEZ|MtTG#yy&IGZm<%EkQ5MHS$-*{%5%B~Z1{BT^j3Lc*)IPrZ6HaU2N z$EGyX(B;pK94O}5>0R}b?&7zyPh*YH*kGo>A<-HYt2nmC{Y-DTAHqf`7-vvqsR3fUrml zDLy3Pe$JrHxQsvJ0{ol$4RLH&Stotqg2nmUh`Ic=Z<1{<6v-Lx8DCZV&=j^9vv~fQOeyH)w$`;FE~D4S#_0xs zbu~LFuNu#V$o;_JTX5S5GG~EVN8ih}6BUNu2H1mh;vc}e@8uS&ZI@YaEa-0yC&7!E z$5o%^@=da?s|yp1w;Yb$5>eDtj$gBn@s^Lu_EY*2gwEFy7835~ zn_l^nJ?_}RXGh+WX!2tsKHJ)aLuUR9$FEeMvp5pk$k9qgpI;9D0G|#8CQh|Ep4YAv z*tg*?rQOX}3zZIU`81kgA&1%q6}7&xrTla>EnEf`H{Wob|Ya@|L<+(?F?K_CnTrmQP zcX^O0hubu4=dd^YiU~-%Yy~<1I`yu5}=Ukhfws43(IsbgfXfbrU%SSFO9N?%Wm!_sp+*f6 zrSM!N*1-yL>-_dZX7eO}rs~9RD9-F%HAQJ3r%EINzUz1{QYCv!bENu=_qDR2N0WkD zV;O8yC-@l$H{W?q;GLqc@|$YcMvG-b0O0I`Q?LYU&`DjoOo= zR?}VOBs+~P@Ro&)@bAShRsYY+M4Q6DtPTYqe90fu4^+=ddEu7xO%yFSS|ajdPj9xk z+<&&DkDp;)BFgJ^A_fe%)-6eMR0_^t?kc8ibr!FV4mA2@xcpX!XtoWT5g0TjFw!V2 zi>W(iwNaM|0_AgDWRSqWw9Yx_&UsrDEwnHip@d&9Y&Vu|2xb4+=Z2vuWjA~N!zp>; z1DH0KfpGFtjl&(8`PM&6!Q*oYMT?8^X=tD{G+!%pm3hG1*9^)CzpBW40E+1v%fFC@EIf# zf7AdE%w%z-HO}^^yYS~28ZOXw4Gkjw-YosnZJ|!T5Tl`#o33pb)p(=)>95A7Knt-8 z7z{7^+RrIB0$vM!&5#KbD-V0Ut0J>VJCP*Wm~~e?mS*#Z%uXa3;z(l&BgDKyl4t@a zd3Y3EW;pnlH?gkIV>Hn`i=j>nR9ZFz)Ev_j5wj?n4va5wB(5qmt5(|VoBpCb*y^Wp zs=_1$Fpkqu&s|`-{k+SxbbK0jOv|L=_LpYbSlk?4{q-C+{i&5Tt1VYg*^~2)lVORI z1y4xH>6g9>rHjI#eEr`YN<)KfGMPu)&4-RilNSA%$Iv8vKs&VO`4q$O#VhK&zS=kS zDknM=K7GH6E9tX-D?9qk)!fb7ZP#`rFSWnRgslIE^T6C-0&z?9yCN$Da}Eu4Vs_V8 zm@7WIZXbJ>qS?TV*|<^_E7z&-^#*2_ZM{a-b#Vkc@~;3?DTIut7Sl+f%LNL-ymYlZ z@Mi7NKSp71Mr!%wU~w8O)B9LhEU*VW9l zEUZ7c-xKM!y1iNchZ-I$@llE2ox)yq{v|3$tRLIX({hnI(=#r8n`0Do=395>yQUi( z?QjfO8J-aao-k_TBOEy6nU>{v0%LvlvX9>V@J&now*R5hKQ5o1sL$!;Z8Fi#q|N!z&gY82m}Bs1_>z9k zTKeCtDEg3Lz4@FD_wQQ`2>;r-FzZO~d*-POV;RaZs8I8<1~x(Ad+)la9Va*9Pcpw_ z-U^#Fl%n*rO>KC2Xcpgibf;WfGR}bhGtYe8T~_~`#e`G9zn)9%d4`*xx2FkZGYE$kEGpeEL~~%kMUl+ZsX!hVW|`CrJ7my{|*!B%tLnong4d89Aa~xC^Cr zR=K`U2!Uxz?bM2*{?QKFKDbO>gW;QlU16EJ*}Z5#*IlaGfl=+jHV#yVZ1;ksDV?pk z3>&z`1CUz78vjKY@yo}%x6Vhkd+SbTrR|jZyVkE|cmE}jv%$-QtL<3l7il9O?Y0K% zgWyS_FJ(l~V=Bv17A>@Sg?fF}4u(JOXEdBX%4jxf*$|3l{HCg}?|g5!AJVt}-XNQe z2>AT4h1l{R@tHAH%<$Psj3zlc{O%QV-cUYOpAr~+2+#$C#Spu#NN{6C!_e{?;gV!f zLl7j#19PWuBK}1HEYV?Ck_{;O59d#;(^99X9a4G%_2y@DV%=X`_sTT^ibgZA$+1RA zk(klv@<*xi0kxl7PAEpQ0uDyz-@j{~V{!&Kb2Uu5JM26k9~qH5TJ3rlM|vLauI3~dnTm3TzXlZuIT-fwOPt)s#-pYGIm+qV-9!|N?P zH$1{^mFLK*m%Q~V-a=yRhN8dlWlSBSt#>)^$r z4fe{tEpsbM@iE<2Po-b_E!2tY@n4<EoQ_Lb6n0?RRB_vz`Y6`1sBC^T09*XMQHR1Xsp>Huzcb)wfkw7Mo8aUy>Nfv z*I1UMR^sac7HX=X-yOcMFGQ+@9TK$G5Lv0lBDY$v!Su8noS*>`K((vEamolH_0Zd z60n>D;CXVVr**6L(;c@Ex){R<%*sednJzDNiTYc*NFq3_q9{8T7*nZjE-&=9%-DNL zPnK*}6`R>V&68`F$_?B+)6e43OXZDAZ{ytoO`;{#O|w+>=v&fx{7Q0oj_qHssnc!# z4uR}ppB;GsrYI`dUy)G#!$(_+jjh7hr34GY(CQLV)2`#EgWby?`k)5Gcz-UP7|GOj zg$kEzW+CtPg{t0NalQ$zqeS&#p2I1lo_^Nneao(%DuxF;{;2F0b+V|}>Y?bcsFX*F zW^R)SWPiOZuhXJiHKlvRzY~!SOkPOfxPRv*c{alVrJ<*H`1Y|f4@P?Qvyk{3|7X+Z zzmWR78Vx)<0CKK@(;LN7=3XkNf4%_J!L=U24CWfuUwksA$X_OT6VITZPDDu zxfx~RxD?D`(hlUjCCjVOBG?OHj=y=6!8l&GI!65N@P=4JqA~h;3p{TO3>sh-2JMoa z5qZkU!t8zX|MIl9=O%4L#qi9?Q0)+}=!7!5^3md%wsbu2M^BjfRQvpgqflhI14#&Mv?e3tq)+cs70 z2+_#%tQUK)dMx+kQ#7_N!hycNqMF)ca(!!qk~eSODDURQ&WyZKH!QKknDDGfO-3{V z0Dzgt-5VGMxtb=jyS7f-l&WtFk!qs0vp<{D-4lmZ~pZ2-kh%3!o$Wr_^=eQxhu`9^lBXjG+F0zz6-pWq(eb(vdw`xaQ znYNEQ4*?hEzksHJQ*H2b;htz`9&m{^Wj#OFflZ6k#PDw4zXn`)sV>U&iqm0SH%GIT zjaT8YkAcGlEYhMnU1I{PKh|kLtoWxGwDye2JpJS389yM~Wg_IO6g=WCspDfIr#9ZY zr_{qbZ6{opsGj8Pu6d1X`FSbY1(JT;Wf}Sm>gwSv)rO!dvcdJpi^HJ*GzpeB;@p7m z1_F5^`E>BynGBnN3G0=O2*y}Hkt`5mb3EhRN_yc!$NAMA6#~kWujH*jcm`i-8q+otSBC&tol@59MmivzF9lgMB`ssPp6$+{20?Dnu9vKbXRANULl zaKI&UO7Jm%ZFw_)?LX^SVe?IER@!IpMoyen)nV;nfM{Q++sK5B z5;<0k?du{7r!`lMjAyox-34NEqE}VlOB?or=h}5*o$D_%nsj3L-WQOAMrtZV+gO8;buZlk}d{-rf{&+}r3}65asMrqrHb3iu16BLNfalq?x767a zo?3$hh>X2^+)P4jCJN1FCf6Of)S{~QS z?}LRie&5P*2o?^c%9koM!OTY_ZZtX7Et7J!y*F?2a;+*>V_V3b;X^UXR$i<_8cXr+ zfmh~MhG(m12^0;lI^SwG+ck6fBr1yFY17*xhrg-5_wTlUD~m{AQjolYn?KtU7v#`n z9%_H4=tkv3u`Oc+etPtfokw$*oj>CUDFGm(fy<85_eR0fGnr#n+#=8GY2!bvo)gY4 z>lZo)v$YJoL^(Z3!BaG-{P=^?`fQ*GVL#O`0@z)FPgDO$Tarv^4u1!sAaPictLZb^ znKsiP3#KzfZ5}17qA<6`mK8l$Dt*QQL@2-s0$lw7++gvro<@>rsxz`83G<>pnb7#i zqTpq@fzu8;h*Nyw{aZ?%4X^pc-I$M$=ACLm561adLhTIeS5JBgn9^KR=>5T}*pO+> z;h+l#S9{8{hN?wsJ|S1lASdvL_iG%vakR5%neohnR_I>NN`3M=ujcP{xqTgA0z&38 zZqCV*&++Cz9Aa>|fE}XsOYI!G1$M`4%Kc-)t}=YXy>`yDF-LvQ^p*=DBOi$>wLd{! ztKQZfRZsnt+xyEm&QftMliO)?{n?d_JD4~9Nx}^uGwV95on4_;bN%Y}39B`z_}1tO z4m#FvfAr`nU{2-Ls_bXHamP7nf1Kfi^Txudv7Uy}EAF#kCQZh#e7cUz+Lv_7Lrax& zd@r-2>ev0@jd&D`Zd^F3#pY5GycNuC{D_c#mSFOo?Tsk4JbF#F*fHrJ2X3(sJym*7 z1kAgXLs=37J50YP*EfX6{f8r_zUY+&dzyvoo2HGMm$_EYU+Z{cm2kyh%jb9}zIcEcHpAQ?f4LdVjh z{?BA1nx#vQ9l0No^$3qP0M3*!99wiI^rxx+gLWdaa{fn;M`Q{<4>9sy zdM#Cz>7Dx61Z%(Q$om^;admh$0$>vKdv^OM{g!)!2dY6*kKUq!e|gH$nq`Fg8&a|N z+fe;0@GyWQaQNGHSgu>zAfO7_t?Fbe;lYT?YtOJ0YBLK@{nk}NDcFkz&E@JxwL*^E z>Ab0zLqx7$iSuv=kZTt_{YEMh_^c(jYf{lK&`c@ij@PaG)4O>hT z5MfQM80WtMUyMQPx7^DX_h+ncN|;EE25^j)yRM9~uvsc@JfdS?@jBgScCH7-SCTT*Q6Dp^o6oj0|Gl>I7RTx2#CiFo8}z4cjPAj{lh zY+I6O#@ZPNTY4n{_>$DwY-L5^%rKs`i%+7Fzfw>}>3j-lWN0m;@JD;6j$V=ml`Qln zb#E!ReFiCcZbPY@uhz)^&6(^m>@2wJ$6H2!cm`2o(zwmD2Gxy4Nj{UFZbL|qEgx|c z%~#KE@nSn~GX_d*2-|bcy*xJOJi+H!O(_*7>rFin)@%YEyniMQ3{uH>jFeL0$w2xF5MNkLlj+ko zsZ9zbO?HFS55&s-qMo)|&oKrToqS?$@}gm|sV7Mg(kYued_=+PCK*d-^dHWPED7NE z$NkS-jigBPcL+T>TbRiH`d@{MF1b=pE<6o{nHbxAr>Vtddw3)j_`H|Cs_Zg3k+z3% z^9(`lQ^~iM8k$-x;&=v@@F=kJU5-QgzclD>tF9P6B{PEFe)j6{FoL1<>XA7SQG&u! z0O-meVS9Owz2kl}&k5>fJH-u2Z}4Aj;fAF)td?Q{wZD+VRllP-!E<{}0?H3La4j~c zB8Lt>=Ds9WeSh%aIgKBFMgoo}8W;TX(AlmoH~4+!`TO>-xhs}Ifb;kD5590qgA2RiBp!w_=I`K}@>_c5P!6@4yA=@OI0ytEcNt^_fDx_||X`j#ezlZj2~X$`l5bC8Ti z`6v1Bz&yaf+m7OJZSJE&rCo+EJec(^lU?cZ51ev6dL2yAUQU|{^gF*lNA<}p+`$N$ zftVYF6O3}Mp!1|*;Pf0k((hPzgdL z$4rxR|EHui@sGhC?bF8*L(V!Il7GOPiW@R_Kt6sl0kT6GIp<2JNBPc`EH)HTQh>Q0 z!v_x^c%OJoW7f2`TT zfj^1$zl9K2?7H1nAxiy|4aSp7XCw=RKO|!dY7)WJkXn<^+|6AM5yS``JhORlf($;j zG$@z*v9xy9+5xgZ<3F74d2De5@BrH05ivj4yQpGbzwS^BppMa>Z{Mr_)UCo-OdZ zwG9pTN@cyswP9`r49ECFwJipH ziZ7M+Uw4!5N}Ys(Bvx^Hb(ZIjS_exl)wYlmj7#z)B)Yq_7I?c~$mV_`hw~R1&)0LN zMUy!Dno~0VTC@T{cJt`gjRm5*B@-P@jbF(WV?)q|o9~M48Im`=V@q!^av!C>Zamm_ zIUqK&a`$aMx`(3`6Jcz{4~0~6K4kV-8A-kWAEbq5$~SsG637gVI80x#Y^ABzm*cFQ z@j373Id|aNkBH6|E%4`2$!V2Mt#@ljOCB0&svM}dXHeW3o@AenR5^ZH;iMZoc<*G< zP`Ix!gf(9(kJ}9+c&m^SKOygfSZrA?nwbKT0xJr<34%uc4)NY2kSA3DiC|6%!E?15qXV zDwXJxfO8+_uxN~lSIz~#`0n@G<8y(Xoe4L|KyAJ8Q|$O0`bC45%=>~h4JYnR_=KYKR-qOlkCnzb$SRqG7aKu4)@ zwl%-c}HsfWsE;I~&7Ro{I!Fm(maolhP0yG!bH*W$$uTb}FJ726Q}0wtaba ziC;TguH)$&DupEwsQRmQBqD;F2Bo0mE~f#{73?4|H`0HWGD3ZnTtScXR_2^fsf@jD zt3f@n8v`i{ILVdbqO0lpLBW(!znePgPXPY?lkpB4{3Zp9a1{8AymgL`(0-P14qFD_ zbQ6$~vJ7XHzP~+X162gSWDq9m9YL9nu;$*$I13oON~xRuDSwa98pUobIm`hb9LFY5 zF{p9|&bRgk!J+UcPYE02zWNWl);2L+^M#eIgwmOGcsi(l8$1aEBDL9Tu2jD*v48i} z-US4_m!)mjh(CeA3+R;^L^fFVZUUl_6oVCC4_HQ&dVaEu7{GqeVnbP9U%9ZIGgp!N zstR`sgO`Y6q1d%QkB?#Q|KU&wFASy$TZht^n#wR*^{a9$gG89C`PER4*<(k)JQo2u z^g16}UEFj^)V2<%Qbc}1XzLYR2(c@>Bb?&Rerk!WR7kO;CB*_w;I&XIQ{b?_ie<2c z`h=C33fCh|oioq@9_dO>`t~Q+)Do4qZmd&IzQn;WrnJiHVGLA%{G2|aE^<%Xs+ZzF z9KdhJxBnlF#Cj)4W7%)Muqv#JWaha0%3tS?qqQr0a9dUDPN?bolMHwoc?@%^brgCE zTZAV+0Jm#ZzL@44`xeBV#uM2yukPTj!F2hwU4@ZLB z)#RSodKm@>!q~>LgvG7%rj04QsWJeG4fTsYpR8@>ulQ?WjjBcacxac4QdtRvQ`XQ= zLSc5Xl2XsMl^gv$jknw8&j@?yl}7*6aqN+~alFtwNrrqHXI_@t%*fH8>RXaQj>RhZ^b;I&)9h`kMN@*TzwJl4bs1UK0<`PsNSJ2!8thZ* z&`uKx;Ck)hU6wc|aT;7bgx5K9SybLI#IH$MEwOWzsN{V{eAP0SH=ts-B~t;SHcI-` z)?EiH&*kSa+rf9R7tO0Np zvkTaloT#0`Ud*K7<=a?uJRK8iQg~#KUXnTbV{VOMP8mJcZdhxH_88vBdqOxM57KUZ zr+==ri<8dhv&HT2925%A)jEvAhj(iA(1{LVZE48>jd2?Sy`1e~daW{(-K;HWWiBtq zPUhnN`e=U<_q7y_{*SHLwr5;3cdyaX5q0FDy5H^wXFN`z_@4Tpb(%k&q{C3t$`4rO zm_BHE@Wr~>3`u?b%TB-;0Cjp$g=0zbc%NOOfI7T{$Tss4^|cWmcYTP=r>~rcO!waB za~lhZo5JyVF;q3eqkm*G6EE4+#s?`&mM4(j`74`_=68^9zhpDgf|WW}X*pb>r;rk1{zVwTzG&jC4(us5|=c#{fY>N{^0B zX*a4IX;v9r?Rsy_)zT5)qe3Y|ms;^AA7C;%c?^ey+}VQs(HDA}*{ct)yCZDD(Bt1N06DjDl` zeRYHCv*G%*lp>OBwjqfFPQKht^g``K?j9*Z?SB1dP6k#H&uQ~k+A}f_okKIAZ4chr z6JETlyHh02RStT=2;lv8*_H3CazgM}ah!**@_NPGz zIWB~}1-X+OEqDHEy2uXXn)e_lnlo!?awBZ)oM|y=uyCY^J=bgyK9c#67}roz<;_k` zl1l}jVOvOqM>uAWc&0xOF{*vH*z^B9xQ%1c2GG#P`;Uy64AA75&qY!kd{xGCwk$ zD@Zia!I6>an7P|uA5YxkE!vo3%_Civz7h`+$G+$;g_IXtK;Qy!sfOrIYdJ zq5P&Z>FqsjYJq^=;;-C(nOCE(20Nl@jbs{zjsq`&m31kgmwhP-!zkvb8!d9Tj)-NT5fR~1Akoy z*Q~1y{&J~asTW`*dg-?wnTT;@5{FjG1o`?)OYu1zF)%ZHioI9_|Dre!HqJz3< zUW@P_KY)AU?(w}7VkV>ar+A3yhD>{9iHT>(-QT+IvYL{%p)sei?PQGH#AC(LeqK<| zBW_2f(O`v3tR;I*wYf<0u}7gw{Qj0;gBESYckWL%{iGnC(Y>lgb^6YpcxQJM=Z#Tx zB;qgFEc{OM^!kM)Z5yK5%wk`uWh7p@Yu7hjKYR4;SAED->3b0)8(daKTGgGV!$LEB zYf)oAK9ih`vQ>wL{xcW*Sf>ekOGC)b7l)_Fyw!F;s)9g43Af&(=~{8d?K6{`PqYbc zVA>PJBS~GCP}=`+miZ=rYFZ;#6Z+YJ^};ZpiKC2L-c-g9P?s8mlI3o~As^qcWyKy= zG~cCig?TJWS?u?AT*(wo`K)tw{Rc&PmE(Teca-uzTWlbhgY!vSurc%JX!&=M_hXLx%FpZX}jJ|Fu#=R^5@4UkjJ0L*)teVcQT^ z3mOzF-jhNi>d>e9B^LT6IzzKvzCg*+L?Gvc}sJQccvxJ$zEY+s(57PiQc7k-XTJ=w!P{(&%4b5}?#3 zQbY&wI;nb10{ni&+ucHh8(=R$wuxD3e$1{=s8B_C&`f5A&rfJZ$IJBf+>kjf)6Y!e ze?r;J$zUh;?O`Rao01)~+-Hy!;}&^@6%b7u@)buHwW*KtFiIMUJ!y`QJk4y)ig@ zg0Vh#-!u&UK%-u=ZcWQoGJXqq*sl&Vc=guc@x!CtwOL2($>2$K#Fm46XCs z`gyosiH-Kxmpl%RI>PIbLPenW(Y1yN4p5ViKWHrS#;tp2a^!iR;yk#2rY!?~bvOxg zPa_gg9=7C-YPNEq>UBNiamzl6T~41N9NWuWKv9p)su?Ny?ZKY8R47^g5to5IhhO8L zRLls(fU-OuZG!L?oI-_ra3v;mE)94xM2Ei}bH%jJ6})_DbUtuWJh+CjzOdi4PIz!d zyb1Ch=M?|w!AUyDp(VP;#~1w4IOFj#rvQf3vh?#MFZF)GrIw@LU`mZo_`Fc4gSRKQChqHsSkQk*m(l+S!zOlWJy=sWP-Iy+@}+t z71Dml768*8>1TB+yJv$!ShT1T9s!crqfcoxLEShIaQopyiav)aqK4p+w~XBKy{}c` z>Y81WHvq<;=Tr^QW^(G~xo0iNoWkJ5kazvFsxX5l+kH zLIA=@73TZnd+i3&lSx>qr(Wnw`ej-7rrMWG3*t@L#!Lk@Y)^tcnj#Wq^LaAL%)5N| zRS^S4AmDeJ|C?U|!u1u@qP!n=nqy>{XD)s@q?_T5sNU;Q&H z(fYH~XhdiFkzf1R0!(&%YRaI@$-Mw%SW}L~n~{Y&^?&o4@m?6ii@PbO1g>ts z8M+4p(&h5XdmwKs3I5P%7mDfF#r=gdw3i>hGHfa;`_t!aD0(%p!L83nX~+pp9mXLiz)Xwvs7>)WyZ$F_6B-pKd8 z=&q~ll)pRk4;owKS~W$3f+{t7Vv^$8Jxm^0U0Mdl^%`|5emADrSr&KlDt*f5z}U2q1=}K|+XV;M6Y+%M8o@pG%eeHwG8# zA$lIGU@tb9e&%o~P9wiTUtT{`CvEaEmr`%5NS=CvKU_J|mDKRKd<|8ws3p4whG^e(|Dy=uwsw+RgQqs2ArJFV8Im&n-kS0iBUT?-~NS7D?V6TJWA%)61~M;}=ObR@0)^ zm)bOpVw`@HT5!fEjqhV6;eT!1>VC}X4$9rvluBAckds*|qIgfNwmAghQcgN$K;V-1 zHK7Nl^i9G|QP1ep3ULoiSzlm^T%!2o{OBpt=g6n!|+KpT$9mN0kpWjHoc4M9t+Xc>{ucvsD7!e0fTR+Ukqy zEoN0lywKslUjG}UmxKMle!4O*n4yRRgu9(hFhAq}gjj|jE03^37j1nqX7Mxzv(&~L zTurdL-%YmPm9*b=TaADE52rd`V5YDz)s?^B)e;~fK(L8nY2$6hsx@eZUX+WUD%x4} zc(>?bzUYznKbf$76#d5KOplo=R;Kg_?w%()y0lvImZ)&hiOjEpV&*fUK4UGHmrbEn zbit*n)VMeF)t@1NS1yca+&g#MO$~eD9}-pl4~x9}nyDTYx$Tu+)mdY|t7{(9gmTEU zkSgwOF`}$Z*!&m5@`6av6Ju<8UO^V5ZoSoF{d9{qajNL|6p_{J`A+VDga<@|`BVKN zL(#M}m-yS6H?fvhQ6>&D{F3%@Xpg=%$_K3k1OV>H?wQ{TPSb+ecCVy%$oJG zOwOh-khL=S#!3m7W9qL6`EwG*VFvcm^dRMM;e6Lus=ogEO%ZS)3t|v(=C55gN4~oM z^t_T!<%7NQI{%EVhA{{Htmg;YYm*0ZAKKf~g>B%EuA@)Nr^vjAj!opi5j!*P=m8;sqtD^SA`4mAch@__QVN>JGsDOhd) z9XyXpj{=XzkFNHieaa`0s&b$m{>ayuDOwiM(rff3VaJznUV>?cT~K%f%r0s=A0Ax^ z`0%BX+}UkyG;2Tn08$CK}y*_I${#Jf9JRue>zz{zI|(cGb|4fUs_#JO+yo z%5YGkY>Kcg9Qx7)-Y}*muGOz{sNGBXb7wJN>X4_oT1W_499xf6fiT$w)4Zl+;PXPn zrjQuq*?fGlu1f9)S?4+C$&AuSIBK3<=AeO8zM6MXGg$5a(q-)QLuv*U$jCpXTgDvR zVMua~&HP|`JZ}qWGHFzWG8#dFA91!fQ6lQ?Fx{dDveke&W`?qruSt;Qlp8KB_w(~T4CB!60?T~B0X8MO(716J5=F^?gU zF3tB;!~iqCMd5+LM|Nw^%YoF8Bec{-suxk=7n#$46A!uJ`c7(=yWfJhw;@>2Is4Fv zkTzw8>r@X8cmgH*$Ir3rnF>9G1+wsVg&mlDYUZ5K+$~p4y_?U`_iJ-qnDn}iZv=~e z<~WY0EXYZmxV4gX#qfzeD-?1z3n-z|d>B+IbKqAt?ch&-07r?Dob3+Z;ld4XyW!k> zk1X}eJCUNTUY}G3t>I)9{jwxB_Z0o|-?jQB&xre5m*|q@P#c}rzdIX99I)ttztrX& zOtZnbNCH&9>vN9Kd(4?8^XL|xkGh1-s0j@e3j;E`Jo`qE!pZ-DAm`!nhRaC(HZ`>+MXg(eM#Nx zRM5$3k@ZQbybOQmt^Xz^gGjOVX^t9Vr_#N_cy(~vzQMy}(c|eN1Ia;~2pz=wq|)MP z4N_A4!h*D8^JjDm3Eh#!lM4YntcyO{@0LNHOfc*9bQYR1w9k{lYnz52!m|qidu6j_ z%_zECcTLkp4f>ZdnG2`s1${Dy$WbKc$tlGk)G*1t*qr}00f zFZkJIM`G5zeEpg#;SHp(dG7VxFKKbOeayXBJWpd1_RfBV_3T*=qy}$F=}hNt{)-u~ zkpdQOc!2qN>14zB_0Q*SlxjLq-S&1}SaqH*dKd=@ko9^T@OIY(7+zRBZJ&=|o{wPJ z{MqSM9`*9dp!HmNsGtykM{F{8wSC597G{7iq+5~gZzeQZMFH|3)jzTVukM~5UX4Vv z6t%_9Zn%1P{fFazrEL&T@JLO^Rs86oXqJ_SmZK~!^A}1cc7XMoYfhZty&A=w@yIuJB=(EK5^BL1Wq;z{I%oT^<9;pgsd3)WjwG59+rIUzgH z;d6$fk`nrTX(ou)6G>xs3bx#gxL-SsE7^A%2rVzZe%I}*_y(agFRiE@XY>jlM7-g1 z`QdWWFyN5|d~W7}^}=HclvM<=ud2@ysly*Y@i6`%XfZgGF3P$j`ipds0Kw{RrmpgE zMbvk?hvgVIN=?8l@pCcg&wCJwD3urHjanj&A>HgVZY#5gu(zGI*ZlAQ!&$dRZzV%K zuPIS{+QJ_xa9`6Pjw;=K-af?VHT4^;PrSMxe+?XA$}pRZe`_qDcw1B+v{cjS z(J!EvFc{Xdn(?tlj2+~N|5yPuEmppKBhzCQ7)j9l(gx>KjzZg8tw~6{l?Qp=uKP*; zv<2Gwp`~lT#B1zXSzbc%mREh$V~&Kz0~t}>-fakOOwiBha6-t6k&c~KFDktI{jnD; zarI~ZJuwHseSHS?!hJCK+4;Sp`1B4+uuwy~$?z9N zNv&D>)>yAA)k@8>n}xz}rnJ|G7$w^K>SO;Cj<;8iPph}hkLOrG8XoYei#(}3v-U9s z&t+@zNR0*Wm{8Gg#5q*4Z(gQQRUrrf?I~Z9F!PJkLy^2@!W~+u@kmx*2j+YO_;!_T z%oMqP{1xq12725UQfx=A?&$g+P(_{Pphbnl9_g|Fxkqv@5&sc+p5o!0)OIF!mUpLA z)3jH~?6&5e-WKZ%pe!&U_d`05KVZ(^NYqEEsk>}p)+I1=ISy`nFWkk-+xZH^S~{F$ z{|z?hea4+3%%+r3XxRjS&Ug6f_{yr9s4(Nm$rGXiI1+~zN?W>f;^&@zX*J-P=4ced zvJVadH0T-#LP#F16lQP1ci~r9`it#XJ=y6iY;rKt(hW|AXLv0G-td#| ztrjG%W!Vi9*BlD)IfZ;e4?~6L+mArTnzK8G1cAvIEB~@EL&pDbbYX&tZ_!qV{HOq9 zPwr`&pcO5Am~<)qe>ek^-CJEjclRE;-MK)7z(p{V-y8j3;;X#)C7q8^L9zB7=2>d#5{BO=LAl;SK5eMAwTn0 zxb)$DVy(Eo@0>cm-q2CPYCPBOmwt2KHLQnQS-c1)`mJ@K*C(uwX@~WQEI3#&Nu?^GK4gpcKNbfF`Ax&Rv+_nPE}67ls17bGwHBZ%V`q z>*}BYY=Wd3ghFQiie`@HMY<4-X zqLQunsI%0DRe+=qliel~3^gKkYds~(o56Bfee?s{t$8Jnh^$frFRSFUrMT7Pld_h> zGp<(|SElgtbC%jXLzbs#hOcscv98s(g|1v`AnW4CE>^FV#n-Nlv;AbW;ZUxqm0!1# zKD7L#vdB`azFt;Lz4T3^v% z&(pMx2B?7cV*}l9iUDs%jnPXVHh__;q!H^>BlV5605_^dRoZlbsHBHRC&VyCjNxa; zF~+JLB+pBXU7NmAc{y*_>zyTM5b<1);FaEbvS-xKua9DWQvRq1!vxhhGc+`>U5v ztG=CZaaL_PXaY?F9I(zYALCpeh8cfPV}yg6{T+qN*W>*eVbyxpRrr4eG(%c?YO}KsD#D%bsf_8zs&vkp-p;<%5?&uvon7m;FW(7wwc%nU zDii!6p({Xn7|gcsdGH;@wB2FIJr`Da8hJReEy!sg>?PgA|8$f9Ogbe3eTB3gOEQ+| z;yb?Av?F-@5JE)GK|1{PWL_g_4`FTQ>KCJ-83FgT&*N7qj;YV15_;kmvu+VAK!4Ol z@;ag_Qpi?2r#MF3l(2bBjBsI0^^4v5VjJtF#S8oiCGuV%;noHH9>R`Sky5=P`cEK; zL5a{qhk6t*QBAu<4M~03I#T;neyKya{`}nlJMJ~^95v4e^~OV$u#czS@B8!_s>OzG z(&ze1q;Au%%M>Sb?IfnXG7Wx599cXs@ZkmiqhT0}i2!}sE=RQLa03|2I{!!3lVMEJ zy9rwa02AY;X5;Ln)}cwK9Q_h;QhBJp8U239aGvuD*pz^vf)!Ar4-hM~J`3N}MI9>D z&%WHD0<2sJi);UtIn5?MBbpKat1q~5LDK=MxA_l;fZj|SV=?s|<(?;-`)NHle|MPE zV_b8gP`6^hj#So)f^;mRTzQxT+NF}tmu9t=uFNAl!(=~eM6tTwJaLiEJA1(|tA`3e z77+K#V*=*=hzD4m=#Q7$upFC7Hhw^2Nw@F&8E@ar)oVH(Bz<<+ucc9WFB+30#jy)q zm`9|)!oPG=g~4+=v*H&MRdyt54pW7|DidkVzXrbr`8=TOu^vKScamN@y%sYLbqZf9 zH%atcwd-?^h;M&mwesj29Ap~2qJ0ApWAs&0htJ{g2?JRivj|bfYm$GZoDQ|G))Pdo zew84lM5YgZK%0l!4PgFS3#Xwi4|ukVY=X{IV6MVsY-Y^J=X8}J37Nh+s~Im zex+dr4IJf^qzN(|C5`5kgGo3{3dbrheq9sXe1!CT=g!{vR0Pfd%g;KA^R{{-m{cg( zrA_YTpQ+z2IW` zdseTOeje@4{u*4g>J<#1)d?lqUM1@Jahpv_1rWmu_SG1Cnh3G@Zq{Y5jcof)fdR+tBIEJ%I1K{fM8|i=@LX$JJ%|fpPSS6 zh<^CJm|@S)vAunKVFqOM1hLA0h)R%`>Ky$M%wB=tuWI<1LA@u&@*bE$KOzVE%cIr( zGoSN=KLnF0T}?2BGKBRAmQAjQ-~x%j98Nir9ByqgrL(s(+2vLVpD;yz1YudpUyUq0 z;DTm{K^3O6RUAPo3Id1s-tN$E7sHwV;Z#OkvCgEHUWs<;kcacETJe+;wX~<@NeQay z2m`OlEKliZ{fYYX;zWm~h*Ya$#~CGD+8_NYt=%;F7KZ1Ocb*qVUF17i#i+9Bsc;s# z_pMUsJ_nfQacwr>RE~CB=RTMi1cf8}Om8ZUj~gUzz1W}^0;s*6Z%(rWH&gQ$y zDz~%pjk7?2R1Wptgh#BIzvD^sIDcoYSgc2gONGI@>KhG;9&%*}kWMazxUbF&Z4~D^ z1BZbJTF^`oC!nl4+&wUO0A=AgCn{x`dNzz*Fd{-=(*ZfrfhehxC^BHmX712r zeiyMp(`j@2C$2!oW{`xG!Hrk*hvvNQ(*lV7aM?_bggIzzu$K{fnw!XHY0+(;N>iLkSd`}zgFkN% zFvoVdY}w3ona99kAn%4JE1@FOrXvg@+wHf_z4u^fnM{=#w293tPIABL0Z2W%iM0Tp zRJykW;tz{)Yt=g2;Y`OwlJGuixtw%{#^BV+37jAbSwP*n-Wt?z?ZP0esu?D zF;A3%t@GrsE)GCaYUX>eAz6Lklao&gg(?dCEsuqXXr$-rV+@?}8s}Z|OiCHg|LX9y zQS5^D#0%deeYL%bU7dS?3k(WmP>au@wbnEWyn*&ArB7s3hy5CIPROZ@Z*jpXf3Sb6 zoc6&#i%G_<^AH689ZqaVOi{tUX@=JgjEs-M=2F`pk;4i84^3|Y7S;EC4=d7LLpRb& zcQZ7?kOK$^QW7HF-Q6MGG0f1NiZl#J2uO~S5&{Au4WIY&{r%tP8F+x1dpULY*?aA^ z*WrTcApDzQs~nz_&c)ph$h@o}?h_x}?^%O~3EIw!B$MF}IHy>XUCiCX#SZz+@SA2%2v zXte6pC+u#Z)ZX!p58fGt9b+5V^)i_rV?RY<)(8W(wFwhsmzP$BTrwPZibJnircPT8 zc^+Fx&N)GReP+AwvdeD`9lEd1UF7f!m1$}9fl#-29?c2bnQM12{YAM+MJk4nb_T_7 zbUB4Z4d3^!2yFwHd+3qMUEN>oZLXI9lj3ExF>&|qhd}0|^aGbW zAt?RdCsn_u%s)Q3Tc%xU)4Nwahf#B+5BAzHm~@r{&!eX!9|u2&(w}{7+RPEiCo+Vm zGcxeA?O5w1Uh223Xd>$NF4cTsmu?vatuN@vk5_U}SP2I#)aj&MKDz@X0^v(7(o zj%3+2r>w$rr?`T=)iht{B)mA;lA={@AzC(>xhpflcI|mA_h>IRiL`t%$WO^2KOz_a zj|Q^*Dvq)_ghq+E7Jl~Z7_V=Wtl0j^ALT$#ZX(B(ESKeSq$Ks0*+f-&kY2;%gQ9Ec zVjy=>`Sc#yJRBs3G87=7Wyhvu+#myXfwo4m@y}Y2dkHID2YNx+0xI<{NN0Tfc)611 zO*55+JI5W~{jMa6E|s1JRv5aUucq9xVC?QZntCX> zk!h^r9;MfSpuPBSTJV9aMzkI zbP_4)iEO{t58P9Nebyid<6!SNmICtRZ+4#eX!Jl4H8k`eK=u?ufi}~E~irJ2E zO4ARqs&$A;QsPT}gO=v!DoypyCs!xwFG1kn_a*C}J5iFCoE%|8KJeCW$KzfN=oc|Y*Mh!ZFYg14>tnUf%)d2lVyPB=e0IP96Sy7UvDxtvg2~lYg>Rv5|fK-s~NsVgDb^ zV~WehOr!B)`=8ip4#k1KI`_L-hPhcJnUAJuV;%`erhOenM5+oLY*WQ`!O>sh2+6$c_$ zt4e#It9Df%^ z#|nt(jvYVkm4cFx97>|F zU2y{8(5Y}ERZnujZev>|D3mp>4CKVwsb*0Ac`yvP=Xb~WXp?Hnrj@#I!YFZ z*a>8Xx00=!{u-wv!L@4O+J_k)RfAun0-{bG3jTo7-_z&ljta@~6K#yhUIJDKd{cy$ z4t^Xfh;YderUZHB&}dkTTanjf?R9An%r)xBl+rlKy#-LD;SGnPg#Ni}RrIMHI_yi< zh;PppLuJ>a$&<&{*Lv9?6N3g9_0R4rjsG|p7Of3J30#mLi&6`g#v7uBueLp<5Pq3+ z7zV`dZx@JvRGLeQP-bM81fIF!iV$kuyg-qDQai_ef^w53ag~ZS{5K|7x-70@s8T7j zNcYM5G~=~fg2|fga=;8)hS%tS z8FccNwY=bi)w@+}lXA>*UT(DHyCfQR#>PIB0z;XTLT@Px7r3Rx0?7|$hNsv?v<9-@ za~Dxs2nN%k2$rP?e>ukFf6&h}{TwSYT2?iY)WbbLh#ekpOQxe)Pgd83AwhRJ$@S}h z5Px4(9AY_?%?+!KCMJ7ER)a{J*!`!{X8t0Ru3#Pabe2`RQ1G>w)#tTK#;7^&0GP|T zs}KCmvYPh|2SbEY-uV0>;3NWGSgX`r7N2Pdvy24vVfuuE^48X{>b=NEguw)1Lm|lf z6tfVwhIkqMfjDTIhNP@&D@aRN<%4K`A6FKh2yUgKzFxwWXa60u025xk$Me=yHa8lJ z!N~7RE5*nFwnY2icrj|U{tfucZXC*b5wD!Bs1(rNAnIO4Tl*=dmj4r=iaqPN{#x?% zxyI~ZhH9|E(=LGcqV%bYpoNC>xK$yLT*>ArY&`B$Jd2ZrVM0QyqMdw@`ic7tQd)l)2{m7bCaBF>==4&@^i;*=8_U; z!D^GX45m5%o003BNzHR0b5g2^&DZWiiDJ*AYT&+Q#2;%{(n_OM>H`VMgk2DMYhVrX z%Rjk+8Llzb#xWc%h-6Kr#53&Va{f(9;xfCJi?F}QuNqP%X9$}W%=(^35NrLvC;k8? zOfn$J0zUB~qc$w+cPsv$eoDXJMW=SrtMvVbsM}L^enjn+dwNH%T_Ekhcr#St-Qnopg7Zoit~(y9iyLL0G%|7gftt{#H5M z{$s-w_cOSQZOB0HZV8IwA2qtPw)(-IGD2)%bi5C6nl-> zb(v4Q&#jSb02q)i-q*GAUu(#&5s~x5&id5-c@8TEB_Ex_Sg&>fgh)Jf&IZE5n_r76 zTS^zI8&BD!f2TTdHcM88(#)QwzB#+r9e0jHeGVn9<=p=D4;!0imp||Rc^x5Sf=E+3 z7h;$D1t;?Rt58Yq`Kx#A2Jmf8E~G*E1UGa{LL+R6hx!OF5)dBs_BN+4<{3=h@eN+U zUGKSH7=%A;wpZVVS$wCbX{b5G1F(>bMIckqZWPZj(5o+N6bnPS+l#Q)FDyq$zN6(fku|KBPmSxePof=#57_UbFaMQ)_6Auk*Y1yeV*clgriUZiZ*S!!#5fuyPB^X89pe1TIXTL} zmVcRW!O|FY$+>at7XgFnnCQy8eOZeBJxuAaxt|*iV*Q+82bl+6+wO2ra!hU&qmTs7*8Tifx4-pV~fZ9UB z=h#{#zZMqdGcfyxmaE{8s#!FAmrJh-*Y#+O7C44z#E#wIg7a9r zlE8~>kV=iosQNK{fuQm;!X^ZR+fRN-&DPJB@fG*bDz7qd4N@r$|4cYDoCsos{o#Nf*xOz?^60F*0Kf; z6~$K=61I&h@#w?$Nuhr=^9pqsa_rkd#(c~*1D<^bp8W7{Uh2uQ8|H;tU;p9Xe3>Q< zsd9JdQM_Z`kt|!%1kUTLD%_a`59&ob_m=N?PI<6{#=9c5l>?8W9}V3^Pr z;@-F-SgL2LVD-EyA`qeL@z#Y$Q~da>qEOqcDF!Jg(KE?r=9k|Ikt{odx30{e5=gIK zsxto??`oqP9D^)Qh87a{`?#N2eDY;I#v72@pcA@fR@gc+BNcP>ypYhy3UONb(S-gZJ6uFtc(B>AfVjh$?Kcn%|W!cc|=l%NF`< zhj@xanj3OnO90`RV7rlBsd8gGW08)frHS;YgkHUTO(tAL3gi9%jHyu!kV||Q7`0(~ z%rhAL=f<3Jn-6>A5*^6<01mC~mykAB)DdUIDw9#>Z=QrxKyYiRE<qAUPjJ+Q)rFsw=jo6I>2n4 z_FSnX#$_R%V~;Z;93KQA`|4JSO%glga3`MXOp%&S75S8R;BNSB8l-G}wVU_Z`J9(3 zuKM3tZHmt1@x0F5+-5jSEhtzQ=G~!YsoQNE}!03k^nbXH^nD}S9hReL_ z4?cHQT_f)A=`_QQcuR>}imLwRd#mw6_FG?K(K|xL4;)G$A zz#jEy9O{twQKE;h?+VJhkpNaFeGz>0L*^&_IR+ecIK685|11kcnoYNs)%+^>D~QEobGoO~MY-@uEg zR|ZGY)n6&kW$62uW--g_5Ke?_h_$P}(eX~rv()oSx#>Tq6|d(R>0mbs5aqP8@I20q z_28(5S>v!ylMAXpNN5glZYRiGdy_}|9QZ)F?bFB^VG1zBFy%P4#j*-W{8KSE@6>U3xn2RNSlw^@gB zuIA<&;5L)e58ZY8v3BW%mWbmBf$FFz=g1O}$H6tH9j=gLmV1|T8EE)TK6GxDUV=qT zpOeaj{>=F<0#Y4%)IyLY&~djDd0vckgW9+1J0y9kVvpM|Lc#e|n>02s$G`M*{H{uA zS5W(G1LpEFxWfEDu0)S}7JYbEPuu%t-O6Es=6BR1M^^L38?!P|MYX%>1~tu(@d3b+ z;VN$PHRQwmvEwWE!zjwEosPrsE-K=W)vs}|xHjZ;`^UKd#{F(Mofez}b__gdSFpgzrTSI|Kv{+QzWlL_>u@ z&o8wrwxA7rVG9SqSwa;whbS0o_46a&Cz#JA<34;K*8f zl}1TTj?J}ol`tX75<;f|XQ9bgF&lEE1X6F2TXSCNL7Y~m0g-$D_k!A)RpH*);bOQ3@EeaOnbNC=3Ec!;ulqRX6Pr}!Db13drwpL`1mu96Q+FI(Qe_i&SWgr*y^N*HA|uBM1iGzcu7uY3o`0R?VExfvya@Eu-A1 zQLlmqIj?oVM1fydsulv+2@e1mXC4j}PA)zv`l~b1GF?-G9qvNN2M$G`<-Pe0`g<2 z3uM+aLw|5V0zIWl;WfZaz2h+np6S#CP(dj^!XLX2Mp!M#jh;$nkW7Dw(M8Qc043<> zQP!qZBh2cS=o;eYmi|dD>(SyLAILB3oU^=@khqJ<$>R32GznF*!RP6Edfa!Ubd<`? zrerg9VCUuRY?$SOoZ*%Yh2N}RYg=wMo=09%w3liNfwiGwZ=V+-lY-f9l-P9%?9U>k zkRy8JW2^|@hXhq$bBeUHa9fFwogF*A41X5zX~$Vq;;TUC4@QyjBULTJg1?z(8kq-{ z2h6jp?3pG8bfG3JtZ8LWaJ$YJGkqri7RdvA+sX4C?4wlv6xWVPP#G^0I-yL`%xq%7 zZ63WX0K!^J^63Y32-aTPDXYLMZ20Iz&YW}O--i;>dK<^Y6m!n{#(Ot<$AMeyZo{QG z6sm3Z-5b?H<#>Xh0}=?!`VO|@!Dk4{Q)-5y8v6U`4TYo3dwGP^lzy~4Jn78E*3tWe zO)5FzZ&H<5N9|d z1XCl&D3GVCOw8iE`X>B^ae2drSe{T6E=7Ve_m11H3wvy0rG1HyF86|iVJ0nCtI3aa zfSLDyUuxY+WW~z#8q2{zt2ZI{Q}yc3HGVU0TC1=y-s7Rs zr9Gb|T{mVUl(?fS>s_8!=JZJ;3kbU&xrN3*Cc>v3PYwa1H1g!Ws8gHqCVu6y>CKx4 z2g9SX1HIZuJVPxzZu^%;jrT}Xlqx{qd2fF3hD4GTdWL`09L#)7tgr5XZVz>Oh1hSL zs!HM(!t~^ER%PFbTG}!A^YC;EibQK;FwNZl(UmgI#%QW*Y{AAMjl=CbzbdJ&JlPlZ z){Mq;W%Ji0`GK(f`|^e6O2x=am6>RKVmb>_xTO;uYmynC2SG{vk`yuP#iwWe>Yhb+ zU|8^P>0!x*qQ#D3nS;w>o&ivG1R&w{&xn*aa(X#0`G{^8aR%+GYfxI2-;5|=O}M)? zlyMB-lDR%*9Aua5>2eGDupfLYtcnjkgXLgIeUyL|h@dhVmXST_5}3pI8~D{Xt64P1 zl^u87IRmE@L)3~iV#0T*xh5n1m$GG0jU(3znVtqR&5U1rH3kk9UvSaQP{H#GH5yc2 z7*=E-1yFAzEpSw`?O{$O!1pXmVIm zDJI~|`jR}GhMQw7QXt_G0qB4Ju|XhJi_RbwV{0*nSOweRBpOX6L`Mo^(8b2S&6W17m;aKF;5PdyYC!mZWm3kf%5u0n{#n@D zqd>I9AI55po%<6Cse#{U1ap^n@Qn7e0NlfjLLp4Xt&#*!;*7{eRLgQ*MjzNod>0#+4XQ@*KaiHS?cU-tmi*8qApxGy5yoC(JkaI5YyBU;SHK5JBjjFQm`RR z?N#RJeAD7>oQ?H+h>^fpZ;6#QutAhxQHf~3;_{?;sT82OjY0g`mKi%DLNRFx> zmN_BHO%40|-;-OYqQm=`fgmuCz$a{Nmvq>FPxQRh0;tjG$Q&?#lJA=LaBR@*cBqjc zJUAskoOQlXVT`}PnZYp6sh-|X+p)O%`v>Rf1slv2zW(F4jXl(nqPHzHYru2W8Br&s zIhYAYKC+Z2lppaPz|S!0lu1K`ie;{GMz z0Oy;Rdt%W002KqG%Tw0oYPv`gW9w2Kgvaz;)o%@ShAtJ|aq5kIfggyES=KK$aKnAF zO!D^?ud-FfHXW(Sx=)>X-?yHXrbwgAY!`aCy25Xx=V9b&x+pa%h-|x>Cp+>&x)?8`Myl>)+~q2;`j7<>4u+u zud;;Cc|7&WH5_zvlsbCCzJBC^|KnSe7D2VV_TZ;9)`jK`*$*8CzbKBs31)GX^jLEH z+3~2p?bJH#Brqdct0%e4dVl}>rf?vyXr?on(F$(dqt#`{;~}9#JX2h*;kTG48>;`+ z?YJ}fxbxVY=>l))j*nQ1S4yY$$H6Je0R>K}SOFYiX3?INcSjoD+~sAEiBVaFIi)){ zrqG$?gWP22^slP6hQLYQ%x=}6zE*3Bvs)RPoqFGbf@>)|f)mI?5Ft?}xdCvBL-N$i z{i@Wx`Jx@rJ~jw?y1%QD#yNyL%%as(&4B z64#$N6D~-R>CU`rx46c-!0Ehap2Q%U$Cz_bGZ1)bZBDr3=3q$ByJFIm6Q=jf8z+f33xMYN}R>`F!jqa@W><}Zb{zR26f!YMwEdBtR_3sZ4@@A?4PU~al z!$%yzD|cwlt>Vrb8Wv=q z{E1|saV$2aAR5%(Hhk*tO^W}f!6~AS=>qcJ?Zd~tlTL$^t?6HGdzDs@h;#`wZ-dBA z+gQoc41DT1WN3CuiEJi-st}|trf0k*1iaN}k5;4K#TKX_sK+|yiF`=W)$h(L4BwPm z>I9Cxtd|M^jW~Y#G@pE+t;+jSEg{~Sz1%Z%u~YJ)X7tZCDby(D#?;Z94Hg9}bz5r)?<0byF+Islbd1Us^$4uo?KKYsybN@Jl+aQQebQrS#%g?nO8LWLZXzq8T zpR@Er;GvvNv}CL2%}9Ly8!aF(DGTmpbU?W=4mbZ~5e{pxQ`hpKHHxObYrtQm{4{Xn zZM?=`N$6r8pAm8|yV`K)17YfEeur}mO!Wq%HUPU@B81glq~ZE$_HvFJLe1+UzHV!< zxtG_BiVzJG5raVC@;+YB=g?Ac$_c>UBbm}!vU8K_%o_GI^^Uc645MV)BtYqh=pGnz zbiWf;AaahJN+5gP#8RkcvV96;-BPvwd7YZC*x? zEJcoNY+;TrMTLh1Ky(0LKVzuAfa_=OHhk+sErL*s^kY^;Hg1gA`I$l7SYVja-p)V^ zvj3qR`0#>bo9Y4(w(c&2RKFqUDb3Z4y{}`w{P)B(3Kw_}oNRqw&SY&>ptD`Uc4X|< z1t3ZPJz1v$DmZHlZ0QbL&!N_3bU6yY?l9yPLnIWA0449o52$TtZcFe-sFI_ijX-`z zfn4<2+0D^4SYCtIh9HL<(n_;R?VAl|sch_@JXrIcmquCsJsYnAI2~I9vWmN0k&Qq> z|Jqq4pfj_d2|uO#era)a!*Sz}qJ@cmGhNL&+gPo>qRU(khzMx73t~#ypWM@st9eb&JJCyI5Y7cp{aCYLpMZN^e7(_G{LMBc^c+{OYiK^!QihNJFEuu2d2 zm0io!QQ@Qy(8I5H2zqTc0*1LIL{=!Lq2ngu?|(8TbAKOXM!PpbAp>d4egQltwe*Wb zJCAKt3IbGc?rPa3S@MU!a(~hgcb9H9sfj>)DC+Qv#8g%+4wcM5vzL|S?*bK>-52X90EDU%m)%- z8T1aB)ANi%ORT&A&p<@tv;G69KA}$F=Ruehj;hu`aVbYPFo2+tFGfU;XEmlMW0?t{ znoQX^fNw)v8mKGPo-IH%)8(iPVoe!6NeW)et68H2t%gK|mmnkal0$#Q{e-tweHXe3 zGUUN#O;9!TqVM9;7ooQ|kkfQN7Ay`cJ5Ft)@{k|dD&4u~`~GKOD5LV&!R9wD;tRi@ zecRzNh})pkOjXd!xL3%bt&O^+oAHEKW?{#TXrME|2$*#M*Y0u!ybd!C9{T0?k3E!b z*s;qb3Qf}7mGlyK&eEq?jP1CS-+dx4$xx6ZIgqilN`4c*>@X{Ilh=c&lcyKi8L$%P zeIA#2Iph7+z0@%3rQ-B|Pt+ADsMVIqypio}|2|o4j~_S4EE3lM4EwYrbEtLDM9lI; zv=KhAkd}eCP%3cXZP!;uuDgO~C|5I3{bAdqwu1p288U#L6kl%s6&Id>js)1wF}zg= z8T-gOEdB6}ZknU7F@rSSU+a#0W%w?&e}MwIsyOC-fkMyWbd>GwfAjLjh^&4x|$?tP&_3880%mZ!bLuQR4hijvv-?2ty>pb~K=H^J6q!KS-VN|b7}q9%-8Kz7^u7h#a0op93O0_E}btl8xCV%{}5!3*Tb4WaJ!XHDkRsKuuT zql5|ONJ~I%1Ge7`#BFczhUYK2p(wR6$Y^gYgT;XO#QsNv`Exn-EVJoX@$j3Z$=Dbl zV<)Y%uLVAC#>k^qJy_$<7a;iqZ|xjvqhd=#obT&mQ6ny%Z*_xE?}&E>HpK~fMCh}FaIl@gclwS1;IgZ2MF3a5E>KV@dX3rv9MM7bS$!Df zBc04)XO>AceVz4$T3?Cr9cPKD^VE(MbB?h9{vE*11@;b;nrW|Lo_Hh5jaO1U#?X@3 ztS|Qy;X8x=e+d%+aj2SDV)x?HVY{RPoe?ObpW;96KCCNf6JOndbi^C9hA?4c2JI8L zj+c7Jkyif#i=wdZHxcCu=Wjw=eLq5WBwN;=y{h2Yr2EyLyNqb(UuY!Rg9_Bv?!z^| z5KCBeycBpZe+3lIJZjCD)SysqW}SVw7q?#1v|q&M$;?#ebb z{{f?u)>w3qEV`O^@q;cu!B)-YwdVV4<3v@Ol0xc^lLi>YZ1wk$D*p zaIg;B8@-x&lx_fi{aBcZVQ&~%qw)8D&DyL7n&mT(DWXVe5VWH=JP+gdK^YCpcGNhp z?O=q{0Inn>n4AY1KRgIndjw#yyWTv6J$exZHJNqf7;k}F;r```-vkYt=``T($Z6W> z7_(o8aO4lnW6xE~E;O{3{qr^ALIN@lz&;9!U%-R1nKb~_|BrXErFN|6{^v6=*Bn|) zzfjCQh%(t}uzfTH+`7`8-e2smrX)H)NJYAyPp>576mvclNs5<;`KYo+At-T6ZVl3U zG5Gza?&*3(bZUKXaXXV%jEDi%HI3qOTyi_Pz0$YQ^<3rJ z=VV&2BkT=_;x;-wS+E@J!e5;7++EzHl*S8dDKTl_(HelG826ap#$=!Q9qE+cX+6NJ z=4Pev2QSLQt;C=y(<}wvLoYW;KdlKiYC~9s|z*p0MIB;nQ6J!#Zr$^jPzU zl#O%$xpij@aF3K+CxJ$?mxmp0yFvif2f1e9ACfP@97RwdyPn#r^Vmn(MpF6X>X4&p zt0v=4N5BU%sWs#QA%=k;N>y*rd1NV=6vvRjAFSHIDW$-?bZI;eb$MQBUc`nDjmH`+ z9atNP1>o|>3;$m$Y93qm{Ds0p`R7a?aFgpo{4iF>Vt-OmzQgq0Gd-Kz*2vlzEag$DRPYCIfOV(`H@P(=!yZ! z+<`^`Y;S;-r7`pV8S7X7Pme+rkGtcJ|0nY(Wx#F>gAtDnVRQ=8MR%3N9yz=dS(C(F{Cu8ZREM+WS?6=ZN8UoG@T9hwerYo#$U50pL z)~qujHVO(11MvI+6t+rWWOx>S$95*f18+1uK2ty=fG78VuEfN@XXNo;pnPjYoHuh> z$g>7>{T{F|7h@A02H8o2J(?aKh3 z8UIgilqCOu10i|_p$#y!S%B>Z#ZU?!_jCs;_lf0Q+XzZ zppxp=2;yb%{OMr&`)g=5)vJPNt{4P}#vdm6l>42=fKdFAH}<+iQEJNmV0pY8Oll4H zrQwBP+8Ph)*vyWPx+4SL2v4T2d>lO0wPesl`01=8=y9lGJLCWPZvyM{ z(SrE_F1`CFYt#;7R_MdezYnI4s$&L4k^~gY1v!qzjw})oh7w%^Ue?i-dQazqD`S(p zmtdCzIc)3IWhtr&NLO%S&GZ(la*TK6A-&MWfb0CIvPN$82b`a9v&~J$C`KbhuD`GB{s;V~6zFS7x01@ndhM`UgT- zo1+|9 zRCzdDZBDccJnsXpiJmgE17IfqHs7#ix0QN_!vq@LGD@r+8f6nh1Ynkc#n)i;zeixW zTTOE|=`JL1)Wp{4!@$P4N@WzoR)%YM7BxKyXXY=lm1Kt8Tiq{nz>kNU+8dBPaQCR*>%;@#}8=#1? zdR3d9p#xkXv<#WpAx)0=9=lW~Aag&c=R`8m4+v8qsbXlB-?;8=|C!VF{PV4#@Frjs z+zFyx5SI0laI^fDf0OZPybr+`IX&MK6MEI5+}HhWkDKfjl49jNucuP4G~xHMj!%TtmCY(@A_O@8TzqE z-dYE4@Cl5oI|d@He*@#`fg5q9_t>629hA{H z3F#O9hu8n{5Dbs>Q^h{1tzHO{k1~=%8X_~k6zYUb$yfd6$R_%Y{oj+KISfOaI8}&B zHwp~X``7nkhud4Jv^f)tX4RDrc{a@I6R@~+aFOJ$U z3EmEYU?JpSM9$ywr5cj$GLqR#pxkP?h1cK3LA z`^pA3Fj0xf!~7D($#MhFEFSlcJLaN;1#0Jdy?8fM$I1_5?h=gur1@ais@#c6s%%KZ zG5pUu>B;)Il68j2Z6DKZ_e5lIq=vhzk_|-lUK?Aw7|9~YYyiu>0#kaTMT+UxBleZp z6DuupkUJzfC@*C&vs1h~GhMvgfw8vgSqH>Ql7-EnDmejht>|f((D#Dnv%$6yYZ)%< zN$j;!neMSJD{JPjkol9(iD9~2^RuJ~eT)B-u6_1Yjya5F%LUuPYR`%#Kc6o3h7YU< zPM-Njv6q&UQyu$!{E}UM-H?Vs(=d@rDeNdTO#8l6oAwU>|72)&*N z%?RUToEbqq79DZti*w_T>7<*Zubx-eFjZ~lzEl}cd_8W99v4e#1+G;`vxwvBm$RuR zPEXcpboy+ymaew^Jmc|@#{a$C)t_g)-YbgMvH_Qu3ARk1Ta=C1JxBA#RQrbSWyxZJ zIYuk6|50)Kv z%W*P@x*=^>o6?>6SkIx@MJ+YB#HvN)E_l#Pk(kcTCc%ES2c{u!Qw=?vQ{=3dXG=Q- z@48!ZPk!i`{bbMkis;0*!o)8+>B&sZn{b=c7gjU8l7~ObsI+C0sMN80BKYiT(8__+ zcVB1)M-3nq!&-}m_#2m|YSo$h#WRQ26rQK`V-}aHjr`fbY3%f;cn-U%`2JqF2#$~t z{O!EzD(bg4Z1U8y=Nr3#6p=brsjK)2m0)>YupzK?uW(p(dAld4_Mth&EnAC_$1NdmEjM{!s~ZTA+8-#HV| z4c!x&tmM<(&{ednbqrvR)uwoC?Bk{|$VR`2@#Y^prWK%wWs5swTa`$ce)}_)meW_4 zr9%BBr$!l*nq!OTdEyI!BI$*|)^}@YSK67CD$SkuTNZmA`dnC&%JkJ7~&8w%^z6H6@Y z-Bhj8CB2`kGPZ$Eg<7fP&SSw0tP@OqO6MGeO4;%HR)*?<3$#lY&MeG0-gL7{y{woI z@BQkBsN7%E&&;ncysX(CA=3HY|2$VzES}xqOi}^Mi6k5|cKpjZQ!Fd`yRNY%x&@^KF>kxD6>x|0RIN6)yX)Ah8eBkW}5^8Z& z3}Y!b3urA(wBVn5=>{2@ntDrHB2`bnIPZw<>%iP{+g6VDb5R_M!FaRRenh;|6TkKy zH8l1}jT1DK6o09dTFTYMi&jPo7Udb_I$QZT4XM(29-0cvFTS4KMo-fG?B9hxS@sH> zB}db^5ATDT)-vRndAcl>yYo%iWH}prL`I1e9?pr%w2x4 z6CBfAAnLumb46y~wgTBzGxaZ_Qj~6RwA)G!Q|}1Rw;}MS1x%FL3dKB62Hi>?@q z`#gVIF&PtWD^n7zSg>l7Cs{`HNfiTMKO;UdO8{$I1?9+mi|qr2u~P#n@RRu4XXKhL+^9cl47`MGqbo7 z%5qCeitND5Ft?6QpOi9Ava44R2Yt>y0y74sxNUur(YM#z|LrrYl4-8uu}Mm#Pud0y z3#_>fe&Kw23-k7ArJwC3db?I%B0#MwooaJO*C@stn}q2}T9IXG9IlP#jyu0wrpZdl zoT+IhKzf0=)5$4(na+)q4pHZL=3m-unW5*(pL6njCdaB&I%$2WfG&mk`9?;jG_?fB zv-`N`P6ADEK^u5s2+cdsSZy_}zxedHiYYwCS%(5=%qFi0dRQZw8l$7)Y;NE^HH<5S z794I-DWSDIVnkOU&`>ux*Dk024@;aCIQP90;qF_+adud<31pikPN|5q4}A@yPGVLo z(fyj#ClmahX}}>};G1n?4;TBcJ*FnowlV+IBivcNMJbVXJETm#BZ4raX!jH%MavL3 zy}*cm-Z6*upeNm|E{)^9{6ieAj+0$oIGE*-98+h&5Ugi1!)1le7sj=wp^x}L7X_38g{B) zan9PEqgdE%%Hm|zk|h=iqamlOkE6s;0DX)-ra?3K$Yo=j+Qd-`?OacYpR`u2{4})Z zdq!fO^AS=!$Kv9CC6cxuhj)a(iLMB?xOi!MeTm>ZBlYZ%rdm{StxZJTW@`jegr zqD~4{S-UCYO%V(kB49)!(MHGj_u2kEw^|W zFYohLuS61FueCIilFeq5z4xQAD!-7`WI2QUe-xdEJKKF1##^gmMyS0K5i5e!o<)#| zQQF#Ds7+C$v>LS{RuWrLqq-`h*yYjuxea^Yh=N9gt z!1Ngf+~YIK=G71XMAq@bUYKM@-{U9KKEJW-h7E#Y{X5@5Hqx%(G7)EvWA@4J@dI{- zt5JOPzmEwJXD+dP5Q2fN|h2xzSxsOdmfljK6?UIOe5m zS}5M*cqc;|25Gbm1c}G1GF`R>=7hNAlWXj?OYPP7OdLZudVhQz9Z2=cxJo2YWoL`p zVF7h^iv#zuYw)1Zh>kO=^kWW(l-&}Q0x>$}E}^eUD4O9f_02zisE(ka^yZfa*e{R} zxCAo`O_8gwRUU+XAk;r(W}3}=PRxe&iFK&UVa`wHx8Zkyo1|6M$39(M)i#T$a+(uJ z`u&rAicr8OQL>akY;|FGryWaHpv`Ap8*J?@pz--kl>RguSTisfN7xf-TPjU`9)nc{bnbgh>5%;wk-b}=j#K|W<DHC8E`rqAd<0D0_WLA-e_fXscbiS0f5v*p zj|mqsWaTcAKO$UdWy}n4$}|>~VFvNBc(7#12%yK1h{1Y|v?LiB7U!9epuxAylON0j zv>5?J@woKpbYx+G1AAsT`tw6NRoSucK-zh9bhh<-_v-{n<5ty+CH9xw@IOCz=uu=T zXTgBp@Mh!@b$TY&$1j~Z98tz#*rVrbIbQWY=*hmCmm5;{av{68!_ZBC}{Ar31Zu8JAxo`8ho%TYr_6ZetG? zxe61DlYCB75y1CXhcC_z@P%-4id*3P_4N6gBWb7nP!v)7JPC^8jUv7t+|AKxAKWM( z7y~U`ckAz?a5zaloyz1FnKk2EbO2kwWlA_oF$Z)?T ze_-)7#d5KTxwovV=BNW%X}l;3W^Uph=E&G4s-qw6RFp^K@Of=on;|qS8Yuz;9fgu~ zG?fT7?amx;*&d#qMLs`YBciT(K~0WlND)|HY@2M6eaQcL*=P;0(WBaW$-~Qer4U;_ z7`u>moU`57uEgRP0@%)UqrhV(_5L+#;dRjO?RlF#od8;iyy@~4HI0Qx+5F13u(7GCo2D~XH1 zD9Moo37n&~UY*XTtsj_Js2N2H{Ng>&{nHO4>j(3oShAjjy%ph+LvoZe8@DzPjte5q zd}d3=LAx-1Cl)iUSqcyIrlTV#+A}_~Lf4TJMk_%0!4Zuw}-9uXsf0E3b@H~}X zP!YBYmvwnXINLA-a++RN*Pi%n^7z3GO|`50-^sKWsk?^eAH%1V+cp^d=W=DjgzfXM zRIw<}m}07Yc44D0qoEJNWjpB(*=kna;AeANT@Og`X?kT3bkl#}Gjp@3a*&OL-ku8e zcE4{6Wow(eiKRA3S5IAtrN#Ab`?t}$vFV_}#=+Br(gJ5lI7Zr@Q=TSo`0+Q^B5!EC zFb?fH+L`2I*pEuOwnzJ}=GnOGvY{wtvyNpLdq4wS@FVuP4Y825m<_`>Yx4 zZysK`990^zwm-Bmg55IL$A0u-wSSlPfa~L5Z-!GrhKm+1#W>cp)=Ovflv(V4GABL# zU42xRlkF%k)~IwaaCjgxc)$oB8AmyGIDQG%lrFVU{My_FVXu}>W}N}`b$`J;KziG8 zyxVu5TB|;nHmX{6wQ^V9#5z(6<%oPo1V0X-#rP3z)piX6Z`(t9zlW1KiF|sX2X{k? zuJ`teoR?zT4g)*2$%usDyRtv6$rHLrICi{y)0|)po2lHLcL@sI5%3BDid*waQ>;vFxh$sUdVDx z#4UfOY8&=LZBcKjQnWXyyPa7DrOw?^X6^=iy2fD-+BChKANrvBq{E=Xe1bOl85(FS z1^%gk52KKQd}>mmgs3=x&tl71f<4PEUfObO8gRtk*yVz%?p^XG?L(!l>n)g^I)sA; z7igXn*`L!TQw0Az!{s(H6l0-#>=oe{*iR%1)MDYd@5IJbO>nDaAkTq7%1~ZL;6kbN zzA_w>^4}Ssh_o$;w-(?e=eHL_<%PU^P|aB$d+EzA=UI0A^;AARmj8MNT`J(t|B#?%^^1X&Z7O&c|a1FhGh`cKRsHJSX4b*sV@$hc6S zZib2pSs*)2N1K{wQ`FG+Ja;S^Wr98k=z*YgFZ7-;Km1~C&7FzMvdxL@?Ujf=P1;8C zdiF?paU^`648f|^XC>67*J%j4!rmT70YfwQ^(Y0yHP@gkgdr;Iy-u56q+An{#^3Jz zJgeBr9+2mA>rr7gcek&7MDDpHp!$IZH}}q>KJdyBji}#%mc4BnFJV2GXSEJUXa?rT zrtW40FM7f_hBvI%8bracSKQ6uWt z7mAex`vDoJ!WCdXRnu0DB=xiyFZC7!x8;ZFk&~r}z(|>c!Q)wld$^Igu>PlUp;{2f=FKSltG6Z9a(Rb-fib7F)PlGQ5v|D375307(+amlM%0oh;p8dB8nn^4x6fQT>oeM`9 zk|iUma$6_1%Rh7^*RX$mJ8Kr8z7dZ@4ytK-lINZ^(Oyp%xy*7D`=SM(J zaka^n9)89@=}cq(WM}}M59*Z+$zSYmu9DUAU%&HUF4u{xDNZm?{Z1>6=)B``nJWUE zrB0PMd3a8H*^XW+BK|0ci#PEz8|6Ak8Ilkjj2pM+PGUW3FiAKEO3c2e9k$(H8Jbq~ z_UyR*-1FrB&U_5g2eIdgqi4(o7A4Kc(@G0z^d7b)7VVM#<(?7YIpG;AdY`6f1mI0o zPjf)bNT$(mrz;(}Oa*r}!*m;P5XiR*4sFVkyK&`G3B@6Rz$q~bm^Vmke5ggUK2E-E zXpE2|sqmJH*+Gs$%O)cNDOrTm_X9<#ft3gt1{&>vgkSuC>K<&!Qgb32ltLDUYH%Jb zwdC%`uF!)*l+Al*dlJ#cUEqP*p zFnpRII$LEVf19$5XHvcEA(kX}eRl}F&mB56j>7uua}T)vL(h~3y| zj!;Op^KO0ht$bkDCEl`!()na4^6Ow~Od>5~m>6R9TuVrtC^5N}pGVSLPU&hC|L#>Z zOz@$;_>!G8rH&@;q8;0FAuF$G0YOssZU<@|p(ONxzFIY8UyDlCF)6nl70({%B}Exo zg^+FGS?`iJ{s9AzIOdKm{4Kc+QDNWql`~F_29s@CwARPjbH=GB$-iFKC?2zlYsjIW zTe9l4>JxfCF=$DXzHL~au4euYyJS0J?m57%Ba zt|F|bdk!oV^Tj}@!3?A6(*+xyY_KdU>N$_o@^``O1 zIT=PO?-3u0W}Onx&f~C?bF7B1=MYC%xeZkANkYoN=)R6$1afb)D2*9%`OfKK; zC5Reqv?oChT#^aCE_tqZeqR^5Wr-q3{&&VS@-s=*S#(B4J>3)f>w|oYh6X1;M?KeH z?udy<0_^m7PR>u3_OGLo}dh$08#xbvTNMBAZMMPLp8%y^D82~q|r};POXU_-M%D}fc176_Of-NBDBGKykR@Ij-*bw z(=irhwA|`&*6$WE_4&5zgx6z@2MoeOdq`K~67Jq!ZPflhv2Ju3dP_@ci;@JPRZCA@ zU!qW>OLw%W&l#?6qS<9!MmnN$jk`LbGh6hXZLsuy?6U?9IId@uw?yr}ug0+iKa25W zH+)NcD*pSSoU`D2s5u>8jBRx;?d_2Ny79ePFpQzhOPywI)DIugW4U&vq_z7^*%uKv z*&+1*A6#89e{EV6%RZ)6F?Y*Lsa_#77a7>R z!v+92*Vr(KdQePEJkDxxJ#CMy4mB~_(Kcla;s^vu|9q4 zSm-FGc7~^B9DLIP(wJ9j;taxj5k<^1^357Uq`bc~{_LrnJ2mo`0c@G~MLuDdw|xg$ zJw{OJkn)V=#*&r}Dy+hIOL>|s{|3<)=q{KbQ0inAi8Lt_zeOvGy1YTp0TiB?jaaLk-BTq&h-@e(w)QzZ6D*vR54rb8mUIfm@{EU?lo3?I zSpCVVBA=RkkE@;qBZT%XXg3Xr-T9tuQhEJ9b*}U%M@popdUIo0F6J%#FfX~4HJIje zKNVS5X2_?k7SeIdf*Fa>np4xCOi}buuJROt-gWYPI>lU2lb?_-6J2~4fx`KY$XM=A zmN#75R!$S8M*jhG&6HOgq!fSp6n_74GM~O7+jQiXy73Wn!QDA{OC?lRYhOnJ*=y1L zpyWVEy%Ivo&t=FOyqe%=jHbbvOI4<{+SAf`gQOyA*L(#Q-d>3O*{~XITGrAs`#m3G zaJv8ad=@rY=PIj0n{h~UCv3DLt<|1J0ffh!&GsHTjGgP<()B_D;6dWT=daWZ7th{# z!wIfCWbqJG4@%_L&ljOZPREOty)MqVq~qlxJuZ&6&kCm&^gLO~I-y-j>CpHan}^^s<;jYkC*MoVfoY*e1; zu?d~XyplQ``bSZnx7VELo4v1~eN(QjQOtFtZ-D zIo!mseo1wW8i(C*&RgTQl5>&#S-GmP#TuciacwMhp6uge&b*b2zWP=o-8rSV8pkr@ zENEKjN+(_#=A!8MA^dv0%NjCq39c@cfO2HHB9IuRnZN zN1R_sVQ76qR0la8UHCXtXUG?^_CS!Wk^^kH0pjm}$ys;ly;vF-5AJpEUc@j$6g7Oc zFq*wzF9MrBCCH3C27|c*{BlUw9sNdK{e2o!;7Q`eayDI4JyjaL0OFe;Qt4XhF z=-ih2gE!HZE^ftec%{l$v>pKmGkJ^Kb8TNvEY3o(dcrNnUrnPD3ym3=Ae9zpjVA*k zE{?cjCvQ%z$$Jl+t9%Uh8U%EDSatFTQ27`36x%tgWPCQVXjNy7)MR~qmprHSso6?f zJ}79Lz-W6gbDTm{URqUm!OlO3(;MGa*06cualIWHoe@!ee5o9iVk2-r;w&KczQM*F zqK|152bIuhk0@d_V@fDlJ5M6T=)Uo8ZVtgo{egT<>@~X)`pZ?v%T!G0!8^LT5l!bu zJJm4U7@I!%K1HN?9*O zFi5_?BwaR(PXW7X&OGMBoq{Xb0;AOel5Qq|-ob=Wt#MX-Yiy0m+}HfDvIiFi;9$ha zPMSiZ?65|wVOrMsIHjPw7=7q;uK}2G^?PRP@G{2PTb#iE)wHGhXMwXpt6naqL?$`h zo_+V?u*cfFdmiS)D=~*N+eP)KkX*Ho)7Wz; z4MM}B_=Uq7G2Y}yWp?Tp+l<|7-CV#TDnZ|YIX0qV@JDI{h{SE}FT*$AAM$F;lFAckLc-dV??HfZs*BXGw`n5SZ#$zk(6MFy5ffQo9jQyA(o6tkl z`CQF9`30}^1|1p)#fjYlzfs1RU4IG2P}iGK`E3-}=#%KeR<$tmH!N1g@FsJqJM%s= z&zS~sjFqe#*V#W2bo2;-)`tOdg0EQbc9HIJQ;+u4YX{Rf%r89^jelb*RWAHk?(PkF z)TE;yN9I2fGM*&Rkub$znCbq=>7#8=^sX0YvMw4`A>5awNPex|i4!DvE^|o61IR>h zY&>5T8uhl9dS-l-CxZa#RekjHiMzu#XZxSj^C2DLxp}>_G|DG}b>7i?T;trL#Pa+` z-UUuy$PRKg|AQmPpt%|hihQ3hV|lChr(U+xU(lspy(t;^m>9o6c-j(^x}!c}_G2`T zgyDrC8WlCRr6-GG47x&YC*1>sbB@u3mD{77>U-$GZ;zjtDzVuV%pfdlWb2rEQRrD) z%ROdg=VY?Vit;)^d^Dn_^)=7u$%lUVW(mDLOUSFc)rbYe2U zt0%M-!rUBbfkoT}%G^=!s<*e%ku#kubE}3VP9f4O`B~{^{#Tq~|s`ZITJI`Go4xt&OQRV#_(u_TmHFx>A5Mg|DBO;-N~cGSYl(}T(z!ua!-pBz-Eu$3b4E2NAeJr6m)_|Ch|Ku8KKy| z7>__R`w6!yBn0fc34--WOoZ|Z)Qfa~t1RV=Xe%|ujG@(NbfDO2^yhzPV#a2F+$9?t zqQsW9x}W)L&Dy{R*AB&+7=aa^X->l;Mn4Yp>)c^tzG)i)HmruufwYo@^OMsDQb}LL zj3oFdhe&bczU`ahwYF}E<9uWK(W5mUsl0&ot^dwAWJLCP{stypnpxk`zdW-Q1MO99 z18Is6fwT}#`CV>7UG7}Cffrav3$5|{loF>%j%b&3YaG9m_6kJXAny3{6J^ae4SoEhaLM zzxga#47bMFkLUrri14SS{JlDEd6a%5`b9$4yiF&>#62WDgs&j#R)2eAe(IehZB-j?Q=6~eAUBZ6=9J~2v%dnnTgKKa0F@$dk9b0C5E_l8 zlLvEww^C*}eZ2aNm?K8jicw%^?;XpGqGLXr=kEPoSmMc`qh5jgkAIxcWrEUHW;+8-ulnWJ0qstQ$=q{Iwr8St^oC0xGlrCo zZ2D!w`flE$yfH;ohcsa2uImq{w>mwIRtE?3(^r5Z1Gs2=u+lQWGZU9nKqOHibofL| z#&a&UKWrupfbo-~V|k5N1K~|vO*WbX!g7({U)A8bs>DNre_dBPxxcaE<537Kc+)ebNGZrU*H(#7n-EbE zYtFbgYtq<98{Eg;)XTodi&|;-G~mNPZK|YyO_QsO@B=%?)9*2j;|oG(TQA=xf$1G? z9vS(0yP=OQ{MNLKwkmbsgIM%a-zJho{eC$P4Ch_-jObUma5v)is;!vqa;x}%fA*d#a!-{0}STt)P(ma+fqk1pc6p(%Q6S9aP{Ug|pBihuBsY~GJG zIOc(a=HcPjKrWE0rV5q+XsMNTZ-C)#YWr0 z1v}qe@727KIA7!X3U|T&cUg~(n8K;E;?+7xgsE97bn8||(860E8Az?{WAi3Qh-J0^ zwcQvOQ-i8w;w!;Rw$No;W6Fppd*s3*39)MRC@Tr9acx$abKlxHA)NfbekC0mDOa2bchxjg|c=+J9-q26BKiYzg z{Xa+EUDywqtTseFWctu0`K|I!)@EoEyFz_N>M&IOnHAIi#mHpm-jW4=#U7Bju0-9v zeSYys2)f>G{b}dc>9GDS1XrY3*F!>*hWx|ls>uIB(rC3rE_#<)D(ym~7*ekO!*bv) z_S=J;jrYLqVpIrG+>>le+Z6}5p5_xSpMbS6BC&61Kb^N$JgKc2FWQ>h4kY>b>A>|x z2{8{#u7^`&l*#hI#7ojaemv@N*73P_MaTtmr4%(sc!;BejS&p0@Co46P<#i+YWQq>)%67tI|0=Rvw?k| z2&GFu@Mu%op+Z>Pfmr@A`Xoc3)4@&w$xsm^A@=+-yeB6oNr+(J45uaa7DgA-T-R) zd*ZlKAA#Y>cUQf_iet)|j2aWxjOTouBajsr?Xb(gEkyAi)@$T0@E7!orL`5jer~c! zJy*2x_&RxvJ%f{Q&gdL^l4CL&Hu)-Vcn`vg0%ndSO-oR2*Y&xJ34!6sA2*4~`XOkH zfe<;2d73s%FK3PQ zdF6Dg9-QQz-BtwIJY@ZbA0NWApn6d+KE16z60VL0S6Ox+7}*rIe)Byp(H^>}On8|S z=YeT4>|5D2MVrQl`%XB{-iVR3+fg#f)B}FF?2!vL-;F8Qw+45yhcPH976c}yRB)^D z5XY6wn$9wc+#mXl@FRr3pplOAD2*1;J4Rnqx(>zIe=;o=P3aBCTQL7KY5^o(m=j8? zJdG6QiA_G{cRR{%oX>&gTZ?Eqq@0V}bo_{aOm-qArD5Z#V4-%uyv345j>#=WOwM1o z%IR9d54;);H!2d)h-JBS?*&>_0jn)q+ts+`PLuV!>2)ttFGs8*`pfTjn4I0dCg$); zc(QBsb3shkT}QOFh|c*ln3&bC}>|JX?Et#R`A(MZ zwaJJ*fJM@ypi2s{dN0ab)YXQ5u#zT>90B!~oE_RV3*H4t?Lv3=F65;vEyo@cka#22 zy;x7KGCMsfwb+u?bAt=Jv8yFq^qzL#T~mGG`S?(B0&uxbP)1}y@@Jx$3t#G=DK^D& z?(uI3woxnFJB-4M`Mq*IuN6Of&~DM{f2w?DwjC0lAuBUn+WcwXntHundWhg@$v`ru z6;o%t+!BJKT7jM#1w0uJ5 zd)qy!MS)TI-q<3zRp<|wqvL= z6zW8?&07)1Wb0ZoNhmcxMpAuWha|=o>el({%bbn|A?0;9kKMnd$;3-Z`({iOf=HCh z6)!LIvgHWMOx(8qLyspCy`WIDB_FVk;b%o|TJfZudMg-#(J-|=Mpwf3G}kT0|8mm} zDi5l@CE;6(K7sv0iemizPcECLOuOY2?Qv6uHNpJOjEDUePQ>Q~8;V0npmH4vsMw^($ zp4{q5TA@})&%)IkG+pIu-QDLO$PEecIG2?rb!cJA1|tXK94t9GH1`b2qJ zVAFh@AMYk-ZI$G2tlX1S!scefp7LULdkAdhX(VHi5ohRac+Mv#(i{N&J2yhoX^BTF ze_cP8Y`_CoWoIYd#E=Os9i&px!^bdl+SNusxi$-mO?VWrTVkbw|`yd*m|4EWk| zOu$hW!MZ^zByJ$OngMxHS(~ye;+iZw=-ABq&i^qv5V~irSvb#lZN0ixb{!~2y-wG+ zA9Mg{?!ilC)%z`0+*mYF}cgcXZBP0|53A%mO-St;siDR#>1 zZCn1+rmiN=+-g3?59;JnblUDlYSItk_1(6^oIYA~S$5q^fI-JYCRgvuUdhBW?FKMS zqf*WzRAe%IK%t~M5SmNk=kexlg^o2D&1wdOtB{CXsTHfB++A03v!*OgnlahFQT9A7 z>^Lj18N6wOu%K2jU7bPl?%urNY>_g4o9VbDe_K`=M3v1{LKbVPdP z9|$S&-x)ULM~D1IwQdjAB|3%v;Pr-2rBOgQOaGSatfj25DR2N)0e{u5QVrYPb?GO$ z(}mx^kmSe9dOWLe%1R_Wma3Px(I%bM#w?qA|JV!>jG`BVX~+E97?7mh+|<0O4>vq@ z9yI4XAUv7o_Vdci9UZLJw3?yCxTW+OW30p-$MT z3zG!#Rz1x}C3XMQov^7)g$19XiVnIzxm63DNcqQU`+t?^Sk&*54o_&*eeI#|NfvyG zEaep$&DW^AHYmW60e}9udE?t_XO1ZkI(=BmxzKs=2oqtuaJ5LzIVM*s-T;gzl;2O} zp4VatwWOxpFN9dvE?3fu%hR}AoqbS{*@>IcRyH*2z;aLwxccplk2y?+&^kvBbA~OL zKkZSuS0G8lC5J&-wwWY<-b)NC@Ry}%Jt)wdYFfWaMm-n!HRWsj?SaS07Ort(&No17 ziA@BtQ`<@B5CFpzc_i)rX_aq=Pu|LH&SaiU9y2{0Ca+{~2wFj4dTi z(fUhIhqilYK{c%JhRn!cBcBmh%LM|zu6Nv%H`i+v>*Jfmwd0@u(G{->J7-Cyv~mVP zP^-__6YZhaU(_@T(j-=z7rd{-(D2eH<+!D<>7-nRWLxD zpGxi}{#Y|Mx$DQs2A|Vf4k$)c5T20d=V$lb<~gsBZD=nPbsVA4JJoJQs?d*CM+&0- zG48`R6xD5^EHCJCg1&oXIi_eA5DWuBr5!>NyCxSZ@0uiRV5^F z>QGIpDyUFQDH6&ITVoF|_~%62Shc!o6~7OT>m>Jx~v{&!!dy5ip6CpF<-MhmvvT<@r zA(m9P%ox9C;Vgh`Uxx2ji2X-&yP{91{D`*mb>3LH`maodH`+c*f;%MLi^}1$9eIv&{CZozzCZ>H7O`q5m#>k=dUUt zJ~CXk$u{GJhV~U9HkGTVH5x{lSq5Zm2k_TRwVm2C-x;RjM@=Cc7YqePIz+ah9isJ+ zu)glyY&VMBaF8pF7GjErym!`1I}+waJTdhv@I1>NW<{DEj=h5SyOMVbqW1Z;vd=f0 z%zhqXF~b7HJkYG9X!jM#T=`cBELr%MajQ3PXm&YS7_0Uy-p1mmk8_Bfy#JJpS?_Xs zJ`R!$dPFOxsj7=h+w>q?o;Q_8RRF0dq0sjxpyqe#8O6D60^5#xCxxO-;r|KL{r`eNfXDurahh2=dI?$2enehrdZHy%~t`mC*bEGbu~vdwY? zR!;q^PXIi@NtTWCgGRBN{zPI6BDTGuw-1kZDjom5cYaf^)4@R`PuA1-Cc><$WkwM@ z#S8sNPCP&=Ui*{xMB7afwLnXGJUFB<+s;>Nm8t*^HjSR`&xaCoXb&Ae@+P$`_&K|+v|77P*gU79hXeKkB zki@#bFw2s$KfvsV{)gh-qXo!8%$ET|tBS7JgMXlhH^!!7eIDo0-;0l{J!-Cf*7i?s z^P0bVmeZ~CzP{1h!X3IU%s&2Y^0%MNL4|V|_An3O8eb%O`I_-e@Sb}5i;UE>}9}QtW>t zJQ_8&(-6qg4n^%|h+jVOIYs{6*BZg|F4r2eFaPMC2N%L*j_&#`IBW(p{gmj5=UqC^ zp?IDxxSD-kZY0bweFBSGqWyjx$Ax+J?sfl2%mzLzzg^{;AkM~%U-u*(J$h+Z$=>7^ z-=pIJKnv+ppRG!O`FD`B4H=1f5t(OQv+&_9>x3^_r%Qm^bBT*js z-+Rc@ZoSgn_YDgn(poL7K&WR5&s;k3jW^mBgoWE7^(G(I5tbq)7jh;Sc#YP4;eeH> z>kmUG=tN#%uI7d20@|{f5FL56+Fzb2CRQ3HF9S@w`jowUDSJFZLCAhR31t{b!;F%( z3NxCz^x2&JLF%D9!<)8O-Zyw0=DB;3N^xYDBA8tF%vXX9ADu0&G5P8^;JxrBEzHy2 z?NY@jebXlX%}lHJ+VE}QB+-75eX|(qU!K;~u~o4uo+CPx%q}YP;E8l+Uy|&UWfY_2 zY6Z3p_-XdD4$R!aW4B;%9MOc#>n1dxFn?bYift@%bMc6FDUK^EZ}pVo0e&pF=@U(P zg%k}5CG=}boo9=3{$WO0#s)?3>HSJ5^7jUy3zmHh31w=X)#d_y6dGxkzZs*?g7I$<9l~zW2d1P_I-0m>}+4@_xd6}vHuGJ}bK0c{Q zm*t7Mx1|dm=OYLnH>%P19}g!38vfx70-Nv0g=kdF zP9gp~17-r)P{{s`=4-|*uabh#pKY{)#|K?UAiIL*z+Fg zu=ND(d}}}R#%Tw$ngbC2Ig}ElLk8SStn!gAPyGwDOC25VFdmB)4xN|NURn6GW_rh} zB+`7qYVjQ}OWr$RlC)@FRTb24wl5J7TNn$yHD=jAqfQyHlX)^gl+P~%Xx=Zwk*=YL zWbvKqLUin9^DDCIhj+P}O!sUI$Bj&sLPhY$v)JWm5&7Oj0iwHxmWt!Si!sDtkeMh} zRz`rL9n4xn9pjA;Ty`q4P*sX9m^TrT6@&GkzSPXhJ0C`Ove0HIxFv zpb_)p&$*V`cL9HuN%L+M*G@qSX#pj>W?#&!Q!2dh+P@u?t+w35u5VsU%O#s5;v(GL zB1X>Rn@Tp!6&^U_k(kZXA5rn!0MebSr>>A2?q%c6@Z_7uaBaD*L=rI$DZZYM%*eLl8*_|v@|S&U$mAJ3)MVm5I83;EN>0W+iD5^Y(6hvr;uN){xo zb55i#S?vta#ss?PblIYH5zij>UB7h@#wa;x|Ii`0OL{sR5**={??uRFWJC_W&Jb$v zpibG@CErd*Ydvw4^lEotX>Wqbb^z`aesWx?T{@Fo!kyD`n}q<4pq^=M&VUhzVFXcT z=x^BX{p3~@NsuZgv!~_9);C}z6Sj6b2w`w4Q-%dyr@|aJ-5*vNWwbyWq@Z>z_VPcb zh|h%YrZ{0gj?r@Ixhun)tx*9#Qxw;q4Sc8{Grjxo=H?Q)+^~tDqf#^68ERYGK;0=l)2|;%O zepk)ogrmu5%GT~?yh-eI`%p;8Xu|pQ7XuvN^NdKjpbfo@Izdg)HgEeSXRm6R=ju`9 zh!r`Rpw6|lMuRnfi`R8}=I;F+BT;YLKM02*+h11M$C6WJ&GKJQ-Kx)!=>MErF;q&D zMRC{th(Jz~>3o8h7te2bkG(I@WV7bXU)(X&v`=JMJM(|Z3le^0&2N82t0$4Wa#BlD z!DFKT5Ym@m;_*Yi`M)y|c+JjWR=VOX&d!%rMs}4P&T*a!gsPgY%Onn}1G-F$B2qXJ zQ$$iU77OH8ejU7_eZ$!)`;;{kIinppv6PagtM=jhLkfp9i6=wt3J@IW;{kYJpN=

z>J7+rUO~-wI?oiKDxr3#NCz2Rv8bP*uh_bmNVv)zk3qjnf?3%uzL1^4)RV#UJY1{K z>U01YxlZuvNY*xinvB}KviqfURu`nInc%a2bP6&EUM=nrpf`4no;F4)*i^)H3Evb8 z(3myb0+5wCuO+98c^b-1_1kwJq#%u*brj{;G`^8ccC206K^hL4UN4H|Qi}zaYEM$f zOO%fQIh&TMZA@K(j9TyocOrq$J)Bi*a&h1EUJz~=cj@p2#2?G$Dsw-e-2eYtNU_$+ z1#^L##dUS(ak7u_t-Iu{^lPntPg37>x0#65ybw^x|2;h=5L&O9V?$C&-*oMJvpUd` za{R)kGWD-)AUl{eBVYy})z2BjDleLsa8*Se4?#0l$UG+|v9h5SQHQVDZYRA>1~&Kt zuP!7jiTB3xVZahOZ*K+ugXP6H4TYl~l6AP>W(L7|)<#5W;h1Wl$Z1IX=D3vE%O`0W zu#)PV(vIT%sLv4EHz@FeYZ6q99ost4gWDfcWLY3|0y;}RNvFRTNGsyRGz)RlRuqsO zR_4cDIUZgSfm-ZyoIe5!_tbC`Rh{xlZ17&IP?T7eqE`(J7n%N zkbZX%pK_bJfK)h~{_dNN=rQj*e>f1t$N!p59NBv9U?gN7T)D2i97AxZl zX>6w7!N{X4vPT4Y)GEwg#~?5MUf^12E!^MyaA4Y+$^6B|iwL@qg1&`!$uO}MWrA7R z{lY+#IeGezxPjJ?rz@ys+@8LIs+K_@$DAmxZ7@sTb^E5X)Rw!ZT5yrHtpZztGGH5y ze)(8kJ$TtpPq}95llX|%m!n+t{&h7;mPq#9Rj!KPoP??i>DBJ$s&8O%f}@Ig$2TeU zjCJC&GgSGl2?DSC1%(7GJIYkw_>dQjfAaL9a})+70V7~kbw&1oDI2L!UBSz-vV${1 zYed(7D8gRT-5W$IY{&?>DuKLiRha0M804zjvn=5$RClnTBan>zmclx8#2cRTJsMEOg z4T^eP7#rit{D4o1#M|>159-lbNqC^e^?B))*3o!9t2;l0q~&}|w$;=>sc~{^X#;%F z$<+*U;=B<_%|5yEtipItmlenP$M62!4NmdslN*=m(Vs2FsGHVP%qiy8Pum+bmrm)n_{krZ~+WO{+d zEPOL8pym62T?zr*yLu_v4_5L5yPXxd2p%6CFh#knKhT@S9%nftWnc0(uwBYOfHsx> z1(sTiihLqlWdiARn_QN0kX@{ps1*K|o$%_Z8gwl=>Gb_+Z2*K=P{vBskOrJS?m$J@ z;{pDub7`{PuTk0k$j_6lHA2WXq<$rnSCJj!Yg*1}FY>@SuzNaSOe5cE&SZ`+*Hht@ zV9R5VOBSlbk&}<9a7)KX!5uA_<>1dhQg+P&HhQ0R)u2H{UB@d-s~e^s(5s;T&fIyc z`^NOYGizi_O$R$c$mF3!#toZui6CnvM!;FxmI{iX{8Qbw77NQ*ykp=FJBzzv-w5X9{y4V$M zdwPynOF>7VQVp-f04mZj5D*m0AgPc&p~P(6aWK%+`iS5ZY4jI#a63EISKS{QTg?s! z)6HsWd#E1zt(5)Eo^y(8|D9Q_96CK)-Z|~jneES&gJcKzld(oU8h%p{v{h3*2U0|> zFnQ+Fxk>xfQ7mIeg8Ar_Ou2F;ckts{iYfk?;WZKx6^$T^D@7{_x#9mY$1pmmACwkP zH~7(nFPSPQe*c|$FQHwJVBbLnyhWP&d_%Q^^StncAw1um={VUbv-#6A#6wn`nH`j{ zcdDq4X8t=f#C*i}QNm6}6$6Pj=w$!(k^P1HBT|#{@M3;jgx0-k;AzdIet^M?EE0*xj^UPX6a(K9pF=xlA0nmu7P*`_tVm zU4J|y-|Sik)VA7EuG)y}MEv#*bS<9}p}%O@-%;#esBPv8C{SO!y5?0!#Kmj@vT@Qc zd=&EAaa=;mruK7F5#N5 z6%~5fJi}i!>ot4{?T;13!onSViU8-qM<>a*tAoCC^vJ<=fUx2SPf}%%fb}o*-R`Kz z%1yHK7J!QUn=6Oa{xhh;Qz`sE0L(x$zgCn*19Vqy z)f3D7GvtycqPW)A*%3Z#iEVa!NSYrf%qRIGDEg!DwNGN^XLd<&i0w&CHz@xAG5UQ`e#rYMm{i-+i3z995);xhvWRlVHloB) z63Kl(0(;U2(&~6>nSAXTHWr zUN9zwFDa9gkQYwbnU-1wR{`!5Z1Jq6B;v18`Q`G&tT4Ic3LfN{0cpAGOtNkYP1QQPujlUSlw7)I?U=!VdH z#CM~(_CrHBnsiMWW7Fse)yG4=Ll~q}jSdk8T(c?ltv`W13#C&aBEb@-WQ%UbGjC+o zMX|Bikvtm3h}k5T^oy%IHOV~*nj$jhw>O}mg?gd}jewO7bdktwRa}KHLl3?DBiGDKo(;bK+ ztEUZYOW0hL(r9Mj;y~Ynh7DLoG-zhDxpCOD6(|ev6=$ZO1HXHf44VF)7`C;1_YnE! z;ulTU8}vamewq=fv18q)(+{}`GCi&sE#opK9LwVpm1a*HpGlFu)Pb$$2mu3=+3ZBoqnnQ*RhjC0iu9t>p6m&tp zP4vMOia{L>5JyWUn_}e&J1ty`v%qf1@P};|4`P-FeGzDTjD!WuCG3emihmlEU{|vn z?6`(~fr7-amO2r-M7M-pF5-AeBf&1+i>hhdZk*e;E`9tcEKEBwEkchO4{V$!Hif7} zr6^f$1j_*v!!0f>rrit@lLIu)+aVNGWD(T_5l9&wFhPA;k|j1oAj}E&jF%)9-bvc5e^GeJu`EF}nPg=!&6qCY=u1SQ zyfR0;jCUOSe2C2OKD8tuo){B06~~dW;$^0s3!$!pAV+f(q9~gD2&y_Fkw~OfQV1Y` z*Pz2LNSWY4=!VKYWHdO08zIpaQQm}{2$MELnkITDtqC297E$1GcXOHUDF)O~qj9Sw zrLN-7giB{#wRf>sdd}-hxwoi?C`YOloLb1)n?lC~=v!W7^xx_s(c?zO zc&Zz$G9m&E6X0E zlB+!qkt7UgHlHP}Mcv5Nx#-lV=!Z_BgtF*Da@+6FOW}y3L{<+o)|j!W<8o^r^ivPixgwBXJZg(j*@4g;4jgv`WwVOnv2Me7v#Vs z{4wOX@CTt3Ue7X5M}Zy$c^wFFA?Sw`L9z{!B}@lVHP1|Szy1j63!+*ii4ocp2xGV< z!8 z1pSXF9su=06gi=%1-Keq5UA+U3Z#pZM3PA)_avT&Vn^3CUyBuz;|IcmB{D$N(b3V; zdRywvF-Ra{xg#yKWIh8`^goY~M$cl{S)@fLm~9ZHJ`;j zE2)VFSws;?tEz~rC-UIQ^b_Dtu8ehKQ==%a(V{N{*p=+q1Td^eNslRvqpw6nj+ms; zJpxw*85$dsFV#PlQI5#*gwr&Nvcn9z*Ha9aOwvdYyO++xvLwLz82TL`f(WD+8AX1L zFlQ3IiP&P1h>W3|tw*9qNhFd<6=m5+VxzIqGGunF^vz_6V|gMH@3J}?t5#TFL!O5m zob*M~=(1g-{FD?Ac6*u5v$Nr#R5s_j|5J}H{_W<32|BIp5(bCDo}YK zN18l|5Y@}@BtVhki7wwPj+q(>Su}zKa9M(5ai1F3Q2Qx$uclGf{{RE&%_4|N=MyB7 zNhFeJ)#!XfQTGkT+B?J1B=jLO-%38TL^}_wlu9DDAe<4k#EgL^k|89LO;c2wr4DF!sYBpIR!c&NwI5YdP!T}|-Y)S^ zbURtfBxDGX=z;^au0)AK(93nHp={W6nPJm^gX#z)p%OGRvmFJ^+#Hj^miUK|$dXAU zl1U_zNvNF?NhP{6MUYXf$h&G-`pT3*)4)s#9<9zo(VB=SsnYci;5->}|9EKGEJ8y}-Kk3&smIwq2ENhHyAX`)0c zklb>eu_?D`85D{|8g(O4m$jJqoELOp!pBCF&HN%`}@CW*Ls){15ncosn807pJs63%ukCZT? z{fLpq`J)M3kN5)I$Zh0%LqLxlaKKY!8axS$p-@2;RRIe#gLU}_*2p&Rd=ABY8C^1OYgr9~)!1*FI zCFs(z%0EKQW%7wNEhr@`v0Z_p`yR}r3ckfDa;6uAd5c7f=|4tq;y;I&%v*-^JYZQx zuHz`)t~F#OqaGR>M7IJ2+b6J^k1|L}iIYMQh+iq#?6{DBiF8Ndnx-l){{ZwyxeAPn z>Y~*fw}RBnvwXNP+rZXbY~|dSHugAdC9=a3*SpD_yE0mW#2N-p<`}RUCH0;J;(pq47OS2t?B5an#jxFp>Tr!A&ntHk$o0wJ; zx;7?H$g)Fw;CMBWvzQghN0JLCCD5&w%vG{VNK3fxu>{K-%gGy9=b9a;WY&7$;8mK* zG|xsWFi+y1jI>!fI8Keb!SsXRDO<5QOx|u{=Xat)Zq^ZKQtc+pz~yEb{Sy<6P01*E z8W4<$_A*$R9H@vIinku?Fr(D)(x;*q}rg||} z=_7d$43NAv6!?u>M|Q~+GlJNOGGd0};N;n1r0z#3aIlr?=$OK}c^dN8hjv|LSe_W1 zruh@Kmh(ySB(2G0CP8jUc4X%wCl@e4-y@v$6VU$v98!8xf@p=)KZbf=V$WeHaEY*r zBontJsd^$#>@w^6EP*MQr0>Q_m6OGc*9D6MNv0L55q9`PLx~h5?{UnjvSVWFWZKZ6 zS)?~8T)%?{1$GkJdj<_;YY0c& zoGPJsgQ}8zu})1kF|rm=wiah*9->>e2Q?=olO6{O%#Zj~T4QWMhY-w0=)EHa#es3} zmvN_bx}6Zf`{82=XI2Mw`w!g^p=QSyKZ8UQXgF6w@jg&!u#bOYZU$l4L6D8LBcPfE z8@ZA7A1~NTv|AVGk!>W}J&IEPLt74Ppj@aPsKNdo$76KT5wCJ_pve^jR6frFm+TNk z(iL|*2+7zr@GAbu`XKU8YuHZKJ~$L;PDbGI)d`){GLl;-EiK|q#Gi6kK|9C5S5p$^ zAjJ5$v1Jx12AgNe5GM+R<;=;pH5VeilTu4?gev50&H8KLRUF4iUY89USn+|pj>B=? z>!99MlWFuFyc3ScRBb|h4p5lx9oU$~6e#4J-J&+A;xe!!!XbZw(0d&pu+d>W4+JNe z8__gF*qEp{6B{tT!&wv9Yh*=p*rRz++U&`>=yFk^pcuUvFPSWD&%s$1nNt{k8eth4_BuX zZnimZB;cHyb@WRka8emR+!4-)jwERGMRLy>7f1S2se>`pZiFT1URpB_T)7a*(9kmm zhenGZ1B5XKj0{vw3#AVvQtlM18w8&lAREs8J=9zHaV0o;bDiCS|tvIG$q!5uq2AP7p{ckU+E?NRv=JfAGD(niZIQ) z=p4FupC?&@R%$16i6LygaW4Wk6@!OlWzQ>Te5uGwWMYGoNcsyOr1>qTh3-w2B^fGa z6X?aactJcvxm+_)*N7RX2?OOm!(q5Y;QBL@sMwzaUksKmyCzw{X~^=C)##aZqofP| zlZzV?_dYOm{gzCd0+kpO3S;9$!760w2-K{EGXu$Oicc(n(`OhG!J>G>wsW@PDD>><7A_F#mUx7iIt zn;bZo%O1-=V(w@F$qP=Re;z}}YDa&OA(LN`vJH&o%P?kTbQ1MSQyLusm}q%6qlL(5 z$=6{WznBRy$_Frs_EDz=$bkDYQUTfN83VD}NP_xt7mNrnCj=`^OLD?wm#7(}GPFSs zMCulhTB3#tTPRDh>(Kb?Cs~rbqC~H_sCyw~>lrPd0)HF}EygZgx(ygZMOq~4j>^uT zc|GRvO?NKxIKYn-5*A2%X`vc9ofX0$m^0vn`jMeSRf0Xo6+(RkWUv(OTp}E2vL%|> z_kxz8(xARXqS#c^YQ_X1Y@EH5B~uK$VjNhW;7K(miZnFilOANelK%kU#KVDYZ>b>b z_eWS*clkjp5-l{{VpmAM>_^>R+d!;eW&jV15;A8E0oZBp=xP~&OOR_1~r7tn)9Nl>**p?Lz76a4GFg9hAHUwxfA~YaE>IR zNPu$5oF+@On=y|B~oDM*i;ut|r3vyliTZR(<9M9@&Y96`Y>_y*^0Zze=be#3#Y+*g|)f?!oT z#;xFZT%7*^!3?T5W*>!=x569~a-9}9#!#IvaXuy!(4Le`I+ND&x}AxU!nVm6G3FkO zR7oW4_cqStjlQOMHas;2!3`ou7*X#B4InEkX6w^*f-Bz0&J(bgH?tyy@=LyOCp|2P z>@%q=;H-|q|8AP;GPn8vo%&8j=t^%ayK%kBEaS!4@BrPL~oIhIvG9I zqc6UQ(nD@DBxS!yT_!ZIf(W#VgG$@cF+BCJVK+c^@FkQ}7lZI+&{7@+XY>*YOIIqI zBM{(}kd?hb8Ra4=VMW+j)od-YHRTZGshXL-Phks;kKuuGGrYCw;KisrtTDujW`a@u zF%>Nab}RW8$n*#9#!awr580HF&hKKF0g$vWW%h6<%*6U*3edV+>)3t;)z-KA^h<&p zhKIk%aXD;TuSMhj+JQ6Wy+R|KOZ ztEjjbSsg1w@Qf|wnNhB>{{RM@X2+A&At}mC>RtFdNk_^45l$hu$bB0!?tcROUgerc zVJvg@KbWyjT4gt<{K+|Uk|jcNW?D3cDH-ub5F*lL4>Lt5(?gc%hTxlWr`R^cFvA{(v_E2c$Ka6KMI(2yetj3`0T)6?)~*ptsMgUQq~wqCF>_so4CIrc z?3WBF7#ZqCRY&{;fuv~D0(|MNWI2X86M+g$z!8?C=>Q7T%j^pfjo((DV)i@bsAylDSpquC9 zQ6Yp?48ZR0B9TJZaVh8&46$xsVM@qANbqn!jSU4zLe2C+4E~X5)VN~O=uq*dqGp>B ziK=H= zI-qDIh_H&g#Sp+%{09?WNGoRSK7U~9pMeb5=wSZngx=XDjYr96*~gb&qHRGNv;Oh`b3d;~g?6$ehD?otTcF?JbTf`bR{<#QWs*Bru-DLQbD1{Wi3BemmrvmM9>Vr!7ITs< zO<;S4=K2d8)X>;Ly+(9Ek%+*#6O3E;NUcF^VF?IKApDTeE~GHpFo!~8x_0!|Kd44% z@PE_|dG;Cq02qAVVPl;3A#U@v0ueCqH2BFqQaEI8AAGUjWYlbQ^(*d5*2#?wPAqn| zH^`h|Yukb}K7;ApL(MeTB0PXOy^D*0_{PD^4(NiFbXV-eK-nfOWR@(^O7w8vg)M z`jUpqTjd=B=s3z26dvWD85ll;LpO^R@)Jzmj`$%!&crB0n2WKRjm#-s$Aq+e1x+8Y z^h-;VI-MDWM@c4rhlPPpF{5wTSKwmZ7w2R~Fy2yg8-3g0jHT?yZs#U_3&#lR^|9QQ zSm2oo71fgR5@Xz>3{AtB5-I8>LjHy<36JX>ljH4@ad<|{SQOVoXOe1mQto){a6g(Y zT2ghnpGedB_cB|b(FJ-xVtIKV@%AXq>IvnG_cFdkpLgsoy$fK2u_isn(Xi|*=j2tY zhweyyhSQrwsU(G2!xNuz= z*hV-uHRmkJLr2;x2i$T}#EB!>9YjfIB7zlX#MBRP<-z$nZdX?uI-xe7S2{nQ`ZTho z=1z_Z5{dHV5UZ^S5CsR>mu2f zFm*DTj2T!xDgH6%xj)7U@0I@m2FtJV9{`@Dl{7p!W$*zUHK}&8} z+jjXo@D<{Y6>WPGGDu(SG{&2U8Ij%AJ0mmNIAa*1 zQ^>6U00bG#em{^YYv84!`1ymgxqKD zC^)6d?4bnj?R}IHJk#?GxAEoU2X(E=8Yn1n!vTF zAFzJ}kuG!_v2)st%%~9IfbP;NUe6PGFN7yg$=ru); zqaX}MXuOdZVQ~r{cFFl2qG8%@Q7+MbDxU%TPNMSfcF2IzZN&SJgq|u+;x;XpFWH}O zIx`vtr}!Vi(39sjpc)siv}Py$9w1H$)Q|#J)6BB-BCi%pmMD*9+&gS=%aQt_N`hNl z29AB=w0w`yiOQcOsXqg8;YPsryB$f}p|c*1)OC^Gsg1(uPKNMKc^ml^uj?R_FAQEJ zMGKtV$MX;1PeRPE$=E{$yv7CK`4FIPeC$)nXUfO7o}i+$b?xDwp95DH&2tGB__m0TH;7e8Gva11fup=kFg)p&vr&>$zAvtWGz4z zm7@Y*QDESO2uM!B+fG=hAUJgh8*(1sqK8Ir-$RxUDILfZmj^A!;7^S@gFgy5o@7~` z@*@1``AI~Et1yJz7xjxA1`z)Mf!PU!J_X#HD<`37SS~JPWKHyw^e1=;tspd>Z)+fC zr-Cb9#Bfl{$_aRT7!p%4gX6ggI85y-h_IEOEUGL&up+mlxdgxBg%ce^ywHT=?SlUR z67pc`3voR78+(~3N}DYF$(5Fir_oaF$y8R!5U}<3HIh3xf&x`MrYBJn>Zn~97s!$c zUz3=wO@Lb|m`YHWl4f)dz(V0=(OF%=(b@)2P8$_INJ{bS(CB-1G$t*y1W%Z`CS~X- z&!`~AxNvU;6f~RWEO>B%yja(y$8HAH3*ob%T7VOVMUixb_&=wCsYrOm`WRwq!xFC_ z_tDSCQlc1gcm;Au|!wio$Llf8gnP0Z7|R(qHU=18F=N zuHU<2i+!v^C|jxg{TwzQUyH>jNSpVg;vP z(mF0wStTbW&b%=-cO@NGB@g?lPBwnWco(qyM2wQ|%Q-YtZD!BdSyRXCaAihJAt;VI z^&0*+2$o!6Y9J+1g#3wcTra@{eAdL62B!wzNnbL;`Eqf9fySari)Yy#P3xbs&&Y!E zZFX2kmsh~2Zf@=aXWjdU%@=Asc;#i-V!me{47He~ob3dYA#5rms^Er>>6 z#uG&yLNx(0jCDH4LLs%}m`7Ve2qJQaSef|%NMi0XznExkI2Qu{07%_W0djwIWDy&a z{LcdYX$vwpgO*&4bo&7z5q_XHyZB;klET`nLJd>-lEsgarl{XUj{W9Ub;oPGc<1sLB(mygy^+VKlxA>_{GC>`j$$W%6|Klsc34b)_kJUV7p+{ux>A48j{^#1^YO&!O;b&*|> zSyC5Mq?AuXBw+WmE&(AkWF-Fpk>O)}ke>ot(Z!sJf6=7_L^6>p7e!I%}~c@zWI4Z}+Ee~#G3AF2twolyks(0yoK zuq>a;44OWoyPVT9B)g;dhiH{CY7R@~8flBvt^|C#F@kj(X3k2uUhlb~1I@gYX^zl0 zv9TZdJea)S+81d0kQLx;Hn}>(z`x}RlkkINt+*1WP=9qiqC~Us$uR2r8xl~Nu6mFY zUg(wNSlB@t!tfK3!M(^>l2|5E^n#mw4ak*9+=}}NXGGx5A0kpyfhz70c}f=n)OX+w z$( zV?xLJklB_u=OPnpBxA?K{f*CjbRec+n)OB`<>YNI z{gJ`FC~KqHh0FX&h3)J&2RGxXf;>o}D=D&rc;bD9ME?NWEYhYrbs;THtavJm*8{-t z9|6MBlZHobM!N(W@_vO==+^`*jBL{@0?STpu43{azRCAS#`yA%cL)^~EcYA!13%+q zPvr>lIeZd~JDSk_93g0YJtn}~@DfXGya=gohKw@a1kPpe524(MC?;TlI!u+FHbkb@ z5@>DZa;VA8$x2kI$~eTpLDQC$a3LXwp(G1whK%rbN`zM#>Pf>0%qz(atdc5-6VygZv#_O!!3h^rJ74a} ze&@-fpR!a9 zknw%jVaEnDFHGQIp7rF}WLf@7LZm;gX@d-m=buY+{?8%vECQclthw{W5 z8_iW$YpfQZFoLHCvrfilOU5BF@VFizyam!N3TX}u2lh(qV-*Z#w>^xdju*xFM=ZyN z%eMzZV{WWcl6gzW?LvJX29qmu{{TlR{$zYV4U+bW_!0MHPb5nFAe8P2lVhK;Du2{C zbSR6D@8oGFzDmRXWXe&LUiXo@P)p5z#(CsoSH=U7(3G&&{SCnqI1rgKuhc4V1IYJu zDe;R8g_u|)1pWle$xREYI3Qlr@9rfy5_}1f8OWMl_BFGm^>r3FJV>&jM!UX<`GI_g zDcIYNp^KNhVt;OgULHhtPT$gBlkg7Z% zZnHSjjFQ>Up?5-bVVmHH;6ya$rR-IwT>IH|BvZ14+#~jaR*{BTw-6y#1$6z1XYXQ# zMmx(QU`9wS3qWWolh~tD^6JiHkL)z&#v0QxI?osrI(hi$XS4=fGcxfnDAgnhsY38S z$)9m+BX#JqlBLFfB+PKhjN;!U`>1YyiMzQ%sy_b!19F$h+_Y*|yN#rqkD;l5E5O{q z+??b34Ye=G)H}H*rZT{`lb>==&>eUm**B@m7YhQKl0{QG9hDBUG6Li!vtkcIS|oH8kx|=&u2_@mQG0C zE!}nssjoc=u-b^mypi&FOA?xxxi-KTwgtg1oo?00BoR_C;3BmXNG!F(bmzg}fzI zK1K;Dlx)bqWLT83_ej&g;c9FugRnr~Ba#AQWte3PHWG|6uE7fFe2LEQs=Tp_!4hg7 zP&zrve?sL{n_dJsq_moRvc#59!lU3n_h@-SsadZBQ{d6JHd ziFWK|pKKv3pCao}Hw?GrNa!X|Y{*h5k<9lFa{LI-fR_FT{{RTY4H*=%iRA+5=uU9V zWNJ5&uYol}j5`Fs%?MS80NL5U_lauV8HdBBS5e!s856F;=afAi&ck3(EXgf1@c|?I zC1>BMc6%Bl{Si4V+y2OoE%U6{%|g>gcpTg(naJ$Dhi?A>x{l;aHc5OFzTE!+Y^;{q zl`O&)*!Z${kS3?NTtQCK1c#x5M=z0g8$*LsBt%IFwKjVKMI|#H#G=W6K;YyyDaJ=> zTot>}ml)Tk#dr6=XRuw@^%KDph9H^=&E0p~$!8$liWQZnJfpP_ZMk*~ajxJ(-wDWd z#uf&%m_)vfq2F2&Y31Z|q|ZUO;HMY7B$G`l9KNNnl&NgTao8}7`Ih;gAV zxhikL8xlBC>P%U~OnU2wTiq{An~&cg!9Ch0T2t9; zZVce+5S&Hs2H|EJ9;8z4SaY$H-cf8^FCsZRtU6B2nm$XD4Xk~b7%S{G)BXsXp)%G` z$Sk5WA~zGWfv)HEL%`|Kvhav`Uy&->gV;c`u0HZP>=F+oe@Q}f{Dzu_-oHMARrcsd z>=qc}8!0>3v)cavBn?j`C;a4>kuj{^gl?+qL#WK36C?O;kL;vytmBU60e^f3M)<{j zM~20NG@kkP8@uK>9wmE@?vKkIJK|p~l9*`rZpupVUL<`9d!O+NI^GKH^x+ePOZ*cJ zG_s-h824KDp*E1NPLM~UJQG8N^UzHlGm=aMNzKs9=-^1y43t!#q>1?WNx@2tu+Jo< zkpp^d{0k6yTp~E4?21jZ#D9#1N%ljZg|wh-Q2Qfom8Q{lVoQt2-}soT+YcOjN;gUD ze5FJ)s$@;Rb{vii9tpHVZqAY~yf9Xx%kVQG*-^l~uAtgY~iA^K? zz&7k?b+yzk6T>Y+x7v!8ub5+LHe_Jltf+D(@~@Zh8=oiHks%jd-@vz`u2d5fzkyAK zfvI%+BqS41s~Y`?z~J)|D~-$8YD#O5*^##8-DI||vdy(U*PEvAlz@EXo#YrRL2BpROS6$es+mlPw=YH}gcecBlGHq2RR9olYDrh^wCr(psdu#LXULS((Ssr+aoMj=`iWz?`j$HkJiD&p|Gg zeT6Wk+n)TI@WlOw6X=_k^%8iO1P(%4L%FQLoXBH7vqJ0>H@peog-I?sB3y^=EbSrS zx|U>~3meGNVnm;}K}^~F8*t(YEdK!EHmL^OTE50AuiUwbY`P6XDGV!_7bCW8zv+g^-gD7_#>DGT=@ zsEN@w*hy2vBv{BZW#x$DrFURfVLSvY#GsuTAZ!Ao6nHc(`XJ0sjwt9yL48Vkp)!@4 zOQzYkfQ86tmkiKrbP&W!OpA@B(MMij`YF`Cj{=T7Ioh5?bW!;Vw(c$oh{%6HfOKfF z-o-7GW|X>&W@3|KHP$JLCx&#!Svs!dG)U@X+G;*UZo-A-!W_55D3NjKYP8!do~YRtzRDg6YKe6sX4)#roFiLG;gq5+e>n7_ z0#~q1W=U}t?1#lH-5N<`;J7h1EyaLY2lCNW&*mXz1Ggz7Ce!8iO>Bgj!Z8{kIgag9Ue3*#7_`qc}K#zu>jgLWaLpG^(e##a=$5(5-GQgbNiW zI*lK!Zj5zApJLA?_A*6FQ6dwXVb_tQrsPk0$3dew=gAO{lQFN*)-0(scyD3VUu;M>P?YWxWT3)Q1%il|Bc4&!Op*vB zmmS48L3gIf3#^*sO%7x!qp)(VZq!F9T5}<={{W@(S5&o}khr^2Cd^H7nRD#tGTkAZ>A`kAgDGC%}01 z618Osq?%8X_Zr7ghY363zIYOEEQ-W$=vi_82P)zROO?VQEff69a*gl6?3$&J{{X=f zl|Eu>eTj30z95@+J=tmCdT5_~mmJ%%QC^w*CLEVsxc>m*21P$aD;DPmqO>l=bB^Y6M5u+jwAJjnvN2P?idJ=XqI%rGD<(4)7076=i&~luABetX5 zj*aey@b~#LV5=utLgaz|IWEd~vhLDe>%57M`syW{?bu6*&J3mr;7$*r3ahH_IZU?N z#J0|3?sN7dUa-N*urJIuXuKFC7+jg3u{DPBoW*kJWUT%X?4d!$u0c!@;mM~GinnVc?p zsq!?JAexrnW!0KM@)1gBR5+VYLZMw)$&-YwvN0>&z@vVbZ3vriSaJ)2p@wxop|q;> z!6ebCsx|~Jm4X^lh{t0hOeowKOog1_vP8rjoAg51>nL+1h|q6_ckU-X1R(Xe>P<+QDfxC$3k4J+=-v-C|C5B z*DOQ+Q1)szLv3jl{+Gn|`6PIn{0#m$6p;6$J^uir+%X@aF4N3n1+1Ew9>H|`q--plB>kBarpjq#;U02LlWVE% z9w1fbOX1vIG1Ip5KcQ5I2#zHDq7N+2$Jms2D)1HIm_%kURJIY%=!~m>czlW3xaIj{ zVJbhQkv7VD(14T`d2(l?O2E#$*e2{;2``!sy1-)HQy1uvX#PvAG0K!CGOMwu8zK;s z9W5BX*;K(?B=lnV6~(~-DPhSp;ueEHn?}c+vw{Vxp8`s~XLel!IS^pVFsHbX_dzT2 zF`|z0$hNCh3kKBPOg1*>@W^TTP}KR${0b)%`VhX_9+o12fA^GN^!*@Ee{av)B4yK}-N#FU@c#_s}90^yk z{Ee-NUKjh=L!<0ENr^!TYjRJ6!U7|&q$ZR4#G_06ODN1!fbs;W^9x1D-1;<~z`1#N zK2Gs_A_+J|FQ)ZAE_O+^77e{SD>b1a5!^g4-h{+H=pykGVpYhS=FP-7{{TohzGOkE zw@)HFF0wq3nGhx>z00lz)JA5JQ)8t>tK4{*Q!H=7=%9t#D`Y~Ws}`4 z@|-jZ<#Z6d_IwHL@*>3RwTM$Sf`q)YBufJF9}p3LX^PJw75g+5b;+;U1wqi2(B!j` zEDB>x8dC!w;H)$)TJ$U#{CyC|l*Fp#*JB+f z;Ngr@DUPR*3WRwOO)fbVbT%a%zQrfWJz0aZEhMFiX3iy#&vjcE_J2@7Pj1pRiXKIA z8X%m|?1R$-GVI!K-s;vH;OK_uvDG}Q42oAmUes) zK_7ghl`NitCAAaAITXX*cp=NNrm^>6U1$%(#DZGVwMa_LT}kQ9huQl#L!|;20DhoQ zonSMmU|=vvu7fZ&{J^EP`C=L6wnVO8!ECuZJF)@wBx~f*oSdJ*$?jM)Re+d8RCqyc zv`CX_xde`qeg}C$nx>QB$HG}9z?L?B0;|C!F$Xc+ zkL={|$bCt=BrSOeMAuW8k_7N&$rqD0HZj)_c(Ol3^eZ0-`rti>K{rNwy(8^4B1*ji z5Uh|vbo)$(Eg^lbs7jNWJ;t%`?1NOWTNEZ5L*Cu7Rt z^gL8~6_bwxXH4gTd6WdgJm0koD)gS?oJu}{x`VT^aRcWGe`OXMeGQja`H(X2-TD+H z)<(6mehz`@a6QcDp)9e-1ACU`hPT;4c~gd@#|>Bzgub;!D~$K_$Ri{V@PioE!x|ZC zAh{zE1oWvn>_;9c*$u`rWx~CS3h642#C(uO&c&&pqz)~LW5CrX#)a3IWYD`2xBNu( zM}p*iQ6#21k~tieV!91&()6@0SuV#A&P7_@1KS)9GUmqinSmqGu1kq7A0gQG9pKad z00AAY5rR@3UY;r>_Y&deJPi%tNYB7< zTxyJELB0T*u;PM+Ji_2WVX{p>k>Vvxzl#>*Y;5J?h4Hece32F_8I8<}###zaCIpjB z4F|vM7%S`@rj+1BI(Nr$C8OjkY;)p2XMiAfOUHq=Hl&lr#Raze2vqLJ!A`4qAx=~~ z=EboU?Sd_9P%cPKLf?$&p*72IXY7 zK@-r4NFie-X?PMzA*DG(;;|u3 z9XS;Vo!CDylmqT%v4Zj=${U%`(G8MkfU-`!*t1F8Dd`DqtJw>x%drWf3HcgN^UlX4 zmf}e3z(Q1r!(z2*coILG-o_Igk7?&q)zFm&*H;bbS5IA$(58Q6(VTwSA7HbeVb>?K z7GEr})xu~rCC>6f4*vl6$45agw~cR5(7Uq@B`4q%4#ro=+wT?uHbhw+mp)L>JIS_4K7^yGH0be{O^pgp*S;JIio*WOOv9v^>jXANbj5A`=`k%;F z$nG*`J7o#{3eC_D$#mb?8?qI%OhoFHi$J7Oq?2iM^f#@$7WY7 zulNT7nfSXwk%=WDb#c#TVKbB5MJdLrKz3*BQ{*+SMyg6CnUOdO?jZGCM12#(+ux%Var(lUme(WoUKaz1sG7T6CY%wY^= zP;4U1d`$fkGCjkJhMy$}cH{K(O@R!0Cu&Ar6Hpz~+Mp!ZV?xo-OXg>u9PfY22ElzjN~gnx$a1 zE2y4ac`o0b4fsDsZ4<5tV4l5(jz}S;{DCE|7c&FCzb+B}3@A$=ZPj9CQOUU*Nut|o za}Ml&&HW`}WsDAJUM;dV^U~O_W&TbIp!IK&DdIW@u#WIq3_C-C@o}cBw>rnri<(1= zDjQ4We`uRXnixDB@HyTNkqPNUbQ8lE_+|)~qF;I=gkv8G3TFor%2+2cS(-8ej)Nx^ zN0K+bN_?Q5UhqK4mk__eZRja>$bwCy56!+urGL^TX1P=in*vmFG_2@xz_DU5EW07N zK_i5jG-=00`-u;30NH?kr<4(*7S*qlDoxj7B7;d>AqtYlWXjNr6a<-U!b}V^IX9GL zq5l8_{DJBAEqQi8)YXUlG{tS$WpR5v0HkQX3nAv~@Ij@#^cxwE%oYt&@;WrKC3%rV zS{**sDeN0QJPQk)mRg!|nm6;ia3D5RILk$>ZiXzkNLy4h_l+X|0KyTB2SP>v03l+( zvUFKcR|$cl!- zWGtoVXZIF{=A|jF7wmZmo7d!l%3SE!*t97YM?azGhRm@HnRG`trHcOmP{$PH#jEZz zNfXnc!za&5*+TS!FXoR%dY~N2CDfmimdZ8LaGX$%tfG4W=bg&JCq1 z=wu=6F!)6io`<-2vYo;)SM`@xXxN;L$|V9@QB0k(O)P(N6PJ%nF{PokL=D79;S7go zR=}M_$|XnG-e2*Jhm|L@c_mT&rYY2uON1@i9F)9-xSbMFnI3N$pY;NHz{ajgNIKGKL8O{^NX)Fm$0qXpRiAWFhrpyb$nt1`b$yB;mUm)}`cP zKh`nVar_CklGf0>q)c6IS_YXClo&UFME(A%6g3c4*oKL0L@T@%KZ=WXy8i&Aq6p&5 zwwF?6B#0l@9N=E$5r;ZSPF29dM0?ocffM9&i_dY%mRti11Os12C$u_bQhSSn1$<7h zY9H!}F?$%?c_-M)lE*5bUjCgh$w!kxz>w1-z~!iIk1z2GbH9*{+tWgS=wTtFdRI;?rMtP;s**byrP04}T zW2n|omt{2_geue${?LQykmST}0GW0|n_`36_zzZpQZgxjkPIq^eLD$u;M!e+4&i6f zAt}=gbi9VOhTg>g0E3WZM_5lbCd)xJ31hXen!S#XoeXSwF48~zLy=fqL4$JJ93O%3 z>z4?y2+QpJbpxyx-90{zL{yCkOAy>;0S1fgI_p4M#ld|Dj{coW6yT4tA?3vAV{pjd zQ7I|dznMhcC_x=Zt?i3MqZak#Yx;pIO=ZEDwx2Y_@TtIxnemrq|pAlp1ljAdg{K%LIvC9M2~Z*LC9`z^AfR^x;7ln{xb2{H$Ak|9q# z>~_Y)=x(5}Z!GzM(j%@_NQ@+|;sdXcV7b47QzL!OPx?#ZW1-00xx|z3BwIOafuuRK zNS7vuWO8d=$MU(Eg8d-yTa+U42`-_zK9PvdGJJ-Q@_8H_9&xwm^Z~@0+heC8COsR+ zBO>xZnOgx8abkG?0D*9|LVX%gq5K5HN7)G|7RiblVw)i9^p8(0sm;9(!aD?OEQTVB z)1R`30_5wskZChLHr6r}sP1h(NBqc@n$fPpkS0e_$)5txxi6A~ zjty6lA3hPzSfo`*(9a^x4&#pA@VG{UxMNNS9gHoZaiIrT5bRcr#1gawA0g@W@DiUq z1QpQdDexyqy#Z6f*s;k3JBeyeN=T`ayvhDzX!h17buwZ9nLcRpl zu7fq;qk+1eMvWfqoychFjIq~ZU@^J_?GTUDu_IaGpRjD~ z5{78*u%MLGjT(Okbk0PYIf{-((urjb=gp7^!?O?86@hM}lLb2n()@tksJEiE+&K`Y z!3<`3qGQu}^de3hG58WDkK_}f@)8_A?31(EFxr|s9qIWXSyrhSX{uEKuf~ zmm}O!XepM7DV&a{Byi1~1$J;yhOKMpo2L#)1v(mbefZPWHiafrJ^F~aARBxSGS#l*D71Rn5cI+9-r12n zh|=n|!t5kR_=AV^Y9e=YBf}zaI~(bOxfGc0Hl&Ebxf5wjk5+N$h;0W^wd3fq1tNXK zGCjtFaUvwAfcN5Y*ziPYj(ZWe-VmZ1HEc^^z&r~bc4|kir@5DY$edJ)YB&-^u?6V} z-1-R6f~lZ265CicSHmH4G1ZR)WU~r9pUh}sE+og`vzd>$##_9PiDe>%Bxfg{4D9{| zqf&pxLk3;dz~37pIWP}HkC_?3JTWR!ic%dB;AnhY`s1*?uK_l&ay0M4O`w=$)hM7Uk?SDxrsBswbfW%62!RUkei}mEe0@-BfA?1aN`i_7JC99wdCB z$Ua6+c2uZ1B}+C?=079mSIIMzJEOvq!E3>2cGXXUJa~qJz`t|!hop@Vj=|O3u@HZ@ zpvAEtkZr+j#R+MYJ0CvcQd4(fo?uct?>X_E%hzVvSPGm~C&~s&2ZJy}?6F{{W{VOlUTSF%a>&9Nqk+en{veBfrpz<~lGl zL~7c-j6>}UU)-4Xx#}Mwc9_p3UxtN|c(W>e1SxzA#OgLs`;?bXMliyum)ZS9l8Na3 z7c~&1Do-^sGI1jcp0PmEp1zA#SM=;%b}(YevrYmDoIh%j?>=9n0J}$^YoI&Ldo%su zJf(Sw>GCLMlMaQKL&(ZbutcHi&BuXYfeP!38!*iy{0W}~5+SrBMK3gHZgF<8 zYr!={o=>5|DYD>5no&6+@1idGkdt-(Mv*5h(B1_?u=x*e41Os?QiPLNWKRD8DF?C} z>MvnS#Dls?jg~M<#c~VBZ{e8gCDeZ}RNPVFkwkVG79B?48IMCqDZK6mO_C3wO^yIB zHg)Nzg3%cl8)nALSz7lTtLh)}kM+TX{tVkdObTqiE1>1RE;@HHKNCQ!cD(7i9GBaK zsxdyngZB>wS47%PHr7m!Ha46IO0hc~2OKvIZ$gzfT=G*d?xrKR z^nXQgcl0wNd+XuUl#4g^IEkWxa*?)l2HYf!6B-klTtDhhKDYbs~8U@HQc2*iW`%A zG7K`yPXaj~-ZOW~C#dDbj|;FbE}VEdf%^m!11J}NP8xVS2sbmBu^Sv$L&Ah9`wx-S z@L2xgATM|Nh7qNHd=RghCWu#GxPc)w*X>x< z;=5doeILezNibILFW93x%#g1k2qXzYeS$mSF@1U>&mnnyhEZ97>R>|b4bV!5E2m+t z{zH@V$-*B}KfudvE*ZRtNouHz(vk2ANme;RXM<~~p#K1g62qJg*}uTHnyQxsoP`rO zQpE`=$3kJSP9Fh1sw{O7(9lh*9{}FPKg|y6myGnEhftXuDh?q5jcnaS(;QSD!^@@N zk8+Ahk->TT9J7)v`5ptwnV*TFSNGA_OdGcbKpR!^3JL9&B|8RPhnFV8djlbVXpQSw zEug-`Acq9^H>2Hn;9mSkLR%%hP_+4xSQN{FzYg*`86aD+4}Sz*worHyLsYgMo3m+* zQz5O8PPKQRH24xb@_hvGeDEYvcO6H-*T`~EPDpP$R*CpRc6=9ABTsO}dQ3FC9H|I! zgp#exM{gstcseJf8Z<^GT$Q%1R@Uf5&87wtRV?7#pTGTp*riC)X~s-^2{-&ng6>av zl~_vn13Z(mZ$dxIx;&a}v`e?>Unvus7;D`&_A^2_plUdFQ2P+}dq+7Ps!OoRqyBa} z5}5Fjy>K#_RH(?9!0e%oZL~J<$JppjGfnJkN@Y2c_OW8eKd~{mlK}(oC@~M9sPIta zZZa+ujbtf8<1$f4Zr`Mv#w?0$o(AwNs~Dd^!qm4!M5s?Pn?d=S1d3kB21c)uAsiJ+ zO-;BOmP2lGFRBugp$AN^1iZQWC(>4dDTCZE?oZ8ojHI?o(UA%2I!@HUtxZ-IQMRah zvr)9!o&h+JEo1z^jm|028RbOqHrEF${V@48)47CPJ>Wy;UW9z>+=ZsZiz@em_sSr5 zxBTOw{Ls6cyF=sHsYR6GP=uRYsBQftmJ?F=LK<~ldJ4;raMcy!f$UZ^d?Qv~{uwp} z5TM^9cfA|>jST@N8IcbbUroOb2Us=84RAgP(}BvlphN8@Ju$g< z(2%~gVAn=86^!y9(8(yGIX>ZK7<^i3p{x2W8MYypf)Y{pN*hV8OQV0IwolP9E3%D` zT*`fiy62$R!X~4&IV<#=ILiDIwGkYY3;UZUWq(m+XleNj#~z{m#?9LW?mkQrNfu7y z%Ql*VmW~YLTn$E8BG<+vagq}Ly@!7{#j zb>)jFcyZKP2lRdf^d`GBIf=2O{6YM-(;a;KS$u^Z^ns0+zr6fAesol zsy1+b7T`!gnPG}Y$e7i;bkiI=Jq{QKpTIQi?Lx+W=1FC8I+fUlElSy+Aj3uH(Ro66 z;CKz;CQHviv!Pdm&BMxEm&+o8l2x33O#&4E0C*6WOct4bFkc4*tp5PR_RHH6?$7U` zVM|=G3T{aww+kaTbuF-ItTQlD9|Uy#8MHH$X}>aw*a=O;6x=_rByS2Ili#5)!I$lp zLZay6Mw)3b%ALa*en{@jQ{U*u^RDhmloe(640E>0LW=qZa1TxrHZX=+o(A_jNv_8^ zE6%$Urxl(BrgD_zwjsOQ+0bIK$gSAB`CSWTEg+hO8qRG?p&cxCC1tZ6OO`iJXRv65LeV;UjKvdDX(Gt3i>8ftw3ytnc{&MGv+Qr6 z;k!@BnxRmqsG7FvB-c`Br4RZWF!Gew@53aY z4x@Q`%cu4Xrwg)f$DN;Q0be^nU>RBz{2o7U+2|5#_J=KhCi) z&$yP4b`YYTKMd$1I?9>5?;!{xOiwp@|dcy>)t z;|5%xoE%(88Yg@W-A|`+vKpYDD}r3WRlG#7JG~ zutHPhORJ<0?*j|K$fi3NEi|Z@HYZ62LpW8#=%XZYIchK=Qz(>lN@*(*2^-A1G(irg zUV4rELlB`$ujVxa`uH8Tx^vi-MuYyN1;xnDZ%(@mswTcigpR|w=z?n@J1dah_FQn? z1oqM zeGFNmHe=P{MU<^89A7~~Vn+6fr{C5jFO!jI>8*u`fwau0p&b+8UP0)JCGe7Oon~4= z_xvt{G-a{(fv743q&F2zd?K=s!JR=Lvf?vPqilPVx76}hC7qH_HW|Wku#8By{{Vtm z)I2-_>PJ~a%Tt*%fMbXD6A50#2~ks_F=Bl`0luV?mUu44pOO%}Wx;{%@sBf6@-Csf zuN}IQVck?@Nm&`GmYI1hB#wiC&}q4AL*GGU{md87;F?>JTZY9fWJHZV?*+YC57?Z; zLoUmMaRj%OAK?eBXJ{=VZjF>ChqGe>q;N%z@FYoUnjOD1IIZu(5dzJ5$wll&h~&(Y z8yg35Nuh5d9>|P~*wEU*`%y9JHZs~5K2v&I8rn%b2M2}NwiDl`ikfRu)`hF^Jk_12 zvr+;?roKj|JLFsGN^ash(#78-rzKS(@3Y_kxnqzL+6|)^fEe9Ee#B@w~MQm z+hlG<#KY>s{SZ>zCVX}iFTlQo@8$T8Pe8=9@;VJ&IBgDHicb(@@E7QJi*JCXIlU6t zig!G+6Bq6%Lri=zt)k0g`oxM3Ny11de4D})S7@{y6BPCIP75C;3SF&{0v{s)8pCej ziqILB$=|q^sD-f!iZMKm$)H7b7B;iWt-iVzQbW1{b`5y^u$C5iNH>?+4or^3t_#Jwe2~ao5!D+_u zEixFIFMF7~N$kNfDTk_WOZ^k_68I_Em`2+1eH9Jn-B@X6SdJ~gTW(a*LM~K5*C&Z4 z%Z%6kD?Phz=-`QDWcqHNbRu%ai;~$~YoLoE)JtK@W+9@4_GX{D7PKihdnPp_?XmWx zwAGAkQfV!XpOSrqA*Ov=C9BBzDcr+BQh0? zl8#@H6&Ny$LgY@$s-EZA1q+(b@-UfymM%aRhWA{VV7Eh$v=-goQfIml(mk?hRL-_< z=w}P~b`%7y+}PjrR8%)OLDl0B^fVqT5A2DfPm-Kf(AFl*UK0v>9V+_h zEhl^s_!2C#O6#E`io|n7tmTXN77jdtdxBdu!XCZS_zkkwC%YjRqYV0q(aI8>Fc~v# z2Bo(aP~U0kO25$45Uf_HZ<6$!)~A7ZuYVMWcLcnOLZg4gVUfiPPp7a@Q&E)yH%Unk z4M)eMMsRy@+NT;~?}C{UR|${nmFd8Qnqo-mq2^e^YEBra+=sS;*{MuWD{r9uf>cA7 zE?!9TGp7teM9PW&;Dp8s zuPn_kv<}9}_Sq>~GOgbt#CL(C^bIO#G-oLCe8dPA?UTwqELehga2MO9K17>Q7=$&} zH4l-%K~V37Li9kDt_JWqTPmI8PAHu~gxm!cOyG4C_9Z_+=sbx;5v~j5bK=?1t!@Z} z4&SA^i@ija=>b93dZ~Cw$O}W%$c28_xvhovo8(*;9GTfnx zWvdS5{_MD_mw5ZO=XVpj+5D~Iq{m#k1v z?Pc@?8?wGanrnnzHj?<1LnYTjWN>`H?866UFtgE-ivi>%;RC0DV38wPN06fP5wYZQ z1oBubpY-jj$Yl~wz{uQB*r|!8sBAUwSErC;OZ1a0bQ**%f}bZmo=%_!bw{F>0ffmL ziUlEBVmLpn*jqYC5!ob4`6GN3q2yyfK+{n4T%ET6rh_bp5WB|pHiLxg6G+BZ}e5-#GCDLgas zW{<%#bUn^_CP(?9mrFu<>**4Saop|cjNtYTbRzL&ybk(`rN^QzoDy1OF=0k7%@VfY z7Tm;eaoxwzS{)G~Cz19QoVmcGw*ZL0BTWAQ;zW*L?B*h#;5Fh2LT0YYFM*{3vVwxv zg7?H}4*5c~(BzxAAE(Ht&IqMv%fMg!eTXv9L*`w|_%M-=I(87M|%6 zejnJE{jDD+@J+IWK+c@qegxk~4X6?0l-%Fw*LR6OMdIofCeW$j8SU~Ujk@>~6--U# z(eaV1e>Db#-rnIEu@=mA7B$T<6#0aKu@()1DM?-d4xW+JAq{Ny?mkuAP6imFjPUL& zW(46y1p5h7f~O>k6=hm@G850Fv2svwXoU{XH$nMb(0TocpQ(hA3qk@pfz z85IFteFP~jh}R{#QS%X-;|_yb;EHeqBTi2%Ll?RG2yp0uEWwh0f+Rl)5?w|`O{CPO z{{WqcCUhfn{ve!xCPda<648S8t4fGc9@aarCCR3j6q3m(?*$R;hQC%SH^Ee$Vi-e_ zV$gNTbsJR3$JlQf$onBeGdJ&rRB)Ad)keo5^n&bS5(CZ9w>@xIpnoA4e~LR5o@Gl( zeu$eF$b$Z#V3Xob`{WkN@I96;P`mIvlqdAW@F#|Q8h9pM1gIwiJ#1G7$!MIo6&&P< zhB+yl5_TJbzNeCzH7&x~mZ3)0=t~p^@UV>Yp`!N{u{}M^n=rjTI*X*j<#`T5MarLq z7~E1iody;OYe5viN#;SQvklLqVr)?()0ry9#I78C5ps-t*!x{J}(@q~V87RiB zNr}zlP{zF4Sd$OpPKnajB~Zi&Xq01#*y>r2$p!T3C%SklTS)$5z?Rj!O8^bdxE=@F??> zG)~46BvN}sanoa34tW*}1i1%^n=O5k6XQcW*b?euGE$3Nc{Vjq6XZH$e0pJnqS&_$ zh|u{&l5DZAr0PQ8s*SbGo@C*}B6KAC$NH!67KdD-XCBaO>v_auxzzDD6?q6|uXK18*YGdyU85JeecX^2@1J@wFZ z>8uT77D71|k-_*sEPCNWEt1(XWC_k;%Ni+FH2MN9UnstUU-E-PjHNz9w$VTOA4*kx z!pW_T0%6zx00H|JSY+ErXA)#f>O+Z1lw`}|Ar7t4endHB{0pG&K1eM-43=$`l!hrw z%7!-zn~$P$u?d6sZ$J{!!0yS50(lhEMurG$ZU@njrs%{0wDU|=N08AV$4!nW#7&Zu zdnA{kjg*^vITi6Q(E+rwYre)y9*|6^C6U8WZbMc}9|WO8*Q4Z=w8-E;Q`8uvhjJ7A zjWjj;q<^GA7YFVh1YhFDN49^Vgr*z+0I~gef+7)nhyED;0hw{Dbe@dTz39{DNuk>* z6L8R(E<_4q(U_YCr_haFM!Br0kK9BAQ5y}U+i9_yamK5$xp=UP8y=%nl`=Ax@!h%< zzr7iby-Zxq=@a~sPpgbI+lDe2i61XP5-2&ekFf7&!2QT$t%BrqAPYqeazCLeyslZ; zqE^YB-SW-8iEpolOllS&kh;VThQI8Bw3d`FK7>*U?1rAbekCJ zX=qAff<;h2LNLb7Ec#OEz6Blgp)0V(wDMqaMd;q6C|k(gY)=B`fqjbA2;VSfQ~vszCkm2_h;~B`iJ%{<3ByL!Cj=r@6&o0L& zPa~>-ft&CMP5xNSi^$Y}zJmPN$MzS<_Rh!}cY!Mxvlc@gm+Y+W1#4Gy&&r4scDw}z zGr)+Jgsz6xw_O|v_D2*>-o z0NL(6$%AWuC5lz;WP)s@`wWOfsAEzwCsK3BX8w%K0x&q87^hK2^*-b5W66aunVyJA z+?(N)v$%!Oz=Z-AGvruMR2RJzAL$+N7ovprT9ymH1H@@(8aegNPjps0sD#(cB0kXr zMP(WA$dyL+nU3V~X**A%?_)ABI;4byJ&Od1b3W2O!Y}B!5!`U>$ipYIjNy;Ni7Yp! z6>}1C;E5hFfaa^V#( zQPZmzRG-bY1N>)Uk8!JUr_kCZ9GgEz9=A;P&Hgp8De^f?>}@^yA3mDrw1MeBRn z7{FOTL??qT42zNyaF993pCuoY`%xl7Njx9RP>Gj8-n|GW8hi-~`S~er$a$p1q&?X9 z9s`#y1}$3&@-(~Xa9J^R6CpQS zDh1`7n4SmB-^i|^revcXf;*3xhq%SpHvED?H7nY3H!L?fh`em zMz|q3P}g!xgK9Dd@1Ba2N3NODCX zZSJCZMo_MG)tW)zM+fDwCzc>>4`1|W3>uV?p)n0_4{_ZIgcI^31i-L)7F3#2#g8Q9 zZIHcN*tqLsc|4~08vT?fM=#kH7n zERennr^z?2)X59{7y1h$wFjXaL!sKo^N6ZuPNk-<#-PYQBFrzabF_@yk-{Hw5Fp?= zFzHwnyS=xOEjtZu!&}^=Jy}v+@nr=W;u%mNmQ9FqaA%NFfW(WATW8uNaP#rnNYM_E zcd7g6bsO@#bM!#QivA>?NEZlLb^3+5pC+^{v4TvL6_+tiAM?z!A-b`($ z$l)MK>Yp>dMjo~&q)pnu7Pr8s}hsz={C}I39X!^)gTINT>f*bi)CVYk$0_r{bA1W&V@ebXrb@0D#p;pQDlsOo@3Jvgqn&IYc&Oq%S~aSdKscM zx+;xnaU=cg3E2sIN|Iv6>13v;S?vOdGYCUAOX95{QH9P6@3|>#v9=gaI#80@5}rp2 zG~cV$>F+17ndSORm#{Mo@H2iYI!9+dld#42V1G~o$8UgtQnrWjK{LESYfpC*Y0qik zV`tMFRauw8Rice|AZ%*zPace!cP7TmISVE4?iv(LM&a&L!1F?JcOzx8P6Q>`FOwzQ zMT*7E7}?^JA`D<#Ce>d-a{Z2V9sLrU_8%i9wD#E0nw;_^Cju84mY)N%o_+cO-8~JG z%W07CatchvEj$I z5Ph7(xm9G;UZ-Zg5Z_T6hqPXE^ehzOS50jRaQu#j&K7#@@F2n}{sW;quhq*gd8ICM zw9wd?r0v_pp$z8IWPFc;)MO(sucJ+kwdj#`5@#b*GM?iVNS!>;ywc-G+@}hM3)2Dw{{V=Fazg@o4}2d8YmwCWKbX7F@z73OnnfI1 zI;{}{L?TfZ8a!nC4ffd3lbF}hC&`ES7^d%7MpIA;NYYi2$NWa4gGZ#;`ncj_$s{o# zNLv2Eb7w}-+t0z3bFK+;Hl3GW$jedL3561_&OXSWW1E^w*uj=cSYU``m8f=wUB@t% z-!wL#+8$Fd&z5)NM)%M=uO=*!Rr4dV-Ipy9`WZ<>{{VJDYZ;Bp2@3vX83S17ycjxiOO`yV78DPm-sE=#{Z(!fP?SCQl;kr{q%U1hvru zayKE2f6gM)ZYZ7iEbpMwH9mxWqb8k5<)DGM8H=XoeWqtUlCJZa+R^$2pG$$`L@)f{q8Agq}qE`IWh z?3Vz{FYY$lT3@GGvAd=uN_#^*;9QD{WDIgEIU5h`m1@gx(C~%#kupDEVb5PiI*Je{ zzw(t6m?M;COrU)l8Xy6`70 zW+h;|khqDJejlP8NfMM5g6d{$$<7#odB=c}zELa^jw{j_Na)LA{RjtyZ90TL8X&tK zB1aqz`WWkhG2;vmBuyCuI}bjVha;LA9w)6Fk{}OkKLFR{ ze^H@=UsS)+r>um;>7b;K5`I)Y7@&t|phk}$=y9iQ3A00igA=95%gEJ3GImK(pb2aH z1V=1iKB7e(2y_A6jGZBX$J8g_2Q~iy(ga^(3F5@1bx5u(ix>O{5Zfc38ZdVQZ&l%`limgu6$^DlAE-pR%m{+;kKtPL#Vf+d$ z*qeihq}Ua5mrssKaYAaIg}{zMztOX3(8u7F4!LzwD?fZkxk2ELtkL*3mDIjG4%j*b z)I9ajV%sOlY^Ri%#!U1c?rZcuC$kS1#3_|8x1ZRf`>7=*_m|*#owR<>*?|W~!y^Ei zo8X6Kq zy(<~SWqGGT%yceSST-F;^Prz!NzVoayPOI)=qD%0+IzeqE0cO4_dAxh=x4DdCO8)v zc@nAY>OpKhiP}4(vT{UNx(kp>B<;zD0rWDWginBI@#zoIG5rues~3>#(eTKz%MJV= z&OFKxco!LKmqJKlTP*9dJUgM5S85s6*~Y(MXb$K<%MpiZ_(24+uVW0mB5_;G5cnqH zjICHxbJV8Ii$uALyA3w5?K3`*K+yVU@JIF}R;l+IPkM%}M7wD6H8^Hl!y@WTxByjY zMGG&O6r+=G=2NWx$NLxhB&mp$5dBVymLo(pRq`={Jd!uwBkwj(`U$9(Y=T>@$h|2T zlLN^pnCejsmN(ADD_GSQXGXMVNNM~+#LK! zHdy({^24G1g)V1jfl0KJeZL}qBlRx05ltH-eh1ir3Q`-jENRZm*QTYeqjgKMBc;hH ze#M+Y6qRHzBFc{X6L}s)>A@g_r;?FE>SRcfRQ~*Z6W{>}L5&!${!Szvaz$JS*~#>w z$aMl_xd3Xne=8VWis}TqH$ts#p*~zyuy{92Nj`=0Efr3T9nu(%60ix@(L@AFOKIJi z6_63Lw6xj_KRxha^f%W8q zz+%kFzNZqk--2tCL)zg`zj%F{q7C5r4u_GMIKl^0^EeMa7a3U471cJ(4PtZUNF4>x zOQ)UHa7`^#oK5mFKh18UQp)_p`bO&8nzP$wBC;G|@Yiv{qzFTt39#}70hev0HT;Yh zlA+3J?J~~iccJwA3rs$_AAq{W%+8_h-UdaSjRkgXAEmg}eq?Q5F@_?$SARkyOFB6k zjkCV+H~WmS@+7_sC^?12NfqF@)G7Ffzv30V0(HkBQ%7RB|gjy(H!$pO>Rk8^C$W`=ouX$ zR~61ahgqHr~z1Ikq`7;{1QfhG3+;n|L`yVHnb`15)+EiL^Vs-WgsZ3bGs(niNxlmJHXZ ziyp0DT@90xW}4_il2_9~f2}vPY(xX)qM2%lXRzKtQXe5Gb}pczceXDeJZ(?lKFy#P zX0*iFBFvElDV&m;9Idgs$vp%nuac6GT7ywdacDv#&!s59p9S}Zv_)`Mp%#UWM14dg zu!;6Yf3#1q*x1=|Fee%|tolUJ;FCSX&}~?!_GXKkP^?9k#kMdmfqF!fB&V+?I_N_N zs7Sm65ZB~O#Ji+q-*|txAu6C4r2UKsaD~8K{UnoeA93yUE&;csPl5%=_zpy9e`0Qe zCxWImY8<1CK%|uR*phO@MH+u(vffW^5MGr?N3j#EDxQQnVU~r~Cr{!L5{}?-Ps|xA zdEt_ip-ERB$5z)I3>sQoBc_L;J0>UKP?O|u9fn5@L($OwMDQgEtO*kZG{__qCz5g{ zQqyOCE~!%jp(b4iWTgh90_|Ft1*O!P(BW7%vE45Rz|UjJ5bk@Apv00{Pq>RnN&Ah$ zfyqWChjTgf)fQlEqk&{QA{5DuGTCfwsKi9fsy98VF7 z-031rds!AA0&c6iFaeDBM3xTniR;pxHId3#I3W?xwuGYKY4jW;!$hx^O!x|T`8qX+ z5JY@GfuS~8dMkivPVpx&Ce|zjh8Dxil-d}HCPW?_2|Xeo-5Bx4{{V*_#4`$8Swi6N zHXHQ2CH@C-2^LaEQ1$eYh`Nnj$cTVZ*q#uZlc#>Kqv|EtIgzG8xFbxmv^Wj>6J~9S zv}93Cy)qN7y~#7=KdeEhPQ@r6m7$!-?2>&qg_98?^y`t3StPxLk%PGms+3!a!99(H z-VwO_p_uv&`>=jMl{5V)f3L=u-A4TTNS#dmL?->l7Q7&aR{=)>+I|Nm@2d$Z2@w2& zEj9YHvP>ZsiCTgV+n8z0REnT{#;YOlFXZ_UJ|r10SqIM0Lw3 zw7QpDyGr5t6(=*wvicjEixVfwuEKX1uEm5zU~O<4Bo*>v^yfsjCdp4I=ah{S_(Ol} z7f^Qe7extQa$Zj7AF;ngzpcoS#y-+BvvnAumON1I_bVY)_E~NI1k)tf?DU^ZWMos< zf^^Hcaw0&5kd8{z7?o^o`;o~ex)~9x#5o3L@$2_A3JOO3f;|TGniGNZ#)U=}DSit| zUd4mQrH(hSJkRt846K+Z3 zx(mQJ;(Qmi-iUmHlkND&@kT(J@s=@@$qxfqqdB0Lc9O_KYU6MrK|cUL?1|m<^xr`e zrDP9P)M|s}`ojyq3|rXrU<+ z?4`q@BI7|`uBG>sqq@{v8JEEvP~A&IOOWG$NW6*W&W1TMM#mfvWBz5bP_@)pY|9u7 zo9M*%8)7Jt@(gC345b-DVqU`Mp~q2>X||B>DKX6@iXAH!Y)Tp;oB6^jDj_@>`7k%~ zHcz*q29X7{=fROAFgkn&K-N$<;7YfVRviIo zV$qTn?0b8S{{Yi@I~K@Dtt$Ks%fBc{@Z^y`2}Srg5naS3!2@0mh$SKhk3v+s@^!Yy zh!DJaIrkk%ir6+xRU^+NaAeXIx-ppwAMiPXqh18|DPinWAZ`+Vgr~YBJ`EnjDvRzp z85N!TKNIf%#tX4w4x97YHs+Y~nPD3<=R<{@&vG`RoNCThtye6Yk%x`*l68=W}uTsD{Uh)Htk%9vKfd2dX3klt;~%3j|gig`HW{ zJHz@&w^Vs&@kjZw{gV<=%&+>-`qgEttaI_0^QK|pf0|Bg8;%H+BJ(~;wsDNmANCA= zm4BtlcdF!6`B~`4JT|CyV7{|?D+42I)g4w)3U*}%E+Bmhx}!#O!{mIRa-{Df&lab1 zz*3DaZGW5j`3k2j^)ssIQ@7lr%OmBakWU=_h3-bAC;#_jp!Q^UHWadOzW%RB`nhlY z7v3I?%*pUv$7EZPTk)=sjpDj7xUHmnW{_vUZ<^2`J{ZJG-f;1nv7=pWhGa+9fxS?r zR8dlXc>|GIhV52YsC60|`z>vQgJ58hM_bRcr-p(mId@dUt- z+zNHSB1IEd=`eSJ%3E()WiA6z=E(irsP0G$ZQjKq-|vH}OUEO5o0%sEH?*!|?y&|M zgDyVJ?11-8NU$b0Z`!v$7k`qD-A4UQ+RQAi)Lomed79rblT2*s?(U4#fB{a4s*qWf zu)oLZ`}IFvf-QP!Ew;rdT8jDfpXuBKiF{Ka=yw&NVhrGs!cxsWI;E&6o&n1Y_+ed# z|A7f3-+&tGcXFYnWNKPlm~2Vhi3^PW!c(ZyAcLKPbMm-bP8* zat==L33LV#SB{<^d9~@^)(ThdUj?E-UvB9ig2%*uZd^DO*lI_(QZ*Z<;J_YdZK^qD zRB>OBeznw*;d0P!{~#aEKZSV48tYzkEvP6#TEUUDu%QD*k{$Gl0%?fKB5X-1Vr1qp zsj?k%GBUSe3A`88W(_VcjD&#$KxkMNO$4qx?glMMgl+LrAN=nah8|#7%h%#&r*xg| z@TnB!(=ai(v84jQ7jgTk+r`2K?WYffsn#1z)FocrzJc8brnw|f2DZPb{So#E+>3}} z{3mx_he?ziH+1-vQ7^GDd9PF!suW0X9!>{&H01HnS0Xb=#YoY`oXfNAafPT5pXh$L zoYY;QRx4MhgG;I%^XzdXmZt4qm5nnzdssX(d+P?Ne#^~!%ebS&TZRVP2f;O$~Qt#YoGN&rBPA7IYYtf1s+Lq_U-f`liqo zFJfr2oW8MuI;A$DP(1d}XDvibnx}pi!#g#-S@#;H0)~Dz^hz;wp!v}+*yoUhN?|AxmF3854E`D~)usfMaHcZn&f%z=% z6>$hk_=jG9!__~velGfl)}09lD0g|&Lg-*an5fb{E@@5)2aZlvVK2e#ix?FTi|Bu< zja$)X2=;eEATSGfbYvRW!LqaUkya@mLLoAoOI3)CPSu^v!WW|6)o}? zS$hjPzQ-^7HQ0%H+UIp|l2S|onbg_hvooiaw?qQAK>zIBo)*tt?~Q#P{I-)ebG5B0 z;Y9uf_Gi=FNcjxwb16;om%bfrq(0xTh$4^pC~dqaWAIgAEc_Wfp9B2U42|HRb4ww^ zhSwAcL2j;pl>AoOdI27HC9q7veGUn5k@}T~L9+LSMg1aS$!vDjETkHDL}db=56crw z6fi}-(mQA6Wbbe)I90&V@WBa&@o$J%nfxYlLh_bAq`4J+0$r9^?ImyjAqp**M>9+M z(}!LAkk{%U8tB%Cu_-o}156j7z2ZEXZ4ucD+ySRI&gi1aNVkw`bD@kPa19be;g=#vZZG?#tJ ztHe>AaZ};Lhdp7c#DW*s^>PhgkeBNuXCLNG;?-e2OIEJ&)+5o9>T-H)#|L1Ud_i8F zrhgSdNf;F+uk%AKo~c&A>2v{@tb?2bW&`_fyH=fI*e( zmr~tokOqSmn)K$PfT=*YMGnkhLCh@7$ zJ`!(y+uoH|Meh~4KBfQI{7+oEUtom*jcUc|8*8?yMYcEi+fX0zrdcPZ#qk25DJyioZ@up9SoSSE3#+Fl0SFpK1;W)`P*S3Oj7 z$hC(AV7`GKJomNUxgJtyO9@MdIYj(Ydt$*8oL}ZI)lk%myEzeF1lb^?d=<)s=&~pW z`vKt%=6g+bf#^+Tn<3!6_?xKHMIp@=YC3E?>@#y@_exd2Zt9>`!yY-mi1#dcJKR~_ zza&%qan_RP8o7bVU{{LBOj=N3hM);Ou2N$d<{Y{`bOy zEfa!?CoW`|L;T=QxlV1vD_@%{52UUqI9ut@4fypX3+oou>1OA?{P+ueQK{e#boH|M z&5vmsxzu|jYMW=K{}wnYbc`cXvWflm`oYa{UA8Mj;M{jX$8z%zfHk79%~k#!2Wi2V zpu$@f-{44IqR*>E3$R7w3t!pKBccPC4=%G+x1p-`KW_tEu(S*gW>CZ62%#bJWyj4k zHHY`_^c}|8C=W%BEnv7TpR{<=4jv~ob<+c9(F6#H+w$zuXIr$Jid>i z_dZpG+@0i*lt0+kv4^(vy@X}uykAH{df%bNmpDJr2>7eVF3mOA$RU*wm$rgJgq5!x@Ijy!iTUbYGz_Te-?K_wY@g)WhaiH8sTSY4}sUOZQv2q%6W2$ z_FoQ;p!fV}S_|Rxu(t0DrZ&rDV7UStxTQwA6*Kj`^QCXnej}KQZBkmHHmMfHWE?Tq z|DPn6*WK1+s@m(Z2HSdkkAElAWlI$HUJN)Q?JDmc@yA^kptv*;Jhx_hGP(lGW%t<< zGHXBunHii*51%;iRZB)L?0iZ;m4f6=r~cAfD7d)iKJee@V-7-d#|XOTs9+F=y@a~8 zI$!y~lmoXr^^kXv;QpY1K|;5kJ1j=#TLF7bCI1x4u1Wl@2!BurIP#=bxbJ{v+`T?I ztH>9_9Qu5U~vUQyq^I}vK>&EfqAjsSZ2t%zaVf9s_cP* zK~%G2R9hpn)xaPa2S`o96M4C&%O^h)jWdC|jn6`8`u7F@O&32_aKBP7OI1TG)ev`_ z#ZI={G3xDrI0FnvhT=`hps1K;tNkggHx&4OFOTBP4;fcaHB6Jm?c2wls#z{#Z|IaK zZ-95^I}yv3b7INo?@2K~J_>mY4=>b{)(uYM3n`{Hfg0YnWLrie0y96+sus`WJvl38 zjy9>{t~sU1t^7|%wKh8Qx_BlL%ffjNoEU_)WsN%xil@lH0@>c&|p+Jx^w3pwq#DiCg`Aj{fSB9=0h4`KX-A4fsVI`A|D^t)txUCc7wfsELLPV_w0l2O$`9d>?_v{n? zMKN`I6zB#X1r1tL-v6pNA~k0yfqi({qxkZ_pP^@!k~S+u83gI>v1ZYJ(_M$x`6?}Z zPjnE*#-}WcG0MtMs!VlY`S9+*%lF|fO@+ImaU@f7CGVC09lK1~hTB+K3V#bvX>Y;Q zw(CiWl#(zO`D^_055WC*TChEe$=7Ffm_U)brIiFFBc=x)n4+}aQ(~rk()~;R3X!28 z%9c-hv|a8iJEMd#$zwR@l%1E_2d5e`mc7Lomm4RH8+I=_k)U_Yd@i%X>lDK}N=MD< zjK4xUsAl-(j6ZcR!l+rToRj%iYp_wr&FV#8x^R?CL}%Kg!E>I4$|^5dm!H+_D5pUE zszO1(H&leWeVB|@w+Vx#y$E4AZ7U3pl#$`+R!k$&GAiNaRiAYTeK^q;D zQfc5dZQ^g}q{8o*?xl{mBWw9tH5ptBQ?y-2$33&=*E7Pl+<8Z_vggID8wPGu#8b+p zaDfw;U(W4m_YMm8dBUko>sxffRplI4&C3kU(zgu1kWLn6mYaq2>1?6<^FNC!rIS(k z(?X`cvH|vdr}MUVeLjqozb0BIQj{9wt#|f-&6d=!t=a;7-^*7wtV8*x8H-YCcV0eg zk+3-VzPye6&iCBV)G{D8owH`!MCFvrmLoRwEfpY-o61Y2eyj@BYYjc#0%S_(DN`5Q zo$t#2TxYHdFeOT5nf=rQSJ&)tuQNDgWs7?aJv>A@*k-t3D2tY(7*anLGjC{x{&y4u zhKO#bv_wrsa!9k>8{`OBBHxdz@gQKJgBl6$SW68p%ZuG{l$jW?q|i6JR96rzx0a8B zA72S~A+{)rhLrpuk&qywLKS|(@7c(3{-b%%%_0!!LoYJiYXX_oLiTi#bP z{(7HyiIzq3LePGoTrtNDW$#c|EY0)3V{g&@b z2b!9|@>n_-X2njNJsIwl=ejS-+85a??Cg;fkQnfB6`A^;cd{s|9pqE}#X`AYqma)> zw#a~tDwLTvIi(ReW+=YeDseoh1bf?}+G?M+xm)$AU?FDTpqp{KjGa|;vrcCQ_iE4TS~dP zbt^=Qgi}@;bo{_bJ8H4NkncC!{Z>`0H$o>5_8~Az=-yJTX@`3|Mz!3I4$h`m!7d_lVLeKu?s{g7S{f_pW+Z~Pd?<2g}#I(PJUUN9nQqH#6;@6n(9_Zgrc z9~QIcUQo>#ivbH%0E8VrapEkz<>6fjDmShbK4&g4x<iBFH3W@r4K1{IC8D0^y#;h+!FJdWyvquyLJ4Q=3#9b#>xUxZK+jq--r9O+) zEXrjjXN*0B5Fz1BWoK2wj1AEnoIuwkl)TJ^|Sd;zAAryiYcXo4Xs zb3mpLH7UvDVO6uSHWNk`%+OYr+}=_~a*-S)E01Nl1?N8EJI9c*q(2?Jt32d^i~Gox zX2-S#+4uJ)x0@;eC3SG9Xzw$eK#x+?gX$tr;8eyhT@=hc2xHz=LVIa`Vq75ci!|XU zRS9HyU^YSk;|ww|inftl_;<`G$P{VC?Pq6zN7-&rQ)9 zCyr1jSizxBW!FaN%tUebHV*qMd6bjD^~;ESRd4xX8g3$Q{lhNeP!ZiVZK(M`uv)AZ zaZB4s-6J}=YFk%A+T7MPVh85qU&$sRZ#0hc(;(CjHl_b}*cJ~8fKw0yhy^PczNsn#L7u9rxtJMio zCjhuRrA-)RMRV$&X24&-!wy8E>8be8a6H*oV5RppZN%vZH!;cSoirrUzOb-ya*U+Z z2*%H7$_yJVv!)d~;}B|qn>>9e75YVhw@Z?0uX(&==!lOj1-q&_&{pjF5b{kInHs- zgo|y4awR0>|HD8YG<#eV?0DQ@|23)-SzXt=zglCc*{wr>t*YVm0p9M1 zG_C6Ll^E*hNU!2fXsVBnAVk;YE3$Vbbp-FOu)eDi=C#d9Yh}?t+2X;`7nNx-iwLa-uAx2Y=q4 zo6#H>a-A?&w4Ac~w3sH*0Lu+;R;knLQ10-(SMjdCtm+OtL`%#mJd7D_6y*nNP%_vC z$aNlA9{VNLQq8*k%gl-r{?bYy`DBU5LTy~_I4eigHflBh`nE{+d*_)8yGZ%oaY~!0 zrk0ZD7Gl>u9b$L?0B{;8qNZ{B@IHAU|Lw|$%W;Kw8{tl2o{rkKfJ{eMe~sjeJ#d(>PoTdhH|~K8F&{CX5_l!0x0Y#XvJ)0oUx z^V|o%zUcM3bQ-{uNoJlS8Y9*SQ$di9N%rdz-A#n00LwfQSFDaK@fwkhC+^9=DXbvs zMcW3rs%rNT8asX|f29W9*gDYF9I*6qR$z`GWS{}*66Q>yP@do}&=B%^2g-9%1*mPa zWOqxyQB;L6DTTS8T~WV6p+(%DkoCY%m%esx`#~DF0vk?OXai_pF_&jHRQ{oq_8~ks zCm&tz4+6V9O3GH#dRh3LBsl-9f7tcv4lolkU+GVTG79uk63@cANZh&Qc1{;gQq?CY_ghJy*?IGOw9hteb{0H*F!mL>R7Vw_)d9*uw7 z|G-4~ZMAOCp_G`JZ<^j=aC=eG2=b%O2gZ3kwn?OkmSNA1jKsGG|T7$yJ(pli0eZO?I9gMXA{o~%~*Ssx#+t6$Uq3f`fylp%KJ z59zyUlxEFrOmUUrX#8(Eh1!u_aMS`h*2-1(v= zPCWk@KnmC_CiYiO1Tg%Dn=h`4sYfADx=XJSXg(p=@~P zi_7d;5;Vp;qQnGSmm~G%1L>)0!?y_$mumIYBI8FV{;0h1kmCZUMnAyVTVtZPqQMuR`pg2`=q7PQG!)n zp>GaBn*q`QxV|({bxJ(^{pEWn;+iwJ9S1iKx$?6_r`Wj}gL8@f+vwWdx;Gd)YmUcu zyXng5R_DPGQ^@?5zoD~PnonXlu`{szJMDP7?zSiAzJj+J8d+RZe*`N1$zSu?7YtH? zDMT^u?b&A4WcRGBuhtB?zfs^rNPcEI{gf@@j zwXZRwmhEuVOD&FNS0?|dUG+|j;nQBUcq-|(V)T#6jQ+s0Wy}#_CsG}!KL76+GdB^9 zy%T*^Qp$?#pDA_IHJ4~G;1_zNdw-6(szWwV3w=!dzM1j{^SMi9vMP)C7`C2ktW&5} z4dKJCUEYwHFSDQ*Fmz=uaVP0PT5?(6J{4&Cq%}x&6b{gn&iJt}*v>zs5oN-|KkXqw^dOfO$3ax=q?h z|J-kfq|$K%ky_oVf)%Q|x-6fk>D7}m@_hiWdhdCm-PcntA1Z5}3eexizz6mPA@Bz)9#RS|3;pb?Tk2^iKWt!rX%Q?BECO@}*PPJc2}oJ=Z#}C5 zp^WnR07%>CQq{~7fA4e|B+5;uZF@mhDrDihM1ctP;DNk>%if|HwwPdm=JWJj8PfT%S6 zNODZ#9beOsN(Vv{mq+CJk11RtD_gEdF#WRWSq=4 zG7uykP>@J1wL^aJl1SEnBJ<=mkVq-|8JDW5w#+#S#|+T9#kxyL54-7Cblvl=TCrUG zSx5h<3~UJh@d!|mQ=Xs7P670E7X}FF(fRPu72Kywr($zXT74*gf&l=8edHJrv&*}x_CFc}n>>5m# zLEY;yl+cRj$%+?r-|YYB9u@YO3<_C^exJm5Ix{5Lsb74}B{R7Ex^(i`msTfQ#1eN`Tf3}7;I;nUuvw*nZO9-$_x_VCWkA2nYwy@D#)%)sfN~1zC zMKX}4*~WPnEdHGsJNGYsYUW)ee_Y6&e*nQ)P20l)2pmeh>ZK{ zfc7VC56nf;o71MSq}g%+`@RI^)pAR!qJ7@_RjeqJ+Cy{8_sAB^B8FEF?K+0l-W233 zgmtS38PXeVWFFhc;XQbpP)X?s7>!5lrxX?co8Z=zt`D{|y<3rDTvw;Ul^i#HDpvtX zds;C$QT<5}5$=rYh_t4JihSffzB`!pRV+?XyD39Oc;%?CI{hg56+ZT0R-4@Wr~ND{ z0mJfs#KY`EeP%xq67(`>yY0jTaeJ}yrvNU0$*lw=9yTk@sxzi2r5Zg3y@-tr4|eG- zbJK)*rbx!xEow0A8uS-tPsJ~cSQF6@U-#2yAz`>|^f|9W!1La57~Ds!VP>W9;uY^& z0tMG?%8sr)#1QKk;VQy1VwAQIG_jku|5-&^-4GNQQX>PQ=Gsltb48)RSBc#DhAxlh zbk+VF`&_69AwSEwpvB%KflQsaJ9QM=mvYm=KIdXl1afk_dA=rFLc`Y3{^EHoY((dH z1ZO%wr*3j{&1m^i${eoDJt6frkpIZlJgSGz8yW=;{L>eNQJ+qG3F`tajr}&z@fUJ z&6-j3&A-L|n|`4x?ec)m8%l^b3hV0sfW&zEpHs2y1!avtqIZT~v2 zL6{FqfnCfMvhJz5by6SZJ1NydtJ{c_WK4E4E@jwHG13UjoY0#8_F$a>cbI@98D#$m zNG()W)k?r^A1oI_HCS#8qD&1lgN|jm{T5oCt3DJ{z~-J9S}1fA$HF#6zHb>-hqFuI z{|%J)bksyVDU&!OAZ_7UYb6+2@Ayt{jc;zFfE+bK7T3!U7}!oNO1zvjP_5APEctO` zjR~2D)jG>#tSP-d_6BLcFFhqpg)bBgJ2O6Wat|}KKar#q4>U)|CtQTuS1#yciuId( zdP!V`>(u!9^0;dQubqlf$-eHQ}rZ_f_My^6Qyns}L&Rc#WXSKKWpRli!{ z_=C`4k1h1_L69(uGOhN(@yfMW`u?$we%hPPwsDjGlJ09!K#YTm2|RGGu%Wz|4ladeT#F{?3Fb_5!vT`g!g#8 z-yt_bBcpik+}4$*=#;yVMrWTV2oV2@UGu8(>+Z4Dy3!gmpXxzIvnNEs-~! zg!w}qA>S@9@+!DLy=g+U8N zgFF^$GnKzP+BNt=ri}h?p(A^43Dj5Xj&v@MwY`HwY_MmvyQg^DHJ{tC5npAKGvG%m z>y~A+ck1@^Ddv2Qg=Q*qcTMXw9?ELMD;q01rVD2Rd*(7_eP_HVWUW~%mpFchrn7QI zLk`958i6xjb&VZ1Bq#ow{|?E$Vic)(JCS=eu76rYdNiKR0?>g^XDB1SMkWzOORt!$ zS}v!R#OeqLoC9Wcb30|obW51caHsTf@UiZ$VK6-2OneeD;`CR%B|h#8+=C$rg}mTO zdp^x5sF*#e+LO+*o0sR&28yZ`iDLFiWNV)ObjwvfukS+kOx6-E_Up<}d}zs@_5c1I K<39Gk)&B#{$L0nA literal 0 HcmV?d00001 diff --git a/admin/DashboardController.php b/admin/DashboardController.php new file mode 100644 index 0000000..9692bd6 --- /dev/null +++ b/admin/DashboardController.php @@ -0,0 +1,590 @@ + 0, 'msgs' => 0, 'media' => 0, 'statuses' => 0]; + $logs = []; + $total = 0; + } + + $pages = $total > 0 ? (int)ceil($total / self::PER_PAGE) : 1; + self::render(compact('stats', 'logs', 'total', 'page', 'pages', 'filter', 'search', 'date', 'user')); + } + + // ─── GET /admin/live ──────────────────────────────────────────────────── + + public static function live(): void + { + SessionAuth::require(); + $user = SessionAuth::user(); + $userName = htmlspecialchars($user['name'] ?? 'Admin', ENT_QUOTES, 'UTF-8'); + + http_response_code(200); + header('Content-Type: text/html; charset=utf-8'); + echo << + + + + + Live — Palmas360 + + + +

+
+

Palmas360 Live Feed

+
+
+ ← Dashboard + 👤 {$userName} + Salir +
+
+
+ + Conectado — actualizando cada 3s + + 0 eventos +
+

Esperando eventos en tiempo real...

+ + + + + + +HTML; + exit; + } + + // ─── GET /admin/webhook/stream?after=N ─────────────────────────────────── + + public static function stream(): void + { + SessionAuth::require(); + $afterId = max(0, (int)($_GET['after'] ?? 0)); + $isInit = isset($_GET['init']); + + try { + if ($isInit) { + // En init devolvemos solo el último ID (sin datos) para anclar + $stmt = db()->query('SELECT id FROM webhook_logs ORDER BY id DESC LIMIT 1'); + $row = $stmt->fetch(); + $afterId = $row ? (int)$row['id'] : 0; + // Devolvemos array vacío — solo queremos anclar lastId en el cliente + header('Content-Type: application/json; charset=utf-8'); + echo json_encode([]); + exit; + } + + $stmt = db()->prepare(" + SELECT id, event_field, from_number, contact_name, + message_type, message_preview, received_at + FROM webhook_logs + WHERE id > ? + ORDER BY id ASC + LIMIT 50 + "); + $stmt->execute([$afterId]); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + } catch (\PDOException $e) { + header('Content-Type: application/json; charset=utf-8'); + echo '[]'; + exit; + } + + header('Content-Type: application/json; charset=utf-8'); + echo json_encode($rows, JSON_UNESCAPED_UNICODE); + exit; + } + + // ─── GET /admin/webhook/raw?id=N ───────────────────────────────────────── + + public static function getRaw(): void + { + SessionAuth::require(); + $id = max(0, (int)($_GET['id'] ?? 0)); + if ($id === 0) { + jsonResponse(400, ['error' => 'ID inválido']); + } + try { + $stmt = db()->prepare('SELECT raw_payload FROM webhook_logs WHERE id = ? LIMIT 1'); + $stmt->execute([$id]); + $row = $stmt->fetch(); + } catch (\PDOException $e) { + jsonResponse(500, ['error' => 'Error de base de datos']); + } + if (!$row) { + jsonResponse(404, ['error' => 'Registro no encontrado']); + } + header('Content-Type: application/json; charset=utf-8'); + echo $row['raw_payload']; + exit; + } + + // ─── Consultas ──────────────────────────────────────────────────────────── + + private static function getStats(PDO $db): array + { + $stmt = $db->query(" + SELECT + COUNT(*) AS total, + COALESCE(SUM(event_field='messages' AND message_type='text'),0) AS msgs, + COALESCE(SUM(event_field='messages' AND message_type<>'text'),0) AS media, + COALESCE(SUM(event_field='statuses'),0) AS statuses + FROM webhook_logs + WHERE DATE(received_at) = CURDATE() + "); + return $stmt->fetch() ?: ['total' => 0, 'msgs' => 0, 'media' => 0, 'statuses' => 0]; + } + + private static function getLogs(PDO $db, int $page, string $filter, string $search, string $date): array + { + $where = ['DATE(received_at) = ?']; + $params = [$date]; + + if ($filter !== '') { + $where[] = 'event_field = ?'; + $params[] = $filter; + } + if ($search !== '') { + $where[] = '(from_number LIKE ? OR contact_name LIKE ? OR message_preview LIKE ?)'; + $like = '%' . $search . '%'; + array_push($params, $like, $like, $like); + } + + $w = implode(' AND ', $where); + + $cnt = $db->prepare("SELECT COUNT(*) FROM webhook_logs WHERE $w"); + $cnt->execute($params); + $total = (int)$cnt->fetchColumn(); + + $limit = self::PER_PAGE; + $offset = ($page - 1) * $limit; + + $stmt = $db->prepare(" + SELECT id, event_field, from_number, contact_name, + message_type, message_preview, received_at + FROM webhook_logs + WHERE $w + ORDER BY received_at DESC + LIMIT $limit OFFSET $offset + "); + $stmt->execute($params); + return [$stmt->fetchAll(), $total]; + } + + // ─── Helpers de vista ───────────────────────────────────────────────────── + + private static function h(mixed $v): string + { + return htmlspecialchars((string)$v, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); + } + + private static function typeLabel(string $field, string $type): string + { + if ($field === 'statuses') { + $cls = match ($type) { + 'sent' => 'badge-blue', + 'delivered' => 'badge-green', + 'read' => 'badge-teal', + 'failed' => 'badge-red', + default => 'badge-gray', + }; + return '' . self::h($type) . ''; + } + return match ($type) { + 'text' => '💬 Texto', + 'image' => '🖼️ Imagen', + 'audio' => '🎵 Audio', + 'video' => '🎥 Video', + 'document' => '📄 Documento', + 'location' => '📍 Ubicación', + 'interactive' => '🔘 Interactivo', + 'button' => '🔲 Botón', + default => self::h($type), + }; + } + + // ─── Render ─────────────────────────────────────────────────────────────── + + private static function render(array $v): void + { + http_response_code(200); + header('Content-Type: text/html; charset=utf-8'); + + // Variables para el heredoc + $userName = self::h($v['user']['name'] ?? 'Admin'); + $dateVal = self::h($v['date']); + $maxDate = date('Y-m-d'); + $filterVal = self::h($v['filter']); + $searchVal = self::h($v['search']); + $totalStr = number_format((int)$v['total']); + $selMessages = $v['filter'] === 'messages' ? 'selected' : ''; + $selStatuses = $v['filter'] === 'statuses' ? 'selected' : ''; + $sTotal = (int)$v['stats']['total']; + $sMsgs = (int)$v['stats']['msgs']; + $sMedia = (int)$v['stats']['media']; + $sStatuses = (int)$v['stats']['statuses']; + + // Filas de la tabla + $rows = ''; + if (empty($v['logs'])) { + $rows = 'Sin eventos para esta fecha.'; + } else { + foreach ($v['logs'] as $log) { + $id = (int)$log['id']; + $time = self::h(substr($log['received_at'] ?? '', 11, 8)); + $from = self::h($log['from_number'] ?? '—'); + $name = self::h($log['contact_name'] ?? '—'); + $type = self::typeLabel($log['event_field'] ?? '', $log['message_type'] ?? ''); + $preview = self::h(mb_substr($log['message_preview'] ?? '—', 0, 70)); + $rows .= "" + . "#{$id}" + . "{$time}" + . "{$from}" + . "{$name}" + . "{$type}" + . "{$preview}" + . "" + . "\n"; + } + } + + // Paginación + $pager = ''; + if ($v['pages'] > 1) { + $pager = '
'; + for ($i = 1; $i <= min((int)$v['pages'], 20); $i++) { + $qs = '?page=' . $i + . '&type=' . urlencode($v['filter']) + . '&search=' . urlencode($v['search']) + . '&date=' . urlencode($v['date']); + $active = $i === (int)$v['page'] ? ' active' : ''; + $pager .= "{$i}"; + } + $pager .= '
'; + } + + echo << + + + + + Admin — Palmas360 + + + + +
+
+

Palmas360 Palmas360  ·  Admin

+ Somos19D +
+
+ 👤 {$userName} + Salir +
+
+ +
+
{$sTotal}
📡 Total hoy
+
{$sMsgs}
💬 Mensajes texto
+
{$sMedia}
📎 Multimedia
+
{$sStatuses}
📊 Estados
+
+ +
+
+ + + + + {$totalStr} resultado(s) +
+
+ +
+ + + + + + + + + + + + + {$rows} +
IDHoraNúmeroNombreTipoPreview
+ {$pager} +
+ + + + + + + + +HTML; + exit; + } +} diff --git a/admin/LoginController.php b/admin/LoginController.php new file mode 100644 index 0000000..fe705ed --- /dev/null +++ b/admin/LoginController.php @@ -0,0 +1,128 @@ +prepare('SELECT id, name, email, password FROM users WHERE email = ? LIMIT 1'); + $stmt->execute([$email]); + $user = $stmt->fetch(); + } catch (\PDOException $e) { + $_SESSION['login_error'] = 'Error de base de datos.'; + header('Location: /login'); + exit; + } + + if (!$user || !password_verify($password, $user['password'])) { + sleep(1); // freno básico a fuerza bruta + $_SESSION['login_error'] = 'Correo o contraseña incorrectos.'; + header('Location: /login'); + exit; + } + + SessionAuth::login($user); + header('Location: /admin/dashboard'); + exit; + } + + public static function logout(): void + { + SessionAuth::logout(); + header('Location: /login'); + exit; + } + + // ─── Vista ─────────────────────────────────────────────────────────────── + + private static function renderForm(string $token, string $error): void + { + http_response_code(200); + header('Content-Type: text/html; charset=utf-8'); + $errorHtml = $error + ? '
' . htmlspecialchars($error, ENT_QUOTES, 'UTF-8') . '
' + : ''; + echo << + + + + + Ingresar — Palmas360 + + + +
+
+
Palmas360
+

Palmas360

+

Panel de administración — Somos19D

+
+
+ {$errorHtml} +
+ + + + + + +
+
+
© 2025 Somos19D
+
+ + + + +HTML; + exit; + } +} diff --git a/admin/v1/WpWebhook.php b/admin/v1/WpWebhook.php new file mode 100644 index 0000000..0fcef40 --- /dev/null +++ b/admin/v1/WpWebhook.php @@ -0,0 +1,376 @@ + 'Verificación fallida'], JSON_UNESCAPED_UNICODE); + exit; + } + + // ─── POST: Recepción de eventos ─────────────────────────────────────────── + + public static function receive(): void + { + // 1. Leer body raw + $rawBody = file_get_contents('php://input'); + if ($rawBody === false || $rawBody === '') { + self::respond(400, ['error' => 'Body vacío']); + } + + // 2. Guardar raw body para los handlers + self::$currentRaw = $rawBody; + + // 3. Verificar firma HMAC-SHA256 de Meta + self::verifySignature($rawBody); + + // 4. Decodificar JSON + $payload = json_decode($rawBody, true); + if (!is_array($payload)) { + self::respond(400, ['error' => 'JSON inválido']); + } + + // 5. Procesar ANTES de responder + self::processEvent($payload, $rawBody); + + // 6. Responder 200 a Meta (menos de 20 seg) + self::respond(200, ['status' => 'received']); + } + + // ─── Procesamiento de eventos ───────────────────────────────────────────── + + private static function processEvent(array $payload, string $raw): void + { + $object = $payload['object'] ?? ''; + + if ($object !== 'whatsapp_business_account') { + self::log('WARN', "Objeto desconocido: $object"); + return; + } + + $entries = $payload['entry'] ?? []; + foreach ($entries as $entry) { + $changes = $entry['changes'] ?? []; + foreach ($changes as $change) { + $field = $change['field'] ?? ''; + $value = $change['value'] ?? []; + + match ($field) { + 'messages', 'conversations' => self::handleMessages($value), + 'statuses' => self::handleStatuses($value), + default => self::log('INFO', "Campo no manejado: $field"), + }; + } + } + + // Persistir evento crudo para auditoría + self::saveRawEvent($raw); + } + + // ─── Mensajes entrantes ─────────────────────────────────────────────────── + + private static function handleMessages(array $value): void + { + $messages = $value['messages'] ?? []; + $contacts = $value['contacts'] ?? []; + $metadata = $value['metadata'] ?? []; + + $phoneNumberId = $metadata['phone_number_id'] ?? ''; + $displayPhone = $metadata['display_phone_number'] ?? ''; + + foreach ($messages as $msg) { + $from = $msg['from'] ?? ''; // Número del remitente + $msgId = $msg['id'] ?? ''; + $type = $msg['type'] ?? 'unknown'; + $ts = $msg['timestamp'] ?? time(); + + // Nombre del contacto (si existe) + $name = ''; + foreach ($contacts as $c) { + if (($c['wa_id'] ?? '') === $from) { + $name = $c['profile']['name'] ?? ''; + break; + } + } + + $context = [ + 'from' => $from, + 'name' => $name, + 'message_id' => $msgId, + 'type' => $type, + 'timestamp' => $ts, + 'phone_number_id' => $phoneNumberId, + 'display_phone' => $displayPhone, + ]; + + match ($type) { + 'text' => self::handleText($msg, $context), + 'image' => self::handleMedia($msg, $context, 'image'), + 'audio' => self::handleMedia($msg, $context, 'audio'), + 'video' => self::handleMedia($msg, $context, 'video'), + 'document' => self::handleMedia($msg, $context, 'document'), + 'sticker' => self::handleMedia($msg, $context, 'sticker'), + 'location' => self::handleLocation($msg, $context), + 'interactive' => self::handleInteractive($msg, $context), + 'button' => self::handleButton($msg, $context), + 'reaction' => self::handleReaction($msg, $context), + default => self::log('INFO', "Tipo de mensaje no manejado: $type | from=$from"), + }; + } + + // Estados que pueden venir dentro del mismo field 'messages' + if (!empty($value['statuses'])) { + self::handleStatuses($value); + } + } + + private static function handleText(array $msg, array $ctx): void + { + $body = $msg['text']['body'] ?? ''; + self::log('MSG', "[TEXT] {$ctx['from']} ({$ctx['name']}): $body"); + self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'text', $body); + self::saveConversation($ctx, $body); + + // ─── Aquí conectas con tu lógica de bot ────────────────────────────── + // Ejemplo: BotHandler::process($ctx, $body); + } + + private static function handleMedia(array $msg, array $ctx, string $type): void + { + $data = $msg[$type] ?? []; + $mediaId = $data['id'] ?? ''; + $mime = $data['mime_type'] ?? ''; + $caption = $data['caption'] ?? ''; + $preview = $caption ?: "[$type id:$mediaId]"; + self::log('MSG', "[" . strtoupper($type) . "] {$ctx['from']} | id=$mediaId mime=$mime caption=$caption"); + self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], $type, $preview); + self::saveConversation($ctx, $preview, $mediaId); + } + + private static function handleLocation(array $msg, array $ctx): void + { + $lat = $msg['location']['latitude'] ?? ''; + $lng = $msg['location']['longitude'] ?? ''; + $name = $msg['location']['name'] ?? ''; + $preview = "lat:$lat lng:$lng" . ($name ? " ($name)" : ''); + self::log('MSG', "[LOCATION] {$ctx['from']} | lat=$lat lng=$lng name=$name"); + self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'location', $preview); + self::saveConversation($ctx, $preview); + } + + private static function handleInteractive(array $msg, array $ctx): void + { + $iType = $msg['interactive']['type'] ?? ''; + $reply = match ($iType) { + 'button_reply' => $msg['interactive']['button_reply'] ?? [], + 'list_reply' => $msg['interactive']['list_reply'] ?? [], + default => [], + }; + $preview = $iType . ': ' . json_encode($reply); + self::log('MSG', "[INTERACTIVE/$iType] {$ctx['from']} | reply=" . json_encode($reply)); + self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'interactive', $preview); + self::saveConversation($ctx, $preview); + } + + private static function handleButton(array $msg, array $ctx): void + { + $text = $msg['button']['text'] ?? ''; + $payload = $msg['button']['payload'] ?? ''; + $preview = "$text | $payload"; + self::log('MSG', "[BUTTON] {$ctx['from']} | text=$text payload=$payload"); + self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'button', $preview); + self::saveConversation($ctx, $preview); + } + + private static function handleReaction(array $msg, array $ctx): void + { + $emoji = $msg['reaction']['emoji'] ?? ''; + $reactTo = $msg['reaction']['message_id'] ?? ''; + $preview = "emoji:$emoji replyTo:$reactTo"; + self::log('MSG', "[REACTION] {$ctx['from']} ({$ctx['name']}) | emoji=$emoji msg=$reactTo"); + self::saveWebhookLog('messages', $ctx['from'], $ctx['name'], 'reaction', $preview); + self::saveConversation($ctx, $preview); + } + + // ─── Estados de mensajes enviados ──────────────────────────────────────── + + private static function handleStatuses(array $value): void + { + $statuses = $value['statuses'] ?? []; + foreach ($statuses as $s) { + $id = $s['id'] ?? ''; + $status = $s['status'] ?? ''; // sent | delivered | read | failed + $recipient = $s['recipient_id'] ?? ''; + $ts = $s['timestamp'] ?? ''; + + if ($status === 'failed') { + $errors = $s['errors'] ?? []; + self::log('ERROR', "[STATUS:failed] msg=$id recipient=$recipient errors=" . json_encode($errors)); + } else { + self::log('INFO', "[STATUS:$status] msg=$id recipient=$recipient ts=$ts"); + } + self::saveWebhookLog('statuses', $recipient, '', $status, "msg_id:$id"); + } + } + + // ─── Firma HMAC-SHA256 de Meta ──────────────────────────────────────────── + + private static function verifySignature(string $rawBody): void + { + $appSecret = env('WHATSAPP_APP_SECRET', ''); + if ($appSecret === '') { + // En desarrollo puedes omitir esta validación; en producción es obligatoria + self::log('WARN', 'WHATSAPP_APP_SECRET no configurado. Saltando verificación de firma.'); + return; + } + + $sigHeader = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? ''; + if (!str_starts_with($sigHeader, 'sha256=')) { + self::respond(401, ['error' => 'Firma ausente']); + } + + $received = substr($sigHeader, 7); + $expected = hash_hmac('sha256', $rawBody, $appSecret); + + if (!hash_equals($expected, $received)) { + self::log('WARN', 'Firma HMAC inválida. Posible payload adulterado.'); + self::respond(401, ['error' => 'Firma inválida']); + } + } + + // ─── Utilidades ─────────────────────────────────────────────────────────── + + // ─── Guardar en base de datos ───────────────────────────────────────────── + + private static function saveConversation(array $ctx, string $content, ?string $mediaId = null): void + { + try { + $stmt = db()->prepare(" + INSERT IGNORE INTO conversations + (message_id, phone_number, contact_name, direction, message_type, content, media_id, timestamp) + VALUES (?, ?, ?, 'inbound', ?, ?, ?, ?) + "); + $stmt->execute([ + $ctx['message_id'], + $ctx['from'], + $ctx['name'], + $ctx['type'], + mb_substr($content, 0, 1000), + $mediaId, + $ctx['timestamp'], + ]); + if ($stmt->rowCount() > 0) { + $convId = (int) db()->lastInsertId(); + self::saveNotification($convId, $ctx['from'], $content); + } + } catch (\PDOException $e) { + self::log('ERROR', 'DB saveConversation: ' . $e->getMessage()); + } + } + + private static function saveNotification(int $referenceId, string $phone, string $preview): void + { + try { + $stmt = db()->prepare(" + INSERT INTO notifications (type, reference_id, phone_number, message) + VALUES ('new_message', ?, ?, ?) + "); + $stmt->execute([$referenceId, $phone, mb_substr($preview, 0, 255)]); + } catch (\PDOException $e) { + self::log('ERROR', 'DB saveNotification: ' . $e->getMessage()); + } + } + + private static function saveWebhookLog( + string $field, + string $from, + string $name, + string $type, + string $preview + ): void { + try { + $stmt = db()->prepare(" + INSERT INTO webhook_logs + (event_field, from_number, contact_name, message_type, message_preview, raw_payload) + VALUES (?, ?, ?, ?, ?, ?) + "); + $stmt->execute([$field, $from, $name, $type, mb_substr($preview, 0, 500), self::$currentRaw]); + } catch (\PDOException $e) { + self::log('ERROR', 'DB saveWebhookLog: ' . $e->getMessage()); + } + } + + /** + * Guarda el evento crudo en storage/events/ para auditoría. + */ + private static function saveRawEvent(string $raw): void + { + $dir = dirname(__DIR__, 2) . '/storage/events'; + if (!is_dir($dir)) { + mkdir($dir, 0755, true); + } + $file = $dir . '/' . date('Y-m-d') . '.log'; + $line = '[' . date('Y-m-d H:i:s') . '] ' . $raw . PHP_EOL; + file_put_contents($file, $line, FILE_APPEND | LOCK_EX); + } + + private static function log(string $level, string $message): void + { + $dir = dirname(__DIR__, 2) . '/storage/logs'; + if (!is_dir($dir)) { + mkdir($dir, 0755, true); + } + $file = $dir . '/webhook-' . date('Y-m-d') . '.log'; + $line = '[' . date('Y-m-d H:i:s') . "] [$level] $message" . PHP_EOL; + file_put_contents($file, $line, FILE_APPEND | LOCK_EX); + // También a stderr en desarrollo + if (env('APP_ENV', 'production') === 'local') { + error_log($line); + } + } + + private static function respond(int $code, array $body): never + { + http_response_code($code); + header('Content-Type: application/json; charset=utf-8'); + echo json_encode($body, JSON_UNESCAPED_UNICODE); + exit; + } +} diff --git a/config/db.php b/config/db.php new file mode 100644 index 0000000..4a60b94 --- /dev/null +++ b/config/db.php @@ -0,0 +1,36 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, + ] + ); + } catch (\PDOException $e) { + http_response_code(503); + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['error' => 'Error de conexión a la base de datos.'], JSON_UNESCAPED_UNICODE); + exit; + } + + return $pdo; +} diff --git a/config/env.php b/config/env.php new file mode 100644 index 0000000..cf1cb2b --- /dev/null +++ b/config/env.php @@ -0,0 +1,38 @@ + + * El secreto se toma de la variable de entorno JWT_SECRET. + */ +class Auth +{ + /** + * Verifica el Bearer token. Termina con 401 si es inválido. + * Devuelve el payload decodificado si es válido. + */ + public static function requireBearer(): array + { + $header = $_SERVER['HTTP_AUTHORIZATION'] + ?? $_SERVER['REDIRECT_HTTP_AUTHORIZATION'] + ?? ''; + + if (!str_starts_with($header, 'Bearer ')) { + self::abort(401, 'Token de autorización requerido.'); + } + + $token = substr($header, 7); + return self::verifyJwt($token); + } + + // ─── JWT HS256 ──────────────────────────────────────────────────────────── + + private static function verifyJwt(string $token): array + { + $parts = explode('.', $token); + if (count($parts) !== 3) { + self::abort(401, 'Token malformado.'); + } + + [$b64Header, $b64Payload, $b64Sig] = $parts; + + // Verificar firma + $secret = env('JWT_SECRET', ''); + if ($secret === '') { + self::abort(500, 'JWT_SECRET no configurado.'); + } + + $data = "$b64Header.$b64Payload"; + $expected = self::base64UrlEncode( + hash_hmac('sha256', $data, $secret, true) + ); + + // Comparación segura contra timing attacks + if (!hash_equals($expected, $b64Sig)) { + self::abort(401, 'Firma JWT inválida.'); + } + + // Decodificar payload + $payload = json_decode(self::base64UrlDecode($b64Payload), true); + if (!is_array($payload)) { + self::abort(401, 'Payload JWT inválido.'); + } + + // Validar expiración si existe + if (isset($payload['exp']) && $payload['exp'] < time()) { + self::abort(401, 'Token expirado.'); + } + + return $payload; + } + + private static function base64UrlEncode(string $data): string + { + return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); + } + + private static function base64UrlDecode(string $data): string + { + return base64_decode(strtr($data, '-_', '+/')); + } + + private static function abort(int $code, string $message): never + { + http_response_code($code); + header('Content-Type: application/json; charset=utf-8'); + echo json_encode(['error' => $message], JSON_UNESCAPED_UNICODE); + exit; + } +} diff --git a/middleware/SessionAuth.php b/middleware/SessionAuth.php new file mode 100644 index 0000000..bc0d036 --- /dev/null +++ b/middleware/SessionAuth.php @@ -0,0 +1,75 @@ + 0, + 'path' => '/', + 'secure' => isset($_SERVER['HTTPS']), + 'httponly' => true, + 'samesite' => 'Lax', + ]); + session_start(); + } + } + + /** Redirige a /login si no hay sesión activa. */ + public static function require(): void + { + self::start(); + if (empty($_SESSION['user_id'])) { + header('Location: /login'); + exit; + } + } + + public static function login(array $user): void + { + self::start(); + session_regenerate_id(true); + $_SESSION['user_id'] = $user['id']; + $_SESSION['user'] = [ + 'id' => $user['id'], + 'name' => $user['name'], + 'email' => $user['email'], + ]; + } + + public static function logout(): void + { + self::start(); + $_SESSION = []; + if (ini_get('session.use_cookies')) { + $p = session_get_cookie_params(); + setcookie(session_name(), '', time() - 42000, $p['path'], $p['domain'], $p['secure'], $p['httponly']); + } + session_destroy(); + } + + public static function user(): array + { + return $_SESSION['user'] ?? []; + } + + public static function csrfToken(): string + { + self::start(); + if (empty($_SESSION['csrf_token'])) { + $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); + } + return $_SESSION['csrf_token']; + } + + public static function validateCsrf(): void + { + $token = $_POST['_token'] ?? ''; + if (!isset($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $token)) { + http_response_code(403); + exit('Token CSRF inválido.'); + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..23d848d --- /dev/null +++ b/package.json @@ -0,0 +1,22 @@ +{ + "name": "bot-palmas360", + "version": "1.0.0", + "description": "WhatsApp Business API webhook — Somos19D / Palmas360", + "main": "server.js", + "scripts": { + "start": "node server.js", + "dev": "nodemon server.js" + }, + "dependencies": { + "express": "^4.19.2", + "dotenv": "^16.4.5", + "jsonwebtoken": "^9.0.2", + "axios": "^1.7.2" + }, + "devDependencies": { + "nodemon": "^3.1.4" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..35600da --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,9 @@ +Options -Indexes +RewriteEngine On + +# Permitir acceso directo a archivos y carpetas reales +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d + +# Todo lo demás pasa por index.php +RewriteRule ^ index.php [QSA,L] diff --git a/public/condiciones-servicio.html b/public/condiciones-servicio.html new file mode 100644 index 0000000..2c9f9d6 --- /dev/null +++ b/public/condiciones-servicio.html @@ -0,0 +1,170 @@ + + + + + + Condiciones del Servicio — Somos19D + + + + +
📄 Condiciones Oficiales del Servicio · Somos19D
+ +
+
+ NIT: 901677603-5 +

Condiciones del Servicio

+

Somos19D — Empresa jurídicamente constituida en Colombia
Vigente desde el 1 de enero de 2025

+
+
+ +
+

1. Identificación del prestador

+

Somos19D, empresa jurídicamente constituida en Colombia, con NIT 901677603-5, es responsable de la prestación de los servicios descritos en estas condiciones. Nuestros canales de atención incluyen WhatsApp y plataformas digitales.

+
+ +
+

2. Aceptación de las condiciones

+

Al usar nuestros servicios —ya sea a través de WhatsApp, nuestro sitio web u otros canales— aceptas íntegramente estas condiciones. Si no estás de acuerdo, debes abstenerte de utilizar el servicio.

+
+ +
+

3. WhatsApp Business Platform

+

Somos19D utiliza la WhatsApp Business Platform de Meta Platforms, Inc. para prestar servicios de atención y comunicación. Al usar este canal:

+
    +
  • Aceptas las Condiciones del Servicio de WhatsApp Business de Meta.
  • +
  • Los mensajes están sujetos a las políticas de uso aceptable de WhatsApp.
  • +
  • Queda prohibido el uso del canal para spam, mensajes masivos no autorizados o contenido ilegal.
  • +
  • Somos19D puede bloquear usuarios que infrinjan las políticas de Meta o las presentes condiciones.
  • +
+
📱 Al escribirnos por WhatsApp confirmas que has leído y aceptado estas condiciones.
+
+ +
+

4. Descripción del servicio

+

Somos19D ofrece servicios digitales y de información a través de múltiples canales incluyendo WhatsApp Business, sitio web y otros medios digitales. Los detalles específicos de cada servicio serán informados al usuario antes de su contratación, incluyendo tarifas, plazos y condiciones particulares.

+
+ +
+

5. Obligaciones del usuario

+
    +
  • Proporcionar información veraz, exacta y actualizada
  • +
  • Usar el servicio únicamente para fines lícitos
  • +
  • No suplantar la identidad de terceros
  • +
  • No interferir en el funcionamiento del servicio
  • +
  • Respetar los derechos de propiedad intelectual de Somos19D
  • +
  • Mantener la confidencialidad de sus credenciales de acceso
  • +
+
+ +
+

6. Obligaciones de Somos19D

+
    +
  • Prestar el servicio con la calidad y oportunidad acordada
  • +
  • Proteger los datos personales del usuario conforme a la ley
  • +
  • Informar oportunamente sobre cambios en el servicio o en estas condiciones
  • +
  • Atender las reclamaciones del usuario en tiempos razonables
  • +
+
+ +
+

7. Tarifas y pagos

+

Los precios del servicio serán comunicados de forma clara antes de cada transacción. Somos19D se reserva el derecho de modificar sus tarifas, notificando al usuario con antelación razonable. Los pagos realizados no son reembolsables salvo disposición expresa contraria.

+
+ +
+

8. Propiedad intelectual

+

Todo el contenido, diseño, marca, textos y elementos digitales de Somos19D son propiedad exclusiva de la empresa. Está prohibida su reproducción, distribución o uso sin autorización escrita previa.

+
+ +
+

9. Limitación de responsabilidad

+

Somos19D no será responsable por:

+
    +
  • Interrupciones del servicio por causas de fuerza mayor o fallas de terceros
  • +
  • Daños derivados del uso indebido del servicio por parte del usuario
  • +
  • Pérdidas de datos por causas ajenas a nuestra infraestructura
  • +
  • Acciones de terceros no autorizados
  • +
+
+ +
+

10. Suspensión del servicio

+

Somos19D podrá suspender o terminar el servicio a un usuario si este incumple estas condiciones, proporciona información falsa o realiza actividades que perjudiquen a la empresa o a otros usuarios. Se notificará al usuario antes de la suspensión cuando sea posible.

+
+ +
+

11. Legislación y jurisdicción

+

Estas condiciones se rigen por las leyes de la República de Colombia. Cualquier controversia se resolverá conforme a la normativa colombiana vigente. Para consumidores aplican los mecanismos de protección al consumidor establecidos en la Ley 1480 de 2011.

+
📌 Ante cualquier disputa, puedes contactar a la Superintendencia de Industria y Comercio (SIC) o a la Defensoría del Consumidor.
+
+ +
+

12. Modificaciones

+

Podemos actualizar estas condiciones en cualquier momento. Los cambios se comunicarán por WhatsApp u otros canales oficiales con al menos 5 días de anticipación. El uso continuo del servicio implica la aceptación de las nuevas condiciones.

+
+ +
+

13. Contacto oficial

+

Para dudas, reclamaciones o ejercicio de derechos, comunícate con Somos19D a través de nuestros canales oficiales de WhatsApp o correo electrónico.

+
+ +
+
© 2025 Somos19D · NIT 901677603-5 · Todos los derechos reservados
Documento generado el 4 de junio de 2026
+
+ + + \ No newline at end of file diff --git a/public/eliminacion-datos-usuario.html b/public/eliminacion-datos-usuario.html new file mode 100644 index 0000000..798a9e2 --- /dev/null +++ b/public/eliminacion-datos-usuario.html @@ -0,0 +1,179 @@ + + + + + + Eliminación de Datos — Somos19D + + + + +
🗑️ Solicitud de Eliminación de Datos · Somos19D
+ +
+
+ NIT: 901677603-5 +

Eliminación de Datos del Usuario

+

Somos19D — Tu privacidad es un derecho.
Ejercelo de forma sencilla y sin costo.

+
+
+ +
+

¿Por qué existe este derecho?

+

La Ley 1581 de 2012 (Colombia) y el Habeas Data te otorgan el derecho de solicitar la supresión de tus datos personales cuando ya no son necesarios, cuando retiras tu consentimiento o cuando el tratamiento infringe la ley. Somos19D (NIT 901677603-5) está obligada a respetar y tramitar esta solicitud.

+
+ +
+

¿Cuándo puedes pedirlo?

+
    +
  • Cuando los datos ya no son necesarios para el servicio contratado
  • +
  • Cuando retiras tu consentimiento de tratamiento
  • +
  • Cuando consideras que el tratamiento viola la ley
  • +
  • Cuando el período de conservación acordado ha vencido
  • +
  • Cuando nunca autorizaste el uso de tus datos
  • +
+
+ +
+

Cómo hacer tu solicitud — paso a paso

+
+
+
1
+
Escríbenos por nuestros canales oficiales de WhatsApp o correo electrónico de Somos19D.
+
+
+
2
+
Indica: "Solicito eliminación de mis datos personales" y proporciona tu nombre completo y documento de identidad.
+
+
+
3
+
Menciona qué datos específicos deseas eliminar o si quieres la eliminación total de tu historial.
+
+
+
4
+
Confirmaremos la recepción de tu solicitud en máximo 2 días hábiles.
+
+
+
5
+
La eliminación se ejecutará en un plazo máximo de 15 días hábiles contados desde la confirmación.
+
+
+
+ +
+

Información necesaria en tu solicitud

+
    +
  • Nombre completo
  • +
  • Número de cédula o documento de identidad
  • +
  • Correo electrónico o número de WhatsApp asociado a la cuenta
  • +
  • Descripción de los datos que deseas eliminar
  • +
  • Motivo de la solicitud (opcional, pero útil)
  • +
+
+ +
+

Excepciones legales

+

Existen casos en los que no podemos eliminar algunos datos de forma inmediata:

+
    +
  • Cuando la ley exige conservarlos (ej. datos tributarios o contables)
  • +
  • Cuando son necesarios para cumplir un contrato vigente contigo
  • +
  • Cuando exista un proceso legal en curso
  • +
+

En estos casos, te informaremos el motivo y el plazo estimado de conservación.

+ ⚠️ Siempre te informaremos antes de denegar una solicitud +
+ +
+

¿Qué pasa después de la eliminación?

+
    +
  • Tus datos serán borrados permanentemente de nuestras bases de datos activas
  • +
  • Las copias de respaldo se eliminarán en el ciclo de actualización más próximo
  • +
  • Recibirás confirmación escrita (por WhatsApp o correo) una vez completado el proceso
  • +
+
+ +
+

Datos de WhatsApp y Meta

+

Si interactuaste con Somos19D a través de WhatsApp Business API, ten en cuenta que:

+
    +
  • Los datos de la conversación en WhatsApp están también sujetos a las políticas de Meta Platforms, Inc.
  • +
  • Para eliminar tus datos en Meta directamente, visita: Centro de ayuda de Meta.
  • +
  • Somos19D eliminará los registros internos de tus conversaciones y datos asociados dentro del plazo indicado.
  • +
  • Esta página puede ser presentada ante Meta como URL de instrucciones de eliminación de datos.
  • +
+ 📋 Esta URL es válida como "Data Deletion Instructions URL" para Meta/WhatsApp Business +
+ +
+

¿No recibes respuesta?

+

Si en 15 días hábiles no has recibido respuesta, puedes radicar una queja ante la Superintendencia de Industria y Comercio (SIC) de Colombia en www.sic.gov.co.

+
+ +
+
© 2025 Somos19D · NIT 901677603-5 · Todos los derechos reservados
Documento generado el 4 de junio de 2026
+
+ + + \ No newline at end of file diff --git a/public/index.php b/public/index.php new file mode 100644 index 0000000..9c7c072 --- /dev/null +++ b/public/index.php @@ -0,0 +1,72 @@ + 'Página no encontrada']); + } + http_response_code(200); + header('Content-Type: text/html; charset=utf-8'); + readfile($file); + exit; +} + +// ─── Router ────────────────────────────────────────────────────────────────── +$method = $_SERVER['REQUEST_METHOD']; +$path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH); +// Normalizar: quitar trailing slash +$path = rtrim($path, '/') ?: '/'; + +// ─── Tabla de rutas ────────────────────────────────────────────────────────── +$routes = [ + ['GET', '/health', fn() => jsonResponse(200, ['status' => 'ok', 'service' => 'bot-palmas360'])], + + // ─── WhatsApp webhook ──────────────────────────────────────────────────── + // Seguridad: HMAC-SHA256 (X-Hub-Signature-256) verificado dentro del controlador + ['GET', '/admin/v1/wp-webhook', fn() => WpWebhook::verify()], + ['POST', '/admin/v1/wp-webhook', fn() => WpWebhook::receive()], + + // ─── Login / Logout ────────────────────────────────────────────────────── + ['GET', '/login', fn() => LoginController::showForm()], + ['POST', '/login', fn() => LoginController::authenticate()], + ['GET', '/logout', fn() => LoginController::logout()], + + // ─── Dashboard protegido ───────────────────────────────────────────────── + ['GET', '/admin/dashboard', fn() => DashboardController::index()], + ['GET', '/admin/live', fn() => DashboardController::live()], + ['GET', '/admin/webhook/stream', fn() => DashboardController::stream()], + ['GET', '/admin/webhook/raw', fn() => DashboardController::getRaw()], + + // ─── Páginas legales (requeridas por Meta/WhatsApp Business) ──────────── + ['GET', '/politicas', fn() => serveHtml('politicas.html')], + ['GET', '/eliminacion-datos-usuario', fn() => serveHtml('eliminacion-datos-usuario.html')], + ['GET', '/condiciones-servicio', fn() => serveHtml('condiciones-servicio.html')], +]; + +// ─── Despacho ──────────────────────────────────────────────────────────────── +foreach ($routes as [$routeMethod, $routePath, $handler]) { + if ($method === $routeMethod && $path === $routePath) { + $handler(); + exit; + } +} + +jsonResponse(404, ['error' => 'Ruta no encontrada', 'path' => $path]); diff --git a/public/politicas.html b/public/politicas.html new file mode 100644 index 0000000..f7628ee --- /dev/null +++ b/public/politicas.html @@ -0,0 +1,165 @@ + + + + + + Políticas de Privacidad — Somos19D + + + + +
📋 Documento oficial compartido por WhatsApp · Somos19D
+ +
+
+ NIT: 901677603-5 +

Políticas de Privacidad

+

Somos19D — Empresa jurídica legalmente constituida en Colombia
Vigente a partir del 1 de enero de 2025

+
+
+ +
+

1. ¿Quiénes somos?

+

Somos19D es una empresa jurídicamente constituida en Colombia, identificada con NIT 901677603-5. Operamos servicios digitales y de comunicación, incluyendo atención a través de WhatsApp y canales en línea.

+
+ +
+

2. Datos que recopilamos

+

Para prestar nuestros servicios, podemos recopilar:

+
    +
  • Nombre completo y documento de identidad
  • +
  • Número de teléfono (incluyendo WhatsApp)
  • +
  • Correo electrónico y dirección
  • +
  • Historial de transacciones y servicios solicitados
  • +
  • Información del dispositivo y dirección IP
  • +
+
+ +
+

3. ¿Para qué usamos tus datos?

+
    +
  • Prestar y mejorar nuestros servicios
  • +
  • Comunicarnos contigo por WhatsApp u otros medios
  • +
  • Procesar pagos y gestionar pedidos
  • +
  • Cumplir obligaciones legales y tributarias
  • +
  • Enviarte información relevante sobre nuestros productos
  • +
+ ✅ Nunca vendemos tus datos a terceros +
+ +
+

4. Seguridad de la información

+

Implementamos medidas técnicas y administrativas para proteger tus datos frente a acceso no autorizado, pérdida o divulgación. El acceso a tu información está limitado al personal estrictamente necesario.

+
+ +
+

5. Tus derechos

+

Como titular de tus datos tienes derecho a:

+
    +
  • Conocer, actualizar y corregir tu información
  • +
  • Solicitar prueba de tu autorización de tratamiento
  • +
  • Revocar tu consentimiento en cualquier momento
  • +
  • Solicitar la eliminación de tus datos (ver enlace dedicado)
  • +
  • Presentar quejas ante la Superintendencia de Industria y Comercio (SIC)
  • +
+
+ +
+

6. WhatsApp Business API y Meta

+

Somos19D utiliza la WhatsApp Business Platform operada por Meta Platforms, Inc. para comunicarse contigo. Al interactuar con nosotros por WhatsApp, aceptas que:

+
    +
  • Tu número de teléfono y los mensajes intercambiados son procesados por Meta conforme a sus propias Políticas de Privacidad.
  • +
  • Meta actúa como sub-procesador de datos en la prestación del servicio de mensajería.
  • +
  • Los mensajes enviados a través de WhatsApp están sujetos al cifrado de extremo a extremo de Meta.
  • +
  • Somos19D no accede al contenido de los mensajes fuera de la conversación contigo.
  • +
+ 📱 Consulta la política de Meta: whatsapp.com/legal +
+ +
+

7. Opt-in y Opt-out de mensajes WhatsApp

+

Opt-in (consentimiento): Al escribirnos por WhatsApp o facilitar tu número para recibir comunicaciones, otorgas tu consentimiento expreso para recibir mensajes de Somos19D por este canal.

+

Opt-out (cancelar suscripción): Puedes dejar de recibir mensajes en cualquier momento respondiendo "STOP", "DETENER" o "NO DESEO RECIBIR MENSAJES". Procesaremos tu solicitud en máximo 24 horas.

+ ✅ Nunca recibirás mensajes sin tu consentimiento previo +
+ +
+

8. Compartir información con terceros

+

Somos19D puede compartir datos con proveedores de servicios que actúan en nuestro nombre (pasarelas de pago, plataformas de mensajería como Meta/WhatsApp), bajo estrictos acuerdos de confidencialidad y solo para los fines autorizados.

+
+ +
+

9. Cookies y tecnologías similares

+

Nuestro sitio web puede usar cookies para mejorar la experiencia del usuario. Puedes configurar tu navegador para rechazarlas, aunque algunas funcionalidades pueden verse afectadas.

+
+ +
+

10. Cambios a esta política

+

Podemos actualizar esta política en cualquier momento. Te notificaremos los cambios relevantes a través de nuestros canales oficiales, incluyendo WhatsApp.

+
+ +
+

11. Contacto

+

Para ejercer tus derechos o resolver dudas sobre esta política, comunícate con nosotros a través de los canales oficiales de Somos19D.

+
+ +
+
© 2025 Somos19D · NIT 901677603-5 · Todos los derechos reservados
Documento generado el 4 de junio de 2026
+
+ + + \ No newline at end of file diff --git a/server.js b/server.js new file mode 100644 index 0000000..b5268cc --- /dev/null +++ b/server.js @@ -0,0 +1,30 @@ +require('dotenv').config(); +const express = require('express'); + +const app = express(); + +// Parsear JSON raw para poder verificar firma HMAC de Meta +app.use( + express.json({ + verify: (req, _res, buf) => { + req.rawBody = buf; + }, + }) +); + +// ─── Rutas ─────────────────────────────────────────────────────────────────── +const wpWebhook = require('./admin/v1/wp-webhook'); +app.use('/admin/v1/wp-webhook', wpWebhook); + +// Health check +app.get('/health', (_req, res) => res.json({ status: 'ok', service: 'bot-palmas360' })); + +// 404 +app.use((_req, res) => res.status(404).json({ error: 'Ruta no encontrada' })); + +// ─── Inicio ─────────────────────────────────────────────────────────────────── +const PORT = process.env.PORT || 3000; +app.listen(PORT, () => { + console.log(`✅ Servidor corriendo en puerto ${PORT}`); + console.log(`📡 Webhook WhatsApp → /admin/v1/wp-webhook`); +}); diff --git a/setup/migrate.php b/setup/migrate.php new file mode 100644 index 0000000..b842d20 --- /dev/null +++ b/setup/migrate.php @@ -0,0 +1,94 @@ +exec(" + CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + name VARCHAR(100) NOT NULL, + email VARCHAR(150) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +"); + +$db->exec(" + CREATE TABLE IF NOT EXISTS webhook_logs ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + event_field VARCHAR(50) NOT NULL DEFAULT 'messages', + from_number VARCHAR(30), + contact_name VARCHAR(150), + message_type VARCHAR(30), + message_preview TEXT, + raw_payload LONGTEXT, + received_at DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX idx_received_at (received_at), + INDEX idx_from_number (from_number), + INDEX idx_event_field (event_field) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +"); + +$db->exec(" + CREATE TABLE IF NOT EXISTS conversations ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + message_id VARCHAR(100) NOT NULL UNIQUE, + phone_number VARCHAR(30) NOT NULL, + contact_name VARCHAR(150), + direction ENUM('inbound','outbound') DEFAULT 'inbound', + message_type VARCHAR(30), + content TEXT, + media_id VARCHAR(150), + timestamp INT UNSIGNED, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX idx_conv_phone (phone_number), + INDEX idx_conv_created (created_at) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +"); + +$db->exec(" + CREATE TABLE IF NOT EXISTS notifications ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + type VARCHAR(50) NOT NULL DEFAULT 'new_message', + reference_id BIGINT, + phone_number VARCHAR(30), + message TEXT, + is_read TINYINT(1) DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX idx_notif_read (is_read), + INDEX idx_notif_created (created_at) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +"); + +$db->exec(" + CREATE TABLE IF NOT EXISTS media_queue ( + id BIGINT AUTO_INCREMENT PRIMARY KEY, + message_id VARCHAR(100) NOT NULL, + media_id VARCHAR(150) NOT NULL, + media_type VARCHAR(30), + attempts TINYINT DEFAULT 0, + processed TINYINT(1) DEFAULT 0, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP, + INDEX idx_mq_processed (processed), + INDEX idx_mq_message_id (message_id) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +"); + +// ─── Usuario admin por defecto ──────────────────────────────────────────────── + +$email = 'admin@palmas360.com'; +$password = 'Palmas360@Admin26'; +$hash = password_hash($password, PASSWORD_BCRYPT, ['cost' => 12]); + +$stmt = $db->prepare("INSERT IGNORE INTO users (name, email, password) VALUES (?, ?, ?)"); +$stmt->execute(['Lizandro', $email, $hash]); + +echo "\n✅ Tablas creadas correctamente.\n"; +echo "👤 Usuario: {$email}\n"; +echo "🔑 Contraseña: {$password}\n"; +echo "⚠️ Cambia la contraseña después del primer login.\n\n";