From b103650cb794bd9bd7da51a2df60d792046f1291 Mon Sep 17 00:00:00 2001 From: mrbobbytables Date: Wed, 28 Oct 2026 17:00:08 -0500 Subject: [PATCH 1/7] Add China Merchants Bank reference architecture Adds the reference architecture submitted to the End User TAB in cncf/tab#140: unified training and inference on Kubernetes across a heterogeneous accelerator pool, using Kubernetes, KEDA, Prometheus, HAMi and Fluid with Kueue admission control. - Hand-authored docs/architectures/china-merchants-bank/index.md with the architecture diagram colocated under images/ - Mirrored HAMi and Fluid icons from cncf/artwork - Regenerated data/architectures/catalog.json - Accept cncf/tab submission issues as a sourceIssue origin in the catalog contract test and CONTRIBUTING.md - Added project and vendor terms to the spelling dictionary Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables --- .cspell.yml | 6 + CONTRIBUTING.md | 11 +- data/architectures/catalog.json | 24 +++ .../images/architecture.png | Bin 0 -> 165648 bytes .../china-merchants-bank/index.md | 189 ++++++++++++++++++ .../cncf-projects/fluid-fluid-icon-color.svg | 137 +++++++++++++ .../cncf-projects/hami-hami-icon-color.svg | 28 +++ tests/architecture-catalog-contract.test.mjs | 15 +- 8 files changed, 401 insertions(+), 9 deletions(-) create mode 100644 docs/architectures/china-merchants-bank/images/architecture.png create mode 100644 docs/architectures/china-merchants-bank/index.md create mode 100644 static/img/cncf-projects/fluid-fluid-icon-color.svg create mode 100644 static/img/cncf-projects/hami-hami-icon-color.svg diff --git a/.cspell.yml b/.cspell.yml index f9895b30..33aa308f 100644 --- a/.cspell.yml +++ b/.cspell.yml @@ -121,6 +121,12 @@ words: - Kubermatic - kubevirt - Kueue + - hami + - Qwen + - Shenzhen + - TPOT + - TTFT + - verl - kyverno - MGMT - MPLS diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index efda6c17..f639430c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -134,11 +134,12 @@ Rules: written. Alongside `title`, an `architecture:` block carries `organization`, `summary`, `industries`, `tags`, `projects`, `sourceUrl`, exactly one of `sourceCommit` (a cncf/architecture import) or `sourceIssue` (a submission - issue), `published` and `updated`. The record's `id` is the directory name and - its `assets` are the files in `images/`; neither is written by hand. After - editing a page or adding one, run `npm run generate:architectures` and commit - the regenerated `data/architectures/catalog.json` with it; the catalog - component, member directory and data-link checks read that mirror, and + issue in this repository or in the End User TAB's cncf/tab intake), + `published` and `updated`. The record's `id` is the directory name and its + `assets` are the files in `images/`; neither is written by hand. After editing + a page or adding one, run `npm run generate:architectures` and commit the + regenerated `data/architectures/catalog.json` with it; the catalog component, + member directory and data-link checks read that mirror, and `validate:architectures` fails when it is behind the pages ([ADR 0010](adr/0010-architecture-pages-are-the-metadata-source.md)). - Architecture `tags` are written with spaces, not underscores (`private cloud`, diff --git a/data/architectures/catalog.json b/data/architectures/catalog.json index 1744dee6..66420b89 100644 --- a/data/architectures/catalog.json +++ b/data/architectures/catalog.json @@ -103,6 +103,30 @@ "/img/architectures/cern-scientific-computing/use-cases.png" ] }, + { + "id": "china-merchants-bank", + "title": "Unified Training and Inference on Kubernetes for Heterogeneous AI Compute at China Merchants Bank", + "organization": "China Merchants Bank", + "summary": "China Merchants Bank runs large-model training, LoRA fine-tuning, and online inference on one Kubernetes-based pool of nearly 10,000 heterogeneous accelerator cards, with separate operating policies for each workload type.", + "industries": ["financial-services", "banking"], + "tags": [ + "ai", + "machine learning", + "llm training", + "llm inference", + "gpu scheduling", + "heterogeneous accelerators", + "multi-tenancy", + "autoscaling", + "platform engineering" + ], + "projects": ["Kubernetes", "KEDA", "Prometheus", "HAMi", "Fluid"], + "sourceUrl": "https://github.com/cncf/tab/issues/140", + "sourceIssue": 140, + "published": "2026-10-28", + "updated": "2026-10-28", + "assets": ["/img/architectures/china-merchants-bank/architecture.png"] + }, { "id": "colopl", "title": "Colopl's FESTIBATTLE Infrastructure Architecture: Dedicated Game Servers with Agones on Kubernetes", diff --git a/docs/architectures/china-merchants-bank/images/architecture.png b/docs/architectures/china-merchants-bank/images/architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..58563072c2edcbcf89e7baeadb3dc398ab6c3790 GIT binary patch literal 165648 zcmeEv2|SeB|9|`DmLwEKSJYm|-f_z4v?Xt?&2uzpq~I<2>g%&w0-0{n(7Z?G&=ECNHbGf% zZHu%)fd45X%xo~wBj#AR3ojA_x(kZ&3h+Xck+s5NP@t2708EURpI20nUx-&w2nOyf zPFewsEi^YjZMX#-izIs;G=v!jWrsyLI3UdDzt#e7>i|ZCZaE{c4oL9bbE`mlCv?NX z3~q~7lgj-_aDDVrC_!>tSB-+Ln!Q+U9 zBhg5-B@Ys9fxsfrX2f@+;o!UGUVMbu13U~zn}eT9i#_>eux3_BM?fDZ?A(LouO+=4 zbwUvfx3f~im?Lb#wJqiv~tk*Sz<}kBz_*$ppA4Ree>KGf^JSo zbA$tNwD~6;F&JA%q}}I@W*9UYO!2dha4Z%=%G?(cUt)o=B`yxJ!46>UvmQ``_E&2U zwdx_w9j%Cc1^J2dgKiu`AT6y(ujUsf-a)}hy@?GDR&apa`2psdzFtVua$+$UFdi9s z=WmezgxE+HVGFG`X(5U40pR=d&n_$nzz6YD{*&Pxk&Xbp^9YCAIuVyx#mN+bMI#&$ z4m@bMBhnf4;Qv$518m{wN@5E~#0fCdgI10xTd=4C;1X_&w1im6415E`DF*>}IU)fu zWr#OWNON=O@q-o^v?CF0f?}lKi91H^cb87dCP^7 zp`L#P6`&6hRNtTd64-NaGF_VHN9KhPn8Cbc0Sjfzqiu(f1wxkJ4&wsoB*;&aP;)EH zuXRunv|)hQK{$Xr050IyMcFkc?Nyu*09A7`Tt!|ENI^)NACgf6q8GZFf0u$SkRISS zGYk-&NB}tqaBy=J(qT^K&h>=kERc=F$IQ$Swg~V_KzPv8))r$1a0;oV#X(W?GETu9 z?g-QpKO8*b;J`aij=u?=E|9#{wu1vf4U=;Lf|Z2OdGRO!A@K`@3dslyi$F-8pU6Lq zP?Gc`B2<_t}1iV+TM2&BA$6GO-DY*h0d@6kJ$B7i3~d z=CBg!Heis29;7x?0G0V?NG%X)!0?M;5V3cH>yh9q|FwzbI z;0WOqVpu_b9q?}Ar8eLPb0+{#(tALU`B#x%4}H|)TLrNgC$#yT%>jwDr9ee4JF#X& zfhYhORKQlVB@=)ObN_*Mz>pXlz`Tp1QA7-;02B`K4oOJ@0r(|E7lbG@Y0|rdK)-(j zvM{2+B*|3%uZ60B2(gVEv81-2f>=l~AkBdE`w?2zNFBjfioj8jyqNz903q)Tv>_N{ z9^n5xf+1_!(F)-N3GI0d6J<5=H_gM^WRv;%02UXLfgOY-=RCAY02bgC{>30H3>b3` z3E#u87_rYUgW(0etq9bw3mn)vKLRtk@3HXEzl2^{TO?%vl8`$m`iZzzLR&&U+%JV) zf&UKS3ycAxX#E~^Nuu_bfvyV%Yh#Ono2$ZIA*K5jZlQ)H)h(nzf1qx^(691x3c_Ss zluW zMn+6B+I`!Xv_)7zrrRI!B!QzgZ}ez?+mjR&5)u-F%%y*ncqC8qbFKqE?EG8F?R1eP z6b8vy`YDtondx!}J6nt^YEB$~LC*QFAS2&jv~)!vdi@QCE(kt3f)E=Na+r%lU=e0c zAgt$%&_c{x`*M&(_%|pn^aaIXUvsYzNfv*`yd-b!r;_{-0uDtuzvNyrU+hazkYV84 zEc~a!K>~B2fIO6MGx35a^GCfQz+=z?^FuiP(z`-qfV;O8I=;yWe?zE=Oad&42NG_6 zDjW`DK=9@(*8jGnKG%OKLlGK-3@Lw6T0lO+m(oI1K}JCqw0{KzSs^(=c_>cvrQ&eJ zK;D@H2=0KW(-G(wxw(M>;>ff<3??KXyr53V!ajdh)cliRB55096o_a!2#L-Uj|^%s z5%Kvpa?vC3bFoGWPyP^Rq>f7g4DdG5?M9nAK=fr31p&h^ngsdPoIv7&#}R>s&-oat z7%eD$vnbyF9-Pj>=8tMMQCXObyxanUzw7-9$_wxVBb{jD5J3qAdgh5rZitfLw#dSN zgV0(UXRxn>k1!CcpA#J9I1?md@27|~2Rnor2zdVpWaPo|{{UxlSh$5F4>3?phA#k9 zD5eOa?`BT6qy&r{m>CF;g9!Mq1ivLh+)Kg_ifsN=_=$p5gBFfl%>8okn`1|x=ur>H~K_U+%3O}+;IMC5!a6IWP)e`(J9uIXS7cL3QcqCflv zYr+Hs<;5UYBxlW~?TEiWyDlX9V;5PFRKr1TKY$?SJSY4V17abJ{-p=}8DD-=;zFza z1BnaAk`jRbdtnh#5a0Du*fh^B?DNgRK{-bzW+H3vqh>l=QiEiO%TILHA zZLVBvzU}ksg0EeMC8Hu*7*L}MSv!#7Ht(U%2TIVO(h4+bEEIyxRbu@;I_^&eNfvyJ zzgi-&wBNA+yG3UH8|2s0c>C{&k|40oAQB;uwwx=0`jOk=tg5QE02ysXRX7yH_z!@n zJ^y+zB>4=;6zN|K9RDe-iOC!kBeS;`19D45M3(e%mo}vTO|1P_ghb{REs~`AGDSlHe{rO;*g4j2+N(beHqW;vf5F3O!D7XKSNie?`U@04bXtZKUfkl#~Kn&?E5}g#k zgKm7kSbMIrmd6|m3O&FM0e-lXBW7VY!NL^g$0tS6zbPgDRDfowFx@{@pbZ%>{{|>Y zZZ%QV2$LcC0lR+o58Bc6^-e57Qc3E66(}7R_lf)%n4}GPU^SN7U-Hi)bUF<
mc--y8`B9?;l7t{#$ZWh*Y5aJ&Z23E8wRJPAfR-4{XAk-_N%IihmZ2&WeY1=41j? zB7s7nFmrn{=i^ak7%UWt`sL)Pynuk5n9NuH02Bg%Wc-iP;r|v!MM;+9_b^Jr<1eG! zEuh__3m(FcL@8;n>B0m2z|Vj-^8HKjl>^&R9T1CKR~D);h&I4sU8o{$Zj&Rx^iQ_{ z_~m7UWguDlxhMOpAy=GK9{(NWF6k?g(EL-(Qm{`6ou9&jmUd2u!8s*Aj#wN5$6;VG;J_OMW^T)@%x6as%#X1kw*NK@ zh<~Zg=jsSJ))uNsf>u*@ZUaBR860a4s*V=Rl#WgYc-r2eg4?1Cgio+#u*N&9`sq9lSO z+>`Ty7%}AcQ+Q$Ckb(oZ^vCS5U`EY%Uo0m5`*~o=0~o$Eqew;6L_fd^928}TLC%%$ zo6S#gVPc=#RP)V?JU~MGd@r)?C`-m0zu?cMD-QX^fbs=)DQN_7HCL>w>4HGRcm#xi zp5=FeV^KWBnes!MSrRbsydbpLVHvt)HFv4r9)tg^`qvWW|^fpXB#E=1VoN@yJ(qqU}n->%$v0(=t0!DPZ{@mPtv|vJ{1)IP4{(?cf z#^&=}^V9nxP4VYuM%0zxT(v(nv-zM4`AJKVqfKVh{>7S$Kb0bpC8brr2%0Qp<)C)b zi8WBBhIG&vF$+lC&8IrIRa{PB=?aX0Adfd^s6p#R6hUGnGnmXA5FnWh z?e$w^lmBny%~1^qzNP+sBLPT?H4vdKzC>19kQ8VlhxSiB3uVsu(3+EdP!0o|LbKz5up!qL%{XxKsJJD`c|NW`xWb@)adIAreur%DDoZW!z_ zFa@WE+RQg80L4z+1NTi$OpNKyol-n!V}J_ig(E5*;aE$M)cNe@mpgr+m6-1_r`x}O zbnCqE`$F1b5yai#_A1}oKPT2fTi~x5pD6$BmikE^_KuxYESmR$oYRns*q$05QNZC0}H48 z&IL??G6!<M$|fdSYJ236ab#qB;{Kc^gn<~MC=d?FtT*rn3cz`EApJu0l!@`2&rb9(|JI2f ze^zIHPZxfZFCe$`v)$i6;tTTN${*$vvIAAf#iYa6JBa=-GKt6+ev1&vZ~32L5*1Jm zuC>JOL@2UJbm;#B#qmAhf5QlzKQH)Oz+c)X{7cAREQBWq{=!bpe-ZAGy#A5Q{m(=p z@my<&*kAdv3vs&t&@uScXiZMlMOy!hWc|LzB3IH&sAm{S(h$|N5Gnjjawq1E9imc) zNcUq5eg4XS)VhEU-6K!xElmH<&Jy(hHLVL0OD(x`f$VQ%{Eu-JxsCmqmBq@RcI_tOjAR8hm<1%ULMx;i-@|H?tat+)VMGl{w9<8gEq~H-N zG<5B07z(8cO92q`08Ng-yarg<;f_?=CQP^!A|x zw_8jE^`|$fR~XiomyI>{VV=u}8u3i~@0aV0v`k9<Yr?PxvD#)l^_C?_)#SUIgF zOU`Dtx|&o<%?f6BjCqz_*{i*h&>3Z;-Y|q=C|zGN7SLcBAskTAe8gmh%M3xL;kJ8g zs;X#x~-=X;eHf(uCctzdVS!eG7mD4 zcGa%S=a(_-(jRN4IJIKSp$C_9M=!Z|JTxvb=RCeQMkpw41#?9)YvgZlCaNSlvL4BH zGz}Jn3Q-gp{>Ez;hsm3~bWNz;@TL6A#}qufGF!!zJEJjCg1%HKsfiDTrnO>2YFYf1 zQ8rJz=w*uBW{UMJ5{D=O&eRH&e0fdQlC~e=KKe zuLo@Np`6RPc$0Buf7!LqstP}8aXKfm+*f_9#Ez_ZSP+89>Wf;77({#Kol_{fcX41` zJMLK&VLU*Q(S6^cWmJ8Xm*h-!I<@z|Qn*efm$2K?Xit~1U3TX4P4$*~;vHvi-l<%% z<-~L$rgY3`)8*uXsklfd`Foki%29#0G)F?Y%k?(Yd-1Pd!J_~epqTU8dl9Bntjw=Al|1bn*mvf1lZV6m`G zCE1pYe7XI3kyf{=s-&k?x9YxD*Md)lnux2f+2MJ9yhoZZ|7^3^SfI1PW3KXh_ey$& zGi8eI-3vdlZN+A*<$!s44wr6C$zEUNt*^0v^jd%REF96qmAdu*<`m9hQMrWYS=k!G zxn491ce{O~8f$s)wkutKDVN};z}R_|&o63RwDly1(f9zHhBV>e;VYA!kp`~~^KV*> zWM%WxpS;(fH64;oM?)2#xZ!GY`+(23Wv4aZgmgIMZh0(WA57qtSJ!7FM;^l`r+f>FNiBsML}q z2?fUHdp&;J#1)bXKW>`*##eqee{><(+SHJ6WqX zibu5d&WLv7{(hn04jQwkt1bPzmp|*Qb}$Vw^w8{SMn?Qzmhhn5P_yQK@m7cHvn5QP z>`xRga_&q^*e}v@!brSe7M|KKsNy>O5+-_ORzB32$L&CF!?q{sTd6Llos@+&Jg!~q%AK4ycE0~btifGW&x*cJ57w5A)Trrk z`bVLhJ6=(@`v|mkOjAm2m`S>p+1iPz&h08l9ntdDE2gxKy_ej{}( zJpQ>*jVg7o|J0*%R4mDyuVSa0;fhg*rw$*er+t0rxd>`1kLqUoB>1eIhmxweQzn>G zhc_9h_z$>e*o2}@;+rm~Yd8{iNtPQnIYk?e72v@XiSr&K6EhMZ`J?q~~MuJJ?TEac6WNG^P_i zDbSy%(s61n6VGUI8Bgw&k$qOt*QMh--;Q!bpHz45b-Vm&WVlLZrZIFNQ;)7Ewd7H3 zAu4m!0{hZc_W6`vQ+?X>u~^l|or+8zA5yM~wKr?!zML#gip(6&$h;#S!nHM*MvF^Y zq^Hq|@ZqLL@YK$ow_h8#C1an-xR>SFBpZi6xD}RMG+JeSrtC3~Nw}+FIzG|jjKF%J zv7L7R?xjOlZocAF|GKkkTRExjdjxH04P9O1qaQy#%9r|h$TK9q*3ojjrNb@{?7gKI!a9I;lAFTfsn_lp$Wn+bg!YmZ?N7E1lb2J4CtfQCFQkvo0Ho z7ah>fYfBhuG`YmEKf%@@-ROf%$w>IkjvSU>AO-KX= zC2?h6qE~Fd9vorgrm37eWppxqyenQsAGx+k#pW&>ZIHd5(Tk*Ho#ooDky4Il>sD0| zlH(KhKq|IpT&QcTIDdzIpJ1YNQ93SHy;nHt&UGU-Pb1%gBV2vwLXCsaYnhD3svjqs z<9#)xW}Y3`pIV|xlQL??qG#+Nd&j2NxsZ!@A8e#p->}uWf4${%#LZ-`mbmFEi--h0 z+Q?Yb-ikK9;EqtE#)xYzuiK{5t*>UC+#&jOvQs2|OUk{EW{B(4mkMfO)4KYS0Fs@L zcBphoAUnD2ryq2N>K6Hgm*_OTdH?B3>+WTzOsRl5r;9tjag`SJ2eqx6_8+Hg$ZdKz z^iDDQN_7PM{Py;#c*SSOY#c9^v!GLMP~N6V3EZm8aYoPB**T2=mPu&S;B}V#6<(2X z8ozl**dlMe%!=o|q9c)1i#Cl5I>BOkw&7&2w_@3h`=Hj;(Xf8c7n(y4W&Mk3>u4Xn z@2@RVWz~&!wW9B(kQjU;`^JrsuTK~`&m+=$SRu;uSg&aR*ki8sisO0IlDVDTW*WgZ zNx9+yk&-$1-5fjIPuO7qSiHSD(5RP(QX-OaqMrKUGG}^YMSIiCHJ#5~#@%5&GR|OOG zZB^?EF4MW3^S)_cg&UhR@2MRuYbS8bR&aP}y;8pdY=3@x%q`ww!i)?yY#?d^>@i zCf%#3+R>@(UD)kSmv?5^NYou{o#`=ncvstVPcUI5h_JS)Xrvl-hBN1Cq6dAVpt+rN zPc_mY?BrBW$D<33!Ln0~dOnUXMWd*bviH@Ny=!3R$fCRf)Yd*cJ-Prb$ z(lvcadreM`2Jdj}UKTd-EQrmZr7Atw_rUb@MeV7wExtTkYD+$HP;#L}tL6GrdkcfE z323S@QloQZH;H>3K3>S{B~%U1G;&@?`y{8O1F%+rG0s2q9NjgOeS>L!wt0{C(d@j{ zXP`QeYiZe2mwCHfq$y#js%cS@JM@xwWTh3@zL`ietMC}T#;V^B%iotGJs^W|ziw~jn~WW$naE2E+`4EcByfuD*_5qgwg%| zQ7k@7S`LoV&Q#BesVy*K5ZV|~11xX83rtRd`=^Rv2;T5muh{Le_%ownSy(CK_-&+L4?oS>*_=F*T8XwP{50fiDEdxU+~Nf?HpgZ44C`=k z*38l6v3^C>mXAB_Uu9&n&OHAT)`zx~nr(S4nz&EqmA7quu=!~nCDzxImeH({F3oY= zO?{XgBe$I=4SO&Vn4AJbsrTgv^j~IPBsdNlOjY5gGX z;t$mf<32n1+IQ;}RS#?N?jLWj4iWdW>vI@U!nTZNUeP+NdAw_9=BAm%(~a(fp4)2i z^?jHC7Ro;3EmF83W0zBhDX7Yf_GbrhWjyPMis+c~=Ibra=kVLMSy#{AmvQ)7ZoPqP zY=?RCRSHCowfB@`G=sf7b>ytY7cTw;v8>oqphNX~?Quzdwl<&*NQ%rChb^@DAYn6yK%bK6OBT zRg4_B(XDdvlK!Ctr;H$mly-}7^V7k)MOY4db`2MMgvRlH2f@b$g0WSY8l=g~* z<_b=Q_aSPp_Q|qnTkkf_4)QSI|1{NyF%Qjm53cOP79Wz7P{@22RwjAHWOk-yT-)3q z=U!%}A;r*a;hPzp>Ti%2;b=6LJD79kH;F`^gM6jIX^ihz#aTC9YorgoV4y46q$_dwJ2PxK*wW4Q1AClZtuQXVW%i6B@+B*))c1jm2Hf zPTiVPJ@)8n9FQ$QIX2E5E7L}q^!fzBy9kpWFKA3Xs2ZlO71+MOXSm&c)~ArDFuIqQ z#e|T`;w8+}x>jgpP>BGH94jew^xF-O-82l{RRl|(SNjXEz~n}bQ`3x$q?$Zq+rDxn zDr-_XaHgRIre3rmqU2RfJ{yn3IIx(DcL9s}qT9m_>yD`IQZ1^6aV9Z3C3%duZ0*T& z_fO@4T^QeY;L%)KdU9-&Yf53Wn-zW#<^*P_hz+WFu0}K-rwBg zub&E%E7D4l%f$5RhOT9DpkRd_r5K)&-lWX40smR>4AgN z-m+)CS(KuL$BTH}s_$nGCqm?4A0JOc@s=`|j>25xuVVx(eD#z3;HEdZY;~DU?^+4> zOop!ToE^teo@0Exlf!h9*42JG9WO!O!~d?)_Y7Z9b|}{#^S!1z?#$wRSJBL4C6?keqR&8wEL+X{t?;P+O@?mE1Ed9)W|RRSBGiIBc+v_OAMDvaK7 z_pL6)p6%2FkOcQt3h!hHsjODv<8>csRb+JS?>Ta~f4zF3e5%rZ^rM}k4Ok9GCBKZD zj_=ver9YF+4DN0h>+SQl&K>mi5BAcBQ#smGY{D6wd~stM3Ow=MI1(YEkEz&Y-P1qJ z8^p)%x&2c}uvbSE^)0GpT^l9#PUN)E=v|^1a=zI!g0Ww#O7OV3<>eE#+raPT=)am4 zfA>O`2+g>=VT4NRA?$QH9St3gcW{w{iF8PY6wbuICb4y=p0UinX|wpZeF1L%#*jN= zxs81^GE0i{UaK#IUf}&p64E6oPhKvUJf%hrJ;9{fm_l_eK202Q%PghY<<6@sB>ZkY zjw9G#yybLbeDV_QA!hx)2e0@)jw%JGWzI>q!jDfS5X`#z?I(^zvi49|zl;m2Y_op( zrg~!6_`zi>CPBRRdEut}%U0-6*{yXocqq7@Pzn1O=^prswIWlvD02dKW0IcAJX$_z z>)~2c7V8*Yym^^lrIIyf=2f))1dU5LtM@s^8uW2n;PGr(Iz0}61bUD9Jw4rB`JA#jwA;hc~Z4c=CyvJnca+P zBP@mU=#gBLts9%R=vE!#Ht{q{1cb5=xrOSL48F*f-kltj)+5BM8@^|+i@UCtu97_W zc-uCm8kfE&`$KOf5~d1;R8zy5CL3*!wCMGfBzftSI*;YaCERy4=UkygdnWvpyI0N(equT9mgTr)*^ox+VY|$#BKfrwm3}W&TO36DQ93yP z?c8;Sbz}00_r0R_*ePXO(JKx3y&rmCmR!2YC}*|h&Ys}nh>BzF@7fTRVpDZ3jSYDdBd!G?YQ;5m~dE1Gpx25*4{i^ z^S(e`AGk;xmcc0qZc*OB=e%M^b$}42opuTo*~w;_-6cJl(RXfCejr;(v*}~anB@S) z>9nd`rkX=F$vRJp>Ns?&-`w*ny7$_@B`48b!kvvd#6LI}C5&Ric-#hBGLZ=@4Z^;B zAZYF}86>gl9{Xi;fjeOn8CvDSbvv+a>7ibXV`yHN({0q(fi1cn3Y84iR7tP(FZR}V ztNQ)srT`E*GjQG%%6P2#=6Fi%@VWj6+nZtD9tP`T-m-PXAX&3Tm5Z>M3KIo8w&}gJ z4|;s8oyzhI?ojfZh>^scNVG5oU!5Y3IiwGE)JI>_!1!@*Jxzg!3CG3w3(6-o9!vI^ zCew~?u8Vtra-3&d4X<6GoTZ$+DckhE8@WajYUW1G?^-}m@^n8?1=W+nN4@mXThH(* z>lJQmboGyleR92KjMAQB{Mf{q#;tXmfHx0#^b(hEvSbr3gKIN)c2UeDffXS7?|Ikv zW$3mGBipxnP`#en(1IB* zNX(klY&^tWag$!!x$1n)x-J#I{rN3x^`ExdMO>5WXKsM!@|>o8n2_~J@KNZ^QJ;w9 zZpozk?Gn=Exa{x@e^DuY-!a|0(!)Cd5hx)dWCd}pvR2qt+TLnD23+k@$VQ(^jhMmt zR)}5+=!$0N+}16Ocz&dz>mf_KG&K`nLsrcu&rt14(#jSQC|%d?0FHJLlG@S|W0jPp z6#nM6W!?@4IgOqSj9!@i)9oFnX7_VSQc7evzRi;ez;ficu~&PanNqH+Y*M+f3AUR0 z9kqtIViaybzQMV#0uhlY52?k#YTGk4N^L7C zr8pILx?6vsd02?a_J;g6!NL6w!P|0z4$_QNGKq-k=c&)$?m@ghY7t^RG%-|`+~Iwj zqx5XV4BM>hgnf^@m1qN^3vZrr)N;LCQD!U7WRr9+tLuojrLxE*v)}t2nc?R`2j3z_ zs~%`Du|BAhin#N;Q|<5CDim(%#gfk&X^xL1P74FutkEWs^Z9{uO+B|Gc%4&hp7#if zdQuXqLkUMu5GwxL~X@9_lS%_v$e zwLV^6vMBv-R_m+RSt4|y3W2E#-ul*Oa`kJAKP~ucpFS#X7rycohh|xtkHX z$KXe|yS_uFPQ>`0ARHV1NReMvawqWF=4k!gSFIv}k4kp#_2o^yp7*KO^URoOWryH7 zH5P0M&rDmdptp3lq&@z6RGYFe;O*3j#s@|mjh9AM?y|=m9jse9TqPD;$emKp{3z@U z3twSexhE>6w_q(}NXxiH!bqUfIl>LuOB*wCdPg6tBp(7kq;ElYBfuU4xO-GB&WUEO zwH+CESv8HN4A48=m5{%wRlj}}XB}2FnbN803zIdnCp5$SLn9?nEYY4)M?0h3E8nU- zi_BrvZ#;j^`Q$CW1jwa3lDUsJN_vE~!R}1@>3f7KS$~yemP7EO`Q$|xW^2T5=OK(%ZlWJHuZOC~ab3H?kknZ;? z^JvVxu0Av>-8AMWs&BwsIH4MrEqmc@)qsHt!T3R9a`k?TtME1A6ZcPH%kZ=6{Vqv3 zC8mo8a%*OsUs{Pzjtna+HBuzM)YG^O!a%GQNiB~Crmp8Bo~b{h%?qr*TQyZs-O*HO z+BIB$i!QeBP5$$Ob@V#BS~K1hEjw8#fOHMy9lMt}XGG-EawSz1#|GR=07gQ!h~>CF zQjWXT_uQQv|2`WosuZC@iP`Dv{Vp#8yr+(tnXvfikM7V5oVxU`XDnN((Xm-k@XhR7 zmIg$XY6UoCzp`N`VV z@9pTNvHpxNEcrkZraSv=fdHE|0}xI?Gi5hbZ{#v4O0qb4B?B#d%;e@oXIL)2*Z`#Z z*qRjLsZ#EtFy7a$ML4!Hzr@mdO3QBtxZjlZoBf+qZs6xE|JSp!g7Py)ET= zlRQjnRGzSv=G#+PryEq+G>%_qK~y{N$?L`?=g~i^$*&W@j!VuW$8Bd>C~5sZ-DRho z7JRq+0wt&KeF~V?lNm)L58ZZC*8T=-I^$k<$xSe0Iaj+%OfEN*K8j!~o7q*{QJJ3ZbSpX!dsoi%RM1FrDvN3(UNnu$GDCh;aR z`}10lV@%>Z`t2VwVvBX!RHRz&Fze<&4Yr=L!HFm_(Qud|_qka#os_)9DUUxpDv;~^ z#u$X~9XI#b^5XpoV+`CN{I6kNcWcFK8oJ2sa*T>bAnl`Ice1^%)q|m#HZ%BzdYRv` zG)h*D>eu)*PK1{4SP1LJ*8OVu%*=YdwvzA=g_d#YncuPprVO;|P}P&l*N$g3Jnbt@ zt5M_HXWXmf=cR*kk9X|v5C?`76J$u)ap5SLEvFH;nnQh&aXn=<)R=E#=&F0q*d|F6#q7RSHT;7u4u#b* zI9 zgB#e0VnRudJ6*o1Q@qQBz0Sxp-eab?{kZ!G$S!h~j7zK19IH zQ8gjm=*?KNyLtDAfY<`f!WTIpDXI+8XwR#pXSpQ?+>ZCeUyVSgp*K6-!&wBbwr?I| zZ(45RKCLF+llJb>m?hpat;IH_;XGDu5Pixk<4IBrgK?2yM}?c=U1!xp)p0>y`qmd- zM=HGU%^KGA~i zrT~`YKR&4%JA6}Yw#{YTf$RDp&+ntdq`#6_B6DCR)uEg{sO!vd&V|~RJ={<&i0;Po zq(Yg?9H&?a(Oa&~#+Y0 zC;WH!O;uVd-0Wt&5)$=mtP6TwAD3FLU3)WvtKz7p4#T0vLY3>qAVi<8e@@$wRD}~r zWmjeH?XFy9kc(`7w#(F)f~@x#_!R4^D_eIHYj3Ppte{6ZP5Wi8HL-#*A=h!e203JI zx@b{3ktXwe_C4bAi={8cV4gbVZjU%gZ`yG1?Gt~g0IuY)U81dSncds?EUG*vYTg@fD`X*tF(P_N~C1~YkOS*n%$~EbJ9XAz8fm(NoD!n zD|n}Y*7?Qp$U5Ai0tBEx#k!p|yUzvz3D8}ph?0;iqz@;15?or#fyxPmT}o?~oYyW1 zAf*~o*bqw(O%F0-_oxm9o?3EV|HGgBY=5BZM2cnml^dZa9zwDsGveN z+RWk%)OU(#tr@}dmd&_&zi_`fAko%bcBbo+l2=0v^-h?8qtZ#M`XH=kA=`$2q&Iv+fgZQGC)X9V3Rsfh zBjqmjS3}8TlbpUrFWWMtEhI18dG?T#(Yk#|HFE0A4(aw4M-$t8Qje9;^fuCoY{}f; zXjr`;=dcBl`)FT$hCvOR+5?}?hc`DuU_J#><+aKT&eifen02!bTe6=vKxN1vQ-ZG8 zY#ATsiF3SR*OgDnwuLjOUGs|jy|AsUIFTM)u;6-wZCOs823HBaI(Xb#L z{6_br5GmWCJB}~S`QF&<)#c#1DXFQ>VpW@?ZXFPnTrNMT(VSu0YZjH=#qBL^j|Y~? z9xA0_kB)TFmF?40J1*<lw3(b!GNMOcZlSlX0(RfpvX- zRp-mjz|Nja6~}Jhj&=y^e}iapKD8`3?kLx#TiV=EO#Ys~Poh%eeXa`N5EvHu_}J>( z2CUZ3FCKs8kGXCeC-1~YaZPzTi?Qk)&u`6z1Uc@y&@`iHn5k-R_f=&&Cgk(zBX5<0 zEQFo)hHdE?aO2@)8EqL62wMEnL_eiyjb1aQn)nhN+Tf+s$6>w#Zr^ergTrSh9j<0M zHQ((jV>HUx7-L<%?luTDwP_om3JRKCtBQ67KBPS)9JyCJ?zyFj$6k(&-8w$^MBXE5AxA zddE8Pr{j-36b2q@kW~dz_T;G||kk;}b$4M;VTKH|0fxfgkAw}wDhmq;a zbM4-i#(RS6CW2C$_z#tdUDUZo$y;E1}}` z&I`>anG>q~hHWHfBQS+k4Cm-Gk8hw(@xZ_840R+#?3D#^8QmprOnSCnQx2;i-Zt$Li;Kh*z%yR6 zM@k@%+-z!%mvjruKzE*TmJlsy8}mm`+Dd>q+g4f)P_)s#!qnRut%2jLo3GVIiL!>- z+(L??k2VXW1*X*TxYTYluY$!4IF#5#a@04a`9%(Rs5hxL3e@b(^q7?M*0*m{(-#lQ zP>C$8Z+`qq41LjmsEuEmzhhHG7yD@bec@9IGLid60*}x1S4PLYrq`TyJTl#6@V;WI zHi0sxI?WR{lVo=K=$U%dLl;b~z&`uoEhnp@f!Q(RbeNi=S?QGX8;gKM3eSxdpe(EO zk!kU|<@*FgsOch?#e2nC+BQ(rP_H)CxKc5;HusFc&TJdS+Q*Lv?leDR##Ks17yq^* z=b4U7vDC`4-*yZ%>_&%=nHF>3saVy>QH>0{xNckK0qk1II@%i7@IuAl5{o+`9O8pT z#$wx~#>N!d%+GtHwNvDGKj0}56&EhNTfv^HI_&=89S7p(=<9WI>e`_Lk6ACpV}?+K zz^R+=m#+9E_qt0(r*MQQmqhqAJi;a8*b(T+^~5wn4o+${XQ}3RY;E zWG*Owtvy{K*~O7iVLf|&JSnBuWW^hc6{f2wo4T&t77u;APTk@iitqKPR4)FWMuRUr zx3#+T94dm4V4zMgHrj73jmR`HIdV(m#mC?}JYUSvn7}5pSQLkviDl?ZS}EHZ`=*_0 zVU*3c9p1JUoMcumN^Lrqv6Ap+4^`Pki2^B6G&6DnSzBGKcX2qX388Tqf3lc%Ck}Tv zIkEv4i7&LbRL!ASo9X$0E@o_^Ybsw!5%=1#6A@T&&V&)ajr-R0Y>RKZ+0q&z?iWVcXmANHXf54-skCvNFS9%l|J-uQ zJeM-123ulXwJG91YM%b z@GtVy89TAl((>A%e1%Hj(ESn`f-1L5o;{Ak2VU*GU1V&s^BR1({Ema#&54{xs|qrL z%xA2J_@}eOEW;kK`yJ|u7|*ux+vDldh0*NW(P3Tr#HY`u#WgCdDHp|l&m^Ig`I;OS zRPF^+j5S*J@-p^UYH(1~^TcADLQO16kEfc(Sl9*>$(e?&e23HAU_I$m7R+?8uRt=L z&R2i+Bv_Q$jJw>ICCmID9)>v$@qUE(X$TW6dENQIV^f_+jag1k5LvJho zQhkzyf%$I{X_K^YIOYk?vb4USP2tr!wGWj{u72DF&khb%5}2MZcOTfgZkxhZwI{+L zVJfj-Kbm4VOvv}<9%%;_{$>%{&b0$g(hkuC-C8}xg5n_jg(Ur6-z*1wTGNH9=*O!X z@9&}aJ0TQvDL=nbb;~93yohVgW3e(REl;{yGUz!rHBoT1vhGP}>CR7D)*H`f!eq&O zEJhCFa&YS_3!DKJzRO73fxvCT;H3hyHnlC>Xyozo-04ud0mVJ<8|C$x1{tmKLmT@T z-k%j^xoE}E`vT4$hKb5}(u~JGoz&824H-mS$oEpp4HhcjL>Md(LcJ@eO>u-^J@>M=+!1$HvAeY)L4hj)Bmzei8+fGA4jo@7>=Yb?&F zw#2siqtwQgt;{d^OPFzhpE3o>4R@qvdW}=t3wL;+uV?p3AN2U@=~7T7OLmRdby}@5m*{Hu`ndX(>O;?PFp&ct}mM*6YdnL0VWtfuu(mpY|iDU^yn zUEL|5$A{hG{k_TV!3(3!D!e;!`HoGu9U45HUc5Z@e7v}vKMCy`!!BvD%y&5Kn3ukS z*Lt%6^C6pz%<~(s7VO*L%R7uR+i1X@+oPaHdy^KY$sDqwZ7f7n+n@dY;}%oX$1htl z-=eo)l(ew%@!{6?oY-BTkr2waqGoirL}2Zhyy!ly==dW=L-G+P?44{oCT z2D2$@mE{xecWOC551JYg30xQidpap%i^A)mlm*&aCTvS{alNpc}y$5F_;;K|xOv6&@#w4|q z3&bC^@ZGE5nNew9tTfslu06LXCP9eF>gI*q1r$(@Te&dD=>U2B==MTJ413 zf=8MRiOy@>W&#wBhk0?g)D(1B^sTnE&7zVSljF5Lb=&l^gGnW zS--d5=j?aTeLUY^*(BF198^`@)udo`_dTEcLGapVi>H~pzs@q~dGs-simRfQAx(mKlhGWa{Zx2Tp&YBK9;Mc+N=)#2WE)p14d zu%f87YFUI_5w_K~v4ELb&WAaeCifFPc}LPvsek(`)YASJ6>jm0NZ{ z(>8lH*|k{yTGoYjLX;BcKuL;yjXI}kwr~HjQ75#K4*kX;kPs?i8^1|0mD^%5+G>%s zoo3p|&kNDCHN+*{Ypcl>mGEqZE3G*=FU)fES?lN%@F;&9I(XZ;Cib=gn8Ud}5=K;9 z_`IS-X@fhN!yBnnnokNKSwn0rkK~R_%JHzIR8IlHQ$2w@B9|lKuSV@nqg&{F{}kpV zeY$Z<*U@N$Wu+L!W2&H?xRqVU*~t8|3)~dsuvkBI;+lB z=c%MDINwmTlpLu+F0jT<}5kp2!UQjk`c)KvC@LLoGU7uS2%(fNH{hx_C`X(@EopS4FxM z1jF3@#mt$uJGAgTvS;XxIPd4(pD0(9TJl=RVV%pSJFZQ`imfMN@KvK9Z?&D{k-D`# z{(XO1SZrkIS?|legChRNu6f4}^O?mD=qokyK6x#r*>ykXu|{Cxti}F~T$$cl_ij~P zbQj+tJUEO6SHk0TJYL1Z6j_k5ZPe+YT2)J2cif;9=8gVUyS}Vs>P8bG zr6H$-2IeWNpYVUIePeB5tCYG~Na}_N>Ot{&LAU;jN4kQ;oqN2iYL$xwsTmOW3|MDo zGB>tM`|sCjYz!IeI~(^&;lOVc$zv$@2W5#)_^9L#YR>XdkAC+j%*y>DHXi?vxVMg~ zvg`VV0YOTnK|qj_4ke`rXBM-y*SSQe_By*iOuQ?_E+=f8 zyFC2|nr0@h%3D(`eW2a8+_M|)EyE^nRT&It+9S_ITv9QNtmkmgs%4iDr%bla7(a)( zq*zdXvpy90db?-SztLB|eSHc3wlyVZA9N0$M?(Zh z#!((#HId|En`%Msh^EX^j#7E`94A`4LHvTqGkkKPAw{yI!b|H`J=-%+_LAZUrl+GX z^=0F2j6loGWiCKbkSv&-Cv!#SP$o2|mCv>eo>4T0X`X@lgo@(5fPpma!-c)BUFae$ z|7FXg-3YCgGLnWl>{#!;@n6Exc8i1wwPgofUY0SJ{s;Q!`Nyy2S~E-^e!qGXdFv8S zV%yxfi#~t$7H4BMMLy=R-Ns6)tMCQi-sQ&#(zC<|vHddEtu;0kZqrY6g6DdloPBvZ z(DiKmj$2PD!YXn9=G#8*E^n~rP@Uc{m#$Lk^|N4z)b(x^WrEh`z9v<%-nh&DpvkV= z#|VQ!ryYh>yM`h>ROy|QnN zcI4(HDDdH3qHP!vo>-fcAxNA%Z(t3qT4}_8s5e$Kma4^vVLuYmCEKKFHf_>|sjSS(v*sJQATW4+^7 zV7Dy$t)7NpN;mZ7V>(z&ds2ed>u*Yjp8?8=KNmj3`&W{|j|qkUW}4jr7832C#{Ybx zEV3Qiqt_GtelTv|!}THJ(`MJT_^CdP_mMG;2Oi?-=_krRKk9a2)(flc)MZ&iw;DbT zHCye zIOVmt+XO8@+bP3Bb>ey$Rju-mPIE;n;}vZlT;pWf1TLDjxCCXYS_~WkjMiTnx&c^C z?~G;K(Vv;&tjvds|6l?BK2!j$pn;_kKg3H%|IN66)qjP=dXR@>{?POTYp_?*>XiaN6bQz<=f+6n`0t1-bgk@!~>iG zWyo!__3JvBws0YJE`vH9qxau#dr?lw7itMaVIxW-y6n)g>A&t^(nbJv(sBr8EtjA8 z?`9j1dN%cHY2c(6-XLydn7L@U&3rSi&n2*YG4~u4RQn27BSQGpWui8VC=}zW9ZM-E zV-G@|Qpt}-YHjFhwIz-HFU3uhN{Op31^f7RJuhi{Za43On{Eoab;@cNnwN_y6Ze@a zIw_^nH^^Y8J0P;WA3W4!W#>hGJRs1>RM~;RcK*0BM6&UXNM;ZshxE_TvX=O%rC$)i z+Z8JfmmVaO&{K8#tb%C(!WJgSMJP^V|013B91%vOT!%8gTVLNSA`^a@{Jf}fLH$n( zl<~;6)L4m#)<(I0Ws05BdqLfWPrMw!5g$?OBNm^k>&gFWXvc9&5naT3CAU12xRemA z&>RvKpYj+J>@Qr}x7sm#Qu}yXC#TxcmQpQ4Yqkcf(3jJ6YNJ3~dh{*gSwpE@_vp`V z#~M5SYv^wt5hFDC|6IZpVnu;ipKQ-keRu|D<%FHh#w)3EQ3MGH z-zEUS$21-B*o>3$B%u_e-3E49iVLf*JF{BL>|P3r8%>}v_JC1HPv6|OlEp81<8D=) z@*-7ZRgy=AwO#O$#an#F-nw!1DIJ-8Z;%)^$_v!qVWo75Y6; zY$=Ue?ot}}c*sP8{Gi&Ag>rHRGx(!RYq!Bptrt-QI)WSSFspGopVC^AocO~fayzT; zCooarLKM8(m8t(e*tPy7wTvQ^<%KI(aufsNw)k>$WJ{FK;&IMy)r4lna+BjEy?O;K zVXdeK4s@q4b$$hPt=VNzqJ#HXB)XCekH>*3I-4sbu!9taNhzhr%fJFZmYWWYlD+b#Fgq0y?)df5P1ZEka=S+%P%8`aV_QHZxAyaMT z?l|3z6qA+3Ye?`YRV?rXwl`=oXTQVE&!xI(06BRh4~LDe{y!N(ZutEk($lE(St9JB%m_b?)2C6cV#RhAJs3dO zsUk34X;p8eR?c5II!-d?f*aF|iWTht5-2~`M=89g$Yoy5kuP*R7v5+! zQcvl4RL9uRgzwcZY6oBnJeNDGpHFoa>(3oFMgyYy*pHI=Y7c4(PzVaPEw(wu6-Q_y zY16Bv0yQ0~NrJ9Bd*|X2e5a2T1|He%hLh|FU7k43d>(5#0%(7a&`0NfmIPUgp1Az%Gn2uUl5|Ah&2BJikw(-uDri@1sS~8K70PbcSNck^!{1dP zQJ)V$v4c6-tj=ak<9!xxg`>jf+GHE960TQ{<>P;KrBQ@3Hz=BOBqqPI(sa)#+%3Jb z9<92w70Sz+qRsFO2vS9f{00;d9D)xP-DuVlJ~ZrN4UM;jPLGso@A;6|jB)4CYk48o zM~Qofm&Fuay}tlXGSu27<2>AsM!Gkg*zvY6$7HupMoTbF`Zf%jnd zRq^F!26qtJBxBDDgUGux{-*ipZRYPYVac*oKC~Y;S8}B>cdl5$3 z!ZtH9#@kuex=(DPWO>H_v_GNT-t#C?FJAna$IU^-Sj`?~?Ov13A(M;%K?9Ium(bPE18>;p`nH zv(?#EV?&jBF=}C+0v!rWst4+7#&JTCoPak8OpvK2#F@A6tJnPk$r!^mHrB)W_P5sL zSUu)i84YJv9c#TB6KsYu048$rkk?wY(Bd*HPL8alw%)#70SCKp-l#RGqH8sRvFyh} zjQIws(ul6XgYe}|wjsXRfpV4@A;O$sqx*nYA7H%lq)f20YP9?KY-bSQAZ=X7!-&pX zu5Clqo!s_LYkS`b%tJY?Hx;JQSv@{ZWm|jBA$;xJr-ODa5I-V-=340a44`by*}btS z%EgABw7Ter>ZslN;6EIgwjFZrzp&Xh-~DmCR`rRhceHkl4W478o+(nHdz3bo!$7>4 zIt~Zai^TG(-+(OqJa^Xq8NVYw*`_c1Wve3O(7LJ11X$Ma?F{AH!oU(@U)^zPqyuU^=+5u&-)3#P#Dx5Q`#yDSS zrS%<_oKh=gcDXlrB~ydw+1)sCZHyX|>2_8+`q9JEHi%qHl}~J_B#t&8q%uo^vt*Vh zm-zy!8>M;WFLcY3IL)S0#z`|cuBOAeT)Ga*>CDu}mDQgc#t67vXC;SgUG_$euWQ5i z7xw@N#ieT;vkU2u$K5Epnl(n(q?$AiGnS_%6~avxWPMOUj0D;|mjQdwj2z z9W@W|I^~i$@WHI=5EML%5xY<+kG-1M$Ma^HKN7CG(%*7ng$I0essil*d}D$pe1^9c zBSVt7izGV^K^ow~dXsPWL}b+MJRM%<{O0AoX|Gh0Q_Al1fXN_5BieaN9oNN0k8Ue~ zqDcS1+Snf>f|yM5eUCSwX9>UAGxWZC$5A}(Ry{dBk9luk$l4IS+@=dmX9S}f*UO{M z$(whItKXn{%zT&JwfyeX^lWZv*PhF=pWUdg@wiK;D}~3;?lz6ui=@R4V^@Z1H;7cO zFRZ#W$fQ$O&ndOBM0so~a!l6qq=1~QFCD$!kK)XIeqav8)ICQuMeG`vkD4-}TS?A| zCSh;d_MQT9aC}}6zO%2_d{&#YyLd6j0vxPb4=W!Nb{}n?Tl}!Nm)l2%+y~WQtl(0|))h{&=4cp%N-dBNy-W3eGf-Tv^3S;B}Ekr8{{(oRd#F zc@Uic({stL<^rGKTbxRVG9l`z}-5Mgbv768F68;0}u5Dyv!Hb;vLdkkokweL&$sxQx&e5k2!Ibk4MGrf6P4G*N8F*44WJ2 z*f*#&m_v2;@E-rNZxEOp==JH@_D^SKg=w{p{1VKokEA-L0D9450U_T1-T=Vg%`f|= z?}Fa1*Tv2~9IP#?d%wN2+$%x=)PZ|^vM0DylCsgmqVUe_Ij=uj8bwN~)+0CW*qzOHOz(gYR?vR(n9>uM z%0BFK&UH&o2uMd_}U-#5>h9M~T|)9S7|BfU3TL*7nH&t?rn z>{d)$lJK4yS~TptT)nWTW5AiArP)GMVdYzyE!_t-o+=!1sq)iigI@=E51(_)ae&TK zdZxwi(GyLSsC`OZXL>M!tw{@t%j1=Ms26`v&u?Ht}rXLVKpdqu7R~jfzQLt%UfrH0^m*cz%z|RiLq$34%z` zaV`s-iF0fb1m9;e9grOau1qmG^=~Ko9bBmQe0DO*^3Z@vY8(;*77A4xFVfO0G4j4L z9AdtsGbwP-$wu_g1H2@j6*WUK0`mIjffqql`SolYWtZdg&83bS_SP))#%}%?8S_GA zlSJs(NhQ(p1<+;%gw?;H#cGg9#~CpJwi7b&==_Nll0DC=JArpcXoT5yl}9K z=;tT&P?i>TueHNzSlqX>))%l|ll0${6NB?Z11{*e%tx^f%aqdh@7~b-Zq`_Z0;XVA z9#JJ2TkK479+qAd3=UGwt^E1c5es-~T*wmA@SspT4KA8dqKsl!MhwnJUM$oD__LBv z+jw)8tV-SX2Ipw8p(#_fbQ)+dUk&fG1LJQk4_v9TN2HhpQEFcf?E?0%Gv@}>U+vu5GD$d_m%J&u|l~X#cInK8(sm0xtU6+gz21UPT2xIk{GW(y%(JQfd4R*r)jRXHL{4u?4&7BF;XAf*l30@@;agkqdBp zcc)|6em8$8ejW0f5Hc$Hd$;Yl6pFq9ubx)XfB@KJ@j1WDK$eig)tZhK!i8f=a10q3 zB97pOeqX})o!li(_Z)4iT8I1oWui%-PGjGAfl!>~+wcAaQFC^W@ozlNLH~uBJj@tX zHC>8$+^#r?uHW&ilktkX80ce+`rO|P(*yPLeLV}Hlf4RbVzS2;`apR=))N&B47z&PNX7tQvu4Nd z+OY9&X7S=FbT8$$UrBvP&ap_ouJR)tHH$g{jZAtbEkPqF_mo8W?SpzBLyPv}yB5R# zi_x6fY7%Tl8#z$NJPP8e(p{mAMYM{M60LSO4iX=?WpL8o5gizUfCzq z$3(i#Qe0ovZe2wP_nGWe1Aq3!L9cXXo!IBAO~J;a>Ysk@7mm!k)EF=eV*;yN>sh&t z>r~{KyVAj!ex#-D;Kc@(l9lOkD$%*kA)~FJL+{omQsgyIt*kkP1!IyvTy`1O^w@nU zieKfQP%pTjp;JQ1K3>%EgA+YE0wAs}-$tcJ}cz9#1^+%IknXl-slCx+F(0(N6D!8*C!9BRRm_(EaY{CbTR7&33{C z5nOi5y-hb5l~O3@5=0+RDVfn zotr~FwcFUsO8Gm#n9-JK?nA>j@-47onb zMeEdu{rG471h3Z9R5~hl#B1NCNY($+@vpi)+g`z-mm8bT+85aQQgd%RV*b@y{3#w35VR>QpW`@hXa=>7a$29R9p;p~4 zvvU%_d17wW9fg=^-R>QZ3NlbwH?|B(Hr|{)M|Zj1t#wW8e#KO+-esi~=7dz0!dn?M z{x!qOhJEX=SOmGR6N=KL^oOl3ob53Lo|7<5g%OkG zyxxMovbZhnw%Ytm00meTla~k<63GH}S9dh;dQ~zD(;Fn(RFh6!SBp(kebM-5lRPcz zC_-DxfBjZArMScr^Wx!KAC?w89-q}rp~&zmaV9c+GfQI=mghNsH%cJy5%YvFI5&Ju zT~9sYF^z}of!1NYwiF2?Kr<=NgRmV3n;+1|*@KyHX!A~ zxAYoWiI5;(Fj*{Zm_yb1)F*C`%sXMu)C@f9UkhQc4K_V42eZdF`!6X{TF}hglk0_H z{0@9(RL)a2n!Xk=;9>o|$IR$skV(e3{1v z-ih{FFawND*!s<39BBJw9q9KV*0A5?^@b^u*-6!%Mr|CO-l($Kf6@E9$xGLnXsa6C zOrr`?4U-`ejw_iVlFIDzT?af0G?~2tkG=VEO0^{A-4^?5OoCeAQ~IqMpgDrwxtiA> z48K_I-v8v{B8FnMth7~6YM!)hwI7ND^+YQ#8U$Sk!`iJCYKjCB8MiW{UBzTAX@5ti z@&kkg2yX2+HKsQiR2dDEv*G6>t3IR!uZKWd-Wz?b!A;>0BVU)~2yCwBq)bSr{n5G? z`5B$EHFhYINDo0A#2Uf=vgc2_|Qu9tar)txl^%AZU@J(Dm-D&_=(D|h9 z!F&o%L=YSEx1r@QDgrL!@;g%c5&&*V;RP*`YC6NOlCR$Utmgt_!AFu@uNg4oZYE|^n=>pJMs z0H9z5`$qX>{wt<5^VAZ!{R=yqg8jF-=Ub0#DLXl;mQW;>Sfi~!Ngvd9Im(SSIgQ<& z+X$3*d3tDNT>6+`aYf7`?{?0ZZwOTO^Hw?uT_i1kRB%*-#JFRm8W~rYlmq_FPllNQ z_7!2#g#?*Q=A8w8*(GGWYP3sxT=N-}6Zx0edueUTkq6n4H0`k)fYvr0i2(ORSWOBd zFTW~2c?q`&Adi%hq(**Cx*U8C8i3YqD27|{mxCud1|w?I(&qMy}tOB z#gpysTYcCDGO%lnjQ-kvK)^QtlakI?npmZ+neCF#2V_ZRo4J=C(i#oU_ERcZcb(cF zx=cNjacs3UxYo+K+ZpIbT5P`lzK15e zd}Sl)!^zO`Fnkw|c!8Q}qi7-z;1ALWoii~meJZRGID2dIfx0qn&%%j_Ohy<#IC%ipKFKd%UMU=`-N<4mDKrrCJHak-oX05m|T}|v!(@F zOri@H&npvBm0BHHtut12)xCj2wQ63k zHBqWypqI`9H%Hsg&}r))yN@{3l^h^h))xxtDGY8*NrNS7W-gTlg+R`SKYI~mIi^xy zT$)J1`3%OeSO8;R0@fWjE~V|E*za5lK?{l>f+tO!G%N$HhzT+fJ0i*a+c4*V(BcTZ za7Vuh@;W*Lrr#_|m#^@z-=yNUAppgP56kTMYucuBA+S^pn7W-JMDnlX&Imt(hXVyj zr2L&&068#b^>sNN{hRuNqQrI)H|dmTf3N^>2(7@|YsdeOqf_|&ps};EKW3l1zJ8V| z0o!bJh;6hXNWUqM;NgOhAlU3T(oElPf2H4q^V)K*aAE1U){Zp@B7$dHIZE}gCKni2 za%Foqx-vAN`!x=@&x#=Xe<3o00+NT49SkWi^%YoPT&c%Pk#z(an|KfWs*mvhlVlEu zE10ofU8IkwEvt3Cu&Dq&Oo-e0RQUz496=|3IyzVyt3C)~CPeKpdrKKu!pf#U_HOcl zX*HhT>jPXK*R1a6sX>ohL}c*O+BZOVb;g$$%qgcYGrZ`z=P&DSjE*^tN02scmC*1S zHBg$)M+lFGJksORYBXgCKDrK?(i5!z763`#YW9bJCGs4xp|)>DayI2CwOFXwOsBF` zQO~L<{hCX0>vx=^vH3!FPZHIrg_D7!t499wcKnIS_=jtg+lj>3*3xouM!aM;uIGMc zdfr+zf~SSMjmI=>$Fl5P_EPl3Kni+6dcW3TkFatVTmrC?;H|vzy5lUvTJ(E~gp{JB z`1h(MBFh6klsmf9YLlDSLH*n^R&lAyAO=_>wS46xz|eY2GitKqtceSkYfFrWp1X%W_ZI&pH4#$tO7`8$c&ec4n!ya`OG-NHR#4=PV#&w6zVeqU( z+Rp)8ixSc032vb{AE6um5lD&hcR5XYT>sPBQ?-Qk1kHRY87U|X1yY5rzZXV}=P!&s zIam+e20A;pMMq3KPf&)m57uHxHO5r;YbGZNU7=>XEwv6U->)*$@5_c1jn*F3{h zFK6xp7ie~XU#XU)u%<9(axY!QN=!dxmO568LFiUtZCzomgRxnqt-;AGnv|lDUZJg#O8! zBG$2dTQ2=34ygMM%p;miE%XeZJ)O(7>;H3{6mK$)v`xV7l}Fix$d^2CxR(wb|>h zF5<=a%U%*2zE>yT03!GIM6iDfgSZc$SwtNR5xL<6lA}xVFjl3JOz(gB259Kv$KW&W zmjaZAoNon2u}GQ_p2IK@{{>&f22dY7jvdZDK)JCbRrY-dNP_hb5T1kug8DvLbrm~O z{u`hNlWH#b$-x1oyZ=frP=2{Z8SVer=r|1U!P`Fgj8VM!!S_ij3t~e7x>#hy3Ru|| zhPtxn$R9u|{xB(@3M}pXA-;YQ6T$KuKT-dma`E3=|IKv24RQdn;n~KU}lzo-3jn#j~YD4t^8omx(;7}?|qhKj+0R(zK({HJidfl1=S3>dD^ zJ%@tpEs~+P3=CzswVn6#AKy7s1DYbr+56G38O7>OU!?>HzDx4gVZKNR`MhcM{H_IB6D4NGW>%bMwY9;jHo8 ziN5j?x)Q;HZj11K_dZoai zgybQBhR$#3?zo`HK zkv|vdFKG+_Z(jZP!s4_qL6C60z}#2GG<0YZ-9d1ArTr*OJ+KVg?+<}?kMPB2Kr?%E zA3p$YC%aum!cq(is!YYWc+Y9{TTyJ5hB&QG74etf;JLrX_!Xm+3-*RsALsO4<=gLo zNV@&b!#)Zu8Q(WE5b=2!HUFA^*cdVC9=C?S@?#VTkis{}C>+n>@Bds;-w$W4nVGi8 zU6~8<|FaR{Ol*{A$hIFe+a*y{V6aa%TYeF8_G$4| zyCzBwOy>j;oQr0DL3!p&*xC-NaP(e6Q2w#mcO7&a-HPJhzs+->3bs6&SO z#{gzHM^zmm0*0h7eA5?(2abOOgW*7nM=+!12Wrsx3mheb^@RQ-#6nsyqkx$5zt|6B zl{phazaI$ze-R*90MW?(^sO1o{29W7WehcgB=mo?Q;`#XqfM2H8XQ^z(4YoI_rH=W z3IK*~6U89>*&BF4{z-DCDdnVB2n} z%AVZ314_^WMCRw*`YKssXqh+U;jEFsj89_q=(M(roi;CP%P;7O;J&1WdvN{w$5ofO zhwKB2_PX|%SC6KL#>Wy~Xk9jQ{yuVgo4wq;q8v-XN z=0^y>oO6Bc{h*j{FKN$s%=zx|&0Xdv*KQrm7R|F-=@201sGR8*_<#-H$}B*0&Kur# z(La(!917>S+*!z4>@Q3Vn@x6ng2c{;;;X_oH6wGSZ&Ek4QB-il)o$oPj#jJvmyEq1 z#T)^t9@tQZPo3-~qTr-1I6)(>|J{@vuelp~Z#;(NivZrQMR9iYeDXSW&gPK4eX=XV z3wK&bCXh(RFzMG^kZRhmmJ0r(alWkc0=mzM&CDYxW*cs|3$QSQnf}Zi`Kg^PUh=Pj zg)8$=rv@E|NK*CKPgDo2bIKO#lB0Vcl-#asn6AXXJcC!-gC6L)o_<^J^buIHZ8RgM zU0Gbg0kUel@Tl*9BiEUqDHE8>PlVncFY_~n_Y+Thpz~~2Am3}`INDC|&}G0)_sj~X z|1k6JM~M7Y)SJmVyqjj=mb>|EnHMrVv%LOlW2_^;q`_L1EZ|^2U-HHVMRQs&wRPfnw9@K zK1AVQ^-BqXg!C*Fnq~RTGry;4m(F-T_Ym|Evt5g_OZ~(wu1aZG-yVfMOVfN}fVFOt zl?L!_^ZE4Lc7Q04dB?i;8Y%`e&IApEC@&v_Hd^xmyGPfSNgJ^&S^d$H4^buby)lm9z3cBtQ7u zI6uHe_nO1h$tzx;q97Ugt~H>0|EF4!eeXY%SKH%9Pke=saq{Z{fuicVC&&NI4mzG_!i<~1Iml!{M&iYk6ZdQWexQS3542&40Xt|&2{bNI?RHfm-sN&7RlxRi1_yJOXhy*LC;_5%t z<`l*86&8b4h6P!+ze1s=#X5scz4o9U_is}~_#e-@iZrkQlpXky{Sa_}{+_iBKfvNY z&ie1)FWf?{v&#xq{vZW-xs@!@_$WZTb=YsV9pWLPDYP{OD~lZnDH?AOq1ide5O+_ZYE{hAbNsnQ zM8MYghz*JH7ZyR`s17>aFpf?X0#N|1=z>-idC!#IC+kuuYtqYy=W`W$R?*r6J6i`N z<^r{8p8E+~q%Myt84>$L>ZQ^hgZdJUE~hG4OX1C8_P*0T(N_U3*^3(yBgz(~$-%-y z416fT-UY3OeIHQ=K6>T8RMI^&xulcduvh}WCa{dMtvPm|zt;>d<)#4B(dq#!MZ}-Tq zyF$m@!|T9bZ>_%3CvIjlL+z~9GNQo+d>g{^MyJTPA0`WUDZ(S0Z4>QQXxLW0LzFKU zSR4*WY+lsp=o)8Ch;!){YV!Y1;eZMe;blK=2}vPlhdD-@+!Q@bJ7 z?HK*iIENT*CWtrET{KohFk@P;`JICFw=rW*gHYSb;LuNM6RlCiLhZ0MXd|lDEMD9= zc%!?RaZXv#>p_c94{XJR^K2}>o(+PrO_Ec2z^*z&x~M| zdnqC5jIB}Jg1t~(j6V9iw#bhc>+LyXv{zSX(}k3l_#_hF_{$FEL(7}!rQZ7<{nRA; z&tH>DOA~-?3!vVxrFFA94}T610@S2e%jm*x9dU-RuH&+1td%+TPB(_c;FW?F;$+D+ zrT)Y$&nplJ^%btf85Z$uRIj;ZS+vvDh`9$a0|ZKJ?I)=XId0u)kQ7l7(Cf74Zp}9g z(_I}ql;;gDFV^oWD@9s_)AV~&4G^#j{R4rH+oQqiPEmIlh1+8KdCzSw=gZZ-j;InH z5U%y^x(p69LLpb2?OT09WG|h8E|U{q7E)J;-@Lmu+R$TE`8_qyLkU;{IO?9C`=Fnd zP7^qZ&b>i(6stYF9FUeAj|5uz7IN({%38DQAUDUF916L^Ric13rZksFI1oIqH0MxD ztTc_6;QjS$YwSS?NQiE<5w$&)f=LLoXl6QKJeAEW>>UsWor|#KL*J0SKQL390MO(oQJPTjcRL1fV=9g}$R%?=4VIVf)|6S`DQZ{B>V@%@0k*P6)7D~{)l zTJ_5Y7}c7Q!p$3P)iiTal#_Qx2mF~ibTxwB!RU?D@nI;Eh)+=-VF`@~!XJ;(B1p3t z!bvg4$X#Rbo$6gl6{lq*Y;>$$Fu8hU63}Bxw_&-Su4KS@;X%rvAwgrb2Lyy%# z_Cn*y$9d!qhb-c4ykrE|r8|^nzV+A-dyzh;8V&i*+fI(FpP8MuCUh+J8ZhEQF!E04 zgI-*HH2rY@eHrnJI5-?NiZu@H*@DW;g7o z^qH@*-y5^?B|DRRQfA8=FW^ z-nCkS29K3Kbf(5P!Q;S}asq@vzdwZ1&k#wl#2gC^u~Zl<54Rnc@uvlI%>4ynCa6~6zy9NQ0a#p;BRe6~BY z)5mJ(3wcP(BvLIEie_75x7%z3smc?^!h9plTqE?|tHE#e#CcaD_<*Fj*D5tE6r`po%{w%>P1j*190X-F) z`_;&2?w-C7T}CtyKl&&XLnv*G_EB4Opx>ehdk_U2jnYLHf0WC?AY+^iqf%YQ6`YDd z-ih~9cXQfzkYN3fivj#$G4+NrJnTX7`K9BrzY2No<&cRn1~@b1j9zP0N^;KDcp)bb zFb2wM4!mYq#SNnQIcQzE(zS9Q$n3YT}5KF4>0*HAAnq)O`#bUT$5Ly zH`&?Dmy1{nF`OH-UT)V(edaMaz13m3-c&h*;0z{Nx0;@1=ZAe`s8y|)uewUt@XajE zZ4jz$jO2a~QFHz#82Qq>O4X-$^1N3~^Y9~?QUPU&R_k+H_)tN$C1z#Pr8W8tyxvyy zp!k*yB6$yjak6QPyW(wlL$?yTU8K*#Y(XaXW$PSc7^QvklfTfha~l_!ZBS5SVx7X% zloho0{)m#j_3w<>aik2&-E=P0tqwWdNxP}|I{cFC%~1-!BGGcvsf6xpAJjPHvJ-W$ z7rhV(s+zKMk=`T`aW}aMSs&(T8@|<5L8)JiL>X5p8NtF6+^FPg`cH@wFpyw;VYsT7 z#LV=~K--;u8$=*Kly_xQkuO@k(!$~Y5z^9~;v$JFQY?N=Ll#6PpMMbCf96NRZOe6L z;m(W3=R9y0W$M9%PqyV@G$Y2MSy81ZdTsnEzK1+PxAo4K;yETQY3Y_w%h8Me<*1g( zL>?vhm}%wnb!GVsD*DPdhoca@fRPMoeZ-y zXnY)VNk7Q6+0DFm-g-7f_(CL3Oj%Y;-@60#g?}iX?M8>?i{PChA0+SwE;i}D95ouP z%6YBn^|*MO=#!LR?=yD~)=sv>$)tMDqOQoSCU@(l6trdW;0@weDDZ<$ccb8)_D)?p zluduQqZn7rn(esn_-IXxwO0Npmxt4fmBcWl4WmubIt_GpZW+iz8-GqioRJK+Ve!*o z*^%(w>^%>G2f|Ec`2Njpc(0HQpE@Y8Fa+f`c%`oA#XRGid6nP(8Am<|+%35YBptig z$dYPUeZ^&JsdV1Hi=)+E6hlnS%w)A`Q#c|_UY<8H@rBO3!o_Wi&&<1({m99d`MAll zOva81q;{AJf5Zmf|NIC|*e^>R4y)+LCONJ<7G6h;SIpbJJOrrnf>E=ecg10LcDj#r zTA4UjAH#qoTTt%)X^aTdR_ckWzr?&kQIrtr!>!X|N<`y3rtj&&O?h=*l{vQsK<9h* zINZBuXwsf1welPhihL#}AKXQUofocsH5T?#8v=$f}Gn?MLWv@ zv4I1BGjz47)+5xL4tW%6_w5fBptI%Bb{;jv#W$X48YgJo7^oV*Ce^W)Xh7GCv}b#X z@VqEU{7P_GeYiwab{&{O@#Y!E)#tJ&*#)vO6J(>|vf0nhtfgQ-S*6R~9EvJI*gVm?BcO3{>e$5qdxg3lnPJW!{% zH3nm*RBOY#DiVw+i719!Zq{x>42peBPb?LApb++3L^0C&r^gKyy_@m9u$7SPHC?F} zr!8J|lb^MDKOn*C!&Eh3$3jvDkLY{RJ$)rnrb=A#HEKaGs!wM;N)ZSwX3mJ^g3nzP z5=LS*3%z8V+Or!?5mQl-+msm>OF`5v_`zTth(rHF$*aJ~Mj6z=vegDXL$LE!TNrdFauU7 zU(UNHzlOa{e~OKt1@IZ|H=3f(-pcL{rb9fp^z&SYY@NQ!oj*D+ju`_li5li3FWfA_ z;R%fHsIKd=?oGYOr_Cx)3e{2{SIPw@lT^+|Jgl1+W~#(UnYaMgWKq8W^NyT+GDiZ* zF7YhISm6>NK2vkB0NzYX4a3aL|Ym#@H2Rx#<$_NprJ?z*b(B(Z<#qo*{HkrIXuW z7iHzP3_na|lMIV7U%_{I7S#}Qx62&vx3GQkl|wpNb>xv;d@wk}u~`SH@I;8fu)>eE ziD|N=m33LX#5JtG*TGO>fxZn-wmybxHlQiub*;dbw#sMQ>T6r~Yxl!(tJ#p?_S79| zcK>qTtkO(HE^{BNUQ4?B;yI0T)Ax^}F1b&{(k&I3wbG5P1`52?udgQO?y?DWZ`#YF z`_nb z9nIl)NJZh78&jJ@dNyxeoVRX#IM&}Em`{~9Q|l@-bXYptQ{96*{5HJX^<;|Zw8K&Q zw4zXT2jz7+jfp&O!Tt4(ea_yW-&`CWdWS>scQ8ES851M#y)JZB9sBHTw7NTX&DKyh zrB&s!$MtpasSWX%+va5CP9l@_h}GhaURWYxR?o#HXZ6zP=VTUbwNo-iy_N^zZ)$SOYSEpFj8+XA8yI2YQLj3dG zr)!{1q}n5Y1beg#RA?Oqr#R~f{ktRry5(8~kv+d=GGy|EsgQOu;Oa!H>EB+Rj+f~P z5wn{<0DGS9Gu|FAsB+p;-kz&1V;)e3+Vqj55&gwFh6m7T+|Vz*A8K2;e0vj^8y_T5 z=?8ooTUGcq=1Wr+o@UUWhz9*%guQiGTut*WiW3OIJ!paj8{C3xkl-@G8Qdkf6C8pD z32wo4f&>pi5;V9w!7bR}a`*7Q-*_dCwvmNyP`Q3`Y!F$-w+0V;|A{3~m03&T& zWG9B33MPyR_PZwcu@r``AkyqqoS^H@Udo_yajbNWnCpcQ?zkpQeHo3f=|7{G*H0fZ0p|O+Ht= z*yk$$r5YcUtif-{VZZ5ysQQT zK>R=Mj8Bc6*Q3u>|`dw|LhA~bVcq|f?54)q|P}yCR&*OqXRX!WZI^=h%2O?)9 zQgxokYac*2!RYhnC;c-RwVXANp|-~O#UM?JCpl$+FK_>1mWtrU*N+d>K6XUuz%k7) zNhbU*4Dq*K(NoFc69Y)4)T=^syE9P9MYoSjO=^Fgx3nuTT%<+&?rR@#lsr`HPbb1b z7(p|vTm8K=Fuf{#+y?7Zd&ftChudJ3DdZFS%brf~cy_CPS7 zsH+;vKZ*F5WYA;0BYcc^1OTM@sA+t0xX9yis4w)l_4MPh+s;^MRol5Pvh;C}Nf5=0 z%R%npk=K7)r4Hum3vT{?&-pF(;ESwo;L=Brmbp6veff-(BXFux&vK$|<-=2}g+^x{ zn~9Ro4yT(#ENAJSUd{#%7xmMI1r|f;c)`5wq>0Y+SiLDABjsSUXZaWe40O+I2YdSz zOjIR=I}o82w8YCM9JN-*)pfShR4?^aP?fN>Col>W69&liBnwm#%j!pg}(lCyJ@Kn61zW*3l`cTy(47REE=+nJ@c1%#)gp zy-%S3@Ii=l+-qIr(tAB;n8Yz{y!v#>K9Bn0y7Q#C%XnNnpGfSrRvt($ar~q z{UjB;-hS!*x9tL}#I=V=Cq9tjxEtcgbUuOa)H6~l7e_TwZ#zxe4Y}+Qx4XSO4tsl? zJ7z?n!Wss~Dxv#J9L&8Fybf@B1$XqM-N+QUES%l=moKtay&WnvbDw^r6NJ)1Te5HZ z&w1+Y%ZD%$WhgQu~w)KUJ25B<=h4Q8ap^09arH1eNa%p@%mlnU=#eMrW7IZKd zaAB@3pQ-%$-D%|LBjdtl@Ho*{PyV|TWSMh=X}N)i(Z~91=)FV#GINBz8~;aR3^t|E zNOvSbscgci!M2)vh8mq)8%B&o@a#5CHwil9d@28p0Iu|~=`)4*(U|9=0MP~33C zwNpA9Y#~41)IL6rK?ae30Ruu*Mz(v&X2#n3E=83U8q`eKcbCRT@9wV5f@dY+0zzea z%}h*F#L!CO$W}X!G31Iz+Ee_3iwt zebBJ>6Twql7FZ$41TsZ2L6InbNy0tmb}?g7K-}FPElo8SF&6qz*+gvA zlh&Z40zUE07x8Ls={CJk#e!l>{9|NH9T(K*Z#2#2GAAy|iU<%vEo|7B7UH55Yri2_ zSWZH+!qtFao8+GxhNvKZzvwVz!MBO%F=DtgPZPEYrZ3N5^h5w&yN47*-&N5Ft3{IEi5k#8+ zOeF#;m+Iq^>P7p{l7bH-PYnRNjlj}e$5)qG8{en$T`Bw0T*}zf_sUhCENPy0otdS3vhhL*SIU%t;i1P%zdK zpZ#1KZUiAr-p#+x5j8y#@x|+vSN*t(#&*A+|IXth;m?2F@?CkdT#LD`{r2;?rf8*|qPw(`#MVv2mV?lx-P9KYpSi@_oWb8x||L$z-bUeWM}zSrOEF89G`l4Yc+W zS72AT;`Sm~9L(8=VH}qzu1C^mdvZ;E&kBg*RN2iO(Es`^b0+oParSF894Q0w;oHdP zZZuo>Icv999v=R*9Np%c!yJ?4Q8y`{KFQQ>-I{&u8<6>PKHDyIyd^|@#!2@g=iBu>XFGB7orsezcFU}p@p*Fqz9FlT zH74|V$?ND|v7vt=9L+ZR=kSn3V<3ewVVCyT2B`z^vXW&}<2Ps8U80{PDyl8n_;VSm zrKSw$)Oj^llLl+&9Js0_)5=+@t%y&%xiT^|r;@}C5p9u#Wo!+kj&Bt-RnD}h8Eh-O zRq1n4bRQTVyI9t@87~&L4pgunMmuF=6Idp9L!6seVu{)ynQp$n8cth!;Ht z6RKT3i=R61CKUTNbe{D){=CM37Y20SbI9pN$jNwwbG5Si8BM35-0e4nOcJAXWh6zE ziJcA^SSH>uJ5{PyTWhNyn(Js#@L_^!Lxkoq?_IkPKUQo-YqaNWqUj*OE1q_mSIkYC z6k>ME#@>4jn!ZZ-m5N<%rVsF9&3u(V%i62v|9qbm)ort$yminPTvdOkk?HgCyS2y2|BO_W86d=F_Gl3v*~3RSrLGF3p{P(_X7UMS zVY2Q-(B3|*6IW4k#cT#&p@$N<9RMQ!(PywJ3+o-D6#B2kXd+ z>xISVTH)ZxDMFtH&hEr`UAL@$ky>8*y`hS1fUv841)oy2|1qWTEbSKt5Sa4+4NMXM zb4%ELQfj3NcNU7zWK2m-+)gqMlMB6D!CsKkK&2BLQ~*;Mrv@UhkS0ITEX0JG&6YIf zcXP8Q)6*}>P|oGNHS%wocoIoy#jxt`APn7|Dy7(JOX?*Uh-IV-rfJCrms#c>(pzov zmUOW(0@2>kyKFjp@GX}Ls~fgfoW${Gf{aWLHZq?2r_hQiO_;)@)#{mV*)l^kvnES+ z|H)Sa_s1|68BZ|KV8-KU(GA|1}REA5z21s6k(<4yI|T0dEWOH7O<`zaWvP;I7Dw-}Y0F=^q+oauF)Kp~$DuBQAO@j>&O2l{ zaRR{@n#*-;aSaDcQotDn5aW5uNQlFTCM#TZvN1p|M(6zQccD2dl(b~$K;`CQt#L#NkwTf6a6ZLX z-=di5q||dc;GrdtJ3KEvF;FG?am@)5X4)I01s=(c!~Bo8rL-v$PXILU%^uz-qZ z5RX&CfdrxvA-MKP zJabWDGFqc&_xMUkbrTest8!f#)7o|u1Jb5fBrHzM7|`g$59slrR%=7iD#KgeG9o7Q zl<7+@8GIcbvGh*K)olQO;x5ti^_l^_JF_N8jY(e>^r_{5gY8~G4BH}^RpxBxQ6GQvF}$9tNqDxS=F7?-=}+srK)M+3st* zBSP;r!>E@ArtI=EzZO0V41J1emWZU1`R%2Hz{50ew5}T)!3BB$Ej{{~{Br#d8e9E& zDQDY@+l>CPWe4`>7juCr0blfsy06T44$;>Ru)cFF{eG9#uO9vTyx%FiLeTLrau1zG zo5AlZgjJQsFsLS5x$$9zR=0uN$GE~0j+(`VSUP-G7DR4JBo_OB#x)!20~NFqtMM>u z##&ar+R5JUNP*_>@l{zhF*^o!t9KOmLFHsEit4jbJtg*CT~K96JO1!=YqdN6!;xyS zH)?@#vk!#x67Vi`&P%M~6{>!&`L(Jv^r)Sf&>D1Q>vT1M@<(J+HN)iST~qD4c8fjv z0&L*yUaR4VY24`d#`d$&aODcWFKyVlgpbbaCF-0C>m|LpdbsD`7jc7@6=^yCH^Iz0 ztb6jYtkqO2-pZ_twu&NI9HxwD$iYZ>+B6>@@6$si&{<9_1%Oc+JIo`h%aSN_k-mhD zNh$%WXL!nQq?hj+vtz5>P+W{r+pb68yc0^qh8>=he_*ohx6vKOX(tQu(v2SE+uGvy zJK@78&&n-m!*7LXQuazeATq^IVTRxV+az;J5i{%2EfK1B%pgCs$0%3lQ2DInf6nif zVilG2JUtf{y5D{oB^gkMf$FPeEIF*-<^Ky$u)P8K&u=1NsZ>#lb(CxN7nRAGz2=vc zHWX+59nh1S4N^P+Gvn?p|Ir@38D@*qa&(qqYd(g`HvDQbRTPbB_n~s5aKfA{H5zqq z;~j7x36T&}y+{};fo!mjdtZ5>TMxFKZhv^bt6re3Wk27b7ys+NYoE<^`p6l6b@xzp*T2!lzg)MPNWI4?=5F<< zvV4E4L7hw8CayLFFV7~EUB`2O7XA5Fw$&$YM|$jYZ}0k}_C+hh5?RB?>yIJ>E^Y5k ztHoMpro3mN$GB{n*($JkGa?~`&T?fRvX~lcA1eE~6h%ggm^UcZo9OP3&O?GpwFaGC zQ7g{rf^s-o#0mG$MexO$eOCeFI`zMGb#<@BUB;D#h+uBBcb#`$ev>0a6SDy^V5d4elO6(B0+ZI|u zd?TU3dcYY`}qEc-IT!it@CF(Nfaj>I#e@OX6jMSSMG!*BrCD}vYY3QZ{QJRwP|zs1O>Et_s87|2P1NiL(< z4V4JGy+hyGTE5S$${<@BOz40v?L;$QtI4?m;hAyc<& z#=Tf%*{;HSYrPvSrm<9YceeL6YvQiSLbF(+=d%ayG>Hn$B!O*z??xT}1p-^n4f@8x z0`=*OwUf0-EvQ1uYLixjuRH`q*FMwkX%#6)=EFE?>ra>5_sV)#?dKnIzhU97=*WSC zS-*}WaAJe&{Fq9u`{eQayMP6a;So6ix$ufbiTe77n%tDVR^j{N@_+=^RDV zdD-x=Hs0a+TnMw)D}pV&Vx%fT>gt%GthzpLhLcY9w&w0X(J@%x?_Qh6mQDQTYmK^8 z7dh7CDEUoo`{TWJ5h(6QW0YEEapK2|M%m=;a*qJsIii@R#=*jEy1gGZhG#-$-_omi z_cR;y<#kVB7G1S5(`-Hy(CPeL#Nuy-Rr1-?qtSa0txkG&zBbE~{$G$px=;WY;||*v zH-GeO39oRAfc*1?3^{~SREcLRyxui^03`0Ogk>j*2m-wHiKNWT8%tDT)@5-v<;sn+ zXbEvvaHL55?-HNKMSGFk&o@pZs6L2Q1_7h^b%8o zH3+lJ{xCe`?)ZC8m-T*Nk8DYH;PYDd@7^BID)s8;OA5T%D&IAC@nps$#=Y|@cT%YB zDU!_Jc>nFEvuPbb~{dK_hip(+}<9{cxxTVFT?!JUUYX-%}kmiCqD)?nJRHGkY+z2 zvX1Eaa9`scoiIU3Lf9*fN~|((iB+zaF_tDE{1F3_v~N+RRBtvJe+Lb!IYPT?j>I4! zmxP@+h~|g}?bdh$s!o}tO+mn(e617?X0B5`RW2R*a8Oe7<{(%%{1;<@hxfK7x%0FK zr+C46&}!PEdm&qSCfEj>8I1}nW$+}99+_;-t;qXmTQGH^iAc56P<6jg^G~CT>^xR> zH_O|hO8P&lThS7q)5qmuUrbd%VecubE~}??)Ms4^x7WF2>4Ge$7Ysnyf%IcKS)f{& zW#QX=7!4onNX<{A#J)UN0VgdP*7HZ}eM9M;$kkv0ri4t;$BNYS=pk$DdJZo*SlR_% zxAjP+z0jgz1;}#gDB5Y$Z|?CA0d&m}7X);Rm|IS7aS zQyF6lIahJGZ)u)2@F$&^3Q%@Xd3hK8UAzV;d}BhMbg$KL!XPUJT~8=|IrfdK8QSTR z1~CsUlM9n)v{L;k*G6QXY7>E@jvy@qD?6inI7*tIrAFD;am~g_w)37 z(AZA)e;VT?Lq;$hS0T?5QP?Hez<6h>`uWLqY51!*Vl(p}MW*&CP;eW@F`)l*`!VCD zz_%YF1Q6drtBe6&95Dk^$xwZeX|`e2B!gE~39uE;k!B|bj7+=DR)8)R#JffKP?_`9 zax;=1SFw|b9)&G|G39y0MkwRdfFDVEc1=l6zSTxs0Wx(tK#qQ~o3G<1c1cxW%EKAM(tvA%?xAGD#FEjE7-kW^t98OdZ8*@xF~5}Sq?sG00x@&P-erW8S$vF=rp43tBp;~-nvYE!Gbi~p%} ztvZM(q6cBisJc38BmJbGV8B6{m8eX<DK7_bKkc9xp0f82Kd^fkqn> zl1BJ!9C?Agd(EVbRy$JJwpLw5ysKL5kWMg5^%J7>s5J zv(y3d42mJ_*a@-bAtN?G>~`UoGw}`t^eGFaiT?EmbOoS(L>$ zGP9sMN_JFtJ7MXk#akM8eD5^#be)Za#4Pwmw`T#K8xLl)QH8PI?NUr_BL#N_07dy| zQ;h%E)cOlxP(YkWlLGpLSA_04L6ed#+}=Y}uZ|gcX8z+dX|jJ=wuD4|j60V~5J#5s zlZa%mJ)D;S2~8t}8DfpI53Bh1iC6aKDkbjz1<%57g_6X4h2JeJREL!jAN85<+`Z;D$be@ z6!EaL3!6@TJ6kdB>WgH5#UF-ARxJ+x-vm9fKUMh9o}fy?7snF@3jIsioL zGKpRLrBKxu_bmF`hp`}qWuZdP94^MGlwT=@Y6jKp2i?V!z$ZD*jp$v51rE2@L8GZH zK?~Mtk3*MY>VsX#WM82-AAl` zO%dCU^`XvtmeD}!K6AM5Nb>nU%8UfE!#=eOQg43VbT&|W<7P%eg6062kZL6mJo>I< zS3X>L7r^;%J)Swr`s%){8q{8y?z!2i^lvFSs5x4mp~+|p(?)oynh)` zn+@qT{5)`@r|j7^nkMtnlh?`f;dfSeHk)(e4?UQ)UsLxexzU{sHe5c(yxtz)341GY z5bCLP%mIs+g&F3%lDPv66GkPI<2={=w;q3&cEtaUG=HYufCq47XbX?b;dV`=z$<}H0VtIJDLQl^pbmnjgprT@qt02 zIXhu*fxIP;I}(1_{m$FxKlx|_!KjX(`V^zc9vtV7oXnQ_9nh#!;8LNCci1`xL=avZ zEnfXBIY)z62oW0!qMF!|NPuw7Ca3K0Q`mK@O6KL#FR1=Iq-3+45+Bw+QSh?V(;0=j z;wm4dx2Dw0D^`Q$jy*0T{n?ij8p>R6QxjM-Yb4qTK8m>SuYI4qSspTi zAhhplvAkr|elz9Y?8Xg;0cg| zDjx2QDEMvf;((P09nMu#FzOWc*`K4%f}OnN&#Kz_wtx6obr1~q-1R5Da@a6rJ2@wK z8f%g>u^O+#@Y0-73FoLJOPTa%XfGpC`{@~1|6)^4tYFiJRf&4vLv1+9Hx*#aan>9x z--U&fXw16MTlY<8Sf4t2(G`OjPP(rz8nw>u-=l^H-u}t!n`|8 zljmk9Ecf4OLS3{;3uB~n5TP$PhZ3m25Osf@E5@wAV=Dan8b<97^Q&0OZokO9{lW8c zwRt~p(r>enB;!V;*&WaFpN8)bCZVr1zbfokeJj6bV)a{{zEsEIlN2ynUsk9> zeKJlp12g7DhOZ36>e4s!wNIg6D5859asBxnofnX2K)|`ECu*U}Ty@CMK?I76MLXnN z(Io1COGEE%=ql8x&@&hzg6M%5@X{9vfC~ktzoiK~pHHd)$nVD6K-tP}yEG!wQ}zN7$He|NKRcCsiTC%|~X=qV-Bj$}wH)z6P|Pnt>BTIHm4l<8Tni*<#=e}FoypmN61;G$HCJbed4;HZ z%!ghq9#A&leX%<>zCNoZOTpbcvxs3;IhvAs_#&pw$iy%QdT&sBvzwhdP*U>@cVOO) zOvcs(C@hMI{ZE6Op=V_|NdlblsZojYb3Xf`0EYv|Tgih^8(hLaZC|@V%3q?omBJD|7HiyZ)@s?g_AmY{$;xg7PyiUT zNxMCTQWZ2mPg0SAM>q|#)U2=Y5x7rb^v`J0Xhrl?O`Zg9Nbebj z6YSzfQN|E{tRUHdr#q^2$mjIC(?qeC<2W`{X?LTa$A#0Cts+u8UmzEZaEe@``jvylGOeu zp$9+-oRvmUJ}Z&qUb^Ak%%hK7m?bEOB(tV-Y@_dreoadlq!ffk z`FhRlBG9C;rKvvor#h?um>3M0q-&%9;~9Tgq%+lc&WRQ<#>^%0-B;fy7KX9wW_2er zbcyrl1{VGkb3;w>_Hd(p?A;`3kSp7o(5a&WANzJ5sC>Qevbl>Tya&*5ObXUaH{{<5-2VJ<&{sVgxm@Z_MS5q z&j>Y$o(#ZsD5q0wG}@a(rSo`*kR~l$*y97Jc2vOw;5?-Y^9BMG0jmBE1TRJf{=!^w zmGt-!wu2ZujEz2Z?}$>a(&y|8uv_ujuC%b;sHWP~i_?$Hi2| z@-6Bk)7ZykmMPvDbHZLX(ZQ4N7pxJuEnrBINe)11kS9(^s~s-ivlC#8P$LNyAC-qA ze*K`@J&K~pgT>eFk822U(NyBB=N;aq1MJP~hjwMo>KJ0181M`-5Q(gyhsdao}rtV3MbRi||P(l3ED(y+51m0RwR{ju2j!0VCmfi1H(~ z5v3ILP)XZ-{Wjl2h$6o>R&c+J8d&HpdW#aRLE{S*Drx%f!kPNXrDheRA;$ zpCkii&AfDW*GJU{ZX@vD(i?2Js~%GLKm=Hv0ziAfe^#r&hXGYXaYrnmwES-+^>haQ-@d#$dX;RQ}oB;W%1!pHFVMIP~F%Yb# ze?iJk*sF<(O~|-LfO*#pXs6VP-5=-fo&`XeF+brSTdJS~2f;~VAoN8ELV;?q^gz*u z#;2)wnxl+3&oWLPE3~4_9SG49DMlnTDMtOB?7+jSb_4*%XdNYmXAT+3C@hbBLk6Za z5u|O(`L%(&BQ|d{$3T%f6BR1 zgoA9%+1m;4+uD59AqefCVpa~1y5i^agj^M~u|DRex7t8+!1GWGV&WigdnT5z-&Nm*FS-3i6$fm#wafd)ft_7G8;5LAJo{}zU+(_RZb5<) z=I1Bbc4jfV^d7mGaCfLTa`EZx>J|85UVGe)_O!-hxLvYgzv6W%-RV@*jSR-GAAW*W zhB06EW@86G5fdfZEYB$K3^EY_xW)^*)DpnB$kB*&0x|!o{*wtFPafLq!`uCBaq20x zvtu3f`}qNpo$n{&utx*6KQ5H+e;3M7R7YUFZ9^lHe56n+JMP|6?65|tf*_BRYbt5Q zTD!>D-LttSk<>7i#&NuE1)g)I58&GNOHphk&Q_nYi+Sh0FqrRVUSAm9h1e2bUUo%{ z!+5I9VS-wwGHKR0hIwC-=o`)3c)6!fEP(lBazXVsXw6yL{WjnMVx?lD(XJWyySR%R zY0(gkv^{IKWiLn=#^N#LZdqO%EaCzB1^WAb^Y#1k`7yY)Z?u1o(d8{4FQ)!jV57yN zhiw5gj`Hl>m7c8^_^}RbyEhrnel_3j@-WPkeYVF~anZ>_uy+0Vjg|vr@`-~56F(?U zXldfpVPpMEgNbG>T8#oD-!9L}n*)Q74~`3Uq3mtV<;RX%8dHDE+`o+xrPjp`B|9kD zmpgZ%x%y4FSYO5?)&Z?4MnCtY<#zt;J8nK-{8sBe;jC~swN?Modehb4vognZ&AH*= zXyLN5bR0@(E&{lbiN`2tL2s??8j);JrIZ;yxtqgBYN)yPgD#-9c08a(fa_m#v z5}$C{@0Kr|Z+$lunKc?*2W#a+!8-0%CZ0&gJxe+-sj~35A`87ECIznF=ot@HF-{eT zEaeulDSs*Bjf?QwPq*@Fa%_KF9=WKIx055t?xybRA8XThd!jUk)W^jR~? z6wpQS0z0Bpnek~^3!BlTVhzt(o_!imh>SQ}ejY*XbbI{iZr}CXk$5H3W4UpmLt$NEf(m$XH-y z!OB>~vh*B{VFX0xZb;4XRro0+Q1Kb#LY==4>%MAk@Qey!)o09Z8=vteo`bu;A4N}L z9ro3ulUctxX(9|FHh?mYo3SIu`DK|8#0|NVL(?Q?(3Mo^oUcs14N`$EMMiYXp=nC< zGd<@%0JgRdaHL6IYwkn)KytNK-|f9Lb;DJrTYwL1yCNb#nX61O$=8OYj7@w?VVKEW6j8X^-F!qZ>G>~#8b)F0>yvf3|}4SNZq>jNOYOx`xC z%b!y-#4DcaQCkFuk}dveA#ztM0H2FIMpV$IMc)i^apZ5zY)Z} zy`Q2jsMEUHCg(XgC37}({K`I6HIG|dAg(f%>V`|x?BkIQSZayO13cEEC-PqBi>F855K>7r^b<+98G_3{-dr zo=f~2M$?J7BMLh|CW}=?Z%9JGod{91$idiQ2uP?i1d1z32;@zSOL~du@9>WjxspP!g&3<%MdL z>KJvL!MqUZ+?d1qWQE}@N!CdM#Za0BKB-T|R4h+a){i20Svp}*1-cMpD&U@^t!TZPG z_jc#3@jf!^H~(#Ld*(6FKm@_%{OsdCQSR!}_Q!g$IYyqAIGi2eE3|>c9pTeWu@u*o z$+b=`pr@)!tfvcWTCR9G{G%L%#fd;*WEXCdHOF5o zdPdDbN6g1$UutURS=7*C1FH_Z`?E`B8sgFKduqEDS!mOLeg$!q*r^TVI2NiU_hJ5< z=gRgJ0H=eGJpH2+!c`PDRCaL1I+#n4+hDPH{vZaGV7uNmipIhzM-MZgCUIw44WW2p zMU=>dtB6zZsr!&ZmnqM1>@8)|=g4@h6emhFR(yuu1E(i6$U^5>dso}M&>8{u4A#t% zeuBL!^ao{+ThkCcY^FPH#K?CpuE$P5i#C!ACFJ;0(?D7b!!fD*+JQC&J6Usx6aqw` zvhbwA$l1#?Ct0_9;Ix4Bh(%Vs)?F`#Y_N?$aT(xc=RMmo*%;@exv z#z(9)30fG_G11<==BN0AIjKl^vVD1{(m@YXV_5owdVO2}wT3Us!5#&s_B4VhX$-8GG=1?w*>Tr$WJU8t5}p}ncz4e+mG~n?JVtsoWZ?lgs)BMWkAB2#r0ZgQ zz;u~U@)=o5Ur)m)F9@L2Bt_wB)G$d5e4ee6{Tl5J4s1{2;=)ImIG?E|YIU`KdfCL& zq|baa#vGv4@6@E^VI1PG{ft+-_Y@939U?M_Ya$e-wb);?ToDjZiQJ{?(5Rqvyu4d1&Ec3J#18z%}p7?2K^?0(vhUl~D~^;tM$# z7uUe(22r;HP#2VBMa-IB^fd$^iWqE!)iOn>7|{Q2(=2I33PXWDQ$TI%K5fd7jNIM- zWwsmMkM;y!wxF2=dYF((ErzmfeVa%?tU>zBKnIi|M#V@M2AQ%j_epXH#>{~vEAN8R zaJV@-MC7P$B@$iYbX!UriNuUi}zeQxJ1)_lnK;N*dz% z=DS1m?VbdcpD-=ht%+y-YyMP!{dO+2THuL@PN3LaIe^Y-68X1{%sd98rb%KNqrr=a z)LHUmA+oD6`57 zv0vqY#emiwBFIj<&q3q{10!*;#N8K3O39t40$LIDwqv#`tcR&t!0`mFh~oxU z9TtrP6udoH9QlRY(k&{+ObdZN;y7= zw9;j&DkCS2-`omh#nYyA(8!ln`CyeYPP#RpBI$B$St2)vEtHSfgQzS{hqwFn%Pu23k*y(Dg225Z#(STi?1(-yJgNdjU}Cc5QY4_YuVP``gPfZQqWj@ISf$&@2zxH)rbBC$37lU*V5NHtO zr6n|JQ_?9irFJ!k=|t8O+O{S}_~bi>O_h>n7W+^8;<^vHlzG2sJ-bNaLoIXm5=r4a^IMscBL53pVy71M-I5YG$jkZk=aORBI zUqN5V7_QP%?U2Ip1H^WVRmAiW?oq({})S)%?v-(Ngg0XUI-qL^1xZEe1K8rC&2hWl0E;ITf_O7l~mLxfJ%cX z>aoFL4IoWAKRoukhUg#y$>JvV|A%@(fXotN_B^sv=>P=;#(yMRjsRbdJ#rFufPi+z4SK~P!N0EHz?2DR^>o|3kC% zs-jL+3%q$CPm^0*Vp2)oBlO_y_Y$irPI(sRZf-iGln=Daxj9O>>O9pcQYC}mccmO@ zXEPFZs+~Voos#>Doz4clc#}6>^+vO0%*fs6Y+J&h#k~;d6iwqhKc9CT2i}gX!fP{8 zGnr;~KGQoeV z`JHc+vCR<*z{pX)bR<5L#tBg7xl0Ll?NmD?k2#?t#T`J7=o$E1dE;UYyG1_KegPLd z;0mH@PxN#B^c|bKeG}8>FrMhzRV!Ha%Xj&s<96lS?@bNJ$Z%T%Ci2HTv-M<#IeIEo zm`3IjbY-?2HbG&R*;TfxTGR@&yjGN%Plz7UoN>UOWy90%czF2RxpA7kyEG zLzRKOwng z=qqfh{$N9evXr6L>n6$WDob-1#wu8uh=~f zo3_TvtJ@VS^}ZDu1>8+G4%aALe1Tk^E_y7F9(-G-8vpQPY9rN1ncHG8cYoh5UGO~v z@Yz^Hp99|O+tcBg^KRmX!csEWuJ(4F?s`t%-C*a=q8u$$?ks_5G60vCt^+Opr@aWoEU84q;?752MeG>UA#;FNdf}`}Q`j8Il zdk>(A`56v#m^{$(n~moHIAE+`fiLk7reI#H5t^>BU1wgPx!h(X7tz2Octg+OsV!C} z>6=IcH05F8Q!KyR<6m{YS1w&sH6~qHo;=QL(gn||7*pTfIksPg0e$a2$Q{m1bo0a+ z!YM!xE@=a)wsQ_?qx|%};jbKTOf1Ve*6Uwz?($HqH=CpHbTOW6m!a2|TKI(! zgdN+v?vbEUxmN4rW@UN{$`Kb-?0*<4oM-9Bar!owCkpuBRSg;g+NpMAX&>K+sE3_! zR35uGL5##kl&{@+TGKRVOgDk!XcUYAXh)2kzm*fPbmXKCIxbNc$#ZC2MFYCOlUFI} zaiec?y&;h?(lAit%7@Q#GpR=YJG}%fc-`JMGjHays3G948@t-dp#ATYKG)fqfA6ly zeN5`9^j+o>%9#{hYu zKt+8aIDQXT?XLH};>(Xt+`6Enlq997oQid?Sxn78u!R^04UUepkanIxMfG$uQyh;r z!!i6Me~V^s?_GqGnz--xxprbOj?6$!ccMY<9EN|Q+bRTxlS1b2P6j||tPmB}c5;3P zCAYn)LJ~ty+LWWLA0$RLOtcSKOvOM;(9B-6MACZqT5~3g;)&soU_FplbP~Y;$T}W< zlgP@LLe#x>YrJLX%a*lV*Ri8@`i|b{O7wH?xZJjO@$8Rfxh{6NXx3)SS@E`s*^a!1m(2oAQK#6% z-uxB)n&IuI9`w~^!S6Wo1bN{YCHDm|rFmL3i!@X1!P1~1CJ7xLhBECXpLes-MM`L! z+$Vp!JKJtY~A7&T9hm)HbgjpQVQ-~+%nGSQ%VoDVR@pRlDR-|m1qwhYAtof+G+9axTz`mp2H*n3N!;wnZnzHXr7;B0qVI!lk@OB6dY zets)DycXQa$OsHyl|~i77)Z&_V*p4HF9C#W^AR%$Q#Nyr54Bp?slo|ub$EAoH zj`(YnkpX!Wzot7NqD%347CnbVlkys;lS!;2+WR2i54h6@cv0GOXcWF$?%~i!X&LY; z2?S3Cp_y&Asw`~4%@m@oohBohq$*x7F{{YEfVPywg5lz5X+?PbZirv@DQbQ$yh2(` zj9!Y5-}2gU=@I9V;4l-n0mw>54Bf#8sNAWrezSc7FPlfi0#`@VY(ElWO3MJy%98t; z3Tp^~ke*<`l%z7N&Pg8pqyan)aTh=W!vZ0QTLsLyq6>U-8oyIqny~SDIJ1CSnrX`l zTuh8RFgplGYl3=$z{+!#g7*sKmjbB*&lY7t7*KeFKf)nzNT?NnZHcnI;MUjq$NJbb zDJ+YRE7gh_HyBLNKb|1>GLs{{9O3bckw_9!6+PqUql3;@6D4n7*-X|e<*_>szw~~u zjM2P7k^j;q^WzgYa8OJ}!$_fyM;&Pv;9}K+Rfnvn;V-Naqa~rvIhm*$0QCslzUPht;!nz z4{L8773JE-jgk@~DJh*&f*?}TLw7gGP}0)Up}+tFBHhv*1JWr{0)o;FN=ZvgfA_ez zd%y3y&bQWC>m2`pQRjK?y7G6$&GPy2E}xSZVU%|vhUL0|Sb)bi%;spWgB4!4>$O7B zRBU}uR>*0(;ib$Ip%7{^k5*|{L?SWc3pk^ zocu#VTRiO26HO}Ow9c&xicPXE>TJ)v&FA+o3SCblf6P6O(y(E!;HdZV4EyR_Y5cV< zWYuTHSxP~geEkc&UOg+##6#p3*Ll}t5Utc8M3f`JQV}Ogbr1Jzj?Klh{r6X)V?u)< z(qV<}jSjD9UgJRxe)w+lg{Eri)n{KtShvH1|0(Lx_db@}$i$(Xy0y&-CKShve2!Bc zNcO#B74k$q(eKi??NQ%+PUYpgRi4*s8enMM(xXd%e?7`Jyj&ni?@7htL`6)L=D5Vt zQ+&Vr*;}VcT)aPRCS`=;fuMN|`jh@G1v+uzXh{2{^K9en6x>CISp!s3EC6R3`4Y2n ztm<>`sm!);tqm!3esG%=JS%~`!1wxFi@?*52BoeA6;k|FeM17<;v6PozWPC? z!aGHl4a)8!Slsj4dmK##hk|2m&Lt#qN%g!#D>^M)AnTyDpbDgXh=WG46wvSz9d1BQ z*G)vUE;sY_6ebVY8oaBV@Fp|$?x={yvgvR*AtfWC2l$&)LbV%7eC;XTP(KiF^t;?} z(?se#6{qVC1J3E})}d6{`^ z;{NV;aWli9RqOTlD*zO6AUl^2+mWw_mhk|w+ikw6C6!*e}RQ&zchvpyo_615(yN1&y9@To3 zQ-sQ9mhj#fuBn@lzL*T?!2d|J)idO92j5oPbS>hd!u#8Ffb691>_s&+`*Phzh?>&RZmMSX3TWH>gXIwaYm4zmaAqzD8 zaZ@i9AAt(4{&-HRm)@IO+k&-rvL+zNcnl*lCJchn+$7059WN+;7IG?R_besdy5}?h z@DcP)pSi9`;EPOE!E%*BRQn;_foBt>i=?UMHm9-b#zng8q(y5F6E+4^N#6>QjH5>P zI-uY2DyIx^`P^`vFGb~EE;ow+!5vDdt!&fyqD6Ubk!!26q@X$`_4Z_jcr~B)^bDrL zJZC}B_O8M0Io+>H3u4>h-Ko^Nm7)6!aqe?B8(VioEO&~|f0&PC-;Y_{+z$(1EY);+ zAa8Z(R2w~Z8e8&mI=v`UZ;r)_i{s|{RKOws%Da%-!R-oQ<-7eCgPSjjLADD6MuJpc zhqdZDMQizZ17n8ESJQ>hh|bK4ViyCh4IiZQH-7ZwLm4i<)%Y4T{}A7Hy1L%p_jxwi zBL%-8J&ul9e(TXFerDTUEWO@7w7&onnm&`av*?ieUD!#4NYq=Vg}2RWr(b)x>Thb} z^U2Ik(&XH{zOqw^5h-WP@Ypcjic;k<`3ZjSyjN5lg%>8|=m%te`AqlHj)eL()`tZh z;DWur5^368Mt)c+7HYwKME0< zoHCC*_W728)kF3RO6JyEP8GE;FF+^7v2Qio;Oshh7`0XUoK5|HF%_(P$5jkq(266A zpz$!-m!sm|b2UUH?pj`u3d&T zy1qX?i~QAG>1XMyZ@ov0dz(;z&NLzluTSh-qAxNj=39<*wJ=tK*t>3?3q%(Z*R1uxhUamH;`xR=`4-cm_V9vGEOlV`hvA5eD4CZ=W*KGd_?yRIlFnObI7FBJAy}>DrbhE!0gt zuQs>|-rNbr{KQ4IBwZZad-cgcY#r5`c5fL0n);9L)bF%w^?uyS3VIvA?qzzm+?0oJ zw-G#EVE65liPJrvQUFNTW4D|5pA%7Vx0o9hWfHqRdg<|Gm@~{iw~0lk(BsTBWvE?T z#;g7L1xh}|C&>MLi-$$1>n)#dtqjw$>q~dd#nDZldAv#iaSq)WN<^MKPNd0J!+fBw z(0v7Bjg0X|4(*~7-RlMjKD)MDNEu%aa++sIa?b4|4x#b5_ zH7!ujmj~rEaQ~bWF@9s~hP^ys+;5_d;zMy}6V^{_G?ZpJveX?p@E*ZZ@SMHvV{AH~{}~a^Fe_QdjOqMLdv$`UD$8=@+^J8i;1y4Hg^PRcw@V4Z4@kZXPDRvNl z1U(e?Mffh`)?d~(w{6Wo9A6hmca5?T!`QA!>Cf9002G3pJr&nAk?L> zQqG7UDSq2> z*Dr4^h=`Kt*d>A}uJ-h5f7gNEzV&TW95HPq92gM1f&BzJf!Teavt53q&w3Yf5vF2r zw$D3p^$;SLNpdT!mbY_yv#0p2g7?DbcT~z>Jry}$YQ6QGaJbYWQ_+L4SxgLMCb&XB z;1#8(MVOJ8T48-7TK%Zeo8xUE-!}!iT_?}H-_kD#U3r-PT~R#Y1ysJzl0FR@wxw9{ zpwz1hG$)zVmBN`daZN#{U_#UAcOg91;T(o3PF0{(Ao?_mONVN+ZJWVZvBrpy;h-zj zg&9~1MnVbI$ynO;cv-R|(C&dMRKfe{#YyAHC>{&<5CunUMz{Xh#EFaeipQ7VszigZ zwktb3W=aeH1U$&o_C zH{F&xpyW4?+XdBQveP$4oL3O;>HhXa;TLO~LB5uOsWeu77yp!A5DJZ2Z_~%raTfUs z8OOuls*KqNZk(}5!*BmZjZFLsi>G^v>^@BuiJ;liu za7sy#jZa~DJ7(^{)&9Qr;V=j-fM~l4Xvhj;?x3iXX{Rj9Vhgm6OOaeV&27QB_PR2W zR4I$I6EGA+mf$!;88q{>5)2f;Q6#KZEXtzDNgAA$SMGZ7O&X_y%&lsj*c8OoMnY%m zUTo?yc{l}ZorSJrnEHdhbl)5(>k6efkY#KIE1$px9=60im&DpK_Z#EpVprvuHq$-XWUTfj+g}* z^I=8U_lN?V(!q&f;x1^>FN@0hBL8KfP)~Bx&5bOb#x@Z58z{~$q29bKrHieOMlTb( z!*W+yOO?Y>(?nJvyHpm1?RQ$GuO{s?SS=!UBlJQwTN4Wzo~{aiwOIVAsx??|j{TO> zrVqm{BRr;|trjdw_m6^|C0&_&p+WC_pJ`I8$R1BTHh(BN6MQ!PlTi zp!R)6Kg-I;LsSK8?=(~&Xt^3|ml{m}2%ZxI-SZ2~JasblOxC-2UaBEFIqGCxl!kul z|E1{_2GYcHCQLzl>80>h`&G;?10R@4gBj^@x>js-iE(EFXKDZUZ;U4D8Y-Vz^H@BR zD5XFQE|n;92m5{;*N9H|{O6fO|6=*YGd@1AX4CNbV{YE@Q6&sa+aD|Cr=|+LH?32c z(#u?X-!~XcSI9exSjINq^|2KuBBAUry&a`!Roc!3ZQxFLNVlaYHim9L`;eY>=f}rS zGc;7=A!F%^R-cB;JF)cREW+o#Dwr-+j^FSYwr>iVDU(CBg?Pdqm(5$T!<+TxXk%mv zD@x^$#=CakCPmHaPNIa}7Uh4gu>BP6RuInjqqBAI%~X~6DP!fT;p4HFguk3>x^~aE z4%$58rsi>=;Ys9SSPbxHE}CU-Y(%2#^K$Vo`0V;&-@+4=vO7=F9px5S9%QeFy){62 zCh(#0gc0Zr4jFzIXg_Nj5t0>!0 zU5c0NxC6@;J362r+9+0rI0yC1OlyUnu2VPTmCO{D#LT{|tyxgCDsrgTp4Ma}yXf2e z<-ko+&`T{tc4(O?@C%OQ!{obo0-3Xp{HCglzV%-)xyD?f`s2DE^3&8Lclkj#$t(sV z)IVZrf(GCox>Rm@)7a^Ppm%dB2w+D?<>pvp%XNAZ{}SZO{IMcg_*i|o4Fv~n+}HZV zZiYR)Yxl%WviK)^MIdsJ=LFkfpzE~<{k+D7 zW6O&d;&#h>4MB#of%=r9Ec%LDXBvx^B=poR{oR`rEPVDnqA*9FoWRYikGIC(D76Mv zNpc9AJa_CKbAONh$!#`z{v62Rga|GSMC{Lg)k2`lg$bJtBd6o!IPBSV;n~>H2uF$5 za^-Rrstsk-iyTCHyVVT;Nte<6*WhvvXzCaFB!KKS-o+nR2Aw%NI|ETp?!vxb_h<5K z=wbu7BOQ^R1JI#>iJ7_+e33m@fG|-(R$ps_fZ>IW{i(6r=#K-pZJT@^kMxu$RUn<6 zY(8Ek3&AzpTWxGlh3l^<4Xj`#J~G}DhnS6Fo4zSCS44kGay0i4-8 zA`-*W%PGNWHDy=(0OWDbPH&6^{PMz=IYTxXvm@PM(FvrRNZ_E^!+|dS(AJD&_&QS^ADzVidf-fRS_p*EyTwZ5JbKDD_MZQ{Tw9r z26P@M0><0k$V)=`_uNAJcM+{hD$Ufv@t}0EZSuiR0Q!a*1IGE5!hVEkmgxgtJUxnq zzr}^V6prX`;Nfz|njHgwAi=Q+v9w3T;woj&hJ48Pmq@3!51#hYpg$MN7Hg83w{5axIB@)v z3n0Of88e(nQn-3=?uwS+*sJ?jtL{<;&29TS;c1`QsvqSjho=>Js;=uJ`GTK|ZBjrm zsm$mv{65SmlI%A?E{h+jYv#XT)_=8JwS|s_s@B1d-sbC7X|{Pe+yBCnM?jch3QzVa ztYC|&S>s`U|Gw1`fXFdUtssgj2q+ia1jMLGO9k?TycQ*LS}rYGd;RX?r=#$zvi3Ee z&G1ohEbW9{yDQJXEjm3a$6h?Nx*$x)x0!j%ww%XT`r{kZp^aK@!Psu{^2qz%1-DXr z)|?ThRygtR$%TPxgjGy-wT?Cv;m4FY(xWHp%a8Mmp~szA)rGhV=48z|Sw1nO7p;>A0a{?Kv4#9`h>bIt1+EU{2G$^oiLOs(-8B_hNNZP z@|=akwb3do<>FE2lsoX2^n~9rD}c!Pa(&S0z%J8&5eQ1x@}n7Cid5n{^+4CpB`oJJ zMi=4eKbLj*J2Q)|f!QNxCkB z=P}Kn#6fvi3Cb49ULoGac1~$%Vqt0&5Ut}}RQ-$R{t{d!XR<;^%nhRHCzRAnABv+A zfjaBEi#|e(=u^eYjdtTU45f%2McldB) z<#tU`i~JBVs82n=rGAl{k6vyxO$(bCDZB&vQl;EJ>Y_m>gYL{de-rKaT8jTtT_9Bl z8J;7!N9MkX4RH@hXwr~2MFmr&{9Dt2IE1^RC#vCNr|coB=8@3jd*7Rcpkp;-n{ztw z$wW?L8Gg^!1Qo$rWD$PvSNrE8^FAXpwOh|FUpZ?vDp(R4*4mCg>bJ1AE_`$uM&tWR zH1k~EDC3aAM3Kd@^)oOgLXCV=kRLo`^jmE9bn1LqFrvS^<=jgnn`G)t?%sar=xwot zRI>QapN*MblcbQSDQy#Q&^+s3L2PxPHMoZi1TNBdeU_{~rwPrdmevG`JoheB2BDZk ze82;Q&A@`H@l=M`enP!$@&L``m5pDk$K1QP)p{|sLYDq^QYM;A+Oj`Bd$Ok$ij!;VTjf<#$-~F{zv~9M7 zG_?n_4gjsW{mxiHL^zt6>1zk6mv9QtkNs(Hg?BM;$>O&pC7+VG1}(T$yXqz_|->Cadj#8@t)F?JhVP% z{Td8`cIM;62gbHX86y4FuGM$M$BPwZb5qu3+n-$qbRQ5iw!>P5ZFsQ0_*iv~9?kt! z2Nm1=u5J0mD4AiLSs8{)jP zB$-Lt)-7sW{9OA=59M&G?vj4u@@Va$DhFRW$OU|nv;Rx*@}O?kiBCLXY;|(c*Id#_ zjv1Ag&uui^W5Wno3-jBMzb1_<88j*6P+0eoO$|LRJw)Pt%wrx^KyZU;qi$5{O?yGw zsvHZE=6LB9?5tkxNbt9I7COM8PQ-4U z>mUOq-A#pW&lT@3Hs|<@8T>rPX7lTj6gn*9{gIGllHZ#}aW^RjTxAnTO=7beZh7KO z4`ZT>@M`pW_)e$LF(cV?vLvCs3j|@qr9a$br*|rBFr$b2+_e@lFz?xT^)+?xoy_lK z=4UM1K1=R}ck=GsdpuG*Jqnr}9di-1_~2TXmxl(2KNvZFn`&J2$^$^Y9wa%#w<3oOhmmQ+fbDwNbfR$ShRRS z={uHouFM@&=>G9e+rviz3n<=4@UYt%gwIG+ib5ZhoKBO3A-hC#wY8jdLDL9x?wd;n z|8fgRx)k$qLa~x|-o0sm%~8!jpbyc4D2w0vKz!W9)zF>HE))Je^&Tl>g#_W}0`>5F z>O{vq=+03u_;w-E3}T+hmiVs;)LJyyMzV zehVcPB~I?%1f?yBFJamb`Dc0WyA|cn@Vq!_wEkr1)V8W6AuR@O85lZq@?6or8>^R^cGfNB zz7{X4cGb%g^Tu=0OE>yvw|2xOF0uMk#pu1^)De%(CoK>TV<&g~Rv}$Qs zs`S|*a(5jG0!1wMb8(;354-twL?u3l9#zddeza^C`0yNh#Wrv;X(ARa)N;DnW1Mrx zbt&qjV_ZoI8~L;Yo9ol&R2^PBe0aYrK0OJ&ju$5eK`GSHLXA9#IBWcqSe7aKqDWqp z8;8sDs!3fecJ`F!kMuvg(nHhR7RAaaM`Q8mb%ZWoCEy1J8iRX@w+}ETrWD18D+}gt z?AF2E2T6@PwL)2mbkKx#PY4I3?7#q*UZ;Dm?;Q_Hr0vAOvY07d?`3xGQHkR?2d|&b zL}Atg+sjm_C6kNi6xuH#GfT+flR#aW=w>>kphtvY-*YFc1hK%S;&JaxOi~c%F>pwk zTuF4`-g)4C$5UV8T|CS(B$iA)9&wHI9mZkQ7nUmx!ni1#MrA6}ITp)RK|IycNCfPL z*Ljb@q%pyg%V~#Qm*yh%YQ(NJ>SkSP4h*85NljVG$mq!95%0^dyGJr>r6&_RN63Q= z?okdLx;U~Uull@3Z0Rzu6>C=*@tT6oW%o-&^>-`GM}$jHJt?H_qIKSdC!@-KqdRzo zgcb~Dj;&Be=a;$O(MST{+>%~MzADC9fXjMu_A)`W)3M0KX=#H@6ekDNohsfGp8U8U z+4Oi3G*2zlR*AkLn-YCG#26-ighujuTF;qo&$kK^y8GTz`ivH;{VFEyHXz6x8;Arg z2SI6Dn~6zQt6V5IMs%n03KlXZ8f_JP^of4^*&~}{Q19^RUNlXcHBS_g!yVwLFTS z6NJJN8Vk&%L-65c&!yI0V=8t*anl3eQbLMowl8>@LXMoYL5jskfRXb zCkvTH#cj0}I#NjNT3`iPU=3cZ*lkSYXV}B_n3vIv5=$Y`|qL_t;3WzweQcWXIA1fMJ6<|R*Ia<@m^aqmW_gQ80nt#xeP z&odFsL}h?p6@G4MUt+hJwcrK43iF0t@UoK1}WT3tqkm@>6%yg5$^5t=DJ)(xhd#X9+aVgQ- z6DTI+f#FbPTa!^ok7$vC&@gGCXJJF&`fpVb*TG!*ezOyp`qvi(tVGOe z3SAnp2AlK>>}ImWtkeYT$xdTSttB2AzD`@8^R)+_=im{*gU87(q*n;K+sX>KeR~aMN#PTHiwpP3s#rAZBh?SOs3Q2HBqDGkigwy*C_Q` z)qV_8CZ8nppjfwDC7ADLG>5qQTlJS@vAJgHH$fcF+%nVaS3O)_Oi~wDi`biwQ~pXz zu**P7#dXjYS2kShpngLD?{xH9!9b40Y&je>=uQ0~`ySrMrWEv#ngKi&g4M+Y{f3H} zmmz+Nk?B(Ma~hUAVv;a88*n=3<#KH}x)Rg8$5wbU`{3}nwm8@(15ow!SVR>%;6@}g zD9f7(0#cQKJM8CAe(I+H#XR{%7a-=$6;3`SPm=NTq*Ku(OeM_hIFvv1;%c6(Z&a#idAx}|t z$f%g?84CH6M>W}Bh;A{d2}lc}jR*xUi(X*0h{AP3qwVe5v-OfGP+)q+&cvb2O7Hga zLU&#rhSg+no9V`LP!p6g=JXNfx#PZu5$ng%nqxv#mvTKP28?rc`Zns_;vF#RZFSxW z5h;cnngm2H2r2xOS_(UToacRHAyzC;gdX%BcS*g9cK9b?j84#fceEZ%{MjA+pR!Mv zmhaF{l$qnhF9{SM5Q7zLj|yR^)!* zSNn|=X!s+88GquxBNAB3MO4Cd*F}OB2mFhf8Y3P*@><7xEX-dFfw0w>xI4x8@VAGO z2J0Qgcj3FfhAT}sEG|Qt^zEVof`ytqXm0_LC%ngC%L)f z>2XY0>$$>zMjHr|R)hs3xh~x=dTUJrI4!@o6bygHR_?l_6``kkqq*|k8WMe3(P!Mt zwC<)5Dn0^M`SwJ7b(I0CJybP9sS*HzM6pj&edVrrj+m+f=teep%(L|6v6+P|HU4u< zZj1st@eUe%0^? zsC2|6@8SF5AWe2CtJ4pz_eC}EOd;(&)udndkeDQCj29A?{IJbtL|aXI39+RLRf^1h6=am|ezRh1OL4Vlzu$In*REWf_dAj4NVw zU1BWKv`WQ1$~cNQ-@W`MoBwIsXeI(iTsd3AjiFKt%b)YxU8d(6A|n4{Y|;7rRoRPX zqZDOyxB7H{o(wy9sZpDf(s?GD$f!(fO+hnTbgm$P*hp zEfZ0ComHHdEAKiBx%}$rQ0$&_#R^{=<{6jL3cevhxkhNbWk|^Z7B|L&EGkc{EFe|9 zeF2NdR8~L2P-%tb8&%xeSIo45^=TvtZC}OH`POo0?uxU@BW&Tf{sNW^(2$RCtp}U8 zIZg-hz0R}luxg`C)XLI6P59okH~=WLY*q2G!k$D?-l`^OQiYa`nnd5Vc&Gs8Cz2`K z6)~Z!pN?uR*)`&*yN)_{Y4Fi(Z&M>yzxjk@x+zlbV&dy#T$eC$LbS(&rd*}h)size zdAaYmXMMA^PTe!ib;hkI+0tJHT*jZNDNB_Qm0aa9E90Y-PK0y(x*2XuJ&~7MNoX3Q z+g;y5u(5;-Jtu;!n!$SOX2tYK#e&jE`P0MQO;m@vBC`Ce2(8OfSyTf=l%wbDb;(Ek zo1gN>&BTdMtaqdk!s9W?izbtD4aJ^8_z{VbkpZ(cH%j zcy9WLy_PMeV@C82y-r#P@Dm7L?^Q%)tbIEFTqs}4<(Z(I2zE|cG}3ixFkG)-be)UX z>jvB_#}1jW$7~jS^B46)l;5=tq8PyX3OJ>`-R_<(kkI=zC#De8OMr3Z=)gFvZWPR6 z3QsR{ZV_x zcaR1NtC}!>tlVPEXsXGdCFLeWycaXP1ni7?v6hD&y@xAFdn$3I9t+wk zbGHcCdA^YMlM%2>4dt=nKPP(O2Q4rARi=X5nkVx7_nT>DP<%7EWv1@_=6!^_BchA~ zezaA0Yd|;*p9E3i-+vis!1($4!hrm_-o0V|t6}5j{!hdNr8o@_=MSc~LxZEK@HK<( zq9S8a%5wT@pD&4b$VyUK#sU3-YB;pMU25uZCAbM$}1P(f|2frA9nhx{9^ltXlARJkJ zgo?ngAUhu;c@0Z2m^2eWg8=2ahz)-1N!cQ{3~bLIM^pA8*rSnUc0&&7uIg^0DdZp? zgz47b_tp>!bO|x<^N5#!Z#3=UZzT&8%*P5$ox^XI8rVggy@_v)fo~2cGBA zSBXfQL{Zq@B}u{7L73R3g#Yzn)&Sq6(ei9BOwXS+4j18By+HHuI%j36*^s3sHYr%S ziv={KT$PoOCZtTMIjP?=L%g_>s7(|;A;IltVYt4iaKyuP8uT&Yvh}Ucq5Z7<>7?+3 zv%?Q}Zg59g5?nsVsWzWh*j8t7!|-#^$(T$se0Cdy&~V#_i!`8GbOef56&2iFbnSJU zZuyWh4R>sVOck0gPyd1Y+DXu}u?kZ4o975d4ixuAKp4Jd?3`Exr5eF!%`^n;0iuOH zoR^8i71&+<%iF6|gmyt1#41uef}(Regllic$Oa+oZew<;C{; zL`3wZhS;u`%dE`4(pCF;nnEs@du6|rsaNez!|c||R)AA{?t;;`cY%gdk+9}gYUP`@eWwOL$9ksA~L#%(>rv;S~dY%kB}M|POSSdqGlsOppbR}9>& zbV>>34~V~lcB!48GJSS8@`OQgqD5(WoeMpD@O}R+Vn1!UE)92q^>o)%$Q@Q;7M1iV zy~K!kjqkI;=(kru6{5%HP0u|ix!!21)uP;J7k|6SiVUR;q498~(OByl9l!Qym64o< ziss!Jvhe(oALqrFg-R*()|p-farI5A#u2LwF;D1wsXWs^Lc)!7jhsW~{4aJ6a%rxL zQmEDrm3bffO_u6b%J?^_ut^R%v_l=P3$6+eCXaR79a@hkpfXU_&=QBSu`z*y2ESs5 zv$Lsz)n-&h*`t)>Z|w*{B@O^9m|ntuFbn*ySvulnEsI zTMKsdt2u|{$~c^Fk0feeuxg)5XSFi~G@N5w`^-iVv#DLLudNOg31qKk(J}LnTf)#)W`=-Me1t2G{q&mn{7m@ zPt-x>-=2Mqmc7TEv#j7oUR?UcZo_hP59XtKSpKW5)5QSOlf{4l7DI;`!jvNtdB2$R z=8}5CL^mOAt{qf|-j{fyQ}+i`+PM8ZN0s^ch`PXG2(9yvUe^qZ&hA&9D~G%FlXza$ z;@zB2wm)`c(V|bRR*rl+lQbhXlPI?653E&{-e)C1X*0?Kg(7$&p(q1DvDZg1z4t(j zCL{K-Tl;g_Mxl~z(TvDPUc+uJt?m5v%y`g}17CG4zdnzZVBksVr`OOC0%3m$2PZe{ zLrCN!Z{ZBWkio->cv!XLypZgD%~&l3y{|TS;6~q`KCU}DvacGY%Ot<*?-p@+GA2B* zJ3Cm7A}}oBAdbq<`Komk>ot@>_+ii?-XvC!#`kB?cJp3awfC`YuRU??3KP_Z?x(fb zMT*gjZy`BdY{Vb(8G7GS39$hN{G@fU`)fJIbE;U5%dfbvs25yl>DaR0!+g>lB9f8S zq$(TYl@XqAKjQH5C}sm=JX+<+h8Cnu>j^qHAuv)1frvVKLG<5B8DSZ`Aqxr^N?ibC z{#uPd##=a>gl+I+?@JkI0wG*M8fs(KO%J10qa{(!TrB&)irwDWwx%~e!zTJ*b-SuE`ZHX-@jrrq@LqX`8nzkG-^75S>@ zdy`p<^Uk9T@^J0J>zBAfa-e83G$&SXZ9>McsyPXkk0wtKC*10}i-X{WScJ|~HUABR z|Euv3>X1=J+%My2!99whd<_CwaIJP6D5)NpRwj#TR8D7kZ3WZzwb#6^NT<*+?-^D;Z@VajW zls<8TW~fV{Ojwf}VX#SbDX231KQB34Z!_zO$?i^|mj%8~#{9Z#v1`|E+o{CHWk#kM zv4rSv(_-l*zzXr?5*a1Bs=EkSc~A-1rH4ATep?o>P$c?^#wd&$St$Xr#?DY-p#Z)KJeQo^Zmy&~}Ij+5{ z%dT4>_P9B_sTa3TySBX4-XyoG%oQSYN3yHG$h?>YjrJ*Lka4DeKiuIwR#xARA(RgR zA2Xpb0i!9NY=iD80kAus#q#z)3aKPY#EPE%ZBqW$XUGV%QbZZd{J%{}U@(z?;b=xD z7~lzeiu;#!i-c0l0t^spQhH#c=+@~)z$_zKs!&lZ!Dwu#sh0J$Q2jOh!Jt1j+VO82 zP4fQ-8|}}0i;@AEmXVp+lhZ=GLxp$&!fDx)poIqZ^6x?9d|9BH$gkDN90r8*7|Meb#{>>2zY#x)QH;M5bEzR-BDRyUFUz(HOd{q(*n3Zr@ zA(_qVw%=At7LPm!e_lDfdjXgU=YQN_ZOfGoPI)5W`@TeH!BLnY><{~A9@Dg6JV!KD zq}TAo*zOVcKj+-d6jmJyuuHvkJ~dt)^PjbBDA3|mLLe|Bj9i#qa{r4FMZhg0up>M0 z_8j^)zQ%p*kM;etTY=(jSUA2d5?!h8IKZsu1OR~t-n0!3ePV|H2R6)jU`=Wh#vWq< z#NU(PmgL_{euGep8_s0EP1iVJx<2+oHKYZ*O0R>Ym&goE^Rb7?2ruL}{n-A7Y}|j_ zpUMb>b>)tI5cn^c9`aNDRA4!4^gaay`j@3&3dmmEtETvv=$Uw@H#jVQ#`2Sike)IRR|Lh)qANy~q3vgpVzn_3Bl-3f& z`9IV^tM(XtsrqZTKLfqab|0@gExiu&oE+1C4Eonc@Dc}vXZ0U%!W4fx{aq+!f6##3 z1#)j=q=u~{gRwTGLyGqvhoIRTP7*VWKdZx+;}2?!qZsN+6-(!Z+n+N2cBMvvDBSs-1vVJZBRVH($=g0PaFP;GN?O}bU=}-m61W_^)ronmMmY5 zwZRky(1L@tc?kGKxixDt5Dq(|Ai6($WAO^%6H$i$_K85;Gf{b=FPyWI^O?cda-m53 z@%#;^x_s72J~NoMi6y(J;(A#Uf29$fkI{tstve2uB2u%ywl7718-BvE`^PIoLRt9D zdOW{bFAd?weYz(I&%a1eX7}E2qfgqNJ>s7ox&Lr;NO&(EQPKbKC_9Y$t$MD^r_PYu ztKlq}Z-DYJ=!v?=l4Rmte0XYC(I_JmP00#O*TT59Z(%fv;I4a9tHESCzl)Ou*I^Oe zwc)J2%L`y(z6FK<`ZKk5ESiNX?z@Ygi++}%RYFwzPW8Y8Wu)mI44*c4)y5q`mia8( zKeUb%B!>mSQ@Q=nRN$%=3Ao0Q)9W}IIjBlIzycrI{DRAd>rI*lv_3f=(;PYxXL{PY z-*b=0Vdjz7O02BK(T}e#;J*1jztedZDj~Nwnks_Q(Zag|g=Do3YT?=}8E$Wl{LfZ% z&{(Om^KblzMNS3Ui(Af5_x3JxU%@4lXwu{lIa@hoFQ!Lp;Qz`nMpZzAUNpaI0j|fz zI+6mm^cf!hPl=8>lA>;ArYFjOyJBI~-bDz1&FO7iM2`kEo&+BMCf|Q+y2hG_V1QGv z*!8^|T2l0oi!AhvJB9Jjxg+?ek1FUrOb;0Und#n}#Y49pPitLP71o&=OoT1QL5M>C z*#7;oWLHEYSL01sM|)EE6DG=N zFrFs2A}WhL2#)^4SmJNd-ot98FP@bN`1De(r0?yjIj`9e!mlrf13s10T$X+p;wRdA zZ2uT`-FcQ%YI#;*k4N&YwLb~H z=@3Q1`)pse@k-)kI#l|fJ)w<4^YFQ3ILa;ZcOb_1aY8@gfRj-;Q%Jbsq)AgcQD$hCiGF`KM(P_elhvr77p4h?tpX63o|orfn$u`s>cy5%nY(p?b+6=@f&R-2|3?M}xe=%tUd4;MeU&Et zgp5JCba@JRWMKtoF3qv&6G7eJJPBK?khyL~b}7KMW6qz)dk2+2NYJ5TcljR9(hny6 zZTky%JyD6vxK|6{toAsQtPiEp57ciOhNq6tKN}DI+FxD;Zd|P8CN}N2OXC&1n?Y`^sl}IaGp)Q*^&?#ahohYywjS(Ga9DnOjP*f56nWVMvi>g z!bXg4>E9ynM4)B8ws~0bp4+mSZh@GF=hDwkL;>uKu=| z@*+BVonMXsx6ZPe69nL{a{9r)RB4HJ3De7`hsUEET=Fo$-&>ksG&eKk4a#x2XOSQ0 z*J0H;&NnSNnV@N<6wnrqytvXKZ!Pcy=%PHYm=_&%wRdvtkvT%r0gS8c=;95GimiE79moUHay;%RNZabs$jN;vcBCcV<(2M)@G<>x#o{-)HJjVO>w#nC3>~9 zt?&2JB$-DG%8)!T`XQjcTAb5Q)HsUhYS9O*XR2vXI~#14t#FjN#xHPtH(j95xvv` znJGxUoFA}!52E_=^tE|>pJp5lO-4p8RW+dg*ZS^9ijUFj=*u|Av4G$Wg^U_lqC|LX zn>|V;mpz@Bca_4mH#7rh=OgY!wFCwK149iKzPL&G=* z()!WMi>W>SvnA7X9hYn(ZT|`It#sf*%6?|FEY06>**hy;S=ryQ+{!QvHANDXQ4z;# z-qiU1;J>!?00QK+>H=zDX^&3ui z!H-iqzW<A0VYlLSPBSr9E$m+iX{dJQ6YYqRu zwW|fImgAft%%4l%enZ{L^IWIYN@n{pnq{L8b{AgMtiCh0$yAy@_6 z7GIV_5dBQ)$zU*Ld7UP(`WvSEYtyFy%ngv+yk2myN59yPfq5FT2i%e0-$q2*Sn>X) zw+<4pzjZI@MLZA)tZs4rUGQ$;>4XeF+NC6be`i+l`VZc#11=AMs5juh9j8tW%ts(5 zns6->1WWLz(Lnu|Pl65rK%3CZIqV5Ic=}?D>faH6+s{3S;O&tB80t8{ESX5!rGZ~AKGB$G2Div?fA&HP; z`adl2do}pN;LTI9Nyfk=p8nzDV_rl*@d|@Fu6^#Xie<3W-#uu%{&aU}(XA;f-K8a6 z==)Ulw}Aas4Z*Eo(}B0c?QRF$1NVhT-#Dfpet6RObX&XHWqh-TlD*tXt{`DhW_H1I zwtVHBy;rWe&LM3sx3QGQsd>MC#Nn`l=}-&nmrypBQV=2Me=)B1J0E#_j3D_M1A$N+ z8a<~l2|eV0$W=on@J!pA@^2*H#-2Wrl_!B6dbO6Cwi5o zc};uoeQqJQmd#5&V?*}#rcEostGt`UYhg!Sbq|;x@wdohD}cze@5*5>Z@r3r%B1-p zCwCW-xf2w}!TXSqV1UXwue(4BcS_OUb;B!&0Uj^z`qgqdZ><$C6=JyI>p)N$@AMgy zqw)u@=HTs8&L4gEiI3fv$J>Dhx^0hr0FZ{DIE7>|@BbTlbkjpyFEtz<6#Z`tY7Cy|#hP;~(#j(Fzb+qWQ+1@JG+UK(uFqJ&_`nij&q|Lq(%f$Cd*f-e$ zqG2WHy2}jLo^YQ1?B0B-3yX;eRcAC%)1dmsjO945B# z)gm&xt@p0j+$??qjQ6}O)@9UzC@tMgyU*D%`;!tWqtKvYgQizXjt0CuTmkLL!I!Iu z2)(rwBZW7k-xJT8>r5lX%)<2?hngrYPxpIqUAyEpt6Y+{n7$N0Q8?py{p?YiaJkJr zdL4r&+EXh3tN?r<-mD?=_A!Fg}sa)agE(%_YU-EhlHyk^9LT!s|&2XVr)R`)H;Xu*i+6@NUpvDZGt?tROO&p^Sv*A|!}YBEu&4LhOvmM&q;UZChtzqd#_G1;6E^U7KUP+zufdjfVZC_2*WzoV zxZe3sxa_ykq4fvCa-Wy09s((I`Luf4CI{gFnW~O0js&G&9`jJ`-%Ws7W@cz9b&VXe z0&LvdTN-cUJk1)4P7H4u!W-?>c}Sp`5w5*G$ZBZ_U}a(3lH~hEn}uCMqYFS1We$Dl z-&>AImHJnWiNAXUB-O}kd-)&)>NH{=MhqTHmAS2eoh!Q7w^hb^>LgK5Btr)!p6Rj9 z3|JMdS{U}|1c+Z!gU%15(uO)B@9xNvMS*s8u&ka@;E@xSrlw%HN%+$`M zL$20|mC}Tb4SzjE!o|O1ze0rm?Q_1ahQWxbX3N&>LtxrJe!95c%OOw59d;ZEYe<7? zW&fb6{MeC;4{v!zUbCO&KH=c$EPV$Mz$=b(2x*(>l%56Aj~J-R3?!;K4AtYw&tyXyMs$8hdM59t$RH zcq^xlcNQ=H3_4D!U`hDb^>!wB>Q79%(LW&3Rg!MD;8G>o#WVa?16M6Ls%h+mhjSr0 zI7W2kQq^;A&o}%F=hM4FFXe?N*-O~Vc3w5%aKZcR((;8fE(XF(*2BCqt}G|?u`El< z;O&iVpH7}Q7-rY>p6@jn6PbPD3?yz^oVRhaNSU?n&APhXxN>uxxaa@KWVijG7a`h* z%DZu`xh(D8R7zOEU4eQ&@<{-+yBIe1@1Bakdjd!Zk?U)m9iiuSOMYGvM7_;!tKU9p z&(vd)y6^>8Cw<$_pC(oaf@zBi8}35>iV6RFGWh&}A{xRA+n*pfmYa|7Cm|p%F-7GN z4sHNEp|EH@L!s9RL2CRDolA>I?$X$5>cWxzKg_)cP?by5E-Fc)k_1$8Mxug>fCR}w za?ZFEkeop>D99pbkQ^kl$XTMW$VqYrB}$eo`OL!Y{@nZj&;4)RI#u^nQM=smzVps> z_w@AiJpBw@8iyY(VI_9y;Ca5ZHdt9RQ6n3{ah@}!0f1Hh72tXaae@~jz9la!fyiTn z-~2y`yI;|OHv{58(B&@bKTmppzy8b_;Od@q--D%8 zb^c!#lyA$E+nb@umKcANQX?huuCnak&Ec^jEvpag-r#Z)h21w4-$vs7 z6wkmTnu3G&kL`qX=Hb1QhERcs zs)jRZ$GI~;+ri4I$H!9_{4SEAvfQ%GDqZCtz+pyfpH!`hle`u5{=k@oepMLekakCI z?QnNx!lPhb9t)Cmg{~cL8a1Bbh+5+%-ipjhlST!1Vck6a53vC~YhQSIwEsf9{Ux;* zgg-xbb99@fcq(#E)mMIJ@SL)0j98Vt!bcqMIh#LH!#>otnh;eh;?Q|jt41>aEnT5vaL(Q`Kps&v>U*nJi_u>CyifT<-l@Tcl9Qkv!`wI+^pvokd?-o@W* zbR7;KEVG#Uaf7OT7;HYI>#;Wrg>upO0uQ>*{Gh6L8tJz5D&$_p(##hUIA(`VGHv=d zOE>dJ0c8DeS>rwMraW6PblwbX9?)=gSO?usVS+(t!X`KH5$?nOwx0RtJ_tX#0KDr5 z<}E@ee8-j**^uAeS_}kxuJWn5*7Oo+bLo`RV+}v3;X4veOOZ50H-h+**NEs8B&Ws3 zGY5Wu@|t%SNTsXx-CrZa5_^g7OZ4b?e1+q*3z-u*2pGO0 zb^S3*BqO{+K>t~!I5P6h*TrCW0<}7NT4}mRALgv;tkM@-e(cbnHKi7usMpi7ikNj_ z>aI1{;&|s0fU_FCF_n}d%6ek>X7ec6_eOsu|0&&6Omn`XEziUtMj7tF6V(|J zts7f$^IB0>C;LS)U3~f+(M4m0EP{k!cuie5NEb&v&t>{%U!bpkDK*q|wpKnyeQY+Q zb=_)I)$v$vY?sUbSk6og7Q0*(MyjWXOgyjJWASz#8SnORnI8Lew%*O}2|?HJtDs_y zIA5Mf#^3hNI5nImx-^}@irblW)BLeYVnZV9jF$s#8r61;q~<$_-nL)WP!uq!ao!XZ zh*0%(o53%xrZQkbqJLF!IiX-uc3D{&e>+c?gH?}atS^psn^pI&X~V1Q-sSkWrz`Sx z1_1(Ry3Fq&OZy&VhQHqT?8Nu|o_pm6ovngk_!c?L*xy?KBj+`&T;fHpsYj*Kt1g{z z`B-k1lPdJFPLouB zQW-56-a zUKN)VD6g6h>s#QGdU(*prVU)daL+oPDg06o>v4*>;0`5xjqbiTJ>Mpd-_~dDp}C6n z#UN8DuzOosy2&=w?5M6BvO7^EOhREw`i!7eT0Q61+?8=}zRpY(^r*m~Q>rjb}3u>cODF%C4N1BCgBY(5woao@3Pa(wje=d(SR4}o>RN?MJL zvp36PiT3k2K4alZx_ZX4E3PP!xO8~5S>*6eRObmh{~?kwHZ`&u!%RY_v45S zI8wx+4sw>ezi`{_!|{iDqIGUUYP?_3cd=Mq=fIkJWbe=NA67<&+nb;;OX`oQ(WvBQ7GP$7*9Em zZy1|>!<5*LtZA7Yq27`Sb^S6ST)jjp80{&jX5IY2`68Vw$`f`B%-^+zy*i3ivl>K;KeoxNM;v6%rYv+qaWNkYk_H za@vU78ow0tPxQD$ue%!(Ary0($%}2)mH((z+W|Ncms+L=5!|RWj6c+RpE}nX6_Q1L zE-TsB)FAhGD)~vz{q-X2y=%xX@HKc3c{H6bdxn#PRl#1y_(jsF72lo4)4~_jw3HaH z-ZmXu$wt<$^p%~Mv*wG!Nc9UMNcCT^ykOAs>|;*rYgL+xWgpMhV;|>hVDs&c8J6l@ zbWq|41wN|-)-gKcB5C*J-Wex`WCy1!b@EHmCfjAv_iv6z;qxHXXIiJ|HZso5 zSax@G2bOuMa@Vu7T>j+M#$51`(@eutSb^kP_>y}(R+$W?xGSA(W5j8q)TQsrv{A?kss>NBipASfeFX^U7*DkfAEB757a3^Ogbe7a-h(e2f+NXz zK(Qc6mFsZ_9Sgv)n3TnJK#(_2Bg=#L1Du0(3$iE)Q^|l|A-e!%4b}Y!Z4s*6R#3+C zNcNftD_xjMV-N}&jT%|hJz93KrrCsNkzxD<@zzob(LL%gdhjcxdVeSp-tEo;>ae9& z&hx=|qxaNEn6GN|K|z)|4qa6|=-$ZI=jucP$y%uD#=1|UfAo;JY=t|h=h^jLof2h@ zK|!Xid4yV8r;(+vHPmyTj>?<$NCrSQg1r~jK!i~`$$vXm8GMSz;ps>pKZr%WWW8E# ze~mJRqQGh8&xRtG;a6Hx4TOBP3%;GjmV#XeAx1(HpDe#ZukEFkdVl2DVNcX^;j zq)~-6Gao22E0eZkh`DqW>N*1tV12jyqupcPwEstehdJWsYsli4oK>MHEh7@rLMgNm zG*oe0GYq;44RLsB7N!Bz7tsrwRPgb4oQ7}&hM9dZ3I*vBjN+_}h90#Pkx)(xMIuh2KZlvz1qR%1sWa^YY~Qgxpb;IkOKq^cPK-Ge#ewk<^oO^U%5 zC}02lI?zJ97VjL!Rbo4tlUvCFlnF3&3DEx^RIaJVI>b?6Vsx7z4EQ*D8nvc2A=`Xl zADWvKLEZO&DJJqJo30@6&rJ+X5T4%?X!jrC-NTJ@+|%^m{u@lGj~@SJ5+eqW$jL^N z3lukKX7UjJ(-&klnHtq|w4Z%vEVXm+tl2Ky8EnwyWBhEK;(1Sk%r(#L(`$d6nU~PL zs#-?52$uF4ov@#VFZ&`Djgx4qrXA%!+Y@eAKfB5QTEGA4zPt9}8g>8E$Im`ll{gD+ z8}T^~@xBwPuvBp^^@t;m-~V8030nkW1LJClXjB$KhR<>rLEp2t$J zQTPjgZZd2fNz)QgBa^aMf4$ij&Fd$u&k1O>`$>);HAHpLW=YQ7jKW ziDH1pRtNsxQs^9spdzOjsOWn{18&dZkbn=mXUMF`$z|;c>W#y!)*HqzYp1#sJw3*M z5{!|{5-cG;$`?UHg^g6|rX#3vVZkpMM^|Rryx*=p@Y~X4Pq9p9@#P1Z$IS zmmvE&-~QxX{O(Zn1(}ziehvX*d9!UA7#f5|Uqfm6l7n)^=e?ssPs+<4jhWGGJX-yNGGF`1?k?lZ zmQ+QpmFt07QEN_(nDC=%C5U5cThcrnA%ZYfW(bj4qaLA|Q-Yequ(q{$id}qA&4y|A zuF~7Z}ovr?bq9|8Nx8aGxeD))s8igq*3A}`(PnXNH z#NQ5 zed0O1YI~Z53!T)`3`pu?q@2P$vQ00kzKan>3t4q6NXF+gZ!9Pi8|9x}t=#n3;kBAY zUV(-*OzqorjUnHj!o;rXcnZ~sy-7y(5`8O5vWis#&e^WV*7c?rq+IPY+t9duAcwhi zmgn8>XrZ+`@wgw3licQUmlF3l%s8#aEo%!%-#sd4GYzVHF}-9v4J}JbxykoRzh*tz zFCmD3OOkmn?yCeUYx#vkW8$v#3i}ipq0ESS(MOry$cWd8=8QO!x)P8j_Yzo1TyUdZ zb_nP3acq)cG%re1@J!-062jWLi!46RlmZtX+&p#t6yl#c!Ct*o(Vb<8760)=DLbm+ zcR43BGWU0BA(_ViDU^I3b~ zY-wpYo93g8MJDG|K6{5-u9l?R;6fIG(wy6=uIA5eF*($>9!rXzi@sR*Y3JT*EhHcVNLh_ax7uBE_a69o-_18xaAt zLu&37QyH7z;v;0qff_cfI&!2tWRFH7-+W{BLlY4kbzi4+6?4p)>kfu%?H-f#`Ai1E zt&ggdXhuiWgG_W()}-F1An|?u$Wzf-HqFsZR5G0&seXEc8DjEzn16LBoWNu9O&XNK zy@+Q(c`50!?VHZZqOF1SFaVu*FepEEtY{~mc`BGQpH29Nji6^oCHAAIT_gWkpb2?! zmO$J5EWzqZjbaWNQLmamG*cf!w3p4!_dTrn)=|ri7XU-PiK(Q|R!Bms&SLU%X*Li_6h;=f)JzkzmU=XIAW`FZwizP4 zIje-<<|usB(zR}OE6dlT5(Cv7IafCMDvH&Hb27GWp(Uh9!g7lmRDZ~%d62~Wrb}b_ zo8@jA7~V}@^3cqMs>05}*-w;Nj~zpg%`3mn(-X^utp~F5paN3ZE^#lQe6SbpZcygT zpjOhEr%g6=j7IdTuJZBgf!=Ak4a-qI<2N~4$G036Hds0) zJ@q{HhTK8Or_iMqpE`vJZn9z9-&Mt4HBuSPIK5;g(RIlLN8gt60BUnbHG-ya)5jHe zX2f|_*;I!~9lkr+m$PddYO=;%ky*8FqPp#nUuuB`0ei$?GN+$5(>UOhB>lv)BF@freK2GWngR+pq~mta@i9 zD=Tc>Ryh07V%e~EX)58VS1+~dU(=bSq)zx_{o&UHltS1092K`!10{>943@2+8m*Ls zCL6KX0-7{4wGPp;Q|0VhHPWCQXj5JAwAVlOl-n?I%y<=Hfm8bReaTP}_~1hJm`q|S zhh-1~A( zvFuBWtP_ngb>Tw-8KZ(x(k`cSFV*`z0rTA! z?@wpTpA(Oj)+XkO`~h0(OK;tD5jR)@E2inqB)+*=1lmb35D_{IKX_z0g-srbf9Ti@TBj(IeNgh{uoH4{Fe#_;$yhw) ztt8AVNRyQtP3`rU$Fv#KQz2N?W4K`uE2V>L+YUGVPGx*D84i$iQ%)9vc#lD`m~1u> z=FMfjm7{95;m9Ci^xFLW%$tR3CiZh2_8N@g5vx!0<=BFX&iCHQm6;4>RgkF&^9-xuub~J|ByMP@a_L`Vixo4f#xN#vy-9F*Mwsd0jE!45~OjB9~+ZD#O z2MARpN$~UU-4{fu^YFSg6`w(g+**lJjeF$aCz=-~zsF1rx%*`^PBH`(kR@7{q@KXDO{@VPL_Aj8ss}sXPQ>QruYEQHL3ccZ7d0_~WS+j-+h$-w zT2!8Aog}+m{MS3YHeJ<~=#GS`Y>=e_H4p`#J#kzTZ9#X2f_zgXS&wA1e$?$8 zu9ohG7Rjt&KOtniJ$_hWTvjQ2DLC-(fHc!o z#A3i$+g;Uc;^mja^o^&li@ZaiVx%%z!8=cJj9IH~`{ftY+V!J|SkxrDV-lWN@JR|< zOetkp|R1L>6m+^Qp5PVXTm}ElsvDR$HA0E z!r8^V?w(=O_T?yRL8|B}GLQiJl`J7Bd44S#`l1y;jUYBK%nXaq11fM+yjZibs<21v2`BbtjcdOmM0DmKKgdp|N}&9ZL*HYz$jI^3jm2_GtGSk$&f=ighxBBwhzw)ZAzm z^{(Be?u4_$gVLf*M+Xr~vze?4x9oMNSDTX+A<&Tqch_T66A=M6t@5y5?l~Q;O4AXl zyqaXvq)95sfIR&W2OeIDsM@Tca!iQ3+$TLdCXl?#XUFjei8nQ&=HE#hlj+Ju5{mOd zfOww}rwTrg*z~EapxN+$CzLsbX*TOF!5~*BVcBrJEN+)ApTcgOX!HK*=|)+f6=U+7 z^dL$>y|uNqR~=#0Ax#d0QjDFT0F^zEn9a75a81U7MW^mfiCw?@ks#Gf<@Z^fcXJJ0 zj?GWB@C-$td2RXtcv3mbZaIRfL5Q;CuN0i*0%U^Y=}D%(Qbt*@(A`r*74+JvWzr3A zFR4@|{QM;bRofGj>@K)JVUl@K&GKEIpI_e@f=fMg{0o)bA(O1tQXkMxgYU}<>ursgz(ADy6wqI zj58B~SaZ*=*tMh~04k;}52|HAnQM8a?nYq{Vz?f^lbayf#_ za9NO_)s*6ohC1veT{5C?af#lXHYS-U@AZ_+a54;ls$v>$RRjxVhHIGeeFK+cGJ?Wf z$Gj|>lHr&pn}xQ{%vin2pHm&-w1%JtBFYz=gjZ3+kIWWYwxpoTjI};(*B|{cgjZV6 zCcH4c|eRVsEXQ12m{%flnN$aC#Y`B4dxYw@-?d`b1n?*!`oO(WDo1R7<&X@YxY~mvE9BaNq0K;zQ#;#g?qX` zX{0JDK9!3)rXS(>2#f6F>jsuy{nS2`y0@(jlK8It<#}SUa}ee!4}k>f4JGkR8nv*} zc{x&0k2w9nz2_MaJHC+ zy^G3TI~wLvR^l5)b8bWX2FU_3Z>-Lnqu_?`W4k{-%5!&q>A(9ZphBzU@ybX_UE6M@ z1$T7&>=WjK++jwI zd5^Q~pt`Buts}6X&4>p}HAOW_ye?4(Ia;@bp`fK6B(-uc{&$LQOR zO>TYF@=fs)HI~ukx|7J*8`0%cOlymW2GkD1eJL|Ay#C97w>N59o-yTX}ufUh|pHjVa1RbGpJyvb#naPit`Qj?W!$%agF- zD=Ur$JAP{<;qm0V@RR7`XipsbpmyHq`r>t7+1mEyg?-7;_wD2-ovYWFi@vo}Q1>_f z4A424l39#jx3UP5W#*u{r$jcK+5M=Sa}JhZb+`On%aEJ4L`83*u(7w(?(p=I zpy=s!H!Jj&?U(GlER~&7AQ2(8-|ZC|^0rfT>LJH@RtC6B;qgcD2F(WH;VJVG#t|-| z3M;2tm2>-zrG>k5VXGGw%LOU8Gqp};1hT6m#=~Vf3R92QQwPu2TSDXOTL-KHRN_uI z%lz!u#?y9=KPGE4mk#TUCs-|4B*_R|ra$0RJ(!@-wwIZiqK#AqIizG!)+Ob#&G?1D ztyt!+iG17-FAFXATsJDqrae|r`m_~C`i>|*<#Va6NwOC0NG@4j6t+JcB0h3U9WE1H zG7-Su=Yp?mrnWyj(80PJO+32yu*(g&%mIf+`vGiW`nES>yX(H0mJ3->Lvf6JV^2JM znF{TSH(XAvIdjY=dtDv}%_h5h9DEjMi-ev`D~X<(k|%>oiAoLxX=6~9&5Vlxwqan4jNL7cfpC{wtBWe)=$>h z^R&07XtriiPlk9+zLnBn|XP%-@nsGR~?H_&TJPpu5$E| z5<28M+7EnBfhOZIJ&>#drJ=mq9y{x1NfymUl=Uy0MS|z6#;A-BDa-nEE)Pwowk&$} ztZJW!>vE{6G>*}HiiH}=1@$1E99`mPjLbKFDf{f^;qxs&XSc()u_qF07!sWwOg5Ww zxn?6P`zn;wrgAU6a|1;Wu#Q@t+{nGlP2v1it;V{CCA(~HaEz@$ZvE-RQNn5dTue{fLwBvHBZ%L5$&|5VN2D)Z#Rgc0y>uy94BD~KAUL5-YHeRBu>Y#a%gNC z&X>OK;lX3wY`{+W|pIPl=IH?`g8x6C$LHcGeN&krAf^0ojl$rbqg!$b}Pr zSYnDq2oo*oX(%`?*br8L@hLDHeterHt}xbn!If zgjx!{btm$D2-eCnnIMcdVBXXVf&Gx~_>|%4S@TNhvO3^~N*@eYFq+t^Ur#~M`jic2 z=C;^8!s&ufxtHY8=5(u6Jwhq?o+ssVlaiJ0d5m+#=aKBV&8MS$nhwrri`6<%<0K76 z+dG`0pJbNGesE0&VkY^^H{MU?$deV^_muBaZ9J|SV%UGBzhuFVdcMzBPt+o#GlH+} zQexg+9!Ql6D&8lD|1pIYVerWG6Y@|3LZakZ{o*|4c?)-d%XPysW9cKJ&gg zh-^Oks>Mi*im@JPMxXSS@KokuRwm!S*bl}tL{_#^_i_1#l9}Ct(^|H z2Os%YLY}BK#)5N#euC)i5Xh)=-uD}i3SIfJ@k*H2xuj;uvp_hJm3+E-oEl$LvjX8o z)~~qdMEBlEu`f=;1C^>Q1z}Cqh7CU+u7rKsp0l5^dbKFeZjWjnJ)2mYAIqtyecd6d z(m5p9D4*n`k>HVX;T=_zLt|x0`6-QHC_SVWnz{T^&+LgZT*<5-GH~RZUTn`dI-s#E zBe&@4}KkdbB0p;macupI&Uwe)s#JKaRM z%R`vWO|YhRBGfC&%AdN~xUJwkzq*q2E^21#?Q~K#D7vM%<^tKN?dFJ@+Ny5cal>v5 zG^w~vx%2U5A``tsPF4Wt4)2rMf?FhDBRDeol&Qa8Bm*P~8LyupWl?AmUfRA3YWT_B zdoyPYSD$DneXg7+5H1WqsT}!N^-UAS3Wqbn`Cy7+tFkls``qS$=%%~xp_zhB2JEkT z@yz(sR0FNZw>Cnu9y0a<&X&C!Wtyis3~j#2HvmOJ`IoNUj!ys{50gHUAZR8o*_WX{ zdZQuxiD{l0iZgppU%Mv>|-dB5c5{?iCgD}@ zGn>*)<9V5eW_HV>fec?JG`|)nH>Q#Q_{hkwpXBt3bXtL+hZszWQcMb=5yNcgQb@>P zxWw|^zFQ^3+eR55U8gx$@|W3Bj@mowXi5SO7@b_Xw>c`s56UiZm?61rewhMcYR`jM z96c)a(9d>PJ}%CpQ(Ej&a~2s(-}2k?<8J^f1zkKGQUip4;jy~3kl~WO&5M37zx!-5 z&bjfXHY;(>V#Sf3JoEHad>!fo^2y`x3z3G|7kp2`B|hza4>RHqXR4eVPh9*!-c$bh z{Mzso>6s;HgM1g_^vjs&JV7?aK_6r&tyB1g> za-?a$C9nZ@ao1f&1bSEAhF}d_dGuBZxm;tbOe$6Zz7eVN3o%+z!EG1Uk`z!~f=~kz zdKE^*iYnYz-VH(2a_U9V*t_W?%{0j2JG~Ij)5b)7HY%vMny9?m*FW8+u%?;buDbVi zQ~2#;8Z}h%d+%9WfZ~3t>FaYWT>fBL(E*$*Gre=u+D_9WkK6I+$()z6w|6E73on)> z;7Y4+%bk^h(@Rp2faGxQOX$`$JlEOi4%piCS$13yp2BpfS#zFO^X?#a*3pzR^Om9GV@;IWv6MWy zWkuwzGW`QGog%;bHd8xYz3&rh(kx$^k6DW3&4#h}pH8^3f9PMMqRjJu@xfFL;PHjl zr2I9u@SYh~3WN=;lX*kXYg{npnFSpx`v&|dZ~ZiIIzk%p+dZF><9mT$n1l>lSauB+tX) zA~4N(nY-Bh-_1l$0w~qedDxE2JM;Gk@!Hn)0yzq%-%Pfq#-_aYxmwnbzaAL?WSd$^ zm2SY>nqWoB4NH$VpP&AinRd)SNjeoWRb>QgOlC^xa@pr|NA|BD1u7R2r@+h~)bV9X z3ib_-tQs__?Jkbf78pRqjmwKwiqK)C=p~7Cjhb~AAZw0m zbpQx^os2U5kYwB}>dDWCz=3*q283S%mt+o!YTnFwaYvFNV-i$5=0UaY z>le${>l8cbn#ZvIBh9Evw>0?QS`QT^&FB>}X8zdOhOed?^CyoUp3B+v^|5BnHc` zGoY@eNIxecTtu{xpT@@S{x#$VOr71J4)`6KM*eC!xv9+ABll>AAW#^&-z{AaKbOKs zShwOF0`Hzxr$t+$ykEi)=O06Io@p-1W>=y}Po$3R;+oYOCko&sRF{ z#3AKJi5pR(JOmJJyB>W9@MAX4}`9p&+!#P zfSX7o_@a$jHCviMRx1CP#9t=VU1)TSHN20cIP?B+n}|_3{+E>(6?t3Kx|F2&nmkfQ zZUFthl$0qGXn7AXLJW#TC7~j@Q;dEs)Lq&}C;#As+0a!k2X`^?z~(VjYMBtg&}?v% zOh?81?pw+tL)1WIG&oDyLB-9tb>`5 zrixx#2wQ_qbP?TelX`A-@PVRhIGG@4Fd`zu-5Y^k#KkHex?4}xCN~-_ zG&HrN`>_LKJD}=%Hs;LskBMnwRM}fTKrvq<$q?-|37mF(=64msOcBl%eF&#u$liEi0bJJDAW|bE>HL5vIqVDKS+U+5UP^6*BHJh+)&bIhgC>|q+%}2y>EnxzK zwTeSUbTm(}VGHpWuL9Iz;^sp^(s=L}ZYQGf%m$U5O5#sN7b%62=W|8To^C}2JrkuB z1?(;C7(T*67St;GbmctA-7fetq&YXElWR0yP27dU6to!Qe1ucGvko|Ovf(aJSEl!V zQJCkPbYZUunZ4_dWE{p%Nn~QX!3Ap~OVUPo7zsiNj|(!i$K>Mp;4>VI4&${1rJ&Sk z;fNTNpV%U^@meuUH+4-?Z+U#qZJC`rcFA?CcTAeomLwtYK8j(BG$vt-XmLG=Ncv=t zc~8A`N5-J+ae?6vBi#ai_)I>fz_RnjRC_gR4jAGE;ydZH}~!{Lj~ zGen%+9lAfi@kb}-5o5%)6NSBbVw`(R6vpZt`RVUcyT1zk{`%f`78Frd{ST6_z)?*) z&%YnKhKeAS-g$`rf2OJRxzp#Pa&a6MH`iDS9M^6pK*8y{80zDe2^xsuc#R6%>AzIM zd`gt{{!f8;2^oP`0PSIkDk?t9!4G?h=wErkp#lr<+`eXQuAzs8KH_0n< zH#~F_7!K4GwdPoJ&331N2I+b|F`E1;)A&%%=cn3{&uPv)2I}V+N=^KTYe-XauE;V0 zRXAvnRWM5OC19#g=NAIuTRAi{&w4_Tmpiv}7}M<4nootS2RO=q@>OK&OM$n?vql9} zaA$qu(}wzL-@#kBd>?N95Gtp7bDpl^jX-#sclD<#Po+QyBkWK@w*M0F0ppds$1Vgj;Cg-hc8 zrv~)bG>SunYN4)x0Ong_CV(@SF3PSUXw(0wWWR>|i#;c;2nP@Vy`Twyb`3vp`9HJp zcLDKzptjZ_GEj{0Uz_qGLLEl>`5*S8Xrjk2P_MN4tC&TV{vLh_b6RXa=*jM?lj&bX z`CdXksKj-(&$jqIi2(gg*aJ;O=`%C}l%EDgY*jhaLRwpRWB?4$urp!!*BvRKH!Pqd zn%}Mm{bHHv2D4Ceiwe6J)N6jZ_W||yVcbEM)}D+&JlEE(tp?H{?=R=q9lLk39uN7K22scd={D64EEpiOyils zKdFge#hA2LdTbKBsvTjL@&~8h^=<&V87<$aZ1&qAXz0MLAhbR*qllIuh#e@(D}1ma z`X3~hY7RPM_z~M45L8m>&=KQ{vc~_1ga89^Gfjt3CxRFq@YN$+Youjxxe`<(e4gI! z_osIy!S6%$viq(Efrq#)O#zZ20Z+g2d&qy7%TrSh@fUhT3puKPJ2#J8C%B+S*F-!FcZ z`noOC7$(S?$RfBsB!6>#@`g0t53y7+cX#*tqA0pQ2)vl2{>{D09G8rGH39;Y0zWM1}Hl=kC;8jGW+% z>?8%;u{pq-xC1=FTsqN5g3mH_k?Htbx_>JTX&o{5S0Yqy`#__yxL?ryp2vSbNyP^i z;nIcfCuVP=5};kbB7>1vEjAr^hUDMH0cO>It%^omeSlnU!f zY7kZGJTmXXbsFRVQW|IuOnjgijR;?Kn&|yA>jXui*5h~S@0u}QkE5YI^A*yd_o2sY z*w$G-oL0%J&Hq%JXLfwB*TXgLzCLR=r!3XcU6Wl*h2eGW>c=Y<^XsaQULX76b!4iq z=*Vw))A%*t!%O|j#?-t4mQK8c67L$))sJ^Iffqc0#e?-GpeRFDBxL&O%Dzc?%%hs} zhKT;CE67FQd8+(10&FL7AmI|4wD)F0*HHiZp~66tWSzbX-lO_zi5#YJxQI*8P0^>P zjYiOIcBj?j?4celjSDf{orm; zc#0n`B}EKwsKqEO?snCSmg^#8J_+`Hi9Ex(%8XhywuU{+I8_V+=ty`}Z{ejY>|Xyx zDA2b}{uQ;W-!IQ^eMocb#>pGbw8_1L%ijnac8xB4;@4Fr$+2^hJA^eBAKA3DE6Mj;Z@P z9()&S5&g6rZ}vTydp32nKs%7*{CIC=2oS+aU=y>Zf}1Op8a>XX-3|c?Y3S?ccjWXX zSXfxEzczV4w3!#Bo`dW(ABoVMoi+Cx(t6H?z1;UuYnwO2w@akH=I_f#O#svpuF&%6 zN;itgXV`rg_$la)v2Lymswvj0xiecim(O#L_Ty8MH6kUPXD-xC&D$8=bKLeKnq_J$ z>vAqa+NE_HJ>fLWAIh>aKA48f-N8PMx|`rM!#dv>l*h3VXrC}bqfeKSfAYxd^alUP1mAH3yt++cb&3dDl4{^Rrv+!2A>o5-UK>s8e@ z8%;cJU>Y0r5P|<5KiAv}|H&ACyE!&N_k&z(RjM$JLTQq>Xb1y0!|Z4rw>eNfj#>2y zpjTntA@>WQ-&SSq+@{lm!9Q&;u_8EF-(k@b3$57*tJ2-!k*fv_`-*p3FTqvPM25!3 zL*U*Jlau{b`Vd0Sm&A&!aT+=^j#C!9cNY`AOu$ z@Y*DnN`<5F^Od$&-!Q))lqiKR2U7|*h|3&1**E~iGc~)Y+(zo|Mzz6lR0~jZ?1DzN`ZbHw|!Kj>pZ7#=s!=jPw^uVG0jRjzxMnin`*AJcuc; z$#OZH{+aBbkylUFi*W1cPj%5qBje(v0QxoK4wn&>HehWCvv(gpZ)TXnQn+FIB^60F z{-M9i{`Y57l@^2&#Ln`&80mWQtdcMcD`Fks5b?M{<2EAOYrfPaI!OYkxWB*p^&$9! zTsOu%(v@$trUBz;G-^G5@C?EuC;`R$?f06*fX~v2V)engdh>tV-rvKyhP*|4&3~yO zk%t-rntX-y;7YwB7{E*4ltOL(Te8=XLJ7U#yKmmIO;XUsh#5R!LwL;UaG}q0b|#k{ z{kbRbe5M-pEYd2k56}Mg!`D!Cgsu^Eqe8}3v*IGe|;r7XsGI(wWJ2-DHtT0!v1y{R`;-!#~B#a@L6mG!$ z9O-J9UmcMpRths)Gz0I^*J7)#O*C&#Jv*bqBSH4t4Y=o|h;Qg9n=u^ZQw{eL`>StF ztEkJCb8@%^I$|8XNzy?F}4+I%sIDZD%NW8(y)fes_BuZKlVP z&SQ;_@iXZfUCi9}wGGNEoi!mAD%z;~;`G2do+AC$BM5AtgSDtl=mGhaK)e_+g&@wH z1u>Rb1l>w?AIN?`*c1vrefGg&GT7M!}NwhZ+3(Hzin`cV7&CoaUrci@IjRgXra(;HH5Z zvsLR+h;-+caI{P1kIBR0zn61FBYt>Za9c?lomIfk!!S<3_YC1KTKSTi0gf$P4ODrSaH@>$({Ir8!RKG?`CI^Q44b#@(4N&uQ zEMa8OOYb*`xP#Fhwn+p&pw~%v_{+)+=s_DSt1fnylB`zCM73AXLNOC{s{BGYCZvgY zQ)HLo#{%9^=wKjwFn~$5vhi~Jm)8&nUAjZ>YZGw|I8wB~#`I5_PJu@zLZ%O}g&{Qp zzT^K=+tvS8hl0MJ+7fR=sY~XQkYIm%hd*Ys03G;nONK;^p(Kn6Y2Nm~{nj3^fgY~C zQ=%{pk4BVYPsBrC@R<4pg&C_TQf-aZKl+q+eMJHO2+3Q-xizXb2g+H?pkyj8jLP+u z;IAfs2mo!KAD%S{c-3jC8*`vd1=8!blCnPuJF-7|w6#M$TyowjH*WVF(lO`cbsdMCb~*lm zGfw76jv7So*csG4e_EdzS|MI@ozjO81Zp#eA7N`$KY9n9$_Hbri`U%fmP44+V4K!2 z$y)f|A{K$3)wTkj9C#z?Xjz#>X%KB~#isX}QJJ@QdA@^$YCCCa##o;3x30)J4*Eeaxu zgW->Flzy`69+C%B@MWT|DGV9(X`=0q4&)4&Lj?0y`labxsy^J`s5wU0}XB?R?z0XNf zV0fDH6A=`r==OL8mF1!5{^d4ZjY5S9pM7~>{EfR`lU#l5LZ`BGw2)NX3nRzD=CLz+ z(j#KJy@gJ_>xT0a0j56*Xz^IV!l&XF2V3CJ_+$Sx!|pjk_;qfAAr5rKN4d_+c8qY| z2cCLL50Ne_rX|$=0Y&fo4Q?7z*f6ZCP!&cbTw};MGR8NS=y#N-jfsV|%qOs_K_mJb zx~}I0^_EYewYQR@;LDOX7Rp*q)l`(yjDt~uyDQ5+jNBrM?D}Qi9quAek5rWJ>A|gA zo$5hM9oEpxPQeVwRw)vn|_iS#eJFMlFzqxQ)~D8MjX$ znnd>#Ro^FpUqWLLN!istWhPdN?D4`cM^f_!P$roz(h&yq>&}*OD8`s$LVfStvG;C` zU(l5QcdI%uf_5#;VV1~SA0n)w85IL69#ZI!3@LrD7@smo`DIIm=W-fnTCbK!abHIn zh3>Q9M+*Ds`FEIm8Fl1PNlT{p&b*dv@=zB@bs*B~rPg>rXMMoLy-@gTMyfE*FvB9# z;%2SY{^|~&3Fi0a{dY(%;M!vi*!*fMr|VDl_-j|R;Z_k|v;~;&jBjEZ-pdKSB&`ll z1J?s!rYlrw+0A?Rq6JvdvuhcgGqYMUSrlqr&1kryQ^|aYxt?b! zm^Yi!vI8$Mgx;V2mXe9a8mQNX1mApb%bN3;{e`9R(B;2^08A{{7V3^i2mxdE_`RFS z*C2)Jy^K?RMZDjGZ*hr=>Ue10>L*IBpc}xwGH>Y;NsgrY3PNSXX8IiCPB=&M(x>dP zpF4vK1n%ZwMmyC!VFHO5qE_FT^_>MEP1m@-4!xOrUB}(}*r34kTQGNA@yJu@p^F!G zJOTnj7}Edp?sski|H86P`q%srfSeO5$rgH3rI`XrMN%H6xTHO6mHxbaL!{6&!6aqZ zq+qEs?w-?~eC`{!DWLIS&D4Gra!ojn_D=856Y7-e6blt}6)BG}qfpye3KF;!FJJyF z;iy7ocRPHIk2kLRz7pBoc$0C%kNe#NHp0auBtM3vbW3k}WnI9Lp%ksPCuJ}#kK=wW zozf{(I``z-kOYAOHda79ulW-OHY)*B=oPzq-EIKfX2qGLi*Am)J)FgqiE`u%vg?>} zE1Wf(ij=asWf_*PsvTQ)ZH6YK*vvcbWAS#!f|}aHQYnqkwpRGxB5}N}*Dn*RVT$J2 zb$eh!9Cq&=xe6=3?65~yRmVq}JTe;28B@B2Z1wC5kuA0-+OOS96JkYIXiAa9JG+>A zP#G9S<&?`q^g|m{%;Z>lS9DY zQ{lhxaO^aNG@lZsT<{YG?+d1U0VDp`7)fKJ-S@BC&FVlD?;FH5t#n69F<;7rwkf|% zfS@J?SgN}1H;ey9u+8A=RrF{y*8+wRIhXo?`M3LXzys}6%Epn!2Frhbd>6piyGyt7 zPcXCVe~CiK{on13b@zS_;9(!hKQ0(yLl@3}BCb2kZFpDbsC3pdSvyygl?!MI`O_Hs z{Qi2f2uQr#*&Glh;ob?6B+)*i1b)j8KorQhJ&=^v_s+lJvx)bpjC~^w}lCR{|gz2cR&nr^vg*Z z#>By3d)&~7W8k#PI3H>Q7g@H)AufQuMIQkCTD)40o(S)H$b1~9zA`LAtc zHhT@03AyU^EU+R!p8j5k(wq(-Ch^uzw^yEj_=VSN&2Zf^sFOV|FZsMNrIS62sB58` zxawJCb4ER)^P#Rn(nCrvA-0xDz3U+B`~843RO^7C8Nh}DMa57prUU~Y&8XQcoO$)mHPK00b~UL z(>QK#>wy@tTYB#|21n$lJpj-D`0*46mmDO6!Pgmh|E#=UK^LHD}pV)0ajc}03bPUTr#Wuw3w%_dmcxms_M^^5bSY@Ge zZ_+enE9a|aH~!vU7YGglKz~dH80x&`5Ut^m$G~(b3tF8b;tTx#bJcZ;$nf0K5sxR7}jZpciO|{{n@Hi z%c*G^mR*xiR8zlC)>^WlB@?u}MDUQ7Vh9-M9y8&Mq%9t*?vu2G&vYiB!+Yd6V;-bM zADJk`y?KC`$doo+x^Kci$IG4hr34w995rc8Cq^&)%~s}A{Y}U(Qpz+9LE+1|=a9(g zMCJX|zQjNg+e;kGWI|y5=93@U<0``@a&FLH!Z{|qw!oAjPs*E}IUvzGO=UEgvsG-P zBj@CP{Hi55kibERy0DBS!)fQ;v_Iu@#4fLRqNDvfp!b~ddDZt#k$K=;?Ps66+BHF-<4UX5D~ z#(#(E<3Y)S5`iJYEP8peu*W~si3oe;>y3AH=Y;_Q3X^NCYp4FC@P)PaF?G8t7>ehs zDGblezEE(F#PTWVSGrgG2e;y#Frz2eUWnL%;q3{#jp3A|5T5`bheUMxu8h8asrE~zN!#la-8$rgH)F?-Q+HseQ8|#3uR24tfznzsh%NPYO+N;wq^pv=bTe zZrn9H-=yrf+oWJA4@{f5rbNsT$KZy45jj`lCB|a(7i8jVK$t3i@6hgX5F@;De(w%` zyuo&;cWvMW1B@sJ2Mg~~Mg8T%;c=dNC4`_ZaersStGQyY67v}{Xu~36Tc%1**-Qc*DOh;;9`&05%3ee)BFmL$kg;MzL=>_r<7g3kv=Es zI+-yp&OW(l+8B6bu)<^{`CVh-^A;~rwYQDs4h@gx@OiU^QxKE?}IH`Y+f<<0AV!|&A%%CI+_1XF&#Vc@+_U$6D%Fry`t;l$PWNK2Ln>Q``mfbpE$m$-23h6Ua{%borQ zs3?1)l>&+v<%ELqI5;%ev6PLz!N|%U|A}(8`4=<#M&h;Cc(^72{+^3dM=+THOK+(u z+;H+-4m@j}1%-=ik8MdHOiV&i8TMqM9oY*eoF5uQh$krr#)=Jz5th6QUZg#j``a60 z62KPoI`n+xf<-`k$EARu?4mF7^DPA)^N@RN2&IN~oiR7TSBRQZ0ndGa4WIa4@}aIG z=K^3Ob(g_!+|7l^eo=ugndZ=^xDaCdMgjUv`UJFznamWpfX%s$fB}GNMc(z?2hHYt zhPs5?$ZDp5xZ*Rb;<5iJKyYQZ8=DH#X?we@14O;x+k~4A#0sN$ybAyTM^Y<4fFr0=r&o3j7RQkHouUluqU;wPNgocC(|+}FCeqVT<*qbWhN;;znBEIcgEy** z2ovM70N*lo2^kN@rULKOO^QAK+$o&lm9HJ%YBU_i=rJMm+6VsLPda&@4q%wHXI`5I z{R`_Eh&|Of?vc)st4PZ^?`!G^{w{bhOc@qp@1t%Ea#w150$_MlK&fe8t^%x(Ovqx> z3Jdxq!FlyM-cvR*TO_2Ys^9b^CMM=}^O0-oa&x1_Zv08W*um<2xy?VA4Ev3z9+tq3jfb;K zGH70L$5wduQPMg|8*b)?@u$XW<7>9dROj@ZRq9r&0#$F-N8Zr|53%_|s1!)eo3`G+ zr~g6YHTY~4Hf`r*pXD1AvLj6t-*dFP9CUoYRP|nI`F+jgj{VtF6lcwsd6Q%O2vyk6 zMtl!f7G+pZE;ao{oIcP=b+%9Vbl4~r@&zm$0W}h^rSV88gK{w1bAcq2(N)EZ12ml9 z8c4%o5VUy3d5ow&1V6rBQI*QhlBB1#y;Sk>T+mF|NJ6~^lnj2RTa>J7*%?bt5n{Ua z`K|byYgR_?+2MrLDcr{JMJw}2XJvN^4Mb&A_C2o6yod62FI~FZ14osrCwA`_u-Udu z6SZli#F&ZA*I&DKji}@V(Ou`Z@a9XYzJp_08iPnMBZE|9zf{X8hXv_iTt>?}n|sse znuDMmR~c@3Hi{z0nM)tsweZc^YX|2kD7t=C-y$IaJBzsb5&-=HViw@Zf{n;~DRw4y zBjIOVVy+~(RphtW(Ej+XTMO~@rIfg@pbst5nJUYbRcUucAC+~oiM1QQAE%V6&JLX% zm(}*tE!7vguLsHT(@#|4g2*IL-LAD22~uS`tVN-s;*1Jsqn(sG=^N*}rK<^|GW13zMj|F~~mr>&Jj&DbTE6TKta<>@e7 z4Q*}68jp$gycMV&9M~zvu3uC4Gr5QKf3l4qFp4}w04m}!cKQ2W#0F@$xOj;H4sJ>4 ze5VFLR?4_?7jQ}`g5oel`d2=U>Y}q$sTv9y8Tl+@VwpXZNCx(G358ZFJNg&WZcAlY zI6D?+M{nCWa~D~E@9R_je7&+ zUWwc4Jt|w6+s9oLNF}SBROj-XqE_4I)ccAPV-Dluj6AM%R}MI6(^*5}O-f#besJT0 z4|vLLtcbxiVS4Z-so6Violf=`wu|{sCS-HC0hq=}0hOM3wE6twfkS&CHtYf`xjdno z#^4oZ3!z^;M#&yu>BTQWaFFavi=R61UH)XE0__l#w+rO)<5uQ88Gbe z4fPE*z(Ucyw^>UAm4&&GVcF(EJkXAvaLPinUG9LL*S;QMCK0UAa7vqJ7o?K1+#cK- z(voQ~_iPD|?J$qJ@oKe?YV~spBPp$CS)uTuSWm&;@OR-KPgJt^c>9he6W>MITGd)d zP}+#SStibvBBDc46j_FBcPu)7G~3c>qY5s)k;V9MfH9@jQEuNG8h~*!?Iz>@w?q~k z4QzyiQX+s?E#t4ZfmHK42N@LE+CH$O5RCfJD~!>P7_+9Y>zZF^$(FnIh|E9F1^NcG~t1js2>=p>*Xn#z|KkL7|?%QM~2pzgm60a9R6`qGpZlt1J5v z0#5aN3ke<%#EdRX6xz43$JHbGyOJD$g20w>TcjQLys%(cYS&Z+%OtvaxG3%8_yc=^r*Y% zD6qM%nRX8}MZPJ*OgBB)R)dyTINAhg<@dNx*zq++=GGrPE>K*YN-NAWU|@e%d_T_C zDRj8z)f_w`WiK(yB*v$bGhUx!^Yr~>Osn8|U#s8zh9ab~2fXbL&Sra{`_h@%Fb(sQ<#jA}S} zXX--SG-2x(XM(^?(I|kZ3u@$lR>w%u^-`=oT((&l7od`MEf^~nF2f2vP05C*dyH8* zx2_Ptu|Wp~sxi5L11!~j&*HKldu+PLqnqeQcF&}DRccR2Z+V;(WHb!VCKn!P1*BXP z@u1K+ZD%ef=}U%+5eH>VGD3rag#&)%E3l!i(rUhA_ZH4A)X6L;-s)l{uj zz-hvRR3J)e$dY&9jo)Xn3MuN{y`r;EYN*#4KO2+oAZmHcyF+Lwy4=MaJrqFkvxjW@ zA`T7ZuS^V)Yrp0(jXO==l?=~Ruv^+GpMKh7M*E*<-L0S~diU#|R2$L)J-#cM zwCkljuoK^{%~REL@8s96XXoV9+NcYRl+@sn8DxC>qbN1nap}~Hgu@jT2_M0}ZgYsKI9I zH*xq>VdHgi-b$h6t)gT>SoAV`*5NJtq#M#wVfHgO^KCta2T2f5o2A|5z8LsOCvVBD zz}EN9(t4>wY#ice?j?Cyjpwj`VrQp9o0LE+VC=28J^9SQo9IQUO@lV-Wh;&dt@B5p zZ^}2WXStU~jd1Efhbr`}y{;H&b*aL{-h42%<2`KJWfY}cAIgiWuW=+{kEee>k4j`g zr^bwhstQZUz4+*rFNi%Yd&2&=_V!mu+X=lZo(SXTHnTWyj4~A4 zS${)(@s!v-FpMFB17=0OI>@(qTOb0mo8G?7F+v}F@V_OgiKov^`AT>$A4t);fR zLea%qmI$B-Ujjhz!66XEmcFFKTKWjrrk*ZvE56pMnRz|(hR@0qkrW4?3a9LTVJEz# zLTgye4lPE-!abB$D_~*~gJ+dYXuLjEzG4hf`>k<`u4ilb%;?n<-r28}AS*~RfVzQj z7xM7S6hQbN_xS#j`@nb$TEu!fn} z_2-}{U|2XhR+^W8Bbv(8Y5er^)nK+4TcQ~wpH$x>Jt_a`Vdar?#W{lS^$p-!H#P^pp7 zN5jmf)!7c6UQK`6ry!BABz_FT#XZ9o`+Dll2fG1UZ>i}6x`rK{C}orx=|w^g^cP{* zh0{0U$(%W{lDssi!`cxgRm(!VRYrA$)QguBzUqAd+2!MNk=FZMAn+CT={`ls;AHKS z2H~Wm(c6N|b6*%aXHS=fTuFBo6eTwFBnAO7DWB{9Zxy>4E?av32+~J@qqjm7L$AyB z4&RQ7zpKXD=q9Kp~aM%>(z(_u(9P*Ig7>@$__$EI&@Qfhqpk5~=`@3voM=p!C zVc?-CkZ=MIQ}@I*3qvPpMFy^{jWDXVXQ1K*@XfDbAAa`uwa;i~f`d1AU=V7i(nYt4 zterh*4~5KfvZ>btU(>DY^6VDw;T#LXthcUJ>)+o?!8F*-HwwPL${tT^biD`wy2SecX~o9Mb8kKU zAV2cbVc9FCO(stZ!TrpF&hzS>9UbI)8YhLOP0~E3jj1++B@d@hk(8Xln-?#UyfgJV z3~+LGE&$gxSD3ZnihCX0sLQn)Xn!KRY?xIhcv)0|dIoF}De-!CziZVUNEi zBQu;x&XZ&o_QmwWm%y#%nG5MJ(>U%WD|`yPlC}1;y6=0A+FfnNVgAl#a)Aqgr${?2G)wvg(ZG%H&pUkcL7-ay8y^mn@Ap zNE91Y2A98oZ@srV?8o*7h8}-;?#=S$FXG(?ij~@hG)n)KcBYpkU-+G7mC?D98lNeO zlp+{e*EQaXYgOBiEhgKRkUMYr__uEFeKFKUBOnH|gt8Q}h$&uxhnI!kK|!d`{Y^R9 zq?kQ)kvaMV9lrQS$jar84Yx zymy`UXKq7ePTbXzW!mBkQE{@s!WX$tJB?93vK3Lxpev1w@>jGkx5 z-I6VLz462h6zzVVLBGBg3*(R$c~zsuD`Q<~GB%Qlu(8m;+HgE2=lIqL@_07zTMYaY zQ~I5zv#O9EAi4c9mD~E|>Gb>CR-bZt{ACOj!@efzv+CP@dU$x?N_+WbN%vRJ(R$0G zpoeY6^QQXfxsoxme9U)Y!Fg42A5DR2r7vAXGI8%aL-s%3i#*I(f7V?eVYSp`5VUWa zB%G!w&95>mFMOa^v~E$q+|W_0>x?;`p)o*go{k)su&}zJJ;41^@lg_zNBsXK8Ie4b zS|g-@9vxr2?dxj*42?S^MgfLqWRfb>)r3-Of;;Tref%hg9*&SXgDYoMPxz$d-jmpN z6Zf(9L~Lp`89!^#3t}q?j^?XO4w*1VRsy0ZowU~rWhA6Me`QexR)U#U-qN4acZyt4oy#~`xy{uS~S!k z_e=Z&I9-t|7e1appry^s&&idi7?yM`QpL!paPoT$T+)Q`S$_>4zU^OTXrJh#Bsj z^bg82o)f!d-_u0wE{i0l^>ncM=+;@JR&zGJ-s$U#;U*i9`aBa}AD?QhT1Ti!N~~M4 zX#$wE@(EQEeWbGU>E~a*hi*i?dGn+%wK|VTW6SwW{cFOPN^T`R6F1W9ynF5CYT=K1 zF_JlD=6Q97p0A#OK;uA$(0UkmJ0zPwBp6)wC|8M6m4;r z%KVWbMu~9YOA_UE=&@cw9NdGTl0uD2(@Cn4mzpA^sA^|gRukqnHW~?E@1)7Z$1xx; zlLM0qTX<4P6M-b~frR z&o2k?TuO8ahKM7sU&*VBh$S8_K+R=W)2SYYZ2w%C57$K$G*o31Sbz$(1o#rQBabAHMlSKtm7F`auLlCsGrNEFiiF)dO{@ zX|?8jjJVepdqce?@x!PnSsJ|}>WO#g54<=HY4DS5S?Op_Xn{opS4pzAr)5VP9MB*E zQ=pJ%m@jG8Et~;5JrD!;Qjd&a^*NY&Bliw`qJWz&FsU8_JsH*BWnVwF{O)VB z9@5fH6ILmw99$pIlN>w~d84U{LamduVMSLZZ*9zSR+@N_QcV-Fq-SWI6E!|E#s0(l z^jV(4_<`rU!Y}HO_%!D4GrO~kEZ0yJ&{&MeqF=ER`n>LyP(bT?2VvA12>8}_F@-hsq>JbXK{)L-tdgWz&@ zF2(UPF>(cqWlPIxPSP>Uv$8Y+#i0{H*~!h6f|~Eu(s7i=kS`xni$2a}j&H)e`Ta%kTSCou$%jOr;Mm1X$PV|Yx1h|xAaUEp>CDu->zAoY_%|rUe=-yNfNVsDZg%d z^W0Ct(>p&k(NOIf?6&F2oItM(|Ikry33=&CCB=$^7I{Pc9A`4xl9)lvJvzHSdNYFp zYLZ0M#H)sSQU8NMQaOEn^zLAP!M(3V`e8~0h_5l6057{VG5awR&f)h6$On8KaqXkw zF^gJ{_3rW1p-|SU}Wt|Vr2qGKEp}+CD z{zzdY)W~{TmNtT@eVf# z(Mlf+?;ZPNf~9o6fU?*xY^|e)>Q1vefVEN+D68+zLXbI(Zzb{^<)ebJfVx1wK~u|) zmqz>xO??Nn?(q93e3e$?g3J%$du3)(?HAqa>-UN*&ojOnR}nqR?(R4x+2uz2GYsk! zsaZ0$?5!DvTsA6mm_Cc#Le|@qDwmukrN%%!n75)Nxf0;h4$qWnIn`(lGaw7V_b&Gt z&v_T=-`b2pBz;=B?W9mD=d(#J?n76CQka%m;eVv>M6%DEx;e6XXZ00RP0Zud(~D80 zv@6a!rdbj54T?s+5NAjZ`}XA78_9HTv?%8?zl@0vALj_aBE z@`~wk3zbP>Y_wF``pQIz6GxMJ`pL{%^Tm5`)=f&SxmQXSPalNso~6>t-LZz~mzg~D zXs4`fCmcxAwSlB`zBZrs&i5u6=oFaekm)PoqE$A8cxrYyf|OBP4x!SU*9OD`9kshh zP@AHX!~&Dj+j_4zFRJQx6iCMgx+i*n3%+N%Cz~LviF)zm!pbY(b6~6v`4)!w35FB_ z0w&xKCjb=>Q2YqxF7yKwW8DK-Exfcku1Y*OeUCdLVM!0+Xtt%Cg7VU~jNpFwA`L$s z#tV7;BHZjW0q*)s4XO@YmB&X2+vY)`lHhrC}YB4=z)qLum&dbG8F^@>p&m8#S8g;Q#z?TOz@cbX@7D@onf{(1c9 zr)MTnuqgmX(nWu?WBowGjECfpAWZPAC`-HZ0z)-{HAhjvY?Oo@B%ZvbO+9fSl&0-F zX5n#=dAMY?(I%#ya5wQ5bXSyRJ85^sV%fRp+lAZiJG?_TQZKW$6MhArl0i(jXrMw# z&@z1PxSqOccD!E|CarOEhRNieC9*xsaag#8@yP#qh2jg10p0>j;z+5@!|cvm3{7x6grE zto*XxsfUZIkjFyXoSji6i88ahAWYZXjry8EJn&oOr{xD!t2Jp_$kuJ6fgve)DQ}0C zokn;2S%uuaIQSQ%QnW-*j#Mt!aFJAQ_B9XZA9c?sCs}$0$Df+JNg;PZ!6hJ8*O_%c zFDxV?ty9YRy_a-(?Q|WJf?j;;o0;hSgb_;hICyze!nn8j{CN1nkOKvj`MpM3l%auz z#kacyg{`+OP**?=-U-YruO{=y%b@HJAP6T{vJ}(bV2L}nf96y#Def0#!Gou$WN;NB z@u87L=;*Gv5YuKjAo(}%f-(8S+)u?8(rasFEzYnc=ZVpFn+4!B8H-NM(+;rooR?QE z@E$|romrLGLGj}+CNzsZnF9_OOd57Bf3m~tUq(si`wsY@9DSIa;|0xH?@XY~0%$)% zpNx_K^9EaFt})jm`*j<9MCJ*T=Vcr$tYb(bs?i7V6hg1i_}`2lCQX1W&di#xFu%j9 zyo_-{L$SI$SITw|=1Dg2s$03Lilx*`{b+IO6(*(}xCtef6$`wyG?(*9t({NFS27Jt zo~m|*Shm8u04p_If*tuBs8T=e=AEbY?on>r^#$@b-WflfFKb$ap}`Z zNR4V4Qp7=08K?QA0@N_Vusu!oPC6EfApwy|9d=mn-B|JSjR2cljB|Lacku+1?MtH-JN# z4w5tlkq2&&uP^MX$V_2H*@@Vw6qD+NLj6MUSGjjp-D%Y;Q!0>n6W+v%ZPWx-TbYU` z0*1s33`1*zjQ(XD8BhY-GXH^oLRN-t!@YM`ct6S6EOd|c=jy4kB*J++0E`?E`>+rL za`t@+J>z9Zj9DDK5Tm^?pB2of$)LGZX+sxE_X&a3O8!vTU3m4IC=YmbL3~&`-B$ZD z^Q01(aGx*YdnCBR0AnjBtZ1>U@n4>r8WvnwE0AMFmqmM*ydYY)76P@jwDcnnq$(^P zzO-cRhjy{a>l-j|AsMDrQ-zsqgR~{+%;-c;6ZWd3+~GQVe1Jn-!G97F(1yknv^c>* z6zB}o`*5jOzW2cXc#0cld8Zjm(xfcQyiSCq!k2si6j77dg7zP7VGp2bY^igj$^XXd z@W}nJi^k82@I?dqxO2iyySnLXu6%nqv2JyhmB#I7N46D1st=mBBR=&neXX`?Z;{t+ zvf=i29DJ*rry9IY$7DCEz+^uJ=MF@gdf%hp-Vfe)SMPD(z%S7(hWk;E_NI*V7gP4t ztR=7h+N9i>^bZi6>V*0`^@c#cuk_c7p5Jad_seyu`_b<@kow_mQ&N~bA}J#P4Yn@$ z4@pHFoOluM&K*!5q_!vdyVV#wa(6=ny7~IAO|PTHJrlXKvTKK36ARxA3kvwD3}NrO zHPy1{yPv6^Jn;!zbTBM1_LK3n=}5>?NRHLlF57(h>`M>n7jkv4+BuUDUB$Z|53?!M z#+hF6S#v7PgnjL%5t}=<8ck5M{_#~rOEqB2zJ*aMH4;w#=+j-$E-f&K!MKdPfT~FV zmIJXH!5^T0+iAKg2r!+Fe11jv21UA05v53spZj_|dHg-0>4epSI^uZk8_UtcT7y-` zk77A9hk?kd55WtQwu2kPY}|Fc#ip7MvVz0R031D6tHZ5(Qws^1sa^6XwrYLWgwKtx z0Ka&g!D{OC*3a%|Jel*BH)H$9P}6ep)w+q7d8>T!!3U-v8tJ|39Vt)u+Lvw=o)-;dPaZyQFJ*_uEN5rqUEdU!yxb*G86Da>8ZuTw2|Ph!sR4M?kWOiW zr!IuLiE}$cU(s=0^s!He*9~bO$y=IPT{(N&@FG< z=0~>l#>+cdd>c3C6WV)3^%Ns0onTJk6XyqP%+(dZQ@=){t|kxds(MV$;P13=&IlgI zr(jGN?O$@eh4JQgKM|pD3y&2!dEy=$HPbM);fyiK4o&Xg<^E7(|Bz+*%ys)7B>c=e zLSjqu)z8YD5iTx7YN%2KdHZ&MG+z)j6^`k6v8-R9o%vA(nxul z6^YmX7L(}EFm^(7NAKQ^9TtkxzD=S2aAl{(Bp&V&Ct}3^eGm0s0bh5Fo9nrLobHj? zsfWkm(fafA_U(&QBB}BvjLDuWJc4sS=Q7KKib{9blTahI^P|p7-K6I%-({-XdHlG! zcdg!4nI^>Qc?oI(NMXRJ5FY(~zSFsz-2AY0@N^|F9fPiB+F$4CB@Q*8Oh`3o>+pO; z&fZF85bQY6Kf@q_cikaC=S|?1rH>=DkiwR1W*uk-JUGnwNY9r%qL-04ww>?rcIAG; zXp>}cfr-deQRziF?YWi#OQ)+P*&fwTNIiUpMR01ZvN_{p14n!wkIdwcoOX8J&U+b_ zf&{{K5}r`7#e#rl2nD~7xdC?G2kc;(`}%GJmogkf31TP4ZnVkWI5G)RChAi(V^clb z=~??Dk9TXW)7NR4O6!;#;`19lJa_k5BGL+`mEzzwbDA}0DlJFG1sk@W2HVV z(cwW7Mrom@=lk1Y-b^T+2z8uV>8L|PzOZ(>M*B=Hor;)yPT)?GYf zl)n8->9OCXfc$sqAiB^4@4 zE=U1x4u?UoC_)(()H?+<1OF%l{%D*%6XpNI_~Qn_uxZ^=HL7cjS*LG^mR|I#6zcH=XvaX4v6O2;fd^Q^HFli& zwbS{|f`y+AE0T^+h&Z%NDy3!H54vU)eRxi`v6+Yka)+O3WOS;iOiMAoe|pG$G|Ti% z$D=rTx`Dc|Ep~h9`VsT}g_R&}lhB||P*Wv@`|j+HH@INg zpmZ$gaqzBr{8RC(9<1jrU(f)50DaxRVFTah{s-?jV7&MX6SQ~=xoH+w38G#kT`(X% zOLp_sj^@_(2)m{O_~ilt#IFDq?F)E}fMQn=hEC`)#oB0XipOpZ3v<;$LyxqnD&_k( zA^Y%Ek{i)?-<*l6gRq53e_eq!B6RKZ=*>LLBVL>R@IZ{yv-MPp+64MKi2(lT3pmx_ ziB5{St{W2S?ZFz~#ddA9hw+|CsbgqglLt`YX;9JhX*R9r1S99vk$@ctE%y@x?Z5^Z z<|2THQTcdHF&Wf_u(giO^O<%MO3L?`!suxAjyPxtH!tJ<(NE{rCl4~R4UnywMf(rs z7k^R}Edd@~KDO9FVGEdA1wCW(t(Dc|FBtB5uXAZFL5f;ltatR86?q5(f+8kquu?7h|>=)0t&6yn`&5LwzFoPX}5&#KWyC=5vwN0GU^Hv z2hbbdHIdRMi?>J0tV0rQf2_n@%~4>-nsmw%{0N5QG0(y|WvC;}b4& zK|g@nv`dLeqT-xVN>VaqzFtc2iyKG{1P}Zqtmjwvt&d`#I!bDJvTGAn;Oy^EN2`=L zcZCfG0H#iw@VtR(DjAsx3=I}D_w=k(M`Bp-{siE@p3h1CkO=%spSljxB&zdKyF;P$ z9G(Ca-Wxtz* zPsbaT1l>ip`sILl=g|y+XZ?bnFz?ZrsX|U_RlfS2+(-#io?{?^ZwM53 zsgJckTM_aLTmY1W0acj0!mo~Ad4PErXl=hJahgs*J&%rqd(}r4l^nD-)O;}Q3z&cT zLG(T{XRIMg71gd7mY4BrojUHZb`6jT0-Nnxx(UXA29-(c{$H~6Fa4Jk$|$RKk_W`N z;~)~En(#WST42_@SD+wN#L+H7hPsNYMKR=A=6jV{MF_ai{b_KooifYqTsiRq zDfA0zL)q5vsJ}2gGBq0%u<4tUHZQrsIT7m}t(wNLn>R@$AyE+uozli%lhf4L7#Ym+ zIYH?I?FsTq(L5`q>801b6qsFXE{zSyCt!BtQGA7E-0^%g6L-M*5eh1kL&zA+0Q}za z8yRf^Bo*Z81E8BB0~{sl^{a8dd!iXy;v>=~i|&@Osb`|Ph`a4Qivy8xMU_WD=i-}! zP0~a>SE|=D_3y1{B?(ymJ*TPC-pTsUj^cPl>s*JDfP#$m;{`CU%HRWcRl8FL?{b5S zg4Or%i*yTEy#+Ufw5S3NEWo6*&OF}Z{&OAx$j7nd_UV*L7nzMr;jhc>A_QQl`B}@H zK3%mLzfJ*F6y?7HQbl&`=dfq#G-DaDKepoD|JMUyIp-kn2dQKP4~RyFwlG-z4mq%# z!58RwasC1ahA#JIq3cMaLwWptWx-P}$r=ih{ATnB^I{v}&kzE1&-vh`gUp{8MvRZs zK7@dx%Z^sQp4p56*wmFFx+GePE&@oXBQf~jY6~Jqf8RHR*BTpxiJTg9V?9UiSE4i+ z$GNI5;jXhdFdq|(pNy!gGWyU$#>PgZ{MfYH$^MTlA;WxHju|v}kMeru(dFdEB_)r{ zyUuh&*~n9z121rtNczMD#-GxFP(~5F=IcvOc;g&F&+uWNt?=6i-kkHSgx_adG&|$D zp1WLSFx{2NY4o_Lx7h#L`S?>Hit|@#z2tJkD!q;Idk$|OJ(?973=#OYaEQaeLWp(i zc!OZwY0h&?#X$3!9UC)nvcOlA%s&1f0uS>f3^z|h$0vpMIgpVJB>#NHZ4#W9CkmAf zYI}wk?*0DN-cG8LWptMg5RxcZZYtXst^cny-(Rl_V>zyqr`ZR@CEunpS(7JnC|#6G zsS-rXZvKV0%JX^10y7lj3Le-ojY%@UiVxF)_w zEkSRht?6=lR%8hWxM>@yF9MT~P<9yi*B%QLb}H1 zl&`~OejLw66=-zt<={UQ*V!eSbEE-5{XtOk*$ij?&uK`-*(3{{hmQ{3I4UW^btAP{ z4&X90LF^u2q4eIykboiMXLWejUZ-2(kw<1Y(Dq#Mu6}3@f{yH#sxP$cYN#PAo<2}4 z>DrAKEAqA05D>n2h~SU6H|5RQ*juAywMDGx=YJ0VWzu5FJSmL(z)uJ|RVYzE z81J<+{-s_Y2~Sgj2ydOAo8TY=eqyeT?9kcS(gF9?@tcoKE9%=0$a$| zWu^vu6vzo5Jdf62ALH~e+YG_~LBBSl?a>;{Z-mqLH+NP7i2vhb-oF~U)0~HQVD)I~ z%f{UZSUrG!SJ|4S%79AjHQVbw7ET#u7&0b;x^b_sCsTR&+-_r(0%I{E`C^h8Se_N zJ(h2`N5bk8hqaEE0ao|lAFO!A(4Q*C-xrI4=Q=zp`vi=gn4~NL>E93j{rFLEd{^N=K2z}W<~w(MKoSHQoFMnW+E zoLexdg6rcUp20~ObT0rKH&Byb^7Wkq?}90X;y=ai7PhCbf26Y)aIrO|QBo6ZuXahy zU;d@&VNuKi9|?{ADEe>jg80D@t?ycz=$|t zkDqw5aJly`R&?$Wn23XyiERvz?1K$4!s^T=(AIijI!v?p;LleanP&-K=$@uoRYw0EaT9 zm~(%sf1X}r36_I>$F=D{DpfF`zi#{=tGTfE=E`s24+MQOI8gQXyv?m!CDB8XD+$yw@3)*Lf04t11*9Y)%}x3 zeMGTgQ*FQ29rsi+z*>56{OA(E`7LOHPV%n>>wu-hD&^wKwgNq|KFK2lH(5}mFBM>O za?YB+vVjc9?@zFV6JCH z>?S$6!SZnt?DD(qqz13P44o}v=(p_qA62nvI50gk+Wx*?%FJ{~OX>upjGVP+IgAp55`1m1{wRF@ zbG8z8gqkV9{)snh&1Nm;}wV1*~)1y23byFV}5K-XwzUTZOfQ-e5FQ4LB#XQCR2`==YuZ0g ze;_;gzxv3&?%mr{HGas90UD zGMsp&(rz!!6StYbT`ORTqQ+00B4kiw?DJDKwTP!~XN|sIsv3p5nXLD`=`6|)4o}~# zH?fh`rKDd6Ku}Smj+x0nb3;Y|&Nv{h4jKe&#$D>uP&z$<0ynyihb8$a49%d=`*Pmu zU6g?$QEyFA(4`(ypL=q&ncxcUC_^r)?l0W_T*Q;JC#H+4D6tK`?DzC( z5WH($X~j(^92ViR4`66u$dUQ#ofCEGfe}gSV&;JqO+Ds@!UgT51N(;Rn5vC(-__2yhTcdNLsic;h4CegiHAfQ@G5t8$@j5D2B_YwNecU7*26*x(U4PPx= zNt?|e$L;&WkfP=TXG6UlgMij_+lb8qJ-E|Z-9`;k|Ew%+XOBi50Vt&O9YnXpNDU0J z7Lv^9L2r)!!zs~62gj6bfA$#(*+FGlWc*w@ms;E3XK2*RneA1XF4lP;=PSLsBv^UR zw)83S@dd!#16?t!Rq+wec)D6rqLW9|o3EiDBFqUCZJ|_1Omx`KxhRQvb(^_ZNsWA| zz0HO(X=`wll38AyfW*hQEjq z9y^e~2>ogSky##UaA;9I#PNGK_)Y-pamX_>R2oB2Ba7IiBs#9(@R$|IETr093J}+* zv7d?eO`VeIGJgTf`tbZI=h5ROhI3*LbiaAvjVt>tSm%X_)0}SdoKVE>U zOgOBEjx{;QIWA8BzBPpU|FQShZ&5zqAFv<_7;j2I0qIaWq`Ra+q?T5?k?vBE4naCq zkOr4-6c&(@?vn0BY8P1InZ?ih^Zh>8_5BB)>w12hh5No|=FF+rnKNgUc)g<3gFt7T=Y#AA}Cr?10!+e!^bKm zZ#K}EevR~aJNO@O?{@%JOZS2j+Rq#6=g9f7o{9Yos6r>|-)7-%C1C|VJf8`YiFk`h z$YMT15)+u!;SE%>BQ9RKYNY}%$v?Xgc}#_gg3Wq+1`?e&A+}AwhI)?8%}H8GOQ4N4 zn9Q^1TVlC6OUps)8HUDz4Yhl0L0=IE@}In2Uz9HjNAi=r0v-hYnP2^WNGIH(kIV!V z^Y}x7@f2!gHIfD~TLhlkZ#>NZ_cm>S9a-ZMaZs!M%=6f?%d9MWH-fpLf)C}0nEtnc z8aM)4CZf$LR<8N+e&rc$eYj2q&5bKic_tX~-a`Ol|1H2KgLMrd&J}<`KeC*^sImnX z)STSMjTtC@*8B?Rmj-c=vnk+>4I4&404w^Ux9w{SyE^^Q_IaH@5U&O=eDxi@X=DuA zFrGZ1ks!iSR$?V`F$KU4O>#-hZ1{rQvd6j9mo5HW+oB0hPvZ9=rLHbh;xab;XtnaG z>*<%!r@KwGwT{^P??B!N)!vNKzt-}}Wq^nRP8zfW1 zg&nB0cMI>GHcrA%s9{6VHa2sQB$=__3Yj`PC%$HMts zoM5c5pc_}id(Xm;%QG7b_F7v%@$uRYg2T&Ssv;yQ6&_+6L58QW`ep|}robH-X*W8j!-QM4 zmk0WzYWN=yqbR*O?o$c|vDXVE0JG4IkDdPyw~M&6i6C!e7*HDjEBgYiR3t!x1c}34 zwCl*zdNe~^3er~7v)zl$0e-sE+Qr&;c<+AwkGUJIcJTrJs+y+Bek4n@KcrFN{Irck<>~eiYV*hIWwhPn z(vF~Ti!vf6Rr+c_6TqSlrO$rgx!FNFT;fHg;k-)kZ8CX-=BMW+hQ~4fvX{Y?r0!Dl z^rkh27YQr;ZQGZieUbGeOG?r)V{bwwj@yD+rj&>k7Yw6>EN_`}-Iiog8+<>`D`QQ; zLc-NDl=`1#u1pTw?V6cXu&@O%XG3oSPBbV0+O3{JBaGnmeQ@9p@xaEg3WLNQBdQG-}bQnbE!}|GXKG~^vzuBQhwIom5s`+q{DGwaA zHH|y04AXD1QK2@{3bbZ{dR~cSt*=i?J??n+u}|RMHK%mYNJ0n!r%(aE{``aG4k1<* z)<1COuVdL1`PviOIYre(H*l~-&^3}=o_4%9kVo_L7NVtpL1|%6m@c%f*_}%CxfTok z%aGuT#rH2)omUI=LJnLPYJ1%nNbZ)n6y*+%keUzkx^3T%A#vs%`NNg))Uxk|dTFj` z5)%Wdj$U^WBgjlsV{PUtf|;m4WA?cNH2=$`lTQ!i@x%w^e$r|^=oWya-4C#-h_e*Q z-|6E012_7}vwHl}sW{PuFfGalxJriM467MJtvkp(ZBwV!)Q|QewIF`^fiC(r(W86} z3%I3xi2ws`FNouLqH#acCF=28kfkM(iH{8VU;a(XY2HHF#l|sgshWpbD_4%AE)XtK z%azEYQNg4AB)lV0-q$rI_9w6SmBE~1i5q$CMvOWGNpEI{QgX6QfkPtfWnOZR*r=0K zDSfY(bAgr70EezQLwXzbb~re>H<20RhL*$cXp{{qcG%s;YD0UWY)fvyyEhu(M6BP& zbclnT2e;{y^FB~}qFfA7C$%kD4rYa}B-}Y2P*Y2zIa30u{H)NU&H}>7Rf5(kwLd(x zP+C#dlq_v&d7f%qQ7ZLOvCJ2pe*n;nJgMp;K82Vxj^Bp+A-||@QrONNO8(=}2X8JwE+@P}=s6$1r2-$f&z-p$B#9Hn3%^GnARvFA&!+Y> zRG2?nO|eK`+!4k5#_T2E+iWyio{yd@%i$&G!!D{g@tc~wh>zq6xd95WP3qsj`PT=M z0(b#kzUe53!|*shS8;TP^#f&X%6M;j^mwUNuaKWjF(0L&SvBMf?ks zwg`7HFPNmSBw*a@lTH%&kb_S3v(?Z9*NLi+FJ;6iJc5fX=wGZ~CQ97J5m62)`49SKEb(m{u z=QlEggQ4k!B^ES5N!(pDvBBrOmY3W4Fi!k1at!pxv}cEdL%_(I(B^deQRk%u@I}xP zx9%V&AFaobRM6?|GWdGBrXj2%SqqyTACv?Kl`e7#$(^{a)pm9Nf8ZIP|H@RzEYEgI zeKsiJl;CcM1=iFWy?{vspu)^J;h;9U8kgRDiYU0?7P{0$$pXM7T4^;Fuq{ZA`cSH) zZp&~OsA+0l1qHi@ymK><`QCSdK9L5a)db$22Oz(*P76L8j*OCow&_@74n^h&-v@s^ zb(z*O@o?r6s~=0=UFe4l6!GKmaM9AkF2V}+?q?8kep_H7_!%`#c>k0~efUasN}sF; z9r>8LKR~Fq#dEOaulY_cD!)W-Z^F-cv0&%vGcjA7v7$$f!xj7%0TTKFrz#>^T$9t! zO_0+MuNPsWBK89K7Xt5r{F=TDl8^vL!Yjy>*u#t6mPgQ&6k&W9aI zWwcDXd5g7Z(`KVL(hkFVAP?pLhGj4fot-R{>Br;Cbq1I6deH%!j%PMcp(dh^%I~7u z&Hic&dK@L7El%En-oy{04BrMS0upp12k+iRhW;-Lcdap+Hx*dx-HRJ!G|HKTYM*af zjXR!&-xlLbx)bwYID{>2codiJ>C-|&s5}`kKud4SGH337qA$)L9%G&rF}0UJZW|3A zQOpVCX`){5GCDQSP6$)^zbqn*G`&JJ8h|}+s@>^Ks>xy@Y~umnBa>>DR_!v=HGgn_ z0XI!er*dK7 zls#{mYSq)LzOdU`1Ls$Wcb1n|@nNi^ zYu+kS;@V9xCj1B8y#zS!rk3_xIb7xf+kD8lY@3z2%u}TGIbJjW#=|7FA8W(H!(Cj_ zeOXdSL~|aDOZvF(vo~wpvKK%Jqh)SN1k&Z{a^AgvA(P0&D-*LmQu_TGid zA|cJp0TPY}V_qduYF;fK9~?=rzMIj&ccf6uOb1JbWYrC6NugXn4o)zuwblTICiq^Ax?14%5nPztpd) z6k0_dNqP!-+EIXY%3vnCTHm{9fjo3kHYHdz@p8No;nuujZ#=MF6+*KkD+^Chy(G01 zW+Q@Ru*~n)$AI7R!92gYL3y!*KSth9uSmVAOKA+VUXI|>(A);1n~p;A$)VxfDqS&<>n)cY}7{WhTdK9s(? zEP6#)tV;Y@Ju}R~PE}L;(D6w1BZRf{gt$afB;c1E>1o(Pps>#%4@ZlZqKU#H?`EM~ z!RhJx?X)`VVz8e&Eoq-N#_u{JY4WHoSd#h`6~<+9HWlCA*R|;30^idL1Y1<1iRz6+ z2$x(0?q5hoApw4(w*5_Nv0J{EEIbVOM7 zC*7&M5ipDuJw5UaNmI+gzINY~y4)GgUOOpop(+|8V{ya;>J2R7s*hfs<7e1tv6 zXSxu%kdzq^Cd~nLSeJt-5_WEN_Ad@iJ|<*2*CBi!C_#ZMa1m-jF;r(`4JtC{-TeV{ z6i|u}(Gh<92k-0C0!OaI;F{sbM<$<#G8GZc&d1Te<9_S5iC$rtOX>WZ3ou*~_}fJu z!gaU3?;=XEB;|FN3^l$mrs~zFM~#`@K8*7JQ$@NJoq}t-c2Vt^f8{p|*yFM%!^54$ z$FcjdQvjQ;?pmf{)>L>Z3haK`PIdWK z`43jcCDIANk1h; z=aZ)9C>(){y=9=;Y9pt^soaOMgy-`klKDSxEtls8f4t+)7VU<10nk?Pz>LnRl`448JHkM`QP%f zubu*`Deap$hvL6ETj)Y-Fw&Q3i`YA^{CR7@P$`k!QAYE*IN{U6tcQHmgLN6{X#pt1 zvN(kq_jA?uF6FNoT+*9wzpjTVXgaNegPXUe7)UM22yNU~d#wMu92rTXz|D|ZIigCF zkLLn%(<$)!!QT)-BN{WY7>Dt31D-OgdH<-`t59 zbW}fY4v4VRrwMfd3wyh$#*->CiIoWYQ?cSS+fR~bK7*-@O4ysT`Q$7EoHIN-l8kv* z+?m@n^Vck@84A~OKsgR|ow|sxHLSVS0YYr+g38JYg#QiH3F zhvaX8PY$$%JugXJ{}7{&HE zqdm_~Uv}YY33i%h2UwFd3s^rxhqt?Xn2!s7&--B)OnF5s?GzerCrJhGdmalc!q5Fo zTKK=3M~Wh;KFR_B6M}Wy$glvhjwPuodhx z;pF9yJsIMNT+s2cNEKBrD9r^Yw6}a%Cj{8xmdC&6niVxQte+N+K`4AU!>fU}V}G$) zE0LJ^@wG^{$aCHA%?-Z8(!FTmGrzPY(n0TFW?V{-INzYu1?mG`Snw|{P(-7q`-|BB zuEuVU4k+v_hf^H0BcWiJj-SXj_fTn1;1hE#1e79&j*9LRh-l<mB$xJVe=!JCY=- zZu2=1$Pt>-Kyx29evv~Gb`jBltRuf`(wHi9-2qpN{sxR))AnZH1RQ@+rIh-6uLKU* z!oABMO7&kg!eR`{@dK!~xsX;gd&Q(EUx@$gUUMgW%V&{3No1?bq)5AeD=16L=8I>2 z9dqr;fNu#0sK+A0FFq9)`$#oYK#}6+3KQGG*#`#K0 z;!{{3F#F=VD?nn@p5?3BG?(9XeAMqD{^D1HbV#5HK?g_Kucdt21Eq3kBU!P?cuI!m zQ_iIHW*tyZpN+$cHm$mnRljD*M2I7Glj+^y8PTLoDJlI z5E;>J>+kcvGBaf9ELf;D@;r5HSlBCt@Q=HY^@o!(Bn>sEzlMjDdw`pfry*z-E+pLk z4J&_g3>8PC#cH3MsBqE0Xl&=y^f`VQFq;8Z&zmLFnc|`!-o10jdgFTwga2lHKWQc- zbl654Pb7~%&6u$Nb4(&@TrBolfb3F!Yl@d7IP#$7Tryq2?ib?$zS^jrH&CqSKS8Ez|%QX?JM*YdLrWIyqYV)`{2st{Aya5 zs6a5nCRS$>SLsE92`Ni%|;K-@^xY$wWI-o z@hrIHINKS5c?XjQt33;!I#ON=$EU@^VLMa9IL|vhHLDPQ*)K@h&Oc{Z>tFkIZ#Q7B zDC^BH26a?9TYxAt`7gSeIgREUTSX()%o>YPvIOJ}-K_Ghf8m zA{H6DFKNqC6LqG}N6MU1kwGs7y5*8EUC&1P_dks5$ds576dP*!So>S8q1-PJ#ZOFl z+ckdSp4Lv=Wee;XV@VBk9f}++Yv2T{QV)1OhuxV=pVU#p{Dj?KAt-wb6cB!B@9)-o zWYsP^ccfm#S~KnY&1(fJc%Puxf43~mXrb{>`hA-2ONVW?P?;x)(?68ap$4ex2I+q; zQ&Popvg@6ZhALUB!TGVm*D7`Sibi=aXn)nWrR-&}y}uVR zez*ti{YO39w_I?%hjStQRd8tYMBt>?@K81vsSy`1AwE^wsi$ec&Gf|nsZy&re^$sz zY*^@atb1%n-DN~+uaQ1wc;;|uuG6A_va1TzI4OmhXa5*3yob-mGKZw2;^v<{DK{^G zxBSD`7#rZKSw6udho`k18+-l)#U*mSu|PNDrd!k$E{A+;^%awg#bv=0sIBwFd3H1L z8`GvQr-xdmXvZzPb{1@-&M0a9OqGhs=bRpN4g0giJM=J1o$OtCdbF42F65$wctUxO;-l$ z&)#836z<#;9rz5qc(QUjd%Z4qL1*^jNg1IM|NWT8P=*fj84DyOee1e{Wpu2+THBbR zJDfb7hte~5!qJ$YyQV9qrch~Nx$}f3+0gW|{OZi&w;^6yvyL$jlKzEu0FF-h$bpyj zkEJJ+Gp**QjqudvONZxs%_zn7hE~D!^q8((R6fg#uhm{#$uZnI##fO)b+~B~KT2;* zjz6qyci-FN{Xw#Rm+FhEs=xWM`J>poqErKigT~JHWdf->;YIOLLWL`*UJXyG2PX zDxdfIWvAWU8hyq!6d(0r@n#c-svGRkN~+7*A{#B4QewBM#KoTzS_(D!~?Zi-D$ z3XGCKSAI;@NK?}%M3D!$r3-E>Q^k}TM3I-Dz1fJ!J@C=^B=1?5UN^mDlNOfv ztY(&L=hDIu0~zJQ&b6K`ShhbyS|fxwIA=Uw)bLNJ3FBQZ$KyA`g-7rp9BHlXn8{~q znvfgm0auol+t_l?ms<9g=S_DmCmjvr7i#+<_C5!j^+S%3EB&rdb6s^#rI$6pO|x0u zwVj?+LHTveVarfAob-@?UPy0dN;-n3`h;%ZMG5t&2Q0Knz}LO0wKV- zUlzgzT;Z9>6zrNwm_ft#ueI>(1-qJA-;uA(BqN1IBfg zOMh2U9oC3TcX(bj*JM#xVvUaGu;<0x?$yLL(xS4m>wVPFo&jfG^2s8R&RomX#G9_9 zy`bUC{%OpV6SuQ$OPN;P1?NtY*6un~*leu7>++trmQT@zLx|q2;}FxKOXsiq&JyDUX~#L z@!*g#9!oQtVCsZ*+(jXo)@RyEQTom^nw?ASME-pJtg|lp@-QKr?b3=R#dk(3+KSEkK4luf(8%wMer`_9$ABF5q+HY6+URH3r0h9(~81fi+j8vYO2*s2n|y&x5`gs9glXS)%yXVgA} z{#4->ZRWb6{z?DL^|4OcTJl&o5?IVT=JR7=r5hW(wT*=6ZRRM&9Qhj7Fygg2wZ({i zRO0RSA~l>VzSHj!ld0(lo%$M`$5hjgIH<0J#xa`ID_P}oRJeZDCFn)!t>rpx=|4|C z`kp{<(w&m(JQvNv%cOK8pjcY)m`I6CUVtr-x${d1woCeLi{DytJk6qox95*UWnFp30@iM$nh$#FAYSDE-y9 z33SygWRLRe2DwDHYYL|zrB0FAA%6xmEQDT)*y_3YKFOoZtA zWiy&Eh{kp7veDVs>PfD!^H!op$`nhQCS0k0_r3^EL@WhWMTnjn`M*;W6)vYKX*gd_ zTFhl*QYO>4PK0a;`)$5s7yb1zJn<-9xgmCPJ$&~-g1I+zr-;h{bK5jnkTYc+P?eIL4$Q^Odu55U8k|$rIm-q1Gt~-Nv{6a+pgw~(o;xayI zP!Z)WtS}~r=!Eb6@+^Svh?N@;BLoh$_!!ujR0yFg0D z4RykIA*vgU2g6D5F^0=;$Xe%)8@uI(lB?Pj8-kYEmkd1STha5P(Ahjvg=Olqi%H=jv)3vcW}u0 zggwR68C9IAWb($pKz72N60u4ng4T_FqXkchsKWhREQUS7Z4ssKzjfu#s6DD}NRC6b zVd(FuU(UonBs=Z8{PkF0!N+8C-j17n)f}s$@Dj$;C2QKj5>p(9#F_x4!KYOqPR=KZsxbl7cVt>d1?1O86?nI!~Cg#OYN{FssNNxQc3^Ef{D z%JY`#>I}}!`Jo=?wp?hcrQoMMAwm|9`Padx9g!T*5HPZXr6nV!qRQFWv_=J%-TNp zQ0KxDsWA}lLp^35U$YTc#UE|t)9g0EWeh?HeYr|y$8Z$AV}C;E@NVtnX-{dh*?I1s zoJ3LRaA#Q~>yTgFzGzd#&&7(W1;&)sH201OhohD;l6Q0ja$@~0nVhPyiVHe&_4U#$ z`Q;QoBfs7n+Wp;Gr7yKt-Rrjb6!!k-k?CKOSx@-zNI$79G}LvKQE`?x*N6}X*csQE zDwVNlDLFZIS1tT5K)vo36eD0MjYU-CabfQgHD_|{?gk^$hmU-T?KS_r35ay6G2d6u zGPNr^v(PToJZ#P!^efK2Na|~HWOCipLENQ1n9N>>_)wh9Urw{h@{}>_Y8b0Gi#f-9l9e@ok~h-+j5{0qoPj7wvI2}vRCNYb z{Mf%>oA)oIm>3H^Y81gbh_aL^IXEF!vX!Ae%F(6MsT$St5nK$gua{MtuvuNn&66)R zNOp;&iK{AsrjXRz3}Fo?8I#QU*Oo1)29=iGYg}!ta^GDIF16dq8dpthRnu3T+ETh# z)K{kA_t)`Ucxq8~GspsW<^cXB62s3!qPquKJGs9to}X%m-)5>s!o0IFwfV zhU)j=Hr(K>*mbWB4hoX{5;?MeAxPvm!N-`g=v5*aT4y#QA}Ee9%2T_(cs($z<6*(g z|17QBA5uS7{=X|b+tPU!K?q*ae&93H7!o$-o@;=AeQ!J_bzm5AAQ9)MH)zv=*Oz7M zPR2J0&e!I@Ap!HF#XUMYO2MYewiFZamH!IJ$o+bW8pkyW?KM?C>zN^=)%NlWUA^ue zU+o4#|8oX;jp^8Q9OGpIm*R2WR^dJ-Bw!(8{O7HN zCE9KaD}8Ayr7=mI@PMFirAN~`D#)7%EKq>=rAg(bkZtNEd5ONG+z@J*2y))TU3pZ^ z-_d`@TgL3Qrk+lo-MnKJq$HKoh;_RqzkF)LZ#y*_6>7M8w2{D(_JiF1 z)mdqyyGPKF5LO!fH?yg2i+QE;l--(nfkR@j0AH3Qzybtnnw7RakIoF4UmGug+3>tz z$G)bVBz_Jd3l9G)nINp5_|PktO=q5fAwnMC$ou_8#U(GP3E1xkA&5LZI_~hGQg2xd z2KujwZd(?&5whSzr}yrb;h>qF7I2b8;0-M58$ry360oArI-450xFW58h%3*JYx}g{ zq3FyK$HIB5^s!3v*Vy>{CXCwcgxuI(z{CJL<<6vF%I)iU zsh~9s*<&WD98S!k;kFQ^&!p1L9v3YZb1k;1ygJ6blhK=ZZ~h2*M>jY!Vmj}OG6cuD z$=6o%dZU{JUJrivRl?a-r7^j+ZgTJK4Xh%m8wAD7S-Di#qk9FuZ6YE;ZGd?&-lmhp z#$VoindG&->!GZsR##)9D~j`zZ@?B*i`TW>q6a(jh4Cs^kn*qtS;58_MU&SZZ6lm4=uco8K z#D5YG-u~cP&j*N)f#Vtpe%1aQ0cQ%qFYu+?|KI+S6={&pg8xjP?wL(_@0{4xEtel( zD*GmC$zLPLs}#!j-j}sz={g>d&5Vgm1fls4kWK14>4Jm*r5BIaxE+r_?2XIsujzyf zcW4G=uQl^`IiPi%FaVR}s9-Vv@*VZ{SSuMV&J=SFPUUoN995g?I7Z)Z zU#}8ATF2Z(H|=SuE63XXkM$3yh4)e@2Y68rO~-ZZc@IxMW#`^0R_Uw1_je#_fhXD` zrh0$n!Va){h11d#^cPZba{IM4LK1Q5u&;H##4D^Y#~?v07xef?KY}Gxd8}4Tb0f$E zN2YSD^|I7!cXxgaqE0-%Rh-&|_vudY!vh22Yqp4>m+)nYXPDPU4pY(49QO zgvHB$n98|#^K1^l}400X6>+VtU@ z#;7&+-*Ga6ai(!jpg(gXh#pN$JoG4U5e!b*6n(pc*=K&;T@DKvrQr|NFMkCsN)l%B zPy$qxs?{#x^l19?`4knOw^mBLXCV^VzNP%TpO~eOxbn(DmGaWRa*ero^wBN90r^+a zTH3sOd$lc7mI=}QWKpS6qXPFZJMcF)H@Ry21Ad68&Kl!#?w6);b!lzONi1D{^WRQa zyEhFx+N5hNH~@?^4CazYu;hdD(6r3gH|7-HC)XceyYLBYi(Nm$RR{eWaoH z*_znM0Nu11shzIcbYoMK7kr6C(4)V@^k<%T;+Ziyl+CI2&G54qx4^8m{?Ph8`S@Mu z@<7LBjz~?`euwK-;8gV$s&BfuRL?5iph*bJ3{B&$lgf>(rpsTAYnL5YoJe-P2fS{5 zeEO-89#i!j7WHCS)UOD>fq3Q3v-CL-_<;L7$Jvk0zK^BHMC}yNxzw@NA{!ZwDqUW= z!%GtwrbQ$-(!YlDQ+X#C`^sWm&rOTR968sQ(tn%ZgXR}daMW?{zE`cUr6yR+TF!eS z4SAgMAE&1F|A>*M8N7oLjVeCcH1+@UX|6w||9zFS;I9z$E8*x@(l};$+DkSzY2cQ$ zosw>hpfk(85u^;}?)&;1*9v{Ct+_u79995^1`fkz$mi{pVwbb~K$AYPu^#^L-bt@3tdex{{^1LrZfz!s0w^@v&p}ZJHNM zn6L{Wuk;ovYGu&kym+hingE!nUMdI?K86?hA}qDCZ<9_g1(&Y&?oV!Iz;;_wua*F( zd0779CVCzdHn05?NY9g)8&0hPH3p9`@qa!Ktjmrjk{e40LfL$wwnu~$*T*dac+!E0 zI(4@O+p1L+D-7j!z~>htkpfz;&u$gB0qabhB>s(&8k4>fL-3{s^$QKq;&l_5gWthe z^4Iw`@&wII)NmdO>NwRK1T2{ZazG1p+g)oRe0+@fslbe&r-@7wv*k^Zo77luK?`qQ z_Tj@Dz>eL>2*iC&NS%6rgadLbNQi(swKSo2)3z2DAKAEzF%1Mh3>AfelM8I7q9u%g zmqCJCU!!Zp9tTS%(2S4T@|EH$c$8(&L;70*vAY(<`YIEP0Feqr2LY zIjW$wy<&ehZ4YSa;1h@d>S9UE^akc8V1eOBPBJREaed>X`>y1e7+?(de?Cfi=>;C` zX#{wI+7q;X8wLkq;DZJDj+=td2quMI5&Qxo&_b`0dpaQV3}ucVjznPHz{5ZZAuu`D z=M?Jy66?K$1Q^3j=i6U3v%sSV>|fvEl@@d1f%|NkWZzesGZW?AioJ1Tr!&CV zX$-HwK7pNoL1g!V%R#uDx2Py$)G^&yxv^vR&8}JH-bS+?<^8)P?0ifyqU{E5Q>PZ~ zK^Law`MX;f4yb?>|NQ#X@y+J5kqW2B4S|zli~6J~`T=f!9JkvnuB2nR4~;#o8I%qV z0_;zn5A&QX)AsWzY-^|loBm{(+pBeDkgdctmn?tz^UtkeAQjXx-=p;KpZLsjG$zo; z_`*}1*5*-^Q4JB3^B(Rj=hu&7*DQ>mpEM}-3HhNA zLVd}$n;1SjH3`TJi}T!zWS6;F8n`!X#6sTViekwh=@)ow5$(+`$U!CTylqlD2Ti3g4-#ka*PEA2Tc``f)Xe#58S1mGedXBNT6lhzy|Sly=EtI*l)F$W*ad#`Ta`~}Gtf^rNpvr$ zg0WITOEFEN87WFGqcEs4;t) zsQiJrYLl1en(6!&5An0v6?MY7?5jV{hjWo%pCz#u+*f!zSkqp^6)SovBMm#yik><* zsIlo9OU`Z`KIqF$)zH5&ZS^}aF)2b(cz7awJ!6fy7^KR(Ry!0I7G7BAh^mzeSy znCsj1I2WAmc{NHYEXQTDIc%=3lkM;BAnoc@OZkFC2$xU?BZHx(n_jI^rsURL60c?V zj7-Apg-S_raH&l86XOv9)+>&y#~#hOzDlyJ=JZZS;?H+Y*i(Gn=<*e|9kn|3eqK<+ zLw6qA-3c)_(}c$2Ph#^~ zdR7NDR^wso0Z4;Xrl?P`yX_3e)nVe3sl?bF0>w=W;bJQmQfr5yfKEuw8;BME7x{c0eARvGPoQ|3pCb$YYn6 zPOEo{w|o||n5_MA;kS<*-^p7@AK!D=`XHgZ?62kfy6bmk%RaHoxEE=VkzaZCNb~Uq#dUo)godD<&&@xjM8URTK&nt38PrX_=2`C!R4N*v?UlLcs5DMdqi;O%et7NSBXn+A|h$yU$GFE%^&uJC_!rfq9YT zrcN(bPg)-z9k?8IefH2E+Md~=@l$WeW%pQIZ5B&xfD*7zD2qu)KZT8PZh+npQF7Q> z67#GV@`ArtTbYRZK$p&1*Ow9F(rdvM9J@TDesH z?nFitTyo=%M18G11@DZF&BLH9Iy^1~pGY^`fOrc>dHTx!_+=5C6{Z*Cb=j@?ud`l9 zLSB}#a!3$-u&gx{d&OSAB=kjT=h^s)NtI~0Q#)@$KS9@pZNLk|x1{{1YlK55U!`=7 z2w1GUzsx0tY3lB{F29}~$AFVyxG(sfe(GIrQbs) zJG^+Xn@6cD!-^t<8yS;32;@v;QKjWJ5}TBUL3VxhHJKb#=qodGl*#c=NP{XmFN#hE zqPw}d7~e*)7dLJ)>7;3>iPsX$ROwCsdOgixVr`Vbhq0#m*;*utUwX#9gU#mw)OJgY zG);pkBl!u~q)XDS=u)xRY=M9g`5_v>)ATW+Kj>e>jcQxS1-Q$W!mU@p0L%GdJ<#cUPM>)1P)_`Re-aPo3YF zB@5PLp%xwc;@>O(FngGKWQQ^Ed_^!>w;uws^j7;Wy%_d~)P$`%3Eekq%PI$?riemO2rt4*HmB zI>eiYHue4(&!mrW^POg=le2U47NBum@EY+8F&>abJB)miFll<&A;q|y;? z0KaRqbB7Iu+0yj9MQvtM6mHI^u&-Ih!Zq37Y)8Phd%sufq2(uJP#sl6=r;~5fH7%2 zG05N2zd)Gr*%R3ZmEoQJ*Hp{I)cH}&_RDJxzF9aS(U~p_&t_wXg+olzSyc~3KSh*-NFooA+-DPOyrB@vAByrDHd3uQS!#K2knB8- zf=sg7HRh=(IJfe_u?~&9e5W=n%A6drM<1CYeJ1uCe3A`aYmgq9Rmh~?;khuK5LO>n zvne^&eh$g`z)SlF-F83cf7BEaT>Dhw!$~KNN|&`%f+AZLj*puB*Ex5+Cazkr6)nm5$tUONG9^ zv`PI1c1rMGu{A#g5wdtg>ul5k&}o;k=a^YK&&tQtEhDfMly2YXdot!+$abavhdoXgh${pLO z&NAo12beIw_c&O?KsDv@EQO^J7WiAc$#n~W=M71~h|KpNxVvWnkG1Q=2sIYfIAwpp2yz7vZ$=4x{tEDo?UrZ5{h&aAD{rsdQ!W$%0CCk& z8Jh+l-TK4c_WcIX8@GOADdQx7FQ@qbV8$5@2d&H|72`&gz`6x{yg?A0keIc+CqbPF zEVK|^Ou{qPrZ3{CDYYZ<6D0^%eCC6(B=1Q zN7$QV4~hm8p;Wx%2Ee1Ny!g3j@8tSn*9ZU+I&w9!{h#kkWBW4f|GDgQ8Va~t>$G(~ zmi~3oW4)e|Z4{u(JW%tUtMlaScVo>-KwB;Q&y{U~nNiX&;vz+)l}&!#+^Q863AJe&$YT;;#!nZ|Hz**lW9$2|-xcVfQO7o7NOS}b6SgE?uQpnE6O_I+Cr-FuP=V zHt3*A&kC5=fdDKioT<|TbW6MGy!(=-cqkyQzrmXd>l_yfw zd5$AmcqB@Eb<$|PD&DG^WvaJ_s|@c`Bt-XYB1)~&fd9x8csEFVgjTr3*m6tf0E3bd zZ+^gWZYS19RhwPtjB4Hks1VofkPj?pX4bXDAPJL5R!o>-Px#H%P%|S<IcQeX?vg17x(C*4@LnO(Hm8cS?&>nXJPGR ziI9U@1yVy|KYm*T#h36u73RHP6iW^VF4IoovKoEACCSlPkwFOl-j+$OJAu&}Igfnh zIzOD(+mxsu|E9a1?mb@gFY(<`qA!QXdk6f5w5V0J{FMFtOw%K8?qXkLa{#X#g>cJ| zx&4dWPp3%2}>oPe&J- zWV`&m`!I%-i#UmWK1OO5G*`V*e>WGlIFkZg`iR>5r8q=XllJ+?k}b6ZS_?Qtg|PTk zkMzX8?~zvnnXX>0)=)!B8~gFLH)xmIRDv1$vA-bp-+#hFYRtYCZ9gI3wvK%mKz)*AI^UP!~kwvGHsuXmy%b` z&a<96C*{hE@0<`SX!Gt96i_NOCcZuFS9srYEr5{k*d$oSq}m{e8Lt z{QL$yQxs0KCr@g&E{sh-Xun6@8Qq8~nc1(6^q=*^l&(7PCLgR~0BHrK;64+R1vemiuI3 zu*gT4&vrI;xj<`{U!}3bz;%jOoxN)D{Y~v2!yZXxmkSHtb3}3UQr-C(oQ6XJuW#|C|K)C+#SKvJ z%Vhnfs!g3GXEeS&S zY{6NoR_Z4)G`HMcE78y}m%=yi_#iV~etW0fmsBS@FJOS#q(1y}`ThDN`g$iVh)HZY zo|E#f*%%^~{s>W0V4%a&JsUid6;hMh&=%i6sM_W>@U8a}#ma*yw&ayz&7QQ3gd8|# zmLj#rwAL8SqG(b}kcIKG*{mrf0ndfm2sj2u$x;pObq`bVE zp^Z=;40}viyBpyss9glDI#85(M(}LM09Lw@)YMLr_l&&L5<#n$Yn#OKdHw}?Ms~Qx}iYq7($cT(H)f0&egMRd>itgetY40`Hf)$#bT#YP97}TE>SYvdD%+Qd zZ}lZ;V%ZZYb+DWU5LfCEKz*I)*e|WjM;5aM1&YoSBREU{xETk3e)~QGB2=@3YP}-} zzOR>;`9LjRhN|)N)V$aaCX?`8+R=JJC2fM<+D-4-7G0+cg=t});xGo29K&#P#}BV` zh8k-+!XXX}zQbZB?hN9z+PZsHllOzhftslP7006aQDQ7%s);s<-JD2L3DIvA8aB4& zEJaZKtgtfq(U}aZfSUGF1G;NY$8pqZ6>MaBpVxEM1 z#J-jW<+jOK(!${CuzHJGi?uV z1v`^+G0^^y)1Slf4ow&p3AG|JC91<;OB;Zdo~@N-&3v;7_OOx-{*+n;JQt2x1?k|C z)`#Tp@4wx!zen%l)OlAaDS@Yr!c~ZAVbWEhl(7 zuFL%0ljJk9m)~c-X@8>D3p8z6Zo{ivFMu7KMN{&A=t_6K-*fp}ukW$1r4PS7TcKX_ z@I%Ibwcn^X>`cuTD8rW_VHFtZPhc~V*dU5lgR0{UO`&?Chu=9m|ywuD64Po zn|FB)>t`S9@;A*C-+y}fDQ_;%G;Kk@7cQQlCfM%NA4`M0zULKbXT1GgyW6bn`oagR zH*A`I=%)1U)dElV@wmPJA8B6py)&Xr?qRpO=c0bu=(jiCKU3Saakt+qU>)Zpbo8jt z$B8*N^t@j_d7M|X{$upx4ZCmdk(Ph_?f;Z)?fR3ECH1=HJUgnVyo#IZ3G8x5d%j?K zmc04-3~_OtuDDx^~UT%W9^ueH&u$oQxahlmew)<5Au%)UJ=tLB|)dm(9UdCB}) zONP3cs_=pSx6+EhUQF`IsR|Q76GLtt@4FQo&ge8{Rj&8Eqrd+BhCRi=Sg|@jYnqoE zu%T?sw|RBllA~JTS4-M5zDFx6=FjK%NV|P}lD4BlFK`~CSKz+5W5bL{maCuQChv%k zyPsJ39N5?|?K9P#+5>D}pOk6aDX>BT*p}zAnySa@4Q#is$u{6&+Nubg80ua9GJ_jv zTU5jGl~>h(?e^UNm#jIaGy?TW?rG@_1*z#$f62~r3aD???9ng*rxOF<8ja#_hx=#f z^UJ60+x(dC>N}mi%?vC}Dj(MFx6RR;`*+9BZ+y3Be^hQ`&s27ET%ZN)yoP>M`P<-7 z3G6VOer>JuUItieo!hu<=_J7&Pk;V=_QCqSQ8kZ5Lf-x7i&Zzv6$4i|XbIeS-)BFo zT3px2{%*E^@quN{t1hViVrWd@yz}c%&F7myExUPN+PCJvEMI;+$MUWDv!~|wO@iIuCLYT% zTM{L^#2h%8e1T<|t@(AC+V6Xx?af}7IZv*518{Af|AlW!p!JZz!XWxd=5`Sl(4vHy zA0FI46SaC>*0MMIq@BVv_q0tE(6DC|+~7B>aDL_EyX9w(%q=sCmoeM&XYL|)0S!i^ zX?(#=UJs0YS{y_^FwcHojP1E%%+Kd;+a|IvPtYRf0fwApLV9Nqm!X2#SR%#B&X8y@ciYS~*~ z|EO+jtlxVD?zf3T3=9m3o-U3d7fhLizNhQN$>=JoyemJ;YZ7Aw9Dh(PmUvdy-f-s3 zsp#&MOhtLn;t*Hi397&yb9ef<)+}-?uH`r)Fkwgi!!^ejEp4p@ gzd-rFUIIVrzaM^>T7G6%F3>UtPgg&ebxsLQ0G)%X(EtDd literal 0 HcmV?d00001 diff --git a/docs/architectures/china-merchants-bank/index.md b/docs/architectures/china-merchants-bank/index.md new file mode 100644 index 00000000..470f8c75 --- /dev/null +++ b/docs/architectures/china-merchants-bank/index.md @@ -0,0 +1,189 @@ +--- +title: "Unified Training and Inference on Kubernetes for Heterogeneous AI Compute at China Merchants Bank" +sidebar_label: "China Merchants Bank" +architecture: + organization: China Merchants Bank + summary: China Merchants Bank runs large-model training, LoRA fine-tuning, and online inference on one Kubernetes-based pool of nearly 10,000 heterogeneous accelerator cards, with separate operating policies for each workload type. + industries: + - financial-services + - banking + tags: + - ai + - machine learning + - llm training + - llm inference + - gpu scheduling + - heterogeneous accelerators + - multi-tenancy + - autoscaling + - platform engineering + projects: + - Kubernetes + - KEDA + - Prometheus + - HAMi + - Fluid + sourceUrl: https://github.com/cncf/tab/issues/140 + sourceIssue: 140 + published: 2026-10-28 + updated: 2026-10-28 +--- + +import CNCFProjectCard from '@site/src/components/CNCFProjectCard'; + +> Submitted by China Merchants Bank and Alibaba Cloud to the CNCF End User Technical Advisory Board via [cncf/tab#140](https://github.com/cncf/tab/issues/140). Documentation is distributed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). + +## Relevant CNCF projects + + + + + + + + + + + +## Organization + +China Merchants Bank (CMB) is a nationwide joint-stock commercial bank headquartered in Shenzhen, China. The bank operates an enterprise AI platform with nearly 10,000 heterogeneous accelerator cards sourced from three mainstream domestic vendors. The platform supports Qwen models ranging from 4 billion to 1.6 trillion parameters, along with DeepSeek, GLM, and other model families, and serves large-model training, fine-tuning, online inference, and other AI use cases for the bank. + +## Teams + +This architecture is owned by the Architecture Management Team in China Merchants Bank's Information Technology Department and was developed together with Alibaba Cloud. The team integrates open source infrastructure and AI runtimes with CMB's internal platforms through Kubernetes-native interfaces. + +## Architecture overview and goals + +### Context and problem space + +China Merchants Bank operates an enterprise AI platform with nearly 10,000 heterogeneous accelerator cards sourced from three mainstream domestic vendors. The platform supports Qwen models ranging from 4 billion to 1.6 trillion parameters, along with DeepSeek, GLM, and other model families. Its workloads include large-model training, fine-tuning, online inference, and other AI use cases. These workloads share the same high-value compute pool but have fundamentally different operating requirements. + +Distributed training jobs are long-running and throughput-oriented. They require stable capacity and should begin only when all required workers and accelerator resources are available. Online inference is request-driven and latency-sensitive, so it must scale with changing traffic while avoiding the cost of keeping excess capacity continuously active. Multi-tenant LoRA fine-tuning adds another challenge: tenant state must remain isolated without loading a separate copy of the same large base model for every tenant. + +The bank's goal was not simply to add more accelerator cards. It was to use existing capacity more efficiently while preserving workload isolation, operational control, and the ability for training and inference technologies to evolve independently. + +### Goals + +- Provide one Kubernetes-based control plane while preserving separate execution policies for training and inference. +- Manage training admission and quotas before compute and data resources are provisioned. +- Scale inference services from live demand signals rather than static peak-capacity reservations. +- Share heterogeneous accelerator capacity at fine granularity without allowing smaller workloads to monopolize a full card. +- Reuse one base-model runtime across multiple LoRA tenants while keeping adapters, configurations, and tenant state separate. +- Provide shared access to datasets, model weights, checkpoints, the model registry, and operational metrics. +- Allow training frameworks, inference engines, and models to evolve without tightly coupling the entire platform to one runtime or vendor stack. + +### Architecture + +The architecture uses one shared Kubernetes foundation with two decoupled workload paths. + +**Training path:** Training requests enter through the Training API, a CMB-built pipeline, UI, and scheduler entry point. Kueue applies queue-, quota-, and admission-based control before the workload starts. After admission, Kubernetes Scheduler selects suitable nodes, HAMi assigns accelerator capacity, and Fluid provides access to datasets and checkpoints. Twinkle runs multi-tenant training on Ray and passes the resulting checkpoints into the downstream model-management process. Built on verl, verl-SpeCo supports draft-model training and integrates speculative decoding with vLLM and SGLang. + +**Inference path:** Online requests enter through the Inference Gateway. In production, RBG orchestrates role-based and multi-node LLM inference workloads served by vLLM or SGLang, with Ray providing the distributed runtime. Prometheus collects service and demand metrics, and KEDA uses those signals to add or remove replicas. Kubernetes Scheduler and HAMi place new Pods and allocate accelerator resources, while Fluid supplies cached model weights so newly created replicas can become ready more quickly. + +Both paths share the Kubernetes control plane, accelerator node pool, data and model access layer, model registry, and observability foundation. They remain separate at the workload-policy and runtime levels so each can use the behavior best suited to its demand pattern. + +![Kubernetes-native training and inference architecture. A workload layer holds a training deployment (Twinkle multi-tenant LoRA training, verl-SpeCo draft-model training, and a Ray runtime) fed by the Training API, and an inference deployment (RBG role-based orchestration, vLLM or SGLang serving engine, and a Ray runtime) fed by the Inference Gateway. A platform control layer holds KEDA event-driven autoscaling, Kueue admission and quota, Kubernetes Scheduler Pod placement, HAMi vGPU, memory, and core quota, and the Fluid control plane for datasets, runtimes, and PVCs. A data and resource layer holds the heterogeneous accelerator pool of nearly 10,000 cards from three vendors with the HAMi device plugin, the Fluid cache runtime for datasets, models, and checkpoints, object storage, and the model registry. Arrows show business requests, data and model paths, control and scaling signals, and GPU allocation, with a model lifecycle of train, checkpoint, evaluate and register, deploy, online metrics, and retrain trigger.](./images/architecture.png) + +### Component ownership and responsibility boundaries + +The architecture combines four types of components. CMB's proprietary platforms integrate the open source infrastructure and AI runtimes through Kubernetes-native interfaces and provide the bank's internal platform capabilities. + +| Category | Components and platforms | +| --- | --- | +| CNCF-hosted and Kubernetes ecosystem open source projects | Kubernetes, Kueue (Kubernetes SIG), KEDA, Prometheus, HAMi, and Fluid | +| Third-party open source projects | Ray, RBG, vLLM, SGLang, and verl | +| Open source projects jointly developed by CMB and the community | Twinkle and verl-SpeCo | +| CMB proprietary platforms | CMB-built MaaS, training, heterogeneous accelerator management, model asset, and data asset platforms | + +The proprietary platforms do not replace the responsibilities of the open source components. Kueue controls workload admission, Kubernetes Scheduler places Pods, HAMi allocates accelerator capacity, Fluid provides data and model access, and RBG orchestrates LLM inference workloads. + +### Key design decisions and trade-offs + +- **Share infrastructure without forcing one operating policy.** Training uses queue- and quota-based admission through Kueue, while inference uses metric-driven elasticity through Prometheus and KEDA. +- **Separate admission from placement and allocation.** Kueue decides when a training workload may enter the cluster; Kubernetes Scheduler and HAMi determine where Pods run and how accelerator capacity is allocated. +- **Treat compute sharing and model sharing as different concerns.** HAMi allocates physical accelerator capacity, while Twinkle enables multiple LoRA tenants to reuse one base-model instance. Neither mechanism replaces the other. +- **Treat model readiness as part of inference elasticity.** Creating a replica is not sufficient if it must still wait for model weights. Fluid's compute-side cache reduces this model-loading delay. +- **Use unit cost to assess efficiency at growing scale.** Cost per one million input and output tokens is more meaningful than total spend when business volume is changing. +- **Prefer a composable Kubernetes-native architecture over a vertically integrated platform.** CMB also evaluated vertically integrated platforms, which could reduce initial integration effort within a single supported stack. CMB selected the Kubernetes-native approach because its modular design supports independent evolution of admission control, scheduling, accelerator allocation, data access, and workload runtimes across a heterogeneous hardware environment. This flexibility enabled CMB to introduce Twinkle's shared base-model runtime independently, contributing to the reported fivefold increase in tenant density. The trade-off is the need for ongoing integration and compatibility testing. + +### Operating context for the reported results + +The reported results come from a shared production platform managing nearly 10,000 heterogeneous accelerator cards sourced from three mainstream domestic vendors. The platform supports Qwen models ranging from 4 billion to 1.6 trillion parameters, along with DeepSeek, GLM, and other model families. For online inference, the primary service-level objectives are a time to first token (TTFT) of no more than 5 seconds and a time per output token (TPOT) of no more than 50 milliseconds. In a Qwen3-14B startup test with model weights cached by Fluid, the measured model-loading time was under 2 seconds. + +## Can you expand on why you are using those projects/services? + +The value of the architecture comes from the interaction of admission, scheduling, accelerator allocation, data access, observability, elasticity, and model-runtime reuse rather than from any single component. + +### CNCF projects + +- **Kubernetes:** Provides the shared control plane, Pod orchestration, Deployments, scheduling foundation, and common resource interfaces for both workload paths. +- **KEDA:** Converts service and demand signals into scaling decisions for online inference workloads. +- **Prometheus:** Collects QPS, request-queue depth, inference latency, and other operational metrics used for observability and demand-driven scaling. +- **HAMi:** Pools heterogeneous accelerator resources and allocates accelerator capacity at fine granularity for workloads that can safely share it. +- **Fluid:** Provides Kubernetes-native access to datasets, model weights, and checkpoints, and caches model data near compute to reduce repeated remote reads and model-loading delays. + +### Kubernetes ecosystem projects + +- **Kueue (Kubernetes SIG subproject):** Manages training queues, quotas, and workload admission so distributed jobs do not partially start and hold capacity while waiting for the remaining resources. + +### Third-party open source projects and technologies + +- **Ray:** Provides the distributed runtime used by both the training and inference paths. +- **RBG:** Provides the Kubernetes workload abstraction used in production for role-based and multi-node LLM inference services. +- **vLLM / SGLang:** Serve online inference workloads behind the Inference Gateway. +- **verl:** Provides the upstream reinforcement-learning training framework used by verl-SpeCo. + +### Open source projects jointly developed by CMB and the community + +- **Twinkle:** Runs multi-tenant LoRA training on Ray, enabling tenants to share one base-model instance while retaining separate adapters, configurations, and state. +- **verl-SpeCo:** Extends verl with draft-model training and speculative-decoding integration for vLLM and SGLang. + +## What has worked well? + +### Production outcomes + +| Metric | Result | +| --- | --- | +| Average accelerator compute utilization | Increased from 35% to more than 60% | +| Inference unit cost | Decreased by more than 60% per one million tokens, counting input and output tokens together | +| Duplicated base-model runtime footprint for the default five-tenant configuration | Decreased by 80% by reducing base-model replicas from five to one | +| Multi-tenant training density | Increased fivefold; eight concurrent tenants have been validated and five are used by default in production | +| Fluid-cached model loading | Under 2 seconds in a Qwen3-14B startup test | + +These results use the bank's internally consistent before-and-after methodology and comparable model and service conditions. + +### Reusable lessons + +- A shared compute pool does not require training and inference to use the same operating policy. +- Inference elasticity depends on model readiness, not only on replica scheduling. +- Physical accelerator sharing and base-model runtime reuse solve different sources of waste. +- Kubernetes-native interfaces allow the control plane, resource layer, data path, monitoring system, and workload runtimes to evolve with limited coupling. +- Accelerator utilization, inference cost per token, and training density measure different problems and should be defined and evaluated separately. + +## What has not worked well? + +A current limitation is that support maturity varies across combinations of accelerator generations, model architectures, and training or inference runtimes. CMB mitigates this by qualifying each new combination before production rollout and continues to expand compatibility coverage and operational automation while preserving the Kubernetes-native interfaces described above. + +The composable, Kubernetes-native approach also carries a standing cost: because admission control, scheduling, accelerator allocation, data access, and workload runtimes evolve independently, CMB must perform ongoing integration and compatibility testing that a vertically integrated platform would absorb within a single supported stack. + +## What sort of "glue" have you had to develop to enable usage of your architecture? + +CMB-built platforms integrate the open source components through Kubernetes-native interfaces and provide the bank's internal platform capabilities: + +- MaaS and inference service capabilities, including the Inference Gateway that fronts production inference services. +- Training platform capabilities, including the Training API (pipeline, UI, and scheduler entry point) that submits workloads for Kueue admission. +- Heterogeneous accelerator management capabilities. +- Model asset management capabilities. +- Data asset management capabilities. + +These platforms do not replace the responsibilities of the open source components: Kueue controls workload admission, Kubernetes Scheduler places Pods, HAMi allocates accelerator capacity, Fluid provides data and model access, and RBG orchestrates LLM inference workloads. + +CMB also co-developed two open source projects with the community to close gaps in the training path: + +- **Twinkle** runs multi-tenant LoRA training on Ray so that multiple tenants share one base-model instance while keeping adapters, configurations, and state separate. +- **verl-SpeCo** extends verl with draft-model training and speculative-decoding integration for vLLM and SGLang. + +## What's next for your architecture? What are you looking to do next? + +CMB continues to expand compatibility coverage across accelerator generations, model architectures, and training and inference runtimes, and to increase operational automation, while preserving the Kubernetes-native interfaces that keep the control plane, resource layer, data path, monitoring system, and workload runtimes loosely coupled. Areas identified for further work include dynamic tenant concurrency for multi-tenant training, broader hardware and runtime support, and unit-cost-based capacity management. diff --git a/static/img/cncf-projects/fluid-fluid-icon-color.svg b/static/img/cncf-projects/fluid-fluid-icon-color.svg new file mode 100644 index 00000000..577e8a3c --- /dev/null +++ b/static/img/cncf-projects/fluid-fluid-icon-color.svg @@ -0,0 +1,137 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/img/cncf-projects/hami-hami-icon-color.svg b/static/img/cncf-projects/hami-hami-icon-color.svg new file mode 100644 index 00000000..ea51f003 --- /dev/null +++ b/static/img/cncf-projects/hami-hami-icon-color.svg @@ -0,0 +1,28 @@ + + + + + + diff --git a/tests/architecture-catalog-contract.test.mjs b/tests/architecture-catalog-contract.test.mjs index 781cad32..2b205884 100644 --- a/tests/architecture-catalog-contract.test.mjs +++ b/tests/architecture-catalog-contract.test.mjs @@ -35,6 +35,8 @@ function isIssueSourced(record) { return typeof record?.sourceIssue === 'number'; } +const SUBMISSION_ISSUE_REPOS = ['cncf/endusers', 'cncf/tab']; + const REQUIRED_STRING_FIELDS = [ 'id', 'title', @@ -142,10 +144,15 @@ test('issue-submitted records cite the submission issue as their source', () => Number.isInteger(record.sourceIssue) && record.sourceIssue > 0, `${record.id}: sourceIssue must be a positive issue number`, ); - assert.equal( - record.sourceUrl, - `https://github.com/cncf/endusers/issues/${record.sourceIssue}`, - `${record.id}: issue-submitted record sourceUrl must be its submission issue`, + // Submissions arrive either through this repository's issue form or + // through the End User TAB's reference-architecture intake in cncf/tab. + assert.ok( + SUBMISSION_ISSUE_REPOS.some( + (repo) => + record.sourceUrl === + `https://github.com/${repo}/issues/${record.sourceIssue}`, + ), + `${record.id}: issue-submitted record sourceUrl must be its submission issue in ${SUBMISSION_ISSUE_REPOS.join(' or ')}, got ${record.sourceUrl}`, ); } }); From 6187aecea247db964018c5cc1e72402ceba4f746 Mon Sep 17 00:00:00 2001 From: mrbobbytables Date: Wed, 28 Oct 2026 17:05:49 -0500 Subject: [PATCH 2/7] Make the architecture source issue and commit optional A reference architecture page may be authored directly from a source that is neither a cncf/architecture import nor a submission issue in this repository. validate:architectures now requires at most one of sourceCommit or sourceIssue instead of exactly one; the catalog contract test, e2e attribution check, CONTRIBUTING.md and ADR 0010 follow. The China Merchants Bank page keeps cncf/tab#140 as its sourceUrl and drops sourceIssue. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables --- CONTRIBUTING.md | 17 ++++---- ...hitecture-pages-are-the-metadata-source.md | 5 ++- data/architectures/catalog.json | 1 - .../china-merchants-bank/index.md | 1 - scripts/validate-architectures.mjs | 4 +- tests/architecture-catalog-contract.test.mjs | 43 +++++++++---------- tests/e2e/architecture-detail.spec.js | 11 +++-- tests/validate-architectures.test.mjs | 14 +++--- 8 files changed, 50 insertions(+), 46 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f639430c..c482134e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -132,15 +132,16 @@ Rules: record and member data use. - The page's front matter is the only place an architecture's metadata is written. Alongside `title`, an `architecture:` block carries `organization`, - `summary`, `industries`, `tags`, `projects`, `sourceUrl`, exactly one of + `summary`, `industries`, `tags`, `projects`, `sourceUrl`, optionally one of `sourceCommit` (a cncf/architecture import) or `sourceIssue` (a submission - issue in this repository or in the End User TAB's cncf/tab intake), - `published` and `updated`. The record's `id` is the directory name and its - `assets` are the files in `images/`; neither is written by hand. After editing - a page or adding one, run `npm run generate:architectures` and commit the - regenerated `data/architectures/catalog.json` with it; the catalog component, - member directory and data-link checks read that mirror, and - `validate:architectures` fails when it is behind the pages + issue), `published` and `updated`. A page authored directly from another + source sets neither and cites its `sourceUrl` in the attribution line. The + record's `id` is the directory name and its `assets` are the files in + `images/`; neither is written by hand. After editing a page or adding one, run + `npm run generate:architectures` and commit the regenerated + `data/architectures/catalog.json` with it; the catalog component, member + directory and data-link checks read that mirror, and `validate:architectures` + fails when it is behind the pages ([ADR 0010](adr/0010-architecture-pages-are-the-metadata-source.md)). - Architecture `tags` are written with spaces, not underscores (`private cloud`, not `private_cloud`): they appear as search chips on the catalog. The importer diff --git a/adr/0010-architecture-pages-are-the-metadata-source.md b/adr/0010-architecture-pages-are-the-metadata-source.md index 8313abc8..1511949c 100644 --- a/adr/0010-architecture-pages-are-the-metadata-source.md +++ b/adr/0010-architecture-pages-are-the-metadata-source.md @@ -70,8 +70,9 @@ pages), and a nested block keeps the catalog's vocabulary out of the theme's. - The front matter of `docs/architectures//index.md` is the only place an architecture's metadata is written. Alongside `title`, an `architecture:` block carries `organization`, `summary`, `industries`, `tags`, `projects`, - `sourceUrl`, exactly one of `sourceCommit` or `sourceIssue`, `published` and - `updated`. + `sourceUrl`, at most one of `sourceCommit` or `sourceIssue` (amended + 2026-10-28: a page authored directly from another source sets neither), + `published` and `updated`. - `id` is the directory name and `assets` is the sorted listing of regular files in `images/`. Neither is authored; both are derived when the catalog is generated. diff --git a/data/architectures/catalog.json b/data/architectures/catalog.json index 66420b89..730eb0c2 100644 --- a/data/architectures/catalog.json +++ b/data/architectures/catalog.json @@ -122,7 +122,6 @@ ], "projects": ["Kubernetes", "KEDA", "Prometheus", "HAMi", "Fluid"], "sourceUrl": "https://github.com/cncf/tab/issues/140", - "sourceIssue": 140, "published": "2026-10-28", "updated": "2026-10-28", "assets": ["/img/architectures/china-merchants-bank/architecture.png"] diff --git a/docs/architectures/china-merchants-bank/index.md b/docs/architectures/china-merchants-bank/index.md index 470f8c75..61834ef5 100644 --- a/docs/architectures/china-merchants-bank/index.md +++ b/docs/architectures/china-merchants-bank/index.md @@ -24,7 +24,6 @@ architecture: - HAMi - Fluid sourceUrl: https://github.com/cncf/tab/issues/140 - sourceIssue: 140 published: 2026-10-28 updated: 2026-10-28 --- diff --git a/scripts/validate-architectures.mjs b/scripts/validate-architectures.mjs index bd14db42..67c4c6f7 100644 --- a/scripts/validate-architectures.mjs +++ b/scripts/validate-architectures.mjs @@ -116,11 +116,11 @@ for (const record of records) { severity: 'error', message: `${FRONT_MATTER_KEY}.${key} must be a list of non-empty strings`, }); - if (!('sourceCommit' in record) === !('sourceIssue' in record)) + if ('sourceCommit' in record && 'sourceIssue' in record) errors.push({ path: record.page, severity: 'error', - message: `${FRONT_MATTER_KEY} must set exactly one of sourceCommit (cncf/architecture import) or sourceIssue (submission issue)`, + message: `${FRONT_MATTER_KEY} must set at most one of sourceCommit (cncf/architecture import) or sourceIssue (submission issue)`, }); if ('sourceIssue' in record && !Number.isInteger(record.sourceIssue)) errors.push({ diff --git a/tests/architecture-catalog-contract.test.mjs b/tests/architecture-catalog-contract.test.mjs index 2b205884..af686f53 100644 --- a/tests/architecture-catalog-contract.test.mjs +++ b/tests/architecture-catalog-contract.test.mjs @@ -23,19 +23,22 @@ const docsDir = join(repoRoot, 'docs/architectures'); const catalog = JSON.parse(readFileSync(catalogPath, 'utf8')); -// Two provenance shapes coexist in the catalog. Records that originated in +// Three provenance shapes coexist in the catalog. Records that originated in // the CNCF Cloud Native Reference Architecture project are pinned to the // cncf/architecture commit they were taken from (`sourceCommit` + a // commit-pinned `sourceUrl`), which is what their CC BY 4.0 attribution // cites. scripts/import-architecture-issue.mjs turns a submission issue into -// a record whose source IS the issue (`sourceIssue` + the issue URL); there is -// no upstream commit to pin, so the commit-pinning assertions below apply -// only to records without `sourceIssue`. +// a record whose source IS the issue (`sourceIssue` + the issue URL). A page +// authored directly in this repository from some other source carries neither +// and cites only its `sourceUrl`, so each pinning assertion below applies only +// to records that carry its field. function isIssueSourced(record) { return typeof record?.sourceIssue === 'number'; } -const SUBMISSION_ISSUE_REPOS = ['cncf/endusers', 'cncf/tab']; +function isCommitSourced(record) { + return typeof record?.sourceCommit === 'string'; +} const REQUIRED_STRING_FIELDS = [ 'id', @@ -43,7 +46,6 @@ const REQUIRED_STRING_FIELDS = [ 'organization', 'summary', 'sourceUrl', - 'sourceCommit', 'published', 'updated', ]; @@ -82,10 +84,7 @@ test('catalog.json is a non-empty array of uniquely identified records', () => { test('every catalog record carries the fields the site renders', () => { for (const record of catalog) { - const requiredStrings = isIssueSourced(record) - ? REQUIRED_STRING_FIELDS.filter((field) => field !== 'sourceCommit') - : REQUIRED_STRING_FIELDS; - for (const field of requiredStrings) { + for (const field of REQUIRED_STRING_FIELDS) { assert.equal( typeof record[field], 'string', @@ -120,7 +119,7 @@ test('every catalog record carries the fields the site renders', () => { test('provenance pins an upstream commit that the source URL points at', () => { for (const record of catalog) { - if (isIssueSourced(record)) continue; + if (!isCommitSourced(record)) continue; assert.match( record.sourceCommit, /^[0-9a-f]{40}$/, @@ -144,15 +143,10 @@ test('issue-submitted records cite the submission issue as their source', () => Number.isInteger(record.sourceIssue) && record.sourceIssue > 0, `${record.id}: sourceIssue must be a positive issue number`, ); - // Submissions arrive either through this repository's issue form or - // through the End User TAB's reference-architecture intake in cncf/tab. - assert.ok( - SUBMISSION_ISSUE_REPOS.some( - (repo) => - record.sourceUrl === - `https://github.com/${repo}/issues/${record.sourceIssue}`, - ), - `${record.id}: issue-submitted record sourceUrl must be its submission issue in ${SUBMISSION_ISSUE_REPOS.join(' or ')}, got ${record.sourceUrl}`, + assert.equal( + record.sourceUrl, + `https://github.com/cncf/endusers/issues/${record.sourceIssue}`, + `${record.id}: issue-submitted record sourceUrl must be its submission issue`, ); } }); @@ -213,7 +207,7 @@ test('doc frontmatter reuses the record title and labels the sidebar', () => { } }); -test('each doc page attributes the revision its record was imported from', () => { +test('each doc page attributes the source its record came from', () => { for (const record of catalog) { const body = readFileSync(docPath(record.id), 'utf8'); if (isIssueSourced(record)) { @@ -221,11 +215,16 @@ test('each doc page attributes the revision its record was imported from', () => body.includes(`issues/${record.sourceIssue}`), `${record.id}: doc page does not cite submission issue #${record.sourceIssue}`, ); - } else { + } else if (isCommitSourced(record)) { assert.ok( body.includes(record.sourceCommit), `${record.id}: doc page does not cite sourceCommit ${record.sourceCommit}`, ); + } else { + assert.ok( + body.includes(record.sourceUrl), + `${record.id}: doc page does not cite sourceUrl ${record.sourceUrl}`, + ); } assert.match( body, diff --git a/tests/e2e/architecture-detail.spec.js b/tests/e2e/architecture-detail.spec.js index d77118bc..4db1b01a 100644 --- a/tests/e2e/architecture-detail.spec.js +++ b/tests/e2e/architecture-detail.spec.js @@ -61,10 +61,15 @@ test.describe('reference architecture detail pages', () => { ).toBeVisible(); // CC BY 4.0 obliges the site to carry attribution for text that - // originated in cncf/architecture, and the pinned revision records - // exactly what was taken. Both live in the page's leading blockquote. + // originated elsewhere, and the pinned revision or submission issue + // records exactly what was taken when the record carries one. Both + // live in the page's leading blockquote. const attribution = page.locator('article blockquote').first(); - await expect(attribution).toContainText(record.sourceCommit); + if (record.sourceCommit) { + await expect(attribution).toContainText(record.sourceCommit); + } else if (record.sourceIssue) { + await expect(attribution).toContainText(`#${record.sourceIssue}`); + } await expect(attribution).toContainText('CC BY 4.0'); // Each declared project is rendered by . A card links diff --git a/tests/validate-architectures.test.mjs b/tests/validate-architectures.test.mjs index 55b26098..a6634d97 100644 --- a/tests/validate-architectures.test.mjs +++ b/tests/validate-architectures.test.mjs @@ -318,9 +318,10 @@ for (const [label, sourceUrl] of [ }); } -// A page is either pinned to the cncf/architecture commit it was taken from or -// cites the submission issue it came from; the attribution line on the page -// and the member directory both depend on knowing which. +// A page is pinned to the cncf/architecture commit it was taken from, cites +// the submission issue it came from, or (when authored directly in this +// repository from another source) carries only its sourceUrl; it never claims +// two origins, because the attribution line on the page depends on which. test('rejects a page that sets both sourceCommit and sourceIssue', () => { const result = runScriptWithFixtures( SCRIPT, @@ -329,17 +330,16 @@ test('rejects a page that sets both sourceCommit and sourceIssue', () => { assert.equal(result.status, 1); assert.match( result.stderr, - /must set exactly one of sourceCommit \(cncf\/architecture import\) or sourceIssue \(submission issue\)/, + /must set at most one of sourceCommit \(cncf\/architecture import\) or sourceIssue \(submission issue\)/, ); }); -test('rejects a page that sets neither sourceCommit nor sourceIssue', () => { +test('accepts a page that sets neither sourceCommit nor sourceIssue', () => { const result = runScriptWithFixtures( SCRIPT, pageFixture([withAuthored({ sourceCommit: undefined })]), ); - assert.equal(result.status, 1); - assert.match(result.stderr, /must set exactly one of sourceCommit/); + assert.equal(result.status, 0, result.stderr); }); test('accepts an issue-sourced page', () => { From 7e6f6a0b8bd64346fb6d4fdc740b64f3449d5779 Mon Sep 17 00:00:00 2001 From: mrbobbytables Date: Wed, 28 Oct 2026 17:31:49 -0500 Subject: [PATCH 3/7] Add China Merchants Bank logo to its architecture card Cropped from the logo CMB serves on its own site (https://wwwcdn.cmbimg.cn/Images/logo.png): the mark and name without the product slogan beneath it. The catalog card shows it in place of the initials fallback. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables --- data/architectures/catalog.json | 5 ++++- .../china-merchants-bank/images/logo.png | Bin 0 -> 3246 bytes 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 docs/architectures/china-merchants-bank/images/logo.png diff --git a/data/architectures/catalog.json b/data/architectures/catalog.json index 730eb0c2..23a7f155 100644 --- a/data/architectures/catalog.json +++ b/data/architectures/catalog.json @@ -124,7 +124,10 @@ "sourceUrl": "https://github.com/cncf/tab/issues/140", "published": "2026-10-28", "updated": "2026-10-28", - "assets": ["/img/architectures/china-merchants-bank/architecture.png"] + "assets": [ + "/img/architectures/china-merchants-bank/architecture.png", + "/img/architectures/china-merchants-bank/logo.png" + ] }, { "id": "colopl", diff --git a/docs/architectures/china-merchants-bank/images/logo.png b/docs/architectures/china-merchants-bank/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..0b39886883f4630c30d62368b9df813c08c6ec08 GIT binary patch literal 3246 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 BU!ed1 literal 0 HcmV?d00001 From 53fd6fd81a24261316a185176efedd236ca34a54 Mon Sep 17 00:00:00 2001 From: mrbobbytables Date: Wed, 28 Oct 2026 17:40:27 -0500 Subject: [PATCH 4/7] Forward optional architecture provenance into member directory data generate-members.mjs always emitted sourceCommit for each member architecture entry, and members-data.test.mjs required it, so a page with no pinned cncf/architecture commit broke the members regeneration and was absent from data/members.json. Forward whichever provenance field the catalog record carries (sourceCommit, sourceIssue or neither), check each only when present, and regenerate members.json so China Merchants Bank appears in the member directory. Align the page's industries with the Title Case labels the other catalog records use so the directory facet groups it with Financial Services. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables --- data/architectures/catalog.json | 2 +- data/members.json | 19 ++++++++++++++ .../china-merchants-bank/index.md | 4 +-- scripts/generate-members.mjs | 6 ++++- tests/generate-members.test.mjs | 25 +++++++++++++++++++ tests/members-data.test.mjs | 24 ++++++++++++++---- 6 files changed, 71 insertions(+), 9 deletions(-) diff --git a/data/architectures/catalog.json b/data/architectures/catalog.json index 23a7f155..e6623daa 100644 --- a/data/architectures/catalog.json +++ b/data/architectures/catalog.json @@ -108,7 +108,7 @@ "title": "Unified Training and Inference on Kubernetes for Heterogeneous AI Compute at China Merchants Bank", "organization": "China Merchants Bank", "summary": "China Merchants Bank runs large-model training, LoRA fine-tuning, and online inference on one Kubernetes-based pool of nearly 10,000 heterogeneous accelerator cards, with separate operating policies for each workload type.", - "industries": ["financial-services", "banking"], + "industries": ["Financial Services", "Banking"], "tags": [ "ai", "machine learning", diff --git a/data/members.json b/data/members.json index 088fe7ab..8ad76829 100644 --- a/data/members.json +++ b/data/members.json @@ -681,6 +681,25 @@ ], "membershipStatus": "member" }, + { + "id": "china-merchants-bank", + "name": "China Merchants Bank", + "slug": "china-merchants-bank", + "logo": "/img/architectures/china-merchants-bank/logo.png", + "industries": ["Banking", "Financial Services"], + "projects": ["Fluid", "HAMi", "KEDA", "Kubernetes", "Prometheus"], + "architectures": [ + { + "id": "china-merchants-bank", + "title": "Unified Training and Inference on Kubernetes for Heterogeneous AI Compute at China Merchants Bank", + "sourceUrl": "https://github.com/cncf/tab/issues/140" + } + ], + "awards": [], + "sourceAttribution": ["https://github.com/cncf/tab/issues/140"], + "membershipSources": [], + "membershipStatus": "unknown" + }, { "id": "citi", "name": "Citi", diff --git a/docs/architectures/china-merchants-bank/index.md b/docs/architectures/china-merchants-bank/index.md index 61834ef5..ee8918df 100644 --- a/docs/architectures/china-merchants-bank/index.md +++ b/docs/architectures/china-merchants-bank/index.md @@ -5,8 +5,8 @@ architecture: organization: China Merchants Bank summary: China Merchants Bank runs large-model training, LoRA fine-tuning, and online inference on one Kubernetes-based pool of nearly 10,000 heterogeneous accelerator cards, with separate operating policies for each workload type. industries: - - financial-services - - banking + - Financial Services + - Banking tags: - ai - machine learning diff --git a/scripts/generate-members.mjs b/scripts/generate-members.mjs index 16d3a466..03525e27 100644 --- a/scripts/generate-members.mjs +++ b/scripts/generate-members.mjs @@ -115,11 +115,15 @@ function legacyMembers(catalog, awardsData) { const projects = [ ...new Set(catalogEntries.flatMap((e) => e.projects || [])), ].sort(); + // A catalog record carries at most one provenance field (sourceCommit for + // a cncf/architecture import, sourceIssue for a submission issue) or none + // when the page was authored directly; forward whichever is present. const architectures = catalogEntries.map((e) => ({ id: e.id, title: e.title, sourceUrl: e.sourceUrl, - sourceCommit: e.sourceCommit, + ...(e.sourceCommit !== undefined && { sourceCommit: e.sourceCommit }), + ...(e.sourceIssue !== undefined && { sourceIssue: e.sourceIssue }), })); const awards = awardEntries.map((a) => ({ year: a.year, diff --git a/tests/generate-members.test.mjs b/tests/generate-members.test.mjs index 74c38104..0a008d44 100644 --- a/tests/generate-members.test.mjs +++ b/tests/generate-members.test.mjs @@ -583,6 +583,31 @@ test('projects only the documented architecture and award fields', () => { assert.equal(member.awards[0].talkUrl, null); }); +test('forwards whichever provenance field a catalog record carries', () => { + const result = run({ + catalog: [ + catalogEntry({ + id: 'acme-issue', + sourceCommit: undefined, + sourceIssue: 42, + }), + catalogEntry({ id: 'acme-direct', sourceCommit: undefined }), + ], + }); + + const { architectures } = memberById(result, 'acme'); + const issue = architectures.find((entry) => entry.id === 'acme-issue'); + const direct = architectures.find((entry) => entry.id === 'acme-direct'); + assert.deepEqual(Object.keys(issue).sort(), [ + 'id', + 'sourceIssue', + 'sourceUrl', + 'title', + ]); + assert.equal(issue.sourceIssue, 42); + assert.deepEqual(Object.keys(direct).sort(), ['id', 'sourceUrl', 'title']); +}); + test('collects source attribution from catalog and award URLs, skipping nulls', () => { const result = run({ catalog: [catalogEntry({ sourceUrl: 'https://example.test/architecture' })], diff --git a/tests/members-data.test.mjs b/tests/members-data.test.mjs index ac2ce79c..a8360122 100644 --- a/tests/members-data.test.mjs +++ b/tests/members-data.test.mjs @@ -230,7 +230,7 @@ test('member logos live under /img/ and exist in the repository', () => { test('member architecture entries carry their provenance', () => { for (const member of members) { for (const architecture of member.architectures) { - for (const field of ['id', 'title', 'sourceUrl', 'sourceCommit']) { + for (const field of ['id', 'title', 'sourceUrl']) { assert.ok( architecture[field], `${member.id} architecture is missing ${field}`, @@ -240,11 +240,25 @@ test('member architecture entries carry their provenance', () => { architecture.sourceUrl, `${member.id} architecture sourceUrl`, ); - assert.match( - architecture.sourceCommit, - /^[0-9a-f]{40}$/, - `${member.id} architecture sourceCommit must be a full commit sha`, + // Provenance mirrors the catalog record: at most one of a pinned + // cncf/architecture commit or a submission issue, or neither for a + // page authored directly in this repository. + assert.ok( + !('sourceCommit' in architecture && 'sourceIssue' in architecture), + `${member.id} architecture must not carry both sourceCommit and sourceIssue`, ); + if ('sourceCommit' in architecture) + assert.match( + architecture.sourceCommit, + /^[0-9a-f]{40}$/, + `${member.id} architecture sourceCommit must be a full commit sha`, + ); + if ('sourceIssue' in architecture) + assert.ok( + Number.isInteger(architecture.sourceIssue) && + architecture.sourceIssue > 0, + `${member.id} architecture sourceIssue must be a positive issue number`, + ); } } }); From 76fbd7c8269c2da16e8a5d2c689b52b7e0d0539e Mon Sep 17 00:00:00 2001 From: mrbobbytables Date: Thu, 29 Oct 2026 20:49:44 +0000 Subject: [PATCH 5/7] fix: remove unverified CMB logo asset Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables --- data/architectures/catalog.json | 5 +---- data/members.json | 2 +- .../china-merchants-bank/images/logo.png | Bin 3246 -> 0 bytes scripts/generate-members.mjs | 7 +++++-- tests/generate-members.test.mjs | 12 ++++++++++++ 5 files changed, 19 insertions(+), 7 deletions(-) delete mode 100644 docs/architectures/china-merchants-bank/images/logo.png diff --git a/data/architectures/catalog.json b/data/architectures/catalog.json index e6623daa..e0f69263 100644 --- a/data/architectures/catalog.json +++ b/data/architectures/catalog.json @@ -124,10 +124,7 @@ "sourceUrl": "https://github.com/cncf/tab/issues/140", "published": "2026-10-28", "updated": "2026-10-28", - "assets": [ - "/img/architectures/china-merchants-bank/architecture.png", - "/img/architectures/china-merchants-bank/logo.png" - ] + "assets": ["/img/architectures/china-merchants-bank/architecture.png"] }, { "id": "colopl", diff --git a/data/members.json b/data/members.json index 8ad76829..828b9793 100644 --- a/data/members.json +++ b/data/members.json @@ -685,7 +685,7 @@ "id": "china-merchants-bank", "name": "China Merchants Bank", "slug": "china-merchants-bank", - "logo": "/img/architectures/china-merchants-bank/logo.png", + "logo": null, "industries": ["Banking", "Financial Services"], "projects": ["Fluid", "HAMi", "KEDA", "Kubernetes", "Prometheus"], "architectures": [ diff --git a/docs/architectures/china-merchants-bank/images/logo.png b/docs/architectures/china-merchants-bank/images/logo.png deleted file mode 100644 index 0b39886883f4630c30d62368b9df813c08c6ec08..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3246 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 BU!ed1 diff --git a/scripts/generate-members.mjs b/scripts/generate-members.mjs index 03525e27..5a2c5109 100644 --- a/scripts/generate-members.mjs +++ b/scripts/generate-members.mjs @@ -75,12 +75,15 @@ function pickLogo(allAssets, awardEntries, slug) { if (namedLogo) return namedLogo; const exactMatch = allAssets.find((a) => basename(a) === slug); if (exactMatch) return exactMatch; - const svgs = allAssets.filter((a) => a.toLowerCase().endsWith('.svg')); + const logoCandidates = allAssets.filter( + (a) => basename(a) !== 'architecture', + ); + const svgs = logoCandidates.filter((a) => a.toLowerCase().endsWith('.svg')); if (svgs.length > 0) { svgs.sort((a, b) => basename(a).length - basename(b).length); return svgs[0]; } - const png = allAssets.find((a) => a.toLowerCase().endsWith('.png')); + const png = logoCandidates.find((a) => a.toLowerCase().endsWith('.png')); if (png) return png; return awardEntries[0]?.logo || null; } diff --git a/tests/generate-members.test.mjs b/tests/generate-members.test.mjs index 0a008d44..1452e97d 100644 --- a/tests/generate-members.test.mjs +++ b/tests/generate-members.test.mjs @@ -728,6 +728,18 @@ test('falls back to a PNG when no SVG asset exists', () => { ); }); +test('does not use an architecture diagram as a member logo', () => { + const result = run({ + catalog: [ + catalogEntry({ + assets: ['/img/architectures/acme/architecture.png'], + }), + ], + }); + + assert.equal(memberById(result, 'acme').logo, null); +}); + test('falls back to the award logo when no usable catalog asset exists', () => { const result = run({ catalog: [ From ccecc78351d2c733ec105690f864fffd14b330e7 Mon Sep 17 00:00:00 2001 From: mrbobbytables Date: Sat, 31 Oct 2026 06:56:13 -0500 Subject: [PATCH 6/7] fix: file China Merchants Bank under one industry label Drop Banking so the industry filter on /architectures and /community/members offers one option for the finance vertical, as #2026 established. Regenerated catalog.json and members.json. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: mrbobbytables --- data/architectures/catalog.json | 2 +- data/members.json | 2 +- docs/architectures/china-merchants-bank/index.md | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/data/architectures/catalog.json b/data/architectures/catalog.json index e0f69263..9b22dc7e 100644 --- a/data/architectures/catalog.json +++ b/data/architectures/catalog.json @@ -108,7 +108,7 @@ "title": "Unified Training and Inference on Kubernetes for Heterogeneous AI Compute at China Merchants Bank", "organization": "China Merchants Bank", "summary": "China Merchants Bank runs large-model training, LoRA fine-tuning, and online inference on one Kubernetes-based pool of nearly 10,000 heterogeneous accelerator cards, with separate operating policies for each workload type.", - "industries": ["Financial Services", "Banking"], + "industries": ["Financial Services"], "tags": [ "ai", "machine learning", diff --git a/data/members.json b/data/members.json index 828b9793..d5b19345 100644 --- a/data/members.json +++ b/data/members.json @@ -686,7 +686,7 @@ "name": "China Merchants Bank", "slug": "china-merchants-bank", "logo": null, - "industries": ["Banking", "Financial Services"], + "industries": ["Financial Services"], "projects": ["Fluid", "HAMi", "KEDA", "Kubernetes", "Prometheus"], "architectures": [ { diff --git a/docs/architectures/china-merchants-bank/index.md b/docs/architectures/china-merchants-bank/index.md index ee8918df..114adcc2 100644 --- a/docs/architectures/china-merchants-bank/index.md +++ b/docs/architectures/china-merchants-bank/index.md @@ -6,7 +6,6 @@ architecture: summary: China Merchants Bank runs large-model training, LoRA fine-tuning, and online inference on one Kubernetes-based pool of nearly 10,000 heterogeneous accelerator cards, with separate operating policies for each workload type. industries: - Financial Services - - Banking tags: - ai - machine learning From 6df2918a4cdc753c434aa07ad97fe3affe33ac7a Mon Sep 17 00:00:00 2001 From: tpx818 Date: Sun, 1 Nov 2026 23:48:43 +0800 Subject: [PATCH 7/7] update index Signed-off-by: tpx818 --- .../architectures/china-merchants-bank/index.md | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/architectures/china-merchants-bank/index.md b/docs/architectures/china-merchants-bank/index.md index 114adcc2..fc70423b 100644 --- a/docs/architectures/china-merchants-bank/index.md +++ b/docs/architectures/china-merchants-bank/index.md @@ -29,7 +29,7 @@ architecture: import CNCFProjectCard from '@site/src/components/CNCFProjectCard'; -> Submitted by China Merchants Bank and Alibaba Cloud to the CNCF End User Technical Advisory Board via [cncf/tab#140](https://github.com/cncf/tab/issues/140). Documentation is distributed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). +> Submitted by China Merchants Bank to the CNCF End User Technical Advisory Board via [cncf/tab#140](https://github.com/cncf/tab/issues/140). Documentation is distributed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). ## Relevant CNCF projects @@ -49,7 +49,7 @@ China Merchants Bank (CMB) is a nationwide joint-stock commercial bank headquart ## Teams -This architecture is owned by the Architecture Management Team in China Merchants Bank's Information Technology Department and was developed together with Alibaba Cloud. The team integrates open source infrastructure and AI runtimes with CMB's internal platforms through Kubernetes-native interfaces. +This architecture is owned by the Architecture Management Team in China Merchants Bank's Information Technology Department. The team integrates open source infrastructure and AI runtimes with CMB's internal platforms through Kubernetes-native interfaces. ## Architecture overview and goals @@ -83,6 +83,10 @@ Both paths share the Kubernetes control plane, accelerator node pool, data and m ![Kubernetes-native training and inference architecture. A workload layer holds a training deployment (Twinkle multi-tenant LoRA training, verl-SpeCo draft-model training, and a Ray runtime) fed by the Training API, and an inference deployment (RBG role-based orchestration, vLLM or SGLang serving engine, and a Ray runtime) fed by the Inference Gateway. A platform control layer holds KEDA event-driven autoscaling, Kueue admission and quota, Kubernetes Scheduler Pod placement, HAMi vGPU, memory, and core quota, and the Fluid control plane for datasets, runtimes, and PVCs. A data and resource layer holds the heterogeneous accelerator pool of nearly 10,000 cards from three vendors with the HAMi device plugin, the Fluid cache runtime for datasets, models, and checkpoints, object storage, and the model registry. Arrows show business requests, data and model paths, control and scaling signals, and GPU allocation, with a model lifecycle of train, checkpoint, evaluate and register, deploy, online metrics, and retrain trigger.](./images/architecture.png) +### Shared model lifecycle + +Training produces model or adapter checkpoints for evaluation and registration. The model registry tracks versions, adapters, and tokenizers; inference services load the selected version through Fluid. Prometheus metrics inform capacity adjustments and subsequent model iterations. This lifecycle connects the two workload paths through shared model assets and operational feedback, as described in the [CNCF case study](https://www.cncf.io/case-studies/china-merchants-bank-2/). + ### Component ownership and responsibility boundaries The architecture combines four types of components. CMB's proprietary platforms integrate the open source infrastructure and AI runtimes through Kubernetes-native interfaces and provide the bank's internal platform capabilities. @@ -184,4 +188,11 @@ CMB also co-developed two open source projects with the community to close gaps ## What's next for your architecture? What are you looking to do next? -CMB continues to expand compatibility coverage across accelerator generations, model architectures, and training and inference runtimes, and to increase operational automation, while preserving the Kubernetes-native interfaces that keep the control plane, resource layer, data path, monitoring system, and workload runtimes loosely coupled. Areas identified for further work include dynamic tenant concurrency for multi-tenant training, broader hardware and runtime support, and unit-cost-based capacity management. +CMB continues to expand compatibility coverage across accelerator generations, model architectures, and training and inference runtimes, and to increase operational automation, while preserving the Kubernetes-native interfaces that keep the control plane, resource layer, data path, monitoring system, and workload runtimes loosely coupled. + +The next steps are: + +- **Dynamic tenant concurrency:** Plan to tune Twinkle concurrency using model size, LoRA settings, memory pressure, and service objectives, building on the eight-tenant validation. +- **Unit-cost-based capacity management:** Use utilization, Kueue queue conditions, Prometheus latency, and token cost to inform training and inference capacity allocation. +- **Serverless inference with KEDA:** Extend autoscaling to allow zero replicas when service objectives permit, restoring capacity from live demand signals and using Fluid caching to shorten model-loading delays. +- **Broader hardware and runtime support:** Extend heterogeneous accelerator support through HAMi and add training and serving backends while preserving independent workload paths.