Repository: facelessuser/coloraide

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:

Solution 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 @@ class Color(metaclass=ColorMeta):
                     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 @@ class InterpolatorContinuous(Interpolator):
         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 @@ class InterpolatorContinuous(Interpolator):
                 # 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 @@ let busyTarget = null
 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 @@
     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/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 @@ class TestInterpolation(util.ColorAsserts, unittest.TestCase):
                 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(