From 1ecdc884b0279f383d3342b04581eb56dc81d240 Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sun, 28 Apr 2024 21:53:26 -0500 Subject: [PATCH] update draft --- content/posts/using-custom-font-hugo/index.md | 119 +++++++++++++++--- .../using-custom-font-hugo/og-sample.png | Bin 0 -> 27337 bytes 2 files changed, 102 insertions(+), 17 deletions(-) create mode 100644 content/posts/using-custom-font-hugo/og-sample.png diff --git a/content/posts/using-custom-font-hugo/index.md b/content/posts/using-custom-font-hugo/index.md index 52c8f59..99262ed 100644 --- a/content/posts/using-custom-font-hugo/index.md +++ b/content/posts/using-custom-font-hugo/index.md @@ -1,13 +1,13 @@ --- -title: "Configuring a Custom Font in Hugo" +title: "Using a Custom Font with Hugo" date: 2024-04-23 # lastmod: 2024-04-23 draft: true -description: "This is a new post about..." +description: "Installing a custom font on a Hugo site, and taking steps to protect the paid font files from unauthorized distribution. Plus a brief exploration of a pair of storage CDNs, and using Tailscale in a GitHub Actions workflow." featured: false toc: true comments: true -categories: Tips # Backstage, ChromeOS, Code, Self-Hosting, VMware +categories: Backstage tags: - bunny - cloudflare @@ -17,10 +17,10 @@ tags: --- Last week, I came across and immediately fell in love with a delightfully-retro monospace font called [Berkeley Mono](https://berkeleygraphics.com/typefaces/berkeley-mono/). I promptly purchased a "personal developer" license and set to work [applying the font in my IDE and terminal](https://scribbles.jbowdre.lol/post/trying-tabby-terminal). I didn't want to stop there, though; the license also permits me to use the font on my personal site, and Berkeley Mono will fit in beautifully with the whole runtimeterror aesthetic. -Long story short, you're looking at a slick new font here. Long story long: I'm about to tell you how I added the font both to the site and to the [dynamically-generated OpenGraph share images](/dynamic-opengraph-images-with-hugo/) setup. It wasn't terribly hard to implement, but the Hugo documentation is a bit light on how to do it (and I'm kind of inept at this whole web development thing). +Well, you're looking at the slick new font here, and I'm about to tell you how I added the font both to the site itself and to the [dynamically-generated OpenGraph share images](/dynamic-opengraph-images-with-hugo/) setup. It wasn't terribly hard to implement, but the Hugo documentation is a bit light on how to do it (and I'm kind of inept at this whole web development thing). ### Web Font -The [risotto theme for Hugo](https://github.com/joeroe/risotto/tree/main) upon which this site is based defines the default font face(s) as the variable `--font-monospace` in `themes/risotto/static/css/typography.css`, and then that variable is inserted wherever the font may need to be set: +This site's styling is based on the [risotto theme for Hugo](https://github.com/joeroe/risotto/tree/main). Risotto uses the CSS variable `--font-monospace` in `themes/risotto/static/css/typography.css` to define the font face, and then that variable is inserted wherever the font may need to be set: ```css /* torchlight! {"lineNumbers":true} */ @@ -36,7 +36,7 @@ body { } ``` -This makes it easy to override the theme's font by referencing my preferred font in `static/custom.css`: +This makes it easy to override the theme's font by inserting my preferred font in `static/custom.css`: ```css /* font overrides */ @@ -54,7 +54,7 @@ And that would be the end of things if I could expect that everyone who visited } ``` -That gives me a few more fallback fonts to fall back to if my preferred font isn't available. But let's see about making that font available. +That provides a few more options to fall back to if the preferred font isn't available. But let's see about making that font available. #### Hosted Locally I can use a `@font-face` rule to tell the browser how to find the `.woff2`/`.woff` files for my preferred web font, and I could just set the `src: url` parameter to point to a local path in my Hugo environment: @@ -65,18 +65,20 @@ I can use a `@font-face` rule to tell the browser how to find the `.woff2`/`.wof font-family: 'Berkeley Mono'; font-style: normal; font-weight: 400; + /* use the installed font with this name if it's there... */ src: local('Berkeley Mono'), + /* otherwise look at these paths */ url('/fonts/BerkeleyMono.woff2') format('woff2'), url('/fonts/BerkeleyMono.woff') format('woff') } ``` -And that would work just fine... but it *would* require storing those web font files in the GitHub repo which powers my site, and I'd rather not host any paid font files in such a way. +And that would work just fine... but it *would* require storing those web font files in the (public) [GitHub repo](https://github.com/jbowdre/runtimeterror) which powers my site, and I'd rather not store any paid font files there. -So instead, I opted to store the web font files in a CDN, where I could exercise some degree of access control, learn more about a web technology I haven't played with a whole lot, and make use of a cool `cdn.runtimeterror.dev` subdomain in the process. +So instead, I opted to try using a [Content Delivery Network (CDN)](https://en.wikipedia.org/wiki/Content_delivery_network) to host the font files. This would allow for some degree of access control, help me learn more about a web technology I hadn't played with much, and make use of a cool `cdn.*` subdomain in the process. {{% notice note "Double the CDN, double the fun" %}} -Of course, while writing this post I gave in to my impulsive nature and [migrated the site from Cloudflare to Bunny.net](https://scribbles.jbowdre.lol/post/i-just-hopped-to-bunny-net). So I'm going to briefly describe how I set this up first on [Cloudflare R2](https://www.cloudflare.com/developer-platform/r2/) and later on [Bunny Storage](https://bunny.net/storage/). +Of course, while writing this post I gave in to my impulsive nature and [migrated the site from Cloudflare to Bunny.net](https://scribbles.jbowdre.lol/post/i-just-hopped-to-bunny-net). Rather than scrap the content I'd already written, I'll go ahead and describe how I set this up first on [Cloudflare R2](https://www.cloudflare.com/developer-platform/r2/) and later on [Bunny Storage](https://bunny.net/storage/). {{% /notice %}} #### Cloudflare R2 @@ -125,9 +127,9 @@ I *eventually* discovered that sometimes you need to clear Cloudflare's cache so ### Bunny Storage After migrating my domain to Bunny.net, the CDN font setup was pretty similar - but also different enough that it's worth mentioning. I started by creating a new Storage Zone named `runtimeterror-storage`, and selecting an appropriate-seeming set of replication regions. I then uploaded the same `fonts/` folder as before. -To be able to access the files in Bunny Storage, I then connected a new Pull Zone (called `runtimeterror-pull`) and linked that Pull Zone with the `cdn.runtimeterror.dev` hostname. I also made sure to enable the option to automatically generate a certificate for this host. +To be able to access the files in Bunny Storage, I connected a new Pull Zone (called `runtimeterror-pull`) and linked that Pull Zone with the `cdn.runtimeterror.dev` hostname. I also made sure to enable the option to automatically generate a certificate for this host. -Rather than needing me to understand CORS and craft a viable policy file, Bunny provides a clean UI with easy-to-understand options for configuring the pull zone security. I enabled the options to block root path access, block `POST` requests, and block direct file access, and also added the same trusted referrers as before: +Rather than needing me to understand CORS and craft a viable policy file, Bunny provides a clean UI with easy-to-understand options for configuring the pull zone security. I enabled the options to block root path access, block `POST` requests, block direct file access, and also added the same trusted referrers as before: ![Bunny CDN security configuration](bunny-cdn-security.png) @@ -146,12 +148,14 @@ I made sure to use the same paths as I had on Cloudflare so I didn't need to upd } ``` +I again tested locally with `hugo server` and confirmed that the font loaded from Bunny CDN without any CORS or other errors. + So that's the web font for the web site sorted (twice); now let's tackle the font in the OpenGraph share images. ### Image Filter Text -My [setup for generating the share images](/dynamic-opengraph-images-with-hugo/) leverages the Hugo [images.Text](https://gohugo.io/functions/images/text/) function to overlay text onto a background image, and it needs a TrueType font in order to work. I was previously just storing the required font directly in my GitHub repo so that it would be available during the site build, but I definitely don't want to do that with a paid font file. So I needed to come up with some way to provide the TTF file to the builder without making it publicly available. +My [setup for generating the share images](/dynamic-opengraph-images-with-hugo/) leverages the Hugo [images.Text](https://gohugo.io/functions/images/text/) function to overlay text onto a background image, and it needs a TrueType font in order to work. I was previously just storing the required font directly in my GitHub repo so that it would be available during the site build, but I definitely don't want to do that with a paid TrueType font file. So I needed to come up with some way to provide the TTF file to the GitHub runner without making it publicly available. -I recently figured out how I could [use a GitHub Action to easily connect the builder to my Tailscale environment](/gemini-capsule-gempost-github-actions/#publish-github-actions:~:text=name%3A%20Connect%20to%20Tailscale), and I figured I could re-use that idea here - only instead of pushing something to my tailnet, I'll need to pull something out. +I recently figured out how I could [use a GitHub Action to easily connect the runner to my Tailscale environment](/gemini-capsule-gempost-github-actions/#publish-github-actions:~:text=name%3A%20Connect%20to%20Tailscale), and I figured I could re-use that idea here - only instead of pushing something to my tailnet, I'll be pulling something out. #### Tailscale Setup So I SSH'd to the cloud server I'm already using for hosting my Gemini capsule, created a folder to hold the font file (`/opt/fonts/`), and copied the TTF file into there. And then I used [Tailscale Serve](/tailscale-ssh-serve-funnel/#tailscale-serve) to publish that folder internally to my tailnet: @@ -165,7 +169,9 @@ https://node.tailnet-name.ts.net/fonts/ |-- path /opt/fonts ``` -Last time, I set up the Tailscale ACL so that the GitHub Runner (`tag:gh-bld`) could talk to my server (`tag:gh-srv`) over SSH: +The `--bg` flag will run the share in the background and automatically start it with the system (like a daemon-mode setup). + +When I set up Tailscale for the Gemini capsule workflow, I configured the Tailscale ACL so that the GitHub runner (`tag:gh-bld`) could talk to my server (`tag:gh-srv`) over SSH: ```json "acls": [ @@ -234,7 +240,11 @@ Here's the image-related code that I was previously using in `layouts/partials/o {{ $img = resources.Copy (path.Join $.Page.RelPermalink "og.png") $img }} ``` -All I need to do is get it to pull the font resource from a web address rather than the local file system, and I'll do that by loading an environment variable instead of hardcoding the path here: +All I need to do is get it to pull the font resource from a web address rather than the local file system, and I'll do that by loading an environment variable instead of hardcoding the path here. + +{{% notice note "Hugo Environent Variable Access" %}} +By default, Hugo's `os.Getenv` function only has access to environment variables which start with `HUGO_`. You can [adjust the security configuration](https://gohugo.io/functions/os/getenv/#security) to alter this restriction if needed, but I figured I could work just fine within the provided constraints. +{{% /notice %}} ```jinja-html {{ $img := resources.Get "og_base.png" }} @@ -279,5 +289,80 @@ All I need to do is get it to pull the font resource from a web address rather t {{ $img = resources.Copy (path.Join $.Page.RelPermalink "og.png") $img }} ``` +I can test that this works by running a build locally from a system with access to my tailnet. I'm not going to start a web server with this build; I'll just review the contents of the `public/` folder once it's complete to see if the OpenGraph images got rendered correctly. + +```shell +HUGO_REMOTE_FONT_PATH=https://node.tailnet-name.ts.net/fonts/BerkeleyMono.ttf hugo +``` + +Neat, it worked! + +![OpenGraph share image for this post](og-sample.png) + #### GitHub Action -All that's left is to update the GitHub Action to handle the build for me. \ No newline at end of file +All that's left is to update the GitHub Actions workflow I use for [building and deploying my site to Neocities](/deploy-hugo-neocities-github-actions/) to automate things: + +```yaml +# torchlight! {"lineNumbers": true} +# .github/workflows/deploy-to-neocities.yml +name: Deploy to Neocities +# [tl! collapse:start] +on: + schedule: + - cron: 0 13 * * * + push: + branches: + - main + +concurrency: + group: deploy-to-neocities + cancel-in-progress: true + +defaults: + run: + shell: bash +# [tl! collapse:end] +jobs: + deploy: + name: Build and deploy Hugo site + runs-on: ubuntu-latest + steps: + - name: Hugo setup + uses: peaceiris/actions-hugo@v2.6.0 + with: + hugo-version: '0.121.1' + extended: true + - name: Checkout + uses: actions/checkout@v4 + with: + submodules: recursive + - name: Connect to Tailscale # [tl! ++:10 **:10] + uses: tailscale/github-action@v2 + with: + oauth-client-id: ${{ secrets.TS_API_CLIENT_ID }} + oauth-secret: ${{ secrets.TS_API_CLIENT_SECRET }} + tags: ${{ secrets.TS_TAG }} + - name: Build with Hugo + run: hugo --minify # [tl! -- **] + run: HUGO_REMOTE_FONT_PATH=${{ secrets.REMOTE_FONT_PATH }} hugo --minify # [tl! ++ ** reindex(-1) ] + - name: Insert 404 page + run: | + cp public/404/index.html public/not_found.html + - name: Highlight with Torchlight + run: | + npm i @torchlight-api/torchlight-cli + npx torchlight + - name: Deploy to Neocities + uses: bcomnes/deploy-to-neocities@v1 + with: + api_token: ${{ secrets.NEOCITIES_API_TOKEN }} + cleanup: true + dist_dir: public +``` + +This uses the [Tailscale GitHub Action](https://github.com/tailscale/github-action) to connect the runner to my tailnet using the credentials I created earlier, and passes the `REMOTE_FONT_PATH` secret as an environment variable to the Hugo command line. Hugo will then be able to retrieve and use the TTF font during the build process. + +### Conclusion +Configuring and using a custom font in my Hugo-generated site wasn't hard to do, but I had to figure some things out on my own to get started in the right direction. I learned a lot about how fonts are managed in CSS along the way, and I love the way the new font looks on this site! + +This little project also gave me an excuse to play with first Cloudflare R2 and then Bunny Storage, and I came away seriously impressed by Bunny (and have since moved more of my domains to bunny.net). Expect me to write more about cool Bunny stuff in the future. \ No newline at end of file diff --git a/content/posts/using-custom-font-hugo/og-sample.png b/content/posts/using-custom-font-hugo/og-sample.png new file mode 100644 index 0000000000000000000000000000000000000000..4a45c769216d3a02a156c15ede5d0e3ad501fd18 GIT binary patch literal 27337 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 z zub0NP?7z;x^lQD_rh^~uYfM&X2A>KpzG-c9FZ14IYcx2-nP;7uoMd|RNw3NSn>f}- zleaC>1;R6!!(M{+`Ta=5lAKN3@%DOUxEDlB&gqFu-_OnpRbMqJSHsOv*3&HDidm}EjBvSS?^HauvN>7)FhdpA zNAD<+xiyCIuKP_Tlf)*}`((8<;SEl(TVMY}C6Tl}k=6J8jLIrv#F=WXIz`jd^AtEs z?bHy78LJw$|3X@-#%RzUM~f4eJh12t?7`84O2p4v$E2&C{9bi=!CuW ztQI<)DBGVXTUpK`*1OsMz82Bc`MM>Hp!JX@OCoC>_psG`Ifm&zt)vXWnvER7eo>3w zS!ZoIOj6-i>aM40v;WS_^gmit-G(Z^P0LJ9Sl0!3OW8&L5xER14iX9sx@6pY&erMF zkzUQLrt*1LepM*blTRxn=G+?fKYmyfy~+$q#ZxF3ySi@OrmU(6~cyT|P{dr)rGvQ@{HD&#f667`ZTF58$Q zI+|CEU{^dsL$ypnNymCZu~HWzQB-h)`zibterR98?Nb-?FK4`@t1q_L=*!@X#wuM! z5d~gEfBXZVQ4C#?zF5Fmt* zZyKje^NioSu0LP@L4TR(tSye*WOl+=B3M5CrN)PFzgAW-O=WK33Hi`k6;o#?;mksI zGkWYS2MN>e3Tl_IdqmKRbhY(J#P(J$Mn!l^Cw*p*gkA!PM8v@%TSiJ!GJ7~Aq?pT! z-pWs~;fIIwcmG<;0?dv#!2yx^7{%)NsLZ+6m>-39Kiv}SFGfRO<>+DzGCles%3{bXxak}i z$RGJK(45{-vU>NDI6BXxQ$661i|BLm8~+0jk8By$N;U(Z2rCZXqxi>e)mBx|I*)(* zX-993-tM{Z*6(B9V0qQu*&X@Hcs-i=2K86Xe9m|KS(5&k$F8k=V}{5l28 zKr`^X8u|6fU0Khltwj4>&c4S7mze`8ob67HW_}tWxDq2{VUXk|%xW;5VC{L&o%GI} zF&DJ}$+)YVvP@TCYbq_Bg`#Ce!@T{V@A+4^S<|$A!I?G8LLaBUSI4$1pV>bBP5s`m zc%*bItfQQezu$XAifKUuCrO~Q46FKgn~LYd_k^34wm@TOU;F%n2Al>{||fi*6(ag zB1l$d^*>YO-JW}MZkOUv+rl@PdvUFmjjuy_Uc1TxGX@RBCp5K1?%L5+(2C!%mnrPQ z;c;7YI;a!94kqnLH9I&#DNm9;E3UC*p5*{D$oo!hx*7Rax3x%sS;)sCBLC-YrdN*e zE3(L%oi!OOWLCB7W^I9@$X$}A=98?H*Qbjf;L{ArR{j|;ZPE@{1~E#H^&Qb596lSB z!muzcY+-BJrX6i+?5nS%NTebdOO=r0USqZQERwQ(S6$6*f^Q9T-G=fsVx-Y3wsz8G zsMaQkdP8&QbZ%?qGqsWTL&Xue`9XwOy`JXalqo1w%(qllfa+G91oc;e8zMb(yFON3 z-Yp~3c<-$j+TkA@;`p=emuSM@>A(I>Ww-a`H^LE~9t0m(x73JfGEgL@o4p%=3Ly|8%)bB5_Ei$qjV~|pTFnacuO^#=^9#EKHhYr z!QMbv%bVAkZ3G13*bMWZc~3_bnp-Htj@(9>A%8-yE*r^$DSz)L(4@+L9(VDl( zXjL6+$(@G_+SO&%&LQ!1musK-o75nE4uv#T$RFb~p1%4jzzS<^DChCbpT1q*ap%&i z7)awRI2%a2-6~u~IHru-yyK*|uqfErv><$8@$zMJ;Dx@OojNDi0Q`vWS~k!Z#_r$j zt_;7v)RmC|ezEU>+SB)Zh7*Av{ED_KG1*cmFa0nkNDC5U`q zTB4Cbrn+bsdB@K8Rlz|if#-VX``K--NmehV;Z&jHtJVuOLOa^oztm)0N*J<_(wt4- z7>N60A4#e96y@m#m7OSkJd34pqTiM`6f z_M<|~6xP>zvEV?i}QsSgM(ne!stAKJIQP0A~<14RJudz!a8 z$al=d%+=!iC^DD7INv;eO{?uuYpd1msjE2_F`xZ`gU1z8#jshUUi7y;Ygwl5&SDLu zu)VZDHPu>e)|vYy#4QC>84w1e1FB1g+KM%kQ0Sut%QwVjTE7186YzcBU{w?pKBl3- zd?5WyS=LN-uOe%aWw6B4rOANa^MJG@cDibX#iP!lZadd7GJITSg$Ph2hv=T5oLjr^ zu&dLYJ3@sAuThJWPRmn-9UGQE+F=nJf2p#m{vo0ZBR!l~MyPIAs&T{W-n$f^Pl_4y z=lP(Y|M>h_YFLb(Oiu4dQO;HnHTRSs_bzHHk1Fh!4FR$*QExR29)(LuC!kTtT>EPtN6` zI+dRZ65&%Kt>Sz2*(w{?|M5_GfLBlU?cq38z{=0r2?TM47vBdReYOeV%N&R84a1eh z9eeu)*YXoqWw0q=5+19yw&4B zAtX<`AMc_+kR}Ezo>+I*A$Nz;neArAVqzvxzlO+IH_SGtr`vk9FJB#v9y|;tjRcvqj?pQ(bY$nJy`*z}(^qrPCDL`P9Rc zH}F_~T*&E*g=EvaKrata2x;+hI*L@JPfDV-vWz)_WxNBRCM@Tpu*cSZyi63RuRJu+ zUkJrOZ`Ri%J)dR|&CeY7M&S+fB`Y%;wh5Q!zv&Gmk^n;DmvQK@{autu$gXa~PBz%W z+DzfNU6EantEL)B>w{N3lJuBx9}dIAvm_6JOjvoK?*z|%Nr+vx*d47F!sk}Y`rt!V zUj<6Sa;KSM2w9#p^@cEN?Vfg^nPX2{?JDWpdM;lMvC*#Ko*ni%*>B-2b zStc{GXy%xV!OwCb&VreqrIWlPVl$(oZfnvTyMwQ97G;o&%It+f9f`dOgCuF)8|JE& zL^$ZsMMU*{xs+6L#n5eN=zH5*?k)|DOhNBz0j~aUiAB?7k5%304mxlAZ&+BKH!Ij} zOBdD60!g+!q8wDi==%OKjpBqHlKj_w;ta|>_l4s>3=cnq;A1}csPwJ0L`(!?RX*sX zp7th-b@)5gGUyWcq~alzxp+IDRew1!f`*1!`IHj#>ahgMT(wY|@F^%#ORL6?ldPnW zqT$tyhfL=r06&r9)H?-b>ANIwLw}{n_52()F$;CM$4gPK;Vako$TxpQVL`_e(qq!PDOuRMK_Q;$L6mcYmv`tv%bDzN%Pm z^B20$R$qgUk6o8xaYI8xjo2Z~T4fB3j7M*Aad4hvepUs2mmvz!@ie&|_vX*fNAG*= z&-Uq)goK1;hA^$>t+Q$4!<`*WW0D8g(Y@w+jm{ss z!pFwcYG&WwXs7h^@bk~i%v>DxP*I8aoc>$w^n{7{e0kE{Iagp==0Lf&d%#_sr+1q*J;U~GfgVe_m6&L_AP3<-OzWLr%`6#QR@NA=tSwKLW)zJ-d8Sgc|<6Nyg z$^^+4c!~Y_y&V|w!*G8ttD)=B*nq_3XxH!GO+mgZfff4)8+aNF6-U$33M{Bx0sU?#p;zU$9;-ytrI5fQ%0RPw2Ro1*3KV5RdO61 z91ac-sYppVGX_aWNRpD0z;iW=6Bw;j7_R?uFa5gaZsVIsB|Pk}5|z_(FiZknMa8JY z#dl6lPH$qmUf_j4dE7xfHaFL7(VuLc@{qVI%WEkuG4YMQH)5fQ$mrvTyW1PB(n+rr znW&fko6N>>JUerZE;OI<^+rZVkCuE7pS1d_tE=loJu3QXB@Jd{at(0T*B{l@u0xpu z)k%Su{l>Q^Vs~7>jIPcPV9u)@Qg|YXsi`}5dd;79K z@Mb!YalwDS-hnkmvAM9emb>i9V*tSZS#t^sCiEu8#l^9ASaZ)EcxDXp3JWickDFEL z2!u6}avgjeO8@4~yXlsbA)&tIcUD$b{{F4L=ui0I zcRgPwp3CNOym}=;C^L^4)ipLb3E(ssz)y}e(E89TPqR?9Y+CgUJn-H{y6N-zA7Z(=^4w;^-GBPqEn9F<3UGJLo-X^!Ti9*Lo;8JAK-2($k$RCRs z2L}ffVe1bixYCpmiaDLDJ9~Q>-x|CLQb(Z+<77JY=varBFMaB|^~&S0ZGJUkGJC%coSB6qemvrFFFS>Izt z9TgN6Q`n3}eb4vfVxqd4cPxSp6 zR!un0L|G8q^oBzoc*1T5 z(zxzp2L_cN_04k@Hn!zjoAF$kC}E2C80hFFrKQFJmlngD*qk6x8PwbBdV728>dqF4 zeE^qUU!K&})nVY0U;OLDn=}ga8-5FS8c$?YpDNeq1M74@S{Ir{D;E!sGZ08ML}ZJL ziWu0~kcMno()#!znxHG{Hjb2-_~YFTGKq>WcWiuI>?CdY-88wN`wke`Z9N+^a|VZ5 zsQVyd5q5QTb>qK3LifF zfIt%**xA{gL8$gx^6qh4V>4>u=i(Z#kx*8SJ~rm&%YrnR{0;)UkO(#@Ia#4c?jJEF zWkqQzi1rI0Md6b3Xa1h+&D7`mEen{Ek zWu>GbCo2Oy22L|FGJG#LQz{K%o*-3$t&*3Qj|&hD4i4s^!~_}GvGq(#7uKgr`{qsJ z*NXuw(eZ_a>x=bRDt>1ZgFa$mUFuq$x3*zV{jZODa(s3fhu2c^hFM|z)k)0SJ}>d8 zM9Y})lM@sF4pkzTd{sW&sJXfx14z*Rp)(Y1`-_IGtn6esnPcPc#Y(ly^3LvPvU?Nc z;8U+w#{bOD$A>(hcQS5tUQIP?+m6v``FK>`u;jDy>vIoPU`s)P#lUnsqIr*riAgx> zu;nCX9NuzsKF{a4z_2)A!ak77v3|9DcPj)wnlX!Q(gywdcOXk74KjZNj%GQS4$RJB zwwm^QINhb*@A6pRv8mwucj|wZAiDR3*V#?uK6_@r+;#)N)q6^8|KYd8PU9>M3)Nu% z(XK45tSYHofM11C1vJ*wsIN+h-CYh3=ZFOk3_3P#CjTPi=H=~%P?M9AHg6{D=R=Kb zZEZh^H-6|u*OlExAeLZWmF)*kumfIr^x;yg@6D4Auw*f5ZNeaGNj(kG)zw|T9P;X3 zDEs--d4Mb*niC-SM?5trCve#xc`0OZ>f>)|xpn*;>{L5yvhw_3o~Un?F1xg{O)q`N z6R}Xtgs-Kc@vePyb@jvM=MfY31;3L)GCs#=*IZednFeQGcjr!bTke8<4s#m1y71YR zoLhK~#*>a{aL!VTE~>~vgD#=i^bhK657yjl6mYqzZS1dkshSJ4gANd`{I;{a(D}L! zPT}K$=QTOJ<=zmFT^Sh>zz${mD?k;mI&bTBRK^A=kl_)0RvJ^i4OM}%ekvGb3H&r&GKok`k76!JR%~0LI zfZXJ&SRL9orIg0mwcHI{X^eZPLIt}%e>MNjOl&N0*f2_;cdLwMycvPl>r}>WgFJC; zMBThLWBI_0E}Hi$)Nj>cAX`-ioRun2%3gsJ4`GLGm42Jd_oEsZ7+~{v&z!+8EwL@`zxxo1Rp46@E%ma z5Nf_=<>PQsWYci*9PKWmX`8Zc8nbxVAK_MAFJ2|<>9p!NCG=_$tV0{0QHh3zMq}W| z?!>GtiUp~nk->DHJ=pS%BmR%+L32+3tNCTE$(_Y4eaB{a;jj5drzQZ%$s6q>A|g_Z z1DZJUF40!K}2A!6Z2Mc+ZuTKFOkdBy0v$wXs~ME)3@_J2m*g7olO7s4Xjsn zb#-J^l)uyZfKtJbqx&w!3dD!o&X*+78!}9i-)C3*nTbD%qiw&Xr6r2B z`LCCMVBj4H<{(hByzKw??cw*mDQnaCeWX5Zhxe+LHMvap;TAWOm009SMJTPHKaeY#%dxG0F!-0b**4X6Ns>a?`9 z)u>)TJOCdA>0rvRbYWy^U(!3*R}kG(1HmnX-^&(J%I2E7y&6#N2}fFaCYuDLcnI}shi>sKQp9i6-83to{8Rd&vT3yY#91|m(cQmE%wAk#i*O)?-gX$n^W8XDy z8;1*f>}tr#$*HIeudJBp>FHToT1rTK-ZsFOxj!F=o&Oyg2r;B*OX8qM%W9~$p}`Bx z?Ch+du+Y-n+}z4aB};I!L27+}w#KRL(vlWAteOuO*LnY*8kW&8f1o0Eb2{(TPVt@Q zeL%qNblW-4EZ!s-L?T9qSx?N(zLnSsvJ!xM012QSDQc3Q^R<4Lu3lu?QC-L2_gg`B zY-@iBwxK_n1qSkkxn>XuFRI5Ft*)C2%T_j4!`c1-ifx`qEu^4yRc@{x3;#7Z;w-MoB4>Jg@RmwD$H<zZ-}AEchX4MC;*j}C?T_Zk-Cb{s9WJ*oH(bFOA~iKNL7J%BkF?^=sBGRXvC8q+ zT6Jl^-ekiAxpc9)uCTDXwXmpY=bno0PcJT(Zh!<5D|{Rdg{}dV8+g%4r4ZO(11OuT zD*&!9+7Bao8@!{&;rA4KDd6fL6!hR80G6j+VQ>$Qbl>R%7dROfqxw^meQ(-`ZA5f* z^c^zr4taZZc;$%;jDNAwCC|y(5a7eq&(1*U$a74{&Sou*ygP6TB)b?Rv|E?$TS|dI zncu!mtfTQDtDBY7($ezrK@~aaYDvwEjNq@dwxf1SAD}-4Jo)H_w!!M1a*+v$0Z7<# zG)e_g;gj8kLZP;^eOdpNMx!JcIn27BA)Q4#J3HqaoR+K1!VVQlqPt5wJapz;3mp*nAq#cq#cg*^A2r#b#AWeJ`|GFLc@nYWydDF*Ww^_n-I z&)HcphlPb1`yF)wu2WlAcZuKxsRO_m!@!%f>SQ8qpnL$~fxQ0_p^YFu%E*e!cfSe% zfApnNfR=!1-Di&4JrjBP2nbaD;!kr!1K%$+mLJF+%z;JPywcJ=ux3aiN#Ijp*lpks z$P0alP6Y*pZt~5;lG2L!asWS7C_k<|2z=x_b8rsKVSl;(9#%zHQqok5y~-FoACba) z67C6T!DfoFqpd9ps2Xn!jWso2WPE-c&OGDOaK%8!m zsP2wN<*1TGJCF{`o28zAitaYt1uZ%shS@!Pp-KqM*><)M{Gu>wC+`+Lz+Etlhll5$ zb!_pq!*6xZW*S}AsqQZ1HWS9LZ;|cDdH(%TbYloR1A48YdHu%4wVy6U@PH@zEiR(KOdLcElNV^9P=Rz3RLO zcMvY;K9@cEb~D=SG!G1{-hOtilD2%%vb3T?)aP`ECRX@$D-{>4di#0&X0#M^Q zK67nNLPBN6?Y9LfMpzYZ*2TyDF~`Tp3!)4S0Yf-YtIk_=Ou^Z+VkcfJ@^9+jM8Q=8 z1uY-i*x6kHs6;i}hsL700LYsKOUo4s^)O!|7AO@g`t^^A6@<`xne<~QgbLqGA1uPO zc|XVxKnAzxn;0meY8sMSR@G)bxL-ya+S+b`3^>MP8-^t20~EGRM3TyTBaQ?5z*#UW zR^&X@o_`a7GjK;ClW=X9sW*U`7R(?M_+tbJJFk3l8k=wRZP@?a;%@q%15g`(*bm;P zEovMepvejU`}L@r%wpE>zr14yjLlnuIUw1jrXYbc{iO`v+TQNbUcUNw?9dCZB>S;l z1+awQ>K7v6y_=ht{b~kZ-KoDa;)!0Yq*C>-tgH~I2*1)7*t)@c-P3@#TN!w>$DvPx z8T4;Vk?mlnil#9bWn_7GW_+jFE4~Nhv2%y8$_-93ne>WRiHi?;d3YEP6RUxP>ENQ& z+S=Fd7neU}8f*`uaUB<)&LJ0eQoaT-$uuD@%Bf0c>En9zUS+#cZ+DgWxst@CIOt-X z923|vJx5G=Nry!UiZ$-rez&cLr5O3h>n-x}^Ak_yeu;*O%I$)!R1;Mk198C*D1Psz z0iBjxwdW4QqoS+}oB-6LK&1Gw#7ui&`=KRo#=%B!!q{;bXZ-jd>Wn}45;CA`+Ko;? zg9YS0o>o!V4!|ZXEUfg5jLDbl_uPoTas`ar948i}ZPOZyKNt5x2*{HnQF-W+S&(h- zUp}|j-f*cj)y@cp$Z8BVQoN8hq?lX`xhlWg7;t<*w)3O&*G&D^CnhxDiDFpAq%J(9X#rS>wNg21RbIG|-{xHvUM z*ZPpbY2|>;pN4#U(cp|W9YXN*F66@NZKS#!u5Mc4Lva*22hJb44p?6$g z`@staZ0l?<2`JBQysa6h8VqG4Wh zaA$65i4`ZrjQ2QBL=tErYLkC|*3_JU1#&qehv0`0&_fC=AxN}%$KrW~7nR2=X z+uXgpRMNS7Yd*pYQcxLv0s*~{()FI$(!N&24zvGINlT}joLo=Qp1!_*76f`)9NErd z!G+lqK>e1LHQD2ZR&IU$IiMDZ)Qro3V=QJ7;TS40$ALJCJ@mqwW)*$6);zaFWHN2Y z5ZlU+RDsu3bK=A(3ICj+7led=?5V%P1=rpsEPAIZ73KhlcEnQ@@n1C^0Z{!)0$!PC zq0I4Y{NxWyCXM`pmuL}xWz!>PVfxFY9TA{2QaiZGZ9CxZYFS%ITk~rIPCC(_2s&&u z0P*sMSl8_)Uac$)uUK@BUF74Hg}p=eB{^?}yQWBYv(}e$+n05N~+2 z?+KeLIiwCaG;dGUD%I39{tro@GCO{!Q(->kPA&ZL-}gbwgo@tbVZdhs1At}#pjp?) zsNL_yH^IpwpU6){l{}ZwIgT?9gEt!KB2B@gnon0KL{-i%{7GBG6~UQzjgwQzJx~EE ze=E>c%<99SOqMme=h{Sn7_zDj-31LjJ?rBs9zBy~f?;0yu2K6wiN=teHT=@K`radB zkM4>$xKUkI2-QAkobXiT<&2+xw1Qlsig^~>kd-Zd8&?PP z-~S25BKQah2r9{4Zm%yv>FQ@;;TAxoE~F9uc0xCkb5B<0v$;e>4CT3eb$1iuZ=x^f zIe#%*e>=pVm1qgyS77#4rhR>5$GMs%=%Fx|P?Mi8&6^Mc4gFbFH7fE_W`$HTlo;pj zpXcpsYtsv+RgYZ=G<9@{`?vG*;s6{r>-yQER@5u7YRn(m=E zNPg8zmySS6v6JJ^8cLv7p%iqt1~m{UBui~Fj~iV^aG~#Ea9OiK1hr=bt12OY#NHrb zC<##YZPe+oOeck0Ll6v+44o`q5Cx@C{HNLHR@AMPE71C!uWQo zzH}!XHj(^^*zz4!pV?&-&rA?ajzRV~sBI7D+yVGP`hzINfB&~3mz2{NvYK^h4>pp< za+s0Y?jPfUID-SD&-wl=Q2d%6nM+CrZTo_Mp^$>BqwK3{eBISuJW~1b-q=!RT?jBH zm*b{JM_oX{^0vSII;wqjr~r^Itx6;RX+tlOqdx=_`b5;KOQ3ZS*_9kNi zboDa^WonU)^Tgrn>*qrq9t@7qfOnrjS>K{o9wu78Vxw*xIRa zH55<|1*@1C#Fz!!X6?^(R9Z3)yO9U3~a z=_>!|M{WJjmX-yAYhqQ)|25M|#>PX{1Ec>r(Z`Z(P+4KH4M16~xpf3m!>yw(VA4cD zoB;cKF9gS!Ds5bd);~2}%Kn(POAlo88`N2K5-4p9i``uVjQkK;0SXu4QQ|xE)}rT+ zKIrVSJMhjUo(pDGl$8zmGZum8zP{rIMMp=(aNzC9y&Ho9sO-)YOrd2ruJEb$Hdx4# zt0-%?O*qfJQ-v;6bJ0SCB>upF_Eip4ml_=njScUjji({X%F1I@gf{$%Q?J#e!ax3~ z&sFmDz%sqX1KIO@N!%_)_u=Y}ppeiq)oR;eWm#D!AVy;aiWWo$4S;9PJHif%q1lnL z@@7$o%2xQ>4lR#6fE3%evoI_9~SHeIvGsvPEd zy>?51mQzxqS8E+t3yaBMhy*g894L!EJ7+q*p}=}A5LTefFG&v~yf5Z!So><}S1et7 zW=2LAj1EwW_RenWEqo7sOLz|7a%JDDbBF=!@5P<#U*T5S-rzp{4L~|kpzc6ZdVa5>Ty>KT{#rcANx5G&8$eV8%F6KU)hvUZg#hAT4_JENFlJ86utWir4IN z^z5;gzP??Zo=7aF2ws*yG(SZU6l%(JYaUB5u&}(48TH4Y#R<{Cd!1Z-bN2KmlE{bp z8DdJZUi&Sc9U*i3pC5sUHkCb^qZ2J-<2%4`sqS@sKj@NPm8r}O9#O1$R=t0F3dfTw zMUB7zqrEf#i*b+Jc<11hr9u)>C<&#|N@|W!LPgO~YN)g?w9+;RNhuYj{b&y{HE6|_x)Wy%XPiK_x!kd5KYV^-|!!XqVLxgb<5Z) z2($EUkIJw1P~IH$Z+GfBc4H*7+Wb>i%Be`b)2H|HT{&Hq$LoCa?b*eN*n4sQ+zINl zncNfSe)~iR=B*J#i4iq-=$TIE`m+W{c0RoSm+xCu$M8n0$3ae--0GG4b9is4mu0$q zYDqY;T_!7YAz-7_t<&qHeCOYIbBe`;Dq(yPvhs&N2W~H0Ddv(t--OE7c(ZH$lk(dg z61&Zxjluk@oqM?Gp~z1^Wze^p=ZY)Krpvm2V8E~F=qUIB*?q^$s0-a5xDIdw5I+&Ff{%9X7>8v+mZ=D+m)&0g5GMl*tbo+%N2_eWshs+^3kMJJE? zUib85K{=N)7Wnec*I#pXKt^Pp(K95<6&JK0+x>1VH!X{6IHFkK=HNiFMAe zBZi!I~h0i;lMact#_{ASdYAlN>Ms} zyPTZ!=YI~T7h6O$o%^v`L+|L}!-sWrbWl4^W;{}UHvE8hn%FSx>bYKOnRcSIn9vuu zI~~0zL->;4`f^)ZSnMEe*d--3EIjus+o*pg*0iQo zx}+Iu9Lc|M$@A#AgRZ-MPG9H`j|n{9G4{waTC~FL{zVJ3c#G&U%Ccq4LIiz_oK8xJ zO_+8WTU?>&EpSJKhVH-q>np-z0RNM<8RbBZfHxH=PwidL(?>4GlNnC4W=|E#h@Bg4 z+j2!&?2~<${8D)msVtrMM`c7R{+NF3@nH$s>Vo|DHqR1*bNUDeQpwT8s|Ia-S9anhZWCS^+LjH?L6Q6s&cD9C?NDF0 zFP>R%iL@NPaC!h{_J=Eq*S2qJe~*tqwZ<4Q$ewu>v(HQ;DQS~;l>a+wVO{;y$%Cju z=vkJsJ?rlAi3pQc^o8Df{o=(SgqlptgPCzX^P&}F3b*!7TDyG}4E`ukpq=-kj3y%G z0E_~!+r|FDPL}nyhH9@Rs%G{1AGi8GWv}_GN#^eZH`=ebLtUt*Zr(Lm8$qW{S}E>Z z{V`TWi78nPx%R=Kb8z$v7-vF6G5DH0m~Q(fK6T0#h?+emx`E?0cxqGV=F!;j@L9s| za~^7)5DW02IGqeV8KvUxFwl~!4}c&Q1Wu`W<^44^l+VpgO$>MX172>clBqrWO}1jo z*Eq{5D9n6fk9=BNm(g+Lsq%(r>AC{qVd`D-h17=Dg`f1AH- z2cHK|*Rz6x8z4|7B*ZlWpYFY^9_nXlZvF)l^@IeV7UQcKkL$En-5K4$-LNQrGVCf^wNrYLK!jN0&ijQx;n(5(lQg5(0CeRR@|rvI)Ox zLP5cSP_aVR?%oMXAdn5~~f!WJ$iySXX18d}gx@L|YN=h(c;1g365e(4JOMz#Pr%EoDUS2)gU}^O;|$ z^{eMeNnc>3hRB+lN?N`qO!VV57)SI(A=b?)#!h}UCM6yy@9hVhlA)>;8@P^eg?x#Q zjrGQ*=DcY$(9n2~Rv_IIHf>Z3O?(lyhP!!`=KqzKD7A8YzM@@4E3;+S#WEl7VNDU` zt6M{j*gu2WRz1Zx(zoMDFfrVs*Dqn-(#s~lKaPmd6#IgLeh?6ygxvLAIMxNtKX{!< zL+jT4_ngab{z08mqK4IH-IIDrqxIz48+mEj*bM2S2tZAl{)E~EM>HWJ0X&taPEU7{ zyX07DGvA+=S#~|e2iAT=d?*A=*B0Mme&xy{0F)R7TZ5#9Rx)KY#>OrD!|N$nBlXcr z87!X&hWHoWJ*FIE0|U1L*Jy?>BLYTIz{3`Z?huaLoxD}_7^ySxJ}Io6w^m`5+(mL0 z_4A$WrERs_mi)DfpiaY;&#P(yTnUi2haOpkZzgCDr?mWsXmQ`(UIulT!s?j_ZFmBB zX0f|>(Rldeu=kLDydii;(56#uGNIWc8q>R@vXfDln>L4?B=gc#)g zd%EW1M^WXgUmwD1ubG|u(GVSWVe%UM6rwEl(!z8=NCx-C!p_~S;`Ry~iAEy|BNXu^ zMqpvrtzW-hQ1JV}fMls*DCaraESuyT5%X!7nXPZ?HHvvRDK3n2*p8u&-uA`tdEgU2 ze3iD(rX`i=Z6Wm?@R+tjkMv4+hoq#Wl9K!UuWv$r_vPi~36;}-SHemU^qr^(*HR`S z^j{w7$VC0}8<@<+bLVDiB;(D|i)C+6a=7S4)R4!n z3#puccQbeth!41V#4&VB1qB6(n!!l7HjK^#RaI5~pO|7cwzmADhc;~7;eqB>8&nl& zN7mdp33d=BEGsL^*~#fQ{ttT!BVWbdm-g~yxGbfo&HEel7z&E;53QF#&wwz#?;S

38AL+`m!F?Ep?#W)=XmwsxD1ujT$vKR8S}7`GOzAcgN3j85NF1s z9ew7%`9TU!d+|a`Tf3pYex&)iu8B#{%|Dj>#kV;hmNGmrlZh&FhKb0H-#t(Ww=8_+ z2FB~TIMYtthKdp{${GKhoKRart@o*sc#Kzfk8!H6cjv94dgB8ekiSCq%^tb8iaC=( zEx}k}H6-G)-@KWGb(xuV+Qh_U#3xGmW*PpN)_s)r6B;?&}eKp zXn@xQRkVo_`lkwfp;3IfSII@1?zmI8Z|3IKj*h1tOHY(~UhQ~&ndl*nn7+r;lyCyF zCR8GQVX-fm)DyJk8j!&Ir(!!Lww*cPVJ`_z(K)BOQ`9JG>g^b1?&RMQ@UK)XJKB^ zdzTRz5#JWSVBhijS$=+gm{i9;nFG=V$dWJ#J%+il z_}qZ@5=>QLqdE^^j#c^#2t2uJGd%@u=B#dm;|H zhTKU1iZx=td%q4O}+g=DfD8ZFmxUAc6Oph5^vsW zCg5Nc@9bIiZF&1i1S)K7h91s?xqCDDm!p0Blh6MZ8*zIMP>jX|BED+dyve{H9>`;}LUEhS20o4)wde9QWti_s3 z>B{jXND}juAGx4i1Zx7nkD(q0^GOdn`4-NTqJ3uz?d1&OLOD>dE_b`)U=n+tZW&(^ zMaELNZXVnmG=n`yaAxGG6~t!|p6HpGK{rYD_A|!Di%8;P*TM=FZ!r8N3%}}DNfFDf zaK3Lgx6u5NZL;4lr?OEK0UonB?^(LT-0|BG#uOrF7Q~5f9$Tpc@*T=c*FN#SNXt0u zISpw#Dgz3 z+=)ji2GQL$<5&spAz(cAPfb#1k-K9km2%+%vpJqE|HkEgN(FK_D0mqQ_% zqSnn9=*bIRWs63B^`@g@oojex>C_I9C6~3dYA_X7D#ns=Y3ZW_puw0FxS<(8v~^>Y zC(4)bzcR{`VX{W>DhgcAv>VMJV8*LS>}#x0b!+QEm`xxMd=v!p6$?K|E)-M?}@b1-qRv7adWG;`K<>8X7UxLsTq&1SojnrCs*j*S=NU zMa4rMJW2W8Oj>MiYtOU8$zfPPU>*xySEiu&!%-U(^ehmD9z1w}2FtB#EEYng0|-(Q zXNn}7CtvX${mKsjobn%jl%l~EEWnH)P-1rUHU zKxIF-)p@%D(VC9&l+=wo1RMZGqlEKH0!vBJjs{S$_QKapPdJuLU>eiyIJ*Gh_ays$ z_Z5l13IHs&ahFTJuY%>^WQZh27n6x4mpV(n=5A)#M=VQmc z2EvUTti3asz=|*w7I-0pJ0q@_xM}ll=Zzq$<@rWBEzmyrR09o!XlzpxZdcre;GByl>O4rdS(f$e~nGd_E#loa?MRvF)N=H0t@ z#WjOQ+A}C_#HC@SV}*j)LQ-~b3iW^l4K8V*5Z(!0-En%>z}@x04$&}LevH|* zXOAkB3(1+MIM@`3K*G=Y#XmJQWoD^8Vt7_x-x>8RBo8bOOeeA*`Rv(j&lV3DNk9P9 z%s)ID85!xQ<;}EoMhZdE2M`d}{Gf^P+}k01)1z%i?g15GRa8=}&Ds-isW?|OZBzKR z=pVe10G+m|d7*8<{Q+Ogl*@*LW*5+5%zD6lK)Zx{hfpG{Xm=jm73vYxhZlOqX3rR$ zJBI^Q2WPF_BHY}zg0#I?QBl#MT8Nv(X@>jVhXH2dtXj(pXEn35S5@)~3RO|u{*>T> zc&eJ35*y5!WAD{;bWgk@2VGEuV6_Dro5|+Rp)jqhs|((IK=0zkFKwj>!?ZMR^*`ky zvW!zXEFtQv)YN>e+6>!=TwFiH_shwN4{OU9X76Mk(BAgb(3xjjo16frZ=C+lj*E*H zdHkJT*ZwnkTikSo)<@LpzUbp0)+P=DJ0*QWo z*_sBVujxtw-R;!t=C(p%5jY~Gfcr+d#bN|w&XCh}C;fuAkkr`KP{mO`xmYbLQaz$E zcs-=*Mi?bM6Um#&WMXXx$zo>?=D+-d>vQZ;;qc5SJHki{VEP_#CUDfN+o3Vy;|_eU z*udzW#L$Dct($IzG-puC&+h?7XbuIjB=q!u_3g0pIO(MK7} zjORF@(K#6*qi}vYbk)XW=Wdr~ZNfS0^YhN5y?kkdb4D<$yfBuMWL~bDW82X+AON6w zN?)}vpdFu$${Tv)NM}yklx@55@;et-B5NWMP9q2sFx?AX@7?0!iD-Wi4H38z*$~=P zU58qrwBQNo9#F3^ti#3>jAtt9WgLuogF^~9mVv$jxbaA98rj3c?=$%Sd&7UD^xx7Te(U1D{qSGZ_