From 6a019d795ad35a961c24a5590504b5c2e0f12816 Mon Sep 17 00:00:00 2001 From: Matt Isenhower Date: Sun, 27 Sep 2026 14:45:50 -0700 Subject: [PATCH 1/3] Add Harmony 404 page and generated Pages route rewrites --- 404.html | 17 ++ src/assets/img/harmony.png | Bin 0 -> 50722 bytes src/not-found.js | 5 + src/router/index.js | 2 + src/router/redirects.mjs | 24 +++ src/router/redirects.test.mjs | 34 ++++ src/router/routes.mjs | 5 + src/views/NotFoundView.vue | 293 ++++++++++++++++++++++++++++++++++ vite.config.mjs | 13 +- 9 files changed, 391 insertions(+), 2 deletions(-) create mode 100644 404.html create mode 100644 src/assets/img/harmony.png create mode 100644 src/not-found.js create mode 100644 src/router/redirects.mjs create mode 100644 src/router/redirects.test.mjs create mode 100644 src/views/NotFoundView.vue diff --git a/404.html b/404.html new file mode 100644 index 0000000..6307528 --- /dev/null +++ b/404.html @@ -0,0 +1,17 @@ + + + + + + + + + + 404 — Splatoon3.ink + + +
+ + + + diff --git a/src/assets/img/harmony.png b/src/assets/img/harmony.png new file mode 100644 index 0000000000000000000000000000000000000000..3b4a992592b2594b7b738e7a80939d93fa8ef688 GIT binary patch literal 50722 zcmV)1K+V62P)q00093P)t-sM{rF3 zD=n5>r-)Ur?Wc2+V2|Rqw&B0I+mM39Xr-=*mD+a3pH_r)I2`zNSn(cjv#i z=D@hdZLrU4rIYJRMd7HGTnvvg#{Vp$0J*MY3DoZ?``7kj(otZq_u|MFkm5*A6Hy(^8 z8B3y5Kax^uGbo&TDeA?uOixfdJVEx2#iOK~JlwKIN=xZ;v-8!*L`O+I*RVc1Qrz2v z>V46E{G2{QMC`({+1Y=+XsY7FyXL>R=ef1Ee4@E?qenoJ+F_-^&V*1xuI{w1w{yJJ zV5a|Yrb0YLM>D3ET%J}r(@ZnE^~%7oanqHSk;HAmkjj(oyRg4+$K!dt?{Kd0hRdXO z-`CcDPCB$uN1fJGzqoPE`fsLFOQ-U&s;YI`ot~EUaH`w4ceiD!pJk(SPO`#ltleL_ zJvvMNiM6pV8lsaq(M!tnr)>9XqrSbc$5Xk#!h<>GwaL4e!?0YYBow~1n$(JiNhiZk zK1;K2otUhq;Gy0F_cHM5|fKs#Erw5r2V zlDUqf&}Xx}aJ7c#N$oB#ja8}Uu6fYASFMGf_QATP#)-(ey_{r@y?2yHH=ln|uqP}j zvs}WIkYt_SrEz7@vZ1V6TVHt5oM1pxZf9|@*LtzOyq%K#v9gf+nxua}V(y`~k0={o z&8S->9j<|UhhB!{a@wcIG`@hRZX_Gxm9_7Q!?=gdL#AKO%#Ys4Y}h+)4zRYXnrqgs zs)*OEY+{^?b#rj9g+@GjeT9ag!)D&a%Fb6yrk6FCa>U7zxnqrMOWu0vhO2~mq_E7S zs%3!6WZJcCVaF#9SDeq^;e@iMc>CVcl)Bu4t-O`DFva7xP)>WB0000>bW%=J0RH~| z{{8;`{{0XB{{H?T{{H?q{{H?^RyF->*8cw7bN*9~wv4a({r!W-nSIXvuCD&r&Y)QR z)cmos$e~!!mj1PM$#2)59zd=p38o2)grET=)X`}_1ag(Ab^Nm65F$wg zzHPUgkBjviHBoKWYRz`)p9n!hK5;yq`a>YUD_TREBw0dfGMQzmKlf7xX71n+>JT;p z0_i+ztPfX3qyF4#4OE2ipaU8XG6ra3m0r6~3LvMf{NR>ABH(rWOl|kk~ZX+X)cSg_S|l zY1SSW^Ot8H%o%h>!aVo`zt162j!6PhHm-=&AD8o2WYKCoXITc9ISk!gMIAu=3*`ad zD)~1;p@RKv1G$(S9VW_vEMs(*?j-&V@b{k0=_A*g0ZYCX?Zi zwSgjoQEBZ+8v+Q0jOF`}Qup1)-Dxh@9EK3bob%u?Mk3G)5XvwyBB56Bs*6srJUUmz z@dZQ<|DM;9v|mhRD!RP}0d{l9)PIt3x)4G)qmT>sN(&>~I=GiaC{pbscz%+>9LsNi?B8dv z%hJ$kH58e2?>%36jrDr5HnCI+nImzaJQcap5I`)6NMpB~MeZLT)ON7H@*cD4%K2E8 z;OO0TzUr(Cu{7=>D=Xm|l7kbGs}6CW11p5Li0o@H$XBdkD3!bXP zSHZ+Dn1)?b86G2fvq`2bG+yM!4)*bDPVV(t1$#jhIXgG`=9uTl%D(!qoQcR1N&ik+ zG}-`T;bbbEt0WR|am@g+u>4%-D!iP>pA2b;hwcNw@hiEze~H6!zm2!~ZWoZ4kl+w} z3*z8wZ8uuod3Dw3bQTLqVqxbg?H`&(S%yMzEFV{Q$c0SOOiblv*~_Zk`ujw|TDflb zR0W%FD#z`P><&R32Qgt!Jj9onA=w@FD@~+(e+|Y$uwchxjRmr_l9r_5mzeixWaX-n z1`z3F#a$$&XmrA=-FMJn*-2DMn-iI7x7z~&MZu034)&wnQT_Uzl~&cJy#D-o;R?j+ zJj5b|a&1KVb>tMfGFS1jNIKNs0hazY9G>@7-I$uy0)jh)28~!w*&HjgRiw%a6 zZ+EeXOCV&<0v@Y-E39f9z*vG9YwM6OWTT;|==D;VK#7&x($M12>lIRC9(*XF8fZ*|hP$&QqRI0Z&#t6+OiKJGm)#tTDYu~1(Y3dl6e5}Hi2BukQP zI-R5`7Dr@>B(l>LN=^kB97rPM(YOr4>-D~L%Lh*R;jo3W=`4*HF~Hi0;1ls{#9>PVPQtAG9<<@r+KVwG!7u+p%VRthtr@j%;0+`WPK3g0smPwF z7kS_ou$%_3uh{?m`Fsaf-fe>^9Qs3gVM6Q+ldnsf0PcB;p7vT2^zAaro$?!qMW_h`>92sR?O3+tgtE{3a$=v z@MK63B$G?tVR&dLwOhjg5DNhU{<>vQd~kgjAOmS0NEqyZ^$2`1sDu*2!l^VGjodQV za*e3C8EQCqb{ais^)_<;p-3DL`3s3H0z|%w&BWupZxnz0_2wf&<`Y~JCioJYP^kk@ z$b5A!Suq}=yDA#eR;m`3luSnasDuV9cCk8mbFr~+ZEp@NK{;w5L2)2e!XqwzYx?u= zx3vt`WUMVsAZ=i2C<8HtRU&D8)+}H}Zs=~{fIF>231n2BtcsBiJ#%XnP$1Lh@wezJ zP<|qXJcS+oT)M&%xuG;XsHMhP7?!ax;y@H^9-N7#jn7gVpiwDO z1|NUs`((>S0iRSd-yb(9#IT&RApD_#h?BTip9ES%C%nVH8x>0(MqFf3?>f(6ZGQ$u61QP`$ASJ@EZJnsA@0xdE z?0$pmNKWvW?^hcujkOKl^=d z2?OdVarGq;q6=7}PnU~UgsNOgP)JOA>Mq`9=k@1>b@53cZ_x%CSRo!^IS`G*{Y(Xu zr>vAEc9Cmg>}5G?lyM|V2$+cS4GRMkNDS=Z@Ek+$q?V`z!P1H0ca2s49{1& zThwm0yI2zlkS+)z1ss+}$cf4-uv{D0xmO=h)%4woH-Q*r*>pCY@y+4TMbG{7k*1%- zZrCt%K8>fCs!WCT^HXl?BLDk%i~|S2iA;r4*6AwOs;t~hb?rP==YQb5B)y1$x9Lm` z)0x<>4=4l-eqI6s0}oIO&W%P@*Q{7WV}hpoW>+Pi8(hL5kxt482sEr!fBE3IqFdN32G0FvvHu zkXrF`b37cJ#6(;dH;O39RQ6yHy%*y)+|amop7L698I)+m&XAabAm(~^pW2Homq5>7 z$3iV!e^ER6hpNtUn?QK{B|zxXmI{JhWmc@Fk!H5j}0r;cChG#_(R{Txa( zdB-i?{IG{-!+XJ|tiYYpiFvw$m=Dk_p;)}HQ!x678@FvI7mc)%m;e=o zyh@tvmKv|*v}3)?lXmqK5R)c!j<6nRibMdfK+YnI176DI%@M&PPYM&NCNMWH0a^Uo z7vY}Z#@xA0+RjQeNZMLi4^zG~<~Q1wvD#^V>hMJMd30qC)gZ^joiushh&5M+z%V?j zU|Vt|=BSOH!esLO>r5j7FNd@@ozq|Om2kWjuCd4aGdR0GP<&ity^iqZ35%O zfM7ki6o5`gj|LcX$UTD_+nOqy9ekph&ned#7X3apQkmPH89uHUn1lrIq?_mTbxkL=J4FtXiPrhAcXnHfq-yk)v0#el0W{oEhpleQ0vq)ampD z8eptC3I}x>6@P9c8s*G+Kz)#v=;fIywE$ww=23fd97r~Ekajqz%@#+1;;pz-W}I|& znNF4?CTu>bsTLmxT%`nMs2bcEmG1! zuzXnQS}T_&(0IOEFuEEFACS3(F|m#YL4E2lXsCD?XCKLvsI~+`*{URu92aw8p!nN& zb3!(t14#iwbg3gJy>9XXce1zJ#nWADMz^b41M8D_m;6`?*48GO0bpD=MQ=3BmZiB- z-ZU$c6LTbnfUuU_FMU%oX0wQ7B%{`mgIIB(1x2dlBr3VmfSsM~G|+gikN{S+E`vav z6%q;)#Q{;|=)f4Jn$QmzPXZKfl($umEOu1C%x3+5U$SF9i*OLJjj>X=2o$h(v{Ok$ zZK-ygoH|jnU<`|QH|2oOd52uLrDQalq5Ou)c#}_vt5M{hNsYUDxd~#(mp)${jVV}v zE#Mh8i>wuM!3jYTB_4QQyp0M{yN$pPyGp_9yr84Ty_>1U;JJpmKbUS3(FXImdMflQ zZ;uBG{}fI7YB7H*!h7A$M}weZ2XXA5k_^AfbZ&_`VX#{;j$U@9go|bXmTuw)=}2EH z>?wjsdcfQt{1#vl_LO^D4(@2I@cM&WDS^iPHX>LHQgx*j`c9CeYpA*IDiIw#0v6H1 zOF!*8Q&^WHtD+GgP)8vs2{*-D=s6^-LT=J}p$Ivod~c7(h3Vw7*Sv48xlY#-vR&Xu ztdF<{(ah-@vzd}3r@QV+kS+bHDMM1DCowRkqe;CgF{8{?Bb0?Eoff$RH|$e#m1J;c z%)~~v*Htre<%C$K3^}^U(`_43#;*I=p1&h4FMT0n~McPS49cD%s8h4!CciSGl5+@wkU_h48L_>aLZkF(^s8hvj zuRtTaN8wIzaMyM^!_08*Zl-cz%WNdk)sFUFrUDLMrm$dO1Yx;aPDWL_@mKVbWv)d0 z7qZ$PoJPexT;spFD>=T*5EirP_F#|F!4~Uc$K_*6NjqjS64%y?T`qjf+$jwPqBBa$sIUvobYuQ)Zoq^h@ie)%xJOlUA!f zX+3*Kzr7J~%&aIQhZnMmDvKFp6H8?kJaqaB9{ZSGdeQBsM^%FAuwtxI!l;n}38bl@ zYorIABT_YNEZDcuE_KtI)Vpx6U%jqcuI15qKKr|9y?ctmnC2TJvLY!(RupN8GFO?s zR`A?$%2tU+EB*HyCcuny`D`RtS51tEU+|)OXx{*3tuX+D?rsgTeV=z^OssOG&~( zxH9yc)n%!F3mpqg#ziC^+yv#z50lB{12sYTvKc(q@B5M$eAJ1({3m8!YI-}3*p@{r zsuo6mz1_~woDkF!isFy7wJPps!t!Oy9A}h&(Uck#0s3SNc|#wiL4(o*St$S`48+OY z^0utrWpKk!ZUKbi29hr_j(pa9!1) z(*5N##hkRZ}g~DSzs{V zs7je}4nVva2zpRxE)4DH@mxAMwKq4D`UI{Y#Z%?Rac*k+eN78>X_=&o|HSg8BoGlI z$Z{EtJG7fQi z*t?ueR&-6vdu4Q!oOvIUi%+EN*5BhWBVtGx1}Ykl3u9-=cb#G2aX8>}EPpuOG}~@A zGU#rS{ef}tI-434k0C?j&A^}s`;wTZ>H|MSZ?Sst%!ii-z>p1)7j+DG-R;hB#un{e z1Tatr6!^BsdjCE32Jh5ht?!J^Yhx$Q-cC7skO>q}FM%#UP-#Y{>;*R^FW9 zD&JP%*o6y?Zyx-S=2agSIW zo#aY5TTPZ58St<}h2*8du)ZxAKn)n>2Zb=aU473?{d+Tg&fO>~7Gp3`0t_wQwrD6j zWdl+eM`VMzLs+Y`J>J4}oOQ%dpt;fMjT(?0;W7>`RjKsD;OWA>!(xaq|HOi(&5=-!bLmw5 zP$~_k+oRzF7}+KcGPfoeQ);Fnx{cpzc;n?B$66~4JS1B%JOxiggZV{r$&S;#-oTWH zh9n4-!>c21s5m{&2aFp--+jOZX37L(PFUv2t7VZOPH`c7DaXoVvB|eADaXf=6pMR4 zg8OKtXb3nat=~%AyFKT+F(_3Ae=Z&p4&O(v?UY(63IzqDX76v!AV+L^QgO1Bpb9FQv4U=jz z`t)h|tUFXL?m2~I_@G$0|DBm&=q;{sP->DPX*UY2SIuTctgV#h2WE#+lA?<72<}fb z;=b@2uZv^^WsOFo!QLCg--ZkYpa$heWBQQPSePmFxAJdYgHY4hc*w6p+`xt^mI5xo zNQnp0ZS2KIanb8*l?TC4eEfODP)IKb0U;{?aq-uH@ix8tHBWQH()BpgPNjq+1}F;b z%Q#B4;yPys2agAhz@o*^$v{>6Sh0yed2VFDq?|oIE&d8HzW${C)@z29GH@}s9|s!w zU}%CA3Pzs&aWUiI=ymzx;vSMKJu;N@KZdJ~(BJx)Ec5qb`s9f8(Z-2rbR4t8* z`cbAwwHl9t;D=-RQiqR)8cAaD;<`G-7K(>_=bRDrV^Y7v*sQP3hTv(GXvynfhw( zYz>j4hNZ*wx3c4oR9b{fxS&QM_Egd1^x)B~!@pN8!5Hf95Scw^$c8a}*PZx{( zSSeoAa2M_qOD{}*q(JdfO0wY+5?&B%{J7*B*57`&tkj@k7L~MAaC1dpnk|i?+wE?S z$AXn>HGZP4gucyS!u3Da?$!+BR6|}>&BM;`|Czg<&^EF&UR(&&GV8)JC5Al&!}jK^ z7t`k6t2GJ+p&I2N9eVO37cK2DO-KF_eh{aziBsDEmHNuYDM2z*XvS8#2j9BYaOdUNEN*;L`}(#dQ)?UEY#^|Bb#^*Dm4FPQh*sY_vC5-%R5rB}n~r)jR*m(@Z%+>B zjO_W7C+FvH-&VYM>9qEz_urDC&7`dPs>8~EH4K)whXou#yLe}DqgMO+cBE1pp63A= zD$WETNgdH(k;Zns5> zhC6g9S7}c5O|5n;-oCsIhOy<%yo=#*ARa)C)8W}**7746?MN3IdW~Uh7v}N}e$w_a z9td4JfBr&F-KzUh&A$cGshs2{18MfrlSA}o1&BHSVGF}uy%RP8HyZ(i&-pb z0UJcq6yqd`vb3scs3D>!Z)NeY>Lub5i+8m35t?(KlAr+~G_De%LWY zyEkj!f*67t$#5`0FpwP+k5YpG5)*}rcVyksR3D{l$Y>{K!B3TY-@evZPzD%2XdYY< z1{X5B`oEp_4&M0+!jGKMROD!?%LFnWo>BwE>cvs^UTsBy zT|Da{NFK;vh1k|QbF zTCmzwuvD7W)Fi>Say0KI7E+|j zhL~3y_Y|;7&>1v14|X$2Rqgl_B)Myw-qw~E$FX=@C#kK7L?MC97<*n8473eMlv253 z0slyXL71Bdl`LJBHn*Sq>6Vg3%uuK+?Pl$?@hB`1tx}oQCHC z9P6IasTtKNk=tg`kZL8I*=InHrcy1PN~touJ|3J&ZcGF>m=vp|gc&uJ)e@uNMXtcB znt3U(+uh3 z4G=3xc#{_e)Q}YhIEF6gxLZ<+P~pV}&j~Y15CR}1AUd&nBlT*bt=#2}Sgp*|+z^kg zO@+lQA=K!>kyaiIcoXu3ui87bf8hLIv@@V+fU+Sw#xF`TDF8!O*RFx%jVe-AHMlKb zmR12AI)dYL?nb--03ZNKL_t)=*5hki!1e z&_JcaO+5Ub(>au5$aY1p*TJunQx*QC)Lpo3<=nFJ1-1@1wn#$>;qW9J0t?u=AZQ>M zv4a?TU#Jz4swQb+jSU)ux{o<-B+23EioDkDt(zXHR`F`-RR$oQQ72xOg<0>$JOa`j z`C?&7)ke#jOqF;@V#qgAYYb>n^L^k!Ylg(FRV>UTwQ0nsZ@QwAY!!ATiy{oVvR>D$?B9B zxopF{<9^$=4oJ5q#={3q-zVIF8jyEL@ zxwjBz6s;#n@t|moffSz7=Y1%~ z;JUbRwn)Lwx&-6fUEK%K%Liz1{a#*j^Qs+nUa9FWKlB@Yv4uR~0mSiWNx*UcV-_9d zU`Rl`L5WaBS?^}LYhTn~GNvOCalNCL*_*q%|P({}lu_Ip%O9ytCcqVU;=XGJD`f^*JK&6gP!Re^2ao zyO)3iJVmS^IYu8rtd=*cFr%ePzkTK5YB^M7nzqchDvq3SM+P!$>z&E2I`Q#er*H)B zyw-}{>GpQF!g$*!KQAy4>$n(oL5Qb)6B3pFblSbs?LIp>QGl$7$I@f5dvDRyP%=d` zs$PtjUZlzs`A!-zH)m3N7wN2?al&6~<6%OMAZS#Osyo};+nw&TTzPoeP>Hn(G?U!zmhaIg}jfC^x6!6eoG0JsywiBn@VX zo{c5k_>rP9*E)8A9Gy=0QD-{+zt<(?>&Jd3_T(EvfnbR3^+;)z1OuJ?nnmDRB@4IE zNZ^QXGAT3ok)y`2vR|0-JKKj!LmnRMNvDY^#>MmBL6FCT7eE0ojm~!Gk$5=xF{gwm z>NKJ%HTFWlV6U;Ku$XprNKCq5;V05JRsa&Q_q)XkmG0tF6OZt+B#J_0jXiTCqE=8T zU1EM+E#iSA`kTVWzq8Q@=5ZqoyMRXbQMc1MoR;=PctQIrUs@rndlrY zX{{1a2s|ENTdS(1xA2@;9mAF}W|jvbUl20VDwIrsd@9kM+(hPA5)AhD3>q1=;zXn5 zWl7=THnO9O{OC@va#4Vz*fZKhIML})UL0z6JTt~IT9Js1?q3Uxs1i3?WNHIUoY^ML z@-u!p&!8))@T=)69zhKVAykaD{qKWZSe18<8<15AAAbaA@1HxJZ2<^+NYNUSG8fS% zv8OAGY1b8K9EY7}CrYV6tCplzU84qEj~sKa&YGh~Y$J{wR>86>M(l1#ovxrlDj2RP zG(<+lVA;s8@@VAETwlHggrSqsr$g)gl5hiTeC2w1 z)kZ6hTa}_`bqphF;1L;gXFm!)8d-v6B1~Djo{eQp;sM8h3^Pc)`5$fP^V-Il#_^(q zmw1KJiw}Z5tbA7xm@d2h7ZfE_2opR+qbz}H8G2YXiMki{(nE+;5UgNNQ%~0{#@JcA zU|8D1q6IlJWw8zk1lgyJV6iV+(&m&y+2_amb2MYia`Z|g$#Rs2_oMIk`#kTwQupe6 z_1F}r>v3KV^eYAe(-;JU3-{elaDZ-NF!;D~-U#?6s5lZwBFW;w=$JjodB3fm^HwWP z9H&Mn4zKVE5le;9;s{Fvr2v=HA50oNN`T}0dd!%hU_7oU94_Jj9!`Z6QVGztzBDh# zx5T3OExV8fIehss>wyH}o`XVZeJ6;8dm=0lvh&r^J!q@VG+Lk(Jw?HIG(wiW>{KSnzt$>*!wOsU^JE8NOBXOl?qg z%OFag@B3aq9)=qn8_Lkpap%q*Ee;$!r7*e3gQplZjMQ*JsX+C4>Qau@g;Whc@N{ zD{}#NRh~wgIO`g*Fh~d4(z@Iy;wh`beG1B^eAI@2Emj(`$bomXYW!4LHL%2y=emlJ z2>*$G*E^;lh@Ab@1!KY86)=+ftPB*#tc!=stPH(}&1SKZyDm;e?R;T`_-bs&7k7r~ zRMFsyirc}%n;#Vv4NuVcDvm}_(eH2wXU&79QgQPWLwJ=dXV@`jnW`^aI*x0*m4U>a z(8q$6oGl12+(qSi<~mixSq&rD)i&slq?SA>5js4qr!d1~E2@B6i3!`! zPc>XBvvg1hkE#$S*NH8s+)8}sflDxGj`u`2Zj70eV=;#?;Lx8BKs4fWu*Mz+v4)#b z`vaxnn|nSZ_Ux$5g;3D`uzpx#gY!Hc7c32*QzNe181lTMtLV436GfvO0|Z~9tjlmM zPM1laiYI|}Sw0`^!CPbq|DeaR8E1Vkj`YkqE`wa+uvkcOs1^0o*5v*i>x666KB={X z+84Fj=^<-@O%88;PoVMHs``5|Fak3R$e32DG6E4NC8$I*oc+X;E5-Jf?m0a8j7D`Vnlsx?h-8zyW8l6rhKNc~blt`{n zR>`%hot+kKe$HjDNA8$D$jAltmbvZ2i|qW2TFXoq&q#i`H06sW5&t}+s!SG3RJ}Uq zQYgo!2y@8``vboAUoBxd^e0?;LX!{n5Jf}a0ChYj8c9V1w2_#3?J%9qEpa)ulFg>$ z&PW|(GR$K~S5a!%Z+?@HuAwA6KIpMuA`X&8tWiZcQiYeKVn;cDwGsb!yTAcJ!108E z&?!KHL8&7#`@;HSI-6e3=CX_DoI7922pl&HV){KJj;#XMl!QuoPu|hOxpFCl08jXR zxE#fGe&_;|tgPR5k89M6$4l9<{l<-Rt$XdtYw?jryx3 z$9T##s~dBpLElVOV;VJ2vl{U~J=Cux+!Erb&~F5_6`(4+GCF9^7j`n21v5(~Isa%{d#APp%E z*2q1Iy^Nnr>Kvc3h)xOqB!Wc|a17&S(s7W6<2YI<5=MY) zPgs>!0w)ei`SK<<=-FuCNwJ4f{!y>TU%$}0F17vaakO9xt>bVt=P+xyfIH2 zi_0A3|10=H9))mE=SBTw#D#CJgCGi`aYQ1pD=BuWVzf~ip`lEwf-HnGge)3i8qMag zQn`#Q^z#ekQ=RGw(D?QXsSQ*I(dbx-A+(X4@3*X{KO`In1)S5?SqPvoY zVAB8?Z`hZt_$Fz%kEVenVhqo>rI=sTDKwzA-P+3h`>cx5!A7mMLKS$tj(jJ( z1jAJ^o_{!Owpkdg4!Y8h(ymN07YBNIq7?yYAdC|*DA2}R2ytCi^-wfsJ(U2*Vu8&0 ze?f5lx0vGxUf(FJIF`e8Q;DA}>F21gko`rUZ_uWWivkCcU<~5E64!*AWkDEt99^>s=H57~fBo8#&pyJKX5+So*^vZ^Y1?&;U_rUCM(Wezz2Jp0`* zy9r-el&EI;EGuinM1jiqtQd)djcXA3?zMZ3VWZv9(rEs2{O6xWqi3Vh=;t#4^89(X z-R^czHpZ4f>X)i-7YK9b(a8zcQUID_yxQxrJf4UcSEVg&<-s53sg1?-Vmgg|;7wsV zrbDe+3xeWNNp{?v5(0(aKRO~5{Wtdfher^(h{RbTfehOWgMo}+0gBP+0bU;G_wi^J2h%UaSGe!1o}f0ssxoH~9N3OOrP#QQ9Y;#H8Uh9tyYmQ+>&wf_ z+1$#?DqM28Y!*_Syh`fBaxGCe@x}w$STKaXxH~!`97iUM;%5rSvGA$5*x;I$VW3U1 zQNc|wlNr%DG2$_Lz+UxLyW0kFz!;kmQg^0J4_u#WG$1vqQX6lns1n+s8n?^4J`J-< zq~=pqWqJFX{EkQ(tPaJ4PpHb-=dMCM*4~5^j^ucA-<3O^ry&%Q=KyDUWJW(G zyEN8W9~2$JtHvAONgkjKbgSVxB+3&J4$}BsIn`Tqs*|TZ;&Gch4)&^!cr0Qh^{$g6 zoueIBOFOMqxU}R)U{!_W>oZ4cT~_#$sSE)_jXx*|5f;Ty56@W>5k6IK^8gyXQRXqi z*hd^cW=5mTGs5v4!~rQ->7HIaZk@Kcn=AEi@KGyW7Vf9r|!v8a!Z z8eH(g_|?1pmi5II@v#E_V&N8U{3L;h_DyVsvW zG6)n#Z#3%4@lVh~2J_>Y6bC#B+8`VouOL299?eGm!W=J?QK2@ZG^$&i;@wBRjUJ2R zWyc&{qN3KU-mN%tER3Zc^=-EQXYTw$+RE}c?$a#BnaCp2%64HDb_i1(1=$@tFckMS zD+5ycl18&jAcj7*PP|J8?n0+h-CZDN9BirtX&YVF$z2Cug9} zU6??|`jU44oZtC>?!8HFms{*F@g}vF!u|OD{X4&NGD_Ul<!BMJ?Vo_?5tL6hE zo%Z!iG7N|tw%@H%+EX1|8DD(g%UE117yeo<{|M^9;y57UAlj(T&;QI8u_M^B21?at z%lrFO8p}_i-k2;`K^yQ~oAp?kwMwGzhw7%-VYpZsm*JR55k2}NgQG)a%AiQ|C;XOH z7vD%QWL>N_^iE@l6Ff=5;rlB)!IRr~f=B}{^DqDVH$viC`3m~NvEvgG$Ug@fSQ}Iv zr4C+sn5|Q)6fVPOQPjqX6p{w1#mh_^4=ZjGQ7jJ9ED1BK>Zg-$EQa%sWg{Up0;JqpZZJ+SXSd67jzuO}`zdXXtT_M2~w= zcHqcyw{Tp*G{9SxwnTEJ1CACe>ZAjs#%Iyk65DY6U;zqvpgf*xV4X0sj;nlFn+Q6ugX!V7vYqVca|1mnt&aJljs7YBA# z*i(H`0u=bdaG>H{GZ|ao9u*54m3xyI#ul`2anlf&8(11^UN<$1Vc=(Y;)o2b@RRgr zC4_kJ72jbn3R|1s zzx?|#qHzUyTtVS>ABp4M<|d)>`J-d>mly>BQYzgl(N>AB@33UKu{LH=C9}K*1;%nO z$#16-jCmrCE#au5?24p;wGlE6JetdBC?-ayPc1AgeEMnqgAa;dfBobM9gcEGjMeAQ zSF>qvxY%RuTA>c6jZ`3MAWyZliR@*$jAemYpsKlCUWRWwyZ_nUT?85>W)uitAxy+& zZTNRZpz+n)yZmoRsGLXOs8BjU;>JVbsFo-Rn&x5_7)f}6V^Dks*^K-VWeSb9vkSoE z(!y6aKED6)lW&T@CqyuaZxM*qe>~5o;la!9J>jhWAVC@<`#^r!zlQhugln zR)*HaKDB8|V;2l)99K)S%~Kpm9d?|t7;o6Vy$@@CFPHJ+hJ&5f8e)Ofu|;mbW+@p} zl+t)R8eYNC&$sUrKgD^>tPF~u`o#jar{v7-8&|Jhy>a!2;Yk1LmncqT5e9g|8$a(v z+Jk%UsF7|IH{=Etu?G&Ou~jZJ6n_S7Ol}fwAgfP%XaEnY4XtT=WCFBd)twDwz39uS zgEXeWQI&wjJabfcqXuOW6^5vU*E#GNx+wdpi~QrTE_WY_HTVb?$5Z74ckh3A`b^ek z{?S4kbGfNBd7bcYR`5k89yaC>jU!BBdVgPNV-kNi1~?X{5RI*p$LPXTs#Ue2TYtIj z95{9SztlUF2gA#Od1M}t`FTG(RUBgXwOed20X|sG)NGQ0p&mGa?^O0Y^;s6w?XB>(P$A?tih(3qjI)m8xSHk zmvQT&Oa?P4A%IZ_8kIYZv>^o!zoe>$S2xJsG972K>(%P|63%ETjwPN@`QZq$H_`*G z^cjKzi=#+(^B)enhDj6__n(cx{cmsJsnQ-6dpxD0mzsQclt9iFH>ft+!4*+;96{^= zc@P#ygvQ(=&{(|Xh2a}FJW%o!h4fHuDU+~W-pasF_zJgg*bfUE2tg5ZpkGA~jR=bx zByx<55E2rPbgQr-Q%c)Sb{Z$#G@NaR@mO9)S?4kp28kMVoKh|NNrMbu+09n~Q+X{< zl|fn13&&#SGM4PF_%rOJ3X6jsJW_=7t7hP}`|!NW9loddsga+uf%01=!IcAw+35Dr z5voKyMXEm?-S2IO%Y)m|W-qHY)}|XcDmEoL(PHQ`p0X{=s|}%%T4u+R)nPDsfH>ao z3{@Q6AdDHpqDZwd@R4Vfga`0v_eMtk=Yz98~~q_Kfj;k4C=1~T#t&(C49_;!!JfCF zo@#bLMM6n&&rxaYIvbcpFINRo29`#(35Wqxz>|qX%h|Ls!nMIJp~em3 ztqxZJMG;QFD57WgfY07?=Bu6|8s6Hkg`?UFN`sAl#uIcIw(yv`s_j_J0e`iz`H90} z)YmE~YOLMy=C;Bnf{eNe7MR2J3^wMUmdr}jFqk%ssN$`{o*RkuAJW6C0LIG7dEbp9 zr%2d9Fn&tAGXPIOu)nJ8SRhZ8Zo1MW_Q9gi+QFAMX6Gmm$Jvd=w&8_Z9Y^rvV>gVd zChzJ9t_y~P*>&EfvMUB60R8l6(lCrDdq7gv*%r3-4IJW6uU1 zi+TksrJm}U06Er26a>ostu)uO1F+NEBG4!w$=XNmk$=}^#_%yDd>oF zfF!DZ+s?-9S2*|$<|2@*O1a|(G7X=pXGj>NxPb#lSKCQiXZtJVw^|b#rmnKkOaq2Mr~ zEVrTFNZw3J0>PFvUSEnEG?Jfbrj44vv$Ev0DkXU;yxBM_)WN+HgOS(~-x7k5-sY*V z(ri1&4^n!yQx17Go>Ak*b(6G6D&*eZOp2O=Su}bk@@7dRn{Lsy)zs?4mX>;$GV(h6 zmFGEap^!IoQdzEPS_fB!?B3u+U2`WPZH;ObzQ=ve(nyIQE^uIVm{VB$BAm= zcv>+v001BWNkl@Hc`hYr?1Y(Txv?ErHZ=zf8RKf$$O%hGIW7(x1`Xm#!||Ke;^?pL ze)*P|^~(!KrD#Lfz+vc8L2kzF0{_t+6y0?yEKS)g82o%aC8>(%1dxm(4jU-~+>{@S z6OQ7i+k>F^?seZt~{DZxZbIv`tUQ#bCrCZjc-A#|CzWyHP z+=s_+%k&E`#^nt*J`Oj3k;&UKW@X@4nXbsfvnVqFhN>No=aLlf`QtvBN|QoiG2j_@ zH8nz20!ZtwL26tS*Y4z%YP_p5Z#%Dc{l_~a8jg*c_Q|ZuqaQ7()DUQlP14<{cxuD( zbD_%WsoQ95TACZ>O7;I~ss9uj9Ek!N<2ox>zx^ME2E{6#aetBdMxenv>x-2-$Y`vIp$ndI`{*+85`C<+zccdc(g)habu%Izd(-1{SP|ieM1`! z1qOk@x>u95;eJiog6HSUc(3DPN_| zme9z-0&WP4^r}tSE$DbIeJP!%taYUxxU4t%uSLDVH z9D>{?f`>POhQp0KzfOS2VG{25v51<`#8tMDgoz1ax_|~e{-;pIn(FY-V0=y)7#{Zv zdTFvxbxR31z^6TkVX@=4^*R+=^||DBh#Tr-BUKIT-)>~^ht8qMR|1P9+)$T4g~Pue{Y%l5Bxw*kXqdy1~&@ZFaNGaBjDUnXuOxL__T#eR2)jH#+j1v zU$CK`$%aKDBA0HAU>{rx%wWH^Vc`vxj|2U;=!m;bjbk%7JW~yd?=(ja@{Pc7BdDQ8 zKxgT(A)pXn>wi})yre{R2IJ#QWH5M2C0n6dI~YA(JjvIKuu;o(QHhjR~=TCG+h#BDbp?CqZrtJDWbR^o$VqVfn6(k=Mr*@2WBJAFf9 zQN$y4QYlrIR>A(V;sP^`NTgs9UXf)Qj07=B5?V~KcdCNLD#Pa&_r={5eH=f7_>gUF z5hhV-bUX&feUoUoHZf|@2qYA7QLC0BQVDLX*B|o5aFm-1P1uWGtehxT(3O}!q}YL* zICoix-X}hEpWW$;yVcWw5!M`7{=JKjIHj2;-Kg@IOo44&A4tqC5hGS0IQ{ydtJXKZExx|Jxx*I$hZV6YOKjyw zTp~B%VV;pNO)eR^%eh7gHv(D#9mEonI0i&aEiTYdBp5n^{beaM^O6&^} zVJn}Qk5^80d>F&|JVL96t}EEF#f%#4!2i7H{ zh5`e);SnG3*V;<1o2&kAb6t_@K2`i+P{0@R4ejD+d}viggPK{u6)qGF)FXHszOATL6@lKpuR9V8K@E!+9t%{YR;LFLa09w5 zGy<}3MhzMOhssm{hgbTY5*q;H*$;Dq$> zk$_`b&JFYHCKsrKQlUgiEONe~pomLUisO;y#}}V|QWINShDA2KNs2CR>y$!6Q4Cgd zR+Qq|Mvm2>@2h>YfQIhgu4bdr$QgCSKbMjCno3f*L<}1k`O@gdrVGfmC{=;YjW}=N zML@)#7^cOsg4RfXfFZZAiK4_lLaP0QQbn}|N9mAg#6C6EqwT6K8KEAjfTSaD_`Hf8 z@>`8A!acewx_B{8RUrZ7kZ5q^TFQ$zA1U1H*Qt zhsHx*9`g;iP9JL%*i2U$(JO_wQfV4g*BzPU2W9P0Se=Y(Koj3(TKRwQOxMHQKwu(5;ojs zBb5LnAe|y^6szw%FDC3cF6V}-1-DwQBE198;znd~Bea&5ukw#%NtW1hzW_+L!KNCYLy(H zU$?)P9ls)P`ydPlg>N#Q3fYRoeSdVaQS(jAC59cU98C)bh8C=n?ZTK}OTaLQ;F79xktz|a2T6`rhciPziEpVU zm4abDx2&7BNKTIqf*gh(vQZVYDew~io=o(YMkB`!AVzA#v3iBX3UN20wuebslxq24 z-1xZrr#4C7h~GwRP_5x~W(7LvxI0H`G^|v{ID&w088EX+MJy)q4`K%3@teb-FfcGc z-qW=pNXRy+Mj^t1wMAHh1#LKc+RMj9^=HtKILr(ntbfaOY7S5HhUfh>8UYzN;S$so ze3RHfpMhO+Ky^HTzlX*Hjr;ZZ6L*$Fg}CFJ|)Y z&q%0d+CbXV(qQX)l(f#8N5irVz@yx}b*hCp1-wvC4^aGB%qWcevzr@(2Otn?#+dtG zs#H5qROogurN~?fZp4cRqf?^lo1u@lOPm{O!MV1Q+lIk7zB7|d!O(rysj5(U8=0DD zrJ77Esai5#I8}(OKOG&N!K(Ghr+Y7b8a8_99=H$h*;+#mN2y5Zf7Pdph4hVu#(@Q@ zS$dL=O3*+%S4uT+oE*pK-oOr5lcTEqhE)4wk{e4XGU}+|q;lQZ%|{}8Sz_Zy;f*QTC~YLO1UvtFi4@A&*v9SbHmD1!{IZa zQCDL85LaxY5$r-jj*dQt`S|?o%+?|34E70+C&q}%uE9BZvqTWs`IwF!CbER0#gK>1heS_L0`Bn%P z8GuEO8Ix~ICv|p{!*S?mK=$Oj9<1uO?7>>EGbjT=j^25m{_d=B39u`wD4Y2PM z4a&5tHKk~A2p+DD!%Y9tGlKDh8wRT}3=aA_yWZj8TB@9T`v&%UXQw@G8lYQ!T7cUd610&f*jKU-um{Y&I@^Nz`$Z*^{JHMgbZEocCeB7Ujt>j*8XW%>?q+DaFVn%pEHp$C2t>e49~(1GOdtCgnA3tUbJz$p ztjU~3bjd0H3(R;3zU&{cmwi?Be$?x3CHAtgy(Ouou?&Oy<8OVd>b+L#EW`^zqu1*% z=Rw-QxVLZr4Q`z-jjdJjtL`m(fOVditQWtI8;e`s{{64_?&w${28mktBPJw{vNEu( znudf?mN}j>Esx8pHrUPctdH$3hjDtBUJOkG=Cp_b8gMR@v#(2|6~3Wn>WNA^q=V$zbbV+_zDV$b|^znacT38f+29ox>f;6?Jff`WD-a=dZEsW#!xd2 zBMuKL-AYOIi+r5wT=nQKA7ZCL8d@28DENg~YYmMdFRPe1mYH`B$q6`=Whup>7nFCT zjZ;<2g<;}1ala&WxKFfAV0tprc+~sP^3**B0@gV$&#J{!-M`yX-|F?IVZs_f(nfBE zAuLOgBvhKh5J*z(ru)jY?=ewSl!5B#@kI4eqmTkQy-Vs?8;>1vvqCAuds8$Ega7Ew zcCRHg){>zXhuox|;24*oNUOsTnW@a(e42hGM>UE=-1Mg8b{7D6%0h6wa7{>jXY!NivMx-nPI3N zLxA`Y`%w`2e*6~?c>L!5!&bvD%s5`$wbiI5DiVfA`$UY3FX7>~1_sVX5@Q&u@lgGS z%vGojA&A_Ff`}lKQO+~V`n^hNJHGS-6>$*wLLuH?zdt$suavi7;WIkoMCQbTK;SX(&o3?-wDCt(-`>GARE}!MRSy-1LV=i8R+`$ebBCX~#7b4#$Sb?p z;GCxtM~z6D*))3ltkIYgh8Qu>LENt&pPrm9OIDBWl&2ie8GCT3Sowp()V8%M*O*Da z*CHCOoEmoZ_)zk|r3@Gh>KS1wYpJ}-BhN;aKd>EL&(7mGihOZk(!j?j_|h;~$PkBD zHke!c#yV+Z=2_Y}lgdEX;M#!ORO^DIvDRr*xO!fwv>}@gHIyo;e3G-mOv%GiN1jza zl)El@%)=-QqX=k769*<33)tdzs&D4ytJ`X0jh4VY;xV(3JUlKWi6sS<#PO_EGZ$j@}Q(;aNLrH>y7b$;vf*u zZpNiD3S;0ZVHI2*8|~5tTmDOwaga_BMX4GKZ5d^0`L`@}>nE^}rLFIWeh6ihsi*?U zLmcO?E>2Er+Bmr_4e$(40kLs(Whye_D6B$PZKP_KG{`v2dXq_4kgG(W0kgq8Q{A@^ zhNMv{79(qn%S6}rF6V-VunlDufvj=^Es({@h57C$=b*l2G7_ z5!~r8YLNVM0V4`ytqYT=%nyQa@%Z9pHE#14y9V`?IcfI)hYmJu5a+C9V}Igod>=9tk*gkuHI3_yqtVoMj|Bw7E%%nWgF@~N^6M((o__)qBgFu zQ0@`=k0&;bCr`h6n%o^Z5b{aXf8;!BUobtKUKz?uPoJFxGQWNL{2vA}>vn(uoRO;{`~h zG91|pq1T85-hneNyz3xfpT3{aB^zq5y5g}3-m>e~22_qLY-g0Epw#v53uRQbQTK6K zPpx&@7=3$f!-~UqhwqZKG$D)Kk#=yEsYcfM+Vmm9`8<#g&Y4t1LNmo+{&r$6)<7gr zu<_VLT6>$-*)1qz=HQ6RBW;XDnwlP4Jh~NiXwwkyw37yW`%5(>Aoy0pl*6#Q3{3)# z)`!~_ETZu9&CNH9c~Er>TN@fjbbU3cUtj5V_UIR$_nIc@l&#P+Jb(e>IBrr09aQ57 zuHm+lMrYez_e)skA+l6r>Z-ETUAYkj;Se=$&n|EMXmNw_nKgVhaVQqZ!#`*8P){rF z9*%&6J;P&%l%bkFY%?4WVIYgC>?gQ&kSa8(jg?MIY1or0HbX2^%u|Unj#@26BoK&Y zO`+k37Yq&sTUjs$|^k?CMcnM#1@ zcJZPmRbVl3kTAMMOO>Iwe{yN4|0oaBTs7Zmp7Uv8Nf~N{!zu_q?CZ_vhK7(wByq$s zTO#MW&#Y^kOpnNr3`O++nr8}X$+YfY@r!>1+HhM;W2HKw;y~0ieU#Jn z8l&tmMM;#oRE6^L${hF4?{DmQ|FdskL?Lw~GGYXx1QG;3+Q&rjm zEN+-@MjC2ykZTJnsZ3G=h$?MI8B>Qe0tOrpMgbKRfZo?#L7ObWkOW}>uGRIIA%DwJuU{CMnj-fq<4^qx44|5*s!)I zRIaQ^$T(gZ~|=P!*Y(zCJK3c!Zv9Nz%+|_JOe0JjtBun5(VwGF z_)8RG$)m<22u->QK0vB^BYKMgWvanc7gR7FQ8-XGvi|@Wz0UuOHrS>7c3~w>d434r z0yD}iuV7%ZigPq3s-wkRgut;>AEB@Gfu~)22n`i~pBpO|;&>=nOce~H4PEETw^X?+ z9^37Qp~r^o%SLP*fNL^T)Afi>+d zd6#FAMM5l9+eR_xL^7~VyD$W1d$2s#9UbQ44n5G#*}nE2w$*f(2t za`711zKs`BRqsc?*ZN_5a%z_?sU>{s58wJ$)q78d50|2#44hLT4fP#7`3Z64CMO~F zno&)Ka7?w0&9fBJaIk`!LxX5(2I9#5arXZHKJvW3#zaU&I-@O2X^XLF(4bbM zg&bP&+?p_sT-~o?d8=lGVFdcXDlx0ucxk0T95%KT2*jEjd|Hyx)}m6Geb>GG=V+92 z&_52FCV{r85fq8`CNeN+?l3K1OmyctClf6 z6r;idKYS@ms_8_QV_)LUFHYD7pEgm$jd$3x?&e`@1uq(hyKj$nZpJsM%r}!1+JQ`j zb4$UrS7T9$70?54K=)|k74aY(dX?*k8a*6W%}~hlGeN@u^66J=dYR-n);+_P6|V&} zpsw0tY;0SzWFb>iTTT-3^QV!45qsK_X9g%s!J|o33?9{j(eTZZ2LI>}1fysQK|`5&bd;f1n}CBzStJeul5gdM7Emv56$yU| zj6#vaFs1SAmnpq!z0=1h6w*H=aky5Ov97f>%f#Cum29<>5rRSgzbQvf9>8d}RLJ?r zWJT*wlSZvpXOyUlp=9;t7b&BQco+Kp@Ar{N2+i!H6v^HSu-_%4kU% z`2a_ri=#G|1EH!*X@rd<5nIz+Z2Q65uy5E6$8o~O?YSnd<*VgHq-Z30Ye6NgLSZB; zp^jRu7H&1dxeEV+XcR?gJaifkt~ouF2hd<=M5D)8X?mh+Z-xA0HBu}fQIR>207xGt zjRvo+M5E4oj;ZQ^HbjmQNgKsYk*ES`Jc<3^G|s>;&N+_p^peUj4tN(W&%i`Q_dQ3# z;2=s(gNJZ(kVk!14_;&GqqIEdL^Px{iqgqHJ=19bj)$AL12kBdjNJV=dq$NY<|By;wq#b?eVLA1BhBV9?H+or0&?re1@=B@#Uh{Io4s{jK zXjF9)6`%PU3~USQwT^>EzMU;Soo001BWNklnRNW=4m7W_h*Y+Uu|_?z}?foHr7)bTu~ zeB*OWd@yDQJ<<2EHy`J5Xh&-~Bb=x-Q8e`{)t1Y`Dvy~;;ecRiJl&Dj)}G9gN-J{@ z7Gg7yI1woe$Cw2Q=6Koikk;`r1pz7A&mRL zKob4Y#m?{;vQ$sNI6Y=#)W&JMJ=-{z79vX{3Aed4EqJnOp?~v7i)X6c2Fk*3qF9n=a;Yp7Jv)d54>OGxtekaapOw!QLomtlC>S`$B z=-~aef^j;8q(yLkG0VoYku`8ZL+`v3{Af{-#v`7{Q)nJuBVL7mqf)69{B&9j zsxUes7Cd}|#>6O{?*(--kefzVkey`Q{;TI|F_hAvX1qNO$5Jf9u~?cNd_IE1bjnp| z;wn)!Ja|rnG}0BCP0_jror3BVr{Un=0Pt^|PldF>ctT{BLH2;%@R z|0+%hOyEdHnZ~N#?@jtfiI=y$q-siKkTd{CJY4}JuYzCDnR2XfgSp6rZPW`nd7{jA zWOlMGe(KK}TwRzX!YB|1NdwBO>yz=8IBrSVN$qNDM>$U+jY-2OYedL2a`_zQsy&Z; z2K->I%6gvHLL0AA*H~r& zjNOINorkCm3R78>bt}g`ReZ~v7vw3BhL?rsR=NTLp=lxL0v=OKDq$N$BS=(26Pim* zl|gWE>V7I}*DQ^+Xhg5c7ClK1#9V*`!L^~$tHBN1&Fi=|M@S5`mTESI-{ zdqNZ-i)_Q&1K$7|@W|KwbiLqnanM|(qY_oeq+vPoumJpyE;JJEopCxGTK(b1(Fkem z_s5fab|Tz^^ZNE_$i2&xI9h1sG$A1ryWB9coC!sozB9K<&QYBzjf1*IgEEyp*ctB3 zw}}ZFqfF-N6&qfqfQHp?Kb9f7E{$e5MZr&5PgZJw)t;0F_8K4!@{V141zF&~T~61k zWhVnif7`J>u;byC<+_%A5r&bBIE+{_)b*9i3WwssS7`-} zU74#qv<_mi3;8O}zfihbts1tWYN}3MR=Bp!8xF_%?@tdP0j}XfdfLu(fyVI4buYi# zF-`}xqYopoWHjLhi?Uf*L11Dc|Arr)t{QQ)4z!T?dd{aWqdX80%&vpgbr;WUTbJki z?!#h8I8rz41!&53&-*+20QV8VP|`3QgF<90HCi_l6^Wxkwh^aa_~7XZ-tYA915pG| zSl~jrRrout{8@uPx^C}*Frc79e*GK9h{nD~1A#<%RH!%NVH{=otgC~7V7K9M6DNT{ zzY(XdgFZ^ek|2(B$Hc&|c%p(#WoN9j?wDPNY4on|pwoM`W6^%-zcENvw|Jyx=i7F~ z_lHcCMzd5Z8(B&`m5rvnxfcjy*Avwgu|XDb530*W=)@HO!^vxsMt{u4xR7_<_=!Xe45fDN*Sx6bi+Inn2J3mA82RvAR|6LGti0 zZzpjs(kV_%s=lK{1vH%gI#V$ouXnpQhlgV(HXzKA2K@QPa7Tb48t!mM_2Em=Hw`rv zF&v|$T*J^tsgw;Y1I?QPud~8A=nF=cYaJ;K38fRX8-=`+aRz7Ivm1!P!0KCQBVBf< zGThr&h>ufn-+c2EcM?V85x@wf5eS2xw#qWNe{gm1Mm&x!U!3=52v^~ zvO*sXPm=LGzRL5Y7}f^9^+l$-35JGpRpW*QI}m2mxaG6-jUj)}&o}MtJ%aTm*=r;x zEkkqga>&PU$@grw0CB^7oXN*lH<*Iv)Y_fUr9 z@exl8Xy{JAeSl=>0Kqy8h10iU;gKR&beP-S=EN! z!9CbMDXE4!9wO4Mn(IMs9PLwENyk7V7BFyPL-aq)oOXx?!T7PJ=a|UK#kh+f-~p2h z3pzTrWP_xI<%a1SH1k&|cF!k*aR(Qu_l!^lNmV))(g@6IZ>%(A!wQzQVL(dMaLP|Y zNeCl{fW_a-r%Dtp!#70F@L>CAlSZ*KF$_K)n~STsab%LQp<(+*FcwDuvwqk#BpwM$ zqeK<%C%(r_m*e=OAqs=Y*S+dP9jRy{7GYr6xj5~$CkaDKMXD3YLoNe- zbLT@WDh(+8Lcu{zW|%Z8{6h~C2Y5J@8wnYu;LBZtlaMB|^r;|$Lw2iLa$D@-P8W^~ z!*YWgcrJI@Df|p|#NlK#ly&?sCNPp&w}(D7DjLUku!!nAU)LF;1k}0^O~fyBlmZ;? zCgs8Ule3P8dy_ja&+s%!sQxB&k5iQte^`hIjRjswh}cwjc~le$fg`(ELv18foVu%6 z_!=bKs}i(O#2t*ZacZ+@4ej6u9`~Q^bnwg=uzW3W zF;pa;bedAC#4rVu1*i2+!jRTM&f%VKIM~?fkT`HVes!{mz_#WW3mU0K*)tag9&BxH z1#Y0i4?NNzEmNrSuNe%P@KDv#>JT_aoc}r4IQ_O;ES5Ue>g!2q-03NRw__p=J%@pt zY2d8SK*Xww@dy4c@eB+X;QIa$5+?tM@y-lY!pU2saBzXFKl!$U2Zy|#umXHnRk11# z;z*m_b3g$LJ4KeOH35J4UvSD)O?O6|2qj?%Ge>dQG)BS@Io8Kj{br-DSolRbe;mY- zx@XS0hK)_`8$qa~ffxjju!2*pLK}XK)tDg){e#h?_O9h>V|_dgs0v%HC^R52wcBdD z*)P&M;y@#rHM{3^JhZS8R6^4+lsuM*hL6s{#00D@jlOpB+MxpRl@iDL^pJl-se1RI>Ue8g=d)mC)1%$s1ni)k1Dq%Vy8KX#~U-Asdz zn|%BSvn+XoTQd<(JZNasfIx)4Gu% z`R?%ZmSG=}#Bl?U3#&+k1=T_vahQa4XInW9S%`x)>MB%88Xqk;n~Yps5|Gm9%UZ+l z3p};Ol%@SglPy{?>u#$bbOtYpqkUCTz zMZfOjH`E4yG}hJ*cF%j0(im?bRw67m_47id{bd|%!<@X}TEL1UBnajxtG!zbWE>*F zWxh5JUuIRP5@5kcW9=bqAb42qMK%scA8j|OGL|!daXi5DMq*I@Ex7AK_+kOF9>5lYwZESC{x*p?1dj`6KJe7+p8$=2oyCJj z%32W;R_dsWpdJVofuRjOxt1hx2n(+pVhqR#s9uIqy^7zpGpq+^p2m_Y{wO-hxeS%q4kx%m9P(}Z zzRId7N-^yl!qpRa@v)J?V zd336iG-PDb#kUAi70h@m=1RT{^=JyYQalbX9Buqsd>MzNDy4R6Ac-(EEJGzz!PZt#4nk{D#v(IHa3%%P_iZbY z`7Q%-00+{@-cjk~DV_IO@=Aryw^2iuOsd*$q$-`oBE?;9K>IvsK#!^+ru-j&U36t3^6U-RfU0d6gt^p^$oER5~dtUx*=l%rYs@=BEf8p9FVNx~o zzOf|j0xmg0uLv7k8U_zjDy?#8&_DaWc;%LNFx456?Gcs$7~8a4VDBJb%F_kaipNRR zGURIbG#;SQMH`>>6>eDr#ugOf0nCkuriYis)1r}K;@`b*ge*%UMmv!|b9+J-oXGZO zUfhAH??Zv!M(cOAuS^=VUjC(V$`y{tt2gQxm3ZLd#dx_~aYorb0DD>Fw~mwdb%#Wg zfhTzQp4^>G2NUbz;p&}UyL}a<{IJ{YiUv=6XMVk57M%jl$20U0gk?t<{HML_c!8;s zL#u-6+*VG@%7B%_oQlNp+`N+%pItSdcNM|VEgqCpb+e?>f2I;5Yb~bM8l?;sOD5Qb=X=gvF zN@g)QnF~Ye;{Ee-yexEqFv>|cR4D>dA&fD*AXKCIa!)u1|D32hVkM27T%G>kA}!Ndsixs*rE@9%rHLOB2eqoU z_Y4}y!#k7GcuzNDc6OqtS41PvL)Gltcn0S*pfOc9dm{G`06i2C=RCA!p#@VKmUl~? zG@BepGe^BD9fG|3?s*qk0$(VvR%1VeDkTkKN)FsIE+iL^FHs<$qM|*_3>m7sXCY1 zs8(OMZ=#Xp7}E26tWGJ9MQhGAlqpqNSjImQ1wG4Y$2j~^wqdxs0SkzzisPxN4UXgJ z{JaZIE4mjG57^`SD0Cy~188&#`F!q18&4)z=2utdX{@eJW2u-GGfL)Y5Dha*ji8aH zw_TGjyk?gk8U?_BV3pe@9Fj&+C06;oXI_j6*SSN1UOL-|Adlm>zls~@F0L&&(kqw-X1aXI=+ZS&b_=GAr|= zMtUk~3=M82Vb3M&;qlD&qV&D3HdTmp?Ef_i+dvbx5d(RP&~+VarfCq z6nVh)TH_YDtFU{XY3On6(+Id~GRB8q}+T&f$^U zz#S(JkBW4jD@AaRjem0+A5CNR#r(K2W!{k-p$#yLkXTeK8v7Y1RQ36g%J4BD`OFAX z3IslVq_O?HP;|9X96`l{PvKlt=~0@yt?KDW8kra4X}p>;9O+RkFvAVq40p&ll8dMf z!#m89L+heO+F%E8XX&N7c2Qb(akMVDi$6Vwt(mx+Day*L!x0(ot<1`cxw#kfFXqOm zBRO?6sN^Wy#w~)DaE<-9<^3UXq`}60tq!wKXwVRm3THX+^qqpJ`;5kVahQka<*RBz zdZf9JFNR)i3Ruw41WYim($i)fL8CFG4cQK<$fn^wesRU2JBGgR`neIThz8r;JJ^Gi zs!%BEaAlN%mW6W~N4QT`v}>c__}o!Pa%FDr(IbK}CSa{jTT(?ceqkfv_HFPG(xB;a z{J!rVf9%Q19^;# zRnr!#XpsmkP=_*{tlPB=Arz;Po8c~w)?q{}QC`?IsDZKxheQ{}RepF=lZa84Ms%b) zvyUEWN5SzY{dRAyJo@C3gn{NU{drYZtVQQ9JE-faJ|nx;v1@;S!A){~p62TLZ>2mhz;d_vpEuQ)Db>JZ^p13Iisy~H%@fN7hpC`*%twwJ;#yE6@gbZA^iR>qJG zxo9jh(19|oClq-h6uO5kIf&gHEQ6qO!7yTDYFJPZn}%E#=CC?BvDrgw6XM&pq`&vx z@AsSE%*d(a)95EzQepy&KKp&&_ulW{A8zt{74d3ClUlZwL`r2)Eq;7AdMfKE!K!>- z{>L>MS_5eyj;Y}|(p8e@=327isH?7#s5ZbkV%-s_$Cs<|yedpHhx8Hq;u4f;Q3R?~pQjMPRp?%*`$(`6i>3|8;i2tz_hgesJV7f*7l zyyA$YQwbO(jb%pTZzjLlufo+~a)l%lD_)ALOGHLn)Q+iDQPZ?WR%_7UIEIF*R84ji zXcpYY)wX0A(#E4KkVhiP#eIH(tUP?h!&jAp!>1ItAKveW$}q(rl2r$#RLb^%hx+Ph zOGM8V3KzA820X|)vSFy&PP;fr8Md$tcL)iN10MNAtb*@3tjg6YoO)Et%_`5T{<4z1 zpEo?an<^0r!{|p%{6OFBjkx8be3(TTnx;x4yS+V(N4iRm+?*>*Z#Ur1pq=fTLoQ4XNzjAq!?+*X#=|3~73f@@ z8Ii`f(^XC2$if2#)g4np9b70Wo98IpgaZ^TKDiVtH{7T+tb~uxscm&%WVfn~)4JTV zfTK6;I(JnZIyVwMV&X@J!IR$o(YFjX35JvhF~K4*tF}neC5=pB>*kg{Y$n{23?vH{ zs*1y>IRdrttE#CKp0IwFJ%b1Oupw~hk;}$uJ?O`9X_=fiXH427 zFbzX(?Dj_&#~FsBi8K&~WHObV;mK|`eZ3K899Cp*NeNDIX`ng^@xFR|xk6~++%P~P zjK+6N{Z%9C@cp~bk9(Dng=k*wkG{M4`k}xPweoCshNA!~>B?{^$#tz^MTV4w2vhL0 zkSIB-GJR5J{J2WQi9FyMuci@2(>v}hsTr^2u{s70R7ZoGhxBvN&qW^Fsavd&w{3Nu zr>my5^3@YS;z{m>&@tr9IDp_ycCL-;39fN64;rzu&=^AS`MnQu^jYG{Zu?cfl$;kdZQi2P-Bn7rZ5k!5%v!S z4EQ*ezGa|!Aq_WC@=-@bW#W{EPID+L($TxII`_k+Z%thvn})dWEV8VjVvMv35oy#S znH77^WVZ&OO^y2N8dMxvA_1Q+W>Ppx7IkoO9hIUAPtk?v2`)|{-W~Bnbwoo} zNaL$91C^X2H2KZ&Vhb(Ii1hD`sEt}Vz);mhH)r;N1t7H7Vd=tlHkJ1a6_eQ%2cg(^ zC=M?l6Nev$DPLWgt2oG*wqaH{jfzSnH1qbg5!HctF0jxvKL3>67Bl7B>D)VzTNvIc zq&B*OfqyI&^U)+%6^AnCB+J6F1C_~db}}P0Ds%z^D8vlQ@{^8)BOKF8UL{i98LG=K zrge{bDcU)AEw#kpKaz@N)l2b`Lz3`C^RQE`hK=@dr9l8f3d#^&lKwrug%%CsWa~I= zavK+~7`0|*W-g|7Z(7mf8=4S=tS{8mR*?w%MJY^lb0LU`a|AvuVt^d$G=VClK@w4L z7}(V9Lw1E{f}eKiGNvC8o7)@ z;8!F1;0G=Q!AGnP|7biKLK^(NV#Z`*V3))&c6;|~<&%$Suhp&tj%iVIXw97_qk-*R zt&!$ko5eZUBhDDq>xw8MWuF9rOx&#t;@@84@d;m9VjDn|f@BH<70_t*#;r6I+c+s$ zVZiF$DZk?W0t!|Eih{9#0W{cS=B-R7)i@}(MTMxHkVuen#GB*RZ!X9=CmEyYEr6e8 z+1>Sn2d9xns10?PVX#7d9Cwqq5Y?nO;1{*)jrH{g!T@RPEH@#^O8JK7Jf%>!8`AJ1 zsjWjS9Qv{Bt(AFYlEarzn(GKe%nHV>HaG-xI1L2{(13M5FJm}VTgNbVW^;3Wb4qJ~ zG5`q^$809$V_x*p)q*b)s2om(+}>VsOUNU4L9*~!km>|gj8(pm@35kzcdG1mI1E{v z^96}dUR-^7k~q-D+0WIX{DNE? zVo6z8pm%B8Li7v8GLD| zI2WAP7&XN@$UR6Ln^Vo5x#GfPT)3Q@vt2pms@4}?EW>rcV3_C*FVY~HW zey$^Zyd%WH^}*gxLBkY2p70H!jHTn>eJQR;`GPq|S6*6ax<+>o*8a4(_zZCT ze3DK;oEMpt6)CYH=h_(D0UEd2 zZ~wXoqrd*kNfJk{SwrnjxF zx@Ua|BnSpNhr}_4ZNzBs2Cf1FS?K@x4=r3bD#xPwJ2DLY1NN1#b=Q89=jAuzIJ2?w z&O7h!F*ku*IR^u-j>*E2DbA_2w*#)>ScF2zL%iFqE#@k%z!x}tsSf`Ny!Op8JL!>@ zRLs9C&mIvB-7t29X~6CdeHx|lx{-N_;nRt-yV-5q3oF;ADH)adx zq&8~P8yg#!GUsb_TP@45xH{gOEE<`-Y@)+=kAX_6LS@SGcK`q&07*naR1W$J_Dg$Z zs{>s^hN8`0KjW4WjH3-Rsf~Cacd7Eu3Kx;HMW+9wBpXx_rvjvm~(xwf{mTgkju6L&TfjXg?mNgG@plSU&`4Ewgxuii`G za93PNasdWDxPjx_YVUNe5pfK9Cl*U^a_*A;oX#|++T1YuAdSaQjtyfre~!0wYvpN9 zgN+;AZ;8g>&y2>eCXGfWSEPnW*qJ&>Aok5I8|rc99c^?EgwbwaXM;v2880g7(7{Pw#<1JyBs zM@#36B`FPu;+2<>2jp5F3snIV#g)$(4uF9;t^kkG_H7LJjL2WY-rqlFMw+pc5#-pi$ChJ~`Q&@P z=bU?IBw+ZhyjUzwI!GFr2Gs^4vao)|xmPm|O+z*vIBKmgs1VS}ul>ATCouSrPc(=$ z{$7}{Y9n7G16lq(Dx+qzNE+zdSQ^jf|NE!EN*bT^ypuSN(OiW)z+#}G&(V&2dX-ql z6^CRi^5)>$YVD1+!8hevqO>v!+bC-p0u`{fXJ?T#VBu%u{@1t(+(3f3y1YS@fsdD8 zTt_ez9Pgwy$lQvY^O?CBWYsfxm|OJFD3Wh9S&m{bcv*EQZHRdYZ^)H(4g_WUyH>p= zzlA_S3}a(^t?+F5&sQ-H^!4m)HoJiX9X`8{XdoP)QtxODzPm3;@Da&V#2<H?Rq z-v4HHV1r2mn|XQn(^DTLdy-Tf7rJ`_X-)K&e%tZlU)oa;8EcZWV4n$%D030ze>w1m z(1r=j;Qc%n*rR71n)Cn(pi*lk>w=99_#)sZ>ucpB~B&WfGaU zWE}yGpEr>Al(8{To3MU+UBJjn8V!VF@DdeA{4`Q|eDdu?;jjIsyWh%>*@$^{=#4YuQmjjTJr^028FUV!EQcn zUP`FSaJV>z2QQyb_K~tG8FQ9W&b|$8=*d@!H`(%-9DBZWH;e{u#}yoOgd18@0lCBn zI_4_BHny70=Hw(MGSGnb0Icy%C8lW%CI&VJvRQ$GetdX7*>l?HLXDf#&%JHiG*8() zU%dg2^w`qU(sONzsSORsL&I5%l&3)F2-1cLtlcIJWEGYL3_xW;ahy7j3aDSGB-RCw z5tJb=5E>Wzx(FlTs>Z=S^&eIkze6w@?xZYc+blXgan`vySl1Ee8-VYB4#5$m4Qq|j z*fK0-9|L{zbWcxTUrsm%BT^n=c`DWlH|c``6VSDFwIuA^VUlGkhjj6Db8~aC80O@w zjwkNjh(H5Gp%HLh&EIOf&E2i7wVGHzx0Lz&>C+ebQlnTHj_Ty+E)r?PJ2Vug@g7c6 zl!UEhDhkFvgqJ5zRzF;7Y~r{XT3AVK@Ti5chz3N_g<|96u9Wx{8%=u0P>uuN&eix4 z{CMV^T2T>wI4vV~)9Cj|1G%_NQ$iZJ*gdFuq)%3>kDhPRcn~%m!9#RJL>9UC!)O>$ zariD95M3eQ>5g?H7X3EHVO*oWAu?6DjA)#Sx1P!*{9&s{wg7Ta94D)fs#TPwBH?Hv z66=mCk87P_7}02$K(h@X=Z1>Ms|gMN3FAk^qgB=#4)nNjG3LgPbbasflMiiO6sk0E zsdb?1tWpTZqhDhXiy_IXiR~SO&{Ea4keeAw7UGPHOe7D2uT>Tq4EXoKp~KS`E~2<0 zx($bwS4X=5L#u7Q_RY0{t6pdyq_jGV@>JCo+CT@*b`CyAY#d9Yybw_v5{4P34WQbE z*x;ikDW(pK-3kL3r&7seA9ao^WtpmmV(!6%6O`U;P;uBK4)FKsM>NU;1&W6+AHNQy z@q}n&U1Q-mooXsyo-#dTJYNT^qun!xaRwJo$x%!n zUtAPC_FkfR{5k;0Dqa3txGh~gq^6=Y__fF)@hJI6KA|QqErEGfJuG&S8ulbw#ik_* zCXaL%6O~6F5(U9QQk89I4q_W+LW2U?c}W8SnPZLM4Bi+0<}6NX`)5uH_Xq&%WkRwHqy zsSV{w0f355z{zOr(CrGlAMzS`XU7U}2P?-dy1VKBVPF!i(r+G#`S z$+b;a1P6vOHNu@E$pMx)VKqQPjq zLP@HEU~E+|5)1>q@2NCEBxR^pE~{Pt6FzMK-&JYom$#-!2yqNy1ZmQGWC@QLjYBN@ z;gjwrV9Dji4VB7PXMr9iHyueEkE+!G8Z2I69FzzW$ycoK+Es9vprdP;9(9-?Kqx^q zm3|SLvV3R&24iY0sTxOyR97_mS`}OP6h-Y}jF~Y2Sh=?N_?{EaG!?x9CgJ^(v z83~_dP#VxpMYHj;LgTqcqy9?4v9j_j{&P|tWECQKcq@lY%9+0tOvpD{2g;q?oalvOp0 z-ZiAHhX>>()5k&W5d9n3xl(}1ErUl|vvGVtj3d_mFGnFzHPD2ljinS_;OKSnp^fi< zc_LID8O=BvUUBSraQw!rj&akELtkUM6JQWQ-tO72pstzol_pgfOde-xrpnTR2=Q@r zoQk)?C2bwVgAdgCK|3MGQks8r(?DMrO1-WNPekg*q0~l4aRlKoEPA&VpesWirJI^v zXb%q+6M(?|y7VFrLxE9Oy(6DR42FoG$6i!nZD0bnYr98?cf$nqIEF%k&?pojzE^L- zJswU&cH>wZ9v`oJ#L*Nw+NIgb5W^(kD{tG^Qf5#$?%xNe-cQ=tsZaTXSi}f|ksT!t zi;v3LO#B@OKH+RcMTUba3mpb5AZ-*74Ct0l91X9kK7>*mUUAet;*dCQQ5y&RwX03` zl76Z*0_Gq-5bb3lmS2JS1=y+AJ;JCf+MqOgMlp+QHrCn5QDr1TvQ?Y*TfsrJ0ShG* zAvlH(1e$a`t$fH2M>~;loHua!}>*Z{BIRBu$~fH{CClj(vQzqd1U{yNWm(oy4KzP`Yu{ z?6G-L$gUkzA61#{F11n0ThnUQ|M$3F4@^^>Mi%#c{p2WKZS)NBs+LU6ZRlemdp-`r zC3oDXuWHoW`*Erxjz_N8vxr19u) z5a}F>Kmn5&>}?SwP-bz5h@mM+WI<&yIg|za;22DLXx+*^^$_-Xp7;06J5DdL>t{yF z#C9N_&wQWn^Stk9Uiz8P&&dfxH4Td$U%zh=ha4NpFd8`qW}X}RYo7q*y?3bnzGqlQ zS7?KTu^|^=+gQt%5}EX?W&oeDh~z3m9k=z;s<#~Cp%NB;gwiryp|60c#IUlg4Z^GY zZK?b2qd25CB$NgA>!b}DTqUplrYb(6q@mDB2wC6M|OjjRwE~CZ%H0db{wP zHs|y#CRZ8ixc%d8sSa(qhZXTsPeV5s^ILuIAL@|Z0>Ut;mB{tcsZ}`=5*5ed!h-a| z`72Wfjo1J5?s;31x@W`D6_&9f*ZZQ?TX4C^Mx#_JLCWJIAYW{CHd72rZQ? zm#&sKqpflmsVU%rE#GyjbzeJ-L~gQs z?;cJxZQ8o;E=y9~n<7WCG({%fkc&)>0T0)6iurtLJTX2FzfoqqP{ls*aF%K&}#n z?$~iJeu?+xm5@uzCi^|fLEP!1u~_N#!j65|r;cMTZJTlc82I%(iR4T^xu3yg#l>M* zh7d+~M-v9wH^A6v$Ylv}WkR<2wu>vGdtMNDL<8SGRMrujtc=3ywiL(i6LU3pVz8oB zSu0^4yh#)~(v}Y5EG#2ZOdX5%IwX_JQ2s!XoDB`av1uD5+!QTFSIbgzbz#l|kNL9O z5CLw%=%~wB1VMAC21tIj6;@yUylWIz-w5Y;2K|cvbS3hUCUveA2K`OD9Z{dmSUx(c z$HngAX)_lY$WsvWiL;40OIh2sBq>RPE!Rm$8*9MAQz&r91#Sfl*gljaB+NSwLh3NP zau5gmS)bymDGv3AmY|j;BvF5bMx|C)_4y<}4C7?tG#G`EPf!|Dvu8vjGi&SkHd&Iw zJf#bRWhlOcsslJ2r3;t*LYfA#Xf}a|rjCQCI@E0oELjnZf$x7#Jf1A~mZOt^N&^bR zim4j$Nc-j9@v&VK#N{MexfVapo%{31$p5C$H*TB}jYN9(-aRqT8de6k43(oej|MAk z*BZJm$ShQrVlXfoYO3P^wy-)(c|3eLKo}~X950Kz0VNpj)rM+9AfT~$`r;T8l+8pGwQ@U`AkAn~ma6!5hBT9)$J3-*({$qL}e#U&|- zfBnR0oaJNNCajhr2SPR;3(LUmFB{A>a1r!TPr0|yhRcM}l+s`kFd)A^J2*J_P@5!| z`al@?BZ7ru(m%w3i=*C(xiYW0jsPF@==C5q9hnx`4NK(3E1g1FDvG>M{7f*gO zaQyJq4}*dKD3waB`O(m>?Qi87-laI&h3_5q>pp(tPn4KUpY}BxUseWtdu+N7P=GLi z1OlmMVrg(`%%AlW4f9>I`3^N1s`*w;AMAj`8FlR}lp>mDe9>&~v@r&Q0e@?^x7yn& zjKBFdX+(y-IgMSU!MCr;zL8;P@ySxp#%#p8{v z&O(yFgBqX!b8ck4z;tjeNm)=}+}dfijp!hnM?@plvCyc;(&*Rgij{A2FjCc*c-jYh z$0yvn6%R;N)>0Fy+Y#pB^Jo9))%2_}t)y8-BdcX8sS7qD;z42Mc!BWnz<^*Q0W6x$ zj$}aZTePQmtPSk8Vcy+=Bw(xSG@=cKFKFDQb6>4izE+apJm8gyvvHQF&SNRe^sI1< z9m-Im$52_SVeoKhP$Y015(%U$=)s%1f!lc8!aNliqCi~$j7KRM9V$yLwxJzJY19eH zsnNfBm!0=Y2n5qcvSOP_N@IOXd1~r>7A7rC%3-N&H@joD-y&*c7Y-f}2l5VwhC|#S zFbu;UUkr5+WEsGty(VEi@)?Ud?-qzg$e>XhAHXY48gonZ3?o)!T}@U+QmRII#H6Y` z(D>wBDk^zB6nK&X7};>cXSg@+HI}i61oR$F<{DbAvU)~y*l8(cYzZnIC5-`Rp(iTe zH*b6DGja6EH^LL!xpX=)zPI;s?N9 zdNQ`gP4f}M@1~}1oa@u<^ZZ^yGfmaFC~8znc_0eU;nBccaJ-V#YSpE`E-fvMkK zpKF1uUl%3DA{(h}g*Kpo0s=^)#(-df>)6IYjM!;$6s@*dSAB2L$isgjots-UXw*-m z;rqy$X!)iJD$tu^XJt2*>IQzmBV|C8aW2LEx~by zuww@pG`%s0C#aB*2g1U4hD1SV{o1OKCDR7mW=**B2FWDrd1H6RpvLt)`^aqoC^Tj0;=lpiFbw<0ZZj-jvDVzw z#w8qqBHt)a$NW0e8iTSRQx*sEFHa2GOCB zU8fZ z@hD3$^qRQ!Pk{L+u{;|VQMl|_Ei4{{d)M><_96$(W$xg5{`}G?;BWOct!9a@9<@IrSH~L+CK}$-O}v587J;-fZa3k^23K z3a{~XivQAHt*&!v$Qmg&<;*A!Wi3rfB*_c3nqRu$6$&T^m!_Clo`RPL?S|(vRp|9C zG=rUOps>$K@Mv$fRZ)dn+1`q}M&b0E@ut`BlOWa+hLT2-Z?R`}g3?r(u_*HcI%Zq) z0*QlGo+}hfMc3scA|wngQ8feY_K;y`A2jhM3WHwzMoA@j9KTU>Fx2t>5j&%+N3sF6ZwIfl-a?VZ;9`%De{h~j;G z$3*o2la@$PtFb9?jOS6cgT{-3(D*G(i#!?1%RYK$~0m8t|S=oT&E zZcy8yWobpYA;I1OkXU^Kn@wJM1tm+4Xo;O~4^W$ZBq zA45^ol4quQ>iypD=MK zO??3zzzW~Nb`^*Vr;ZyirA?uyfxIhwSsoKPc?2k~MHiA+{d_^3;trsN!8SaXI2Fwwzda@%csZ>v5RlY6D*(g4 zSR7vh3&rwK5U4Oz8ShZ+A)3s*V})S@7L^>&&Thp326Nvryt;bU7^+YlQ0O@#E~A1! zewRL;rhuYg7^DrN0X#GYti0B$uJe1#0vaUuj)Zyn{q%)2pv$p{#Jr{FG?Vi0aT+mK z98ok6R1z_gcUS;k^aTW>5bLlsV1a!oUDUs^e{^m*L=ldg|H9#6p!&FDsOWD_i)K^G zb17Oqep}cXH9=-P35=v-gaj8>`mW;Bg;|C7_FF81fz(kL`@pOh169YG$E_c!et$6x z8mvZMpCb|=QFC&XM)EsRWLsO2oHyN(c~tc`vglu`JSWFibi@+}0+~qdQE09_Izd*& zF1|$>r#oMnu{TPc&8N~82PcQuhJbT6<2Cna%mvDOC^_1f=lyOR_w!uoJTJT@aY_{d z4LqUT3Q({(41w$W8|qYTHI2`^|1S+#242xX54^%3&yCua1`b0gJh4vDIF1)W+-|qy zi}Q<%9F|5HDi@y!Xlx5sm{i$R7jaNc4lq9bd`aEscK{;@|8p-hvVHQVO!aKW6*$-5 zluJe88-rstjE+FJfv!;$yd%(X0;&32X8qu+p4FxbZ*@;Ih) z{AxVT#%A4RS(apFo+r61jTCgTxs>pr#vya*plx7FS9-cu8(SMx&xAqA5j%iCufSTO zY0JS7f8{Z4oE=a77pIfaxH2%zGt0`dbbbLQjwEuWw&37?I?4kWV0%PStkQmli$os8 zsgI}6{b;oIz>X*6Id?Pfrc4!`V>*+XV}r->_{O9+8jZ$xAdT{_G&mCBkk@sAo{>Wt zp*C0)Jl{}!AZ-wqj?JoWT{ZrX&1qlz`Kip1u5Z51=X99PxDM%_?BL@b3wfChjwDiD zO?tiFXpF1Osypxw7pL-~&I_HZBExC@asU7z07*naRP+o!tNpYJhaB8IWE7o18yls@ z=Pxgb4ny%`Um#LvH`NX3<6HoGEEZAJf|KrXL@5tOmQ;7+k-@>n0qRgxU8qnK4hh?Z z*QEk4vC{B(eEQ?%sZ{93kxh?`CZ;@gnqmtueo9r-*(}gSi`P+9<5#_&qfup-5wsOso+Xd6i?42?23G_LQi%M$ad+5y4yT57=!*KpDRBd3g4*)0ob z;jj5&HhtIQ2=9-Hnj_VgtO|Hwq%voR&v8ct0uEpscNu8ou1r?u1cTJZs_PBYD12eq zQrxDv*224cpg}AaG!De)Q&YTQkX1QZ;5zvHFYXBqu<@#_sswKOHSUq*+!&F<1CQ7( zDQeA@;czev5Co=H>>4*6nsMBId(AMAMot<)MD7V+pi279G^RmTMV`Uy&~4m*S{gl* z*upniVvGVBtJPL%)P?4aB8(%Tffcyx8q$!%(0Jt!-5NL=_U>;Z4#IJ^Q;dT;V?!IQ zLsuLV=Nd*DBWN0$(l5(a@I!6G+Lh&`4f1g1%)`2PNAttRDN1l}zrF6?GalIBkN24^ z7I;_e0)WgLcbuorIBQ>%RY(%9Bj+i7UG zAD3UwUp9E|h+9xk{p!@v(xXb}>wPb%fyUy9V?UvID3JxZYV4l82^FBatGf?J>PJ`;C0|G?g(o?6P-q!QL#F5 zQ*{7|G9e&|*FjW}+!7Csw_#f6DEwGupzQBTqew;CfS517v3$B0>uelA5Q!EEWO>-O zVH+TDtg5(2Rb^0fB;|ERBsgSQ9I(-iDh?J3bgW!j^^3)ExyL44*G8%(QCLuVM1zXP z|M1YK0VLLdf|wk*7{AKUz>$Zg0V_!|;gFL^YPZ=c?d()0Ybrz(;K_h_Z)#! zx&K16(ee(>+Hj3SE;r1}nwcD&hOzMxc5lZtYZIPt!lMF_Pw;?KqB#OE*?3jkr;Pq8Yw1J*21acsOmf;bwGfE(3Kb(t5uTg zO?_zIT*Wsn!|@Hq%U#jNd?8&Xi{pv+)b-S7;b45-I{YS{_GE+}KJukeWhe`%$1zZ? zupWdqJMGL3a42q56{HKL+HXYzfGlhwjiJBQ`rooSr|QrA*?2e@KZebp>4cnvl#$^q z7T$c8281e%S}Rb;M%zj&J9Wa_mM`P>TMW?Rfz7GDOM>be9O+ZG@#iBnj^b{!D+pBM z5tn{+!+cQXR_8Q>u(wcJkr1#|E9Kt%KJW9s@AJ-RMwWBL3cSzQmSj5% z`+od=e!b7U@|Wmtv+_%HRI&m@4E&Z%-9G%4?su%v`RLl()>oXkke-U=R3;4oGB<7* zo{HEK9dEJr?A;Sx0*bH!;X~Aak4Zs}Rk)nuS=s*D?;HZ2s&tt0R3MG_#oH7WN8SD5 zWPH_9-N9dZ`ImQu1&TxU5MMtw?&(;;osE_4uRp(9mNA^+Fr&tJPEJ)r4ym{S5?Q)K zs>-#k=ZHgeNB;SQu=tbAYWbEQI;ri4m?g%&zoSE^M71$~KQF^AZz>i73zf!F9yRj( zi3%M`7mw){Ip2VVF8cP?_V$DPFVwJQ$d5S$0PhtM_N-Fm;xq?vRRqWSQXXztdHGJk z(5-cHy28o|Op8<=?ro;lq&7+p*T$a(hVjMR(T@!TA>#(shQFl8@RTdhww_B2@c7yY z8NWW?X0mudFS{Wd>bx~##PRp@XgDf_D~T-Uxi6`|zuFeSU|gh|dM;>eG57Sas;+4m zM;FXj!TY2DjpO249JiYOBf~hs;V=8SpQ~%N+A2SVq*B>>&C=LMtL4g8W$oeLeXW9N z&>`O%KQ3Wjb$lVl4l8%ih6>_3(XBlCcC5TiF%I`PN{3>+4G&irLx-iK{AI1In<*9I z0BQK&@`2IIK!f4n(>r`r;o|s6-93=MtQBD4_y!Z94gZ_c#&QW&cSgi0F85XfhEqhN zEDnBiOd$AV&93X0(cobNv;ibg8ppMwc!QZO1ae1zIR0kYuIv4yxY+t*vcTA(9991D zovaeaG>WPMzhlG3m&T1lhhVrk7SHmh6l%UhXb=?qjZLkix_9;G%hQFA&`*^Vl!6JK z4V^`)XOf1E;rFhC)-er&K9vj@63L8Riq$H!a#j8_*`xAR_2)a*QGIb|1O}=glLBRk zG3k^xs{8x<%^}!RN<+FV@!z?zG`=`)@Hk%LDBv805~f*Yq6qOSIwRgd3`YZTXjoKp>-`C$-@aKZWJs^@v&1%Hw`Cd?)>;4RBT%d$Nw%QMKO(79b74@rFvnQQ0m$ z{LE=wT{W#f?v+!Cv+YIA0YHxM%>rW6{P4q2bH5 zrP}ygA5FoKG|2v|{A3C4h>FAFSi~x{*`)mscE+L7a3zgCF7VaWoAhX*qom=#K^O;D z;@52~U!)W#eGO7Nz$eeCR(AqLV~8*kM>{I5EYyqA22%&;(M%>tDxMV)f*ki5pkm$1o3|f4W3(F|Ky9=XDm=i5b?(c z=*>n-BH*ibn^InG{K77KZnH*;jw;ZB1MT*ypCb-uECW4i@sHwhZ+H*UL`{#ev}iSVTe@t+*B25ttckH_7YQss5;($Qln@k(^ARk9Gz2Lt|+FQ&L6vc3u z@os%D;L3<&n^YB)8*-OOaQK7F)s{ur0Q=<4;BkBY6qDf_e|$cjo==$`hB8K^SR^rr z!QzIckz-|Sgc$0$!GYS%RYD_((>S6?5SfnsF+(wn05R^RV!^|Ds@%9i=5W+O6@S3r zJMW7S8fI!0NmEz~&2zaZT0Eg@Sx=SgseH0a0T^!dw0Sv2BUU&fV*NW<(gG7a_Uy9H zw$%+MB@U8QWwgP~OR=~E4jwRCv1HM*VWU7Ax|lX$km8T{D%XpmMPLlQ#HG4u*&tq^ zjdk6B^^J`tyaS)oaFZ;GA{;}{4dRw&A%WQ2333}F#vG1MZa5Y*3W~<392CgHV;XSX zfL$)f#vfuyLhAy)*szhCQms3VIT%Iu05=qkBnO4(MJi*$b>}&3E62nSY?CU_HXQ1y z^zI*glaIDlxqr%0MdY1+kTAGO9Ie`Q z@ze7k(|#d~)4||$&>Msv-^-)gh)qqzDTTxq#@x7(v74s_C_K)B>4JZHV#k81Lq&|3 zR(k0K*S4sNX_RKb@W%zRa0imbfNLX0N7ZU&-BoNlESBBcTBESsDB)$=G)EOE3uQge ziTAtp_xMOu$Zc zrg@( z3AoxsCMQUPbZ}cK|0L;HKSgXGP(=Kruf0`LGNd6kVo64Is@7j$s1f)Y2pZW9rr2z# z$JS37Zps^af(3gN3gLHwO%HJ=9OgGm7vu4F-`#2$-b@fWc!ZLM@=-B~AQaG^g+XjD z;o9IJn7{J+L)g!b_?Y1I{PvvLEwg`r7M4w@C=T)(XavRx0x8B-YGrd<)9PWEfRE}U z5HU2)Ck)uv&!*}0HtnR^hBn%~_M%NE8oYCXZAMAIx%BCJni(F?(-gr)nD_ zMhx$98q8eJ^OT!X`e5?-9A#m68AmlRQmlcR&edBR%2Vl{;m)(kE4#%+9aR`24o)OV z0EzNcQ6F%4k;i^OCOaXcg4$1g7~1F(8m%}sHpel|J-KY0O(tiP?=1smWsXA806R%I zlf+{WF8^@d6aEWfZ*W2!Ra;RY&3hvgJHwCrqN+I2ni+zmQeAJ zp7dcMu+iG^s5IKN;t&d1P#HF*a;pJ$BX~5cm6JJYgrsmv(11Q!i<;~(k$tA>_;AN zi!6bVCap=c=pPVLV-tbvdkcXZgIj?My)MNRuH7u!!QB+YD|V(12xRnNJ2eYa?fv~r zR~mU{b{pR_iN|&l2K34Ie9t+$_nIJ(V_Q-{F&J!mMc`0v{O5BQjKVmr3g2PE@fUpG z6@BgT?WgxQ;_kS=!hg#hW}*A|$K&g zg}x@Ya5U`ZL8rIcSe?UQRh5{GEL-BZYMOt{OB(z4Hx*$KOs@3^&E@K|y2dnIiEFcR z^Y$OR(*b0y`>Vw_{)sTGx7+o0&Elaf@e+j}M&AZV234rQt9cC?m#2AGzkVa6NQ@)=7;=vy)GHxfEi{}m7t&D}!_ z#JVIj%DvPEy57h$Rz7;HO&Y{jT&8LnIdcecTU=YOz$#q~h2SWVQ4mew{6rr#9ta1d zE{=?$CabE*b+3(`8wq*$ukP|&w2_FxdTK6p!;K)JkrV5o`mrY^Kh}gmS$bOhwa? zC(HeIEBvAh2@?m;Rer0cDzu_%f{ew9L(f#kk}7QIx_Ka7fD(iFp_#Wdj;*Q=Ar4vS zPJ+69A{Fib91bHsCyB;Gv2@6?*4>(-P_+o*aX4KDvkuts#bLfoslagZY);n7<1f8 zblqC2TCXkUO)%Uw%WvP3zkiVJIP!)9A`4L`RRxhoLMMm#_P85Ysi_K3<1pnRV63-V zu3Fnf@o*=WA^MYvWjM0o3<`Z#g&f}HD&05$x#gFt(_66L%Cbo}@m3H`h{%IUEm`>7 z%heo39s%n}YIhG%H4d@>l$BI?8!Vm^f@&*Jto0JtyrMG|Pk_O&9lO}vG6Wx@YSDH_AW&F@+pr>VJS+c-s)GM>ZC5PnF&E%xtV6U7wMEsd9 zXp<8|TwsBUdj^Bi(gymzs~{{a3#Ee~l(#lyqB0kjDB*4b@OL55J|g=Kas!<1eWi=p@N9k06rhw}U86&4Dz>Kvi(}8dL3o60I?6x2_k)Rux@%#s z@P$XiX+xciAZ=hCblV^Cj=jc0(m*UwJ2z2dntZz&vH;Q1c)S(=%vZ3f_y0hinoR{O zsmiKeP4t-N`f(#-t#zEo zhS0}VZfMI? z+L!l7~+e$x+DTjiQqiN(i9)% z{#J*+80ShD5O(`T>Sl*68swlb4F`jx$s;$PVQEZ#pE*X2Ogd0}oE>_YLfC_&{r1i2 z(bGuT`3aH|bsZAv6nw@G zAjXkG_#_-i8pnO?Gc|;q_Gb2#u=h#ewn^ zqH)Y6?xlz0p)x*ugPvtikB!#OjaK?Yg$?b;ee}2CTx#vh?E0kih@k2sJXroFGQ^$ViXuSF;Xn5*&eQ`i8V2=_> ztUOcG7|mmFU>GO_i{qwoDQV30&u*eXQt@$GX637@CKj&;fJhA-Hwp?A$2_MROB!Bd z!q9O@UyscK7zptU)dp@iRquA%;O#~?j##g-ECKZ1B-Z>pt$J{v%r=897RRlPOO=K< zuiCk4V6gHF_LNe(vEvG?+Bq6_ZDd+y6^qaPOXK(eD*EL&TXFRTS)h`(X}obXB$6st zaU3L%7LDGZGp@?f=*(1}_xiRGFjN-lOT&O#D)}mX z8jTJs2RRKx9LIfI+{jdzNp{{;;#^#cAx#fVREl9&)~-Cxi8OLk96!Bs+Tbpp5pkec zR6JK5W*lAqZA()$5@#Bgsi9zkVMNjGyo!|$a3GR&sDbA)?v*rkapcQ)P7D?lMi!la z|5~Zq7=R-kXyPE(A{HzzkA4yEnWr}#OdD7pQIpDcW1u|JN7NB(vQTaOi`z+K462xI zoD+3K=TX)i*lqNexpCY=fnx7i$V@d-J8`Csh|s{1E#^`f2cf~Ahz1FmSq$mH-_`(M ze!6($Hp4O+AKTiXKF)YVs2v2o!$Nzoim3~Nh`%`!HXF}aw?UPGSuh^o7gc4Eg?3Aj zzmR{L4~u5x5NI{-s4Wd02Np_8Aj(Y+^##Y03_+3P&1*-)ZXMh2Pv=? zO{y<>Gd35nkC>It&=t3_3AF$K0zOGZK~(Vq{RsRs$L`|W+TSBpta5B-I?xUIYzS;trW# zWjc?{LIxFCiL%w7tvT#1X&aOc&v{!zXt-v4P#2V2KoyC+!0F zDn?e(EN-bPC=AbKsspO5sBPgkAm5|x_V#PDB%{To`Ho&?i^W&OscDv=SyqS;s-JH0 zR5;_|N!#$=x@$ckE~9?uFaulttxAb^EbPye@G^zQnY+}323X3K&W1AS0F`BtAq+vo z`NqIp6`3_|c7Rq4Anov6zj25-3>$xzI5Z%h%u{Yob!b_YJs$^wah|m+DpyiH#W|wq zP|0km%1Ptkx=P&WcnNhxQXSmHN3NneBwLL~+C9K0XQ`HxJ7qj0T|Ebdi9=|^!8lwV zXXEE3s!XnPYS~0X_am!d8h@hmyO;!%Xo4pcrkvCVaN*CV>~;S$#p v))Ll{2IdxNEp06zrL7|_F092*|E3cF*bAKojw+Q{00000NkvXXu0mjfSyO{C literal 0 HcmV?d00001 diff --git a/src/not-found.js b/src/not-found.js new file mode 100644 index 0000000..9cc6abd --- /dev/null +++ b/src/not-found.js @@ -0,0 +1,5 @@ +import { createApp } from 'vue'; +import NotFoundView from './views/NotFoundView.vue'; +import './assets/css/base.css'; + +createApp(NotFoundView).mount('#app'); diff --git a/src/router/index.js b/src/router/index.js index 2406e83..9620a9b 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -7,6 +7,7 @@ import AboutView from '@/views/AboutView.vue'; import SplatfestsView from '@/views/SplatfestsView.vue'; import ChallengesView from '@/views/ChallengesView.vue'; import SocialsView from '@/views/SocialsView.vue'; +import NotFoundView from '@/views/NotFoundView.vue'; const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -18,6 +19,7 @@ const router = createRouter({ ChallengesView, SocialsView, AboutView, + NotFoundView, }), }); diff --git a/src/router/redirects.mjs b/src/router/redirects.mjs new file mode 100644 index 0000000..5198ea4 --- /dev/null +++ b/src/router/redirects.mjs @@ -0,0 +1,24 @@ +// Only known page routes receive the SPA shell; other paths use Pages' 404.html. +export function createRedirects(routes) { + return routes + .filter(route => route.path !== '/' && !/[:*]/.test(route.path)) + .flatMap(route => { + let destination = '/'; + let status = 200; + + if (route.redirect) { + destination = routes.find(target => target.name === route.redirect.name)?.path; + status = 301; + + if (!destination) { + throw new Error(`Unknown redirect target for ${route.path}`); + } + } + + return [ + `${route.path} ${destination} ${status}`, + `${route.path}/ ${route.redirect ? destination : route.path} 301`, + ]; + }) + .join('\n') + '\n'; +} diff --git a/src/router/redirects.test.mjs b/src/router/redirects.test.mjs new file mode 100644 index 0000000..b5db195 --- /dev/null +++ b/src/router/redirects.test.mjs @@ -0,0 +1,34 @@ +import { describe, expect, it } from 'vitest'; +import { createRoutes } from './routes.mjs'; +import { createRedirects } from './redirects.mjs'; + +describe('Pages route rewrites', () => { + it('serves known routes and their trailing-slash forms without a catch-all rewrite', () => { + const rules = createRedirects(createRoutes()).trim().split('\n'); + + expect(rules).toContain('/gear / 200'); + expect(rules).toContain('/gear/ /gear 301'); + expect(rules.some(rule => /[:*]/.test(rule))).toBe(false); + expect(rules.some(rule => rule.startsWith('/screenshots'))).toBe(false); + }); + + it('resolves the FAQ redirect from the named router destination', () => { + const routes = createRoutes(); + routes.find(route => route.name === 'about').path = '/about-us'; + + expect(createRedirects(routes)).toContain('/faq /about-us 301\n'); + expect(createRedirects(routes)).toContain('/faq/ /about-us 301\n'); + }); + + it('automatically includes new static pages', () => { + const routes = [...createRoutes(), { path: '/new-page', name: 'new-page' }]; + + expect(createRedirects(routes)).toContain('/new-page / 200\n'); + }); + + it('fails the build for an unresolved named redirect', () => { + expect(() => createRedirects([ + { path: '/old', redirect: { name: 'missing' } }, + ])).toThrow('Unknown redirect target for /old'); + }); +}); diff --git a/src/router/routes.mjs b/src/router/routes.mjs index 3f52e62..53390df 100644 --- a/src/router/routes.mjs +++ b/src/router/routes.mjs @@ -40,5 +40,10 @@ export function createRoutes(views = {}) { path: '/faq', redirect: { name: 'about' }, }, + { + path: '/:pathMatch(.*)*', + name: 'not-found', + component: views.NotFoundView, + }, ]; } diff --git a/src/views/NotFoundView.vue b/src/views/NotFoundView.vue new file mode 100644 index 0000000..e11429a --- /dev/null +++ b/src/views/NotFoundView.vue @@ -0,0 +1,293 @@ + + + + + diff --git a/vite.config.mjs b/vite.config.mjs index 9dc3765..57df523 100644 --- a/vite.config.mjs +++ b/vite.config.mjs @@ -6,6 +6,7 @@ import vue from '@vitejs/plugin-vue'; import tailwindcss from '@tailwindcss/vite'; import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'; import { createRoutes } from './src/router/routes.mjs'; +import { createRedirects } from './src/router/redirects.mjs'; const redirectToDist = [ '/assets/splatnet/', @@ -16,6 +17,7 @@ const redirectToDist = [ export default defineConfig({ input: { main: resolve(import.meta.dirname, 'index.html'), + notFound: resolve(import.meta.dirname, '404.html'), screenshots: resolve(import.meta.dirname, 'screenshots/index.html'), }, plugins: [ @@ -25,9 +27,10 @@ export default defineConfig({ include: resolve(import.meta.dirname, './src/assets/i18n/*.json'), }), { - name: 'sitemap', + name: 'page-metadata', generateBundle() { - const urls = createRoutes() + const routes = createRoutes(); + const urls = routes .filter(route => !route.redirect && !route.path.includes(':') && route.meta?.sitemap !== false) .map(route => { const url = new URL(route.path, 'https://splatoon3.ink').href @@ -48,6 +51,12 @@ export default defineConfig({ '\n', ].join('\n'), }); + + this.emitFile({ + type: 'asset', + fileName: '_redirects', + source: createRedirects(routes), + }); }, }, { From 6f76a63b1944f6137384097d8433abb108554a50 Mon Sep 17 00:00:00 2001 From: Matt Isenhower Date: Sun, 27 Sep 2026 14:50:02 -0700 Subject: [PATCH 2/3] Give Harmony 404 card more space on the left --- src/views/NotFoundView.vue | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/views/NotFoundView.vue b/src/views/NotFoundView.vue index e11429a..b3ea708 100644 --- a/src/views/NotFoundView.vue +++ b/src/views/NotFoundView.vue @@ -60,7 +60,7 @@ onUnmounted(() => { .portrait-card { position: relative; - width: min(680px, 100%); + width: min(704px, 100%); border-radius: 38px 65px 40px 52px; background: #5432bb url('@/assets/img/octoarrow-transparent.png') center / 240px; box-shadow: 0 20px 0 #0003, 0 26px 55px #0004; @@ -84,7 +84,7 @@ onUnmounted(() => { } .portrait-orbit { - left: 14px; + left: 38px; top: 45px; width: 305px; height: 325px; @@ -93,7 +93,7 @@ onUnmounted(() => { } .portrait-dots { - left: 3px; + left: 27px; top: 29px; width: 330px; height: 350px; @@ -104,7 +104,7 @@ onUnmounted(() => { .portrait-art { position: absolute; z-index: 2; - left: 34px; + left: 58px; bottom: -12px; height: 473px; width: auto; @@ -115,7 +115,7 @@ onUnmounted(() => { .portrait-copy { position: relative; z-index: 3; - padding: 34px 36px 40px 350px; + padding: 34px 36px 40px 374px; transform: rotate(1.3deg); } @@ -176,7 +176,7 @@ h2 { position: absolute; z-index: 3; top: -42px; - left: 264px; + left: 288px; padding: 1px 24px 17px; border-radius: 50%; background: #eaff3d; @@ -206,7 +206,7 @@ h2 { .portrait-tag { position: absolute; bottom: -12px; - left: 290px; + left: 314px; padding: 5px 12px; background: #242328; color: #b5a4d7; From 686224a74421ea4aae8f366fed1c4fe4eee5681e Mon Sep 17 00:00:00 2001 From: Matt Isenhower Date: Sun, 27 Sep 2026 14:53:23 -0700 Subject: [PATCH 3/3] Explain generated Cloudflare Pages route rules --- src/router/redirects.mjs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/router/redirects.mjs b/src/router/redirects.mjs index 5198ea4..e3b3cdc 100644 --- a/src/router/redirects.mjs +++ b/src/router/redirects.mjs @@ -1,4 +1,12 @@ -// Only known page routes receive the SPA shell; other paths use Pages' 404.html. +// Generate Cloudflare Pages' _redirects file from the Vue router at build time. +// A top-level 404.html disables Pages' automatic SPA fallback, so known page +// URLs need explicit 200 rewrites to the root HTML entry for direct visits and +// refreshes. Vue Router then renders the page for the original URL. +// +// Named redirects (such as /faq to /about) and trailing-slash URLs use 301s. +// The root is served normally; parameterized and catch-all routes are excluded +// so unknown paths reach 404.html with a real 404 status. New static routes are +// included automatically, keeping the hosting rules in sync with the router. export function createRedirects(routes) { return routes .filter(route => route.path !== '/' && !/[:*]/.test(route.path))