RunSnakeRun-2.0.5/0000775000175000017500000000000013572471440015336 5ustar mcfletchmcfletch00000000000000RunSnakeRun-2.0.5/MANIFEST.in0000664000175000017500000000044213541777402017077 0ustar mcfletchmcfletch00000000000000include MANIFEST.in include license.txt include readme.txt include setup.py include *.desktop include runsnakerun *.png recursive-include doc *.html recursive-include doc *.png recursive-include doc *.css recursive-exclude . *.gz recursive-exclude . *.profile recursive-exclude . *.memory RunSnakeRun-2.0.5/PKG-INFO0000664000175000017500000000140213572471440016430 0ustar mcfletchmcfletch00000000000000Metadata-Version: 1.1 Name: RunSnakeRun Version: 2.0.5 Summary: GUI Viewer for Python profiling runs Home-page: https://github.com/mcfletch/runsnakerun Author: Mike C. Fletcher Author-email: mcfletch@vrplumber.com License: BSD Download-URL: https://pypi.org/project/RunSnakeRun/ Description: GUI Viewer for Python profiling runs Provides explorability and overall visualization of the call tree and package/module structures. Keywords: profile,gui,wxPython,squaremap Platform: Any Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Intended Audience :: Developers RunSnakeRun-2.0.5/setup.py0000775000175000017500000000434013572471233017054 0ustar mcfletchmcfletch00000000000000#!/usr/bin/env python """Installs RunSnakeRun using distutils Run: python setup.py install to install the package from the source archive. """ import os, sys from setuptools import setup version = [ (line.split('=')[1]).strip().strip('"').strip("'") for line in open( os.path.join(os.path.dirname(__file__), 'runsnakerun', '__init__.py') ) if line.startswith('__version__') ][0] if __name__ == "__main__": ### Now the actual set up call if sys.platform == 'darwin': gui_commands = [ 'runsnake=runsnakerun.macshim:macshim', 'runsnake32=runsnakerun.runsnake:main', 'runsnakemem=runsnakerun.runsnake:meliaemain', ] else: gui_commands = [ 'runsnake=runsnakerun.runsnake:main', 'runsnakemem=runsnakerun.runsnake:meliaemain', ] setup( name="RunSnakeRun", version=version, url="https://github.com/mcfletch/runsnakerun", download_url="https://pypi.org/project/RunSnakeRun/", description="GUI Viewer for Python profiling runs", author="Mike C. Fletcher", author_email="mcfletch@vrplumber.com", install_requires=[ 'pathlib2', # dependency for wxPython 'six', 'SquareMap >= 1.0.5', # to work with python 3.x and Pheonix 'wxPython', ], license="BSD", package_dir={'runsnakerun': 'runsnakerun',}, packages=['runsnakerun',], options={'sdist': {'force_manifest': 1, 'formats': ['gztar', 'zip'],},}, zip_safe=False, entry_points={'gui_scripts': gui_commands,}, install_package_data=True, classifiers=[ """License :: OSI Approved :: BSD License""", """Programming Language :: Python :: 2""", """Programming Language :: Python :: 3""", """Topic :: Software Development :: Libraries :: Python Modules""", """Intended Audience :: Developers""", ], keywords='profile,gui,wxPython,squaremap', long_description="""GUI Viewer for Python profiling runs Provides explorability and overall visualization of the call tree and package/module structures.""", platforms=['Any'], ) RunSnakeRun-2.0.5/RunSnakeRun.desktop0000664000175000017500000000026613541777402021153 0ustar mcfletchmcfletch00000000000000[Desktop Entry] Name=RunSnakeRun GenericName=Python profile viewer Comment=Viewer for Python profile data Exec=runsnake Icon= Terminal=false Type=Application Categories=Development; RunSnakeRun-2.0.5/setup.cfg0000664000175000017500000000004613572471440017157 0ustar mcfletchmcfletch00000000000000[egg_info] tag_build = tag_date = 0 RunSnakeRun-2.0.5/doc/0000775000175000017500000000000013572471440016103 5ustar mcfletchmcfletch00000000000000RunSnakeRun-2.0.5/doc/screenshot-2.0.png0000664000175000017500000045310713541777402021300 0ustar mcfletchmcfletch00000000000000PNG  IHDR@(@sBITO pHYs+ tEXtDescriptionWindow Class: pythonɱ39zTXtTitlex *SKNU*ͳR(I-.)/Hsq+I(+(OIBNj IDATxw`S。=,ocͰ1BaMfid6mh)٫IA VF`޶[CޖdlZOnݽGo M>` B!Por_n`30MV !B!yE!7n}teB!B>z',JR  $`ӷ&(eYR%sBGE)p:VZ%t&3gӵD`0 òϫy^u4P\y_ GYYVj*k(Qۡ)B CAcd&T6Q"\NQ @S5Z9#bEN((s°FӲGr9Q@jt:۵j~w˻XI|f8ܭfX6x;!M?;hBLyZ8#AE$1 ILj,n4't% 0:e :!Իh_!N&TВ^|liNI/(-BݼwWf#\W+lq}Ӝ !Sybg+TWWK SHk_}uCQ69>w-\Ĝ3eBtІX",9¢>u@F"iER&h~,2:ʹ:mxDhYiioR*!h!x?!zb-/Q'mڈ:$W}E&fֱ jj pjnR*e%'@!4!R,j=߾vc%w=xdvKF*i5>gTА9lNg ѰHRɖʶS '=҉5}PS3[C|w_U%%VEmdyھKڈ:Z^7 *v hq)vw!z* ih$ xF(hm3M , baa 7>Wj=+}Gw0h4Z!c V{7v9h_1R[᦯{jbPE ӟ~e$3 be_~[&6o) @ȊK 3;FoM|r{-C!-u_st d@(+-+"0wer(=ѻ]_#Z PLƝwu ݻ{@lkQl6/J^5)b?aՏ?QJ.S? ;}mY?]WxmkVDʕrysRRo_@Y;n;w!An\װl@'K@V 5-x0;h`VQ0zAb>7r^v3ޯ}t4|)y+TOO4\z(ٗ]~ݠw{Dd|uܡ}dXOK|H2݉o?$~μϜ/Ww%Ϊ?ɑ{q["&vՊ VYRІ6b+ͅWT1uK>)ҷt~[?go{/GT#>W#3nwm{pӄ'/[Ўkzz/|ġnE_M>7EЪdoF0^aX`h>.Dǵ9 a[d>[y^=МRW,-PsFB:MtQ܏=`$vG<30~{(RvrOfCק7.,y 7ϾpܳevSn=_~'UHLteC-p6~ /ΫꖙW/.5خ^lrB˂k_Zpſ8P(J^6Oҍ|[f^{׫@W9P!P\J7`շ̾oW$(#/|nq?pZ{_tv(>FVdwk>wG&e9+_׵tm^vlBRYDJ)è >0G]@fμ˞)Qlf CfD*I.Yw2}ր:{Wa!PXVq`4/{`|$\I3y҅m<˲Zݲ,RBO˝=] B:B9Nqͽxu^Z󾄬GpnOB((p5?1$::B!BZ_hV!B!OUW6}=TB!trB!=0A!B30A!B30A!B30A!B3#q[8}n !B!Mܷpnv߿.<Ʈ'f$Q7_Z1YsY+ !B!t 8]}mC׳o%h֊!E[SsQʕw\4hʸn+!B!tn:%d^WI{O愃Ա⯫O[NM;?E>OEkŵ2HEKyۮ7!B!t&~Ƿ, z3ԿܠBZ`ࣇ ǭ (vKerPrnm B!B'8;{<^@(޴LP qTˑEn/9%{FFMe2\iuɀٖV^:nxuSn8:`ZFVYߖ0O#B!zKtS,m>BҜA-"#itS_.mGѕ9%5⎊oycQ4B!Ղ `:C^cS"#jԘ6̍xT۬|$ 5ڹ(tXbDӲh˶] B!ݺF7~U,]Ѣ#WuR#s֌/ZQ5hF]}Ҳ`B!}76?y`=XB!s30u#}Nw)g,B!9' B!M!Bs0!Bs0!Bs0!Bs0!Bs0!Bs0!Bs0!Bs0!Bs0!Bs0!Bs0!BsTjJ$Ia!W ypSJAD!BAQ'm# P^^r9Z]wT55ՊG znpr&Z0#JA!B7 .Db0 &qK d۶%e0(i5IU;5տo۬1NVrt{Hz|yeeߐ3R(ʇQZW0"S]~F!B tnu[풙%!!0 ' fBBcҎ&˖ppnɂիQJVkiiIEEn?;ZZ^Vf{QhQ҅CL*ЙrKܧ3sB!PtjTdjTh+DQ8^]]r2aj׬yY,ZB̒YfnQsƌ/.5}+f5S F'8Nۛc4..$ς[(,,wI11Qje/@{ !B f洔5ia0bگk©RerKE3U׬ Lt,^v쬩'%&&m۱]p=zi>fj#6%ΏOOen<[l9Ӫ4SQ.yeҸ>{ !B-R(,,q1<5W܁0 rlpr~҂Yn'B!'FeEVy~c!* 2ee%bQތʊ?/:t_gOϖ._t:CCO3q t1{H 7N۳dz5;3 “,n?qҚ;(Жk9ZR))uvO?SJTs:a)羅s?}5cb4Oeg>^y/Ϯ`~VUP7'<0ckYwҺ)d)!B|D#HTg Va !DVKP8X$Jܾʊ+W.=w=h k_T}>u^6-*:ۖ vkUq1G.a!κrBAQ*RQ`-ٷ ʼnܨxQDqXp n2j!igkGti-O>ywMfve^^j9z3RWbeQ-\碔+t]B!P/ Y{`V/+YT}/yue+~RDqܹiiia,aGyW_]~ZOzD8w!*UΑqY$IEQpPSUcHY@ISs~Yut;nuչ8:~80ݗWQ^[݄Ӧ]}򒛓Ս\'V&?ἦ9p>]k_|zgJEK_xusT.B76\gݒ>4VEeY]\kg~#?-QR͛@vv`t^>)1XB~ZSQѩ Is64] NvKd"ˌB BYYaD%-N(B#nߟ_֠jN-LntYQS=Z4!ؔP_充o_UÓP{ym/gi߿uQ-/|F~um:ﺧU媬޸'Mv]CV7cO;ƣagGIr[P*v6(4助 Bw h*dkE,E@mShnZ)LU]>'jo t}L֮[+ >C/˯Ȩ jV*oY EpsD0a`2 HejUNʚ{PAy g$$J{UEhciGߝ{?sśv .KebF\5uÂEi3'Ԧ%sfsq#{hR/gJNc`p}_ִ$a,32/T6tf r٦%€LO/tK8:`ZFq &QB!PP`M),<{ަyE=5:3tAёA U-J 9_󂱨+w$? AVQ 5OY!,pa(U"KT!,oUc&w .yKTJVK 0gʋRJARdO7*:e[N6=è랽&ݻ@UԔn|ꁥGHS7Fja`蹬֬m'̿kjRLfN+jxUsn>x"@ u%p q{}øckS\R9x`uuMW&DeP?{{.v-O47~]72;|a"kC.} r3 nܝ̥ 5 zAg0*L/yူ`12",]^O)aoe'URyr#ɒ-V[yWN m̜1T+ Mퟤ-<B!t6hƨP Ot_6ݘ$Q[L@7R ˲ ebMcFI>cXbxNvJY ;PeY8:kTÒ6Y%l3{rsBXFѨT2nZ.Fb~Yoٻl6YQhuMޠB!S `jXQ@DȭՕj4*h;sVz^kL 4=UdR-!XȒBNTI8N 뢢yB!SpkYh qKcpkiJԊñliiç5dYGS"JrXL;9};bЩ\6r{"@a)q,sF!ȲfM;ZGQ:0<ϳ~缄B!S `LjP _ۭ8T52t6$1Grϵ4rmrTn- )ΚKA5rp:kZQ1}+o]m29#CUB**"2( .5O?,Na/!B:FSJ1zNN {HJU[S'۲> 1mֆpYűlBk7.-ޝ-ٶ7JE\Tb͉5>)7n?\jW@<XaOrNY%PGxm3*T6V+nᒾj_딺rJUG\DmD:uzAE[|rۑ*76jYW_>*?/Nz>tE8ˢW,*1~뮟Դ;.qr'&k !B{8cB^?yǛ_LcM3x-۷u䓷kuj/)*W%~?4CRԮKGOP/Ӳ>!PwDFw(^(ϭ Nil;bw~'OBmM7>]M~*:Vu>tE'mC?fZ_4Oe\( JÞOc?ݼz)!>M^-]ާ_V4?5}/ƨN^qIT];*-?Uh`9}DH|FLf]kIO螣HU:p+ }gշjTU{Ca~[V9_Riym *(˭wV*=ev7_'.}@NMU`=̢c;*6zE!Йu!YOmƤU+[ 3/7]sbwG$-n&IyuDβ6-z̀(N=Zǀ^6rQtաCfOT ko2Iױ^{+3:2STJ1=~E,v[ĵ4aI}|ɑ›27?ӄZN[uIRT}jlG@[w.1tUBC^"|Ĩㆇ6ΓgMʖԎqCs%%- y?$7Q,1zfO>ZSD{5->|w6}Ʀ/G^cmKӫ9V=rFD:Ov8%ΐ46T]]'(;mQRǪ8=9Bոio*mzjZ1,Ʃdˑ&%E8FEdz5.S*6dP3 b"5t}Tn2jQhN;U%Lil>6vĐꝕ6&#UHE2Gњ{&dU~׾77/,gOeE8*̨NFedEЭ[![$l ;iq 6nhcYj!r;_ɝ\v>&,y،ǃϖqYd¯NK7cvҙQRo?<ؾu+~6s!Νa74Ƞ?gsm1J21/nwh@}owoz[. e[˗~?Ʃi7XWP}UL 5B_le m5@< H _D˿hUĕϐDYZ}AeQPDJnhf epʯ_.I 1E[ŒM+|m*;au4G,xNۧm JgM DM[==TM+D3%[$٭Ȯcl]kiaxV$ .G%Ya;WX)CGF2NuI*n8#E&Oi  mWy)B!;thz=AUO3 QEᯣnh`:16GXˠwhOZEoUi *2{]3ƧK{lǟmzr.w~交)?1v/U9xKr%\+6H cnLx.2s3l-pMATBUo`L1 5NK \̄+2jN5T?udQݰGbyjjy:ג&o܎Kur24ga5cU:D#XVVVFQ@̐'}7V~iU6zO1A!kB Z%kq`{{1I֜DZtSG\-k<ςʐņSVȯ%EvUVZU쐩tocuhRG$|7U_'9JtFEEZTEriBEMo6rA6W&ӆ0'eG;SJ&6ۥVWG>\Cv N we';IU6B)B!tv]J py۫t,)31!/q 2PWPk26ql]R(mk*π? 34ĺT 8.}pEomiys" ʎaˎ؝U$&Bg?ꦊ$+ظBhL`msJ~_[ga`:kPEBg]J\xq-UӅ?_1 F/=+Pj60O.z9G#c`+v\`J'hΠ 86͟'?,g= GZh̘ԊUϝ B&f`koȚ6Ǿ:j uW_gg%'%g/ڔfӷ^6rRrꍿX;I6uXZrRrrƸ?<ٵ 52#9)9y?{C\e/r䤔A? &W{na0{~+nL&SOk&- ~9zi[0/!Pj= s_hTAP/׭ʗߊe?[eG=/68 c t]ίsΕ3@N IDAT7o}piyɺ>{05[֕ynkl~ =~<$~K^C;{8qWԘ/rȡ>Ï.@xlkn? ; [ahJ;9㮗s^\hrk3cجr1y{A!YEJ)lL..b2gVj"+=]28uߺ=]x7NjLg.[^lmK>~[3˧?;GG\WENC"YǗ_ϛ.{$]} ۫/{;f>367O>)Bk"Eޠi3/ڄ̽%n]ҳ1w`Z * @JYI" ӴV5ƪFf/ JL >mꥃLM'AW,-tCboW4o&=K4F%i[g/:6O&Vf= ;uFk5S `};o>0LSxR5Os$`BV6q!DhRY@zFu쑭T]db:ͰU~F"PNVB)6#Je[2g47]vˎ:-`LIƜ&8E L(cZ%?U}>1kNnɣ\r.MMXŽs|bDž,]qϛqG}$CP083cJ>:#!--Y.et*_T(liXҒq[+t\lw4Ø;YE}h5[Lib7IyR}cT&1S81̚'3hҰY3pԵM2y庽Fa] Ro3 MxBn'@Ԍ>N?E fBhT}r(mr3G6UUZf2w7Қw-*PnqeAak/fOĤF]zLqꝆ6^Q)2c*V=}Oup}H,NkMj%~ʻ s? Bu駵yJIٕ7Z601!g,x J$RS|oS)q|$]< ۙT&_3zc J􂇘Ye*1 KYE2,p :m|x@5\ nL1Hu2arF+ -[%;ȭ+Xx'B6ޞ8#kF>QH^xvhx_]`V7,K^\04MsK@ +Ga24fcE]sƔ^gv;7f7@zy\mWXuN8!:a,*Y9C2|@\<$OScZna]-Ba[e%ac̝0D%"oo}+^Xn{ cRTIZ@k! |_̎B4hIJ}#YYCRKE_0 VSSu:X,n_ lU> Bէh3 ꮪ0frF3 *ؐ?Q I9e ZRLJƜKkR 80ıJ܈ 8%kt&]^(8@'(+:xYֻj-; q/<5x4M$j=KjPuƔ^0 T} blgr~BB5d)!fso-I8=G?g59KI w% lSW({'d5&!fŊ6Un.}B`ӓU{ebndns&Ogr[` v$_5kp!I/^m0P:Ҹv2`au}{Wi/`U_gUv_1%iڽWR6j Jri<$RxEVFUFKx2\ie?׼_R8EU٤< ;ۃ;Cl yLٞIL/N uAPP7֏/N)?ߛSx>x<`{45UT NS}Ջ~~l4m`$mL,mЮY @Iިގں6KtKoJҩPz>Z?c<~`e}pDȿ}YW*_% #T^Ցkabih0 T[Q^׵j) q%yvɗ 3 HNo8u9m=V4[N\՘VS;Ț Fk8wOTԌ K~mv/1F^J(iOѵ ߞn&ɝz WAUwu?U5*tJ{O~FY?Fsdhw ^*՟~Q1]3726ի IA~mn<[)&sZācyk)arL-6i#i|V?J]{ $%ᐂVz(PpS'Ɗ~t |`6@Q)H^cwN0iuEsMI"'D6m?^=R \e.]͞aapY}ZF6l<|E*fz|ՃLWO"?wي8JFzv82#ܛ{- wiK>{SJkjvZ'x/HR='|̰p¹,N&>)-p̕{of?)>\/s 6+)怢Ho>t^+w҇FKq{?JΣ-1_!d> D ' jl齤-htV)QТj15r)Gu,!ڹœbY 93RO;utҞA[ ?'&1E# qA\P(>G$uA<5۸R ]|0 d051L/@-1 ?i$ScRo$S0q(O}9ouiP<\~stxkEKꌆ6^1?EEBѪ?Ǩ[Y >q8)?)&w:y#CP=j`z?*#]~.m"  oI?l0lzr'Uj֎ KΧ:1%1,Ԋ֥8Ȧ(w^jW O o'1f(j=+&T7^ǹ|6?%E2/݌oǩ'xC^nB ״NBPJjh,]bSG r<rOTӋ9SWk"7TSj ߽}e2 l#\d8gգטt`;yW )W--,|Kv|0lW^ǾM{Ӭ֛O5>*Zђ` }&h:Ch]a •f9 y~sTYKOc)l;U1Q֞ۖ#O:[Hmzs`4\)+E"<^>n+],{`?W&NڼY,y/әje,+k'O<YxfQm#/]mBQS?G"Pl・XT}MJ.Mx /H ^ iaJTAxSo\ΫHt $_p-ՏG r<'prU?e^{w({q-Ɓ6>eK.hS)uVV"Y p^<I?'20= ݼZqc~~g.+Moz/9TkVRֆcO\Ks(v{ ٕKeֈ]Ğ:t s%ؒm"5)OFݽ2*T$[WTسN\K=0-{t6}Ι C8ዢ-:swCu?Z|!?Yzsߚs̟/߻Qf)Z[5`kb/HS7EMYUGn܏wNᆬv)d_*ZRwx!~Ţ/3~j ",}⊦eW xM9}4?(>yC߶`Gz:O%寐c '7=ɯn/3˺gF J惞cPA?̋idad?˽ v8%JbmCxO| )I|^ˈϾ^'9{ߐ? {x8J2)7EN:Cu?%Yo?8kñbqwT][O~;q<O>4&M\eɍ7Zɣ[9O޳B>^齷 zSl,p<>+i?Osb^l^6j{T 0M/!1e?ƴա:2|ʕc i/Wxeկ ' }'ϧkkލZn;q^ok/_gxqxĬ*> YgVKn,2QNdZe(µJnb|eK~hε)W)h*1׵W甴)F#x7mniٜm6/~NjҦGFKM? RpzXAu7.YK:_1e`D!Z UkΠ;#.N^({]!p̹I>GJ=DXx(S?go(:;1'3p:Fs0opA1ӦN+)s7sûiS+rߠZ-'_>4GYŮjT=rP=>(,D\rz=^J=& gU^P-W:ؙ^LPa$Sf14dv_e]jꃛ˄<"wXYYZP @yG-Ͼy٫7aLwLW ̇ . mm~+6tW5N2WQ&o.RRaT>sYD~BӨ$G. ]gfođ/ λ 27ɨrã5H+]&x~yhB5!$ƢK nD,c%{3)O%zPGO6)=pwO}_ͧ~:Ey|T—uZ(\s=GbNJ9~6>aJO~x%4ñUPCU Ӌكus?j8Ȃ"G }qCck><G_7$: 09o+n X:b4{{RF>ҹ-"߼1 1{ӴVUg+Ԑn|˓ 6c'oXz«_P=4`0> UPNbb< j9l욹הAKE{9xo}[ BU L/aua0 BU rj05^L0 `A!* 0׏dz1ap2!BR4#Y:{p~< jCz1;@6`A!:^r *ۭ%3  B!TqOT+5P}R@N T'=0on[]*#+Kc "Eǡs3[pӮ;$Thy؜]*!QRh>S?G"Pl・^n`"YYm,aLnYR~5$@"% 6zO%*~"#L/jT[4 h},,ߵ]LfҔ|H3Ͽy*Lrn M`IǢc=V{ gVb p;g6 U3P*cڥ<9ivE:P_3}UkqqwEMYUGn܏wNᆬ6ܷ\h6_qGnj&5K~ Eˎ[CM}N'0& ̾JU!* J5r5:&ԛ=||S.;R!I<~6S`P6:k.ZFB%Ϸnw#Cu×^rLrE;M0]loQ2џOk(wV1"<; BuO[{>](t "jP̺:6`ԙ1o5}Ǚ;1w4#"w'xYZM dbuR$*kWaL/9>Y7)ʎ4KL쬕jj@SmB4KY_i[f lLE~TX?RanU2( &{PyX v*XDC8 H;@ig.vɛItsMZԴSIr~]څw_LŇi'un1ͬEzvtUd2۰nJMY1p֎o~RoY%RұTKXȨ9Ra*/L/8)b6h FeLuIkBv*|=EJb$ݠdIpgȁӚfhc; kCQ^y᣸߅ &//Էo)9XY/>/hwy* |Z5iI!1&iW0vNURkƝbHttVޥWY*B `dhI`D<#δ`%+%2Tgx{t::(B\֫'^FOm92E{u5|R/>U`л w#NcMbG-/7^*ggāEwjRzD ;6R*.ڶ hмP]\붃[9o&AMj /ő ɴBݢɻ2(wٮ;2XbHJw]e>FA!G-ظD+AV3o8޿hs5qOֈ}tzsN+QcFQFf?5Y)q[р6R&+?jh _|g4㭮\!ѹ}_}?ZTe)3|;D\ݷ㿚uG+\'hB0$ Ū? J\o2sGq\99v:ˉ4j,^]‡٢T]kYPH//bv,|͇T ?|Q!&mbiXV;ftd#foJ[%;ȭ+Xx'B6ޞ8}>Vy|TKpm @7MWkF>QH^xMxb/yf ?҅W;!T+1|&nIi3iÀ~5shY/! l߈ewK|tK>zu!TozFgOXh$]=Jǚn2ey];QkɩiU4% 8+$N#jommwԂ9r*e^=ӵ]΢'$k왝*Cye䢀`)izEU_z)_u\.@@-F{yVlSsRf9p$ž Cn_Hpթgdc!1]҉MRRWm4y7h&j@_{ahF,a΢xOj|3AP؟v+?#rf&YaRʇvDK`%nz3ua)`nS2%*1%B!J ժDλHO=}z51}Ћ>MNaW)J DeƩ:BA&oϣ$}KT|v8/k ZK7={ ice c޳籱vϕi^?@~sIXbx6ќ\vI~7&1!Q+P<"v1и eE%(e!=i3IP{Z-! Z-?'=[_)Y48-sd˽_vhO87<^Vd\BB9_agVÓ2]@lн \Hɦ{K #:͍'x\ܖRJWV&BSP)Ƞ^<A+n@`P5f/ ]vu-ҥ^ϼ 2h:0knHӽvW[J&@.V@jQGO|9VƊ~9s ֈ$}-0'Ds NeW z7fi^ROjk4#ub,Iٌc3&y Uehޓr^#@˧P1pi4diHm]k!|(nsS@HLTW0^O%3 .!C!ѯ԰bMh|RnΖ 푖cG gڙfGYv5 ]IovSH7%M\o jr^ %ۧ MOb{ugڔJg@C6\#zRa}~I4u~SDtSTb!.osbje!NPzicob"|t8 0Q h∅CjL/խ2k0 BWj]8 #c@NoaWOf|jnp4#"}؞[NQm6 Yû)&- E33g\3j{TQ|m7WpܬYN, M-UvOpƷ߶9q0rt1Wc ?Rȴ& j- 0!P];yzb62W߄%cγB'7߻os`T*{~AsV8jgrݗcj]~*|ݬ$ BSʼ4It5,Rf4 J ɩ&P-`K7O”5R(-NTC;*Y|aQM3td3%,?-*Ntqy^D7k{=ih1?X׫Izh ; K^qc{*ǒVO҇ 6JWL%P&UC ->:ETgg߂{a}s˫![?<:cym%5ݵj `L:0ռn |g ǖa~> ;!PM*I$L`u%jxu50ճ=(H'u) $̫= _8ekԕ, hf5XUnzhio1p2Ua' W>EC(9Wzt49;Y;?M##Dz0 .g O#z]%\*I׸a}Y~W Jn3>gώ})D2fpo}4~ GuJxOh9iG%Zy>M9 ?V|h`ZNu/R?#JSg{ +6_gTZPeF!0ftN5+Cl+<+b м*R*sAs=D0dj֖Ѕ%9>bb-B0}mT:.m?{Ȓ.P™>\o2<}"Vy`^i(:=y3I]ι&QNf/;P=n+_%]xm$_|vrZZ$^z0'|kȏ~͵!\6VXp*#SUzЖ #BY `::2L2v2l21Y$2I.;Khk&n>TNjդQ SLNuWy/jhY#S1$g޻ʱs@YN5~!/޼Q\|E/_Gﳻg 0><~Rߎÿce(..ף}U6~jvoh\3AծW5NrettVޥWY*2-, IDATB!d9*-5F(g%ͣx.ˇZHM.P寐`_lLWtE ͺVw]XQ#tT_vVx o|e䢥~4Ɋ={ks^]އ4Yo{.¤D4{}ʌ&)W-~oݔG+\'hB!T [f[xw3fB[.(\;lg+dY.-.IiRd~[߈? g|oi~iW#e*JE2,p :m|x@5\ nL1Hu2ar++EymcMA9bi@Zܺb鈅w j3jWV[㢭muwx.Zkh_]`V7,bU/B!}+UR. =ȜM鷻ҞMV 6vkJ D%"|鷾{n-^VܴߴOIQ=&UUNwO\|MwxiЈeF,S^[K׫!B05wZB!B`B!Bu%d%W B!P30!B: B!BB!p=8Jۋ@UQ[da!'ado,EZce~A6 .,sȲ=ol{SxI7~mސruߒL!2taw!rw'X$?Sb-S1; 0ayuPZ]q5^ݭk \R].ᕙۢ*˱4B!xV3 ThW`i WWFMұBآ9{-ivTx1RJ>]l5t'?KDG>⯱:ލZn'{k$ G̊ZE@?m~lp+w-x䊨A1~zXp*մ@&*Q'E22vF!GgL/<#n+ةsK8 H;@ig.vɛID\#v U" }wzWNگKXnI?0-H\ATՎ!R * NEթh*S,F!ayLUmΛ kC?[}pSP#wGd9b|>%}Wo[™?&xkƝd ;鮭KT!jL"?@&KK.Syp&8eD @tBۆup3}ܻ'iWOB0e[CK>"<%U>Jzvf=+C΁\TءE!jŒQdN*<[=7/+no~ʧǤ*j"'.;@ k4hIJ}#Y)/-Y?{Fu۾kQ-{-^FSmcPey?B!GUjU711*E^p~U*CGB/7Q*'Wr#* B!TC[ *?TrePa$,B∉5aG,b0`Ab)\QBFRi+p9NR4qĮL/6TqXz)tA0\M,!5Rd 廃B D1'*8>\lsr\BB9VK/&'owAaʙ^L<Sfz|'u9Fڂ\Wm35\A)΁T@ŗ4=# X}EU_Lz |$>XKrw Kf)(:vy/s:c_ӮUD(C&/bTk䨶.5iͽ}Uۿ/$M{^|P-Kք oAbH<}ehͰļS TمUPTnj)5w0 =#p4rVsz.]Rû6M*YiLp W.M|"^C\oܻSfĝu!ˬKAX]}@PdCb]2XZ?SSjjE/)9V)԰@QyM(jY"*Q-T 8k9Fx3Nƚ.:X33:S+-DTJfH9NTrTFʨ c%b p;g6 U3Pjዢ-:swCu?Z|!Ow-:mTOtnՀ凮݋#g”buVSg{ ̷ B=vFځ5[No.};_j$?{fOPA*"BDh]uխVq=:ZVUTp+*{g}\!$!Ni=Rzt'2rKE\kq,n gZ~`DҸblIbi=R3 MTcEPk׎w`֬nשl9UC4;?ZzmF9[Щ [?Oi낲. B7 @J0J$*KzeF  01Go.=8k4jFfCAV/U2sT ϸ*s;@4miPxFZsEonTs6F۳ߕač}ɥ)D/Ѝew"o|GLRPQtEg'*t~6O\)7%RZ:ZLӅrjK_*O.Ѳ۬賏ywj~6I TڹjkϒE~/H&P`! ޭ2dCٸ'{WۚaYzLac!峳\ͷ!R/G1ռers,ri4Tks:&PgDԸ-PXUQUQdZ<0R޹9.kwls@Vovо>-ΕP-]n>K U[ ]k͢Mt@0.yc ,%n {Rڏ@ xq;8 v ;32/>0؂8Y /QQaAl5dz0/j4SfóBaJk:A(wv*\QMX֯X,DT\!'YIqs[q0,vB!8@Z`4_ִC*-qNT"cN/gBu"mR;w^E0~bRrʻﴽGDŽK3,=Uߺ)0SPrфA]!v͠zVP]/iUKgw]"w|μ"FH>2 ٵgvYH"!_ 92U(ơvA9p:߇g K"ӿZъm-(ExLag毒d` sJB!BJB3|'mi L'-Lb2ق]%0ո? &_*RHlW%E%E[8wR0[ȣ"U&]o4xʅCOK2E%Mfr ;CDV1GxQQ|7C 8Ѓ҃K&b4(sQi2Cyd%ح9傳~ `@ߐ̤8[FS| sjog\99mRYY'S] 3U#ZD*J)T+D951Ջ8aj.U(QvP2F1"`A^ċq KSHL+%ȢIaLa*wEJt.jDS @ LfW5cCٌF' a2LR/uP(،7$`*@ LkΕh*RZEH(LK:*,c.^a@ γ"-UFyoH+aTeL_~/2γ&^aA 0 |>g"dJ HcHb K@ DUORFAT^j>y`@ I9TbtD~0B)^L0~ m @ 0)te2}1Yy @ E!0tnn6W@  @ DCO %eL婀K K -J6Jt2Hv>zt 0z=ot 16+ZLU+B hwG[P ^ԣd1F,7Гeaz3@ 㠿 &J5.кE k9 `od~nF8ߞ ܰC?/֊VTj0 jӞ׵ȒON>˺K]Z%u𩧒ezf6@8O/Њɪ=jzQ2Rr-1vd5AY\2ߑE[{'ڙBM_4U_ع]-ǵmѸ ێ۸Q/e6@0&^jiZʻ2yϵh8ïʥcӹ#;y}e%ޕa{oZ:k&nn?\M2y{֪WAsg&]Y?1<;te|,"`)?-\\܊i3fDتa:E*kPq^fFߖk$]G [1}bwc>Kl$;&LP b\hq 7m5l@uu9g*ä9:]^X}yW~ۃtZz7Ҿ|iW_=<>̬7г1KDN3* gwF0_Vkcgy3K& by6b*8JSrl|iT9 i֔@ CJ?^[i0 c3z1e]h0nڵ45u@YeM[y]W}o'4V hhF+z|Mo0qQm],WS|h#ŒN[y19kQ9mF'=-ݚEJSMĘ]/{ׯZ=rw3Ϧj^`arԁ*)(q/Q@ @g1QKQsꅠz5]ȘQCwg M6-4V3 IDATXobKkgtNt_d [2!GF BI3/loYz >[,9VѮ5_߹;{Ruu$**`VG/rh;)3@ L v, VBTճO~>ucx*Jk\ SE:^_U]鹍ްϕRX?5q"|ԐFjtA-F6ew12&ֿ! kԦ^O~LTʦ3rN%)[Da$ ^zUq>G~PUvim_S8n֕:_ZÐ Eɸپ W8YSfZ@ MHGZ(Q6=1E=3Bfƴ0h2 S/͙Qj Ѿso7ϙ@mfgV}9W, _<9q~`zhi믧^deGRP-]n>K(?Uk"Ѧ#/>^l@-9,y֛tD&zsm۴)eOZTSg/=} M. g9@ @=ژE֫ri @}ضU/6TQxNJ?1l9fw_#:E%\b/t2y2lgO +`57bZ 2SPtv3*-y|fșũ>l_>%)iFO t~7ly(V>:_#uHԹPn9XtvU);~G7뼍l/@ .预hj\1-_X̀~Bcslɵ0Z ɼոsk<VO: ;4)ܐBf^\OwMzQa(##"KӥKĦ.U`qk؞WRER='@ v|jk( cjꅠFk:?FP-Qdh%@ CR!BطcLSX2> @ 0 "%+^ a& ;8@ ؘz!1%LB02A@ Qc@@ @A aBfA"C j:ZQF @Tb+?0&Q*~٣Y~mElWK8H @JhJN|ck*jP~;*YnMuS2Duf^ Q"KQݢ?OݢkA@ TH &Fd5,KmDut! jҤ1EI"QRnϓz  @ !ǹȱO%~;46^eOyWzW eFy ڴM~TU$[4}S7W77OhQPlD;Q{QS/S/cU9uz!Yç/#A5?ՄX쉺byh $}cQN 7a\R]o_7M4 #tmkыزq\\۰[zR_f@ u^yQQmf򢢨ȿzk~%|2 bi' n_'Z$`xW5v\sUaj$.xn՘.-\Z}OV.L/q :bd'o77Ww޳S=`$\ȩ$]G V`lݘϥ4e6hR/Fz!0vCP  h !'8pG|/5}n{{rqyƥCmc_uewPqY?\}; /(]uu9o{{j٤?nG%=C͙MmEYGnC ]C(6i-60BL&&R,Z-.:W(2-7~L=RkmԠ'H @azt6+afޝMCzްOs JyC.vtyצ5&j0ܰC?\?1LeUY/c ~ӄ0fA2i͙Qj Ѿso7Яl'o1O"p#jʙF+N;A6?e+>+Io0%kY Kx6kK~3ɠԵǩ} _*{ :YJ!sY^BTjP/aZQ! S2hvaީRƘQFZ攍fc^O~LVv5Z@ksPIg1+ҧ^]v=~?$u߿w3VZN{jƈav]n)r/iOΧː3qZv˱mX7b4 `†m:6&cJ_-*Et3Kי:a BE:PBkXO@$Vz Kw1&\T#DKTm zQ_G K5E[8wz#aƘn-9 vwJ:^ǟ6uWӥKĦ.mk؞WR7wc> 4 R/AР^k(ZO6Q:|jzAT9+TFRDY!3E_-uz1EEy;o/ԩ. 轈@TH 0HH:a4 Bd Deƌ^0uzqԔWxyf3+{m&uEK8}צa2kuK kW;W_M]ꔉ>ꅖ` tA6 K ?)Pz!ЩaLvEJ X, #bE6Bɘц- ʥg7}/s==5-B^)=15urS2 MLJ^ppeéwn^T!L3U::(PB@ B:ꘆ)z!i "4iczL Ղi\^L]ьR^ ?( 0M@jv^k{7F\Rc?C4hHNKZze+ Aa,pBV*) &0FP(t.Ş^DA]^^=&ĒPLB @ ܺ>-kPR~%8]JؿT)82LL;& ^r^LJXʯ0`0p%^ ~$`QZ&Xy/CQ$J%SBAQUR̔qAb'j)Ϋa1P2\C@0APLK?&e\e+Y)=xT : }#r \NJJ0;s,Em:T֑GL$ߘ߿Ёg):X9ftqAMv\&YA; h@W18"T[m:]RYϾQ r$[wO3-KMMJڏԋ 5NÀP*ӧcFP/ @%,s'm垫". HɏXtXRH݊K6WY9H_^`f38םg,s< 1m]W%t6 @|לQW@2us_)SL}xbe|Z/Er*^='%?d۵ϛ&bi]y8rkB#ա^ߧT P^ k!0e$8A :^OmEf$7#j u2 ~З/I8 WtJ.Z?%L *i)Qgz6J[yg}xX@2,30oa:'>+;* RpxuC d@QYJ}P#ϳi 5ST. S+1z0+Âwy8 ^Ԡd$wէrl:h:xWeT.|wqǖ]'c~ʫ?Oڈ.HMM%=TF[wn=d'_OR=>:9kTҙ)5{WF/ڿuk;M!3, VV]V!Jyґ-ki0 ZRq^fW9ui0;=RX%3 YҼ1;`FZtT 6OZ]nʜa&}sK/?Aҥ@'PVKHjIAe;%_}],iq7w3 ~SZx3?Y/)>m&GISFɲ!hRM1}L1mV5S(gJPju>c&^0ED9W*ZF%Z<0.v㈯Y~fmcOٷ?9[=;t꘩݃j+;2+ DŽ:qoWw,T*J8vOoe$+]?IȔպIps`aԄn%6:6͹&3gwF"_CTյ˪J_xUHJR`LQp=rM+tv-sz>ɓP.P1SUC !%rmS85XX 7en~@"+!;sr)c:[!5cUd AE擋d꯱ԬZ=Fv(s ?jםc+䞷k/ 0c]SN0U n5kˏWFsj*oWs-Y:L__ϞTT r%~jI Uʗ(Ԍ'=-ݚc~X[Pq~X1zXÐ9N]ĝԓMKk%UPFwhUL{c /}{6ԯa3a5 *0WVoMWGGWfξUNmԕ0Z ӣwQ`fޝM+|}ǧos֙oϻtVѠ5GtoV=rR kڛOb돘,Dpضej+`e&|ėDeS|̊g _JJLşN4XU*;\3 YNzX B RQFS# A 0)teUuU\%҅h2Fc5aܡk63X}k+:B'ϲ9/TɦȺ} kT';J"s@QP, L ef|T4%.^) 7&Y8,0uX2#t RGXچ6ŮMty4R/%^$6|fyHG2lbV/lʬ"%oD(!*,o4Z"`Doc^-y/clh[']{Q|)?ZuK'LD ?:|6"O8/;;"fu[*grw,3l`.䂴}+iDkuKŒz#acmo*QR (W?U:ݔ~ZClF^ VDybwI&J|뷱Z25ƚmn6 ֣w6U[0~bRrʻﴽG~.Gf+HV'^;&oAE~߾揈s@~חK>{Jѳ׀lkoߗOnئ?t&(NPZ: ??q~-y|f(%UwO 'jJ v˱mX7b4 `†m2mDu1_گM,Jf8 IDAT5@ R>nDe :HyqNߨ钅 gnPOz5ްm]kA>4õ¿,r9x+K_Q?xԵ To]%bS܍5*s`.Z=kݿ!>vn-0ǍMiRqBDMxHHcryg؉4ICeHu(uK-d R/aj@T xNI6&a_ȡ|se,]:E^dh2ΟfHnX]m.@(QP2&c*^k[ !b{4H 4̭_UdOE1$Ή$.sqKqS7?Wnr;ݳ\uՄPa_m.j]/g:\E[:5wq-0, ŀ!c<mEvT\NJ}Ǿ!ٶց|rP8y#&v B JG`.ZKcN%Khf 'Q$q.uIARغKwb)xA \ n/ٽےgZJU-gL!Kul)/ܣwM؅9̎qGsd@lǩ;8-J~Se(J.|{voQ知^ES=X#7'wĐQy)O1F}"G&iI3s5M>O:Yi(m_ؖ]l6 H 5TLé8))} -MPX_Du?Dˏ3 ?d*Szn0F%`c(^m,2Hyi$3 irsx!Fm IlyYnφ 1SJ[rRɂ]4£-?l6DNZ|߂@3WB)mJS-Oʨeoa ]}i~:ruJl9~Y͜x=}y@)M-E\3r=S1w! oN{ 6%]$!7J$^ׯ0!oh:sw4jPT@A*d;JNNG /^Sapph=M"ZͰ|T4Rgaꅠ5LcHQ7WNX:p>fE_'NB5 k)ŀJpZNd_߻z1,k#Z4j?j7ǜH( $N]u-A¢>w^ypXKNE:tİY4<,P}ͳv(ƽYm@m>~c䘶dGȴ&_WZȒJm5%ԳjĔlA Ƽ" g%/gSq1-oݘ0U}%KRq #OQ a ev)]Ҙ+KTHWILu1 {PDܧL!uzvbX8id \H,Ω 䥏|#@?-qBDꥂoNa# h}t7B"KG^ˑ /G9&G5MvfR'[:[PP`@#:m|Hv?Щߤߏ=˜A/h|Daou7 ߞ^>мKoCDAmXvuXɳoE9b\9ty+[7'w(ܰ@bpIf#:9.kAe(Mu :bDBwSK"dN瀠@=K:1F0D"DJ#]x1{xTW ϺBtT(մSY~͹EVkS0DM7w:r.Qs%LLs33[Efs>&W`kfb}/8yRO+t+/ʗa2NEn,ˍc'dd L£3{ӧ Uh½FRXT - tͣZo;}q4{~Q:݄ 7Rscjk)}{}tSNB3M2 &X|)Гe FKJkZCkry3>}N[t.E9EJ?|bJc3 7Sk{KO}' V: dK^?}%K.$onwn]ٻɗBEn;c>?_}ʞd#:Ym"!g\^v[6y%Sd?68sӒ$OGo: ho~\uW܏3=oqU=D@looOuK;&Z]m㩭H c^uh-+]?2ë@.˞Fof6$)e wض\XQiWGg ћ3=i}S !C j4$kw{s)Y 1V!"ε E e%kFm?nf/"pg`Q0}=0m]ߵqIn<͋VWeTy}WQ>6ðb8m$bv%Gn= wqRN,h! ?y>y"P%sm\AY"ż{ NpSWA6"[c1vnbebRbT֎֭ء*L* V / I|L8}TLj1 R/ [fŠ my3tG4X-.^?lazo{uHֵ2}9ums1f/{4;@Zz1kX{<Șp;̷m܁K961y;BmS{˓gG0!hNmsϧK]=/藗e.7 <-\aĊcC&Sc4vƛ |͌#<X1͕:vhƏǟ/hAcښcve+2:T^vpA}o3}RʦplL Qh+SQœ0֮3ꗜK[N;KB-p)V]RuweX7A nمLI8v7[24ޕa-&Ī姆z;D)qị;:V^]OyBFL pAK7z,ez1}W`8={ #ʺ_Vi+Έ|C)zve+\M0QAyAi[w)Ty mARI .-54N,Bu u-Z,T. +V]-=$-L2)_i/QujV-2[:8uyKp\yUVP{s0l J"=`Ջw',]:E^dh @|{*X0g;nj /rw*d4)Rwà<@ؕI;{oY~AYsm΅/Dg4;zŮ`2ۚ!HpVA™C " 2Ae!4;I`CqXѻ-pXAaP0"5$<ӱk)\CE=-RO;le~zD[Wg{AGAL{se/S_wX|˳ JMumtfG oUыk]ES~Ȍ:=aguӪ-{'hvFܕ?Aw_>& Q62/a#mZil[ ū,o0s>ɧKmFI/1)UnLMJr9HVwܳrj/Kh2b#t4}y#s#{͛&rl+0M k쌗PBY"Ny&Vz.t'A:*)sԮ>KimV)x"fְ]Rj‡M.@Gs%}=1g&~󫻣%FNp\gkOE*C9ZmڏZ8o ::jn&eS, i=l:UG}W71aL{l)>.zb~^푽5Yyx"y61tnr Pw0fƩEazТGݎ/} ӾHg+/_GԱ)wgȈ!kыra\k6 ێ۸sYQ/×4ZG498c;G4茾WUsC]iP 3*4V?&ˣz,M9PdGwRm+i.GHſ X,S5* ,G+}h[OX/:,I 7yd3ne")H [Qâ@q\BKq RX0?b@_8"nOwZLO%}׭ 翾l‰ޖ$_%Nq't0>k&ͩU7nAj$~Ֆ44YG߃A O?Gpw_c'7KJ|s_Zk祝P:Yu@xw -7|EZ ծ{v'o2ąVFAͩ!xkQ[X.7Od-l|߭}H%kO]E0 YZ%-n2NAuj _jRӖqaBmU/`ڵ/.[R!C>O\)nC&R?" 萬)?dV$& BX7&yɘ ?X9"y:,oY<+6:CLtJLtJ~Ŀ6ǔ,_yyH*Jv|edl=S {u"3ѕ+c]l>#$ud--j=bW:!2N#p[mIg;qmfL.|yd_QFm M3GHK?ɗfϮW-lPpr@\vrS_̳y ~@|ݔA.tNW1QPGsj}>9t O*e} y9ي%K%y\PgSGEVjj)7v}/iOT pǟErQN7+9|K?JdG/hz\&%Io r\|u>/ &k/P]jͰRc.>#l etooOg c4"Xac^г^[3[Z2C DZyp;,!=U?j١ߖ ڔ&}S)^dK>o/NO^/.R\k}N@iҮiɍAᆯ];`Ziu>znj~dV%3ω儤倌-_o'{Ci'bk[JO&!K1u}-EfV~(B^@۔Ne"N)Niϕ \w*ː3w|:iK`a>Vo+QI3ݘ8.z,j19:Μ#/%}F_O{=P#=4 ϙ{%^X wl|k+QC䂽&Pշ>-;iaԜ&bڵK%m-Q7K +-,41Xn|I.F\^ǴtK+UL'[yKejߡ":U&6iT[7rQlmJϊUf2&Xj!ضYpS^ԍJt o(*hD cD:D{`ϙC<2n1F9Ot+e (ksi:0˓/ty(VcKpc-V_9z'p(g@ԢkD֝*(?> gd szO^OD\bՓAm#E؁=@{pġOS^|Vr[\H*^ -P7/|(f5b4ԭ'tp K%BGsV'sqKe%ra܂ WE0omͫͅ[VIOTXyaH=A|<{®6^~G-o eFN޽Vʳd9xiNo]xYDcKyK[jNmYXc\lu}/N|4o+':E>/4/0m|9rDөK.~;/(IYmd|▂Nlm9V0yʧMwF{ZoO>ÝG!4Æ+Êw|y ] T50BWlVz'X+J qh-Cb{ #T ="wO%Ɂ  ߅nx+[Y>DU[a%:BBכS!j䨲9SK4dǙ!g ıC5LC-s[Z?OFlᬬwNxkU`1hꯧ \8  \Hbb_W 9O.`0FoN0 PtǞtǞn~?{Q .FF'_0L `0^ ʏOItCf|_cPF-[uChGѣų{g0xT醤GOvޗ\8XDžmfQ&>ϾFsp.5=&kvkzDyK7miBT?a)J?O*}c$)g5"̧Z?iݏYv,1Ehq~'<Ԝ9 P͡+vx̊]S--9I554X!8uscQ`0 ƍ Pm o9dƸgƬ`0i:^lK{Z{ `Jc |W] kLK] kL6,)? %-:%-0f/80^iKr˜_<7V x^OI2{3o]3RҢ=eM d}3hߢ|*v,q2{N˜xͶ__c` R?_k* N4q^1o-q=(VB1Hrlql/ {C1|;J$rɐx N!`0 +h0u+9 d!l/Hɇѡ3Jt2j*y>KEtZSF ~u/`0?}4q*ˉdLOa|٫ P XͬüT]mp ~`0  4 0{aoK9 jQK5?++2[kr6A߄ZLif>L[j z#þky`0 .t^Ar0Zi $ƠKlhҼ,'+El| L(X}F J7o$"1kT+Ѭ@(8>PXZ~] 6{ @HkHY") ګ< bIM֪֨499F" Op_;1 €[؅-AV0Ʌ I.c Pa#i^@/9"{2@5%GO{XZ,%!a8 J_`mUoBP6WBEi_)u!yp[4:^^vR1߶P%@h_WݬpkS1 h/zd[4R>^ m:Q,W `)(u9NUє?*ūmG oBv5RȤ``T(FRwOj_4}V c^ /z;3;_~X9 #g:{S% n"]><"2<}paTT%qDX6380R>r{`PmŲAAʪgk%Fh'RLT jF30x#ZQ՝#ΈeӤFeU+>)UeR z50l LRt y%qC(y9K0]8DU/V5}1OP`:7ՒT9mQϲ W.$VSsG4P,  q%_ٝ8cJ`T}f)zLuWK!Fi7)pjzA 5Rp=T~1b tzP~-PRQ&q Av);vC%zaV+=KhV+a?Q;@&Z2HD4,T%Mӱ!1ަompzz 0mžISkk=PiFpe|L1B 9ȩ0 QDEq4AJC([Z?)Ivb0 q&@AK0ӐX)\Q3eEz9Fh֍KZR ZTLi@/0 b4 MB#-G}0R]Ց5)|j:\E4V3m 8@N="z{聴c`mUi90yU ~90p.]M[3#VnՍWɛs%4`pK c57OI0\T@MB3M#9.UoQTB{ `| DZؼky7UxF6KaSڵR-:o0YJFvFI~3BQDHfɫ8mG * 1ԲѸD% t3,ݏ?W2iZgXº ۣJ y7g[ĥbE~$ j*ޢG_3 s): ΋Ȧ:F fHRxYcl$:9GP,)Ve,E -QPsʖjM!86I~Q nge^;qE@ %hu?6Xm_}fG>iCg$`&mX~:h~ڰaI[[7 4h/psvY*b_Q3!ٮCЍ\faJdS$%ȓ9B]ͿdBfx&4;ZKl֡"F#/N4A&t)۪\({V*9LJjRe8X'C*>N*-AuRӤP,BUWb2UsfoNB5U`BR 'fTjJPpYYwY PMRx ᙔV)31@[0^\a,LS=SBc¦rؚ3@F2iB|Q?[7ɛ}JQ<  "&i VkHN= h5Zs`uN= )!G(^3HE ԩB#ZTUͪZJL֙GT## HXC[F= m:$ګдPV%? m24$%i ƟII?T`t0(wQJ%P68Vг`f/&5ax^s 3e*T͞tMk.F@9N&9,EҐ/VlWG8j`;ǰ{A1 V]k2X[UR^vJ9d (+/]zUkf( `d/^0^RҢф~Ks)TzUa3@A0BpB{Aa^ae `\̠8 z(Xj0@(ɏ[XhSV8_w%>hћ nds$<꒗?k?AB`0 ; ب.zPI4u%C^~{c166A{I?$yø6#׺%2ISC[]`g7L$XtE)oO1TTV8_O+Og `0P_c| &j /paƠ|3_=^x6<Ei!r-/%W{qYr˧ `\,2uGew᫿.1Cd{e` IqALP&>Z(u ,0L#'G&C4:-}8< 4txvJ( kcMyFGYA@ӱ y\;e #jJHBu>Jw l1ݨn͌ٚEtr⑶5Ae `%S ,2/S4paU0BA +H.%VVӶEi͹eHyG'L;ý]""81 `Wۋ4C,`ZޠT`Ԇ|m$Kl EOE tTͩ%?V1S[qo;& նiq BQѬɴeH]ދ\$u0P NHp?]GhU2HE7D ^d5I%0 $JTMLVv!X`077oѣ2džñ-z{/@g6: _*om ^m VNd kֆTJ}`6eM@TfXUѫDNvl(t(F39x`$xG^{bЪTND+kږJuGX0W5#?<۬:f4φ֧ ~tz@Ns䮏6ϻ6T0*ZD hV#VS~oPhB2`>a,(1>uOr9[C)$vl$?rn Մm4p^W>u4dǵf~:Sc '/c+>xKD>|gJ-3{]K{M9/>E~3ia7a^Kal Xⓔ4C1vً40Cp`.8,2{1 > mU#eX UPO"j=9-^[k3B*;tP>c,Gq+"蚛[MlϿ{;$7͗"yC(2aKn}wDoH7^}lM7w!ծb _o lt/q^u+ W!LAxp:ƈFl/ǡL*u5ACYY5U褦cZ $ӖN2{p$VNU#ZUs-[3hN!A +[kkORkNow|e:*˨+>AFSzg%C烂e[/{ e )=s)C5yJ@~6$5Wv}kaQ+f퟼l;Rf]3ƗeϩWRcGW-9hu1By bћڮD v_SѠb/zP(휱Jάn,eLo9Yd ^RyYeI7?5dLRtwv-ܼ+H\ IDATcVd쟺4;#=0K!|SǛKWFA{F cF=͡BY[}fjkZ-_Fynƛ)ڳpW޹JJZ(-)   {9~n/`}fl_5yKŐI(?z[00fl2px|Ƨ!۹sm0ـ!\b5&א\b:1Hs (4N;:Ν+}P:mrm7W4qKAӊ['6휌5ݫ)칖c0:g/33avu AjAU{\ʆ&8&oE9Cw5w˲,w>R._:oN9KwLܼf\sH:fPfOW棧 ^:}}{1܂_/;y{'xjg^ )ra+ 9v%cbi^ Ɨ{Axm"؟K<{% ʈR?yL*{caȐ3/xАgMLj 66[}ցYXo/!k?^7{1.)o 珙MҀ}'+U[^ufW$$@Syki˾ae*0'`jAq9EC7`sc0)624cy1E/b& y 8l/a u ,0 c ݙqQ-K) ",6ⶦs!I glq0MW0d1^0F's0 q7t®߶eR{IƳ0o[u [9coև`0AR5~q3)u)jd8jB-c,0 cRJ@_Ұ/&p5_Qz:Ӣ,o}>^z5^a0 a`,`0%B%>s^Tb]xAXCjHg@];|W )L 5x> %'$ƮXs sɰ``,A6eߔ:BsF(RX1AQqxDbTD36TW, W|,F~(i `8>咑À,pA^0V`0V "# t|SuAEyvh#}\I@C L5#N`0m^ g@n7}VL``0b/zb#3<06`%s.[SExv{toH Ǿ)~Wm1*&.KyOQ `0>I47Ki2dKssTu rWC`hL #XnlRLA{yJʩyNzge}/ +YˋW[jOfqIM<~_# I 2Syhs:mTZlwzr\KZR$g Sy۾h74鹋gnX&UK7=}W☞,_<{ekr?nqA1|FRE Q V/f6:'0.*{A/}^IHL6~Ǐ:[7E3{]bdlT8~=;t_6Taԛfa.m6OezÔ.qL]kf^`Ia\)0Ó4φ]_ԗO'|2MH/_[uW ,oݓZkl Ny,ƘyM @ʦ? l <!ޡp{GPdH ^e3Ej1k/! P^ A-ׇbՇb k4 Řr[Gisس@mhЇs^$4v#0+̕sv^շ̃r_Pƫ#6};QX.UlC_Eft+|Ԏ| XÊRS^0_KEϨ73|aX;9wmo?pLGEt5ҧ;tjCﬤ]O^{#|P}`e~s":g._:{nN?ِ ֶ¿9SKпdw=侱ۧ|߫o}K8j:ZJA$3G ixKc@:D,>zS۵k*Ӹ/8/zd~ѣ%s&GKXUd\MnT/>sic VvtRO䛦>Ssƭ_k׮lɟ| |Ie}qG4dz~k׮_rl.7vnK}ַIs}G7ЦeG=҉6/>D7??N[y󗏗n*8Շ.=#4<&}ڦL477D~L;o{linLE~`l/Qof99WyB (}͚=CYϩWޛ#fɔ t)gW94W 5 _QYmM0x7go81@y],7֗O&M(4qՆ+K^}35Q >OcR0PRIIVhY {98 HMSx^J$^5a{`0n ¸FZ@۔NZ"SJEPWR{\YuC +;sGkZ &=Y`Kw$b֚Mny'7k_ygRmcK eBZ=V"\a0ً46 }՟{ɖ3/4Ϥ煤yvdWZq~袯/4sdK=ql`қ'^vlF\}Tw %Kϗ%65} a[Jbq 0+ǁ O,PU/-+0 eZt(Ϫ (\!HX N:]6k}4euJiyD>|NGDKiDN+s~aGkWzP9=vibnma.Kً炒\T9` VZ[O߫V;uѢg63Q1%-5,Zr1E°V;?}* @5|SokI 5O;fcg V=Os/ W}ji7U %U$ff95[ V:y^ַmdtYCY~xR {vWq7 a#Gr2ʮHLT['18?#'+F}yk5yשqP(jB .KQc~L`Y_!;efGKg)g陛׌k.Inj_VrjQ0HMSZ(#Srzm²Z7eW.]8le=߶d],~(8$=qѫko$\s#`0Â!=f_4o!; 1)4}7י"n5a / (+T_ܠ j6 7wD@s6 c%> =iT4xi 4"kQe[o$Ga@{0(d)/nG}AA36AzC  ѝ3-V{4*#gjt- "$%|}jBty޳_J>۳.)0fCteM#Ăx /~ž7>No2/ǝbdFFr@a0쫛Z1H\k3[r+Ő=a0ƣaۘO}yb'hȎa0ލ UPDǦI9h=k/qw6=4Nkkna^F*񔽘f"/\ڦza_c Hx ]_!2Fm v <8.7R7D1_c#{1 JWz,/iL {qϽu{`'32*9 Az01 v +Ơk͆S:Lo8 8 i4^wcblqQG=BdtZQq^ld`J?f8gK"!\H4HapRƥ4g"6~Iez>n֖ ƒ"{<u!!߄ݗͅN{A:gG:L4wGӎ8GbY'wXRziLcR`0ރc!aܩ1v5øGcЍ\{Ax:{ppɓ|Ppˏ.]:֗+{v48nPlDql{zxK?͈g6c_̻jW /7'0 _%pJuԀNm (0̈́i-,[SoVXii΀,iA?F!Tg 8IIC_z]1D^c) ï `0 ˎaql^y'?c34Vwwkܺ? [i~3&Eܑ}Z̰wG~ޚZvΧƴ5\ % Kf+ QaN~Hf.TKxEKWTWt!7].$=[[fQ[S늍bvd0nX IDATø^a0_E&#s^Bp GzƊ2D@PMdD{0,CtM}k3z꽂rsizg'ԩ[{[VEw$HX^ޕsϜ5⿟5&T~_QdvΞ *mמQadw~>``&"go7N"n7lܱ$ffy2k~ܺ =;W,¯:֨[N=~{ͤG{153I4!~GrSP:Iwy"g4Erq  i X0}!A߻d7|nh04`0އ>R:u1D?wѢɍ޽E l?kV3DxQs,ٌ"a 7{@2y6Dc?֮%4&{s@7ٽao^)ӂ0m[~{MQ1QVv99[0uG;u6}ʮ\pb-{mɘi7:oѣ/L/ ʆ?f.\:!nGJ [Duzj{Y*]_ j}Pp7ۋM&ccuME&`x { 0dH[o\ \`xhܚoVCn:kGnO/2rG `;ACv\l%> =i 7ytmLOf.4B7;Մ_O Ͷ*&u$ޕڑBmcH y],]7w cK.9ř`Ơ3\Xh!ɪ^nKF3Ӹq=7o4/Kک25d5R0LI{s3)'becրM\p mUzS3niP!,{P ;vYuя-li}A^.-xA?BS0Hx\efp$DZ:{?(d2ď`|ÐDG*L7ݽ»& 7d; qtQ`W?RT 5EpUtӎf69t*b=9L.QvGI[0WB&cro,0.t*}IsTV@,3/1'0I_ ^a<%{&>Y VӠIJx1"2:l(y{WE /ZƆW@x1"rU6_l/ΣMapi^0zm4nFH`K2l$7p~{aal_ 2:h 8-/Yٵ°_x_` fR-;x!hČ,h0»t{A|f*cf6S7}3L'뱞9fUV*ll/Mү0X`0Fsʴ}?rKnW E㰽 {A l/0 a w,0 {P8i/q  Xøl/I4~A]axYpd^0/a `{q58 ď`>!!CY`,2kBB|BB!^scy )/zeB &dᆲ#nlS3 XbHq"? [F.$X}¢['/J׍ЖP¢">K3¢»(y%adMEDžE/nRFJnaKvS2}mkgm&x5 Au+'ɔO͚JO7P~FWW]Z,Z Q_b?MXst|v^zw.ڞ1͢G|~˅߿L7 {aC8_=YϮ?g/_:{p{k{jZͭm؋0XJ0C]CҳdKsӣy87~,?#(]ӞtnLp$,BFW3*bdጆ`C5 a>JE6甗J4@ΰaZ+~ltQao&̎Y~_mesxdK[>e@CօҐ|17^}lM7w!ծ&=2Sr% "!Zv)1<-IvZd`/ghb[pdp͙lf x 荐LpxOlp8NEjwGX8Ni"tMckAhFb}܁\'SU;Nbh_92NGPq7.+N<"W?)ܫ/y s!@,yB?8Y:H*q*4tNsn"N14 F$coqNz잾HLMf;tr?dݜ" .^~V{־uURDW ;jgE^\z^AO/5B3Ż}rد?׌^߷G9Gay{OO{qmzg%C烂em^~ g]|fφkƆ9Imw@j6qITM%W1}6=#Es: Ck_mя'A d"Npa5Sa^9<ʜ Xc˨;E\h0)/!t:P]Nɀ>c! gP? u 1Lx,K) NU< X@.(6$@!P[pBU, %*+ )fCj3Ud5R$@dšqa]Ӟ\M+$CuY'NTU vJkB #ש! LPP B P dZqbi-2%}Bt-:s` 8!@N`9 6ljH]6q" 1:D5iJN0 w؆(̔R:i4 6NB{Eؐ֬L`#oGQDVstlB+PesO7'(+gpO#{4-{G͢-:Y`^$9eO>xA@JG=&:0U3_վ=djgl&uu>?/-Ȁ;bsKp+L/ȸs{}ۃ \э>K6wM/bֲ5ʭqk7m2XDy}Iֻ>Ry~w/+z4†햭1_:Ki+~ڦҁovBEQmѣnLz{h!_ޥ1Bc˜QާX` 6IȐX GqmLD7VT H%]"(3RQMaN*ɇR ۤ)TLԣ}:p!6UXZ!ҕ#9@!cbEЖPeW6@Ge%[N+6[E>[0;.^w(){/_5$$j1D1h[ĚXEE vlH:G˻)̭w{5SZm-NE߳lIa7kJXE8܁$1ݤ1i. D#rh .擎T1^HdܦNCHY"O 'ҫU&{WҮ3~N޴zrf#??p[ @>yڄ*u$ƍfs-3מ߉8yZs;јtɐtQz(muhr=!] z-#`tBV(]oЫdewCE6e"k1hfi t1T`9* 1UP!3Φiha$hrh<ӄ +$F4(jfhLZbdV5PM*׬#EoqO X@copC!cTMP|8S6\8V 0lp$_}P_C$1ڋ6P yNa'p.X6xx0tUnVfZBKh=g+#8R[Ps2d1Q" ]?vŃbgu;Nr5yC105Xa1pbA@rEt?~eY!FDSB/ NwD~ʍYVND)9f~Vx5ͱgfPv_xutqdWr#;`*ݢz ͣc|xad\=Ow ,]pa>M 4[9Mk Þ>OшO+9uV8`xZ{'J,$]ĕ;b+c+I&qewEjq-un)Dif=Wi$ p="~6\a #`STƨ$"yvdXSݔh0rXizb8FpŒb mӢ4hR~4?٪teuBa'D!N4C0"biVϸ9\+]YE;S qyV{Nxoن:f p!})~t 2Ii~l{*=1M8 t"wVe3G:ۊ2^ +d/Ћ*Cq!q.>jn)ӄ$%ޓ5+ 3/ynݍ/_&^ T'DqyjWh"xl}-O;Όq -x9>ԅO~_Dj/ѕ٬֔*eHp+r[kC; ɝpH/AQ4@v}E3*5CzXqƝi1`>7AO{Ϙ+G`< Lqi\56pkVf)p0!-"d\ 1E6iLNH;gb\) hf*JpqLHX tlnjMG ֍tvJ⇘vv-k+z*$(T_e.ţ1e9p@df;Vy*llNNmSҥ$o,pr! Dvs A;8*TJA?OV:0XG7{CZIRL_!u넿/ZtoIoW%;CnF ~U w k'$w&_A=S=*dL%!k+~{KPVizagz`'w(Qdٽhѵf{{9׭[s5jzoNԞgs)S~Ԯ;|fk~/!S,wgȧJ]~kfRNT_pKQI!LțO[JᯧL;呎uDc/ߝpzނ]7^KJ>W3J,jLa8cLfo||:MMA5 mǡʝ0dT0hιhtyU-cjFTBShr0<%@J҉$#\by/p[Vnv*dSP06ˉxv VNmGcRPB;`<|hXq Fc )Da&0nL7Ӊ@F?4"qΟQa tkIZ!hw(xH1Z ũDN6x&` W^Nc aN~IȤ@@+1:Ҙ nC/,2^rRvc3HEyum֗{ fQ{kΎpHIo{%yX-U}S&ۺx IDATGwн;' y>șU3O zw%.فezs~-9"BX͹@qlzBD3q"56(+/ ձ]vv_8[Ηݮͻ6|p ?fZ/jg,l7mН k'}~?Sw^7_Ga،}3a\ Qæ;ͅv: j2r^jJW#|Ă=K{3 6-ggϒ[ߔi  T/ }n\j&s$TҔ`e5#`p7.`R1MX!u| ;}Otp{eUFMū|}W-o}[0aZwKLof@Rr `^…0 Lo*}D&_ 7h7Ы5q8a;E mkˢ?xAOgBlJ5N׿1M)M۲)ɾ_hQ׶YDxc;0 E`4!#eh%&KaIXcdS4a\?xAФ;T+r󉝦e?rH  i [~'& `'(;zfD Fsh[L71Ժ~Vd8IΧD-IۊȲT8fPմrMe;N!:)/&֪-p̹.c ʦd˴Z]}hjԆ@ ZN~ji߲BT-u)B&Al fY[Q`luuxmہ­@ *L3U✚ގ̀zLMX&غLU%i Kj"|Hς42J5XͣIqjB0SNE D 9 SO}/@  H  0T/t\Lre5将`00%}-lI19ȍ@ j Q_1E`Y cT0cj۴RFzAc}TG(2%jZTc.U_OVǮfm+aIW3%,߂c;TeSL sY&:5.V[xK%LuezG @  N(TÔ5^4/jt:a@X12qS//5EVtaLA dH "  QY&jD`0W=4)1^Զ Lz7.:ǖ ,BCHf]RZ}~I?e:f C  0@˳=ww2N˦MQ[>cGɁ>rG 4V97rp` [y6V< Rocԋ6,,eLYưza.K{Y&غ2"MFռ#v߱0 !ɍ$9zmhdU7q}fg=}r73Ow$Mebf+[[5L%SfĪ mbɪab@Jew0,3^&gwS^9ΥjX2OgUS`b9XKAg#*' g r DCy`&rHkи+{[AO&d~&a,)j{~ Y= @ @MӡscnU@e+wj^KϏ>tZkN' V-Zzs٧uR;nq|H{c(SP _캻D˳}C%׶||6E|!cדIz޲Ozd^Or ׼銄(R/ׄGa6#q)㙭gA G1XSØ^,aLc4 +c>Jhz ;״/U3aVUf Ve5N^a'L[/?x֡-S$پ#d7Ju>y:F9ۋGxGTTRK|q/?T}֊E4MG-?|+y# ^_>Ǡ5;zzs9Yd͎!xLc{?T~ĒNV0dbɪNTb|27qO3Hd4c0K A@ p[g;eޟt]svr- zmYYSIy䙬kz)Vݶh3gau98A)JWA<[)QP&e;℁'֞fl#f jQT6SV62jSeԮQ0N\1 \1.Ra H Dc@7 - l|N_l?]#Nm4P  9ރZ۔ d(joI" \&R1,kO4BR"\P2-h]&jИ L5X#JJ2"ݍcD @ ז1{ۨ)omrgn)ӄ$%ޓ5+OK"dLUIR.ѡ .|t!F;@h񉌠.~ -;><|1)4vƶaY°}YYZAkm@ R|a?,bW-Z\6#i{ݺQ{D>ՠO?ݷy6}x׻])LEG K">?iWN]4(!nX6&2X_?:Tdp k~ݘA#jBQO G т@ =F8s+H1x~1؝P_6(+/ ({yWfvYONALk3X?f(^͞[Ϗo;34SYMFnKZQU zXgpO7vVTiXV,9uC@ 0z n~ElS;|ҿFq&dS3W=ҍٰԬ=^PJW 5^_&Wxqu^|T|=$&uYJ0NwibI0@2@ (I˳nl\aណ7A: e݅D22Xh %ÐA F|~|Iw?xxȱ'v[qw"@XWd/wAEMa0 ihxta<4۩&F %` bڟ'3 @O-F PO4=BBw_^=aˢ6N S4) ,k!;4qfYŤT,o.{#N?մd)g/OЇ]ƩE`ZE ;̌vB.d?헍zoD&~'ۏQɓ|yVo7:^<ǫp[g;eޟt]svr- zmYYSIy䙬kz)Vݶh3gaQ?R%[īq((2bza4Z^ ŏѪo7=Qp<Ch7/o=,IB"}߁??]axKNɃw\J~-WTwdPlo?]mQte|PgeH{gǿrXGc['F_Ԇ o|;e?<,YB3^lx'JwUbB}{ V:J!}nF>^5*Ezhy}.gF>?^sMϓgX/>љG+RϜ;NZ1a6jޠN\uyIfs(Ƀ/5gr&ܻ bV齸?\IL߱Y͞KC/7öE]l0Zv?| ΟۺEV Q? CMa~`۲o\68'DE9[z;TNܶ NrA=MyA2ϫ6v^~,P\&R1,kO4BR"{IlGSWaɘFv0ЈC7T^G){gl7/?MVsdPW43t8#8Tg>fO[V\d4k_$O{\ǝ,XE7f $S43N;y|+}8{%w/"^_86e=i?$Bo; Q}ûc|g+$0%{>nG.v̧;~9I0B\v!@5F/ljǕsM]M>rNS[,ӧ6iF# %&KG`\On\MdO'ehھ.sFYP6OWx1jȎM: #<ں\m @eܿo~f] 2?fs@K\y3Lˊ݃+M: ב}Yzj&KWacTsiGOo(KK?kZwHĕ-O^)tSfM2x~scd~ܕvc' nx1䓴Flcۏߓq~ IVڌ?hW12La;^3g xޭgϽC6=OHc#KΤ^hL-SoީSOg23"OQ]i;z;~ 2glCrҹcNk++8vRR;az}Go`3وRңOSƤTe#[:ǟ%|gR/#Q% ކ`7pdeQ,XkrQ~z7Y)(Ҟ"\~2^9dTKu_<kPdgv%oOܒ0w6L؞?\YiD?ێy׹mk SԨza#`d/ ,#ŏR]}j4=''jM 0חCz:\ʼndLUIRԧ[BREG LA?࣐Ki.rLlUkMC=9SC IDAT+DC‚ouUKǭb.ʂDžv=}tDEGO8~yIh,ZUv_&/NULb߳|?2L]<[eLDW<R*ie"zys(E݁Y&XqtsaeM(E#.إB+EoqC^ťM;w!@YTlۣ [r/reL靽;GhRoX6-4\M)R! 6sG(ʼb(OF[rnc9:W"^ܩRX31qbsNrQHW#m=~>i&@: (Yǁs(\Go7Vд9Vdze9ֺvYxŸ0ZAyM7SO~8C rѵEf{{9w[05jo8g6/ƶ/RvzwykW\ݼ8I~]hs\9J٩"ߝ0d ƄCƝ+>GǂJ,!xvڏLMLRkT ;u0zQPj?#1<4,Ʋu8,g7ܩ ƶc+sKhxp T]sE~V hi.~MFkPTL1Tkݱ+Wp(|)?"1Q6Z}6iv&d:k@5*`]|gIB NJ.&m:\@Sr9iAlan$bq^ׁ%ϑQ`#=+P~7*%z 7eybѝ/8>p'ˎ,~aF=4<s _ v/#h;mxQW>_~P&YC7*Z.i)i-|˳?] às~D|~|ۙOߘj2r^jJW#|Ă=K:Rguomi8cWJɟzT* -ߋ^;zŌ4.Ȯ0>U޽5MoӈiD\ɛR̤)X-Ew(2~ZL e{(rU&T˲mmSt獢Gy^39%ԷWw'7G!~hۉ.;^}={b8lm*{d)tWo!٪(0$}! ͅ,ʏ+n/3Iٷr]NnF=o3DWO޺Z|N `ߢGGytiܭ΅Ń=s8?W7wnIƣ_\VtnQ8Ps1h-=t|q#-2䞝@6h0#`p7.`R1M46!Sןy'節nx͆<0y1bJW 5^_&Wxqu^|T|=_nQ>d6UeFFuu+-jM3J:nQQ25%cp۳_^lp`mMɫ)n;~*L&9iOL"{8~xܩ|yG;Ǻx?$`pK?[J {FI=cyG;~.el"w=x®;6Ɂ$gnq~NǝC:scϛlVa-/9=ڛ'I}@]d?^9?},~9Er a1HZ N1==9||^|[x ugf9eyDIʳ?+Vg& ~+3{h;s&0axfۏ]zXX%mۿ^C>˰30Hq%83[ NaAE<ƅ{?Vzt>_[G@]@K7rR f4ޏ6w :ҥLv(]*X2!*9R 64p>_׷ݿ/WBרѽ9)/~pA;xvX|!Mo5sm[|`=k䗷t2 A}^YɫgNMϾ5fv\oE."2`6-_n:%<~庅Wef+a8cp|1ۙc\s~d?Ii\ҵS[yf*r9?*pӹ%GjM`{޳sʶQK۱d'6f&=:,>:R32Zrg&W^ Z6z,nbĶ0ĭ١5Rq5#hq0N:.0FZȰ'Ϗo73^4iΥ\+Jx7[qV|л".l V6/^l6UJǎrwF/^Waƶ'6`ӿQ3z1ftw+mwzu/һloǭH2?GaF΁>ܸ{6>fѽoCg}V˦DXkwcU-K2غs`ү˪^Β?0ps4Tڗ+7rXaq陫ݐژ"0*B~ӮTR)jobLбG=},Ų?IO.j=vu_E li.~:^`00^`5iXz鱫ĝK/&pSMGM't7z_"xf۞AmXҌ9mGzRa9E ׶}w`Z1 Z4 3J*/ܷ7fZ=krYJiK[,5j@sNRYht7lU^3@ :H)S4L]V/ hZT/ HØ a4/hJ4.K^cKq:U|q~m+h;EY˹R!|;P;9e9h̔N0K0r,ݢF]Q2hX})&=gIU4L8M) ?ȯC b:5LR/ 5LW/ 5La<iMDu B$߮j1;űU.`* 9eD{P/jW/ ؔm M" ^eMGAU} °b^pیv cXJy0S ef-ũ @QzΪm S SiQsX\00uN}UEP@ QuSk0PX2/ 5HfWψlzsD@(="~/As1Lrvv,mɯ>_4A Z @ ,-I}|*=AgU:5En Zb'eɃ6E*]KZE{媁 @ 0=sHQaX-j9N%XYX#-Y-Oyp%f)GF87ԱilOX|;irz⑁B=^ʙpuE jݲΜFO( ,^4IV5ʤU|~|ӮG'tO8$_y 9;.n+mj_Uy?# 2XpLSGEےcT=H[hȻ;L !ی,Crd3))3@5znW ٷ4Q+3S+XXY"z?D9.f5R1QE@ j*&\,?vkSl @ 䌾d~ޜ_;12}㖔~ w<yv:2_F#jtP$}v#?D\+NODLsfP:j)!dK%"x8I%^Z:E_=aU.`*=ar RM OX C';4H<5^_'z -}K60d9Ů k@EGJe -J8k=p\AmgķN:Oj14t/ 16up͗*Oa"lR_Ž *,TN[:Gc" ;e+Ǜw7[薶޶ wJoU'o+zz|{,h~c -{, i-|Oz5؞.g2PY\/Pe .4-d/\?3_^|o1UL0,/E'Gѵe>h@/bC5bq€4 E : M cQ,^@Q˪3S0ak݋e2WbJ_7 #MaJ/}d%[u#t#b-aؤ:C)pȦXJ:b+u.mdo&)z܄ň6e^x05^A u s)KŞUkP/PYL6y/Ew'2hJf˗IbJc0]XM%wǎ]O߻a7xN/۽Ctf2AC+7H1],JY&ju>,:d LIbS2*d4f7SDQ2<%8_&)OOT^#G^'0$x;F_^;j֑2QMtƏU/jҢ1K> :H),!=0pqGq/d[*Ζ`S H{./+%K6ylKXxAKlwnOn9.SU9>> P4><|򽯶pӕ٪֚LT/ [퇡+/1d(9yr"l[<'+#laCdMx1:Į/>>Q-_HOزTy~w{vŵ͋St(;oˊa&lvWշM!|O}T [Pw6Oqk4l_Cc/ߝ0d ƄCƝ+>GǂJ[DGf]1 h[nwmM7m|x\cdHS[J&@*٬ nq0g҄jO1/4`d dԮ. :w!#oE|+h)nozdNaoli>ٟ.c@aE?͘nּVR(FwZ+|0K\6.Xt[?,Om1n qmc/-{U?*]\ ,K[^# P] #cCP4uK^ng:KstnQQ2՗1Vv0 ' @TQ+4zREA;>ҷ,wF~sz>k6la-7fә1*q9gS9n/3R*]5V'6L6! |}`:/VI*goȜjԋ&026` ŔJգ}'D'ԐtʄSt|4a BhYMhS~R/T]{tɴhӷF֢{0Ecԋg0tl1Quez2-dA *WMg`}P cJ҅fAQdQ tuaJ+k)X&K^>dfS֡Cqs;V6|{bJ~$Y@sE,P$KlJVo-Ps~& 3Qh1@ j<N%h!')7"ӱYO̴Ũzy2Sk`DRL!%^?^["Yu.˯8[q{ )$>ZՔlMv CMh5[A@QL0:Ջ1\1qa=hPլ[ -$Zݥ )`s\8aq;T<+g==c+e9EHEl,?6C [ *9'CS8rV-+yJxT%K~$WAxk;WwuFSa}i0(Ttb/$` VR*~AKtӘI҈d'z9mBu)k"Kٶ$Iوm}HQLKf  !k%—,Vv-Ȱ-B_2*T#Ĺv@|Uk;at_b. ̥SujA ut^,~a ^Shgt |ᛖ6^0Tx{ҠBºMZd޴dO;}?2U֫ ߷mBon/WijȮU۩ R9hk =Y\/)fԮw[f J7ik__Y$2Z?ThZGje'T:م!]m"1ۑ1 6m\`09 g0Y Ĩ8S6KǼuGӿutoWWk3/ޗnڞ3$߭Do^Xۀ':s< W܋ZW=.yWwr'< [NZrEW}a5~{~T1έNvgqA"DwR몇| *_O 16 Pw=E|kq5%=T85hħj"T=izwSX/,\WY"{tDݣ/Xk5'~P6nmjFarUA0S^Q>vx&QQuW9wSu߮zw)TJU\"wuc+>אָo輆m=>;擳W "9׏wyu?/ܔxk\K{ɍɃzw閖Qa|B+'{g[[gnnqJWw`0+W-CQ!TmQ,|ꗴr3Jˏ?@t}{dw]= 4:1oTxtMxvkȦ:O,~iP]į蔍+&[}g̊^(K}.ٰI/Հ2OF:pڊ힡a]4^Y _-7|Z:Œ0{A8ahp0 96Yi1TIrBxȦ!6Xr$۱K \TeERRh <9 OH<{=ʛ^öFSVN`pX °4e-$dyTݜuO{ 6y YWU@[qU8wz{a~q^VK |pe/\o+bᑶڋ1:쯨)%cPg dӐQԈ8&G?(pPr) 6}JB ^8f)? ZcԈU*[F_^L/UYV^ `#{)[ '[ a{Mq: 1 Y 5¤ rJAm/`1 qqű|lQ6Â~q r&IDIpdpk/0V;` \2W",f*bYW . *[` DEc`ZޒeZ\ÛX+<ƈA]{A0q d/c : "[#1c: B'VDo/\mG&@`0 d d8>/1Hf1V9A0Na/z^4Õ paÈ&F{,0 ԜC1̣E!ˈA]g{AXr'%^í 8 # }‰yrȲCs{ֽ>q@а*l댴񂡪`ۓ==nUƅ'F8򅬏8+ib7 ?hK0uF^a1 U)`*/.3ƫ+5շ_lV<~s3vp ZL՘̛}ÿw>\^Prm}]o}P{f՚j ^ 5_I/6ie9u$a *l.pw55՞IiEѣ99L 4j ; Wpb/S`l댴^ذ^" x ,z싣V2(ɿ4c Ql>).s!0΍^tX{)P[;PRGMH9v)wBVTZ] QE*h*&;jNtcY}L@rBW@_Ս{^mCI<0TFYԅ\29\ P LŁA1"w+_e4YJE@13.J)AcgGܒs@ W[뾽xW/kc䔸Ϥ6 Pw=E|kq5%=T'`9.OEz'.^Xb^ D e g{ RFLF~zm̋0\ tG9$ҝWҦRx4ܑ qnrBcÀ.t^b/[ATzyBF@ʒDx9"u߯ 3t{gٞu}|Źb|;N~6룣_)?3%1s_rC˻45=\ Aho^?"Hn|MԻͽ}`*0Tj$#u=ε#weǠF[ڒ`살U[rXq?f֤Jwi+m==4kDJ Pzÿ:a7H}~c2zuU{TeݫaKc~esަ)8+6zȼ;aA`e,Q$kh/C>n={'v`?PZlMՌo(ڽE{-_|F)oE-d,g\煛L(1;krOfy7ORgT؉ %SR7yT1=◖6^Еj鋫eG,wQ U<8paX 9 c;cB À P5kNo!!A&=(.گ1`9jA{FǾNtpITrA?0su1n %h ^)dܳ}ikWzG9u>u?Ίg}7KE8=ii ^ TxEO}qf(ɿk|NI]Hp;Hc&CƱ P]1ɐm`$lȔzIVcH7LJȣE206Xci 5YcR&{j88(#fVdyt 2ԕ;+X3fE=<%pȓ[rU:=LZ6T|:L0}}-nkfh#!u/N ܾ\49G(x`숮Ll7#%齚2UE UI~ư@u5: 'BBI l4[n!6̱cYdlt,#U[r:LKұ0-Nӎ#0~xUNf 2R$ι3v~@o۠ IDAT;/M55+=b1s^ e򴺒sn喟B7o)Zݿ\dnhիDaȨ9}E7oj'-mڛj81O(PҪ룓Voם)O?ٻ?d)BtVz6s[K3ԟ\sM{ Dk+k=BUY C1s4E]Qp.ԈF&únAuνl ?%o!! Xi 1rg1 Ʀ U00Ђx-ag/`y?!3i|qo8CkOM-ԳcoK=]S^N.dͰ!<}3{웍;xxgW\+oݷZ;.ixZ۾ۚgQv"=i2>nHcviqvᅪs1S#SЃFD b*JYS#Rc\ahD04M0{A8 =hz4p%kuA0ۅʑ)!S1_8xIMEq,{~V«߉nVHe#(2 LsޚYȬm\2"akW<8V?{׹y5,7Tu0`]‚OXMV(ExHoѰZk"a;,MFH{!70 X*i(&{!̎t0@1eQxj/0V!ڤ`Xc0eǨ6oxAW|Fu Yo„+6|wK%i"Ix9rxJ ÿy_gxXqRRFLyP_Ƀ_.re1"2vVjȚSۗCyhf?$!%HӠF7edkSU]S|_HG[Hq8CaX^aag/qa@` O /;˦!؈8˒p. Wpe9i#63Qto=Ƽ4G3~ĻKK}61|Æ$O`ŋGO ElW^":jŔŗ=v_WN[xd'd~_xej (ǧn^0K+ޮ%iV$[YiƠ b?EcXhaa8|=h9Hcg ɧ{DŽ^Fdok+Isnf194i!;% \v!̰ "g/ 7U7E(ÞiYV@]EVzK)%{YOZ)2ImM¿c^) wz{1*ax 8 px=PA0 aD q0~"pL^sD9 )v/ee\ ÚX"e -$My`A0a0΂0BB1 F$i= F E),2vcN)΃C`IbB(H9^X:\c`0 {AP:pF^ FT0w>/ Wa@G[ eCi/(9Ħ1[61*X#Pδ^H2FYu^(hi(u=`0-( 4a M7+`0|szGVPs\em20ޑUεA?6oJ¼) YcYUK.s "c͊|  `0Ί%(݆qA_j2N 4(8]݋6Ja \)qpt *xKKX_P) 8!`/q ᒅYij~s1.{Al?(Fdei1 c45hO0 A=a M0Ky~{!ڄc/*m0V / +aQeۯ.ԎbDl/+:1&Z˒àH&g&­È^ajp8  )$ 8i k%8}lu. Sww-=m3~ҍݯ_5RYVyڻa ETg|<-{a.6XyHJReq  51ٛHxNF9oN {Ry?p]5cc?OZVqCGՏ4>if2Nq-IZOxH.Wš+4v!BB>zƦU8`V$YW*6͵:RWbZPZn+jz݋U \" @Ro*:[HA._,8@-,GJ3|}u/5z$?KtX'?YIi=oiEh5nAQMLa0E5( .ix0M-9 81JH{zg_i6P=~ #@⣟Ne0/<?*z}rʨ{or֜S19u]qbk*ع|ݧJ@=aUM xřv*7Q/wcg#u+?3o:(QY4NhGj>bέ$ Kf/$U,rl2r?k0y%!l_fq#{ b[1Bw#g'?z7Kyo븏k[]1bƫ+5Wˎn 7OmO{Y֏7/,|Yc^H"w.ilQױ0B.ў%ifퟥgywi|ӡZ]G;|wж|nxFZ/!Gꥣ0z͈ͪ^ ʖԸ Owd04X X|z oTk}=+[' pSt:W \ojx({KɠAO1[Y} 2ߓ WŴW7y(cT{O9X`Ht7,ά >j~kp*lxi9㭽a핑?OE@YīG/m}JQ i yN `!<mƦWǘ"=2Ȧ[?M.;5y;N*u9P5ceM͊[>iT]Cc"kafm"[[c/KAE0HnO[="NN߷%~6>7CYPWf ^Ҁ<(\(+|5 -muU&.ă:\6'%壃K${KK#\yO52bfE؛WxO'>P/C]i닕>cf.]^]r\ޫgPO?\Map]`AuAi &^P\!ήc? |6bhӿ"ϷZky&hTRhn7]vdv`0!PkHexĔdWEfk!Uluk5O 1] ?Pц)+|=7Wu^2d]$sڠo7htczJˡk{T}ZSDpEG ;3. @,ūr2tV^%wHjWW8kzcQ_eڱbu|6/rwo!c<_\>O|/?/_~uwi;;:6^J+t_yʵ󝗨 clŪ F06 T5L㟬Fd#r)Ot`0QnjEMLi_{A`q9ICv*"֋ 4{: 1-2DͭSLhhmѬzvکudTZP_S֑&vSBݵ˥?͉P6jQΨ#݋Og1%hiUrmem3YVj  Q YsA6z9[Pmb섵 XZ" 8u^:{6Z,թt[r J5i_fUĻI, 2;ڢ/_+quN?/_)Zxj]@~Ԍw^h\_wƨ20=#W]),ʖ"oW{r=VX''4,l)Ru-mv}Ϋ״s}5*  yNZuB,x?9{D. P_0v8iQnqqkwvd[-H;۾Y@š;j%: 4vHU(zzhм(۾RWᄛKrkJ~~(e(pJ 'oV_ ? (;ow+zmBa[ 6}j15u-mٻկ!Bk:a‚?:~Wg?d셏,;9dȚ ӎFpElpe/A\2#k$%YoD4 ->ԿsMD};Ue_>o[ZWmo W+m~ hw[swO/F{=f] 0LF179}PE#/}#6{N\= ~j5egOz&ʀKΌ=۫^=KjH ["2vVjȚSۗCyhȃka!%Eа?^h^Ho)osݠƺb2ND~႞pk/vU[rRvR惔$p=Ύ B[+ (U3w4!;u6˼BpO@ݦ0M;%j{3PA"^(Np7M G~c^o;%L ScVoH ߝR (z>tJj 8g 8'.kW~Be _ր20z|N,2Bbv R1+H]Xx Y5 .QD;4Ʃ&KS;90~a0$"ax!y zfXK[XBf/6}( cR{^fоIMuEN/ IQ4iNpc:Ȓ\hiAU%aD=bj*hDk;0B.t+j60v;\ǿ5;swb0h$jÃ}.ASaY6 C1 x4KV{ EbrlHq>^XdC18d0#o/ȐUIF-c$($c/L !]Xx  `Ҫ)&iټVxNRegsŨ Lؓac/0\_$jifߛ$ 0|^AN4j1qTrRcPۋMGco2jhWigV6yKU /v&h :CFT>'/O J>s@fSd(- scZxs!}^خ1 S0LIpdP~JQ!)%e2EcP \2{0 oi@a^cQa]zrxi;20@Yĸ@wmҘyٔBBMf?= =QYh}K4 d8i=c^ d0\c,D P珙g_yA:Znanztv5R}zqۑ!*̰Y&B$7 fUYz ;_aYvJ?A%^v: 4 aa/0QkM8nS`*$>_ kK?n}G ʀu7 IDATOϙ w U;/^TI('^2B :}hV'擳F_vCg~U 3^>xlȴW@X8 M昭cn/ 0(1b5sAa8C۷#YEo-+WTu?[>*Qi%} °i7HE,3k*$[$sҋMY|e`XC~A"1S'pY;c5"+|Z[iYd6knyٻla.d׬gVK_\/;-<=gfI[?>H_[k#W^{ο3{zw6+W=(Ne.^ذ^" x ,z싣V ?&X=Gyjd <lQ_wV}Li2AdIB>67r#&PVܚM:lFZl>8; l |=c|mo=ܬtӕ*⁉-_+&W1G},F8/4B"YH0(clʖeiB1TSq qPF̬{ $oYw=E|kq5%=Sp u_ʯ/V*tQbOIWؖTO?LWpe1"16 XiKJUǞ_>wpFH$]M^MHxb"MnlQB?^co$/|D*gT=*,\WA0d(2,OMbHc6Na>;{' c0 d/0}y×4 oУ />gLW.{DUXX=۵%vƼ:8`0b `bmwEs˟{$[Ahfm^ݽR1yyƨ/.kkh/-{:2M>zsy2+V<RO_>'(Cff-{66R֦fvǿjJTH K^C0Vin;7ORWA3^=tx_^>{챯칩;e|x>W_l- L1b8'=~`/'_:+[wd)O:#Tډ@qǴ ٜMt ̼) 0q^_r۔Qb5B6h &jnbBv$w9BBB{gSQuңYsjյkJ w8C&#*f^D."){I]W5:j*m-Z̞kܕUrmemR+T|L3^ρ{sblR cgHʜ5{\uO:GGTEKt1؋GP7\@MY#,oDCԱx11,5c{FʻRXxߕ-CE_8{WꜼ^RxԺh/J2W'xMU*ƧljwW7 ?hnvo+,$6nqAu,ΣKl`2 eM#b9L 4R `8*P}1BG]&G,LܿݭTy]WuMI/,K)%P~ˇ/>hCm zGniR7MUe:a/i~P] kP0)l:W^]E;^GT'[24%M@\cPal/6my #Yd( },L""#NJ6x$)b)H٤U#5Dq#R%ʀKΌ=۫^=K>ʑϗs_cڂb#?\/Q M*N*bsbfS#LΣ`(~5FP> X $%;i>CV`TԾq8; rhn |Τ>mil0(5c/Əε,TѷB511)پ]Sthe[2$0VQјiU-^R[ $b3eK> =H;[BS kKbb =fWPM=9`6mDF)0h_2\B4k>}2v 0  d/L,LTcưS.b8 DXcS8 Ze۲z{Ap0|dޑ<c~aÀ-*¢` !Ar¤$ ~u>AB38ahÈ^.dv5la0gȚ sb !k.L? 4C\HAN ߱0qK2 u|;,RًI=1"YGo%ӿіL|7%cb/6%;/A!It۔?{13&pPtØ@yH%`}nϺ's?PUI 7i΂*`!A_ o#^cCu8aD0Įb^8qJ{uF1H#q:A}^pY*p7.˞ʏk`c>e0/kko]pNz ZxmO;0Py|c:SnhiЕj鋫eG,wQ3W%GrL&asbvm cH'՝{dㇲMavd'U[ZCJNmw|4QNQE|9a{<QXn6";Ur<eKG N7͓&hU}Bz#A~)^3 Pq`@]o k~*̢'^;8zQo%¿KZ]OBHiQpRl4>äp2M,.s8ig)yÀGcZ,ɦH!B& h^\*88(#fVdyt Tj*7ֺo/Z9%3Ƕ z;עG|_=> `ي}87 擳ۆye0BsuΊǗG{uF\#%TUE FA aHet_I05؋1 `88e{a1XA|A2@ƨ9`1- ع1/ʇ[z|cǻ䟗NnJ~z]g%W=ݚKRh hB^bCł]XS<^N=T_ zvφ{oXE(ED)J)$B 3쓙lzed[Igԉ‡Ar' ԽJ$MQMi ͍A&{Y~~ߋ>ѝ0F$eǵnS] ~H^v݄9L ?׻q՝>NWOh1xeo#sLU_m?;d=kH^ux Z_ؾz?fS3Qۑ_fNa|Y 25u]} S_dϟ9%ވ\psoG$-j)1ՉS'^1$\PK~V#}K]2͇5{Aޅà :r"NNd2mL?N 3}E/R}4l[~݇;Ծ"]C0]9ucй? Vc)[7zԚ5aM(MZMp UOo8d-*5Z:"R3_o7: oQljWvn٘%;Mv5@6-mMu'KGDad;*'Mt +mI ݽIbߋ"9{ ϟץ.)8Pp? Yg7xʂ%j!G6 PSұoq*zLXY>lkp-y{N+#$/3B(ƱH)^| [7,5H㗜\+AD…7Vahd/|rBcriHl[V3g6}̄MC^cEL[^xڿ3˅lyF9 <^jm[nsm[~XF쥉Buc<#:h%,ݕ-+5k mdoM[q]}_|E7e^PMɤ|8 dKf/H9L"[_맻rkjȑb!I__`Fޏ|?6jmjo,qV|?|R"@ Nǔ S*9 sv)j$K3e[7iMJ\ }hN$90ܺPA@ @ -rad/*aP[l ZJ H`h-(?A"e Zt2-3E;77"-9z&' IDAT;!錏?? r=NuV{1pzHwSSop~K) _g29_>fdP~n/2xU(ubNՂjkw2n]AsOn+B" ,H {yɥ?&J[I-=XѯZ[ֱ|{h?TB&? HR~2clF]]ê;ox~ӤN`ޟJ6f}~MJZkc#pާiFOÐ!Z5cb?sdŞ[.f%ٱw3GͶW(Z~g+zxSJ:M0r-I)`KUĸfol6ǫc؅_BZyEȝngݴL&[I/y]!dDg:\sv~mH=%]#WH e]:{=3E+6v2C\5]-wB](6$T, ;w㵯\W^Z,8@s E'o/`ԕ8euJUVF--kOfffVW9ZG} mFN^pŢ:e0/Lde}5Ճ\s4l̔Macϰ=]\u"G†k2xO7ﭜOjω6o`{{['|'bX֥Elz%i8踕t6A(|*bdU:!y;D$n?wm;}+|]pZ6y:1{sa]D !pZDy針^Z7Q`RSI}Nj?;d=kRP/^פ<ޏ"-k}KTaEà :R"NNd2GK~A Fs:f`e8Ba[w -vյ2q4gk6L-,gs* S^ĖhRu }y_I֢j7QoAbJ$U[g Ԧ(Wvn٭%Grl6=' Tw{­Ws Hl>;4ϤB" `Bo8vѲ k<7tl|&[JL|c֖Eln>nE$͜ߜ[3BPs0u1HBX[ٷma !Đs v}`e^J"mXGeB) ˇlc!%'W> y5L&kYnǓdYOOHl7n||̙M_#3a%ش1qnέ]6ſ5,/x<~@&'8: Fgggw5ԤC0G3s>11J&#;rBw[A[q'*1=Ail=d. gC* Kb(^(^DM 9Z_#OxS"bv ~YH D RmsIV,1)tB8KM|[;6U]P,Ӧ2 bjɽ8=D闐]Q~˦oԞ:R2E$\kʥ%9h`sQcR;vҷQǎSzSKAn=ҹ3 xiܺyPgs;NR`_1{:jiFQ)-ۚsXZzu)XWs^Onʷv sO5 !dЬaޡM}ȉ+SD" x:H!-MwJ`*>#!cҙOs*:Q}Z/2M2m'v#1w{؂> ڡoڕ [(`b,;εۯrJ&ƌqBDpʝYӐc=Lj]c彾uQ\7Bʺq֗0Fږi*=>$e*:sf%BmR,*]0 Sb?p̘>*[Y3G+"?]pW*P]1L-U3/Żo>ӹJFv\)>nXbz`vnrC[jL/mBzH=%ɻʁ,M<׍tzkc&{np4$U%=r!˭P֥C)ݛ骁!:3x{\Լzkc},?Xurq!Dڮ J0ʐ9cOv2V(쯅c]1e3uz'[:Mgq_ҡ)"Q[F"Xe\&Uߓ_{[e[,EvAڗW_wV_٨+&~r={o|ʌjaӣ~*`fǤixQB!1U D&ek&vsM۬pIMu!ԵQC qUъ*4,mLTpᵻ9 $s bh!t_$"Ba_l?\9)r} 3Gi)XL^ڇ!D8){͸ Uoq3M\KQ.=^ǘ,}O4{6xQA!1Mgr-K|~Lrwf[SeakꮟZAE$cO{iTSZrJZ&4A[ l}ZAB#iwwfBE_,ԃd`5)Cv^b" KD 0eսᕧ}z$,nx噉L1"Yk}Og{h "aB#t8yQʿnMã?K>)heXit+uPy^y"::ߓr: -~qL|N7R#q#z+L&,$xL񋐊E+]Ӓӳr>z~l!pm CVRQ- ”:Y{ IguƏU +<+X)FyYuIut AAtfEDgdZ퉋pA0tok:|ʰq /g6Բ3ԩ:D&^?'I< !b(r2E$pӫN~L[U`s1B6l?FP5s#gp8̲k{aTxK?pY<}iZT~Nz|fOXrE)'v},zAS3 ֳ/rM&}k&SrSJӰGɻ$yfҊҾy vKV0īZ(61,TĖmBkظ>וKdxZ&4'Ej]̼{'k2^!d-sm)MxIbe[!hu,j4爩'!VwrIꗺR X2nd!]C0]1\lw&]^_>#D4 ~fMX\A% l8ZXT-Ѥ"huS$œbC͊<}_X0?wo fϲ&!m \r4*fs.mpM0BPD?4[8͔| s Z8!pNn8ɦia?sz#.r,]<)$H!_޽_kq*ƞ'b݊KԭGH?7ɻ/+8\vyGveB.x׊*=?ɓoDO Bᴝe_Sq9eӢ)qåcע˘*-7=K&f}kaͷyYNmy.R&˩('ţ+!}/Tʪb~zq1~?';q_*NeqF%$8AF}pʋ?xZĖWO%t 3.\ʬYt6:iԤ8Pp? Yg7xʂ%j!G6 PSұoq*wK!;fmy[F&V_dMBi^5FY5Qs36%^ۼ疌eB) ˇlc!%'Wۧ:")"m^Y-0ӰXd6m۴ ~y}?BJZv>s|DD"o^GS`*>f+E. f1__33W/&S@ѣ|,ʴ]^~.!!ظkkW `RQ6,H}%=LUKn:<&""FnArd/GS1%”`9 k3h/ Z)^(^DM >\Ah7  h$_Z"m YED ͤaazu_ ѣv\n^n^һ ޜ -¯'g͸1;uہu=h"#|ݗbsd:a'Xaq-[۶.+;ήGrJZWZu -ij5P:rzKۣ/'bƧ遗r9RnZu_i7͸~9"{B!Z!YG+ʷv sO5 !dЬaށ$E/ӄW ZNz`h~v0k%B5y#h[*b:jy;FzF4R)F-޵}Z#5|T Jq<;{FYc@LY>"tqrױ+D lz%i8踕t6A(|* dd:ivpD&A@ Ulbx, ׻~q՝>NW誎.8~<yil0.MVH``5)c>;/HZ_x͢"!d,KK?mC{NYL&T~!!x좷nߋIG Dja>hp?b{UkݖoEBkKl:h~UklM!:R+}:>c>K !,STYpRوbwGVS.]7AAtf8]UEDgdژ~Bhɏ?0iC!xpqsGCܺx$l!xs^L\n߳zj>ts)QU1e[g_KaC=|葷fHKvjgMUm Usd7xx_ ~i֜h:5'8_!T^:2QYߵAY|p}G걈**oiYsUƯũvj=~{3  *H$uW_EǑg\3aЛDHQ6xI6yɻPs?}:c#G+^Ljs\(xh ~li{N~z6"@8x{0ƈ)(?Ŝ?޺YV*ʜ &\Ygben}mCq߲f:ʼ[ȭGK8|YPs=znf^`ق R캫=KVnAw-$+٣'X)=i..V,ZQx~{v(6qļ˨*sHyo}Δ{'KbrX&$YZE[CBۧm@c>pOeWD2Fԙ(ڄϯ9~Vk|Dx1USE\sUf:*JB/oǹN "IPUVPiHCm[Ti !ݴp) ~*rٟ6)1D_gN C iS.[^%` Hmj0@ ?YˆzOϏ`4(>EP$-05of=9 OE E5}.|gRwB1?E<\ $V~!iPY`զNDeJ}}:Nu^r'%̚0rM,=:$ E][tpuVYQm1Ȧ1H̀qI ureq[W{+*ƺvRͤI.AGߜtVPM.HuV;SfKUF(s/peh{65$ҟڒԓJ kh B&V19hځB*2@aL9UO& _U,Jh_r+z[eK@Uu~dbuF"FqyW_cf +VimdkV}ՎpwsMC\ĕDе*}j*NUp솘zcE^y[d #tY Wmz|c#ZF~D+#'E}a)@SHomQפPyYI_):5&|ܕב/?"e翌2G>mm2~~尘?8߲K3`VBi&+bumWOFxxŝ!D"vMzC~Yf7At mkFgޔ<FÈwUUqa4$> ӋlnUe闷O="ND l16){]bk?3[zjo|bf'htD+oNJynM!U|Jz ;(Y*ItX7=%tGP;zma9(xwąL#/;/6kӫK6@Me;Uaoݫ;`ʠ5PI k-@\v/)ϯ 34]4@BJd}oK99/pZ.C)^R@Ҵ!{(,}c\cZ pȂIelUAHY2ܧVvSa., |n}445Gbe[Ƕ(We8a`kuk%Qxf\UVu-.ѵUS&:^AJ=TgwSWp0gn`30_gVB!ˬeUWϜz&uˍPW Uv-û hp.Ng)&BʺnF_Ko7_YJp)[xTP'h ݟ%+n=WD5Q"CYl)?KT0i9sfo(1qnέ]6qmg ի )Ƅѣgeȫ2BQW*{i!b?JQ{H ]_Fo!뷞Q˴&y"r t Qy ̼>.Ǵl.ٶϦztϵ{L~͒ggQm z~ƽW_0Ҡ`͒Asbq !j#p1ٍ(`Alpӫn /v遡}ˡD !nqĪI+Gn?c0Kq #'Ÿ({z^4_7ꭍk_yѐTɰOB-~ nCµ@ Cџ`[rQAGLCԛ+xJ9WvG;oHN ޕ>r!˭P֥C)ݛ骁!:3x{\Լzkc},?Xurq!$Il2k8euMq" LUlbxī]ubnn:yStzE<0xTrMae^om3}s}EڧcW6$\+#J.qq+l:Q(U&czo<߷ ]ѥN;O'F.3 8v| ,7DR Xk}McK,Ҳ)&0h;KH= 3+E,"8D&xђ.Nm_>X?p q&^5(1.>y0%JU ]C0]1\lw&]^_>#D4 ~fMX\A% 3lMlNeaʋM.!V7/O Y<)6@#) 4hTͦD]x|NZ­Ws H!Y8"hG +C^jqVC >:x.ʦp \&j1ۆ+/&!l37Wf*)aC͌GPbb9Gqux]&Z{oK+!+/9+)" pm'T+7r T J(a.f)zqAT*JuƧ_3Yx}I梎O\_2fdD]ٽhHw}~v،_^ͭв'YmWcR3>fd$> k+]w?fd|Ȩݢ Ogk"PձԬ&o9P=;4ǃ^-­Qa":M >-9z&;!3잫F%&3M5 NGm9EC5ċ>9 ~7>5%LA 7>_}QBJZʳ-~YǚB宪_~{4qˏ?zr(5~oIQuɧglXkgI))Oo//SZV+ RHX,in vnv0tm?{2ǤxFtК3JXfѻ+[VWkSݝCf]X^C%НwYhİG1TǓeڏN%V L9~˘=zkϟHaN sVlDʷv 1H$x3'}wLۺ}MÐLē.غPW9Dɿ!rnczsEnZsIAUkƆ[7X!#FυGjJ$X,+$~K)Myo5q +Ǖl[k߿Mك Ys}sioM[a fmi>}ϗ!GXA@XwiԇXSWC3FT*uw!Cv0}=JRYXKjϥ+'w}kD#( !VQ:ȍZ/fU3Avkʎ o S?{(K1$Sa#*q[ hi86rkB/:' ;)EIhXt\I.ZK[{Pre9Y/ ?Nf4]V̜-8H`p=_z1Mđ P- ? v'Ne^\۳jjoSU#I+̖{5vчn:9]y./^r5 jo՞ѱ{bk4/#+,r16UU,Ɏ9j BD]srnLF?Dg%KYKFo*B9tƚ O)loTZ`[R f4Bz6adQ&FT5"h{ޔ)B'P槧fG~˚JR-{ |-֐-GhQ??{I{C;EJhXH\5X Y:pW_6qqbU5\]i  ~RH& @STo0XS,i@ ;h֎SBN ޕ>r!˭B$:٩k7~ogFIoPgXo~V}xz~˺tZGf ,t,ߕ׾Fr]yij-|ro3-Tٹ̧֞{VZrʐ9cOv2V(쯅c]1e3uz NYX3-1 ѤCW<4m}Mqp CskꍽL dRkbϑkSZ7ZoO-t4}mgeGȨ{aj~k0zzzۂQ\nzXsQXL܍~A'~yu{vӮ?z.j>fۯ2>fd>s[5*Mg!D0WoX;/HZ_Fm>p5}?jBDTVkS ~| IDAT5Goo ۜxO,]xjƽWrD­eȺH[TzKCܿUf`;[32>9bUmJ[hFж2gӱQ82>&pYV{DgVʼny3GQik6pb?+`n.A3ԩ:D&^H9Tu/*)\(}Dw?V}[3d&=yof;@^ ull>0ؖKrL|zo :a=92e[v{s Znj߂.f09fI֫ )g_6~a~|uq,NA* 6ya.̞eMB) 4hTͦD]x|Bbm?|Th ^Z6l}&֯R"cĢ-K>H-p*R#v'~[6d1s!&BS^yx\ @Z*WumlϷ~8éI`*6h:Eheζ>^8Pp? Yg7xʂ%jIa^z5Oeeu%},"zM 9o' !59c_iRHa8c燛սد3'8Ƒہ՜{cǬM ,6=z%35| [7,5H㗜\kG!5'Q;XPBoWOԛ>^I7"o?xdR3̊ 5%Fm")#b M^זxnK)My\I:d,ZKe&ml ̫#w6uSGܿ 4][dei>fG$do%&o||̙-Q6ELskע@M\[zxgffdL4z.LGbxī ^w8Dqy]u75QWWpտ<< =j뷞efe|-0$wFw)J^pU! m! ux9(r>ʏ=y@ܵE é(We Y]m'?ݻwI~Yx:lnF-P͙Oiz !hd]ux+'=0;C-;nz1" xV@ t-SUUPs!TVFjEB1}}E !E9uxì!.T |BGo25=-)I3u>_NEQ5~i^4-͹iq۴fxQjYn"\"K-me1<,㐽0 $xז^z$ !wyl;fl]#Ofbs(߂̴If^[;K+:#k.ߵOT$lfm8<%=%-,jGq5V^^u)":KlC@}ȸbm[5`LE>ꭃg!',?jTWꗔs`G)M=8jvC<{xBK$R7]oǘW _u,#৮mHg0yH18Q$yJ[4ǣg(u4LSd {۬*=`oG+Xs2ׄUJtĢROC_"icԾDSgBbxN3Ť Q+\B@kZ˔daT"G)JM܇N]f1#$T!0Dn"SQQWK3":%Yݻ~;K,m]((-K\,^MO9qޚ' Hq~zuDB1)T_3Tt0O_ӌ lt$|%*J]l&'?n<(^>f߷h%ӝs>k}hlGݴ_8˥6dDʪf,c s%d n9f+,r&#Dq0g;cT/{h#gǬq;wsr;usL$jjZL?wG'w:-9>N[,,uC6gȍ%LZ&{[z}z9h]}v{/j(8s WE=+'8z m*rcV~9h4_0kUWKU^_5vFη(zYƘ/ߖZ`X2Wd/J#N (I)f:c'V҆;" ѲhE[m&=iRIJC?G?ݘ͐,T"5Ѿڋ8M_.?NW~ {>t>6N:Θyv^G<ƸN5Mg·aИaN˾ #\98^y2b7:1`ԯgsY^E%7^1+Wm`YQI$f>v: F+ txͦWa̍^A;z{MDm!a;^8B 씖kբE Vh!hjqJ4ş8-qr¿vvtnA;: 3ᵗa̜kgNW~h /v?*{c wb:naO5p~x-mA17dvIf7Mz'z|/_ꮓ)-^U-UU{օUE- eO: Zzeʨ)vYݠn4-68h:[|qϔe}g^<ЕF צ c)E.sL!P&c7iIQ{0!BAyO /0U&fjUlW{ԲEtM4w7.K-n3%Jn +7p琌DܫeSij+W=W ?=+ })*ͮWKIwfnK\.127йz9+yCL~2nمg)ώON~)m.=OJпRW%EӟxҶn胇WD] K]j,6(fWn!;XYzo_sWW2ҢURU_5_Y_9eNH/} !^!۷?9cB m&dc6~łAҙ}fgL~.B!F¡H|!o=Nqۮirvˮ̑? X"C=^PidV:̢7"/˥L5.UO+)ԾoJVo},9hɂW SAҙcMHkD0Mvn=Ľbhq}>wŋ)eLVvVF[]vZg'-7H qSdUuI ҒVrsk?mPʮ܈C";La`K/l2be.q.oe|/ebm BH='d}+1?30i K+= a Et:jS̻~B+X<$Ńi y-JR\bJ۬{< ! ЭK/dM4}H4u6(M.D*1pɹԒ[F{hobVrL~7gege?~`2>]VnBпӿIi1bnrs.L1w&B=mVVvo#N4$uk^R$"K+=1~M"$?Ak)|==vhȝ{G%&̷yKP◿F%!6 4(Don"_$>{_ȯJx7ҳ܂x{r+7ae O5gDNj( ۫jпjԿ,ݍSɯHoCѽ>WEMb0>W9r_\r1a y4Yq4# TXoD9*N4$0+b?x<[xÜr6së7U!D48zAn,I>턌kneW~HaӺL8iдbS\g[r4㌂أn/7M{k˜EަLsOVpQFI Cشn!))-^U-UU{թe}!u7jE5욢'~}8/r jpgw;L&~717[Dkv6:cIK5O~xQa}̸oтK3jPT Rq1Zz0Q @}@a|u#(Ao~u%_FH۲ *?Wutzzs۴IlQ<슜K+;??|jZL?ۼnyB6"y_rq_VyX5Kn.ܠst=+'K{}Q{k/WEOc%ꤾNU [Eݽl=M]QdT(hlP\3c/|UbIr@%K]|MrR= S*U_}kz3@BB#`Wh޽¯Jx7KtBq%(-K\,^MO9qޚ' Hq~zuDB1)TxzκSijä>}QO3&"D4yHgH*7Sav7–-`8 Ⱋ g^d9N8%C0ЖMLg#ېɡKX,zqiEy%s+@m$&$:m۠mmk%zN$ 5d 8{vחJ0tޛ]DJO=TEˁ~ei6))9hmUQ-0xJ#7 ]gK^fVBgk+Wo03qlc;~|GS]5r_zh_xewlILVs$X@Ѫ^,{qY~%_jCTmݵd[c .L(&&NځP;AܭRBZmN5ڡdF3o' `i7ϟ~󹨾53\8u9>'y|6>I-aaVF7CWtr14L=k%Q 7SݗYCBLs{ғ~o'L/F^~X:i&^YS&`2"Odu,Q[e'-FJsJ0_v)Ba_pl̛6畿i5rIR]H0 M  Naj`;/ ew @{NLlj7.Uy(Os{u ާLJoFݸU=(k1Ԩ-7~)zU4{)h-MKmsc/|t@!2 E}[Cbͻ6^׀%]ALNNdƛۯFrWĥ[ވbMa_8~/ӝ0^0sLG#SƓ;lkzq"k`p,9N8qRsK2Q6sQ'0lzjiٽ*" eW#zJ̍_2FJ+/09c2;IP{ihy͜6ހI1wY !.=na;5)p~'n8A!l0oײkja⼀+Yr6S$-~[5_$ ]# R߱^Ͳ}.cY~26*&X}h/%$:oN5/s2A[<EY#jir8O6gV}*(lsxMl>}t W|UN_9NUGGIڽ{֥W:Q4L2uNb:?/: coE6݌?Ȭl~#L˜箋+$S"!cVQ/kJ].fXi`])DТ,!/־_{usڹ8w1$a!M6& n%ۨnP!x8@+2*Kߖ!f!?')`r0Ǐ8D! i;;]i%u!&: ϩw[PC/,VT_NM$FֱDqHܭcWg<:w0!hR4958Ux GBlD--N-{Φob)|#Oˌ-ѓs+5XY<[ -$zߑC~kiD #517)g%lj,uM,W!4:XT}}Χ rji&f"9<^?D&q̲Rgϳ4Y~~% o&?Zh]_4KogLDhd[W&/THN$ˁ zBhD~|Ϭ+6M!!t0b.?}᏿d?Bljez9dѯ+\vep.#R1'}Cj^ɠ<-cK>3aa{8sA4NΆr.zM76T_H:/ %#v/Mʩυ,u/?ߒu,!lj\|J@4ݜOήM> #7'~vH6,e.x3soq̒*eL*!Uzᛐf$-c7_dpr6SM7j.].UFf?z5W{ zeOyR;Q>ds05I;$8#Xuߜ~KO +Y<,7=(|G B8|4*2KӣlPkH3IV+%jo†[6/y\D1v:’t]Om=fh0ѡGjpKA0YXsW T+C,BaToaw.F8[Al eKFW2X5MLrw= U'J, tbʼnnq<VĬ9}3/7hJ܀)sd}~ZB2/X,cah04 },}"8hh3jX_oEvb<}Ͽrڽt&BdcG߱K6@13^˭AGzqnӶ-XN9ɕ̃P zݷ[wZ7]+&߸&+ $a~=-t\F黬ObK./v TK4Ǽ*BҲ##7<& @SvC?2.hL~xSbef4L4کw\TT[U\Z6uSЬd'*Q_5Swuache4gSc_$B] Y{A @sHB3Ѡk/ҧ `II`p΃Botfh5j_a$L` A"aBVIENDB`RunSnakeRun-2.0.5/doc/screenshot.png0000664000175000017500000020052713541777402020777 0ustar mcfletchmcfletch00000000000000PNG  IHDR*2S+ IDATxyxUǿ3ڴ,--;e("TUY/"n",K_/) bU " {{~ I:M$|g޹sϹ9sgNf&f3 0 0 0$s0 0 0 ]6KR 28I90 0 0A l8@w@UA9,JgaalľUfC8p@ۯUs{~te.s\2klٙsΡ*Fl9UjP0–\2e.s5}}q9zp\;*)HNNbgfX 0 0 0c<[&QKjR'*eQj Co@:u`ٰf7PbG^>7t?#bJwaa&Bt +IodE,9V;2}ă} P F v₽l\ZVn߇?p?re.s\r.ᯯ ֢\=EwŎ^Ģ>BZZ:wDBsk' \wee= e8/MŅpx>0Wҡ`X9rŏVBlۻt<8E:e.s\2\cj\6WU2Ŏ;fZbd Qd8 :c,I.uG6cGfo02ssGł_!ѶV.aajEiʼ]lwTx7 ]թe=dYFV-s.Piaᮛo_b2|Kp\@tǓ#buaFc~+[:<.>|=2]S|~E(Uw0i0 0 ÔR݊ƍILL 8Zdp9\p,ݹv <(_bͧaKg-Nʠᓟ &UM-#Aѯ6q߹e.s\2ktY !_-*ҶT&ϖy{GEk!B z=$th<΅d4yy)kSW'pin6R7Nul޴ i+_d0c؋3p|O8 iU/Wt'"ecD5Q;0 gwĉ 1`q DZW1.xۖw'ں'AXsPkٹ+ 2e.s\e5<i&_(efռQF@ޮT8rȋ$َ'%E\? [T;\o-W6r_z?{v9Dx2r樓d3r~"޹ťmO-D}<[- ].dbi*IbM`-ľ ܡ%t߁qSGPt`-n|8k+݇dŒVcXe?5渂IcaaHޮ2dddh߲ez^S}GE_|GEWxc,`g/{00#>z#"꫻㕗F4KGwVKzy?x)x8ox_ч#raX h[: znVb0> aaR*;'M J}=mo_Qh-hY;iY9bAnn. #yQ8i 6ۖ%U^3Sxװi6!|_b,07?z'N{.W_ 9H>tۓ{MBC݊ ἤsmoTlۈ!CDzl[6-5i+e.s\r.Qǹ藷rwVC$ mzEa8%ݎ6&K nY2aڧȓ:tr:QW[W>Iz}|< ӷ Yȗ\Y4VXalZƟJ:I"x'~!#bGZ[@e.s\2klY O/|._ߺu6j8Q} {7|zbNYGv,20Saa0 8u!id7o2Y{x4na9smcլS a;wf[İpC"bnA'/Rt N֢NBᏋ}r%kB;Y9ߪwT$bCO\Ç ka%XOcŗ_c8}aaj*ٛ,JZZ_.))Q}GE;vx_W:=%$޾LeΎp$ZZQH/Cq0 hFCi[*%_mĴIxmܳa1YBuT8Ѳy2>J3&rލ :5za]n<ubpC@+dg 2! l/^uѯN8ytQ L_HA׏_Ƈ3Ay(8DpdwXP;)nnM,Gk0 0 \27YRby =B e>.2ϣE} ס_fI^^|y0n poS^+>5#lRz(̨iCmya{yB Yzkpw3_o=a_]_p}4U]騟5,D5 +fVw _Z ke.s\2ktY OTdѢ*񎊯(v%L?8 QL؝oEf^Zl6[;AGT_ygz Gfmpo ƒϼgsB>9Gw u;Xzy ;.\7&▷֢Hg?˶ _1}4񏈈Q_;/|p݀ugEX?;݂b>ymPk{\\2e.sƖո;* pvJ% ޢQ:{)ZJpm(jԉBo/O8<= ;hWaa9zqwT<藾H;*Uؗȃӭb0^Cxf ~ vT>gaao:$X/^xe9|.s\2]vUz=_+8jX鯉xNT0{2e.s\ieGGGJa/NJ+(vaaFvi„@ $% _ 0 0 pƔ}^aĈ0 0 05yf~S\\\8s9"IR| o~o~$IHOO/SUȖ-[e֯~o~o87?_0 0 0 Sp0 0 0L 0 0 0A'* 0 0 0 0 0 tTKҢE /XWhx9X/ * q[>JTp*zi|7f||hѢZh-[ڛ[kXW/77Nz9W>N}7G6pC{0a*/uIHT/ vE?e$ 'O [!C-0j /F&PDC0nU& o"|orUvYr 0V?T!#\ea|wN8cb弗 {K] )N8'OrRI?rJZP;?cd1&:XalM9>٨HG`]}%Z<6ćHǾ;nZeMarX{b_Ĝ';5U'-;N?1s~dHo܂7<ϓۡcNd ͮ)^O_s;ۊ ]V "Om[uއe{Tǖ-[:QҚ[m_=wxs{/(Py-KL\2/?_UuWw=OBW7bʣ5Zg*ʷzWn? ~ K& ǟ1 [u x}sh=|~?r^L{%eGet5:ۨr(_^ /]l>wDWXJZl<-Rcoü~GCe:ś5{9M cEA_]"ؐ]ǘU{/_At>~c$`"'ewWĉ<|8[`]}"z50w^XYp}i>ND^iyQ~vURݣrXuDyǩB]R7m Ij]3*w=tZ8 8OIV;WBw37޻?EKU|9`t̺-f`+hʗ~?9q㮝xb.p彽\=]x3pbnl Q4+&=2v<͆»8[ļ8t Y6 Dj7oװiы  pPYW3*};lv+~£]/S?߅pr#{Ljj7ܱr';N4l?^˶mM^x?!ux' &9{C3wN$IcNK hͭ%HRo^% ɇouN*Y'Oĉ?R^ۃz:f⴦SUO}⍧UmD 8 y_}fFizv+VE$:H~uηg;'-UW3DL^&N۴v<><6CDy͙<큶o??lmvDn~_Z6/.N,y:u̟D:?NoXך[ոy<|Ch 68kUI`?ǬZ^n]GMХ<$`ĈlٲC~ O=J n_ǟopF_ᡍۧQ9 4o~藞yf#)i SRwT M>w$.05"B˖-GE_#\lj(0aa*p"0UIM{aaaaaaGlR~\v~o~o~ődgFrr 7X?`| 7X?`| o8oGezzzbaaQ}+..l`| 7X?`| 7X?`ӧWzQF!;;L==10 0 0>3q o#IF?NTaa ^-aa :8Qaa GeQݨ0DAQYCnjaPDEXdsPdF3$.ֆV| plTti& [wV ov`4ѲӭxtHXdPk NKK?o|4_!"f9W@Ŷ?9l>[^n`'Lؽzz7V{bSJ"¶I7q7o^>^M.: _)[0`@RxV ! 7^v 8>Cn3js9X9=5(m>bq7>7|>b}.m*!/U0yNò0_˹G?DŁrP&+DD}Pzz:# I3eqׯCv畐J~%cdyTF?6B+H~'AMkmGjґsVAeSk<~lHZ !\7;電~Pݰ~ᬟV҄Xҡ)P:QZ)oFF{Ӳ߳NLM)2 _~4599^x{K7J 3齟Ψ˩Od%Ir,ʺ]綕p?Ihɨ@ho5[=~52dxgBPڪ蚧:fC,Tq{ 5-Q}mlp?YM^/V-xi7dTcgc&6)ϕ6K&kK3w ӦM#R-@ .$G锔4Ƒ\lω?qϤ/M"ua,4~jm~W o/3̡&a$aMh2۩q$ 8zbI'(*H_Cמ7>T7o'*1X-V::HACEҰũTd)EOPdO/B9:L#imgR9dT\mJZ Ytl\2SM_6 Q2-j?6(51iݖGwkGo|&<ᯚKщQxtbJe kamǾY,3ه`+s;^:1ftv ~^>5۫m?i$&LENv6EնN\1q_$%VHz35$ =>R!yX7I~ >ߵ KyYVegU??"0o "'cpBXcƂ>?aCrU_2ȗsOmE.⡦cId7R;Q;WJN~ "Ҿ݅bWWJڐIo6 )5(@VՇ17-@ǐ^Sx2j~oXtjsmo寋njG&BoOOˇ@~z7^+wQMɨ7Rӎ=製w&26C=;S틏I䰭I#@?^ mɮEu@s{oS~42j:_|ēf$Qx4p-x#o<1 IDATBП'SE,>01  --ǭfGA}S ޘ\^G`AQ\Bmɶؽ. 'Ԩ;*D:0~o8;ڌ3P}s@D^ă!){ɲ8,˰e!h{-2} _`ӧcĉeC"//٘7o6 99)W 0 Tم+IRl3GAg+w#g-[/NTa\c\.,'* 0 0 Q_ᎧaaaBEQ?0 0 0L 0 0 0A'* 0 0 0 0 0 tp0 0 ,W[&*,;"re "d|tmFny^{ o ):M<ֻC smҍ!_IN fmΜQև ohVNE `2аuXm~YnjF-;݊NK&E&0tVkƇ@SpaD߉V\ u 9L)W=!vK$IB8E>0 C@AQ.L~&/߉sX6^,:1Rܣjiհj̼Lx MUׇokx|c0}HmFmb7Pw+'b³Pl9=e:OK'zf{r7E4 k{"[I/wNȡu`*eg1N!H2 ]ߊv^(!!GidY9d/Ӿ8gG֬W5FhzPO`"XY2_X,IDBVM!HJ)lFQ BԴvv+:j5Tf;6ǡR@{6PfnFc8Ƈ&5߅<Wt(}2g*ƫݚ>2ٶ$P(3I(zYs+My z-hԂ~Zǒ!.RGOfjS_zur:Y Q?;;6oТ2ӦM#R-].\H(//))i#'@>%*B><ߵq, :tY$L.sЃčzU_'-|m=oBV%ٙ2t2Y{ ɺ2ۨBTi}J9$@$> ޓYf;6q\qzNcQT5=@Ɵ'*5w$2 :SbsB1ik;D$zds:v#o|N!cd'B4bN*OK*ӟ x6eUFQ"ixzpR5~ ޻ @#MY``6ʞh&z[r%I9)zy .\૫AIUw;vtj c`-}xTu}(U N‹_k ~Emǹ,EH]>c{\t8>W:aϝвx&aG67?dx$# =Ztւe"yP&\[+#[aLG׻gg 1Vv?.~Ûr98sd;`B+tSɰy&q8U aOh8o|4 )>3oߏ]J0w$IuOƆ}HuzP[/ۗ>5^UcƋ+n/+.fⳳPҬ'Vzo[ D(_Yv!0s@Dڏ~=J| H۱emx J쮏:8/{:Թ*Y?E?oFCnN^M3"BΑwvG?X?8}І&gjW;wø~}h+k"w:pC83g~JK!7iI]8 !2&]W)[cg_[j]hYk0+^WhZQ-C{O-3j3Ύ/_}Me)& ;݆Og;>^7Q4@+ҧiX:4@DxaA.X~7Cшmo;ς+"_ .|Dͮ Ow^eYwn܀{;Wvs[:k.)ݵ vH-h0;қyBDD٧))i ;B$L=SwL:,vABua,4~jm$ 8zgO& !I䲮ՏI'(*H_Cמ B3H$҇5{2lƓj:yˑ]A5?~ᬟ /2 >X-V::HACEҰũTd)EOPdO/B9:L#imgR9dT\mJZ Ytl\2SM_6 Q2g}e}?UV?0lGbzb;:c[+ߠ (fwfmtEXƆjZegn4l)B԰LW~4NQfvZvy?b]@5;6tUjJo`gڴiiӦJ-yyyNIIc9 Dϸ!HJHA%y1c< *ZZ|~^&GxOH#0Yl:t VX?B3tL"seSkIW5uGA'$Iv\&?CŒ8e٠iCM w=F6!h}V,~sV<ź6@m;2 ^xcZJo`*~yk}Lوbk6Dڥ$}dz !,ok3>($6 JOY'Zu-]+nwyDл?_9Ǹԩ1cܧ`[q0ޯ^m!M#1ie*r,u: o%( nnB$8/X$IؐiúYO#gLeXrsȲ~ژFyy}\=>ņ1iz,1wcA0z!Lw^*گyߵOhŴXW&|u-ٍk+k*D}G`)qׯ(+'!DmSjVQ< 6O kAmMs؈"8g'=pS;2TUzc}OM7th<ӄUj:y[!x~ߺͨ4ǺzޏGǦdiL;Zy類GN$Irv\Ak]A?^wԶdWAK:az7)m?Hzi@,W3I(Nc8a<ґ^7 !ύ)~"l|tFـNXr݆V# K>ۈo./PO~4VOiZ~s&x3e[J9/Ԩ;*D;.~o8;ڌ3P}s@D^ă!M]'r),,nDfy<-̺P<~I† ϡ>}:*mBB1ol$%Arr S 0 l|sSE$)`33!0 0 s \Nc R9?,Ʉ>3 0 0 tp0 0 0L 0 0 0A'* 0 0 0 0 0 tp0 0 0L 0 9,F!"lx"zȲ\e u3?k&uV,<Dà9&k0p#Dھ&SdF3$.W@0"ЪsOt D_5hFN]N&] U^kNe +x "[9]Z7`B]cu/Ԫ۹YaP-T_OK]:!"f9W@Ŷ?9l>[^nPMWvBD X2]& t+S.nRߵ*o+5rg]zُr(M&a((Śp<0% 3/o%€RH~1'$I&/߉sX6Ɋ@QYnP:}gW؇`ߵT^kNesXcE;_ !۪V\jkoۑ}hB/ZzhZhסG̵υC6$5A$lθO,>W|eBREy О9T(;4%%tra4v9B8iێf#[12ku0BPIޯd BĜB*AQ]n)=RVHA6K&kK3w%I*CP!*\5'~DBԴvv+:j5٧$IV\k[ %g)uku\# !h-M'1n#ԤN8EkA'!e_J⛑Qo޴,GSSӺfiC%/ &udnN !M jpEwz3+rӹt#%Ir,ʺ]綕W'I-u1(u--,Siʺq?G]y?>6E6,vABF׋g *Ճ~AfNutާjmsw;BNKלW=>ekT'LΡszE+ʴihӦMZ(==8rTnb4{l? 7R'HA|6:5&3z: !T$sLTua,4~Z1P؀&ne$ 8zgO& !ˑ]e&PڇϽr,WӜ2̡&a$aMh2)h%*qUB_g)vku\#J:aEfSJ'R1 !hHH8,E l4[(B'I:}$X,V9LWMI~"mK~Ƒ4t6*]ᬻrK6{$*mu2_<)o{(@Q'-|m=\UJDc|wSNe7LB_ߨ~j1Lg]FD +M IB2Ȳ9yGEA2'~D'c4Ҙ;ecnK+.{JXz ?giukv\+f}E]$\P)qe˔g\EZ{tȲaRZW`^{c*K\ >m3ԾY,. BЮS )vCo̧t_P&ߊ^=UqUj]#>\xcV|t:QyJpo器>F[2I֙=U9+Usszf̎3G㙾3m_yk}Lوbk6Dڥb.uXu-ٍtt?q8U aXvwgJCyzV8{t˜iVhNW:}:4ՊKzOzgJdH?̿ZzhZסP/~K 3} V?/sն4V" ͢j['I.f^QKvv+$IBm~KڌExL??"0o "$IuOƆ}Huzңّ$ {O&Em\ՅA;Fn+vicoCV֢,ڽPv2/|9gyo:Jl6dśOhO"0kS!`s/"ҾRzߪ >ݑʲ6L\D%R5 wRB2M&?fȳ?1KNO kAmMsPڇOMEPO-th<ӄ~rZ\jk-WchD~DWZzhZ(h=L8뷮w32ͱ~AYؔz#5؃>ڛzgBk=/c#=Գ3վȉ$I꟤k❽qKm{Ovtx/'{Tۨ 4Rm>Kb#dl@'(sliL'(XQLF4xcFZ f2ci+kʽRwHkIOtmLǸrw/in5o=O״nHb[]C"~jW+~+$IdC{<@K8WWB"]LTpHNN!...S蒑o~~z87WDE`L<R#"t:;uvBky[j= >}:*mBB1ol$%Arr S 0  IDAT€ؕ$)`/'Fg+wì aNTaa*3 S1Bgzaa1p0 0 0L 0 0 0A'* 0 0 0 0 0 tp0 0 0L 0 9,F!"lx"zȲqdKg_CQe,xKDmntSd~YnjF-;݊N$g'uo ɌagNIU-(ɽ^uFSZuٛNzśQk%!k0p#c{V,<DàӅ~wPwyN eTЊ?z9$Ԫ?ʩҺLWWS/T "f9W@Ŷ?9l>[^n@BPH`mh\wEc F4hO [UՌJwvc]!#e>_n!`&+~sEygrz" j̼Lx Z:O:w"?qje&a((Śp<5(m>b-~Ux("PҚ!"eO^n!0VEi@~q>/| Ӈ$:l3߿k yۇ mHk C6tc -{g܉'+Gna~2!nU f"">MIIc(==Y2_X,IDBr[ %u!-gC j !Cv畐J~%cd2\猢$IFuM]J)(Ӿ8gGJww6q*ph)H#v,6 :\7;Wu#_ ZG0v*ǫZ<ܩĥsjuğq:i-(YV:uj:6XpOAoiBw?Ǻ)P:QZ)oFF{Ӳ߳NLM)2 _~4599^x{K7J 3齟Ψ˩OdɎ]$ǢkunvUD?"= ֱdKwԣm5_=T2u.K$Z2.c2PlZ[&e~"O ! aE_?)^{Dҿ5We4nOS֝t]R}շ׊M!n6U}=?G+Z\W ӦMM6UjˣtJJIPʗ#;STRAهgP󻖗 TI`wI'_:P%$ªGjF+PtBPAdTH=`4qwட7qYgg-gSSh2=g3ylo4{l? 7R'lOUp%*;sVsjuğqg5 3$IkB/{`=Q^',tЈ)bsى4Q$ [JE"J]E6h-Sh?$>F,Fy+eCȫIAOզUPJǶ%sl?UhH`X.peв<CE0+>K6$I.">JB۫) |t>m:56RjMTūQ'S+N£55wM淏_oU{K&NpeC$*YCAS:^(#M UZ:j:)-$̎.n 酏d??Bh27{l1Hs;Iw'Oߨy}t9D!?38=ecn/\l8WjwuKraēY/Snu$tjնӹƩ,/ Su nxZ]'*\hݿ|Thq:#HAgqMZ߿z0RjMT,qT\ xN}Gg}X2\^ Z+ѤN>7t 1peCHT}Gl IcʼnBH@vKŮ12e#Eؐ2؂wLM&AD1h$ Z)Cުěj:Ctt'"q<ty~NAtU5\~49̝ʜ).%cvxIPл*O8M+B+=:4;,\ 9Ǹԩ1cܧ`[q0ޯ^m!M#1ie*r,ur>r_$%VHzbj{;\v\$I0ރ}~0a./ zaw0_NA؋']ک`Ӟ(ِo>}O޹GU9{M6KBB/VEZO"R*QbR*E DQjE VH@B 䶗Hβ{r&ɞ ٙyf>̜y%;ϩٶf;Z*/fG[BZzpm:g)m^p#ԹyBZhQEy㩬TL{,eѮtn|=*PG7XMVts E~IU9]NہqIUP)uzRQ7+tiY{ňvWa̬ըvaMa5жK<%UhI"^Q@֝e-SKBxWkjs<=7:d0MffZW|<?=zĦdɂfqGr[q߀H{lN$m;&2ZBfu^1V+ȮkDR DY>wT]Sa$'V/PK5#bBjWV|}PHMn[ u{<;*? tNlKȧ6ջ,'vmф.b|of߃ ,t-|woOVxy9>F~j`z*FSQ:wGɥ(NKaa!_x~ J#t_[[&){cn4FͿ,Ww!u6}Lҥ<Ã#?>9Fu8TZZJK.쩔K99dpa K+bWnќFOmK65~s2bZ60 0 ÄT;Xl32eaa沁aaat* 0 0 Taa0 0 0 ;8PaaaFwp0 0:`0h7OfEv C@A5^KŴ|zލ h@VY ԥZ;}/);jPM.jYmtuI;|@.ʛ3wL!X{_]/gBCÇoh!{@zlyzCTvQz9hPݣfӘU;(((@vToLBD)P=qý=1ki!n?g_zd:߹VD`k6ᚓPрEӆum:_o RPF-Oޜ^R`&) a0Z!hP^~Jn@%,lV`UFޜ;u.zEK;ŕ޾N|e.:]8{/!0^G hoGW~J'N}"&;&N w-s!Hf"7|* w,-mP};Ʈ܎ ǯʀ2pYc1ж}[V{$Igo{!d`}xB;1ب55JSF7N~)55-]~hذD7CI?Q Ty }Sd64~!0wwTi`\Tˁ渣"#@K^,]d"[;e渼NqU_յ9OK?!u(IDhm_Дi;hV_S6f-o|NͶ%5+T^U~L+~nhjg2jg&+IP􏰕W@JBTc&+9""h~vaMa5жK<~$+ͅR?5Q^ GMګ8F$ cfFG48]DRH^ uJT;eGV0ZAXյ9OFK?s\z䛮W|<?=Vkпg,& 2zǚŪw& gj%c"u,@``V']/ !v@$ř@DC}G5&K"x"/meQ+$IX3i0-&vu`|΋^|3%X`c7ThiK߽>mZ᡿~%eB#s}rk4.Ps~\8q̌r~a_x~ߠ=RL5kЭmhb7->FhrE{RAoSqo ]7M1ૅ pQޜԽc zz9SSFlV]o$* )bkn\poZGSXAk+Q[;48]mCy#M2~k߯=K7uoOkzὂt@śȖ20*l;LZ}x<Oм^g !tz#0X9uh4SzkikGhsWu BS+]_cP[{>9Ak"n]XDKӇEcO鱿RWW喇iǪhM!P]wH9O/}xn|Cy5ƬIUiӟ=#x+<%BHjW^mΆkr]M6'osђQUYZ?0~k62J}MdkLlWo%͸lx9? ;{* EuNķ!b HËB$!.uBh%ۏq'*cXFM?!$I;99-~$XևjbYZ!fz݂%ۏv'agyǨ}R )7c~x4~H+`j|ΆjkhwqV`hiT & !񖎸c)m{?:&# (=:b 3k^ěl=f;?Ddl)1e!!pw;g6#~x鋟TmRWu R$G>ֲ뛷1>}i0%O h[x?l&xIw"jFZWV~]#/> NBq{;6h42g Gֶzc3I`0ԡn>UO7e9_ݾqIS;k͋Nj˪h?}aK'ϛ7۶mkԧΞI!*'}g:fm= !ޝC^\K,@;ML}1 I`EM$@j4`Ѵ!hoAb'z9j4\Z=50Q#k7WIkBV?+JO#oH:)/z)tSmP-GK;ŕ>L|e.:]8{/!0^G hoGW~J'N}"&;&N w-s!Hf"7|* w,-mP};Ʈ܎ ǯ l ᬳJގ~V͸ 'b#I={C%303B܉hF %PI08/%rPvՈO\O7}o|pl}@Em^XT{Z~ZkZ[>9j=oz |1f$-iXv76,n'ۛM$@݂>sUWP]/㊬#.zg1 F[*|GaD2PBMW[;V4;몾/7)N0կ䟰&=$oc,f2]i{:jz &mߍ:P TF:PB@kD+khJgAzp -CoKտ&@e=: ) : s=ݴ!nƯ;~~;.B5:@ml,ZG-aJwT>}y*lrGg$I$I9>owsQLJ F*ODXc#y]I2r7I[UENb IDAT7L9V:krw$""xH8KhRj5/M=,F_M.\7li4aU~۩jXw:&"FSF^iq$Ih2з|j֗\Aۨg6?ًOJ$-.Zy4eayսuD pm:g)m^0% t\ &9W7ۖMY@5F<[A'"!e !*|ۿB݃~"ZckKjۻl>K34|ɟcjN虆'"N27ќu"zmF_>6"GuUKת?E?< M@eG݋J5ƬIUiӟ=#ެGi; _BCi5ҚzOQuǼÕnr$[/Y,rM},a׳sծSA=S~ty PZܜi !pM{k @MX=`ׅz-pB@$O5!7f,Ug2BTD|ABxWq_4F?-_lhY!ixqYH_+](˲[d18Nd1,,ͲBHIH2M$OFּn k~Bl#rۏsGǤx$Wb`V'XLdf kߔx=w42mvÌuǑǑl-3:!.~f_/}P*=V;n$y?HN;d5#+.Բ # nƎg+qpthmS퇲Ͼ :ͧ}i0%Os#a3Dj]UOZXo~ѯ ?Bz^_U߆1m &5ya۶mS1 !hb5hMk1Bj4\Оq2BYw톮~7$w]*ji餤l홎Y[O{5V^WPҕ觖GG;7މS+](ϛsѫS $5e! FfYy͓ o\F &'ԩ!kּ+@_R)WvӅac1|T9!ۏtG(t/hc+QtpbX?d&"{Wrp|҆wcpykٍ~~V8>Kf`܇g ѮB bœ7vO~Y!_F|`vvL|mU" o[co$2PE_}WԮCds~VZ~idZ>/*JO}bW; N_톮~2g1 F[s5]4抬g)xt-}Jת_D`'PډZt%߬h!(Ԑ5Uk^_*K kcIVf2]{4j~j0}7YXʆ]-PQId[)!`+ξ[v^߽j.nEONl{g~3=:\GW.m/ <칣_B,vã+ǢCZuOC^9MZDkRCi@%;*3D>Ipc[]U~$j{tosGEՏVw*qd8۬'$blӛDUceV@(iih=9\QZz,x解;h˩ TΡEՏt-=PPZ4fM%ҞzhRj5/M=,F_M.\7li4aEnm$hD[M˧`]Lc4OMW_$E+o./܊Fb٫lֱYwZ'Y3i0-&vu`;*Zq^<Я$!>Fof߃ ,tF; E{_F.0[q`4%KklxSl00M~1i'WOI]Sa$'TkW:!~H/֤wT@Νrrri)333SRXX_x~~Rl4H1֬m@IG޴z*Bwp.΃ަ⢏)@MDP6^ռly溘g_ԥ_vyk( TjET_\l4ߔ M 9^H#ӵ5=\3zR{up=匾ޝ{ޞ\-_PC^E 4~ 5U׹镇`zR+'"hZ'X;A˄6Zz@ӧ/sldh Q,Ä "!h  `)u+ȶ1"L .Sv8Mt&MzR'PWtyDBgWe%fX)k<d}C,- v;Zr] i)4cTGJI إ+''DL;-^ޞ;BvSYO۶_ӄ>vHw}`c9_ey5qZwogibDr_kOжڧV~3P]mhQ==7~2tOHk]o<`ڨc~^cH7wL=z Q;"yM#٢FDZhFEE(i Vd'B!"k~M&%-_m@SP]cybu7I$*wCB*OZkę/3i΄4bi3gSksLBj:qZ$}'^9WD?EIi+=:O+kN4 e%4 (}z4~IOw~K|[E1gSvu=Pg*vFHNHTRni,ͤ?\gvWS뮤/_磧iU=b%ߥkBLGs3h۳B*S}l)_3-EKY\pQp-6j~qIΨ ;'8K̭=zс,?c~Rܠfsxc|~Zy˂ۧ;ѷ."hCioS54ZЕcЯ #}Wh!kj'}S4'P^K`:imGo9X/=3%Q7} $"2;ѯ t߾ёP=-SN *O$uLu&|0eؾY?Wvݻ"9Chf7{O4d=;m\\#pUee*&kMZ(զ)Y;&V1 V^lYCֶutcIz m lj&th 9]1F*KN3.ps"w9]{s'*;SSV}2;iK-t k@SP]cy/t~2U%SFnי.էgB{-=T=m*Q<ƚ~IҨzyߧ@/n?Ϡ2j?s=gH,[Y@3G]IZH%T^wY1>ֆh[zki^tEZ07ٌ[D{ =b"jKDD ?=O&>j]3;Z|%-[?C)]e-?^MѸǕ3\ ^"-SO-kKDD@H994q㔙I$o0TRq~_xSfSn; F׼NXPbf\24~- }_t=r8*p8.]DS)''rrr 0 0Mß틒evL^.lyzM^6wFp0 0 ~PizwK;@wFaaatG;*=˿P:?6_x~_x~Gy"^fҐ?\23B&4X`ƒ /<[A'"$I$X}@2M~Nk pQޜԽc nEPy˟c"" Çs|@DD7ќu"zmF_>6""EK>8DUgi4ccTW喇iǪhDF˟|@eG݋eTe+6P~74]k 珽\Ϸ|{lj'UTMKxxCOX9Oϴ'ez1opV$?Ak7[s^UݗO @iΞ(B@z2.@k,[^={_]qV`hiX@M?Bh%ۏq'*c7ơ%/r;1$# />$IBMWOא~7&]F7R?o;nt;qŰس4oP/Z72J?S⫟o;ޏIHhs&<!JN,׾){hd$`O##1[JgLYuB]3ęH^'UۡUzhn}F׿%I~c-/>^6mڗ7N$YHʯ!~g0ԡn>7jc$IXHLF?Pk[`OGԵӍرlEj}Tw?h 99 öm)//GAAzc"BXGj4\0q~ޞ阵7]f[& k>w]qfH`* IDATS\G,鷖cȟdޝC^ܭO`>7_Cݘt#J9:lM]S`j@~ MQe/)Wzo+;pŰ{A1J>U_G{?#U:qa41(wPk1CG2+T\8c liCTmR;1vvT<~]eWI`L{;ƿY6*漱}+I_{+a7N~)U_ |^$<~Vۖ @s']#>ڬ1h`kۢiC:ނ6O6'DiXvwBvvk蛞'_=P ħ h5BT~|N?Z[Zz\J(Wd-;*B9gB5x /Z7w|~%5F$I~Wl&ݵbwӣ_| ׶F-Dc ut@En$B@e=:;2FS8gztJY5P5P_K/FVYZ*ξ[vߖDD?5}9^h{~.n+ TzSܑhQ4>?ؖ&njW;0Ч/OM#R,$i$CYNtZNTh`4eGCQ'%N!DֲJJ(mohbw,g3<2Ⱦ%)Q{f:{l'M{9yb@hzDsi)ڵdMKS;aKw/M'[0jdi|*r!۩j(I~hD[M˧r]LC4$IC{{-:ZN+mKpQ@Yj{^M/_ ja40Wk$IdKVMyffuojPGmvW1hhְt"1$cZOhQQ^M􍆟JBTc&+9"m+?Nv,Fv`$u:kRBѯἙ9& m20o!PCKR@Dʝڝt-[jz15ߍIךz$;f`Dr0fj] ՚ ?zJ4OGyP' \{udɂf~­o@o$=^(I׶k !Pz{'Rkh^\CjQqtMɒ;ȫwGE#fn򦭙4R:7AZ{:F|[g ^jh6HMn[ U >ڬ_jcRQ꧵ZêvaMa5жK<[A'"$jC=~~~c\ٔ\CTU~L3!SzU2IYT\^L>CÇovbPE/k3!W喇iǪh22cTvt9ݽ zشVHʺ{@zlyzCTv{=-=wMcV}o ?}R{ֲIhptM9.}r_V<61[>oHՁ_C| ̂hŨ>z{$ Iz`S~k6QmSW} ]%Icɟ!N{/zMO_1ЪSoCզBr++vb޼yضm[>(((@vToLBD)P'ٖ+ !Pzd:߹TFޜ;uRzZJF!c\Z_u>3[c$@;7މK4F?F_َr j9x$3B˅;6Dv(ucWnGuS{5FckPym|k?BP~V~!^ꑊ9'ː'7L@ /l_=BqՈOjGMG񏤎ZjYtIPY.R>!<OU[k P|P;(J+Z"ħ K; N_-h=- O{^C<o6,n'Uhh `wK8蕆2=,+!wT4d(>0q7C:>zWʒšxX$Uf2]\罁Z~qF`0ym\6б\x*jv#66`7+[є!v?u-~ Dž_;!9УSu}7̪ H^-]-bG;SYXf%I9. ¿ !XOKB_UI>:jc(KԲ Ԯ)?NDΩ0Lh~G teP4F?*X"XW랥'FW5^Ah\7eZc? 4,DQov$ly<KDwW.SK@?3]5ƬIUiӟ=#~'~$I""ckKjoa:e{QutCl>K34|h7)Ehκ]tb6/MrEOP>xKVHO%~`1f}iZZch^띟>]F=WɑlrAk߫f(((/Yv l?ۉ,Ş!$IB8XRpob+ qvBoBw$I~߷$]`!PS{(,6G?!v" ?_TQ5_+O-"b2gVF5EPW=TQZkVz$';Vj=㫟o;s7Ͻ L^yB\Y`1Y5}SH 3GGc Θ8ݻg3~U?OC: XKZv#$I0 Hs7gmW`OG@!ܸVh}i0%wQTfvl$p /H()Bh/\+AP^(KZ*ZE2dfdwy^9sy99sNΙ/7i֮zdϐjM@f<w_-Z?"zJ l zƠ^ڴXB޺h|xbڵEjpwOBDhv_t$XSq׌eMV9!j_dH9 BXM2ItC,%xsZxߠg5ɗ'?)1JW_u_`cTo*-O/S$}+ N0͵"ь?8 f\ڍD>u^\te X vLZ_:WJY.j]8s0혺~]n_B`JN |:-s`zA[kƏHk_h @Ōy?Wgc!Kisum:17Ť&=$wz@sw#i1W$hzŠ^i6j ծQqdnnM6!n+xiP'rW"D%۵ID?zh!]zN\Eۗ=LDDIwҚь}hޑ;{ۧzEx_%"2I# }'"J1Fqo,\nC~BϚhZꭟc?Q5!ӵ0#T2-U1ްc١UX{d)Ubd^/XVʺ(y:Rtc(FX%T ѧS;,u0|%hnW͵chƟQ_h"m O{M 7}`çO=.߉GJb7T۾OLTp~'vI+Ȯyrރd ,,X$ I]0fV=#H;˛Mk3fK x=$aôX虇0HM4I0WQ\ M%xYSJkF999<-_~_x7,F;辎6!&wнIq‰?r>l9ξG6S۴[eR%&tFX7hɒ%עyyyt:iժTX8aa0]If;L&2%d;QRNCWW؂7* 0 \DݥX}gȯXr 0 0 Qaaa& 0 0 01oTaa9x0 0 0Laaabި0 0L#2!ޟ-feMۡ[ ;#ڰnL4;fŚL=廾n בjU v)F?< Ջvd3tSdJ}I~Yj-%(M% 'R`2y-Y+,]t+ J`S=Ț`N=S[Nz = ~\X&6OOiul%[z~TUmGiޡ5q Qǵɔ@Y=~H7q70fz[fŋgiA4gaMA19i-v)F?9z &>MG/޵Ғ DX{EQ!:^^Ć^x@70j~F}b4N/P ŽcKž EQ㮡g'mwh3f\ IDATp`D}>$fxAOPuh>o<Z^!a$I~*.Fn !=BC[YB?1&-X$\N{n?\Z2n{N­qh=6N$sj"Ӊ!q90";$I*zm6¨͍_!Oi0c _x햮cݏIHp B8?`1[; ?߶hh~zy* `;;/EmjVG/P#>ɂ%۾|}uKG5wXdm+9B% tML$I0'vƸi.j_dH9 B9?Fx lmv Vϓ~M.$#svsRZ2ݞaò.ػ`˸=B@q9 lB AuUZQ1j~B>Ѣ%| )ǒ$32=ʥpnO4/fm;bX[ѽHFzW(tDBpK ?#~ޛ}&0}>J!pR$ބ*ܔ* 6o{jN+mv!`L/5C%ۭQi8ܺƖ4x'ջi9v)F?4f$I衅v:}pm_%BDs&=(2HnMzy^}w0~%IfUbd^/XVʺ(yQ@e}}:ɒ^7 wމy"7SK;mQz}~7f3:gvymɲ ińРĮ+~3`萓y/}T%$qkYuwc`3zl\8k~ۇuCc;nٰ-;>u|=.߉GJWQ$Ibt,?!?)^@v} E`4{lŞ1^<9fnzmIfLJ1}$I¬/ȆoOo?FZ=G ꑁk~ 0SBn_F׌xh'*RFΝi('''ڛ /:$73)rդ"@V]դK,#IV-YTTTLEEd 0 ÄngmTJ5 VL&$e@faaaAoR]3 0 0 sUaaabި0 0 0 sFaaa7* 0 0 Qaaa& 0 8,_8?.[$rC[omZK7~hvKk+4vudciUC]+O/}cwMqǡזlXG|M$ E+u9r*l|Xj[ɖj;L[!EQ"R_4ƕ$IGWIez&}cd2Eæ򷞥bO/݄U"'hehM4zhWQPӅ?(J ŋgiA4g&y |Z._k% (tҍX(ZYyaτKS^;IL)irXZ1Fv4a>;O[Dy=(,2hB@&LS]l!P}{(yD?h~zy!-j_dH9- _xUqo,U+51$;IWv285o8jˍ/KWb!&tcRԹPwȚwQU™l{Pr| X?SrRPԹ8w%l#tmS]옸fj܊_;|jٍ~4|:$mLۨ2z#~3)<Xɰս8c ]X8z86NSB|\?mnh-Pk T_ퟯ/BnH -JOT#!M7ie׶O]u]p+FEn$ F#=+z}e"?YNQ EP%BO?ڠτ8v/ڧt=^iV!ΝZԛPU_RVP\N[{R|5ڨ۾h:mZG 1ՖF%lC~5#M+I:zxuqN]+(Oᩫmœu|ʰ~gQ[ؒCT<>W;kd2]JeLDoTu|=.߉GJ$I6Cw,?!?|c^P F#=_/XY3Uo˓hl_Oߖ|FO?>{I]0f֠tBۿO$Il{*fkwH>W^m_ۨ-1/&&uC'=mIkF999<-_~_x7,F;辎6!&wнIq8ƒ ֏hɒ%עyyyt:iժTX8aa0]IfaF 0 0 0Laaabި0 0 0 sFaaa7* 0 0 Qaaa& 0 0 01oTa&ƑeDۍ@Ͽ3ɲvږ[=hvگ<6?Izf5JzjE4vudciUC]+O/pS‰Իk:%L~) Q=o=K{ebo^pa~J7;8RMk2?I8 %!^tld3tSdJ}L/ZVGUۑ`ڲwhwE )A$BDxxZ= ~qyl9I<4=n]H{>HK&Bsb-G7vo ѣDۥ"XOp}=o<l=w[@AtϘ[$"nw<0yYZi?]x6DsF o(B'eM妕 ڼ掾kCQ>x2nx,mP^o0W:ֽO^^E oBYYxBHΩ&cO'bjn{N­qh=Nh~zy9-5%I֓k`垓py\8 X칑kp~JW!&FqJ<CSQ\58v1ugxMU|B[gؾ~tMMBrk0}BقaY7E㑝f=n:_E4l1cQ!p_oyCbB?Nv0u9nj]$G=6Iqx-~3 isM|xmhtiok_!՚̞yXs,#K,~Ưmjy# H{I!M~oa"vVzkkKxkcm~b~z^!<.Fdgqq] ŋc׮]-TWW {"BP!Ǘ65p8B;sa+51$;Z_(j/O JdSb<Z^!&g@$ :t!l2٨#f,lai"W_u_59ogS0:F3| O'kUݨ NMZoۦߋ.7,]َIKQC_y7#kEU g>|&SAˍ+`BLIAOPvޕeеL]tc=q+~]`H:17j3F%bW⼏$wz@ˏ!)._ |R$ 3)HJDokU_m_`M=$o᪎'YFҢNqnOܹe׶B#Dc LH@ͅ&ka}J'392&s2xQ閉Fe9Awjm^Z f\[o5o +Ax=O?C@Fm7/꧷B AnJ56*At;]mœu|ӵn2.M2kOG{kίvi;]GoO7ΉKqE0噛Edj-(Tqr=zju GH3qu-9DsucogƓQg{}XznrDi+We IDDPH*x*\bWQY~izQ6r+.xe2̯W~Bl.:7)BK׶I_{LD4fRh`]Eq7[&TFgj3$IۥGU}se2FѨiRum5}k%""J1P5WKzzj An_7IȖywnjP-P^K_Ysu$IҼ3 d"Z{b*UL?V2g,!'^vQ@_]e)FlE(gA0i婯ڏq7lF̎2~8-Y6!ӵ0}*I"O3ӥ(BPs"ь/Ov0YaX7פXWú!iνz\ قCS~oh4~EE$m !OcW>]zBJ^ -)&OTTI]0fVoچiH3/6z=Lb˜yzxyr>R50KO#|Sq]<OӖP-3WXF_0xA(qB}KEE4ucSR^^_x~~m4hkSmiqݛW+'2)s@&/ם=FQL-ox~DK,#IV-YTTTLEEd 0 ÄngmTJ5LSB&=Lbp 0 0 Q֎dCF s?0 0 0 oTaa9x0 0 0Laaabި0 0 0 sFaaa7* 0 ȲLFEvdYvhbnդ%O=~j4gYԩzj)@lznݙ,W[oy= ~❐JN])djj?|٬6nX_m`Ӌ- *Rho.= F?<"7 ^[JCsbM]_7cFzo=K{ebo^pI#A[Ɵ5 XֱlQ[ -{vWԐ(HL{ձh2%PV'oxz fW]>MG/޵Ғ DD4}Vs+h;6o'Hw/|T\5wMA19i-v)F?ml !H$@U'V7E""EQH7TO~Fy"n4ŋgiA4g&yHPq h}TSw>9z=e]<(ZYIbW#g;R^EQ㮡g't݃R-pM[3p:Y(++/ca垓p+nxeB@qhmT@$! i},w} @CAvô IDATX}Y|ҢEI95t DOn6WO,!"h5R_I5I7?#=B\+‰WbmaZhƟ^b_x햮c! I/]SL_9p~2sb 'w6~VͿmxd`腹Nc5[zwX{BכykӵL]Σ05dޒ$y?걑H.m~UdYFj>XFH lj6o}*$dϐjM@f<㿅=k\hу;ZEMؚĢ~B'Bb`ohh[_,^vjѧeee(,ݓݨ8@HsbW,?S'v@7Ljd,=,X˶Ԯg5ɗ')1J-O/bQK+,i=\=DKQl$!FEøoy S(_t$XSq׌eMV  kJ<,xQm{qƗ+`:1i})\u(] ;dͻu̇dc=vQ@)9)( nڻ.vL\5nůEFv#dXX^_|:$ŏ.$a?Q>$Ik+1iB%46׶O];;>szx@ӵC Q=Æe±wq x!)}(He@T;݂;sW_Vh~z(U.=t@6KUbJ9$ۨT܈AY QN:AbͭA85I% V֔cIi,ڣ\7zMq'fm07:VVĭFEn$ka}J'3!^ѣ- e9Aw矚ǥfڨ\ 0!@My!cd`~x!D*]o>,s[r~(5^P}ݫiK[-`_5~פxU!w_{Tr܊>4l 땟mK}K׶I_{LD4fRha]Eq7[&T~Bz>/{F_M_k]+ ^\>#.lJIDDIwҚь}hޑ;GݖҏHҘӮqw?&e.ͅh=̄'*J_ e3:bK_@/Ov0YaX7MvV_ڏq7lF3Z*K12f+zDie]<O{F/'IS8:`cg'RzsHO{7L$8]JPgGKUMHt-&_%v*F3Iگ]M_ͧ;q0o6,f O_51:.߉GJ3%IֻSnt,?!?N^@v} E?$IHJ1B Af{{ОzͫmdžiH3/xi1~gymm M/Dŗx?qB}KEE4ucSR^^_x~~m4hkSmiqݛ'2)DWr>l9ξG6S2ђ%K(//EetҪU˩pSQQ1##0 0aY$EՌd"SB&=%u1Laa6xza޷3 0 0 sFaaa7* 0 0 Qaaa& 0 0 01oTaa9x0 01, n z]dIk] Ś^Zb]Xif{'i@,&XSԖSގX:RMk2?0j =}5PlV]7x,jh7}'t,ɦgޝb~VYHHO<̼ UB;Uq?^h3ZVGeܨ#eR%""8ZP','Qz"Fr?1MiiɄ$ޏckh򖳴p~x,m;0J'T=2z4}SPLjk=zKx2nx,mP^$IH}KS^;IL)+-q4a>;O[Dy=ʞ>(,226V9 ƉW]XhyIz}>$tV?_CW2ZOPuh>aYI XVˁٙx@$IjR᷋Ѯ8~}D?#"X%W$tNM59:{Sc8ΝĥoX%!W?!^+qBHG$$w|!n-Uzo[4i63zaS(XtM3&~=$&$ xtmS&  &;%I~c#46_26YJ dÚ86m;,#K,~Y[F㿅=k\hۃ;ZE_[)Vi]nō隆*ktm %v V9 Dž﯀Ş1ŋk׮}QVVY= ٍ tML$I0'v9!Ǘ6,޾Yfӯ$5X=g5ɗ')Ѱv!WV7LjN$!vէX%txݨ;o8B;sXm:wťQX$g4~CCv285o8jm~/.t,~B`Bg;&/E~{yU.9vL].7!0%'[>AۍS{W–9Bv0u=Ŏkƭ7y@n$Sm4G &Iwz B;bWO;7!ݸ+h;Y6{m. ŪѱZƥFEn$Sm]X`2',=^]?)pϬW4PyQ閉vrB҅xY9#v쁧l2o\Σ-~aI K%Ǒ9HL9~Dب4Z7L&ܵ?Bۑ$I>,s[rLU@z_j`GVuv4x㜰˺'P_B$IT0pUQ鋳}nb~Fy"τ2oy*i[$wODc9Gvoy4ex˳WQY~izQ6r+.xe2̯W~Bl.:7)BK׶I_{LD4fRhr]Eq7[%$ȗ ٔ1&'>O}DD$I衅v:}pm_0e5!UVgV h+P:QRƝfG4c1wzM+LXӯSwGZb %I"[]~Z>hZBw'ңw/mU??Q9V2g,!'^{ L-{\K1Lл#WWYy`5[+o$J+t݉6*g өLdaVMEZQH2~yS8Bݱ1TN;lz_?f_~ۇuCc{ 7}`ç͕.߉GJ%I}bbt,?!?^@v} E?m0)32zw>qtO!Olcm/OGjٛ{lŞ1^+g+Pduז~=3VkH>h5$\?dلNbuhPb{^x"5nTܹoN}rrry[Y0`ƒ /2 0 &Q+IRl3ƘL&2%d;QR_rWFF"І-x0 0 oI@K7W.ސ/`3Ufaa&V 0 0 01oTaa9x0 0 0Laaabި0 0 0 sFaabY @n1,qm8aTݨ,%4T#F KR\~zy|'= ~F}@M_xzm) &5zJw}mWJN])dj`~W~ֱlQ[ -{vWԐ(/Ծ҈8V~oC7(im#2Y{a؟D#hJcMA19i-v)F?<j{y}P҅qCQ_xLrnO/sќÛ1|T$I 9?w/P ŽcK$_웼@ƵPjOWE%R<ڻazv]mfW{<;Z'dc8Fa,A$5Igd U7@ꃰFɳ%Br`Dv&;PFU$I;EXЛT!&F:ݜGΆ_kY~xOn;v^/]SL_9p~2sb 'w6~VͿmxd`腹Nc5[zwX{BכykӵL]Σ05dޒ$y?걑Hk7Mէ l+/2Rg<[سF! w㵊}g:5^^;]ۼi@$ L[!p{o2qx-~3 isAY01#س /1h{AR(,^vjѧeee(,ݓxaYMMilJgAK#csįQ~txPX0޾Y&|OCbɶ/U/ wu'DurA 혴u:{?]Tպp`21uT(߿V nun7N] []@;&ك~RAn$a?'>ȗCRzXIN/AA5z}Sk8bW[ ;7vIZǛP0!;:'tcKoL0NBIߍ]ڵ3w4Ǘ6yjXB7*q?Q H>He;PW/4濊1(+3_:뿑N}q<.x<*ե_m_`M=$o!fQHU7O4)fmua tuA`6ڨٍ~z=jOJ+z}e"1,'@7 F?<*d+^NNU1ްcQPWթaݐX{']=t͆lAv!CλquN7?R} !OcW>]zBO'#5Ц^{^/XY3UGw{ liۤ#) 1ܮ`ƵQk3fK x$> F/mMh6/~Dn~kXF_OTƍ ;-ԩQNNN7OqKyy9_x~ KM}@uHtofR\Qaq=J)i-YZT6//N'Z gQQQ19>2 0 &Q+IRl2d2)!ql+g0 oTaa 5&0m L0 0 0Laaabި0 0 0 sFaaa7* 0 0 Qaaa& 0 8,h2wb&Y$ˑ_4Wokٽa]|C-d&SCi AdD5L&NDj-4T#F KR\~zy, E~:x0ZCP? Ի3Y,6~o*-Cwqqj4gYԩzj)9Ru4x5/]}!^@dKϏ|ڎӖC+jHQF XK%R:6R| w%(msԅmǷ^@жk5BY/6{g5%}2/(goߝ!կ羨dM{<5ZoBYYڇ i},_h0<%d U7@ꃰFɳ%B-X$\N{n*B1~(~kuZJ0$wlv;snō@B@$tNM59~ IDAT:{S$Թ(^c?#]U !-]qǎ3޸پ~tMMBrk0}BقaY7E㑝f=n:_E4l1cQ!p_oyCbB?Nv0u9nj Iٍ~5Ör.↔dl)C`3=ǒ$AevEM$LR 왇5p]^Zr-YRƒ;ZEMuYi6j3ЮpK+jܚUg{]ϮQi{=-/__ۻ(ʳo̞͒ #)Z->֏EDE[^ִBXQ*U҃C# (XLZap?v'3{&ُ3{fkg MQ/Hou֘nUUU(-$D~3 < !l&Gs] Nm:O]{f/\,MMi Yj%~z(sT0W,,6u1d- 9:"~і.V,~gG#j\hK3I`N뉊Π\'n-;9\v*k.㐪B`HV^w֫Фջpʼn%:Bq TzcZ|gLf& NjK`s|B<;G׋cž7RH꺯WD4ݨxou1|!pdpV |Q ÉwW!=gDz'}L}wC-hZ:} !_n}KTc4W"Q\L:8zjr&ٲɎUIy$7*aʩ^<bG>n/Ayx乤]е6BH˾!Bs %o9)T*".oεc[#Þ{s8!AʵS+p&=T_}_`˼V}.I|:㴛e}=&tzrC]fťss^y !pBe]Z\^ja{COﭲѿW,-ceKz/s03^^\%*zm՝zOlO~RScM7kyv9p:k"}kGMjD%oT494f݇T>H|JI3GKĂNڮ4Mj6'Skf$K)%mcT?l7=|rх!|~z,w@<>#~і $""Ixj:d`tz/L͗X$x뾆z|9z%y:RF/z:k*h.Z{QiAezowiƟ {ޝ?As^o=m$)hkNSURm~7>ѐ$MGaFtF~7v822>Ө2,{'k=/MUsrr׻K 1N鹣^ ^\ܟЊGh[ʉi=c&PYq֧7^I(wte 1~+6n53HG8n,ѥwf$h>YҲ0h[[DQvjhk.㐪\ ^9>)RX `5[Q0`(p}nwMu:IԶ#p-ס0,ߨQk7uw&C$L{w*xa0d=( s0Mj;aՑfT5G jFnb+s&'C¢j=ͷQDGQ> ahjD99N݈/i DD4e05O+ F?YOYPFmx?~,qaj}"OA=ƭMu gi鎻6хjm?_Wii0IWQS itizq`1rxmƧ~r}{J5j?ymFqMYʽoHm; SS] xI?;RYv]2z0ZE~mpiB I=+ \?uB +>t7A&:!aѩB֣Wʴ3\y8ݐOC}㐊d|># hߩx9X3x||c Ih1tgtt*#X⧷܊\w2;޹u !k`﹦<׶r& !=q˖/yy޽處. V VJ5l;0s11m=SWg~Z=Y,ȿd7mGRz Lz>H>F3~@9nʭȲY׷+>r&2zǼ|uhlvlZzm> G‡8\hwP7lB;7–9%s/[?iӞ"y0Zmjϟ[pݨBi45'!"MT P:usoAvBf/|&Ȧ4u{ebXNz•$*z>ӭRxv"qHEE27&EZ0W,,6u1d-h{%f$I0DEN6OoK"U!kI}:oU=Ǎ1Ͽ5i!YixY}]8DX!LX]O*W=G؎zس&VE%9!읉 ű]Kav$uÁ+vvin<㧴5q;-G%']B jܗwl@M$,QQ=N&W !槐sa=x$*xpX {RQ,ZdY΃3}CD g7ڱپܛ8JOE ck ó'ϵ*BF_⚬W_2UKd7p~Y5A^o4Sp|d٬,(}C=W:Y%*z3~J[bs&sxaKKd!?ΙpǴ?͈Q[u^G~[F$uPu.䱋$Q?;*V\/)zhTJDQ@z'V>=ѯJߤFo|2ufӟz' YOo+x,' ~$H8\L"锞;nxR|$I]ʃtey/t?k+='b4uuzrR:rW> K| rk֦cO-!<"7;ƾYv }raeGɜixxa0d[dICWy+Pp'hxzQaaZQ O"ga3>%Q3gr4ݻwU]]k_pچ6 _IuϺ;]2hQ'ݓR&rɲL~U *,y")y?D*,6jzr1ۖQyь;T>n$yf4_!nxgYLEB/qH޹9rܕaжSuR_[H׿ e4bWdP~+h&_){$$(De4w^:48s09\}M>$IR'p}{Ju=GW4jC[dՈrr_ݥIwϡq+wS]Y`㮍DD4_Wii!JcIߣwʹaW3o0嚳mSdF!|g)GR#>*ζ]t,oZ ݝ\t`v7;@I=+ \?u5}\yYENA$!"'hwycVǀ,5%~B9Zby%: NX3x^|c :B-dKw, Ofz?:e$yXo|!; 6l' O8$ !=q˖/9y޽處. V VJ5l;0s11m=SWg~Z=Y,ȿd7mGRz L:_%IRsv?p_̓%-?yV}xuhloտuSnE͂X3h"2zǼ_M(z($n6> GEK?}~-_`Nm=J8=5i\MBCo§;!-kZ>z URk4bіњ%̟?@s,"}\Dۍ*NSs"BDJ~3 <T^:usoAvA宣 Qxzc \/h'ig3. &Ȧ,5%~sT7^9زpŐM6!ܿ=,$ 洞FזQy%~ь;rE*.JL6#9݊.W`k'R>~0C&*C^Vy'*!uw`J4xP8Uhv{ŞE0z'/.}!`Lnx ^/Z {Hݶ#_u^8eL\NKl&JTrf}yW}ӬW|8*] 0;vF$ |uQߖ+m_B3Eq6^Kˏ@#ˇ τȾd4|R6G/~ꏵ_J|A<D~6Z%QYreT6'*>xsڃo~ɮ>B`ޠ<<{:,Ӈp"6O4G^w ͹v,~(<>l_ {l*dD[ m |]$hpX L%;*0~5-Z$IA We>2ܾE{VM?,f3zue0JTڍghbs{y wLZ>&sxaKKe٢(1Ў(^(+I՝zOlO~RiuBe]Z\^vB`wPы_cׅ;P _?+T3|%s{cOVBSwSd~P-)\@Փ[3{Musc1K^'0c1ƒ'*1cÉ c1c,HDic1cQYY9)~ c1c] /_IENDB`RunSnakeRun-2.0.5/doc/pyaccellerate-64.png0000664000175000017500000000647413541777402021673 0ustar mcfletchmcfletch00000000000000PNG  IHDR@@iqsBIT|d pHYs^tEXtSoftwarewww.inkscape.org< IDATxśypTוnhChcl$@mLlf8$v2TqةSgT`$q=@Q)x%* jgh#ByxGUbho!x xq(4U0Y`(넆J?%+` ~hvڅ=a:?9w++ kF04G/G1=6oo;:HJJ ՃH6ruXc`{L0x+~NImm NroOD$B!v7^] u0Dv] ^bgzex6mZ… yjS#RY32a|1@E$'E18l^P9"2ōFǓ}dyy]> #R4|]w<DPȥb\SJrr'55~w$d"ؓSqDXTB@Md.]̙q46&QQU-Xb(u'[\E,=;,cZ\+"Xqu kvhx-Ɓ:D6FD2%t.!~i:0b]ru7 2qIJ$G?x(^MȚ88yT #RxMqpM͡eDKaUXY@tnR!)  FT GN=:ꇖ&]nX,=V>A"g:yc <Ƌ-b˿nj#+X38FMe jn{JαoECxELiH=Y1UED6[KĒu;"ѶTNnm\/mI>At35;t^ 5n#[UPP3W =`ۅMM#;񌿜Hf]}E);h 5B"Oip ʰ"# T {xs)ʦ2,<]^vWFDdU%o344ӻz8:`!뷸|2b}&徨u1k-6)|XhJ.:^o;bW}7M We݂o1G:,"Ӏu@8>o{װ:wk3.SVo䞵"2QzJn=h@D5"q+p ]&ܭ b;!L&0,.Z q{Z r'Uyj#ݽ, \"b+K4Ղ>SՎ}] O݁K G^FE0Ef_čW:mW{g.VdgЭYGwwpK@79C)ち3@'$&NJ>=:% ->(Љs9z@~[Ңc*%?h#%]WVy[D;KSO\nnF1=w`<XUɶmڵeȭt/R\VEsؠz xXYba_h5(Pbhil Kx>T8 r(]b Ƀ8W'\6>f+6GcDPDEd}dD =u%KE:mƱ)EQLM#T!ѭ(ytwAeHip52ᬙD.U=#<$kW  ʷ1"2 (֋秂b)n4oOf>aX"Xp$!usVcykTX|?Ȇ2D3PWvo:7 .))^yJD Ddd:1;14;ed=='H̀kHn\o~H !#9~8?C8 Sr܀'h"˵T;Ή}TK{ū"Ux$\DH8}T^@'UP \UG%⻿G? +b|a&L iF>jW[9b48 cEdYDR^uƋ okxgah<Uݩ [X̀ecSp5?U'>?⡡D1|E)C$=8VJ 7S1|4job7` 9(.τB< XUUDc?B1bql\14=5;P)R_'/ͩ {z*U};`CoƧGX^5bl_?& HX蚯"aSp-|πjFp k*8 No73fбuU2>1:wޯ=F4:sqsz???<2L7?I K:깘0b&u)_>禛 )m:ZB81TGzUDp,>exD~-UmQD PX1l4ny)Bp vXbQ6 lsꭈ%UnA1Ƣֱ^5l%@,/v\"No'c2zvɈU [½. 'h |j}E=:?_R1f IENDB`RunSnakeRun-2.0.5/doc/meliae-sample.png0000664000175000017500000064102513541777402021337 0ustar mcfletchmcfletch00000000000000PNG  IHDR-sBITO pHYs+ tEXtDescriptionWindow Class: pythonɱ3tEXtTitleRun Snake Run$+ IDATxw`TUs_^B""" bc?Zֺ {w+tEEt!Rz'3L!Y%/w޻f_Ǯ.hjah$ԛ9'g=\BswgDigw'"U?q[rQQ.EdIoi~O7LNDĘhs\bwm\_/vЎlѼ}>ZXJxQ4¢΃#m_Pħex?~K)j3r"|v` `]SU$Iۇ 3LpTEQHNIr8QiS-v#" j&Q]dнS |I$g|JXm6\1hp?ǠSSR{ nU~LNLN e8?dJBNNBG39 6g\WD9Xh =0)9XQjiZM]uZMt9RRgid, }V=eYZ{o3Ya^ WJ]I^YŤs]O vEѼ$bo!DDڱKk*.zQ0_9. O|}^|rF=WQRmjsTvv7tԹK'QjWG=Uf2'uNbDdE&-wj_[8(̉dٻbӧ]ݛriNs^#U&}o9msdUaYQ\^=} [q?59Fa=)C:|W>w{C[ьU~q O{}^H>Y[sw.__mq ^o4޹K' Q Dگ9vI*r@9D$bD$+ Ԡk>1:ɥKʶW?\Cd'"- |6oaE[7QC%֡= 3u<Ͼڧߟ߃5ɏu˰'M`w٫|nhXW}HzDY^tC(8n.֟ ^oK޻[鿃V%Ik|]9A,n^$Ib}{*̀2ew楝>nyS.9ojC(eM&IDL(>\8w*!0f@B{x=XK[tr$[ŞqvVw[X"/|)H@Di7抗$w`Q鴍3k~ܪ!޵GUԮK\1a%IuI%"ҵ nXU%1i_rUuocր 3}Ɉx.??DhirrŔweYVw_T>msс-.߯_nOp2|5`{o~ ?~X'9*/?r%ʇV" i[%8,{ufVkۣgnm/U\*/,R~+7X5p Pw`L hP>t>qt-Fag\:.aI=VO>-ګj줒c_62ko*f pSl9{odpk{@tޓ#tp钃S/uu~Ϸ̄>'N>wz ϽwvlE5:ݺwk΀.mrkl}yjEQ}mր L}\eo갡'_7)e>umS&>(8UUT0"ُ^+ lγKnt]Z__~_x93Yg"ίV_W?Q ڽz˳UK&Ԯ>jϦM.c;%&ėNp6 h~q~ޱڷ{>KpZG4F!EMgӧZDZK+ֺnj LQ*ױuC:צ>M%NEqDҾjpYҢum r _Xz@ i k@4m[ABsw& *P@h[~zImT7[zeW}goZ99M׃{OeU6q/=퀳&=9't49Ψ^|&>gd-[7lrGbfqVso8ec0p|EGЕ7M̙4v9de`msL""3ggOұzo\8u@]n`Ȯ#5[;Tla}-Sg;ʾw*:uNGg8LjN۳:z՘0#{#9<DE}zn3:7'Oś S]θc]:>"~uYI'JO_Gbͭk@+iF]k0⃛1+uӋitޢ ѩPfO vψ ٹ`u=̺fG=qw)N=碞bK4N~s: h:8ph80Q$1i/tآ6w k7ͬ^l>J f@@T}(@@T Q4D (@@T Q4D (@@T Q4DTo ιaeGA$Ib5cPƧrex@+SZ4f\Y_^iDyp6uWQxvDc"#G%!dbD=9VQ gD\Yݹߥ[v}vN^h]7va c?21'Ҙ])awK!tܙثl}t&7|t3@ZZBVPQ},B3&0AdBk$6&܅ ܵsǁ?,[0;;svzymŏSRhKܽuYM uř3nGژ֍g5;&hXς+p4$6K,K>Ͷh˗/:Oy'&r5Tڴ$#8y0kSB1C%'k'qz.Q8kvaCtqufb{,dc"UWZx8 1Tko;)c\ O|I'h.6tfne˗Ks9~K Ϝ2ib^kׯ3}b=TZ7jTxWÈ@1F*o߽_4^ti1?~CiHѿq>tpO2Mk۶هu>K%HճsnYW.Q_崥uG|G k$ֿum9G-^q_}5 #][o~ ^o2LGvN]$0F1C-ikq~9&VEK1qϻ{֬}2A؁ ȸ뮻z꩕+\ݻywf$ 1 ?$1Qbh VY;L0 ]uMucoQhM3X^trvӕϺINF-s^}|j}g<3gw?ao!OtuOb_ Y>u@tVQ -K)5Y{QtjrS{,h~p\*(8u fddu>E_;t @%Ƣ_rK<#$H Ab"V5'asEx#~R_7&i)+ ґK0L2tC"s󞼴TGα(FUN}^5/yRgH;z=?{r$MuYDd:S{ DDڡfM":?*ιl|F@d8mBk5j"+iQ5k68|ڀ?]3"9eDc{\8uuc1f?FOl|''s+)DDefDik"MWA;uӧiZ*˂8Ԟ ntޗ 75MzJnfbb2 6A"DDQ pnq4HE٫?"QhxMA1-&rDL!A,r9dXf0O\{XgӬܴcGV=p- +UQ 3(A #QZ&BIS75uGԱoN/]N߉LjN۳:z՘0#{ :B.-KZWL09 T{ eN+VuS5 L̜cĦ{+8[.OY??;*]zvx*mԵ1lc>/56.k~g䎍Uy|kD$0A$D-"U_\R\.GP,M;'u ,.UEKH,4tKU)7@n^~B{LORQ"[:\ݸJIv9C~"EWݛUdpIa68"T5ZuԊn^Ƽu;Be;/V~mfPnQ*̨itޢ ۉ7~Z;vxFgXǩp?X .ieELY5-DQ 0tvsMfYV #G i.M)bdRX""F$V@U-f38K#LjȼU"ܥ{|$LQDQ%fSvn9^@ YLw*))qH4*&_"ˊ$DdŅ?6.Ot)3a-P87yA)ϙu͢>{l/SzE=mD5+JnwbJru*ῶDŽS?<+w3Q|aFQbK4N~s:g?NāC-"Iu/Qb~?v9lx VeZܧSȘ/yK& 2X]qFn~nߵ߼`׽˦槍z ߋKy$\4Xhw\IiI)1gL˦(&=qۘaI (1>nh |< ˥?PZ6E$ PUDugҀX-5mCYUWuղ;2;H`"rtBs 2sjO,̉)W]g[Y"f$3EQyThc;(2b:Kdq/($teMGvґ(R|dWOiwwH@î(tI {-1&Jd]Q$"uCT.VgWsuٲxWS %H,@l,`Y&M&*Sy_,4 U/Կ^q~{y 0Y)'pe+9Vέ=T'eqHF/pߩK?Êlg!ǰQTlvrm cPHٙ%.]:>Xr IDAT|$;HK0Ɯ.gN),7F R!vԈ'ЍVG1AZB9͊,G$}GN;rj4 򕗙uLk hezc1NEGۺkb: LK%Cј*\$Q%n3LREI2˜ULlۺujY<8QYE.QTttĶYQ}5V3HUN(nR}ӏ%Y2($K}k;sH"A>ciSyQƬQMO޿[n,ک !*FƉ[[e&#fY3Da{cEQD^%H|%xf՟>掹MR\V{}%˙ڡMQ q͊>+!!qx< /^r Ͽb#x=ppD|{Ĥd&2cn{M=#{J>x YGs[V8&,66gtk9?0SDtňiԧwCȲIPәikmr9gO:㕅;opqK d&%gt3[翙IDe[8'VFFK"j4ԭ)W8J+MDC}Oh *P@h  *PiS&4w[0[ T֝n~MSSjhZ3rZZ 5ZiS&Ϩ>@K3u-4@ UV}hBנ]ZUUIjG ޶ mCZ5vj a4wG۶!޶ gUD']4>l`d "m aBPl $B&Laiژ 5փUo;]wwƳs2%TUE&^90ڇn(V~ʉO[W.^v۞#nHO;t3 JQX3?<6SD|~?o~V@ci"dDھ~>^fK3r7ͣ?ksTj9uޯ``>pnܘGބ[}.r9i|c78_P'$[(HHP .v -SV Vڑyk/MѠj$תS>Zqj%6 xܳ>.z?~>ӺOwxۮ7G7L7qrLqSZ=߈}uWhKo˾cʒ!}?lؕ5YδHoY^k~xva͝e zE4=.g$; |ђUwM``w]nΑ|AC!B@D@ hϐ

,pteKT9?eR.]k{o woyo猼u#>~\tb'4]1NH:IhCߛk_}븳.}vG~M-%W}C%|~{a/>ɶ>{t $^-wG~^"i6מ[u#wvϿf&dlz_wuٱ]?.[{HVg&4u{oNOYS Mo>pG[˟dVo:^z_owoޡa8uۅa7vZܹW*]:ޑw<{Kg-O__p+Q l[raGƫ'`<"~ۦ?F6  F"!@{RȄR> :s 6V_^AݿNF$:F^w6ɞ1X.$2]]4*-VQb{/>;@L9 /?Pdcmqўgܥg%X2u敧96zobdQM;q6g-f@X[*ykx5%${b \;y&yt͂}!bi/[AB{~i3<_K'fAC0^|eWwb\?QJ?+Kq Y թdҬ4[ щB$Y4wSegJ 琢`7R-?D - D $ B  -SX%5N%yn͌aܽeٶFtҽ䎔{vWj~:)nb+'lx}oPeYc٧ VmP-E %L2bݭZ䊼~-^ϓ:ge:{M/Щ3.N=Lh!=RbʄKsgn_G/>CN3h@$Y.Lh9p#Q?4$[(HHJ!Zp槇_dCGtt'_*oY/ڇׂJ7;b>%^\-iɱvY`oUYRE a@jqIf0`۠z2e, BLod~d6y}Z%SAM>}G1oe)dAW)nm|ۉSotG K(r08k HH!op!B@D@ hϐ

dT%Y3J"!z ; >S~8asX`F]o,ȯ|At B@D@ hϐ

+|n(V"µNK\J{㤟^nv}헎NXfe͛I =3N;;֤DfϰqJKD$u<Ⓑ?ǢBȞig0 b]|_|h[1.}خwS>n_bZx}^539ܜv9OIӜ(I\>V!bM M&;D{!qmig8qntx[!Y2SOx{0/@[yJL}̳ҚcVpxWM~mg'~)~Ws4MPVٝKdcDV7C3y6&_۔&" 1P'hjꌅ3qZQv R,sZ:7~׬-tOWe^pWcr#Pwv/weVQ0'ڔwaxb:* &DSM)DŲ 91qJPSRM.)C\j˖s(|E{n@r648Ȏwd_эg5#eG©ޒsM.3m0ٚ#4fX=/ڪm aBᲭ| Vh6z*l#f5o_][lV{ 9ע0OzR[hM-x|w=n]lrF^9eSyw{ ?Hj?WQPHj,[}ΦxK1[\j7Vo.[h0$ju -sgKvڍ3OMmPͦiQ۶!޶ w>K L[YfDde辫zLyoVNDd1y,řgQ;\Ic>Uʾ58Gܡ>$lDsŚ~`E4KP7R\"3q$,UaL5o$Q^L([RfBI9YLJ.VHUvqb-f[( \?+ȢBehFm|E*Xh^d7Nx GnSU&Vs.&+ 盦W{g{Fӽ%=m-怑i-o4TbZ4DDT`N,Ay * f2۳1N U\e5j s!p˶ꮎG$OMj 6"9B dYUmC|ٿ6dSCojdYVVXAmmo&X/:Zޛ<%}9+1Y|\حs=-"8>\أ  ?YtKlf'"sYL@L&ؾV1aWLdĉzińW@R :nk댕~G-F)#E@DX~w""7$Q,"A㖭Aw3J^0I>-u?@;(ySBJU%?:Q]Z1Ӭ@`0elB`rA\ݤ4# XUiYĎȎw+&qg O>;j]ֈ7p;S݌L| =\`?1Hݫ&5b>WK?Ble[&#\ L OYQ|Y]3rz^Xz`)5籠= Q]sC_`5mFb) Sk:_Mt0SN{/jq-Y`øyJʕ/.[ͬ grGS;OxWwSSDU-ps%zXM3wJƾ9D=Lk{ D?ID L֔0a!Dv0"\!˶*$QOp  <c@ 0e1e?S3n)~Y3ML=AP-I#""|D2vTjץzS05ҦOlr_wUE9Z! )T\=piWHo[e:?Cb1yEpJ\wǕm`e*ML_ UsO,"!s|vg܋3jai ֈ7V>2-m3~ʨگG7l=K= x s^i0%˶]]5v%HVw+pff2Ą|A^HdƇݿ=(.V%3alnLfe(-=^p,?(H[+23[HR˲1QY#qlĦ DD?wŭ</|x_y]2&jZon$(_u-Ѿb#~nL[2<~5薑l ~sȄrHM K=b^ t!N1 Oٍt x% Be"/ۚ$OJshYLhP&~G]ڍ'XBmm[@?]J3q8S=Wvb/cƹDq:Q5$r` IDATuOz?ɈxC=#`|d`>Wlc\#a zcY]_/_ٞsŚ^w3B(X_)8>O2o^*O{+g\SQq.v:IX{zJh+z$?' HdDkLmC#2qoFmCo=8D,CZd7͢[u)+a ZAm=I/۪:~XA942a+**}+JAmm[@ԍ)@O2~i 9.UgBSͧ%[oHHm:H(Lh|-@ Qdua2DUY9< (-o=xs#ಅC@֜ >D Z:f<o|hoy;8ڻvLJײ{_fa/9 p ]o[{~ņ\k+C'Yc~:Ś]:: x{fL hdĽ;?yg?ߐ g=|υ]!Qiu稑 7e{W_;{QŇD5NKKpW\>&D燻zQwzێ^!e];ZE`K.ۮ۰`g_xg~zwW;?]{Ze;V3{.}puqTU^[5?ʹgk;6/9s2E8Z9jmghykEP3b'} SZ9!Yo<3s|DD]Oxf $o}eʟ?nċǍsŎnx"">k_]URƄZq޻[}cOuE)`o`k97bD~;_Odj)Q#oPw>C Vy>Uͽ;>Q{u76~:/|3zoxn^[a{-kԟgUJ1&^t+>`]nBLx?1j[#L`h"5 징Zq,Ww>CKUQ};c4CE'3ws⪭;||{/hl/벇w eޝ~Wi_7ݷwo^o?'CY}`fj >zṃ{V|7|7<͈sv R)Grz=GԸj9W#e+>c3[s_Ǘ^32N_*:#}\7[EUP핽bvƔJY|G#pGT@[r~|P{mQhSm.r-wD,"vW{/M}s.33ߡ3?;w?]\2ƳH}z饙}v~pDݔx|,xY$mIEBQcC o.wr#vG==G3΍BLMR1m㢡%ۍwGL>{D [ػwoL'S62;7T5i[\~h㒛7귍ʞ@i\g;{=f52;aSqi񂢛ZI6nlٽ#n|Ű >^p$}GcW|шVۓD5q3Ƌ2W5<^Eq׶lC%m^}[*Ր̵?{o Ek9.Μ?󭖼s[Y"~+彇[k".~jٛ mQ.Rwx &r;-sS>u{7e&w~<^ \kifi Vݕ#_0-ࡧu3*xUǧ~:eKz_ڿfrqiq6>x}P:2W\CdOs^yo-{86.Xx%5h?tQ!Dlq;?@D=>:X-*cmAԒ}Tzoopi|BDI#lNI,)pϺ+Кc\Sf%&yɋ<= Wof׋L`^Q݆MYЦxػU {,k7 u<_\aM) azR׽=o`x[.FˁC.5oV-BCCI t.^JVwi˾[(.1T#pV x$03{;8$IduhHz_Ԟ"+5ހf( (x袙9WkB(Cޅc7>ڣD ߝĿ0#Ώg<ܻx/W%O{}tLLtLLut19tj3'}Q땟NާC'bhF7Kgx%˕سmtLLtçgdݴ8d8e֨wDĴM5{I/._g~X4ixb|LtLL=SݻM6[{?=}z:d0 9+94sx5y{g t ]ݡYI/-~~z9s,iU- #ǫ79t}zֺU74۽z'nfI`+R\ {~ΌntӞLe^5/}@緟yG^\+>͛Vz| V*`ߊlqYV+_h};u@0W/=6U|&yyjݷXq\~BN,y U_V߇E: ~--Z6wt g4۞;&Ϧl9q5uM4 &Ñ G.NMi 1mn3O xK\6}ҞҧBU*aP[Śl [7O~,j۟+>>9Ol@@cG< >!V ۾F1}[\?xRgS6iߴF,QM;{"O=!"e&wpt.a|T4^o ҏԤl0"˗ yys?0/Jʨnæ{ehSyuHw>?|3 z"MCnzixw +Z #6^L^^^]rP] lo` 9p{xr rwjTX}?%} <*&P`L=9\7ul *"cB.?xԩJW@su O[7#\?: ʃx:7husaH*`^M:_,%8/ȘPA ?*I=G@r$IrG_zP' 4,TOx\Oyc ^8ZV ;ڮ~P352;?sd{n{􌬛6+?-ݻX  BoSsuoh:{O1ļM:߮, tᗖ}?O=}=:_%ەmO.=`gFHzpiO_ɿxg9s,iU]ԝlˣWCcUAcC;?@!s =c1&x^x$P3P7րƪ,{|`)5SɉmL_x>;֩ȔaOĔ7?geƃCgqG'5|l3x CD-z=(=iQYL5V KJ>H}q=zW/Bn`4&V%;Xyjo g\L/ʳ6K( =X_ ߾D]:p(!Nlzq11wu4y͡|J翝bbc.?3ӄSS +;FTéUSپTg֋?g 0h: 'Zn{?^#p.@5e ثsUZLv( %CKJxʗFTQµo&N=|o{ 5_yR_pc8m8-cqyWgϝ=B@d͍>!| Xn_<[K,l_NTW</>q/wdF>\2s'H|2h( s1򾀞@J᫖{7U(9;V5on 枧psK/nO?&&g(&i$"",y3ۦO[Գe4]3tƨϊ)>KފDu񊼁BUɪB9^oۣƵ jq@eTR"Z~2?̒ۍ}k F۾ot[˅_#Bf'S׼ڻ~՗\2BE1tpp'tpO*bW#G hE!ϵ啙k^5YMW~Krȋ]~9y[-y񯷲 D\V{_J>B?#go^$Rwx &r;-sS>uor{ue.3:7NTk3^R}5/y^iɩ?ĥkWx Vڸv5,/|ZLmO!ڙچOG<`F󓌩xgA9eUV[^`jwh4ɚ ^~+/Ϳ%Yv'?åp#9?dN7*m7nb$J| IDATRG7` -H?#SZü_S/-4YH>iĂ)"}=:Qx͙͆\+) MNOQcoh}U.3ӄDDtSt K,JVsW?8# =- 0Izޟq<0˫>Ԓ_գK]` l6^/o4O>Xq\~BN]-kE>`gA^ jlhf[)@J2!cR597MiZbTM9lb[&>aA$8_]/(X!f 0Fw{:MZoL)Π)upKp o목T>9MI nG 6aVDD$2לH+X5Ij#߭ BQ}6V"2* $eB*k &}TjDD"AfY:u%"4Bn-Ԑ ])/y`K=Ria) 0_'8(.lR|QZwNȞs#C`*&&zh/h-Q| *Eٌt[V g"ߐ1M'tVOݯR2NJfJf :|2A*J աgV)ZTM r*- A@ jaM5g":PnjSZ̃5*B4M1Z'Y[BSKoyYyQ*g m- fa_ˬt6 m,e >,p.MzJDDwZz{BN"DT3A8Zx]~s(E Pz_11:YOs`K _Z̭5X Z.9"Jr[l #@DDR4/(d< $DK+m }_b6bF&lʐ1r a8Ib$"JЮ^n%UTOOtBD^i{KM;95-,C.Nn}gΒXHٴ7foq^gF8mqu̩z{US #6^ oL|}$t,uoBAWK@P5.jb Ԝ?>=kݪ^=k73v&"1oaN=8{;4 3?;ieS%ەmO.=`gFHzpiO_G͙dI8tńj{}z69^ר` TACŰTtj,,4Q&yx&p9 CDbomo+48.eH:Z ,zp;C4_srBGJ|* ECXXFEe7$eB*k &}mdq\Dc3(g[E<<5  &}?'G+ R>g7ndda7=obYHNDn3`«ѴN=D {"l5Р=#g-3>ԧ|l3x CD-z=(=iQY\aI'2W˨z89ר` T2hps`(ΝG̬ێkkQkI) ZKdbkfJQ63]2j7dLIi&]UD"bÿt{FY<:CU2(]V.Tj 3[Yhsr216eVHD&6d`Ϗ3f&,DWЫvoP]2cbb>hC_Ώgm翝bbc.?3ӄS|4֎+bMp*gD0rY/7,0˞]U6^ՑP;>cb11wL_cU)FS;Q$I+Z[lrɜZjɬD6V=k`4%$&d+d6"U~-3ڈ\XtV]n7EIwZ6v|-KY$a$sXlo2S8}3yt{7kly#eI}ҍ;?Fo[[?q|썇W?YsϬx5ďhz.W,T*|tךXeć`S\ӎnSkE C/#Za:w^LJOѫ)уŏ'b*эQށG3c7>NĞ_ .^P 렡`[=hkc()m1Dij]JѼP$-)~ieRmRMƓPfC"ǰef$!tgۜJBHٝVsvRiw8nOIR>u5ɘ{&yy]\7+QLDKsΧe$OFg"4}&"wg"B ^ >HYctN/f(DнWB#X)Q6fp^PUmˊhKo7j-hSm.r-wi} _L}j;uӫR9cGޔo9;47-7EBs/G&G^>Q.gLLDg4~z~ "O[> TBqKj5bU!!&s,1gUra^hdSgĜBWr`#`ij6s'xJ\-#zkUKDÞvɬϛrE3&'̖6D,'ޠǚ}nW`&Ĝ4Mey*h-ҞI6nlٽ#YͰ >ph eI"I bڶN2ݶK굴/H7WE]LΝfD8l 2-jVF- choVRvѳ ٮ3hIX`,j eQק0{ZH+X?H&YR!)jHjlomwKR!Tsah٦r dy^/l U0$IƼ6c!)j5DaeA׳'VCk?蕙k)K߄k9.kfN^'z6"c_Wg%p[i.=|=Ocs&1}=ڼ\$7&N|+t3uhFoݻTǧ>:٣579_+uu>woek^#]QJIR}|ZQ"YDCB(;}zb_m` +yl7l^a"ͥ%v:WlLL6`Da[RE?[5lpsm>9\7ϙ3K&j~yBv&v~.5z|t!1 LMzj~>*RFLķ|bҴ^f!"ed 6$׺˛ O_/Λ3yVRFu6e+CVI]fr @:xVx=kT}0xN!q}Q-+i3s>v=h:uj/ѥv lo` 9p{xr rwjX+]P6,sB"ٯoBX5\{ ujy+g^>߁O-5P_L`Gmb@N%I4-1XՏ./&pByebߔ'CU.,~Q^OE yX]`tUD "c~~э n,Wtj[y9E^^r a4"@u~e x&ܑpaAg֔q1;7Ý@s? W6shlw0ۊ8ʶ'Ȟ_3[$]=y'SٯW k3gx=_o\'Kơ+&|U׽@d?M2p!cbqݲ_wD5n\BF117{Lx|\IJq?f5#}6oL| Id Y߄'eBL|KpmJqU9vV/6VCk9FԴmxwmUmu*J|wOeh"FmsCs="(x9aF>g͜tÛcóh"jE9M8>Ju/FTt+ .jƩoRE7LT?Lvs88Vhq\ː$t&X$""vhDZYwBP>tVzW"Y*tP`n'8)O!ds4Bn-CK./`H+XVщS1RpW|Z_"Q|- uT̋[m/3^V1ҊpDܸp""d!Kd5Fs^ZpQ. UMOPs *8 'cW^2i Kה.<сNDDÛSfr=Rm6Cђwhd{l7i"WWK_-}}zlW8;;޹/˜{ADZlM7w~^?-Aְ7Β}d=}wi#\ፅyOxKn˝/7?ð~=9֎^t5x=_ᒁ3}Q6s ]q,yjI) ZKdbkfJQ63]2j7dLIi&]UD"bÿt{FY +!u*e^U.+BC5]r˙,wS9Yo,jĆ s,ӄ zI$S $2 WU*9=i2GW)?!~bEF4ݽy݆#%8tDK`GzZ~J3N|oxaKߤl,E{c՘'YW m IDATY*rIx"oOb|-fژ)oW Ǯ I]M>'TwkF6W0B+n>ѕW(73z/? ˽'nG<شT,iFw^' G#\2a11 ;;qG7PiԒ82_%Zz˫ʋrV=k7HhkMߨ6 Zf3Hhc=/kۯV]n3SeV)d2J%Q, VI0Gd93R~ Y@qԂ(UbX$*K$D.\\$btlOx6J4,Cn7JJN0j'|C;s>еVNlmnCy6h9i}cqMnxȆ]#F;A?sn[WGx.TU x}@0ףNň.<->hkc()m1Dij]JѼP$-)r1ڈ4C"ǰEfr Z3mNf%*>}*"EI`I k.}[|{EWC+7YjJ+OyN`^?QVocȚj4jn?vG0O߫kn;5 a+IժG?Dd9uI '9ldz^=G/H_!q}s`E E_Gnܡ-o}}JqMoe)׵xjZ3Ք#:>p[mY#rכEҖcPpףNň.`vbws)(ʗZvR|{'#"b(DнWB#X)Q6Bep^PY\_L;;7fS#s[7fQy['ܽO {Fr̲7g6t [bOWSI A֙gϕ|q,fmvpz#Qpu(7bpz+FMoh1}Ko9v11111&(8\蘘3/皴h.︍;Qm$Wq zI8%5h2%39V8"N뱊 [$KܔKC+u絃h}&Bɕ]llDk1k\dDN*YdU:AUɕKpߩ8[SCㇽ*sV yg+!Hf;>W?ߥ7:|Y-]۲ OHvIZ2^:#GdF.ZU!!'ư'aVAN$-lSEH)X͜V}]reĘYejEI߽赙(?*̟Ur D&?ذW4Fdc\ y埋ls9ꐃ2+#Sy?4sbJ]`%ArgX5 !hnJRksz!8XQ_u#o3_?18"~+彇[\S{~s,6xϽ>DDbif. 6eYŅES뾝1s&/s CZ*w}&f>˯;N魸 r].?SC=ܯTǧ~:eKz_ڿfrqiM>guFpDs oI½Ƃ\m8F`Bh,S=M%傢!D2ɒbU)cVq}fR'c(img·ʥDM2>Zφ 4=ϋ MHPpB=j<>#VGo3GTi ?/DuE4w7ʵ#p(LD?%T{!3 fnUBJ4T5|.%OCq&}h NJDJg+zYuˆ-X8c7x m0䥕*ݸKMhk Կ;[}~Ʈ~Qn%e3eJ p})o+cG~pPk]zFDf/^H|oiI>H~LjeޘBlvSּ;\Lo{a _m.r f׋L`^Q݆MYЦ0ԅ`GUNi"":)ԩdu"ĖV8;+7ﰖxxR3.es-7:W?S~-3"0OTv,xߓHBW1LIIep>.FLԕ*,uM4xW}%8ԫGE{ 窙7a FˁCӧFF6s'_ӽ{W0?`kϘqDtr`73&>a?1oӺ \rsƍK?rA43&yxҴ`{וx#fQN{&x3#r ‚@(dPs>s!X %D=R.g]|ʬGUG9rf~0̓ϟADgnL!+#vnt"}SN/*61h^Ș7ZSvg=\v=V{=߹Xv) ch V=@`A gpg Ƞ dbRL}^Ly4D>9voQhvާl?o%svCA ¯[ X)#Z-΄oyVn4Ծ!mqDDYzá-F@Y.|1EM_vf%h\| q׽@?܇K_>CMS2&RV]J^HbhΜ={̆¼s6ڔ./I7?}~H1שɃ*MB!7/yw>NUm_\N&UG-7j%K'++zşEU3U?D(1|ەSx2WvA4BWO$;.!u}#P.؊8EׄQP%8(LүXI dr@yl{FqV4L$y)m=$ țeWơ!B:BgꕚbKHx#3\ Ri! !k&+YZy@٫"r1a? *n+(.mUruyyZUQJkRRԑtM[KXEM!B!4B!B0f:Nd 9{Wo򴹄I)b LiFt_wvP!:!aBrLўuۆ\e1Iq63IhuHS伈:%$g SJMGB!P()8B!B" s(a(kk^[8A('"'֐0t-B"JgmϤrX+Fj0 ˁ v$mWm?F+*f *OF\W{eqEYɴxB~̺̓Y2@55B!B!BAZ rEEI1ʈĬeM-^:`RjTduس5cdI&3):'Q.WLGRϐ3):+ěJ2 !]_R$ b+#@eqM.dtK6AlIé&]+*rB~J$2a%DIUQ7U12Lǥ+WIT>pME rYK8j\&jL~$XHbBpbkx!FՏ3t/=B!;!B(DpS"\"RYX3|NBL,Rd,=,"q x<*CAp16K/mx\c!!UnS)Km2gq2v/k{ qC䬩;HG*"@f=\DqPCDZ𖅶onGUVm9zDqHXI em, -8U꒔1 f"WF6u\,)H.ib*а*`1SElf ^Yg*GƘJ$jbQloVkh \T m0fA_m{\I\N]SvgXz4] 9mųB!?4B!Pmm>,!9]WdJ7t&[2Isc-o.wK3R@^Tܪob.1,v΢#\T0݌Uy\kyUWnL~ɮf]{gy'FZ>@{4qKSJdmiXǢ! _F!B샠q5yP*H'R}9urB>∮Zʂ=3֓Y嗳:.Y[ۚթ` qsWe{w gֲQoڜtaOED^qվ#&C Va.c* !P&Y!onҸ<Z.I,5k "GFvPy=s~B8?sy') ̋NjԾ$&ݜƕ:Jv~Uן}-ﴖ8O>yU ` AviW䫳|^ߊ={ !?BV/̩!dWgyvju9g]h$-7+AM“=\|^oМ#jxn(:&dmbbF莤"{g=dQX^mb g]p.l}P&qqu0Ӆl C;f//`D# wZ"!scޤ7>Û e!݉o]wР` x}*$/"4ҏ]@|RH^6 tBBLvyW;#v8:\MA  %#-Qoڱu^sl8@ʏf.ٳ#A=5bvŻu?r7g'U o Df[³;gg̽i aMb%P! n#F^؅{Vj?57& hp,/}ƒ<8|קB""ܴɐ?5ږm?Ub4QWq~fB!B (+ #l9hP%sХna*$hBø>~ݷWvRӦ e;9 ki\ Hw"d'Ddvx*(gWy NuD7zͪvG$\U^-Ӫ&$hȇo֬)#-OS!y{WxdH.n XB!ZKdͮsOͳ^Ser[0zp\+xTϥ뿟ԼNz6SBܳTQk;<|֞[3nLnTH^Duq14 E:a;p'!B!$B(9;ҘֽG=zuàaN$6s纗MPJ񮞁}yN$ Gy엢OE\.Zʊs_uGOݰ{gncvs'M4Nu.ŏD w:(t x}*$/"rC ~F! i ;#poaIlPS24W[xHw.|{AT\ X7gX9Q+m6y(Z 7y'؄>][x,6kэnK@7N>>ud5:HzwG/5l|^$\ꎤ>>H2fN?4'gj219C^ ɿPYd!B!"_]'A+l>e. Iɯ(i>>>3)ŷ$4^S}A(%9=ӯ ;%Oz@ e'삙Y,ZAn?d닝OED,l2dW3B!B QPP2ToOܱmKQ}0^ax-@ߞ<]xҕucE׮]Сbumݡ7IA25עf¹自 \A>F!5 sSo 80G"'U'#B! !otldx:Ú. m6i}J(5{ cB!_nEhAҩ]eq5j٭ hܮ+>oXAZic'e! h~ڛi'~@c[v܈у;ԗ=tIm~BۦSvSp'vnpޱLݶجic~=x8܅3W>uS&Ξ ׅE zYr'[sv\f{ψ`)-^{~{GF1U eBU/9hܐ2QϘ}ZE(9~kh6ڲC\M-5 Pr6}W&~eh_xG&Y$gΕe~gnn~𑔖 gkooзUmկ6{{Q8ʧŏnL­S;6*ܷaHJPH^GL*6`~4n"OT]:O0B!7x=fBa49=﷿jY]jtڲ C\Ld45Kv_'Cg;'kk|b+2(d-[Ol1%!*+/Yu'4?Z/i-(|lAGV;1E/EzjM!B/㚮6w5r$kz< &kk_ܐc.AUc}sſ(^yw>ئ`ˉ5L-|kunS:W/-.^g6xkj+orpT-^օѭSeQ[yp6VVU ɃDU+EOK.焦17@3j-9`ǧG^I1޷(ꨜi+VՑ[dqDw^(,ZiϽ+O}o'֖JkpE>diW,Ԩi9WL};uE|Z٫kM>9ut _񒔒fLIΚ4NЕ,$/Z!B7rKˤIsqKNZ4O+Q%ּw^Ky% =wfb]9D!҂!B!T4˓ ss,|?T::6K댤2(~X6--ߙ/hSQ؍:JG;ջ}9/Ȋy%_wY=1A}t'uUNn?֧K7:ݶ+4Nu.%4uAIZH B!BHtwb__9AF;#-¹l9"BY:Λ},%}h:ք??aѲ/:aZwimW*ooFh8xj5wJS_̹}.N6ƾoqOiRpg8^f{/~E~ُ/f OY;t0lzrG k1.3~`Fg o_n1g&Y7ĭBB!h(˨ A^)~$R~tF[йwgF;hB?ثɫ if]:쯆x^ #(*(3n]K.cVN|o5KG'GH?s!j4iˬZOBn\8ow i)mz"kt|}.}~ƒ_o9^|N=:'kP1sja٪:8;۾\uFrp%^qU ff=@k)[䉝AC!yԂ鎤I? 't\FE[!BaO=wҽz7H1l߉4B)Q6Y.W'ڽwSxꕊ#zٝvz +'i21?Q=:/L>--$O[=p!BN3~d߹DZ̮ʀ9hrB>{tJ N@5^WˆE!?w\uʮo)_;ç&@%A!P}'lg?\|p@|nvM_.B1jS+fc5-e7q\~CnX+@dG(\× Ag~ώByJ Ezb:4Z>Հ0"r !B(mt/ܾ~ק.{&岟531l9`!9}«aD"Sp B!O"^Wˆ(0B!Fmݯt}g:%İfϴkި %_P 9!s>^Wˆȧ(0B!$| 0&g|h*D ro$Հ0"DF!ΡI%(_jN{\z (P`J&Q5 ov!P(9}«aDT(5;&dťןIE_ouӋlgr8&\G'Xlw-7OPon脮S /aզ]~ZFẹrqb™+wii)gOKIP:Y1M>Ynعz 2u>cMM*ПKJsP[=NPpt J'4j9ygs;i\(v@ΤzsQ:Hѭn5n,rGh:ԷХp亝$w^C x^ #*D)asfȎƥPso}ˇk$^BѨwtZ3̘oy=yv>=3֓Y~Yn9{~81k;\I>nL­S;6*ܷaHM>=vc޺oڦ_m|ՑLkvM[e9إ@!zş+͢۽׎icu?~$&]KAqbl_~Mϒ]CC0 gd_dϸٻYv1zq|;yIkKAs'Z\0f[8vkUq4rs:'{ RngvsW^KO( hW]_ZWFS!y[d?\ѭ@'k r~b@BU}Z䛒09GTk*AN B ',b܏M:wGtA} Ҡ`V 9h>(< ^y*Tz s^"cxkJO? pM,<3۞yĕ6ӆzm|׺ygۥg&?Vޱ+=mfvD54'YV+r ?amKshhD}S_?91oRY_Gv_Ĵc׭z?<<(^ ɋSv2B,  !PH\w4>OB0($:]&S@\[/רf*nWt%=bY3eW <{^J3bzӅ~i%{13W\zJɄ_V~\cޞ.\rIxg"]˵~p> {kOhkX`4Êy]-:jgwd{uWYȿQ+WwH{Cq ]2:Mѷ.N`=6&=Vb{^fLZ= (h󧮰 6+ ]jʺMe ܻx`z-:ׄWcaE{7jTq,6ДJVnjRh `> x}*$/"ƮIǺ,ٵP'&C!I2G6&i}q65 B) 2ʯ#F(DTE؃&s\wm^U Y[. }UMHJIz3 eȚ4ى x}*$/"gSGON'kT! 0t ANaZ Hkt3׻vtmuH+BZ։w]  Je;#S5۪2dsgxT kvE{5]WzvHY78,}_q]'vsj_s8{E8u:tW"asNVMk ϥ뿯<..6..6Mɢō8%6j1$=Qk;-w?=wfbݪ=S؟-^ ɋ~8eO~D! ɐ?3uVskgt}NXv3,k9sqǚw?i3QdfEc?~YTH)-M$iR7wSА9_r ^^dˌ%1{l{$A֝) Hذ[#do@7sC7zȃ/<00.ߥ|;ˇVPND̹r᯺#]7pxW}=/F4vLIvKb':Gqr?h:9pקB""8^[.1EM^N]Saa&Ïdu aoPx N7a\3)G 5U6նhZJ+?f)EƷonY".IspȖ$ߚ;"\ԃ:Wo5F"U!%i2v^%.L1Ԅ!mk,$Hl_)úׄX^}ir \Yq34Z>cxzpԎ9S59‹S![lᩕc>k4{{= O%H;(n>?S[;lc¾岷54B„|=/xȖ$҇l?ߥA0)u5_F%>9O@W.B6j&ۻ6/QS]%։ rK0DN/=&Y8]Uߨb G0{^^v\u*ps5+`__L!BQO؁hWk*ƞBUm8jԴ`WmXBLEI#6˳fcW^rmf /yRH`llVK˙ED;I$,h3[\(刃QQh>s8x==Șc (DN;5DmW@Ӝ!nT@w"5ډo?]8fhɶ=I2[# _q\c^Sots4B!?#*!*%Ƙj'2A%O5~3Ѭ0'NPj%}c`I6F1LR|핪؍wطݮ<XJTd6|*$ *U+w"FU ~FBz5ڲg;c {ٞ}5y>l_u0B! ꂭhVpL |[)Jb[ J?Tn(YOZ$e#8۞G1%b&jhJ[I!?#B((0B!$ʔC+Iۄ6`H(:IǴ-KP} 4럱Od$/aD1NT6%Ť8%%Da9Ji(S 1ZQr۳ uT,." +~OW ðf\^mQ u{,֚dM1<>safڵט6DW~fwU<2QTҢVm]ŒJ\0dx8CHW SH,VX\7XI6BAW}sUrprts90a Wp`! I|7]Ľk}#B(rd)qɧʈ*Nm3ˠ+]y͒E~0N6K*EL_؍;E^8IWϑ%2ɇ ӊ "K^׎+TJà]+IcMe6jeDʿb qRVFuE]Śq Hq1/jnSDaLVYEu*uUlce\$kk4-PDfBY`-ʰR(6T&(n!'ϰ@! O|'ADšMYH֒b9sf%uJd҃5hJd91$Zt6A}"kɔrbI^9'fHn-]oIJ3mcXh", &Xi6~ ֌1$aLf,Gq\cna,V?I52*zdTHg(im)(eLa2A\E 62#PsA;pxFH{=|i< F!BHĬN_,'qXb#&E%aƐ"DTki\Gi뜯"$DFPf!aTyRi! !qi&+tXZy@y[RaS3"+0@.\r A*!Hsm 3 t[*u]G+UTc"ib47?o6* ,BT=CC$,&r[n1pۺom}m*nXwFZ=$c?;Ɗ|g ` !P.G."6ne9N(daqk]%&芉B2% ӑN5@םcHpH:\Su!BеDycY2WJ62ˍbyjbZ%T.hf @YeFŧRsY:$*؞*" ƙ^VcB`Eݡ&ҡ_.#t*PM8t*>MS6RV}JXE:ޯWgiD<|\ 4B!°°ß} f-}L9˔jgZry eJ"H#reI۔ȖyVkX&{b!Ų"˦rI`;?"g)#͖RlMJR !]/M6cB)7m#F5c/ kmuQFNWY,6A%%p`.\fcD<N.OB:LFU8p<^ ü~B['u(O5='uGRnz=#cTU#mO[q2-/aզ]~ZFẹr'q g}ۧL=-%A+#-r;>ٚm|}?M^tBj?ePUT˱E ;"j3+]Κty 1:>GP3.dv:ZHe;Dؚ oYhFqdZҶlUѣ%C J`$,h3dYhǹRi02bIGrISWA*b3S2J2χSSAV8ps)DUF8׻jbqb֖wZ?=7enL­S;6*ܷaHPNTH^D9Ӷ 3xm_}mLj-zePU@."6>t6XٮHTЫ@ o e[2qc-Lr5,hHjg΅e8?U6꛻l&pL;Uu{u* ag+=s5OPa{9oꓽՄ\$t=ӕ?o\yϪC/=$a_uײNk‹קB""O": @wdc׼i_ۭ3W}`dµP=up* a_ +ݔUkU\mO&6..6.nđGRqDWfE]%#bMbv_ wqktd _?91oRY_GvķǮ{.T/^ ɋ‹e`j,X ɐN~^ :ߺ^ F(DީS7X?n0 :9g6t+W^DrC܅]3Hj̔ϭsao|Z^Tz݋ #'K|6S7jJqqqu;nKF_з.Ueb%,d'AED3LF gbTT!֏PH;}l?fŸ}o>bKWܻDZXR_z&+'9!Ϥ |QorlOس|@=1cՓo9&<g K/ڻyQ6ДJF]FTzzH x}*$/" …WS-nʛ+dW'Px"b{!_T͆P|j??*VzdXx1PPP  vBvIUɤg_T"RAH샠8cd@E:[vduD}O[-f+__ߤzT&Hһ J)63!/<|/E"8/niPPNnfNS. B *@Ұ{gncvx6IpuInI]Z=QH4p~QB{l*ܷgΕWIoB5l'&Cȏx/^PX)9AΕ_sV-q=m~|'Vذ{ oOC]RlMr=3`f 9;Sh2oeh?ڨk0icλq0% hfcߜӭk'yڲŻ[\Bpvڮ9UTṝc{%\KZˌ9׃[v̙zICkJS!QUxj_|~vVo@ˍr" 'bU*wJm y Sdx^/TCN|R5O{IߊܲצI@HRIVW%~6A3>Cj1hҖY3Y[ȍ u1-{=1BC)ۦ%|9go[A\IvLI~>Rov霌ʆn=| nv̬gh U2e+;xY>y;&$8̡S@ \ng@av I9G٣0&i}><|| Vpտm|WQFvP[O tWS]/YG/nZwӝ; v)+l[vۓKo4/]Rn(ڵ:Xۻ_5PљS埘|;] <|V5Zh^LGN[teSp$Wj a^O1)82èڧiJO&yBB]x"_^_`Ջ:|8<| "Hޫ6\<ޗD|xN!&B!~PX]nOS^O[a8o`L / (W^ ~r8ȏl3'ͿB*Kv9zʫEU] /ojWS2+HTxޕ 1B6v; 7ˍPi$j -pٚm3z }O@QMa9{}IƆ g}ۧL=-%AY|c ,Yf" <~ʜs@~;&dTM>,7OᎃcmY&E:m!M 9[?wC4E'MУċmUO܂<nR:/ZX^Pp5I8鋚r`"$*#f8/t:4Ko8QW؄#/I2}a7Q{9$]aAR)V,̴V-9,=+Eߕpg;RJd": ϝަ˓*pְ g/fu&!KO鮌uHomK}~5aў5[M}>ܹjXcw#{ܨe6ԽE]xp-IvJuWP R >n6*[Wœ_aՠ_=kkvhrt3.uoX}ՆfgA՟ܜ,Jj_/G0ն"O". ERq<|FVDNQ8tcDd%6U,Ry(#Hk%ꓩE HN:No@dz{~S=B5#$.kW~rOg}VbS^#f}j:>tisϞj𧻓\ju哬cr6wݿzfwmQXȾOYgZkw]ޣ-%f՗"N[|Τ s|Uk.Ʒr:{y뵌OY7aiSX)wm96ލ`mEE{]!^b׽!߰E;+-,F&K}%OGt^+K Cq ElR=TA8(&Hߜu\/\e+#<)+ [W:% l2i)[/.}Uӊ8G]nc!WV's2hաF1'l<wաF?Ŧxx2 I=2c:uyggLk -D_z 9,O>(vOP_bw>ӠݐsNj!A귋fn=xEuZ%L^8'u ׾7|DmwZ 2MXoxh[ᄺͰxbƁǬ.(ZtnnY 9 ;i QwVrgdeUD($) km| Pڋ<*Cؽؽ%{B>`[ sbl>D)*oMRпo`C]Έ\)@$/TXEvs z wT5 s}W\0VE0d %KyF ګYQߘ.}8=w8x2˦K2hӥ#߾AuAb5̊Ί '?[{笶'r_5!Y n˙u?֎&ɚ_w#|j[{g{m{! !T"}.6|FUfE^K0W 6Wq@!keY$ MEi#p&`C2$E^#\]d ]mnleTA *SU)&_,XC(n9TȻqn*3Q<\Q-d/Dϟypa~jeuJ;qȓk>YuNgM&qy]_~c{NW _.9ოo֣f^r]1yۧtP"gȟXR9UGىia|E]xp-ᶡ~[xTÝ!|VNnXmAߕ{V #=_F0Զf^ftyb%`bb" ٦z3hIeYLZاMnBHhIVJbSL 5پ~hBjg* l A pT Jb'5? $`oK9p _UBvQMrSeIixКQRhP@'7YvIWT^hUJjJ$Fx4SH]z<e幾Y(U]$ڗ R̠k38QY COgLmu:؟]8!Vo-ڱ"i` n$j:|kkB} \|tz)g/wܰgL=zGս&ڠm.Q mQ$j̛kyA)_fxuA؄Pg^`|a1+>[n@\ %2>%cʾwaK͵P^TeuO^{{ @!J6ʠ|jދ# 4tt+RZ#rt}wgT,1GZLYJ/'D)1 +VVC+'m{:$tdpޥq[|شb@Kqj^ENGG `+N_ Z,~2eͰlITKnG K{O<_vn9r͒PW3Y<{d-sn9Vr0}G?׷Sx]R/q Lޒ=*T?wm_=OĂK^#n3IKu0$%n^2=,݀e tr- SڋB!Ts#} :55.04w*7c[~ǁYL+ңjDʓ i{o@C^[~]To>3g7PI F*{:r#9s m>2/Vln6;.h:mxyҴoa@ްuE[RbmseM6 L FM0shcøgsrA8w jv\W۹DOeé)q;m#:~8 uC/OݱҴc̭/wєgזSm^B!PMPT׋gT*d"k䗣'wPӵ> n6A_(d2]xa2ek׮wґe~~Pߦ>cv`v33+Ξ04XNB->󏿜 ^msWurVo׀F!B!BOMfҮ3x7Juĭ&UO0F!B!BR]3xAqI{ B!Bvpm񅞜\|~]춞,[`/@gоajҞW}4B!B!@Nd&-s{ZzFzt~qEܯrG?:ϣB(UWԋ[MO0F!B!0}̤e)> WY&7/1Z-a=iK"!;P}G7 @lʳ,DVʞM<[kMla4B!B!TYgNmL8a!TBF((A"ڨs\0RMDդ=O2h B!BπؔbˈJ1VFJ9$c-,映B5tl6!B!rA{rBZ9K̲T7L-Ėi{uIYk @$=JNZ 3C?pA Wh` z'%N( PGC@& O aWadvS7~'#XEV>LGV`͆9+CyzC&񬵮T 5jҞ hB!B!̔jho=&`6CfkFe tN$ J5-%"Ri8ê/%SD^bԙ _=UlwbFmwl%ePĖ-V̤r`L7KSuR.)L W Hy*d`UҨ`B!B9Oy 8 !&#@Kl"YΥ=MY9QFwd9J!'Su71T@u)'P>Hv7vR:E(J@rp@B8=BIf[eHaf `DS BHVb=c_GjҞI5n~oRQ{5YB7)"<ܿȱ?@bo0onQz$N[s侫7$㹭Fx<"<""*vsFGjNmk/ $Nt-#"jï2B@a Oޑ!|R*E;2d /yi%s8+Ez㙠$ڰѡPyٝIH$(ڶ- |XDI 4GjM77`M<Ǔߨ묦IR7еCHM^sC&QдҬ }|eYG_cF;񷶥>hϚN ->J\5EVZOFL-)Z9mԥdn.\Z2h UO6.pAحQ@&Ȍ~@yC&̞lo}+q d{x7LDVNx7>bm,LnBH朲wPbV})3ruF} pW8%  ՟D7KSx/֪u!;̨&)Ru:a|դ(U/FQOOnY[07\r;߲G-̼8xEzu ~;N/f,mۯ|-iK%Oe >IG7MK?D֞u>EE+I ֊/K^U2 ZJ!C!*W[Oo̲}`*sTr2`0>pi!&U/X{qnEJ|_s~_sɑˍebjcgٲhVYH7ě@S&cIWx}:2PtȖױY?Txȥlٻu@h[nv,"0)G&'ɳ׾'QttIi`A[rh1pqrE"TB!T 9{Gw13 QTL)nKA8}wTy=S厼85B}=StLMHG&Է ?^^y΋@!3Q/sdaM m<{L7Aɛ \{uzK5%"TB!TQؼrѳy.=#ל]>^!PU&=TxWhV˴X.CWTeIǁ;5cTpg_ծ/uWF2^96irO7;,.Fܷ&l'uMN-"TB!P>?gb|kp IDATB(FLd*Ay Y%YLdBC+hB۾~X%ZVT.ɔSk2Se [P# ,$uQ/VҎVR -dwTʓ$iBR!礼fC٭& +sTB}G7:wo9~=97Λo鿙>cfoSGwE&W_tߢܟ6/ł/pEC9JctR'=|qNJ2m\+9n=uWk* !gӟe/]nmh@ ^&`gjzQ[/tu|Z/*zIVPm_G?kPڙ FtKڇ^ ͑I& J皺>NLoʟK m5Ћz= +S'YuGs }.er5&2ybO ~6};O?L.UW۹Deé)q;m#/]&Ys[gyN&o9w}^mjW ߛ.(mup|$H !B!jo[M:(??߻+/GOtڡkQ} j[{mտ=QdxrÆ d4Md׮]ҥ# Рp\$ؾ0|FVO9E!p4B!B9>g$ؾZ9NKtv2&!!B!^%ř2&!Pi@#B!02=SlqfNx$dy)ס'<9CjB5{ڏګ/ \{yw o#qښ#R'XotRb6mbge-鯗NѽexD'P7_%2<""nOf|d{A2:kd##"bG9g>pcTI7}>#B!B؄jg849t]nLn5}7qG'MGܢop=WYEp)l{tԺ,ro64?NiNxnO՜Vm/='~ۋO~q>pcTI7~>#B!B1> %R9mmfJ\}*rŷLZ*aJlj{>kyĬOMLJn#B)\!Bը hɘvi.C&=Q`Zzd͂8d{%}]xDD-,|RwV^23IpN!SD&Hb7*^ڪN '~9p~ N[52Fs!B(!Zq$zҘ,=sӡ+ʝ,3mԻvlmϳ;trUWmו'\|Ts$6}Rv`ҴQ`_O]y2X ٜqIkvWn>kۘ.}qtw8;{u1B+|F!PiGWӕ@~*?ckC~l"SlퟷJXќ:g/bP@>:2r7gqu  <ƶiڳm.85kC\W|S:+6Z7]Q׍G[hgRW9#Gke& ݽ:ٯ!=B!T.ā U}i{k)>!=gsپ=Db.%-)۾V׏kڻ( {T=f}1h/uF_*84g짖;{6g0:Ӆt Ǿ[3)g_ci%i5,ej,Z aWdGc<B!{83B(gWr_#?Fm"/OynqЦLqMæ,=szrLn۔ojϘ*Q%2>%cJӓ;}*b{L^4F5˗~y!Ba`Csx|bs~(fu y]фWISb O9pzؤ?\P[I<'R p{fq1m͗g퓺~>dUcc<!BA#L3!`5B8nj_fXj}|+H¿::c^-WGtkXp<1޲hh3JfT{&,ϳ:/{y1~oRQ{mK~y;-#ȥf^o,݀*aTS[JMn^;)uw˴q oTnO~8Fs!r3 *BmBOÜ=1PAIF~vTo>3g7PI F*V&55&]WOH5c<(NM9hlِN{[?^4mwX7l7|іؒKYw]ӁV;^x+!M;IrM5/^ʚ$fm̙oA: a2EyuoU !rb?\Py Hȳ}Qr2BR1i;$lOByMGfӊJ f}'-;Bw) i7-oZE+ZE*^B9-#sv=:UQ!0j%khsOⶶ*vL1y ! P51O!B!YQfQD TTN*1MF*:@lJ}o/w !B!wt7pӟ Nqu0rp4B!B)/N b%1B…8ۏؔzrUG4B!B(ڡx h'0{>#OT .B! ^1:_a6җ 29xc>#0F!Bj5o3h;V̠ B!Bg4 f~&g|RU`x>b@#B!Ϩtoxb01qi#B7!D!BLQYCL1f!((^%?@:*hB!P9a:('6/8ֻϕRT)NQubzF!#lp ;IG7)"#f@&؃ >._):h:AuVX}ՆfgA՟ܜ,J8 k[ n2oUل^*-׎+i%x !B(σHo6~t1L@{ؓթdu]9~=y :{y굌OY7aiSXٖW/40k+4'YL]෣WJzUɀh'_ɲߘdro ,A3d!Ug,4Mn^b*+wC"!;P}G7 @lʳ,ۏ%[9KQz?γV6R,.")F-\ (ҟ%G;jR+&E\3~rl?nӝ[DDːI<%7nޢӐi~^ozjB .M䳹/XDxDDT7c DEGDwV'$I?&ㇵUI '~9p*-U%E~wqK F=B{h !C!BZ 0>XSu7:iRpuN{LʼnW{JM:ߔﵺoVI݅ΘeՌBݪ—Z>WV 5>q9t y(scf}>g۹ŏ٧>N˗\\% X ȅ)/^^iЙ\hݴ ſ1bSs~=c_TX^ }%.}ὗVFuz gm/s9$f7rc9wN}UǥNQgGrHւ?6'~\Rkpsm\&գG{jTiW %;<xh !C!c*M.{d JЎտkSjj 4BsH7x!I*r=X}^z3qRr5; Fi5n(xͅ/2hL+ 3Ar>u=^EsױV o)aZ3c2iչOd|?Pu_BKt`[Pz̋goZ$e΍H5iY&G)7<(9<\#6j_vs 252 bնjU{d@ ]JsGP0 B!{Β#,4U 4}%gc0m4}$@dZG zRЏ/\B"d/‡I d0e7$(49 }M4tϊ$G9Mj<\bYYh d2ZM4 [W } }[dzֺS&&9E2:l>Hȿf\{I{KGASPukVv$Z1Y86G K4*`4..(]U8o㶒m. =gܳrP4g-yL8ZvA:/ժzUɀhkS9?a@CB,3#tI`&oz٨/>Bx0I:~ 4}AKȨTZ N*Kɔ/h!u2{nyBb YҨnv[Ihm)Al 2jL* tCA D?U(̔j`|Šk)gBfZE+ܖꞕJ\]u1ڇNE֗L=n(P{T|.PXFeKr Iggμ*a0|)iYM)ؼKIEl[ xţdݞ;4?ç3QMdu BV{SIthքκzooKv3y,qVxtNG뵌Oɘ]G?U۪Gۅt]y>@\2( !Yhl2?&ʟ\j#oєe|iM6$X}2UwC)IY͑~UcHv7vR:E(AD,X!IA$U2R0NVw3Cuep^0)lne$xKFVJlfm&rdgM:0λe}@`NU3$vdcz:Bq7m`5)S8+9Ǻe[PB WV=;bʼn{A ߧfY3=?K!w\$w`d:4S-G/N>r~:tH&!GkJ<'R a4Ӷֶsh̶}Rr^*-r6{~oR=X.~4!B5K&K}%OGt^Jᜠc(|m^G9V`jÖ:HhD YB"] AВDHh-[MYAٺ"q( a+!HKB|AvmEWM+V(vեcm :jkW ~.tqw=aG9@e +aoZA{>WOoN!*iT.Q6Wuݸ > 摡QC|3{6ڂ_cB)G;;oD-nʍ'4 Hьƴ0ӔFkqmotTgu[d(|֎~y̓m{G7KX^nşw+SϤN~d쑝Ƿ̝崯ZW^뮒"TB!TYK-ps<Ƿ&@)7.gD._ a#TMqyA*p H\ܖsauӁp߁%IK$H]LyI[,65I8E327!khckԜZ^*-B!BՄy-\-JSZAhC2<$HAJAܧHG0yh˾.6ɔ97m/Ze+sMAe !8P#ے^]H"=@UL k4)h$ 1:8M"AT6^B%03K=J\|R۵'EH)]i ҊHa{"%K&fJK-绎˃6eʊ7ě@S&cAWVN#۞N# Y}GG#tqqp.Bd'$v޳$Tc*M.o4ЎշԳTc.=B\~T"׃bvy^ή= 9lQ!j|{(|ǝ(ܣ5湣Z@ǟ[s k!B!jP6!ܔRe? 0:6ȷ ?,4U 4}%gc0m4}$@dZG zR&?c1+D+4_0=ɓna gnH@Qhr!h6<)8XB$?8}.Å.V*O&D!n uPз 5|is[rX{V+qvХ0@WϞ :ZJ)]!B!PSkJU'F4O6[-IZMdydI-sDNSV"&s($!'.R3#EI& ~'y@ʷd(2 =j5 e`K@rp+$##ľZX1j˾f(]AhJ7%ZBHV)X H$j 6Z8_=Z]Q L:Ԩxp@աFA9ftp4B!B!ؼfoc2Yd"_ԷJQb!pL'%Y :@z:XIOY [Z SRD YB"] ARřh-[MYAٺ"q( a+!HKBměei.w*V(vԥX0}[lJ" _ ݫ,u B!Bvަ&>/`e@Rпo`C]Έ\)@% Վ 2>Pk@/ޯ\0ZG۔tzнZ3ܞgиB!B!hՒJSZAhC2<$HAJAܧHE&G0yޤh˾ƲM2e E[c-[k4UGho *S- }JrtteZGHQˆ!B!BK2(2s9&dLdd23k E @.MIZVT.ɔSV;Se [P# ,$uQ/Vm@b6iQ)O IbZ ]6-ʢʜg4d Ҥh 2dZLv x (̾9moַsTeJPK= F-Km<ɠ'!B!Pm:ր:Z!& L:RUI߳0 L "Z'Y; (M1V+CSTԀgZ5+ sg,Q-(`~T?ר$&)7/9Tx/֪u!;̨&)č4p= B!" ګ}WT3|jދ# 4tt+RKXxq̂i.[]\xsAy˄=e2&:~qAtjhd³mOBλ,h. $!J<Ǩ67D \-Nm\gEoR&W_m =?ʿgcZL0b]ޓW׭ʓW._._#!36\ ަ:49t]nLn5}7qG'˼XEZ{_;f$uRUi4y{]?*5,}o}sg蹺?':/:ͳ&𷶥>N<{r}o/z>u-%*MO3?o-3zܢUU J~B!B!#4 *ARH}5un@Pā}ŖXwu gQR:hkJ"U'}Q[ ?*TTȼ3d|?w眛rŎ bi{#E9NP %/1υ҄2(A%vLTgylcsHVƺL_|_\4W^ YH+Btz9t.MP⢝%/pT}0~"PL()Z/yI' /rm%ţT:[HF.mk;T<߽_a9,ߒۃNnq4m`Qǟ袳sG̹<rg5+ ; eMXw޴ޕr[?DExF8-c\gґ?sӻգl Zۍ_m0#k #][V,ɚ>H( ޸Ͼ|4}ԅI+ F-=[/[+ z`RjĖئ|ҿe*I\q/s>KQ3oD0H(|3ߔeiiq6rO&B!Pg9ZftFlǚDm\Z6C*kN3$T0*KI@b)b000JbUj[1Y& DS1YUX҉ǫ82R2Ά $6C}TZ:T!Nĥ2[4C2Z>Ra69. o;WNykVkS7v%2 } A z}?Gd]q >zYJ^uDA~A\ŃkorkUN&ki6u.8`l=te62|ZK}u/1 "_~*$Z߮gPɃǎզ@$ 8F~۲e6~̪PX!h7+uʄsF,_k?̶ VJG(ËTֽX;\^޽7 FĖ~lSHDڅv6rCB!3D9J# |o헑'JY]B9_OOV["@0TPE RKl%M+zC⚜S Z*Z_5 IE]--'aK+Fd+@ O J4&<{ C+8h挏S{w0rϐ>e$|»>;OA{v.cJ!:=Q-cMe-nl<7uWKO.WY{/xF {M ٸW{!æ x!jk-Q{5۲WӢcR}ZB=88sw>RR띤kv-Kvo[zJ)Id3ƬHÞ-%H߱dI📻R"R,BhXIzq;@?hv B{ǧ-;{g/[r FmLz "B!3D1o 84Br3:r;jr1klw.gn24W,?tkghqI3d/&@%P"*_QrfiZi8aq|qq7JZa`u+H`˪wS׋uﻙMŊEhk5K u5@+{9l@+jI8!:rs, ->F);_Ұʓ t]gdz;>\n0] ՗1ۻȝ&^"=Q@i}Eyog n^yZAks7<`֔}dKt lV0@9AEPYpyݰ[lִY3aqODi &!t6B_!B49h",8a\bbJeIGֹ*Rώ G5ʇ'VA>QIP+밸(6l$ ٬KZGp $`,ZJpG)+lpIa)ɮV'2_DfJ|lBVPQ%2IBIs4ea (Q,nE&4d C)T߷&K?I:1o(:h&)OEr߼ 1ݷ|ptwaeyey%tdD7o ivH j鉰ӳoYyyyi?s#dZ?e5Y}.^׌5 F|cӔ]>ۡZһ^z\3v^şbtv!w8 h^ff ֑N8tcv˷K`$ه263w}Uw2 CEʼnȽTy "B!+gTLٔDyNtX`VBZ#B)qh/]ggL k3G=\M PzzA@!6Z<5Մ%TQ;oղlZ>B]gx2&X9gي2eg//1r*fqeeD5D&.)QiʩD֨;q$ksVLTɖхkUnvY+W& Զ<ߪ3oו'2ɕ]s^l;) :EI?^yR)g/U m|-sc?}sw볫nuB{O[  /̛&wΝ3(WRƍptgŗ[/3BE>>qF'LWftHo1竦'%RQ/IܷEFrcJSO~R)OIڝVyoM>Tk pBτܐ B!id$pf?`JK/ŧ._Zҵ4KwdxVԞlRb8_ >u6LOJ8LkiH7ѧ$o&Ry*2}^u'֛Ug/~Oj.OyҲ[Soj. :1fȵ8@+ VSmh(h{[AXwHJ]eYۣm>&*[ -xƎ 󫁚1Y~ݗdmY4g 5h{T܌:Ń?E'?'DR MBh?m,Z8˒4˯yˣ^bֱY5UEp}fc3+n#5CNWOX|8~! !op}H_u" }Jax~3!עRK@f?e+o} v2sߧQMIrDpAB!d%sePD`cyXb}:Q-XUdHRy~eW=݊2I|!+!ӻA+?Jt}"S8@+&"^zep*7e97*:#g]ܡKQ{0^׆6wW=jR4/nÆ 8$Ir84PQ:2Lki1#:H)$70ЊW>/ ZUwS>lq@+ouF!ԟG7j[t iʱB!dSF?$ Uc/N<ҍzdhWիs>imnEGߛыpV., BƜm qˁVџv61B!GY6k"`#&R}K>WW uHCOOߩ :;c_.',~dU ^}F!B6gB!d:3Z4}1T':,0֗t ;B#|$5fUPen7d-BZ hBȥ^Zb痍œ~F%VKrJS>q΀BHKZ4B!6 oS;A,&^ԁB!0B9 1!B6DHB r/B!T#F!B!tM>3G.)6̟!rF!BA3Krkt?Mܫӷc;N^YC!D0B!TBvIjވ4rW3_:^ۮozȜ!#t5bݚ6 ZO?{72mZgiG<;lwŪǙm[ж&v\i~vx {J7k\Vxk[1}G=]kZ!8$9SrӕW-$k_yLqEBu5Z*Z{d/=x9Ⓟ>xCw1j,fuUͩ~a O]L!BDYŠLMf ,3}ښ~~ !(ˮңیNٵ,ƠKWBԎ[N쳃ԭy:mi;U-f5f< qz9w}Q /3&BŰ:Vr߷_5x 5GGlbn7T CcW=̵ܜkg~jl.+k]*eɣW=fw3?;LF3|ź$Ťw3{}iNo? B!_?v =IBYk ?}=3rOCiO#t Jߢvn9оW?4rgvB|A:o#niB7]"j{/h.<:镡{nȺv5֤B_*' B-kMy;O.e+^EO Z{:&- wIqrz.Fm _.~Ϯݺzhi56na7 !SH!*b`] !S+M@Gj6ąi'7W| u ;pTJfUbk9x҅*So/%6<#yQts7P({W Sy1yqq_=G%zʲV_Ko.)^"u*J1#(%^@X,$%H]<8 T?yWwnJ^0t(EY=[V,!h11CEfBoDG f l~BxV1̽bM ߴ] }[Q_ w`ŭ=2SaApZ\]tn9e.~Gķˮ7նxU 0", [ ws#N'B!7R'LOMݽ{}Kt_eԽtwC6s7ɇFNoR'8T @;bYǎhƘOO|TG>$!#;RmW݄UKtp֎/˳ZLq֎z&`kvL:gݻwժ[opb׾ktIEK/L-nZl9lmׇ+jeIk[zZ? -0=iEcOr^lLV^F6nUeS},eT!ޏVBz'3'Ջm~}?"L$oʲcyRWM3% }Ϛq3Mg$,5 B!׍Npj[kS'w%8/>@slG/K 7uW1-9$/>lRk#Ns?WG #6l|DWOQ(*$ѵNңAж=-N-GJanmBծ9ykfunF Imٲ{QɓJ+%JˣʫE* +lT14=arJ<7}mǻ%:mT+֕%E}s3vhygؽ~#SdVN_զ\ox"t^3B!HF4jsǩXtg;9gHpT=| ~f޳s%V:mW x˻"݂=ko&hݵc : OkqFl<^d(E=88sw>R ^iwzqޤO?̦~,֖c3ƬHÞ-%H߱dI📻Y>Å$쟒j`,R@*r|*ꂖW&.m}[r\jl z݆O`cA4*b] hʣx-;{g/[ۣMaT U6ܲB!;20 !˿gBu?>ѿ?m]фW߲<)^mW?d<O͉>ﺤ"1RYQ7rg}7D8#.yفGnJeZH;?Z ۓ-A&3\H(+O:btFau CT7 kݾfJEC}uge+Wgcyz)HÔ+5š6k=wQZ!B!Pe PE<>/lB[/n]eRy%e2i)j l[_o*] 8Xrc m̍Z:`E1b7zIh1*% $ չ8PevW3|W>7[Ga%ه27nԬRu;-57"g=us62uz]҉wB!B0id'҄d.\{fb7q+qOj[ޡU):1gޮ+Od ٓ+ν+eOosNl?5wԨv͊z]ftlcZ]|%e= jh`\/d) VJ-y\tjbWMO:xKJ^>so3i]԰U#|J|/#V*\I! jT|鳩2n?TԋzB̉6I )xoM*=h!zd>!B4V}ذ3_!d!8g 4'Qztm1<~ϺڹC[}kߛYg7Ն z0^׆KҼ 6$X3,:/id?c4KKY? :u/}t4gNDﻷ[:idA{b2ԳSwwH29ixN{c`W>#B!BD8}j0!b'Embǭy{mӗc;HpҺAI?ĭyF^-_nʾ[Mܸ\3B%m$0BMYYkmϖ1ȍ Ӱ6?*XUvlSf<|RF9ED!L>0B9?h6:2z1o`254pI# Ï>>Yi4#Kh_o\W#!\4Nt?`| B!LL/#[FXv]=Ϯ=h B'I䞰4B!r Y4 c@.j0Fo [?#jdmj0!.\[!B!T}yfks-lzrs@ 6k$NJ1 ԽgbdABaXr%5"0k^1̖RهG Aourl-C={ɔ‚ ]fo,TٳMB!B!w h!x;N[G6GGlbn7mVŏ]3rsYɪz5Rfs߰sq'ͮb&#+Θ=nᡒY/f\:1+I\q&C!Bր]B9#L@ n7g\P=_*ՄmrmYsow:7r;O.oޚ7)+`׬b8Hk@a}+[wv Mv2}c>W/sv 7B!'9hidd:q ԐNdwuRMYZjm h) -zƬ Dm?PyfO|]3aPeĜ=م髦 =bl~S>L( j1xξ[@`gJ'Q1M*~կ&.ݔ4{mEY=eKAa=?TگTfAl]b "f$t_qyGp&C!B!{Z|3e73>s?o|}?nݾYopptlf}z8ia 3?UM%Fl:ԽtwC}O ӓVZ:6kʔOr^l\%kK6nUeS}5Rfka/}0[tR?P*Ś !B!BRt:6#=7n[f&S7$Oz6pR't~. 1i| e7~$?ڻkS'w%YeE%Oj3{ֶJ2 ËT}jkV15'J C,ۢOucPf''ue !BȡCUvp]Ӊ8`:`NP5(qEUS%V}h׸k=CYBi$!}ʲ@OxgW)06g.#ܬϚiTn ptr:R, k4R>t8fҲ,AyFt|~/lB v]={}W{{ݽW(=붘 zyk6*n`t¡[]:a#>t鼶]/^ e*Fd#iJ̮z@ YfMp%gҌV)M+:A^ICCF2AڱF,\6'+i?#!liGzSe5P]n ptr:R,>Vhg LE g]gYт6׵[.YWJyyw6l!IyaDD;R۷{=mwLwswA\VMa5̢۲+515Pjw҂RN'UE;S뤣еݬ=u-!q;給CVm`V>X3,-Ud^\<|,-,t"XX$3N nQzt,~qE. B!B! ҎС4aVD%jw҂RN'UE; ޽w՝{WB!BHL(%*:Y+)5giAg)q*u"]M1z@#BLv,p)cbXֆkSX` pfPDC9S y.YZYDJHvW:4B!B!dmVL^X \u+YgY4fMi2%afV3ZY8=Zl5<7}KR8bB\F!ްzצzAf1o _N=jqa\u*`v&;n22ww7i_`щ5tDQO@khZѻ[LiYL@#B )֠7k X6ի 2g+}W/?y)UմM^Omg2+YWQh2we IDAT7oJ[qF0Y[a5=X#fjoxݧP ZwȦogc3Bbٺ!J> I:` VMa5bV`ݯgUYRfVyIlZBMqLHj]„3=kJw8_d`MVgB4B! 0b)X)^}fY>ۨGmTWenVd'kw px-Ny~ x#24F!&SgF|X6ի 2d5j!=j!AlJwQ4j{3wIb5c7YmgbdABaXr%ֿD Oh̯bMiVVZ0!n'g &SadSk^kšB.cݍå]eދ5MYZƥ7/~_6|Xrp#oܼrnw3K'Ͻ(^ˋ?봥|)N2?\;7k٩gj3f[x$b99N?=}kR}Š_\L>qG;w߹ٗvX7Z\KŰ:Vr߷_5ёX BPUO{8s-7ڙ彟 {ݽw'/#]wZhfL\Q>6]^޵^ZbM&H# 0bXiY0V zm Wd.G%3VQ btu75ϫ}vNN9؋+ `/_}[ &i!sm'½ JߢٹѠi B{ǯ+p}Y>o'lOV;{K#wf'#3KugWn?=6na7+X2^+_D5Ѽ:^{W!UHT=Q`mYsoϓywߟf/[j!N=8J6F&[[3 En(|d])rXz`V>X3,\0v%SQW~#NMo%#dZMe竷V&[fd\0fTִ߫WU;ȰGivq[E*vg,]8-&PN~?\ʗu(y*~~vSf'zW-) t՝pf]/ܢD]R:&cߝ nj}Gu[̅J6EՖ& 꽬Oi Vpt=5y"V)<:^k Ʈ)k\0lmڕlr|l>#0Q^1SڵU̫Ĉa YBۿAs7.X-}JnX0aĆ @;bN^V"/ N?FZzt㘍kڷ ?>5omk4(=l'38kX:ɸCgݕmW{Ko1ko:g?qs @{됩s.ge%|ZŔ<>=i 5`kKOP'(ml |dedV_y%96{YFF̡ZP5}Rܾ?۱i|7'dW(Beo}u\9r:8h} g!\ ]A n8i3XT[ Ay'~i;o^@rm~NDp/_>/ h?!y_8 ̶+}8^>C-E<zW?}^DozCt4o1[6f,  IG\^޹7~"9 ^TىIߵtZRT{b]'_sp]xyҏ,[rM%uHJ2a蜑;˗9<o˖݋M3㝀iDIzyT"b3+{5W[ gౣzi"?y~7 .8z@#WjPr1ҿceR;}n=[=FvgޅWI%7Wbg-Y 1$|="4z.nU$?PY+׌ܖ\ WqШcх77`(!˞'{̼g;6Kt# .dU5آ"Fߖ{5 o\{d{T:Gwm:n~[^h>*X`Fucyzz^^ƭO:賲Wgcy\#{Yi mn(ifCv *$o(võ&'[ڥ ]v敧jT1wedʡ *bSx^7z EdMXc}md8^I fӞ(5~"# joIw$>|7瞭Q#C&bZ;' *O@,hyabo 7KɈnϯ> @ѩ!uH zNX]浯<!]|eN۪^ ,$\~6q(V>pj.M*g:rnF/oJJF|cӔ]>ۡaՆ-w>#v^bóGruݘY:%ه26MgOmT'-(Y%gb^ŸP:Gb](vpݜ{{FЅq|=9|L+_rH!FJ!u x 55H.b4ߜs tUOg?DkIMV#gmqAڟtSjʺu_?cJ?9$arsۄ/zkUu62cqKe~&U'N?h#]HVTW(r1.gęnswϨݙqᕓgDqю "Ic:X1;J6uH 8A%vLP>J?.}ThgD%qǖY;<33*ع4ÜwYr(2uo#Se==Oa2uВI ȾzƎ 󫁍,Kv,KU3=*nF[Y^/8m36'{5g[tx _Mh.K^,/zf:aU)/0Woqȸķ0Qzt,5Bv?V.0ƭq_e¾?W^ݎͬغls&V.@ 4dOl32^Kԉz&?)݆1.R̊q^JC/]8{ƶ'OUpo__;g8cDʔW(r.1SnswϨݙKfHeMd(O_u$[9,)"V, c@FbuӸ.r5c+&d C)T߷tH8p,*B2C&kgZ ֔W^<2`|Μz>ox{ڻumksx5\ ߳.J6l؀C$ÈvзozCw]=vpݜ{{FN30GO"FH@Q+ĔO٪wWlr1[iLnVUK h& 8$:wwbbZ2Si԰kS;c]t|u'jMcz?hbrF MBP.7kOޭ6,B!jcMsws5;A3վV_LdŹ m[bDZtm4ԧ[ƈC_ UG0yw hQzt,~qE!ptnswϨݙ=Q$! UD@}VVaqTY(r5I^0Ӛ${b;Syre-zM¬n(+=e!B! T_fOx<;fzXoɃCzm$ %F5ѓF.v1̭6bY[ʊ ׬2tw@%l3B!joYmt i &*}4fin;}Fp55P*Z;Ɋ^|"5ՓR1O;r* cc@]桬˴X5x!95啧FKaj X\Ae/?Ҟ菽xvD]§ -*3e_髾bTez*DQ:(aj%Zמ|۔>V;usãŋ hBOW$I,`ԭ)QZbS]şK<2hQL]ȗVvaCF\*Y,W%ԡ I3gbWP-R-k!H#K'30q3l9YG>k8^>֟@'+&B!&ϑct\+8DY0V I,ySph $Q> s^zX Z3}}`gzxO VSQ2qOigjDy:@%ڶC/{XcϊP7S<ࣦdeGw"MU Ug4Ou 1%ĕ0rYU&x'ت2V,FP+w 'dDYIܥrnxIʺ />_V<?u\!e/<l)iYdg +aVvx+a)k)]f .L@#BF柡%S% C|F9JE/}4AT°T |ߣ4QT̰p)l#}7XcAVR})*j8Wi}yqhDl)%q*:ʹ+h?mO^whGjd):t.2㶝 !Bǥe34C2MEQ*#Dd+T,)"V* D*).[feP0PJ4Uɘ>>;QŊ%h  qsˮadh] &vFi>YfJ C*ēU\؉4Q&{fHUGR8l yUO*?FwYR_ˡ˴{F׼xjY>#!<3$Q/Ӯ5dI9>kd6tۺ Rl=ghM BF! Vկ'p-QdqJ*")%\&_VTqM"L"%k}VZHJPk} & EwόB9 thZ.ZK5?*+-ӌ 4',yՓzkFW0Z^P/Oue :i}Lx@?x:N$@/̹fLB8 BVkѳ2j:SDQx(XdmFu[I#ctoaӵ}¬9wQztkQN}˷ksTi=_Xp+)5nh^T>ٹ[)"2$gZnexSq&CR}QdxEŔݹҟŻMs ;$]1(\(v%Rj.IHV^I,mBV߂je{dƷԆ(˂3F׼ 5^+u"*1z+m4Y= m0J;pjru9W֬ϲ,,:;0{^{ݽWTOM:bO6#!IR WNd-ZGRYH{B SٲOjޗIH% zʂ֡;٭~Q+CE vԔHPf"ɷA<5Y͠UX3UW BVmUhIHy%DGDFC^!ؠ`]STt 3 ,׼];ѐy}\=;<1V>ѧ_˼ͣG;yGӝEAssObevٖ_[#EV~)XRw yi,n]OO0Z禃¤p@T=2SFժ'4-O5jDoԵ'ۢ拓t.-,puHNxӬKm.b'r2A[Nᑺ^ʂ^faJ+f[&.Ռ,2Ӕx{!컕p}¨{Sdh VNi6ֶ֚# )=x5:ׁmE5-I͔#62 >L&+p;MG^Z&mbju"T=]T cRcv#5jQ|Z{;*6ĎZ W%Ggf3kg^&" _~΍!)c@㣂4zq7M膎G>? LGnKٳ4Ks[mk_![ng3!2u 0$"j"ɵJP:e$'Q̒qr0Ũ^qzݽ}Ve-}04\V@{}_T*9M#8;'q'$@vE+~4qy!~7kJ!ۢ^2Ɨ֐Ս<+0+-tXCcnQ_c֫M.4ogtrS֋' urBr0DG$uHNxD^ĦL}!  t0Ӡf-5܆%3#is]MysVN~HDu[ dIڼ jgڍ&G{.=RT{GGt끰is-nFS>I`,87lQJS%&(wo슳[EnRI9I fXkuzIG3:J 97mGM(vtYhE/A%G~pi_&p{:3_%~p}{g51U~RH7o ^|RJ2/VڵBP sn65R?l? '0g?0F|45qʑ0Z̠Wf_G֝Kއo.wE]*6˻/D)ODu (r~[/z͓k_~"E}FAAA8ONI:ְɡT7G0ya'wp|2z b[RԟAAAvQ**P3 5h4/av    ;AލAH&04,@#   )p_,}f3i- 1PFAAAVM*v]ve63" hAAAa>M`ڕ0uk*A @Pc#rZB$=$@Zh5*$  B z$ivIn ;Bٖtl2A    2ؑ Y/Xŗ4*ɋ"D憐az廊# /f<Nz )ŅH^H! w^bl٧R?X;d[gD)\d (*m~‘WZܤY7kP{ya+e^ח"hAAAaPM8li"jRf&'.l!_3 xoyrU (Mx~L@G:4W`tDZ5hp(7[A7nBNhAAAa ,q+@KeҠF}M?ꈞ HOPDjl:CFg dm-y 8[A2<cAAAAAkd 8PuYf64hp|ķjXwRxNM\Zc&{' Ѭç| PjxVM{g6㵨W3wԦ+6,c6(JxzGjߵ`\vQM;JݚTOq`ЎFGDDɆ=xCAR sFr#Z5"iY^gNԩiL8@3# AA d HlGlֲQJ.PA 4zcw'CjJ1[iNgbp<ˋ38z sM֍zsq,e׮_3zWmΈr|ӯGZvׯ]<׍'G9Yo,.uׯ_a϶?T'sݔ{֭n@vڡ6wxs[߫ݤrv?8;>8C 딑GnO43prVa+sê~?yМsFY&3e  =X)Vb9A ^F'x7D6 #3_Mp}%rC꤄M=){,i~ʡFK>kI*A"qH͈6 ?PWhUzDT%HTalŒѮ 9㺼Z;D,jy슯6:w'Txl~'bJDMz(:mEV57{ez}J"Q[+ok/2~SFr#:KP[8>ʞ35f۰X W{!sMvfeM8~3e  ؃4,աGV[-"(:Hv\2$nFty>(N/"2m \fp*6E}]\ROGv8e9Iō}? N>޸V/\hm7YWMt?9^y6_ӵC_Xɩ"PJi!q߆'64mL%|NʯKC/r-jg rۉӣzyQaa*bq:{gGK˼$v!fmXaSuHNxDVs'a HȲTkt)CAA8 XWo`N+CZ/ܢwR3syimqSqq%+ٵV:K`fk'SMjE*Vu[hXG=eX]{.w9Ӷ1Js@1ښiˎd*⦢}N-͢:ѕms~o^Ֆ]|G3,Lb"(.L D#c8ed\-u1R'D۴GoԵ'ۢ拓t.-,puHNxӬKm.x(8zTՄ*~[tSc? AA LzeG"eI`K+.CQFI}Tcp9ѡ 쎤e8Ӝ.zs-0ޔk~ĭӬwJhݓE_Ѻ~@\?6!56N֨ՋG⨖3Mp edqVbJcmSܺM!6 Bjk+=!clú/U?vfҔ.=oK4N>!@*6o.u 0$2;(DkY`7uHNx/=hb듄q8vi1Rn/)CAA\,nܙ-lQtx5}I)˷VMG"eIe9,cn=BEDs5b :_z{r9OK4uʒǕ7nS;bSՠK8IQz<ۻ{֭b;Z rp.T+PL-m(J6UOzbKKO=^D%&t v(]\?G[_=fZi|5Ui{gw6J:fyjN"bUF)#95˫^za3Y6fzHwF E^r1iNwE  AAV" Z1sӟԋ̷+FJY~t*,NP)R.kaצNm2k͈N9 #al|_y㪃G3TG)^۪⸖#(yU;-.{/~Orǔvr; |TZ"~c])Q6/ooTz^)y"naC-]FmM\5u>Pb]'UjHo_GB̎]h^J\fڄPyqʎ1-`AUJ[+FfP[Y AL}6~0O t6$ZfjfzS2x$;llcMq?geguaukl DuAѣjF ӎ\p4|62TRʻ @\ZZrf:{jQVtbKkxcD7Fhoo?dq[^G:eg;,Rc~ڬ\RǙ /nrutg&Xw Tn^IMPjqƔCWR_+Ih@*:E_ېݹh_GԘV(8"UfiL 8S)bmP}RdO@)7WM|M>2)8\&Lt[`a| F̷\*NzPJ_dApgJ3zԺAm2^t[`(@na[momoZ*@xQhQ_T) ,.q|ZnjV{7G4.sFuAO~vΟMfƵW_xO\8̠ '߷mxU(lN_qUW=kJGY?͙q][\_|Kg3(1w~p%oٌ:ٸȷ6\9whlxxqi'~1Gn i>'&- n*A+oyzOOS  VOL=pIvX98qsvOw7l-K X4;/c3= 8QYL .r)֠p HTBmaEi3ȒRZzX9ߟ A\‡'GI&$E)ŭX JaPICDF6cN!r Z[Vk)׾̯iΡXm/tZMx븎!DK=zo/{aFytH^ƌMʕ_~AFȸ\ V^m2AAR{,ׂ8,v]Ե02QEفצĵ^?If{I.S  x ,k&0͈ Q<} 8e -O}d`[F 'e$Zz߹FxcVK 7hpwRwvZP(ܹsM^otƒQh`~ok@;k ])8 `),џxVu4Pcrbk/p1 Rl0)\.(HKw "  )cYwdUx"J\U$avdIvdA֘gwyc,b Gܧ+ FAA?a .aZ{  r@qXT7&av]jc#$Y-_q274   0kb&7]ƍnYEeUlM܈6%jyrh'-m_    $;,RZh9Ěgq3y:C)4׽ r    Mrl"7Pm4&]ɜ qL ΀4   ,Bi7-7"H @>`|g?͞kӵ ʻmgkPFAAA,~gA< FAA]2yXS8$7"H`}9@A+\AAa/H& =rHF^Jy`AAAAJ 8$;,]0s󊰾e})/4hg/q IDATrrnAxZ(|@N9J{!  )򜵌Xhh}1C`zm2~x]jxV1M"Aj\9vƐ#",<8k>#"›v5ޢƁ9C;%: i'g {@6'ܟ2A.EX "+&)|ӋΟBm8KNwϾ,zXQ27^nE6=b(*m>0f+f^||a1=A~~]e0S٩o96}z˜I#n=2%\ɭ L M{]2,=%QiJ 7B<@,)4R{gGO!m> 1]m"˦*+_.ڌ A{8pV|Rs~V+)Q.'J4&`] OXfl-8e H4ϒ.6{&3)3ua.X_E=<>ӱ0Iyl}wh:?^pqco]{N5mto|Qئ%E[ *W \N `03obg4x ^_LҴ>QAf, ۦAύjM$m|P=NU_f}as_i M^ v,^8ӫ ռ1R8Pr2ܽ*(~]q.O?:tE?Zz2vXqXf k;S=K E#~2e BŁ0}2HY6Ff&.j7PSBYل$; ŋo烻9e_o}O*Uؘ6jB\~t#S~y}'a64e޺rifF7 ,h{8G/ AA"$%(WѣYl{uj^!^AAa%9e;SР\IAGc0׎#3S^1{XWDB}65^JֹVv/   0^p$as@dPW`&@tVkFe94*qbԝ4Ғu+!밺y-‹߁ɷheXB A AAAX'Ԗ?0i`8\W\^IvHvwh]*Tʎ!>oݻRS1'}Ϧq % Kh<եn]˼0Mj7   )ODx*v_s fGהRoR +ZZv*})ƹl*eꑲ2OeZρV)˷)C@xRԥnþ{PFA.<<[#w"Ȝ;ެuku,7ůM>1ku?$ S\ScR(msɗ-xAEʴc0[ޤMg/jЌc?S+&>H өKQA0A @AAKr .p㿗\)tǣ!t+ >}gЁ; ~M>HYBuAn}0C,o0>_  Ƥ>[ >%PhL82D(7P_Y8tf`$H.|\FY3&N)`l]Jt8N(Sxmap$H Cˉ{hAA`j**ՠ%a$4Æbֿ#׮zps*fZ/FgVwQFAA5pML:;pI2l)w~3 0a9.0Ci3nru:w-]nɬ˞@^׮iC h  F<`}\y*pP 1%APX֠6 &SQf$h/@g%Ul ]H̓.*<""iA[s h];ePe&g~-q`ЎFGDDɆ=xCA̙ž!u ɕckg i(<""ޠ?eIB 7PBu]A{IvXdI#3p%sIv؆5v7a(O]5 mYc#'n!/N]]%u&"Qf?Էǫׯ^&X453prVa+sê~?yМsFC#WpvTi0uqZ߇b_2nۭ˖#AfjB 30֝B$$ΞuIe'v!fmXdYǩž#}pA1*AjB^ wB?`T+;H6߱RI8!!0I T?0ͦR^4/y44>#uUh}4[24t|닢.}h/2ؔQ-|`^҂򶖅 ONW8b^"=pۑk s3s7+' _liNGQMHwE !_=}M߭ʇ_xмa5_|Ι^u ، AAo 3((I"ni?UcuFc38t~cTxBǬlnͅ%Mr33D)uwc0j;W/:9:2 }%r'<(w8b'&W% "~ܢx14N>!@*JBzzƸf QVH;)`)t ^PP'vh3B2A_%!E URS # Pv|}MҳpiF\Z/s_aN*u3-ѮN`EXizO(:LT긃,TIBK&Bunߢ/kQh|5Ui{gwZgic֩{kKP/,DzdMۖb=ֵNJv*Dk@bilB ]FmM\5s+kL;8e>3\'VKT|Ib1 *BOZinW(.;b#$@R\؈剤 yax%& #IMtu_wyKʛF(d$D(ng Ht=Vk/A1Y^I7uJEI':¡sjTc1,K?Ȏ.#~F77Ɩt̨ϔz-9b%8WulVg kC|;txUs59s3,LڲaZ.Z_@0CQ,_4&qc},v\H0ʹA|ԡ+'W"wnh|֩%}p$1y;q>!"jRH I2Ԩ Hu]!_ 牿i+UQFR@4oE|='>׎UIih)~_G$  \E`43H E&\$u"_ NӋh5֚$|*NjvGKYu u٧>=ˆw`zUPf'?NU_f}as_i Mȵ,̯kyniZZZS 5;Մ(ݔk6uEb<-|xhm>UdX!}mJϏi@\Yd߂z2vXqXf k;S=EMݥ8+ peɔ! X Asl(\쨺ȨEjTTQy7:@CQ~G*G]š3$agȪ#1U4y] և(,s+3t#b-n%G>'_5qJ2oݦ8OtM~g/[! {@ס,=ͲS Mr@]R9n>poBӢD$C !tUx;ZOO<"!'4m%0gK-T:q _7Xe4?ZsGȯb01 ]a:66I[pIt? q6n?0Yl~ !  qFM/c*u$7!rzd:B AS'/ԏ?O(*kdTQ=PegP(&Kt}_ XF%-$SrZHPG,T)Ma ěSTp n *v;¡cyIv)EaÔ=t[})0%}fOjA)PFAA됆וE`Pi@AOYܩD4S*BVJB w|$`Kp$ @km|?"[* tO6Au [VIr ɿ$YϠ~CYYOFU T2h*ۑ:R1pX !.P6ߜ-饒Ggbג K8چ5%yhAAY82 X_E,e)*nxPIuŌbyޥ-2JBlWUa Mb퓶; NoA ]֎#>$+Me923 y*޻2(@#   YL"MeZa^;A/@g$`ӓ^- hAAA; AIvؙR͗ +l#PE5}Z>vJދmϱݛx6!  >'p#&W- |c:vǖ xIvT1)Va%2c:u)#WkE];+J׶ߑrtr j1 F@# kVA LV|֧;]b:٤/SXKQNuF@}בg;- ;^~W4hAA_A_ X61IǩWfu7JP99H7 <-> HSW"lҞ [f%#OtmS[;[(l.Fՠ@AAݰ 2>#+rn eg`FpakwzRŗ4*ɋ"DtIM<ziykRɒ찊K3UN%   }_AAė0N=ٵi IDATȨT5!n^qW b=]ӯ =F湼0hM% 6(Jm̹*h߽ryϴ [z1kabv: yrwE*g|P)^k)W'HJ];l[QKP=ެ [ʞ353iU{!s)/}Eթ$K.BmYZF ԿoYsWƉ^Р{2ZOZut|y?nFj<[g9G.Ckg|ZMNQ}Ega9ލIo6 v)^r=8ť~zJ/ "Iz Md] 6wsf0lʉs-[PtaBYl73GCmw2EWOۦqDDx6gCA"5wpTfᑱ}S\+?6WwLZdDD;e7[Xƀ *s(%gѻ[FDGbP /}1_FoY-ٖ6KtDDxDDc}8Ykmhy&XShļ,PFG0-B$dOF y]Fg v!~>sWˠΡ}`qQsDc'74I>k  x+0ʲUnTG}ťyt Nq!!/vϩϦ\Ha'vWh*[mPdH;6G:KD\,ˌvyAĦ}`۝v؜`E]98?eT6S gÉ>ac}j]vSNywSP}ѕ \0q y["A-R>Nr;ujըQT6U+MK G,=KĿn;rM,Np☍k۲raw%Ƿ'{Vun]|s`)bNs˂I O.md=jBgf-^Yt hnfpfph$=u-Tja5_|ƌTV\Gv6qȸZV c[pNQW;^&9pS-_gLHžxpC |T#GrlW:Gyv%?/Xw?=>,K+nYfT0aӯq ٥~ J>-hllWA>>:2 KA8%Ggf3kg^&پ̄-;*xɥ[N_:{iIGW=;K;q1?nQ<C_ucT&m,M '_~8ioT cs8w(u:U)ѶXKIH[O7z;ʎcg]\ŁΌQ C,R]B:|DpxG֪Tڙ=KS޺4ʾu,.r=*nY`bY6 /n!㋾b[$ ={8eS4xO*J \3]TN^Lkvv`}}#*̮j_&h.)a/$(~hQDa'ft3>=Tj"5@pʞ'Bun= 9yOOk<٬} OwiV*i|d@`x@)yngjD50>Ǐ?sZzݳ?:Z,c,.l8Cޠ)O7ÀwS:+l01旙S6wVSp/Q^nĹ3v ݎfe73RqVbYtco]{kyIɊI xF׼I˟،=,4b:K6yu:?OI>(elSSOsR<ɓygtY{VY97G]lD;|6uݩOzɍɓ{|~jժzmFv]D\۠# q4^ΒCŬٌ [ ۱kp1d`ے6=Ccr̞`OmnIIitPӱZMHRE2I1:/l0oidLdpW?7՚~ujmYpWkA\yaIScX~ k>ɯ޴1wYd؛kϡ>NXV`WoԦm{7 t_LҴ>QAf, ۦAύjM$m|P=4( Sr5B늌pyZi奛/h\7M# k7b#Q[e,F m\cQa5\36+Wu藺j orsXe󓺍#6h0mpBn뢛E@8 l#_0"a5^ɓľ,-'rw^3UG#DAAe͍}G]݆n%3K|R1j.c`݉=?_ /\*]Tݪ]@( wmӦF-+߱C\X#-Z?KN}U`*#4|w:wpiM{\gUxT]?ꤏ_w!k,Q,x^h'׾죃AD 5jMFEnd1>y 3;{g,9~') &D:DB@( *BARDP)B0PZ"]<ԨEHQ!tH6d&Mvfv'lf{νe~s\GUԣ8R| y)CVbˤc#Oy6l{#ڎkaKOVAAxBR+@& ۼ "A1.>!LrO nkݱe25(Zth'DoxH0rvCqFRo+o~y3C9t@A)B2rhy91eCߨT7d2{bcG1<䗔4 ljdwS)N2+n07;|vD[}v"¾"Ћ{BDӮv;_Ŵ#~t2h$(@Y rJj3mN5xBAA&Ӥ] bmL~Aݢ{⯢qTGԯ0ft@\yFG¾Lv.8hb@*dFܶ{AFR r/>~",^g'2'c"^(RF&XTU[27G[u;Ukr8oHyrܗ`݄p;I%>||  -ߴaZqZ aWϐlaaaaZP#n`2بe'COZl0C52Y7KCAg'/+rHӝQQ}vUNT] EPC\}'CQ~+3)xy4Ca-E؜'- ~ {+#~N Lc4  bkn.L2peoCuT|֒pHؗ][G.Y9!ajL 'gr "KX:k [o6fIj}:T fXTХYGΡoURnx2>}`%<d2W "KxKTCJO"rN BshI\v!"(@# H"[{(Ѕ sDY\[Vʹ2ŏڈ`lk_TVh#B  ?0N1w/u!"+}/'kCk:l6LWhhgxYo77 n7ض*f䡇mS ;dTOuᡆ/)l7pQ٪ _e4l7+ԷzǬPuXvS )?y酞"3hA8R2#{;P]t"^vk5Cu-`lByȢGsj  Dp4;TG4dU:m]S)Vܜd,;[ɐdUT+6f<ݡt Y1]JkRAa;] V.SvⰇi!E&sQ8L)q\0ΪܯVؼu=cwH[RapkwZYuxd:5Y3%t($A~Z)m:4͈#6\{HUGVQ҇2'&DVYuBX7 t'ӟxW@96<&RV hAA5E%d\0Eih-_ vӓnXj>eUWmYU])J&7 C-T ;c{R9vaɜeZ9+PjFAS )? ˣrANGr9;LoU{($hn6 tWiLF,E$R  "!MQ!6-PSj\󷬨jE=W~IjsvTTS\󷬨*jL}z?Q>A[]@S;*bW:)(u-dH {(B,76k,VCVbLtLQxaǻC:<2'B!RB42rRQB=ӽWܾJO [#d4Q?*EͦP,OWR XfCv_!,Y*Թ4VUFUX~Q`;;sUxfS1\Sob{EzazɦԨ*TBTV!F2BA6?CҟtB A6Eo!+e`7XoF4#N+횓W._vm|ƭ#ѷ'/?n/ŋ#he$" ?k󥪽?X:Ÿ>EL BzkCC/dV:|٦PMпKwVl\]aò^<ئrA.drinYhEm +#׆ˋAV,W҄U/*hS*d5[6۔:rѼ<|NRyG&Xe\;3 m["jC+ 3uK"P("W]\Ai\^\AH_.I):; 1,=,,+%r*֧dBy܂>}g,TXoxg6Rzgu2OV\{az^5,(</#'%7VL0d+S 8lš]>@hXrooWg [3DLϛl(@0M4*ׅFNխn]-y2nkL`\l%TkCt´dpԶ0>lu BE]@,Bn3 (4sx騘2t2Q`HvQf}ZlnTFPÚ^huXF<>~.lj-Z8d q8ȇ-byxbW%qyi pK rDBsVG8" /=C^}Z()AR%ϕ3< |BM%ߒTtDaqc|.)pI- EBfʼOz "〉oO}IkNn YR&:㫜ˏvkOl}$uT;OnG4zN 'v\?GTJCVg7=_.=&uxgӢO}3huz彔) Օ`J찴؆?mi IDAT=xUQYߩ}Fg~cQue1mXӇUlwχSފG]R\weeffnސ FD2rR!!$Ԛ`ai|ܓȔaV[3 fXZ|_&CsRׅ<3Mfd,H#Caol.hL\К(:ɐRcK0>JNs>W80ӵQF}/9we7c[JjEbL٧035ryF}(بOw_?/('ֆ&%UZe(H᠃sp|$:\%v:Ǿ/|kɵm˞s/e .ߔݿ|g'gSXsߘF:빿kS۱wʍvo_~Lo:\XQ<`ϟaU_ÊS߱ }ݪ4]ٱjt5l~;tшhؤ蘘g{|R-?ڬVzZͫ=:GT7_*^FNJ"":М ` AADĸg~ţԍPK4ޤUF{B tUMRF RS9IMFHJrl/瓡^~8:.JEōNY̚],'Kdں\㣅'0.҇iWڐOYhtq7fvs9n&xn)BU,fo HIID3Ɣ!  >C:¬Lccu|)-ּiaA{QŃEr{nΥ`*z.˜݉ETFȓm_\SI2qRV-Z`qP4pռ[+]UmHf巄XM mйID鷪,Iw_7c_amC;Y}|Y T³'v•oQi"ֺO-oC*RP\XTajoKZ GIID3Ɣ! Iia?*EͦP,OWrPn|ri͎S:1J$*J4yf(}-07…+RdOޟ7ZTא)BѹꨨI=Zyn!բ}:Σkw͙&IQQk})c-KzL,V^m3@`N  "8Dum lJz[顡E [٬uUNҦk ^ bI@QOAfzjs㽯Y"J-6/0WtϊUĺ9~2M=71|emO_ dr؃)oJ4+AxM]3s*/9r'gi :kTibG%m>=wN\ͷ~x׌Wu_Yܰ*uwْ%gvr_YO<[DD! @ AA18T K.!aK#ty(FȉZg3O>XFWQG;_뎎7p<R8-ݖoF,9hDdpW4)q#/{( ~z{bhSY/ETS8*=ɻ K3]B|%ݧQ+fnjҚY>;Yd[J#E͞g)miEVn[0 ~~wÆ< Õ/ygwͤ΄rnH_NZoٜ!q5}`RJ< x9)A=F@L   By 8$2%wX=23 졟X!s/鿞@a yREȤJ.=H+x@zoo] YuҠߗ.,V7ߛjI-[% Kl(jYzuĶoh9lOFI4_NhUnw,+m1~u-,F]q~_lSw̠>3OcWl/;\3hL<-%ѱb%e$"4d%H:^H@2AAAJ1sRztcBQI$hgN(|==RGZYHڹCJ~rD{Ӆޣ&ked x79vh4^xFJJT^zM&/Rw@|&8g995/qp\:7W`^?"{F}_?Q}v7V|]OJ`&@px@h e$8x"]xC=DO KLnΥ_F#6ȇM/K{:?0=-& AAAAĉO}>C";qn/A.q>q56c f6U(X8ޛ~mX䚖A6/h`JltLxuUAAA ( 3Kd6;JȵGs$Se#M_6DdITh6;K1(ŬL*CukJ|.QkoG8I}Fx׌?H*fw͸tEXoAAAߢ͎⸲GEz@&bF4DԠ9Z`݊Th>H rXkT /ɘV`& cK|kǪ7wnhWIs3X;CmQDoœ|]gRI U&1FZ&ҊvM5i+hAAA&T}vj2SWjJg]0RsԠi8q T Jt4cK'r 4"hwn    ]i ekj8B>sθ "T%Ϥ_v*klp!Hk!))(@#   (ҠENX,E0_vR/˓,<-d7-oAAAAcAx]a6;* 2]p'G,jYV0QTj]7    <͎/EČ6;*C@f|_ҤDG> gIk#)$;ڐrXgW Y11ןLo^SaautFD70pFz}p0FD5yu^DɼP90~awzʙ7))R[  f wxIvI"s L?6䔤B;qeVj)1^HJ3 Y׏q[pomhM`?Nu".m~nQ g{w7}Y+׽;iݳZhALЉzs5qiQXڙ"YoZbzY ?蟖.&S&7 xAA$0sǍsO͌Rŭle9? yIJ^HzdHĤ!aq0fK2;&58To0rnQ[yij7NL69c퟇l<3E[)t"?wE-kN0Uzgu2OV\{az^5,Ƅ'8`ZWa)R[  dTP q8_iЈ;EJuKt඘^9-[@-ӟDNlt Xhh& /OvO6d%vX|lß<ҬEs>0]=~uRSS%6x Wve-( ۽kr%}k3ur 2Fi)4&lwχSHe|.)N].YG7T`4e_AAAS}v 4R vY"[{(&x;"X9Aq*Zu]J茓k˕0dmWpamF9~YDGO}֧Co yG˺E.7a웑W Be/nZOo׎#AU^9wmfJ~rrUQKMUyGޱ4 02q/   ”xq.\Δ(XƢzr +,Qr4K i{@]S+^~8:.R>uh{h;NŹɰũ{tFRS[E]6/|il|}JۗTt})GK Q{ŋ \oТ )\<$Le)0}a4eb_AAAKoevk5C%yh&Nms |( [`+@6ܤ"t{wu Цr.=<%Vv7M_q  7%[œFQAx0( gld$!HF}vG .k>dy.m7kջBC:Me`w=d S{6/)ͷ)xl˝"e#׫U<ծ杜aXash?m\n=[MRNnxڣc7UyK'Xp#t͸|`6L%'<=ٳ%: {ԑԘ}IoQ/4\` GoX,7nx#5m:eқ_ R\?N&pe B6;*3g3,(?E NQ院"45G$>k?lh' 6/NҊaY+1tWJitHqZ'9>,M:{~b۷ ur>Q0͗d>5,+w^Qn!kM݆NJG [WK?wĮIW túD+t)oZ֦~5p "o(k\žhr͠0uOIBEFS& 7P x.%X?c"6."b1s(v~"N-vAA6W苀4[cZyfzpyСּu [h5t[ߟeC$5+ o;IeҜq[֭3Zph'~;$lOx´ ܏}m=AydW?yO* G5;ujP7|+}>|^~xȝr'-ѐgljN$WRBŋ `_9vADrpLfLmvT>=q\ǰ2YwK4(ђ([9sjEM%r@/ᛋr+8A!/ADe)?4JBZwnhmO \F3 :!;(>Z-YU)JY]+I!LyhAAĎ6;ʨ'fAGxY/MN hфOCީ2(VR0)RIY9] rK;3AAD死=<( Mq #>Н?bl|/4hi_O3HAA$ vA${6;w4~,jpРE\7},"$BAADh~ۅwAb(\ç6;>  Fїn:,\G  PFAAH`sK#NxYy0A    H͎: 6h~mvP3"rPFAAA؝|@~!Lv1hIiujd@ UyOg%qV8{ HP%8AAA`ǥ0rzJGI.pNQUMء͎_.&u+{.6(@CVbcJ_Imj䶮ӭ7l?ӹfjšYc⫒ .u 4N7k`#o9l2sRQ0;-3vc/Y,76闒chS")C̨'~pǎ Ag!x%g "Ḯ΍~ ] Hogzh0 ыhЙ#k=k_lVuN~?}Z"3[;G,UpG$PKd3)^FNJ""/?k"Ӓc{yҌua>f6cG)R\J\Ua{}D'X'' k'l:~ӅZ}kQjOTעμf]c A8GW;G<;yCĄjJm3y3[%Pd\R_NuۿɊk/LO?=gGIID Y눏?wE-kN1SA0_sTЎqnG5-xfJg1RVv%ǓhЮ24|| HpZQxaǜaDD6f [$?1111ò Sp g6Nl~#r0]jMbblD#g[/ĖfCf5։Luw IDATQZ M׿?*2Y2]]dfx2rRqvyY4߮p'8 I0da6;~D~ 6;*3tof ~uz^?G!곓x[YQȡCDps;b5-4Źgo߼Ty'V,"a(8|S܏whQ'B$5H{&&$9-fy3>BA[?8{}[yƾEG2 ؤh@]~\1"::(8ن{mFXr=jkռڣoX7#xe$"~rC S  nP?N4j"#4"4~v!` Ж{Wkt޺N@S'ߌ~@ݨJ]c*^FNJ""Nx񕁫4 ?e )˹1B(4L1\h%?>rLYeiBC{]'5%qA8PiY8 ߿ح}q-j<6:g0_?qNgK%JYD!;L\{xJ|)n4h%칅++yӪ[j8볿~L3]rOӶӡ_rNe)(CD*L-P$x9)P|*u^ S # 3&Bx8Apm3ri ƕuAlv1ꅼRdo}[]}z6n , SQK/_)pcO5;wUCQC'oYֿSɵo䞾W)tDD\niO[&x,x흟 Fl 1d%t٤+?;qVӃ2iw1c5#Gm1gur}4\` GoX,7nx#5Wכҋq AAAhqO. /R1%ܿ0c.pw кI*ltǦO?ݸ_GzJ I-K/y@wqI7jC>plgUy 6YC=ӰQNc\+葍Zlt~~;cO+NrMKhTR &:&wlcQ{-S}7{5w5n^ѿ`d2rRyǐ6h S  q&AA;KO7AĉE E={wM;w S]Z-RS𓜯IlvLqIؖLzOwǏssD2rDf:5T_-D~?o`/N^Ƌ/רQ]RʫWid2}G_=@> '8gkԞ<6Dd EKa{G~wOT>4.&cHlF$6;T2"jˮ!fא,b)Y.?2[M̐>U}FAA}i5\` bJu%gMC?'p׌cA^r:%n.xqNBڡcزDrm51ă,pwnܴ mҿF{  ÖgAD\Rޟ H9vA9`ZOLa{GZq㉳Kd2_[f tu$ )[#+%HĘc o䶮a ]>s AAZz:1X̱# NǠ^~tOE>a@lZa@(p>P0#6[wt+vAA@* `b~ލ"isXvmKٵґHZY~ /Nx(~tOE>W<Bh-k|l<=9/^vN9Kъ^@ޑHg} '+ "Џ ܵ'5txlj#?~'vI.M-{mK)I]dnpyB;7r<(@# j mvQ2݉c[E !+=х/~tOE>agp4*/M:^;^]Z7Οe]GL!C#=(@# b.EP} Y)>={w-` >;)S|`P2̻f=,8,ePFAAAu,H򗼨f}Q@& ~ 5}8d1]tGzDvi~Ɨ#[vͪ_̩@AAA- bT |,2r~SD.(T5j 0AI4  bSD2Pf,D&]I(DPwToK8掐2eh)Y;Ӓ\f:գ!+?nܶ\4w?zuCdFxŖw_: h7y~Y.="X6mל5F P T oHpnXa5CHTcf_vBweMH'kD[߯hC,m]Oz?]jK;-3vc6Yb_7,76闒ch減"s+XAA Lgc:iI_ht羀ڬFx69baqQ!XnYML BS~7+V1Td—_Sٟ/jU.|ke_-Q#ڮ!AmL Fx׌W6Z(Ȟ1rcݼfU^wj%2f3yRkKMo_0}D|DQGdcү5|7>= 9@6+z?-i>.7wY#O]]q; XAA8Iܡ@gM 'TR#@_5hN㏨,Su\{lT4C/gDž;ȐzqfnyFsoIkr.M^˶"r`*;Iyij7NL69c퟇l<3E[=u/\dPk2 #*:HթX~䳃xE;VL0d_̱?wE-kN/>  І'$SOkR痊* ӠMN rQ T`wX x=Lz YR'u tOv='卄k %ϳkZ荃˧#?wb}`STik⼹ZF{t;H_oDDw0}A@ +2 ED6S';@(-&awIiVvtMt:rܼ!YH !$Sz޲c>VO}1XAAĿHPsA7 z?鹥p}<ʚ]XӐ $Ru%'< xSؔNwDTԭ _eZ!-~퍩O}i@ɵKptfBH-z3CWEd/&=apm%y/5R',wkZDis޾ynڇÜw̅+'|=}ؤh@]~\1"f 1%w엽I(~G6n3ˆ,?ڣV9UW{ E@BUJf7ڰpwz31F kܡGD V'}43Z&`tڜf! A_Y)&k>;!ՠ%Z$B8S4RN%a;A~L&P*=rQ}0\#h'/aLI_B$@kMZhd# @ޜ7 yZUGR.vm"e6c‡܀{Wkt޺N@S'ߌ~|E츯Vk=ʊ8B;bhזutŷٺd'^ֻk x5%0)D+6]9cʑRvt|0"Т )wE;t?!]if֊̓_/2pUPDᤏv"Me!`OD*L?v#8>7cˡ7?g&ZϩX , 30uƨFG >zOC(؀ycRNO>|#]I2UGV-Z`!|[)_h'=^u@٬knE/z/vkߺe\}ڡ jKLuo:7칅++9LSU߷qgw[ x5%(ǿn:#&L~5]rOӶӡY&WTb;D`/.bk/й$b\г'XEaOMljH}|.F-#֖%Hf'!K8H,8PFS<աoN ]B܋RdOޟ7Zc_(4t2Pg/v"m" kq ;Zmc͓FVORɵ^%J5VЁ,"U3"1vu%I̯k}c-KjӇ{6I4XAmv̺!pW[A"q' &rmIӟjr /k =<لYIv1h$h | VH׾x~c2z]0ҍer(??O֞0O_W~}3WiY۫r"Tocw@r' a!*7^ B4Y^7klwmv+޿p^36qu/>$$o?twyѾs=Qi#*m<-a qeɵm#ڮ9yeBON E$`?AD$&rW)LW0g6;y`oNk1Ω0U]sn%M[ݙy&㻗6䣣O%Y37]d.}|[TIs7b-{"c9SM Y-eq&d\_d NxFAWll5=)v3:VCm0%4~Ȗ2ySGRcU.&L o$`"R#6I <~j5=ێS"J.;HIx=cAA<0s]t.AċťW1v-9LV i=~>/NoK5x` [N _p6/^QRR)W^kӦd&kb.u$J. c?qiB0BdCgKC+RF&XTU[27G[u;Uk[hZ3s;_|}=ШhH[~}@WefM- tf yDȯ-]tX/ه*A:]>PC&=z8 ,NAAA`_ O$(Rh/o" ]0GJ!uTg<$5h.+Kf!F"   ""~<1Bm/j,jlwiɪt'lsr&egQ)"_8LGINeȢ 8  b%Ru*^)S9x BiVs7P߂ gii[߰4VoQ7!4XO؆/JfhAAAq/ ⊁AI>&E.c|Kl>ߊ*m  )! kr <趬E$oADG !r Z `~BvB*Xe!)o7YC*o0j1(@# !GvA~ *NnB(4ră? yùDDԦ=ZϷ9SIgivh^zB |Tͨ//S%^E(b zZFAAD/Gv@A~8u F+(x(bw1I@)2$gU+'#EO$oPFA) к!rYAIj[g%fGOL܊pob"\8wQv4OYWϥPk%PM.z9%rJo'V$vB&֔Y %{Z&q]^(!:7'=K#O $zBIw(@# D8!pCЇP~L7"!C͎:Oo8†gf 6HJ0َR&*x-QlP  %XyӬ[/TP!Y yC~=,z/cdx p&{HH9mnMZ7ג7  "${ 5#vԿ$0pD?U7QZԟT$hpσN[~'hJʈ_AXWb\ HI5/$k#)XB]&( =3ũ{_,54To%[$Q0o{ p^\q/C'%%ӽ3m߲9c;kNno| )<8I ܃8^ IDATA~Cw~C5/x:g4A!z-\Ǿ|픡ݷYbg/ՠ.˛m6g5߾yq胋0ěmJ~/:]3._qvkYjizkg򈥊ז~Wn߾`dj~FIID䅂gmV$ Z^{sa~)" !p_6/6iA~fZ%:j^9tN}K#LJ"z6@LDg'e2M ,2[޲yxEJ.Olŋr`*˙?-sׯ>@~ zƗ^'e$"FxŠ u~vEb_PsM2cx})!r~^T;>K2A$Y=w(X?"riNk.9SJ>}"C\BfʼOz "〉oO}IkNn YR&:㫜ˏvkOl}^K?_7*5;5e^bc vo翹w5cwR#^|UcVb6is*N]4w3%ONl~l*MzM7wTH9o߆:|eW~G]R9)5E65sj̉q |?s}ڵdʐW*@K y B+R:9@ڥV l`.5 ǐS`P-雈/ۃRt.u’G5`ա+"2s_I0dxۇ؋/{yuP{,?ڣ}VjcQjaA/#'%NBF'R*rNpHK^!U"`E 8t\O>4'}F<"f"H %\*nYwKh˽+5:uo]'B oF\?Q#uQG$S준ƞ9>Sm2lq^7]>d$zɩOpƻ;bCKvex?)ōNY sB㟝]wcDtm.Iw7R+ Om=9xS4q{n)Bʕ,f;ϞC0IIDSx"'5i)8uHdU*Q)GJm"R},)vjЈ~r-L_zyHޥ{ڷnAߢv(qE\ymg0s) mik?>–K5܊e6UAѤsݻ =^e"u`M34 ^on_7kJ!XTaj3ƏGDD;8eH$x !%wW5/qAu$2,J/ ҅,G%~WL$R]U^o}'gOJ|Ij;˔W=VѯY$;6u*|FEHH׫|cӖ3DU33?䞾W)7$^FNJ""28S82KZ}Q5/qAtr'3 .H&ZH0ѠySb=QFvUe{ oc8ھW2Sޚռs_5-nOxג754~S|;EGWk^??sz̄ 9SU&Tͩofϖ,(Tꟾ@DdUm}E2292:Rݒy A|c"">Kh]A/]6?Y n|7WO@qZ'9>ڮ9+^Dr/fTomĩtΝw'j Q0͗d>5ys'tX.ܸ %rn哠WhE e+͝}Q4QqnݿyL2rRyǐ"k]ƌ)C )spHy͏xJ!F#T9 Q!/4\)/r]U.H^8 )A ?DyO9A ~9v}V\pJ@~o`wQT?5MB1?@ $DP "D@QAzSZPTWKT""JPHOINݝ='2;g؉ WSj+m۶2Ts鞊wyÔS*8L{2bB^}#K"&ϒpo\~^sKk* ՌJc"ԥ]SίobfR$ gwo~'af9&dk$BZq@ " H(?tyޟ>ƔS*8$)%tyagWZCM0EL%a@^bֶ 1x݄;*1n{6 [CB,JGRPAAAA$LXJN ,a?<`0y>wl 2ê s hDwU7AP bQUi^c=;:39bW:Y?$=eǯzR! $a):awZf SĄ/DΙ:/DmTjAPhAADFhDU (u^*W^V؂L 4SƢI$1!p9@70(2ola쿁 t@AAqQ:k-|`liG#akn*n0TpҰ 0~༑$"&T:ȼqCV,+}A%ABU@A 3#,lju,a{N$d}=jU!@\iSVSOsQi\XRָf(#vh7 Ҍ]l$] 7J%joJl7*eFZTLiԲը 9Sת>Q H]^!zOgL)T:)-EC7Sf L($,<@·!k,!@/+TlrS@  0*u;YQTRS55VepO (6TVGT)@(b$LYEw6˲{t1G\?Gu>'Lcl(7B*ٴUUZ/;oa.* B}n-vK4;RD; 5裄CFa~'w M{1RIECP,)w0ELZ̜{MU{GQ䫉gɻMt0|zc].Fi s,  rCc77j#nJ3YUL#+jU3 Ɔvakh*ʰ*jVBGi~hl`wQ6vʚQ\n׀sqUK"rGH{pXyF0r\UFigHc75;G%[@o҄)ŔbJAaH)/ؾ a-ײ.DA%8e y;ik ZHCsJBU0%TjP vnX5>Ҙإn 6_. hu ͞f!g*bݎ_?RLtRU%lǐb'TG"tߪtƣf LDe!~/!Br΋'q_~!U`h.LUAiiw'x=P&{719iCJ\MY84ᔟE}@AAo[ Va%V0zK{ jeŦ6dtL)T)6B6*͐^R 9n^ؙW6%`S} ˽4h"4!m KRd R>hY_"٥Y6/'I=a[$h˝_?_n|@D%5i{оmkjwZ7֮''vsn;Ou wڸ}3#_ݪau;zUv91G" lۼ)wvF%v̞d&l5}rZ xY9)a{>s򋚮:vt_fjjM5s#t.hvk 05sj_jeͦBs P @Yq[mYYTk; i~Vhѻ7"w(-vg әjeeM @060) Q?Z go57ճ~&s,`).0H˄ դӝPf%zJ%LR- J(mE<>>D5L1|ڳdhH&;OH炙n[Us0ibg'- EEX`/uEm^Zvc#6._6ejnq]kwϷ1St˾C"?yq^yc~qmYWʰx ofc.o5<>c@7); /Dx}gQ m]nC2{V)a/+'e#vO]n?L7S|Ih(Os:UgйdHQM=WGFfKZ/neխ4&qARMجj+PWjfmOi/`1"bɔSq@ie|XkT{:RSu[$ヶeځЮ3&qQ_2:4$r JCN*~ZUc3=WZկAFD}qbU8 >%8@CI@͔f,b#)@+4(E2Vc[oUfIU)3M}@*$ fJ3e~}l?Œa%zLIHD{=a_[}Ņ`$4꣧F9⭆Jʏݛd+, 2 *+,(5[i- rV ifUfo^C-WxYψxXd-H3?і'a+^80#kgy_RLضضnɦ閿n-f˧yuWѥ~gov6QuIS\]=<=ny$A:3@5~*}͒ =ry:^^s7֞n38޳'e,"bƗrJGnN S[Ŏ5%mLYf8w)cNzM\2$(8lO K#c?e{:~"苜jMd1:g5u+"D/=R\5 4v8B5JAQVpIkEH1 c6S?JlTp0`s(k980ACqA_4VS8Zi(.jew\D-EKlVoHJ,-*l"dl$qA_,*(7t= _X{_H/t!#1z@ߠǹl]P;LiL#凞f]o[0 #IS|p)D^`_K2E <YcemBzޛ޻g{ff/ ͂d"||H:A.|n%v̙싟.Io\" j;.n/޳*گ>,?4ǫHݲ'qY|iΒ綉aϘ4bS:*-=+*+lo9Qbᣊ9M+>OK%&bnV_"--^VN""f?TW} {F"2X* H5VGK}j xHkzɤϔeof*jFVAra#`V N_yW&]_Z6G;5ilz:r55U[ED~?sn $hE6jԵi(G\b굶)-%Bh\2A' -D7!殘^viu'0~dY+SrRa'jU;FݺOv>Uagk!S-l%wLz_p78PV͞l~XkH\_[Z ;},~T]aۼ2 ?xH]n-%uTR[$e,"gϾr^}wBꍜ/4pC1mI&}pA C4MM- ퟄ1[7T\P+c-6 ]a][ظ"RFܩ/wpVCWgH)iБ¾+| 'A?bi )tmv  i < vˤ-;)fzI׌tF>RWUk]s/^xrun:Kj>'uxpY4.K(4QQ5.0NVtY2LRjR\qK-(tw x8))m3=gg4 mx7mIJs>=>3lĴy Ai}g*RQJT_jeͦP,TfP5&n+jlr>ӪK<T;v036l4 IDAT!΄JˍPI7s0M}vj1C`S!uy-^D0j]4z} i.Pt!?*Ce*6nɆq(z;*ڄun9qwX8B~y{8)=rsX#ԃ B5֭_?Q~L_{ QF*OXULUauvIIYDD+{փǚ'>8{0v®6!cG9nB A $*LciQU6M .V 6Sm~:bjZ#*l7FD 3`#"(ͣXkT{:RSu[$ヶeOUmvUu4jjuba"ܲ$V~B(EHBeJҗ;렙lN,oVf"T౩N0&(DKFD\$|d0\jx*:Bڸf7>|iV CSj]^`ÏNe 6i1>q oyn>;0>ȶ >qrk}YE4uR;8hѪB5\/˶Nd{SM۸8JN<谴tzц_,EDDwͽxۢKH8@ A (.F8F_c36urBooo|`Z/l*A01DV#qVSR.qV%J Jd^(QŶQZOZvc*h m~%Eύ[(%GhHIXHrl߬LB2X b/`"0T!g^.۽C9ekϫ췁ߞ]A&VU;{U_;rΝd /=|Գ3ϓըһ=w_3!g+b;E{rݪO79aijE N޶tWEF-9dž_?jx< ܻyS>!WmF%}k>inⶽo]~ј08Q5:iӐNQ^m9ݪdRou޻Q~yz:MٹK׍_u@ kGv1P'ʸggϷ4cL׌:L:1mG=ݺڪZi9e?5 ozo HAIYDr?Z1gio4zlRYOB!  pVjuW*IE5tJHs"H4L`00oAqV{r2gs%~;A* j\] AZMS/nmOv-8$ɀphDwͽx)N     dZtS! L`ˋ `>;aA94Dӄ`;    AƐR@Ӳ $,$]CJAɾgK=+[H tyN y r͢X08[/,c0hAAA]^4nʩBS}v~-] +Qo"+M\)vp".)DļJc̍'\õ9?;?zNjm[L䭜2_PtsX&SH   ./v 3" J>{0OSVK%EGVM.K#Ho[|AMӓdQzR H^#PFAAAA:qXS)%;jbW){`z l   "ctyIc&Anmݡ9b%E*t--fע!(_Z-bqV&%mtFs* hAAA=Ic.//: rA?H|C@JqKR*xi4dgϖr) i>tNF5Z8LNgMߴ[u9L[mk=gO[~w^=w^+]^Ԛ+gyڸ]^;ytZ#Əώs;fO[uhkN˚>9,A}5]u Cs?r(  rF/ke)$qACmS3A'-B&]Ҷo)7[nMVp9%Gb!=u,K$FC3&oRvAn_x:VçlZLӇkwOn#S_iR+ 9ǦlN쫿?'Z&UÖo0mW:V ^gC(G-طuuq|o TYݯ&#V٭W_hC.AAD]uнt^yu$,3  t;2/lۚU2֠YK|&߸!Ez "ѝsv(ڿ"Mc:WS^x㇁Ng5o0r(v)iwKՇ pSNKM]ѮRg)C,#盗 E9W~c홞6zjpprZNiZvXW/4s!  CJAy _R4 Caid@|HxȤˋw <;ɯ}{tS|DU)ҵ`A{+9H)fQ>sCYA%@78py[g= Kw\lDUPϚc- _{Oj 4z~$ڶ ѷqPiU5:9P3BPzKzWUiZq7&RɇjkjpP2 9^A(  3\H_4M+# ˟Y6a%1܇0(γUEnGiTNj@8з3 w?:2Qb,ђd*4&pO҃pK=ڣG[[g~4ԎY/wueot %wM=bb/sz)WE$ouTM4A;/umZ+Qx3zmJa~p3snwX+p535U5e Av{̹/"SrxQAA<)'cvJ+Zaڞ5&{'=0UJ`eW,lS"E}PE[W"_3קctBߟ/o9w;NŹً|kHGCH0]ݙ=sw,%bI7ҶkBKzΚz|>Нj}[J,QEDRl,jpаٗVΫODW/   _DW7T*kXM{ ]aߡ"j`g`pG{qLA4~οǯ?wc'&$&&$&&4ɕ^3H& ^U ǃi#?e#}j讹/]߮nXY֫-ť>K-( `Qgzh@ڔZW/  |0x%w8bL= ]^ίݿzWb +Qu./~vS+ Ѵ0Yuy]IA,dK"T0TJJ<= /^waKhɈ$p8 v+S7=;amU-ިzhiOJmzcL}rY]aۧ ,3,nUiX]r?W<'yƱc6OHLHW/  HDutyIch$ ڹHSceWK=Q-%;5hr^s"Ҡn1@,>pMfd+ l֩.oA(jpѮ ܋K:SΏ;Zu @#k̿\ڧ)SF۟~Էi$Q>j+#Ԓ(.YSs=km\=(%wptXZ׷? "kKߺo %sxxQAA/tyI)¨˺#\.NiFTWpV )OXDޝa3hQZ?{mUfM KuS)w#Gꉤ *9٩IE6ev~d5^i;-a)jo72xq:}'t89}Wÿ;QPyD\/:lsϺ&rd]yc>Dk-wn|WYsv_mE3§Npxdf]l}toe{D~K9^A(  !e`KWIŷV'3<9cy`꠩J$Aa_#,v_o:+x53a [urk/5#ݛ%}}l2Q 2i?2㮍]C鱲oP=s{56Iƌo G61;{ 섋DH bU4n$NAAAqb`4T(esCW}v Ai~ hAAA)Ԡ!nTj*oA$"    ɇ;ZyŇ TAAAAA2$n  AAAAX4 sPFAAA~ãWds#2vA    P =]0R4uUl6[A.A4-l"p3K"F$P   IEJ&QjPD0[u sr޿K놉 w4íǮE[ _x sVo}>qBRA 4E5q{M[7J|>pGɹSv|,1!1a;Ε8D=/K'e-$":LN}tҀ^wE AA$x%/g+zz&)^Ʈˋ1dʎ9gWr2tEQߤ͙ 4KOf+{ѯˆ=;k{Jֲ=GϜ=[Oz3 ~#GdFNJϔz.=~1j1kwϷ1_[X讹/]w>ofj5y^=u"#|ר;3,mΞa d.z,xY:)nIkt٩3&oYbP%CA")*RV0MpFTR _ sQLWwLӋeh,z.b<s3o ` $PUl6M>>**d3v֛{)UTjmmlQٯlpߍ\ӫZo/zeT*FZ޻Û{jN/Ձ4d ケג'uzi9#7zk,#盗 E9W~c홞6ӊ7WB?^VN""~Dwh "apAAB|0$׾p gNghBó,ZpFr4 @`LUo/.{eD0lg9 ,'$siNq*Xy&]?b0o܎9ӗ}%1 y{|#[d8<ڭ:+O︸]fۿʿxϪhĖ.є$ցG&|xpMn}+#u[?5Q.ds]f_w̗v,yzn(yK#&6dkGQ٭cOU|QEꜦɄITb+f)3&e,"BK  "<$9?ZbϏsRm?q!VD2r"G#d&%2hLG_h4|#bJ24=H@-V|ڳ֙$t&F).qmcy Y҂m['WwZ7gۋ,٘8mc4ґ՟l^YDt1aTU-ѹ-ϺcW5 P`W>#B;CA_ϭlvv{̹/۽fjݴ$0 %^o`hJj IS&CB! H'#}OFm0\Ogpe9q.gKYGy膌ba.R* ܥg&4Y\jX#Rl0xR&@[n]*SjǨ[n X7la-"[Sd޳Ij.OrJF|y?;&@=7du^C7Zܢ}G(mˁJ6ٗVΫ n)"<{EDRlд$CED~!"z!/tmQ[_z̡-;_ IDAT;1u^5BPh\2AAFd se*p a-X{mbs1k癬r,c/G#|AّH0gL>dV`bf#duy1\GǸfk¢ tm,'ǝ2FlX=>LZҼV$eup>RWUk UԪ讹/ANx-4cTW&V:jcHw)q_OtRz+7t?9?m<CߨVMYgz.ɨ BW[KSqK-(rR%Kw}7,|f>c94.  q@:ykԲal[Y `!V7Fͅ>ȷL#(?HayY +T0" &Ҩ0Lo.}l׊3MXƞwՎ!eg̝O}w;WW~y{)=rsXk _|?'˝W<|#5OpU{ >]`WY NݪҰIED!|{ !(@%CAej֨st#IcƚFc'V{,|2*cu˲vR-_ӄ|~,遼\L tv[)̕ ߿=Ệ郺Mw*%VS8QM9Ӌ>Xο.ziR,nlM{؍h<23uNغ8mƄoeHz?'?2`Az潳F sB! H2 "*&g/M1 +qX05!2v$!a0ZfLs2Z^4]>v !oh},X߲@T>WmF%ok>顨nⶽo]~ј08Q5:iӐNQ^m9Ks̗~\raoO..KEZӠ>kZS ̠oo֔o/+'e-_…/TU=;{>TW)J_E>%CA2K$ACH"^@8Cy _Y8)^/vC dy`rBn)["9?;ѡ]`{80 m-^'!Nm0ΟXzJVT/_i۶dLTG!tpڇ)L`JY ޵oa3Ap(w#; !r<(7*7@G ;H>gw~֐[,gsP M6Jf[9\wd:AAA$\ E iYI~qjm* 5QlUAiTpnyGOPFAAA’_I!QLB:B xɃB˶˾ =`96.6]4Kz"   9xha,Dx,taV]^E'u.+~!Eyؼ\ΐ.3,7o˝l}VQFAAAAТj\ZͅZak ǃi!r~#j;ehAAA$P0/| 0tKY`#%s!87ʭsH@P]4     a0eJԖ pW>&d  ,xq}^>k9A4"eΘBlrg:=t¶olٳG־4^ߙ9dns۲6?[wʄy?ݩۻILqRӮufzp[{58zLcݖ"_3A ;bلӱJڥPՖR;T_b:JB*g9xAA# w bAG0$I$x]]껚Hu*Х xi{~cd*Q )E8Lw{%W}:fp3= "mGw{jM[y#wQn 5V}7N[~RpV>\B)^90/  [_56"ɊP6%Ke%u +X|0XrI1 W%K5to4FW d6N,_GWjQKuZ}Ls~?tԹ#k̿\ڧYLHqZ5rƇu4u:'۳vnƵKֳDB,^90/  ظi!#VUUB"|&Eʢ6b@[ w%+S<* PXi4S+LK?11Is6jH&hu>\?y܊y'yߙK&Oڐ3}`JNm{ﭼz|Dyq&o\2m/ -uN0hmڽI-ٞ{6uGuKY>WWЊh<23uNغ8mƄoe%Onđ] !}F AAD|ZSzXt"K-9J'Azn@;W+0'2^׾WGDo!BݱuLbay/gN79L W[p(z|k7mZϏ6B} l]i;׮ڨR(k^IF?>CPg_mIPT} 5g|f5˜- qQ?y18<ݪ[F "mB=*F7㮁Օ>kZS ̠oo$jSr/T7 K  " }'6C!UҌ} ./R*K'J[_ ]V#I!a$ۙypfw,n3Ei'-C؉Zۋ6ohn: .՞S3D仧qp|z s>   +e?}쑵/~' AtzmU:?dz7N)]k~)![! nv乳'}Ƃ![Y'%le,"C7]AV1vF|B! <+E,G d\o6 )2ۨ>KN}ԠÐo5׮b-i~T=aY/唎ܜVwxx_oukyΤfɅ9߼FO@//ʹk|VX>rR#sEٕ AADU2#,lju,a{Nޤ`;*'7aK3-Je'Oa!',)%v̙싟.Io\" nɭ]az2[U{VE'tZ|)ڟi݈#Ze+xqq#DL>oNbs5cf%Vv|5BUYJLAo/?AuGdkTw=IQ٭ܾ;4Gt$_MWL[<Ũȝ+ag 9 ]a=JfxzWoωkFK95׬+Q"2T{Zr!u^8꾝M?0xbw:Vx晞36Phj ]ٵaN5薙k7}PՖR^ZlQGi9/+'e^2Aas*gw\>_H_mr܌ !#H!)dkS8gw /(^Yv3b:gl'f(,qؓ2BQmحw^6m/E+ QՃ`[7/替z[[Imu=1/,gm^طv>-osʟ+o8곓 ˱ ./\Z>-e݊%Fb6Z333a/岠#>ݗC *<'&|̖xӽ~KO2׉ ߿=Ệ郺Mw*%VS86Q㗽6~IUޅ͛y= xdfs.:u q|ی Qu^_D;xA^pE j)|KxiO$rRsI+Ha ݣǻg.tVdf\k.ɷIXOLַ˂/~- DI3q؆Zh-^LnXVڕGYŗߚ]>C>,ͶM]_& yxw[~1jey IDATVMgBŊMfk`uebFfq@_} ['Zi9e?5 ozoM%e,"OXTtd ",v""hg'AGZ=B>WԁFN3䆛JKwzЯ)C Z\)V Wy#$u}>^,vzc':kl/`M$؉ WSj+m۶2|;ͻx{D>8Ɣ TpRW7L Տ4Y ޕb9Hѭ(;X)$iH)痱KNNl<}LpPxZH+/S2)Hm UBz B%+Nx~:g|\K- h}:A ~j?+cw;{-ΩS%JMvuAO0Y\3&(ILAK|r0ΟzlRϵ~^0?wR/AQAEH j!ɀ ZHx^w͢G:3ZIJX9 k*En}ۤPH+Lbn\*7=KPFAy`H),5՟%Nِ"_/%~4>tG )ջ`@J9gtɖ&Ky񩴟vςi z./>)e &CGg.B'T tmY̑F3F襩Qk\%]ի 7]~jIa٤w 5Kv(@# HIdDTp0p攡}#"-WDrrX @+PC2=:F'Ysx[$1Hn'Q;M@p:[؄Е:KIhAAtٻ?;9JQh Sao9.3Z+DzX7k]9Y+((G15}ߟwzg>_ܤ`I5hl`(yUL`WOd*mAWnPEMAj*;\Tv:[}q4  vSRw" B7{eVkUׄ4i'W5Vej/wM,uZj-m%:J 26j'XK.T– XUZX\b~Aҫ {/BSY܏LzU־y&UVB㹫1_U`bæ7Wtj*% S[x0u ,o:]<꭮ # XBb墩u%_SNVc;g.@xԖДЊuu$h`y-͢2H7FtLХ*53R:szRkRRVjPZ8Z#[/SD".WG* Ѕ1]Nq4F6xߺԵ/> ; 9d1]\)GTϑ'}CmzpZFf;ƄNqL GCld8V?"F_{96l^,4v=HZ}քXb;~Vr.;pbP}oXl˩w,Bw6sa-tꖚ]kF]yb}Čvw68Ytb!"T4OaMR Iz9E=V!OCdΚ ufޯ36w0/zW}-ҧ'zw1_>eZɮhh~w d9V㭕>n?3>.Oi]<~t/VuVc5؄IKQCbyYBa ,%wW~uc9RTcen0v=$;ycègw u֙䌸o,:yȆI}Ŭa_ӥݟ4 ȐSH9.oN ~&q׳>I}5hTwΒZzvB+6Q}WI%jDt# "\Tjn,A!85Dfig[4aE6by u@5/޾껺ݧ3`bqV=ϋ쉚ђġeeJ G-TMRmܷyzpSBl'|cfQ+}{ˋ>ngE!vzSdƗ<]YH 99d ^iK9Xҥ!6 !0f3e[Y:аFk%M0RwӟLBwW]wUR]9gh9*BzpǗr>YEhT uxD5hB-AՔXT}{:c\ XeMyBdj&T. 9hO`bմ넥kf[\=׍Ryv˼+;c[>oSs*,ծ䙄p`O=PnRM˗?)5˷u!n]N_ti|s/,ynh;50b4!D}ek?N'zڌjkШ>Jgљ:sJO2|KL,/r&3 H 옕RkSYWEU(#_( R ZDYHjh.ӟ.#8CdшQUEd>|{չϞZ9g-C$jo~gBzZZzZBX2{ۉc=ݤt}_|[&,儰7O[&dS%?>n)DS?k*zt݈?)Yᳮ}&KKZs84koPͭi&`UA(#Uy' Y0@N]_WNc]sS^zL 7Ih; S5b6tU9[detzۣwuت;+Rֻ|Fu)h.05ւ3zLhp7׈\4 @DqX7(crDp4K/y_TFjч&*= ;&ξe gߧhr/ٱ_@ξ,joW~p \ٷ>sEntAv.p^Zѥ+jfmpoam3Z '@n57(ɹ6QJq\b[ɡYu)*#^eXsލm+nBbҲ6ֈ8:26G<93J W,E+} k XE6%TՊV/WZ>WݐC &F T񭞕lDOFo51)P }}~4if\?U1>}+N?)ZN杝dIci =4oΨ4{SlB4_~u(s Mga6Ȧ!.r5P='+1Q;3Qq⑫Z:MJ*I](r>f<Zփqnk z/2^`Xtz/>Tr 3S:>Rŝ}vu34B7|J]U+9H8tBeOѡA)*aBU..Ϻ亵:ޒ*p0q19p]:- s ˼`@W$K^Az~aI>ca4bǃɻIAA2Ĝ&},kF=Qe.Iǚv;VܧmuElG}mTs~~V߿1wNGqX4s ΌN nW`() &:U= 7W) w g %W"V~ ԕ@t'KM_V6rۗ}✐!̓yr^EΧKnEH 4y&.Zˮ[QviMӆu)m>zݤ#llW .ad~MICI1o-Ŝܔ; SM cBFV)[ļ5'b_/)+g{ty_+|[.c}x~Y3N78.ñ5zjs]yWZVV4fk،?੅c7?~ W##6χw5aovߴ֡*,Fw0#d|'VYSƽ*N'zGRX0?ICۗ2hs~-SSz ]r￑ K@c3WY r9~Wh2d7N!'Hߓ!{KH*N)v (ޏuj 3jQG(A-TJF ̀6o aAE&,>qeֽsvL!2=;Y߶hiV|R7}/I9U)o8a<v <,}-+I76ظ Uu`+o߸qϏrĴLck2q_2+?Lw d:soBE6D>*$[ת;F: /AL <],ת,6; spg](u:Z}֙_~"p|z dRZ4HW,{~Л? Pg[_\A:+AwUեyk4nz.MĤ`Q˹Z\-3E qʉRwEY2Q7yVP@\cK^T.p/UT?FQBgT'r4E.kڎAC=_Qh5lװ[|U_9::h4SW2۲Xlqݽ 竞RNJATХKJ¬8NdXZK ^bdUX麲4n"V~PʬUҬf/lnH.-(%rmk&fCʸjX"Ui,j+0X C+pk K[@`g:\}&{c%hIHD'nX>SBd۫3*6)Xq \̇55hj*ڊ&cq\I_&#  U,6JʐPMZ4!yz R Zķ + nRsV9TZmEvϨ&s+y `2(=u-t9혺.**MMg!nYtA༃RRn?3P\yѿf[tnҳI=7wrB~d謘:6Yr /gЉY[J ]t 9=^LxpƆzW&TrF̻?/<~GVIGP* N v$ LJ꪿Ӊ5j8(?CSY}e_E:yZ0bG$+Z^Xa!C&ã!6ԇjnˇliFײOHWdY)52,Fth3luO"$VNaM馦MۍXm^kKN$WJwoy'r]ll\;~)O=OX"$dy>jӂqZ֯>T5XeENbPzWʸQuV P # Y )z;Yvh^Q= g{ϟ(8WU_e0mz\;% na\'Vsf7(QL馜"v^js{FImɭ+lB(4sQ>9"<;|%μ~}UU+)we/C!ڢ#Bs/,yMh4I&RKU]rRYBBU?yIzpo7SmRrhSf.^Ct|ry-O?1 9m iiii+x̄zkf eƟ?Bev֘ZJ򩾷s"٧Pr-0P>&bm֨Uc̴ APiO~K_jfރꢩw`5e"̧`#`f<zcqnߙU* T~RC$Ha^@ځ)luU^&V.<ͪN]*gi}I{^k57 tȌy#P՝@$3q mTDJ#Oh`"9"tH8<;\RkpJtbQU̼+ݚ+κEG؄I/V>FFojkd ]*tʡKe^ ]$ ItH~3ݮ u6wubUĊF+vgQUn:xj;].Ɏ?sFk2;|6s{GBojFB.%*͏r¤"ץB,Fw0#d|'VYSƽچO˜P1 J Ҽ0as}pvc7+Wκ@G(xUʍM眾otlХ*.zI*t,#}tUUݎJjjY6ՑTX hJ}41i8`-}ƳuS[Z:ġ#?YӳZjmAyof twc0 sKm|TuvnpKí9b [ئyVǭf1KO2j}܃3 hռE}f"kgm+-HF"ip)O>_rs0rjY cBn )qqS}8/aӍ?euKAT%E٧k9򺙻|eTb Q`,$,{ ^V{upnj9#ϟ܉{бkؐa3| ;q...NMMstt0h^eeR[̭uToRQХ*.zI*t,%;Gb5#._2)Ay{8T>24&d & jAVyÐqO5&cl:Jaq8J?\z "(Ԉpwτ܄@xot,!UL(0:+ ]*]rRYBB^I5D(Poՙ"Ɗ Fdx*)c*nY|DѬq\djP5R9FP}DQaHXU6$ "-LtuFYg 6k،-_>Z%3d]EOKU]rץ%EPU/nW_2Q pk1]S3jPODC%N{7YRnj=Δ(pb'>\Wɀ5f`4it]COKU]rRYB֞nW_: їӋ5-EU)[ E?8UQ׌ UM@x'U}&(@,Ԡ@?>tYE ehMAk@8OA+5UΔPzC@TDDhԺs?)XYXoPԔ  `rs֭ՊB<}Bc aMy7:P7au[g`1n^̊-xEOԊ`xv"zV+_zDlaLO-ػmsiĂCI3c6|/Г`>i}u;<֫"wk`?D#5Q9 \TbjNHZ ;]jVU(V^CS\[r LMio)@* Ьֽ YÔgϮh~#jȑ]mLHOKKOK;bC!d="NKIKK=F{+5jw~ɗdafU'?{{djӳ.'=ݤt}_|[QTf>|Se%?Owj^;uuQw%;r !W%{(gǤ疋 F,+:set|f>)3dDVҶNT۹ݢi> >p-_ԋ@ VDPN^zc^m]lM  L!"g79߼zpNJQQ7۪q-kGdhCSriRI4e[Yy4-tgFGYշ4w9%265 z&n^H{%*\6i[5ǮK~,9ʱ5#JMZv+'mk-T,qpK(nl^d0d*T.+yx~Oײ۾ ~p1TԳWx=5(*U(G!ƾHKK`T8s.ޮiݚK*ZCOIY5>J̳t -Ɩ\AEF CzK^lO1>N5hĎww%*p Sެgc7^5kS/](+HYϯ!,yHo֡aN ,FxD{ ⷚqgF'{XW}qk3uB\AEF CfLX,V^BGWh6 p4⹗=CGdԥ~JɎрFϾ ] sWַklW \>.?Onzh됹G/8^?_:ו) wҍ?JV*K]f̈^UF6m}?6[kμ0asl\:2!Ɏ? gZk.+5HaȌEa!333Kco>m<Y|F_oU *QYj;e '|!֮AI'f԰ "BH GCꤟTu,gBL߶hiV|R7}/J?jn+PwSR.z>ߊ%O02j5[g~}Bwl<|P!fhX!eVe )`蜃8%cl^d$]aL8B!qn/PZ2!,vf뀶~vvu yyDխ0&wJ\L Kt#s+zzb-߱9` ҭ+_zx<ֻب&N}&/TL2qdO<-jBhq>:u4R:n՜T!ʵ nYxVMf c9t2%T-«jVki {v:yds½w,[WnoDnyҟbk cg?ڃlB4ѷE dͤV+J%Sz2"XkC&/2"J2o=s5-Kn}N.]nwZo<4ӷ%1k3@,YT\V!̆Nw:w?.kV՟yyWTIF֡Bt?݊} jL Ȯ{= *!݃wqL&8! fub&ӡS?iYY顭Wl7aO>xȍ.Iy1q1!{c/b^_Y,7B!=WU==f3."֭Ȝ7%8_w& !16Wlڧ2j]0Ѽc?-g҇rzϭzYLo=hΚ塭kLKO|}Fu ;]j5Rv,i.ӟzE/+HH293k<@1rXʗ$XeʣmhR.])O /?VҢ+jWNγw|?u`-sHcMͺcmqv-[jVOuSYql;LgB!zA;b_\x"͚.fe9qgfM$l}qo&'/-8p؜-QwsrT^Wbۢu{ *!un'wh15BmC:V/#cM4!T;!s~ x囜7IOo>\ayٛo49ÂB#27CRZ?˯ݭ%Т˰R:|=/.ζ(^{>c3 !fne?Syں7c׉^tÏz.?0lӑ.ѸsG|ۍ޶O_ٞBÕG,HƞnS˧Mow.C5 mBD+(nFz=G}7{lMF8)vq٧9[0W "# uY_\4@٦9jKfp=?m}ɰ֥9Ja__q-&V9GJo"m䴗_9߾O؜ Qe+NpاTV_4nZ[+Эh&K,EWǸu9.gV!ѥi9O^|X}Ƨ2Dћ}`æg>&͚{ثW%ͤFc4xe1S[Fz1DB!zݦAM !W)ިٗ}dkl^y.K̄Oe е|H/*:V Xrϋ8/ }Uo2ohvO^صW[[SB."f3WX8#㪋(Xׄ੹yXgی^9ߢ?R{e񇫶Dp͠B\J\;nKOoP_친"ڼƟTskGUrɁ>kEkh bF<Ϝz`Wz tMq3C4U;hes: M:Bq v &_4% $Ъ-Uk@sy:|$ Whؔ|v ܕcۢۥ 72=Q䕼q:?{<ѿuEi\zv/86B?%l"PLm]["--`Z)qMO N7)]it*K*ߧ,LYhl?&gx֜-{'H64%7mo9l9zdce?7Zzyw!6/g$UjJ̳t{y M2| R/2Gm6NF[}ݴi?o?~UqA~J}ұEQwh!6 )֞6O=-ƓKʸ/.ݸ|zM[ߗI|(zilBߗgCq*~{?_$nb8g,n9]jfE,Ԅ-#kab^qƵCk7m>-+~̡mf,*|v9;]Y4joeeN#,z=:v7N|U&iBI=`t,+XBw=ƧB`B.>mP'l<ʿY9J7!pU*NͲfԓwkpwftbw^򊒢:nmsV 9_ԋ1wNGq90dx$L!KG!ޫd>")S{ڿd$Y|[&~skTE5ʽJ;q...NMMstt0h^ee~ ѣ~F#jKgϝz(ť!_"L^FJBIU,^X2V>kנwBZ3ojXg!΄!Z VL;s٢i_gRuЩ-'Buꈑ?% sa 5c.ԟ6W-+o߸qϏrĴ,P- G!$׭2<-6yjYxUYlBw :!V3| R/2ކGsZuHGb 1@n L h#`s| 5lƖ/d 53E3鱆!j7'tp0Ԕdx=cx) FH С 89v:0c#ia hP @-t ЌG!o޼v -Āz2R:DM:tB177wttEe@4fJzBPP|@kZ%<b ]SaLBlME8 hhQ3˜P? F-٩Íutc0Zw'}V*ǓV*(;S,6ٶߙVh6Eݐsń) 陽alةw:Y3| R/2y_Ȫb9̛E;x+)%ƞ3c̯ ŚZq0d`0ڨe[Y:9b⍔>޽EM_wt13q>[ۊRkhwʝklBF\AEFJ;Vsf7(ZSL馜".gaCƉbaC (Jw;ie: X5FF#~Ɂ:Dc&Fxb?hjs:Eϳ=KPهBJmbǗ6.;͑F>T=F18=_BĽLkoHD;Sӌ j%x+.O1>N5hĎww%*p S&1tfľ*@hXI5tUc]75&HZz1]N![8-6˚QO4gĝݮh+[N+HHRGL9y[?U;HsclL[9v܏w6E!N)>x]ȥ4 8fd?عvJb8plhWm .eD8L}Qq>ӷ_5 3zTgWs )yan4K25go=~]XFm$iCDO5OLhÂM5 ΂7Ym7ӯD;Yȥڸ9GJB1{ o$p ƿ➀Z<5Ӷjn➽gbتc!;kKY VwwMS4SVr'}S7rgqDlC\혰lξ}.xFTbhJ R2Rn~q9.=A?τ0g^_^PY혜=}PHK78ؼ}CĴ#%^Cc+~b5EFn?{*zD ""_vNJW3+Eir$WݑJؼ}ʩJ/l}c9!p X c_m^plB+A]/ho[mwO'C|o濋vc!rK!=.rمYO.36\g$Xd6 y>u(+@6ٻM]oh\+6!]ͱӪ# X@ܛC[Yُaa]hH7r]spQc{}Ҧ#u׫v3lה}Of6?5ascx&s{%ݨ#hvࢿMV+WjQx^=[ eYbIQܲ*Xѐ%FCӳG|-'׋{ hN#D7\- ]# ɓ;gSBH賩Ԕ٣?X}&ΰqK[UNޓt3N',]}e_iEjЬV&zL:ii3D|/MǾ̄H<MOVdG/:xOzwtv !%Φuæ>׺ɣdws}YƃgNX2hkؗ2S(ɹuY?݆\:4+h2cKVthE?(NcY߹G;f}7}w3-ai'|dHXEnT fVMgH6B`2VY֬ܭs `wrqlHg5Il FkF}Ñ$ZvUa?;:Mqs\c`Ӥ5W4=˱k]V[kjQ]>hQ˰ʹ(KѺW7]HgON_d""BXm˿Ok޺eޝ@Se^žeT:1TUcg‘:}IKr>qZw i"`vhYQ>,)KƄ'=kOVߤ:Tuwj̿FLڐԼV7NPu/ܨ Goaen~ײGOw;gZr]T~;fZ`'^&^ y%mwV:;8wZ%3#R[U?L 5qzukW3N2֑=gS~iB蘸Lp~tJrȩ+f|ڒˤ~^~eZU={O8uaPd5PPZ"ӫƷw|8vvjj%S:׳^}<ޣH2aމqIiO_vpT쭮kLR7a}Ǝ|vJ͗eEQV³.Ң7-:3 a[=RdŻ_cqduO-14"-Hx a1!2b3?Iu E¼Š oSٖ)ԽC[r_'dTu 3^s[2 ah:I΍NhIOL-}F:vI[+/<.( ^%s#a|{@:&NR#))&y{WW/خ-N=w(cW-*)=KJ6Ū{2L/@]Ђ@=rݜ Wj7m*\~;VIhs'OqNtBqlϥ}xѧyńI>=lOaucu7fa'Ba8kLϽ+&D%e?أ\W„Η2f"~/!NFu߇~y!!Ɲ\2;| UN3γ3ݷѝ+4ٓ{B’?#"^C5;ȷ~V/.qzTcGv8Ɠ9f?ȨapoƫAWWN\͔ZK:=m%67Bg]Nf}2v߫JPT P/\eDnFsv(lWi[4 0L&iPXո3=XbhL[qK#X?϶дrr^Sy B"kfޮm2alS(ɬ-A j6|g| IDAT PPb1 hU!Q м~Lvԍ#G3W=?lBv~y=tҼmc,1-?vFR1锞dy$/BDD=z#&l/]:v&ΧVn>o?'짬8gpז3K5~>1@P, gPS帅Wq#"Fٔ×'_B_]}$+ؚ}glJ_ G^zXsm>|):@ږ{칲ChlmHC n«ǘ#~7sƇEj(7c̊1#G7?d1B[zownN+zN+w:fd1`V_}5Q6r??>FtB!rK#=hsof Z/q̢vs.‹k.[[Hb61U*@Kv.MNˮ\_mGs=-8^MHt7.!} RMG~oס\Lj.5RFИei8 @(tA*(;?7>oTApeK-ְӷ|%b[e0]W)$B|D j*դYZ( 4kWgFuۊ:͊zy]h.Iz0)onp# X0a }} kmq OKO{|¾y-ZEۇ?U;W/󋪤')⋙,uiK)JVÎGi 4T˭l[9G#6. B# ec,;yYz밍,Z,tbAÕ@Ƒ+oWwgV2gZʬiNAT[tQjdb~YuYK|f`f1 r}E/2kMӈ%Ճ5Aʏ=kWſm݁]AR,2Ur;pɫKaO2ϗeSrdb '/I]۫ICSPW$x願BQaV̡%Knt޾G:൰Xvj4ZlHA5x^v#x5?'xNwbỌ;M/HbB&M>bXsY˿o=~]X\"⽌;iahI2nf|v$˕/ѵQb1yy-uNLu M-}ƳOm z܃?mC'CC.[D@Hs'|ϧe=ݱGԍIߵ޹~ߠ%c~B#'84GYPqMScMгy^cfrG}l"z)-VKݨ#A"n0re#2TJw}"W j5站-_\eDnFsv(lWi[4 0L&iP(ظ۵1nHEfΙhPc[iUp Tq OKWvЂhP@!P@hP-.@/4ť(ncn8v;S(m "G__Zs)KQO6 0'c-]$/3ђKQ{ Bo;oWKQ= P\I)W9ť(cW"hI+_*sԲI R]*S "y{eȅ7Z{m8(9Ʊ޶K6(EvmGiiiG8Q~smxQe"&84ӽn׷$oor S=+޻I߉7^MI=+x練 N-W0T$e}5&,h%P#WL0.-XlcT\~c wOtpp =B!rSoFfE ?_Ч!Dc<c.bb2)Ee#=hsof Z/qFOڕ\aH Sj X2J;+Jq)k>%#A~W7*Exz hߙR.hDŽ%2_Ex2ӱEq;9[|4R?'ZSXb{7RG$v"MʋΎKQ}I˖d8D젚Ns\}wBDϮDG+?ڎS2uW0T$f?,0)dOm~äg}{%,iwlzZĭ<}'9--5싦#Xtm~p}ۻϰKB~!:mJ?eOxW U !H\Z2fqTDžNJ}KkꢿK!$UݗIJ{|aӉɩ<7wpL}?q<5T ۣ+HEy˺yi\O?3C(.Euv<}ݙ hYZumˬWbYN3+ Kj-I7?̀`0sYX&CMv47`j'ԧ{넿.ڡǰϗߊaC=^v"~oulu!_J"~v*4a9.! 2=heO}w0`R'֫&EqLZjQY$%7SvoOwjÔw}4',CFK"UzubHR}RiRr"1Ca@mnn;C0cЕv}vk׬vp6kaD"OE;ڄOڠL3v5>LHɭs{v[D^/ĒvPO[@fQ^\nDukq OK'%·.Z݃[ [Ok_C7?t ^:S)IAGR3YuiRr"1Ca@mU/\ݼ8Gm˓sBh z؟Z_J-zD[+~\z/ܟ=;zP3f݇)b bO'Bajɉj^yT=R_W?lme:!^aqf|SI3+ KjR!6rœ?_Ea !4:H4[ނۛ~ezb1/Kn_ځ(521/%F>3v0gWWʪR;<˫n/+z''M:t Wc)K]fi4,i<ɱhŪv$ܥJ7f$$uvm_}P| CEbÒ*+xo|pJJv(;f̻1abErTUՁ$ ⃬anƝ~CFL)m."x願BQaV̡%KntޞE|Ub2r׎n|B~{鼝W䉄W}xKP{:=fGoڴ ce6Exٍ׏ÿo=~]X\"⽌;iahI]Ya>et/Dl6x[Ǡk=ݷ9b|[M뢼"h`u1Ca@]ֳ}7x9bos]s؄.i% 8=`~ewSW "ZI9g-lj@+UExiCqGk8r7ߡy%oor S=+޻Yxywb+cSc/np {eq$ 'W ":V/= {exdRqـТGF[WVKv3&.\dޭ=BCF1wvKhƠ`VprҞ| R-2 % !"*9&KZ|Tr|]).Eqܧ~$ȏ=ʾ΋ =о3ť,&\RѼ/By:v(n'a&UBT}7l-ťz\|$/);z )_weg# E7ъR?_.(k %WmΝ4=r.e;s}JYgWFvգ=Cӳ9v32C7+WjT%UV&?O~t̺uc88MOKKOK;!Oz(wRþ(/ /j|rxϾ*)}wyUvIL6hQ:8;׀%9y7&EgKjY >^&rY$|rQǗ~_8x32+wRe5~Jܨ7V+WjT%UVhoff[9 Y_A,!&;h5P ΐ 8x_眰TFi5žkgu7esb^[Bd^`w;{;w`Y ?dže<)tsC6md5t9CuIƮ)'[;x5aJC>!% L}*L1_$iĀH+H*Ò*v`Ǡ+ݝ֮Y7(mD*N3 Wk*2<3!28ޠG/Ǿ,߃LW*Z fmWQk\mתBP8$$Rf :K_3t 5|0y]?8cEbP/f3Ѷ| R-2ʰdʪt~k.\[n^n6؃GY-Zq;ӷbRlsELWy_~7vBQ\RGajɉj^{᥾auBfC+SfʢmZda@mU*&_N}\˷(l=!FF~˻(521+%F>3v0gRJŬ#{P&H\z\XI\;H8ni*Z{u2,VPǷ29O&,sK'+($$uvm_}h[rAeX2P[eh}_I.e'ߌyׂ2f4Zlw1Kd b-Yr,BfƏ|/*.I9skӗ\kQ7SF笝RJNQqqQNJ69kUi? ^^`]/G{oZ.T[WT%uUZgk䈉yv͵bBLc7÷;m\>'f]fd=l!,||cg9''kp-j&cպMWry'DϼGj/h7*$(`P8xو YcU+WjQx^| !DwDC -77W144\E>W _͆|d}3^も4SSd0>pt w/..avm$R{s9 @!(-洳PA 4( (@B 4( Z\eG_6iP+KQN]pvPExٍ5i?" KU ]ε,_1]{ѧ-_Tj%ğݶx8d*@HI^Y>r^NE%>JqlҦb;6=-W;44/ON ~blJr Y}O,VdE+HȨK?n6<@(&,h%m] futX&=O]ʎMiMeS۰{>;%#uDaSH4)_Tq =w|IʎE4b@++Jq)k>%#A~W7*u0Exz hߙR.v`DŽ%5 8՚<RBx&DƱ䣋9ZP$N*̾ӖRV=G.>ȗ(&:d_9wJZlj]UV Mf ƒlD\AEFP VYZ26u?a3ֽGw TǠ?q롼/OINKK SU|{6}IP/DTɑd⨎ |xEepj*J^797lǵ# JᗽX}xgZhĔmÊvXޮ9\RV=Qܘ9.T IDATh"UIYZum[jlkk.cD{+H*Ò*+@sM73`3-rdrȺɎ,Z #Ts1ox_;"B?[7|UK6zRBg8 mXzm{LٸӠpT}8_v&h\w]~; +浻ua25`ĝINi fBuGH1S_J>S)gv *_T2,m'{{ 2ΡOnZYH': &'-&|'R/inѴ^/IJΓ 3yZi֮Vmm>z9ei=qk1ށz6>l޶hϥq!CB-.Bg1" 1xHb>K:kUrAeX2P[e a5-r7/Ngl7QjlAch\Ճ"Rj!D*㴴Ǎlԉ3|w|VlRm50N}%eIxsXRs-5*gZLY4:_T2,JP s' 4"Ѽoy noU[j:?խ2a5!,sV#8KDR YGL8l=#i2,B8nK}e5f\:/(K '/I]NY49_T2,4>doƼkA3 av{q-6[4r$ ⃬anƝ~CFLiF|Ub2r׎nzL7-=U(*̊9dn67~|QqQNʅg9[>eWiOn։Yk^] *yty9[OO*ҵQb1yy-uϙv[WT%uUZgk䈉yv͵bBLc7÷;mD}?v7ni8h/au !n }?&d}ܬU?`ޫJuZv5Xa,||cg9'}7{{%" #CGldzD?0(SDmF?lD[FG6%-W ""DBƭ!4d@rssC}٩h:W!_ͦmҀoF+\PPfjj`2 ӧBcznƸI"P9gΞӸ j@hP@!P@hP@!P@4/n|P_R˨keť(n>z]\imF(.EqmzqRTo:/4/ RsKQV}Ǯ=E b V[@3 RcFZO 8kmua΄MJr97q$=zs6x?sG+)=mnZ>=`4zEcvNңI1~[?pԀyYR3b~Q/f곪!`"k%56>:4k\f /Zm | "$4ꅚlme:!J qf|)+7XAa@ YG&mx?L-:YD\M4:HԣwOlo[Fw`q۟徐b|t,sK'K '/I]W/5XuAa@=; a}sC1Y¬K.jgwtΫOD% iAŵlǷkńL|tժWm x"&㝰X.5~~˺>w9ExٍBMAZOxw|]wuq- RsKQV}Ǯ=E ULO/HȨf2KYNWv` KڪBKMiwlzZZQ7!uI'|m߷.̙)<;1Ƌ)ɱ7gO= rhSrՆVyeSe\ف)/h+V%eEҦD7F9mbF-hTr|]).Eqܧ~$ȏ=[/[ϐ};S\b%( R?'ZSX@JOrR48ŘQfB=E0|"Ň(4/_T!J?;}I GYZ26u?a3ֽGw TǠACy_Emz2G@d⨎ |xEepdM]'i*9\RV=2IUfCqVV]2+?lkk.)+Wj}eLف(-h]| ; 'qY&CMzO55͏!&:BR,;:߲'i-ϴf܁ӆMfgWVٚQeI @׭쀮E/7W "ą]j1@HÖ IY-dtAW;9ۭ]vpjSbsc1bqAkG|_$2"GkRwŬ5G?. o^ GL{_ke=ݱGݔ8?t#5{1![D&6fGpQ]WoO~wfqDad{?cBwCx$n˙<5TFkFQG$A2EaFeTLZ\AEFu=xKm(jȒ*;&r3SweGtfCM-YߌW 55Ԅd2O30sp6M)½9sL ZBԋF1iwQ7¢DZZOKWv-8@!P@hP@!P@^/P+%Rhɥ(罆\z!RAc|Nq)ʪؕMGњ| R-2Tv1\T?yV%WPt敞,J9D%?Lqh^{KȫUW/Ʀ$^<&I@NZ\AEFuG^zq+ϵA Vyhypu(;Wu6 hz(3O9ܹql#./y{>;%#uDa W "p\B߲xe+ƇiDUh^F- RAwŵsx ?«Ot~n\*;/3d_@pIMGK`Eq;9]p~⥻y:v(n'a&/>jsu t=E0|uP-W "м5/#e57aR̟sIϬZJX-9ʶy;=){‹Fpu0^JoÕܘ9.h"U0(/_B_xY75@U׶Uj̶_3ކҪ| R-2jKP2QuqNzif BfBݾ,!&5k(_Sm{c !zSZІSOZB!6x;~AOex*;n]]?ub4'q1{׫M0X fV.Lg"ʡeZdeZv`Ǡ)795t;8qչL6e%GZnQ}f/XgdoƼkA3 av{q-6[Tnhl7Եd b.YvbJ9bޟzҡ%KntɅ~eܙM CMZgeWwXzosG=Q֥vE+H˨!4/AEM}F Ah\+6!˴9v3|{Z !Nc)1t_fYVB72d ڽ}K3~[B36C[(7^ҳy^cfrGZ0ڍ =" )"6#^6-ChZdTJ}I-77W147yqtz8FW _͆|d}3^も4SSd0>pt E50sp6M)½9svLaw_i/ ËHθo7h4$Ų۴TTbcc]$5tPZ&&|4>(>zC3"/Z9@Pyhqg h+:wEn.=vl[uc oSƴ6ɘ<5)kyL&ͭc&):( ;[߯:dUt{gsݗr` &^Xz(I>ot%<6&ʏ|&-t ĉ6Mvlۻ ]~ .x˴BhI S&Iy W첎}{IjUU46Ř0ed%eWeٰ1;'BBHћgVdL]L_xM!^\27oȘF &ϼ͘/;iC{g+O_j~\ !HbL\Y;fżVWD3oSj'\ IDATSMViZ|7ǝ kuu<{0_fugw߹BIFT6:ln~e^qDꏝtpGcyc}c^ N>|qpk= [ʥR.i- .K/~Zfߦ3 cĉӭu2\l7EuJߵ_ o$Ď$=ʰ\~Iێ{B/ħX~qoĤ[Mxf팥6,v1X:,iHN_rQˮ~Z^soSjSM\/'$('|ʹ7Gב>(`v4|Z CVuWa56Ř0eMܑCA @)M@sڹ%ET}R ۢqܨe¶r3y¥xQqm6=Z}(AG1a/o9.˯,$]u:ӻ]jn@ͬM1f=LYSV}FZ4<\dϭ9q[邐U+ %´߬m7c s^uҊ[XV# ߰dXRHZ,Wk7\GAyN؎S[;3ҊS2y *_*uovt*)4Ay+46Ř0eMUż3r2MfH^~ȶWBb4*;;c@>ѥp mZZ5^ }\sqҹ,\"" Զc@ޤf\ tJ{eb\@}H@F  4hH@F  4hoЧ ;eyA>Whd91vglێ=-qB [A?'.=vl[uc hemȋViW?q֐SQv@#Cb\zjC1bYbxոwr* n5xʲeZ5 #MXǣ7#6/ hda>:5,޿@3P3&}!uT/ "zeE!.5Q:{h"<l,׿u1k+ )Qj·!}F:fFM"zVvqh4t,P;WGZ ;邘+F C=ΑB*opE//m޿@`+:tt^NЄγCsCt~n4b`j$}F/\u{u\K N!$\hI ;)W'/EF98NWT %KiǷc5t(3be eo/.7bwHdLTo#{ce\Y>~CL5gÞ2h ݣs%9Iw}5 B nNtiҴ,WJI/y'ӬAZ_!]~8#Yag6-):͕fbN]Op敾5m)uIԆ3dAIF|e>ENi?5'RYi90//2!Y![ gl>f=˷l|9bҸ~YҞy:\Z er+fpuY|_GzӠNe\9pY!sKPF88Ǯ9R!OڲŨ?7ع.yEdxO@!)*IeXz;~gPzvw[d@hUKlXu]YCצ]ߎnkaq-f._Ɖ atX|Q\/e&NA*,D1 H֎R#ʳ_ CV,ZZwteGZV802sFWyQ{Z?y(ǩ͘^llAIq#*>z0-!qQ,*)6m |:M\.OMIzm[4U@FNj*in3oM"r|oIr&?ٺOj"o[d MBs=oCm׵ ^(u^uu4a,E赫Ÿ%Bq[ΐ%RZ|jhԼ"B?d¦43¿_ ׅ0gѾ*/2l%f=-_OĞT|/oQú([E)MB+${!kdgϜ jjZo4=~'e$W|9ӈts" փF-Z*H{t-'/S3—hy <{L;3=03n^0IǒN͏=V>2+s}}ғ;: ~=N\]Pi~gޣBAޣb#MvyFY٧e7Oo;nv'4-|Mi̚ |M1_ΘG 3#ݗvQ4W\M7Ձ[#\=%yD!ZY^m}gBme=8gXG KubﵞnlGZwl߭g[<!rG:0gy<>_|&o~ޅduXN:rB]spkhyMŝd~g1+-Y57-I vtOUkfsW-%jjӋ-8U_h% W.z*O>|XO NC*n,?7[4RrbpL@a67>K5s3u\W-G!#QQ9-}vԟw'ڳXy+OyZ 'l#AF8e<{N"1s;v`'.K]8ݘ 1k>|҄-9kBWwNPjTÉR0quk;lR{c(-0`y?NslFg3鬞M):˳c܍Kmx/{^UjLYbg3tlQ Dh3T yV.;1%oc2 ]l[ե`Tw?.aiu39ދf9*L/ͳ1dI<W[Ibeϩ+] "oyZk&?TF/32'MS*jaTJN1JYʖ%ueVtQ&I{b8 EHQfݧz՚.ٽ wL6F\Zt*P1ߚCƦv;qE8S`ܦO3hq켦LqH0^e;cS׮ȁRS$\ńSgtifv0euR;N!Gkw47WCeuڴLr0!La|6o[t>Sk$oG3]ŷ6SW)RBdB/ ngzO[)fS)\rÔch5uOݳk98_*XLG/*\pj e1Т\ ϩܨ0gּfjե_bWn]z!tXԸܷN&ZLI{u*+mU%Kp^ ZO^auU\j5j9naLAS*j?FCu uIݷm1ڽzV-ʸw@?)۳xϛ׫6fΊ5TtF)툙Yҹ [XnSjjZˠnAjLe)P`v*;2s6y!mUZ72qfOҌw[uf7. mkWGRFECumZC6.O1NWX2TN4YJN^v!SJ,ԬdTDyq ^:RcUP]$W,'US2Q˥-P%9ʍ?MXf|gKr(]_K,kBӰY?9YU8^n6Fvضwr1bSD[IzSEe&[qgʩ ~o2옫g.'f/9F骨P+ 5)&T .䙉0cHcѕN$@BK9t. e~!KD2-EMӅOvJzLYjmR3AMSlmVPR||ollTsmެ$aJjg*kC Fmk~Hc[g3?˻WӨdnzT/Ԫ]q^Uct,.lBo+/z4nh0!D_a9f=~Yi Wυ~eH)b-;)k$iB?8v*;CU$*FX]"EU~2n#/fcaTmkB[ P\C]CiBcn$YZrsˬ˦0U>KUoSkI_ a"&U>wPش$)$?\Co%I:8֢iZR(N&(3}_^,,*ҢL,-S#,ߐV>9KW)t}mjTb鿋x)TV*V]TRh+z-jբiÜ473A*"geV\0¤:M ~~֯_X)n0>\Kx U~zBT1.^yEEG_ |^TPmj-J/g Z8#%@pTiU ZctxS}Æ[W^6*b OE峙D꒤Elxw<"taRTUBBRY!}?(%23zEoiB2%ΖVyYi ,R7:m=Z3Q |%Io>kN.m> 9W*+f<}l &9vFd}m! o\;r&N2TY /#bx--RժE#:8qn|FT.弉9; Fie쑲|/L[z]ƏDpPԛL&M>uo؉]JVT9P.fzܰȗy"\^$}8AMv:fS̞-P*d?cdžmg O~q6=û ~W{.%gta҃E&[$IriTVZf?xzح$;!嫋e,K$P&~|qЂVj ({v7ӆ[e07Ƭô/Ei7_ʰqTx][Iïiv>ι=}/>#_*I {!ϹU4-y\bag'4)ճDܶ<^w2ON<.aȠOo[/&kj=Bؖ޻zb?wNzTSe?l3CBV=M&R*ø=GS|KA2kƸ~k 2~1u)9EDSACm9{V C'w=G3nJT]6sҙSd퓅kؔѬp RJ~u^D4! akϗq"*yZ\҉wbečCַ͗u0gѾ8NhK/P@"\vGcJ@V5IDAT@SzsY5%;0}˜IENDB`RunSnakeRun-2.0.5/doc/index.html0000664000175000017500000003515013541777402020107 0ustar mcfletchmcfletch00000000000000 RunSnakeRun Python (c)Profile Viewer

RunSnakeRun

RunSnakeRunRunSnakeRun is a small GUI utility that allows you to view (Python) cProfile or Profile profiler dumps in a sortable GUI view.  It allows you to explore the profiler information using a "square map" visualization or sortable tables of data.  It also (experimentally) allows you to view the output of the Meliae "memory analysis" tool using the same basic visualisations.

Features

RunSnakeRun is a simple program, it doesn't provide all the bells-and-whistles of a program like KCacheGrind, it's intended to allow for profiling your Python programs, and just your Python programs.  What it does provide, for profile viewing:

  • sortable data-grid views for raw profile information
    • identity: function name, file-name, directory name
    • time-spent: cumulative, cumulative-per, local and local-per time
    • overall data-grid view
    • (all) callers-of-this-function, (all) callees-of-this-function views
  • squaremap view of call tree
    • size proportional to amount of time spent by the given parent in the given function
  • squaremap view of packages/modules/functions
    • size proportional to time spent in each package/module/function
  • basic navigation (home, back, up)

For Meliae memory-dump viewing, it provides:

  • sortable data-grid views
  • squaremap of memory-usage
  • basic navigation

Installation

You will need to have all of wxPython, SquareMap and RunSnakeRun installed to use RunSnakeRun.  You may also need the "python-profiler" package for your platform, which provides the pstats view.  You will likely want to use your platform wxPython package (i.e. a pre-built binary). For Debian/Ubuntu distributions the prerequisite setup looks like this:

apt-get install python-profiler python-wxgtk2.8 python-setuptools

RunSnakeRun and SquareMap will install well in a VirtualEnv if you would like to keep them isolated (normally you do not want to use the --no-site-packages flag if you are doing this).  I recommend this approach rather than using easy_install directly on your Linux/OS-X host.

virtualenv runsnake
source runsnake/bin/activate

If you already have Python setuptools installed (a.k.a. easy_install), you should be able to install the Python packages with:

easy_install SquareMap RunSnakeRun

You will require a modern wxPython (e.g. 2.8) and Python 2.x (e.g. 2.5 through 2.7) installation.  The setup will create a script named "runsnake" on Linux machines which launches the profile viewer.  On OS-X machines a wrapper script runsnake is created that runs the runsnake32 executable with a flag to tell Python to use the 32-bit implementation (for wxPython compatibility).  On Win32 machines, a Scripts\runsnake.exe executable is created.  If you have added your scripts directory to the PATH then this will be available from the command-line.

Usage

If you are new to profiling you may wish to check out:

cProfile Viewing

To use cProfile to capture your application's profile data, either using the command-line, like so:

$ python -m cProfile -o <outputfilename> <script-name> <options>

Or in code, like so:

import cProfile
command = """reactor.run()"""
cProfile.runctx( command, globals(), locals(), filename="OpenGLContext.profile" )

To view the results of your run:

python runsnake.py OpenGLContext.profile

There will be a brief delay as the application is created and begins the loading process, then you should see something like this:

Screenshot of the application viewing a HotShot profile

Click on any column title to sort by that property within that list.  Select a record in the left-most list view to see a breakdown of that record in the right-side list views.  Choose the appropriate view on the right via the tabs.  You can resize the borders between the lists and square-map views.  You can select a package/module/function hierarchic view via the menus.  You can also toggle use of percentage displays there.

Meliae Memory Analysis

Note: this feature is considered experimental, the memory consumed loading even a tiny meliae dump is enormous, so real-world programs will make RunSnakeRun quite slow and require a very large amount of RAM (far more than the process being viewed).

To install Meliae, you will need a working C extension compilation environment (Meliae uses a Cython extension):

easy_install meliae

Now instrument your application to be able to trigger a memory dump at the moment you would like to capture, like so:

from meliae import scanner
scanner.dump_all_objects( filename ) # you can pass a file-handle if you prefer

The memory dump will generally be quite large (e.g. 2MB to describe an application with 200KB of user-controllable memory usage (i.e. not the interpreter itself)) and for any real application will take an extremely long time to load (multiple minutes for 16MB dumps).

$ runsnakemem <filename>

Screenshot of a meliae memory view

The Meliae loader in RunSnakeRun performs the following simplifications:

  • only displays memory which is reachable from a module (there is normally > 1MB of unreachable objects included in a meliae dump)
  • treats modules as memory-cost barriers, so referencing a module does not cost the referrer anything
  • treats all (reachable) references to an instance as sharing the cost of the instance equally
  • treats loops as being a separate object which holds all objects in the loop, breaking inter-loop references but retaining child references, all references to the loop members become references to the loop
  • eliminates dictionary objects from modules (always) and from types and classes when the dictionary is only referenced by the class/type, the cost of the dictionary is folded into the cost of the parent object (note: this means that function __globals__ references are "0-cost" and do not create loops)
  • compresses large numbers (>=10 currently) of "simple" objects of the same type held by a single parent into a "<many>" object with the type as the name

Even with those simplifications, however, the program is tracking most ints, strings, tuples, lists, etc. separately, which uses a large amount of RAM and slows down the GUI substantially.

Code Access and Contributions

RunSnakeRun is reasonably stable.  I don't tend to do much work on it, as it tends to just work.  My (personal) current wish list for the project follows:

  • Speed up and reduce memory requirements for meliae loading
  • Clean up the meliae loader (was grown organically from a quick hack and doesn't particularly invite further hacking)

If you have an idea, feel free to check out the code and implement the new feature.  I'm certainly willing to entertain new features or bug-fix requests as well.  The code is available in bzr here:

bzr branch lp:~mcfletch/squaremap/trunk squaremap
cd squaremap
python setup.py develop
bzr branch lp:~mcfletch/runsnakerun/trunk runsnakerun
cd runsnakerun
python setup.py develop

You can contact me directly if you'd like to contribute.  Or you can just set up a bzr branch on LaunchPad and request a merge.

Roadmap/Wish-list

This is just a listing of things that either I or others have requested as features:

  • provide comparison views and "progress" views that compare across multiple profiles
  • (re)support Hotshot profile dumps (removed because Hotshot itself was deprecated)
  • support Robert Kern's line_profiler module (line and import timings)
  • support IronPython profiles (with cleanup on load to remove "noise" functions)
  • with a line-profiling module, allow per-line profile views
  • support (C) calltree/cachegrind files (as used by kcachegrind)
  • clean up the UI code (very hacky)
  • configuration/storage of preferences such as column widths, rounded corners, padding, etc.
  • utility functions for capturing data

Other Tools

RunSnakeRun is by no means a comprehensive tool-set for profiling, you may want to have any or all of these other tools available for your profiling needs:

  • Gprof2Dot -- Converts various Profile formats into dot-format graphs
  • Robert Kern's line_profiler -- Cython based Python profiler with line timings
  • KCacheGrind -- KDE viewer for CacheGrind C-level profiler or converted Python profiles (via pyprof2calltree), KCacheGrind is basically what RunSnakeRun started off trying to imitate save that RunSnakeRun was intended to be Python specific and cross-platform
  • profilehooks -- specify which function to profile by using a decorator on a particular function

Releases/Downloads

  • 2.0.3 -- Stores list control column widths in config file (contributed by Gerald Dalley), minor bug-fixes, coldshot profiler support, wxPython compatability, do not use separators on OSX
  • 2.0.2a1 -- Stores window position and size in config file
  • 2.0.1 -- Fix for OS-X loading (32-bit mode forced)
  • 2.0.1b6 -- Fixes regression from introducing runsnakemem command
  • 2.0.1b5 -- Fix regression for OS-X during work-around for Win32, add program icon, provide a dedicated command alias for meliae loading (runsnakemem dump.memory)
  • 2.0.1b4 -- Win32 source-code-control bug work-around (disables source-code view on Win32)
  • 2.0.1b3 -- Performance and correctness fixes for meliae loads (still slow, but not as horribly slow)
  • 2.0.1b1 -- Experimental support for meliae loads
  • 2.0.0b6 -- Fixes and enhancements by Marius Gedminas (percent-in-tooltips, code restructuring, home-button fix), display source-code for functions when selected, make SquareMap an explicit dependency, more robust selection of "root" nodes (better first-view selection)
  • 2.0.0b5 -- Add names of loaded files to the window title, use same colour for each node, make colours cycle across far wider range of colours, bug-fixes
  • 2.0.0b4 -- Win32 bug-fixes, drawing of labels on squaremap where there's enough space
  • 2.0.0b1 -- packaging fixes, UI fixes
  • 2.0.0a1 -- Eliminate support for (obsolete) Hotshot profiles, add squaremap visualization and callee/caller views, lots of UI work to make the application more usable, preliminary i18n work (just gettext markup)
  • 1.0.4 -- Add preliminary support for standard cProfile/profile profile results, note that we do not load cProfile results incrementally.  Switch to numpy support from Numeric.  Use setuptools for distribution.  Provide source repository access.
  • 1.0.3 -- Fix stupid bug introduced by last fix
  • 1.0.2 -- Magically grow the stack-tracking structures if we pass recursion limits, this will be slow, but it should allow for loading even extremely stack-exhausting programs
  • 1.0.1 -- Bug-fix, increases stack-tracking size to 10x recursion limit, instead of == recursion limit, but as of yet, doesn't seem to fix the reported stack-exhaustion
  • 1.0.0 -- Initial release, no fancy features, just the raw functionality
RunSnakeRun-2.0.5/doc/toolkit.css0000664000175000017500000000232113541777402020303 0ustar mcfletchmcfletch00000000000000/* Generated by CaScadeS, a stylesheet editor for Mozilla Composer */ h1, h2, h3 { background-image: url(greypinstripe.png); border-top-style: solid; border-top-width: 1px; background-color: rgb(200, 200, 200); color: rgb(0, 0, 0); } .footer { color: rgb(17, 17, 68); background-image: url(greypinstripe.png); text-align: center; border-bottom-style: solid; border-bottom-width: 1px; } .introduction { margin-left: 60px; margin-right: 60px; color: rgb(85, 85, 85); } .technical { margin-left: 60px; margin-right: 60px; color: rgb(85, 119, 85); } p { margin-left: 10px; margin-right: 10px; } ul { margin-left: 30px; } pre { background-color: rgb(255, 255, 204); margin-left: 60px; } blockquote { margin-left: 90px; } body { background-color: rgb(255, 255, 255); color: rgb(0, 0, 0); font-family: Arial,Helvetica; } a:link { color: rgb(51, 51, 224); text-decoration: none; } a:visited { color: rgb(17, 17, 170); text-decoration: none; } a:active { color: rgb(17, 17, 51); text-decoration: none; } th { color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); } RunSnakeRun-2.0.5/doc/greypinstripe.png0000775000175000017500000000021313541777402021517 0ustar mcfletchmcfletch00000000000000PNG  IHDR'gAMA@ cHRMntFdIX*LIDATxbb&ښ<IENDB`RunSnakeRun-2.0.5/license.txt0000664000175000017500000000335313541777402017530 0ustar mcfletchmcfletch00000000000000THIS SOFTWARE IS NOT FAULT TOLERANT AND SHOULD NOT BE USED IN ANY SITUATION ENDANGERING HUMAN LIFE OR PROPERTY. RunSnakeRun, a simple wxPython GUI viewer for Python profile logs Copyright (c) 2005-2011, The Contributors (Listed Below) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The names of The Contributors may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. The Contributors: Mike C. Fletcher Marius Gedminas RunSnakeRun-2.0.5/RunSnakeRun.egg-info/0000775000175000017500000000000013572471440021243 5ustar mcfletchmcfletch00000000000000RunSnakeRun-2.0.5/RunSnakeRun.egg-info/not-zip-safe0000664000175000017500000000000113542001311023450 0ustar mcfletchmcfletch00000000000000 RunSnakeRun-2.0.5/RunSnakeRun.egg-info/dependency_links.txt0000664000175000017500000000000113572471440025311 0ustar mcfletchmcfletch00000000000000 RunSnakeRun-2.0.5/RunSnakeRun.egg-info/entry_points.txt0000664000175000017500000000014213572471440024536 0ustar mcfletchmcfletch00000000000000[gui_scripts] runsnake = runsnakerun.runsnake:main runsnakemem = runsnakerun.runsnake:meliaemain RunSnakeRun-2.0.5/RunSnakeRun.egg-info/PKG-INFO0000664000175000017500000000140213572471440022335 0ustar mcfletchmcfletch00000000000000Metadata-Version: 1.1 Name: RunSnakeRun Version: 2.0.5 Summary: GUI Viewer for Python profiling runs Home-page: https://github.com/mcfletch/runsnakerun Author: Mike C. Fletcher Author-email: mcfletch@vrplumber.com License: BSD Download-URL: https://pypi.org/project/RunSnakeRun/ Description: GUI Viewer for Python profiling runs Provides explorability and overall visualization of the call tree and package/module structures. Keywords: profile,gui,wxPython,squaremap Platform: Any Classifier: License :: OSI Approved :: BSD License Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Intended Audience :: Developers RunSnakeRun-2.0.5/RunSnakeRun.egg-info/SOURCES.txt0000664000175000017500000000134113572471440023126 0ustar mcfletchmcfletch00000000000000MANIFEST.in RunSnakeRun.desktop license.txt setup.py RunSnakeRun.egg-info/PKG-INFO RunSnakeRun.egg-info/SOURCES.txt RunSnakeRun.egg-info/dependency_links.txt RunSnakeRun.egg-info/entry_points.txt RunSnakeRun.egg-info/not-zip-safe RunSnakeRun.egg-info/requires.txt RunSnakeRun.egg-info/top_level.txt doc/greypinstripe.png doc/index.html doc/meliae-sample.png doc/pyaccellerate-64.png doc/screenshot-2.0.png doc/screenshot.png doc/toolkit.css runsnakerun/__init__.py runsnakerun/_meliaejson.py runsnakerun/coldshotadapter.py runsnakerun/homedirectory.py runsnakerun/listviews.py runsnakerun/macshim.py runsnakerun/meliaeadapter.py runsnakerun/meliaeloader.py runsnakerun/pstatsadapter.py runsnakerun/pstatsloader.py runsnakerun/runsnake.pyRunSnakeRun-2.0.5/RunSnakeRun.egg-info/requires.txt0000664000175000017500000000004713572471440023644 0ustar mcfletchmcfletch00000000000000pathlib2 six SquareMap>=1.0.5 wxPython RunSnakeRun-2.0.5/RunSnakeRun.egg-info/top_level.txt0000664000175000017500000000001413572471440023770 0ustar mcfletchmcfletch00000000000000runsnakerun RunSnakeRun-2.0.5/runsnakerun/0000775000175000017500000000000013572471440017711 5ustar mcfletchmcfletch00000000000000RunSnakeRun-2.0.5/runsnakerun/meliaeloader.py0000775000175000017500000004734613572471233022727 0ustar mcfletchmcfletch00000000000000#! /usr/bin/env python """Module to load meliae memory-profile dumps Trees: * has-a * module root * each held reference contributes a weighted cost to the parent * hierarchy of held objects, so globals, classes, functions, and their children * held modules do not contribute to cost * module * instance-tree """ from __future__ import absolute_import from __future__ import print_function import logging, sys, weakref import six log = logging.getLogger(__name__) from gettext import gettext as _ try: from ._meliaejson import loads as json_loads except ImportError as err: try: from json import loads as json_loads except ImportError as err: from simplejson import loads as json_loads import sys LOOP_TYPE = _('') MANY_TYPE = _('') NON_MODULE_REFS = _('') STOP_TYPES = set(['module']) def recurse(record, index, stop_types=STOP_TYPES, already_seen=None, type_group=False): """Depth first traversal of a tree, all children are yielded before parent record -- dictionary record to be recursed upon index -- mapping 'address' ids to dictionary records stop_types -- types which will *not* recurse already_seen -- set storing already-visited nodes yields the traversed nodes """ if already_seen is None: already_seen = set() if record['address'] not in already_seen: already_seen.add(record['address']) if 'refs' in record: for child in children(record, index, stop_types=stop_types): if child['address'] not in already_seen: for descendant in recurse( child, index, stop_types, already_seen=already_seen, type_group=type_group, ): yield descendant yield record def find_loops(record, index, stop_types=STOP_TYPES, open=None, seen=None): """Find all loops within the index and replace with loop records""" if open is None: open = [] if seen is None: seen = set() for child in children(record, index, stop_types=stop_types): if child['type'] in stop_types or child['type'] == LOOP_TYPE: continue if child['address'] in open: # loop has been found start = open.index(child['address']) new = frozenset(open[start:]) if new not in seen: seen.add(new) yield new elif child['address'] in seen: continue else: seen.add(child['address']) open.append(child['address']) for loop in find_loops( child, index, stop_types=stop_types, open=open, seen=seen ): yield loop open.pop(-1) def promote_loops(loops, index, shared): """Turn loops into "objects" that can be processed normally""" for loop in loops: loop = list(loop) members = [index[addr] for addr in loop] external_parents = list( set( [ addr for addr in sum([shared.get(addr, []) for addr in loop], []) if addr not in loop ] ) ) if external_parents: if len(external_parents) == 1: # potentially a loop that's been looped... parent = index.get(external_parents[0]) if parent['type'] == LOOP_TYPE: continue # we haven't already been looped... loop_addr = new_address(index) shared[loop_addr] = external_parents loop_record = index[loop_addr] = { 'address': loop_addr, 'refs': loop, 'parents': external_parents, 'type': LOOP_TYPE, 'size': 0, } for member in members: # member's references must *not* point to loop... member['refs'] = [ref for ref in member['refs'] if ref not in loop] # member's parents are *just* the loop member['parents'][:] = [loop_addr] # each referent to loop holds a single reference to the loop rather than many to children for parent in external_parents: parent = index[parent] for member in members: rewrite_references(parent['refs'], member['address'], None) parent['refs'].append(loop_addr) def children(record, index, key='refs', stop_types=STOP_TYPES): """Retrieve children records for given record""" result = [] for ref in record.get(key, []): try: record = index[ref] except KeyError as err: # print 'No record for %s address %s in %s'%(key, ref, record['address'] ) pass # happens when an unreachable references a reachable that has been compressed out... else: if record['type'] not in stop_types: result.append(record) return result def children_types(record, index, key='refs', stop_types=STOP_TYPES): """Produce dictionary mapping type-key to instances for all children""" types = {} for child in children(record, index, key, stop_types=stop_types): types.setdefault(child['type'], []).append(child) return types def recurse_module( overall_record, index, shared, stop_types=STOP_TYPES, already_seen=None, min_size=0 ): """Creates a has-a recursive-cost hierarchy Mutates objects in-place to produce a hierarchy of memory usage based on reference-holding cost assignment """ for record in recurse( overall_record, index, stop_types=stop_types, already_seen=already_seen, type_group=True, ): # anything with a totsize we've already processed... if record.get('totsize') is not None: continue rinfo = record rinfo['module'] = overall_record.get('name', NON_MODULE_REFS) if not record['refs']: rinfo['rsize'] = 0 rinfo['children'] = [] else: # TODO: provide a flag to coalesce based on e.g. type at each level or throughout... rinfo['children'] = rinfo_children = list( children(record, index, stop_types=stop_types) ) rinfo['rsize'] = sum( [ ( child.get('totsize', 0.0) / float(len(shared.get(child['address'], [])) or 1) ) for child in rinfo_children ], 0.0, ) rinfo['totsize'] = record['size'] + rinfo['rsize'] return None def as_id(x): if isinstance(x, dict): return x['address'] else: return x def rewrite_refs(targets, old, new, index, key='refs', single_ref=False): """Rewrite key in all targets (from index if necessary) to replace old with new""" for parent in targets: if not isinstance(parent, dict): try: parent = index[parent] except KeyError as err: continue rewrite_references(parent[key], old, new, single_ref=single_ref) def rewrite_references(sequence, old, new, single_ref=False): """Rewrite parents to point to new in old sequence -- sequence of id references old -- old id new -- new id returns rewritten sequence """ old, new = as_id(old), as_id(new) to_delete = [] for i, n in enumerate(sequence): if n == old: if new is None: to_delete.append(i) else: sequence[i] = new if single_ref: new = None elif n == new and single_ref: new = None if to_delete: to_delete.reverse() for i in to_delete: del sequence[i] return sequence def simple(child, shared, parent): """Return sub-set of children who are "simple" in the sense of group_children""" return not child.get('refs', ()) and ( not shared.get(child['address']) or shared.get(child['address']) == [parent['address']] ) def group_children( index, shared, min_kids=10, stop_types=STOP_TYPES, delete_children=True ): """Collect like-type children into sub-groups of objects for objects with long children-lists Only group if: * there are more than X children of type Y * children are "simple" * individual children have no children themselves * individual children have no other parents... """ to_compress = [] for to_simplify in list(iterindex(index)): if not isinstance(to_simplify, dict): continue for typ, kids in children_types( to_simplify, index, stop_types=stop_types ).items(): kids = [k for k in kids if k and simple(k, shared, to_simplify)] if len(kids) >= min_kids: # we can group and compress out... to_compress.append((to_simplify, typ, kids)) for to_simplify, typ, kids in to_compress: typ_address = new_address(index) kid_addresses = [k['address'] for k in kids] index[typ_address] = { 'address': typ_address, 'type': MANY_TYPE, 'name': typ, 'size': sum([k.get('size', 0) for k in kids], 0), 'parents': [to_simplify['address']], } shared[typ_address] = index[typ_address]['parents'] to_simplify['refs'][:] = [typ_address] if delete_children: for address in kid_addresses: try: del index[address] except KeyError as err: pass # already compressed out try: del shared[address] except KeyError as err: pass # already compressed out index[typ_address]['refs'] = [] else: index[typ_address]['refs'] = kid_addresses # Types which *can* have their dictionaries compressed out SIMPLIFY_DICTS = set(['module', 'type', 'classobj']) # Types which will *always* have their dictionaries compressed out, # even if there are multiple references to the dictionary, these values # should *only* ever be part of STOP_TYPES, as their size contributions # will be lost (STOP_TYPES make no contribution) ALWAYS_COMPRESS_DICTS = set(['module']) def simplify_dicts( index, shared, simplify_dicts=SIMPLIFY_DICTS, always_compress=ALWAYS_COMPRESS_DICTS ): """Eliminate "noise" dictionary records from the index index -- overall index of objects (including metadata such as type records) shared -- parent-count mapping for records in index module/type/class dictionaries """ # things which will have their dictionaries compressed out to_delete = set() for to_simplify in iterindex(index): if to_simplify['address'] in to_delete: continue if to_simplify['type'] in simplify_dicts and not 'compressed' in to_simplify: refs = to_simplify['refs'] for ref in refs: child = index.get(ref) if child is not None and child['type'] == 'dict': child_referrers = child['parents'][:] if ( len(child_referrers) == 1 or to_simplify['type'] in always_compress ): to_simplify['compressed'] = True to_simplify['refs'] = child['refs'] to_simplify['size'] += child['size'] # rewrite anything *else* that was pointing to child to point to us... while to_simplify['address'] in child_referrers: child_referrers.remove(to_simplify['address']) if child_referrers: rewrite_refs( child_referrers, child['address'], to_simplify['address'], index, single_ref=True, ) # now rewrite grandchildren to point to root obj instead of dict for grandchild in child['refs']: grandchild = index[grandchild] parent_set = grandchild['parents'] if parent_set: rewrite_references( parent_set, child, to_simplify, single_ref=True, ) assert parent_set to_delete.add(child['address']) for item in to_delete: del index[item] del shared[item] return index def find_reachable(modules, index, shared, stop_types=STOP_TYPES): """Find the set of all reachable objects from given root nodes (modules)""" reachable = set() already_seen = set() for module in modules: for child in recurse( module, index, stop_types=stop_types, already_seen=already_seen ): reachable.add(child['address']) return reachable def deparent_unreachable(reachable, shared): """Eliminate all parent-links from unreachable objects from reachable objects """ for id, shares in six.iteritems(shared): if id in reachable: # child is reachable filtered = [ x for x in shares if x in reachable # only those parents which are reachable ] if len(filtered) != len(shares): shares[:] = filtered class _syntheticaddress(object): current = -1 def __call__(self, target): while self.current in target: self.current -= 1 target[self.current] = True return self.current new_address = _syntheticaddress() def index_size(index): return sum([v.get('size', 0) for v in iterindex(index)], 0) def iterindex(index): for (k, v) in six.iteritems(index): if isinstance(v, dict) and isinstance(k, six.integer_types): yield v def bind_parents(index, shared): """Set parents on all items in index""" for v in iterindex(index): v['parents'] = shared.get(v['address'], []) def check_parents(index, reachable): for item in iterindex(index): if item['type'] == '': print('parents', item['parents']) def load(filename, include_interpreter=False): index = {} # address: structure shared = dict() # address: [parent addresses,...] modules = set() root_address = new_address(index) root = { 'type': 'dump', 'name': filename, 'children': [], 'totsize': 0, 'rsize': 0, 'size': 0, 'address': root_address, } index[root_address] = root index_ref = Ref(index) root_ref = Ref(root) root['root'] = root_ref root['index'] = index_ref raw_total = 0 for line in open(filename): struct = json_loads(line.strip()) index[struct['address']] = struct struct['root'] = root_ref struct['index'] = index_ref refs = struct['refs'] for ref in refs: parents = shared.get(ref) if parents is None: shared[ref] = [] shared[ref].append(struct['address']) raw_total += struct['size'] if struct['type'] == 'module': modules.add(struct['address']) modules = [index[addr] for addr in modules] reachable = find_reachable(modules, index, shared) deparent_unreachable(reachable, shared) bind_parents(index, shared) # unreachable = sum([ # v.get( 'size' ) # for v in iterindex( index ) # if v['address'] not in reachable # ], 0 ) # print '%s bytes are unreachable from modules'%( unreachable ) simplify_dicts(index, shared) group_children(index, shared, min_kids=10) records = [] for m in modules: loops = list(find_loops(m, index)) promote_loops(loops, index, shared) recurse_module(m, index, shared) modules.sort(key=lambda m: m.get('totsize', 0)) for module in modules: module['parents'].append(root_address) if include_interpreter: # Meliae produces quite a few of these un-referenced records, they aren't normally useful AFAICS # reachable from any module, but are present in the dump... disconnected = [x for x in iterindex(index) if x.get('totsize') is None] for pseudo_module in find_roots(disconnected, index, shared): pseudo_module['root'] = root_ref pseudo_module['index'] = index_ref pseudo_module.setdefault('parents', []).append(root_address) modules.append(pseudo_module) else: to_delete = [] for v in iterindex(index): if v.get('totsize') is None: to_delete.append(v['address']) for k in to_delete: del index[k] all_modules = sum([x.get('totsize', 0) for x in modules], 0) root['totsize'] = all_modules root['rsize'] = all_modules root['size'] = 0 root['children'] = modules for item in iterindex(index): item['root'] = root_ref item['index'] = index_ref return root, index def find_roots(disconnected, index, shared): """Find appropriate "root" objects from which to recurse the hierarchies Will generate a synthetic root for anything which doesn't have any parents... """ log.warn( '%s disconnected objects in %s total objects', len(disconnected), len(index) ) natural_roots = [x for x in disconnected if x.get('refs') and not x.get('parents')] log.warn('%s objects with no parents at all', len(natural_roots)) for natural_root in natural_roots: recurse_module(natural_root, index, shared) yield natural_root rest = [x for x in disconnected if x.get('totsize') is None] un_found = { 'type': 'module', 'name': '', 'children': rest, 'parents': [], 'size': 0, 'totsize': sum([x['size'] for x in rest], 0), 'address': new_address(index), } index[un_found['address']] = un_found yield un_found class Ref(object): def __init__(self, target): self.target = target def __call__(self): return self.target class Loader(object): """A data-set loader for pulling root and rows from a meliae dump""" def __init__(self, filename, include_interpreter=False): self.filename = filename self.include_interpreter = include_interpreter self.roots = {} ROOTS = ['memory'] def get_root(self, key): """Retrieve the given root by type-key""" if key not in self.roots: root, self.rows = load( self.filename, include_interpreter=self.include_interpreter ) self.roots[key] = root return self.roots[key] def get_rows(self, key): """Get the set of rows for the type-key""" if key not in self.roots: self.get_root(key) return self.rows def get_adapter(self, key): from runsnakerun import meliaeadapter return meliaeadapter.MeliaeAdapter() if __name__ == "__main__": import logging logging.basicConfig(level=logging.DEBUG) import sys load(sys.argv[1]) # import cProfile, sys # cProfile.runctx( "load(sys.argv[1])", globals(),locals(),'melialoader.profile' ) RunSnakeRun-2.0.5/runsnakerun/pstatsloader.py0000664000175000017500000003132513572471233022774 0ustar mcfletchmcfletch00000000000000"""Module to load cProfile/profile records as a tree of records""" from __future__ import absolute_import from __future__ import print_function import pstats, os, logging import six from six.moves import range log = logging.getLogger(__name__) from gettext import gettext as _ try: unicode except NameError: unicode = str TREE_CALLS, TREE_FILES = list(range(2)) def load_pstats(filenames): """Given list of filenames, load pstats, potentially using a different python version Internally will create a python2 subprocess to convert python2 pstats dumps for loading in python3, that will create a cPickle/pickle dump and load it locally. """ # first up, happy path... filenames = [filenames] if isinstance(filenames, (bytes, unicode)) else filenames try: log.debug("Using native loading for %s", filenames) stats = pstats.Stats(*filenames) return stats.stats except ValueError as err: import subprocess try: import cPickle as pickle except ImportError: import pickle log.info("Failure loading %s with native, trying python2", filenames) converter = ( '''import pstats, cPickle; print(cPickle.dumps(pstats.Stats(*%r).stats))''' % (filenames,) ) try: content = pickle.loads( subprocess.check_output(['python2', '-c', converter,]) ) except subprocess.CalledProcessError as err: raise RuntimeError('Unable to load %r as a pstats dump' % (filenames,)) else: return content class PStatsLoader(object): """Load profiler statistics from PStats (cProfile) files""" def __init__(self, *filenames): self.filename = filenames self.rows = {} self.roots = {} self.location_rows = {} self.tree = self.load(load_pstats(self.filename)) self.location_tree = l = self.load_location() ROOTS = ['functions', 'location'] def get_root(self, key): """Retrieve a given declared root by root-type-key""" if key not in self.roots: function = getattr(self, 'load_%s' % (key,))() self.roots[key] = function return self.roots[key] def get_rows(self, key): """Get the set of rows for the type-key""" if key not in self.roots: self.get_root(key) if key == 'location': return self.location_rows else: return self.rows def get_adapter(self, key): from runsnakerun import pstatsadapter if key == 'functions': return pstatsadapter.PStatsAdapter() elif key == 'location': return pstatsadapter.DirectoryViewAdapter() else: raise KeyError("""Unknown root type %s""" % (key,)) def load(self, stats): """Build a squaremap-compatible model from a pstats class""" rows = self.rows for func, raw in six.iteritems(stats): try: rows[func] = row = PStatRow(func, raw) except ValueError as err: log.info('Null row: %s', func) for row in six.itervalues(rows): row.weave(rows) return self.find_root(rows) def load_functions(self): """Load function records from the pstats file""" return self.load() def find_root(self, rows): """Attempt to find/create a reasonable root node from list/set of rows rows -- key: PStatRow mapping TODO: still need more robustness here, particularly in the case of threaded programs. Should be tracing back each row to root, breaking cycles by sorting on cumulative time, and then collecting the traced roots (or, if they are all on the same root, use that). """ maxes = sorted(list(rows.values()), key=lambda x: x.cumulative) if not maxes: raise RuntimeError("""Null results!""") root = maxes[-1] roots = [root] for key, value in rows.items(): if not value.parents: log.debug('Found node root: %s', value) if value not in roots: roots.append(value) if len(roots) > 1: root = PStatGroup( directory='*', filename='*', name=_(""), children=roots, ) root.finalize() self.rows[root.key] = root self.roots['functions'] = root return root def load_location(self): """Load the location root record (loading regular records if necessary)""" if not self.rows: self.load() return self._load_location() def _load_location(self): """Build a squaremap-compatible model for location-based hierarchy""" directories = {} files = {} root = PStatLocation('/', 'PYTHONPATH') self.location_rows = self.rows.copy() for child in self.rows.values(): current = directories.get(child.directory) directory, filename = child.directory, child.filename if current is None: if directory == '': current = root else: current = PStatLocation(directory, '') self.location_rows[current.key] = current directories[directory] = current if filename == '~': filename = '' file_current = files.get((directory, filename)) if file_current is None: file_current = PStatLocation(directory, filename) self.location_rows[file_current.key] = file_current files[(directory, filename)] = file_current current.children.append(file_current) file_current.children.append(child) # now link the directories... for key, value in directories.items(): if value is root: continue found = False while key: new_key, rest = os.path.split(key) if new_key == key: break key = new_key parent = directories.get(key) if parent: if value is not parent: parent.children.append(value) found = True break if not found: root.children.append(value) # lastly, finalize all of the directory records... root.finalize() return root class BaseStat(object): def recursive_distinct(self, already_done=None, attribute='children'): if already_done is None: already_done = {} for child in getattr(self, attribute, ()): if child not in already_done: already_done[child] = True yield child for descendent in child.recursive_distinct( already_done=already_done, attribute=attribute ): yield descendent def descendants(self): return list(self.recursive_distinct(attribute='children')) def ancestors(self): return list(self.recursive_distinct(attribute='parents')) class PStatRow(BaseStat): """Simulates a HotShot profiler record using PStats module""" def __init__(self, key, raw): self.children = [] self.parents = [] file, line, func = self.key = key try: dirname, basename = os.path.dirname(file), os.path.basename(file) except ValueError as err: dirname = '' basename = file nc, cc, tt, ct, callers = raw if nc == cc == tt == ct == 0: raise ValueError('Null stats row') ( self.calls, self.recursive, self.local, self.localPer, self.cumulative, self.cumulativePer, self.directory, self.filename, self.name, self.lineno, ) = ( nc, cc, tt, tt / (cc or 0.00000000000001), ct, ct / (nc or 0.00000000000001), dirname, basename, func, line, ) self.callers = callers def __repr__(self): return 'PStatRow( %r,%r,%r,%r, %s )' % ( self.directory, self.filename, self.lineno, self.name, len(self.children), ) def add_child(self, child): self.children.append(child) def weave(self, rows): for caller, data in six.iteritems(self.callers): # data is (cc,nc,tt,ct) parent = rows.get(caller) if parent: self.parents.append(parent) parent.children.append(self) def child_cumulative_time(self, child): total = self.cumulative if total: try: (cc, nc, tt, ct) = child.callers[self.key] except TypeError as err: ct = child.callers[self.key] return float(ct) / total return 0 class PStatGroup(BaseStat): """A node/record that holds a group of children but isn't a raw-record based group""" # if LOCAL_ONLY then only take the raw-record's local values, not cumulative values LOCAL_ONLY = False def __init__( self, directory='', filename='', name='', children=None, local_children=None, tree=TREE_CALLS, ): self.directory = directory self.filename = filename self.name = '' self.key = (directory, filename, name) self.children = children or [] self.parents = [] self.local_children = local_children or [] self.tree = tree def __repr__(self): return '%s( %r,%r,%s )' % ( self.__class__.__name__, self.directory, self.filename, self.name, ) def finalize(self, already_done=None): """Finalize our values (recursively) taken from our children""" if already_done is None: already_done = {} if self in already_done: return True already_done[self] = True self.filter_children() children = self.children for child in children: if hasattr(child, 'finalize'): child.finalize(already_done) child.parents.append(self) self.calculate_totals(self.children, self.local_children) def filter_children(self): """Filter our children into regular and local children sets (if appropriate)""" def calculate_totals(self, children, local_children=None): """Calculate our cumulative totals from children and/or local children""" for field, local_field in (('recursive', 'calls'), ('cumulative', 'local')): values = [] for child in children: if isinstance(child, PStatGroup) or not self.LOCAL_ONLY: values.append(getattr(child, field, 0)) elif isinstance(child, PStatRow) and self.LOCAL_ONLY: values.append(getattr(child, local_field, 0)) value = sum(values) setattr(self, field, value) if self.recursive: self.cumulativePer = self.cumulative / float(self.recursive) else: self.recursive = 0 if local_children: for field in ('local', 'calls'): value = sum([getattr(child, field, 0) for child in children]) setattr(self, field, value) if self.calls: self.localPer = self.local / self.calls else: self.local = 0 self.calls = 0 self.localPer = 0 class PStatLocation(PStatGroup): """A row that represents a hierarchic structure other than call-patterns This is used to create a file-based hierarchy for the views Children with the name are our "empty" space, our totals are otherwise just the sum of our children. """ LOCAL_ONLY = True def __init__(self, directory, filename, tree=TREE_FILES): super(PStatLocation, self).__init__( directory=directory, filename=filename, name='package', tree=tree ) def filter_children(self): """Filter our children into regular and local children sets""" real_children = [] for child in self.children: if child.name == '': self.local_children.append(child) else: real_children.append(child) self.children = real_children if __name__ == "__main__": import sys p = PStatsLoader(sys.argv[1]) assert p.tree print(p.tree) RunSnakeRun-2.0.5/runsnakerun/__init__.py0000664000175000017500000000010113572467336022023 0ustar mcfletchmcfletch00000000000000"""The RunSnakeRun GUI Profiler utility""" __version__ = '2.0.5' RunSnakeRun-2.0.5/runsnakerun/homedirectory.py0000664000175000017500000000536213572471233023146 0ustar mcfletchmcfletch00000000000000"""Attempt to determine the current user's "system" directories""" from __future__ import absolute_import, print_function try: ## raise ImportError from win32com.shell import shell, shellcon except ImportError: shell = None try: from six.moves import winreg as winreg except ImportError: winreg = None import os, sys ## The registry keys where the SHGetFolderPath values appear to be stored r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" r"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" def winreg_getShellFolder(name): """Get a shell folder by string name from the registry""" k = six.moves.winreg.OpenKey( six.moves.winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders", ) try: # should check that it's valid? How? return six.moves.winreg.QueryValueEx(k, name)[0] finally: six.moves.winreg.CloseKey(k) def shell_getShellFolder(type): """Get a shell folder by shell-constant from COM interface""" return shell.SHGetFolderPath( 0, # null hwnd type, # the (roaming) appdata path 0, # null access token (no impersonation) 0, # want current value, shellcon.SHGFP_TYPE_CURRENT isn't available, this seems to work ) def appdatadirectory(): """Attempt to retrieve the current user's app-data directory This is the location where application-specific files should be stored. On *nix systems, this will be the ${HOME}/.config directory. On Win32 systems, it will be the "Application Data" directory. Note that for Win32 systems it is normal to create a sub-directory for storing data in the Application Data directory. """ if shell: # on Win32 and have Win32all extensions, best-case return shell_getShellFolder(shellcon.CSIDL_APPDATA) if winreg: # on Win32, but no Win32 shell com available, this uses # a direct registry access, likely to fail on Win98/Me return winreg_getShellFolder('AppData') # okay, what if for some reason winreg is missing? would we want to allow ctypes? ## default case, look for name in environ... for name in ['APPDATA', 'HOME']: if name in os.environ: return os.path.join(os.environ[name], '.config') # well, someone's being naughty, see if we can get ~ to expand to a directory... possible = os.path.abspath(os.path.expanduser('~/.config')) if os.path.exists(possible): return possible raise OSError( """Unable to determine user's application-data directory, no ${HOME} or ${APPDATA} in environment""" ) if __name__ == "__main__": print('AppData', appdatadirectory()) RunSnakeRun-2.0.5/runsnakerun/pstatsadapter.py0000664000175000017500000000546413572471233023153 0ustar mcfletchmcfletch00000000000000from __future__ import absolute_import import wx, sys, os, logging log = logging.getLogger(__name__) from squaremap import squaremap from runsnakerun import pstatsloader class PStatsAdapter(squaremap.DefaultAdapter): percentageView = False total = 0 TREE = pstatsloader.TREE_CALLS def value(self, node, parent=None): if isinstance(parent, pstatsloader.PStatGroup): if parent.cumulative: return node.cumulative / parent.cumulative else: return 0 elif parent is None: return node.cumulative return parent.child_cumulative_time(node) def label(self, node): if isinstance(node, pstatsloader.PStatGroup): return '%s / %s' % (node.filename, node.directory) if self.percentageView and self.total: time = '%0.2f%%' % round(node.cumulative * 100.0 / self.total, 2) else: time = '%0.3fs' % round(node.cumulative, 3) return '%s@%s:%s [%s]' % (node.name, node.filename, node.lineno, time) def empty(self, node): if node.cumulative: return node.local / float(node.cumulative) return 0.0 def parents(self, node): """Determine all parents of node in our tree""" return [ parent for parent in getattr(node, 'parents', []) if getattr(parent, 'tree', self.TREE) == self.TREE ] color_mapping = None def background_color(self, node, depth): """Create a (unique-ish) background color for each node""" if self.color_mapping is None: self.color_mapping = {} color = self.color_mapping.get(node.key) if color is None: depth = len(self.color_mapping) red = (depth * 10) % 255 green = 200 - ((depth * 5) % 200) blue = (depth * 25) % 200 self.color_mapping[node.key] = color = wx.Colour(red, green, blue) return color def SetPercentage(self, percent, total): """Set whether to display percentage values (and total for doing so)""" self.percentageView = percent self.total = total def filename(self, node): """Extension to squaremap api to provide "what file is this" information""" if not node.directory: # TODO: any cases other than built-ins? return None if node.filename == '~': # TODO: look up C/Cython/whatever source??? return None return os.path.join(node.directory, node.filename) class DirectoryViewAdapter(PStatsAdapter): """Provides a directory-view-only adapter for PStats objects""" TREE = pstatsloader.TREE_FILES def children(self, node): if isinstance(node, pstatsloader.PStatGroup): return node.children return [] RunSnakeRun-2.0.5/runsnakerun/_meliaejson.py0000775000175000017500000000610213572471233022552 0ustar mcfletchmcfletch00000000000000#! /usr/bin/env python """Horrible hack to attempt to load meliae dumps a bit faster Makes meliae loading about 4.25x faster on python 2.6 compared to the json + C speedups. This is *not* however, a full json decoder, it is *just* a parser for the flat records meliae produces (i.e. no recursive structures, no floats, just ints, strings and lists-of-ints) """ from __future__ import absolute_import import re, unittest, json from six import unichr try: unicode except NameError: unicode = str whitespace = r'[ \t]' escape = r"""(?:\\[uU][0-9a-fA-F]{4})""" string = r"""(?:["](?P<%(key)s>([^"\\]|(\\")|%(escape)s|\\[^uU"])*?)["])""" key = string % {'key': 'key', 'escape': escape} string = string % {'key': 'string', 'escape': escape} integer = r"""(?P[+-]*\d+)""" listcontent = r"""([+-]*\d+[,]?%(whitespace)s*?)*""" % globals() intlist = r"""\[%(whitespace)s*(?P%(listcontent)s)%(whitespace)s*\]""" % globals() attr = ( r"""%(whitespace)s*%(key)s%(whitespace)s*:%(whitespace)s*(%(intlist)s|%(string)s|%(integer)s)(,)?""" % globals() ) escape = re.compile(escape, re.U) simple_escape = re.compile(r'\\([^uU])', re.U) assert escape.match(u"\\u0000") attr = re.compile(attr) string = re.compile(string) integer = re.compile(integer) intlist = re.compile(intlist) assert string.match('"this"').group('string') == "this" assert string.match('"this": "that"').group('string') == "this" assert string.match('"this\\u0000"').group('string') == "this\\u0000", string.match( '"this\\u0000"' ).group('string') assert integer.match('23').group('int') == '23' assert intlist.match('[1, 2,3,4]').group('list') == '1, 2,3,4' assert ( intlist.match('[139828625414688, 70572696, 52870672, 40989336]').group('list') == '139828625414688, 70572696, 52870672, 40989336' ) def loads(source): """Load json structure from meliae from source Supports only the required structures to support loading meliae memory dumps """ source = source.strip() assert source.startswith('{') assert source.endswith('}') source = source[1:-1] result = {} for match in attr.finditer(source): key = match.group('key') if match.group('list') is not None: value = [ int(x) for x in match.group('list').strip().replace(',', ' ').split() ] elif match.group('int') is not None: value = int(match.group('int')) elif match.group('string') is not None: def deescape(match): return unichr(int(match.group(0)[2:], 16)) value = match.group('string') if isinstance(value, bytes): value = value.decode('utf-8') value = escape.sub(deescape, value,) value = simple_escape.sub(lambda x: x.group(1), value,) else: raise RuntimeError( "Matched something we don't know how to process:", match.groupdict() ) result[key] = value return result if __name__ == "__main__": import sys, pprint for line in open(sys.argv[1]): official = json.loads(line) RunSnakeRun-2.0.5/runsnakerun/coldshotadapter.py0000664000175000017500000001263413572471233023451 0ustar mcfletchmcfletch00000000000000"""Adapter for RunSnakeRun to load coldshot profiles""" from __future__ import absolute_import import wx, sys, os, logging log = logging.getLogger(__name__) from squaremap import squaremap from coldshot import stack, loader class BaseColdshotAdapter(squaremap.DefaultAdapter): """Base class for the various adapters""" percentageView = False total = 0 def filename(self, node): return getattr(node, 'path', None) color_mapping = None def background_color(self, node, depth): """Create a (unique-ish) background color for each node""" if self.color_mapping is None: self.color_mapping = {} color = self.color_mapping.get(node.key) if color is None: depth = len(self.color_mapping) red = (depth * 10) % 255 green = 200 - ((depth * 5) % 200) blue = (depth * 25) % 200 self.color_mapping[node.key] = color = wx.Colour(red, green, blue) return color def SetPercentage(self, percent, total): """Set whether to display percentage values (and total for doing so)""" self.percentageView = percent self.total = total def parents(self, node): return getattr(node, 'parents', []) def label(self, node): if self.percentageView and self.total: time = '%0.2f%%' % round(node.cumulative * 100.0 / self.total, 2) else: time = '%0.3fs' % round(node.cumulative, 3) if hasattr(node, 'line'): return '%s@%s:%s [%s]' % (node.name, node.filename, node.line, time) else: return '%s [%s]' % (node.name, time) class ColdshotAdapter(BaseColdshotAdapter): """Adapts a coldshot.loader.Loader into a Squaremap-compatible structure""" def value(self, node, parent=None): if parent: return parent.child_cumulative_time(node) else: return node.cumulative def empty(self, node): """Calculate percentage of "empty" time""" return node.empty # # class ColdshotCallsAdapter( BaseColdshotAdapter ): # def value(self, node, parent=None): # return node.cumulative / parent.cumulative # # def empty(self, node): # """Calculate percentage of "empty" time""" # return node.empty class FunctionLineWrapper(object): def __init__(self, function_info, line_info): self.function_info = function_info self.line_info = line_info @property def children(self): return [] @property def parents(self): return [self.function_info] @property def cumulative(self): return self.line_info.time * self.function_info.loader.timer_unit @property def empty(self): return 0.0 @property def local(self): return self.line_info.time * self.function_info.loader.timer_unit @property def key(self): return self.function_info.key @property def name(self): return '%s:%s' % (self.line_info.line, self.function_info.filename,) @property def calls(self): return self.line_info.calls class ModuleAdapter(ColdshotAdapter): """Currently doesn't do anything different""" def label(self, node): if isinstance(node, stack.FunctionInfo): return super(ModuleAdapter, self).label(node) if self.percentageView and self.total: time = '%0.2f%%' % round(node.cumulative * 100.0 / self.total, 2) else: time = '%0.3fs' % round(node.cumulative, 3) return '%s [%s]' % (node.key or 'PYTHONPATH', time) def parents(self, node): if isinstance(node, stack.FunctionInfo): parent = node.loader.modules.get(node.module) if parent: return [parent] return [] elif isinstance(node, stack.FunctionLineInfo): return [node.function] else: return getattr(node, 'parents', []) def children(self, node): if isinstance(node, stack.FunctionInfo): return [ FunctionLineWrapper(node, line) for lineno, line in sorted(node.line_map.items()) ] return ColdshotAdapter.children(self, node) def label(self, node): if isinstance(node, FunctionLineWrapper): return node.name return ColdshotAdapter.label(self, node) class Loader(loader.Loader): """Coldshot loader subclass with knowledge of squaremap adapters""" def functions_rows(self): """Get cProfile-like function metadata rows returns an ID: function mapping """ return self.info.functions def location_rows(self): """Get our location records (finalized) returns an module-name: Grouping mapping """ self.info.finalize_modules() return self.info.modules ROOTS = ['functions', 'location'] # ,'thread','calls'] def get_root(self, key): """Retrieve the given root by type-key""" return self.info.roots[key] def get_rows(self, key): """Get the set of rows for the type-key""" return getattr(self, '%s_rows' % (key,))() def get_adapter(self, key): """Get an adapter for our given key""" if key == 'functions': return ColdshotAdapter() elif key == 'location': return ModuleAdapter() else: raise KeyError("""Unknown root type %s""" % (key,)) RunSnakeRun-2.0.5/runsnakerun/runsnake.py0000775000175000017500000007602713572471234022131 0ustar mcfletchmcfletch00000000000000#!/usr/bin/env python """The main script for the RunSnakeRun profile viewer""" from __future__ import absolute_import import wx, sys, os, logging, traceback import six log = logging.getLogger(__name__) import six.moves.configparser try: from wx.py import editor, editwindow except ImportError as err: log.info('No editor available: %s', err) editor = None from gettext import gettext as _ import pstats from squaremap import squaremap from runsnakerun import pstatsloader, pstatsadapter, meliaeloader, meliaeadapter from runsnakerun import listviews from runsnakerun import homedirectory if sys.platform == 'win32': windows = True else: windows = False if sys.platform == 'darwin': osx = True else: osx = False log = logging.getLogger(__name__) ID_OPEN = wx.NewId() ID_OPEN_MEMORY = wx.NewId() ID_EXIT = wx.NewId() ID_TREE_TYPE = wx.NewId() # ID_PACKAGE_VIEW = wx.NewId() ID_PERCENTAGE_VIEW = wx.NewId() ID_ROOT_VIEW = wx.NewId() ID_BACK_VIEW = wx.NewId() ID_UP_VIEW = wx.NewId() ID_DEEPER_VIEW = wx.NewId() ID_SHALLOWER_VIEW = wx.NewId() ID_MORE_SQUARE = wx.NewId() PROFILE_VIEW_COLUMNS = [ listviews.ColumnDefinition( name=_('Name'), attribute='name', defaultOrder=True, targetWidth=50, ), listviews.ColumnDefinition( name=_('Calls'), attribute='calls', defaultOrder=False, targetWidth=50, ), listviews.ColumnDefinition( name=_('RCalls'), attribute='recursive', defaultOrder=False, targetWidth=40, ), listviews.ColumnDefinition( name=_('Local'), attribute='local', format='%0.5f', defaultOrder=False, percentPossible=True, targetWidth=50, ), listviews.ColumnDefinition( name=_('/Call'), attribute='localPer', defaultOrder=False, format='%0.5f', targetWidth=50, ), listviews.ColumnDefinition( name=_('Cum'), attribute='cumulative', format='%0.5f', percentPossible=True, targetWidth=50, defaultOrder=False, sortDefault=True, ), listviews.ColumnDefinition( name=_('/Call'), attribute='cumulativePer', format='%0.5f', defaultOrder=False, targetWidth=50, ), listviews.ColumnDefinition( name=_('File'), attribute='filename', sortOn=('filename', 'lineno', 'directory',), defaultOrder=True, targetWidth=70, ), listviews.ColumnDefinition( name=_('Line'), attribute='lineno', sortOn=('filename', 'lineno', 'directory'), defaultOrder=True, targetWidth=30, ), listviews.ColumnDefinition( name=_('Directory'), attribute='directory', sortOn=('directory', 'filename', 'lineno'), defaultOrder=True, targetWidth=90, ), ] MAX_NAME_LEN = 64 def mem_name(x): if x.get('name'): return x['name'] value = x.get('value') if value: if isinstance(value, (str, six.text_type)) and len(value) > MAX_NAME_LEN: return value[: MAX_NAME_LEN - 3] + '...' else: return value return '' MEMORY_VIEW_COLUMNS = [ listviews.DictColumn( name=_('Type'), attribute='type', targetWidth=20, defaultOrder=True, ), listviews.DictColumn( name=_('Name'), attribute='name', targetWidth=20, getter=mem_name, defaultOrder=True, ), listviews.DictColumn( name=_('Cum'), attribute='totsize', targetWidth=5, defaultOrder=False, format='%0.1f', percentPossible=True, sortDefault=True, ), listviews.DictColumn( name=_('Local'), attribute='size', defaultOrder=False, format='%0.1f', percentPossible=True, targetWidth=5, ), listviews.DictColumn( name=_('Children'), attribute='rsize', format='%0.1f', percentPossible=True, defaultOrder=False, targetWidth=5, ), listviews.DictColumn( name=_('/Refs'), attribute='parents', defaultOrder=False, targetWidth=4, getter=lambda x: len(x.get('parents', ())), ), listviews.DictColumn( name=_('Refs/'), attribute='children', defaultOrder=False, targetWidth=4, getter=lambda x: len(x.get('children', ())), ), ] class MainFrame(wx.Frame): """The root frame for the display of a single data-set""" loader = None percentageView = False historyIndex = -1 activated_node = None selected_node = None viewType = 'functions' viewTypeTool = None TBFLAGS = ( wx.TB_HORIZONTAL # | wx.NO_BORDER | wx.TB_FLAT ) def __init__( self, parent=None, id=-1, title=_("Run Snake Run"), pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE | wx.CLIP_CHILDREN, name=_("RunSnakeRun"), config_parser=None, ): """Initialise the Frame""" wx.Frame.__init__(self, parent, id, title, pos, size, style, name) # TODO: toolbar for back, up, root, directory-view, percentage view self.adapter = pstatsadapter.PStatsAdapter() self.CreateControls(config_parser) self.history = [] # set of (activated_node, selected_node) pairs... icon = self.LoadRSRIcon() if icon: self.SetIcon(icon) def CreateControls(self, config_parser): """Create our sub-controls""" self.CreateMenuBar() self.SetupToolBar() self.CreateStatusBar() self.leftSplitter = wx.SplitterWindow(self) self.rightSplitter = wx.SplitterWindow(self.leftSplitter) self.listControl = listviews.DataView( self.leftSplitter, columns=PROFILE_VIEW_COLUMNS, name='mainlist', ) self.squareMap = squaremap.SquareMap( self.rightSplitter, padding=6, labels=True, adapter=self.adapter, square_style=True, ) self.tabs = wx.Notebook(self.rightSplitter, size=(300, 50),) self.CreateSourceWindow(self.tabs) self.calleeListControl = listviews.DataView( self.tabs, columns=PROFILE_VIEW_COLUMNS, name='callee', ) self.allCalleeListControl = listviews.DataView( self.tabs, columns=PROFILE_VIEW_COLUMNS, name='allcallee', ) self.allCallerListControl = listviews.DataView( self.tabs, columns=PROFILE_VIEW_COLUMNS, name='allcaller', ) self.callerListControl = listviews.DataView( self.tabs, columns=PROFILE_VIEW_COLUMNS, name='caller', ) self.ProfileListControls = [ self.listControl, self.calleeListControl, self.allCalleeListControl, self.callerListControl, self.allCallerListControl, ] self.tabs.AddPage(self.calleeListControl, _('Callees'), True) self.tabs.AddPage(self.allCalleeListControl, _('All Callees'), False) self.tabs.AddPage(self.callerListControl, _('Callers'), False) self.tabs.AddPage(self.allCallerListControl, _('All Callers'), False) if editor: self.tabs.AddPage(self.sourceCodeControl, _('Source Code'), False) self.rightSplitter.SetSashSize(10) # calculate size as proportional value for initial display... self.LoadState(config_parser) width, height = self.GetSize() rightsplit = 2 * (height // 3) leftsplit = width // 3 self.rightSplitter.SplitHorizontally(self.squareMap, self.tabs, rightsplit) self.leftSplitter.SplitVertically( self.listControl, self.rightSplitter, leftsplit ) self.squareMap.Bind( squaremap.EVT_SQUARE_HIGHLIGHTED, self.OnSquareHighlightedMap ) self.squareMap.Bind(squaremap.EVT_SQUARE_SELECTED, self.OnSquareSelectedList) self.squareMap.Bind( squaremap.EVT_SQUARE_SELECTED, self.OnSquareSelectedMap, ) self.squareMap.Bind(squaremap.EVT_SQUARE_ACTIVATED, self.OnNodeActivated) for control in self.ProfileListControls: control.Bind(squaremap.EVT_SQUARE_ACTIVATED, self.OnNodeActivated) control.Bind(squaremap.EVT_SQUARE_HIGHLIGHTED, self.OnSquareHighlightedList) self.moreSquareViewItem.Check(self.squareMap.square_style) def CreateMenuBar(self): """Create our menu-bar for triggering operations""" menubar = wx.MenuBar() menu = wx.Menu() menu.Append(ID_OPEN, _('&Open Profile'), _('Open a cProfile file')) menu.Append( ID_OPEN_MEMORY, _('Open &Memory'), _('Open a Meliae memory-dump file') ) menu.AppendSeparator() menu.Append(ID_EXIT, _('&Close'), _('Close this RunSnakeRun window')) menubar.Append(menu, _('&File')) menu = wx.Menu() # self.packageMenuItem = menu.AppendCheckItem( # ID_PACKAGE_VIEW, _('&File View'), # _('View time spent by package/module') # ) self.percentageMenuItem = menu.AppendCheckItem( ID_PERCENTAGE_VIEW, _('&Percentage View'), _('View time spent as percent of overall time'), ) self.rootViewItem = menu.Append( ID_ROOT_VIEW, _('&Root View (Home)'), _('View the root of the tree') ) self.backViewItem = menu.Append( ID_BACK_VIEW, _('&Back'), _('Go back in your viewing history') ) self.upViewItem = menu.Append( ID_UP_VIEW, _('&Up'), _('Go "up" to the parent of this node with the largest cumulative total'), ) self.moreSquareViewItem = menu.AppendCheckItem( ID_MORE_SQUARE, _('&Hierarchic Squares'), _('Toggle hierarchic squares in the square-map view'), ) # This stuff isn't really all that useful for profiling, # it's more about how to generate graphics to describe profiling... self.deeperViewItem = menu.Append( ID_DEEPER_VIEW, _('&Deeper'), _('View deeper squaremap views') ) self.shallowerViewItem = menu.Append( ID_SHALLOWER_VIEW, _('&Shallower'), _('View shallower squaremap views') ) # wx.ToolTip.Enable(True) menubar.Append(menu, _('&View')) self.viewTypeMenu = wx.Menu() menubar.Append(self.viewTypeMenu, _('View &Type')) self.SetMenuBar(menubar) self.Bind(wx.EVT_MENU, lambda evt: self.Close(True), id=ID_EXIT) self.Bind(wx.EVT_MENU, self.OnOpenFile, id=ID_OPEN) self.Bind(wx.EVT_MENU, self.OnOpenMemory, id=ID_OPEN_MEMORY) self.Bind(wx.EVT_MENU, self.OnPercentageView, id=ID_PERCENTAGE_VIEW) self.Bind( wx.EVT_MENU, self.OnUpView, id=ID_UP_VIEW, ) self.Bind( wx.EVT_MENU, self.OnDeeperView, id=ID_DEEPER_VIEW, ) self.Bind( wx.EVT_MENU, self.OnShallowerView, id=ID_SHALLOWER_VIEW, ) self.Bind( wx.EVT_MENU, self.OnRootView, id=ID_ROOT_VIEW, ) self.Bind( wx.EVT_MENU, self.OnBackView, id=ID_BACK_VIEW, ) self.Bind( wx.EVT_MENU, self.OnMoreSquareToggle, id=ID_MORE_SQUARE, ) def LoadRSRIcon(self): try: from runsnakerun.resources import rsricon_png return getIcon(rsricon_png.data) except Exception as err: return None sourceCodeControl = None def CreateSourceWindow(self, tabs): """Create our source-view window for tabs""" if editor and self.sourceCodeControl is None: self.sourceCodeControl = wx.py.editwindow.EditWindow(self.tabs, -1) self.sourceCodeControl.SetText(u"") self.sourceFileShown = None self.sourceCodeControl.setDisplayLineNumbers(True) def SetupToolBar(self): """Create the toolbar for common actions""" tb = self.CreateToolBar(self.TBFLAGS) tsize = (24, 24) tb.ToolBitmapSize = tsize open_bmp = wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR, tsize) tb.AddTool( ID_OPEN, _("Open"), open_bmp, open_bmp, shortHelp="Open", longHelp="Open a (c)Profile trace file", kind=wx.ITEM_NORMAL, ) if not osx: tb.AddSeparator() # self.Bind(wx.EVT_TOOL, self.OnOpenFile, id=ID_OPEN) root_bmp = wx.ArtProvider.GetBitmap(wx.ART_GO_HOME, wx.ART_TOOLBAR, tsize) self.rootViewTool = tb.AddTool( ID_ROOT_VIEW, _("Root View"), root_bmp, shortHelp=_("Display the root of the current view tree (home view)"), kind=wx.ITEM_NORMAL, ) self.rootViewTool = tb.AddTool( ID_BACK_VIEW, _("Back"), wx.ArtProvider.GetBitmap(wx.ART_GO_BACK, wx.ART_TOOLBAR, tsize), shortHelp=_("Back to the previously activated node in the call tree"), kind=wx.ITEM_NORMAL, ) self.upViewTool = tb.AddTool( ID_UP_VIEW, _("Up"), wx.ArtProvider.GetBitmap(wx.ART_GO_UP, wx.ART_TOOLBAR, tsize), shortHelp=_("Go one level up the call tree (highest-percentage parent)"), kind=wx.ITEM_NORMAL, ) if not osx: tb.AddSeparator() # TODO: figure out why the control is sizing the label incorrectly on Linux self.percentageViewTool = wx.CheckBox(tb, -1, _("Percent ")) self.percentageViewTool.SetToolTip( wx.ToolTip(_("Toggle display of percentages in list views")) ) tb.AddControl(self.percentageViewTool) self.percentageViewTool.Bind( wx.EVT_CHECKBOX, self.OnPercentageView, id=self.percentageViewTool.GetId() ) self.viewTypeTool = wx.Choice(tb, -1, choices=getattr(self.loader, 'ROOTS', [])) self.viewTypeTool.SetToolTip( wx.ToolTip(_("Switch between different hierarchic views of the data")) ) self.viewTypeTool.Bind( wx.EVT_CHOICE, self.OnViewTypeTool, id=self.viewTypeTool.GetId() ) tb.AddControl(self.viewTypeTool) tb.Realize() def OnViewTypeTool(self, event): """When the user changes the selection, make that our selection""" new = self.viewTypeTool.GetStringSelection() if new != self.viewType: self.viewType = new self.OnRootView(event) def ConfigureViewTypeChoices(self, event=None): """Configure the set of View types in the toolbar (and menus)""" self.viewTypeTool.SetItems(getattr(self.loader, 'ROOTS', [])) if self.loader and self.viewType in self.loader.ROOTS: self.viewTypeTool.SetSelection(self.loader.ROOTS.index(self.viewType)) # configure the menu with the available choices... def chooser(typ): def Callback(event): if typ != self.viewType: self.viewType = typ self.OnRootView(event) return Callback # Clear all previous items for item in self.viewTypeMenu.GetMenuItems(): self.viewTypeMenu.Delete(item) if self.loader and self.loader.ROOTS: for root in self.loader.ROOTS: item = wx.MenuItem( self.viewTypeMenu, -1, root.title(), _("View hierarchy by %(name)s") % {'name': root.title(),}, kind=wx.ITEM_RADIO, ) self.viewTypeMenu.Append(item) item.Check(root == self.viewType) self.Bind(wx.EVT_MENU, chooser(root), id=item.GetId()) def OnOpenFile(self, event): """Request to open a new profile file""" dialog = wx.FileDialog(self, style=wx.FD_OPEN | wx.FD_MULTIPLE) if dialog.ShowModal() == wx.ID_OK: paths = dialog.GetPaths() if self.loader: # we've already got a displayed data-set, open new window... frame = MainFrame() frame.Show(True) frame.load(*paths) else: self.load(*paths) def OnOpenMemory(self, event): """Request to open a new profile file""" dialog = wx.FileDialog(self, style=wx.FD_OPEN) if dialog.ShowModal() == wx.ID_OK: path = dialog.GetPath() if self.loader: # we've already got a displayed data-set, open new window... frame = MainFrame() frame.Show(True) frame.load_memory(path) else: self.load_memory(path) def OnShallowerView(self, event): if not self.squareMap.max_depth: new_depth = self.squareMap.max_depth_seen or 0 - 1 else: new_depth = self.squareMap.max_depth - 1 self.squareMap.max_depth = max((1, new_depth)) self.squareMap.Refresh() def OnDeeperView(self, event): if not self.squareMap.max_depth: new_depth = 1 else: new_depth = self.squareMap.max_depth + 1 self.squareMap.max_depth = max((self.squareMap.max_depth_seen or 0, new_depth)) self.squareMap.Refresh() def OnPackageView(self, event): self.SetPackageView(not self.directoryView) def SetPackageView(self, directoryView): """Set whether to use directory/package based view""" self.directoryView = not self.directoryView self.packageMenuItem.Check(self.directoryView) self.packageViewTool.SetValue(self.directoryView) if self.loader: self.SetModel(self.loader) self.RecordHistory() def OnPercentageView(self, event): """Handle percentage-view event from menu/toolbar""" self.SetPercentageView(not self.percentageView) def SetPercentageView(self, percentageView): """Set whether to display percentage or absolute values""" self.percentageView = percentageView self.percentageMenuItem.Check(self.percentageView) self.percentageViewTool.SetValue(self.percentageView) total = self.adapter.value(self.loader.get_root(self.viewType)) for control in self.ProfileListControls: control.SetPercentage(self.percentageView, total) self.adapter.SetPercentage(self.percentageView, total) def OnUpView(self, event): """Request to move up the hierarchy to highest-weight parent""" node = self.activated_node parents = [] selected_parent = None if node: if hasattr(self.adapter, 'best_parent'): selected_parent = self.adapter.best_parent(node) else: parents = self.adapter.parents(node) if parents: if not selected_parent: parents.sort(key=lambda a: self.adapter.value(node, a)) selected_parent = parents[-1] class event: node = selected_parent self.OnNodeActivated(event) else: self.SetStatusText( _('No parents for the currently selected node: %(node_name)s') % dict(node_name=self.adapter.label(node)) ) else: self.SetStatusText(_('No currently selected node')) def OnBackView(self, event): """Request to move backward in the history""" self.historyIndex -= 1 try: self.RestoreHistory(self.history[self.historyIndex]) except IndexError as err: self.SetStatusText(_('No further history available')) def OnRootView(self, event): """Reset view to the root of the tree""" self.adapter, tree, rows = self.RootNode() self.squareMap.SetModel(tree, self.adapter) self.RecordHistory() self.ConfigureViewTypeChoices() def OnNodeActivated(self, event): """Double-click or enter on a node in some control...""" self.activated_node = self.selected_node = event.node self.squareMap.SetModel(event.node, self.adapter) self.squareMap.SetSelected(event.node) if editor: if self.SourceShowFile(event.node): if hasattr(event.node, 'lineno'): self.sourceCodeControl.GotoLine(event.node.lineno) self.RecordHistory() def SourceShowFile(self, node): """Show the given file in the source-code view (attempt it anyway)""" filename = self.adapter.filename(node) if filename and self.sourceFileShown != filename: try: data = open(filename).read() except Exception as err: # TODO: load from zips/eggs? What about .pyc issues? return None else: # self.sourceCodeControl.setText(data) self.sourceCodeControl.ClearAll() self.sourceCodeControl.AppendText(data) return filename def OnSquareHighlightedMap(self, event): self.SetStatusText(self.adapter.label(event.node)) self.listControl.SetIndicated(event.node) text = self.squareMap.adapter.label(event.node) self.squareMap.SetToolTip(text) self.SetStatusText(text) def OnSquareHighlightedList(self, event): self.SetStatusText(self.adapter.label(event.node)) self.squareMap.SetHighlight(event.node, propagate=False) def OnSquareSelectedList(self, event): self.SetStatusText(self.adapter.label(event.node)) self.squareMap.SetSelected(event.node) self.OnSquareSelected(event) self.RecordHistory() def OnSquareSelectedMap(self, event): self.listControl.SetSelected(event.node) self.OnSquareSelected(event) self.RecordHistory() def OnSquareSelected(self, event): """Update all views to show selection children/parents""" self.selected_node = event.node self.calleeListControl.integrateRecords(self.adapter.children(event.node)) self.callerListControl.integrateRecords(self.adapter.parents(event.node)) # self.allCalleeListControl.integrateRecords(event.node.descendants()) # self.allCallerListControl.integrateRecords(event.node.ancestors()) def OnMoreSquareToggle(self, event): """Toggle the more-square view (better looking, but more likely to filter records)""" self.squareMap.square_style = not self.squareMap.square_style self.squareMap.Refresh() self.moreSquareViewItem.Check(self.squareMap.square_style) restoringHistory = False def RecordHistory(self): """Add the given node to the history-set""" if not self.restoringHistory: record = self.activated_node if self.historyIndex < -1: try: del self.history[self.historyIndex + 1 :] except AttributeError as err: pass if (not self.history) or record != self.history[-1]: self.history.append(record) del self.history[:-200] self.historyIndex = -1 def RestoreHistory(self, record): self.restoringHistory = True try: activated = record class activated_event: node = activated if activated: self.OnNodeActivated(activated_event) self.squareMap.SetSelected(activated_event.node) self.listControl.SetSelected(activated_event.node) finally: self.restoringHistory = False def load(self, *filenames): """Load our dataset (iteratively)""" if len(filenames) == 1: if os.path.basename(filenames[0]) == 'index.coldshot': return self.load_coldshot(os.path.dirname(filenames[0])) elif os.path.isdir(filenames[0]): return self.load_coldshot(filenames[0]) try: self.loader = pstatsloader.PStatsLoader(*filenames) self.ConfigureViewTypeChoices() self.SetModel(self.loader) self.viewType = self.loader.ROOTS[0] self.SetTitle( _("Run Snake Run: %(filenames)s") % {'filenames': ', '.join(filenames)[:120]} ) except (IOError, OSError, ValueError, MemoryError) as err: log.exception('Failure loading: %s', filenames) self.SetStatusText( _('Failure during load of %(filenames)s: %(err)s') % dict(filenames=" ".join([repr(x) for x in filenames]), err=err) ) def load_memory(self, filename): self.viewType = 'memory' for view in self.ProfileListControls: view.SetColumns(MEMORY_VIEW_COLUMNS) self.loader = meliaeloader.Loader(filename) self.ConfigureViewTypeChoices() self.viewType = self.loader.ROOTS[0] self.SetModel(self.loader) def load_coldshot(self, dirname): from runsnakerun import coldshotadapter self.loader = coldshotadapter.Loader(dirname) self.loader.load() self.ConfigureViewTypeChoices() self.viewType = self.loader.ROOTS[0] self.SetModel(self.loader) def SetModel(self, loader): """Set our overall model (a loader object) and populate sub-controls""" self.loader = loader self.adapter, tree, rows = self.RootNode() self.listControl.integrateRecords(list(rows.values())) self.activated_node = tree self.squareMap.SetModel(tree, self.adapter) self.RecordHistory() def RootNode(self): """Return our current root node and appropriate adapter for it""" tree = self.loader.get_root(self.viewType) adapter = self.loader.get_adapter(self.viewType) rows = self.loader.get_rows(self.viewType) adapter.SetPercentage(self.percentageView, adapter.value(tree)) return adapter, tree, rows def SaveState(self, config_parser): """Retrieve window state to be restored on the next run...""" if not config_parser.has_section('window'): config_parser.add_section('window') if self.IsMaximized(): config_parser.set('window', 'maximized', str(True)) else: config_parser.set('window', 'maximized', str(False)) size = self.GetSize() position = self.GetPosition() config_parser.set('window', 'width', str(size[0])) config_parser.set('window', 'height', str(size[1])) config_parser.set('window', 'x', str(position[0])) config_parser.set('window', 'y', str(position[1])) for control in self.ProfileListControls: control.SaveState(config_parser) return config_parser def LoadState(self, config_parser): """Set our window state from the given config_parser instance""" if not config_parser: return if not config_parser.has_section('window') or ( config_parser.has_option('window', 'maximized') and config_parser.getboolean('window', 'maximized') ): self.Maximize(True) try: width, height, x, y = [ config_parser.getint('window', key) for key in ['width', 'height', 'x', 'y'] ] self.SetPosition((x, y)) self.SetSize((width, height)) except six.moves.configparser.NoSectionError as err: # the file isn't written yet, so don't even warn... pass except Exception as err: # this is just convenience, if it breaks in *any* way, ignore it... log.error( "Unable to load window preferences, ignoring: %s", traceback.format_exc(), ) try: font_size = config_parser.getint('window', 'font_size') except Exception: pass # use the default, by default else: font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) font.SetPointSize(font_size) for ctrl in self.ProfileListControls: ctrl.SetFont(font) for control in self.ProfileListControls: control.LoadState(config_parser) self.config = config_parser self.Bind(wx.EVT_CLOSE, self.OnCloseWindow) def OnCloseWindow(self, event=None): try: self.SaveState(self.config) config = config_file() temp = config + '~' self.config.write(open(temp, 'w')) os.rename(temp, config) except Exception as err: log.error( "Unable to write window preferences, ignoring: %s", traceback.format_exc(), ) self.Destroy() class RunSnakeRunApp(wx.App): """Basic application for holding the viewing Frame""" handler = wx.PNGHandler() def OnInit(self): """Initialise the application""" wx.Image.AddHandler(self.handler) frame = MainFrame(config_parser=load_config()) frame.Show(True) self.SetTopWindow(frame) if sys.argv[1:]: if sys.argv[1] == '-m': if sys.argv[2:]: wx.CallAfter(frame.load_memory, sys.argv[2]) else: log.warn('No memory file specified') else: wx.CallAfter(frame.load, *sys.argv[1:]) return True class MeliaeViewApp(wx.App): handler = wx.PNGHandler() def OnInit(self): """Initialise the application""" wx.Image.AddHandler(self.handler) frame = MainFrame(config_parser=load_config()) frame.Show(True) self.SetTopWindow(frame) if sys.argv[1:]: wx.CallAfter(frame.load_memory, sys.argv[1]) else: log.warn('No memory file specified') return True def getIcon(data): """Return the data from the resource as a wxIcon""" import cStringIO stream = cStringIO.StringIO(data) image = wx.ImageFromStream(stream) icon = wx.EmptyIcon() icon.CopyFromBitmap(wx.BitmapFromImage(image)) return icon def config_directory(): base = homedirectory.appdatadirectory() directory = os.path.join(base, 'RunSnakeRun') if not os.path.exists(directory): os.makedirs(directory) return directory def config_file(): directory = config_directory() return os.path.join(directory, 'runsnake.conf') def load_config(): config = six.moves.configparser.SafeConfigParser() filename = config_file() if os.path.exists(filename): config.read(filename) return config usage = """runsnake.py profilefile runsnake.py -m meliae.memoryfile profilefile -- a file generated by a HotShot profile run from Python """ def main(): """Mainloop for the application""" logging.basicConfig(level=logging.INFO) app = RunSnakeRunApp(0) app.MainLoop() def meliaemain(): logging.basicConfig(level=logging.INFO) app = MeliaeViewApp(0) app.MainLoop() if __name__ == "__main__": logging.basicConfig(level=logging.INFO) main() RunSnakeRun-2.0.5/runsnakerun/listviews.py0000664000175000017500000002575713572471233022334 0ustar mcfletchmcfletch00000000000000from __future__ import absolute_import import wx, sys, os, logging, operator, traceback from gettext import gettext as _ from squaremap import squaremap from wx.lib.agw.ultimatelistctrl import ( UltimateListCtrl, ULC_REPORT, ULC_VIRTUAL, ULC_VRULES, ULC_SINGLE_SEL, ) import six from six.moves import range from six.moves import zip if sys.platform == 'win32': windows = True else: windows = False log = logging.getLogger(__name__) class ColumnDefinition(object): """Definition of a given column for display using attribute access""" index = None name = None attribute = None sortOn = None format = None defaultOrder = False percentPossible = False targetWidth = None getter = None sortDefault = False def __init__(self, **named): for key, value in named.items(): setattr(self, key, value) if self.getter: self.get = self.getter else: attribute = self.attribute def getter(function): return getattr(function, attribute, None) self.get = self.getter = getter class DictColumn(ColumnDefinition): def __init__(self, **named): for key, value in named.items(): setattr(self, key, value) if self.getter: self.get = self.getter else: attribute = self.attribute def getter(function): return function.get(attribute, None) self.get = self.getter = getter class DataView(wx.ListCtrl): """A sortable profile list control""" indicated = -1 total = 0 percentageView = False activated_node = None selected_node = None indicated_node = None def __init__( self, parent, id=-1, pos=wx.DefaultPosition, size=wx.DefaultSize, style=wx.LC_REPORT | wx.LC_VIRTUAL | wx.LC_VRULES | wx.LC_SINGLE_SEL, validator=wx.DefaultValidator, columns=None, sortOrder=None, name=_("ProfileView"), ): wx.ListCtrl.__init__(self, parent, id, pos, size, style, validator, name) if columns is not None: self.columns = columns if not sortOrder: sortOrder = [(x.defaultOrder, x) for x in self.columns if x.sortDefault] self.sortOrder = sortOrder or [] self.sorted = [] self.CreateControls() def SetPercentage(self, percent, total): """Set whether to display percentage values (and total for doing so)""" self.percentageView = percent self.total = total self.Refresh() def CreateControls(self): """Create our sub-controls""" self.Bind(wx.EVT_LIST_COL_CLICK, self.OnReorder, id=self.GetId()) self.Bind( wx.EVT_LIST_ITEM_SELECTED, self.OnNodeSelected, id=self.GetId(), ) self.Bind(wx.EVT_MOTION, self.OnMouseMove) self.Bind( wx.EVT_LIST_ITEM_ACTIVATED, self.OnNodeActivated, id=self.GetId(), ) self.CreateColumns() def CreateColumns(self): """Create/recreate our column definitions from current self.columns""" self.SetItemCount(0) # clear any current columns... for i in range(self.GetColumnCount())[::-1]: self.DeleteColumn(i) # now create for i, column in enumerate(self.columns): column.index = i self.InsertColumn(i, column.name) if not windows or column.targetWidth is None: self.SetColumnWidth(i, wx.LIST_AUTOSIZE) else: self.SetColumnWidth(i, column.targetWidth) def SetColumns(self, columns, sortOrder=None): """Set columns to a set of values other than the originals and recreates column controls""" self.columns = columns self.sortOrder = [(x.defaultOrder, x) for x in self.columns if x.sortDefault] self.CreateColumns() def OnNodeActivated(self, event): """We have double-clicked for hit enter on a node refocus squaremap to this node""" try: node = self.sorted[event.GetIndex()] except IndexError as err: log.warn( _('Invalid index in node activated: %(index)s'), index=event.GetIndex() ) else: wx.PostEvent( self, squaremap.SquareActivationEvent(node=node, point=None, map=None) ) def OnNodeSelected(self, event): """We have selected a node with the list control, tell the world""" try: node = self.sorted[event.GetIndex()] except IndexError as err: log.warn( _('Invalid index in node selected: %(index)s'), index=event.GetIndex() ) else: if node is not self.selected_node: wx.PostEvent( self, squaremap.SquareSelectionEvent(node=node, point=None, map=None), ) def OnMouseMove(self, event): point = event.GetPosition() item, where = self.HitTest(point) if item > -1: try: node = self.sorted[item] except IndexError as err: log.warn( _('Invalid index in mouse move: %(index)s'), index=event.GetIndex() ) else: wx.PostEvent( self, squaremap.SquareHighlightEvent(node=node, point=point, map=None), ) def SetIndicated(self, node): """Set this node to indicated status""" self.indicated_node = node self.indicated = self.NodeToIndex(node) self.Refresh(False) return self.indicated def SetSelected(self, node): """Set our selected node""" self.selected_node = node index = self.NodeToIndex(node) if index != -1: self.Focus(index) self.Select(index, True) return index def NodeToIndex(self, node): for i, n in enumerate(self.sorted): if n is node: return i return -1 def columnByAttribute(self, name): for column in self.columns: if column.attribute == name: return column return None def OnReorder(self, event): """Given a request to reorder, tell us to reorder""" column = self.columns[event.GetColumn()] return self.ReorderByColumn(column) def ReorderByColumn(self, column): """Reorder the set of records by column""" # TODO: store current selection and re-select after sorting... single_column = self.SetNewOrder(column) self.reorder(single_column=True) self.Refresh() def SetNewOrder(self, column): """Set new sorting order based on column, return whether a simple single-column (True) or multiple (False)""" if column.sortOn: # multiple sorts for the click... columns = [self.columnByAttribute(attr) for attr in column.sortOn] diff = [(a, b) for a, b in zip(self.sortOrder, columns) if b is not a[1]] if not diff: self.sortOrder[0] = (not self.sortOrder[0][0], column) else: self.sortOrder = [(c.defaultOrder, c) for c in columns] + [ (a, b) for (a, b) in self.sortOrder if b not in columns ] return False else: if column is self.sortOrder[0][1]: # reverse current major order self.sortOrder[0] = (not self.sortOrder[0][0], column) else: self.sortOrder = [(column.defaultOrder, column)] + [ (a, b) for (a, b) in self.sortOrder if b is not column ] return True def reorder(self, single_column=False): """Force a reorder of the displayed items""" if single_column: columns = self.sortOrder[:1] else: columns = self.sortOrder for ascending, column in columns[::-1]: # Python 2.2+ guarantees stable sort, so sort by each column in reverse # order will order by the assigned columns self.sorted.sort(key=column.get, reverse=(not ascending)) def integrateRecords(self, functions): """Integrate records from the loader""" self.SetItemCount(len(functions)) self.sorted = functions[:] self.reorder() self.Refresh() indicated_attribute = wx.ListItemAttr() indicated_attribute.SetBackgroundColour('#00ff00') def OnGetItemAttr(self, item): """Retrieve ListItemAttr for the given item (index)""" if self.indicated > -1 and item == self.indicated: return self.indicated_attribute return None def OnGetItemText(self, item, col): """Retrieve text for the item and column respectively""" # TODO: need to format for rjust and the like... try: column = self.columns[col] value = column.get(self.sorted[item]) except IndexError as err: return None else: if value is None: return u'' if column.percentPossible and self.percentageView and self.total: value = value / float(self.total) * 100.00 if column.format: try: return column.format % (value,) except Exception as err: log.warn( 'Column %s could not format %r value: %r', column.name, type(value), value, ) value = column.get(self.sorted[item]) if isinstance(value, (six.text_type, str)): return value return six.text_type(value) else: if isinstance(value, (six.text_type, str)): return value return six.text_type(value) def OnGetItemToolTip(self, item, col): return self.OnGetItemText(item, col) # XXX: do something nicer def SaveState(self, config_parser): section = 'listctrl-%s' % (self.GetName()) if not config_parser.has_section(section): config_parser.add_section(section) for i, dfn in enumerate(self.columns): col = self.GetColumn(i) config_parser.set(section, '%s_width' % dfn.attribute, str(col.GetWidth())) def LoadState(self, config_parser): section = 'listctrl-%s' % (self.GetName()) if config_parser.has_section(section): for i, dfn in enumerate(self.columns): width = '%s_width' % dfn.attribute if config_parser.has_option(section, width): try: value = int(config_parser.get(section, width)) except ValueError: log.warn("Unable to restore %s %s", section, width) else: self.SetColumnWidth(i, value) RunSnakeRun-2.0.5/runsnakerun/macshim.py0000664000175000017500000000041713572471233021706 0ustar mcfletchmcfletch00000000000000from __future__ import absolute_import def macshim(): """Shim to run 32-bit on 64-bit mac as a sub-process""" import subprocess, sys subprocess.call( [sys.argv[0] + '32'] + sys.argv[1:], env={"VERSIONER_PYTHON_PREFER_32_BIT": "yes"}, ) RunSnakeRun-2.0.5/runsnakerun/meliaeadapter.py0000775000175000017500000001376113572471233023073 0ustar mcfletchmcfletch00000000000000#! /usr/bin/env python """Module to load meliae memory-profile dumps Trees: * has-a * module root * each held reference contributes a weighted cost to the parent * hierarchy of held objects, so globals, classes, functions, and their children * held modules do not contribute to cost * module * instance-tree Planned: * is-a * class/type root * instances contribute to their type * summary-by-type """ from __future__ import absolute_import from __future__ import print_function import wx, sys, os, logging, imp import wx.lib.newevent import six log = logging.getLogger(__name__) import sys from squaremap import squaremap from runsnakerun import meliaeloader RANKS = [ (1024 * 1024 * 1024, '%0.1fGB'), (1024 * 1024, '%0.1fMB'), (1024, '%0.1fKB'), (0, '%iB'), ] def mb(value): for (unit, format) in RANKS: if abs(value) >= unit * 2: return format % (value / float(unit or 1)) raise ValueError("Number where abs(x) is not >= 0?: %s" % (value,)) class MeliaeAdapter(squaremap.DefaultAdapter): """Default adapter class for adapting node-trees to SquareMap API""" def SetPercentage(self, *args): """Ignore percentage requests for now""" def children(self, node): """Retrieve the set of nodes which are children of this node""" return node.get('children', []) def value(self, node, parent=None): """Return value used to compare size of this node""" # this is the *weighted* size/contribution of the node try: return node['contribution'] except KeyError as err: contribution = int( node.get('totsize', 0) / float(len(node.get('parents', ())) or 1) ) node['contribution'] = contribution return contribution def label(self, node): """Return textual description of this node""" result = [] if node.get('type'): result.append(node['type']) if node.get('name'): result.append(node['name']) elif node.get('value') is not None: result.append(six.text_type(node['value'])[:32]) if 'module' in node and not node['module'] in result: result.append(' in %s' % (node['module'])) if node.get('size'): result.append('%s' % (mb(node['size']))) if node.get('totsize'): result.append('(%s)' % (mb(node['totsize']))) parent_count = len(node.get('parents', ())) if parent_count > 1: result.append('/%s refs' % (parent_count)) return " ".join(result) def overall(self, node): return node.get('totsize', 0) def empty(self, node): if node.get('totsize'): return node['size'] / float(node['totsize']) else: return 0 def parents(self, node): """Retrieve/calculate the set of parents for the given node""" if 'index' in node: index = node['index']() parents = list(meliaeloader.children(node, index, 'parents')) return parents return [] def best_parent(self, node, tree_type=None): """Choose the best parent for a given node""" parents = self.parents(node) selected_parent = None if node['type'] == 'type': module = ".".join(node['name'].split('.')[:-1]) if module: for mod in parents: if mod['type'] == 'module' and mod['name'] == module: selected_parent = mod if parents and selected_parent is None: parents.sort(key=lambda x: self.value(node, x)) return parents[-1] return selected_parent color_mapping = None def background_color(self, node, depth): """Create a (unique-ish) background color for each node""" if self.color_mapping is None: self.color_mapping = {} if node['type'] == 'type': key = node['name'] else: key = node['type'] color = self.color_mapping.get(key) if color is None: depth = len(self.color_mapping) red = (depth * 10) % 255 green = 200 - ((depth * 5) % 200) blue = (depth * 25) % 200 self.color_mapping[key] = color = wx.Colour(red, green, blue) return color def filename(self, node): if 'module' in node and not 'filename' in node: try: fp, pathname, description = imp.find_module(node['module']) except (ImportError) as err: node['filename'] = None else: if fp: fp.close() node['filename'] = pathname elif not 'filename' in node: return None return node['filename'] class TestApp(wx.App): """Basic application for holding the viewing Frame""" handler = wx.PNGHandler() def OnInit(self): """Initialise the application""" wx.Image.AddHandler(self.handler) self.frame = frame = wx.Frame(None,) frame.CreateStatusBar() model = model = self.get_model(sys.argv[1]) self.sq = squaremap.SquareMap( frame, model=model, adapter=MeliaeAdapter(), padding=2, margin=1, square_style=True, ) squaremap.EVT_SQUARE_HIGHLIGHTED(self.sq, self.OnSquareSelected) frame.Show(True) self.SetTopWindow(frame) return True def get_model(self, path): return meliaeloader.load(path)[0] # tree-only def OnSquareSelected(self, event): text = self.sq.adapter.label(event.node) self.frame.SetToolTip(text) usage = 'meliaeloader.py somefile' def main(): """Mainloop for the application""" if not sys.argv[1:]: print(usage) else: app = TestApp(0) app.MainLoop() if __name__ == "__main__": main()