Repository: facelessuser/coloraide (language: python)

Issue:
Continuous hue handling can miscalculate hue fixups
Continuous hue handling (which is also used in spline interpolation) can sometimes fixup hues improperly. This seems to be caused by improperly applying a hue offset to the first hue (which is already offset) increasing the hue disparity during the fixup calculations.


Discussion / hints:

Fix patch:
diff --git a/coloraide/__meta__.py b/coloraide/__meta__.py
index e2f5550c..8158913b 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, 0, "final")
+__version_info__ = Version(4, 0, 1, "final")
 __version__ = __version_info__._get_canonical()
diff --git a/coloraide/color.py b/coloraide/color.py
index b9e18dbb..bdf24294 100644
--- a/coloraide/color.py
+++ b/coloraide/color.py
@@ -386,7 +386,7 @@ def register(
                     cls._get_convert_chain.cache_clear()
                 raise TypeError(f"Cannot register plugin of type '{type(i)}'")
 
-            if p.NAME != "*" and p.NAME not in mapping or overwrite:
+            if p.NAME != "*" and (p.NAME not in mapping or overwrite):
                 mapping[p.NAME] = p
             elif not silent:
                 if reset_convert_cache:  # pragma: no cover
diff --git a/coloraide/interpolate/continuous.py b/coloraide/interpolate/continuous.py
index 091b54d3..4caf7b8f 100644
--- a/coloraide/interpolate/continuous.py
+++ b/coloraide/interpolate/continuous.py
@@ -90,7 +90,7 @@ def normalize_hue(
         else:
             raise ValueError(f"Unknown hue adjuster '{hue}'")
 
-        c1 = color1[index] + offset
+        c1 = color1[index]
         c2 = (color2[index] % 360) + offset
 
         # Adjust hue, handle gaps across `NaN`s
@@ -156,7 +156,8 @@ def handle_undefined(self) -> None:
                 # Two good values, store the last good value and continue
                 if not a_nan and not b_nan:
                     if self.premultiplied and i == alpha:
-                        self.premultiply(c1)
+                        if x == 1:
+                            self.premultiply(c1)
                         self.premultiply(c2)
                     last = b
                     continue
diff --git a/docs/src/markdown/about/changelog.md b/docs/src/markdown/about/changelog.md
index 2dcf3667..8958ffe0 100644
--- a/docs/src/markdown/about/changelog.md
+++ b/docs/src/markdown/about/changelog.md
@@ -1,5 +1,12 @@
 # Changelog
 
+## 4.0.1
+
+-   **FIX**: Fix issue with `continuous` interpolation (and any that are derived from it, e.g., cubic spline
+    interpolations) that can cause bad hue fixup calculations.
+-   **FIX**: Fix issue with `continuous` interpolation (and any that are derived from it, e.g., cubic spline
+    interpolations) that can cause premultiplication to be applied to a color twice.
+
 ## 4.0
 
 -   **NEW**: Officially support Python 3.13.
diff --git a/docs/src/markdown/demos/3d_models.html b/docs/src/markdown/demos/3d_models.html
index f2cc2735..ea0991ee 100644
--- a/docs/src/markdown/demos/3d_models.html
+++ b/docs/src/markdown/demos/3d_models.html
@@ -905,7 +905,7 @@ <h1>ColorAide Color Space Models</h1>
 let colorSpaces = null
 let colorGamuts = null
 let lastModel = null
-let package = 'coloraide-4.0-py3-none-any.whl'
+let package = 'coloraide-4.0.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 9e6ee072..ae7bf104 100644
--- a/docs/src/markdown/demos/colorpicker.html
+++ b/docs/src/markdown/demos/colorpicker.html
@@ -421,7 +421,7 @@ <h1>ColorAide Color Picker</h1>
     let pyodide = null
     let webspace = ''
     let initial = 'oklab(0.69 0.13 -0.1 / 0.85)'
-    let package = 'coloraide-4.0-py3-none-any.whl'
+    let package = 'coloraide-4.0.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 f9831ee0..a9ab22ab 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-70f29cae.js
+  - playground-config-4f0f586c.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-DQWpIrCE.js b/docs/theme/assets/coloraide-extras/extra-notebook-DQWpIrCE.js
deleted file mode 100644
index cbf57b7a..00000000
--- a/docs/theme/assets/coloraide-extras/extra-notebook-DQWpIrCE.js
+++ /dev/null
@@ -1,2 +0,0 @@
-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;end=node.end_lineno;stmt=lines[start-1:end];command=''\n\t\tfor (i,line) in enumerate(stmt,0):\n\t\t\tif i==0:stmt[i]='>>> '+line\n\t\t\telse:stmt[i]='... '+line\n\t\tcommand+=A.join(stmt)\n\t\tif isinstance(node,AST_BLOCKS):command+='\\n... '\n\t\ttry:\n\t\t\twith StreamOut()as s:\n\t\t\t\tfor x in evaluate(node,g):\n\t\t\t\t\tresult.append(x);text=s.read()\n\t\t\t\t\tif text:result.append(AtomicString(text))\n\t\t\t\tconsole+=command\n\t\texcept Exception as e:\n\t\t\tif no_except:\n\t\t\t\tif not inline:from pymdownx.superfences import SuperFencesException;raise SuperFencesException from e\n\t\t\t\telse:from pymdownx.inlinehilite import InlineHiliteException;raise InlineHiliteException from e\n\t\t\timport traceback;console+=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.0: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.0:stops[-1]+=B;stops.append(color.convert(gamut).to_string(hex=_B)+B)\n\t\tif not stops:stops.extend([_M]*2)\n\t\tif len(stops)==1:stops.append(stops[0])\n\t\tEtree.SubElement(sub_el,A,{_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-DQWpIrCE.js.map
diff --git a/docs/theme/assets/coloraide-extras/extra-notebook-UmZ-G8NV.js b/docs/theme/assets/coloraide-extras/extra-notebook-UmZ-G8NV.js
new file mode 100644
index 00000000..1d8346fd
--- /dev/null
+++ b/docs/theme/assets/coloraide-extras/extra-notebook-UmZ-G8NV.js
@@ -0,0 +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;end=node.end_lineno;stmt=lines[start-1:end];command=''\n\t\tfor(i,line)in enumerate(stmt,0):\n\t\t\tif i==0:stmt[i]='>>> '+line\n\t\t\telse:stmt[i]='... '+line\n\t\tcommand+=A.join(stmt)\n\t\tif isinstance(node,AST_BLOCKS):command+='\\n... '\n\t\ttry:\n\t\t\twith StreamOut()as s:\n\t\t\t\tfor x in evaluate(node,g):\n\t\t\t\t\tresult.append(x);text=s.read()\n\t\t\t\t\tif text:result.append(AtomicString(text))\n\t\t\t\tconsole+=command\n\t\texcept Exception as e:\n\t\t\tif no_except:\n\t\t\t\tif not inline:from pymdownx.superfences import SuperFencesException;raise SuperFencesException from e\n\t\t\t\telse:from pymdownx.inlinehilite import InlineHiliteException;raise InlineHiliteException from e\n\t\t\timport traceback;console+=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-UmZ-G8NV.js.map
diff --git a/docs/theme/assets/coloraide-extras/extra-notebook-DQWpIrCE.js.map b/docs/theme/assets/coloraide-extras/extra-notebook-UmZ-G8NV.js.map
similarity index 99%
rename from docs/theme/assets/coloraide-extras/extra-notebook-DQWpIrCE.js.map
rename to docs/theme/assets/coloraide-extras/extra-notebook-UmZ-G8NV.js.map
index 5ecfd74a..97eeeec9 100644
--- a/docs/theme/assets/coloraide-extras/extra-notebook-DQWpIrCE.js.map
+++ b/docs/theme/assets/coloraide-extras/extra-notebook-UmZ-G8NV.js.map
@@ -1,1 +1,1 @@
-{"version":3,"file":"extra-notebook-DQWpIrCE.js","sources":["extra-notebook.js"],"sourcesContent":["(() => {\n  let webspace = ''\n  try {\n    let gamut = 'srgb'\n    if (window.matchMedia(\"(color-gamut: rec2020)\").matches) {\n      gamut = 'rec2020'\n    } else if (window.matchMedia(\"(color-gamut: p3)\").matches) {\n      gamut = 'display-p3'\n    }\n    webspace = (CSS.supports('color: color(display-p3 1 0 0)')) ? gamut : 'srgb'\n  } catch {\n    webspace = 'srgb'\n  }\n  let pyodide = null\n  let busy = false\n  let raw = \"\"\n  let gist = \"\"\n  let editTemp = {}\n  const reIdNum = /.*?_(\\d+)$/\n  let initialized = false\n  let lastSearch = \"\"\n  let fake = false\n  const tabStart = /^( {1,4}|\\t)/\n  // This is the Python payload that will be executed when the user\n  // presses the `Run` button. It will execute the code, create a\n  // Python console output, find color references, steps, and interpolation\n  // references and render the appropriate preview.\n  const pycode = `\n{{pycode}}\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback(gamut='${webspace}')\n`\n\n  const defContent = window.colorNotebook.defaultPlayground\n\n  const getContent = content => {\n    return `\n/// new | This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). \\\nLearn more [here](\\\n?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md\\\n). Preview, convert, interpolate, and explore!\n///\n\n\\`\\`\\`\\`\\`\\`\\`\\`py play\n${content}\n\\`\\`\\`\\`\\`\\`\\`\\`\n`\n  }\n\n  let notebookInstalled = false\n  let playgroundInstalled = false\n\n  const fakeDOMContentLoaded = () => {\n    // Send a fake `DOMContentLoaded`\n    fake = true\n    window.document.dispatchEvent(new Event(\"DOMContentLoaded\", {\n      bubbles: true,\n      cancelable: true\n    }))\n    window.document$.next()\n  }\n\n  const textResize = inpt => {\n    // Resize inputs based on text height.\n\n    const scrollLeft = window.pageXOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollLeft\n\n    const scrollTop  = window.pageYOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollTop\n\n    inpt.style.height = \"5px\"\n    inpt.style.height = `${Math.min(inpt.scrollHeight, 408)}px`\n\n    window.scrollTo(scrollLeft, scrollTop)\n  }\n\n  const encodeuri = uri => {\n    // Encode the URI component.\n\n    return encodeURIComponent(uri).replace(/[.!'()*]/g, c => {\n      return `%${c.charCodeAt(0).toString(16)}`\n    })\n  }\n\n  const pyexecute = async currentID => {\n    // Execute Python code inside a playground\n\n    const currentInputs = document.getElementById(`__playground-inputs_${currentID}`)\n    currentInputs.setAttribute(\"readonly\", \"\")\n    pyodide.globals.set(\"id_num\", currentID)\n    pyodide.globals.set(\"action\", \"playground\")\n    await pyodide.runPythonAsync(pycode)\n    currentInputs.removeAttribute(\"readonly\")\n  }\n\n  const pyrender = async text => {\n    // Render an entire notebook page\n\n    pyodide.globals.set(\"content\", text)\n    pyodide.globals.set(\"action\", \"notebook\")\n    await pyodide.runPythonAsync(pycode)\n    const src = document.getElementById(\"__notebook-input\")\n    if (src) {\n      raw = text\n      src.value = text\n    }\n    if (window.location.hash) {\n      // Force jumping to hashes\n      window.location.href = window.location.href // eslint-disable-line no-self-assign\n    }\n  }\n\n  const setupPyodide = async full => {\n    // Load `Pyodide` and the any default packages we can need and can load.\n\n    if (!initialized) {\n      initialized = true\n      pyodide = await loadPyodide({ // eslint-disable-line no-undef\n        indexURL: \"https://cdn.jsdelivr.net/pyodide/v0.26.2/full/\",\n        fullStdLib: false\n      })\n    }\n\n    if ((!notebookInstalled && full) || (!playgroundInstalled && !full)) {\n      const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`\n      const packages = (full) ? window.colorNotebook.notebookWheels : window.colorNotebook.playgroundWheels\n      const installs = []\n      if (full) {\n        notebookInstalled = true\n      } else {\n        playgroundInstalled = true\n      }\n      for (const s of packages) {\n        if (s.endsWith('.whl')) {\n          installs.push(base + s)\n        } else {\n          installs.push(s)\n        }\n      }\n      await pyodide.loadPackage(installs)\n    }\n  }\n\n  const showBusy = (target, label, relative) => {\n    // Show busy indicator\n\n    const loaderLabel = (typeof label === \"undefined\" || label === null) ? \"Loading...\" : label\n    const classes = relative ? \"loading relative\" : \"loading\"\n    const template = document.createElement(\"template\")\n    template.innerHTML = `<div class=\"${classes}\"><div class=\"loader\"></div><div>${loaderLabel}</div></div>`\n    target.appendChild(template.content.firstChild)\n  }\n\n  const hideBusy = target => {\n    // Hide busy indicator\n\n    const loading = target.querySelector(\".loading\")\n    if (loading) {\n      target.removeChild(target.querySelector(\".loading\"))\n    }\n  }\n\n  const popState = () => {\n    // Handle notebook history\n\n    const base = window.location.pathname.split('/')[1]\n    if (\n      window.location.pathname === `/${base}/playground/`\n    ) {\n      const current = decodeURIComponent(new URLSearchParams(window.location.search).toString())\n      if (current !== lastSearch) {\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const interceptClickEvent = e => {\n    // Catch links to other notebook pages and handle them\n\n    const base = window.location.pathname.split('/')[1]\n    const target = e.target || e.srcElement\n\n    if (target.tagName === \"A\" && main) { // eslint-disable-line no-use-before-define\n      if (\n        target.getAttribute(\"href\") &&\n        target.host === window.location.host &&\n        window.location.pathname === `/${base}/playground/` &&\n        window.location.pathname === target.pathname &&\n        window.location.search !== target.search\n      ) {\n        e.preventDefault()\n        const search = new URLSearchParams(target.search)\n        main(false, search) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const handleTab = e => {\n    // Prevent tab from tabbing out.\n\n    if (e.key === 'Tab') {\n      const target = e.target\n\n      if (target.selectionStart !== target.selectionEnd) {\n        e.preventDefault()\n\n        let start = target.selectionStart\n        let end = target.selectionEnd\n\n        const text = target.value\n\n        while (start > 0 && text[start - 1] !== '\\n') {\n          start--\n        }\n        while (end > 0 && text[end - 1] !== '\\n' && end < text.length) {\n          end++\n        }\n\n        let lines = text.substr(start, end - start).split('\\n')\n\n        for (let i = 0; i < lines.length; i++) {\n\n          // Don't indent last line if cursor at start of line\n          if (i === lines.length - 1 && lines[i].length === 0) {\n            continue\n          }\n\n          // Indent or deindent\n          if (e.shiftKey) {\n            lines[i] = lines[i].replace(tabStart, '')\n          } else {\n            lines[i] = `    ${lines[i]}`\n          }\n        }\n        lines = lines.join('\\n')\n\n        // Update the text area\n        target.value = text.substr(0, start) + lines + text.substr(end)\n        target.selectionStart = start\n        target.selectionEnd = start + lines.length\n      }\n    }\n  }\n\n  const init = async first => {\n    // Setup input highlighting and events to run Python code blocks.\n\n    const notebook = document.getElementById(\"__notebook-source\")\n    const playgrounds = document.querySelectorAll(\".playground\")\n\n    if (notebook && first) {\n      const notebookInput = document.getElementById(\"__notebook-input\")\n\n      notebookInput.addEventListener(\"input\", e => {\n        // Adjust textarea height on text input.\n\n        textResize(e.target)\n      })\n\n      notebookInput.addEventListener('keydown', handleTab)\n\n      const editPage = document.getElementById(\"__notebook-edit\")\n      editPage.addEventListener(\"click\", () => {\n        editTemp[notebookInput.id] = notebookInput.value\n        document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n        document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        // Reset height\n        const inpt = document.getElementById(\"__notebook-input\")\n        inpt.setAttribute('style', '')\n        textResize(document.getElementById(\"__notebook-input\"))\n      })\n\n      document.getElementById(\"__notebook-md-gist\").addEventListener(\"click\", async e => {\n        let uri = prompt(\"Please enter link to the Markdown page source:\", gist) // eslint-disable-line no-alert\n        if (uri !== null) {\n          uri = encodeuri(uri)\n          e.preventDefault()\n          history.pushState({notebook: uri}, \"\", `?${new URLSearchParams(`notebook=${uri}`).toString()}`)\n          main(false) // eslint-disable-line no-use-before-define\n        }\n      })\n\n      document.getElementById(\"__notebook-py-gist\").addEventListener(\"click\", async e => {\n        let uri = prompt(\"Please enter the link to the Python code source:\", gist) // eslint-disable-line no-alert\n        if (uri !== null) {\n          uri = encodeuri(uri)\n          e.preventDefault()\n          history.pushState({source: uri}, \"\", `?${new URLSearchParams(`source=${uri}`).toString()}`)\n          main(false) // eslint-disable-line no-use-before-define\n        }\n      })\n\n      document.getElementById(\"__notebook-input\").value = raw\n      document.getElementById(\"__notebook-cancel\").addEventListener(\"click\", () => {\n        notebookInput.value = editTemp[notebookInput.id]\n        delete editTemp[notebookInput.id]\n        document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n        document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n      })\n\n      document.getElementById(\"__notebook-submit\").addEventListener(\"click\", async() => {\n        const render = document.getElementById(\"__notebook-render\")\n        raw = document.getElementById(\"__notebook-input\").value\n        render.classList.toggle(\"hidden\")\n        document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        const article = document.querySelector(\"article\")\n        showBusy(article, \"Loading Notebook...\")\n        render.innerHTML = \"\"\n        editTemp = {}\n        await setupPyodide(true)\n        await pyrender(raw)\n        await init()\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      })\n    }\n\n    playgrounds.forEach(pg => {\n\n      const currentID = pg.id.replace(reIdNum, \"$1\")\n      const inputs = document.getElementById(`__playground-inputs_${currentID}`)\n      const results = document.getElementById(`__playground-results_${currentID}`)\n      const pgcode = document.getElementById(`__playground-code_${currentID}`)\n      const buttonEdit = document.querySelector(`button#__playground-edit_${currentID}`)\n      const buttonShare = document.querySelector(`button#__playground-share_${currentID}`)\n      const buttonRun = document.querySelector(`button#__playground-run_${currentID}`)\n      const buttonCancel = document.querySelector(`button#__playground-cancel_${currentID}`)\n\n      inputs.addEventListener(\"input\", () => {\n        // Adjust textarea height on text input.\n\n        textResize(inputs)\n      })\n\n      inputs.addEventListener('keydown', handleTab)\n\n      inputs.addEventListener(\"touchmove\", e => {\n        // Stop propagation on \"touchmove\".\n\n        e.stopPropagation()\n      })\n\n      results.addEventListener(\"click\", e => {\n        // Handle clicks on results and copies color from single color swatch when clicked.\n\n        const el = e.target\n        if (el.matches('span.swatch-color')) {\n          let content = ''\n          const parent = el.parentNode\n          if (!parent.matches('span.swatch-gradient')) {\n            content = parent.getAttribute('title').replace('Copy to clipboard', '')\n            content = content.replace('\\n', '')\n            if (window.clipboardData && window.clipboardData.setData) {\n              // Old `IE`` handling, do we really need this?\n              return window.clipboardData.setData(\"Text\", content)\n            } else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n              const textarea = document.createElement(\"textarea\")\n              textarea.textContent = content\n              textarea.style.position = \"fixed\"\n              document.body.appendChild(textarea)\n              textarea.select()\n              try {\n                return document.execCommand(\"copy\")\n              } catch (ex) {\n                return prompt(\"Copy to clipboard: Ctrl+C, Enter\", content) // eslint-disable-line no-alert\n              } finally {\n                document.body.removeChild(textarea)\n              }\n            }\n          }\n        }\n      })\n\n      buttonEdit.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        editTemp[currentID] = inputs.value\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        textResize(inputs)\n        inputs.focus()\n      })\n\n      buttonShare.addEventListener(\"click\", async() => {\n        // Handle the share click: copy URL with code as parameter.\n\n        const base = window.location.pathname.split('/')[1]\n        const uri = encodeuri(inputs.value)\n        const loc = window.location\n        let pathname = \"/playground/\"\n        if (loc.pathname.startsWith(`/${base}/`)) {\n          pathname = `/${base}/playground/`\n        }\n        const path = `${loc.protocol}//${loc.host}${pathname}?code=${uri}`\n        if (path.length > 2000) {\n          alert( // eslint-disable-line no-alert\n            \"Code must be small enough to generate a shareable URL under 2000 characters!\"\n          )\n        } else {\n          navigator.clipboard.writeText(path).then(async() => {\n            alert(\"Link copied to clipboard :)\") // eslint-disable-line no-alert\n          }, async() => {\n            alert(\"Failed to copy link clipboard!\") // eslint-disable-line no-alert\n          })\n        }\n      })\n\n      buttonRun.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        if (busy) {\n          return\n        }\n\n        busy = true\n        // Load Pyodide and related packages.\n        const form = pgcode.querySelector(\"form\")\n        showBusy(form, null, true)\n        const buttons = document.querySelectorAll(\".playground .playground-run\")\n        if (buttons) {\n          buttons.forEach(b => {\n            b.setAttribute(\"disabled\", \"\")\n          })\n        }\n        await setupPyodide(false)\n        results.querySelector(\"code\").innerHTML = \"\"\n        await pyexecute(currentID)\n        if (buttons) {\n          buttons.forEach(b => {\n            b.removeAttribute(\"disabled\")\n          })\n        }\n        hideBusy(form)\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n\n        delete editTemp[currentID]\n        busy = false\n      })\n\n      buttonCancel.addEventListener(\"click\", () => {\n        // Cancel edit.\n\n        inputs.value = editTemp[currentID]\n        delete editTemp[currentID]\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n      })\n    })\n  }\n\n  const main = async(first, search) => {\n    // Load external source to render in a playground.\n    // This can be something like a file on a gist we must read in (?source=)\n    // or raw code (?code=).\n\n    editTemp = {}\n\n    if (window.location.pathname.endsWith(\"/playground/\")) {\n      const params = search || new URLSearchParams(window.location.search)\n      const loadMsg = \"Loading Pyodide...\"\n      const pageMsg = \"Loading Notebook...\"\n      const uri = params.has(\"source\") ? params.get(\"source\") : params.get(\"notebook\")\n      const article = document.querySelector(\"article\")\n      if (uri !== null && uri.trim()) {\n        // A source was specified, so load it.\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        try {\n          const gistType = params.has(\"source\") ? \"source\" : \"notebook\"\n          lastSearch = decodeURIComponent(params.toString())\n          let value = \"\"\n          const xhr = new XMLHttpRequest()\n          gist = uri\n          xhr.open(\"GET\", uri, true)\n          xhr.onload = async() => {\n            // Try and load the requested content\n            if (xhr.readyState === 4) {\n              if (xhr.status === 200) {\n                value = xhr.responseText\n              }\n            }\n\n            if (gistType === \"source\") {\n              value = getContent(value)\n            }\n            await pyrender(value)\n            await init(first)\n            hideBusy(article)\n            fakeDOMContentLoaded()\n          }\n          xhr.send()\n        } catch (err) {} // eslint-disable-line no-empty\n      } else {\n        gist = \"\"\n        const content = getContent(params.has(\"code\") ? params.get(\"code\") : defContent)\n        lastSearch = decodeURIComponent(params.toString())\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        await pyrender(content)\n        await init(first)\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      }\n    } else {\n      gist = \"\"\n      lastSearch = \"\"\n      init(first)\n    }\n  }\n\n  // Capture links in notebook pages so that we can make playgound links load instantly\n  document.addEventListener(\"click\", interceptClickEvent, true)\n\n  // Handle history of notebook pages as they are loaded dynamically\n  window.addEventListener(\"popstate\", popState)\n\n  // Before leaving, turn off fake, just in case we navigated away before finished\n  window.addEventListener(\"unload\", () => {\n    fake = false\n  })\n\n  // Attach main via subscribe (subscribes to Materials on page load and instant page loads)\n  window.document$.subscribe(() => {\n    // To get other libraries to reload, we may create a fake `DOMContentLoaded`\n    // No need to process these events.\n    if (fake) {\n      fake = false\n      return\n    }\n    main(true)\n  })\n})()\n"],"names":["webspace","gamut","window","matchMedia","matches","CSS","supports","_unused","pyodide","busy","raw","gist","editTemp","reIdNum","initialized","lastSearch","fake","tabStart","pycode","concat","defContent","colorNotebook","defaultPlayground","getContent","content","notebookInstalled","playgroundInstalled","fakeDOMContentLoaded","document","dispatchEvent","Event","bubbles","cancelable","document$","next","textResize","inpt","scrollLeft","pageXOffset","documentElement","body","parentNode","scrollTop","pageYOffset","style","height","Math","min","scrollHeight","scrollTo","encodeuri","uri","encodeURIComponent","replace","c","charCodeAt","toString","pyexecute","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","currentID","currentInputs","wrap","_context","prev","getElementById","setAttribute","globals","set","runPythonAsync","removeAttribute","stop","_x","apply","this","arguments","pyrender","_ref2","_callee2","text","src","_context2","value","location","hash","href","_x2","setupPyodide","_ref3","_callee3","full","base","packages","installs","_iterator","_step","s","_context3","loadPyodide","indexURL","fullStdLib","sent","origin","pathname","split","notebookWheels","playgroundWheels","_createForOfIteratorHelper","n","done","endsWith","push","err","e","f","loadPackage","_x3","showBusy","target","label","relative","loaderLabel","classes","template","createElement","innerHTML","appendChild","firstChild","hideBusy","querySelector","removeChild","handleTab","key","selectionStart","selectionEnd","preventDefault","start","end","length","lines","substr","i","shiftKey","join","init","_ref4","_callee12","first","notebook","playgrounds","notebookInput","_context12","querySelectorAll","addEventListener","id","classList","toggle","_ref5","_callee4","_context4","prompt","history","pushState","URLSearchParams","main","_x5","_ref6","_callee5","_context5","source","_x6","_callee6","render","article","_context6","forEach","pg","inputs","results","pgcode","buttonEdit","buttonShare","buttonRun","buttonCancel","stopPropagation","el","parent","getAttribute","clipboardData","setData","queryCommandSupported","textarea","textContent","position","select","execCommand","ex","_callee7","_context7","focus","_callee10","loc","path","_context10","startsWith","protocol","host","alert","navigator","clipboard","writeText","then","_callee8","_context8","_callee9","_context9","_callee11","form","buttons","_context11","abrupt","b","_x4","_ref13","_callee14","search","params","loadMsg","pageMsg","gistType","xhr","_context14","has","get","trim","decodeURIComponent","XMLHttpRequest","open","onload","_callee13","_context13","readyState","status","responseText","send","_x7","_x8","srcElement","tagName","subscribe"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"extra-notebook-UmZ-G8NV.js","sources":["extra-notebook.js"],"sourcesContent":["(() => {\n  let webspace = ''\n  try {\n    let gamut = 'srgb'\n    if (window.matchMedia(\"(color-gamut: rec2020)\").matches) {\n      gamut = 'rec2020'\n    } else if (window.matchMedia(\"(color-gamut: p3)\").matches) {\n      gamut = 'display-p3'\n    }\n    webspace = (CSS.supports('color: color(display-p3 1 0 0)')) ? gamut : 'srgb'\n  } catch {\n    webspace = 'srgb'\n  }\n  let pyodide = null\n  let busy = false\n  let raw = \"\"\n  let gist = \"\"\n  let editTemp = {}\n  const reIdNum = /.*?_(\\d+)$/\n  let initialized = false\n  let lastSearch = \"\"\n  let fake = false\n  const tabStart = /^( {1,4}|\\t)/\n  // This is the Python payload that will be executed when the user\n  // presses the `Run` button. It will execute the code, create a\n  // Python console output, find color references, steps, and interpolation\n  // references and render the appropriate preview.\n  const pycode = `\n{{pycode}}\n\naction = globals().get('action')\nif action == 'notebook':\n    callback = render_notebook\nelse:\n    callback = render_console\n\ncallback(gamut='${webspace}')\n`\n\n  const defContent = window.colorNotebook.defaultPlayground\n\n  const getContent = content => {\n    return `\n/// new | This notebook is powered by [Pyodide](https://github.com/pyodide/pyodide). \\\nLearn more [here](\\\n?notebook=https://gist.githubusercontent.com/facelessuser/7c819668b5eb248ecb9ac608d91391cf/raw/playground.md\\\n). Preview, convert, interpolate, and explore!\n///\n\n\\`\\`\\`\\`\\`\\`\\`\\`py play\n${content}\n\\`\\`\\`\\`\\`\\`\\`\\`\n`\n  }\n\n  let notebookInstalled = false\n  let playgroundInstalled = false\n\n  const fakeDOMContentLoaded = () => {\n    // Send a fake `DOMContentLoaded`\n    fake = true\n    window.document.dispatchEvent(new Event(\"DOMContentLoaded\", {\n      bubbles: true,\n      cancelable: true\n    }))\n    window.document$.next()\n  }\n\n  const textResize = inpt => {\n    // Resize inputs based on text height.\n\n    const scrollLeft = window.pageXOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollLeft\n\n    const scrollTop  = window.pageYOffset ||\n      (document.documentElement || document.body.parentNode || document.body).scrollTop\n\n    inpt.style.height = \"5px\"\n    inpt.style.height = `${Math.min(inpt.scrollHeight, 408)}px`\n\n    window.scrollTo(scrollLeft, scrollTop)\n  }\n\n  const encodeuri = uri => {\n    // Encode the URI component.\n\n    return encodeURIComponent(uri).replace(/[.!'()*]/g, c => {\n      return `%${c.charCodeAt(0).toString(16)}`\n    })\n  }\n\n  const pyexecute = async currentID => {\n    // Execute Python code inside a playground\n\n    const currentInputs = document.getElementById(`__playground-inputs_${currentID}`)\n    currentInputs.setAttribute(\"readonly\", \"\")\n    pyodide.globals.set(\"id_num\", currentID)\n    pyodide.globals.set(\"action\", \"playground\")\n    await pyodide.runPythonAsync(pycode)\n    currentInputs.removeAttribute(\"readonly\")\n  }\n\n  const pyrender = async text => {\n    // Render an entire notebook page\n\n    pyodide.globals.set(\"content\", text)\n    pyodide.globals.set(\"action\", \"notebook\")\n    await pyodide.runPythonAsync(pycode)\n    const src = document.getElementById(\"__notebook-input\")\n    if (src) {\n      raw = text\n      src.value = text\n    }\n    if (window.location.hash) {\n      // Force jumping to hashes\n      window.location.href = window.location.href // eslint-disable-line no-self-assign\n    }\n  }\n\n  const setupPyodide = async full => {\n    // Load `Pyodide` and the any default packages we can need and can load.\n\n    if (!initialized) {\n      initialized = true\n      pyodide = await loadPyodide({ // eslint-disable-line no-undef\n        indexURL: \"https://cdn.jsdelivr.net/pyodide/v0.26.2/full/\",\n        fullStdLib: false\n      })\n    }\n\n    if ((!notebookInstalled && full) || (!playgroundInstalled && !full)) {\n      const base = `${window.location.origin}/${window.location.pathname.split('/')[1]}/playground/`\n      const packages = (full) ? window.colorNotebook.notebookWheels : window.colorNotebook.playgroundWheels\n      const installs = []\n      if (full) {\n        notebookInstalled = true\n      } else {\n        playgroundInstalled = true\n      }\n      for (const s of packages) {\n        if (s.endsWith('.whl')) {\n          installs.push(base + s)\n        } else {\n          installs.push(s)\n        }\n      }\n      await pyodide.loadPackage(installs)\n    }\n  }\n\n  const showBusy = (target, label, relative) => {\n    // Show busy indicator\n\n    const loaderLabel = (typeof label === \"undefined\" || label === null) ? \"Loading...\" : label\n    const classes = relative ? \"loading relative\" : \"loading\"\n    const template = document.createElement(\"template\")\n    template.innerHTML = `<div class=\"${classes}\"><div class=\"loader\"></div><div>${loaderLabel}</div></div>`\n    target.appendChild(template.content.firstChild)\n  }\n\n  const hideBusy = target => {\n    // Hide busy indicator\n\n    const loading = target.querySelector(\".loading\")\n    if (loading) {\n      target.removeChild(target.querySelector(\".loading\"))\n    }\n  }\n\n  const popState = () => {\n    // Handle notebook history\n\n    const base = window.location.pathname.split('/')[1]\n    if (\n      window.location.pathname === `/${base}/playground/`\n    ) {\n      const current = decodeURIComponent(new URLSearchParams(window.location.search).toString())\n      if (current !== lastSearch) {\n        main(false) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const interceptClickEvent = e => {\n    // Catch links to other notebook pages and handle them\n\n    const base = window.location.pathname.split('/')[1]\n    const target = e.target || e.srcElement\n\n    if (target.tagName === \"A\" && main) { // eslint-disable-line no-use-before-define\n      if (\n        target.getAttribute(\"href\") &&\n        target.host === window.location.host &&\n        window.location.pathname === `/${base}/playground/` &&\n        window.location.pathname === target.pathname &&\n        window.location.search !== target.search\n      ) {\n        e.preventDefault()\n        const search = new URLSearchParams(target.search)\n        main(false, search) // eslint-disable-line no-use-before-define\n      }\n    }\n  }\n\n  const handleTab = e => {\n    // Prevent tab from tabbing out.\n\n    if (e.key === 'Tab') {\n      const target = e.target\n\n      if (target.selectionStart !== target.selectionEnd) {\n        e.preventDefault()\n\n        let start = target.selectionStart\n        let end = target.selectionEnd\n\n        const text = target.value\n\n        while (start > 0 && text[start - 1] !== '\\n') {\n          start--\n        }\n        while (end > 0 && text[end - 1] !== '\\n' && end < text.length) {\n          end++\n        }\n\n        let lines = text.substr(start, end - start).split('\\n')\n\n        for (let i = 0; i < lines.length; i++) {\n\n          // Don't indent last line if cursor at start of line\n          if (i === lines.length - 1 && lines[i].length === 0) {\n            continue\n          }\n\n          // Indent or deindent\n          if (e.shiftKey) {\n            lines[i] = lines[i].replace(tabStart, '')\n          } else {\n            lines[i] = `    ${lines[i]}`\n          }\n        }\n        lines = lines.join('\\n')\n\n        // Update the text area\n        target.value = text.substr(0, start) + lines + text.substr(end)\n        target.selectionStart = start\n        target.selectionEnd = start + lines.length\n      }\n    }\n  }\n\n  const init = async first => {\n    // Setup input highlighting and events to run Python code blocks.\n\n    const notebook = document.getElementById(\"__notebook-source\")\n    const playgrounds = document.querySelectorAll(\".playground\")\n\n    if (notebook && first) {\n      const notebookInput = document.getElementById(\"__notebook-input\")\n\n      notebookInput.addEventListener(\"input\", e => {\n        // Adjust textarea height on text input.\n\n        textResize(e.target)\n      })\n\n      notebookInput.addEventListener('keydown', handleTab)\n\n      const editPage = document.getElementById(\"__notebook-edit\")\n      editPage.addEventListener(\"click\", () => {\n        editTemp[notebookInput.id] = notebookInput.value\n        document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n        document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        // Reset height\n        const inpt = document.getElementById(\"__notebook-input\")\n        inpt.setAttribute('style', '')\n        textResize(document.getElementById(\"__notebook-input\"))\n      })\n\n      document.getElementById(\"__notebook-md-gist\").addEventListener(\"click\", async e => {\n        let uri = prompt(\"Please enter link to the Markdown page source:\", gist) // eslint-disable-line no-alert\n        if (uri !== null) {\n          uri = encodeuri(uri)\n          e.preventDefault()\n          history.pushState({notebook: uri}, \"\", `?${new URLSearchParams(`notebook=${uri}`).toString()}`)\n          main(false) // eslint-disable-line no-use-before-define\n        }\n      })\n\n      document.getElementById(\"__notebook-py-gist\").addEventListener(\"click\", async e => {\n        let uri = prompt(\"Please enter the link to the Python code source:\", gist) // eslint-disable-line no-alert\n        if (uri !== null) {\n          uri = encodeuri(uri)\n          e.preventDefault()\n          history.pushState({source: uri}, \"\", `?${new URLSearchParams(`source=${uri}`).toString()}`)\n          main(false) // eslint-disable-line no-use-before-define\n        }\n      })\n\n      document.getElementById(\"__notebook-input\").value = raw\n      document.getElementById(\"__notebook-cancel\").addEventListener(\"click\", () => {\n        notebookInput.value = editTemp[notebookInput.id]\n        delete editTemp[notebookInput.id]\n        document.getElementById(\"__notebook-render\").classList.toggle(\"hidden\")\n        document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n      })\n\n      document.getElementById(\"__notebook-submit\").addEventListener(\"click\", async() => {\n        const render = document.getElementById(\"__notebook-render\")\n        raw = document.getElementById(\"__notebook-input\").value\n        render.classList.toggle(\"hidden\")\n        document.getElementById(\"__notebook-source\").classList.toggle(\"hidden\")\n        const article = document.querySelector(\"article\")\n        showBusy(article, \"Loading Notebook...\")\n        render.innerHTML = \"\"\n        editTemp = {}\n        await setupPyodide(true)\n        await pyrender(raw)\n        await init()\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      })\n    }\n\n    playgrounds.forEach(pg => {\n\n      const currentID = pg.id.replace(reIdNum, \"$1\")\n      const inputs = document.getElementById(`__playground-inputs_${currentID}`)\n      const results = document.getElementById(`__playground-results_${currentID}`)\n      const pgcode = document.getElementById(`__playground-code_${currentID}`)\n      const buttonEdit = document.querySelector(`button#__playground-edit_${currentID}`)\n      const buttonShare = document.querySelector(`button#__playground-share_${currentID}`)\n      const buttonRun = document.querySelector(`button#__playground-run_${currentID}`)\n      const buttonCancel = document.querySelector(`button#__playground-cancel_${currentID}`)\n\n      inputs.addEventListener(\"input\", () => {\n        // Adjust textarea height on text input.\n\n        textResize(inputs)\n      })\n\n      inputs.addEventListener('keydown', handleTab)\n\n      inputs.addEventListener(\"touchmove\", e => {\n        // Stop propagation on \"touchmove\".\n\n        e.stopPropagation()\n      })\n\n      results.addEventListener(\"click\", e => {\n        // Handle clicks on results and copies color from single color swatch when clicked.\n\n        const el = e.target\n        if (el.matches('span.swatch-color')) {\n          let content = ''\n          const parent = el.parentNode\n          if (!parent.matches('span.swatch-gradient')) {\n            content = parent.getAttribute('title').replace('Copy to clipboard', '')\n            content = content.replace('\\n', '')\n            if (window.clipboardData && window.clipboardData.setData) {\n              // Old `IE`` handling, do we really need this?\n              return window.clipboardData.setData(\"Text\", content)\n            } else if (document.queryCommandSupported && document.queryCommandSupported(\"copy\")) {\n              const textarea = document.createElement(\"textarea\")\n              textarea.textContent = content\n              textarea.style.position = \"fixed\"\n              document.body.appendChild(textarea)\n              textarea.select()\n              try {\n                return document.execCommand(\"copy\")\n              } catch (ex) {\n                return prompt(\"Copy to clipboard: Ctrl+C, Enter\", content) // eslint-disable-line no-alert\n              } finally {\n                document.body.removeChild(textarea)\n              }\n            }\n          }\n        }\n      })\n\n      buttonEdit.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        editTemp[currentID] = inputs.value\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        textResize(inputs)\n        inputs.focus()\n      })\n\n      buttonShare.addEventListener(\"click\", async() => {\n        // Handle the share click: copy URL with code as parameter.\n\n        const base = window.location.pathname.split('/')[1]\n        const uri = encodeuri(inputs.value)\n        const loc = window.location\n        let pathname = \"/playground/\"\n        if (loc.pathname.startsWith(`/${base}/`)) {\n          pathname = `/${base}/playground/`\n        }\n        const path = `${loc.protocol}//${loc.host}${pathname}?code=${uri}`\n        if (path.length > 2000) {\n          alert( // eslint-disable-line no-alert\n            \"Code must be small enough to generate a shareable URL under 2000 characters!\"\n          )\n        } else {\n          navigator.clipboard.writeText(path).then(async() => {\n            alert(\"Link copied to clipboard :)\") // eslint-disable-line no-alert\n          }, async() => {\n            alert(\"Failed to copy link clipboard!\") // eslint-disable-line no-alert\n          })\n        }\n      })\n\n      buttonRun.addEventListener(\"click\", async() => {\n        // Handle the button click: show source or execute source.\n\n        if (busy) {\n          return\n        }\n\n        busy = true\n        // Load Pyodide and related packages.\n        const form = pgcode.querySelector(\"form\")\n        showBusy(form, null, true)\n        const buttons = document.querySelectorAll(\".playground .playground-run\")\n        if (buttons) {\n          buttons.forEach(b => {\n            b.setAttribute(\"disabled\", \"\")\n          })\n        }\n        await setupPyodide(false)\n        results.querySelector(\"code\").innerHTML = \"\"\n        await pyexecute(currentID)\n        if (buttons) {\n          buttons.forEach(b => {\n            b.removeAttribute(\"disabled\")\n          })\n        }\n        hideBusy(form)\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n\n        delete editTemp[currentID]\n        busy = false\n      })\n\n      buttonCancel.addEventListener(\"click\", () => {\n        // Cancel edit.\n\n        inputs.value = editTemp[currentID]\n        delete editTemp[currentID]\n        pgcode.classList.toggle(\"hidden\")\n        results.classList.toggle(\"hidden\")\n        buttonEdit.classList.toggle(\"hidden\")\n        buttonShare.classList.toggle(\"hidden\")\n        buttonRun.classList.toggle(\"hidden\")\n        buttonCancel.classList.toggle(\"hidden\")\n      })\n    })\n  }\n\n  const main = async(first, search) => {\n    // Load external source to render in a playground.\n    // This can be something like a file on a gist we must read in (?source=)\n    // or raw code (?code=).\n\n    editTemp = {}\n\n    if (window.location.pathname.endsWith(\"/playground/\")) {\n      const params = search || new URLSearchParams(window.location.search)\n      const loadMsg = \"Loading Pyodide...\"\n      const pageMsg = \"Loading Notebook...\"\n      const uri = params.has(\"source\") ? params.get(\"source\") : params.get(\"notebook\")\n      const article = document.querySelector(\"article\")\n      if (uri !== null && uri.trim()) {\n        // A source was specified, so load it.\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        try {\n          const gistType = params.has(\"source\") ? \"source\" : \"notebook\"\n          lastSearch = decodeURIComponent(params.toString())\n          let value = \"\"\n          const xhr = new XMLHttpRequest()\n          gist = uri\n          xhr.open(\"GET\", uri, true)\n          xhr.onload = async() => {\n            // Try and load the requested content\n            if (xhr.readyState === 4) {\n              if (xhr.status === 200) {\n                value = xhr.responseText\n              }\n            }\n\n            if (gistType === \"source\") {\n              value = getContent(value)\n            }\n            await pyrender(value)\n            await init(first)\n            hideBusy(article)\n            fakeDOMContentLoaded()\n          }\n          xhr.send()\n        } catch (err) {} // eslint-disable-line no-empty\n      } else {\n        gist = \"\"\n        const content = getContent(params.has(\"code\") ? params.get(\"code\") : defContent)\n        lastSearch = decodeURIComponent(params.toString())\n        showBusy(article, loadMsg)\n        await setupPyodide(true)\n        hideBusy(article)\n        showBusy(article, pageMsg)\n        await pyrender(content)\n        await init(first)\n        hideBusy(article)\n        fakeDOMContentLoaded()\n      }\n    } else {\n      gist = \"\"\n      lastSearch = \"\"\n      init(first)\n    }\n  }\n\n  // Capture links in notebook pages so that we can make playgound links load instantly\n  document.addEventListener(\"click\", interceptClickEvent, true)\n\n  // Handle history of notebook pages as they are loaded dynamically\n  window.addEventListener(\"popstate\", popState)\n\n  // Before leaving, turn off fake, just in case we navigated away before finished\n  window.addEventListener(\"unload\", () => {\n    fake = false\n  })\n\n  // Attach main via subscribe (subscribes to Materials on page load and instant page loads)\n  window.document$.subscribe(() => {\n    // To get other libraries to reload, we may create a fake `DOMContentLoaded`\n    // No need to process these events.\n    if (fake) {\n      fake = false\n      return\n    }\n    main(true)\n  })\n})()\n"],"names":["webspace","gamut","window","matchMedia","matches","CSS","supports","_unused","pyodide","busy","raw","gist","editTemp","reIdNum","initialized","lastSearch","fake","tabStart","pycode","concat","defContent","colorNotebook","defaultPlayground","getContent","content","notebookInstalled","playgroundInstalled","fakeDOMContentLoaded","document","dispatchEvent","Event","bubbles","cancelable","document$","next","textResize","inpt","scrollLeft","pageXOffset","documentElement","body","parentNode","scrollTop","pageYOffset","style","height","Math","min","scrollHeight","scrollTo","encodeuri","uri","encodeURIComponent","replace","c","charCodeAt","toString","pyexecute","_ref","_asyncToGenerator","_regeneratorRuntime","mark","_callee","currentID","currentInputs","wrap","_context","prev","getElementById","setAttribute","globals","set","runPythonAsync","removeAttribute","stop","_x","apply","this","arguments","pyrender","_ref2","_callee2","text","src","_context2","value","location","hash","href","_x2","setupPyodide","_ref3","_callee3","full","base","packages","installs","_iterator","_step","s","_context3","loadPyodide","indexURL","fullStdLib","sent","origin","pathname","split","notebookWheels","playgroundWheels","_createForOfIteratorHelper","n","done","endsWith","push","err","e","f","loadPackage","_x3","showBusy","target","label","relative","loaderLabel","classes","template","createElement","innerHTML","appendChild","firstChild","hideBusy","querySelector","removeChild","handleTab","key","selectionStart","selectionEnd","preventDefault","start","end","length","lines","substr","i","shiftKey","join","init","_ref4","_callee12","first","notebook","playgrounds","notebookInput","_context12","querySelectorAll","addEventListener","id","classList","toggle","_ref5","_callee4","_context4","prompt","history","pushState","URLSearchParams","main","_x5","_ref6","_callee5","_context5","source","_x6","_callee6","render","article","_context6","forEach","pg","inputs","results","pgcode","buttonEdit","buttonShare","buttonRun","buttonCancel","stopPropagation","el","parent","getAttribute","clipboardData","setData","queryCommandSupported","textarea","textContent","position","select","execCommand","ex","_callee7","_context7","focus","_callee10","loc","path","_context10","startsWith","protocol","host","alert","navigator","clipboard","writeText","then","_callee8","_context8","_callee9","_context9","_callee11","form","buttons","_context11","abrupt","b","_x4","_ref13","_callee14","search","params","loadMsg","pageMsg","gistType","xhr","_context14","has","get","trim","decodeURIComponent","XMLHttpRequest","open","onload","_callee13","_context13","readyState","status","responseText","send","_x7","_x8","srcElement","tagName","subscribe"],"mappings":"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"}
\ No newline at end of file
diff --git a/docs/theme/playground-config-70f29cae.js b/docs/theme/playground-config-4f0f586c.js
similarity index 76%
rename from docs/theme/playground-config-70f29cae.js
rename to docs/theme/playground-config-4f0f586c.js
index a505c2d3..b519c484 100644
--- a/docs/theme/playground-config-70f29cae.js
+++ b/docs/theme/playground-config-4f0f586c.js
@@ -1,5 +1,5 @@
 var colorNotebook = {
-    "playgroundWheels": ['pygments-2.17.2-py3-none-any.whl', 'coloraide-4.0-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-py3-none-any.whl'],
+    "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'],
     "defaultPlayground": "import coloraide\ncoloraide.__version__\nColor('red')"
 }
diff --git a/mkdocs.yml b/mkdocs.yml
index 1b73b406..149a8639 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-70f29cae.js
+  - playground-config-4f0f586c.js
   - https://cdn.jsdelivr.net/pyodide/v0.26.2/full/pyodide.js
-  - assets/coloraide-extras/extra-notebook-DQWpIrCE.js
+  - assets/coloraide-extras/extra-notebook-UmZ-G8NV.js
 
 extra:
   social:
diff --git a/pyproject.toml b/pyproject.toml
index 5a408000..e3c108bd 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -118,6 +118,8 @@ lint.ignore = [
     "RUF012",
     "RUF005",
     "PGH004",
+    "RUF022",
+    "RUF023",
     "RUF100",
     "B905"
 ]


Test patch:
diff --git a/tests/test_interpolation.py b/tests/test_interpolation.py
index c911043b..6456b45c 100644
--- a/tests/test_interpolation.py
+++ b/tests/test_interpolation.py
@@ -1563,7 +1563,7 @@ def test_bspline_undefined_alpha(self):
                 space='srgb',
                 method='bspline'
             )(0.75),
-            Color('rgb(3.4932 38.425 174.66 / 0.76042)')
+            Color('rgb(3.4932 76.849 174.66 / 0.76042)')
         )
 
         self.assertColorEqual(