diff --git a/go.mod b/go.mod index aaa68504..5d8e4dd4 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,8 @@ require ( github.com/gorilla/securecookie v1.1.2 github.com/gorilla/sessions v1.4.0 github.com/lib/pq v1.12.0 + github.com/libdns/ionos v1.2.0 + github.com/libdns/libdns v1.1.1 github.com/miekg/dns v1.1.72 github.com/mileusna/useragent v1.3.5 github.com/oracle/nosql-go-sdk v1.4.7 @@ -74,7 +76,6 @@ require ( github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 // indirect github.com/aws/smithy-go v1.24.2 // indirect github.com/aymerick/douceur v0.2.0 // indirect - github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/billputer/go-namecheap v0.0.0-20210108011502-994a912fb7f9 // indirect @@ -90,7 +91,6 @@ require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/deepmap/oapi-codegen v1.16.3 // indirect github.com/digitalocean/godo v1.176.0 // indirect - github.com/dnsimple/dnsimple-go v1.7.0 // indirect github.com/dnsimple/dnsimple-go/v8 v8.1.0 // indirect github.com/exoscale/egoscale v0.102.4 // indirect github.com/failsafe-go/failsafe-go v0.9.6 // indirect @@ -216,7 +216,6 @@ require ( go.opentelemetry.io/otel v1.40.0 // indirect go.opentelemetry.io/otel/metric v1.40.0 // indirect go.opentelemetry.io/otel/trace v1.40.0 // indirect - go.uber.org/mock v0.6.0 // indirect go.uber.org/ratelimit v0.3.1 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect go.yaml.in/yaml/v3 v3.0.4 // indirect diff --git a/go.sum b/go.sum index 7b6fd2eb..522a98ff 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,6 @@ cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIi cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c= cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= -codeberg.org/miekg/dns v0.6.62 h1:3Uua303EC8Og75QqT+pGRrcvKNTOouehHOQS36KbSqc= -codeberg.org/miekg/dns v0.6.62/go.mod h1:fIxAzBMDPnXWSw0fp8+pfZMRiAqYY4+HHYLzUo/S6Dg= codeberg.org/miekg/dns v0.6.67 h1:vsVNsqAOE9uYscJHIHNtoCxiEySQn/B9BEvAUYI5Zmc= codeberg.org/miekg/dns v0.6.67/go.mod h1:58Y3ZTg6Z5ZEm/ZAAwHehbZfrD4u5mE4RByHoPEMyKk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -75,74 +73,40 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= -github.com/aws/aws-sdk-go-v2 v1.41.2 h1:LuT2rzqNQsauaGkPK/7813XxcZ3o3yePY0Iy891T2ls= -github.com/aws/aws-sdk-go-v2 v1.41.2/go.mod h1:IvvlAZQXvTXznUPfRVfryiG1fbzE2NGK6m9u39YQ+S4= github.com/aws/aws-sdk-go-v2 v1.41.3 h1:4kQ/fa22KjDt13QCy1+bYADvdgcxpfH18f0zP542kZA= github.com/aws/aws-sdk-go-v2 v1.41.3/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= -github.com/aws/aws-sdk-go-v2/config v1.32.10 h1:9DMthfO6XWZYLfzZglAgW5Fyou2nRI5CuV44sTedKBI= -github.com/aws/aws-sdk-go-v2/config v1.32.10/go.mod h1:2rUIOnA2JaiqYmSKYmRJlcMWy6qTj1vuRFscppSBMcw= github.com/aws/aws-sdk-go-v2/config v1.32.11 h1:ftxI5sgz8jZkckuUHXfC/wMUc8u3fG1vQS0plr2F2Zs= github.com/aws/aws-sdk-go-v2/config v1.32.11/go.mod h1:twF11+6ps9aNRKEDimksp923o44w/Thk9+8YIlzWMmo= -github.com/aws/aws-sdk-go-v2/credentials v1.19.10 h1:EEhmEUFCE1Yhl7vDhNOI5OCL/iKMdkkYFTRpZXNw7m8= -github.com/aws/aws-sdk-go-v2/credentials v1.19.10/go.mod h1:RnnlFCAlxQCkN2Q379B67USkBMu1PipEEiibzYN5UTE= github.com/aws/aws-sdk-go-v2/credentials v1.19.11 h1:NdV8cwCcAXrCWyxArt58BrvZJ9pZ9Fhf9w6Uh5W3Uyc= github.com/aws/aws-sdk-go-v2/credentials v1.19.11/go.mod h1:30yY2zqkMPdrvxBqzI9xQCM+WrlrZKSOpSJEsylVU+8= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.18 h1:Ii4s+Sq3yDfaMLpjrJsqD6SmG/Wq/P5L/hw2qa78UAY= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.18/go.mod h1:6x81qnY++ovptLE6nWQeWrpXxbnlIex+4H4eYYGcqfc= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19 h1:INUvJxmhdEbVulJYHI061k4TVuS3jzzthNvjqvVvTKM= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.19/go.mod h1:FpZN2QISLdEBWkayloda+sZjVJL+e9Gl0k1SyTgcswU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 h1:F43zk1vemYIqPAwhjTjYIz0irU2EY7sOb/F5eJ3HuyM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18/go.mod h1:w1jdlZXrGKaJcNoL+Nnrj+k5wlpGXqnNrKoP22HvAug= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19 h1:/sECfyq2JTifMI2JPyZ4bdRN77zJmr6SrS1eL3augIA= github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.19/go.mod h1:dMf8A5oAqr9/oxOfLkC/c2LU/uMcALP0Rgn2BD5LWn0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 h1:xCeWVjj0ki0l3nruoyP2slHsGArMxeiiaoPN5QZH6YQ= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19 h1:AWeJMk33GTBf6J20XJe6qZoRSJo0WfUhsMdUKhoODXE= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.19/go.mod h1:+GWrYoaAsV7/4pNHpwh1kiNLXkKaSoppxQq9lbH8Ejw= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5 h1:clHU5fm//kWS1C2HgtgWxfQbFbx4b6rx+5jzhgX9HrI= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.5/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5/go.mod h1:AZLZf2fMaahW5s/wMRciu1sYbdsikT/UHwbUjOdEVTc= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6 h1:XAq62tBTJP/85lFD5oqOOe7YYgWxY9LvWq8plyDvDVg= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.6/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 h1:LTRCYFlnnKFlKsyIQxKhJuDuA3ZkrDQMRYm6rXiHlLY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18/go.mod h1:XhwkgGG6bHSd00nO/mexWTcTjgd6PjuvWQMqSn2UaEk= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19 h1:X1Tow7suZk9UCJHE1Iw9GMZJJl0dAnKXXP1NaSDHwmw= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.19/go.mod h1:/rARO8psX+4sfjUQXp5LLifjUt8DuATZ31WptNJTyQA= -github.com/aws/aws-sdk-go-v2/service/route53 v1.62.2 h1:zoD/SoiVQi8l8tuQn//VexrXS2yorg/+717JNA4Ble8= -github.com/aws/aws-sdk-go-v2/service/route53 v1.62.2/go.mod h1:Ll1DCasPTBFtHK5t/U5WIwGIyRuY3xY+x8/LmqIlqpM= github.com/aws/aws-sdk-go-v2/service/route53 v1.62.3 h1:JRPXnIr0WwFsSHBmuCvT/uh0Vgys+crvwkOghbJEqi8= github.com/aws/aws-sdk-go-v2/service/route53 v1.62.3/go.mod h1:DHddp7OO4bY467WVCqWBzk5+aEWn7vqYkap7UigJzGk= -github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.16 h1:k+TqYbG/WtL43wSCALuuPjLPEt//Ck/ZDKpCWrzhjUU= -github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.16/go.mod h1:yEr1gPPNbetOFxQV0J9ZLL5cR4U4ujEBgwk6p6oKYc8= github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.17 h1:Fw2SIR63jhfLpFZr6955zU3g9V8ouHC/pRpmmiHmIFM= github.com/aws/aws-sdk-go-v2/service/route53domains v1.34.17/go.mod h1:x9PRRtbCQ/gv1ziQPXFB7nQwQgVLQ+FSvPIkVAhRcYY= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.6 h1:MzORe+J94I+hYu2a6XmV5yC9huoTv8NRcCrUNedDypQ= -github.com/aws/aws-sdk-go-v2/service/signin v1.0.6/go.mod h1:hXzcHLARD7GeWnifd8j9RWqtfIgxj4/cAtIVIK7hg8g= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7 h1:Y2cAXlClHsXkkOvWZFXATr34b0hxxloeQu/pAZz2row= github.com/aws/aws-sdk-go-v2/service/signin v1.0.7/go.mod h1:idzZ7gmDeqeNrSPkdbtMp9qWMgcBwykA7P7Rzh5DXVU= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.11 h1:7oGD8KPfBOJGXiCoRKrrrQkbvCp8N++u36hrLMPey6o= -github.com/aws/aws-sdk-go-v2/service/sso v1.30.11/go.mod h1:0DO9B5EUJQlIDif+XJRWCljZRKsAFKh3gpFz7UnDtOo= github.com/aws/aws-sdk-go-v2/service/sso v1.30.12 h1:iSsvB9EtQ09YrsmIc44Heqlx5ByGErqhPK1ZQLppias= github.com/aws/aws-sdk-go-v2/service/sso v1.30.12/go.mod h1:fEWYKTRGoZNl8tZ77i61/ccwOMJdGxwOhWCkp6TXAr0= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15 h1:edCcNp9eGIUDUCrzoCu1jWAXLGFIizeqkdkKgRlJwWc= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15/go.mod h1:lyRQKED9xWfgkYC/wmmYfv7iVIM68Z5OQ88ZdcV1QbU= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16 h1:EnUdUqRP1CNzt2DkV67tJx6XDN4xlfBFm+bzeNOQVb0= github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.16/go.mod h1:Jic/xv0Rq/pFNCh3WwpH4BEqdbSAl+IyHro8LbibHD8= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.7 h1:NITQpgo9A5NrDZ57uOWj+abvXSb83BbyggcUBVksN7c= -github.com/aws/aws-sdk-go-v2/service/sts v1.41.7/go.mod h1:sks5UWBhEuWYDPdwlnRFn1w7xWdH29Jcpe+/PJQefEs= github.com/aws/aws-sdk-go-v2/service/sts v1.41.8 h1:XQTQTF75vnug2TXS8m7CVJfC2nniYPZnO1D4Np761Oo= github.com/aws/aws-sdk-go-v2/service/sts v1.41.8/go.mod h1:Xgx+PR1NUOjNmQY+tRMnouRp83JRM8pRMw/vCaVhPkI= -github.com/aws/smithy-go v1.24.1 h1:VbyeNfmYkWoxMVpGUAbQumkODcYmfMRfZ8yQiH30SK0= -github.com/aws/smithy-go v1.24.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0= github.com/aws/smithy-go v1.24.2 h1:FzA3bu/nt/vDvmnkg+R8Xl46gmzEDam6mZ1hzmwXFng= github.com/aws/smithy-go v1.24.2/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0= -github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6/go.mod h1:J29hk+f9lJrblVIfiJOtTFk+OblBawmib4uz/VdKzlg= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -181,12 +145,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deepmap/oapi-codegen v1.16.3 h1:GT9G86SbQtT1r8ZB+4Cybi9VGdu1P5ieNvNdEoCSbrA= github.com/deepmap/oapi-codegen v1.16.3/go.mod h1:JD6ErqeX0nYnhdciLc61Konj3NBASREMlkHOgHn8WAM= -github.com/digitalocean/godo v1.175.0 h1:tpfwJFkBzpePxvvFazOn69TXctdxuFlOs7DMVXsI7oU= -github.com/digitalocean/godo v1.175.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= github.com/digitalocean/godo v1.176.0 h1:P379vPO5TUre+bUHPEsdSAbl5vIrRRhP91tMIEPoWYU= github.com/digitalocean/godo v1.176.0/go.mod h1:xQsWpVCCbkDrWisHA72hPzPlnC+4W5w/McZY5ij9uvU= -github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY= -github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8= github.com/dnsimple/dnsimple-go/v8 v8.1.0 h1:U4ENaNCe5aUFHLiF7lj2NNpLPzFY3YIriu/UzrdfUbg= github.com/dnsimple/dnsimple-go/v8 v8.1.0/go.mod h1:61MdYHRL+p2TBBUVEkxo1n4iRF6s3R9fZcvQvyt5du8= github.com/earthboundkid/versioninfo/v2 v2.24.1 h1:SJTMHaoUx3GzjjnUO1QzP3ZXK6Ee/nbWyCm58eY3oUg= @@ -200,8 +160,6 @@ github.com/failsafe-go/failsafe-go v0.9.6 h1:vPSH2cry0Ee5cnR9wc9qshCDO6jdrMA9elB github.com/failsafe-go/failsafe-go v0.9.6/go.mod h1:IeRpglkcwzKagjDMh90ZhN2l4Ovt3+jemQBUbThag54= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/color v1.19.0 h1:Zp3PiM21/9Ld6FzSKyL5c/BULoe/ONr9KlbYVOfG8+w= github.com/fatih/color v1.19.0/go.mod h1:zNk67I0ZUT1bEGsSGyCZYZNrHuTkJJB+r6Q9VuMi0LE= github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= @@ -216,14 +174,10 @@ github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9 github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= -github.com/gin-contrib/sessions v1.0.4 h1:ha6CNdpYiTOK/hTp05miJLbpTSNfOnFg5Jm2kbcqy8U= -github.com/gin-contrib/sessions v1.0.4/go.mod h1:ccmkrb2z6iU2osiAHZG3x3J4suJK+OU27oqzlWOqQgs= github.com/gin-contrib/sessions v1.1.0 h1:00mhHfNEGF5sP2fwxa98aRqj1FOJdL6IkR86n2hOiBo= github.com/gin-contrib/sessions v1.1.0/go.mod h1:TyYZDIs6qCQg2SOoYPgMT9pAkmZceVNEJMcv5qbIy60= github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= -github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= -github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= github.com/go-gandi/go-gandi v0.7.0 h1:gsP33dUspsN1M+ZW9HEgHchK9HiaSkYnltO73RHhSZA= @@ -355,8 +309,6 @@ github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/ github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw= github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI= -github.com/happyDomain/dnscontrol/v4 v4.35.101 h1:9GL4OZ05AXOBUNjRdU72UUJGFAQz6OTCRVQw3WTQuo8= -github.com/happyDomain/dnscontrol/v4 v4.35.101/go.mod h1:R6j+Fv+etKriXI3runhnv42nPZPLcn81NNRt9gl1hTs= github.com/happyDomain/dnscontrol/v4 v4.36.100 h1:wrNaUV3Ihcqd9t9+AEIyBiyF1QNAeuFbCj+j8w0a/sM= github.com/happyDomain/dnscontrol/v4 v4.36.100/go.mod h1:7fgVrun0ecnT8fJhcFHQQXBg6yVIfEWRRQOj27hxm+s= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= @@ -434,10 +386,12 @@ github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1 github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lib/pq v1.11.2 h1:x6gxUeu39V0BHZiugWe8LXZYZ+Utk7hSJGThs8sdzfs= -github.com/lib/pq v1.11.2/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= github.com/lib/pq v1.12.0 h1:mC1zeiNamwKBecjHarAr26c/+d8V5w/u4J0I/yASbJo= github.com/lib/pq v1.12.0/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA= +github.com/libdns/ionos v1.2.0 h1:FQ2xQTBfsjc7aMArRBBCs9l48Squt76GHXbxDsqOKgw= +github.com/libdns/ionos v1.2.0/go.mod h1:g/JYno/+VXdujTGPBDMDeCfeLF0PJyJynsCrFu+2EFQ= +github.com/libdns/libdns v1.1.1 h1:wPrHrXILoSHKWJKGd0EiAVmiJbFShguILTg9leS/P/U= +github.com/libdns/libdns v1.1.1/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= github.com/luadns/luadns-go v0.3.0 h1:mN2yhFv/LnGvPw/HmvYUhXe+lc95oXUqjlYVeJeOJng= github.com/luadns/luadns-go v0.3.0/go.mod h1:DmPXbrGMpynq1YNDpvgww3NP5Zf4wXM5raAbGrp5L+8= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= @@ -494,8 +448,6 @@ github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:Ff github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= github.com/oracle/nosql-go-sdk v1.4.7 h1:dqVBSMulObDj0JHm1mAncTHrQg8wIiQJNC0JRNKPACg= github.com/oracle/nosql-go-sdk v1.4.7/go.mod h1:xgJE9wxADDbk7vR4FGA4NOt4RNAaIsQOj4sCATmCVXM= -github.com/oracle/oci-go-sdk/v65 v65.108.3 h1:n2G4QwGoRNhtLE8r24/+Ny+WpEMdc9ggGpnPvVYM2Yk= -github.com/oracle/oci-go-sdk/v65 v65.108.3/go.mod h1:8ZzvzuEG/cFLFZhxg/Mg1w19KqyXBKO3c17QIc5PkGs= github.com/oracle/oci-go-sdk/v65 v65.109.0 h1:EsbFVvcV+uid9SoQnFQbTKS6FgqsM9NtoKmUIovKsbk= github.com/oracle/oci-go-sdk/v65 v65.109.0/go.mod h1:8ZzvzuEG/cFLFZhxg/Mg1w19KqyXBKO3c17QIc5PkGs= github.com/ovh/go-ovh v1.9.0 h1:6K8VoL3BYjVV3In9tPJUdT7qMx9h0GExN9EXx1r2kKE= @@ -522,8 +474,6 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= -github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= -github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= github.com/prometheus/procfs v0.20.0 h1:AA7aCvjxwAquZAlonN7888f2u4IN8WVeFgBi4k82M4Q= github.com/prometheus/procfs v0.20.0/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= github.com/qdm12/reprint v0.0.0-20200326205758-722754a53494 h1:wSmWgpuccqS2IOfmYrbRiUgv+g37W5suLLLxwwniTSc= @@ -644,14 +594,6 @@ github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 h1:BHyfKlQyqbsFN5p3Ifn github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE= -github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yuin/goldmark v1.7.17 h1:p36OVWwRb246iHxA/U4p8OPEpOTESm4n+g+8t0EE5uA= -github.com/yuin/goldmark v1.7.17/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yuin/goldmark v1.8.0 h1:mxoLcGPka9ac7V4GfJ3X/bu4KYxT64J61l/uHDFET3M= -github.com/yuin/goldmark v1.8.0/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yuin/goldmark v1.8.1 h1:id2TeYXe5FpqwLco0Pso4cNM5Z6Okt4g7kDw9QBMhTA= -github.com/yuin/goldmark v1.8.1/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= github.com/yuin/goldmark v1.8.2 h1:kEGpgqJXdgbkhcOgBxkC0X0PmoPG1ZyoZ117rDVp4zE= github.com/yuin/goldmark v1.8.2/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo= @@ -698,8 +640,6 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= -golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4= golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -746,13 +686,9 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= -golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -765,8 +701,6 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -796,8 +730,6 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= -golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo= golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= @@ -821,8 +753,6 @@ golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= -golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI= @@ -855,8 +785,6 @@ gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= -google.golang.org/api v0.268.0 h1:hgA3aS4lt9rpF5RCCkX0Q2l7DvHgvlb53y4T4u6iKkA= -google.golang.org/api v0.268.0/go.mod h1:HXMyMH496wz+dAJwD/GkAPLd3ZL33Kh0zEG32eNvy9w= google.golang.org/api v0.269.0 h1:qDrTOxKUQ/P0MveH6a7vZ+DNHxJQjtGm/uvdbdGXCQg= google.golang.org/api v0.269.0/go.mod h1:N8Wpcu23Tlccl0zSHEkcAZQKDLdquxK+l9r2LkwAauE= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= diff --git a/internal/adapters/libdns-providers.go b/internal/adapters/libdns-providers.go new file mode 100644 index 00000000..8311273c --- /dev/null +++ b/internal/adapters/libdns-providers.go @@ -0,0 +1,317 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2025 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package adapter + +import ( + "context" + "fmt" + "strings" + + "github.com/libdns/libdns" + "github.com/miekg/dns" + + "git.happydns.org/happyDomain/model" +) + +// LibdnsConfigAdapter is an interface that provider configurations must implement +// to work with libdns. It allows retrieving the underlying libdns provider instance. +type LibdnsConfigAdapter interface { + // LibdnsProvider returns the underlying libdns provider instance. + // The returned value must implement at least libdns.RecordGetter. + LibdnsProvider() any +} + +// RegisterLibdnsProviderAdapter registers a DNS provider that uses libdns as its backend. +// It automatically populates the provider's capabilities by checking which libdns +// interfaces the provider implements. +func RegisterLibdnsProviderAdapter(creator happydns.ProviderCreatorFunc, infos happydns.ProviderInfos, registerFunc happydns.RegisterProviderFunc) { + prvInstance := creator().(LibdnsConfigAdapter) + infos.Capabilities = append(infos.Capabilities, GetLibdnsProviderCapabilities(prvInstance)...) + + registerFunc(creator, infos) +} + +// GetLibdnsProviderCapabilities checks which libdns interfaces the provider implements +// and returns the corresponding capability strings. Since libdns providers are type-agnostic, +// common record types are declared for all providers. +func GetLibdnsProviderCapabilities(prvd LibdnsConfigAdapter) (caps []string) { + p := prvd.LibdnsProvider() + + if _, ok := p.(libdns.ZoneLister); ok { + caps = append(caps, "ListDomains") + } + + // libdns providers are type-agnostic, so declare support for common RR types. + for _, v := range []uint16{ + dns.TypeA, dns.TypeAAAA, dns.TypeCNAME, dns.TypeMX, + dns.TypeNS, dns.TypeTXT, dns.TypeSRV, dns.TypeCAA, + dns.TypePTR, + } { + caps = append(caps, fmt.Sprintf("rr-%d-%s", v, dns.TypeToString[v])) + } + + return +} + +// NewLibdnsProviderAdapter creates a new provider actuator instance from a libdns configuration. +// It discovers the provider's capabilities by checking which libdns interfaces it implements. +// The provider must implement at least libdns.RecordGetter. +func NewLibdnsProviderAdapter(configAdapter LibdnsConfigAdapter) (happydns.ProviderActuator, error) { + p := configAdapter.LibdnsProvider() + + adapter := &LibdnsAdapterNSProvider{ + provider: p, + } + + if g, ok := p.(libdns.RecordGetter); ok { + adapter.getter = g + } else { + return nil, fmt.Errorf("libdns provider must implement RecordGetter") + } + + if s, ok := p.(libdns.RecordSetter); ok { + adapter.setter = s + } + if a, ok := p.(libdns.RecordAppender); ok { + adapter.appender = a + } + if d, ok := p.(libdns.RecordDeleter); ok { + adapter.deleter = d + } + if z, ok := p.(libdns.ZoneLister); ok { + adapter.zoneLister = z + } + + return adapter, nil +} + +// LibdnsAdapterNSProvider wraps a libdns provider to implement the happyDomain ProviderActuator interface. +type LibdnsAdapterNSProvider struct { + provider any + getter libdns.RecordGetter + setter libdns.RecordSetter + appender libdns.RecordAppender + deleter libdns.RecordDeleter + zoneLister libdns.ZoneLister +} + +// normalizeZone ensures the zone name has a trailing dot (FQDN format expected by libdns). +func normalizeZone(domain string) string { + zone := strings.TrimSuffix(domain, ".") + return zone + "." +} + +// CanListZones checks if the provider supports listing zones. +func (p *LibdnsAdapterNSProvider) CanListZones() bool { + return p.zoneLister != nil +} + +// CanCreateDomain returns false since libdns has no zone creation interface. +func (p *LibdnsAdapterNSProvider) CanCreateDomain() bool { + return false +} + +// CreateDomain is not supported by libdns providers. +func (p *LibdnsAdapterNSProvider) CreateDomain(fqdn string) error { + return fmt.Errorf("libdns provider does not support domain creation") +} + +// ListZones retrieves the list of all zones managed by this provider. +func (p *LibdnsAdapterNSProvider) ListZones() ([]string, error) { + if p.zoneLister == nil { + return nil, fmt.Errorf("libdns provider does not support zone listing") + } + + zones, err := p.zoneLister.ListZones(context.TODO()) + if err != nil { + return nil, err + } + + result := make([]string, len(zones)) + for i, z := range zones { + result[i] = z.Name + } + return result, nil +} + +// GetZoneRecords retrieves all DNS records for the specified domain from the provider. +func (p *LibdnsAdapterNSProvider) GetZoneRecords(domain string) ([]happydns.Record, error) { + zone := normalizeZone(domain) + + recs, err := p.getter.GetRecords(context.TODO(), zone) + if err != nil { + return nil, err + } + + return libdnsRecordsToHappyDNS(recs, zone) +} + +// GetZoneCorrections compares desired records against the current zone state and returns +// the changes needed to synchronize them. It uses the DNSControl diff engine to compute +// the diff, then creates correction functions that call the libdns provider's API. +func (p *LibdnsAdapterNSProvider) GetZoneCorrections(domain string, wantedRecords []happydns.Record) ([]*happydns.Correction, int, error) { + zone := normalizeZone(domain) + + // Step 1: Fetch current records from the provider. + currentLibdnsRecs, err := p.getter.GetRecords(context.TODO(), zone) + if err != nil { + return nil, 0, fmt.Errorf("unable to get current zone records: %w", err) + } + + currentRecords, err := libdnsRecordsToHappyDNS(currentLibdnsRecs, zone) + if err != nil { + return nil, 0, fmt.Errorf("unable to convert current zone records: %w", err) + } + + // Step 2: Compute diff using existing DNSControl diff engine. + diffs, nbDiffs, err := DNSControlDiffByRecord(currentRecords, wantedRecords, domain) + if err != nil { + return nil, nbDiffs, fmt.Errorf("unable to compute zone diff: %w", err) + } + + // Build a lookup from happydns Record string → original libdns records (with ProviderData). + // This ensures delete operations use the provider's record IDs. + libdnsRecordsByKey := make(map[string][]libdns.Record) + for _, rec := range currentLibdnsRecs { + rr := rec.RR() + key := fmt.Sprintf("%s\t%s\t%s", rr.Name, rr.Type, rr.Data) + libdnsRecordsByKey[key] = append(libdnsRecordsByKey[key], rec) + } + + // Step 3: Create corrections with executable F closures. + corrections := make([]*happydns.Correction, len(diffs)) + for i, diff := range diffs { + corrections[i] = &happydns.Correction{ + Id: diff.Id, + Msg: diff.Msg, + Kind: diff.Kind, + OldRecords: diff.OldRecords, + NewRecords: diff.NewRecords, + } + + corrections[i].F = p.makeCorrectionFunc(zone, diff, libdnsRecordsByKey) + } + + return corrections, nbDiffs, nil +} + +// makeCorrectionFunc creates an executable function for a single correction. +func (p *LibdnsAdapterNSProvider) makeCorrectionFunc( + zone string, + diff *happydns.Correction, + libdnsRecordsByKey map[string][]libdns.Record, +) func() error { + kind := diff.Kind + + // Resolve old records to their original libdns Records (with ProviderData). + oldRecs := p.resolveOriginalRecords(diff.OldRecords, zone, libdnsRecordsByKey) + newRecs := happyDNSRecordsToLibdnsRecords(diff.NewRecords, zone) + + // If we have both appender and deleter, use granular operations. + if p.appender != nil && p.deleter != nil { + return func() error { + ctx := context.TODO() + switch kind { + case happydns.CorrectionKindAddition: + _, err := p.appender.AppendRecords(ctx, zone, newRecs) + return err + case happydns.CorrectionKindDeletion: + _, err := p.deleter.DeleteRecords(ctx, zone, oldRecs) + return err + case happydns.CorrectionKindUpdate: + if _, err := p.deleter.DeleteRecords(ctx, zone, oldRecs); err != nil { + return fmt.Errorf("delete phase of update: %w", err) + } + _, err := p.appender.AppendRecords(ctx, zone, newRecs) + if err != nil { + return fmt.Errorf("append phase of update: %w", err) + } + return nil + } + return nil + } + } + + // Fallback: use SetRecords if available. + if p.setter != nil { + return func() error { + ctx := context.TODO() + switch kind { + case happydns.CorrectionKindAddition: + // SetRecords with the new records will add them to the zone + // for their (name, type) pair. + _, err := p.setter.SetRecords(ctx, zone, newRecs) + return err + case happydns.CorrectionKindDeletion: + // To delete, we need to set the (name, type) pair to empty. + // DeleteRecords would be better, but we only have SetRecords. + // Use DeleteRecords-style wildcard via setter: set with empty set + // is not directly possible with SetRecords semantics. + // Fall through to delete if we have deleter, otherwise error. + return fmt.Errorf("cannot delete records: provider only supports SetRecords, not DeleteRecords") + case happydns.CorrectionKindUpdate: + // SetRecords replaces all records for the (name, type) pair. + _, err := p.setter.SetRecords(ctx, zone, newRecs) + return err + } + return nil + } + } + + return func() error { + return fmt.Errorf("libdns provider does not support record modification") + } +} + +// resolveOriginalRecords tries to find the original libdns Records (with ProviderData) +// for the given happydns Records. This ensures that delete operations use the provider's +// record identifiers. +func (p *LibdnsAdapterNSProvider) resolveOriginalRecords( + records []happydns.Record, + zone string, + libdnsRecordsByKey map[string][]libdns.Record, +) []libdns.Record { + result := make([]libdns.Record, 0, len(records)) + for _, rec := range records { + rr := happyDNSRecordToLibdnsRR(rec, zone) + key := fmt.Sprintf("%s\t%s\t%s", rr.Name, rr.Type, rr.Data) + + if originals, ok := libdnsRecordsByKey[key]; ok && len(originals) > 0 { + // Use the original record and consume it from the map. + result = append(result, originals[0]) + libdnsRecordsByKey[key] = originals[1:] + } else { + // Fallback: use the converted RR (without ProviderData). + result = append(result, rr) + } + } + return result +} + +// happyDNSRecordsToLibdnsRecords converts happydns Records to libdns Records (the interface). +func happyDNSRecordsToLibdnsRecords(rrs []happydns.Record, zone string) []libdns.Record { + result := make([]libdns.Record, len(rrs)) + for i, rr := range rrs { + result[i] = happyDNSRecordToLibdnsRR(rr, zone) + } + return result +} diff --git a/internal/adapters/libdns-providers_test.go b/internal/adapters/libdns-providers_test.go new file mode 100644 index 00000000..a018b1e1 --- /dev/null +++ b/internal/adapters/libdns-providers_test.go @@ -0,0 +1,331 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2025 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package adapter + +import ( + "context" + "net/netip" + "testing" + "time" + + "github.com/libdns/libdns" + "github.com/miekg/dns" + + "git.happydns.org/happyDomain/model" +) + +// mockLibdnsProvider implements RecordGetter, RecordAppender, RecordDeleter for testing. +type mockLibdnsProvider struct { + records []libdns.Record + appended []libdns.Record + deleted []libdns.Record + zones []libdns.Zone + appendErr error + deleteErr error + getErr error + listZoneErr error +} + +func (m *mockLibdnsProvider) GetRecords(_ context.Context, _ string) ([]libdns.Record, error) { + if m.getErr != nil { + return nil, m.getErr + } + return m.records, nil +} + +func (m *mockLibdnsProvider) AppendRecords(_ context.Context, _ string, recs []libdns.Record) ([]libdns.Record, error) { + if m.appendErr != nil { + return nil, m.appendErr + } + m.appended = append(m.appended, recs...) + return recs, nil +} + +func (m *mockLibdnsProvider) DeleteRecords(_ context.Context, _ string, recs []libdns.Record) ([]libdns.Record, error) { + if m.deleteErr != nil { + return nil, m.deleteErr + } + m.deleted = append(m.deleted, recs...) + return recs, nil +} + +func (m *mockLibdnsProvider) ListZones(_ context.Context) ([]libdns.Zone, error) { + if m.listZoneErr != nil { + return nil, m.listZoneErr + } + return m.zones, nil +} + +// mockLibdnsConfig implements LibdnsConfigAdapter. +type mockLibdnsConfig struct { + provider any +} + +func (m *mockLibdnsConfig) LibdnsProvider() any { + return m.provider +} + +func (m *mockLibdnsConfig) InstantiateProvider() (happydns.ProviderActuator, error) { + return NewLibdnsProviderAdapter(m) +} + +func TestNewLibdnsProviderAdapter(t *testing.T) { + mock := &mockLibdnsProvider{} + config := &mockLibdnsConfig{provider: mock} + + adapter, err := NewLibdnsProviderAdapter(config) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if !adapter.CanListZones() { + t.Error("expected CanListZones to be true") + } + if adapter.CanCreateDomain() { + t.Error("expected CanCreateDomain to be false") + } +} + +func TestLibdnsAdapter_GetZoneRecords(t *testing.T) { + mock := &mockLibdnsProvider{ + records: []libdns.Record{ + libdns.Address{ + Name: "www", + TTL: 300 * time.Second, + IP: netip.MustParseAddr("192.0.2.1"), + }, + libdns.TXT{ + Name: "@", + TTL: 300 * time.Second, + Text: "v=spf1 ~all", + }, + }, + } + + config := &mockLibdnsConfig{provider: mock} + adapter, err := NewLibdnsProviderAdapter(config) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + records, err := adapter.GetZoneRecords("example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(records) != 2 { + t.Fatalf("expected 2 records, got %d", len(records)) + } + + // Check A record + if records[0].Header().Rrtype != dns.TypeA { + t.Errorf("expected first record to be A, got %s", dns.TypeToString[records[0].Header().Rrtype]) + } + + // Check TXT record + txt, ok := records[1].(*happydns.TXT) + if !ok { + t.Fatalf("expected second record to be *happydns.TXT, got %T", records[1]) + } + if txt.Txt != "v=spf1 ~all" { + t.Errorf("expected TXT 'v=spf1 ~all', got %q", txt.Txt) + } +} + +func TestLibdnsAdapter_ListZones(t *testing.T) { + mock := &mockLibdnsProvider{ + zones: []libdns.Zone{ + {Name: "example.com."}, + {Name: "example.org."}, + }, + } + + config := &mockLibdnsConfig{provider: mock} + adapter, err := NewLibdnsProviderAdapter(config) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + zones, err := adapter.ListZones() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(zones) != 2 { + t.Fatalf("expected 2 zones, got %d", len(zones)) + } + if zones[0] != "example.com." { + t.Errorf("expected first zone 'example.com.', got %q", zones[0]) + } +} + +func TestLibdnsAdapter_GetZoneCorrections_NoChanges(t *testing.T) { + records := []libdns.Record{ + libdns.Address{ + Name: "www", + TTL: 300 * time.Second, + IP: netip.MustParseAddr("192.0.2.1"), + }, + } + + mock := &mockLibdnsProvider{records: records} + config := &mockLibdnsConfig{provider: mock} + adapter, err := NewLibdnsProviderAdapter(config) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + // Pass the same records as wanted + aRR, _ := dns.NewRR("www.example.com. 300 IN A 192.0.2.1") + corrections, _, err := adapter.GetZoneCorrections("example.com.", []happydns.Record{aRR}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(corrections) != 0 { + t.Errorf("expected 0 corrections, got %d", len(corrections)) + } +} + +func TestLibdnsAdapter_GetZoneCorrections_Addition(t *testing.T) { + // Provider has one A record, we want to add a CNAME. + mock := &mockLibdnsProvider{ + records: []libdns.Record{ + libdns.Address{ + Name: "www", + TTL: 300 * time.Second, + IP: netip.MustParseAddr("192.0.2.1"), + }, + }, + } + + config := &mockLibdnsConfig{provider: mock} + adapter, err := NewLibdnsProviderAdapter(config) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + aRR, _ := dns.NewRR("www.example.com. 300 IN A 192.0.2.1") + cnameRR, _ := dns.NewRR("blog.example.com. 300 IN CNAME www.example.com.") + corrections, _, err := adapter.GetZoneCorrections("example.com.", []happydns.Record{aRR, cnameRR}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(corrections) == 0 { + t.Fatal("expected at least 1 correction") + } + + // Execute the correction + for _, c := range corrections { + if c.Kind == happydns.CorrectionKindAddition { + if err := c.F(); err != nil { + t.Fatalf("unexpected error executing correction: %v", err) + } + } + } + + if len(mock.appended) == 0 { + t.Error("expected records to be appended") + } +} + +func TestLibdnsAdapter_GetZoneCorrections_Deletion(t *testing.T) { + // Provider has two records, we want only one. + mock := &mockLibdnsProvider{ + records: []libdns.Record{ + libdns.Address{ + Name: "www", + TTL: 300 * time.Second, + IP: netip.MustParseAddr("192.0.2.1"), + }, + libdns.Address{ + Name: "old", + TTL: 300 * time.Second, + IP: netip.MustParseAddr("192.0.2.2"), + }, + }, + } + + config := &mockLibdnsConfig{provider: mock} + adapter, err := NewLibdnsProviderAdapter(config) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + aRR, _ := dns.NewRR("www.example.com. 300 IN A 192.0.2.1") + corrections, _, err := adapter.GetZoneCorrections("example.com.", []happydns.Record{aRR}) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if len(corrections) == 0 { + t.Fatal("expected at least 1 correction") + } + + // Execute the deletion correction + for _, c := range corrections { + if c.Kind == happydns.CorrectionKindDeletion { + if err := c.F(); err != nil { + t.Fatalf("unexpected error executing correction: %v", err) + } + } + } + + if len(mock.deleted) == 0 { + t.Error("expected records to be deleted") + } +} + +func TestGetLibdnsProviderCapabilities(t *testing.T) { + mock := &mockLibdnsProvider{} + config := &mockLibdnsConfig{provider: mock} + + caps := GetLibdnsProviderCapabilities(config) + + // Should include ListDomains since mock implements ZoneLister + found := false + for _, c := range caps { + if c == "ListDomains" { + found = true + break + } + } + if !found { + t.Error("expected ListDomains capability") + } + + // Should include common RR types + expectedTypes := []string{"rr-1-A", "rr-28-AAAA", "rr-5-CNAME", "rr-15-MX", "rr-16-TXT"} + for _, expected := range expectedTypes { + found = false + for _, c := range caps { + if c == expected { + found = true + break + } + } + if !found { + t.Errorf("expected capability %s", expected) + } + } +} diff --git a/internal/adapters/libdns-records.go b/internal/adapters/libdns-records.go new file mode 100644 index 00000000..8f15bb33 --- /dev/null +++ b/internal/adapters/libdns-records.go @@ -0,0 +1,188 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2025 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package adapter + +import ( + "fmt" + "strings" + "time" + + "github.com/StackExchange/dnscontrol/v4/pkg/txtutil" + "github.com/libdns/libdns" + "github.com/miekg/dns" + + "git.happydns.org/happyDomain/internal/helpers" + "git.happydns.org/happyDomain/model" +) + +// libdnsToHappyDNSRecord converts a libdns Record to a happydns Record. +// The zone parameter should be the FQDN with trailing dot (e.g. "example.com."). +// For TXT records, it produces happydns.TXT directly (single concatenated string). +func libdnsToHappyDNSRecord(rec libdns.Record, zone string) (happydns.Record, error) { + rr := rec.RR() + + fqdn := libdns.AbsoluteName(rr.Name, zone) + if !strings.HasSuffix(fqdn, ".") { + fqdn += "." + } + + ttlSec := uint32(rr.TTL.Seconds()) + + // For TXT records, the libdns Data field may be either raw text or + // RFC1035 presentation-format with quotes and escaping (depends on provider). + // Use txtutil.ParseQuoted to decode presentation-format data. + if rr.Type == "TXT" { + return &happydns.TXT{ + Hdr: dns.RR_Header{ + Name: fqdn, + Rrtype: dns.TypeTXT, + Class: dns.ClassINET, + Ttl: ttlSec, + }, + Txt: decodeTXTData(rr.Data), + }, nil + } + + // For SPF records (if any provider returns them) + if rr.Type == "SPF" { + return &happydns.SPF{ + Hdr: dns.RR_Header{ + Name: fqdn, + Rrtype: dns.TypeSPF, + Class: dns.ClassINET, + Ttl: ttlSec, + }, + Txt: decodeTXTData(rr.Data), + }, nil + } + + // For all other record types, build a zone-file line and parse it. + line := fmt.Sprintf("%s %d IN %s %s", fqdn, ttlSec, rr.Type, rr.Data) + return helpers.ParseRecord(line, zone) +} + +// happyDNSRecordToLibdnsRR converts a happydns Record to a libdns RR. +// The zone parameter should be the FQDN with trailing dot (e.g. "example.com."). +func happyDNSRecordToLibdnsRR(record happydns.Record, zone string) libdns.RR { + hdr := record.Header() + + name := libdns.RelativeName(hdr.Name, zone) + typStr := dns.TypeToString[hdr.Rrtype] + ttl := time.Duration(hdr.Ttl) * time.Second + + // For happydns.TXT / happydns.SPF, extract the raw text directly. + if txt, ok := record.(*happydns.TXT); ok { + return libdns.RR{ + Name: name, + TTL: ttl, + Type: typStr, + Data: txt.Txt, + } + } + if spf, ok := record.(*happydns.SPF); ok { + return libdns.RR{ + Name: name, + TTL: ttl, + Type: typStr, + Data: spf.Txt, + } + } + + // For ConvertibleRecord types, convert to dns.RR first. + var dnsRR dns.RR + if cr, ok := record.(happydns.ConvertibleRecord); ok { + dnsRR = cr.ToRR() + } else if rr, ok := record.(dns.RR); ok { + dnsRR = rr + } else { + // Fallback: try to extract rdata from string representation. + return libdns.RR{ + Name: name, + TTL: ttl, + Type: typStr, + Data: extractRdata(record.String(), typStr), + } + } + + return libdns.RR{ + Name: name, + TTL: ttl, + Type: typStr, + Data: extractRdata(dnsRR.String(), typStr), + } +} + +// decodeTXTData decodes TXT record data that may be in RFC1035 presentation +// format (quoted, with escaping) or raw text. Some libdns providers (e.g. +// PowerDNS) return quoted data like `"value"`, while others (e.g. libdns.TXT) +// return raw unquoted text. ParseQuoted handles quoted data correctly but +// treats unquoted spaces as separators, so we only use it when quotes are present. +func decodeTXTData(s string) string { + if strings.ContainsRune(s, '"') { + if decoded, err := txtutil.ParseQuoted(s); err == nil { + return decoded + } + } + return s +} + +// extractRdata extracts the rdata portion from a miekg/dns RR string. +// The format is: "name.\t\tIN\t\t" +func extractRdata(rrString string, rrType string) string { + // miekg/dns uses tab-separated fields + marker := "\tIN\t" + rrType + "\t" + idx := strings.Index(rrString, marker) + if idx != -1 { + return rrString[idx+len(marker):] + } + + // Fallback: try space-separated (shouldn't happen with miekg/dns) + marker = " IN " + rrType + " " + idx = strings.Index(rrString, marker) + if idx != -1 { + return rrString[idx+len(marker):] + } + + return "" +} + +// libdnsRecordsToHappyDNS converts a slice of libdns Records to happydns Records. +func libdnsRecordsToHappyDNS(recs []libdns.Record, zone string) ([]happydns.Record, error) { + result := make([]happydns.Record, 0, len(recs)) + for _, rec := range recs { + hdr, err := libdnsToHappyDNSRecord(rec, zone) + if err != nil { + return nil, fmt.Errorf("converting libdns record %v: %w", rec.RR(), err) + } + result = append(result, hdr) + } + return result, nil +} + +// happyDNSRecordsToLibdns converts a slice of happydns Records to libdns RR values. +func happyDNSRecordsToLibdns(rrs []happydns.Record, zone string) []libdns.RR { + result := make([]libdns.RR, len(rrs)) + for i, rr := range rrs { + result[i] = happyDNSRecordToLibdnsRR(rr, zone) + } + return result +} diff --git a/internal/adapters/libdns-records_test.go b/internal/adapters/libdns-records_test.go new file mode 100644 index 00000000..ae6d72fa --- /dev/null +++ b/internal/adapters/libdns-records_test.go @@ -0,0 +1,343 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2025 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package adapter + +import ( + "net/netip" + "testing" + "time" + + "github.com/libdns/libdns" + "github.com/miekg/dns" + + "git.happydns.org/happyDomain/model" +) + +func TestLibdnsToHappyDNS_A(t *testing.T) { + rec := libdns.Address{} + rec.Name = "www" + rec.TTL = 300 * time.Second + rec.IP = mustParseAddr("192.0.2.1") + + result, err := libdnsToHappyDNSRecord(rec, "example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if result.Header().Name != "www.example.com." { + t.Errorf("expected name www.example.com., got %s", result.Header().Name) + } + if result.Header().Rrtype != dns.TypeA { + t.Errorf("expected type A, got %s", dns.TypeToString[result.Header().Rrtype]) + } + if result.Header().Ttl != 300 { + t.Errorf("expected TTL 300, got %d", result.Header().Ttl) + } +} + +func TestLibdnsToHappyDNS_AAAA(t *testing.T) { + rec := libdns.Address{} + rec.Name = "@" + rec.TTL = 600 * time.Second + rec.IP = mustParseAddr("2001:db8::1") + + result, err := libdnsToHappyDNSRecord(rec, "example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if result.Header().Name != "example.com." { + t.Errorf("expected name example.com., got %s", result.Header().Name) + } + if result.Header().Rrtype != dns.TypeAAAA { + t.Errorf("expected type AAAA, got %s", dns.TypeToString[result.Header().Rrtype]) + } +} + +func TestLibdnsToHappyDNS_TXT(t *testing.T) { + rec := libdns.TXT{ + Name: "@", + TTL: 300 * time.Second, + Text: "v=spf1 include:_spf.google.com ~all", + } + + result, err := libdnsToHappyDNSRecord(rec, "example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + txt, ok := result.(*happydns.TXT) + if !ok { + t.Fatalf("expected *happydns.TXT, got %T", result) + } + + if txt.Txt != "v=spf1 include:_spf.google.com ~all" { + t.Errorf("expected TXT value 'v=spf1 include:_spf.google.com ~all', got %q", txt.Txt) + } + if txt.Hdr.Name != "example.com." { + t.Errorf("expected name example.com., got %s", txt.Hdr.Name) + } +} + +func TestLibdnsToHappyDNS_CNAME(t *testing.T) { + rec := libdns.CNAME{ + Name: "www", + TTL: 3600 * time.Second, + Target: "example.com.", + } + + result, err := libdnsToHappyDNSRecord(rec, "example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if result.Header().Rrtype != dns.TypeCNAME { + t.Errorf("expected type CNAME, got %s", dns.TypeToString[result.Header().Rrtype]) + } +} + +func TestLibdnsToHappyDNS_MX(t *testing.T) { + rec := libdns.MX{ + Name: "@", + TTL: 3600 * time.Second, + Preference: 10, + Target: "mail.example.com.", + } + + result, err := libdnsToHappyDNSRecord(rec, "example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if result.Header().Rrtype != dns.TypeMX { + t.Errorf("expected type MX, got %s", dns.TypeToString[result.Header().Rrtype]) + } +} + +func TestHappyDNSToLibdns_A(t *testing.T) { + rr, _ := dns.NewRR("www.example.com. 300 IN A 192.0.2.1") + + result := happyDNSRecordToLibdnsRR(rr, "example.com.") + + if result.Name != "www" { + t.Errorf("expected name 'www', got %q", result.Name) + } + if result.Type != "A" { + t.Errorf("expected type A, got %s", result.Type) + } + if result.TTL != 300*time.Second { + t.Errorf("expected TTL 300s, got %v", result.TTL) + } + if result.Data != "192.0.2.1" { + t.Errorf("expected data '192.0.2.1', got %q", result.Data) + } +} + +func TestHappyDNSToLibdns_TXT(t *testing.T) { + txt := &happydns.TXT{ + Hdr: dns.RR_Header{ + Name: "example.com.", + Rrtype: dns.TypeTXT, + Class: dns.ClassINET, + Ttl: 300, + }, + Txt: "v=spf1 include:_spf.google.com ~all", + } + + result := happyDNSRecordToLibdnsRR(txt, "example.com.") + + if result.Name != "@" { + t.Errorf("expected name '@', got %q", result.Name) + } + if result.Type != "TXT" { + t.Errorf("expected type TXT, got %s", result.Type) + } + if result.Data != "v=spf1 include:_spf.google.com ~all" { + t.Errorf("expected data 'v=spf1 include:_spf.google.com ~all', got %q", result.Data) + } +} + +func TestHappyDNSToLibdns_Apex(t *testing.T) { + rr, _ := dns.NewRR("example.com. 300 IN A 192.0.2.1") + + result := happyDNSRecordToLibdnsRR(rr, "example.com.") + + if result.Name != "@" { + t.Errorf("expected name '@', got %q", result.Name) + } +} + +func TestRoundTrip_A(t *testing.T) { + original := libdns.Address{} + original.Name = "www" + original.TTL = 300 * time.Second + original.IP = mustParseAddr("192.0.2.1") + + zone := "example.com." + + hdRecord, err := libdnsToHappyDNSRecord(original, zone) + if err != nil { + t.Fatalf("unexpected error converting to happydns: %v", err) + } + + roundtripped := happyDNSRecordToLibdnsRR(hdRecord, zone) + + origRR := original.RR() + if roundtripped.Name != origRR.Name { + t.Errorf("name mismatch: got %q, want %q", roundtripped.Name, origRR.Name) + } + if roundtripped.Type != origRR.Type { + t.Errorf("type mismatch: got %q, want %q", roundtripped.Type, origRR.Type) + } + if roundtripped.TTL != origRR.TTL { + t.Errorf("TTL mismatch: got %v, want %v", roundtripped.TTL, origRR.TTL) + } + if roundtripped.Data != origRR.Data { + t.Errorf("data mismatch: got %q, want %q", roundtripped.Data, origRR.Data) + } +} + +func TestRoundTrip_TXT(t *testing.T) { + original := libdns.TXT{ + Name: "test", + TTL: 600 * time.Second, + Text: "hello world with spaces and special chars: @#$%", + } + + zone := "example.com." + + hdRecord, err := libdnsToHappyDNSRecord(original, zone) + if err != nil { + t.Fatalf("unexpected error converting to happydns: %v", err) + } + + txt, ok := hdRecord.(*happydns.TXT) + if !ok { + t.Fatalf("expected *happydns.TXT, got %T", hdRecord) + } + if txt.Txt != original.Text { + t.Errorf("TXT text mismatch after first conversion: got %q, want %q", txt.Txt, original.Text) + } + + roundtripped := happyDNSRecordToLibdnsRR(hdRecord, zone) + + origRR := original.RR() + if roundtripped.Name != origRR.Name { + t.Errorf("name mismatch: got %q, want %q", roundtripped.Name, origRR.Name) + } + if roundtripped.Type != origRR.Type { + t.Errorf("type mismatch: got %q, want %q", roundtripped.Type, origRR.Type) + } + if roundtripped.Data != origRR.Data { + t.Errorf("data mismatch: got %q, want %q", roundtripped.Data, origRR.Data) + } +} + +func TestLibdnsToHappyDNS_TXT_QuotedData(t *testing.T) { + // Some libdns providers (e.g. PowerDNS) return TXT data in RFC1035 presentation format. + tests := []struct { + name string + data string + expected string + }{ + {"simple quoted", `"some-acme-challenge-value"`, "some-acme-challenge-value"}, + {"escaped quote", `"foo\"bar"`, `foo"bar`}, + {"escaped backslash", `"foo\\bar"`, `foo\bar`}, + {"multi-chunk", `"chunk1" "chunk2"`, "chunk1chunk2"}, + {"unquoted passthrough", "v=spf1 ~all", "v=spf1 ~all"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + rec := libdns.RR{ + Name: "_acme-challenge", + TTL: 3600 * time.Second, + Type: "TXT", + Data: tt.data, + } + + result, err := libdnsToHappyDNSRecord(rec, "example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + txt, ok := result.(*happydns.TXT) + if !ok { + t.Fatalf("expected *happydns.TXT, got %T", result) + } + + if txt.Txt != tt.expected { + t.Errorf("expected %q, got %q", tt.expected, txt.Txt) + } + }) + } +} + +func TestLibdnsToHappyDNS_TXT_UnquotedData(t *testing.T) { + // libdns.TXT returns raw unquoted text — should pass through unchanged. + rec := libdns.TXT{ + Name: "@", + TTL: 300 * time.Second, + Text: "v=spf1 ~all", + } + + result, err := libdnsToHappyDNSRecord(rec, "example.com.") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + txt, ok := result.(*happydns.TXT) + if !ok { + t.Fatalf("expected *happydns.TXT, got %T", result) + } + + if txt.Txt != "v=spf1 ~all" { + t.Errorf("expected unquoted TXT value, got %q", txt.Txt) + } +} + +func TestExtractRdata(t *testing.T) { + tests := []struct { + input string + rrType string + want string + }{ + {"www.example.com.\t300\tIN\tA\t192.0.2.1", "A", "192.0.2.1"}, + {"example.com.\t3600\tIN\tMX\t10 mail.example.com.", "MX", "10 mail.example.com."}, + {"example.com.\t300\tIN\tAAAA\t2001:db8::1", "AAAA", "2001:db8::1"}, + } + + for _, tt := range tests { + got := extractRdata(tt.input, tt.rrType) + if got != tt.want { + t.Errorf("extractRdata(%q, %q) = %q, want %q", tt.input, tt.rrType, got, tt.want) + } + } +} + +func mustParseAddr(s string) netip.Addr { + addr, err := netip.ParseAddr(s) + if err != nil { + panic(err) + } + return addr +} diff --git a/internal/provider/registry.go b/internal/provider/registry.go index 4a32edd9..74e839aa 100644 --- a/internal/provider/registry.go +++ b/internal/provider/registry.go @@ -25,6 +25,7 @@ import ( "fmt" "log" "reflect" + "slices" "git.happydns.org/happyDomain/model" ) @@ -50,6 +51,15 @@ func GetProviders() map[string]happydns.ProviderCreator { return providerRegistry } +// ProviderHasCapability checks if the registered provider type has the given capability. +func ProviderHasCapability(provider *happydns.Provider, capability string) bool { + creator, ok := providerRegistry[provider.Type] + if !ok { + return false + } + return slices.Contains(creator.Infos.Capabilities, capability) +} + // FindProvider returns the Provider corresponding to the given name, or an error if it doesn't exist. func FindProvider(name string) (happydns.ProviderBody, error) { src, ok := providerRegistry[name] diff --git a/internal/usecase/orchestrator/factory.go b/internal/usecase/orchestrator/factory.go index 7964dc1d..c9cb394c 100644 --- a/internal/usecase/orchestrator/factory.go +++ b/internal/usecase/orchestrator/factory.go @@ -87,7 +87,7 @@ func NewOrchestrator( zoneCorrectionLister := NewZoneCorrectionListerUsecase(providerService, listRecords, zoneCorrectorService, zoneRetrieverService) return &Orchestrator{ RemoteZoneImporter: NewRemoteZoneImporterUsecase(appendDomainLog, providerService, zoneImporter, zoneRetrieverService), - ZoneCorrectionApplier: NewZoneCorrectionApplierUsecase(appendDomainLog, domainUpdater, zoneCorrectionLister, zoneCreator, zoneGetter, zoneUpdater), + ZoneCorrectionApplier: NewZoneCorrectionApplierUsecase(appendDomainLog, domainUpdater, zoneCorrectionLister, zoneCreator, zoneGetter, zoneRetrieverService, zoneUpdater), ZoneImporter: zoneImporter, } } diff --git a/internal/usecase/orchestrator/propagation.go b/internal/usecase/orchestrator/propagation.go new file mode 100644 index 00000000..cd7fcb3b --- /dev/null +++ b/internal/usecase/orchestrator/propagation.go @@ -0,0 +1,130 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2025 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package orchestrator + +import ( + "time" + + "github.com/miekg/dns" + + svc "git.happydns.org/happyDomain/internal/service" + zoneUC "git.happydns.org/happyDomain/internal/usecase/zone" + "git.happydns.org/happyDomain/model" +) + +// SetPropagationTimes stamps each service in newServices with a PropagatedAt +// time based on whether the service changed compared to the provider state. +// It reuses the same matching technique as ReassociateMetadata (subdomain + +// type + ServiceRDataHash). +// +// For changed/updated services: PropagatedAt = publishTime + old service TTL. +// For new services (additions): PropagatedAt = publishTime + SOA minimum TTL +// (negative cache duration), falling back to defaultTTL. +func SetPropagationTimes( + newServices map[happydns.Subdomain][]*happydns.Service, + providerRecords []happydns.Record, + origin string, + defaultTTL uint32, + publishTime time.Time, +) { + // Find SOA minimum TTL for negative cache duration (used for additions). + negativeCacheTTL := defaultTTL + for _, rr := range providerRecords { + if rr.Header().Rrtype == dns.TypeSOA { + if soa, ok := rr.(*dns.SOA); ok { + negativeCacheTTL = soa.Minttl + } + break + } + } + + // Analyze provider records into old services for comparison. + oldServices, oldDefaultTTL, err := svc.AnalyzeZone(origin, providerRecords) + if err != nil { + return + } + + for dn, newSvcs := range newServices { + oldSvcs := oldServices[dn] + + // Group old services by type. + oldByType := map[string][]*happydns.Service{} + for _, s := range oldSvcs { + oldByType[s.Type] = append(oldByType[s.Type], s) + } + + for _, newSvc := range newSvcs { + candidates := oldByType[newSvc.Type] + + if len(candidates) == 0 { + // New service (addition): use SOA negative cache TTL. + propagatedAt := publishTime.Add(time.Duration(negativeCacheTTL) * time.Second) + newSvc.PropagatedAt = &propagatedAt + continue + } + + newHash := zoneUC.ServiceRDataHash(newSvc, origin, defaultTTL) + + if len(candidates) == 1 { + oldSvc := candidates[0] + oldHash := zoneUC.ServiceRDataHash(oldSvc, origin, oldDefaultTTL) + if newHash != oldHash { + // Service changed: use old service TTL. + oldTTL := oldDefaultTTL + if oldSvc.Ttl != 0 { + oldTTL = oldSvc.Ttl + } + propagatedAt := publishTime.Add(time.Duration(oldTTL) * time.Second) + newSvc.PropagatedAt = &propagatedAt + } + continue + } + + // Multiple candidates: try to find exact RDATA match. + matched := false + for _, oldSvc := range candidates { + if zoneUC.ServiceRDataHash(oldSvc, origin, oldDefaultTTL) == newHash { + // Exact match: service unchanged, don't touch PropagatedAt. + matched = true + break + } + } + if !matched { + // No exact match: service was modified. Use the max TTL + // across all candidates of the same type as a conservative + // upper bound. + var maxOldTTL uint32 + for _, oldSvc := range candidates { + ttl := oldDefaultTTL + if oldSvc.Ttl != 0 { + ttl = oldSvc.Ttl + } + if ttl > maxOldTTL { + maxOldTTL = ttl + } + } + propagatedAt := publishTime.Add(time.Duration(maxOldTTL) * time.Second) + newSvc.PropagatedAt = &propagatedAt + } + } + } +} diff --git a/internal/usecase/orchestrator/zone_correction_applier.go b/internal/usecase/orchestrator/zone_correction_applier.go index 468188c1..b0973937 100644 --- a/internal/usecase/orchestrator/zone_correction_applier.go +++ b/internal/usecase/orchestrator/zone_correction_applier.go @@ -28,10 +28,12 @@ import ( "time" adapter "git.happydns.org/happyDomain/internal/adapters" + providerReg "git.happydns.org/happyDomain/internal/provider" svc "git.happydns.org/happyDomain/internal/service" domainlogUC "git.happydns.org/happyDomain/internal/usecase/domain_log" zoneUC "git.happydns.org/happyDomain/internal/usecase/zone" "git.happydns.org/happyDomain/model" + "git.happydns.org/happyDomain/services/abstract" ) // ZoneCorrectionApplierUsecase applies a user-selected subset of zone @@ -43,6 +45,7 @@ type ZoneCorrectionApplierUsecase struct { domainUpdater DomainUpdater zoneCreator *zoneUC.CreateZoneUsecase zoneGetter *zoneUC.GetZoneUsecase + zoneRetriever ZoneRetriever zoneUpdater *zoneUC.UpdateZoneUsecase clock func() time.Time } @@ -56,6 +59,7 @@ func NewZoneCorrectionApplierUsecase( lister *ZoneCorrectionListerUsecase, zoneCreator *zoneUC.CreateZoneUsecase, zoneGetter *zoneUC.GetZoneUsecase, + zoneRetriever ZoneRetriever, zoneUpdater *zoneUC.UpdateZoneUsecase, ) *ZoneCorrectionApplierUsecase { return &ZoneCorrectionApplierUsecase{ @@ -64,6 +68,7 @@ func NewZoneCorrectionApplierUsecase( domainUpdater: domainUpdater, zoneCreator: zoneCreator, zoneGetter: zoneGetter, + zoneRetriever: zoneRetriever, zoneUpdater: zoneUpdater, clock: time.Now, } @@ -78,11 +83,11 @@ func (uc *ZoneCorrectionApplierUsecase) computeExecutableCorrections( domain *happydns.Domain, zone *happydns.Zone, wantedCorrections []happydns.Identifier, -) (execCorrections []*happydns.Correction, targetRecords []happydns.Record, nbDiffs int, err error) { +) (execCorrections []*happydns.Correction, targetRecords []happydns.Record, providerRecords []happydns.Record, nbDiffs int, err error) { // Step 1: Compute the diff and get provider/WIP records. corrections, providerRecords, _, nbDiffs, err := uc.listWithRecords(ctx, user, domain, zone) if err != nil { - return nil, nil, nbDiffs, err + return nil, nil, nil, nbDiffs, err } // Step 2: Build target records from selected corrections. @@ -91,15 +96,15 @@ func (uc *ZoneCorrectionApplierUsecase) computeExecutableCorrections( // Step 3: Get executable corrections from the provider for the target state. provider, err := uc.providerService.GetUserProvider(user, domain.ProviderId) if err != nil { - return nil, nil, nbDiffs, err + return nil, nil, nil, nbDiffs, err } execCorrections, nbDiffs, err = uc.zoneCorrector.ListZoneCorrections(ctx, provider, domain, targetRecords) if err != nil { - return nil, nil, nbDiffs, fmt.Errorf("unable to compute executable corrections: %w", err) + return nil, nil, nil, nbDiffs, fmt.Errorf("unable to compute executable corrections: %w", err) } - return execCorrections, targetRecords, nbDiffs, nil + return execCorrections, targetRecords, providerRecords, nbDiffs, nil } // Prepare computes the executable corrections for the given selection without @@ -112,7 +117,7 @@ func (uc *ZoneCorrectionApplierUsecase) Prepare( zone *happydns.Zone, form *happydns.PrepareZoneForm, ) (*happydns.PrepareZoneResponse, error) { - execCorrections, _, nbDiffs, err := uc.computeExecutableCorrections(ctx, user, domain, zone, form.WantedCorrections) + execCorrections, _, _, nbDiffs, err := uc.computeExecutableCorrections(ctx, user, domain, zone, form.WantedCorrections) if err != nil { return nil, err } @@ -142,7 +147,7 @@ func (uc *ZoneCorrectionApplierUsecase) Apply( zone *happydns.Zone, form *happydns.ApplyZoneForm, ) (*happydns.Zone, error) { - executableCorrections, targetRecords, _, err := uc.computeExecutableCorrections(ctx, user, domain, zone, form.WantedCorrections) + executableCorrections, targetRecords, providerRecords, _, err := uc.computeExecutableCorrections(ctx, user, domain, zone, form.WantedCorrections) if err != nil { return nil, err } @@ -171,8 +176,22 @@ func (uc *ZoneCorrectionApplierUsecase) Apply( log.Printf("unable to append domain log for %s: %s", domain.DomainName, logErr.Error()) } - // Step 5: Create a published snapshot zone from target records. - services, defaultTTL, err := svc.AnalyzeZone(domain.DomainName, targetRecords) + // Step 4b: If provider manages SOA serial, re-fetch to get the actual published state. + publishedRecords := targetRecords + refetched := false + provider, provErr := uc.providerService.GetUserProvider(user, domain.ProviderId) + if provErr == nil && providerReg.ProviderHasCapability(provider, "manages-soa-serial") { + fetched, fetchErr := uc.zoneRetriever.RetrieveZone(ctx, provider, domain.DomainName) + if fetchErr != nil { + log.Printf("%s: unable to re-fetch zone after deploy, using target records: %s", domain.DomainName, fetchErr) + } else { + publishedRecords = fetched + refetched = true + } + } + + // Step 5: Create a published snapshot zone from published records. + services, defaultTTL, err := svc.AnalyzeZone(domain.DomainName, publishedRecords) if err != nil { return nil, happydns.InternalError{ Err: fmt.Errorf("unable to analyze target zone: %w", err), @@ -196,6 +215,10 @@ func (uc *ZoneCorrectionApplierUsecase) Apply( } now := uc.clock() + + // Compute propagation times for changed services on the snapshot. + SetPropagationTimes(services, providerRecords, domain.DomainName, defaultTTL, now) + snapshot := &happydns.Zone{ ZoneMeta: happydns.ZoneMeta{ IdAuthor: user.Id, @@ -204,7 +227,7 @@ func (uc *ZoneCorrectionApplierUsecase) Apply( CommitMsg: &form.CommitMsg, CommitDate: &now, Published: &now, - ParentZone: &zone.ZoneMeta.Id, + ParentZone: zone.ParentZone, }, Services: services, } @@ -217,6 +240,28 @@ func (uc *ZoneCorrectionApplierUsecase) Apply( } } + // Update the parent zone of the WIP zone + zone.ParentZone = &snapshot.Id + + // Step 5b: If we re-fetched, update the WIP zone's Origin SOA serial to match. + if refetched { + if newSerial, ok := extractOriginSOASerial(snapshot); ok { + if updateErr := uc.zoneUpdater.Update(zone.Id, func(z *happydns.Zone) { + if services, exists := z.Services[""]; exists { + for _, s := range services { + if s.Type == "abstract.Origin" { + if origin, ok := s.Service.(*abstract.Origin); ok && origin.SOA != nil { + origin.SOA.Serial = newSerial + } + } + } + } + }); updateErr != nil { + log.Printf("%s: unable to update WIP zone SOA serial: %s", domain.DomainName, updateErr) + } + } + } + // Step 6: Insert snapshot at ZoneHistory[1] (after WIP at position 0). err = uc.domainUpdater.Update(domain.Id, user, func(domain *happydns.Domain) { if len(domain.ZoneHistory) == 0 { @@ -236,5 +281,27 @@ func (uc *ZoneCorrectionApplierUsecase) Apply( } } + // Update propagation times on the WIP zone as well. + if updateErr := uc.zoneUpdater.Update(zone.Id, func(wipZone *happydns.Zone) { + SetPropagationTimes(wipZone.Services, providerRecords, domain.DomainName, wipZone.DefaultTTL, now) + }); updateErr != nil { + log.Printf("%s: unable to update WIP zone propagation times: %s", domain.DomainName, updateErr) + } + return snapshot, nil } + +// extractOriginSOASerial extracts the SOA serial from the Origin service +// at the zone apex, if present. +func extractOriginSOASerial(zone *happydns.Zone) (uint32, bool) { + if services, exists := zone.Services[""]; exists { + for _, s := range services { + if s.Type == "abstract.Origin" { + if origin, ok := s.Service.(*abstract.Origin); ok && origin.SOA != nil { + return origin.SOA.Serial, true + } + } + } + } + return 0, false +} diff --git a/internal/usecase/orchestrator/zone_correction_applier_test.go b/internal/usecase/orchestrator/zone_correction_applier_test.go new file mode 100644 index 00000000..e7f01584 --- /dev/null +++ b/internal/usecase/orchestrator/zone_correction_applier_test.go @@ -0,0 +1,427 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2026 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package orchestrator_test + +import ( + "context" + "encoding/json" + "fmt" + "testing" + + "github.com/miekg/dns" + + providerReg "git.happydns.org/happyDomain/internal/provider" + domainlogUC "git.happydns.org/happyDomain/internal/usecase/domain_log" + "git.happydns.org/happyDomain/internal/usecase/orchestrator" + serviceUC "git.happydns.org/happyDomain/internal/usecase/service" + zoneUC "git.happydns.org/happyDomain/internal/usecase/zone" + "git.happydns.org/happyDomain/model" + "git.happydns.org/happyDomain/services/abstract" + + // Import AXFRDDNS provider to register its capabilities. + _ "git.happydns.org/happyDomain/providers" +) + +// mockDomainUpdater implements DomainUpdater for testing. +type mockDomainUpdater struct { + domain *happydns.Domain + err error +} + +func (m *mockDomainUpdater) Update(_ happydns.Identifier, _ *happydns.User, updateFn func(*happydns.Domain)) error { + if m.err != nil { + return m.err + } + if m.domain != nil { + updateFn(m.domain) + } + return nil +} + +// inMemoryZoneStorage implements ZoneStorage for testing. +type inMemoryZoneStorage struct { + zones map[string]*happydns.Zone +} + +func newInMemoryZoneStorage() *inMemoryZoneStorage { + return &inMemoryZoneStorage{zones: map[string]*happydns.Zone{}} +} + +func (s *inMemoryZoneStorage) ListAllZones() (happydns.Iterator[happydns.ZoneMessage], error) { + return nil, fmt.Errorf("not implemented") +} + +func (s *inMemoryZoneStorage) GetZoneMeta(zoneid happydns.Identifier) (*happydns.ZoneMeta, error) { + z, ok := s.zones[zoneid.String()] + if !ok { + return nil, fmt.Errorf("zone not found: %s", zoneid) + } + return &z.ZoneMeta, nil +} + +func (s *inMemoryZoneStorage) GetZone(zoneid happydns.Identifier) (*happydns.ZoneMessage, error) { + z, ok := s.zones[zoneid.String()] + if !ok { + return nil, fmt.Errorf("zone not found: %s", zoneid) + } + + // Convert Zone to ZoneMessage by marshaling services. + msg := &happydns.ZoneMessage{ + ZoneMeta: z.ZoneMeta, + Services: map[happydns.Subdomain][]*happydns.ServiceMessage{}, + } + + for subdn, svcs := range z.Services { + for _, svc := range svcs { + body, err := json.Marshal(svc.Service) + if err != nil { + return nil, err + } + msg.Services[subdn] = append(msg.Services[subdn], &happydns.ServiceMessage{ + ServiceMeta: svc.ServiceMeta, + Service: body, + }) + } + } + + return msg, nil +} + +func (s *inMemoryZoneStorage) CreateZone(zone *happydns.Zone) error { + if zone.Id == nil { + zone.Id = happydns.Identifier([]byte(fmt.Sprintf("zone-%d", len(s.zones)))) + } + s.zones[zone.Id.String()] = zone + return nil +} + +func (s *inMemoryZoneStorage) UpdateZone(zone *happydns.Zone) error { + s.zones[zone.Id.String()] = zone + return nil +} + +func (s *inMemoryZoneStorage) DeleteZone(zoneid happydns.Identifier) error { + delete(s.zones, zoneid.String()) + return nil +} + +func (s *inMemoryZoneStorage) ClearZones() error { + s.zones = map[string]*happydns.Zone{} + return nil +} + +// mockZoneRetrieverFailOnNth returns records until the Nth call, then fails. +type mockZoneRetrieverFailOnNth struct { + records []happydns.Record + failOnNth int + failErr error + calls int +} + +func (m *mockZoneRetrieverFailOnNth) RetrieveZone(_ context.Context, _ *happydns.Provider, _ string) ([]happydns.Record, error) { + m.calls++ + if m.calls >= m.failOnNth { + return nil, m.failErr + } + return m.records, nil +} + +// testZoneRetriever is an interface matching orchestrator.ZoneRetriever. +type testZoneRetriever interface { + RetrieveZone(ctx context.Context, provider *happydns.Provider, name string) ([]happydns.Record, error) +} + +// buildTestApplier creates a ZoneCorrectionApplierUsecase with the given overrides. +func buildTestApplier( + providerGetter *mockProviderGetter, + zoneCorrector *mockZoneCorrector, + retriever testZoneRetriever, + domainUpdater *mockDomainUpdater, + storage *inMemoryZoneStorage, +) *orchestrator.ZoneCorrectionApplierUsecase { + listRecords := zoneUC.NewListRecordsUsecase(serviceUC.NewListRecordsUsecase()) + lister := orchestrator.NewZoneCorrectionListerUsecase( + providerGetter, + listRecords, + zoneCorrector, + retriever, + ) + + zoneGetter := zoneUC.NewGetZoneUsecase(storage) + zoneCreator := zoneUC.NewCreateZoneUsecase(storage) + zoneUpdater := zoneUC.NewUpdateZoneUsease(storage, zoneGetter) + + return orchestrator.NewZoneCorrectionApplierUsecase( + domainlogUC.NoopDomainLogAppender{}, + domainUpdater, + lister, + zoneCreator, + zoneGetter, + retriever, + zoneUpdater, + ) +} + +func TestApply_NoRefetch_WhenProviderLacksCapability(t *testing.T) { + // Provider without manages-soa-serial capability. + provider := &happydns.Provider{ + ProviderMeta: happydns.ProviderMeta{ + Type: "NoSuchProvider", + }, + } + + storage := newInMemoryZoneStorage() + + wipZoneID := happydns.Identifier([]byte("wip-zone")) + wipZone := &happydns.Zone{ + ZoneMeta: happydns.ZoneMeta{ + Id: wipZoneID, + DefaultTTL: 3600, + }, + Services: map[happydns.Subdomain][]*happydns.Service{}, + } + storage.zones[wipZoneID.String()] = wipZone + + domain := &happydns.Domain{ + Id: happydns.Identifier([]byte("test-domain")), + ProviderId: happydns.Identifier([]byte("test-provider")), + DomainName: "example.com.", + ZoneHistory: []happydns.Identifier{wipZoneID}, + } + + retriever := &mockZoneRetriever{records: nil} + + uc := buildTestApplier( + &mockProviderGetter{provider: provider}, + &mockZoneCorrector{corrections: nil, nbDiff: 0}, + retriever, + &mockDomainUpdater{domain: domain}, + storage, + ) + + snapshot, err := uc.Apply( + context.Background(), + &happydns.User{Id: happydns.Identifier([]byte("test-user"))}, + domain, + wipZone, + &happydns.ApplyZoneForm{ + WantedCorrections: nil, + CommitMsg: "test deploy", + }, + ) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if snapshot == nil { + t.Fatal("expected snapshot, got nil") + } +} + +func TestApply_Refetch_WhenProviderManagesSOASerial(t *testing.T) { + // Use the DDNSServer type which has manages-soa-serial capability. + // First verify it's registered. + creators := providerReg.GetProviders() + _, hasDDNS := creators["DDNSServer"] + if !hasDDNS { + t.Skip("DDNSServer provider not registered") + } + + provider := &happydns.Provider{ + ProviderMeta: happydns.ProviderMeta{ + Type: "DDNSServer", + }, + } + + storage := newInMemoryZoneStorage() + + // Create WIP zone with an Origin service containing old SOA serial. + wipZoneID := happydns.Identifier([]byte("wip-zone")) + oldSerial := uint32(2024010100) + wipZone := &happydns.Zone{ + ZoneMeta: happydns.ZoneMeta{ + Id: wipZoneID, + DefaultTTL: 3600, + }, + Services: map[happydns.Subdomain][]*happydns.Service{ + "": { + { + ServiceMeta: happydns.ServiceMeta{ + Id: happydns.Identifier([]byte("origin-svc")), + Type: "abstract.Origin", + }, + Service: &abstract.Origin{ + SOA: &dns.SOA{ + Hdr: dns.RR_Header{Name: "example.com.", Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 3600}, + Ns: "ns1.example.com.", + Mbox: "admin.example.com.", + Serial: oldSerial, + }, + NameServers: []*dns.NS{ + {Hdr: dns.RR_Header{Name: "example.com.", Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 3600}, Ns: "ns1.example.com."}, + }, + }, + }, + }, + }, + } + storage.zones[wipZoneID.String()] = wipZone + + domain := &happydns.Domain{ + Id: happydns.Identifier([]byte("test-domain")), + ProviderId: happydns.Identifier([]byte("test-provider")), + DomainName: "example.com.", + ZoneHistory: []happydns.Identifier{wipZoneID}, + } + + // The re-fetched records contain a new SOA serial. + newSerial := uint32(2024010101) + refetchedRecords := []happydns.Record{ + &dns.SOA{ + Hdr: dns.RR_Header{Name: "example.com.", Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 3600}, + Ns: "ns1.example.com.", + Mbox: "admin.example.com.", + Serial: newSerial, + }, + &dns.NS{ + Hdr: dns.RR_Header{Name: "example.com.", Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: 3600}, + Ns: "ns1.example.com.", + }, + } + + retriever := &mockZoneRetriever{records: refetchedRecords} + + uc := buildTestApplier( + &mockProviderGetter{provider: provider}, + &mockZoneCorrector{corrections: nil, nbDiff: 0}, + retriever, + &mockDomainUpdater{domain: domain}, + storage, + ) + + snapshot, err := uc.Apply( + context.Background(), + &happydns.User{Id: happydns.Identifier([]byte("test-user"))}, + domain, + wipZone, + &happydns.ApplyZoneForm{ + WantedCorrections: nil, + CommitMsg: "test deploy with SOA", + }, + ) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + // Verify snapshot has the new serial. + snapshotSerial := getOriginSOASerial(t, snapshot) + if snapshotSerial != newSerial { + t.Errorf("snapshot SOA serial: got %d, want %d", snapshotSerial, newSerial) + } + + // Verify WIP zone was patched with new serial. + updatedWIP := storage.zones[wipZoneID.String()] + wipSerial := getOriginSOASerial(t, updatedWIP) + if wipSerial != newSerial { + t.Errorf("WIP zone SOA serial: got %d, want %d", wipSerial, newSerial) + } +} + +func TestApply_RefetchFails_FallsBackToTargetRecords(t *testing.T) { + creators := providerReg.GetProviders() + _, hasDDNS := creators["DDNSServer"] + if !hasDDNS { + t.Skip("DDNSServer provider not registered") + } + + provider := &happydns.Provider{ + ProviderMeta: happydns.ProviderMeta{ + Type: "DDNSServer", + }, + } + + storage := newInMemoryZoneStorage() + + wipZoneID := happydns.Identifier([]byte("wip-zone")) + wipZone := &happydns.Zone{ + ZoneMeta: happydns.ZoneMeta{ + Id: wipZoneID, + DefaultTTL: 3600, + }, + Services: map[happydns.Subdomain][]*happydns.Service{}, + } + storage.zones[wipZoneID.String()] = wipZone + + domain := &happydns.Domain{ + Id: happydns.Identifier([]byte("test-domain")), + ProviderId: happydns.Identifier([]byte("test-provider")), + DomainName: "example.com.", + ZoneHistory: []happydns.Identifier{wipZoneID}, + } + + // Retriever succeeds on first call (lister diff), fails on second (re-fetch). + retriever := &mockZoneRetrieverFailOnNth{ + records: nil, + failOnNth: 2, + failErr: fmt.Errorf("connection refused"), + } + + uc := buildTestApplier( + &mockProviderGetter{provider: provider}, + &mockZoneCorrector{corrections: nil, nbDiff: 0}, + retriever, + &mockDomainUpdater{domain: domain}, + storage, + ) + + snapshot, err := uc.Apply( + context.Background(), + &happydns.User{Id: happydns.Identifier([]byte("test-user"))}, + domain, + wipZone, + &happydns.ApplyZoneForm{ + WantedCorrections: nil, + CommitMsg: "test deploy fallback", + }, + ) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if snapshot == nil { + t.Fatal("expected snapshot, got nil") + } +} + +// getOriginSOASerial extracts the SOA serial from the Origin service in a zone. +func getOriginSOASerial(t *testing.T, zone *happydns.Zone) uint32 { + t.Helper() + if services, ok := zone.Services[""]; ok { + for _, svc := range services { + if svc.Type == "abstract.Origin" { + if origin, ok := svc.Service.(*abstract.Origin); ok && origin.SOA != nil { + return origin.SOA.Serial + } + } + } + } + t.Fatal("no Origin service with SOA found in zone") + return 0 +} diff --git a/internal/usecase/zone/reassociate.go b/internal/usecase/zone/reassociate.go index d73802eb..0a985e59 100644 --- a/internal/usecase/zone/reassociate.go +++ b/internal/usecase/zone/reassociate.go @@ -65,6 +65,7 @@ func transferMetadata(oldSvc, newSvc *happydns.Service, origin string, defaultTT newSvc.UserComment = oldSvc.UserComment newSvc.OwnerId = oldSvc.OwnerId newSvc.Aliases = oldSvc.Aliases + newSvc.PropagatedAt = oldSvc.PropagatedAt if oldSvc.Ttl != 0 { serviceTtl := oldSvc.Ttl diff --git a/model/service.go b/model/service.go index bbe811e6..4e258c2a 100644 --- a/model/service.go +++ b/model/service.go @@ -23,6 +23,7 @@ package happydns import ( "encoding/json" + "time" ) type Service struct { @@ -109,6 +110,10 @@ type ServiceMeta struct { // NbResources holds the number of Resources stored inside this Service. NbResources int `json:"_tmp_hint_nb"` + + // PropagatedAt is the estimated time at which the last published changes + // for this service will be fully propagated (old cached records expired). + PropagatedAt *time.Time `json:"_propagated_at,omitempty"` } // ServiceCombined combined ServiceMeta + Service diff --git a/providers/IonosAPI.png b/providers/IonosAPI.png new file mode 100644 index 00000000..9e85ec58 Binary files /dev/null and b/providers/IonosAPI.png differ diff --git a/providers/axfrddns.go b/providers/axfrddns.go index b1bdf47b..7b9bd4e5 100644 --- a/providers/axfrddns.go +++ b/providers/axfrddns.go @@ -68,7 +68,8 @@ func init() { adapter.RegisterDNSControlProviderAdapter(func() happydns.ProviderBody { return &DDNSServer{} }, happydns.ProviderInfos{ - Name: "Dynamic DNS", - Description: "If your zone is hosted on an authoritative name server that support Dynamic DNS (RFC 2136), such as Bind, Knot, ...", + Name: "Dynamic DNS", + Description: "If your zone is hosted on an authoritative name server that support Dynamic DNS (RFC 2136), such as Bind, Knot, ...", + Capabilities: []string{"manages-soa-serial"}, }, providerReg.RegisterProvider) } diff --git a/providers/icons.go b/providers/icons.go index cde261f9..ed13a9dc 100644 --- a/providers/icons.go +++ b/providers/icons.go @@ -34,6 +34,7 @@ // providers/INWXAPI.png // providers/InfomaniakAPI.png // providers/InternetbsAPI.png +// providers/IonosAPI.png // providers/JokerAPI.png // providers/LinodeAPI.png // providers/LoopiaAPI.png @@ -98,6 +99,7 @@ var Icons = map[string][]byte{ "INWXAPI": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xc0\x00\x00\x00\xc0\b\x02\x00\x00\x00ݾ\xfbP\x00\x008ZIDATx\xda흇W[i\xb6\xe5\xf9Wf͚\xf5fͫ*W\xae\xe7vuuO\xf7\xd4\v==\xd3ӯSuWWW\x8e\xce9\x94S\xd98\x83s\xc69\xe7\x9c\x13ɀI\x06\x83m\x82\t\xc6\x18\xb0\t\x06L0Aa~\xf7;\xd2\xe5*\"\x84\x00!_\xad\xbb0\x16BH\xf7n\x9d\xef|\xe7\xec\xb3w\x94ݼy\xbb\xd9lv\x8b\xd5\xc6\xc17n\xb7\x17]\x96\xb2\xfa\xb6녵\xbb\xd3\x1e\xad\xb9Q:\xf7l\xc17\xfbs\xffc}\xdaG\xdb3o\x14ֵuZl\xbe\x9f\xd6j\xb3E؉\x8a2\xb1\xd2+\x92j\x9a;2\x1e6\x9ḙ^x\xa1\xf0\x8b=\xb7\x7f\xbf%\xfd\u05ebS\xde]\x968bQ\xfc\xeb\xeax{I¿,O|gi\xc2{\xcb\x12\x7f\xb7)\xfd\xd3\xdd\xd9\x13\x8e\xe6\x03\xac\x9f\xce\x17\xce9S0\xfeH\xde\xdfwf\xffx\xfa~ec;Oh\x89,\x10\x99\x00\xf2\x06\x1a\xbb\xfdY[\xd7ŻO\xa3/\x14}\xbd/\xe7\x7f\xadI\x01%\xaf,\xbc\xf1Z\xf4\x8d7\x16ǿ\rP\x96'\x8eZ\x91\xf4~L\xb2\x1c\xa3b\x92~\xb6\"\x89\xaf\xdc\t\x8cx\f\xd8\xe2\xc1\x1c#8\x16ſ\xb98\xe1Յ7~\xb9\xea\xe6\xd1\xec*\x89C\x11\x83\xa2\xa8\x978\xb4جVm\x892^J\xb9\xaeEOZ\xb8\xd8#\x14\\\xde\\\x1cO\\\x01%?\x8f\xed\x81\v@\xf9\x99\x8f\x83\x9f\xea\xc02\x1cI\xfc\xfa{*h\xc5^+\xe9\xb2X#f9\x8bzi\xa1c\xfc\xafg\xa6\xb3=\xa5b\xe4\xf2\xa47\x16Ń\x89\x0fb{\xc2L\x7f\x0e\xc1\x16\x91\xec\xbb\x03\xb9UM/\"\x03CQ/\x13n\xec\x12r\xe4\xbf\xed\xed\xedyy\xf7\xb6m\xdb\xfb\xf0a\xa5\x96\x9aX\xac\xc6%\x8c[\xf1\xd3V\x92\x9e\x0fפ\xb0\xfa\x109\xdeu\xc6!g(J\xf2\x1f\x8a\xbcc\b8\xaeLfA\xfc\xcd\xfa\xb4\xfc\xaafyU&\x80\x86Yȩ\xaeyr\xf5j\xc2\xdcyK\xbf\xfcj\xdcǟ|\xbbv\xedV\x8b\xc5\xe2\xb9]\x92+K\xa8ؑZA\"\xfc\x9b\ri,g\x92ٰ\xb4\xbd\xb5$\xe1ݥ\x89$C#Uh\x11`\xf9?\x80\x1d\x18\"\xdd\xe6+O\xc2ׂ\x9a\x16\xf5\xb7L\x00\x85}\xa2\xc3\xf7\x9d\x9d\x9dw\xf2\xeemܴc\xec\xb8\x19\x9f~>\xfa\x9bo'\x8e\x19;\x9d\xef\xf9f\xc9\xd2ՅE\x0f\xb4k\xa9\x1eluܴm\xbc\xfeT\xf5\xad\x9d\xec\xc5\xce\xe7?!\x89\xf9\xf6@\xee_\xb7g\xfev\xe3\xad_\xafI\x01=\xec\xc2\x00\x04k\x93\x9f\x830\xf6\x86J\xa7~\xb1\xf2濭K\xfdc\\\xc6\x7fnI\xdf}\xeb\xd1p_Ȣ^\x06贶\xb6]\xb9\x1a?o>!g\xfc\x17_\x8e\xfd\xfe\x87)@g\xf4\x98i\xf2\xf5\x8b/ǁ\xa1ĤT\xf9-\xb7\xe7\xb1X\xad]\xdd\x16\xe3\x02\xa7\x87\xa8\xf6.K\xed\xf3\x8e{\xd5ϓK\xea/\xdc}r\xecv\xd5\xc1\xcc\xc7{\xd3+w\xa6U\x10\xb4\xe4\x00\"\xfb3*\x0fg=>}\xa7\xe6za]fEcy}[\xf3\x8b\xee\xcen\xab\xb9\v\x1b\x16\xd0i\xbd|\xf9\x06\xabէ\x9f\xfd\xa0\x85\x1c\x05\x9a\x1fFO\x15\xf4\x80'\x8eu\xeb\xe2jk\xebyp\xf6\xed;ħ\xb5붞>}\x91\xf4\xa8\xad\xad\xdds{\xdfm\xb5u[\xac\xe0I\xad\x896\xfbK\x7f\x8bH\x00i_\x9f=k<{\xee\xf2\xb4\xe9\xf3?\xfb|\f\xd0\x19;N\v6@\x87\x03\xe8p\x0f\xa1h\xf9\x8au%\xa5\xe5<\xf8AI\x19\xab\xd8W_\x8f\xff\xfc\x8b\xb1$F\x9f~6\xfa\xebo&N\x9d6\x7f\xd1\xe2\x95\a\x0e\x1cKI\u0378w\xaf\xb0\xaa\xaa\xe6EGG__\x8c\x94\xb3\xf5CU\x80\xb4Wh3\x01\x14\xb67\x16\xac\xb3g/M\x9a<\x1b\xe8|\xfb\xdd$Y\xa7t\xe8\xf0\x955k֏ѷneɃ\xf7\xec=\xfc\xd5\xd7\x13\bE\x12\x96ƌ\x9d&h\xe3w\xb9\x1fH\xf1<\xf2ӹ\xf3\x96\xacX\xb1n\xc3\xc6\xed;w\x1d8v\xec\xcc\xd5k\t\x19\x19م\x85\x0f\x1eVTVVVUW?yZ[WW\xd7PWW__\xdf\xc0\xd1\xd8\xd8d\xb3\xd9\xcc\b4\xcc\xd6/b\xc9'\xff\xf8^Ot\x04:\xfa\x9a\x05,\x8e\x1e;MB̓\xd33\xb2Ǎ\x9f\tDF;\x976\xe3\xc1\x9dNH9\x9e\x87\xb8%Y\x14\x90\xe2\xe0\x1b\xfe\xfb\xf57\x13\xbe\xf9v\xd2w\xdfO\x11\x80\x92\x95s\xf0\xb4\xe3'\xcc\x1c=vڽ\xfb\x85*7\xb7\x99\x00\x1a\x067٫\x1f;~\xe6\xb3\xcfGs\tu(p]\xbf\xfb~2\xd7{\xd9\xf2\xb5\xacV<\x86ذe\xeb.V+\xee\xf7\x84\x8e\xafC\xe1\xc9\x01)\x1dXr\xc8\x03@\xad~p\xe7?>\xfd\x01\xb0\xea/\xcc\x04\xd0\xf0\xc8~\xba\xba\xbacWn$\x8fa%\x92\xcbL\x8c\x998\xe9G\xf6Y\xb2\x99\xe2\x9b\t\x13\x7f\xfc\xfc˱\xc6k\x1f\xf2\x838\xf4\xd9\x17cX\x1fM\x00\x85/V\xbc.a|mii]\xb7>\x0e\xdcp\x90ǀ'R`)\x05\xed\xddw\x84\xf8ԧ\xc0\x13\xdc\xc1\xf3\xb3̑-\x99\x00\n;\xe8HFa\xb3\xfb\xc3\x10\xd7,++\xf7С\x13\x05\x05\xc5Rh~\xfa\xb4n\xf1\x92U@ʘ\x1b\r(\x80>\xffb\xcc\xf6\x1d\xfbL\x00\x85S\x96#5e\x8b\xb5\xb4\xae\xd5\xe67\x95ַ?\xf2\xcd\xf3\xe7-\x93\xa7\xcc\xf9\xeb߾\xd6K\x88\x03\r#\x01\x10\xbd6\x13@\xe1\x11xTME\x83\u008b\xee\xe9'\xef\xfd).\xa3S%4~\xb6\xc9Ύ\x84U\x16\xb5\x8b\x97\xae\xb1\x03gsĢ\xa6\xed\xa1T\x06m\x04ShS\"ɽ\xe2\xe2\xf6\x98\x00\n\x93eKCJ\xf6\xa3&\b\x81B\x05\\}\xa3\xd4\xdeGr\x16ш\xfdם;wY\xdaV\xae\xda8y\xca\\U<\x1c\xa3R\xa5\xf1\xecҁ\x94\\{)\b\xe9\xa8\x1a=&H\x00mݺ\xdb\x04\xd0\xd0/[6\xf5ucb9|?\b\x81\x10tha\x82\xa1\r\x89e\x82\x1e\xaf\xe4eπ\xe4\xf6 \xaaՔ\x01SR\xd2ɬ\x97.[3{\xce\"6k`H \xc5&\x9fX\x05\xaa(\x1d\xb1-\u05cbI\xbe\x0e\x03ڦ\xd13\xa1\x8e@\x95h\xd3\xe6\x9d&\x80\x86>\xe9\xe9\xe8\xb6\xce8y\xef\x9f\x17\\\x17N\x96pk\xf8\x86\x16\xf7\xe8Cw\x9e>\xef\x905.\x90h\xa47\xdb=\x11\xd7\xddݭA\xaa\xe8AB\xc2M:\x18\xab\xd7l\x8e^\x14;{\xceb\xfa!\xe3'\xcc\x02@\xb2\xf6\xd1\xc9\xff\xccp\x806UQ\x04m\xe3y\x00\a\xa5E\xbe瞿|\xf4\xe5\xe1#\xa7L\x00\r\xd9M\x92\x9eҺ\xb6\x7f\xec\xca\x1e\x11\x1d\x0f\xa5ƍ\xc0\xc5=p$\xe0,\xd3\xf4nl\xeb\xd2\u05fb@\x02\x92\x11L~*Š\xaa\xbd\xfd\x05\xdd֒\x92\xf2\x9c\xdc\xfc\x9b)\xe9\xd7o$]\xbct\xfd̙\x8b\x14\t\xf7\x1f8\xb6c\xe7~\xc2\fh[\xbe|\xedҥ\xab9\xd8\xebŮܰm\xfb\xbe\xf3\x17\xae\xd2*\xb1{k\xf2\x9b\x00\x1a\xa4\x94\x19\n\xc4/V&\xc3\xe4\x02+^9~\xc4!H6\xafF\xdf\xf8\xf7u\xa9\xach%\xb5\xad\xfa\xc5\x02E\xaa\x7fهΥ\x11R}\xbd\xea\x86\xdf\x1d\x82x#i\xe2\xe0S\x8b\xa2\xc2\x19=\x90l \xfe\x81\x0f_\xe8ѹ\xc6BY\aF\x10\x99Y\xec\x12\x8a\xeb\x9aڻܖBi\x86ۂ\xb966\x05\x8e\x1e|\xb8ݼ>\xab<~\xe0b\x8f\xcd\xf9\xa6\xdc\u00ad\xcd6\xa84ٰ\x03\x90\xfe\xfe7&\x96\x81\x1e\x891\x01R\xd6\x05g\xaf\xab\x91\x9a\xdfmN\x9fz\xe2\ue25c\xeaG\xcf\xda\x19\x05\xf4L\xad\x1cx\x1a&\xcc\n\x9b3\xc6HL\xf5\xbc=\xef\xe8f\xdc\x11\xb6Z\x97\x1al\x1c4\fE\x85\xdbi\x92\xab\xbb\xe8b\x91\xa4\xccA\xccB\b\xf5\xfd\x9d\xa5\x89\xc0\xe8u5V\xf1ǭ\x19K.\x15C\x17̩lj\xed\xb0\xf8\xff4\xcbB`\xb5\r\x01\xdd]\x8a\xec\xf2\x02\xf4\x17\xe3\xebe\xc0\x87\xbc_\xf3\x1c\xa2\xe3\xe6\xa4\xf2\xc9\xc7\xee\xc2\xd2\xe7\\A\xb8fL\xf6q\xe3\xe0\x8d|D\x85\x1bz8ks\xce\x16\x80\x1eϔ\xb9\xaf34:\x8f\x9d\xcd\xff\xab\x8a\x98\xcc\xf9\xfd\xdf\x1b\xd2H\xc9\xe7\x9d+\x84\x81\x9a\xf7\xb8\x19v\xa9\xc5/\xd7\xc2\xe6zE]A\x16\xcca\xf1\xf6T\xfe\xaf5?}\xd1e\x05\x16ie\r{n=\xa2\x8eʨ\xeb\xff\xd9x\x8b\xf7(\\\xec\xd7\xd5Ј\xbck\xde)\x1f\x98\xa6\x17]\x83\x13\x87\xc2\t@\xea\xddJ\xec\xf9 6\xb9\x9fCX\x9e`\x92\x05\x8e\x13͜({:-aZ\x91D\xeaMQ\x9b\xf1Ӆ\x17\x8a\xf6\xa5W^\xbe\xff4\xb5\xb4\xe1n\xf5\xf3\xcag\xed,\n\xb6\xc1}\xfb\xa0\xb9\xe2Y\xfbݪ\xe7ieϮ\x14\xd4\x1e\xcaz\x1cs\xf5\xc1\xd8\xc3y\x1f\xef\xc8\xfa\xbf\x9bn\xfd\xcfU7\xe5\x93\xf0\xba\x1au%\xc4\xca>\xf4\xe7\xaeck\x8c\r\x81*b\x92\xacζ\x97\a@\x12\t\x96_y\xc09\xe2,\x84\x10@^'Gu<1S\xa1\r#\x03)\xe7\xf02\xd7\xe9W\xabS\x98\x9a\xf8l\xf7m\xeaLS\x8e\xdfe\xc4\x1ddS\xfbޙZq<\xa7\xfaҽ\xa7I\x0f\xea)\x8bè/x\xd2R\xfc\xb4\xa5\xa4\xae\x95\xf6\x9cd!rP}\xe0\x9e\a\xb5\xad̹\x16\xd4<ϫjN/\x7fv\xa3\xa8\xee\\\xfe\x13\x90\x11w\xf3!\xe0Xp\xa1p\xf6\x99\xfb\x93\x8e\xe53jH\\\xfc\xfd\xe6\xf4_*\x94\xbc\xa1\xe6\x87\xe4\xf5\x00\x17rA\xe0B\xf8\xd4ê\xffAG\x1e\xc3\xefr&\aa!\v#\x00\xc9J\xf2\xb0\xa1\xedWJ\xba \xc0ܹ\xffx2BJ\xff4\x8bX\x02\xe5\x03\xae\x1fؒ˩M\x18\xaa+\xaaF\x9e\x13@\x1eeq^\xaa6\x1d\xb6\xd00\xee>*\xe0\xe1\xd4Q\xaeHuy\xc2\xd8d\xa3Hè\x10\xbd~^\x1e\xc8fr\xcdQ\xa6\xb7E(\x80<\xb3G\xc1\xd0ՂZ\xce&\x1fVi{\r\x15\x8c\x86\xf5\x014\to\xd3N܍X\x00\xf9\xda{\b\x86\xa8)\x7f\xbd?\xe7\x7f,\xb8.\x85D\x13FAc\xe8p\xf6\xe3\x81[Ȣ\x86\x10=\xdch^z/\xe3\xaa;ٻ\xd2\xe4B\xfc\x8b\x1d\x13ن\xc4y\x13\x16}\xca\xf0H\u0380Q\xd1Ӂ\x1a\xc2\x1f\x1a\x00I\xb7(''o\xc1\xc2\x15\x1d>\xa6\xf5\xa4\x9aǍ\xcd-\x1b\xec?lɐ\xecU>XZ\xc6`B$\xb0 \xc4I\xfbroN\xb7:\x9b\xb6\b\x00\x90\x84\x1c\xfa\xdbS\xa6\xcec\xf0\x05\x18\xd9}\x10\x1et\x1e\x99\x14^\xd9S\xb0\xdd\x1d\xa9\xa4-\x00\x93d\xd9&\x98z=>P\v\xd9\xc5{O\ab!\x8b\x1a\x12\xf4tw[bc7@\x9a\x81\xbd\xc5\xe0zs\xf3s?)\x91\x83\x9e\xe1\xac\x15Qbٖ\xf2\x90\xf2̯V\xdf\x14\xb1\x15i\xb8\xea\"b!\xdc\xcbD\xc0\xc1\t\x81\xce\xf0O\xf3\xaf\xd1\xf4\x88\x1c\x00\xed\xda}P\x9f\x8e\x80~U\xa4\xa4U\x9c\x8a\x05\xbe[\xf4\xae%\x7f4+\x89I\x94\xcb>ޙ\xf5\xe1\xdaT\xea(\x80\xe9MU\x06\xd4\x16~\u05faΨ\x97\x0e7\x8e\x85\xfemU\xbc\xa6\xafܡ\xf4@\x86\xf7\x12&\xf8\xb8\x11\x9f\xccԟ\xd0@\xe1\xefEGǪ\x0e|\x0f:\xfc\xb3 \xa4-\xe5B`\xb0\xdb\xebZ:\xe3\x8b\xeb\xa8\xed~\xbe\xe76U\x7f\xce݈h\x87*\x0f\xc0\xa2\"2ҵ@\x17\xf2\xbaː'ˆ\xb7\xa6\x150\x89ʼ}\xbe\xd2\x17;\x95[\x1d\t\xdbx\xb9\xe6\x88\x10@\x16\x96\xc9_\x0eV1(\xee\xf2\x00\xd4\b\x98\xe1\x82\x01hw\x95h\xf1\xd3<\x92f\xa4\xdb\xfd\xec\xddP\xa7\xa3c@ہ\xfe\x03\xf9#\xfb\xb8\x0fT\x7f^o\x11\x8cP\xf9\xb8\xc4*\xc7ُ\xf1V\u058b\t;\xa0x\xad\x9b\xbf\xa75\xf8\xe2\xf5\x05\x9d{>ٙ\xbd\xeaz\t\xfd\x16\x9d\xdda\x1b\xee\x00\xb2\xab\xc1PX\xc6P͝\x13\xc7c\x98c\x97\x1fUTTΘ\xb9\x00Q\x95y\xf3\x97\xa1?\xd7\xd6\xd6f\xf7\xcb_\x0e\x10L\x12\xb1\x98\x04\xa2\x95M7\n\x86\x1a\xacE\x14\x9c'\x1e\xcd\aX\fx\xd0{\x92^\x98\xde{\xa2q\xa17\x16\xb80#\x1d\x9f\xef$\xcf\n\xb2ka\xda\xeb\x91\xd4S\xb0\x8e\xd1/\x7fϳy=<\x85\xf1\xf4\xce\xd7{z\xe7n\x91\xd6\f\x96\xc6*\xaf\x93O\b\xa1wډ{\xeb\x12\xca\x00\r\x8b{\xa7A\x11k@\xdbaQ\x83\x19~\x98\xf35\xa6>`\xe5\xc5\vm\x0f\xdf\xd8\xd4<}\xc6O\x02,0\x04q\x1d\xf9\x95\xb3g/755\x1b\x97\xbf\x00\t~n\xe4\x1e?\x8f\xa4\xdf^\xd1\xd0\x0e\xa9\x83\x0e<\xb5\xef\x13\xb9՛\x92\xcaiˣ\x88Hk\xf3?\xb7d\xa0E'iě\\\xb6E\x0e\xf5\xe7W\x9c=,A\x9b.7\xceu\x15Y`\xc0\xf7\xa6\xea|\xc9\xf1\xb6\xeb\xf1\x96\xe1\xd0\x1e\xb9\xd8\xf1\x8b\xf2$#\xb4\xd6\xdb\rA\xf3+\xceN\x99H2\x02 ^ϟ\xe32a\xfc\xc0x\xa1\x1dK\x94\x05.\x88u\xb2\x82{\xbeQ\xed\f\f<\x9f#j\xd0R\x9f\xdc\xdc|\x16,\x99\xdc\xe3+\xe32y\xf9\xf7\xe5\x01\xbb\xf7\x1cB\x87\x005\x02}t\x06\xc1\x14`\xc48ľ\xfdG\x1f<(3֊\x02Y\xdd<\xe3\x93͓\xa8\xd5ۯ\xb4tt?i\ue823\x0e\xbb#\xab\xa2\xf1fI\x039;}x\xb63\a2+\xb7\xde|Hs\x1e\x9e\x1a\xd7\x12\xee\x04\xbbB\xea\xe6\xe8\xd8\xd3\xc0\xffdW6|\x9d\xbf\xed\xc8\xfa\xeb\xf6,\xfc\x0f\xfe\xbc-\xf3/\xdbz\xber\x0f\xf7\xf3SH\x1a<\xf2\xd3ݷ\xf9-\xf8$c\x0e\xe5A\xf4\x99\x7f\xae\x90m\x01a\x92\xd2ש\xdc\x1a\xf6\xde\xf1Eu\xb0;r+\x9b\x8bk[\xd1\xccg\x81\xf6\x9f\x1d\x0e2\xcd2jpb\x0f\xc3\t\x04\x15@#\xf8 \x0e\x1d>|R\x1e\x90\x99\x95\xa3\x03\xcbUHe:\x03Y<\x92X5g\xee\x92#GO#\x91\xe9Vu\f\x9a\x00o\xa83\xb9\x03+\xd8'\xf3\x12\bu\x12\xaaW\x91\xb2\xfe<\xb3\xf1iC\xf5\x82\xc3\x14@\x12~\x0e\x1c<\xce\b\x95(\x7f\t \x98\x95\x91ŋ\xd4G\x80\xe5C\x8fg\xba\x84+%;7\x81\a#\xbb\x91\x9a\x9a\xe1\xd9\x031&L\xb6P\x9cSc\xdc\xf2d\x12Z\f$CydП{[\xcf\xdf2\xfc9o\x04\xc80dpG\rB\xf8\xb9{\xb7@\x9f\xec\x94\xfd\x173V\xf2\x80M\x9bvHV\x14\x80\xb2\x93Cv\x0e\x81:f\xf6\x18!\xa5\rr\xf0Љ\xcc̜\xd2\xd2rTý\xfeu\xe3\xe0\xc4P}Nm\xaeG\x84ݢ\x06\x1a=,:\xe8\xeb\xb2H\x89\xb6\x17pA6U\x1e@ \x01\r}\xd2\xe9ч\x8b)a\x13\x90\x94\x02\x90\xa6\xa19{\xf6\"\xd4UI\x98\x92\x92\xd2\xca\xcb\x1f\x11\x9f\xba\xba\xba|DD\x9b\xdbD\x8e\xcd\x16\xf1B\x86\xc3\x13@\xb2x\xa5\xa7g\x7f\xaa-^3D\xa2\x10\x91J\xab\xdaa64<\x9b:m\x1e\x11%8A\f7\x01CQ]U\xba\x85\xe3xN$8\xe6\xcd[\xca\xc0(R\x98(Dggߩ|\\E\x94\n\xa0\x1c`sN\x81\xf9\x1c\x02\xd3A\xe7\xf7f\x02(D\x00*..eK%a\x86o\x8a\x8aK\xe4\xa7*+b\xe7\x15\x1a\x990\xa3\xec\xc1h\xa5U\xe8\x84\xd4h\x92')\x10L\x9f\xb1\x00]_&\x91O\x9c8\xc7lrbbjNN~yy\x05z\x1d\x14\xa8h\xcf\rD\f6UZCp\x8b\x89YO`\xe0`V\\\xee)))\x93\xach\xe0\x0e\x17H\xa9\xdcK\xc9\xf6jb.\xba:\x02\x8d\x14~4q\xd2lrs$|\x17FǠ¹~\xc36\x84\rO\x9d\xbe@\xe8JNN#\x82\x12\xc0\xd0\x1d\xa7J\xfe\xe0Aii\xe9C\xccY\x1e?\xae\xae\xa9y\x8a\x9c/ke\xf3\xf3\x96\xe7\xa8\x0f\xb5R\xfb$ƵS\xd9\xe2\xd6\xd9\xd9\x15\xc1\x82\n\x83\x9dDs\xbaI\x80\xb6\xc6\xed\x96;\xf9\xac/^\xbc\x8a\x8bǝ\x03\xad3\xe7k\xd53*\x94\x91N\x81\xad\xaf\xbf\x9d(j\xd1\n\xebZj\xa5\xb4|]\xc47Ⱥ8x\xb0hh\x82\xe9\xe8E*\x8c\xa2\x06\x02=\xbe*fr\x1232nϝ\xbb\x84\xc4B:\x18\x83#\xba;$\a\xcb\x1cܕ'OjM\x00\xf5\xe1\x06\xf3\x8d\xb9n\xff\x8fa\xdb\xcc\xee\x86-\x0f\x9fQ\xb6\xd9b\x89\x12\x01\x8b\x9a{\x10\x1a=\x95\xb7\x86\x15\x8b\t\xa0\xc0\n?Ҹ\xa8~\x0e[\x19\xe6\xb2\xdd\a\x13E_\xcel\xaaJ\x84P܌\x99?\x01#\xb6?\xd2舘\x98$\x8d?q\x94\x8a\xd4<:\xb4\x00Ҿ\xa2\x16\xf0_\xe7\\\x8d\xbeXd\xf7M\xe1v\U000ff954\x97\x98\x98\xb2y\xf3N*\xc8\xe4\xd7ҝ\xd0͗\x86;\x80\xf8\x90\x98\x00\n4q&\xf0\xfcB\tk@\x95\xc2\xf0\xd1ޛ\x00\xafQQ\x90Ǒo\x92!a\x0f@)\x85S\x0fI\b<\x89q\x93\xae\xa3;\xbc\x00D\x9eG\x05\xd2\x04P\xef7\t6\xa8e\xc1\xa3\x93\x81v\x98u\xbb\xd2\x1eɏ\xac\xbd\xb0\x9b\xdd9b\xd4s\xf9\xe0^\xbb\x9e\xb8r\xe5FJv\xbam\x8a\xf4\xceĆ'\xfc\xc1\xc4+\xe4\x03\x80ۡ\t\xa0\xde\u008f\xfa\xca\xec\x1f\x84K\b\xa0\xbal\x05\\\xccu\xf1\xa5\x82-}ҴW$\x19\xcf5\xf7P̽\x9d\x93G\xaaDM\x85ʯp\x83\xc0\x13\xdf\xe89Sx\xc6'\x01P\xfe\xdd\x02\x13@\x01\xa5\xcf\xf0sa\xf8\xea\xe3\xeb\xa2i\x02\xab\x17\xae'\x84v\xbb\x93\xa1\xd7'\x05g\xe3\xa3\xf9\x9e\x96\x13D\xd8\v\x17\xaf\xed\xdcy`ΜŊC=A\t\xcbk\x8b\x9d\xd1\xfb\"\x1cB\x14\t\x1c5w\xfah&\x80\x02\x02\x10\xfa\xba\"\a\xee9\x9b\xcd8\x01v\xeb\xb5-\x0e\xad\x1a_R\xa3\x01\x86%\xbd\x16@;\xf3\xfe\xfd\"L\x96\xb1\xa4\xa0(0i\xf2\x1cq9Ux\xd2̼\xe5*\xfa2\x18\x1c\x04\xc7'`\r\x19\xdc\x04P\xef\xe93BF\xe8\r\x02\x14\xcfY*\x89I\x8c\x19|\xb86\xe5@F\xa5\xae\xe0l5\xcc,\xf7\tL\x16o\x999\xf7444\xe6\xe7\xdf\xc7q7n\xdb^L\xe6 ΪEd\x9c3D9\xbc/\\\x1dU\xa6\x0f\xd0\n\xc8sRE\xf4?\xfco\x02\xa8'}f\xe4\x8aI%?\x9ab\xfc\b9\x04Rl\xe4E\x99:@\xbe\xd9fx\x86 f\x97ܘ_\x9e\x90\"\x13\x87\b\x00\xa16--\xf3\xf8\xf1\xb3k\xd6l\xa1\x8bB\xdb\\sT\xf9a\x8a\xc6\xeb\xf8Lx\x1d\x8ep%\xc0\n\xb0\x9f\xea\xbf\x05Kr\xc6\xfe\v\xef_\x8c\xc3\xf1\xae7\v\x89\xbdg\xd0\xe3\x8e\xe4\xbdaH\x80\xfc\xa8\xa5\x8a\x823\x19Ҵ\x93\xf7\xae\xdcgY\xeb6.\x85\x96~\x88\xbb\xfbǓ\x04K\xa8\xae\x90x\xe0\xb5a\xd2s\xf1\xe25\x80\xc5P\x11N\x17\f\xa9\xe1\x14.\x95\x1b7G\x15\xc5耈=^\x8cT\x9c-wG\a\x9eƻ⁌S\x06\xe1\xa3%\xc1\aC\x84\xc0\xcbW\xe2\x9d^\x19\xf6H\xbd\xf5\x17@\x129\x18%\x1e\xd5G\xd1]\xbe\x919\xbd?\xc5e2Η\xf3\xa8\xa9\xdbb3\xd6$\x83v&\bu^\x8d\xf3\xa3\xc3Œ\xe7%\x05\x10\xf6\x1f\xaf\xf4=\x01\xea\x93Җ\x80\x89\xc8\x04\x9e4ي\x05\x9a\x12\x19\x82\xf6\xa4M\xc8\x12\xac\xb8\xfa\xe0dn5up\xdck\xea[;\xad\xbe\xa5\xf2\\\xa6\x86}\xcc&\x0f-\xd4l\x86Ig\xe3`u؆\xba~\x01H.\x15~\x11#\aK=^Ǔ\xacto\x1bl%\xd0F\xa1\x8c\x89\x19\x0f\xfa\x18h\\\xecM\x7f\x84\xb4\x05\x92\x1a\U00013a9a^xZ\x86\xf5\xfa\xd6\xdcD\x11z9l\x1eG_~=\x90\xa4)<1\x14\x9aV\xc6W\xfbr\xde\xf0\xedJ9\xd0n\x04:\xa4\x9cf<\xf1\x92B\xbd\x1a-\xfaK\x89d\xe5tyi\xc9M<\x96\x8f\x1aˊ+\x0f\xb6\xa7V\x9cͫ\xc9(\x7fV\xf8\xa4\x05\n\n\xab!\xa1\x8b\x8a\x149\xbbu\xe8.\x14\x7f\x19a\xa8\xb6NKc{ד\xe7\x1d\xd4Z\xf1p!\xac\xf2\x11\xadj|\x11\xc9u\xa0ۏ\x9a\xc4}h\xc85\xe1\xbc(\xc0\xa9\xb5O\x17\xf6ҕ\xc8D\xb5I\xcb\xfdW$\xfdb\xe5\xcd_\xafN\xc1\xb3\r\t\x9f/\xf6ަ(\xfa\xe3\xe9\xfb\x8b/\x15SVX\x1b_J\x99j{J\x05+\xf5\xfe\x8c\xca\xc3Y\x8f1\x1a;u\xa7\x06q'\xb4\x82(\x84\"\x1a\x94X\\\xcf\x02j<\x12\x1fԓ\xa5]+\xa8\xbd|\xef)5\xfa3y5x'\x1eͮ§\x87\x04\x0e\x96\v\xf2PX2\xae\xb9QʟX|\xb1h\xd6\xe9\xfb\xe3\x8f\xe4\xf39d\xd3@\xa5\xfe\xc35)$|\xbc~\x14\xf88\xb1\x9a\x9f˲D\x91Y\xb5\x86Y \nA\x04\x92\xb7D)H\xea\xcba(&?\xca\x03Xn\xea\xadx\xe4\x002\xcd\xfaIs\xe8I\xd0\xddt^\xf1}\xe8.;\x02D7\xe91\xa5>\xe6\xd0\x1d\x1b\xd1\xdbS\xe9&@\xfc\n\xcf\xc3v\x01\xb8\xfc\x8br\x00\x92\x17ϫE\xf2\f\xf1P\xb4\xfa\xc2m-\ve7\x1eOIN\x01\xef\x7f\b]v\x82G\x987\tK\xff\x87\x9b\x1c\xa7\x87\x16\xa2S\xf3\xb0/ϦS\xa9t\xcf(\xbd\x93\b^/\r\x8cX\xf8\xd0\x03H\xc7\x10\xc1\x9c\x9a\x10\x1f&\xd3\xd7\"\xe4\x8e\x05\xc4*\b\x9f\x11\v \xfd\x8dշtN>~W\xf4f\xf5\xdc\xd6<\xfa\x0f V:Ǩ\x82-B\x01$qH\xde\x1c\xe6\xa3HI\xc2/#\xa50a\x14\x12\xc7\x02\xce$r\x9cVۀx\xa6\x84\v\x80\xec\x06\x87\x14v\xa4lUP\xbc\x06Fh\xe4J\xa7´\xfd\nzwIf\re\xaf9\xcc\xf2\xe8\xa8~\x00\xc5F3\xda\xe7r\xe6,\x9e\x02\xa3\xa3\xb7\xab\xa8\xc1\xa0\x87ͺ\xf6\x8e\xb2\xfd2\x91\x14D\x9aϾ\xec\x97+o\xd64\xbf\x88\x10\x00Ac\xb8\x99\x92\ue9c2j3\f\x85\xf1/J\xc7\xf4\x1c\x10\x87'\x14\x93\x0f\xbe\xa3\x867L$\xf5\xe9\x00C\xd8@\x87U5(*\xb8\xd8cW\xd2ϋ\x16\xaf\xaa\xad\xad\xb3\xfb\xe5k\xda\\g\v;\xbb\xadTؖ])\xa6\x8d\xa5Ǥ\x9f\xe9\xddS\x13L~W1\xf6%\x88\x8eG\b\x80\x10\x9d\x80߹m\xdb^{`\x8cqi\n\xea\xffe\x88\f\x8f\x01\xfcu\xb0g\x17\xfe\x06`\xa2\x8c&u3\xbd\xd0g\xe2ƘGS\x1f\xa1\x0e\x1eV;\xf9`\x00$pA0\x10:0GڭL\xed-Y\x02\xeaVJ@2\xbe\x7f\x90\x84\xbf.5~\x84\xfeq\x02\xa0\x1c,\xb42\xbd\xcf`\xda\xc8\x19w\xf2\xb4V\"\x04@\xcc\xcb1x c\fw\xd4\xec\x1c\x18\n\x9cv`\xf3\x88I\x02&\xacC(\x01`\xd3D\x15\x80\xe6\x14[\x0f\xce\x1a\x9b\xb8\xb7\x95wΨ\x98\xa4\x97\xd6FN\x004\xef\\a\x84\x00\b\x15\x84ϕC\x8aH\x05\"hj7\xe8\xd8\xf5\x89\x01\xa3\xb3\x9e\xdd\xca\x01\xb4~`\xb5\xd2w\x1c{8\x0f\xef\x1c\x9a\xeat\x16\xa5\x7fD0\xa7g\"\xdd\"O\x1b\xb9H]\xc2h\xaea\xec2\xecs \x81H|\xc2M\xc6_t\x11]\xe6Z\xf6\xed;*\x0e\x18A\xc0\xc8?\x98\xb4M\x9f\xd5\xc6\xec\")$-q\xac\xd4&\x1cͧ\xb9\x88\x12\ba\x89Ӫ\x99gI?R\xf9\xa7\x8e2\xa0*\xcc=\xe4\x02\xa7h\xb2\x87\xff\xef\xf3\xaf\xc1H\x89\x10\x00\x9d>s\x91\b$\xb2b2\\\xc7\x7fg\xcfYDd\xb2(\xe6\xb25X\x18\xb9\xd5$}M\x8a\xc1\x9b\x81\xc7S\xf4\xa4\x05\xab\xaf\xf5\tes\xce\x14\x10\xa8\xf0Y\x92\x85\xcf\xc5C\xce\xd93\x17\x0f\xb9\x9f\xad\xf0\xd94u\xb3\x8bs\xe9\x8fz48\a\x885\xe0\xc9Ha\x93\xf1\xbab8\xfd).C\x1c\xe0\x87w\x1dH`\x81_\x93\x9bO\x8a\xee\xf3ŐTY\xd9C}\xcb\x16\x92)\x057\xf7$_\xcfǏ\xe0\xde\xc3\xc0\xbax\xf7\xe9\x96\xe4\xf2\x05\xe7\v\xc9͙\xf1\x80\xf9\n\x9f\xfa\xffmN\xff\u05f5\xa92\x01b\xa4m\xf4\x18\xc89\x19\x1a\xfcTH\x1a`N\xe88\xef-7P,b\\\xb8l\xfd<\xf4e\x97\xe7\xe7\x0f\xf1\x17\xdfR\xfev\xaf9\xc3*k\xf7\xf7\a\xef\x10ze\b3\xac\bA\xc1o\xe3w\xed:\x88P\xa6\x9b\xb0\xa1\f\xf9\xb2\x9c\x91\x15!\xb3\x9d\x93\x9b/\x1e\xa8\xf6\x01\x98\x93\xb2\xd9=m\xe4\xfcV>-\xb6\xa6\x17]\x04-jq\xa8\x85d\xae\xaaf\xa1D>\x11\n\xaff\xa9\xab\x99\xea\xa2P\x8d\xb6\x1d\xe2v\x80\xd0\xd2k\xfaej$\xfa\xbcq\x12\xa9/\v\xa9#\x84\x00\xa2M\xeb\x06 L\xe6'O\x99+B\xf4\xc1\xf9\xeb\xea\xc2\xf5\x02/\xcdeW\xa9\xab\x12\xb4\xc0\x191L\xe4ɕѮ\xa6\xc9J`\x13\xd5_>\x1e\x13&̢j\xc5\v\xc0ha\xfa\xf4\x9f\x00\x1fZ\xc1\xb3g/B\x87\x1a\x14\xa2\xb9\xc9A\xc0\xfbi\xc1ru\xacX\xb00\x86\x83\x1eNL솄\x84\x9b\x91\x1d\x84\xfa5\xd6cW\xb3\x19\x1b6n\u05c9A!\x01\x10\x8b\x8e\x1b\x80Xwƨr\xf6\xc0\xb8\xecz\x11\x86\xd6ߋ\x02\x9c\x8b\xbf\xae\xd1bW\x91z'x=\x04\x9d\x1f\x7f\xf2\xed\xad[YvSh\xdc\x0f\x86\b\xe3\xec\x8f\xd8=q\x8a\xfb\x19\x8a\x04@g\xce\\\xd2ϸUu\xd8\x1f>|\xe4\xb9~\r\xa2gJ/\xfe\xba\xbe}wg\x80!\n\xeevSh\xdc\xff\x16\x86\x1b\xba\xddXU\x10\x8ad\xed\xe8\x0f\x80آ\x1b\x00$\x04\xfe2>\xd3\xc3\xce\xc6PZ7\xacwN\xb9q\x9b\t\xa0\x9e\x1b\xa2q\xedJ7N\xf6\xc0\x92\xa9\xb0\x9dVݮq\xb2.\x04\a\xa0ĤT7\x00\x91ϊC\xef\xf0\xf4ݝ\x81c\x95\t \xf7\x1b\x9e)\x055Һ\xb2\x1b\xd7x*1[\xb6\xec\x02C_|5N\xcc\x06\x03\xbf\xf0b\xb0\x95\x9d\x9d\xeb\x06 ,T\xb8\x7f8\x02\x88\xd7L\u0084\x00\xbe\xbe\x1c\x9b\x00\xea\xb91\xa3Ԩ\xacwl\xaee\x0f\xbe\u07bdWHr-\x11Eҗ\x00\x03\x12\x89TQ\xd1\x037\x00\xc1l\fy\xd5{\x10]/'\x14\x15\x95Dj\x1e\x1d$\x80d.iډ\xbbs\xcf\x16\xd8]ǔ\x8c=Κ\x9a'\xc7O\x9c\x9d9k\xa1ؑ\x18\xddO}\x05\xfc\xb1c\xa7WVV\xe9\x01_N:5@O\xfa\xec0\xb2M\x8d`\xd7\xcb~\x01\b\xe2\xe6\x7f\x99s\x05R\xa6]\x8d\xdd\xd8\\+\x8d:\x8c(\xbeݻ_\xb4n}\x9cХ\xa9\xb8\xc8~\xcd\rIR\x03\x1c?a\x16\xbd\b7\x00\xc1\xf4\x18\xa6\x00r\x98\x16\xe6\xdf7\x01\xe4Z\x896x\\\xc2\x06G\xac\xde\xee\xcd\xf6\xcbX\xcb\xe7\x1b\f\xe1蠭߰m\xcaԹ\xc0\bL\x88\xa9\xe0Xg\xf5\x85\xef\xe9B<{\xd6\x14A\x00\x9a\xce\xe2\x9b\x13\xb9\xa6\x85\xfd\x02PY]\x1b\xf3(\f\xa30T\x80\x16\xae\x84%O\xee\xb7']\x15Ǯ۷\xef\xc0me\x8bK\xd4q\x9a\xe8N\xc2ߏ\x1a\xae\xf1\x91rұ`\xea\x0f\xf7h\xa8\x014ָ-0\x01d\xd7w^\xcd\xed\x9a\xcd\n\x00b\x06\x8fѪч\xeeT6\xb6۽\r\xbd\xfbB\x12\x85\xec\a%e\x17/]g\xff\x8f\xb9\x1f=\x81\xdc\\\x97\xd1]9\xe9%%\xe5Īa\x1a\x81\xf8ldf\xe6\x98\x00\xf2@\x83\xfa\xca0(cM2 \xc7 \x1cS\xa1\x88jwY\xc4\xe7\xdb\xee۶\xc2\v\x85\x9e\x8a6\xedI\xaf\xc5n\x9a\x97\xf4\x9e\xb8\x12n\xddxҦ\xe1\x00\xa01\xe9\xe9\xd9&\x80\xbc\xe7\xd1\a2+G,rX\xf5\x80!\x11g\xf9tw6\xbeqN\xbbx\xbb\x7f\x17K\xab6\x96\xd0\xf3\b_\xddl\xdc\xd7\xe9bj\xcc\r\xcdA\x17\xfe+\xfdN\xdd7~\xc8|\x99\x03d8\x89\x02\x8e\t /i\x10f\x97,an\x9e_\xcc\x05k\x92\xa2{o32g||УqNRG+\x15Ť\xe4\xb4#GO\xc3\xf5a\xbdc\xcb\x06\x8c\x84\xb6!Φ왹\x87ʓt^\aښ9\xc0%\x8c>\x8f\t \xefi\x10\xf5\xe8\xdfx\xb8͉6\x00\xd3\xdd\xcc\xff2\x94\x8e\xc9ó\xb6.w$ق\xc1\x90\xf1\x06'\xe7\xe9Ӻ\xd2\xd2r\x94\x8a\xb0)\x85ͳi\xf3\xce%KV\x01,H\x17p\xab\x99\xf7p\xb5f\x1e/\xd6̂-\xaf\x94\x0f\xa35sHX\xde06\xff\xf6\xf17\x11ܐ\xef\xa7ݓ\xf6u\xe6\xa9\xfb\b\xf9z\xda\x1b8`\xa4,Np\x0f\xc1\xbb\x84\x01^\xa3\x85e_\x91\x14\xa0\x83.\x1c/X_`\x8b\x0e\x1a\x1f}F\xcfN\x9c<\xa7Y3\xaf\xde\fk\a6\x19v\xee\\c\xc0D\xb8\x126\xa3\n`ce\x16[y\xcbO\xd2-\xc0}\xe0l\xba\x1fkp\xf5䓄cğزu\xb7\f\xbe\x99\xbd0\xefi\x90\x7f\xc39\x81\x91\b\x8d!v\x81r\xc0\x92\xcbŘ\xd94\xb4v\x1az \xf6 \f+\xc5w\xd2\xc8e\xee\xf5\xf7a\x11\xb6\xb4\xb62\x14\x8b\xab2\xfa!\f\xc8\u07b8\x91\x8c53B\x11\xf4\xefX\x16WĬ\x8f\x8e\x8eŎ\x19f\x81\x13d\xd4\xd0ǻ2\xce\x1c!\xcdp\x8c\x16\b*\xfci\xaam<\x03\x93\xbb\xfb\x0f\x1c+~P\x1a\x91-\xb0PE \xed\xd4\xe0f\x1a\x88\U0008d230R1\"\\\x91h#y\xb1\xf2z\t\x12\x05\xb2\xf3w\xc3e?=\xbf\xbd\xda\xe7\x06\xfa\xa6\xacֶ\xb6\xb6\xba\xfa\x86Ǐ\xabKK\x1f\x92ueddC,\xbcp\xf1\xea\xe9\xd3\x17 \xbb\x1d\xaa|\xdc\xd6\xd6\xee\xf6bL\x00\xf9\xdc\xc9#%\xfe\xfb\xcd\xe9o+\xdd\xe7\x00\x9du\xf5\xfd\x1a\aΕ\xd4\x02p\xceb\x81C\x83\xccM\xfd/\xe4\x1e\xcd:\x81\xc9c\f#\xc4\xf3\x16N\x04\x87#tlΨ߫&\xce\xc0\x02H\x0fB\xd8\x00\xea\x9b\xf9>y4s\xe8\xf2[d\xdc\x18\xbf\xa1ͳ\xeaz)\xba8\x88Dy\xfaT\x0e\x8eG\xb3o\x90\x05t\v\xab\x90\xe3P\xf9\xf0+\xf4a\x1bB\x00I\xc0\xc0\x13\xe3\xd5`}wG\x19T\xc61~\x13\x1d{\x84\x9b\xf8\x11b\xe4\v.\x14\xeeL\xad\xc0'\xebaC{\xa7\xc5\xea\v\xc4\xee\x1a\x17\xf6\x97\xebf\xf3\xa1\x8a\xe4\vR0\x019\x9f(\xbesb\xcb\xeaۆ>\x02\x95ֵ\x8e\n\x9d\x9a\xa4D&\xfe+R\xf6x4\x13\xa2\x90\x98$\x01\xff|\xcf\xed\xe8\vE\b:\xc5\x17ס2\x86\x9a\x9d\x7f\x8ff_\xf2?6\xfb\xf0\x00\x99\xcdE\xd6ȋ\xb8\x8c\xff0\xcc\x03\xf0^\xc5v\x98\xf4\x80\x0f\xf9\xe6\xe4\xf2I\xc7\xf2\x91\xfa\xc3U\x93\xf3)\x9e\x8a\xac\x004\xc5\xed\xc1\nw\x86\xcc\xf2\x12\x99\xcb\x7f^p\xfd\x83\x90z\x15\x8er\xf1h\xd6\xf0\xa4\x19\xeaFk\xeb\xdd\b%\vG'\x8e\xaa7\x8a\xad\xf3\xce\x15lH(æ\x99\x85\x0f\x11;c\xb1\xa0\xd7\x17\xef_\xb3\xc7\xc5\x14\xdcfP\f\n\xe2\xb0\xf9\x83B\x10>\xce\xfa\r.\r\xa6\xc1H\xf7\x01\x05\xb4\xd2\xd0\xff\xffQ3a\xcd\xfbdW6\x9ay\b\xf2\xbdap!~K\xb9j\xaa\x0ef29\x03\xf7##9\x94\x00r4V_t\xe3\x8c\f\xa2?\x18\x18\xbf\xcb\x1e\x8f\xe6\x98\x1ea\xca\xf74\x8f\xe6\x04ݣ\x99\xbfNn\xfe\xe1ڔ\x8f\xb6e~w wꉻ\x88lB\x9bD\x06?\xa1\xb8\x0el\x95)\x83憶\xae\xd6\x0e\xdan\xc3 \x06qQI\x049\xb7O\x95\x893\x10A`\x0fUZ\xe4\xf1\xd0:\xe6c\xc3{D\x7f\xf3\xe3\x1dY\xbfݐ\xc6\t\xd1\x1d\xabE0\x94\x93#\xea\xec\x9eRڣzl\xc8\xe2\xbfݟk\x0fV\xf95\x94\x9e\xa9\xbc\xbd\x0fצ\xf2\xa2?\x18,\xcfT\xaf\x1e͜2Q\xc0\x94X%\x96\xf2\xbc*\xf1\x95\xe63\x87\\&E\x84\xbf\xef\xcc\x1as8o\xf6\x99\xfbK/\x17\xaf\xbeQ\x8a\x80!\xc9\x16\x17\x86\xfc\xfd|\xfe\x13\xf2\x03\x84\x10\xb9Z\xc8\xea\"\x8dX\xd3\xdc\xc1G\x9c\v\x89N*\x92\x89\\\xd4\x17]V\xe2\x1c\a\x99Y\x97\xc5\n\x1c9\xf8\xa6\xd3⸧S\xfdT\x1b=贴vZ\xf8E\x84\x16y\x12\x143K\xeb\xda0\xf3\xcey\xd4t\xab\xecY|Q\x1d\x8b\v\x0e\x18t\x15w\xa5U \xa2\xb8.\xbe\x14y\xcd9g\xb4\x10\x82\xc3\x1c\x89 QDL\x9c\xc5~\xba\xc7\xd7\\s\xeb\x8dw\x04\x15%_\xecv6z\x95]\x17\xff\r\x04=\x87\x18@\xc6\xd6\x18\xfa\u07fc=04j(e\xb9\x93\x8cn\xb7\xc6S\xc9R\b\xc2\xdeU \x13-i\xaf\x8e\xcc\\\xa4w\x94\x12>\xbf\x8ex*\xb5\x06\x8a\xe9\\H\x16\xcd\xdfn\xb8\xc5{\xfcݦ[\xe4d\xb8Wa\x16\xc35\xfec\x9cv\xfcaK\xcf\xc1\xfd<\x80G\x92p\x80W~\x91_\xe7I~\xb5\xfa&\xfa\xe8\xef+\xb5W\x96\x12\x90\xed\xeb5\x88n\xbah[\x1b\x15\x86]\x14\xaec\xfa\xa5\xcf/\x00\xa2\x970\x94K\x98\x1b\x86\b\xb6,\x1f\xe4Cr\xf6\xc3֠\xf9}\xbfB\xcf\xfa%\x19\xa9\x1c\xc1E\xc1Y\x90\xc7U\x7fG;\x12\xe4x[\x0e%*\xfd\xf6R\x97C\x1e\xf0\xae2~w\x88M;\xa10\xd2c\xd3Ы\x8f\xf3\x80\xf8o\xc4$\xe3kC\f\x0e\v\x00\xe9\xed\x1eb8\xcb\x01\x8b\x05\x1f#\xb9N\xc3\xda*p\x94\xab/x\xbf\x8e\x15\x83\xa1x\xdfW\x03\x17\xa4\x89\xed\xc1\x1a\xb8\x84\x18@\x8c`\x92\x9d\n\x96Y\xec\xc9\xf2Dt\xddaNh\xda~\x85\xa5\x03\x10I\xd8\xd0\x03HWA\xa0\r\xaem,\x9dE?*\x10$\xf9R\xd1!z\x9b\x0e\xceahb\xc7\x165\\\"\x10\xb4ԣ\xc7N766\t\x86$\x14\xf1\x15\x19v\xf6;\xbf^\x9d\x02\xdeI\x1bG\xae0\xddR\xc3\x04@Z\xe9?\xbb\xa21<\x92h\x05\xe1̬\x1c\x14\x80\xa5\x1d\r5\xc7\xc8\xf8\xa1\x06\x83\x833[S\xa0\xa3\x19\\.M\xe81$4/\xe7P\x1c#U\x10*\xa9k\r\x97$Zn\xb0a\xe6\xccY\xac\x8b\xad\xdal.\xad\x19\x9b\xaa\x18\xc5^+a\xa3ˮ\x84\xfd\x1a{f6&\xef\xc7$\x9b`\x1ad\x17_\xf6\x86\x14\x1a\x1a\x14_t\x88\xeb@:\x99\x86\xaf\u0601\xff\xfd\x93\xef \xfe]\xberC\xa4\b%\n\xb99\x86PmÐpk\xf2Ch\xaf\x1f(&\xb5\xe6n\xa9\xc0\xf4s\x13L\x83\x92\x00Qz\xf8xg\xd6Pv㽦\xd2\xcc2ϛ\xbf\x14E\x1f&(bb\xd7{\xeaϻ\xf5\x8a\xb5\x9e_sǵ\xc2Z\xacR\xbf؛#\xfb\xff\xd7TkBZ6\x11og9$\xe8\xe1<\xff\xd3\xfck?\x9d/\xb4\xf7\xc3\x021\xf4K\x98\x04\xa1\x8b\x17\xafA\x00Ey\x9eaS\xa8\xa2^%Qm\xdeF5\xf8/\xad\x83\xc3Y\x8fI\xba\xbfڛC\t_l\xb9F8\xbb\x80?s\xfa\x82\x9b!*8\xdcH=\x85\x93I\xbc\xfff\x7f.\x8c\x06{?,\x10C\x0f \x894$\xd1dBp\xcbǏ\x9f\xf9\xe9g?\\\xb9\x12o\xf76\x96```y\x01\x13\xff\xa1\x83\x98Z\xda@\xabh\xd6\xe9\xfb\x7f\xd3Z\x86\xb7x\xf3R\xfb\x7fMY\x83\xbf\xe7\xb4\x06\x7fiݜ\xfbĐ\u1311tr\xd2\xe8\xbf2\x02\xda\xddo\xc2\xe4\x80$\xd1\x0eQ\x9f\x9c<\x18\xe6\xcc*0\xa5\x85\xcb\x13lv\xbb\xef\xc9\x04㬪\xcc\"zZ\x88\xf3\x7f\x1a\x994ՙ\x13B\x18\x84*%\x0e\xa9tF\xc9\x04\xa5\x7f$)\xd4;\x8a\xab\xa0\xb7\x8d<;\x03\x11\x8d\x15\x97ƻ\xd8hJ\xb0\xe1\x007\xb0_\xe0\xbd\xd0$\xb6:\xb3R\x9b-\xfc\x00\xa4_\xef\x15+\xd61\xd2@6\xcdrv\xf5Z\x82[\x10b]C8\x87ᛎ\x8e\x0eo1\xc9\x00&\xabw~\x1d\x1f\xa0ږ\x8e\xf4\xf2g\x84\xa8\xad7\x1fF_,\x82\xdb@\v\x93\x85O\x8cQ_\xef\xe9Z;\xa80\xdeMw\xbdz\xed\x86M\xcf\xc1\xad\x91\xa2\xbfT\xb7\xb8+Xэ`\xf9,\xf1f9\x15\x9f\xec\xccf\xa6\n\x9e\x10\xe3\x0fF\x12KH\xbcj\x06\n@\x02\x14\xf0!\xa2\b\xace\xachn\xa6\xe0%\xa5\xe5\x8c\xc20\xe6\xc7\xcc2\xce\x1b\x88\xe8\xc8\x03<Ò\xcdP\x020\xb26\xbd\xe6U\xf05AUy}\xdb\xedGM'r\xaa\xe1\x03\x89\xf5\xee\xf7\asY\x04\x19\x83\x94H\xae\r\xac9\x1dw\x05^\xba\u05een\xb4\xab5>uj\x9b[\xd73\xc6\xcd\xe2\xd9\xff\xe1\x88\r\xbd\x1e\x9e\xfdT\xbd\xa1\xab\xfcx\x85Ρ\xbdx\x1d(\xb2\xdb\xe0~(\x03\x98\xad\"qAw\x1d\xb6\x10tU\xb8(\xb5-\x9dn딯S\x17\x86\x11H{\x95۶\xedE߄ \xc4ׄ\xc4\x14\xbbA{\n\x05x\xc6\xfc\x00\x90\xb8С\xa98g\xeebD\xe3q\xa4\xa7%b\fKv\xc3T\xa1\x1b\x9eܨ\xab\xfe_\x12\x85\x03N(U(>\x8b\xa9e\r\xd7\njY\r11]r\xa9\x18\x84\xd1r\xc1k\xf7\xa3\xed\x99\x14\xa8 `\xc0m\xe2\xe3+\xae\xdb\\\x9e\x11юU\xd2\xe1\xef\xec\xb4x\u0590\xa7\xc0\xa7\xf0\x17/c\xdd\xd00\xde\xf2q\xbc\xa9\x10\xa0\x0e\xc7o\xbd\xee|\x9e\x11\n\x13b\xd6,\xc4p\x1e&\xfd\x1f\xc0\x01\x1b\x04f\b>\xc0\xf0\fI~g\x9e\xba\aJ 0\x01\x14\xfaE\xbc#\x06\xa4:\xbb\xfd\xd1\xc6\a\xc2\x1ek\xc0\x01\x84^\x9d\fk\x82\x12\xb4\xee\xa4B\xad\a\xa1͛w\x1a57\bW2\xe2\x0e\xaa\x90\x0eھc\x7fVV.\x12\xa7m\xed\xed\xbe\xd2&ϑBO\x86y\x9fF8xd\xa72\xdae\x1c\xfbq\xe3\v\\v\xb3\x1f5A\x15\xc5G\x9c2:S\x94[\x92\x1fB@\x03s\xc8\xfb!\xf27\xeeH\x1e\xeb\xe6W\xfbr\xd0\x02\xf8l\xf7m Hf\xc6A\xb4\xd3\x0f@Il\xe0\x1bRW\xf9)\x0f#\x1d\xa1(\xcf/\x123&\x1e\xcd\a\xc1duP\xc9 \a\xc3e\x80\xf7\x8d\xa3/\xbc6JeEOZ(\xe2\xc3G#\xb8\xf6\x9a\xf6\ua7e8\xc1\x191\x88\x1a\xc8'w:\xcc\x1f\xc1a~\x8c\nB\xe3\x92o\xder&:\xda\xfb\xba{\xaf@\x86\x88=]\xe8X\xf5ą\x8e\xef\xc9\xc1\x99\x1c=}\xfa\"3\U000153ebp\xab\xb0\xf9\xd6\x1f\xf23]cĖ\a\xe5>\xc4^\xbbF*t\xc8/\xa4\xfb'\xc4\xe6|\v\x83N\xba\x1dX\x00\xe9\xea>\xf3\xe7/\x13{\x00T\xa4t\x0f\x03\x87y\xef\xaaM_x3\xae\x130\xe9ы5N\x84̸\x93\x9c\t\x9f\x14\f\xa0\xae_Oʾ}\a\x19r\xc4\xf3|\xb9\xefx\x9bR\xedż\xc9\xe6a\xf1l\xf16\xe0\xa1\xc3.h\xb3\xdc@\x98\xf6a>L\x125\xd0\x7f@\xe0\x92\x91q\x9b\xf0#\xd2\xff\f\xff\xea\xbb-\xbe!&\xf5\xaa\x7fh\x947\x90\x9c\x89\x91u~K&\xd2\xd1s\x992e.\x90Bƀ\xf9\xe2\xb4[Y\xcc#\x97\x95U\x90c\x81\xdd>5\x83\x03\x18\x18\xec\xeb-\u0087Ԣ\x06\xe1o\xc8ju\xee\xfce\xae7\x17~\xd5\xeaͮ%\xc76ҝ>Yax\xba<\xb1\x0e*H)\xa9\x8d/Pr\x19G\xc0\xc3Όȇ^\x02\xb2\x9e\x84+lȮ]KD\xaf\x93\xdd\x1fsﵵu\x988\x91\x93\x012\xeb@\x0e\x92\x9a\xb3\xf1![\xcb\xe8o\x88\xde\x05\xa2\x99\xfa'^a\xebJ?=\xa3)\t\xf2 \xcb\xc8\a\"!e\x14,s\xb5\x0fss\x10s\x98\x88\xb9\x1e\x93P(;v\xfc\xac\xddT(\v\xe1ZƩ\xecr\xba-\xeb\xfa\x873\xbd\x99Z\x86\xa5{\xc1ԾX\x86i\xc5-\x9c\f\xcd%,\xc4I\xa5qG*\x1fM\xea\xd4l\xd4Y#\x86\xa3+\x8f\x7f\xb7\x1e\x966\xd9\x0fF\xde\"\x165$\x7f\xb5SM\x04\xbb\x9dP@\xb5q\xd3\x0e\xa8\x8c^\x9d4\x86/\x80X\xe9Ȗ\"\xd5snh\x00D},\xf7q3\xa3\xe6v\xd7i\x12v4\x94\xad\xa7L\x9d'\x9a\x84\xec\xa1\xf4\xecdXȊ{]\xefșȻ\xd1\xcc3\x01\x14\xb22\xbc]M@CL\xa9Ut8g\xb1ՑP\xb3Cf\xffL\xefb\xfeO\xcbI d\xfb\rAVw\x8b\x1a^\xc1IL\vi\x0f\x9b\x00\n\xddv̩Ή,\x01\xfdp\x1dX\x16\xab\u0378U!o())KIMߵ\xfb $kdʼnLNg\x16\xf6\xd5S\x8d\xf1)\x8c\x01\xa4\xbdN\xf6\x9e&\x80B\xbc\x8a\xf1\xf5za-\\\x88o\x0f\xe4f\xa9\xd96\x81Q\xb7\xd5\xca@\x99ۦ\x97SO혲ޙ\xb3\x97\xe2\xe2\xf6Pe\x113@\xe9ދ4\xbd[y:\xacP\x85_\x8c=\x12]/\xa3\x86\xf0o\xeb\xfa\x8a\xffm\xde5\b\\\f\xf7@\x9c\xb0;wgΞ\xa2w\x01h\x8a\xbf\xccP\xdfɻw\xfa\xccE\xac\xec(\xe5\x01\x1ar&\x82\x93\xb3\xe2\xfbA\u00980q\x1d\xf1F\x85\x1c\xee\x9c0\xf1G\x88\xdes\xe7-\xa5\xdfGػz5\x01\xea\x88=roQa\xf2:$\x90p\x95\xe7\x9c)0j\x96;\x94\xa9\x94 \xabhFs'\xa4w\xa4}\xe1\x93g<|\x06m\xd9\xdd\xe9\xd7\xeeA\n6\xb0\xba\x02\x8cU^\xd7D@\x06{\x89I\xedg\x8dM\r\r\xcfȺH\xe4\x89gr\xb0Id\xd1\x04\x85\xad\xad\xad\xd09ܶ\x90&\x80\x06)\x0eI>\xc4\xf4\xa4\x9b\xbe\xa2\xae\x19\xad\r|-M\x90ygF\x1a\xd0\x1cb\x9c\x1eY\xe4\x1d\xa9\x15\xactd߾.\x96Ńcߣ\xfbl3\xda\x1bxa\"\x06\xf7v\xfa\xf3뾖{\xcfA\x94\x00'R\"\x1f@Ƶ\f\x95\x05\xd62_\xa3\xef\xfaȩ\xcc܈ت\b\x0e1\xf6E9\x80\xc1(\xc4r\xf1K,x҂\xd2\x1e\x12\xbb\xfe/\xa2W\x9f\x80\x1e\x84\xd9\\\x10\x16 \x93\xb5ϰ\xf0=Ob\rcJcT\xb8\xbd =\x0e\xad\xb8\xfa\xe05\xe5\x98\xe1_\xea\xd58\xfb-\x827\x82']w\xfc\x83\x95\xc9\fy!\x1c\x8bG\xc2\xc6IJ}\x19\x95\fR1s\b\xb0\x98\xdd\xe9\xebp\xb8W\xe3\x01\xb7\xc3uR\xc2\xcb\x114\t\x9fW\xab\x8dM>\xef(\xa8i\xc1)\x8by\\\xf41\xd7*]i\xbe\xe1\xed\xd8\a\x9du\x1f\x15\x86\xa0\xb69\xed\x9e\x0fdT\xca\b\xa9Lm\x06.=n\xd4\xee\xd0\xe4\x98\x15\xaa^uJ03\xbfG\xdcbh\x10`isz;\xb3Q\xdaf&\x8b\x81,\xf2*\xfc\x12\x90\x18't\x91]\xb1\xf5C&\x1c\xee\x80e Y\xd3<9\x7f\x02d\x10)i\x11\x96Զ\x82ot\v\xcf\xe6\xd5\xecN{\x14s\xad\x04a\t>\x00\xcc\x13\xf2j\x7f\xbb\xf1\x16r\x00\xbc5Ό.*\xcd[C\xa8%\xab\x1fJu\x11\x05 \xe3\xde>\xfbQ#\x06PohR\xf3\xc0(\x18\xe1\xe9Q\xdeT\x16Du\xe0]}R\xd89\x15*\xda\xef\xdc\xcfc@ؿ\xaeM傑\xb3\xe3\xe2\xc0X\xe0?\x18\x05ܛ\xc3\x18!s\x80\f\x86\xa2\xac\xb3\xf8R\x11\x9f~&D\xd7%\x94Q\x0eݔX\xce\u05f8\x94\x87\xdbR*\x10\xce\xe2\xbf\x1b\x12ˈ\x10\f\"\xf20F\xf7\x81)\xcb+\xbf\x0e \x98*d\xb6\x90Q\xc3?o\xd3fa\x99:\xfd\x8f\xf5\xa9\xa4t\x1fh\x8a\xf4I\xba\"\x82\x98\x16\xa83\xa0IQ\xf3\xda\xdeS\x03\xd7\xef\xc7$\xb9\rA\x97+ߝA΅\xc2\x14@\xc6\x1a#\x1f\xd0\xeb\x85u\xf8\xf4h\xe7Թ\xa8\xf5_dC\x97+p\x9bKwĭ\x15\x8eqt%+\xae]\xb9\xb7\fC\xe9\xfa$\xb2\xb8/\xba\x1d\xaf\xaa\xc3\xf3~\x1e\xec6\rͧ\xe2-\xa5P\xae$\xc951r]\x91\xdeSW\xc4(:>\xcaU\xf2\x87\xa7\x02\x91f\x0e\xe4\x1dC\x12\x92\xf9z\xb3\xa4\x81M>'\x94=\x1a'}@\x05:=\x95Žk!\xf8֙\xf7\xa5<\xefyx*\x91\xf7U3\n \x92\x12\r\xfe\xfa5\f\x00\xd4\x03#\xe7\xf7EO[IV\x185\x97\x1a\xe3\xebZB\x93\xa4'\xd1/\xa1P&{Or\xa3!ɠ\x87\r\x80\xf4B\x8eչI\xc3\b\xe7^u3N\xab\x84n\x92\x95W\x9d\xdbxG\xb9\xe8\xa5\x11T\xe4\xcd\xf2Ƒ|\xb0\a\xab\x14\xfe\x12\x01Hnm\xed/j\x9e\xd4\x19'\xe1+\x1aڮ\x14\xd4\xe2\x18\x02=\x8dd\xe2U\xa5\xbd\xe2\xa6~\x17\x91\xd2w\"*\xf5okS\x1d䅡\xa8\x15\r?\x00\xd9\x15\xe7\xf5Ν{\xc5%e\x16\xd7\x0e%\xb6\\\xb9\x95M\x10\x8c\xa8C\xb2i\xfa\xf7u\xa9\xba\xfa\x1d+\x1dߓ\x9f\x1a\x8b\x90\xc3\x1aR\xbc~\xf6k\xec\xde\xfb\xe3\xb5\xf3\x92\x02Ȯ\xfa\xeai\xb72w\xee:\x90\x92\x9a\xc1\x18\xb1\xd7b\x12U\x1c\xd4\xef0rc\x17\x8d\xb38\x14\x11p\xf3\xceR\x87\xee\x9d\x06)MM\xd1K\xf5HOl\xc3M+\xd3\t}\xad\xb8%\xfbAV\xf0!\f?\xc3\x15@z\xb3\x80F7\xea0\xb4\xc7\xf7\xed;\xf2\xa8\xb2\xca\xc8\xf7s\x9d<Ӿ{\xde\xd1Mm\x10\"6:QTe\x80\x14\"\xed\xb0GF\xaa\xa2\xcb\xebN\xdf\xcc\x11j\x83\xfd\xf6R\x87\x9a\xa2\xa7\xad\xd8\xfb^\x05\x15\xfb\xee\xe64\xca\xef^\xcf薧\xeb\x1f\x8ep\xfa\xa3s?\xc5O\xf4k\xbb\xadC\xdc\xe4\x18\xae\x11\xc8\xee$g\x01\x14\xf8b0\xb9`\xde@\xeb9r\xf4Tn\xee\xddz5C\xe3(\xffk~\x94\xde\xd3Kv.5\xcd\x18P\xb6RzF\x99z\xe5\xb5\x12\x18#\xf8\x1a\xa3\x1a\xf6ǭ\x19T\x11G*\x1br]\x8dPRu\xa9\xe5hU\x1cU\x1c\x12c9w?9\xa7\xa5\x9c\x9b\xe3\x98Ѥ\xc2he\xf7\xee2c\xb5)\xde\xe1\xd7\x19\xed\xf0\xeb|K\xe9\x1fRr\xc4\x04\x13\xe8\xb3cG\x97]ޓ\xcd6\xc4Ê\xc3\x18@v\x83T\x1e\x14\v\x845\xbe\xfaf\xc2_\xff\xf65L.X;\x88ȜS@\xf4\xa2\x8e\x8cR\x1d\xee\xbed\xee\xd8_\xb2>\xc2X\xa2\xc9\xc0\x96\x10GK\xbd\xa6\xa0[\x1d:\xe0\xb5\xccaW\xc8O?Pf\x9a\x94\x9eA*M\x15\x9e\x04\xd3LP\x82N\x1e\xb2y\x8b.\x15!e\f\xbb7\xf1A=\x9d\r\xf4\x0f\xdd\\\x82\xf5\x86\x8f\xd9L\rA(r\xe81>\xaeBc\n6\xa0\"\xaajrAP\xbdȓ\xc4\xf6E\x1e\x86\"\x8bW-3\xd1\x13\x96p\xe5\x1f[n\x05*\x84;q\xd6%\x7f\x17O]Vɲ\xba6\x90\x87\x9e5\xcb%\xd7>\xf3a\xa3\x1c\xb0\x97hW\xa1\xd1\xcc\xfd\x98\xee\xd2\xf3\x12;_r5e\xe4\xab9\xf7\xdaz\xfbs}\xd2{4\x01ԧP\xe48\xa9\xb9w\xee\"\xa4G\x1c\x82\xe6\fK\x90\xa5\r)\x16\xc4:姌\x98M\x9d6\x0f\xbd\xa9\xe3'\xce\"]\x8dB^UU5\"?\x96\xde(\xa7\xb6\x1eF\x91\xd5\xd2C\x15\xb2\xf6\xd8ʇN\x81\u038d\xf1c\rc\xa5\xb3\b\x01\x90\xa1\uf85dg\xa4\x9dRS3\x18\xcc`$\x03J2\x19\x12\xa4\xe6#GOs\xc9)\x01,[\xbe\xf6/\x1f})\xd3\x1a\xdc\x0f3\x15\xa6=\x83\x8b\xc8L!2|\xec\xf8\x19\x92\xaa\xcc\xcc\x1c\xa4\xf8\x8a\x8a\x1eTTTB;D\xcb\f\x19\xa9\xfe|\xf0=\xc4\x15\r\xbc\x0e\x9b=\x94\xe83\x01\x14\xaa\x15M`\x842\x86\x1a\xb3ר\xf2(\xe7?{\xa6q\x1e\x8e\x1f?\xcb\x02\xa7OM\x10\xab\x18\xcc`\x1a9)\x89R\x00n\xe6̅\x04\xb6m\xdb\xf7\xa2nn\x8f\xc4\t\xc3\xff\x0f \xbd\xb9w\x96\x1b\x973\x00\x00\x00\x00IEND\xaeB`\x82"), "InfomaniakAPI": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\x00\x00\x00\x02\x00\b\x06\x00\x00\x00\xf4x\xd4\xfa\x00\x00\x00\x01sRGB\x01\xd9\xc9,\x7f\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\v\xfca\x05\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00 \x00IDATx\xda\xed\xddw\x9c\\u\xbd\xff\xf1\xd7\xf7\xcc\xccf7\x9bM6\tI\xe8\xbd\x06\x14\x10\x90\"UE\xa5\b\x88\x82\xedڽ@6$\x04P\x01\x7f^]Q\xef\x05\xe5\x06\b)\x80\x1dlTi\x1a\xb8\b\x84\x0eR-\x04\x84P#\x90\xde6\xc9fwg\xce\xf7\xf7Ǣ\x04H\xd9$[fμ\x9e\x8f\x87\x0f\x11dw\xce\xfb\x9c\xc9\xe7}\xbesΙ\x80\xa4\xf2\xd6\xfcT\x81\x81\xdb\f\xa3.?\x1c\x92\xe1\xc4\xd0H\xa0\x11\x18\xbc\xd2_\x0f\"PO\xa4?PO\xa0\x06\x18\x04\xe4\xdf\xf8\xef7E\x06\x10B\xe1\xad\x7f/v\x10X\xfa\xb6\xff\xdf\"\x02%`1\x91v`\x19\x81\xe5D\x96\xbd\xf1\xcf\x16\x11c\xe7\x7f\xc3BҸ\b\xd29\xb4\x15\xe7\xf2\xcc\xf49\\\xbewѝ'\x95\xaf`\x04R\x1f\x9a\xb2t\x18\xa5\x9a\xcd\t\xc9\x16\x84\xb0%!lN`s`3\"Áa\x840\xac\"\xb7-ƹ\xc0\x1c\x02s\x89\xfc\x13x\x95\x18\xff\t\xf1eB:\x93\x8e\xb6\x7f2\xb6a\x9e\a\x81d\x01\x902x\xf6>-\xc7\xf0\xfd\xb6$\xe6\xb7'\t\xdb\x11\xc3\xf6\x04\xb6#\xb0=\xb0\x1d\x84\xba\xea\x0e(\xb6\x12\x99\x01<\x0f\xcc \xc6\x19$\xf1y:\x8a3\xb8\xe7\xa6W\xb8\xe6\xc4ԃH\xb2\x00H\xe5m\xfc\xf2M\xe9_3\x924\xecJ\b#\t\xecJd\x0fB\xa87\x9c\xf5ZAh\af\x00O\x11\x99N\x88OAi:\xb3\x1fx\x86\xe6CK\x06$Y\x00\xa4^>\xab\x7f\xaa\xc0\x88\x1dv$\xe6\xf6\x82\xb0\x17\t{\x11ٓ\x10\xfa\x1bN\xaf\x14\x83\x0e\xe09\x02\x8f\x91\xc6\xc7\b\xe9c,\x9d\xff8_\xdfx\xb9\xe1H\x16\x00\xa9\x9b\x86\xfd\xb4\x1c\xc3\x0f\x18I\x92ۗ\x18\xf6\x03\xdeK`\x17\by\xc3)\xabVP\x04\xa6\x93\xf2gB|\x88b\xe9a\xee\xb9a\xba\x1f!H\x16\x00\xa9k\xce[0\x90\x81\x03\x0f\x84\xe4}\x04\xf6\a\xf6&\x84\x06\x83\xa9\xc8R\xb0\x84\xc8#\x04\x1e\x82\xf4~\xda\x17\xdf\xc7ء-\xe6\"Y\x00$\x980\xbf\x81\x9aA\xfb\x12\x93\x0f\x128\x90\xc8{\xdfq\x8b\x9c2\xd2\ab\t\xf8\ap\x1f\xc4?ѱ\xfc.\xefB\x90\x05@\xaa\x16ͯ\xd51l\xf8\x81$\xc9\xe1\xc0\xe1\xc0\xee\x84\xe0\xfb\xa0:\x1bA\n\xfc\x05\xb8\x1d\xd2\xdbY\xfe\xfa}\x9c\xb1\xc5\ns\x91\x05@ʊI\xed\xbb\x13r\x1f&\x84Á\x03\t\xa1\xd6P\xb4\x8aB\xd0J\xe4^b\xbc\x1dJ\xb7\xd1T\xf373\x91\x05@\xaa$\xe3g\xd6\xd2\x7f\x93\x03I\x93\x8f\x128\x8e\x10\xb64\x14\xadG!x\x99\xc8m\xc4\xf4\x16V\xbc~\xbb\xab\x03\xb2\x00H\xe5肖\xa1\xd4\xf5?\x96$\x1c\x03|\xd0{\xefս] .#\xf0\x7f\xa4\xf1&\xd2e7q\xea\xc0\x05\x86\"\v\x80\xd4W&\xb4lD\xbe\xff\x91$\xe1\x04\"\x1f\xf6\xe2=\xf5R\x19(\x11x\x884^C\xa9\xedj\xc6\xf4\x7f\xddPd\x01\x90zڤe#HjO\x84p\"\x81\x03 $\x86\xa2>-\x03p?ī\xa1\xf5jF\r\x98k(\xb2\x00Hݥ\xf9\xb5:F\x8c8\x9a\x10>\uf67e\xca~e \xc6+\xe8X\xf4[\x9f9 \v\x80\xb4>Nz4\xcf\xee{|\x84\\\xf29\xe0\xa3~i\x8e*\xac\f,'p\x131\xfd\x15\xb3\xef\xbb\xd5\xef.\x90\x05@Z\x9bK\xdav\"W\xf84\x81/y\xf5\xbe2R\x06^'r\r\xa5\xe2O\x19S\xf3W\x03\x91\x05@\xfa\x97\t\xf3\x1b\xc87~\x8a\x10\xbeD\b\xfb\x1b\x882\xdc\x06\xee'Ɵ\xb3d\xe1U\x9c\xb5\xd1R\xf3\x90\x05@\xd5iR\xdb\xce$\x85/\x128\t\xc2`\x03Q\x15\xad\n\xb4\x00\xbf%-Nft\xcd_\fD\x16\x00U\xc1\xd9\xfes5\x14\xb6=\x16\xc2I\x84\xf0A\x03\x91\xe2c\xc4x9\xb3g_I\xf3\xa6\xad\xe6!\v\x80\xb2e\xfc\xf2M\xe9_\xdbD\xe4$B\x18f \xd2;\x8a\xc0\x1c\"\x97S\\1\xd9g\v\xc8\x02\xa0\xca7\xb9\xfd=\x84\xfc\xc9\xc0\xe7}\x06\xbfԕ\x1e\x10ہ\x1b\x89\xa5\vi*k\x02K\x89L\xa2\xb4\xf4\x87~E\xb1,\x00\xea9\x13Z6\"_\x7f*\x81q\x9e\xf1KeV\x04R~Fl\xfdoF\xd7\xcf6\x0fY\x00\xd4=Ο7\x80\x81\x83GC8\xc7\xc1/U\xc0\x8a@ے\xffa\\\xe3b\xf3\x90\x05@\xeby\xc6\xff\\\r\x85m\xbf\b\xe1\\B\x18a R\xc5\x14\x81\xf9\xc4\xf8#Z_\xbbػ\x06d\x01Pם\xf4h\x9e=\xf6\xfc\x12!|\x9b\x1067\x10\xa9R{@|\x854~\x97\xb9\xf7\xfeү$\x96\x05@kvi\xf1\x83\xc4d\x0f!1\x10)\xf3%\xa0\r\xb8\x98E\x8b~\xc0\xd9C\x96\x98\x87\x05@զ\xf9\xa9\x02\xc3wn\"\x84\xef\x11B\x83\x81HUW\x04\xe6\x93\xc6\xef1\xe7މ^\x1f`\x01P\xb5\x98\\\xfc\x00!\x99@\b#\rC\xaa\xfa\"\xf0\x04ii\x1cM\x85{\xcc\xc2\x02\xa0\xac\x9a\xb4b;\x92\x9a\xff!\x84\x13\fC\xd2ۊ\xc0-\xa4\xedci\xaa}\xd1,,\x00ʊ\xe6\xa7\n\x8c\xd8\xf9\xeb\x10\xfe\x8b\x10j\rD\xd2jJ@+il\xe6\xc9'\xc6s\xf9\xdeE\xf3\xb0\x00\xa8\x92Mi߃\x90\xff\t\x84\xbd\fCR\x17\x8b\xc0_\x89\xa5\xaf2\xaa\xf0\x88YX\x00Tqg\xfd\xaf\xd51b\xe3\xef\x00_#\x84\x9c\x81HZ\xc7\x12P$e2q\xde7\x19=|\x99yX\x00T\t&w\x1cL\xc8\xfd\x98\x10v4\fI\x1bX\x04^\x80\xf4dN\xc9\xff\xc9,,\x00*\xdb\xc1\xbf\xa8\x910\xf0|\xe0?\t\xc1}+\xa9\x1b{@\xbc\x86e\xcbF\xf1\xb5\x86\xf9\x86a\x01PY\r\xff\xe2GI\x92)\x1063\fI=T\x02f\x13\xe37h\xca]a\x18\x16\x00\xf5\xb5\xce'\xf9]\n\xe1hÐ\xd4KE\xe0F\x8a+F1\xa6\xff\xeb\x86a\x01P_\x98T\xfc\x18\xb9\xe4\xc7\x10\x86\x1a\x86\xa4^.\x01\x8bH\xe3(F\xe7~g\x18\x16\x00\xf5\x96\xe6\xd7\xea\x18\xbe\xf1y$a\xacaH\xea\xe3&p%\x8b\x174q\xd6FK\xcd\xc2\x02\xa0\x1e=\xeb\xef؛$\xf7k\xaf\xf0\x97TF\xab\x01/\x12K\x9f\xa5\xa9\xf0\xa0aT\x0e\xbf\xfd\xadb\xce\xfa\x9b\x03\x93K\xa7\x91\xe4\xeew\xf8K*\xafSɰ\rI\xee\x1e&\xa7\xcd4O\xf3\xb9#\xae\x00\xa8\xdbLlݒ\\\xbf+\b\xe1\x10ÐT\xe6\xab\x01\x0f\x12\xdb?\xebw\n\xb8\x02\xa0\r5\xb9\xf8\tr\xfd\x9ep\xf8K\xaa\x90Հ\xfd\t5O0\xb9\xf4Y\xc3p\x05@\xeb\xe3\xbc\x05\x03il\x9c\b\xe1s\x86!\xa9B\x97\x03~\xc1\xe2\x05c\xbc@\xd0\x02\xa0\xae\xba\xa4m'\xf2\x85\xeb\ta\xa4aH\xaa\xec\x0e\x10\x9f\x85\xe2\xf1\x8c\xaay\xca0ʋ\x1f\x01\x94\x9bI\xc5c\xc8\x17\x1ev\xf8K\xca\xc6if\xd8\x11\xf2\x0f2\xb9\xf8\tð\x00hU\x9a\xa7嘒\x9eG\x92\xdc@\b\x83\fDR\x86J@\x03!\xb9\x9a\xc9\xe9Ŝ\xf4h\xde@\xcad\xb7\x18A\x19\x98в\x11\x85\xfa\xdf\x10\xc2\xe1\x86!)\xd3b\xbc\x9b\xb4\xf5\x93\x8c\xae\x9fm\x18\x16\x80\xea6\xb9\xfd=$\xf9\xeb lm\x18\x92\xaa\xa4\x04\xfc\x93X\xfa\x04M\x85\x87\r\xa3\xef\xf8\x11@\x9f\x0e\xff\xd2\xe7I\xf2\xf79\xfc%Uשg\u061c$w7\x93K\xffi\x18\xae\x00T\x97\xe6\x97\xfa1b\xcbK\b\xc1\x83_R\xb5/\a\\ɬY'Ӽi\xabYX\x00\xb2m\xfc\xf2M\xa9\xab\xbd\x81\x10\xf61\fI\x02b|\x98\x15\xad\xc7qz\xfd,ð\x00d\xd3%\xed\xbb\x91\xcf\xff\x81\x10\xb64\fIzK\vx\x95X<\x9aQ5O\x9aE\xef\xf0\x1a\x80\xderi\xf1\x83\xe4\xf3\xf79\xfc%i\x95磛A\xfe\x1e.-\x1ea\x16\x16\x80\xec\x98R\xfa\x121\xf9\xa3\xf7\xf7KҚ:@h\x80\xe4&&\x97N6\f\v@ekn\x0eLN\x9b\t\xc9\xcf\b\xa1` \x92\xb4\xd6\x16\x90'I.erz1\xcd\xcd~LݓI\x1bAO\r\xff\x97\xfa\xb1\xf1\x96?\x85\xe07bI\xd2\xfa\x88\xf1\x1aZ_\xfd<\x90$\x7f\x13\x17.\xdb\xd8\x02\x90%\xe3g֒\xaf\xbd\x91\x10\xb6\xf4 \x97$\xad\xa6\x04lM]\xdd\xef\xab\xe5\xf6\xc0\xea(\x00u\x9bM$\x84}<\xb8%Ik)\x01\xfb\xb1\xf1\x96\x17[\x00\xb2`J\xe9$B\xf8\x8a\a\xb5$\xa9\x8b%\xe0d\xa6\x942?7\xb2}\x11`\xe7\x17\xfc\xdc\x03\xa1\x9f\a\xb4$\xa9\xcbb\\AZ:\x88хG]\x01\xa84\x17\xb4\f%\x9f\xbb\xca\xe1/IZ\xf7\xd3\xe3PK\x92\xbb\x8e\t-\x1bY\x00*I\xf3\xb4\x1c\xf5\xf5\xbf\x81\xb0\xb5G\xb1$i=K\xc0\x96\x14\xea\x7fG\xf3\xb4L>6?\x9b\x05`\xc4\xc1\xe7\x11\u0087\xc0\xf0\x83\xcf\xcd\xe4\xa6en\x8b\xa6\x14\x8f\x83\xe4zB\b\x1e\xb9\x92\xa4\r\x16c$\xa6'Ҕ\xbf\xd6\x02P\xae.iۉB\xe1\xcf\x10\x06z\xc4J\x92\xba\xb1\x04\xb4P*\xeeǩ5ӳ\xb2I\xd9\xf9\b\xe0\xbc\x05\x03)\x14nt\xf8K\x92\xba\xfft94\x90\xcb_\xc3\xf9\xf3\x06X\x00\xcaMc\xe3D\b;y\x94J\x92z\xa8\x04\x8cd\xe0\x90\x8b2\xb39\x99؊\xc9\xc5O\x90\xe4\xae\xf1\xe8\x94$\xf5\xb8\x98~\x8aQ\xb9\xab,\x00}>\xfc[7'\xf4\xfb\v!\f\xf1\xa8\x94$\xf5|\x01\x88\x8b(\xb5\xedΩu\xafT\xf2fT\xf6G\x00'\\\x9d\x10\xfa]\xe1\xf0\x97$\xf5ީsh$\xd7\xef\xcaJ\x7f>@e\x17\x80\xc3>~\x0e!\x1c\xe6\xd1(I\xea\xe5\x12p0\xc3\x0f:\xb3\xa27\xa1b_\xf9%\x1d{\x91\xcf=@\b5\x1e\x89\x92\xa4^\x17c\a\xa5ҁ\x9cZ\xf8\xb3+\x00\xbdeҜz\n\xb9_;\xfc%I}\xb8\nP \x9f\xfbu\xa5\xde\x1aX\x99\x05 \xd9\xe8bo\xf9\x93$\x95A\v؞\x81C~T\x91\xaf\xbc\xf2\xce\xfe\x8b\x1f#\x97\xbbރN\x92T6\xd2\xd2q4\xe5o\xb4\x00\xf4\x94\t\xcb7\xa3\xa6\xf6/\x10\x86z\xb4I\x92\xcaF\x8c\xf3(\xaex7c\xfa\xbf^)/\xb9\xb2>\x02(\xd4Nr\xf8K\x92\xca\xeft:lD\xbe\xf6Ǖ\xf4\x92+\xa7\x00L*}\x8a\x10\x8e\xf5(\x93$\x95i\t8\x8a)\xa5\xcfT\xcc˭\x88W9q\xc9\x10r\x03\xa6\x13\xc2\b\x8f0IR\xf9\x8a\xf3)\xb5\xee\xca\xe8\xfaٮ\x00t\x87܀\xf1\x0e\x7fIR\x05\x9cW\x0f%\xa9\xbb\xcc\x15\x80\xee0\xa5x\x18$w\x10B\xf0\xc0\x92$U\x84\xb4t\x02M\xf9k-\x00\xeb\xebG\xb3\xfa3`\xf8_\ta;\x8f&IRňq6\xad-\xbbpƠ\x85\xe5\xfa\x12\xcb\xfb#\x80\x01ÿ\xe7\xf0\x97$U\x9c\x10FP\xd7\xf0߮\x00\xac\x8f)\x1d\xfb@\xeeAB\xc8y$I\x92*p\x19 %\x96\x0ebT\xe1\x01W\x00\xba\xea\xa4G\xf3\x84\xdce\x0e\x7fIR\x05/\x03$\x84\xdce4?U\xb0\x00t՞{~\x03\u009e\x1e<\x92\xa4\n/\x01\xbb1b\xe73\xca\xf2\x95\x95\xdd+\x9a\xb4b;\x92\x9a\xbf\x13B\xad\a\x8e$\xa9\xe2Ÿ\x9c\xb6\xf6\x91\x8c\xab}\xd9\x15\x805\xbe\xa2\x9a\v\x1d\xfe\x92\xa4\xec,\x02\x84\xfe\xf4\xab\xb9\xc0\x15\x805\x99R\xfc\x10!w\x9bG\x8b$)sJ\xa5\x8f0:_63\xae|V\x00&\xb3}\xe7{蔑\xe6Q]\x05 \f\xa2\x7f\xc3\xd8l\x14\x80\xf3\x16\f$2ڽZ\x1d\x06\xd6\xc0\xb5\x87w.e6\x14\xccC\xda\xd0\xf7Ӕ\x83\xe0\xea\xc3}?U\x99\xd38\x7fހ\xca/\x00\x8d\x83\x9a\b\xa1\xd1\xfd\x99}#\xeaஏ\xc2Ƿ5\v\xa9;\x9d\xb0m\xe7{kx\x9dYT\xc92\xc0`\x06\x0e\xfeRe\x17\x80\xe6\x97\xfa\x11\xc3Xwfu\f\xff{\x8e\x85\xf7ld\x16RO\xd8k\x18\xdc{\xac%\xa0\x8aJ\xc0\xe9\x9c\xf4h\x8f^9ճ\x05`\xf8\x16_$\x84Mܑ\xd96\xb0\x06\xa6\x1e\xd9yO\xbf\xa4\x9e\xb3\xe3 \xf8\xe3\x11~\x1cP\x1d\xf3?lÞ{~\xac2\v@\xf3\xb4\x1c!\x9c\xe9^̾\x9f\x1d\x02{z\xe6/\xf5\xdaJ\xc0O\x0f5\x87*i\x01_\xaf\xcc\x020\xfc\xc0\x8f\x11\xc2\x0e\xee\xc0lk\xda\xd5\xcf\xfc\xa5\xdev¶p\xb2w\aT\xc3*\xc0>L\xe98\xb0\xf2\n@H\xcep\xefe\xdb&\xfd\xe1\xbf\xdfk\x0eR_\xf8\xd1~\x9d\xcf\xdaP\xd6\xe5zl%\xbdg\n\xc0%\x1d{\x11\xc2\xfe\xee\xb8l\x1b\xbf\x7f\xe73\xfc%\xf5\xbe\x86\x02\x9c\xbf\xaf9T\x81c\x99жK\xe5\x14\x80|γ\xff\x8c\xdbep\xe7\xa3K%\xf5\x9dOo\x0f\xbb\x0e6\x87L\v!P(\xf4\xc8\xddt\xdd_\x00\xc6/\xdf\x14\xf8\x84{-\xdb\xce\xda\xc3'\xfcI}-\tp\xe6\xee\xe6P\x05\xbeȤe#ʿ\x00\xd4֎&\x04\x17\x863l`M\xe7EH\x92\xfaމ\xdby[`\x15\xac\x02Ԓ\xab;\xa5\xbc\v@\xf3K\xfd\b\xfc\xa7{+\xdb>\xbeM痖H\xea{\xf5y\xf8\xd86\xe6P\x05\x9ah~\xa9_\xf9\x16\x80\x11[\x9c@\b\xc3\xdcO\xd9vĖf \x95\x93\x8fla\x06U\xb0\f0\x9c\xe1[\x1c_\xbe\x05\x800ʝ\x94\xf1C\x108tSs\x90\xca\xc9\xfb7\xeb|o*\xeb\x7f\x00\x87n\xfd\x18\xa0\xfb\n\xc0%\xed\xef&\x84\x03\xdcCٶe\x03\f\xab5\a\xa9\x9c\x8c\xa8\xf3\x99\x00UR\x00\x0e\xe6\x92\xf6\xddʯ\x00\xe4\xf3\x9e\xfdW\x81\x9d|\u07bfT\x9e\xefM\xbfs\xb5:\xe4\xf2\xddv\x9d]\xf7\x14\x80\xf3\xe7\r \xf0\x19\xf7L\x15\xac\x00\f0\x03\xa9\x1cm\xd5`\x06ձ\n\xc0\x17\x984\xa7[\xd6{\xba\xa7\x004\f\xfe4\x84\x81\xee\x99\xec\x1b\xe8\r\x9eRy\xbe7\xbd\x15\xb0J\n@\x18D\x18zB\xf9\x14\x80$|ٽR\x1d\xea\xbd\xfdO*K>\v\xa0\xaaJ\xc0\x97ʣ\x00\\Ҷ\x13\x11\x9fH]%r\x89\x19H\xbe7\xd5\xc7\x0e\xe2\xe2\xb6\xed\xfb\xbe\x00\xe4\v_!\x04\xef@\x91$\xa9wV\x00\x02\xfd\n_\xec\xdb\x02pңy\xe0?\xdc\x1b\x92$\xf5\xaa/\xd2<-\xd7w\x05`\x8f=\x8e \x84M\xdc\x0f\x92$\xf5\xea2\xc0f\f;\xf0\x83}W\x00B\xf29w\x82$I} \xb7a3x\xfd\v\xc0\x84\xf9\r\x04\x8ev\x0fH\x92\xd4\a\"\xc7q\xfe\xbc\xf5~:\xcb\xfa\x17\x80\x9a\xc6\xe3!Թ\a$I\xea\x03!\xd4\xd30\xf8\xa3\xbd_\x00b\xf0\xc9\x7f\x92$\xf5m\t\xf8t\xef\x16\x80\x8b\x96\x0e'\xf0~\x93\x97$\xa9O}\x84\vZ\x86\xf6^\x01\xa8\xad\xfb\x14\x04\x9f\t'IR߮\x00\x14\xa8\xef\xbf^\x8f\x06^Ϗ\x00\u0089\xa6.IRY\x94\x80^*\x00\x17.\xdb\x18\xd8\xdf\xc4%I*\x03\x91C\xb8h\xe9\xf0\x9e/\x00\xfdj\x8f\x87\xe0S\xa7%I*\x8f\x15\x80\x1c\xb5u\xc7\xf4|\x01H\xc2\xc7M[\x92\xa4rZ\x05X\xf7ټn\x05\xa0\xf3JÃMZ\x92\xa4\xb2\xf2\x01\xc6/\x1e\xdcs\x05\xa0\xbe\xff1^\xfd/IR\x99\t\xa1@\xbf\x01\xeb\xf4t\xded\x1d\x7f\xc1q\xa6,IR\x19J\xc2:]\a\xd0\xf5\x02\xd0\xfcR?\xf0\xe1?\x92$\x95\xe7*\x00\x1fycVws\x01\x18\xbe\xf9\a \f0aI\x92ʲ\x01\f`\xe3\xcd\x0f\xea\xfe\x02@\xe27\xffI\x92T\xcebrT\xf7\x17\x80\x84#MV\x92\xa4r^\x04\xa0\xcb\xd7\x01t\xad\x00\\\xd2\xfen\b[\x99\xac$Ie\xdd\x00\xb6eR\xdb\xce\xddW\x00r\xb9\x8f\x18\xaa$I\x15 \xc9wifw\xad\x00\x84p\xb8\x89J\x92T\x11\xab\x00]\x9a\xd9k/\x00\xe3g\xd6\x12x\x9f\x81J\x92T\x11\x0e\xe9\xca\xed\x80k/\x00u\x9b\x1c\f\xa1\xce<%I\xaa\x84\x05\x80Pϰ\xcd\xd7\xfa\xad\xbd]\xf8\b q\xf9_\x92\xa4\x8a*\x01k\x9f\xdd]\xb9\x06\xc0\x02 IRE\x15\x006\xb0\x00L\\2\x84\xc0\xbbLR\x92\xa4\x8a*\x00{1yQ\xe3\xfa\x17\x80\\\xff\x83!$&)IRE5\x80\x840\xe0}\xeb_\x00Br\xb0!J\x92T\x91\x1d\xe0\xe0\xf5/\x00\x91CLP\x92\xa4\n\xb4\x96\x19\xbe\xfa\x02pނ\x81\xc0\xee&(IR%\xae\x00\xb0\x17\x13\xe67\xac{\x01\x188\xf0@Bș\xa0$I\x15\xd9\x00\xf2\xe4\x06\xed\xb7\xee\x05 $\a\x1a\x9e$I\x95\xdc\x01\x92\x83ֽ\x00\xc0~&'IR%\x17\x00\xf6]\xb7\x02p\xc2\xd5\t\x81\xbdLN\x92\xa4\x8a\xb6/'\\\x9dt\xbd\x00\x1c|\xdcn\x10\x06\x9a\x9b$I\x95\xbc\x02\x10\x06q\xc8q;w\xbd\x00\xe4r\xfb\x9a\x9a$IY(\x01\xb9\xfd\xba^\x00B\xb0\x00H\x92\x94\x05ɪg\xfa\xea.\x02|\xaf\x89I\x92\x94\t],\x00\xe3g\xd6\x12\xd8ż$Iʄ\x91\x8c\x9fY\xbb\xf6\x02P\xb3\xf1\xbb!\xe4\xcdK\x92\xa4\f\b\xa1@툑k/\x00I\xb2\xa7iI\x92\x94\xa5\x12\x90۳\v\x05 X\x00$I\xcaV\x03\xe8B\x01\x88\xbcǠ$Iʔ\xb5\x14\x80\xe6i9\x02\xbb\x99\x93$IYZ\x00\xe0\xddo\x7f\"\xe0[\v\xc0\xf0\xfd\xb7\x83PgR\x92$e\xaa\x01\f\xe0\xb0c\xb6Z}\x01\x88\xb9]\rI\x92\xa4\f\x8a\xf9\xb7\xcc\xf8\xb7\xde\xee\x17\xc2H\x13\x92\xd4U\xcf/\x81k_\xc8\xfev~hs\xd8s#\xf7\xb7*}\x11 \x8c\x04n\xb1\x00H\xda \xf3V\xc0\x91\x7f\x84g\x17g{;?\xbb\x03\x9c\xf9n\xf7\xb72S\x00\xfe\xed\xedw\x01X\x00$\xadUk\x11\x8e\xb95\xfb\xc3\xff\x94\x91p\xc5a\x90O\xdc\xe7ʄ\xd5\x14\x80\x13\xaeN\b\xecd>\x92֤\x14\xe13w\xc0\x83\xb3\xb3\xbd\x9dg\xed\x01S\x0e\x82$\xb8ϕ\x95\x15\x00v\xa1\xb99\xbc\xb3\x00\x1cv\xccV\xde\x01 im\xc6=\x007\xbc\x94\xfd\xe1\x7f\x9e߉\xaa\xec5\x80\x01\f?k\xb3w\x16\x80\x98\xdf\xdep$\xad\xc9\x0f\x1e\x87\x89\x7f\xcf\xf2\t\x12\x8c\xdf\xdf\xe1\xaf\f\x8b\x85\xed\xdfY\x00r\xc1\x02 i\xb5~;\x03\xfe\xeb\x91\xecn_.\xc0\x8f\x0f\x81ӽ\xe0OY\xb6Ҭ\x7f\xf3.\x804l\x87\x17\xbaHZ\x85\xbb^\x83/M\x83\x98\xd1\xed\xcb'\xf0\xb3C\xe0s;\xba\xaf\x95qi\xd8\xee\x9d\x05 \xe0\n\x80\xa4w\xf8\xfb\x028\xfe6h+es\xfb\xfa\xe5\xe0\xb7\x1f\x80\x8fm\xe3\xbeV\x15Xi֯\xfc\x1c\x00\v\x80\xa4\xb7xu\x19\x1c9\x15\x16\xb5gs\xfb\xea\xf3\xf0\xfb\x0f\xc3\u16fb\xafU5\xdeV\x00:o\v\xb0\xffJ\xfa\xb7\xc5\xed\x9d\xc3\x7f\xe6\xd2ln_c\r\xfc\xe1H8`\x84\xfbZU\xe5\xdf\x1f\x01t~\xea?\xe2k\x1b\x11B\x7fs\x91\x04О\xc2\xc7\xff\x0f\xfe:?\x9b\xdb7\xa4\x1f\xdcv\x94\xc3_U(\x84\x06\xc6/\x1e\xfcf\x01\x885[\x98\x8a$\xe8\xbc\xd0\xef+\xd3\xe0\x8eW\xb3\xb9}\x1b\xf7\x87i\xc7\xc0{\x87\xbb\xafU\xa5\nu[\xbcY\x00H,\x00\x92\x00\xf8ڃ\xf0\xab粹m[5\xc0\xbd\xc7\xc0\xbb\x86\xb8\x9fU\xc5\xf2\x9d3\xff\x8d\x8b\x00\x83\x05@\x12S\xa6\xc3\xf8\xbffs\xdbvj\x84?\x1d\r\x9b\u05fb\x9fU\xe5B\xd8\xf2\xcd\x02\x90X\x00\xa4jw\xd3K0\xe6\xbelnۮ\x83\xe1\xf6\xa3a\x13\xaft\x92 \x86\x95V\x00\"\x9b\xe3\x17^HU\xeb\xe19\xf0\xe9;:\xbf\xe8'k\xf6\x1e\x06\xb7\x1e\tCk\xdd\xcf\xd2\x1bV*\x00\x81M\xcdC\xaaN3\x16\xc3G\xa7\xc2\xf2b\xf6\xb6\xed\x90M\xe0\xe6#\xa0\xa1\xe0~\x96V\xb2\t\xbc\xf9]\x00\xde\f#U\xa1\xb9+\xe0\x88\xa9\x9d\xff\x9d5Gn\tS\x8ft\xf8K\xef\x10:g\xfe\x1b\xb7\x01Z\x00\xa4j\xd3\xd2\x01\x1f\xf9C\xe7\n@\xd6\x1c\xbb5\\\xff!\xa8˻\x9f\xa5U\x18\xdeY\x00\x9a\x9f*\x00\x83\xcdC\xaa\x1e\x1d)\x9cx;<>/{\xdb\xf6\xd9\x1d\xe0\xda\xc3;\x9f\xf1/i\x956\xe2\xa4G\xf3\tC\xb6\x19N\b^\x02(U\x89\b\x9c|\x0f\xdc:3{\xdb6j$\\qX\xe7\xb7\xfbIZ\x9d\x90\xb0\xfb.C\x13\x92\xbc\xcfÒ\xaaH\xf3\xa3\xf0\xf3\x7fdo\xbb\xce\xda\x03&\x1f\x04\x89\xa73\xd2ڥ\x85\x11\t\xb9d\x98IH\xd5\xe1\xa7\xcf\xc0\xb9\x8fes\xf8\x9f\xb7\xaf\xfbW\xea\xb2\\2,\x0f\xc1\xcf\xff\xa5*0u&\x9cro\xb6\xb6)\x00\xe3\x0f\x80q\xefr\xffJ\xeb$Ҙ'\xd2\xe8C\x80\xa4l{ln\xe7E\x7f\xc54C'0\x01.;\x18\xbe\xb2\xb3\xfbWZ\x8f7\xd0\xe0<\x89w\x00HY\xf6b\v\x1c}+,\xed\xc8\xce6\xe5\x13\xf8\xd9!\xf0\xb9\x1dݿ\xd2zIi̓\x86AxŬ\x94I\xf3W\xc0\x11\x7f\x84Y˳\xb3M\xfdr\xf0\xbb\x0f\xc2q[\xbb\x7f\xa5\xf5\x16\u00a0<\x81F\x93\x90\xb2\xa7\xb5\b\xc7\xde\x06\xffX\x94\x9dm\xaa\xcf\xc3\xef?\f\x87o\xee\xfe\x956\xd0\xe0<0\xc8\x1c\xa4lI#\xfcǝp\xff\xac\xeclSc\r\xfc\xe1H8\xc0\xe7\x96Jݰ\x02@c\x1e\x18`\x12R\xb6\x9c\xfe\x00\\\xffbv\xb6gH?\xb8\xf5(\xd8Ǜ\x96\xa5\xee\x11\xa9\xcf\x03~C\xb6\x94!?|\x12&\xfc=;۳q\x7f\xb8\xfd(\xd8m\x88\xfbV\xeaF\xfd\xf3@\x9d9H\xd9p\xd5\xf3pΟ\xb3\xb3=[5\xc0\x9f\x8e\x82\xed\xfd\xa0R\xea^\xa1\xf3\xbb\xb2\\\x01\x902\xe0\xee\xd7\xe1\vwu~\xfe\x9f\x05;7\xc2\xedG\xc3\xe6\xf5\xee[\xa9\xa7V\x00,\x00R\x85\x9b\xbe\x10>v\x1b\xb4\x95\xb2\xb1={\f\x85\xff;\x1a\x86պo\xa5\x9e*\x00\t\xc1\x8f\x00\xa4J\xf6ڲ\xce{\xfd\x17\xb6ec{\xf6\x19\x06\x7fr\xf8K=\xad.O\xa4\xd6G\x01K\x95iI;\x1c9\x15^Y\x9a\x8d\xed9d\x13\xb8\xf9\bh(\xb8o\xa5\x1e\x15\xa9K\b\xe4MB\xaa<\x1d)|\xe2v\xf8\xcb\xfcllϑ[\xc2\xd4#\x1d\xfeR\xaf\b\xe4\x13\xa2\x05@\xaa\xbc\xf2\x0e_\xbd\x1bn\xffg6\xb6\xe7\xc4\xed\xe0\x86\x0f\xd3yY\xb2\xa4\xde\xf8C$\x97\x009\x93\x90*\xcb9\x0f\xc3\x15\xcffc[\xfec\a\xf8\xf5\xfb\xa1\xe0w\x92H\xbd\xba\x02\x90'X\x00\xa4J\xf2\xec\"\xf8\xfb\x82ll˘\xdd\xe0\xe2\xf7\xe1eHR\xefs\x05@\xaa4\xedi6\xb6\xe3\xac=`\x82\xc3_\xea\x1b\xb1\xf3\x1a\x00\v\x80\xa4^\xb5\xf708o_s\x90\xfaL\xe8\\\x01\x90\xa4^\xf5\xe8\\\xf8\xe3+\xe6 \xf5\xa5\x84@\xc9\x18$\xf5\xb6\xd3\x1e\xc8Γ\v\xa5\x8a\x13)%`\x01\x90\xd4\xfbf,\x86\xf1\x7f5\a\xa9O\x04\x8a\t\xd1\x02 \xa9o|\xffqx\xa9\xc5\x1c\xa4>\xe0\n\x80\xa4\xbe\xb3\xbc\b_{\xc8\x1c\xa4^\x17)&\x04\x8a&!\xa9\xaf\\\xf7\x02L\x9di\x0eR\xaf\n\x94\x12\xa2\x05@R\xdf:\xed~/\b\x94\xfab\x05`\x85IH\xeaK\xcf-\x86\v\xfff\x0eR/\xae\x00\xb4&DZMBR_\xfb\xdec\xf0\xb2\x17\x04J\xbd\xa55\x01\x96\x9b\x83\xa4\xbe\xb6\xbc\b_\xf7\x82@\xa9\xd7\xder\x16\x00Ie\xe3\x9a\x17\xe0V/\b\x94z\xad\x00\xf8\x11\x80\xa4\xb21\xd6\v\x02\xa5\x9e\x17\xfd\b@R\x99yn1\\\xec\x05\x81R\xaf\xac\x00,5\aI\xe5\xe4\xbb^\x10(\xf5\xac\xc0\xb2\x84\xc8\"\x93\x90TV\xa7&E8\xebas\x90zLdAB\xb0\x00H*?W=\x0f\xb7yA\xa0\xd4S\x05`QB\x8c\x16\x00Ie\xc9\v\x02\xa5\x1e\x92\xc4Ů\x00H*[\xcf.\x86\t\x7f7\a\xa9ەX\xe85\x00\x92\xcaڹ\x8f\xc1\xab\xcb\xccA\xea\xe6\x15\x80E\t1.4\tI\xe5ji\x87_\x19,u\xbb\xc8\xe2\x84$\x9dk\x12\x92\xca\xd9\xeff\xc0\x9d\xaf\x9a\x83\xd4mJ\xe9\xec\x84bq\xb6IH*wc\ue1ce\xd4\x1c\xa4\xee)\x00\xeds\x12\xfe6}.D\xdfV\x92\xca\xda\xf4\x85^\x10(u\x8b\x18K,zt~\xc2\xe5{\x17\x89,0\x11I\xe5\ueecfzA\xa0\xd4\r\xe6\xd1|h)y\xe3\x7f\xcc1\x0fI宥\x03\xbe\xe1\x05\x81҆\t\xcc\x06\xf8W\x01\xf0:\x00I\x15\xe173\xe0\xae\xd7\xccAZo\xb1\xf3\xa4\xff_\x05\xe0u\x13\x91T)N\xbd\xcf\v\x02\xa5\rX\x01x}\xe5\x02\xe0\x13\xb7%U\x8c\xe9\v\xe1\x12/\b\x94\xd6\xd7++\x15\x80h\x01\x90TQ\x9a\x1f\x85\u05fc PZwi\xe7\xccOV\xfe\x1f\x92\xaa\xc3\xe0~\xf0\xf1m+{\x1bZ:\xe0\x1b~e\xb0\xb4\x1eV.\x001\xb5\x00HUbH?\xb8\xed(\xf8\xc9!\x9dE\xa0\x92\xfd\xfa9/\b\x94\xd6Y)]\xe9#\x80\x15m\xaf\x98\x88\x94}#\xea`\xda1\xb0\xcf0h\xac\x81\xd3\xdeU\xf9\xdb4\xc6\v\x02\xa5u,\x00\xcbWZ\x01\xf8Z\xc3|b\\n*Rvm1\x00\xee=\x16\xde5\xe4Ϳw\xe6\xbbaXmeo\xd7S\va\xd2S\xee_\xa9k\xe2\x12\xc65.~\xb3\x00\x00\x04^0\x18)\x9b\xb6j\x80\xbb>\n;\fz\xeb\xdf\x1fP\x803w\xaf\xfc\xed\xfb\xf6#^\x10(u\xd1\xf3\xff\xfa\x8b7\v@d\x86\xb9Hٳ\xe3 \xb8\xefX\xd8n\xe0\xaa\xff\xf9\xd8\xdd`\xb3\xfa\xca\xdeƖ\x0e8\xfb\xcf\xeeki\xed\v\x00o\xce\xfad\xa5\xbfm\x01\x902f\x97\xc1\x9dg\xfe\x9b\xafa\xc0\xd7\xe5\xe1\x1b{T\xfe\xb6\xfe\xeaY\x98\xe6\x05\x81\xd2ڬ\xaa\x00\xc4\xe7\xcdEʎ=7\x82\xbb\x8f\x81M\xbbpv\x7f\xcaHغ\xa1\xd2Ol|B\xa0ԅw\xca*>\x02H-\x00RV\xec5\fn?\xaa\xeb\x17\xf8\xd5$pΞ\x95\xbf\xddO-\x84\xc9^\x10(\xad^\xba\xaa\x02\x10\x8a~\xb3I\x11]\x00\x00\x1a4IDAT\x04 e\xc0\x81\x1bÝG\xc3\xd0u\xbc\xba\xff\xcb;\xc1N\x8d\x95\xbf\xfd\xdf~\x14^\xf7\x9e&i\xd5B\xc7*>\x02\xb8릗!\xb6\x9a\x8eT\xb9\x0e\xd9\x04\xa6\x1e\t\x03k\xd6\xfd\xdf\xcd'\xf0\xff2\xb0\n\xb0\xa4\x1d\xce\xf6\t\x81\xd2*ĥ\xcc9\xff\xd5w\x16\x80kNL\x81g\fH\xaaLGl\xd19\xfc\a\x14\xd6\xffg|f\a\x189\xb8\xf2\xb3\xb8\xf2Y\xb8\xdb\xef8\x95\xden:\xcd\xcd\xf1\x9d\x05\xe0_\xffPR\xc5\xf9\xe8V\xf0\xfb\x0fw^ѿ!r\x01\x9a\xf7\xce\xc0y\x0e\x9d\x17\x04\x16\xbd PZ\xed\x8c\x7fk\x01\x88\xd1\x02 U\x98Om\x0f\xd7}\b\xfa\xe5\xba\xe7\xe7}b\xdb\xce;\b*\xdd\xdf\x17\xc0\x14\xffD\x93V;\xe3߶\x02`\x01\x90*\xc9gw\x80+\x0f\x83B\xd2}?3\x00\xe7\ue74d|\xbe\xf5\x88\x17\x04J\xab\x9b\xf1o[\x01(Y\x00\xa4\nq\xf2H\xb8\xe2\xb0\u038b\xf7\xba\xdb\xd1[\xc1\xfe#*?\xa3%\xed\xf0M\x9f\x10(\xbd1\xe3\x8bk(\x00s\x1e|\xde/\x05\x92\xca\xdf\xe8]a\xcaA\x90\x84\x9e\xfb\x1d\xe7\ue4cd\xac~\xf9\x0f\xb8\xc7\v\x02\xe5\xf4_\xday\xb7\xdf\xea\n@\xf3\xa1%\xe0o\x06%\x95\xaf\x9d\x1aa⁝K\xf5=郛\xc1a\x9bf\xe0\x8f=\xe0\xb4\xfb\xa1\x14=vT\xcd\xf3\x9f'߸\xdbo5\x05\xa0\xd3\x13&%\x95\xafB\xd2{\xbf\xeb{\x19Y\x05xr>L\xf1\t\x81\xaan\xef\x98\xed\xab\xf8\xa3$Z\x00$\x01\xf0\xbe\x8d;\x9f/\x90\x05\xff\xcf\v\x02U\xcd\xd2\xf8\xe4\xda\v@\x9a>nR\x92V^\x05\b\x19؎%\xed\xf0\xff\xbc P\xd5*\x96\xba\xb0\x020\xf7տ\x11c\x87iI\x82\xce/\x16:n\x9bll\xcb/\xbc PU9\xfcc;\xf3^\x9b\xbe\xf6\x02мu\x1b\x81\xa7ML\xd2ʫ\x00I\x06\x96\x01\"0\xee\x01/\bTՙN\xf3\xd6mk/\x00\x9d\xef\x12\xbfJCҿ\xed:\x18>\xb5]6\xb6\xe5\x89yp\x99OU\x95\x88\xab\x9e\xe9\xab~;\x17K\x16\x00Io\xb1\xc3 \xf8\xfc\x8e\xd9ؖ\x85mp\x8e\x7fʩj\n@q\x1dV\x00\xee\xb9a:1.65I+\xfb\xf6{\xba\xefK\x87\xfa\xdaϞ\x81\ag\xbbO\x95\xf9\xb3\xffEL\xbb\xf1ٮ\x17\x80Χ\x05=jr\x92V\xb6U\x03|u\xe7\x8c\xfc\xb9H\xe7W\x06{A\xa02\ue877?\x01p\xcd\x05\x00 \xac\xfa\xa2\x01I\xd5\xed\xff\xbd\a\xfa糱-\x8fσ˽\xe7I\x99^\x01X\xfdE\xfdk\xb8\xa4'\xbd\xdf\xe4$\xbd\xdd&\xfda\xd4\xc8\f\x15\x9a?{A\xa02,I\xef[\xf7\x02о\xf8>\x88Eӓ\xf4vg\xef\t\r\x85ll\xcb\xc26\xf8\xa6\x17\x04*\x93g\xff\xb1\x83҂\a\u05fd\x00\x8c\x1d\xdaB\xe4I\x13\x94\xf4v\x1b\xd5\xc2\xd8weg{~\xf6\x0fx\xc8\v\x02\x95=\x8f2z\xf8\xb2u/\x00\x9d\xee1?I\xab\xf2\xf5\xddaH\xbfllK\x1aa\xb4\x17\x04*{\xd68\xc3\xd7\\\x00bj\x01\x90\xb4J\x83j\xe0\xf4wgg{\x1e\x9f\a?\xf1\x82@e\xc9Zf\xf8\x9a\v@\xba\xfc^\x88\xa9)JZ\x95q\xef\x82\xe1u\xd9ٞo\xfe\x19\xe6yA\xa021\xfcc\t\x96>\xb0\xfe\x05\xe0ԁ\v\x80\xbf\x98\xa4\xa4U\x19P\x80o쑝\xedY\xd0\xe6W\x06+#\x02\x8f\xd1Ըh\xfd\v@\xa7\xdbMR\xd2\xea\x8c\xde\x156\xaf\xcf\xce\xf6\xfc\xe4\x19xx\x8e\xfbU\x15o\xad\xb3\xbb\v\x05 \xb5\x00HZ\xad\xda\\\xe7m\x81Y\xf1\xaf\v\x02S/\bTe\x1f\xc9\xddP\x00\x96\xbf~\x1f\xc4VÔ\xb4:'\xed\x02\xdb4dg{\x1e\x9b۹\x12 U\xa4\x18\x971\xeb\x9fk}\x9a\xef\xda\v\xc0\x19[\xac r\x9f\x89JZ\x9dB\x02\xdfzO\xb6\xb6震\xbd P\x15*p\x17\xcd[\xb7mx\x01\xe8\xac\x13~\f i\x8d\xbe\xb0\x13\xecܘ\x9d\xedY\xd0\x06\xdfz\xc4\xfd\xaa\x8a\\\x02\xe8\xd2\xcc\xeeZ\x01(\x96\xa6\x1a\xa8\xa45\xc9\x05\xf8\xaf\xbd\xb2\xb5M?~\x1a\xfe\xec\x05\x81\xaa4\x1d\xc5ۺ\xaf\x00\x8c\xa9\xf9;1\xbeh\xaa\x92\xd6\xe4S\xdb\xc1\xeeC\xb3\xb3=^\x10\xa8\xca;\xf9\x8f\xcf3\xa6\xdf?\xba\xaf\x00\x00\x04\xfe`\xb2\x92\xd6\xf8\aJ\x80ogl\x15\xe0ѹ\x9d\xdf\x15 U\x88\x1b\xbb\xfc~\xedz\x15N-\x00\x92\xd6\xeac\xdb\xc0{\x87gk\x9b\xcez\xc8\v\x02U!\xd6aVw\xbd\x00\xcc\xf9\xe7]\xc4\xd8b\xba\x92\xd6$\x00\xcd{gk\x9b\x16\xb4\xc1\xb7\xbd Pe/.\xa1\xf4b\x97\xef\xda\xebz\x01h\u07ba\x8d\xc0\x9f\fX\xd2\xda\x1c\xb1\x05\x1c\xbcI\xb6\xb6\xe92/\bT\xf9\xbb\x95\xb1;\xb4w\x7f\x01\x00H\xe3M\xe6+\xa9+\xbe\xbfO\xb6\xb6\xc7\v\x02U\xfe\v\x00\xf1\xe6u\xf9\xbf\xe7\xd7\xed\xa7\xb7\xdc@\x1cx\x19!Ԙ\xb4*Ո\xfe\x9dO\xae\xabT\x9bV\xc8s\xf7\x0f\xda\x04\xbe\xb3\x17\xbc\xbe<[\xc7\xcf?\x16\xc1.\x83}\x1f\xa9\xec\x86\x7f;\xadK\xd7\xe9Z\xbdu+\x00M\x8d\x8b\x98\x92\xde\r\x1cnڪT\xdb4\xc0e\a\x9bCo\xc8ڵ\x00R\x19\xbb\x9d3\x06-\\\x97\x7f!Y\xe7_\x11\xe3u\xe6,IRY-\x01\xac\xf3l^\x8f\x02\xb0\xe2\x06b,\x19\xb6$Ie1\xfc\x8bt,\xbfy]\xff\xadu/\x00\xa3\xebg\x03\xf7\x1b\xb8$I\xe50\xff\xb9\x8b\xb1\r\xf3z\xbe\x00\x00\xc4x\x8d\x89K\x92T\x16\r\xe0\xda\xf5\xf9\xb7֯\x00\x84֫ \x16\r]\x92\xa4\xbe\x9c\xfd\xb1\x9de\xcb\xd7\xebڼ\xf5+\x00\xa3\x06\xcc%\xfaP I\x92\xfa\xd8T\xbe\xd60\xbf\xf7\n\x00@\x1a\x7fc\xee\x92$\xf5\xe9\x12\xc0o\xd7\xf7\xdf\\\xff\x02\xc0\xfc\xeb\x89q\x99\xe1K\x92\xd4\x17\xb3?.#\x9d\x7fK\xef\x17\x80\xd1×\x01\xb7\xb8\a$I\xea\x03\x81\xebߘŽ\xbd\x02\x00\x90^\xe9\x1e\x90$\xa9\x0f\x946l\x06oX\x01\x98}߭\xc4\xf8O\xf7\x82$I\xbd(\xc6\x7f2\xf7\xbe;\xfb\xae\x004\x1fZ\x02~힐$\xa97\v\x00?\x7fc\x06\xf7Q\x01\x00\x88\x1d?#F\xbf S\x92\xa4\xde9\xfb\x8f\xc4\xf6_n\xe8\x8f\xd9\xf0\x02\xd0\xd4\xefY\xe0A\xf7Hu(\xa5f \xf9\xdeT\x9f\n\xdc\xcd\xe8\xda\xe7\xfb\xbe\x00t֑\x9f\xb9G\xaa\xc32\x9f\xff(\x95\xa5\x96\x0e3\xa8\x1ai\xfcyw\xfc\x98\xee)\x00K\x16^\x05q\x89{%\xfb\x96\xb4\x9b\x81T\x96\xefM\v@u\x88q\x11\xcb\xe6^\xdb\x1d?\xaa{\n\xc0Y\x1b-%\xf2+\xf7L\xf6\xbd\xbc\xd4\f\xa4r\xf4R\x8b\x19T\x89_\xf2\xf5\x8d\x97\x97O\x01\x00(\x15'y1`\xf6\xfdc\x91\x19H\xbe7\xd5w\x8a?\ueb9f\xd4}\x05\xe0Ԛ\xe9\xc0\xfd\xee\x9cl\x9b\xb9\x14洚\x83TNf-\x87\xd7|0{\x15\x88\xd3\x18U\xf3T\xf9\x15\x00\x80\x18/u\ae\xfc\xf0\x03\xee~\xdd\x1c\xa4rr\xe7k\x9d\xefMe\xfd\x0f\xe0\ue771\xdd[\x00\xe6̼\x96\x18纗\xb2폯\x98\x81TNn\x9di\x06U0\xfcg\xd3\xf1\xc2\xef˷\x004o\xddF\xc4U\x80\x8c\xbb\xfeEX\xee\xed\x80RYXV\x84߿h\x0e\x99\x17\x98\xc2\xd8\x1d\xba\xf5>\xac\xa4\xdb_di\xc5\x14b\xf4f\xb1\f[\xd2\x0eW?o\x0eR9\xb8j\x06,\xf5\x16\xc0\xac\x9f\xfe\xb7\xd1\xdazYw\xff\xd4\xee/\x00c\xfa\xbf\x0e\\\xed\x0e˶\xf3\x9f\x84\xd4\x0f\x1d\xa5>U\x8a\xf0ÿ\x98C\xf6\xe7?\xbf\xe1\xf4\xfaY\xe5_\x00\x00b\xf1B\xf7X\xb6=\xb3\b~\xe7*\x80ԧ~\xf3\x9c\xb7\xffU\x87℞\xf8\xa9\xa1\xc7^\xef\x94\xf4^B8\xd0\x1d\x97]\x1b\xf7\x87g>\t\x83j\xccB\xeamK\xdaa\x97\xab\xe0\xb5\xe5f\x91\xf1\xd3\xff;9%\xf9@O\xfc\xe4\xa4\xe7^t\xea*@\xc6\xcdZ\x0eg?l\x0eR_\xf8\xdaC\x0e\xff\xaa\x90\xa6\x17\xf5ԏ\xee\xb9\x02p\xe7\xf57\x10\xe3t\xf7^\xb6]:\x1d~3\xc3\x1c\xa4\xdet\xf5\xf3\xf0\xe3\xa7͡\n\xce\xfe\x9f\xe6\xae\xeb\xffPy\x05\xe0\x9a\x13S\x88\xe3݁\xd9w\xca=\xf0\x98O\x7f\x90z\xc5#s\xe1+w\x9bCu\x9c\xfd\xc7\xf3:gi\xa5\x15\x00\x80\xd9\xcf\\\x01\xd1GTd\\K\a\x1c9\x15\x9e]l\x16RO\xfa\xc7\"8\xea\x8f\xde\xf6W\x1d'\xff\xf1\x9f\x14_\xf8]O\xfe\x8a\x9e-\x00ͻv\x90\xc6\t\xee\xc9\xec\x9b\xd3\n\a\xdc\x00\x0f\xcd6\v\xa9'<:\x17\x0e\xbe\t\xe6\xae0\x8b*)\x00\x17t\xf7\x83\x7fz\xb7\x00\x00\x14\x17]\x06q\xa1{3\xfb毀\x0f\xfd\xc1\x87\x04I\xdd\xedw3ఛ\xfd\"\xae*\x1a\xfe\vhY\xf8Ӟ\xfe5=_\x00\xc6\x0em!r\x89{\xb4:\xb4t\xc0'\xff\x04\xa3\xee\xed\xbcMI\xd2\xfa[\xdc\x0e'\xdd\x03\x9f\xbe\xc3e\xff\xaa\x12\xe2E\x9c\xb5\xd1\xd2\x1e\xff5\xbd\xb21\x17-\x1aD\xbf\x81/\x11B\xa3{\xb6zl\xda\x1f~\xb8\x1f|z{H\x82yH]\x95F\xf8\xd5sp\xd6Ý\xb7۪\xaa\xce\xfe\x17\x13\x97lMSc\x8f?\xe2\xa9\xf7\xfeX\x9e\x92~\x8f\x10\xbe\xe5ޭ>;7\xc27\xf6\x80\x13\xb7\x83\xfa\xbcyH\xab\xb3\xac\xd8\xf9l\xff\xf3\x9f\xf4\xa2\xda\xea-\x00\xe9w\x18\x95;\xb7W\x16\x1azm\xa3&/j$\f|\xd1U\x80\xea5\xa0\x00\xc7o\x03Gl\x01\x87m\x06#\xea\xccD\x9a\xdd\nw\xbe\nSgv~\xab\x9fK\xfd\x9e\xfd\xf7\xc6\xd9\x7f\xef\x16\x00\x80\xc9\xe9\x0fH\xc27\xdd\xcb\x02\xd8b\x00\xec8\b\xb6n\x80\x815\xd0P\x80\xfe\xae\x10(Ö\x17;\xaf\x93Y\xd2\x0e/\xb5t\x9e\xe5\xcf\\j.\xfaw\x03h\xe6\x94份\xf5\xdbz\xb7\x00\\\xd02\x94\x01\xf5/@\x18莖$\xe9\xdf\xc3\x7f!\xe9\x92m{\xeb\xec\x1fz\xe3.\x80\x95}\xada>\xe0\xd3\x01%Iz\xcb\xfc\x8f?\xea\xcd\xe1\xdf\xfb\x05\x00`\xf1\x82\xff%F\x1f\x17#IR\xe7\xf4\x9fCǢ\x89\xbd\xfd[{\xbf\x00\x9c\xb5\xd1R\x88\xe7\xb9\xc3%I\x02b<\x97\xb1C[\xb2_\x00\x00:^\x98L\x8c/\xba\xd7%IU>\xfd_b\xf6̟\xf4\xc5o\xee\x9b\x020v\x87v\xd2\xf8}w\xbc$\xa9\xaa\xa5\xf1;4o\xddV=\x05\x00`\uef7f\x84\xf8W\xf7\xbe$\xa9:O\xfe\xe3\x93̹\xf7\xd7}\xf5\xeb\xfb\xf6\x01\xadS\x8a\x87\x11rwz\x14H\x92\xaaO\xe9PN\xc9\xdf\xddW\xbf=\xe9\xd3m\x1f\x95\xbf\x8b\x18o\xf0 \x90$U\xd9\xe9\xff\xd5}9\xfc\xfb\xbe\x00\x00t\xb4\x9f\t\xb1̓A\x92T\x1d\xb3?\xae\xa0\xa3\xfd\xac\xbe~\x19}_\x00\xc6־\x00\\\xec\x11!I\xaa\x12\x170\xa6\xf6%\v\x00@\xfb\xc2\xef\x13\xe3\xeb\x1e\x13\x92\xa4\x8c\x9f\xfe\xbfʒ\x05\xe7\x97\xc3+)\x8f\x020vh\v\xc4\xff\xf2\xc0\x90$e{\xfedz;\x1f\x88g\x01xӝ\xd7\xfd\x9c\x18\x1f\xf1\xe8\x90$et\xf8?\xcc\xec\xef\xfd\xba\\^N(\xabp\xa6t\x1c\x00\xb9\xfb\b!x\xa4H\x9224\xfc#\x94\x0efT\xe1\xberyIIY\x054\xaa\xf0\x00\x81k\xe31'I\xea\xe3\xd3\xff\xa7Y:\xe7\x1b\x95\xf8\xca+\xf7\xe1:\x93\xdb\xdfC\xc8?H\b5\x1e\x80\x92\xa4>\x18\xfem\xc4\xe2~\x8c\xaay\xb2\x12_}R\xb1\xb97\xd5-P\x922q\xe6\xdfA)=\x91Q\xf9\xbb\f\xc3\x02\xb0v\xa3\xf3\xb7\x11\xd3\xcf@,\x1a\x86$U\xec\xf0/\x91\xc6\xcf3:\x7f\x8baX\x00\xbanT\xfez\x88_\x85\x98\x1a\x86$U\xdc\xf0\x8f\x84x\n\xa3s\xbf3\f\v\xc0\xba;%\xf7Kb\x1ck\x10\x92Ta\xc3?\xc6S9%\xf7\x13ð\x00l\xc0J@n\x121=\xdd $\xa9b\x1a\xc094\xe5&\x9b\x83\x05\xa0;J\xc0E\xc4\xf8}\x83\x90\xa42\x97\xc6\xef2*w\xbeA\xac\x9dO\x02\\\x17SJg\x11\x92\xf3\fB\x92\xca\xf1\xc4?\x9eϨ\xe4l\x83p\x05\xa0'V\x02\xce'M\xcf2\bI*\xbbS\xffo;\xfc]\x01荕\x80S\ba\x12\x04\v\x94$\xf5\xedY\x7f$\xc6\xd3i\xca]l\x18\x16\x80\xde1\xb9\xf4Y\x92\xf0\v\byÐ\xa4>\x19\xfe%\x88\xffɨ\xdc\xcf\r\xc3\x02\xd0\xdb%\xe0DB\xf8\x15!\x14\fC\x92zu\xf8\xb7\x13\xd3\xcfҔ\xbf\xd60,\x00}cJ\xf1(Br\r\x84:Ð\xa4^\x99\xfem\xa4\xe9'i\xca\xdfh\x16\x16\x80\xbeui\xf1\x10br3!4\x18\x86$\xf5\xe8\x99\xff2Bz\x1c\xa7\xe4\xffd\x18\x16\x802Y\t\xe8\xd8\ar\xb7\x12\xc2\x10Ð\xa4\x1e\x19\xfe\x8b\xa0t\x14\xa3\n\x0f\x18Ɔ\xf3*\xf6\xee2\xaa\xf0\b\xc5҇\x88q\xb6aHR\xb7O\xffY\x94\x8a\xefw\xf8[\x00\xcaӘ\xc2c\xc4\xf6\xfd!>m\x18\x92\xd4mg\xfeO\xb1\xa2}?N\xady\xc20,\x00嫩\xf6E\x96\xb7\xbc\x8f\x18\xfd\xeeiI\xda\xf0\xe9\x7f'qɁ\x8c\xab}\xd9,,\x00\xe5\xef\x8cA\v\xe9x\xfe#\xc4x\x85aH\xd2z\x0f\xff_\xd0\xfe\xfc\x1145.2\x8b\xee\x973\x82\x1e2\xf5\x92\x12\xfb\x84\x1b\xe9\x7f\b\xc0!\x84\xe0\x05\x97\x92ԥ\xb9\x1f#\x91s\x99}\xee\x19\x9c\xf5\xf1\x92\x81\xf4\f\x87Ro\xb8\xb4\xf4\x05b\xb8\x9c\x10j\fC\x92\xd68\xfc\xdbI\xe3W\x19\x9d\xbb\xd20,\x00\xd90\xa9\xf8~\x92\xe4:Bh4\fIZ\xe5\xf4_H)=\x9e\xd1\xf9ifa\x01Ȗ\x89\xed#\xc9\xe7\xff\x00akÐ\xa4\xb7\x9c\xf9\xbfHG\xc7Q\x8c\xed\xe7]T\xbdċ\x00{ө5\xd3im\xdd\x1f\xe2C\x86!I\xff\x1e\xfe\x0fж|?\x87\xbf\x05 \xdbN\xaf\x9f\xc5\xe3\x8f\x1fD\x8c\xe7\x1b\x86$\x87\x7f\xbc\x9c\x8e\xe7\x0fc܀9\x86ѻ\xfc\b\xa0/M)\xfd\a\x84\xcb\b\xa1\xbfaH\xaa\xb2\xc1\xbf\x824\x8eft\xeeg\x86a\x01\xa8\xd2\x12о\a\xe4\xaf'\x84m\fCR\x95\f\xffW\xa0\xf4\tF\x15\x1e1\x8c\xbe\xe3G\x00}mT͓,[\xb6\x0f\xc4\xdb\fCR\x15\f\xff\xa9\x94\x96\xee\xe9\xf0\xb7\x00\b\xe0k\r\xf3\x99u\xee\x11\xc4\xf4l\x88\xa9\x81H\xca\xe0\xe0\x8f\xc4x>w^{4\xa7\x0e\\` }Ϗ\x00\xcaͤ\xe2\xd1$ɕ>/@R\x86\xa6\xff\x12J\xe9\x17\x19\x9d\xff\xbdYX\x00\xb4&\x13\xdbv _\xb8\x1e\xc2n\x86!\xa9\xc2\xcf\xfc\x9f\xa1\xa3\xe3xo\xf1+?~\x04P\x8eN\xed\xf7\x1c\x8b\x17\xec\x0fѫc%U\xf2\xf0\xff1鼽\x1d\xfe\xae\x00h}L)\x1eOH.\x870\xd40$U\xc8\xe0_D\x1aG1:\xf7;\xc3p\x05@\xebkT\xfezZ[w#\xc6[\rCR\x05\f\xff;\xe8X\xb1\x9b\xc3\xdf\x02\xa0\xeepz\xfd,f\x9f{$i:\x0eb\x9b\x81H*\xc3\xc1\xdfA\x1a\xbf˝\xd7~\x88\xb1\xfd_5\x90\xf2\xe7G\x00\x95\xe6\x92\xf6\xdd\xc8\xe7\x7fC\b\xef2\fIe2\xfd\x9f\xa6X\xfc,\xa7\xd6J.\x1c\xfbF\x19h0\x14u\xe3\xd4_B\xe46\x887\xd1\xd6r\xb3_\xc4#\v\x80T\x8e\x9a\xa7\xe5\x18\xf1\xbe\xfd!w\xf4\x1b\xdfE\xb0\x8b\xa1h=\x86\xfe\vD\xfeDLo\xa1\xf8\xe2m\x8cݡ\xddLd\x01\x90*ɤ\xb6\x9dI\xf2\x1f\x81p8p\x88w\x14h5\x03\x7f)\x91\xbb\x89\xf1v(N\xa5\xa9߳f\"\v\x80\x94\x15\x13\x9e\xab!\xb7\xcd\x01$ɇ\x80Á=\xbd\x90\xb0Z\xe7},\x01\x8f\x13\xf8?Ho\xa7\xfd\xc5\a=˗\x05@\xaa\x16\xe7\xcf\x1b\xc0\xa0\xc6\xfdH\x93\x03\t\xbc\x0f8؋\t3<\xf0\x03O\x92r?!\xdeGi\xd9\x1d^\xb5/\v\x80\xa47\v\xc1\xc0\xc6\x03\x88Ɂ\x04\xf6\x05\xf6%\x84A\x06S\x91\x03\x7f\x11\x81\x87Iy\x88$\xbd\x8f҂\a\x19=|\x99\xc1H\x16\x00i\xedN\xb8:\xe1\x90\xe3v&\x97\xdb\x17\xc2~\xc0\xbe\xc0HB(\x18NY\r\xfb\x0e\xe0\xa9\u0381\x1f\x1f\xa2X|\x98\x05\xff\xf3\f\xcd\xcd\xd1p$\v\x80\xd4=\x9a\x9f*0b\x87\x1d\x89\xb9\xbd \xecE\xc2^\xc0\xee\x10\x06\x18N\xafL\xfb\xa5\xc0?\x80\xe9\xa4\xf11B\xfa\x18\xb3\xe7>\xe6W\xe9J\x16\x00\xa9o\x8c_\xbe)\xfdkF\x92\x86]\ta$\x81]\x89\xbc\xdbg\x12\xac\xf7\xa0o#\xf2<\xf0\x14\x91\xe9\x84\xf8\x14\x94\xa6s\xe7\rO\xfbl}\xc9\x02 \x95\xf9jAs`\xf0Y\x9bSS؞\x10\xb6#\x86\xed\tlOd;`;\xcbA\\B\xe4\x05`\x06\x91\x19$\xf1yJq\x06\xa1c\x06s\xce\x7f\xd5%|\xc9\x02 et\xd5`\xf1`j\xeb6'&[\x91\v[\x90\x86\xcdI\u0602Ȧ\x04F\x10\x19F`\x18\x84\xa4\xc2\x06{Jd.\x81\xb9Df\x13x\x8d\x94\x99\x848\x934\xfe\x93\x90\xbe\f\xcbg\xd2Ըȃ@\xb2\x00HZ\xe5*´\x1c\x83\xf6\x19F\xbf\xc20b2\x8c\xc0\x10\x92\xd0HJ#Ih$\xd2H\xa0\x11\xe8O\xa4\x01\xa8%PG\xa4\x9e@\r0\bX\xb9@\xd4B\xa8{\xdb\xc0n\x05V\xac\xf47R`1\x91v\x02ˀ\xe5D\xda\b\xb4\xbc\xf1\u05cb\b,\"\x8d\x8b\b,$\x8d\x8b\x80\x85\x84t.m\x1dsy\xe0\x0fs\\\xa6\x97\xca\xdb\xff\a\xa3\xab@>\x15\x1e\xe1\x8e\x00\x00\x00\x00IEND\xaeB`\x82"), "InternetbsAPI": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xe1\x00\x00\x00\xe1\b\x06\x00\x00\x00>\xb3\xd2z\x00\x00\x01\x84iCCPICC profile\x00\x00(\x91}\x91=H\xc3P\x14\x85OSE\x91J\x11\v\x8a8d\xa8NvQ\x11\xc7Z\x85\"T\b\xb5B\xab\x0e&/\xfd\x83&\rI\x8a\x8b\xa3\xe0Zp\xf0g\xb1\xea\xe0⬫\x83\xab \b\xfe\x80\xb8\xba8)\xbaH\x89\xf7%\x85\x161>\xb8\xbc\x8f\xf3\xde9\xdcw\x1f 4*L\xb3\xba…\xdbf:\x99\x10\xb3\xb9U\xb1\xe7\x15!\fP\r!,3˘\x93\xa4\x14|\xd7\xd7=\x02|\xbf\x8b\xf1,\xff{\x7f\xae~5o1 \x12Ǚa\xda\xc4\x1b\xc43\x9b\xb6\xc1y\x9f8\xc2J\xb2J|N嫠x\x05\xeb\x10\x89\r\xd2[D\xcd(l\x02\xd33\xe8\xdf9\xb4Y㧵\x954\t\x13\v0\x9c\xeb\x87$\xf6k\xd7\b\xd9l7\xd5\"Z\x90}`\xf6\x06\x02\x05_\xa8\x88#P\xf2\x9c\xd2&\xa14\xe7\a\"\xdc\x1b\xc4\xc18\x9e\xfb\x9a\xddT\x8bh\xc1\xe9\r\x12L\x06K\xc7>\xb4\xf9\xfb\x12&au\x03\xc8\xf7\xee\xb7\x05\v\x1c\x141P\xfb\xec\xa6ZD\v]Y\xb4\x97\xf5=\xa4\x03\xf0@\xa6Ì\x1b\x86L\xc2\xfcb\x8c:\xe5@)\b~г\xefu\xbb\xa9\x16\x11C\x16\xc9.\xf6{H\vҰ\a)ה&\t\xa5\xb8\x04t\xc7A\xdfUA\xd0\xd3\xc2\"z\x10\xb2\rp\x0f\"\xa1\x8b\x11\xef\n\xab66D\x12V7\x80\xb3\xf4P)\b\b\xfd\x96\xddM\x8bH\xc2\x13=C}\x17H\xa38\xa5\xb4H\xa8\xf4*\x8c\xee\x1e\xe2*q@\xbclw\xd3\"\x9a\xc8\xef\x05\xe1\x1e\xfa}\xd3\xe7\x87+&\x9f\xca\x16\x1e\t=\xf7\xf8C\xc56\x00\x0eB\xbca7\xd3\"\x9ap\x9a\a\xb2\xbe\x0e\x91\x86\xf2hH\x1cV\"$\xac<\t\xe1\x9cz\x88Wԗ\x84q\a\xea\xe4\x12!\xa1\xf7\xbeaTQ0\xa6\x05\xdc^\xbb\x99\x16\x91\xc5H\x8eE#\xe6O\xd6K\x1a\x06\tS\b\xb5lhU\x14\x05ƶ\xb3\xb0\x88:\v\xdb\x0e\n\xd8\x0f\xb2\v\xa9\t4\xc1\xe9$a\xfc\b\x84\x9a3\xa4*:p\x8b\xd8\x12&\x8b(\xa3P\xdc;$\x14\xd2;fzI\xa8\x9ceC\x87&\x06X\x98\xb7\x9bh\x11q\xe4\x001\xcc\xf9\x0e\xec\u0089\xd7\x19N\x9e\x84Ç&\x18TGhUR\x8b\xe8B\xab?\xef\xaf+<\xe4\x7f\x82a\x11\xe4\xe2\xd3GB)\x8f\x18:\x98iaQ6,\xec\x1aI\f\xf9\xe6\x98n\x9c&\x12&\x16`\xc4,\xbf\x9b\xdap\x7fA\xf5`{\x8dZD\xdb&\x1c\xf9\xfc\x1a\xdd=\x99\x14\xb6\xc9J£\x80Y\f\xe7\x94\x01\x05\x9e-a\xb2\x888\x12\xbb\x82\x1e\xa4\xc3\xc1\r̲\xe9 \xa1\xac\x1e^W\xf6\x8dB\xbb\x81\x16\xe5\x0f\xe3\"\xd4\xe2\xe9!\xa1\x12\r\x1cRkea1\xf3\xf4U\xa0~:H\x98\u0098\xf9\f\xeb\x19\xb5\xb0\x98i\x98X\x03\xa8I\x90\xb0A\x01\x87م\xb7\xb0\x00?\xa3Ɲ;\xc5$\xcc\xc5\xc1\xd4\xd9\xf0\x84\x85E\x01\xb19So\x13\x1aY?bx\xc2\xc2b&A\x99\xca)&\xa1\x9b\x04S\xcd\xf0\xe1\t|{Q\xcd\xc6\x0e\x06\xb5\x884\xf2\x8b1f\xb4\xf4K\x0529\xf5\x92\xd0Oܶ\xb0\xb0\x000n\xedԓpt\x96\xba\xc0B\xa8\xb6\x92\xd0\"\xc2j\xa6ZxPG\xf9PQd\x12j\xc0\xc4|\xd5\xd5\xc2\"\xaa\x12\xae\xb8\xa1\xb8bO\xea\xf50\xea\x18\xd0\t\xbb\x93\x16\x11\xc6\xc2bF\x01&㘙;\x06c\x15\xa0\x16D\xa3\xddG\x8b\xe8JB1\xbf\x98Q\x80I\x90\xd0i\x1e%\xa9\xb5\xf0\x06}Hs\xb2\xddI\x8bh\"\xbe\b\xccA\x03\x8e\xa2\xa5\x8e\xe2\x8f\x1aV\x1f\xb4\x9bi\x11M\xa8w\x8eR\xa4\x10\x05\x12\xe2!\x9c\x13\xfd6\xf9\x16\x16\x11\x83\f\xa7\xd5\xfdt\x93\x10\x8c\x97A\xb9\xe7\xd8\x1d\xb5\x88\x16\x92\xf30\x9c>L'\xc1\x92\xb0\t{1z\xa4.T\x83\xe1b\xc4{\xb1\x993a!5ʗE(\x10K\xfcV\xf7c\xb2\a\xbd\x89N\xa3v\xc2\xe1\xf1h\x9e\xa3\x81QR\uf01e\xff\xb2\x9b;\x164TC\xd7\\\x10\x8d(1\x17dr #C3\xb2\xb7Y\xaa\x1e\xf0:\x80\x1cB\xb6\xf9\x93\x85\xf2{!\xb1\v\xba\xecH\x821\x1fm\xf3\t\xcc!\xa3\xfeF\xa0\xe1\x90\x13\x9c\x8aI\xc2x\x0e\x91}\x15cN\x1d\xd3-\x015\xe0^\bX\x12\x1eB\xb6\x9eY\xe0\xceE\xcaw\x83Z\xec_X})_\xc9\x10Npǩ\x81\xed\x12\xa3\xdc\xccf\xd0\xcf\x1a<\xbf\xbfA\x05๐\x02\xc1\x8b\xc0.4O\x81y\x06\x9cޠ#\x9e\xed\x054\x80\xc4r\x7f\xe0\xadΌ\xfdw\xf2{\xa7\x98\x84-\x1e\xa4\xde\xf6\xeb\xa8\xcc\x18ĵ\xc9!b\xab1\xce\xddV\x1a\xc6\x17\x81hD\x9a\xe3!\xbb\x18\xa3N\x05U\x8b19\xc0\xf5m\x90\u009a\x9a\xf0]\xe3F\x1e\a\xe6\x04\x84\xf8DpG\xbe\x86H\xfd\x1ea^\xc2s_\x83\xfc\xce\x19N\xc8\x14R\xae\xc1\x98qH6\xe1\xfa#\xe1\xf3SIB\xb2\b\xf1\x06\x06\a\xbf9\xeaXv\xbf\ai.A\xb3~\xe6mrb\x01J\x9d\x851\xcb1b.\x88Y\x18\x93\x00\xd3\x17\x8c\xde\xcaLݳh\xcf\xd7N\x06\xf2!\xeb1\xe2#\x18\x01\xa2\xa2\r\xe1\xbc\x05\xe2et\xfeg3\x93\x90\xa9\xb31\xe2\x8cq\xe4\x8b*\x7fM'6\x12^M\xeaYM\xecH\x84x?c\x0fdz \x8eBJ\x8d\xf1\x9e\x98\x19\x12/~&2\xf6yD\xecf\x8cY\x82ߝ.\x11H\xb8<`J\xe0AM\xf0,y\xffbV\xf5\xc0\xf1\xc8\u0605\xe0\xfc5RV`\xa4\x80t\x17d\xfb\xcb~τs;\x18=\x8e\xbd\x91\b\xb3\v\xe3\xfe\xc748f\xf2{\xa1\xa2\x13\x18G0Ӹ\x18\xb5\x16\x12/@\xdf#幑\xb1Ӑ\xb1\xf3}\xf7\xb68\x02c\xfa\xc0\xdd\x13\x9d\xe7\x0f$\xa5\xf1\xf6\x02\n\xe3\\\x8a\x109D\xf6\tD\xf2wx\xbd[\xcbS:V7 \xbdk0f\x1c\xda\x1d\x04\xc3b&<\x8dZMr\xb3ڑ\xceY \xea\xc7qk\x18@!\xd4߀\xf3:\xe4_.\x9b\rTj5\xc4oE\xc6.\xc1\xb0\x00d\"PiL\x84_,\x90\x92\xc6\x00Gb\xe4\nd\xf2\xcb\b\f&\xd1;QgD\xe9!9\x0f\xa9o\xc5\xc8\x13}\x13a<\x90\xb5\x98\xfe[@7M\x03\t\xc9c\xd4R\x84:\x86\xf1\xe5\xd6\x19\x10\xfd\bNE99\x8c\xbb3\xd2F\xbcJ\xfe5\xc2\xfc#F]\bF\x80\xe9\nl.Cy! \xa4\xee\x04u:\u009c\x8b\x94\xd5\x18'\x03^&\xba\xaf\x95X\x80\x947\x04\x04\x9c\x80\x84\x17\xfd\x10\xfb\x0e\xf4g\xa7\x83\x84@<\x81\x90\x7f\x05f\x9c\x83@\x8d\x01\xe2\x18\xb9\xdc\x0f\x88V\xbc\x04ngt6\xae\xa1\x1ae>\n\xf1\x8d\x18\xf1\x01\x90i\xd0وK\xbd\xf1]\xc0\xa0@\x9d\x8c\x10\x1f\x06yl\xf4\xf60\xb8@Q_\x031o\xfc\x12\x10@\xc41\xeeÐ}\x90\x89\xb8F\xc3!a\"\x83\xe0S\xe3'\u181bU\xa8\xe3\x10\xe2<\xa4Labo\x83\xdbQ\xda{\x97X\x8e\xcc_\x87Q\x17\xf8\x92o@]\x9bi0\x81\x06d\xfc=\xe4þdL\xfdi\xa2Ra\xca.P8\x17\x19\xfb\fF}*p\xc2Lp\x84\x9f\x88\xa3\xe4O1\xf9?L\xf4i\xc2iS/S?\xc0p\x1c\x93+\xf7P~\xb6\xbaiB\xb0\v\xcd/@=VZ\x19\x1e\xc9yH\xb1\x0e#O\r\xb2\x84<,\x0e\xde\xc3\x04B\xefD\x8b\x1fA\xf6\xfe\xd2z\xbc\xd8iHy&\xc8\xd3\xfcbs\xe3L\xbem\x85\xc8a\xfa\xaf\x82\xe9&!\xa9U\b\xf1u0=!0Z\xf9\x8b\x83\x83Pi\x8c\xf7*¼\x01\xde\xd3h\xf5\xa7\xc0#\x9b\xf3Ӳb=SC\xd2\xea\x06\x94^\x85況\x00\xc8Y\xbe\x8dBF\xa1\x1a\xc0\xfb9ڻ\x13r\xafL\x8dt\xeb\x99\xe5wqp\x92\xe0\xd5!\xcd\xf1h\x16\xfas\"\xe4\xd1\xc1\xde\xf5\x05\xfb\xe7\x85rV\x85~\x11\x9d\xfdԤh\x1c\x9aa+\xe4\xb7\xf1\xfb\xf1{\xa1ohA\xec\xef\x7fތ?\x86[\xb4\xa1\xbdl\x90+\xb9\x0f\xe1\xf4\xe1y\xbb\x82\xc5n\x02\x19\xe8\xf8\x95\xed\xd0\xd25\xfa\x06\x82\xdfEY\xa5Pb.F\xd7\x05-\x1b\x17bĒ\xf06o\xa6@\xc4\xc1\xec\xc5x;\x914!\x9c\x8e\xfd\xfb\xc3n\x10A\xd2q\xef\x9eQ5\x90\x01\fڟ\x81|ZU\v\x1c\x06\xa6\xce\x1f\xd5'\xeb\x81\xda`\xbf\x82\f\xa4b\xec\x9bL#\xbd\x1b\xf0z\x7f\\\x02$\x04d\xfc2\x8c\xf3ɉy\x97&c\xcb\ng\xd0\xf7ā\a`\xf0\x9b\x8e\xd0\x05\xe0\x806\x1d\aH\xb9\xc0\xe6\x11n\x10;\xb3\x98\x98\x8aꌸ?\xa3uh\x18y\x7f\x02\xb3\xe0\x80r#o\x8a\xde+\x8bI~d\xe4\v~*IHb\x01\xb2\xe27\x98(\x05\xa5-,&L\x9dJ\x84\xfb/\xe8\xdcw'-\xbf\xc2{\xa8\xbe\xd7\xc1\xfd\xcfb\xb7\x02\xb0\xb0\x98~H\x05\xe6M4\xbf\n\xe5\xd3B}6\xed\xdd\tt\x12J\xe8\xc3¢Ta\x12\b\xef\xfe\xb0\x1cN!\xb7\xb7Ƚ\x82\xb0\xd2Т\xdcm\\\\t\xf5ݡ\xc9\xd5\xd0\x1fQW\xff+\xb0\xd7JC\x8b2\xb5\x05\x1d\x8c\xb9a\xb2Θ\x03>\xb18\x0f\x9aX\x8e\x8c}?\xc8·\x98\xb0ݡ9г(\xe2\xfb=\x89\xa2b\x04u\xa9\xdf\xf7(\x0ex\x12\xddA\xdeC\xeb\xe5\x9d8]R\x18\xf7\x01\xc8\xdd@\x88U$\xa2xg(~\x19\xc6Yk\x03\xdb\xe3UuD\" \xcd^\x84iG\xeb7\xfd\x18\x9bl\xc63\xcd\xfb\xe3\x9f\xc3\xc5\xd6\n\xbdi\x9c$\x98\xf9H\xef\xc8 \xd6y\x18\x86\x85\xc0,\x10\x95\x145~V\xb6{ӎ\x91\x17\x85\x9d R<\x12\xd2P\x8d\xccމ\x11'X\"\x8eh_\x00\xb2\x16L\x1f\xc2lG\x88'\xfd\x80\xb6i\x82\x8a\xb6\x107<\x05\xf1#@ς\xd8\x1c$\x7f\xe9\xf7\xb2\x11\x87\xfb\x99N6\x16:\xea\xe5h\xbc/\x16\xa3\x06V\x14\xf7٫\x1b\x10\xde}\xc1a\xb3\x1b\xbc\x7f\xd9\xe3\xc1\x9a\xecE\x98f4\xff7ȓ\x9d\xcafKAk\xc4\xc4i`V\x06\xa9]\xf5\xe1\xe4S\x96\xa1\x1a*\xf5\xa6\xc9f\xc6L\x13\t\x01*OB\x98\x9b(NJ[\x14\xc9\xe7 \xcc\xef\x10\xe6wx\xec\x18=ek\xaaP\xdd\x00\xde\x19HN\xc1p\xbe\xaf\x16\x87\x91\v\x1cy\xdb<\x8d4\x9b\xf1z~X\xb4S15/2\xe0\xa8i\x99\x81D,\xa4m9\b\xf34Z\xdc\x0e\xc9]az\xd7\u0097\x90\xf1#\x90\xac\x84\x8a\xcfat\xd7\xcc͙\x95iL~+\xe4\xd6\x17\xf5j\x9e\xba\x17J,G\xc8/\xcf,\x89(\xe2\xfe@\x1co;\xf0\xfd\xa9\xa9&\bY:\xfa\xd5#\x1f\a\xe6\xce,\xc9(ӈ\xfc\x9d\xe8\xdc\xff.\xb6\x89 \xa6\xf6\xc5*OB\x88\x7f\x99\x01vG\xa1\x94\xe7w\xbe\xe4\x8bz\x9f\xd5\xf8\"$+1\xce\xc5\xf8^\xd52\xde;\xa9\x10\xa2\x01\xfa\xbf\x85\xce\xdd1%W\xf5\xb4ܮһ\xa5|\xbd\xa6\"\x85\xd0ϣ͖\xf2\xeb&\x17_\x84T\xd7\x04\x05ܔ\x9fF#\xe2@'\xc6\xdc>\x95\x05\xc9Ӑ\xd5ҟ\xc5\xd4\xfe\x1a\xd9\xe7\"b\x1f\f\xfaz\x94Ak\b\xa9\x80$\xc2܇\xe6V\xe8+\xc3.\xe3^\x06\x93\x7f\x00b\x7fF\x88\xb3\x03[\xb7L\x88(*\x11\xfa\x05\x8c\xb8\x0e\xb2\xbf\x9dҿ<\xbd/^\xb0\x13Ec\xb4\x8d\xff\x82\xed\xc7ͥ\xd7ҡh{\xb7\x00)\xafĈe rэ1\x06y\xce½\xcbO\xb9\x9cz\x87\xd94\xe7w\xba\xafC\xedVd\x9f\x04ut\x90\xc9\x11\x9d\xcdT1\x851)\x8c\xfb p5\xf4\xfe\x81\x19\x03\xb7\x03\x93\xff\x19\xaa\"W%z\x96\xf4W\xd4&\xf0\xf2Q\"\xa2\n\xd2\xd0\x1e\x04\xf7\x16L\xff\x7fLWw\xf1\x12H\xb2\xce\xf6c\xbc\xc7A>\x8a\x14G \x9c\xc2P\xc6\xf1\xb4!\x9fZ\xe2U$*\xa8\x9d\x93>Z6\xa5.[\x96\xff\xe5û\xbc\xeb\xc1\x9d\x99#\xc7L\xfe\xe9\x9bW\x919yN\xf6\xc3\xdb;\x17&Q1\a\xcfu1ڔ.\xf9d\x1d\x98,\x86\xafC\xdf\x0fA\xbf>\x9d\x0f$Jo\x8d⋐\xea\x02\x8cx\x0f\xbe[\xbc\xafd\xa4c<\x15\xafʷ\xf4.;\x82\xc4\r\x7f\xcd\xdc\xe3k\xb8\xa5\xf6k|\x13\vZ׳8\xd3\xcf\xff\xfc\xfe\xd34\xfcۣ\xbc\xd9DC\n7\uf58et\x14)0Y\x04\x7f\xf4;\xf9\x95\x8e\xd9 Jw[\xe3\x8bP\xf2\x14\xb4\xb8\b\xa1\xde9(h̔\x91R\xc5|M!YS\t\xb0\xe6\xc8=\xee\x95g1\xff\xb8z\xeau\x96\xb5\xe9۸\xdb\xd2\xef@\"\xaa8w\xb7y\x9c\xf0ӧ\xf8\xd3w\x1ee\xdf\xf3\xea\xd8\xd9\xf4d:\xa7\x81\x90A\x92\x84\xa8\x04Ӄ0[\xd1\xe2>\xe8y\x95\x12\x9b\xa3!\"\xb0\xb7\x8328\xe4i\x18Y\x0f4\xf8\x8b\x1c\xa23G\xc5\x14Nl\xff\x80\x1c7\xefV\x99\x8e\xfc\xfcj\xc4\xea\xbf\xe0\xf0Ϝ\xc9Q\xe98J\xc4!\x9faY\xfd&vX\xda\r\xa1\x9dn#ޱ\x83\x9f\v\x87\x158\xf0B\x13\xad\xb7>\xc4\x1b;v\xd1ՙGt\xc7\x1a\x92\x83\xd78Db\xee\xcfL\xf2\x93\n\xda1\xdeNP\xbf\x85\xec\xaf)\xe1\x016\"b{\x1cT\x02\xa8w\"\xbdc@\x9d\x8c\x91\xc7!D\x03FwS\x95\x1e\x9f\x8d[\x91\x8c\x03T\xb5\xbf\xbc\xb7&\x869q6ɣ\x1b\xa8X<\x87dC\r\xc9w̦f\xd1\x1cj\x1d\t\xae\vHp\xbb,\x01GC\xd3\x054$\xe7\xf1?d\x8a5NP\xf5\xb8\xaf\aoo\x1b\xedO\xec\xa2u\xe7^z_k\xa1\xff\xd9}\xf46\xe5R\x8a\xf4\x91\x87\xd1\xdf;\xb1\x98qw\x9b\x7fq\n\xef)\xb4~\x13%\x9f\xf2K\xbeb;\xa32\x1a\\D{\xbb\x1b\xaa!\x17\x87|\xe5\xa7O\xec\xbb\xe8\x83'\xf3e\xb7\x9f1\xb7\xd0?\xaa\x9e\x94\xa3p\xeak\xa8*|/\x9dD9\x83\xfa\r\xb8:p\x11ip{-\x01'*\x11\x0f^\xd3L\xef~\r\xa6\xb5\x93n\xd7\xc3\xdd\xdd:>i\xd5\xd6\xc1+\xff\xf0\xf3\xd8U\xe04Gy\xe4\xb7(\x9b\r\x7f\x8c\xc7c\t\x96L\xe6s\\=\xc47\xb5/\x01\xbd\x1eV\xa77r\xbf\xa5\xd78\x84\xd4f溝\xdcS \xe2\xc1p&\xd9\\\xc5S\xe0\xb6G\x7f_d9lvۯX\x83a\x89\xab}\"M\xf4kH\x82\xe7A\xbb\\a\t8~T\xad\xa3\xd9\xcb\xf3\x15\fM\xe8\xa1/\xbd\xc9|\x99^\x10\x1e\x9f4ۈ[\x12N\xf3m\x8b\xe4\xf3\xa3\xf4p\x9e\x18\xf4@.\xcc\xcbQ\xdf\xe8\xe9B\xfd&v\xb8}\xfcmA\xa5\x0f\x15\x0e\x888k\xda~\xcb\a-\t\xa7\x11\xfd{9GU\xb3\xb4(o\"\xfd\x83\xa3\xe2lm\x7f\x98\xbb2W\xb3\xca\xd2jbD\xf4\xfa\xb8&t\x12\x02\"\x06RqE\x94\xd7'\xd26a\xd3\x054\xa4\x16\xf1\xa0pXR\xf4\xeb\xc4\xf5o^\xaf\x93-FpG\xfd&vZz\x8d\xcfno{\x90\r\xaa\x86+\x87\xb2\x0f'\xab\xb1x\xbdѵ\r#-\t\x13Gq\x06f\n\b\x18\xa8>hP).q\xaay\xae\xed+|\xa1{3s-\xbd\xc6xۯ$W1\x97\xdbD\xb2\bj\xa9\x06<>\x14U\x93!\xd2$\x94\x8a+\x8ab\v\x8e\xb4Z\x01\x19e\x8c;\xfa\xdf\xe6\xbe\xcc\x15\\h)66T\xad\xa3\xd9mg\xb5ɇ\xbf/\xaa\x86K2\x8f\xf0\x0eK\xc2)D\xe6jV\x89\nVL۪9\xa0\xaaY*S\xdc\xd5~\x1dOg\xaef\x95uތ\x8e\xba\xf7\xf1\x80α\x057\xe4\xfdpA\x1a\xbejI8\x95\xea\x8d\xcb\xd2B\fo:WO\xc4AH\x96\xa8$[\xdb\x1edC\xebz\x16[\xaa\x8d\xac\x96\x1a\xc1\x1dÅ-&c.\x888k\xa2x\x11F\x92\x84m\xb7s\x94L\xf1w%\xf3\xf4\x81\xa3A\xd5p\xa5\xaa\u0e76/\xf3uk/\x0e\x8f\xfaM\xecԂ\xdbBWK\x81\xf6\xed|ڒp\n`\xf6q\x82\xd14\x96\xd4\xd3\a*\xaa\x88\x81\xac\xe4Z\xaf\x87'3Wp\xa1UQ\x87Ƭ\xd3\xf9\xb6\x90\xe1JC\xa1\xc0\xb4qZ\xd4\xd6<\x92$\x9416\bU\xc2+\xea\x8fpiT\xd5\xdcձ\x83\x9f\xdb\xf8\xe2\xd0j\xa9\xd7ͺPUR\t\xce\x02\xd6f\x1e\xe1ݖ\x84ED\xf7f\xe6bX\x12z\xac\xa9X\x92\xb1\x82\x15\xd2ak\xdb:~Һ\x9e3-\xfd\xf6\xa3b\x0e\xbf\xf2\xda\xf9ihD\x94\xa0\xbb\x816N\xb7$,\"\xfa\xf7rN\xd4\x14~\x11\a\x99bM,\xcdvk/\xeeG\xd5:\x9aI\xb0=L\xdbP(PGD+f\x18=uT\xb1\\Dq\xfch\xd0\xeeXVr\xad\xd7\xc7[\x99\xab\xb8ڒ\x11\xd27\xb3Q(\xc2\v\xe0;\x80\xcbY=\xcfQgIX\x04\xb4\xdd\xceQ\x18N\x8al`\xa5`/\xfav\xedMn'\xf7\xd8`?\x18\xd8\x12v\x16M\x944\xa6H\x1dg\xddL\xa3\xaaei\xe4O]!\xbe\xe8\xb0BUsW\xfb\xb5<Ժ\x9e3g\xaa'\xd5\xeb\xe5\x8eB&RX*\xa9P|Ē\xb0(\xa2\x90\xd3M\x8e2\xa9\x82\f\xa4\xa2\xe3\x93\xd1I\xb2}\xa6\x06\xfbso\xb0Wwro\x98\x0e\x1ac\x98\x17\x95K-R\xc7Y\x1d\xc1\x87B\xb5\au\t\x91\xd1\xcf\x7f\xbc\xd2I\xf0\xcb\xccU\\=\x93\xa4b\xe3=\xb4\xe8v\xb6\x87zVR̋J\xa8\"2$4ۈ\v\xc1Y\xa1=\xb1\x9fy߄[\"d\x1c\x14_\x941n\xea|\x9c\xd7fT\xb0\xbf\x8e߇\xa6\x92J@\xd0(\\\x16Z\x12\x86\x88\xcc#\xbc\xc3\xe4C|b\r^?\x9f\xf6\xbaX\x8b\f\x9a'\x96\b\x19\x83aڍ\xaa\x9a\xbb\xda\x1f殙\x10_\xac\xdf\xc4\x0e\xd3\xcf3\xa1^ܽ\xbcӒ0L\x8d-\xce\xd9a\xaa\xa1F\xf3LE\x1dO\xa4o\xe3\xee\xdak\x11\xa6\x8f\r\x03\x92\xb1Tv\xc6\xf1㋪\x82\xed\xed7\xf0\xebr\xb7\x17M/[ü\bU\x9a\xf75]@\x83%aX\x1b$914{P\x83\xee\xe6\x81\xca\x13h\x1bІn\xe1\x9f\xdc>\xce\xf5\xb2l19(\x192:\x81'\xd5pV,]\xde\xc9\xe1Z\xf23\xe3\x85w\xb2\x85\xe2ؚ\xbf(\xf9ܪ\xe8\x90P\xb7\x87\x9c\xb0-xZ\xac$w\x90J\xb43\xbd\x99K\xbd~\x96\r\xa4S\x95\x10\x19\v\xc1~\xb7\x95\x87\xca\xd1^̽\xc1\xcb\"\x1e\x9e]h4\x8dV\x1d\r\tݛ\x99K,$\xb5B\a\x0e\x90\x8a\xe1\x9b\x04\xd7obG\xfa\x9fY\xe5u\xb0\xd6h\x9e)%{\x11\x7f\xba\xc2q2\xb5?9\xbc\\\xc8x\xf8Et\x99>\x1e\x0es\xad\xfb\xdb8Ւ0\x8c\x1b\xb2\x95z)\xa9\r\xed\x03\xf34\x89\xd9<7ڏ\xa5o\xe3\xee\xec+|@\xe7\xb9\x06\x02\xa9XB\xce\x1b\xe1\xb0BU\xfa\x9d\xe0\xca\xc5^\xd4Y\x9e\b\xf3\xf3D\x9cc-\t\xc3A\xadL\x0f\xccI\x9f4\xbc,{\xea.g\xf7X~\xb6\xf1\x1eZ\xd27\xb3QW\xb3P\xf7\xb0A\xc4KKEE\xfb\xce\x1b\xa7\x92\xe72\xeb\xf8^\xdb\xed\x1c\x15U\x02\x8a\x95\xe4\xbcvB\x1bU-\x14\b\xc2;73\x9a\x84B\x92\x0e-\xd3^\x83\xac\x1a\xff\xbc\x82\xba\xcb\xd9]w\v\xff\x94ϰ\xcc\b\x1e*5\x15\x15@ƹD\xb4q_\xdbW\xf8BTUT5\a\x1df\n\x1b\xa2\xf4\x9b?EC\x12\xf6S\x1bf?\x19\xd3=\xf1\xec\x8c\xfaM\xec\x98u=g\xeb,kM?\x0f\x97\xa0\x8a\xbaDƸ\xa3\xf3q^\x8b\xa2\xbdh4\x19\xf24\x85v\xba=Җ\x84a\b\xaf6TX\x92\xd0x@\xe5\xfe\xd0\xc4D\x91\xbe\x8d\xbb\x9d\x1a.\xf0\xbaX\x1b\xb4\xca/\xbd\xcc\x1bg\xc0^\x8cR\xb0\xbf\xc3\xf4\xd1\x19\x9a\x16U1\xb9!A\x96\x84\a\xe9\xf7\xa1ݶ9^\x0e\xe3s\xaa\xd6ќ\xbe\x8d\xbb\xa5\xe0p\xddí\x85\xd6{\xa5\xb2\xb3\x85bb\xa7\x9a\xed\x99u|/\n\xf1\xc5x=\xadZ\x8f}\xbc]9\xa0\xe4Ih\xb6\x11\x97\xb381t\x95'DT\xad\xa39\xfd\r\xbe\xecv\xb1\xcc\xcb\x06=5K)9<\xe8\x1c\xee\xf5\x97~1q\xe7\x1fq\xc9\x13\xeap\xcfRwVIf ro\x84#\t\x87\xb2\x17\xebV\xf0y/\xc7j\xe3\x96^|\x11\r*\xc1M\xfdos_\xa96\x9fj\xbc\x87\x16\xfai+\x99Kl\x8a\xeeI\x8b0\xd5f?\v\xe7~\xe0\xfe\xcc\x15\\\x88\xe4\U000ea4a5%\xb1\xd2\xd2\xffR\xd5,5y\xb6v\\O\x93\xdbǹ\xe9\xe5\xbczp\xf6\x90\x85\x95\x84e\x81\xf4m\xdc-\x1a\xf9\x84\xces\xd9@>j)Uj\b\x1a\x9dj\x9ek{\x98o\xda\xceᖄe\x8b\xba\xcb\xd9]w#w\x9a4\v\xbd,[J1دR\\R\xee\xc9ᖄ\x16\xd4]\xce\xee\xf4f.u\xdbY\xad\xb3\xdc[j\xc5\xc4&\a\"\xc1\xb5n7?\xb7\x9d\xc3-\t\xcb[E\xdd\xc8\xfd\xb3V\xb0\xd6\xebbm\xa9U\xf6\x17\x82\xfd\xaa\x96\xbb:\x1e\xe3q۬ؒ\xb0h\x88ϟޤ^\xb1\x92\\\xfa6\xeeV\x95\xbc[繬\xa4T\xd4\xc0y#\x1c\x96\xa8\n\xb6Ou\xe7p\xb3\x8d8\x15ԅy2cy\xfa,\t'y`u;φ\xfa\x99\xb24R\x99\xaa\xd6\xd1\\w#w\xe63\x9cp@1q\tIF\x99b\x8d\x93\xe0'm_\xe6\xebS\xa1\xa2\xf6Ag\xb9\x17(\xad`\xbf\xa2QVrm\xe7\xef\xe9+\xf6\x98\xf0\\+\xf52Iª\xa3\xa5\xf6\x90uxa\xa5\xad\t\x05\xba\x97٥\xf8\x9e\xf5\x9b\xd89k\x05k\xbd^V\xe3\xd1Tr\xc1~9hLx\xf1\x82\xfd\xb5BpXh\x9f\x16V2\xf8\x8c\x97\x84\x15t\x84\\\xdeR\xb25fb%\xb9\xf4F\xee\xafY\xca\xd1Fs\x99\xe9\xe1\xc5R\xf3\xa4\xaaJ\x96\xaa$[\x83\xce\xe1\xa1\xc6\x17\x85$M,\xa4\xb6\x14\x1a\x8c\xe4%K\xc20TQMF\xc4\xc2{cc\x98\x17\x05[\xb8\xeeF\xee4s9_\xf7\xb0\xa1\xa4\x92\xc3\x03\xa9(\x1cV8\x95~|1,2z{\x91\xb8!\x9eLë\x96\x84\xe1\xa0\xc3d\xc3S+\xa4\xa46*A\xe9B1\xb1\xdb\x15؋n\x89\x91\x11\xbf\xf9\x94\x93\xe0\x97m_\xe1\v\x93m1\xa8f\x87+Yu\x1f\xbb,\tC@\xbc\x9eV/˞ФL5\xc7\xe5Z9:J\xc6{\xfd&v\xd6m\xe6o\x83\xe4p\xbf\x19R\x89\xd5/\n\xc9\x1dU'\xf3\xf6D\x8b\x89\xcd6\xe22\xc9\aCӠ<@\x84\xebY\x9f\xb1$\xacZGsh\xe5-\xd2?\xbcQi\x91~0\xd2\x1b\xb9ߩ\xe1\x02\xaf\xa34;\x87\x9b\x1c\fj>5\xae\xf8\xe2[\xffF\xb5L\x848\xea\xc07e\xac$\f\xedAg\xd1\x14\xdaa\xd3\xd1i\x91>ܥ\x94\xbe\x8d\xbb{vrXIv\x0e/4\x9fJ\x0e\x04\xfbǤb\xc6\xe7s\xac\xee\x0e\xe9Tj\x10\x92\xa6x=\xad\x96\x84\xa1\xd9\u05fc\x18fwf\x95\xe6}QOVn\xbc\x87\x96\xc1\x9d\xc3K\xc6^,\xa8\xa8\xce\xc0\x98\xf0\xe7Z/勣\xad\xb7Ԝ\x1fj\a\x05\x8f\x97;\xffX2\xd7S\xf4I\xa8{y,\xcc\xcf\x13\x15\xacȵRO\x19\xa0\x10\xecw{Yf4ϔ\x8c\xbd\b\x03\xc9\xe1N#\xb7{=<9Rr\xb8\x88\xf3\xde0\a\xfe\xe8,O\x1c~\x11]\x96\x84a\xd9B\xcby2\xb4\xd9\xe6\x12L\x1e\x84\xe0C\x94\x11\xea7\xb1\xa3\xf6\f\x96z\x1d\xac-\xc9\xca~E\xe3\xe0\xce\xe1\x83\x7f\xa4u=\x8b\x85\n7\xa7W\xb7\xf3l\x14\x8a\x95#\x95\xc0mtx\xa3\xb3D\f\x9c:n\xa2\xccPH\x0ew\xaa8\xaf\xd4;\x87\x0fnV,\\NF\x844oD\x83H\x82\x9c\x13n/\xa1\x19OB\xb1\x92\x9c\xd7\xcc\x0fCk\x02,Aw\xfb70e\x88\xaau4\xa7of\xa3Jpx)\x17\x13\x8b\f\xbb2_\xe2\x16z9/\xcc?\xe1\xb6\xf0xE]\xb8-\xf5\xad$\x04\xb4\xcbka\x1a\xeeB\x95\x9fJ:$\x197si>\xc32\xe3\xf2p\xc9\r\xb7\x89\xfbc\xc2\xd5lֆևG\x83\x10\xec)\xf5\xea\x89H\x92P\x1eƟ\x06\x1c\x0f!\xbd\xbdt8w&\xb4t\xa8\xdfĎY\x1b8K\xbb\xac.\xa9\xce\xe1\x05\xc9\x18b#,\xe3\x81L\xf0\x9bȜ\xeb\x88\x1d\xa4\x9d\xba\x8f߇IB\xe1\xb0\"\n\xe3\xb3\xc2B!د\xf3\\VR\x95\xfd!CU\xf1\x13K\xc2b-n\x82gì-\x04\x90\x8a+\x98A(\x14\x13\xabJ\xdem\x18d/\x96\x03\x195 x&*\xaah$I\xa8\xeb\xd8\x1a\xba*$X1\x13\xfb\xa9T\xad\xa3y\xd6W\xb94\x9f)\xc1b≪\xa2y\xd0\xfd\xfc8RfV\xd4\x16\xb9\xeerv˪p\x0f\x8bP \f\x173CQ\xb2\xc5\xc4\x13\x90\x82\"\x0e\xc6\xf0\x88%a\x91\xe1\xeecmh\xa1\x8a`\x15T\r\x97\x94jk\xf8\xa9@\xa1\x98\xb8\xf6\x06\x8e0\x9a˼.\x1e\x8f\x1c\x195\xe8N\xeeM/\xe7IK\xc2b\xab\x1c\x0eO\x87*\r\x83\x82Y\xe1\xf1I\xdbo\x13\xean\xe4N\xd1\xc8't\x0f\xb7\xa2\xa3c/\x1a\x0f\x8c䩨\xb5\xf4\x8f$\t\xd3\xcby\xd5\xdd\x1b\x1c\x90\x10mC\x11gMۯX\x83\x85߬\xf8\x1b|YײPg\xb9\xb7\xa4*\xfbG@E\x9a\x1fDN\v\x89\xea!\xc9\\\xcd*\x95dk\xa8\xd7H`SH\xc1\xe1Q\xf2\xaeM\xd5z\v\x8fO\x8a8kD\xac\x04\xafo\x17\x8c\xe0\xa1Y\xd7sv\xd4\xd66\xb2\xcd\x7f\xd3\x1b\xb9߸!\x06\xee\x83\xd50\xbd\x90\xdb\xcd?Z\xda\x1d\xba\u07b3V\xb0VgK\xacs\xf8 xY\xae\x8d\xe2\xdaF\xba\x03\xb7\xee\xe1\x96P\x1d4\xc1\x8a8\xb3\xf9\xa7\xcc\x15\\h\xa9w\x90\xda\x14$\x87\xd7,\xe5h\xaf\x8fkJ\xa6\x98\xd8\x05\x9d\x8d\x9eC\xa6,H\xd8\xd7\xc4/\xc2\x0eW\f\xcc\xf0\xab\xe3.\xeb\xa4\x19\x81\x8c7\xb3\xd1\xed\xe3\\à\xce\xe1\xd3\b\xe3q_Tg,\x8a\xa8\x1f\x88\xcc\x15\\\xa8\xaa\xb9+\xf4!\x9c\xc1\xed:k\x05k'\xb7\xb9\xc9y\xe0\xceEU,Ƙ\xf9\xfe\xaa\x8b7\xf0\xfaw\x82\xd3\f\xbd{J`\x19S\x90\xac\as4\xd2\x1c\x0f\xcao\x8e,\xccKx\xf2\x05\x90M\xd05l\x8f\x9f\xd6\xf5\x9c)\r\x97˪\xc0\xa95\x95W\xbb\x06\xe3\xf2̬\xafqrT\xcfp\xe4'\xf5\x8a#\xd9n\x9ayQTr\\\xa8\x9b\uf02cbM\xdbox\n\xd88\xfe\x0fH,@\x9a\x8f`\xe4y\x10_\x8069\x10\xbe\xbc08\x88x\x1c\xf4k\x88\xf8\x03h\xb6A\xee\x95\xe9Y\xc1ʓ\xfc\xe7\x14\xcbA\x1c\x8e\x19$\u05cc\xf8(B\xc4\x11\xeeS\x10\xff\x1dZ\xfet\xa8K\xa3~\x13;\xcc6\x9el\xfb\x15\xf7\xa9*6\x9b<\x8dS\xe5\xbc1y\xd0Yn\x89\xf4\x19.\a\xf5\xa8\xed+|AH\xee\x10a+\x8fA\x9b\b\xaf\x8b\xb5\xe9۸{̿\xa7*/Fs\x11P\x17\xf4C\x1b.\xdbU\x053sې\xfc\x1b^Ͽ\x03٩3F\xe2\x9f\xc1\xa8O\x82p\xc0\xb8czN\xe3}\r\xfa\x86\xcdH1ۈ\xb7\xfd\x86/\xa98\x9fC\xd0X\xd4k\xde\x05\xe3\xf2p\xf6O\xfcm\xe3=!u\xe3\xb3$\x9c\xe0m\xb8\x8dx\xe7㼆\n\xa92\xfb \"\x8a8\xe43,\xab\xdfĎQ\xd5:\x19\xbf\x04\x13\xfb4\xe8\x8e\x11\x0e\xf5\x10\x87\\\xd6\"\xf4\x8f\xd0\xd9[\xa7\x84\x882u\x1dF|\x14L\xdf\xf8\x9eS$\x10\uefe0s\xdf\x1d\xf1b\xbc\x9d\xa3\xcc\x1e>\xabj\xb8\xb2(DԾ\xa4\xf5zX\x9d\xde\xc8\xfdQ>\xbfe1\x9fP\xac$\xe7u\xb3\xae(.\xf3\xa0\xb7g,\xcd\xf6Q\xab\xf0U\xe5\xc70\xceZЙq\x1cl\xfc\x9f\xd5\x19\x8cX\x8d\xaa\xfc\xd8\x14H\xc0\xcb\x02\x02\xf6\x8c\xff9M\x0f&\xf6\x05H,\x1f\xe9\a\xeb.g7\x0e\xb5Ŵ\x05\xbd\x16~Z\xf7>\x1e\x88\xfa\xf9-\x9b!\xa1u\xe7p\xef@ۿb\x10\xb1\x17bi\x9e+\xf4D9\x14\xf1E\x18uC\xa0~NT\xa6\xbbh.\x83ʓ\x8a\xb7R\x89\xe5\xfeEaz&\xc1\x80\x0e\x84\xba\n⋆\xd3L2_\xe2\x16\x95⒢IA\xc0\xc4Y\x1fU\x8fhY\x92P\xac$g\x04?\f\xbb\xd6p\xb0\xa3\xc6\xf4\x82h\xe3\xbe!\x89(\xd5\x05\x18o\xb2\x8df=\xc0E\x9aK\x8a\xf3\x12\r\xd5H\x19FZ\x9e\a\xccE\xb2rHU\xf4A6\xa8\x1a\xae,\xd6\xe92y\xf0:\xb9\xb5~\x13;\xcb\xe1\xec\x96ո\xec\xfaM\xec\xd0=\xdcZ\xb4\x98\x95㏑\x16\x19v\x1dX\x7fXy\x92\xef]4!\xdc\xca&\x87\x11\xef-\x8e4\xec8\x0e#\xcf\t\xe99{0\xce\xc5P=0\x00\xa6{3s\xdb\xd6\xf1\x93\x01;\xb0\x18\xa7K\x83\xee\xe3q1\x8fo\x97˹-\xbb\x99\xf5\x15s\xb9\u0378A\x0f\x95\"\xad\x98\x88\x81\x93\xe0'\xfbK\x9f\xcc| =N\xfbj\xc4\x13\x8e\xe2\x94\xf0\x9f]\x9e\x198b\xc2\xd2?\xe2\x90_\\p\xc4\xe4[\xf8\xa6L\xb1\xa6\x98\x1eQ\x93\a\x1c6\xd4]\xcenK\xc2\x12E\xd5:\x9a\xb5\xc7m\xa1\x0e\x15\x1dj\xd5\x14\x8d*\xc9\xd6\xccU\\\x8d\xf4\x8e\x01L\x88\x7f\xc1\x1b\b\xec\x87\nu2\x88\x10m(Ӈ4'\xb7\xaeg\xb1i\xe2G\xc5& .\xa0\xd8\x12uohٓ\x10\xfcdc\xaf\x9bkB\xcf+=x\xe5$\xa8\x047\xfd呹\v\x89'õF\xb5W\t\r\xd5\xe1\x8a\x11y\\\xa87S<\xe9\x9d3?w^,\xcds\xaa\x92\xa5\xc5&\xa0\xd7\xc3\xe3N\x8a\xeb\xca\xed\xbc\x96%\t\x01\xfa^g\v\x82g\x8a\x9e\xd3XԜ\xa3\x96\x90\xddL&\x1e\xa2\xca\f@]\x929\xca+\xf2:\x041A\x1c6\x94c\x89Yْ\xb0\xf1\x1eZ\xbc\x1c\x17bB\x1c\xa96\f\xaa+\x8bv\x04C\x0eڛ&@\x85\xf9\x89\x87%\xa7\xe0\fi\xf0\xb2\\Snjhٓ\x10\xfc\x06F^?\x9f.\xa6Z\xeaHXq\x14\x95Ēa&\xcd)d\x11\x86[\x1ao\xa7\x9f\xa2\x16\x12b\xc9\xf8\tG\x161 \x8f\xef\xc7\xf5\xb2l\xa9{?\xdf(\xd7sZ\xd6$,؇:\xcf5\xc5TK\x8f\xa9ǥ\xbb\xb53ď\x14h]\x84\xda8\xf5[\x10\x95a~\xe2\xd2\x05\xd4\x15\xd3\x0e\xc4\xf0pE\x03וCP~ƒ\x10\xa0\xee\xfd|\xa3X\xd94\xae\x86\xe3\x16\xf0\xce\xf7\xcc\xceJ\xe2\xa90\xa4\xa1\x022\x90\xffC\x11H\xf8\x18\x98\xd7CQI\xe3\xa9\xf8{R{-(\x8e\xf3\x00\x00\n\xceIDAT\xba\x17͡\xd6-\x86\xba\x1fLV\xf2\xf2|\xae\xdc[\x8d\xcc\b\x12\x8a\x95\xe4\xeaV\xf0y\xa3\x8b㨙]\x89\xba\xf0\x14\xea\xc3QIe-R\x7f\xaf8+\xd1Ղ\xe4\xc7AEĤq\xe1)\xd4;E\nȋ8\xb8\xed\xac.\x97\xac\x98\x19O\xc2\x02\x11\x9d*\xce\v;\x90\xefHx\xe1-:\xbe\xf3(\xfb\xe8\xed\xec\x99\xe4S\xc61\xf9\xadx\xbd[\x8b\xb6\x10^Ͽ#\xcc3\x93&\xa2\x9bw\xbf\xf3(\xfb\xf6\xf5\xe09!7\xdbB\xfb\x04,WǦ%!\xf8\x81|/\xcf\xe7D\x92\xd0\xda1\xb8\x1an~\x90מ\xefkH\xe0\xe5'\xee\xfe\xf7U\xd9\x16\x90ߢ\xb8\xa5LY\xb4\xfe*U\xe9\xf8\xa4\xd4g/\xef=\xefͫ\xdd\xfc3\x9e\v\x93\x80&\x0f:\xcfe3\x85\x80\xbe\x03`\x06\xa2\xedv\x8e\x12m\xdc'$K&\x13\\p$\xfc\xf01v\x7fv\xfb\xb1\xfdd\xfe\xfc\xf6\xc4̴\x98\u00899\xef\xa9m\xc9o\xf9\x04\xd9y\xb5\xfc?7ǯ\xe5\\zz\x7fOwXŪf\x1b\xf1\x9e\xe7\xa8˵R/$\v\x9f\x7f\x9b\v\xbe\xfeK\x16\xfd\xa2m^\x82\xdeΞ\t_ \xf1T\xfcG\x1fn\x99\xb3z\t\xf3&e\x1b\x06\xbf\xebu\x8c\xb3\x80ڒ0\xbah]\xcfb\x15\xe7\xee\x89\x12ё\xb0\xaf\ao\xd9mlork+F=\xc4*v\xa03ĉ9Ēq\xf2\xbd\xb9o\x9d\xd5R\xf3W\xa7pL:\x8e2y\x7f6\x86\xd1ߑ\x1a\xfd\x8cT\xd5\xd7|\xfb\xac=\xd5\x17\x9f\xc1Q㖆\x85\n\xf9\xb6\x99I\xc0\x19O\xc2\x02\x11y\x8b[Ɠ|\\\x90\x82'\xde̎nQ\x1b\x1bQZ\xc4S\xf1\xf5\xefi\xa9\xbb\xee\x83\x1c\xb3\xaf\xc7O\x19K'Q\x83\x9d\x19c>\xb8\x13Q\xf7\xe4\xd8\xdeg\xf0\xb3dz\xf7?\xe7\x98.\x1a\x15SU\xa6#\xff\xe6\r\xbco\"N\x18/7s\x9c03\xde13\x14\xea.gw\xef\x1e\xfe\xc1\b\x1e\x1aOW\xe9mϲ\xa7;5o\xd6h\x04\\\xb3\xb0E]s\x0eǀ\x1f\xca\x18,\xf5\n_\xe3ڭ\xf1~\x8dѹ4\xf8Y\n\xcf\xe9H\xb8\xe6\x1c\x8eyW\xa2\xa5oD'\x8e\x97\xf7\xbac\rɟ=˞1{J\xfd\xb6RM3\x9d\x80\x96\x84\x01\x1a\xef\xa1e\xd6\xf5\x9c\xad{\xd80V\x89\xb3\xfe\xa7\xec\x191$\xa1b\xaa*\xdf\xd2{\xd5\a8\xba\xa0\xf6\x8d\x9btӄ\xc1\xcf\xeaH\xf8\xd7\xff\xc6\xf1cQ\xb9\x7f\xf0(\xcdcy?\x93\U000fb939}\x9c;\xd3\thIx\x10f\x9d\xc5\x06\xaf#\x98}\xe8\x0e\xaf\xba\xbd\xf0\x16\x1dݱ\x86\xe4\x88R0YS\xf9\xd9\xf7\xd3x\xfc\xe1E\xca(\x99BB\x1e\xdfH\xfd?\xfcE\xb6\x8a\xaa\xfa\x9a\xe1\x7f0\xef>\xbb\x8f\xdeW\xf6\xd21\xac4\xd4>\x01u\x8e-N\r\x17̄@\xbc%\xe1x\r\xe4`ւ\xd7\xcf\t\xc6\xe5\xe1\xe1\x9a@<\xf6*{G\xfc \x15SU\xd9=\xed\x9f9s\xb8\xa6Pт#\xe1\x93gpdUvO\xfb!^\xdeA*iSl^ݫ\xfb\x86v\x18\xe1\xfa\xa7\xcdh.Ko\xe6R;\xf5ʒpD\xd4ob\xa7S\xc3\x05\xba\x87[\x0f\x9eV\xebjxx7#g\xc681\xe7\xa2%Ԥ\x93(WG\x7f=\\\r'\x1eI\xfd\x89\r88\xb1\xe1\xddW\xf9\xde\xdc#\xaf\x90\x19J\xfa\x19\xcd3^\x0f\xab\xebn\xe4N{\xc2,\tDŽ\xaau4\xd7}\x80k\xb5\xcbj\xd3Ë\x05\xf54Ӌ\xf7f\x86\x91\xfb\xb4䲹\xe5\x8bH;e\xb6\xbak\x97r\xf8\x88\xf9\xb1n\xde}\xe45\xba\x06.\x9eB1\xaebK\xed\x19,\xb5\xf6\x9f%\xe1\xc4\xd4Ӎ\xdco\xe6r\xbe\x97e\v\x1aZ;\xe9~\xbd\x83\xfc!A\xed\xc1\xaa\xa8\xcc\xeaw̦\xa6\xdc\xd6c\xe5\x89̣\"9\xa2\x97\xb4\x10W\f\x9c/\xcfx=\xac\x9e\xf5U.-\xe7R$K\xc2)@\xdd\xe5\xec\xae[\xc1\xe7\xbd^V\xbb\x8a\xce\xce\xfc\xc8\xf1՚\x18\xa6\xbe\x86\xaarZ\x03W\xfbq\xc3Q\x7f0}\xe4a\x00\xa6\x8f\rN\x15\xe7Y\xe97\x06\x9b\xdb.\xc1إ\"p?\xc4_B8߅\xfc\xb0\x17\u0602Zb\xe5b\x0f\x1e\x8cƞ\x97\x9b\x9b\xd4\bizmoI\xb7\x8b\x13\xeao\xb1\x9eO+\t\x8b\xbftCK\x85\xc0q\xe1\xccؕ\x15\x156\xf4`I8\xcdz[\xde\xed\xc8\xe1\x15R\xd4\xca\r\xa3\xa9\xe2\x16\x96\x84S\x85\xfe\x91\xd2j\x06'j\x97\x132\xbdxݳ\x8e\x9d3\xa9\xbaI\vK\xc2\x10\x96\xac\x0f\xa1[GZ\xba\xce<\xe2\xc5\xd7yɑ0\x9e|Ԓ\x84\xf6\xdf\xc1\x91\xf0\xe2\xeb\xbc4\xaa\x8an\xbc\xe7\xed\x19\xb1$,2*\xdb\xd1\xfaM0C;\xb5\xbc\xbc\u05ed+\x93\xe7ߓ\xfcZ_\a\xcb\xdc}|ݸ<30\x84ZG\x87|&\xe77\xc1\xf0\xb2lɵ\xb2\xf6\xb2\x9f\xf3\xefd\xde\xec\x1c\U00057131\x990\xe3\x84\xf5\x8e\x8e\x1b-]\xc8x\x13f\x14w\xbd\xa7O\xa9\xdfď\x81\x1dݛ\xf9N\uf2dc\x1e\x9b\xcf*\x01\x97\x98\x9c_\xb8;p\r\xca\xe9'\xdc\xc0̿\x82\xa2)x\xc6h\xfe5\x9f\xe1W\xe9\x15\xbc*V\x92C\xa6~\x00\xc2\x1d~\xec\x86H\x80\xfb\xb8=#\xe3\x835\xb2'\x84\xc4r\x84\xba\x1d\xcc\b\xbd`d\x1ac>\x01=\xffu\xf0\xffi]ϙB\xb0\x9cN\xde%\x1b8Q8,)T\xd4O\t)\x0f.\x1864y\x1d\xfc\x11\xc9\v\b\x9e\xae;\x87{\x0f\r\xae'\x96#䍣\x1c\xa7J\f\x9f\x1c\xea\x9d-,\tCFu\x03B?0\xf2\xb4[\x11G\x98\xc7\xd0\xd9\xcf\x0f\xf7\x13f\x1b\xf1\xf6\x978\\7\xd3h\xde\xe6\x1d\xce|ދ\xe6t\fK\x0e\xf8$5A\xe3a\x10\xd1\x06\x0fO\x95U\xa0\xfbx\xc8t\xb3]K~\x06\x10\xaf絑\x93\xaa\xe3\x9b\x10\xce\xd9#\xcc6T\b\xf3'4WC\xef\x1e{F,\t\xa7\xc0\x9aN}\x13#\xce\x18y\xe0\xa6T\x18\xf7*\xe8{d\xbc\x1fߺ\x9e\xc5B\xb2P\xc5X\xe8u3\x1f\x87Z\xfa\x83\x96\x151\x1aF\xfc\xe5|\xd0\x1c\xaa\x9f69\x9b^\xdd\xc7.UA\xb7\x9b\xe3\xc9\xdc\x1b\xbc<\xfe\xe6Q\xa9U\b\xb9\x19tf\x84\xa3\x94B\xb8\xff\v\x9d\xbb\xc3\x1e\x0eK©TI\xffy\x94\xd9\xef\x81tp\xbe\b]-a\xfd\xe5B\xe7\xb4\xe1\xfe\x7f\xb8eB\xc9y\bq\x0f~\xd7nϪ\xa2\x96\x84%\x84\x86jd\xf6N\fǍr8\xe3\b\xf3\x1c:\xfb\xa9H\xaa\xddһ~t\x89_\xb8lz\xd7\xdas1~(\xbb\x04\x13E\xb6\x1f\x13\xf3\x10\xf2\xfd`F\x9a\xd2\xeb\x81\\\x84t\xea1\xf9?\x00\xf9\x88\xbc`\n\xe9l\xc0\x88\xf7\x82\xe9\x1d\xe5.Ob\xf2ׂn\xb2\xe7\u0092p\x8a\x91\x7f\x19\xe9\xbc\x17D\xe3\xc8\xd2\xd0\xf4\x02\xc7\"c\xb31\xf9G\xa2A\xc0ԕ\x18\xf9!0\xa3L\x9b\x12)\x8c\xfb\x00\xf4\xff$B\x17\x8c%aY\xc1\xc8\xe7\x11\xf2o\n\xff\x1a\xe9'A\x9c\x84\x8c\x9d\x81q\x9e\x02\xb7\xb34_(\xb1\x00Q\xf1C\x10\xa7\x8fN@\x14\xb0\x0f\xc4\xf5\xe0\xb6\xda\xc3`I8M\xf02\xa8\x8a2q\xa0\x13#?\x1ef\xecӒ\xd0\"d\"\xaak0b\xc9ȹ\xa5C\x92\xd1A\xc8Y\x18\xef%\xa4\xb8\x17\xaf\x7f'8\xcd\xd0\xdb\xca\xc4g\x16\xa6 q\x18\xa8Z\xa4{\x16\xc6\xf9\x10\x88\xc3}\xe2\t\x17\xb47.\x02\n\xf3\x1c\xda\\gS\xd3,\tK\x1c\x89\x05Hq#F.\x1e\x9f\x949\x80\x90\t\xc0E\xe8\x97\xd0\xfaM$M\bٌg\x9a\xc14AE\x1b\xb8ɀ\xa0@\xb2\x1e\x9c^\xe8\xaf\x03ш\x12s1z.\x9aF\x84Z\xecK2\xf1\x83?HB\x1eh\xbf{\xa3\xff\xce\xe0\x9f5\xee\xa4\xff\xbep\xefB\xe7\xb6P\xdc)\u0096\x84\x16E\x80J~\x1c\xad\xbe\xe8\x17\x01\x9b\x88\xf5\xde\f\xe6\xda\x1bs\x03dm\xebBK\xc2(#9\x0f\xc9\xc6\xc0a3\x19\xa94eW\a\b\a\xe3\xfe\x1a\xf8~\xf1\x1dE\x96\x84\x16S\xa7\xa1\xaeB\xf0\x19\x90G\x83\xee(=2J\x05&\x81\xd0;\xd1\xe2GV\xfaY\x12\x96)\xaa\x1bPz\x15Z|\x1aL\x02L\xdf\xf4\x93Q\xc4\xf1[\x9dd\x90\xfa{x\x95۠\xa5\xcb\xee\x95%aًET\xe5\xc70\xe6\xdd~\xa9\x10j\x92\x0e\x9c\x89\xa8\x9cq\x109\x84~\x02\xcd/\xac\xe4\xb3$\x9c\xa1h\xa8\x86\x8e\xe3\xfc\xe0\xb9<\x1f!\x1a0\xba;\x90\x90\x84D\xca\xc0[*\x1c\xc0A\xc8*\x8c~\x03\xe1\xfe'\xday\b\x92\xbb\xac\xe4\xb3$\xb4\x18@\xe5I(N\xc1\x98\xe5`b\x18y8P\x13\xa8\x8b\x86\xfd!\x87\x91\xb6\xb5\x10\xd2\x10\xc1\xef\xb4!\xf4[ \xda\xc0ۉvv\xd8\nxKB\x8b1!9\x0fܹ\xa0R(\xb5\x10c\xe6\x03\x87\x01`X8\xa8\x05T\x00\xe3!\xd8\x15\b\xd0W\xfd\xe0\xbe\xe8\x81\xfc\xde \xf3\xc6f\xb9X\x12Z\x84bK\xfaj\xec0\xc9\xf7-\x05\xf5\xd5\x06\xd5-,,,,,,\"\x80\xff\x0f`\x80\xd88\xb1O-\xb6\x00\x00\x00\x00IEND\xaeB`\x82"), + "IonosAPI": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x000\x00\x00\x000\b\x06\x00\x00\x00W\x02\xf9\x87\x00\x00\x00\x01sRGB\x01\xd9\xc9,\x7f\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\v\xfca\x05\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x02\xd1IDATh\xde\xed\x99kHSa\x18\xc7\xffgsN\xddL\xcd4\r\x11\x17j\x99Eh\x17,i\f\xd3\x1cf\x90\xe0\a\xd143\x15+\t\x03%\x8a\x82>uQꃉ\xa6(]\xd0\xcaA\x84հ\xb2e**)E\x16\xa2\u074c\xcc4\xf3\x92n\xeat\xdaN\x1f\xa2 \xce\xeb\x97Q\xf9\b\xe7\xf9\xf8\xfc\xe0\xe5\xfc\xf8\x9f\xf3\xde\x0e\xa7X\xb3\x9f\xc7\".\t\x16y\x89\x02\xa2\x80(`cy{\xba\xa2\xba(\x1b}\xad\x85h\xa8>\x01\xf5\xe6\xd5\v\"\xc0\xd92\x8dJ$\x1c\x9at'\xb1>\xc8\xf7w\xcf2;\a\xed\xde|\xb4u\xf4\xd0O P\xe5\xfd\xc7\xc3\x03\x80\xbd\xcc\x0e\x05\xc7\x13\x17\xc7+\xc4q\xec\xfe\x86\xb5~\x88\f\x0f\xa6/\xd0\xfd~\x00\xfd\x83ߘ\xechV,}\x01\x9e\xe7QRe`\xb2-\xa1\x01ضi\x15\xfdY\xa8\xecz=\x86GM\v\x9e\x82\xcd\x02\x93\xe6\x19\x14W>b2MX\x10\xc2B\xfc\xe9/d%U\x8f1f\x9cb\xb2\xbc̝\xf4\x05L\x13\xe6yS\x88V\xafCh\xb0\x1f\xfd\xadDѵ:\x8c\x9b\xd8)\xe4f\xc6\xd0\x170\x9a\xcc(\xbbQ\xcfd\xbb\xb6\x87 8Ї\xfef\xee\xe2\xd5:LLN3\x16<\x0ey\x191\xf4\x05F\xc7&P^\xfd\x84\xc9\xe2\xa27\"@\xe5E\x7f;]x\xe5!\xa6\xa6-\x82\xbeT*A\xee?L\xe1\xaf\t|\x1d1Ⲯ\x81\xc9\x12bð\xd2ד\xfe\x81\xe6B\xc5}\x98\xe7I!'MK_`px\x1c\x95\xb7\x9b\x99,9.\x1c\xbe+\xdc\xe9\x1f)ϗ\xd7\xc22;'\xe8\xcb\xec\xa48\x9c\xba\x83\xbe@ߗQTմ0Yj\xbc\x1aޞ\xae\xf4\x0f\xf5\x05\xa5zf\n\x0er\x19\xb2S\xa2\xe8\v\xf4\xf6\x8f@\xa7\x7f\xcad\xe9\t\x1a,[\xeaL\xffZ\xe5ܥ{\x98\xfbn\x15\xf4\x15\x8er\x1c\xdc\x13I_\xe0ç!ܪmc\xb2\x03I\x11p]\xe2D[\x00\x00\xf2K\xf5\xb0Z\x85\xb76\xceJGd%F\xd0\x17x\xdd3\x80\x9a\xbagLv(%\nJ\x85\x03m\x01\x008]|\x87\x99\x82\x9b\x8b\x02\x19\t\x1a\xfa\x02]\xef\xfa\xa1\xaf\x7f\xc1d9\xfb\xb4P8\xc9i\v\x00\xc0ْ\xbb\xe0ya\n\xeenJ\xa4ƫ\xe9\vtt\xf5\xe2A\xe3+&;\x92\xa6\x85\xa3\x83=m\x81_\xeb\x02\xab\xbc<\\\x90\xb4{+}\x81\xf6\x97=0\xb4t2Yvr\x14}\x81\x9f\xdf\x02;\x05\x7f\xbf\xe5P\xf9x\xd0\x17h}\xfe\x16\x8dm\xddLf\xe5y\xfa\x02\x00\x90w\xe6&\xa6gf\x05b\x1f?\x0f\xdb4\x9e\xd4\xde#\xf4\xd4\xff\x14\x18\x1a1\xa2\xa9\xfd\r\x02U^\x90ɤ04w\"\xfdX\x05\xa6\xcc\x16\x9b\xc6\xe3\xc4?\xf5\xa2\x80( \n,h\xfd\x00\x1a\x88ްv\x97S\xdb\x00\x00\x00\x00IEND\xaeB`\x82"), "JokerAPI": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\xe1\x00\x00\x00\xe1\b\x06\x00\x00\x00>\xb3\xd2z\x00\x00\x00\x06bKGD\x00\x00\x00\x00\x00\x00\xf9C\xbb\x7f\x00\x00\x00\tpHYs\x00\x00.#\x00\x00.#\x01x\xa5?v\x00\x00\x00\atIME\a\xe9\f\x16\t\x15-0\xa6\x84F\x00\x00\x00\x19tEXtComment\x00Created with GIMPW\x81\x0e\x17\x00\x00\x19|IDATx\xda\xed\x9d}t\\\xe5}\xe7?\xf7ޙ;/\x92,ɶ\xa0\xd0S\bKaK\x92\xda16\xac\xd9\xc2b\xf3\x12\xe37\b\x18\bI\x0f\xebR\xd8s\xa0\xa5\xe1$\x9b\xfea\xdcf\xbb\xe5%=m\xd2\x16B\x9a\xdd\x1c7\x89\x9b\xdd\xe2\x18\xdb`\x90mD\x00\xd9I\x93\x05\x1b\xea؛]8\xa4\xc9\xc6nj\x1a\vے,\x8d43\xf7\xdeg\xff\x98\xd1hF\x9a\x91f\xe4\xd1hF\xfa~\xce\xd1\x1f\x92\xeeܹ\xf7\xb9\xbf\xef\xf3{y^.\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10ecͅ\x9b4]4\xd1\xcfU8\\I\x88\x8b\x01\xf08F\xc0Oh\xe1uk\x15\x832\x05!\x11N\x87\xf8\xb6\xd3A\x84/\xd0\xc4\xc38%\x0e\xf2\x81a\xb6\x91\xe0Q\xebn\xfe\x9fLBH\x84\xd5\x12\xe0N\ue9d5-8\x80Ej\xe2\x83q\xf1\x81\xb3\x8b\x14\x0e\x17\xc9D\xc4t\x13\x9aEw\xf2+P\x85|0\x1f_\x06\"\xe4\t\xcb'\xc9;\x18ܪ\x9eӑ\x81\b\x89\xb0|\x86\xf9~U\xcfgpIqD&\"$\xc2r\xf18P\xf5\x9c\xd0e\xb1y\x95cf\a\xcbd*b\xba\x9853fL\x17M8\f\x9c\xf3l\x99b\x1eqt\xa5\xc5g\xac\xbb\xe9\x91\xd9\b\x89\xb0\x94^^\xe0qZ\xd9\\\x95\x01\xfbRb<ˣ\xb4\xf1\x17\xd6J\xbc\x86\xeb\xa4\xcer!К\xf7\xe7>\x02zձH\x84\xd53\xb4nB@zZD\x98/F\x80\xd3\xdcem`G]\xb7Gf\x16\xd1F\xda\xf8C\xbc\xecu\xe7\x17\x9b\n\xab\xbf\xc7\x19\xe4E<~\x84\xe1{֝\xfcD\xf2\x90\b\xa7nx\u0558\xc4]\x9egg8\xd2\xf0\x1bS\xe5\xe7ʭ\x9c0/\xf0\xb8\xe9\xa2i\xf6\xa7\xcabr\xfb\xde\xcdW\x98\xc7\xc33R\xfe\x1f\t\x87Oq\xabu'/\x95[f]^8\xb1\x18\xebr\xaf\x1f\x89p:\x9f\xfbt\xac?\xac\x96gH\xb1\x8f\x18\xab\xe7\x8c\b\xf3\xef}\x98m\x84y \x7f\xcb\r\xd3E\x13\x03\xac\xc6e\r-\xfcv.zHq\x84$\aH\xf2\xfcLO(\x97\b\xa7\xfa\xdcw\xb0\x9e6^\xac\xbb!\x81\xe9\xd8_\xa6\x01CT法^\xfe\x90\x16\x9e\xccm\xf3\x98\xdf.\xf9[t8\xcch\xe5U\"\x9c-\xf9\xa1\x18/\xc6Jv\xdb\xf3p\x19f\x9b\xb5\x8eOI\x84\xca\x0f\xc5L\x8a7\xc9A\xeb\x16\xfe]-\xbfVC\x14\xe7\xcaL\x8f\x1f\x8aj\xba\xa4\x14\x11\xae6/\xf1\r\x89\xb0\x91\x9e[=\x8c\x1f\x8a\xea\n1\xc6}\xb5\\\xe7(\x11V\xe3\xb9\xd5j\xfd\xa1\xa8\r\x0e\xd0\xceV\xe5\x84\xca\x0fgo\xde5]\x1e\xac\x9ax\xb8\xf4ry-^\x8c\x13\x92UT9?̌\x1f\x8aR\x02\xec\xe5\xd12\x8e\x9bl\xd6Or\xcc\xf1ô\xf2\x05B\xfcJU\xbd\xa1\xcd\xc7A\"l\xb8\xfc\xd0\xec\xe0ֺ\x1c?\xac\x1f!&\xad;\xf8\xcbi\x88B\xb6@\x95\xdb<\xccR儍\x9a\x1f&xZ\xf9a\x89\x90q\x1e_\xae\xf6\x0es\xd36\x91;\xc4%\x12a\xa3\xdaڭ\xc7<\xbe\\і\v\xb3\xbeQp9\xc5UӹKZn\xa3\xa7\b\x1bh掼\xbde\x8e\x93\xe0\x05m\xf44\x17\xecl'\x17\xd0\xcc>\\\x16K|EDx\xba\xf1\xf7\rU8Z\xdf\x02\xbc\x9fVNH\x80\x13\x10\xe2cs>/\x96\x15LK\xee\xd7\xc1<:U\x80)\xc3\x13\xd6pP\\\"\x9c;\xde\xefNZyN\xb9_\x99x\xb88\x84\xad\x95xs7\x18\x10\xd5+\x00\xf8<\x87\xcbj-譐\x1e~\r\x1a\xf8M\xc3\xca\t\xeb@\x80;X\x8f\xc3\x001\t\xb0b2\xdbH|tn\xa7\xc5\xe2ܼ_\x9a-D\xb9G\xe2;'Wp\x91D(*\x17\xe0s\xac\xc0\xa5\x1bW\xb9\xdf9S\xa3\xbd\\$\xc2\xd9\"\xbenB\f\xf0ub\xdc'\xf1U\x89\x187J\x84\xa2|\xef\a\xdd4\xcb\xfbU\x8dL;\xce\xe9pT\x85\x99r\x05\xf8\"O\xd1Nw\xee\xfd\xe9s\xba1\x8a\xcc\xc5<\xd7S\xee\xe4\x02yBQ\xdc8v\xb0\x8c\x05\x1c\xca\xeb\xb5\xe7\x9e\xe0\x80ܢ\xe4\x10)R\x1c\x01\xc0eq\xee\x15d\xe7\xd2>\x0e\x10\xf0o\x81\xf7%BQh\x7f/\xf08\xcdl\x9e\xb3\xe2\xf3\xc9l\xa04\xc8\xd71|\xafؖ\xf0f;\x1dX|\x84(\xff\x91\x18\xf7My\x92\x82ͥ0\xb3\x13\xa9g.\"\x17ż\xdfe,\xe4\xc7s\xf2\xad\xb7#\xe2K\xf04\xc3\xfc\xb5uw\xf9\x83見&\x86\xd8D3\x9b+\x12\xa3\xc1\xa5\x8f'\xacO\xf0G\x12\xa1\xc0<Ϧ\xdc+\x96\xe7\x9a\x00=\\R\xecc\x88\xfb\xad\rS\x0f\r+^9bp\x19f\xbf\xb5\x9a\x95\x12\xe1\\\x16\xdfv.a>\xfb\xe7\xe4\xaeh#y\xdf\a\xac\xac\xe6ں\\8\x1f*O\x88\xd5\xdc}\xad\x91Pu\x140\xbb\xf8}\xe6\xf3\xb39+\xc0a\xf6\x93\xa2\xb9ڋ[\xadO\xf0G\xf4qWY\x1b\\\xf9\xd3\xf8N\ty\xc2\x1a\xe5p6\x1f'\xccR\x9c\xec\xeb\xb1|\xfe\x95\x14?(UP\x98R\xd84\x1b\xc3ϳR\xf1\x1b\xe0\tR\x1d2\xbb9\x8f\xfc\x8c\x1c\xeb\x8d9n&\x84j\xb2\xe3\x80uZ\xf6/\xfa\x92\x1cg\xee\xedC\xda09\xa1\xd9O\xb2\xe6\xa2\xcb\b,\xb3|\xa7\x9f\xffF\x9a\xefc\xf89\x16\xff\xc2|z&ۦ\xcft\xd1D\x1f\xe7a\xb3\x00\x8b\x0fas\x19\x11\xae#\xc6\xea\x82%@\x99'\x91\xaa\xfa\xf57H\xb51\x97\x1f\x02\xa48b\xad\x9a[Bl\x1c\x11\xbe\x8a\xa9I>82\x8c\x01\xc7\xe9\xe3O\x81\xbd\xe72\x99\xb9\xe4\u05cc,\x01r\xb8\x92\x18\xeb\t\xb3\xa2j\xa2l\xb0Mu\xcdN.\xa0\x95\x13\x84H\xcd\xc5}H%±\xe2\x1b\xe2\x9b$\xf9b\xad\xcb\xf8\xa6\x9b\x10\xa7\xf8\x18\x0e7\xd3\u0083\xe4\xcf\x02\xaaT\x90\x1e.\xa79Ϻ\x9b\x9e\x86\xca\xf9\xdbx\x11\a\xa6\xfb%1\x12\xe1ԍ\xd4L\xcb\xd8\xe0\x98\xd94\xf5b\xb8\xd9\xed\x1e~\x8b\x18\xbf\x8b\xcb\xea\xb2\x059R\t\xbd\xab\xf1\x16\xc8\xe6V]\xf4\xf3\xb0u\a_\x95\b\xeb\xed\x01M\xc7 }\xe6\xd5\xc8\xe7\xbc~n\xda\xef}\xe4\xf5^\x93\tr\x16,\x8e5{ً\xcbG\xe6\xd2\xfb)\x1aG\x84;\xb9\x9f\xf9l\xa9\x9a\b\r.g\xf8\xcf\xd6\x1d\xfceC\x19\xe9v:p\xb8\x95V\xbe\x90\vYG\xde\xd3>K\x8a\x1a\xe6U\x8e\xd1\xc7\xf2z\xee\x18\xe7\xa6\b\xb7\xd3\xc1|NV-/\xf4p\xad\x9b\x1a|\x15\xc9\x0e.#\xc4F\x9a\xd9\f\xd0hy\xe0\x84\xf7\xf6\x1c+\x1a1\xa4\x9e\xd5\"\x84춃-|朽a\xc6\vΚ\xbc#[Թd\xa6焊\xb9 \xc2nB@\xba\xac\x02\xc5D\x02\xd4;\xf1D\x1d\xd1PsG\xad\x95x\x9c\xe2\xf2\xa2s\x0e\xcb\x15`&l[\xa6G/$©\n\xf1N~B/\x97W<\x05ld\xfb\xc2\xd3\\8[\xf2&!\x11ά\x10S43\xc07\v\xe6f\x16\x13\xde\xc8<γ<\x8d\xa1i\xaeT܄r\xc2\xda\xe5\x89۹\x840\xf7\xe4f\x99\xe4\xe3s\x84A\xfe\x0e\x8fo\xcb\xfb\t\x89\xb0\x16\x82\xec&D\x0f\xed\x00tpf.\xbf\a]\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10\xa2\b\x8d3wt\xc9K7\x12qW\x10\x98\xa1q\xff\xb3\xad\x18\x9e\xf7=\xdeZ\xfb\xddI?\x1fu\x97\x13\xb2\xdb\x00\bL\x9ad\xfa\b\xa9\xf4~\x92N'GW\x95~\x11\xc9\xf2\xae\xc7r\xdfm[1\x92\xde\x16\x0e\xaf=6\uee2b_~t\xdc\xdf\x0e\xde\xf2$\x00Wv^\x81\x1b\xfet\xd1{(\x86\xef\x1d\xe1\xedu{r\xbf/ݷ\x11\xc7\xfa\xd5\t\x1e\xe7\x10~p\x9a\xc0\xfb\x05\x87\u05ffV\xf5\xb6\xcfo;/\xe8c8\xfd#|\xef\x10\xc9\xe1n\x8e\xdeq\xb2\xf4\xe7\xf7\\L\xd8YOĽ\x96\x88si\xee\xefI\xff\xa7$\xd3o\xe2\xa5_\xe6\x1f\u05fdS\xf2\xf3K;\xd7\xe2\x84\x16\x17<\xef\xe4\xf0n\x0e\xdf\xf6V\xc9\uf2c4\x1e\x18\xd3\xce\xfd\x1c\xbc\xe5\x99z4\xedPÈ0\xe4,$\x1e\xb9\x91\xc0$\x8a\x880N_\xf0OE?\xb7h\xd7y\xb4\xb7\x7f\v\xc7j#0\t\f)\xd2\xc1芊p\xe8\xd7\t\x87\x7f\x836{\x13K;7\x17\x18}>\xcd\xd1[\xf0\x82\xbe\xccg\x9c\x85\xa4\xfa\xff\xbe\xa8\x00\x9bck\t\x82\xccÏ\x87\xfe\r\xef\xf7\xaf\xcc\xfd\xdf\xf8M4\xb7\x8c\x9eg\"l;\xc6\xc0\xf0\x100z=a\xe77\x89\xbaK\xc1L\xb0\xac\xd9r\xb0-\x97\x1b\x0e\xfc)gz\x1f)i\xa8\xe5pe\xe7\x15\xcckz\x1aێ\x13\x04\t\f邶\x8b\x86\x17\x83\xbb\x94\xb6\xe6M\\ݵ\x95\x83\xab\xfe\xaah\x9b\xb4\xc6\xef&\xed\x7f\x00\x98\x82\xcf\xdb\xd6<\xe2\xeeZB\xd1O\xb3\xfc\x95\x03\xbc\xf1\xf1\xcf\x17\xbd\x0e'tIA\xbbb9\x84×\x01\xf7\x14=>\xec\xfc6\xf1\xe8\r\x05ǧ\xd3\xef֫i7\xd6zB\xdb\n\x83\xe5d~0\x18R\x18R\x04%\xb6\xc8_\xb2\xe7b\xce_\xf8\n\x16a|Ӌ!\x85\x85\x8bc\xb5\xe1XmXV\fC\x1ac\x86H\xf9'ho\xf9\x13\x96\xee\xdbX\xf4\\A\xf6\xbb\f)\xfc Q\xd4[̋ݎ\x1f\xf4aH\x11\xb2[y\xbf\xf7?\x8d\xf3\x96\xf9\xe71\x95n\xd1a\x86\xc0xy\x9f5\xa3\xed1\xd2&f\b?\xe8\xc3\x0f\xfaXؾ\x85+;\xa7\xf6\x96\xa3%\xbb\x97\xb1`\u07b3\x18\xd2\xd9{Jc\x11Ʋb8v+\x8eݚ\xb9$3D\xda\xef!l_>\xee\x1c\xbf\xf5ݯ\x11\x8f\xdeL\xca?\x91\xbbW\xc7nʹ\xbf݊E8\xd7)F\xc3\x1f\xe3\xba\u05f7\x95\xbc\x9e \x18\x1am73DĹ\xb4\xe8\xbd-\xeaj*x\x0e\x86\x14\x98\xba^M\xd38\x9e\xd0\x0f\x8e\xd27\xf8%\x82` \xd3\vG\xd6\x11\x0e\xfd:&\xbb\xe7L1Z\xe3[H\xfb=\xb9c\xc2v\a\xfdC[\xf1\xbc\xd70V\x02\x87\xcbi\x8a\x7f6k\f\x99^~~\xd3gY\xb2\xfb\xffT\xe4A\x16\xed:\x8f\x05\xf3\xfe,\xd7\xcb;v+\xfdC[\xcb\n\t\x13\xc9\x17\xc0\n\x17\xbf\xe7\xf4{\x13$\x12a\x86So\x90N\xbf\x91\xf5\x9c\u0378\xe1\x15\x84ÿ\x81Ɇai\xbf\x87X\xe43\xc0C\x15\xb5\xf5\xa2\xae&\x16D\xbfF\xca?1ꍬ6\x12\xa9\x1f\x92L\xeeòN`̅D\xdc\x15\x05\x11B\xa1\a|\x98\x88\xbb\b?\xfb?ˊ\x91N\xbfK\"\xf1\xb7\x10\xea\x01\xaf\x83H\xec\x1e\xe2\x91kr\x82q\xac\x85,\xefz\x8c7V\xfd\xf1\xa4\xd7\xe8\x05\xbd\xb8\xe1O\x03\x85dž\x83;\xf1\xcc@#\xf9\x96\xc6\x11a&gx'\xef!/&\x1c\xba\xac\xe4\xf1W\xed\xfd$\xb6\x1d\xcf\x19A\xd8\xee\xe0T\xefCc\xc4u\f\xf8.\xd7w\xef\xcd\xfd%\xed\xf7\xd0\xdc\xf2\xf9\x92\xa1N1\xdaۿ\x85\x17\xf4f\xc5\xe1\x92L\x1d-+\xff\b\xcc9\xe4)V\b\xdf\xff\xf1\x98\xf0\xf9;,\xefz\x8c\xa8{M\xd6\v\xa4\x89\xb8\x8b*>u\xd46\x91\xdc5YV\x8c\xb4\xff\xcf\x05\x1e\xaa,\xf2<)P0\xa4P.\xf9QH\xe6ZOO\x92\x1c\xf7\x8d\xb9\xb74\x8b\xba\x9a\x8av@\xb6\xe5B\xd0Gbh+M\xf1\a\xf1\x83>\xa2\xd1{I\xa5\xdf\xc5\v\xfa\xb0\xac\x18\x89\xc1\x86\xdaY}\xf6\xe6\x84\xc5BԉC\xc3XeB\x1f3\xbc\xe0\xd8\xe7\x97\x1cޘ\xd0\xe6GJ\xf6c~\\{AY\xe1lȾ\x00ۚ\x97\x19\x9a0\xbd\x05\x85\x90\xef\xdfpO\xe5\x16a\x86\x1b\xc0l[I:\x9d\x84\xed\xf6l\x1b.$\x1e\xb9!34d5\xf3\xf6\xba=\xd8VT9\xe1Lb9\x83\xe3\v\x12\x83M\xc0\xe0\x04bX\b\x98\\\xe6\x11pz\x92\xe2\x80[ Dc\x86\x98\xdf\xf4Y\xae\xec<8\xe1\xec\x8f\x02\a`\xfa9p\xfd\x9a\xa9\xdf'.\xb6\x15' YP\x114\xa4\xca*\xf3\x97\x13\xe2\x86펊\xcf1\xd6{Z\xd6\xfcIE\x95\x1f\x02[Vx\xc20\x1c\xe0\xe8\xaaA\x96\xbf\xf2j.\x85\x18\x19\x03\x1e\x18~\xb9\xd1\xccuvzB/|\x1cǎ\xe7\xe5p)\x1c\xe7\xa2I\xf2\x98\xbc$\xder0ycdŌ?\x91|\x81\x03+\xd7\x14\x18i\xca?\xc1\xbc濙\xd4\xebV\xa5\xa3\xc9^\xc3\a\xa7?A\xdf\xd9\xc7\v\xae\xc3\xc2ey\xd7cS\x13\xa1\xff\xcbLȗ\xeb(\xd2,\xd9S\xd9{;\x92\xe9\xff;Z\x9d4^\xa6P3Q\xf8\x1a\xbe\xa2\xa0B:\xec\x957\xbb%9\xb4\r\xdb\x1am\xeb\x90\xddJ*\xfd\xf7\x12aͮܞ\x9f\xe7\xb9\xc6\xf7\x92\xc3\u07bb9C\b\x82\x04\xf1\xf8\xfd%ϵ\xe4\xa5\x1b\xc1\x1a=W\xc8j\xc63oL\x10\x06\xc6\xf1\xbcL\xe5\xf2T\xefC\x85\xde\xc2\xf8\xb4\xd8_\xaa\x85\xbb\xc7\x04=\x1c\xbd\xe3$\x87\u05ffF\xff\xd0V\xaclH\x9d\xa9\x1a\xde²=7W|\xda÷\xbd\x85M\xbe\b\a\x89\x84\xff`\xd2\xcf\xe5\x87\xe2\xe9T7X\xa1쵤i\x8e\\?a\xc7\xd4\x1c\xfbT\xc1\x90H2\xf5\x0fe_k`\x06s3x\x92\xfeOˎB$\xc2*\xe4w͑\xeb\v\xcb\xcf\xfe\a\x05\xc7$\x12\xdf\xc6\xcezCC\x9aHx1K;\xd7\x16=Wk\xf3\xa6\x821\xc5a\uf772+\x82\x87o{\x8b\xfe\xa1\xe7\v\x04\x10q\x17q\xd5\xdeOִM\x0e\xde\xf2\f~\xf0\xcb\xd11\xb4\xa0\x87\xf6\x96\xbf`Ѯ\xf3\xc6\x1d{ӁCܰ\xff\x87ܰ\xff\x87\xac\xf9\xfe\xcf\xc6y\xba\xfe\xa1籲B4\xa4\x89G\xae)\x99\xef^\xd9y\x05\xd7w\xef%\x1aZ>*\xc2\xf0~BV\xf3hd\x12\xf4\x96옖w=6:Ǔ̼\xdc\xe1\xc4\xf6\xb2ﻯ\x7f\x13g\a\x9f\xe6\xec\xe0\xd3\f&\xfek#\x9as\xfd\xe7\x84\xcb_\xf9\x12\x98!\xd2\xe97\b\xcc0!g!M\xee\x03\x85\x93\xb0\xedv\x02\xeb\xc7\x05\x9f{{\xdd\x1e\xae{\xfd^\x1ckAf\xfe\xa3饵y3˻\x96\xe7\xc6\fC\xe1Ki\x8a\x9f/\xc0t\xfaݢ+1f9\r\x14\x8e\x1a\x8f H\x80\xf12\xb3\xf9q\t\xdb\x1d\f\xa7\xde.\xb9\x04\xe6\xe8\xaaAN'ב\xf6~B\xd8\xeeȆX&\xb7\xca s.73\xa3ߊ\xf1\xc1\x99\aJN\xcfr\xac&,+\x96]E\x10\x1f\xdf#\xaf=F\xef\xc0\x173ߓ=ζ\x9a\xc6y\xba\xfc\xf3XV,\x93;\x15\xfb)6\xdd̊a\xdbq,+V\x10\ue34d\x00\x12\xa9\x1f\xe6\xee\tˡ%\xb6\xbe \x14\xb7\xed\u0604\xf72\xe2a>8{\x1b\x86tf\xc5\xc9Hx\x9a]\xa5\x91\x99\x11c\xe1ح\xd8VS\xc1\xb4\xb5\x11\xdeX\xf5\xc7\xf4\r\xfdw\\\xe7\xc2\xcc\xf7\x11\xce}>_|\xaes!\x89䋥\xa7\xfbYal+s\xdf6.\x8e]\x9e݆\xac\xe6\xccg\xec8\x96\xddT\xaf\x96]\xff\x9e\xd0\xf3\xbe\xc70\x99!\x84\x91\x86\xf4\xfc\x93\x04\xc1\xcf\xf1\xbc\xd7&M\xc43\xa5\ue1f8\xb2\xf3\nB\xa1\x1b\t;\x1f!\x14\xba8\xbb\xbc\xe9\x14\xc9\xd4Q\xd2\xe97'\x9d\"vz\xb0\xb0\x87\xf6R\xa7\x8a\xf6\xfeK\xf7ELj\xae\x85%{.\xcex\xeaPϸ\xf3LX\xa9\xf4~Q\xf0{:\xd5M\x9f\xff\xbfG\xff\x9f\xfei\xd1\xcf%\xcc\x7f!\x18\xba\x0fߜ\x1d\xbd\x8e\xd0%\xa3\x11B\xe2\xeb\x05\xd7\xe7'\x8bOx\xceD\x17kX\xb2{\x19\xe1\xe8u\xb8\xa1%١\x1c\xf0\x82\xf7Iy\x87I\xa7\x8eN\xd8vo\xaf\xdeʢ\xae\x1dD\xfcu8\xa1\xab\x88\x84?<\xbaj\xc5\xfb\xa7̂\xeaI\x16\x05\xa7SG\xe9\vF\x87\x8c\x8c\xf9\xc5\xe4}6?\xe3Lbt\xea[C\x8c\x7f\n!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\x10B\b!\x84\xa87\xfe?J\x98~QP\xe1$B\x00\x00\x00\x00IEND\xaeB`\x82"), "LinodeAPI": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00p\x00\x00\x00\x85\b\x06\x00\x00\x00\x83\xbf|\xe1\x00\x00\x01\x84iCCPICC profile\x00\x00(\x91}\x91=H\xc3@\x1c\xc5_[\xa5U*\x1d\xec ␡:\xd9EEt\xabU(B\x85P+\xb4\xea`r\xe9\x174iHR\\\x1c\x05ׂ\x83\x1f\x8bU\a\x17g]\x1d\\\x05A\xf0\x03\xc4\xd5\xc5I\xd1EJ\xfc_Rh\x11\xe3\xc1q?\xde\xdd{ܽ\x03\xfc\xcd*S͞\x04\xa0j\x96\x91I%\x85\\~U\b\xbe\xa2\x0f\x11\x840\x8b\x80\xc4L}N\x14\xd3\xf0\x1c_\xf7\xf0\xf1\xf5.γ\xbc\xcf\xfd9\x06\x94\x82\xc9\x00\x9f@\x9c`\xbaa\x11o\x10OoZ:\xe7}\xe2(+K\n\xf19\xf1\xb8A\x17$~\xe4\xba\xec\xf2\x1b\xe7\x92\xc3~\x9e\x195\xb2\x99y\xe2(\xb1P\xeab\xb9\x8bY\xd9P\x89\xa7\x88c\x8a\xaaQ\xbe?\xe7\xb2\xc2y\x8b\xb3Z\xad\xb3\xf6=\xf9\v\xc3\x05me\x99\xeb4G\x90\xc2\"\x96 B\x80\x8c:*\xa8\xc2B\x9cV\x8d\x14\x13\x19\xdaOz\xf8\x87\x1d\xbfH.\x99\\\x150r,\xa0\x06\x15\x92\xe3\a\xff\x83\xdfݚ\xc5\xc9\t7)\x9c\x04z_l\xfbc\x14\b\xee\x02\xad\x86m\x7f\x1f\xdbv\xeb\x04\b<\x03WZ\xc7_k\x023\x9f\xa47:Z\xec\b\x88l\x03\x17\xd7\x1dM\xde\x03.w\x80\xa1']2$G\n\xd0\xf4\x17\x8b\xc0\xfb\x19}S\x1e\x18\xbc\x05\xfa\xd7\xdc\xde\xda\xfb8}\x00\xb2\xd4U\xfa\x0688\x04\xc6J\x94\xbd\xee\xf1\xeePwo\xff\x9ei\xf7\xf7\x03\x81Dr\xac\xb7\x16\xd3\xcd\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\tpHYs\x00\x00\v\x13\x00\x00\v\x13\x01\x00\x9a\x9c\x18\x00\x00\x00\atIME\a\xe7\t\x0f\t\x14+\x1f%\xe6'\x00\x00\x00\x19tEXtComment\x00Created with GIMPW\x81\x0e\x17\x00\x00\x19\xacIDATx\xda\xed\x9dyp\x1c՝ǿ\xef\xf5=3\xdd=3:-۲\xc1\xc6\xd8\xd8\xd8`Y\x06\x81\xb1\x1d\xec\x18\x13\b$$[\xb9 \x84\\d\x97\x04*\xd9\x1cl*\xbbKv\x97\xad\x04\xa8-\x8e@ \xc9&K\xd8\x14\x04\x02l\x0eB\xc0\x81\x18\x83\x0f\x8c\xef\x13\x83\x0fI\x96\xacs\xa4\xb9\xa7\xef\xde?dl\x84gF3\xa3\xd6H\x96\xf4\xab\x9a*\x0eM\xbf\xe9\xf7\xe9\xdf{\xbf\xeb\xfd\x1a\x18%\t\x06\x02+\xe4@\xe0\xff$QlQ\x02\x81\x7fƤ\x8c}\t\xca\xf2\xf5J \xb0\x8e\xe7\xf9\x04\x00\xf7\xfd\x1f\x8e\xe32r@~\f\x00?9ScGx%\xa0\xfc\x83\xdf\xe7\xdb\xc52\x8c\xf5Ah\xd9>,\xcb\x1a\xb2_~b& NN\xdf(\x88,˕\xc1\x80\xf2\xef\x92(\x1e\xa1\x94:\x85@\xcb\n\x92à/\xf0\x9c\xa2(\xe1\xc9Y\x1da\xa9\xa8\xa8\x98+\a\xe4\xc7DQ\xec$\x84\xb8\xa5B\xcb\xf6a(\xb5\x03~\xff\xfa\x8a\x8a\x8a\xa9\x933\xed\xb1\x11\x12\xf0\x05\x9e\xe3y>\xe6%\xb0\xa1@\xaa\xaaz\xce\xe4\xec\x97&lHQn\f\xf8\xfd\xeb9\x96\xd5\xcb\x01-ۇ\x12\xea\xf8}\xbe]\xc1`\xf0\xa2I$C\x88\xaa\xaa\xa1\xa0\xa2\xfc\xc0\xef\xf3\xede\x18\xc6\x1e-h\xd9>\x84\x10\xd7\xef\xf3\xed\xaaP*\x1a'I\xbdO\xaa\x14ev0\xa0\xfcD\x92\xa4\xe6\xe1\x18!\xe5\x04)\x89\xe2\x11UU\xd7LXh!Y\xbeB\t\x04~+\x89b\x8f\xd7FH9?\x92(\x1e\x0f\xc9\xf2G'\x14<\x7f\x8d\xd2s\xb6\x02\xcb\x03\xb2-\xa4(\x9f\x9d\x18\x9e\xf6\xaaڨ\xb0(\xec\xb2<\xe7\x8e7\x90>\xc5\xdfUw\xf5\xa2q\xbd\xb4R\xce$\xef\xea\xd3XثÐ\xa6+ \x84\x9c\xf57\xe5;\xb7\x12\xb5\xb76\xa1\xe2\xb1k\xabً\xaa\xbe4\xae]\x03Ƣ\x1b\x01{\x89K\\d\x16\x8a`g\xf0`v%\xa1'\xb5\xb3\xebFd\x11\xea\x95\xe7AZs.P/\x03'ՐR\xf8\xc75@j\xda\xcf\x03\xb8\xe3\xbd\xff`\xa9\x14\xd6\n\x05B\xb3\x04\xebP\x1c\xb6e\x8f\xdd_O\b\x94\xc6\x19\b\xac:\a\xb4q\n\xc0\xd1,k\f3\xbe\x01F\xdf\xea|\x8dY[\xed\xd8\f\x06ݽ>\x93\x03\xad\xad\x80\xb47\x8dLwrL\xfdhqz\b\xca\xea\xf3\xc0\xaf\xa8\a*\xf2Ǽ]\x96\x8co\x80\x00\xc0\xe94b\xfb\x9c\xaa\x0f\xfeOG\x042\x8d>\xf0\xdd\x02\xb0/\x01#c\x8c\xdef-\xb0P\x97\x9d\v\xff\x9aY\xc0\xbc\n\xa0Э\x9a%Ҹ\a\xc8Z\xe4 \x80\xaa\\\x7fdT3 +\x83\x10\x0f\xea0Z\x13p\x1c\xa7l?00\xaf\x06\xf2G悽\xb4\x0e\xae\xc8\x14\x7f\x01\x86\x8a\xe3\x1e 5\x98\xf5\x80\xbd<\xefRD\x01m\xbe\x00v\x06\x0f~o\nZ_z\xe4\\\x9b\xaa\x00\x94\x95\xb3!\xae\x9a\tL\r\x9c2HJ\x11\x97!\xe3\x1f \v\xfa[\x00\xffR\xc8\x17\xac\x00\x81\xd5\x14\x80\xd0\"\xc2>\x14\x87eZ\x1e\xad\x91\x04ʒ\x19\x90\xd7\xce\x06Y\\\x030\x1e\xb93,\x11\xc6=\xc0\xbe7[\x0f\xb0k\xaam\x8bC\xc1k\x94>\x83\x05\xa9\vAܧA\xefH\xc2uK\xd3\x11\xe9\x9c\n\xa8k\xe6\x80]Q\x0fȜ\xf7\x86*\xcbp\xe3\x1e \x00p&\xd3iqvQIS\x97#\xd0.\x96\xc0M\x17@\xf6$`d\xf4\xc2\x06\r\bP\xae\x98\x05\xdf\xca\x19\xc0\x05\x15#z\x83.\x87\x89\x01\x905\xb0\a>\x94\x94\xf56+)p\xa5\n\xf1\x1d\x03\xe6\xd18l\xdb\xc9\xea\xb3\xc9\v\xeb\x10X=\x1bLS\x1d 0e\xbaC\xcaN\b\x80\x8cE_\x01쫇s1m\x0e\x0fZ\x1f\x86\xb8;\x03\xad7\x05\x00\x10\xaae\xa8\x1f\x9e\x03~\xd5L\xa0\xaa\xfc\x16\xbd\xcbQfb\x00\xa4\xe4)\xb8\xb8\x0fô\x1d\x1c\x91B\xbb\xc4\x0f\xb1ۏ\x8aO6\x80\xcc\v\x03\xa3\x19_\xe5\x18:\x9e\x01\x9e\xba\xb9\xc8\xe6\xb6vΤ\x9ey\xeaZ\r\x019\x7f\x94\xe1\x01\x00G'\x06\xc0\x93\xfb`\x9bwk\x97\vD\xc6@@\x9c\xa7hhh\xe0&\x06@\x93\xec\xf0\xf2\xe2N$=\x06\xee\x90 Z/\x84&\x04@j\x91\xbfxyq;\x9a\x1e\x137I\x14R5!\x00\x12\x83\x7f\x96\xb8\xde]܊\x8d\r\x80:\x87\xf0\x84\x00\x18\xdd\xd5\x1ce\r\xea٬\x1b\x891\x92\x86b\xe8\xc4\x00\b\x00\xbcN\x9a={\U00093a71q\x97\xdc\x04\x02Hm\xf7M\xcf4P\xd7@\xf4\xd1\xcf\xe83\f\rN\x18\x80\x8c\xc9\xfe\xc9\xcb\x01\xdc\xde\xccX\bWL\x1c\x80\xd1t۟\x88\x03\xcfL\x19\xa7o\xf4\x01\xba\x94\xc8\x13\x06 \xf6\xc3\xe0\f\x1a\xf7\xcc\x12\xed\x1f\x03\xfb \xa5\xea\xc4\x01\b\x805\xc8a\xcf\x00\xc6Gߕp\x99\x89\xa4\x81\x00X\x9bl\x1aO\x96(a\xc6omhV\x80Tw\x9e\xf7\x0e\xe0\xe8\xfb\x82.\xa5\x81\t\x050\xba\xbd\xf35jyc\xc8X\x96\t\x924Gُ\x18\xbf\xa5\x85\xb9R-\x0eoЈg\x1a\x10\x19eK\x94%\xbe\x89\x06\x10\xacM\x0ez5\x88\xdd7ʆ\f;~kCs\x02d\f\xba\xc13Kt\xb4\xb3\x12\xe3\xb864'@꒧\xbd\x1aČ\x8f\xae%JX\xcaO8\x80\xfdo\xb6\xeda,\xe2I \xd3\x18eW\xc2e& @\x00\xf0\xc5\xe9\xffx\x91\x1f\xd4RɁ\x12\x8b\xd1\x02\xc8RnB\x02Ll\xee\xf8r0\xc2\xdf\xc4\x1adX\xf5\xf3\x8e\xe3\x80DG\xe9d\x93f\xbb\xe4x\xe2\xf5\t\t\xf0\xe4R\xfa\xbf\xbe$7OLӞaiAo\x99\r\x19\xc3\x06\xdd\x13هu\xed\x8bZ\xef^\xb7v\xbc\x02,\xa6\xe6\x8f\t\\^\xf7bR\xb5>\\J\xedhm\xc3|\xb0\x8dehwf\xbb\xa0oG\x0f\xf2\xc737\x1e~\xf8\xd5\x1dcm«\x82\xc1\x8b{\xa2ѝe\xd3\xc0\xf7OMr\xe3\x895r\x9c\xfd'\xea\xa0\xe8\x03\x82F\x7f\xb2\f\xe0\xfa[\x98\x97ۮl\xbd\xf3\x85\v\xc6\x1a\xbc` \xf0!Q\x10zz\xa2\xd1\x1d\x92(\x1e\x0f\x87×\x95[\x03OIť3/I\xf83\x7f5D\xb7\xe0\x18\xa3\x18\f\xa2\xf2\xd3KG\xc0BqA\x0f\xc7\xda\xdcc\xf1/\x1d\x7fh\xc3\xcbcM\xe3\x14E\t;\xb6\xfd\\*\x9d^\xf1\xfe\x13\\\x84\x10\xf8%i\x8b I\x9f\x8cD\"\xede\x05\b\x00\x95\x97\x9f/\xa7\xd9\xf8\xe6t\xc0\x9e_P0D\x10P{\xcb\n\x0f\xc1\x01\xe6\xaeN\x97\xd9\xd3w\xe7\x89\xdf\xed\xb8g,\xeeO\xaa\xaa~?\x9dJ\xddeZVN+\x98\xa1ԑ$\xe9w\x95\xa9\xd4\xcd̀V6\x80\xa7\x9e\xb0˧\xfc4\xa1\xd8_s\x87Z\x8c\t\xc1\xd4/\xad\x02a\x87_\xe9\xae\xef\xea@\xec\xf1]0\x0eG@)u\xfd\x92\xff7\x89T⦱\x02\xaeRU\x1bR\xba\xfetF\xd3\xce-\xf4;\x1c\xcb\x1a\x92$=\x1cO$\xbeUV\x80\x00\xa0,\xac\xb9#Y\xe5\xdc\xef\x88\xf9/W{}\x13\xd8)\xa5\xe7V\x8d\x83=\x88=\xb1\v\xfaޮ3\x97hA\xe8\x90|\xbe\xb5\xfd\xfd\xfd{F\v\\]]\x9d/\x11\x8b=\x95\xcad\xaeu\x1c\xa7\xa4\xb9\xe59..\x88\xe27\x13\x89\xc4/G\x1c`(\x14\xbaP״\x9ff4\xed2\x97\x01\xc1\"\x05\xa8\xcd}\xa2\xb9\xb2i\x01\xc4EuŃ;ԋ\xf8\xd3\xfb\xa0m\xcd\x7ftc4\xb51\xa8(\xdfH\xa5\xd3\xf7\x98\x96\xe5I\xdcU\x12\xc56\x81eo\x8c&\x93\xafy\x0e0\x18\b\xac0\x1d\xe7\x81t&\xb3茣ճ|\xc0\xf9\x81\xacWV\xe7\x9c\v\xf9\xca\xd9\x05\x8fc\xb6F\x11\x7fr/2\x1b[\x8a\xear \nB\xb7,Ik\xbd4\xd7\xf3<\xc4\v\xb4L\xe6\xf7\xc5,\x97\x05/\x8f\x84@\x92\xa4\x83\x92$\xdd\x10\x89D\xde\x1e6@UU\xff\xce\xd0\xf5\x1f\r\xf9c+x`\xb1\x02\xf0\x83\xf7;\x7fm\rB\x1f[4\xe48V[\x1c\xf1g\xf6!\xbd\xfe\x18\xe0\x94\x16\x82+\x836\xb2r@~8\x95N}\xa5\xd4岨{\x11\xa5\xbf0<\xf7\xd9h4\x1a-\x1a\xa0\x7fAu\x8ds$\xbe;\x93\xd1j\n_\x03(\xb0X\x05\x82\xa7\r0A\x96Q\xf5\xb9\xa6ܮ\\O\n\xf1\xa7\xf7!\xb5\xee0`{\x13;\x95D\xb1\xcd\xe7\xf7\xaf\x89D\"\x9e\xe57\x83\xc1\xe0M\xe9T\xfa\xa7\x86i\x94\xb5ֆe\x18\xcb'H\x8f\xc5\xd3\xc9ہ\x01_\xbc \x930U\xd9\x1d\xb1\x17\xf8+Y\xb6\x88\xe3\xe6\x19\a\xd8\x1c\x05\x9aOg\xe3--{\x13\x04'\xa6!\xf6\xf8Nt\xde\xfa\a\xa4\xfe\xf2\xaeg\xf0\x00 \xa3i\xd3\xe2\xe9ľ\xaa\xb5\xf3o\xf6\xc45h\xa8[\xa3U\xb8\x8f\x97\x1b\x1e\x00X\xb6\xcd\xc6\xd3\xc9\xdbx\x8e\x8b\xa9\xaa\xfa\xd5\xc2#1\xebaAa\x13\xee\x15!\xf0\xbe\"ڮ8.\xb0?\x01\xec\x8a\x03\xb6\v\xdb2\xe0j\xa7\xe3\xe2N\\G\xec\xf1\x9d\xe8\xf8\xe2\xf3H\xfcn?\\\xd3\xfb2|u\xd9,\xd4\x9fzS\xd8\xe4\x12\b\xa7\x83A.2\xb5\x04l\xb8\n܁\x14\xf4\xf6\x91\x8b\xf7\n\xf5!T}o\xf9\xa9^\xa8$\xe3\xbc[\x14@\xb0\xe4Y\x00\xdf|\xef_\xb5\xf9\x02\x049\fs\x7f\xb4\xf0\xe6w\xa6\v\xed\xf5֑\xb1\xd4D\x0e\x95\x9fX\b\xe1\xe3s\xe0f\xe9A\xe32E\xb5\x9d\xe4\x01d}\xc2(9\xb3u\x97Ż\xb0.\xf2A8\xc7\a{g\x14\x96\xc7\x0fgx\xed<\xf8\xbf|Ѡ\xfbr\rsw\xe1{ \x80\xc4\xeb'6Q{p\x16B\xafg\xc14\x86\xc1r\xa3\xd8K\x87\x00\xa1Us0\xf5\xd1\xeb\xc1\x7fz^Vx'm\xf1!kC\a2\x06b7\xc7q\xb1\x90\xa2ܘU\x03\xe1伎\xae\x02\xce\xf2\x10ĹaOb\\\xac,\xa0\xee\a\xab\u0eed\xe1\xcc\xfbrȖ\xe24\x10p9\x83Ftip_Q\xb3\x92\x82\xb9\"\b\xe1\xcd$\xf4Ty\xbbR\x04\x16LA\xf0\xcbK\x80Y\xea\xd0~>\x93\xfbmh\xefe\fb\xa9ԩ\x8cA\xd44\x9f\b\xf8|\xb7\xf1\xa2xU___\xfc\xf4\x12J\x05 \xb7\xb1\xe5P\x17\xda,\x16\\]\r\xc8\xde$\x8c\x9e\xd2\xea\x81\xe4\x86iP\xefh\x02BY\x8cF\xdbE\xcb\xf1\xaem\xc5\x02\x04k\x92\x03\xba\x843R\n\xb6D\xe1,W nc\xa1\xf5\x8c|)\xbdP\xab\xa0\xe2\x96\x06Ц\xa9E4~\xcd^\x1b\xaa\xca\xf2\xb7\xd3\xe9\xf4ݦe\xf1\x835\rH\xa6ӗr\x86\xd9\x1d\f\x06\xff>\x1a\x8d\xfej\x00\xa0[\x90\x19nJ.\xd0\xe8\x87\xd8ヱ\xbb\x0f\x8eQ\x98\x85M\x18\x82\xaa\xcf7\x82\xff\xd8y\x00\xcd~s$\xaa\x1bxf\xbfQ4@\xc6\"\xaf\x01Ț\x13r)\xa0-\xf5A<\xc8B?\x1a\xc5H\x9401\x12\x8f\x8aO_\x04\xfe\xa3\xb3\xb3\xf7\xc7η|0d\x10\xa0JU]\x9c\xd2\xf5gb\x89Dި\x92i\x99B,\x1a\xfd\xa5\xdf\xe7\xbb#@\xe9\x9a\f\x8ah_I\x00\xad\x9a\x80YY\t\xf1\x88\x0e\xedH4\xff\x83Y\xa7\xa2\xea;ˁ\xd9\xeaP\x06\xe1)\xeb\xb18\r\xb4ا\x01+o_Qm\x1e\x0f!\x10\x86\xb9/\xea]g_B\x10^;\x0f\xbe\x1b\x17\x00Ji\x15\x82\x84\x1b(-\xac\xa9\xa9\xf1g\x92ɧ\xfa\x12\x89k\n\r\x81\xb9\x00R\xe9\xf4\"\x9deۤna7Bŵ_\xb39\x17\xf6\\\x1e\u0094jX\xbb\xa2\xb0\x93FA\x86J\xeeȊ\xd1U\x12\xc0\xbe\xb7Z\xf73W\xd5\xd86\xeb\xe6\x1dE\x9f\u0382\rT\x80\xd9\x16\x85i\f\xcf\xcfS\x96\xd4C\xf9\xd2b`\xda\xf0\xdc8\x97!\\PQn\xef\x8b\xf4\xddcZfIM`-\xcb\xe2\x12\x87#K`H\xc0\xbc\x00\xc0\x16g\xa9\xe8*@\xae\bBl\xb3\xa1\x1f\xe8\x87k;`e\x01\xd5w,\x03\xbddJ\xc1\xab\x16\xc9\xd8GJ\x02\b\x00\x9cA;mv辢V\x88\x80^\xa1B\xd8R\x9aq#ևP\xf1\x85\x06\x90\xc6Zo\xc2P\xae\xe3\x8b\xc6\xe3\x0fxr\xb1\xd6\f\xd0k\x00\x17\xca@eq+\x82K\x01\xad\x9e\x01WU\x05\x9f&A\xf9Z#\xdcPq\xcf\x13լ\x03%\x03dL\xb2\x17(\xac\xaf\xa8#R\x18\xcb\x15H;9d:\x13\x85-ӊ\x88\xca\xcf\\\fv\xed9\x00\xeb]\x9f:\x97\xf38a\x90\xb6\x817\xa3@}i\xdahJ.|+g\x17\r\x0f\x00``k\xc9\x00Y\x1b\xaf\x00X[\xcc\x13\x97i\x90 \x1ed\xa0\x1f\x8b\xe5l\xcdLX\x8a\xf05\xf3\xe1\xfb\xd4<\xb8\xb2\xf7\x95\xf0T\x18!_\xb55\x03t\xeb\xc0\x02\x19\xa8)R\x93|%\x14\x8c\xbb\x00\xa31\x9bJ\xd7@\x81<\x05\xe0\xdeb\xbf\xa7\xcd\xe3\xc1\xaba\xd8{\xa2\xb0\xed\xc1&\xb5\xb2t&\x94/^\fL\xf5c\xa4\n\xf0\x890\x82\xc1\x06\xcd\x01\xb6ŀ)\xc2\x00H\xbe\xc0\x95\xc3_\u0083\x9a0\x9d#\x8f\xbe\xdc]2\xc0\xbe\xf5\xedm\xec\x9aZ\xc3✢G7\xea\x18\xb0\xfe\x10\xb8\xad1\x98\x86\tif\x18\xe1//\x05YT9\xf2\x01\x1b\x81\x1d\xf0\x19G\xf2\x88F\x87\x0e\xf4\x99\x03\x10k\x87\xd6F\xea\xe7\x8b\xfe94a\fr\xb4Kz,9\x03\xed\x16\x87\x92^Fl\xa9\x14tE\b5\xf53\xc1]\x97\xdbY\x1d\x89\x90\x1b\xe1Y\xb8\xba5\xb2\xe3\xe8\x0e\xb0=\x06ԉ\xc0\xfc@^mt\xfd%L\x7f\xdc\xe8\x1d\x04\xb4$\x87\xdad\x86Uk\xe2\xf0\x00\x9d&\x97\x0f\xde)-,_\xfbl\x12\xb1\xe0\x9f\x96ۂ\xa6,\v\xf0\xc5\xff\x1e\xa2٭\xc3\ah9/\r\xf7\x06\xedh\xf9\xcf\f\x12\xb1Hđ\xd9\x03\x85e\xd3\x10\xbe\xedR0\x81\xc1\t\x0f7O\x06\x82\xe1\n\xd7@ڙѰ\xb5\xeb\xa3\xcd?\x7f\xe3\xafgp(\x1d \xb3\rpJ\x06\xe88\x0eЧ\x95\xf5e ^k a\b\xaan>\x99\xfa\xc9\xf2z\x85|\x1aH}\x85i =\x14m\xe1\xf7\xc7\x1a\x0f\xffꍬ\alK\xbe#\xceq\xff\x04\xe0\xc6a\x85\xb7\"\x19\x902\x02\xe4+\xfc\xf0*\xe5,֩\xa8\xfc\xeer`V\xeeԏc\xe4vY\x18)\x7f\x14\x86\xd8.\xe8\xae\xde\x17[\xeez\xe9\x9a|\xdek\xc9\xc1F\xa5\xf3\xc4\xef\xc90\xb3EN\x7fy\x8f][\xf3\xfd\x10\xcf\v\x0e\xfbM\xdd\xe1\xab/@Ճ\x1f\xc9\v\x0f@^\x9f\x93J\xb95\x90$M\x87n\xe8\xfaN\xcb]/}d\xa8\xd0C\xc9\x1a\xd8\xdc\f\x8d\x9fE\x13\x86\xe8\x94|\xdcȊ\xa5Q\xce\x17\x1b\x11\x96\x816\x87\a\x1f\n\xc3\xd9\x19+\xfa݇Ŧ~\x9c<\xd7'9\xc2h\xa4#\x9d\xa6\xef\xc4V\xb7\xfc\xd7+\x9b\vZb\x873!R\x9c\xf98k\x96\xde\xc1B\x8f\x97\xb9\x93\xe1\xc9\x04\xb3Q\xc5\xc0Y\x19\x86\x18,\xbc\xd2PY2\x1d\xb5\x0f_\azɔ\u0081\xc7휛 ɲ\a\xd2C\xfdG\xc8\xce\xeei-\xf7\x15\x06\x0f\xc0\xf0\x14@?\x918\x16\xae\b\xbfh\xb2\xee\xcd\x0e\xeb\x16\xafͶ\x03\xff\xc53F\x9e\x9ba\"\xba\xf1\x10R\aO\x9fdv\x19\xc0\xaa\xe7!\xda\x1c쨞\xd7P\xa9\xfe\xc2R\xf8n]\f\xf8\x8a\xbbE\xb9ú\xc59\x1c5\r\xc1\x99\xff\xc1\xda\x1d\xa5a\xd6\xe9W\xf0Y\x0e\x98\xd7;\x9ek\xbd\xeb\xe5e\xb1m\xadEm\xd3\xc3N\xb8\xf5n=\xbeM\x8dJ\x8bx\xad\xf8\xf7M躞\xd7\xd4\xf6B\xb4\xd6\x1et=\xb5\t\xa9\x03\xd9\xcf\x16j\xf3xpK\xb2\x97F\nu*\xa6\xdew-\xf8\x1b\xe6\x94\x14\xf6sA\x8e\xc77\x9f\xf8\x94\xda#|\x8c\xd3\xe8\xe9C\"\x04\x80\xff\xa4\x11\x133\x1c\xe6\x95\xf6\xdbZ\xee{\xf5\x13%\xf9\x9f^LR\xef\xb6c\x87\xe44;GȐXQ_$.\xac\xce\xe4\x88i]\xff\x86\x03\xe8\xfd\xf3N\xd8\xe9\xfco\x165\xaaO.\xa9\xaa4\xc8P\xa9~\xf0#C\x17\x18\xe5\x9b\\\xd3:\x01\x00\xd1m\xc7\x7f\xaf\xb6Y5\x81\x18\xb3\x11.\xc0\xb2\x1c\xc0\x10\x90\xe3\xc98\xf7f\xcf▟\xbc\xf6H\xc9\xee\x9cW\x13\x16\xd9\xdc\xd6.7\xd4\xcd&\xae{P\xf3\xd9\x05燬\x9e\x04\xb8z\xd5c\xad\xebE\xffk\a`\x17Q\xca\xe1\xf0\x80\xb6L\x86\xefm\x11\xa1\xcf\r\x94r\f7\xf3\x14\xaa\n\x9dR\xfb\xdeC\xbd\t\x1c\xc22\xb5q\xcaW\xec\xe9\u0083\xf4@\xff\xb1`\x8fٸ硿\r+\xa6\xe8y\x18\xa4\xf2\xf2\xf3\xe5\x14\x17?\x90\xf1\xdb\xd3\n\xf9{u\xf6Lȫ\xe7x\xa3u)\x13\xb1\xdf\xecD\xaa\xafgйĢ\xa2*\x8a\x8c\xaa\xcf6\r\xff\xc7\xe86\xda>\xf9d\xd6\xf9\xadZ9?г~\xbf'K\x8f\xe7\xc1\xc1ލ\x87\x12\x98\x8fY\x92;eO&`\x9f?\xa4\x06z\x14\xd4\xd6v\x9c@\xffC[`\xf7\xa6\a\xf6\xab\x0520\xbd\x84\xe3_^\xa5\xb8\f'\xe7\xe6\xee\x15\xbc\x11\x01\b\x00\xc1\x96\xc0\xe5\xda\xe1\xbe0\xce\xe5\x80s\xf3\x9b\xeaVrx혝\xb4\x89دv \xf5һ\xa7]^\xc7\x05\xf6ā\xe8\xc9\xec8)\xff\x9aD4k\x843\xc7#\x000\x1c\x0e+\xba\xa6=\x1bK\xa5V\xbb\xae\v\x1c\xd4\x01\xc3\x01\xe6\xe6\xce;\x98\x99҃[\xdaΎ\x01\xad\xcbu\xfe\xa05\x03\xa4\xac\x81\xa3ޅ֩xTrAt\xc78\xab\x00ʲ\xfc\xfdx,v\x97eۃ7\x9f#i\xc0r\x81\xf9\xd95\xc1q-8)\x03\xb4\x88\x02\x1fW\xb7\x10\xfb\xf5.$\xff\xf8\xf6\xd0\x13\x1e1\x81\x8d\xfd\xc0\x12\x15\x90ٲ\x01tM\xb7,'}\xd9i\x1b\xd8\xd4\x0ft\xe9eSA\xa2\x99\x89\xb3\x06\xa0['\xb4\x8asC\xf9\xb7\x8f\x13\xda@\xb1O\x96\xb6!VO\xa20\xad{|'z\xee\\\a\xab\xa3\xf8\xb9\xa1>\x0e\xa1k\x17\x96\x85\x1f9\x12\xef!\xef$V\x9f5\x00\x05M\xfa\xad6\x8b\x03\xbf \x9c?\xd2ߥ\x03[c\x03K\xea\xfb\x01\xf6\xe77d\x8c\x83=\xe8\xba\xfd\x05$~\xb7\xbf\xa4\xd6\xcd|c-\xaa\x1f\xb9\x16\xfe\x86\x19CZ\x99d8\xad\xa1]\x80\xd9\x1d\xd9r\xfc\x89\xf6\xa9-\xbf\xd8p\xec\xac\xd9\x03{v\x1d}\x97\xad\xae\xb1\xf4\x19,+ \x04c\x7f\x7f\xce\nlD\x8c\x81\x92\xf4\xc6ӆE.W\xc25lğ܃ij\aJ\xeb\xb9\xcd\x10\xc8_\\\x04\xe5\x9a\v@\x98\x81\xb1(\xcb\xe4\xcdӹ\xa5\xaa\xa0n\xbb\xec֞{\x9a\xef\xf9\xeb\x9d(\xa3xf\xc4p:\xe9\xb08w\xba>\x83\x85@B0\xf6\xe5\x81\x185\az\xc8\\\x12\x04D\n+K\xc4\xc48\u0603\xbe\a6\xc3j/\xedMxB\x9d\x8a\xca\x7f\xbc\x02d\xce\xe0w?\x12\x8e\x01\xf2\x00,\x85\x1f\xe9J\xeb̶\x9e\xeb\x9b\x1f}\xfd%\x94Y<\x03\xc8\xdat7\xe0L\a\x06\xce\xce\vL\x18\xe6\x9e>8\xb9Ze%-`s?pI\x10\x16ɜ\xa9u\xcf\x1d(\xb9\xcdVp\xd5\x1c\x04n]\fHg\xde\x1ea\x86J\xc0\x14\xe7\b\x92C\xd1v\xfaN\xac\xb1\xf9g\xafw`\x14\xc43\x80\x8c\x85u\x00\xae=\xb5\xa2Le \x900\xcc\xdd\xfd\xb9\x0fz\x9e\xb4\x0e\x9dK\x82\xb0\xa3\x1a\xec\xae$\xfa\xee\xdf\x04\xab\xad4\xadc\x03\x02\xaa\xbfq9\xe8e\xb9;\"\x12n\b\x80\x05.Յ\x96<\x9c5\x00\x85\xb4\xf4\x14\t'\x1ep\xdf\xf7\x00\xebu\fx\x84`僨;\xc0\x96(\xfa\xed7\xa1mn+Y\xeb\xfc\v\xa6 \xf4\xadˆ,\x92\x12m.c\x02\xc3*\xc4!)ˡۻ\xbf\xd7r\xef\xab\xf7a\x94ų\x03x]{\x8et\xb3\x06=\xc3\xd12\xea\x18\xb0\raP\x9ag(Á\xb6\xf1xi\xf0\x18\x82\xea[\x1a\x11\xba\xfbʂ*\xdc\xc2\xd5u\xff\x19H\xb0[J\xdd\x04IG:M6w\xae\x18\v\xf0<\x05\b\x00\xacA\xb3v\xf11\xaa)؆\x10(\xe3\xe9p\x10\xa6\xa8\x98vߵ\xe0o8\xbf\xe0 4\xe1h \xb9\xe1D\x93\xdc\xcf=A\xb2\x86\x86\xf2L֡\xfe\xa3\xee\x9b\x1d\xd3[\x1fX\xff\x06ƈx:\xa3\x9c\x83\xed9\x95\xac\x9a\x01\xdb\x10\x02\xe3\x11\xc4\xf0\xday%%\\]\x86*\x00\x90\xd8\xd4\xfey%\xc2\xddI\xed\xc1\x87\x04\xb2\xba\x11\x96\x03据\xa7Z\xbf\xfd¬\xb6\xff\xde܇1$\x9e\x02\xa4&\xf9s^\x87\xbc\x8a\x01]\x1a\x02Ô^\x8a\xc3\xca\x02\xea\xbe\x7f\xe5@\xf7\xa2\x12*\xad]\x06\xca{\xff\x1c\xdb\xd2\xf6c\xb9\x97\xb9\x8a3i\xee\xc0s̰\x99\xd7N|\xa5\xe5\xc7\xeb>\x831(\x9e\x02\x142\xd6sC\x1dz1\xc3\f\xc8\xd2\x10\x18\xb6\xf8\xc9\x0f\\X\x87\xda\a?\n\xdaT7\x8c;&\x83R#\xb1m'\xd6\x05{\xd9\xf9B\x86D?h\x85\xd2\xe3\xa9\x18\xbf\xa5\xf3\xe2\x96\xfb\xd7\xff\x02cT<\x05ص\xa7+\xc5\xe9d\xc8\f\xad\x15\xa6EA$'\r\x95\xe0\x7f|\b\xa8\x1c^\x8fN\u00903r[=;\xda\x0e+N\xe5t)\xc5\x1e\xc1I3\x9a\x1e\xe8?X\xd5m\xd5\x1d\xfdɆ\xbd\x18\xc3\xe2yB\x975\x99\xa3\x86h]8$\xc4\x10\x05\xbb4\ffk\x1fl\xcb\xce\x1bQ\xa9\xfa\xce\x15\xc0\xec\xa0G\x0ek\xf6\xae\x85'\xb3\xe4\xe7\x05?|\xce\xef\xe9\x86\x13ͭ\xf7\xbez{+ƾx\x0e\x90q\xb0\x05\xc0\x85\x85\xfc\xad\x15\"`\x9bB`\xb7D\xb3VI\x17ս\xa8\xe0\x1f\x98\xb7k\xa1\x1b]w\xec\xba\xe8\xbac8[\x84z\xfeD\x18\xe4\x0f\xc5\xfc\xbd\xa5P\xa0)8\xa8.3o\x9b\xc5\xe1\xdf\xf1\xb8z%\xb9\xe7\x1a\xd8\xefk\xff\vuj\\\x87\xba\x05\a\x15-\x99\x82m\n\x82\xdd\x1c\x85\xb4\xb06w\x9bE\x0f\xc4a\xc7\xd7\v\x91=\xd7@\xac\x87\xc5\xe9\x88\x15\xfb5K\xa6\u0bde\x06\xf5_W\x8c\x18\xbc\x01G\x9e\x11&\x01\x0ei\xc8\xd0wJ\xf9\x9eV\x8e2\x12\x06\xfc$\xc0\xa1\xe6H\xcf\xef\xd0\xe7\\\xde\x1c\a\xa4\x7fd\x8b\xb9\\\x96\xe1&\x01\x0e!\xf1\xad'~\x18\x881%\xbdx؍\x8c\xe0\xa1O\x17\xa0\x1d\xc9\xed\x93\x00\v\x90\xe4\x1b\x1d\xcb\xfd\t止\xf7\xc2\xe8\xc8\x00$\xba\r\xe6\xf5\x8e\x87[\xeezy\xe5$\xc0\x02%\xb5\xa1\xe3R)ɼ=\xea\x00\xfb4\x8by\xb5\xe3\xd3-\xf7\xbe\xf2u\x8c3\xa1#|}'\x93\xecX(\xa5hK\xa1_0\x13\xde\x02$G\xe3=\xcc\xeb\xdds\x9a\x1fY\xff[\x8cC\xa1#>\xc2v\x985\x10\xe7JI\xb6\xa0\x9a\x11=\xe9ѹ\x8f\xf7J\xfc~]\xbe\x12\xbf\xf1\t\x10@\xf3\xfafML\x8a\xf3\xc443d.Mˤ\x87\xfd\xf62b\xd8.\xf3Fǽ-?x\xb1\t۷\x9b\x18\xc7B\xcb5P\xff\xf6\xa3\xb1`ԝ\xcbk4\x7fŒ\xeb\x0e4\x00*\xf5\x86\"\x9aA֟\xb8\xbe\xe5\x9eW\xbe\x8b\t \xb4\x9c\x83u\xee\xec\xec\xf1G酼\x9e\xff<}\xa9\xae\x04=\x12\xefbwv\x9e\xd7\xfa\xd0k\x7f\xc4\x04\x11Z\xee\x01\xfb\xb7\x9fh\x95\x93\xc2\x12\xce 9O\x9aX\xc56\x00r\\\xd0\xed\xdd\x1b[7\xfea\xea\xd1\a\xdeh\xc5\x04\x12:\x1a\x83F\xb6\xb4\x1cTc\xfc2\xd6\xc8\xdecƊ\x15\x010m\xba\xec\xdf\xda\xefj\xbd\xeb\xe5ex\x066&\x98\xd0\xd1\x1a\xb8w\xeb\xf1m\xfe\b{\x15c\x913&\xdd,\xf0\xd85\xed\xcch\xf4\xaf\xedk\x9a\xef_\xffCLP\xa1\xa39xlG\xfb\xabJ\x0f\xfb1\xc6\x1e\xdcuMO\r\xedJ\xd0C\xd1\x16~Sw}k\x96\x16\x8c\x13I\x98\xd1\xfe\x01ZG\xe2\x9d`e\xe8\x88!8\x1fw\xe9@\xa1\xa6\xedXP\x17\xce\x04\xb2\x94 \x12\xdb\x05\xb3\xb3\xf7\xc5\xd6\ufff8\xb4oWk\n\x13\\\x98\xb1\xf0#\xb4\xb6\xf8^%\xact\x9a\xa2{\xcd{\x10\x95\xe9u\xc0\a^\x00B\x92\xa6C7\xf5|\xaf\xe5G\xebnä\x8c\x1d\x80\x00\xa0\xb7'\xb7+\xd5!\xcd\x10\xed\xd5 \x80\\Y\x01Rs\xba\xfe\x88t\xa6\xd3dG\xef\xaa\xd6\xfb_}j\x12\xdb\x18\x04\b\x00\xfa\xf1\xf8F\xb5B\x95\f\xc9Y&)A03\x06\xaa\xae\xe9\xdb\xd1c\xce[\x1d\x17\xb4\xfdl\xe3\xa1Idg\x81\xc8MS\x1f\rߺؙ\xf6\xfcg\xdd\x19\xdf]\xfd\xec䌜\x85Rs\xc3\u009f\xd7\xdf\xfe\xa1\xafN\xceD~\xf9\x7f\xbc\x1e#ls;\r\x81\x00\x00\x00\x00IEND\xaeB`\x82"), "LoopiaAPI": []byte("\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x02\xaf\x00\x00\x01\xbd\b\x06\x00\x00\x00;\x97\x9f\x90\x00\x00\x01\x84iCCPICC profile\x00\x00(\x91}\x91=H\xc3@\x1c\xc5_[\xa5U*\x1d\xec ␡:\xd9EEt\xabU(B\x85P+\xb4\xea`r\xe9\x174iHR\\\x1c\x05ׂ\x83\x1f\x8bU\a\x17g]\x1d\\\x05A\xf0\x03\xc4\xd5\xc5I\xd1EJ\xfc_Rh\x11\xe3\xc1q?\xde\xdd{ܽ\x03\xfc\xcd*S͞\x04\xa0j\x96\x91I%\x85\\~U\b\xbe\xa2\x0f\x11\x840\x8b\x80\xc4L}N\x14\xd3\xf0\x1c_\xf7\xf0\xf1\xf5.γ\xbc\xcf\xfd9\x06\x94\x82\xc9\x00\x9f@\x9c`\xbaa\x11o\x10OoZ:\xe7}\xe2(+K\n\xf19\xf1\xb8A\x17$~\xe4\xba\xec\xf2\x1b\xe7\x92\xc3~\x9e\x195\xb2\x99y\xe2(\xb1P\xeab\xb9\x8bY\xd9P\x89\xa7\x88c\x8a\xaaQ\xbe?\xe7\xb2\xc2y\x8b\xb3Z\xad\xb3\xf6=\xf9\v\xc3\x05me\x99\xeb4G\x90\xc2\"\x96 B\x80\x8c:*\xa8\xc2B\x9cV\x8d\x14\x13\x19\xdaOz\xf8\x87\x1d\xbfH.\x99\\\x150r,\xa0\x06\x15\x92\xe3\a\xff\x83\xdfݚ\xc5\xc9\t7)\x9c\x04z_l\xfbc\x14\b\xee\x02\xad\x86m\x7f\x1f\xdbv\xeb\x04\b<\x03WZ\xc7_k\x023\x9f\xa47:Z\xec\b\x88l\x03\x17\xd7\x1dM\xde\x03.w\x80\xa1']2$G\n\xd0\xf4\x17\x8b\xc0\xfb\x19}S\x1e\x18\xbc\x05\xfa\xd7\xdc\xde\xda\xfb8}\x00\xb2\xd4U\xfa\x0688\x04\xc6J\x94\xbd\xee\xf1\xeePwo\xff\x9ei\xf7\xf7\x03\x81Dr\xac\xb7\x16\xd3\xcd\x00\x00\x00\x06bKGD\x00\xff\x00\xff\x00\xff\xa0\xbd\xa7\x93\x00\x00\x00\tpHYs\x00\x00\x12t\x00\x00\x12t\x01\xdef\x1fx\x00\x00\x00\atIME\a\xe7\t\x0f\t\b\x1583\xa6\xd1\x00\x00\x00\x19tEXtComment\x00Created with GIMPW\x81\x0e\x17\x00\x00 \x00IDATx\xda\xed\xddy\x94\x9cu\x9d\xb7\xff\xebs\xd7\xd2\xe9@\x80\xb0oa'd\xabN 8.(*ਸ\x8d\xfeXDY\x15\xc2&\x8b\xe3\x82Bb\xbaӉ\xb8\x8d\x10v\":\x02**\x8f;\x8e>\x0e\xa8\xe3\xe8\xe3\xe8\x18\xc1nBX\x15T\x10\x94=!Km\xdf\xdf\x1f\x89 \x1a\xa0\x93tu\xd7r\xbd\xce\xf1\x9cq\x84tջ\xaa\xee\xba\xeaNWU I\x92\x9e\x96ޟ6\xa1\xbb2\x11\xd2ޤloH\xfb\x10L\x00\xc6\x01\x9bA\x8c\x854\x16\xd8\x1cx\x02X\x0e<\xb5\xf6?\x8f\x92\xf8=\xc4]d\xf5;I\xdc\xc9\xe3Ż\xe3\xe2X\xed\xb2\xd2\xf0\b'\x90$ut\xac\x9e\x9b\xb6#_>\x90\x14/\a\x0e\x00\xf6\x1b\xe6\xe7\xc7:p;\xf0S\"\xddH\xa5\xf8\xc38?\x1eqy\xc9x\x95$ih\xc1\xda[ޏ\x1a\xef\x04\xde\x00\xec3\xc2?\xbeNb\x80,}\x8bH_\x8a\xbe1wz\x8bHƫ$I\xcf\x0e\xd6\xf3VL \xf2o#8\x0eط\x89.\xdam\xa4\xb8\x86|\xfe\xea\xe8\x8d\a\xbd\xa5$\xe3U\x92ԩ\xc1:7\xe5I巐\xe2T\xe0\xa0&\x7fޫB|\x87\xe0r\xe6\xe5o\f\"y\vJƫ$\xa9\x13\xa2\xb57mO\xb5z\x1c\x91N\x03vi\xc1\xabp7)\xae\xa2\x96\xbf\xcaߏ\x95\x8cWIR\xbbF\xeb\x9c\xf2L\x12g\x11\xbc\x1d(\xb4\xc1UZ\r\xf1m\xea\\\x18\v\n\xff\xcf[X2^%I\xad\x1e\xac\xbdi3j\x95\xb7\x03\xef\x01Jm|U\x17\x03\x8b\xc8\n_\x88\xbeX\xe1-/\xe3U\x92\xa4V\x8aֹ\xab'Q\x8fS\x81w\x01\x9bv\xd0U\x7f\x02\xf8\n)]\x18\xf3\xbb\x96zO\x90\xf1*IR\xb3\x06ko*R/\xbf\x85\x14\xb3\x80C:|\x8e:\xf0C\"-\"\x8a߈\xbe\xa8z\x0f\x91\xf1*IRSD\xebS;R-\x1eCp\x06\xa4\x9d\\\xe4\x1f\x9e\xce\x1f \xea\x9f!+^\x16\xbd\xf1g\xf7\x90\xf1*I\xd2H\a\xebܔQ\xab\x1eD0\v\xd2[\x81\xbc\xab\xbc\xa02ķH,\x8a\xf9\x85\x1b\x9dCƫ$I\x8d\x8e\xd6s\xd2\xe6\x14+G\x02g\x03\x93]d\x83\xddN\xe2\n\xf2\x85\xcfFo,w\x0e\x19\xaf\x92$\rg\xb4\xce)\xcf\x04f\x01G\x03c]d\xd8<\t|\x19\xd2%\xd1\xdf5\xe8\x1c2^%I\xda\xd0`=#u1\xbe\xfcfR\x9c\x05\x1c\xe0\"\r\xb7\x18\xb8\x88\x87\n\xd7Ţ\xa88\x87\x8cWI\x92\x86\x12\xadsW\xedE\x8a\x13Iq\"\xb0\x95\x8b\x8c\xf8-\xf0 \xc1\xd5d\xf5ˢ\xb7\xfb\xf7\xee!\xe3U\x92\xa4\x7f\bֿ\xbe\x01\xab~\x16\xc4\x1b|\x0ej\nuH\xffA\xca\x162?\x7fS\x10\xc9Id\xbcJ\x92:;Z\xcfMۑU\x8f'\xd2)\xc0n.Ҵ\xee\"\xc5g\xc9\xe5?\x13}\xf1\xa8s\xc8x\x95$uV\xb4>\xf3\x06\xacc\x811.\xd22V\x91\xb8\x9e<\x9f\x8e\xde\xe2-\xce!\xe3U\x92Ծ\xc1\xfa\xc14\x8e\xae\xcaQ\xc0i\xc0t\x17iy\x8b\x81E,/\\\x1b\x17\xc4J\xe7\x90\xf1*Ij\x8fh\x9d\xbdj\x1f\xb28a\xed\u05f6\x8ew\x91\xb6\xf38p\r\xa9va\xcc\xef\xfe\x9ds\xc8x\x95$\xb5^\xb0\xf6\xa6\"\xf5\xf2[\xd6\x06\xeb\xc1>\xa7t\x84:\xf0C\"-bi\xf1\xebq}ԜDƫ$\xa9\xb9\xa3\xf5ܴ\x03Y\xf5X\"\x9d\x0eLp\x91\x8e\xf5[R,\xa2\x96\xff\\\x9c\x1f\x7fq\x0e\x19\xaf\x92\xa4\xe6\x8a\xd6\xf3*/'\xe3LHo\x05\xf2.\xa2\xb5VC|\x9bĢ\x98_\xb8\xd19d\xbcJ\x92F/X\xcfI\x9bS\xac\x1c\t\x9c\tLu\x11=\xff\x1d\x86_\x13\\\xc9\xca\xc2\x17\xe3S\xf1\x94\x83\xc8x\x95$\x8dL\x83\xf4\x96\xf7\xa3\xc6\xc9\xc0;\x81M\\D\xeb\xe9I\xe0ː.\x8a\xfe\xae%\xce!\xe3U\x924\xfc\xc1zF\xeab|\xf9\xcdk߀u\x88\x8bh\x98\xfc\x8cH\vy\xb0\xf8\xcdX\x14\x15\xe7\x90\xf1*Iڸh\x9d\xbdjO\xb28\x89\x14\xef\x06\xb6v\x115\xe8\x9e\xf6'\x82k\xa8\xd5.\x8d\x05c\xff\xe0\x1e2^%ICψ\xb9)\xa3V=\x88`\x16\xa4\xb7\x019W\xd1\b\xa9A\xfa\x1e)[\xc8\xfc\xfcMA$'\x91\xf1*Iz\xaeh݂Z\xe58\x82\xb3\x80\xdd]D\xa3\xec\x0eR\xfc;\xd5\xfc\xa2\xf8X<\xe6\x1c2^%Ik\xa2uNy&0\v8\x06\xe8v\x115\x99e\xc0u\xc0e\xd1_\xfc\x8ds\xc8x\x95\xa4N\fֹi\f\xf5\xca\x11$\xdeK0\xc3E\xd4\"\x16\x03\x8bX^\xb86.\x88\x95\xce!\xe3U\x92\xda>ZWM$ŻHq\x12\xb0\xa5\x8b\xa8E=D\xa4\xcf\x13\xf5+\xa2\xaf\xfb^\xe7\x90\xf1*I\xed\x14\xac\x87\xa7\x1c\x93W\x1fJ\xca\xce\x04\x0e\xf6\xf8\xae6R\a~H\xa4E,-~=\xae\x8f\x9a\x93\x18\xaf\x92\xa4V\x8d\xd6\u07b4=\xd5\xeaqD:\r\xd8\xc5E\xd4\xe6\xee&\xc5U\xe4\U0009f37ex\xd89\x8cWIR\xabD\xeb\x9c\xf2L\x12g\x11\xbc\x1d(\xb8\x88:\xccj\x88o\x03\v\xa3\xbf\xf03\xe70^%I\xcd\x18\xac\xbdi3j\x95\xb7\x938\x83`\x9a\x8bH\xc0_\xdf\xe0\x95\x15\xbe\x10}\xb1\xc29\x8cWI\xd2hG\xeb\xecՓ\x898\x05x\x17\xb0\xa9\x8bH\xeb\xf4\x04\xf0\x15\xb2\xb40\xfa\xbans\x0e\xe3U\x924\x92\xc1ڛ\x8a\xd4\xcbo!\xc5,\xe0\x10\x17\x91\x86\xec\x997xE\xf1\x1b\xd1\x17U'1^%I\x8d\x8a\xd6\xf3V\xecD.w\x12)N\x03\xb6q\x11i\xa32\xe7\x01\xa2~-Y\xed\x92\xe8\x1d\xfbG\xf70^%I\xc3\x11\xacsSF\xadz\x10\xc1,Ho\x05\xf2\xae\"\r\xab2ķH,b~\xfe\xa6 \x92\x93\x18\xaf\x92\xa4\xf5\x8f\xd6-\xa8U\x8e#8\x13\xd8\xc3E\xa4\x11q;\x89+\xc8\x17>\x1b\xbd\xb1\xdc9\x8cWI\xd2\vE\xeb\x9c\xf2L`\x16p40\xd6E\xa4Q\xb1\f\xb8\x8e\\\xba4z\xbb\x06\x9c\xc3x\x95$\xfdm\xb0\xceMcH\xe57A\x9cM\xe2e.\"5\x95\xc5\xc0Edq\xc2گm\x1d\xef\"RG{\x1c\xb8\x86\xac\xb60\xfa\xba\x7f\xeb\x1cƫ$5G\xb0\xf6\xa6\"\xf5\xf2[\xd6\x06\xeb\xc1\x1e;%\xfd\x9d\xb5o\xf0J\x8b\x88\xe27\xa2/\xaaNb\xbcJ\xd2(D\xebS;R-\x1eC\xf0\x1eH;\xbb\x88\xa4!\xa4\xd5\xfdD\xfd**\xc5K\xe3\xfc\xf8\x8b{\x18\xaf\x92\xd4\xd8`%\x05\xb3\xab\a\x13̂\xf4V \xef*\x926@\x19\xe2[$\x16\xc5\xfc\u008d\xcea\xbcJ\xd2\xf0FkoڔZ\xe5D\xe04`o\x17\x914\x8cn\x06.!W\xf8B\xf4F\xd99\x8cWI\xda\xf0h\x9d\x9b\xb6&\x95\xdfC\x8a3\x80-]DR\x03=D\xa4+X]\xbc >\x1eO8\x87\xf1*IC\x8f\xd6\xde\x15;SϿ\x9fĉ\xc0&.\"i\x04=B\xa4K\x88\xe2E\xd1\x17\x8f:\x87\xf1*I\xcf\x1d\xad\xb3R\x81m+\xa7\x11\xf4\x03\xe3\\D\xd2(z\x94\xc4<\xee(\\\x12\xd7G\xcd9\x8cWIzv\xb8~\xa4\xf2jR\xba\x04\x98\xe2\x1a\x92\x9a\xc8b\xe0\xf4\xe8/\xfe\xc2)\x8cWI\"\xf5\xa6m\xa9U/\x85t\x98kHjR5\xe0J\xb2\xc2\a\xfc\xd6.\xe3UR'\x87\xeb\x9c\xca+\x81/A\xda\xd15$\xb5\x80\xdbɥ#\xa3\xb7k\xc0)\xd6-s\x02Im\x19\xad\xa4H\xb3+\xe7@\xba\xc9p\x95\xd4B&Q\x8b_\xa4\xd9峜b\xdd<\xf3*\xa9\xfdµ7mK\xad\xf2e\xe0ծ!\xa9\x85_\x85\x7f\x91\\a\x96\xbfF`\xbcJj\xe7c\xfdܕ\xbbQ\xcf\xfd_`\xa2kHj\x03\xbf +\xbc1\xfa\xe2a\xa70^%\xb5[\xb8\xf6\xae\x9eF-\xfb>\xa4\x9d\\CR\x1bYJ\xae\xf6\xba\xe8\xed\xfe\xbdS\xf8;\xaf\x92\xda%\\\xe7T^I-~j\xb8JjC\x93\xa9\xe5\x7f\x9ezW\xf78\x85g^%\xb5C\xb8ή\x1cD\xa4\xef\x02c\\CR\x1b{\x84,\x1d\x18}]\xb7\x19\xaf\x92Ԫ\xe1:gu\t\xe2'\xc0\x16\xae!\xa9\x03\xd2\xed~\xea\xd5\x03bA\xf7}\x9d\xba\x80\xbf6 \xa9u\xc3u\xee\xca=\x80\x1f\x18\xae\x92:\xe8ȷ\x13Y\xee?\xd2ܴ\xa5\xf1*I\xadt\xf8\xfepچz\xee{\x10ۻ\x86\xa4\x0e3\x85T\xf9^z\x7f\xda\xc4x\x95\xa4V\b\u05f9)O\xa1\xf2M\xfc8,I\x1d{ \xe4\x9f\xe8\xae,2^%\xa9%\x0e\xda\xe5\xf9$^\xe6\x10\x92:\xdc;\xd2G\xca\xef\xee\xb4+\xed\x1b\xb6$\xb5V\xb7ή\xbcn\xed'\v\xf8\xe2[\x92`\x15\xf0\x92\xe8/\xfe\xc6x\x95\xa4f\v\xd7s\xd3v\xe4ʷ\xf8{\xae\x92\xf4,w\xb2\xba\xb0\x7f|\"\x96u\u0095\xcd{{KM\x18iS\xa6lI\xa10\x85Zm\"\x11;\x93\xd2vDl\x01\x14ּ\xec\x8c:)=\x0e\x81\x94\x16\x90\xd2\xd6.\xd24\x0e\xa1^\xbf9\xf5\xf4\\N\xf5\x89\x19\x14\xb6p\x11I\x1a\xb1'GN\xa6\x85?\x9a\xd0_\x1bP\xfb>6K\xa5C\x80\v\x81\xa9\xae\xd1Ċ[\xc0\xa4\x13a\x8f#\xf1/\x83$iD\xac\xa0R\xd89>\x16\x8f\xb5\xe2\x85\xf7\x99B\xed\x17\xad3f\xec\x9dJ\xa5\xaf\x02\xffi\xb8\xb6\x80\xf2\xe30\xf0)\xf8\xd1\xd1\xf0ȯ\xddC\x92\x1ao,\xf9ʱ\xadz\xe1=\xf3\xaav\x8a\xd6-\xa8\xd5>\x04\x9c\rt\xb9H\x8b\xda\xfe@\xe8\xf9\x00\x8c\xdd\xd1-$\xa9q\ue8bf\xb0O\x10\xc9x\x95F:Z!\xa3\xa7\xe7hR\xfa\x04\xb0\x9d\x8b\xb4\x81\xac\v\xf6<\n\xf6y\x17\xe47q\x0fIjH\x05\xc6!1\xaf\xd0r\xdflh\xbc\xaa\xb5õTz%\x11\x17\x92\xd2\f\xd7hCc\xb6\x86\xa9g\u0084C=\\I\xd2\xf0g\xe0ע\xbfp\x98\xf1*\x8dD\xb4\xf6\xf4\xec\f|\x94\x94\x8e\xf6~\xdc\x01\xc6O\x85\xd2\xfba\xcb\x1e\xb7\x90\xa4\xe1S%W\xdd=z\xc7\xfe\xb1\x95.\xb4o\xd8RkE\xeb̙cSOO/)\xddIJ\xc7\x18\xae\x1d\xe2\xb1%\xf0\x93w\xc1\xff\x9e\x03+\x1fr\x0fI\x1a\x1eyj\xb9\x93Z\xedB\xfbįֈV\bJ\xa5È\xf8$)\xed\xea\"\x1d,\xd7\r{\x1f\v{\x1f\a9ߗ'I\x1b\xf9\f\xfb \x0f\x15w\x89EQ1^\xa5\xe1zX\x95J3\x89XHJ\a\xb8\x86\x9eֽ\x1dL9\x1d&\xbc\xc1-$i\xe3\x9ei\x8f\x8c\xfe\xae\xaf\x1a\xaf\xd2\xc6>\x94&Oށ|\xbe\x178\x11\x7f\xc5E\xcfe\x9b\x17\xc1\xb4\xf7\xc1\xe6{\xbb\x85$m\x98\x1fG\x7f\xf1\xd5ƫ\xb4\xa1\xd1:uj\x91\\\xeeTR\x9a\al\xe6\"z\xe1#Y\x06\x13^\x0fSφ\xae-\xddC\x92\xd6W.\x95\xa2\xb7\xeb\xd6V\xb8\xa8\x9e\xcdRs\x85kOϛȲ\xa5\xa4t\xa1᪡\xdfq\xea\xf0\xfb\xef\u008d\xff\x1f\xdc\xf5y\xa8W\xdcD\x92\xd6G-Nn\x95\x8b\xea\x99W5G{\x94J\x93\x80\v\x80\u05f9\x866ڦ\xbbB\xe9_a\xbb\x97\xbb\x85$\r\xcd2r\x85\x9d\xa37\x9el\xf6\v\xea\x99W\x8dn\xb4N\x99\xb2e\xea\xe9Y\b\f\x1a\xae\x1a6\xcb\uf0df\x9f\x05?;\r\x9e\xfc\xad{H\xd2\v\x1bG\xad\xf2\x8eV\xb8\xa0\x9ey\xd5\xe8D\xeb\xab^\x95\xe7\x91G\xdeEJ\v\x88\xd8\xdaEԸ\xa3\\\x1e\xf68\x1c&\x9f\x02\xf9M\xddC\x92\x9eے\xe8/N3^\xa5\xbf\x0fמ\x9e\x83I\xe9\x02\xa0\xe4\x1a\x1a1\xc5-`҉\xb0Ǒ\xf8\x97N\x92\xf4\x1c\xea\xf1\x8aXP\xf8i3_D\x8f\xe0\x1a\xb9h\x9d2e\xafT*}\x95\x94n4\\5\xe2ʏ\xc3\xc0\xa7\xe0\xc7\xc7\xc0#7\xbb\x87$\xad\xb3\fө\xcd~\x11=\xf3\xaa\xc6GkO\xcf&\xc0\aH\xe9C\x80_\x89\xa4\xe6\xb0\xfd\x81\xd0\xf3A\x18\xbb\x83[H\xd2\u07fcԧV\xd8%>\x1aM\xfb]ܞyU\xe3\xa2\x15\xb2\xd4\xd3s,)\xddCJs\rW5\x95\a\x7f\xb2棵\x96\\\f\xd5\x15\xee!Ik\x14\xc9U\xdf\xdd\xcc\x17\xd03\xafjL\xb8N\x9f\xfeO\xd4\xeb\v\x81\x97\xb8\x86\x9aޘm`\xea\x190\xe1P\x0f\x8b\x92\x04\xbf\xe7\xf6\xc2\x1eq}ԌWuB\xb4\xeeDJ\xe7\x93\xd2\xd1\u07bf\xd4r\xb6\x98\n\xd3?\x00\xe3\xfd\x95lI\x9d\xfe\x84^\x7fK\xcc\x1f\xf3m\xe3U\xed{\x1f\x9f9s,\xe5\xf2\x19\xc0l\xc0\xcf#R\v\v\xd8\xe5P\x98r&\x8c\xf1S\xdc$u\xec3\xfb\xf7\xa3\xbf\xeb\xf5ƫ\xda\xf3\xee\xdd\xd3\xf3&R\xba\b\xd8\xcd5\xd46rݰ\xf7\xb10\xf1xȊ\xee!\xa9\xe3\x9e\xde\xc9ꓢo̝\xcdv\xc1|Ö6&Z\xf7K\xa5\xd2OH\xe9ۆ\xab\xdaNm%\xdc~%\xfc\xf0\b\xb8\xffF\xf7\x90\xd4i\x82z\x9cԜ\x17LZ\xdfh\x9d4i+\x8aŏ\x90\xd2\xe9@\xceE\xd4\x11\xb6~\x11\xf4\xbc\x1f6\xdb\xcb-$u\x8a\xc7\xc8\n;G_4\xd5G\xb2\x18\xaf\x1az\xb4ΜY\xa0R9\x8d\x94\xfa\x80\xcd]D\x1d'r\xb0\xeb[`\xcaiP\x1c\xef\x1e\x92:\xc1\t\xd1_\xfc\xbc\xf1\xaa\xd6\v\xd7R\xe9\x10\xe0\"`\xb2k\xa8\xe3\x156\x83ɳ`\xf7#\xd6\x04\xad$\xb5\xed\x8bv~\x19\xf3\x8a/6^\xd5:\xd1\xdaӳ\x0f)}\x1a8\xd45\xa4\xbf3n7\x98\xf6\xaf\xb0\xdd\x01n!\xa9}\xd5yQ,(\xfe\xcaxUsGk\xa94\x1e8\ax/\xe0[\xad\xa5\xe7\xb3\xfd\x81Pz\x1fl\xb2\xb3[HjG\x9f\x8b\xfeb\xd3|\xeb\x96\xf1\xaagG+d\xf4\xf4\x1cMJ\x9f\x02\xb6q\x11i\xa8G\xd3<\xecq8L:\x05\n~Ա\xa4\xb6\xb2r\xed\x1b\xb7\x1em\x86\v\xe3Ge\xe9\x99p\xed\xe99\x88R\xe9fR\xba\xdap\x95\xd6\xf7\x01T\x85{\xae\x83\x9b\x0e\x83{\xbf\x0e\xd4\xddDR\xbb\xe8\xa6^=\xbei\xce\x15x{(M\x9b\xb6'\x11\xe7\x03\x87\xbb\x864L\xb6\x98\xbc棵\xb6\x9c\xe1\x16\x92\xda\xc1=d\x85\x89\xd1\x17\xa3\xfe\xca\xdcx\xed\xe4h\xed\xe9\xd9\x04\xf8\x00)\x9d\x03\x8cq\x11\xa9\x01\x87؝\x0e\x86\xa9g\xc3\xd8\x1d\x9cCR\x8b\x87C\xbc6\xe6\x17~0\xda\x17\xc3_\x1b\xe8\xc4\xfb\x1eD\xea\xe99\x96\x94\xee&\xa5\xb9\x86\xab\xd4\xc0G\xdb\xfd7\xae\xf9U\x82%\x17Cu\x85\x93Hj\xe5\xd7\xe3\xa75\xc9i\x01u\xd4S\xe9ԩ3Ȳ+\x80\x17\xbb\x864\xc2\xc6\xee\b\xd3?\xe4GkIjU5\xb2\xda^\xd1\xd7}\xefh^\bϼvJ\xb4ΜYH\xa5\xd2\xf9d\xd9\xff\x1a\xae\xd2(Y\xf1\x00\xfc\xfcL\xf8չPY\xe6\x1e\x92ZM\x8e\x94\x9d8\xda\x17\xc23\xaf\x9d\x10\xaekސu\x1d\xf0\"א\x9a\xc4\xd8\x1d`\xff\x05\xb0\xe5t\xb7\x90\xd4J\xfe\xc2\xe3\x85\tqq\xac\x1e\xad\v\xe0\x99\xd7v\x0f\xd7R\xe9@\"~n\xb8JMfş\xe0\xa7'ý\xdft\vI\xadd\x1bƗ\xdf6\x9a\x17\xc0xm\xe7p\xed\xe99\x0e\xb8\t?\xb3UjN\xf5\n\xdc\xd2\x0f\xb7]\xea\x16\x92Z(0\xe2\xd4\xd1\xfc\xf1\xfe\xda@\xbbޯJ\xa5Ӂ\x8b\xbd\x8d\xa5\x16\xb1\xfb\xe10\xfd\x1c\x1f\xb2\x92ZC.M\x8fޮ\x81\xd1\xf8ўym\xc7p\x9d6\xedH\xe0\"\x9f\x05\xa5\x16\xf2\xbb\xeb\xe1\xb6\xcb\xddARk\xa8\xc7)\xa3\xf5\xa3\x8d\x9bv\v\xd7R\xe9@\xe0\a@\x97kH-h\xfa\x87֜\x85\x95\xa4涜\\a\xa7\xe8\x8d'G\xfa\a{浝\xc2uڴ\xc9\xc07\rW\xa9\x85\xfd\xe6\x13\xf0\xe0O\xdcAR\xb3۔j\xe5\x98\xd1\xf8\xc1\xc6k\xbb\x84\xeb̙\x9b\x13\xf1]`\xbckH\xad\xac\x0e\xbf\x9a\r\xcb\xeeu\nI\xcd-8=\x91F\xfco\xf1\x8d\xd7vQ._\x06\xec\xee\x10R\x1b\xa8>\x05\x8b\xcf[\xf3i\x04\x92Լ&3\xa7z\xa0\xf1\xaa\xf5\x96J\xa5Áw\xb8\x84\xd4F\x1e\xbf\x1d\xee\xb8\xca\x1d$5y\x84\xa4\x11\xff\xd8,߰\xd5\xea\xf7\x99\xbd\xf6ڌ\xee\xeeۀ\x9d\\Cj3Y\x01^\xf5%\xd8l\x0f\xb7\x90Ԭ*\xe4*\xbbE\xef&\x0f\x8cء\xd1\xcd[\\w\xf7\x87\rW\xa9M\xd5+\xb0\xe4Bw\x90\xd4\xcc\nT\x8b\xef\x1e\xd1\xd7\xf5n\u07baҤI[\x01\xa7\xbb\x84\xd4\xc6\x1e\xfa\x19<\xbe\xc4\x1d$5\xaf\xe0\x944+\x15\x8cW\xbd\xb0b\xf1}\xc08\x87\x90\xda\xdc\xed\x9fq\x03IM,\xed\xc8\xf6\xe57\x8e\xd4O\xcb;\xf8\xb3}\x15r\xb7\x15\x98\x1eP\x8a`\x0f\x12\xdb\x06t%\xa8$X\x96\xc1}\xf5ĝ\xc5*\xbf\xfc0<6jw\x93)S\xb6$\xa5\xf7x\x8bI\x1d\xe0\xc1\xff\x86\xc7o\x83-\xa6\xb8\x85\xa4&\xed\xd78\x15\xf8\xc6H\xfc(߰\x05\\\x04]\x8f\x15yc\xd4y\a\xc1k\x18\xda\xd9\xccz\xc0-)q}\xbd\xc0\x97zW\xf2\xfb\x11\xbd\x8f\x94J\xb3\x81~o=\xa9C\xec\xfcϰ\xff\xf9\xee \xa9i\xf3\x95T\x9f\x1c\xf3\xc7\xdca\xbc6\xd0'a\x93Uyޓ2\xce\"\xb1\xc3F\xfcQU\xe0\xffԃ\x05\xbdenm\xfc\xbd\x83\xa0T\xba\v\xd8\xd3NJ\xd4!\xb2\x02\xbc\xee\xfbP\xdc\xc2-$5\xa7\xe0\x82\x98W\xfcW\xe3\xb5A\xfa\x8b\xbc-%.\x04&\f\xe3\x1f[Mpy\xaa0\xbb\x17\x1a\xf6]\xbf\xa9\xa7\xe7\x15\xa4\xe4\xf7GJ\x9dfƇa\xb7\xc3\xdcAR\xb3z\x9c\x95\x85\x9d\xe3S\xf1TC_\xcbwڪ\x9f\x86\xeey\x05\x16\xa6\xc4׆9\\\x01\xf2\x01gd\x05\x06\xe6\xe5yiîDJ\xff\xe2\xe3C\xea@\x0f\xfc\xd8\r$5\xb3-\x18[y{\xa3\x7fHG\xc5\xebGa\xabe\x05~\b\x9c\xd9\xe0\x1f\xb5+\xc1\x8f\xfa\x8a\x1c٠?\xff\x8d>>\xa4\x0e\xf4卿\xdc\x1d$5\xaf:\r\x7f3y\xc7\xc4\xeb\xfcn&T\v\xfc<\xe0%#\xf4#\xbb\"\xf1\xa5y\x05f\r\xe7\x1f\x9a\xa6O\xdf\t\x98\xe8\xa3C\xea\xc4'\x85\n<\xfa\x1bw\x90Լ\x82\x19iN\xf9\xc5\xc6\xeb0\x84k\xbdʏ\x80\xbdG\xf8Gg\xc0\x15\xfd\x85a\xfc\"\x81\x94\x0e\xf4\x91!u\xb0G\x8cWIM.q\xaa\xf1:<\xe1:Z\xef̏\x04\x17\x0fc\xc0\xee\xe7\xa3B\xea`\x8f/u\x03I\xcd-x{\xfap\xda\xc6xm\xcdp\x1d\xfe\x80Mi\xaa\x8f\n\xa9\x83-\xbb\xc7\r$5\xbb.r\xd5\xe3\x8d\xd7\xd6\r\xd7\xe1\x0eX\x7f\xdfU\xead+\xff\f\xb5\x95\xee \xa9\xb9E:%\xcdM\r\xe9̶\x8c\xd7&\f\xd7\xe1\f\xd8\x1d}DH\x9d,\xc1\xaa\x87\x9dAR\xb3ۃT{\xad\xf1\xda\xda\xe1\xba\xd1\x01\x9bf\xcc\xd8\x02\xe8\xf6\xf1 u\xb8U\x7fq\x03I-\xf0Z\xbbv\x9a\xf1\xda\xfa\xe1\xbaq\x01[\xad\x8e\xf3\x91 \x89\xea\n7\x90\xd4\x02\xe2\xd04{\xe5\xee\xc6k\xeb\x87\xeb\x86\al>?\xc6\a\x82$je7\x90\xd4\n2\"\x9b5\xfc\x7f\xa8\xe1\xda:\x01[\xad\xe6}\x1cH\xa2^q\x03I\xad\x92:'\xa6\xb9iXO\xbe\xb5|\xbc\xb6p\xb8nX\xc0J\x92$\xb5\x8e\xad\xa9\x97\x0f3^\xdb'\\\rXI\x92\xd4\xde\"\x86\xf5\x1b\xb7Z6^\xdb(\\\rXI\x92Ծ\x12/K\xbd\xe5a\xfb\x86Ж\x8c\xd76\fW\x03V\x92$\xb5\xaf\x1a'wl\xbc\xb6q\xb8\x1a\xb0\x92$\xa9]\x1d\x9d>\x94\xc6w\\\xbcv@\xb8\x1a\xb0\x92$\xa9\x1d\x8d\xa5P9\xa6\xa3ⵃ\xc2Հ\x95$I\xed\xe8\xd4D\x8a\x8e\x88\xd7\x0e\fW\x03V\x92$\xb5\x9bI̮\xbe\xba\xed㵃\xc3Հ\x95$ImV5l\xf4\xc7f5u\xbc\x1a\xae\xcf\x0e\xd8\xcf\xdc{\xf7;\xbc\xd7K\x92\xa4֕\xfe%\x9d\xb7b\xa7\xb6\x8cW\xc3\xf5\x1f\x03\xf6\xc1ի\xce\xfb\xd5c\x8f\xb8\x84$IjUyr\xb9\x93\xda.^\r\xd7\xe7\x0e\xd8\xef=\xf4\x00\x06\xac$IjY\x89YiV*\xb4M\xbc\x1a\xae/̀\x95$I\xad+v`\xdb\xf2[\xda\"^\rW\x03V\x92$uB\xbf\xc6\x06\xbfq\xabi\xe2\xd5p5`%IR\xc78(\xcdY=\xb5e\xe3\xd5p5`%IR\xa7\x89Y-\x19\xaf\x86\xab\x01+I\x92:\xd2\t\xe9\x83i\\Kū\xe1j\xc0J\x92\xa4\x8e5\x8e\xae\xcaQ-\x13\xaf\x86\xab\x01+I\x92:\xdei-\x11\xaf\x86\xab\x01+I\x92\x04LO\xe7U^\xd6\xd4\xf1j\xb8\x1a\xb0\x92$I\xcf\xd4hZ\xaf\x8f\xcd\x1a\xd1x5\\\rXI\x92\xa4\xbfsD\xeaM\xdb6]\xbc\x1a\xae\x06\xac$I\xd2:\x14\xa9U\xdf\xd5T\xf1j\xb8\x1a\xb0\x92$I\xcf-\x9d\x9a\x0eO\xb9\xa6\x88W\xc3Հ\x95$Iz\x01\xbb0y\xf5\xa1\xa3\x1e\xaf\x86\xab\x01+I\x924$)\x86\xf4ƭ\x86ū\xe1j\xc0J\x92$\r]\xbc.\xcd^\xb5\xf7\xa8ī\xe1j\xc0J\x92$\xado\xbd\x92\xc5I#\x1e\xaf\x86\xab\x01+I\x92\xb4AR\xbc+\xcdMcF,^\rW\x03V\x92$i#lE\xaa\x1c9\"\xf1j\xb8\x1a\xb0\x92$I\x1b-qj\xc3\xe3\xd5p5`%I\x92\x86ɋ\xd3y\xe5\xfd\x1b\x16\xaf\x86\xab\x01+I\x924\xac\x82S\x1a\x12\xaf\x86\xab\x01+I\x92Ԁx}G\x9a\x9b\xb6\x1c\xd6x5\\\rXI\x92\xa4\x06\xe9\xa6V9n\xd8\xe2\xd5p5`%I\x92\x1a*8-\xcdM\xd9Fǫ\xe1j\xc0J\x92$\x8d\x80\xbdHՃ7*^\rW\x03V\x92$iĬ\xe3c\xb3\x86\x1c\xaf\x86\xab\x01+I\x924\xc2\xf5\xfa\xa6ԛ\xb6]\xefx5\\\rXI\x92\xa4Q\x90\xa7\xfa\xeco\xdcz\xc1x5\\e\xc0J\x92\xa4Q\x13\xbcs\xc8\xf1j\xb8ʀ\x95$I\xa3\xec\xc5i\xf6\xaa}^0^\rW\x19\xb0\x92$\xa9)dq\xd4\xf3\xc6k\xefXv\xacW\xf9\xb1\xe1\xaau\x05\xec\xcdO<\xe6\x10\x92$i\xe4\xd4\xe3-\xcf\x19\xaf\x1f\x83\xcds\x15\xbe\v\xec\xe1RZ\x97\xef>x?\xb7/\x7f\xd2!$I\xd2\xc8\bz҇\xd3V\xff\x10\xaf\t\xa2\\\xe4K\tf\xb8\x92\x9eKJ\x89o>\xf0\a\x1e.\xafv\fI\x924\x122\n\xe5\x97\xffC\xbc\xce/p6\x89C\xddG/\xa4R\xaf\xf3\xb5\xfb\x7fO-%ǐ$I# ^\xf9\xacx\x9d\xdf̈́\x04\xfd\x0e\xa3\xa1\xfa\xf3\xeaU\xfcϣ\x0f;\x84$Ij\xbcī\x9e\x15\xaf\xa9\xcaǁM\\F\xeb\xe3\xbf\x1f\xf93˫U\x87\x90$I\x8d6=\xbd7ug\x00s\xbb\xd8#\xc1\x11n\xa2\xf5U\xa9\xd7\xf9\xe5c\x9e}\x95$I\r\x97\xb1yy\xcf\f \xab\xf3\x1e \xe7&\xda\x10\x8b\x1f\x7f\x94\xaa\xbf\xfb*I\x92\x1a\xad\xca\xc4l.d\x918\xd25\xb4\xa1V\xd5j\xdc\xfd\xd42\x87\x90$I\x8d\x15\xd9Ĭ\x90\xe7e\x04;\xba\x866\xc6\x1d\xcb\xfc\xdcWI\x92\xd4hi\xef,\xc1+\x1dB\x1b\xebާ\x96;\x82$Ij\xb4ݳ\x043\xddA\x1b\xeb\xc9j\x85\x15~\xea\x80$Ij\xacͲ\b\xf6v\a\r\x87G+eG\x90$I\x8d\xb4i\x96\xf0\xf7]5<\x9e\xacV\x1cA\x92$5P\x8cˀq\x0e\xa1\xe1P\xae\xd7\x1dA\x92$5P\xda4\x03\xc2!4,w'?\xebU\x92$5\xd6&\x19\xe0\xdb\xc45,\xbar~υ$Ij\xa8\x95\x19\xf0\xa0;hX^\n\xe5\xf2\x8e I\x92\x1a(-\xcb\b\xeev\b\r\x87-\x8bEG\x90$I\r\x14˳\x047;\x846\xd6&\xf9<\xe3\xf2\x05\x87\x90$I\x8d\x93X\x96eu~\xe2\x12\xdaX\xbbvo\xe2\b\x92$\xa9\xb1\x82eY\xad\xcaO\x80G]C\x1bc\xe2\xb8\xcd\x1cA\x92$5\xda}Y/\x94\x81\xaf\xbb\x856T>\xcb\xd8gS\xe3U\x92$5Zܕ\x01ԃ\x8b\x01?\xa4S\x1bd\xc6\xe6\xe3)f\x99CH\x92\xa4\x06\xabߙ\x01\xf4\x96\x19 \xf8\xbe\x83h}e\x11\xbcd˭\x1dB\x92$5^.\xee|\xfatY\r\xde\x0f\xf8\xe5\xf4Z/\xff4~+\xc6\x17\xfc\x88,I\x92\xd4p\t\nw?\x1d\xaf}enK\xc1\xa7\xddEC\xb5y\xbe\xc0\x81[o\xe7\x10\x92$i$\xdc\x1e\xbd\xb1\xfcY\xbf\xa8\xb8}\x999\xc0\xcf\xddF/$\x8b\xe0\xad;N\xa0\xcb\xdfu\x95$I#!\xf81\xc0\xb3\xca\xe3d\xa8\xd4\xf3\xbc\x9d\xc4\x1f]H\xcf\xe7\xb5\xdb\xee\xc0\x84\xb1~\xb6\xab$I\x1a)\xe9\xbf\xfe!^\x01zW\xf2\xfbz\xc6\xeb\xf1\xb3_\xf5\x1c^\xbe\xf5\xb6\xec?~+\x87\x90$I#V\xaed\xc5u\xc7+@o\x99[\xebp0\xf0\x88[\xe9o\xbdd˭y\xb5\xbf\xe7*I\x92F\xd6\xed\xd1\x1b\x0f>g\xbc\x02\xf4V\xb8\xa5\x0e\x87\x18\xb0\xfa\xdbp}Ͷ;8\x84$I\x1aa\xe9\xbb\x7f\xfd\xbf\x9e\xf7\xdd6\x06\xac\fWI\x924\xear\xf1\xc5!ū\x01+\xc3U\x92$\x8d\xb2\xa5\xd1[\xbce\xc8\xf1j\xc0\x1a\xae\x86\xab$I\x1a5)\xae\xfd\xdb\xff:\xe4\x0f\xe94`\rWI\x92\xa4\x91NWr\xd5\xeb6(^\rX\xc3U\x92$i\x84\xfd0\xfa\xba\xef\xdd\xe0x5`\rWI\x92\xa4\x11\x93\xd2e\x7f\xff\xffڠ\xef\xf64`\rWI\x92\xa4Ɗ\a\xf8s\xf1;\xc3\x12\xaf\x06\xac\xe1*I\x92\xd4`WƢ\xa8\f[\xbc\x1a\xb0\x86\xab$IR\x83T\xa9W>\xbb\xae\xff!\xdb\xd8?ـ5\\%I\x92\x86\xd9\xd7c\xc1\xd8\xfb\x1b\x12\xaf\x06\xac\xe1*I\x924\xbc\xe2\xb2\xe7\xfa_\xb2\xe1\xfa\x11\x06\xac\xe1*I\x924\f\x96ҟ\xffI\xc3\xe3Հ5\\%I\x926Z\xe2\xd2 ҈ī\x01k\xb8J\x92$m\x84\xe5\xe4\v\xd7>\xdf?\x905\xe2\xa7\x1a\xb0\x86\xab$I\xd2z\v\xae\x8d\xdexr\xc4\xe3Հ5\\%I\x92\xd6[\x96\xaex\xc1\x7f\xa4\x91?߀5\\%I\x92\x86迣\xb7k`T\xe3Հ5\\%I\x92\x86$\xd2\xe5C\xf9Dz\x91\xb8,\x06\xac\xe1*I\x92\xf4<\xfe\xc2ců7M\xbc\x1a\xb0\x86\xab$I\xd2s\x8a\xb4(.\x8e\xd5M\x15\xaf\x06\xac\xe1*I\x92\xb4\x0e5\xa2~\xd5P\xff\xe1l\xa4/\x9d\x01k\xb8Jr\xca+\xc3\x00\x00\x19\x80IDAT\x92$=#n\x88\xbe\xee{\x9b6^\rX\xc3U\x92$\xe9\x99v\xe5\xf2\xf5\xf9dzѺ\x9c\x06\xac\xe1*I\x92:\xde=D\xfe?[\"^\rX\xc3U\x92$u\xb8\x14\x97G_\xd4[&^\rX\xc3U\x92$u\xac\x95\xd4\xf2\x9f_\xdf\x7f)k\x86Kn\xc0\x1a\xae\x92$\xa9\xc3$\xbe\x1c\xe7\xc7z\xb7_\xd6,\x97߀5\\%IR\aY\xcf7j5]\xbc\x1a\xb0\x86\xab$I\xea\x187G\x7f\xf1\x7f[>^\rX\xc3U\x92$u\x80\xe0\xe2\r\xfdW\xb3f\xbc>\x06\xac\xe1*I\x92\xda\xd6\xe3D\xe1+m\x15\xaf\x06\xec\xbamV(|\xdep\x95$I--\xf8l\xf4Ŋ\xb6\x8bW\x03\xf6\x1f|\xfa\xac\x89S?\xea\f\x92\xc8\xf2n \xa9U%\xa2\xbeh\xa3\x0e\x81\xcd~\r\r\xd85\xe1\xfa\x91\n\xef\xa3Z]\xe5}^\x12Y\xd1\r$\xb5j\xbb\xfe \xfa\xc6\xdc\xd9\xd6\xf1j\xc0\xae\rW\x80\x88\xe5\xde\xe9%\x91\x1f\xeb\x06\x92Z\xd3\x06~\\\x7fT\xd6\xca;\xb4Y\xc0\x0e%\\\xa1Z\xfd\xa9\x8f\x00\xa9\x83m9\xdd\r$\xb5\x9a%\xb1\xa00l\xfd\x92\xb5\xfa\x1am\x12\xb0C\vW \x96.\xbd\x0f\xf8\xad\x8f\x03\xa9\x03E\x1e\xb6\x9a\xe1\x0e\x92Z\xcd%\xc3\xf9\x87e\xed\xb0H\x8b\a\xec\x90\xc3\xf5i)}\xc7ǁԁ\xb6\xde\x0f\n\xe3\xdcAR+YF\xae\xf0%\xe3\xb5}\x02v\xfd\xc3uM\xbc~\xcbǂԁvx\xa5\x1bHj5WGo\x1e\xa4\x0e\x92\x15`\xe7\u05fa\x83\xa4֒KW\x0e\xfb\xe1\xb0\xdd6j\x91\x80\xdd\xf0p\x05\x02\x12p\xad\x8f\b\xa9\x83l\xff\n(\x8ew\aI\xad\xe4\xc7\xd1\xdbu\xab\xf1\xda\xfa\x01\xbbQ\xe1\xfa\xb4b\xf1b`\xb9\x8f\v\xa9C\xec\xf9N7\x90\xd4b\xd2\xe5\x8d\xf8S\xb3v\x9d\xabI\x03vx\xc2\x15\x88ŋ\x1f&\xe2J\x1f\x18R\a\xd8\xf6\xa5~ʀ\xa4V\v\xd7\ay\xa8\xf8\r㵵\x03v\xd8\xc2\xf5i\xf5\xfa'\x81\x15>@\xa46\xb7ϻ\xdd@R\xabY\x14\x8b\xa2b\xbc\xb6n\xc0\x0e\x7f\xb8\x02q\xeb\xad\x0f\x01\x9e}\x95\xda\xd9\xd6/\x82\xad\xf6u\aI\xad\xa4J\xae\xf6\x99F\xfd\xe1Y',\xb86`\xffyT\x026\xf8D#\xc2\xf5i\xb5\xda|\xe0\xcf>N\xa46\x149(\xbd\xd7\x1d$\xb5\xda\xc1\xeb\xdb\xd1;\xf6\x8f\xc6\xeb\xc6\a\xec\xaf#x\x05\xf0\xfb\x11\xfa\x91)\x05}\x1f)sNC\xef\x1e\xb7\xdd\xf6()\xbd\xdf\a\x8aԆ\xf6|'l\xbe\x8f;Hj-\x89\xcb\x1b\xf9\xc7G\xa7\xed\xb9\x00v\xa8\x15\xf8\x02pP\x03\x7f\xccc\x11\xbckN\x99o\x8e\xd8\xfd\xa4T\xfa\np\x84\x8f\x18\xa9Ml\xb6\a\xbc\xea\v\x90u\xb9\x85\xa4Vr7\xfd\x85\x89A\xa4F\xfd\x80\xac\xd3\x16=\x0f\xfeT\xab\xf0\x1a\x12\x1f\xa0\x11\x1f5\x15\xdcP\xcf3c$\xc3\x15\x80J\xe54\xe0\x8f>f\xa46\x90u\xc1\xfe\xe7\x1b\xae\x92Zѥ\x8d\f\xd75\xa9\xd5\xc1zDzcT\xf8H\xc0q\xc0\x98\x8d\xfc\xe3~\x91\xea\xf4ͭ\xf1\xbdѺ>\xa9\xa7g?R\xfao`\xac\x8f\x1d\xa9U\x05\xec?\x1fv~\x9dSHj5+\xc9\n;G_o\xeb}\x04\xf8Z\x96\xb8vv\x95\x9f6\xc3uI\xa5\xd2;\x80/x\xdbJ-j\xe2\xbba\xcai\xee \xa9\x15]\x15\xfdœF\xe0%\xbe\xfe\xd6\x02خZ\xe4\xe5@)\x12{\x12lCb,\xb0\x9aē)\xb8/\xe0N\xe0\xe7\xb5\n\x83}Po\xb6\xeb\x90J\xa5ӁK\xbc5\xa5\x16\xb3\xcb\x1ba\xbf^\x0f͒Z\xd5\xfe\xd1_\\l\xbcjC\x03\xf6\x1c\xe0c.!\xb5R\xb8Υ\x03ߊ \xa9\x1d\x04\xff\x13\xf3\x8a/\x1d\x89\x1f\xe5Q\xb2]\xefC\x83\x83\x1f'\xe2t\x9a\xf0̰\xa4\xbf\xb3\xe7QkϸzH\x96Ԣ\x1a\xfc\xf1X\xc6k\xa7\x04\xec\xc0\xc0e\xc0\x1b\x81'\\CjF\x19L=\x03J\xefǿ\b\x93\xd4\xc2\x1e!+|\xd5x\xd5\xf0\x04\xec\xe0\xe0\xf7\xa8\xd7_\x06,q\r\xa9\x89\x8c\xd9\x1a\x0e\xb8\x04\xf6>\xde-$\xb5\xb8\xf4\xd9\xe8\x8bUƫ\x86/`\x97,\xb9\x8dM7}\x11p)\x90\\D\x1ae\xdb\x1f\b\xaf\xbe\x0e\xb6y\xb1[Hj\xf9r%\xa5\xabF\xb4kܼ\xc3\xeeaS\xa7\x1e@\x96]\x01Ls\ri\x84\x8d\xd9\x1a\xa6\x9e\t\x13\xde\xe0\x16\x92ڥ,\xfe#\xfa\xbbF\xf4\xa0\xe6\x99\xd7\x0e\x13K\x96\xfc\x8c\xad\xb6\xda\x178\x99\x94\x1ev\x11i$\x1ex\xf95o\xca:\xe4k\x86\xab\xa46k\xd7\xdc\xe5#\xfd#=\xf3\xda\xc9\xf7\xb7)S\xb6$\x9f\x9fKJ\xa7\x01y\x17\x91\x1a`\x9b\x17\xafyC\xd6f{\xb8\x85\xa4vs\x1f\xb7\x17\xf6\x8c\xeb\xa3f\xbcjd#\xb6T\x9a\x04\\\x00\xf8}\x94\xd2p\xd9t\x17\x98\xf6\xaf\xb0\xfd+\xdcBR\x9b\x06D|(\xe6\x17>>\xd2?\xd6x\xd53\xf7\xc1\x9e\x9e7\x91҅\x80\xa7\x88\xa4\rU\x18\a\x13\x8f\x87=\xdf\tY\xc1=$\xb5\xab\xd5\xe4\n\xbbDo\xfc\xd9x\xd5\xe8\x06\xecԩEr\xb9SIi\x1e\xb0\x99\x8bHC=\x9af0\xe1\xf50\xf5l\xe8\xda\xd2=$\xb5y0pm\xcc/\x1e;*\x87[\xd7\xd7:\uf4d3'\xef@>\xdf\v\x9c\x88o쓞\xdf6/\x82i\xef\x83\xcd\xf7v\vI\x9d\xf2\x8a\xfde\xd1_\xf8\xb9\xf1\xaa\xe6\x8b\xd8i\xd3\xf6'\xcb.$\xa5\x03\\C\xfa;\xdd\xdb\xc1\x94\xd3\xfd\x04\x01I\x9d\xe67\xd1_\x9c1Z?\xdcw\x98\xeb\xf9_\xdd\xdcz\xeb\xaf\x12\xbc\x82R\xe90\xe0S\xc0.\xae\xa2\x8e\x97놽\x8f\x85\xbd\x8f\x83\\\x97{H\xea\xb08\xe0\xd2\xd1\xfd\xf1\xd2\x10\xa5\x993\xc7R\xa9|\x90\x94\xce\x01Ƹ\x88:\xf1\x88\xcdN\a\xc3\xd4\xf7\xc2\xd8\xed\x9dCR'z\x82\x95\x85\x9d\xe2S\xf1\x94\xf1\xaa։\xd8i\xd3&\x90e\vH\xe9h\xefC\xea\x18[L\x81\x9e\xf7Ö\xd3\xddBR'\xbf\x86_\x18\xf3\x8ag\x8f\xeeE\x906\xe9\xa7˛\xa4=\xa4ᓦO\x9fHJ\xffFJot\r\xb5\x9cq\xbbC\xe9}\xb0\xedK\xddB\x92\x9e\xfd\f\xff'\x1e*\xee\x1a\x8b\xa2b\xbc\xaa=\xef\xe2\xa5\xd2!\xc0\x85\xc0T\xd7P\xd3+n\x0e\x93N\x82=\x8eĿ\x90\x92\xa4u=\xb1Go\xcc/\xf45\xc3E\xf1(\xadƼ*\x1a\x1c\xbc\x91bq_\"\xce\x06\x9ep\x115\xe7\x1d5\x0f\xbb\xbd\r\x0e\xf9:\xecq\x94\x87DIZ\xb7*\xa9rU\xd3\x1c\xba\xbd=\xd4\xf0\x17k\x93&mE\xb1\xf8\x11R:\x1dȹ\x88\x9a\xc26/^\xf3\xd1W\xe3\xf6p\vIz\xfe\\\xbc>\xfa\vG\x18\xaf꼈\x9d>}_\xea\xf5\v\x81\x03]C\xa3f\x93\t0\xe5=\xb0\xd3!n!IC\xaa\xc58(\xe6\x15~d\xbc\xaas#\xb6\xa7\xe7M\xa4\xb4\x10\xd8\xdd54b\n\xe3`\xe2\xf1\xb0\xe7; +\xba\x87$\r\xcdR\xfa\vS\x83H\xcdr\x81\xfc\x05/\x8d\xfc+\xa6\x81\x81\xef\xb0\xe9\xa6S\x81\x0f\x01\xcb\\D\x8d\xbd\xc3e\xb0\xcb\x1b\xe0\x90\xaf\xc1\xde\xc7\x1b\xae\x92\xb4>\x12\x977S\xb8\x82g^5ڏ\x89}\xf7ݑZ\xedc~լ\x1ab\xeb\x990\xed}\xb0\xc5>n!I\xebo9\xe5\xc2\xce\xf1\xf1h\xaa7^\x1b\vj\x8e\x88\x9d:\xf5Ed\xd9B\xc0\x0f\xd8\xd4\xc6\xeb\xdev\xcd\xef\xb5N8\xd4Ü$mx%^\x19\xf3\x8a\xa74\xdfŒ\x9a%`!(\x95\x0e\x03\xfe\r\x98\xe0\"Zo\xb91\xb0\xf7q0\xf18Ⱥ\xdcC\x926\xea\x98\xca\xcc\xe8-\xfe\xdax\x95^(b{z6\x01>@J\xe7\x00c\\DC:\x94\xedt0L=\x1b\xc6\xee\xe0\x1c\x92\xb4\xf1~\x16\xfdŗ7\xe9\x11_j҈\x9d6m\x02Y\xb6\x80\x94\x8eq\r=\xa7-&\xaf\xf9\xbc\xd6-g\xb8\x85$\r[!\xa6\xa3c^\xd7\x17\x8dWiC\"v\xea\xd4W\x93e\x17\x02=\xae\xa1\xa7\x8d\xd9\x06&͂]\xffe\xcd'\nH\x92\x86\xcb\xc3d\x85\t\xd1\x17\xab\x8cWiC\x03\x162zz\x8e&\xa5O\x01۸H'\x9f\r\xc8\xc3\x1e\x87äS\xa0\xb0\xa9{HҰ\x1fg\xd3\xf91\xaf\xebܦ\xbdx\xdeBj\xa9\x88-\x95\xc6\x03\xe7\x00\xef\x05\xfc\xc0\xceN\xb3\xfd\x81Pz\x1fl\xb2\xb3[HRc\xd4I\xb5\xbdb~\xf7\xef\x8cWi8#\xb6\xa7g\x1fR\xfa4p\xa8kt\x80q\xbb\xad\x89\xd6m_\xe6\x16\x92\xd4\xd84\xfcN\xf4\x17\xde\xdcԗ\xd0\x1bI-\x1d\xb1\xa5\xd2!\xc0B`\x8ak\xb4\xa1\xe2\xe60\xe9$\xd8\xfd\b\x88\x9c{HRßX\xe3\xf51\xbf\xf0\xfdf\xbe\x88\xbe\xcbA\xad\xfd\xfapp\xf0F\x8a\xc5\x19D\x9c\r<\xe1\"\xedr\xc3\xe6`\xb7\xb7\xad\xf9J\xd7=\x8e2\\%id\xdcC.\xff\x83\xa6\x7f\x8a\xf0vRۼX\x9c4i+\x8aŏ\x90\xd2逵Ӫ\xb6\xf9\xa75\xbf\"\xb0\xd9^n!I#\x9b\x85\x1f\x88\xfe§\x8cWi\xa4#\xb6\xa7g?R\xba\x10x\x85k\xb4\x90M'\xc0\xe4\xf7\xc0N\x87\xb8\x85$\x8d\xbc\xd5T\v\x13\xe2\xfc\xf8\x8b\xf1*\x8d^ľ\x89\x94.\x02vs\x8d&\x96놽\x8f\x85\x89\xc7C\xe6\aHH\xd2(\xf9|\xf4\x17Oh\x85\v\xeaJm\xc5\xc0\xc0w\xd8t\xd3)\xc0\x87\x80\xe5.҄\xaf\x9dwy\x03\xbc\xe6\x9bk\xbel\xc0p\x95\xa4\xd1S\xe7\xf2\x16z\xf6\x90\xda_\x9a>}'R:\x9f\x94\x8e\xf6~\xdf\x04\xb6\x98\n\xd3?\x00\xe3Kn!I\xa3\xef\xe6\xe8/\xee\xd7*\x17\xd63\xaf\xea\b\xf1\x9b\xdf\xdc\x1f\x03\x03ǒe/\x01\xfe\xc7EF\xcd\xfd\xecs\xfc\xb7y\xd5Ն\xab$5\x8fKZ\xe9\xc2\x1a\xaf괈\xfd%\x83\x83/#\xe28\xe0A\x17\x191+\x80\x8fS\xafOb\x9fS\xdf\x03Qs\x12Ij\n\x8f\x93\x15\xbel\xbcJ\xcd\x1c\xb0\x90b`\xe0\x1a\"\xf6\"\xa2\x0fX\xed*\x8d\x1cW\xb8\xaey\xd5\x1c\x89\x14\x8b\x9cL\x92F\xb3][\xf3o\xc1<\xf3*\xad\xeb\xf1\x1a\x7f2^%iT\x8fT\x85\x0f\x03\x0f;\x84$=\xaf\xdbx(\xbf\xb0\xed\x9f\x12\xbc\x9d%5\xbb\xe8\x8bG\x81\xf3\\B\x92\x9eG\x8a3bQT\x8cWIj\x8a\xa3U\xe1*\x82_:\x84$\xad+\\\xb9.\xe6\x17~\xd8\x11O\a\xdeڒZA\xf4E\x9dz\xfdh\xe0Iא\xa4g\x1d!\xffH\xaepf\xa7\\[\xe3UR\xeb\x1c\x9e珹\x8bH\xb3\\B\x92\x9eV\xa5\xceQ\xed\xfc\xd1Xƫ\xa4\xd6\x0e\xd8y]_!\xf1\xef.!I@\x8a\x8fĂ\xc2O;\xe9*\x1b\xaf\x92Z\xcfS\x85\xd3I\f8\x84\xa4\x0e\xf7C\xee\xc8\x7f\xa2Ӯ\xb4\xf1*\xa9\xe5\xc4\x05\xb1\x12\xea\x87\x01\x7fv\rI\x1dj)\xd5\xc2\x11q}ԌWIj\x85\x80\x9d?\xe6.\xe0P`\x99kH\xea\xb0#\xe0\x03\xd4k\xaf\x8f\xf3\xe3\x91N\xbc\xf6ƫ\xa4\xd6=|\xf7\x17\x17\x13\xf1\x16`\xb5kH\xea\x10O@:4\x16t\xdfש\x03\x18\xaf\x92Z;`\xe7\x15~D\xa4\x13\x80\xbakHjs+\xa9\xc7\x1b\xa3\xbf\xf8\x9bN\x1e\xc1x\x95\xd4\x06\x01\xdbu\x1d)\x1d\x0e\xacr\rIm\xeaq\xea\xf1\xbaN\xfbd\x81u\x1e\xf3\xbd/Hj\x17iv\xe5 \"}\x03\xd8\xcc5$\xb5\xd1\xd1\xedAr\xf1\xfa\xe8-\xde\xe2\x16ƫ\xa4v;\xc4\xcf)\xcf\x04\xfe\x03\xd8\xd65$\xb5\x81{\xc8ꯋ\xbe1w;\xc5\x1a\xfeڀ\xa4\xf6zE\xde_\\L\xaa\xbf\x1cX\xe2\x1a\x92Z\xdc\x7f\x91\x15^b\xb8\x1a\xaf\x92\xda=`珹\x8b\xac\xb0?p\x91kHjA\t\xb8\x88\x87\n\xaf餯}\x1d\xf21\xde\t$\xb5\xf53\xc0\xecՇ\x11q\x15\xb0\xb9kHj\x01\x7f&\xe2ؘW\xf8\xbfNa\xbcJ\xeaԀ\x9d\xbbj\")\xbb\x9a\xc4K\\CR\x13\x1f\xadn\xa0V<1>\x1a\x0f\xb9\x85\xf1*\xa9ӟ\x12H\xc1\x9c\xca1\xc0'\xf1\xcd\\\x92\x9a+\xc7\xfe\b\xe9\xbc\xe8/^\xe3\x16ƫ$=;b?\x94\xc6S\xa8\xf4\x02\xa7\x039\x17\x914\x8a\xca\xc0\x15\xe4\n\xe7Eo,w\x0e\xe3U\x92\x9e;b{\xcb\xfbQ\x8b9\x90ތo^\x954\xd2њ\xf8\"\xd4\x17\xc4\xfc1\xf78\x87\xf1*IC\x8fع\xab\xf6\xa2\x9e}\x008\x01(\xb8\x88\xa4\x06Z\r\\M\xbd:?\x16\x8c\xfd\x83s\x18\xaf\x92\xb4\x11\x11\xbbr7\xea\xb9\xf7\x02\xc7\xe37tI\x1a^\x0fA\xfa\f\xd5\xe2Eq~\xfc\xc59\x8cWI\x1aƈMc\xa8W\x8e \xf1^\x82\x19.\"i#,\x06\x16\xb1\xbcpm\\\x10+\x9d\xc3x\x95\xa4Ɔ욯\x9a\x9d\x05\x1c\x03t\xbb\x88\xa4!X\x0e|\t\xb8,\xfa\x8b\xbfq\x0e\xe3U\x92F>b{ӶT\xab'\x10\xe9d`w\x17\x91\xb4\x0ew\x92\xe2s\xe4\U0009f27ex\xd49\x8cWI\x1a\xfd\x88\x9d\x9b2jՃ\bfAz\x1b~Ԗ\xd4\xe9j\x90\xbeG\xca\x162?\x7fS\x10\xc9I\x8cWIjΐ\x9d\xbdjO\xb28\x89\x14\xef\x06\xb6v\x11\xa9\xa3\x8e\x00\x7f\"\xb8\x86Z\xedR?5\xc0x\x95\xa4\xd6z\n;#u1\xbe\xfcfR\xcc\x02\x0eq\x11\xa9\xad\xfd\x8cH\vy\xb0\xf8\xcdX\x14\x15\xe70^%\xa9\xb5C\xf6\x997x\xbd\x13\xd8\xc4E\xa4\xb6\xf0$\xf0er\xe9\xe2\xe8\xed\xba\xd59\x8cWIj\xbf\x88='mN\xb1r$p&0\xd5E\xa4V| \xf3k\x82+YY\xf8b|*\x9er\x10\xe3U\x92:\xe3\xf9\xef\xbc\xca\xcb\xc98\x13\xd2[\x81\xbc\x8bHMm5ķI,\x8a\xf9\x85\x1b\x9d\xc3x\x95\xa4\u038d\xd8s\xd3\x0ed\xd5c\t\xde\x03ig\x17\x91\x9a*\x87\xee'\xeaWQ)^\xea7`\x19\xaf\x92\xa4\xbf\x8d\xd8\xdeT\xa4^~\xcb\xda7x\x1d\xecqX\x1a5u\xe0\x87DZ\xc4\xd2\xe2\xd7\xe3\xfa\xa89\x89\xf1*Iz\xbe\x90\x9d\xbdj\x1f\xb28amȎw\x11iD<\x0e\\C\xaa]\x18\xf3\xbb\x7f\xe7\x1cƫ$i}#\xf6\x83i\x1c]\x95\xa3H\x9cN\xd0\xe3\"RC,\x06\x16\xb1\xbcpm\\\x10+\x9d\xc3x\x95$\rG\xc8>\xf3q[\xc7\x02c\\D\xda(\xabH\\OpA\xf4\x17ov\x0e\xe3U\x92Ԩ\x88=7mGV=\x9eH\xa7\x02\xbb\xba\x88\xb4^\xee\"\xc5g\xc9\xe5?\x13}\xf1\xa8s\x18\xaf\x92\xa4\x91\x8aع)\xa3V=\x88\xa8\x9f\x05\xf1\x06\x8f\xdb\xd2sZ\xfb\x06\xac\xfaE\xcc\xeb\xba!\x88\xe4$ƫ$iTCv\xd5^\xa48\x91\x14'\x02[\xb9\x88\x04\x90\x1e$\xb8\x9a\xac~Y\xf4v\xff\xde=\x8cWIR\xb3=U\x9f\x91\xba\x18_~3\xc4\xd9$^\xe6\"\xeaP\x8b\x81\x8bx\xa8p],\x8a\x8as\x18\xaf\x92\xa4V\b\xd9g\xde\xe0u40\xd6E\xd4\xe6\x96\x01\xd7A\xba$\xfa\xbb\x06\x9d\xc3x\x95$\xb5jĞ\x936\xa7X9\x128\x1b\x98\xec\"j3\xb7\x93\xb8\x82|\xe1\xb3\xd1\x1b˝\xc3x\x95$\xb5K\xc4>\xfd\x06/fAz+\x90w\x15\xb5\xa82ķH,\x8a\xf9\x85\x1b\x9dCƫ$\xb5{\xc8\xf6>\xb5#\xf5\xfc,R\x9c\nl\xeb\"j\x914y\x80\xa8_K\xadvq,\x18{\xbf{\xc8x\x95\xa4\x8e\x8b\xd8T\xa4^~\xcbگ\xa1=\xc4EԄ\xd6~\xccUZD\x14\xbf\x11}Qu\x12\x19\xaf\x92$\xd2\xdcՓ\xa8ǩ\xc0\xbb\x80M]D\xa3\xec\t\xe0+dia\xf4u\xdd\xe6\x1c2^%I\xeb\x8e\xd8\u07b4\x19\xb5\xcaہ\xf7\x00%\x17\xd1\b[\f,\"+|!\xfab\x85s\xc8x\x95$\r=d\xe7\x94g\x928\x8b\xe0\xed@\xc1E\xd4 \xab!\xbe\r,\x8c\xfe\xc2ϜCƫ$i\xe3\"\xb67mO\xb5z\x1c\x91N\x03vq\x11\r\x93\xbbIq\x15\xb5\xfcUq~<\xe2\x1c2^%I\xc3\x1b\xb1sSFZ\xfd\x06Rv&p\xb0\xcf\x15\xda\x00k߀U\xbf\x88y]7\x04\x91\x9cDƫ$\xa9\xf1!;{\xd5\xded\xf1nR\x9c\x04l\xe9\"z\x01\x0f\x11\xe9\xf3D\xfd\x8a\xe8\xeb\xbe\xd79d\xbcJ\x92F'b\xe7\xa61\xd4+G\x90x/\xc1\f\x17\xd1\xdf\xf9\xeb\x1b\xb0\xae\x89\xbeX\xe5\x1c2^%I\xcd\x13\xb2s\xca3\x81Y\xc01@\xb7\x8bt\xace\xc0u\xc0e\xd1_\xfc\x8ds\xc8x\x95$5w\xc4\xceM[P\xab\x1cGp\x16\xb0\xbb\x8bt\x8c;H\xf1\xefT\xf3\x8b\xe2c\xf1\x98s\xc8x\x95$\xb5Z\xc4fԪ\a\x11̂\xf46 \xe7*m\xa7\f\xf1-\x12\x8b\x98\x9f\xbf\xc97`\xc9x\x95$\xb5IȮ܃\x94\xcd\"Ż\x80m\\\xa4\xe5o\xd1?\x11\\C\xadvi,\x18\xfb\a\xf7\x90\xf1*Ij\xcf\xe49#u1\xbe\xfcfR\xcc\x02\x0eq\x91\x96\xf33\"-$\x8a߈\xbe\xa8:\x87\x8cWIR\xe7\x84loy?j\x9c\f\xbc\x13\xd8\xc4E\x9a\xd6\x13\xc0W ]\x14\xfd]K\x9cCƫ$\xa9\xc3#6mF\xad\xf2v\xe0L`\xaa\x8b4\xcb\rï\t\xaede\xe1\x8b\xf1\xa9x\xcaAd\xbcJ\x92\xf4\xf7\xbdt^\xe5\xe5d\x9c\t\xe9\xad@\xdeEF\xdcj\x88o\x93X\x14\xf3\v7:\x87\x8cWI\x92\x86\x12\xb1\xe7\xa6\x1dȪ\xc7\x12\xe9t`\x82\x8b4\xdc=\xa4\xf8\f\xb9\xfcg\xa3/\x1ev\x0e\x19\xaf\x92$mH\xc4\x1e\x9erL^}();\x138\xd8\xe7\xa7aU\a~H\xa4E,-~=\xae\x8f\x9a\x93\xc8x\x95$i\xb8Bv\xf6\xaa}\xc8ℵ\x9fT0\xdeE6\xd8\xe3\xc05\xa4څ1\xbf\xfbw\xce!\xe3U\x92\xa4FF\xec\a\xd38\xba*G\x01\xa7\x01\xd3]d\xc8\x16\x03\x8bX^\xb86.\x88\x95\xce!\xe3U\x92\xa4\x91\x0e\xd99\xe5\x99\xc0,\xe0\x18\xa0\xdbE\xfe\xc1*\x12ד\xe7\xd3\xd1[\xbc\xc59d\xbcJ\x92\xd4\f\x11{nڎ\xacz<\x91N\x01vs\x11\xee$\xc5\xe7\xc8\xe5?\x13}\xf1\xa8s\xc8x\x95$\xa9\x19#vnʨU\x0f\"\x98\x05\xe9m@\xae\x83\xae~\r\xd2\xf7H\xd9B\xe6\xe7o\n\"y\x8f\x90\xf1*IR˄쪽Hq\")\xde\rl\xdd\xc6\xd7\xf4A\x82\xab\xc9\xea\x97Eo\xf7\xef\xbd\xe5e\xbcJ\x92\xd4\xcaiwF\xeab|\xf9ͤ8\v8\xa0\x8d\xae\xdab\xe0\"\x1e*\\\x17\x8b\xa2\xe2--\xe3U\x92\xa4v\v\xd9g\xde\xe0u40\xb6\x05\xaf\u0093\xc0\x97ɥ\x8b\xa3\xb7\xebVoQ\xc9x\x95$uBĞ\x936\xa7X9\x128\v\x98\xd2\x02\x17y)\x89+\xc9\x17>\x1b\xbd\xb1\xdc[P2^%I\x9d\x18\xb1sSF\xbd\xfa\nRz'\xc1a4\u0557\x1f\xa4?\x11\xf1e\x12_\x8c\xfe\xe2bo-\xc9x\x95$\xe9\x99T<#u\xb1y\xf9\xf5D\xf6NH\xaf\x05ƍ\xc2\xc5x\x04\xf8\x0e)\xbe\xc8\x1d\xf9\x1f\xf9\x95\xad\x92\xf1*I\xd2\v\x87\xec\xe1)Ǥ\xca\f\x12/'\xe2\x00H\xaf\x01\xb6h\xc0\x8fZ\x06\xfc\x82\x147\x12\xe9F\xb2\xc2\xcd\xd1\x17uo\x01\xc9x\x95$i\xc3cvn\xcaCy\"5&B\xb67\xa4\xbd\t&\x02;\xaf\x8d\xdaM\x801\xeb\xf8WW\x00O\x01\x8f\x03\xf7\x02w\x01w\x91\xb2;\xa1z\x17\xf3\xbb\xee\xf6\xf3X\xa5\xe1\xf1\xff\x03Q\xd2`\xa2Wa\x98\xa4\x00\x00\x00\x00IEND\xaeB`\x82"), diff --git a/providers/ionos.go b/providers/ionos.go new file mode 100644 index 00000000..9748cd81 --- /dev/null +++ b/providers/ionos.go @@ -0,0 +1,53 @@ +// This file is part of the happyDomain (R) project. +// Copyright (c) 2020-2026 happyDomain +// Authors: Pierre-Olivier Mercier, et al. +// +// This program is offered under a commercial and under the AGPL license. +// For commercial licensing, contact us at . +// +// For AGPL licensing: +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package providers // import "git.happydns.org/happyDomain/providers" + +import ( + "github.com/libdns/ionos" + + "git.happydns.org/happyDomain/internal/adapters" + providerReg "git.happydns.org/happyDomain/internal/provider" + "git.happydns.org/happyDomain/model" +) + +type IonosAPI struct { + AuthAPIToken string `json:"auth_api_token,omitempty" happydomain:"label=Auth API Token,secret,required,description=Your IONOS Auth API token"` +} + +func (s *IonosAPI) LibdnsProvider() any { + return &ionos.Provider{ + AuthAPIToken: s.AuthAPIToken, + } +} + +func (s *IonosAPI) InstantiateProvider() (happydns.ProviderActuator, error) { + return adapter.NewLibdnsProviderAdapter(s) +} + +func init() { + adapter.RegisterLibdnsProviderAdapter(func() happydns.ProviderBody { + return &IonosAPI{} + }, happydns.ProviderInfos{ + Name: "IONOS", + Description: "German hosting provider (1&1 IONOS)", + }, providerReg.RegisterProvider) +} diff --git a/web/src/lib/components/domains/DomainTableRow.svelte b/web/src/lib/components/domains/DomainTableRow.svelte new file mode 100644 index 00000000..2114f85f --- /dev/null +++ b/web/src/lib/components/domains/DomainTableRow.svelte @@ -0,0 +1,73 @@ + + + + + navigate("/domains/" + encodeURIComponent(domain.domain))} +> + {domain.domain} + {domain.group || ""} + + e.stopPropagation()} /> + + + OK + + + + + + + + diff --git a/web/src/lib/components/domains/Table.svelte b/web/src/lib/components/domains/Table.svelte index a45be74e..ff9851fa 100644 --- a/web/src/lib/components/domains/Table.svelte +++ b/web/src/lib/components/domains/Table.svelte @@ -24,14 +24,13 @@ + +{#if $providers_idx && $providers_idx[id_provider]} + {@const provider = $providers_idx[id_provider]} + + + {#if provider._comment} + {provider._comment} + {:else if $providersSpecs && $providersSpecs[provider._srctype]} + {$providersSpecs[provider._srctype].name} + {:else} + {provider._srctype} + {/if} + +{:else} + {id_provider} +{/if} diff --git a/web/src/lib/components/services/PropagationCountdown.svelte b/web/src/lib/components/services/PropagationCountdown.svelte new file mode 100644 index 00000000..4d566496 --- /dev/null +++ b/web/src/lib/components/services/PropagationCountdown.svelte @@ -0,0 +1,73 @@ + + + + +{#if propagatedAt} + {$t(localeString, { countdown })} +{/if} diff --git a/web/src/lib/components/services/PropagationStatus.svelte b/web/src/lib/components/services/PropagationStatus.svelte new file mode 100644 index 00000000..9d2a4f32 --- /dev/null +++ b/web/src/lib/components/services/PropagationStatus.svelte @@ -0,0 +1,51 @@ + + + + +{#if isPropagating} +
+
+ + {$t("service.propagation-in-progress")} +
+

+ +

+
+{/if} diff --git a/web/src/lib/locales/en.json b/web/src/lib/locales/en.json index 4759c473..f0ee39a2 100644 --- a/web/src/lib/locales/en.json +++ b/web/src/lib/locales/en.json @@ -415,7 +415,10 @@ "default-ttl": "Default TTL", "ttl": "TTL", "ttl-long": "Time-To-Live", - "ttl-tip": "0 means default TTL, others values are exprimed in seconds" + "ttl-tip": "0 means default TTL, others values are exprimed in seconds", + "propagating": "Propagating {{countdown}}", + "propagation-in-progress": "DNS propagation in progress", + "propagation-remaining": "Propagation complete in {{countdown}}" }, "records": { "add": "Add record", diff --git a/web/src/lib/locales/fr.json b/web/src/lib/locales/fr.json index 69b883c7..f0850f45 100644 --- a/web/src/lib/locales/fr.json +++ b/web/src/lib/locales/fr.json @@ -373,7 +373,10 @@ "default-ttl": "TTL par défaut", "ttl": "TTL", "ttl-long": "Time-To-Live", - "ttl-tip": "0 correspond au TTL par défaut, les autres valeurs sont exprimées en secondes" + "ttl-tip": "0 correspond au TTL par défaut, les autres valeurs sont exprimées en secondes", + "propagating": "Propagation {{countdown}}", + "propagation-in-progress": "Propagation DNS en cours", + "propagation-remaining": "Propagation complète dans {{countdown}}" }, "upgrade": { "title": "Une mise à jour est disponible !", diff --git a/web/src/lib/model/service.svelte.ts b/web/src/lib/model/service.svelte.ts index ef0e489f..ff5a0904 100644 --- a/web/src/lib/model/service.svelte.ts +++ b/web/src/lib/model/service.svelte.ts @@ -29,6 +29,7 @@ export class ServiceMeta { _mycomment? = $state(undefined); _aliases? = $state | undefined>(undefined); _tmp_hint_nb? = $state(undefined); + _propagated_at? = $state(undefined); constructor(init?: { _svctype: string; @@ -40,6 +41,7 @@ export class ServiceMeta { _mycomment?: string; _aliases?: Array; _tmp_hint_nb?: number; + _propagated_at?: string; }) { if (init) { this._svctype = init._svctype; @@ -51,6 +53,7 @@ export class ServiceMeta { if (init._mycomment !== undefined) this._mycomment = init._mycomment; if (init._aliases !== undefined) this._aliases = init._aliases; if (init._tmp_hint_nb !== undefined) this._tmp_hint_nb = init._tmp_hint_nb; + if (init._propagated_at !== undefined) this._propagated_at = init._propagated_at; } } @@ -65,6 +68,7 @@ export class ServiceMeta { _mycomment: this._mycomment, _aliases: this._aliases, _tmp_hint_nb: this._tmp_hint_nb, + _propagated_at: this._propagated_at, }; } } @@ -82,6 +86,7 @@ export class ServiceCombined extends ServiceMeta { _mycomment?: string; _aliases?: Array; _tmp_hint_nb?: number; + _propagated_at?: string; Service?: any; }) { super(init); diff --git a/web/src/lib/stores/thiszone.ts b/web/src/lib/stores/thiszone.ts index f10d8fa6..02d212c0 100644 --- a/web/src/lib/stores/thiszone.ts +++ b/web/src/lib/stores/thiszone.ts @@ -19,7 +19,6 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . -import { get } from "svelte/store"; import { derived, writable, type Writable } from "svelte/store"; import { domainCompare } from "$lib/dns"; import { retrieveZone as APIRetrieveZone, getZone as APIGetZone } from "$lib/api/zone"; @@ -83,11 +82,6 @@ export const sortedDomainsWithIntermediate = derived(sortedDomains, ($sortedDoma // getZone retrieve a given zone export async function getZone(domain: Domain, zoneId: string) { - const currentZone = get(thisZone); - if (currentZone?.id === zoneId) { - return currentZone; - } - thisZone.set(null); const zone = await APIGetZone(domain, zoneId); diff --git a/web/src/lib/translations.ts b/web/src/lib/translations.ts index ab83e161..4c34066d 100644 --- a/web/src/lib/translations.ts +++ b/web/src/lib/translations.ts @@ -43,6 +43,7 @@ interface Params { name?: string; nbDiffs?: number; nbSelected?: number; + countdown?: string; // add more parameters that are used here } diff --git a/web/src/lib/utils/datetime.ts b/web/src/lib/utils/datetime.ts index 45b27878..ee38c5be 100644 --- a/web/src/lib/utils/datetime.ts +++ b/web/src/lib/utils/datetime.ts @@ -31,3 +31,31 @@ export function fromDatetimeLocal(datetimeLocal: string): string | null { return null; } } + +/** + * Format a countdown timer string from a target date. + * Displays the remaining time in a human-readable format (e.g., "2d 5h", "3h 20m"). + * @param date Target date to count down to + * @returns Formatted countdown string (e.g., "2d 5h", "30m", "45s"), or "0m" if date is in the past + */ +export function formatCountdown(date: Date): string { + const diff = date.getTime() - Date.now(); + if (diff <= 0) return "0m"; + + const seconds = Math.floor(diff / 1000); + const minutes = Math.floor(seconds / 60); + const hours = Math.floor(minutes / 60); + const days = Math.floor(hours / 24); + + if (days > 0) { + return `${days}d ${hours % 24}h`; + } else if (hours > 0) { + return `${hours}h ${minutes % 60}m`; + } else if (minutes > 9) { + return `${minutes}m`; + } else if (minutes > 0) { + return `${minutes}m ${seconds % 60}s`; + } else { + return `${seconds}s`; + } +} diff --git a/web/src/routes/domains/[dn]/ServiceDetailsOffcanvas.svelte b/web/src/routes/domains/[dn]/ServiceDetailsOffcanvas.svelte index 99d206c5..88ab07fd 100644 --- a/web/src/routes/domains/[dn]/ServiceDetailsOffcanvas.svelte +++ b/web/src/routes/domains/[dn]/ServiceDetailsOffcanvas.svelte @@ -43,6 +43,7 @@ import { getServiceSpec } from "$lib/api/service_specs"; import { deleteZoneService, updateZoneService } from "$lib/api/zone"; import ServiceBadges from "./[[historyid]]/ServiceBadges.svelte"; + import PropagationStatus from "$lib/components/services/PropagationStatus.svelte"; import RecordLine from "$lib/components/services/editors/RecordLine.svelte"; import { collectRRs } from "$lib/dns"; import type { Domain } from "$lib/model/domain"; @@ -154,6 +155,7 @@ {/each} {/await} {/if} +
{#if service._id}
diff --git a/web/src/routes/domains/[dn]/[[historyid]]/+layout.ts b/web/src/routes/domains/[dn]/[[historyid]]/+layout.ts index f912339a..5534fe1c 100644 --- a/web/src/routes/domains/[dn]/[[historyid]]/+layout.ts +++ b/web/src/routes/domains/[dn]/[[historyid]]/+layout.ts @@ -1,7 +1,7 @@ +import { get } from "svelte/store"; import { error, redirect, type Load } from "@sveltejs/kit"; -import { domains_idx } from "$lib/stores/domains"; -import { getZone } from "$lib/stores/thiszone"; +import { getZone, thisZone } from "$lib/stores/thiszone"; export const load: Load = async ({ parent, params }) => { const data = await parent(); @@ -32,7 +32,10 @@ export const load: Load = async ({ parent, params }) => { const zoneId: string = domain.zone_history[zhidx]; - getZone(domain, zoneId); + const currentZone = get(thisZone); + if (currentZone?.id !== zoneId) { + getZone(domain, zoneId); + } return { ...data, diff --git a/web/src/routes/domains/[dn]/[[historyid]]/ServiceCard.svelte b/web/src/routes/domains/[dn]/[[historyid]]/ServiceCard.svelte index 235ce7ee..1665a015 100644 --- a/web/src/routes/domains/[dn]/[[historyid]]/ServiceCard.svelte +++ b/web/src/routes/domains/[dn]/[[historyid]]/ServiceCard.svelte @@ -30,6 +30,7 @@ CardSubtitle, Icon, Spinner, + Progress, } from "@sveltestrap/sveltestrap"; import ServiceBadges from "./ServiceBadges.svelte"; @@ -38,8 +39,8 @@ import type { Domain } from "$lib/model/domain"; import type { ServiceCombined } from "$lib/model/service.svelte"; import { servicesSpecs, servicesSpecsLoaded } from "$lib/stores/services"; - import { navigate } from "$lib/stores/config"; import { t } from "$lib/translations"; + import PropagationCountdown from "$lib/components/services/PropagationCountdown.svelte"; interface Props { dn: string; @@ -50,6 +51,9 @@ let { dn, origin, service = $bindable(null), zoneId }: Props = $props(); + // Will be changed by PropagationCountdown + let isPropagating = $state(true); + function openService() { if (service) { const subdomainParam = dn === "" ? "@" : dn; @@ -62,7 +66,7 @@ {#if !$servicesSpecsLoaded} @@ -79,7 +83,24 @@ {$t("service.new")} {/if} - + {#if service?._propagated_at && isPropagating} + + + + {:else} + + {/if}
{#if service}