diff --git a/docs/WIP_InteractivePlottingBackend.ipynb b/docs/WIP_InteractivePlottingBackend.ipynb
new file mode 100644
index 00000000..2e694b53
--- /dev/null
+++ b/docs/WIP_InteractivePlottingBackend.ipynb
@@ -0,0 +1,1435 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# WIP: An Interactive Plotting Backend for `pyrolite`"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import plotly\n",
+ "import numpy as np\n",
+ "import plotly.graph_objects as go\n",
+ "from pyrolite.data.Aitchison import load_kongite\n",
+ "import matplotlib.colors\n",
+ "import pyrolite.plot\n",
+ "from pyrolite.util.log import Handle\n",
+ "\n",
+ "logger = Handle(__name__, level=\"DEBUG\")\n",
+ "pyrolite_plot_BACKEND = \"matplotlib\"\n",
+ "\n",
+ "\n",
+ "def set_plotting_backend(backend=None):\n",
+ " if backend is not None:\n",
+ " if backend in [\"matplotlib\", \"plotly\"]:\n",
+ " global pyrolite_plot_BACKEND\n",
+ " logger.debug(\"Setting plotting backend to {}\".format(backend))\n",
+ " pyrolite_plot_BACKEND = backend\n",
+ " else:\n",
+ " raise NotImplementedError(\"Backend {} not available.\")\n",
+ "\n",
+ "\n",
+ "class backend:\n",
+ " def __init__(self, backend=None):\n",
+ " self.start = pyrolite_plot_BACKEND\n",
+ " self.backend = backend\n",
+ " set_plotting_backend(self.backend)\n",
+ "\n",
+ " def __enter__(self):\n",
+ " return self\n",
+ "\n",
+ " def __exit__(self, exc_type, exc_value, exc_traceback):\n",
+ " # only reset when changed in the first place?\n",
+ " if self.backend is not None:\n",
+ " set_plotting_backend(self.start)\n"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Plotly Plotting Functions\n",
+ "\n",
+ "* TODO: Make margins smaller\n",
+ "* Enable passing labels to markers\n",
+ "* Make plot variant for density plots"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def to_plotly_color(color, alpha=1):\n",
+ " # note that alpha isn't 255 scaled\n",
+ " return \"rgba\" + str(\n",
+ " tuple([int(i * 255) for i in matplotlib.colors.to_rgb(color)] + [alpha])\n",
+ " )\n",
+ "\n",
+ "\n",
+ "def scatter(df, color=\"black\", alpha=1, **kwargs):\n",
+ " layout = dict(width=600, plot_bgcolor=\"white\")\n",
+ " fig = go.Figure()\n",
+ " marker = dict(color=to_plotly_color(color, alpha=alpha))\n",
+ " traces = [\n",
+ " go.Scatter(\n",
+ " x=df.iloc[:, 0],\n",
+ " y=df.iloc[:, 1],\n",
+ " mode=\"markers\",\n",
+ " marker=marker,\n",
+ " showlegend=False,\n",
+ " text=df.index.map(\"Sample {}\".format),\n",
+ " )\n",
+ " ]\n",
+ " fig.add_traces(traces)\n",
+ " fig.update_layout(layout)\n",
+ " fig.update_xaxes(linecolor=\"black\", mirror=True, title=df.columns[0]) # todo: add this to layout\n",
+ " fig.update_yaxes(linecolor=\"black\", mirror=True, title=df.columns[1]) # todo: add this to layout\n",
+ " return fig\n",
+ "\n",
+ "\n",
+ "def ternary(df, color=\"black\", alpha=1, **kwargs):\n",
+ " layout = dict(width=600, plot_bgcolor=\"white\", ternary= {**{\n",
+ " a: {\n",
+ " \"title\": c,\n",
+ " \"showgrid\": False,\n",
+ " \"linecolor\": \"black\",\n",
+ " }\n",
+ " for a, c in zip([\"aaxis\", \"baxis\", \"caxis\"], df.columns)\n",
+ " }, \"bgcolor\": \"white\"})\n",
+ " layout.update(kwargs)\n",
+ " marker = {\"color\": to_plotly_color(color, alpha=alpha)}\n",
+ " data = {\n",
+ " \"mode\": \"markers\",\n",
+ " **dict(zip(\"abc\", [df[c] for c in df.columns])),\n",
+ " \"text\": df.index.values,\n",
+ " \"marker\": marker,\n",
+ " }\n",
+ " fig = go.Figure(go.Scatterternary(data))\n",
+ "\n",
+ " fig.update_layout(\n",
+ " layout\n",
+ " )\n",
+ " return fig\n",
+ "\n",
+ "\n",
+ "def spider(df, color=\"black\", unity_line=True, alpha=1, text=None, **kwargs):\n",
+ " layout = dict(width=600, plot_bgcolor=\"white\")\n",
+ " fig = go.Figure()\n",
+ " line = dict(color=to_plotly_color(color, alpha=alpha))\n",
+ " #hovertemplate = \"%{text}
\" if (text is not None) else None\n",
+ " traces = [\n",
+ " go.Scatter(\n",
+ " x=df.columns,\n",
+ " y=row,\n",
+ " mode=\"lines+markers\",\n",
+ " line=line,\n",
+ " showlegend=False,\n",
+ " hoverinfo ='text',\n",
+ " #hovertemplate =hovertemplate if (text is not None) else None,\n",
+ " text = None if text is None else text[idx],\n",
+ " name=\"Sample {}\".format(idx) ,\n",
+ " )\n",
+ " for idx, row in df.iterrows()\n",
+ " ]\n",
+ " if unity_line:\n",
+ " traces += [\n",
+ " go.Scatter(\n",
+ " x=df.columns,\n",
+ " y=np.ones(df.columns.size),\n",
+ " mode=\"lines\",\n",
+ " showlegend=False,\n",
+ " name=None,\n",
+ " line={\"color\": \"black\", \"dash\": \"dot\", \"width\": 0.5},\n",
+ " )]\n",
+ " fig.add_traces(traces)\n",
+ " fig.update_layout(**layout)\n",
+ " fig.update_yaxes(type=\"log\", linecolor=\"black\", mirror=True) # todo: add this to layout\n",
+ " fig.update_xaxes(linecolor=\"black\", mirror=True) # todo: add this to layout\n",
+ " return fig\n"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Interface Switching"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "2024-07-04 16:14:01,480 __main__ - DEBUG: Setting plotting backend to plotly\n",
+ "2024-07-04 16:14:01,481 __main__ - DEBUG: Setting plotting backend to matplotlib\n",
+ "2024-07-04 16:14:01,482 __main__ - DEBUG: Setting plotting backend to plotly\n",
+ "2024-07-04 16:14:01,483 __main__ - DEBUG: Setting plotting backend to matplotlib\n"
+ ]
+ }
+ ],
+ "source": [
+ "with backend(\"plotly\"):\n",
+ " with backend(\"matplotlib\"):\n",
+ " ...\n",
+ " ...\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "logger.setLevel(\"INFO\")"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Some Example Data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/html": [
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " | \n",
+ " A | \n",
+ " B | \n",
+ " C | \n",
+ " D | \n",
+ " E | \n",
+ "
\n",
+ " \n",
+ " Specimen | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ " | \n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " K1 | \n",
+ " 33.5 | \n",
+ " 6.1 | \n",
+ " 41.3 | \n",
+ " 7.1 | \n",
+ " 12.0 | \n",
+ "
\n",
+ " \n",
+ " K2 | \n",
+ " 47.6 | \n",
+ " 14.9 | \n",
+ " 16.1 | \n",
+ " 14.8 | \n",
+ " 6.6 | \n",
+ "
\n",
+ " \n",
+ " K3 | \n",
+ " 52.7 | \n",
+ " 23.9 | \n",
+ " 6.0 | \n",
+ " 8.7 | \n",
+ " 8.7 | \n",
+ "
\n",
+ " \n",
+ " K4 | \n",
+ " 44.5 | \n",
+ " 24.2 | \n",
+ " 10.7 | \n",
+ " 11.9 | \n",
+ " 8.7 | \n",
+ "
\n",
+ " \n",
+ " K5 | \n",
+ " 42.3 | \n",
+ " 47.6 | \n",
+ " 0.6 | \n",
+ " 4.1 | \n",
+ " 5.4 | \n",
+ "
\n",
+ " \n",
+ "
\n",
+ "
"
+ ],
+ "text/plain": [
+ " A B C D E\n",
+ "Specimen \n",
+ "K1 33.5 6.1 41.3 7.1 12.0\n",
+ "K2 47.6 14.9 16.1 14.8 6.6\n",
+ "K3 52.7 23.9 6.0 8.7 8.7\n",
+ "K4 44.5 24.2 10.7 11.9 8.7\n",
+ "K5 42.3 47.6 0.6 4.1 5.4"
+ ]
+ },
+ "execution_count": 8,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "from pyrolite.util.synthetic import example_spider_data\n",
+ "\n",
+ "ree_df = example_spider_data(\n",
+ " noise_level=0.05,\n",
+ " size=100,\n",
+ " start=\"DMM_WH2005\",\n",
+ " norm_to=\"Chondrite_PON\",\n",
+ " offsets={\"Eu\": 0.2},\n",
+ ").pyrochem.REE\n",
+ "df = load_kongite()\n",
+ "df.head()"
+ ]
+ },
+ {
+ "attachments": {},
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Bivariate Scatter"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 9,
+ "metadata": {},
+ "output_type": "execute_result"
+ },
+ {
+ "data": {
+ "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjQAAAGxCAYAAAB1Hiz1AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAAAleUlEQVR4nO3dfWxUZd7/8c/w0KHVdhSFGRqq1LUxWIRVMNDq2rrYLsTwoMZ9AAXXXYMBXCvZwFYTGcmmFczd4KbKBk3UxiD7hyJd7xVpohZ3W+8tuF1x3AWNRbuLYxeCMxXrVNrz+8Od+fVhWlrozDnXzPuVnOCcc2b4Dkc4n17nenBZlmUJAADAYOPsLgAAAOB8EWgAAIDxCDQAAMB4BBoAAGA8Ag0AADAegQYAABiPQAMAAIw3we4CkqG3t1fHjx9Xdna2XC6X3eUAAIARsCxLnZ2dys3N1bhxw7fBpEWgOX78uPLy8uwuAwAAnIP29nZNnz592HPSItBkZ2dL+u4PJCcnx+ZqAADASITDYeXl5cXu48NJi0ATfcyUk5NDoAEAwDAj6S5Cp2AAAGA8Ag0AADAegQYAABiPQAMAAIxHoAEAAMYj0AAAAOMRaAAAgPEINAAAwHgEGgAAYDwCzRjo6u6xuwQAANIageY81TUfU+HmfaprPmZ3KQAApK20WMspUeqaj+nRvQFJiv26qmiGjRUBAJCeaKE5R33DTNSjewO01AAAYAMCzTmIF2aiCDUAACQfgWaUurp75K+PH2ai/PUBOgoDAJBEBJpRyswYL//SwmHP8S8tVGbG+CRVBAAACDTnYFXRDG1ZFj/UbFlWSMdgAACSjEBzjuKFGsIMAAD2YNj2eYiGF399QP6lhBkAAOxCoDlPq4pm6M65efSZAQDARjxyGgOEGQAA7EWgAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAINAAAwHoEGAAAYj0ADAACMR6ABAADGI9AAAADjEWgAAIDxCDQAAMB4BBoAAGA8Ag0AADAegQYAABiPQAMAAIxHoAEAAMYj0AAAAOMRaAAAgPEcEWj+/e9/66677tIll1yirKwsff/739ehQ4dixy3Lkt/vV25urjIzM1VaWqpAIGBjxQAAwElsDzSnTp3SDTfcoIkTJ+r111/Xhx9+qP/5n//RRRddFDtn27ZtqqmpUW1trVpaWuTz+VRWVqbOzk77CgcAAI7hsizLsrOA3/zmN/rLX/6id955J+5xy7KUm5uriooKbdq0SZIUiUTk9Xq1detWrVmz5qy/RzgclsfjUSgUUk5OzpjWDwAAEmM092/bW2jq6+s1b9483XnnnZo6daquvfZaPfPMM7HjbW1tCgaDKi8vj+1zu90qKSlRU1NT3M+MRCIKh8P9NgAAkLpsDzSffPKJduzYoYKCAr3xxhu6//779atf/Up1dXWSpGAwKEnyer393uf1emPHBqqurpbH44lteXl5if0SAADAVrYHmt7eXl133XWqqqrStddeqzVr1ui+++7Tjh07+p3ncrn6vbYsa9C+qMrKSoVCodjW3t6esPoBAID9bA8006ZN09VXX91v38yZM/XZZ59Jknw+nyQNao3p6OgY1GoT5Xa7lZOT028DAACpy/ZAc8MNN+jIkSP99h09elSXX365JCk/P18+n08NDQ2x493d3WpsbFRxcXFSawUAAM40we4CHnroIRUXF6uqqko//vGP9de//lU7d+7Uzp07JX33qKmiokJVVVUqKChQQUGBqqqqlJWVpRUrVthcPQAAcALbA83111+vPXv2qLKyUlu2bFF+fr62b9+ulStXxs7ZuHGjurq6tHbtWp06dUrz58/X/v37lZ2dbWPlAADAKWyfhyYZmIcGAADzGDUPDQAAwPki0AAAAOMRaAAAgPEINAAAwHgEGgAAYDwCDQAAMB6BBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAINAAAwHoEGAAAYj0ADAACMR6ABAADGI9AAAADjEWgAAIDxCDQAAMB4BBoAAGA8Ag0AADAegQYAABiPQAMAAIxHoAEAAMYj0AAAAOMRaAAAgPEINAAAwHgEGgAAYDwCDQAAMB6BBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAINAAAwHoEGAAAYj0ADAACMR6ABAADGsz3Q+P1+uVyufpvP54sdtyxLfr9fubm5yszMVGlpqQKBgI0VAwAAp7E90EhSYWGhPv/889h2+PDh2LFt27appqZGtbW1amlpkc/nU1lZmTo7O22sGAAAOMkEuwuQpAkTJvRrlYmyLEvbt2/XI488ottvv12S9MILL8jr9WrXrl1as2ZN3M+LRCKKRCKx1+FwODGFAwAAR3BEC81HH32k3Nxc5efn66c//ak++eQTSVJbW5uCwaDKy8tj57rdbpWUlKipqWnIz6uurpbH44lteXl5Cf8OAADAPrYHmvnz56uurk5vvPGGnnnmGQWDQRUXF+vkyZMKBoOSJK/X2+89Xq83diyeyspKhUKh2Nbe3p7Q7wAAAOxl+yOnxYsXx/77mmuuUVFRkb73ve/phRde0IIFCyRJLper33ssyxq0ry+32y23252YggEAgOPY3kIz0AUXXKBrrrlGH330UaxfzcDWmI6OjkGtNgAAIH05LtBEIhH94x//0LRp05Sfny+fz6eGhobY8e7ubjU2Nqq4uNjGKgEAgJPY/sjp17/+tZYsWaLLLrtMHR0d+u1vf6twOKzVq1fL5XKpoqJCVVVVKigoUEFBgaqqqpSVlaUVK1bYXToAAHAI2wPNv/71L/3sZz/TiRMnNGXKFC1YsEDvvvuuLr/8cknSxo0b1dXVpbVr1+rUqVOaP3++9u/fr+zsbJsrBwAATuGyLMuyu4hEC4fD8ng8CoVCysnJsbscAAAwAqO5fzuuDw0AAMBoEWgAAIDxCDQAAMB4BBqH6urusbsEAACMQaBxoLrmYyrcvE91zcfsLgUAACPYPmwb/dU1H9OjewOSFPt1VdEMGysCAMD5aKFxkL5hJurRvQFaagAAOAsCjUPECzNRhBoAAIZHoHGAru4e+evjh5kof32AjsIAAAyBQOMAmRnj5V9aOOw5/qWFyswYn6SKAAAwC4HGIVYVzdCWZfFDzZZlhXQMBgBgGAQaB4kXaggzAACcHcO2HSYaXvz1AfmXEmYAABgJAo0DrSqaoTvn5tFnBgCAEeKRk0MRZgAAGDkCDQAAMB6BBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAJNmunq7rG7BAAAxhyBJo3UNR9T4eZ9qms+ZncpAACMKdZyShN1zcf06N6AJMV+ZeFLAECqoIUmDfQNM1GP7g3QUgMASBkEmhQXL8xEEWoAAKmCQJPCurp75K+PH2ai/PUBOgoDAIxHoElhmRnj5V9aOOw5/qWFyswYn6SKAABIDAJNiltVNENblsUPNVuWFdIxGACQEgg0aSBeqCHMAABSCYEmRQ3sFxMNNeNchBkAQOoh0KSgoSbQW1U0Q4HHFhFmAAAph4n1UszZJtCjAzAAIBXRQpNCmEAPAJCuCDQpggn0AADpjECTAphADwCQ7gg0KYAJ9AAA6Y5AkyKYQA8AkM4cFWiqq6vlcrlUUVER22dZlvx+v3Jzc5WZmanS0lIFAsM/XklXTKAHAEhXjgk0LS0t2rlzp2bPnt1v/7Zt21RTU6Pa2lq1tLTI5/OprKxMnZ2dNlXqbEygBwBIR44INF999ZVWrlypZ555RhdffHFsv2VZ2r59ux555BHdfvvtmjVrll544QV9/fXX2rVrl40VOxsT6AEA0o0jAs26det066236pZbbum3v62tTcFgUOXl5bF9brdbJSUlampqGvLzIpGIwuFwvy3d0AEYAJBObJ8pePfu3XrvvffU0tIy6FgwGJQkeb3efvu9Xq8+/fTTIT+zurpajz322NgWCgAAHMvWFpr29nY9+OCDevHFFzVp0qQhz3O5XP1eW5Y1aF9flZWVCoVCsa29vX3MagYAAM5jawvNoUOH1NHRoblz58b29fT06MCBA6qtrdWRI0ckfddSM23atNg5HR0dg1pt+nK73XK73YkrHAAAOIqtLTQLFy7U4cOH1draGtvmzZunlStXqrW1VVdccYV8Pp8aGhpi7+nu7lZjY6OKi4ttrBwAADiJrS002dnZmjVrVr99F1xwgS655JLY/oqKClVVVamgoEAFBQWqqqpSVlaWVqxYYUfJAADAgWzvFHw2GzduVFdXl9auXatTp05p/vz52r9/v7Kzs+0uDQAAOITLsizL7iISLRwOy+PxKBQKKScnx+5yAADACIzm/u2IeWgAAADOB4EGAAAYj0ADAACMR6ABAADGI9AAAADjEWgAAIDxCDQAAMB4BBoAAGA8Ag0AADAegQYAABiPQAMAAIxHoAEAAMYj0AAAAOMRaAAAgPEINAAAwHgEGgAAYDwCDQAAMB6BBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAINAAAw3ogDzalTp3THHXfotddeG/Kc1157TXfccYdOnjw5JsUBAACMxIgDzbPPPqu///3vWrRo0ZDnLFq0SIcPH9ZTTz01JsUBAACMxIgDze7du3XfffdpwoQJQ54zYcIE3Xfffaqvrx+T4gAAAEZixIHm6NGjmjdv3lnPu+6663T06NHzKgoAAGA0Rhxozpw5o4kTJ571vIkTJ+rbb789r6IAAABGY8SBZtq0afrwww/Pel4gEJDP5zuvogAAAEZjxIGmpKRETz/99LCtL99++6127Nihm2++eUyKAwAAGIkRB5qHHnpI//znP3Xbbbfp+PHjg44fP35cy5cv15EjR/TQQw+NaZEAAADDGXrI0gCzZ8/WU089pbVr1yo/P19z585Vfn6+JKmtrU2HDh1Sb2+vduzYoWuuuSZhBQMAAAzksizLGs0bmpubVVVVpbfeektff/21JCkrK0sLFy5UZWWlFixYkJBCz0c4HJbH41EoFFJOTo7d5QAAgBEYzf171IEmqre3VydOnJAkXXrppRo3zrmrKBBoAAAwz2ju3yN+5DTQuHHjNHXq1HN9O9JEV3ePMjPG210GACDFObdZBcaraz6mws37VNd8zO5SAAAp7pxbaIDh1DUf06N7A5IU+3VV0QwbKwIApDJaaDDm+oaZqEf3BmipAQAkDIEGYypemIki1AAAEsX2QLNjxw7Nnj1bOTk5ysnJUVFRkV5//fXYccuy5Pf7lZubq8zMTJWWlioQiH/DhL26unvkrx/+2vjrA+rq7klSRQCAdGF7oJk+fboef/xxHTx4UAcPHtQPf/hDLVu2LBZatm3bppqaGtXW1qqlpUU+n09lZWXq7Oy0uXIMlJkxXv6lhcOe419ayKgnAMCYO+d5aBJp8uTJeuKJJ3TvvfcqNzdXFRUV2rRpkyQpEonI6/Vq69atWrNmTdz3RyIRRSKR2OtwOKy8vDzmoUmSoR47bVlWSMdgAMCIjWYeGttbaPrq6enR7t27dfr0aRUVFamtrU3BYFDl5eWxc9xut0pKStTU1DTk51RXV8vj8cS2vLy8ZJSP/1pVNENblvVvqSHMAAASyRGB5vDhw7rwwgvldrt1//33a8+ePbr66qsVDAYlSV6vt9/5Xq83diyeyspKhUKh2Nbe3p7Q+jFYNNSMcxFmAACJ54h5aK666iq1trbqyy+/1Msvv6zVq1ersbExdtzlcvU737KsQfv6crvdcrvdCasXI7OqaIbunJtHnxkAQMI5ooUmIyNDV155pebNm6fq6mrNmTNHTz75pHw+nyQNao3p6OgY1GoDZyLMAACSwRGBZiDLshSJRJSfny+fz6eGhobYse7ubjU2Nqq4uNjGCgEAgJPY/sjp4Ycf1uLFi5WXl6fOzk7t3r1bb7/9tvbt2yeXy6WKigpVVVWpoKBABQUFqqqqUlZWllasWGF36QAAwCFsDzRffPGF7r77bn3++efyeDyaPXu29u3bp7KyMknSxo0b1dXVpbVr1+rUqVOaP3++9u/fr+zsbJsrBwAATuHIeWjG2mjGsQMAAGcwdh4aAACAc0GgAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAINAAAwHoEGAAAYj0ADAACMR6ABAADGI9AAAADjEWgAAIDxCDQAAMB4BBoAAGA8Ag0AADAegQYAABiPQAMAAIxHoAEAAMYj0AAAAOMRaAAAgPEINAAAwHgEGgAAYDwCDQAAMB6BBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAINAAAwHoEGAAAYj0ADAACMR6ABAADGI9AAAADjEWgAAIDxCDQAAMB4BBoAAGA8Ag0AADAegQYAABjP9kBTXV2t66+/XtnZ2Zo6daqWL1+uI0eO9DvHsiz5/X7l5uYqMzNTpaWlCgQCNlUMAACcxvZA09jYqHXr1undd99VQ0ODzpw5o/Lycp0+fTp2zrZt21RTU6Pa2lq1tLTI5/OprKxMnZ2dNlYOAACcwmVZlmV3EX395z//0dSpU9XY2KibbrpJlmUpNzdXFRUV2rRpkyQpEonI6/Vq69atWrNmzVk/MxwOy+PxKBQKKScnJ9FfAWmiq7tHmRnj7S4DAFLWaO7ftrfQDBQKhSRJkydPliS1tbUpGAyqvLw8do7b7VZJSYmamprifkYkElE4HO63AWOprvmYCjfvU13zMbtLAQDIYYHGsixt2LBBN954o2bNmiVJCgaDkiSv19vvXK/XGzs2UHV1tTweT2zLy8tLbOFIK3XNx/To3oB6LenRvQFCDQA4gKMCzfr16/X+++/rpZdeGnTM5XL1e21Z1qB9UZWVlQqFQrGtvb09IfUi/UTDTF+EGgCw3wS7C4h64IEHVF9frwMHDmj69Omx/T6fT9J3LTXTpk2L7e/o6BjUahPldrvldrsTWzDSTrwwExXdv6poRhIrAgBE2d5CY1mW1q9fr1deeUVvvvmm8vPz+x3Pz8+Xz+dTQ0NDbF93d7caGxtVXFyc7HKRZrq6e2K/+uuHnyrAXx+InQ8ASC7bA826dev04osvateuXcrOzlYwGFQwGFRXV5ek7x41VVRUqKqqSnv27NEHH3yge+65R1lZWVqxYoXN1SOV9e34m5kxXv6lhcOe719ayKgnALCJ7Y+cduzYIUkqLS3tt/+5557TPffcI0nauHGjurq6tHbtWp06dUrz58/X/v37lZ2dneRqkS76Pl4a+Dgp3mOnLcsKedwEADZy3Dw0icA8NBiNofrKREPLwOOEGQBIjNHcv21voQGcZDQdf/31AfmXEmYAwAlooQH+q6u7R4Wb96l3mL8R41xS4LFFyswYz0zBAJBgRs8UDNhltB1/nR5mGHEFIJ0QaIA+VhXN0JZl8UONSX1lWJoBQLqhDw0wQLzRTKaFmaFGaAFAqiLQAHGY2vF3qKUZJEINgNRGoAGGsKpohu6cm+f4vjJRLM0AIJ3RhwYYhilhhqUZAKQ7Ag1wDpwWDFiaAUC6I9AAo+TUEUSpMkILAM4FfWiAUXD6CCLTR2gBwLki0AAjZMoIIlNHaAHA+SDQACNg2ggi00ZoAcD5og8NcBamjiAizABIJwQa4CwYQQQAzkegAUaAEUQA4GwEGmCE4oUawgwAOAOdgoFRYAQRADgTgQYYJUYQAYDz8MgJOAeEGQBwFgINAAAwHoEGQIzT5tIBgJEi0ACQ5NxFNwFgJOgUDMDxi24CwNnQQgOkuaEW3aSlBoBJCDRAGjvbopuEGgCmINAAacrURTcBIB4CDZCmWHQTQCoh0ABpjEU3AaQKAg2Q5lh0E0AqYNg2ABbdBGA8Ag0ASSy6CcBsPHICEEOYAWAqAg0AADAegQYAABiPQAMAAIxHoAEM4rRZe5NZj9O+OwBnIdAAhqhrPqbCzfscs77SWNczXGBx2ncH4DwEGsAA0UUkey1nLBo51vUMFVi6unsc990BOBPz0AAOF29F7OhrOybAG+t6+n5e38+paz6mzXsDsgacb+d3B+BcBBrAweKFhyg7buxjXc9Q4ej/Pjmp/z0cHPJ9hBoAA9n+yOnAgQNasmSJcnNz5XK59Oqrr/Y7blmW/H6/cnNzlZmZqdLSUgUC8f9BBVJJV3eP/PXD/7/urw8krbPsWNczXDgaLsycy+8FIPXZHmhOnz6tOXPmqLa2Nu7xbdu2qaamRrW1tWppaZHP51NZWZk6OzuTXCmQXJkZ4+VfGn8l7Cj/0sKkze47lvWMJBydTTK/OwDnc1mWNfARtW1cLpf27Nmj5cuXS/qudSY3N1cVFRXatGmTJCkSicjr9Wrr1q1as2ZN3M+JRCKKRCKx1+FwWHl5eQqFQsrJyUn49wDG0lAtGXatiD1W9QzXQnM2rAYOpIdwOCyPxzOi+7ftLTTDaWtrUzAYVHl5eWyf2+1WSUmJmpqahnxfdXW1PB5PbMvLy0tGuUBCrCqaoS3L+reM2HlDH6t64n3OSBBmAMTj6EATDH73HN3r9fbb7/V6Y8fiqaysVCgUim3t7e0JrRNItOjNf5zLGTf0saonXqi59Rpf3HNdcsZ3B+BMRoxycrlc/V5bljVoX19ut1tutzvRZQFJtapohu6cm+eYfiNjVU80oGzeG9Bj/w0s8wc8jtqyrNBR3x2A8zi6hcbn++4ntYGtMR0dHYNabYB04LQb+ljW0/dnlHgtQE777gCcxdGBJj8/Xz6fTw0NDbF93d3damxsVHFxsY2VARgrQ80EvKpohgKPLeIRE4ARsf2R01dffaWPP/449rqtrU2tra2aPHmyLrvsMlVUVKiqqkoFBQUqKChQVVWVsrKytGLFChurBjAWzjbrMK0yAEbK9kBz8OBB3XzzzbHXGzZskCStXr1azz//vDZu3Kiuri6tXbtWp06d0vz587V//35lZ2fbVTKAMeC0WZABmM1R89AkymjGsQNIvK7uHhVu3qfeYf71GeeSAo8topUGSGMpMw8NgNR0rrMOs9QBgKEQaADYYriJ9eLNN1PXfEyFm/fFOg0DQF+296EBkL6ioWXgnDPxwkz0HPrXAIiHQAPAVtFg4q8PyL90+DATRagBMBCBBoDthpp1mJFQAEaKPjQAHCFeB2B//fCrcfvrA3QUBiCJQAPAoc51JBSA9ESgAeAofVtcRjsSCkD6ItAAcIyBQ7O7unvihhrCDICB6BQMwBEGDs3+v09O6vUPgv1GPg01EgoACDQAbBdvNNP/Hg5K6j+aKd5IKACQCDQAbDbc0OwohmgDOBv60ACwzUiGZkc9ujfAsgcAhkSgAWCbkQzN7suJ8844rR4gXRFoANhquKHZAzlt3hkWzAScg0ADwHYjCTVOG6od7fvTayX3cViiWoRoaYLpCDQAHCEaasa5pFuv8fU75tQw01cyQk2iWoRoaUIqYJQTAMfoOzR7fvMxR847Y9eCmQPn6Rmr3ydRnwskm8uyLMvuIhItHA7L4/EoFAopJyfH7nIAjFBXd4+j+sx0dfeocPM+9Q7zr+Y4lxR4bNGY1j1UiDrflqtEfS4wVkZz/+aREwDHclKYkexZMPNsLULn+pgoUZ8L2IVAAwCjkMwFM0cyT8+5DGVP1OcCdiLQAMAoJWvBzES1CNnR0gQkGp2CAeAcJGvBzOjnjnVfl0R9LmAXAg0AnKNkLZgZL3yMRehI1OcCdiDQAMB5SNZjmUS1CCWrpQlINIZtA4BBEjWU3WlD5AGJYdsAkLISFToIMzAdgQYAABiPQAMAAIxHoAEASGLFbZiNQAMAYMVtGI9AAwBpLrquU6/FOk5OQ6vZyBFoACCNxVukklDjDLSajQ4T6wFAmjrbituSmGjPJn2vDddiZGihAYA0xIrbzkWr2bkh0ABAGmLFbWc6W6sZoWZoBBoASFOrimZoy7L4oYZFKpPP5FYzJ9REoAGANBYv1BBm7GFqq5lTOi/TKRgA0hwrbjtH9M8+3mMnJwZNJ3VeJtAAALSqaIbunJvnuJ/+01G8UOP0MBNlZ6gx5pHT008/rfz8fE2aNElz587VO++8Y3dJAJBSCDPOEX0UOM5lTpiJsqvzshGB5g9/+IMqKir0yCOP6G9/+5t+8IMfaPHixfrss8/sLg0AgIRYVTRDgccWOS7MOLXzshGBpqamRr/4xS/0y1/+UjNnztT27duVl5enHTt22F0aAAAJ48RWM6d2XnZ8oOnu7tahQ4dUXl7eb395ebmamprivicSiSgcDvfbAADA2HDikH/HB5oTJ06op6dHXq+3336v16tgMBj3PdXV1fJ4PLEtLy8vGaUCAJA2nDbk3/GBJsrlcvV7bVnWoH1RlZWVCoVCsa29vT0ZJQIAkFac1HnZ8cO2L730Uo0fP35Qa0xHR8egVpsot9stt9udjPIAAEhrThny7/gWmoyMDM2dO1cNDQ399jc0NKi4uNimqgAAQJTdYUYyoIVGkjZs2KC7775b8+bNU1FRkXbu3KnPPvtM999/v92lAQAABzAi0PzkJz/RyZMntWXLFn3++eeaNWuW/vSnP+nyyy+3uzQAAOAALsuyLLuLSLRwOCyPx6NQKKScnBy7ywEAACMwmvu34/vQAAAAnA2BBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFoAACA8YyYh+Z8RUems+o2AADmiN63RzLDTFoEms7OTkli1W0AAAzU2dkpj8cz7DlpMbFeb2+vjh8/ruzs7CFX6EZyhMNh5eXlqb29nUkOHYDr4RxcC2fhejiDZVnq7OxUbm6uxo0bvpdMWrTQjBs3TtOnT7e7DPSRk5PDPxIOwvVwDq6Fs3A97He2lpkoOgUDAADjEWgAAIDxCDRIKrfbrc2bN8vtdttdCsT1cBKuhbNwPcyTFp2CAQBAaqOFBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFokBAHDhzQkiVLlJubK5fLpVdffbXfccuy5Pf7lZubq8zMTJWWlioQCNhTbIqrrq7W9ddfr+zsbE2dOlXLly/XkSNH+p3D9UiOHTt2aPbs2bHJ2oqKivT666/HjnMd7FVdXS2Xy6WKiorYPq6JOQg0SIjTp09rzpw5qq2tjXt827ZtqqmpUW1trVpaWuTz+VRWVhZbdwtjp7GxUevWrdO7776rhoYGnTlzRuXl5Tp9+nTsHK5HckyfPl2PP/64Dh48qIMHD+qHP/yhli1bFrtBch3s09LSop07d2r27Nn99nNNDGIBCSbJ2rNnT+x1b2+v5fP5rMcffzy275tvvrE8Ho/1+9//3oYK00tHR4clyWpsbLQsi+tht4svvth69tlnuQ426uzstAoKCqyGhgarpKTEevDBBy3L4u+GaWihQdK1tbUpGAyqvLw8ts/tdqukpERNTU02VpYeQqGQJGny5MmSuB526enp0e7du3X69GkVFRVxHWy0bt063Xrrrbrlllv67eeamCUtFqeEswSDQUmS1+vtt9/r9erTTz+1o6S0YVmWNmzYoBtvvFGzZs2SxPVItsOHD6uoqEjffPONLrzwQu3Zs0dXX3117AbJdUiu3bt367333lNLS8ugY/zdMAuBBrZxuVz9XluWNWgfxtb69ev1/vvv689//vOgY1yP5LjqqqvU2tqqL7/8Ui+//LJWr16txsbG2HGuQ/K0t7frwQcf1P79+zVp0qQhz+OamIFHTkg6n88n6f//9BPV0dEx6CchjJ0HHnhA9fX1euuttzR9+vTYfq5HcmVkZOjKK6/UvHnzVF1drTlz5ujJJ5/kOtjg0KFD6ujo0Ny5czVhwgRNmDBBjY2N+t3vfqcJEybE/ty5JmYg0CDp8vPz5fP51NDQENvX3d2txsZGFRcX21hZarIsS+vXr9crr7yiN998U/n5+f2Ocz3sZVmWIpEI18EGCxcu1OHDh9Xa2hrb5s2bp5UrV6q1tVVXXHEF18QgPHJCQnz11Vf6+OOPY6/b2trU2tqqyZMn67LLLlNFRYWqqqpUUFCggoICVVVVKSsrSytWrLCx6tS0bt067dq1S3v37lV2dnbsp02Px6PMzMzYvBtcj8R7+OGHtXjxYuXl5amzs1O7d+/W22+/rX379nEdbJCdnR3rSxZ1wQUX6JJLLont55oYxMYRVkhhb731liVp0LZ69WrLsr4bDrl582bL5/NZbrfbuummm6zDhw/bW3SKincdJFnPPfdc7ByuR3Lce++91uWXX25lZGRYU6ZMsRYuXGjt378/dpzrYL++w7Yti2tiEpdlWZZNWQoAAGBM0IcGAAAYj0ADAACMR6ABAADGI9AAAADjEWgAAIDxCDQAAMB4BBoAAGA8Ag0AADAegQaAcZ5//nm5XK5+25QpU1RaWqrXXnvN7vIA2IBAA8BYzz33nJqbm9XU1KSdO3dq/PjxWrJkif74xz/aXRqAJGNxSgDGmjVrlubNmxd7vWjRIl188cV66aWXtGTJEhsrA5BstNAASBmTJk1SRkaGJk6caHcpAJKMFhoAxurp6dGZM2dkWZa++OILPfHEEzp9+rRWrFhhd2kAkoxAA8BYCxYs6Pfa7XartrZWP/rRj2yqCIBdCDQAjFVXV6eZM2dKkk6cOKE9e/Zo3bp16unp0fr1622uDkAyEWgAGGvmzJmDOgV/+umn2rhxo+666y5ddNFF9hUHIKnoFAwgpcyePVtdXV06evSo3aUASCICDYCU0traKkmaMmWKvYUASCoeOQEw1gcffKAzZ85Ikk6ePKlXXnlFDQ0Nuu2225Sfn29zdQCSiUADwFg///nPY//t8XiUn5+vmpoarV271saqANjBZVmWZXcRAAAA54M+NAAAwHgEGgAAYDwCDQAAMB6BBgAAGI9AAwAAjEegAQAAxiPQAAAA4xFoAACA8Qg0AADAeAQaAABgPAINAAAw3v8DDJ6ZXTf0EP0AAAAASUVORK5CYII=",
+ "text/plain": [
+ "