summaryrefslogtreecommitdiffstats
path: root/application/basilisk/base/content/newtab
diff options
context:
space:
mode:
Diffstat (limited to 'application/basilisk/base/content/newtab')
-rw-r--r--application/basilisk/base/content/newtab/alternativeDefaultSites.json50
-rw-r--r--application/basilisk/base/content/newtab/cells.js126
-rw-r--r--application/basilisk/base/content/newtab/customize.js124
-rw-r--r--application/basilisk/base/content/newtab/drag.js151
-rw-r--r--application/basilisk/base/content/newtab/dragDataHelper.js22
-rw-r--r--application/basilisk/base/content/newtab/drop.js150
-rw-r--r--application/basilisk/base/content/newtab/dropPreview.js222
-rw-r--r--application/basilisk/base/content/newtab/dropTargetShim.js232
-rw-r--r--application/basilisk/base/content/newtab/grid.js279
-rw-r--r--application/basilisk/base/content/newtab/newTab.css654
-rw-r--r--application/basilisk/base/content/newtab/newTab.inadjacent.json3209
-rw-r--r--application/basilisk/base/content/newtab/newTab.js71
-rw-r--r--application/basilisk/base/content/newtab/newTab.xhtml89
-rw-r--r--application/basilisk/base/content/newtab/page.js297
-rw-r--r--application/basilisk/base/content/newtab/search.js15
-rw-r--r--application/basilisk/base/content/newtab/sites.js440
-rw-r--r--application/basilisk/base/content/newtab/transformations.js270
-rw-r--r--application/basilisk/base/content/newtab/undo.js116
-rw-r--r--application/basilisk/base/content/newtab/updater.js177
19 files changed, 6694 insertions, 0 deletions
diff --git a/application/basilisk/base/content/newtab/alternativeDefaultSites.json b/application/basilisk/base/content/newtab/alternativeDefaultSites.json
new file mode 100644
index 000000000..018d3edcc
--- /dev/null
+++ b/application/basilisk/base/content/newtab/alternativeDefaultSites.json
@@ -0,0 +1,50 @@
+{
+ "directory": [
+ {
+ "bgColor": "#ffffff",
+ "directoryId": 10000000,
+ "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAIX0lEQVR4nO1afXDbZh1+sxbWsbGvsrLbuBt36766sR3sOEgiuU4kx2vTpFGKm0SKsyyOlI8laUZTulLojQEHx4CyAaNnt72yrivklo1YSpxcW7YVbKXHgCvduCvroDt6o6OtLSWN1MRWX/5I4imyJMu2bPNHnrvfSZbf6P09z+/jfV+3ACxhCUsoAEouNWGlMRLri5GuZwUSe1Ug8bcFEjsjUPgHAoX/UyCxkyKJjQoU/iOhCd8WJSvW/8vpXFFsx7PGeaJsVaytul+g8KMiic+IFA7NTNB/rggk/jeRcu26RGFris3JEqIUtkFsdo2KFK6kI52pCSR2UmirZgY9YFmxeaYg1uyqFSj8lMXI5mofRb3rOwEAJcXmDS72ex8QvO43skjv3MeT2DtRX2150cgLzVUDIonF8xBh64KQ2FWRwncPejyFK4tYq/Nmoa1mPE/pnZ1ILe4TFxpdd+SdvOhxrhabXaeLTVjfsHfzSj5K4V8QKfyjnGs3P2UiCt/v/1LeyAsNlXebkbeRSOZ/Q+JCrBH/Yt7IX+qlbhS96dM+Y+dJLC6S+BWRwmazFizf5AEAQPRtHLEhukqMwo8KTfg2oamy8t+e0uvUczwDwDWxhopHBBLvElrc+wUSm/r/IN9a3ZtrbYqUe9eHTc7PZDLvoAcsi/lq2wQSO1M88k93r7ayjzdI76sxEv/5hdryT+foRknM696q9qMg5AEAQHx83WhWtU5i56PtG1E7fYkO+B4SKNd7AoWLBSEv9G3Asol8zOs+ddFTeWc+fDrXgq2MNmEP5+PdKZB/XR4RvRnWe8tjJ8+1ECsL4mA+EQ+vcCg8gHHuPjjZvc5S6guU6/3/POG5rdi+24IEv+KwEgFQ4QFU/rAKTu90pal5fCY60PlQsf22BefHwfUKD2YVfl6ACIAKfx2UX0QNBYj6arqL7bdtSIQBnYy+2iIAzg49Cid9bm3qv11sn21FggeHUwSILGQCgIljd8Kpreq+4Koqts+2QuGBmBL9FLsFSj+sgAKFnyq2v7ZCDoO7dKOvvc7fS3vcW4rts61I8OBxXdI6/UCJADgVvmGVHfMSAelgfUA6VBeQDqmv2nuzZ3rf6Y2r3SM7DB1RwmCnOsLaiGuenbWD/JwAcqI+IEPCL8H6gAwX7omADIn5z/Wqe0Iz1sgI3edSv6EjcR78OEk4jQiJCNhnlwD1ATlBmDqdCUHzcYRf3mXoSCIMXjdK95SeEAbfslUAk4iaEc1EsLnx0vNmAhw3q3mNAFvtFCBd2i8i4bdWAgYCDBkLwIMJw8antTDos12ARSTNM8JK5Amd8URAPmosQAS8Zdr41N/lIQOS0Z2/pkZe0iWoS35+rIY8rPfLvzcWgAdDljMgAr5tlwCEWgArjUxnnJXSmX8eMnQkPrH8OasCJMJgfyEE0KZxMrJ+i2WgyZq6gHTQ0BGFv+abujs//ab4gV0CqEvAar1n0gQXizj9PUNHEmHgTSFt1At4O3eCH+8D0tW2YUmoMkKvfyQzwC/vMHREegN8Tpe4zjIY55fD14+X9tgiwC8mV2ZrHS/LGOGXRd3y8aeKVee/3GrqjBIGMcMsmL/GJu6AW4+1QZRl/mKHADmipD4gz1jJHCIgw9oXJ+8zfVsi/ImXU7bDquvfI2ugZ7wHoiwDUY6BTrbTWRie+ti0d7rGrHTU5UD45StpX5iILPMZrQTD4Q0QG+2GKMckzcF28AXgaYiv7ZNesdokCb90PO0LP2TBpxQezKpFkPmb4Q/ebFlEHOWYZBY8FtriKwDXFDAHhLvr/bJi9TzQtPeycQNUI3HihkML5M9NfB4+caRTl/jHRsvtb333gTzzTUHDPonNZFkkfjVl7Zfr+MRtiMID+McICqtDvfrE2cWfHRxz2j321K155pxE84HLLWb7BK0odX75TEYTBI43hB1ch0HE554h7GJhKrkn/4wPMjfliXMSO4alcsIvx/UanZE17pcGMppkU2iL2zDt9QSZtwqu66/Okdbb88Qd7PydVFYfkGVthLWHHk1JyOteuHRjxpNh3JNjRtE3EgDlGIiwzLlqrq/MbvKtLwkewi/PalPc8PyQPDdIP8lqQvdw92qEZWbNyBqJgnD0VTTI7H74Je/1uRL/8mDr7VWjfYeJkecgdfC/6c8JavPL0+6fitn3JtdIzxbdqLPqiNMmwtAxR7BzZ+mgL2MnHGzHPQhL/wzlmCsLc64PbYPU4Xd1zwN6WdCwT/p61uQXsH6sL5TS/dOUgY4QCZRlxsuD9EDZsM/x4KDnk5ppSsqGfHehw3QjytHfQVj6HaP+U8F1wZbhMf1Dkerzpr3Sn4Ad/5/Yc2T7TQ6OOW2YBWZimAsVRzlaRoL0DMLRV/WW19SVh05+v5nbAxsPCPpZ4Jclwj95b87kF+BgO+5Bg8yFFHKZZkO68XqimoyvGd0FqUNnU/pA1yvTdbaRXwDCtj2CsszFjFLfSjZoRbEiqEqoqtE+6H2VT5LfvPfydtvJJ0V4jb537QhzxjLRdMSsimIhq5q538DNgSnbfqs0FoHrusUd6j2ScdTNyGZTNovfHa8Z6/fmnbwaTq5r+1wj0ziZrjlmvIKYP3ew9Hvk+NOPFpT8AjxHd6ypGOl607Z+YDUL5s4iChpkdq8b7b22KOTVQIPtGxet3bmQtVA6eKhnyBP6hvnPW8UAwvpq1nIdoeS6bpWY0fK3aMfJTCMc/csqtuf+YvNMi68Mt38WDTJPoSx9DGHpmaxLI8hcqBzpCiDB9ibnM87lxeaVLUrKg+1fRVimby3LPItw9G9Rlj6Bssw/EI4+i3DM+0iQPomy9JiD69hdztI7SoPtTWWvddry7w5LWIIx/gdCuvcjoZqlLQAAAABJRU5ErkJggg==",
+ "type": "affiliate",
+ "title": "Google",
+ "url": "https://www.google.com/"
+ },
+ {
+ "bgColor": "#E62117",
+ "directoryId": 10000001,
+ "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACd0lEQVR4nO3av0tVYRzH8WOIBEVDUUIGCa32FwQ5OrS42NKeRUOTdGmoqUGiLVBqa5UG+7WUREGiEqhTDkVJEA2iYZBkxKvhHumo96o3uM9z0ucNZ7zn834+XO59znm+WZZIJBKJRCKRSGwCx3AWfbiIaxjEPYzgOd7gLWbwIb8WsFjjWrU9q3U+u1C4/0yeOZ47jOROg6jkrn25e3uji27NbzC9A9n/hWnVNbVut/hOTMZ1bSqT6Ky3+A58jOsXhE/o2Lj4FryILBaSF2gpFtAT2ygCPcUCHse2icDTtcW3YSW2TQRW0JahK7ZJRLoy9Ma2iEhvhoHYFhEZyDAU2yIiwxkeBgj6FSDjXxjN8CpA0A1cxucAWY0wkeFdgKBK/pe7H1fxNUDmTpjLMB8gqLJh631A9dF6IUD2Vsxn+BYgaF0BhSIO4WYgh1osZVgOEFSzgEIRh3EL3wO4FFnOAgVtWUChiKO4gx+BvJSqgEIRx3EXP5stVsoCCkWcxH1N3EeUuoBCEafwshlipS8AJzTxW1DaAnAEtzX5B7F0BeAgrmMphFhpClB9M3UFXwI5oQQFYB8u4H0gl3VE3QninOoxVyyWozwL4AxeB8jdjqWgT4M4jUcB8nbKfKj3AUN4gN8BshphLtQbobIyEeqdYFkZzTAc2yIiw+lcQDoZSmeDe/t0ON+gPIltE4Fnxa3pnp8QacFYbKOAjCnOCOUldKhOUO12Nk+JFUroxFRkwWYypd6cYKGEVvTbfZOil2w3KVqjjHZ047xqKRWbZ4XHVed2Z/2d5a0167vYgHC9z6/df9bWs8L9uXO3RmeFE4lEIpFIJPYKfwAcall+TY3q/wAAAABJRU5ErkJggg==",
+ "type": "affiliate",
+ "title": "YouTube",
+ "url": "https://www.youtube.com/"
+ },
+ {
+ "directoryId": 10000002,
+ "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAACT0lEQVR4nO3bzWsTQRgG8PlPHMVLqRVMoQiFehJyUBAFtRCFHspExaaSoFg8CMGPSg+R3kQhh3osIbOlMVrbGKtrsbYESTbB0gqNVGu1WCkWutnXg+ihQjqxi7Oz8w481533+V32iyGEEEIZ76Rho0SZ4ewOG+D3UMatXSx9nPwqb5ySPZC0dPMzhDJelD6IrDCjQijjtvRBJIWGeY3IHkJ2EED2ALKDALIHkB2lAJoujkIwnoNQwoQL96aha3AKQgkTTtyZhKM383D4+gQEoll/AQRiWbg1XILZ+VWwaw6IrE3bgZbejNoAe8+PwEC6DOsbm0Klt679lxQGCESzMD335Z+KKw+wrzcDpcVvOyqvNMCwubjj8soCnBx44Up5ZQGeFZf1BWi7/BhqjthtzpcAseRsQwVrjgNzS9/hZWUFJq3Pf6U5MqoWQHJ8Qbh8aqoKB688cWVfzwBMvP0kVN6srMCec+7t6xmAmfmvQgCRBzOu7usZgHJ1TQjgyI283gCHrj3VG6C9bwwBEAABEEAtgAPRR9A3VKibpdUfQgD9KWvba529+8pbAMF4TqicW+th/r3eAP0pS2+Anvtv9AY4dvu53gCtMfGfI74DWN+wG5rNdwDl6preAGOFj3oDJMcXvAfQHMlAKGHWTeWD2KPw1aFC3et0NPi9wDPvAq/fif0LDMZzru6LALKLIwACIAACIAACIAACIAACIAACIAACIAACIMD/BvDKwUkZAJRx2zNHZyUBFAntTp+WXV4iQCf5c3yecUsXAMq49bv8Txsl6ZCTabOAAAAAAElFTkSuQmCC",
+ "title": "Facebook",
+ "type": "affiliate",
+ "url": "https://www.facebook.com/"
+ },
+ {
+ "bgColor": "#ffffff",
+ "directoryId": 10000003,
+ "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAA/CAYAAABQHc7KAAAEyUlEQVRoge2abYhVRRjHf7veVqSFhIQwa7E3ojXNpSiNgl0S+tAHKUjohbQohUgqKKwMSXpbsATdqOgFU4zKpAzMioploxI/WFBZmhRlL/S2lbpsudvd24dzjve5c58558ycey9B84MB95x5/vM/d+bMzDNHCAQCgUAgEAgE/rf0AOd6lJmKVrdDfI8SfxawIKNcEscfa8TOzBFrlj6Aimd5XnmAbx01TD5xiL3IiH3Y8zm4DXgaGALGMip/DDwHDACXKQ9wA/AiMJyi8T3wAnCvEr841t9tiR2JY/uB443YC4BHgA3ApyntTxD90FuAlaaBU4EfLIHvKIZtnAT8ZtE5O6fGCiNuFJiTM7YNWKe0PQScmRV8ncX4+zkbT1hq0bkyZ/wyI+5ux/bPM+I/ACbnCSyhv8tloMvBQAnYr+h8mDP+PRHzGXCMQ9sA14j4ceAMl+A70HtvjaMJ22jqy4i70Kh/sWO7AO+K+Jdcg6cCh6k3/gfQ6aBTAr5UdN7OiHtL1H3NxXhMN9Fkl2jM89BgPXrv3eKoc71Fx2ZqvqhTJv+kKRkQGjs94gE4PTZgGt9DNMvmpQR8pehst9R/Q9TZ5OG7EzgkNK720DjKNvTeu9RRZ4miMUH9bnCeuH8EOMXD881C40egw0PjKL3oP8Cbjjq2FWGrUW+HuDfg6XmP0NA2W060GYKy97odtbQVoQzMiu+fL66PACd4+O0VGqPANA+NOm5CHwVPOeqUgH2Kzub4/uvi2gOeXrcU8GdlCtG7ZBr/C5juqHWtojMOXCX+HgaO8/B5YqyV6GjZpjf3oI+C+x11JgF7FZ1/xL/v9PS4WmgMempYsW2MfsdtYwTRsqT9mBXgANGIc6WD2lG60EMjk0fRTS931GkHPrdo3ejpbZHQ2B+30XC6iNZm0/Q3RBOcC7Yc4WRPb0NC43ZPjVxsRDe+yFHHHLJJWevhabaIP0z0ujaNWdQmGUn5yEPrPkVnBPe1+0kRv97DhzPb0UdBr6OObZv9kIOGnJzLRPlL0+lFN+6yPe5BH0kV4E/yD+PlIm6bQ/uF2Um98Qlgbs74V5V4WVbl0GgDvsB/BBbiCnTj2lG5yVyqvX+QaOSYOsNk7y8WiPo+c1Ah2tFPesbJTmFfEfX7qU2BZVmRoSPnkMU+D1EUW5L0WErMHKq9P0o149NeqZ+w7wq7qO77f02p11Qmo6/laWnoVlFvnbh+uaJTAW616Dwo6rjmIw3lLnTjminZ+38DM8Q92yv1HfUnOh3AL/H9I7hnpA1lKrXnb0nRkqSXxf0nFC3bK7XMqCdT6o2NeIiirEE3Lvfks6kesI6hf1m2nTt8TW2uIeeLhub8vsxAT5IOUB2+8qTm2RStlYqOnOV7xLXBRj5EUWxJ0hKic/2k98dJ367azh32Es0Tz4hrTcn5fZE9I8s+ajc6m20CgrUWrdVEK0yFJub8RRhEN56UMjk+TVO7xtuK6yFMS1hIuuk82+SETSk6h3A/hmsJ7egfPypEh555ej/hHOzZYktyfl9keiqLzzc+LUlqWc7vSyfRJ3Rpegw4zUOrj/ofoKU5vy/91Jp+vIDWLkPL/J9h/0mmAT9TXa58vvIkzKe6ydpQ3FogEAgEAoFAIBCI+Rf5q90lTPZHIwAAAABJRU5ErkJggg==",
+ "title": "Wikipedia",
+ "type": "affiliate",
+ "url": "https://www.wikipedia.org/"
+ },
+ {
+ "bgColor": "#400090",
+ "directoryId": 10000004,
+ "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAD3ElEQVR4nO3bS4xecxjH8WmLBVVEx63JBIkEISkhJqURpAsZQioWqpeNSxraYlKpSwiDIRY0aSakqgS9qHRBIhKxYdFFFxWXIGkilYZEUCKj4zLzsfi/LN55zpiZc/lr+/6Ss3nfc57ze77n9r88/y7swxaswgLM7jpMhTlYiNWtnPd1Ga9RfIVtuB+L0J3b/FSFeejDQ9iBvRhrTzYCUKTv8RFewlrcgAtxQsYk5+Ii3IQHsBm78ONkk5oKgIn0Mz7BO3gBA7gHS3EtLsXZre1UnITj2pI5vvV7D85BL67DCvRjEJvwHj7HcBXGqwJwyKoDILeB3OoAyG0gt8oAGMYj0qdnJ17DY3i2vK1CPYmn8Cq2YwgP4rfpBix7BwwE3+aZ2F0ybqQPMSM439NlgpYFMILzAlO9glZXCf2F+cF5LsafZQJX8Q4oujKbK4j9j4aC+EdhT9nAVb0Ebw8MduNABbF/wMlB/LUVxK4MwE84JTC5uoLYK4O48/BrBbEr/Qy+XnCbfloi5h7MCuJurcSxagGMYWFg9qr/SbxQVTeEiq7Ym9OI9UYQ52ipJ1iZ6mgJ3h0Y7zG17usvOC2I01+12ToAHBCMIGHdFGKsCo4/QwJTqerqC2wMEjgGX0zi2KLH6JU6jNYFYBSXBElc/R/HjaE3OO4y1bYs/1WdvcFd4hbilgmOie6cGa1Ytaju7vDSIKHTxc9yUYtvWZ0G6wawH8cGSa0J9r0t2G92K0ZtamJA5PEgsfaOTNHjMlC3uSYADKMnSG6B9GIr6uqehYN1m2tqSGxre4KtJDdhfcF/O5ow1hSAMVweJNmNOcHvlbb3J1KTg6K7MTO62m3Jz1LBQMdk1fSo8IpJALizSUNNA/jWBNPvOFGahG1MOeYFnpgAwHNNm8kB4CDODJI/F380bSbXzNAzAYD1OYzkAjAYABjKYaQDIMdJxQDqnFMsVC4A6wIAgzmMdADkOKkYwKM5jOQCcFcAYCqjxpUpF4Bovu+IB3BfDiO5AIzrFWJlDiO5ACzpABgP4I4cRnIBWBwAWJLDSC4AfR0A4wHcksNILgCLAgB9OYzkAnDFkQ5gDZbj3ta2XCp5bVydYuncBnKrAyC3gdzqAMhtILfqBDCCb6SZ3velatGXsUFa5NC+vdjatrf2/QAfSyUyv9dlsgyAEXyGt/G8VBl+PS7A3PaGTllJCy7n40Zp8GQD3sWXSgCaDIBRqcBxGx7GYmll57hixlySaojPx83SuqW3pLXC0wKwX7oF+3GloILjUJE03X6NtAh8J76LAOzFRtwqKGY63CStX14mLen5+m9Vgqdbrd+9cgAAAABJRU5ErkJggg==",
+ "title": "Yahoo!",
+ "type": "affiliate",
+ "url": "https://www.yahoo.com/"
+ },
+ {
+ "directoryId": 10000005,
+ "imageURI": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAJdklEQVR4nO1ba1QTZwL9iCY8hCDxDUpYOIUDBOVZAlJ5NQXRFlEQ8YGiRaqESlhxeRQ3FAWURRC6FYglqBHTEaI8Eg+CRMRatfKwLNL6oqer1h57XEWYbwJK9sdKixiSmRCCbrnn3D8w351770wy3zd8ADCJSUxiPMHhcPS3bdv2/tq1a9MWL16MODs7t5iamt4zMjLq0dfX76VSqU8sLCzueHt7S+3t7QtjYmLWJyYmzp1o32NGSUmJd0BAQLmRkVEPAEBOhCQS6bm3t7c0MjIyHACgMyEB1AGCILTY2NgUOzu7fwGCoUfj/Pnz/x0XF/fXgoICXW3nIYTs7Owlpqam94CGgo+ktbX1j4mJiY7azIQbMTExu3V0dF6AcQo/RF1dXYggSIj2kuFAfHx8Lhjn4ODVElCxWOygpXjKkZWVxQZaDD9EOp3eXV9fb6yVkKOho6Njgb6+fp8ig9pgfHx8gjZyjgYdX1/fhtHMqSKJRHpOJpNl6o4HAMidnJxatJJUEWpraz3xmBxOExOT30JDQ/+elpZmD14+26uqqubExcVFzJs3T53H5uCJEydMtZN4BKKiovKJmA0KChLu3bt3zmh6Bw4c0F+3bl0BEU0AgLygoCByXAKqgq2tbSdek0FBQTV4dZlM5kW8ugAAOZPJ/IeGIuHH9evXp+no6DzHa7K+vt4Lr3ZiYuIOvLoAALmnp6dQQ7HwIzc31xqvQRsbmy5AYC6fnJzsjlcbACD38/M7p5lUBBEeHp5lbm7+E4lEUnonREdHpxPRLSwsNFWmN5Kurq5XNZNITfj4+EwtLCw0dXFxcebz+UFhYWFbmExm6qZNm/IjIiKyampqDIjonTp1ajp4mwrQNP70BfD5/D9PAcXFxQZcLteOwWCw9u/f/3FwcHC6paVlOfg/K4CUlpbmEB0dvSEkJCTLxsamwtnZuXXmzJmPAACDgEBYRXxjC8jJyfFYtmzZYWNj48dgjCGV8Y0qICsryyQiIiKVTqf/BMYxNHgTC8jPz/+ISqU+AVoKDt6kAnbs2MGeMmXKANByePAmFBAbG5utyJi2OKEFJCcnx+MxqYizZs361d/fvyw9PX0bg8FgZWRk2FZVVc1pampaQERnwgoQi8VLVK0DRpJMJstWrlx5hMPhvMflckmKdN+amSDRdbuenl5fRkaGnyrdt6KAsrKyD4iYpFKpTy9cuPAuHu23ogAmk9lIxGRCQsLneLVLS0tnEdHWegFisXgu0b8ANTc3W+LVT0pKsiSirfUCDh06tJyIQSsrq5tE9PPy8jyI6Gu9gMDAQA5Bg9VE9Hfu3BlFRJ/BYHSMPRUBsNnsfUQMksnkciL6q1ev5hHRNzQ07AHa3D9A9N19QEAA7lfiAAAdOp3eTUQfACBHEMR87MlwgmgBZmZm9wHOK1RUVLSFiPYQd+/eHaOheKrB4XCyiBrk8XguqnTb29vNDAwMeolqAwDkCxcuvKbBiMoREhLyKVGDy5cvr1Cm2d3dPd3Ly+sCUd3h3LNnT7xGg46GoqKiQHUMbt68uZjL5VJG6qWkpPjS6fS76miO4Ivm5maVd9qYUV5ePlPdtb+FhUV3cHBwkbm5efrGjRvz7O3tr2og+O90dHRslUqlUxX5lkq5U7HmJEtUsnTxwG0kEJ7b4Cer32ArlXIVHq8ULBarVpPGNcng4GDP4V6xloxArNq3oq+M9hTlUeSvsfwvPxMuoKGhwWO8N0RRKBSM6Bg6nf4jgiC0zk6Egl3czsYQhxsKQ48g4QIAAMDf3//0eIWn0WiPjh075jx79uyHeMfY2dl1IAgyFwAAZA1rjqE8ihw9rPscrXRp7xO5lckaN6X0t+dt7m/LiYanPI+iPPLgmApoa2t75+W7fY2GX7RoUcvx48fpAAAgEom88NwJLBbr65ycnGlD3gZuli15VhfC6JZy9Ubzj1W6to6pAAAAEAgEDsbGxv/RVHh3d/ezEomEOvwcqamp6crGsNns/NHeLg0HPPOhV98Pf2ynQRHG+ZcFDKpdAAAAFBcX+6qzF3gkly5dqjCIVCrVs7e3v6RozKpVqw6q8idrybCFonfrUB5FDqsWfzv0c1jh2IHyKHIotL0J+lsyY7CqJXmyO4hamw/Ly8vnhIeH51Op1KdEQtNotN9WrFjxpVAodFOmv337dkMmk1k9NI5CoWCZmZk7EQSZouj4bilfT/ZtUjhW4yNCDxv0ozyKHJaZ9Mq+S1sDAACdnQgF8o1RlEeRy5picsDA3dPv9QnMHqI88iAUudYNdJV4q1NEXFyc7q5duzZ4eXmdtLKyukUikV6ZL1Cp1CeOjo6tHh4eRVwudwWfzx/1MzoSXC53alRUVCaLxapjs9kBio55fC3bGPvm0wRUQL/3yjc9n9Yz0HX090zolTSP//2OPIjdEVkDAAB42nmYJjsbWjo0CEMcfoCNkXvR5lh3BAlT2LQqhIWFTZFIJFSJRELdunUrWR0NVXhc/zdj9MxHa6B4qRAemfHasx6rYUnQjn8uGD5G9k3CHpRHkcvqQk+8Joh1lX2AHl9wf+RkAWtYvx9eSvaWSn2Iz5w0jId1O6fJLn8Wila6iVCe/oCiZ3sff8YT7CLnE6BgJQoRhxtoqcmz3l8vK9629+xW6Sx4dnUmLJv55DXxo3MeQ8ThDKxlfS77Pm8F1pxkqegkmsItSZxu75nAhf1NMZFY47ov4MlFzejLz69ClhrB/vObc3uuZM5QpIf9fM4K5VHk/W25sSpP3tdaaArPrBSgJbovlM6m+LQeWO13HqtwO4i1Zn0CRZ5+2Hf7bB5cK8a9P6hbytfDOgqsMJErC7vyWRw87VUERR5X0VJDiGc2h/IocljL+rr3Klfpv9pg9xttsLOrVIcfDtltEQOtcP0CFZg/wGvmjysyvQ8VmP8ChTa3McThBiZya8NEbm3YSUYXFNrcRgXmv8Ay2jOUp0tMd9gdidWHFsiuH2QQCqUOuFwuSXY5ZT1a6dyullkNEiKMLky6NaYTeX2JrRXILqcslIkDk2GFYyP6lSE27oGPzHiKVTiJZdV+qf2dh50mJPRo6Jby9bBLycvRSpcCeNLpe7SEovw7Aw+/MpDBUx5XsNqAbHgp2buzc4KutDp4dHGXEVq3xh02fbwFq2Htg5WuQljlcwFWLOqAJ97p7hOYPewTmD2EQuu76Emn67DauxmtdEawap8ceH5TNFofznxQs5XQBstJTGISk1AX/wUPVWOeSpK50AAAAABJRU5ErkJggg==",
+ "title": "Amazon",
+ "type": "affiliate",
+ "url": "https://www.amazon.com/"
+ }
+ ]
+}
diff --git a/application/basilisk/base/content/newtab/cells.js b/application/basilisk/base/content/newtab/cells.js
new file mode 100644
index 000000000..47d4ef52d
--- /dev/null
+++ b/application/basilisk/base/content/newtab/cells.js
@@ -0,0 +1,126 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * This class manages a cell's DOM node (not the actually cell content, a site).
+ * It's mostly read-only, i.e. all manipulation of both position and content
+ * aren't handled here.
+ */
+function Cell(aGrid, aNode) {
+ this._grid = aGrid;
+ this._node = aNode;
+ this._node._newtabCell = this;
+
+ // Register drag-and-drop event handlers.
+ ["dragenter", "dragover", "dragexit", "drop"].forEach(function (aType) {
+ this._node.addEventListener(aType, this, false);
+ }, this);
+}
+
+Cell.prototype = {
+ /**
+ * The grid.
+ */
+ _grid: null,
+
+ /**
+ * The cell's DOM node.
+ */
+ get node() { return this._node; },
+
+ /**
+ * The cell's offset in the grid.
+ */
+ get index() {
+ let index = this._grid.cells.indexOf(this);
+
+ // Cache this value, overwrite the getter.
+ Object.defineProperty(this, "index", {value: index, enumerable: true});
+
+ return index;
+ },
+
+ /**
+ * The previous cell in the grid.
+ */
+ get previousSibling() {
+ let prev = this.node.previousElementSibling;
+ prev = prev && prev._newtabCell;
+
+ // Cache this value, overwrite the getter.
+ Object.defineProperty(this, "previousSibling", {value: prev, enumerable: true});
+
+ return prev;
+ },
+
+ /**
+ * The next cell in the grid.
+ */
+ get nextSibling() {
+ let next = this.node.nextElementSibling;
+ next = next && next._newtabCell;
+
+ // Cache this value, overwrite the getter.
+ Object.defineProperty(this, "nextSibling", {value: next, enumerable: true});
+
+ return next;
+ },
+
+ /**
+ * The site contained in the cell, if any.
+ */
+ get site() {
+ let firstChild = this.node.firstElementChild;
+ return firstChild && firstChild._newtabSite;
+ },
+
+ /**
+ * Checks whether the cell contains a pinned site.
+ * @return Whether the cell contains a pinned site.
+ */
+ containsPinnedSite: function Cell_containsPinnedSite() {
+ let site = this.site;
+ return site && site.isPinned();
+ },
+
+ /**
+ * Checks whether the cell contains a site (is empty).
+ * @return Whether the cell is empty.
+ */
+ isEmpty: function Cell_isEmpty() {
+ return !this.site;
+ },
+
+ /**
+ * Handles all cell events.
+ */
+ handleEvent: function Cell_handleEvent(aEvent) {
+ // We're not responding to external drag/drop events
+ // when our parent window is in private browsing mode.
+ if (inPrivateBrowsingMode() && !gDrag.draggedSite)
+ return;
+
+ if (aEvent.type != "dragexit" && !gDrag.isValid(aEvent))
+ return;
+
+ switch (aEvent.type) {
+ case "dragenter":
+ aEvent.preventDefault();
+ gDrop.enter(this, aEvent);
+ break;
+ case "dragover":
+ aEvent.preventDefault();
+ break;
+ case "dragexit":
+ gDrop.exit(this, aEvent);
+ break;
+ case "drop":
+ aEvent.preventDefault();
+ gDrop.drop(this, aEvent);
+ break;
+ }
+ }
+};
diff --git a/application/basilisk/base/content/newtab/customize.js b/application/basilisk/base/content/newtab/customize.js
new file mode 100644
index 000000000..39724fa91
--- /dev/null
+++ b/application/basilisk/base/content/newtab/customize.js
@@ -0,0 +1,124 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+var gCustomize = {
+ _nodeIDSuffixes: [
+ "blank",
+ "button",
+ "classic",
+ "enhanced",
+ "panel",
+ "overlay",
+ "learn"
+ ],
+
+ _nodes: {},
+
+ init: function() {
+ for (let idSuffix of this._nodeIDSuffixes) {
+ this._nodes[idSuffix] = document.getElementById("newtab-customize-" + idSuffix);
+ }
+
+ this._nodes.button.addEventListener("click", e => this.showPanel(e));
+ this._nodes.blank.addEventListener("click", this);
+ this._nodes.classic.addEventListener("click", this);
+ this._nodes.learn.addEventListener("click", this);
+
+ this.updateSelected();
+ },
+
+ hidePanel: function() {
+ this._nodes.overlay.addEventListener("transitionend", function onTransitionEnd() {
+ gCustomize._nodes.overlay.removeEventListener("transitionend", onTransitionEnd);
+ gCustomize._nodes.overlay.style.display = "none";
+ });
+ this._nodes.overlay.style.opacity = 0;
+ this._nodes.button.removeAttribute("active");
+ this._nodes.panel.removeAttribute("open");
+ document.removeEventListener("click", this);
+ document.removeEventListener("keydown", this);
+ },
+
+ showPanel: function(event) {
+ if (this._nodes.panel.getAttribute("open") == "true") {
+ return;
+ }
+
+ let {panel, button, overlay} = this._nodes;
+ overlay.style.display = "block";
+ panel.setAttribute("open", "true");
+ button.setAttribute("active", "true");
+ setTimeout(() => {
+ // Wait for display update to take place, then animate.
+ overlay.style.opacity = 0.8;
+ }, 0);
+
+ document.addEventListener("click", this);
+ document.addEventListener("keydown", this);
+
+ // Stop the event propogation to prevent panel from immediately closing
+ // via the document click event that we just added.
+ event.stopPropagation();
+ },
+
+ handleEvent: function(event) {
+ switch (event.type) {
+ case "click":
+ this.onClick(event);
+ break;
+ case "keydown":
+ this.onKeyDown(event);
+ break;
+ }
+ },
+
+ onClick: function(event) {
+ if (event.currentTarget == document) {
+ if (!this._nodes.panel.contains(event.target)) {
+ this.hidePanel();
+ }
+ }
+ switch (event.currentTarget.id) {
+ case "newtab-customize-blank":
+ sendAsyncMessage("NewTab:Customize", {enabled: false, enhanced: false});
+ break;
+ case "newtab-customize-classic":
+ sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: false});
+ break;
+ case "newtab-customize-enhanced":
+ sendAsyncMessage("NewTab:Customize", {enabled: true, enhanced: !gAllPages.enhanced});
+ break;
+ case "newtab-customize-learn":
+ this.showLearn();
+ break;
+ }
+ },
+
+ onKeyDown: function(event) {
+ if (event.keyCode == event.DOM_VK_ESCAPE) {
+ this.hidePanel();
+ }
+ },
+
+ showLearn: function() {
+ window.open(TILES_INTRO_LINK, 'new_window');
+ this.hidePanel();
+ },
+
+ updateSelected: function() {
+ let {enabled} = gAllPages;
+ let selected = enabled ? "classic" : "blank";
+ ["classic", "blank"].forEach(id => {
+ let node = this._nodes[id];
+ if (id == selected) {
+ node.setAttribute("selected", true);
+ }
+ else {
+ node.removeAttribute("selected");
+ }
+ });
+ },
+};
diff --git a/application/basilisk/base/content/newtab/drag.js b/application/basilisk/base/content/newtab/drag.js
new file mode 100644
index 000000000..e3928ebd0
--- /dev/null
+++ b/application/basilisk/base/content/newtab/drag.js
@@ -0,0 +1,151 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * This singleton implements site dragging functionality.
+ */
+var gDrag = {
+ /**
+ * The site offset to the drag start point.
+ */
+ _offsetX: null,
+ _offsetY: null,
+
+ /**
+ * The site that is dragged.
+ */
+ _draggedSite: null,
+ get draggedSite() { return this._draggedSite; },
+
+ /**
+ * The cell width/height at the point the drag started.
+ */
+ _cellWidth: null,
+ _cellHeight: null,
+ get cellWidth() { return this._cellWidth; },
+ get cellHeight() { return this._cellHeight; },
+
+ /**
+ * Start a new drag operation.
+ * @param aSite The site that's being dragged.
+ * @param aEvent The 'dragstart' event.
+ */
+ start: function Drag_start(aSite, aEvent) {
+ this._draggedSite = aSite;
+
+ // Mark nodes as being dragged.
+ let selector = ".newtab-site, .newtab-control, .newtab-thumbnail";
+ let parentCell = aSite.node.parentNode;
+ let nodes = parentCell.querySelectorAll(selector);
+ for (let i = 0; i < nodes.length; i++)
+ nodes[i].setAttribute("dragged", "true");
+
+ parentCell.setAttribute("dragged", "true");
+
+ this._setDragData(aSite, aEvent);
+
+ // Store the cursor offset.
+ let node = aSite.node;
+ let rect = node.getBoundingClientRect();
+ this._offsetX = aEvent.clientX - rect.left;
+ this._offsetY = aEvent.clientY - rect.top;
+
+ // Store the cell dimensions.
+ let cellNode = aSite.cell.node;
+ this._cellWidth = cellNode.offsetWidth;
+ this._cellHeight = cellNode.offsetHeight;
+
+ gTransformation.freezeSitePosition(aSite);
+ },
+
+ /**
+ * Handles the 'drag' event.
+ * @param aSite The site that's being dragged.
+ * @param aEvent The 'drag' event.
+ */
+ drag: function Drag_drag(aSite, aEvent) {
+ // Get the viewport size.
+ let {clientWidth, clientHeight} = document.documentElement;
+
+ // We'll want a padding of 5px.
+ let border = 5;
+
+ // Enforce minimum constraints to keep the drag image inside the window.
+ let left = Math.max(scrollX + aEvent.clientX - this._offsetX, border);
+ let top = Math.max(scrollY + aEvent.clientY - this._offsetY, border);
+
+ // Enforce maximum constraints to keep the drag image inside the window.
+ left = Math.min(left, scrollX + clientWidth - this.cellWidth - border);
+ top = Math.min(top, scrollY + clientHeight - this.cellHeight - border);
+
+ // Update the drag image's position.
+ gTransformation.setSitePosition(aSite, {left: left, top: top});
+ },
+
+ /**
+ * Ends the current drag operation.
+ * @param aSite The site that's being dragged.
+ * @param aEvent The 'dragend' event.
+ */
+ end: function Drag_end(aSite, aEvent) {
+ let nodes = gGrid.node.querySelectorAll("[dragged]")
+ for (let i = 0; i < nodes.length; i++)
+ nodes[i].removeAttribute("dragged");
+
+ // Slide the dragged site back into its cell (may be the old or the new cell).
+ gTransformation.slideSiteTo(aSite, aSite.cell, {unfreeze: true});
+
+ this._draggedSite = null;
+ },
+
+ /**
+ * Checks whether we're responsible for a given drag event.
+ * @param aEvent The drag event to check.
+ * @return Whether we should handle this drag and drop operation.
+ */
+ isValid: function Drag_isValid(aEvent) {
+ let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
+
+ // Check that the drag data is non-empty.
+ // Can happen when dragging places folders.
+ if (!link || !link.url) {
+ return false;
+ }
+
+ // Check that we're not accepting URLs which would inherit the caller's
+ // principal (such as javascript: or data:).
+ return gLinkChecker.checkLoadURI(link.url);
+ },
+
+ /**
+ * Initializes the drag data for the current drag operation.
+ * @param aSite The site that's being dragged.
+ * @param aEvent The 'dragstart' event.
+ */
+ _setDragData: function Drag_setDragData(aSite, aEvent) {
+ let {url, title} = aSite;
+
+ let dt = aEvent.dataTransfer;
+ dt.mozCursor = "default";
+ dt.effectAllowed = "move";
+ dt.setData("text/plain", url);
+ dt.setData("text/uri-list", url);
+ dt.setData("text/x-moz-url", url + "\n" + title);
+ dt.setData("text/html", "<a href=\"" + url + "\">" + url + "</a>");
+
+ // Create and use an empty drag element. We don't want to use the default
+ // drag image with its default opacity.
+ let dragElement = document.createElementNS(HTML_NAMESPACE, "div");
+ dragElement.classList.add("newtab-drag");
+ let scrollbox = document.getElementById("newtab-vertical-margin");
+ scrollbox.appendChild(dragElement);
+ dt.setDragImage(dragElement, 0, 0);
+
+ // After the 'dragstart' event has been processed we can remove the
+ // temporary drag element from the DOM.
+ setTimeout(() => scrollbox.removeChild(dragElement), 0);
+ }
+};
diff --git a/application/basilisk/base/content/newtab/dragDataHelper.js b/application/basilisk/base/content/newtab/dragDataHelper.js
new file mode 100644
index 000000000..675ff2671
--- /dev/null
+++ b/application/basilisk/base/content/newtab/dragDataHelper.js
@@ -0,0 +1,22 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+var gDragDataHelper = {
+ get mimeType() {
+ return "text/x-moz-url";
+ },
+
+ getLinkFromDragEvent: function DragDataHelper_getLinkFromDragEvent(aEvent) {
+ let dt = aEvent.dataTransfer;
+ if (!dt || !dt.types.includes(this.mimeType)) {
+ return null;
+ }
+
+ let data = dt.getData(this.mimeType) || "";
+ let [url, title] = data.split(/[\r\n]+/);
+ return {url: url, title: title};
+ }
+};
diff --git a/application/basilisk/base/content/newtab/drop.js b/application/basilisk/base/content/newtab/drop.js
new file mode 100644
index 000000000..748652455
--- /dev/null
+++ b/application/basilisk/base/content/newtab/drop.js
@@ -0,0 +1,150 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+// A little delay that prevents the grid from being too sensitive when dragging
+// sites around.
+const DELAY_REARRANGE_MS = 100;
+
+/**
+ * This singleton implements site dropping functionality.
+ */
+var gDrop = {
+ /**
+ * The last drop target.
+ */
+ _lastDropTarget: null,
+
+ /**
+ * Handles the 'dragenter' event.
+ * @param aCell The drop target cell.
+ */
+ enter: function Drop_enter(aCell) {
+ this._delayedRearrange(aCell);
+ },
+
+ /**
+ * Handles the 'dragexit' event.
+ * @param aCell The drop target cell.
+ * @param aEvent The 'dragexit' event.
+ */
+ exit: function Drop_exit(aCell, aEvent) {
+ if (aEvent.dataTransfer && !aEvent.dataTransfer.mozUserCancelled) {
+ this._delayedRearrange();
+ } else {
+ // The drag operation has been cancelled.
+ this._cancelDelayedArrange();
+ this._rearrange();
+ }
+ },
+
+ /**
+ * Handles the 'drop' event.
+ * @param aCell The drop target cell.
+ * @param aEvent The 'dragexit' event.
+ */
+ drop: function Drop_drop(aCell, aEvent) {
+ // The cell that is the drop target could contain a pinned site. We need
+ // to find out where that site has gone and re-pin it there.
+ if (aCell.containsPinnedSite())
+ this._repinSitesAfterDrop(aCell);
+
+ // Pin the dragged or insert the new site.
+ this._pinDraggedSite(aCell, aEvent);
+
+ this._cancelDelayedArrange();
+
+ // Update the grid and move all sites to their new places.
+ gUpdater.updateGrid();
+ },
+
+ /**
+ * Re-pins all pinned sites in their (new) positions.
+ * @param aCell The drop target cell.
+ */
+ _repinSitesAfterDrop: function Drop_repinSitesAfterDrop(aCell) {
+ let sites = gDropPreview.rearrange(aCell);
+
+ // Filter out pinned sites.
+ let pinnedSites = sites.filter(function (aSite) {
+ return aSite && aSite.isPinned();
+ });
+
+ // Re-pin all shifted pinned cells.
+ pinnedSites.forEach(aSite => aSite.pin(sites.indexOf(aSite)));
+ },
+
+ /**
+ * Pins the dragged site in its new place.
+ * @param aCell The drop target cell.
+ * @param aEvent The 'dragexit' event.
+ */
+ _pinDraggedSite: function Drop_pinDraggedSite(aCell, aEvent) {
+ let index = aCell.index;
+ let draggedSite = gDrag.draggedSite;
+
+ if (draggedSite) {
+ // Pin the dragged site at its new place.
+ if (aCell != draggedSite.cell)
+ draggedSite.pin(index);
+ } else {
+ let link = gDragDataHelper.getLinkFromDragEvent(aEvent);
+ if (link) {
+ // A new link was dragged onto the grid. Create it by pinning its URL.
+ gPinnedLinks.pin(link, index);
+
+ // Make sure the newly added link is not blocked.
+ gBlockedLinks.unblock(link);
+ }
+ }
+ },
+
+ /**
+ * Time a rearrange with a little delay.
+ * @param aCell The drop target cell.
+ */
+ _delayedRearrange: function Drop_delayedRearrange(aCell) {
+ // The last drop target didn't change so there's no need to re-arrange.
+ if (this._lastDropTarget == aCell)
+ return;
+
+ let self = this;
+
+ function callback() {
+ self._rearrangeTimeout = null;
+ self._rearrange(aCell);
+ }
+
+ this._cancelDelayedArrange();
+ this._rearrangeTimeout = setTimeout(callback, DELAY_REARRANGE_MS);
+
+ // Store the last drop target.
+ this._lastDropTarget = aCell;
+ },
+
+ /**
+ * Cancels a timed rearrange, if any.
+ */
+ _cancelDelayedArrange: function Drop_cancelDelayedArrange() {
+ if (this._rearrangeTimeout) {
+ clearTimeout(this._rearrangeTimeout);
+ this._rearrangeTimeout = null;
+ }
+ },
+
+ /**
+ * Rearrange all sites in the grid depending on the current drop target.
+ * @param aCell The drop target cell.
+ */
+ _rearrange: function Drop_rearrange(aCell) {
+ let sites = gGrid.sites;
+
+ // We need to rearrange the grid only if there's a current drop target.
+ if (aCell)
+ sites = gDropPreview.rearrange(aCell);
+
+ gTransformation.rearrangeSites(sites, {unfreeze: !aCell});
+ }
+};
diff --git a/application/basilisk/base/content/newtab/dropPreview.js b/application/basilisk/base/content/newtab/dropPreview.js
new file mode 100644
index 000000000..fd7587a35
--- /dev/null
+++ b/application/basilisk/base/content/newtab/dropPreview.js
@@ -0,0 +1,222 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * This singleton provides the ability to re-arrange the current grid to
+ * indicate the transformation that results from dropping a cell at a certain
+ * position.
+ */
+var gDropPreview = {
+ /**
+ * Rearranges the sites currently contained in the grid when a site would be
+ * dropped onto the given cell.
+ * @param aCell The drop target cell.
+ * @return The re-arranged array of sites.
+ */
+ rearrange: function DropPreview_rearrange(aCell) {
+ let sites = gGrid.sites;
+
+ // Insert the dragged site into the current grid.
+ this._insertDraggedSite(sites, aCell);
+
+ // After the new site has been inserted we need to correct the positions
+ // of all pinned tabs that have been moved around.
+ this._repositionPinnedSites(sites, aCell);
+
+ return sites;
+ },
+
+ /**
+ * Inserts the currently dragged site into the given array of sites.
+ * @param aSites The array of sites to insert into.
+ * @param aCell The drop target cell.
+ */
+ _insertDraggedSite: function DropPreview_insertDraggedSite(aSites, aCell) {
+ let dropIndex = aCell.index;
+ let draggedSite = gDrag.draggedSite;
+
+ // We're currently dragging a site.
+ if (draggedSite) {
+ let dragCell = draggedSite.cell;
+ let dragIndex = dragCell.index;
+
+ // Move the dragged site into its new position.
+ if (dragIndex != dropIndex) {
+ aSites.splice(dragIndex, 1);
+ aSites.splice(dropIndex, 0, draggedSite);
+ }
+ // We're handling an external drag item.
+ } else {
+ aSites.splice(dropIndex, 0, null);
+ }
+ },
+
+ /**
+ * Correct the position of all pinned sites that might have been moved to
+ * different positions after the dragged site has been inserted.
+ * @param aSites The array of sites containing the dragged site.
+ * @param aCell The drop target cell.
+ */
+ _repositionPinnedSites:
+ function DropPreview_repositionPinnedSites(aSites, aCell) {
+
+ // Collect all pinned sites.
+ let pinnedSites = this._filterPinnedSites(aSites, aCell);
+
+ // Correct pinned site positions.
+ pinnedSites.forEach(function (aSite) {
+ aSites[aSites.indexOf(aSite)] = aSites[aSite.cell.index];
+ aSites[aSite.cell.index] = aSite;
+ }, this);
+
+ // There might be a pinned cell that got pushed out of the grid, try to
+ // sneak it in by removing a lower-priority cell.
+ if (this._hasOverflowedPinnedSite(aSites, aCell))
+ this._repositionOverflowedPinnedSite(aSites, aCell);
+ },
+
+ /**
+ * Filter pinned sites out of the grid that are still on their old positions
+ * and have not moved.
+ * @param aSites The array of sites to filter.
+ * @param aCell The drop target cell.
+ * @return The filtered array of sites.
+ */
+ _filterPinnedSites: function DropPreview_filterPinnedSites(aSites, aCell) {
+ let draggedSite = gDrag.draggedSite;
+
+ // When dropping on a cell that contains a pinned site make sure that all
+ // pinned cells surrounding the drop target are moved as well.
+ let range = this._getPinnedRange(aCell);
+
+ return aSites.filter(function (aSite, aIndex) {
+ // The site must be valid, pinned and not the dragged site.
+ if (!aSite || aSite == draggedSite || !aSite.isPinned())
+ return false;
+
+ let index = aSite.cell.index;
+
+ // If it's not in the 'pinned range' it's a valid pinned site.
+ return (index > range.end || index < range.start);
+ });
+ },
+
+ /**
+ * Determines the range of pinned sites surrounding the drop target cell.
+ * @param aCell The drop target cell.
+ * @return The range of pinned cells.
+ */
+ _getPinnedRange: function DropPreview_getPinnedRange(aCell) {
+ let dropIndex = aCell.index;
+ let range = {start: dropIndex, end: dropIndex};
+
+ // We need a pinned range only when dropping on a pinned site.
+ if (aCell.containsPinnedSite()) {
+ let links = gPinnedLinks.links;
+
+ // Find all previous siblings of the drop target that are pinned as well.
+ while (range.start && links[range.start - 1])
+ range.start--;
+
+ let maxEnd = links.length - 1;
+
+ // Find all next siblings of the drop target that are pinned as well.
+ while (range.end < maxEnd && links[range.end + 1])
+ range.end++;
+ }
+
+ return range;
+ },
+
+ /**
+ * Checks if the given array of sites contains a pinned site that has
+ * been pushed out of the grid.
+ * @param aSites The array of sites to check.
+ * @param aCell The drop target cell.
+ * @return Whether there is an overflowed pinned cell.
+ */
+ _hasOverflowedPinnedSite:
+ function DropPreview_hasOverflowedPinnedSite(aSites, aCell) {
+
+ // If the drop target isn't pinned there's no way a pinned site has been
+ // pushed out of the grid so we can just exit here.
+ if (!aCell.containsPinnedSite())
+ return false;
+
+ let cells = gGrid.cells;
+
+ // No cells have been pushed out of the grid, nothing to do here.
+ if (aSites.length <= cells.length)
+ return false;
+
+ let overflowedSite = aSites[cells.length];
+
+ // Nothing to do if the site that got pushed out of the grid is not pinned.
+ return (overflowedSite && overflowedSite.isPinned());
+ },
+
+ /**
+ * We have a overflowed pinned site that we need to re-position so that it's
+ * visible again. We try to find a lower-priority cell (empty or containing
+ * an unpinned site) that we can move it to.
+ * @param aSites The array of sites.
+ * @param aCell The drop target cell.
+ */
+ _repositionOverflowedPinnedSite:
+ function DropPreview_repositionOverflowedPinnedSite(aSites, aCell) {
+
+ // Try to find a lower-priority cell (empty or containing an unpinned site).
+ let index = this._indexOfLowerPrioritySite(aSites, aCell);
+
+ if (index > -1) {
+ let cells = gGrid.cells;
+ let dropIndex = aCell.index;
+
+ // Move all pinned cells to their new positions to let the overflowed
+ // site fit into the grid.
+ for (let i = index + 1, lastPosition = index; i < aSites.length; i++) {
+ if (i != dropIndex) {
+ aSites[lastPosition] = aSites[i];
+ lastPosition = i;
+ }
+ }
+
+ // Finally, remove the overflowed site from its previous position.
+ aSites.splice(cells.length, 1);
+ }
+ },
+
+ /**
+ * Finds the index of the last cell that is empty or contains an unpinned
+ * site. These are considered to be of a lower priority.
+ * @param aSites The array of sites.
+ * @param aCell The drop target cell.
+ * @return The cell's index.
+ */
+ _indexOfLowerPrioritySite:
+ function DropPreview_indexOfLowerPrioritySite(aSites, aCell) {
+
+ let cells = gGrid.cells;
+ let dropIndex = aCell.index;
+
+ // Search (beginning with the last site in the grid) for a site that is
+ // empty or unpinned (an thus lower-priority) and can be pushed out of the
+ // grid instead of the pinned site.
+ for (let i = cells.length - 1; i >= 0; i--) {
+ // The cell that is our drop target is not a good choice.
+ if (i == dropIndex)
+ continue;
+
+ let site = aSites[i];
+
+ // We can use the cell only if it's empty or the site is un-pinned.
+ if (!site || !site.isPinned())
+ return i;
+ }
+
+ return -1;
+ }
+};
diff --git a/application/basilisk/base/content/newtab/dropTargetShim.js b/application/basilisk/base/content/newtab/dropTargetShim.js
new file mode 100644
index 000000000..57a97fa00
--- /dev/null
+++ b/application/basilisk/base/content/newtab/dropTargetShim.js
@@ -0,0 +1,232 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * This singleton provides a custom drop target detection. We need this because
+ * the default DnD target detection relies on the cursor's position. We want
+ * to pick a drop target based on the dragged site's position.
+ */
+var gDropTargetShim = {
+ /**
+ * Cache for the position of all cells, cleaned after drag finished.
+ */
+ _cellPositions: null,
+
+ /**
+ * The last drop target that was hovered.
+ */
+ _lastDropTarget: null,
+
+ /**
+ * Initializes the drop target shim.
+ */
+ init: function () {
+ gGrid.node.addEventListener("dragstart", this, true);
+ },
+
+ /**
+ * Add all event listeners needed during a drag operation.
+ */
+ _addEventListeners: function () {
+ gGrid.node.addEventListener("dragend", this);
+
+ let docElement = document.documentElement;
+ docElement.addEventListener("dragover", this);
+ docElement.addEventListener("dragenter", this);
+ docElement.addEventListener("drop", this);
+ },
+
+ /**
+ * Remove all event listeners that were needed during a drag operation.
+ */
+ _removeEventListeners: function () {
+ gGrid.node.removeEventListener("dragend", this);
+
+ let docElement = document.documentElement;
+ docElement.removeEventListener("dragover", this);
+ docElement.removeEventListener("dragenter", this);
+ docElement.removeEventListener("drop", this);
+ },
+
+ /**
+ * Handles all shim events.
+ */
+ handleEvent: function (aEvent) {
+ switch (aEvent.type) {
+ case "dragstart":
+ this._dragstart(aEvent);
+ break;
+ case "dragenter":
+ aEvent.preventDefault();
+ break;
+ case "dragover":
+ this._dragover(aEvent);
+ break;
+ case "drop":
+ this._drop(aEvent);
+ break;
+ case "dragend":
+ this._dragend(aEvent);
+ break;
+ }
+ },
+
+ /**
+ * Handles the 'dragstart' event.
+ * @param aEvent The 'dragstart' event.
+ */
+ _dragstart: function (aEvent) {
+ if (aEvent.target.classList.contains("newtab-link")) {
+ gGrid.lock();
+ this._addEventListeners();
+ }
+ },
+
+ /**
+ * Handles the 'dragover' event.
+ * @param aEvent The 'dragover' event.
+ */
+ _dragover: function (aEvent) {
+ // XXX bug 505521 - Use the dragover event to retrieve the
+ // current mouse coordinates while dragging.
+ let sourceNode = aEvent.dataTransfer.mozSourceNode.parentNode;
+ gDrag.drag(sourceNode._newtabSite, aEvent);
+
+ // Find the current drop target, if there's one.
+ this._updateDropTarget(aEvent);
+
+ // If we have a valid drop target,
+ // let the drag-and-drop service know.
+ if (this._lastDropTarget) {
+ aEvent.preventDefault();
+ }
+ },
+
+ /**
+ * Handles the 'drop' event.
+ * @param aEvent The 'drop' event.
+ */
+ _drop: function (aEvent) {
+ // We're accepting all drops.
+ aEvent.preventDefault();
+
+ // remember that drop event was seen, this explicitly
+ // assumes that drop event preceeds dragend event
+ this._dropSeen = true;
+
+ // Make sure to determine the current drop target
+ // in case the dragover event hasn't been fired.
+ this._updateDropTarget(aEvent);
+
+ // A site was successfully dropped.
+ this._dispatchEvent(aEvent, "drop", this._lastDropTarget);
+ },
+
+ /**
+ * Handles the 'dragend' event.
+ * @param aEvent The 'dragend' event.
+ */
+ _dragend: function (aEvent) {
+ if (this._lastDropTarget) {
+ if (aEvent.dataTransfer.mozUserCancelled || !this._dropSeen) {
+ // The drag operation was cancelled or no drop event was generated
+ this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
+ this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
+ }
+
+ // Clean up.
+ this._lastDropTarget = null;
+ this._cellPositions = null;
+ }
+
+ this._dropSeen = false;
+ gGrid.unlock();
+ this._removeEventListeners();
+ },
+
+ /**
+ * Tries to find the current drop target and will fire
+ * appropriate dragenter, dragexit, and dragleave events.
+ * @param aEvent The current drag event.
+ */
+ _updateDropTarget: function (aEvent) {
+ // Let's see if we find a drop target.
+ let target = this._findDropTarget(aEvent);
+
+ if (target != this._lastDropTarget) {
+ if (this._lastDropTarget)
+ // We left the last drop target.
+ this._dispatchEvent(aEvent, "dragexit", this._lastDropTarget);
+
+ if (target)
+ // We're now hovering a (new) drop target.
+ this._dispatchEvent(aEvent, "dragenter", target);
+
+ if (this._lastDropTarget)
+ // We left the last drop target.
+ this._dispatchEvent(aEvent, "dragleave", this._lastDropTarget);
+
+ this._lastDropTarget = target;
+ }
+ },
+
+ /**
+ * Determines the current drop target by matching the dragged site's position
+ * against all cells in the grid.
+ * @return The currently hovered drop target or null.
+ */
+ _findDropTarget: function () {
+ // These are the minimum intersection values - we want to use the cell if
+ // the site is >= 50% hovering its position.
+ let minWidth = gDrag.cellWidth / 2;
+ let minHeight = gDrag.cellHeight / 2;
+
+ let cellPositions = this._getCellPositions();
+ let rect = gTransformation.getNodePosition(gDrag.draggedSite.node);
+
+ // Compare each cell's position to the dragged site's position.
+ for (let i = 0; i < cellPositions.length; i++) {
+ let inter = rect.intersect(cellPositions[i].rect);
+
+ // If the intersection is big enough we found a drop target.
+ if (inter.width >= minWidth && inter.height >= minHeight)
+ return cellPositions[i].cell;
+ }
+
+ // No drop target found.
+ return null;
+ },
+
+ /**
+ * Gets the positions of all cell nodes.
+ * @return The (cached) cell positions.
+ */
+ _getCellPositions: function DropTargetShim_getCellPositions() {
+ if (this._cellPositions)
+ return this._cellPositions;
+
+ return this._cellPositions = gGrid.cells.map(function (cell) {
+ return {cell: cell, rect: gTransformation.getNodePosition(cell.node)};
+ });
+ },
+
+ /**
+ * Dispatches a custom DragEvent on the given target node.
+ * @param aEvent The source event.
+ * @param aType The event type.
+ * @param aTarget The target node that receives the event.
+ */
+ _dispatchEvent: function (aEvent, aType, aTarget) {
+ let node = aTarget.node;
+ let event = document.createEvent("DragEvent");
+
+ // The event should not bubble to prevent recursion.
+ event.initDragEvent(aType, false, true, window, 0, 0, 0, 0, 0, false, false,
+ false, false, 0, node, aEvent.dataTransfer);
+
+ node.dispatchEvent(event);
+ }
+};
diff --git a/application/basilisk/base/content/newtab/grid.js b/application/basilisk/base/content/newtab/grid.js
new file mode 100644
index 000000000..b6f98fa17
--- /dev/null
+++ b/application/basilisk/base/content/newtab/grid.js
@@ -0,0 +1,279 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * Define various fixed dimensions
+ */
+const GRID_BOTTOM_EXTRA = 7; // title's line-height extends 7px past the margin
+const GRID_WIDTH_EXTRA = 1; // provide 1px buffer to allow for rounding error
+const SPONSORED_TAG_BUFFER = 2; // 2px buffer to clip off top of sponsored tag
+
+/**
+ * This singleton represents the grid that contains all sites.
+ */
+var gGrid = {
+ /**
+ * The DOM node of the grid.
+ */
+ _node: null,
+ _gridDefaultContent: null,
+ get node() { return this._node; },
+
+ /**
+ * The cached DOM fragment for sites.
+ */
+ _siteFragment: null,
+
+ /**
+ * All cells contained in the grid.
+ */
+ _cells: [],
+ get cells() { return this._cells; },
+
+ /**
+ * All sites contained in the grid's cells. Sites may be empty.
+ */
+ get sites() { return [for (cell of this.cells) cell.site]; },
+
+ // Tells whether the grid has already been initialized.
+ get ready() { return !!this._ready; },
+
+ // Returns whether the page has finished loading yet.
+ get isDocumentLoaded() { return document.readyState == "complete"; },
+
+ /**
+ * Initializes the grid.
+ * @param aSelector The query selector of the grid.
+ */
+ init: function Grid_init() {
+ this._node = document.getElementById("newtab-grid");
+ this._gridDefaultContent = this._node.lastChild;
+ this._createSiteFragment();
+
+ gLinks.populateCache(() => {
+ this._refreshGrid();
+ this._ready = true;
+
+ // If fetching links took longer than loading the page itself then
+ // we need to resize the grid as that was blocked until now.
+ // We also want to resize now if the page was already loaded when
+ // initializing the grid (the user toggled the page).
+ this._resizeGrid();
+
+ addEventListener("resize", this);
+ });
+
+ // Resize the grid as soon as the page loads.
+ if (!this.isDocumentLoaded) {
+ addEventListener("load", this);
+ }
+ },
+
+ /**
+ * Creates a new site in the grid.
+ * @param aLink The new site's link.
+ * @param aCell The cell that will contain the new site.
+ * @return The newly created site.
+ */
+ createSite: function Grid_createSite(aLink, aCell) {
+ let node = aCell.node;
+ node.appendChild(this._siteFragment.cloneNode(true));
+ return new Site(node.firstElementChild, aLink);
+ },
+
+ /**
+ * Handles all grid events.
+ */
+ handleEvent: function Grid_handleEvent(aEvent) {
+ switch (aEvent.type) {
+ case "load":
+ case "resize":
+ this._resizeGrid();
+ break;
+ }
+ },
+
+ /**
+ * Locks the grid to block all pointer events.
+ */
+ lock: function Grid_lock() {
+ this.node.setAttribute("locked", "true");
+ },
+
+ /**
+ * Unlocks the grid to allow all pointer events.
+ */
+ unlock: function Grid_unlock() {
+ this.node.removeAttribute("locked");
+ },
+
+ /**
+ * Renders and resizes the gird. _resizeGrid() call is needed to ensure
+ * that scrollbar disappears when the bottom row becomes empty following
+ * the block action, or tile display is turmed off via cog menu
+ */
+
+ refresh() {
+ this._refreshGrid();
+ this._resizeGrid();
+ },
+
+ /**
+ * Renders the grid, including cells and sites.
+ */
+ _refreshGrid() {
+ let cell = document.createElementNS(HTML_NAMESPACE, "div");
+ cell.classList.add("newtab-cell");
+
+ // Creates all the cells up to the maximum
+ let fragment = document.createDocumentFragment();
+ for (let i = 0; i < gGridPrefs.gridColumns * gGridPrefs.gridRows; i++) {
+ fragment.appendChild(cell.cloneNode(true));
+ }
+
+ // Create cells.
+ let cells = Array.from(fragment.childNodes, (cell) => new Cell(this, cell));
+
+ // Fetch links.
+ let links = gLinks.getLinks();
+
+ // Create sites.
+ let numLinks = Math.min(links.length, cells.length);
+ let hasHistoryTiles = false;
+ for (let i = 0; i < numLinks; i++) {
+ if (links[i]) {
+ this.createSite(links[i], cells[i]);
+ if (links[i].type == "history") {
+ hasHistoryTiles = true;
+ }
+ }
+ }
+
+ this._cells = cells;
+ while (this._gridDefaultContent.nextSibling) {
+ this._gridDefaultContent.nextSibling.remove();
+ }
+ this._node.appendChild(fragment);
+
+ document.getElementById("topsites-heading").textContent =
+ hasHistoryTiles ? "Your Top Sites" : "Top Sites";
+ },
+
+ /**
+ * Calculate the height for a number of rows up to the maximum rows
+ * @param rows Number of rows defaulting to the max
+ */
+ _computeHeight: function Grid_computeHeight(aRows) {
+ let {gridRows} = gGridPrefs;
+ aRows = aRows === undefined ? gridRows : Math.min(gridRows, aRows);
+ return aRows * this._cellHeight + GRID_BOTTOM_EXTRA;
+ },
+
+ /**
+ * Creates the DOM fragment that is re-used when creating sites.
+ */
+ _createSiteFragment: function Grid_createSiteFragment() {
+ let site = document.createElementNS(HTML_NAMESPACE, "div");
+ site.classList.add("newtab-site");
+ site.setAttribute("draggable", "true");
+
+ // Create the site's inner HTML code.
+ site.innerHTML =
+ '<span class="newtab-sponsored">' + newTabString("sponsored.button") + '</span>' +
+ '<a class="newtab-link">' +
+ ' <span class="newtab-thumbnail placeholder"/>' +
+ ' <span class="newtab-thumbnail thumbnail"/>' +
+ ' <span class="newtab-thumbnail enhanced-content"/>' +
+ ' <span class="newtab-title"/>' +
+ '</a>' +
+ '<input type="button" title="' + newTabString("pin") + '"' +
+ ' class="newtab-control newtab-control-pin"/>' +
+ '<input type="button" title="' + newTabString("block") + '"' +
+ ' class="newtab-control newtab-control-block"/>' +
+ '<span class="newtab-suggested"/>';
+
+ this._siteFragment = document.createDocumentFragment();
+ this._siteFragment.appendChild(site);
+ },
+
+ /**
+ * Test a tile at a given position for being pinned or history
+ * @param position Position in sites array
+ */
+ _isHistoricalTile: function Grid_isHistoricalTile(aPos) {
+ let site = this.sites[aPos];
+ return site && (site.isPinned() || site.link && site.link.type == "history");
+ },
+
+ /**
+ * Make sure the correct number of rows and columns are visible
+ */
+ _resizeGrid: function Grid_resizeGrid() {
+ // If we're somehow called before the page has finished loading,
+ // let's bail out to avoid caching zero heights and widths.
+ // We'll be called again when DOMContentLoaded fires.
+ // Same goes for the grid if that's not ready yet.
+ if (!this.isDocumentLoaded || !this._ready) {
+ return;
+ }
+
+ // Save the cell's computed height/width including margin and border
+ if (this._cellHeight === undefined) {
+ let refCell = document.querySelector(".newtab-cell");
+ let style = getComputedStyle(refCell);
+ this._cellHeight = refCell.offsetHeight +
+ parseFloat(style.marginTop) + parseFloat(style.marginBottom);
+ this._cellWidth = refCell.offsetWidth +
+ parseFloat(style.marginLeft) + parseFloat(style.marginRight);
+ }
+
+ let searchContainer = document.querySelector("#newtab-search-container");
+ // Save search-container margin height
+ if (this._searchContainerMargin === undefined) {
+ let style = getComputedStyle(searchContainer);
+ this._searchContainerMargin = parseFloat(style.marginBottom) +
+ parseFloat(style.marginTop);
+ }
+
+ // Find the number of rows we can place into view port
+ let availHeight = document.documentElement.clientHeight -
+ searchContainer.offsetHeight - this._searchContainerMargin;
+ let visibleRows = Math.floor(availHeight / this._cellHeight);
+
+ // Find the number of columns that fit into view port
+ let maxGridWidth = gGridPrefs.gridColumns * this._cellWidth + GRID_WIDTH_EXTRA;
+ // available width is current grid width, but no greater than maxGridWidth
+ let availWidth = Math.min(document.querySelector("#newtab-grid").clientWidth,
+ maxGridWidth);
+ // finally get the number of columns we can fit into view port
+ let gridColumns = Math.floor(availWidth / this._cellWidth);
+ // walk sites backwords until a pinned or history tile is found or visibleRows reached
+ let tileIndex = Math.min(gGridPrefs.gridRows * gridColumns, this.sites.length) - 1;
+ while (tileIndex >= visibleRows * gridColumns) {
+ if (this._isHistoricalTile(tileIndex)) {
+ break;
+ }
+ tileIndex--;
+ }
+
+ // Compute the actual number of grid rows we will display (potentially
+ // with a scroll bar). tileIndex now points to a historical tile with
+ // heighest index or to the last index of the visible row, if none found
+ // Dividing tileIndex by number of tiles in a column gives the rows
+ let gridRows = Math.floor(tileIndex / gridColumns) + 1;
+
+ // we need to set grid width, for otherwise the scrollbar may shrink
+ // the grid when shown and cause grid layout to be different from
+ // what being computed above. This, in turn, may cause scrollbar shown
+ // for directory tiles, and introduce jitter when grid width is aligned
+ // exactly on the column boundary
+ this._node.style.width = gridColumns * this._cellWidth + "px";
+ this._node.style.maxWidth = gGridPrefs.gridColumns * this._cellWidth +
+ GRID_WIDTH_EXTRA + "px";
+ this._node.style.height = this._computeHeight() + "px";
+ this._node.style.maxHeight = this._computeHeight(gridRows) - SPONSORED_TAG_BUFFER + "px";
+ }
+};
diff --git a/application/basilisk/base/content/newtab/newTab.css b/application/basilisk/base/content/newtab/newTab.css
new file mode 100644
index 000000000..658ad2ed3
--- /dev/null
+++ b/application/basilisk/base/content/newtab/newTab.css
@@ -0,0 +1,654 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+html {
+ width: 100%;
+ height: 100%;
+}
+
+body {
+ font: message-box;
+ width: 100%;
+ height: 100%;
+ padding: 0;
+ margin: 0;
+ background-color: #F9F9F9;
+ display: -moz-box;
+ position: relative;
+ -moz-box-flex: 1;
+ -moz-user-focus: normal;
+ -moz-box-orient: vertical;
+}
+
+input {
+ font: message-box;
+ font-size: 16px;
+}
+
+input[type=button] {
+ cursor: pointer;
+}
+
+/* UNDO */
+#newtab-undo-container {
+ transition: opacity 100ms ease-out;
+ -moz-box-align: center;
+ -moz-box-pack: center;
+}
+
+#newtab-undo-container[undo-disabled] {
+ opacity: 0;
+ pointer-events: none;
+}
+
+/* CUSTOMIZE */
+#newtab-customize-button {
+ position: absolute;
+ top: 10px;
+ right: 20px;
+ z-index: 101;
+}
+
+#newtab-customize-button:dir(rtl) {
+ left: 20px;
+ right: auto;
+}
+
+/* MARGINS */
+#newtab-vertical-margin {
+ display: -moz-box;
+ position: relative;
+ -moz-box-flex: 1;
+ -moz-box-orient: vertical;
+}
+
+#newtab-margin-undo-container {
+ display: -moz-box;
+ left: 6px;
+ position: absolute;
+ top: 6px;
+ z-index: 1;
+}
+
+#newtab-margin-undo-container:dir(rtl) {
+ left: auto;
+ right: 6px;
+}
+
+#newtab-undo-close-button:dir(rtl) {
+ float:left;
+}
+
+#newtab-horizontal-margin {
+ display: -moz-box;
+ -moz-box-flex: 1;
+}
+
+#newtab-margin-top,
+#newtab-margin-bottom {
+ display: -moz-box;
+ position: relative;
+}
+
+#newtab-margin-top {
+ -moz-box-flex: 1;
+}
+
+#newtab-margin-bottom {
+ -moz-box-flex: 2;
+}
+
+.newtab-side-margin {
+ min-width: 10px;
+ -moz-box-flex: 1;
+}
+
+/* GRID */
+#newtab-grid {
+ -moz-box-flex: 5;
+ overflow: hidden;
+ text-align: center;
+ transition: 100ms ease-out;
+ transition-property: opacity;
+}
+
+#newtab-grid[page-disabled] {
+ opacity: 0;
+}
+
+#newtab-grid[locked],
+#newtab-grid[page-disabled] {
+ pointer-events: none;
+}
+
+body:not(.compact) #topsites-heading {
+ display: none;
+}
+
+/*
+ * If you change the sizes here, make sure you
+ * change the preferences:
+ * toolkit.pageThumbs.minWidth
+ * toolkit.pageThumbs.minHeight
+ */
+/* CELLS */
+.newtab-cell {
+ display: -moz-box;
+ height: 210px;
+ margin: 20px 10px 35px;
+ width: 290px;
+}
+
+body.compact .newtab-cell {
+ width: 110px;
+ height: 110px;
+ margin: 12px;
+}
+
+/* SITES */
+.newtab-site {
+ position: relative;
+ -moz-box-flex: 1;
+ transition: 100ms ease-out;
+ transition-property: top, left, opacity;
+}
+
+.newtab-site[frozen] {
+ position: absolute;
+ pointer-events: none;
+}
+
+.newtab-site[dragged] {
+ transition-property: none;
+ z-index: 10;
+}
+
+/* LINK + THUMBNAILS */
+.newtab-link,
+.newtab-thumbnail {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+}
+
+/* TITLES */
+.newtab-sponsored,
+.newtab-title,
+.newtab-suggested {
+ overflow: hidden;
+ position: absolute;
+ right: 0;
+ text-align: center;
+}
+
+.newtab-sponsored,
+.newtab-title {
+ bottom: 0;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ vertical-align: middle;
+}
+
+.newtab-suggested {
+ border: 1px solid transparent;
+ border-radius: 2px;
+ font-size: 12px;
+ height: 17px;
+ line-height: 17px;
+ margin-bottom: -1px;
+ padding: 2px 8px;
+ display: none;
+ margin-left: auto;
+ margin-right: auto;
+ left: 0;
+ top: 215px;
+ -moz-user-select: none;
+}
+
+.newtab-suggested-bounds {
+ max-height: 34px; /* 34 / 17 = 2 lines maximum */
+}
+
+.newtab-title {
+ left: 0;
+ padding: 0 4px;
+}
+
+.newtab-sponsored {
+ background-color: #FFFFFF;
+ border: 1px solid #E2E2E2;
+ border-radius: 3px;
+ color: #4A4A4A;
+ cursor: pointer;
+ display: none;
+ font-family: Arial;
+ font-size: 9px;
+ height: 17px;
+ left: 0;
+ line-height: 6px;
+ padding: 4px;
+ right: auto;
+ top: -15px;
+}
+
+.newtab-site[suggested=true] > .newtab-sponsored {
+ background-color: #E2E2E2;
+ border: none;
+}
+
+.newtab-site > .newtab-sponsored:-moz-any(:hover, [active]) {
+ background-color: #4A90E2;
+ border: 0;
+ color: white;
+}
+
+.newtab-site > .newtab-sponsored[active] {
+ background-color: #000000;
+}
+
+.newtab-sponsored:dir(rtl) {
+ right: 0;
+ left: auto;
+}
+
+.newtab-site:-moz-any([type=enhanced], [type=sponsored], [suggested]) .newtab-sponsored {
+ display: block;
+}
+
+.newtab-site[suggested] .newtab-suggested {
+ display: table;
+}
+
+.sponsored-explain,
+.sponsored-explain a,
+.suggested-explain,
+.suggested-explain a {
+ color: white;
+}
+
+.sponsored-explain,
+.suggested-explain {
+ background-color: rgba(51, 51, 51, 0.95);
+ bottom: 30px;
+ line-height: 20px;
+ padding: 15px 10px;
+ position: absolute;
+ text-align: start;
+}
+
+.sponsored-explain input,
+.suggested-explain input {
+ background-size: 18px;
+ height: 18px;
+ opacity: 1;
+ pointer-events: none;
+ position: static;
+ width: 18px;
+}
+
+/* CONTROLS */
+.newtab-control {
+ position: absolute;
+ opacity: 0;
+ transition: opacity 100ms ease-out;
+}
+
+.newtab-control:-moz-focusring,
+.newtab-cell:not([ignorehover]) > .newtab-site:hover > .newtab-control {
+ opacity: 1;
+}
+
+.newtab-control[dragged] {
+ opacity: 0 !important;
+}
+
+@media (-moz-touch-enabled) {
+ .newtab-control {
+ opacity: 1;
+ }
+}
+
+/* DRAG & DROP */
+
+/*
+ * This is just a temporary drag element used for dataTransfer.setDragImage()
+ * so that we can use custom drag images and elements. It needs an opacity of
+ * 0.01 so that the core code detects that it's in fact a visible element.
+ */
+.newtab-drag {
+ width: 1px;
+ height: 1px;
+ background-color: #fff;
+ opacity: 0.01;
+}
+
+/* SEARCH */
+#newtab-search-container {
+ display: -moz-box;
+ position: relative;
+ -moz-box-pack: center;
+ margin: 40px 0 15px;
+}
+
+body.compact #newtab-search-container {
+ margin-top: 0;
+ margin-bottom: 80px;
+}
+
+#newtab-search-container[page-disabled] {
+ opacity: 0;
+ pointer-events: none;
+}
+
+#newtab-search-form {
+ display: -moz-box;
+ position: relative;
+ height: 36px;
+ -moz-box-flex: 1;
+ max-width: 600px; /* 2 * (290 cell width + 10 cell margin) */
+}
+
+#newtab-search-icon {
+ border: 1px transparent;
+ padding: 0;
+ margin: 0;
+ width: 36px;
+ height: 36px;
+ background: url("chrome://browser/skin/search-indicator-magnifying-glass.svg") center center no-repeat;
+ position: absolute;
+}
+
+#newtab-search-text {
+ -moz-box-flex: 1;
+ padding-top: 6px;
+ padding-bottom: 6px;
+ padding-inline-start: 34px;
+ padding-inline-end: 8px;
+ background: hsla(0,0%,100%,.9) padding-box;
+ border: 1px solid;
+ border-spacing: 0;
+ border-radius: 2px 0 0 2px;
+ border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
+ box-shadow: 0 1px 0 hsla(210,65%,9%,.02) inset,
+ 0 0 2px hsla(210,65%,9%,.1) inset,
+ 0 1px 0 hsla(0,0%,100%,.2);
+ color: inherit;
+ unicode-bidi: plaintext;
+}
+
+#newtab-search-text:dir(rtl) {
+ border-radius: 0 2px 2px 0;
+}
+
+#newtab-search-text[aria-expanded="true"] {
+ border-radius: 2px 0 0 0;
+}
+
+#newtab-search-text[aria-expanded="true"]:dir(rtl) {
+ border-radius: 0 2px 0 0;
+}
+
+#newtab-search-text[keepfocus],
+#newtab-search-text:focus,
+#newtab-search-text[autofocus] {
+ border-color: hsla(206,100%,60%,.6) hsla(206,76%,52%,.6) hsla(204,100%,40%,.6);
+}
+
+#newtab-search-submit {
+ margin-inline-start: -1px;
+ color: transparent;
+ background: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go") center center no-repeat, linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1)) padding-box;
+ padding: 0;
+ border: 1px solid;
+ border-color: hsla(210,54%,20%,.15) hsla(210,54%,20%,.17) hsla(210,54%,20%,.2);
+ border-radius: 0 2px 2px 0;
+ border-inline-start: 1px solid transparent;
+ box-shadow: 0 0 2px hsla(0,0%,100%,.5) inset,
+ 0 1px 0 hsla(0,0%,100%,.2);
+ cursor: pointer;
+ transition-property: background-color, border-color, box-shadow;
+ transition-duration: 150ms;
+ width: 50px;
+}
+
+#newtab-search-submit:dir(rtl) {
+ border-radius: 2px 0 0 2px;
+ background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-rtl"), linear-gradient(hsla(0,0%,100%,.8), hsla(0,0%,100%,.1));
+}
+
+#newtab-search-text:focus + #newtab-search-submit,
+#newtab-search-text + #newtab-search-submit:hover,
+#newtab-search-text[autofocus] + #newtab-search-submit {
+ border-color: #59b5fc #45a3e7 #3294d5;
+}
+
+#newtab-search-text:focus + #newtab-search-submit,
+#newtab-search-text[keepfocus] + #newtab-search-submit,
+#newtab-search-text[autofocus] + #newtab-search-submit {
+ background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-inverted"), linear-gradient(#4cb1ff, #1793e5);
+ box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
+ 0 0 0 1px hsla(0,0%,100%,.1) inset,
+ 0 1px 0 hsla(210,54%,20%,.03);
+}
+
+#newtab-search-text + #newtab-search-submit:hover {
+ background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-inverted"), linear-gradient(#4cb1ff, #1793e5);
+ box-shadow: 0 1px 0 hsla(0,0%,100%,.2) inset,
+ 0 0 0 1px hsla(0,0%,100%,.1) inset,
+ 0 1px 0 hsla(210,54%,20%,.03),
+ 0 0 4px hsla(206,100%,20%,.2);
+}
+
+#newtab-search-text + #newtab-search-submit:hover:active {
+ box-shadow: 0 1px 1px hsla(211,79%,6%,.1) inset,
+ 0 0 1px hsla(211,79%,6%,.2) inset;
+ transition-duration: 0ms;
+}
+
+#newtab-search-text:focus + #newtab-search-submit:dir(rtl),
+#newtab-search-text[keepfocus] + #newtab-search-submit:dir(rtl),
+#newtab-search-text[autofocus] + #newtab-search-submit:dir(rtl),
+#newtab-search-text + #newtab-search-submit:dir(rtl):hover {
+ background-image: url("chrome://browser/skin/search-arrow-go.svg#search-arrow-go-rtl-inverted"), linear-gradient(#4cb1ff, #1793e5);
+}
+
+/* CUSTOMIZE */
+#newtab-customize-overlay {
+ opacity: 0;
+ display: none;
+ width: 100%;
+ height: 100%;
+ background: #F9F9F9;
+ z-index: 100;
+ position: fixed;
+ transition: opacity .07s linear;
+}
+
+.newtab-customize-panel-container {
+ position: absolute;
+ margin-right: 40px;
+ right: 0;
+}
+
+.newtab-customize-panel-container:dir(rtl) {
+ right: auto;
+ left: 0;
+}
+
+#newtab-customize-panel {
+ z-index: 999;
+ margin-top: 55px;
+ min-width: 270px;
+ position: absolute;
+ top: 100%;
+ right: -25px;
+ filter: drop-shadow(0 0 1px rgba(0,0,0,0.4)) drop-shadow(0 3px 4px rgba(0,0,0,0.4));
+ transition: all 200ms ease-in-out;
+ transform-origin: top right;
+ transform: translate(-30px, -20px) scale(0) translate(30px, 20px);
+}
+
+#newtab-customize-panel:dir(rtl) {
+ transform-origin: 40px top 20px;
+}
+
+#newtab-customize-panel:dir(rtl),
+#newtab-customize-panel-anchor:dir(rtl) {
+ left: 15px;
+ right: auto;
+}
+
+#newtab-customize-panel[open="true"] {
+ transform: translate(-30px, -20px) scale(1) translate(30px, 20px);
+}
+
+#newtab-customize-panel-anchor {
+ width: 18px;
+ height: 18px;
+ background-color: white;
+ transform: rotate(45deg);
+ position: absolute;
+ top: -6px;
+ right: 15px;
+}
+
+#newtab-customize-title {
+ color: #7A7A7A;
+ font-size: 14px;
+ background-color: #FFFFFF;
+ line-height: 25px;
+ padding: 15px;
+ font-weight: 600;
+ cursor: default;
+ border-radius: 5px 5px 0px 0px;
+ max-width: 300px;
+ overflow: hidden;
+ display: table-cell;
+ border-top: none;
+}
+
+#newtab-customize-panel-inner-wrapper {
+ background-color: #FFFFFF;
+ border-radius: 6px;
+ overflow: hidden;
+}
+
+#newtab-customize-title > label {
+ cursor: default;
+}
+
+#newtab-customize-panel > .panel-arrowcontainer > .panel-arrowcontent {
+ padding: 0;
+}
+
+.newtab-customize-panel-item {
+ line-height: 25px;
+ padding: 15px;
+ padding-inline-start: 40px;
+ font-size: 14px;
+ cursor: pointer;
+ max-width: 300px;
+}
+
+.newtab-customize-panel-item:not(:first-child) {
+ border-top: 1px solid threedshadow;
+}
+
+.newtab-customize-panel-subitem > label,
+.newtab-customize-panel-item > label,
+.newtab-customize-complex-option {
+ padding: 0;
+ margin: 0;
+ cursor: pointer;
+}
+
+.newtab-customize-panel-item,
+.newtab-customize-complex-option {
+ display: block;
+ text-align: start;
+ background-color: #F9F9F9;
+}
+
+.newtab-customize-panel-item[selected]:-moz-locale-dir(rtl) {
+ background-position: right 15px center;
+}
+
+.newtab-customize-complex-option:hover > .selectable:not([selected]):-moz-locale-dir(rtl),
+.selectable:not([selected]):hover:-moz-locale-dir(rtl) {
+ background-position: right 15px center;
+}
+
+.newtab-customize-panel-item:not([selected]),
+.newtab-customize-panel-subitem:not([selected]){
+ color: #7A7A7A;
+}
+
+.newtab-customize-panel-item:not([selected]):hover {
+ color: #FFFFFF;
+ background-color: #4A90E2
+}
+
+.newtab-customize-complex-option:hover > .selectable:not([selected]),
+.selectable:not([selected]):hover {
+ background: url("chrome://global/skin/menu/shared-menu-check-hover.svg") no-repeat #FFFFFF;
+ background-size: 16px 16px;
+ background-position: 15px 15px;
+ color: #171F26;
+}
+
+.newtab-customize-complex-option:hover > .selectable:not([selected]) + .newtab-customize-panel-subitem {
+ background-color: #FFFFFF;
+}
+
+.newtab-customize-panel-item[selected] {
+ background: url("chrome://global/skin/menu/shared-menu-check-active.svg") no-repeat transparent;
+ background-size: 16px 16px;
+ background-position: 15px 15px;
+ color: black;
+ font-weight: 600;
+}
+
+.newtab-customize-panel-subitem > .checkbox {
+ width: 18px;
+ height: 18px;
+ background-color: #FFFFFF;
+ border: solid 1px threedshadow;
+}
+
+.newtab-customize-panel-subitem[selected] > .checkbox {
+ background: url("chrome://global/skin/menu/shared-menu-check-black.svg") no-repeat #FFFFFF;
+ background-size: 9px 9px;
+ background-position: center;
+ color: #333333;
+}
+
+.newtab-customize-panel-subitem {
+ font-size: 12px;
+ padding: 0px 15px 15px 15px;
+ padding-inline-start: 40px;
+ display: block;
+ max-width: 300px;
+}
+
+.newtab-customize-panel-subitem > label {
+ padding: 0px 10px;
+ line-height: 20px;
+ vertical-align: middle;
+ max-width: 225px;
+}
+
+.newtab-customize-panel-superitem {
+ line-height: 20px;
+ border-bottom: medium none !important;
+ padding: 15px 15px 10px 15px;
+ padding-inline-start: 40px;
+ border-top: 1px solid threedshadow;
+}
+
+.contentSearchSuggestionTable {
+ font: message-box;
+ font-size: 16px;
+}
diff --git a/application/basilisk/base/content/newtab/newTab.inadjacent.json b/application/basilisk/base/content/newtab/newTab.inadjacent.json
new file mode 100644
index 000000000..53fb542af
--- /dev/null
+++ b/application/basilisk/base/content/newtab/newTab.inadjacent.json
@@ -0,0 +1,3209 @@
+{
+ "domains": [
+ "rp5slFCxq/e7hYhXJCd0vQ==",
+ "2rEimAJDNX5g8HPZehOrGg==",
+ "nvLEpj6ZZF3LWH3wUB6lKg==",
+ "9Cqd4Lm3VvXuJxz79Bbqyg==",
+ "vNRy4LR+7TOKTixqsr5ybw==",
+ "N4zSgsZCo6Z4XRwZ4fu8WQ==",
+ "jsDtRfVbMsFg3KkEl2UiZQ==",
+ "TckkKpiq0a6J6NTw7uOZqw==",
+ "9Or7IAYuuIgZA370w9rNIg==",
+ "ul8WvOjCkxTz9LjT4RqTHg==",
+ "ZGJrbwb5878Nsqm0z+A7nQ==",
+ "5iT64HTeeG5SIFXG7A9o3w==",
+ "YSeSEghPe1kV6g8ghFcNAA==",
+ "0jIUl1NDmJZQkDY12VDeIQ==",
+ "aos6UyDyIw0R1nTK5wTawA==",
+ "G1xxubsq65ugK06UT2DO5A==",
+ "lbhavoDrDPP/8m0onwo63w==",
+ "ObcLsjW0SkdvY0nkZmiTGQ==",
+ "FHZ5084LC0nTAzZlnSKN3Q==",
+ "cdEr+0Fv5iaVZzalZToseg==",
+ "Co8WbNYbCPTFPcHpeK3hRQ==",
+ "qXSzhCEhByLQq9N84tqV+Q==",
+ "h3ufhRk5IEFaNH11rIACtQ==",
+ "fQ1PJ/JwazIaYoy/zy49QQ==",
+ "zAJqfbn54Nsm2ddGtkb59A==",
+ "ixPM9T8ik/gWGZ7BRIcaig==",
+ "/E9pwA3E3hVAZoYq3FmCyw==",
+ "U6ygonI8CxpruhpGB2+Q6A==",
+ "Igi4voB8oVMVw6WUeDSjZg==",
+ "jtuHIJhwoTGzavFpM7ilNw==",
+ "eBvTV27n6Gs+ZsBkpVynvw==",
+ "sFbzw0AUOGG0NEzkaSxVDg==",
+ "yAkIS+Ezj6woEff9YvdO7Q==",
+ "IP1+BwG6q60QzDADi8j7oA==",
+ "Q/teQEBFepHtwZ7UHa2TEA==",
+ "B1vDep5a1Gok5Gnth39+LA==",
+ "cyEIyQ2MZaPGf+K1x9Bbkg==",
+ "aaM+oEJnF4/nwMWyXJU8rA==",
+ "qpDNIpxah8FUiqXm5IRaUg==",
+ "ZTeJ35gMPqIv2WWbeNyIEg==",
+ "nzoAGQAnC/Xgg5PmOgXqkA==",
+ "J5pJDuNi3cqQiyaRJAJk4g==",
+ "2vqN53BXhXzPrKYsh6QH1A==",
+ "QlrzHNYxCwCBMVENvbXjQA==",
+ "Ou2HGn43nmsL3RWSNvMdXw==",
+ "3qk9lsvGTMqVMAZW+xihfw==",
+ "RncMe42RB2bhmUbYtGVnKQ==",
+ "hzNXR6dqPq1+vf4Qh5ByWA==",
+ "sRq3S2ZRs3H39cEQHv4Vig==",
+ "B4ThUBTVJOUPyOsHxikHXA==",
+ "A2lU9GkAdSibLO1JJfFnIA==",
+ "ef3HNkSvuWQrAzkuty2iqg==",
+ "yKDiRM6bf2xc0QXIwHYuaA==",
+ "AdCk4ccJuhA0bIT/61J+RQ==",
+ "UXvAZ7ULCVz2f505K0Wkvg==",
+ "ueKWblrOwVJNgiOvkXKLBQ==",
+ "s8u/jPuBAxu1d18HfV5Z0g==",
+ "hUT0Uc5YMUdNZQEGLz4hJw==",
+ "6jo/phmMTrEXKrNRsionGQ==",
+ "s/Ea/3fkyJ9honzPJkgEQQ==",
+ "hgu2/Jf+WrQAHfO+asW2zw==",
+ "kiVuTNwZ1r2lqYEZxIHyiQ==",
+ "24T5KVrVE2mYwJ5Goj3xJw==",
+ "fiWBVlfj97GGjEvf/Q9Spg==",
+ "5VWdlvJe7eoXMGkTtHzCUg==",
+ "+cFQxKa5RWVtc1z00Jujew==",
+ "nVa+rLH5p+yXBksLwQsjRQ==",
+ "5tyI6bMdb3tMIi4ewvr/SQ==",
+ "S6Roj31yS5bZbSFcd3f4Hg==",
+ "uW1Zl8iuEF8ZT/gwCBEqwA==",
+ "YwL+FJgxlZ8JVig+9iP5Cw==",
+ "ThIYK/mQsp9cMf8+rws/4Q==",
+ "w0oSxOhRG6kE9B868aoYVQ==",
+ "DJUDGQ0J32dF1kfItyxALg==",
+ "34/ab69lPkuAKt6WBxJPpA==",
+ "25jH4C9apgqWZGZP15lM6Q==",
+ "GxvwleSaSwILD1pG9k9buA==",
+ "YRAMt2ArEINo83ms6AqJ0A==",
+ "15HyTJNoMYzi3XCkeU5Z7A==",
+ "/SqjXGD+TKC90uz1vsjqUw==",
+ "karhKOknkhtg/LSFo9BGRA==",
+ "+tD1d0t3vfJvc1hUAvTT4Q==",
+ "rkaKbtlnyVr53D0rexLqdQ==",
+ "fAugw4rtnXzzRXfC1wRgOQ==",
+ "RgxoepF/XOwIsGat5r5HpQ==",
+ "Y49/EnzVz3ugXCYxFjFN7g==",
+ "tHMyzBm/2wNDw7TeNeujbg==",
+ "LlqzYV4uZpiJy4ORWPSekA==",
+ "M3Huar7/ded9OGgDwJhZgw==",
+ "QkNNATSx/PJ1XjgZyTtkUQ==",
+ "skVw0v6Wx00sfHAScPK1Bw==",
+ "v1gsIvg+C68T9wixMzL2sQ==",
+ "hDL75EXhl7BaYnAxkoGwbw==",
+ "tReG97snx2ESpXbfllCL7Q==",
+ "EiZBXR15dT1TMrkgkzmkvw==",
+ "5hRHirfD90/sdp0ILJQU8A==",
+ "rabElvtYtG0jW6dxAOHofg==",
+ "JpxoTRKWN+SEeBQ453R1YQ==",
+ "Faz4Lm0cpjvF0IjVkHiZMg==",
+ "jGErFAIoXx+50KFpVIGZiA==",
+ "5GzBkduKpUX7u1uwtYIFug==",
+ "cRBe0J9/KWRX19N2vPkCiw==",
+ "t/7g8t4Kr3/+SCnOn3XFWQ==",
+ "sd08c6jUXs5/hxND0fBkPA==",
+ "nTxKpqIdnHNdpDk7Dx3TEg==",
+ "5l+RALcce+lTDnmXI+Wqqg==",
+ "pzJ4QmEBGRNiiX6z0xHh8g==",
+ "Vfl3YbqR6JRR7SIdsUA/vA==",
+ "cgfhOdB376a4GAcuACADvA==",
+ "inAefsQM6tiIhQCMtcPcyA==",
+ "FTSULGL8CMhmcc7Cyf/X8A==",
+ "9XSWpaZyHEy7V/tuw5uZEw==",
+ "+VtM1opKlgb/jrCwc4YjFA==",
+ "oF46xheuI/NUxUOnOttzvA==",
+ "Qy+lvhDbJCumr6kiPLd1oA==",
+ "swps7UEKpIbVBJ9SnPK3zQ==",
+ "b7wyIiJvJs+29QePxsdWtQ==",
+ "x3iDZxYyuHtG/9rNW5HMYg==",
+ "r1dx1g5UOksywvOaQTamfA==",
+ "KvVF3Si/fr4JQtr7jCJiog==",
+ "spvZ7hhtG5QY7JXs96lBUg==",
+ "ECL8mA5B6CswyDH6yJ4hVw==",
+ "7Uu+YsdS69dMSDYUr6vTag==",
+ "Rnm9pSvQRRbkHpOijraLZw==",
+ "aQJqpnXdzqNSFhMn3EJA2Q==",
+ "TctnXpd7Wd5ZXKMnOFHAQA==",
+ "+lPqG8l6mf2FWVGWflyF/g==",
+ "mPmnmL2oRRJmKYjQ6TfN3g==",
+ "fyXFcT5ZCawDBg74n1WSpg==",
+ "uq5Zrxq10pO1HoPxReT5og==",
+ "3eoCsOKXY8RDrHSdlXqmrA==",
+ "9nQv2BFG56xsHViN5UpHYw==",
+ "RtP/nJgy/ItyuDrpBbAotg==",
+ "5E/drRptfHmBhJ7qplujGg==",
+ "cUxyZvoqXbQ0a/0I9s6Zbg==",
+ "womzqSigwEF30V422YmxKw==",
+ "FPvZqDfN8dTFHLVOuYEbUA==",
+ "YZMXx+scKXp/v9GaJjb1bA==",
+ "bjURu5MRsNIZavG5HV0eZw==",
+ "iY0C9uSMEOn8ikT+J7+/Eg==",
+ "aXkD6BzsdkMEv7A+eYqQQQ==",
+ "dOcOfEDGHYG2kgmrglDkPw==",
+ "c7GjtY05Mh+cp6SNuWY3Ig==",
+ "lM1uY1oVncHXNzKs/cCEtQ==",
+ "7jXnQJkutLsi+r9aYmrMxw==",
+ "NgrugWWduj2qdWnEQf9dLA==",
+ "faYjmy/yn5iXdS28QCIdWw==",
+ "68XbaOvIZpCGb4G1gaKErA==",
+ "Yi67HkOLtGYXeL7WD4GPrA==",
+ "Puo8gXuUkwcoQViaXwkdSQ==",
+ "L202Et5aZh60Vl20LTKNFg==",
+ "4agAzQ5+dnTmLZEjsZs26g==",
+ "LegGM1ft8Y7Ka3CUxpObvg==",
+ "KRdILc1QDOpow5im/qY+Kw==",
+ "peMW+rpwmXrSwplVuB/gTA==",
+ "Pic1ncr+Zn6wv75zjAdzQA==",
+ "ilSPlWYbiPzIC13vQUBlOw==",
+ "GUlDufLoTalBqrG/h3mZ6w==",
+ "5twANNlT57T9BG4r2D9+Hw==",
+ "ENrnM8HlMi+5y8Hsu4Pn4A==",
+ "K/DzpLEbz1MpRjA6qyYn4Q==",
+ "yN1cHJRHDXoFxFZacL6wsw==",
+ "Rc6r+KqIePH+dnj1aNYCsQ==",
+ "8u/z5htgqXVU5Dqwd9whJQ==",
+ "jV575O42EYoqDNxCm9643Q==",
+ "xCxGo0h3lS8N6X+ivKfpjA==",
+ "us+2nfpj2gjI7s14Hw0gmA==",
+ "bp90A/rbESwVU7eh9xRTfQ==",
+ "5QtMXzbTafvKDQOWZP7M8w==",
+ "1gFCxPLjQlQGKmSGmHwmJQ==",
+ "m+/dnOIe6SaIFhfvg+ybDg==",
+ "9Dcg87+RPq9U+swRg4dH3Q==",
+ "mnjbL7WFmrWp0RUqS8AMGA==",
+ "/0e0E+NFmq8GeE5+y2Gekw==",
+ "y11mbpHHtka9Ep8cr2nEvQ==",
+ "GdmjRyliw+W21Q+dHO4CWA==",
+ "X65wWQTpkg756V/Nfn92kQ==",
+ "xj06KvacQOxRSofbhzBNgA==",
+ "nVDxVhaa2o38gd1XJgE3aw==",
+ "4IV+JOGXrltpkQamBRXMgA==",
+ "jIfp8LqaYXT88r/K3a8gNw==",
+ "vhT4dDtbMFVyevS6yCGy0g==",
+ "zMs7/x8hDt8xj2FFc5+6vA==",
+ "1J7u2N62JGb2VrnCRlJIrw==",
+ "3hJs9P/RRxB0CO4q0Icb+g==",
+ "ZpuVY1ZyoKD3hqosdsfT6Q==",
+ "6KIM7C7eWgxZtqZboiJvZQ==",
+ "vtb6fdqirkuUkqITAmXTlw==",
+ "C/rEVr22mw2u/1dwUx9VTg==",
+ "NrY4Q5C67haCWLK8HXHq9g==",
+ "X9qvEftCEFWX3gBU5hXy+Q==",
+ "0zgw7xNB3xVGaH48TyxaNQ==",
+ "g7J9Jy/PJrAGRgVdvA+bEg==",
+ "9zb+anAyZVBzuU9rW4cJtg==",
+ "6Zc5FzT/m0YIjxEPYA6zDQ==",
+ "R2YPNlvCbVK0EodTR7czIw==",
+ "gsI6EGgXMtDu+1u364A8mw==",
+ "Bg2wBFb1/xaxeEiHfBHX+A==",
+ "64aapfVI6dV3LpTK56KZlg==",
+ "HdgcJU0W3yVnH69VYStmug==",
+ "qTDCcv+LK3JPFB/++t66IQ==",
+ "P0HEIXMnAmbvq+QYREwFzw==",
+ "aaU7CAmtyE35jNKTkyXOkg==",
+ "r9G97WKDiQ48qJHP9LBRNg==",
+ "8mPgQhYVDn8KshDDvvf5SA==",
+ "GCQiiOLDguXLiYwuLcFPsA==",
+ "R2Use39If2C0FVBP7KDerA==",
+ "23C4eh3yBb5n/RNZeTyJkA==",
+ "2QQtKtBAm2AjJ5c0WQ6BQA==",
+ "Qc+XYy2qyWJ5VVwd2PExbw==",
+ "zJ7ScHNxr2leCDNNcuDApA==",
+ "vFtC0B2oe1gck28JOM1dyg==",
+ "bLEntCrCHFy9pg3T3gbBzg==",
+ "G3PmmPGHaWHpPW30xQgm3Q==",
+ "me61ST+JrXM5k3/a11gRAA==",
+ "+LJYVZl1iPrdMU3L5+nxZw==",
+ "CLPzjXKGGpJ0VrkSJp7wPQ==",
+ "Pc+u0MAzp4lndTz4m6oQ5w==",
+ "cwBNvZc0u4bGABo88YUsVQ==",
+ "q7m/EtZySBjZNBjQ5m1hKw==",
+ "8ZBiwr842ZMKphlqmNngHw==",
+ "LMCZqd3UoF/kHHwzTdj7Tw==",
+ "0ODJyWKJSfObo+FNdRQkkA==",
+ "ViweSJuNWbx5Lc49ETEs/A==",
+ "x+8rwkqKCv0juoT5m1A4eg==",
+ "pxuSWn1u+bHtRjyh2Z8veA==",
+ "GKzs8mlnQQc58CyOBTlfIg==",
+ "Owg8qCpjZa+PmbhZew6/sw==",
+ "YLz+HA6qIneP+4naavq44Q==",
+ "9ajIS45NTicqRANzRhDWFA==",
+ "DjeSrUoWW2QAZOAybeLGJg==",
+ "qxALQrqHoDq9d91nU0DckA==",
+ "yPIeWcW8+3HjDagegrN8bw==",
+ "ocpLRASvTgqfkY20YlVFHQ==",
+ "RuLeQHP1wHsxhdmYMcgtrQ==",
+ "3WwITQML938W9+MUM56a3A==",
+ "ZbLVNTQSVZQWTNgC4ZGfQg==",
+ "X6Ln4si8G5aKar52ZH/FEQ==",
+ "+gbitI/gpxebN/rK7qj8Fw==",
+ "7cnUHeaPO8txZGGWHL9tKg==",
+ "epY+dsm5EMoXnZCnO4WSHw==",
+ "nf8x+F03kOpMhsCSUWEhVg==",
+ "VE4sLM5bKlLdk85sslxiLQ==",
+ "Hs3vUOOs2TWQdQZHs+FaQQ==",
+ "hkOBNoHbno2iNR7t3/d4vg==",
+ "Ar9N1VYgE7riwmcrM3bA2Q==",
+ "SbMjjI8/P8B9a9H2G0wHEQ==",
+ "tU31r8zla146sqczdKXufg==",
+ "tFmWYH82I3zb+ymk5dhepA==",
+ "XHjrTLXkm/bBY/BewmJcCQ==",
+ "FV/D5uSco+Iz8L+5t7E8SA==",
+ "yKLLiqzxfrCsr6+Rm6kx1Q==",
+ "B6reUwMkQFaCHb9BYZExpw==",
+ "5jyuDp82Fux+B0+zlx8EXw==",
+ "WGKFTWJac8uehn3N59yHJw==",
+ "JQf9UmutPh3tAnu7FDk3nA==",
+ "hv5GrLEIjPb4bGOi8RSO0w==",
+ "p3V7NfveB6cNxFW7+XQNeQ==",
+ "DinJuuBX9OKsK5fUtcaTcQ==",
+ "UEMwF4kwgIGxGT4jrBhMPQ==",
+ "Y78dviyBS3Jq9zoRD5sZtQ==",
+ "zbjXhZaeyMfdTb2zxvmRMg==",
+ "kydoXVaNcx1peR5g6i588g==",
+ "M2suCoFHJ5fh9oKEpUG3xA==",
+ "/VnKh/NDv7y/bfO6CWsLaQ==",
+ "S+b37XhKRm8cDwRb1gSsKQ==",
+ "jz7QlwxCIzysP39Cgro8jg==",
+ "IjmLaf3stWDAwvjzNbJpQA==",
+ "cHSj5dpQ04h/WyefjABfmQ==",
+ "+gO0bg8LY+py2dLM1sM7Ag==",
+ "fSANOaHD0Koaqg7AoieY9A==",
+ "vqYHQ3MnHrAIAr1QHwfIag==",
+ "Uh1mvZNGehK1AaI4a1auKQ==",
+ "HCbHUfsTDl6+bxPjT57lrA==",
+ "S7Vjy/gOWp0HozPP1RUOZw==",
+ "KPh6TwYpspne4KZA6NyMbw==",
+ "cfh5VZFmIqJH/bKboDvtlA==",
+ "H1zH9I8RwfEy5DGz3z+dHw==",
+ "2ksediOVrh4asSBxKcudTg==",
+ "+jVN/3ASc2O44sX6ab8/cg==",
+ "uvKYnKE01D5r7kR9UQyo5A==",
+ "BB9PTlwKAWkExt3kKC/Wog==",
+ "yqQPU4jT9XvRABZgNQXjgg==",
+ "6v3eTZtPYBfKFSjfOo2UaA==",
+ "49z/15Nx9Og7dN9ebVqIzg==",
+ "VjclDY8HN4fSpB263jsEiQ==",
+ "vSKsa0JhLCe9QFZKkcj58Q==",
+ "PolhKCedOsplEcaX4hQ0YQ==",
+ "D0Qt9sRlMaPnOv1xaq+XUg==",
+ "gBgJF0PiGEfcUnXF0RO7/w==",
+ "sC11Rf/mau3FG5SnON4+vQ==",
+ "rKb3TBM4EPx/RErFOFVCnQ==",
+ "+n0K7OB2ItzhySZ4rhUrMg==",
+ "Epm0d/DvXkOFeM4hoPCBrg==",
+ "K8PVQhEJCEH1ghwOdztjRw==",
+ "xjA21QjNdThLW3VV7SCnrg==",
+ "nE72uQToQFVLOzcu/nMjww==",
+ "2Hc5oyl0AYRy2VzcDKy+VA==",
+ "Y7XpxIwsGK3Lm/7jX/rRmg==",
+ "MK7AqlJIGqK2+K5mCvMXRQ==",
+ "mXycPfF5zOvcj1p4hnikWw==",
+ "V1fvtnJ0L3sluj9nI5KzRw==",
+ "TahqPgS7kEg+y6Df0HBASw==",
+ "EKU3OVlT4b/8j3MTBqpMNg==",
+ "EdvIAKdRAXj7e42mMlFOGQ==",
+ "uPm+cF4Jq08S5pQhYFjU8A==",
+ "CnIwpRVC2URVfoiymnsdYQ==",
+ "wyx5mnUMgP5wjykjAfTO7w==",
+ "OwIGvTh8FPFqa4ijNkguAw==",
+ "4ID0PHTzIMZz2rQqDGBVfA==",
+ "rlXt6zKE7DswUl0oWGOQUQ==",
+ "4NP8EFFJyPcuQKnBSxzKgQ==",
+ "bJgsuw29cO2WozqsGZxl7w==",
+ "b3q8kjHJPj9DWrz3yNgwjQ==",
+ "QGYFMpkv37CS2wmyp42ppg==",
+ "Kzs+/IZJO8v4uIv9mlyJ2Q==",
+ "ZJY+hujfd58mTKTdsmHoQQ==",
+ "R8FxgXWKBpEVbnl41+tWEw==",
+ "+CvLiih/gf2ugXAF+LgWqw==",
+ "BDbfe/xa9Mz1lVD82ZYRGA==",
+ "Dz90OhYEjpaJ/pxwg1Qxhg==",
+ "MLHt6Ak288G0RGhCVaOeqA==",
+ "r0QffVKB9OD9yGsOtqzlhA==",
+ "hK8KhTFcR06onlIJjTji/Q==",
+ "wMum67lfk5E1ohUObJgrOg==",
+ "JKmZqz9cUnj6eTsWnFaB0A==",
+ "rtJdfki8fG6CB36CADp0QA==",
+ "cUyqCa7Oue934riyC17F8g==",
+ "y4Y4mSSTw/WrIdRpktc5Hw==",
+ "r36kVMpF+9J+sfI3GeGqow==",
+ "ydVj2odhergi+2zGUwK4/A==",
+ "J2NFyb8cXEpZyxWDthYQiA==",
+ "qYuo5vY8V3tZx41Kh9/4Dw==",
+ "jrfRznO0nAz6tZM1mHOKIA==",
+ "JSr/lqDej81xqUvd/O2s7w==",
+ "vHGjRRSlZHJIliCwIkCAmQ==",
+ "sQAxqWXeiu/Su0pnnXgI9A==",
+ "xPe76nHyHmald6kmMQsKdg==",
+ "50jASqzGm4VyHJbFv8qVRA==",
+ "uuiJ+yB7JLDh2ulthM0mjg==",
+ "TI90EuS/bHq/CAlX32UFXg==",
+ "JgxNrUlL8wutG04ogKFPvw==",
+ "aMa1yVA71/w6Uf1Szc9rMA==",
+ "k/Aou2Jmyh8Bu3k8/+ndsQ==",
+ "iANKiuMqWzrHSk9nbPe3bQ==",
+ "7GgNLBppgAKcgJCDSsRqOQ==",
+ "bzVeU2qM9zHuzf7cVIsSZw==",
+ "rkeLYwMZ1/pW2EmIibALfA==",
+ "91+Yms6Oy/rP0rVjha5z9w==",
+ "JgXSPXDqaS1G9NqmJXZG0A==",
+ "ZzduJxTnXLD9EPKMn1LI4Q==",
+ "6W79FmpUN1ByNtv5IEXY4w==",
+ "Y1Nm3omeWX2MXaCjDDYnWQ==",
+ "ejfikwrSPMqEHjZAk3DMkA==",
+ "WNfDNaWUOqABQ6c6kR+eyw==",
+ "4BkqgraeXY7yaI1FE07Evw==",
+ "AjHz9GkRTFPjrqBokCDzFw==",
+ "T/6gSz2HwWJDFIVrmcm8Ug==",
+ "VWy9lB5t4fNCp4O/4n8S4w==",
+ "/FdZzSprPnNDPwbhV1C0Cg==",
+ "LUWxfy4lfgB5wUrqCOUisw==",
+ "r1VGXWeqGeGbfKjigaAS+Q==",
+ "ztULoqHvCOE6qV7ocqa4/w==",
+ "QCpzCTReHxGm5lcLsgwPCA==",
+ "Hst3yfyTB7yBUinvVzYROQ==",
+ "gf1Ypna/Tt+TZ08Y+GcvGg==",
+ "3rbml1D0gfXnwOs5jRZ3gA==",
+ "2vm7g3rk1ACJOTCXkLB3zA==",
+ "11FE2kknwYi2Qu0JUKMn3A==",
+ "1b2uf+CdVjufqiVpUShvHw==",
+ "0a4SafpDIe8V4FlFWYkMHw==",
+ "7btpMFgeGkUsiTtsmNxGQA==",
+ "dUx1REyXKiDFAABooqrKEA==",
+ "knYKU74onR6NkGVjQLezZg==",
+ "Scto+9TWxj1eZgvNKo+a9A==",
+ "cvZT1pvNbIL8TWg+SoTZdA==",
+ "1nXByug2eKq0kR3H3VjnWQ==",
+ "tG+rpfJBXlyGXxTmkceiKA==",
+ "7W9aF7dxnL+E8lbS/F7brg==",
+ "8vr+ERVrM99dp+IGnCWDGQ==",
+ "oFNMOKbQXcydxnp8fUNOHw==",
+ "uJZGw3IY2nCcdVeWW1geNQ==",
+ "q6LG0VzO1oxiogAAU63hyg==",
+ "f0H/AFSx2KLZi9kVx5BAZg==",
+ "1RQZ2pWSxT+RKyhBigtSFg==",
+ "scCQPl0em2Zmv/RQYar60g==",
+ "A2ODff+ImIkreJtDPUVrlg==",
+ "vRgkZZGVN7YZrlml0vxrKA==",
+ "68jPYo3znYoU4uWI7FH3/g==",
+ "iJ2nT8w8LuK11IXYqBK+YA==",
+ "54XELlPm8gBvx8D5bN3aUg==",
+ "PTAm/jGkie7OlgVOvPKpaA==",
+ "v7BrkRmK0FfWSHunTRHQFQ==",
+ "dVh/XMTUIx1nYN4q1iH1bA==",
+ "TSGL3iQYUgVg/O9SBKP9EA==",
+ "wTO49YX/ePHMWtcoxUAHpw==",
+ "bMb1ia0rElr2ZpZVhva0Jw==",
+ "sNmW2b2Ud7dZi3qOF8O8EQ==",
+ "3djRJvkZk9O2bZeUTe+7xQ==",
+ "I9KNZC1tijiG1T72C4cVqQ==",
+ "sQzCwNDlRsSH7iB9cTbBcg==",
+ "mk1CKDah7EzDJEdhL22B7w==",
+ "lON3WM0uMJ30F8poBMvAjQ==",
+ "88PNi9+yn3Bp4/upgxtWGA==",
+ "C+Ssp+v1r+00+qiTy2d7kA==",
+ "11U5XEwfMI7avx014LfC8g==",
+ "xsf0m31Am0W9eLhopAkfnA==",
+ "d13Rj3NJdcat0K/kxlHLFw==",
+ "UP7NXAE0uxHRXUAWPhto0w==",
+ "ZKXxq9yr7NGBOHidht34uQ==",
+ "Fd2fYFs8vtjws2kx1gf6Rw==",
+ "ojf6uL85EuEYgLvHoGhUrw==",
+ "KjnL3x+56r3M2pDj1pPihA==",
+ "WdCWezJU4JK43EOZ9YHVdg==",
+ "/jH6imhTPZ/tHI4gYz2+HA==",
+ "+OLntmlsMBBYPREPnS6iVw==",
+ "5lfLJAk1L3QzGMML3fOuSw==",
+ "AZs3v4KJYxdi8T1gjVjI2Q==",
+ "7pkUY2UzSbGnwLvyRrbxfA==",
+ "BjfOelfc1IBgmUxMJFjlbQ==",
+ "TcGhAJHRr7eMwGeFgpFBhg==",
+ "Y7iDCWYrO1coopM3RZWIPg==",
+ "mnalaO6xJucSiZ0+99r3Cg==",
+ "plXHHzA8X9QGwWzlJxhLRw==",
+ "Zqd6+81TwYuiIgLrToFOTQ==",
+ "1Pmnur6TbZ9cmemvu0+dSA==",
+ "OaNpzwshdHUZMphQXa6i8w==",
+ "WKehT4nGF2T7aKuzABDMlA==",
+ "4LvQSicqsgxQFWauqlcEjw==",
+ "BMZB1FwvAuEqyrd0rZrEzw==",
+ "YfbfE3WyYOW7083Y8sGfwQ==",
+ "46FCwqh+eMkf+czjhjworw==",
+ "734u4Y1R3u7UNUnD+wWUoA==",
+ "yf06Slv9l3IZEjVqvxP2aA==",
+ "bIk7Fa6SW7X18hfDjTKowg==",
+ "DnF6TYSJxlc+cwdfevLYng==",
+ "ionqS0piAOY2LeSReAz4zg==",
+ "hlMumZ7RJFpILuKs09ABtw==",
+ "NjeDgQ1nzH1XGRnLNqCmSg==",
+ "o7y4zQXQAryST2cak4gVbw==",
+ "29EybnMEO95Ng4l/qK4NWQ==",
+ "udU65VtsvJspYmamiOsgXw==",
+ "v1AWe5qb5y3vSKFb7ADeEw==",
+ "wK6Srd83eLigZ11Q20XGrg==",
+ "GmC+0rNDMIR+YbUudoNUXw==",
+ "W4utAK3ws0zjiba/3i91YA==",
+ "MlKWxeEh8404vXenBLq4bw==",
+ "Gdf4VEDLBrKJNQ8qzDsIyw==",
+ "Z9bDWIgcq6XwMoU2ECDR5Q==",
+ "VIkS30v268x+M1GCcq/A8A==",
+ "iPwX3SbbG9ez9HoHsrHbKw==",
+ "yKrsKX4/1B1C0TyvciNz5w==",
+ "BophnnMszW5o+ywgb+3Qbw==",
+ "eJLrGwPRa6NgWiOrw1pA7w==",
+ "eV+RwWPiGEB+76bqvw+hbA==",
+ "oad5SwflzN0vfNcyEyF4EA==",
+ "Uw6Iw+TP9ZdZGm2b/DAmkg==",
+ "9qWLbRLXWIBJUXYjYhY2pg==",
+ "dxWv00FN/2Cgmgq9U3NVDQ==",
+ "AX1HxQKXD12Yv5HWi39aPQ==",
+ "J0NauydfKsACUUEpMhQg8A==",
+ "mxug34EekabLz0JynutfBg==",
+ "bNq/hj0Cjt4lkLQeVxDVdQ==",
+ "nW3zZshjZEoM8KVJoVfnuQ==",
+ "ghp8sWGKWw20S/z1tbTxFg==",
+ "S4rFuiKLFKZ+cL7ldiTwpg==",
+ "8ZqmPJDnQSOFXvNMRQYG2Q==",
+ "6XYqR2WvDzx4fWO7BIOTjA==",
+ "Uo+FIhw1mfjF6/M8cE1c/Q==",
+ "bsHIShcLS134C+dTxFQHyA==",
+ "19yQHaBemtlgo2QkU5M6jQ==",
+ "sWLcS+m4aWk31BiBF+vfJQ==",
+ "BlCgDd7EYDIqnoAiKOXX6Q==",
+ "MrxR3cJaDHp0t3jQNThEyg==",
+ "cMo6l1EQESx1rIo+R4Vogg==",
+ "VOvrzqiZ1EHw+ZzzTWtpsw==",
+ "1/ZheMsbojazxt31j/l3iA==",
+ "0QxPAqRF8inBuFEEzNmLjA==",
+ "UXUNYEOffgW3AdBs7zTMFA==",
+ "lOPJhHqCtMRFZfWMX/vFZQ==",
+ "rXSbbRABEf4Ymtda45w8Fw==",
+ "jfegbZSZWkDoPulFomVntA==",
+ "hfcH5Az2M7rp+EjtVpPwsg==",
+ "VsXEBIaMkVftkxt1kIh7TA==",
+ "M20iX2sUfw5SXaZLZYlTaA==",
+ "VUDsc9RMS1fSM43c+Jo9dQ==",
+ "itPtn+JaO4i7wz2wOPOmDQ==",
+ "rCxoo4TP/+fupXMuIM0sDA==",
+ "cSHSg9xJz/3F6kc+hKXkwg==",
+ "b4BoZmzVErvuynxirLxn0w==",
+ "e4B3HmWjW+6hQzcOLru6Xg==",
+ "lTE6u9G/RzvmbuAzq2J2/Q==",
+ "897ptlztTjr7yk+pk8MT0Q==",
+ "jd6IpPJwOJW1otHKtKZ5Gw==",
+ "b4aFwwcWMXsSdgS1AdFOXA==",
+ "FltEN+7NKvzt+XAktHpfHA==",
+ "ZyDh3vCQWzS5DI1zSasXWA==",
+ "kcJ1acgBv6FtUhV8KuWoow==",
+ "zgEyxj/sCs63O98sZS94Yw==",
+ "/kGxvyEokQsVz0xlKzCn2A==",
+ "cxqHS4UbPolcYUwMMzgoOA==",
+ "62RHCbpGU8Hb+Ubn+SCTBg==",
+ "ePlsM/iOMme2jEUYwi15ng==",
+ "0fN+eHlbRS6mVZBbH/B9FQ==",
+ "k0XIjxp2vFG7sTrKcfAihA==",
+ "0rfG4gRugAwVP0i3AGVxxg==",
+ "M98hjSxCwvZ27aBaJTGozQ==",
+ "kzGNkWh3fz27cZer4BspUQ==",
+ "3CJbrUdW68E3Drhe4ahUnQ==",
+ "NGApiVkDSwzO45GT57GDQw==",
+ "lMjip5hbCjkD9JQjuhewDg==",
+ "GrSbnecYAC3j5gtoKntL0A==",
+ "9dbn0Kzwr9adCEfBJh78uQ==",
+ "64QzHOYX0A9++FqRzZRHlQ==",
+ "YZt6HwCvdI5DRQqndA/hBQ==",
+ "6GXHGF62/+jZ7PfIBlMxZw==",
+ "PBULPuFXb6V3Di713n3Gug==",
+ "8Cm19vJW8ivhFPy0oQXVNA==",
+ "zDSQ3NJuUGkVOlvVCATRwA==",
+ "6QAtjOK9enNLRhcVa2iaTg==",
+ "v/PshI6JjkL9nojLlMNfhg==",
+ "yTgN5xFIdz1MzFS6xMl5uQ==",
+ "SCO9nQncEcyVXGCtx30Jdg==",
+ "7b0oo4+qphu6HRvJq6qkHQ==",
+ "ol9xhVTG9e1wNo50JdZbOA==",
+ "hIABph+vhtSF5kkZQtOCTA==",
+ "k+IBS52XdOe5/hLp28ufnA==",
+ "6HnWgYNKohqhoa1tnjjU3A==",
+ "HDxGhvdQwGh0aLRYEGFqnw==",
+ "LDuBcL5r3PUuzKKZ9x6Kfw==",
+ "HPvYV94ufwiNHEImu4OYvQ==",
+ "h2cnQQF2/R3Mq2hWdDdrTg==",
+ "nqpKfidczdgrNaAyPi7BOQ==",
+ "2ywo4t5PPSVUCWDwUlOVwQ==",
+ "jZMDIu95ITTjaUX0pk4V5g==",
+ "bA2kaTpeXflTElTnQRp6GQ==",
+ "lwYQm2ynA3ik2gE1m11IEg==",
+ "5ugVOraop5P5z5XLlYPJyQ==",
+ "l2NppPcweAtmA1V2CNdk2Q==",
+ "DbWQI3H2tcJsVJThszfHGA==",
+ "H6HPFAcdHFbQUNrYnB74dA==",
+ "H1NJEI+fvOQbI51kaNQQjQ==",
+ "53UccFNzMi9mKmdeD82vAw==",
+ "lffapwUUgaQOIqLz2QPbAg==",
+ "rSvhrHyIlnIBlfNJqemEbw==",
+ "BLJk9wA88z6e0IQNrWJIVw==",
+ "5m1ijXEW+4RTNGZsDA/rxQ==",
+ "GG8a3BlwGrYIwZH9j3cnPA==",
+ "HhBHt5lQauNl7EZXpsDHJA==",
+ "/XjB6c5fxFGcKVAQ4o+OMw==",
+ "+tuUmnRDRWVLA+1k0dcUvg==",
+ "SM7E98MyViSSS9G0Pwzwyw==",
+ "c5q/8n7Oeffv3B1snHM/lA==",
+ "kwlAQhR2jPMmfLTAwcmoxw==",
+ "0b/xj6fd0x+aB8EB0LC4SA==",
+ "S8jlvuYuankCnvIvMVMzmg==",
+ "kZkmDatUOdIqs7GzH3nI1A==",
+ "obW3kzv2KBvuckU7F+tfjA==",
+ "pa8nkpAAzDKUldWjIvYMYg==",
+ "m+eh+ZqS74w2q0vejBkjaw==",
+ "LcoJBEPTlSsQwfuoKQUxEw==",
+ "KO2XVYyNZadcQv8aCNn5JA==",
+ "uvzmRcvgepW6mZbMfYgcNw==",
+ "KhUT2buOXavGCpcDOcbOYg==",
+ "fo3JL+2kPgDWfP+CCrFlFw==",
+ "wIfvvLKC61gOpsddUFjVog==",
+ "SPHU6ES1WVm0Mu2LB+YjrA==",
+ "LWWfRqgtph1XrpxF4N64TA==",
+ "LCvz/h9hbouXCmdWDPGWqg==",
+ "PXC6ZpdMH0ATis/jGW12iA==",
+ "z920R8eahJPiTsifrPYdxA==",
+ "GIHKW6plyLra0BmMOurFgA==",
+ "k6OmSlaSZ5CB0i7SD9LczQ==",
+ "YZ39RIXpeLAhyMgmW2vfkQ==",
+ "bs2QG8yYWxPzhtyMqO6u3A==",
+ "pKaTI+TfcV3p/sxbd2e7YQ==",
+ "xWYecfzAtXT9WyQ8NYY/hw==",
+ "Fz8EI+ZpYlbcttSHs5PfpA==",
+ "wfwuxn+Vja1DNwiDwL2pcQ==",
+ "wux5Y8AipBnc5tJapTzgEQ==",
+ "U+oTpcjhc0E+6UjP11OE/Q==",
+ "yTVJKBn72RjakMBXDoBKHg==",
+ "0TxcYwG72dT7Tg+eG8pP1w==",
+ "imZ+mwiT22sW2M9alcUFfg==",
+ "CkDIoAFLlIRXra78bxT/ZA==",
+ "4qMSNAxichi3ori/pR+o0w==",
+ "zNLlWGW/aKBhUwQZ4DZWoQ==",
+ "D31ZticrjGWAO45l5hFh7A==",
+ "HdXg64DBy5WcL5fRRiUVOg==",
+ "yhI5jHlfFJxu4eV5VJO2zQ==",
+ "e9GqAEnk8XI5ix6kJuieNQ==",
+ "EC0+iUdSZvmIEzipXgj7Gg==",
+ "chwv4+xbEAa93PHg8q9zgQ==",
+ "B1VVUbl8pU0Phyl1RYrmBg==",
+ "A+DLpIlYyCb9DaarpLN76g==",
+ "wHA+D5cObfV3kGORCdEknw==",
+ "+Mp+JIyO0XC5urvMyi3wvQ==",
+ "vUE8Iw3NyWXURpXyoNJdaw==",
+ "ParhxI6RtLETBSwB0vwChQ==",
+ "NxSdT2+MUkQN49pyNO2bJw==",
+ "JSyhTcHLTfzHsPrxJyiVrA==",
+ "PAlx9+U+yQCAc5Fi0BOG0w==",
+ "W/0s1x3Qm+wN8DhROk6FrQ==",
+ "L3Jt5dHQpWQk74IAuDOL8g==",
+ "VWb8U4jF/Ic0+wpoXi/y/g==",
+ "1wBuHqS1ciup31WTfm3NPg==",
+ "BDNM1u/9mefjuW1YM2DuBg==",
+ "SDi5+FoP9bMyKYp+vVv1XA==",
+ "23d9B9Gz5kUOi1I//EYsSQ==",
+ "/a9O7kWeXa0le45ab3+nVw==",
+ "PcoVtZrS1x1Q+6nfm4f80w==",
+ "A6TLWhipfymkjPYq8kaoDQ==",
+ "lzUQ1o7JAbdJYpmEqi6KnQ==",
+ "/2jGyMekNu7U136K+2N3Jg==",
+ "ZItMIn1vhGqAlpDHclg0Ig==",
+ "Ee4A3lTMLQ7iDQ7b8QP8Qg==",
+ "bO55S58bqDiRWXSAIUGJKw==",
+ "zeHF6fdeqcOId3fRUGscRw==",
+ "BxsDnI8jXr4lBwDbyHaYXw==",
+ "ylA6sU7Kaf9fMNIx1+sIlw==",
+ "ZWXfE3uGU91WpPMGyknmqw==",
+ "f1+fHgR5rDPsCZOzqrHM7Q==",
+ "8VqeoQELbCs232+Mu+HblA==",
+ "beSrliUu0BOadCWmx+yZyA==",
+ "NQVQfN3nIg9ipHiFh4BvfQ==",
+ "4wnUAbPT3AHRJrPwTTEjyw==",
+ "/cdR1i5TuQvO+u3Ov3b0KQ==",
+ "wtyAZIfhomcHe9dLbYoSvA==",
+ "ulpDxLeQnIRPnq6oaah2AA==",
+ "pdPwUHauXOowaq9hpL2yFw==",
+ "1+A9FCGP3bZhk6gU3LQtNg==",
+ "raYifKqev8pASjjuV+UTKQ==",
+ "+OERSmo7OQUUjudkccSMOA==",
+ "FeRovookFQIsXmHXUJhGOw==",
+ "USCvrMEm/Wqeu9oX6FrgcQ==",
+ "kly/2kE4/7ffbO34WTgoGg==",
+ "IindlAnepkazs5DssBCPhA==",
+ "Bq82MoMcDjIo/exqd/6UoA==",
+ "ocvA1/NbyxM0hanwwY6EiA==",
+ "rtd6mqFgGe98mqO0pFGbSw==",
+ "nvLEpj6ZZF3LWH3wUB6lKg==",
+ "AGd0rcLnQ0n+meYyJur1Pw==",
+ "wI7JrSPQwYHpv2lRsQu9nQ==",
+ "OnmvXbyT2BYsSDJYZhLScA==",
+ "CmBf5qchS1V3C2mS6Rl4bw==",
+ "TafM7nTE5d+tBpRCsb8TjQ==",
+ "wxkb8evGEaGf/rg/1XUWiA==",
+ "y1J+o6DC2sETFsySgpDZyA==",
+ "SVLHWPCCH7GPVCF7QApPbw==",
+ "HMWOlMmzocOIiJ7yG1YaDQ==",
+ "DJmrmNRKARzsTCKSMLmcNA==",
+ "/XC/FmMIOdhMTPqmy4DfUA==",
+ "63OTPaKM0xCfJOy9EDto+Q==",
+ "PxReytUUn/BbxYTFMu1r2Q==",
+ "WjDqf1LyFyhdd8qkwWk+MA==",
+ "/DiUApY7cVp5W9o24rkgRA==",
+ "alJtvTAD7dH/zss/Ek1DMQ==",
+ "xLm/bJBonpTs0PwsF0DvRg==",
+ "eAOEgF5N80A/oDVnlZYRAw==",
+ "LqgzKxbI6WTMz0AMIDJR5w==",
+ "MJ1FuK8PXcmnBAG9meU84A==",
+ "JLq/DrW2f26NaRwfpDXIEA==",
+ "fsrX00onlGvfsuiCc35pGg==",
+ "tXVb5f90k9l3e1oK2NGXog==",
+ "1JRgSHnfAQFQtSkFTttkqQ==",
+ "B0TaUQ6dKhPfSc5V/MjLEQ==",
+ "nkbLVLvh3ClKED97+nH+7Q==",
+ "avFTp3rS6z5zxQUZQuaBHQ==",
+ "lNF8PvUIN02NattcGi5u4g==",
+ "bBEndaOStXBpAK79FrgHaw==",
+ "dM9up4vKQV5LeX82j//1jQ==",
+ "4WO6eT0Rh6sokb29zSJQnQ==",
+ "RHKCMAqrPjvUYt13BVcmvw==",
+ "Ju4YwtPw+MKzpbC0wJsZow==",
+ "tzV7ixFH37ze4zuLILTlfA==",
+ "oPlhC4ebXdkIDazeMSn1fQ==",
+ "5pje7qyz8BRsa8U4a4rmoA==",
+ "7E6V6/zSjbtqraG7Umj+Jw==",
+ "8QK7emHS6rAcAF5QQemW/A==",
+ "LhqRc9oewY4XaaXTcnXIHQ==",
+ "p/7qM5+Lwzw1/lIPY91YxQ==",
+ "fy54Milpa7KZH/zgrDmMXQ==",
+ "LyPXOoOPMieqINtX8C9Zag==",
+ "aD4QvtMlr8Lk/zZgZ6zIMg==",
+ "dsueq9eygFXILDC7ZpamuA==",
+ "+mJLK+6qq8xFv7O/mbILTw==",
+ "nHUpYmfV59fe3RWaXhPs3Q==",
+ "VbCoGr8apEcN7xfdaVwVXw==",
+ "/2Chaw2M9DzsadFFkCu6WQ==",
+ "rKAQxu80Q8g1EEhW5Wh8tg==",
+ "RJJqFMeiCZHdsqs72J17MQ==",
+ "GF2yvI9UWf1WY7V7HXmKPA==",
+ "JyIDGL1m/w+pQDOyyeYupA==",
+ "wR2Gxb07nkaPcZHlEjr8iA==",
+ "PbDVq2Iw1eeM8c2o/XYdTA==",
+ "BL3buzSCV78rCXNEhUhuKQ==",
+ "i42XumprV/aDT5R0HcmfIQ==",
+ "DuEKxykezAvyaFO2/5ZmKQ==",
+ "6ACvJNfryPSjGOK39ov8Qg==",
+ "YaUKOTyByjUvp1XaoLiW5Q==",
+ "jNcMS2zX1iSZN9uYnb2EIg==",
+ "VRnx+kd6VdxChwsfbo1oeQ==",
+ "4Qinl7cWmVeLJgah8bcNkw==",
+ "Fiy3hkcGZQjNKSQP9vRqyA==",
+ "HaSc7MZphCMysTy2JbTJkw==",
+ "VhYGC8KYe5Up+UJ2OTLKUw==",
+ "K2gk9zWGd0lJFRMQ1AjQ/Q==",
+ "NfxVYc3RNWZwzh2RmfXpiA==",
+ "JGeqHRQpf4No74aCs+YTfA==",
+ "7VHlLw20dWck+I8tCEZilA==",
+ "V5HKdaTHjA8IzvHNd9C51g==",
+ "9TalxEyFgy6hFCM73hgb7Q==",
+ "R/y6+JJP8rzz1KITJ4qWBw==",
+ "7bM/pn4G7g7Zl6Xf1r62Lg==",
+ "CHsFJfsvZkPWDXkA6ZMsDQ==",
+ "uXuPA/2KJbb7ZX+NymN3dw==",
+ "o+nYS4TqJc6XOiuUzEpC3A==",
+ "8N3mhHt29FZDHn1P2WH1wQ==",
+ "uZ2gUA74/7Q33tI2TcGQlg==",
+ "8B12CamjOGzJDnQ+RkUf4w==",
+ "9FdpxlIFu11qIPdO7WC5nw==",
+ "G+sGF13VXPH4Ih6XgFEXxg==",
+ "y+1I05LDAYJ09tKMs3zW6g==",
+ "gnkadeCgjdmLdlu/AjBZJg==",
+ "1I+UVx3krrD4NhzO7dgfHQ==",
+ "8LNNoHe6rEQyJ0ebl151Mw==",
+ "yOE90OHQdyOfrAgwDvn2gA==",
+ "ayBGGPEy++biljvGcwIjXA==",
+ "o/Y4U6rWfsUCXJ72p5CUGw==",
+ "5kvyy902llnYGQdn2Py04w==",
+ "6k2cuk0McTThSMW/QRHfjA==",
+ "2XrR2hjDEvx8MQpHk9dnjw==",
+ "fv/PW8oexJYWf5De30fdLQ==",
+ "861mBNvjIkVgkBiocCUj/Q==",
+ "NKGY0ANVZ0gnUtzVx1pKSw==",
+ "4DIPP/yWRgRuFqVeqIyxMQ==",
+ "cgSEbLqqvDsNUyeA3ryJ6Q==",
+ "xbBxUP9JyY0wDgHDipBHeg==",
+ "c3WVxyC5ZFtzGeQlH5Gw+w==",
+ "ZKeTDCboOgCptrjSfgu0xw==",
+ "DjHszpS8Dgocv3oQkW/VZQ==",
+ "Iqszlv4R49UevjGxIPMhIA==",
+ "uChFnF0oCwARhAOz/d47eA==",
+ "0egBaMnAf0CQEXf1pCIKnA==",
+ "FnVNxl5AFH1AieYru2ZG+A==",
+ "2Ct+pLXrK6Ku1f4qehjurQ==",
+ "x2nSgcTjA3oGgI8mMgiqjw==",
+ "AUGmvZkpkKBry5bHZn4DJA==",
+ "x8kRVzohTdhkryvYeMvkMw==",
+ "rXfWkabSPN+23Ei1bdxfmQ==",
+ "ElTNyMR4Rg8ApKrPw88WPg==",
+ "9jxA/t3TQx8dQ+FBsn/YCg==",
+ "I07W2eDQwe6DVsm1zHKM8A==",
+ "0p1jMr06OyBoXQuSLYN4aQ==",
+ "odGhKtO4bDW5R8SYiI5yCg==",
+ "5Q/Y2V0iSVTK8HE8JerEig==",
+ "Ily2MKoFI1zr5LxBy93EmQ==",
+ "8dUcSkd2qnX5lD9B+fUe+Q==",
+ "80UE+Ivby3nwplO/HA7cPw==",
+ "sS6QcitMPdvUBLiMXkWQkw==",
+ "5VY++KiWgo7jXSdFJsPN3A==",
+ "aY6B28XdPnuYnbOy9uSP8A==",
+ "ZfRlID+pC1Rr4IY14jolMw==",
+ "/YuQw7oAF08KDptxJEBS9g==",
+ "16d+fhFlgayu3ttKVV/pbg==",
+ "8dBIsHMEAk7aoArLZKDZtg==",
+ "wRqaDZVHHurp5whOQ1kDbQ==",
+ "lFUq6PGk9dBRtUuiEW7Cug==",
+ "FoJZ61VrU8i084pAuoWhDQ==",
+ "4mig4AMLUw+T/ect9p4CfA==",
+ "Po0lhBfiMaXhl+vYh1D8gA==",
+ "z9cd+Qj+ueX34Zf3997MNQ==",
+ "1dsKN1nG6upj7kKTKuJWsQ==",
+ "UtLYUlQJ02oKcjNR3l+ktg==",
+ "O538ibsrI4gkE5tfwjxjmg==",
+ "G736AX070whraDxChqUrqw==",
+ "THs1r8ZEPChSGrrhrNTlsA==",
+ "pVG1hL96/+hQ+58rJJy6/A==",
+ "1BjsijOzgHt/0i36ZGffoQ==",
+ "6rIWazDEWU5WPZHLkqznuQ==",
+ "cdWUm6uLNzR/knuj2x75eA==",
+ "nsnX3tKkN1elr18E31tXDw==",
+ "0fnruVOCxEczscBuv4yL9A==",
+ "SVuEYfQ9FGyVMo1672n0Yg==",
+ "ZRWyfXyXqAaOEjkzWl949Q==",
+ "S2MAIYeDQeJ1pl9vhtYtUg==",
+ "vsRNZx4thFFFPneubKq1Fw==",
+ "kuWGANwzNRpG4XmY7KjjNg==",
+ "i6r+mZfyhZyqlYv56o0H+w==",
+ "wqWqe0KRjZlUIrGgEOG9Mg==",
+ "t5wh9JGSkQO78QoQoEqvXA==",
+ "AGoVLd0QPcXnTedT5T95JQ==",
+ "aRrcmH+Ud3mF1vEXcpEm4w==",
+ "C65PZm8rZxJ6tTEb6d08Eg==",
+ "oAHVGBSJ2cf4dVnb/KEYmw==",
+ "BuDVDLl0OGdomEcr+73XhQ==",
+ "bLsStF0DDebpO+xulqGNtg==",
+ "xukOAM0QVsA72qEy0yku9A==",
+ "LpoayYsTO8WLFLCSh2kf2w==",
+ "LEVYAE54618FrlXkDN01Kw==",
+ "Jm862vBTCYbv/V4T1t46+Q==",
+ "X4kdXUuhcUqMSduqhfLpxA==",
+ "cLR0Ry4/N5swqga1R6QDMw==",
+ "0klouNfZRHFFpdHi4ZR2hA==",
+ "JGx8sTyvr4bLREIhSqpFkw==",
+ "ZiJ/kJ9GneF3TIEm08lfvQ==",
+ "hP7dSa8lLn9KTE/Z0s4GVQ==",
+ "600bwlyhcy754W1E6tuyYg==",
+ "U49SfOBeqQV9wzsNkboi8Q==",
+ "5DDb7fFJQEb3XTc3YyOTjg==",
+ "6uT7LZiWjLnnqnnSEW4e/Q==",
+ "tq5xUJt8GtjDIh1b48SthQ==",
+ "eJFIQh/TR7JriMzYiTw4Sg==",
+ "jdRzkUJrWxrqoyNH9paHfQ==",
+ "RKVDdE1AkILTFndYWi9wFg==",
+ "AEpTVUQhIEJGlXJB6rS26A==",
+ "PD+yHtJxZJ2XEvjIPIJHsQ==",
+ "dOS+mVCy3rFX9FvpkTxGXA==",
+ "lz+SeifYXxamOLs1FsFmSQ==",
+ "QTz21WkhpPjfK8YoBrpo+w==",
+ "9wUIeSgNN36SFxy8v2unVg==",
+ "ash1r2J6B0PUxJe8P0otVQ==",
+ "y7yS9x3yshVhMpDbQtfYOQ==",
+ "f07bdNVAe9x+cAMdF1bByQ==",
+ "N2KovXW14hN/6+iWa1Yv3g==",
+ "2DNbXVgesUa7PgYQ4zX5Lw==",
+ "WQznrwqvMhUlM3CzmbhAOQ==",
+ "FpWDTLTDmkUhH/Sgo+g1Gg==",
+ "OVHqwV8oQMC5KSMzd5VemA==",
+ "Bv4mNIC72KppYw/nHQxfpQ==",
+ "MI+HSMRh8KTW+Afiaxd/Fw==",
+ "10OltdxPXOvfatJuwPVKbQ==",
+ "y4/HohCJxtt+cT7nLJB08w==",
+ "RhcqXY4OsZlVVF7ZlkTeRw==",
+ "/mrqas0eDX+sFUNJvCQY8g==",
+ "ZIZx4MehWTVXPN9cVQBmyA==",
+ "z20AAnvj7WsfJeOu3vemlA==",
+ "dL6n/JsK+Iq6UTbQuo/GOw==",
+ "rMm9bHK69h0fcMkMdGgeeA==",
+ "ftsf2qztw3NC78ep/CZXWQ==",
+ "/n1RLTTVpygre1dl36PDwQ==",
+ "/FsJYFNe+7UvsSkiotNJEQ==",
+ "Yy2pPhITTmkEwoudXizHqQ==",
+ "lizovLQxu6L9sbafNQuShQ==",
+ "XV5MYe0Q7YMtoBD6/iMdSw==",
+ "5jHgQF4SfO/zy9xy9t+9dw==",
+ "16iT/jCcPDrJEfi2bE5F+Q==",
+ "syeBfQBUmkXNWCZ1GV8xSA==",
+ "sr3UXbMg5zzkRduFx/as7g==",
+ "xUXEE7OBBCudsQnuj5ycOA==",
+ "ojZY7Gi2QJXE/fp6Wy31iA==",
+ "RlNPyhgYOIn28R4vKCVtYA==",
+ "KOm8PTa+ICgDrgK9QxCJZw==",
+ "DJoy1NSZZw87oxWGlNHhfg==",
+ "jEdanvXKyZdZJG6mj/3FWw==",
+ "Omr+zPWVucPCSfkgOzLmSQ==",
+ "71w3aSvuh2mBLtdqJCN3wA==",
+ "xjTMO2mvtpvwQrounD4e8g==",
+ "Zz/5VMbw1TqwazReplvsEg==",
+ "hIjgi20+km+Ks23NJ4VQ6Q==",
+ "00TVKawojyqrJkC7YqT41Q==",
+ "YgVpC5d5V6K/BpOD663yQA==",
+ "wX70jKLKJApHnhyK0r6t3A==",
+ "lacCCRiWdquNm4YRO7FoKA==",
+ "cWdlhVZD7NWHUGte24tMjg==",
+ "t5U+VMsTtlWAAWSW+00SfQ==",
+ "AMfL0rH+g8c0VqOUSgNzQw==",
+ "0G93AxGPVwmr66ZOleM90A==",
+ "9tiibT8V9VwnPOErWGNT3w==",
+ "+dBv88reDrjEz6a2xX3Hzw==",
+ "xX6atcCApI08oVLjjLteLg==",
+ "+YrqTEJlJCv0A2RHQ8tr1A==",
+ "aqcOby9QyEbizPsgO3g0yw==",
+ "s/BZAhh1cTV3JCDUQsV8mA==",
+ "x9VwDdFPp/rJ+SF16ooWYg==",
+ "k/OVIllJvW6BefaLEPq7DA==",
+ "rIMXaCaozDvrdpvpWvyZOQ==",
+ "qQQwJ/aF87BbnLu3okXxaw==",
+ "TIWSM78m0RprwgPGK/e0JA==",
+ "r/b5px/UImGNjT/X5sYjuA==",
+ "7K8l6KoP0BH82/WMLntfrg==",
+ "gEHGeR2F82OgBeAlnYhRSw==",
+ "1/SGIab+NnizimUmNDC4wA==",
+ "WADmxH7R6B4LR+W6HqQQ6A==",
+ "pcoBh5ic7baSD4TZWb3BSw==",
+ "es/L9iW8wsyLeC5S4Q8t+g==",
+ "D175i+2bZ7aWa4quSSkQpA==",
+ "WQMffxULFKJ+bun6NrCURA==",
+ "82hTTe1Nr4N2g7zwgGjxkw==",
+ "oyYtf08AkWLR52bXm5+sKw==",
+ "8uP4HUnSodw88yoiWXOIcw==",
+ "x2NpqNnqRihktNzpxmepkQ==",
+ "x5zMDuW66467ofgL3spLUQ==",
+ "OMO4pqzfcbQ11YO4nkTXfg==",
+ "N4/mQFyhDpPzmihjFJJn6w==",
+ "NN/ymVQNa17JOTGr6ki3eQ==",
+ "htDbVu1xGhCRd8qoMlBoMg==",
+ "S47hklz3Ow+n5aY6+qsCoA==",
+ "ji+1YHlRvzevs3q5Uw1gfA==",
+ "3Y4w0nETru3SiSVUMcWXqw==",
+ "XfBOCJwi2dezYzLe316ivw==",
+ "kMUdiwM7WR8KGOucLK4Brw==",
+ "V/xG5QFyx1pihimKmAo8ZA==",
+ "sQskMBELEq86o1SJGQqfzg==",
+ "6+jhreeBLfw64tJ+Nhyipw==",
+ "8iYdEleTXGM+Wc85/7vU9w==",
+ "D7piVoB2NJlBxK5owyo4+g==",
+ "hDGa2yLwNvgBd/v6mxmQaQ==",
+ "WLsh3UF4WXdHwgnbKEwRlQ==",
+ "D5jaV+HtXkSpSxJPmaBDXg==",
+ "jCgdKXsBCgf7giUKnr6paQ==",
+ "XqW7UBTobbV4lt1yfh0LZw==",
+ "EbGG4X18upaiVQmPfwKytg==",
+ "dXDPnL1ggEoBqR13aaW9HA==",
+ "Vik8tGNxO0xfdV0pFmmFDw==",
+ "Swjn3YkWgj0uxbZ1Idtk+A==",
+ "JPxEncA4IkfBDvpjHsQzig==",
+ "F5FcNti7lUa9DyF2iEpBug==",
+ "HJYgUxFZ66fRT8Ka73RaUg==",
+ "Jbxl8Nw1vlHO9rtu0q/Fpg==",
+ "fmC+85h5WBuk8fDEUWPjtQ==",
+ "dZgMquvZmfLqP4EcFaWCiA==",
+ "XF/yncdoT4ruPeXCxEhl9Q==",
+ "QJEbr3+42P9yiAfrekKdRQ==",
+ "Sr9c0ReRpkDYGAiqSy683g==",
+ "Nr4zGo5VUrjXbI8Lr4YVWQ==",
+ "NDZWIhhixq7NT8baJUR4VQ==",
+ "GFRJoPcXlkKSvJRuBOAYHQ==",
+ "WHutPin+uUEqtrA7L8878A==",
+ "2rhjiY0O0Lo36wTHjmlNyw==",
+ "XsF7R12agx/KkRWl0TyXRA==",
+ "R6cO8GzYfOGTIi773jtkXw==",
+ "zrZWcqQsUE3ocWE0fG+SOA==",
+ "uNzpptKjihEfKRo5A1nWmw==",
+ "gICaI06E9scnisonpvqCsA==",
+ "TA9WjiLAFgJubLN4StPwLw==",
+ "sBpytpE38xz0zYeT+0qc2A==",
+ "Ej7W3+67kCIng3yulXGpRQ==",
+ "nR3ACzeVF5YcLX6Gj6AGyQ==",
+ "b0vZfEyuTja2JYMa20Rtbg==",
+ "f1h+Vp+xmdZsZIziHrB2+g==",
+ "WzjvUJ4jZAEK7sBqw+m07A==",
+ "OzMR5D2LriC5yrVd5hchnA==",
+ "cw1gBLtxH/m4H7dSM7yvFg==",
+ "CZbd+UoTz0Qu1kkCS3k8Xg==",
+ "WtT0QAERZSiIt2SFDiAizg==",
+ "QsquNcCZL9wv7oZFqm64vQ==",
+ "FXzaxi3nAXBc8WZfFElQeA==",
+ "Ml3mi1lGS1IspHp3dYYClg==",
+ "XGAXhUFjORwKmAq9gGEcRg==",
+ "wOhbpTzmFla8R0kI9OiHaA==",
+ "qoK2keBg3hdbn7Q24kkVXg==",
+ "ZAQHWU6RMg4IadOxuaukyw==",
+ "RiahBXX2JbPzt8baPiP/8g==",
+ "Qx6rVv9Xj8CBjqikWI9KFA==",
+ "ZRnR6i+5WKMRfs3BDRBCJg==",
+ "91LQuW6bMSxl10J/UDX23A==",
+ "0dIeIM5Zvm5nSVWLy94LWg==",
+ "Ja3ECL7ClwDrWMTdcSQ6Ug==",
+ "f6iLrMpxKhFxIlfRsFAuew==",
+ "iSeH0JFSGK73F470Rhtesw==",
+ "DwOTyyCoUfaSShHZx9u6xg==",
+ "rdeftHE7gwAT67wwhCmkYQ==",
+ "kUhyc3G8Zvx8+q5q5nVEhw==",
+ "W8bATujVUT80v2XGJTKXDg==",
+ "dMRx4Mf6LrN64tiJuyWmDw==",
+ "9cvHJmim9e0pOaoUEtiM6A==",
+ "RHToSGASrwEmvzjX6VPvNQ==",
+ "V7eji28JSg3vTi30BCS7gw==",
+ "4+htiqjEz9oq0YcI/ErBVg==",
+ "jKJn4czwUl/6wtZklcMsSg==",
+ "bvyB6OEwhwCIfJ6KRhjnRw==",
+ "59ipbMH7cKBsF9bNf4PLeQ==",
+ "M/cQja3uIk1im9++brbBOA==",
+ "AChOz8avRYsvxlbWcorQ3w==",
+ "FcKjlHKfQAGoovtpf+DxWQ==",
+ "y+cl1/Knb9MZPz8nBB0M+w==",
+ "b8BZV1NfBdLi70ir4vYvZg==",
+ "aFJuE/s+Kbge4ppn+wulkA==",
+ "CWBGcRFYwZ0va6115vV/oQ==",
+ "glnqaRfwm6NxivtB2nySzw==",
+ "mPk1IsU5DmDFA/Ym5+1ojw==",
+ "LGwcvetzQ3QqKjNh5vA8vw==",
+ "yctId8ltkl3+xqi9bj+RqA==",
+ "spJI3xFUlpCDqzg0XCxopA==",
+ "V8m51xgUgywRoV6BGKUrgg==",
+ "rgcXxjx3pDLotH7TTfAoZw==",
+ "/TSsi/AwKHtP6kQaeReI3w==",
+ "8dbyfox/isKLsnVjQNsEXg==",
+ "MOrAbuJTyGKPC6MgYJlx5Q==",
+ "uNWFZlP7DA96sf+LWiAhtQ==",
+ "hNHqznsrIVRSQdII6crkww==",
+ "GT6WUDXiheKAM7tPg3he9A==",
+ "JC8Q+8yOJ52NvtVeyHo68w==",
+ "HMQarkPWOUDIg5+5ja2dBQ==",
+ "nknBKPgb7US42v8A0fTl/w==",
+ "fDOUzPTU2ndpbH0vgkgrJQ==",
+ "GTNttXfMniNhrbhn92Aykg==",
+ "D2JcY4zWwqaCKebLM8lPiQ==",
+ "/c34NtdUZAHWIwGl3JM8Tw==",
+ "/G26n5Xoviqldr5sg/Jl3w==",
+ "GF0lY77rx1NQzAsZpFtXIQ==",
+ "BMOi5JmFUg5sCkbTTffXHw==",
+ "R+beucURp/H5jLs4kW6wmg==",
+ "xfYZ6qhWNBqqJ0PdWRjOwA==",
+ "Ahpi9+nl13kPTdzL+jgqMw==",
+ "oIU19xAvLJwQSZzIH577aA==",
+ "50xwiYvGQytEDyVgeeOnMg==",
+ "M0ESOGwJ4WZ4Ons1ljP0bQ==",
+ "fS471/rN4K2m10mUwGFuLg==",
+ "RrE3B3X/SJi3CqCUlTYwaw==",
+ "oDca3JEdRb4vONT9GUUsaQ==",
+ "pHo1O5zrCHCiLvopP2xaWw==",
+ "7sCJ4RxbxRqVnF4MBoKfuQ==",
+ "7R5rFaXCxM3moIUtoCfM2g==",
+ "4rrSL6N0wyucuxeRELfAmw==",
+ "9Gkw+hvsR/tFY1cO89topg==",
+ "aw4CzX8pYbPVMuNrGCEcWg==",
+ "KyLQxi5UP+qOiyZl0PoHNQ==",
+ "T1pMWdoNDpIsHF8nKuOn2A==",
+ "Qv6wWP4PpycDGxe7EZNSCw==",
+ "ZJc7GV0Yb6MrXkpDVIuc8g==",
+ "aXrbsro7KLV8s4I4NMi4Eg==",
+ "7k5rBuh8FbTTI4TP87wBPQ==",
+ "NRyFx6jqO/oo9ojvbYzsAg==",
+ "P7eMlOz9YUcJO+pJy0Kpkw==",
+ "jpjpNjL1IKzJdGqWujhxCw==",
+ "9k1u/5TgPmXrsx3/NsYUhg==",
+ "c1wbFbN7AdUERO/xVPJlgw==",
+ "Yw4ztKv6yqxK9U1L0noFXg==",
+ "GnJKlRzmgKN9vWyGfMq3aA==",
+ "91VcAVv7YDzkC1XtluPigw==",
+ "h1NNwMy0RjQmLloSw1hvdg==",
+ "pzC8Y0Vj9MPBy3YXR32z6w==",
+ "UTmTgvl+vGiCDQpLXyVgOg==",
+ "CzWhuxwYbNB/Ffj/uSCtbw==",
+ "VOB+9Bcfu8aHKGdNO0iMRw==",
+ "X2Tawm2Cra6H7WtXi1Z4Qw==",
+ "6cTETZ9iebhWl+4W5CB+YQ==",
+ "X4hrgqMIcApsjA9qOWBoCw==",
+ "1buQEv2YlH/ljTgH0uJEtw==",
+ "FH5Z60RXXUiDk+dSZBxD3g==",
+ "FI2WhaSMb3guFLe3e9il8Q==",
+ "O/EizzJSuFY8MpusBRn7Tg==",
+ "b6rrRA0W247O+FfvDHbVCQ==",
+ "ng1Q0A7ljho3TUWWYl46sw==",
+ "1Ym0lyBJ9aFjhJb/GdUPvQ==",
+ "+OXdvbTxHtSoLg7bZMho4w==",
+ "cuQslgfqD2VOMhAdnApHrA==",
+ "pCQmlnn3BxhsV2GwqjRhXg==",
+ "6PzjncEw2wHZg7SP7SQk9w==",
+ "nqtQI1bSM7DCO9P1jGV97Q==",
+ "O1ckWUwuhD44MswpaD6/rw==",
+ "RUmhye56tQu9xXs4SRJpOQ==",
+ "llujnWE17U8MIHmx4SbrSA==",
+ "UwqBVd4Wfias4ElOjk2BzQ==",
+ "kBAB2PSjXwqoQOXNrv80AA==",
+ "w1zN28mSrI/gqHsgs4ME3A==",
+ "301utVPZ93AnPLYbsiJggw==",
+ "qIFpKKwUmztsBpJgMaVvSg==",
+ "QmcURiMzmVeUNaYPSOtTTg==",
+ "x/MpsQvziUpW40nNUHDS5Q==",
+ "t1O9jSNjg4DTIv/Za4NbtA==",
+ "1B5gxGQSGzVKoNd5Ol4N7g==",
+ "81iQLU+YwxNwq4of6e9z7A==",
+ "x0eIHCvQLd2jdDaXwSWTYQ==",
+ "96ORaz1JRHY1Gk8H74+C2g==",
+ "bNDKcFu8T5Y6OoLSV+o/Sw==",
+ "WrJMOuXSLKKzgmIDALkyNw==",
+ "+gpHnUj2GWocP74t5XWz4w==",
+ "z5DveTu377UW8IHnsiUGZg==",
+ "irnD9K8bsT+up/JUrxPw6A==",
+ "ginkFyNVMwkZLE49AbfqfA==",
+ "2hEzujfG3mR5uQJXbvOPTQ==",
+ "E9yeifEZtpqlD0N3pomnGw==",
+ "OpC/sL320wl5anx6AVEL+A==",
+ "D7wN7b5u5PKkMaLJBP9Ksw==",
+ "83WGpQGWyt6mCV+emaomog==",
+ "X6ulLp4noBgefQTsbuIbYQ==",
+ "BH+rkZWQjTp7au6vtll/CQ==",
+ "Ex3x5HeDPhgO2S9jjCFy4g==",
+ "YNqIHCmBp/EbCgaPKJ7phw==",
+ "312g8iTB9oJgk/OqcgR7Cw==",
+ "LcF0OqPWrcpHby8RwXz1Yg==",
+ "gaEtlJtD6ZjF5Ftx0IFt0A==",
+ "bvbMJZMHScwjJALxEyGIyg==",
+ "StoXC7TBzyRViPzytAlzyQ==",
+ "XqFSbgvgZn0CpaZoZiRauQ==",
+ "AqHVaj3JcR44hnMzUPvVYg==",
+ "jTg9Y6EfpON4CRFOq0QovA==",
+ "q/siBRjx6wNu+OTvpFKDwA==",
+ "goSgZ8N5UbT5NMnW3PjIlQ==",
+ "9onh6QKp70glZk9cX3s34A==",
+ "o5XVEpdP4OXH0NEO4Yfc/A==",
+ "a5gZ5uuRrXEAjgaoh7PXAg==",
+ "PaROi5U16Tk35p0EKX5JpA==",
+ "dtnE401dC0zRWU0S/QOTAg==",
+ "7J3FoFGuTIW36q0PZkgBiw==",
+ "hiYg+aVzdBUDCG0CXz9kCw==",
+ "vhdFtKVH4bVatb4n8KzeXw==",
+ "DWKsPfKDAtfuwgmc2dKUNg==",
+ "M2JMnViESVHTZaru6LDM6w==",
+ "G/PA+kt0N+jXDVKjR/054A==",
+ "6rqK8sjLPJUIp7ohkEwfZg==",
+ "wajwXfWz2J+O+NVaj6j2UQ==",
+ "C4QEzQKGxyRi2rjwioHttA==",
+ "N/HgDydvaXuJvTCBhG/KtA==",
+ "6erpZS36qZRXeZ9RN9L+kw==",
+ "bbBsi6tXMVWyq3SDVTIXUg==",
+ "aySnrShOW4/xRSzl/dtSKQ==",
+ "rxfACPLtKXbYua18l3WlUw==",
+ "L4+C6I7ausPl6JbIbmozAg==",
+ "R3ijnutzvK6IKV3AKHQZSA==",
+ "leDlMcM+B1mDE8k5SWtUeg==",
+ "KGI/cXVz6v6CfL8H6akcUQ==",
+ "NtwqUO3SKZE/9MXLbTJo/g==",
+ "dJHKDkfMFJeoULg7U4wwDQ==",
+ "IEz72W2/W8xBx5aCobUFOQ==",
+ "wUYhs4j3W9nIywu1HIv2JA==",
+ "GzbeM7snhe+M+J7X+gAsQw==",
+ "3/1puZTGSrD9qNKPGaUZww==",
+ "eKQCVzLuzoCLcB4im8147A==",
+ "CCK+6Dr72G3WlNCzV7nmqw==",
+ "CJoZn5wdTXbhrWO5LkiW0g==",
+ "bJ1cZW7KsXmoLw0BcoppJg==",
+ "OlpA9HsF8MBh7b45WZSSlg==",
+ "JZRjdJLgZ+S0ieWVDj8IJg==",
+ "uhT12XY79CtbwhcSfAmAXQ==",
+ "isep9d+Q7DEUf0W7CJJYzw==",
+ "K9A87aMlJC8XB9LuFM913g==",
+ "uqe3rFveJ2JIkcZQ3ZMXHQ==",
+ "0e8hM3E5tnABRyy29A8yFw==",
+ "4iiCq+HhC+hPMldNQMt0NA==",
+ "X4o0OkTz0ec70mzgwRfltA==",
+ "1E3pMgAHOnHx3ALdNoHr8Q==",
+ "xNilc7UOu1kyP0+nK5MrLw==",
+ "DQlZWBgdTCoYB1tJrNS5YQ==",
+ "iruDC5MeywV4yA8o1tw/KQ==",
+ "z+1oDVy8GJ5u/UDF+bIQdA==",
+ "uExgqZkkJnZj252l5dKAGg==",
+ "ZgdpqFrVGiaHkh9o3rDszg==",
+ "5N2oi2pB69NxeNt08yPLhw==",
+ "G37U8XTFyshfCs7qzFxATg==",
+ "0ZEC3hy411LkOhKblvTcqg==",
+ "ITZ3P47ALS0JguFms6/cDA==",
+ "WWN44lbUnEdHmxSfMCZc6w==",
+ "r2f2MyT+ww1g9uEBzdYI1w==",
+ "ZvvxwDd0I6MsYd7aobjLUA==",
+ "uQs79rbD/wEakMUxqMI48A==",
+ "022B0oiRMx8Xb4Af98mTvQ==",
+ "afMd/Hr3rYz/l7a3CfdDjg==",
+ "xmsYnsJq78/f9xuKuQ2pBQ==",
+ "dFetwmFw+D6bPMAZodUMZQ==",
+ "TBQpcKq2huNC5OmI2wzRQw==",
+ "skrQRB9xbOsiSA19YgAdIQ==",
+ "anyANMnNkUqr3JuPJz5Qzw==",
+ "6QUGE2S8oFYx4T4nW56cCw==",
+ "rwtF86ZAbWyKI6kLn4+KBw==",
+ "6txm8z4/LGCH0cpaet/Hsg==",
+ "wdRyYjaM11VmqkkxV/5bsA==",
+ "+k5lDb+QdNc9iZ01hL5yBg==",
+ "k/pBSWE2BvUsvJhA9Zl5uw==",
+ "jQjyjWCEo9nWFjP4O8lehw==",
+ "R6Me6sSGP5xpNI8R0xGOWw==",
+ "9+hjTVMQUsvVKs7Tmp52tg==",
+ "VQIpquUqmeyt/q6OgxzduQ==",
+ "KXvdjZ3rRKn60djPTCENGA==",
+ "5HovoyHtul8lXh+z8ywq9A==",
+ "1+XWdu4qCqLLVjqkKz3nmA==",
+ "LCj4hI520tA685Sscq6uLw==",
+ "b53qqLnrTBthRXmmnuXWvw==",
+ "WTr3q/gDkmB4Zyj7Ly20+w==",
+ "FbxScyuRacAQkdQ034ShTA==",
+ "qaTdVEeZ6S8NMOxfm+wOMA==",
+ "ZNrjP1fLdQpGykFXoLBNPw==",
+ "/Bwpt5fllzDHq2Ul6v86fA==",
+ "/mFp3GFkGNLhx2CiDvJv4A==",
+ "RppDe/WGt1Ed6Vqg1+cCkQ==",
+ "6M6QapJ5xtMXfiD3bMaiLA==",
+ "Ghuj9hAyfehmYgebBktfgA==",
+ "GncGQgmWpI/fZyb/6zaFCg==",
+ "R1TCCfgltnXBvt5AiUnCtQ==",
+ "5NEP7Xt7ynj6xCzWzt21hQ==",
+ "4yEkKp2FYZ09mAhw2IcrrA==",
+ "y2Tn2gmhKs5WKc01ce74rg==",
+ "wnfYUctNK+UPwefX5y4/Rw==",
+ "BV1moliPL15M14xkL+H1zw==",
+ "80C9TB9/XT1gGFfQDJxRoA==",
+ "yL1DwlIIREPuyuCFULi0uw==",
+ "D09afzGpwCEH0EgZUSmIZA==",
+ "eCy/T+a8kXggn1L8SQwgvA==",
+ "+dIEf5FBrHpkjmwUmGS6eg==",
+ "kzXsrxWRnWhkA82LsLRYog==",
+ "Nf9fbRHm844KZ2sqUjNgkA==",
+ "XAq/C+XyR6m3uzzLlMWO5Q==",
+ "jiV+b/1EFMnHG6J0hHpzBg==",
+ "HK0yf7F97bkf1VYCrEFoWA==",
+ "Cz1G77hsDtAjpe0WzEgQog==",
+ "xdCCdP8SNBOK3IsX6PiPQA==",
+ "8snljTGo/uICl9q0Hxy7/A==",
+ "sLdxIKap0ZfC3GpUk3gjog==",
+ "IA1jmtfpYkz/E2wD0+27WA==",
+ "PPa7BDMpRdxJdBxkuWCxKA==",
+ "CuGIxWhRLN7AalafBZLCKQ==",
+ "MWcV03ULc0vSt/pFPYPvFA==",
+ "QVwuN66yPajcjiRnVk/V8g==",
+ "aLY2pCT0WfFO5EJyinLpPg==",
+ "dGrf9SWJ13+eWS6BtmKCNw==",
+ "YtZ8CYfnIpMd2FFA5fJ+1Q==",
+ "Umd+5fTcxa3mzRFDL9Z8Ww==",
+ "Al8+d/dlOA5BXsUc5GL8Tg==",
+ "/KYZdUWrkfxSsIrp46xxow==",
+ "kr8tw1+3NxoPExnAtTmfxg==",
+ "PwvPBc+4L73xK22S9kTrdA==",
+ "VWNDBOtjiiI4uVNntOlu/A==",
+ "lJFPmPWcDzDp5B2S8Ad8AA==",
+ "Mofqu40zMRrlcGRLS42eBw==",
+ "BuENxPg7JNrWXcCxBltOPg==",
+ "nmD7fEU4u7/4+W/pkC4/0Q==",
+ "axEl7xXt/bwlvxKhI7hx4g==",
+ "W04GeDh+Tk/I1S85KlozRA==",
+ "tVw8U1AsslIFmQs4H1xshg==",
+ "TSPFvkgw6uLsJh66Ou0H9w==",
+ "IYIbEaErHoFBn8sTT9ICIQ==",
+ "WBu0gJmmjVdVbjDmQOkU6w==",
+ "ZgjifTVKmxOieco81gnccQ==",
+ "ZrCnZB/U/vcqEtI1cSvnww==",
+ "2D6yhuABiaFFoXz0Lh0C+w==",
+ "SfwnYZCKP1iUJyU1yq4eKg==",
+ "tsiqwelcBAMU/HpLGBtMGw==",
+ "S9L29U2P5K8wNW+sWbiH7w==",
+ "sGLPmr568+SalaQr8SE/PA==",
+ "Hm6MG6BXbAGURVJKWRM6ZA==",
+ "euxzbIq4vfGYoY3s1QmLcw==",
+ "/FchS2nPezycB8Bcqc2dbg==",
+ "ZKvox7BaQg4/p5jIX69Umw==",
+ "HkbdaMuDTPBDnt3wAn5RpQ==",
+ "eddhS+FkXxiUnbPoCd5JJw==",
+ "Muf2Eafcf9G3U2ZvQ9OgtQ==",
+ "a7Pv1SOWYnkhIUC22dhdDA==",
+ "O839JUrR+JS30/nOp428QA==",
+ "2qK2ZEY9LgdKSTaLf6VnLA==",
+ "BTiGLT6XdZIpFBc91IJY6g==",
+ "EqYq2aVOrdX5r7hBqUJP7g==",
+ "SIuKH/Qediq0TyvqUF93HQ==",
+ "c5ymZKqx/td1MiS2ERiz9A==",
+ "rqucO37p86LpzehR/asCSQ==",
+ "1tpM0qgdo7JDFwvT0TD78g==",
+ "Ar1Eb/f/LtuIjXnnVPYQlA==",
+ "V8q+xz4ljszLZMrOMOngug==",
+ "P5WPQc5NOaK7WQiRtFabkw==",
+ "Xo8ZjXOIoXlBjFCGdlPuZw==",
+ "jTmPbq+wh30+yJ/dRXk1cA==",
+ "KSumhnbKxMXQDkZIpDSWmQ==",
+ "Kh/J1NpDBGoyDU+Mrnnxkg==",
+ "3BjLFon1Il0SsjxHE2A1LQ==",
+ "dml2gqLPsKpbIZ93zTXwCQ==",
+ "ZyoaR1cMiKAsElmYZqKjLA==",
+ "vnOJ3e9Zd4wPx8PX7QgZzQ==",
+ "2melaInV0wnhBpiI3da6/A==",
+ "mUek9NkXm8HiVhQ6YXiyzA==",
+ "RZTpYKxOAH9JgF1QFGN+hw==",
+ "a/Y6IAVFv0ykRs9WD+ming==",
+ "yhRi5M9Etuu9HSu4d24i3w==",
+ "+1gcqAqaRZwCj5BGiZp3CA==",
+ "o1zeXHJEKevURAAbUE/Vog==",
+ "cvOg7N4DmTM+ok1NBLyBiQ==",
+ "uPdjKJIGzN7pbGZDZdCGaA==",
+ "REnDNe9mGfqVGZt+GdsmjQ==",
+ "XqTK/2QuGWj50tGmiDxysA==",
+ "bL2FuwsPT7a7oserJQnPcw==",
+ "uO+uK1DntCxVRr1KttfUIw==",
+ "Xconi1dtldH90Wou9swggw==",
+ "HRF3WL/ue3/QlYyu7NUTrA==",
+ "5LuFDNKzMd2BzpWEIYO2Ww==",
+ "dNTU+/2DdZyGGTdc+3KMhQ==",
+ "H+NHjk/GJDh/GaNzMQSzjg==",
+ "/Ph/6l/lFNVqxAje1+PgFA==",
+ "4WRdAjiUmOQg2MahsunjAg==",
+ "j+lDhAnWAyso+1N8cm85hQ==",
+ "nFBXCPeiwxK9mLXPScXzTA==",
+ "vGKknndb4j6VTV8DxeT4fQ==",
+ "fdqt93OrpG13KAJ5cASvkg==",
+ "1MIn73MLroxXirrb+vyg2Q==",
+ "Q7teXmTHAC5qBy+t7ugf0w==",
+ "bWwtTFlhO3xEh/pdw0uWaQ==",
+ "Omi2ZB9kdR1HrVP2nueQkA==",
+ "+ZozWaPWw8ws1cE5DJACeg==",
+ "3FH4D31nKV13sC9RpRZFIg==",
+ "4kXlJNuT79XXf1HuuFOlHw==",
+ "36XDmX6j542q+Oei1/x0gw==",
+ "MqqDg9Iyt4k3vYVW5F+LDw==",
+ "cvrGmub2LoJ+FaM5HTPt9A==",
+ "uC2lzm7HaMAoczJO6Z/IhQ==",
+ "MnStiFQAr3QlaRZ02SYGaQ==",
+ "ZuayB6IpbeITokKGVi9R5w==",
+ "FtxpWdhEmC6MT61qQv4DGA==",
+ "KujFdhhgB9q4oJfjYMSsLg==",
+ "ZV8mEgJweIYk0/l0BFKetA==",
+ "gDLjxT7vm07arF4SRX5/Vg==",
+ "/MEOgAhwb7F0nBnV4tIRZA==",
+ "k2KP9oPMnHmFlZO6u6tgyw==",
+ "fbTm027Ms0/tEzbGnKZMDA==",
+ "HOi+vsGAae4vhr+lJ5ATnQ==",
+ "9Bet5waJF5/ZvsYaHUVEjQ==",
+ "Wd0dOs7eIMqW5wnILTQBtg==",
+ "z/e5M2lE9qh3bzB97jZCKA==",
+ "b16O4LF7sVqB7aLU2f3F1A==",
+ "lsBTMnse2BgPS6wvPbe7JA==",
+ "0nOg18ZJ/NicqVUz5Jr0Hg==",
+ "MFeXfNZy6Q9wBfZmPQy3xg==",
+ "ksOFI9C7IrDNk4OP6SpPgw==",
+ "NquRbPn8fFQhBrUCQeRRoQ==",
+ "ccmy4GVuX967KaQyycmO0w==",
+ "DY0IolKTYlW+jbKLPAlYjQ==",
+ "aJFbBhYtMbTyMFBFIz/dTA==",
+ "9pdeedz1UZUlv8jPfPeZ1g==",
+ "qZ2q5j2gH3O56xqxkNhlIA==",
+ "N7fHwb397tuQHtBz1P80ZQ==",
+ "uOkMpYy/7DYYoethJdixfQ==",
+ "E9ajQQMe02gyUiW3YLjO/A==",
+ "dFSavcNwGd8OaLUdWq3sng==",
+ "TAD0Lk95CD86vbwrcRogaQ==",
+ "jLI3XpVfjJ6IzrwOc4g9Pw==",
+ "CzP13PM/mNpJcJg8JD3s6w==",
+ "GSWncBq4nwomZCBoxCULww==",
+ "9k17UqdR1HzlF7OBAjpREA==",
+ "TrWS+reCJ0vbrDNT5HDR9w==",
+ "CXMKIdGvm60bgfsNc+Imvg==",
+ "6NP81geiL14BeQW6TpLnUA==",
+ "hW9DJA1YCxHmVUAF7rhSmQ==",
+ "8M0kSvjn5KN8bjsMdUqKZQ==",
+ "eS/vTdSlMUnpmnl1PbHjyw==",
+ "h2B0ty0GobQhDnFqmKOpKQ==",
+ "n7KL1Kv027TSxBVwzt9qeA==",
+ "yYmnM/WOgi+48Rw7foGyXA==",
+ "FhthAO5IkMyW4dFwpFS7RA==",
+ "81ZH3SO0NrOO+xoR/Ngw1g==",
+ "t7HaNlXL16fVwjgSXmeOAQ==",
+ "N+K1ibXAOyMWdfYctNDSZQ==",
+ "yQCLV9IoPyXEOaj3IdFMWw==",
+ "3+zsjCi7TnJhti//YXK35w==",
+ "600mjiWke4u0CDaSQKLOOg==",
+ "K4VS+DDkTdBblG93l2eNkA==",
+ "5KOgetfZR+O2wHQSKt41BQ==",
+ "kj5WqpRCjWAfjM7ULMcuPQ==",
+ "AxEjImKz4tMFieSo7m60Sg==",
+ "jp5Em/0Ml4Txr1ptTUQjpg==",
+ "jQVlDU+HjZ2OHSDBidxX5A==",
+ "4NHQwbb3zWq2klqbT/pG6g==",
+ "PeJS+mXnAA6jQ0WxybRQ8w==",
+ "l6Ssc04/CnsqUua9ELu2iQ==",
+ "nFPDZGZowr3XXLmDVpo7hg==",
+ "yYBIS9PZbKo7Gram7IXWPA==",
+ "/HU2+fBqfWTEuqINc0UZSA==",
+ "adT+OjEB2kqpeYi4kQ6FPg==",
+ "GW1Uaq622QamiiF24QUA0g==",
+ "rTwJggSxTbwIYdp07ly0LA==",
+ "4yrFNgqWq17zVCyffULocA==",
+ "vvh9vAIrXjIwLVkuJb5oDQ==",
+ "C7UaoIEXsVRxjeA0u99Qmw==",
+ "x1A74vg/hwwjAx6GrkU8zw==",
+ "7XRiYvytcwscemlxd9iXIQ==",
+ "64AA4jLHXc1Dp15aMaGVcA==",
+ "u/QxrP1NOM/bOJlJlsi/jQ==",
+ "5M3dFrAOemzQ0MAbA8bI5w==",
+ "wyqmQGB6vgRVrYtmB2vB7w==",
+ "8vLA9MOdmLTo3Qg+/2GzLA==",
+ "/u5W2Gab4GgCMIc4KTp2mg==",
+ "lhAOM81Ej6YZYBu45pQYgg==",
+ "MArbGuIAGnw4+fw6mZIxaw==",
+ "ZZImGypBWwYOAW43xDRWCQ==",
+ "L2IeUnATZHqOPcrnW2APbA==",
+ "bQKkL+/KUCsAXlwwIH0N3w==",
+ "f09F7+1LRolRL5nZTcfKGA==",
+ "hPnPQOhz4QKhZi02KD6C+A==",
+ "78b8sDBp28zUlYPV5UTnYw==",
+ "iVDd2Zk7vwmEh97LkOONpQ==",
+ "LHQETSI5zsejvDaPpsO29g==",
+ "Yjm5tSq1ejZn3aWqqysNvA==",
+ "gkrg0NR0iCaL7edq0vtewA==",
+ "Lo1xTCEWSxVuIGEbBEkVxA==",
+ "8GyPup4QAiolFJ9v80/Nkw==",
+ "3L3KEBHhgDwH615w4OvgZA==",
+ "hJSP7CostefBkJrwVEjKHA==",
+ "9oQ/SVNJ4Ye9lq8AaguGAQ==",
+ "n7Bns42aTungqxKkRfQ5OQ==",
+ "K5lhaAIZkGeP5rH2ebSJFw==",
+ "ZaPsR9X77SNt7dLjMJUh8A==",
+ "18ndtDM9UaNfBR1cr3SHdA==",
+ "0QbH4oI8IjZ9BRcqRyvvDQ==",
+ "J/eAtAPswMELIj8K2ai+Xg==",
+ "qenHZKKlTUiEFv6goKM/Mw==",
+ "vjrSYGUpeKOtJ2cNgLFg2g==",
+ "DA+3fjr7mgpwf6BZcExj0w==",
+ "rh7bzsTQ1UZjG7amysr0Gg==",
+ "tFMJRXfWE9g78O1uBUxeqQ==",
+ "e/nWuo5YalCAFKsoJmFyFA==",
+ "gqehq46BhFX2YLknuMv02w==",
+ "Uudn69Kcv2CGz2FbfJSSEA==",
+ "Otz/PgYOEZ1CQDW54FWJIQ==",
+ "IwfeA6d0cT4nDTCCRhK+pA==",
+ "jgNijyoj2JrQNSlUv4gk4A==",
+ "KzWdWPP2gH0DoMYV4ndJRg==",
+ "pv/m2mA/RJiEQu2Qyfv9RA==",
+ "ATmMzriwGLl+M3ppkfcZNA==",
+ "tVvWdA+JqH0HR2OlNVRoag==",
+ "n6QVaozMGniCO0PCwGQZ6w==",
+ "gU3gu8Y5CYVPqHrZmLYHbQ==",
+ "cBBOQn7ZjxDku0CUrxq2ng==",
+ "w+jzM0I5DRzoUiLS/9QIMQ==",
+ "MLlVniZ08FHAS5xe+ZKRaA==",
+ "wMyJLQJdmrC2TSeFkIuSvQ==",
+ "dG98w8MynOoX7aWmkvt+jg==",
+ "zm+z+OOyHhljV2TjA3U9zw==",
+ "Tk5MAqd1gyHpkYi8ErlbWg==",
+ "g6zSo8BvLuKqdmBFM1ejLA==",
+ "d0VAZLbLcDUgLgIfT1GmVQ==",
+ "SNPYH4r/J9vpciGN2ybP5Q==",
+ "XA2hUgq3GVPpxtRYiqnclg==",
+ "fVCRaPsTCKEVLkoF4y3zEw==",
+ "FpgdsQ2OG+bVEy3AeuLXFQ==",
+ "JquDByOmaQEpFb47ZJ4+JA==",
+ "e369ZIQjxMZJtopA//G55Q==",
+ "Nsd+DfRX6L54xs+iWeMjCQ==",
+ "+/UCpAhZhz368iGioEO8aQ==",
+ "e5l9ZiNWXglpw6nVCtO8JQ==",
+ "Cl1u5nGyXaoGyDmNdt38Bw==",
+ "6sNP0rzCCm3w976I2q2s/w==",
+ "qcpeZWUlPllQYZU6mHVwUw==",
+ "kzYddqiMsY3EYrpxve2/CQ==",
+ "3iC21ByW/YVL+pSyppanWw==",
+ "3HPOzIZxoaQAmWRy9OkoSg==",
+ "xsCZVhCk2qJmOqvUjK3Y8Q==",
+ "i2sSvrTh/RdLJX0uKhbrew==",
+ "7Y87wVJok20UfuwkGbXxLg==",
+ "ibsb1ncaLZXAYgGkMO7tjQ==",
+ "+VfRcTBQ80KSeJRdg0cDfw==",
+ "kgKWQJJQKLUuD2VYKIKvxA==",
+ "ARKIvf4+zRF8eCvUITWPng==",
+ "1fztTtQWNMIMSAc5Hr6jMQ==",
+ "md6zNd7ZBn3qArYqQz7/fw==",
+ "kvAaIJb+aRAfKK104dxFAA==",
+ "UIXytIHyVODxlrg+eQoARA==",
+ "Dk0L/lQizPEb3Qud6VHb1Q==",
+ "64YsV2qeDxk2Q6WK/h7OqA==",
+ "90dtIMq0ozJXezT2r79vMQ==",
+ "wy/Z8505o4sVovk4UuBp1A==",
+ "ytDXLDBqWiU1w3sTurYmaw==",
+ "9pk75mBzhmcdT+koHvgDlw==",
+ "DQeib845UqBMEl96sqsaSg==",
+ "UPYR575ASaBSZIR3aX1IgQ==",
+ "swsVVsPi/5aPFBGP+jmPIw==",
+ "1cj1Fpd3+UiBAOahEhsluA==",
+ "ifuJCv9ZA84Vz1FYAPsyEA==",
+ "uu+ncs63SdQIvG6z4r7Q3Q==",
+ "UvC1WADanMrhT+gPp/yVqA==",
+ "llOvGOUDVfX68jKnAlvVRA==",
+ "SusSOsWNoAerAIMBVWHtfA==",
+ "VznvTPAAwAev+yhl9oZT0w==",
+ "luR/kvHLwA6tSdLeTM4TzA==",
+ "PcdBtV8pfKU0YbDpsjPgwg==",
+ "5l6kDfjtZjkTZPJvNNOVFw==",
+ "4FBBtWPvqJ3dv4w25tRHiQ==",
+ "JJbzQ/trOeqQomsKXKwUpQ==",
+ "0bj069wXgEJbw7dpiPr8Tg==",
+ "tejpAZp7y32SO2+o4OGvwQ==",
+ "kq26VyDyJTH/eM6QvS2cMw==",
+ "+zBkeHF4P8vLzk1iO1Zn3Q==",
+ "BzkNYH03gF/mQY71RwO3VA==",
+ "RnxOYPSQdHS6fw4KkDJtrA==",
+ "65KhGKUBFQubRRIEdh9SwQ==",
+ "k1DPiH6NkOFXP/r3N12GyA==",
+ "DqzWt1gfyu/e7RQl5zWnuQ==",
+ "gnez1VrH+UHT8C/SB9qGdA==",
+ "vZtL0yWpSIA+9v8i23bZSg==",
+ "FNvQqYoe0s/SogpAB7Hr1Q==",
+ "6nwR+e9Qw0qp8qIwH9S/Mg==",
+ "BPT4PQxeQcsZsUQl33VGmg==",
+ "rOYeIcB+Rg5V6JG2k4zS2w==",
+ "Je1UESovkBa9T6wS0hevLw==",
+ "HFHMGgfOeO0UPrray1G+Zw==",
+ "NBmB/cQfS+ipERd7j9+oVg==",
+ "iIm8c9uDotr87Aij+4vnMw==",
+ "S3VQa6DH+BdlSrxT/g6B5g==",
+ "BwRA+tMtwEvth28IwpZx+w==",
+ "vg3jozLXEmAnmJwdfcEN0g==",
+ "gW0oKhtQQ7BxozxUWw5XvQ==",
+ "Q6vGRQiNwoyz7bDETGvi5g==",
+ "Ak3rlzEOds6ykivfg39xmw==",
+ "G4qzBI1sFP2faN+tlRL/Bw==",
+ "ND9l4JWcncRaSLATsq0LVw==",
+ "yQmNZnp/JZywbBiZs3gecA==",
+ "ZoNSxARrRiKZF5Wvpg7bew==",
+ "GhpJfRSWZigLg/azTssyVA==",
+ "QyyiJ5I/OZC50o89fa5EmQ==",
+ "4kj0S8XlmhHXoUP7dQItUw==",
+ "Dt8Q5ORzTmpPR2Wdk0k+Aw==",
+ "/hFhjFGJx2wRfz6hyrIpvA==",
+ "eFimq+LuHi42byKnBeqnZQ==",
+ "JrKGKAKdjfAaYeQH8Y2ZRQ==",
+ "JFFeXsFsMA59iNtZey7LAA==",
+ "91SdBFJEZ65M+ixGaprY/A==",
+ "+S+WXgVDSU1oGmCzGwuT3g==",
+ "1X14kHeKwGmLeYqpe60XEA==",
+ "4xojeUxTFmMLGm6jiMYh/Q==",
+ "+1e7jvUo8f2/2l0TFrQqfA==",
+ "8WU1vLKV1GhrL7oS9PpABg==",
+ "DYWCPUq/hpjr6puBE7KBHg==",
+ "birqO8GOwGEI97zYaHyAuw==",
+ "6e8boFcyc8iF0/tHVje4eQ==",
+ "FLvED9nB9FEl9LqPn7OOrA==",
+ "ji306HRiq965zb8EZD2uig==",
+ "AklOdt9/2//3ylUhWebHRw==",
+ "VGRCSrgGTkBNb8sve0fYnQ==",
+ "oqlkgrYe9aCOwHXddxuyag==",
+ "KXuFON8tMBizNkCC48ICLA==",
+ "9aKH1u5+4lgYhhLztQ4KWA==",
+ "3hVslsq98QCDIiO40JNOuA==",
+ "OOS6wQCJsXH8CsWEidB35A==",
+ "YXHQ3JI9+oca8pc/jMH6mA==",
+ "V9vkAanK+Pkc4FGAokJsTA==",
+ "OFLn4wun6lq484I7f6yEwg==",
+ "3WVBP9fyAiBPZAq3DpMwOQ==",
+ "5gGoDPTc/sOIDLngmlEq4A==",
+ "E2lvMXqHdTw0x+KCKVnblg==",
+ "f1Gs++Iilgq9GHukcnBG3w==",
+ "uIkVijg7RPi/1j7c18G1qA==",
+ "9T7gB0ZkdWB0VpbKIXiujQ==",
+ "KCJJfgLe00+tjSfP6EBcUg==",
+ "WbAdlac/PhYUq7J2+n5f+w==",
+ "GLnS9wDCje7TOMvBX9jJVA==",
+ "VAg/aU5nl72O+cdNuPRO4g==",
+ "kzTl7WH/JXsX1fqgnuTOgw==",
+ "1HDgfU7xU7LWO/BXsODZAQ==",
+ "D0W5F7gKMljoG5rlue1jrg==",
+ "9reBKZ1Rp6xcdH1pFQacjw==",
+ "SSKhl2L3Mvy93DcZulADtA==",
+ "hlu7os0KtAkpBTBV6D2jyQ==",
+ "sfte/o9vVNyida/yLvqADA==",
+ "gYGQBLo5TdMyXks0LsZhsQ==",
+ "dNq2InSVDGnYXjkxPNPRxA==",
+ "fiv0DJivQeqUkrzDNlluRw==",
+ "msstzxq++XO0AqNTmA7Bmg==",
+ "DCjgaGV5hgSVtFY5tcwkuA==",
+ "aMmrAzoRWLOMPHhBuxczKg==",
+ "qNOSm15bdkIDSc/iUr+UTQ==",
+ "2nSTEYzLK77h5Rgyti+ULQ==",
+ "BhKO1s1O693Fjy1LItR/Jw==",
+ "kRnBEH6ILR5GNSmjHYOclw==",
+ "R97chlspND/sE9/HMScXjQ==",
+ "1Oykse0jQVbuR3MvW5ot4A==",
+ "Dmyb+a7/QFsU4d2cVQsxDw==",
+ "W5now3RWSzzMDAxsHSl++Q==",
+ "IrDuBrVu1HWm0BthAHyOLQ==",
+ "V6zyoX6MERIybGhhULnZiw==",
+ "ZQSDYgpsimK+lYGdXBWE/w==",
+ "lV70RNlE++04G1KFB3BMXA==",
+ "QmSBVvdk0tqH9RAicXq2zA==",
+ "qNyy6Fc0b8oOMWqqaliZ/w==",
+ "xvipmmwKdYt4eoKvvRnjEg==",
+ "Q7Df6zGwvb4rC+EtIKfaSw==",
+ "n1M2dgFPpmaICP+JwxHUug==",
+ "1k8tL2xmGFVYMgKUcmDcEw==",
+ "fFvXa1dbMoOOoWZdHxPGjw==",
+ "UP9mmAKzeQqGhod7NCqzhg==",
+ "PMCWKgog/G+GFZcIruSONw==",
+ "dnvatwSEcl73ROwcZ4bbIQ==",
+ "hY82j+sUQQRpCi6CCGea5A==",
+ "QoUC9nyK1BAzoUVnBLV2zw==",
+ "+aF4ilbjQbLpAuFXQEYMWQ==",
+ "XTCcsVfEvqxnjc0K5PLcyw==",
+ "ML7ipnY/g8mA1PUIju1j8Q==",
+ "tOkYq1BZY152/7IJ6ZYKUg==",
+ "2bsIpvnGcFhTCSrK9EW1FQ==",
+ "Af9j1naGtnZf0u1LyYmK1w==",
+ "ZmblZauRqO5tGysY3/0kDw==",
+ "PF0lpolQQXlpc3qTLMBk8w==",
+ "emVLJVzha7ui5OFHPJzeRQ==",
+ "gR0sgItXIH8hE4FVs9Q07w==",
+ "PTW+fhZq/ErxHqpM0DZwHQ==",
+ "g0kHTNRI7x/lAsr92EEppw==",
+ "24H9q+E8pgCEdFS7JO5kzQ==",
+ "HtDXgMuF8PJ1haWk88S0Ew==",
+ "pulldyBt2sw6QDvTrCh6zw==",
+ "ehwc2vvwNUAI7MxU4MWQZw==",
+ "enj9VEzLbmeOyYugTmdGfQ==",
+ "auvG6kWMnhCMi7c7e9eHrw==",
+ "R36O31Pj8jn0AWSuqI7X2Q==",
+ "3AVYtcIv7A5mVbVnQMaCeA==",
+ "T9WoUJNwp8h4Yydixbx6nA==",
+ "t0WN8TwMLgi8UVEImoFXKg==",
+ "mS99D+CXhwyfVt8xJ+dJZA==",
+ "AFdelaqvxRj6T3YdLgCFyg==",
+ "Lu02ic/E94s42A14m7NGCA==",
+ "7w3b73nN/fIBvuLuGZDCYQ==",
+ "O209ftgvu0vSr0UZywRFXA==",
+ "MQvAr+OOfnYnr/Il/2Ubkg==",
+ "e5txnNRcGs2a9+mBFcF1Qg==",
+ "YA0kMTJ82PYuLA4pkn4rfw==",
+ "QIKjir/ppRyS63BwUcHWmw==",
+ "P3y5MoXrkRTSLhCdLlnc4A==",
+ "WY7mCUGvpXrC8gkBB46euw==",
+ "g0GbRp2hFVIdc7ct7Ky7ag==",
+ "Cv079ZF55RnbsDT27MOQIA==",
+ "cvMJ714elj/HUh89a9lzOQ==",
+ "9inw7xzbqAnZDKOl/MfCqA==",
+ "F58ktE4O0f7C9HdsXYm+lw==",
+ "CsPkyTZADMnKcgSuNu1qxg==",
+ "mAzsVkijuqihhmhNTTz65g==",
+ "FxnbKnuDct4OWcnFMT/a5w==",
+ "P5wS+xB8srW4a5KDp/JVkA==",
+ "ctJYJegZhG42i+vnPFWAWw==",
+ "OrqJKjRndcZ8OjE3cSQv7g==",
+ "aXqiibI6BpW3qilV6izHaQ==",
+ "BA18GEAOOyVXO2yZt2U35w==",
+ "saEpnDGBSZWqeXSJm34eOA==",
+ "CUEueo8QXRxkfVdfNIk/gg==",
+ "H0UMAUfHFQH92A2AXRCBKA==",
+ "CT9g8mKsIN/VeHLSTFJcNQ==",
+ "E4NtzxQruLcetC23zKVIng==",
+ "203EqmJI9Q4tWxTJaBdSzA==",
+ "Do3aqbRKtmlQI2fXtSZfxQ==",
+ "JaYQXntiyznQzrTlEeZMIw==",
+ "VK95g27ws2C6J2h/7rC2qA==",
+ "CQ0PPwgdG3N6Ohfwx1C8xA==",
+ "/MeHciFhvFzQsCIw39xIZA==",
+ "u5cUPxM6/spLIV8VidPrAA==",
+ "OwArFF1hpdBupCkanpwT+Q==",
+ "PdBgXFq5mBqNxgCiqaRnkw==",
+ "lC5EumoIcctvxYqwELqIqw==",
+ "xoPSM86Se+1hHX0y3hhdkw==",
+ "F5bs0GGWBx9eBwcJJpXbqg==",
+ "1mw6LfTiirFyfjejf8QNGA==",
+ "daBhAvmE9shDgmciDAC5eg==",
+ "AvdeYb9XNOUFWiiz+XGfng==",
+ "JJJkp1TpuDx5wrua2Wml7g==",
+ "3y5Xk65ShGvWFbQxcZaQAQ==",
+ "l6QHU5JsJExNoOnqxBPVbw==",
+ "X2YfnPXgF2VHVX95ZcBaxQ==",
+ "g6udffWh7qUnSIo1Ldn3eA==",
+ "V2P75JFB4Se9h7TCUMfeNA==",
+ "IUZ5aGpkJ9rLgSg6oAmMlw==",
+ "pyrUqiZ98gVXxlXQNXv5fA==",
+ "83ERX2XJV3ST4XwvN7YWCg==",
+ "eJDUejE/Ez/7kV+S74PDYg==",
+ "M9oqlPb63e0kZE0zWOm+JQ==",
+ "0rTYcuVYdilO7zEfKrxY3A==",
+ "rfPTskbnoh3hRJH6ZAzQRg==",
+ "QtD35QhE8sAccPrDnhtQmQ==",
+ "jpNUgFnanr9Sxvj2xbBXZw==",
+ "nykEOLL/o7h0cs0yvdeT2g==",
+ "wX2URK6eDDHeEOF3cgPgHA==",
+ "jqPQ0aOuvOJte/ghI1RVng==",
+ "nHTsDl0xeQPC5zNRnoa0Rw==",
+ "mNv2Q67zePjk/jbQuvkAFA==",
+ "HjlPM2FQWdILUXHalIhQ5w==",
+ "cHkOsVd80Rgwepeweq4S1g==",
+ "kTCHqcb3Cos51o8cL+MXcg==",
+ "nvmBgp0YlUrdZ05INsEE8Q==",
+ "kFrRjz7Cf2KvLtz9X6oD+w==",
+ "Tmx0suRHzlUK4FdBivwOwA==",
+ "bG+P+p34t/IJ1ubRiWg6IA==",
+ "uESeJe/nYrHCq4RQbrNpGA==",
+ "ehfPlu6YctzzpQmFiQDxGA==",
+ "ZH5Es/4lJ+D5KEkF1BVSGg==",
+ "HHxn4iIQ7m0tF1rSd+BZBg==",
+ "DQJRsUwO1fOuGlkgJavcwQ==",
+ "HITIVoFoWNg04NExe13dNA==",
+ "MeKXnEfxeuQu9t3r/qWvcw==",
+ "Y7OofF9eUvp7qlpgdrzvkg==",
+ "XSb71ae0v+yDxNF5HJXGbQ==",
+ "p8W1LgFuW6JSOKjHkx3+aA==",
+ "y2JOIoIiT9cV1VxplZPraQ==",
+ "MN94B0r5CNAF9sl3Kccdbw==",
+ "Q1pdQadt12anX1QRmU2Y/A==",
+ "JIC8R48jGVqro6wmG2KXIw==",
+ "eWgLAqJOU+fdn8raHb9HCw==",
+ "5CMadLqS2KWwwMCpzlDmLw==",
+ "H1y2iXVaQYwP0SakN6sa+Q==",
+ "CUCjG2UaEBmiYWQc6+AS1Q==",
+ "yV3IbbTWAbHMhMGVvgb/ZQ==",
+ "80PCwYh4llIKAplcDvMj4g==",
+ "fgdUFvQPb5h+Rqz8pzLsmw==",
+ "2SI4F7Vvde2yjzMLAwxOog==",
+ "kJdY3XEdJS/hyHdR+IN0GA==",
+ "IKgNa2oPaFVGYnOsL+GC5Q==",
+ "eXFOya6x5inTdGwJx/xtUQ==",
+ "uTA0XbiH3fTeVV7u5z0b3w==",
+ "onFcHOO1c3pDdfCb5N4WkQ==",
+ "Slu3z535ijcs5kzDnR7kfA==",
+ "SElc2+YVi3afE1eG1MI7dQ==",
+ "ND2hYtAIQGMxBF7o7+u7nQ==",
+ "Pv9FWQEDLKnG/9K9EIz4Gw==",
+ "6CjtF1S2Y6RCbhl7hMsD+g==",
+ "rs2QrN4qzAHCHhkcrAvIfA==",
+ "eTMPXa60OTGjSPmvR4IgGw==",
+ "pvXHwJ3dwf9GDzfDD9JI3g==",
+ "CRmAj3JcasAb4iZ9ZbNIbw==",
+ "rcY4Ot40678ByCfqvGOGdg==",
+ "l4ddTxbTCW5UmZW+KRmx6A==",
+ "NKRzJndo2uXNiNppVnqy1g==",
+ "0NrvBuyjcJ2q6yaHpz/FOA==",
+ "3YXp1PmMldUjBz3hC6ItbA==",
+ "CmVD6nh8b/04/6JV9SovlA==",
+ "HjyxyL0db2hGDq2ZjwOOhg==",
+ "4PBaoeEwUj79njftnYYqLg==",
+ "vFFzkWgGyw6OPADONtEojQ==",
+ "czBWiYsQtNFrksWwoQxlOw==",
+ "9iB7+VwXRbi6HLkWyh9/kg==",
+ "zwY6tCjjya/bgrYaCncaag==",
+ "mW6TCje9Zg2Ep7nzmDjSYQ==",
+ "5LJqHFRyIwQKA4HbtqAYQQ==",
+ "INNBBin5ePwTyhPIyndHHg==",
+ "dChBe9QR29ObPFu/9PusLg==",
+ "1dhq3ozNCx0o4dV1syLVDA==",
+ "nyaekSYTKzfSeSfPrB114Q==",
+ "TfNHjSTV8w6Pg6+FaGlxvA==",
+ "m/Lp4U75AQyk9c8cX14HJg==",
+ "uU1TX5DoDg6EcFKgFcn0GA==",
+ "B+TsxQZf0IiQrU8X9S4dsQ==",
+ "6b7ue29cBDsvmj1VSa5njw==",
+ "RvXWAFwM+mUAPW1MjPBaHA==",
+ "pdaY6kZ8+QqkMOInvvACNA==",
+ "7nr3zyWL+HHtJhRrCPhYZA==",
+ "BXGlq54wIH6R3OdYfSSDRw==",
+ "b06KGv5zDYsTxyTbQ9/eyA==",
+ "8ylI1AS3QJpAi3I/NLMYdg==",
+ "0fpe9E6m3eLp/5j5rLrz2Q==",
+ "Qrh7OEHjp80IW+YzQwzlJg==",
+ "lqhgbgEqROAdfzEnJ17eXA==",
+ "Dulw855DfgIwiK7hr3X8vg==",
+ "wsp+vmW8sEqXYVURd/gjHA==",
+ "VoPth5hDHhkQcrQTxHXbuw==",
+ "TgWe70YalDPyyUz6n88ujg==",
+ "9lLhHcrPWI4EsA4fHIIXuw==",
+ "UymZUnEEQWVnLDdRemv+Tw==",
+ "qnkFUlJ8QT322JuCI3LQgg==",
+ "/p/aCTIhi1bU0/liuO/a2Q==",
+ "hWoxz5HhE50oYBNRoPp1JQ==",
+ "88tB/HgUIUnqWXEX++b5Aw==",
+ "Z8T1b9RsUWf59D06MUrXCQ==",
+ "BZTzHJGhzhs3mCXHDqMjnQ==",
+ "XfY+QUriCAA1+3QAsswdgg==",
+ "TZ3ATPOFjNqFGSKY3vP2Hw==",
+ "cl4t9FXabQg7tbh1g7a0OA==",
+ "9SgfpAY0UhNC6sYGus9GgQ==",
+ "d/Wd3Ma1xYyoMByPQnA9Cw==",
+ "DDitrRSvovaiXe2nfAtp4g==",
+ "s+eHg5K9zZ2Jozu5Oya9ZQ==",
+ "z3L2BNjQOMOfTVBUxcpnRA==",
+ "v4xIYrfPGILEbD/LwVDDzA==",
+ "HoaBBw2aPCyhh0f5GxF+/Q==",
+ "i9IRqAqKjBTppsxtPB7rdw==",
+ "cWUg7AfqhiiEmBIu+ryImA==",
+ "E+02smwQGBIxv42LIF2Y4Q==",
+ "W4CfeVp9mXgk04flryL7iA==",
+ "9SUOfKtfKmkGICJnvbIDMg==",
+ "xweGAZf+Yb3TtwR/sGmGIA==",
+ "EJgedRYsZPc4cT9rlwaZhg==",
+ "wv4NC9CIpwuGf/nOQYe/oA==",
+ "ZXeMG5eqQpZO/SGKC4WQkA==",
+ "bzXXzQGZs8ustv0K4leklA==",
+ "RkQK9S1ezo+dFYHQP57qrw==",
+ "mrinv7KooPQPrLCNTRWCFg==",
+ "qIUJPanWmGzTD1XxvHp+6w==",
+ "Js7g8Dr6XsnGURA4UNF0Ug==",
+ "dpSTNOCPFHN5yGoMpl1EUA==",
+ "ugY8rTtJkN4CXWMVcRZiZw==",
+ "rqHKB91H3qVuQAm+Ym5cUA==",
+ "UjmDFO7uzjl4RZDPeMeNyg==",
+ "cu4ZluwohhfIYLkWp72pqA==",
+ "ZydKlOpn2ySBW0G3uAqwuw==",
+ "LWd0+N3M94n81qd346LfJQ==",
+ "VbHoWmtiiPdABvkbt+3XKQ==",
+ "J4MC9He6oqjOWsYQh9nl3Q==",
+ "ahAbmGJZvUOXrcK6OydNGQ==",
+ "Byhi4ymFqqH8uIeoMRvPug==",
+ "LSN9GmT6LUHlCAMFqpuPIA==",
+ "IAMInfSYb76GxDlAr1dsTg==",
+ "qYHdgFAXhF/XcW4lxqfvWQ==",
+ "26+yXbqI+fmIZsYl4UhUzw==",
+ "AwPTZpC28NJQhf5fNiJuLA==",
+ "SESKbGF35rjO64gktmLTWA==",
+ "YVlRQHQglkbj3J2nHiP/Hw==",
+ "DdaT4JLC7U0EkF50LzIj9w==",
+ "G0LChrb0OE5YFqsfTpIL1Q==",
+ "5Yrj6uevT8wHRyqqgnSfeg==",
+ "NmWmDxwK5FpKlZbo0Rt8RA==",
+ "iUsUCB0mfRsE9KPEQctIzw==",
+ "Tm4zk2Lmg8w4ITMI31NfTA==",
+ "Vu0E+IJXBnc25x4n41kQig==",
+ "6wkfN8hyKmKU6tG3YetCmw==",
+ "trjM81KANPZrg9iSThWx6Q==",
+ "iGuY4VxcotHvMFXuXum7KA==",
+ "ICPdBCdONUqPwD5BXU5lrw==",
+ "alqHQBz8V446EdzuVfeY5Q==",
+ "74FW/QYTzr/P1k6QwVHMcw==",
+ "avZp5K7zJvRvJvpLSldNAw==",
+ "TIKadc6FAaRWSQUg5OATgg==",
+ "PfkWkSbAxIt1Iso0znW0+Q==",
+ "Z+bsbVP91KrJvxrujBLrrQ==",
+ "mrxlFD3FBqpSZr1kuuwxGg==",
+ "nUgYO7/oVNSX8fJqP2dbdg==",
+ "tVhXk9Ff3wAg56FbdNtcFg==",
+ "DdiNGiOSoIZxrMrGNvqkXw==",
+ "CDsanJz7e3r/eQe+ZYFeVQ==",
+ "wVfSZYjMjbTsD2gaSbwuqQ==",
+ "6c0iuya20Ys8BsvoI4iQaQ==",
+ "qCPfJTR8ecTw6u6b1yHibA==",
+ "fZrj3wGQSt8RXv0ykJROcQ==",
+ "gR3B8usSEb0NLos51BmJQg==",
+ "vTAmgfq3GxL4+ubXpzwk5w==",
+ "jLkmUZ6fV56GfhC0nkh4GA==",
+ "3v09RHCPTLUztqapThYaHg==",
+ "nULSbtw2dXbfVjZh33pDiA==",
+ "IHhyR6+5sZXTH+/NrghIPg==",
+ "tnUtJ/DQX9WaVJyTgemsUA==",
+ "7xTKFcog69nTmMfr5qFUTA==",
+ "IshzWega6zr3979khNVFQQ==",
+ "Ng5v/B9Z10TTfsDFQ/XrXQ==",
+ "hnCUnoxofUiqQvrxl73M8w==",
+ "VPa7DG6v7KnzMvtJPb88LQ==",
+ "4LtQrahKXVtsbXrEzYU1zQ==",
+ "Ev/xjTi7akYBI7IeZJ4Igw==",
+ "41WEjhYUlG6jp2UPGj11eQ==",
+ "JvXTdChcE3AqMbFYTT3/wg==",
+ "2rOkEVl90EPqfHOF5q2FYw==",
+ "mjFBVRJ7TgnJx+Q74xllPg==",
+ "Uy4QI8D2y1bq/HDNItCtAw==",
+ "wMOE/pEKVIklE75xjt6b6w==",
+ "ZcuIvc8fDI+2uF0I0uLiVA==",
+ "CX/N/lHckmAtHKysYtGdZA==",
+ "j8to4gtSIRYpCogv2TESuQ==",
+ "iS9wumBV5ktCTefFzKYfkA==",
+ "ewPT4dM12nDWEDoRfiZZnA==",
+ "vWn9OPnrJgfPavg4D6T/HQ==",
+ "J/PNYu4y6ZMWFFXsAhaoow==",
+ "catI+QUNk3uJ+mUBY3bY8Q==",
+ "F8tEIT5EhcvLNRU5f0zlXQ==",
+ "zyA9f5J7mw5InjhcfeumAQ==",
+ "MlOOZOwcRGIkifaktEq0aQ==",
+ "Pt3i49uweYVgWze3OjkjJA==",
+ "sfIClgTMtZo9CM9MHaoqhQ==",
+ "HeQbUuBM9sqfXFXRBDISSw==",
+ "SFn78uklZfMtKoz2N0xDaQ==",
+ "H6j2nPbBaxHecXruxiWYkA==",
+ "fU32wmMeD44UsFSqFY0wBA==",
+ "hDILjSpTLqJpiSSSGu445A==",
+ "ieEAgvK9LsWh2t6DsQOpWA==",
+ "xfjBQk3CrNjhufdPIhr91A==",
+ "j+8/VARfbQSYhHzj0KPurQ==",
+ "/zFLRvi75UL8qvg+a6zqGg==",
+ "U0KmEI6e5zJkaI4YJyA5Ew==",
+ "uXvr6vi5kazZ9BCg2PWPJA==",
+ "jEqP0dyHKHiUjZ9dNNGTlQ==",
+ "1xWx5V3G9murZP7srljFmA==",
+ "OIwtfdq37eQ0qoXuB2j7Hw==",
+ "fUAy3f9bAglLvZWvkO2Lug==",
+ "duRFqmvqF93uf/vWn8aOmg==",
+ "ysRQ+7Aq7eVLOp88KnFVMA==",
+ "CkZUmKBAGu0FLpgPDrybpw==",
+ "TrLmfgwaNATh24eSrOT+pw==",
+ "83wtvSoSP9FVBsdWaiWfpA==",
+ "pUfWmRXo70yGkUD/x5oIvA==",
+ "PybPZhJErbRTuAafrrkb3g==",
+ "8hsfXqi4uiuL+bV1VrHqCw==",
+ "TVlHoi8J7sOZ2Ti7Dm92cQ==",
+ "za4rzveYVMFe3Gw531DQJQ==",
+ "JKphO0UYjFqcbPr6EeBuqg==",
+ "hqeSvwu8eqA072iidlJBAw==",
+ "bUF0JIfS4uKd3JZj2xotLQ==",
+ "hKOsXOBoFTl/K4xE+RNHDA==",
+ "JHBjKpCgSgrNNACZW1W+1w==",
+ "Rrq0ak9YexLqqbSD4SSXlw==",
+ "+NmjwjsPhGJh9bM10SFkLw==",
+ "xMIHeno2qj3V8q9H1xezeg==",
+ "TcFinyBrUoAEcLzWdFymow==",
+ "Rvchz/xjcY9uKiDAkRBMmA==",
+ "TYlnrwgyeZoRgOpBYneRAg==",
+ "PbnxuVerGwHyshkumqAARg==",
+ "iFtadcw8v6betKka9yaJfg==",
+ "7wgT9WIiMVcrj48PVAMIgw==",
+ "2HHqeGRMfzf3RXwVybx+ZQ==",
+ "tdgI9v7cqJsgCAeW1Fii1A==",
+ "4ZFYKa7ZgvHyZLS6WpM8gA==",
+ "gB8wkuIzvuDAIhDtNT1gyA==",
+ "g1ELwsk6hQ+RAY1BH640Pg==",
+ "UZoibx+y1YJy/uRSa9Oa2w==",
+ "yS/yMnJDHW0iaOsbj4oPTg==",
+ "JzW+yhrjXW1ivKu3mUXPXg==",
+ "/wIZAye9h1TUiZmDW0ZmYA==",
+ "YK+q7uJObkQZvOwQ9hplMg==",
+ "Rs8deApkoosIJSfX7NXtAA==",
+ "MsCloSmTFoBpm7XWYb+ueQ==",
+ "3ltw31yJuAl4VT6MieEXXw==",
+ "1+qmrbC8c7MJ6pxmDMcKuA==",
+ "AYxGETZs477n2sa1Ulu/RQ==",
+ "Q0TJZxpn3jk67L7N+YDaNA==",
+ "OGpsXRHlaN8BvZftxh1e7A==",
+ "UbABE6ECnjB+9YvblE9CYw==",
+ "kZ0D191c/uv4YMG15yVLDw==",
+ "QWURrsEgxbJ8MWcaRmOWqw==",
+ "xiFlcSfa/gnPiO+LwbixcQ==",
+ "Szko0IPE7RX2+mfsWczrMg==",
+ "Ugt8HVC/aUzyWpiHd0gCOQ==",
+ "8j9GVPiFdfIRm/+ho7hpoA==",
+ "KR401XBdgCrtVDSaXqPEiA==",
+ "d0NBFiwGlQNclKObRtGVMQ==",
+ "XEwOJG24eaEtAuBWtMxhwg==",
+ "0Y6iiZjCwPDwD/CwJzfioQ==",
+ "MvMbvZNKbXFe2XdN+HtnpQ==",
+ "fsoXIbq0T0nmSpW8b+bj+g==",
+ "Uje3Ild84sN41JEg3PEHDg==",
+ "i6ZYpFwsyWyMJNgqUMSV1A==",
+ "+P5q4YD1Rr5SX26Xr+tzlw==",
+ "z4oKy2wKH+sbNSgGjbdHGw==",
+ "XwKWd03sAz8MmvJEuN08xA==",
+ "Xv0mNYedaBc57RrcbHr9OA==",
+ "9oUawSwUGOmb0sDn3XS6og==",
+ "9RGIQ2qyevNbSSEF36xk/A==",
+ "q8YF9G2jqydAxSqwyyys5Q==",
+ "m5JIUETVXcRza4VL4xlJbg==",
+ "aRpdnrOyu5mWB1P5YMbvOA==",
+ "rM/BOovNgnvebKMxZQdk7g==",
+ "fQS0jnQMnHBn7+JZWkiE/g==",
+ "gAoV4BZYdW1Wm712YXOhWQ==",
+ "hCzsi1yDv9ja5/o7t94j9Q==",
+ "CoLvjQDQGldGDqRxfQo+WQ==",
+ "pfGcaa49SM3S6yJIPk/EJQ==",
+ "yYp4iuI5f/y/l1AEJxYolQ==",
+ "Jj4IrSVpqQnhFrzNvylSzA==",
+ "4jeOFKuKpCmMXUVJSh9y0g==",
+ "+NMUaQ7XPsAi0rk7tTT9wQ==",
+ "Jt4Eg6MJn8O4Ph/K2LeSUA==",
+ "CiiUeJ0LeWfm7+gmEmYXtg==",
+ "c5Tc7rTFXNJqYyc0ppW+Iw==",
+ "4KJZPCE9NKTfzFxl76GWjg==",
+ "aXs9qTEXLTkN956ch3pnOA==",
+ "f5Xo7F1uaiM760Qbt978iw==",
+ "wpZqFkKafFpLcykN2IISqg==",
+ "vIORTYSHFIXk5E2NyIvWcQ==",
+ "prOsOG0adI4o+oz50moipw==",
+ "blygTgAHZJ3NzyAT33Bfww==",
+ "rBt6L/KLT7eybxKt5wtFdg==",
+ "vMuaLvAntJB5o7lmt/kVXA==",
+ "iujlt9fXcUXEYc+T2s5UjA==",
+ "LyYPOZKm8bBegMr5NTSBfg==",
+ "ZtWvgitOSRDWq7LAKYYd4Q==",
+ "kh51WUI5TRnKhur6ZEpRTQ==",
+ "VzQ1NwNv9btxUzxwVqvHQg==",
+ "8fJLQeIHaTnJ8wGqUiKU6g==",
+ "vvEH5A39TTe1AOC11rRCLA==",
+ "dihDsG7+6aocG6M9BWrCzQ==",
+ "3jqsY8/xTWELmu/az3Daug==",
+ "mpOtwBvle+nyY6lUBwTemw==",
+ "E1CvxFbuu9AYW604mnpGTw==",
+ "1LPC0BzhJbepHTSAiZ3QTw==",
+ "XpGXh76RDgXC4qnTCsnNHA==",
+ "3Gg9N7vjAfQEYOtQKuF/Eg==",
+ "+WpF8+poKmHPUBB4UYh/ig==",
+ "UNt7CNMtltJWq8giDciGyA==",
+ "RIZYDgXqsIdTf9o2Tp/S7g==",
+ "0QCQORCYfLuSbq94Sbt0bQ==",
+ "hvsZ5JmVevK1zclFYmxHaw==",
+ "3+9nURtBK3FKn0J9DQDa3g==",
+ "jdVMQqApseHH3fd91NFhxg==",
+ "VX+cVXV8p9i5EBTMoiQOQQ==",
+ "I5qDndyelK4Njv4YrX7S6w==",
+ "rWliqgfZ3/uCRBOZ9sMmdA==",
+ "vwno3vugCvt6ooT3CD4qIQ==",
+ "cffrYrBX3UQhfX1TbAF+GQ==",
+ "nOiwBFnXxCBfPCHYITgqNg==",
+ "LQttmX92SI94+hDNVd8Gtw==",
+ "iCF+GWw9/YGQXsOOPAnPHQ==",
+ "nwtCsN1xEYaHvEOPzBv+qQ==",
+ "CQpJFrpOvcQhsTXIlJli+Q==",
+ "tYeIZjIm0tVEsYxH1iIiUQ==",
+ "iCnm5fPmSmxsIzuRK6osrA==",
+ "tX8X8KoxUQ8atFSCxgwE1Q==",
+ "hZlX6qOfwxW5SPfqtRqaMw==",
+ "2aIx9UdMxxZWvrfeJ+DcTw==",
+ "TlJizlASbPtShZhkPww4UA==",
+ "p+bx+/WQWALXEBCTnIMr4w==",
+ "4VR5LiXLew6Nyn91zH9L4w==",
+ "bfUD03N2PRDT+MZ+WFVtow==",
+ "cTvDd8okNUx0RCMer6O8sw==",
+ "49jZr/mEW6fvnyzskyN40w==",
+ "vHmQUl4WHXs1E/Shh+TeyA==",
+ "fgXfRuqFfAu8qxbTi4bmhA==",
+ "Wn+Vj4eiWx0WPUHr3nFbyA==",
+ "2SwIiUwT4vRZPrg7+vZqDA==",
+ "nkedTagkmf6YE4tEY+0fKw==",
+ "8nOTDhFyZ8YUA4b6M5p84w==",
+ "qnzWszsyJhYtx8wkMN6b1g==",
+ "ka7pMp8eSiv92WgAsz2vdA==",
+ "pGQEWJ38hb/ZYy2P1+FIuw==",
+ "cVhdRFuZaW/09CYPmtNv5g==",
+ "prCOYlboBnzmLEBG/OeVrQ==",
+ "oIWwTbkVS5DDL47mY9/1KQ==",
+ "PKtXc4x4DEjM45dnmPWzyg==",
+ "f9ywiGXsz+PuEsLTV3zIbQ==",
+ "6G2bD3Y7qbGmfPqH9TqLFA==",
+ "DMHmyn2U2n+UXxkqdvKpnA==",
+ "XOG1PYgqoG8gVLIbVLTQgg==",
+ "1FSrgkUXgZot2CsmbAtkPw==",
+ "BxFP+4o6PSlGN78eSVT1pA==",
+ "EZVQGsXTZvht1qedRLF8bQ==",
+ "eYAQWuWZX2346VMCD6s7/A==",
+ "jkUpkLoIXuu7aSH8ZghIAQ==",
+ "mXPtbPaoNAAlGmUMmJEWBQ==",
+ "HLesnV3DL+FhWF3h6RXe8g==",
+ "nDAsSla+9XfAlQSPsXtzPA==",
+ "RAECgYZmcF4WxcFcZ4A0Ww==",
+ "W+M4BcYNmjj7xAximDGWsA==",
+ "ueODvMv/f9ZD8O0aIHn4sg==",
+ "cszpMdGbsbe6BygqMlnC9Q==",
+ "siHwJx6EgeB1gBT9z/vTyw==",
+ "FN7oLGBQGHXXn5dLnr/ElA==",
+ "Tud+AMyuFkWYYZ73yoJGpQ==",
+ "TuaG3wRdM9BWKAxh2UmAsg==",
+ "8CjmgWQSAAGcXX9kz3kssw==",
+ "ays5/F7JANIgPHN0vp2dqQ==",
+ "PCOGl7GIqbizAKj/sZmlwQ==",
+ "rZKD8oJnIj5fSNGiccfcvA==",
+ "gFEnTI8os2BfRGqx9p5x8w==",
+ "5r1ZsGkrzNQEpgt/gENibw==",
+ "1YO9G8qAhLIu2rShvekedw==",
+ "6ZKmm7IW7IdWuVytLr68CQ==",
+ "mMfn8OaKBxtetweulho+xQ==",
+ "GQJxu1SoMBH14KPV/G/KrQ==",
+ "IYIP2UBRyWetVfYLRsi1SQ==",
+ "Jit0X0srSNFnn8Ymi1EY+g==",
+ "ARCWkHAnVgBOIkCDQ19ZuA==",
+ "qA0sTaeNPNIiQbjIe1bOgQ==",
+ "iGI9uqMoBBAjPszpxjZBWQ==",
+ "+L1FDsr5VQtuYc2Is5QGjw==",
+ "4XNUmgwxsqDYsNmPkgNQYQ==",
+ "Yig+Wh18VIqdsmwtwfoUQw==",
+ "uqp92lAqjec8UQYfyjaEZw==",
+ "QiozlNcQCbqXtwItWExqJQ==",
+ "JFHutgSe1/SlcYKIbNNYwQ==",
+ "Y26jxXvl79RcffH8O8b9Ew==",
+ "bQ7J5mebp38rfP/fuqQOsg==",
+ "HI4ZIE5s8ez8Rb+Mv39FxA==",
+ "OzH7jTcyeM7RPVFtBdakpQ==",
+ "HLxROy6fx/mLXFTDSX4eLA==",
+ "s5RUHVRNAoKMuPR/Jkfc2Q==",
+ "X9QAaNjgiOeAWSphrGtyVw==",
+ "ALJWKUImVE40MbEooqsrng==",
+ "9MDG0WeBPpjGJLEmUJgBWg==",
+ "9RXymE9kCkDvBzWGyMgIWA==",
+ "vFox1d3llOeBeCUZGvTy0A==",
+ "r3lQAYOYhwlLnDWQIunKqg==",
+ "2os5s7j7Tl46ZmoZJH8FjA==",
+ "O5N2yd+QQggPBinQ+zIhtQ==",
+ "ZygAjaN62XhW5smlLkks+Q==",
+ "AgDJsaW0LkpGE65Kxk5+IA==",
+ "omAjyj1l6gyQAlBGfdxJTw==",
+ "fY9VATklOvceDfHZDDk57A==",
+ "StpQm/cQF8cT0LFzKUhC5w==",
+ "CYJB3qy5GalPLAv1KGFEZA==",
+ "coGEgMVs2b314qrXMjNumQ==",
+ "DQQB/l55iPN9XcySieNX3A==",
+ "6dshA8knH5qqD+KmR/kdSQ==",
+ "qyRmvxh8p4j4f+61c10ZFQ==",
+ "apWEPWUvMC24Y+2vTSLXoA==",
+ "RzX2OfSFEd//LhZwRwzBVw==",
+ "NdULoUDGhIolzw1PyYKV0A==",
+ "5w/c9WkI/FA+4lOtdPxoww==",
+ "bV9r7j2kNJpDCEM5E2339Q==",
+ "vbyiKeDCQ4q9dDRI1Q0Ong==",
+ "9xIgKpZGqq0/OU6wM5ZSHw==",
+ "RYkDwwng6eeffPHxt8iD9A==",
+ "w5N/aHbtOIKzcvG3GlMjGA==",
+ "3P2aJxV8Trll2GH9ptElYA==",
+ "yteeQr3ub2lDXgLziZV+DQ==",
+ "yqtj8GfLaUHYv/BsdjxIVw==",
+ "NyF+4VRog7etp90B9FuEjA==",
+ "uwA6N5LptSXqIBkTO0Jd7Q==",
+ "6lVSzYUQ/r0ep4W2eCzFpg==",
+ "1d7RPHdZ9qzAbG3Vi9BdFA==",
+ "7br49X11xc2GxQLSpZWjKQ==",
+ "peMW+rpwmXrSwplVuB/gTA==",
+ "RqYpA5AY7mKPaSxoQfI1CA==",
+ "dqVw2q2nhCvTcW82MT7z0g==",
+ "5S5/asYfWjOwnzYpbK6JDw==",
+ "NvkR0inSzAdetpI4SOXGhw==",
+ "tIqwBotg052wGBL65DZ+yA==",
+ "S4RvORcJ3m6WhnAgV4YfYA==",
+ "UAqf4owQ+EmrE45hBcUMEw==",
+ "4aPU6053cfMLHgLwAZJRNg==",
+ "3Y6/HqS1trYc9Dh778sefg==",
+ "ck86G8HsbXflyrK7MBntLg==",
+ "GLmWLXURlUOJ+PMjpWEXVA==",
+ "jNJQ6otieHBYIXA9LjXprg==",
+ "AsAHrIkMgc3RRWnklY9lJw==",
+ "FCLQocqxxhJeleARZ6kSPg==",
+ "3Leu2Sc+YOntJFlrvhaXeg==",
+ "hSkY45CeB6Ilvh0Io4W6cg==",
+ "DwrNdmU5VFFf3TwCCcptPA==",
+ "u2WQlcMxOACy6VbJXK4FwA==",
+ "E9IlDyULLdeaVUzN6eky8g==",
+ "EXveRXjzsjh8zbbQY2pM9g==",
+ "5VO1inwXMvLDBQSOahT6rg==",
+ "HaHTsLzx7V3G1SFknXpGxA==",
+ "MMaegl2Md9s/wOx5o9564w==",
+ "mpWNaUH9kn4WY26DWNAh3Q==",
+ "w3G+qXXqqKi8F5s+qvkBUg==",
+ "wM8tnXO4PDlLVHspZFcjYw==",
+ "LFcpCtnSnsCPD2gT/RA+Zg==",
+ "bhVbgJ4Do4v56D9mBuR/EA==",
+ "yU3N0HMSP5etuHPNrVkZtg==",
+ "FzqIpOcTsckSNHExrl+9jg==",
+ "BYz52gYI/Z6AbYbjWefcEA==",
+ "h3vYYI9yhpSZV2MQMJtwFQ==",
+ "adJAjAFyR2ne1puEgRiH+g==",
+ "eDcyiPaB954q5cPXcuxAQw==",
+ "40gCrW4YWi+2lkqMSPKBPg==",
+ "ulLuTZqhEDkX0EJ3xwRP9A==",
+ "y4iBxAMn/KzMmaWShdYiIw==",
+ "ilBBNK/IV69xKTShvI94fQ==",
+ "0HN6MIGtkdzNPsrGs611xA==",
+ "twPn6wTGqI0aR//0wP3xtA==",
+ "3UNJ37f+gnNyYk9yLFeoYA==",
+ "4SdHWowXgCpCDL28jEFpAw==",
+ "Mr5mCtC53+wwmwujOU/fWw==",
+ "81pAhreEPxcKse+++h1qBg==",
+ "KmcGEE0pacQ/HDUgjlt7Pg==",
+ "Gt4/MMrLBErhbFjGbiNqQQ==",
+ "lf1fwA0YoWUZaEybE+LyMQ==",
+ "RIVYGO2smx9rmRoDVYMPXw==",
+ "rJ9qVn8/2nOxexWzqIHlcQ==",
+ "lfOLLyZNbsWQgHRhicr4ag==",
+ "wgH1GlUxWi6/yLLFzE76uQ==",
+ "Qg1ubGl+orphvT990e5ZPA==",
+ "Z5B+uOmPZbpbFWHpI9WhPw==",
+ "snGTzo540cCqgBjxrfNpKw==",
+ "ZqkmoGB0p5uT5J6XBGh7Tw==",
+ "uPi8TsGY3vQsMVo/nsbgVQ==",
+ "Y5XR8Igvau/h+c1pRgKayg==",
+ "ZmVpw1TUVuT13Zw/MNI5hQ==",
+ "60suecbWRfexSh7C67RENA==",
+ "kZ/mZZg9YSDmk2rCGChYAg==",
+ "OpL+vHwPasW30s2E1TYgpA==",
+ "ZVnErH1Si4u51QoT0OT7pA==",
+ "3pi3aNVq1QNJmu1j0iyL0g==",
+ "tb5+2dmYALJibez1W4zXgA==",
+ "jOPdd330tB6+7C29a9wn0Q==",
+ "5oD/aGqoakxaezq43x0Tvw==",
+ "HdB7Se47cWjPgpJN0pZuiA==",
+ "6WhHPWlqEUqXC52rHGRHjA==",
+ "WLwpjgr9KzevuogoHZaVUw==",
+ "E8yMPK7W0SIGTK6gIqhxiQ==",
+ "1/Hxu8M9N/oNwk8bCj4FNQ==",
+ "Uo1ebgsOxc3eDRds1ah3ag==",
+ "5pqqzC/YmRIMA9tMFPi7rg==",
+ "ri4AOITPdB1YHyXV+5S51g==",
+ "HfvsiCQN/3mT0FabCU5ygQ==",
+ "UQTQk5rrs6lEb1a+nkLwfg==",
+ "VH70dN82yPCRctmAHMfCig==",
+ "yD3Dd4ToRrl53k/2NSCJiw==",
+ "fO0+6TsjL+45p9mSsMRiIg==",
+ "fM5uYpkvJFArnYiQ3MrQnA==",
+ "V+QzdKh5gxTPp2yPC9ZNEg==",
+ "XHHEg/8KZioW/4/wgSEkbQ==",
+ "2abfl3N46tznOpr+94VONQ==",
+ "gxwbqZDHLbQVqXjaq42BCg==",
+ "WnHK5ZQDR6Da5cGODXeo0A==",
+ "SChDh/Np1HyTPWfICfE1uA==",
+ "yhexr/OFKfZl0o3lS70e4w==",
+ "N65PqIWiQeS082D6qpfrAg==",
+ "RM5CpIiB94Sqxi462G7caA==",
+ "CBAGa5l95f3hVzNi6MPWeQ==",
+ "OHJBT2SEv5b5NxBpiAf7oQ==",
+ "p48i7AfSSAyTdJSyHvOONw==",
+ "/SP6pOdYFzcAl2OL05z4uQ==",
+ "N8dXCawxSBX40fgRRSDqlQ==",
+ "bMWFvjM8eVezU1ZXKmdgqw==",
+ "Um1ftRBycvb+363a90Osog==",
+ "QAz7FA+jpz9GgLvwdoNTEQ==",
+ "qO4HlyHMK5ygX+6HbwQe8w==",
+ "UgvtdE2eBZBUCAJG/6c0og==",
+ "q5g3c8tnQTW2EjNfb2sukw==",
+ "gsC/mWD8KFblxB0JxNuqJw==",
+ "SVFbcjXbV7HRg+7jUrzpwg==",
+ "bz294kSG4egZnH2dJ8HwEg==",
+ "ybpTgPr3SjJ12Rj5lC/IMA==",
+ "yDrAd1ot38soBk7zKdnT8A==",
+ "BB/R8oQOcoE4j63Hrh8ifg==",
+ "GNrMvNXQkW7PydlyJa+f1w==",
+ "w0PKdssv+Zc5J/BbphoxpA==",
+ "D5ibbo8UJMfFZ48RffuhgQ==",
+ "MdvhC1cuXqni/0mtQlSOCw==",
+ "wQKL8Ga6JQkpZ7yymDkC3w==",
+ "o1uhaQg5/zfne84BFAINUQ==",
+ "Ft2wXUokFdUf6d2Y/lwriw==",
+ "sLJrshdEANp0qk2xOUtTnQ==",
+ "jx7rpxbm1NaUMcE2ktg5sA==",
+ "ZQ0ZnTsZKWxbRj7Tilh24Q==",
+ "KhrIIHfqXl9zGE9aGrkRVg==",
+ "jS0JuioLGAVaHdo/96JFoQ==",
+ "tr+U/vt+MIGXPRQYYWJfRg==",
+ "TXab/hqNGWaSK+fXAoB2bg==",
+ "0K4NBxqEa3RYpnrkrD/XjQ==",
+ "3oMTbWf7Bv83KRlfjNWQZA==",
+ "yLAhLNezvqVHmN1SfMRrPw==",
+ "ZYW30FfgwHmW6nAbUGmwzA==",
+ "CZNoTy26VUQirvYxSPc/5A==",
+ "CF1sAlhjDQY/KWOBnSSveA==",
+ "+CLf5witKkuOvPCulTlkqw==",
+ "1m1yD4L9A7Q1Ot+wCsrxJQ==",
+ "2E41e0MgM3WhFx2oasIQeA==",
+ "mDXHuOmI4ayjy2kLSHku1Q==",
+ "sCLMrLjEUQ6P1L8tz90Kxg==",
+ "zDUZCzQesFjO1JI3PwDjfg==",
+ "x/BIDm6TKMhqu/gtb3kGyw==",
+ "DEaZD/8aWV6+zkiLSVN/gA==",
+ "7dz+W494zwU5sg63v5flCg==",
+ "Y5iDQySR2c3MK7RPMCgSrw==",
+ "GglPoW5fvr4JSM3Zv99oiA==",
+ "myzvc+2MfxGD9uuvZYdnqQ==",
+ "V9G1we3DOIQGKXjjPqIppQ==",
+ "gYvdNJCDDQmNhtJ6NKSuTA==",
+ "rXtGpN17Onx8LnccJnXwJQ==",
+ "/a+bLXOq02sa/s8h7PhUTg==",
+ "htNVAogFakQkTX6GHoCVXg==",
+ "eshD40tvOA6bXb0Fs/cH3A==",
+ "K1CGbMfhlhIuS0YHLG30PQ==",
+ "aOeJZUIZM9YWjIEokFPnzQ==",
+ "r0hAwlS0mPZVfCSB+2G6uQ==",
+ "0q+erphtrB+6HBnnYg7O6w==",
+ "bkRdUHAksJZGzE1gugizYQ==",
+ "J8v2f6hWFu8oLuwhOeoQjA==",
+ "qkvEep4vvXhc2ZJ6R449Mg==",
+ "6HGeEPyTAu9oiKhNVLjQnA==",
+ "JoATsk/aJH0UcDchFMksWA==",
+ "QozQL0DTtr+PXNKifv6l6g==",
+ "HiAgt86AyznvbI2pnLalVQ==",
+ "lY+tivtsfvU0LJzBQ6itYQ==",
+ "EfXDc6h69aBPE6qsB+6+Ig==",
+ "gnAIpoCyl3mQytLFgBEgGA==",
+ "p2JPOX8yDQ0agG+tUyyT/g==",
+ "zeELfk015D5krExLKRUYtg==",
+ "wDiGoFEfIVEDyyc4VpwhWQ==",
+ "7Ephy+mklG2Y3MFdqmXqlA==",
+ "8ZFPMJJYVJHsfRpU4DigSg==",
+ "ocRh5LR1ZIN9Johnht8fhQ==",
+ "l5f3I6osM9oxLRAwnUnc5A==",
+ "yxCyBXqGWA735JEyljDP7Q==",
+ "qE/h/Z+6buZWf+cmPdhxog==",
+ "HCu4ZMrcLMZbPXbTlWuvvQ==",
+ "TDrq23VUdzEU/8L5i8jRJQ==",
+ "L+N/6geuokiLPPSDXM9Qkg==",
+ "v6jZicMNM3ysm3U5xu0HoQ==",
+ "b85nxzs8xiHxaqezuDVWvg==",
+ "ca+kx+kf7JuZ3pfYKDwFlg==",
+ "KlY5TGg0pR/57TVX+ik1KQ==",
+ "3jmCreW5ytSuGfmeLv7NfQ==",
+ "ucLMWnNDSqE4NOCGWvcGWw==",
+ "NSrzwNlB0bde3ph8k6ZQcQ==",
+ "nL4iEd3b5v4Y9fHWDs+Lrw==",
+ "W2x0SBzSIsTRgyWUCOZ/lg==",
+ "ifZM0gBm9g9L09YlL+vXBg==",
+ "4WcFEswYU/HHQPw77DYnyA==",
+ "TLJbasOoVO435E5NE5JDcA==",
+ "WyCFB4+6lVtlzu3ExHAGbQ==",
+ "BW0A06zoQw7S+YMGaegT7g==",
+ "qP1cCE4zsKGTPhjbcpczMw==",
+ "UVEZPoH9cysC+17MKHFraw==",
+ "eQ45Mvf5in9xKrP6/qjYbg==",
+ "fOARCnIg/foF/6tm7m9+3w==",
+ "lK2xe+OuPutp4os0ZAZx5w==",
+ "Tug3eh+28ttyf+U7jfpg5w==",
+ "ENFfP93LA257G6pXQkmIdg==",
+ "FuWspiqu5g8Eeli5Az+BkA==",
+ "kIGxCUxSlNgsKZ45Al1lWw==",
+ "RzeH+G3gvuK1z+nJGYqARQ==",
+ "0ofMbUCA3/v5L8lHnX4S5w==",
+ "VI8pgqBZeGWNaxkuqQVe7g==",
+ "x6lNRGgJcRxgKTlzhc1WPg==",
+ "La0gzdbDyXUq6YAXeKPuJA==",
+ "dAq8/1JSQf1f4QPLUitp0g==",
+ "WN7lFJfw4lSnTCcbmt5nsg==",
+ "2aDK0tGNgMLyxT+BQPDE8Q==",
+ "9W57pTzc572EvSURqwrRhw==",
+ "37Nkh06O979nt7xzspOFyQ==",
+ "4TQkMnRsXBobbtnBmfPKnA==",
+ "f/BjtP5fmFw2dRHgocbFlg==",
+ "9vEgJVJLEfed6wJ7hBUGgQ==",
+ "HRWYX2XOdsOqYzCcqkwIyw==",
+ "StDtLMlCI75g4XC59mESEQ==",
+ "99+SBN45LwKCPfrjUKRPmw==",
+ "HbT6W1Ssd3W7ApKzrmsbcg==",
+ "l8/KMItWaW3n4g1Yot/rcQ==",
+ "s7iW1M6gkAMp+D/3jHY58w==",
+ "GWwJ32SZqD5wldrXUdNTLA==",
+ "YhLEPsi/TNyeUJw69SPYzQ==",
+ "g0aTR8aJ0uVy3YvGYu5xrw==",
+ "m6get5wjq5j1i5abnpXuZQ==",
+ "ymtA8EMPMgmMcimWZZ0A1Q==",
+ "HEcOaEd9zCoOVbEmroSvJg==",
+ "F8l+Qd9TZgzV+r8G584lKA==",
+ "3yDD+xT8iRfUVdxcc7RxKw==",
+ "1eRUCdIJe3YGD5jOMbkkOg==",
+ "DO1/jfP/xBI9N0RJNqB2Rw==",
+ "SiSlasZ+6U2IZYogqr2UPg==",
+ "tBQDfy48FnIOZI04rxfdcA==",
+ "HEghmKg3GN60K7otpeNhaA==",
+ "mTLBkP+yGHsdk5g7zLjVUw==",
+ "RgtwfY5pTolKrUGT+6Pp6g==",
+ "EyIsYQxgFa4huyo/Lomv7g==",
+ "HwLSUie8bzH+pOJT3XQFyg==",
+ "7Tauesu7bgs5lJmQROVFiQ==",
+ "ojugpLIfzflgU2lonfdGxA==",
+ "ZqjnqxZE/BjOUY0CMdVl0g==",
+ "oQjugfjraFziga1BcwRLRA==",
+ "JXCYeWjFqcdSf6QwB54G+A==",
+ "TeBGJCqSqbzvljIh9viAqA==",
+ "1Gpj4TPXhdPEI4zfQFsOCg==",
+ "asouSfUjJa8yfMG7BBe+fA==",
+ "ccy3Ke2k4+evIw0agHlh3w==",
+ "CzSumIcYrZlxOUwUnLR2Zw==",
+ "9QFYrCXsGsInUb4SClS3cQ==",
+ "3RTtSaMp1TZegJo5gFtwwA==",
+ "aTWiWjyeSDVY/q8y9xc2zg==",
+ "UK+R+hAoVeZ4xvsoZjdWpw==",
+ "rHagXw+CkF3uEWPWDKXvog==",
+ "MfkyURTBfkNZwB+wZKjP4g==",
+ "Qf7JFJJuuacSzl6djUT2EQ==",
+ "K1RL+tLjICBvMupe7QppIQ==",
+ "R2OOV18CV/YpWL1xzr/VQg==",
+ "o+areESiXgSO0Lby56cBeg==",
+ "VPqyIomYm7HbK5biVDvlpw==",
+ "pw1jplCdTC+b0ThX0FXOjw==",
+ "gTnsH3IzALFscTZ1JkA9pw==",
+ "JYJvOZ4CHktLrYJyAbdOnA==",
+ "P8lUiLFoL100c9YSQWYqDA==",
+ "LATQEY7f47i77M6p11wjWA==",
+ "U9kE50Wq5/EHO03c5hE4Ug==",
+ "pFKzcRHSUBqSMtkEJvrR1Q==",
+ "vHVXsAMQqc0qp7HA5Q+YkA==",
+ "3XyoREdvhmSbyvAbgw2y/A==",
+ "qOEIUWtGm5vx/+fg4tuazg==",
+ "a6IszND1m+6w+W+CvseC7g==",
+ "KuNY8qAJBce+yUIluW8AYw==",
+ "5Wcq+6hgnWsQZ/bojERpUw==",
+ "l2ZB9TvT68rn8AAN4MdxWw==",
+ "h5HsEsObPuPFqREfynVblw==",
+ "fvm0IQfnbfZFETg9v3z/Fg==",
+ "QV0OG5bpjrjku4AzDvp9yw==",
+ "nMuMtK/Zkb3Xr34oFuX/Lg==",
+ "jMZKSMP2THqwpWqJNJRWdw==",
+ "fX4G68hFL7DmEmjbWlCBJQ==",
+ "ZlBNHAiYsfaEEiPQ1z+rCA==",
+ "ckugAisBNX18eQz+EnEjjw==",
+ "Dt6hvhPJu94CJpiyJ5uUkg==",
+ "eYE9No9sN5kUZ5ePEyS3+Q==",
+ "Tp52d1NndiC9w3crFqFm9g==",
+ "MBjMU/17AXBK0tqyARZP5w==",
+ "1EI9aa955ejNo1dJepcZJw==",
+ "FqWLkhWl0iiD/u2cp+XK9A==",
+ "j8nMH8mK/0Aae7ZkqyPgdg==",
+ "ZtmnX24AwYAXHb2ZDC6MeQ==",
+ "who8uUamlHWHXnBf7dwy4A==",
+ "CmkmWcMK4eqPBcRbdnQvhw==",
+ "61V74uIjaSfZM8au1dxr1A==",
+ "778O1hdVKHLG2q9dycUS0Q==",
+ "IdadoCPmSgHDHzn1zyf8Jw==",
+ "Z2rwGmVEMCY6nCfHO3qOzw==",
+ "Q3TpCE+wnmH/1h/EPWsBtQ==",
+ "HnVfyqgJ+1xSsN4deTXcIA==",
+ "XgPHx2+ULpm14IOZU2lrDg==",
+ "IbN736G1Px5bsYqE5gW1JQ==",
+ "nY/H7vThZ+dDxoPRyql+Cg==",
+ "wlWxtQDJ+siGhN2fJn3qtw==",
+ "MrbEUlTagbesBNg0OemHpw==",
+ "LJtRcR70ug6UHiuqbT6NGw==",
+ "hSNZWNKUtDtMo6otkXA/DA==",
+ "LawT9ZygiVtBk0XJ+KkQgQ==",
+ "DLzHkTjjuH6LpWHo2ITD0Q==",
+ "i8XXN7jcrmhnrOVDV8a2Hw==",
+ "ogcuGHUZJkmv+vCz567a2g==",
+ "rUp5Mfc57+A8Q29SPcvH/Q==",
+ "6706ncrH1OANFnaK6DUMqQ==",
+ "gK7dhke5ChQzlYc/bcIkcg==",
+ "t3Txxjq43e/CtQmfQTKwWg==",
+ "6ZMs9vCzK9lsbS6eyzZlIA==",
+ "uTHBqApdKOAgdwX3cjrCYQ==",
+ "zirOtGUXeRL22ezfotZfQg==",
+ "iK0dWKHjVVexuXvMWJV9pg==",
+ "uzEgwx1iAXAvWPKSVwYSeQ==",
+ "FHvI0IVNvih8tC7JgzvCOw==",
+ "jjNMPXbmpFNsCpWY0cv3eg==",
+ "/cJ0Nn5YbXeUpOHMfWXNHQ==",
+ "WkSJpxBa45XJRWWZFee7hw==",
+ "edlXkskLx287vOBZ9+gVYg==",
+ "+Pl0bSMBAdXpRIA+zE02JA==",
+ "3xw8+0/WU51Yz4TWIMK8mw==",
+ "GdTanUprpE3X/YjJDPpkhQ==",
+ "qnsBdl050y9cUaWxbCczRw==",
+ "pnJnBzAJlO4j3IRqcfmhkQ==",
+ "USq1iF90eUv41QBebs3bhw==",
+ "QH3lAwOYBAJ0Fd5pULAZqw==",
+ "gvvyX5ATi4q9NhnwxRxC8w==",
+ "7xDIG/80SnhgxAYPL9YJtg==",
+ "WVhfn2yJZ43qCTu0TVWJwA==",
+ "twjiDKJM7528oIu/el4Zbg==",
+ "6sBemZt4qY/TBwqk3YcLOQ==",
+ "m3XYojKO+I6PXlVRUQBC3w==",
+ "gUNP5w7ANJm257qjFxSJrA==",
+ "mMLhjdWNnZ8zts9q+a2v3g==",
+ "kjWYVC7Eok2w2YT4rrI+IA==",
+ "ZzT5b0dYQXkQHTXySpWEaA==",
+ "YzTV0esAxBFVls3e0qRsnA==",
+ "9xmtuClkFlpz/X5E9JBWBA==",
+ "nhAnHuCGXcYlqzOxrrEe1g==",
+ "cbBXgB1WQ/i8Xul0bYY2fg==",
+ "AkAes5oErTaJiGD2I4A1Pw==",
+ "Wx9jh/teM0LJHrvTScssyQ==",
+ "fU5ZZ1bIVsV+eXxOpGWo/Q==",
+ "k8eZxqwxiN/ievXdLSEL/w==",
+ "E2LR1aZ3DcdCBuVT7BhReA==",
+ "1eCHcz4swFH+uRhiilOinQ==",
+ "JipruVZx4ban3Zo5nNM37g==",
+ "IPLD9nT5EEYG9ioaSIYuuA==",
+ "pHozgRyMiEmyzThtJnY4MQ==",
+ "p0eNK7zJd7D/HEGaVOrtrQ==",
+ "dGjcKAOGBd4gIjJq7fL+qQ==",
+ "uMq8cDVWFD+tpn8aeP8Pqg==",
+ "gC7gUwGumN7GNlWwfIOjJQ==",
+ "It+K/RCYMOfNrDZxo7lbcA==",
+ "4CfEP8TeMKX33ktwgifGgA==",
+ "nxDGRpePV3H4NChn4eLwag==",
+ "300hoYyMR/mk1mfWJxS8/w==",
+ "DmxgZsQg+Qy1GP0fPkW3VA==",
+ "1vqRt79ukuvdJNyIlIag8Q==",
+ "RWI0HfpP7643OSEZR8kxzw==",
+ "zZtYkKU50PPEj6qSbO5/Sw==",
+ "UNRlg6+CYVOt68NwgufGNA==",
+ "kkbX+a00dfiTgbMI+aJpMg==",
+ "VIC7inSiqzM6v9VqtXDyCw==",
+ "l+x2QhxG8wb5AQbcRxXlmA==",
+ "GUiinC3vgBjbQC2ybMrMNQ==",
+ "6uMF5i0b/xsk55DlPumT7A==",
+ "aK9nybtiIBUvxgs1iQFgsw==",
+ "BLbTFLSb4mkxMaq4/B2khg==",
+ "mTAqtg6oi0iytHQCaSVUsA==",
+ "eBapvE+hdyFTsZ0y5yrahg==",
+ "lHN2dn2cUKJ8ocVL3vEhUQ==",
+ "Mj87ajJ/yR41XwAbFzJbcA==",
+ "FA+nK6mpFWdD0kLFcEdhxA==",
+ "FrTgaF5YZCNkyfR1kVzTLQ==",
+ "5eHStFN7wEmIE+uuRwIlPQ==",
+ "AyWlT+EGzIXc395zTlEU5Q==",
+ "I+wVQA+jpPTJ6xEsAlYucg==",
+ "Y1flEyZZAYxauMo4cmtJ1w==",
+ "1AeReq55UQotRQVKJ66pmg==",
+ "xzGzN5Hhbh0m/KezjNvXbQ==",
+ "meHzY9dIF7llDpFQo1gyMg==",
+ "RnOXOygwJFqrD+DlM3R5Ew==",
+ "JKg64m6mU7C/CkTwVn4ASg==",
+ "gGLz3Ss+amU7y6JF09jq7A==",
+ "Pu9pEf+Tek3J+3jmQNqrKw==",
+ "EATnlYm0p3h04cLAL95JgA==",
+ "o64LDtKq/Fulf1PkVfFcyg==",
+ "hUWqqG1QwYgGC5uXJpCvJw==",
+ "RfSwpO/ywQx4lfgeYlBr2w==",
+ "VaJc9vtYlqJbRPGb5Tf0ow==",
+ "9JKIJrlQjhNSC46H3Cstcw==",
+ "6Z9myGCF5ylWljgIYAmhqw==",
+ "9bAWYElyRN1oJ6eJwPtCtQ==",
+ "ohK6EftXOqBzIMI+5XnESw==",
+ "AVjwqrTBQH1VREuBlOyUOg==",
+ "G2UponGde3/Z+9b2m9abpQ==",
+ "DoiItHSms0B9gYmunVbRkQ==",
+ "vUC0HlTTHj6qNHwfviDtAw==",
+ "hq35Fjgvrcx6I9e6egWS4w==",
+ "sw+bmpzqsM4gEQtnqocQLQ==",
+ "ApiuEPWr8UjuRyJjsYZQBw==",
+ "VXu4ARjq7DS2IR/gT24Pfw==",
+ "3TbRZtFtsh9ez8hqZuTDeA==",
+ "CazLJMJjQMeHhYLwXW7YNg==",
+ "ROSt+NlEoiPFtpRqKtDUrQ==",
+ "IUwVHH6+8/0c+nOrjclOWA==",
+ "lkzFdvtBx5bV6xZO0cxK7g==",
+ "4ekt4m38G9m599xJCmhlug==",
+ "fzkmVWKhJsxyCwiqB/ULnQ==",
+ "LZAKplVoNjeQgfaHqkyEJA==",
+ "91vfsZ7Lx9x5gqWTOdM4sg==",
+ "MVoxyIA+emaulH8Oks8Weg==",
+ "oGH7SMLI2/qjd9Vnhi3s0A==",
+ "vmqfGJE6r4yDahtU/HLrxw==",
+ "Y5KKN7t/v9JSxG/m1GMPSA==",
+ "gXlb7bbRqHXusTE5deolGA==",
+ "/2c4oNniwhL3z5IOngfggg==",
+ "HgIFX42oUdRPu7sKAXhNWg==",
+ "A3dX2ShyL9+WOi6MNJBoYQ==",
+ "hN9bmMHfmnVBVr+7Ibd2Ng==",
+ "DB706G73NpBSRS8TKQOVZw==",
+ "JSyq2MIuObPnEgEUDyALjQ==",
+ "kSUectNPXpXNg+tIveTFRw==",
+ "XVVy3e6dTnO3HpgD6BtwQw==",
+ "td7nDgTDmKPSODRusMcupw==",
+ "Lt/pVD4TFRoiikmgAxEWEw==",
+ "mmRob7iyTkTLDu8ObmTPow==",
+ "Fd0c8f2eykUp9GYhqOcKoA==",
+ "18RKixTv12q3xoBLz6eKiA==",
+ "RClzwwKh51rbB4ekl99EZA==",
+ "oONlXCW4aAqGczQ/bUllBw==",
+ "foPAmiABJ3IXBoed2EgQXA==",
+ "wEJDulZafLuXCvcqBYioFQ==",
+ "K1RgR6HR5uDEQgZ32TAFgA==",
+ "SEIZhyguLoyH7So0p1KY0A==",
+ "ggIfX1J4dX3xQoHnHUI7VA==",
+ "HBRzLacCVYfwUVGzrefZYg==",
+ "aWZRql2IUPVe9hS3dxgVfQ==",
+ "Err1mbWJud80JNsDEmXcYg==",
+ "Z2MkqmpQXdlctCTCUDPyzw==",
+ "JnE6BK0vpWIhNkaeaYNUzw==",
+ "5dUry23poD+0wxZ3hH6WmA==",
+ "DwP0MQf71VsqvAbAMtC3QQ==",
+ "kHcBZXoxnFJ+GMwBZ/xhfQ==",
+ "SUAwMWLMml8uGqagz5oqhQ==",
+ "79uTykH43voFC3XhHHUzKg==",
+ "P5fucOJhtcRIoElFJS4ffg==",
+ "s8NpalwgPdHPla7Zi9FJ3w==",
+ "8cXqZub6rjgJXmh1CYJBOg==",
+ "tY916jrSySzrL+YTcVmYKQ==",
+ "DRiFNojs7wM8sfkWcmLnhQ==",
+ "wqUJ1Gq1Yz2cXFkbcCmzHQ==",
+ "0u+0WHr7WI6IlVBBgiRi6w==",
+ "GCYI9Dn1h3gOuueKc7pdKA==",
+ "nVDxVhaa2o38gd1XJgE3aw==",
+ "5I/heFSQG/UpWGx0uhAqGQ==",
+ "1PvTn90xwZJPoVfyT5/uIQ==",
+ "jHOoSl3ldFYr9YErEBnD3w==",
+ "swJhrPwllq5JORWiP5EkDA==",
+ "tj2rWvF2Fl+XIccctj8Mhw==",
+ "QvYZxsLdu+3nV/WhY1DsYg==",
+ "fKalNdhsyxTt1w08bv9fJA==",
+ "CHLHizLruvCrVi9chj9sXA==",
+ "sa2DECaqYH1z1/AFhpHi+g==",
+ "LbPp1oL0t3K2BAlIN+l8DA==",
+ "5SbwLDNT6sBOy6nONtUcTg==",
+ "AfVPdxD3FyfwwNrQnVNQ7A==",
+ "jt9Ocr9D8EwGRgrXVz//aQ==",
+ "KkwQL0DeUM3nPFfHb2ej+A==",
+ "WwraoO97OTalvavjUsqhxQ==",
+ "fAKFfwlCOyhtdBK6yNnsNg==",
+ "EqMlrz1to7HG4GIFTPaehQ==",
+ "YmjZJyNfHN5FaTL/HAm8ww==",
+ "L2D7G0btrwxl9V4dP3XM5Q==",
+ "oUqO4HrBvkpSL781qAC9+w==",
+ "c6Yhwy/q3j7skXq52l36Ww==",
+ "FWphIPZMumqnXr1glnbK4w==",
+ "AcKwfS8FRVqb72uSkDNY/Q==",
+ "uSIiF1r9F18avZczmlEuMQ==",
+ "XrFDomoH2qFjQ2jJ2yp9lA==",
+ "N2X7KWekNN+fMmwyXgKD5w==",
+ "IdmcpJXyVDajzeiGZixhSA==",
+ "Wf2olJCYZRGTTZxZoBePuQ==",
+ "oVlG+0rjrg2tdFImxIeVBA==",
+ "7w4PDRJxptG8HMe/ijL6cQ==",
+ "rueNryrchijjmWaA3kljYg==",
+ "ZybIEGf1Rn/26vlHmuMxhw==",
+ "yYVW07lOZHdgtX42xJONIA==",
+ "4ifNsmjYf1iOn2YpMfzihg==",
+ "KTjwL+qswa+Bid8xLdjMTg==",
+ "THfzE2G2NVKKfO+A2TjeFw==",
+ "QoqHzpHDHTwQD5UF30NruQ==",
+ "dTMoNd6DDr1Tu8tuZWLudw==",
+ "wOc4TbwQGUwOC1B3BEZ4OQ==",
+ "gfhkPuMvjoC3CGcnOvki3Q==",
+ "vljJciS+uuIvL7XXm5688g==",
+ "EGLOaMe6Nvzs/cmb7pNpbg==",
+ "oLWWIn/2AbKRHnddr2og9g==",
+ "7l0RMKbONGS/goW/M+gnMQ==",
+ "eFkXKRd2dwu/KWI5ZFpEzw==",
+ "jWsC7kdp2YmIZpfXGUimiA==",
+ "Jcxjli2tcIAjCe+5LyvqdQ==",
+ "MUkRa/PjeWMhbCTq43g6Aw==",
+ "g2nh2xENCFOpHZfdEXnoQA==",
+ "x6M66krXSi0EhppwmDmsxA==",
+ "26Wmdp6SkKN74W0/XPcnmA==",
+ "ycjv4XkS5O7zcF3sqq9MwQ==",
+ "gfnbviaVhKvv1UvlRGznww==",
+ "aIPde9CtyZrhbHLK740bfw==",
+ "0p8YbEMxeb73HbAfvPLQRw==",
+ "Is3uxoSNqoIo5I15z6Z2UQ==",
+ "NZtcY8fIpSKPso/KA6ZfzA==",
+ "iQ304I1hmLZktA1d1cuOJA==",
+ "0QB0OUW5x2JLHfrtmpZQ+w==",
+ "kgyUtd8MFe0tuuxDEUZA9w==",
+ "AcbG0e6xN8pZfYAv7QJe1Q==",
+ "bb/U8UynPHwczew/hxLQxw==",
+ "NuBYjwlxadAH+vLWYRZ3bg==",
+ "Ao1Zc0h5AdSHtYt1caWZnQ==",
+ "FL/j3GJBuXdAo54JYiWklQ==",
+ "E2v8Kk60qVpQ232YzjS2ow==",
+ "zVupSPz7cD0v/mD/eUIIjg==",
+ "sEeblUmISi1HK4omrWuPTA==",
+ "xQpYjaAmrQudWgsdu24J0A==",
+ "vCekQ2nOQKiN/q8Be/qwZg==",
+ "8g08gjG/QtvAYer32xgNAg==",
+ "miiOqnhtef1ODjFzMHnxjA==",
+ "sXlFMSTBFnq0STHj6cS/8w==",
+ "+SclwwY8R2RPrnX54Z+A6w==",
+ "g8TcogVxHpw7uhgNFt5VCQ==",
+ "9viAzLFGYYudBYFu7kFamg==",
+ "BAJ+/jbk2HyobezZyB9LiQ==",
+ "/DJgKE9ouibewuZ2QEnk6w==",
+ "fxg/vQq9WPpmQsqQ4RFYaA==",
+ "lM/EhwTsbivA7MDecaVTPw==",
+ "pVgjGg4TeTNhKimyOu3AAw==",
+ "gYnznEt9r97haD/j2Cko7g==",
+ "/ngbFuKIAVpdSwsA3VxvNw==",
+ "VCL3xfPVCL5RjihQM59fgg==",
+ "eDWsx4isnr2xPveBOGc7Hw==",
+ "FIOCTEbzb2+KMCnEdJ7jZw==",
+ "40HzgVKYnqIb6NJhpSIF0A==",
+ "ccK42Lm8Tsv73YMVZRwL6A==",
+ "MpAwWMt7bcs4eL7hCSLudQ==",
+ "zxsSqovedB3HT99jVblCnQ==",
+ "4erEA42TqGA9K4iFKkxMMA==",
+ "BaRwTrc5ulyKbW4+QqD0dw==",
+ "CT3ldhWpS1SEEmPtjejR/Q==",
+ "lkl6XkrTMUpXi46dPxTPxg==",
+ "3EhLkC9NqD3A6ApV6idmgg==",
+ "fsW2DaKYTCC7gswCT+ByQQ==",
+ "pW4gDKtVLj48gNz6V17QdA==",
+ "KjfL7YyVqmCJGBGDFdJ0gw==",
+ "bGGUhiG9SqJMHQWitXTcYQ==",
+ "8RtLlzkGEiisy1v9Xo0sbw==",
+ "R81DX/5a7DYKkS4CU+TL+w==",
+ "Tu6w6DtX2RJJ3Ym3o3QAWw==",
+ "nx/U4Tode5ILux4DSR+QMg==",
+ "mjQS8CpyGnsZIDOIEdYUxg==",
+ "wJpepvmtQQ3sz3tVFDnFqw==",
+ "a4rPqbDWiMivVzaRxvAj7g==",
+ "6o5g9JfKLKQ2vBPqKs6kjg==",
+ "UzPPFSXgeV7KW4CN5GIQXA==",
+ "NdVyHoTbBhX6Umz/9vbi0g==",
+ "Fzuq+Wg7clo6DTujNrxsSA==",
+ "XXFr0WUuGsH5nXPas7hR3Q==",
+ "JVSLiwurnCelNBiG2nflpQ==",
+ "NiawWuMBDo0Q3P2xK/vnLQ==",
+ "nNaGqigseHw30DaAhjBU3g==",
+ "+edqJYGvcy1AH2mEjJtSIg==",
+ "1WIi4I62GqkjDXOYqHWJfQ==",
+ "rwplpbNJz0ADUHTmzAj15Q==",
+ "iWNlSnwrtCmVF89B+DZqOQ==",
+ "tHDbi43e6k6uBgO0hA+Uiw==",
+ "fHNpW230mNib08aB7IM3XQ==",
+ "OChiB4BzcRE8Qxilu6TgJg==",
+ "d+ctfXU0j07rpRRzb5/HDA==",
+ "GDMqfhPQN0PxfJPnK1Bb9A==",
+ "bLd38ZNkVeuhf0joEAxnBQ==",
+ "nvUKoKfC6j8fz3gEDQrc/w==",
+ "fhcbn9xE/6zobqQ2niSBgA==",
+ "HGxe+5/kkh6R9GXzEOOFHA==",
+ "mPwCyD0yrIDonVi+fhXyEQ==",
+ "5PfGtbH9fmVuNnq83xIIgQ==",
+ "XePy/hhnQwHXFeXUQQ55Vg==",
+ "yfAaL0MMtSXPQ37pBdmHxQ==",
+ "NiQ/m4DZXUbpca9aZdzWAw==",
+ "uT6WRh5UpVdeABssoP2VTg==",
+ "oxoZP897lgMg/KLcZAtkAg==",
+ "oKt57TPe4PogmsGssc3Cbg==",
+ "RxmdoO8ak8y/HzMSIm+yBQ==",
+ "6leyDVmC5jglAa98NQ3+Hg==",
+ "+QosBAnSM2h4lsKuBlqEZw==",
+ "hy303iin+Wm7JA6MeelwiQ==",
+ "m9iuy4UtsjmyPzy6FTTZvw==",
+ "f6Ye5F0Lkn34uLVDCzogFQ==",
+ "iGykaF+h4p46HhrWqL8Ffg==",
+ "LPYFDbTEp5nGtG6uO8epSw==",
+ "t2vWMIh2BvfDSQaz5T1TZw==",
+ "OONAvFS/kmH7+vPhAGTNSg==",
+ "g/z9yk94XaeBRFj4hqPzdw==",
+ "2wesXiib76wM9sqRZ7JYwQ==",
+ "n7h9v2N1gOcvMuBEf8uThw==",
+ "ITYL3tDwddEdWSD6J6ULaA==",
+ "inrUwXyKikpOW0y2Kl1wGw==",
+ "iwKBOGDTFzV4aXgDGfyUkw==",
+ "+fcjH2kZKNj8quOytUk4nQ==",
+ "Srl4HivgHMxMOUHyM3jvNw==",
+ "qngzBJbiTB4fivrdnE5gOg==",
+ "G0MlFNCbRjXk4ekcPO/chQ==",
+ "t+bYn9UqrzKiuxAYGF7RLA==",
+ "RVD3Ij6sRwwxTUDAxwELtA==",
+ "RNdyt6ZRGvwYG5Ws3QTuEA==",
+ "9DRHdyX8ECKHUoEsGuqR4Q==",
+ "oMJLQTH1wW7LvOV0KRx/dw==",
+ "bjLZ7ot/X/vWSVx4EYwMCg==",
+ "+p8pofUlwn8vV6Rp6+sz9g==",
+ "cchuqe+CWCJpoakjHLvUfA==",
+ "NvurnIHin4O+wNP7MnrZ1w==",
+ "RBMv0IxXEO3o7MnV47Bzow==",
+ "xTizUioizbMQxD0T6fy/EQ==",
+ "ZCdad3AwhVArttapWFwT/Q==",
+ "Hy1nqC40l5ItxumkIC2LAA==",
+ "W/5ThNLu43uT1O+fg0Fzwg==",
+ "b3BQG9/9qDNC/bNSTBY/sQ==",
+ "neQoa8pvETr07blVMN3pgA==",
+ "oR8rvIZoeoaZ/ufpo0htfQ==",
+ "zEzWZ6l7EKoVUxvk/l78Mw==",
+ "IHyIeMad23fSDisblwyfpA==",
+ "m6srF+pMehggHB1tdoxlPg==",
+ "kggaIvN2tlbZdZRI8S5Apw==",
+ "2RFaMPlSbVuoEqKXgkIa5A==",
+ "//eHwmDOQRSrv+k9C/k3ZQ==",
+ "X/Gha4Ajjm/GStp/tv+Jvw==",
+ "+H0Rglt/HnhZwdty2hsDHg==",
+ "a1aL8zQ+ie3YPogE3hyFFg==",
+ "HxEU37uBMeiR5y8q/pM42g==",
+ "68nqDtXOuxF7DSw6muEZvg==",
+ "s5+78jS4hQYrFtxqTW3g1Q==",
+ "drfODfDI6GyMW7hzkmzQvA==",
+ "pT1raq2fChffFSIBX3fRiA==",
+ "sfowXUMdN2mCoBVrUzulZg==",
+ "AV/YJfdoDUdRcrXVwinhQg==",
+ "3AKEYQqpkfW7CZMFQZoxOw==",
+ "PHwJ5ZAqqftZ4ypr8H1qiQ==",
+ "AoN/pnK4KEUaGw4V9SFjpg==",
+ "soBA65OmZdfBGJkBmY/4Iw==",
+ "mSstwJq7IkJ0JBJ5T8xDKg==",
+ "h13Xuonj+0dD1xH86IhSyQ==",
+ "HK9xG03FjgCy8vSR+hx8+Q==",
+ "oFanDWdePmmZN0xqwpUukA==",
+ "zCRZgVsHbQZcVMHd9pGD3A==",
+ "EvSB+rCggob2RBeXyDQRvQ==",
+ "tXuu7YpZOuMLTv87NjKerA==",
+ "DJ+a37tCaGF5OgUhG+T0NA==",
+ "KkXlgPJPen6HLxbNn5llBw==",
+ "2W6lz1Z7PhkvObEAg2XKJw==",
+ "n+xYzfKmMoB3lWkdZ+D3rg==",
+ "CPDs+We/1wvsGdaiqxzeCQ==",
+ "2Wvk/kouEEOY0evUkQLhOQ==",
+ "ezsm4aFd6+DO9FUxz0A8Pg==",
+ "9sYLg75/hudZaBA3FrzKHw==",
+ "Pp1ZMxJ8yajdbfKM4HAQxA==",
+ "xiyRfVG0EfBA+rCk+tgWRQ==",
+ "/IarsLzJB8bf0AupJJ+/Eg==",
+ "LJeLdqmriyAQp+QjZGFkdQ==",
+ "IhHyHbHGyQS+VawxteLP0w==",
+ "nGzPc0kI/EduVjiK7bzM6Q==",
+ "m06wctjNc3o7iyBHDMZs2w==",
+ "mSJF9dJnxZ15lTC6ilbJ2A==",
+ "xdmY+qyoxxuRZa9kuNpDEg==",
+ "oNOI17POQCAkDwj6lJsYOA==",
+ "p73gSu4d+4T/ZNNkIv9Nlw==",
+ "vOJ55zFdgPPauPyFYBf01w==",
+ "4A+RHIw+aDzw0rSRYfbc7g==",
+ "/gi3UZmunVOIXhZSktZ8zQ==",
+ "a6vem8n6WmRZAalDrHNP0g==",
+ "kGeXrHEN6o7h5qJYcThCPw==",
+ "wrewZ0hoHODf7qmoGcOd7g==",
+ "Z0sjccxzKylgEiPCFBqPSA==",
+ "LKyOFgUKKGUU/PxpFYMILw==",
+ "L2RofFWDO0fVgSz4D2mtdw==",
+ "KI7tQFYW38zYHOzkKp9/lQ==",
+ "ewe/P3pJLYu/kMb5tpvVog==",
+ "IADk81pIu8NIL/+9Fi94pA==",
+ "0L0FVcH5Dlj3oL8+e9Na7g==",
+ "tdiTXKrkqxstDasT0D5BPA==",
+ "R906Kxp2VFVR3VD+o6Vxcw==",
+ "wc+8ohFWgOF4VlSYiZIGwQ==",
+ "wJKFMqh6MGctWfasjHrPEg==",
+ "UHpge5Bldt9oPGo2oxnYvQ==",
+ "vX7RIhatQeXAMr1+OjzhZw==",
+ "s2AKVTwrY65/SWqQxDGJQg==",
+ "Q4bfQslDSqU64MOQbBQEUw==",
+ "mVT74Eht+gAowINoMKV7IQ==",
+ "EuGWtIbyKToOe6DN3NkVpQ==",
+ "ALlGgVDO8So71ccX0D6u2g==",
+ "Rww3qkF3kWSd+AaMT0kfdw==",
+ "hlvtFGW8r0PkbUAYXEM+Hw==",
+ "Oc3BqTF3ZBW3xE0QsnFn/A==",
+ "3j0kFUZ6g+yeeEljx+WXGg==",
+ "8BLkvEkfnOizJq0OTCYGzw==",
+ "Lqel4GdU0ZkfoJVXI5WC/Q==",
+ "rvE64KQGkVkbl07y7JwBqw==",
+ "HbXv8InyZqFT7i3VrllBgg==",
+ "zwQ/3MzTJ9rfBmrANIh14w==",
+ "gglLMohmJDPRGMY1XKndjQ==",
+ "lyfqic/AbEJbCiw+wA01FA==",
+ "XqUO7ULEYhDOuT/I2J8BOA==",
+ "wPhJcp7U7IVX83szbIOOxQ==",
+ "1gA65t5FiBTEgMELTQFUPQ==",
+ "ll2M0QQzBsj5OFi02fv3Yg==",
+ "wt+qDLU38kzNU75ZYi3Hbw==",
+ "a4EYNljinYTx9vb1VvUA6A==",
+ "T6LA+daQqRI38iDKZTdg1A==",
+ "gwyVIrTk5o0YMKQq4lpJ+Q==",
+ "bPRX2zl+K1S0iWAWUn1DZw==",
+ "KQw25X4LnQ9is+qdqfxo0w==",
+ "6tfM6dx3R5TiVKaqYQjnCg==",
+ "OlwHO6Sg2zIwsCOCRu0HiQ==",
+ "mr1qjhliRfl87wPOrJbFQg==",
+ "8c+lvG5sZNimvx9NKNH3ug==",
+ "5Nk2Z94DhlIdfG5HNgvBbQ==",
+ "F50iXjRo1aSTr37GQQXuJA==",
+ "tfgO55QqUyayjDfQh+Zo1Q==",
+ "h7Fc+eT/GuC8iWI+YTD0UQ==",
+ "3TjntNWtpG7VqBt3729L6Q==",
+ "+DWs0vvFGt6d3mzdcsdsyA==",
+ "VJt2kPVBLEBpGpgvuv1oUw==",
+ "XLq/nWX8lQqjxsK9jlCqUg==",
+ "9s3ar9q32Y5A3tla5GW/2Q==",
+ "51yLpfEdvqXmtB6+q27/AQ==",
+ "AiMtfedwGcddA+XYNc+21g==",
+ "p/48hurJ1kh2FFPpyChzJg==",
+ "CRiL6zpjfznhGXhCIbz8pQ==",
+ "/jDVt9dRIn+o4IQ1DPwbsg==",
+ "UNdKik7Vy23LjjPzEdzNsg==",
+ "Koiog/hpN7ew5kgJbty34A==",
+ "4itEKfbRCJvqlgKnyEdIOQ==",
+ "zi04Yc01ZheuFAQc59E45A==",
+ "etRjRvfL/IwceY/IJ1tgzQ==",
+ "3sNJJIx1NnjYcgJhjOLJOg==",
+ "4yVqq66iHYQjiTSxGgX2oA==",
+ "Q8RVI/kRbKuXa8HAQD7zUA==",
+ "OERGn45uzfDfglzFFn6JAg==",
+ "JGEy6VP3sz3LHiyT2UwNHQ==",
+ "1zDfWw5LdG20ClNP1HYxgw==",
+ "TGB+FIzzKnouLh5bAiVOQg==",
+ "n5GA+pA9mO/f4RN9NL9lNg==",
+ "bUxQBaqKyvlSHcuRL9whjg==",
+ "tOdlnsE3L3XCBDJRmb/OqA==",
+ "XdkxmYYooeDKzy7PXVigBQ==",
+ "PMvG4NqJP76kMRAup6TSZA==",
+ "qpFJZqzkklby+u1UT3c1iA==",
+ "fW3QZyq5UixIA1mP6eWgqQ==",
+ "9nMltdrrBmM5ESBY2FRjGA==",
+ "1Vtrv6QUAfiYQjlLTpNovg==",
+ "ur9JDCVNwzSH4q4ngDlHNQ==",
+ "4u3eyKc+y3uRnkASrgBVUw==",
+ "XddlSluOH6VkR7spFIFmdQ==",
+ "NOmu8oZc6CcKLu+Wfz2YOQ==",
+ "3Ejtsqw3Iep/UQd0tXnSlg==",
+ "y/e3HSdg7T19FanRpJ7+7Q==",
+ "YodhkayN5wsgPZEYN7/KNA==",
+ "pZfn6IiG+V28fN8E2hawDQ==",
+ "jGHMJqbj6X1NdTDyWmXYAQ==",
+ "olTSlmirL9MFhKORiOKYkQ==",
+ "CrJDgdfzOea2M2hVedTrIg==",
+ "fpXijBOM3Ai1RkmHven5Ww==",
+ "eLYKLr4labZeLiRrDJ9mnA==",
+ "9vmJUS7WIVOlhMqwipAknQ==",
+ "G7J/za99BFbAZH+Q+/B8WA==",
+ "Hb+pdSavvJ9lUXkSVZW8Og==",
+ "gTB2zM3RPm27mUQRXc/YRg==",
+ "e5KCqQ/1GAyVMRNgQpYf6g==",
+ "1ApqwW7pE+XUB2Cs2M6y7g==",
+ "/wiA2ltAuWyBhIvQAYBTQw==",
+ "HFCQEiZf7/SNc+oNSkkwlA==",
+ "JFi6N1PlrpKaYECOnI7GFg==",
+ "E4ojRDwGsIiyuxBuXHsKBA==",
+ "+25t/2lo0FUEtWYK8LdQZQ==",
+ "up2MVDi9ve+s83/nwNtZ7Q==",
+ "cXpfd6Io6Glj2/QzrDMCvA==",
+ "DCvI9byhw0wOFwF1uP6xIQ==",
+ "PibGJQNw7VHPTgqeCzGUGA==",
+ "0ZRGz+oj2infCAkuKKuHiQ==",
+ "2QS/6OBA1T01NlIbfkTYJg==",
+ "P14k+fyz0TG9yIPdojp52w==",
+ "g5EzTJ0KA4sO3+Opss3LMg==",
+ "R5oOM58zdbVxFSDQnNWqeA==",
+ "Vg2E5qEDfC+QxZTZDCu9yQ==",
+ "YPgMthbpcBN2CMkugV60hQ==",
+ "gZWTFt5CuLqMz6OhWL+hqQ==",
+ "YrEP9z2WPQ8l7TY1qWncDA==",
+ "7p4NpnoNSQR7ISg+w+4yFg==",
+ "9L6yLO93sRN70+3qq3ObfA==",
+ "QH36wzyIhh6I56Vnx79hRA==",
+ "9DtM1vls4rFTdrSnQ7uWXw==",
+ "ZlOAnCLV1PkR0kb3E+Nfuw==",
+ "9UhKmKtr4vMzXTEn74BEhg==",
+ "Ndx5LDiVyyTz/Fh3oBTgvA==",
+ "mXZ4JeBwT2WJQL4a/Tm4jQ==",
+ "N9nD7BGEM7LDwWIMDB+rEQ==",
+ "dmAfbd9F0OJHRAhNMEkRsA==",
+ "jV/D2B11NLXZRH77sG9lBw==",
+ "1C50kisi9nvyVJNfq2hOEQ==",
+ "NMbAjbnuK7EkVeY3CQI5VA==",
+ "J1nYqJ7tIQK1+a/3sMXI/Q==",
+ "m416yrrAlv+YPClGvGh+qQ==",
+ "rLZII1R6EGus+tYCiUtm6g==",
+ "xktOghh1S9nIX6fXWnT+Ug==",
+ "FcFcn4qmPse5mJCX5yNlsA==",
+ "xAAipGfHTGTjp9Qk1MR8RQ==",
+ "RQOlmzHwQKFpafKPJj0D8w==",
+ "WRjYdKdtnd1G9e/vFXCt0g==",
+ "z0BU//aSjYHAkGGk3ZSGNg==",
+ "M55eersiJuN9v61r8DoAjQ==",
+ "l2mAbuFF3QBIUILDODiUHQ==",
+ "IhpXs1TK7itQ3uTzZPRP5Q==",
+ "t2EkpUsLOEOsrnep0nZSmA==",
+ "lMaO8Yf+6YNowGyhDkPhQA==",
+ "UbSFw5jtyLk5MealqJw++A==",
+ "5u2PdDcIY3RQgtchSGDCGg==",
+ "MQYM3BT77i35LG9HcqxY2Q==",
+ "8AfCSZC0uasVON9Y/0P2Pw==",
+ "evaWFoxZNQcRszIRnxqB+A==",
+ "+8PiQt6O7pJI/nIvQpDaAg==",
+ "eRwaYiog2DdlGQyaltCMJg==",
+ "JyUJEnU6hJu8x2NCnGrYFw==",
+ "l0E0U/CJsyCVSTsXW4Fp+w==",
+ "XV13yK0QypJXmgI+dj4KYw==",
+ "jrRH0aTUYCOpPLZwzwPRfQ==",
+ "N3YDSkBUqSmrmNvZZx4a1Q==",
+ "0yJ7TQYzcp3DXVSvwavr+w==",
+ "rhgtLQh0F9bRA6IllM7AGw==",
+ "IWZnTJ3Hb9qw9HAK/M9gTw==",
+ "izeyFvXOumNgVyLrbKW45g==",
+ "xYD8jrCDmuQna+p1ebnKDQ==",
+ "SOdpdrk2ayeyv0xWdNuy9g==",
+ "HYylUirJRqLm+dkp39fSOQ==",
+ "q4z6A4l3nhX3smTmXr+Sig==",
+ "Zyo0fzewcqXiKe2mAwKx5g==",
+ "LMEtzh0+J27+4zORfcjITw==",
+ "LoUv/f2lcWpjftzpdivMww==",
+ "mXBfDUt/sBW5OUZs2sihvw==",
+ "PggVPQL5YKqSU/1asihcrg==",
+ "mI0eT4Rlr7QerMIngcu/ng==",
+ "NmQrsmb8PVP05qnSulPe5Q==",
+ "TcyyXrSsQsnz0gJ36w4Dxw==",
+ "y4mfEDerrhaqApDdhP5vjA==",
+ "ynaj4XjU27b7XbqPyxI8Ig==",
+ "Ua6aO6HwM+rY4sPR19CNFA==",
+ "3go7bJ9WqH/PPUTjNP3q/Q==",
+ "n1ixvP7SfwYT3L2iWpJg6A==",
+ "W8y32OLHihfeV0XFw7LmOg==",
+ "uzkNhmo2d08tv5AmnyqkoQ==",
+ "hJ8leLNuJ6DK5V8scnDaZQ==",
+ "KodYHHN62zESrXUye7M01g==",
+ "H+yPRiooEh5J7lAJB4RZ7Q==",
+ "dZg5w8rFETMp9SgW7m0gfg==",
+ "LsmsPokAwWNCuC74MaqFCQ==",
+ "1QGhj9NONF2rC44UdO+Izw==",
+ "uwGivY3/C9WK+dirRPJZ4A==",
+ "rXGWY/Gq+ZEsmvBHUfFMmQ==",
+ "j4FBMnNfdBwx0VsDeTvhFg==",
+ "81nkjWtpBhqhvOp6K8dcWg==",
+ "dCDaYYrgASXPMGFRV0RCGg==",
+ "Kj1QI+s9261S3lTtPKd9eg==",
+ "LblwOqNiciHmt2NXjd89tg==",
+ "46piyANQVvvLqcoMq5G8tQ==",
+ "XJihma9zSRrXLC+T+VcFDA==",
+ "K3NBEG8jJTJbSrYSOC3FKw==",
+ "cT3PwwS6ALZA/na9NjtdzA==",
+ "wJ4uCrl4DPg70ltw1dZO3w==",
+ "JATLdpQm//SQnkyCfI5x7Q==",
+ "X1PaCfEDScclLtOTiF5JUw==",
+ "444F9T6Y7J67Y9sULG81qg==",
+ "8JVHFRwAd/SCLU0CRJYofg==",
+ "aLh1XEUrfR9W82gzusKcOg==",
+ "U+bB5NjFIuQr/Y5UpXHwxA==",
+ "Egs14xVbRWjfBBX7X5Z60g==",
+ "KSorNz/PLR/YYkxaj1fuqw==",
+ "RDgGGxTtcPvRg/5KRRlz4w==",
+ "5T39s5CtSrK5awMPUcEWJg==",
+ "+PUVXkoTqHxJHO18z4KMfw==",
+ "Bvk8NX4l6WktLcRDRKsK/A==",
+ "kNGIV3+jQmJlZDTXy1pnyA==",
+ "E3jMjAgXwvwR8PA53g4+PQ==",
+ "MbI04HlTGCoc/6WDejwtaQ==",
+ "aEnHUfn7UE/Euh6jsMuZ7g==",
+ "z4Bft++f72QeDh4PWGr/sw==",
+ "1lCcQWGDePPYco4vYrA5vw==",
+ "iu5csar0IQQBOTgw5OvJwQ==",
+ "raKMXnnX6PFFsbloDqyVzQ==",
+ "uPnL9tboMZo0Kl2fe24CmA==",
+ "8OFxXwnPmrogpNoueZlC4Q==",
+ "V6CRKrKezPwsRdbm0DJ2Yg==",
+ "xmGgK3W5y+oCd0K2u8XjZQ==",
+ "Ry3zgZ6KHrpNyb7+Tt2Pkw==",
+ "IwLbkL33z+LdTjaFYh93kg==",
+ "caepyBOAFu0MxbcXrGf6TA==",
+ "iIWxFdolLcnXqIjPMg+5kQ==",
+ "P430CeF2MDkuq11YdjvV8A==",
+ "yCu+DVU/ceMTOZ5h/7wQTg==",
+ "4mQVNv7FHj+/O6XFqWFt/Q==",
+ "OEJ40VmMDYzc2ESEMontRA==",
+ "D66Suu3tWBD+eurBpPXfjA==",
+ "RNK9G1hfuz3ETY/RmA9+aA==",
+ "BYpHADmEnzBsegdYTv8B5Q==",
+ "DBKrdpCE0awppxST4o/zzg==",
+ "KOmdvm+wJuZ/nT/o1+xOuw==",
+ "gDxqUdxxeXDYhJk9zcrNyA==",
+ "UPzS4LR3p/h0u69+7YemrQ==",
+ "hf9HFxWRNX2ucH8FLS7ytA==",
+ "ozVqYsmUueKifb4lDyVyrg==",
+ "TfHvdbl2M4deg65QKBTPng==",
+ "SzCGM8ypE58FLaR1+1ccxQ==",
+ "3nthUmLZ30HxQrzr2d7xFA==",
+ "1jBaRO8Bg5l6TH7qJ8EPiw==",
+ "eJlcN+gJnqAnctbWSIO9uA==",
+ "G8LFBop8u6IIng+gQuVg3w==",
+ "3JhnM6G4L06NHt31lR0zXA==",
+ "342VOUOxoLHUqtHANt83Hw==",
+ "hRxbdeniAVFgKUgB9Q3Y+g==",
+ "cFFE2R4GztNoftYkqalqUQ==",
+ "YmaksRzoU+OwlpiEaBDYaQ==",
+ "jon1y9yMEGfiIBjsDeeJdA==",
+ "oSnrpW4UmmVXtUGWqLq+tQ==",
+ "zaqyy3GaJ7cp8qDoLJWcTw==",
+ "luO1R8dUM9gy1E2lojRQoA==",
+ "YHM6NNHjmodv+G0mRLK7kw==",
+ "ZSmN8mmI9lDEHkJqBBg0Nw==",
+ "520wTzrysiRi2Td92Zq0HQ==",
+ "RAAw14BA1ws5Wu/rU7oegw==",
+ "vb6Agwzk4JG0Nn7qRPPFMQ==",
+ "joDXdLpXvRjOqkRiYaD/Sw==",
+ "dK2DU3t1ns+DWDwfBvH3SQ==",
+ "gZNJ1Qq6OcnwXqc+jXzMLQ==",
+ "R8ULpSNu9FcCwXZM0QedSg==",
+ "mc45FSMtzdw2PTcEBwHWPw==",
+ "d0qvm3bl38rRCpYdWqolCQ==",
+ "o9tdzmIu+3J/EYU4YWyTkA==",
+ "5eXpiczlRdmqMYSaodOUiQ==",
+ "KYuUNrkTvjUWQovw9dNakA==",
+ "02im2RooJQ/9UfUrh5LO+A==",
+ "kWPUUi7x9kKKa6nJ+FDR5Q==",
+ "6z8CRivao3IMyV4p4gMh7g==",
+ "SmRWEzqddY9ucGAP5jXjAg==",
+ "DJscTYNFPyPmTb57g/1w+Q==",
+ "uOHrw37yF9oLLVd16nUpeg==",
+ "HaIRV9SNPRTPDOSX9sK/bg==",
+ "K4yZNVoqHjXNhrZzz2gTew==",
+ "bTNRjJm+FfSQVfd56nNNqQ==",
+ "x5lyMArsv1MuJmEFlWCnNw==",
+ "cxpZ4bloGv734LBf4NpVhA==",
+ "kUudvRfA33uJDzHIShQd3Q==",
+ "3Wfj05vCLFAB9vII5AU9tw==",
+ "FUQySDFodnRhr+NUsWt0KA==",
+ "eC/RcoCVQBlXdE9WtcgXIw==",
+ "NoX8lkY+kd2GPuGjp+s0tQ==",
+ "EzjbinBHx3Wr08eXpH3HXA==",
+ "0VsaJHR0Ms8zegsCpAKoyg==",
+ "e2xLFVavnZIUUtxJx+qa1g==",
+ "Kt6BTG1zdeBZ3nlVk+BZKQ==",
+ "EUXQZwLgnDG+C8qxVoBNdw==",
+ "0SkC/4PtnX1bMYgD6r6CLA==",
+ "rzj6mjHCcMEouL66083BAg==",
+ "V5HEaY3v9agOhsbYOAZgJA==",
+ "tJt6VDdAPEemBUvnoc4viA==",
+ "g0lWrzEYMntVIahC7i0O2g==",
+ "zCpibjrZOA3FQ4lYt0WoVA==",
+ "4Xh/B3C16rrjbES+FM1W8g==",
+ "GHEdXgGWOeOa6RuPMF0xXg==",
+ "3kREs/qaMX0AwFXN0LO5ow==",
+ "GLDNTSwygNBmuFwCIm7HtA==",
+ "JBkbaBiorCtFq9M9lSUdMg==",
+ "rJCuanCy51ydVD4nInf9IQ==",
+ "OzFRv+PzPqTNmOnvZGoo5g==",
+ "7mxU5fJl/c6dXss9H3vGcQ==",
+ "9J53kk+InE3CKa7cPyCXMw==",
+ "x9TIZ9Ua++3BX+MpjgTuWA==",
+ "h0MH5NGFfChgmRJ3E/R3HQ==",
+ "25w3ZRUzCvJwAVHYCIO5uw==",
+ "1Wc8jQlDSB4Dp32wkL2odw==",
+ "ipPPjxpXHS1tcykXmrHPMQ==",
+ "r95wJtP5rsTExKMS7QhHcw==",
+ "TZT86wXfzFffjt0f95UF5w==",
+ "VpmBstwR7qPVqPgKYQTA3g==",
+ "3++dZXzZ6AFEz7hK+i5hww==",
+ "mAiD16zf+rCc7Qzxjd5buA==",
+ "1JI9bT92UzxI8txjhst9LQ==",
+ "TNyvLixb03aP2f8cDozzfA==",
+ "spHVvA/pc7nF9Q4ON020+w==",
+ "GA8k6GQ20DGduVoC+gieRA==",
+ "T7waQc3PvTFr0yWGKmFQdQ==",
+ "P0Pc8owrqt6spdf7FgBFSw==",
+ "DKApp/alXiaPSRNm3MfSuA==",
+ "UreSZCIdDgloih8KLeX7gg==",
+ "xJi0T+psHOXMivSOVpMWeQ==",
+ "cNsC9bH30eM1EZS6IdEdtQ==",
+ "XjjrIpsmATV/lyln4tPb+g==",
+ "qt5CsMts2aD4lw/4Q6bHYQ==",
+ "h+KRDKIvyVUBmRjv1LcCyg==",
+ "2j83jrPwPfYlpJJ2clEBYQ==",
+ "ZrCezGLz38xKmzAom6yCTQ==",
+ "SEGu+cSbeeeZg4xWwsSErQ==",
+ "Duz/8Ebbd0w6oHwOs0Wnwg==",
+ "Ci7sS7Yi1+IwAM3VMAB4ew==",
+ "DG2Qe2DqPs5MkZPOqX363Q==",
+ "v0Bvws1WYVoEgDt8xmVKew==",
+ "CtDj/h2Q/lRey20G8dzSgA==",
+ "WRoJMO0BCJyn5V6qnpUi4Q==",
+ "RQywrOLZEKw9+kG6qTzr3g==",
+ "mU4CqbAwpwqegxJaOz9ofQ==",
+ "aN5x46Gw1VihRalwCt1CGg==",
+ "U6VQghxOXsydh3Naa5Nz4A==",
+ "YA+zdEC+yEgFWRIgS1Eiqw==",
+ "oPcxgoismve6+jXyIKK6AQ==",
+ "PqLCd/pwc+q5GkL6MB0jTg==",
+ "fHL+fHtDxhALZFb9W/uHuw==",
+ "dhTevyxTYAuKbdLWhG47Kw==",
+ "VllbOAjeW3Dpbj5lp2OSmA==",
+ "3itfXtlLPRmPCSYaSvc39Q==",
+ "GNak/LFeoHWlTdLW1iU4eg==",
+ "HuDuxs2KiGqmeyY1s1PjpQ==",
+ "xs8J3cesq7lDhP/dNltqOw==",
+ "foXSDEUwMhfHWJSmSejsQg==",
+ "6fWom3YoKvW6NIg6y9o9CQ==",
+ "NhZbSq0CjDNOAIvBHBM9zA==",
+ "5w4FbRhWACP7k2WnNitiHg==",
+ "0UeRwDID2RBIikInqFI7uw==",
+ "/y/jHHEpUu5TR+R2o96kXA==",
+ "voO3krg4sdy4Iu+MZEr8+g==",
+ "hdzol5dk//Q6tCm4+OndIA==",
+ "Nc5kiwXCAyjpzt43G5RF1A==",
+ "3UBYBMejKInSbCHRoJJ7dg==",
+ "dRFCIbVu0Y8XbjG5i+UFCQ==",
+ "t8pjhdyNJirkvYgWIO/eKg==",
+ "FAXzjjIr8l1nsQFPpgxM/g==",
+ "SPGpjEJrpflv1hF0qsFlPw==",
+ "9Y1ZmfiHJd9vCiZ6KfO1xQ==",
+ "7Eqzyb+Kep+dIahYJWNNxQ==",
+ "9rL8nC/VbSqrvnUtH9WsxQ==",
+ "H4FZ5Wcnb40hQM1DMGGe8A==",
+ "AjoXWGb/l9xH/hscgEc6kQ==",
+ "6nzFl41uutgDdC30oOeCqg==",
+ "3jo1jRy3MybXtoLR+JIbJw==",
+ "mXdE08dv+OlIhlcqMBH2Gg==",
+ "Ifd7DI6o8N5gnyAKqZTlRw==",
+ "JNUvg/kxL3rdcZnD4IqUxw==",
+ "ry8B+sAHNeFIZHCCDynFyw==",
+ "TXaEd5lIKhzjcncfNcBgSg==",
+ "Mr3ehuDMUimOSn+FlkchdA==",
+ "cwiGhjmX9v8I7E/ekQ0h+g==",
+ "I/r5+1jnqumCPprKC/2BqA==",
+ "S4V3MfGYk8I4fd3WH09yYw==",
+ "A+crVyUeynAkEMYKbnFjZw==",
+ "vtyHcNQPcUTRuZcQvRUX4Q==",
+ "UNKx1ZVv3HNp21zrUSm6ew==",
+ "rsAlvGLv2D0swd6ol3WlvA==",
+ "2qwqb8ENAR2fpQnw55sPDw==",
+ "xBJJuYYnsTJOeFggZSKC4Q==",
+ "omvtZZKruPiEt6fV0YXTdg==",
+ "JZEgKUhUN+USJsvtF4HZOg==",
+ "euG/kpJ5elSDOGNbWWDfNQ==",
+ "DiiVmM6/WNcp0MUjSaFq6w==",
+ "QCNS8gAml1M2pJ+MxZsueg==",
+ "M6+pggFsHfM3alFxcMOFNQ==",
+ "YLoWpDTwXnszEQm8FA164Q==",
+ "N08oUZtlXbQvO9t3vXnGog==",
+ "jkjuJowWuOa4CLY+RZiErQ==",
+ "mPf+S+6oAoVIYEVveaiNFA==",
+ "R0iVyo5qreP/68uZlZphDA==",
+ "GYlqhQgp03B0mXpUhQ+ZCA==",
+ "lQNbmWD7PhwNGye+zbc3GQ==",
+ "cNeaOJEOzUSDdRmenPQyuw==",
+ "Gp66/Txv6ebv5bn85TuQtA==",
+ "xAda6DVkcvvqhI8vWZeGyA==",
+ "Ggk1Qa0lEdAgCXG6SmCkBA==",
+ "MYuO7ZURXtyaf56q7hH4Zw==",
+ "RUIdZRTgJBudWUZQFgiFaQ==",
+ "bgFJxLirUom2zT0h7LdOpw==",
+ "A2gaOpIlrS7TKVQgy9XMSw==",
+ "zevXp0lqqnXv9X6Bgmjtqg==",
+ "a5iuFqWAdFFsRgp7SFYwNg==",
+ "TxTy0TaDsWTcRH3wdBEQLQ==",
+ "jephVdKDeJIhXPrdMOJ4qA==",
+ "C4KdamfqUPuJ3RGFdpIEdw==",
+ "zl6l2Ioz1qovRUIWrSyxVA==",
+ "+gGaDxUe0UnNrf3PPg1qQQ==",
+ "1HgbrlaLMHS6Qj/0kkaJxg==",
+ "eGxTly6Pnu7eV/MKYMmuYw==",
+ "RAMKfnlrzNjpyh2BWt6JHg==",
+ "4pZQm9ogCZ/EAR9pjJm1eA==",
+ "l1zv3erwXIegQFd02NlCag==",
+ "uHGyRZchuA4ulmuD5LqquQ==",
+ "/vFu89tsV+lbcoiqM/XWog==",
+ "63SUgqfQimrmjvy/bEDQ0w==",
+ "JLHuf+FlChFDa9LYfTQ4Eg==",
+ "I+ZnPePTFX8ZODe14bxgyA==",
+ "CtoK1k3U82BkvzuPfQ4pjQ==",
+ "6nqQm4C7y+wZ+qX0kVjwmA==",
+ "+C3kBxRXIjqBk0EJxe3Xfg==",
+ "qVu748pIxEZtiywg4/4qhw==",
+ "07o+sKjjRCYkwy/ACyoYhg==",
+ "CiLF4dkbLURekBcQbwPUVA==",
+ "W/N5/nkp4iQIPYfAagVV7A==",
+ "3PJOphhEjw0E4arTfVVwdg==",
+ "YdMbARHwB+bSOd0PlTlXiA==",
+ "41hbx5Yr7UWxsV6+bWUYUA==",
+ "SqJHXD0MorNwHtHL9TbWLg==",
+ "pWKGUzm/muwOiBtzkRMnRg==",
+ "az9zZ7HTa4FJGRQMcamvEw==",
+ "zavAAN8C9Wo8oBLyztp63Q==",
+ "yBAnPmwrMJ8kpPP292S/Lw==",
+ "E6szQhjuUAz2e0h9ffQfEQ==",
+ "Fs3cQxQyS9kM4T8j5R7rWw==",
+ "GB5fRLZxnjRUfEe0SwcePQ==",
+ "+9OY8xkT9dM/rb2T6ACtOQ==",
+ "If2xFBD1p91iDD7ZrsfgjA==",
+ "QCFfoMhy8EleZAOpfRY88w==",
+ "NobWPk1Z6bHt5s9NHXt/pg==",
+ "nK6T4vV4384OIcqO5tQMhA==",
+ "Zov1EzK+VomiuwT1+ulQ8g==",
+ "pF98OKDvLUlnTzo7wmlpOw==",
+ "Wrq9YDsieAMC3Y2DSY5Rcg=="
+ ]
+}
diff --git a/application/basilisk/base/content/newtab/newTab.js b/application/basilisk/base/content/newtab/newTab.js
new file mode 100644
index 000000000..bbd2ef39d
--- /dev/null
+++ b/application/basilisk/base/content/newtab/newTab.js
@@ -0,0 +1,71 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+var Cu = Components.utils;
+var Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/PageThumbs.jsm");
+Cu.import("resource://gre/modules/BackgroundPageThumbs.jsm");
+Cu.import("resource:///modules/DirectoryLinksProvider.jsm");
+Cu.import("resource://gre/modules/NewTabUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "Rect",
+ "resource://gre/modules/Geometry.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
+ "resource://gre/modules/PrivateBrowsingUtils.jsm");
+
+var {
+ links: gLinks,
+ allPages: gAllPages,
+ linkChecker: gLinkChecker,
+ pinnedLinks: gPinnedLinks,
+ blockedLinks: gBlockedLinks,
+ gridPrefs: gGridPrefs
+} = NewTabUtils;
+
+XPCOMUtils.defineLazyGetter(this, "gStringBundle", function() {
+ return Services.strings.
+ createBundle("chrome://browser/locale/newTab.properties");
+});
+
+function newTabString(name, args) {
+ let stringName = "newtab." + name;
+ if (!args) {
+ return gStringBundle.GetStringFromName(stringName);
+ }
+ return gStringBundle.formatStringFromName(stringName, args, args.length);
+}
+
+function inPrivateBrowsingMode() {
+ return PrivateBrowsingUtils.isContentWindowPrivate(window);
+}
+
+const HTML_NAMESPACE = "http://www.w3.org/1999/xhtml";
+const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+
+const TILES_EXPLAIN_LINK = "https://support.mozilla.org/kb/how-do-tiles-work-firefox";
+const TILES_INTRO_LINK = "https://www.mozilla.org/firefox/tiles/";
+const TILES_PRIVACY_LINK = "https://www.mozilla.org/privacy/";
+
+#include transformations.js
+#include page.js
+#include grid.js
+#include cells.js
+#include sites.js
+#include drag.js
+#include dragDataHelper.js
+#include drop.js
+#include dropTargetShim.js
+#include dropPreview.js
+#include updater.js
+#include undo.js
+#include search.js
+#include customize.js
+
+// Everything is loaded. Initialize the New Tab Page.
+gPage.init();
diff --git a/application/basilisk/base/content/newtab/newTab.xhtml b/application/basilisk/base/content/newtab/newTab.xhtml
new file mode 100644
index 000000000..eef51b4b2
--- /dev/null
+++ b/application/basilisk/base/content/newtab/newTab.xhtml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+ - License, v. 2.0. If a copy of the MPL was not distributed with this
+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
+<!DOCTYPE html [
+ <!ENTITY % newTabDTD SYSTEM "chrome://browser/locale/newTab.dtd">
+ %newTabDTD;
+ <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd">
+ %browserDTD;
+ <!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
+ %globalDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>&newtab.pageTitle;</title>
+
+ <link rel="stylesheet" type="text/css" media="all" href="chrome://global/skin/" />
+ <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/content/contentSearchUI.css" />
+ <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/content/newtab/newTab.css" />
+ <link rel="stylesheet" type="text/css" media="all" href="chrome://browser/skin/newtab/newTab.css" />
+</head>
+
+<body dir="&locale.dir;">
+ <div id="newtab-customize-overlay"></div>
+
+ <div class="newtab-customize-panel-container">
+ <div id="newtab-customize-panel" orient="vertical">
+ <div id="newtab-customize-panel-anchor"></div>
+ <div id="newtab-customize-panel-inner-wrapper">
+ <div id="newtab-customize-title" class="newtab-customize-panel-item">
+ <label>&newtab.customize.cog.title2;</label>
+ </div>
+ <div id="newtab-customize-classic" class="newtab-customize-panel-item selectable">
+ <label>&newtab.customize.classic;</label>
+ </div>
+ <div id="newtab-customize-blank" class="newtab-customize-panel-item selectable">
+ <label>&newtab.customize.blank2;</label>
+ </div>
+ <div id="newtab-customize-learn" class="newtab-customize-panel-item">
+ <label>&newtab.customize.cog.learn;</label>
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <div id="newtab-vertical-margin">
+ <div id="newtab-margin-top"/>
+
+ <div id="newtab-margin-undo-container">
+ <div id="newtab-undo-container" undo-disabled="true">
+ <label id="newtab-undo-label">&newtab.undo.removedLabel;</label>
+ <button id="newtab-undo-button" tabindex="-1"
+ class="newtab-undo-button">&newtab.undo.undoButton;</button>
+ <button id="newtab-undo-restore-button" tabindex="-1"
+ class="newtab-undo-button">&newtab.undo.restoreButton;</button>
+ <button id="newtab-undo-close-button" tabindex="-1" title="&newtab.undo.closeTooltip;"/>
+ </div>
+ </div>
+
+ <div id="newtab-search-container">
+ <div id="newtab-search-form">
+ <div id="newtab-search-icon"/>
+ <input type="text" name="q" value="" id="newtab-search-text"
+ aria-label="&contentSearchInput.label;" maxlength="256"/>
+ <input id="newtab-search-submit" type="button"
+ title="&contentSearchSubmit.tooltip;"/>
+ </div>
+ </div>
+
+ <div id="newtab-horizontal-margin">
+ <div class="newtab-side-margin"/>
+ <div id="newtab-grid">
+ <h1 id="topsites-heading"/>
+ </div>
+ <div class="newtab-side-margin"/>
+ </div>
+
+ <div id="newtab-margin-bottom"/>
+ </div>
+ <input id="newtab-customize-button" type="button" dir="&locale.dir;"
+ value="&#x2699;"
+ title="&newtab.customize.title;"/>
+</body>
+<script type="text/javascript;version=1.8" src="chrome://browser/content/contentSearchUI.js"/>
+<script type="text/javascript;version=1.8" src="chrome://browser/content/newtab/newTab.js"/>
+</html>
diff --git a/application/basilisk/base/content/newtab/page.js b/application/basilisk/base/content/newtab/page.js
new file mode 100644
index 000000000..f7626ced2
--- /dev/null
+++ b/application/basilisk/base/content/newtab/page.js
@@ -0,0 +1,297 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+// The amount of time we wait while coalescing updates for hidden pages.
+const SCHEDULE_UPDATE_TIMEOUT_MS = 1000;
+
+/**
+ * This singleton represents the whole 'New Tab Page' and takes care of
+ * initializing all its components.
+ */
+var gPage = {
+ /**
+ * Initializes the page.
+ */
+ init: function Page_init() {
+ // Add ourselves to the list of pages to receive notifications.
+ gAllPages.register(this);
+
+ // Listen for 'unload' to unregister this page.
+ addEventListener("unload", this, false);
+
+ // XXX bug 991111 - Not all click events are correctly triggered when
+ // listening from xhtml nodes -- in particular middle clicks on sites, so
+ // listen from the xul window and filter then delegate
+ addEventListener("click", this, false);
+
+ // Check if the new tab feature is enabled.
+ let enabled = gAllPages.enabled;
+ if (enabled)
+ this._init();
+
+ this._updateAttributes(enabled);
+
+ // Initialize customize controls.
+ gCustomize.init();
+ },
+
+ /**
+ * Listens for notifications specific to this page.
+ */
+ observe: function Page_observe(aSubject, aTopic, aData) {
+ if (aTopic == "nsPref:changed") {
+ gCustomize.updateSelected();
+
+ let enabled = gAllPages.enabled;
+ this._updateAttributes(enabled);
+
+ // Update thumbnails to the new enhanced setting
+ if (aData == "browser.newtabpage.enhanced") {
+ this.update();
+ }
+
+ // Initialize the whole page if we haven't done that, yet.
+ if (enabled) {
+ this._init();
+ } else {
+ gUndoDialog.hide();
+ }
+ } else if (aTopic == "page-thumbnail:create" && gGrid.ready) {
+ for (let site of gGrid.sites) {
+ if (site && site.url === aData) {
+ site.refreshThumbnail();
+ }
+ }
+ }
+ },
+
+ /**
+ * Updates the page's grid right away for visible pages. If the page is
+ * currently hidden, i.e. in a background tab or in the preloader, then we
+ * batch multiple update requests and refresh the grid once after a short
+ * delay. Accepts a single parameter the specifies the reason for requesting
+ * a page update. The page may decide to delay or prevent a requested updated
+ * based on the given reason.
+ */
+ update(reason = "") {
+ // Update immediately if we're visible.
+ if (!document.hidden) {
+ // Ignore updates where reason=links-changed as those signal that the
+ // provider's set of links changed. We don't want to update visible pages
+ // in that case, it is ok to wait until the user opens the next tab.
+ if (reason != "links-changed" && gGrid.ready) {
+ gGrid.refresh();
+ }
+
+ return;
+ }
+
+ // Bail out if we scheduled before.
+ if (this._scheduleUpdateTimeout) {
+ return;
+ }
+
+ this._scheduleUpdateTimeout = setTimeout(() => {
+ // Refresh if the grid is ready.
+ if (gGrid.ready) {
+ gGrid.refresh();
+ }
+
+ this._scheduleUpdateTimeout = null;
+ }, SCHEDULE_UPDATE_TIMEOUT_MS);
+ },
+
+ /**
+ * Internally initializes the page. This runs only when/if the feature
+ * is/gets enabled.
+ */
+ _init: function Page_init() {
+ if (this._initialized)
+ return;
+
+ this._initialized = true;
+
+ // Set submit button label for when CSS background are disabled (e.g.
+ // high contrast mode).
+ document.getElementById("newtab-search-submit").value =
+ document.body.getAttribute("dir") == "ltr" ? "\u25B6" : "\u25C0";
+
+ if (Services.prefs.getBoolPref("browser.newtabpage.compact")) {
+ document.body.classList.add("compact");
+ }
+
+ // Initialize search.
+ gSearch.init();
+
+ if (document.hidden) {
+ addEventListener("visibilitychange", this);
+ } else {
+ setTimeout(() => this.onPageFirstVisible());
+ }
+
+ // Initialize and render the grid.
+ gGrid.init();
+
+ // Initialize the drop target shim.
+ gDropTargetShim.init();
+
+#ifdef XP_MACOSX
+ // Workaround to prevent a delay on MacOSX due to a slow drop animation.
+ document.addEventListener("dragover", this, false);
+ document.addEventListener("drop", this, false);
+#endif
+ },
+
+ /**
+ * Updates the 'page-disabled' attributes of the respective DOM nodes.
+ * @param aValue Whether the New Tab Page is enabled or not.
+ */
+ _updateAttributes: function Page_updateAttributes(aValue) {
+ // Set the nodes' states.
+ let nodeSelector = "#newtab-grid, #newtab-search-container";
+ for (let node of document.querySelectorAll(nodeSelector)) {
+ if (aValue)
+ node.removeAttribute("page-disabled");
+ else
+ node.setAttribute("page-disabled", "true");
+ }
+
+ // Enables/disables the control and link elements.
+ let inputSelector = ".newtab-control, .newtab-link";
+ for (let input of document.querySelectorAll(inputSelector)) {
+ if (aValue)
+ input.removeAttribute("tabindex");
+ else
+ input.setAttribute("tabindex", "-1");
+ }
+ },
+
+ /**
+ * Handles unload event
+ */
+ _handleUnloadEvent: function Page_handleUnloadEvent() {
+ gAllPages.unregister(this);
+ // compute page life-span and send telemetry probe: using milli-seconds will leave
+ // many low buckets empty. Instead we use half-second precision to make low end
+ // of histogram linear and not lose the change in user attention
+ let delta = Math.round((Date.now() - this._firstVisibleTime) / 500);
+ if (this._suggestedTilePresent) {
+ Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN_SUGGESTED").add(delta);
+ }
+ else {
+ Services.telemetry.getHistogramById("NEWTAB_PAGE_LIFE_SPAN").add(delta);
+ }
+ },
+
+ /**
+ * Handles all page events.
+ */
+ handleEvent: function Page_handleEvent(aEvent) {
+ switch (aEvent.type) {
+ case "load":
+ this.onPageVisibleAndLoaded();
+ break;
+ case "unload":
+ this._handleUnloadEvent();
+ break;
+ case "click":
+ let {button, target} = aEvent;
+ // Go up ancestors until we find a Site or not
+ while (target) {
+ if (target.hasOwnProperty("_newtabSite")) {
+ target._newtabSite.onClick(aEvent);
+ break;
+ }
+ target = target.parentNode;
+ }
+ break;
+ case "dragover":
+ if (gDrag.isValid(aEvent) && gDrag.draggedSite)
+ aEvent.preventDefault();
+ break;
+ case "drop":
+ if (gDrag.isValid(aEvent) && gDrag.draggedSite) {
+ aEvent.preventDefault();
+ aEvent.stopPropagation();
+ }
+ break;
+ case "visibilitychange":
+ // Cancel any delayed updates for hidden pages now that we're visible.
+ if (this._scheduleUpdateTimeout) {
+ clearTimeout(this._scheduleUpdateTimeout);
+ this._scheduleUpdateTimeout = null;
+
+ // An update was pending so force an update now.
+ this.update();
+ }
+
+ setTimeout(() => this.onPageFirstVisible());
+ removeEventListener("visibilitychange", this);
+ break;
+ }
+ },
+
+ onPageFirstVisible: function () {
+ // Record another page impression.
+ Services.telemetry.getHistogramById("NEWTAB_PAGE_SHOWN").add(true);
+
+ for (let site of gGrid.sites) {
+ if (site) {
+ // The site may need to modify and/or re-render itself if
+ // something changed after newtab was created by preloader.
+ // For example, the suggested tile endTime may have passed.
+ site.onFirstVisible();
+ }
+ }
+
+ // save timestamp to compute page life-span delta
+ this._firstVisibleTime = Date.now();
+
+ if (document.readyState == "complete") {
+ this.onPageVisibleAndLoaded();
+ } else {
+ addEventListener("load", this);
+ }
+ },
+
+ onPageVisibleAndLoaded() {
+ // Send the index of the last visible tile.
+ this.reportLastVisibleTileIndex();
+ // Maybe tell the user they can undo an initial automigration
+ this.maybeShowAutoMigrationUndoNotification();
+ },
+
+ reportLastVisibleTileIndex() {
+ let cwu = window.QueryInterface(Ci.nsIInterfaceRequestor)
+ .getInterface(Ci.nsIDOMWindowUtils);
+
+ let rect = cwu.getBoundsWithoutFlushing(gGrid.node);
+ let nodes = cwu.nodesFromRect(rect.left, rect.top, 0, rect.width,
+ rect.height, 0, true, false);
+
+ let i = -1;
+ let lastIndex = -1;
+ let sites = gGrid.sites;
+
+ for (let node of nodes) {
+ if (node.classList && node.classList.contains("newtab-cell")) {
+ if (sites[++i]) {
+ lastIndex = i;
+ if (sites[i].link.targetedSite) {
+ // record that suggested tile is shown to use suggested-tiles-histogram
+ this._suggestedTilePresent = true;
+ }
+ }
+ }
+ }
+
+ DirectoryLinksProvider.reportSitesAction(sites, "view", lastIndex);
+ },
+
+ maybeShowAutoMigrationUndoNotification() {
+ sendAsyncMessage("NewTab:MaybeShowAutoMigrationUndoNotification");
+ },
+};
diff --git a/application/basilisk/base/content/newtab/search.js b/application/basilisk/base/content/newtab/search.js
new file mode 100644
index 000000000..cbbb6e243
--- /dev/null
+++ b/application/basilisk/base/content/newtab/search.js
@@ -0,0 +1,15 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+var gSearch = {
+ init: function () {
+ document.getElementById("newtab-search-submit")
+ .addEventListener("click", e => this._contentSearchController.search(e));
+ let textbox = document.getElementById("newtab-search-text");
+ this._contentSearchController =
+ new ContentSearchUIController(textbox, textbox.parentNode, "newtab", "newtab");
+ },
+};
diff --git a/application/basilisk/base/content/newtab/sites.js b/application/basilisk/base/content/newtab/sites.js
new file mode 100644
index 000000000..9d103ce9b
--- /dev/null
+++ b/application/basilisk/base/content/newtab/sites.js
@@ -0,0 +1,440 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+const THUMBNAIL_PLACEHOLDER_ENABLED =
+ Services.prefs.getBoolPref("browser.newtabpage.thumbnailPlaceholder");
+
+/**
+ * This class represents a site that is contained in a cell and can be pinned,
+ * moved around or deleted.
+ */
+function Site(aNode, aLink) {
+ this._node = aNode;
+ this._node._newtabSite = this;
+
+ this._link = aLink;
+
+ this._render();
+ this._addEventHandlers();
+}
+
+Site.prototype = {
+ /**
+ * The site's DOM node.
+ */
+ get node() { return this._node; },
+
+ /**
+ * The site's link.
+ */
+ get link() { return this._link; },
+
+ /**
+ * The url of the site's link.
+ */
+ get url() { return this.link.url; },
+
+ /**
+ * The title of the site's link.
+ */
+ get title() { return this.link.title || this.link.url; },
+
+ /**
+ * The site's parent cell.
+ */
+ get cell() {
+ let parentNode = this.node.parentNode;
+ return parentNode && parentNode._newtabCell;
+ },
+
+ /**
+ * Pins the site on its current or a given index.
+ * @param aIndex The pinned index (optional).
+ * @return true if link changed type after pin
+ */
+ pin: function Site_pin(aIndex) {
+ if (typeof aIndex == "undefined")
+ aIndex = this.cell.index;
+
+ this._updateAttributes(true);
+ let changed = gPinnedLinks.pin(this._link, aIndex);
+ if (changed) {
+ // render site again to remove suggested/sponsored tags
+ this._render();
+ }
+ return changed;
+ },
+
+ /**
+ * Unpins the site and calls the given callback when done.
+ */
+ unpin: function Site_unpin() {
+ if (this.isPinned()) {
+ this._updateAttributes(false);
+ gPinnedLinks.unpin(this._link);
+ gUpdater.updateGrid();
+ }
+ },
+
+ /**
+ * Checks whether this site is pinned.
+ * @return Whether this site is pinned.
+ */
+ isPinned: function Site_isPinned() {
+ return gPinnedLinks.isPinned(this._link);
+ },
+
+ /**
+ * Blocks the site (removes it from the grid) and calls the given callback
+ * when done.
+ */
+ block: function Site_block() {
+ if (!gBlockedLinks.isBlocked(this._link)) {
+ gUndoDialog.show(this);
+ gBlockedLinks.block(this._link);
+ gUpdater.updateGrid();
+ }
+ },
+
+ /**
+ * Gets the DOM node specified by the given query selector.
+ * @param aSelector The query selector.
+ * @return The DOM node we found.
+ */
+ _querySelector: function Site_querySelector(aSelector) {
+ return this.node.querySelector(aSelector);
+ },
+
+ /**
+ * Updates attributes for all nodes which status depends on this site being
+ * pinned or unpinned.
+ * @param aPinned Whether this site is now pinned or unpinned.
+ */
+ _updateAttributes: function (aPinned) {
+ let control = this._querySelector(".newtab-control-pin");
+
+ if (aPinned) {
+ this.node.setAttribute("pinned", true);
+ control.setAttribute("title", newTabString("unpin"));
+ } else {
+ this.node.removeAttribute("pinned");
+ control.setAttribute("title", newTabString("pin"));
+ }
+ },
+
+ _newTabString: function(str, substrArr) {
+ let regExp = /%[0-9]\$S/g;
+ let matches;
+ while ((matches = regExp.exec(str))) {
+ let match = matches[0];
+ let index = match.charAt(1); // Get the digit in the regExp.
+ str = str.replace(match, substrArr[index - 1]);
+ }
+ return str;
+ },
+
+ _getSuggestedTileExplanation: function() {
+ let targetedName = `<strong> ${this.link.targetedName} </strong>`;
+ let targetedSite = `<strong> ${this.link.targetedSite} </strong>`;
+ if (this.link.explanation) {
+ return this._newTabString(this.link.explanation, [targetedName, targetedSite]);
+ }
+ return newTabString("suggested.button", [targetedName]);
+ },
+
+ /**
+ * Checks for and modifies link at campaign end time
+ */
+ _checkLinkEndTime: function Site_checkLinkEndTime() {
+ if (this.link.endTime && this.link.endTime < Date.now()) {
+ let oldUrl = this.url;
+ // chop off the path part from url
+ this.link.url = Services.io.newURI(this.url, null, null).resolve("/");
+ // clear supplied images - this triggers thumbnail download for new url
+ delete this.link.imageURI;
+ delete this.link.enhancedImageURI;
+ // remove endTime to avoid further time checks
+ delete this.link.endTime;
+ // clear enhanced-content image that may still exist in preloaded page
+ this._querySelector(".enhanced-content").style.backgroundImage = "";
+ gPinnedLinks.replace(oldUrl, this.link);
+ }
+ },
+
+ /**
+ * Renders the site's data (fills the HTML fragment).
+ */
+ _render: function Site_render() {
+ // first check for end time, as it may modify the link
+ this._checkLinkEndTime();
+ // setup display variables
+ let enhanced = gAllPages.enhanced && DirectoryLinksProvider.getEnhancedLink(this.link);
+ let url = this.url;
+ let title = enhanced && enhanced.title ? enhanced.title :
+ this.link.type == "history" ? this.link.baseDomain :
+ this.title;
+ let tooltip = (this.title == url ? this.title : this.title + "\n" + url);
+
+ let link = this._querySelector(".newtab-link");
+ link.setAttribute("title", tooltip);
+ link.setAttribute("href", url);
+ this.node.setAttribute("type", this.link.type);
+
+ let titleNode = this._querySelector(".newtab-title");
+ titleNode.textContent = title;
+ if (this.link.titleBgColor) {
+ titleNode.style.backgroundColor = this.link.titleBgColor;
+ }
+
+ // remove "suggested" attribute to avoid showing "suggested" tag
+ // after site was pinned or dropped
+ this.node.removeAttribute("suggested");
+
+ if (this.link.targetedSite) {
+ if (this.node.getAttribute("type") != "sponsored") {
+ this._querySelector(".newtab-sponsored").textContent =
+ newTabString("suggested.tag");
+ }
+
+ this.node.setAttribute("suggested", true);
+ let explanation = this._getSuggestedTileExplanation();
+ this._querySelector(".newtab-suggested").innerHTML =
+ `<div class='newtab-suggested-bounds'> ${explanation} </div>`;
+ }
+
+ if (this.isPinned())
+ this._updateAttributes(true);
+ // Capture the page if the thumbnail is missing, which will cause page.js
+ // to be notified and call our refreshThumbnail() method.
+ this.captureIfMissing();
+ // but still display whatever thumbnail might be available now.
+ this.refreshThumbnail();
+ },
+
+ /**
+ * Called when the site's tab becomes visible for the first time.
+ * Since the newtab may be preloaded long before it's displayed,
+ * check for changed conditions and re-render if needed
+ */
+ onFirstVisible: function Site_onFirstVisible() {
+ if (this.link.endTime && this.link.endTime < Date.now()) {
+ // site needs to change landing url and background image
+ this._render();
+ }
+ else {
+ this.captureIfMissing();
+ }
+ },
+
+ /**
+ * Captures the site's thumbnail in the background, but only if there's no
+ * existing thumbnail and the page allows background captures.
+ */
+ captureIfMissing: function Site_captureIfMissing() {
+ if (!document.hidden && !this.link.imageURI) {
+ BackgroundPageThumbs.captureIfMissing(this.url);
+ }
+ },
+
+ /**
+ * Refreshes the thumbnail for the site.
+ */
+ refreshThumbnail: function Site_refreshThumbnail() {
+ // Only enhance tiles if that feature is turned on
+ let link = gAllPages.enhanced && DirectoryLinksProvider.getEnhancedLink(this.link) ||
+ this.link;
+
+ let thumbnail = this._querySelector(".newtab-thumbnail.thumbnail");
+ if (link.bgColor) {
+ thumbnail.style.backgroundColor = link.bgColor;
+ }
+ let uri = link.imageURI || PageThumbs.getThumbnailURL(this.url);
+ thumbnail.style.backgroundImage = 'url("' + uri + '")';
+
+ if (THUMBNAIL_PLACEHOLDER_ENABLED &&
+ link.type == "history" &&
+ link.baseDomain) {
+ let placeholder = this._querySelector(".newtab-thumbnail.placeholder");
+ let charCodeSum = 0;
+ for (let c of link.baseDomain) {
+ charCodeSum += c.charCodeAt(0);
+ }
+ const COLORS = 16;
+ let hue = Math.round((charCodeSum % COLORS) / COLORS * 360);
+ placeholder.style.backgroundColor = "hsl(" + hue + ",80%,40%)";
+ placeholder.textContent = link.baseDomain.substr(0,1).toUpperCase();
+ }
+
+ if (link.enhancedImageURI) {
+ let enhanced = this._querySelector(".enhanced-content");
+ enhanced.style.backgroundImage = 'url("' + link.enhancedImageURI + '")';
+
+ if (this.link.type != link.type) {
+ this.node.setAttribute("type", "enhanced");
+ this.enhancedId = link.directoryId;
+ }
+ }
+ },
+
+ _ignoreHoverEvents: function(element) {
+ element.addEventListener("mouseover", () => {
+ this.cell.node.setAttribute("ignorehover", "true");
+ });
+ element.addEventListener("mouseout", () => {
+ this.cell.node.removeAttribute("ignorehover");
+ });
+ },
+
+ /**
+ * Adds event handlers for the site and its buttons.
+ */
+ _addEventHandlers: function Site_addEventHandlers() {
+ // Register drag-and-drop event handlers.
+ this._node.addEventListener("dragstart", this, false);
+ this._node.addEventListener("dragend", this, false);
+ this._node.addEventListener("mouseover", this, false);
+
+ // Specially treat the sponsored icon & suggested explanation
+ // text to prevent regular hover effects
+ let sponsored = this._querySelector(".newtab-sponsored");
+ let suggested = this._querySelector(".newtab-suggested");
+ this._ignoreHoverEvents(sponsored);
+ this._ignoreHoverEvents(suggested);
+ },
+
+ /**
+ * Speculatively opens a connection to the current site.
+ */
+ _speculativeConnect: function Site_speculativeConnect() {
+ let sc = Services.io.QueryInterface(Ci.nsISpeculativeConnect);
+ let uri = Services.io.newURI(this.url, null, null);
+ try {
+ // This can throw for certain internal URLs, when they wind up in
+ // about:newtab. Be sure not to propagate the error.
+ sc.speculativeConnect(uri, null);
+ } catch (e) {}
+ },
+
+ /**
+ * Record interaction with site using telemetry.
+ */
+ _recordSiteClicked: function Site_recordSiteClicked(aIndex) {
+ if (Services.prefs.prefHasUserValue("browser.newtabpage.rows") ||
+ Services.prefs.prefHasUserValue("browser.newtabpage.columns") ||
+ aIndex > 8) {
+ // We only want to get indices for the default configuration, everything
+ // else goes in the same bucket.
+ aIndex = 9;
+ }
+ Services.telemetry.getHistogramById("NEWTAB_PAGE_SITE_CLICKED")
+ .add(aIndex);
+ },
+
+ _toggleLegalText: function(buttonClass, explanationTextClass) {
+ let button = this._querySelector(buttonClass);
+ if (button.hasAttribute("active")) {
+ let explain = this._querySelector(explanationTextClass);
+ explain.parentNode.removeChild(explain);
+
+ button.removeAttribute("active");
+ }
+ else {
+ let explain = document.createElementNS(HTML_NAMESPACE, "div");
+ explain.className = explanationTextClass.slice(1); // Slice off the first character, '.'
+ this.node.appendChild(explain);
+
+ let link = '<a href="' + TILES_EXPLAIN_LINK + '">' +
+ newTabString("learn.link") + "</a>";
+ let type = (this.node.getAttribute("suggested") && this.node.getAttribute("type") == "affiliate") ?
+ "suggested" : this.node.getAttribute("type");
+ let icon = '<input type="button" class="newtab-control newtab-' +
+ (type == "enhanced" ? "customize" : "control-block") + '"/>';
+ explain.innerHTML = newTabString(type + (type == "sponsored" ? ".explain2" : ".explain"), [icon, link]);
+
+ button.setAttribute("active", "true");
+ }
+ },
+
+ /**
+ * Handles site click events.
+ */
+ onClick: function Site_onClick(aEvent) {
+ let action;
+ let pinned = this.isPinned();
+ let tileIndex = this.cell.index;
+ let {button, target} = aEvent;
+
+ // Handle tile/thumbnail link click
+ if (target.classList.contains("newtab-link") ||
+ target.parentElement.classList.contains("newtab-link")) {
+ // Record for primary and middle clicks
+ if (button == 0 || button == 1) {
+ this._recordSiteClicked(tileIndex);
+ action = "click";
+ }
+ }
+ // Handle sponsored explanation link click
+ else if (target.parentElement.classList.contains("sponsored-explain")) {
+ action = "sponsored_link";
+ }
+ else if (target.parentElement.classList.contains("suggested-explain")) {
+ action = "suggested_link";
+ }
+ // Only handle primary clicks for the remaining targets
+ else if (button == 0) {
+ aEvent.preventDefault();
+ if (target.classList.contains("newtab-control-block")) {
+ // Notify DirectoryLinksProvider of suggested tile block, this may
+ // affect if and how suggested tiles are recommended and needs to
+ // be reported before pages are updated inside block() call
+ if (this.link.targetedSite) {
+ DirectoryLinksProvider.handleSuggestedTileBlock();
+ }
+ this.block();
+ action = "block";
+ }
+ else if (target.classList.contains("sponsored-explain") ||
+ target.classList.contains("newtab-sponsored")) {
+ this._toggleLegalText(".newtab-sponsored", ".sponsored-explain");
+ action = "sponsored";
+ }
+ else if (pinned && target.classList.contains("newtab-control-pin")) {
+ this.unpin();
+ action = "unpin";
+ }
+ else if (!pinned && target.classList.contains("newtab-control-pin")) {
+ if (this.pin()) {
+ // suggested link has changed - update rest of the pages
+ gAllPages.update(gPage);
+ }
+ action = "pin";
+ }
+ }
+
+ // Report all link click actions
+ if (action) {
+ DirectoryLinksProvider.reportSitesAction(gGrid.sites, action, tileIndex);
+ }
+ },
+
+ /**
+ * Handles all site events.
+ */
+ handleEvent: function Site_handleEvent(aEvent) {
+ switch (aEvent.type) {
+ case "mouseover":
+ this._node.removeEventListener("mouseover", this, false);
+ this._speculativeConnect();
+ break;
+ case "dragstart":
+ gDrag.start(this, aEvent);
+ break;
+ case "dragend":
+ gDrag.end(this, aEvent);
+ break;
+ }
+ }
+};
diff --git a/application/basilisk/base/content/newtab/transformations.js b/application/basilisk/base/content/newtab/transformations.js
new file mode 100644
index 000000000..f7db0ad84
--- /dev/null
+++ b/application/basilisk/base/content/newtab/transformations.js
@@ -0,0 +1,270 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * This singleton allows to transform the grid by repositioning a site's node
+ * in the DOM and by showing or hiding the node. It additionally provides
+ * convenience methods to work with a site's DOM node.
+ */
+var gTransformation = {
+ /**
+ * Returns the width of the left and top border of a cell. We need to take it
+ * into account when measuring and comparing site and cell positions.
+ */
+ get _cellBorderWidths() {
+ let cstyle = window.getComputedStyle(gGrid.cells[0].node, null);
+ let widths = {
+ left: parseInt(cstyle.getPropertyValue("border-left-width")),
+ top: parseInt(cstyle.getPropertyValue("border-top-width"))
+ };
+
+ // Cache this value, overwrite the getter.
+ Object.defineProperty(this, "_cellBorderWidths",
+ {value: widths, enumerable: true});
+
+ return widths;
+ },
+
+ /**
+ * Gets a DOM node's position.
+ * @param aNode The DOM node.
+ * @return A Rect instance with the position.
+ */
+ getNodePosition: function Transformation_getNodePosition(aNode) {
+ let {left, top, width, height} = aNode.getBoundingClientRect();
+ return new Rect(left + scrollX, top + scrollY, width, height);
+ },
+
+ /**
+ * Fades a given node from zero to full opacity.
+ * @param aNode The node to fade.
+ * @param aCallback The callback to call when finished.
+ */
+ fadeNodeIn: function Transformation_fadeNodeIn(aNode, aCallback) {
+ this._setNodeOpacity(aNode, 1, function () {
+ // Clear the style property.
+ aNode.style.opacity = "";
+
+ if (aCallback)
+ aCallback();
+ });
+ },
+
+ /**
+ * Fades a given node from full to zero opacity.
+ * @param aNode The node to fade.
+ * @param aCallback The callback to call when finished.
+ */
+ fadeNodeOut: function Transformation_fadeNodeOut(aNode, aCallback) {
+ this._setNodeOpacity(aNode, 0, aCallback);
+ },
+
+ /**
+ * Fades a given site from zero to full opacity.
+ * @param aSite The site to fade.
+ * @param aCallback The callback to call when finished.
+ */
+ showSite: function Transformation_showSite(aSite, aCallback) {
+ this.fadeNodeIn(aSite.node, aCallback);
+ },
+
+ /**
+ * Fades a given site from full to zero opacity.
+ * @param aSite The site to fade.
+ * @param aCallback The callback to call when finished.
+ */
+ hideSite: function Transformation_hideSite(aSite, aCallback) {
+ this.fadeNodeOut(aSite.node, aCallback);
+ },
+
+ /**
+ * Allows to set a site's position.
+ * @param aSite The site to re-position.
+ * @param aPosition The desired position for the given site.
+ */
+ setSitePosition: function Transformation_setSitePosition(aSite, aPosition) {
+ let style = aSite.node.style;
+ let {top, left} = aPosition;
+
+ style.top = top + "px";
+ style.left = left + "px";
+ },
+
+ /**
+ * Freezes a site in its current position by positioning it absolute.
+ * @param aSite The site to freeze.
+ */
+ freezeSitePosition: function Transformation_freezeSitePosition(aSite) {
+ if (this._isFrozen(aSite))
+ return;
+
+ let style = aSite.node.style;
+ let comp = getComputedStyle(aSite.node, null);
+ style.width = comp.getPropertyValue("width");
+ style.height = comp.getPropertyValue("height");
+
+ aSite.node.setAttribute("frozen", "true");
+ this.setSitePosition(aSite, this.getNodePosition(aSite.node));
+ },
+
+ /**
+ * Unfreezes a site by removing its absolute positioning.
+ * @param aSite The site to unfreeze.
+ */
+ unfreezeSitePosition: function Transformation_unfreezeSitePosition(aSite) {
+ if (!this._isFrozen(aSite))
+ return;
+
+ let style = aSite.node.style;
+ style.left = style.top = style.width = style.height = "";
+ aSite.node.removeAttribute("frozen");
+ },
+
+ /**
+ * Slides the given site to the target node's position.
+ * @param aSite The site to move.
+ * @param aTarget The slide target.
+ * @param aOptions Set of options (see below).
+ * unfreeze - unfreeze the site after sliding
+ * callback - the callback to call when finished
+ */
+ slideSiteTo: function Transformation_slideSiteTo(aSite, aTarget, aOptions) {
+ let currentPosition = this.getNodePosition(aSite.node);
+ let targetPosition = this.getNodePosition(aTarget.node)
+ let callback = aOptions && aOptions.callback;
+
+ let self = this;
+
+ function finish() {
+ if (aOptions && aOptions.unfreeze)
+ self.unfreezeSitePosition(aSite);
+
+ if (callback)
+ callback();
+ }
+
+ // We need to take the width of a cell's border into account.
+ targetPosition.left += this._cellBorderWidths.left;
+ targetPosition.top += this._cellBorderWidths.top;
+
+ // Nothing to do here if the positions already match.
+ if (currentPosition.left == targetPosition.left &&
+ currentPosition.top == targetPosition.top) {
+ finish();
+ } else {
+ this.setSitePosition(aSite, targetPosition);
+ this._whenTransitionEnded(aSite.node, ["left", "top"], finish);
+ }
+ },
+
+ /**
+ * Rearranges a given array of sites and moves them to their new positions or
+ * fades in/out new/removed sites.
+ * @param aSites An array of sites to rearrange.
+ * @param aOptions Set of options (see below).
+ * unfreeze - unfreeze the site after rearranging
+ * callback - the callback to call when finished
+ */
+ rearrangeSites: function Transformation_rearrangeSites(aSites, aOptions) {
+ let batch = [];
+ let cells = gGrid.cells;
+ let callback = aOptions && aOptions.callback;
+ let unfreeze = aOptions && aOptions.unfreeze;
+
+ aSites.forEach(function (aSite, aIndex) {
+ // Do not re-arrange empty cells or the dragged site.
+ if (!aSite || aSite == gDrag.draggedSite)
+ return;
+
+ batch.push(new Promise(resolve => {
+ if (!cells[aIndex]) {
+ // The site disappeared from the grid, hide it.
+ this.hideSite(aSite, resolve);
+ } else if (this._getNodeOpacity(aSite.node) != 1) {
+ // The site disappeared before but is now back, show it.
+ this.showSite(aSite, resolve);
+ } else {
+ // The site's position has changed, move it around.
+ this._moveSite(aSite, aIndex, {unfreeze: unfreeze, callback: resolve});
+ }
+ }));
+ }, this);
+
+ if (callback) {
+ Promise.all(batch).then(callback);
+ }
+ },
+
+ /**
+ * Listens for the 'transitionend' event on a given node and calls the given
+ * callback.
+ * @param aNode The node that is transitioned.
+ * @param aProperties The properties we'll wait to be transitioned.
+ * @param aCallback The callback to call when finished.
+ */
+ _whenTransitionEnded:
+ function Transformation_whenTransitionEnded(aNode, aProperties, aCallback) {
+
+ let props = new Set(aProperties);
+ aNode.addEventListener("transitionend", function onEnd(e) {
+ if (props.has(e.propertyName)) {
+ aNode.removeEventListener("transitionend", onEnd);
+ aCallback();
+ }
+ });
+ },
+
+ /**
+ * Gets a given node's opacity value.
+ * @param aNode The node to get the opacity value from.
+ * @return The node's opacity value.
+ */
+ _getNodeOpacity: function Transformation_getNodeOpacity(aNode) {
+ let cstyle = window.getComputedStyle(aNode, null);
+ return cstyle.getPropertyValue("opacity");
+ },
+
+ /**
+ * Sets a given node's opacity.
+ * @param aNode The node to set the opacity value for.
+ * @param aOpacity The opacity value to set.
+ * @param aCallback The callback to call when finished.
+ */
+ _setNodeOpacity:
+ function Transformation_setNodeOpacity(aNode, aOpacity, aCallback) {
+
+ if (this._getNodeOpacity(aNode) == aOpacity) {
+ if (aCallback)
+ aCallback();
+ } else {
+ if (aCallback) {
+ this._whenTransitionEnded(aNode, ["opacity"], aCallback);
+ }
+
+ aNode.style.opacity = aOpacity;
+ }
+ },
+
+ /**
+ * Moves a site to the cell with the given index.
+ * @param aSite The site to move.
+ * @param aIndex The target cell's index.
+ * @param aOptions Options that are directly passed to slideSiteTo().
+ */
+ _moveSite: function Transformation_moveSite(aSite, aIndex, aOptions) {
+ this.freezeSitePosition(aSite);
+ this.slideSiteTo(aSite, gGrid.cells[aIndex], aOptions);
+ },
+
+ /**
+ * Checks whether a site is currently frozen.
+ * @param aSite The site to check.
+ * @return Whether the given site is frozen.
+ */
+ _isFrozen: function Transformation_isFrozen(aSite) {
+ return aSite.node.hasAttribute("frozen");
+ }
+};
diff --git a/application/basilisk/base/content/newtab/undo.js b/application/basilisk/base/content/newtab/undo.js
new file mode 100644
index 000000000..b856914d2
--- /dev/null
+++ b/application/basilisk/base/content/newtab/undo.js
@@ -0,0 +1,116 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * Dialog allowing to undo the removal of single site or to completely restore
+ * the grid's original state.
+ */
+var gUndoDialog = {
+ /**
+ * The undo dialog's timeout in miliseconds.
+ */
+ HIDE_TIMEOUT_MS: 15000,
+
+ /**
+ * Contains undo information.
+ */
+ _undoData: null,
+
+ /**
+ * Initializes the undo dialog.
+ */
+ init: function UndoDialog_init() {
+ this._undoContainer = document.getElementById("newtab-undo-container");
+ this._undoContainer.addEventListener("click", this, false);
+ this._undoButton = document.getElementById("newtab-undo-button");
+ this._undoCloseButton = document.getElementById("newtab-undo-close-button");
+ this._undoRestoreButton = document.getElementById("newtab-undo-restore-button");
+ },
+
+ /**
+ * Shows the undo dialog.
+ * @param aSite The site that just got removed.
+ */
+ show: function UndoDialog_show(aSite) {
+ if (this._undoData)
+ clearTimeout(this._undoData.timeout);
+
+ this._undoData = {
+ index: aSite.cell.index,
+ wasPinned: aSite.isPinned(),
+ blockedLink: aSite.link,
+ timeout: setTimeout(this.hide.bind(this), this.HIDE_TIMEOUT_MS)
+ };
+
+ this._undoContainer.removeAttribute("undo-disabled");
+ this._undoButton.removeAttribute("tabindex");
+ this._undoCloseButton.removeAttribute("tabindex");
+ this._undoRestoreButton.removeAttribute("tabindex");
+ },
+
+ /**
+ * Hides the undo dialog.
+ */
+ hide: function UndoDialog_hide() {
+ if (!this._undoData)
+ return;
+
+ clearTimeout(this._undoData.timeout);
+ this._undoData = null;
+ this._undoContainer.setAttribute("undo-disabled", "true");
+ this._undoButton.setAttribute("tabindex", "-1");
+ this._undoCloseButton.setAttribute("tabindex", "-1");
+ this._undoRestoreButton.setAttribute("tabindex", "-1");
+ },
+
+ /**
+ * The undo dialog event handler.
+ * @param aEvent The event to handle.
+ */
+ handleEvent: function UndoDialog_handleEvent(aEvent) {
+ switch (aEvent.target.id) {
+ case "newtab-undo-button":
+ this._undo();
+ break;
+ case "newtab-undo-restore-button":
+ this._undoAll();
+ break;
+ case "newtab-undo-close-button":
+ this.hide();
+ break;
+ }
+ },
+
+ /**
+ * Undo the last blocked site.
+ */
+ _undo: function UndoDialog_undo() {
+ if (!this._undoData)
+ return;
+
+ let {index, wasPinned, blockedLink} = this._undoData;
+ gBlockedLinks.unblock(blockedLink);
+
+ if (wasPinned) {
+ gPinnedLinks.pin(blockedLink, index);
+ }
+
+ gUpdater.updateGrid();
+ this.hide();
+ },
+
+ /**
+ * Undo all blocked sites.
+ */
+ _undoAll: function UndoDialog_undoAll() {
+ NewTabUtils.undoAll(function() {
+ gUpdater.updateGrid();
+ this.hide();
+ }.bind(this));
+ }
+};
+
+gUndoDialog.init();
diff --git a/application/basilisk/base/content/newtab/updater.js b/application/basilisk/base/content/newtab/updater.js
new file mode 100644
index 000000000..2bab74d70
--- /dev/null
+++ b/application/basilisk/base/content/newtab/updater.js
@@ -0,0 +1,177 @@
+#ifdef 0
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#endif
+
+/**
+ * This singleton provides functionality to update the current grid to a new
+ * set of pinned and blocked sites. It adds, moves and removes sites.
+ */
+var gUpdater = {
+ /**
+ * Updates the current grid according to its pinned and blocked sites.
+ * This removes old, moves existing and creates new sites to fill gaps.
+ * @param aCallback The callback to call when finished.
+ */
+ updateGrid: function Updater_updateGrid(aCallback) {
+ let links = gLinks.getLinks().slice(0, gGrid.cells.length);
+
+ // Find all sites that remain in the grid.
+ let sites = this._findRemainingSites(links);
+
+ // Remove sites that are no longer in the grid.
+ this._removeLegacySites(sites, () => {
+ // Freeze all site positions so that we can move their DOM nodes around
+ // without any visual impact.
+ this._freezeSitePositions(sites);
+
+ // Move the sites' DOM nodes to their new position in the DOM. This will
+ // have no visual effect as all the sites have been frozen and will
+ // remain in their current position.
+ this._moveSiteNodes(sites);
+
+ // Now it's time to animate the sites actually moving to their new
+ // positions.
+ this._rearrangeSites(sites, () => {
+ // Try to fill empty cells and finish.
+ this._fillEmptyCells(links, aCallback);
+
+ // Update other pages that might be open to keep them synced.
+ gAllPages.update(gPage);
+ });
+ });
+ },
+
+ /**
+ * Takes an array of links and tries to correlate them to sites contained in
+ * the current grid. If no corresponding site can be found (i.e. the link is
+ * new and a site will be created) then just set it to null.
+ * @param aLinks The array of links to find sites for.
+ * @return Array of sites mapped to the given links (can contain null values).
+ */
+ _findRemainingSites: function Updater_findRemainingSites(aLinks) {
+ let map = {};
+
+ // Create a map to easily retrieve the site for a given URL.
+ gGrid.sites.forEach(function (aSite) {
+ if (aSite)
+ map[aSite.url] = aSite;
+ });
+
+ // Map each link to its corresponding site, if any.
+ return aLinks.map(function (aLink) {
+ return aLink && (aLink.url in map) && map[aLink.url];
+ });
+ },
+
+ /**
+ * Freezes the given sites' positions.
+ * @param aSites The array of sites to freeze.
+ */
+ _freezeSitePositions: function Updater_freezeSitePositions(aSites) {
+ aSites.forEach(function (aSite) {
+ if (aSite)
+ gTransformation.freezeSitePosition(aSite);
+ });
+ },
+
+ /**
+ * Moves the given sites' DOM nodes to their new positions.
+ * @param aSites The array of sites to move.
+ */
+ _moveSiteNodes: function Updater_moveSiteNodes(aSites) {
+ let cells = gGrid.cells;
+
+ // Truncate the given array of sites to not have more sites than cells.
+ // This can happen when the user drags a bookmark (or any other new kind
+ // of link) onto the grid.
+ let sites = aSites.slice(0, cells.length);
+
+ sites.forEach(function (aSite, aIndex) {
+ let cell = cells[aIndex];
+ let cellSite = cell.site;
+
+ // The site's position didn't change.
+ if (!aSite || cellSite != aSite) {
+ let cellNode = cell.node;
+
+ // Empty the cell if necessary.
+ if (cellSite)
+ cellNode.removeChild(cellSite.node);
+
+ // Put the new site in place, if any.
+ if (aSite)
+ cellNode.appendChild(aSite.node);
+ }
+ }, this);
+ },
+
+ /**
+ * Rearranges the given sites and slides them to their new positions.
+ * @param aSites The array of sites to re-arrange.
+ * @param aCallback The callback to call when finished.
+ */
+ _rearrangeSites: function Updater_rearrangeSites(aSites, aCallback) {
+ let options = {callback: aCallback, unfreeze: true};
+ gTransformation.rearrangeSites(aSites, options);
+ },
+
+ /**
+ * Removes all sites from the grid that are not in the given links array or
+ * exceed the grid.
+ * @param aSites The array of sites remaining in the grid.
+ * @param aCallback The callback to call when finished.
+ */
+ _removeLegacySites: function Updater_removeLegacySites(aSites, aCallback) {
+ let batch = [];
+
+ // Delete sites that were removed from the grid.
+ gGrid.sites.forEach(function (aSite) {
+ // The site must be valid and not in the current grid.
+ if (!aSite || aSites.indexOf(aSite) != -1)
+ return;
+
+ batch.push(new Promise(resolve => {
+ // Fade out the to-be-removed site.
+ gTransformation.hideSite(aSite, function () {
+ let node = aSite.node;
+
+ // Remove the site from the DOM.
+ node.parentNode.removeChild(node);
+ resolve();
+ });
+ }));
+ });
+
+ Promise.all(batch).then(aCallback);
+ },
+
+ /**
+ * Tries to fill empty cells with new links if available.
+ * @param aLinks The array of links.
+ * @param aCallback The callback to call when finished.
+ */
+ _fillEmptyCells: function Updater_fillEmptyCells(aLinks, aCallback) {
+ let {cells, sites} = gGrid;
+
+ // Find empty cells and fill them.
+ Promise.all(sites.map((aSite, aIndex) => {
+ if (aSite || !aLinks[aIndex])
+ return null;
+
+ return new Promise(resolve => {
+ // Create the new site and fade it in.
+ let site = gGrid.createSite(aLinks[aIndex], cells[aIndex]);
+
+ // Set the site's initial opacity to zero.
+ site.node.style.opacity = 0;
+
+ // Flush all style changes for the dynamically inserted site to make
+ // the fade-in transition work.
+ window.getComputedStyle(site.node).opacity;
+ gTransformation.showSite(site, resolve);
+ });
+ })).then(aCallback).catch(console.exception);
+ }
+};