Repository: facelessuser/coloraide (language: python)

Issue:
Create color averaging method
We recently rewrote our 3D model plots. We use triangulation and then we color the faces with one of the vertices. That gives us adjacent colors that are more abrupt. What we need is a way to resolve the three colors. 3 way mixing essentially.

What we need to do in this case is take the colors of each vertex of the simplex and find a color at the centroid of the simplex. Essentially averaging the colors and creating something kind of like a 3-way mix.

A low res polygon model before averaging:

<img width="534" alt="Screenshot 2023-04-13 at 10 56 21 AM" src="https://user-images.githubusercontent.com/1055125/231831299-20f70a4f-c873-4d81-a7da-4753f0a3d458.png">

The same model after averaging:

<img width="556" alt="Screenshot 2023-04-13 at 10 56 45 AM" src="https://user-images.githubusercontent.com/1055125/231831366-f50df5ec-14b5-4e8e-9262-7c4ba35273f5.png">

Undefined channels should probably be omitted from the averaging. I'm curious if we should premultiplication for alpha transparency though...something to experiment with.




Discussion / hints:
So, I've spent some time refining this and accounting for transparency. Most implementations I've seen just average the channels and don't think about transparency. So regardless of transparency, you get the same color, just more or less transparent. But a transparent color should have less of a weight in the average, so we premultiply. We will premultiplication optional, but enabled by default. You can see the results here. It seems to work really well. And when disabled, it gives the results you would expect.

<img width="1362" alt="Screenshot 2023-04-13 at 6 31 51 PM" src="https://user-images.githubusercontent.com/1055125/231911777-b4ab65f7-d846-401b-99dd-cb078a58e1db.png">



Fix patch:
diff --git a/coloraide/__meta__.py b/coloraide/__meta__.py
index c442731cf..2ff012d34 100644
--- a/coloraide/__meta__.py
+++ b/coloraide/__meta__.py
@@ -193,5 +193,5 @@ def parse_version(ver: str) -> Version:
     return Version(major, minor, micro, release, pre, post, dev)
 
 
-__version_info__ = Version(2, 0, 2, "final")
+__version_info__ = Version(2, 1, 0, "final")
 __version__ = __version_info__._get_canonical()
diff --git a/coloraide/average.py b/coloraide/average.py
new file mode 100644
index 000000000..15029073f
--- /dev/null
+++ b/coloraide/average.py
@@ -0,0 +1,104 @@
+"""Average colors together."""
+from __future__ import annotations
+import math
+from .types import ColorInput, Vector
+from typing import Sequence, TYPE_CHECKING
+
+if TYPE_CHECKING:  # pragma: no cover
+    from .color import Color
+
+
+def premultiply(color: Color, hue_index: int, alphas: Vector, enabled: bool) -> Vector:
+    """Premultiply the color before averaging."""
+
+    alpha = color.alpha()
+    alphas.append(alpha)
+
+    if not enabled or math.isnan(alpha) or alpha == 1.0:
+        return color.coords()
+
+    return [c if e == hue_index else c * alpha for e, c in enumerate(color.coords())]
+
+
+def postdivide(coords: Vector, hue_index: int) -> Vector:
+    """Undo premultiplication of semi-transparent colors."""
+
+    alpha = coords[-1]
+
+    if math.isnan(alpha) or alpha in (0.0, 1.0):
+        return coords
+
+    for i, value in enumerate(coords[:-1]):
+
+        if i == hue_index:
+            continue
+
+        coords[i] = value / alpha
+
+    return coords
+
+
+def average(create: type[Color], colors: Sequence[ColorInput], space: str, premultiplied: bool = True) -> Color:
+    """Average a list of colors together."""
+
+    obj = create(space, [])
+
+    # Check if there are enough colors to average.
+    length = len(colors)
+    if not length:
+        raise ValueError('At least one color must be provided in order to average colors')
+    elif length == 1:
+        return obj.new(colors[0]).convert(space, in_place=True)
+
+    # Get channel information
+    cs = obj.CS_MAP[space]
+    hue_index = cs.hue_index() if hasattr(cs, 'hue_index') else -1
+    channels = cs.channels
+    coords = [] * len(channels)
+
+    # Convert to desired space and premultiply values. Wrap in zip to iterate values per channel.
+    # Alpha will be collected in a separate list.
+    alphas = []  # type: Vector
+    zipped = zip(
+        *[premultiply(obj.new(c).convert(space, in_place=True), hue_index, alphas, premultiplied) for c in colors]
+    )
+
+    # Average each color channel
+    for e, points in enumerate(zipped):
+        div = s = c = value = 0.0
+        for e2, p in enumerate(points):
+            alpha = alphas[e2]
+            # Undefined values do not contribute
+            if not math.isnan(p):
+                if e == hue_index:
+                    # Hue doesn't care about alpha
+                    div += 1
+                    rad = math.radians(p)
+                    s += math.sin(rad)
+                    c += math.cos(rad)
+                else:
+                    # Non-hues are weighted averages based on transparency
+                    div += 1
+                    value += p
+
+        # Divide by the weighted average.
+        if e == hue_index:
+            coords.append(math.degrees(math.atan2(s / div, c / div)))
+        else:
+            coords.append(value / div if div else value)
+
+    # Average alpha
+    alpha = count = 0.0
+    for a in alphas:
+        if math.isnan(a):
+            continue
+        count += 1
+        alpha += a
+    coords.append(alpha / count if count else alpha)
+
+    # Undo premultiplication
+    if premultiplied:
+        coords = postdivide(coords, hue_index)
+
+    # Return the color
+    return obj.update(space, coords[:-1], coords[-1])
diff --git a/coloraide/color.py b/coloraide/color.py
index dea35babf..06c66fd60 100644
--- a/coloraide/color.py
+++ b/coloraide/color.py
@@ -12,6 +12,7 @@
 from . import filters
 from . import contrast
 from . import harmonies
+from . import average
 from . import util
 from . import algebra as alg
 from itertools import zip_longest as zipl
@@ -132,6 +133,7 @@ class Color(metaclass=ColorMeta):
     INTERPOLATE = util.DEF_INTERPOLATE
     DELTA_E = util.DEF_DELTA_E
     HARMONY = util.DEF_HARMONY
+    AVERAGE = util.DEF_AVERAGE
     CHROMATIC_ADAPTATION = 'bradford'
     CONTRAST = 'wcag21'
 
@@ -821,6 +823,26 @@ def interpolate(
             **kwargs
         )
 
+    @classmethod
+    def average(
+        cls,
+        colors: Sequence[ColorInput],
+        *,
+        space: str | None = None,
+        out_space: str | None = None,
+        premultiplied: bool = True,
+        **kwargs: Any
+    ) -> Color:
+        """Average the colors."""
+
+        if space is None:
+            space = cls.AVERAGE
+
+        if out_space is None:
+            out_space = space
+
+        return average.average(cls, colors, space, premultiplied).convert(out_space, in_place=True)
+
     def filter(  # noqa: A003
         self,
         name: str,
diff --git a/coloraide/util.py b/coloraide/util.py
index 2fa8e0389..14682b73e 100644
--- a/coloraide/util.py
+++ b/coloraide/util.py
@@ -16,6 +16,7 @@
 DEF_FIT = "lch-chroma"
 DEF_HARMONY = "oklch"
 DEF_DELTA_E = "76"
+DEF_AVERAGE = 'oklab'
 
 # Maximum luminance in PQ is 10,000 cd/m^2
 # Relative XYZ has Y=1 for media white
diff --git a/docs/src/dictionary/en-custom.txt b/docs/src/dictionary/en-custom.txt
index 155b7d86e..3ad9aa9db 100644
--- a/docs/src/dictionary/en-custom.txt
+++ b/docs/src/dictionary/en-custom.txt
@@ -253,6 +253,7 @@ preformatted
 premultiplication
 premultiplied
 premultiply
+premultiplying
 prepended
 preprocessing
 prerelease
diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index 71b99cc1f..5cc4bc041 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -1,7 +1,8 @@
 # Changelog
 
-## Next
+## 2.1
 
+- **NEW**: Add new color averaging method.
 - **FIX**: Interpolation should not modify any input colors.
 
 ## 2.0.2
diff --git a/docs/src/markdown/average.md b/docs/src/markdown/average.md
new file mode 100644
index 000000000..4a89c293b
--- /dev/null
+++ b/docs/src/markdown/average.md
@@ -0,0 +1,68 @@
+# Color Averaging
+
+Color averaging is the process of calculated an average color from a set of other colors by taking the mean of each
+color channel. It can take as many colors as desired and will return a color that represents the average. This is not
+to be confused with interpolation which employs a different technique, but in certain situations, it can sort of
+function like mixing multiple colors.
+
+## Rectangular Space Averaging
+
+ColorAide, by default, averages in rectangular color spaces, the default being Oklab. If desired, other color spaces
+can be used.
+
+```py play
+Color('red').mix('blue')
+Color.average(['red', 'blue'])
+Color.average(['red', 'blue'], space='srgb')
+```
+
+Averaging is not restricted to any certain amount of colors.
+
+```py play
+Color.average(['red', 'yellow', 'orange', 'green'])
+```
+
+## Cylindrical Space Averaging
+
+ColorAide can average colors in rectangular spaces and cylindrical spaces. When applying averaging in a cylindrical
+space, hues will be averaged taking the circular mean.
+
+```py play
+Color.average(['orange', 'yellow', 'red'], space='srgb')
+Color.average(['orange', 'yellow', 'red'], space='hsl')
+```
+
+## Averaging with Transparency
+
+ColorAide, by default, will account for transparency when averaging colors. Colors which which are more transparent
+will have less of an impact in the average. This done by premultiplying the colors before averaging.
+
+```py play
+Steps([Color('darkgreen'), Color('color(srgb 0 0.50196 0 / 1)'), Color('color(srgb 0 0 1)')])
+for i in range(12):
+    Color.average(['darkgreen', f'color(srgb 0 0.50196 0 / {i / 11})', 'color(srgb 0 0 1)'], space='srgb')
+```
+
+If you'd like to average the channels without taking transparency into consideration, simply set `premultiplied` to
+`#!py False`.
+
+```py play
+Steps([Color('darkgreen'), Color('color(srgb 0 0.50196 0 / 1)'), Color('color(srgb 0 0 1)')])
+for i in range(12):
+    Color.average(['darkgreen', f'color(srgb 0 0.50196 0 / {i / 11})', 'color(srgb 0 0 1)'], space='srgb', premultiplied=False)
+```
+
+## Averaging with Undefined Values
+
+When averaging with undefined values, ColorAide will not consider the undefined values in the average.
+```py play
+for i in range(12):
+    Color.average(['darkgreen', f'color(srgb 0 none 0 / {i / 11})', 'color(srgb 0 0 1)'], space='srgb')
+
+```
+
+When `premultiplied` is enabled, premultiplication will not be applied to a color if its `alpha` is undefined.
+
+```py play
+Color.average(['darkgreen', f'color(srgb 0 0.50196 0 / none)', 'color(srgb 0 0 1)'], space='srgb')
+```
diff --git a/docs/src/markdown/demos/colorpicker.html b/docs/src/markdown/demos/colorpicker.html
index 2d868975f..4835c6a04 100644
--- a/docs/src/markdown/demos/colorpicker.html
+++ b/docs/src/markdown/demos/colorpicker.html
@@ -404,7 +404,7 @@ <h1>ColorAide Color Picker</h1>
     let pyodide = null
     let webspace = ''
     let initial = 'oklab(0.69 0.13 -0.1 / 0.85)'
-    let package = 'coloraide-2.0.2-py3-none-any.whl'
+    let package = 'coloraide-2.1-py3-none-any.whl'
     const displayMapping = 'clip'
 
     const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`
diff --git a/docs/src/mkdocs.yml b/docs/src/mkdocs.yml
index 407d22b17..262fc560f 100644
--- a/docs/src/mkdocs.yml
+++ b/docs/src/mkdocs.yml
@@ -40,6 +40,7 @@ nav:
       - The Color Object: color.md
       - Manipulating Colors: manipulation.md
       - Color Interpolation: interpolation.md
+      - Color Averaging: average.md
       - Compositing and Blending: compositing.md
       - Color Distance and Delta E: distance.md
       - Gamut Mapping: gamut.md
@@ -266,7 +267,7 @@ extra_css:
   - assets/coloraide-extras/extra.css
 extra_javascript:
   - https://unpkg.com/mermaid@8.13.3/dist/mermaid.min.js
-  - playground-config-c87dd48d.js
+  - playground-config-c8a475b3.js
   - https://cdn.jsdelivr.net/pyodide/v0.23.0/full/pyodide.js
   - assets/coloraide-extras/extra-notebook.js
 
diff --git a/docs/src/py/notebook.py b/docs/src/py/notebook.py
index d013a6113..6f376eff7 100644
--- a/docs/src/py/notebook.py
+++ b/docs/src/py/notebook.py
@@ -569,8 +569,10 @@ def _color_command_console(colors, gamut=WEBSPACE):
     bar = False
     values = []
     for item in colors:
-        if isinstance(item, (HtmlGradient, Steps)):
-            current = total = percent = 0
+        is_grad = isinstance(item, HtmlGradient)
+        is_steps = isinstance(item, Steps)
+        if is_grad or is_steps:
+            current = total = percent = last = 0
             if isinstance(item, Steps):
                 total = len(item)
                 percent = 100 / total
@@ -584,15 +586,20 @@ def _color_command_console(colors, gamut=WEBSPACE):
             stops = []
             for e, color in enumerate(item):
                 color.fit(gamut)
+                color_str = color.convert(gamut).to_string()
                 if current:
-                    stops.append('{}'.format(color.convert(gamut).to_string()))
-                    stops.append('{}'.format(color.convert(gamut).to_string()))
+                    if is_steps:
+                        stops.append('{} {}%'.format(color_str, str(last)))
+                        stops.append('{} {}%'.format(color_str, str(current)))
+                    else:
+                        stops.append(color_str)
+                    last = current
                     if e < (total - 1):
                         current += percent
                     else:
                         current = 100
                 else:
-                    stops.append(color.convert(gamut).to_string())
+                    stops.append(color_str)
             if not stops:
                 stops.extend(['transparent'] * 2)
             if len(stops) == 1:
diff --git a/docs/theme/assets/coloraide-extras/extra-notebook-40c84faf.js b/docs/theme/assets/coloraide-extras/extra-notebook-3d99782d.js
similarity index 57%
rename from docs/theme/assets/coloraide-extras/extra-notebook-40c84faf.js
rename to docs/theme/assets/coloraide-extras/extra-notebook-3d99782d.js
index d1d662d2a..ae1314843 100644
--- a/docs/theme/assets/coloraide-extras/extra-notebook-40c84faf.js
+++ b/docs/theme/assets/coloraide-extras/extra-notebook-3d99782d.js
@@ -1,2 +1,2 @@
-function _typeof(t){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof(t)}var runtime=function(t){"use strict";var e,n=Object.prototype,o=n.hasOwnProperty,r=Object.defineProperty||function(t,e,n){t[e]=n.value},a="function"==typeof Symbol?Symbol:{},i=a.iterator||"@@iterator",s=a.asyncIterator||"@@asyncIterator",l=a.toStringTag||"@@toStringTag";function c(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{c({},"")}catch(t){c=function(t,e,n){return t[e]=n}}function u(t,e,n,o){var a=e&&e.prototype instanceof _?e:_,i=Object.create(a.prototype),s=new I(o||[]);return r(i,"_invoke",{value:S(t,n,s)}),i}function d(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}t.wrap=u;var p="suspendedStart",f="suspendedYield",m="executing",g="completed",h={};function _(){}function y(){}function v(){}var w={};c(w,i,(function(){return this}));var x=Object.getPrototypeOf,b=x&&x(x(T([])));b&&b!==n&&o.call(b,i)&&(w=b);var E=v.prototype=_.prototype=Object.create(w);function k(t){["next","throw","return"].forEach((function(e){c(t,e,(function(t){return this._invoke(e,t)}))}))}function L(t,e){function n(r,a,i,s){var l=d(t[r],t,a);if("throw"!==l.type){var c=l.arg,u=c.value;return u&&"object"===_typeof(u)&&o.call(u,"__await")?e.resolve(u.__await).then((function(t){n("next",t,i,s)}),(function(t){n("throw",t,i,s)})):e.resolve(u).then((function(t){c.value=t,i(c)}),(function(t){return n("throw",t,i,s)}))}s(l.arg)}var a;r(this,"_invoke",{value:function(t,o){function r(){return new e((function(e,r){n(t,o,e,r)}))}return a=a?a.then(r,r):r()}})}function S(t,e,n){var o=p;return function(r,a){if(o===m)throw new Error("Generator is already running");if(o===g){if("throw"===r)throw a;return O()}for(n.method=r,n.arg=a;;){var i=n.delegate;if(i){var s=A(i,n);if(s){if(s===h)continue;return s}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===p)throw o=g,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=m;var l=d(t,e,n);if("normal"===l.type){if(o=n.done?g:f,l.arg===h)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o=g,n.method="throw",n.arg=l.arg)}}}function A(t,n){var o=n.method,r=t.iterator[o];if(r===e)return n.delegate=null,"throw"===o&&t.iterator.return&&(n.method="return",n.arg=e,A(t,n),"throw"===n.method)||"return"!==o&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+o+"' method")),h;var a=d(r,t.iterator,n.arg);if("throw"===a.type)return n.method="throw",n.arg=a.arg,n.delegate=null,h;var i=a.arg;return i?i.done?(n[t.resultName]=i.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=e),n.delegate=null,h):i:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,h)}function C(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function B(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function I(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(C,this),this.reset(!0)}function T(t){if(t){var n=t[i];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,a=function n(){for(;++r<t.length;)if(o.call(t,r))return n.value=t[r],n.done=!1,n;return n.value=e,n.done=!0,n};return a.next=a}}return{next:O}}function O(){return{value:e,done:!0}}return y.prototype=v,r(E,"constructor",{value:v,configurable:!0}),r(v,"constructor",{value:y,configurable:!0}),y.displayName=c(v,l,"GeneratorFunction"),t.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===y||"GeneratorFunction"===(e.displayName||e.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,v):(t.__proto__=v,c(t,l,"GeneratorFunction")),t.prototype=Object.create(E),t},t.awrap=function(t){return{__await:t}},k(L.prototype),c(L.prototype,s,(function(){return this})),t.AsyncIterator=L,t.async=function(e,n,o,r,a){void 0===a&&(a=Promise);var i=new L(u(e,n,o,r),a);return t.isGeneratorFunction(n)?i:i.next().then((function(t){return t.done?t.value:i.next()}))},k(E),c(E,l,"Generator"),c(E,i,(function(){return this})),c(E,"toString",(function(){return"[object Generator]"})),t.keys=function(t){var e=Object(t),n=[];for(var o in e)n.push(o);return n.reverse(),function t(){for(;n.length;){var o=n.pop();if(o in e)return t.value=o,t.done=!1,t}return t.done=!0,t}},t.values=T,I.prototype={constructor:I,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(B),!t)for(var n in this)"t"===n.charAt(0)&&o.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var n=this;function r(o,r){return s.type="throw",s.arg=t,n.next=o,r&&(n.method="next",n.arg=e),!!r}for(var a=this.tryEntries.length-1;a>=0;--a){var i=this.tryEntries[a],s=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var l=o.call(i,"catchLoc"),c=o.call(i,"finallyLoc");if(l&&c){if(this.prev<i.catchLoc)return r(i.catchLoc,!0);if(this.prev<i.finallyLoc)return r(i.finallyLoc)}else if(l){if(this.prev<i.catchLoc)return r(i.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return r(i.finallyLoc)}}}},abrupt:function(t,e){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev<r.finallyLoc){var a=r;break}}a&&("break"===t||"continue"===t)&&a.tryLoc<=e&&e<=a.finallyLoc&&(a=null);var i=a?a.completion:{};return i.type=t,i.arg=e,a?(this.method="next",this.next=a.finallyLoc,h):this.complete(i)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),h},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),B(n),h}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var o=n.completion;if("throw"===o.type){var r=o.arg;B(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,o){return this.delegate={iterator:T(t),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=e),h}},t}("object"===("undefined"==typeof module?"undefined":_typeof(module))?module.exports:{});try{regeneratorRuntime=runtime}catch(t){"object"===("undefined"==typeof globalThis?"undefined":_typeof(globalThis))?globalThis.regeneratorRuntime=runtime:Function("r","regeneratorRuntime = r")(runtime)}!function(){"use strict";function t(){t=function(){return e};var e={},n=Object.prototype,o=n.hasOwnProperty,r=Object.defineProperty||function(t,e,n){t[e]=n.value},a="function"==typeof Symbol?Symbol:{},i=a.iterator||"@@iterator",s=a.asyncIterator||"@@asyncIterator",l=a.toStringTag||"@@toStringTag";function c(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{c({},"")}catch(t){c=function(t,e,n){return t[e]=n}}function u(t,e,n,o){var a=e&&e.prototype instanceof f?e:f,i=Object.create(a.prototype),s=new S(o||[]);return r(i,"_invoke",{value:b(t,n,s)}),i}function d(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}e.wrap=u;var p={};function f(){}function m(){}function g(){}var h={};c(h,i,(function(){return this}));var _=Object.getPrototypeOf,y=_&&_(_(A([])));y&&y!==n&&o.call(y,i)&&(h=y);var v=g.prototype=f.prototype=Object.create(h);function w(t){["next","throw","return"].forEach((function(e){c(t,e,(function(t){return this._invoke(e,t)}))}))}function x(t,e){function n(r,a,i,s){var l=d(t[r],t,a);if("throw"!==l.type){var c=l.arg,u=c.value;return u&&"object"==_typeof(u)&&o.call(u,"__await")?e.resolve(u.__await).then((function(t){n("next",t,i,s)}),(function(t){n("throw",t,i,s)})):e.resolve(u).then((function(t){c.value=t,i(c)}),(function(t){return n("throw",t,i,s)}))}s(l.arg)}var a;r(this,"_invoke",{value:function(t,o){function r(){return new e((function(e,r){n(t,o,e,r)}))}return a=a?a.then(r,r):r()}})}function b(t,e,n){var o="suspendedStart";return function(r,a){if("executing"===o)throw new Error("Generator is already running");if("completed"===o){if("throw"===r)throw a;return C()}for(n.method=r,n.arg=a;;){var i=n.delegate;if(i){var s=E(i,n);if(s){if(s===p)continue;return s}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if("suspendedStart"===o)throw o="completed",n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o="executing";var l=d(t,e,n);if("normal"===l.type){if(o=n.done?"completed":"suspendedYield",l.arg===p)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o="completed",n.method="throw",n.arg=l.arg)}}}function E(t,e){var n=e.method,o=t.iterator[n];if(void 0===o)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=void 0,E(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),p;var r=d(o,t.iterator,e.arg);if("throw"===r.type)return e.method="throw",e.arg=r.arg,e.delegate=null,p;var a=r.arg;return a?a.done?(e[t.resultName]=a.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=void 0),e.delegate=null,p):a:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,p)}function k(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function L(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function S(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(k,this),this.reset(!0)}function A(t){if(t){var e=t[i];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,r=function e(){for(;++n<t.length;)if(o.call(t,n))return e.value=t[n],e.done=!1,e;return e.value=void 0,e.done=!0,e};return r.next=r}}return{next:C}}function C(){return{value:void 0,done:!0}}return m.prototype=g,r(v,"constructor",{value:g,configurable:!0}),r(g,"constructor",{value:m,configurable:!0}),m.displayName=c(g,l,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===m||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,g):(t.__proto__=g,c(t,l,"GeneratorFunction")),t.prototype=Object.create(v),t},e.awrap=function(t){return{__await:t}},w(x.prototype),c(x.prototype,s,(function(){return this})),e.AsyncIterator=x,e.async=function(t,n,o,r,a){void 0===a&&(a=Promise);var i=new x(u(t,n,o,r),a);return e.isGeneratorFunction(n)?i:i.next().then((function(t){return t.done?t.value:i.next()}))},w(v),c(v,l,"Generator"),c(v,i,(function(){return this})),c(v,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=Object(t),n=[];for(var o in e)n.push(o);return n.reverse(),function t(){for(;n.length;){var o=n.pop();if(o in e)return t.value=o,t.done=!1,t}return t.done=!0,t}},e.values=A,S.prototype={constructor:S,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=void 0,this.done=!1,this.delegate=null,this.method="next",this.arg=void 0,this.tryEntries.forEach(L),!t)for(var e in this)"t"===e.charAt(0)&&o.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=void 0)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function n(n,o){return i.type="throw",i.arg=t,e.next=n,o&&(e.method="next",e.arg=void 0),!!o}for(var r=this.tryEntries.length-1;r>=0;--r){var a=this.tryEntries[r],i=a.completion;if("root"===a.tryLoc)return n("end");if(a.tryLoc<=this.prev){var s=o.call(a,"catchLoc"),l=o.call(a,"finallyLoc");if(s&&l){if(this.prev<a.catchLoc)return n(a.catchLoc,!0);if(this.prev<a.finallyLoc)return n(a.finallyLoc)}else if(s){if(this.prev<a.catchLoc)return n(a.catchLoc,!0)}else{if(!l)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return n(a.finallyLoc)}}}},abrupt:function(t,e){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev<r.finallyLoc){var a=r;break}}a&&("break"===t||"continue"===t)&&a.tryLoc<=e&&e<=a.finallyLoc&&(a=null);var i=a?a.completion:{};return i.type=t,i.arg=e,a?(this.method="next",this.next=a.finallyLoc,p):this.complete(i)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),p},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),L(n),p}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var o=n.completion;if("throw"===o.type){var r=o.arg;L(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:A(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=void 0),p}},e}function e(t,e,n,o,r,a,i){try{var s=t[a](i),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(o,r)}function n(t){return function(){var n=this,o=arguments;return new Promise((function(r,a){var i=t.apply(n,o);function s(t){e(i,r,a,s,l,"next",t)}function l(t){e(i,r,a,s,l,"throw",t)}s(void 0)}))}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function r(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=function(t,e){if(t){if("string"==typeof t)return o(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?o(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){n&&(t=n);var r=0,a=function(){};return{s:a,n:function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,l=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return s=t.done,t},e:function(t){l=!0,i=t},f:function(){try{s||null==n.return||n.return()}finally{if(l)throw i}}}}!function(){var e="";try{var o="srgb";window.matchMedia("(color-gamut: rec2020)").matches?o="rec2020":window.matchMedia("(color-gamut: p3)").matches&&(o="display-p3"),e=CSS.supports("color: color(display-p3 1 0 0)")?o:"srgb"}catch(t){e="srgb"}var a=null,i=!1,s="",l="",c={},u=/.*?_(\d+)$/,d=!1,p="",f=!1,m=/^( {1,4}|\t)/,g="\n_O='<div class=\"color-command\">{}</div>'\n_N='swatch'\n_M='transparent'\n_L='pycon'\n_K='playground'\n_J='gamut'\n_I='exceptions'\n_H='color'\n_G='highlight'\n_F='class'\n_E='eval'\n_D='<string>'\n_C=None\n_B=True\n_A=False\nimport xml.etree.ElementTree as Etree\nfrom collections.abc import Sequence,Mapping\nfrom collections import namedtuple\nimport ast\nfrom io import StringIO\nimport sys,re\nfrom functools import partial\nfrom pygments import highlight\nfrom pygments.lexers import get_lexer_by_name\nfrom pygments.formatters import find_formatter_class\nfrom coloraide import Color\nfrom coloraide.interpolate import Interpolator,normalize_domain\ntry:from coloraide_extras.everything import ColorAll\nexcept ImportError:from coloraide.everything import ColorAll\nPY310=(3,10)<=sys.version_info\nPY311=(3,11)<=sys.version_info\nWEBSPACE='srgb'\nAST_BLOCKS=ast.If,ast.For,ast.While,ast.Try,ast.With,ast.FunctionDef,ast.ClassDef,ast.AsyncFor,ast.AsyncWith,ast.AsyncFunctionDef\nif PY310:AST_BLOCKS=AST_BLOCKS+(ast.Match,)\nif PY311:AST_BLOCKS=AST_BLOCKS+(ast.TryStar,)\nRE_INIT=re.compile('^\\\\s*#\\\\s*pragma:\\\\s*init\\\\n(.*?)#\\\\s*pragma:\\\\s*init\\\\n',re.DOTALL|re.I)\nRE_COLOR_START=re.compile('(?i)(?:\\\\b(?<![-#&$])(?:color|hsla?|lch|lab|hwb|rgba?)\\\\(|\\\\b(?<![-#&$])[\\\\w]{3,}(?![(-])\\\\b|(?<![&])#)')\nLIVE_INIT='\\nfrom coloraide import *\\nimport coloraide\\ntry:\\n    import coloraide_extras\\n    from coloraide_extras.everything import ColorAll as Color\\nexcept ImportError:\\n    from coloraide.everything import ColorAll as Color\\n'\ntemplate='<div class=\"playground\" id=\"__playground_{el_id}\">\\n<div class=\"playground-results\" id=\"__playground-results_{el_id}\">\\n{results}\\n</div>\\n<div class=\"playground-code hidden\" id=\"__playground-code_{el_id}\" data-search-exclude>\\n<form autocomplete=\"off\">\\n<textarea class=\"playground-inputs\" id=\"__playground-inputs_{el_id}\" spellcheck=\"false\">{raw_source}</textarea>\\n</form>\\n</div>\\n<div class=\"playground-footer\" data-search-exclude>\\n<hr>\\n<button id=\"__playground-edit_{el_id}\" class=\"playground-edit\" title=\"Edit the current snippet\">Edit</button>\\n<button id=\"__playground-share_{el_id}\" class=\"playground-share\" title=\"Copy URL to current snippet\">Share</button>\\n<button id=\"__playground-run_{el_id}\" class=\"playground-run hidden\" title=\"Run code (Ctrl + Enter)\">Run</button>\\n<button id=\"__playground-cancel_{el_id}\" class=\"playground-cancel hidden\" title=\"Cancel edit (Escape)\">Cancel</button>\\n<span class=\\'gamut\\'>Gamut: {gamut}</span>\\n</div>\\n</div>'\ncode_id=0\nclass Ramp(list):0\nclass Steps(list):0\nclass Row(list):0\nclass ColorTuple(namedtuple('ColorTuple',['string',_H])):0\nclass AtomicString(str):0\nclass Break(Exception):0\nclass Continue(Exception):0\nHtmlRow=Row\nHtmlSteps=Steps\nHtmlGradient=Ramp\ndef _escape(txt):txt=txt.replace('&','&amp;');txt=txt.replace('<','&lt;');txt=txt.replace('>','&gt;');return txt\nclass StreamOut:\n\tdef __init__(self):self.old=sys.stdout;self.stdout=StringIO();sys.stdout=self.stdout\n\tdef read(self):\n\t\tvalue=''\n\t\tif self.stdout is not _C:self.stdout.flush();value=self.stdout.getvalue();self.stdout=StringIO();sys.stdout=self.stdout\n\t\treturn value\n\tdef __enter__(self):return self\n\tdef __exit__(self,type,value,traceback):sys.stdout=self.old;self.old=_C;self.stdout=_C\ndef get_colors(result):\n\tdomain=[]\n\tif isinstance(result,AtomicString):yield find_colors(result)\n\tif isinstance(result,Row):yield Row([ColorTuple(c.to_string(fit=_A),c.clone())if isinstance(c,Color)else ColorTuple(c,ColorAll(c))for c in result])\n\telif isinstance(result,(Steps,Ramp)):t=type(result);yield t([c.clone()if isinstance(c,Color)else ColorAll(c)for c in result])\n\telif isinstance(result,Color):yield[ColorTuple(result.to_string(fit=_A),result.clone())]\n\telif isinstance(result,Interpolator):\n\t\tif result.domain:domain=result.domain;result.domain=normalize_domain(result.domain)\n\t\tgrad=Ramp(result.steps(steps=5,max_delta_e=2.3))\n\t\tif domain:result.domain=domain;domain=[]\n\t\tyield grad\n\telif isinstance(result,str):\n\t\ttry:yield[ColorTuple(result,ColorAll(result))]\n\t\texcept Exception:pass\n\telif isinstance(result,(list,tuple)):\n\t\tfor r in result:\n\t\t\tfor x in get_colors(r):\n\t\t\t\tif x:yield x\ndef find_colors(text):\n\tcolors=[]\n\tfor m in RE_COLOR_START.finditer(text):\n\t\tstart=m.start();mcolor=ColorAll.match(text,start=start)\n\t\tif mcolor is not _C:colors.append(ColorTuple(text[mcolor.start:mcolor.end],mcolor.color))\n\treturn colors\ndef evaluate_with(node,g,loop,index=0):\n\tl=len(node.items)-1;withitem=node.items[index]\n\tif withitem.context_expr:\n\t\twith eval(compile(ast.Expression(withitem.context_expr),_D,_E),g)as w:\n\t\t\tg[withitem.optional_vars.id]=w\n\t\t\tif index<l:evaluate_with(node,g,loop,index+1)\n\t\t\telse:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\telse:\n\t\twith eval(compile(ast.Expression(withitem.context_expr),_D,_E),g):\n\t\t\tif index<l:evaluate_with(node,g,loop,index+1)\n\t\t\telse:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\ndef compare_match(s,g,node):\n\tif isinstance(node,ast.MatchOr):\n\t\tfor pattern in node.patterns:\n\t\t\tif compare_match(s,g,pattern):return _B\n\telif isinstance(node,ast.MatchValue):p=eval(compile(ast.Expression(node.value),_D,_E),g);return s==p\n\telif isinstance(node,ast.MatchSingleton):return s is node.value\n\telif isinstance(node,ast.MatchSequence):\n\t\tif isinstance(s,Sequence):\n\t\t\tstar=isinstance(node.patterns[-1],ast.MatchStar);l1,l2=len(s),len(node.patterns)\n\t\t\tif star and l1>=l2-1 or l1==l2:\n\t\t\t\tfor (e,p) in enumerate(node.patterns[:-1]if star else node.patterns):\n\t\t\t\t\tif not compare_match(s[e],g,p):return _A\n\t\t\t\tif star and node.patterns[-1].name:g[node.patterns[-1].name]=s[l2-1:]\n\t\t\t\treturn _B\n\t\treturn _A\n\telif isinstance(node,ast.MatchMapping):\n\t\tif isinstance(s,Mapping):\n\t\t\tstar=node.rest;l1,l2=len(s),len(node.patterns)\n\t\t\tif star and l1>=l2 or l1==l2:\n\t\t\t\tkeys=set()\n\t\t\t\tfor (kp,vp) in zip(node.keys,node.patterns):\n\t\t\t\t\tkey=eval(compile(ast.Expression(kp),_D,_E),g);keys.add(key)\n\t\t\t\t\tif key not in s:return _A\n\t\t\t\t\tif not compare_match(s[key],g,vp):return _A\n\t\t\t\tif star:g[star]={k:v for(k,v)in s.items()if k not in keys}\n\t\t\t\treturn _B\n\t\treturn _A\n\telif isinstance(node,ast.MatchClass):\n\t\tname=g.get(node.cls.id,_C)\n\t\tif name is _C:raise NameError(\"name '{}' is not defined\".format(node.cls.id))\n\t\tif not isinstance(s,name):return _A\n\t\tma=getattr(s,'__match_args__',tuple());l1=len(ma);l2=len(node.patterns)\n\t\tif l1<l2:raise TypeError('{}() accepts {} positional sub-patterns ({} given)'.format(name,l1,l2))\n\t\tfor (e,p) in enumerate(node.patterns):\n\t\t\tif not hasattr(s,ma[e]):return _A\n\t\t\tif not compare_match(getattr(s,ma[e]),g,p):return _A\n\t\tfor (a,p) in zip(node.kwd_attrs,node.kwd_patterns):\n\t\t\tif not hasattr(s,a):return _A\n\t\t\tif not compare_match(getattr(s,a),g,p):return _A\n\t\treturn _B\n\telif isinstance(node,ast.MatchAs):\n\t\tif node.name is not _C:g[node.name]=s\n\t\tif node.pattern:return compare_match(s,g,node.pattern)\n\t\treturn _B\n\traise RuntimeError('Unknown Match pattern {}'.format(str(node)))\ndef evaluate_except(node,e,g,loop=_A):\n\tfor n in node.handlers:\n\t\tif n.name:g[n.name]=e\n\t\tif n.type is _C:\n\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\tbreak\n\t\telif isinstance(e,eval(compile(ast.Expression(n.type),_D,_E),g)):\n\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\tbreak\n\telse:raise\ndef evaluate(node,g,loop=_A):\n\tif loop and isinstance(node,ast.Break):raise Break\n\tif loop and isinstance(node,ast.Continue):raise Continue\n\tif isinstance(node,ast.Expr):_eval=ast.Expression(node.value);yield eval(compile(_eval,_D,_E),g)\n\telif isinstance(node,ast.If):\n\t\tif eval(compile(ast.Expression(node.test),_D,_E),g):\n\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\t\telif node.orelse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\telif isinstance(node,ast.While):\n\t\twhile eval(compile(ast.Expression(node.test),_D,_E),g):\n\t\t\ttry:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,_B)\n\t\t\texcept Break:break\n\t\t\texcept Continue:continue\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\telif isinstance(node,ast.For):\n\t\tfor x in eval(compile(ast.Expression(node.iter),_D,_E),g):\n\t\t\tif isinstance(node.target,ast.Tuple):\n\t\t\t\tfor (e,t) in enumerate(node.target.dims):g[t.id]=x[e]\n\t\t\telse:g[node.target.id]=x\n\t\t\ttry:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,_B)\n\t\t\texcept Break:break\n\t\t\texcept Continue:continue\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\telif isinstance(node,ast.Try):\n\t\ttry:\n\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\t\texcept Exception as e:yield from evaluate_except(node,e,g,loop)\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\t\tfinally:\n\t\t\tfor n in node.finalbody:yield from evaluate(n,g,loop)\n\telif PY311 and isinstance(node,ast.TryStar):\n\t\ttry:\n\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\t\texcept ExceptionGroup as e:\n\t\t\tfor n in node.handlers:\n\t\t\t\tif n.name:g[n.name]=e\n\t\t\t\tm,e=e.split(eval(compile(ast.Expression(n.type),_D,_E),g))\n\t\t\t\tif m is not _C:\n\t\t\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\t\tif e is _C:break\n\t\t\tif e is not _C:raise e\n\t\texcept Exception as e:yield from evaluate_except(node,e,g,loop)\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\t\tfinally:\n\t\t\tfor n in node.finalbody:yield from evaluate(n,g,loop)\n\telif PY310 and isinstance(node,ast.Match):\n\t\ts=eval(compile(ast.Expression(node.subject),_D,_E),g)\n\t\tfor c in node.cases:\n\t\t\tif compare_match(s,g,c.pattern):\n\t\t\t\tif not c.guard or eval(compile(ast.Expression(c.guard),_D,_E),g):\n\t\t\t\t\tfor n in c.body:yield from evaluate(n,g,loop)\n\t\t\t\t\tbreak\n\telif isinstance(node,ast.With):yield from evaluate_with(node,g,loop)\n\telse:_exec=ast.Module([node],[]);exec(compile(_exec,_D,'exec'),g);yield _C\ndef execute(cmd,no_except=_B,inline=_A,init='',g=_C):\n\tA='\\n';console='';colors=[]\n\tif g is _C:g={'Ramp':Ramp,'Steps':Steps,'Row':Row,'HtmlRow':HtmlRow,'HtmlSteps':HtmlSteps,'HtmlGradient':HtmlGradient}\n\tif init:execute(init.strip(),g=g)\n\tm=RE_INIT.match(cmd)\n\tif m:block_init=m.group(1);src=cmd[m.end():];execute(block_init,g=g)\n\telse:src=cmd\n\tlines=src.split(A)\n\ttry:tree=ast.parse(src)\n\texcept Exception as e:\n\t\tif no_except:\n\t\t\tif not inline:from pymdownx.superfences import SuperFencesException;raise SuperFencesException from e\n\t\t\telse:from pymdownx.inlinehilite import InlineHiliteException;raise InlineHiliteException from e\n\t\timport traceback;return '{}'.format(traceback.format_exc()),colors\n\tfor node in tree.body:\n\t\tresult=[];start=node.lineno;end=node.end_lineno;stmt=lines[start-1:end];command=''\n\t\tfor (i,line) in enumerate(stmt,0):\n\t\t\tif i==0:stmt[i]='>>> '+line\n\t\t\telse:stmt[i]='... '+line\n\t\tcommand+=A.join(stmt)\n\t\tif isinstance(node,AST_BLOCKS):command+='\\n... '\n\t\ttry:\n\t\t\twith StreamOut()as s:\n\t\t\t\tfor x in evaluate(node,g):\n\t\t\t\t\tresult.append(x);text=s.read()\n\t\t\t\t\tif text:result.append(AtomicString(text))\n\t\t\t\tconsole+=command\n\t\texcept Exception as e:\n\t\t\tif no_except:\n\t\t\t\tif not inline:from pymdownx.superfences import SuperFencesException;raise SuperFencesException from e\n\t\t\t\telse:from pymdownx.inlinehilite import InlineHiliteException;raise InlineHiliteException from e\n\t\t\timport traceback;console+='{}\\n{}'.format(command,traceback.format_exc());break\n\t\tresult_text=A\n\t\tfor r in result:\n\t\t\tif r is _C:continue\n\t\t\tfor clist in get_colors(r):\n\t\t\t\tif clist:colors.append(clist)\n\t\t\tresult_text+='{}{}'.format(repr(r)if isinstance(r,str)and not isinstance(r,AtomicString)else str(r),A if not isinstance(r,AtomicString)else'')\n\t\tconsole+=result_text\n\treturn console,colors\ndef colorize(src,lang,**options):HtmlFormatter=find_formatter_class('html');lexer=get_lexer_by_name(lang,**options);formatter=HtmlFormatter(cssclass=_G,wrapcode=_B);return highlight(src,lexer,formatter).strip()\ndef color_command_validator(language,inputs,options,attrs,md):\n\tvalid_inputs=set([_I,'play'])\n\tfor (k,v) in inputs.items():\n\t\tif k in valid_inputs:options[k]=_B;continue\n\t\tattrs[k]=v\n\treturn _B\ndef _color_command_console(colors,gamut=WEBSPACE):\n\tB=' ';A='<div class=\"swatch-bar\">{}</div>';el='';bar=_A;values=[]\n\tfor item in colors:\n\t\tif isinstance(item,(HtmlGradient,Steps)):\n\t\t\tcurrent=total=percent=0\n\t\t\tif isinstance(item,Steps):total=len(item);percent=100/total;current=percent\n\t\t\tif bar:el+=A.format(B.join(values));values=[]\n\t\t\tsub_el1='<div class=\"swatch-bar\"><span class=\"swatch swatch-gradient\">{}</span></div>';style='--swatch-stops: ';stops=[]\n\t\t\tfor (e,color) in enumerate(item):\n\t\t\t\tcolor.fit(gamut)\n\t\t\t\tif current:\n\t\t\t\t\tstops.append('{}'.format(color.convert(gamut).to_string()));stops.append('{}'.format(color.convert(gamut).to_string()))\n\t\t\t\t\tif e<total-1:current+=percent\n\t\t\t\t\telse:current=100\n\t\t\t\telse:stops.append(color.convert(gamut).to_string())\n\t\t\tif not stops:stops.extend([_M]*2)\n\t\t\tif len(stops)==1:stops.append(stops[0])\n\t\t\tstyle+=','.join(stops);sub_el2='<span class=\"swatch-color\" style=\"{}\"></span>'.format(style);el+=sub_el1.format(sub_el2);bar=_A\n\t\telse:\n\t\t\tis_row=_A\n\t\t\tif isinstance(item,Row):\n\t\t\t\tis_row=_B\n\t\t\t\tif bar and values:el+=A.format(B.join(values));values=[]\n\t\t\t\tbar=_A\n\t\t\tbar=_B\n\t\t\tfor color in item:\n\t\t\t\tbase_classes=_N\n\t\t\t\tif not color.color.in_gamut(gamut):base_classes+=' out-of-gamut'\n\t\t\t\tcolor.color.fit(gamut);srgb=color.color.convert(gamut);value1=srgb.to_string(alpha=_A);value2=srgb.to_string();style='--swatch-stops: {} 50%, {} 50%'.format(value1,value2);title=color.string;classes=base_classes;c='<span class=\"swatch-color\" style=\"{style}\"></span>'.format(style=style);c='<span class=\"{classes}\" title=\"{title}&#013;Copy to clipboard\">{color}</span>'.format(classes=classes,color=c,title=title);values.append(c)\n\t\t\tif is_row and values:el+=A.format(B.join(values));values=[];bar=_A\n\tif bar:el+=A.format(B.join(values));values=[]\n\treturn el\ndef _color_command_formatter(src='',language='',class_name=_C,options=_C,md='',init='',**kwargs):\n\tB='formatter';A='fenced_code_block';global code_id;from pymdownx.superfences import SuperFencesException;gamut=kwargs.get(_J,WEBSPACE);play=options.get('play',_A)if options is not _C else _A\n\tif not play and language==_K:play=_B\n\tif not play:return md.preprocessors[A].extension.superfences[0][B](src=src,class_name=class_name,language='py',md=md,options=options,**kwargs)\n\ttry:\n\t\tif len(md.preprocessors[A].extension.stash)==0:code_id=0\n\t\texceptions=options.get(_I,_A)if options is not _C else _A;console,colors=execute(src.strip(),not exceptions,init=init);el=_color_command_console(colors,gamut=gamut);el+=md.preprocessors[A].extension.superfences[0][B](src=console,class_name=_G,language=_L,md=md,options=options,**kwargs);el=_O.format(el);el=template.format(el_id=code_id,raw_source=_escape(src),results=el,gamut=gamut);code_id+=1\n\texcept SuperFencesException:raise\n\texcept Exception:from pymdownx import superfences;import traceback;print(traceback.format_exc());return superfences.fence_code_format(src,'text',class_name,options,md,**kwargs)\n\treturn el\ndef color_command_formatter(init='',gamut=WEBSPACE):return partial(_color_command_formatter,init=init,gamut=gamut)\ndef _color_formatter(src='',language='',class_name=_C,md='',exceptions=_B,init='',gamut=WEBSPACE):\n\tE='backtick';D='title';C='Only one color allowed';B=' 50%';A='span';from pymdownx.inlinehilite import InlineHiliteException\n\ttry:\n\t\tresult=src.strip()\n\t\ttry:color=ColorAll(result.strip())\n\t\texcept Exception:\n\t\t\t_,colors=execute(result,exceptions,inline=_B,init=init)\n\t\t\tif len(colors)!=1 or len(colors[0])!=1:\n\t\t\t\tif exceptions:raise InlineHiliteException(C)\n\t\t\t\telse:raise ValueError(C)\n\t\t\tcolor=colors[0][0].color;result=colors[0][0].string\n\t\tel=Etree.Element(A);stops=[]\n\t\tif not color.in_gamut(gamut):\n\t\t\tcolor.fit(gamut);attributes={_F:'swatch out-of-gamut',D:result};sub_el=Etree.SubElement(el,A,attributes);stops.append(color.convert(gamut).to_string(hex=_B,alpha=_A))\n\t\t\tif color[-1]<1.0:stops[-1]+=B;stops.append(color.convert(gamut).to_string(hex=_B)+B)\n\t\telse:\n\t\t\tattributes={_F:_N,D:result};sub_el=Etree.SubElement(el,A,attributes);stops.append(color.convert(gamut).to_string(hex=_B,alpha=_A))\n\t\t\tif color[-1]<1.0:stops[-1]+=B;stops.append(color.convert(gamut).to_string(hex=_B)+B)\n\t\tif not stops:stops.extend([_M]*2)\n\t\tif len(stops)==1:stops.append(stops[0])\n\t\tEtree.SubElement(sub_el,A,{_F:'swatch-color','style':'--swatch-stops: {};'.format(','.join(stops))});el.append(md.inlinePatterns[E].handle_code('css-color',result))\n\texcept InlineHiliteException:raise\n\texcept Exception:import traceback;print(traceback.format_exc());el=md.inlinePatterns[E].handle_code('text',src)\n\treturn el\ndef color_formatter(init='',gamut=WEBSPACE):return partial(_color_formatter,init=init,gamut=gamut)\ndef _live_color_command_formatter(src,init='',gamut=WEBSPACE):\n\ttry:\n\t\tconsole,colors=execute(src.strip(),_A,init=init);el=_color_command_console(colors,gamut=gamut)\n\t\tif not colors:el+='<div class=\"swatch-bar\"></div>'\n\t\tel+=colorize(console,_L,**{'python3':_B,'stripnl':_A});el=_O.format(el)\n\texcept Exception:import traceback;return '<div class=\"color-command\"><div class=\"swatch-bar\"></div>{}</div>'.format(colorize(traceback.format_exc(),_L))\n\treturn el\ndef live_color_command_formatter(init='',gamut=WEBSPACE):return partial(_live_color_command_formatter,init=init,gamut=gamut)\ndef live_color_command_validator(language,inputs,options,attrs,md):value=color_command_validator(language,inputs,options,attrs,md);options[_I]=_B;return value\ndef render_console(*args,**kwargs):\n\tC='.swatch-bar';B='code';A='id_num';from js import document;gamut=kwargs.get(_J,WEBSPACE)\n\ttry:\n\t\tinputs=document.getElementById('__playground-inputs_{}'.format(globals()[A]));results=document.getElementById('__playground-results_{}'.format(globals()[A]));footer=document.querySelector('#__playground_{} .gamut'.format(globals()[A]));result=live_color_command_formatter(LIVE_INIT,gamut)(inputs.value);temp=document.createElement('div');temp.innerHTML=result;cmd=results.querySelector('.color-command')\n\t\tfor el in cmd.querySelectorAll(C):el.remove()\n\t\tfor el in temp.querySelectorAll(C):cmd.insertBefore(el,cmd.lastChild)\n\t\tfooter.innerHTML='Gamut: {}'.format(gamut);pre=cmd.querySelector('pre');pre.replaceChild(temp.querySelector(B),pre.querySelector(B));temp.remove();scrollingElement=results.querySelector(B);scrollingElement.scrollTop=scrollingElement.scrollHeight\n\texcept Exception as e:print(e)\ndef render_notebook(*args,**kwargs):\n\tM='diagram';L='pymdownx.blocks.tab';K='pymdownx.blocks.admonition';J='pymdownx.arithmatex';I='pymdownx.keys';H='pymdownx.magiclink';G='pymdownx.inlinehilite';F='pymdownx.superfences';E='markdown.extensions.smarty';D='markdown.extensions.toc';C='validator';B='format';A='name';import markdown;from pymdownx import slugs,superfences;from js import document;gamut=kwargs.get(_J,WEBSPACE);text=globals().get('content','');extensions=[D,E,'pymdownx.betterem','markdown.extensions.attr_list','markdown.extensions.tables','markdown.extensions.abbr','markdown.extensions.footnotes',F,'pymdownx.highlight',G,H,'pymdownx.tilde','pymdownx.caret','pymdownx.smartsymbols','pymdownx.emoji','pymdownx.escapeall','pymdownx.tasklist','pymdownx.striphtml','pymdownx.snippets',I,'pymdownx.saneheaders',J,K,'pymdownx.blocks.details','pymdownx.blocks.html','pymdownx.blocks.definition',L];extension_configs={D:{'slugify':slugs.slugify(case='lower'),'permalink':''},E:{'smart_quotes':_A},J:{'generic':_B,'block_tag':'pre'},F:{'preserve_tabs':_B,'custom_fences':[{A:M,_F:M,B:superfences.fence_code_format},{A:_K,_F:_K,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'python',_F:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'py',_F:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator}]},G:{'custom_inline':[{A:_H,_F:_H,B:color_formatter(LIVE_INIT,gamut)}]},H:{'repo_url_shortener':_B,'repo_url_shorthand':_B,'social_url_shorthand':_B,'user':'facelessuser','repo':'coloraide'},I:{'separator':'＋'},L:{'alternate_style':_B},K:{'types':['new','settings','note','abstract','info','tip','success','question','warning','failure','danger','bug','example','quote']}}\n\ttry:html=markdown.markdown(text,extensions=extensions,extension_configs=extension_configs)\n\texcept Exception:html=''\n\tcontent=document.getElementById('__notebook-render');content.innerHTML=html\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback(gamut='".concat(e,"')\n"),h=window.colorNotebook.defaultPlayground,_=function(t){return"\n/// new | This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). Learn more [here](?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md). Preview, convert, interpolate, and explore!\n///\n\n````````py play\n".concat(t,"\n````````\n")},y=!1,v=!1,w=function(){f=!0,window.document.dispatchEvent(new Event("DOMContentLoaded",{bubbles:!0,cancelable:!0})),window.document$.next()},x=function(t){var e=window.pageXOffset||(document.documentElement||document.body.parentNode||document.body).scrollLeft,n=window.pageYOffset||(document.documentElement||document.body.parentNode||document.body).scrollTop;t.style.height="5px",t.style.height="".concat(t.scrollHeight,"px"),window.scrollTo(e,n)},b=function(t){return encodeURIComponent(t).replace(/[.!'()*]/g,(function(t){return"%".concat(t.charCodeAt(0).toString(16))}))},E=function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(o=document.getElementById("__playground-inputs_".concat(n))).setAttribute("readonly",""),a.globals.set("id_num",n),a.globals.set("action","playground"),t.next=6,a.runPythonAsync(g);case 6:o.removeAttribute("readonly");case 7:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),k=function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return a.globals.set("content",n),a.globals.set("action","notebook"),t.next=4,a.runPythonAsync(g);case 4:(o=document.getElementById("__notebook-input"))&&(s=n,o.value=n),window.location.hash&&(window.location.href=window.location.href);case 7:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),L=function(){var e=n(t().mark((function e(n){var o,i,s,l,c,u;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(d){t.next=5;break}return d=!0,t.next=4,loadPyodide({indexURL:"https://cdn.jsdelivr.net/pyodide/v0.23.0/full/",fullStdLib:!1});case 4:a=t.sent;case 5:if((y||!n)&&(v||n)){t.next=14;break}o="".concat(window.location.origin,"/").concat(window.location.pathname.split("/")[1],"/playground/"),i=n?window.colorNotebook.notebookWheels:window.colorNotebook.playgroundWheels,s=[],n?y=!0:v=!0,l=r(i);try{for(l.s();!(c=l.n()).done;)(u=c.value).endsWith(".whl")?s.push(o+u):s.push(u)}catch(t){l.e(t)}finally{l.f()}return t.next=14,a.loadPackage(s);case 14:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),S=function(t,e,n){var o=null==e?"Loading...":e,r=n?"loading relative":"loading",a=document.createElement("template");a.innerHTML='<div class="'.concat(r,'"><div class="loader"></div><div>').concat(o,"</div></div>"),t.appendChild(a.content.firstChild)},A=function(t){t.querySelector(".loading")&&t.removeChild(t.querySelector(".loading"))},C=function(t){if("Tab"===t.key){var e=t.target;if(e.selectionStart!==e.selectionEnd){t.preventDefault();for(var n=e.selectionStart,o=e.selectionEnd,r=e.value;n>0&&"\n"!==r[n-1];)n--;for(;o>0&&"\n"!==r[o-1]&&o<r.length;)o++;for(var a=r.substr(n,o-n).split("\n"),i=0;i<a.length;i++)i===a.length-1&&0===a[i].length||(t.shiftKey?a[i]=a[i].replace(m,""):a[i]="    ".concat(a[i]));a=a.join("\n"),e.value=r.substr(0,n)+a+r.substr(o),e.selectionStart=n,e.selectionEnd=n+a.length}}},B=function(){var e=n(t().mark((function e(o){var r;return t().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:r=document.getElementById("__notebook-source"),document.querySelectorAll(".playground").forEach((function(e){var a=e.id.replace(u,"$1"),d=document.getElementById("__playground-inputs_".concat(a)),p=document.getElementById("__playground-results_".concat(a)),f=document.getElementById("__playground-code_".concat(a)),m=document.querySelector("button#__playground-edit_".concat(a)),g=document.querySelector("button#__playground-share_".concat(a)),h=document.querySelector("button#__playground-run_".concat(a)),_=document.querySelector("button#__playground-cancel_".concat(a));if(d.addEventListener("input",(function(){x(d)})),d.addEventListener("keydown",C),r&&o){var y=document.getElementById("__notebook-input");y.addEventListener("input",(function(t){x(t.target)})),y.addEventListener("keydown",C),document.getElementById("__notebook-edit").addEventListener("click",(function(){c[y.id]=y.value,document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),x(document.getElementById("__notebook-input"))})),document.getElementById("__notebook-md-gist").addEventListener("click",function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(o=prompt("Please enter link to the Markdown page source:",l))&&(o=b(o),n.preventDefault(),history.pushState({notebook:o},"","?".concat(new URLSearchParams("notebook=".concat(o)).toString())),I(!1));case 2:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),document.getElementById("__notebook-py-gist").addEventListener("click",function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(o=prompt("Please enter the link to the Python code source:",l))&&(o=b(o),n.preventDefault(),history.pushState({source:o},"","?".concat(new URLSearchParams("source=".concat(o)).toString())),I(!1));case 2:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),document.getElementById("__notebook-input").value=s,document.getElementById("__notebook-cancel").addEventListener("click",(function(){y.value=c[y.id],delete c[y.id],document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden")})),document.getElementById("__notebook-submit").addEventListener("click",n(t().mark((function e(){var n,o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=document.getElementById("__notebook-render"),s=document.getElementById("__notebook-input").value,n.classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),o=document.querySelector("article"),S(o,"Loading Notebook..."),n.innerHTML="",c={},t.next=10,L(!0);case 10:return t.next=12,k(s);case 12:return t.next=14,B();case 14:A(o),w();case 16:case"end":return t.stop()}}),e)}))))}d.addEventListener("touchmove",(function(t){t.stopPropagation()})),p.addEventListener("click",(function(t){var e=t.target;if(e.matches("span.swatch-color")){var n="",o=e.parentNode;if(!o.matches("span.swatch-gradient")){if(n=(n=o.getAttribute("title").replace("Copy to clipboard","")).replace("\n",""),window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",n);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){var r=document.createElement("textarea");r.textContent=n,r.style.position="fixed",document.body.appendChild(r),r.select();try{return document.execCommand("copy")}catch(t){return prompt("Copy to clipboard: Ctrl+C, Enter",n)}finally{document.body.removeChild(r)}}}}})),m.addEventListener("click",n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:c[a]=d.value,f.classList.toggle("hidden"),p.classList.toggle("hidden"),h.classList.toggle("hidden"),_.classList.toggle("hidden"),m.classList.toggle("hidden"),g.classList.toggle("hidden"),x(d),d.focus();case 9:case"end":return t.stop()}}),e)})))),g.addEventListener("click",n(t().mark((function e(){var o,r,a,i,s;return t().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:o=window.location.pathname.split("/")[1],r=b(d.value),a=window.location,i="/playground/",a.pathname.startsWith("/".concat(o,"/"))&&(i="/".concat(o,"/playground/")),(s="".concat(a.protocol,"//").concat(a.host).concat(i,"?code=").concat(r)).length>2e3?alert("Code must be small enough to generate a shareable URL under 2000 characters!"):navigator.clipboard.writeText(s).then(n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Link copied to clipboard :)");case 1:case"end":return t.stop()}}),e)}))),n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Failed to copy link clipboard!");case 1:case"end":return t.stop()}}),e)}))));case 7:case"end":return e.stop()}}),e)})))),h.addEventListener("click",n(t().mark((function e(){var n,o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!i){t.next=2;break}return t.abrupt("return");case 2:return i=!0,n=f.querySelector("form"),S(n,null,!0),(o=document.querySelectorAll(".playground .playground-run"))&&o.forEach((function(t){t.setAttribute("disabled","")})),t.next=9,L(!1);case 9:return p.querySelector("code").innerHTML="",t.next=12,E(a);case 12:o&&o.forEach((function(t){t.removeAttribute("disabled")})),A(n),f.classList.toggle("hidden"),p.classList.toggle("hidden"),m.classList.toggle("hidden"),g.classList.toggle("hidden"),h.classList.toggle("hidden"),_.classList.toggle("hidden"),delete c[a],i=!1;case 22:case"end":return t.stop()}}),e)})))),_.addEventListener("click",(function(){d.value=c[a],delete c[a],f.classList.toggle("hidden"),p.classList.toggle("hidden"),m.classList.toggle("hidden"),g.classList.toggle("hidden"),h.classList.toggle("hidden"),_.classList.toggle("hidden")}))}));case 3:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),I=function(){var e=n(t().mark((function e(o,r){var a,i,s,u,d,f,m,g,y;return t().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(c={},!window.location.pathname.endsWith("/playground/")){e.next=32;break}if(a=r||new URLSearchParams(window.location.search),i="Loading Pyodide...",s="Loading Notebook...",u=a.has("source")?a.get("source"):a.get("notebook"),d=document.querySelector("article"),null===u||!u.trim()){e.next=16;break}return S(d,i),e.next=11,L(!0);case 11:A(d),S(d,s);try{f=a.has("source")?"source":"notebook",p=decodeURIComponent(a.toString()),m="",g=new XMLHttpRequest,l=u,g.open("GET",u,!0),g.onload=n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return 4===g.readyState&&200===g.status&&(m=g.responseText),"source"===f&&(m=_(m)),t.next=4,k(m);case 4:return t.next=6,B(o);case 6:A(d),w();case 8:case"end":return t.stop()}}),e)}))),g.send()}catch(t){}e.next=30;break;case 16:return l="",y=_(a.has("code")?a.get("code"):h),p=decodeURIComponent(a.toString()),S(d,i),e.next=22,L(!0);case 22:return A(d),S(d,s),e.next=26,k(y);case 26:return e.next=28,B(o);case 28:A(d),w();case 30:e.next=35;break;case 32:l="",p="",B(o);case 35:case"end":return e.stop()}}),e)})));return function(t,n){return e.apply(this,arguments)}}();document.addEventListener("click",(function(t){var e=window.location.pathname.split("/")[1],n=t.target||t.srcElement;if("A"===n.tagName&&I&&n.getAttribute("href")&&n.host===window.location.host&&window.location.pathname==="/".concat(e,"/playground/")&&window.location.pathname===n.pathname&&window.location.search!==n.search){t.preventDefault();var o=new URLSearchParams(n.search);I(!1,o)}}),!0),window.addEventListener("popstate",(function(){var t=window.location.pathname.split("/")[1];window.location.pathname==="/".concat(t,"/playground/")&&(decodeURIComponent(new URLSearchParams(window.location.search).toString())!==p&&I(!1))})),window.addEventListener("unload",(function(){f=!1})),window.document$.subscribe((function(){f?f=!1:I(!0)}))}()}();
-//# sourceMappingURL=extra-notebook-40c84faf.js.map
+function _typeof(t){return _typeof="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},_typeof(t)}var runtime=function(t){"use strict";var e,n=Object.prototype,o=n.hasOwnProperty,r=Object.defineProperty||function(t,e,n){t[e]=n.value},a="function"==typeof Symbol?Symbol:{},i=a.iterator||"@@iterator",s=a.asyncIterator||"@@asyncIterator",l=a.toStringTag||"@@toStringTag";function c(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{c({},"")}catch(t){c=function(t,e,n){return t[e]=n}}function u(t,e,n,o){var a=e&&e.prototype instanceof _?e:_,i=Object.create(a.prototype),s=new I(o||[]);return r(i,"_invoke",{value:S(t,n,s)}),i}function d(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}t.wrap=u;var p="suspendedStart",f="suspendedYield",m="executing",g="completed",h={};function _(){}function y(){}function v(){}var w={};c(w,i,(function(){return this}));var x=Object.getPrototypeOf,b=x&&x(x(T([])));b&&b!==n&&o.call(b,i)&&(w=b);var E=v.prototype=_.prototype=Object.create(w);function k(t){["next","throw","return"].forEach((function(e){c(t,e,(function(t){return this._invoke(e,t)}))}))}function L(t,e){function n(r,a,i,s){var l=d(t[r],t,a);if("throw"!==l.type){var c=l.arg,u=c.value;return u&&"object"===_typeof(u)&&o.call(u,"__await")?e.resolve(u.__await).then((function(t){n("next",t,i,s)}),(function(t){n("throw",t,i,s)})):e.resolve(u).then((function(t){c.value=t,i(c)}),(function(t){return n("throw",t,i,s)}))}s(l.arg)}var a;r(this,"_invoke",{value:function(t,o){function r(){return new e((function(e,r){n(t,o,e,r)}))}return a=a?a.then(r,r):r()}})}function S(t,e,n){var o=p;return function(r,a){if(o===m)throw new Error("Generator is already running");if(o===g){if("throw"===r)throw a;return O()}for(n.method=r,n.arg=a;;){var i=n.delegate;if(i){var s=A(i,n);if(s){if(s===h)continue;return s}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if(o===p)throw o=g,n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o=m;var l=d(t,e,n);if("normal"===l.type){if(o=n.done?g:f,l.arg===h)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o=g,n.method="throw",n.arg=l.arg)}}}function A(t,n){var o=n.method,r=t.iterator[o];if(r===e)return n.delegate=null,"throw"===o&&t.iterator.return&&(n.method="return",n.arg=e,A(t,n),"throw"===n.method)||"return"!==o&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+o+"' method")),h;var a=d(r,t.iterator,n.arg);if("throw"===a.type)return n.method="throw",n.arg=a.arg,n.delegate=null,h;var i=a.arg;return i?i.done?(n[t.resultName]=i.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=e),n.delegate=null,h):i:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,h)}function C(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function B(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function I(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(C,this),this.reset(!0)}function T(t){if(t){var n=t[i];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,a=function n(){for(;++r<t.length;)if(o.call(t,r))return n.value=t[r],n.done=!1,n;return n.value=e,n.done=!0,n};return a.next=a}}return{next:O}}function O(){return{value:e,done:!0}}return y.prototype=v,r(E,"constructor",{value:v,configurable:!0}),r(v,"constructor",{value:y,configurable:!0}),y.displayName=c(v,l,"GeneratorFunction"),t.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===y||"GeneratorFunction"===(e.displayName||e.name))},t.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,v):(t.__proto__=v,c(t,l,"GeneratorFunction")),t.prototype=Object.create(E),t},t.awrap=function(t){return{__await:t}},k(L.prototype),c(L.prototype,s,(function(){return this})),t.AsyncIterator=L,t.async=function(e,n,o,r,a){void 0===a&&(a=Promise);var i=new L(u(e,n,o,r),a);return t.isGeneratorFunction(n)?i:i.next().then((function(t){return t.done?t.value:i.next()}))},k(E),c(E,l,"Generator"),c(E,i,(function(){return this})),c(E,"toString",(function(){return"[object Generator]"})),t.keys=function(t){var e=Object(t),n=[];for(var o in e)n.push(o);return n.reverse(),function t(){for(;n.length;){var o=n.pop();if(o in e)return t.value=o,t.done=!1,t}return t.done=!0,t}},t.values=T,I.prototype={constructor:I,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=e,this.done=!1,this.delegate=null,this.method="next",this.arg=e,this.tryEntries.forEach(B),!t)for(var n in this)"t"===n.charAt(0)&&o.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=e)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var n=this;function r(o,r){return s.type="throw",s.arg=t,n.next=o,r&&(n.method="next",n.arg=e),!!r}for(var a=this.tryEntries.length-1;a>=0;--a){var i=this.tryEntries[a],s=i.completion;if("root"===i.tryLoc)return r("end");if(i.tryLoc<=this.prev){var l=o.call(i,"catchLoc"),c=o.call(i,"finallyLoc");if(l&&c){if(this.prev<i.catchLoc)return r(i.catchLoc,!0);if(this.prev<i.finallyLoc)return r(i.finallyLoc)}else if(l){if(this.prev<i.catchLoc)return r(i.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<i.finallyLoc)return r(i.finallyLoc)}}}},abrupt:function(t,e){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev<r.finallyLoc){var a=r;break}}a&&("break"===t||"continue"===t)&&a.tryLoc<=e&&e<=a.finallyLoc&&(a=null);var i=a?a.completion:{};return i.type=t,i.arg=e,a?(this.method="next",this.next=a.finallyLoc,h):this.complete(i)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),h},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),B(n),h}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var o=n.completion;if("throw"===o.type){var r=o.arg;B(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,o){return this.delegate={iterator:T(t),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=e),h}},t}("object"===("undefined"==typeof module?"undefined":_typeof(module))?module.exports:{});try{regeneratorRuntime=runtime}catch(t){"object"===("undefined"==typeof globalThis?"undefined":_typeof(globalThis))?globalThis.regeneratorRuntime=runtime:Function("r","regeneratorRuntime = r")(runtime)}!function(){"use strict";function t(){t=function(){return e};var e={},n=Object.prototype,o=n.hasOwnProperty,r=Object.defineProperty||function(t,e,n){t[e]=n.value},a="function"==typeof Symbol?Symbol:{},i=a.iterator||"@@iterator",s=a.asyncIterator||"@@asyncIterator",l=a.toStringTag||"@@toStringTag";function c(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{c({},"")}catch(t){c=function(t,e,n){return t[e]=n}}function u(t,e,n,o){var a=e&&e.prototype instanceof f?e:f,i=Object.create(a.prototype),s=new S(o||[]);return r(i,"_invoke",{value:b(t,n,s)}),i}function d(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}e.wrap=u;var p={};function f(){}function m(){}function g(){}var h={};c(h,i,(function(){return this}));var _=Object.getPrototypeOf,y=_&&_(_(A([])));y&&y!==n&&o.call(y,i)&&(h=y);var v=g.prototype=f.prototype=Object.create(h);function w(t){["next","throw","return"].forEach((function(e){c(t,e,(function(t){return this._invoke(e,t)}))}))}function x(t,e){function n(r,a,i,s){var l=d(t[r],t,a);if("throw"!==l.type){var c=l.arg,u=c.value;return u&&"object"==_typeof(u)&&o.call(u,"__await")?e.resolve(u.__await).then((function(t){n("next",t,i,s)}),(function(t){n("throw",t,i,s)})):e.resolve(u).then((function(t){c.value=t,i(c)}),(function(t){return n("throw",t,i,s)}))}s(l.arg)}var a;r(this,"_invoke",{value:function(t,o){function r(){return new e((function(e,r){n(t,o,e,r)}))}return a=a?a.then(r,r):r()}})}function b(t,e,n){var o="suspendedStart";return function(r,a){if("executing"===o)throw new Error("Generator is already running");if("completed"===o){if("throw"===r)throw a;return C()}for(n.method=r,n.arg=a;;){var i=n.delegate;if(i){var s=E(i,n);if(s){if(s===p)continue;return s}}if("next"===n.method)n.sent=n._sent=n.arg;else if("throw"===n.method){if("suspendedStart"===o)throw o="completed",n.arg;n.dispatchException(n.arg)}else"return"===n.method&&n.abrupt("return",n.arg);o="executing";var l=d(t,e,n);if("normal"===l.type){if(o=n.done?"completed":"suspendedYield",l.arg===p)continue;return{value:l.arg,done:n.done}}"throw"===l.type&&(o="completed",n.method="throw",n.arg=l.arg)}}}function E(t,e){var n=e.method,o=t.iterator[n];if(void 0===o)return e.delegate=null,"throw"===n&&t.iterator.return&&(e.method="return",e.arg=void 0,E(t,e),"throw"===e.method)||"return"!==n&&(e.method="throw",e.arg=new TypeError("The iterator does not provide a '"+n+"' method")),p;var r=d(o,t.iterator,e.arg);if("throw"===r.type)return e.method="throw",e.arg=r.arg,e.delegate=null,p;var a=r.arg;return a?a.done?(e[t.resultName]=a.value,e.next=t.nextLoc,"return"!==e.method&&(e.method="next",e.arg=void 0),e.delegate=null,p):a:(e.method="throw",e.arg=new TypeError("iterator result is not an object"),e.delegate=null,p)}function k(t){var e={tryLoc:t[0]};1 in t&&(e.catchLoc=t[1]),2 in t&&(e.finallyLoc=t[2],e.afterLoc=t[3]),this.tryEntries.push(e)}function L(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function S(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(k,this),this.reset(!0)}function A(t){if(t){var e=t[i];if(e)return e.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var n=-1,r=function e(){for(;++n<t.length;)if(o.call(t,n))return e.value=t[n],e.done=!1,e;return e.value=void 0,e.done=!0,e};return r.next=r}}return{next:C}}function C(){return{value:void 0,done:!0}}return m.prototype=g,r(v,"constructor",{value:g,configurable:!0}),r(g,"constructor",{value:m,configurable:!0}),m.displayName=c(g,l,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===m||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,g):(t.__proto__=g,c(t,l,"GeneratorFunction")),t.prototype=Object.create(v),t},e.awrap=function(t){return{__await:t}},w(x.prototype),c(x.prototype,s,(function(){return this})),e.AsyncIterator=x,e.async=function(t,n,o,r,a){void 0===a&&(a=Promise);var i=new x(u(t,n,o,r),a);return e.isGeneratorFunction(n)?i:i.next().then((function(t){return t.done?t.value:i.next()}))},w(v),c(v,l,"Generator"),c(v,i,(function(){return this})),c(v,"toString",(function(){return"[object Generator]"})),e.keys=function(t){var e=Object(t),n=[];for(var o in e)n.push(o);return n.reverse(),function t(){for(;n.length;){var o=n.pop();if(o in e)return t.value=o,t.done=!1,t}return t.done=!0,t}},e.values=A,S.prototype={constructor:S,reset:function(t){if(this.prev=0,this.next=0,this.sent=this._sent=void 0,this.done=!1,this.delegate=null,this.method="next",this.arg=void 0,this.tryEntries.forEach(L),!t)for(var e in this)"t"===e.charAt(0)&&o.call(this,e)&&!isNaN(+e.slice(1))&&(this[e]=void 0)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(t){if(this.done)throw t;var e=this;function n(n,o){return i.type="throw",i.arg=t,e.next=n,o&&(e.method="next",e.arg=void 0),!!o}for(var r=this.tryEntries.length-1;r>=0;--r){var a=this.tryEntries[r],i=a.completion;if("root"===a.tryLoc)return n("end");if(a.tryLoc<=this.prev){var s=o.call(a,"catchLoc"),l=o.call(a,"finallyLoc");if(s&&l){if(this.prev<a.catchLoc)return n(a.catchLoc,!0);if(this.prev<a.finallyLoc)return n(a.finallyLoc)}else if(s){if(this.prev<a.catchLoc)return n(a.catchLoc,!0)}else{if(!l)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return n(a.finallyLoc)}}}},abrupt:function(t,e){for(var n=this.tryEntries.length-1;n>=0;--n){var r=this.tryEntries[n];if(r.tryLoc<=this.prev&&o.call(r,"finallyLoc")&&this.prev<r.finallyLoc){var a=r;break}}a&&("break"===t||"continue"===t)&&a.tryLoc<=e&&e<=a.finallyLoc&&(a=null);var i=a?a.completion:{};return i.type=t,i.arg=e,a?(this.method="next",this.next=a.finallyLoc,p):this.complete(i)},complete:function(t,e){if("throw"===t.type)throw t.arg;return"break"===t.type||"continue"===t.type?this.next=t.arg:"return"===t.type?(this.rval=this.arg=t.arg,this.method="return",this.next="end"):"normal"===t.type&&e&&(this.next=e),p},finish:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.finallyLoc===t)return this.complete(n.completion,n.afterLoc),L(n),p}},catch:function(t){for(var e=this.tryEntries.length-1;e>=0;--e){var n=this.tryEntries[e];if(n.tryLoc===t){var o=n.completion;if("throw"===o.type){var r=o.arg;L(n)}return r}}throw new Error("illegal catch attempt")},delegateYield:function(t,e,n){return this.delegate={iterator:A(t),resultName:e,nextLoc:n},"next"===this.method&&(this.arg=void 0),p}},e}function e(t,e,n,o,r,a,i){try{var s=t[a](i),l=s.value}catch(t){return void n(t)}s.done?e(l):Promise.resolve(l).then(o,r)}function n(t){return function(){var n=this,o=arguments;return new Promise((function(r,a){var i=t.apply(n,o);function s(t){e(i,r,a,s,l,"next",t)}function l(t){e(i,r,a,s,l,"throw",t)}s(void 0)}))}}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=new Array(e);n<e;n++)o[n]=t[n];return o}function r(t,e){var n="undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(!n){if(Array.isArray(t)||(n=function(t,e){if(t){if("string"==typeof t)return o(t,e);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?o(t,e):void 0}}(t))||e&&t&&"number"==typeof t.length){n&&(t=n);var r=0,a=function(){};return{s:a,n:function(){return r>=t.length?{done:!0}:{done:!1,value:t[r++]}},e:function(t){throw t},f:a}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,s=!0,l=!1;return{s:function(){n=n.call(t)},n:function(){var t=n.next();return s=t.done,t},e:function(t){l=!0,i=t},f:function(){try{s||null==n.return||n.return()}finally{if(l)throw i}}}}!function(){var e="";try{var o="srgb";window.matchMedia("(color-gamut: rec2020)").matches?o="rec2020":window.matchMedia("(color-gamut: p3)").matches&&(o="display-p3"),e=CSS.supports("color: color(display-p3 1 0 0)")?o:"srgb"}catch(t){e="srgb"}var a=null,i=!1,s="",l="",c={},u=/.*?_(\d+)$/,d=!1,p="",f=!1,m=/^( {1,4}|\t)/,g="\n_O='<div class=\"color-command\">{}</div>'\n_N='swatch'\n_M='transparent'\n_L='pycon'\n_K='playground'\n_J='gamut'\n_I='exceptions'\n_H='color'\n_G='highlight'\n_F='class'\n_E='eval'\n_D='<string>'\n_C=None\n_B=True\n_A=False\nimport xml.etree.ElementTree as Etree\nfrom collections.abc import Sequence,Mapping\nfrom collections import namedtuple\nimport ast\nfrom io import StringIO\nimport sys,re\nfrom functools import partial\nfrom pygments import highlight\nfrom pygments.lexers import get_lexer_by_name\nfrom pygments.formatters import find_formatter_class\nfrom coloraide import Color\nfrom coloraide.interpolate import Interpolator,normalize_domain\ntry:from coloraide_extras.everything import ColorAll\nexcept ImportError:from coloraide.everything import ColorAll\nPY310=(3,10)<=sys.version_info\nPY311=(3,11)<=sys.version_info\nWEBSPACE='srgb'\nAST_BLOCKS=ast.If,ast.For,ast.While,ast.Try,ast.With,ast.FunctionDef,ast.ClassDef,ast.AsyncFor,ast.AsyncWith,ast.AsyncFunctionDef\nif PY310:AST_BLOCKS=AST_BLOCKS+(ast.Match,)\nif PY311:AST_BLOCKS=AST_BLOCKS+(ast.TryStar,)\nRE_INIT=re.compile('^\\\\s*#\\\\s*pragma:\\\\s*init\\\\n(.*?)#\\\\s*pragma:\\\\s*init\\\\n',re.DOTALL|re.I)\nRE_COLOR_START=re.compile('(?i)(?:\\\\b(?<![-#&$])(?:color|hsla?|lch|lab|hwb|rgba?)\\\\(|\\\\b(?<![-#&$])[\\\\w]{3,}(?![(-])\\\\b|(?<![&])#)')\nLIVE_INIT='\\nfrom coloraide import *\\nimport coloraide\\ntry:\\n    import coloraide_extras\\n    from coloraide_extras.everything import ColorAll as Color\\nexcept ImportError:\\n    from coloraide.everything import ColorAll as Color\\n'\ntemplate='<div class=\"playground\" id=\"__playground_{el_id}\">\\n<div class=\"playground-results\" id=\"__playground-results_{el_id}\">\\n{results}\\n</div>\\n<div class=\"playground-code hidden\" id=\"__playground-code_{el_id}\" data-search-exclude>\\n<form autocomplete=\"off\">\\n<textarea class=\"playground-inputs\" id=\"__playground-inputs_{el_id}\" spellcheck=\"false\">{raw_source}</textarea>\\n</form>\\n</div>\\n<div class=\"playground-footer\" data-search-exclude>\\n<hr>\\n<button id=\"__playground-edit_{el_id}\" class=\"playground-edit\" title=\"Edit the current snippet\">Edit</button>\\n<button id=\"__playground-share_{el_id}\" class=\"playground-share\" title=\"Copy URL to current snippet\">Share</button>\\n<button id=\"__playground-run_{el_id}\" class=\"playground-run hidden\" title=\"Run code (Ctrl + Enter)\">Run</button>\\n<button id=\"__playground-cancel_{el_id}\" class=\"playground-cancel hidden\" title=\"Cancel edit (Escape)\">Cancel</button>\\n<span class=\\'gamut\\'>Gamut: {gamut}</span>\\n</div>\\n</div>'\ncode_id=0\nclass Ramp(list):0\nclass Steps(list):0\nclass Row(list):0\nclass ColorTuple(namedtuple('ColorTuple',['string',_H])):0\nclass AtomicString(str):0\nclass Break(Exception):0\nclass Continue(Exception):0\nHtmlRow=Row\nHtmlSteps=Steps\nHtmlGradient=Ramp\ndef _escape(txt):txt=txt.replace('&','&amp;');txt=txt.replace('<','&lt;');txt=txt.replace('>','&gt;');return txt\nclass StreamOut:\n\tdef __init__(self):self.old=sys.stdout;self.stdout=StringIO();sys.stdout=self.stdout\n\tdef read(self):\n\t\tvalue=''\n\t\tif self.stdout is not _C:self.stdout.flush();value=self.stdout.getvalue();self.stdout=StringIO();sys.stdout=self.stdout\n\t\treturn value\n\tdef __enter__(self):return self\n\tdef __exit__(self,type,value,traceback):sys.stdout=self.old;self.old=_C;self.stdout=_C\ndef get_colors(result):\n\tdomain=[]\n\tif isinstance(result,AtomicString):yield find_colors(result)\n\tif isinstance(result,Row):yield Row([ColorTuple(c.to_string(fit=_A),c.clone())if isinstance(c,Color)else ColorTuple(c,ColorAll(c))for c in result])\n\telif isinstance(result,(Steps,Ramp)):t=type(result);yield t([c.clone()if isinstance(c,Color)else ColorAll(c)for c in result])\n\telif isinstance(result,Color):yield[ColorTuple(result.to_string(fit=_A),result.clone())]\n\telif isinstance(result,Interpolator):\n\t\tif result.domain:domain=result.domain;result.domain=normalize_domain(result.domain)\n\t\tgrad=Ramp(result.steps(steps=5,max_delta_e=2.3))\n\t\tif domain:result.domain=domain;domain=[]\n\t\tyield grad\n\telif isinstance(result,str):\n\t\ttry:yield[ColorTuple(result,ColorAll(result))]\n\t\texcept Exception:pass\n\telif isinstance(result,(list,tuple)):\n\t\tfor r in result:\n\t\t\tfor x in get_colors(r):\n\t\t\t\tif x:yield x\ndef find_colors(text):\n\tcolors=[]\n\tfor m in RE_COLOR_START.finditer(text):\n\t\tstart=m.start();mcolor=ColorAll.match(text,start=start)\n\t\tif mcolor is not _C:colors.append(ColorTuple(text[mcolor.start:mcolor.end],mcolor.color))\n\treturn colors\ndef evaluate_with(node,g,loop,index=0):\n\tl=len(node.items)-1;withitem=node.items[index]\n\tif withitem.context_expr:\n\t\twith eval(compile(ast.Expression(withitem.context_expr),_D,_E),g)as w:\n\t\t\tg[withitem.optional_vars.id]=w\n\t\t\tif index<l:evaluate_with(node,g,loop,index+1)\n\t\t\telse:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\telse:\n\t\twith eval(compile(ast.Expression(withitem.context_expr),_D,_E),g):\n\t\t\tif index<l:evaluate_with(node,g,loop,index+1)\n\t\t\telse:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\ndef compare_match(s,g,node):\n\tif isinstance(node,ast.MatchOr):\n\t\tfor pattern in node.patterns:\n\t\t\tif compare_match(s,g,pattern):return _B\n\telif isinstance(node,ast.MatchValue):p=eval(compile(ast.Expression(node.value),_D,_E),g);return s==p\n\telif isinstance(node,ast.MatchSingleton):return s is node.value\n\telif isinstance(node,ast.MatchSequence):\n\t\tif isinstance(s,Sequence):\n\t\t\tstar=isinstance(node.patterns[-1],ast.MatchStar);l1,l2=len(s),len(node.patterns)\n\t\t\tif star and l1>=l2-1 or l1==l2:\n\t\t\t\tfor (e,p) in enumerate(node.patterns[:-1]if star else node.patterns):\n\t\t\t\t\tif not compare_match(s[e],g,p):return _A\n\t\t\t\tif star and node.patterns[-1].name:g[node.patterns[-1].name]=s[l2-1:]\n\t\t\t\treturn _B\n\t\treturn _A\n\telif isinstance(node,ast.MatchMapping):\n\t\tif isinstance(s,Mapping):\n\t\t\tstar=node.rest;l1,l2=len(s),len(node.patterns)\n\t\t\tif star and l1>=l2 or l1==l2:\n\t\t\t\tkeys=set()\n\t\t\t\tfor (kp,vp) in zip(node.keys,node.patterns):\n\t\t\t\t\tkey=eval(compile(ast.Expression(kp),_D,_E),g);keys.add(key)\n\t\t\t\t\tif key not in s:return _A\n\t\t\t\t\tif not compare_match(s[key],g,vp):return _A\n\t\t\t\tif star:g[star]={k:v for(k,v)in s.items()if k not in keys}\n\t\t\t\treturn _B\n\t\treturn _A\n\telif isinstance(node,ast.MatchClass):\n\t\tname=g.get(node.cls.id,_C)\n\t\tif name is _C:raise NameError(\"name '{}' is not defined\".format(node.cls.id))\n\t\tif not isinstance(s,name):return _A\n\t\tma=getattr(s,'__match_args__',tuple());l1=len(ma);l2=len(node.patterns)\n\t\tif l1<l2:raise TypeError('{}() accepts {} positional sub-patterns ({} given)'.format(name,l1,l2))\n\t\tfor (e,p) in enumerate(node.patterns):\n\t\t\tif not hasattr(s,ma[e]):return _A\n\t\t\tif not compare_match(getattr(s,ma[e]),g,p):return _A\n\t\tfor (a,p) in zip(node.kwd_attrs,node.kwd_patterns):\n\t\t\tif not hasattr(s,a):return _A\n\t\t\tif not compare_match(getattr(s,a),g,p):return _A\n\t\treturn _B\n\telif isinstance(node,ast.MatchAs):\n\t\tif node.name is not _C:g[node.name]=s\n\t\tif node.pattern:return compare_match(s,g,node.pattern)\n\t\treturn _B\n\traise RuntimeError('Unknown Match pattern {}'.format(str(node)))\ndef evaluate_except(node,e,g,loop=_A):\n\tfor n in node.handlers:\n\t\tif n.name:g[n.name]=e\n\t\tif n.type is _C:\n\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\tbreak\n\t\telif isinstance(e,eval(compile(ast.Expression(n.type),_D,_E),g)):\n\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\tbreak\n\telse:raise\ndef evaluate(node,g,loop=_A):\n\tif loop and isinstance(node,ast.Break):raise Break\n\tif loop and isinstance(node,ast.Continue):raise Continue\n\tif isinstance(node,ast.Expr):_eval=ast.Expression(node.value);yield eval(compile(_eval,_D,_E),g)\n\telif isinstance(node,ast.If):\n\t\tif eval(compile(ast.Expression(node.test),_D,_E),g):\n\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\t\telif node.orelse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\telif isinstance(node,ast.While):\n\t\twhile eval(compile(ast.Expression(node.test),_D,_E),g):\n\t\t\ttry:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,_B)\n\t\t\texcept Break:break\n\t\t\texcept Continue:continue\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\telif isinstance(node,ast.For):\n\t\tfor x in eval(compile(ast.Expression(node.iter),_D,_E),g):\n\t\t\tif isinstance(node.target,ast.Tuple):\n\t\t\t\tfor (e,t) in enumerate(node.target.dims):g[t.id]=x[e]\n\t\t\telse:g[node.target.id]=x\n\t\t\ttry:\n\t\t\t\tfor n in node.body:yield from evaluate(n,g,_B)\n\t\t\texcept Break:break\n\t\t\texcept Continue:continue\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\telif isinstance(node,ast.Try):\n\t\ttry:\n\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\t\texcept Exception as e:yield from evaluate_except(node,e,g,loop)\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\t\tfinally:\n\t\t\tfor n in node.finalbody:yield from evaluate(n,g,loop)\n\telif PY311 and isinstance(node,ast.TryStar):\n\t\ttry:\n\t\t\tfor n in node.body:yield from evaluate(n,g,loop)\n\t\texcept ExceptionGroup as e:\n\t\t\tfor n in node.handlers:\n\t\t\t\tif n.name:g[n.name]=e\n\t\t\t\tm,e=e.split(eval(compile(ast.Expression(n.type),_D,_E),g))\n\t\t\t\tif m is not _C:\n\t\t\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\t\tif e is _C:break\n\t\t\tif e is not _C:raise e\n\t\texcept Exception as e:yield from evaluate_except(node,e,g,loop)\n\t\telse:\n\t\t\tfor n in node.orelse:yield from evaluate(n,g,loop)\n\t\tfinally:\n\t\t\tfor n in node.finalbody:yield from evaluate(n,g,loop)\n\telif PY310 and isinstance(node,ast.Match):\n\t\ts=eval(compile(ast.Expression(node.subject),_D,_E),g)\n\t\tfor c in node.cases:\n\t\t\tif compare_match(s,g,c.pattern):\n\t\t\t\tif not c.guard or eval(compile(ast.Expression(c.guard),_D,_E),g):\n\t\t\t\t\tfor n in c.body:yield from evaluate(n,g,loop)\n\t\t\t\t\tbreak\n\telif isinstance(node,ast.With):yield from evaluate_with(node,g,loop)\n\telse:_exec=ast.Module([node],[]);exec(compile(_exec,_D,'exec'),g);yield _C\ndef execute(cmd,no_except=_B,inline=_A,init='',g=_C):\n\tA='\\n';console='';colors=[]\n\tif g is _C:g={'Ramp':Ramp,'Steps':Steps,'Row':Row,'HtmlRow':HtmlRow,'HtmlSteps':HtmlSteps,'HtmlGradient':HtmlGradient}\n\tif init:execute(init.strip(),g=g)\n\tm=RE_INIT.match(cmd)\n\tif m:block_init=m.group(1);src=cmd[m.end():];execute(block_init,g=g)\n\telse:src=cmd\n\tlines=src.split(A)\n\ttry:tree=ast.parse(src)\n\texcept Exception as e:\n\t\tif no_except:\n\t\t\tif not inline:from pymdownx.superfences import SuperFencesException;raise SuperFencesException from e\n\t\t\telse:from pymdownx.inlinehilite import InlineHiliteException;raise InlineHiliteException from e\n\t\timport traceback;return '{}'.format(traceback.format_exc()),colors\n\tfor node in tree.body:\n\t\tresult=[];start=node.lineno;end=node.end_lineno;stmt=lines[start-1:end];command=''\n\t\tfor (i,line) in enumerate(stmt,0):\n\t\t\tif i==0:stmt[i]='>>> '+line\n\t\t\telse:stmt[i]='... '+line\n\t\tcommand+=A.join(stmt)\n\t\tif isinstance(node,AST_BLOCKS):command+='\\n... '\n\t\ttry:\n\t\t\twith StreamOut()as s:\n\t\t\t\tfor x in evaluate(node,g):\n\t\t\t\t\tresult.append(x);text=s.read()\n\t\t\t\t\tif text:result.append(AtomicString(text))\n\t\t\t\tconsole+=command\n\t\texcept Exception as e:\n\t\t\tif no_except:\n\t\t\t\tif not inline:from pymdownx.superfences import SuperFencesException;raise SuperFencesException from e\n\t\t\t\telse:from pymdownx.inlinehilite import InlineHiliteException;raise InlineHiliteException from e\n\t\t\timport traceback;console+='{}\\n{}'.format(command,traceback.format_exc());break\n\t\tresult_text=A\n\t\tfor r in result:\n\t\t\tif r is _C:continue\n\t\t\tfor clist in get_colors(r):\n\t\t\t\tif clist:colors.append(clist)\n\t\t\tresult_text+='{}{}'.format(repr(r)if isinstance(r,str)and not isinstance(r,AtomicString)else str(r),A if not isinstance(r,AtomicString)else'')\n\t\tconsole+=result_text\n\treturn console,colors\ndef colorize(src,lang,**options):HtmlFormatter=find_formatter_class('html');lexer=get_lexer_by_name(lang,**options);formatter=HtmlFormatter(cssclass=_G,wrapcode=_B);return highlight(src,lexer,formatter).strip()\ndef color_command_validator(language,inputs,options,attrs,md):\n\tvalid_inputs=set([_I,'play'])\n\tfor (k,v) in inputs.items():\n\t\tif k in valid_inputs:options[k]=_B;continue\n\t\tattrs[k]=v\n\treturn _B\ndef _color_command_console(colors,gamut=WEBSPACE):\n\tC='{} {}%';B=' ';A='<div class=\"swatch-bar\">{}</div>';el='';bar=_A;values=[]\n\tfor item in colors:\n\t\tif isinstance(item,(HtmlGradient,Steps)):\n\t\t\tcurrent=total=percent=last=0\n\t\t\tif isinstance(item,Steps):total=len(item);percent=100/total;current=percent\n\t\t\tif bar:el+=A.format(B.join(values));values=[]\n\t\t\tsub_el1='<div class=\"swatch-bar\"><span class=\"swatch swatch-gradient\">{}</span></div>';style='--swatch-stops: ';stops=[]\n\t\t\tfor (e,color) in enumerate(item):\n\t\t\t\tcolor.fit(gamut)\n\t\t\t\tif current:\n\t\t\t\t\tstops.append(C.format(color.convert(gamut).to_string(),str(last)));stops.append(C.format(color.convert(gamut).to_string(),str(current)));last=current\n\t\t\t\t\tif e<total-1:current+=percent\n\t\t\t\t\telse:current=100\n\t\t\t\telse:stops.append(color.convert(gamut).to_string())\n\t\t\tif not stops:stops.extend([_M]*2)\n\t\t\tif len(stops)==1:stops.append(stops[0])\n\t\t\tstyle+=','.join(stops);sub_el2='<span class=\"swatch-color\" style=\"{}\"></span>'.format(style);el+=sub_el1.format(sub_el2);bar=_A\n\t\telse:\n\t\t\tis_row=_A\n\t\t\tif isinstance(item,Row):\n\t\t\t\tis_row=_B\n\t\t\t\tif bar and values:el+=A.format(B.join(values));values=[]\n\t\t\t\tbar=_A\n\t\t\tbar=_B\n\t\t\tfor color in item:\n\t\t\t\tbase_classes=_N\n\t\t\t\tif not color.color.in_gamut(gamut):base_classes+=' out-of-gamut'\n\t\t\t\tcolor.color.fit(gamut);srgb=color.color.convert(gamut);value1=srgb.to_string(alpha=_A);value2=srgb.to_string();style='--swatch-stops: {} 50%, {} 50%'.format(value1,value2);title=color.string;classes=base_classes;c='<span class=\"swatch-color\" style=\"{style}\"></span>'.format(style=style);c='<span class=\"{classes}\" title=\"{title}&#013;Copy to clipboard\">{color}</span>'.format(classes=classes,color=c,title=title);values.append(c)\n\t\t\tif is_row and values:el+=A.format(B.join(values));values=[];bar=_A\n\tif bar:el+=A.format(B.join(values));values=[]\n\treturn el\ndef _color_command_formatter(src='',language='',class_name=_C,options=_C,md='',init='',**kwargs):\n\tB='formatter';A='fenced_code_block';global code_id;from pymdownx.superfences import SuperFencesException;gamut=kwargs.get(_J,WEBSPACE);play=options.get('play',_A)if options is not _C else _A\n\tif not play and language==_K:play=_B\n\tif not play:return md.preprocessors[A].extension.superfences[0][B](src=src,class_name=class_name,language='py',md=md,options=options,**kwargs)\n\ttry:\n\t\tif len(md.preprocessors[A].extension.stash)==0:code_id=0\n\t\texceptions=options.get(_I,_A)if options is not _C else _A;console,colors=execute(src.strip(),not exceptions,init=init);el=_color_command_console(colors,gamut=gamut);el+=md.preprocessors[A].extension.superfences[0][B](src=console,class_name=_G,language=_L,md=md,options=options,**kwargs);el=_O.format(el);el=template.format(el_id=code_id,raw_source=_escape(src),results=el,gamut=gamut);code_id+=1\n\texcept SuperFencesException:raise\n\texcept Exception:from pymdownx import superfences;import traceback;print(traceback.format_exc());return superfences.fence_code_format(src,'text',class_name,options,md,**kwargs)\n\treturn el\ndef color_command_formatter(init='',gamut=WEBSPACE):return partial(_color_command_formatter,init=init,gamut=gamut)\ndef _color_formatter(src='',language='',class_name=_C,md='',exceptions=_B,init='',gamut=WEBSPACE):\n\tE='backtick';D='title';C='Only one color allowed';B=' 50%';A='span';from pymdownx.inlinehilite import InlineHiliteException\n\ttry:\n\t\tresult=src.strip()\n\t\ttry:color=ColorAll(result.strip())\n\t\texcept Exception:\n\t\t\t_,colors=execute(result,exceptions,inline=_B,init=init)\n\t\t\tif len(colors)!=1 or len(colors[0])!=1:\n\t\t\t\tif exceptions:raise InlineHiliteException(C)\n\t\t\t\telse:raise ValueError(C)\n\t\t\tcolor=colors[0][0].color;result=colors[0][0].string\n\t\tel=Etree.Element(A);stops=[]\n\t\tif not color.in_gamut(gamut):\n\t\t\tcolor.fit(gamut);attributes={_F:'swatch out-of-gamut',D:result};sub_el=Etree.SubElement(el,A,attributes);stops.append(color.convert(gamut).to_string(hex=_B,alpha=_A))\n\t\t\tif color[-1]<1.0:stops[-1]+=B;stops.append(color.convert(gamut).to_string(hex=_B)+B)\n\t\telse:\n\t\t\tattributes={_F:_N,D:result};sub_el=Etree.SubElement(el,A,attributes);stops.append(color.convert(gamut).to_string(hex=_B,alpha=_A))\n\t\t\tif color[-1]<1.0:stops[-1]+=B;stops.append(color.convert(gamut).to_string(hex=_B)+B)\n\t\tif not stops:stops.extend([_M]*2)\n\t\tif len(stops)==1:stops.append(stops[0])\n\t\tEtree.SubElement(sub_el,A,{_F:'swatch-color','style':'--swatch-stops: {};'.format(','.join(stops))});el.append(md.inlinePatterns[E].handle_code('css-color',result))\n\texcept InlineHiliteException:raise\n\texcept Exception:import traceback;print(traceback.format_exc());el=md.inlinePatterns[E].handle_code('text',src)\n\treturn el\ndef color_formatter(init='',gamut=WEBSPACE):return partial(_color_formatter,init=init,gamut=gamut)\ndef _live_color_command_formatter(src,init='',gamut=WEBSPACE):\n\ttry:\n\t\tconsole,colors=execute(src.strip(),_A,init=init);el=_color_command_console(colors,gamut=gamut)\n\t\tif not colors:el+='<div class=\"swatch-bar\"></div>'\n\t\tel+=colorize(console,_L,**{'python3':_B,'stripnl':_A});el=_O.format(el)\n\texcept Exception:import traceback;return '<div class=\"color-command\"><div class=\"swatch-bar\"></div>{}</div>'.format(colorize(traceback.format_exc(),_L))\n\treturn el\ndef live_color_command_formatter(init='',gamut=WEBSPACE):return partial(_live_color_command_formatter,init=init,gamut=gamut)\ndef live_color_command_validator(language,inputs,options,attrs,md):value=color_command_validator(language,inputs,options,attrs,md);options[_I]=_B;return value\ndef render_console(*args,**kwargs):\n\tC='.swatch-bar';B='code';A='id_num';from js import document;gamut=kwargs.get(_J,WEBSPACE)\n\ttry:\n\t\tinputs=document.getElementById('__playground-inputs_{}'.format(globals()[A]));results=document.getElementById('__playground-results_{}'.format(globals()[A]));footer=document.querySelector('#__playground_{} .gamut'.format(globals()[A]));result=live_color_command_formatter(LIVE_INIT,gamut)(inputs.value);temp=document.createElement('div');temp.innerHTML=result;cmd=results.querySelector('.color-command')\n\t\tfor el in cmd.querySelectorAll(C):el.remove()\n\t\tfor el in temp.querySelectorAll(C):cmd.insertBefore(el,cmd.lastChild)\n\t\tfooter.innerHTML='Gamut: {}'.format(gamut);pre=cmd.querySelector('pre');pre.replaceChild(temp.querySelector(B),pre.querySelector(B));temp.remove();scrollingElement=results.querySelector(B);scrollingElement.scrollTop=scrollingElement.scrollHeight\n\texcept Exception as e:print(e)\ndef render_notebook(*args,**kwargs):\n\tM='diagram';L='pymdownx.blocks.tab';K='pymdownx.blocks.admonition';J='pymdownx.arithmatex';I='pymdownx.keys';H='pymdownx.magiclink';G='pymdownx.inlinehilite';F='pymdownx.superfences';E='markdown.extensions.smarty';D='markdown.extensions.toc';C='validator';B='format';A='name';import markdown;from pymdownx import slugs,superfences;from js import document;gamut=kwargs.get(_J,WEBSPACE);text=globals().get('content','');extensions=[D,E,'pymdownx.betterem','markdown.extensions.attr_list','markdown.extensions.tables','markdown.extensions.abbr','markdown.extensions.footnotes',F,'pymdownx.highlight',G,H,'pymdownx.tilde','pymdownx.caret','pymdownx.smartsymbols','pymdownx.emoji','pymdownx.escapeall','pymdownx.tasklist','pymdownx.striphtml','pymdownx.snippets',I,'pymdownx.saneheaders',J,K,'pymdownx.blocks.details','pymdownx.blocks.html','pymdownx.blocks.definition',L];extension_configs={D:{'slugify':slugs.slugify(case='lower'),'permalink':''},E:{'smart_quotes':_A},J:{'generic':_B,'block_tag':'pre'},F:{'preserve_tabs':_B,'custom_fences':[{A:M,_F:M,B:superfences.fence_code_format},{A:_K,_F:_K,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'python',_F:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'py',_F:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator}]},G:{'custom_inline':[{A:_H,_F:_H,B:color_formatter(LIVE_INIT,gamut)}]},H:{'repo_url_shortener':_B,'repo_url_shorthand':_B,'social_url_shorthand':_B,'user':'facelessuser','repo':'coloraide'},I:{'separator':'＋'},L:{'alternate_style':_B},K:{'types':['new','settings','note','abstract','info','tip','success','question','warning','failure','danger','bug','example','quote']}}\n\ttry:html=markdown.markdown(text,extensions=extensions,extension_configs=extension_configs)\n\texcept Exception:html=''\n\tcontent=document.getElementById('__notebook-render');content.innerHTML=html\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback(gamut='".concat(e,"')\n"),h=window.colorNotebook.defaultPlayground,_=function(t){return"\n/// new | This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). Learn more [here](?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md). Preview, convert, interpolate, and explore!\n///\n\n````````py play\n".concat(t,"\n````````\n")},y=!1,v=!1,w=function(){f=!0,window.document.dispatchEvent(new Event("DOMContentLoaded",{bubbles:!0,cancelable:!0})),window.document$.next()},x=function(t){var e=window.pageXOffset||(document.documentElement||document.body.parentNode||document.body).scrollLeft,n=window.pageYOffset||(document.documentElement||document.body.parentNode||document.body).scrollTop;t.style.height="5px",t.style.height="".concat(t.scrollHeight,"px"),window.scrollTo(e,n)},b=function(t){return encodeURIComponent(t).replace(/[.!'()*]/g,(function(t){return"%".concat(t.charCodeAt(0).toString(16))}))},E=function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(o=document.getElementById("__playground-inputs_".concat(n))).setAttribute("readonly",""),a.globals.set("id_num",n),a.globals.set("action","playground"),t.next=6,a.runPythonAsync(g);case 6:o.removeAttribute("readonly");case 7:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),k=function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return a.globals.set("content",n),a.globals.set("action","notebook"),t.next=4,a.runPythonAsync(g);case 4:(o=document.getElementById("__notebook-input"))&&(s=n,o.value=n),window.location.hash&&(window.location.href=window.location.href);case 7:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),L=function(){var e=n(t().mark((function e(n){var o,i,s,l,c,u;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(d){t.next=5;break}return d=!0,t.next=4,loadPyodide({indexURL:"https://cdn.jsdelivr.net/pyodide/v0.23.0/full/",fullStdLib:!1});case 4:a=t.sent;case 5:if((y||!n)&&(v||n)){t.next=14;break}o="".concat(window.location.origin,"/").concat(window.location.pathname.split("/")[1],"/playground/"),i=n?window.colorNotebook.notebookWheels:window.colorNotebook.playgroundWheels,s=[],n?y=!0:v=!0,l=r(i);try{for(l.s();!(c=l.n()).done;)(u=c.value).endsWith(".whl")?s.push(o+u):s.push(u)}catch(t){l.e(t)}finally{l.f()}return t.next=14,a.loadPackage(s);case 14:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),S=function(t,e,n){var o=null==e?"Loading...":e,r=n?"loading relative":"loading",a=document.createElement("template");a.innerHTML='<div class="'.concat(r,'"><div class="loader"></div><div>').concat(o,"</div></div>"),t.appendChild(a.content.firstChild)},A=function(t){t.querySelector(".loading")&&t.removeChild(t.querySelector(".loading"))},C=function(t){if("Tab"===t.key){var e=t.target;if(e.selectionStart!==e.selectionEnd){t.preventDefault();for(var n=e.selectionStart,o=e.selectionEnd,r=e.value;n>0&&"\n"!==r[n-1];)n--;for(;o>0&&"\n"!==r[o-1]&&o<r.length;)o++;for(var a=r.substr(n,o-n).split("\n"),i=0;i<a.length;i++)i===a.length-1&&0===a[i].length||(t.shiftKey?a[i]=a[i].replace(m,""):a[i]="    ".concat(a[i]));a=a.join("\n"),e.value=r.substr(0,n)+a+r.substr(o),e.selectionStart=n,e.selectionEnd=n+a.length}}},B=function(){var e=n(t().mark((function e(o){var r;return t().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:r=document.getElementById("__notebook-source"),document.querySelectorAll(".playground").forEach((function(e){var a=e.id.replace(u,"$1"),d=document.getElementById("__playground-inputs_".concat(a)),p=document.getElementById("__playground-results_".concat(a)),f=document.getElementById("__playground-code_".concat(a)),m=document.querySelector("button#__playground-edit_".concat(a)),g=document.querySelector("button#__playground-share_".concat(a)),h=document.querySelector("button#__playground-run_".concat(a)),_=document.querySelector("button#__playground-cancel_".concat(a));if(d.addEventListener("input",(function(){x(d)})),d.addEventListener("keydown",C),r&&o){var y=document.getElementById("__notebook-input");y.addEventListener("input",(function(t){x(t.target)})),y.addEventListener("keydown",C),document.getElementById("__notebook-edit").addEventListener("click",(function(){c[y.id]=y.value,document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),x(document.getElementById("__notebook-input"))})),document.getElementById("__notebook-md-gist").addEventListener("click",function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(o=prompt("Please enter link to the Markdown page source:",l))&&(o=b(o),n.preventDefault(),history.pushState({notebook:o},"","?".concat(new URLSearchParams("notebook=".concat(o)).toString())),I(!1));case 2:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),document.getElementById("__notebook-py-gist").addEventListener("click",function(){var e=n(t().mark((function e(n){var o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(o=prompt("Please enter the link to the Python code source:",l))&&(o=b(o),n.preventDefault(),history.pushState({source:o},"","?".concat(new URLSearchParams("source=".concat(o)).toString())),I(!1));case 2:case"end":return t.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}()),document.getElementById("__notebook-input").value=s,document.getElementById("__notebook-cancel").addEventListener("click",(function(){y.value=c[y.id],delete c[y.id],document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden")})),document.getElementById("__notebook-submit").addEventListener("click",n(t().mark((function e(){var n,o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return n=document.getElementById("__notebook-render"),s=document.getElementById("__notebook-input").value,n.classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),o=document.querySelector("article"),S(o,"Loading Notebook..."),n.innerHTML="",c={},t.next=10,L(!0);case 10:return t.next=12,k(s);case 12:return t.next=14,B();case 14:A(o),w();case 16:case"end":return t.stop()}}),e)}))))}d.addEventListener("touchmove",(function(t){t.stopPropagation()})),p.addEventListener("click",(function(t){var e=t.target;if(e.matches("span.swatch-color")){var n="",o=e.parentNode;if(!o.matches("span.swatch-gradient")){if(n=(n=o.getAttribute("title").replace("Copy to clipboard","")).replace("\n",""),window.clipboardData&&window.clipboardData.setData)return window.clipboardData.setData("Text",n);if(document.queryCommandSupported&&document.queryCommandSupported("copy")){var r=document.createElement("textarea");r.textContent=n,r.style.position="fixed",document.body.appendChild(r),r.select();try{return document.execCommand("copy")}catch(t){return prompt("Copy to clipboard: Ctrl+C, Enter",n)}finally{document.body.removeChild(r)}}}}})),m.addEventListener("click",n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:c[a]=d.value,f.classList.toggle("hidden"),p.classList.toggle("hidden"),h.classList.toggle("hidden"),_.classList.toggle("hidden"),m.classList.toggle("hidden"),g.classList.toggle("hidden"),x(d),d.focus();case 9:case"end":return t.stop()}}),e)})))),g.addEventListener("click",n(t().mark((function e(){var o,r,a,i,s;return t().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:o=window.location.pathname.split("/")[1],r=b(d.value),a=window.location,i="/playground/",a.pathname.startsWith("/".concat(o,"/"))&&(i="/".concat(o,"/playground/")),(s="".concat(a.protocol,"//").concat(a.host).concat(i,"?code=").concat(r)).length>2e3?alert("Code must be small enough to generate a shareable URL under 2000 characters!"):navigator.clipboard.writeText(s).then(n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Link copied to clipboard :)");case 1:case"end":return t.stop()}}),e)}))),n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Failed to copy link clipboard!");case 1:case"end":return t.stop()}}),e)}))));case 7:case"end":return e.stop()}}),e)})))),h.addEventListener("click",n(t().mark((function e(){var n,o;return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!i){t.next=2;break}return t.abrupt("return");case 2:return i=!0,n=f.querySelector("form"),S(n,null,!0),(o=document.querySelectorAll(".playground .playground-run"))&&o.forEach((function(t){t.setAttribute("disabled","")})),t.next=9,L(!1);case 9:return p.querySelector("code").innerHTML="",t.next=12,E(a);case 12:o&&o.forEach((function(t){t.removeAttribute("disabled")})),A(n),f.classList.toggle("hidden"),p.classList.toggle("hidden"),m.classList.toggle("hidden"),g.classList.toggle("hidden"),h.classList.toggle("hidden"),_.classList.toggle("hidden"),delete c[a],i=!1;case 22:case"end":return t.stop()}}),e)})))),_.addEventListener("click",(function(){d.value=c[a],delete c[a],f.classList.toggle("hidden"),p.classList.toggle("hidden"),m.classList.toggle("hidden"),g.classList.toggle("hidden"),h.classList.toggle("hidden"),_.classList.toggle("hidden")}))}));case 3:case"end":return e.stop()}}),e)})));return function(t){return e.apply(this,arguments)}}(),I=function(){var e=n(t().mark((function e(o,r){var a,i,s,u,d,f,m,g,y;return t().wrap((function(e){for(;;)switch(e.prev=e.next){case 0:if(c={},!window.location.pathname.endsWith("/playground/")){e.next=32;break}if(a=r||new URLSearchParams(window.location.search),i="Loading Pyodide...",s="Loading Notebook...",u=a.has("source")?a.get("source"):a.get("notebook"),d=document.querySelector("article"),null===u||!u.trim()){e.next=16;break}return S(d,i),e.next=11,L(!0);case 11:A(d),S(d,s);try{f=a.has("source")?"source":"notebook",p=decodeURIComponent(a.toString()),m="",g=new XMLHttpRequest,l=u,g.open("GET",u,!0),g.onload=n(t().mark((function e(){return t().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return 4===g.readyState&&200===g.status&&(m=g.responseText),"source"===f&&(m=_(m)),t.next=4,k(m);case 4:return t.next=6,B(o);case 6:A(d),w();case 8:case"end":return t.stop()}}),e)}))),g.send()}catch(t){}e.next=30;break;case 16:return l="",y=_(a.has("code")?a.get("code"):h),p=decodeURIComponent(a.toString()),S(d,i),e.next=22,L(!0);case 22:return A(d),S(d,s),e.next=26,k(y);case 26:return e.next=28,B(o);case 28:A(d),w();case 30:e.next=35;break;case 32:l="",p="",B(o);case 35:case"end":return e.stop()}}),e)})));return function(t,n){return e.apply(this,arguments)}}();document.addEventListener("click",(function(t){var e=window.location.pathname.split("/")[1],n=t.target||t.srcElement;if("A"===n.tagName&&I&&n.getAttribute("href")&&n.host===window.location.host&&window.location.pathname==="/".concat(e,"/playground/")&&window.location.pathname===n.pathname&&window.location.search!==n.search){t.preventDefault();var o=new URLSearchParams(n.search);I(!1,o)}}),!0),window.addEventListener("popstate",(function(){var t=window.location.pathname.split("/")[1];window.location.pathname==="/".concat(t,"/playground/")&&(decodeURIComponent(new URLSearchParams(window.location.search).toString())!==p&&I(!1))})),window.addEventListener("unload",(function(){f=!1})),window.document$.subscribe((function(){f?f=!1:I(!0)}))}()}();
+//# sourceMappingURL=extra-notebook-3d99782d.js.map
diff --git a/docs/theme/assets/coloraide-extras/extra-notebook-40c84faf.js.map b/docs/theme/assets/coloraide-extras/extra-notebook-3d99782d.js.map
similarity index 99%
rename from docs/theme/assets/coloraide-extras/extra-notebook-40c84faf.js.map
rename to docs/theme/assets/coloraide-extras/extra-notebook-3d99782d.js.map
index 5cb48e921..c59d3e4e7 100644
--- a/docs/theme/assets/coloraide-extras/extra-notebook-40c84faf.js.map
+++ b/docs/theme/assets/coloraide-extras/extra-notebook-3d99782d.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"extra-notebook-40c84faf.js","sources":["extra-notebook.js"],"sourcesContent":["(() => {\n  let webspace = ''\n  try {\n    let gamut = 'srgb'\n    if (window.matchMedia(\"(color-gamut: rec2020)\").matches) {\n      gamut = 'rec2020'\n    } else if (window.matchMedia(\"(color-gamut: p3)\").matches) {\n      gamut = 'display-p3'\n    }\n    webspace = (CSS.supports('color: color(display-p3 1 0 0)')) ? gamut : 'srgb'\n  } catch {\n    webspace = 'srgb'\n  }\n  let pyodide = null\n  let busy = false\n  let raw = \"\"\n  let gist = \"\"\n  let editTemp = {}\n  const reIdNum = /.*?_(\\d+)$/\n  let initialized = false\n  let lastSearch = \"\"\n  let fake = false\n  const tabStart = /^( {1,4}|\\t)/\n  // This is the Python payload that will be executed when the user\n  // presses the `Run` button. It will execute the code, create a\n  // Python console output, find color references, steps, and interpolation\n  // references and render the appropriate preview.\n  const pycode = `\n{{pycode}}\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback(gamut='${webspace}')\n`\n\n  const defContent = window.colorNotebook.defaultPlayground\n\n  const getContent = content => {\n    return `\n/// new | This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). \\\nLearn more [here](\\\n?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md\\\n). Preview, convert, interpolate, and explore!\n///\n\n\\`\\`\\`\\`\\`\\`\\`\\`py play\n${content}\n\\`\\`\\`\\`\\`\\`\\`\\`\n`\n  }\n\n  let notebookInstalled = false\n  let playgroundInstalled = false\n\n  const fakeDOMContentLoaded = () => {\n    // Send a fake `DOMContentLoaded`\n    fake = true\n    window.document.dispatchEvent(new Event(\"DOMContentLoaded\", {\n      bubbles: true,\n      cancelable: true\n    }))\n    window.document$.next()\n  }\n\n  const textResize = inpt => {\n    // Resize inputs based on text height.\n\n    const scrollLeft = window.pageXOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollLeft\n\n    const scrollTop  = window.pageYOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollTop\n\n    inpt.style.height = \"5px\"\n    inpt.style.height = `${inpt.scrollHeight}px`\n\n    window.scrollTo(scrollLeft, scrollTop)\n  }\n\n  const encodeuri = uri => {\n    // Encode the URI component.\n\n    return encodeURIComponent(uri).replace(/[.!'()*]/g, c => {\n      return `%${c.charCodeAt(0).toString(16)}`\n    })\n  }\n\n  const pyexecute = async currentID => {\n    // Execute Python code inside a playground\n\n    const currentInputs = document.getElementById(`__playground-inputs_${currentID}`)\n    currentInputs.setAttribute(\"readonly\", \"\")\n    pyodide.globals.set(\"id_num\", currentID)\n    pyodide.globals.set(\"action\", \"playground\")\n    await pyodide.runPythonAsync(pycode)\n    currentInputs.removeAttribute(\"readonly\")\n  }\n\n  const pyrender = async text => {\n    // Render an entire notebook page\n\n    pyodide.globals.set(\"content\", text)\n    pyodide.globals.set(\"action\", \"notebook\")\n    await pyodide.runPythonAsync(pycode)\n    const src = document.getElementById(\"__notebook-input\")\n    if (src) {\n      raw = text\n      src.value = text\n    }\n    if (window.location.hash) {\n      // Force jumping to hashes\n      window.location.href = window.location.href // eslint-disable-line no-self-assign\n    }\n  }\n\n  const setupPyodide = async full => {\n    // Load `Pyodide` and the any default packages we can need and can load.\n\n    if (!initialized) {\n      initialized = true\n      pyodide = await loadPyodide({ // eslint-disable-line no-undef\n        indexURL: \"https://cdn.jsdelivr.net/pyodide/v0.23.0/full/\",\n        fullStdLib: false\n      })\n    }\n\n    if ((!notebookInstalled && full) || (!playgroundInstalled && !full)) {\n      const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`\n      const packages = (full) ? window.colorNotebook.notebookWheels : window.colorNotebook.playgroundWheels\n      const installs = []\n      if (full) {\n        notebookInstalled = true\n      } else {\n        playgroundInstalled = true\n      }\n      for (const s of packages) {\n        if (s.endsWith('.whl')) {\n          installs.push(base + s)\n        } else {\n          installs.push(s)\n        }\n      }\n      await pyodide.loadPackage(installs)\n    }\n  }\n\n  const showBusy = (target, label, relative) => {\n    // Show busy indicator\n\n    const loaderLabel = (typeof label === \"undefined\" || label === null) ? \"Loading...\" : label\n    const classes = relative ? \"loading relative\" : \"loading\"\n    const template = document.createElement(\"template\")\n    template.innerHTML = `<div class=\"${classes}\"><div class=\"loader\"></div><div>${loaderLabel}</div></div>`\n    target.appendChild(template.content.firstChild)\n  }\n\n  const hideBusy = target => {\n    // Hide busy indicator\n\n    const loading = target.querySelector(\".loading\")\n    if (loading) {\n      target.removeChild(target.querySelector(\".loading\"))\n    }\n  }\n\n  const popState = () => {\n    // Handle notebook history\n\n    const base = window.location.pathname.split('/')[1]\n    if (\n      window.location.pathname === `/${base}/playground/`\n    ) {\n      const current = decodeURIComponent(new URLSearchParams(window.location.search).toString())\n      if (current !== lastSearch) {\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const interceptClickEvent = e => {\n    // Catch links to other notebook pages and handle them\n\n    const base = window.location.pathname.split('/')[1]\n    const target = e.target || e.srcElement\n    if (target.tagName === \"A\" && main) { // eslint-disable-line no-use-before-define\n      if (\n        target.getAttribute(\"href\") &&\n        target.host === window.location.host &&\n        window.location.pathname === `/${base}/playground/` &&\n        window.location.pathname === target.pathname &&\n        window.location.search !== target.search\n      ) {\n        e.preventDefault()\n        const search = new URLSearchParams(target.search)\n        main(false, search) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const handleTab = e => {\n    // Prevent tab from tabbing out.\n\n    if (e.key === 'Tab') {\n      const target = e.target\n\n      if (target.selectionStart !== target.selectionEnd) {\n        e.preventDefault()\n\n        let start = target.selectionStart\n        let end = target.selectionEnd\n\n        const text = target.value\n\n        while (start > 0 && text[start - 1] !== '\\n') {\n          start--\n        }\n        while (end > 0 && text[end - 1] !== '\\n' && end < text.length) {\n          end++\n        }\n\n        let lines = text.substr(start, end - start).split('\\n')\n\n        for (let i = 0; i < lines.length; i++) {\n\n          // Don't indent last line if cursor at start of line\n          if (i === lines.length - 1 && lines[i].length === 0) {\n            continue\n          }\n\n          // Indent or deindent\n          if (e.shiftKey) {\n            lines[i] = lines[i].replace(tabStart, '')\n          } else {\n            lines[i] = `    ${lines[i]}`\n          }\n        }\n        lines = lines.join('\\n')\n\n        // Update the text area\n        target.value = text.substr(0, start) + lines + text.substr(end)\n        target.selectionStart = start\n        target.selectionEnd = start + lines.length\n      }\n    }\n  }\n\n  const init = async first => {\n    // Setup input highlighting and events to run Python code blocks.\n\n    const notebook = document.getElementById(\"__notebook-source\")\n    const playgrounds = document.querySelectorAll(\".playground\")\n    playgrounds.forEach(pg => {\n\n      const currentID = pg.id.replace(reIdNum, \"$1\")\n      const inputs = document.getElementById(`__playground-inputs_${currentID}`)\n      const results = document.getElementById(`__playground-results_${currentID}`)\n      const pgcode = document.getElementById(`__playground-code_${currentID}`)\n      const buttonEdit = document.querySelector(`button#__playground-edit_${currentID}`)\n      const buttonShare = document.querySelector(`button#__playground-share_${currentID}`)\n      const buttonRun = document.querySelector(`button#__playground-run_${currentID}`)\n      const buttonCancel = document.querySelector(`button#__playground-cancel_${currentID}`)\n\n      inputs.addEventListener(\"input\", () => {\n        // Adjust textarea height on text input.\n\n        textResize(inputs)\n      })\n\n      inputs.addEventListener('keydown', handleTab)\n\n      if (notebook && first) {\n        const notebookInput = document.getElementById(\"__notebook-input\")\n\n        notebookInput.addEventListener(\"input\", e => {\n          // Adjust textarea height on text input.\n\n          textResize(e.target)\n        })\n\n        notebookInput.addEventListener('keydown', handleTab)\n\n        const editPage = document.getElementById(\"__notebook-edit\")\n        editPage.addEventListener(\"click\", () => {\n          editTemp[notebookInput.id] = notebookInput.value\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          textResize(document.getElementById(\"__notebook-input\"))\n        })\n\n        document.getElementById(\"__notebook-md-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter link to the Markdown page source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({notebook: uri}, \"\", `?${new URLSearchParams(`notebook=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-py-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter the link to the Python code source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({source: uri}, \"\", `?${new URLSearchParams(`source=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-input\").value = raw\n        document.getElementById(\"__notebook-cancel\").addEventListener(\"click\", () => {\n          notebookInput.value = editTemp[notebookInput.id]\n          delete editTemp[notebookInput.id]\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        })\n\n        document.getElementById(\"__notebook-submit\").addEventListener(\"click\", async() => {\n          const render = document.getElementById(\"__notebook-render\")\n          raw = document.getElementById(\"__notebook-input\").value\n          render.classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          const article = document.querySelector(\"article\")\n          showBusy(article, \"Loading Notebook...\")\n          render.innerHTML = \"\"\n          editTemp = {}\n          await setupPyodide(true)\n          await pyrender(raw)\n          await init()\n          hideBusy(article)\n          fakeDOMContentLoaded()\n        })\n      }\n\n      inputs.addEventListener(\"touchmove\", e => {\n        // Stop propagation on \"touchmove\".\n\n        e.stopPropagation()\n      })\n\n      results.addEventListener(\"click\", e => {\n        // Handle clicks on results and copies color from single color swatch when clicked.\n\n        const el = e.target\n        if (el.matches('span.swatch-color')) {\n          let content = ''\n          const parent = el.parentNode\n          if (!parent.matches('span.swatch-gradient')) {\n            content = parent.getAttribute('title').replace('Copy to clipboard', '')\n            content = content.replace('\\n', '')\n            if (window.clipboardData && window.clipboardData.setData) {\n              // Old `IE`` handling, do we really need this?\n              return window.clipboardData.setData(\"Text\", content)\n            } else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n              const textarea = document.createElement(\"textarea\")\n              textarea.textContent = content\n              textarea.style.position = \"fixed\"\n              document.body.appendChild(textarea)\n              textarea.select()\n              try {\n                return document.execCommand(\"copy\")\n              } catch (ex) {\n                return prompt(\"Copy to clipboard: Ctrl+C, Enter\", content) // eslint-disable-line no-alert\n              } finally {\n                document.body.removeChild(textarea)\n              }\n            }\n          }\n        }\n      })\n\n      buttonEdit.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        editTemp[currentID] = inputs.value\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        textResize(inputs)\n        inputs.focus()\n      })\n\n      buttonShare.addEventListener(\"click\", async() => {\n        // Handle the share click: copy URL with code as parameter.\n\n        const base = window.location.pathname.split('/')[1]\n        const uri = encodeuri(inputs.value)\n        const loc = window.location\n        let pathname = \"/playground/\"\n        if (loc.pathname.startsWith(`/${base}/`)) {\n          pathname = `/${base}/playground/`\n        }\n        const path = `${loc.protocol}//${loc.host}${pathname}?code=${uri}`\n        if (path.length > 2000) {\n          alert( // eslint-disable-line no-alert\n            \"Code must be small enough to generate a shareable URL under 2000 characters!\"\n          )\n        } else {\n          navigator.clipboard.writeText(path).then(async() => {\n            alert(\"Link copied to clipboard :)\") // eslint-disable-line no-alert\n          }, async() => {\n            alert(\"Failed to copy link clipboard!\") // eslint-disable-line no-alert\n          })\n        }\n      })\n\n      buttonRun.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        if (busy) {\n          return\n        }\n\n        busy = true\n        // Load Pyodide and related packages.\n        const form = pgcode.querySelector(\"form\")\n        showBusy(form, null, true)\n        const buttons = document.querySelectorAll(\".playground .playground-run\")\n        if (buttons) {\n          buttons.forEach(b => {\n            b.setAttribute(\"disabled\", \"\")\n          })\n        }\n        await setupPyodide(false)\n        results.querySelector(\"code\").innerHTML = \"\"\n        await pyexecute(currentID)\n        if (buttons) {\n          buttons.forEach(b => {\n            b.removeAttribute(\"disabled\")\n          })\n        }\n        hideBusy(form)\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n\n        delete editTemp[currentID]\n        busy = false\n      })\n\n      buttonCancel.addEventListener(\"click\", () => {\n        // Cancel edit.\n\n        inputs.value = editTemp[currentID]\n        delete editTemp[currentID]\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n      })\n    })\n  }\n\n  const main = async(first, search) => {\n    // Load external source to render in a playground.\n    // This can be something like a file on a gist we must read in (?source=)\n    // or raw code (?code=).\n\n    editTemp = {}\n\n    if (window.location.pathname.endsWith(\"/playground/\")) {\n      const params = search || new URLSearchParams(window.location.search)\n      const loadMsg = \"Loading Pyodide...\"\n      const pageMsg = \"Loading Notebook...\"\n      const uri = params.has(\"source\") ? params.get(\"source\") : params.get(\"notebook\")\n      const article = document.querySelector(\"article\")\n      if (uri !== null && uri.trim()) {\n        // A source was specified, so load it.\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        try {\n          const gistType = params.has(\"source\") ? \"source\" : \"notebook\"\n          lastSearch = decodeURIComponent(params.toString())\n          let value = \"\"\n          const xhr = new XMLHttpRequest()\n          gist = uri\n          xhr.open(\"GET\", uri, true)\n          xhr.onload = async() => {\n            // Try and load the requested content\n            if (xhr.readyState === 4) {\n              if (xhr.status === 200) {\n                value = xhr.responseText\n              }\n            }\n\n            if (gistType === \"source\") {\n              value = getContent(value)\n            }\n            await pyrender(value)\n            await init(first)\n            hideBusy(article)\n            fakeDOMContentLoaded()\n          }\n          xhr.send()\n        } catch (err) {} // eslint-disable-line no-empty\n      } else {\n        gist = \"\"\n        const content = getContent(params.has(\"code\") ? params.get(\"code\") : defContent)\n        lastSearch = decodeURIComponent(params.toString())\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        await pyrender(content)\n        await init(first)\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      }\n    } else {\n      gist = \"\"\n      lastSearch = \"\"\n      init(first)\n    }\n  }\n\n  // Capture links in notebook pages so that we can make playgound links load instantly\n  document.addEventListener(\"click\", interceptClickEvent, true)\n\n  // Handle history of notebook pages as they are loaded dynamically\n  window.addEventListener(\"popstate\", popState)\n\n  // Before leaving, turn off fake, just in case we navigated away before finished\n  window.addEventListener(\"unload\", () => {\n    fake = false\n  })\n\n  // Attach main via subscribe (subscribes to Materials on page load and instant page loads)\n  window.document$.subscribe(() => {\n    // To get other libraries to reload, we may create a fake `DOMContentLoaded`\n    // No need to process these events.\n    if (fake) {\n      fake = false\n      return\n    }\n    main(true)\n  })\n})()\n"],"names":["webspace","gamut","window","matchMedia","matches","CSS","supports","_unused","pyodide","busy","raw","gist","editTemp","reIdNum","initialized","lastSearch","fake","tabStart","pycode","concat","defContent","colorNotebook","defaultPlayground","getContent","content","notebookInstalled","playgroundInstalled","fakeDOMContentLoaded","document","dispatchEvent","Event","bubbles","cancelable","document$","next","textResize","inpt","scrollLeft","pageXOffset","documentElement","body","parentNode","scrollTop","pageYOffset","style","height","scrollHeight","scrollTo","encodeuri","uri","encodeURIComponent","replace","c","charCodeAt","toString","pyexecute","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","currentID","currentInputs","wrap","_context","prev","getElementById","setAttribute","globals","set","runPythonAsync","removeAttribute","stop","_x","apply","this","arguments","pyrender","_ref2","_callee2","text","src","_context2","value","location","hash","href","_x2","setupPyodide","_ref3","_callee3","full","base","packages","installs","_iterator","_step","s","_context3","loadPyodide","indexURL","fullStdLib","sent","origin","pathname","split","notebookWheels","playgroundWheels","_createForOfIteratorHelper","n","done","endsWith","push","err","e","f","loadPackage","_x3","showBusy","target","label","relative","loaderLabel","classes","template","createElement","innerHTML","appendChild","firstChild","hideBusy","querySelector","removeChild","handleTab","key","selectionStart","selectionEnd","preventDefault","start","end","length","lines","substr","i","shiftKey","join","init","_ref4","_callee12","first","notebook","_context12","querySelectorAll","forEach","pg","id","inputs","results","pgcode","buttonEdit","buttonShare","buttonRun","buttonCancel","addEventListener","notebookInput","classList","toggle","_ref5","_callee4","_context4","prompt","history","pushState","URLSearchParams","main","_x5","_ref6","_callee5","_context5","source","_x6","_callee6","render","article","_context6","stopPropagation","el","parent","getAttribute","clipboardData","setData","queryCommandSupported","textarea","textContent","position","select","execCommand","ex","_callee7","_context7","focus","_callee10","loc","path","_context10","startsWith","protocol","host","alert","navigator","clipboard","writeText","then","_callee8","_context8","_callee9","_context9","_callee11","form","buttons","_context11","abrupt","b","_x4","_ref13","_callee14","search","params","loadMsg","pageMsg","gistType","xhr","_context14","has","get","trim","decodeURIComponent","XMLHttpRequest","open","onload","_callee13","_context13","readyState","status","responseText","send","_x7","_x8","srcElement","tagName","subscribe"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"extra-notebook-3d99782d.js","sources":["extra-notebook.js"],"sourcesContent":["(() => {\n  let webspace = ''\n  try {\n    let gamut = 'srgb'\n    if (window.matchMedia(\"(color-gamut: rec2020)\").matches) {\n      gamut = 'rec2020'\n    } else if (window.matchMedia(\"(color-gamut: p3)\").matches) {\n      gamut = 'display-p3'\n    }\n    webspace = (CSS.supports('color: color(display-p3 1 0 0)')) ? gamut : 'srgb'\n  } catch {\n    webspace = 'srgb'\n  }\n  let pyodide = null\n  let busy = false\n  let raw = \"\"\n  let gist = \"\"\n  let editTemp = {}\n  const reIdNum = /.*?_(\\d+)$/\n  let initialized = false\n  let lastSearch = \"\"\n  let fake = false\n  const tabStart = /^( {1,4}|\\t)/\n  // This is the Python payload that will be executed when the user\n  // presses the `Run` button. It will execute the code, create a\n  // Python console output, find color references, steps, and interpolation\n  // references and render the appropriate preview.\n  const pycode = `\n{{pycode}}\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback(gamut='${webspace}')\n`\n\n  const defContent = window.colorNotebook.defaultPlayground\n\n  const getContent = content => {\n    return `\n/// new | This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). \\\nLearn more [here](\\\n?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md\\\n). Preview, convert, interpolate, and explore!\n///\n\n\\`\\`\\`\\`\\`\\`\\`\\`py play\n${content}\n\\`\\`\\`\\`\\`\\`\\`\\`\n`\n  }\n\n  let notebookInstalled = false\n  let playgroundInstalled = false\n\n  const fakeDOMContentLoaded = () => {\n    // Send a fake `DOMContentLoaded`\n    fake = true\n    window.document.dispatchEvent(new Event(\"DOMContentLoaded\", {\n      bubbles: true,\n      cancelable: true\n    }))\n    window.document$.next()\n  }\n\n  const textResize = inpt => {\n    // Resize inputs based on text height.\n\n    const scrollLeft = window.pageXOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollLeft\n\n    const scrollTop  = window.pageYOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollTop\n\n    inpt.style.height = \"5px\"\n    inpt.style.height = `${inpt.scrollHeight}px`\n\n    window.scrollTo(scrollLeft, scrollTop)\n  }\n\n  const encodeuri = uri => {\n    // Encode the URI component.\n\n    return encodeURIComponent(uri).replace(/[.!'()*]/g, c => {\n      return `%${c.charCodeAt(0).toString(16)}`\n    })\n  }\n\n  const pyexecute = async currentID => {\n    // Execute Python code inside a playground\n\n    const currentInputs = document.getElementById(`__playground-inputs_${currentID}`)\n    currentInputs.setAttribute(\"readonly\", \"\")\n    pyodide.globals.set(\"id_num\", currentID)\n    pyodide.globals.set(\"action\", \"playground\")\n    await pyodide.runPythonAsync(pycode)\n    currentInputs.removeAttribute(\"readonly\")\n  }\n\n  const pyrender = async text => {\n    // Render an entire notebook page\n\n    pyodide.globals.set(\"content\", text)\n    pyodide.globals.set(\"action\", \"notebook\")\n    await pyodide.runPythonAsync(pycode)\n    const src = document.getElementById(\"__notebook-input\")\n    if (src) {\n      raw = text\n      src.value = text\n    }\n    if (window.location.hash) {\n      // Force jumping to hashes\n      window.location.href = window.location.href // eslint-disable-line no-self-assign\n    }\n  }\n\n  const setupPyodide = async full => {\n    // Load `Pyodide` and the any default packages we can need and can load.\n\n    if (!initialized) {\n      initialized = true\n      pyodide = await loadPyodide({ // eslint-disable-line no-undef\n        indexURL: \"https://cdn.jsdelivr.net/pyodide/v0.23.0/full/\",\n        fullStdLib: false\n      })\n    }\n\n    if ((!notebookInstalled && full) || (!playgroundInstalled && !full)) {\n      const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`\n      const packages = (full) ? window.colorNotebook.notebookWheels : window.colorNotebook.playgroundWheels\n      const installs = []\n      if (full) {\n        notebookInstalled = true\n      } else {\n        playgroundInstalled = true\n      }\n      for (const s of packages) {\n        if (s.endsWith('.whl')) {\n          installs.push(base + s)\n        } else {\n          installs.push(s)\n        }\n      }\n      await pyodide.loadPackage(installs)\n    }\n  }\n\n  const showBusy = (target, label, relative) => {\n    // Show busy indicator\n\n    const loaderLabel = (typeof label === \"undefined\" || label === null) ? \"Loading...\" : label\n    const classes = relative ? \"loading relative\" : \"loading\"\n    const template = document.createElement(\"template\")\n    template.innerHTML = `<div class=\"${classes}\"><div class=\"loader\"></div><div>${loaderLabel}</div></div>`\n    target.appendChild(template.content.firstChild)\n  }\n\n  const hideBusy = target => {\n    // Hide busy indicator\n\n    const loading = target.querySelector(\".loading\")\n    if (loading) {\n      target.removeChild(target.querySelector(\".loading\"))\n    }\n  }\n\n  const popState = () => {\n    // Handle notebook history\n\n    const base = window.location.pathname.split('/')[1]\n    if (\n      window.location.pathname === `/${base}/playground/`\n    ) {\n      const current = decodeURIComponent(new URLSearchParams(window.location.search).toString())\n      if (current !== lastSearch) {\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const interceptClickEvent = e => {\n    // Catch links to other notebook pages and handle them\n\n    const base = window.location.pathname.split('/')[1]\n    const target = e.target || e.srcElement\n    if (target.tagName === \"A\" && main) { // eslint-disable-line no-use-before-define\n      if (\n        target.getAttribute(\"href\") &&\n        target.host === window.location.host &&\n        window.location.pathname === `/${base}/playground/` &&\n        window.location.pathname === target.pathname &&\n        window.location.search !== target.search\n      ) {\n        e.preventDefault()\n        const search = new URLSearchParams(target.search)\n        main(false, search) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const handleTab = e => {\n    // Prevent tab from tabbing out.\n\n    if (e.key === 'Tab') {\n      const target = e.target\n\n      if (target.selectionStart !== target.selectionEnd) {\n        e.preventDefault()\n\n        let start = target.selectionStart\n        let end = target.selectionEnd\n\n        const text = target.value\n\n        while (start > 0 && text[start - 1] !== '\\n') {\n          start--\n        }\n        while (end > 0 && text[end - 1] !== '\\n' && end < text.length) {\n          end++\n        }\n\n        let lines = text.substr(start, end - start).split('\\n')\n\n        for (let i = 0; i < lines.length; i++) {\n\n          // Don't indent last line if cursor at start of line\n          if (i === lines.length - 1 && lines[i].length === 0) {\n            continue\n          }\n\n          // Indent or deindent\n          if (e.shiftKey) {\n            lines[i] = lines[i].replace(tabStart, '')\n          } else {\n            lines[i] = `    ${lines[i]}`\n          }\n        }\n        lines = lines.join('\\n')\n\n        // Update the text area\n        target.value = text.substr(0, start) + lines + text.substr(end)\n        target.selectionStart = start\n        target.selectionEnd = start + lines.length\n      }\n    }\n  }\n\n  const init = async first => {\n    // Setup input highlighting and events to run Python code blocks.\n\n    const notebook = document.getElementById(\"__notebook-source\")\n    const playgrounds = document.querySelectorAll(\".playground\")\n    playgrounds.forEach(pg => {\n\n      const currentID = pg.id.replace(reIdNum, \"$1\")\n      const inputs = document.getElementById(`__playground-inputs_${currentID}`)\n      const results = document.getElementById(`__playground-results_${currentID}`)\n      const pgcode = document.getElementById(`__playground-code_${currentID}`)\n      const buttonEdit = document.querySelector(`button#__playground-edit_${currentID}`)\n      const buttonShare = document.querySelector(`button#__playground-share_${currentID}`)\n      const buttonRun = document.querySelector(`button#__playground-run_${currentID}`)\n      const buttonCancel = document.querySelector(`button#__playground-cancel_${currentID}`)\n\n      inputs.addEventListener(\"input\", () => {\n        // Adjust textarea height on text input.\n\n        textResize(inputs)\n      })\n\n      inputs.addEventListener('keydown', handleTab)\n\n      if (notebook && first) {\n        const notebookInput = document.getElementById(\"__notebook-input\")\n\n        notebookInput.addEventListener(\"input\", e => {\n          // Adjust textarea height on text input.\n\n          textResize(e.target)\n        })\n\n        notebookInput.addEventListener('keydown', handleTab)\n\n        const editPage = document.getElementById(\"__notebook-edit\")\n        editPage.addEventListener(\"click\", () => {\n          editTemp[notebookInput.id] = notebookInput.value\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          textResize(document.getElementById(\"__notebook-input\"))\n        })\n\n        document.getElementById(\"__notebook-md-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter link to the Markdown page source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({notebook: uri}, \"\", `?${new URLSearchParams(`notebook=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-py-gist\").addEventListener(\"click\", async e => {\n          let uri = prompt(\"Please enter the link to the Python code source:\", gist) // eslint-disable-line no-alert\n          if (uri !== null) {\n            uri = encodeuri(uri)\n            e.preventDefault()\n            history.pushState({source: uri}, \"\", `?${new URLSearchParams(`source=${uri}`).toString()}`)\n            main(false) // eslint-disable-line no-use-before-define\n          }\n        })\n\n        document.getElementById(\"__notebook-input\").value = raw\n        document.getElementById(\"__notebook-cancel\").addEventListener(\"click\", () => {\n          notebookInput.value = editTemp[notebookInput.id]\n          delete editTemp[notebookInput.id]\n          document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        })\n\n        document.getElementById(\"__notebook-submit\").addEventListener(\"click\", async() => {\n          const render = document.getElementById(\"__notebook-render\")\n          raw = document.getElementById(\"__notebook-input\").value\n          render.classList.toggle(\"hidden\")\n          document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n          const article = document.querySelector(\"article\")\n          showBusy(article, \"Loading Notebook...\")\n          render.innerHTML = \"\"\n          editTemp = {}\n          await setupPyodide(true)\n          await pyrender(raw)\n          await init()\n          hideBusy(article)\n          fakeDOMContentLoaded()\n        })\n      }\n\n      inputs.addEventListener(\"touchmove\", e => {\n        // Stop propagation on \"touchmove\".\n\n        e.stopPropagation()\n      })\n\n      results.addEventListener(\"click\", e => {\n        // Handle clicks on results and copies color from single color swatch when clicked.\n\n        const el = e.target\n        if (el.matches('span.swatch-color')) {\n          let content = ''\n          const parent = el.parentNode\n          if (!parent.matches('span.swatch-gradient')) {\n            content = parent.getAttribute('title').replace('Copy to clipboard', '')\n            content = content.replace('\\n', '')\n            if (window.clipboardData && window.clipboardData.setData) {\n              // Old `IE`` handling, do we really need this?\n              return window.clipboardData.setData(\"Text\", content)\n            } else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n              const textarea = document.createElement(\"textarea\")\n              textarea.textContent = content\n              textarea.style.position = \"fixed\"\n              document.body.appendChild(textarea)\n              textarea.select()\n              try {\n                return document.execCommand(\"copy\")\n              } catch (ex) {\n                return prompt(\"Copy to clipboard: Ctrl+C, Enter\", content) // eslint-disable-line no-alert\n              } finally {\n                document.body.removeChild(textarea)\n              }\n            }\n          }\n        }\n      })\n\n      buttonEdit.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        editTemp[currentID] = inputs.value\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        textResize(inputs)\n        inputs.focus()\n      })\n\n      buttonShare.addEventListener(\"click\", async() => {\n        // Handle the share click: copy URL with code as parameter.\n\n        const base = window.location.pathname.split('/')[1]\n        const uri = encodeuri(inputs.value)\n        const loc = window.location\n        let pathname = \"/playground/\"\n        if (loc.pathname.startsWith(`/${base}/`)) {\n          pathname = `/${base}/playground/`\n        }\n        const path = `${loc.protocol}//${loc.host}${pathname}?code=${uri}`\n        if (path.length > 2000) {\n          alert( // eslint-disable-line no-alert\n            \"Code must be small enough to generate a shareable URL under 2000 characters!\"\n          )\n        } else {\n          navigator.clipboard.writeText(path).then(async() => {\n            alert(\"Link copied to clipboard :)\") // eslint-disable-line no-alert\n          }, async() => {\n            alert(\"Failed to copy link clipboard!\") // eslint-disable-line no-alert\n          })\n        }\n      })\n\n      buttonRun.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        if (busy) {\n          return\n        }\n\n        busy = true\n        // Load Pyodide and related packages.\n        const form = pgcode.querySelector(\"form\")\n        showBusy(form, null, true)\n        const buttons = document.querySelectorAll(\".playground .playground-run\")\n        if (buttons) {\n          buttons.forEach(b => {\n            b.setAttribute(\"disabled\", \"\")\n          })\n        }\n        await setupPyodide(false)\n        results.querySelector(\"code\").innerHTML = \"\"\n        await pyexecute(currentID)\n        if (buttons) {\n          buttons.forEach(b => {\n            b.removeAttribute(\"disabled\")\n          })\n        }\n        hideBusy(form)\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n\n        delete editTemp[currentID]\n        busy = false\n      })\n\n      buttonCancel.addEventListener(\"click\", () => {\n        // Cancel edit.\n\n        inputs.value = editTemp[currentID]\n        delete editTemp[currentID]\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n      })\n    })\n  }\n\n  const main = async(first, search) => {\n    // Load external source to render in a playground.\n    // This can be something like a file on a gist we must read in (?source=)\n    // or raw code (?code=).\n\n    editTemp = {}\n\n    if (window.location.pathname.endsWith(\"/playground/\")) {\n      const params = search || new URLSearchParams(window.location.search)\n      const loadMsg = \"Loading Pyodide...\"\n      const pageMsg = \"Loading Notebook...\"\n      const uri = params.has(\"source\") ? params.get(\"source\") : params.get(\"notebook\")\n      const article = document.querySelector(\"article\")\n      if (uri !== null && uri.trim()) {\n        // A source was specified, so load it.\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        try {\n          const gistType = params.has(\"source\") ? \"source\" : \"notebook\"\n          lastSearch = decodeURIComponent(params.toString())\n          let value = \"\"\n          const xhr = new XMLHttpRequest()\n          gist = uri\n          xhr.open(\"GET\", uri, true)\n          xhr.onload = async() => {\n            // Try and load the requested content\n            if (xhr.readyState === 4) {\n              if (xhr.status === 200) {\n                value = xhr.responseText\n              }\n            }\n\n            if (gistType === \"source\") {\n              value = getContent(value)\n            }\n            await pyrender(value)\n            await init(first)\n            hideBusy(article)\n            fakeDOMContentLoaded()\n          }\n          xhr.send()\n        } catch (err) {} // eslint-disable-line no-empty\n      } else {\n        gist = \"\"\n        const content = getContent(params.has(\"code\") ? params.get(\"code\") : defContent)\n        lastSearch = decodeURIComponent(params.toString())\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        await pyrender(content)\n        await init(first)\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      }\n    } else {\n      gist = \"\"\n      lastSearch = \"\"\n      init(first)\n    }\n  }\n\n  // Capture links in notebook pages so that we can make playgound links load instantly\n  document.addEventListener(\"click\", interceptClickEvent, true)\n\n  // Handle history of notebook pages as they are loaded dynamically\n  window.addEventListener(\"popstate\", popState)\n\n  // Before leaving, turn off fake, just in case we navigated away before finished\n  window.addEventListener(\"unload\", () => {\n    fake = false\n  })\n\n  // Attach main via subscribe (subscribes to Materials on page load and instant page loads)\n  window.document$.subscribe(() => {\n    // To get other libraries to reload, we may create a fake `DOMContentLoaded`\n    // No need to process these events.\n    if (fake) {\n      fake = false\n      return\n    }\n    main(true)\n  })\n})()\n"],"names":["webspace","gamut","window","matchMedia","matches","CSS","supports","_unused","pyodide","busy","raw","gist","editTemp","reIdNum","initialized","lastSearch","fake","tabStart","pycode","concat","defContent","colorNotebook","defaultPlayground","getContent","content","notebookInstalled","playgroundInstalled","fakeDOMContentLoaded","document","dispatchEvent","Event","bubbles","cancelable","document$","next","textResize","inpt","scrollLeft","pageXOffset","documentElement","body","parentNode","scrollTop","pageYOffset","style","height","scrollHeight","scrollTo","encodeuri","uri","encodeURIComponent","replace","c","charCodeAt","toString","pyexecute","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","currentID","currentInputs","wrap","_context","prev","getElementById","setAttribute","globals","set","runPythonAsync","removeAttribute","stop","_x","apply","this","arguments","pyrender","_ref2","_callee2","text","src","_context2","value","location","hash","href","_x2","setupPyodide","_ref3","_callee3","full","base","packages","installs","_iterator","_step","s","_context3","loadPyodide","indexURL","fullStdLib","sent","origin","pathname","split","notebookWheels","playgroundWheels","_createForOfIteratorHelper","n","done","endsWith","push","err","e","f","loadPackage","_x3","showBusy","target","label","relative","loaderLabel","classes","template","createElement","innerHTML","appendChild","firstChild","hideBusy","querySelector","removeChild","handleTab","key","selectionStart","selectionEnd","preventDefault","start","end","length","lines","substr","i","shiftKey","join","init","_ref4","_callee12","first","notebook","_context12","querySelectorAll","forEach","pg","id","inputs","results","pgcode","buttonEdit","buttonShare","buttonRun","buttonCancel","addEventListener","notebookInput","classList","toggle","_ref5","_callee4","_context4","prompt","history","pushState","URLSearchParams","main","_x5","_ref6","_callee5","_context5","source","_x6","_callee6","render","article","_context6","stopPropagation","el","parent","getAttribute","clipboardData","setData","queryCommandSupported","textarea","textContent","position","select","execCommand","ex","_callee7","_context7","focus","_callee10","loc","path","_context10","startsWith","protocol","host","alert","navigator","clipboard","writeText","then","_callee8","_context8","_callee9","_context9","_callee11","form","buttons","_context11","abrupt","b","_x4","_ref13","_callee14","search","params","loadMsg","pageMsg","gistType","xhr","_context14","has","get","trim","decodeURIComponent","XMLHttpRequest","open","onload","_callee13","_context13","readyState","status","responseText","send","_x7","_x8","srcElement","tagName","subscribe"],"mappings":"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"}
\ No newline at end of file
diff --git a/docs/theme/playground-config-c87dd48d.js b/docs/theme/playground-config-c8a475b3.js
similarity index 76%
rename from docs/theme/playground-config-c87dd48d.js
rename to docs/theme/playground-config-c8a475b3.js
index 1931e799a..fa7c96d4e 100644
--- a/docs/theme/playground-config-c87dd48d.js
+++ b/docs/theme/playground-config-c8a475b3.js
@@ -1,5 +1,5 @@
 var colorNotebook = {
-    "playgroundWheels": ['Pygments-2.12.0-py3-none-any.whl', 'coloraide-2.0.2-py3-none-any.whl'],
-    "notebookWheels": ['pyyaml', 'Markdown-3.3.4-py3-none-any.whl', 'pymdown_extensions-9.10-py3-none-any.whl', 'Pygments-2.12.0-py3-none-any.whl', 'coloraide-2.0.2-py3-none-any.whl'],
+    "playgroundWheels": ['Pygments-2.12.0-py3-none-any.whl', 'coloraide-2.1-py3-none-any.whl'],
+    "notebookWheels": ['pyyaml', 'Markdown-3.3.4-py3-none-any.whl', 'pymdown_extensions-9.10-py3-none-any.whl', 'Pygments-2.12.0-py3-none-any.whl', 'coloraide-2.1-py3-none-any.whl'],
     "defaultPlayground": "import coloraide\ncoloraide.__version__\nColor('red')"
 }
diff --git a/mkdocs.yml b/mkdocs.yml
index 3cf157262..0dc413fed 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -40,6 +40,7 @@ nav:
       - The Color Object: color.md
       - Manipulating Colors: manipulation.md
       - Color Interpolation: interpolation.md
+      - Color Averaging: average.md
       - Compositing and Blending: compositing.md
       - Color Distance and Delta E: distance.md
       - Gamut Mapping: gamut.md
@@ -266,9 +267,9 @@ extra_css:
   - assets/coloraide-extras/extra-391b1ef8ad.css
 extra_javascript:
   - https://unpkg.com/mermaid@8.13.3/dist/mermaid.min.js
-  - playground-config-c87dd48d.js
+  - playground-config-c8a475b3.js
   - https://cdn.jsdelivr.net/pyodide/v0.23.0/full/pyodide.js
-  - assets/coloraide-extras/extra-notebook-40c84faf.js
+  - assets/coloraide-extras/extra-notebook-3d99782d.js
 
 extra:
   social:
diff --git a/tools/gamut_3d_plotly.py b/tools/gamut_3d_plotly.py
index 9f62538fe..c8c0f18c8 100644
--- a/tools/gamut_3d_plotly.py
+++ b/tools/gamut_3d_plotly.py
@@ -1,16 +1,22 @@
 """Plot color space using Plotly."""
 import sys
 import argparse
-from coloraide.everything import ColorAll as Color
 from scipy.spatial import Delaunay
-from coloraide import algebra as alg
 from plotly.figure_factory import create_trisurf as trisurf
-from coloraide.spaces import HSLish, HSVish, Cylindrical, Labish, LChish
 import plotly.graph_objects as go
 import math
 import plotly.io as io
 import os
 
+sys.path.insert(0, os.getcwd())
+
+try:
+    from coloraide_extras.everything import ColorAll as Color
+except ImportError:
+    from coloraide.everything import ColorAll as Color
+from coloraide.spaces import HSLish, HSVish, Cylindrical, Labish, LChish  # noqa: E402
+from coloraide import algebra as alg  # noqa: E402
+
 
 def create_custom_hsl(gamut):
     """Create a custom color object that has access to a special `hsl-gamut` space to map surface in."""
@@ -32,6 +38,12 @@ class ColorCyl(Color):
     return ColorCyl
 
 
+def get_face_color(cmap, simplex):
+    """Get best color."""
+
+    return Color.average([cmap[simplex[0]], cmap[simplex[1]], cmap[simplex[2]]], space='srgb').to_string(hex=True)
+
+
 def cyl_disc(ColorCyl, space, gamut, location, resolution, opacity, edges):
     """
     Plot cylindrical disc on either top or bottom of an RGB cylinder.
@@ -100,7 +112,7 @@ def cyl_disc(ColorCyl, space, gamut, location, resolution, opacity, edges):
                     s.fit()
                 else:
                     s.clip()
-                cmap.append(s.to_string(hex=True))
+                cmap.append(s)
 
         # Calculate triangles
         tri = Delaunay(list(zip(u, v)))
@@ -111,7 +123,7 @@ def cyl_disc(ColorCyl, space, gamut, location, resolution, opacity, edges):
             simplices=tri.simplices,
             show_colorbar=False,
             plot_edges=edges,
-            color_func=[cmap[t[1]] for t in tri.simplices]
+            color_func=[get_face_color(cmap, t) for t in tri.simplices]
         ).data
         trace[0].update(opacity=opacity)
         traces.append(trace)
@@ -215,7 +227,7 @@ def render_space_cyl(fig, space, gamut, resolution, opacity, edges):
                 else:
                     s.clip()
 
-                cmap.append(s.to_string(hex=True))
+                cmap.append(s)
 
         # Calculate the triangles
         tri = Delaunay(list(zip(u, v)))
@@ -226,7 +238,7 @@ def render_space_cyl(fig, space, gamut, resolution, opacity, edges):
             simplices=tri.simplices,
             show_colorbar=False,
             plot_edges=edges,
-            color_func=[cmap[t[1]] for t in tri.simplices]
+            color_func=[get_face_color(cmap, t) for t in tri.simplices]
         ).data
         trace[0].update(opacity=opacity)
         fig.add_traces(trace)
@@ -270,7 +282,7 @@ def render_rect_face(s1, s2, dim, space, gamut, resolution, opacity, edges):
                 s.fit()
             else:
                 s.clip()
-            cmap.append(s.to_string(hex=True))
+            cmap.append(s)
 
     # Calculate triangles
     tri = Delaunay(list(zip(locals().get(dim[0]), locals().get(dim[1]))))
@@ -281,7 +293,7 @@ def render_rect_face(s1, s2, dim, space, gamut, resolution, opacity, edges):
         simplices=tri.simplices,
         show_colorbar=False,
         plot_edges=edges,
-        color_func=[cmap[t[1]] for t in tri.simplices]
+        color_func=[get_face_color(cmap, t) for t in tri.simplices]
     ).data
     trace[0].update(opacity=opacity)
 


Test patch:
diff --git a/tests/test_average.py b/tests/test_average.py
new file mode 100644
index 000000000..375a7083d
--- /dev/null
+++ b/tests/test_average.py
@@ -0,0 +1,110 @@
+"""Test Averaging."""
+import unittest
+from coloraide.everything import ColorAll as Color
+from . import util
+
+
+class TestAverage(util.ColorAsserts, unittest.TestCase):
+    """Test averaging."""
+
+    def test_no_colors(self):
+        """Test averaging no colors."""
+
+        with self.assertRaises(ValueError):
+            Color.average([])
+
+    def test_one_colors(self):
+        """Test averaging one color."""
+
+        self.assertColorEqual(Color.average(['red']), Color('oklab(0.62796 0.22486 0.12585)'))
+
+    def test_average_premultiplied(self):
+        """Test averaging with premultiplication."""
+
+        colors = [Color('darkgreen'), Color('color(srgb 0 0.50196 0 / 1)'), Color('color(srgb 0 0 1)')]
+        results = []
+        for i in range(5):
+            colors[1].set('alpha', i / 4)
+            results.append(Color.average(colors, space='srgb').to_string(color=True))
+        self.assertEqual(
+            results,
+            ['color(srgb 0 0.19608 0.5 / 0.66667)',
+             'color(srgb 0 0.23007 0.44444 / 0.75)',
+             'color(srgb 0 0.25725 0.4 / 0.83333)',
+             'color(srgb 0 0.2795 0.36364 / 0.91667)',
+             'color(srgb 0 0.29804 0.33333)']
+        )
+
+    def test_average_no_premultiplied(self):
+        """Test averaging without premultiplication."""
+
+        colors = [Color('darkgreen'), Color('color(srgb 0 0.50196 0 / 1)'), Color('color(srgb 0 0 1)')]
+        results = []
+        for i in range(5):
+            colors[1].set('alpha', i / 4)
+            results.append(Color.average(colors, space='srgb', premultiplied=False).to_string(color=True))
+        self.assertEqual(
+            results,
+            ['color(srgb 0 0.29804 0.33333 / 0.66667)',
+             'color(srgb 0 0.29804 0.33333 / 0.75)',
+             'color(srgb 0 0.29804 0.33333 / 0.83333)',
+             'color(srgb 0 0.29804 0.33333 / 0.91667)',
+             'color(srgb 0 0.29804 0.33333)']
+        )
+
+    def test_average_cylindrical_premultiplied(self):
+        """Test cylindrical averaging without premultiplication."""
+
+        colors = [Color('darkgreen'), Color('color(srgb 0 0.50196 0 / 1)'), Color('color(srgb 0 0 1)')]
+        results = []
+        for i in range(5):
+            colors[1].set('alpha', i / 4)
+            results.append(Color.average(colors, space='hsl').to_string(color=True))
+        self.assertEqual(
+            results,
+            ['color(--hsl 150 1 0.34804 / 0.66667)',
+             'color(--hsl 150 1 0.33725 / 0.75)',
+             'color(--hsl 150 1 0.32863 / 0.83333)',
+             'color(--hsl 150 1 0.32157 / 0.91667)',
+             'color(--hsl 150 1 0.31569)']
+        )
+
+    def test_average_cylindrical_no_premultiplied(self):
+        """Test cylindrical averaging without premultiplication."""
+
+        colors = [Color('darkgreen'), Color('color(srgb 0 0.50196 0 / 1)'), Color('color(srgb 0 0 1)')]
+        results = []
+        for i in range(5):
+            colors[1].set('alpha', i / 4)
+            results.append(Color.average(colors, space='hsl', premultiplied=False).to_string(color=True))
+        self.assertEqual(
+            results,
+            ['color(--hsl 150 1 0.31569 / 0.66667)',
+             'color(--hsl 150 1 0.31569 / 0.75)',
+             'color(--hsl 150 1 0.31569 / 0.83333)',
+             'color(--hsl 150 1 0.31569 / 0.91667)',
+             'color(--hsl 150 1 0.31569)']
+        )
+
+    def test_average_ignore_undefined(self):
+        """Test averaging ignores undefined."""
+
+        colors = [Color('darkgreen'), Color('color(srgb 0 none 0 / 1)'), Color('color(srgb 0 0 1)')]
+        results = []
+        for i in range(5):
+            colors[1].set('alpha', i / 4)
+            results.append(Color.average(colors, space='srgb').to_string(color=True))
+        self.assertEqual(
+            results,
+            ['color(srgb 0 0.29412 0.5 / 0.66667)',
+             'color(srgb 0 0.26144 0.44444 / 0.75)',
+             'color(srgb 0 0.23529 0.4 / 0.83333)',
+             'color(srgb 0 0.2139 0.36364 / 0.91667)',
+             'color(srgb 0 0.19608 0.33333)']
+        )
+
+    def test_average_ignore_undefined_alpha_premultiplied(self):
+        """Test averaging ignores undefined."""
+
+        colors = [Color('darkgreen'), Color('color(srgb 0 0.50196 0 / none)'), Color('color(srgb 0 0 1)')]
+        self.assertEqual(Color.average(colors, space='srgb').to_string(color=True), 'color(srgb 0 0.29804 0.33333)')