Repository: facelessuser/coloraide

Issue:
Issues with averaging in polar spaces
Based on the information here: https://en.wikipedia.org/wiki/Circular_mean, when a hue are evenly distributed, there is no circular mean.

Essentially, when the components are broken apart in a Cartesian plane on a unit circle, and the results approach zero, the hue becomes unstable. So when these x and y components are zero (and for our purposes very close to zero), a circular mean is impossible. This makes sense if you thing about finding the hue of red, green, and blue. Whe you are trying to determine the average color, you'd likely get something achromatic. When red, green, and blue are combined, you get white. In this case, you'd probably get a gray though just due to how the other components combine.

Additionally, we should be able to apply premultiplication to rectangular hue components as well when we are calculating the mean to better realize transparent affects on the average.

Hints from issue comments:
@facelessuser: If applying an undefined hue when there is no circular mean, we probably need to force an achromatic state for the color or we'll just get red (or whatever color) which also isn't meaningful.



Solution patch:
diff --git a/coloraide/__meta__.py b/coloraide/__meta__.py
index 8158913b..dec358b4 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(4, 0, 1, "final")
+__version_info__ = Version(4, 1, 0, "final")
 __version__ = __version_info__._get_canonical()
diff --git a/coloraide/average.py b/coloraide/average.py
index f67352aa..243be900 100644
--- a/coloraide/average.py
+++ b/coloraide/average.py
@@ -1,6 +1,7 @@
 """Average colors together."""
 from __future__ import annotations
 import math
+from .spaces import HWBish
 from .types import ColorInput
 from typing import Iterable, TYPE_CHECKING
 
@@ -8,20 +9,31 @@ if TYPE_CHECKING:  # pragma: no cover
     from .color import Color
 
 
+ACHROMATIC_THRESHOLD = 1e-4
+
+
 def average(
     color_cls: type[Color],
     colors: Iterable[ColorInput],
     space: str,
-    premultiplied: bool = True,
-    powerless: bool = False
+    premultiplied: bool = True
 ) -> Color:
-    """Average a list of colors together."""
+    """
+    Average a list of colors together.
+
+    Polar coordinates use a circular mean: https://en.wikipedia.org/wiki/Circular_mean.
+    """
 
     obj = color_cls(space, [])
 
     # Get channel information
     cs = obj.CS_MAP[space]
-    hue_index = cs.hue_index() if cs.is_polar() else -1  # type: ignore[attr-defined]
+    if cs.is_polar():
+        hue_index = cs.hue_index()  # type: ignore[attr-defined]
+        is_hwb = isinstance(cs, HWBish)
+    else:
+        hue_index = -1
+        is_hwb = False
     channels = cs.channels
     chan_count = len(channels)
     alpha_index = chan_count - 1
@@ -35,7 +47,7 @@ def average(
     for c in colors:
         obj.update(c)
         # If cylindrical color is achromatic, ensure hue is undefined
-        if powerless and hue_index >= 0 and not math.isnan(obj[hue_index]) and obj.is_achromatic():
+        if hue_index >= 0 and not math.isnan(obj[hue_index]) and obj.is_achromatic():
             obj[hue_index] = math.nan
         coords = obj[:]
         alpha = coords[-1]
@@ -43,12 +55,17 @@ def average(
             alpha = 1.0
         i = 0
         for coord in coords:
-            if not math.isnan(coord):
+            # No need to average an undefined value or color components if alpha is zero
+            if not math.isnan(coord) and (premultiplied or alpha or i == alpha_index):
                 totals[i] += 1
                 if i == hue_index:
                     rad = math.radians(coord)
-                    sin += math.sin(rad)
-                    cos += math.cos(rad)
+                    if premultiplied:
+                        sin += math.sin(rad) * alpha
+                        cos += math.cos(rad) * alpha
+                    else:
+                        sin += math.sin(rad)
+                        cos += math.cos(rad)
                 else:
                     sums[i] += (coord * alpha) if premultiplied and i != alpha_index else coord
             i += 1
@@ -57,21 +74,35 @@ def average(
         raise ValueError('At least one color must be provided in order to average colors')
 
     # Get the mean
-    alpha = sums[-1]
-    alpha_t = totals[-1]
-    sums[-1] = math.nan if not alpha_t else alpha / alpha_t
-    alpha = sums[-1]
-    if math.isnan(alpha) or alpha in (0.0, 1.0):
+    sums[-1] = alpha = math.nan if not totals[-1] else (sums[-1] / totals[-1])
+    if math.isnan(alpha):
         alpha = 1.0
     for i in range(chan_count - 1):
         total = totals[i]
-        if not total:
+        if not total or not alpha:
             sums[i] = math.nan
         elif i == hue_index:
-            avg_theta = math.degrees(math.atan2(sin / total, cos / total))
-            sums[i] = (avg_theta + 360) if avg_theta < 0 else avg_theta
+            if premultiplied:
+                sin /= total * alpha
+                cos /= total * alpha
+            else:
+                sin /= total
+                cos /= total
+            if abs(sin) < ACHROMATIC_THRESHOLD and abs(cos) < ACHROMATIC_THRESHOLD:
+                sums[i] = math.nan
+            else:
+                avg_theta = math.degrees(math.atan2(sin, cos))
+                sums[i] = (avg_theta + 360) if avg_theta < 0 else avg_theta
         else:
-            sums[i] /= total * alpha if premultiplied else total
+            sums[i] /= (total * alpha) if premultiplied else total
 
-    # Return the color
-    return obj.update(space, sums[:-1], sums[-1])
+    # Create the color and if polar and there is no defined hue, force an achromatic state.
+    color = obj.update(space, sums[:-1], sums[-1])
+    if cs.is_polar():
+        if is_hwb and math.isnan(color[hue_index]):
+            w, b = cs.indexes()[1:]  # type: ignore[attr-defined]
+            if color[w] + color[b] < 1:
+                color[w] = 1 - color[b]
+        elif math.isnan(color[hue_index]) and not math.isnan(color[cs.radial_index()]):  # type: ignore[attr-defined]
+            color[cs.radial_index()] = 0  # type: ignore[attr-defined]
+    return color
diff --git a/coloraide/color.py b/coloraide/color.py
index bdf24294..a7628701 100644
--- a/coloraide/color.py
+++ b/coloraide/color.py
@@ -17,7 +17,7 @@ from . import average
 from . import temperature
 from . import util
 from . import algebra as alg
-from .deprecate import deprecated
+from .deprecate import deprecated, warn_deprecated
 from itertools import zip_longest as zipl
 from .css import parse
 from .types import VectorLike, Vector, ColorInput
@@ -1155,12 +1155,14 @@ class Color(metaclass=ColorMeta):
         if out_space is None:
             out_space = space
 
+        if powerless is not None:  # pragma: no cover
+            warn_deprecated("The use of 'powerless' with 'average()' is deprecated as it is now always enabled")
+
         return average.average(
             cls,
             colors,
             space,
-            premultiplied,
-            powerless if powerless is not None else cls.POWERLESS,
+            premultiplied
         ).convert(out_space, in_place=True)
 
     def filter(  # noqa: A003
diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index 8958ffe0..369a9f52 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -1,5 +1,20 @@
 # Changelog
 
+## 4.1.0
+
+-   **NEW**: The `powerless` parameter is deprecated in `average()` as it is required to be always on for proper polar
+    space averaging.
+-   **FIX**: Polar space averaging was not setting hues to undefined when colors are evenly distributed. This is
+    required as circular means cannot be found in these cases.
+-   **FIX**: When averaging within a polar space, if the result hue is determined to be undefined at the end of
+    averaging, the color will be treated as if achromatic, setting saturation/chroma as necessary. This is needed to
+    prevent serialization of achromatic colors to a non-achromatic color when undefined values are resolved.
+-   **FIX**: Fully transparent colors should only contribute alpha in color averaging, regardless of `premultiply`
+    setting. This prevents fully transparent color channels, which provide no meaningful data, from distorting averages.
+-   **FIX**: When averaging in a polar space, if a color is considered achromatic but does not have an undefined hue,
+    the hue will be treated as undefined. Essentially the `powerless` parameter is now always `True`. This ensures that
+    achromatic colors properly contribute to the average without distorting the hue.
+
 ## 4.0.1
 
 -   **FIX**: Fix issue with `continuous` interpolation (and any that are derived from it, e.g., cubic spline
diff --git a/docs/src/markdown/api/index.md b/docs/src/markdown/api/index.md
index 5fc6f658..d7653c47 100644
--- a/docs/src/markdown/api/index.md
+++ b/docs/src/markdown/api/index.md
@@ -1060,6 +1060,11 @@ Return
 
 ///
 
+/// warning | Deprecated 4.1
+`powerless` parameter has been deprecated in 4.1 and as it is now always enabled. The parameter no longer does anything
+and will be removed in the future.
+///
+
 ## `#!py Color.filter` {#cvd}
 
 ```py
diff --git a/docs/src/markdown/average.md b/docs/src/markdown/average.md
index 615abce6..9915aec3 100644
--- a/docs/src/markdown/average.md
+++ b/docs/src/markdown/average.md
@@ -29,26 +29,28 @@ Color.average(['red', 'yellow', 'orange', 'green'])
 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.
 
-Cylindrical averaging may not provide as good of results as using rectangular spaces, but is provided to provide a sane
-approach if a cylindrical space is used.
+Colors that appear to be achromatic will have their hue treated as undefined, even if the hue is defined.
+
+Cylindrical averaging may provide very different results that averaging in rectangular spaces.
 
 ```py play
-Color.average(['orange', 'yellow', 'red'])
-Color.average(['orange', 'yellow', 'red'], space='hsl')
+Color.average(['purple', 'green', 'blue'])
+Color.average(['purple', 'green', 'blue'], space='hsl')
 ```
 
-Because calculations are done in a cylindrical space, the averaged colors can be different than what is acquired with
-rectangular space averaging.
+It should be noted that when averaging colors with hues which are evenly distributed around the color wheel, the result
+will produce an achromatic hue. When achromatic hues are produced during circular mean, the color will discard
+chroma/saturation information, producing an achromatic color.
 
 ```py play
-Color.average(['purple', 'green', 'blue'])
-Color.average(['purple', 'green', 'blue'], space='hsl')
+Color.average(['red', 'green', 'blue'], space='hsl')
 ```
 
 ## Averaging with Transparency
 
 ColorAide, by default, will account for transparency when averaging colors. Colors which are more transparent will have
-less of an impact on the average. This is done by premultiplying the colors before averaging.
+less of an impact on the average. This is done by premultiplying the colors before averaging, essentially weighting the
+color components where more opaque colors have a greater influence on the average.
 
 ```py play
 for i in range(12):
@@ -57,8 +59,12 @@ for i in range(12):
     )
 ```
 
-If you'd like to average the channels without taking transparency into consideration, simply set `premultiplied` to
-`#!py False`.
+There are cases where this approach of averaging may not be desired. It may be that color averaging is desired without
+considering transparency. If so, `premultiplied` can be disabled by setting it to `#!py False`. While the average of
+transparency is calculated, it can be discarded from the final result if desired.
+
+It should be noted that when a color is fully transparent, its color components will be ignored, regardless of the
+`premultiplied` parameter, as fully transparent colors provide no meaningful color information.
 
 ```py play
 for i in range(12):
@@ -77,8 +83,8 @@ provided for averaging cylindrical colors, particularly achromatic colors.
 Color.average(['white', 'color(srgb 0 0 1)'], space='hsl')
 ```
 
-Implied achromatic hues are only considered undefined if `powerless` is enabled. This is similar to how interpolation
-works. By default, explicitly defined hues are respected if working directly in the averaging color space.
+When averaging hues in a polar space, implied achromatic hues are also treated as undefined as counting such hues would
+distort the average in a non-meaningful way.
 
 ```py play
 Color.average(['hsl(30 0 100)', 'hsl(240 100 50 / 1)'], space='hsl')
@@ -94,7 +100,8 @@ for i in range(12):
     Color.average(['darkgreen', f'color(srgb 0 none 0 / {i / 11})', 'color(srgb 0 0 1)'])
 ```
 
-When `premultiplied` is enabled, premultiplication will not be applied to a color if its `alpha` is undefined.
+When `premultiplied` is enabled, premultiplication will not be applied to a color if its `alpha` is undefined as it is
+unknown how to weight the color, instead the color is treated with full weight.
 
 ```py play
 Color.average(['darkgreen', f'color(srgb 0 0.50196 0 / none)', 'color(srgb 0 0 1)'])
diff --git a/docs/src/markdown/demos/3d_models.html b/docs/src/markdown/demos/3d_models.html
index 37f40028..bd340424 100644
--- a/docs/src/markdown/demos/3d_models.html
+++ b/docs/src/markdown/demos/3d_models.html
@@ -909,7 +909,7 @@ let busyTarget = null
 let colorSpaces = null
 let colorGamuts = null
 let lastModel = null
-let package = 'coloraide-4.0.1-py3-none-any.whl'
+let package = 'coloraide-4.1-py3-none-any.whl'
 const defaultSpace = 'lab'
 const defaultGamut = 'srgb'
 const exceptions = new Set(['hwb', 'ryb', 'ryb-biased'])
diff --git a/docs/src/markdown/demos/colorpicker.html b/docs/src/markdown/demos/colorpicker.html
index ae7bf104..ca2b527d 100644
--- a/docs/src/markdown/demos/colorpicker.html
+++ b/docs/src/markdown/demos/colorpicker.html
@@ -421,7 +421,7 @@
     let pyodide = null
     let webspace = ''
     let initial = 'oklab(0.69 0.13 -0.1 / 0.85)'
-    let package = 'coloraide-4.0.1-py3-none-any.whl'
+    let package = 'coloraide-4.1-py3-none-any.whl'
 
     const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`
     package = base + package
diff --git a/docs/src/mkdocs.yml b/docs/src/mkdocs.yml
index a9ab22ab..c9482e58 100644
--- a/docs/src/mkdocs.yml
+++ b/docs/src/mkdocs.yml
@@ -309,7 +309,7 @@ extra_css:
   - assets/coloraide-extras/extra.css
 extra_javascript:
   - https://unpkg.com/mermaid@10.6.1/dist/mermaid.min.js
-  - playground-config-4f0f586c.js
+  - playground-config-152e791e.js
   - https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js
   - assets/coloraide-extras/extra-notebook.js
 
diff --git a/docs/theme/assets/coloraide-extras/extra-notebook-BvWUnGuN.js b/docs/theme/assets/coloraide-extras/extra-notebook-lX1Ayavv.js
similarity index 52%
rename from docs/theme/assets/coloraide-extras/extra-notebook-BvWUnGuN.js
rename to docs/theme/assets/coloraide-extras/extra-notebook-lX1Ayavv.js
index 2cc2d757..e9bd59a4 100644
--- a/docs/theme/assets/coloraide-extras/extra-notebook-BvWUnGuN.js
+++ b/docs/theme/assets/coloraide-extras/extra-notebook-lX1Ayavv.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},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",s=i.asyncIterator||"@@asyncIterator",l=i.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 i=e&&e.prototype instanceof h?e:h,a=Object.create(i.prototype),s=new I(o||[]);return r(a,"_invoke",{value:A(t,n,s)}),a}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",_="completed",g={};function h(){}function y(){}function v(){}var w={};c(w,a,(function(){return this}));var x=Object.getPrototypeOf,b=x&&x(x(T([])));b&&b!==n&&o.call(b,a)&&(w=b);var E=v.prototype=h.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,i,a,s){var l=d(t[r],t,i);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,a,s)}),(function(t){n("throw",t,a,s)})):e.resolve(u).then((function(t){c.value=t,a(c)}),(function(t){return n("throw",t,a,s)}))}s(l.arg)}var i;r(this,"_invoke",{value:function(t,o){function r(){return new e((function(e,r){n(t,o,e,r)}))}return i=i?i.then(r,r):r()}})}function A(t,n,o){var r=p;return function(i,a){if(r===m)throw new Error("Generator is already running");if(r===_){if("throw"===i)throw a;return{value:e,done:!0}}for(o.method=i,o.arg=a;;){var s=o.delegate;if(s){var l=S(s,o);if(l){if(l===g)continue;return l}}if("next"===o.method)o.sent=o._sent=o.arg;else if("throw"===o.method){if(r===p)throw r=_,o.arg;o.dispatchException(o.arg)}else"return"===o.method&&o.abrupt("return",o.arg);r=m;var c=d(t,n,o);if("normal"===c.type){if(r=o.done?_:f,c.arg===g)continue;return{value:c.arg,done:o.done}}"throw"===c.type&&(r=_,o.method="throw",o.arg=c.arg)}}}function S(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,S(t,n),"throw"===n.method)||"return"!==o&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+o+"' method")),g;var i=d(r,t.iterator,n.arg);if("throw"===i.type)return n.method="throw",n.arg=i.arg,n.delegate=null,g;var a=i.arg;return a?a.done?(n[t.resultName]=a.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=e),n.delegate=null,g):a:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,g)}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(null!=t){var n=t[a];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,i=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 i.next=i}}throw new TypeError(_typeof(t)+" is not iterable")}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,i){void 0===i&&(i=Promise);var a=new L(u(e,n,o,r),i);return t.isGeneratorFunction(n)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},k(E),c(E,l,"Generator"),c(E,a,(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 i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return r("end");if(a.tryLoc<=this.prev){var l=o.call(a,"catchLoc"),c=o.call(a,"finallyLoc");if(l&&c){if(this.prev<a.catchLoc)return r(a.catchLoc,!0);if(this.prev<a.finallyLoc)return r(a.finallyLoc)}else if(l){if(this.prev<a.catchLoc)return r(a.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return r(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 i=r;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,g):this.complete(a)},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),g},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),g}},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),g}},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,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=Array(e);n<e;n++)o[n]=t[n];return o}function e(t,e,n,o,r,i,a){try{var s=t[i](a),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,i){var a=t.apply(n,o);function s(t){e(a,r,i,s,l,"next",t)}function l(t){e(a,r,i,s,l,"throw",t)}s(void 0)}))}}function o(e,n){var o="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!o){if(Array.isArray(e)||(o=function(e,n){if(e){if("string"==typeof e)return t(e,n);var o={}.toString.call(e).slice(8,-1);return"Object"===o&&e.constructor&&(o=e.constructor.name),"Map"===o||"Set"===o?Array.from(e):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?t(e,n):void 0}}(e))||n){o&&(e=o);var r=0,i=function(){};return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(t){throw t},f:i}}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 a,s=!0,l=!1;return{s:function(){o=o.call(e)},n:function(){var t=o.next();return s=t.done,t},e:function(t){l=!0,a=t},f:function(){try{s||null==o.return||o.return()}finally{if(l)throw a}}}}function r(){r=function(){return e};var t,e={},n=Object.prototype,o=n.hasOwnProperty,i=Object.defineProperty||function(t,e,n){t[e]=n.value},a="function"==typeof Symbol?Symbol:{},s=a.iterator||"@@iterator",l=a.asyncIterator||"@@asyncIterator",c=a.toStringTag||"@@toStringTag";function u(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{u({},"")}catch(t){u=function(t,e,n){return t[e]=n}}function d(t,e,n,o){var r=e&&e.prototype instanceof y?e:y,a=Object.create(r.prototype),s=new T(o||[]);return i(a,"_invoke",{value:S(t,n,s)}),a}function p(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}e.wrap=d;var f="suspendedStart",m="suspendedYield",_="executing",g="completed",h={};function y(){}function v(){}function w(){}var x={};u(x,s,(function(){return this}));var b=Object.getPrototypeOf,E=b&&b(b(P([])));E&&E!==n&&o.call(E,s)&&(x=E);var k=w.prototype=y.prototype=Object.create(x);function L(t){["next","throw","return"].forEach((function(e){u(t,e,(function(t){return this._invoke(e,t)}))}))}function A(t,e){function n(r,i,a,s){var l=p(t[r],t,i);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,a,s)}),(function(t){n("throw",t,a,s)})):e.resolve(u).then((function(t){c.value=t,a(c)}),(function(t){return n("throw",t,a,s)}))}s(l.arg)}var r;i(this,"_invoke",{value:function(t,o){function i(){return new e((function(e,r){n(t,o,e,r)}))}return r=r?r.then(i,i):i()}})}function S(e,n,o){var r=f;return function(i,a){if(r===_)throw Error("Generator is already running");if(r===g){if("throw"===i)throw a;return{value:t,done:!0}}for(o.method=i,o.arg=a;;){var s=o.delegate;if(s){var l=C(s,o);if(l){if(l===h)continue;return l}}if("next"===o.method)o.sent=o._sent=o.arg;else if("throw"===o.method){if(r===f)throw r=g,o.arg;o.dispatchException(o.arg)}else"return"===o.method&&o.abrupt("return",o.arg);r=_;var c=p(e,n,o);if("normal"===c.type){if(r=o.done?g:m,c.arg===h)continue;return{value:c.arg,done:o.done}}"throw"===c.type&&(r=g,o.method="throw",o.arg=c.arg)}}}function C(e,n){var o=n.method,r=e.iterator[o];if(r===t)return n.delegate=null,"throw"===o&&e.iterator.return&&(n.method="return",n.arg=t,C(e,n),"throw"===n.method)||"return"!==o&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+o+"' method")),h;var i=p(r,e.iterator,n.arg);if("throw"===i.type)return n.method="throw",n.arg=i.arg,n.delegate=null,h;var a=i.arg;return a?a.done?(n[e.resultName]=a.value,n.next=e.nextLoc,"return"!==n.method&&(n.method="next",n.arg=t),n.delegate=null,h):a:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,h)}function B(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 I(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function T(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(B,this),this.reset(!0)}function P(e){if(e||""===e){var n=e[s];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,i=function n(){for(;++r<e.length;)if(o.call(e,r))return n.value=e[r],n.done=!1,n;return n.value=t,n.done=!0,n};return i.next=i}}throw new TypeError(_typeof(e)+" is not iterable")}return v.prototype=w,i(k,"constructor",{value:w,configurable:!0}),i(w,"constructor",{value:v,configurable:!0}),v.displayName=u(w,c,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===v||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,w):(t.__proto__=w,u(t,c,"GeneratorFunction")),t.prototype=Object.create(k),t},e.awrap=function(t){return{__await:t}},L(A.prototype),u(A.prototype,l,(function(){return this})),e.AsyncIterator=A,e.async=function(t,n,o,r,i){void 0===i&&(i=Promise);var a=new A(d(t,n,o,r),i);return e.isGeneratorFunction(n)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},L(k),u(k,c,"Generator"),u(k,s,(function(){return this})),u(k,"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=P,T.prototype={constructor:T,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(I),!e)for(var n in this)"t"===n.charAt(0)&&o.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=t)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var n=this;function r(o,r){return s.type="throw",s.arg=e,n.next=o,r&&(n.method="next",n.arg=t),!!r}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return r("end");if(a.tryLoc<=this.prev){var l=o.call(a,"catchLoc"),c=o.call(a,"finallyLoc");if(l&&c){if(this.prev<a.catchLoc)return r(a.catchLoc,!0);if(this.prev<a.finallyLoc)return r(a.finallyLoc)}else if(l){if(this.prev<a.catchLoc)return r(a.catchLoc,!0)}else{if(!c)throw Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return r(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 i=r;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,h):this.complete(a)},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),I(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;I(n)}return r}}throw Error("illegal catch attempt")},delegateYield:function(e,n,o){return this.delegate={iterator:P(e),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=t),h}},e}!function(){var t="";try{var e="srgb";window.matchMedia("(color-gamut: rec2020)").matches?e="rec2020":window.matchMedia("(color-gamut: p3)").matches&&(e="display-p3"),t=CSS.supports("color: color(display-p3 1 0 0)")?e:"srgb"}catch(e){t="srgb"}var i=null,a=!1,s="",l="",c={},u=/.*?_(\d+)$/,d=!1,p="",f=!1,m=/^( {1,4}|\t)/,_="\n_N='swatch'\n_M='transparent'\n_L='pycon'\n_K='playground'\n_J='gamut'\n_I='color'\n_H='exceptions'\n_G='highlight'\n_F='eval'\n_E='<string>'\n_D=None\n_C='class'\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',_I])):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 _D: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=_D;self.stdout=_D\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 _D: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),_E,_F),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),_E,_F),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),_E,_F),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),_E,_F),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,_D)\n\t\tif name is _D:raise NameError(f\"name '{node.cls.id}' is not defined\")\n\t\tif not isinstance(s,name):return _A\n\t\tma=getattr(s,'__match_args__',());l1=len(ma);l2=len(node.patterns)\n\t\tif l1<l2:raise TypeError(f\"{name}() accepts {l1} positional sub-patterns ({l2} given)\")\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 _D:g[node.name]=s\n\t\tif node.pattern:return compare_match(s,g,node.pattern)\n\t\treturn _B\n\traise RuntimeError(f\"Unknown Match pattern {node!s}\")\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 _D:\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),_E,_F),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,_E,_F),g)\n\telif isinstance(node,ast.If):\n\t\tif eval(compile(ast.Expression(node.test),_E,_F),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),_E,_F),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),_E,_F),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),_E,_F),g))\n\t\t\t\tif m is not _D:\n\t\t\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\t\tif e is _D:break\n\t\t\tif e is not _D: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),_E,_F),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),_E,_F),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,_E,'exec'),g);yield _D\ndef execute(cmd,no_except=_B,inline=_A,init='',g=_D):\n\tA='\\n';console='';colors=[]\n\tif g is _D: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 f\"{traceback.format_exc()}\",colors\n\tfor node in tree.body:\n\t\tresult=[];start=node.lineno;col_start=node.col_offset;end=node.end_lineno;col_end=node.end_col_offset;stmt=lines[start-1:end];command=''\n\t\tfor(i,line)in enumerate(stmt,0):\n\t\t\tif i==0:stmt[i]='>>> '+(line[col_start:col_end]if isinstance(node,ast.Expr)else line)\n\t\t\telse:stmt[i]='... '+(line[col_start:col_end]if isinstance(node,ast.Expr)else 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+=f\"{command}\\n{traceback.format_exc()}\";break\n\t\tresult_text=A\n\t\tfor r in result:\n\t\t\tif r is _D: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={_H,'play','wheel'}\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\tis_grad=isinstance(item,HtmlGradient);is_steps=isinstance(item,Steps)\n\t\tif is_grad or is_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);color_str=color.convert(gamut).to_string()\n\t\t\t\tif current:\n\t\t\t\t\tif is_steps:stops.append(f\"{color_str} {last!s}%\");stops.append(f\"{color_str} {current!s}%\")\n\t\t\t\t\telse:stops.append(color_str)\n\t\t\t\t\tlast=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_str)\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=f'<span class=\"swatch-color\" style=\"{style}\"></span>';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=f\"--swatch-stops: {value1} 50%, {value2} 50%\";title=color.string;classes=base_classes;c=f'<span class=\"swatch-color\" style=\"{style}\"></span>';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=_D,options=_D,md='',init='',**kwargs):\n\tC='</div>';B='formatter';A='fenced_code_block';global code_id;from pymdownx.superfences import SuperFencesException;gamut=kwargs.get(_J,WEBSPACE);wheel=options.get('wheel',_A);play=options.get('play',_A)if options is not _D 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 wheel:\n\t\t\tgamut='srgb';exceptions=options.get(_H,_A)if options is not _D else _A;_,colors=execute(src.strip(),not exceptions,init=init);l=len(colors)\n\t\t\tif l not in(12,24,48):raise SuperFencesException('Color wheel requires either 12, 24, or 48 colors')\n\t\t\tcolors=[c[0].color for c in colors]\n\t\t\tif l==12:freq=4;offset=6\n\t\t\telif l==24:freq=8;offset=12\n\t\t\telse:freq=16;offset=24\n\t\t\tprimary=colors[::freq][::-1];secondary=(colors[offset::freq]+[colors[offset//3]])[::-1];tertiary=colors[::offset//6][::-1];color_rings=[primary,secondary,tertiary];extra_rings_start='';extra_rings_end=''\n\t\t\tif l>12:extra_rings_start='<div class=\"tertiary2\">';extra_rings_end+=C;color_rings.append(colors[::offset//12][::-1])\n\t\t\tif l>24:extra_rings_start='<div class=\"tertiary3\">'+extra_rings_start;extra_rings_end+=C;color_rings.append(colors[::-1])\n\t\t\tcolor_stops=''\n\t\t\tfor(i,colors)in enumerate(color_rings,1):\n\t\t\t\ttotal=len(colors);percent=100/total;current=percent;last=-1;stops=[]\n\t\t\t\tfor(e,color)in enumerate(colors):\n\t\t\t\t\tcolor.fit(gamut);color_str=color.convert(gamut).to_string()\n\t\t\t\t\tif current:\n\t\t\t\t\t\tstops.append(f\"{color_str} {last!s}%\");stops.append(f\"{color_str} {current!s}%\");last=current\n\t\t\t\t\t\tif e<total-1:current+=percent\n\t\t\t\t\t\telse:current=100\n\t\t\t\t\telse:stops.append(color_str)\n\t\t\t\tcolor_stops+='--color-wheel-stops{}: {};'.format(i,','.join(stops))\n\t\t\tcolor_wheel='<div class=\"color-wheel\" style=\"{}\"><div class=\"wheel\">\\n{}<div class=\"tertiary\"><div class=\"secondary\"><div class=\"secondary-inner\"><div class=\"primary\"><div class=\"primary-inner\"></div></div></div></div></div></div></div>{}'.format(color_stops,extra_rings_start,extra_rings_end);return color_wheel\n\t\telse:\n\t\t\tif len(md.preprocessors[A].extension.stash)==0:code_id=0\n\t\t\texceptions=options.get(_H,_A)if options is not _D 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=f'<div class=\"color-command\">{el}</div>';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=_D,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 as e:\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)from e\n\t\t\t\telse:raise ValueError(C)from e\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={_C:'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.:stops[-1]+=B;stops.append(color.convert(gamut).to_string(hex=_B)+B)\n\t\telse:\n\t\t\tattributes={_C:_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.: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,{_C:'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=f'<div class=\"color-command\">{el}</div>'\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[_H]=_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=f\"Gamut: {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\td='quote';c='example';b='bug';a='danger';Z='failure';Y='warning';X='question';W='success';V='tip';U='info';T='abstract';S='note';R='settings';Q='new';P='types';O='diagram';N='pymdownx.fancylists';M='pymdownx.blocks.tab';L='pymdownx.blocks.details';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,L,'pymdownx.blocks.html','pymdownx.blocks.definition',M,N];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:O,_C:O,B:superfences.fence_code_format},{A:_K,_C:_K,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'python',_C:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'py',_C:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator}]},G:{'custom_inline':[{A:_I,_C:_I,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':'＋'},M:{'alternate_style':_B},K:{P:[Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d]},N:{'inject_style':_B},L:{P:[{A:'details-new',_C:Q},{A:'details-settings',_C:R},{A:'details-note',_C:S},{A:'details-abstract',_C:T},{A:'details-info',_C:U},{A:'details-tip',_C:V},{A:'details-success',_C:W},{A:'details-question',_C:X},{A:'details-warning',_C:Y},{A:'details-failure',_C:Z},{A:'details-danger',_C:a},{A:'details-bug',_C:b},{A:'details-example',_C:c},{A:'details-quote',_C:d}]}}\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(t,"')\n"),g=window.colorNotebook.defaultPlayground,h=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(Math.min(t.scrollHeight,408),"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 t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(n=document.getElementById("__playground-inputs_".concat(e))).setAttribute("readonly",""),i.globals.set("id_num",e),i.globals.set("action","playground"),t.next=6,i.runPythonAsync(_);case 6:n.removeAttribute("readonly");case 7:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),k=function(){var t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return i.globals.set("content",e),i.globals.set("action","notebook"),t.next=4,i.runPythonAsync(_);case 4:(n=document.getElementById("__notebook-input"))&&(s=e,n.value=e),window.location.hash&&(window.location.href=window.location.href);case 7:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),L=function(){var t=n(r().mark((function t(e){var n,a,s,l,c,u;return r().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.26.2/full/",fullStdLib:!1});case 4:i=t.sent;case 5:if((y||!e)&&(v||e)){t.next=14;break}n="".concat(window.location.origin,"/").concat(window.location.pathname.split("/")[1],"/playground/"),a=e?window.colorNotebook.notebookWheels:window.colorNotebook.playgroundWheels,s=[],e?y=!0:v=!0,l=o(a);try{for(l.s();!(c=l.n()).done;)(u=c.value).endsWith(".whl")?s.push(n+u):s.push(u)}catch(t){l.e(t)}finally{l.f()}return t.next=14,i.loadPackage(s);case 14:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),A=function(t,e,n){var o=null==e?"Loading...":e,r=n?"loading relative":"loading",i=document.createElement("template");i.innerHTML='<div class="'.concat(r,'"><div class="loader"></div><div>').concat(o,"</div></div>"),t.appendChild(i.content.firstChild)},S=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 i=r.substr(n,o-n).split("\n"),a=0;a<i.length;a++)a===i.length-1&&0===i[a].length||(t.shiftKey?i[a]=i[a].replace(m,""):i[a]="    ".concat(i[a]));i=i.join("\n"),e.value=r.substr(0,n)+i+r.substr(o),e.selectionStart=n,e.selectionEnd=n+i.length}}},B=function(){var t=n(r().mark((function t(e){var o,i,d;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:o=document.getElementById("__notebook-source"),i=document.querySelectorAll(".playground"),o&&e&&((d=document.getElementById("__notebook-input")).addEventListener("input",(function(t){x(t.target)})),d.addEventListener("keydown",C),document.getElementById("__notebook-edit").addEventListener("click",(function(){c[d.id]=d.value,document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),document.getElementById("__notebook-input").setAttribute("style",""),x(document.getElementById("__notebook-input"))})),document.getElementById("__notebook-md-gist").addEventListener("click",function(){var t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(n=prompt("Please enter link to the Markdown page source:",l))&&(n=b(n),e.preventDefault(),history.pushState({notebook:n},"","?".concat(new URLSearchParams("notebook=".concat(n)).toString())),I(!1));case 2:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),document.getElementById("__notebook-py-gist").addEventListener("click",function(){var t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(n=prompt("Please enter the link to the Python code source:",l))&&(n=b(n),e.preventDefault(),history.pushState({source:n},"","?".concat(new URLSearchParams("source=".concat(n)).toString())),I(!1));case 2:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),document.getElementById("__notebook-input").value=s,document.getElementById("__notebook-cancel").addEventListener("click",(function(){d.value=c[d.id],delete c[d.id],document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden")})),document.getElementById("__notebook-submit").addEventListener("click",n(r().mark((function t(){var e,n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return e=document.getElementById("__notebook-render"),s=document.getElementById("__notebook-input").value,e.classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),n=document.querySelector("article"),A(n,"Loading Notebook..."),e.innerHTML="",c={},t.next=10,L(!0);case 10:return t.next=12,k(s);case 12:return t.next=14,B();case 14:S(n),w();case 16:case"end":return t.stop()}}),t)}))))),i.forEach((function(t){var e=t.id.replace(u,"$1"),o=document.getElementById("__playground-inputs_".concat(e)),i=document.getElementById("__playground-results_".concat(e)),s=document.getElementById("__playground-code_".concat(e)),l=document.querySelector("button#__playground-edit_".concat(e)),d=document.querySelector("button#__playground-share_".concat(e)),p=document.querySelector("button#__playground-run_".concat(e)),f=document.querySelector("button#__playground-cancel_".concat(e));o.addEventListener("input",(function(){x(o)})),o.addEventListener("keydown",C),o.addEventListener("touchmove",(function(t){t.stopPropagation()})),i.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)}}}}})),l.addEventListener("click",n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:c[e]=o.value,s.classList.toggle("hidden"),i.classList.toggle("hidden"),p.classList.toggle("hidden"),f.classList.toggle("hidden"),l.classList.toggle("hidden"),d.classList.toggle("hidden"),x(o),o.focus();case 9:case"end":return t.stop()}}),t)})))),d.addEventListener("click",n(r().mark((function t(){var e,i,a,s,l;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=window.location.pathname.split("/")[1],i=b(o.value),a=window.location,s="/playground/",a.pathname.startsWith("/".concat(e,"/"))&&(s="/".concat(e,"/playground/")),(l="".concat(a.protocol,"//").concat(a.host).concat(s,"?code=").concat(i)).length>2e3?alert("Code must be small enough to generate a shareable URL under 2000 characters!"):navigator.clipboard.writeText(l).then(n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Link copied to clipboard :)");case 1:case"end":return t.stop()}}),t)}))),n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Failed to copy link clipboard!");case 1:case"end":return t.stop()}}),t)}))));case 7:case"end":return t.stop()}}),t)})))),p.addEventListener("click",n(r().mark((function t(){var n,o;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!a){t.next=2;break}return t.abrupt("return");case 2:return a=!0,n=s.querySelector("form"),A(n,null,!0),(o=document.querySelectorAll(".playground .playground-run"))&&o.forEach((function(t){t.setAttribute("disabled","")})),t.next=9,L(!1);case 9:return i.querySelector("code").innerHTML="",t.next=12,E(e);case 12:o&&o.forEach((function(t){t.removeAttribute("disabled")})),S(n),s.classList.toggle("hidden"),i.classList.toggle("hidden"),l.classList.toggle("hidden"),d.classList.toggle("hidden"),p.classList.toggle("hidden"),f.classList.toggle("hidden"),delete c[e],a=!1;case 22:case"end":return t.stop()}}),t)})))),f.addEventListener("click",(function(){o.value=c[e],delete c[e],s.classList.toggle("hidden"),i.classList.toggle("hidden"),l.classList.toggle("hidden"),d.classList.toggle("hidden"),p.classList.toggle("hidden"),f.classList.toggle("hidden")}))}));case 4:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),I=function(){var t=n(r().mark((function t(e,o){var i,a,s,u,d,f,m,_,y;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(c={},!window.location.pathname.endsWith("/playground/")){t.next=32;break}if(i=o||new URLSearchParams(window.location.search),a="Loading Pyodide...",s="Loading Notebook...",u=i.has("source")?i.get("source"):i.get("notebook"),d=document.querySelector("article"),null===u||!u.trim()){t.next=16;break}return A(d,a),t.next=11,L(!0);case 11:S(d),A(d,s);try{f=i.has("source")?"source":"notebook",p=decodeURIComponent(i.toString()),m="",_=new XMLHttpRequest,l=u,_.open("GET",u,!0),_.onload=n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return 4===_.readyState&&200===_.status&&(m=_.responseText),"source"===f&&(m=h(m)),t.next=4,k(m);case 4:return t.next=6,B(e);case 6:S(d),w();case 8:case"end":return t.stop()}}),t)}))),_.send()}catch(t){}t.next=30;break;case 16:return l="",y=h(i.has("code")?i.get("code"):g),p=decodeURIComponent(i.toString()),A(d,a),t.next=22,L(!0);case 22:return S(d),A(d,s),t.next=26,k(y);case 26:return t.next=28,B(e);case 28:S(d),w();case 30:t.next=35;break;case 32:l="",p="",B(e);case 35:case"end":return t.stop()}}),t)})));return function(e,n){return t.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-BvWUnGuN.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},i="function"==typeof Symbol?Symbol:{},a=i.iterator||"@@iterator",s=i.asyncIterator||"@@asyncIterator",l=i.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 i=e&&e.prototype instanceof h?e:h,a=Object.create(i.prototype),s=new I(o||[]);return r(a,"_invoke",{value:A(t,n,s)}),a}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",_="completed",g={};function h(){}function y(){}function v(){}var w={};c(w,a,(function(){return this}));var x=Object.getPrototypeOf,b=x&&x(x(T([])));b&&b!==n&&o.call(b,a)&&(w=b);var E=v.prototype=h.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,i,a,s){var l=d(t[r],t,i);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,a,s)}),(function(t){n("throw",t,a,s)})):e.resolve(u).then((function(t){c.value=t,a(c)}),(function(t){return n("throw",t,a,s)}))}s(l.arg)}var i;r(this,"_invoke",{value:function(t,o){function r(){return new e((function(e,r){n(t,o,e,r)}))}return i=i?i.then(r,r):r()}})}function A(t,n,o){var r=p;return function(i,a){if(r===m)throw new Error("Generator is already running");if(r===_){if("throw"===i)throw a;return{value:e,done:!0}}for(o.method=i,o.arg=a;;){var s=o.delegate;if(s){var l=S(s,o);if(l){if(l===g)continue;return l}}if("next"===o.method)o.sent=o._sent=o.arg;else if("throw"===o.method){if(r===p)throw r=_,o.arg;o.dispatchException(o.arg)}else"return"===o.method&&o.abrupt("return",o.arg);r=m;var c=d(t,n,o);if("normal"===c.type){if(r=o.done?_:f,c.arg===g)continue;return{value:c.arg,done:o.done}}"throw"===c.type&&(r=_,o.method="throw",o.arg=c.arg)}}}function S(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,S(t,n),"throw"===n.method)||"return"!==o&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+o+"' method")),g;var i=d(r,t.iterator,n.arg);if("throw"===i.type)return n.method="throw",n.arg=i.arg,n.delegate=null,g;var a=i.arg;return a?a.done?(n[t.resultName]=a.value,n.next=t.nextLoc,"return"!==n.method&&(n.method="next",n.arg=e),n.delegate=null,g):a:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,g)}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(null!=t){var n=t[a];if(n)return n.call(t);if("function"==typeof t.next)return t;if(!isNaN(t.length)){var r=-1,i=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 i.next=i}}throw new TypeError(_typeof(t)+" is not iterable")}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,i){void 0===i&&(i=Promise);var a=new L(u(e,n,o,r),i);return t.isGeneratorFunction(n)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},k(E),c(E,l,"Generator"),c(E,a,(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 i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return r("end");if(a.tryLoc<=this.prev){var l=o.call(a,"catchLoc"),c=o.call(a,"finallyLoc");if(l&&c){if(this.prev<a.catchLoc)return r(a.catchLoc,!0);if(this.prev<a.finallyLoc)return r(a.finallyLoc)}else if(l){if(this.prev<a.catchLoc)return r(a.catchLoc,!0)}else{if(!c)throw new Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return r(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 i=r;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,g):this.complete(a)},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),g},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),g}},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),g}},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,e){(null==e||e>t.length)&&(e=t.length);for(var n=0,o=Array(e);n<e;n++)o[n]=t[n];return o}function e(t,e,n,o,r,i,a){try{var s=t[i](a),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,i){var a=t.apply(n,o);function s(t){e(a,r,i,s,l,"next",t)}function l(t){e(a,r,i,s,l,"throw",t)}s(void 0)}))}}function o(e,n){var o="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!o){if(Array.isArray(e)||(o=function(e,n){if(e){if("string"==typeof e)return t(e,n);var o={}.toString.call(e).slice(8,-1);return"Object"===o&&e.constructor&&(o=e.constructor.name),"Map"===o||"Set"===o?Array.from(e):"Arguments"===o||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(o)?t(e,n):void 0}}(e))||n){o&&(e=o);var r=0,i=function(){};return{s:i,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(t){throw t},f:i}}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 a,s=!0,l=!1;return{s:function(){o=o.call(e)},n:function(){var t=o.next();return s=t.done,t},e:function(t){l=!0,a=t},f:function(){try{s||null==o.return||o.return()}finally{if(l)throw a}}}}function r(){r=function(){return e};var t,e={},n=Object.prototype,o=n.hasOwnProperty,i=Object.defineProperty||function(t,e,n){t[e]=n.value},a="function"==typeof Symbol?Symbol:{},s=a.iterator||"@@iterator",l=a.asyncIterator||"@@asyncIterator",c=a.toStringTag||"@@toStringTag";function u(t,e,n){return Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}),t[e]}try{u({},"")}catch(t){u=function(t,e,n){return t[e]=n}}function d(t,e,n,o){var r=e&&e.prototype instanceof y?e:y,a=Object.create(r.prototype),s=new T(o||[]);return i(a,"_invoke",{value:S(t,n,s)}),a}function p(t,e,n){try{return{type:"normal",arg:t.call(e,n)}}catch(t){return{type:"throw",arg:t}}}e.wrap=d;var f="suspendedStart",m="suspendedYield",_="executing",g="completed",h={};function y(){}function v(){}function w(){}var x={};u(x,s,(function(){return this}));var b=Object.getPrototypeOf,E=b&&b(b(P([])));E&&E!==n&&o.call(E,s)&&(x=E);var k=w.prototype=y.prototype=Object.create(x);function L(t){["next","throw","return"].forEach((function(e){u(t,e,(function(t){return this._invoke(e,t)}))}))}function A(t,e){function n(r,i,a,s){var l=p(t[r],t,i);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,a,s)}),(function(t){n("throw",t,a,s)})):e.resolve(u).then((function(t){c.value=t,a(c)}),(function(t){return n("throw",t,a,s)}))}s(l.arg)}var r;i(this,"_invoke",{value:function(t,o){function i(){return new e((function(e,r){n(t,o,e,r)}))}return r=r?r.then(i,i):i()}})}function S(e,n,o){var r=f;return function(i,a){if(r===_)throw Error("Generator is already running");if(r===g){if("throw"===i)throw a;return{value:t,done:!0}}for(o.method=i,o.arg=a;;){var s=o.delegate;if(s){var l=C(s,o);if(l){if(l===h)continue;return l}}if("next"===o.method)o.sent=o._sent=o.arg;else if("throw"===o.method){if(r===f)throw r=g,o.arg;o.dispatchException(o.arg)}else"return"===o.method&&o.abrupt("return",o.arg);r=_;var c=p(e,n,o);if("normal"===c.type){if(r=o.done?g:m,c.arg===h)continue;return{value:c.arg,done:o.done}}"throw"===c.type&&(r=g,o.method="throw",o.arg=c.arg)}}}function C(e,n){var o=n.method,r=e.iterator[o];if(r===t)return n.delegate=null,"throw"===o&&e.iterator.return&&(n.method="return",n.arg=t,C(e,n),"throw"===n.method)||"return"!==o&&(n.method="throw",n.arg=new TypeError("The iterator does not provide a '"+o+"' method")),h;var i=p(r,e.iterator,n.arg);if("throw"===i.type)return n.method="throw",n.arg=i.arg,n.delegate=null,h;var a=i.arg;return a?a.done?(n[e.resultName]=a.value,n.next=e.nextLoc,"return"!==n.method&&(n.method="next",n.arg=t),n.delegate=null,h):a:(n.method="throw",n.arg=new TypeError("iterator result is not an object"),n.delegate=null,h)}function B(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 I(t){var e=t.completion||{};e.type="normal",delete e.arg,t.completion=e}function T(t){this.tryEntries=[{tryLoc:"root"}],t.forEach(B,this),this.reset(!0)}function P(e){if(e||""===e){var n=e[s];if(n)return n.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var r=-1,i=function n(){for(;++r<e.length;)if(o.call(e,r))return n.value=e[r],n.done=!1,n;return n.value=t,n.done=!0,n};return i.next=i}}throw new TypeError(_typeof(e)+" is not iterable")}return v.prototype=w,i(k,"constructor",{value:w,configurable:!0}),i(w,"constructor",{value:v,configurable:!0}),v.displayName=u(w,c,"GeneratorFunction"),e.isGeneratorFunction=function(t){var e="function"==typeof t&&t.constructor;return!!e&&(e===v||"GeneratorFunction"===(e.displayName||e.name))},e.mark=function(t){return Object.setPrototypeOf?Object.setPrototypeOf(t,w):(t.__proto__=w,u(t,c,"GeneratorFunction")),t.prototype=Object.create(k),t},e.awrap=function(t){return{__await:t}},L(A.prototype),u(A.prototype,l,(function(){return this})),e.AsyncIterator=A,e.async=function(t,n,o,r,i){void 0===i&&(i=Promise);var a=new A(d(t,n,o,r),i);return e.isGeneratorFunction(n)?a:a.next().then((function(t){return t.done?t.value:a.next()}))},L(k),u(k,c,"Generator"),u(k,s,(function(){return this})),u(k,"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=P,T.prototype={constructor:T,reset:function(e){if(this.prev=0,this.next=0,this.sent=this._sent=t,this.done=!1,this.delegate=null,this.method="next",this.arg=t,this.tryEntries.forEach(I),!e)for(var n in this)"t"===n.charAt(0)&&o.call(this,n)&&!isNaN(+n.slice(1))&&(this[n]=t)},stop:function(){this.done=!0;var t=this.tryEntries[0].completion;if("throw"===t.type)throw t.arg;return this.rval},dispatchException:function(e){if(this.done)throw e;var n=this;function r(o,r){return s.type="throw",s.arg=e,n.next=o,r&&(n.method="next",n.arg=t),!!r}for(var i=this.tryEntries.length-1;i>=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return r("end");if(a.tryLoc<=this.prev){var l=o.call(a,"catchLoc"),c=o.call(a,"finallyLoc");if(l&&c){if(this.prev<a.catchLoc)return r(a.catchLoc,!0);if(this.prev<a.finallyLoc)return r(a.finallyLoc)}else if(l){if(this.prev<a.catchLoc)return r(a.catchLoc,!0)}else{if(!c)throw Error("try statement without catch or finally");if(this.prev<a.finallyLoc)return r(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 i=r;break}}i&&("break"===t||"continue"===t)&&i.tryLoc<=e&&e<=i.finallyLoc&&(i=null);var a=i?i.completion:{};return a.type=t,a.arg=e,i?(this.method="next",this.next=i.finallyLoc,h):this.complete(a)},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),I(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;I(n)}return r}}throw Error("illegal catch attempt")},delegateYield:function(e,n,o){return this.delegate={iterator:P(e),resultName:n,nextLoc:o},"next"===this.method&&(this.arg=t),h}},e}!function(){var t="";try{var e="srgb";window.matchMedia("(color-gamut: rec2020)").matches?e="rec2020":window.matchMedia("(color-gamut: p3)").matches&&(e="display-p3"),t=CSS.supports("color: color(display-p3 1 0 0)")?e:"srgb"}catch(e){t="srgb"}var i=null,a=!1,s="",l="",c={},u=/.*?_(\d+)$/,d=!1,p="",f=!1,m=/^( {1,4}|\t)/,_="\n_N='swatch'\n_M='transparent'\n_L='pycon'\n_K='playground'\n_J='gamut'\n_I='color'\n_H='exceptions'\n_G='highlight'\n_F='eval'\n_E='<string>'\n_D=None\n_C='class'\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',_I])):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 _D: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=_D;self.stdout=_D\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 _D: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),_E,_F),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),_E,_F),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),_E,_F),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),_E,_F),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,_D)\n\t\tif name is _D:raise NameError(f\"name '{node.cls.id}' is not defined\")\n\t\tif not isinstance(s,name):return _A\n\t\tma=getattr(s,'__match_args__',());l1=len(ma);l2=len(node.patterns)\n\t\tif l1<l2:raise TypeError(f\"{name}() accepts {l1} positional sub-patterns ({l2} given)\")\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 _D:g[node.name]=s\n\t\tif node.pattern:return compare_match(s,g,node.pattern)\n\t\treturn _B\n\traise RuntimeError(f\"Unknown Match pattern {node!s}\")\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 _D:\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),_E,_F),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,_E,_F),g)\n\telif isinstance(node,ast.If):\n\t\tif eval(compile(ast.Expression(node.test),_E,_F),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),_E,_F),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),_E,_F),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),_E,_F),g))\n\t\t\t\tif m is not _D:\n\t\t\t\t\tfor ne in n.body:yield from evaluate(ne,g,loop)\n\t\t\t\tif e is _D:break\n\t\t\tif e is not _D: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),_E,_F),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),_E,_F),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,_E,'exec'),g);yield _D\ndef execute(cmd,no_except=_B,inline=_A,init='',g=_D):\n\tA='\\n';console='';colors=[]\n\tif g is _D: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 f\"{traceback.format_exc()}\",colors\n\tfor node in tree.body:\n\t\tresult=[];start=node.lineno;col_start=node.col_offset;end=node.end_lineno;col_end=node.end_col_offset;stmt=lines[start-1:end];command=''\n\t\tfor(i,line)in enumerate(stmt,0):\n\t\t\tif i==0:stmt[i]='>>> '+(line[col_start:col_end]if isinstance(node,ast.Expr)else line)\n\t\t\telse:stmt[i]='... '+(line[col_start:col_end]if isinstance(node,ast.Expr)else 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\ttext=s.read()\n\t\t\t\t\tif text:result.append(AtomicString(text))\n\t\t\t\t\tresult.append(x)\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+=f\"{command}\\n{traceback.format_exc()}\";break\n\t\tresult_text=A\n\t\tfor r in result:\n\t\t\tif r is _D: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={_H,'play','wheel'}\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\tis_grad=isinstance(item,HtmlGradient);is_steps=isinstance(item,Steps)\n\t\tif is_grad or is_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);color_str=color.convert(gamut).to_string()\n\t\t\t\tif current:\n\t\t\t\t\tif is_steps:stops.append(f\"{color_str} {last!s}%\");stops.append(f\"{color_str} {current!s}%\")\n\t\t\t\t\telse:stops.append(color_str)\n\t\t\t\t\tlast=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_str)\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=f'<span class=\"swatch-color\" style=\"{style}\"></span>';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=f\"--swatch-stops: {value1} 50%, {value2} 50%\";title=color.string;classes=base_classes;c=f'<span class=\"swatch-color\" style=\"{style}\"></span>';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=_D,options=_D,md='',init='',**kwargs):\n\tC='</div>';B='formatter';A='fenced_code_block';global code_id;from pymdownx.superfences import SuperFencesException;gamut=kwargs.get(_J,WEBSPACE);wheel=options.get('wheel',_A);play=options.get('play',_A)if options is not _D 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 wheel:\n\t\t\tgamut='srgb';exceptions=options.get(_H,_A)if options is not _D else _A;_,colors=execute(src.strip(),not exceptions,init=init);l=len(colors)\n\t\t\tif l not in(12,24,48):raise SuperFencesException('Color wheel requires either 12, 24, or 48 colors')\n\t\t\tcolors=[c[0].color for c in colors]\n\t\t\tif l==12:freq=4;offset=6\n\t\t\telif l==24:freq=8;offset=12\n\t\t\telse:freq=16;offset=24\n\t\t\tprimary=colors[::freq][::-1];secondary=(colors[offset::freq]+[colors[offset//3]])[::-1];tertiary=colors[::offset//6][::-1];color_rings=[primary,secondary,tertiary];extra_rings_start='';extra_rings_end=''\n\t\t\tif l>12:extra_rings_start='<div class=\"tertiary2\">';extra_rings_end+=C;color_rings.append(colors[::offset//12][::-1])\n\t\t\tif l>24:extra_rings_start='<div class=\"tertiary3\">'+extra_rings_start;extra_rings_end+=C;color_rings.append(colors[::-1])\n\t\t\tcolor_stops=''\n\t\t\tfor(i,colors)in enumerate(color_rings,1):\n\t\t\t\ttotal=len(colors);percent=100/total;current=percent;last=-1;stops=[]\n\t\t\t\tfor(e,color)in enumerate(colors):\n\t\t\t\t\tcolor.fit(gamut);color_str=color.convert(gamut).to_string()\n\t\t\t\t\tif current:\n\t\t\t\t\t\tstops.append(f\"{color_str} {last!s}%\");stops.append(f\"{color_str} {current!s}%\");last=current\n\t\t\t\t\t\tif e<total-1:current+=percent\n\t\t\t\t\t\telse:current=100\n\t\t\t\t\telse:stops.append(color_str)\n\t\t\t\tcolor_stops+='--color-wheel-stops{}: {};'.format(i,','.join(stops))\n\t\t\tcolor_wheel='<div class=\"color-wheel\" style=\"{}\"><div class=\"wheel\">\\n{}<div class=\"tertiary\"><div class=\"secondary\"><div class=\"secondary-inner\"><div class=\"primary\"><div class=\"primary-inner\"></div></div></div></div></div></div></div>{}'.format(color_stops,extra_rings_start,extra_rings_end);return color_wheel\n\t\telse:\n\t\t\tif len(md.preprocessors[A].extension.stash)==0:code_id=0\n\t\t\texceptions=options.get(_H,_A)if options is not _D 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=f'<div class=\"color-command\">{el}</div>';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=_D,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 as e:\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)from e\n\t\t\t\telse:raise ValueError(C)from e\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={_C:'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.:stops[-1]+=B;stops.append(color.convert(gamut).to_string(hex=_B)+B)\n\t\telse:\n\t\t\tattributes={_C:_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.: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,{_C:'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=f'<div class=\"color-command\">{el}</div>'\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[_H]=_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=f\"Gamut: {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\td='quote';c='example';b='bug';a='danger';Z='failure';Y='warning';X='question';W='success';V='tip';U='info';T='abstract';S='note';R='settings';Q='new';P='types';O='diagram';N='pymdownx.fancylists';M='pymdownx.blocks.tab';L='pymdownx.blocks.details';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,L,'pymdownx.blocks.html','pymdownx.blocks.definition',M,N];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:O,_C:O,B:superfences.fence_code_format},{A:_K,_C:_K,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'python',_C:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator},{A:'py',_C:_G,B:color_command_formatter(LIVE_INIT,gamut),C:live_color_command_validator}]},G:{'custom_inline':[{A:_I,_C:_I,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':'＋'},M:{'alternate_style':_B},K:{P:[Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d]},N:{'inject_style':_B},L:{P:[{A:'details-new',_C:Q},{A:'details-settings',_C:R},{A:'details-note',_C:S},{A:'details-abstract',_C:T},{A:'details-info',_C:U},{A:'details-tip',_C:V},{A:'details-success',_C:W},{A:'details-question',_C:X},{A:'details-warning',_C:Y},{A:'details-failure',_C:Z},{A:'details-danger',_C:a},{A:'details-bug',_C:b},{A:'details-example',_C:c},{A:'details-quote',_C:d}]}}\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(t,"')\n"),g=window.colorNotebook.defaultPlayground,h=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(Math.min(t.scrollHeight,408),"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 t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return(n=document.getElementById("__playground-inputs_".concat(e))).setAttribute("readonly",""),i.globals.set("id_num",e),i.globals.set("action","playground"),t.next=6,i.runPythonAsync(_);case 6:n.removeAttribute("readonly");case 7:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),k=function(){var t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return i.globals.set("content",e),i.globals.set("action","notebook"),t.next=4,i.runPythonAsync(_);case 4:(n=document.getElementById("__notebook-input"))&&(s=e,n.value=e),window.location.hash&&(window.location.href=window.location.href);case 7:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),L=function(){var t=n(r().mark((function t(e){var n,a,s,l,c,u;return r().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.26.2/full/",fullStdLib:!1});case 4:i=t.sent;case 5:if((y||!e)&&(v||e)){t.next=14;break}n="".concat(window.location.origin,"/").concat(window.location.pathname.split("/")[1],"/playground/"),a=e?window.colorNotebook.notebookWheels:window.colorNotebook.playgroundWheels,s=[],e?y=!0:v=!0,l=o(a);try{for(l.s();!(c=l.n()).done;)(u=c.value).endsWith(".whl")?s.push(n+u):s.push(u)}catch(t){l.e(t)}finally{l.f()}return t.next=14,i.loadPackage(s);case 14:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),A=function(t,e,n){var o=null==e?"Loading...":e,r=n?"loading relative":"loading",i=document.createElement("template");i.innerHTML='<div class="'.concat(r,'"><div class="loader"></div><div>').concat(o,"</div></div>"),t.appendChild(i.content.firstChild)},S=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 i=r.substr(n,o-n).split("\n"),a=0;a<i.length;a++)a===i.length-1&&0===i[a].length||(t.shiftKey?i[a]=i[a].replace(m,""):i[a]="    ".concat(i[a]));i=i.join("\n"),e.value=r.substr(0,n)+i+r.substr(o),e.selectionStart=n,e.selectionEnd=n+i.length}}},B=function(){var t=n(r().mark((function t(e){var o,i,d;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:o=document.getElementById("__notebook-source"),i=document.querySelectorAll(".playground"),o&&e&&((d=document.getElementById("__notebook-input")).addEventListener("input",(function(t){x(t.target)})),d.addEventListener("keydown",C),document.getElementById("__notebook-edit").addEventListener("click",(function(){c[d.id]=d.value,document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),document.getElementById("__notebook-input").setAttribute("style",""),x(document.getElementById("__notebook-input"))})),document.getElementById("__notebook-md-gist").addEventListener("click",function(){var t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(n=prompt("Please enter link to the Markdown page source:",l))&&(n=b(n),e.preventDefault(),history.pushState({notebook:n},"","?".concat(new URLSearchParams("notebook=".concat(n)).toString())),I(!1));case 2:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),document.getElementById("__notebook-py-gist").addEventListener("click",function(){var t=n(r().mark((function t(e){var n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:null!==(n=prompt("Please enter the link to the Python code source:",l))&&(n=b(n),e.preventDefault(),history.pushState({source:n},"","?".concat(new URLSearchParams("source=".concat(n)).toString())),I(!1));case 2:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}()),document.getElementById("__notebook-input").value=s,document.getElementById("__notebook-cancel").addEventListener("click",(function(){d.value=c[d.id],delete c[d.id],document.getElementById("__notebook-render").classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden")})),document.getElementById("__notebook-submit").addEventListener("click",n(r().mark((function t(){var e,n;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return e=document.getElementById("__notebook-render"),s=document.getElementById("__notebook-input").value,e.classList.toggle("hidden"),document.getElementById("__notebook-source").classList.toggle("hidden"),n=document.querySelector("article"),A(n,"Loading Notebook..."),e.innerHTML="",c={},t.next=10,L(!0);case 10:return t.next=12,k(s);case 12:return t.next=14,B();case 14:S(n),w();case 16:case"end":return t.stop()}}),t)}))))),i.forEach((function(t){var e=t.id.replace(u,"$1"),o=document.getElementById("__playground-inputs_".concat(e)),i=document.getElementById("__playground-results_".concat(e)),s=document.getElementById("__playground-code_".concat(e)),l=document.querySelector("button#__playground-edit_".concat(e)),d=document.querySelector("button#__playground-share_".concat(e)),p=document.querySelector("button#__playground-run_".concat(e)),f=document.querySelector("button#__playground-cancel_".concat(e));o.addEventListener("input",(function(){x(o)})),o.addEventListener("keydown",C),o.addEventListener("touchmove",(function(t){t.stopPropagation()})),i.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)}}}}})),l.addEventListener("click",n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:c[e]=o.value,s.classList.toggle("hidden"),i.classList.toggle("hidden"),p.classList.toggle("hidden"),f.classList.toggle("hidden"),l.classList.toggle("hidden"),d.classList.toggle("hidden"),x(o),o.focus();case 9:case"end":return t.stop()}}),t)})))),d.addEventListener("click",n(r().mark((function t(){var e,i,a,s,l;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:e=window.location.pathname.split("/")[1],i=b(o.value),a=window.location,s="/playground/",a.pathname.startsWith("/".concat(e,"/"))&&(s="/".concat(e,"/playground/")),(l="".concat(a.protocol,"//").concat(a.host).concat(s,"?code=").concat(i)).length>2e3?alert("Code must be small enough to generate a shareable URL under 2000 characters!"):navigator.clipboard.writeText(l).then(n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Link copied to clipboard :)");case 1:case"end":return t.stop()}}),t)}))),n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:alert("Failed to copy link clipboard!");case 1:case"end":return t.stop()}}),t)}))));case 7:case"end":return t.stop()}}),t)})))),p.addEventListener("click",n(r().mark((function t(){var n,o;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(!a){t.next=2;break}return t.abrupt("return");case 2:return a=!0,n=s.querySelector("form"),A(n,null,!0),(o=document.querySelectorAll(".playground .playground-run"))&&o.forEach((function(t){t.setAttribute("disabled","")})),t.next=9,L(!1);case 9:return i.querySelector("code").innerHTML="",t.next=12,E(e);case 12:o&&o.forEach((function(t){t.removeAttribute("disabled")})),S(n),s.classList.toggle("hidden"),i.classList.toggle("hidden"),l.classList.toggle("hidden"),d.classList.toggle("hidden"),p.classList.toggle("hidden"),f.classList.toggle("hidden"),delete c[e],a=!1;case 22:case"end":return t.stop()}}),t)})))),f.addEventListener("click",(function(){o.value=c[e],delete c[e],s.classList.toggle("hidden"),i.classList.toggle("hidden"),l.classList.toggle("hidden"),d.classList.toggle("hidden"),p.classList.toggle("hidden"),f.classList.toggle("hidden")}))}));case 4:case"end":return t.stop()}}),t)})));return function(e){return t.apply(this,arguments)}}(),I=function(){var t=n(r().mark((function t(e,o){var i,a,s,u,d,f,m,_,y;return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:if(c={},!window.location.pathname.endsWith("/playground/")){t.next=32;break}if(i=o||new URLSearchParams(window.location.search),a="Loading Pyodide...",s="Loading Notebook...",u=i.has("source")?i.get("source"):i.get("notebook"),d=document.querySelector("article"),null===u||!u.trim()){t.next=16;break}return A(d,a),t.next=11,L(!0);case 11:S(d),A(d,s);try{f=i.has("source")?"source":"notebook",p=decodeURIComponent(i.toString()),m="",_=new XMLHttpRequest,l=u,_.open("GET",u,!0),_.onload=n(r().mark((function t(){return r().wrap((function(t){for(;;)switch(t.prev=t.next){case 0:return 4===_.readyState&&200===_.status&&(m=_.responseText),"source"===f&&(m=h(m)),t.next=4,k(m);case 4:return t.next=6,B(e);case 6:S(d),w();case 8:case"end":return t.stop()}}),t)}))),_.send()}catch(t){}t.next=30;break;case 16:return l="",y=h(i.has("code")?i.get("code"):g),p=decodeURIComponent(i.toString()),A(d,a),t.next=22,L(!0);case 22:return S(d),A(d,s),t.next=26,k(y);case 26:return t.next=28,B(e);case 28:S(d),w();case 30:t.next=35;break;case 32:l="",p="",B(e);case 35:case"end":return t.stop()}}),t)})));return function(e,n){return t.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-lX1Ayavv.js.map
diff --git a/docs/theme/playground-config-4f0f586c.js b/docs/theme/playground-config-152e791e.js
similarity index 76%
rename from docs/theme/playground-config-4f0f586c.js
rename to docs/theme/playground-config-152e791e.js
index b519c484..7bfd2457 100644
--- a/docs/theme/playground-config-4f0f586c.js
+++ b/docs/theme/playground-config-152e791e.js
@@ -1,5 +1,5 @@
 var colorNotebook = {
-    "playgroundWheels": ['pygments-2.17.2-py3-none-any.whl', 'coloraide-4.0.1-py3-none-any.whl'],
-    "notebookWheels": ['pyyaml', 'Markdown-3.6-py3-none-any.whl', 'pymdown_extensions-10.10.1-py3-none-any.whl', 'pygments-2.17.2-py3-none-any.whl', 'coloraide-4.0.1-py3-none-any.whl'],
+    "playgroundWheels": ['pygments-2.17.2-py3-none-any.whl', 'coloraide-4.1-py3-none-any.whl'],
+    "notebookWheels": ['pyyaml', 'Markdown-3.6-py3-none-any.whl', 'pymdown_extensions-10.10.1-py3-none-any.whl', 'pygments-2.17.2-py3-none-any.whl', 'coloraide-4.1-py3-none-any.whl'],
     "defaultPlayground": "import coloraide\ncoloraide.__version__\nColor('red')"
 }
diff --git a/mkdocs.yml b/mkdocs.yml
index 1e6734a8..adaddb11 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -309,9 +309,9 @@ extra_css:
   - assets/coloraide-extras/extra-696a2734c9.css
 extra_javascript:
   - https://unpkg.com/mermaid@10.6.1/dist/mermaid.min.js
-  - playground-config-4f0f586c.js
+  - playground-config-152e791e.js
   - https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js
-  - assets/coloraide-extras/extra-notebook-BvWUnGuN.js
+  - assets/coloraide-extras/extra-notebook-lX1Ayavv.js
 
 extra:
   social:
diff --git a/tools/average_img.py b/tools/average_img.py
index 84b0d3b8..bfeeee99 100644
--- a/tools/average_img.py
+++ b/tools/average_img.py
@@ -5,6 +5,7 @@ import time
 import argparse
 import sys
 import os
+import json
 
 # We want to load ColorAide from the working directory to pick up the version under development
 sys.path.insert(0, os.getcwd())
@@ -51,11 +52,15 @@ def get_color(space, p):
     return Color('srgb', [x / 255 for x in p[:3]], p[3] / 255 if len(p) > 3 else 1).convert(space, in_place=True)
 
 
-def iter_image(img, space):
+def iter_image(img, space, no_resize):
     """Process the image applying the requested filter."""
 
     with Image.open(img) as im:
-        if im.size[0] > 500 or im.size[1] > 500:
+        if im.format == 'PNG':
+            if im.mode not in ('RGBA',):
+                im = im.convert('RGBA')
+
+        if not no_resize and (im.size[0] > 500 or im.size[1] > 500):
             factor = 500 / max(im.size)
             new_im = im.resize((max(1, int(im.size[0] * factor)), max(1, int(im.size[1] * factor))))
         else:
@@ -84,16 +89,20 @@ def main():
     parser.add_argument('--space', '-s', default='srgb', help='Color space to average in.')
     parser.add_argument('--out-space', '-o', default='srgb', help='Color space to average in.')
     parser.add_argument('--premultiplied', '-p', action='store_true', help="Premultiply values.")
-    parser.add_argument('--powerless', '-P', action='store_true', help="Treat achromatic hues as powerless.")
+    parser.add_argument('--no-resize', '-r', action='store_true', help="Disable resizing of image.")
+    parser.add_argument('--gamut-map', '-g', default="clip", help="Specify GMA method to use (default is clip).")
+    parser.add_argument('--gamut-options', '-G', default="{}", help="Define gamut mapping options.")
     args = parser.parse_args()
 
+    gmap = {'method': args.gamut_map}
+    gmap.update(json.loads(args.gamut_options))
+
     print(
         Color.average(
-            iter_image(args.input, args.space),
+            iter_image(args.input, args.space, args.no_resize),
             space=args.space,
             premultiplied=args.premultiplied,
-            powerless=args.powerless
-        ).convert(args.out_space).to_string()
+        ).convert(args.out_space).to_string(fit=gmap)
     )
 
     return 0


Test patch:
diff --git a/tests/test_average.py b/tests/test_average.py
index 311e1b86..b23ab9d7 100644
--- a/tests/test_average.py
+++ b/tests/test_average.py
@@ -11,13 +11,9 @@ class TestAverage(util.ColorAsserts, unittest.TestCase):
     def test_average_achromatic(self):
         """Test that we force achromatic hues to undefined."""
 
-        self.assertEqual(
-            Color.average(['hsl(30 0 100)', 'color(srgb 0 0 1)'], space='hsl', powerless=True).to_string(),
-            'hsl(240 50% 75%)'
-        )
         self.assertEqual(
             Color.average(['hsl(30 0 100)', 'color(srgb 0 0 1)'], space='hsl').to_string(),
-            'hsl(315 50% 75%)'
+            'hsl(240 50% 75%)'
         )
 
     def test_no_colors(self):
@@ -58,7 +54,7 @@ class TestAverage(util.ColorAsserts, unittest.TestCase):
             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.19608 0.5 / 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)',
@@ -75,10 +71,10 @@ class TestAverage(util.ColorAsserts, unittest.TestCase):
             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 180 1 0.34804 / 0.66667)',
+             'color(--hsl 169.11 1 0.33725 / 0.75)',
+             'color(--hsl 160.89 1 0.32863 / 0.83333)',
+             'color(--hsl 154.72 1 0.32157 / 0.91667)',
              'color(--hsl 150 1 0.31569)']
         )
 
@@ -92,7 +88,7 @@ class TestAverage(util.ColorAsserts, unittest.TestCase):
             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 180 1 0.34804 / 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)',
@@ -116,12 +112,48 @@ class TestAverage(util.ColorAsserts, unittest.TestCase):
              'color(srgb 0 0.19608 0.33333)']
         )
 
+    def test_average_with_undefined_alpha_result(self):
+        """Test average when the resulting alpha is undefined."""
+
+        colors = [
+            Color('color(srgb 1 1 0 / none)'),
+            Color('color(srgb 0 0.50196 0 / none)'),
+            Color('color(srgb 0 0 1 / none)')
+        ]
+        self.assertEqual(
+            Color.average(colors, space='srgb').to_string(color=True, none=True),
+            'color(srgb 0.33333 0.50065 0.33333 / none)'
+        )
+
     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)')
 
+    def test_evenly_distributed(self):
+        """Test evenly distributed colors."""
+
+        colors = ['red', 'green', 'blue']
+        self.assertEqual(
+            Color.average(colors, space='hsl').to_string(color=True, none=True),
+            'color(--hsl none 0 0.41699)'
+        )
+
+    def test_hwb_handling(self):
+        """Test HWB handling."""
+
+        colors = ['red', 'green', 'blue']
+        self.assertEqual(
+            Color.average(colors, space='hwb').to_string(color=True, none=True),
+            'color(--hwb none 0.83399 0.16601)'
+        )
+
+        self.assertEqual(
+            Color.average(['orange', 'purple', 'darkgreen'], space='hwb').to_string(color=True),
+            'color(--hwb 38.824 0 0.36863)'
+        )
+
     def test_all_undefined_hue(self):
         """Test all hues undefined."""