From 6afd1d127dcf182555e82ef9114ea8d5237ffc94 Mon Sep 17 00:00:00 2001 From: m-bohra8999 Date: Sat, 8 Apr 2023 18:51:37 +0530 Subject: [PATCH] kanban board --- package-lock.json | 323 ++++++++++++++++++ package.json | 6 + src/App/App.tsx | 6 +- src/App/axios.ts | 3 +- src/App/router.tsx | 12 + src/App/store.ts | 10 + src/App/theme/theme.tsx | 106 +++++- src/App/types.ts | 38 +++ src/features/Board/BoardSlice.ts | 48 +++ src/features/Board/Filters/FilterSlice.ts | 35 ++ src/features/Board/Filters/Styles.ts | 73 ++++ src/features/Board/Filters/index.tsx | 148 ++++++++ src/features/Board/Header/index.tsx | 26 ++ src/features/Board/Lists/List/Issue/Styles.ts | 57 ++++ src/features/Board/Lists/List/Issue/index.tsx | 90 +++++ src/features/Board/Lists/List/Styles.ts | 35 ++ src/features/Board/Lists/List/index.tsx | 72 ++++ src/features/Board/Lists/ListsSlice.ts | 47 +++ src/features/Board/Lists/Styles.ts | 6 + src/features/Board/Lists/index.tsx | 111 ++++++ src/features/Board/index.tsx | 130 +++++++ src/features/Board/types.ts | 29 ++ src/features/auth/authSlice.ts | 6 +- src/features/home/index.tsx | 50 +-- .../components/AvatarGroupWrapper/index.tsx | 76 +++++ src/shared/components/Breadcrumbs/Styles.ts | 15 + src/shared/components/Breadcrumbs/index.tsx | 19 ++ src/shared/components/ButtonWrapper/index.tsx | 10 +- src/shared/components/PageError/Styles.ts | 57 ++++ .../PageError/assets/background-forest.jpg | Bin 0 -> 564518 bytes src/shared/components/PageError/index.tsx | 28 ++ .../components/TextFieldWrapper/Styles.ts | 15 + .../components/TextFieldWrapper/index.tsx | 25 +- .../components/layout/BaseLayout/index.tsx | 1 - .../components/layout/SidebarLayout/index.tsx | 44 +++ src/shared/constants/card.ts | 37 ++ .../constants/{constants.ts => error.ts} | 14 - src/shared/helpers/common.ts | 44 +++ src/shared/hooks/mergeState.ts | 27 ++ 39 files changed, 1810 insertions(+), 69 deletions(-) create mode 100644 src/App/types.ts create mode 100644 src/features/Board/BoardSlice.ts create mode 100644 src/features/Board/Filters/FilterSlice.ts create mode 100644 src/features/Board/Filters/Styles.ts create mode 100644 src/features/Board/Filters/index.tsx create mode 100644 src/features/Board/Header/index.tsx create mode 100644 src/features/Board/Lists/List/Issue/Styles.ts create mode 100644 src/features/Board/Lists/List/Issue/index.tsx create mode 100644 src/features/Board/Lists/List/Styles.ts create mode 100644 src/features/Board/Lists/List/index.tsx create mode 100644 src/features/Board/Lists/ListsSlice.ts create mode 100644 src/features/Board/Lists/Styles.ts create mode 100644 src/features/Board/Lists/index.tsx create mode 100644 src/features/Board/index.tsx create mode 100644 src/features/Board/types.ts create mode 100644 src/shared/components/AvatarGroupWrapper/index.tsx create mode 100644 src/shared/components/Breadcrumbs/Styles.ts create mode 100644 src/shared/components/Breadcrumbs/index.tsx create mode 100644 src/shared/components/PageError/Styles.ts create mode 100644 src/shared/components/PageError/assets/background-forest.jpg create mode 100644 src/shared/components/PageError/index.tsx create mode 100644 src/shared/components/TextFieldWrapper/Styles.ts create mode 100644 src/shared/components/layout/SidebarLayout/index.tsx create mode 100644 src/shared/constants/card.ts rename src/shared/constants/{constants.ts => error.ts} (55%) create mode 100644 src/shared/helpers/common.ts create mode 100644 src/shared/hooks/mergeState.ts diff --git a/package-lock.json b/package-lock.json index 734f123..bf2cd9f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,54 @@ } } }, + "@atlaskit/analytics-next": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/@atlaskit/analytics-next/-/analytics-next-9.0.0.tgz", + "integrity": "sha512-9I28hJjQCwH8cEKAVjikN2F0rnZGWq7/77Od3yJ/goiEoaAKGFZjoFMFvPPpMPfxiURnisxx7/U1thgpWM6vcA==", + "requires": { + "@atlaskit/analytics-next-stable-react-context": "1.0.1", + "@babel/runtime": "^7.0.0", + "prop-types": "^15.5.10", + "use-memo-one": "^1.1.1" + } + }, + "@atlaskit/analytics-next-stable-react-context": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@atlaskit/analytics-next-stable-react-context/-/analytics-next-stable-react-context-1.0.1.tgz", + "integrity": "sha512-iO6+hIp09dF4iAZQarVz3vKY1kM5Ij5CExYcK9jgc2q+OH8nv8n+BPFeJTdzGOGopmbUZn5Opj9pYQvge1Gr4Q==", + "requires": { + "tslib": "^2.0.0" + } + }, + "@atlaskit/avatar": { + "version": "21.2.0", + "resolved": "https://registry.npmjs.org/@atlaskit/avatar/-/avatar-21.2.0.tgz", + "integrity": "sha512-PnUC/rohel4fZ1IXoycln9YV3R6U+zl0NGltCr7/8E2SkuFsMmGQFF6ZFBZoc3mOXRzmChb4VjkKQhokxDOzrg==", + "requires": { + "@atlaskit/analytics-next": "^9.0.0", + "@atlaskit/icon": "^21.11.0", + "@atlaskit/theme": "^12.2.0", + "@atlaskit/tokens": "^1.2.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1", + "@emotion/serialize": "^1.1.0" + } + }, + "@atlaskit/avatar-group": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@atlaskit/avatar-group/-/avatar-group-9.2.4.tgz", + "integrity": "sha512-m8vWeCPjtoE5tCeMuyDddwEnZYCBshNb8RSJctk0P5brGNCVnpBVhnUYnm58/JuwDf3P51SKs/BsX5ZFGKpwIg==", + "requires": { + "@atlaskit/avatar": "^21.2.0", + "@atlaskit/menu": "^1.5.0", + "@atlaskit/popup": "^1.5.0", + "@atlaskit/theme": "^12.2.0", + "@atlaskit/tokens": "^1.2.0", + "@atlaskit/tooltip": "^17.7.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1" + } + }, "@atlaskit/codemod-utils": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/@atlaskit/codemod-utils/-/codemod-utils-4.1.3.tgz", @@ -34,6 +82,17 @@ "@babel/runtime": "^7.0.0" } }, + "@atlaskit/ds-explorations": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/@atlaskit/ds-explorations/-/ds-explorations-2.0.10.tgz", + "integrity": "sha512-dQ6PVT+nEDalKuG++iY/XGU64Y+Vr7XjjVVYcywa7ZPAph3hMH/lPD2g1KcyX8hPlPQEi9Rbh3lWzWoMt1ZZMw==", + "requires": { + "@atlaskit/tokens": "^1.2.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1", + "tiny-invariant": "^1.2.0" + } + }, "@atlaskit/ds-lib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@atlaskit/ds-lib/-/ds-lib-2.1.2.tgz", @@ -43,6 +102,16 @@ "bind-event-listener": "^2.1.1" } }, + "@atlaskit/focus-ring": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@atlaskit/focus-ring/-/focus-ring-1.2.5.tgz", + "integrity": "sha512-X/O5mpE+lPW/LMGHcpYVuwsb7iid+AjZ9U66h/P5A8d4v02EqQ9SP+KXF90Tf7khELLVmRq/pDiuJZg7LuypGg==", + "requires": { + "@atlaskit/tokens": "^1.2.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1" + } + }, "@atlaskit/icon": { "version": "21.11.5", "resolved": "https://registry.npmjs.org/@atlaskit/icon/-/icon-21.11.5.tgz", @@ -54,6 +123,101 @@ "@emotion/react": "^11.7.1" } }, + "@atlaskit/in-product-testing": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@atlaskit/in-product-testing/-/in-product-testing-0.1.5.tgz", + "integrity": "sha512-vS6eFkQBInT0oAd9fuB1LSl4xQtQk69KVqXM1yyhHyGHLQ+T7pB9u0dnEwgUVaGxV5wSuvbz9JUGVeug1YlvWw==", + "requires": { + "@babel/runtime": "^7.0.0" + } + }, + "@atlaskit/menu": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/@atlaskit/menu/-/menu-1.5.3.tgz", + "integrity": "sha512-WcDHzvuXr3Xpo6rpRlwMj/5o5ioNNZH5pMidF2q4E4oHPfUKFJfkd4OIiRyyF18qs+txUCjjEpBFzbxf0iwFbA==", + "requires": { + "@atlaskit/ds-explorations": "^2.0.0", + "@atlaskit/ds-lib": "^2.1.0", + "@atlaskit/focus-ring": "^1.2.0", + "@atlaskit/primitives": "^0.4.0", + "@atlaskit/theme": "^12.3.0", + "@atlaskit/tokens": "^1.2.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1" + }, + "dependencies": { + "@atlaskit/theme": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@atlaskit/theme/-/theme-12.3.0.tgz", + "integrity": "sha512-kLWNtbcmyWthhHRXNelif2QwCz8TrYkXz/J2i6yb+H2CMDFdYI/mP1+/WJ+dv3b2YVlrbazzA/HS33RJHBJYPQ==", + "requires": { + "@atlaskit/codemod-utils": "^4.1.0", + "@atlaskit/ds-lib": "^2.1.0", + "@atlaskit/tokens": "^1.2.0", + "@babel/runtime": "^7.0.0" + } + } + } + }, + "@atlaskit/motion": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@atlaskit/motion/-/motion-1.3.2.tgz", + "integrity": "sha512-CNYlhuwXBdVi38cb9vbEIPOai3UqJsxH79uvW6n9c6Gam1heK3VOhZ+9ymervpUSN/KtpqicZsYpoOn347RrUw==", + "requires": { + "@atlaskit/ds-lib": "^2.1.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1", + "bind-event-listener": "^2.1.1" + } + }, + "@atlaskit/popper": { + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/@atlaskit/popper/-/popper-5.4.11.tgz", + "integrity": "sha512-jq00dRTP50RJ39nVkADfgQrGUF0KD82UH4CUzAuEfNTHYOc04LArujz9BWqBD9ahexQK1M7ph90+rAtE5ypRVQ==", + "requires": { + "@atlaskit/in-product-testing": "^0.1.5", + "@babel/runtime": "^7.0.0", + "@popperjs/core": "^2.9.1", + "react-popper": "^2.2.3" + } + }, + "@atlaskit/popup": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@atlaskit/popup/-/popup-1.5.5.tgz", + "integrity": "sha512-K4hjsgBSH0FKhY2GI4K7I99IhxG8srzOUNNJSE8R69eG7RuVTgUORxDp2QWhfx5vRPr8/S9px5+T9NLiJLSMxQ==", + "requires": { + "@atlaskit/ds-lib": "^2.1.0", + "@atlaskit/popper": "^5.4.0", + "@atlaskit/portal": "^4.0.0", + "@atlaskit/theme": "^12.2.0", + "@atlaskit/tokens": "^1.0.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1", + "bind-event-listener": "^2.1.1", + "focus-trap": "^2.4.5" + } + }, + "@atlaskit/portal": { + "version": "4.2.12", + "resolved": "https://registry.npmjs.org/@atlaskit/portal/-/portal-4.2.12.tgz", + "integrity": "sha512-wWwiTOZPZa0IidB3QAZmNbi75seTc4vTXplKqnJWe49yRTcwWaTz5tEnw15iIi1iPSfM97KND3GIREjyH7CrvA==", + "requires": { + "@atlaskit/theme": "^12.2.0", + "@babel/runtime": "^7.0.0" + } + }, + "@atlaskit/primitives": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@atlaskit/primitives/-/primitives-0.4.2.tgz", + "integrity": "sha512-vFkCDmrn1Wy/wjYBXYno2QCVo3FCPLs5TdV5jnM4ERczyDrycjVL2vbFxhZ3D2I4pMtsmNdUZVa/ObFEIec0SQ==", + "requires": { + "@atlaskit/tokens": "^1.2.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1", + "@emotion/serialize": "^1.1.0", + "tiny-invariant": "^1.2.0" + } + }, "@atlaskit/theme": { "version": "12.2.9", "resolved": "https://registry.npmjs.org/@atlaskit/theme/-/theme-12.2.9.tgz", @@ -77,6 +241,24 @@ "bind-event-listener": "^2.1.1" } }, + "@atlaskit/tooltip": { + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/@atlaskit/tooltip/-/tooltip-17.7.0.tgz", + "integrity": "sha512-CswGrNAeT0KxQg3mCzIzh6UC52BnVZ3nGw7f3tM7de/Md/RlonHtGKOw06oS6rzDJdWjSzBHED2cl1Y8R9cLxg==", + "requires": { + "@atlaskit/analytics-next": "^9.0.0", + "@atlaskit/ds-lib": "^2.1.0", + "@atlaskit/motion": "^1.3.0", + "@atlaskit/popper": "^5.4.0", + "@atlaskit/portal": "^4.1.0", + "@atlaskit/theme": "^12.2.0", + "@atlaskit/tokens": "^1.2.0", + "@babel/runtime": "^7.0.0", + "@emotion/react": "^11.7.1", + "bind-event-listener": "^2.1.1", + "react-uid": "^2.2.0" + } + }, "@babel/code-frame": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", @@ -1585,6 +1767,12 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "@types/lodash": { + "version": "4.14.192", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.192.tgz", + "integrity": "sha512-km+Vyn3BYm5ytMO13k9KTp27O75rbQ0NFw+U//g+PX7VZyjCioXaRFisqSIJRECljcTv73G3i6BpglNGHgUQ5A==", + "dev": true + }, "@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", @@ -1615,6 +1803,15 @@ "csstype": "^3.0.2" } }, + "@types/react-beautiful-dnd": { + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/@types/react-beautiful-dnd/-/react-beautiful-dnd-13.1.4.tgz", + "integrity": "sha512-4bIBdzOr0aavN+88q3C7Pgz+xkb7tz3whORYrmSj77wfVEMfiWiooIwVWFR7KM2e+uGTe5BVrXqSfb0aHeflJA==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, "@types/react-dom": { "version": "18.0.11", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.0.11.tgz", @@ -1632,6 +1829,17 @@ "@types/react": "*" } }, + "@types/react-redux": { + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", + "requires": { + "@types/hoist-non-react-statics": "^3.3.0", + "@types/react": "*", + "hoist-non-react-statics": "^3.3.0", + "redux": "^4.0.0" + } + }, "@types/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -2103,6 +2311,14 @@ "which": "^2.0.1" } }, + "css-box-model": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/css-box-model/-/css-box-model-1.2.1.tgz", + "integrity": "sha512-a7Vr4Q/kd/aw96bnJG332W9V9LkJO69JRcaCYDUqjp6/z0w6VcZjgAcTbgFxEPfBgdnAwlh3iwu+hLopa+flJw==", + "requires": { + "tiny-invariant": "^1.0.6" + } + }, "css-vendor": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/css-vendor/-/css-vendor-2.0.8.tgz", @@ -2903,6 +3119,14 @@ "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", "dev": true }, + "focus-trap": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-2.4.6.tgz", + "integrity": "sha512-vWZTPtBU6pBoyWZDRZJHkXsyP2ZCZBHE3DRVXnSVdQKH/mcDtu9S5Kz8CUDyIqpfZfLEyI9rjKJLnc4Y40BRBg==", + "requires": { + "tabbable": "^1.0.3" + } + }, "follow-redirects": { "version": "1.15.2", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", @@ -2963,6 +3187,11 @@ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true }, + "fuse.js": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz", + "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==" + }, "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3614,6 +3843,11 @@ "p-locate": "^5.0.0" } }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -3656,6 +3890,11 @@ "@jridgewell/sourcemap-codec": "^1.4.13" } }, + "memoize-one": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-5.2.1.tgz", + "integrity": "sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==" + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4010,6 +4249,11 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "raf-schd": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.3.tgz", + "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" + }, "react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -4018,6 +4262,40 @@ "loose-envify": "^1.1.0" } }, + "react-beautiful-dnd": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-13.1.1.tgz", + "integrity": "sha512-0Lvs4tq2VcrEjEgDXHjT98r+63drkKEgqyxdA7qD3mvKwga6a5SscbdLPO2IExotU1jW8L0Ksdl0Cj2AF67nPQ==", + "requires": { + "@babel/runtime": "^7.9.2", + "css-box-model": "^1.2.0", + "memoize-one": "^5.1.1", + "raf-schd": "^4.0.2", + "react-redux": "^7.2.0", + "redux": "^4.0.4", + "use-memo-one": "^1.1.1" + }, + "dependencies": { + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" + }, + "react-redux": { + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/react-redux": "^7.1.20", + "hoist-non-react-statics": "^3.3.2", + "loose-envify": "^1.4.0", + "prop-types": "^15.7.2", + "react-is": "^17.0.2" + } + } + } + }, "react-dom": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", @@ -4027,11 +4305,25 @@ "scheduler": "^0.23.0" } }, + "react-fast-compare": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.1.tgz", + "integrity": "sha512-xTYf9zFim2pEif/Fw16dBiXpe0hoy5PxcD8+OwBnTtNLfIm3g6WxhKNurY+6OmdH1u6Ta/W/Vl6vjbYP1MFnDg==" + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" }, + "react-popper": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz", + "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==", + "requires": { + "react-fast-compare": "^3.0.1", + "warning": "^4.0.2" + } + }, "react-redux": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", @@ -4086,6 +4378,14 @@ "prop-types": "^15.6.2" } }, + "react-uid": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/react-uid/-/react-uid-2.3.2.tgz", + "integrity": "sha512-oeaoT4YOjsqHdrEJoO8SONNNBsoGh7AJPbsNqRK6Dv8UMdctWxA4ncj9gAA/Odki5g0GZaDSR7HydBJ8HxwgNg==", + "requires": { + "tslib": "^2.0.0" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4377,12 +4677,22 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, + "tabbable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-1.1.3.tgz", + "integrity": "sha512-nOWwx35/JuDI4ONuF0ZTo6lYvI0fY0tZCH1ErzY2EXfu4az50ZyiUX8X073FLiZtmWUVlkRnuXsehjJgCw9tYg==" + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", "dev": true }, + "tiny-invariant": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, "tiny-warning": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", @@ -4521,6 +4831,11 @@ "punycode": "^2.1.0" } }, + "use-memo-one": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", + "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==" + }, "use-sync-external-store": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", @@ -4550,6 +4865,14 @@ "tsconfck": "^2.0.1" } }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index c1e529a..ed32232 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "lint": "eslint . --ext .ts,.tsx" }, "dependencies": { + "@atlaskit/avatar-group": "^9.2.4", "@atlaskit/icon": "^21.11.5", "@emotion/react": "^11.10.6", "@emotion/styled": "^11.10.6", @@ -25,15 +26,20 @@ "axios": "^1.3.4", "date-fns": "^2.29.3", "firebase": "^9.18.0", + "fuse.js": "^6.6.2", "history": "^5.3.0", + "lodash": "^4.17.21", "notistack": "^3.0.1", "react": "^18.2.0", + "react-beautiful-dnd": "^13.1.1", "react-dom": "^18.2.0", "react-redux": "^8.0.5", "react-router-dom": "^6.8.2" }, "devDependencies": { + "@types/lodash": "^4.14.192", "@types/react": "^18.0.27", + "@types/react-beautiful-dnd": "^13.1.4", "@types/react-dom": "^18.0.10", "@typescript-eslint/eslint-plugin": "^5.54.0", "@typescript-eslint/parser": "^5.54.0", diff --git a/src/App/App.tsx b/src/App/App.tsx index c5a245c..3d2eda9 100644 --- a/src/App/App.tsx +++ b/src/App/App.tsx @@ -23,14 +23,12 @@ const StyledSnackbarContent = styled(MaterialDesignContent)(({ theme }) => ({ const App = () => { const content = useRoutes(router); - const user = useAppSelector((state) => state.auth.value); - console.log('user from state', user); - const dispatch = useAppDispatch(); useEffect(() => { onAuthStateChanged(auth, (user) => { if (user) { - dispatch(saveUser(user.refreshToken)); + dispatch(saveUser(user)); + localStorage.setItem('token', (user as any).accessToken); } else { dispatch(saveUser(undefined)); } diff --git a/src/App/axios.ts b/src/App/axios.ts index a46f2a0..d53ddcc 100644 --- a/src/App/axios.ts +++ b/src/App/axios.ts @@ -7,7 +7,6 @@ axios.interceptors.request.use( if (config.method === 'post') { config.headers['Content-Type'] = 'application/json'; } - console.log('Intercepted request', config); return config; }, (error) => { @@ -16,7 +15,7 @@ axios.interceptors.request.use( ); export const request = axios.create({ - baseURL: 'https://dev--mira-backend.netlify.app/.netlify/functions/api/v1', + baseURL: 'https://dev--mira-backend.netlify.app/.netlify/functions', headers: { Authorization: `Bearer ${token}` }, timeout: 4000, }); diff --git a/src/App/router.tsx b/src/App/router.tsx index 0f0bfb2..22f3167 100644 --- a/src/App/router.tsx +++ b/src/App/router.tsx @@ -5,6 +5,8 @@ import Home from 'features/home'; import Status404 from 'features/home/Status404'; // types import type { RouteObject } from 'react-router'; +import ProjectBoard from 'features/Board'; +import SidebarLayout from 'shared/components/layout/SidebarLayout'; const router: RouteObject[] = [ { @@ -29,6 +31,16 @@ const router: RouteObject[] = [ path: '*', element: , }, + { + path: 'project', + element: , + children: [ + { + path: ':id', + element: , + }, + ], + }, ], }, ]; diff --git a/src/App/store.ts b/src/App/store.ts index 71de037..7a25143 100644 --- a/src/App/store.ts +++ b/src/App/store.ts @@ -1,10 +1,20 @@ import { configureStore } from '@reduxjs/toolkit'; import authReducer from 'features/auth/authSlice'; +import filterReducer from 'features/Board/Filters/FilterSlice'; +import boardReducer from 'features/Board/BoardSlice'; +import listReducer from 'features/Board/Lists/ListsSlice'; const store = configureStore({ reducer: { auth: authReducer, + filterBar: filterReducer, + board: boardReducer, + card: listReducer, }, + middleware: (getDefaultMiddleware) => + getDefaultMiddleware({ + serializableCheck: false, + }), }); export default store; diff --git a/src/App/theme/theme.tsx b/src/App/theme/theme.tsx index 671e1af..ebd0a46 100644 --- a/src/App/theme/theme.tsx +++ b/src/App/theme/theme.tsx @@ -19,13 +19,38 @@ const LinkBehavior = React.forwardRef< LinkBehavior.displayName = 'LinkBehavior'; -const themeOptions: ThemeOptions = { - colors: { - shadows: { - primary: - '0px 1px 4px rgba(85, 105, 255, 0.25), 0px 3px 12px 2px rgba(85, 105, 255, 0.35)', - }, +const colors = { + primary: '#0052cc', // Blue + success: '#0B875B', // green + danger: '#E13C3C', // red + warning: '#F89C1C', // orange + secondary: '#F4F5F7', // light grey + + textDarkest: '#172b4d', + textDark: '#42526E', + textMedium: '#5E6C84', + textLight: '#8993a4', + textLink: '#0052cc', + + backgroundDarkPrimary: '#0747A6', + backgroundMedium: '#dfe1e6', + backgroundLight: '#ebecf0', + backgroundLightest: '#F4F5F7', + backgroundLightPrimary: '#D2E5FE', + backgroundLightSuccess: '#E4FCEF', + + borderLightest: '#dfe1e6', + borderLight: '#C1C7D0', + borderInputFocus: '#4c9aff', + + shadows: { + primary: + '0px 1px 4px rgba(85, 105, 255, 0.25), 0px 3px 12px 2px rgba(85, 105, 255, 0.35)', }, +}; + +const themeOptions: ThemeOptions = { + colors, palette: { primary: { main: '#2151c5', @@ -76,6 +101,11 @@ const themeOptions: ThemeOptions = { size: 'small', }, }, + MuiToggleButton: { + defaultProps: { + disableRipple: true, + }, + }, MuiAppBar: { defaultProps: { color: 'transparent', @@ -104,6 +134,7 @@ const themeOptions: ThemeOptions = { MuiCheckbox: { defaultProps: { size: 'small', + disableRipple: true, }, }, MuiFab: { @@ -164,15 +195,78 @@ const themeOptions: ThemeOptions = { } as LinkProps, }, }, + sidebar: { + width: '290px', + }, }; declare module '@mui/material/styles' { + interface Theme { + colors: { + primary: string; + success: string; + danger: string; + warning: string; + secondary: string; + + textDarkest: string; + textDark: string; + textMedium: string; + textLight: string; + textLink: string; + + backgroundDarkPrimary: string; + backgroundMedium: string; + backgroundLight: string; + backgroundLightest: string; + backgroundLightPrimary: string; + backgroundLightSuccess: string; + + borderLightest: string; + borderLight: string; + borderInputFocus: string; + + shadows: { + primary: string; + }; + }; + sidebar: { + width: string; + }; + } + interface ThemeOptions { colors: { + primary: string; + success: string; + danger: string; + warning: string; + secondary: string; + + textDarkest: string; + textDark: string; + textMedium: string; + textLight: string; + textLink: string; + + backgroundDarkPrimary: string; + backgroundMedium: string; + backgroundLight: string; + backgroundLightest: string; + backgroundLightPrimary: string; + backgroundLightSuccess: string; + + borderLightest: string; + borderLight: string; + borderInputFocus: string; + shadows: { primary: string; }; }; + sidebar: { + width: string; + }; } } diff --git a/src/App/types.ts b/src/App/types.ts new file mode 100644 index 0000000..ffe3c5b --- /dev/null +++ b/src/App/types.ts @@ -0,0 +1,38 @@ +export interface Icard { + _id: string; + title: string; + description: string; + id: string; + project?: Iproject; + createdBy?: string; + assignee?: string; + estimatedDate?: Date; + prioroity?: string; + status?: string; + reporter?: Iuser; +} + +export interface Iproject { + name: string; + description: string; + logo: string; + users: Iuser[]; + admins: Iadmin[]; + id: string; +} + +export interface Iuser { + _id: string; + firstName: string; + lastName: string; + email: string; + imageUrl: string; +} + +export interface Iadmin { + _id: string; + firstName: string; + lastName: string; + email: string; + imageUrl: string; +} diff --git a/src/features/Board/BoardSlice.ts b/src/features/Board/BoardSlice.ts new file mode 100644 index 0000000..0e1f85d --- /dev/null +++ b/src/features/Board/BoardSlice.ts @@ -0,0 +1,48 @@ +import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; +import { Iboard } from './types'; +import { request } from 'app/axios'; + +export const fetchProject = createAsyncThunk('board/fetchProject', async () => { + return request + .get('/api/v1/projects/642569949ef06adb176ed64e') + .then(({ data: { data } }) => data.data); +}); + +const initialState: Iboard = { + title: 'Kanban Board', + project: null, + loading: true, + error: '', + allUsers: [], +}; + +const boardSlice = createSlice({ + name: 'board', + initialState, + reducers: { + setTitle: (state, action) => { + state.title = action.payload; + }, + }, + extraReducers: (builder) => { + // builder.addCase(fetchProject.pending, (state) => { + // state.loading = true; + // }); + builder.addCase(fetchProject.fulfilled, (state, action) => { + const { admins, users } = action.payload; + state.loading = false; + state.project = action.payload; + state.error = ''; + state.allUsers = [...admins, ...users]; + }); + builder.addCase(fetchProject.rejected, (state, action) => { + state.loading = false; + state.project = null; + state.error = action.error.message || 'Something went wrong'; + }); + }, +}); + +export const { setTitle } = boardSlice.actions; + +export default boardSlice.reducer; diff --git a/src/features/Board/Filters/FilterSlice.ts b/src/features/Board/Filters/FilterSlice.ts new file mode 100644 index 0000000..23f8e9f --- /dev/null +++ b/src/features/Board/Filters/FilterSlice.ts @@ -0,0 +1,35 @@ +import { createSlice } from '@reduxjs/toolkit'; +import { Ifilters } from '../types'; + +const initialState: Ifilters = { + searchTerm: '', + userIds: [], + myOnly: false, + recent: false, +}; + +const filterSlice = createSlice({ + name: 'board/filter', + initialState, + reducers: { + setSearchTerm: (state, action) => { + console.log('action', action); + state.searchTerm = action.payload; + }, + setUserIds: (state, action) => { + state.userIds = action.payload; + }, + setMyOnly: (state, action) => { + state.myOnly = action.payload; + }, + setRecent: (state, action) => { + state.recent = action.payload; + }, + setClearAll: () => initialState, + }, +}); + +export const { setSearchTerm, setUserIds, setMyOnly, setRecent, setClearAll } = + filterSlice.actions; + +export default filterSlice.reducer; diff --git a/src/features/Board/Filters/Styles.ts b/src/features/Board/Filters/Styles.ts new file mode 100644 index 0000000..399ff30 --- /dev/null +++ b/src/features/Board/Filters/Styles.ts @@ -0,0 +1,73 @@ +import { styled } from '@mui/material/styles'; + +import { color, font, mixin } from 'shared/utils/styles'; +import { InputDebounced, Button } from 'shared/components'; +import { Avatar } from '@mui/material'; + +export const Filters = styled('div')( + () => + ` + display: flex; + align-items: center; + margin-top: 24px; +`, +); + +// export const SearchInput = styled(InputDebounced)(` +// margin-right: 18px; +// width: 160px; +// `); + +export const Avatars = styled('div')( + () => ` + display: flex; + flex-direction: row-reverse; + margin: 0 12px 0 2px; +`, +); + +export const AvatarIsActiveBorder = styled('div')( + ({ theme, props }) => ` + display: inline-flex; + margin-left: -2px; + border-radius: 50%; + transition: transform 0.1s; + cursor: pointer; + user-select: none; + box-shadow: 0 0 0 4px ${theme.colors.primary} + ${(props) => + props.isActive && `box-shadow: 0 0 0 4px ${theme.colors.primary}`} + &:hover { + transform: translateY(-5px); + } +`, +); + +export const StyledAvatar = styled(Avatar)( + () => ` + box-shadow: 0 0 0 2px #fff; +`, +); + +// export const StyledButton = styled(Button)( +// () => ` +// margin-left: 6px; +// `, +// ); + +export const ClearAll = styled('div')( + () => ` + height: 32px; + line-height: 32px; + margin-left: 15px; + padding-left: 12px; + border-left: 1px solid #dfe1e6; + color: #42526E; + font-size: 14.5px; + cursor: pointer; + user-select: none; + &:hover { + color: #5E6C84; + } +`, +); diff --git a/src/features/Board/Filters/index.tsx b/src/features/Board/Filters/index.tsx new file mode 100644 index 0000000..1096c9f --- /dev/null +++ b/src/features/Board/Filters/index.tsx @@ -0,0 +1,148 @@ +import React, { useCallback, useEffect, useState } from 'react'; +import { InputAdornment, ToggleButton } from '@mui/material'; +import SearchIcon from '@mui/icons-material/Search'; +import { debounce, xor } from 'lodash'; + +import { ClearAll, Filters } from './Styles'; + +import TextFieldWrapper from 'shared/components/TextFieldWrapper'; +import AvatarGroupWrapper, { + type AvatarPropsExtended, +} from 'shared/components/AvatarGroupWrapper'; +import { useAppDispatch, useAppSelector } from 'app/hooks'; +import { + setClearAll, + setMyOnly, + setRecent, + setSearchTerm, + setUserIds, +} from './FilterSlice'; + +const ProjectBoardFilters: React.FC = () => { + const dispatch = useAppDispatch(); + const { filterBar, board } = useAppSelector((state) => state); + const { searchTerm, userIds, myOnly, recent } = filterBar; + + const [userInput, setUserInput] = useState(searchTerm); + const [formattedAvatarData, setFormattedAvatarData] = useState< + AvatarPropsExtended[] + >([]); + + useEffect(() => { + if (!searchTerm) { + setUserInput(''); + } + if (userIds && !userIds.length) { + setFormattedAvatarData((prev) => { + const data = [...prev]; + data.map((d) => (d.selected = false)); + return data; + }); + } + }, [searchTerm, userIds]); + + useEffect(() => { + if (board.project) { + const { users, admins } = board.project; + const allUsers = [...users, ...admins]; + setFormattedAvatarData(() => { + return allUsers.map((d) => ({ + email: d.email, + key: d._id, + name: d.firstName, + src: d.imageUrl, + selected: false, + })); + }); + } + }, [board.project]); + + const handleSearchChange = useCallback( + debounce((value) => { + dispatch(setSearchTerm(value)); + }, 500), + [], + ); + + const handleUserSelect = (avatar: AvatarPropsExtended) => { + dispatch(setUserIds(xor(userIds, [avatar.key]))); + setFormattedAvatarData((prev) => { + const data = [...prev]; + data.map((d) => { + if (d.key === avatar.key) { + d.selected = !d.selected; + } + }); + return data; + }); + }; + + const areFiltersCleared = + !searchTerm && userIds.length === 0 && !myOnly && !recent; + + return ( + + + + + ), + }} + value={userInput} + onChange={(e) => { + setUserInput(e.target.value); + handleSearchChange(e.target.value); + }} + /> + + { + dispatch(setMyOnly(!myOnly)); + }} + sx={{ + '&': { + border: 'none', + ml: 1, + p: 1, + }, + }} + > + Only My Issues + + { + dispatch(setRecent(!recent)); + }} + > + Close to Deadline + + + {!areFiltersCleared && ( + dispatch(setClearAll())}>Clear all + )} + + ); +}; + +export default ProjectBoardFilters; diff --git a/src/features/Board/Header/index.tsx b/src/features/Board/Header/index.tsx new file mode 100644 index 0000000..94fa21d --- /dev/null +++ b/src/features/Board/Header/index.tsx @@ -0,0 +1,26 @@ +import { Box, Typography, Button } from '@mui/material'; +import GitHubIcon from '@mui/icons-material/GitHub'; + +const ProjectBoardHeader = ({ name = 'Kanban board' }) => ( + + + + {name} + + + + + +); + +export default ProjectBoardHeader; diff --git a/src/features/Board/Lists/List/Issue/Styles.ts b/src/features/Board/Lists/List/Issue/Styles.ts new file mode 100644 index 0000000..edb970f --- /dev/null +++ b/src/features/Board/Lists/List/Issue/Styles.ts @@ -0,0 +1,57 @@ +import { HTMLAttributes } from 'react'; +import { styled } from '@mui/material/styles'; +import { Link } from 'react-router-dom'; +import { Avatar, Box } from '@mui/material'; + +export const IssueLink = styled(Link)` + display: block; + margin-bottom: 5px; +`; + +// interface IIssueProps extends HTMLAttributes { +// isBeingDragged: boolean; +// } + +export const Issue = styled(Box)( + ({ theme }) => ` + padding: 10px; + border-radius: 3px; + background: #fff; + box-shadow: 0px 1px 2px 0px rgba(9, 30, 66, 0.25); + transition: background 0.1s; + cursor: pointer; + user-select: none; + @media (max-width: 1100px) { + padding: 10px 8px; + } + &:hover { + background: ${theme.colors.backgroundLight}; + } +`, +); + +export const Title = styled('p')` + padding-bottom: 11px; + font-size: 15; + margin: 0px; + @media (max-width: 1100px) { + font-size: 14.5; + } +`; + +export const Bottom = styled('div')` + display: flex; + justify-content: space-between; + align-items: center; +`; + +export const Assignees = styled('div')` + display: flex; + flex-direction: row-reverse; + margin-left: 2px; +`; + +export const AssigneeAvatar = styled(Avatar)` + margin-left: -2px; + box-shadow: 0 0 0 2px #fff; +`; diff --git a/src/features/Board/Lists/List/Issue/index.tsx b/src/features/Board/Lists/List/Issue/index.tsx new file mode 100644 index 0000000..03d0ffd --- /dev/null +++ b/src/features/Board/Lists/List/Issue/index.tsx @@ -0,0 +1,90 @@ +import React from 'react'; +import { Draggable } from 'react-beautiful-dnd'; + +import { + ArrowDownward as LowPriorityIcon, + ArrowUpward as HighPriorityIcon, +} from '@mui/icons-material'; + +import { Box } from '@mui/material'; + +import { + IssueLink, + Issue, + Title, + Bottom, + Assignees, + AssigneeAvatar, +} from './Styles'; +import { useAppSelector } from 'app/hooks'; +import { CardPriority } from 'shared/constants/card'; + +const ProjectBoardListIssue = ({ card, index }) => { + const allUsers = useAppSelector((state) => { + return state.board.allUsers; + }); + + const assignees = allUsers.find((user) => user._id === card.assignee) || []; + + const renderPriorityIcon = (priority) => { + switch (priority) { + case CardPriority.LOW: + return ( + theme.colors.primary }} /> + ); + case CardPriority.HIGH: + return ( + theme.colors.danger }} /> + ); + default: + return ( + theme.colors.warning }} /> + ); + } + }; + + return ( + + {(provided, snapshot) => ( + + + {card.title} + + +
{renderPriorityIcon(card.priority)}
+ + {[assignees].map((user) => ( + + ))} + +
+
+
+ )} +
+ ); +}; + +export default ProjectBoardListIssue; diff --git a/src/features/Board/Lists/List/Styles.ts b/src/features/Board/Lists/List/Styles.ts new file mode 100644 index 0000000..427e622 --- /dev/null +++ b/src/features/Board/Lists/List/Styles.ts @@ -0,0 +1,35 @@ +import { styled } from '@mui/material/styles'; + +export const List = styled('div')( + ({ theme }) => ` + display: flex; + flex-direction: column; + margin: 0 5px; + min-height: 400px; + width: 25%; + border-radius: 3px; + background: ${theme.colors.backgroundLightest}; +`, +); + +export const Title = styled('div')( + ({ theme }) => ` + padding: 13px 10px 17px; + text-transform: uppercase; + color: ${theme.colors.textMedium}; + font-size: 12.5; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; +`, +); + +export const IssuesCount = styled('span')` + text-transform: lowercase; + font-size: 13; +`; + +export const Issues = styled('div')` + height: 100%; + padding: 0 5px; +`; diff --git a/src/features/Board/Lists/List/index.tsx b/src/features/Board/Lists/List/index.tsx new file mode 100644 index 0000000..2b61fd2 --- /dev/null +++ b/src/features/Board/Lists/List/index.tsx @@ -0,0 +1,72 @@ +// import moment from 'moment'; +import { Droppable } from 'react-beautiful-dnd'; + +import { CardStatusCopy } from 'shared/constants/card'; +// import Fuse from 'fuse.js'; +// import { isAfter, subDays } from 'date-fns'; + +import Issue from './Issue'; +import { List, Title, IssuesCount, Issues } from './Styles'; +import { parseISO, isWithinInterval, endOfDay, addDays } from 'date-fns'; +import { intersection } from 'lodash'; + +const ProjectBoardList = ({ status, cards = [], filters, currentUserId }) => { + const filteredCards = filterCards(cards, filters, currentUserId); + + return ( + + {(provided) => ( + + + {`${CardStatusCopy[status]} `} + <IssuesCount>{filteredCards.length}</IssuesCount> + + + {filteredCards.length + ? filteredCards.map((card, index) => ( + + )) + : null} + + {provided.placeholder} + + + )} + + ); +}; + +const filterCards = ( + listCards: any, + filters: Ifilters, + currentUserId: string, +) => { + const { searchTerm, userIds, myOnly, recent } = filters; + let cards = listCards; + + if (searchTerm) { + cards = cards.filter((card) => + card.title.toLowerCase().includes(searchTerm.toLowerCase()), + ); + } + if (userIds.length > 0) { + cards = cards.filter( + (card) => intersection([card.assignee], userIds).length > 0, + ); + } + if (myOnly && currentUserId) { + cards = cards.filter((card) => [card.assignee].includes(currentUserId)); + } + if (recent) { + cards = cards.filter((card) => + isWithinInterval(parseISO(card.estimatedDate?.toString() || ''), { + start: new Date(), + end: endOfDay(addDays(new Date(), 2)), + }), + ); + } + + return cards; +}; + +export default ProjectBoardList; diff --git a/src/features/Board/Lists/ListsSlice.ts b/src/features/Board/Lists/ListsSlice.ts new file mode 100644 index 0000000..2251917 --- /dev/null +++ b/src/features/Board/Lists/ListsSlice.ts @@ -0,0 +1,47 @@ +import { createAsyncThunk, createSlice } from '@reduxjs/toolkit'; +import { Icard } from 'app/types'; +import { request } from 'app/axios'; + +export const fetchCards = createAsyncThunk('Lists/fetchCards', async () => { + const id = '6412ea879a7101f9f0017bad'; + return request + .get(`/api/v1/projects/${id}/cards`) + .then(({ data: { data } }) => data.data); +}); + +interface IinitialState { + cards: Icard[]; + loading: boolean; + error: string; +} + +const initialState: IinitialState = { cards: [], loading: false, error: '' }; + +const listSlice = createSlice({ + name: 'lists', + initialState, + reducers: { + // setTitle: (state, action) => { + // state.title = action.payload; + // }, + }, + extraReducers: (builder) => { + builder.addCase(fetchCards.pending, (state) => { + state.loading = true; + }); + builder.addCase(fetchCards.fulfilled, (state, action) => { + state.loading = false; + state.cards = action.payload; + state.error = ''; + }); + builder.addCase(fetchCards.rejected, (state, action) => { + state.loading = false; + state.cards = []; + state.error = action.error.message || 'Something went wrong'; + }); + }, +}); + +// export const { setTitle } = listSlice.actions; + +export default listSlice.reducer; diff --git a/src/features/Board/Lists/Styles.ts b/src/features/Board/Lists/Styles.ts new file mode 100644 index 0000000..acefca2 --- /dev/null +++ b/src/features/Board/Lists/Styles.ts @@ -0,0 +1,6 @@ +import { styled } from '@mui/material/styles'; + +export const Lists = styled('div')` + display: flex; + margin: 26px -5px 0; +`; diff --git a/src/features/Board/Lists/index.tsx b/src/features/Board/Lists/index.tsx new file mode 100644 index 0000000..2a8329d --- /dev/null +++ b/src/features/Board/Lists/index.tsx @@ -0,0 +1,111 @@ +import { DragDropContext, DraggableLocation } from 'react-beautiful-dnd'; +// import { +// moveItemWithinArray, +// insertItemIntoArray, +// } from 'shared/helpers/common'; +import { CardStatus } from 'shared/constants/card'; + +import List from './List'; +import { Lists } from './Styles'; +import React, { useEffect, useState } from 'react'; +import { useAppDispatch, useAppSelector } from 'app/hooks'; +import { fetchCards } from './ListsSlice'; + +import { Icard } from 'app/types'; +import { Ifilters } from 'features/Board/types'; +import type { DropResult } from 'react-beautiful-dnd'; + +interface IlistCardsMap { + [k: string]: Icard[]; +} + +const ProjectBoardLists = () => { + const dispatch = useAppDispatch(); + const { filterBar: filters, card, auth } = useAppSelector((state) => state); + + const [filteredListCardsMap, setFilteredListCardsMap] = + useState(null); + + useEffect(() => { + dispatch(fetchCards()); + }, []); + + useEffect(() => { + let allCards = card.cards; + if (allCards && allCards.length) { + const arrangedCards = getArrangedListCards(allCards); + setFilteredListCardsMap(arrangedCards); + } + }, [card.cards]); + + const handleIssueDrop = ({ + draggableId, + destination, + source, + }: DropResult) => { + if (!isPositionChanged(source, destination)) return; + const issueId = Number(draggableId); + setFilteredListCardsMap((prev) => getNewState(prev, destination, source)); + // call api to update + // revert if api fails + }; + + return ( + + + {Object.values(CardStatus).map((status) => ( + + ))} + + + ); +}; + +const getArrangedListCards = (cards: Icard[]) => { + const map: IlistCardsMap = Object.fromEntries( + Object.values(CardStatus).map((status) => [status, []]), + ); + cards.forEach((card) => { + const status = card.status || CardStatus.BACKLOG; + if (status in map) { + map[status].push(card); + } + }); + + return map; +}; + +const isPositionChanged = ( + destination: DraggableLocation | null | undefined, + source: DraggableLocation, +) => { + if (!destination) return false; + const isSameList = destination.droppableId === source.droppableId; + const isSamePosition = destination.index === source.index; + return !isSameList || !isSamePosition; +}; + +const getNewState = ( + prevState: IlistCardsMap, + destination: DraggableLocation, + source: DraggableLocation, +) => { + const allCardsInSource = prevState[source.droppableId], + allCardsInDestination = prevState[destination.droppableId], + draggedCard = { ...allCardsInSource[source.index] }; + allCardsInSource.splice(source.index, 1); + if (destination.droppableId === source.droppableId) { + allCardsInSource.splice(destination.index, 0, draggedCard); + } else { + allCardsInDestination.splice(destination.index, 0, draggedCard); + } + return { ...prevState }; +}; + +export default React.memo(ProjectBoardLists); diff --git a/src/features/Board/index.tsx b/src/features/Board/index.tsx new file mode 100644 index 0000000..4964e17 --- /dev/null +++ b/src/features/Board/index.tsx @@ -0,0 +1,130 @@ +import React, { useEffect } from 'react'; +// import { Route, useRouteMatch, useHistory } from 'react-router-dom'; + +import Breadcrumbs from 'shared/components/Breadcrumbs'; +import { Box, CircularProgress, useTheme, Backdrop } from '@mui/material'; + +import Header from './Header'; +import Filters from './Filters'; +import { useAppDispatch, useAppSelector } from 'app/hooks'; +import { fetchProject } from './BoardSlice'; +// import Lists from './Lists'; +// import IssueDetails from './IssueDetails'; + +import type { IProjectBoardProps as Props } from './types'; +import PageError from 'shared/components/PageError'; +import ProjectBoardLists from './Lists'; + +//! remove later +const project = { + name: 'singularity 2.0', + users: [ + { + _id: '641414a2668355902630d0a3', + firstName: 'boby', + lastName: 'johnson', + email: 'boaloysius+1@gmail.com', + imageUrl: 'https://randomuser.me/api/portraits/men/60.jpg', + }, + { + _id: '641414a2668355902630d0a4', + firstName: 'boby2', + lastName: 'johnson2', + email: 'boaloysius+1@gmail.com', + imageUrl: 'https://randomuser.me/api/portraits/men/60.jpg', + }, + { + _id: '641414a2668355902630d0a5', + firstName: 'boby', + lastName: 'johnson3', + email: 'boaloysius+1@gmail.com', + imageUrl: 'https://randomuser.me/api/portraits/men/60.jpg', + }, + { + _id: '641414a2668355902630d0a6', + firstName: 'boby', + lastName: 'johnson3', + email: 'boaloysius+1@gmail.com', + imageUrl: 'https://randomuser.me/api/portraits/men/60.jpg', + }, + { + _id: '641414a2668355902630d0a7', + firstName: 'boby', + lastName: 'johnson3', + email: 'boaloysius+1@gmail.com', + imageUrl: 'https://randomuser.me/api/portraits/men/60.jpg', + }, + ], +}; + +const ProjectBoard: React.FC = () => { + const theme = useTheme(); + + const boardState = useAppSelector((state) => state.board); + const dispatch = useAppDispatch(); + + useEffect(() => { + dispatch(fetchProject()); + }, []); + + if (boardState.loading) { + return ( + theme.zIndex.drawer + 1, + }} + open={true} + > + + + ); + } + + if (boardState.error) { + return ; + } + + return ( + + +
+ + + + {/* + ( + history.push(match.url)} + renderContent={(modal) => ( + + )} + /> + )} + /> */} + + ); +}; + +export default React.memo(ProjectBoard); diff --git a/src/features/Board/types.ts b/src/features/Board/types.ts new file mode 100644 index 0000000..c7e2a42 --- /dev/null +++ b/src/features/Board/types.ts @@ -0,0 +1,29 @@ +import { Iproject, Iuser } from 'app/types'; + +export interface Iboard { + title: string; + project: Iproject | null; + loading: boolean; + error: string; + allUsers: string[]; +} + +export interface Ifilters { + searchTerm: string; + userIds: Array; + myOnly: boolean; + recent: boolean; +} + +export interface IProjectBoardProps { + project: any; + fetchProject: any; + updateLocalProjectIssues: any; +} + +export interface IProjectBoardFiltersProps { + projectUsers: Iuser[]; + defaultFilters: any; + filters: any; + mergeFilters: any; +} diff --git a/src/features/auth/authSlice.ts b/src/features/auth/authSlice.ts index 411a666..087b925 100644 --- a/src/features/auth/authSlice.ts +++ b/src/features/auth/authSlice.ts @@ -1,7 +1,11 @@ import { createSlice } from '@reduxjs/toolkit'; import type { PayloadAction } from '@reduxjs/toolkit'; -const initialState: any = {}; +const initialState: any = { + user: { + id: '641138545ab8c5b59a359637', + }, +}; export const authSlice = createSlice({ name: 'user', diff --git a/src/features/home/index.tsx b/src/features/home/index.tsx index d58c7ad..0f968d0 100644 --- a/src/features/home/index.tsx +++ b/src/features/home/index.tsx @@ -2,6 +2,7 @@ import { Outlet, useLocation } from 'react-router-dom'; import { Box, Container, Grid, styled } from '@mui/material'; import Hero from './Hero'; import HeroImage from 'app/assets/hero.png'; +import Header from 'shared/components/Header'; const HomeWrapper = styled(Box)( () => ` @@ -22,31 +23,34 @@ function Home() { ); return ( - - - - - hero_image - + <> +
+ + + + + hero_image + - - {content} + + {content} + - - - + + + ); } diff --git a/src/shared/components/AvatarGroupWrapper/index.tsx b/src/shared/components/AvatarGroupWrapper/index.tsx new file mode 100644 index 0000000..09cc153 --- /dev/null +++ b/src/shared/components/AvatarGroupWrapper/index.tsx @@ -0,0 +1,76 @@ +import AvatarGroup from '@atlaskit/avatar-group'; +import { Checkbox, Box } from '@mui/material'; +import type { AvatarProps } from '@atlaskit/avatar-group'; + +export interface AvatarPropsExtended extends AvatarProps { + selected?: boolean; +} + +type Props = { + data: Array; + onAvatarClick: (avatar: AvatarPropsExtended) => void; + maxCount?: number; +}; + +const AvatarGroupWrapper = (props: Props) => { + const { data = [], maxCount = 3, onAvatarClick } = props; + + return ( + { + onAvatarClick(data[index]); + }} + size="large" + overrides={{ + AvatarGroupItem: { + render: (Component, props: any, index) => { + const avatarItem = ; + return ( + +
{avatarItem}
+
+ onAvatarClick(data[index])} + color="primary" + checked={props.avatar.selected} + required + /> +
+
+ ); + }, + }, + Avatar: { + render: (Component, props: AvatarPropsExtended, index) => { + const avatarItem = ; + return ( + + {avatarItem} + + ); + }, + }, + }} + /> + ); +}; + +export default AvatarGroupWrapper; diff --git a/src/shared/components/Breadcrumbs/Styles.ts b/src/shared/components/Breadcrumbs/Styles.ts new file mode 100644 index 0000000..bba458c --- /dev/null +++ b/src/shared/components/Breadcrumbs/Styles.ts @@ -0,0 +1,15 @@ +import { styled } from '@mui/material/styles'; + +export const Container = styled('div')( + ({ theme }) => ` + color: ${theme.palette.text.primary}, + font-size: 15px, +`, +); + +export const Divider = styled('span')({ + position: 'relative', + top: '2px', + margin: '0 10px', + fontSize: '18px', +}); diff --git a/src/shared/components/Breadcrumbs/index.tsx b/src/shared/components/Breadcrumbs/index.tsx new file mode 100644 index 0000000..ca398de --- /dev/null +++ b/src/shared/components/Breadcrumbs/index.tsx @@ -0,0 +1,19 @@ +import React, { Fragment } from 'react'; +import { Container, Divider } from './Styles'; + +interface IProp { + items: (string | undefined)[]; +} + +const Breadcrumbs: React.FC = ({ items }) => ( + + {items.map((item, index) => ( + + {index !== 0 && /} + {item} + + ))} + +); + +export default Breadcrumbs; diff --git a/src/shared/components/ButtonWrapper/index.tsx b/src/shared/components/ButtonWrapper/index.tsx index f9e4fd3..b07afd3 100644 --- a/src/shared/components/ButtonWrapper/index.tsx +++ b/src/shared/components/ButtonWrapper/index.tsx @@ -1,23 +1,27 @@ import React from 'react'; import { Button } from '@mui/material'; +import type { ButtonProps } from '@mui/material/Button'; import LoadingButton from '@mui/lab/LoadingButton'; -type Props = any; // ExtendButtonBase; +interface IProps extends ButtonProps { + children: React.ReactNode; + loading?: boolean; +} const style = { margin: '15px 0px', padding: '10px', }; -const ButtonWrapper: React.FC = (props) => { +const ButtonWrapper: React.FC = (props) => { const { children, loading, ...buttonProps } = props; return loading ? ( Loading... diff --git a/src/shared/components/PageError/Styles.ts b/src/shared/components/PageError/Styles.ts new file mode 100644 index 0000000..d46d639 --- /dev/null +++ b/src/shared/components/PageError/Styles.ts @@ -0,0 +1,57 @@ +import { styled } from '@mui/material/styles'; +import BugReportIcon from '@mui/icons-material/BugReport'; +import imageBackground from './assets/background-forest.jpg'; + +export const ErrorPage = styled('div')` + padding: 64px; +`; + +export const ErrorPageInner = styled('div')( + ({ theme }) => + ` + // margin: 0 auto; + margin-left: ${theme.sidebar.width}; + max-width: 1440px; + padding: 200px 0; + background-image: url('${imageBackground}'); + background-position: 50% 50%; + background-repeat: no-repeat; + background-size: cover; + background-color: ${theme.colors.backgroundLight}; + + @media (max-height: 680px) { + padding: 140px 0; + } +`, +); + +export const ErrorBox = styled('div')( + ({ theme }) => ` + position: relative; + margin: 0 auto; + max-width: 480px; + padding: 32px; + border-radius: 3px; + border: 1px solid ${theme.colors.borderLight}; + box-shadow: 0 1px 0 rgba(0, 0, 0, 0.25); + background: rgba(255, 255, 255, 0.9); +`, +); + +export const StyledBugIcon = styled(BugReportIcon)( + ({ theme }) => ` + position: absolute; + top: 32px; + left: 32px; + font-size: 30px; + color: ${theme.palette.primary.main}; +`, +); + +export const Title = styled('h1')( + ({ theme }) => ` + margin-bottom: 16px; + padding-left: 42px; + font-size: 29; +`, +); diff --git a/src/shared/components/PageError/assets/background-forest.jpg b/src/shared/components/PageError/assets/background-forest.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ee8c28310d5915372dca612f4399406e234cc7b3 GIT binary patch literal 564518 zcmbq*d0f)T`}o^+)3z+zPH$@6vaHlJH4n7SO}AWS%aqiV%7YS*^1_3|w$cud+VaSY z%9NCl%#^&q@+=j+@y7B1L`4NuQ1FNCRr~q=_ZxgM&+t6+%ro=Md*1Ur^NcG!E5pF1 zleQ;p0XaDUkdu9Ym44s`uvV77Tl?L*b>D5+sI+mzmd%?sZQi1}ZM*EFc|c>QhV1Wv zj{cq>_vq``njSi2YJ2MEqd%Xzc=qf?R5@1o0=6M-B?$@DIIX~6>LRq>N~YgZlh=0GJUT>EXzqE_t9n!1w`nN<9eZ1u7f6-q+48HXd)<{;ao=GYU z>q0v5vr|RRyrk6(n}!sr3Hy1N72py8Y(qV0WV~&w^U%1=XR%8vhQbFSK7?W$6)rlp zR8ePS1%UFBK183p6NVQ+T6ccIUu^}@8V;wVva3-$YS@_H7lyw;{t3$M^H!w=djkgY za`zgQ4#j&ZDXEeHtOwXO04ZGH$tS6lzC$ER3o;!i^Vu zvf$)_mjw3+(i{?c*TED%W$p4sGjjDJdJ40h7j5nIX8$7g&Io#h^S@%q8>WP09!d!| z1ZotHo>w(gx)6UMRxbWOYT7kUK_a{7myz$n;3Urm;?&i$O2}hL^%u?k1Ac=`Tb9_O z27IE-!~Dmxct5#}liH|}D3*9nRAAS@rHdX3R?cP( z!B&aqrjfxs%o_;Fs}^X-#dr1S&|L| z$~*WFqpAnV&63@G<*cZU$Imh(KFuN|oz$8?eQ7kfD*MG#r-5mS-7_^U(1;-`-I?Vz zg@b<4xEzZj?@vCMs4>WWV?IbK6Yu;2`6sB9`^a12s9da}&%GM?UH7jmsVEs-i2a&u zD+>NTAd2KO7X;(HrZ}MQvv?zA3%6swrutlxPnxp=WyS?(>vJFuGo+vyNk9MuAB_zY zA#AD!S<@3p2?)m0sF=_1E;R8Ik#f;omh}%gf+TOiu4Xxe=FZORP0bZi3nbsofwJdx z>!}k%HP^;4K`a3nqMZTDWgiMGRHdJ+@=V3rJz|wil%uRKECk(I=1zb@-+Up^M(Dj6 zPiO@=k{vKt5KfjRbPFti%aKF$vtJN>20xsD@AL-FA9}D;Nh!v_Ktbiuf2Xh4FlI+p z|Kt_am|HTf360B+V^81vFPqi!Rg6vD+#rNH8=dXNp+HmVq8(P|An&COE5QC4Py3F6 zO#cGYF%`Q_I!v*3z6jeOZ4_tx^J zxIB&8J1f2$nnuXVKu$XBb`xtt@}tq9n-kJlcFY%oB-JeQEOHwe*^r+IRZ3!ry>4iU z*$%XF_m@Pg^h!-;aP6HywUP{RUhcZmq1gXCvBs64hQcl?&RLATLhV|nvouzK3iQs^ zy8lhVRz@wuNbIp`g*;|GC8Xst<~7&q)W^lG;*ChSGv)))Ph?SXK1@nx%wn9Jux!sX zOT|W!djH#vL0OXT1lhhr4P(+@!zLu4sq0Cir{(*=4w*qGa@q-)7%-nRm)D+<1QEXA7#c;PDqktDu7S12aQFL4K#9 zT#P*6{WezRZM?x(G;*{&${=}c>x|qs|+c7LfP&>rdlzjyMuL%Dv9G2R@9T>x0 z8;}$6-}}9zGY(om5WP9|4i{K;d!jPCu&AnU>fN{G`3h-&n@C^ztx%Q8&%UHO@T&av z3gDo)+TUGbqro-U6#v$)#L|W0S@a9LR=eg9aaEz?jj-1TCxyJ2)adR7iT-`j!j5i< zJ?aZ7l$B=!Hcmezmn`*_moLzf_AvOg){8F)Rzdj#EHn6lM@mXB&%eK?6jQBo-q5gK z_H195SNe()WV%St6)UzsaCAmOAD%(;9Fz9s`0t75!oOf z8hMX4KMG1K3w5p#*EBAZ-H))uN+QXWhv(0)U-KwcC&`k`k}>tt(5peO1leA-zpk<5 zoa9h{+o0Ss5P^V-O$QS|cTo!=js+F&p$I?d#)il3-EHmMnUb(#A6J1E&P|~!-9nnf z5HrDZJTJk~FXXVgFf%li{9-{QzLMNpz5*1W6^6e+uYyJo4B>lzy%u9&lyVf1S5Q$J zHFz6i;H6+t{UzZBnBp8eENX~5o^9fQ&E-Z=vRNRz>1@Hc6eEVVAN`W{Pk4jA1-Du; zYx%un*AZXM*wYw>>dY0Se2Z2iKKi!`4UV>QqRu{a{q+l#OxsCu8T zRyBAVe&vzGnUh&L3B9h6UI4rp>XC)+CO1A=f~?R z^=mDKl69}8EvzE_^+L~vSX{Ry>4T&}pJ#E7o)*zhsL#V$^mPR8x@)rQ`R^@6&0G33 zYG(H-s<<-}bR)!gHebAjqZNI(Z#oi2Ps@7_o67mPVDVq89Fz7)BOBv*tRw zQc|)PUUb=>CR}tA(uX8lp8YG(491)HL=zEb?kOw1&KY~+m+Af83JELwwaQ9P= zKi@Prr*+O!G6l^YkZ4(*n)ADK(>hWd08;yO>9E;daq6@L!B}KwOF~|5jZ{{x&2ckv zR}=aT^)imaFGk(9kS(7AlYiP)H2tK7tT^Z0yx0BwTsi2n7>*NG|AYMtpanM<-}7!f zZvZsylq~~F!2A0#DoPg*czs1E5`(gWR0TWim5pyJGS1A7Bs0p?{A)8 z=GJB+heGtG1z3(7^T1r^DW#_1tjPMR1AYiZF9{zwm7VimY=zfD=`Gmc$m3-3Pzc*d zgwLIWJr?6KWt$&G7R)-wkzysBv^r!<>AtrKVsSNI$g6N8TuSV&((qWP8~S42twP}U zpf~TnU>p!Ss%>ba#6CkNsZ#Rr6J^$ZB}>TAa}6-vUmdxvOlLPTM@!r z0Wzfxe0A&z(F$-K^9Yni7(p0``DYYRcU0v9J^q;2w1?2fST!Ym%E)V_c97%)LZCn~Q@}#5c{zL*-AN2!-T!b2<$AB*0SfMycIs{d|Z-k#6g|DYtyO&Q)UX0SG#IZNd#S=^KCW~E51_BTGZRSk<>qL>^~7BtKQgX2zbkuL4#_;MpadBgBq0@rLXr! z3gq=wpCVglw_oa_=M997u|9IppfUkQezdO-dvvMlA0hr0MwTm(nyj4FjW6S|eW(Q< z)2gi;<(M)Rb)U#Pa3;Q7Hg2*+_)0a~chi^_!^?pmfhsA;an41pTR=jOaLM4}SG zqh~B3xAnAQVJQoHdiXIOs4Q6MLd{g=#EuGJlF;;t1ywabq-S%obS zZzAv)_H6$?;qG>)VzKh)1w|EjoB2ouXjD?Ukoibnd(Tg?2KBPX=&LkK1VuY5)HXJKu`MkIFF-TeD*5|%w=6gOeAYaA)r0*h-pCZ*&Vd+ENO zhl|OGxKR`>*Y!r|qSam1YWFGd3J}f5^(>iFoJPKHKO9(Km6YR|Cu!tDTRWezIe}A` z`HO2AoJbKPug^HJSipL=i0`Agj&jf(Q4SnNk(EQb zg@0|F73IgXU9NYC-ss|0A5N3|%c#H2U=-5*vmPFMpA+bAZ72TIa+Kd=t7NFEq#|=k zDZNrs`uZgz>*x653XpngAu+4M&S+#g5vgw9y9Dy${vX2ujLwCYE+eyNmNG@0-k|(A z(1U?7NLK)dIVNyOOreyVZ84`bHB0{xwpc$xRkVJ%E4w}(#Ob>Z9b0{sfBkU3iVnZX2Af4_GVc2Kso zulgTx6!-JDS9AnK=`Gk-yc(I{iv~RPWUhj%Lofd%@sna(6T)bnem8ys-#RO#oX~VS zvS!{#zznN`Htp@^{^jgYS|wLikUwx;wzPbeO&r$z_&`tZ6clg$T|6 zG^;1bNbm0x_unVjoX^pjf)EmhG3 z?bI<}{TGw}&Bjr2*Aru>^SYB&V`-t<5Q~%P;W=j}YN97Ra|UAmmmUC_%^dcdn&>jn zwta08`bHe?mjOFIV|wXW7{X4V*e-`37h$OUHJ(i{+}l_*da+!iP{-*>!wA2H!U}$q zp=V*2aYr|BDq4-y)?2EPxKo>U_@k{9O#sbS9Q%ioxU-yAAI9aQG+d$J{&!@I#uMtUOL#mz11v) zUHz-_|7LQ0X57W-440u-g+2y}uNTU!sJt^GThk?jiK##NeO*TjKDw!MAm^NtZt`{e z8-wj=`6^4)X5mo<{tIsL2pyM9Gr=zW$-BC1J)Tmj@HGETlsPJwtep z+?-q@p$z$EL@+`k!*yr}#f+zm=;dYKDma5e14Pz!62~sfLf?5XbW72ZNDt+w68ibS zWRS02W+e@_#n} z6`+0*=i4!NPSdk6g%kumW=V@H>vqbja^IhDj`AZ<_~2s{1l&8sU&cN~BdUh2G>d8b zb3kX8&dc#vfHhBg1fIv3SrYqqA(HXeRS=TE{pepEQG@BuwU*cJbbF5QaBN`19$i_~ zz{2M-JMtNSnoQr2z=Ja&^X}($`@L&+JO2!9>G8Hr?}(9mus-l+_6Xba#$TNNkL*z6 zm{|9<1y)}~GIdG(!!x5z5M}WP7x{PNUsRDJeyW68IGDU9b^9~vq}+`Gk;QO(#1v*f z2YhuFi*q8HkNj#?GXGc(*0`M1U*YM_M@}lMi|B%&qQy8GI`ix8U{$mW@3fk#rl)9E>3C z9u)txS=CakD=SAkdg6SW5gzMWGp@t!D};%|KpXS3%$B%X^QdjN+6!B*ts{L9m|DWLnGQ2hv;xV zHB%5(uD*1*!)zp@yS(bBEW+U&J(x~a&Ou_OfO1`+J-Pzu=e_7!_hfPfuq(4pl_;{O zVvaDi1Xw7_hKq*8i?NuH*|xvrkiRy=1L@n5Nz}4HO6bA%!B%Q&A$Pi|O{~SpdDA^Q zSJ|L=pM$BWT&0(Lx41>&!q3M`8MnNAe?9$N-n6G?cZl~^TcGHO*M*c7fQ>l%neUwE zo+uD>lpB5JbMdP$xqQ~*a+NZewbRSNV=9mCWvDbS(ZLq~EzuXmyT+^{Ym!6L`q~&{ zZ2$TBfY{1Z?g`j&0rr_Zzd_k$I(S>hw6$%FJaiOxdP0gESgMN~4{)q+-pfd#g)WxQ z@bK$7Jque?WoKFfLJkAyHW-ThS_oQ+*+ocyRa%KnV1638**A5N(#Z7WZdhGDTpI72t{Z{O8}l`eF=6kc>&X z_$Jm(w0)VzSy)>|5t%mP&aAlIQy}vCLAATHQ-BTQd{s$SkgI3nYETS>eO4K!qc8fWSj_6|P@yNkN!taW{YV#lkf)?Ma(G?pFX z3O<;|XuqHQQzA8(f{5uZ(0R$%3Q8KUBEQEhOom#)hv&;A8m>^C)P#&b8hk0fAF7U7 zN6Zhe*4YTX`B9{?tu0nHVH@0Qe>f-k=H|LGqOb9lZ<>r=xT3rpf1=3(H8Ub`juUn-2pn=i%;~DfYrt>?yyUTy;zz44YCpx+Y+Fx-)t(Y7& zP->KOh;HVtU#(r{t1k!s4%#sHl;<#vj56R?da%QuY(O9Eta3u*ozvowKN>gFrZG48VT-j63HD*^L<_)$H3ek_$)sPR{wjsw!^_Y+P>X-B|8CQ zF0h7iYQ5gNi9f>4aoEqR956Gq#~hTS>a}7YI2m z_P+i4WAS5%!zm5^(j$Z;S_ow&}U+^P3r)&M{NB%r)F7ginz`{!P#jZvm16|;lhZZihWAd;aH34 z8EYWc3{Qm{M-9|d@|aH8_DD}k{ozB!9%iM{63DJv627fxsgO68z|hOTxV25pDE)*| z?wgDTLEcRbZ<8MHa^6VlqXczGloZE7`objgs)UNEqtP>KtkWt-+_aXc74u1Q{Bs@~ zqLIRq$&NT{oF*DuwuGZcUFGojuXX4HOV(}GtJSnj$DA+48((!P^4F%8uH)XEyLaQ2 zo%^~R@9L8uUS{>C?90z!Ws`%jb;%5bURd?_vqj*m~BUX`rr%Te% zktq8SBKXAAW%_-q6sfnr->LdGf>*|Vbqh_cgqx_U4bd<1#?WeLEoK{>g~?Mm>V5tn zFNs3o=N;Y1@^wdwNo+FO`e`ubzNlYd`nFV9HN>D56VDYq1rNzW4J<)kqH(76cSJ!xXo?Uq@q&Cz=yz8RI?X3{^lHJuK5Pd&@mVZIK~oIXW61}Q$q+6)>lU`Z$$P; zV+9WcfIK~dULac)Te6J=Ntr^=H;Oc=)A)0+G7}6j9oE&+iqoq~2yj2F>x37>d+f)Y zM5QZ08(1GP?n!TpSsf>kq3Hg0w>B?`y2rX%GbN~_64TqSAX;@BD>LgcAbU4^2th%g zmsC0WB0Vur4ZSgG-3oxPRu?AyM4tG2sQ<}FB0yQ93b8?q>-u@}RF-fq3UcsCyhl;f z!y$SLtUdHw#PH>Y;0*jUC3)hgsw$xHk4e21iNDTnKzVgVX_-D*8rQP^ z1Pc(_?Rdns8{4Rq%-~o<<64APTMVtk#i(jEPzFl2NgM@$uH^^BsmdUz(CYn@arE=W zu1dPoq)F-SkxIM7&Wex+87>NxWPW?^qE3J+`_t2irvtXBoCndbWe8t zzsi0!E%NFmrW`_y3~ab5DvUGo$`xcwlZy8)e`Jk#B1rj|5`(NWh#j@5QDyuVZ`?fDyruj+87>QQ_`KX(UHzmP;1IMv=_$_{nk8HT?Elx_ zHD~4CgfQ|w(zg-s^oW>Hh}B*HM6QTrM_}@oo1)#)TJFXECSV3kFnz3Siu(*HW;ocav-ckaZEI{S}peAJIW zS!$fWU=3ZQS3{dVuAzG=Ir+VeF|`lvu{nO#GbM`WV(y2>?wpO z&>t_bI2=J48JHG)vtar(fe~mrN4Dn$PTF& zK|AM)g&0De$P=YU0#n;97SErT%e=k^sQEL9Kn@0?T@{Mdt$&-2QB=USEH@9fH%w&2 zth2Tdfhr^_z{i&J}y6x1BUE4d;RiHncgkR3h0H8N6zUfDDk`2994aXGo$V(bE3rxf zVlRg6e4chOVVzlD7kpD!IEFWk(Vo+6Ny1Ai=DKr1Pr+WS6<}-o#}P#9u6bQc((g;D zZ3o|fv~nId8)_Ot!xdCOyA~@{ZelO9(OaIfLXTQ9#}@59jRtb2K~O7e@`$Bx-03X& zAg08snoj0I&-oge5w1))JSo9m8@2!un7};sBp|bE>PjN>&?L6z zu(N1^)e)b|@hRh!nHR-bWZ*H>)A^UfqAK(Q1WmG$)m`M>e{tbqSob-4jvrF`Htqc| z3X;Czjz;t9P>f0_l3V7go|r7S@jC`h3rqtmjv z45a*=;7RoCqEI`dvA@UyL(c=U*jHIzZ}3@ZYFdz+G2@7&r_mej+;@Vqr09nhRS>Wk zSqX@AYQ`$&15M$a==1Uo%Xb^2wQvKLaVc}z$BSrr0k~6YX3)z`ISGz8Utb}-t9vvV z8oG__Ga62d2y0y8^!rFG`H$NwD zqt*c~1m=W)qInA%TI6{oGv3~`M^IteWM+~6@Wb~{HLa-W1bDEAG|sdI+9hy{>Z|0E zUmQY0+;+_9jTfy$%x6TEG#S&}D#Sg#ZLGn%DSr_q369O_n9(5KDdDR)CE4H(S-Ubt zVO3%lw;Tg$h_Q>F9%2-TkhP*{tGgl1m?r{7TBTyQL}P%eEXdO`;vWyL3lZC~J@lKY z7Y7G~Npds#h=oCX3q^j)qEyl_I-oD#{61}5ZT^FL$V2=6if#oZ2ppvN;N2*X1Hqng z?4@eJOBSr$Rc}1`_`}k-VMY7A4)xNmJUqH4IK_Co-*4HpmXep3J2bxSzbImTx8}s` zbkAl=MBX#fqq5c>f%U00*?7w35Rhpirjb2yDl$`lP017{pJnCq0ncWh{UT6iRf$UR zi~9QfY-WlWN}Sigx@IfeVD-XNm6NN78(^uq>vt182M*DwQA627;b_ym=>^{B;u?VuodDTdg>fykSr~0bP5=Cns>jMr6fc7tXhx@0yIW!+ z|Irf>HywrDS8;f1JmFRok$l8-|5KHT zEKBREDnmkaOLz7S_7;@6+Nq&L47Geg1+r=D_p=t~p8~3kOVP>7{N7s>r8FcJWD>eATQ@-?@_} zIy*HlAx=3`Awh`Te9Yi0vIWkA6C?Kt<3L#3dLX$hA-v#OJh9Y96;NUHeArahM2Pmk zqnf#|>)DpR#@?3D{=hxEjz4@7>AgItG%U7QS%J5j-O4n&0nrhkGhv!!VVd$g1e{YgNbK--%NPr z^o(DAH$5GvS0~9jplV00SZB;H%GYuwt?hy!D{QAL^Gn?h3yX8ePu9(niKNQJs?4T+ zgzsYu!SG5x#p02R&Ow}yQ2FVRA)A`WlV;^o5|@b!V+lz)kyIm|q{b>}E^~KUP0oB$ zo(OhX#2P1Cc&4uaTg0u(?@?(IzoaKizSb7YTmmg&1&9)nZ+TQL@UDtFaz2_--S{+^ zX)l({zOaiNXslmK6Q-EK`=^IGgn{dB* zQ#a1GTH(;n`a+{3gNxe_Z3ymf>*{{4Q@r!Le#={o^?CJIpBokL!oq?k1|P3#2y;o$ht^_@BcuK0B^a3?i*ZJDHdvmwYA zVwa?B0oAEdY52lDLqmlt=W9NzPsY82pB)7R{~!lz5u`2Y^kh0V4G=&;Ros7ke zVe`?qf)|4JitOtCsM`jw5@#S~mo#*j;O!XX%*(|2mVV?rD8wn1hNl)69}jPW9odC6 zO=w}mWN!FMBw5twzU^3O&8c2C->)ax?YGQ@^5`8Gb&;#fW4eVoxU)6a{ZVrq};Exca-X0I0n zrrz&x?wjh^Hne@tROm5K?Sg*-(wuK@33R8{47zPh3Z<9fF9)X%@zYko$XYx}1xg z0%w$#Lnpj09<-k*JOlBgY)?Fp(kyr}>Ga``EqQ85HYF}ELS6fcI6+VE@G-O!lMWZA z>GifwwyVpHf}2|e9(wvtSob7mdv9!r!@>lYWxy|=;f9)Z*%}t8UGhEM5|VD#VzulbiQ^;%Ais5tmt4Q3Z-#!Mi6D6?@NWb>w$hG&`S zML*B#AMcyX&WLVXRMyeMzrqt-vJX-wLn7T;-O7^J0Udly#KS%>$akjUW3YoDJZ`DC}+N^@47ARQH1#q^^KM?Mg_l4GQp>@^~^E13l9^3W~21NL%HW)`GbusnD z3jBA`_NQ8VMM>{YCtfO^hCx}V;>jda5n~9wqwCjYK7R^LVX+gHt4oeilDwV-ec#Cm zDSGYf-x>ft0ojqy4KI2>K381gQx$1!X2d8kDBSKZ@9yp*C;VvQMYxaSY96r0pvOp%7#+R+rm6x!mA%zVI&R5omUt!`17 zu9n5QI+k!ynoZo+fqdH8sV~&RcLaQ?zDA|7%&`XtVvnCoRNPOG^xURd@LJS;T1eYq z{u*;5Y5lt;KQJz+ttCE27N&F*cpIzaCHq`R)YpeW$_D$^V4Uc`X9q?N=ip-G=CZNS zo}fY@c>1OqY`^HOCI`JVund~4vZh(tyR~7t*mRV)Q^rq7o1B0h?g@FUWdd5m;j0WlG}NxYPs?d>oYbOxOser0OGcqfSST zC9VMdQCO|nbg)*#y;sju7PRs091q9RTum)sB6*vQ!=2gE!gztU0Ft+~KMq7&W{oA+ zgdEuQLbb2!6|)?T9HESmi{_}Qk}W;+=A9_h@x#!#90FvbUySn&Spg1RZ8A>|F=$3Z zIw>H0;U7*t(;kHOOQGQJ%o4M{Pa7x*MVbhbL9k| z)0GHr26%0~|7hL!lz_;-#KPTa1iKx%VYj&Fw+|+V%d5(1Ks}8t<`NU1o0Kcr{+4|r zsDqvJSYXAK9j40j2M_$}rI$kg<|>al9@5rfQ)c%=XgF`!f0Aue!okG7`a*+0%I^u5 zT>&)o-r!e>eLMqFlMM{4UCeWsu`;1#fnJ*5S=P_)9U=^d9$hv6WRKu#xV}Lh#`GRO z9T&t1U$<<1WaByY{++cx5KBwtvZB#)veSrZMF!8lR0K;3LSk~>&JApo9TD@AL_x5* zLXUluXb1uFWD#feV(Lan2gjfG2yrQx(<4Yo=lI*e-S*7K=2kg?l{RPQe6y9AOH3Ht zQ)yhtO;7$*yKor1;g9}qQeb-7xk9*mw7ZaM#1D_NNj)>-Y()_281Y?hp3C42c0VP+ z1A0Q2w!*izmDIJ|;lw_ZEFi}W>UKEokG>_8P_1c^4u1Fq_ePrLP-XPn<(8 zVfA~260ANyMr{y+5WoUPu_ifHf+2FoL}Zep21}Ld)<-03HH0*WJo$DhN|J8&NFZc; zkw`fk2gMqShDHOUd-Q*q(frW)$BWt#-eMR@(A#@SZXEL*INs-PsQJ zkkk97e88D-mt9#!-^K2$*r{?X-?QGVQ_%*lyZ>UpkIDy32EyqaFFNU@?xzWVMARd| z+N5nCE!ehxb8~4~_wSh_+Xa!vHCuj~UjcsmSD|v5kCd*P(OeA`j&3x)Bi{aT45K~v zs(V6OY@jmSQ1lY;RyAC`dLi41)@$%IpA)iT*kLBGOODo|y0Q$k3D1=?_>xqcIJOt` z28-Cwq~Z6g+70NuJtDWg0vcD8lkch1&Y5z`DI*h0 z0!wL?re!^e<1Jf%J7me>OcsY1=F#FW$C7Od5pxIXYvBXsEhG!9ubbrt+oZgwTW7EI za-6)wMi`QSF^W7MrsLb_*QM%=;(OAeCBN>Et&L=a6p<1jkOd|k^>bM1?uUoI>-f>X z(D=8^=w&K!uF`uw;x!M@)@~HQwLd&z#kXyS9-~Ot9pXl>4Tj^SS+IVYk{h)g!)K3+!ypv{^FEtzO#*$UWEz7`%;@1p^bBX4XU*1F))lc8~5x?TjOj*Wqghh11nz`1SKtMS`AS0IaDL|<&WDAv4aLtInG*tWNY0{`vi6zkF&PV z_sDV}9wZJ1LOm1EEdh6n!uNL7pB)c&pp>90q38B;=5=mGEpmR zGb7F~W0yk!Emz!iHJqQ|hfZbFcg&JZ&zZ1#CZRtgjciGV+q|H@Pcw{F%lmFg--)OX zrXqtjom3%AS}Nnk(z51RP_}O7$lf+tkcwm1M+)TQM}=D1CFXet%>fE{R(DFwlm&dY zV75x3)n^_KJ+Ql***I93);2gb5@ciA^oS`?;V)ZxB;=#UiJNBrbR{qA>*==PU)NLO~Qz~4>&$Q_WgaeVvP1VScrJ%XN74&T7<@w zJF@tlh8$TOtJmtu&yTc_6kEAWnGR!s5Rs;S)4jYq6|%#U!styhY@_$;JMVn`5sb?{ z-Hzu9H1=i00ru#woL>}`>t^)Qt(w{*K^nW!<kTne`k0>dDdFM3nJ9uy>`Sazs59M$r>N{%cXKG&_={=wT6I>H{2UGV)RGW@E; z86w$@qBoR+4{GH$WU=BxPU9Y<9)wq6s*G;v((q51u}M0?26;G`I3sBe1kUXejT&)~ zVND~N8&O`zBeO3TpW3h2>;>akKY4@8LOnY3aREn^dd-ftUb}-xdd@{Rb(!^thhVH5 z=a$WamSjtN&}cuHXT-WxZ0#V9BPicR-M9y>nzw?qM2251pAQ)rwZIg53|+TFw-Cnr z+7eE<1~!W;&W;}I8@;jnX4E{aB&9Npm{xo-J!W^nBbAoWi{@$WN6s7|pA9@wWO;q7 z*ZG9+fiJe z+MEPK_}vj15lFUKXA9NQ34Nbhx@+8R61+>sCV3s?+jW}d##mQT5)H~8Jo7|NZKzDo zH@SqdE{Ym5j2gM!D@>>8-I3UKZQ8~+o^^0-i7ejS1ePjTP@kG&+~*S9bdyt!2B#MN zM|NtlAYGRx=9bZqfxLr5ZL zf`+2TmP_9p+Xj6ZI1Oi{= z)m^=gw%u=N-B<4?*vS0MaD||k3DD%-?L))!vyYSnx|YBF6Oszy^r?Xe7gbGD`W`q=B8vh5)c~W~A=Hx?|x1ejV2Wq&2Om z4v=SRVI`oOFe$r07Lsz7@W_$=o6r4w3P%;zS(`>mQTo}eC-fjjSjFIKT!1(JCM&{e zdLeq@rObv8MzM|nUVq4Yp?2k00~#+84x&$^18Y6;?NLvqyIaC zPkUzQM}MPu*No$aFZ1`p55+(6=T1&^w7}Gj3kqBuxfhueftQ#hHB;lr)*C?rqf(@! zdHFf?&%*+60@(dcxkB`r328;c=oGqTozGe}Gn{2_*+)n?R4_O=z4g%qL?erLq6q(D zSIrr&0BlDWrKj}oM}u@%0H^x750_tcS!~;V$Lq&pi~R|`>tstxeEVy;Gky)x49WG5 zt{F%sU`xQ22c*;UfhJuOKm)!o%2^A2q8k*%E$BVCGsp2Gq3FYyEzy z)#+YREC09_F;k+Q<7hc>sp|&d>-xg&VPGMeUJ`b6qxJe!&Jr2Es=hGkK4DT?aFza> zfeG)`HB?1}Z#*KrNUB(Nzer2$VnK(N2r{R&_gelDRD{_*ogQA8c=I7mu7AKMHlMlSd;M|Be4#=Y0@ zu=QszuJ+vNq$tZ(UXh;j*WlQ@x3U^kF97}Wvf1hsT>6OUq4GpCXCLI!a9LV#z z{cYINx#(xW#Y{AeQPw$YM)50uk~1kg@p5M#olz4gFrg;H_>+%>d%Az`Z;SV5yoxxL zaQoHTiRVv_Y!{w=AA5DZaY@jY-ugmdb1l!%%k8r5VO_S_zf7;0_m|s*kPVFj zDL1Io+gtX3OhhCw%MzzM^rKh5#BL6kFv;uB5)zrw6D9#UPBx^0^YRDvbT-~6<|#SD z?U67D6dtk@aDEb_Q*|Er#&SSeby)k>y!p@)VqEI|&DM9*tYQI3uY=uB$S1AiKg|8{ zhgkDdhkoVOb-X*=t6HD_5sb4TLbSLa*Xg=z+T+gzmZGIML+jBS4upvOa)&~~Vgki$ z%`}?!>vNs;0&hq_d%6oRs9nBM$VIgI8>bCPoO-TE501npW)K(yUF{pkRoySJA?QD>egfZ+#xZfyQ1f6Wkb?DO!*^FUnT92 zejgm>of2Y(FgYqn;R`~aU99j+Db*7Pm3cYY#O3F_BLr2zIw-E=AyZ%^XgramH&i&Z z@5L*WIDqq^z~lh*j(z8OU-zB0d+VZl){9-AP8KA5OgP>>a_}7B8f8>}{B(0N_xGmU zTZp3XjJSm|5N>sW;M6*B0R=nsg5#HX{ZQ#yfe#u&2({Y1SKCgUX;ewsc zd~5CL6DV%0#EF#2I#5FSu9$a3+AxN)CM}(iZHhL@W>mwXRt-BlHGjt1%!OPmQ5(h} z@P2m#6QiQdYK;ZaI4t|TToZq}c@1iL?WgqXMWwP6UVO|JjzX0P*wh-+uzpmlqat_O zO>2GgA94xJ^I^+lE+>P5?+d}|Yr>VB%@7|psR>Q1^vsrtl^yB2?&pwVr;fJnZ1nNu z;c~q7$vEh-ohB8tg;tSahD@g4Wbow<;kik;^IEQ51)+)3>*4TyPLROPhK1J8L!G&!~#{UvGJ?{B`A+(K=pa_$T6ie>C}vg3L? z=}>LydR`(w;$+OUCntzuu8=b zqYtS?;bJiN>cQ6H>Dc#D4LvYAx$H=2yuRbFK_o>_KQYVGkB;JWPrm)wk{9Z}Utqk`3X4Wgf zW#FmV_oa>8goGx2^@V+P7DvmJuaWVG|HvaQC2VL(NV?Els$VBXA4_fRlq-KMxEhcY zKDHQ5M5puHle#O$Cz}3hve5dr5?`#}USLZN*gVtv>Ii@ndvLaix5sZC-w7R1Ce?T{ zxSDS{$yfNT6LlAmN$e~mu29qzptPJZM2sHlX)wn9MSo!`_XMD~dF#xFkr2xVC-rV! z&MApUbzGq?Wk-}!0+IgLzA&H3sHZw0KAnadrRC0b>dI}Ig64U-HK-8Wz@_MqO%j~w z_(<3-tAbh_Kx1u*Z#rRODA;Pdpl@L8^^b+!=fP(l?orT1T;&(EA^8QD(gW|XFc_p^ zD~6Z87SRgIG4ZG~U_)?Y-#0A#Xh&+zY`d>CbE(%19$!|%l^2O2+tY}h&*EW4V6Tdv z1>d$46zLWW_a<~HcIxTQ&#!@hrD~=nJzuGxj~z%@vz16S1=EgPU@Y=i^V3M`70ej( zKdoP&yLbUBFsRI_;9RwazQJl$_H8L0<>;vg3{=+r;|Jp=>r&o*s$H$sGFFb5>#2Cg z$;?MGZM_jM?j%%?(h<(j42F->Sms(@GUP7@olnbtml!_07P_>d;I&|3?rg`&yg1_P zxSB{B0UWBDX-7-J_su7dHp-;Risl<$*j{EhN07T@pez4J7P~BXl;>JF^8%9}c765| zbEPALRfL*tzm!gbg76%iA7)8dX8X-r&wJ$$e_vt)evJ59w$9(a-u_ZVtL$HZL4EAgUj- zO0=Q2$jP=PSD6n!N--+es$3*`8Wap(KOJTy`$eM3`WmA_w%X@#JX@5X1@I2LEV~`g zGnaW1QFqkBJZX!h4s?n4w=6m)4^-x8U2 z&rQev?c^k;$PNA@ThZLU;eZ`w3Exdz z4K*ZfAMR1c~oqDhWD`<&*{FEziHG%QD5uNZ%vKu{)kzDZr0?R9C zGeYrGYorWhJ>Dr+uw$^VVg){qepz=iE>{f$Ur8SV;G92;Cwx8BSZEX2#}^Nxa8>E! zxwu;7;TGGW#CjhOQ_bj>@urF4?D{*Kwk+3NrzcH&BYl9wJRb~HT0l&!N!g7yZr>pO zb*ObQF=c#Wg~;zo!1OW3b_@Oy5kAf?$h-n%T?|-ap7q+=QYyB%(Ea98AS9`tW9qB> zE!R+|$gAH$5?7CCrO+7hSM&$)sBW6~&L8JG$1I)By`?9LY{(vbkE0^uI^?(qFz%H* zNf8^uan{X0cCoR|$8Q``&^r9L`-a;4C#m{?a?c+CC5kfEccFH02I?7T9 zIW9~Lnfhg+hb5!xSe8H8A)WW8;U&9nZy`)c79Z5R^Cd33O}9ywW(yzba*1p!9;dm# zubqw5kBQmZKCX=hRaR1{mK2R2u8oO%Suc3AG7uvEs{T?o=SUT4043w>fFWWm+-tHG z?|2q$-ptqueNFEV^Hiq-Yfu%^YyOrd9nYQGhtQ+kLoa39g%!~>Jk%v>u}$c<=}=tM z)(y@>ZA}5E6I!4pHmx%|7vjSzP^e{dj#l>%i2=#pT}8100aellnAEFG>_zNTRQ$ks zi+l2qS7^68NZu360wEt37xKuRXmIVhO`VZtqefPutL3|+*PD#T5d3daxXXzh~iN5U2R0^Y;i-i!8w>fOmu8rJfxT8Lj|>#Q$D8$++TX z7$tw@&!t51cRdobkNw5`t~uTXfEx~B7=Rz*yQNC0%I>_Mpsd&mv(tC3wkCy8ptrU+sef0;i%{nM-`A$H&?aFiLMt)UH#X zbgf=!_&Y)kbr2oXm=MYL?Z94KUR?(0@eT4R#B+F=YDB#GVYb*`U6C}>B&Sj{Dx%iF z13NM@ni2emmDl*2BXV#(EC*N}&S;#qgG2L4ZU+`zXpS&gT*paZ4Nk%qf1?{V1Mh*o9eJ`t0i#j; zse;JpkRCUzFVTBIN~?5j&B$OHRV{@UHZPf za&UIxe4ot4x|fneL9;a_HEr5t+T-o=#{mDhj$c%)a^#4HIS4Koe$&v)?*$1~MxgHm z62YiV!d1oY@56`WJsuzN{CHt0_{lMNGZG&em=f5v>q~e5&{LCvC4lZ*Nh#W};d*;~ zvd&4ZvcJI6enwFFo0e96BSlj!r*A-^@kNp*#Va+z4!q_{Gx7(p%eh>wrQoUCvaGg9 z8}FTPy~ddL6SRJAZQqk45W|2Gd-$%Quigkc*^MQ@!c_+Y@_EI)-apcy|n@TdMawem#kw0LXDvA&i^g1k(dx|plHB$i*%%ns4=Kk75IKJ zR#I2=5^Oa>lpUQ*^G4tp$D^*1Lj6Jt10N^{f2ZggO%fiYn;gf9D}O{ zO_DQJ9-%%00Oa%1{3}}DdrMGUV7h>GXU@#G$tbWYxFthUfW^}L8VAqKR@}kWHJt8s z_970Vi;n6b{Dam&(TFj!nxj+y7gKrh;xG4tW?hH~kB+2&cE@*bya54@8naIsH?L0h zQfLwkv{y3L$badJJ$z;ibBu6uQ*nHBaRiz10fag;FJ@JNy-vQBjl5!7BEz8B)X;~g zg_r9$guVf}`QhxQ-G~S|*8L(%F)(GSWU;O)RJY!{Z>z2$CpC?jh$;AN}Ilu{# z&K-nCxkr?%Z)jW(d6F#>2iUU+LFQ#nG8Gi zi(A%_(}mTw{;5&7Rhw}2zT;Jiaxvis9qC)I&K_Iu!#vtZdvsLy>LD@RQfTXTx%u~& z4nNxHrhJ&Z$?3VnFFSGD)qsB@Xz7V&PN2v`@8Ar-sK3*-7->qjZLu ztdDkT!eTF8rMQ;;0;uO}S1gnG2vxkq+msV@CH(UGbILk98+gy&9 z8%2P5G}doS{PnAwG)9(awt-u%MFp>jjd+q`66Mb%MZ64voBA)@iodC76-GF@g!gc$ zgo~%Mb7zh2W?y6$-m8{$E*p(^>y6tWJUbO#m~F5fy&>BsD`2r_yJKXN-Y&vLmG?0A znd-INN-1Wp4|93_=LZ-y{PqjDh)Ip73=ichDpWtsHt=x>tz9iQMLP>I1BUDho12c9 z5eO3b=z-W!lg{g-hkG0>O`-#ry-a3}z%5M6dLT?4X%;}n(uREY_Chon|MVk$Uej>Q z_$$dax!txnLj>BJjA zZR*H=bJ%4Y*?$3M-*xVo4Cko_gfN@DOLQEV4tKyoJ!dCg4FhwLD3RA*l9xy{=$iY z)$<(UHp@e~502PvV5HcpvSO0fN#^B1I! z*TSzoxJ)#vyHmTqKE=DVViZgc`3Pq9j_plLN0C*aQ2NZPM0n0HZ5PKYm!= z_$&v@txP9}bpJf6hQNs9I17GhBORg1g2;~v0JSgsw zNZ{5=2K`4h;$IYIxR)z$oz9Zm(He5g!0IQlkFJ(plmORDgQ zQd=E=)8YA4dO0#S@$L{c6&1%*5jE@hItk-ZckneQu@y1ZfYGd0ToG&|8i{n@R9`;8 z@AZ)<>p+rU^ds@8;ckO5kZs~Sa@6LZk@ui-7oEl7kX^cm{~?b|Ym{ zz)DyYF6bRTLbLJyrmUH7msu}VhV}BCU@B-qaGkz!Mbr6AN3PF3 zWK8Rw5Pc)b2%-(>8M(=`gll1%F&o|1Jc1dY58HX4R6^;k@{k|!3>0dRoW^C!#`v4Gwf0QhnY(xs^RmyT=rLTl zaq_hdlXa0z+~VlBB#GKg7RDoT0Y2RA2fIc#8P8>ut~wT9@+q_g`Fh>jAZo6aZ%rP~ zsYrZq9AHc;Gk!ZFGSakP@4EX@QO+vD%@8CDL3Fj!-)DE%Gw9U%(uWJ})TY^GVfnE| z(_J}{@ave{Aam@Pi=RVf(k+n%!djR9_O>E*$d}}?xqdR>r_x{f>b!64A4~rW#n8ZkN*A0 zTQ{;sCZRY{;qUPJ|r`i1wWrw?-Fh0MC|`6S7HJ$3|X>7!TBTO zhn+$a|XWL@R76u>^qf=!KL}&ivveB!P{)3k&CQZ6{Pn=a?!SBKa zYG)(?u0w9u+AL#?-3J_Tcy;{4e`XY?9nU9WnvYy`bUBYP7A;@xOeHa>boTkC-PN*N z&r^RSXe1^oWb$Y!xZtKJ2<1H_uFkbI7>H=}4Lha$dqbLXkXi~_e_qvZEV27t?9HX(u_66fo9Z!SWS|dCxT&}?NTQ%$Y7y+rGWVe`< z&PjSm6B^pQ6Gii=YDnKivub`Xfgh!#6z87Rrt(8EV6x-=`} z3k|ezGa!oF=-)2_1UUXHiCJD>G!IpH^pSO0kmxinJ;)e9w3hZhIRXC`ZmjKWt%*x| zHX6W8XvQ|o3=WU3Y!_`@d=4ZIExYELU9UzKT{yY9WqMh|9u>P<9P5W>EQBvt|AXVw zgIHK>n>EU{+pSl%NssM-x0BUAM(0_nH@q)FGa6z>G@la%#Hr^$_}9AKl0m{>KLI2c zpUD37dmw`Hb)uRMg~}sU-bHZ1$WjYpvvzZWMOaZc_sSOrsrEWT;e!D;mVBcFyx-fF=p=v zTXE)*(~nz)EMFk2-!~yT3!a)g~I$#`<4Y41Tl-FHU(%@ z&C_tD(<`e%UIA4fCaR0M^lZ+%bHjs>R=lG4{U!==m_Gh~zvC_}&lYa(;c2}hIqTWH zFW>5ouy;esQ?fhW>_+m?ZgNEPVB^(3?;j^Ozo#tG@d3UfCOH+HVG6(Wg{7P8l%n78 zrNTpZbW34YB$!I2TbIO%4qE0n(d+UVZ^w`pF*RQ=3*n5=)uDk|IsmR!9lV2!PSwh8T01*BV30E-n!N3{@LJ-zYQqKzkb@TOwDKb{*;F z*+&;9mnZBOPowF(SE>NkQjf&dK1o-r2Z^9NT>CYG9&)bw#Y58*ls~>0r9d;G$M92T zPYzX0Cy-t(1jDt|`^pB^@gWPTt?2TaWZ(tL!oPryax&*;QyldY@^>uS(&BAE_i~Im zkgzDLVD)Y1tbVc=l1JE$KPc4()P31wWYoCytCwB?!}A|w#XeM)DzGR zl}~)-Dh&>ajw_wan){5$U}#d}<-1$rue5*C_9+=QL(lnIml&k+UjL9sc*Tn@-d)8OnDXI5GoDy(6?wyi3PCw|c z9-@UVDxy)ROblFQm79^UAc@Rbxz^ET8pe6|a_p>L4IzBhldhU_4Kl%!ZNt($gBP12 z#hYJVDkg10E?~R|#TH)Tupeq{K)$*?u)(yd2yep`*AP&DF6_xDQhN7F!_TR=W8*Xi zN}6-^v=4r8YRM;Be|s~Kxv`(EdM4UL)RG|>4)AL7H0Rn9bjGP5@OlK)bum;C+Z@vf-F-uPl6+f}{{nZXcT@nioe z*V4Zy48^WJk&R@xNa|%ilB64mAO(OVT$kdFM35SPEBQ53N7_dE>j_9=D*zzY_x1-+ z=?(*O@?ohHlkp`cIw^zi<;6*u3T5rvq1Cu)lsH*a1nZo#@lPruVyCU3n?faqq!=b9 zkBN*MjXXh}d@0w;3RId{@A5rGA8xds{_fO+B{Q3p;m#p63~6TVDsscyR-0X2Vh_zR zvG2Mg@*H%rqT@OcLs<`3NC(H=tzHbXYgMp>e!>)AT9@5V`|z*5lD+GXU3 zkOhA-85=d7T}2=8b-NGq?}G-L(TESuWlM~m@vUBXf01zk`>jXLmG6t321Nz(uVuYbY2$bc^0}mM#AJI72i8lu&n-F&Luh>`_gM zb^fIw@z}2sS9MX;JfSh*{*T z&Ya#vqPoZCgDl(J)bYsSMc`;ml77#Tn6bpmbw%Bx?b4wjnHpOR8%1c;Tf&7*LSVDn zGidVTHkr0o#~Ramfe#G{~#s!8rzSbi^ci;|$vMxWw@GCBJ%XynD|z zrda5k*Pi?_DpC8m=wPd}u{SJKpN))+aqnlLobxHt*ZS8BodsT%+@0iy>#OpQ)3Am@ zNacxzKNqCm*v0S3DxZ+(NAg-$?L$2#R^|@Z29h2DWGB`TkNXmBh77P~zZHOq^KFwE zb0#s1d|{#~Y;Zn&o?A7vF`^pwA+e}s1lbORR=Z6xOeC>`c9KFPZbR-o!gCsjnN!;xR)5d*FUJF`z!f8P z*<%|W4P~RT3ZbcA(HGZXy^#T-4kv5MKMLR-Uk8=~14lU3e-eW4EqNF%adBG_=7DN# zyyUh;`bH*?2V4FM;aX7Za0vvC>{RUY?ho0`x&klMA4kduk&x3o|Hs5jD%oeq-Ty21 zAkW(xl_pwnUN3L97ucL5S&b}j_>AUc3HDZcvAZks-=yCiBCv}=Z*|{Fkd-o_hhreG zM6tmCz<0sMuX2=cVqj5;70HT?_IY3ScEO8Y(aZ)_-?;pU-@-C=GM(2Q(3S~8BMU>h ze*u=;2lW6mul{BOx}!B-*M*WZZeBo1dRRkYjda{suO_l5Re-$7jGj2_$em$M#KY1p z9UrV~e#E0HRbTQg?aZKTpW@vEQp*wRGikR(sf^(V5oME()kH!`gWs39;7E53_d5&c z$7v}VLW9BVhN-h=YsLs-uRaosPO8!|*&RL&I;C<~eWWg$>A(Zrxtb%3Cn$|8US2aq5oJ}$dcUFnuynz|?|k3!xIugj*w?IwyzkGzux1z6tW9uSlYKFV z4;5Lq_UTB#oG^l1P2ee?WB8MGd&iy2bQ%h&D)Tc}s$GhI! zfdL&DOg&g*!ZUxwSb%5iU@V~$G)Co9!sg8fJGh1@ZlW%CN1Y#!=!`wEqlLsyK?djI zG(^>^W1}f;p!vSxxRtmsVT9J0LY}a|FdA@-y;5?cf4u%tzuU3B zVz#!x4sA#*;+H>xYg(hn4q5~CKdagq+g*R>{p<41HYMSJXt;kfevx?SiLsaF&b-|E zbFTs_IT1Nzp2p-;q5K?~@%f#?3bcbcr*e8{wa)s|YM%_$twBpYM*8|w;e6Ioqxy1V z`dot(AZj06Q94SsH~*BXsbw=a<;ahpSXC*0tI;v=MFB{6XgGsFCD~|B3fc$otHOrw zfsb3@*ZOME;y-6y^c)q~Z;KLi>$2+H5|%?8Rx+OeK;IY>UH5ul7;d)+W(1m)`nLGC zAQQ7i?<_wXR9)iukF2mVDdluK=}w#=01LLhJoYuz>Eg=PPoe2hcJt=!7&EuR3E_XL zI#Lft?!bh4qe`~w0VnTT%Q*o~2Si-5%|Ns1n1?c7YLP84ko+lJ)Mo$M5K1i3G;8Kp z%ZHkbP+;AH@FU*|ojme5zRYVV+KgNRG->4S-b73x1`x!pa!=;r8-Ueq)6lc)E9@)p zCre61g4Yp2N| zUd@LmIdYQ!SYxygvjKB^5jOoI;z-0^7KLX_n3pwP8tRXWdi_l zK~y)nK}M#I(Q4qr#Z@hc~^(k`Qram$r5vk(~ zHGV+8-!vrVknP*C3`J);@gnt%1g?!`X+|;d_#Iaiu|k?wyBKOv<(Z%F|0OFs>rG}V z!Oe|7H8{l>&Nhgutqg4)7{#2ca83+f`P-#B^BBF0RB_BCV|&_|ntWBK82Ni$wt@P< z+uG~Cu2^?<#&F)qIIHLAHD-T6Ma|uHz{-!0ybTz@??xG=`JG<`ROES+_`EyzrK}7+ zlQ@;0T9PQYo~+){B!HnqreC5K;}yILgg3SR=Km2P6nVZdPV&tIlb$sLe6o{Ehw~}y ziTx8GuEFZu1~K$?WwcvMTH^E3_~NPZ9YNq`$G?EaHnW>#0TP>`O5gUf<0ooC{oZWw zW=Ryp)&KAmjaB$r{ZL@ew=Fr(FcP?lxny_UM(q2k|8jZ2FJ(I_>7$i`vxB2a9t$Ia zWa6Qhv$@PZV;!lhzD({8^%Xzb{CWMR-p`vpi-ku-KI7+q>{GNbyW2-7q9a0-85NrK zNYR`vyH}l}C-j^H0Or@#7QcE%Fq*_{drvws^J&|xLS;{mDGW)iGc9p{e}lQ`DhL5) z3oai-UPeovN_q|hQZ0Yq#=%1_73T})GYcaVsMh1L+I4{__8*y{0X7zIEnk33RYIEM zA-81tXg7251h%hwR-uhIyXX%^|CmK9upnsz7mB{NQpwT2u0W`Q$biUwvxoG zZd3Y}TbsF5P{HC@_HN0U$`(hja6@5%-m$4Bgngp9QSS$^tmqaSN9%@JYH^M(M(Y>G1c*@{$jqspVpDZ_HbK2efO36 z`&}K-W62@GerU+=i=l;rlbs?7r0P9+*ARC$dyDz|} zRT59!e`P6YORQgL@Hq6_eDP-2+2Hxu66yD%CR3g7U8vk62%_9oEOwDgD^^5p#>P^* zFQB_E6GOn(%wYW(0|TFXcfU)lkFRHD+M+!F1)u z2&bB1`cfjahOrEbD~J5>(zhl@)M-_Qh>$tC$B76!sr4U70DxS_vwUH-PUdvJuJQjr z@K1`K34~7#-_-e8U9cGX4xn?y_}lBtI?^1yIAMnlYRw#3H@4n!VH}S7{-{4;GU&(U zCnApwb0i9g+!WP7`vZbOCs!?NAf>J^G~T!5`}U!k9o9FL(*MSguFm`%U*QD_VS5EP zVa9L@|> z22u}#LIfuspxm5L9%0Dgpp)ZinFa_=UxP@oZs*}zb%X6-z)9?%&=af-C3_rH)eq=U z$0^zRD#;3ZNZ{%1A$3O||BUf7J%19*?RuPd&qG6$J$=})o@yLi-?qHpS2wv9XPy+4 z2L*CB^k%0EEO&xjk*$La9{Uv_Ea7v$(zPXF@?QWz;E$cQwu6%4(zCi6UQr{m2`C5O z$tq{dE4QYCceQR(%Lk&QX!bX6FFz5*#+%Rl{%KKwq1*o-6~JlXzkoQ7#%j@5-T!}J z_Ah`V@8Lz$uj1}%twM8XsHUPp{FhQX**S8~d&3+2Fv0MJX7q+MHKg(Jj!`L*R=gpBmh_n>zZ z?+%=a5^e``qV4Tkvk<56oP>@sX`F89a$t#E8^et@2T>@i_fMmO-P%?d1Q(Ohl^EmL z(tC`PMEx%)CzScp*UFw?eqrae9NS=2{}TXM`f2G@i0wmrx7W6b@*m|okPu2_3}#`w zE$7h3Ln06T_`h)4+_i1f;wdA#ML{btjZdE$H${+u^LoYwzJ-B_o)0-uKZ_Y62l+~EVrUjbVQ77(KuV2U}H=vpe0QJ&iP$E_xa3O zYC^Jl9a(VmeZszHOm7?|XKY^^N)?LCAg=-dIXOcNdgT)9mdNc6sKwph4wn_0tt8%` zOt;o#GOE%chL*cuPCTJ{&US^Z)nJz!hWIz`i`|DQ})$Vn|6~%tTp=n|Ip`8LwXS7(hbhu zb%gCF5@k0IYg^V>^FG1+dCRN80Mq!Ux@2JQ*TIOmal^*TeKOe%M2W_vY;rW*qc1+$ zVpim4QRerRK^Wimdo{?RM1gBI#k+#;cs-*LZNL?xTSkwYxuof@~eaaYalcs_L2bS@vpof3#vmS~4j;l`M4%L2h|gVVws-FHhupt)c8 zt^a@k0Adba*R}osP6W8AAJ@CoJ$~>}lz+Zh@3=O&xUcp1e5^tamyJ5`>)(s17XDJJ z;P-kVI_|aTwOTsg=oE`;z||t4RuS6kCY*;S$X#{pn)XUlJhhB^d6)&4Gk9|N;M+n1 zxe20BLio&?Q-fIrmS9f%xdv4jFGzY^enirKdC8TEz|?t5f}~fMojsfS)Jv-*xiCsJ zZA2>U?h3+Gr_M88b7A`u^|mjTNx?VHY$302D`YxTmhPK* zX6O4k!%3DrZSkA(V|epgLs3ZodqD*q6~T!i_5c9Jld5&RHVY*X9sXDxcvf!nL&{c1 z!Rwip!F)tg_kX@wP>wK(AOF0kG=@;3a9$pDovcvT-%SgNfZsa($NxjaU5>XXHx!{E z8dqd@f})o84+$QN=(ppGB0{du6Lza)%|Ssv4=0i;w4g9hO3a*(r#o4 z0Y~YxS8<~z+NQL)-WyIEh*ptSRP~N-u5YSwh_zH#OVhBErYO21dgy6>>F%TB9aT}j zKdq(w;!9Erp%>X#>?b%=bFE2Jeu!B;O~DPt3WN5|7#!zXz(`$`+iTYQn(gs~j5RiW zjO6QE-L#TUbs~nObsEP8b1hK@1I(sZa=rP_T7uY_x08& z(QOCxx{mnX&M0KYqa3fg7=zF^+Ajgi*;diK^W|5OLyGMk+i^pRRoEAlQ zm?Sc)75PMGS;oH8cL3lV-_uQWz1pH#;*Dn_FDk0_ur@}U+ufIVBvyK(Eu`R|9zgic zs9;z0;^XX_HY+R^qRKUvl|LR_1DZoGPl;oq@#wzc{Y~f$78k zm5{Y5Jaup&|Gp?NYEc#zsjzXu^8AiyN9$IH#+rISc+bExG``_Ny`Q&EigHkWZT+33 zNm~A0oAL^v7bCp2J=ovg%Sob%d021Ux>&0%<5i}zGc%>Aqa75YbKQF8Mm9mb5`Rg8L9i&!K7(V}UPhFm4w5z}#BYhI zQx0XmSLQxEh5srO_tV*dTxBYsr0g;^z7*u()Fit8004O0p7pUGT1gU!7KP$;bHG5< zKIE!Y-#{EIlKUQ!Q}?Zc&&43mLYJQaYV|!H>+L-^l)n-)zr##3Xkkt@Ili(%f0vA{r3FKuurG%|uj1t_cjd3}h?>pfqvmzqF-^|_r#@oeb~xAFMs$I^iM{0DY2P4A`0Y%dN-uMGL5>dmnH zalPMb`(F(db~ez)fO>wWCw1LxQs1a{h*`yf-(^|&#S9xy#uVXcZH2+Lf8RC4VqfC* zxbJtvP~d1L%nInsTLYmRF`0k9)Q@&EkKF)6YCPOB*633pIsMI5!6(?~K738(F^HRh z$El#tZv2UQ2Ghn!s%8&*W1@E*(?qU^)Gem65>vD-0Sk zjmSZ^HaZk|X2k715VMZ@u6^jOsfUJU*$St;L3S(9w!ZQ8P|mwH?`VjrMpN`Db-+Sw zovLN6K}XpU7s$B=EH=n89B-AJIwMh8v$h>6wQPBz*g3Y$qD#*aIJke|*~}8T^Z<=J zu0HTIipQ!PKGM5$H&}=g_bznwY5Z7h6dKUdkPd1BJq1#oB`234t%5#eD7DY~nth|N0FX>8vXnAXv>i-l{a zXwn%4A9ABm?jvx4O*mB^V5{atxT9Z}Ba@ z;WnScC0Dogl`mrFFI)G$eT|I3$W9%`=}%fH2zYsSKqrMUUtI~ z*94_)%D)X@9q-6WdhnREiKX?2=#e3Od{O94Kd-?s7!_DFxGu3y?h^#f z4id_a6SM4pTWD59HH=v$d)`~-!HD->^7>oH39N*be4KiUn((*rgJ05x^sMuIvotj} z_5EzfN|*_J!eU#uGK7Pr<=AzHZ3d4c-`+FWGWZ$U*NEi^qqcWED@mXDBS_5f40vgg zpTD#6K)hu5XaId6cMy6)n(Ru3>r+r}xTuYzPw>Ry9_e2D{Y3Za+}LQCzG~_Ielri2 zM{Zf7Rs@1-jDmvvcZ#ECV;T@x-)mI;>=;=CZxqmVl7IOF&uSR1>1BbA=pScHk!;%x zbx_t+#lhee-V#67kcDF87Uc;E5@nluFw0ZT0xWJH0JzX}@AuNR3uyN$dDmB<{2d%{M3v}xB#qf;>`kBbXv*i|S1dR4z=6bAGf zzYBQCsc{wmQ;0SP+4Br9IhHoChY29lcBZ#QNfqi#o=ktD!mRAXw(693Y(L+=Gj0478Qe2huz6FYjA9DQiLVVk+YrADv__J4boM1H3BTXX> zz|W|(e23scGJwPX0>YNsw=eYyHK_)Pq(jzI;B=s+No-rzfPU`G%lp-G+Nc);CD6JE z8CMTg=p~5R9cSYvZit{19ni&z;12csJ>s^tg>+^%&X^l=(9kg(GD2r- z#B4?{4UJ%&`csWCI!%8-WFJV`g$zJY)iux)L0>J;Gl6b`R*5ps(9-M<0*0TCQO}qh zt4;S-$Cw(o1Z^eN5ZpUdI$g~tqj3w92D*d_o(#u!sMJ8{>2%hU6^SZ7h7K^W%aj1$fVJ1b~;LBeCZ-jxk^J_ zkbqM{x2i!WM!LZ+nadRYFF(OxJCh%rMZ{_TIzHYLi*vpf%())8%0yLFj4Un4Vxdl^ z`dx6Ds3PFiBEhEQ36sYJP4Y7q#hZeg(OM2bqODhjuL{+5ta{DtM=X zQ+r>dI~X;!Tr-F4$?Sn5>${KA5Kd4D-Aw0?FC#rnX7m4-HYe$N-AX29Ydk!<`|cMSVp396=eAMPEuFIEPwz5sgsdtd`hI&7-o6^~HirB!``-Vvw z15117Sz#J&J0TND(qf$McsYXBSu@rkTf*1~YeklZa7VHd!#yqsvTD?^Ai>tm)seyU zQ9r#HmHr7qVddY*wYcawO>?b3foCLmTYMAGWIXNts`ccYYLn>%yRDWR){X*N^$oL0 z=a^*j!CchlR_iF6P-9%pkH|n3y)59S zF8)jt&G8j@s6NsGkHLIl<9hsIyyd^1gC9Fmm^_{U$?r-W6D^JD5+-~pKegX8}O3FX)UA$;Q zWT{AI(s81=YH*aS>l=3O`+y_H2$$|XW@S-c5=9gjSEcf>2~g|Bnei(5^sQ^dKsRY} z*I%{Ys@&&Yq`Q80DyF%Nd7-hzjXshdY0+vQs-+2mFX9#a>=4Tj)Z)a|pxC1>%HF%G*_{K(zoZ1)%6fQNB zVQeDJq2j#^RITb-eU}%9B4g#vGgO@6aGdkWTJpZ^ThLPo#Fe6!w`qA|*$*femSYD5 zWpS0rV{>E!pVyf;$d6xX^R{J<>z=ViB$n(nB>7OOAa6FpL zk&1EtwtKmonY}T&WHaJrd{Rp1<1|Lo#{I=5uF^e~){toKJn?ziro!|2Nw+mn4>dwI zwkC7-*NFTZ*0(bYd(OR1v-ddhBi^F!i%pEwCVJN25>XeQlngZODCmyD(D34J|3}o9 zfU}u)@9Q!h+H`7}YC>sMQENqNU)rIK4$71gs;Gpd#J)tW?X;w5Y(;8`7*z}!DM3nv zwj#AeR4uU^YwSuawe|bIo$vcy|6ILtUEbz-m*;)XIrll|Ip_YC5gJNaKuLd3G0Udk z+C6eaQ3xvK*NH%Be(E;j742*VOZjFUMO}Q`nxX?69mqEy2+x;T)oGATiu`r7uKND{ zpYFO`R+x*}_&CZuneuxPpLs?ki5m>5s0MSBI)YExZ(L5^xKciCJ!tc*kMr|T0i@fS zrAhf%Y z3b#;IB@?$4LTfFGXlTE?xKw&V!PN@QVZXRtj*-4%?spp9j`ES56>Fz>)EMCG3u)%> zn$ntQHbcJ+&WB)VS&PVpNf%$k+MpUr%kIdIiwr=(v!#EqYF=k&*`grhSG0>JEe_B%Tap4OSvhd4N%grcGj1AUj2O{;$pcOQj}1E zm#b8^)Z|U!gHdczMW1P@MjD+)E#{m-t< zxif{!hHge1t|_yk^MX5WH3QSjeP7mHjCa57+_-KZp}{_!wN)u>jlMTkK<}@i!d*LGF2#*2B@knm6iDwNrd9<1l8W!c5fgC|P+2uXz zZupN-Zt=lb7`B9f>fZUb?BnI*bxaGWbu^SVns3f;8ve(7g@67C=&_lp7y~(OGq<-Z zYv}e-U@+QSE}>|ysnhi%ZH0Mn#nHw5;|YQF2F!8Y@;i~TTt0VmqMx2}w&l9qx!?PQ=WzmFpTOD0 z#rl!ivw`6_k}zd<6T@dJsU$xOe)K7PZ#!BD+yTn+K*S? zjLKQ0p&&hjO>TxS=Z#OP8pXS5JTtU8v+D+B*q{P{N=tZ;!|JQA`_zIdFMs<=>mo9> z!}ge#P&WCIiLnx9<*M>OIFlkl*9*h~ZmqDdmF?JiWn*aqTG@whGL){P+ekZa`P}2` z4Rtr2h8bvV#H26v9jCWnKkjy z_ynaJ)s5RBnb6S{n5+u%8-Dwe<#EFRv7e!H;pd*h#T*yo@yGVDwZSTto)HL(rQ6TT z^AOghw`1fDFOkHH{qWVwB{a&Nl_Y5cU4QRxo8a`fNfDdvL)t4?^r&pFe(j(v_cpxE zNn3kTFW37-sCxp!vd}tiY|_;~vyRgA1-~L^v@>F!ExVP>Gz83-Dvv=aEM~)e>wH#L zeQe^|ENg}brv%v5-IFQW1%*r#|H#Zr8-tak+^9C+sr->;H2GN3=eZ@*WXXPLPE9RF z{bXZp<7S^jt4;U9*EL9LR&p@@8t`(a&I^HGC8^)5sCQ0f+y@N$efFhSK(;xsw_X{e z)n#aQH)3xX5xg_{-GOZosqdaDjDmOlUN~K_VH3!Yfq5M0&`*iZEk=ItGZ^#FrLhP4 zOB1llDW!|Biy_szx;qlfHl00mk1d@1FELFRgeg~^T3YFGWkX?jyoT_&9loXQq>z?> zgVo=bR570GGPp+aS==&^b#^Pls5WtugOeV)*Gwvh7PSs62r#_Qt2>d((Cj{fVfDsu zL?4`DcgyQ~X6YQpTlrcaQ^G$RofKVG(%nX= zB%$-+zn=mVadGVXF-Hc&){4)ytw%F=0e`+-@(=VIyvQFrL!)_OYq+0g-$SHh>spk z3=6M@k1|D^;hoTO^c$bsrCHuScBd?RCkA>s-c0*Ei%No6p$7xyP4UPsO>t?(D+6?_3PI+W7I;z(l z!q#FtYKf(~ztECDpKK8>)$g<7%W1x#-$o#K2(bgWFO_cOE|(*va!-#J^v*9A#@jK6=CE^=5gwh`|_V-DEdVO`hI<&rC(m%BB z>}YxIyF7~j)k++<$oJlgzf<(sE1(ZUh`|*v%f5h1Tak@NT$=J4ua-{CM<$sZG4qpZ z`;c3@*5`I3$(NaT7Opu|KeUpf|79*xgSb(1jE_)eFEJE4+zthTtZ_F363p8ibGSTSzgxzarwk$18H$CzTwiGkM#kiEOa|?x-`XEs+-)W>_V7aRGsg7G1p<|ki5!#*~ZL&`?(~4 zQkmZ58S852*XU>HIIGT|EVWPE9lk=NN0oRiSN9C&!&floM$0nG*d;-xzc!O<5@Xlv z-^b#1$rmhym-X`PuyG~4!FjB?^HYrx-Hp)YS&UmDt*6i6`=ju#CLl;~*=dDFor&V$ zYL~^h*TC%(a5KmuLY6AN7>Cn>n}O2O2sg#jA4u$PfcD<^qEe)V1mT`MY#Z>BPf z+Q~X}UDcMm+w)6H3*(feq+R>LWH>4Xa)jUu@qIIZ#cl7Q8and-tU(1~c z5e|A+?H6fL*}+?0?z1uMS+C3Mik|*%M^8E5xYw(#eZ^R&yr$v1E+e2*^E2NxX^cEbU*4?U|Jm?!S6iUx{BCHt zN@L!jz$pF}{$?xtrWIQOa##y>o_!IT>YfUMxRX5bHw?}mJm`cs*_q1tG7U%c(b>zP zyD>EL9Mpp0bq}PJ z#ODPcJ@I0RCGS2{;{$VZJ=4%(!tYH*62gv|8EL6fd$)yv!UmrR8`WRwp~{17dT?at zjj&+u$4$fW zYPrH5-mEq_6I{e7iT=Wcs;8KJeEH~4@KTqB$L`r;=a)gRQ6M~&NWW~F)#dll-h=q% zwsmBN83bU{*awK@A`4&Bza-xY+P)=h~OI>pF5?&E&n(I&FD_(}b_>Rms z+e$}lu5O^rgWq_Fu|3VN+Vn5a$hx7t6E~u^D&$;^&0bQN7(@E!nb2U$r=|JD?)J?< zLdZjg%&ifgftxKjeg zzwn$oe-9VPq`s!M1|686X}7e!**6z0Oz#tX`{Q%Z$Pllw5f{6?MkQfao3TN&fkZ8^ z2gsQSl^fnLk*x{O+klc#dgfZ{TO&;x^63|(hcu>{KOafx@8M^Im2`MuZp{{ z&rXhVC-7$ARHVV(Xbt!Q&uBStHMF5<+dGtT7Y-_dEPZ@KOAbN385pcJI{4;-FuBw7 zd3*>Z-T@Y4{TXlFkez_Xs38MWILcNzMj2n?9D#*s|V* zT{SJd+6i34v~l&$hMbB)<{H11-JiUqqn>M*{h6NDO@*)iM&W+pEls&|2Bv*iZO}=- zyp*?%JiyBpb#B}pH(LtOchmbaxH<0F5A5;CECcql*?UVsQ-yEcTW4Q0bpj!;0h~^v zSzr(NX*286*v-AJ(!q>KiQ!=MR2z)8|Lp__hh^G~21#BMhz? zl{q`HP&YD`g6Iks6nRvdqk1#9jZ1PTuWUX%C=(PEWh3Zy<)ujnUdy2%56xERTV!sR zgiBt9M@0QlcnZoOB69yb{z{OOaX1e1VX#6b!m~4Wui-308QMFG)ZM*mTuxjLSmt-l zYMY8Y1>qrni@mI{PRQ#w_8LxFT0FJdjhj)4~X3JfBR4!AlgwiG4rF899Pu)SC;spLb%fyuFv6M4tM5|_4M^fS9{(pq>>$BL*c270ay7s$c zDfzuqKE8`Ce-X!NGsFCE?>6$?=zj_xDOU||46}_w`!H^LW>{NF?nAoAy- z>B2=B9x|@SWA=r3cNty1RmuSI>mK*MpfRlH;nqd(n@S zn!VTt&T80|y?gc=jX*!BFraB+=dB?xhQ;tUjDe89>kw9QUbCZ;-rm3A>b+8OmAAvy z!CgGhQBd@puhDb4MKShuIk>x)^$At_>C7MVf{9ATd>z?)^t<)<#{^FiOM`c<$F!O+ z#5{d!KbGHq<8#UF1TZTLr!U<4(Y0Xq{y?$u3cApEC$MaO-7qw;B>9XPeX2Up!C4a9 z2SRti5+b#eyFncx8c<8#UM(+-r3#YMIGaDGw!aR>`QVj!uubRdv-{;?Ml!B z5FT+_c-K&~R$idtr#{y7yt_Le6DNs@=O3TBPzOduR44HNJoLWUiF6w6d90)mRdk zT~o8II@`V@K;ZUV%_D25GcMK@eA@b$VfKxKQ@=BHjFP?RZj$VV#V=z+^aO-^N#*DQ z)>=xceTvcBGLkT7W`dvF(mT@yDSv9hlsT!h;^5NC-|MJ$r_R)Ui(OsfwU_@oj8?5L zY;Q<5vEmi6J!Sg6hgk7m&_8*DBXx{zARXeh_U~ zcs(Y}`1nNWJA4g!zO=6QAIr+HbI+N_tCuY$Eo2@9YUe$tzXkwrp*+M4Wr^&NdmvPZ zb*ZaJ?kZp3?fzZFGu}p<8`F`(*Ks#_cDbN`a^WfD_E8VEmDW*@`v86D#UqgW;|qbl z8?xr*yxEYbS*n?(9@4U=xB{T({If*kq_MSZai3yipQLkQ0SVny5bke=lUI8T(#u@% zw=c=N>@2n*K z>~t^@1dZ>PPe??`M5tv@`jh2o(w9lfl%(o6ze6Tr>K-gLu4tTtr5tI>PI{+Zi?!aN zFXCxk1>?$P3wG)w{hr*-K#eyzShx( z_cCkvT~QH+#*LJR)XEN46z@@uta(Pns(nXO`|#}M0&nQb7&mEjId27XI6B`rc`W~e z=Fo~od0}UAoQz6D9?%4>4G+4BW~p)9y_}35%QK6GT5z6sM~?jJMuI!F1QY(co(f9i zd~j74i_1>JS?G5F?Zi~rip|VVrSgze=$-l~X6`5;cB(>sboQ&641jYbdpC8?b5UBNpCaT)T?zZwVW;cVWt?kNOqoW7}q>WlLmy z*e1cYMavJYZyAKC4-QZD@CIKg`(Sn49iURiige_G1_np2Fm#T3^!udt{Ye{|LJ+%V zgjwOLt4qz-&GjqZ#xY%lL+MdB3}1Ga`db!}b?uCp16{HX(WBNe+Pk|ZPdl986}Z+m08ICU_{sapFxhQH$HFMp&k?Hnw@&os%t9G;>*OS9 zW2!!H%S4`Bb0-ie3YAMh`e?P_JWkI(^k6AmlyJ{NzNg$50!@h#BbffGPc%uHvkxnR z+(o9Ial8RU|9zYzP)+vFdk}h%lFaXBE-tY>2$;0^TR{DF-xyFV6}Vu;E129_J&Egd zxHIq)<9_+}qfA~sY0%NFvXgin<=!{V59aNx$j?VG z^$og%ON>tFOws>8=-K#YWEPH?pi@fof{XqDFjVD42U+Q zGF_BJ-{~6!EIrsm2=8&^^kB~J$jPqA?((T9Tvz?@T7P@j)y3#nDOpZq&r)Bx-DG?S z-ZEjjk@^DX`USNi$P}#I=>Dp82-XjNcXQY6bx`=-;fTx?9oWYnhFLH&n&UDTMX4y} zlag|s&vL9PR-P%9ay!YNo_%bp{E%;%-(B*1&G7oS`Z{xC!*GKwzB3Xsx3Rw&hQdXC z1w4}TVyyRor=SHDnFiz&)cVBJ->jWC7aSR~fW@GSS~{!gOr?xhbvJb)45hSo{J6|$ z8_c;wt__%#D-8*uF1J>G{%dj6@7nQ&>5A!L9K9E}B^&wPzL%X@vlPnj;dfwq!+nh@ z758?d#)>P-!>~z^Y1o*c#xZXLAn@W?)_j7Ryi^CZ-lwShTB^=0BC-dwRPY~E%kC1? zHRA$GJm0q5W)v~y&)hs+Id$Nwc0|mRXjNs(p%IKh>&LNs*>-HSA0e%GM>+#gAOi5c*Y>IyTP zk6z7atSnq>uvn~jG1fR&JJRziMR`->Q>Xv#x!kX3HD)%w$6XtXfyRsPSxRZ~jx41N zccfM;ONj_!8MvfCUuae>1f8CJFzI6&4%cx{1(XJ0eVr|$xT|G$Q~UU7lfL-}JLl4d zD$Y4P>oR$^JRxusA0M3$cRi>Y?j1S{@iY3)w<&$MvqCB;q5ZOzqBIt*`f0dMR#zSy zB+;ddzz&Dk@6rP$Hy_sC_VH=aO{f0SbwT`gj6!@@q}eY`O4{wwQq^fFNxwZCxz^!A z?JgBT-hn}pTzm)gW`*sO`v49J&J52MLD$_><$S;g4oyX{@WV8`E#v`i`1QGH4) zJF-vHCb#S7to@plAV@9lg}DcOV_9D;tY-!dt&DdWow5b}X4EWsyo3ZmBJUQ1eFF{l zn^n(*y@8#R-W8-1svWRbjJb+4&S;Q*(h4bkfCEK??Wd!y-X`6~*VJc`rc`0&9$OxC z8114O(Q5LylTmgvKz)&CtgOw`DLLc+2;G>*oKTD7&G$uovq-`&_pR)zyIi#!`CgLMRwKO?UH0eXul_!( zKFq4%Bgf5Wsu0S@AUEXjR;J;I>`94MdFdmdKV8wP08hPExxec*K>a_j4ev42BJyC* zS0eT_C%@$z;JeB;@RTO=)7LoMJQTM`2tat z43CV8m`ty0?QfzM(Ar0O$439*9EK3(jNZ2YI`2ZpWjgR~j6KT>v*AQEl~}gy&(JGN z)T5b(Fy7{9zVejzgtmYa2)Ug^DO*}`f6-v$+~zOd8|TzXM7JRl|48;DYcwK!M~wh_ z$!QE|ZEK4;yDiB35S|J-R=baZBi`<;1aoZ)8vlHH}+7aCeO zMBHn<;fl3A=eV&xx$p1F2{BIPwcM-l8Fk`x*Im)Ks zt$e~$(H!wKLRM@MdF3TEc^hV(N6t5q7h9O?HyH1v*;b*md9^P*SH!%kLQ4mNI$vQjj2MEEt*#G%862TzeOj zj2)N8zAyIr#~^SW`4hK{m2`s$TRMtKk2O1vV#r+*baTT2udfs3O+_RgsiUMlIWX_Q z2sXdp9}$Ju0-5WZo?dJ=eP`JnKI#^^pfM3O?6zQ#f0fQ;6!F%2L%lvXRc>@dxg~6# zS&#f~AeCEVu8l~P$JBiEfhJ?}2$e}W3wd>JM9r(-p21B9|&S7#hd;LLmI@=L4 zhVM*t#1{P`NN|e~eFI8))AcAp+hz>&YuBmyik=M_*|29R1I9LSJHEMN4s zb$xVpR~-HbdZL$FsxD zC4i@3+m{YJ89;uxM}wdt>0(?LuCW7lRAe_s7Fg)BkQd6Z;VJtBbCnt83ooFRl1#~U z6;9dqfvi$2eQz>|rQdpWy6^@dmX z=cWSXTLipt#|06*oU;50D|0Pjz8oH|8}gpu1BGBj$+wf9LO`bBs>JZS&aO>A*p+Ur zk6JraM`H#X_$?2L#;eNrd6v$U(zyw1?a;F6Rlnc^+%%uDVSTwRM9#cmYqL4HWZn9d z4V69GZ$h&_f#B99DvpF!w3SEy zG%7fOCRJndj5|ApDqv6Z>NdZVKe5A@=brYj?v?GI90Rh8XQsRdH;f;hWDYNe#`v3- zt%2)ZGc-Sur$#-UhVYC6>CLu}i5d`QlAez}?Kq#r^7nVfIW=k)+RnR$-aSjUb(nN& zGN?8kU8pW$&e zcMlLY!Jvh9TN_1{f4Uc#v3e#-F-hO!L1xyGc2JSBs%t{-Y4IHwQTLC4;OzoUR5_i` znLK0h)*OiR9*Uo|6;hr38m;tYhPx2(@T`gn|HJxl41e0lLT9yioF7ojv`K3W+-AmL zET?zL&r0ZZoZY?{#jY@c^*QIcD2>MDv7cM9^M0H4VapG_`DZRrf9qL1g-E%477cW_ znJGhRwc%0HhX_yf$Pjb!4$!0)0O#csvH%!)-dy6BPo;vmXBQ0(-y+6*RMAlh z&DPi|p+n%VOMHdkR=fvF=9gzV%>I;flKwsA=Z7EM%5zl^&zP`Iv2iP3H71&zF66F6 z%ep?}emnX7r_bAG?;Xe&BG}*32e+ML3bt6s@N|Ch z7-+Q(Sl1wVpce9F;;F)wR7HZFvtSft7Do|*|C7Y!1v#_n(Iq7SPu1#b`6a# z17Q4xGMF&H4gyqb1t$y8u0g2tDgfTRe<78v-1xkHghUT}7u0+nCH_O}J_iFb87T7C zB%ilC;tiN}2m{j}^(l8D+H9u55BD-+yy9C|N(c~vpwhRr+0^{oMFV9ECTZ>KjHW+! zx{|g{8Z|#pePbGUZ#6a-@{LbD73BO87kv`wfBUha(-m{pQV%1Vs|Y*#0X%Sn07U)j zeh0PPdktI~>~RA?1)6B)IrBx-$zQH&nADrxBlxIhJkiS%x}hj%RGBj)4|;lfFzx7v za@KqV<&ksS&TBbU?cK8s>~cuSzn~o!5@8bY&PlqQ2$X~l)$afi?A%3u(wu&dXHe=P z@WAQzYwm=Zc&^&$d{jeN>F3%ps%-m!{3Yv9v=&ib?ZMgVHLN8od@Ey-$ zhaVR}@s5DIt#%AbidV#Y9Ku@&3uQ&ujT`O#;3vDH zJYyAxq>Wfo_D3zMcLEgRA;zj0oShBe6H=mG+(UR)ABD@wDhuua z;kj=Uz+P+6v3}yq%h`>~yA?l0>^6+e@+AKwWJaNu_7_uPFmDTAegf7+^}@zRqrAaz z-h=TKy>NQpGbVjJcwcAspavT_kAJb8jR?6^ zHDK{v)2Up2tftm!zM)UN@m&|SHQA9+1x)}FJRS04#Ov` zaGGB`CMJ`Pu{OM2hWMEGojCRf$FIp*dsF|62Ot-TW}5JiP_q53-#PKn)wzg!X)KP1 z2wLa^Nlw`Z^b2`hGP{WG1o5P*!k7gr{K1LAM7|>An7rDPIt!60z1Vd?r~qa8LNAMe z0m7gFiVIZJh_~B2L1^pEGPO}vSgeZc_p#{9r?I_CX@9SQx)5%IlKSEN46Lh~5!6fE|Tq*xop=+4@{x zloM;)44qzA9Uo0ei|e}aet_TQUwY2CZUI$Fn>D!odFAUGAW}cSL+AMl-yR`0cF`7g zhMByS?p%m|)S@v}V(@E}Moej)r>rGsb*pZlNv3?83Dg+n68?VWSiIlf*->&UH{yia zNCxUY`{IWm0xw)dNaZ{hZ?c6=t`%8t8}?4ZjsS|ozwaiLgoG>Ud#Ddi4-QZFJi=n* zGHk~RZNnu^^$*wG1Zl~W9v?-y6WEfmsQbc`_nYNKGv2lVM#rPV7C`TE&xP5*beL&@ zTcIKmt~wRKmcy*&o%$*2_)PFS>LVYcxX?icho#jwzol?diB5_4_BU;G81Wgb`Q;}a zgz>G;gSsW;F_gZl;{}X7u)9R)$8tB*0$zlC+z>NJAo-3O181akC+Dk)|)gA=j zNOqKwdp%HXQj4qAtVgI4VtJ;6{)q!}Aixa)?~)aqGoy)wT}TDNekEuffq+}(6VQ6O z;52Xvu(F^4-bn-S2%DqTe4Z7YHS5U6OmCDl(Wt_~Gd1OOpREuLzSjoKP`j4SH~Cqq za9{?D^?$Gx{<&zrR&c$s1~+0NQ90DW3LiN+r_T3xN{K9yF)~AWb03|u2`*^;Jh$bC z)Z);NIya`Y_y1PeKPmP*p->vy18A3Oq#=}Qtf5_ZSdaJzJdear;8Xxvm(rVuZx&=9 z5z89yFH~#iJZ8(IJ@wJz>C}=^%qzj(8T+CyGp4p+kJIh?WO=oCWb-Pe!5br zk9_-FkXqhe#3&eL5!Bl``itk+-YzV9Ox>vq6Qf6_8+Q$sfeZbz`^@ctG;nT5Pg5ba z=wwBHOmdV$?gO&0+pWf)m$L^yA4_pIC&QAO%%+RtEg1fNmEZx>H%llRf3eDYzOCTa ziMhp|nu0|X;W_sWx!0Njo%Y1%-yF%|I@k-q zXD&A{B&BjPHVnN<3D zFsN@~@}M)alEa9(Yp4SCT&`E{?pqkI^SjTz-8Xb4w30jY>h8g%4doe^v7t4GCBKc; z3P$}s4ho<)jm!2K?@A8h1R+%X;&OAkn|s2sV838BGF;1@d&pAr1ynSk&B9smPuRbrrU2biia=YspF z$#z#MxQ>1DyFE?iP3EFnRj*y&n+%`!KR89%7zs~#33l*vsH7M%C|#|MkmU(#bx*^a zLf>k(5`2V z$Efp%T+u>6NeEI>sN@7^BHrQ}5cHBjY1`-2qA1bpr@Pe5^vK8;fD?v6CYIL2xV0%Z z76!xFWRBp;C3Jf?<5C|kFyR;kp$zs+^vO{}_$1B{Z?pLKJkyR2q#VB2Uc2-CjbF3r z=R_;muh~rq@zyb__0E%`Y{_B5e(|snrgC3k*hNS0)I#1A-#1DV!7t1L6Ql0K&toozMD_DfJ8|LGJ_R8c2}9F4{Ut`2Zf-L~6y5 zFWv*W5d8UbGbk(WadP#RD(7RvOomd1EeP~f3@Aw|Py;T19_%5PEn+5)2lANy`X-)r zv%9^vKUTm~KdHfE&|IjhkkA02r|=$NfYv$zURL1H0HaW{(69=qQ`Vcz(Ai+mJ1ZG? z2BqFqv1>U2#7lW!S#pM2Eg6f$D2IKT8av0o`3$_iNEJ%xF%+{`2(Q&^193{w1J0qj zlFr5nNEm<*IzVYR@g7i-o5G&bfWZYcK_Xm~<$m}yTmK2C2<=!k(jgW{L%xA$^mgAk zZFX*TSj0(iVx5hS^q7C9;yf zDJ7cJF3AI-r0s4v__bgQ@6^Idtozbl4I*47r(sY_on{AMjM(qRk{$!zoJx*ff-vudTq5j< z>lHS^+OZ{!`^I|TM(1t2w|zP5?l+n;vUt;eIAaF9&>kL_UQxe9D!gPLGLeNavIp8Y zWDY0T=au&1I$sWZej!W)N*YkxtS5l^lwkS5bpQkuyAH(1#fX7`9~S>nSv2u_aQq+y zxCOAeKI*)=J_HEWce4Z1GXHR7gR7L=AaDm2R^eU8C!E(DKl@(;(=JLJ!zemc*a8b1 zfxaD=E!vXUFFYAY5Io;pgSw(YXmH+8*puBwPmm+X)K*?ml_p1+0)$5%Fss6dv!v(%d#)=$?lc)}S+g-7 zjvOHJ3D+yrEAkF+kv`+SG}~Uqc~H-hplVyUPC6w?L&`kLiQ1JlSpZA0nX@mE+}SrM zY%R=fEdosrDS|ArJI`|Kai^_Yf1~AD=wRa8u2b=HB3*hc`8#js*qUTah#(}LAuoaf z_H8@?XbCQ`<>D-+?1y+5*LH0`b~Q~zg|4qy#$iJ$h1JQ91n*kMR~~Vp-1#p39xg}H z^U2+{L31@zZ67B+WP@8)-$kzh&OABrUgdGWj9*8r_w1@7McS|PFM28h3tBAcPvM?> zD2Iz&MQcmj-@w9?+JiT~6smn3>9K{jl)Wz7U8G%c@Xu~3P=Wv%xzb*xK$uxKr( zJBo2bdv{K|saqE4sn%a{(Vw)mzfcaXw3^9Q$~M)r^O?Hyh8;}3Qa~fg`Dw(hTi9Y? zTqMzl4Tfby(?MxZIPpj}?LZC9c{Z zo!WD0@oH9x)8CRM(UjgRg_OEw0AvHsDYZhwGc50pmc0~8*@*+-m{^4TsZu)c>M56J zDu(RX=*-)(at7tGSekfJWr+?N*5WX%2A4?Ei!tZTMVzdHHV zd!&|27Fmxe*GoEQBcVe)XTPAg?gXyapoiyM03`ul2DkJvGy#yXw?Mc+NEi*512>DZ z$m)+`CX$81b`N?yovtTSRbDfIJBPHxGnyoo(2xS>Zq` zT6Ei6H3&+VuuFjds?&ZuW4?c&3YuxC-6d9>E06xzd8g!3p-6k^>}^ZYvYi_W8N5)Z zoCR2>W@BgQn@_f#^&LgW-96qG2RW(R6NceId7=zG3p<`u;&MWEby1`NLn}6PE1ON8 z4fK7;(nu_Coz=GYn2P7+x+@TP&RT4_6IB^A$5FVz+_G4hdV+l78~W+l0ef__nY0dq z8dZ2Joi$Nf>jYAzix*?%vU?~Bx!Ucg9qVhM(h521$bhP>L1pt}a-rcFKE>Xl^rAec zp;+|{Pt#eoq&rLTJSl-b26z*KxX-`E+ZhIsyjpT4(G8WyFLPDdjV-Z!VXT{?T1$XA z7M6_i(B?C4IZO3hGXfoIwxKGSW@ry5miC#kjK4ZX2dYHix_0Gsl9Mx(Hz>}kDX*QC z?7JbYGlLJ{D%?m%YFRogx+gjN@~YZykjxzR3%#@8xWXLbtT5cM^KG;6EXPgec@esk zXg%^6=u@wR|HJA>4&t{f5{ET^I~`E*u30MbN?&EkrEbH@OdPV#Mc;er{)@j|rFb@w zJg15WL&+NbeVj4|qQAgC;7Qqn{l!8bWzzJETn(=LbNL%v?TP+CGP&nDMubPHwh?2g zvr2PXEkdwuo?ki81gEpZHyrpniyeB66sKWixzs>oIR*|`$AmGWI|+zlM*T%ri5tME z-y)()eHZ0!v^kfaz<53+J;+#K=yQ)zh+VGIP;Fe1%B5j5F}h}&3(-srNqJ)-_9~as zsMki7$xxw6!$?+r@Xj=JsB$gKGwXI$1={`6qNS%ybT(UR*z1Ze=B`9WP@BOZJM_%} zk8#v~sIw32l9@%-2bz3LWPUCVE*mN$aPN38&)z`?;~SRSvzFL)C7Q&5Dlvk3Mxnx$ zrS`u))x-*-)16)ov0iZ%-VAb7iYfC>PNaoF98~So=_z+epF)nnTC)VeY5~B4RiUZ) z$Ho>~GhYs|6^VIEfIsK0K?;1XK+$&sSzh6}5C;jElg_@*m%dov`h6Hj*1>k-)GGcS zc9|e)^KsA&d10USfFuV;fc)iQtp&xjZtAqPBcYlV9L^{>@rH%1yNAP2%IRqB%P&s5kZJ@p5p;Hpv_Z zsY8c^jvNBM{{QFD;Uhl)ZMS;U>IC!JaVmlr2dC={|DE;T`67zps!3iBU zaT{8d)i}rwZT-K|!tpAH&RsSWKlF^VYw>0K&05f^u8l=hla9d@nU0;ueYzEAwBlz~IA4;EkM3w78;8SM zYP;KW=ZD9mLsI`88np9k;zY)Vo58{5YyUgf;lCe?ToV!(v3mU912FzHg}$)EO^NAy z`@f$E3CZ)ROG|;_5s?k9>R7AI#h!e!>r32V_f(Gok2*i*cKU!K-!|1qx{FD!w1AqCyIq;%UnNy{$vCN-viu7|(O^ZJOfd zfmSa6`~3Vf{H3h_$-PFb^_chS@V%N2E)(NhcVic6k~SSQK4|y!#R!)xvph`ABM$_Q z5%bM^7XKZ(=D#q|^`36Du@wrC9R2qbUnVRrEF@xe^nC{Be=}Q>+vfU)HobXZ-WCzl zAMyDAek#;;?kZ$@ab=B330PX+&%GN?IpLJox?q_v5Zt+ab9yO)$tJfpMtZJFe%l4p|Tm-eg z(NCAOYTP*X{>R|2`(u&4i_6>pm4Tz~l=ngxE{F;V3#DC>Qdga^ zUcLuVG`nfux|wO4T9RpIX70Or4R_JfLcJsRHn%_`^Sm$`kB9eC#Z*gEho2;Jukxjf@TYu~@0wM<;9G zwoE+SG%mE`-`9;&CrUI*`Q4@Pcq(AQ7PKpE(hV~t#1HqKrEyn*Hrj2Ns4@LwMagN+ z5Q}gQm;Zm20DnXrd<)s#xy=jIme2o(m*TA#uvhy$*HWq*VWSGpb1N1mrtwW-WB<@b zGu|Dkr)(Xv@*2C)H!)(?ZmsW7KHb(F(l^-2_XJAVyH^AJS*VRE_eR&-@FqD_bI`7g zPFU7~y1a&Trt~?K5}1SsCKVIMzsf03|Ep3&u7LH=9-f@x#Ax2Lq5tcFJO1gJXdW>P zAN3DkF|B`1qm^EfnutfLkVAI$HgK36dhh)51EW~g<*Z34ez5(RwN?7}IFq&Qk-qZ= z=N;}aOp84nT86?=OB(?5 zPgae8+mWU4#k=S|dhOo$PyfZaVF!d76_IbzZW_v;fAQ)zxFhWiqNQr{o8G3~Lwe|k zdyOG_3qt%1e{#0e?vvj9lOkyIwVHS!e`av-1B1{;m7>g&&nO2#CGn;?@DhTLI8yAg zU!0V@uBKh6sEu3i>ol14}2)EYGIm;#W~A3P&Q~kBb}H%m1B6 zfdp#f8}LY0lP69E>1fAocf0w=8O|VuFukbJg|06bn@jRGL^VV#(iubDl2L1Z=yy1i zNVe$?ESAcYk_Gh^UN;D({7ArsqS}#diDn_Yl199qf<(qc^QZ;yF1D3rT#DzGopf(- zPRh6f67eqXU3PLKe)u10AU|Gg4EJh@9w`92Xfys!Z`dPpZTP9VSTc}6i)jw>6UMCZ z+uhD9HwEZ(6pUG=Y-VV=V+nRS?0ZzK37Hu1u@a*{In5Fa@t{1kip?E<(I!L;clKCb~Xw&4$j^Tqb)`_|U5_#>7trz=bH%Izb?_9<--Me#4J zm*O^tKh-u(DI{5Gxw_&2tfK+Gr3X%8m$V;ylAS(GLNJw4a$eFUrh^k1h~Ou~ah@9s zM;5w^76|VcblMF6NzvsJB2)Xz-5+zk_u^LsVe4-5?R%2SD?le6+)emY>Px`}2-oq5 zsiIlwg#LwVE(rH@3+?<&dJIUUPuNl}&;J&-8gk<|t$^|NW8EDiaLswgtpi_1#^A$p zk>9ws$CK@V>3V;Da=5^%xNz55Q^ASDeP;>fJIsua@N?Fe@XsKP57zo#(`#NW4wALI z5zv_H)OyEJ&#;y39C8q!GIYJOM1z&$TFWI5=}z`C24zPO;ljqY`7bmRT4b}XYFEh9 zMUWiwK)*Vye$Msl)HxMftV0>OLD3%hz+e0RBrJ3hnBd(WzGKPN&K418x4ZQ=i15}! z8LhNJ_~4g!%`=njwOkupF%eaVWRQ~Gt6=R(+7==`)Wz|^TZ7n5?Vg|*wRnd7h+#m_ zQHKUBrrm;HrS=yA1tI`a+6<(>s4aZ`WnyN4S zcDXsbOQ+st@1rJo#3__oHH!>zYx}yLFtcPGuPc3jT zpndzYD}mL6#9kzHbFN#P`m-5h!!p}pMn#q+eEwO$j3d5-;(!qo7Y>KEZo$t@XG6<} zCo4JQV|fYEfr#?*5&^Y2m9oyh0`E0Kwc(AzWfyr|tdstk#XB@JC!>1IC9JpoCt$_- zBV=3%U+c7kEZWUxOy-}-;HEpKS^8A)CBZqxxaBvR?Tn|ObK}#U!2#ZXa);(hMz%JS zf72}nIc{ZgMsu3a-Qcqb3r|HsVCRAY5Xi>*tUMQX?rR=0Ux-Hg^-9qP{(+)$g7UF_ zj@isXM{3lFd$?~!KxNyZHIp-hVaC!j!sbo4k>iJUs~jk~<;=L`Nv}d7cctUUSB_&) z#RHU1c$nXTyMYh%I_sNb4FsIT!^D$t`&0kGtBuNLt=yWj9Zrg_Rz{3?f_ojuEMq{& zREw-A)TD<6RQbPyHJ*!h^n9=pVR^1MjOACAJ0w8gM}Qdt!A0!W z@$PsSckIvj#>&KpnwFD$%7&u^e0u4g>ZFVaF5}Pw<>$vVj?rB*v$psI1ZJdBu{4c% z@p*%k5Jxon9?LSE8c4)=kcX@&)yCDQUD34Xg)SbnraghLq!6&IIM0`9v!y=o_sf;Q zb&?%qE022zjImBD@(W%{MD?n)yB`W->`IZuU?7_$V~M{aooFHk5ya*OfTy-sTXwA@ry@pe?5db@mz zSMqsrpX*G#Wx`*G@(%u>hT6yJPWERJho+Ux-J6MKPU?sK08a&%RL|Hv-Ff@C=v!Z} zm(%9hi=wI^By)mpL&37{R)pcA*o|@zrdzq_`IyGs(VNhTNJ`8U^=DR|V=%#JNw{YV z{_5rO8mmBbP+$}voZ8(OB&bmS5sP$C&N{iw|C(sE8k^+0N<`axt1|0Rcl?gfQj8(s zI%F@qvEgF{ln;%3qEus=RBCs;&YYyMH;%#`LEM_&Fb?PUrVUdXaIaj<9_WV6+4c7` z6;h&A@}6vP(TD-5xwvGR%GjoeUgP*7)gIfiy0^GM@@=w+o|H2~lo^gFRW~~KUdmoY zJ)JG(Bd|WHuHR^V_OSBjHhJ?@!1O=0`13)>*1|ki3!O(9F^lLONr)KE0*_|?{Fzxp zOT_G+`UG4%>2^AsApc`+Y5bf*wBDsk#o+giW`DVT8tW5;3F?3u?cOr8GG`{g#gT-((h?u)xlU?EMsp^q?nd&9S zDHHvhAAj6RF5$t-Bw-EBx}j|0Z@b%Ew(vFl_*nxjgjekq2Z$xUXYn&lQEAk_^${wb z^Ur}r%(>B6Au|$Zn3;jnl*Y?8A{NyJeC}smqxgoe)5CQMHKY0A;c;@GcR5wc z8EncMzU^0R_fE+(tIb{av-2P~ZT?uFtYdeULck#r)u-OE$K*6Bs%`G*HMpYGJQ^mU zm@6la#wT73&<9C?PMp1|^5;ZAc|5xiqY#|ecBe}d8ah_EJTong(Lw4~z*{ya^JvrW zLW9_wVmGs=siS2<5|GQ1 z4ls;4NM<^-Rr3Wz&1T{aYgl?;jY*=HejXUcNeYHfa|M)=gbRU}P$e&-z7ODvMvlB| zU5B$0$Z5qVPSJ8yY8r{lUpw?x45|#Lc3FLHMvrhR6WTr~`-5o0*&Vn)2-POFNLLtyn-Y`mi6IW49U~ zl|C+TA%7?IL$j?eJLrzt6J_i$xq06PRSwF7#Vs(}aonFV3ojCfc#Y?gsRU4yWlq6! z5V3k7aYI-@JG9`@O(U$W_+KR_Y&tz-lz71XBZo`VUqpE6wHGR1tr?MqzQQ>Mr&02K znuq2zjaa#lrKPX&Ro{W*waH;bXb1|ob>zl4|K7-v&`CA7K4ICfI~%`pi^&5?3av}r z`iDrX+^NyC-AE4t`v?C4^m2_b>#~b_RK<8=b2KHjJ7p)6H|_A z1^0`k)sv6dpPAm|`uI>XqJ2Bt+RT+rT9y5WhT<}q7~WNA+o5)7?3TjW%$FkCB7p_h zB`@Tu>W$e6U`?TD_SdP3<>;c;5znCu-uC}s6SER^Nm#pXE8yZc?Z|wCbDJadto3<2 zZn)6f-ZDZ3&O0=H_Z!wqSB2zg_raaL@FO;+xJ8Vc;rphmByS9H!<#{vtC+&ee9gSS z@X)fU8iPK4wP@}-6CJ~5vTvKt8#l~?b?JobNU-+`} zIy1zERgHyPg4c1|1b>Ua?GJmZ62Iwz6>QnDi znb#PnvcudkFDGcqk;}g6s5|PxRJ-M&N^)(=ABjiUT&Ml3nZ7m=wbaMjC66(NO$bz= zmv-fi-c$`8Y5`0dGwmzK(61BT44{n<*I8)tc+(YKtJG$?z6zdk%dFJoo8LK+WlxeNbUi*UqF8*%?gDZ^$}V|tu$g~0$Jh7Ra=w<{Q(28Uk$Tr64!=hyEr5V< zH1S{K)*~DnXsSgp^#t5X>cOG=VCC-|8;aX7&S!pOV?#TrBTiwTe>=3^dVqr*yHK7Xd5zLo9A2Y;Uyz#q?vj+~ zpm#ZIE;pyjvqsq3vtl%Nuaz3v7DObZy4*wIJ!3aI?Ysl0Y<3{?vEJC`-r;+$l$=Sz zD8oH1B#2l6tz)Vm&;DUtE%AREE(cEhCxiLOvdLmEJAgc4KBaflsL) z7`WSPtU(`ohMwaISHkSJj03ba>36vGe!`yiD5^trB)bGonH%%0;}}5AL7+2@uFC4- zuz<1|KqBlr9neVXo{lr^dTjUi$t59X7?~mUb@JXw@grOm{?8T9KXf6M)rQ*LMh#SZ zGJlavIPp(X=2;c*Ya2h7F3ns`A!NujV&h?P>#=EAy9$TDsVi9Tln>k@d1N%SEO;^^ za-@$QQ%TBMl*S!|u3x8Ye#~v^3h%AT$9{a_uc1Sb*4F2uq)d;(uVkH#WmWRv9R3tZ z?M&WEvrEEsksHDBM>0Jxa4bQS{kdMhhWem7WslcU$ZHXL>tkRmblWGSl2~)c93-M( zW!5bg_eNWW09Q2elsAje!C!& zG*hwVW}%R(CAy*lFc?Fw@7ObPVs}S0pQ-FGWv`s@1G@RRFINpcd_}WE{ph@iTrDff zKB7F&kcH7eCLn?VIVI~ezL*c}nL!Az=xjiKm4J3*%!<8{mP#40e#SyNSu;;ykAT7_ z@eauWxfN~(X$_sFXRhqo3S8phLyBo_4Y*7CGtK_>4;FP~%J)zn-yan^oI*V_imiE| zRcUm#VJwdn7rr>nDla#-*5kKM!+)Wan~A8B-A}-<-26dx)Za-1_&mqBQJ)cG2S|Ui za6zA+WfqTqzQYV*^#gR`NnDc=!B7<);n4$)ehH!*3N}s88ihp*pS^@D$k(1F&fF?7}+iAxs@CN3AG7Ti|zxl$*6ARk6yUQ)$1 zPR^vhL!)1QXmW_UAKq5y9fe?X3I~m1>rl-;oVHjZJ-B&nfVwfLkarBGUpP@CgRXMz0mX7p;vr#ty-ILiSXkWF z5d$G!XH-f$u@;MppNrS-KFvAlqwLm3is$2UQ)>>WpvN;kU}=#EJ9Ldn(WBAJ@3!)M zU*nq9sM0xPIy4H0Wve3NIBJja&v*zgN?QJt!3@Vs9>ZBLL@#MxPlG(x7Ec4axYoC+ z+tOG@yWbs%;4$`P`)ReQl9ba&o0w6|aJGuYJ!+6WdLXMNo48@LQ63yzm3i!feeB~A zS_9hgv4zCRCqm z;LR=cO`|CV@8Gy0Hn~{%PEz)=@^0iuvTHuPUR$qMULNp|`%ItR$p1PWA%x&#>8i_3 zYLCX?ylhY=@*(1NJEJuccYW9+qF?0HU7VIsp%uPg;`HNlg(K!qz(M!RPC*v;)3B4a zeN9@vdyxv?-Up^{EU$!Caw_LA>UMpOCK9s^>WwNghwz-RIddvvde-Y3-9fMySJYS5^>m)%VbfAS^QcpQQALO2fw01P96GhH>KZvO!bG z(UFqlI<2eLchCQw@~1}pibKV1RavH#ZfEzm#Rtmj?zKu|?>Wp?-*a9vcV62$qAH%; zojx}o&|Vt+DgCMhPTotVroQxmwVT5^mbyAB{=b=kNR<$Pu z|CIM-*rur2mo6f?GdO)1U*=EYm@KCve-8U0-sQx;-sPy%hl>oiS_e61-3&R1%{Xq< ztj(ZPEntBcgq*x))jNF{orFbthx6-n_iU_dIeL=4tuB4@#nMKg$-niQ! z@lKc5rt4R!{2t27i0hhA(<1{L(^opQ5M;uLX|wMOOhQCWtaBF0^n{%^Cca5`k{0X# zt0Zzh+$~VhUEb51?l*Y15#Z80n|({3f@J5~d@%Ooba$0_xX&yC*#ADnu&E}Zacb@} z6Qjj63x=n>$0EH^A)Ze<>GR`jG$z~o6c$Ng$yAw|P^hm$$DtUTl6fJ2;#T04e8kuj zhO9J0zEBXx0AU!3O#zh;@snYqaT-GhyK^$JE0|7glTXfUvad}B;8mzthW5EWvg{F> zyNakDlv|Q|RFL7IXlk&sG140R z3lo7q`>KqG98v~HPER*hv+x<-VF|%|_-MgbPPy8qhvkA4gC3;CZf&idb-|(mr-ZX@ zei3W~!-H+8+9NL?;Ek-Iwe?;Bg+GSzrKPz#V@4PjFFcMbytdsyQOxx_`OJ09k%+4( zf~y|2frUlS5d->4jTw~UPvMR(Q8%O{cx=E}OvHC35Z2nkr7vy-xkg-d!cNx8RyvFnpr?&eX5r;B`3ztJL zi;-%NJFJ9KNVU@u8}*E`9IZDs#Xmp6ge8~%-WS538}P6YQV#d?2axxFek;9j{&aC$ zxGZ2yQIl7^Aa|*Z_`@7Z*Xx4w6%FohZ=RivVyb!@6%Uyg&a{lZl^9T`$-HWs;FCx+9M#i zu=svO+$;=__C>_hEzU3?ua+~u5u0pR@8=t6>1Wy+xqozGslulw->FK>L$nasi-2Z5A70`3gaDOE{c;{#;9VH!UZz8Zn{6wH(Pq{j!T5tP9x zYAdUPv-4ZG84*=1k-E@ZY?40~AHMx1cX_FeOhb_5myP8kJtTia$EJ{f-oM?W!^g8w zyx0Q`F1cA_-Gc+Rw}x|N8vTvNGFyaqnlY>>P9cPSRgZkaEXaM@33EJu-)(U27VLe6pAnbX5enICy#GCe{cQbt{IU_3}MWi~x9N+R+7`eFG z+lkruc)&fy)ExB3=J*i=uzs8yHkfV9@eXV?4BKoR9}Zgg(jPw4=DN0za)JrHzjd_mwAk6vnQb ztJuyA2N|Br9JTA$?`+I1F1nt-I7R;coO67|$PJeD#tHVMFgzlNpz^0-twNDi9`OhZ8RoJQ;Pe5y{9T`qiPzd_*^IMbf z3rKx9Pl^7FCvQR{EFIA!o%c4~{zM>OBm@F^*O>NqsooVPH(=miV>&zf+lqk+L2$Pb=Y}r10Ro9|2D}7-kpA0B zyxzvIlG%-A8W#{~ehORqflN7e-a9Huhi}NM@1rS+`uO7W^?Ct%O*6tbo&vw3qj(0r ze{86mr+JHGw-)>OAQ4!lg7h18BGjG$HiLGrx?vT(Eq?jM$Hx@Kt@+uvE7=YpsV=&P74%3)1dZO@~MN<>sa%XFv0v@2Vn)f~0pd%k3ab zSm4Y8X%1Ah4I(v-h2Akd`piPl_}t)7U)KN&57Q|=H$6W)D~#a}cUDA%zW$vMSli84 z3%BVNjcN@j+QtDOFCRsD^+vm-0rxT8vDueYUi{1Ff$6cp(SrCptl#|V zqw?=+M86gPXfibX|CH6Xx%Uc@A#IO>kG5Q^>n{(v@J~izBcD78-Kf$hsuVVjhJ!Du zAP+AbiFENU(AtfyZaaQ*rKyYes_S5ay{{tOX(Jm*=k)HYWE4uFitf&nl=}M`y z@U6x1d;+*$kGuk`pNW14+ZNgu1N&hZ_v{X3^tlFU*Qa0~|7ytKIcSg)tRZ~5QcVW( zT3V~1VF;t4m$MiH4KN@+)5D_dhW2H=RsQI3Qd3hi2ru`&616WCq^|b_tf*Cx|2X!E zZJD(8zO*#UbgsWrp(U)Lt6C-lS(m1|`z-{rFM9_%{I+kk+_0572vmUehDO%eb%jX5 z$t~~B6p)E13J2cT4;jF?K7#r$69yn~WeH;0pmHPeqvdQ4M(pkD0zwxbtnT{s?*l~J zIxwG-nsK_Y-$C6q#{n*N3UvT}JcDg>Ybm>%Gl$6}`$R*(zPEGn=4(Q4(S+bsfyupN-5TK=_49@cIOn1fgpJ5Ys(V z50Wp!p%Ha8ass|)e?8YPB9R!?$MyWo7YD_kPZ^# zV(?bYGq736Yju0eGWDS8lb$#_pksRUe>$fBKPA(Dbxe2tRx;fI^kz_Z5>d7D2`=Gc z3DstKi?BgW_}z_m)c={n5NznteuuUnSg!w?olR@@$o1pkV{LW$)+$G86_5XqZ zQ^Vr|K2CPL?0nQd$V2{h2-F_!8a<1bpDf9evI~3LT|XP3;I^$o1t^NHgk-ulKD&9~ zzs#Z-;<(-;$Qg*VPXhtA4_JWz2Gn2=u9+9DZ2rG6PzfpCb-{1CgZzaYM}26}{jeul zow{1$?fs%%pYmg>=Hh*UHE9qY?mPW&9+hfmhDpI?K*;_th^{hiAEl-h?6XO|1A$mx z`4_vRI%qN`we!D;3z+&$TdtZEQ>T&g#;3~`s+07si}OpUgbSj+nWcJK^%bSWzxYul<-;%*2)dQh}t0 z@CvrermfU~;1-BV;<@*{+Kd<9(O*qV?avqYCXW7WI+vREAZ`*X764TnF#nwoQ9mT` zxya-FuMkmxHW}9;e)p@51sEK3>9R$w%)c>v`>s+Fi<(~vXXx8A^S?0q`0x3+SU_Fl z8WWcJt94`D68#kGv4Us4ghHr3@}zb`^mg=4erAnCwyJ2t(MHwGn| z>{;;hu)st#$KCjv>7!>@}#8y%$cOU3aQZ9iJ9^9T7RF^QHIc z)xPa?BBpVVo#M|IByR_F+4cQS(5X@_U=}QZ+c-RO=#diZJ*fv)gTIArCjfyY*lXnX zT6m~|`S0NNTIN+|*i%H|OT4gRwE zZVG4V0lR=9>kPMm3aIfI@@)MG+I?GPvsjn{q>w%+b4V-DOd@&{uq1W#m}6bxJ-r8 zXX$S5x?A$FN((7a&F%ET_l+x0>9iYx{lg}JZCdj+(fx`_Vvn@HZg0KLUzpu+NDA66 zcpF6YS?C`5=!x56u7`lc{{kYZjJwFdn?+1l4fJmIG0$zhlpY&+$c||e0oe z&`ss@McXv~hCQ3$peNF^s8_a@0Dl-iNjm7bSsnGw(I5^7{-OmdC=BQ+G?f%RAJvRH2fv7#G ziy+wruCT|kX5MI(7&cjUB5811wX-KruVs?LM8+HO(^ON=DKZ5oc)nwbK0G@5qAXVvrh*fjPHadgEc zd?dh33siaRgweL+dYrwqW^3Kplai4sMawl-T(~L{&=c&kYdh$d+2qa$GCPiPtFn zPjgnpc=3ifVT?IBWvfd+WpPql3t&)SK={-;Z1QH1i~r;A;r0U2$On;~w*01{Rx1;G z=3~-}7nuq{Mz(2uJ1ZhZi*T2)gNR93rawD%^$rMB97mklO!)jcDfd^% z_9xp0d3l@LBB;5AFH=MxDJgMfKP@nroSF&}T~qep({#Tvi;6maW#$V7X;Bg3G*+b= zaP)Ve?XlxSJGBEm&O=FfS|Ms?qvWA0y6>&nkQ9GG$}`s3us%Q^d0%tb(qXlYt#BN){s5!53@X%|T-P;r0&+ zTS?_pFDL#t(8c=a%1>dvAr;HbCWL1)6=IP7N-)4Hx~_m!?4^}fZcMV|exT_=Uxrx$ zo(7AKCCwr5$J!U6l^)Ac1Q&YE5L8hVGqcPzj4_ujp}k7??LrUB9b|rF=G-qHVruo( zq4IVhiM3xi<(1kg$B@sPv#w(|FMs{gP*&tN8tbz%U+1HgV}26!MEQfcxf1x*BnWhH zd5M_i@!t|eM6aMAdtfDhS7l?CZKY4uK0ucb0#kJ-noFZU*@Q4s_WY=p`#Dk|&uPx6SZJziNn<3kV`0nG&%WE1gh^rKz&(#XYN)^ zM@z5R-={=Q&b23ac>Zi^fLX+oH`;OR#}BjS>)G{Pc5fGlWAOS$mvW9^G(Es8y`gOF zc1y#R`=RsPgEi3^CkzxdC827rIDc`QJH5{oPi2E4p#6{`8L?|MmmS{j!a<3FQK9HO zCk@!82Qk~+8Q9%nz#*uHO0doEAvqT-BP^r0+el&j0EqODz>cj)IN5BWU8#DDV32}gBu1Y}M&G*^8&(8oKw*e_?9tRT!c51#~HoF&K zXs388gY#E@vNU<}h_dCTxiN5yf#1rE-75(DCPpN5SAKP1iKKA8D5a14qgq_kI z=jtAJoJ<^*UDjBsaoW<*WE7;{ZpEHnyu3R+!eJR%W24ldle_S z5#e3uW}zqEdl|(g8Xx7@tl=eUN^T?EemzrIW^}lL>83%NKBeo%erwl*xc@=y6oNJ zA76Bz7EP2KnCNVQ5;@|@@m_V*Je zx@@71IlVH^vNAb zHJ?M0+biD!CkRGA5R-QsCj@C0ucm5#^cv}P?tKuW+{8P6ce=45j(cOHs_v^Z_?nc6 zmWU|C#+<3w77Exu(w5#2QAEqYM>d_+VUiXBo?DU~_YK1cZ3-nx9)8XY_(KF< z6&gCe8t$SXfpyp%OrvMzdc29B%TY&lLziGD4AluR@G5-y9}~U&Tbepb1e@k35)yX+ zzVp^x`Ql@-YFTEo+JQ8^`;Yb?m`>i=+}zxB-Ka%xa!ETQGJ5sf9X7CAG$}T1m&Rj1 zEj`=My3TH{j`QVZq3x4uJV=#&bVk?gcOe@DetHWna`~B-$c}gv_Rz5HQ>lLt5Sw&l zKtPyJPDdDE3H=4n`i~pQro@;Q8N9wm{gc+uQI@3H7x-gZ&z0E~{qI~DyAOASBuv?i z1~@#ELD`8nytTM!Zu3M*<}OjmhTgo6aw=LF*`>$I(ujo52N#RJozF_O*9;=4vF zBcurnG2*g>xI+W|oaMo%Y2;)AwE7@O#AvRk za#{x_{vroqS$1bCK7``MCRinWf-p@T^V6rMp2c;*R+fcZhbm)3SLy=#`c%Ey`85fx zy=5mOvWj8sm+57gK)A0Ft%Z3};}G}KWp#6jw1sKf!THItl4d4~aY%IJ=g;?dHw~+k z?#tYc?D%!Bq4Tbi#WN7-!k@QHO;1|}v@=+0-`5MdYJ~oeA`LJNM04ZlAoiIZQd?+v zCr;s>2lNU7zD9Y}zDpdY&QJWSe}n&Or(~JBB(Pe}H5%2S1oj-hfOtWuPa6tq%YV@n zK4oKF-K<)gy&pYHKs;omcb`pq04^%x>#S7k((`g(Di!1xK8tt@ku895)sDU`H>u*( zT-xpIWpramBAxaanMq4B-qdkb@M~$#rn^an6wIw>|Gz)Kg=gp~-%wKl!k$8241Jr~X>3Vy|@LXzYtM*G=&ch>j z6it7%Kj;C8f;-eupft2*O+;@!BPKwh=FHOBGv?{HHTdenI@{+`AzT9h%K6% z?Jk{Vo+xaqwG)K(_uaHp&i>k=CJs$Yf1_VGD2BV%qL+Lphp2vz-*^OKQ6I4>_i58} zt0;k7ib%olbtjyGw#midyy`poSG!D)0xD^bQ)ED@A`&2xKQ|^uj4aVIl_+DB!;4)= zcFhJ`T{acP7^5FW$GJL~d@5eLV3jl^7j%fv`IG`*ZIaDbLYR9sFL-7lu3s*OH- zD<)mVL2w7}fBl(u;4rr=hn_1{oY+<6uYm z|5E*`y9M(JB?EXO)P;c^p}`IieeBWcjENov2%FyqVXv6j60l!D=4 z4adRh$(_o*AI%?uz`FsP)+i~sr3S#2MH=0rWEQ6R@Ebo6U1wI*=98SVHd41uSjJvYu-UQ#9Wn-?@d6tyL7r4t2dcTcAsUsZQ7 zSr)szm*k|O{fS;$ZHA1wv*KIA4KVbke)hODTRmm}u^Y|8J_1)A2b)VN0argNV5%~d z+I-NStPMNhGf;bfvOT@sNx>e7aP=?>)q9=M3Z?| zv{PiY=lT-yZ!L4#2AGI!oo$({onlU04)fo#V10xfl?){FFkkIA6D57C|`e_a?7w3Z1a8n~DPtU;lwPO9Tt zLx3&ZHw1lNzesG8I}!--^EBjZ4h_CR63!8WFI5DfEd5t(0~cjH;syO38y~V$l@-l8 zR)`4;)o_GHpnpR*9WEfAB#{7*rDdvZV6tEaOSgVneb&K8P3%dsQmRrz?;npNB~d0D z#KS+9@Bhp=DOxs&p7X1CrvPZFokeiy-{w01vIFP#_1EL;Jd5^iALxNVH99mva~&iC z91ptD~Rf~lg67vv5}yiWs;Y-X?J~_3<5PW*uTz;D@%BgJXd2w8GZeTM9gvHA7O$k zJCH>Y*oX-3WwkE)Be1U_)BSTH-yL!DLZy4k+2X^(sY5(zdFtKjoS#2d_=m!;HR6lZ zoKB)4PAxVBm)j>1KJDI^fGqNX2fJN*Y?e2(34YVBpX|>o?@EUe_C5@#_CEGugKI;c zu7yVq-z!8I{TOt4{{jX9>8~i#r;}CKr5bGEIfWXAlm0;>B|+}BC<|d3LFjl22x{c2 z06|ln*@#(u(XMN8NcE(0dN-E6gc_sw&N0pZLM{tLl=wrux6+)s0YC9h`up8(_Nroi zjt?#Us&oO(uf=OFg9aMvK#HVS){Nhi+@49qdHLo>LX5p(88SDy~&F zt>qf0plyk$!`u>23t#riy2)YtIbJz^<9fDABOcq1wTq3m)!Mo7W&su|RDO8}bTsar z!bK5$E%yDboBpVjf)Kxy++6|B#vgcmDoiWt$xnvz0h8E{fE3v{@#oLISBjexM@Pap zK7CuM6~sy-nEURCe6v#UF)uc5Wg5k2zUXJKXpQ$i9^~{4>!fvKPtT1FNol(mq)s`Ra;R;KcoO;fURzT;5)QH2&#-u`5~cxvjM6E`RX}FZBLV8J1+{f{0c(cpc+Lm|Ul5Qc}`8LKvzvH+E1r1izlt{hj@wWec zDw%k#KmH(nU@F}kFdvV6Xq-|#6E*c+km1A%+el#8jo73{Z>3~>J&_p_FC68}f8lN+ z9HcZo3cGY>Yeu~x{fgSQ4jn$q==}w^2Q71WW2OcRne38VMzJL~Z+aJu3~IajfXU3y ztwt>9_o^Z+5S(SI;J78h`n5 z-s%09+2y!j(d=)XlRxKxEkOhw_7hz;Xxsk6NyU<1dX|hUGT(VUW7v$k$u`ggp=Mzw z-2G0~x>~|}TM8*`mlVd5Y244h7{FQ-Kh?KKd&uj?Q!yp-1*=!ED}cd+^adK2cQfGK zGx->pbV#kxWOz7>Lx?%9!dx>VS^f&|zSlg~4s5PS@)5Jy%-nB0*0BryL}3Oj;>4gg zmgb4#V-z&)r8IR@1tCS?R42!xUsJCD2lcsh2K$DfEFrd1PeJ!PSz}neLwAZ@<^dZkk4YkfS$h}8Jq>I(i;~ip1zTPwH;=?o-T1LFfT;P8 zLH;Di7&AbDx(|CA|NMalw5?BxTrYL`2av|DY&19N3)E_^s5cJAjovJOHPz( zDoHpinD|N;clq4~#<=lvdljAkLuyH4%*05BcqScY82*hrC`{z8BT1$7x!9W*NcizY zFW?eS^G`=d!nsZQ(J8BSX^<#O{FZc#;{N?vn(cT6A2eJ^e{t1JdnTqfBRqPm@qxf= zz4ZLUv!6CiWL`?2OVcPKA-`GHm)x&shqeSYP9h6=Bm)t7gGfh% z$nfQWM>|{-=^sG2I!|PzWpRw`Omgw_p0~ z^Zdz5dr&CzdaCZtZoZoKeD@)ev*#%))G?fe!B6EzNU?PkkT$U#8wWs;TCU z77j>9K}1Blf>MHjbO^m8LTCwKXd)uL_ZpFo0wTRPAtaOtgx;hmMLGne7a{cC`_22i zcYW)dKh8lgF9vgV^-Ed&-3p@LiU(T!1LpGJJeNdov*l