From 817bc2dcff684817380340cc4a18d41143313df3 Mon Sep 17 00:00:00 2001 From: Shelly Cheng Date: Wed, 28 Jun 2023 15:11:38 -0700 Subject: [PATCH] add new template: before and after comparison. closes #19 --- _base/lib/pym.js | 2 +- before_after_comparision/README.md | 79 +++++++ before_after_comparision/graphic.js | 103 +++++++++ before_after_comparision/graphic.less | 204 ++++++++++++++++++ before_after_comparision/index.html | 31 +++ before_after_comparision/manifest.json | 17 ++ .../partials/_beforeafter.html | 38 ++++ before_after_comparision/synced/test1.png | Bin 0 -> 14695 bytes before_after_comparision/synced/test2.png | Bin 0 -> 13630 bytes 9 files changed, 473 insertions(+), 1 deletion(-) create mode 100644 before_after_comparision/README.md create mode 100644 before_after_comparision/graphic.js create mode 100644 before_after_comparision/graphic.less create mode 100644 before_after_comparision/index.html create mode 100644 before_after_comparision/manifest.json create mode 100644 before_after_comparision/partials/_beforeafter.html create mode 100644 before_after_comparision/synced/test1.png create mode 100644 before_after_comparision/synced/test2.png diff --git a/_base/lib/pym.js b/_base/lib/pym.js index 5ffd762..817b6f1 100644 --- a/_base/lib/pym.js +++ b/_base/lib/pym.js @@ -28,7 +28,7 @@ switch (getParameterByName("mode")) { // on the NPR homepage." checkbox when pulling the embed code.) case "hp": document.body.classList.add("hp"); - isHomepage = true; + // isHomepage = true; break; // Direct links to the child page (iOS app workaround link) case "childlink": diff --git a/before_after_comparision/README.md b/before_after_comparision/README.md new file mode 100644 index 0000000..f227307 --- /dev/null +++ b/before_after_comparision/README.md @@ -0,0 +1,79 @@ +Before and After Comparison +======================== + +### About this template + +This template offers an animated toggle between two images (a "before" and an "after") — often useful for comparing satellite imagery between two time periods. + +Columns in the spreadsheet: + +* `key` — A unique one-word descriptor for this pair of before and after images (such as the location the image). This is used as the unique id for each photo embed. +* `headline` - A headline for this pair of before and after images _(optional)_. This is most useful in cases where you are including multiple before/after toggles in the same embed. +* `image1` - The before image filename. We assume that it will live in the `synced/` folder inside the graphic. +* `image1_alt` - Alt text for `image1` +* `label_hed1` — The primary label for the first button. When user clicks the button, `image1` will be displayed. The text for the label is typically "Before." +* `label_dek1` — A secondary label for the first button — typically the date when the `image1` was taken. _(optional)_ +* `image2` - The after image filename. We assume that it will live in the `synced/` folder inside the graphic. +* `image2_alt` - Alt text for `image2` +* `label_hed2` — The primary label for the second button. When user clicks the button, `image2` will be displayed. The text for the label is typically "After." +* `label_dek2` — A secondary label for the second button — typically the date when the `image2` was taken. _(optional)_ +* `photo_credit` — Photo credit for `image1` and `image2`. _(optional)_ + +Key files: + +* `synced/` — All images should go here. (Note: This does not get committed to the repo. Files are published using a separate syncing process. See further below.) +* `partials/_beforeafter.html` — Template code to display each pair of before and after images +* `index.html` — View all before/after comparisons in this project + +----- + +### Creating multiple pairs of before and after images + +Add rows with corresponding attributes in the `data` spreadsheet with a unique `key` value. Then, depending on your desired way of presenting the images: + +#### All pairs appear in the same embed + +By default, `index.html` is set up to show all before/after pairs in the spreadsheet, in the order they're listed in the spreadsheet. + +#### Each pair gets its own embed + +If you want separate embeds for each before/after pair in the spreadsheet: + +* Make a copy of `index.html` and rename it according to the `key` for that row +* Change this section of code: + +``` +<% for (let key of Object.keys(COPY.data)) { %> + <%= await t.include("partials/_beforeafter.html", { COPY: { ...COPY, data: [ COPY.data[key] ]}}) %> +<% } %> +``` + +to: + +``` +<%= await t.include("partials/_beforeafter.html", { COPY: { ...COPY, data: [ COPY.data['KEY_FOR_THIS_ROW'] ]}}) %> +``` + +----- + +### Optimizing images + +Create a folder locally somewhere on your machine with the original-size images. Inside that folder, create a new folder called `resized`. + +Run this ImageMagick script (from our [best practices](https://github.com/nprapps/bestpractices/blob/master/assets.md)) to resize the images: + +``` +for f in *.jpg; do convert $f -quality 75 -resize 1600x1200\> -strip -sampling-factor 4:2:0 -define jpeg:dct-method=float -interlace Plane resized/$f; done +``` + +Save the `resized` images in the `synced` folder in this project. Do not keep the original high-res images here. + +----- + +### Synced files + +For this project, images are synced to S3 rather than stored in the repo. Run this to retrieve / sync them: + +``` +node cli sync $PROJECT_SLUG +``` \ No newline at end of file diff --git a/before_after_comparision/graphic.js b/before_after_comparision/graphic.js new file mode 100644 index 0000000..7a61fbd --- /dev/null +++ b/before_after_comparision/graphic.js @@ -0,0 +1,103 @@ +var pym = require("./lib/pym"); +var ANALYTICS = require("./lib/analytics"); +require("./lib/webfonts"); +var { isMobile } = require("./lib/breakpoints"); + +var pymChild = null; +var isMobile = isMobile.matches; + +/* + * Initialize the graphic. + */ +var onWindowLoaded = function() { + pym.then(function(child) { + pymChild = child; + child.sendHeight(); + window.addEventListener("resize", render); + }); + + initUI(); +} + +/* + * Render the graphic. + */ +var render = function() { + // Update iframe + if (pymChild) { + pymChild.sendHeight(); + } +} + +var initUI = function() { + document.querySelectorAll('.graphic').forEach(function(wrapper) { + var toggleTimeout; + var toggleButtons = wrapper.querySelectorAll('.toggle-btn'); + var splitId = toggleButtons[0].getAttribute('id').split('-'); + + toggleButtons.forEach(function(button) { + button.addEventListener('click', function() { + var parentToggleWrap = button.parentElement; + parentToggleWrap.classList.add('clicked'); + window.clearTimeout(toggleTimeout); + + splitId = button.getAttribute('id').split('-'); + + // select before image by its unique id + var beforeImage = wrapper.querySelector('#image-' + splitId[1] + '-1'); + + if (splitId[2] == '1') { + beforeImage.classList.remove('hidden'); + } else { + beforeImage.classList.add('hidden'); + } + + if (!button.classList.contains('active')) { + let activeToggleBtn = parentToggleWrap.querySelector('.toggle-btn.active'); + if (activeToggleBtn) { + activeToggleBtn.classList.remove('active'); + } + button.classList.add('active'); + } + }); + }); + + var autoToggle = function() { + var stepList = [2, 1, 2, 1, 2]; + toggleStep(0); + + function toggleStep(step_i) { + if (step_i < stepList.length) { + var step = stepList[step_i]; + + if (!wrapper.querySelector('.image-toggle').classList.contains('clicked')) { + // select before image by its unique id + var beforeImage = wrapper.querySelector('#image-' + splitId[1] + '-1'); + + if (step == 1) { + beforeImage.classList.remove('hidden'); + } else { + beforeImage.classList.add('hidden'); + } + + let activeToggleBtn = wrapper.querySelector('.toggle-btn.active'); + if (activeToggleBtn) { + activeToggleBtn.classList.remove('active'); + } + + wrapper.querySelector('#toggle-' + splitId[1] + '-' + step).classList.add('active'); + + toggleTimeout = window.setTimeout(toggleStep, 2000, step_i + 1); + } + } + } + }; + + autoToggle(); + }); +}; +/* + * Initially load the graphic + * (NB: Use window.load to ensure all images have loaded) + */ +window.onload = onWindowLoaded; diff --git a/before_after_comparision/graphic.less b/before_after_comparision/graphic.less new file mode 100644 index 0000000..da8426c --- /dev/null +++ b/before_after_comparision/graphic.less @@ -0,0 +1,204 @@ +@import "./lib/base"; + +body { + max-width: 1000px; + margin-left: auto; + margin-right: auto; +} + +h1, +h2 { + .mmedia-constrained-centered(); +} + +.beforeafter + .beforeafter { + margin-top: 33px; +} + +.graphic h4 { + .mmedia-constrained-centered(); + .lato(); + font-size: 18px; + margin-bottom: 11px; + color: #666; +} + +.footer, +.footnotes { + .mmedia-constrained(); +} + +.graphic + .footer { + margin-top: -11px; +} + +.top-wrapper { + .clearfix(); + text-align: center; + + .image-toggle, + .legend { + display: inline-block; + } +} + +.image-toggle { + margin-right: 2.5%; + padding-left: 5px; + margin-bottom: 10px; +} + +.toggle-btn { + box-sizing: border-box; + display: inline-block; + width: 160px; + padding: 8px; + border: 1px solid #ccc; + border-radius: 4px; + background-color: #ddd; + color: #666; + margin-left: -5px; + opacity: 0.7; + transition: all 200ms ease-in; + .lato(); + + @media @screen-mobile { + width: 120px; + } + + .btn-hed { + text-transform: uppercase; + display: block; + font-size: 13px; + } + + .btn-dek { + display: block; + font-size: 11px; + font-style: italic; + font-weight: normal; + color: #aaa; + } + + &:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; + } + + &:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; + } + + &:hover { + color: #999; + opacity: 1; + } + + &.active { + background-color: #fff; + border-color: #ddd; + color: #454545; + font-weight: bold; + cursor: pointer; + opacity: 1; + } + + @media screen and (max-width: 500px) { + font-size: 1.2em; + + img { + display: none; + } + } +} + +.img-wrapper { + position: relative; + max-width: 1240px; + margin: 0 auto; + overflow: hidden; + + img { + padding: 0; + margin: 0; + max-width: 100%; + display: block; + + // @media screen and (max-width: 500px) { + // max-width: 130%; + // margin-left: -15%; + // } + + &.image-1 { + position: absolute; + top: 0; + left: 0; + transition: opacity 500ms ease-out; + opacity: 1; + + &.hidden { + opacity: 0; + } + } + } +} + +.footnotes { + display: none; +} + +@media screen and (max-width: 440px) { + .top-wrapper { + text-align: center; + } +} + +.hp { + h1, h2, h4 { + display: none; + } + + .graphic { + margin-bottom: 10px; + } + + .footnotes { + display: block; + margin-bottom: 6px; + } + + .footer, + .footnotes { + max-width: none; + margin-left: 0; + margin-right: 0; + } + + .image-toggle { + display: flex; + padding: 0; + margin: 0 auto 2px; + justify-content: center; + + @media @screen-mobile-above { + max-width: 400px; + } + } + + .toggle-btn { + box-sizing: border-box; + display: block; + width: 50%; + border: 1px solid #ccc; + margin-left: 0; + + @media @screen-mobile { + width: 50%; + } + + &:first-child { + border-right: none; + } + } +} diff --git a/before_after_comparision/index.html b/before_after_comparision/index.html new file mode 100644 index 0000000..73f219b --- /dev/null +++ b/before_after_comparision/index.html @@ -0,0 +1,31 @@ +<%= await t.include("lib/_head.html") %> + +<% if (COPY.labels.headline) { %> +

<%= t.smarty(COPY.labels.headline) %>

+ <% } %> + +<% if (COPY.labels.subhed) { %> +

<%= t.smarty(COPY.labels.subhed) %>

+<% } %> + +
+ <% for (let key of Object.keys(COPY.data)) { %> + <%= await t.include("partials/_beforeafter.html", { COPY: { ...COPY, data: [ COPY.data[key] ]}}) %> + <% } %> +
+ +<% if (COPY.labels.footnote) { %> +
+

Notes

+

<%= COPY.labels.footnote %>

+
+<% } %> + + + + + +<%= await t.include("lib/_foot.html") %> diff --git a/before_after_comparision/manifest.json b/before_after_comparision/manifest.json new file mode 100644 index 0000000..ec857d4 --- /dev/null +++ b/before_after_comparision/manifest.json @@ -0,0 +1,17 @@ +{ + "templateSheet": "1nvUwNbvKM7QsgMJe2beoFHXrSMGKOy8FjdpzvmKqPVk", + "files": [ + "*.html", + "!_*.html", + "graphic.js", + "graphic.less", + "*.png", + "*.jpg", + "*.gif", + "*.json", + "!manifest.json", + "*.geojson", + "*.csv", + "!README.md" + ] +} \ No newline at end of file diff --git a/before_after_comparision/partials/_beforeafter.html b/before_after_comparision/partials/_beforeafter.html new file mode 100644 index 0000000..55dc70b --- /dev/null +++ b/before_after_comparision/partials/_beforeafter.html @@ -0,0 +1,38 @@ +
+ + <% if (COPY.data[0].headline) { %> +

<%= t.smarty(COPY.data[0].headline) %>

+ <% } %> + +
+
+ + +
+
+
+ <% if (COPY.data[0].image1_alt) { %><%= COPY.data[0].image1_alt %><% } 
+              else { %> Image for <%= COPY.data[0].label_hed1 %>, <%= COPY.data[0].label_dek1 %><% } %> %> + <% if (COPY.data[0].image2_alt) { %><%= COPY.data[0].image2_alt %><% } 
+              else { %> Image for <%= COPY.data[0].label_hed2 %>, <%= COPY.data[0].label_dek2 %><% } %> %> +
+ + <% if (COPY.data[0].credit) { %> + + <% } %> + +
\ No newline at end of file diff --git a/before_after_comparision/synced/test1.png b/before_after_comparision/synced/test1.png new file mode 100644 index 0000000000000000000000000000000000000000..eec29789a373e55099ea33371307b731af1dabf9 GIT binary patch literal 14695 zcmeHui91yN`~OiSMT*2D@+ee#$nq$%RZ`KQ8Z-8tY$5wPXqEI>vhS_788gV(jVUyk zm`Y=0n=C^NGg$}2%yYBMRn6 z^-~YB8rR0BGb*NpJ%V;6PYIhVczo}2|K8Pe{&S#GflmLk)?BMx86gcF4fi00uGd|u zvc``fJ%8#xSsAGOcCvDyxu5Ha+jK)CefBihR%yP~H(JauEyjHf9Ziu1rw4%EvAI}f z|GVgFct%~;uz;y-G4&L#g5R!KQjDP=|=Z4>I`JE16 z8vI@*zpDeU9Q>||zncY^2EUu+|LfS{vt5xIpiLl$AF6MR+WcbCIUL z_OsmH(>P`mg-Zz~wXtb_vdM&v$Qi4o$?^#rz0+@g$u@U#@|+5Wu(g%N6l$b-MlFnT zsO-7kiA7baTviH|tpPxiL0~o07~V=ZXjG?`PJg*i=5Ein)>dUewO|^TYFT4!&r?(vc%b~HQp>u&1yFpzV%NpGLxv?qN0RYj*z~Wty zr4|yhJoB^KEKxliqvD@ydreP=6Q$m`3n8}l!G8~{8s_RVCK@!{$$l3pwh_!;-|mdQ zWDwsS-SJf^itqdR!RkH0r$YW0*(}NaF!tjU8%J_4_Oc)icMXJ=-S%bcNO0!)rw`I} z`V^Mi3>{l8vm{`o9+sJN?{-9l=i=55;MGykj0BbHiNyp5R*K<1@#|tlM%cH%I_alM`XUcQwU|=@9CRS3Z`i?gDQ1f~gcJ zQDTvxaCdWkVB)B&TXIDqYd0Wu%0&Xu)+3fRb!WEL)4JsCV9Q5-ZdoMB zmO%eR?ZBU~5dZ+0ESfnv^yS==@+g=YI*(K>NM>a=MPr4~q+sL4tdj=srqujutU{jB zfisD%?4mOsbX(viMhqgl=q z5mTs+cQWa2sgqH{r?hORR*Uyu@SEsl8MY}|wH~*hn)lUV9!Nw*9$9t_Tw6U+u>6v`HvEwakfOG8w(EoSb z&%K3}STgm;7|`_inx~qHN^UJRy6m)wI@6b&3X_Sg`mH~Vm@^Ks)>WnkmV+UtAyE2d zGC%oMX%b}~H|3ef%mwcU0sZ6E7$E`Nk;>|KQVBZ%Bbk;Rfb6rPRu5{t(SDR!Bo{M6Mhfipx zx_x4shi&LpmSNcyvL2JWUEkSJRwe|Xz<2}8+5MSz;mBJzVGtML%@TMv9eDJNIm&91 z)%z@hr||V&I)^mVbTYD%;3BJ0 zJqagM3{l%fhTLG*sq;X*%>g)H{D!ZHjS=JK)E$M*)o#Zx)l8d(q^3-7vLDmB*O3fs zb|P*5FrmoCwT`j@;A0V3Q9e5P)~Z+bSSz6F=52b7t85Lm2TNi|e)jRcl4ALGR&gDr z)b;BEfOQf$xXQg=nf*zly6LONs!oS7$`&_soefI~z{V}42RNYi0oM7vQ5h#M3}Sm8 z%vw|URvwc1iShbGXUXk+tM6FtH%^ zS~i>l+@9okiZukOV=lpD}U*!^z=l&QKJITWC`%}(fq_u9-H|SlZ{D6;T2`r_Eu~Y;Af){^zR%=PP z8u_ffU*nJMt>$8G_%-X^*V6{c)GTJ;+8#FhF{;t2vKgjX=~Ju$R0)9WRV}Xc7+G0J z)5zXMw(ndkTa&8`eU4Z=0Jkf-NP6@=>v7~{&nBz8~ zX%>E48poq4e6^6^dj9WzL^uCdFYtH`U41=5HjIz7Nd2WyrVJ~x{AISkQ@uS0+s#Gn{#aa8bKrapGP{ZEg&2! z=52QYUc3ZPIOc*4rObI3k61%6bp?AwkhKrUNeaSs5C`T_RNYptn$^@^Eq)lAUNAp=*c_8A!3hYee z8Cd1+v%txw8&37#U0ojt+j(f^4_Ddq#Mf(Q1_0DsQp4)bye@8PEsn5X@}CFUCTOAuz?&USthgKGwkp1qJKWjlH@rsx3?g0CCF z_{Cr<24*z-=K#R&mMd7&A&JlB^lbuE@HS`Be;r+*xBaCW;_)OiskWmX=kQ$RfTm=~ z(1*Z5jmkXaf@t-w=chWXeLhe_RNN;DWdj+Rnyv%DLk7iREt7p?yCo3!>4L8{yc$&69^ zB&KS|uppMN=c7#kU{F&RTvcL-pbJR;mk&PKKliZ{v)0s!SP9Y9J)K+U*V$eWORZ=B zedBK`CIE{!X2g98Gpxh5g=EW}N3mrrM_YzMokm9&SP?&OFUIZwg!?*_0sPH1HAj8N zdB@R#sCb6EG2SVT8cO22>jT5pDdprW*bZo;bAFN)AE3+2fPzfx+9Z6Q(EARunZ@T@ zW45ZbwRC-CZpcFZNZ&)MEmIJ{3-bgaNt;~*RDIimr52G~$L+1KVef&Dq&lT6&AZ=% zAWF&TW&Qfl&lPX7po`&+Zsgb6K-JDL@c#7XmG5drEs*`wS+c1@=8b+)T1%*1SFbj) zBJ5btP7Y3U#vb(I^pT_8UwuN`0*J4DX{6ga5{7c;=AVGsHqXnUczB{wq6x*&4pMCp zRs9W`z1PlWFTN=Z>xuOcIS+TAr{B8{0LOUC2X#ywm3wBpw=`d10430s+2Jxvqt}(b z43#}!f;=UjKkT?uZCCCYL10jWr)r!@+nt4vTB)Tc2Ve{H5CiSHNhhtXREz5e;>V=n z&9ap{2iK(IpFoIkC70sXxu(Nbn{EEtYuQtouK_x{1kP-p0gY#jrc1BF~V^6TY zFC=~RrZncjCjPQiK;4>av?#f5=juh2j+dlTCIZ4W#<#ow;b4Zz?z6Zsl+qq*Oaq6> zT}<~II}A7zz()WEOZZ}G<>#ewue0=&>f=? zQU|%ha+s>{c!|}TC?ZRrN7B`5qF%v>lRJSEyao|=@-s5%hB7o1<#rf~M2xG;?MEGk zhwIStlDx5AqndkxPgi+&#@heW8tOytn2W&{Oyl~L;~8KtlW~*m?B^%&Tue~iIokxO z-0^E!0c$TpzmRxiA=l7{;msf1=3h?wX8Qul6}s?dS8FT*e7>W+=aW-j6dd?0X7HB4 zYKizJ33qD!riYp){dn6~zFFDdG}?U*kaGk}0}qAHw=1PT{@9LYMc3{6u>9WD>GsHn z+BsFHotf)4O{0tea;Z#Lyt)ZjxD5HG@8dh9CtcHYxra`;*} z%N9f->RK#hfbqLCYsj$ZhIl*LQTQT-%Es>m1|R>jp;A{iT((&1vaj{%hn~l#)(g6- z#jSaL(n<5`V7h#m6h-{t15jqXNF)qYHDMgGp7z(h_n}VRDzOwl$WA88tJ-3_4|)$A zvJ9(qY#a%-U?zgC(U#ZL9j>+bG#-udbj?)pF0@_PiyXGydA-_us)g0Cwi@a81RN** zYn*P=w>1&Rm^SUg+zszS>#?k?KckqNuCB{RQyg!zB1R~GhZz(^Ecq?4{+gUK2p``8 zq#x(SM|0eds#zTgNZWm;!<+JyPJb};m*Hp@0pmhMz1*czMh+@A8s?~uNVM6QudeT1c+Tuc)B$lg%+zY zjH(%9Zm(~nqa))M&+P&l;z4(Rq|T=1^)HEAYre}%{NiWvMsbfmrwVaXE2yVN3s^p5 zY3&f+idRi0WMk^No@;xC+*K_fQ zj4*sZ!W#B`N9mo;b?g;W!a%wF5s8Jv+YaJ{X~oaG zyu~hP2x!l=Wf%T7zC!pNM(q+1`$cOgg+k!)&+RXR7R+vk@j`| zL3+NGWWAqxmtu+1J%vY4$7_8`+_J}SH}3oXvao$4fUWKLmf<{a_1SRSAdQtki|#}p z_YNMf(laFH%(Y7aQmxkG#CJD-mE~0>@FO9FRCNR?@$XHN|0X%` zm#~%dnBK-{3Xct4L?Ad0lva+Rp;^3ob7bghVf5yg6j4A41Q78jy9_(pnxYqF5sL_l z1NU~DsKSeSU7;rY3Joz0>RkVf^3*GaWAl0n7i6LOF$_Tf5a&rDgC3@<3iqQY=1`kblhT(dE2y=w3SoWLE}7-abc`u=Y~9fLdpgT4 zVxF-0jk3HH7w*8FbWoHVb3e*i33f4!)n~QYUz$%Evr7q3DYBEZ<-`AQm}_DXmI>0iMy3C!?OLry~kPCU|T;odEI`OW?SxFIG|l`sB=IGoQJwFw70luiMU zva~a$($&b}>XKe*lP3uMZ5+?)_Mm+A)uTGe;sN3k3Hwk+#PWsWk^R09lxC2ONa&M@m##bL%Z3}z z|76-F-iuUy@Gi;2&~L30{e?9y4XB*}Ys`le>PJf{jtWq7Itq|_t2YKYta`dYK!p)k zwL1a{zcmjvA78uh?xJgONrEWiS$O9B8wbaErk+kw(9@m&3RqH#J*a2Ut1}T=j7$7b z|JtjykjEr+KcZmC3A^3g+0CEihv>qKw#z7O1rWXIF{c3*s8Fv0BLL(gQKzw zn2o}XpsGeH%a2<*z4K=5s6q&h#X0!eAfHgNv+gv(+I*XIX)1?y|6Z}`m$l9bS7W!J zO|3%8w{H|%B|_RIb%}UckU&Ok5M2C;AnLzX1|8=i8fM zbE{@&{rUq898UWybt%NsD!7d>BVU}s_+Nn%=ET5E>qh^UxaIbV75aldnPEu*QcST7 zVdJ@5I+8IHdrJ#{#o|%QlSWY@!69?TZNnbb95!AmTT4~(-@5s7*4PEBE7Y$O8#BoN zOY_9%xJ!;#oNSq&7@nCLZsI<6GRG^zkH+r?fImcd?*ce`OsE8EmA-{535(Y(MX%|+ zS#7?;W;>QHL{+xiAE7AS&=S8Z1g*prdjKERM+#%CQ_J7AT&8Sr5}&BM+mB8~pDs?B z59jmTZJpVb z`aJ!7CZT@rrM;)($do$Mw|IWgoHCZBqlXTCHJ2VB2_4Hf-=wi-NG3l>fw@BOD>}$9 zXbm)tkUAre>4gkhDOoR%_uvfFa)*{j&SLYpSr~N?55F3pfB|ZUa_8)|K5xwRlKO+8 z8QOVjnf+;YD&c#B1_u%=B3s>E)!AnCf4mHmIqtvBq8^GiMaJ3&s;BR@r8RafvuEN4 zVv8v&8(B~!GJ*j(Tk?`U2^XhEqPnS zFK!$`$j_tnlJ$yo9BBIKNU|uT1x=#Vqvc7%1MqLBDNE|gI3BbjXaqh;ex9Q|0$a*dcoGn9RQM&ZKG{(vF5>q;vd78`2LWQE!j zBL7BMYQ+qxRKYlPaN(NAj=gmt3 zXWSd(>M~7MmTC8E3*OvGgDkSEgn-Kzz)Jo?u>w6Lm%E;WNDltmG#wlUt+2}JnNOQdXA)zpaaBH7RQ_|FskJpo{LyM;9pm8P!^AL4 zS2y!EIp}kex`T~LYJbzr8N>;cKRRIPZ2!oFG9YXYS}VW0-L7qw5W5kDGkmFIcxE7d za3Jbk#e>owa}vVjAQHu&GyHYV-YR=OzZ?v?J{YSp6gfX*>D>1@$~LA1MreuCmV07Z0-rh94MF)| zp$hui2!4Mb`)}!c^d-o6zR?0z_Xw8WoFIQgtGcZ7pz0hv*S2@_e$3#GYq?tsNy{Z* z-M9|UBmCwx3SKf=QlY3CuJnE1WkoUl7z2){qTKG5sD93BB_^RdpExOXA19irNBPeL zu5CVcSBWR7!A^WC}QCEi>0Ak zn>P=W^ig$1Ybq5-9`#I(W+W%}AoOd&LXUMKQg`yqQRA8Of_Cp%@IIsvkx)N`tE(w} zHk;>b-Rr)P#2m)0_0S^iKUIb-Viwv3lwF@8O;UlS(EtTjU#M5z}- zao-@|Rldh0S96~k<=L7^G4em8%oj<(hgbA1c+>oQ*|t$cpSt=DtVi~(Fyt6FNRIVb z-77J0^pcg4WeKU&pgM|szYglJX?WZR{&(<$F*7o3|rg8j?}c5`P?YAiqF* zMDm#hd)cs=F}|!na^do^{*RR<(oo8R6jtpu(KW7qsZUS( zNM==@=!ug3-AnSO9yhfx%LsF1l>SaYSBZzQAd$+LIdVQ)H_FE}l(Ht96U!<)w9Br2 zB;&a3OfB?pajeZ^+AyttIMzbx3p1vg9(~3sQok~)khfEJA5>(VsUL0PbIX|(?eN5y<)Axe|kU15r`K8nX~ilee&nshg2k+yL-<8wq_ex^+#+Dd2~Cr z?Ko96?0C|>e7bJzfCv@9U*-_|1%c>kIec3PEr^1MZKgYp)hmIzag%pff+CNf-6WHQ zfgE+v7O4dO0mxTbYR&1?4V?#W=PsTP8_zFUUHJULtvy$Px zrg2Md5*tp5yJ;93x9Br9RMaV0-!bgMFdTvA1>^lxlG8DQG8Jtzvo%=V5G_y`$Y)Odx-&lO4O~8cEjULZb z0#`YL*zFplPO^?z&LFmfY~lZx<4mJ-CJY!RFUd;+RpC4a+nn9??0nwdA$L(XWCxib zx5-znM$>--j)Eq838A>_ZWP&3nRkVJz@Uma$dow>RZ7x|S#{=^X}X3$HuPz3sU)?2 zfmXOw^hN#Bcvd&9ps&roF*Wo^WZ$yyJ#XU@tH~d;j3XdL#q)S=TaayBiIv>gY*RC3 z2p3vH4RVn=#W!8PIuo^95@YIqC3FN4ObPkLr zP43gT_Ce`14VCP&c0DXZ0`17}2eEacxNZOZzH%<*tYIw|7ZX46(k(xKN%}w0`Y@f! z;X}+MtzAv8Qda#4RaBa;T`BJl9F~4az&UB%UETD=iW(;eENnXR0m3}h@=-c8*)F_P z>C;q*`*f+8c&YYhhelFmf3r~!y>976*8;2Lj}AT{inkq8r7ZbI%yYUN92FsKX|O-% zqVYMbtH3hy||_)^JnR~%BHVT+=t}V6^C_VGT1pEfcCNnmPEfB={gL|z6&`X$mkXI zvoKb=K+wbH#pj$FukUh;U61*$+am80TED4O{P2ITs@aPPI43lHqEyprhnvzx!np3XVd3->cBvS$A8ELjm>&t`^uxnMOqmHzx_r>LRy1-4@v=Wcd^Uh8u< zy-J$oh(#2Zlk;$GqD!pA|EWBWK1m9Ss_2bu_zhEpb}wf`^W<8+;&SBL4AGQpN?yF3 z%I*7}%Q_`?hAaEwzMD#L1c<8d^I-gLL}~AlFXc74ADVa(t1I&VSSzbvIl4`dOZHSe z&$y=KZ8vrQULyn<_K;Ev1GEtGL+qpf)62}H6hF##L8FjvZ}vX=UtZ zAjoWo_Qdl~>6kg!;|zl3m7-q{=YoCnGq39HR^gl2Z=P+Y)(~B}O}E47^{se3TPEkP zC8U+l^qgED&T6g5bld1;E$6`(%-62W1Y)c9JvZACLglXoqw%lhLi-V)y%^*2{SR}0 z`mRn5cPbo9kjJD&r}&C$xoCoV@Np|<+$WG#`g1o?K*MsUD)aLl+fw*L@)-mP$~m%# z+x_pIP9XSP`^M$RPnG)DGvEuiLTDjFG_9L9LZ1pd$cRb->sald6e=Z_x_x@)aJxO; zr+MB=;9vH60#S-3g^IcyfofG4L@WL&Q!y{!OKLkx7$CA8!e{E6qrcRAI7$elt#Bj2 zw-1gOP|2;*Mf%8L9!4nxB_Op7qmj3H(2`FP{?Y=ooU6=-g*YZzQ?gAZY%JB zVf`OJHQwYopuvsFp}>*COXNm5Vs3}u=s&(bq1X;K{}0%F;jZ`#t+ZLe_`B{2?n;Yr z2V*_)aA>jrwZ}b^U1To%=(|Xb>IO`INy0w;$bvORPH79=-vDKC?uw%mmlIL_>MZ6> zsFCGSD+8&n>XC5u7t0F5ay^3lk;#U!ZCrZTHs{PLC78NRQqQF90@S2MaQbso8q~El+J4(f zUS~;Mp`>*W@{^4Uls}SA$UUv?V8+~0KygZOdoi>P>=}Mw*9?!F)#83W>(AB{iaHUr zd0Q3k9{wj%p@lonOp4bzvr#owx*m-$^{F>l!^KCGq4j#Yc2hh7ZZBXa^k#_rRa8scil1ZXNh2i2)e!CW{h7lx*N`+PJonU`zD

C$=-H~Z}1Lx}0Ed!c`n1rZa(8ut&MnbPii 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 literal 0 HcmV?d00001