From 7957e98a2df78726a603ca335ded178233116950 Mon Sep 17 00:00:00 2001 From: Matthieu Dubuget Date: Tue, 1 Nov 2016 17:47:59 +0100 Subject: [PATCH] Nettoyage --- .../chambrew20151126_3.resized.jpg | Bin .../chambrew20151126_4.resized.jpg | Bin files/{ => chambre1}/dsc03930.resized.jpg | Bin files/{ => chambre1}/dsc03931.resized.jpg | Bin .../chambree20151101_2.resized.jpg | Bin .../chambree20151126_2.resized.jpg | Bin .../chambree20151126_3.resized.jpg | Bin .../chambree20151126_5.resized.jpg | Bin .../chambres20160118_1.resized.jpg | Bin .../chambres20160118_4.resized.jpg | Bin .../chambres20160118_5.resized.jpg | Bin .../cuisine20160118_2.resized.jpg | Bin .../cuisine20160118_3.resized.jpg | Bin .../sjour20151102_1.resized.jpg | Bin .../sjour20151102_2.resized.jpg | Bin .../thumb_img_3740_1024.jpeg | Bin files/{ => sdb}/dsc03926.resized.jpg | Bin files/{ => sdb}/sdbe20151126_2.resized.jpg | Bin files/{ => sdb}/sdbe20151126_3.resized.jpg | Bin files/{ => sdb}/sdbe20151126_4.resized.jpg | Bin files/{ => sdb}/sdbe20151126_5.resized.jpg | Bin files/{ => sdb}/sdbw20151125_1.resized.jpg | Bin files/{ => sdb}/sdbw20151126_2.resized.jpg | Bin files/{ => src}/GPS-AgenceChauvin.png | Bin .../{ => src}/GPS-LesTerrassesDesChoseaux.png | Bin files/{ => src}/chauvin-redimensionné.jpg | Bin files/{ => src}/chauvin.eps | 0 files/{ => src}/chauvin.png | Bin files/{ => src}/chauvin.svg | 0 files/{ => src}/gps.svg | 0 files/{ => src}/location.svg | 0 galleria-1.4.2.zip | Bin 103198 -> 0 bytes galleria/LICENSE | 21 - galleria/galleria-1.4.7.js | 6919 ----------------- galleria/plugins/flickr/flickr-demo.html | 63 - galleria/plugins/flickr/flickr-loader.gif | Bin 2129 -> 0 bytes galleria/plugins/flickr/galleria.flickr.js | 384 - .../plugins/flickr/galleria.flickr.min.js | 1 - galleria/plugins/flickr/loader.gif | Bin 1849 -> 0 bytes galleria/plugins/history/galleria.history.js | 147 - .../plugins/history/galleria.history.min.js | 1 - galleria/plugins/history/history-demo.html | 100 - galleria/plugins/picasa/galleria.picasa.js | 321 - .../plugins/picasa/galleria.picasa.min.js | 1 - galleria/plugins/picasa/loader.gif | Bin 1849 -> 0 bytes galleria/plugins/picasa/picasa-demo.html | 55 - galleria/themes/classic/classic-demo-cdn.html | 124 - galleria/themes/classic/classic-demo.html | 130 - galleria/themes/classic/galleria.classic.js | 101 - index.html | 635 +- site_69553_1_29.css => mon_site.css | 6 +- published-site-jquery-lightbox.js | 343 - published-site.js | 6 - robots.txt | 4 +- sitemap.xml | 9 +- sitemap_pages.xml | 12 +- translations.js | 1 - twig-widget-views-v1.js | 3 - 58 files changed, 252 insertions(+), 9135 deletions(-) rename files/{ => chambre1}/chambrew20151126_3.resized.jpg (100%) rename files/{ => chambre1}/chambrew20151126_4.resized.jpg (100%) rename files/{ => chambre1}/dsc03930.resized.jpg (100%) rename files/{ => chambre1}/dsc03931.resized.jpg (100%) rename files/{ => chambre2}/chambree20151101_2.resized.jpg (100%) rename files/{ => chambre2}/chambree20151126_2.resized.jpg (100%) rename files/{ => chambre2}/chambree20151126_3.resized.jpg (100%) rename files/{ => chambre2}/chambree20151126_5.resized.jpg (100%) rename files/{ => chambre3}/chambres20160118_1.resized.jpg (100%) rename files/{ => chambre3}/chambres20160118_4.resized.jpg (100%) rename files/{ => chambre3}/chambres20160118_5.resized.jpg (100%) rename files/{ => salon_cuisine}/cuisine20160118_2.resized.jpg (100%) rename files/{ => salon_cuisine}/cuisine20160118_3.resized.jpg (100%) rename files/{ => salon_cuisine}/sjour20151102_1.resized.jpg (100%) rename files/{ => salon_cuisine}/sjour20151102_2.resized.jpg (100%) rename files/{ => salon_cuisine}/thumb_img_3740_1024.jpeg (100%) rename files/{ => sdb}/dsc03926.resized.jpg (100%) rename files/{ => sdb}/sdbe20151126_2.resized.jpg (100%) rename files/{ => sdb}/sdbe20151126_3.resized.jpg (100%) rename files/{ => sdb}/sdbe20151126_4.resized.jpg (100%) rename files/{ => sdb}/sdbe20151126_5.resized.jpg (100%) rename files/{ => sdb}/sdbw20151125_1.resized.jpg (100%) rename files/{ => sdb}/sdbw20151126_2.resized.jpg (100%) rename files/{ => src}/GPS-AgenceChauvin.png (100%) rename files/{ => src}/GPS-LesTerrassesDesChoseaux.png (100%) rename files/{ => src}/chauvin-redimensionné.jpg (100%) rename files/{ => src}/chauvin.eps (100%) rename files/{ => src}/chauvin.png (100%) rename files/{ => src}/chauvin.svg (100%) rename files/{ => src}/gps.svg (100%) rename files/{ => src}/location.svg (100%) delete mode 100644 galleria-1.4.2.zip delete mode 100644 galleria/LICENSE delete mode 100644 galleria/galleria-1.4.7.js delete mode 100644 galleria/plugins/flickr/flickr-demo.html delete mode 100755 galleria/plugins/flickr/flickr-loader.gif delete mode 100644 galleria/plugins/flickr/galleria.flickr.js delete mode 100644 galleria/plugins/flickr/galleria.flickr.min.js delete mode 100644 galleria/plugins/flickr/loader.gif delete mode 100644 galleria/plugins/history/galleria.history.js delete mode 100644 galleria/plugins/history/galleria.history.min.js delete mode 100644 galleria/plugins/history/history-demo.html delete mode 100644 galleria/plugins/picasa/galleria.picasa.js delete mode 100644 galleria/plugins/picasa/galleria.picasa.min.js delete mode 100644 galleria/plugins/picasa/loader.gif delete mode 100644 galleria/plugins/picasa/picasa-demo.html delete mode 100644 galleria/themes/classic/classic-demo-cdn.html delete mode 100644 galleria/themes/classic/classic-demo.html delete mode 100644 galleria/themes/classic/galleria.classic.js rename site_69553_1_29.css => mon_site.css (99%) delete mode 100644 published-site-jquery-lightbox.js delete mode 100644 published-site.js delete mode 100644 translations.js delete mode 100644 twig-widget-views-v1.js diff --git a/files/chambrew20151126_3.resized.jpg b/files/chambre1/chambrew20151126_3.resized.jpg similarity index 100% rename from files/chambrew20151126_3.resized.jpg rename to files/chambre1/chambrew20151126_3.resized.jpg diff --git a/files/chambrew20151126_4.resized.jpg b/files/chambre1/chambrew20151126_4.resized.jpg similarity index 100% rename from files/chambrew20151126_4.resized.jpg rename to files/chambre1/chambrew20151126_4.resized.jpg diff --git a/files/dsc03930.resized.jpg b/files/chambre1/dsc03930.resized.jpg similarity index 100% rename from files/dsc03930.resized.jpg rename to files/chambre1/dsc03930.resized.jpg diff --git a/files/dsc03931.resized.jpg b/files/chambre1/dsc03931.resized.jpg similarity index 100% rename from files/dsc03931.resized.jpg rename to files/chambre1/dsc03931.resized.jpg diff --git a/files/chambree20151101_2.resized.jpg b/files/chambre2/chambree20151101_2.resized.jpg similarity index 100% rename from files/chambree20151101_2.resized.jpg rename to files/chambre2/chambree20151101_2.resized.jpg diff --git a/files/chambree20151126_2.resized.jpg b/files/chambre2/chambree20151126_2.resized.jpg similarity index 100% rename from files/chambree20151126_2.resized.jpg rename to files/chambre2/chambree20151126_2.resized.jpg diff --git a/files/chambree20151126_3.resized.jpg b/files/chambre2/chambree20151126_3.resized.jpg similarity index 100% rename from files/chambree20151126_3.resized.jpg rename to files/chambre2/chambree20151126_3.resized.jpg diff --git a/files/chambree20151126_5.resized.jpg b/files/chambre2/chambree20151126_5.resized.jpg similarity index 100% rename from files/chambree20151126_5.resized.jpg rename to files/chambre2/chambree20151126_5.resized.jpg diff --git a/files/chambres20160118_1.resized.jpg b/files/chambre3/chambres20160118_1.resized.jpg similarity index 100% rename from files/chambres20160118_1.resized.jpg rename to files/chambre3/chambres20160118_1.resized.jpg diff --git a/files/chambres20160118_4.resized.jpg b/files/chambre3/chambres20160118_4.resized.jpg similarity index 100% rename from files/chambres20160118_4.resized.jpg rename to files/chambre3/chambres20160118_4.resized.jpg diff --git a/files/chambres20160118_5.resized.jpg b/files/chambre3/chambres20160118_5.resized.jpg similarity index 100% rename from files/chambres20160118_5.resized.jpg rename to files/chambre3/chambres20160118_5.resized.jpg diff --git a/files/cuisine20160118_2.resized.jpg b/files/salon_cuisine/cuisine20160118_2.resized.jpg similarity index 100% rename from files/cuisine20160118_2.resized.jpg rename to files/salon_cuisine/cuisine20160118_2.resized.jpg diff --git a/files/cuisine20160118_3.resized.jpg b/files/salon_cuisine/cuisine20160118_3.resized.jpg similarity index 100% rename from files/cuisine20160118_3.resized.jpg rename to files/salon_cuisine/cuisine20160118_3.resized.jpg diff --git a/files/sjour20151102_1.resized.jpg b/files/salon_cuisine/sjour20151102_1.resized.jpg similarity index 100% rename from files/sjour20151102_1.resized.jpg rename to files/salon_cuisine/sjour20151102_1.resized.jpg diff --git a/files/sjour20151102_2.resized.jpg b/files/salon_cuisine/sjour20151102_2.resized.jpg similarity index 100% rename from files/sjour20151102_2.resized.jpg rename to files/salon_cuisine/sjour20151102_2.resized.jpg diff --git a/files/thumb_img_3740_1024.jpeg b/files/salon_cuisine/thumb_img_3740_1024.jpeg similarity index 100% rename from files/thumb_img_3740_1024.jpeg rename to files/salon_cuisine/thumb_img_3740_1024.jpeg diff --git a/files/dsc03926.resized.jpg b/files/sdb/dsc03926.resized.jpg similarity index 100% rename from files/dsc03926.resized.jpg rename to files/sdb/dsc03926.resized.jpg diff --git a/files/sdbe20151126_2.resized.jpg b/files/sdb/sdbe20151126_2.resized.jpg similarity index 100% rename from files/sdbe20151126_2.resized.jpg rename to files/sdb/sdbe20151126_2.resized.jpg diff --git a/files/sdbe20151126_3.resized.jpg b/files/sdb/sdbe20151126_3.resized.jpg similarity index 100% rename from files/sdbe20151126_3.resized.jpg rename to files/sdb/sdbe20151126_3.resized.jpg diff --git a/files/sdbe20151126_4.resized.jpg b/files/sdb/sdbe20151126_4.resized.jpg similarity index 100% rename from files/sdbe20151126_4.resized.jpg rename to files/sdb/sdbe20151126_4.resized.jpg diff --git a/files/sdbe20151126_5.resized.jpg b/files/sdb/sdbe20151126_5.resized.jpg similarity index 100% rename from files/sdbe20151126_5.resized.jpg rename to files/sdb/sdbe20151126_5.resized.jpg diff --git a/files/sdbw20151125_1.resized.jpg b/files/sdb/sdbw20151125_1.resized.jpg similarity index 100% rename from files/sdbw20151125_1.resized.jpg rename to files/sdb/sdbw20151125_1.resized.jpg diff --git a/files/sdbw20151126_2.resized.jpg b/files/sdb/sdbw20151126_2.resized.jpg similarity index 100% rename from files/sdbw20151126_2.resized.jpg rename to files/sdb/sdbw20151126_2.resized.jpg diff --git a/files/GPS-AgenceChauvin.png b/files/src/GPS-AgenceChauvin.png similarity index 100% rename from files/GPS-AgenceChauvin.png rename to files/src/GPS-AgenceChauvin.png diff --git a/files/GPS-LesTerrassesDesChoseaux.png b/files/src/GPS-LesTerrassesDesChoseaux.png similarity index 100% rename from files/GPS-LesTerrassesDesChoseaux.png rename to files/src/GPS-LesTerrassesDesChoseaux.png diff --git a/files/chauvin-redimensionné.jpg b/files/src/chauvin-redimensionné.jpg similarity index 100% rename from files/chauvin-redimensionné.jpg rename to files/src/chauvin-redimensionné.jpg diff --git a/files/chauvin.eps b/files/src/chauvin.eps similarity index 100% rename from files/chauvin.eps rename to files/src/chauvin.eps diff --git a/files/chauvin.png b/files/src/chauvin.png similarity index 100% rename from files/chauvin.png rename to files/src/chauvin.png diff --git a/files/chauvin.svg b/files/src/chauvin.svg similarity index 100% rename from files/chauvin.svg rename to files/src/chauvin.svg diff --git a/files/gps.svg b/files/src/gps.svg similarity index 100% rename from files/gps.svg rename to files/src/gps.svg diff --git a/files/location.svg b/files/src/location.svg similarity index 100% rename from files/location.svg rename to files/src/location.svg diff --git a/galleria-1.4.2.zip b/galleria-1.4.2.zip deleted file mode 100644 index 8fdd00bd1d82157f005f2e7488b0276524326a29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 103198 zcmeFZV~{T0wk2G4)h^riF59+k+qP}ncI~ol+qP|g@9A^8Z+FKz=iZL^e%_48Tu=U) zG4qKv*I09mktrt$3<3r4x1$LaS@?ha_{Rkj02{zm-^$9^!Ce2hvJxZ!aLV0-;@?hZ zH)sGrkW*j)fd6rk`(Gg%orC%Q_YesGdk8x#XH#<<$G?YqNc5Kdx1s*;Y|#H%C_8gQ zeaHViIpn``f&lnia@6H5G{j&40PNrZ0EGW0qLr<_k+B1`(v@%7@3+nVzY8`YHDeH?)C+i zmzQsE>m2@+&;CdtR#c@}T(Fo|S9^3UDwvd0?dY#HFF$*o!4W_5@R9E<3UUycPb5MP zPZpImaZK9g7e9AB6CiY|PzuZYoU#U*6@+&hTw+Qf>E55Wde6+nm*H_b?q*u{>i?&F`1iTiio=wD)2}hyt+}*vCw;7QQ14`)B#()WA z82C4k!;rW`bigtV1L-^hVtffuOKS@L?7z{pTt2E>WjSk$7Q}n)Kx~L;lAVx&e6Q!@ zH+XkwZRY4fo)o!lBy&C|ArZTy!>vSH3*c;LkZ}Xf9;u=&2Q>h=t>}D?cb%O1&BOV| z#h{MSWz{Rrk*d}J^YOJHFPA>70)2I-Ug&a|v0>}@iDH4frL#=drUckjS_VuxwDI5MgS`cS(ID6TV|^<_D(BXjida~ zHP}#dH}Fz$02Sx;hi4d3$I@E+wh0@L)69Fg6jG}azp!D=S76%@SCGIwi_zweQ0r~x z8;y5f3MQ91qIlC(Do(VCXfOehI}9=j`04WKhtdZ$Uxw{$FNB2^w#=-_CMw#dl`^7q zdCWUstm=<#s$AVD@Q7C~_Ev+W5ejIMQ~jtWy2OsZYQ0>4RXb_OYFg&k@z?T}=oa}M zCEfF?56s_SN;Ws(#D0 zAxhZ1`0^TX_fOhv#iJ@GWxgz^TC?Xg#2e2X15v4JCl)L%XZ*|^QdmQ5oSZGaT>jDo z*_{A{<>}ox2lZ1FX+I`Oq_mLbGMwQ-ifIoWaO(UHJU*C*9Lty>@s9ZBt0GH22oR*@ zaXHH(=PQWrG#W6_i(KJKan#rcOgp={!^StVbZIjt0rA&lu+j)2Cq^%>*A|QuYj5&m z&CR2->VW6_gR=Y?CX8syekP1(&Zvd&ZhXk=yDVGL8Cc(1RM}+%o?0bWRNHM+OMP&k zv3I-us101%JGp;C+zo8RDQ8sNd^0a_Mto~*hZ6S=$Z&XXW$Iqir8YEF1 zKtQ)2yd_+&oo8$)@9(EZBvunfv~ehjxgQ_+tr%Fb=vf>gzSO$!s%X_su5igp>CJ8X zm^hVkmEU;?Ojhl@pDJ=wa;{N@_JpKETk3NG4|i<1&7P}9zm80crsaLb*^!q23JQ`F zrRVI$(*eCl$j7aRt|Z2Vz>g6B!Td=qNv%<%RUa2iT*$@5=w=jsC$}E%ZM)SuSM&Yy z#tWj?Lsrfwf6d`!;Ote^_(d9pLgGOhi0RxSI4#6UQ|g2{x1Fqg!qgXVHWDiv=E*l= zoXSl?3b4=ag+9Gb2ZRJg;px*{l@r^XUzEogbuRcOz-=>8NmH&&WAW-+D_{ClcAc9m z^a6JtGoKQ8mwVO4a{1EOCvO$g_Tc3UafQQ#LNvYadJ!;U|1?^B@y&m*H6p?TgWc0^ zV4~57hM;IT5Gx5NecxXmjoz2QHYF!d$p6Zq|)DvNF&O!5(s@H7_^8%q*F4 z|CxBNxoAdNHTe_Uk`R8)XnM4RG+1M|sfkBy=4}jTs6qX*8EvS71zN=ee zl(POgVrnI(^6S(IgOUA%GOgEe011I55!|1SN@Qji8hu&CK#(9^zNFH4YrHtI;D;r( zN$ThozgR}(j8&09q1cUzt!bh+ZVJ+ok@9Exn7gFmoJU-A;nLy`tYU1=i+ez#$SI^n0<|?sfLeqErRbJg5(|8OQNtCLoH~LLUZ}R0m(r7X*Qu8reM8{%bp0}r`U%Xvy z?_;+)Q6k?pVk{aZ;l2zex*~;R2i{3F?t?tvmGE!Ya+G*~3Z$v@nI>9!qHNrzx4S%k zTwT=bA)sl9P_Bc!3Hx37P8J;KUc>qxzDV~a)>fG0IexQnOkEYd4jxb=!l;{yY)Gbr z8Itr~`n%0T>6`+aS!4&L!1g_x)NJO{t6R?2QHMLnlSOoaWxLfQ6o# z0YX0T2NUXmQ-WCo3*uHC@rXG>#(<4R&826N@R8grKvdTYoOTfa2hW=I8$b3y0!;=g zGLM#5y&TohngPSCcsWLws6oF&*^?lVv;+WEItir=bU#^>_LCoJBHDwi_5P$ZP%7My zk49*mFsv~W!Jx0uLCCCzYvtXDid;EZ%z^3Yz3JoD%_Q%>9rwDJ`5&Un0UES6^RrTp zb8$KUN6cW1bj%HEm2SkRj(YslPNZ@8M{2R92fg_rS)2$IptiXgQLiSS8rn zTAn-E#TJHne=>P2ewr-7QkoxN?!*2@LcojbH_g!poW0-W^io=U{cQe&Ju%n8aRYs@ zi);Bq$OKR=NBDv~5y5PvjU_WsB61!yGQ4_(MzzyBiO`)S9WvSw-y)nAP>`_jyhuSinqZm*f?}}WQUKAH-w?i+>NneG+W6oLknQF&{yh12p+ur$dR7Ku zLv=_4u0r?Y`AP8BcdH2k9mo#07kCg9$qJCf2^KC&K+~2WF4)f(>=vxk>9wR6*?orO zc>q9$gn(V^z6Rd?W7+E3W0eGNkhU1F97|s~oHJ6=Wx!DIJi3TolsQIZy-6U5vNu=K&z8*An`*4{l%GYka8tN z1uR1R%=ONaf9S>>eJ1ch1y3P0+f&6&=NA6#EsPgSGZMoWMaxWcFTVN_8(51&W!29 z?&lk$8dvbr!Y*i(H?UzVubu;sD6OKAAXiBx$M9#dDod#vZSvKh7R<~+o;2h`xXL&Z z4rfrgHJu6 zb6t~PJa&3CEJtzhr7&V2DM0#ko=Zy#xvBR~&F2;>zE*zgftFzvnfqpqBPQD88Q_|< z9jp`7>2Q)xptr?BX!x-F>TYmRTTDSCZPHF@!KX$mPhf}SPyQmCU)vPSIHa%&74;Yq zuS*xIMd+03H`1yi^E6a^V1f)-`1#1;AP;~*G|t3Ud*u;q$9Z$%HUWlQb`b0n8|%S; zO|oTXJ*PP)hc8ukN6b>qw!ntfM_sljJiyr=)Y1}MGNIjIluFv-yn_h;ev}x7IfGmz z@L`lJCnp3bTlI>hpzSDH;yYZGJ1pQqrizC^qY-{Evsk-$?9^Etnz1hIc7YB$DLlDm zIVVO?q~;YN_@$c73@*EhYK;b3K@!0nlla{IcoyOyua~)Dijl zNo^OhnAf0%fg3k}sMLVKdG}mEg+HpG4EkIs$#O## z$!XSvplrc+*DU^kJqg*}*MV2VoaNljQ3Q&;ZP}M1)|EkR-e<9?0-F17u9)8Bb#VbE z=UFkRMziXXt)P&yJDk{twu@&)wbMmgkHLgy??LprjA~Z>RHKU#?X^ibH6AJal9*31 z%-|T#q|{~{Ep@ifTe$n%7F3dR=?)@iJ3WlP1;RK0rc9-+RHy6&MGdPA~u zttN6hybm%hp+=naNUtyWvem#o;jrH=ORoU&bWW6m6vS_KevrC|^0+rD>{8Gdy=c zY9W-(N6iAONzLm)qCR1E1eGFm1NHLFH5b#oBA6u6Orar1)_{2QF0BDIc%ue-&R-E~;p$d~E9-%2-Xq=Zvv<2=lG3xU3=UKGoa8c}_ z<(uAE$AaNksyeoei%ERA{f*>l%XCdxebB2M5JynR7Qu7mShk_PnfRzzgNS*K9zp3b zNcZ^eID!Eniuw$XdB)yD7gSeAPz3>9wq|$Cf$N-7i6qEEkqjlT>`liEqP}jYjsRWI z-uU-8C>b;}?R()4NG;7FV``P$r$DFm`kn`=hmwNHU`99>P|*8vBvmZu07ia?NeLF% zdr-UV_hF2F>r}98zY5DzNY}+RZ6VLmkujoEK)K(Vd`>YxOY;)Fg$q=4wR?%7y}- zdpUCtJaBq3jQFWpV1j$R0SkfpVUfOEWTr(e@YmkVrs=AcckNOlnHnhfd{a3I)YaVlnoR-r5l^7 z@a=rQY(C#i=*svm?yolt7^D#Hau)X6c6h-v@EnUY1!-%t)ymSOQu(xK=b1ke-fC*q(d8qft3|8r5J_kc4F9WQ?xm&}~*-9v6M0;NqUX;zdNp+s(Yt^>_ zOq^E#L?zW83%Nk$EJKZ?9};-MJdGp1Y>8S5hPA*I&bl(90@&SH&vR@($OXoj#BRBj zVG8nmuZ%!o{^~yXTERU2GNdzjTTcxx>3y6m3I;J>m|>V^!;6@ldmevYZ+~3rjAk9Ns?Ax ziC%I1YK)J_Y-O7s%XdtmRMB;kunY>S&948Gg83c4(9hhdh@9A$eFX`-;6A+9d)M*L zUR|o(J*5bk0zI&tU|!*DfU#^JLJDE++5$W3!NDhJfuoazOncpqwHKbBJ}JTIzg+b)){= zc(snK3XfhkOrA?0iZLDHjMR$kFc@TqBWqsPZ<@_NRBxlZ`;w54=RPw^TuQGeA2T1_M80Q ztnz;+9B7P;t!-(|oUE<>9q}KmtZBPIhwQUc%O**}Q9@!fF^E4!SqJL|NMF=-dpc~h zKV27iWks{}&Dl+SW~?L>Z-9sAyVK@XIwf=Cv&r+>{sU87{(4F5h_|bTyn=u-cL{Qt zn2enG=W!zf6UIF}x#XC`Vv_J1{t6q*ge}{9C`)mO&TEg_SIKTBGawu$c%iz5#j@oF z_L~31PLvArTWWxPozs~>XOcwS_L$9=I>`z|96WK%NJHP4eSYrI_(tG1IYJHvOT9Gp z399ihs#lMR!%4=00tUq-QIb}fqqV&~gSLtSNA?^AlPncJIf++(zyT(Jg{i%lMcOC7 zZnmzO;&;hRR2qXfFUC?OEolqbCb~PHY78qJ_wwbhC*&MzpOPwaY09Dsy4>b`c!8K= zHQRPzbpL~O-r?C|#`Mk2ZLciMb_V+VHlz0|zd)dGALm34_@5f{g&|4cD zCvu|)Vh*(Hjv|)88pmr3=hHZZA%5RcQWR0M4KXh?ewk}}n|dU%ipP0(EE-gn86_x5ed2XACoG^_@QRN>a-0&s;tfp8p2L8&$=k1;ZmEEY2< z3NqJq;Y$ zF*lS9f%kH>cFp$`!D`o5UCedS3r`#lWXy#PZ0w8`xk|RiuFhW?xV?Hb!V_cOw_2Uq zyai(Mo@POo1dRT24`j7A6zJ+;p)DJe)Rac6;td^r;)UX7-a6{8QHkUBI2DBwJlX$U zs>yn&7qb0Q4DDWd_y-!Q8OZ5J-xu(21^3UTw0|mInOK<{S~~ov%G%$_!@q6R@XI&x zss1WqiND0Fe_F!-i1_#6zgof@F&ixK-ZQFFhv21s5{=n;8{-<@!VnY+zJUU)!n3NUA)6wHK$@qX=r*>L|h||8kQ`YY|8j!yy|?q+2HHe>1-5A zH$JUB0V<32=rpNo`qayl55}`4Xqv`MUtV4=a5CeWUt9f zC~l~gS(?)BZN7-pDj)DvBcJI84_Ej&OKVThkH$P@t6xLGBluEy?B$neRo9u6YCh!9 z4O@Xn6fr`&gy+ue zFkjc9qDqmmzp_GsH;bYV?K07IBSi#OvMcp@1#y^oZk?(x;c-6su@VG9n)25iDRxRJ z#$lSj__}PnX2=YwV9s&;De)4sI9bnvZ!Zn4nr~0YYVJ4q$kZcJu%cP}xyp_+?iqb% zS;IHCd&sRaEMawTh}vZ=N+~F)S6+sA`ssGHPgtiDZ-E3`Q6Jp7*N$Ub4#tc1nN5EM zD=u2*A^t*_0`Jh-PCKWoKDA{BY{9ZsT6PaEhazb$R!K6PdGlwXsW=pG#T4;PQB+)3 z=U=~o`s`10WyD50f$J)O|2BXRX>H&Wwz z&pT6qIFa^69|5SxQ~8xx&?=3%1`F2(e0`GYWG+*8s_-6YIN^JgeSdp)!uWf@qv)+D zXaEZ?)W^wlOrPV)f=A}!6Hex2eD7^_F(0^_{zM|SwKa2qtKgxb1;HWsYxBKw;&_y$ ziM!RA~3N1#W(v0=>Npi z0KVat+P}J{S=fKkHT|O){}+@0_j}s^ylaY9wf?JXg8!zXY(YVsWRPfXOjlxFrL$V~ zYr>fKh6?aYnPD&#UlgM>KR@lc5tFFDWV7Z~D;VoI=;CqpsI$7*gisG9UH|NxKup?| z>hrCZ%NsCsagZ1rK>_JWCDg6lEwF-?2M6Y-`vc;d#}ok>7nlvE07}A|haNu9SpyUw zU9U+bF$G1J+J+e2wrheSa^`k^4|6&6BE8X3TnCz1{^wrtN>;0HIgnjbh zE%Wv1V!%toIkfNUg-Tou!#3~Kjs|KoZK3A(tbcahAPY4>hg;jU*P?G{@c%Os|G zE~YqZhsD`47FGokPa`E@)i(>O4LJmB9q`Q7@Bpb&UcTe3fcix1X;d(j{?7POI@EQKIT{ZibDwdCpFL@guU|2M3`p{jM zBIEbv@u#c5y1`mhcR@q)x&0hUl_Oxz4v%9vHpsk?3!;M&ljD==qh(@Z;E`5|kLW_L zh2Y*tRj%jQ?MI0isc2Ew+%8Ngl!xj@ZJVkfn`AwcY1V_Xkk*N$8G>;vWg`&Xx&@@4 zKba>+B_|&+#zv)_Qs8jzR*phn^4B3F)C}kv_edug2v>;L0UQBS7KL!|m89U)pkc*w zCP3+ken$(CLlt5`-jb3Ti6FMrz~{oRkOx2rX|sCB7eLF$>I%nm$pb|`m28Tv|F~j; zxNX}N@6D{^?{%rAEkzfN*gsys9#Z4F4Z~BnRaBuqa}&wX$IAxpFAnwkWgxtWQkxtO z-yD;}{7kM{E5_M~V!gedqUDAPA6?n&bzuQunTS1g(XnvMk)B|Bu*u>-Y?5YE?OrTq zpFwSPaxW}2w2^OyPx##MI&CBgQ2Nuv$%2eNd}m{uX!a(w6l0vVu(${GIq@M`_gxu( zF}eQQU-1J(E=OL0v`1BR4fK?FS-e(nKRGdHyy)0^JJhuwD!983O;*3M8a*rreq z@lMVewqLwLv5nOUZkI5VBn@Ek(uXpV3@&8U_^IHs)4{GN(5M8Cy$+E4y<=YW{|7fq}XasQ#!QX!g zGdy}jon=o7y7FR~CSBcrBlI@m&4l5Cz|cam4u-nm(MsDDqe%7UfXVRW*2Vuc2RDNQ za$iXLrBm2N5KlFP*IZvnFvhV1jvcv~OZ}2wHVsG7=cEXQln^A;SoBmh$Wiee{y~c> zpY!ChG!4CLWo}7rCqEF7^=kuC!lwh?^+s&ap?V-1c>b`Iu^mXhDoT4SD6@0%`1^I)A7);ooUzMm3mOxa9LqtnrqAKLWTenE_H#eHu zO5RCJT;Z(rShJ(ltCfXQ@r#w&)HWcGk-A-AdgA)8N{MYipBwTJP&wqhe)*0apSM@& z3a*s5TkAcl=0-*VUXn}CvWxx=Ukz-5!pHwh;QdbxM*o0?|27!?x54PY4MzWMF#2zU z(SI9^{{J!<1$(awu^q$u1^*@FsKyBa ziW2iR%XOuiOk>Lh<67wk67P?=lM`_Hyr48;_aR84q(23A|uYTZOzAZHIQGf zp&#DhI9zUY`oC6Xxn_iE*gZ2Q9y?8b-^l7@cuygvkWUm1_m|-N*4tv zd)+li36~E=Fds=QPFjI{9Ia8MY#8?_4{T@Xl3JRxOfiTn+xHrmYj}Z!u81sx^YVUN z#Lnn`o7v+@kuFqGC=w~Ncd;7YkR=9!Uue;|Pj7z~B0MQ?GT=2xs@E)%T-`^C(|m7@ zYMh?wJ3P{v%u(&u_)7em6W@k_Zjg zn$!7?#c3{2939^#v)tcF+=~XlT6~3n3mG_*yO3ph)m@>G*)ASku_bwzf~HK1UNBAF zLRN*GiUa5g)-TTKX2{ZehDx&baz#C~Ocp6~ZPE=fFZPF-B#5kM$q0zg>u z?FB*~sBf3PZ>HF_=U?RA>*R%}e$T{LD(bgQZWKG=ppj5@3DO8dn#~Nb_*PKVOhXLI zpjlkayLSpThRTwEME_i>N2cN97`$%}M249+9Wwm59cnCr-HszhX_^67&;~DmP~|HU z1CJsEsH+1Wqqz0?6!%K1erT22+XA|_p$yCjWALq-LjQ?gbxVF;CPYIsBL$p*i1`MA zp-~%lqzSp7?T?EXgSimd)wLV2BRj|_&gyOsBf$3W!H9FT^lo@rvG-#G^`~|BxQ@cb zBRCvWm`Faw@KRXHvvgDrCsy@ZO6Z+xqn^Pz(7d!9?3i3lwpbTLt{nwU`wWxwP#GBvPJ@8<#9 zkM~>b`S!9}O*=M(bde669Nu38Kql{db;hqqU2MI7PV+nF0J!m!_XLl&xM3cXjiE0p zInT%WJ(b_4a-&PI1@oIZQh4RnaRP+HE=82vT!cU2l-smgYm^oF*Mq|J0n~h_j%2NtqXY4{ zwWoWSJKg(N(`ONfqI#l>$kBP?r+=u0?^~J23X{EN_kPe5;e)7rzNGf>pu1-hC27KBx`c&3`xxpr$zFddEJ|VjAj17kGZ&S@i1E*toSH*<8 zQLL3dl^(IShi&IG0~d=s^-%Srb7**4@cpQQO?N$^r5wQ$1lHyNIboHvX*Jdfuc#2|YOczsH+c3%=84Fok>BwH< z*8u8X2Ho=nI$o03wwyE2FUy8Cey2`q@NGX*HsgCEpUFd4Kj`nvtLO%S$U2fwjU3!q z{Ve>1in&ah2kK9`S7SAzv{EJ)&$*00&zFeK?;HWF(~j8Un5@s1 z(n?OA417j2i4xbks;Ir5r3MWuZ+c8O=cHWwlXlx$*cwAOC8SHWU1i=b^?*#gwyn10 zNA?qK>(*UQLm;aI1lfw*F5753`WBavXsZvjNSM>)mlk|zchawX_KO%NhrSwxx2QwO z1bqKyx5?jdD)6ko5V=|<>1 zP@N5~Y~S$#ii0$fP~y4w*h1FR;ThCp5h{>-(%`*AJ)-mWzw+yPJZ}LRC2r(a_Bl%C zd94O4uJ*&f#6>yWCjLCbkDNfPU{em0`L&E$HiP7T9Fa85=;w#~Gp{ezwK4bYr@s-7 zq>uNj?Wy}Ix7`R`IINQXX^@H$(w<-7fD0O^lbZu3an%9e+H)|slQytf(8jZE7Z@X?i6tb9bqXiWh9Lb6DWkZIUQc?4a&IzS{ zX=TaC#MRic^Ig|tSA~{Bum1g`dWlGWr?J$(&i}Fg{SA38{vd%Wz-+P} zX-?qmknh=B3+T`f;5rJzk@k`q7x-$&^J{`DOM-vsGKh450>h_X)2C{Yb9~_S{Q zYxl;+M<_H|fLLzm$)l^sZf~!@T>g-w(5Nal863}ksqs92x z@RFKPk8r_$8}oqa5tCDcX7svga7$Z8m~41E ziJdb)-rqgBMzY5;^5#qspf4@JzuEl!wXy#)icrR>VFGyct^>@2`x(KP+4z;U2;omR z+#Pm5irZd7TAd70k3G%}I>uLg0E)a2soXS`0m@%H#~6_EF^5)~$kf5PQ=nW9S_m-! zmUj=Gs>6&?SdFm%DvoM+((}7!o1VAZ=2aOUuOsytbFcj+!FwHzp$5VtcMJ?bO-mbq z;&T^S)d{oq-KblJD45K#1_rnPuUU7%qX#pT1{Ves;PV~eL^KoT1N>Cnba!$`#mF0Fm- zLgLfG8=n2(PRs;E&rw{8n_rys;Ft(GnWUz6z0B=C85F|l)RGSTJk3)X$D?!kIlWBv z$ZbszwSJBTr`htd{{YWsL2b!ZY(-Y-PI$+g2G2wB~_rISq?IS!7>)Ayw_66#=X{Pq%+89|0-0=Pz!hfk7B3iPq&ahEz^Z?fPl9tZ|M* zu8DAfxV7{boIpIybV@>h1pVHTp70dz01u>J2ct>Rx_ z)s9j`GU}xDE1E|eS-hPkt6?pP;mc~PN)|^Czl2H3JSZ?_Q@UWB@APCw&+yM(XDD@l zlK8YaxMX?7@_2TV*n$hE#lmw4W6=atp-Nu6OTqFHM7K7B3Txw>tTQmz)hEFLntuaHB| zWzUORm_MDqv0DN$G9;0?{@#tvZ{>96C5Bn$Pm)e!*O9ttcsfShhEhGdLi~*+W4Ua? z;*5EK7EFnJzwiPSVn^EDxX{|7qB`mPMA}o6DTzmA6lt)pzk@0W`54f0nCwnv9Ox{S zD2^Rul5jEXY;VauuXgmAxcDiyxgq=7a?WNt4J@eDgeE|0u%drSN>-Qt-mee0ENW(UMV8)K>;cDu~w?}>E{5W*?dY)cS9oFcdS&H+}fEFL&%F=~Rg zyDbpZA^^5WlicZGtGgzs{QZD?jV^*GcOc!RvBLzMkCAM-A%EKQ*YoUI!~08Y>_ALH zmY4$V1R+2`xc0WT(05J*i)Pw^4BLi;#}(9#TSw1EZYMz63aac{gFIcGV)(ejKZQ4p z!+L|9&+9*~$AX+cjPdRe$;qa7gzlEU~{%gMn#y?w-&CDI0Y#rSH z9}FK_1zQcmf0;d^G5-ab^FKrWWBjjKKDyMk9S&F!eP$>)GVWzq5FjJ!M^b1yBvMSd z8Xk~rhn2@Jp`i&05OERp0A`ynC6p;!Rztm4iL9;=N*v;|jIi*Z3}@EsxgCgA!$D?w zPruve%wBqUUVYp?_fFZ3N=9G0&o}T!%f(zZr5c~Rfj%D@MH1iVx=<(O!Wb)<7(1%R zqq?e>`~T7%O+7=IX43bObsVgVGJ558inSiaxw&;~rUtubz%E0*puwx+c8{67Bx@!$ za5jk2rD#Q&zSAhx!;L<~(L*>vmB|e`SKp4H_`6gpf+%K29Xz|Zz-b(FdK2+myH{h2 z>7>#o)Q%ObdDk{KH!%)oUC5|s#7A^PRfg{sP28mT|3oycBfq4#Fr%z5w4U5eW5`N1 ze^JAXKa|TnW0)BqGTW=4%sad=_2|h2AsuJa=a`siiv6|Tm&%ifCuBCO>Bx}b15jO@ zGX{K7hjLlW`S;hnm*noSeaY+S%1J!C4V}+NjAQ6 zk5r39`3-A^a?{LUIBqR)3d#MVNU@MLmtgtmvo|a@Et-+_X_X!)^RSzHx{M3uZ1r8c zxF%wobnyZ5Q^NTGFXwZLrbT^XO~VphGB2!%6(j^x4>GLK*Q(Ge#6J}f`Dj8?vj0_e z?3xJVtuW%V6C#%gi|7MoFVnPb&75D4{-u6$JUi0%*6%PA(mFd#2=81>SCBC>YX)+e zg=#$Q<))iltRx~x(BvPVV2Wl+(twzJhS@-Y-gFs(5v*E+fw_5(++aCG-qq|iXCReaj-5pG%via9#?pne;d6_tg|<@f_n?|( z@0rocwCFSm=Rx5hmk1q$lt?hj;RcfX0y+qm0G&VVOUo6Wt`Q{L*$n-37KoA={8Oha zXg_xsJu&vq{UT5c9b2{0lr=+&z$D6I+DA%9EMD}CW=xhi)G9%o{+H!)XA#Fd^&TL( zJ1b?n1`A7s22#UOFv!|iE-TNRi?LvHj+r<}?Wk}>QWc*-;DL4saIRY2Akd>n3%;k; zHb3SC)t1b=dwH0iwE>0p)Vvy21`0!wfeYLsY~yS#QFjr*?Ktqk12-I zG*`f+Xc%iqF$-dO1SnG&F+HPH*bLY5m>4(??h?VfbAY%wmV3u9P~ZczSV`l8LONrR zu@r`o4q4=7!hK4M6<C2Nvi)(}7I9wjuquWDOB_w29)NX-oY{6% z9z;}=`Up8)6@1w~1^q_Yx+u}=PG#t*d2`8$d*4Zt*z0tyPf2#21c`2f)D))*`u2Wg z!i+va&3g192+JT%yUKyP&{oY*iPfk8SVo4C*kf6in$gIKr%hT|HdWTa4n?$Tn4p=N z-#amI@^5xHO}gC<;enQ5dKkTyZy&bIch=vyeErVp3uBGbx_Wy9-Gh`nF&61$S>??g zxoiH4Aus+}dsCFDYTTG-BCPgr@q=uI0g8Zv;&t<*djR}_uC%MFT*Z(Aq3r^Wl=ol4 zUVR3%T%FwepfyN@sV&sgap7IFIJb&5ZODF0$K8|Z-(RdAV6{s_hcFjjjP5~%kJmoX zxckkb$Ufb%}oV1NceDul4!L4t5Gl|MzIQ1o5s9-z|9RB z3kR-&oo?SQe$Im;Eh_`LL{ix*u?&$SiDvkSLuQS?Nk|JuXJe&=6omL^pj)i!&sPi2 za5y7*#GdTuq^XSC2a6pAJbQ@<)CABS7~5!^rO=x9w!k}C{>=X|Fp>z9I*X*~fiMAEg4c>7q;{p1jbP;j( zPP|tdsom?aOsh<7e$~|kAS|ZCdQ(LfscLp+xtzhQK;yad#8mrmqkFcD2xMClZ9tYV z^4z9p<1#+gvdqyuu)|fIIcF113OlA1Z<1#Y$NP0LEj3Bi2iu}*&SL1P98xjJDr@@n zfpON^rPZ@!eZ*t`(yStm%^ zF47?f|48f$TRbikWB}__=^wZ$;s)^`vO&x8vL^T_5_IaG;K_U}vUcf=$JsH`yah~V z@FGM_e@K@{=)|w$8pCBeET_C^88_AN`ROaPN`mZ72GQ3l9(KIGEp<`W2#nsGNSqx2 z$0fFJR?e^1FwXVMBO`}8A6#F;FP3T!5z#Dj?J&Rjra1^#J=srrYR@kxzn4R1G+)*< zckOVhrw70skY;uZ8{4od^zsA8Dn}^|5zw^^{ z=QDnnCE^1KON04TNuMx`Y+Ef$y|^vIty7R+)nci#EuvY<3BI)Ju$tTKMO*pU@Tqcg zF2$-{juUR0U(M)A=t-8ENc69*zSxsRsxh%xf`k5AiJyo_F0n#(&JrztIG1b6=x#e|d(J z{?Y`g|DR^&zyIVww2J26UhVREsbzxfM^U+S0*GWHh1_*$wDC$}I*8JA^Nuzzvq-N#)1} zW=RC%<)Y+|99^Uw3FP~k-eLG)*T?nB=0ZsgRv2rlw`3hG* zdm%9=oi?1Yb_n)7+dVc30NgjATE4FFsk}`^H{T+WSKgsW8wEx_@tmt2#1YCR)3#ybF=5 zl^H=dP}PL%Z5PTwEpov65bj`Qe2?MHT8L{6Ttnfz+{eJ>9|#c>iJ!E!eo#2##0@$` zy0>6nFX5JzS{#{_=MhB&Gz{C^Gskly#>8Cjjsu#r6 z8%})Q6G-Uudb!nDhY&-<$@60;gCmL8+b>TTU_Sq6m% zC_#KB!vVqh3WmO5fzN)|A_9YuKT)*lw~l|!}?ByliN7> z=v3u13^i5IQuI|(^{e9iV4DMnCT@W@^R0z@1^>c>%{vTKgBu7xaQ3;#;@B3$$apKG zkb#L@8&B(Y+Lz%5fsSjqtuDW5BW7$|$T(1#YVsuvIeg?$KmC)3)tNDuaKW(w^|1c; zuCtMN@W=3es^M=0!H$7g>NqtA<{&{}V?0&FYR-gdbC4X?)*y2ArV3!hG=!biT-r@Z zVDF-pFy8-r z$Pl5^x?|F2fJ4%@6Szu8h}#7B^}H|mw?HBp>N~vq<210Ok~Z?ol>P3J=(;g6op(={ zMLIwfDCZApBn$EBlS;}wtH^gs87Ic$RsXDnMnViWCs6pj|7JLP)cpkz)h6=dZ_~Bh zNE}trK!s+n9z1;8f4)Sm3DM2~Ryxd3s(@tHfqw>c z|8~TFMs8LI2qoM?9{=a~{j{Z5Kq7~(ovfXmjhENcN z@dT31>BSYk90x!74yj|2Hu4_w9}S3uXHoJOCx0x5cL{xy*As7 zuddE}(%Nq{usj5ToK&$O5XthqhXKyhb6eDs+I-5Bb=6uI%$Ri|@eACR!R_p9BXHjA z%ahr`lbO%E-&Nw6AV=@*OD?xu)bH*34NEkKQ$qFB&J~pDL>{TvY;L{KJ5RnKRScgD z&@7)H8nZ;;4&czSyB{Za4P*DNgNyo-HyUm|6xc)#)nBMYed5i%Rg2@~kANyx$CW;C z88C6p;E4gA10&C;CX@KRB<0u?yI9#+iRi3P`UmG0778h5+^Eg~bb5$F`UwqY8d)NJ zM`k4ZbB?Az3^4y&0KIQLkWhO%tPy{-dh$D<^e#)8oxaDQ_2j>1ahTJo$Qhq>2Xh!Q z$~mTFZxi`vjw2Bill*j^-UD-#blrQxX$=fvZPkc6bqL&8Z+RG}JOz%7)1l)b8KyHv zYTuYbkaJ33q>|X8uzK(Y!Y;9dD$@UuuKNc5OSC0)ID5o_8eNxFELj&}Fjj~de z`66~b<9R?;%O5JphX{Vn3r7WbX^ONLyHDNOCT)Lq&pIOt7)&79`FO(lC8%kg3a!uy zu$~m9iXw}|eCCWJeP$IX%am=?W3D6${iYR}(I=j0avH6Xj=z8p2Y)>M2_=2ra8|i> zh*Q9J(E4dbhQcf6g(f}|RJPT4rD{Z3?|);!p0xn>|2QW8D^^ZqQ8kh1#JspcojQa^ zrZ#HwJaW}6D6}SYS*uo*;WtFp!rySTKNjQAx(V3{xA^IQcE_%A{tW}@CpbhaEqiQI zsI3DkTAauTQSV`Qq3qnks6(8(pif_U(QCmp@wjZ*rrk8az0bEjbvzd6Pfvl#L$|*B zB;|I=Hc304BGu~*F@zJ&r~<~h&rXewM_qkU*oug|SuW1~c(d@1PN*o*D5q8GQka0f ziKzkuVL)7c3$*3#PFyV1jj4=mfvJfD#-BH9t!Kd1x3sP4_Y|wTcu2^zs_J30%KS6@ zx+DmAHo>?Dfo1fSDDgoL0gmxkX&grvx@UIDBm=LO8@N3fQ2DF8!^6wB#M}9H__65w zdY`?*`IivfJBaaK=@*sV!*$)h{(kvN)qbh7qYYc@hWFX@p+qqpH*0XVfYi$${aBVJ z*2ACgnkaP9-?M%56HMXhN3i`OTebvWMVBxaisN0e5U}QcIF9l6`nsB=te7vW^UO#v zQD$%&A}CW(2{B;MCsQ=Tpr{Y=09#Ex@1$BE%L(7u%MbrW5+F?uU;vjE^b_Wr48Ln4 zu?>BM$1!A|%Map*4*Rq4HBitLJB$6efK?$b4Ba72TyE0&Xvzceb0d*SbNc9Ya7X`E z*CT>eBO=Re41CNY$g*7J?S-WtqY%_|V6Av?#dOWhofyXrSKY-Y5D!q0*B9=1x8rSC zALr(mKo}RcAET`nGW6fY*oM&Z%- zXZ!|6X5B{fVUQ>Jo9M734%rQc>KE7O5z}CkZ^e!=gVR4Kswe$RcNAo)z8oT=&dP#C zj__!(j0@+Q*La@+LBn&o6y?q{Q6}HrWEAW8vYK|l8fgo#!0FB7y4m@5?st!WW>zO6B{xl?7I!0Ki{9W_EDF4sN@cd}7@!$3u(Aquv_AgoaBZox zhMwHAr+Js?;yFbXW}sen?gVRDZc2j?;)UqaSZ+_i$LD8CU&X>gGGDG8E!u9zxNiJO zsR)8hhnwAv5Sc#@RnDbU$xk?64=RqON1KpP+#&)JobW(#)Ji9rF+Kw{0-z+flF)xo zxa`)U!07)|>l0MaAg^&uSgojLu7pA7=}-mW20yHMa+9UjY{Za|1z|EXLBE-K8fdn1 zf`c&t^(5cVOwvgLgV^Z^%&H7lJm3HnSlci($fHA77vO?SrNAsj2XZFEE8x7#+A2TQ3*2fQxoC@JwLU`UtfTAr)wkVfq=bM#qZ7g*{4&+( zn$I0;&6r0{`Hs7G`KLh8{s86Qmz~pz3-70Fk@{>i(Icl{E=AD)_NVJlX1+cECqF~u zWmG4{XPI)gGO5Mqjek1hDbu~#iorL@f>WQSNqJ*>naf)&6t6H+{SZEvnWZ#{J8^oR ze7sf`YFbHeuIi22T8{-pR2cB?Z;4$rfn`7pY!-tZH(KgyMWEj=oDwb_*jUKK(u>cO zbbPZ8Q*#$GTPejBjpmQ`RB5#x#;}H3I}hFzXj9H<2$~nobL|@wojJp1g8px|@n}YV z8G9F6;_(4=w!}P!gU04AND{)y$olj&D?(Qz92gC_ST!IFm8Z6*H}i3aC?VQYGYOPnKd4df-k$LodHg=?ovS(8XI)Nh7VI)j^rTjBiF_2uN zMU>JlLN6Dx5Wh*~-~u#q(GkOcj^k-KA;Sv8fb;DRlT@*eq3d?XLhC%L=sC!r?LaR< zlxStMVISfdZ0;iY*I9%{QOx+_?75rdaYXMDa`>|)9BIp?97za9ar_`rBj2`_vWu~qaTOQhO`Q8p>#TrdDifT!nl z093V{P{|{ry79Xhjw-ckF-Y@i$jyg0sw`3qg@EHfkQnQ)Xv0e%=A^{S~VXDVikYr zav{*iSbr?@NHN6ks~n|}9ydvD!<;K);$COVv1{7kiD~)+*%Mqqr?m?#O}wd+0DItg zhGC=(8kv3nea1VnjtcxlE!`=(Vg-lgq&R#fi?F9kcsaNjRYVXa^yAX2sYdb#ApX^% z%sW*;9zgZAe86VEueG?QD85rL1`1<3J;GX&5M9wcx4NeiytCvv3~`L_4d%KWR%PqD zoPS1rF?pHb3vl=bCy3Hswyf*#{>dUlPlL;{cIH08)Vf)mu?<=q_^)3KIzd@Tr@-vF zNXst;RkvsX@|7>YFJF7BmY4v(zGms+n@6sI2A4CmVBwbHkqMc%d^oXJNltGNe1t@^ z3YQLHeK(U?SBYv$r^#;PjwhpwY`Kwn<5CA{RG1`3pB3KY66}8D6-)E`2&bjZ7(qbGS6-jHR|EzQJoT{d# z%F7P|YB~Te)1L0C0pgQ-W2*6=EFALG4Kn^t+yOGbx|hiBo3jIie;AJX@o^93)4|h` zFq2^T6&j`{M={f`ocd{9yT5J-q!nOcadDbV;}(;q z6Jl&r>WAr0)mzrI@@^B^xsr$j6#l;Aj+%;c5&)^`3c(BRuUw7UDVd~VRxAhn(?|ti zrWxyV0VOCY=h+z3NlP{N8^XkV$E%Sk8-1~UzjH~@+6(9+=w^0$->a81Sm%&7APx&h z{W~{fNSzIPjME=!7 z#t94LqQYo4`9Ff`As&%%`P96EYNZQq8TqYIO}HHJL+nOFFaG?K=)TIKrq-iR7Dz0a zRS<=y@Q=k-vt4xsNFFrOp2es2_Y#rWzeIN(sNOUQte#{pSOCV5aGV+ql7SAEvQXBHHYSldWV_14iL6-5nx*2# zwWW1>KFQ^xu8yd44Jy<l$9+MV!f|zqZBQd53-j& zKEQm=IV4i{asf1}Kqz{lz$gtp-W>zUA&4Y)%jnPIMSST|#Y7Ug1~3h&C3mB(vY z=`^&gI$SsBw|>E>Qc}MQL5=9c9V_L!>`UF{v@9EoZd;~avSRZqhF|8@W!Vv=Ff~1 z$g0DK*9>uF13WlZ#)%J&wNUr z@rZoj%+WO5cXHj`q$P{6Z6(?gptSdxZ{%9TFGj4vq1~`9mGw*J?{g;No3)5Zo6fnq zl$f~ zgIYV?fAqcT*}pyzSujkh5QiZ@4bc1j*6`lx+FiF#N1HjEDh(CrR88PGcpj#?w7>@C zo)ovU)zH73Ani9LX|~ZN02CMBSyFLjW^3TM0W+&f5&Tu2Y2siv4@qij!m^%Q3){S` zfH13#Ds*AM#*o?fuwhAsZGhrr6{LKWT(I`{K%Ob5ueo`sBz?7pX5-RnwcDkwc2$@l z9TUT8z!!O{(Bq_Q9R(i|)oc(+h+ZiTk@?pA_kL14fWi8bUZ0KAWOhydtZ=&Q@#*!o8+2~sI_`jRl5DSe0R*w^=hcXs-dp|pm1Xyz6!eoXQm`jS@Lvl( z9yJ6QlBgFo_>23A?(as2uXD(o_XR30wi%IfOIazGeu?O}b~WQw<&sL2oYpI+jo!rm z>^MxrMPLN*bU|-6nrbqg5Zi2aZ3(!XrFV-rat;l7J=Rv|HR`j53|PwvQv}B#I=%b- z5@b$3Q0Zrsp5~d5lh^ztGc@xx08>hkrYo+!qWNzxW*ENvYYdcHSd>ImDz(jm<{zNtj>c*n^$hS4GL z>edi@iq8Uq?4iphh56dcT2Zw^MV?MoW^ESI62m^37ULPudFwXefY}f=$$P%gx~`dt zvd=*Z7A-?@zp-W~n)uyHf<@!EkokDPznfj8ABh?1(_e~dHQF-i(p4Re$WqZe!y+8A zO^9M`+T)f4=1CP_!^S7zRx2LaLTzdknW{6|)XkvIA--*EH#rL}#PH@VT5n1EJK7-{ zoJgr$;M4wmU|a5=5wVKcRv&X#g#3!ijuDbc4}v%_=Q*>iv-f0jxqlBg!)Ru5ms_30 z6x;l}?su&(wxP5@O$UE%5)CPq-mO-#pH?H>8!R0^{3hL@ls4GJbj?NqnRljD0<>V! zuME1P5%7fNGpT?lUZyfE>u3uNC+(WJ2L~_L#!QUH_ciSQI!jwE$_FahlU(Ei&62z*)KGsbG%DJSXqN>TUG*Z5?7bunQyu1 z6Gc$u)iuk-I;>+MRDU1)F0+iEoJg;QJM3xTj z@RWs2AAguRdmJk~(z#>1tnJn^C(PEPe^PLu+AZ$@c7Ou%vVSf6^z{3n?MlU{QVG234@ki_G9gfJ ztx|LLR}MXp61vLV?Ell{N5Hz~qd(a*;gVgLs(G(E(?D_<&oUH0gMfoHz^UlO8)R4b zBtiQr_5_P$QO>C4s&J6&s#ZAx=CA_jtFgsCgXm zJ6nfOx7fqLA1YRH^ijaq>)ggIsEmKuCABv z@p6P?zq%Q3(J$GS9zdiD<+d7(->g*WhEJ%qT_;8|N?)L0xwcWa$x27Mx|>>JgCVO1 z3`rhOBWG9>5m&X)I?X1rR|XG2wQgP|(y2 zn~A9vcf|R_;QI;f_s409|;0jiPd7GeA zP-1{uw~5*9x=)XdG^PVwErhhoO?`YNe?kJ+M=o|-sPu>#a!sA>BNxK8mZx(;=RYKw zF!B~BA<3R7xlrVTHNS9$KO+M?c5?VRw&Ys~z5*y`62lg=$F$L61Y%Sz`S7iH^d%6U zx;LjG#>60VOki|n_~ zL{2aeVXc{OKgkzYflZs=q&uwEu7q2fXYqDYEN?$O;Y6z!k~td#8sE`el?%akV(+$OJ?rb26Zi&CUTM4wi9lQnU zu1?lh%y{Ro+yYbtUt-~5JOVBhHtQRD6AZwG<(gjKGooi_zRL<(^)?rMJtl)rQ(|*_ z&6RK6>fYN+V4G37lRgy-YHyds)uC;8KBe!!EyCdRUn3 zsru;JMpwuG^F-1MWT`ZWD`aU5*|Wzl?cxCqv5P;ITmkA43DU0>?E0rT0~?zEMK)la zb!>l>RASOiQTtuJz=j5%FaiRs8T9F{BF%`Q!$!x~56D_ecQGqW=;q&5U~d{@BkF}r zJT7>hVQst&vu@1?7&Xx4rJ)lYnk+Q8`g`{0|97qZf(E_BM9)r7{zBYKQQc*t&!b zR$X72W>1m|t$KUHlVM_X_+Y9>*gXBc7Uu!<5ck`Ir;=v|a`;1?QWmU6Bxu^?cz+!m zOESn{xS%I4?Zn;1;eM=VWQBKg`*};f(1N?!D-~{vgeNDE)eYPs-$IGy@ zyPAC}?d;@R|IBJdzqRZa-fsuHCaq;tF$!u(WH)FA%ESKjD2Sh8ztfL?ZqD)X0iWX2 z^R8O6GN+|!dhDc=?_HDi1oP#|eFbjw&(%(Kk3^IdfRGv!1`cJP+%3FpEdVIUu>S)U zb+0Vqfd9)+8FkbIR?5kqtw!`tN&kRMbVXSZP;3?wRjKcfVc-mJ=&2U$Y^N)#3Y!~O z^4dW`(3I1n1Xy6NozBJC^_|HIMWS;o$zrk%ZbdA(Rf|-@oL_;lh+w~8O)*y1m}Z9a zjGzI$>%d&|9~FpPglE@WVHV+e(||ty?D7UD3uo1;O9R-8K9zA1a_CeP*=4WY^wxWA zZmN;oW*Hhy9%VWvF|f!+08ng|C1wLA+bi6jV1V0kaPSYFPr{%HCCQS(rb`Vwb;~n9 zu&kt{7K}X9Du*$P<>j8ja;|8#EcLv)2|S_4HlSuA#IU^zXU*_v;PFGzDK+_%d{DhA ze4?<43g;g1DbWNR_)O@^H{$LoDAsIL)e4#>gTT*y^s9|RHr25;BK%-xf&D=+Yh=qm zNN)xcXb*RiF{z5|E$=2t?UztyJ5wX~ge5Z*H<=6AT^C%2!BG6TnW~Y*#%QSYuQ`_h zBpHn^0WIM!+AnDQT1tYl-4FxrUp$U!TMv3HMyO1eQbJwQz?(Mmf$=TP7;KbR^8Zq` z8<(YR`FPTved`A-b}9#@E?YrCU2TJjhp&N}6*r)AYqVf;%&YxJMzPwXwyUyPcWfs{ zmzEmq19$x=5JN+30?Y_>e)USP3eLA@<`iVeBYyCW_tlbL9v$R|@s(@w1K%en-z!Ll zl(n@kO|U>}6)DI%H_J<7!$Moizq2>^;a>_jaY4@+IV_8D@Nq0`>RF%9IfW6!rQ=pZ z3(E!!Uygb~bYQ7BTX4DSvyMdIi>!>I*wv7Uum;2Z%-Z9;G(Q{XWmpCV~5WHppvp zrNM(fTu88X>Nc^5S$3st0bgZ8Jt4n_cX`2jIt^8*)p=qDXjc|Ll;oFXN?u5DZn#Zr z{eGdDta$u+F5!Q5d_$zy0)!Lf`rs03%~O<&p*p;>N=AUIcl?Za4C0spcgv9D*>YX* z2({&Z8-R-`gjQH)pPGSx&y2~47{2;cMD0_XIKq0voH^y{dDIT7(9@j2qeKL!-01?c zSTMFBn(W_BDm7y0$%f(o3CZ9a#^bMYpRG@JDAnfaPBe5B;51jcCMF=f!-gl z*Tje2bgS_yNHM)AwTe&);$8`3>&q8%#QqkFIY-04IjV%T1Yu$p{uAn5`fFlVTA=x* zy}h((ou;`*bZPT0Y&WF~I}BRv8$Arh>_uZb5jG+s=0<2i?)Lu8ZI0Z%4!DfmxKmx{oV8MT%We9 zT3__dU%I6-uu-Ez}MQI-n%fNZqwqS!4_CgYCj(I)jCVx`O_Y z7^-hbkQFhk&jjK$+ueXF z{VF#9O;<%(?y#_J;FeIAp{d~GE-|S%x==3n4cK~?-T~BZ&>jjZ(@&;m<4+hi9~_%5 z*KybrtxjS*CqHxBJWwE|< zmQtAkRI4d%6)=k`L7#GI?b48&GvhRFfZ=-KZF#N^i2ZFjIQhL3p5|5T?|@mg!Oj>D2ojesYl%5YTCcO1)O> zA0T=cQ_)K22Nu~A)!j?6y#r)tM8Mc2-wC0d>5n`1r1JM+UqNBRdS$mWurGh^VwnX% zT-~Y2?Qer&)s!=K0)7sk9nuU5CYylJTk7X}`T_oB1s+T=nb2d=6Bn#viP$FhpV^AxXF(_I&PX-WC=@A5*usTNrfJZ z>eMry;QNwJQBG9lU3p{f{LBVWoGl>=Zo~a5r%zDajxG1RrgU_MhrQ&Vl4~10S6`zK z!ZG_djsT_s&vhjt1Zgqwb@*95nPxN|R{@bg_tZ;)*23jP9ui0n!Y~>QppNx`ueehA zAEb-0vLV8#Q|?0eC;GS+q-al84uzH^qi0R1GTrf6%|EGyuZtvd*Kj@tv{@*>Z@4M6c!NgXcu8`7~9=Kj^w}-^QW?bMtgwnw zp#|EhpgKJeHFSuxsVPH2@uId*wDWPg8c_v-9zBY+3gR9)e+_yN6rDF>URLlq-t)I7 z`PB%etq1J7oO0s3PC1~fIdgA3+cw|0!>V)8_;xgvGD(W^5gW%_Kd5v{SXYVRzKqN^ zQck?3Hi$TCECp7K{mdhqB#v^9D3n?*oX|=4El}F9HCuulL0|Tc%`;v&J#&-%u8AA1 z4eJW4jf*Zvmie83I}W($*8}w}&0Wzz7@qIt7*|$J?gtow zC|7}}o}D{T?L2B45Z*#%1Si<`g9aH%y6Is6bik*G=ziW~5kVl+@Acg?xoGl)lKxLN{WJESY5fUx*&C$YCl-2IqA{ z|3tjo-U9vqM&K`!u=$lBLXI6gGi>l32P|vuGi<}tUo!Q$L$75Me2b7Hf!>Z-i><~T zA@X3V-mmxtiI~UhBcvMdO*I7~+R2wBX?dS!vP0(3QdFHimwS?(i!AmSTl*y!Td(gA7jGI79 zh5qfczM4$XWqK`r;hFxogv5IV8~#rwx#KtlmCV1*B|W6Qzci#%ofoLUOhIhcNwEm* zd7epRZt(KfN2Lw6@aI~PW4#`|g_{5_l1n0$vmH5hb&11bp-hJ3+Ds*eS_FHFdQ#nl zk|Fe56yL>BKTrM5`Hrs4{Fa!n3m$~A##jF?r9vc(Icaz!_P1LC5>PH6mE#h@OZq>Y zR7`A<#~ml?_GJc&?$`ZfYOShr0D8?-nVtCb=_%LKi(f$QCVP+es8jE)m>-1ku^0xddD(CTT_<}X2jO~6xcJM07d?d4M$|p9Il|6!hqTSn=Emq z^FRA1?&G72c?x-7NXUq1)c#%NWi9$nBar>YNBl^$7ywTX1zG5T;0lYIJSrTB`164R zze&FrRN|&-aH0PA=VfAfyuk~i)Opod3;i6Y-cm{m^P;N6&rfL|djS{uny`Zq(upRKT_x8*;)lSM5t7n?!3B2LWr&g5V!{NL`M6j~p zc8&vIbOx2kEC*x|%tU8nv0^I>TCEuS>X?Vu`go0>mBZ@ zTGz`c?`n0(=d!UVFhiV&;+|ufbfzw)X!xdei;XDC1OzdSyNm<3 zhtT>A3OH*bsD*HJ;tJy)4_10l3roa#oA|8r_})_=eW~=3-dTSY494R-&E%r-87KFL z$Ol0ksW7z%j)p~gnUvZiNv?)CfTeZ@@nduIhc>I9o3!L>xiWC1lf*4WAbi?+$4ZaF zt9GzZXJ8Ebw8{;;5S=QvqrDvouS9Oz&E11v)F)~H?!HgbjX*@XyK{$fwqoQbG~5g| zt$x`@{I!VwaWw+lU34M>Z8Pq8_)O2uUs;$*R}(vXFW`5T*)NEYfKL+1kUC^mUrgh* zjO-w^e-cbcyKB@5omE0l%EF!7ljf3H*>Nk>5DWDj^02JJ)c5Qpnr#+F%(U~y-fmMC zyvV6}H3v`2>J_;BwN0#|lON)tVsW@C6^A9L@K@gX`9rhu*{3U*Y6|%C*_Q_oQ)jO3 z%i!L(T^{~66h!YRG7MD8Q&85^7vt;Rc2i=uF6OOAy@SC9+3jB6n997RG!Akm?Y~eK=RVETZFGE5DTaQ^8b*4 zhmA|Y*bwX0H)D%Qc5L5gXTfv}mI0>42a48@zc)b?RIv#phE@sEPE&CU^XT~QV2KU^ z)UcV5wqd>pjlZ96axt*gQCE*GqKGFm`mzwWU`eFHFGkzYFUSr`XOe7VtXBwbQc{`w zaPQ&4?|L4JL3ZqEtJkdOYhwGN3^BXhEruXA)qh8Me0jvlpzKQxz@%MT+ZDl)2pz%v zr47MM>TKhOxIl%Z<17d$;)_vFEF6+#>r{!_W(-x}5~6GyjcJ~iaOVUYgBTRUd-wi?y9MxcbtA9492X)N#+ z5wfK!iP8^aIbLhfazDSWO|^Iu9$;w%%`9R#D{4z_;u!poQL+pZMad zjYoXu;rCp&wQ`=SxIaC=ShzA$AJG}b$knM+=0p9l#?T@3#u;YNx2{?;VEVE_JOR5@+!)4e>k#cY5*X8j%>T0@Ov7;C zUhcIB%;@&mB%rK0B@0g%4+=8Ch1=)DIKi*gf_-~|oRk{qgZHD4G7%z6EPPd(y=?C3(S`~w&a+^h zl-9Hy2Zb(@&1Z2Iym*4Mu%B?Mlruq}vQ&wwq&$vOwb|-hvXJgbs??nUOx9lb-cd!= zK-|ePl~QEghjcuA)>W{CJ!1lW+xiyLl^y6ePsd%tx~dR>0}o#uq`Rn`;>xO7QPf|Y zG}y{mW6kr}!qeoK7@_1Imp1?seUYMByz!Oyv*G~!QH_glcN!IOpO4XxP7iidATZWX zoFQhoF#GtKW0B?VSMJJI!NTGbUbfYd?Hyn@vkg9TLYg4&;IKsjBaCN=3_EAXhf){V z69PoqR~6CdU^<2VFB~hnOM-{4B67-7P(`>ibGS52Y8isHK}>U!!|a3qBfvZF zeEHtK=^PJHDI9BEboPk>!T=Q06cEyFC8J%R?Kk&p8@5q1N*zCVtTn+MuW!|mDZ|LF zg@L_*a(@fMlmW*11rihEWf?OT>6b9&fR!(7t!V>9YEA)q%z%J6S2t(StX&8U$p<&G zy05gEa-=#hu7xG~rz;(L(U_URCj~)$h6IXe1H~h_#FnN2FHh83{NH3W(g}fQ&;+%v z#-ZR{wre3}RlU&!aO{oY%HpV1x3u0yQ8z%OW*XZ6ogu&y2T0?0{eWr5MCtnqhO1u7C8<)LP)DV{c0K(ZO2=!gl~W{RXUm<)*J=jY(k{^SFgTyZ zrlkIXeK1UJRICdd>tSbzy#wOJ4w)AD0CCVFwCt}ky~2q^FBL&0b~%iKomn9|yOAu) zffYAM&r-%=c7BK-TV@5DzBJJ{yM>68JA22ofo~TEq@v6GL1O3&8XYK{`=WQ9-ssem4a7s-ro)i?Q>h~_bR~?ogEgAaQ3Gk z*1Q~l`?8Z#3vDxK3$jvY_y*7A4raoxY{dq2u%x=b^d>t)g0G@=hAa>sjTH(wlLfF!g3~ykm&fz_%vRBw zUDl~*|KFqu#g>{86m_FonI96V{=%-|`~dJr?>qpx4*XyIltq?<{uI1@&F~YaC!`fj z!Rz&BCmAK>b|CqxsKLpzih_9k;(EYZg6@m!K&3x`T$~pe#Gkq%?vs-U{ zOGow}x3}}D-6RjcKb?#e<{9W&oK_ZF2TldpP5bhmjqW4yKMBE~)t2P6@PdS^9l)S?)I9#?UFlL8jQ0B_c9 zCzwc{W||j3KE<$G(l}WsR5Vd&=SV=KWOEqZbeqYbx}Nc5=9{u6ceutYxezjEnd4yS zBUFhI@(z;=o09RFmRnG*88#e6-c|F^t*~BT9Ig~nx~=&^ciIWQ>}mu`(}<4}3GC09 zet6e}I^w2?4#}-DfPd4EZ1O6dtmfhkP`J}a4e6- zqIr~)?4xi=1yIyHTM8lwwyZ3#ht306bq3W!_a3p3=m)+FPQ^!yLw`#lAMa6_mEt#NaF|bTtEqpMhbj-9Ge)b2_^#eK?IJ-MNB`HuNqh`Sn&7&5fQXP;X3zAB1cv22iBQ zVsP_0h3vZINA&40jygtPZg(OdCpU(U_0Y=rvF3xh;j7V<$>ePP!1d|vsI4Xqdol+^ zVcG*B=zMVj17l={QXzJwCde6I0gUiF)T6@s+R?jghvFR`ypKR^`ip?ikx1j;q~D+% zwS+EPm8Cz>J0O-%cm=Ut0cX^q19v@HW0vCjF>N{?Xcjsz&VCgZP3caQPv=fwbRCT6 z5R1D=VIpAsXLV(%NN&Fci#O-+VBk#uqA|%M_;ZLn)Sm*w7sUsG(f#TI6m}BQJY_7A z?6tqeVl5*nY&N^aT0GU{wZO}w>IzRTGM#&64&p$zs@iTmbNy^IuevOwA4>zrx}p z0|X&y&17YuaDgJ81g&`5lXPy))s=EGG2k8|bS6SlY*6hRA+)4=>u3+)&5)qH~|ZlesN-kn^e1+R7g1^mc8Q)VjvD=B!8GUmjK_wo+erD46*$DfI9Fx=S@9b zyaT}=CPyIW$)Do6df1U1NF14HOnrv;W%`!f6G3TE>B|gUv}YtDC@#cNaH>-65JXvN zyUlC~MQ%4&4)6?5V^275-boPdQ^8nV9&f|rOE`XdVVkvZEYb(@B8V0Tpfh@PJXG9C zGQ|g)s(J6eOCqfZF5HVjPJH*^(U_XCpZ&5cU>8*!B`Q6lr_8Wqu-N=STW6D?y0&^# z&W~yjtpiLzF{etqle)zLmXR;G0*!w->rMRm`Qq3;*?8H~Ye@##-c|S2{?>XHEJD_b z>a1h=P2FxhpUOkn`0&0Sm>{yknsrL?oEb6Zev~;kdV)HX`yzKRol{=Bm}^MA>%DcS z6i;=UQr1P7hfgR|Cal==!G{YC5v@5*R~RJI?N?I6lE-E3tQK^aMh$chHs0nDg~ zPHs?4F=aGhoYZtycRAXX2&@B}bL>(_gC&z9u#$olTsAt~ZK6*&zIOnv(0AHQfx3(& z%Q)Hf>OVrYXROpRIA)&9ekg-2^MZNL^s9@O(GaUMo#E19TAS1vIa%npjw#CzT|u{# zv-$;F7YqorcWMT!U=f48qUgXPQ?@Z0jHy-7(DwZ0?sw!Oko!Fh5J59P5r1gW!Q@bB z1gd#fE`&fC&mzQiL$VlvD16P1Pn>KSSA31P6 zP~bB!u0%DvE=`z@RVmN5oi27t!omYVJ{|32A3D$Vty?h@LhJ`sD#co#kKetJo{ACrwzHvFD#A&sU_=T_{)Z(kn8Gd5+$VEiLVffO&id zO$fT^qY(V#+$P{Vw_8I*-yqWW6zvHZM=rnl+V}KWx8}F}srWFD&5|T4j(8@Oabgd)`3>X^fYTw|v3Q zq1)F>f;n?nIhqUS5gDzY>6xt7pTK2a%=~3ywx@L8Wci13{JPCRF@^Blk&!ub@S^Ab z-geEptCrR2UogKgV!vXnk6msh30)BPXDH|XAQ47(npt%rEsX8n|99?>VJL9~_+lnx zwv>B}*E^u{Se9$PsJI3vv#9O*%H1Y=5D5e@;x)h1Xd2R&s)}(CiP}9wPty&H8%ym2 z)~Tj_TlYsn;|A>PyYxU$i+7|W6 zX)e!g$ej4CqE9scQg4bXIj#>l2QYod^CzFHB#s9nAT!{;?m1D2f{AIYCyS!js*9#K z`n`tgz#Is2_b%~D@Rc;qrbw%@@B3<#e3a&M}CkT&rNXG)EZ7G{-^e;Zq%)y8sk zxG+8UysiubB$wWl1LZC$$*M$XD^Uth=T%kKJ7~Bhe#YLo>91X<(6(kiWrC0CleZV; zlH1UkxY>MleCG9Bb)rliyKiS`%j}X5GH%NK;P;|m<{&jbRxCi5B%~a}%^uS1EJB|f zA}&?3Qgsod3qY%u%pv76=(*X|QP6i*HYsNoobbOy!BzTmsun5UuSqJ({GR z;IyfhLwj>(`BPN-=tN2J{N0&lN-OiHWx)n{W+oV?9c5jyI=1Zp!30YS>FAxmV1)@ z{{cooxxWg!T{LvL-Q%5oD#w&BnsSn+kXr-w1ZYcj34{`6aVkcZNEj?1Klu}`^Qu~p zE_C9D?6L&gX^>N1TT?fM60!83`K|lecO6ZLaJplT=PvKG4fIb6aEyVi&}!)PrY!-i zu1~S(C;7N|31PAC?un^JV_|bp=(f8ryX+Ui^&FB`YFV%ib6M6|4S68p=OXvxd;5_c zk6#@^b0KN6ChSL~av0YtPOf-8QsKr4T^?fNa~K&US;|2fDA_E=`UV@%h=z4lft| za5{ImW5}8GjSv?C+W67VFKmQ6cU$?R(8{VxifcK1h8b&f1PwbJxm?dO!@UDF-ceC1 zO6*Kx7juu^*^v@NxeeeQ-*4e(UJ~6vyf+1wabo->5jP>)8l+TZ^;^7$=xQqMo!k9@ zyQKp+X&#pJu}QRJG=iHe$`cz|hVW)-2I1LIh3I-&`#esw!*|WZN1oeLMVN6`iO^}- zLU-@_(6j#dhaca5|MKtej-Ma>@T7U1o-;e~Zt-QreUjnc;L)z(UO;Jmn6=k3Or=hq z;v`5xs~iAXgR{14k{+NX+%C9*?yj!gl61hy*Q75*_Y5@c>T=by7rym$+HMwZDl=se z*llrxlHC&pIm~pFL*wulEtl)!CO}rsgZK&FG^Xu@FHQJew%utMt+`{wX{f^0SD*tS zqy-iUBW+k;e{cJWykwa8*c!uZ*GJD@zIn2VUCIlTj3*~yrtUjwV3Yy-QHQEe8Mi^@ zSExeRv?HjsVMlHXag2iyZlhFADd{~9E{AkT;B3W*NHvw^T{)NFi7^= z)NITUGSgu-7#|cCRpkgh{8Ai9(4HR}3kbP0OY;}UUv$K<#;IGD5QXz!@9` z>2=rcgSzy-o6Ir1SIL>k;bFl^fc_6T$Y@5&Ohm?Rg=LBn~7wfTloC;MC(#UK0wlg?=XGMka2y4!qw)9Y+ee63DJlO!D|fF`<@zG_7T2*25MkYc?ZmOvR<2rl6C_tfnsd zgkhbrL?qB?;X$p!iL)saHd{Ik7_A9)NV-y_CDf@kM@``Lv~}P$u~=5H+_hST=>js7 z7ORVDTt|TwbaiSR2+%un!`1E)`mZ>$!pECrsD!K>D`s{+$i@ZAu%?w@QBaQ2hYyYw zxD`DHLFyJTe!O?|Mm4G)8bT2xhio?+J1~J2-8gz^nlX;iyrK)~v zQxgy=jiCn_@n+TJf`OAn_@BTePi^`bH@UFbzPnloCV#!+BM|TQ=pW&f6T!zrFs@iQ z2ydv_sWes9dVz*TUdhPEHN4T2i076XGsNi`V|)kGggC%4m{MT06(~4h{0OeF$S1oY zFaSY8Jcn_=6_pyxPQO|-&^`<^cv~(CJyAA=1Pryb z)B?yyt;RlDRm(5FFtQBHtOS6ww8D=kg^}ECRZ2xw%yp&==abbCG0N`VxnlDZ71cwnBwe_EvSuKiQTos`e7e^Nq=F^VS)sjbk z+}WiPFk5%?QqKd^w6~LOHl26V;yfQ+zoZv^Tin?Rp4`<0=$fA|i*e~$=+WU|iiCRZ zm5v@wL-W3IzXzGES|`|+m( zRHV>vJcs&wt)S7Shd={BTMh`U=9B;vnn>A`l?Gz&Nq%2oU&klCg97lp({E}v!XxF6 zUmf$JWyNx-2Bt{PywWpMMaPQhj#f^tdLpPE=pqsnW?UmxET&nTfO$lZa@2;zD6~Af z@kU9(?!pjr3^aqd{zx?MDuzKHAqBS4-<~Sg2NXD10!Bgm0**|@qmR&n{?e56itX3bc=75SX{X+oNNwPhby>oc%yUpVLt<-f^D zFkX8pPv+Se%kQl61(Gb!MlsQaHE#(A^+&IUzU~ExqN9f-2dE1~wSbd6$i9ve_Za8< z1JsTC-*hZW5h3vFbIP|CjT64T%IE2d>f;;CcRep^K>52;8Jm{q+vt)^CM?7sH!m>r zGilI&1G&@{6$H~#n|u41s(DSlFN%fU1j5V|AuW~>MT|$JZ>qWxUFvJGlrb9;mMCF1 zC6=7Or=eq@##$okv;67}$oyV|iI%vFUBy5M#y|Td%X!=ug>2=60q+`dMc<-Aq1N!b zZwFF|?_HYvhrKiSzW_-VxjIE&s-;x-`+P)eA5R-Y9XwO;sl`=gMWBMI|NfurVl4)J zTNd>~ktK|R7=I;$hrRgaG5Sx)6&`7)K>0H+={)}+e!nb1QO;+mB^f&pAQH7=KX@I! zhBu>&e15Lp;N62>2e_-aD4--1Yr+4po}Cf3hzEfmF^<+-v|97biQ|$9vV!0Ky3Sc> zFK`7|;xRdOzNA!S-ah;;E*(-CD*AO?5c464lLNxvm9np#ay^g?hcgHXklS3$T=5#= zO)esI$nF;Tc$nxR#eVq#<^vG^$t${s90BtWc^%TSZ$j}$$#$PT1LEObzYGu-wHm8n z)xHi&DUvVobnIm-uvTZ+iulQ&AVj|6!R6F=#NZl40PZtI33zTA!tG zbKBwPmf&rVpM3w*4{}T)A#I(y3bH6U?v=%9Uc7K-gM9lpX&7&hpFer|)7vn|AJ^|P zE@b0dM}?(mIO-a&P*)z#EID}e9fu*vxK?E2>b^JDx_P`#pqc03Z zqGvgV`Nk%tRva)KU6j-D5>hM~?W5b$&p9aE)MokTx?H}mkqr2FYXk^?{ptAiU!r-1 z@`Ya%@RnyR~50gjI47*3sQ zXb;uV7-fGv1}j1;4k^lE9lW&fKA`5+Wp-I)ze0-m3zPy?NI;1`Tokmt!{N}aMD~iK zi(>SivN)=$wF382op0ADk_=@q@95=QXsk{Jg|!mo00q**X><-a1oO1}QWxs|_I88B zTJ8?^ir3mnc{-e@Qb6d3MBj|EVfD05?@R&h{U-{#Qx-7fsRE)g98O&I3@xd^E|NR6(<@@Qf(%l%r%INBPk;&7AuIg zR#j8nDa-X7F!%DJm|H}LW)O?LuHHeVKqe{7*HbXyw}H_YU^UWJ!qMGDM6as?rqA+u zxd4whI9e4rN#VP$NotF_ac-S@d>4q)y)zXy4F>0@Q(P2chbMe^Slfk4*=7fHFYCdv zuMXXE3ViMltRXPVqp63}zDVSFV@EFrg;V3V4N_>RGJO=Zv3$Vit8l?6#uLn_l zvH5XX=V#NPdE)j03MwtytswD|1D%_GFypNNcHFbsM5~K@l~KGJ@Oo3*7rsJ}zyOdQ z6U%J}c&Wb{VY|%2dd%djd>)tb@sLh&w4T7bqrM=RGImX&gnVe96a zu{Bgy4F7_IBIl~`TYId=cRb8P^9yn-L=Axq9Gk0vy6H3a+wO9b0f#;X#Fl^U)cFoBj-qxeV?; zK6-o9l%dA@#9>D6341Us$}4r&0?w+r)ri6KY=7_WH(7sHDTZNj0Uj$`F$&l;WSnBq zd%h;lbnO|F_`cPrs6L6Oi4Ha3-iP3DSoNqGMXdON-;JyjbV|%0scm;Dq87N{X z4KRDCM;aE&#QV5@W@OHtU-hM#4uY53tGmgTa&||L_&!0r(ON>=-5)x}pP%kk8C~qO zLKqB~qLkUeA;aDrcCljrsA;jPZFmSByVO%~n}#v59%5r}%QLpsUtQlCA-ECjR&A6) zMtGt4%g?)r&4zgw<96Y$OK$OMwRk<%PQ0JpjW>gD!Ow;7qpNu;ih??5m#;Z!0KHjy zfBB8Idbv6DLz9aEtU|A*yPkK)8`X6LqWKzA+-PCh-oWa?LQ5_vzH$Q#G@6w0F>A72 zD*o>r9bc_GhBr51h4IL;ONc>9v{aaf>D3`mDVVZge6LWkoHlt6J3WKW3H+$gz_7~B zN&G>f&cr$dMOr~s`sW{0mUK?4Oit;osz%AY;hiNVQahTNGRwi4qfKM{2ecMtE(R8)vh3Q%zFcmhw7Ith+#h1cH0c%TBdDrPRwV24xf|F(qqDjS! zt6fr8b49v~v-fIu%!^_S(YZkp4oSL<9U?6K0^>O6jxmq>_;R72pM3upi1gk-&LvyN zu7>Rlg!R11^!i3lj)R|?9BDdrAe=BlKx#1A>A26Bl3Xh8PH_rnil-)NSPfTuvH-fk z^penK-EgLQ`=AMsp_J|sUeTdXouaE=PbTFEjKzp1?lR7zaKlntyN|QCs$K#2^1N2} zEwy!smV$?f-H+Q@Z*gUbtNzH1a7XBY zwbK~8V8}{a5V$fUbMWDb3*EkIG3M1l#4f0u> zY^;VhP|SudEhey_JCv|ZtFPUemURMHwop@jhe1m=Vkb9<`_``+d)Iuc5avatnn$O!txz>@S|Ua} zvo|{bLW(78xFqAy`WW+WfB#-DH5r>5TSFka;gXI*(H}I@8iBVNm~eS4JD#!RSfn_# z%X|(tDhC_~7;U2^122)4w=Qib9uWFr47!H^4b?2V4)O3J2>Ue0=+Xl$G9FbZpWEqe zJHooTOJ7chzgFcOgH;Mp;&dOY$^Zw$D(X_Md26%qNJmM8>m1&|`*;1|nDYJG2?LB( z*{?q~-PMm9tf^DHR6SYLOE5PEX|xBre5AcXlj}S2dZ83-mEUaS5T_1vQw%ujhWf#tyv>fhcZErv z?8(t6{cyK(+$wX^<0HfgIocMgl)K=Z^x_`ydNE0|3EWb4Y;Kay{X97B_2Xu??;6;G zv(JZ)jS{+2Q5RkF)k@J;B!xXUj5E97{-@Bn*}?mpgnPJe`R-Gmo! zt8SPP@hWsU*~$UUgTFkPNAdUwpJ!ERGk&Sqz1Fwm;PWhnA&}oN)I~}Ck02;ev=R$L-jOC3Q`e=;YoxBu&NevR44cK_y~hXI4mPCeG@7W zwyP5jZ*SwEg5K19IkR^AiKE{5?naGL6{gT!VK~7WCfL;{TD?dVAW(k2e)8tg(X%Hl z;RPMq0au*$B9c8zUEMZ>1cEX5bh6;)m<*|KVgd|0pkX@dwb)pvcpw%9%KDW$rWIIP zL}o4#?7EcjxXhJ&g!5|-FnF3KSeK>=T#|-}!|+`ArGI2Ga~d2Xs}}98mK5jkd;-xB z`%bfg2n{+=FB>4h2Wtb6Y^WZ2v?d~i2@%`gR2*9wo6=EM#IK(i>4jkSJH-lV2QWMa z$jMS(@(a5!n;JFef-Kp9U>s^*FrCO~N(K=H6l(4i9-edeU8WxmhG@sNSEV(ZmNT$n z^H!}P{u=vcG&bHCTqQ-sfTv2L=>`c1EG-8AujV)kK`ch&6xAAKNo^Y&I-^pzDW^+y zv3z$n&FAlvDAKA*;D)Ew2&G=bi)As@EzPf@mmBUrvJI-<-B;(;X? z5nUGiz`TOu$lqqWLMonExoJl&VN)Ak4 zTcGx7NwKcW5)7cDO^jhu)6lK@(}0=Hl6OO7^+G<6tE5R^IXjQpAzG6Ys@%W^)yt8t zT-MfEj8y+)4wpLSP^pR_I6*oMU)UJs&5LEKBb+s*{hpn73-Og;emF=NTl z5IS@Kgnm8|Ao_^_)4eJ@ZQ&zRPq(m=spqB(kJ~t0neP?*YKk}*6>crnT;h|sAdzmS z{tiv@fpN7WqCpnvge9ynxq;2b30=iwVXG_*)mF7cxSYJA`EprZ3hKi^bIzgltZG?I z#MHokK-e3&D8oL|w&9R}sSunB4bvC-%crde#ano6705I9^&NPs1Jk&RbJa=CIO?3b zT)d#&{*Y7oWjgnt-y4kM1R6T^_?ep~DT&vB6i70hz-m2b(@tXqPvA;}(Uw%lU9&)( zMgf_-AZl4oI1)qEPR&O#^f}b$5Da2;QPtpFRGCsXSsj@PSPKfzfFjJZDI4AMWSo?4 z#dKJ&&+65(zc<*25aK^A7ABLO`*|NEf*56^zq_+L==C7cU9;CL=`BHui22NH`c2iU zpE7SNWT?|1L$%&|p+h)@&YFmWc!CG@z-zGtTh?{GMo*PGpP=ialjbFC3^UkKy1ID* ziI`!bb^J7d=w+d+mukn?6`RYV%_q1xA`L>TLDf#*>mDdTR?MsQ`9+q`uP^g!E0w0B zQ)8ZuT7t}!YDsp13u9;n353Gi{j7jkOB5r~Rc%>^ zE;0$B26}?~hGPx&2;63Ytm8m|yD`;L!*s^jYHSrZpRmqG(z;|vI3u)H#1eKI9W=Pe z{%j*DcQ{iFFAtj&($~q}_l{>W{Mmj@ef#52&%b|hbo{J~Tzb6#@7_l|zNDaddz(io zo5ur^u{9kH*|DDk!9KiuknJUzIYP!rfRFV$#hJBVqSKiDFDM{3?kgLt1tJm2D`v~Y zMlP7=1I}fW=c5tMv@@k^Q={IGBY1zt^lh-JT|A!LSXLB0Dxt^~;$y`UeZ$2V%X)+f znloY0NClT>VJaZMI{6h999^mZf#-nwcdGtXgjZ(48SlL8_8lTw+pzi=kY7cl*ds{+rm$E#|!nj_GLG zuVzI|vvxsxJ4fn8M><&DD&Wi_?U#N=pm)}Si~?ftpBH~m6upj%{vsEp^oa5zYn2Lk z%qS|=$MNpaLfnVIY1tONS3^^;ub|+besvA6uK87~;DEN9yZO_1qfJ7cZ@wmsX7lhQ zG2dYsMpucC0Qk|hfT95_*7xFr3sf1Sfcoyo$g-MKteWGw7KrxXRS0b3s-xCgyLX>~ zolwlnTFD=_1i^zZw1^UW%bJ9MSdI=`tPLj~4GAL(W0c-*JZaK}KOc|ZV!-f35;iBM zIA~>tXwcYqUk`Y{%Wc_ z$muB@vFWIrFP?wm-1cMO-nL9)STY&ofPLEn;~dP+9^(B;52uRKyMhhI{p;CG3|JI| zNNKzDd-|Re)#jL&=(EvGtpzpQM#MHm&Rv2gZVc@sg)n4SE+Tm2a)OcGS6PiW z`Wih^&zJcb7KV7minB_1hdMhHZTd8^em=l`*I9&;qY;)ODk~6UqzLa9O8%Lz~=aWW_QAhA|t|wkE#}(J&(|8 zzUHVYT7-;H*H=_s6oO2gVfd0U1ijAZ*SsYr!{W*Y{XsJ;3PuF9*@W5Q_*FVwc?q2` z5znXQ*rZ4vP@>Sj8hq@r4~`w98y^~*^bQTdA7>NKcMRyW90}n!o;kEa($e?9vC=oS2LcX#*l=;-LtkKcZO^yDw< z*U_^he7-+AdZPY0e)L-X`||R?zJ9F!zc+|@3pgF%CQ>SlhkUbSCTBJTO8$zgvR?Tn zrY2u+`{m!*DcisdMPw_JbvsIQX zWa*HBDp;&){?>%X_HZ|0HXUnqrTZOD6@|E6Rl4vr8&@aTRfkh0&=^PlD1;9@u3yP* z5XP}r@mn1lb&OE%VHwe8&~k%LO7~lbIwgGLcehytgAlk!_X-&rG#>r){>&yd6g4YuIPJ$EX}KViiPUPss2awp!SNu(R)KhAb&5&+0WXB^Yt6r~{liFP@rJQOw|<`dSf#w3T^)dBqz zEyp%#dVy1JD)7L1Tr9zc+TqL;!!jvlVGleQqY5)Ep7cy~h-wjre+VBIf%SgYLckvj zDQZOc%$h$dBGOzyauw2>J!y%oA7pi>BfQ2kpw#tLFOBSW1`kU-)s#aCCrLe8E&f2L z%4L0KxY?`?NkrelSv)~7tSXr7IPZb`p0%VA)DH*%LB`u|Qm0C4Nep%+$VjCpeLO(d z9ZdN)9HGKi$~So`D1h|D?nvfP3TWa!%yEq$upm&_d3ASZ9h_L(YEEZ$F0h!^q4P z5uX{)8>{uDij=+r)dbkRpW8mW&#$%U?dt|d*(Rtl>l!65~bALN=2Zwf$hnUIcc zH0hY#=QFH<+x&sxiKY^;R1M9`H#d>9^!|?Gc^i?cKQPpLI?@~TS&54H*2y4yEoKX~ zuak;$Ot-wcSfafjp4BLVrhqlJB~xWmE&JI$M;uD&fK76ONJ#5NQ{~*jk`$2i4*Hr0 zj8nA~qOg#E2r`gV3OqlYsIk8M7LVgt>}3vQmX9e41RKAnZ81{K^LZ_C)f@<_OJE^t zI1!DdOvH^bQEYKjCwO*!0}hiha~qRsex8|4o@m1*0xZ)^wgo^-G=qe+y#;iJOf*4` zl8tRRW|(G)h1SH4p`}aFfh~8{7K;}iPya9R0&>%6Z7neTkxEf?!4X@v_pB&4tA6M- z%?<<|q?UTBF3Dsdt;A&ASW7ExZ;)<=F5;@0QvMFxK7;S-ha?M=z>3<-uRsb6-8~6&t-$b5WjOHUjCcTsbmk)J>2va-MACoiXb$x zs?xhl8+C?+G{L7hGjKe)34MJ>*5QdXdj-GU+#` zG6|bO^3lUWL8K&t93SUyECh92Gw#9eB;AL1vLEUO!?$E{RHu@6(Gi`H=4li@@I&A^ z!OjpiVg?2TKYWcUW9HhbOx2Q%Z|c-Jkb6ZUr$`OsBpaqGZCNbn5cA;W91@jMWVr;Y(1seW{pA?bkCd zFiXEYID^igwDbIt(~ z^Hss?YK^8l>_$iaOsJ2;EV%2Mbl9r;JAC~PUWbib7Ci+p=o6~ffXdtksoMG0gqiEm z!E3P!jAA6wo@x)szwf|R4Z~c{;Au}<5)#L-A%Gx#A@v$-*A$MBp9V8eCO_}MS4$?F z!CHXzJ?|I{u?jZ1HUv?GMV*?`E>8hK2&LAr@ZtU2WKauKIG(q#W9SpruhGV+uV}ywDB>)NtA~pMTM)2Yi5=u1#SL9{9*hxn^f8%*z92Wp*V0t(f_ImVHEH z_J6-XvVFr^PE?S>4IQno!6*;kE1apkb6s_)s7{bZQ8)aQMP@ffdy+lUq83ayr3TI! z$erK0TKs(Pc{k9{x)20kOn8?1HR47;s(5Y6( z@Mxugps){tq&5tJ=O8n&13TJrbHYCqhno*t&gkngN;JBVlahhk!-FW0p*2~Poetzw zRoyXH|4poHP_$*(I(EoXKQ7vk8$O-`kTC{`+YIe*-L@5tqt;{6 zsfi{^A275Rm@k7jFA@Gm@~A7HAmewMJ!bxIbqVASTOrBCh9vJ14%Q`nFuVctml4rZ z8!TbA>mz;{yBE*nSFD8&h{a0X(S+9ywRA9n#(Bv9s%xD~GFd)d-dDqxQ|3ZnbbOc6 zrrX}01LeRKQ*DEG20)N-*8&Q}tN=_wK<~M%;xsc(BEP>1kO_rMe(lB+jRT=ZtR zC?}C!5l&H##`y_R3h^M&Xw}a%&&eY8c(o-%A*NPQWPm}Sh z))bRR8{hdB6>uDLlxb?i9UM-_?6}T+Inq>M+8@TIfML=oFAL(dIJ*ufH3GML6GqY2 z^m3H>drzmu+22!7VA#|tdzl*5O9h`?T`2Q~eD60pm6xxcygq8S-1FS2NyyF$5K4fe zu0+L-I@U&Vpg}&N5x>Z|0Aj5~#7YHGrG z1!YcL-6!(VNL?^7Ei8?|w^|M@)jH-`^R-(ErP({j`d{1J5$Of z*d*XW(Kn`N!B}jufJKOKX#?_z@J2sTmd!d#Yhz?{&O9;f`JH%K6C^awk|MY0rcNmv ztqa=op=@plCTcs)6gEqSqMz^uC;5d&^=7*qFQ9Ro<;*)E&&MOYvB#-3l0!@PFNY5$7I8+&5E^&Irs-Am(>2YC zetzS0EBg68H%vE#N~L4bPuH|8`e{qgqMwb^wCG2S^-dUrzZ>}4G%wN=z8`DLM<>KD z;@E4^ccL-mo?x??=}2v{pq|^r=ou!S)I9&t<=jigp9+Ac1291+j~Id*Oc$d5WIEn? zmvQN`=_A>9P)UoPq!Hd#Su zSNY9sltE&Hpz8sglg9FB7Y1;HnEZCABr-b#THB zfg{3Jhm@PhiWbO?ztu@X4e|Ifu22%Sv>wWB=~Ls*+B>0^ORo`oYK9fxM)qa|So28U|OD&$iR;tdbsW*0^&e|p$L znCbfsX7whcRfP|1%UFVnxytGpB5`H$i={k`nad+tijcrO7L7IK2zM4k(@0TEg$gP^ zXo4QFDU?*=L$L2TMa2MSPs_6~WUw*V)Ne7Y3tUX`f}K+CQy7Sw?1bz|PP3OfKFt5T zdHKRB`63Y81ge5-etU|~o;i;8;iq;L%5YJ{<6?3~!!*`xv1i>w1hRg_wcjZz3X zg+bfl@;ICUt2Y?W#vfw7(jTyIG*gy`g=Tm{pVnC6L@~>g^4#fDBQn&VRpWAUotcO{ z?8y#aQHxlNL7r}S6+KKlm^VdXYCpoBv`0SB!C8f_1?uN4524en{R7PKlzs^0ff)hD zaDd*LR0u8cbA0synR^;YAQqYL)+r>+zv9&t?5kRQVRU9YFW8Imf^mCM#A3PP=t(Ag zpeYbs77DiXXgswUf`_JpPabSDXh@av$ysv~Jb(7)7fo_kS? zrgLsDIOm9Z zQgHCzrksD}{3TY=XfE*S27sFArIy1)J~Wuj+7P6Q91YY*8yJO_x~KZLp~@9YUXIZQ zI9V7TZ^zWU%5H(=RUkM^vmRQNPt@Kh#s@^=$$n{GVO+IxJQNJ#qHetJY#PZjT#y-P z+goj_sIjWQKfF8q)0Vt5w$=U`P$L6wpch+{dR}WRVTLXN{i66Fw=G;b=$!GQrI%8R)f>BMYJjy}_{SL%utZY{3-o1!G}LKS73<2^=TkI8 zK%-ZOvp{wN0_=UuN3B}-@@&0Q$Gh5;5Yca*;jT+wZhJ74Rk@lf5?9otWl1atruRdY z6m7E}2FYCYds%NQ@OcIU|Hi8?E+SgKVe+)58!ug)pv62NN$ z%rbOXC)dw3?o?W?S$UOl{4Qs?YU0WCCA(t>)*@XsSbPB!6J)fv#n5OPe>0vmDqNwcZeCbyNuAg8@agWK__HjNng^ zNXOuEteO{Gu37|5>Qb_*@bn)-v^*B+SYBh`Hs$u~_+$m0EfvOAv$!iKh9-2?Zx#Ts zc=q`a6@Pv8FE-oX+S=J0etWMAK)`m3Wqhz_9v{6uV)qF_r{SfJ@ogl;dEgzA!r8Q^ zK#3(MIGD&b*PBNG3E4Q!+GrWFa9J(iYeTXrn~9mxdUrrMSXASkj{~duFDY6DyJ`n_ z#Q8LcRF#UMMO#SppXvL5-Qlot(97pV!4C-1?uVN;b#;gr_|Ugc+ad79xK% zCydlEPiLeQqKL9;q9v*N3^al-5{e4~*$uTzb7J5w0tVJ{;%2^PHO(3WcS8kw^ z+G)$829D&=W87T}oD{pn6_a7^cuu8j5rb*1`&4tNh!S+M9B@;^a*Q!b&WbVSb?Y~q z3Oay*%cjoHkSdnc_nu_IcrXt^)+0GXvo=Npv0j0!r1!8lFh=cZA_0$2zS1Lc_t^X5 zx|y?fA8U-Rs)3yP5G2@GyLn`dv8Lbw9tK71*VTHpK2rzIq8OEva#RmMGjowIYKjJ| zxKqNZ3_`ZWst5ORFv`vzR)ITdUk08uhPAtdcvpwjBLC;Q=$(Qc&nRC(1i01^VNG9| zxWig+BYc0Y%6Y%{Ra4^Ibc@_tua`I{`dg`mAm9F-NwFGT(C*JP$UrYJF7uSdgQ7z| z`BS{FdDEW$*rs_TiaTIa)hKreI<>YfnAwoH&g>))N1d;Y!U?{rYB1UD6d=!=&LJu4 znwK4(E#SaS$n!;{frA_ z1A|rV-V?FiZSgA2xY~=|^fM0?GB5jm!-*}2MBCafT+VIM2LXIWkQ znn>+|z*oc(q;AF%#tU9&V>RvkcX5>i+fID)m|FFQ)2y1~8jZ=YyxdUQe^eX$_H@|y zNDJm?pBh$^iCZnIzc5(hRCExR|pQZOOZ@qU+{@dyUe^XZboFKanpXOPhsfM zc#P7)UCby7;Hb5_!)TDh6bL`#?H{c;r{()1W7!VoHZp}Ec}RV*yE`sE6jP8B3}@B9 z%ITEShZOVO|H(h(Z%~4^`&x^vc7K>wXZiFUsn+UUYfKv@_S$#wwu5;y!(9A0%kh+_lLhO&U*j| z8!xc7W|iTjI^rCP<9`>7^9dRh*ECG=GW)>Az&p^=i2*1=RN?-(jwmGkG~CAANB>F8 z7F+i5JL`ntkjL?e!p0<4&>_u^lZUCMH<@lwtM5I@Y9xOFS#&k74s7vUF;w*mlCQM#Tjx}9tr{by@ ztyhK3LPkRYvpkY`dl6Z@-AYMLnLYPi$L+a1thYu=`4rtYi?-EGK1 z*IgJ&Jg098PNq3Cj^pP?KRmJA4&E(5sIIQ#2uQwfxI;^DU~_%NB9gVNuCDtqq8N3X zS%aVEXTRO@t91w4qK;r)&n3Y6S>QecLcpWyvKxWqc|Kob3=ggJ$t_!tFzODM${5df zgo*Cb%l~j4Is!9TSR~0;R7dXU`%@deEo02btR7X6UAt?Tj}%~ZcEA*+`H*sAz4L!+&0ZHegyV^PPkDW^^(b(cBA0C&^UL{(7a zvRJ|hvwQ{)Y#4M3Dq++rvn?nIr0NNy>SBt-dH$h1M{7w-ryMVEb)7-F9%BdGe4fx? zjfpHOWnsXN73Bs?8P6UTW(bEOaTs<=t14=o_?jD4;Cjl5AR+Cr{!=%EBUY2f#z4lI zZ0H281gEVH&B1hZ8nyC$RjF$Xn70DpPIWj=G`~~42t>2H%xPm+hlj# zv~CaX#)UN=FaQU5(;CpE;~dqnEOC}>c>B5esh#cgnr}?7c^ss25+}lHQA9xxYFob% zPScewL}~y`XZvGnA_?vkXsO!o3f-p_*alitbj8(xd#v4Yo#%-4V2aOGt;W>mI5$A4 z{%h?C zT+#YzZ5sx14zI5D*|FKuJvFT*jU;@~*zSkefQzTUA%;FtOI8100HPY_XTea_|D8bi z7Sr7Pe+R?NNbtIYlT!1120%~fO z)1FTGw60=zC$yD>l+_e97_8{LoYm0W@#6z>$6e%#Cvmti>KWhk>jD-Id5gOFV02H! zm(Q~ou%OW9Y6U^}oIt)YS4T(czbzWkxZYwQAp*m!sA~u{kv-CL242@eG4NK>hyek& zphXvHqHFY9YT4zrT<@1b)_d;8EbK|#R`kjIk%*@5jv!L#s;^Pz|zA!v` zZ_^t-w-_^U*0tQT<2HiC>_fP&fJx}G zs4p~NwzL4kS@PG#xR|KBncYlw_xw~7bVDwES?tgzup5v7!mcyqx00QKb)_j`_U8ZL z?a`uZ12}#%%24&+7inG-K7{MmzTy;Hf!yZ26{qmda8Dl4jhHKPNI!7=-KF%ubmV-( z^24HBfNnI@I|-1?S+i>dM;o zv%1`-wWkO}(Xpok#ACF&4`sbpNY9r!Ev3+gFf_&Z zNp~mM>Vp2__OP6@=G>GUXf?jJw9+5guV?ok_4Y1Uyg$fx_S3Wep;$GbxO9pb2zZ3# z?L|<lsZ|^!n1;ob803OyE8lZ#TT$_x+xu< z_I6)K4A>fCb+|5BZKSb21I?$}MyMPzaTCCT4eIDL&8qkilMBn-q>-A^zeKgKvahmh z%3x5~i5q|zpJr#Bygps&e<7@uuk2K0tQaoT;`}|^N$Wyt#ei=OA)21ANxs&#e`&A1 zs%)s-o7U^vBA?IU@F^w}PSawe5QS@fQqIm#alI=Y48bP>Kqu=wTlw3$yGt5ZZ>iZdS8%asq}QYG3Jll0&QdzR%X~F7usy z#skqko3hU`T@0)dyRje0L<@o|`sWaO*I|US-Ry3F9d0QdEjTU)mS=xwf8n|~27M7! zpg_o&TO3qJ`+K3cG1U7dRS$BJ%hl9s{~bp~{X*#WsK76#z%N39amfP~-v1)JHz$MO znWWBpf)OV|R_w9DvDqSY#-_}VaoZ>o=l9+Ria<;$%ALLA7BS@24e1V(7yt|g@I7sM z2IbTNy_d9M#gQEv*E#iLmS1tbJL+H`z?)L_xQE?oA491r@=8JoK!!DJxzRO)%2LU; zT+GK$a0h+|EuxRXNb$i_l%3^h{0$LLj-MnO!G;vxX(#%VtVd0N-vfZ~v`-_3NjHW$ z>k>o_ebhQ7I>#jEs((LqJQ^|+SlT888%h0d^T2G;+vY$_6#i?p24{^rJo!oO`t9DV z4z>eVaB)|(42Lz2_7iSLd=QUQfFv?c zpr5Ab6cq&y@k-&B5NsmcZqeK}hf(y3NTz>Y>_oAz;--kC1}BJDkpf}~H4EzTD%*`? zY~A4j-7y!8uqt$V?N{Z{TX%R+a$P)Kwhu8)1oW^&Z?;TR-ubT>hc}oCc3#xA*w`<& zv0tdMUph7xwWjwJ(coW@>ZWU z^gE1^w!p6!ipPUQH$JE2l4QRZm(UKWQ8oNN!G#DczlKrv3HTD>)dVia>{MK7jwS6+ z+J!<8KS`TLjmZLxE+M89%`2O13S<>;ZXCUVL*vL|EA`O_JV&J|@Q2@@;#A2nKI>t6 zPaRmU91pNGWKfK)7dlBGzF*=(qWLt~_~_tB*G5MaaqVo#XEj_^cDAH+gl;1dvyY#g zxMx&U*A_GsxBI<6SalRcBcGO|_kGXy&DAF0`#=?|F7axyvn}ZoXXVJRHK?3v8A+VJ zXySOi8w8HQyFg6lY%Aq)S3&H~Tg@>Qc-@{#cK_7&A^*$Qhe%A3w2;-`=f?OJ+UX|H zYPkBnEfly>CTwG`&cTP5FT-j3=#Ou-37x4F-jUzJ7Yr!WL6kuOU7?wFdl(p5a9ia7 zWOOs^OGwjTouaCwl9d?q-Ep;6S2v0YrU6Yy5gGG6gtNUhz7$Yy{Ib4!nS^Ic73*9t<)w>SeV5H z2kIvTf$42zN5<{=vWRgUS7ThwjGR*a7J@CvI*PzC>1?_#77DD9FTQH?#QAz^uD5ZH zYCtxp9fwYAj(Mc|dtY3iRr%5+$Za%9)&jU$z9502`j>V5kRxqf0NGeiq8E$j=xa*!$KOy>^0+`80rQS-c+#TBO-;99rc~*7 zpXt-Q1`0Y|umpp=j;uZp%+XCSTF{a*0ajeOvEkHoNibB=^pu!!MMmG^F^C~o9OBAx zc^!)D*j20X2pK1J%cF~OI#x}rd~zLVbWJlcVbwgZLtXi&ONXfxw(&`7{DMPxa!$^bK;QIp+ljd#H|DA-tMYqb)Xfm3l?z9}FR~V&jbq#gon3$%< zNf|nQro2AAvHXe&XmtxGznC4IBc~G+$4f(-8^$;JFxU|xBYV*4!9VFZnpM>4z(%0$9F@Yl;_{m z(Q0c&UEH?avU*G?!DTYN*>M4(Y}i#Y;+=FQiVSy*C+Ao_`TF#05KphkvTerA* z@QOwmTqsltVAgU>9%U_G*lQyShsNn4aC~_*vn@yhyb+_jc?@N7)-j9<%q@cNbc*x& z9C9K`z**!*)H^cy)XmuPA@Lt`u(;IGS%A@FHX>g?`p*P|1tbgb%+*rr)V1s4X833N zkJQ+hE4BH&-GI_wurD$K)s8t;Dl>`AOAaPfP=#KxyWgCwtp(a*R%wCC7Z`kYnlq9< zh0bOn0wo0LUE6MOxKKh6Z_5lxkBd;>*}WfB7U+NvGLlZn7JyqAjhv6U5y|Tr3uBO# zm@Bc6zFWRtfetz;M!Jm2rVpg}S}AzXi=eJMBc$T3XQ^=&%}NO-|8F{QG$Aw+GFVm4Warvo&cfU`j%N``qX~>8+p(zZ(WfDXAPI2fbXYzQGrN|C(a^};Y|U5ne*`k z05WhqBdZ9}wdcOVI%^d{^rXza&vDAVn3zZJ_qZg`I2U9v2MP$)^AU+Pq&^9sy$k-; zdC!RtsDvj*Afsx%E{WU9|3_%Np=o$WTRGL-N=S&Kb4GG_NW0j5#xK{Rmybr&*X}LK zX+`uox^S-n;N03Z$pJaPh8AuP#QTCVw-L4VVy|lgh^g z?UvNGY$`d{yqcazR5cq-OXZ*y?^sVuw^lE~vn0!*T=y)hbd zVX0<$-Kc3&S6BYOs3#yc53#Ym3$c82AUdIAS|~0!XYctqIyuR75q?FImcZzJ#X;<1 zmooG|jG(4u+u=6|1i+M|SR>ucN&D-Qg`;*mc-_92uZSjU^Q(%~4T~+{N#;q&R07`7 zYnMdg8Y@|C;WdBCeCFAYL08>wJNIs)HWa25Dclp?+0tD1NC2Lm-iGfp@k2J1E`EOC z_WbYR3bd*~)TY_R4C7M#7Z-f+-p>=bBfgy{KL{;_#v}u5P@ZgGaj&)=6Gf>OWVxDI zG;omN#PJUva$r}GGl+05Grc(xqppUxW&jVL=Dtk z*+R$}OBcM))+{)P8GXb-f|WVXO-$AEmYs{$Qlr%|O#NKq+~Y=z87}(CT+*r?h8N(6 znX3DhBz%C;Nz2~oy7q!&@h(0cSu|@wa=j&Bg;xWF(D%sKbtM5GWcZcKK{ zhfhvkk5dErsS^Ye^#G?1hYu3c2Je*RE7OZ58ION0K5LanbS4A{Bt}xTWv9F>kXDSBou$j?GTS?gaJG+Mg?r%sS;%_g?BfejLn<)e z(>_)i>VE^tX}MW%TKc|VSqyI2BO%Qk_^)t{S;g55Z8-$*+w|uyn>zA22d;I*d6)W7`~fi zN`rp75jI7)I;F<$H2&q(_$fydj?W5|Fo0{{fThRGh0^wiA9;vwwU1_9D#2i}P-$9$ zlnOnI=t-BJW03Fn$Bj_Ai(Z=O(84$D6bOnIr|P5P{&8|?Y70fB-B(3XKV9|)zm|4* zI=6}_9HR0#)(-!6wA;zu-q$1 zd8QVL*T7gKTqjl?ph&aPK;Co;^v!@%Bcs1@ve>X*Z0?v1(US_hHm@q3!x7tz5A+No z$-XlQ3#b=t8^pnaqkUyCc1xRGhSMp2S}|PwoR)!a==?E}_GBF^A>{#aQjBSL@6Gmr z?7%neuI<}^W*;2%i9U)UY~A3>V{p|WaGxS-PU&$tPuZ^3;bdTC)&<~lp&yU7PbGs) zk{N+sXp9#Kda^b@BH+o{4{E)zpoYL5Xiy?A|EkPPiZDT5c=RY0&H$hLYn)&-V;{GU zDKNd6%E$9juN7$7%fpSNJM(w{ZAMI?Zh7fZ3zvLt2FGr4dfFSW41L+Ko1d&|&>-4+ zxzrzt)1!oHvj2KOY+jLhMJN)AFedv3T;q0oojJGHt{6Pqu+zb9ZoUaiL3k_51P};+ z@%Xgrz>FpqKy0wDMF6p~y+1EAj)DP9p^jv z#Ni=hp&?zi0^XX|z+SYKUo0?*;`Cw^XFhPt#|#ydo7R%i-8Q2b#U6bSGa6a+uWjH) zlw*UV^t8I?IuW?RzOA8#51@S^O&EQ#Zon%?Xu+v)g|UpX^Ht!N^x)9W{P=`ezrzgsdy936ml7F zW(DG&&wX)OFY);ssVv;AI$DLnhhDR7VVA4peLe*oA)bU$7OTdF)sl%tvzC4-9AVVi z1v3!ce7b);6)EZ9jXJk|hctQf4zv_M0ajh3f01(pQ4h*03Y2i0^d3N(s0l6t=dLD; z`g`z-Rzk&O3y=+poEDTk;J9ucGVPTpFt+)wOn4CW1k#W&5&u>kNc_)owV!HMs;c1) zapT`qXVk~#x^x;s!z7Yzo-vQ^S^~7RhQ&q!Iaz=_&vn3GXk!|+n9YLl$=qp+d~dCWD6ubg5DJBSHerc1 zkMqy5fpWuJ&i|Y8Bxu_gD1x$0u^ouzg?MpsigBG`@}{qHIioNY_y8-^rFQ(9*3}F_ zz+&w9Yh8hGm$EMe_)?m$6e?i~e(DUXP(sfj-mNLOfTV2)z|WPH`PpaT(?`t_?o(R$ zUh>|xXDhf;07(hMjZ4CCM*^#`7`177Rh3(FfbGsIR2u`r%P#dgu;_|xV=>u_<`Fu; zi`)|MM5iM7D|-}HkzJ{n*tsa<>X@>sTXd(=qus9qy^h|GJihegg~7k0Jyi?cFWZ!h z41xZb{MZ9;)?}HZzZaYX#>6z63ORBdujp;?WqkHWjrJ#Q2Y1Mpp#zjxR(iQ8YG%+{ zt~uzqrSas-5@$05x$C!Q?!}7%A@?K~=uWMo{+GG$RXLkv4s(x727ug-R}Th&yy4)Q zYt%3eJdKPiB9u6ZhPIACVj8G)?(Jlg^d*~Jq4O-4ab2WtqW9bwFhsur#s4Dl^aG2I zAC!zer0-PLS_Zp~c}G##UIt2?*A+Nhb-hSEhOUSQmGqrypC$j7qevp;F5zE;r;|~d zfM=0@OVEKrW;ZUwY*tS)8wkNrhqtL$&N<*8%|IpFH4r5OXAzfN#_9bH<|&34?~YuChM*G zG}~`S*VxG-hBeL<2l4rj;QdPCq}!v*G3l&#F=|wGFJEq zcAT1{PIhGC-y`-ur)!jx@cp$PHBLl!aP3fyQ%saJG|sE6_mx^`7gvS0n-0P$_b%P> zf-Lu+0g>R09nR~^v-{=%9&i?+&Og%#%qhQV=MUh@-a#->E{@~HU3WDc)f#R& z0@iF};DxNl8t8?Vyfr+k0Jcc}`K01|VzR!NOL&D@AR~q1aN!~|8l?(BPuop)Y0eO` ziyTWZ6II>(JM4&Z^CJ2y01+fyFHE7s97kl*_GaHARY;rd?r<}*S;=N%z1Dblr!j)> z<|1S>>D9Cj9f8nOD+zdxgn5F{f0veGeLWwIAKSZ0Lk>0SJA$vy+7kTnm_@V6PFjc7 zVC^Hp$&FO$r+oq1XnmOL;`4Yh?V-<17wiR+DqPl-aXnDJx;d*lApaarkEu_&asIYH z&te&HxHTcKOY6k5VpORZI%CydhZnd0j9v4}G_Rb2KsC>=>Hle}(`V+Ix&h1mN3!vH zFnFsAw${IJCVVu@B$S4Gw!WvHJ2*6BJ500Cg0i7c52H)aMYNkyOi*L#RDTE`JhFsu zq8go3E@XEsMPLPlPm!D^(a0YUZ}FPZ7`>u_wD<;bd{V2``?>oV&t&UOM$zF*8FB=- zFnB0Xk5%5)etoxBPEu+l>f8_90z|%5e)7PgTaaGdGS(EBfLzR}*iqjl?E=@9p~+J2 zv;c1bKm41jFfdBQ1QbJI#EP`G6Jv`MW}4wqu^xw1 z?^Arc_CY`YW*JTr=K+IRD{RA?HJGBxwn=r*NJOKYp+ zOQnh}UJDG}9dYnJlV+S>X~P-T5~8@48b!eMFwSye{tuG);@bGngifMz4|F3W7#Dq_ z#3=JM3boJ%k3H%lm{D%KT^w=gS)NBV_P3lZS)Gv-gm>q?ouPZ|T8E673GaFJzktIt zSkK6xf^-CooGdU6&Usdm=sK_l51UEHOrqTdf0_YTLu^DXXDq)n z^RCQ{N}UzH+{tuQ=pH(#eG{N#3Z}w!)1$NpJsD`#zI9ii&2`WD*TDR?JH=wMlS*G3 z6vf|$#YqjnBFZzz+e*|JBdwR?QYMp;&q98mYpvQ)I^xRJCShN$k&Lvnv!J|`S&9r; z&q5%bLA$ZIzpxfWDCoRRpY6uwZ`{w)SCHxk+N5obAmc*H$$h^ojc8+e1dPsFf^@Hu zEEGvQrctr~iT0gNIJK{~MfrVO2?>UZEq@6C0*O{~RdXpm*5gnXIQ1Z1HZ6;dF` zuNzYZU$_8%;vnT1geEDlWF9A+i9u%r#_P@~oJVpLZs$MMzrOT5I`>hiDLU(TZegEiXqne$TW2&HYNRsfe5fnYoz-_WjO&{owlkklVTBJ74vC(*0HFJ<+;j z@IwFjI{NIz=~emT_U9ji=2&v@czAx7dG+ILboEcJQ1|xya6<;FU_6_c++SUMp?J>R zvge1$JTGOvimB$`kH!1T-oCcDWiX>F%i!|zhh?WavGCo#=$3mXU%}sGAMUEWdM9Qcb_x9{vM8#TR(iYOP|sWi;#S{05o-|T1RbwcatVo*3OJ*J@C~cuhlP^q1`6#9!pn&pM zmd%e{7wVFuD9JKpXAV*7gbci*+R+DF@<)CKItEH-Mxc9sP1rPmLL&1on0Qh<8F?}d z4D67$4wa-LLznJQFLdXYzsrfido?5kJoy?=@j)tzh z45xzp%}$DZFi7T2tD)FxTZ^2myfm&cXH`DPt$9F_z=n_)U2J~o%0T6+n!!CUaA?%O zuE-!cF8wGUPo(wmLnn9$5$p3&_X9*(51-&~3$k}nl1D1i(G1&P%q$=5uk;FB{+rUh1xLcTT z8=it~ViM3Ptb8ne4@D6_&44`RcrK=|xG}<@@But_?S&%|Rd3moqkaFx-?OaZO(Y5FfTa%MKYL-RCRV0yjAOZ=3`cx)&fM?tnyo<-o9A8Ql5_ z(Uo{@M4QiWeNC6MU9_CdOETZI0DUmp`Gk=gpS~b$O(%}8) z{x2bA7jp#cThw(GxCj>a7J$<9jj47;YGL&XzhTpC`q3-_hq#f$#zPD6;L}ac7vI0c zrfw%Mbc|hECQOx|L}Ce(Y(a_nWx$sDjeeiy-M)qeF6TR{&<*~Thp+UiYbgMW_MA)D zLV7Ga)3a?!Guu>A9L})b4MV8@MN-cB6W_lPSpGu%R~ucsSFT$-GkC_kE!Bz%A^-`{ z&}Qqv4sAL>n?vfxkOKstXvFNKTygm*-Q5wHb=krN{p=Va>ET|Yw2r6xsDA~yFr1?3 z`hLLv3{8~-qeRRG>7`iwCSz(QY1OLkX@KD0&kaV=W?^~yc!TYPqo)uv`)Q$F+yE;I zaCg5s>vxo{y($FojHmh|pSW+6)J@TCdh<@PflpOqW{s|FymxrhhW-g>T&5=At2yaT zj;N6fQuSiXRfO;v5IDK|*xAoJ0kPe?2`EV2cg2VB$G81O7`)yMdh-@cLsR>_q0e0M znX;=uzRyVq(mg=gRIP=wA8jRv&+p`1&c{R=esU@Kq>a6dbJcGf&JOcZe|C>0+DjhD zhLU}~y2)7y`YaeaUJ$Llz=E%*f z6dEiDsplv?-&$G_V5SWqL;4JnKGM?veMnG?8km%xpn0Ta2Tt|^3uy8|$|w?e4Q>QI%aVbX{NadWBa&YgdV%s0`vC6ab8p zP+jyZ#Y!GG7nzqTdg=>)v1KL{snWo*Kac~Kd(+IT_xFOjUmfcrw=5xWn{j0nC_<&x zP?zE;U3&Ko$e61J9oiPMcJ?zS*2c~@u# zHtY>Ub*MfssT~oe7oS13%;8Q&ZPPW^i}pk2?0k1kdf7kYgmVvyJYbV8z0$(j-;1PQ zzDkgMtMa6033gB_t;fgFSow^%{%&PgnWu^GpRMVtoX3Uk;R7hlyTmCSK=p7_2vG5TqCKraLHqwMu*_p6j%V(j|2NO(+~p zeS$cUe+u=RQ7Ky45AEtJ@}*StFylEx*h!z@YgMwmdI<3OQ&gAm+mI#+kv^} z3Cql>YcCytp*n4=G*%$*ZBsP}{4A>e=~*rUUiOigkISJ}e?F{&Cc#L}x=7`Oom`?z zcP;6{j*VR(*rU1|Udn85=C=cOQ2W_Hi#WeGOZ|9w5?-2{ref8*5ilqO;|n;C9=$Xp zLUZ?)m03AndDIXTCKVrPIVamHOXQ;X=)Cx*ydfOHa}&0#mnLwK7-N~fx_T5S7Z#G><;<~&z2dN{0SQ}z}ne}5^owZDNxCq@wV;* zfW|4M8g-jSjZg~8&dNscMw!QOnD%ZYk|p$;M^n|M+iApe+rq`SrY@-c5|xHa>#}TL z6{Fw=N2t+fY?9KvovEu@Cxu0KXDM0nIqC=zv(>O%PNe$S?Plrp`_Hm@Npc5NOeJE? z!(9~?weI=9>=n1W=kg7xewHuogqDH)!nvU-HTkPurZ1Jh!AJI5A_iqb;%l9pg~Cv54o7dzv{ubM zoR}ieKlBigeplp@x>y*w{5DRgeK@D=xJ}^hB4U6#x>b0qqZ!rTackja%kUw2K5QUE zZ-v3mBLtmfg8XsZ0vC_kzui<|8HQo?OOqz+ z?mI6pI27<%h8oHPF%f&%jW|z|h9Zk2SO?Hyo7sz;7eSTPYN-L8RIS75;G^R!qn>|m zV*hd!@cP=z9A55DFF-l|(*LtLc~ij$$TO2lK*Rnf^k*}+Om$cAuG43t#o_fvXN_f3 z<8~(%Uh`s0jY4^P79ZnLSLKqRv)4*j=>;wyF)feE+fQx!P#}$A%35@=4}6HtGM47t zN61sqV?GvdRn82N1@%nES`;3>GDHQvCaE>wfYoi)9ps+2nO)}w5YG+DQi0-2GOQ8&qvf4~ zAJ7nt0;jyzpxrSU&xP~#>Z|rMjAp=n^F7}-6IbnG^?KS)qx^I8VQ`y;3uOFN4`IyS z3w~`cl3XEREG$W-RIBA%%sOVhIjqsC@b~t*gR!&lTCIkmkhKdj&2*8$Lm0YYkp`xb zW;~4VrVlbS9}6%J=R0-FHka3S2FNZc@7>L;M2P8?H=KQ9)i^LF8s7eac@Mf>iqxg( zM;8l$!GVa8UuJx(k>*I_wJ1)Ht$CPk|3#fo8D&v4xhg}#RrY7b1?5#$eXsQmL>f}< zw~YG)%k97dzr>SY=hSoG1#npB6TbO`|AI0As@nkP;j(ic#Rb+h$*yACue_ zCH3WTQZv9%g@7y;{~JBwfcES+gd$3=KD{Wopb9LKDj#yTklX7ysMrW-%E(4NBGS>h0;9qf0UKO{%M zHQ}8}g~FsK3m`M5vzAzsr6qPAsb z^>&E!ab9rARKH_JZ1!RZMez-_i)e$k#X;lXV?%3U+P{_{Bh9P8H_m(B3d!xPv~11FhWFFSdgbga zJ_p$Z?2t1{yTq1sAvQ(tFKEzvg6UQh>-c;jbXC62a=-_v-oRF}?Zkab? z-)!BR0A%G*_(7`5gD3bKH-MYg!+j4e3m{)Q0+#3sw5JD{Du)W3UPuw( z1W|#A(?&|CS~=W*L$|iAGMPMY3O{M7wp}fDiDjGkT*I2PwcYFWnrY|OHlIBla^P>} zC)t|C@m_8^UcKli=9`6E8tZpWv#d)qS7r%-D4=>QjR+#!ksJu>5t0{gV$3QPrB`{r zX}2S$KTildT>DD`ZezUKHQ&L;9`N$!v)yvEm1#Uz*>T&LRuyDIGfUh2IJI=x2Qov_ zp2RaXZ$&s8Eh8u9Xnc;yM6##8z>nO4#LHx2zRXaFSNBXu50><_e_XWdwH7pX!S$Jj zf|CphZ^Bh9T0!jBac*U0Ys%KzXU1P3B+~<7A0u`s`jn|TYr2{dk>O8;M_Xb@&KV3a zk>Ka~^OY)UI0=yg3d5)-EnPkBMbyM9a$t5XDFFvdony`y8ZTFII2{HQ!l9v87{|Ou z9=$of=&FCils%*EuvSEDNSxRL;Qvv7SDIu@KiBjVYGwtZEGiBJBi8^{%-HgPauoaX zeVamCL`p60N5^?&a5@Q`(yGu9_q6mPdL+-D?-d8}=p}l@5rZ7n!(d|f%?~U;9>nUB+QWam&oTz zAH4g2=10@lRz}<$rUgG&&1R@!;;+B5q-9y1yyjd{ZxAMRrn0qSZDMawotKS=8MPVW zXI=wUx+Enczs9E@Dz`N_#0<)@ul%ReJTI`1@f7&jH6kkpY9FXQ zk3st%y~&q`eGqkOu7&p>2`&dA*qISjr1Q3`DTA>W?2Bc4b z(83@*yKChOFsj96E@s#*XZ@V(_YrhfrQBXxYxb}iXfRsgw-1)jrXuuOx$sCwV@#2_ zs`DtBl|5G@tcI@t1OAzTMy&p86+hdbd+CEN6oOupV$Gc5JBHJSyw6k%(5`g?Tkl=M z6@6k4Lc&9%1t&BJ6d;UeJ~2lxSJm70?n54^f)TopN#Y#aaPB0$+w!3oT^2uiY|G5DTnt`E$ z$;J$i{v&CrA~qXl=`&>6SvVQ+^&@B~NfD>wswduH4h~C~kh-32P07UKl-6O12OUmI z65x`NEBJUjKYX*D-Ton$0Zo#4H&2SvWlcq)ku`a>ULrUlmzI{N_e4(O)PSq_@L?@Y z&nUdfOHS85PvlNOQ{2D5ceqPBxc;jv>}9X1k!d6wJ-Zt%-lmg02QCQeWSZH?ULXS| zqhJYRvdEQ@ICpyVAd-Ka?*hS(*!43&1_!-9tDHUe^=Gf#!O@Lqk6 z3ToY+K!zyAQ8d_1S-?fbt<&kNMI|^6F};g28;Ndj-^>*ACqYBgj{fDOFvgxPkbT-z z8N=~Z70)KF!0Pu)2HsYM30iHkbagP+Vr{~1a54iMZx>#_qNtmS%@;9!kx@olK(sG-%?6cm0vw z)etEW^BJO$r=&Zq*uV6s_f#2<=ceyl;ivWoqnWh;!qSLYMyS?_Ca%IKpzQp8`;(Gq z#HVEw70^ynZ;)veB^Hj^LNB4;>1&R*pp$`XvzumoSsOoW^_FIFsU6NFQs?%v?597s znQnlvKRXLMV#yh$;ToIXQmz2d9C;=iL!P9<=+9!>!j!UH03JF^@?ySl`po|jV4?xC zpzc0CRZO?7)OM%WJwj!+Y^gGRW$ujXv9oYKK@-S}#e(oPx6n`k$sWeuk^Q+>E+s;L z#Umw*ZGnb9>$zKz?!3%8P#Ef~7zhWw0^Xz!;Y~P}V+_ZXOpiC=dO;e6#QVdV^NRfP^$Rf3wX+{l@3QncEH|pPyxEcY1e& zmfF*4QfWTihPQv;wTR)e>1Lm&bweyML$W%ibuc@?0gX)QrU6dtNfd}e8D$c z=~w>y0+cQl$6m(`(>AlUHWHX$MID_FK!u=YB5sPmYt&Th%Yd6VnAJJX0C?DKUA#ya zDjpqSKu~)i^kvp*ChfEj0B_6O~O5aXB;8V=ksEYt$Rv;;4F@b=wB2-gx+X~wV25ZJCsQ&S-juelfo-+ zUF;hs(hKsK{im79dUs7dAMPaAihswuMx5Ao_@f{TGwXO(ZXI^Mf9Wq?&OqpScgcWQ z2W8cA)JdP}uvB>y!FcHbSbS@0DQt)-RBNV`vJLH01W?MemGkZ-Nu!0;VJPLUTO%Ko zE)m=O2Y@jw594>x*gvw6P9z|t>sOQENup}B%*5jvT@VKlkDaP93p;i+*a4iYEHFDPyjtgB_BSo>o$H=_uoEDy_>!oy z*_7VuyJPZ3Ae@2V8$Ygir2QF=v|4%4IOfcmEIS(a`%7ye(;Cwlz@%OhZ;XEHpC}Ki zD-|5!@l8(~R%Svn4BsIE$a&LXe!=v#{ai0V#{RnZ#B^ZKXU}2PwMcP+XH_TQG$-wbzKM@aMjaXeEY{yI~jDh<^hnl_`KZ zsFl5JoX-2ILb36rHZup%u~)&&5ioX~lmfh(3bMTty0v`=3e~j6Y#$pB@%P=(@!+>{ z+z27!o88071Xz%i-~(g?-+_M06D*NCwTd%}qR#->*)(UMx8>m(psqt;^SF^AVt82K zui8x~1cGoCTiTg4E*?pE3@y=vxCTIcLfE8`J{An?c?R{_yo zaF`q-VPBm_8^=314kHR!T=S=qQTB}HCbI1QMVqjoHtMv#=ix$q8~laT4}2ANo#v7f z@9tom`_TJz*n_h%(_2yHEY0HiaJ{0qU3*Dr1;X#BjpoS>U$1z##TzzKbGqhStO?FAY3jfe`E zJ0Y0NTBG8PE3Qv|&YW+^kc~jU8|-A?W1^9yIU7JaH0+r8m9-9ieP-R-hTSfBTqV}J zqiUjmy4a(OU&#xX#(9_2+> zT2=fqsIB)mRoCRD6jFZV4;cptCvQhQApbT538G4OQooYjUvDSKeQ3d zjl#wJjg+8W`AP|NWVlASuMSN5aCg5_-804_B7*#4M^Svi)d$c|*!#q)1e2&|IPc_C zg$orEWgvoT23%IBsY^UX1x65lteW)6VwyTYSxj@%2MN=rpRm7P9AUyEME8+qJ4D&v zIS!*t&BcLD4aMBr%y~8OYOyT$m_O6xZ|*4Wk|eSqN4&WZ*zRg zQ4bV@0+m?Bj8HZ-UFVTHfF;l}Vc4R6o+Sl^y!>sBE-#=i3{$W2ORI*zqkk>*`gF$z zdh__XzHKMag4VC79tFP6=Cv?_5~WEWDkNa%so{FQh zI+q=an=PWnDf7Iwmz-5lbNdGd1p2}Mj{Y)?>o`ASSfHg5{$ip#O$gd3XrGcR-Fsl( zn##tJ6&#T}=qM2HhMG*`GPHeK6J^8fWBn&mcmCdu4 zG^1g~W|;YfB*1i77=p zC%`x1zf&`OG7OFXr>+quP$vZ!017Z5^leZ=qBt;S*wFf~pvy!^90I>*E;eYq?qhlO zrM%V^H48Pa@>qrETomSvJV#d&*VkW7DgC&tTdkP@4*E+6eP37%6Zkhh2q`E?0FCB6 zw!aAa)L`To@P@p);Rbqy__D%w(dQ}jbfXdGbn;rTWpFou!GPmxV}z6C1+fmik2IcYJV2PA?);s+!Vivt!@ zHF>dR2~L!By=^>MQ!+TBYK*vEN{wh`dxZgFLVjGVP?J_7^=7s6#-+>}I5uOfG~z?T zrxd9ROIxzw0R>r6vKhkdpx<)=K|VrFPCRV_t~GEeQAB?a1Kw?-IM7Wp($BP}ef<5? zQK&hQw9SO+Ro~DOQdiT$JaZH*%egzJQk@dDXMMi9d}QiVSR-nUkw!=Tx5si^8v7)0 z^}7XjGlj(?1)*mchz&SG^smTVLZ<_PY`R zbB9G(x4?fAxyyBMrq2#d(i-J_M0o`_c)xc^mHweOn0kBQAs)@IF2-Jay#yloP%k6L6g? z^l8eCR#J(S>k=rW)SCzs(9uOou~)E5L7ORoyZ`peO96vG0sQA_atY!8ub2O^AOPS1 zm>F1Gn>bn+{Bbrnu`zM_qoNE60Q{KfBbRdjsN~`f4FCvo1`Gi3U(5eeYDPm5`QMc= z{x3>K)&@>a7DoSF@jq(+4@H!JLJ$C{@n9mJEp zu0>wBhr`Wgis2m=L%V%ZXfzsn3NT*xyUZKS;JaB(SP)2EZ z0moeOhD1Mn4kk29f|L^tt9%8)9a#RwfHB!EzK4H+=<5pD4Q~vAG8^^!u#IxOC^U-z z5gAMhAd@pkcZGf8+2p7RO=2NjL!qf!h$mh=XQKgjvPqyQ4Mg{&>SqJBU$9+Fp%@Ld zki?Rwph$#DIY+ACd_GDLUW(T}A$YAVD>S2AXb< znQA~|W<%M&8638_vQzXp1_c4FLrDAS}tO zO^e9Q2YqXrF<|x4pY6)J&I54E3tMHJzO{olMG*z5yhzupgA{@4ku1#IQ!w@8v^K}b z#N3MbnNa}vFd=tvkplmRl8;!At1gRDJ~q2BBb*fxI^-SXktxWfP<{X}^u&s?eslX+ z(p`w~MT!0;8KI;iZC*u;g}E8RXoQURaY~9(AXWDc(|5F)#xPm&XG;Iu1Bmg7-Hg9# zv&&X?m}slL`(8-ocVW3?T`>nD@$dnn&9J0H<4Jh_&qq-;n^KhxStdV=R{QsW)7G_D zbroOl(`>&2^tyg$=JvDLBi&#@<54Jw;Z{dYDbhm!r#bq1F|pn`W?^{ZY-*ohz(8Xx^e7Dglqg1$Nf}uL-%AY!VWj^TD7jBn+$W?U|XiZyUhpr_%%vm z>tuxWB4bWXYp+eI)=pYQrOsfoZXG-@w(py2muf{zcr-Q!_O$l4X8)I1|1U((N5xAXSqz648YS8UqnR>rV!A{ckZ@c? zaEz2eUl2tyUP4|Thm-`|*wAtRCKv?&4X-*M$Wo-<1jU<3U`bOLx#|#t$j}B=1f`OD zWb|&y5Gq(#*t)Ff2H&f9cjxu{WpmrktaWr`%B{>}9ss~TPMaVB*nd%r^2OmZ@dDKy zD(XX;oES+QG*!@)(g6iR&1jqgqg<)9&{4UZwPdvbC=%4-0BHTM1meuX89~c-mMuGh{ci+Wj3MS7>psaR3kp5D6%S@T_sg@SV^d`J-;tp z9@Lql93-YA#S@4Ds=&@NsT|RoBV$7f}P`L^L4FibjUlYGJ zEgOPyqdr>Fu<5`RL3-4b0Wme&TaUn!bsHyWf>iPCX(1zFvS=b$@c7i!l(F%QfxbH> z^2xn>ES9w^LI?zrw5Os4%mVULJrq*1{5}?NdH+*Bu^O3Cr8pr-42^)o`?2fTS;a?zhWF=Pia;ECiSkQOL41@JUMw|Lla46ziF&{2c6 ziF%!AnL+Vr@j;k;^?pDT$rRDsvE6+WMiNE2c*$<4m}Ce-%ix0fzliC>u&}x40}1xU z+8C+g|MKpJf9Ti)k!K)7*SF>vYCx2#7YaNbqbq;XupcC92BC_qQC5xfE&s%x_qj=l zGULw=WDOqn7i7y<;C(sJ6lp(~HG}vmLMI^&e(egx!7AK11mjyvk>W?kUHoZ1OsP!;VIYY_4TumE9t;Rot)98rEz%7WpC*Bnd9rNa@+9v zYp1CDlTkSM+S(o_{Qj9&z4hxz(A0RCmK>WCavtWM^G#k?ozjwzucq|@nxj%NIhi5g zrn{7==MHAU1F(0p-`Gry{`Cp+#?uOmjF>mzPlf=H*wPs;3|V+h9{>p+Y ze>`pdN@?K)WJxx^qM^m9qsMZ5e&1G}+dg{_w)kf>j*Hn#QKhm~rn`N_#-`8BwYnA_ zKsx4jy|aUTgl#ihZaS?yaAM#>JK!0-tNW9k%+9kP)}ZR(stD2t9tnWpdQ5h!h}r^q zS9NaZ3J8E1`exq@IP|1U@X=|6=iGKI-dL^47;SFaV6e+EuJRghurAW%rD7HC%a&ZW z)XxRaqVBd^3g*!c+q7j?a?^F#`%~XpG_RqMTBFy}KgKVL?`~6)hKbUPqcd}Nw9l#) zwU%ex&r8UC^BvEtx4GB@Dy(zOQG%Q3?-9%x{lQ8!s+QkrW7g}{oz(}Q%sBt zgOeR?;^1n+zYSVBv(|h^B=~+k1@{MYFqIlR%eaV#Ebm(bqiR?@)T~B_%95iu=nOCY z8ycFo6f(EK)OEzVIC6d-quRfvaqc%2nZArxN2bpF;%vIhWBBINE;hOgi+Z?&Wwriz zPypnw>#Q&jp;PiMv5k|3_OZ?FH<_gKx^06y%2_3viVhJN3G6?qQm#3xTyQhYkJ5$LHvd*;2h^6EmA$VTvVYxqH>?IWN)v(KTX3tYa1FPgV7AfW$9-a;g4;^f7a`33je5do!hct*pc^@N2eoyDttElGzE5d$SN;7XK zL%H2n0~OjnWe7o3)KRP37e9?DNp_ZU-re+tUu%nbVOLrWq4i%KMtd}~#y*w_&pf@dR|a(umBt^xK}{uZILXrR2SN>Rbc)gq=GOie4k!CvY1obw>C>#2WaF3 z($bAbUh?jHFE=qKtYz4O01&hujGL@bkN82ytX=!*A97Wj4{wsyNfR0yXe*`;1Q)10 zK|Sk0Uu+k;I9slNTC8y5jSHtsbgR@m#@3PR>UxgsTt6=V9>PXNhbJV@N^QKs|EI6~ z#~r=xDNQdP3;+NR4*=lL{|8?&HnFjzHFvhL{y&}Ne{*T?*4S3uWJl?_Rmu*H`jIvq z4i$t9$OyfeyLk$uvF7T2plCsgT1!+*1P(Z#>KWl3;2rH5=N-pemlX$+fY~M)j9**$ zSKNBeB{r)1dA>P2db%s;7cfS0KcCd{9he^ZV-ORuF^}9Q$7RS&?R%02$%GOZPB}eg zK*Q8Ma=D@0xKCy(M$R0YaexwQRKWtj$888{l~nlL(#lHg#nW!UcSPD{5)s@bGbqKl zX!&QQlM!dz*@FIzDkGw<`PgGeKu{$wO7(GXG+JO@ts=fWG{M4(yc>wd2yZ~Okz;oq zvY1{vJ&S)tvAN~t+fYT22o_Nww(sA!rOcp5je zg4L>3shW}O3)|e(So=QF>qsFRbFb+;!n=Nq)W~Oo1!OrA7Jjnw0KN8+p(m5AKiOKn zY1W_U?fb472eaS4I;uqo4FXgaZ73Y^Ixge_b@hRh#netFk(J>|d^fZk?gK1kG^V;; z3Y@c8eIhVoLSr6UjP!5;zFwZdzjv;_1+5oV&Gop)EN+{U^**JUwaLr7xXZ#0c_ zF(XYYK*LJFnxJ9LW9dyI5Z(D|vU(G~Q|1#aHNJ_v#0cfD~4N1fT;A<7VY+}z*@B)?&{dHoB!6D zafOK2?-;8zF4crOje~O=5SGO%`xw?LdWqO4R6mlCOHdTxo!e8+(K%fkIX>1}M1O<% z4$2vid1Z&>Iwib}Uy?!9DU{#h3}%zceb}GYd`nX~>TGR;+t=<+G8Tujc69anR_t6} zXrn7lw`LA*fPh`~s0>guKx-fdr=!DL-IClmVio%Xfhizu*~1(c!fE%Ba~4Y$#Lp^r z9dCu?AX66n7CE|&+w$+Eha293E&T@WpC}!=S${n9%>ia1U02v<&0DdI*s_dV%3Fv8 zhVZK~YL`z#0;vaA6b?nhDW!UcYp4`-H)tW0KIsE29dS`xE(;TQ=|_A&vZr$b>az+SG9+QvD@n*zUY@&K}-;7`UdFAAV39aC{G_)6A)6+k|3XB6MjH%^az zIKZ*sAI@?L|FVB@#U1o=>dXQSpb)6{RR}mv04Et72OP8}AS@(IAMB1G1C0)&__sov zQL|9@hxaY4+t{*Wyo~KoJ?N_2l|0m!VjIeke_xkxb?3VgC-N|+6%5skbU9{XAm)6zWjBY{Z6p-Su8^*nGl5c-|jd+$ArvZ{Iqz7o!SUHRM<1hco3A zt?VVCGETFgTKKVvTjLX@rEXP3+p2_2bR{2NE|JpT4%m_IcreoV#oA*)82SFlw{v>DzIe10wxn{h=Wc91 z$AH#b2cIaMPF~BIQg$cOre2pseHv&qRd&v?dc%?@yOxygSpUDcajf_WI2V;ov>DC?H(*Qn@Ef{8Zr|gu2K6l`Tb3)*I z#h9prG>3Oz&}!ghkCb}{+J-6p{*e>#G~Y3`Q@f$5Blai%z)dW4t0DvnYL z>ZX|?$hlL_0hPvx!h?ty{Tw5#OrAjuLcqU*!v{U-taoO}djz$5_iIu&geF;bEkXdH z3?4PVL>PAYl3B0ph!?TDqH>x2(4}2C8;jbHiOkh=f10o4lCF7r5FTH)0f`y}8Fj@byT9(49J z+)VwPbbIvRqzqrOOmTvFRD9PBx9kGGOO(LWoxqqA?c8@>7qX$?$a>IyfhvUYDk$9x7fpIn{jA;_nTJKbWQN*v}Kb&?~16N0Sqi# zIafXuf{>m5vFg|U(M7NNyNK$Kepm`l$TLZw7=ft6FH=@RH7@fm(Jr`7^1Nuk)%>dj zm@BN|J1~yJ8~*d=BcxbVR-W9DLM2`g;06Trapfo%MhKs;(w2je_T~-SjwxZImUD+N zKNQ7rPv|VhKHL_PpKvYJur)-1YNFM7hnp47zV;J*kIKP2!qt^ zeB)2)#3<_YCCf`;Z8gs``u$uc)?;^BtUnN;+W1hdQ>4H8^=Ad>DcO;22BdkEFWf0z z1cH00XEqGqz9;FwP{kY5@j;HYda=t2A{aD6QG_GDeaU&$YTtn5b2AG6mWsN&yW1bS zji6+ZTWuK-Rud=qXrr_N)H83Z=W05u;_-4zI3m!;qSVA9#`WNeo?$Z6KbcXN+ed_; zpXcL@kPQ`dfB?6?pddHo;o)Cp0Y{`^Rl2C^y9t4t%_!Rn=C&Q8R@QeA`}_(eTWiQj zfg&%qjSo}?d&y6bN+yrEN?=g(A=7A(8pn!57+38a@I~5|48B{V4Soe1i*5NSzglH) zCoxG{4e9s|eUbpn)zN+>-OjiorIPg5(Sp0CY|MLy!E&x7=LLA9?Q5kUvbvQ#eLufH zE}Erx@y|}VUZUw@B4ow*kYCWWQPa{oPjwU5Bmha_Sw_+gunfwKKGz2+8LkY zF{CcPSQ~#9v_~9Abdo+Y^n|T0+;jeWF3+&tev6Ep-Q#;g`eIh!A&arSd<@~S51Y%$ zAG)@7h1{AlUF1`FAqd&5R-vm+&GDAKyEEy|B0oTVjWI5(yv&Rds_q#1icdzM&qhAB z!hfUN1@rxY{-?D32au#LZ>1sm=b#+_fF$LAAuay{NLt$&7@IiKnpv3sS4=Wx*-JX< z6$|_>?e)9cXSXNqMNCAMlDGuLM#^fkTG=7D6%-_35U{k)0h31E6mx2Te=Ss;4nm}6 z!k)eMls>c&dyn)6$dEL_#vy6SI%5+_XRUC`rcSEVlnbu|M)2T=V>VANSMOo`bv#M$ z;Y23X1udNa2z^Km9-kKl0%Uo4nUIhWomShva~nD*ARqvn&DPk=%n65$i%Uye`)jX1 zsJy&fOE%c=qtgE0Pd^0UlZM@=l%%H7C&v6t8{r_~lQW*vPGDoiJ;)v$;#iTuO2U@qmLFC*>P&qzD%KOI zzx0i^)I5!Re>j0k@&_U^jj7{kZT#9rOeSa+JY9>Z)kt31u@@?E97ZZgVP3>(^G2!l zw+f6Wx~_y${yL%h&{Qf-wu@>q15r2*F$?}&NxLmFojBlx4-zxG-R4(;ZgQOD)YEe-AswKI`O}uHp-h5X(YszU^71RsV@|Efp z`yVGi@Trl!91{`OPK8m+XR6Ilt+5AM@UomK`j2reya|hbIh<^O|7dMVxYhR8_pzz{ z$hRX&+P?bn8S)HF*={GGsU&B;E~?pZdk#e1U6C;HHe|2KmCZlD>h0W z9=oTc>D23jt|MUbYL|mF(c97s%_{U~WL?@a-%A9z6QdoDJavW*6k2p`pKGqp^ny1~ zklbi}7jNE9=zSu79(@dDac)Eb#Dq_lFA^zg%^K~7_&AaxZe}KT_G@2aM6vS?INPqH8^msX(}VJ@07XRP_16rEG%{=oCmIJs~y z{!x=O9#S%Z0}gMDnGJd%WT-!0zAaU`aV-VK`CQQ#Lhph+wv&}Kib7AoAS~;O=YVOYikpT4%_n*!T{e2j?oG@HUSaO8N-y?Lhl9`E z6P$N7Aj)QDts2lVD9LJF6Eep1d#FPVAT0}3OCta-X1Xc3B_#LyAiah$B!pfmnhL07 zQ%9W>MSWQ`i=J`gdm!j+DwLlwBtJ6{7O3z$I8qT2eXD{+)KG6iCkt0dElDMW6Ge+X zc}E-Lj`8+T$08{e$l_UqmiS>s;wbf~fvE&kCjwmtf6L*=?7tYh`JOT#1S-d}lW8dd zDHBWq<01Se-U(6IsF{*Zw5yQD-qU(R%q0jSOqQMHLD!P{ogNB|ARr$Fwip7GSdFP6NqB2DA!Ha)Ly|x9as&4WMeK1 zs*rmLrgIW5nMKxf*RqBYa56$jND)hjxfY_w-PaxH9+B2@R*qD0?%Pk$Gvk!ufK-Vq zbFy^fdat(q@?oF-5Q%sjkt&S?tFTV$5W0QFV?HURo>y0kLgemUNVIpQTki=Vy|N7b z3_r4&^%1>$ambbjBVXcGZSwN8KMA~AgORzizT&nbAK6s@@%I@{<{d1f*6^_=%4YxGhK#~LXLfWnF@7|`ItY}e) zwuY5Wx2M6nkQMuqkk|WDg!hLrj2}5PVwhtyPE78``?aX(Ktj~`LJm5?McFC3=Ll6t zudJYhAO0zSL8VbN9CmjMRuMG8x(m`x0cP)-=p91tr$V3XCMZC9DkleWiCP)$3iG1P17j`8MY`s7$75+3EWl8hV`rc`tNQEF`nDD{>W7o2vh zzrm$41*mepng+@rg4Xa_eeeX$=}@k68cfl`Gsd_zh(=&MNNs||%a|V7o0`O&@ahYi zaHO?zPf`qP*Hx3YJM_u+7Z7;Xnd&mv1Q1uPzN=6oadh_1$)%Bm8||9x`{lJoK@0b4 zFH6F1tXc)pZSGq4Kk-(#7u_N2+6R_@nZ_rO__ev(ed&N~)C?&ffS45qk(qAr5F-8P z-p&pk)q#+K=@(kBk+Rx`PAXzxuV})0d^y_zbWK+!%VvUQbmRy0+&UE@!&G*cav=GI zsgD*;ALWGwp{1w~OrUvQ3PNxSK|ArL zb7R;vZ396Q3vU|3D$LE?b_j3)6i>zg6Qn%1}Eo_ zmrHta;ND!>!bHCu>9%TZ_dF2J-w)Q$+|G2Y%%5|Hjh|?289s1NX~Jr_Ql+hHMcBC% zIj{w?Vn$nATXg|J2Ix!ojlBM{DS9wYVNz_>S~z$4H)C%c-eaMbH}^?~%g4OS#@ZQE zAgR={G|}09Eds_h{pyn5i;ob?qqZ*s&xM|4g5!TdXR&q>6?Mk(_c7J{p%M5bk#02o`Xn)O50%DN1uy?0c-i;P@C6|SSnJ1;`T?+n_2NB zVt8oc@-z1u8;F|K$H6eGB^pLeB-`X2D*E9-lv_1l5OQC)L&o_EW44Z_`Xgc9mp|OA zz%v4$FpmJJQdBQ0#KW7BIRp<11IUP1?IOGwm4c%1_Y3QI@o^kA9HvsMhqokkRxzXK z`6v2jXWp0pg$k33M~m9&rNV%AzPBoINgxj4Gs)xYs9lV>TYSi>J7aW^@Q=wHY&&}45?_0F)v8>RLAkWpi zAb)WoL+aaYtDSGL=xp7bg*&!Cm>^P}U0bb#RM%SlVPdcmSjV1ROu5zNRnsf=AvhOsRz$>bp*V^@tr<;B*GwliwVaD$h>eosyQf}b>V`I z1;8NSB)ZsOr_D9w_~_|a!e2-aJ148m{wh0DKllP|M?W+nuBc)luZ3j2f8EM|<;Psh z5!(^3X2#4?m|aGead%X5q%jO@umWY(SxLJ^8+#8&(?lkIh3>zRS$&7%ZnfG6#EeWrv^>M}INQ-JFpb^TfOM^alSjCj zLz|v|euN8G6Ez>ieNp!H?H6#PBF)JnJQ&i&;bQ?5)3dv;BuazC@1Agl?P0md;wwS& zh255%ok|{58};dFVNt%WL?$?nkxD! zS`?egV*JXaUB?pEDNYpnJajrs-y2;oQr)e@@WeMbWxKn7!#?5Rtn}J7J}x|s+lTMz z<o}fvkBr%j&>PbY3(f zOYg~!SE**suW7-1@VE-PwLmDZxI{^A?(^2tG9h*SSFf#oKY*7pWgZTHzmTRrdJj}W zUtIEClxj^ir_2TByH?fiP@ve`{dSXAy8{ch;Pra4dP*0y&rA!{%mIx%@*27$k`#RnF>NaMb@>k0SG2H_F^64Yq|zd=&~h#@ZiE#N+aRLYKXd~Sm+%PR1KR8=qK4Ij^BK%+z?CLwzWI%UAsWLLYH@PzspF*!U%cONL_-mK6w9+Ni^15X zYLt#uR7AXwwlEW6I>8ox%q9Gy^-&^$T*blNK+Ld2p)Dz=`wCJao?d_44Z7RfDO_ma zG5u$9pLHplfpJ?$b8_tYCUZwj#U zl!wlDR=0jL!cZTTKE?Q;cidz#AgEwDa3q2cb zDwdtLIuwZLz~3Bn>dP3?W)6059xA1(U^iGz-uYAb=U6L{KOuHOWX}eo+(E+DZKp{r zWkJubiD$*=1Q0O4m)M z!`-tf;&n>ORSGt>GbTUP;hVB`-a>6ocpDtY8h1rPcPHV>9q$>3a>mMFq>U}~Kx9d& zX_}O6ZUMsjEa5#Y0v;xb2?0dBxD%uNpcx3i`^gG`4`u&SU#}VuGIj7iInfCrU%OE| zzEN2+Qkj5H!8olLHgsxZLx$~)tO(pJVau13A4+X})f0zQlVfzTvn!{esYLtdj~M~2 zj-AY>1Yh41%tJ<&{6+dfo$du{r9ACiiO>&0#-cA{W!U)E*7;(D?*3f9r=)W4@iY+P za#Bs5Oz}i5{_Sl)*Jw;Wc~o<>DVwy3073GAr* zq$=+c@Z?a_{bVDPLn`ngbZqZa9q!aCnj$5FWIP{QGvoP7yvIQqF)y8k;&HNU43v^_ zjA5KSz&bGDBNTJCERY7daJ?D;1g1i^O|6I}FkSA4xBBxQr*LqQN=0{!pOP;XQpB2b z;P8PQ_K0(XuGqn8G_e_%20Ikwk+mK?*xU2;_jkldq-Az6P~**u$6173ujh9hWu+AX z)tBs!8i%M|rLIB0MVc^4le-oGxDggGH^#7F4cn@O<*6UDfc6@~UxPZ+S`+-zgq}iz91+H@P{iM=7$(Ns`Mh^aEczGr&r{Z;)KN^ z338K~LjooJFdfUha8Qf%6_TcDfhrXumxa+7T++mQ46J$#_@{|9OCcktfjHF+7 z?ad4fBkQL)k#;oN9OK8$VCekge;i^eUIn#)^f z`C%Qj$R}b1G1L14PWnv$X@@$V>6AKE*xHLYApj~bFHLttQlRKHLhD0LFo)uA$kz<I;+*CUWcrYdtX)Z$SdQ--fRS_h74Kr>LS**yYUfC^zVbQ3BWVB$P5+f&jx ze3BNU;Skc4X-doADmw=oR5w;hK~F|Za7o~ibNY>~fPT*{;M%K!Sg-ml0R>Lod4t&u4(wlsjTtR^$}X*JC2glZM{F|HbyGHS$;c;P9h{C4f!+b73aQn7l3H^J~wI(h(#> z(9KO(6_C97oul>zkN{ml5)||<3r^`&pX_w!&YMUU&(CjYYX#WY=vfI$%a=#1;Q*bm zng8Mrvo{n3EDLw`gh6t&Mi6H2IGnU$Ep2RFHep*rtMY^!-xXNA#>BYszqVdD2|4_yF9dty#9i|1;_*_>%zMq$@buA`7^ohEYNxuw5LzwDYSmBrU<8U%$($*%p(UqxNGhYG8aWSBim2giW)G?ugo3*_el-dOlVqgV+R6qOchZrYj)%> z;PUA;2k*7XgI>P8t}5xz0+w}JKi25^Hp8_{e&X++m=E`dc6|oaW=gN&VQVF5lJ_eb z@WS{XK2t+ZMEh%MdRO%WL4(9%KNG^DxMN2Ym#I9D6D$}F_JCFzgh&1dbAzNy02);U z=+7|RGjhGdcjoUZAZuON&?~O;(jc}RV}w!4E+18HRR`w`71V3>4yvosZ5X<*+Tq^@ zpZllU2bkDTa3)^rDd=tkYt=4r{$d2_L0tO0VBM{*c3(cOzOMyW1(rMhH3dA*LzMIq z5^{h}8LNd_2=0Mg7DUu%7HI08CbVV?TuyOomQ}Cys=&N4^&q)g(5JeDv|^+KIJ|jO zjDLrBxDJq5bW{hSa*ttT@%x2Ho!=dRHjVV@5LMjq7RS?{ePKU0V5}2c;&#Sl6xZu) zEvu;N==^X)0EbvN1;RrhDAS7LTfJZeTGVAeveJFf8em>zA!s;TvS#@qUDL)LM{sV* zp13}XoF=qBO!kjgi@v%kd!GLAG{3YDyglI$aA20DA|Y%JHU_*BB7CHmJY$-RbkEXh z?fqRV)vBsiXcgLdHJIkn2Bca%IRZ&T!tr)x?zCdTkr?wNfE8OjbtDuDX6kG4UDqPB z{uErlms@(TRvlT#=goZxkeKU*0Aa*6U*z9z?Y2Llpf5>RL{5iWKXoRix`hW?iY29&0lTBB^A(LLv2mI zKD87O!$S$|mcKApsJFd8NIzXwN|#C2`{>x+e?ENQ&dNRCZ|v;C;yy2?&nx2w#rzcU zXMP^Ae7`h&*uURa;qAhL#4et`hQ~h__viDL;>hWK4!^#~qZap-hW+qymoGSV`szz+ z#9faDZ4^8@P)6BdeR>IgyHsvXQ{yC3Lh~HWU_pEUN9itu&!F_?)nLyJt7A0?;Zti= z>5Zm$lx4-8EOqc70ip8}sMPgUFf8H+u*5o-x*wKBd_6L%^dY8r9;&q?#VeaTZ|0Tv zoSuSQCQ0W>&4I>!idT3tiE(~O9!Kr)k94Gb2zV$mI9r+o@IA@!vDDmDfZErd!a}h6 zeuZbwE01L^EbRBAjiE~Xa9$I7gMIvn3KfLxOv?@IJd)@d4mIN3yN^Q(+|mZuLu~I7 zHNBv6S4K9PJjB2Sj1PdB$)ES3aDJ{b(2 z24aKI9eXuKKK9hbzh@KrGF{h#X&Bs-VXj%+0jIE}hyPY~x?uLzHxp3P-~TGuqC6M@ zqS+5>@?L3>)N6={fHo}!=Eo4?u+oFK^G>Nnop4Zcse)NwyGWT~jxlTgEL|#_MW_no zk#Z2Vd>rs&k=wy+*Hz$gRRtG&Fpo-Iujj9eh^M}373d;Y^I6y4&iaacXD0!xfW=UUog_ z_J&6zc*i#HX!6N2SB9wBs&nbnNox8;3v`##R-p58Uo&#Z(YmqzI|z^gd9w9f>meX* z-L@};H<|1-qh51jMaKgpbDU#ZzrWLIbA$bM;!1zc4 zPw?m98<6Iuz(=IG)3i<^PB^TAUmS$rg`plWwjCOeS`8s>ByJi`RCH69MsX5k&rs3u zYED^HE%BSHp`$=hqSaQqY$KwU+L(N?jZB;-jM5^K1mF`d4otqxPzU~40P7i#pjC{* zUQEqIE%>AcRQ7s&6&*d?>fIAN9{vue`Jnr9i zTDLab_`Zspy@)aPrTj_Av3DPOK6b^%6C0Z^p1*Lh5F2Az%rWx}k-kJ#l-FcIKYzLX zb8}-A3m$wx{T>S&RV||JX?mT(v~i*kW=HNzrAHugn9wqm3+fw5wiy`FYA)Ik;AsWa zxY|7Ih|hfH4fIVeC~2{3C4hi6rtS_!EawM%+X!&*t3daAD@GUvK=83vL#EoWK8k$x zLcTY^HP(3?y_?W@8c$PN2NP6D4h-qX@CsbT{S$f=eddj*(RE@FMAwP6Oh>UpUKLBl zJnF%xpzB#^hN9lMzxSw-SHRz2LDUWB&wCKe9Bf@3PfTAn*FfuU`Pcb-i+(&D4 zO3Y(i`>y%u;8mJlxA($+AXpCDbzl}U4oKISU(JQrY>~%+7WXgFj%A?rxe;NvJ~9ls zg4#Bw1(S&1G-LHI^)jvZ=X;Q3d>DfoGkRBMScxvSGum zy5FWk{Ju^qN9BW-rD4<_uXC93=rB%xaB9XE)aT24nLmH-~AOTHgW19 zQqV0FiGZtmT^xr7(;m2eOj0AqpZS+{2{@xQQ0K$fg@Mb}jvO3gj@6RQn|q6O`orC( z)2YxkTn)J^3xAqhikNg?jBnL8{0fmaOs_gk$lX-?a$27^>TvyZ7+d~*eIdDtSq#l= z+A#a6Sgrg>HEyMEv$H5c%Eyq`%`~@xntEI; z1YJ!KB4})%BEuAKPPsRW)po=zSR4(@$W{T7nvrb1zd(5EYS4SJ+uAB$rd>0~fIInY zM?GpH<6_}~&A#n5!ny82%CGYQT8xWw?8#-u{Dq6WZwpRAId$qtPD94Ew&r;1*{ywz zz}$ik`sTV8hK$@b?fwgt6~K0YC;u%$et>By@V7yJAouzXQ{kSF2I5X#@)vA6nXSbG zaY1PSzm-sZS_2T|jm1d?4%IkvWa?yjC-*1##b^Umm>tBkeN9X9B;{LVXa)P?f)r19 z%u36%cxC)X^}^Y!(`pR)ZW}vpgyLwe^l#-HFSDe)l}`yMd#G}?*57fo0|%K7f3mQ+ zk_N4|NCjE#Nv&3Hp=0{Z=@}Mf8bNmp6h8kIEDuH2%lhX7EYZa;DoO%*thqh-<{b7) zy;%%|2wOdYRZh6*%;xQV_fU|-=aq0hjqPZYh2ve9Fk`B9!_U3^E7@xvx8? zMr-#OnIwz4J>CLy7jUae&^z(WEOo?uSS!XsQ>ay)Y`3zyxqjU5cM37( z)%(H>qONSD+L&_H{py<0BwOwhzM}b2=WkV>z!uUeQkq-%(;iH&K7BJc z9nMBA5A7+ofwT!4BsR@^Nm9dfhAy<~aBOijrF~!O_$?;V>Lj<^MZCP&-VkHYclTqW z%UYsy$WyTjR0L-{uimjNK*n)t#A1VX;C-kh2m83LNXA|Wx;UYkZ@WJ(v)E4Qc(ZeR zzMVf_4$r}_BmLZZuhNhhl_|;&;tF0pWp86J6hp~JA%xr-k9q^J`3MgJtJ3W4^PX55 z4W|_#$VWnTb<5$owH8m#hyP}_Fd^;m<9oim4XQK|WGhwWP-9P4H&8 zAEvL%hAbnv%^9%LOF8D2ig+VChX^`YvPj(7v9-jdfH)&IFc>Qr7nBQ8Pbb|dqfJed zAPe_Ka1wzJp~EbnZlbIW3%#yThRPP;pr(FH&o5BBJZ7_DDpXOO;JOn-(;Un}sT=lU z_TX&MK*mnbAVA`TfZ>}*(f~QsqEC|BpXL`9=BcljP)yt53NQ!11u?6G8HgAp#S8BI zNEHBv&Pbsr!Q#9Tg}(%%jvgEO#7L=0IF{Bp-vaNLVU;V0Xm4pzwu!o%472rpGe#{Mfq?qv#4(oX>zVZt>Jg*edR$=-Ez(^}GRy{7O{jECxEnFEf|B93945CLApPM{qn$?%ZURz>y zejhQdi;J=el1PPQVW|S2;^WYfAUi+7t*9t#Q?mr3K{k`ZJN*J!$KR}%qX0MUr5I5h zN(=G(1kR1|Y7Hm+p?q3fAZ5S0UMs(19-&Xax!mHX&3OH>R)EIRE!I z&sQpYxwy~RMM^zpZhH+HH~(XBF=Y`+_AdnV_HB3~QvHw$?2wr@tsR7u+_Zq-=(nCi zJt|n3od2V>Z;sA1P2P^}q+{FY*tX4%JGPyUZQHhOtJAS<+vqQ|JF`2pzn$ILbH4oX z=1I;;T~AeAch#NueeSxxx*Fb=#exm5I5hwz`g>u`<<3)Yo8<;(NK{maIY;5~l6HgZ zal?T_5Q|f(4Vk5&jsZu9U6){Rulo1wNDSbP<7bEzkh<-Rp3KPN1p{4xhdlw@j~?i= zkxF|WF07)j!qc-koLRzsf5Y~UG?Z-XYcq$#YZ%u%OfNsJ?02GR4@|17zil4i#BwTL z>VDuJHQ+?AZxAq&axK{Z?5Nt1axZE*Bg4oK@A8tjXRelwApP@GI}p1S9?x^m9@eG% zJC%sq(q3P8%w6d%_)GNF>XS$eadk)`x~JLjAtOO~Yjoh&nJ0*AG9>DbY5lQ3wR%jDO#pr~7-63*&&C$`GvGj6^v9W>}!SyBa|I zkUk{Sg>|0WYMo?Lnw02H<{GF=#T&B#vG9U$iSQcxKGU+$S~=F7iMi!ExWJuq{$<8y zc$=JD_2EUIO7VO#8$^gCK z;i2se(IBvQDA-6Dh$88+ln!fY+xm|!vQz(kTFiF;3`BN3!hJ5oxfNjX)yU*Fn_*l} zsHoH_YEef7t!Q=SGzN+d9!AixPJ6GBCD7MqDX7mwbyFpbg58RG@nc%#bz1<)*|Aeq zM;Zb9Sl_$@FhWI7;CirZ^tZu+UjhT@LT0KT)}}T`g7YRM3@0CM?-7qn)_!EBAb-tK z)XMkDtd%sqybSvWI{k=_>Fsv=I7#HQ0t4#oS0IbvB`7|FN#jWL&T|nCAGQ7F z=hGr;9NEc!kY@OE;PL{80J7fZNLS7LHq~1a+VsTf$YSi&Du}x&)P}fkxR40IJnv1l zny`3}MG(7n?(OmXBI~;s$J3Z;+FGbebX&$9l;fF%bTvL0=7*p{CNl9Ch+Cpp?c(tt zhJs=g9ED(^-?1tR1}ZyT6Llp4F?;)YkdS>iVTkn~%37?$Q#F5n4u!4~mL3JVEHT0{ zbm7q-dXniR-#_u5cyPViUwbN%=k@n8XN{yx4R>TETpGFtKpM7$-|QF!*4~uxWW17( zKmt8)MsLL|T3O+t;00oM74h@a)VWxDnQ5xwB8}^8dD>8)O{ovT$=G~gt3sAEi;?PlV&?sXHKkL!p7m>NB}40yYMk|$ ztrj}0T9V?pHqJZyTONu|NK%gM&(A%Vu<%D=#tBDmeMY3yvLhjWDUy)EG@>wBRvbu$KuBic4PVZU zy%nRPSMSkE%=PxGLavDgXjYI%W+Uj;*czto zd3#$aF}bp>f60hRXkYl8Qe{Q9Qv$G$R^S@H8wXe(W7({=sTQRPUi^^8f3Cpxl>TO` zx@Bvs1#8lHisXkeV_t4M4Sg_1_@H`r6+mfhd9pg&DQ;ijS5ZMvq^c?P196EsgAXO& z2F)WN1`nv-19H-n1cJp8;RME$4Qw25lLosqyLc%uO#%0j;IYPbmBk=Kvzw}d9e(2c z+|1fq7!h=Q4gc1B6*F%xLRiYw9Me)NL(jiaT|)f?Jh11d)Gjx9-{BZ(gF~&YemmR^ zpS$d~MyiL9OM5>nA{2yVP9KZtYMlA!3x0*J^bVEy|U!hR@HSJkg?Cyi=>icKbmAfulG)o%Bu@Bns6P_yN&d zo&5d11EdNzc7-0(7NJPIuA#8nD4S zs#HVOlgT~->G_3)jm@fHF_8mgiv5pw)8zS_t|I$-DO}VmtK=N}b2c-uWT5hUYZO9k z6U@!?r~{Q$2ZvdN-Z!#!wTL%mF{PwbFJ^i>Ad?OjzP6-(LQgZaAua%Oe+Ch!gEm5X ztN$UwXkFfAxFoP2saX__e7-#el+%ef8gvV!nXk~I`r7*iVfyRH1Q4D>(<)+K!)DM5%OF$0c_sIv+ARFOs@aV1r(HH=5*7ZHrk$khYK*UhK4F3*FvD^ zHm+2|H)XYM89{f#FL5R_MZC>cmRrzMbZJ0teS~j>BW;qPO0Y?Nr=QMCjTO7Fq!{dKzVeoO3` zHR|>rlasvVptD(u4PjW9CEyGGeC%ODfVNm8IXEh*)`@7wQ#WKur_5{Gx}p#Ochaaj zVSzTcc&$kps9({FLPes9=|0m*1jDdXK=+pkh&T}8tL!)3mAUV}+r};OIaL&tw>thz z7g|Ldhiv}$Y`UL7gEPHP&ct*N>8c^=MJB$pTENR{+C?rQ$)$8aQB zr`(F}F@Et@IyUs6nTa9p(vDAxPgK|s8>^X(8r@nu)oJDL%g_{8(td*vUmNcv=PM3* zfa8^KJB@ut5x}%a)@`^|JsNHgDKcZggHYZ7j#3PAYVm}>A@#j5!$IcC!ztYu2b>sF ziZL|peqy;o_ER^_uku3-TCsE3In3apDAmunD7l}h0Q;0Ch9Y}Iu zpKV`{W%?Mcr2NxQ$=DhW&*9Tv_C|){0Cpsrb$eq!4q(+n?HN^DaJR0e3oN+h5MdRK zaY%=dr5fs7+urm1Oq~d!>P`Y%Z%0c6CZQt^_u&QlN;|;Bmx=W9RLB4GkiplY>UwfS z0%Z|D2+TY<7jro$6=v@+AcEjVUlb?jq6MleW=H)17##A{5)wMBud>46=Pa(18cC;JyV^-I6P@43q~SJ?$QkZ%=&YjCxfpNE(yi+(1mWt*k-rmLKvP;=QU-)8 zlhf85ieyn_Snr&AVaAkakS&9gDO?bD4o?2T;-Kz_{LP#@XEzDJ*QJ)g9hl)MyJn(~ zN}&xB2U3djl*p+z-c_SDBRnG9;Hg&9Um8D!e;hSmJlZ*2i8I`635&#slb*NQt%80ZwGQ3Uf{xr#2mHGMv1XO zxf-QSo&?wuk|2WA$t1i=K7|d7!C2wra~+WkRbamidw!Alo|QrFz2=vSx}&5B=&dvqpO+Zi zM(qI3xur`baU$jCN4cARsly4&)J?@}1M&i>0A|aY62X$sbE<5(8^s-g*w@k9E1OzD!Rgtu`n1tJJ!ODFuY>-Uyuo@Lrr^+r>LjXhmxYGwsxhek?K0Dl!qo4!T` z-ne|o_CpYFoL>VTC&C!i7;D!2M*eHyXwOJyNt?BR#%&aO4^*E*J_Z!+q8 zuGCd9WLz=RDXV8!ODmp!ky3I3AfPofuLmV1s@AAuACdv`hN zbaGj(tAk?4;?%`NskFzb$@ER$;@S>_3`2N1_L%b7fmt?8hj6F5kSN{81G!T9#KGv@ z&L}=gl20NDi_d@t!IpSHvfo}xQnNo^M3FwyEFVhoGBZ!(^0|{-$qTY5QrBipb~|0fS;zzJAHrl!`biEe+P|5D540}BfMq; z_`sIqwF~uZ{{F0za3yzwWCuhwvL*)MQ5bGi$*b~^T2ez}j$02c%SZ`}hcQ2LCNJBA zuRZ8e41-lTs9psmQOmOf9mTh^h z#r1Cy@*48+so(>!$<}8Y*xod}nM;$|$`a2hX4;FQ?u|zy^1@VA zQq4KfLNc)?O8%(M<#{UGp>}n+-8t!czuj4ht7C;7{MJ{|6>an=+_vUAT`Kz76m-z) zeCO(>GczPw5Mu@`H%4O&HI`FL6SE7oIXEyM8m&&8K3CJ6AzY(zanIBO3T4Cj(*`NO4i4M7J2ZRvfUv4}#TGa~Lp`^IhPRf6l!`n>>};n$_Pf5OB8)X= zK=X7jwFb^W#_1T3AT4j_OXRI;zXEq%w0pkVg>!Q*uav>5Oyb_XxVu-QW#RN}yy6FR zJyM|S9(ZL>wTmM%0VgWu5d!+qjxf9^XjBnh#y-sU@t6ae>#Ox|ERdHasnx>(IO-NH9fKTm^ zM{nUvNE}6q3Klgd<-iN7RYB_KtFuR&D_GjoE-}85tm$r}NgdzacAP9UJU5Kh=26kM zwF+f)L3ylAf7hx#bwuEwQjxQ+Dz>MPa=lb@1=DFBrEA2-*rN}d3tbBY4 z5|DQ;(kNQrRnmRGwzB-3(0hO+oXBkDp545WSCG_y4*@wK+j0+UVwQ+96geS)KABr| zMrM{eJ_~{_*YK@w)82QnNi24*63r#C2kQ+e%r>@&50nRQdk&}y&Zna_kQQzzXy<(^ zYPj}+=Ri>x8lp)E{DuG}ymHh3b*tw2N7m21wXvtuU0zu)F4w4^oLpS(?Ck8WSI;9+ zWJNy#yJXhWe|Ym|rlpv4eDC7Hn1EbB? zAWWW5UBqIf6fW-EMNG;N83#X#nHjZamqn%vFi_O!M>sd%^>efiOUQ{M$>O$EyIgh2 zf3+*}qVp`Y9I7pxP9>?2y~0STT&o2z1CnA92H&reU*jclAkVfhqW2ouDxMB!sQgke zE&_**{YhYz7!bVEYL9;i7d}<-QfLau8>O#WDg@GO;34f8?3CtrU(_AiG1(Li0Au^vLzs5c&-b;VU`sk3CKw zM^J4`V(8d*>#KJMUrq576a?3Bg-(>nnb3b$5sFF0Y@gZgF+iC^i(&a356z~)7aaLc zdN6M8`5l2lay0~TtDOSppgER7q_pV(BF{<(LIor=r>RK>!(ttYamxBw-ceqg6eAZ; zBat6eltz`3{6WbZCHO;Fv^Fd_cPFn)bGvD4b*uWx@Kx7HOjo{@og^=An;5;G#^?uv zMwzG78)HaP)6d}y05lWOY0>$#qAo8+qX2P5ErIlIAWbsY3|zzs7SOH>Cs7$ds^u;_ zHJ7~bEyWB;as2t^sS1iaf#-}bbh<{{m{&A1k)2^ndnSR4iC?$Ta@(MozbWL0RL?;U zGs_;LB@3kcLx9A|JfdF@cB%uu@lt8~jKFv;IU8>Zew;3(6%*VieTCMMhA1!7$IdYb z(y<8&1s?jA=()6s`*K}EWPx?bT)Wiw()*nsH1dpH(PkWWtkrX-Kdq$<;8S-h3+Ru8 z_jT=o(tuMX+9kc1aW80>)nn=wFf2w?N$-5XgCT-#Rxc!^p zSre9Qq96+<{ObaFYfm4H9=`-sIixA5h+SXy)vrP*1F0gK)W)YX*pe;~nm!-9Om?}c z?*`!nw(?j{3e2AQ*`iwP0#Oizj3;nH%MFo)g(5TJ`NEP7Ut`=fPN~)kQz@Df-KH%CR~Yn~3uIH55^+KL}8tUroz#oAn!m&4wEqs}F+Zlv+uNc~cL`;`G>M zBlvnCFo_~9Iv+*D7BXlhVR^z0}U-I(Nht_@dic5^U_G${Yo|hh;Sx-v>%$PEp(OUTl z-eEVee&P}bu@=9L_c-SN9BPJx{zgu+)p+{myso)b3L$N98v-?NNe!GlR10{c_U;XF zBZkFdE=^$8j-fVB63AET_W*@Usg}ksKkei5s4AVhPrm2dv6ua>6CEQ zx{vzZuwk&)oh%Zb9#qje*XA}98325(net|r?pNisp0_Oln`EPLbx2c%aHv>`W9l3b z+W7_q>trNbQA09aS_8a6#55TM&p5P;;TXSZJ7Y+r*~B!DRQX1$8d)=AR7wYJI_S%e z;dXS{5N}@ZheTNsfma2r!=v6wlr>@n4*_z-FNBdp;-O1~Qm?&%cv3-yaWEEU$xo|~ zC%~erBc|V?V<3Rl4uPT{{PEUSPIhh7FgDbaH|w(Ak@Tu_)mt4HnD`4)k8jOgH^T>pM2?ikq|Fv8wmo;?kp2H%H+o>G+T6JHNHb*g3u~_XCw(0 zcXxD;_Fa~}9|8f{RvRgH#;SP)G%=NQY*hep!VXy!G^j*h33SNNiZMX=#*(+onpq8j z4S-*B$9CHlp*STBzwt@7%g3y6oyc`km&;Lv(}&MKQl>dWLSi7;zuJW*+8h+COP&_sA~9yL;;c9;kyXRF$Q`G^?tK`DFO&`SLK8S zkNhqr?4uml1EmyngpWrfhyd*J7_yh=sGK!w0sHymquTjP7p3qh$riVy_Qa9zt3Qdg zp~Q88$wDae_dl>GEEm4;t)CBj&1r0PzR>LCEp3ZS!~#}>468GJavyHmtZ;jI(VhI+ z)-;k7(C}PhFB=^q@hgUF~feEuF%$MVWKUT@i*=_5*hDR41h2_F=je z0<*o1eUYjx83PrTrnCPzxT z-e!0LuPY1zBixK!o)2Yj?@J7CyX8vjCFX%ySDq)7hDTwZFO!YrZ1dyymr2hF)dwz8 z3}{SQ{U{l&zmwZJanXBYXlFvnbdRW6VV==&>(ve5AvrfOJgu9DJD^%jvEw=;Rz0$2UoRcBLzBxv z{}9NeqDa`8Q@#yXh~+9RBltrg*2#-gp!|uSpRdHVJ{u!QVV#7b zSLa@|1A+?SJVJ#0Om%*adD$AaE- zAm;>+lRgW!rjG_b#&TzeH(}`j7!q7!tE)<@#V+~BeIqXjWQmH zws4Kbnp#e%FCulLDkaj~5_F;X9?bRqRf$MD6`lTibnOpp$vp1UtU9`bu|S0vkPC=h zt1qDtJM)|y#{jiK3c+^>SS#>O(QTpqQ_D{-`-zV^KEd{fbL)70FyW=d+_&cERW%+< z(j0p|pLxdp2KED{F(+~~9O=8NmK}{N_9>r($AD=E%}R1v>!Xk7>Gp^zGk2V0%{}t# z`hlJ(u{J^$KLnlP*YcC~sb7-tqdp}DS9OeF1ds*itzwA@e^6AA2gHS`k^yk7(AJ;9{6wv0oZfSczG4eax~p zvr9p`Hw^n8v<+gGA$Zduz>X`thkBAtj`v#GQQS`x)BtHP&fHNav*8YLFtsk7hgSK> z>2BL@yxg325%bv}5vum_zOjX^?geXFWrn3VI?5F(XporNS1&%C$?xMg~Cy z;y7AfPU@-lYW2H~IY@U8n>%xm|?&l0IKy!Ox^-c??J#XTG>DC}M7kAo@fH2t!iv zcyd@L{CBA2Sy{j>pC-_Vg-EjtkVVq5_DW2jpE&laaPTit_rdybz#iJa1*89@Z@&-` zn$6x$+y~XQu(+mChN)e=6R`>(WFuTCrZS~BlgS?L=%A@Gm5Zu0Tgd-*Bfl8Z!DvU> z!XK=5kkK=Um$OwcKhL1ZKDV;DCHaHhoOzZLzJV;$SvyVxa~D7rW(1^d0(8ZqjG05W zRz4A-39FootTOJi{66T|e6L3u6N~iMZQ56gkN>uCMACsSe5QgFk+&d;Ko-tm4X+Jd z98xZqT~`zL{E+)=byx&@S05e}t;RsAzx3E&I8VtKW?BMrDFbd&6z_{TS2YR;m0&`o zcJo(Wx93tIiL76`=o)(M?F6x*S)(%xaRxmllm#+N3fio#kK8La_-K>{>X=p_+D8B& zD7!-)`>x*sCV0|?ltu`stPl|>X+lJ$T`c;~+0Z;{UN;zg*O2lZ>C(I-fOXY^XlAUD zPAvij^hAl{S}{$AAt|)bUB1?c<(LO=gvcY#Cp{BPtmokz&3q8WF!E9hh;irgAO-4D z0gGG9B^4~j3na<*4qBFCh7wUq&PS+@ledFG^77Z@TGZ-iQ*w9z43A=|>hLm&x3-ST zlCF=?9Ab8i9Ej)lRmgP+7E8eb+DI|_@cerq)+8921fN2iw$jbc+M0tJ*UV%H6^dAT zLFALn{>RBVgDJV)JI`xa+yaSAG5Eqr2IPr)|QlzTpm`i*W)& z5DOTp!R;y3Xz%(6RU&QyEkh$ASq9A<`}G`$8(Uf@vHKh&gVd1C!XX0kTDe%nO!q*2 zk}@3TN})`*N&_S~hGB++^5l9m=nqYlZTxw{$9rh0kW%Y+uxVl`2M~ojZRXc{GBW|6 zO~cnS+PQwZTyGiRaJaiW zy{85VnRKJoS-e7v826hm4Xju?=d0_HV_#lnq}VD~Uq-JPO5g3X%nxg=6dLoF$6)vk zFW^o)P1*B^6Iw9BO+tUN!`ZkiMNtCVxK4!$aHw8mXI%%z{v^7yI?{U3EfXwJEZrP! z#!8zmE6#M6B!%cxzKh6#c2mJlXLXkAT~cHAJeIV)5Luknw6uSgR*^d)@)M4#V~Mh3 zX>iNPUWjq0@N_-C&oHt4OeTG(nh}drKF|%aZPs4@3zjqb6H5#+F~73va`kG%*Y~Bh z3JaU$HrDxGr%10bd#SM5eJ#l+RS{m-kv6Q#Z_7oburf9+vIw$EEvC?tJAp_Tdb>dg z9JJN@UXr(^)ty*`l4q-Nk)T9p%*mCFh%EM#^`I-UdT>mbY5lmI3h;DZakLx+Qp~AEH>J7!l8st%;6+X-8P)gH+@)H2P?5vx zJee&%^7)4?cWbtT)X`>iS{lc$QgLyUz?}i9WVm3cjivDJus(N@&RKEBmpX{x(%9Y- z$lw+2ba1IS-|)aIYC7;xz-cUZ-e=BMyKuFaX+bR_{N}Yp{9|MDlf4pH7F=F(6eYq| zY}4p0lbM?^$i|nYg4C$+Q1mNq1>^5VdivWuy2&k@$0adEmiG)ucW`Hv z8tA1@SPDz>g(`MsNOYaqmxCo-M2++xH)jv_N5=T^@*Rs5%(J%&QX7L6S$6f^TOwQ0 zi`9wCKSt=7dco)rSK^s3xEflfq>f&5C5(JYYQ**bS*w;f0dK@6OQLll)tPx)p^h5f z;?LV&)nfIOI@4ICK1Y)kLG5C03v2NxOB0u{v%th=Lf{blv$2+|g56^}2rLY_TUYxu zoB=A?+e}hIU|@d3EzP^j<)DDu05KQw5Wzq2Mq*7ZfR>lkn$L!n2eL%23O?xRc_L`Z z&ipg0d5Qqo=&n;*zoX@sR;h!-l|8f10k#et4Uoc8=O*Iq*@~Q`r^XW_+JOSN8MDIV zm+o99YrcXc)_kxPUmS_jwuoDWM9*DzA}PzKz>G8V9CwSfSu%`v=B6=U&~SzVJ7ieU zEkU#gLI!=+VbaA-PZLP?@=Y^{BvkF)Uz#_nXfDJ!x5*|uOyGpfw>XHHLF+f_?CTOU z+5+zDEe`4lln;l4CD7jhHV=#}7#Ws>aufu|IKjeBhCS%(FEDQQ3@q($z*+jiQ zkH}_`?HTAY(1w>odE3u9vcJIMTA>d0HVe{O5;jdhtBGm3Y`VJ2MG79Vk~ocl@rsK; ziAOCev9VBn-u69wl zrcaauZIc&hlYFL!UW4oT72LqoXWxZ+S-J?_ITm6QxfP$Z>t!Lw_RMUWA2-xTWrXa< zWlY^R3F1OPkv$=5a4I4sGY0^Y5;&fVM^rZ}++rh^+pe{>8%S)rO;gze%8Fc9WkEx; zFYp)d*IT!*S~Rt0;cTel5?MGLp67Xdpj3D=(<4Y`QU@fMSa9G=d1_w{Zd@xboX=r6MUP-=3wCY(uN|G7Ks zD>#`gZm|!uAnTv4J#iVmZB=ivqmslM=?ALT6+O&KyEZaAoKA zD1Uwi|9=M87T;>oXwRxqahX{yaYNE#ycIp--rFV$Ihxl=iYJoo)!5 zJlU7tc^voAhK^p}AIE+V_h#B`cWe=Yw zI?s!+Wdqf@pRWfTWu2B;awlGiM~LJLK1xWl)3hCld>E&CDT9MpGzHFR6Sb?f4!Ut{ zR*=eq8${A#BxLZ}ya^He@?{rI(?(uJ?w6PI4VUI)pUGqUWVg>U2ZmB$Z(ffs83$c) zjq+XzZ*~N9NWtFc!&*TNU>>n2=Jro-Cj~)d-qkZQcnWl6w-&Mv7qT`N;BQaBADLeZ z*?ML!FG<^;NfsCyifY`hp8MLeWP*Zr)Rnc38(&{{=SG6+wzfWJ6e?SdKHNKDDN`71 zU1E)Lk#`qTIka6?MLX$kPoXIxm1N0i!@yU~)G#UJ>s(JBm6l)TYxYRA!x3syLEV2| zT_gFVkWgCpP_@w!pmz|auFht_?(Th!Bsmj8!|D2R-PguQE)yoMy#F01_AC%FScGNM zE>aTk#+9g|5XEoaXv{q~`ZQp0Vs&@3?;0n%Xz+bj~Y1=T5d&+WZ zD6&IWkLA;=!%^!VQN+!(a&Mvl1{YMuJVunj{002d!Aw;c95+=7w~J-$Jxw7_u+|(E zQ&7`zUb0NzOzt(qIv%qPd2(=oiOiVIwJw`c%gNU*ZD+l7 zZ8fy-F9&^NZxWl)dI6fWB7S$^~@?? zxug_a)d3n?L znug)qoV~TLOBU~l`mOP(M>CP^)Q+_`IZvc5$5Y@e3o0*%Yg%I8Wc3`pgSp4s zhvuomKcaILyJ6<1AxEKjsf)d?P6y5>9YjEO`-5v?5E;*W;9 zb9nI~pnM_b<;K8AO73T@K0}VcV|sFQ9DCR$u?5drYgSnf%Z=AXZKJa^0aSClwbNQ5 z$d;LHG=2Z{{fZ;fQji5^g$&<7b#GVm)f$`5@ne8%PytUkFkt)51e_gLJthZJ-|mwB zcjWn8PwT_I2P8?UcXWc zul3M!lNa837hLxmyAOc3Lm7nG+Z9-P(A7=`4xl*dQ$}*6M2HV?RD4-M8*yZBPHKG( zaQlIp!KP=!)K=p}Gb^aUW1gVCF30+A-o8;lkTUhe$U7N#?nmS8FDDBwb43tKoQsj+ zK=DCzQE0|ShE63~s(su1cqW)|YEe67tmMU@)vV5eKTGs zcC}p#-)Ixx3P=6tfaoWO_-iUt*n)|H0XwO9**w~ady?`9bXKJ6FdQ7@=@d+23=0rX z+!9!kI=oiZ|vZdb3ovjXL{?rNG&44)b5vu68NH}HB%Q+0D zL(b79w9+-uQZ&?=sJfXVHo^lMS2=1-d6Pwq)4NY&hi#7lK6+|60=(+L)5}m~ucf-5 z8TC7r{m1(q->KxpYgzitco>>jgqT9=$G5 z{UPRU+q81p8t-UM>eiU+{i2dB@aH4(e zEYbL#0o#fEi#D@}a`!xXs=E97!}!?CIq6rt+bK(F5QH89EOe%vs^s-3aX%5&)w|{L9W1SIOqa zJ|JIa^xW1|&+BDyK|K;}qRkZHxM}@+q7in`=yFvrt=rhj%Jk#bgtawQ2aN1tnnWjT zmDItaiJoqY^a?(S$`74Ukkg2fq|tFM*C&0V%d2;=HedR{l?(OVHeyMpOt}*m#U?r) z!DEo2IqfjHQ?t-W25mdX26Ri3Z;TxZR@P+8Cs+6L_J*0wG6CHdQWLSg#`VyKFM_05 zA?wO~21OP92?-1tOZ@XY+_l~)c!m6^ILgEsM~#@Z_VJHo&EGI@IJCNJze%5) zJka{UhZ3&m&>I?>-&XodGLxxL_aU`_RtYD$oB+B4ia+>5`z`zs_F59($`XRQEP^92 z2!btmv9ASwmXt^w9X~|@+ug?Hw`*v6AYE@i`g(JkYJObqPDH`f^7uGpQXbSZgc3FD$v z2>L>Yx7}yvETUMjbwt1`VjX>iR{b!cGy02VQyHTho77N^%ZN`hM~`GW1(xSrxyksd>fb^`2^svBfOV7c4CO7+?R?a8En^9Qqnl)-@VTneO9*b9V}dJc18UGjjcdjj zli`qLbYkm0l?TWvt_Z;)bAybRw5&HOMii6}x6U}F7ymdVU_5AQRK&)$JbC%E6>Kz6 zSndv=J@jZ$9_9hY=&szv@(XX9tY`mhrtAKio8yom_&&j5JO`2T1C^b><)HTas^0~f z33W_-uS9ZyPs3Lc_^_=`J7HUIaebiCSGafQh$T9{Mqh9C0&QQ-qyX~xqTDI6o~CbV zt^Nbg24DllyF1DC@h^n{;$}(&CB&PJ&!B_ zu6z|w3Oda)$M+-K9RzXKwxxC>8dkP^u(oEr0c|alY;6xbTIiD0Y~9T|57`dMrvh!; zz677{x+Fhvif6GR$NCuyn?w37ETfz%67&(I*g@SU6xumzUTxXNrrU1a=%L&&J7!7G zjXu~_vj<-5NBOpZCIbw2i#sqVO}9!ei%2=ZG{5Y!#TFs(6TV6&Kzxx4Of^xgmXg(? zivEhw7hFG~0YFp}QZTCRTxO-4ntY}r6REF>$y)OnJWrkeG=5*R)3#l2&Fo^FiW>Zo zX@UyZLJHRIEioO-?N)3Ia2-UBBqPfUt8@qHTd<`Lasi`>!W_fSdQ=T#IuOOW7b_I95t*r`XJyjXO9qzliUFeh$4>Le7c29gUDYKQW=PKcPXM{Bj2BNKycG8&` zTkF1br!*%MpccewYj@4LZLNaf!mVdIVOUpXXFkEc%$o!`NhqD-Q=sAQxLS);6{Si_V< zNJF#o_iTIdT-qDyC&K_R_)c3HJX46*2C_28If2oXkqpdfuC-b0b*feEoTyFmJz{N5 zWN$@t+mu7b`-+jab_UPsC5p|d9k9;bqJoTqw|96mowaeZhXE2!piS%&ES)X1{cKA`M= zX$o1_JXO%^y?KM>Ve)JkE=uX0E~R=Z(OMX|AyLkvI4sP8mG_>^gPsc==H+rql7(Tl z$ww-KhI5#87;4aqwWja#u_%*tPX)0;g*GuGcey;>Iuyzhdwl4cpu>e}%6iCv)~r4! zF-%UUVHzIqa9$}9W_%DO4ahE9pv+y?Uk&~ctpXrvbBN_GT-(g3pno!!-+nRg(+N0C zlbH*db1y|wC9trKKp9_h>*)sFw;id9p^JSY6hsSor(UXcP!}mZcX6Ym1335j8 zA5t84hPw@hN$^gn_k399yZNvQQ>O238}qxk!?kzq(KLdr>A22!T&;9dpTTK{ZLi0sk~dsgB-j3die2#Ns_BHey6D(z6~r_T>G8E0Zbkp0SjN)G^7?X z18-7?IvYgWxEdKGiE~uSxM{I+(29wB8|8MCv2f?-ks%oDL4BtmokC07pA!q5b9tS@ z&hhfr@o+!~kd@^8t#B*tRz;PdF=MXV5om1fnl}OG-SWsv3^`Y z=%Yq3lC5K91H$AxXvt1mPGFjwhJ;DW=yZH70?hUc4p`7vN0~oFD#(gvW1Q6X?+I7W z&W@A-7UEp`y4FD0(58OAB6D+Uwe<5N#!5$f@)8qF{34A82!sm^1@Oz)FXQz8cJb>A zBmnxaR|o)a{J&iOHjbQ5SqT&X_}?f){odR!DlxzQ{olSJ{=uB!@6Fj*I2xN;+5g?_ zO`NB!qYE?uAjsi|bk*NpesA_)?-KnFW+VTdSsPOWJ$t?Xa?}6R+Wx(?4dFkm0|3)xe#QSq!{=tsF!~R1t;6KIhpN#x-=JS*MIp+Vy z`~c5IA+~+kZvh`H%qIU==J!zjInKZO_KQf}hhL@NN)-QXz4)hJAk~JSXg^{p5Alo2 z@o!ZP0N~B1l=aW?e$Cupb?@KP5aSg|IS1Y-4$Z`4~Z4j4~Z4}KdfO^;s4;yKhpIp@c+ogrKz{!sgKnb|G^XL zKcG&D{x7J%vgE(i<6qWyE0mA8KpOyny#z1-<{uCtq<)9^n_s_ba{Oxle{6;bf1pJs zIN(2ftAoi`%dh`Gdg0-}vHGhV+h5|^FA9=wWJq%HA9*iC{nspTK>Xi({>}PtA)@{D z7qkZUe_yM=2ul8!wJMO7cl+?MR_Q+&PWF!|{n8bgVE-KPS0EZoJsVmZE91WvhQE;V zKgyr~z6FOP|97yz*q{Dc)Bh+v`+GQV%s+?wKhgZ_E%^V6fc_rT4Cj9U{gvl`A%nl~ zBERixKDIR<85|(^bHLv+_*cvAKco6b38>#YC{6x5ynhHn{r6t@OEvhTCeQD!B2oR$ h>Tk*U7locb!vOu*2LXI2{9prEeblwopkMZT{}1qN)$;%V diff --git a/galleria/LICENSE b/galleria/LICENSE deleted file mode 100644 index beac466..0000000 --- a/galleria/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License - -Copyright (c) 2016 worse is better UG http://wib.io - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/galleria/galleria-1.4.7.js b/galleria/galleria-1.4.7.js deleted file mode 100644 index 4fccedd..0000000 --- a/galleria/galleria-1.4.7.js +++ /dev/null @@ -1,6919 +0,0 @@ -/** - * Galleria v1.4.7 2016-09-17 - * http://galleria.io - * - * Copyright (c) 2010 - 2016 worse is better UG - * Licensed under the MIT license - * https://raw.github.com/worseisbetter/galleria/master/LICENSE - * - */ - -(function( $, window, Galleria, undef ) { - -/*global jQuery, navigator, Image, module, define */ - -// some references -var doc = window.document, - $doc = $( doc ), - $win = $( window ), - -// native prototypes - protoArray = Array.prototype, - -// internal constants - VERSION = 1.47, - DEBUG = true, - TIMEOUT = 30000, - DUMMY = false, - NAV = navigator.userAgent.toLowerCase(), - HASH = window.location.hash.replace(/#\//, ''), - PROT = window.location.protocol == "file:" ? "http:" : window.location.protocol, - M = Math, - F = function(){}, - FALSE = function() { return false; }, - IE = (function() { - - var v = 3, - div = doc.createElement( 'div' ), - all = div.getElementsByTagName( 'i' ); - - do { - div.innerHTML = ''; - } while ( all[0] ); - - return v > 4 ? v : doc.documentMode || undef; - - }() ), - DOM = function() { - return { - html: doc.documentElement, - body: doc.body, - head: doc.getElementsByTagName('head')[0], - title: doc.title - }; - }, - IFRAME = window.parent !== window.self, - - // list of Galleria events - _eventlist = 'data ready thumbnail loadstart loadfinish image play pause progress ' + - 'fullscreen_enter fullscreen_exit idle_enter idle_exit rescale ' + - 'lightbox_open lightbox_close lightbox_image', - - _events = (function() { - - var evs = []; - - $.each( _eventlist.split(' '), function( i, ev ) { - evs.push( ev ); - - // legacy events - if ( /_/.test( ev ) ) { - evs.push( ev.replace( /_/g, '' ) ); - } - }); - - return evs; - - }()), - - // legacy options - // allows the old my_setting syntax and converts it to camel case - - _legacyOptions = function( options ) { - - var n; - - if ( typeof options !== 'object' ) { - - // return whatever it was... - return options; - } - - $.each( options, function( key, value ) { - if ( /^[a-z]+_/.test( key ) ) { - n = ''; - $.each( key.split('_'), function( i, k ) { - n += i > 0 ? k.substr( 0, 1 ).toUpperCase() + k.substr( 1 ) : k; - }); - options[ n ] = value; - delete options[ key ]; - } - }); - - return options; - }, - - _patchEvent = function( type ) { - - // allow 'image' instead of Galleria.IMAGE - if ( $.inArray( type, _events ) > -1 ) { - return Galleria[ type.toUpperCase() ]; - } - - return type; - }, - - // video providers - _video = { - youtube: { - reg: /https?:\/\/(?:[a-zA_Z]{2,3}.)?(?:youtube\.com\/watch\?)((?:[\w\d\-\_\=]+&(?:amp;)?)*v(?:<[A-Z]+>)?=([0-9a-zA-Z\-\_]+))/i, - embed: function() { - return PROT + '//www.youtube.com/embed/' + this.id; - }, - get_thumb: function( data ) { - return PROT + '//img.youtube.com/vi/'+this.id+'/default.jpg'; - }, - get_image: function( data ) { - return PROT + '//img.youtube.com/vi/'+this.id+'/hqdefault.jpg'; } - }, - vimeo: { - reg: /https?:\/\/(?:www\.)?(vimeo\.com)\/(?:hd#)?([0-9]+)/i, - embed: function() { - return PROT + '//player.vimeo.com/video/' + this.id; - }, - getUrl: function() { - return PROT + '//vimeo.com/api/v2/video/' + this.id + '.json?callback=?'; - }, - get_thumb: function( data ) { - return data[0].thumbnail_medium; - }, - get_image: function( data ) { - return data[0].thumbnail_large; - } - }, - dailymotion: { - reg: /https?:\/\/(?:www\.)?(dailymotion\.com)\/video\/([^_]+)/, - embed: function() { - return PROT + '//www.dailymotion.com/embed/video/' + this.id; - }, - getUrl: function() { - return 'https://api.dailymotion.com/video/' + this.id + '?fields=thumbnail_240_url,thumbnail_720_url&callback=?'; - }, - get_thumb: function( data ) { - return data.thumbnail_240_url; - }, - get_image: function( data ) { - return data.thumbnail_720_url; - } - }, - _inst: [] - }, - Video = function( type, id ) { - - for( var i=0; i<_video._inst.length; i++ ) { - if ( _video._inst[i].id === id && _video._inst[i].type == type ) { - return _video._inst[i]; - } - } - - this.type = type; - this.id = id; - this.readys = []; - - _video._inst.push(this); - - var self = this; - - $.extend( this, _video[type] ); - - _videoThumbs = function(data) { - self.data = data; - $.each( self.readys, function( i, fn ) { - fn( self.data ); - }); - self.readys = []; - }; - - if ( this.hasOwnProperty('getUrl') ) { - $.getJSON( this.getUrl(), _videoThumbs); - } else { - window.setTimeout(_videoThumbs, 400); - } - - this.getMedia = function( type, callback, fail ) { - fail = fail || F; - var self = this; - var success = function( data ) { - callback( self['get_'+type]( data ) ); - }; - try { - if ( self.data ) { - success( self.data ); - } else { - self.readys.push( success ); - } - } catch(e) { - fail(); - } - }; - }, - - // utility for testing the video URL and getting the video ID - _videoTest = function( url ) { - var match; - for ( var v in _video ) { - match = url && _video[v].reg && url.match( _video[v].reg ); - if( match && match.length ) { - return { - id: match[2], - provider: v - }; - } - } - return false; - }, - - // native fullscreen handler - _nativeFullscreen = { - - support: (function() { - var html = DOM().html; - return !IFRAME && ( html.requestFullscreen || html.msRequestFullscreen || html.mozRequestFullScreen || html.webkitRequestFullScreen ); - }()), - - callback: F, - - enter: function( instance, callback, elem ) { - - this.instance = instance; - - this.callback = callback || F; - - elem = elem || DOM().html; - if ( elem.requestFullscreen ) { - elem.requestFullscreen(); - } - else if ( elem.msRequestFullscreen ) { - elem.msRequestFullscreen(); - } - else if ( elem.mozRequestFullScreen ) { - elem.mozRequestFullScreen(); - } - else if ( elem.webkitRequestFullScreen ) { - elem.webkitRequestFullScreen(); - } - }, - - exit: function( callback ) { - - this.callback = callback || F; - - if ( doc.exitFullscreen ) { - doc.exitFullscreen(); - } - else if ( doc.msExitFullscreen ) { - doc.msExitFullscreen(); - } - else if ( doc.mozCancelFullScreen ) { - doc.mozCancelFullScreen(); - } - else if ( doc.webkitCancelFullScreen ) { - doc.webkitCancelFullScreen(); - } - }, - - instance: null, - - listen: function() { - - if ( !this.support ) { - return; - } - - var handler = function() { - - if ( !_nativeFullscreen.instance ) { - return; - } - var fs = _nativeFullscreen.instance._fullscreen; - - if ( doc.fullscreen || doc.mozFullScreen || doc.webkitIsFullScreen || ( doc.msFullscreenElement && doc.msFullscreenElement !== null ) ) { - fs._enter( _nativeFullscreen.callback ); - } else { - fs._exit( _nativeFullscreen.callback ); - } - }; - doc.addEventListener( 'fullscreenchange', handler, false ); - doc.addEventListener( 'MSFullscreenChange', handler, false ); - doc.addEventListener( 'mozfullscreenchange', handler, false ); - doc.addEventListener( 'webkitfullscreenchange', handler, false ); - } - }, - - // the internal gallery holder - _galleries = [], - - // the internal instance holder - _instances = [], - - // flag for errors - _hasError = false, - - // canvas holder - _canvas = false, - - // instance pool, holds the galleries until themeLoad is triggered - _pool = [], - - // Run galleries from theme trigger - _loadedThemes = [], - _themeLoad = function( theme ) { - - _loadedThemes.push(theme); - - // run the instances we have in the pool - // and apply the last theme if not specified - $.each( _pool, function( i, instance ) { - if ( instance._options.theme == theme.name || (!instance._initialized && !instance._options.theme) ) { - instance.theme = theme; - instance._init.call( instance ); - } - }); - }, - - // the Utils singleton - Utils = (function() { - - return { - - // legacy support for clearTimer - clearTimer: function( id ) { - $.each( Galleria.get(), function() { - this.clearTimer( id ); - }); - }, - - // legacy support for addTimer - addTimer: function( id ) { - $.each( Galleria.get(), function() { - this.addTimer( id ); - }); - }, - - array : function( obj ) { - return protoArray.slice.call(obj, 0); - }, - - create : function( className, nodeName ) { - nodeName = nodeName || 'div'; - var elem = doc.createElement( nodeName ); - elem.className = className; - return elem; - }, - - removeFromArray : function( arr, elem ) { - $.each(arr, function(i, el) { - if ( el == elem ) { - arr.splice(i, 1); - return false; - } - }); - return arr; - }, - - getScriptPath : function( src ) { - - // the currently executing script is always the last - src = src || $('script:last').attr('src'); - var slices = src.split('/'); - - if (slices.length == 1) { - return ''; - } - - slices.pop(); - - return slices.join('/') + '/'; - }, - - // CSS3 transitions, added in 1.2.4 - animate : (function() { - - // detect transition - var transition = (function( style ) { - var props = 'transition WebkitTransition MozTransition OTransition'.split(' '), - i; - - // disable css3 animations in opera until stable - if ( window.opera ) { - return false; - } - - for ( i = 0; props[i]; i++ ) { - if ( typeof style[ props[ i ] ] !== 'undefined' ) { - return props[ i ]; - } - } - return false; - }(( doc.body || doc.documentElement).style )); - - // map transitionend event - var endEvent = { - MozTransition: 'transitionend', - OTransition: 'oTransitionEnd', - WebkitTransition: 'webkitTransitionEnd', - transition: 'transitionend' - }[ transition ]; - - // map bezier easing conversions - var easings = { - _default: [0.25, 0.1, 0.25, 1], - galleria: [0.645, 0.045, 0.355, 1], - galleriaIn: [0.55, 0.085, 0.68, 0.53], - galleriaOut: [0.25, 0.46, 0.45, 0.94], - ease: [0.25, 0, 0.25, 1], - linear: [0.25, 0.25, 0.75, 0.75], - 'ease-in': [0.42, 0, 1, 1], - 'ease-out': [0, 0, 0.58, 1], - 'ease-in-out': [0.42, 0, 0.58, 1] - }; - - // function for setting transition css for all browsers - var setStyle = function( elem, value, suffix ) { - var css = {}; - suffix = suffix || 'transition'; - $.each( 'webkit moz ms o'.split(' '), function() { - css[ '-' + this + '-' + suffix ] = value; - }); - elem.css( css ); - }; - - // clear styles - var clearStyle = function( elem ) { - setStyle( elem, 'none', 'transition' ); - if ( Galleria.WEBKIT && Galleria.TOUCH ) { - setStyle( elem, 'translate3d(0,0,0)', 'transform' ); - if ( elem.data('revert') ) { - elem.css( elem.data('revert') ); - elem.data('revert', null); - } - } - }; - - // various variables - var change, strings, easing, syntax, revert, form, css; - - // the actual animation method - return function( elem, to, options ) { - - // extend defaults - options = $.extend({ - duration: 400, - complete: F, - stop: false - }, options); - - // cache jQuery instance - elem = $( elem ); - - if ( !options.duration ) { - elem.css( to ); - options.complete.call( elem[0] ); - return; - } - - // fallback to jQuery's animate if transition is not supported - if ( !transition ) { - elem.animate(to, options); - return; - } - - // stop - if ( options.stop ) { - // clear the animation - elem.off( endEvent ); - clearStyle( elem ); - } - - // see if there is a change - change = false; - $.each( to, function( key, val ) { - css = elem.css( key ); - if ( Utils.parseValue( css ) != Utils.parseValue( val ) ) { - change = true; - } - // also add computed styles for FF - elem.css( key, css ); - }); - if ( !change ) { - window.setTimeout( function() { - options.complete.call( elem[0] ); - }, options.duration ); - return; - } - - // the css strings to be applied - strings = []; - - // the easing bezier - easing = options.easing in easings ? easings[ options.easing ] : easings._default; - - // the syntax - syntax = ' ' + options.duration + 'ms' + ' cubic-bezier(' + easing.join(',') + ')'; - - // add a tiny timeout so that the browsers catches any css changes before animating - window.setTimeout( (function(elem, endEvent, to, syntax) { - return function() { - - // attach the end event - elem.one(endEvent, (function( elem ) { - return function() { - - // clear the animation - clearStyle(elem); - - // run the complete method - options.complete.call(elem[0]); - }; - }( elem ))); - - // do the webkit translate3d for better performance on iOS - if( Galleria.WEBKIT && Galleria.TOUCH ) { - - revert = {}; - form = [0,0,0]; - - $.each( ['left', 'top'], function(i, m) { - if ( m in to ) { - form[ i ] = ( Utils.parseValue( to[ m ] ) - Utils.parseValue(elem.css( m )) ) + 'px'; - revert[ m ] = to[ m ]; - delete to[ m ]; - } - }); - - if ( form[0] || form[1]) { - - elem.data('revert', revert); - - strings.push('-webkit-transform' + syntax); - - // 3d animate - setStyle( elem, 'translate3d(' + form.join(',') + ')', 'transform'); - } - } - - // push the animation props - $.each(to, function( p, val ) { - strings.push(p + syntax); - }); - - // set the animation styles - setStyle( elem, strings.join(',') ); - - // animate - elem.css( to ); - - }; - }(elem, endEvent, to, syntax)), 2); - }; - }()), - - removeAlpha : function( elem ) { - if ( elem instanceof jQuery ) { - elem = elem[0]; - } - if ( IE < 9 && elem ) { - - var style = elem.style, - currentStyle = elem.currentStyle, - filter = currentStyle && currentStyle.filter || style.filter || ""; - - if ( /alpha/.test( filter ) ) { - style.filter = filter.replace( /alpha\([^)]*\)/i, '' ); - } - } - }, - - forceStyles : function( elem, styles ) { - elem = $(elem); - if ( elem.attr( 'style' ) ) { - elem.data( 'styles', elem.attr( 'style' ) ).removeAttr( 'style' ); - } - elem.css( styles ); - }, - - revertStyles : function() { - $.each( Utils.array( arguments ), function( i, elem ) { - - elem = $( elem ); - elem.removeAttr( 'style' ); - - elem.attr('style',''); // "fixes" webkit bug - - if ( elem.data( 'styles' ) ) { - elem.attr( 'style', elem.data('styles') ).data( 'styles', null ); - } - }); - }, - - moveOut : function( elem ) { - Utils.forceStyles( elem, { - position: 'absolute', - left: -10000 - }); - }, - - moveIn : function() { - Utils.revertStyles.apply( Utils, Utils.array( arguments ) ); - }, - - hide : function( elem, speed, callback ) { - - callback = callback || F; - - var $elem = $(elem); - elem = $elem[0]; - - // save the value if not exist - if (! $elem.data('opacity') ) { - $elem.data('opacity', $elem.css('opacity') ); - } - - // always hide - var style = { opacity: 0 }; - - if (speed) { - - var complete = IE < 9 && elem ? function() { - Utils.removeAlpha( elem ); - elem.style.visibility = 'hidden'; - callback.call( elem ); - } : callback; - - Utils.animate( elem, style, { - duration: speed, - complete: complete, - stop: true - }); - } else { - if ( IE < 9 && elem ) { - Utils.removeAlpha( elem ); - elem.style.visibility = 'hidden'; - } else { - $elem.css( style ); - } - } - }, - - show : function( elem, speed, callback ) { - - callback = callback || F; - - var $elem = $(elem); - elem = $elem[0]; - - // bring back saved opacity - var saved = parseFloat( $elem.data('opacity') ) || 1, - style = { opacity: saved }; - - // animate or toggle - if (speed) { - - if ( IE < 9 ) { - $elem.css('opacity', 0); - elem.style.visibility = 'visible'; - } - - var complete = IE < 9 && elem ? function() { - if ( style.opacity == 1 ) { - Utils.removeAlpha( elem ); - } - callback.call( elem ); - } : callback; - - Utils.animate( elem, style, { - duration: speed, - complete: complete, - stop: true - }); - } else { - if ( IE < 9 && style.opacity == 1 && elem ) { - Utils.removeAlpha( elem ); - elem.style.visibility = 'visible'; - } else { - $elem.css( style ); - } - } - }, - - wait : function(options) { - - Galleria._waiters = Galleria._waiters || []; - - options = $.extend({ - until : FALSE, - success : F, - error : function() { Galleria.raise('Could not complete wait function.'); }, - timeout: 3000 - }, options); - - var start = Utils.timestamp(), - elapsed, - now, - tid, - fn = function() { - now = Utils.timestamp(); - elapsed = now - start; - Utils.removeFromArray( Galleria._waiters, tid ); - if ( options.until( elapsed ) ) { - options.success(); - return false; - } - if (typeof options.timeout == 'number' && now >= start + options.timeout) { - options.error(); - return false; - } - Galleria._waiters.push( tid = window.setTimeout(fn, 10) ); - }; - Galleria._waiters.push( tid = window.setTimeout(fn, 10) ); - }, - - toggleQuality : function( img, force ) { - - if ( ( IE !== 7 && IE !== 8 ) || !img || img.nodeName.toUpperCase() != 'IMG' ) { - return; - } - - if ( typeof force === 'undefined' ) { - force = img.style.msInterpolationMode === 'nearest-neighbor'; - } - - img.style.msInterpolationMode = force ? 'bicubic' : 'nearest-neighbor'; - }, - - insertStyleTag : function( styles, id ) { - - if ( id && $( '#'+id ).length ) { - return; - } - - var style = doc.createElement( 'style' ); - if ( id ) { - style.id = id; - } - - DOM().head.appendChild( style ); - - if ( style.styleSheet ) { // IE - style.styleSheet.cssText = styles; - } else { - var cssText = doc.createTextNode( styles ); - style.appendChild( cssText ); - } - }, - - // a loadscript method that works for local scripts - loadScript: function( url, callback ) { - - var done = false, - script = $('').attr({ - src: url, - async: true - }).get(0); - - // Attach handlers for all browsers - script.onload = script.onreadystatechange = function() { - if ( !done && (!this.readyState || - this.readyState === 'loaded' || this.readyState === 'complete') ) { - - done = true; - - // Handle memory leak in IE - script.onload = script.onreadystatechange = null; - - if (typeof callback === 'function') { - callback.call( this, this ); - } - } - }; - - DOM().head.appendChild( script ); - }, - - // parse anything into a number - parseValue: function( val ) { - if (typeof val === 'number') { - return val; - } else if (typeof val === 'string') { - var arr = val.match(/\-?\d|\./g); - return arr && arr.constructor === Array ? arr.join('')*1 : 0; - } else { - return 0; - } - }, - - // timestamp abstraction - timestamp: function() { - return new Date().getTime(); - }, - - loadCSS : function( href, id, callback ) { - - var link, - length; - - // look for manual css - $('link[rel=stylesheet]').each(function() { - if ( new RegExp( href ).test( this.href ) ) { - link = this; - return false; - } - }); - - if ( typeof id === 'function' ) { - callback = id; - id = undef; - } - - callback = callback || F; // dirty - - // if already present, return - if ( link ) { - callback.call( link, link ); - return link; - } - - // save the length of stylesheets to check against - length = doc.styleSheets.length; - - // check for existing id - if( $( '#' + id ).length ) { - - $( '#' + id ).attr( 'href', href ); - length--; - - } else { - link = $( '' ).attr({ - rel: 'stylesheet', - href: href, - id: id - }).get(0); - - var styles = $('link[rel="stylesheet"], style'); - if ( styles.length ) { - styles.get(0).parentNode.insertBefore( link, styles[0] ); - } else { - DOM().head.appendChild( link ); - } - - if ( IE && length >= 31 ) { - Galleria.raise( 'You have reached the browser stylesheet limit (31)', true ); - return; - } - } - - if ( typeof callback === 'function' ) { - - // First check for dummy element (new in 1.2.8) - var $loader = $('').attr( 'id', 'galleria-loader' ).hide().appendTo( DOM().body ); - - Utils.wait({ - until: function() { - return $loader.height() > 0; - }, - success: function() { - $loader.remove(); - callback.call( link, link ); - }, - error: function() { - $loader.remove(); - - // If failed, tell the dev to download the latest theme - Galleria.raise( 'Theme CSS could not load after 20 sec. ' + ( Galleria.QUIRK ? - 'Your browser is in Quirks Mode, please add a correct doctype.' : - 'Please download the latest theme at http://galleria.io/customer/.' ), true ); - }, - timeout: 5000 - }); - } - return link; - } - }; - }()), - - // play icon - _playIcon = function( container ) { - - var css = '.galleria-videoicon{width:60px;height:60px;position:absolute;top:50%;left:50%;z-index:1;' + - 'margin:-30px 0 0 -30px;cursor:pointer;background:#000;background:rgba(0,0,0,.8);border-radius:3px;-webkit-transition:all 150ms}' + - '.galleria-videoicon i{width:0px;height:0px;border-style:solid;border-width:10px 0 10px 16px;display:block;' + - 'border-color:transparent transparent transparent #ffffff;margin:20px 0 0 22px}.galleria-image:hover .galleria-videoicon{background:#000}'; - - Utils.insertStyleTag( css, 'galleria-videoicon' ); - - return $( Utils.create( 'galleria-videoicon' ) ).html( '' ).appendTo( container ) - .click( function() { $( this ).siblings( 'img' ).mouseup(); }); - }, - - // the transitions holder - _transitions = (function() { - - var _slide = function(params, complete, fade, door) { - - var easing = this.getOptions('easing'), - distance = this.getStageWidth(), - from = { left: distance * ( params.rewind ? -1 : 1 ) }, - to = { left: 0 }; - - if ( fade ) { - from.opacity = 0; - to.opacity = 1; - } else { - from.opacity = 1; - } - - $(params.next).css(from); - - Utils.animate(params.next, to, { - duration: params.speed, - complete: (function( elems ) { - return function() { - complete(); - elems.css({ - left: 0 - }); - }; - }( $( params.next ).add( params.prev ) )), - queue: false, - easing: easing - }); - - if (door) { - params.rewind = !params.rewind; - } - - if (params.prev) { - - from = { left: 0 }; - to = { left: distance * ( params.rewind ? 1 : -1 ) }; - - if ( fade ) { - from.opacity = 1; - to.opacity = 0; - } - - $(params.prev).css(from); - Utils.animate(params.prev, to, { - duration: params.speed, - queue: false, - easing: easing, - complete: function() { - $(this).css('opacity', 0); - } - }); - } - }; - - return { - - active: false, - - init: function( effect, params, complete ) { - if ( _transitions.effects.hasOwnProperty( effect ) ) { - _transitions.effects[ effect ].call( this, params, complete ); - } - }, - - effects: { - - fade: function(params, complete) { - $(params.next).css({ - opacity: 0, - left: 0 - }); - Utils.animate(params.next, { - opacity: 1 - },{ - duration: params.speed, - complete: complete - }); - if (params.prev) { - $(params.prev).css('opacity',1).show(); - Utils.animate(params.prev, { - opacity: 0 - },{ - duration: params.speed - }); - } - }, - - flash: function(params, complete) { - $(params.next).css({ - opacity: 0, - left: 0 - }); - if (params.prev) { - Utils.animate( params.prev, { - opacity: 0 - },{ - duration: params.speed/2, - complete: function() { - Utils.animate( params.next, { - opacity:1 - },{ - duration: params.speed, - complete: complete - }); - } - }); - } else { - Utils.animate( params.next, { - opacity: 1 - },{ - duration: params.speed, - complete: complete - }); - } - }, - - pulse: function(params, complete) { - if (params.prev) { - $(params.prev).hide(); - } - $(params.next).css({ - opacity: 0, - left: 0 - }).show(); - Utils.animate(params.next, { - opacity:1 - },{ - duration: params.speed, - complete: complete - }); - }, - - slide: function(params, complete) { - _slide.apply( this, Utils.array( arguments ) ); - }, - - fadeslide: function(params, complete) { - _slide.apply( this, Utils.array( arguments ).concat( [true] ) ); - }, - - doorslide: function(params, complete) { - _slide.apply( this, Utils.array( arguments ).concat( [false, true] ) ); - } - } - }; - }()); - -// listen to fullscreen -_nativeFullscreen.listen(); - -// create special click:fast event for fast touch interaction -$.event.special['click:fast'] = { - propagate: true, - add: function(handleObj) { - - var getCoords = function(e) { - if ( e.touches && e.touches.length ) { - var touch = e.touches[0]; - return { - x: touch.pageX, - y: touch.pageY - }; - } - }; - - var def = { - touched: false, - touchdown: false, - coords: { x:0, y:0 }, - evObj: {} - }; - - $(this).data({ - clickstate: def, - timer: 0 - }).on('touchstart.fast', function(e) { - window.clearTimeout($(this).data('timer')); - $(this).data('clickstate', { - touched: true, - touchdown: true, - coords: getCoords(e.originalEvent), - evObj: e - }); - }).on('touchmove.fast', function(e) { - var coords = getCoords(e.originalEvent), - state = $(this).data('clickstate'), - distance = Math.max( - Math.abs(state.coords.x - coords.x), - Math.abs(state.coords.y - coords.y) - ); - if ( distance > 6 ) { - $(this).data('clickstate', $.extend(state, { - touchdown: false - })); - } - }).on('touchend.fast', function(e) { - var $this = $(this), - state = $this.data('clickstate'); - if(state.touchdown) { - handleObj.handler.call(this, e); - } - $this.data('timer', window.setTimeout(function() { - $this.data('clickstate', def); - }, 400)); - }).on('click.fast', function(e) { - var state = $(this).data('clickstate'); - if ( state.touched ) { - return false; - } - $(this).data('clickstate', def); - handleObj.handler.call(this, e); - }); - }, - remove: function() { - $(this).off('touchstart.fast touchmove.fast touchend.fast click.fast'); - } -}; - -// trigger resize on orientationchange (IOS7) -$win.on( 'orientationchange', function() { - $(this).resize(); -}); - -/** - The main Galleria class - - @class - @constructor - - @example var gallery = new Galleria(); - - @author http://wib.io - - @requires jQuery - -*/ - -Galleria = function() { - - var self = this; - - // internal options - this._options = {}; - - // flag for controlling play/pause - this._playing = false; - - // internal interval for slideshow - this._playtime = 5000; - - // internal variable for the currently active image - this._active = null; - - // the internal queue, arrayified - this._queue = { length: 0 }; - - // the internal data array - this._data = []; - - // the internal dom collection - this._dom = {}; - - // the internal thumbnails array - this._thumbnails = []; - - // the internal layers array - this._layers = []; - - // internal init flag - this._initialized = false; - - // internal firstrun flag - this._firstrun = false; - - // global stagewidth/height - this._stageWidth = 0; - this._stageHeight = 0; - - // target holder - this._target = undef; - - // bind hashes - this._binds = []; - - // instance id - this._id = parseInt(M.random()*10000, 10); - - // add some elements - var divs = 'container stage images image-nav image-nav-left image-nav-right ' + - 'info info-text info-title info-description ' + - 'thumbnails thumbnails-list thumbnails-container thumb-nav-left thumb-nav-right ' + - 'loader counter tooltip', - spans = 'current total'; - - $.each( divs.split(' '), function( i, elemId ) { - self._dom[ elemId ] = Utils.create( 'galleria-' + elemId ); - }); - - $.each( spans.split(' '), function( i, elemId ) { - self._dom[ elemId ] = Utils.create( 'galleria-' + elemId, 'span' ); - }); - - // the internal keyboard object - // keeps reference of the keybinds and provides helper methods for binding keys - var keyboard = this._keyboard = { - - keys : { - 'UP': 38, - 'DOWN': 40, - 'LEFT': 37, - 'RIGHT': 39, - 'RETURN': 13, - 'ESCAPE': 27, - 'BACKSPACE': 8, - 'SPACE': 32 - }, - - map : {}, - - bound: false, - - press: function(e) { - var key = e.keyCode || e.which; - if ( key in keyboard.map && typeof keyboard.map[key] === 'function' ) { - keyboard.map[key].call(self, e); - } - }, - - attach: function(map) { - - var key, up; - - for( key in map ) { - if ( map.hasOwnProperty( key ) ) { - up = key.toUpperCase(); - if ( up in keyboard.keys ) { - keyboard.map[ keyboard.keys[up] ] = map[key]; - } else { - keyboard.map[ up ] = map[key]; - } - } - } - if ( !keyboard.bound ) { - keyboard.bound = true; - $doc.on('keydown', keyboard.press); - } - }, - - detach: function() { - keyboard.bound = false; - keyboard.map = {}; - $doc.off('keydown', keyboard.press); - } - }; - - // internal controls for keeping track of active / inactive images - var controls = this._controls = { - - 0: undef, - - 1: undef, - - active : 0, - - swap : function() { - controls.active = controls.active ? 0 : 1; - }, - - getActive : function() { - return self._options.swipe ? controls.slides[ self._active ] : controls[ controls.active ]; - }, - - getNext : function() { - return self._options.swipe ? controls.slides[ self.getNext( self._active ) ] : controls[ 1 - controls.active ]; - }, - - slides : [], - - frames: [], - - layers: [] - }; - - // internal carousel object - var carousel = this._carousel = { - - // shortcuts - next: self.$('thumb-nav-right'), - prev: self.$('thumb-nav-left'), - - // cache the width - width: 0, - - // track the current position - current: 0, - - // cache max value - max: 0, - - // save all hooks for each width in an array - hooks: [], - - // update the carousel - // you can run this method anytime, f.ex on window.resize - update: function() { - var w = 0, - h = 0, - hooks = [0]; - - $.each( self._thumbnails, function( i, thumb ) { - if ( thumb.ready ) { - w += thumb.outerWidth || $( thumb.container ).outerWidth( true ); - // Due to a bug in jquery, outerwidth() returns the floor of the actual outerwidth, - // if the browser is zoom to a value other than 100%. height() returns the floating point value. - var containerWidth = $( thumb.container).width(); - w += containerWidth - M.floor(containerWidth); - - hooks[ i+1 ] = w; - h = M.max( h, thumb.outerHeight || $( thumb.container).outerHeight( true ) ); - } - }); - - self.$( 'thumbnails' ).css({ - width: w, - height: h - }); - - carousel.max = w; - carousel.hooks = hooks; - carousel.width = self.$( 'thumbnails-list' ).width(); - carousel.setClasses(); - - self.$( 'thumbnails-container' ).toggleClass( 'galleria-carousel', w > carousel.width ); - - // one extra calculation - carousel.width = self.$( 'thumbnails-list' ).width(); - - // todo: fix so the carousel moves to the left - }, - - bindControls: function() { - - var i; - - carousel.next.on( 'click:fast', function(e) { - e.preventDefault(); - - if ( self._options.carouselSteps === 'auto' ) { - - for ( i = carousel.current; i < carousel.hooks.length; i++ ) { - if ( carousel.hooks[i] - carousel.hooks[ carousel.current ] > carousel.width ) { - carousel.set(i - 2); - break; - } - } - - } else { - carousel.set( carousel.current + self._options.carouselSteps); - } - }); - - carousel.prev.on( 'click:fast', function(e) { - e.preventDefault(); - - if ( self._options.carouselSteps === 'auto' ) { - - for ( i = carousel.current; i >= 0; i-- ) { - if ( carousel.hooks[ carousel.current ] - carousel.hooks[i] > carousel.width ) { - carousel.set( i + 2 ); - break; - } else if ( i === 0 ) { - carousel.set( 0 ); - break; - } - } - } else { - carousel.set( carousel.current - self._options.carouselSteps ); - } - }); - }, - - // calculate and set positions - set: function( i ) { - i = M.max( i, 0 ); - while ( carousel.hooks[i - 1] + carousel.width >= carousel.max && i >= 0 ) { - i--; - } - carousel.current = i; - carousel.animate(); - }, - - // get the last position - getLast: function(i) { - return ( i || carousel.current ) - 1; - }, - - // follow the active image - follow: function(i) { - - //don't follow if position fits - if ( i === 0 || i === carousel.hooks.length - 2 ) { - carousel.set( i ); - return; - } - - // calculate last position - var last = carousel.current; - while( carousel.hooks[last] - carousel.hooks[ carousel.current ] < - carousel.width && last <= carousel.hooks.length ) { - last ++; - } - - // set position - if ( i - 1 < carousel.current ) { - carousel.set( i - 1 ); - } else if ( i + 2 > last) { - carousel.set( i - last + carousel.current + 2 ); - } - }, - - // helper for setting disabled classes - setClasses: function() { - carousel.prev.toggleClass( 'disabled', !carousel.current ); - carousel.next.toggleClass( 'disabled', carousel.hooks[ carousel.current ] + carousel.width >= carousel.max ); - }, - - // the animation method - animate: function(to) { - carousel.setClasses(); - var num = carousel.hooks[ carousel.current ] * -1; - - if ( isNaN( num ) ) { - return; - } - - // FF 24 bug - self.$( 'thumbnails' ).css('left', function() { - return $(this).css('left'); - }); - - Utils.animate(self.get( 'thumbnails' ), { - left: num - },{ - duration: self._options.carouselSpeed, - easing: self._options.easing, - queue: false - }); - } - }; - - // tooltip control - // added in 1.2 - var tooltip = this._tooltip = { - - initialized : false, - - open: false, - - timer: 'tooltip' + self._id, - - swapTimer: 'swap' + self._id, - - init: function() { - - tooltip.initialized = true; - - var css = '.galleria-tooltip{padding:3px 8px;max-width:50%;background:#ffe;color:#000;z-index:3;position:absolute;font-size:11px;line-height:1.3;' + - 'opacity:0;box-shadow:0 0 2px rgba(0,0,0,.4);-moz-box-shadow:0 0 2px rgba(0,0,0,.4);-webkit-box-shadow:0 0 2px rgba(0,0,0,.4);}'; - - Utils.insertStyleTag( css, 'galleria-tooltip' ); - - self.$( 'tooltip' ).css({ - opacity: 0.8, - visibility: 'visible', - display: 'none' - }); - - }, - - // move handler - move: function( e ) { - var mouseX = self.getMousePosition(e).x, - mouseY = self.getMousePosition(e).y, - $elem = self.$( 'tooltip' ), - x = mouseX, - y = mouseY, - height = $elem.outerHeight( true ) + 1, - width = $elem.outerWidth( true ), - limitY = height + 15; - - var maxX = self.$( 'container' ).width() - width - 2, - maxY = self.$( 'container' ).height() - height - 2; - - if ( !isNaN(x) && !isNaN(y) ) { - - x += 10; - y -= ( height+8 ); - - x = M.max( 0, M.min( maxX, x ) ); - y = M.max( 0, M.min( maxY, y ) ); - - if( mouseY < limitY ) { - y = limitY; - } - - $elem.css({ left: x, top: y }); - } - }, - - // bind elements to the tooltip - // you can bind multiple elementIDs using { elemID : function } or { elemID : string } - // you can also bind single DOM elements using bind(elem, string) - bind: function( elem, value ) { - - // todo: revise if alternative tooltip is needed for mobile devices - if (Galleria.TOUCH) { - return; - } - - if (! tooltip.initialized ) { - tooltip.init(); - } - - var mouseout = function() { - self.$( 'container' ).off( 'mousemove', tooltip.move ); - self.clearTimer( tooltip.timer ); - - self.$( 'tooltip' ).stop().animate({ - opacity: 0 - }, 200, function() { - - self.$( 'tooltip' ).hide(); - - self.addTimer( tooltip.swapTimer, function() { - tooltip.open = false; - }, 1000); - }); - }; - - var hover = function( elem, value) { - - tooltip.define( elem, value ); - - $( elem ).hover(function() { - - self.clearTimer( tooltip.swapTimer ); - self.$('container').off( 'mousemove', tooltip.move ).on( 'mousemove', tooltip.move ).trigger( 'mousemove' ); - tooltip.show( elem ); - - self.addTimer( tooltip.timer, function() { - self.$( 'tooltip' ).stop().show().animate({ - opacity: 1 - }); - tooltip.open = true; - - }, tooltip.open ? 0 : 500); - - }, mouseout).click(mouseout); - }; - - if ( typeof value === 'string' ) { - hover( ( elem in self._dom ? self.get( elem ) : elem ), value ); - } else { - // asume elemID here - $.each( elem, function( elemID, val ) { - hover( self.get(elemID), val ); - }); - } - }, - - show: function( elem ) { - - elem = $( elem in self._dom ? self.get(elem) : elem ); - - var text = elem.data( 'tt' ), - mouseup = function( e ) { - - // attach a tiny settimeout to make sure the new tooltip is filled - window.setTimeout( (function( ev ) { - return function() { - tooltip.move( ev ); - }; - }( e )), 10); - - elem.off( 'mouseup', mouseup ); - - }; - - text = typeof text === 'function' ? text() : text; - - if ( ! text ) { - return; - } - - self.$( 'tooltip' ).html( text.replace(/\s/, ' ') ); - - // trigger mousemove on mouseup in case of click - elem.on( 'mouseup', mouseup ); - }, - - define: function( elem, value ) { - - // we store functions, not strings - if (typeof value !== 'function') { - var s = value; - value = function() { - return s; - }; - } - - elem = $( elem in self._dom ? self.get(elem) : elem ).data('tt', value); - - tooltip.show( elem ); - - } - }; - - // internal fullscreen control - var fullscreen = this._fullscreen = { - - scrolled: 0, - - crop: undef, - - active: false, - - prev: $(), - - beforeEnter: function(fn){ fn(); }, - beforeExit: function(fn){ fn(); }, - - keymap: self._keyboard.map, - - parseCallback: function( callback, enter ) { - - return _transitions.active ? function() { - if ( typeof callback == 'function' ) { - callback.call(self); - } - var active = self._controls.getActive(), - next = self._controls.getNext(); - - self._scaleImage( next ); - self._scaleImage( active ); - - if ( enter && self._options.trueFullscreen ) { - // Firefox bug, revise later - $( active.container ).add( next.container ).trigger( 'transitionend' ); - } - - } : callback; - - }, - - enter: function( callback ) { - - fullscreen.beforeEnter(function() { - - callback = fullscreen.parseCallback( callback, true ); - - if ( self._options.trueFullscreen && _nativeFullscreen.support ) { - - // do some stuff prior animation for wmoother transitions - - fullscreen.active = true; - - Utils.forceStyles( self.get('container'), { - width: '100%', - height: '100%' - }); - - self.rescale(); - - if ( Galleria.MAC ) { - if ( !( Galleria.SAFARI && /version\/[1-5]/.test(NAV)) ) { - self.$('container').css('opacity', 0).addClass('fullscreen'); - window.setTimeout(function() { - fullscreen.scale(); - self.$('container').css('opacity', 1); - }, 50); - } else { - self.$('stage').css('opacity', 0); - window.setTimeout(function() { - fullscreen.scale(); - self.$('stage').css('opacity', 1); - },4); - } - } else { - self.$('container').addClass('fullscreen'); - } - - $win.resize( fullscreen.scale ); - - _nativeFullscreen.enter( self, callback, self.get('container') ); - - } else { - - fullscreen.scrolled = $win.scrollTop(); - if( !Galleria.TOUCH ) { - window.scrollTo(0, 0); - } - - fullscreen._enter( callback ); - } - }); - - }, - - _enter: function( callback ) { - - fullscreen.active = true; - - if ( IFRAME ) { - - fullscreen.iframe = (function() { - - var elem, - refer = doc.referrer, - test = doc.createElement('a'), - loc = window.location; - - test.href = refer; - - if( test.protocol != loc.protocol || - test.hostname != loc.hostname || - test.port != loc.port ) { - Galleria.raise('Parent fullscreen not available. Iframe protocol, domains and ports must match.'); - return false; - } - - fullscreen.pd = window.parent.document; - - $( fullscreen.pd ).find('iframe').each(function() { - var idoc = this.contentDocument || this.contentWindow.document; - if ( idoc === doc ) { - elem = this; - return false; - } - }); - - return elem; - }()); - - } - - // hide the image until rescale is complete - Utils.hide( self.getActiveImage() ); - - if ( IFRAME && fullscreen.iframe ) { - fullscreen.iframe.scrolled = $( window.parent ).scrollTop(); - window.parent.scrollTo(0, 0); - } - - var data = self.getData(), - options = self._options, - inBrowser = !self._options.trueFullscreen || !_nativeFullscreen.support, - htmlbody = { - height: '100%', - overflow: 'hidden', - margin:0, - padding:0 - }; - - if (inBrowser) { - - self.$('container').addClass('fullscreen'); - fullscreen.prev = self.$('container').prev(); - - if ( !fullscreen.prev.length ) { - fullscreen.parent = self.$( 'container' ).parent(); - } - - // move - self.$( 'container' ).appendTo( 'body' ); - - // begin styleforce - - Utils.forceStyles(self.get('container'), { - position: Galleria.TOUCH ? 'absolute' : 'fixed', - top: 0, - left: 0, - width: '100%', - height: '100%', - zIndex: 10000 - }); - Utils.forceStyles( DOM().html, htmlbody ); - Utils.forceStyles( DOM().body, htmlbody ); - } - - if ( IFRAME && fullscreen.iframe ) { - Utils.forceStyles( fullscreen.pd.documentElement, htmlbody ); - Utils.forceStyles( fullscreen.pd.body, htmlbody ); - Utils.forceStyles( fullscreen.iframe, $.extend( htmlbody, { - width: '100%', - height: '100%', - top: 0, - left: 0, - position: 'fixed', - zIndex: 10000, - border: 'none' - })); - } - - // temporarily attach some keys - // save the old ones first in a cloned object - fullscreen.keymap = $.extend({}, self._keyboard.map); - - self.attachKeyboard({ - escape: self.exitFullscreen, - right: self.next, - left: self.prev - }); - - // temporarily save the crop - fullscreen.crop = options.imageCrop; - - // set fullscreen options - if ( options.fullscreenCrop != undef ) { - options.imageCrop = options.fullscreenCrop; - } - - // swap to big image if it's different from the display image - if ( data && data.big && data.image !== data.big ) { - var big = new Galleria.Picture(), - cached = big.isCached( data.big ), - index = self.getIndex(), - thumb = self._thumbnails[ index ]; - - self.trigger( { - type: Galleria.LOADSTART, - cached: cached, - rewind: false, - index: index, - imageTarget: self.getActiveImage(), - thumbTarget: thumb, - galleriaData: data - }); - - big.load( data.big, function( big ) { - self._scaleImage( big, { - complete: function( big ) { - self.trigger({ - type: Galleria.LOADFINISH, - cached: cached, - index: index, - rewind: false, - imageTarget: big.image, - thumbTarget: thumb - }); - var image = self._controls.getActive().image; - if ( image ) { - $( image ).width( big.image.width ).height( big.image.height ) - .attr( 'style', $( big.image ).attr('style') ) - .attr( 'src', big.image.src ); - } - } - }); - }); - - var n = self.getNext(index), - p = new Galleria.Picture(), - ndata = self.getData( n ); - p.preload( self.isFullscreen() && ndata.big ? ndata.big : ndata.image ); - } - - // init the first rescale and attach callbacks - - self.rescale(function() { - - self.addTimer(false, function() { - // show the image after 50 ms - if ( inBrowser ) { - Utils.show( self.getActiveImage() ); - } - - if (typeof callback === 'function') { - callback.call( self ); - } - self.rescale(); - - }, 100); - - self.trigger( Galleria.FULLSCREEN_ENTER ); - }); - - if ( !inBrowser ) { - Utils.show( self.getActiveImage() ); - } else { - $win.resize( fullscreen.scale ); - } - - }, - - scale : function() { - self.rescale(); - }, - - exit: function( callback ) { - - fullscreen.beforeExit(function() { - - callback = fullscreen.parseCallback( callback ); - - if ( self._options.trueFullscreen && _nativeFullscreen.support ) { - _nativeFullscreen.exit( callback ); - } else { - fullscreen._exit( callback ); - } - }); - }, - - _exit: function( callback ) { - - fullscreen.active = false; - - var inBrowser = !self._options.trueFullscreen || !_nativeFullscreen.support, - $container = self.$( 'container' ).removeClass( 'fullscreen' ); - - // move back - if ( fullscreen.parent ) { - fullscreen.parent.prepend( $container ); - } else { - $container.insertAfter( fullscreen.prev ); - } - - if ( inBrowser ) { - Utils.hide( self.getActiveImage() ); - - // revert all styles - Utils.revertStyles( self.get('container'), DOM().html, DOM().body ); - - // scroll back - if( !Galleria.TOUCH ) { - window.scrollTo(0, fullscreen.scrolled); - } - - // reload iframe src manually - var frame = self._controls.frames[ self._controls.active ]; - if ( frame && frame.image ) { - frame.image.src = frame.image.src; - } - } - - if ( IFRAME && fullscreen.iframe ) { - Utils.revertStyles( fullscreen.pd.documentElement, fullscreen.pd.body, fullscreen.iframe ); - if ( fullscreen.iframe.scrolled ) { - window.parent.scrollTo(0, fullscreen.iframe.scrolled ); - } - } - - // detach all keyboard events and apply the old keymap - self.detachKeyboard(); - self.attachKeyboard( fullscreen.keymap ); - - // bring back cached options - self._options.imageCrop = fullscreen.crop; - - // return to original image - var big = self.getData().big, - image = self._controls.getActive().image; - - if ( !self.getData().iframe && image && big && big == image.src ) { - - window.setTimeout(function(src) { - return function() { - image.src = src; - }; - }( self.getData().image ), 1 ); - - } - - self.rescale(function() { - self.addTimer(false, function() { - - // show the image after 50 ms - if ( inBrowser ) { - Utils.show( self.getActiveImage() ); - } - - if ( typeof callback === 'function' ) { - callback.call( self ); - } - - $win.trigger( 'resize' ); - - }, 50); - self.trigger( Galleria.FULLSCREEN_EXIT ); - }); - - $win.off('resize', fullscreen.scale); - } - }; - - // the internal idle object for controlling idle states - var idle = this._idle = { - - trunk: [], - - bound: false, - - active: false, - - add: function(elem, to, from, hide) { - if ( !elem || Galleria.TOUCH ) { - return; - } - if (!idle.bound) { - idle.addEvent(); - } - elem = $(elem); - - if ( typeof from == 'boolean' ) { - hide = from; - from = {}; - } - - from = from || {}; - - var extract = {}, - style; - - for ( style in to ) { - if ( to.hasOwnProperty( style ) ) { - extract[ style ] = elem.css( style ); - } - } - - elem.data('idle', { - from: $.extend( extract, from ), - to: to, - complete: true, - busy: false - }); - - if ( !hide ) { - idle.addTimer(); - } else { - elem.css( to ); - } - idle.trunk.push(elem); - }, - - remove: function(elem) { - - elem = $(elem); - - $.each(idle.trunk, function(i, el) { - if ( el && el.length && !el.not(elem).length ) { - elem.css( elem.data( 'idle' ).from ); - idle.trunk.splice(i, 1); - } - }); - - if (!idle.trunk.length) { - idle.removeEvent(); - self.clearTimer( idle.timer ); - } - }, - - addEvent : function() { - idle.bound = true; - self.$('container').on( 'mousemove click', idle.showAll ); - if ( self._options.idleMode == 'hover' ) { - self.$('container').on( 'mouseleave', idle.hide ); - } - }, - - removeEvent : function() { - idle.bound = false; - self.$('container').on( 'mousemove click', idle.showAll ); - if ( self._options.idleMode == 'hover' ) { - self.$('container').off( 'mouseleave', idle.hide ); - } - }, - - addTimer : function() { - if( self._options.idleMode == 'hover' ) { - return; - } - self.addTimer( 'idle', function() { - idle.hide(); - }, self._options.idleTime ); - }, - - hide : function() { - - if ( !self._options.idleMode || self.getIndex() === false ) { - return; - } - - self.trigger( Galleria.IDLE_ENTER ); - - var len = idle.trunk.length; - - $.each( idle.trunk, function(i, elem) { - - var data = elem.data('idle'); - - if (! data) { - return; - } - - elem.data('idle').complete = false; - - Utils.animate( elem, data.to, { - duration: self._options.idleSpeed, - complete: function() { - if ( i == len-1 ) { - idle.active = false; - } - } - }); - }); - }, - - showAll : function() { - - self.clearTimer( 'idle' ); - - $.each( idle.trunk, function( i, elem ) { - idle.show( elem ); - }); - }, - - show: function(elem) { - - var data = elem.data('idle'); - - if ( !idle.active || ( !data.busy && !data.complete ) ) { - - data.busy = true; - - self.trigger( Galleria.IDLE_EXIT ); - - self.clearTimer( 'idle' ); - - Utils.animate( elem, data.from, { - duration: self._options.idleSpeed/2, - complete: function() { - idle.active = true; - $(elem).data('idle').busy = false; - $(elem).data('idle').complete = true; - } - }); - - } - idle.addTimer(); - } - }; - - // internal lightbox object - // creates a predesigned lightbox for simple popups of images in galleria - var lightbox = this._lightbox = { - - width : 0, - - height : 0, - - initialized : false, - - active : null, - - image : null, - - elems : {}, - - keymap: false, - - init : function() { - - if ( lightbox.initialized ) { - return; - } - lightbox.initialized = true; - - // create some elements to work with - var elems = 'overlay box content shadow title info close prevholder prev nextholder next counter image', - el = {}, - op = self._options, - css = '', - abs = 'position:absolute;', - prefix = 'lightbox-', - cssMap = { - overlay: 'position:fixed;display:none;opacity:'+op.overlayOpacity+';filter:alpha(opacity='+(op.overlayOpacity*100)+ - ');top:0;left:0;width:100%;height:100%;background:'+op.overlayBackground+';z-index:99990', - box: 'position:fixed;display:none;width:400px;height:400px;top:50%;left:50%;margin-top:-200px;margin-left:-200px;z-index:99991', - shadow: abs+'background:#000;width:100%;height:100%;', - content: abs+'background-color:#fff;top:10px;left:10px;right:10px;bottom:10px;overflow:hidden', - info: abs+'bottom:10px;left:10px;right:10px;color:#444;font:11px/13px arial,sans-serif;height:13px', - close: abs+'top:10px;right:10px;height:20px;width:20px;background:#fff;text-align:center;cursor:pointer;color:#444;font:16px/22px arial,sans-serif;z-index:99999', - image: abs+'top:10px;left:10px;right:10px;bottom:30px;overflow:hidden;display:block;', - prevholder: abs+'width:50%;top:0;bottom:40px;cursor:pointer;', - nextholder: abs+'width:50%;top:0;bottom:40px;right:-1px;cursor:pointer;', - prev: abs+'top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;left:20px;display:none;text-align:center;color:#000;font:bold 16px/36px arial,sans-serif', - next: abs+'top:50%;margin-top:-20px;height:40px;width:30px;background:#fff;right:20px;left:auto;display:none;font:bold 16px/36px arial,sans-serif;text-align:center;color:#000', - title: 'float:left', - counter: 'float:right;margin-left:8px;' - }, - hover = function(elem) { - return elem.hover( - function() { $(this).css( 'color', '#bbb' ); }, - function() { $(this).css( 'color', '#444' ); } - ); - }, - appends = {}; - - // fix for navigation hovers transparent background event "feature" - var exs = ''; - if ( IE > 7 ) { - exs = IE < 9 ? 'background:#000;filter:alpha(opacity=0);' : 'background:rgba(0,0,0,0);'; - } else { - exs = 'z-index:99999'; - } - - cssMap.nextholder += exs; - cssMap.prevholder += exs; - - // create and insert CSS - $.each(cssMap, function( key, value ) { - css += '.galleria-'+prefix+key+'{'+value+'}'; - }); - - css += '.galleria-'+prefix+'box.iframe .galleria-'+prefix+'prevholder,'+ - '.galleria-'+prefix+'box.iframe .galleria-'+prefix+'nextholder{'+ - 'width:100px;height:100px;top:50%;margin-top:-70px}'; - - Utils.insertStyleTag( css, 'galleria-lightbox' ); - - // create the elements - $.each(elems.split(' '), function( i, elemId ) { - self.addElement( 'lightbox-' + elemId ); - el[ elemId ] = lightbox.elems[ elemId ] = self.get( 'lightbox-' + elemId ); - }); - - // initiate the image - lightbox.image = new Galleria.Picture(); - - // append the elements - $.each({ - box: 'shadow content close prevholder nextholder', - info: 'title counter', - content: 'info image', - prevholder: 'prev', - nextholder: 'next' - }, function( key, val ) { - var arr = []; - $.each( val.split(' '), function( i, prop ) { - arr.push( prefix + prop ); - }); - appends[ prefix+key ] = arr; - }); - - self.append( appends ); - - $( el.image ).append( lightbox.image.container ); - - $( DOM().body ).append( el.overlay, el.box ); - - // add the prev/next nav and bind some controls - - hover( $( el.close ).on( 'click:fast', lightbox.hide ).html('×') ); - - $.each( ['Prev','Next'], function(i, dir) { - - var $d = $( el[ dir.toLowerCase() ] ).html( /v/.test( dir ) ? '‹ ' : ' ›' ), - $e = $( el[ dir.toLowerCase()+'holder'] ); - - $e.on( 'click:fast', function() { - lightbox[ 'show' + dir ](); - }); - - // IE7 and touch devices will simply show the nav - if ( IE < 8 || Galleria.TOUCH ) { - $d.show(); - return; - } - - $e.hover( function() { - $d.show(); - }, function(e) { - $d.stop().fadeOut( 200 ); - }); - - }); - $( el.overlay ).on( 'click:fast', lightbox.hide ); - - // the lightbox animation is slow on ipad - if ( Galleria.IPAD ) { - self._options.lightboxTransitionSpeed = 0; - } - - }, - - rescale: function(event) { - - // calculate - var width = M.min( $win.width()-40, lightbox.width ), - height = M.min( $win.height()-60, lightbox.height ), - ratio = M.min( width / lightbox.width, height / lightbox.height ), - destWidth = M.round( lightbox.width * ratio ) + 40, - destHeight = M.round( lightbox.height * ratio ) + 60, - to = { - width: destWidth, - height: destHeight, - 'margin-top': M.ceil( destHeight / 2 ) *- 1, - 'margin-left': M.ceil( destWidth / 2 ) *- 1 - }; - - // if rescale event, don't animate - if ( event ) { - $( lightbox.elems.box ).css( to ); - } else { - $( lightbox.elems.box ).animate( to, { - duration: self._options.lightboxTransitionSpeed, - easing: self._options.easing, - complete: function() { - var image = lightbox.image, - speed = self._options.lightboxFadeSpeed; - - self.trigger({ - type: Galleria.LIGHTBOX_IMAGE, - imageTarget: image.image - }); - - $( image.container ).show(); - - $( image.image ).animate({ opacity: 1 }, speed); - Utils.show( lightbox.elems.info, speed ); - } - }); - } - }, - - hide: function() { - - // remove the image - lightbox.image.image = null; - - $win.off('resize', lightbox.rescale); - - $( lightbox.elems.box ).hide().find( 'iframe' ).remove(); - - Utils.hide( lightbox.elems.info ); - - self.detachKeyboard(); - self.attachKeyboard( lightbox.keymap ); - - lightbox.keymap = false; - - Utils.hide( lightbox.elems.overlay, 200, function() { - $( this ).hide().css( 'opacity', self._options.overlayOpacity ); - self.trigger( Galleria.LIGHTBOX_CLOSE ); - }); - }, - - showNext: function() { - lightbox.show( self.getNext( lightbox.active ) ); - }, - - showPrev: function() { - lightbox.show( self.getPrev( lightbox.active ) ); - }, - - show: function(index) { - - lightbox.active = index = typeof index === 'number' ? index : self.getIndex() || 0; - - if ( !lightbox.initialized ) { - lightbox.init(); - } - - // trigger the event - self.trigger( Galleria.LIGHTBOX_OPEN ); - - // temporarily attach some keys - // save the old ones first in a cloned object - if ( !lightbox.keymap ) { - - lightbox.keymap = $.extend({}, self._keyboard.map); - - self.attachKeyboard({ - escape: lightbox.hide, - right: lightbox.showNext, - left: lightbox.showPrev - }); - } - - $win.off('resize', lightbox.rescale ); - - var data = self.getData(index), - total = self.getDataLength(), - n = self.getNext( index ), - ndata, p, i; - - Utils.hide( lightbox.elems.info ); - - try { - for ( i = self._options.preload; i > 0; i-- ) { - p = new Galleria.Picture(); - ndata = self.getData( n ); - p.preload( ndata.big ? ndata.big : ndata.image ); - n = self.getNext( n ); - } - } catch(e) {} - - lightbox.image.isIframe = ( data.iframe && !data.image ); - - $( lightbox.elems.box ).toggleClass( 'iframe', lightbox.image.isIframe ); - - $( lightbox.image.container ).find( '.galleria-videoicon' ).remove(); - - lightbox.image.load( data.big || data.image || data.iframe, function( image ) { - - if ( image.isIframe ) { - - var cw = $(window).width(), - ch = $(window).height(); - - if ( image.video && self._options.maxVideoSize ) { - var r = M.min( self._options.maxVideoSize/cw, self._options.maxVideoSize/ch ); - if ( r < 1 ) { - cw *= r; - ch *= r; - } - } - lightbox.width = cw; - lightbox.height = ch; - - } else { - lightbox.width = image.original.width; - lightbox.height = image.original.height; - } - - $( image.image ).css({ - width: image.isIframe ? '100%' : '100.1%', - height: image.isIframe ? '100%' : '100.1%', - top: 0, - bottom: 0, - zIndex: 99998, - opacity: 0, - visibility: 'visible' - }).parent().height('100%'); - - lightbox.elems.title.innerHTML = data.title || ''; - lightbox.elems.counter.innerHTML = (index + 1) + ' / ' + total; - $win.resize( lightbox.rescale ); - lightbox.rescale(); - - if( data.image && data.iframe ) { - - $( lightbox.elems.box ).addClass('iframe'); - - if ( data.video ) { - var $icon = _playIcon( image.container ).hide(); - window.setTimeout(function() { - $icon.fadeIn(200); - }, 200); - } - - $( image.image ).css( 'cursor', 'pointer' ).mouseup((function(data, image) { - return function(e) { - $( lightbox.image.container ).find( '.galleria-videoicon' ).remove(); - e.preventDefault(); - image.isIframe = true; - image.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { - width: '100%', - height: IE < 8 ? $( lightbox.image.container ).height() : '100%' - }); - }; - }(data, image))); - } - }); - - $( lightbox.elems.overlay ).show().css( 'visibility', 'visible' ); - $( lightbox.elems.box ).show(); - } - }; - - // the internal timeouts object - // provides helper methods for controlling timeouts - - var _timer = this._timer = { - - trunk: {}, - - add: function( id, fn, delay, loop ) { - id = id || new Date().getTime(); - loop = loop || false; - this.clear( id ); - if ( loop ) { - var old = fn; - fn = function() { - old(); - _timer.add( id, fn, delay ); - }; - } - this.trunk[ id ] = window.setTimeout( fn, delay ); - }, - - clear: function( id ) { - - var del = function( i ) { - window.clearTimeout( this.trunk[ i ] ); - delete this.trunk[ i ]; - }, i; - - if ( !!id && id in this.trunk ) { - del.call( this, id ); - - } else if ( typeof id === 'undefined' ) { - for ( i in this.trunk ) { - if ( this.trunk.hasOwnProperty( i ) ) { - del.call( this, i ); - } - } - } - } - }; - - return this; -}; - -// end Galleria constructor - -Galleria.prototype = { - - // bring back the constructor reference - - constructor: Galleria, - - /** - Use this function to initialize the gallery and start loading. - Should only be called once per instance. - - @param {HTMLElement} target The target element - @param {Object} options The gallery options - - @returns Instance - */ - - init: function( target, options ) { - - options = _legacyOptions( options ); - - // save the original ingredients - this._original = { - target: target, - options: options, - data: null - }; - - // save the target here - this._target = this._dom.target = target.nodeName ? target : $( target ).get(0); - - // save the original content for destruction - this._original.html = this._target.innerHTML; - - // push the instance - _instances.push( this ); - - // raise error if no target is detected - if ( !this._target ) { - Galleria.raise('Target not found', true); - return; - } - - // apply options - this._options = { - autoplay: false, - carousel: true, - carouselFollow: true, // legacy, deprecate at 1.3 - carouselSpeed: 400, - carouselSteps: 'auto', - clicknext: false, - dailymotion: { - foreground: '%23EEEEEE', - highlight: '%235BCEC5', - background: '%23222222', - logo: 0, - hideInfos: 1 - }, - dataConfig : function( elem ) { return {}; }, - dataSelector: 'img', - dataSort: false, - dataSource: this._target, - debug: undef, - dummy: undef, // 1.2.5 - easing: 'galleria', - extend: function(options) {}, - fullscreenCrop: undef, // 1.2.5 - fullscreenDoubleTap: true, // 1.2.4 toggles fullscreen on double-tap for touch devices - fullscreenTransition: undef, // 1.2.6 - height: 0, - idleMode: true, // 1.2.4 toggles idleMode - idleTime: 3000, - idleSpeed: 200, - imageCrop: false, - imageMargin: 0, - imagePan: false, - imagePanSmoothness: 12, - imagePosition: '50%', - imageTimeout: undef, // 1.2.5 - initialTransition: undef, // 1.2.4, replaces transitionInitial - keepSource: false, - layerFollow: true, // 1.2.5 - lightbox: false, // 1.2.3 - lightboxFadeSpeed: 200, - lightboxTransitionSpeed: 200, - linkSourceImages: true, - maxScaleRatio: undef, - maxVideoSize: undef, // 1.2.9 - minScaleRatio: undef, // deprecated in 1.2.9 - overlayOpacity: 0.85, - overlayBackground: '#0b0b0b', - pauseOnInteraction: true, - popupLinks: false, - preload: 2, - queue: true, - responsive: true, - show: 0, - showInfo: true, - showCounter: true, - showImagenav: true, - swipe: 'auto', // 1.2.4 -> revised in 1.3 -> changed type in 1.3.5 - theme: null, - thumbCrop: true, - thumbEventType: 'click:fast', - thumbMargin: 0, - thumbQuality: 'auto', - thumbDisplayOrder: true, // 1.2.8 - thumbPosition: '50%', // 1.3 - thumbnails: true, - touchTransition: undef, // 1.2.6 - transition: 'fade', - transitionInitial: undef, // legacy, deprecate in 1.3. Use initialTransition instead. - transitionSpeed: 400, - trueFullscreen: true, // 1.2.7 - useCanvas: false, // 1.2.4 - variation: '', // 1.3.2 - videoPoster: true, // 1.3 - vimeo: { - title: 0, - byline: 0, - portrait: 0, - color: 'aaaaaa' - }, - wait: 5000, // 1.2.7 - width: 'auto', - youtube: { - modestbranding: 1, - autohide: 1, - color: 'white', - hd: 1, - rel: 0, - showinfo: 0 - } - }; - - // legacy support for transitionInitial - this._options.initialTransition = this._options.initialTransition || this._options.transitionInitial; - - if ( options ) { - - // turn off debug - if ( options.debug === false ) { - DEBUG = false; - } - - // set timeout - if ( typeof options.imageTimeout === 'number' ) { - TIMEOUT = options.imageTimeout; - } - - // set dummy - if ( typeof options.dummy === 'string' ) { - DUMMY = options.dummy; - } - - // set theme - if ( typeof options.theme == 'string' ) { - this._options.theme = options.theme; - } - } - - // hide all content - $( this._target ).children().hide(); - - // Warn for quirks mode - if ( Galleria.QUIRK ) { - Galleria.raise('Your page is in Quirks mode, Galleria may not render correctly. Please validate your HTML and add a correct doctype.'); - } - - // now we just have to wait for the theme... - // first check if it has already loaded - if ( _loadedThemes.length ) { - if ( this._options.theme ) { - for ( var i=0; i<_loadedThemes.length; i++ ) { - if( this._options.theme === _loadedThemes[i].name ) { - this.theme = _loadedThemes[i]; - break; - } - } - } else { - // if no theme sepcified, apply the first loaded theme - this.theme = _loadedThemes[0]; - } - } - - if ( typeof this.theme == 'object' ) { - this._init(); - } else { - // if no theme is loaded yet, push the instance into a pool and run it when the theme is ready - _pool.push( this ); - } - - return this; - }, - - // this method should only be called once per instance - // for manipulation of data, use the .load method - - _init: function() { - - var self = this, - options = this._options; - - if ( this._initialized ) { - Galleria.raise( 'Init failed: Gallery instance already initialized.' ); - return this; - } - - this._initialized = true; - - if ( !this.theme ) { - Galleria.raise( 'Init failed: No theme found.', true ); - return this; - } - - // merge the theme & caller options - $.extend( true, options, this.theme.defaults, this._original.options, Galleria.configure.options ); - - // internally we use boolean for swipe - options.swipe = (function(s) { - - if ( s == 'enforced' ) { return true; } - - // legacy patch - if( s === false || s == 'disabled' ) { return false; } - - return !!Galleria.TOUCH; - - }( options.swipe )); - - // disable options that arent compatible with swipe - if ( options.swipe ) { - options.clicknext = false; - options.imagePan = false; - } - - // check for canvas support - (function( can ) { - if ( !( 'getContext' in can ) ) { - can = null; - return; - } - _canvas = _canvas || { - elem: can, - context: can.getContext( '2d' ), - cache: {}, - length: 0 - }; - }( doc.createElement( 'canvas' ) ) ); - - // bind the gallery to run when data is ready - this.bind( Galleria.DATA, function() { - - // remove big if total pixels are less than 1024 (most phones) - if ( window.screen && window.screen.width && Array.prototype.forEach ) { - - this._data.forEach(function(data) { - - var density = 'devicePixelRatio' in window ? window.devicePixelRatio : 1, - m = M.max( window.screen.width, window.screen.height ); - - if ( m*density < 1024 ) { - data.big = data.image; - } - }); - } - - // save the new data - this._original.data = this._data; - - // lets show the counter here - this.get('total').innerHTML = this.getDataLength(); - - // cache the container - var $container = this.$( 'container' ); - - // set ratio if height is < 2 - if ( self._options.height < 2 ) { - self._userRatio = self._ratio = self._options.height; - } - - // the gallery is ready, let's just wait for the css - var num = { width: 0, height: 0 }; - var testHeight = function() { - return self.$( 'stage' ).height(); - }; - - // check container and thumbnail height - Utils.wait({ - until: function() { - - // keep trying to get the value - num = self._getWH(); - $container.width( num.width ).height( num.height ); - return testHeight() && num.width && num.height > 50; - - }, - success: function() { - - self._width = num.width; - self._height = num.height; - self._ratio = self._ratio || num.height/num.width; - - // for some strange reason, webkit needs a single setTimeout to play ball - if ( Galleria.WEBKIT ) { - window.setTimeout( function() { - self._run(); - }, 1); - } else { - self._run(); - } - }, - error: function() { - - // Height was probably not set, raise hard errors - - if ( testHeight() ) { - Galleria.raise('Could not extract sufficient width/height of the gallery container. Traced measures: width:' + num.width + 'px, height: ' + num.height + 'px.', true); - } else { - Galleria.raise('Could not extract a stage height from the CSS. Traced height: ' + testHeight() + 'px.', true); - } - }, - timeout: typeof this._options.wait == 'number' ? this._options.wait : false - }); - }); - - // build the gallery frame - this.append({ - 'info-text' : - ['info-title', 'info-description'], - 'info' : - ['info-text'], - 'image-nav' : - ['image-nav-right', 'image-nav-left'], - 'stage' : - ['images', 'loader', 'counter', 'image-nav'], - 'thumbnails-list' : - ['thumbnails'], - 'thumbnails-container' : - ['thumb-nav-left', 'thumbnails-list', 'thumb-nav-right'], - 'container' : - ['stage', 'thumbnails-container', 'info', 'tooltip'] - }); - - Utils.hide( this.$( 'counter' ).append( - this.get( 'current' ), - doc.createTextNode(' / '), - this.get( 'total' ) - ) ); - - this.setCounter('–'); - - Utils.hide( self.get('tooltip') ); - - // add a notouch class on the container to prevent unwanted :hovers on touch devices - this.$( 'container' ).addClass([ - ( Galleria.TOUCH ? 'touch' : 'notouch' ), - this._options.variation, - 'galleria-theme-'+this.theme.name - ].join(' ')); - - // add images to the controls - if ( !this._options.swipe ) { - $.each( new Array(2), function( i ) { - - // create a new Picture instance - var image = new Galleria.Picture(); - - // apply some styles, create & prepend overlay - $( image.container ).css({ - position: 'absolute', - top: 0, - left: 0 - }).prepend( self._layers[i] = $( Utils.create('galleria-layer') ).css({ - position: 'absolute', - top:0, left:0, right:0, bottom:0, - zIndex:2 - })[0] ); - - // append the image - self.$( 'images' ).append( image.container ); - - // reload the controls - self._controls[i] = image; - - // build a frame - var frame = new Galleria.Picture(); - frame.isIframe = true; - - $( frame.container ).attr('class', 'galleria-frame').css({ - position: 'absolute', - top: 0, - left: 0, - zIndex: 4, - background: '#000', - display: 'none' - }).appendTo( image.container ); - - self._controls.frames[i] = frame; - - }); - } - - // some forced generic styling - this.$( 'images' ).css({ - position: 'relative', - top: 0, - left: 0, - width: '100%', - height: '100%' - }); - - if ( options.swipe ) { - this.$( 'images' ).css({ - position: 'absolute', - top: 0, - left: 0, - width: 0, - height: '100%' - }); - this.finger = new Galleria.Finger(this.get('stage'), { - onchange: function(page) { - self.pause().show(page); - }, - oncomplete: function(page) { - - var index = M.max( 0, M.min( parseInt( page, 10 ), self.getDataLength() - 1 ) ), - data = self.getData(index); - - $( self._thumbnails[ index ].container ) - .addClass( 'active' ) - .siblings( '.active' ) - .removeClass( 'active' ); - - if ( !data ) { - return; - } - - // remove video iframes - self.$( 'images' ).find( '.galleria-frame' ).css('opacity', 0).hide().find( 'iframe' ).remove(); - - if ( self._options.carousel && self._options.carouselFollow ) { - self._carousel.follow( index ); - } - } - }); - this.bind( Galleria.RESCALE, function() { - this.finger.setup(); - }); - this.$('stage').on('click', function(e) { - var data = self.getData(); - if ( !data ) { - return; - } - if ( data.iframe ) { - - if ( self.isPlaying() ) { - self.pause(); - } - var frame = self._controls.frames[ self._active ], - w = self._stageWidth, - h = self._stageHeight; - - if ( $( frame.container ).find( 'iframe' ).length ) { - return; - } - - $( frame.container ).css({ - width: w, - height: h, - opacity: 0 - }).show().animate({ - opacity: 1 - }, 200); - - window.setTimeout(function() { - frame.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { - width: w, - height: h - }, function( frame ) { - self.$( 'container' ).addClass( 'videoplay' ); - frame.scale({ - width: self._stageWidth, - height: self._stageHeight, - iframelimit: data.video ? self._options.maxVideoSize : undef - }); - }); - }, 100); - - return; - } - - if ( data.link ) { - if ( self._options.popupLinks ) { - var win = window.open( data.link, '_blank' ); - } else { - window.location.href = data.link; - } - return; - } - }); - this.bind( Galleria.IMAGE, function(e) { - - self.setCounter( e.index ); - self.setInfo( e.index ); - - var next = this.getNext(), - prev = this.getPrev(); - - var preloads = [prev,next]; - preloads.push(this.getNext(next), this.getPrev(prev), self._controls.slides.length-1); - - var filtered = []; - - $.each(preloads, function(i, val) { - if ( $.inArray(val, filtered) == -1 ) { - filtered.push(val); - } - }); - - $.each(filtered, function(i, loadme) { - var d = self.getData(loadme), - img = self._controls.slides[loadme], - src = self.isFullscreen() && d.big ? d.big : ( d.image || d.iframe ); - - if ( d.iframe && !d.image ) { - img.isIframe = true; - } - - if ( !img.ready ) { - self._controls.slides[loadme].load(src, function(img) { - if ( !img.isIframe ) { - $(img.image).css('visibility', 'hidden'); - } - self._scaleImage(img, { - complete: function(img) { - if ( !img.isIframe ) { - $(img.image).css({ - opacity: 0, - visibility: 'visible' - }).animate({ - opacity: 1 - }, 200); - } - } - }); - }); - } - }); - }); - } - - this.$( 'thumbnails, thumbnails-list' ).css({ - overflow: 'hidden', - position: 'relative' - }); - - // bind image navigation arrows - this.$( 'image-nav-right, image-nav-left' ).on( 'click:fast', function(e) { - - // pause if options is set - if ( options.pauseOnInteraction ) { - self.pause(); - } - - // navigate - var fn = /right/.test( this.className ) ? 'next' : 'prev'; - self[ fn ](); - - }).on('click', function(e) { - - e.preventDefault(); - - // tune the clicknext option - if ( options.clicknext || options.swipe ) { - e.stopPropagation(); - } - }); - - // hide controls if chosen to - $.each( ['info','counter','image-nav'], function( i, el ) { - if ( options[ 'show' + el.substr(0,1).toUpperCase() + el.substr(1).replace(/-/,'') ] === false ) { - Utils.moveOut( self.get( el.toLowerCase() ) ); - } - }); - - // load up target content - this.load(); - - // now it's usually safe to remove the content - // IE will never stop loading if we remove it, so let's keep it hidden for IE (it's usually fast enough anyway) - if ( !options.keepSource && !IE ) { - this._target.innerHTML = ''; - } - - // re-append the errors, if they happened before clearing - if ( this.get( 'errors' ) ) { - this.appendChild( 'target', 'errors' ); - } - - // append the gallery frame - this.appendChild( 'target', 'container' ); - - // parse the carousel on each thumb load - if ( options.carousel ) { - var count = 0, - show = options.show; - this.bind( Galleria.THUMBNAIL, function() { - this.updateCarousel(); - if ( ++count == this.getDataLength() && typeof show == 'number' && show > 0 ) { - this._carousel.follow( show ); - } - }); - } - - // bind window resize for responsiveness - if ( options.responsive ) { - $win.on( 'resize', function() { - if ( !self.isFullscreen() ) { - self.resize(); - } - }); - } - - // double-tap/click fullscreen toggle - - if ( options.fullscreenDoubleTap ) { - - this.$( 'stage' ).on( 'touchstart', (function() { - var last, cx, cy, lx, ly, now, - getData = function(e) { - return e.originalEvent.touches ? e.originalEvent.touches[0] : e; - }; - self.$( 'stage' ).on('touchmove', function() { - last = 0; - }); - return function(e) { - if( /(-left|-right)/.test(e.target.className) ) { - return; - } - now = Utils.timestamp(); - cx = getData(e).pageX; - cy = getData(e).pageY; - if ( e.originalEvent.touches.length < 2 && ( now - last < 300 ) && ( cx - lx < 20) && ( cy - ly < 20) ) { - self.toggleFullscreen(); - e.preventDefault(); - return; - } - last = now; - lx = cx; - ly = cy; - }; - }())); - } - - // bind the ons - $.each( Galleria.on.binds, function(i, bind) { - // check if already bound - if ( $.inArray( bind.hash, self._binds ) == -1 ) { - self.bind( bind.type, bind.callback ); - } - }); - - return this; - }, - - addTimer : function() { - this._timer.add.apply( this._timer, Utils.array( arguments ) ); - return this; - }, - - clearTimer : function() { - this._timer.clear.apply( this._timer, Utils.array( arguments ) ); - return this; - }, - - // parse width & height from CSS or options - - _getWH : function() { - - var $container = this.$( 'container' ), - $target = this.$( 'target' ), - self = this, - num = {}, - arr; - - $.each(['width', 'height'], function( i, m ) { - - // first check if options is set - if ( self._options[ m ] && typeof self._options[ m ] === 'number') { - num[ m ] = self._options[ m ]; - } else { - - arr = [ - Utils.parseValue( $container.css( m ) ), // the container css height - Utils.parseValue( $target.css( m ) ), // the target css height - $container[ m ](), // the container jQuery method - $target[ m ]() // the target jQuery method - ]; - - // if first time, include the min-width & min-height - if ( !self[ '_'+m ] ) { - arr.splice(arr.length, - Utils.parseValue( $container.css( 'min-'+m ) ), - Utils.parseValue( $target.css( 'min-'+m ) ) - ); - } - - // else extract the measures from different sources and grab the highest value - num[ m ] = M.max.apply( M, arr ); - } - }); - - // allow setting a height ratio instead of exact value - // useful when doing responsive galleries - - if ( self._userRatio ) { - num.height = num.width * self._userRatio; - } - - return num; - }, - - // Creates the thumbnails and carousel - // can be used at any time, f.ex when the data object is manipulated - // push is an optional argument with pushed images - - _createThumbnails : function( push ) { - - this.get( 'total' ).innerHTML = this.getDataLength(); - - var src, - thumb, - data, - - $container, - - self = this, - o = this._options, - - i = push ? this._data.length - push.length : 0, - chunk = i, - - thumbchunk = [], - loadindex = 0, - - gif = IE < 8 ? 'http://upload.wikimedia.org/wikipedia/commons/c/c0/Blank.gif' : - 'data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw%3D%3D', - - // get previously active thumbnail, if exists - active = (function() { - var a = self.$('thumbnails').find('.active'); - if ( !a.length ) { - return false; - } - return a.find('img').attr('src'); - }()), - - // cache the thumbnail option - optval = typeof o.thumbnails === 'string' ? o.thumbnails.toLowerCase() : null, - - // move some data into the instance - // for some reason, jQuery cant handle css(property) when zooming in FF, breaking the gallery - // so we resort to getComputedStyle for browsers who support it - getStyle = function( prop ) { - return doc.defaultView && doc.defaultView.getComputedStyle ? - doc.defaultView.getComputedStyle( thumb.container, null )[ prop ] : - $container.css( prop ); - }, - - fake = function(image, index, container) { - return function() { - $( container ).append( image ); - self.trigger({ - type: Galleria.THUMBNAIL, - thumbTarget: image, - index: index, - galleriaData: self.getData( index ) - }); - }; - }, - - onThumbEvent = function( e ) { - - // pause if option is set - if ( o.pauseOnInteraction ) { - self.pause(); - } - - // extract the index from the data - var index = $( e.currentTarget ).data( 'index' ); - if ( self.getIndex() !== index ) { - self.show( index ); - } - - e.preventDefault(); - }, - - thumbComplete = function( thumb, callback ) { - - $( thumb.container ).css( 'visibility', 'visible' ); - self.trigger({ - type: Galleria.THUMBNAIL, - thumbTarget: thumb.image, - index: thumb.data.order, - galleriaData: self.getData( thumb.data.order ) - }); - - if ( typeof callback == 'function' ) { - callback.call( self, thumb ); - } - }, - - onThumbLoad = function( thumb, callback ) { - - // scale when ready - thumb.scale({ - width: thumb.data.width, - height: thumb.data.height, - crop: o.thumbCrop, - margin: o.thumbMargin, - canvas: o.useCanvas, - position: o.thumbPosition, - complete: function( thumb ) { - - // shrink thumbnails to fit - var top = ['left', 'top'], - arr = ['Width', 'Height'], - m, - css, - data = self.getData( thumb.index ); - - // calculate shrinked positions - $.each(arr, function( i, measure ) { - m = measure.toLowerCase(); - if ( (o.thumbCrop !== true || o.thumbCrop === m ) ) { - css = {}; - css[ m ] = thumb[ m ]; - $( thumb.container ).css( css ); - css = {}; - css[ top[ i ] ] = 0; - $( thumb.image ).css( css ); - } - - // cache outer measures - thumb[ 'outer' + measure ] = $( thumb.container )[ 'outer' + measure ]( true ); - }); - - // set high quality if downscale is moderate - Utils.toggleQuality( thumb.image, - o.thumbQuality === true || - ( o.thumbQuality === 'auto' && thumb.original.width < thumb.width * 3 ) - ); - - if ( o.thumbDisplayOrder && !thumb.lazy ) { - - $.each( thumbchunk, function( i, th ) { - if ( i === loadindex && th.ready && !th.displayed ) { - - loadindex++; - th.displayed = true; - - thumbComplete( th, callback ); - - return; - } - }); - } else { - thumbComplete( thumb, callback ); - } - } - }); - }; - - if ( !push ) { - this._thumbnails = []; - this.$( 'thumbnails' ).empty(); - } - - // loop through data and create thumbnails - for( ; this._data[ i ]; i++ ) { - - data = this._data[ i ]; - - // get source from thumb or image - src = data.thumb || data.image; - - if ( ( o.thumbnails === true || optval == 'lazy' ) && ( data.thumb || data.image ) ) { - - // add a new Picture instance - thumb = new Galleria.Picture(i); - - // save the index - thumb.index = i; - - // flag displayed - thumb.displayed = false; - - // flag lazy - thumb.lazy = false; - - // flag video - thumb.video = false; - - // append the thumbnail - this.$( 'thumbnails' ).append( thumb.container ); - - // cache the container - $container = $( thumb.container ); - - // hide it - $container.css( 'visibility', 'hidden' ); - - thumb.data = { - width : Utils.parseValue( getStyle( 'width' ) ), - height : Utils.parseValue( getStyle( 'height' ) ), - order : i, - src : src - }; - - // grab & reset size for smoother thumbnail loads - if ( o.thumbCrop !== true ) { - $container.css( { width: 'auto', height: 'auto' } ); - } else { - $container.css( { width: thumb.data.width, height: thumb.data.height } ); - } - - // load the thumbnail - if ( optval == 'lazy' ) { - - $container.addClass( 'lazy' ); - - thumb.lazy = true; - - thumb.load( gif, { - height: thumb.data.height, - width: thumb.data.width - }); - - } else { - thumb.load( src, onThumbLoad ); - } - - // preload all images here - if ( o.preload === 'all' ) { - thumb.preload( data.image ); - } - - // create empty spans if thumbnails is set to 'empty' - } else if ( ( data.iframe && optval !== null ) || optval === 'empty' || optval === 'numbers' ) { - thumb = { - container: Utils.create( 'galleria-image' ), - image: Utils.create( 'img', 'span' ), - ready: true, - data: { - order: i - } - }; - - // create numbered thumbnails - if ( optval === 'numbers' ) { - $( thumb.image ).text( i + 1 ); - } - - if ( data.iframe ) { - $( thumb.image ).addClass( 'iframe' ); - } - - this.$( 'thumbnails' ).append( thumb.container ); - - // we need to "fake" a loading delay before we append and trigger - // 50+ should be enough - - window.setTimeout( ( fake )( thumb.image, i, thumb.container ), 50 + ( i*20 ) ); - - // create null object to silent errors - } else { - thumb = { - container: null, - image: null - }; - } - - // add events for thumbnails - // you can control the event type using thumb_event_type - // we'll add the same event to the source if it's kept - - $( thumb.container ).add( o.keepSource && o.linkSourceImages ? data.original : null ) - .data('index', i).on( o.thumbEventType, onThumbEvent ) - .data('thumbload', onThumbLoad); - - if (active === src) { - $( thumb.container ).addClass( 'active' ); - } - - this._thumbnails.push( thumb ); - } - - thumbchunk = this._thumbnails.slice( chunk ); - - return this; - }, - - /** - Lazy-loads thumbnails. - You can call this method to load lazy thumbnails at run time - - @param {Array|Number} index Index or array of indexes of thumbnails to be loaded - @param {Function} complete Callback that is called when all lazy thumbnails have been loaded - - @returns Instance - */ - - lazyLoad: function( index, complete ) { - - var arr = index.constructor == Array ? index : [ index ], - self = this, - loaded = 0; - - $.each( arr, function(i, ind) { - - if ( ind > self._thumbnails.length - 1 ) { - return; - } - - var thumb = self._thumbnails[ ind ], - data = thumb.data, - callback = function() { - if ( ++loaded == arr.length && typeof complete == 'function' ) { - complete.call( self ); - } - }, - thumbload = $( thumb.container ).data( 'thumbload' ); - if ( thumb.video ) { - thumbload.call( self, thumb, callback ); - } else { - thumb.load( data.src , function( thumb ) { - thumbload.call( self, thumb, callback ); - }); - } - }); - - return this; - - }, - - /** - Lazy-loads thumbnails in chunks. - This method automatcally chops up the loading process of many thumbnails into chunks - - @param {Number} size Size of each chunk to be loaded - @param {Number} [delay] Delay between each loads - - @returns Instance - */ - - lazyLoadChunks: function( size, delay ) { - - var len = this.getDataLength(), - i = 0, - n = 0, - arr = [], - temp = [], - self = this; - - delay = delay || 0; - - for( ; i 50 ); // what is an acceptable height? - }, - - success: function() { - - // save the instance - _galleries.push( self ); - - // postrun some stuff after the gallery is ready - - // create the touch slider - if ( self._options.swipe ) { - - var $images = self.$( 'images' ).width( self.getDataLength() * self._stageWidth ); - $.each( new Array( self.getDataLength() ), function(i) { - - var image = new Galleria.Picture(), - data = self.getData(i); - - $( image.container ).css({ - position: 'absolute', - top: 0, - left: self._stageWidth*i - }).prepend( self._layers[i] = $( Utils.create('galleria-layer') ).css({ - position: 'absolute', - top:0, left:0, right:0, bottom:0, - zIndex:2 - })[0] ).appendTo( $images ); - - if( data.video ) { - _playIcon( image.container ); - } - - self._controls.slides.push(image); - - var frame = new Galleria.Picture(); - frame.isIframe = true; - - $( frame.container ).attr('class', 'galleria-frame').css({ - position: 'absolute', - top: 0, - left: 0, - zIndex: 4, - background: '#000', - display: 'none' - }).appendTo( image.container ); - - self._controls.frames.push(frame); - }); - - self.finger.setup(); - } - - // show counter - Utils.show( self.get('counter') ); - - // bind carousel nav - if ( self._options.carousel ) { - self._carousel.bindControls(); - } - - // start autoplay - if ( self._options.autoplay ) { - - self.pause(); - - if ( typeof self._options.autoplay === 'number' ) { - self._playtime = self._options.autoplay; - } - - self._playing = true; - } - // if second load, just do the show and return - if ( self._firstrun ) { - - if ( self._options.autoplay ) { - self.trigger( Galleria.PLAY ); - } - - if ( typeof self._options.show === 'number' ) { - self.show( self._options.show ); - } - return; - } - - self._firstrun = true; - - // initialize the History plugin - if ( Galleria.History ) { - - // bind the show method - Galleria.History.change(function( value ) { - - // if ID is NaN, the user pressed back from the first image - // return to previous address - if ( isNaN( value ) ) { - window.history.go(-1); - - // else show the image - } else { - self.show( value, undef, true ); - } - }); - } - - self.trigger( Galleria.READY ); - - // call the theme init method - self.theme.init.call( self, self._options ); - - // Trigger Galleria.ready - $.each( Galleria.ready.callbacks, function(i ,fn) { - if ( typeof fn == 'function' ) { - fn.call( self, self._options ); - } - }); - - // call the extend option - self._options.extend.call( self, self._options ); - - // show the initial image - // first test for permalinks in history - if ( /^[0-9]{1,4}$/.test( HASH ) && Galleria.History ) { - self.show( HASH, undef, true ); - - } else if( self._data[ self._options.show ] ) { - self.show( self._options.show ); - } - - // play trigger - if ( self._options.autoplay ) { - self.trigger( Galleria.PLAY ); - } - }, - - error: function() { - Galleria.raise('Stage width or height is too small to show the gallery. Traced measures: width:' + self._stageWidth + 'px, height: ' + self._stageHeight + 'px.', true); - } - - }); - }, - - /** - Loads data into the gallery. - You can call this method on an existing gallery to reload the gallery with new data. - - @param {Array|string} [source] Optional JSON array of data or selector of where to find data in the document. - Defaults to the Galleria target or dataSource option. - - @param {string} [selector] Optional element selector of what elements to parse. - Defaults to 'img'. - - @param {Function} [config] Optional function to modify the data extraction proceedure from the selector. - See the dataConfig option for more information. - - @returns Instance - */ - - load : function( source, selector, config ) { - - var self = this, - o = this._options; - - // empty the data array - this._data = []; - - // empty the thumbnails - this._thumbnails = []; - this.$('thumbnails').empty(); - - // shorten the arguments - if ( typeof selector === 'function' ) { - config = selector; - selector = null; - } - - // use the source set by target - source = source || o.dataSource; - - // use selector set by option - selector = selector || o.dataSelector; - - // use the dataConfig set by option - config = config || o.dataConfig; - - // if source is a true object, make it into an array - if( $.isPlainObject( source ) ) { - source = [source]; - } - - // check if the data is an array already - if ( $.isArray( source ) ) { - if ( this.validate( source ) ) { - this._data = source; - } else { - Galleria.raise( 'Load failed: JSON Array not valid.' ); - } - } else { - - // add .video and .iframe to the selector (1.2.7) - selector += ',.video,.iframe'; - - // loop through images and set data - $( source ).find( selector ).each( function( i, elem ) { - - elem = $( elem ); - var data = {}, - parent = elem.parent(), - href = parent.attr( 'href' ), - rel = parent.attr( 'rel' ); - - if( href && ( elem[0].nodeName == 'IMG' || elem.hasClass('video') ) && _videoTest( href ) ) { - data.video = href; - } else if( href && elem.hasClass('iframe') ) { - data.iframe = href; - } else { - data.image = data.big = href; - } - - if ( rel ) { - data.big = rel; - } - - // alternative extraction from HTML5 data attribute, added in 1.2.7 - $.each( 'big title description link layer image'.split(' '), function( i, val ) { - if ( elem.data(val) ) { - data[ val ] = elem.data(val).toString(); - } - }); - - if ( !data.big ) { - data.big = data.image; - } - - // mix default extractions with the hrefs and config - // and push it into the data array - self._data.push( $.extend({ - - title: elem.attr('title') || '', - thumb: elem.attr('src'), - image: elem.attr('src'), - big: elem.attr('src'), - description: elem.attr('alt') || '', - link: elem.attr('longdesc'), - original: elem.get(0) // saved as a reference - - }, data, config( elem ) ) ); - - }); - } - - if ( typeof o.dataSort == 'function' ) { - protoArray.sort.call( this._data, o.dataSort ); - } else if ( o.dataSort == 'random' ) { - this._data.sort( function() { - return M.round(M.random())-0.5; - }); - } - - // trigger the DATA event and return - if ( this.getDataLength() ) { - this._parseData( function() { - this.trigger( Galleria.DATA ); - } ); - } - return this; - - }, - - // make sure the data works properly - _parseData : function( callback ) { - - var self = this, - current, - ready = false, - onload = function() { - var complete = true; - $.each( self._data, function( i, data ) { - if ( data.loading ) { - complete = false; - return false; - } - }); - if ( complete && !ready ) { - ready = true; - callback.call( self ); - } - }; - - $.each( this._data, function( i, data ) { - - current = self._data[ i ]; - - // copy image as thumb if no thumb exists - if ( 'thumb' in data === false ) { - current.thumb = data.image; - } - // copy image as big image if no biggie exists - if ( !data.big ) { - current.big = data.image; - } - // parse video - if ( 'video' in data ) { - var result = _videoTest( data.video ); - - if ( result ) { - current.iframe = new Video(result.provider, result.id ).embed() + (function() { - - // add options - if ( typeof self._options[ result.provider ] == 'object' ) { - var str = '?', arr = []; - $.each( self._options[ result.provider ], function( key, val ) { - arr.push( key + '=' + val ); - }); - - // small youtube specifics, perhaps move to _video later - if ( result.provider == 'youtube' ) { - arr = ['wmode=opaque'].concat(arr); - } - return str + arr.join('&'); - } - return ''; - }()); - - // pre-fetch video providers media - - if( !current.thumb || !current.image ) { - $.each( ['thumb', 'image'], function( i, type ) { - if ( type == 'image' && !self._options.videoPoster ) { - current.image = undef; - return; - } - var video = new Video( result.provider, result.id ); - if ( !current[ type ] ) { - current.loading = true; - video.getMedia( type, (function(current, type) { - return function(src) { - current[ type ] = src; - if ( type == 'image' && !current.big ) { - current.big = current.image; - } - delete current.loading; - onload(); - }; - }( current, type ))); - } - }); - } - } - } - }); - - onload(); - - return this; - }, - - /** - Destroy the Galleria instance and recover the original content - - @example this.destroy(); - - @returns Instance - */ - - destroy : function() { - this.$( 'target' ).data( 'galleria', null ); - this.$( 'container' ).off( 'galleria' ); - this.get( 'target' ).innerHTML = this._original.html; - this.clearTimer(); - Utils.removeFromArray( _instances, this ); - Utils.removeFromArray( _galleries, this ); - if ( Galleria._waiters.length ) { - $.each( Galleria._waiters, function( i, w ) { - if ( w ) window.clearTimeout( w ); - }); - } - return this; - }, - - /** - Adds and/or removes images from the gallery - Works just like Array.splice - https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/splice - - @example this.splice( 2, 4 ); // removes 4 images after the second image - - @returns Instance - */ - - splice : function() { - var self = this, - args = Utils.array( arguments ); - window.setTimeout(function() { - protoArray.splice.apply( self._data, args ); - self._parseData( function() { - self._createThumbnails(); - }); - },2); - return self; - }, - - /** - Append images to the gallery - Works just like Array.push - https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/push - - @example this.push({ image: 'image1.jpg' }); // appends the image to the gallery - - @returns Instance - */ - - push : function() { - var self = this, - args = Utils.array( arguments ); - - if ( args.length == 1 && args[0].constructor == Array ) { - args = args[0]; - } - - window.setTimeout(function() { - protoArray.push.apply( self._data, args ); - self._parseData( function() { - self._createThumbnails( args ); - }); - }, 2); - return self; - }, - - _getActive : function() { - return this._controls.getActive(); - }, - - validate : function( data ) { - // todo: validate a custom data array - return true; - }, - - /** - Bind any event to Galleria - - @param {string} type The Event type to listen for - @param {Function} fn The function to execute when the event is triggered - - @example this.bind( 'image', function() { Galleria.log('image shown') }); - - @returns Instance - */ - - bind : function(type, fn) { - - // allow 'image' instead of Galleria.IMAGE - type = _patchEvent( type ); - - this.$( 'container' ).on( type, this.proxy(fn) ); - return this; - }, - - /** - Unbind any event to Galleria - - @param {string} type The Event type to forget - - @returns Instance - */ - - unbind : function(type) { - - type = _patchEvent( type ); - - this.$( 'container' ).off( type ); - return this; - }, - - /** - Manually trigger a Galleria event - - @param {string} type The Event to trigger - - @returns Instance - */ - - trigger : function( type ) { - - type = typeof type === 'object' ? - $.extend( type, { scope: this } ) : - { type: _patchEvent( type ), scope: this }; - - this.$( 'container' ).trigger( type ); - - return this; - }, - - /** - Assign an "idle state" to any element. - The idle state will be applied after a certain amount of idle time - Useful to hide f.ex navigation when the gallery is inactive - - @param {HTMLElement|string} elem The Dom node or selector to apply the idle state to - @param {Object} styles the CSS styles to apply when in idle mode - @param {Object} [from] the CSS styles to apply when in normal - @param {Boolean} [hide] set to true if you want to hide it first - - @example addIdleState( this.get('image-nav'), { opacity: 0 }); - @example addIdleState( '.galleria-image-nav', { top: -200 }, true); - - @returns Instance - */ - - addIdleState: function( elem, styles, from, hide ) { - this._idle.add.apply( this._idle, Utils.array( arguments ) ); - return this; - }, - - /** - Removes any idle state previously set using addIdleState() - - @param {HTMLElement|string} elem The Dom node or selector to remove the idle state from. - - @returns Instance - */ - - removeIdleState: function( elem ) { - this._idle.remove.apply( this._idle, Utils.array( arguments ) ); - return this; - }, - - /** - Force Galleria to enter idle mode. - - @returns Instance - */ - - enterIdleMode: function() { - this._idle.hide(); - return this; - }, - - /** - Force Galleria to exit idle mode. - - @returns Instance - */ - - exitIdleMode: function() { - this._idle.showAll(); - return this; - }, - - /** - Enter FullScreen mode - - @param {Function} callback the function to be executed when the fullscreen mode is fully applied. - - @returns Instance - */ - - enterFullscreen: function( callback ) { - this._fullscreen.enter.apply( this, Utils.array( arguments ) ); - return this; - }, - - /** - Exits FullScreen mode - - @param {Function} callback the function to be executed when the fullscreen mode is fully applied. - - @returns Instance - */ - - exitFullscreen: function( callback ) { - this._fullscreen.exit.apply( this, Utils.array( arguments ) ); - return this; - }, - - /** - Toggle FullScreen mode - - @param {Function} callback the function to be executed when the fullscreen mode is fully applied or removed. - - @returns Instance - */ - - toggleFullscreen: function( callback ) { - this._fullscreen[ this.isFullscreen() ? 'exit' : 'enter'].apply( this, Utils.array( arguments ) ); - return this; - }, - - /** - Adds a tooltip to any element. - You can also call this method with an object as argument with elemID:value pairs to apply tooltips to (see examples) - - @param {HTMLElement} elem The DOM Node to attach the event to - @param {string|Function} value The tooltip message. Can also be a function that returns a string. - - @example this.bindTooltip( this.get('thumbnails'), 'My thumbnails'); - @example this.bindTooltip( this.get('thumbnails'), function() { return 'My thumbs' }); - @example this.bindTooltip( { image_nav: 'Navigation' }); - - @returns Instance - */ - - bindTooltip: function( elem, value ) { - this._tooltip.bind.apply( this._tooltip, Utils.array(arguments) ); - return this; - }, - - /** - Note: this method is deprecated. Use refreshTooltip() instead. - - Redefine a tooltip. - Use this if you want to re-apply a tooltip value to an already bound tooltip element. - - @param {HTMLElement} elem The DOM Node to attach the event to - @param {string|Function} value The tooltip message. Can also be a function that returns a string. - - @returns Instance - */ - - defineTooltip: function( elem, value ) { - this._tooltip.define.apply( this._tooltip, Utils.array(arguments) ); - return this; - }, - - /** - Refresh a tooltip value. - Use this if you want to change the tooltip value at runtime, f.ex if you have a play/pause toggle. - - @param {HTMLElement} elem The DOM Node that has a tooltip that should be refreshed - - @returns Instance - */ - - refreshTooltip: function( elem ) { - this._tooltip.show.apply( this._tooltip, Utils.array(arguments) ); - return this; - }, - - /** - Open a pre-designed lightbox with the currently active image. - You can control some visuals using gallery options. - - @returns Instance - */ - - openLightbox: function() { - this._lightbox.show.apply( this._lightbox, Utils.array( arguments ) ); - return this; - }, - - /** - Close the lightbox. - - @returns Instance - */ - - closeLightbox: function() { - this._lightbox.hide.apply( this._lightbox, Utils.array( arguments ) ); - return this; - }, - - /** - Check if a variation exists - - @returns {Boolean} If the variation has been applied - */ - - hasVariation: function( variation ) { - return $.inArray( variation, this._options.variation.split(/\s+/) ) > -1; - }, - - /** - Get the currently active image element. - - @returns {HTMLElement} The image element - */ - - getActiveImage: function() { - var active = this._getActive(); - return active ? active.image : undef; - }, - - /** - Get the currently active thumbnail element. - - @returns {HTMLElement} The thumbnail element - */ - - getActiveThumb: function() { - return this._thumbnails[ this._active ].image || undef; - }, - - /** - Get the mouse position relative to the gallery container - - @param e The mouse event - - @example - -var gallery = this; -$(document).mousemove(function(e) { - console.log( gallery.getMousePosition(e).x ); -}); - - @returns {Object} Object with x & y of the relative mouse postion - */ - - getMousePosition : function(e) { - return { - x: e.pageX - this.$( 'container' ).offset().left, - y: e.pageY - this.$( 'container' ).offset().top - }; - }, - - /** - Adds a panning effect to the image - - @param [img] The optional image element. If not specified it takes the currently active image - - @returns Instance - */ - - addPan : function( img ) { - - if ( this._options.imageCrop === false ) { - return; - } - - img = $( img || this.getActiveImage() ); - - // define some variables and methods - var self = this, - x = img.width() / 2, - y = img.height() / 2, - destX = parseInt( img.css( 'left' ), 10 ), - destY = parseInt( img.css( 'top' ), 10 ), - curX = destX || 0, - curY = destY || 0, - distX = 0, - distY = 0, - active = false, - ts = Utils.timestamp(), - cache = 0, - move = 0, - - // positions the image - position = function( dist, cur, pos ) { - if ( dist > 0 ) { - move = M.round( M.max( dist * -1, M.min( 0, cur ) ) ); - if ( cache !== move ) { - - cache = move; - - if ( IE === 8 ) { // scroll is faster for IE - img.parent()[ 'scroll' + pos ]( move * -1 ); - } else { - var css = {}; - css[ pos.toLowerCase() ] = move; - img.css(css); - } - } - } - }, - - // calculates mouse position after 50ms - calculate = function(e) { - if (Utils.timestamp() - ts < 50) { - return; - } - active = true; - x = self.getMousePosition(e).x; - y = self.getMousePosition(e).y; - }, - - // the main loop to check - loop = function(e) { - - if (!active) { - return; - } - - distX = img.width() - self._stageWidth; - distY = img.height() - self._stageHeight; - destX = x / self._stageWidth * distX * -1; - destY = y / self._stageHeight * distY * -1; - curX += ( destX - curX ) / self._options.imagePanSmoothness; - curY += ( destY - curY ) / self._options.imagePanSmoothness; - - position( distY, curY, 'Top' ); - position( distX, curX, 'Left' ); - - }; - - // we need to use scroll in IE8 to speed things up - if ( IE === 8 ) { - - img.parent().scrollTop( curY * -1 ).scrollLeft( curX * -1 ); - img.css({ - top: 0, - left: 0 - }); - - } - - // unbind and bind event - this.$( 'stage' ).off( 'mousemove', calculate ).on( 'mousemove', calculate ); - - // loop the loop - this.addTimer( 'pan' + self._id, loop, 50, true); - - return this; - }, - - /** - Brings the scope into any callback - - @param fn The callback to bring the scope into - @param [scope] Optional scope to bring - - @example $('#fullscreen').click( this.proxy(function() { this.enterFullscreen(); }) ) - - @returns {Function} Return the callback with the gallery scope - */ - - proxy : function( fn, scope ) { - if ( typeof fn !== 'function' ) { - return F; - } - scope = scope || this; - return function() { - return fn.apply( scope, Utils.array( arguments ) ); - }; - }, - - /** - Tells you the theme name of the gallery - - @returns {String} theme name - */ - - getThemeName : function() { - return this.theme.name; - }, - - /** - Removes the panning effect set by addPan() - - @returns Instance - */ - - removePan: function() { - - // todo: doublecheck IE8 - - this.$( 'stage' ).off( 'mousemove' ); - - this.clearTimer( 'pan' + this._id ); - - return this; - }, - - /** - Adds an element to the Galleria DOM array. - When you add an element here, you can access it using element ID in many API calls - - @param {string} id The element ID you wish to use. You can add many elements by adding more arguments. - - @example addElement('mybutton'); - @example addElement('mybutton','mylink'); - - @returns Instance - */ - - addElement : function( id ) { - - var dom = this._dom; - - $.each( Utils.array(arguments), function( i, blueprint ) { - dom[ blueprint ] = Utils.create( 'galleria-' + blueprint ); - }); - - return this; - }, - - /** - Attach keyboard events to Galleria - - @param {Object} map The map object of events. - Possible keys are 'UP', 'DOWN', 'LEFT', 'RIGHT', 'RETURN', 'ESCAPE', 'BACKSPACE', and 'SPACE'. - - @example - -this.attachKeyboard({ - right: this.next, - left: this.prev, - up: function() { - console.log( 'up key pressed' ) - } -}); - - @returns Instance - */ - - attachKeyboard : function( map ) { - this._keyboard.attach.apply( this._keyboard, Utils.array( arguments ) ); - return this; - }, - - /** - Detach all keyboard events to Galleria - - @returns Instance - */ - - detachKeyboard : function() { - this._keyboard.detach.apply( this._keyboard, Utils.array( arguments ) ); - return this; - }, - - /** - Fast helper for appending galleria elements that you added using addElement() - - @param {string} parentID The parent element ID where the element will be appended - @param {string} childID the element ID that should be appended - - @example this.addElement('myElement'); - this.appendChild( 'info', 'myElement' ); - - @returns Instance - */ - - appendChild : function( parentID, childID ) { - this.$( parentID ).append( this.get( childID ) || childID ); - return this; - }, - - /** - Fast helper for prepending galleria elements that you added using addElement() - - @param {string} parentID The parent element ID where the element will be prepended - @param {string} childID the element ID that should be prepended - - @example - -this.addElement('myElement'); -this.prependChild( 'info', 'myElement' ); - - @returns Instance - */ - - prependChild : function( parentID, childID ) { - this.$( parentID ).prepend( this.get( childID ) || childID ); - return this; - }, - - /** - Remove an element by blueprint - - @param {string} elemID The element to be removed. - You can remove multiple elements by adding arguments. - - @returns Instance - */ - - remove : function( elemID ) { - this.$( Utils.array( arguments ).join(',') ).remove(); - return this; - }, - - // a fast helper for building dom structures - // leave this out of the API for now - - append : function( data ) { - var i, j; - for( i in data ) { - if ( data.hasOwnProperty( i ) ) { - if ( data[i].constructor === Array ) { - for( j = 0; data[i][j]; j++ ) { - this.appendChild( i, data[i][j] ); - } - } else { - this.appendChild( i, data[i] ); - } - } - } - return this; - }, - - // an internal helper for scaling according to options - _scaleImage : function( image, options ) { - - image = image || this._controls.getActive(); - - // janpub (JH) fix: - // image might be unselected yet - // e.g. when external logics rescales the gallery on window resize events - if( !image ) { - return; - } - - var complete, - - scaleLayer = function( img ) { - $( img.container ).children(':first').css({ - top: M.max(0, Utils.parseValue( img.image.style.top )), - left: M.max(0, Utils.parseValue( img.image.style.left )), - width: Utils.parseValue( img.image.width ), - height: Utils.parseValue( img.image.height ) - }); - }; - - options = $.extend({ - width: this._stageWidth, - height: this._stageHeight, - crop: this._options.imageCrop, - max: this._options.maxScaleRatio, - min: this._options.minScaleRatio, - margin: this._options.imageMargin, - position: this._options.imagePosition, - iframelimit: this._options.maxVideoSize - }, options ); - - if ( this._options.layerFollow && this._options.imageCrop !== true ) { - - if ( typeof options.complete == 'function' ) { - complete = options.complete; - options.complete = function() { - complete.call( image, image ); - scaleLayer( image ); - }; - } else { - options.complete = scaleLayer; - } - - } else { - $( image.container ).children(':first').css({ top: 0, left: 0 }); - } - - image.scale( options ); - return this; - }, - - /** - Updates the carousel, - useful if you resize the gallery and want to re-check if the carousel nav is needed. - - @returns Instance - */ - - updateCarousel : function() { - this._carousel.update(); - return this; - }, - - /** - Resize the entire gallery container - - @param {Object} [measures] Optional object with width/height specified - @param {Function} [complete] The callback to be called when the scaling is complete - - @returns Instance - */ - - resize : function( measures, complete ) { - - if ( typeof measures == 'function' ) { - complete = measures; - measures = undef; - } - - measures = $.extend( { width:0, height:0 }, measures ); - - var self = this, - $container = this.$( 'container' ); - - $.each( measures, function( m, val ) { - if ( !val ) { - $container[ m ]( 'auto' ); - measures[ m ] = self._getWH()[ m ]; - } - }); - - $.each( measures, function( m, val ) { - $container[ m ]( val ); - }); - - return this.rescale( complete ); - - }, - - /** - Rescales the gallery - - @param {number} width The target width - @param {number} height The target height - @param {Function} complete The callback to be called when the scaling is complete - - @returns Instance - */ - - rescale : function( width, height, complete ) { - - var self = this; - - // allow rescale(fn) - if ( typeof width === 'function' ) { - complete = width; - width = undef; - } - - var scale = function() { - - // set stagewidth - self._stageWidth = width || self.$( 'stage' ).width(); - self._stageHeight = height || self.$( 'stage' ).height(); - - if ( self._options.swipe ) { - $.each( self._controls.slides, function(i, img) { - self._scaleImage( img ); - $( img.container ).css('left', self._stageWidth * i); - }); - self.$('images').css('width', self._stageWidth * self.getDataLength()); - } else { - // scale the active image - self._scaleImage(); - } - - if ( self._options.carousel ) { - self.updateCarousel(); - } - - var frame = self._controls.frames[ self._controls.active ]; - - if (frame) { - self._controls.frames[ self._controls.active ].scale({ - width: self._stageWidth, - height: self._stageHeight, - iframelimit: self._options.maxVideoSize - }); - } - - self.trigger( Galleria.RESCALE ); - - if ( typeof complete === 'function' ) { - complete.call( self ); - } - }; - - scale.call( self ); - - return this; - }, - - /** - Refreshes the gallery. - Useful if you change image options at runtime and want to apply the changes to the active image. - - @returns Instance - */ - - refreshImage : function() { - this._scaleImage(); - if ( this._options.imagePan ) { - this.addPan(); - } - return this; - }, - - _preload: function() { - if ( this._options.preload ) { - var p, i, - n = this.getNext(), - ndata; - try { - for ( i = this._options.preload; i > 0; i-- ) { - p = new Galleria.Picture(); - ndata = this.getData( n ); - p.preload( this.isFullscreen() && ndata.big ? ndata.big : ndata.image ); - n = this.getNext( n ); - } - } catch(e) {} - } - }, - - /** - Shows an image by index - - @param {number|boolean} index The index to show - @param {Boolean} rewind A boolean that should be true if you want the transition to go back - - @returns Instance - */ - - show : function( index, rewind, _history ) { - - var swipe = this._options.swipe; - - // do nothing queue is long || index is false || queue is false and transition is in progress - if ( !swipe && - ( this._queue.length > 3 || index === false || ( !this._options.queue && this._queue.stalled ) ) ) { - return; - } - - index = M.max( 0, M.min( parseInt( index, 10 ), this.getDataLength() - 1 ) ); - - rewind = typeof rewind !== 'undefined' ? !!rewind : index < this.getIndex(); - - _history = _history || false; - - // do the history thing and return - if ( !_history && Galleria.History ) { - Galleria.History.set( index.toString() ); - return; - } - - if ( this.finger && index !== this._active ) { - this.finger.to = -( index*this.finger.width ); - this.finger.index = index; - } - this._active = index; - - // we do things a bit simpler in swipe: - if ( swipe ) { - - var data = this.getData(index), - self = this; - if ( !data ) { - return; - } - - var src = this.isFullscreen() && data.big ? data.big : ( data.image || data.iframe ), - image = this._controls.slides[index], - cached = image.isCached( src ), - thumb = this._thumbnails[ index ]; - - var evObj = { - cached: cached, - index: index, - rewind: rewind, - imageTarget: image.image, - thumbTarget: thumb.image, - galleriaData: data - }; - - this.trigger($.extend(evObj, { - type: Galleria.LOADSTART - })); - - self.$('container').removeClass( 'videoplay' ); - - var complete = function() { - - self._layers[index].innerHTML = self.getData().layer || ''; - - self.trigger($.extend(evObj, { - type: Galleria.LOADFINISH - })); - self._playCheck(); - }; - - self._preload(); - - window.setTimeout(function() { - - // load if not ready - if ( !image.ready || $(image.image).attr('src') != src ) { - if ( data.iframe && !data.image ) { - image.isIframe = true; - } - image.load(src, function(image) { - evObj.imageTarget = image.image; - self._scaleImage(image, complete).trigger($.extend(evObj, { - type: Galleria.IMAGE - })); - complete(); - }); - } else { - self.trigger($.extend(evObj, { - type: Galleria.IMAGE - })); - complete(); - } - }, 100); - - } else { - protoArray.push.call( this._queue, { - index : index, - rewind : rewind - }); - if ( !this._queue.stalled ) { - this._show(); - } - } - - return this; - }, - - // the internal _show method does the actual showing - _show : function() { - - // shortcuts - var self = this, - queue = this._queue[ 0 ], - data = this.getData( queue.index ); - - if ( !data ) { - return; - } - - var src = this.isFullscreen() && data.big ? data.big : ( data.image || data.iframe ), - active = this._controls.getActive(), - next = this._controls.getNext(), - cached = next.isCached( src ), - thumb = this._thumbnails[ queue.index ], - mousetrigger = function() { - $( next.image ).trigger( 'mouseup' ); - }; - - self.$('container').toggleClass('iframe', !!data.isIframe).removeClass( 'videoplay' ); - - // to be fired when loading & transition is complete: - var complete = (function( data, next, active, queue, thumb ) { - - return function() { - - var win; - - _transitions.active = false; - - // optimize quality - Utils.toggleQuality( next.image, self._options.imageQuality ); - - // remove old layer - self._layers[ self._controls.active ].innerHTML = ''; - - // swap - $( active.container ).css({ - zIndex: 0, - opacity: 0 - }).show(); - - $( active.container ).find( 'iframe, .galleria-videoicon' ).remove(); - $( self._controls.frames[ self._controls.active ].container ).hide(); - - $( next.container ).css({ - zIndex: 1, - left: 0, - top: 0 - }).show(); - - self._controls.swap(); - - // add pan according to option - if ( self._options.imagePan ) { - self.addPan( next.image ); - } - - // make the image clickable - // order of precedence: iframe, link, lightbox, clicknext - if ( ( data.iframe && data.image ) || data.link || self._options.lightbox || self._options.clicknext ) { - - $( next.image ).css({ - cursor: 'pointer' - }).on( 'mouseup', function( e ) { - - // non-left click - if ( typeof e.which == 'number' && e.which > 1 ) { - return; - } - - // iframe / video - if ( data.iframe ) { - - if ( self.isPlaying() ) { - self.pause(); - } - var frame = self._controls.frames[ self._controls.active ], - w = self._stageWidth, - h = self._stageHeight; - - $( frame.container ).css({ - width: w, - height: h, - opacity: 0 - }).show().animate({ - opacity: 1 - }, 200); - - window.setTimeout(function() { - frame.load( data.iframe + ( data.video ? '&autoplay=1' : '' ), { - width: w, - height: h - }, function( frame ) { - self.$( 'container' ).addClass( 'videoplay' ); - frame.scale({ - width: self._stageWidth, - height: self._stageHeight, - iframelimit: data.video ? self._options.maxVideoSize : undef - }); - }); - }, 100); - - return; - } - - // clicknext - if ( self._options.clicknext && !Galleria.TOUCH ) { - if ( self._options.pauseOnInteraction ) { - self.pause(); - } - self.next(); - return; - } - - // popup link - if ( data.link ) { - if ( self._options.popupLinks ) { - win = window.open( data.link, '_blank' ); - } else { - window.location.href = data.link; - } - return; - } - - if ( self._options.lightbox ) { - self.openLightbox(); - } - - }); - } - - // check if we are playing - self._playCheck(); - - // trigger IMAGE event - self.trigger({ - type: Galleria.IMAGE, - index: queue.index, - imageTarget: next.image, - thumbTarget: thumb.image, - galleriaData: data - }); - - // remove the queued image - protoArray.shift.call( self._queue ); - - // remove stalled - self._queue.stalled = false; - - // if we still have images in the queue, show it - if ( self._queue.length ) { - self._show(); - } - - }; - }( data, next, active, queue, thumb )); - - // let the carousel follow - if ( this._options.carousel && this._options.carouselFollow ) { - this._carousel.follow( queue.index ); - } - - // preload images - self._preload(); - - // show the next image, just in case - Utils.show( next.container ); - - next.isIframe = data.iframe && !data.image; - - // add active classes - $( self._thumbnails[ queue.index ].container ) - .addClass( 'active' ) - .siblings( '.active' ) - .removeClass( 'active' ); - - // trigger the LOADSTART event - self.trigger( { - type: Galleria.LOADSTART, - cached: cached, - index: queue.index, - rewind: queue.rewind, - imageTarget: next.image, - thumbTarget: thumb.image, - galleriaData: data - }); - - // stall the queue - self._queue.stalled = true; - - // begin loading the next image - next.load( src, function( next ) { - - // add layer HTML - var layer = $( self._layers[ 1-self._controls.active ] ).html( data.layer || '' ).hide(); - - self._scaleImage( next, { - - complete: function( next ) { - - // toggle low quality for IE - if ( 'image' in active ) { - Utils.toggleQuality( active.image, false ); - } - Utils.toggleQuality( next.image, false ); - - // remove the image panning, if applied - // TODO: rethink if this is necessary - self.removePan(); - - // set the captions and counter - self.setInfo( queue.index ); - self.setCounter( queue.index ); - - // show the layer now - if ( data.layer ) { - layer.show(); - // inherit click events set on image - if ( ( data.iframe && data.image ) || data.link || self._options.lightbox || self._options.clicknext ) { - layer.css( 'cursor', 'pointer' ).off( 'mouseup' ).mouseup( mousetrigger ); - } - } - - // add play icon - if( data.video && data.image ) { - _playIcon( next.container ); - } - - var transition = self._options.transition; - - // can JavaScript loop through objects in order? yes. - $.each({ - initial: active.image === null, - touch: Galleria.TOUCH, - fullscreen: self.isFullscreen() - }, function( type, arg ) { - if ( arg && self._options[ type + 'Transition' ] !== undef ) { - transition = self._options[ type + 'Transition' ]; - return false; - } - }); - - // validate the transition - if ( transition in _transitions.effects === false ) { - complete(); - } else { - var params = { - prev: active.container, - next: next.container, - rewind: queue.rewind, - speed: self._options.transitionSpeed || 400 - }; - - _transitions.active = true; - - // call the transition function and send some stuff - _transitions.init.call( self, transition, params, complete ); - - } - - // trigger the LOADFINISH event - self.trigger({ - type: Galleria.LOADFINISH, - cached: cached, - index: queue.index, - rewind: queue.rewind, - imageTarget: next.image, - thumbTarget: self._thumbnails[ queue.index ].image, - galleriaData: self.getData( queue.index ) - }); - } - }); - }); - }, - - /** - Gets the next index - - @param {number} [base] Optional starting point - - @returns {number} the next index, or the first if you are at the first (looping) - */ - - getNext : function( base ) { - base = typeof base === 'number' ? base : this.getIndex(); - return base === this.getDataLength() - 1 ? 0 : base + 1; - }, - - /** - Gets the previous index - - @param {number} [base] Optional starting point - - @returns {number} the previous index, or the last if you are at the first (looping) - */ - - getPrev : function( base ) { - base = typeof base === 'number' ? base : this.getIndex(); - return base === 0 ? this.getDataLength() - 1 : base - 1; - }, - - /** - Shows the next image in line - - @returns Instance - */ - - next : function() { - if ( this.getDataLength() > 1 ) { - this.show( this.getNext(), false ); - } - return this; - }, - - /** - Shows the previous image in line - - @returns Instance - */ - - prev : function() { - if ( this.getDataLength() > 1 ) { - this.show( this.getPrev(), true ); - } - return this; - }, - - /** - Retrieve a DOM element by element ID - - @param {string} elemId The delement ID to fetch - - @returns {HTMLElement} The elements DOM node or null if not found. - */ - - get : function( elemId ) { - return elemId in this._dom ? this._dom[ elemId ] : null; - }, - - /** - Retrieve a data object - - @param {number} index The data index to retrieve. - If no index specified it will take the currently active image - - @returns {Object} The data object - */ - - getData : function( index ) { - return index in this._data ? - this._data[ index ] : this._data[ this._active ]; - }, - - /** - Retrieve the number of data items - - @returns {number} The data length - */ - getDataLength : function() { - return this._data.length; - }, - - /** - Retrieve the currently active index - - @returns {number|boolean} The active index or false if none found - */ - - getIndex : function() { - return typeof this._active === 'number' ? this._active : false; - }, - - /** - Retrieve the stage height - - @returns {number} The stage height - */ - - getStageHeight : function() { - return this._stageHeight; - }, - - /** - Retrieve the stage width - - @returns {number} The stage width - */ - - getStageWidth : function() { - return this._stageWidth; - }, - - /** - Retrieve the option - - @param {string} key The option key to retrieve. If no key specified it will return all options in an object. - - @returns option or options - */ - - getOptions : function( key ) { - return typeof key === 'undefined' ? this._options : this._options[ key ]; - }, - - /** - Set options to the instance. - You can set options using a key & value argument or a single object argument (see examples) - - @param {string} key The option key - @param {string} value the the options value - - @example setOptions( 'autoplay', true ) - @example setOptions({ autoplay: true }); - - @returns Instance - */ - - setOptions : function( key, value ) { - if ( typeof key === 'object' ) { - $.extend( this._options, key ); - } else { - this._options[ key ] = value; - } - return this; - }, - - /** - Starts playing the slideshow - - @param {number} delay Sets the slideshow interval in milliseconds. - If you set it once, you can just call play() and get the same interval the next time. - - @returns Instance - */ - - play : function( delay ) { - - this._playing = true; - - this._playtime = delay || this._playtime; - - this._playCheck(); - - this.trigger( Galleria.PLAY ); - - return this; - }, - - /** - Stops the slideshow if currently playing - - @returns Instance - */ - - pause : function() { - - this._playing = false; - - this.trigger( Galleria.PAUSE ); - - return this; - }, - - /** - Toggle between play and pause events. - - @param {number} delay Sets the slideshow interval in milliseconds. - - @returns Instance - */ - - playToggle : function( delay ) { - return ( this._playing ) ? this.pause() : this.play( delay ); - }, - - /** - Checks if the gallery is currently playing - - @returns {Boolean} - */ - - isPlaying : function() { - return this._playing; - }, - - /** - Checks if the gallery is currently in fullscreen mode - - @returns {Boolean} - */ - - isFullscreen : function() { - return this._fullscreen.active; - }, - - _playCheck : function() { - var self = this, - played = 0, - interval = 20, - now = Utils.timestamp(), - timer_id = 'play' + this._id; - - if ( this._playing ) { - - this.clearTimer( timer_id ); - - var fn = function() { - - played = Utils.timestamp() - now; - if ( played >= self._playtime && self._playing ) { - self.clearTimer( timer_id ); - self.next(); - return; - } - if ( self._playing ) { - - // trigger the PROGRESS event - self.trigger({ - type: Galleria.PROGRESS, - percent: M.ceil( played / self._playtime * 100 ), - seconds: M.floor( played / 1000 ), - milliseconds: played - }); - - self.addTimer( timer_id, fn, interval ); - } - }; - self.addTimer( timer_id, fn, interval ); - } - }, - - /** - Modify the slideshow delay - - @param {number} delay the number of milliseconds between slides, - - @returns Instance - */ - - setPlaytime: function( delay ) { - this._playtime = delay; - return this; - }, - - setIndex: function( val ) { - this._active = val; - return this; - }, - - /** - Manually modify the counter - - @param {number} [index] Optional data index to fectch, - if no index found it assumes the currently active index - - @returns Instance - */ - - setCounter: function( index ) { - - if ( typeof index === 'number' ) { - index++; - } else if ( typeof index === 'undefined' ) { - index = this.getIndex()+1; - } - - this.get( 'current' ).innerHTML = index; - - if ( IE ) { // weird IE bug - - var count = this.$( 'counter' ), - opacity = count.css( 'opacity' ); - - if ( parseInt( opacity, 10 ) === 1) { - Utils.removeAlpha( count[0] ); - } else { - this.$( 'counter' ).css( 'opacity', opacity ); - } - - } - - return this; - }, - - /** - Manually set captions - - @param {number} [index] Optional data index to fectch and apply as caption, - if no index found it assumes the currently active index - - @returns Instance - */ - - setInfo : function( index ) { - - var self = this, - data = this.getData( index ); - - $.each( ['title','description'], function( i, type ) { - - var elem = self.$( 'info-' + type ); - - if ( !!data[type] ) { - elem[ data[ type ].length ? 'show' : 'hide' ]().html( data[ type ] ); - } else { - elem.empty().hide(); - } - }); - - return this; - }, - - /** - Checks if the data contains any captions - - @param {number} [index] Optional data index to fectch, - if no index found it assumes the currently active index. - - @returns {boolean} - */ - - hasInfo : function( index ) { - - var check = 'title description'.split(' '), - i; - - for ( i = 0; check[i]; i++ ) { - if ( !!this.getData( index )[ check[i] ] ) { - return true; - } - } - return false; - - }, - - jQuery : function( str ) { - - var self = this, - ret = []; - - $.each( str.split(','), function( i, elemId ) { - elemId = $.trim( elemId ); - - if ( self.get( elemId ) ) { - ret.push( elemId ); - } - }); - - var jQ = $( self.get( ret.shift() ) ); - - $.each( ret, function( i, elemId ) { - jQ = jQ.add( self.get( elemId ) ); - }); - - return jQ; - - }, - - /** - Converts element IDs into a jQuery collection - You can call for multiple IDs separated with commas. - - @param {string} str One or more element IDs (comma-separated) - - @returns jQuery - - @example this.$('info,container').hide(); - */ - - $ : function( str ) { - return this.jQuery.apply( this, Utils.array( arguments ) ); - } - -}; - -// End of Galleria prototype - -// Add events as static variables -$.each( _events, function( i, ev ) { - - // legacy events - var type = /_/.test( ev ) ? ev.replace( /_/g, '' ) : ev; - - Galleria[ ev.toUpperCase() ] = 'galleria.'+type; - -} ); - -$.extend( Galleria, { - - // Browser helpers - IE9: IE === 9, - IE8: IE === 8, - IE7: IE === 7, - IE6: IE === 6, - IE: IE, - WEBKIT: /webkit/.test( NAV ), - CHROME: /chrome/.test( NAV ), - SAFARI: /safari/.test( NAV ) && !(/chrome/.test( NAV )), - QUIRK: ( IE && doc.compatMode && doc.compatMode === "BackCompat" ), - MAC: /mac/.test( navigator.platform.toLowerCase() ), - OPERA: !!window.opera, - IPHONE: /iphone/.test( NAV ), - IPAD: /ipad/.test( NAV ), - ANDROID: /android/.test( NAV ), - TOUCH: ('ontouchstart' in doc) - -}); - -// Galleria static methods - -/** - Adds a theme that you can use for your Gallery - - @param {Object} theme Object that should contain all your theme settings. -
    -
  • name - name of the theme
  • -
  • author - name of the author
  • -
  • css - css file name (not path)
  • -
  • defaults - default options to apply, including theme-specific options
  • -
  • init - the init function
  • -
- - @returns {Object} theme -*/ - -Galleria.addTheme = function( theme ) { - - // make sure we have a name - if ( !theme.name ) { - Galleria.raise('No theme name specified'); - } - - if ( typeof theme.defaults !== 'object' ) { - theme.defaults = {}; - } else { - theme.defaults = _legacyOptions( theme.defaults ); - } - - var css = false, - reg, reg2; - - if ( typeof theme.css === 'string' ) { - - // look for manually added CSS - $('link').each(function( i, link ) { - reg = new RegExp( theme.css ); - if ( reg.test( link.href ) ) { - - // we found the css - css = true; - - // the themeload trigger - _themeLoad( theme ); - - return false; - } - }); - - // else look for the absolute path and load the CSS dynamic - if ( !css ) { - - - $(function() { - // Try to determine the css-path from the theme script. - // In IE8/9, the script-dom-element seems to be not present - // at once, if galleria itself is inserted into the dom - // dynamically. We therefore try multiple times before raising - // an error. - var retryCount = 0; - var tryLoadCss = function() { - $('script').each(function (i, script) { - // look for the theme script - reg = new RegExp('galleria\\.' + theme.name.toLowerCase() + '\\.'); - reg2 = new RegExp('galleria\\.io\\/theme\\/' + theme.name.toLowerCase() + '\\/(\\d*\\.*)?(\\d*\\.*)?(\\d*\\/)?js'); - if (reg.test(script.src) || reg2.test(script.src)) { - // we have a match - css = script.src.replace(/[^\/]*$/, '') + theme.css; - - window.setTimeout(function () { - Utils.loadCSS(css, 'galleria-theme-'+theme.name, function () { - - // run galleries with this theme - _themeLoad(theme); - - }); - }, 1); - } - }); - if (!css) { - if (retryCount++ > 5) { - Galleria.raise('No theme CSS loaded'); - } else { - window.setTimeout(tryLoadCss, 500); - } - } - }; - tryLoadCss(); - }); - } - - } else { - - // pass - _themeLoad( theme ); - } - return theme; -}; - -/** - loadTheme loads a theme js file and attaches a load event to Galleria - - @param {string} src The relative path to the theme source file - - @param {Object} [options] Optional options you want to apply - - @returns Galleria -*/ - -Galleria.loadTheme = function( src, options ) { - - // Don't load if theme is already loaded - if( $('script').filter(function() { return $(this).attr('src') == src; }).length ) { - return; - } - - var loaded = false, - err; - - // start listening for the timeout onload - $( window ).load( function() { - if ( !loaded ) { - // give it another 20 seconds - err = window.setTimeout(function() { - if ( !loaded ) { - Galleria.raise( "Galleria had problems loading theme at " + src + ". Please check theme path or load manually.", true ); - } - }, 20000); - } - }); - - // load the theme - Utils.loadScript( src, function() { - loaded = true; - window.clearTimeout( err ); - }); - - return Galleria; -}; - -/** - Retrieves a Galleria instance. - - @param {number} [index] Optional index to retrieve. - If no index is supplied, the method will return all instances in an array. - - @returns Instance or Array of instances -*/ - -Galleria.get = function( index ) { - if ( !!_instances[ index ] ) { - return _instances[ index ]; - } else if ( typeof index !== 'number' ) { - return _instances; - } else { - Galleria.raise('Gallery index ' + index + ' not found'); - } -}; - -/** - - Configure Galleria options via a static function. - The options will be applied to all instances - - @param {string|object} key The options to apply or a key - - @param [value] If key is a string, this is the value - - @returns Galleria - -*/ - -Galleria.configure = function( key, value ) { - - var opts = {}; - - if( typeof key == 'string' && value ) { - opts[key] = value; - key = opts; - } else { - $.extend( opts, key ); - } - - Galleria.configure.options = opts; - - $.each( Galleria.get(), function(i, instance) { - instance.setOptions( opts ); - }); - - return Galleria; -}; - -Galleria.configure.options = {}; - -/** - - Bind a Galleria event to the gallery - - @param {string} type A string representing the galleria event - - @param {function} callback The function that should run when the event is triggered - - @returns Galleria - -*/ - -Galleria.on = function( type, callback ) { - if ( !type ) { - return; - } - - callback = callback || F; - - // hash the bind - var hash = type + callback.toString().replace(/\s/g,'') + Utils.timestamp(); - - // for existing instances - $.each( Galleria.get(), function(i, instance) { - instance._binds.push( hash ); - instance.bind( type, callback ); - }); - - // for future instances - Galleria.on.binds.push({ - type: type, - callback: callback, - hash: hash - }); - - return Galleria; -}; - -Galleria.on.binds = []; - -/** - - Run Galleria - Alias for $(selector).galleria(options) - - @param {string} selector A selector of element(s) to intialize galleria to - - @param {object} options The options to apply - - @returns Galleria - -*/ - -Galleria.run = function( selector, options ) { - if ( $.isFunction( options ) ) { - options = { extend: options }; - } - $( selector || '#galleria' ).galleria( options ); - return Galleria; -}; - -/** - Creates a transition to be used in your gallery - - @param {string} name The name of the transition that you will use as an option - - @param {Function} fn The function to be executed in the transition. - The function contains two arguments, params and complete. - Use the params Object to integrate the transition, and then call complete when you are done. - - @returns Galleria - -*/ - -Galleria.addTransition = function( name, fn ) { - _transitions.effects[name] = fn; - return Galleria; -}; - -/** - The Galleria utilites -*/ - -Galleria.utils = Utils; - -/** - A helper metod for cross-browser logging. - It uses the console log if available otherwise it falls back to alert - - @example Galleria.log("hello", document.body, [1,2,3]); -*/ - -Galleria.log = function() { - var args = Utils.array( arguments ); - if( 'console' in window && 'log' in window.console ) { - try { - return window.console.log.apply( window.console, args ); - } catch( e ) { - $.each( args, function() { - window.console.log(this); - }); - } - } else { - return window.alert( args.join('
') ); - } -}; - -/** - A ready method for adding callbacks when a gallery is ready - Each method is call before the extend option for every instance - - @param {function} callback The function to call - - @returns Galleria -*/ - -Galleria.ready = function( fn ) { - if ( typeof fn != 'function' ) { - return Galleria; - } - $.each( _galleries, function( i, gallery ) { - fn.call( gallery, gallery._options ); - }); - Galleria.ready.callbacks.push( fn ); - return Galleria; -}; - -Galleria.ready.callbacks = []; - -/** - Method for raising errors - - @param {string} msg The message to throw - - @param {boolean} [fatal] Set this to true to override debug settings and display a fatal error -*/ - -Galleria.raise = function( msg, fatal ) { - - var type = fatal ? 'Fatal error' : 'Error', - - css = { - color: '#fff', - position: 'absolute', - top: 0, - left: 0, - zIndex: 100000 - }, - - echo = function( msg ) { - - var html = '
' + - ( fatal ? '' + type + ': ' : '' ) + - msg + '
'; - - $.each( _instances, function() { - - var cont = this.$( 'errors' ), - target = this.$( 'target' ); - - if ( !cont.length ) { - - target.css( 'position', 'relative' ); - - cont = this.addElement( 'errors' ).appendChild( 'target', 'errors' ).$( 'errors' ).css(css); - } - cont.append( html ); - - }); - - if ( !_instances.length ) { - $('
').css( $.extend( css, { position: 'fixed' } ) ).append( html ).appendTo( DOM().body ); - } - }; - - // if debug is on, display errors and throw exception if fatal - if ( DEBUG ) { - echo( msg ); - if ( fatal ) { - throw new Error(type + ': ' + msg); - } - - // else just echo a silent generic error if fatal - } else if ( fatal ) { - if ( _hasError ) { - return; - } - _hasError = true; - fatal = false; - echo( 'Gallery could not load.' ); - } -}; - -// Add the version -Galleria.version = VERSION; - -Galleria.getLoadedThemes = function() { - return $.map(_loadedThemes, function(theme) { - return theme.name; - }); -}; - -/** - A method for checking what version of Galleria the user has installed and throws a readable error if the user needs to upgrade. - Useful when building plugins that requires a certain version to function. - - @param {number} version The minimum version required - - @param {string} [msg] Optional message to display. If not specified, Galleria will throw a generic error. - - @returns Galleria -*/ - -Galleria.requires = function( version, msg ) { - msg = msg || 'You need to upgrade Galleria to version ' + version + ' to use one or more components.'; - if ( Galleria.version < version ) { - Galleria.raise(msg, true); - } - return Galleria; -}; - -/** - Adds preload, cache, scale and crop functionality - - @constructor - - @requires jQuery - - @param {number} [id] Optional id to keep track of instances -*/ - -Galleria.Picture = function( id ) { - - // save the id - this.id = id || null; - - // the image should be null until loaded - this.image = null; - - // Create a new container - this.container = Utils.create('galleria-image'); - - // add container styles - $( this.container ).css({ - overflow: 'hidden', - position: 'relative' // for IE Standards mode - }); - - // saves the original measurements - this.original = { - width: 0, - height: 0 - }; - - // flag when the image is ready - this.ready = false; - - // flag for iframe Picture - this.isIframe = false; - -}; - -Galleria.Picture.prototype = { - - // the inherited cache object - cache: {}, - - // show the image on stage - show: function() { - Utils.show( this.image ); - }, - - // hide the image - hide: function() { - Utils.moveOut( this.image ); - }, - - clear: function() { - this.image = null; - }, - - /** - Checks if an image is in cache - - @param {string} src The image source path, ex '/path/to/img.jpg' - - @returns {boolean} - */ - - isCached: function( src ) { - return !!this.cache[src]; - }, - - /** - Preloads an image into the cache - - @param {string} src The image source path, ex '/path/to/img.jpg' - - @returns Galleria.Picture - */ - - preload: function( src ) { - $( new Image() ).load((function(src, cache) { - return function() { - cache[ src ] = src; - }; - }( src, this.cache ))).attr( 'src', src ); - }, - - /** - Loads an image and call the callback when ready. - Will also add the image to cache. - - @param {string} src The image source path, ex '/path/to/img.jpg' - @param {Object} [size] The forced size of the image, defined as an object { width: xx, height:xx } - @param {Function} callback The function to be executed when the image is loaded & scaled - - @returns The image container (jQuery object) - */ - - load: function(src, size, callback) { - - if ( typeof size == 'function' ) { - callback = size; - size = null; - } - - if( this.isIframe ) { - var id = 'if'+new Date().getTime(); - - var iframe = this.image = $('