From 659e69f8f7f21f0368df0f910918524bb9e531ab Mon Sep 17 00:00:00 2001 From: DeepFal <41166795+DeepFal@users.noreply.github.com> Date: Tue, 13 Oct 2026 21:23:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=9B=AE=E6=A0=87=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=E5=8A=A8=E6=80=81=E5=88=97=E8=A1=A8=E3=80=81=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E7=AB=AF=E5=8F=A3=E5=85=A8=E8=87=AA=E5=8A=A8=EF=BC=9B=E8=8F=9C?= =?UTF-8?q?=E5=8D=95=E6=A0=8F=E5=90=88=E5=B9=B6=E9=80=9A=E9=81=93=E7=BB=84?= =?UTF-8?q?=EF=BC=9B=E6=8E=A5=E5=85=A5=E8=AE=B0=E5=BD=95=E5=8F=AF=E6=8C=89?= =?UTF-8?q?=E5=9C=B0=E5=9D=80=E6=9F=A5=E7=9C=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加通道 - 目标服务改成列表:每行一台主机,多个端口用逗号隔开(也支持 8080-8082、主机范围); 「添加主机」沿用上一行的端口,粘贴一串 IP / 主机:端口会自动拆成多行 - 新建时不再手动指定对外端口,统一自动分配;预览里列出每个地址分到的端口, 连通性测试并发进行,结果标在每个地址后面 - 超过一个地址自动放进以名称命名的新通道组(也可选加入已有组),只有一个地址时为不分组; 编辑通道仍保留端口栏和「新建通道组」 - 网页面板同步:同样的目标列表、自动端口与通道组规则 菜单栏 - 同一个通道组合并为一行「组名(N 个地址)」,子菜单里整组开关、逐个地址开关 连接与授权(通道组) - 当前在线、历史接入台账增加「按设备 / 按地址」切换:按地址列出组内每个地址 有几台设备在用、谁访问过;按设备的汇总行显示访问了组内哪些地址,并带上授权姓名 - 网页面板的在线连接同样可以按地址查看 --- README.md | 6 +- README_EN.md | 6 +- cmd/portrelay-agent/web/index.html | 330 +++++++++---- docs/images/app-edit.png | Bin 142164 -> 147954 bytes mac-native/PortRelayApp.swift | 725 +++++++++++++++++++++++------ tools/ui-snapshots/main.swift | 24 +- 6 files changed, 851 insertions(+), 240 deletions(-) diff --git a/README.md b/README.md index 074b637..46935e4 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ PortRelay 把这件事变成三步: - 需要审批时,App 会弹出系统通知,一键批准或拒绝;访问者的页面会自动刷新结果。 - **计时从首次连接开始**:同事拿到授权后不用急着连,开始用的时候才开始计时。 - 授权到期或被撤销后,**已建立的连接也会立刻断开**;未授权的连接直接被重置(TCP RST)并留下拦截记录。 -- **通道组**:添加通道时目标可以一次填多个(例如 `10.0.1.11-13:22, 10.0.1.11:8080`),每个地址一个通道,自动分配一段连续端口,并放进同一个通道组。组内地址共用一条邀请链接和同一份授权:同事授权一次即可访问整组,撤销一次全组断开。 +- **通道组**:添加通道时目标是一个列表,每行一台主机、多个端口用逗号隔开(也可以直接粘贴一串 IP),每个地址一个通道,自动分配一段连续端口,并放进同一个通道组。组内地址共用一条邀请链接和同一份授权:同事授权一次即可访问整组,撤销一次全组断开。 **通道生命周期** @@ -208,11 +208,11 @@ make server # 产物:dist/portrelay-server-linux-{amd64,arm64} ### 3. 创建通道并邀请同事 -1. 点 **添加通道**,填写名称和目标地址(如 `10.0.1.16:3306`)。可以先“探测”一下本机能否连通;端口会自动推荐。 +1. 点 **添加通道**,填写名称和目标主机、端口(如 `10.0.1.16`、`3306`)。可以先测试一下本机能否连通;网关上的访问端口自动分配。 2. 访问方式保持默认的 **仅授权链接**,然后点 **邀请**,选择授权后可访问时长、可用设备数,以及是否需要审批。 3. 把生成的文案或二维码发给同事。同事打开链接、填写姓名后,就可以用数据库客户端或 SSH 连接 `192.168.1.10:33660`。 -需要一次开放多台主机时(比如一组服务器),同样点 **添加通道**,目标填 `10.0.1.11-13:22`,表单会预览端口映射并自动选上「新建通道组」,闲置关闭、限速、访问控制等设置对每个地址都生效。创建后点 **邀请整组**。之后要加地址,点组卡片上的 **添加地址**;已有通道可以在编辑时选择加入某个组。 +需要一次开放多台主机时(比如一组服务器),同样点 **添加通道**,每行填一台主机(端口用逗号隔开,可以直接粘贴一串 IP),表单会预览端口映射并自动放进新建的通道组,闲置关闭、限速、访问控制等设置对每个地址都生效。创建后点 **邀请整组**。之后要加地址,点组卡片上的 **添加地址**;已有通道可以在编辑时选择加入某个组。组的「连接与授权」可以按设备或按地址查看在线连接和接入记录。 ## 配置参考 diff --git a/README_EN.md b/README_EN.md index c36b72e..2e42079 100644 --- a/README_EN.md +++ b/README_EN.md @@ -58,7 +58,7 @@ PortRelay turns that into three steps: - When approval is required, the app shows a system notification and you approve or deny with one click. The requester's page refreshes on its own. - **The access clock starts at the first connection**, so a teammate can accept an invite now and use it later. - When access expires or is revoked, **existing connections are dropped too**. Unauthorized connections are reset (TCP RST) and logged. -- **Tunnel groups**: the add-tunnel form accepts several targets at once (for example `10.0.1.11-13:22, 10.0.1.11:8080`), creates one tunnel per address on a contiguous block of gateway ports and puts them in one group. A group shares one invite link and one set of grants: a teammate is authorized once for the whole group, and one revoke disconnects them everywhere. +- **Tunnel groups**: the add-tunnel form takes a list of targets, one host per row with comma-separated ports (a pasted list of IPs is split into rows), creates one tunnel per address on a contiguous block of gateway ports and puts them in one group. A group shares one invite link and one set of grants: a teammate is authorized once for the whole group, and one revoke disconnects them everywhere. **Tunnel lifecycle** @@ -217,11 +217,11 @@ Open ⚙️ Settings and fill in: ### 3. Create a tunnel and invite someone -1. Click **添加通道** (Add tunnel) and enter a name and a target such as `10.0.1.16:3306`. You can probe the target from your machine first, and a free port is suggested automatically. +1. Click **添加通道** (Add tunnel) and enter a name, a target host and port such as `10.0.1.16` and `3306`. You can probe the target from your machine first; the gateway port is assigned automatically. 2. Keep the default access mode, **仅授权链接** (invite-only). Click **邀请** (Invite), then choose how long access lasts, how many devices may use the link, and whether approval is required. 3. Send the generated message or QR code. Once the teammate has entered their name, they can connect their database client or SSH to `192.168.1.10:33660`. -To open several hosts at once (a set of servers, say), use the same **添加通道** (Add tunnel) form and enter `10.0.1.11-13:22` as the target. The form previews the port mapping and selects 新建通道组 (New tunnel group); idle close, bandwidth and access settings apply to every address. Then click **邀请整组** (Invite group). To add addresses later, click **添加地址** (Add address) on the group card; an existing tunnel can join a group from its edit form. +To open several hosts at once (a set of servers, say), use the same **添加通道** (Add tunnel) form with one host per row (comma-separated ports; you can paste a list of IPs). The form previews the port mapping and puts the addresses in a new tunnel group; idle close, bandwidth and access settings apply to every address. Then click **邀请整组** (Invite group). To add addresses later, click **添加地址** (Add address) on the group card; an existing tunnel can join a group from its edit form. A group's connections and history can be viewed by device or by address. ## Configuration diff --git a/cmd/portrelay-agent/web/index.html b/cmd/portrelay-agent/web/index.html index 18226ce..71d5f5f 100644 --- a/cmd/portrelay-agent/web/index.html +++ b/cmd/portrelay-agent/web/index.html @@ -329,6 +329,16 @@ .preview-row { font-family: ui-monospace, Menlo, Monaco, Consolas, monospace; font-size: 12px; } .plan-box { margin-top: 8px; padding: 8px 10px; border-radius: 6px; background: rgba(148, 163, 184, 0.08); color: var(--text-muted); font-size: 12px; line-height: 1.7; } .plan-box .route-endpoint { color: var(--accent, #38bdf8); } + .target-row { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; } + .target-row input { min-width: 0; } + .target-row .t-ports { flex: 0 0 150px; } + .target-head { display: flex; gap: 8px; font-size: 11px; color: var(--text-muted); margin-bottom: 4px; } + .target-head span:first-child { flex: 1; } + .target-head span:last-child { flex: 0 0 182px; } + .plan-box .ok { color: var(--success); } .plan-box .bad { color: var(--danger); } + .dim-toggle { display: inline-flex; border: 1px solid var(--card-border); border-radius: 6px; overflow: hidden; float: right; } + .dim-toggle button { background: none; border: 0; color: var(--text-muted); font-size: 11px; padding: 2px 10px; cursor: pointer; } + .dim-toggle button.on { background: rgba(56, 189, 248, 0.18); color: var(--text); } .add-member { background: none; border: 0; color: var(--text-muted); font-size: 12px; cursor: pointer; padding: 8px 0; } .add-member:hover { color: var(--text); } @media (max-width: 860px) { .member-name, .member-meta { display: none; } } @@ -442,7 +452,7 @@
${escapeHtml(publicHost)}:${t.listen_port} ➔ ${escapeHtml(t.target)}
+ ${conns.length ? `${devs.length} 台设备 · ${conns.length} 个连接` : (t.enabled ? '无连接' : '已关闭')}
+ ${escapeHtml(ip)}${leaseNames.get(ip) ? ` ${escapeHtml(leaseNames.get(ip))}` : ''}
+ · ${byIp[ip].length} 个连接 · ↑ ${formatRate(sum(byIp[ip], 'rate_in'))} / ↓ ${formatRate(sum(byIp[ip], 'rate_out'))}
+
+ SHWG?0EZ7!{g=O?SDXF zVQKoOaCUWeZk(RS8QK0z_%3u$JRzk!0fQXkMaCYmaU~v2wJ*RkO~OLsk=v+&<>lw$ z0y;(kivwfOvZP7MDh(8ptNfr3|2$tWs||5v07rTgRIh%W@ygNN_diYGSq{mYnVssh zCqCH)BIc`CugW5i*#8gP1LpUjc?qg1@D0?CAOJbY1eUfFyhSGL6xYRx){JJ6y%>XL zmdgH5Z~7lYNG8?)&mKJWS8{1aEIq}-;^d)W3)M!L}Vz_>)3v&khpepZF^Y>3_b#OiKHoZ%EPd9Q)7D zc=XTz=Vu1xjW;5$BmxWq5h=M?V#E(Fh}kZ~Vl~F!laM`KOG+yw_ob*uhJ=iK-j6d= zID*!>qy`f((MjenW7Xx4W-t#Y2#$a~Q%G>}x`6j?RP*i{x)|GL4jBO(?K4uKV-2Uw z;u0K7&^;8POKIiq`xstlyk3;hWO`?9Yi|UM_9ONMvRN3eGX|L?MNSS6ABLB&IU6C1 zrop`D79<-n#^2RmpXmZeQI~gKSeWc+_%th*qAs$2hL6sw+ b8#TAc<3ft>8jcEnZQK zr+PennVy!m4)ixo`RMUu*YSj~WNpkFwXR<`xylJ6fhk|KkX<~Uhy-Sm;C _mxNw(k*r#pVu~Fq|6%E9ci(_0gr8VH=@V$xd z5<02`J0Pe9`gRl Hr! zNa}!5f9B`mXP;@E%VA+=z9&`>VMn7DPh*nOd+5_;fl`Ye(aMDu`NJ3!H0#=6V5Pn; zZv((hxUrd;4$up5ii)m-NaDv%4h|JPM~L|nJ?hOYB; ayLMeo3j)j+*un8gbI*Mtr>XF|_vV-xv?uWxexoqYlh@T{ z2G`U~_n9oH|DwudcefAq-#FuI2J6c~=`^ZNMm=b1kUroDr0e=${L^g-4AbTu+oe z)o|z;Y{_r_9=wUCKaj=CgedG9V0&;Bi8E`4hjw)ZU7p@gN_vOI*4)&z(L9%$9zp`# zFUUA d@&dDedFY!P01p4*K=?|@bq8P( Ln1l zR@Q(Xt= tNwxzyUf0w#Eh#~$;7kmRy>w@9 z?R*;iuS$}Teza%+HTWqVrL>zo?#v9`?#Wo=>?0h%sHr5fG>Z{qKA*}Bd11-c!4W#N zSe$IVc~b(n$jzMzKOIO?N}IVzl!Q?YWdL82hPdm(9un4*EG(Lmq5z}N_a{OjH#~oS z=-zq#O*t@jt`VaP41Kk=`# _nmtbdO{CCk7uKn7BtqFYw(}^h*LCU7aakjUn%! zlW(o$B<={jw^Ko=!?Xr1)4*WJd)toLr+&!rxFiAn ((y5 zUl^w1G$Ba;VLCsCh|(9I^uJVA-mu&lePt8tYQjTnSqg1IO(6k~=#cuX3ih+u1uH)W ze`b7<*b=;!99;-T5Il|rD-DPOQx?xV5f&Chs8H0IjyrSskSQ0e`lT?;tvmwP4uyGW zI~C3%wuWx^!!kjeEkkw1B6@co 2ppgOQ|=Xakh$?Z6tzQ9N`kk(JPN&e zITxntH%;u6`@kH?$YHA0IY4`CY0y@vUT*(v0Npv`CpZ@H b6s}*;H(kY2z1dU0pJU{iw|-IhdvSj{9pZe%j5X zX~{f4sGWL6ke`2Kbo9{9PsZ7BcSw&mzIaF^?Gvvv@Zb?d6cjPG7klG(F$M`DSk@i( z<-U!LB|JAjddiZAR-XgH=I_=b(_F0=)ptOR$~LEMAZSp~{~R5CEE5mHeFcxD^DLju zKTj?PHBZda)N~Iyc@p*e7U^cy^1(lp^5CWQ4Gnr(w`6f50Q?KQ?~2W?+w@v(*(S;+ zWxFoIpfNRN8K<%*O3Ot}n%K8nj_^G2^OI`u-hBKAs*9xrD|G-fy-bSw3@iaCj@Yi& zZJ&6&(i9Tl(@qlj-eYOz3HgTk?C7`P69Pr2jFFOfW&t|%$cWLowg;c|K`*ZokF40Q z;8|nb0hMqBnVFlf;ZY>{I@VyLc+Lx+{(wU|CvKcJ{5GUtK8pv4g+CqxJA(%X{mglm z{s@jsby?y-yf9AdEKEP}^{xE!h4@rLh;nd)__Ss&VOK}NQ66r=1N6Ff1m(UZSND_c zc5nw!;~cF{JZ<6Dc0JkzuHZ{BT@Rj{`{!DD|6Mi>*CD!#boLZKA74K8{o_QC _au7MHUdK^4PBmN1FAL<3* zA}y~o3KZ5n7C!=|{hQaX$-miMYV-b_mzNiq-On!p$Jb4u{Zjm4Q=IMPrvCyR0g;Zs zLbZJp=ASiO#mn8ZM_7qq|1EQ*(=({K@1pyYz1_^;;|6D9@#s_U+&aM%1Q>@%g|P18 z-gyhz37u?PCNHR;;5YJgu~%Ms`8EjcinWm09yj+ M3%&hlhhV#rL71P?%8T {5#=xY8vo;S|Qu07qSpkC z=Uyz-GP>b=xP zk1h_LyaG2a%tu1(q65u(6Ky`a=z^Q1(v{!zXjk{Y8!>g)=a4xv!#sOwCOixfN}!7M zqT(@Sj-DNJnvdL-#iqSpM?U2Eaa=}bv8a&F{$b6Xp1MoW2eKlt{i1rP@G_1q=iz5x zzfL9j;QV%J_eX48)0g(WH}ja7=>B3md@=jpoLr`y^_mAsaYi*`7tSe|x4e-x;vZG; z^_*S&gedc%4dQ*#P-`UGbWK+t<13ri%L 4B@&G^T8y%Mw8Mh=`iUX%(aA&Y^UYE!n#A#!hNroOo~H z1-1M(&=*kqSX)P|)bzW2@6*}A{&$@=SgWbe-kc^acW&&^Gb4A)+0@3;-HsX_JlkfA z|J}zgfi?pZQX56}qaN6&x$7(b*OGWdbQhHGtnV7%L9$fY0|)jJI{*wM+=~fYpo%Tj zCx)A$BR?i>x2RXg=g&@1;-g2WEFa&e<_1jlhA%fAb*w1?uoO^(nFcD%kr8|SX~l>i z97gOHeYJOKJm}Xs2~Ft6n_uW g=pR}KRH`n8>eobpPNPTp0gsU7v%RC0bp$27Z^KO)5YvDxqMeJ4vsi}L%OYxF&L z*%d@avh&!vG_>ZF{cXusjkd8#S)OQrF}~92a{Qt^mqi{Sgf+%Bfon5MtHMA z-@j*RLRMdSouXhf746@15-qdRUxqE$_=A=yG9toJr-nsTY%30JLsvx7o&zK+!cCa} zr_ImEsqNl5s<)&h&!ReZ!O;Ci$AW`JRw<~TY)13QUCa1U6KZeyB6a;dP(k3<6^dGY z*1SJ8e% G wU z+4{Y+Q$FAxub!3NU89&=Gewu~+jndBh*zI>KJnKNqsTjPLhsZE^FDGevJ2xZpe($< zMxz$6c8eAh7l$@#0L=xz(JfrJydn*p&^u3%7kYSf3Ub@idgGCL;ulg4$#$vMmYZds z`Fq-S4m _hn;a&xZVJm+g*@qh@IH_O(TgzEJ68yUFT54B)FyPbtlL=H{8< zrE4f%wr#aeE-{sv!7|ZP2*mUj7l*1qHNGaWB8OOH5dL2;^SaOOo%&!xba@j@?xjtO z;wx!k#EgZMy;q})Mr>8FA)ZUNWm-4QuqoKuD0c^~*;DrR&>{FpfIDn=Kl}V*;irB? zk6~MyiVP#%Onm$b5OPFdESD}=18ii=V}DMQB{vbgAT@kXkKsXW_orMabL7Fe>qqg) z-Q0AtGY=}-O%u2HwDC`pjeRBNXYV{21qJro71l34999VnyXPe$tOGf%r;i?=_@x!) z2(z=%{%LvBSEx|Vd`=2&8!y>!md>l#%TO&Cf<_kG_3qVc!^EK3iI#%k#5ytbVdJxv z{)4W>23~k#l&K$7$Tj`re^*v={xL{&1DB^-Q)2cbZK`V?0%OI!- zkQ;(*R7pv?ENXGwa{}q+)gADD?K;`csM;Y`s(Oi7o|Mp|3f0-Wc8}S;v%0^%xK*tB zX1D1f8;=}4>f>b#=zI0z)vGeDvs*trchN0)yy2?$bkrrK32MipqV`f;lh`EdFGO!f zj{UU#N~|sg6xq^s53UTLD~QYXcIncNXt_fZt~#U!9t?$5x8bHmJ&NFOa@VHRjJ9#) zE$wAyv) 1 z{v1A&qT?4?pK|ER1>Lp#lAEi~hJ WO`e=h3jozqp=XDxoZjQuyS~dcLW}JVnE&HCjf9}Ly{o&K z?y$4B&sVT~g507l`Hj?%Rg}E4lb2DE*=e);q*S{kT9#~h`@QG+GDkj&`I)J4RV~#n znRl-|#cGf3Pjx6E>H=o+{X3;k_32@ucGHIZOBWk_Z2HB;87F><-5wgY?6#?}-#5#P zbmt(Q7;O??nVDnReXtZkud=dBi4~cFG|n_;|9Y7sk6nmJ**%LyGLC&Pe{jv?)tz36 zmXiIW*%pmf%~uWiO-?ypoID%UT-jh-jStU0EGoLT_h;t9QG0&837f27zG@Zvp{k<0 zhpjZ8(5|zP=Rf#^e;k^;&_0ds%p}??=15@R_B{c$sM1wKHfYK9?%n(HK#y6u0~WaH zN14VLkF6tQ FM$0K~JzC23maO$W__yG`doV_6$5~@D%0KS1&89_xqD3PkFKO@9DW)11C)jrm+``%pr&_;{g2V2$or*vn< zR|=<0_=KLHm!8?%QB8U~8w8A)@w&{&$RP<^-!?RaoI0fkBj}%!Mio%eD+ &*6dnuY3c3Tvn+J4 zubsV8vx?Xj7u^+ohkABYJ8%@eYzaJibcDn8)U %{eWrA_{dTi^p5^J zZA_Fd*Ok0+_0D_Q)YQwMJ6$r-b?gubBZQX9bT~=;I`YMpO1x?5)`?Np$pjs@w9|fY zjAexLwNf Fyv3kn_+6O}-3YC>}KaE!pToPvi zp f}HP={e-R~$ThZ_SdqbN{7Qq-LiP@i{9l>`vg~ zU4GRrNms6%FK;rRFL&gO>Z7oM3JR?+hbjI2RsS17S5nj8C-(P$N&J7u*9F*s_dNf< zlZpTQKLP4Jt?rw<>*z m-|fL3Jb_oXU6$0Qwf T$M>eq0JJ~$A0quNC`+{`qFQy=t^m|Dm7#w~hC z7dLLszB6UA$*Pu!nU}}(kOIhsG;+~RTb=+ItrX<<-(OWfd4<$~ @4*X4&vuWthWzMlrvm!q0;^G6!bVJVVeQ$&eugFNU@>%)F zHf@A)*F FzmQ8`@M)s+{I1((s{N%-=LThU&pS7cE~Rr#)azV*d+SO* zE4%#K6e2}F7VeiZQ5>VJY!qh!>&jOO8*TFb`}7$w9K?*8N<{VEqsV qj#8PNNvtiI Z z_Kjt(eU<>VP~WoR;0m4E;(i|gCRrV~jKAv`J?5U2;&oN~o?=p4@_EYN+lTusY!t~_ z-?K}#K1v}v$-VTr{`7s4uEvG?wkn1k7n?Wm)ebm~sGiS56&K9O7e45_h#p!){@LfY z3T@ Ma6|jy)?
k0a1csR@Q>oObN$Y 2_c#J%_qDR zWtx#0uK_98b$)_I>edY#JGL!qM=g6mQmF&EC8s0Q)C~-Nhb%AzFv@!Bm~uCtCZl%m zw-@Q@>6C0l#HEGo*{iv3dqq&C@Af!w4!W%|C+F%${>GB>^jAA#n@_Y_lsqdnv#@{C zx(Yeh4V%k43}nPU32qBw50npWD8EF(|9 $+<1 zeU=Zf=jyoUvG3~v!a(|efsAhy@3zx V@Nid6dg9c9V4B*mokqXfzDZ;;v6JC9g^WbbRq zN$JS9@o5*Bn{zI9;?9wmmj~}^=l^xJtm#Va(%e{AAS|`yHC+I=4&LpSYnCovoC@sz zJw%tD5VZ|>Agh#*ZIN8%$?xF68F%BOXl)VuOsIuASuCnL0&e91qeW>2Z^gwgjjtp> zN;|SN`DRB%$(vpW=yAHwki=>U#L)ivv;MZX_kpO{HnES8-8NW3;b@knPYtTfb$})a zBX=>1$eEvR%c?sw&2u$iY!CHFtJ_;(PhE5)l@CEp48>i~mv2GR080pwJwzu>4;NIG zBS&7Om|fG=xy;?Y9XW2h$8U;ACSMqkobgzNGyqxunKC}hH3R^9M~e5u#?1`J0r$Is zj9Pfs-fQu7P|_@XSvslCY~H-#66ZM&HDsT;RK%7!V&uGHqzsiY4hdO*M9egnCGxr< zy=)iYEfi!({1oJ!`-|jTX+5RTk)rOJVs{uZGsO1k(+VwXdEb0|=hY%MWllxjJqVTs zr?iX{EkE!$F#B;(Z?C-^u={E1`Vy``ddDkRTtR>{+@bMh{H #n zo^M^V#f+(+8<|Ig`nAqZyP7{L*sE`346Ar@WO&FAKEN{@Eh3l)OC3ao%iluzh1eQ! zuZb-xrPXLHVo9r?}PrWW`^SzMt4uDEZ5s-a_-3--``tTGy9p!ZZK=sew@gFRRJ!Yd|ck z`?J5bw(}DW?>uG;C~pIEZLGk68(1?nyYX431ovU=j(Pm4E?$Xt^OfdA<73$ zGJ8y;801GCVsjq!`>XV8?ilMsnJF9Z+UHPjY!`lz0Gjo8g!H6OKJJ zQXJFdB1p0FJh{a^%S3m=z}&oX A^J zdp1HeO>RENi3j<>*$S{NW{i9*zLW#)rS|R4+ay#J%@`PEUTCL1t@B+BBI@JUPYO2n zr`6$ofg!f>K=vCgw6?bX;b|P=w^CCr3tGjk-YDhE(DUTNT>o(EI osUbXHvM{Oz4ff?s^CQ1?xHQ!h)#8xH-IPPT?;N#7TsXzTb&)Vmm|`fg5?FgVye zJY IK zsa2N(EaNu1V{HE0Ula&8l9SkBcaq|+N{Wz||L$K`?x;g_5{4B(0@)wesEaowTBY54 zyFI2%qW>MX-9;ZZn4g>!ZbnZpW-O&N^=W6IJ~S#fNdC|L5RvY+*8N `5-<6(r`y*180#Oi1#PprCIZ9S6InH!Fj_DL?zp%!~}o_Or*WB=V2L zP9Un}#5ayFFs6T)F+=Q!FhYQRzx4k7*RI(BQQOg<2*Q>AHIfW|NsQk^sCB@kTEQ@% z*tjC5*2wzG872lSL%RFAfQupXdBq@ajf4kN=XWg`sI_pnzqRPnU7BH%U$$9!?e9rz z0YSCooze#-rr*5Eub%u_T`#k!Xm<9>KOAegOvQ4VC723#NRCsM6LZ~*sgU7OK&3Ab zZL?iCvSE$w9D6bu(T$m7%fBM8Bl10oW#q0n`6Eiq``GQW42dxP o797tl~VCGX-#%I0261I9kyiB`};T@md;_Ij8q z9s*MOaJ+>xBs(ZTgNp5VO+VFj{rQG_p{VW2gqC!jD!}G-1lsnh?;kGrgCoNztp}~$ zqi1tUeeQTgd*^M=x~LmXyX|;Fee77@an}qw9_<4tBIh27?aXnrs57a%K(hFq2R)z4 zn5+_t;d3{;7EL&yj75*VM~kG4u#)MWuJc5^>8bEo r%qoh0D5vGt z`=i>0i_N!;l$E>0(=A?X{;5=RxZ35QeHwHZ{V}n>p1&G~qE4rI2C@bgh)YT`M6)(z z^9|dr^>iMM7AsarHW_)9+GC$O)7e<(`&lbD<)YVq dE;r>QZ-Bo0p>mjq qKznbUgv5)trbq zp<{@e=DBa<#x_WwX$)qW%|! goC4P7jwmm!$59kR z%rkJfX~4w2wLf_SI=_9`?67QbX_4QCQkT&5@QIkX=0_>dQa`DyqXV^*|IXoBQrw%7 z{}dnSA&C&Y-_W58bjOg?wR~gSR$Q8UzrG8ucG=fEblWa@(SuOtbcTc;0oQJ`w_5fM zn^AGU&bAc4j)KN7^~v(?hx$Uo4*nzPynn?XlxcQFGls=<>h2Dgzp@Y87O%YE&+JDC zPT;Kc-yO5Cvg*}#s3Nx;2UUimcb-rcyZf7|K0|mwsxVb_+%sFf%ZhA>K8y09x`Y9T zn4ZLo=dt%wGP< WAuA~+3e2Z1fOT3n@3cNn%5~8tp2u1(KmSDBYnQyXbia;rz~1luXRqoLJfq`M z^&VLjAN}qb)_uOEFu|-P`z?EDV^b4>07X_uPmg^FqIlrImH7C$FUrAiiN!YEg_F0| zD{t+a5a?k_SSAcuxokcOgrn0@Fq261ZhdVnQc9*vTDx|%TFD(JjfL@svt!D9OoYVl zb2phhIr&c@N(=;LPr#BdPq!_#Pcu{X9$f<<)I-$R)bt*e;CEcMSvnP0LSm-%xV`N2 z=5A(1>-!mlN?Yk@WE3jZ^sRn0GwSgvM3xhKuG;}fKZ ~dzf__t`qIf)i33%_C_q7V(yGnOOz%9UpOl(~=}(ATv)8v=NB^O? 3ncxagPDdob=- 3MJ;cNidxEntV#AZI>9w|W&|PXr zo5{O&j{4`Y;CI)LN-A@t!ObA?LatqheUu}yz_mg*&&&SsjQq7Jn4PA;7$d$kD)B9I z6b8WpW&ktbL%MJOh5G@G)Y|v;yZdJjo){tSo#N5njF*UoOe$*&F9yz|bHu{DiwQcn zJBJFXqQ^^Jm#5uUEfN|AdVr`GFlr)VeNnP7EN|P@@_#dy<;nachi5O$<>ELu;GE3> z05H$Cy1De;Cc}bd#Ku!-x~@l5)a (b5+w%LQFGA@_Vt`S)=_JV(ZzNbrAqk7s~kGg`2}OLKC-! z7KAv|;~^m!Zm+FON>2X3d8F8{pRI0WyT{F9J8d08b^SDv`{c0U0~B*MKw?5=`ZKpD z-je8;<#86UVNh5s$NXm`0pxL_N{QcGom}2z9pNx~+_<2XeMNF#se_nQH19*e1+I=+ zf<)+$VjpX()vIfTz^27<0?0s^7sLR~1+db4{ ^~y>Gqj0r z %B_!@}UMstO9=)Qo$Y zpdh Dr67O5Dwn4XV6=bv#*xXGq?J)hO9FX9%MDqk_cCy-rPMY zveYuZ@?-0m cZ}F*0O>lj+`ipbFcX@`r{$ z&D2lw9(AxCP;LWVy@1bhUyinidWDUCrIa*2nYBP0x DEQ{A+I<%Ww;%Te2?Kw@ zL4owKv9WOnbCJM!9y{s?)=uny;5CU^wFFP*5F5u0|4v)K7d(nh++%d{(rhCDCqaK@ ze)<}UdVqx4wy8?=4e`mBVq=-s`R}l0J-Q!!lDASeX})%kNp3A~cgY82vT_0Oso7`7 zlpRZX3B7HI(anEE1?9gdML78 z)psY_sM+ zeQO=NspIH1S8ej(kLiz~Ht8{N?8^su+^l_-%le)yVvTwVXH)b*FZ0;j9W~D2OWF9$ zK;}!{IAzG^4A6M5d-a&fyjc?g?-)*G*%yUct=4TPvc@%Z2lek?V5hxi*PD|hA{w>% zo5tKEoDUTfFbtR$UVZo*?h*yD?6wv-5ek=rX3dJPvn8o#SOLFjLa@V!o;vmP-sWE^ zegAAf-(kKg{Z;WOb#+iMG^1@>$A!+lNV|ipwXmTb8{9?T@QLz$KrN)j6zjYZ`m23& zKkb}6Y;eFm47O-Hqs+l+ncMa#Y05P2aeqrgEO|m7 oquH$V*TW9$pN4TB7&aygaBd0DNOmwX7YUPb}-B)J*W$9|x^nH-wjh+)_ zOw`9Af(Tdt n;BE_Oc{=+Oe%q5L5+z+f%EQfb_^ zu~YO8_k`?dwyx5EQ_ylt@e)Zb-SWeX&DH`u-Nr=gf4*wfa7QO!^N4wDSB9wgsYA 2udKU$jXz`4uTRU}DgEFsl&_6_X7yx%a4|2OL*?5- z<{ghtI oRskBEr)I0&jQYClUV+zh(y(}@uRrQw@orH=B8DJquf zkLrJ$D25b@hZH@jtTgyBXBEHQiZy{s{dMVJ;ijCdN|<>cmi2JMVExH}u}w|YgHwz2 z-}=3J^X6{-maiUru?YN;7fSd!BmRNDuHV9u_Lurvv*!?5s$SjZ%rLg_D78l3%$lpM ztwk7)fl^ND=urLXKHbJhLMx%kA$B^jl$j3tSJuytEysC|X#t(w^5sJinS`hjTkGt+ zLB|?;IW4=-PPJK=omZtvWXl!1RSZe1Zbh+vK$-8L*-x3pPn^+8t6ur+sPZAcFvv;i ze}DhMCn?{)Av;M~4%%v^VaXnyHvBiAI(yI0#Q1oWnmY1hM~v_(Y!Ha3+eH)o7Y>q? zJ2z{EhHSyB;Rr6Em&qH#N1~}1VEVHwDD}txCt@ xe{I_Ogqcvr _zB15a-m1hXs9yZ tPMwi2UHS5I8eRD?*AZwD_Tv+#> 8OsMqNQjb&zl5c2zAxq=E?Eb3lRc_KP^`|#|7GZI4RV3{Mf%aIRj^dIk} zPn7&nv^GV&uhP+FdcrDNI7nLVsA)`|&D9?RB1^&79=u<8aWMm;`iqqT1y)HnL1+$_ zcm zhoBj&>kiKzK_iv+R2c0{;3!xQd-%*WUOnQa+N5l? HmFq8*2L2#%)vK8JZLhiY)DDZ{PScdunYyqN{0LztXa@zEN9kTwTPSlxZgH8QtC7 zxkpN4SMP3{IH=i(Yf=p T{2_*CyYeN+p`c8^cy)C$iL8#BHfg%Av#_Y3vUhoM5Emx3qj>N@X5P2L%5nkD zU#fQ2=lA#?&dn517vF_>pSGn)lnDNaLh`k~X5Ids7|{6nsbtTdJ^lRrs0x6x$qD-B z!{`55d+c{%B^gP9P?jd&M2%%YoqXOt6fmrcHoyc0eK*G;L7C^zi{6tvF)?jtCbf@U zZa0$%V>z_Nmlw3RJ=+0&r&M}*Y)eJodit3ynvc5mU229IK{vAP^JvhM$4!Yr)*JqM z&;ma^vC%T>v6q i;D* lHrJui&GRzW41@6+Wa@=olktS?FBlTT%`#!9D8-K5G d^2Ja+apbZh$yvpbu!dBqnWvX5T9iTpT1;7yjTUI?oY-=1G9nXN?PB{h zyfbmWU_Mv`c+pn<8L8*4DTw}OCMG|-u~=bR*mm`)w4TB|!1Q!x=`r5(M%i#StW^_j zX1kcaIA7_+8r_B|rm5)%YQ>gzkLI*Trb*>ZL?rfd7j=pUrHD^R7$I>$-Ur7IH#B8v z6_YCmH>c`8dy)9;HdnwDnjX9KWJSD#f{4<*9QBP7Ums5A$JI-h#FdC@G>({07y>~q zMc 2Zn(&Q@M4VyTz(ou)Z8d^@mhfSjP zA)=;w;?d~qM@VV0vF>1A-d~L#MGlzV%J1W+xNBN~XvsA26T}}_58BeavL^W|K~+Y| z=qiA-BDL4|u6;+15uGHjm0P!)In=57%hs&vJO2z=U(Ud@36pSC8uvM#V=#7XpPF`o zgm7(ug}J+S>%0w50!xU{0o^zKiga_%#l<`^*H=3+2)(B>O~?X~GXCaY=7|6OYOra{ zhREQ)t6I)(wIT;hY=Ug}FvJ-oU7?L5SP(HbEN?;#!%n;Hou7EifA$DQirsGSKvuYT zsH&RU^wUq&)2dIOJULV54uX%k-zt3Mp_B(0YMAzi;BDQuD_Y@usQicsHQIh=D&!vr z3|4&ugD80|315@Tdzg?h-9Rqs0GTwgmoDi}oG3WvOl!vsIKnGylzf*B14eG8gxqO^ zK~CSJA|iU%Wq>%8da*rhsLIzmMj`p8vGG5Dn|r;N@vvadPc pThOBCdw z7-$S|d;eQ4rXttyOdYoynvdv(a-{6orvWNL1sWN3J1Vo29(BsYzO&;iO&lEzB&Ogk zwM`SKyD0sE`G<-2bDAV!*B?=ej1uEp7dbz+VEO)aM`SZ=l)SKsP6H+;mgL08jszlKrKmKOS=?bvE*b$ {(l7OVTii)osGFsvH*>tDG zn=TL9pz@=$6L<7c{c8xOFp8o)I=)U0T_64B>~7Az{0dSI85Nx)VyfGNLkTCQEM2Y| zlIO5C>gn`N4D#kIP;?etPS4f9$IY5C10A2lg?cTR`$zYz_D1Osdd$KHbnZU 9-deB10^It{?)TZe z?r%7muvX~CPRdA*4sZL=;Q7T!xrh&du;kbt3Z;?3v)S6;6s_2j{amfTmQm;-&dbu^ z?to#^Qc}M_Y=rZdD0o=0r#J{)KCckRNG1DamK9t0^E8K`yY~b}=vNmC_-EQ<0#TGA zL_|ZiaFm^voUU_a-~d(UBw2rRqq=_Hc@!b-?d^6B5+|}WrOIW4-Pa#Fq|_j<9C-E` zYP(ZY)z$x9`#iWu;lqooB&Tm$jS|?(D!jB}^xw4>;3e`_l9!b7 1R9R+LZ zuP$^-+;7tvGl*|}YQA_MFDO$jyz_R}`wjv|1XQJ@Q r!5i1fy%&Ain@nyjd zy|-x^ubVnpYo~{Y^@w+jb$!>~iBx>K#tkFYU0IV(X%((LIO?6WK9UV?4_l=m?s}Ok z;*=DO1@vye(6F$q&ecedE5?^o%h;z)<~UH8V%yJ0?>(PMOH$U%XP}Z2qThF+sgc%W zr6w*D_qM&cM=8McOGgLrNJY)qUv>6gJ%`ZQmG)EK*!c1=S5fig31 GY4gAJVyj4ZV;SyO= ^PCYfrq(kh)GS%e81~ztu{$a z%NOTd9C>8pfrKj@GQqY|W xU4hQC?g2{E_yw7L@3Jf* +oY2Y5c~b^2Hr-Q8S|0Hh lJ+G_1YE3E?})zS>-c8LE-f2)4xV^7jJP= zxZuY-jBE+da^_yeqiDs1<|iw6=RpKBi*EbE@1sc5zy1ZeREwLwcOJR880p9-Kyqk7 z8ORKRLA|GY??9nkY?u1SH}}-$)QhL753*ODoV$M8+?B2|r4|ZE(`sg{$~Y#B>ZDe= zzU7sce>{aqY54War}e`+#vJ{N3VcoPA@!)E8g5QPj+Uv|a6c-z5!l@w9M)vJt_Lg~ zdlLk 6+%W(AjzJ@lm0bIMa%*CD z@mcDgNKnjFmuQBCw5v$SG3_;B!K}p86)uRj7iidc-5sA0e^)`e(Ra}5YkPitrXz)? zZm6%f-S(SkMUlP3wR#3dt(LgCdclJc^G1f1)Gwt?!d|I1Yw`i9dfGX1{07R)dr*r- zFFb`4V$h&Q7h65?v}&4Sja$wjFSkXSw|4&gNx W zgIW6Je{YG@ORuO^4GIEk5;b1PA9<}2KnG2@l#0W6ocLzU17tH|Xqw{v9CYbg7Ruwt zmp#a>;|7mgk$K-^hP%0W;F6woOcm?dol9ulncFSk5! jxQx6;AEEq-S66==ozE67IKYyy@GwZDYI3m~2tyqPzJ;&cManJ9A=|*_t}Hy4ss{slu6-4&;`;I9y?{Q(>)QH9`9?r+U9bR^`0tJp2x<`2;JZH zEV=g*$*g9?lbKdCx4&NIuvhcgC>s3ty2Iz?``kslg3j#G#Gci2&7 {;1IB)wkM}vhe?MhMBOXJcQqN-c{IjR!OrPa{4y?>5h|7nX z(vY2(Tt)7%wbXo-f<^wD`@bE_WV8#H;?X#;P$Jj;+t%fx)NpuuYjjo1M)AkiiL#&X z2vwQ5RNz_e*MHtVk1L`FVd^M-VIIw+$izkl%gkbqe+rFmJy7J`vC#r=(s}p{j{qh% z#K4mk9?-6wUbQs9I@s4`^Qrk~3+i*HFOR;DAwsEUsB`=#(-)%Sc1#_tIM>p`LQYDs z@90Nu(vs7E)>p!5o$j-}d6n_Y$TsIorM EC9ZAnw2f>$0}Zb z&)@iHZJ*H&6~$r79bP(DnL042H&{OkDD;ZpVE=xQs|E?bKk7;+j1hZpvjYt7d zJ@0h){v8DedI`w@d%kPAC++B&CIp_+v9jSHJL70r@Z_=nTn5zvLKOM&NHCb|4*KFW zhfI;3JN4XVf$c-7W?d9ff|!-f+3qyn#jz}G?nUdwC;E!BhXo6Yyx97pT4H0E4c8`R zm|_}RzCovkx9R(yeH52a*@`Q#jU`A(PwyJ3g>*G^A!f5@dsXk`%wpTMaqMHYjPB5E zlm#y9l0i2<=1X$c>qlvl9V70v;(ovoI=z7d5fC3I7rcM}?%75hzsTRT)`Tu;kut39 zpLNRaXy@>_gapPM5XEz}L^#bw60&~V$&L`Br?hMw2XWLKTwg@OjdEj8r((8)2b#l= zojvQ>`gHu|(M%t&^}So6G#p?aYywi 4#6Lv#AVM`+r z&Tdle)2bDQ3~>%#vuRuHf& oC+U&>bK}&mCLia@%8aM zjP-FpHs)=^6-o~TeR4sUc(=J1{|PK*7Gmv Bjxpn4}HfE zl=4VX8YEDo99c}-pz@^ahU=BPmT#YSmO3``;p}Ij{da`^EoE?^e4Vqs^+h+ Xac`8MI+Rr{o0+!aKt>4(I()2;@!rOxc^xt)Tu|z0Fwv`T&DLvw^7rjI zC}jl6xU+u_+b{O5GYZHo3HD&f3-3|+11E974=O=3)p9#+ YV+emlsv^E_(d8vaC+6R;s?x(XyeERZ5Qd(NN zZ(j=K-5{*PPx4_*c7}x>&!oa@n{6mWZ?--h;T( Gx zZZ_qtCl*p<;IKB)mCp+c)!4TGd^3!x?ytAixgo+JblZm5{9}?;Y&e5*&Iq@qVzj9E zyA_9mg0j|_##b(OZd@pG(eU+`9~76&rc&UrUg0E8pw@ YG|rnhZ=-aGpgP2%zUALCAPb7WK?hIhttAkjSDZXS z4cU+sW27wW)(r=Xylg40sBaNpNukoR4_}!;WfJw>lJySRL}_%EZj+n7|H)Q``m)xP zL8wK8jvjUUr6n3^P+amTuK$iBOBz4#lyugSKcyenHbz{?bvg88vF D~XwZ}=vt zXgv}I+7~eWs7afZvQwg?jiVRp$qmn#G2$N{B<;)OTeAEA=GIWnBx*)`ow4Nmu>x>{ z3PQ(E k)%ea>86}zhbNy-Ql?YDHFro$_;+J9Q^my7EyTyYfY5o zmmgD=`cCUpu|M5 *dMQ+oD3YJSd)A^$ou#2>1}^ zvh3YkuLwzxO8y1)GA7qD7}C|+*49Im840ObS%rD~O;=l#ju?mEalK#|&KoVlH}8Cf zSuj3+%%xnvMr|9?%~(D<7B5}18FXS2y^s*gol_Y+7-QE-hGn;IE-_Y9gm7K?KH}bg zosA43&8#6j46*y=jb4qTg?UH(3e}LqB%XVC%pLL1>3{e+FE!klq&{$G{?ZZNW`m{< z6@hXerJ*sxhr*qP_q@DtK`)!ehnukhEsi@O^NJkhQzFfA#in!4j}4YkS)IW|E&iFh z6ponYmjG9p#TFKXG;B3Hw|bfRl1eSC)u<7`EjgY}iwl3*;S#8FYU*NT86fmOcULw2 zDRk6%9N1s)Mu6${55m;OE}f8ZPjm{dK$!)YqAbLCyLIc|zcY_>o;WUW?KhuIgCdDk zI5BtRFdwx;N@m`9=!6}ADbu!!8kf(~p8q*cJN&53tG2d)(AmNdKa}$;`1JLwU8-FG zRTN<>{l-ph`yQQ>V;yJlN3lEh()cn*Bu2AG NBy;c5{U49Jlkvr*{iKe#vCQx;{?FXUv+OAHBQdsOj*wUcYzr zlKbjmpdxU|&&f1r#! YR2;AF{Qa7h=2hJZPtM7A7n72Z zJF@{YaOvMaD#ITgWn;Aaf@+0N&!KmJSzfMeK6vJ~ct)4AqlfU9-;(oY@M$k8Xr7Gd z5xgTIHT9l YeBumEx%omm#lXEQs?F&)&<;=ZR8H{eA(9H zENa;G!I}Cf>Zc=hSunytWdsw|q4?MxLgrpfN=l;UXf2O@$gZ%W>c(^Ja2Nb1Y#$mL z8ai@P6bDVDiDNzo39+4cGtUM+(l<&(uE0%y6@4R$h^tuMp!=VDaq%w)$AqVdub+O_ zRAmR$59bIiY;(wR%`ml*Bds)dY}?jS5!Zh&$rxvtwenDbfp3+F-g=1UfyJ4rrTrvn z9M;M5KWkUXS3$8NP#HDPF#TY?*_=If)F{W_o$a2Vj3(Ol@qV#wt1${uhTTkKW}+1n zY;X+;GuOshr@v!}_;>#%;Bs&Qu+3s=@uW&Yu0-G{O6?7q#k7G0fGt_Is#If6vOCbi z0>d98n6IjF6GO)2ZExY4pRW0gS_Sx3827zuyzr{zN~)5%M 2INS)yK)%mi8Iw8%CohJ->3S(>pPXaDe z2^Ffhwinlh2_j5zhDowovg8ZRe1zF0giBY;ntG`q?He2*tDvYz#Zim=n96_y)}CQ; zYHDQRw}3viuC4*}M^~tNQ<>Q!0!K;U&WRIlB*lX!gN~@F#R6=lOj}FsqhtN?+c!_h zv8dChasM+WgNtLMA+nFzz>?36g_Yp@jmI#{)HGu3O58w|cW|Yi+qIQQ{4RuJsb&lU zy?5i1yK4L3V_&!cM1?!t+*W2d4J`kDku+}@pQl_TEA={q{L<#jRu1z?Aa{x*pWd5A z6@iThP2G(CgnIi&-8z4ME&b=ipQCq6iyl05NFw5=;ErS=-#`5Ti4hNz7lq8MwC-L9 zFJX!J1Jo#?LRY{&A^hol373bb^c8=TOgVaEW_1_eR~5#lBsN+z-Qs$V6Ob8SMvDi{ z_61*3co4QHy&dlrR4(A;; 0s+3Z;Vt8VR?yjz&2oh#|WEdt@z{Ri-Axww=rA0~12&4^vQ z@ndz=P%ox*7vdFp%`Old2I>d1FzFf2Ee{@6RfV>k6k}y=EJ?DIH+kf76qr5I>=MKr z|IyzB)$UL^xkFyjy #B)Q{m7RFP>rAq*_P9{R1BYL%Bfn zC+r621UF-orDMSoiH|7|T5NSP F5YP$vqVpU$H_+*I@yu(Xx?Buryc&Ykm;d5k!t zBqf@hkZT*tRZV7_nu?1Gd)D_zlp$ceH z_n|v_9N3$WY35LYVM9niG>zHHlfq)aoTB6wNnsi=kddH+gwbS7&a|Jc6UhBvCKx`j z7W0jD@R+DowZX8nSKeAzC@m&cIu8pF`!E0pF;MFd@B3X&=*WaYR_G1z#G=V)`UlMb zFoJMPTt+-$VU>-_ymG~fk{IdYecxx$gN&dNg54E25Krl(BX4qu+xcdYBolnb5&63H z1E19E_F=AIl3Ra{M^<@71{&Iwbgi(C_3LxyrWFQ^9W&-x>U!u^DS9RJHe^J#EdXA9 zgK{Wr+#02U1BG~ N@b0T&%-Zyy zG3?SOi7&&Dv!)JsYHA=ZdQc7P#R=V>Yo|Wi}>KKI+V1@lzf1_Hn-Oia!VUfnXG* z8Nk7aeVF^gfk^C^&YlaEJ%I0lfLY{}0`gim-GU1J0|I_?h#&Fy2N>+)h=&R zfUc;x$ssgN1YJ&%>%k}8nSvt!skEGi!-I^pv?2O#qZB)j%V-ns382K>X8cPG!c(0( zN>h`OmcRg^BHi0u=5KRjA9v^w+_5)TPXm+e(CX~^@z7IBygS2&s*<9tcFV?;?PL~g zjrpAi58eY)uwGlmIAR=X##L@Rx=c)Jfhqi5?XE_}h?0lJ#jsLBt{A;yn1+?f&ucov z43>Cau#9gkjm%nmw|D1uqp=PSjaZ)M$5|**FP-iBr8a+oTHj^yl`If&x%H~5r^l}| zg^OU;>mqAw5AHeY`N?{EGA5_u^wCNs{8^L!?}6+Dp#;o5c Mc^D?~6a3O0d?diQNe>#u9b@M=`}6 zA@+<^4!^4#D$-ZoJ$LEL zYr;$`3B} wg|2WR1HR9M-)Vyl&n{@(G2DkL(;n)U+j(*L&)dhYJ^ZkYr%B5C-dWDR?=HLw znEfz)bDF+SKa~q?4sNcKYW_LAYM@O<(+W_*Q;$LpuXuN+Y55#`@L|WXepao*t^O!F z0r7R@)2Nfx@9eHYeqYE=g)FDPviCWUr8> HS108h4$uiWry%D>BFaMOj%&PEJJA%Eyns z-goPh9vwW=BZbij_NloPw2y;qOe9Lawq`IhoNy>0jAp&rW<6w=^!t02`9egb%Yx^+ z3>dmJeAJW}cP1lA`%PC{GJ$A>o&yID{_+0$hu&fb*f^L_$w4|klKyST-oW9*h9Qt( z7k3;yKIXy&ADP9=`b;-T?CeToxo(7+V63{!vMb6qju%i!PzK4EV0WIju|_8?gOQCF z7niO65-_hWdU{Vl9PS(nDRe zOJEj~H3Z|7 LUD4POkT}W)^-V-}_7A@M4AyhLPCg!6*`}OM= zT22HUr^YYcut9r*dvZA4Eql#BCXVle1MaEwURh3ReSEP5M||}>VI(}JoSa+R*RQ|m z?Om` LOshY{Lr* zqx%|YRa6x}yn}LCf6(kAr$&?GJS2h!rQZdAh4)Jm6OKgv;jgmWrdOY?oKweV>E`tb zLOSw6j1Wk{l74Kbjc{Tg#tBF-80K_^(5Rj?{9p{jf|tK 4+?T_+$apnrHx7hN^fxD*;irC$!dr%=Q!gETlp+wOAJ0=-Y z9ft`u>U*vQzsRMic_aQQUa|RR<+ZOq$9P)=m(PR=UoeKDexzcS=+$eExw#NL3lr5# zh2btAZhlh=;a={eU}HcQ+zPhn&cbPb#$yDRw-PpaH`yS{CG82RWg;hdf|ks~>fiqh zANOZWkRe$vlo+@tZaa!zI%~+C$gRuc7*E_jbUiOoi7#56aU^Xo9y4OZ1)QMiyJoXT z*x9`XToi_2icF`=D6LD|alWdBQ7mcH0%T^} U~PYI}6U(4hSO>rxI3PV)DUFZx&S!;9@oE7KXVI?hbZj}m Jw&nz!*w4v3Yk7+PLK{@yfhKXi%Ajh%!ac)YxJ=c%>>9(kaoZ!M6FHK zJhG8hS(_BkKFmr>qsU%odiDAB9m!UKj9cjoA~|Y+cEj5x056<51UInC7+RFxxh6<{ zV)Hm9h!2aY8|N=9$gTf1X)ah$X2INpH*fx)RJW&`*NCbSX{vVA;s1ok*-n+}Y3r&U zv1~|Rz%WXOCHV6)70;It?t}Z<=1Geerjc^g4?=eX7o=*jWy_XR>=@I!ek>^Q NEUUBWrkMT!J-e^~!x$Q{MZRQjMUdtB1 z=C_lp^zTh^<)7`_&rEcdRoqTP6UrATTv1U`YTBLeQR8~fzKtQbNZ%;e->X5OqYm zhk;)KBUHJ9_m83lEA6tXyj?)|;l vOxA&2hoG`>U zuHXHf8pHDEKhu(Jg+bKeW~|rEk9y1{8wAkk$`$n*s~?AB!;0;oUMW$S9mw=E%jrGR zep8)d07E9ZdGiO(*;H?vc(hiydcZw6Vd=9d%eNMYvNx#ql6zcUPX6KV6(!`5Us{<_ zhWRM!Rqnl)GtIQw`#j#tLA(eetC09hV-1xe9pYQgA^d~pu{1cpa1>Uru&}D~DQj4T z3DylWrR9WuNpAUkIW=J?{Z)$7hGLOK7+z41O^ZqQ&Ttl)+I^2<9r5;a40C#=w%U*V zBYf| bj*Etk<5}<`o^s*F?o@zPBb h2TJqq{pPQoM`Xy1;iTAR5@(qsaIuo8eYVsRWwM>rT z;|8ts|7Hy9TaSHUApGVf(c$AG#>Y?FZ$#paSIjpJsvjMlq}}hki!-K|sRKIl1AF&K z68@H#!vYkz0jB$n9-UL2b7HxM>HUuyF}|wFl^Y@~9o=NA(MdQ=yDU`0xpk+D?bJt) zwgn#qL?lzA>}-9LeR=lES+fe?J`%s5G{>;AxOfg(k~$ImSgd}5P+E37MLIGmXXH^A z7sr)N=~waicTkz5PPm!eq^@zM62#DTY`zpxJg7lu>EPRcX(HYs5`)+@uFVjB!I}NS z=!3_LrTzNL$vr*PG5h0=qjnL^-Uttb3@a5pSCj&dkz#!BM+@fLJht|c;h>u#xp2Yh zOQms$BWb@witjXjVff&XngxG5%jWPV1RCW{Zhyn_2+DqWD)&o2tw)(m7@O(VETb9L z^7{3N0lj;O{$I4cd039^+xJUI$XH0EB9$qX6eUASp(qlCL^Mi8MI}Qil0>Ek8YxLg z10o@rDjKALgbYn?LkSsLpVR$&-u13`t#@17v$k#d =lo-~BsuC8eY9 z)jvNcI(PDnb=m2n;cR$KLP}f|zfOzPx0|MYSS2?=%=B`X$E$D7BGs>^uXM8TUS0-E zh;^ss+;RH&WbW}0{6glRMz{AL_**Ug-@C2oy6l-szzUeC2OjMhGbq?JwaX- CFDHvOU~x+|GNAy-~9jb z&;PyG{_p+h|J!SSTE`7b&XFaf_0XYP)(IA=P_8bNI&5gc=#*3&snEGA|K6`pTK1K@ zW7A3<(ET=l_@E1^ROMS ^?eq?GsS=9D4s|zlbu9m-NW++6 z+7lZqyNaw SB)9dGm4b*A2xQK{+x$(LgdhuqfYr^*Pk&SM&cqVnYYLpEsqq(+SR* z5r18@I9rQjbXUj?z&(AKINjSy6{cT;f;lX#zr22OIS(zo-ag&^QN;*FO?7aogWxK# zZQFEtvJB-phNwmWc?YN6feELud#ks%`_vOSwH}>sAojVvJ?WWOW7&Epb1fGn@opYG zn3v-~c{JfU{=~dGKwo!}t{EjD;#)uc=Lx!gvn8s%o?{E_7CbHnLOhiRZ!|in=kA02 z4Uwz-7n_~OwY9&gdwK`ne*D-KNDP%l%Si~A0yS&eG+rL)3NuKoAW$rOMX}o3pV5VN z_&c7}XX z@^84uyj@xZIDc~!KV#WJt4;fQ#q{r@>N@8zdBw|N+nXvY>;~~1t*97edAhPWa;RBW z10*-UDay+CH_V(9Bn|^NEFhqp{3%X3QrA>=kR2p{r=lVY9nHxbJb*2q5|fhNVe*!# zxGVn^h#feof})~|Ri@a`-oj5~` ~S49W^W7lmbxk zpz55&9(qO?l0agvN@dT)ZJ=ra=6QGOKSx{!A7IzzBcxen5!V91qPTlM&VDIJsB8hZ z?aFMQFBN_k54_}hJG)D*znR<{d+lf_i3dpZC`th2ymIZDkpAhh6x$9=>@u)wS&Ds8 ztA*SEuJ}Ih=J)Tp hYu*jB;ISz*qW(-KUSBn z`5A5$gMoUtuAiLhzShV{% xYj<#?D>AOPTL3`Jl?v;T47VO@_3nSMylm!w8SZV({R`4Gy?r*sYnh zY2v#yy?7hL9vdcFW!l`{k9s2`OUt?9eIa&2<)4qEx`*o<1sO$J+UaTSRZ2s <)L=8L z1Cm2e79p3TsVZ$ZLu3$dim@6Gb+`ZVgv_O1`Gysxx+^74#MrVXY1s#7Q57MpUZHYX zdZI&C4Z8r&t`HxA;9;6kSUr38Y;sphD1ZG?Ys#X(`v3i$JOcZtYHOGMQy>};PlrtV z!sPNiJ0P9**Wce-T7W*^eqr;-7~_=X!!7sFYdFHGOD1yK3N6KAU|F| clq576 z?H9?qIREO^E03eq7tdyM;nHGE!oP2uQ66@?xHyeJ(>rdgI6K(a?lQEA48wUK(50oN zSAzb&O4m8%wBO9wvAx!9zHMu{ux>8fLI#0}u2^LfW+o@MGq^YF8Yvf|{l;g)Q(zYU zpW{X(D0xAOIkfYVX)!Jeh{B#_IS*|;Hf&h%p<~D9zMpG4?x^vBymJ=1dGoN+Z_T-W zeL9FXTtpkyZP*w7j} eEk51pgsI6iC=#L^)X07%}Ztc#UT_6|16XqUA87m$# zdcu?n%&dL809%kn*W7(OFGZ`E BoWAHV1UE%4y*(YhNvlI;T zH#A5|N(w{H6IPvCaj)DQ%x$IxHDc<3>CA-Vg^rT~Q8DIzc{pCE(qier>dqFt=)WhQ z4`!#s0D2p(vY5PHJV(tug>bLV(F4T9 )8LgiE=uGR8Nver<+tO1P{P= zgPQdF&@HqMXgSwg|1DLz#C-funHDu!rQg2=+yAB%`@hvg!ix(T)c^kf|60fG%$s=4 z?yCzw==?GC%cMti-tzWW@^769Y;v#uv$OkEv1sAPH9eX=Ieug1H{~vg@21$bu;d4;N-3*3(fo76JBa(T5$9l z051JLCB}>vHTDUWrNi8=0lc`f#!4nfc`#tjp`GHQn4d_1+IWcsVuLaj^{xidt9-^2~;i3+!?p=^}W$`is@n#iig zMNZXNab>FTcKE*U!w-a=s%&<@r8`u0>tBuseHO+IPV3i?@db2wL?}20L(NzBa0FtM zhk8k4(xm>!Wkf`Ift~LIYx^8jD!hMRum$RTI8wB)G;FdfIZuW12s;h7ay(c~SOtx@ zsSxQRk=O#=J$*m=UmFhgczU16K%j;Uwd@Vcmsc@~+wJ@Wzmz;0X>bf|3coTT`+M_l zhDfMRpRFD_L0h}yLJN$w l^Qs3 zw%9P-GIiX^nIo>lc|51Y$~aB-amFBIOApWk#L9N6I17yT`l4{L ^s41aM-YFuKu(2&nTmnb_+u_ zK3L|;;e!U<&h$v2)pv8OiNjw;WfjAnReEA!_Xq--Z(>4pB}XIRKb3jDyigBrU3_KI zuN_-qe%4I!hIQGu=3-`MTgapvOaS3fSYEW*wcekfTC)ESz~jlIN0(M^XEPr;eJjS> z!Wcr&2# >W4i_qq%#XK(c{nEXBgP0Hy1V$-@R*nz zNZ|C0_zJ)->(0J3GM!IXxDJ+-{Pg436z8W^&z`MF0zCo5B1m=q=}k!Ppurt;gs2Ic zASREVof%t}^#x&AlbDdedA=v)!oX9D8)+n#ELqY^e%p*rJ_>SxseWqArK8@F@!Sz| z^5x%^y5^fmr|YJxzwq=uoj;&g;O!1qM0cPwtI<@e9KVJf07$s H6VUUUV;}Qfi3V0&~fKl3zZ+Lmw40fl*Q_fJpJn}Ud;-5e5;H~)zRke`&OnB zT8QR4JGHYjR$TK+J9)Ae+QYnOJF_;{3W0BT2MW8zteZ9`OC46``eap4?`4(N4vVCJ z-@Yf+*YB%HgLBD8XE_vTY+3U#t$C2Nv|v-jdb3!%R4`OwK}75NYKGk#y&H~1Cqqz= zWgoA%E?l!Feqr+H-GYf=dHLb$d}>}d`KO1C6-V#pIwM5A0hZOWl>FF?$1@<}(w&_4 z95{8QaJR&y(4Kn;+A!)AF#(*VjP>{d?`6c&@iS+3;?4DDQ}K#*GE?1l&h103#)tCe z#A|MKXLkIHn?o^eX=RlI L$)Q}Lz-EwIL5| qQaA1zo=i@f$PFS)Me++R}Yr_&6Nn=yEo1i zR>ln!LfF1cQ472G6TE(nt1AuMEn0J?0^ecQXgNpgi#bxewrZ2p>Yy=55AKES(>gTD z1N0_n*%O85LJP9{AS4-h8ff%LiYtQ@&LX_>N1D+?8_gxqL56mZk)CfK4n8`6iqjM2 z!WrX)_w#9sxD@aGt02R>awWpc-8y?iHB5WiYZXXcfUt-)M?oWy)4;n+&*d$JWjtm# z;<5;XKD!5GS(%8%PZ2*xrQ%rG1KJWTfG~8#&|eRlRsJb&hQjXhPs`a!kbZYCdfxV} zb_)Z6bmLEGAIl$H&9a)PJz01wayH*D&;*t^;3U$OndRl8@)f9+Az+L>UdWP*IeK)= z(fMF<=aLYf@C+*LMuGc$lM55cRf4&O;D(1_Epv0Au_9{{YdXwN?@&>?f1dKrC+p|O z!KvoshSHd!O3Zlh9ezAXm}@#}E=`dZe*Q0$Zb2;4Ul_IDBZx-HIHIKF`FjW=*q(=6 ze&LgP-eK2(OYFUWNs+5Df+)