- Typescript, React, Remix, Tailwind, pnpm, Plausible, Prettier, ESLint, - Plausible, clsx, pretty-cache-header. -
-From ec4638a8afd48014be9d5f27cf4ab5a191a5d799 Mon Sep 17 00:00:00 2001 From: Christian Cito <30470476+chrcit@users.noreply.github.com> Date: Sat, 16 Nov 2024 15:11:40 +0100 Subject: [PATCH] refactor: clean up --- .eslintrc.cjs | 5 ++ .vscode/extensions.json | 3 +- README.md | 5 +- app/config.ts | 62 +++++++++++----- app/root.tsx | 14 ++-- ...ifest.json].tsx => [site.webmanifest].tsx} | 0 app/routes/_index.tsx | 66 +++++++++++------- docs/screenshot.png | Bin 0 -> 430365 bytes eslint.config.js | 4 +- tailwind.config.ts | 9 +++ 10 files changed, 110 insertions(+), 58 deletions(-) rename app/routes/{[webmanifest.json].tsx => [site.webmanifest].tsx} (100%) create mode 100644 docs/screenshot.png diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 4f6f59e..43660b5 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -35,9 +35,14 @@ module.exports = { "plugin:react-hooks/recommended", "plugin:jsx-a11y/recommended", ], + rules: { + "react/react-in-jsx-scope": "off", + "react/jsx-uses-react": "off", + }, settings: { react: { version: "detect", + runtime: "automatic", }, formComponents: ["Form"], linkComponents: [ diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 91df13c..01f96c9 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -2,6 +2,7 @@ "recommendations": [ "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", - "eamodio.gitlens" + "eamodio.gitlens", + "bradlc.vscode-tailwindcss" ] } diff --git a/README.md b/README.md index 56cef24..4e70a76 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -# Arthouse full-stack starter-kit +# Arthouse full-stack Starter Kit -Base starter-kit for full-stack Typescript+React web dev projects. Has sensible defaults, clears out boilerplate and adds minimal utilities on top. + +Starter Kit for full-stack Typescript+React web dev projects. Has sensible defaults, clears out boilerplate and adds minimal utilities on top. Includes a `.cursorrules` file to get you started with Cursor – adapt it to your needs/style. diff --git a/app/config.ts b/app/config.ts index d165139..c8664f3 100644 --- a/app/config.ts +++ b/app/config.ts @@ -1,6 +1,34 @@ const productionDomain = "change me"; -export const config = { +type Config = { + productionDomain: string; + productionUrl: string; + themeColor: string; + manifest: Manifest; +}; + +type Manifest = { + name: string; + shortName: string; + description: string; + backgroundColor: string; + display: "standalone" | "fullscreen" | "minimal-ui" | "browser"; + themeColor: string; + orientation: + | "any" + | "natural" + | "landscape" + | "portrait" + | "portrait-primary" + | "portrait-secondary"; + icons: { + src: string; + sizes: string; + type: string; + }[]; +}; + +export const config: Config = { productionDomain, productionUrl: `https://${productionDomain}`, themeColor: "#000", @@ -13,22 +41,22 @@ export const config = { display: "standalone", orientation: "portrait", icons: [ - { - src: "/icons/icon-192x192.png", - sizes: "192x192", - type: "image/png", - }, - { - src: "/icons/icon-512x512.png", - sizes: "512x512", - type: "image/png", - }, - { - src: "/icons/icon-512x512.png", - sizes: "512x512", - type: "image/png", - purpose: "maskable", - }, + // { + // src: "/icons/icon-192x192.png", + // sizes: "192x192", + // type: "image/png", + // }, + // { + // src: "/icons/icon-512x512.png", + // sizes: "512x512", + // type: "image/png", + // }, + // { + // src: "/icons/icon-512x512.png", + // sizes: "512x512", + // type: "image/png", + // purpose: "maskable", + // }, ], }, }; diff --git a/app/root.tsx b/app/root.tsx index 7041477..edd1537 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -1,3 +1,4 @@ +import * as React from "react"; import { Links, Meta, @@ -10,12 +11,7 @@ import type { LinksFunction } from "@remix-run/node"; import "./tailwind.css"; import { config } from "./config"; -export const links: LinksFunction = () => [ - { - rel: "manifest", - href: "/webmanifest.json", - }, -]; +export const links: LinksFunction = () => []; export function Layout({ children }: { children: React.ReactNode }) { return ( @@ -31,7 +27,7 @@ export function Layout({ children }: { children: React.ReactNode }) { src="/js/script.js" data-domain={config.productionDomain} > - - + /> */} + diff --git a/app/routes/[webmanifest.json].tsx b/app/routes/[site.webmanifest].tsx similarity index 100% rename from app/routes/[webmanifest.json].tsx rename to app/routes/[site.webmanifest].tsx diff --git a/app/routes/_index.tsx b/app/routes/_index.tsx index 3abedf6..21429da 100644 --- a/app/routes/_index.tsx +++ b/app/routes/_index.tsx @@ -27,33 +27,45 @@ export const headers: HeadersFunction = () => { export default function Index() { return ( -
- Typescript, React, Remix, Tailwind, pnpm, Plausible, Prettier, ESLint, - Plausible, clsx, pretty-cache-header. -
-+ Typescript, React, Remix, Tailwind, pnpm, Plausible, Prettier, + ESLint, Plausible, clsx, pretty-cache-header. +
+7X=m zLj6f)4~idRYa>>i XzuUz0@;H&BE=;d4@>Au)hokwbH# L&pkv`wtd3axSGyjS3R-iB@tl%h4kFcf8sF zUWWXUdBwiyLFPQD!Nl$5zIp5W*O_|7cZ;HM%>7ZS;^yY)>YH|x--|8_lm*Tb&xV{B z$+*OC4Sllz+p2wSp4L7Rx^h_p<=2fPZgVkDTuSF1p?O z5V`WT^EOvriAX$cX?*dOa4)xJ37rCaZuJf2CJsU z1RSt`qobR$3|7LWTnNA$YVqjxpg66V2AmvO#3_`}domwwlcS IDim23KE{eFi37GWra5gN|*RYAPzylp{42%Rmh1GDUXW5dkB8lMwy zS9jH|;VR=Ym#hE33t$Fqq2&|mmskg+pBff 6`*nKpm9jU+(YRstq;#T6uq*Dl z%y0MjI{dVp$)91<9muxlj8^4Xc@~NYwJc*uw(sMgv=}i^Hv%7iwH#t>$no-0Ey&Cq!;Ceaj^pX|Z&9z@O~uyGl#PEbd}!fi+t52Ma3kcsBOe5>Z(Vi-Y; zV)Osw?aiZ--u|}XX0viAn@r8hiUuolB1I*wW0Of`r!*@yO)>{GQ$z$bO;0C>${|gK z%E|^6hZGF~P178yG$#}s!3n-13L?|X?|z>5UC%%7TKD1H>siaim$gLPYY(5#bzPrp z@7-5|cMD~PQ09r2?3Gh)-3P|8RoAZe*$}d?%mDKX6D~bBWQzU~_4xLY?|H5f9bMI4 zx3+X!4e8_cS}l?*j{Tlf-yUnz6@bMn?22f{S+nxemw( =n01O9AWxaip&5ztxp_;uL241Ry4)JfQK6oQQXBdFrV5Q%P>^T}e(Y^1~e zsSmN- *{l6K%4q{~a=P`Qra^elFne8L_&-nRA>3xyy_eLykOudhjx!n%vd1rMQ zN2f<>LOJw`?l6(Hb2Z!gYg=VV=%PDIe_B5Q8A9-H>1{_jb C za;r#Lr-jz$C{ACS_0;Ru>snpYoq>e;@}Jd3^A>BSu6Rw}SL>O%X8p-H zGO0ESi8jJFiu&_bIM!0Bv@Fd@2;-I(OsrV_;GTb${dixnF-ZdqQi3_$^nWyB=sFxx`!Ru&Fsz6LQ)!JD0%VuRR9eP+~ zZ|;vV=1XmeV|Imv`~nnK`E{-++0Y-!-Gr=2Mag1o@AIPW1SJzjDiiAVgVba~H|?fJ zltHWa_ftQvrz+DWA~aHAkINLfPR%R6R4y({p f>%`OsAJ+)^ zkcCoeo{5-{q$soW?QO)7s9(zWRd;6f%kaoWd0qExxHk642HM}Zgi#9RT`q(K4mlu$ z{+Sx ;_RpjQI;PiJWF%~OH!Yx_ONC_Fa@IWWQJrhL1Gug zk=VBogoJIwar~I3W?FGL<@AeeCeD-j9}tq$jWV>g!%D}QK;4Z1W2M?aB@IW8Zs9p$ zlyHTKI+UM!UDRD3_E*=#o^ygPJBW=v3nf3sZgLe+zTEq^L$^Tf%m%{XfW7J4gM`VF z$gNXVb)39|aPKEr3h`E cadp#` zI)`tm?FSxPaWqP|Iv#y*mLRpGe@~2PwO;Bvp0FBQGstGPKlD5sdVD-0rg+ZA1wFVT zoNbjuna$JpSf=aq=0#}L*6js{`i=?uDfm&1)7HbL?(1?q?iZ6?cx%$zn?h`%`b};n z8kG$c{ K&)5#D-&2_>-EO3C3wl9u>x{9N;Bt=X~pc1Z%@(r&yET**$)|S zevY3{wR7hdU921c2^((=!kNVvuF%3XuPVxJ=kMo;^QLVod+!*~Fuf8yl1@u~m +`T@?zd_*t(8|DQ0j{?5IfUXhf+nank&xng&u3IGGW-YXy963 z70c`B8rPewQ!tpA;cWfM&tHzd3wqpZK9=;o_eZ2tq-I7s2lrsgbzlMkv+mD e9J=f$vT}v_tX@?92x?VtN(_=<)sm6@w!a 8aMx(e4;RCs5ndE{N{U`D$z!-9YiwDA%7l&KeG zYHLv=YYcd7P}s%)Wn^QHWgC7g>gulOgvye=&F)NK+m@$z-{&=W3*{Q5>-uceQ`1kd zD*w-R+j;qdetfEkXGjNIRu^5|oTYt)>(sMgqnPw)gwT88w*IV4zUvjF4FN$E=1)#& z-Bgo$UzGI6J%ST#u$I1AVNMVi#TRh*W-TvgbI!?7Q9@v2TrbLgLZN?hjQTF?i> zzUS3RRG0YNF;W(FWIHOr>E;$T-_zZgQk24bp3NWek?<-ShlumTX{JIbC*SsY8FT7E z%JPb==l1<~+18>q$o7msIDYXG-Y3j-hc`+X^qWh?r?`o7{?5OlHMn?dfHR{8g()sR z4=jOpeYvR z%D;tIyh=#fGgT2dMexNiNw%AhCB3!lH&mO Kxq*Zx4Px?q89)Se(4cmTZ(of =A)>v6Cs;zb^St;oXx>3nPwl)rOVeBueqGrh&=%V1NvJ`wMO8>mw zO8}}&tbngF?Q1RJNRDg=2@KX^>ixe~o%$<{Hv4Bbk=f Q-UOmGd=u+oDOH+ou+9kb0`FrLWs^ZGh1omgU)w&lsJw0}A!A_b zY8vf@$p7ZZc-qvwr7Xe@C=C*0;>z#>6C68AI}% 3&4X+Kev}t8v z&Scef#lC=aK}=0uY`4jjK6$`H=8qE!1voaeilXa;iki=52xJ(|U%5w(D;+<+J^Wzb zu7wuO;Xj&8ekAss-oihh)`VGp3{tpldjz2?;E8sd*s(KQO5BAVJ%t+=jzIYX3@ybA z!zzp{7r|muO*PTH9ipyx8Moi pmp%#kY#V0Leq@Pm7Q| zq)7!N+DyK}#^{^kE7x8LDXQ8^>4R;F`@|Z0QQzpPw-Xe{{l9YKfx_?yyaKeT=0Qd) zG%j=J7C5@4b@0nZck!HrJ4HgIhU7~VH{ZR+8kKLH@wn(z?m|@D^)%%Qi0TW^L22k& zm~sB4E3Mz>l5PC9;^X0SEp9>H@{V +O`!}qGbsEJ2EO|fGRivwSm%xz_L-Ugf{n>q?n*73=ud!UA9LKU*f=y zo7A8q*3H@NjBNbOp_%Y;O(^&rs*yx+BKsj%B|umIMs#E<4#viI=rK9eF*ilS=6FF$ z i2Sl`~oyI`$ zqGX=6Z;|!*#}CLEF-wkAZssB?G+4QD3g;fGibK0&>B`nj8fLzbfsl}~joc&BEGSaq zqTmv~3^e6I|H1 {|S36JNwUP>3{vj;B$4Grnib7!~&lIETXX>e|(}1bZAc3 zp848$;7p-T2AD{7%q8%LG)f@HrQ42T$5>gRD^ORhtSN3HkULIRh@i{b%;k)cq@QfR zztd#3CJTB`(RG5 >GlNL#*}k35yn z0fNTyW4wL-cRD4Bw-izB+!WaYk&F?66cwSA+b>j!5dZ1>1=<#qJox}Y`iP;0du~5K zSTRcQVK#k~jC>B-SHGH{V2@1YGBd+C$wu8Q@lIW+pfPSdi_ =S7SvPJ)U>%DTTd!l& zLq{WH7wE`}^8UJ{_dZ4;ieUe`S(owRYX`h`Hbv=(SB>dzA`IFMp?HkSx?#YKmSHR6 za2v4$L}er{1YF%*RES0Y6}=QGE2;7>5(2t7V3-vxP3>RgVjfO{ICdcsujhb+J7Di~ zFR}w~Vb>RXh>^<|(mbuQBIE%njnj?7-Rl&NnR21|BbwuL!bUqiJ247;8j9=9F|kFe z|8QAq)NO|Lej`=?oz3&uDP?fM@(fnbow+&&QKd|=BgXJ#&BX~^2SR+_Y(`>#7Rzb0 zA3-kTL##w+igh01o*-yXAAx`IEak3~!W}xWx^ sUqZY@t;wSFKFuvz+Ut_ z^U}Q==mrR2WB3 !=9J7quh%;hEU%&lJBXEDyF>`!VYblNeDw zB#up#y KJFUj9j8oj9h1p7>e@W8aSvZ5B5A}pIte~$l%e8hfIH|70F zegXF$TD_*z@TSEVyH3MNE#k8IgsVwKTJs5ub)SyQhW^Z(Iw5-{pE+;=7x8<1@qg&! zxG7PBvVi;|@k{JiLzsggu3PKtRI({B$Ty3s&a0?#g-ux`BgOI?QM65y*E>^X>@Q zOj+;sArm1Z_O#ttVcl_AE+p9*F^SFpT~{wx8r?~&c!uj@5N?idk#mb5el*iD<9q)x zuK3?Ep1#4PoBCiT(Ew`n1F}roFvyP|*Jxw0=(QsnjMNn5OoRh3?d?!g6~xqbthHXJ z2>C^kpkPBorClr;j71fHqJ93gaOLi6eA7?10S|x6tXj4X4H$RGqnJ#JEwyTZiR9^2 zvRDY9UopWFp@U#wh3Ee{F8E)6A$_?_YncEymm-CexSzN}VT73_4sEk_BOV$*EGs)& zT%9EnLoP;OkN&6@i$F^w%LK@Ke8?D8zQ`4V6rXU&+ia~o@rt4IJrIL808(ecXQ;5J zWXeE@Z9ev1#?N_TdlB7jdW-UDYdL v=B@(OLn@7}?Ow5)3~3xpVbhdK>se+J!FWZtRHF7V f9d)KIItw()ofU`a;<1gWx?X;VbpsGkaF-J+7R8@F(&e5-f6~IQJr_3Nbu@ z%A2OE_hbiwB< w&y02O1N6qTk2UpXjaRPWpdNY*SlPQjU#qZXh zyX-u}Y$!;ycq0{iaoS~}vF}ujT`RCVmX=K<+u_dp-xqV@Mzl_S1TR;7PAox{&Pum_ zq|E|sE&$P8nC~ukVO8kG<1Wl(|0(v``E}O+d!+kq{Mkb!y)PoWx?U(??!3VKdtE2p zRcvYVyCB!ILS-;ucp>_|%_G!uzO!#%TQQU%8SQDKBNC6%5TlGk$K@DrPq8fbzHP~( zMUAu|(|%Oz-ps}qHL}Fh&=ZX8#{3wI(&~pAoy4SfSFZKC7O&62X;*@e(;z*z_EJdQ zaP}~+sGp)|q4G#BU%NF8TxPfYtC^|H(oZbmmRu5yvb+D9L&i>zvd#?9+oZR=pYzzG z`;o0X1fzpu@5A_~V~3<~maKI}y`8`M5_|3Ct4%q`%TX@U!(l#=yXK}h{s|eS81<6# zRbHb}%2TR=RYPaUkh|5mDhm>C!-?6eMw%OG*zE;naU=B97X)Qi;%vRZjF448zDOI` zX7#pbWCPbUx?Q3PXPBXq9F!V~ld$aukDK;xNWH^s1$C!Pd zFA0$wW;aK@Ac3#rS}BawQ7ZRB+%M_9gWz&~(kY`~kAJEdBxY8wSl4QHOFG)4RX5!l zWM*uOWUcEIcteZ@T6t|O9<14=>$=n{lUX1UzSM46-B DH^fpYHVZI^=1zUf2T4(li|!6A2H94y&K(RmXP8gV9X4KZOug z^QNJzr(>4rc~#gf&+zH|qbgzn`2*^Na5MT^jbzny)j-p?GM@^HUKCu+uACD!8siPj z%yA~bj(M{uwt7sBA5f=3m#mn`?zVlx`tdVN#$ej37x|Cms!#LinxII$*Py|i%y}Pk zJzGnO=2DeE9$ -d8V|&N@d$YVF z(EefL5)5M@%R2w>fhz$|Z29zD1M| Q|aO!c|FGp4B|)eotSa+y)mAut1rhT~V3b-K?24U^!n^IDvyO0x)A<9*N( zg=07tz2O1wSv#`hgP5y)pGJtbYvGyI+e~0A?TUVmcQ@}x#7gSLg|fE~Q{H_^Rh12C z?e#RrI%aaf%UedD@co5zheFgBb>Q==)5oGJ)7v z$aZw_O!%5cv|rPSjtF%Dz_fF%Q%>zwPr;XIM-@KVT%24$Qyz>l0_~Zh+HMWRJ9Np+ zPr`y&JEuR~COo`y_a5sf=c<`z2y|&=#nEqwNSex!;mFS7RSBTtpa{I-J-(B4*GP~Y z!-Kr87FC8k)r~*^>|yZij4|Bhp3 3F{NmTTb;dHJVlDoX>`m*!2r<1|$Pjcdq;{m$~-b>yGnb+c-yg)`-XDQre| zqGa7+953!e)UsIy_Y-2ELgJmV?IkU{0v>cp#I!y@S&GW&__eKyNiHhe)Me#Bf%xY7 z%;LUvh^QhnFpfHRnR3oNLI0+qyOK+tP%^2P@|ll6=U*u)SHvbI>AHI#^B$@sUMrQP zYugPa^->bA7$xa)RQh87M?Svr`=?=RS++Ye4W$TJ(JedLAs?hC?xwfaGny!{>VcnA z@Y?3@?v3sAtD_@H)v0LE5=A@WKws~0@X5%77MG!<{-YrP#zmZlBB1V8+}_(E)eHqb z$2WP1B)O`tYR>9u&P(8v=85T(!v-;UGz>@$BeY6<1~pnCZpi^QxWB&B2l<-TiZ=f4 zEp#bV2$R;1c*vG3rj=S}&4Yt_FjwXU8P{) VlWti3}%oL*OG|Uw1EmWkwGechm_xQ ^$D3H1}_Iz%m8}<^*ZRI9%#OHIi%GV>U_8q+p%C~M;St4HLuvL{*9KH zpFxBIm+uUz9*&}Gatp}I>-B;N_Crk-kloS_`(fQ3%-iv7WgCi&LV!rM6x?*iP7V6_ zye|v6OvD}{S$wpq>oc3I)+^;zTzs;r-)JLre dF^D oV-;ZN$H^ z&FggUh?^ex>!e(k+bKhBggnAFzGoR^;R${ yTIFEQN9 zPWqY}12#symPc&Gff&x0u-?o{@<=nRfq6$7P-6B#7J`N{v%q@v2C_YBjgzMQjQxrE zdZ9);>qE@mcTaO00y;E$Z!HrhU#B^iE8Si;ZXGIu@Fz7&l=8|hD@-sQ&lHyj?j3FV z0u$ysL98Nf@tr;;?p(}w6FsWQM#1$q2c;yOS+MvnWe6?nI>}?sn0GUPDB;hU5k$}p zXYal9Kx=>tw63os`b57T5lL9bQk|v$v10Xi!$f`Hv_Q`*vW)99s$Ocg%~oW%cd&}0 z6w;3YJu_r+cpW#u$Bt>LR2?6ow@6y<%WJ>SF*-B~f8O>#xyZ=oM;t(HdzrsJPaHJ= z()bU P{8-~U1mdA)3}Tcy#3OtTYv938 zOZ`50s45Iay^F4zm( 4ay{R~ADUP`a|S~9E2dWE$d%GAPK z=k40IpW~$TYGg6$EZs!78UKW0^oy*~LOL@_bbnDcXKq=?WSBsDRGv{=bUb%NH2g)V z9Wh+DQDIUO^gUN1GE-1>KI2R`%4)T|yUY6AK|B}c(lKyz_5-9jdhZ5NJYT&@50A`q z^EF{=xbg@|-z4T0A^rz&e wP@BEDE%MovGWk`9%#hRit?g`Viy<`y+m|3NTzQNc~Q_2-+oH z=ZlNyTrI{Hjw4lObw@lKFsqVC2krryYoJJw7jV{eMtU#9YgA03OYKBiIJ{up2^`2C z7!G6+NL>36M?BIfc2?5`uuZ5&rb71164Ws+0_UJ}BL(ckg&QVtnPqS-`cB@}DlAA< zWlVS3K`>x47e5BSqb#>E+N6so``zR_y4pY1)ebjR(w-u~hB#cl*X(R4p)}EpZY)4n z^bqK}53xyRz{~lK!QUgzW-r^_4ycXK-}$_1d0L1oy1C%99Ik&Od#|dE!tDwM?ZJVx z5e)-=pmv@sU*5Xw#C$*5?6h>771n5^-Da%oxWGp#?xe}9bShZlFdVvHGyW4O4yrex z-sWDi)`{t2+awh+ fCP2dXry4_jBJb#u6Y|LT? wUFgv*#`+pm^@!QkWfnEW<=1-+i8bWd&exU1_zI?+C-eBNhjaSGzw=qh)8{idrf2 zx|sy8>8z4 Q zBrjI~B)8T`eI_-SWi?VsY*?}r@I;wE==w1cF5 uac}qZ!Swyy6QadpQE%-NqbH-#fo$h#ZpqjkAiSDVK%ZSa)_Yl;=2=5+GAlRV? ztwL1<7cay*RSW#zqa5FWx56^;50m%O4w&o*g69(~tdCx!e8Bvg3u@B1tv+Lz=t(<& zaPuvLB(lmC=$Ip*nq#x{+@BoX f8F(`{N?V_yXsM5o z%zjB~pk*B&vgz3)r0<%{c(5T*zi%P&GCk!325x+6t&4gRU|#AVa;eSt;ty1+oMPzO zN_$)05BEm<$$= j?8-0H1=dZ2{qSD^YB=F$nnb^5SX za`tM0l0+!5ng 3p^^;!kJq368`Ul8 R5lxL#Lw}Rz4 z`nk;BIxoN=7wesD5OHm+lLYxFdn3{qq>n!MH@Ny_zrj7cKDlbaOc#0vm7t6mco4ud z1U+vXNQiAEUYye6k$+sTekzhcr4mIApD25U8xo$QEyx%H`>498Yo_HmefoZ%6Y-Pz zPxBc72{|&ChQcY>!l=@C9|f2d6^iD_0WpU5+(Grcimx%0^(y9+m8k5PArjc}6^pt{ zAg>He;R?e8S`lV1rH%!;Zl*I@+jifFY2sgvz=OrPVm0+erA;?X0>~E(!wq(#E(zer zS*=p8Uyt1Qbb0C* Jv)v}d<9K&*PCzI*ZOr*DLjQ|noUk1mcGps;4Hhzoc_j#d}( zrS0wBo;10+X?kg5AE78X;mR7^wn^1>U8Cb~23FWigzt3_h}1jH;C6C-eP)=_*|KGz zsR074o{#5=F+pW)a0N@q!J_R51-nlo9wOlH@nT5&h6;Ee^ntMbnmFI1b^U9WaQ|t8 zvaSuPk7Gtn;sJywe(8t-RDLE?ZdC5Pidi5%YSch{BI5_knn}d?to$DhzeFRLr2U9V zdCAdgTerv#p&n^-aAjn^?tSK1>T_riY|D?;%LmHZpH3Q(@$rVqH*xH#fnwDo;ietM zynO 5=JZSn!z0899KM!&NI!J7dex$KOXThjKIF#AL&l%-w+q`mxQvHoxPIJ#7sFK7pD zo{2i3v~=hQ<0mM&iSi&jf+X<*?hhgT#g{Xxnvc{r1ur01y@s3aM(n_^9|Mu(mA3jD z@r0y)vQaw%UaZ90@U_Zf@KJHDyV@&gvWQ_h=1Qhqd|QIPi_DA!P2E`DOK$zs|Ir7G z(cGtvBFnGB&Q{Mk|HlU(0|6>a7X%{{xA}B0Xb@f3PwpqgI83iohdsf9^l@9Gz>@YI z0*1haH*i|XKj=MzGz$o{M8s9%v@6BG&khlHP7^LinPgBlz4%Umb`CpUQSy@1R*%~` zq+fKauNCK2?W)w83f)Vft+Z8HAbNXl>}7Hl>K>1Ibc$+rM_PNFU)1LoL>=&hAP{j= zZS8c^t6W%oK9r*$!ZeY-nSRvIG8o2-H|2TQqZ7)(&H#|!Omf`2*>rAtN7_N0cR zJ{{LZG_I}^dP7gl$Bz}haEni%1^V{7!8bFbtBtx~HB2dF)3F0Gfvl=oNlsSR0Mg!l z#Yb`88y9nT%gu+iMFDUgvjM&_(nauYYX4DaKpFkQ+$a0ZmMYg*dzU4jhVsJ%GoxJw zVOR&=$zj98MhfS%SnOUyT*c`(_?VIIJM*FsHSeo+BO0H8lW;b^m63S@$WC$Haof5s z<#iQou6jr4iID<$UivV&3}&@_j-y#6FF+mu{zc>*tekz t)ii zaUfw(C8o=!YL6abBX)SkhY25G^aYVq8<5ec=g>2gdasc&o4$0$*?Iq>6Lib*Z;^F^ z0;+?+@^0AS3e{)0heOSAWuR;^du 2O$8tr~$Xzdr%5&mmb<>bB zQf#Iy;N+f!R}lw&(jrG@-tpn}k$Twt*@2@I=f}xLX&m7MCj2iMpDpx6sT>cKy>(rp z_bB2u&neLk_Dt?MvoNr!m7XLHj};<0tzU>a)gp~XM8EZnR4%`t$6zG=kOu8^m@^Bo zUAeA>cv;>*wB;h&@eQ=6VNGJQ%ZoJXl=$3gg0%+QERy1`y4-Yog?_r6zq>}h$x2vP zJ97TB-W||ooXys)_%WSeFrBKjDIsej1i Jtxi8!(I%+gkkttog2lS=nZM9>fIM4gyH-mS29{G8AH@L()%^uyqypz>)K zavX&f`t?7dl+)<@gq#TR;X5i*g0dAn_HUN%27E0G8473~qGL|I0xwZ`&MoAAm--Af zQ6Ul1#C^aQNo);-5o-4B{D|4pXK 6=~!c#3B%Mm86nl*e9{=SEkbkw`+3x%<)0A%vQ0X#A)FhS}`ro9;1R(BRak`n-C$ zVz0zGegFz~nA5rkXnhqVSRpe82zy6$FW|MSN4~?x@sea69O2@~jVVvT=#UafnaJX} z8b5Tt6S876DNPdf-!7RU?EGJi_9u!$GdksOCf!JSRMKHaIH 7$XeS7M{NHD zHnic-` zLsd8E3OiU$>!Lh!J*RMdhXypSO{wjzhkDm4^|ZE&Q%yAGO-@`GRwo?HqPk#z0Stlg zrBvxj?ocd1QBplcC+)t(pQU)qNZQE-9YdTbz}}2Od5hl6BQHrMWaNjxZbLM u6^;%K5EB>9-;vj1t}uCVY#{jp z^cA{e#wqPa9^H_XR8YNBLZk`ixiBdo_c-wUV0JS6)xjKnwtUBK=!rf(N`7miIo LL(7YD #IH&emDQGM^Uk& yU>=M!AF3c2QJYjry0M*6m5 z@L?S27_Qn@X{H<($hT&&;IW(Dd+fQI=YLH4;iKx6jErdUyrg6O7}9}%`CH9Qqs1|s zmah6zvk~4BKIEcEeGu}p`qg53a{j)M$Oj9Z;baQ5_xm$g>}>roCn1{h%@qf)nm{Lf zP!5)5|4_oJp7r+@QrmFW{WA07@VBZ@ujJ^g`4QfoS)cB#qsphiu@CI{2LAhGzl?ia z;1az~>g |95$DLN=Q{PJ!!yZCp-S<2*_7iDeCea`dt9GEL!APS-IP+eyf`%wpKg3@C^F$W z%T>HXLbc_k=niA!-;tIbFfW0AkhNJI%-j}$U!yyY*K?7S9jy44DN?IrWRJsxC8{e| zf7Lig4=gO!a+^zFrI<-(P#mj`mg)`t-oVoJ!#|PwFhEc`=E00pJzxC?L|Z12bOg&R z;%wG( tRa<`UE8^O_H7d)cd5 zP`58tU&rl|`rQ!L|H8VnXU6;_t*~11Xa3I!P`8zpsqEzFd79axG>+#sTEkD?0eqkH zW$HrZt+gIQ$P9hWtFU7E(5kZaE&FU@P?kBjuT=NFXwZL!-5|*T$NY=Z%7&ir)wGMx zUqvhz^dI9abId|UFIYrW#|R-tKXd{KUhG3*=MRVWtsZqz`gslL%(LshcGPU+F=N rYpGr7ewtgov6b+3p}9D1KmiQCc06u%lXc zAva2rq)i!$91$jNf%YQ1iKdO*>=8+SZsc}SW30AKdMX9JJF;#z;FwX1-rxCubIy*V z&%KdXm|d5xX=7xjU;5kH^&7WU_%CLV>(j6Ye4PxE^{IG~ud;TdbfzY-wq`LmjgDu1 zug-o%2z0IC#{SJiE(0!q#>~&3YQ ANHAG#h`j2vHnYJJuER-3K4y$(W_~PU=0H{HhHZCMlo|x zR v|poC%1GR!s0B$bD#O;PKNU?=O4ju}w+bL`!i{R6 z=>eTUf1OM1WS!}APb@dX4IC??oG+U1chfQI1pEu4*u6owr- j%YNH|4M43(Q*aZd2~RzD=lx?L2qWH(}+$Mha?DclFGe2nWmQCO#ynf zS5(W5+XJfC=jb{;y8D^M(l-oJ($e8V`Vv_ &wgmS`$Tw>HT_U6=HtuiKr$DF@Kx-k zQAHF&m00jLfAYp_tI?Uoo{vhe-v6!bQU6DIs*ac}4+gbRS0#XF<<(CU;HJj(=$ZcP zrK3&X=(cKqbGG{}oT-2mSNm^8V!NQmr*!YlI1XOD!@RAQ*AB!_5+ns#7uoqQ)v;?9 zx}#-rJOkxU%T-goao;KiRF);TtglpNq(0)(K?8H_7(=}s;wnwF#%cR|DC?6yOy3QI z?f{Y4?dz Omdl&eN_En7A>I!roKi`#Zc{t1Y}ND%UIL*HOj2VZ*ZzD(9+(4zeW zIkb(6NAI2k`9PPVGu(Z#N*`+Nrs{nAI I*--TB-an_f}V=TL&X zfalz3T+PDQk5l{|nbneQS 3P&)SrO*F`M+bpDj z+rg7n+*?>Rj39A>T9x~J|FqqI)To`z^SgsT8_;s7GWYzQdJ|d0;=r}Se# ; z+bex4Pq^pWJF2LrQ=<%nt@0f!5g7w9gUT&q#mavy(1|7#kQv&U1QQ$5VedFG_?FOj zQ1=1;AtT(Iq5hS1W(eXc+eVd#qZO+g$`Un@-Kps$^_JH9HhwVP)Nri(qw3C>*tMAm za2; }%Mgem8hDGIf#nV|vK#99U)Ei?506Rxe6* z2bJ+so`#>w0)4X+hi~9_)DQd|$!e|Ci=-jm4e!5wPhRyvY4?B~z-s(~xPT3;{>m@Q z3@l7;>wR)@s(0bcN9MhFKx`3%X7u##PxwgNAnmxOx=yez29oy!(l!YA^dV3E4Zr6Z z(ZNer1I(9yFAJCjif&zA9I^ENWp=>UDx%q~VOEC(zOR_s?zI5 X=C7WNrmemFe z>pACtBi_uwS1dx74-%)PYv{!5vH-x@T;-BR)v| >|6aEVZiBUOmn$oGxLJH_Uz+GmM7&mVl(Dh2KWXn&uq4O zgh5W$a}gsggDd|HVOrugKVlz&pZ Gh1?_p@%Xa2n=Hw+^#u|992W>& zR~-l(EM64_W;vf }{t1apMb_9dKmDYV94zqn9jQ_TPRpxOT;} z&xToYZ0nq;o`2Q19WlWugN6>3-L90TJ5T{D_%<;lmUd3mcxntUng+_ U3QGVPP^Pb@$TInw!6em09W!*u*d1NL7ZraBDXW#Kb0@eT0WD?D_wILlG-_ZYDP z@MDq@rlOqmgQnhc9>WkdH7M5AXKk0uGyMd))~t?e-2gG#Zi{6a00S{ZF74ObyXJL6 zS<7gTa|?OoOT@NQs`ZdX2OFYIP34eQ&AXJtcSsLD^MGX7p^5joxhJ7e^=U{VcH2TC zfp)1I+@Pr3i#9E#dPN;M?}Xc%3^ZvdmDKJ}>DZtzoa3-SV_bOw9rjqNkIx | zY%$mAPn>V3?1kuh#(OHb5_We7;Y8WYGt@$_ZLPGL6S{UW^wuJFBK)dE1SkHt7uf$d zxPzg~CPsC>gJS?;$40TZ!u$oSgXwLsAL_!