@taprootio/espalier 3.0.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -52,6 +52,27 @@ export interface DataPaletteIssue {
52
52
  * the threshold.
53
53
  */
54
54
  export declare function auditDataPalette(palette: Readonly<DataPalette>, threshold?: number): DataPaletteIssue[];
55
+ /** Vision conditions covered by {@link auditColorDistances}: normal plus every CVD simulation. */
56
+ export type VisionCondition = ColorVisionSimulation | "normal";
57
+ /** One too-close pair found by {@link auditColorDistances}. */
58
+ export interface ColorDistanceIssue {
59
+ /** The two entry names, in input order. */
60
+ pair: [string, string];
61
+ /** The vision condition under which the pair collapses. */
62
+ simulation: VisionCondition;
63
+ /** Post-simulation OKLab distance between the pair. */
64
+ distance: number;
65
+ /** The threshold the distance fell below. */
66
+ threshold: number;
67
+ }
68
+ /**
69
+ * Audit an arbitrary named color set for pairwise distinguishability
70
+ * under normal vision and every CVD simulation (ESP0172 — the intent
71
+ * collision check). Values must be concrete CSS colors, like
72
+ * {@link auditDataPalette}'s — resolve anchors first; the palette-shaped
73
+ * audit remains the categorical-series wrapper.
74
+ */
75
+ export declare function auditColorDistances(entries: ReadonlyArray<readonly [string, string]>, threshold?: number, conditions?: readonly VisionCondition[]): ColorDistanceIssue[];
55
76
  /** Minimum supported number of colors in a generated data ramp. */
56
77
  export declare const MIN_DATA_RAMP_STEPS = 3;
57
78
  /** Maximum supported number of colors in a generated data ramp. */
@@ -1 +1 @@
1
- import{clampChannel as L,gamutMapToSRGB as E,linearRgbToOklab as I,oklabToOklch as C,oklchToOklab as S,oklchToSRGB as w,parseCssColor as M,serializeOklch as b,srgbToLinearRGB as N}from"./color-engine.js";const u=["series1","series2","series3","series4","series5","series6","series7","series8"],y={series1:"#000000",series2:"#E69F00",series3:"#56B4E9",series4:"#009E73",series5:"#F0E442",series6:"#0072B2",series7:"#D55E00",series8:"#CC79A7"},k=["deuteranopia","protanopia","tritanopia"],O=.07,P={protanopia:[[.152286,1.052583,-.204868],[.114503,.786281,.099216],[-.003882,-.048116,1.051998]],deuteranopia:[[.367322,.860646,-.227968],[.280085,.672501,.047413],[-.01182,.04294,.968881]],tritanopia:[[1.255528,-.076749,-.178779],[-.078411,.930809,.147602],[.004733,.691367,.3039]]};function x(e,t){const r=w(E(e)),o=N(r),n=s=>L(s[0]*o.r+s[1]*o.g+s[2]*o.b);return{r:n(t[0]),g:n(t[1]),b:n(t[2])}}function q(e,t){return Math.hypot(e.L-t.L,e.a-t.a,e.b-t.b)}function p(e,t){const r=M(e);if(!r)throw new TypeError(`${t} is not a valid opaque CSS color: "${e}".`);return r}function G(e,t=O){if(!Number.isFinite(t)||t<0)throw new RangeError("Data-palette distance threshold must be a finite number \u2265 0.");const r=new Map;for(const n of u)r.set(n,p(e[n],`dataPalette.${n}`));const o=[];for(const n of k){const s=new Map;for(const a of u)s.set(a,I(x(r.get(a),P[n])));for(let a=0;a<u.length;a+=1)for(let i=a+1;i<u.length;i+=1){const l=u[a],c=u[i],g=q(s.get(l),s.get(c));g<t&&o.push({series:[l,c],simulation:n,distance:g,threshold:t})}}return o}const A=3,f=11,m=7,T=1e-6,v="oklch(0.96 0 0)";function _(e,t){if(!Number.isInteger(e)||e<A||e>f)throw new RangeError(`Data-ramp steps must be an integer from ${A} through ${f}.`);if(t&&e%2===0)throw new RangeError("Diverging data-ramp steps must be odd so the neutral is the midpoint.")}function d(e,t){if(!Number.isFinite(e)||e<0||e>1)throw new RangeError(`${t} must be a finite number from 0 through 1.`)}function U(e,t={}){const r=p(e,"Sequential ramp source"),o=t.steps??m,n=t.lightnessStart??.95,s=t.lightnessEnd??.25;if(_(o,!1),d(n,"Sequential ramp lightnessStart"),d(s,"Sequential ramp lightnessEnd"),n<=s)throw new RangeError("Sequential ramp lightnessStart must be greater than lightnessEnd.");if((n-s)/(o-1)<=T)throw new RangeError(`Sequential ramp lightness bounds must leave more than ${T} lightness between serialized stops.`);return Array.from({length:o},(a,i)=>{const l=i/(o-1),c=n+(s-n)*l;return b(E({l:c,c:r.c,h:r.h}))})}function R(e,t,r){return{L:e.L+(t.L-e.L)*r,a:e.a+(t.a-e.a)*r,b:e.b+(t.b-e.b)*r}}function B(e,t,r={}){const o=p(e,"Diverging ramp start"),n=p(t,"Diverging ramp end"),s=p(r.neutral??v,"Diverging ramp neutral"),a=r.steps??m;_(a,!0);const i=(a-1)/2,l=S(o),c=S(s),g=S(n);return Array.from({length:a},(F,h)=>{if(h===i)return b(E(s));const D=h<i?R(l,c,h/i):R(c,g,(h-i)/i);return b(E(C(D)))})}export{k as COLOR_VISION_SIMULATIONS,u as DATA_SERIES_KEYS,y as DEFAULT_DATA_PALETTE,m as DEFAULT_DATA_RAMP_STEPS,v as DEFAULT_DIVERGING_NEUTRAL,f as MAX_DATA_RAMP_STEPS,O as MIN_DATA_COLOR_DISTANCE,T as MIN_DATA_RAMP_LIGHTNESS_STEP,A as MIN_DATA_RAMP_STEPS,G as auditDataPalette,B as generateDivergingRamp,U as generateSequentialRamp};
1
+ import{clampChannel as x,gamutMapToSRGB as m,linearRgbToOklab as S,oklabToOklch as k,oklchToOklab as b,oklchToSRGB as P,parseCssColor as F,serializeOklch as E,srgbToLinearRGB as q}from"./color-engine.js";const p=["series1","series2","series3","series4","series5","series6","series7","series8"],G={series1:"#000000",series2:"#E69F00",series3:"#56B4E9",series4:"#009E73",series5:"#F0E442",series6:"#0072B2",series7:"#D55E00",series8:"#CC79A7"},A=["deuteranopia","protanopia","tritanopia"],T=.07,_={protanopia:[[.152286,1.052583,-.204868],[.114503,.786281,.099216],[-.003882,-.048116,1.051998]],deuteranopia:[[.367322,.860646,-.227968],[.280085,.672501,.047413],[-.01182,.04294,.968881]],tritanopia:[[1.255528,-.076749,-.178779],[-.078411,.930809,.147602],[.004733,.691367,.3039]]};function d(e,t){const s=P(m(e)),a=q(s),n=o=>x(o[0]*a.r+o[1]*a.g+o[2]*a.b);return{r:n(t[0]),g:n(t[1]),b:n(t[2])}}function R(e,t){return Math.hypot(e.L-t.L,e.a-t.a,e.b-t.b)}function g(e,t){const s=F(e);if(!s)throw new TypeError(`${t} is not a valid opaque CSS color: "${e}".`);return s}function U(e,t=T){if(!Number.isFinite(t)||t<0)throw new RangeError("Data-palette distance threshold must be a finite number \u2265 0.");const s=new Map;for(const n of p)s.set(n,g(e[n],`dataPalette.${n}`));const a=[];for(const n of A){const o=new Map;for(const r of p)o.set(r,S(d(s.get(r),_[n])));for(let r=0;r<p.length;r+=1)for(let i=r+1;i<p.length;i+=1){const l=p[r],c=p[i],u=R(o.get(l),o.get(c));u<t&&a.push({series:[l,c],simulation:n,distance:u,threshold:t})}}return a}const v=[[1,0,0],[0,1,0],[0,0,1]];function B(e,t=T,s=["normal",...A]){if(!Number.isFinite(t)||t<0)throw new RangeError("Color distance threshold must be a finite number \u2265 0.");const a=e.map(([r,i])=>[r,g(i,r)]),n=[],o=s.map(r=>[r,r==="normal"?v:_[r]]);for(const[r,i]of o){const l=a.map(([,c])=>S(d(c,i)));for(let c=0;c<e.length;c+=1)for(let u=c+1;u<e.length;u+=1){const f=R(l[c],l[u]);f<t&&n.push({pair:[e[c][0],e[u][0]],simulation:r,distance:f,threshold:t})}}return n}const D=3,I=11,L=7,C=1e-6,$="oklch(0.96 0 0)";function M(e,t){if(!Number.isInteger(e)||e<D||e>I)throw new RangeError(`Data-ramp steps must be an integer from ${D} through ${I}.`);if(t&&e%2===0)throw new RangeError("Diverging data-ramp steps must be odd so the neutral is the midpoint.")}function w(e,t){if(!Number.isFinite(e)||e<0||e>1)throw new RangeError(`${t} must be a finite number from 0 through 1.`)}function V(e,t={}){const s=g(e,"Sequential ramp source"),a=t.steps??L,n=t.lightnessStart??.95,o=t.lightnessEnd??.25;if(M(a,!1),w(n,"Sequential ramp lightnessStart"),w(o,"Sequential ramp lightnessEnd"),n<=o)throw new RangeError("Sequential ramp lightnessStart must be greater than lightnessEnd.");if((n-o)/(a-1)<=C)throw new RangeError(`Sequential ramp lightness bounds must leave more than ${C} lightness between serialized stops.`);return Array.from({length:a},(r,i)=>{const l=i/(a-1),c=n+(o-n)*l;return E(m({l:c,c:s.c,h:s.h}))})}function N(e,t,s){return{L:e.L+(t.L-e.L)*s,a:e.a+(t.a-e.a)*s,b:e.b+(t.b-e.b)*s}}function z(e,t,s={}){const a=g(e,"Diverging ramp start"),n=g(t,"Diverging ramp end"),o=g(s.neutral??$,"Diverging ramp neutral"),r=s.steps??L;M(r,!0);const i=(r-1)/2,l=b(a),c=b(o),u=b(n);return Array.from({length:r},(f,h)=>{if(h===i)return E(m(o));const O=h<i?N(l,c,h/i):N(c,u,(h-i)/i);return E(m(k(O)))})}export{A as COLOR_VISION_SIMULATIONS,p as DATA_SERIES_KEYS,G as DEFAULT_DATA_PALETTE,L as DEFAULT_DATA_RAMP_STEPS,$ as DEFAULT_DIVERGING_NEUTRAL,I as MAX_DATA_RAMP_STEPS,T as MIN_DATA_COLOR_DISTANCE,C as MIN_DATA_RAMP_LIGHTNESS_STEP,D as MIN_DATA_RAMP_STEPS,B as auditColorDistances,U as auditDataPalette,z as generateDivergingRamp,V as generateSequentialRamp};
@@ -43,9 +43,9 @@ export declare class EspalierElementBase extends LitElement implements SeedColor
43
43
  scheme: "dark" | "light" | "";
44
44
  /**
45
45
  * The element's [intent](/espalier-guides/) — its meaning: `neutral`
46
- * (no pin), `success`, `warning`, or `danger` (each pinned to its
47
- * fixed status family), or `info` (pinned to the complementary
48
- * family). On token-emitting controls a non-neutral intent pins the
46
+ * (no pin), or `success`, `warning`, `danger`, `info` each pinned
47
+ * to its fixed status family (blue for `info`), retunable per theme
48
+ * via `intents`. On token-emitting controls a non-neutral intent pins the
49
49
  * filled-action pair to that family, derived over the governing
50
50
  * zone's theme; class-styled chrome (badges, callouts, status pills)
51
51
  * opts out of inline emission and renders its treatment from CSS
@@ -1,4 +1,4 @@
1
- var h=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,r);else for(var i=f.length-1;i>=0;i--)(a=f[i])&&(s=(o<3?a(s):o>3?a(e,t,s):a(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as R,LitElement as C}from"lit";import{property as p,state as S}from"lit/decorators.js";import{subscribeToRootEvent as u}from"./root-event-subscription.js";import{traverseToClosest as b}from"./utilities.js";import{parseCssColor as w,serializeOklch as x,gamutMapToSRGB as P}from"./color-engine.js";import{computeVariants as v}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as m}from"../root/helpers/compute-semantic-properties.js";import{lightnessRampProperties as E}from"../root/helpers/lightness-ramp-properties.js";import{ROLE_NAMES as V,mergeTheme as U,semanticToCSS as A}from"./theme.js";import{alignAttributeTextInheritance as I,focusRing as O}from"./style-fragments.js";import{syncNormalizedAttribute as D}from"./attribute-helpers.js";import{INTENT_VARIANTS as y,normalizeIntentVariant as z}from"./intent-values.js";const k=new WeakMap;class n extends C{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.contextBacker="",this.scopedTokenOriginalValues=new Map,this.warnedUnknownContexts=new Set,this.pendingInitialThemeRoot=null,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.intentBacker="neutral",this.intentEmitsTokens=!0,this.warnedUnknownIntents=new Set,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyScopedColorTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyScopedColorTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyScopedColorTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const r=()=>{const o=e();return o?(o.focus(t),!0):!1};r()||this.updateComplete.then(()=>{r()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent("value-changed",{detail:e,bubbles:!0,composed:!0}))}get intent(){return this.intentBacker}set intent(e){const t=typeof e=="string"?e.trim():"";t!==""&&!y.includes(t)&&!this.warnedUnknownIntents.has(t)&&(this.warnedUnknownIntents.add(t),console.warn(`Espalier intent: "${t}" is not an intent; expected one of ${y.join(", ")}. Treating it as "neutral".`));const r=this.intentBacker,o=z(e);D(this,"intent",o),o!==r&&(this.intentBacker=o,this.requestUpdate("intent",r),this.applyTokensWhenRootReady())}get context(){return this.contextBacker}set context(e){const t=e??"";t!==this.contextBacker&&(this.contextBacker=t,this.applyTokensWhenRootReady(),this.refreshDescendantIntentDerivations())}refreshDescendantIntentDerivations(){const e=new Set,t=o=>{for(const s of Array.from(o.children))r(s)},r=o=>{if(!e.has(o)){if(e.add(o),o instanceof n&&o.applyTokensWhenRootReady(),o.shadowRoot&&t(o.shadowRoot),o instanceof HTMLSlotElement)for(const s of o.assignedElements({flatten:!0}))r(s);t(o)}};t(this),this.shadowRoot&&t(this.shadowRoot)}static flattenedParent(e){return e instanceof Element&&e.assignedSlot?e.assignedSlot:e instanceof ShadowRoot?e.host:e.parentNode}resolveAncestorZoneTheme(e){let t=n.flattenedParent(this);for(;t;){if(t instanceof Element&&t.localName==="esp-root")return null;if(t instanceof n){const r=t.contextBacker.trim();if(r){const o=this.resolveNamedContextTheme(e,r);if(o)return o}}t=n.flattenedParent(t)}return null}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents(),this.clearScopedTokens(),this.espRoot=null}firstUpdated(e){this.syncRootFromDom(!0),this.applyTokensWhenRootReady()}syncRootFromDom(e){const t=b(this,"esp-root");if(!t){if(this.espRoot&&this.clearScopedTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const r=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,i=this.seedColor!==t.seedColor;return this.espRoot=t,r&&this.isConnected&&this.subscribeToRootEvents(t),(r||a||i)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyTokensWhenRootReady()),r&&this.requestUpdate(),t}applyTokensWhenRootReady(){const e=this.espRoot;if(e&&(!e.hasUpdated||e.isUpdatePending)){this.applyTokensAfterInitialRootUpdate(e);return}this.applyScopedColorTokens()}applyTokensAfterInitialRootUpdate(e){if(this.pendingInitialThemeRoot===e)return;this.pendingInitialThemeRoot=e;const t=e.updateComplete;if(!t){this.pendingInitialThemeRoot=null,this.applyScopedColorTokens();return}t.then(()=>{this.pendingInitialThemeRoot===e&&(this.pendingInitialThemeRoot=null),!(!this.isConnected||this.espRoot!==e)&&(this.scheme=e.scheme==="dark"?"dark":"light",this.seedColor=e.seedColor,this.applyScopedColorTokens())})}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[u(e,"seed-color-changed",this.handleSeedColorChanged),u(e,"scheme-changed",this.handleSchemeChanged),u(e,"theme-changed",this.handleThemeChanged),u(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}traverseToClosest(e){return b(this,e)}applyScopedColorTokens(){if(!this.espRoot)return;const e=this.intentEmitsTokens?n.intentColorSources[this.intentBacker]:"";if(!e&&!this.context.trim()){this.clearScopedTokens();return}const t=this.espRoot.activeTheme;if(!t){this.clearScopedTokens();return}const r=this.resolveContextTheme(t),o=r.theme,s=w(o.seedColor);if(!s)return;const a=v(s,o),i={};if(r.applied&&(Object.assign(i,m(o,a)),Object.assign(i,E(o))),e){let c=o;r.applied||(c=this.resolveAncestorZoneTheme(t)??o);const l=c===o?a:v(s,c),T=m(c,l,{effectiveSource:(g,d)=>n.semanticActionTokens.has(g)?e:d});i["--esp-color-primary"]=x(P(l[e]));for(const g of n.semanticActionTokens){const d=A(g);i[d]=T[d]}}this.applyScopedTokenProperties(i)}resolveContextTheme(e){const t=this.context.trim();if(!t)return{applied:!1,theme:e};const r=this.resolveNamedContextTheme(e,t);return r?{applied:!0,theme:r}:(this.warnedUnknownContexts.has(t)||(this.warnedUnknownContexts.add(t),console.warn(`Espalier context: "${t}" is not defined by the active theme; inheriting root tokens.`)),{applied:!1,theme:e})}resolveNamedContextTheme(e,t){const r=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,t)?e.contexts[t]:void 0;if(!r)return null;let o=k.get(e);const s=o?.get(t);if(s)return s;const a={};for(const c of V){const l=r[c];l!==void 0&&(a[c]=l)}const i=U(e,{lightness:r.lightness,roles:a});return o||(o=new Map,k.set(e,o)),o.set(t,i),i}applyScopedTokenProperties(e){for(const t of this.scopedTokenOriginalValues.keys())t in e||this.restoreScopedTokenProperty(t);for(const[t,r]of Object.entries(e))this.setScopedTokenProperty(t,r)}setScopedTokenProperty(e,t){const r=this.scopedTokenOriginalValues.get(e);if(r){const o=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(o!==r.generatedValue||s!==r.generatedPriority)&&(r.originalValue=o.length?o:null,r.originalPriority=s),r.generatedValue=t,r.generatedPriority=""}else{const o=this.style.getPropertyValue(e);this.scopedTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:o.length?o:null})}this.style.setProperty(e,t)}restoreScopedTokenProperty(e){const t=this.scopedTokenOriginalValues.get(e);if(!t)return;const r=this.style.getPropertyValue(e),o=this.style.getPropertyPriority(e);(r!==t.generatedValue||o!==t.generatedPriority)&&(t.originalValue=r.length?r:null,t.originalPriority=o),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority),this.scopedTokenOriginalValues.delete(e)}clearScopedTokens(){for(const e of[...this.scopedTokenOriginalValues.keys()])this.restoreScopedTokenProperty(e)}}n.intentColorSources={danger:"danger",info:"complementary",neutral:"",success:"success",warning:"warning"},n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[O(".esp-field:focus-within","--esp-field-focus-shadow"),I,R`
1
+ var h=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,r);else for(var i=f.length-1;i>=0;i--)(a=f[i])&&(s=(o<3?a(s):o>3?a(e,t,s):a(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as R,LitElement as C}from"lit";import{property as p,state as S}from"lit/decorators.js";import{subscribeToRootEvent as u}from"./root-event-subscription.js";import{traverseToClosest as b}from"./utilities.js";import{parseCssColor as w,serializeOklch as x,gamutMapToSRGB as P}from"./color-engine.js";import{computeVariants as v}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as m}from"../root/helpers/compute-semantic-properties.js";import{lightnessRampProperties as E}from"../root/helpers/lightness-ramp-properties.js";import{ROLE_NAMES as V,mergeTheme as U,semanticToCSS as A}from"./theme.js";import{alignAttributeTextInheritance as I,focusRing as O}from"./style-fragments.js";import{syncNormalizedAttribute as D}from"./attribute-helpers.js";import{INTENT_VARIANTS as y,normalizeIntentVariant as z}from"./intent-values.js";const k=new WeakMap;class n extends C{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.contextBacker="",this.scopedTokenOriginalValues=new Map,this.warnedUnknownContexts=new Set,this.pendingInitialThemeRoot=null,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.intentBacker="neutral",this.intentEmitsTokens=!0,this.warnedUnknownIntents=new Set,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyScopedColorTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyScopedColorTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyScopedColorTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const r=()=>{const o=e();return o?(o.focus(t),!0):!1};r()||this.updateComplete.then(()=>{r()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent("value-changed",{detail:e,bubbles:!0,composed:!0}))}get intent(){return this.intentBacker}set intent(e){const t=typeof e=="string"?e.trim():"";t!==""&&!y.includes(t)&&!this.warnedUnknownIntents.has(t)&&(this.warnedUnknownIntents.add(t),console.warn(`Espalier intent: "${t}" is not an intent; expected one of ${y.join(", ")}. Treating it as "neutral".`));const r=this.intentBacker,o=z(e);D(this,"intent",o),o!==r&&(this.intentBacker=o,this.requestUpdate("intent",r),this.applyTokensWhenRootReady())}get context(){return this.contextBacker}set context(e){const t=e??"";t!==this.contextBacker&&(this.contextBacker=t,this.applyTokensWhenRootReady(),this.refreshDescendantIntentDerivations())}refreshDescendantIntentDerivations(){const e=new Set,t=o=>{for(const s of Array.from(o.children))r(s)},r=o=>{if(!e.has(o)){if(e.add(o),o instanceof n&&o.applyTokensWhenRootReady(),o.shadowRoot&&t(o.shadowRoot),o instanceof HTMLSlotElement)for(const s of o.assignedElements({flatten:!0}))r(s);t(o)}};t(this),this.shadowRoot&&t(this.shadowRoot)}static flattenedParent(e){return e instanceof Element&&e.assignedSlot?e.assignedSlot:e instanceof ShadowRoot?e.host:e.parentNode}resolveAncestorZoneTheme(e){let t=n.flattenedParent(this);for(;t;){if(t instanceof Element&&t.localName==="esp-root")return null;if(t instanceof n){const r=t.contextBacker.trim();if(r){const o=this.resolveNamedContextTheme(e,r);if(o)return o}}t=n.flattenedParent(t)}return null}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents(),this.clearScopedTokens(),this.espRoot=null}firstUpdated(e){this.syncRootFromDom(!0),this.applyTokensWhenRootReady()}syncRootFromDom(e){const t=b(this,"esp-root");if(!t){if(this.espRoot&&this.clearScopedTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const r=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,i=this.seedColor!==t.seedColor;return this.espRoot=t,r&&this.isConnected&&this.subscribeToRootEvents(t),(r||a||i)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyTokensWhenRootReady()),r&&this.requestUpdate(),t}applyTokensWhenRootReady(){const e=this.espRoot;if(e&&(!e.hasUpdated||e.isUpdatePending)){this.applyTokensAfterInitialRootUpdate(e);return}this.applyScopedColorTokens()}applyTokensAfterInitialRootUpdate(e){if(this.pendingInitialThemeRoot===e)return;this.pendingInitialThemeRoot=e;const t=e.updateComplete;if(!t){this.pendingInitialThemeRoot=null,this.applyScopedColorTokens();return}t.then(()=>{this.pendingInitialThemeRoot===e&&(this.pendingInitialThemeRoot=null),!(!this.isConnected||this.espRoot!==e)&&(this.scheme=e.scheme==="dark"?"dark":"light",this.seedColor=e.seedColor,this.applyScopedColorTokens())})}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[u(e,"seed-color-changed",this.handleSeedColorChanged),u(e,"scheme-changed",this.handleSchemeChanged),u(e,"theme-changed",this.handleThemeChanged),u(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}traverseToClosest(e){return b(this,e)}applyScopedColorTokens(){if(!this.espRoot)return;const e=this.intentEmitsTokens?n.intentColorSources[this.intentBacker]:"";if(!e&&!this.context.trim()){this.clearScopedTokens();return}const t=this.espRoot.activeTheme;if(!t){this.clearScopedTokens();return}const r=this.resolveContextTheme(t),o=r.theme,s=w(o.seedColor);if(!s)return;const a=v(s,o),i={};if(r.applied&&(Object.assign(i,m(o,a)),Object.assign(i,E(o))),e){let c=o;r.applied||(c=this.resolveAncestorZoneTheme(t)??o);const l=c===o?a:v(s,c),T=m(c,l,{effectiveSource:(g,d)=>n.semanticActionTokens.has(g)?e:d});i["--esp-color-primary"]=x(P(l[e]));for(const g of n.semanticActionTokens){const d=A(g);i[d]=T[d]}}this.applyScopedTokenProperties(i)}resolveContextTheme(e){const t=this.context.trim();if(!t)return{applied:!1,theme:e};const r=this.resolveNamedContextTheme(e,t);return r?{applied:!0,theme:r}:(this.warnedUnknownContexts.has(t)||(this.warnedUnknownContexts.add(t),console.warn(`Espalier context: "${t}" is not defined by the active theme; inheriting root tokens.`)),{applied:!1,theme:e})}resolveNamedContextTheme(e,t){const r=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,t)?e.contexts[t]:void 0;if(!r)return null;let o=k.get(e);const s=o?.get(t);if(s)return s;const a={};for(const c of V){const l=r[c];l!==void 0&&(a[c]=l)}const i=U(e,{lightness:r.lightness,roles:a});return o||(o=new Map,k.set(e,o)),o.set(t,i),i}applyScopedTokenProperties(e){for(const t of this.scopedTokenOriginalValues.keys())t in e||this.restoreScopedTokenProperty(t);for(const[t,r]of Object.entries(e))this.setScopedTokenProperty(t,r)}setScopedTokenProperty(e,t){const r=this.scopedTokenOriginalValues.get(e);if(r){const o=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(o!==r.generatedValue||s!==r.generatedPriority)&&(r.originalValue=o.length?o:null,r.originalPriority=s),r.generatedValue=t,r.generatedPriority=""}else{const o=this.style.getPropertyValue(e);this.scopedTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:o.length?o:null})}this.style.setProperty(e,t)}restoreScopedTokenProperty(e){const t=this.scopedTokenOriginalValues.get(e);if(!t)return;const r=this.style.getPropertyValue(e),o=this.style.getPropertyPriority(e);(r!==t.generatedValue||o!==t.generatedPriority)&&(t.originalValue=r.length?r:null,t.originalPriority=o),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority),this.scopedTokenOriginalValues.delete(e)}clearScopedTokens(){for(const e of[...this.scopedTokenOriginalValues.keys()])this.restoreScopedTokenProperty(e)}}n.intentColorSources={danger:"danger",info:"info",neutral:"",success:"success",warning:"warning"},n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[O(".esp-field:focus-within","--esp-field-focus-shadow"),I,R`
2
2
  :host {
3
3
 
4
4
  --_esp-field-resolved-hover-bg: var(
@@ -1,8 +1,8 @@
1
- import{css as o,unsafeCSS as e}from"lit";const l=o`
1
+ import{css as o,unsafeCSS as e}from"lit";const a=o`
2
2
  :host([align]) {
3
3
  text-align: inherit;
4
4
  }
5
- `,a=o`
5
+ `,l=o`
6
6
  .sr-only {
7
7
  position: absolute;
8
8
  width: 1px;
@@ -50,8 +50,8 @@ import{css as o,unsafeCSS as e}from"lit";const l=o`
50
50
  }
51
51
 
52
52
  .intent-info {
53
- --_esp-intent-background: var(--esp-color-link-hover-bg);
54
- --_esp-intent-border-color: oklch(from var(--esp-color-link) var(--esp-l-border) c h);
55
- --_esp-intent-color: var(--esp-color-link);
53
+ --_esp-intent-background: oklch(from var(--esp-color-info) var(--esp-l-raised-2) c h);
54
+ --_esp-intent-border-color: oklch(from var(--esp-color-info) var(--esp-l-border) c h);
55
+ --_esp-intent-color: oklch(from var(--esp-color-info) var(--esp-l-text) c h);
56
56
  }
57
- `;export{l as alignAttributeTextInheritance,i as disabledControl,p as focusRing,d as intentSurfaceTokens,a as srOnly};
57
+ `;export{a as alignAttributeTextInheritance,i as disabledControl,p as focusRing,d as intentSurfaceTokens,l as srOnly};
@@ -36,21 +36,35 @@ export type LightnessKey = "surface" | "raised1" | "raised2" | "raised3" | "rais
36
36
  /** Lightness values (0–1) for every ramp position. */
37
37
  export type LightnessMap = Record<LightnessKey, number>;
38
38
  /**
39
- * A geometric color-theory variant **or** a fixed semantic hue.
39
+ * A geometric color-theory variant **or** a fixed status family.
40
40
  *
41
- * Geometric variants are derived by rotating the seed hue; semantic
42
- * hues (`danger`, `success`, `warning`) use fixed angles defined
43
- * in `semanticHues`.
41
+ * Geometric variants are derived by rotating the seed hue; the status
42
+ * families (`danger`, `success`, `warning`, `info`) use fixed hue
43
+ * angles from `semanticHues` — or a theme's `intents` override, which
44
+ * retunes a family with a declared absolute color (ESP0172).
44
45
  */
45
- export type ColorSource = "primary" | "analogous-left" | "analogous-right" | "complementary" | "split-complementary-left" | "split-complementary-right" | "triadic-left" | "triadic-right" | "danger" | "success" | "warning";
46
+ export type ColorSource = "primary" | "analogous-left" | "analogous-right" | "complementary" | "split-complementary-left" | "split-complementary-right" | "triadic-left" | "triadic-right" | "danger" | "success" | "warning" | "info";
46
47
  /**
47
- * Non-primary color sources — the ten variants that can carry
48
+ * Non-primary color sources — the eleven variants that can carry
48
49
  * independent chroma overrides.
49
50
  *
50
51
  * Primary is excluded because its chroma is always the seed
51
52
  * color's chroma.
52
53
  */
53
54
  export type VariantColorSource = Exclude<ColorSource, "primary">;
55
+ /**
56
+ * The fixed-meaning status families (ADR-004): the colors
57
+ * `intent="danger|success|warning|info"` and the same-named mapping
58
+ * sources resolve to. A theme may retune each with `intents`.
59
+ */
60
+ export type StatusColorSource = "danger" | "success" | "warning" | "info";
61
+ /**
62
+ * Status-family color overrides, by family (ESP0172). Values are an
63
+ * `anchor:<name>[.<slot>]` reference or a supported color form
64
+ * (`#rrggbb`, `#rgb`, `rgb()`, `hsl()`, `oklch()`); see
65
+ * {@link EspalierTheme.intents}.
66
+ */
67
+ export type ThemeIntents = Partial<Record<StatusColorSource, string>>;
54
68
  /**
55
69
  * The object form of an anchor: a required base `color` plus named
56
70
  * sub-slots — per-family variants the way designers already specify
@@ -175,9 +189,11 @@ export type SemanticMappings = Record<SemanticColorName, SemanticMapping>;
175
189
  * automatically (see {@link ROLE_PAIRED_INK})
176
190
  * - `structure` — borders and shadows
177
191
  *
178
- * `status` is deliberately absent: the danger/success/warning families
179
- * carry meaning through fixed hues (ADR-004) and are not a brand
180
- * decision.
192
+ * `status` is deliberately absent as a role: the four status families
193
+ * (`danger`, `success`, `warning`, `info`) carry reserved *meanings*
194
+ * that no role may reassign (ADR-004, as amended). Their *colors* are
195
+ * a brand decision — retune a family with the theme's `intents` field
196
+ * and every derived token follows.
181
197
  */
182
198
  export type RoleName = "canvas" | "ink" | "accent" | "action" | "structure";
183
199
  /**
@@ -190,7 +206,7 @@ export type RoleName = "canvas" | "ink" | "accent" | "action" | "structure";
190
206
  export type RoleSlotName = {
191
207
  canvas: never;
192
208
  ink: "heading";
193
- accent: "text";
209
+ accent: "text" | "hover";
194
210
  action: "ink";
195
211
  structure: never;
196
212
  };
@@ -232,7 +248,10 @@ export declare const ROLE_NAMES: readonly RoleName[];
232
248
  * The `accent` role has no body-text slot on purpose. "Rose is
233
249
  * decorative only" is a structural guarantee here, not a comment: text
234
250
  * that must come from the accent family comes through `accent.text`,
235
- * the deepened variant a designer picked for legibility.
251
+ * the deepened variant a designer picked for legibility. `accent.hover`
252
+ * lets a hover change *family*, not just lightness — "plum link, rose
253
+ * hover" is an ordinary brand rule (ESP0172); absent, `linkHover` keeps
254
+ * following `accent.text` exactly as before.
236
255
  */
237
256
  export declare const ROLE_TOKEN_PLAN: Readonly<Record<RoleName, Readonly<Record<string, ReadonlyArray<[SemanticColorName, LightnessKey]>>>>>;
238
257
  /**
@@ -356,7 +375,7 @@ export interface EspalierTheme {
356
375
  /** Triadic offset from seed (default 120). */
357
376
  triadic: number;
358
377
  };
359
- /** Fixed hue angles for danger / success / warning colors. */
378
+ /** Fixed hue angles for the danger / success / warning / info families. */
360
379
  semanticHues: {
361
380
  /** Danger hue angle (default 27, red-orange). */
362
381
  danger: number;
@@ -364,7 +383,46 @@ export interface EspalierTheme {
364
383
  success: number;
365
384
  /** Warning hue angle (default 90, yellow-green). */
366
385
  warning: number;
386
+ /** Info hue angle (default 244, blue). */
387
+ info: number;
367
388
  };
389
+ /**
390
+ * Status-family color overrides, by family (ESP0172).
391
+ *
392
+ * Each entry retunes one of the fixed status families — the colors
393
+ * `intent="danger|success|warning|info"` and the same-named mapping
394
+ * sources resolve to — with a declared color: an
395
+ * `anchor:<name>[.<slot>]` reference or a supported color form —
396
+ * `#rrggbb`, `#rgb`, `rgb()`, `hsl()`, or `oklch()`. CSS keywords
397
+ * such as `red` are not parsed.
398
+ *
399
+ * An override is **absolute**, like an anchor: it carries its own
400
+ * lightness, chroma, and hue, and `semanticHues` / `variantChroma`
401
+ * are ignored for that family. Overrides retune a family; they do
402
+ * not reassign its meaning (ADR-004): give `danger` your brand's
403
+ * red, but never point one family at another — a family name as a
404
+ * value (`intents.success: "danger"`) is rejected by validation; a
405
+ * color choice that creates a rendered collision is flagged by the
406
+ * distance warning, while a merely unusual — but separated — color
407
+ * passes silently. `validateTheme` warns when two
408
+ * status families — or a family and the action color — become hard
409
+ * to distinguish as rendered on controls, and its advice is
410
+ * counterfactual-tested per pair: it recommends retuning, widening
411
+ * the chroma band, or moving the lightness stop only when that
412
+ * change can actually separate the pair, and says "then retune"
413
+ * when a band or stop change merely makes a retune possible rather
414
+ * than separating the pair on its own. The built-in warning is
415
+ * normal-vision-only; status meanings need redundant cues (icons,
416
+ * labels) regardless, though lightness and chroma separation chosen
417
+ * here can still genuinely help color-vision-deficient users — see
418
+ * ADR-004's amendment and the data-color guidance.
419
+ *
420
+ * @example
421
+ * ```jsonc
422
+ * "intents": { "info": "anchor:sky", "danger": "#700007" }
423
+ * ```
424
+ */
425
+ intents: ThemeIntents;
368
426
  /**
369
427
  * Per-variant chroma overrides (OKLCH chroma, 0–0.4).
370
428
  *
@@ -489,10 +547,12 @@ export declare const TOKEN_PAIRINGS: Readonly<Record<"actionText", TokenPairing>
489
547
  export declare const SEMANTIC_COLOR_NAMES: readonly SemanticColorName[];
490
548
  /** Valid color-source identifiers for {@link SemanticMapping.source}. */
491
549
  export declare const COLOR_SOURCES: readonly ColorSource[];
550
+ /** The four fixed status families, matching {@link StatusColorSource}. */
551
+ export declare const STATUS_COLOR_SOURCES: readonly StatusColorSource[];
492
552
  /**
493
553
  * Non-primary color sources that support independent chroma overrides.
494
554
  *
495
- * Matches the ten entries in {@link VariantColorSource}.
555
+ * Matches the eleven entries in {@link VariantColorSource}.
496
556
  */
497
557
  export declare const VARIANT_COLOR_SOURCES: readonly VariantColorSource[];
498
558
  /** Valid keys for the lightness ramp. */
@@ -587,13 +647,26 @@ export declare function encodeTheme(partial: PartialTheme): string;
587
647
  * @returns A new fully-resolved {@link EspalierTheme}.
588
648
  */
589
649
  export declare function mergeTheme(defaults: EspalierTheme, overrides: PartialTheme): EspalierTheme;
650
+ /**
651
+ * Validate a single encoded theme partial.
652
+ *
653
+ * Structural grammar aside, the advisory checks (the status-collision
654
+ * warning and chroma-band provenance) resolve the partial against
655
+ * {@link DEFAULT_LIGHT_THEME}. A partial written for the dark side of a
656
+ * pair should be validated through {@link validateThemePair}, which
657
+ * audits it against the dark defaults instead.
658
+ */
590
659
  export declare function validateTheme(base64: string): ThemeValidationResult;
591
660
  /**
592
661
  * Validate the light and dark partials that form one scheme-paired theme.
593
662
  *
594
- * Each partial first passes through {@link validateTheme}. Once both are
595
- * structurally valid, their context-name sets must match exactly so a stable
596
- * `context` attribute cannot silently change meaning when the scheme changes.
663
+ * Each side runs the same validation as {@link validateTheme}, with one
664
+ * scheme-aware difference: the dark partial's advisory checks resolve
665
+ * against {@link DEFAULT_DARK_THEME}, so a collision that only appears
666
+ * through the dark ramp is caught. Once both sides are structurally
667
+ * valid, their context-name sets must match exactly so a stable
668
+ * `context` attribute cannot silently change meaning when the scheme
669
+ * changes.
597
670
  */
598
671
  export declare function validateThemePair(lightBase64: string, darkBase64: string): ThemeValidationResult;
599
672
  /**
@@ -601,7 +674,7 @@ export declare function validateThemePair(lightBase64: string, darkBase64: strin
601
674
  * and therefore need key-by-key merging instead of wholesale
602
675
  * replacement when combining two {@link PartialTheme} objects.
603
676
  */
604
- export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "contexts", "dataPalette", "dataRamps", "roles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
677
+ export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "contexts", "dataPalette", "dataRamps", "intents", "roles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
605
678
  /**
606
679
  * Deep-merge two {@link PartialTheme} objects.
607
680
  *
@@ -1 +1 @@
1
- import{ACCEPTED_COLOR_FORMS as I,apcaContrast as pe,deriveSemantic as me,parseCssColor as O,parseOklch as ge,serializeOklch as de}from"./color-engine.js";import{computeVariants as he,parseAnchorSource as ye,resolveAnchorColor as be,resolveMappingSource as $e}from"./variant-engine.js";import{auditDataPalette as xe,DATA_SERIES_KEYS as P,DEFAULT_DATA_PALETTE as F,DEFAULT_DATA_RAMP_STEPS as ke,MAX_DATA_RAMP_STEPS as W,MIN_DATA_RAMP_LIGHTNESS_STEP as Y,MIN_DATA_RAMP_STEPS as j}from"./data-colors.js";const A=/^[a-z][a-z0-9-]*$/;function X(e){return ye(e)}function Se(e,t){return be(e,t)}function Ae(e,t){const r=X(e);if(r){const s=Se(t,r);return s&&O(s)?s:null}return O(e)?e:null}const H=["canvas","ink","accent","action","structure"],Z={canvas:{color:[["background","surface"],["layer1","raised1"],["layer2","raised2"],["layer3","raised3"],["layer4","raised4"]]},ink:{color:[["text","text"],["inputSelection","text"]],heading:[["headings","muted"],["headingsHover","ink"]]},accent:{color:[["linkHoverBg","raised2"],["inputSelectionBg","raised2"],["inputCaret","ink"]],text:[["link","accent"],["linkHover","text"]]},action:{color:[["actionBackground","muted"]],ink:[["actionText","surface"]]},structure:{color:[["border","border"],["shadow","shadow"]]}},Re=new Set(["action.color"]),Oe={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},Ce={"action.ink":{role:"canvas",slot:"color"}},ve=.45;function Q(e,t){const r=te.actionText,s=[...R].sort((p,y)=>e[p]-e[y]||R.indexOf(p)-R.indexOf(y)),a=t?s.filter(p=>t(p)>=r.targetLc):s,u=a.length>0?a:s;let l,m=1/0;for(const p of u){const y=Math.abs(e[p]-ve);y<m&&(m=y,l=p)}return l??"muted"}function Me(e,t){const r=t[e]>.5;let s=R[0];for(const a of R)(r?t[a]<t[s]:t[a]>t[s])&&(s=a);return s}function L(e,t){if(e===void 0)return;if(typeof e=="string")return t==="color"?e:void 0;const r=e[t];return typeof r=="string"?r:void 0}function ee(e,t,r,s={}){const a={},u={};for(const[l,m]of Object.entries(s.explicitMappings??{}))m!==void 0&&(u[l]=m.lightness);for(const l of H){const m=e[l];if(m!==void 0)for(const[p,y]of Object.entries(Z[l])){const b=Ce[`${l}.${p}`];let h=L(m,p),n=!1;if(h===void 0&&(b&&(h=L(e[b.role],b.slot),h??=r[Oe[b.role]]?.source,n=h!==void 0),h??=L(m,"color")),h!==void 0)for(const[o,c]of y){let i=c;if(Re.has(`${l}.${p}`))i=Q(t,s.actionSurfaceContrast?f=>s.actionSurfaceContrast(h,f):void 0);else if(n&&b){const f=te[o],d=(f&&u[f.bg])??Q(t,s.actionSurfaceContrast?k=>s.actionSurfaceContrast(L(m,"color"),k):void 0);i=Me(d,t)}a[o]={source:h,lightness:i}}}}return a}const te={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},z=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],K=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],Te=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning"],R=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],Ee={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},Be={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},U={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},B=.4;function G(){const e={};for(const t of z)e[t]={min:0,max:B};return e}const ne={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90},variantChroma:{},chroma:G(),semanticMappings:{...U},anchors:{},roles:{},contexts:{},dataPalette:{...F},dataRamps:{}},oe={...ne,chroma:G(),semanticMappings:{...U},anchors:{},roles:{},contexts:{},dataPalette:{...F},dataRamps:{},lightness:{...Ee}},we={...ne,chroma:G(),semanticMappings:{...U},anchors:{},roles:{},contexts:{},dataPalette:{...F},dataRamps:{},lightness:{...Be}},D=new WeakMap;D.set(oe,new Set),D.set(we,new Set);const se=new Set(["__proto__","constructor","prototype"]);function g(e){return!se.has(e)}function _e(e,t){return se.has(e)?void 0:t}function Ve(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function Ie(e){try{const t=atob(e),r=JSON.parse(t,_e);return typeof r!="object"||r===null||Array.isArray(r)?null:r}catch{return null}}function V(e){return btoa(JSON.stringify(e))}function N(e){if(ge(e))return e;const t=O(e);return t?de(t):e}function re(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&(r[s]=a);if(!t)return r;for(const[s,a]of Object.entries(t)){if(a===void 0||!g(s))continue;const u=r[s];if(u!==void 0&&typeof a=="object"&&a!==null){const l={};if(typeof u=="string")l.color=u;else for(const[m,p]of Object.entries(u))g(m)&&(l[m]=p);for(const[m,p]of Object.entries(a))p!==void 0&&g(m)&&(l[m]=p);r[s]=l;continue}r[s]=a}return r}function ae(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const t=e,r={};for(const s of H){const a=t[s];a!==void 0&&(r[s]=a)}if(typeof t.lightness=="object"&&t.lightness!==null&&!Array.isArray(t.lightness)){const s={};for(const a of R){const u=t.lightness[a];u!==void 0&&(s[a]=u)}r.lightness=s}return r}function Pe(e,t){const r={};for(const[s,a]of Object.entries(e)){if(!g(s)||!A.test(s))continue;const u=ae(a);u&&(r[s]=u)}if(!t)return r;for(const[s,a]of Object.entries(t)){if(!g(s)||!A.test(s)||a===void 0)continue;const u=ae(a);if(!u)continue;const l=r[s];r[s]={...l??{},...u,...l?.lightness||u.lightness?{lightness:{...l?.lightness,...u.lightness}}:{}}}return r}function v(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function M(e){const t={};for(const[r,s]of Object.entries(e))s!==void 0&&g(r)&&(t[r]=s);return t}function ie(e){if(!v(e))return e;const t=M(e);return v(e.lightness)&&(t.lightness=M(e.lightness)),t}function He(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&(r[s]=ie(a));if(!t)return r;for(const[s,a]of Object.entries(t)){if(!g(s)||a===void 0)continue;const u=r[s];if(!v(u)||!v(a)){r[s]=ie(a);continue}const l={...M(u),...M(a)};v(u.lightness)&&v(a.lightness)?l.lightness={...M(u.lightness),...M(a.lightness)}:v(a.lightness)&&(l.lightness=M(a.lightness)),r[s]=l}return r}function Le(e){const t={};for(const[r,s]of Object.entries(e)){if(!g(r))continue;if(typeof s=="string"){t[r]=N(s);continue}const a={};for(const[u,l]of Object.entries(s))g(u)&&(a[u]=typeof l=="string"?N(l):l);t[r]=a}return t}function w(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:N(e)}function De(e){const t={};for(const r of P)t[r]=w(e[r]);return t}function ce(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&A.test(s)&&a&&typeof a=="object"&&!Array.isArray(a)&&(r[s]={...a});if(!t)return r;for(const[s,a]of Object.entries(t)){if(!g(s)||!A.test(s)||!a||typeof a!="object"||Array.isArray(a))continue;const u=r[s],l=u!==void 0&&a.type!==void 0&&a.type!==u.type;r[s]={...l?{}:u??{},...a}}return r}function Ne(e){const t={};for(const[r,s]of Object.entries(e))if(g(r)){if(s.type==="sequential"&&typeof s.source=="string"){t[r]={...s,source:w(s.source)};continue}if(s.type==="diverging"&&typeof s.start=="string"&&typeof s.end=="string"){t[r]={...s,start:w(s.start),end:w(s.end),...typeof s.neutral=="string"?{neutral:w(s.neutral)}:{}};continue}t[r]={...s}}return t}function ue(e){const t=O(e.seedColor);if(!t)return;const r=he(t,e);return(s,a)=>{const u=$e(s,r,e.anchors)??r.primary,l=e.chroma.actionBackground,m=me(u,e.lightness[a],l.min,l.max),p={l:m.l>.5?0:1,c:0,h:0};return Math.abs(pe(p,m))}}function Fe(e){const t=D.get(e);if(t)return new Set(t);const r=new Set,s=ee(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:ue(e)});for(const[a,u]of Object.entries(s)){const l=e.semanticMappings[a];(l.source!==u.source||l.lightness!==u.lightness)&&r.add(a)}return r}function We(e,t){const r={...e.roles,...t.roles},s=Pe(e.contexts,t.contexts),a={...e.lightness,...t.lightness},u=Le(re(e.anchors,t.anchors)),l=typeof t.seedColor=="string"?N(t.seedColor):e.seedColor,m=t.semanticMappings,p={...e.angles,...t.angles},y={...e.semanticHues,...t.semanticHues},b={...e.variantChroma,...t.variantChroma},h=_(e.chroma,t.chroma),n=De(_(e.dataPalette,t.dataPalette)),o=Ne(ce(e.dataRamps,t.dataRamps)),c=Fe(e),i=new Set(c),f={};for(const x of c)f[x]=e.semanticMappings[x];for(const[x,T]of Object.entries(m??{}))T!==void 0&&(i.add(x),f[x]=T);const d=_(e.semanticMappings,m),k=ue({angles:p,anchors:u,chroma:h,lightness:a,seedColor:l,semanticHues:y,variantChroma:b}),S=ee(r,a,d,{explicitMappings:f,actionSurfaceContrast:k}),E={};for(const[x,T]of Object.entries(S))i.has(x)||(E[x]=T);const C=_(_(e.semanticMappings,E),m),$={...e,seedColor:l,fontBody:t.fontBody??e.fontBody,fontHeadings:t.fontHeadings??e.fontHeadings,fontBrand:t.fontBrand??e.fontBrand,fontMonospace:t.fontMonospace??e.fontMonospace,fontWeightBody:String(t.fontWeightBody??e.fontWeightBody),fontWeightHeadings:String(t.fontWeightHeadings??e.fontWeightHeadings),fontWeightBrand:String(t.fontWeightBrand??e.fontWeightBrand),fontWeightMonospace:String(t.fontWeightMonospace??e.fontWeightMonospace),stylesheets:t.stylesheets??[...e.stylesheets],rootFontSize:t.rootFontSize??e.rootFontSize,typeRatio:t.typeRatio??e.typeRatio,spaceRatio:t.spaceRatio??e.spaceRatio,borderRadius:t.borderRadius??e.borderRadius,viewportMin:t.viewportMin??e.viewportMin,viewportMax:t.viewportMax??e.viewportMax,angles:p,semanticHues:y,variantChroma:b,lightness:a,chroma:h,semanticMappings:C,anchors:u,roles:r,contexts:s,dataPalette:n,dataRamps:o};return t.pageBackgroundImage!==void 0&&($.pageBackgroundImage=t.pageBackgroundImage),t.pageBackgroundImageOpacity!==void 0&&($.pageBackgroundImageOpacity=t.pageBackgroundImageOpacity),t.boxBackgroundImage!==void 0&&($.boxBackgroundImage=t.boxBackgroundImage),t.boxBackgroundImageOpacity!==void 0&&($.boxBackgroundImageOpacity=t.boxBackgroundImageOpacity),t.vellumOpacity!==void 0&&($.vellumOpacity=t.vellumOpacity),t.vellumBackgroundImage!==void 0&&($.vellumBackgroundImage=t.vellumBackgroundImage),t.vellumBackgroundImageOpacity!==void 0&&($.vellumBackgroundImageOpacity=t.vellumBackgroundImageOpacity),D.set($,new Set(i)),$}function _(e,t){if(!t)return{...e};const r={...e};for(const s of Object.keys(t)){const a=t[s];a!==void 0&&(r[s]=a)}return r}function J(e){let t;try{t=atob(e)}catch{return{error:"Failed to decode Base64 string."}}let r;try{r=JSON.parse(t)}catch{return{error:"Decoded string is not valid JSON."}}return typeof r!="object"||r===null||Array.isArray(r)?{error:"Theme must be a JSON object."}:{value:r}}function Je(e){const t=J(e);return t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:q(t.value)}function q(e){const t=[],r=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):O(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${I}.`));for(const n of["fontBody","fontHeadings","fontBrand","fontMonospace"])n in e&&typeof e[n]!="string"&&t.push(`${n} must be a string.`);const s=["normal","bold","lighter","bolder"],a=["inherit","initial","unset","revert","revert-layer"];for(const n of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(n in e){const o=e[n];if(typeof o=="number")(o<1||o>1e3)&&t.push(`${n} numeric value must be 1\u20131000 (got ${o}).`);else if(typeof o=="string"){const c=s.includes(o)||a.includes(o);if(/^\d+$/.test(o)){const f=Number(o);(f<1||f>1e3)&&t.push(`${n} numeric value must be 1\u20131000 (got "${o}").`)}else c||r.push(`${n} = "${o}" is not a standard font-weight value.`)}else t.push(`${n} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(n=>typeof n!="string")&&t.push("Every entry in stylesheets must be a string."):t.push("stylesheets must be an array of strings."));const u=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[n,o,c]of u)if(n in e)if(typeof e[n]!="number"||!isFinite(e[n]))t.push(`${n} must be a finite number.`);else{const i=e[n];o!==void 0&&i<o&&t.push(`${n} must be \u2265 ${o} (got ${i}).`),c!==void 0&&i>c&&r.push(`${n} = ${i} is unusually high (max ${c}).`)}for(const n of["typeRatio","spaceRatio"])if(n in e)if(typeof e[n]!="number"||!isFinite(e[n]))t.push(`${n} must be a finite number.`);else{const o=e[n];o<=1&&t.push(`${n} must be > 1 (got ${o}).`);const c=n==="typeRatio"?1.3:2;o>c&&r.push(`${n} = ${o} is very high (max ${c}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const n=e.viewportMin,o=e.viewportMax;typeof n=="number"&&typeof o=="number"&&n>=o&&t.push(`viewportMin (${n}) must be less than viewportMax (${o}).`)}if("angles"in e)if(typeof e.angles!="object"||e.angles===null)t.push("angles must be an object.");else{const n=e.angles;for(const o of["analogous","complementary","splitComplementary","triadic"])if(o in n)if(typeof n[o]!="number"||!isFinite(n[o]))t.push(`angles.${o} must be a finite number.`);else{const c=n[o];(c<0||c>360)&&r.push(`angles.${o} = ${c} is outside 0\u2013360.`)}}if("semanticHues"in e)if(typeof e.semanticHues!="object"||e.semanticHues===null)t.push("semanticHues must be an object.");else{const n=e.semanticHues;for(const o of["danger","success","warning"])if(o in n)if(typeof n[o]!="number"||!isFinite(n[o]))t.push(`semanticHues.${o} must be a finite number.`);else{const c=n[o];(c<0||c>360)&&r.push(`semanticHues.${o} = ${c} is outside 0\u2013360.`)}}if("variantChroma"in e)if(typeof e.variantChroma!="object"||e.variantChroma===null)t.push("variantChroma must be an object.");else{const n=e.variantChroma;for(const o of Te)if(o in n)if(typeof n[o]!="number"||!isFinite(n[o]))t.push(`variantChroma["${o}"] must be a finite number.`);else{const c=n[o];c<0&&t.push(`variantChroma["${o}"] must be \u2265 0 (got ${c}).`),c>B&&r.push(`variantChroma["${o}"] = ${c} exceeds ${B}.`)}}function l(n,o){if(typeof n!="object"||n===null||Array.isArray(n)){t.push(`${o} must be an object.`);return}const c=n;for(const i of R)if(i in c)if(typeof c[i]!="number"||!isFinite(c[i]))t.push(`${o}.${i} must be a finite number.`);else{const f=c[i];(f<0||f>1)&&t.push(`${o}.${i} must be 0\u20131 (got ${f}).`)}}if("lightness"in e&&l(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const n=e.chroma;for(const o of z)if(o in n){const c=n[o];if(typeof c!="object"||c===null){t.push(`chroma.${o} must be { min, max }.`);continue}const i=c;(typeof i.min!="number"||i.min<0)&&t.push(`chroma.${o}.min must be \u2265 0.`),(typeof i.max!="number"||i.max<0||i.max>B)&&t.push(`chroma.${o}.max must be 0\u2013${B}.`),typeof i.min=="number"&&typeof i.max=="number"&&i.min>i.max&&t.push(`chroma.${o}.min (${i.min}) must be \u2264 max (${i.max}).`)}}if("anchors"in e)if(typeof e.anchors!="object"||e.anchors===null||Array.isArray(e.anchors))t.push("anchors must be an object of named colors.");else for(const[n,o]of Object.entries(e.anchors))if(g(n)?A.test(n)||t.push(`anchors: "${n}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${n}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),K.includes(n)&&t.push(`anchors: "${n}" collides with a reserved color source name.`),typeof o=="string")O(o)||t.push(`anchors.${n} is not a valid CSS color: "${o}". Accepted forms: ${I}.`);else if(typeof o=="object"&&o!==null&&!Array.isArray(o)){const c=o;typeof c.color!="string"&&t.push(`anchors.${n} must declare its base "color".`);for(const[i,f]of Object.entries(c))g(i)?i!=="color"&&!A.test(i)&&t.push(`anchors.${n}: "${i}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${n}: "${i}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof f!="string"?t.push(`anchors.${n}.${i} must be a CSS color string.`):O(f)||t.push(`anchors.${n}.${i} is not a valid CSS color: "${f}". Accepted forms: ${I}.`)}else t.push(`anchors.${n} must be a color string or a { color, \u2026slots } object.`);const m=new Map;if("anchors"in e&&typeof e.anchors=="object"&&e.anchors!==null&&!Array.isArray(e.anchors))for(const[n,o]of Object.entries(e.anchors))m.set(n,o);function p(n,o){const c=X(n);if(!c){t.push(`${o} "${n}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!m.has(c.name)){const i=[...m.keys()];t.push(`${o} references undeclared anchor "${c.name}". Declared anchors: ${i.length>0?i.join(", "):"(none)"}.`);return}if(c.slot!==void 0){const i=m.get(c.name);if(typeof(typeof i=="object"&&i!==null&&!Array.isArray(i)?i[c.slot]:void 0)!="string"){const d=typeof i=="object"&&i!==null?Object.keys(i).filter(k=>k!=="color"):[];t.push(`${o} references unknown slot "${c.slot}" on anchor "${c.name}". Declared slots: ${d.length>0?d.join(", "):"(none)"}.`)}}}function y(n,o){if(n.startsWith("anchor:")){p(n,o);return}K.includes(n)||t.push(`${o} must be one of: ${K.join(", ")}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}function b(n,o){if(n.startsWith("anchor:")){p(n,o);return}O(n)||t.push(`${o} is not a valid CSS color: "${n}". Accepted forms: ${I}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("dataPalette"in e)if(typeof e.dataPalette!="object"||e.dataPalette===null||Array.isArray(e.dataPalette))t.push("dataPalette must be an object with series1\u2013series8 color values.");else{const n=e.dataPalette;for(const[o,c]of Object.entries(n)){if(!P.includes(o)){t.push(`dataPalette.${o} is not a series slot; expected one of: ${P.join(", ")}.`);continue}typeof c!="string"?t.push(`dataPalette.${o} must be a CSS color or anchor reference string.`):b(c,`dataPalette.${o}`)}}if("dataRamps"in e)if(typeof e.dataRamps!="object"||e.dataRamps===null||Array.isArray(e.dataRamps))t.push("dataRamps must be an object of named ramp declarations.");else for(const[n,o]of Object.entries(e.dataRamps)){if(g(n)?A.test(n)||t.push(`dataRamps: "${n}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${n}" is a reserved JavaScript property name and cannot be a ramp name; rename it.`),typeof o!="object"||o===null||Array.isArray(o)){t.push(`dataRamps.${n} must be a sequential or diverging ramp object.`);continue}const c=o,i=c.steps??ke;if((typeof i!="number"||!Number.isInteger(i)||i<j||i>W)&&t.push(`dataRamps.${n}.steps must be an integer from ${j} through ${W}.`),c.type==="sequential"){typeof c.source!="string"?t.push(`dataRamps.${n}.source must be a CSS color or anchor reference string.`):b(c.source,`dataRamps.${n}.source`);const f=c.lightnessStart??.95,d=c.lightnessEnd??.25;for(const[k,S]of[["lightnessStart",f],["lightnessEnd",d]])(typeof S!="number"||!Number.isFinite(S)||S<0||S>1)&&t.push(`dataRamps.${n}.${k} must be a finite number from 0 through 1.`);typeof f=="number"&&typeof d=="number"&&f<=d?t.push(`dataRamps.${n}.lightnessStart must be greater than lightnessEnd.`):typeof f=="number"&&Number.isFinite(f)&&typeof d=="number"&&Number.isFinite(d)&&typeof i=="number"&&Number.isInteger(i)&&i>=j&&i<=W&&(f-d)/(i-1)<=Y&&t.push(`dataRamps.${n} lightness bounds must leave more than ${Y} lightness between serialized stops.`);continue}if(c.type==="diverging"){typeof i=="number"&&Number.isInteger(i)&&i%2===0&&t.push(`dataRamps.${n}.steps must be odd so the neutral is the exact midpoint.`);for(const f of["start","end"])typeof c[f]!="string"?t.push(`dataRamps.${n}.${f} must be a CSS color or anchor reference string.`):b(c[f],`dataRamps.${n}.${f}`);"neutral"in c&&(typeof c.neutral!="string"?t.push(`dataRamps.${n}.neutral must be a CSS color or anchor reference string.`):b(c.neutral,`dataRamps.${n}.neutral`));continue}t.push(`dataRamps.${n}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const n=We(oe,e),o={};let c=!0;for(const i of P){const f=Ae(n.dataPalette[i],n.anchors);if(!f){c=!1;break}o[i]=f}if(c)for(const i of xe(o))r.push(`dataPalette.${i.series[0]} and dataPalette.${i.series[1]} are only ${i.distance.toFixed(4)} apart under ${i.simulation} simulation (minimum ${i.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function h(n,o){if(typeof n!="object"||n===null||Array.isArray(n)){t.push(`${o} must be an object.`);return}const c=n;for(const[i,f]of Object.entries(c)){const d=`${o}.${i}`;if(!H.includes(i)){t.push(`${d} is not a role; expected one of: ${H.join(", ")}. (The status family is reserved and is not a role.)`);continue}const k=i,S=Z[k];if(typeof f=="string"){y(f,d);continue}if(typeof f!="object"||f===null||Array.isArray(f)){t.push(`${d} must be a color source or a { color, \u2026slots } object.`);continue}const E=f;typeof E.color!="string"&&t.push(`${d} must declare its base "color".`);for(const[C,$]of Object.entries(E)){if(!Object.prototype.hasOwnProperty.call(S,C)||!g(C)){const x=Object.keys(S).filter(T=>T!=="color");t.push(`${d}.${C} is not a slot of the ${k} role. Declared slots: ${x.length>0?x.join(", "):"(none)"}.`);continue}typeof $!="string"?t.push(`${d}.${C} must be a color source string.`):y($,`${d}.${C}`)}}}if("roles"in e&&h(e.roles,"roles"),"contexts"in e)if(typeof e.contexts!="object"||e.contexts===null||Array.isArray(e.contexts))t.push("contexts must be an object.");else for(const[n,o]of Object.entries(e.contexts)){if(!g(n)||!A.test(n)){t.push(`contexts.${n} must be a lowercase slug matching ${A.source}.`);continue}if(typeof o!="object"||o===null||Array.isArray(o)){h(o,`contexts.${n}`);continue}const c=o,i=Object.fromEntries(Object.entries(c).filter(([f])=>f!=="lightness"));h(i,`contexts.${n}`),"lightness"in c&&l(c.lightness,`contexts.${n}.lightness`)}if("semanticMappings"in e)if(typeof e.semanticMappings!="object"||e.semanticMappings===null)t.push("semanticMappings must be an object.");else{const n=e.semanticMappings;for(const o of z)if(o in n){const c=n[o];if(typeof c!="object"||c===null){t.push(`semanticMappings.${o} must be { source, lightness }.`);continue}const i=c;typeof i.source!="string"?t.push(`semanticMappings.${o}.source must be a string.`):y(i.source,`semanticMappings.${o}.source`),(typeof i.lightness!="string"||!R.includes(i.lightness))&&t.push(`semanticMappings.${o}.lightness must be one of: ${R.join(", ")}.`)}}for(const n of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])n in e&&typeof e[n]!="string"&&t.push(`${n} must be a string.`);for(const n of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(n in e)if(typeof e[n]!="number"||!isFinite(e[n]))t.push(`${n} must be a finite number.`);else{const o=e[n];(o<0||o>1)&&t.push(`${n} must be 0\u20131 (got ${o}).`)}return{valid:t.length===0,errors:t,warnings:r}}function qe(e,t){const r=J(e),s=J(t),a=r.error!==void 0?{valid:!1,errors:[r.error],warnings:[]}:q(r.value),u=s.error!==void 0?{valid:!1,errors:[s.error],warnings:[]}:q(s.value),l=[...a.errors.map(p=>`light: ${p}`),...u.errors.map(p=>`dark: ${p}`)],m=[...a.warnings.map(p=>`light: ${p}`),...u.warnings.map(p=>`dark: ${p}`)];if(a.valid&&u.valid){const p=new Set(Object.keys(r.value?.contexts??{})),y=new Set(Object.keys(s.value?.contexts??{})),b=[...y].filter(n=>!p.has(n)).sort(),h=[...p].filter(n=>!y.has(n)).sort();(b.length>0||h.length>0)&&l.push(`contexts must declare the same names in both schemes. Missing from light: ${b.join(", ")||"(none)"}. Missing from dark: ${h.join(", ")||"(none)"}.`)}return{valid:l.length===0,errors:l,warnings:m}}const je=["anchors","angles","contexts","dataPalette","dataRamps","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function ze(e,t){const r={};for(const[s,a]of Object.entries(e))g(s)&&(r[s]=a);for(const[s,a]of Object.entries(t))a!==void 0&&g(s)&&(r[s]=a);for(const s of je){const a=e[s],u=t[s];if(a&&typeof a=="object"&&!Array.isArray(a)&&u&&typeof u=="object"&&!Array.isArray(u)){if(s==="anchors"){r[s]=re(a,u);continue}if(s==="contexts"){r[s]=He(a,u);continue}if(s==="dataRamps"){r[s]=ce(a,u);continue}const l={};for(const[m,p]of Object.entries(a))g(m)&&(l[m]=p);for(const[m,p]of Object.entries(u))p!==void 0&&g(m)&&(l[m]=p);r[s]=l}}return r}function Ye(...e){let t={};for(const r of e){if(!r)continue;const s=Ie(r);s&&(t=ze(t,s))}return V(t)}function le(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const fe={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function Xe(e){return V({...fe,pageBackgroundImage:`url("${le(e)}")`,pageBackgroundImageOpacity:.5})}function Ze(e){return V({...fe,pageBackgroundImage:`url("${le(e)}")`,pageBackgroundImageOpacity:.55})}export{A as ANCHOR_SLUG_PATTERN,K as COLOR_SOURCES,Be as DEFAULT_DARK_LIGHTNESS,we as DEFAULT_DARK_THEME,Ee as DEFAULT_LIGHT_LIGHTNESS,oe as DEFAULT_LIGHT_THEME,U as DEFAULT_SEMANTIC_MAPPINGS,R as LIGHTNESS_KEYS,je as NESTED_THEME_KEYS,H as ROLE_NAMES,Ce as ROLE_PAIRED_INK,Z as ROLE_TOKEN_PLAN,z as SEMANTIC_COLOR_NAMES,te as TOKEN_PAIRINGS,Te as VARIANT_COLOR_SOURCES,Ze as buildTaprootDarkTheme,Xe as buildTaprootLightTheme,ee as compileRoles,V as encodeTheme,Ye as layerThemes,ze as mergePartials,We as mergeTheme,X as parseAnchorSource,Ie as parseTheme,Se as resolveAnchorColor,Ae as resolveDataColorSource,Ve as semanticToCSS,Je as validateTheme,qe as validateThemePair};
1
+ import{ACCEPTED_COLOR_FORMS as ee,apcaContrast as et,clampChannel as le,deriveSemantic as we,gamutMapToSRGB as fe,linearRgbToOklab as tt,oklchToSRGB as nt,parseCssColor as N,parseOklch as ot,serializeOklch as ae,srgbToLinearRGB as st}from"./color-engine.js";import{computeVariants as Te,parseAnchorSource as rt,resolveAnchorColor as at,resolveMappingSource as Ee}from"./variant-engine.js";import{auditColorDistances as _e,auditDataPalette as it,DATA_SERIES_KEYS as ie,DEFAULT_DATA_PALETTE as pe,DEFAULT_DATA_RAMP_STEPS as ct,MAX_DATA_RAMP_STEPS as me,MIN_DATA_RAMP_LIGHTNESS_STEP as Ie,MIN_DATA_RAMP_STEPS as he}from"./data-colors.js";const z=/^[a-z][a-z0-9-]*$/;function de(e){return rt(e)}function Le(e,n){return at(e,n)}function ut(e,n){const t=de(e);if(t){const s=Le(n,t);return s&&N(s)?s:null}return N(e)?e:null}const Z=["canvas","ink","accent","action","structure"],He={canvas:{color:[["background","surface"],["layer1","raised1"],["layer2","raised2"],["layer3","raised3"],["layer4","raised4"]]},ink:{color:[["text","text"],["inputSelection","text"]],heading:[["headings","muted"],["headingsHover","ink"]]},accent:{color:[["linkHoverBg","raised2"],["inputSelectionBg","raised2"],["inputCaret","ink"]],text:[["link","accent"]],hover:[["linkHover","text"]]},action:{color:[["actionBackground","muted"]],ink:[["actionText","surface"]]},structure:{color:[["border","border"],["shadow","shadow"]]}},lt=new Set(["action.color"]),ft={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},pt={"action.ink":{role:"canvas",slot:"color"}},mt=.45;function Pe(e,n){const t=Ne.actionText,s=[...U].sort((p,S)=>e[p]-e[S]||U.indexOf(p)-U.indexOf(S)),a=n?s.filter(p=>n(p)>=t.targetLc):s,u=a.length>0?a:s;let f,h=1/0;for(const p of u){const S=Math.abs(e[p]-mt);S<h&&(h=S,f=p)}return f??"muted"}function ht(e,n){const t=n[e]>.5;let s=U[0];for(const a of U)(t?n[a]<n[s]:n[a]>n[s])&&(s=a);return s}const dt={"accent.hover":"text"};function gt(e,n){const t=new Map;try{const s=se(n,e),a=(u,f,h,p)=>{const S=de(f),$=S?Le(p,S):null,x=$===null?null:N($),C=t.get(u)??[];C.some(o=>o.source===f&&o.chroma===x?.c)||(C.push({source:f,where:h,chroma:x?.c}),t.set(u,C))};for(const[u,f]of Object.entries(s.semanticMappings))f.source.startsWith("anchor:")&&a(u,f.source,"the root table",s.anchors);for(const[u,f]of Object.entries(s.contexts)){const h={};for(const S of Z){const $=f[S];$!==void 0&&(h[S]=$)}const p=se(s,{lightness:f.lightness,roles:h});for(const[S,$]of Object.entries(p.semanticMappings))$.source.startsWith("anchor:")&&a(S,$.source,`contexts.${u}`,p.anchors)}}catch{return new Map}return t}function te(e,n){if(e===void 0)return;if(typeof e=="string")return n==="color"?e:void 0;const t=e[n];return typeof t=="string"?t:void 0}function De(e,n,t,s={}){const a={},u={};for(const[f,h]of Object.entries(s.explicitMappings??{}))h!==void 0&&(u[f]=h.lightness);for(const f of Z){const h=e[f];if(h!==void 0)for(const[p,S]of Object.entries(He[f])){const $=pt[`${f}.${p}`];let x=te(h,p),C=!1;if(x===void 0){$&&(x=te(e[$.role],$.slot),x??=t[ft[$.role]]?.source,C=x!==void 0);const o=dt[`${f}.${p}`];o!==void 0&&(x??=te(h,o)),x??=te(h,"color")}if(x!==void 0)for(const[o,r]of S){let i=r;if(lt.has(`${f}.${p}`))i=Pe(n,s.actionSurfaceContrast?c=>s.actionSurfaceContrast(x,c):void 0);else if(C&&$){const c=Ne[o],m=(c&&u[c.bg])??Pe(n,s.actionSurfaceContrast?y=>s.actionSurfaceContrast(te(h,"color"),y):void 0);i=ht(m,n)}a[o]={source:x,lightness:i}}}}return a}const Ne={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},ge=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],ye=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],Q=["danger","success","warning","info"],yt=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],U=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],bt={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},$t={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},be={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},G=.4;function $e(){const e={};for(const n of ge)e[n]={min:0,max:G};return e}const Fe={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90,info:244},variantChroma:{},intents:{},chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{}},Se={...Fe,chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{},lightness:{...bt}},We={...Fe,chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{},lightness:{...$t}},ce=new WeakMap;ce.set(Se,new Set),ce.set(We,new Set);const je=new Set(["__proto__","constructor","prototype"]);function A(e){return!je.has(e)}function St(e,n){return je.has(e)?void 0:n}function Dt(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function xt(e){try{const n=atob(e),t=JSON.parse(n,St);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}function xe(e){return btoa(JSON.stringify(e))}function kt(e){const n={};for(const t of Q){const s=e[t];typeof s=="string"&&(n[t]=s.startsWith("anchor:")?s:ne(s))}return n}function ne(e){if(ot(e))return e;const n=N(e);return n?ae(n):e}function Ke(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&(t[s]=a);if(!n)return t;for(const[s,a]of Object.entries(n)){if(a===void 0||!A(s))continue;const u=t[s];if(u!==void 0&&typeof a=="object"&&a!==null){const f={};if(typeof u=="string")f.color=u;else for(const[h,p]of Object.entries(u))A(h)&&(f[h]=p);for(const[h,p]of Object.entries(a))p!==void 0&&A(h)&&(f[h]=p);t[s]=f;continue}t[s]=a}return t}function ze(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const n=e,t={};for(const s of Z){const a=n[s];a!==void 0&&(t[s]=a)}if(typeof n.lightness=="object"&&n.lightness!==null&&!Array.isArray(n.lightness)){const s={};for(const a of U){const u=n.lightness[a];u!==void 0&&(s[a]=u)}t.lightness=s}return t}function At(e,n){const t={};for(const[s,a]of Object.entries(e)){if(!A(s)||!z.test(s))continue;const u=ze(a);u&&(t[s]=u)}if(!n)return t;for(const[s,a]of Object.entries(n)){if(!A(s)||!z.test(s)||a===void 0)continue;const u=ze(a);if(!u)continue;const f=t[s];t[s]={...f??{},...u,...f?.lightness||u.lightness?{lightness:{...f?.lightness,...u.lightness}}:{}}}return t}function J(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Y(e){const n={};for(const[t,s]of Object.entries(e))s!==void 0&&A(t)&&(n[t]=s);return n}function Ue(e){if(!J(e))return e;const n=Y(e);return J(e.lightness)&&(n.lightness=Y(e.lightness)),n}function vt(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&(t[s]=Ue(a));if(!n)return t;for(const[s,a]of Object.entries(n)){if(!A(s)||a===void 0)continue;const u=t[s];if(!J(u)||!J(a)){t[s]=Ue(a);continue}const f={...Y(u),...Y(a)};J(u.lightness)&&J(a.lightness)?f.lightness={...Y(u.lightness),...Y(a.lightness)}:J(a.lightness)&&(f.lightness=Y(a.lightness)),t[s]=f}return t}function Rt(e){const n={};for(const[t,s]of Object.entries(e)){if(!A(t))continue;if(typeof s=="string"){n[t]=ne(s);continue}const a={};for(const[u,f]of Object.entries(s))A(u)&&(a[u]=typeof f=="string"?ne(f):f);n[t]=a}return n}function oe(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:ne(e)}function Ot(e){const n={};for(const t of ie)n[t]=oe(e[t]);return n}function Ge(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&z.test(s)&&a&&typeof a=="object"&&!Array.isArray(a)&&(t[s]={...a});if(!n)return t;for(const[s,a]of Object.entries(n)){if(!A(s)||!z.test(s)||!a||typeof a!="object"||Array.isArray(a))continue;const u=t[s],f=u!==void 0&&a.type!==void 0&&a.type!==u.type;t[s]={...f?{}:u??{},...a}}return t}function Ct(e){const n={};for(const[t,s]of Object.entries(e))if(A(t)){if(s.type==="sequential"&&typeof s.source=="string"){n[t]={...s,source:oe(s.source)};continue}if(s.type==="diverging"&&typeof s.start=="string"&&typeof s.end=="string"){n[t]={...s,start:oe(s.start),end:oe(s.end),...typeof s.neutral=="string"?{neutral:oe(s.neutral)}:{}};continue}n[t]={...s}}return n}function Ve(e){const n=N(e.seedColor);if(!n)return;const t=Te(n,e);return(s,a)=>{const u=Ee(s,t,e.anchors)??t.primary,f=e.chroma.actionBackground,h=we(u,e.lightness[a],f.min,f.max),p={l:h.l>.5?0:1,c:0,h:0};return Math.abs(et(p,h))}}function Mt(e){const n=ce.get(e);if(n)return new Set(n);const t=new Set,s=De(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:Ve(e)});for(const[a,u]of Object.entries(s)){const f=e.semanticMappings[a];(f.source!==u.source||f.lightness!==u.lightness)&&t.add(a)}return t}function se(e,n){const t={...e.roles,...n.roles},s=At(e.contexts,n.contexts),a={...e.lightness,...n.lightness},u=Rt(Ke(e.anchors,n.anchors)),f=typeof n.seedColor=="string"?ne(n.seedColor):e.seedColor,h=n.semanticMappings,p={...e.angles,...n.angles},S={...e.semanticHues,...n.semanticHues},$={...e.variantChroma,...n.variantChroma},x=kt({...e.intents,...n.intents}),C=re(e.chroma,n.chroma),o=Ot(re(e.dataPalette,n.dataPalette)),r=Ct(Ge(e.dataRamps,n.dataRamps)),i=Mt(e),c=new Set(i),m={};for(const g of i)m[g]=e.semanticMappings[g];for(const[g,b]of Object.entries(h??{}))b!==void 0&&(c.add(g),m[g]=b);const y=re(e.semanticMappings,h),I=Ve({angles:p,anchors:u,chroma:C,intents:x,lightness:a,seedColor:f,semanticHues:S,variantChroma:$}),D=De(t,a,y,{explicitMappings:m,actionSurfaceContrast:I}),W={};for(const[g,b]of Object.entries(D))c.has(g)||(W[g]=b);const l=re(re(e.semanticMappings,W),h),d={...e,seedColor:f,fontBody:n.fontBody??e.fontBody,fontHeadings:n.fontHeadings??e.fontHeadings,fontBrand:n.fontBrand??e.fontBrand,fontMonospace:n.fontMonospace??e.fontMonospace,fontWeightBody:String(n.fontWeightBody??e.fontWeightBody),fontWeightHeadings:String(n.fontWeightHeadings??e.fontWeightHeadings),fontWeightBrand:String(n.fontWeightBrand??e.fontWeightBrand),fontWeightMonospace:String(n.fontWeightMonospace??e.fontWeightMonospace),stylesheets:n.stylesheets??[...e.stylesheets],rootFontSize:n.rootFontSize??e.rootFontSize,typeRatio:n.typeRatio??e.typeRatio,spaceRatio:n.spaceRatio??e.spaceRatio,borderRadius:n.borderRadius??e.borderRadius,viewportMin:n.viewportMin??e.viewportMin,viewportMax:n.viewportMax??e.viewportMax,angles:p,semanticHues:S,variantChroma:$,intents:x,lightness:a,chroma:C,semanticMappings:l,anchors:u,roles:t,contexts:s,dataPalette:o,dataRamps:r};return n.pageBackgroundImage!==void 0&&(d.pageBackgroundImage=n.pageBackgroundImage),n.pageBackgroundImageOpacity!==void 0&&(d.pageBackgroundImageOpacity=n.pageBackgroundImageOpacity),n.boxBackgroundImage!==void 0&&(d.boxBackgroundImage=n.boxBackgroundImage),n.boxBackgroundImageOpacity!==void 0&&(d.boxBackgroundImageOpacity=n.boxBackgroundImageOpacity),n.vellumOpacity!==void 0&&(d.vellumOpacity=n.vellumOpacity),n.vellumBackgroundImage!==void 0&&(d.vellumBackgroundImage=n.vellumBackgroundImage),n.vellumBackgroundImageOpacity!==void 0&&(d.vellumBackgroundImageOpacity=n.vellumBackgroundImageOpacity),ce.set(d,new Set(c)),d}function re(e,n){if(!n)return{...e};const t={...e};for(const s of Object.keys(n)){const a=n[s];a!==void 0&&(t[s]=a)}return t}function ke(e){let n;try{n=atob(e)}catch{return{error:"Failed to decode Base64 string."}}let t;try{t=JSON.parse(n)}catch{return{error:"Decoded string is not valid JSON."}}return typeof t!="object"||t===null||Array.isArray(t)?{error:"Theme must be a JSON object."}:{value:t}}function Nt(e){const n=ke(e);return n.error!==void 0?{valid:!1,errors:[n.error],warnings:[]}:Ae(n.value)}function Ae(e,n=Se){const t=[],s=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):N(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${ee}.`));for(const o of["fontBody","fontHeadings","fontBrand","fontMonospace"])o in e&&typeof e[o]!="string"&&t.push(`${o} must be a string.`);const a=["normal","bold","lighter","bolder"],u=["inherit","initial","unset","revert","revert-layer"];for(const o of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(o in e){const r=e[o];if(typeof r=="number")(r<1||r>1e3)&&t.push(`${o} numeric value must be 1\u20131000 (got ${r}).`);else if(typeof r=="string"){const i=a.includes(r)||u.includes(r);if(/^\d+$/.test(r)){const m=Number(r);(m<1||m>1e3)&&t.push(`${o} numeric value must be 1\u20131000 (got "${r}").`)}else i||s.push(`${o} = "${r}" is not a standard font-weight value.`)}else t.push(`${o} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(o=>typeof o!="string")&&t.push("Every entry in stylesheets must be a string."):t.push("stylesheets must be an array of strings."));const f=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[o,r,i]of f)if(o in e)if(typeof e[o]!="number"||!isFinite(e[o]))t.push(`${o} must be a finite number.`);else{const c=e[o];r!==void 0&&c<r&&t.push(`${o} must be \u2265 ${r} (got ${c}).`),i!==void 0&&c>i&&s.push(`${o} = ${c} is unusually high (max ${i}).`)}for(const o of["typeRatio","spaceRatio"])if(o in e)if(typeof e[o]!="number"||!isFinite(e[o]))t.push(`${o} must be a finite number.`);else{const r=e[o];r<=1&&t.push(`${o} must be > 1 (got ${r}).`);const i=o==="typeRatio"?1.3:2;r>i&&s.push(`${o} = ${r} is very high (max ${i}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const o=e.viewportMin,r=e.viewportMax;typeof o=="number"&&typeof r=="number"&&o>=r&&t.push(`viewportMin (${o}) must be less than viewportMax (${r}).`)}if("angles"in e)if(typeof e.angles!="object"||e.angles===null)t.push("angles must be an object.");else{const o=e.angles;for(const r of["analogous","complementary","splitComplementary","triadic"])if(r in o)if(typeof o[r]!="number"||!isFinite(o[r]))t.push(`angles.${r} must be a finite number.`);else{const i=o[r];(i<0||i>360)&&s.push(`angles.${r} = ${i} is outside 0\u2013360.`)}}if("semanticHues"in e)if(typeof e.semanticHues!="object"||e.semanticHues===null)t.push("semanticHues must be an object.");else{const o=e.semanticHues;for(const r of["danger","success","warning","info"])if(r in o)if(typeof o[r]!="number"||!isFinite(o[r]))t.push(`semanticHues.${r} must be a finite number.`);else{const i=o[r];(i<0||i>360)&&s.push(`semanticHues.${r} = ${i} is outside 0\u2013360.`)}}if("variantChroma"in e)if(typeof e.variantChroma!="object"||e.variantChroma===null)t.push("variantChroma must be an object.");else{const o=e.variantChroma;for(const r of yt)if(r in o)if(typeof o[r]!="number"||!isFinite(o[r]))t.push(`variantChroma["${r}"] must be a finite number.`);else{const i=o[r];i<0&&t.push(`variantChroma["${r}"] must be \u2265 0 (got ${i}).`),i>G&&s.push(`variantChroma["${r}"] = ${i} exceeds ${G}.`)}}function h(o,r){if(typeof o!="object"||o===null||Array.isArray(o)){t.push(`${r} must be an object.`);return}const i=o;for(const c of U)if(c in i)if(typeof i[c]!="number"||!isFinite(i[c]))t.push(`${r}.${c} must be a finite number.`);else{const m=i[c];(m<0||m>1)&&t.push(`${r}.${c} must be 0\u20131 (got ${m}).`)}}if("lightness"in e&&h(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const o=e.chroma,r=gt(e,n);for(const i of ge)if(i in o){const c=o[i];if(typeof c!="object"||c===null){t.push(`chroma.${i} must be { min, max }.`);continue}const m=c;for(const I of r.get(i)??[])I.chroma!==void 0&&typeof m.min=="number"&&typeof m.max=="number"&&(I.chroma<m.min-1e-9||I.chroma>m.max+1e-9)&&s.push(`chroma.${i} clamps the anchor-sourced token ${i} ("${I.source}", effective in ${I.where}) and moves it off its declared swatch. Remove the band if that is unintended \u2014 anchors otherwise keep their own chroma.`);const y=c;(typeof y.min!="number"||y.min<0)&&t.push(`chroma.${i}.min must be \u2265 0.`),(typeof y.max!="number"||y.max<0||y.max>G)&&t.push(`chroma.${i}.max must be 0\u2013${G}.`),typeof y.min=="number"&&typeof y.max=="number"&&y.min>y.max&&t.push(`chroma.${i}.min (${y.min}) must be \u2264 max (${y.max}).`)}}if("anchors"in e)if(typeof e.anchors!="object"||e.anchors===null||Array.isArray(e.anchors))t.push("anchors must be an object of named colors.");else for(const[o,r]of Object.entries(e.anchors))if(A(o)?z.test(o)||t.push(`anchors: "${o}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${o}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),ye.includes(o)&&t.push(`anchors: "${o}" collides with a reserved color source name.`),typeof r=="string")N(r)||t.push(`anchors.${o} is not a valid CSS color: "${r}". Accepted forms: ${ee}.`);else if(typeof r=="object"&&r!==null&&!Array.isArray(r)){const i=r;typeof i.color!="string"&&t.push(`anchors.${o} must declare its base "color".`);for(const[c,m]of Object.entries(i))A(c)?c!=="color"&&!z.test(c)&&t.push(`anchors.${o}: "${c}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${o}: "${c}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof m!="string"?t.push(`anchors.${o}.${c} must be a CSS color string.`):N(m)||t.push(`anchors.${o}.${c} is not a valid CSS color: "${m}". Accepted forms: ${ee}.`)}else t.push(`anchors.${o} must be a color string or a { color, \u2026slots } object.`);const p=new Map;if("anchors"in e&&typeof e.anchors=="object"&&e.anchors!==null&&!Array.isArray(e.anchors))for(const[o,r]of Object.entries(e.anchors))p.set(o,r);function S(o,r){const i=de(o);if(!i){t.push(`${r} "${o}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!p.has(i.name)){const c=[...p.keys()];t.push(`${r} references undeclared anchor "${i.name}". Declared anchors: ${c.length>0?c.join(", "):"(none)"}.`);return}if(i.slot!==void 0){const c=p.get(i.name);if(typeof(typeof c=="object"&&c!==null&&!Array.isArray(c)?c[i.slot]:void 0)!="string"){const y=typeof c=="object"&&c!==null?Object.keys(c).filter(I=>I!=="color"):[];t.push(`${r} references unknown slot "${i.slot}" on anchor "${i.name}". Declared slots: ${y.length>0?y.join(", "):"(none)"}.`)}}}function $(o,r){if(o.startsWith("anchor:")){S(o,r);return}ye.includes(o)||t.push(`${r} must be one of: ${ye.join(", ")}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("intents"in e)if(typeof e.intents!="object"||e.intents===null||Array.isArray(e.intents))t.push("intents must be an object.");else for(const[o,r]of Object.entries(e.intents)){const i=`intents.${o}`;if(!Q.includes(o)){t.push(`${i} is not a status family; expected one of: ${Q.join(", ")}.`);continue}if(typeof r!="string"){t.push(`${i} must be a string (a CSS color or an anchor: reference).`);continue}if(r.startsWith("anchor:")){S(r,i);continue}N(r)||t.push(`${i} "${r}" is not a supported color form or anchor: reference. Accepted forms: ${ee}, or anchor:<name> / anchor:<name>.<slot>. An override retunes a family with a declared color; it never points one family at another \u2014 retune, never reassign.`)}function x(o,r){if(o.startsWith("anchor:")){S(o,r);return}N(o)||t.push(`${r} is not a valid CSS color: "${o}". Accepted forms: ${ee}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("dataPalette"in e)if(typeof e.dataPalette!="object"||e.dataPalette===null||Array.isArray(e.dataPalette))t.push("dataPalette must be an object with series1\u2013series8 color values.");else{const o=e.dataPalette;for(const[r,i]of Object.entries(o)){if(!ie.includes(r)){t.push(`dataPalette.${r} is not a series slot; expected one of: ${ie.join(", ")}.`);continue}typeof i!="string"?t.push(`dataPalette.${r} must be a CSS color or anchor reference string.`):x(i,`dataPalette.${r}`)}}if("dataRamps"in e)if(typeof e.dataRamps!="object"||e.dataRamps===null||Array.isArray(e.dataRamps))t.push("dataRamps must be an object of named ramp declarations.");else for(const[o,r]of Object.entries(e.dataRamps)){if(A(o)?z.test(o)||t.push(`dataRamps: "${o}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${o}" is a reserved JavaScript property name and cannot be a ramp name; rename it.`),typeof r!="object"||r===null||Array.isArray(r)){t.push(`dataRamps.${o} must be a sequential or diverging ramp object.`);continue}const i=r,c=i.steps??ct;if((typeof c!="number"||!Number.isInteger(c)||c<he||c>me)&&t.push(`dataRamps.${o}.steps must be an integer from ${he} through ${me}.`),i.type==="sequential"){typeof i.source!="string"?t.push(`dataRamps.${o}.source must be a CSS color or anchor reference string.`):x(i.source,`dataRamps.${o}.source`);const m=i.lightnessStart??.95,y=i.lightnessEnd??.25;for(const[I,D]of[["lightnessStart",m],["lightnessEnd",y]])(typeof D!="number"||!Number.isFinite(D)||D<0||D>1)&&t.push(`dataRamps.${o}.${I} must be a finite number from 0 through 1.`);typeof m=="number"&&typeof y=="number"&&m<=y?t.push(`dataRamps.${o}.lightnessStart must be greater than lightnessEnd.`):typeof m=="number"&&Number.isFinite(m)&&typeof y=="number"&&Number.isFinite(y)&&typeof c=="number"&&Number.isInteger(c)&&c>=he&&c<=me&&(m-y)/(c-1)<=Ie&&t.push(`dataRamps.${o} lightness bounds must leave more than ${Ie} lightness between serialized stops.`);continue}if(i.type==="diverging"){typeof c=="number"&&Number.isInteger(c)&&c%2===0&&t.push(`dataRamps.${o}.steps must be odd so the neutral is the exact midpoint.`);for(const m of["start","end"])typeof i[m]!="string"?t.push(`dataRamps.${o}.${m} must be a CSS color or anchor reference string.`):x(i[m],`dataRamps.${o}.${m}`);"neutral"in i&&(typeof i.neutral!="string"?t.push(`dataRamps.${o}.neutral must be a CSS color or anchor reference string.`):x(i.neutral,`dataRamps.${o}.neutral`));continue}t.push(`dataRamps.${o}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const o=se(Se,e),r={};let i=!0;for(const c of ie){const m=ut(o.dataPalette[c],o.anchors);if(!m){i=!1;break}r[c]=m}if(i)for(const c of it(r))s.push(`dataPalette.${c.series[0]} and dataPalette.${c.series[1]} are only ${c.distance.toFixed(4)} apart under ${c.simulation} simulation (minimum ${c.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function C(o,r){if(typeof o!="object"||o===null||Array.isArray(o)){t.push(`${r} must be an object.`);return}const i=o;for(const[c,m]of Object.entries(i)){const y=`${r}.${c}`;if(!Z.includes(c)){t.push(`${y} is not a role; expected one of: ${Z.join(", ")}. (The status family is reserved and is not a role.)`);continue}const I=c,D=He[I];if(typeof m=="string"){$(m,y);continue}if(typeof m!="object"||m===null||Array.isArray(m)){t.push(`${y} must be a color source or a { color, \u2026slots } object.`);continue}const W=m;typeof W.color!="string"&&t.push(`${y} must declare its base "color".`);for(const[l,d]of Object.entries(W)){if(!Object.prototype.hasOwnProperty.call(D,l)||!A(l)){const g=Object.keys(D).filter(b=>b!=="color");t.push(`${y}.${l} is not a slot of the ${I} role. Declared slots: ${g.length>0?g.join(", "):"(none)"}.`);continue}typeof d!="string"?t.push(`${y}.${l} must be a color source string.`):$(d,`${y}.${l}`)}}}if("roles"in e&&C(e.roles,"roles"),"contexts"in e)if(typeof e.contexts!="object"||e.contexts===null||Array.isArray(e.contexts))t.push("contexts must be an object.");else for(const[o,r]of Object.entries(e.contexts)){if(!A(o)||!z.test(o)){t.push(`contexts.${o} must be a lowercase slug matching ${z.source}.`);continue}if(typeof r!="object"||r===null||Array.isArray(r)){C(r,`contexts.${o}`);continue}const i=r,c=Object.fromEntries(Object.entries(i).filter(([m])=>m!=="lightness"));C(c,`contexts.${o}`),"lightness"in i&&h(i.lightness,`contexts.${o}.lightness`)}if("semanticMappings"in e)if(typeof e.semanticMappings!="object"||e.semanticMappings===null)t.push("semanticMappings must be an object.");else{const o=e.semanticMappings;for(const r of ge)if(r in o){const i=o[r];if(typeof i!="object"||i===null){t.push(`semanticMappings.${r} must be { source, lightness }.`);continue}const c=i;typeof c.source!="string"?t.push(`semanticMappings.${r}.source must be a string.`):$(c.source,`semanticMappings.${r}.source`),(typeof c.lightness!="string"||!U.includes(c.lightness))&&t.push(`semanticMappings.${r}.lightness must be one of: ${U.join(", ")}.`)}}for(const o of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])o in e&&typeof e[o]!="string"&&t.push(`${o} must be a string.`);for(const o of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(o in e)if(typeof e[o]!="number"||!isFinite(e[o]))t.push(`${o} must be a finite number.`);else{const r=e[o];(r<0||r>1)&&t.push(`${o} must be 0\u20131 (got ${r}).`)}return s.push(...Bt(e,n)),{valid:t.length===0,errors:t,warnings:s}}const O=.045;function Bt(e,n){try{return wt(e,n)}catch{return[]}}function wt(e,n){const t=se(n,e),s=qe(t),a=[...s],u=new Set(s);for(const[f,h]of Object.entries(t.contexts)){const p={};for(const $ of Z){const x=h[$];x!==void 0&&(p[$]=x)}const S=se(t,{lightness:h.lightness,roles:p});for(const $ of qe(S))u.has($)||a.push(`contexts.${f}: ${$}`)}return a}function Tt(e){const n=nt(fe(e)),t=st(n);return tt({r:le(t.r),g:le(t.g),b:le(t.b)})}function q(e,n){return Math.hypot(e.L-n.L,e.a-n.a,e.b-n.b)}function V(e){return Tt(N(ae(fe(e))))}function Je(e){return(Math.floor(e*1e4)/1e4).toFixed(4)}const X=2,Ye=1e-4;function qe(e){const n=N(e.seedColor);if(!n)return[];const t=Te(n,e),s=e.semanticMappings.actionBackground,a=e.chroma.actionBackground,u=e.lightness[s.lightness],f=(l,d,g,b)=>fe(we(l,d,g,b)),h=Q.map(l=>({name:l,base:t[l]})),p=[];if(Q.includes(s.source))p.push(`actionBackground is sourced from the "${s.source}" status family: ordinary and ${s.source}-intent action surfaces render identically (their labels may still differ). Remap the action to a non-status source \u2014 retuning "${s.source}" via intents moves both colors together.`);else{const l=Ee(s.source,t,e.anchors);l&&h.push({name:"action",base:l})}const S=_e(h.map(({name:l,base:d})=>[l,ae(f(d,u,a.min,a.max))]),O,["normal"]);if(S.length===0)return p;const $=new Map,x=(l,d)=>{const g=`${l}:${d}`;let b=$.get(g);if(!b){b=[];for(let w=0;w<360;w+=X)b.push(V({l,c:d,h:w}));$.set(g,b)}return b},C=O-.002,o=(l,d,g,b)=>{const w=Math.hypot(l.a,l.b),M=Math.atan2(l.b,l.a)*180/Math.PI+180;let E=0;for(const B of g===b?[b]:[g,b]){if(B+w<O-1e-4)continue;let L=M,R=q(V({l:d,c:B,h:M}),l);if(R>=O)return R;const P=x(d,B);for(let v=0;v<P.length;v+=1){const k=q(P[v],l);if(k>=O)return k;k>R&&(R=k,L=v*X)}let H=L;for(let v=L-X;v<=L+X;v+=.1){const k=q(V({l:d,c:B,h:v}),l);if(k>=O)return k;k>R&&(R=k,H=v)}if(R>=C)for(let v=H-.1;v<=H+.1;v+=.001){const k=q(V({l:d,c:B,h:v}),l);if(k>=O)return k;k>R&&(R=k)}R>E&&(E=R)}return E},r=(l,d,g)=>{const b=d===g?[g]:[d,g];let w=0;for(const M of b)for(const E of b){if(M+E<O-1e-4)continue;const B=x(l,M),L=x(l,E);let R=0,P=0,H=-1;for(let _=0;_<B.length;_+=1)for(let F=0;F<L.length;F+=1){const j=q(B[_],L[F]);if(j>=O)return j;j>H&&(H=j,R=_*X,P=F*X)}const v=(_,F,j,ve)=>{const Re=[];for(let K=F-j;K<=F+j;K+=ve)Re.push({h:K,lab:V({l,c:E,h:K})});let ue=-1,Oe=_,Ce=F;for(let K=_-j;K<=_+j;K+=ve){const Qe=V({l,c:M,h:K});for(const Me of Re){const Be=q(Qe,Me.lab);Be>ue&&(ue=Be,Oe=K,Ce=Me.h)}}return{distance:ue,hueA:Oe,hueB:Ce}},k=v(R,P,X,.1);if(k.distance>=O)return k.distance;let T=Math.max(H,k.distance);if(T>=C){const _=v(k.hueA,k.hueB,.1,.001);if(_.distance>T&&(T=_.distance),T>=O)return T}T>w&&(w=T)}return w},i=l=>Q.includes(l),c=(l,d,g,b,w)=>{const M=V(f(l.base,g,b,w)),E=V(f(d.base,g,b,w));if(q(M,E)>=O)return{outcome:"direct"};const B=i(l.name)&&i(d.name),L=[l,d].filter(H=>i(H.name)),R=B?"one of them":`"${i(l.name)?l.name:d.name}"`;let P;for(const H of L){const v=o(H===l?E:M,g,b,w);if(v>=O)return{outcome:"retune",target:R};v>=O-Ye&&(P=P??R)}if(B){const H=r(g,b,w);if(H>=O)return{outcome:"retune",target:"both"};H>=O-Ye&&(P=P??"both")}return P!==void 0?{outcome:"near",target:P}:{outcome:"no"}},m=l=>l.outcome==="direct"?4:l.outcome==="retune"?l.target==="both"?2:3:l.outcome==="near"?1:0,y=l=>[...l].sort().join("|"),I=new Set(_e(h.map(({name:l,base:d})=>[l,ae(f(d,u,0,G))]),O,["normal"]).map(l=>y(l.pair))),D=new Map(h.map(l=>[l.name,l])),W=new Map;for(const{pair:l,distance:d}of S){const g=D.get(l[0]),b=D.get(l[1]),w=i(g.name)&&i(b.name),M=c(g,b,u,a.min,a.max);if(M.outcome==="direct"||M.outcome==="retune"){const T=M.target??(w?"one of them":`"${i(g.name)?g.name:b.name}"`);I.has(y(l))?p.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish under normal vision (distance ${Je(d)} < ${O}); status meanings must stay distinguishable \u2014 retune ${T} via intents.`):p.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish as rendered (distance ${Je(d)} < ${O}); the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }) pushes them together \u2014 widen the band, or retune ${T} via intents.`);continue}const E=c(g,b,u,0,G);let B={outcome:"no"};for(let T=1;T<=19&&B.outcome!=="direct";T+=1){const _=T*.05;if(Math.abs(_-u)<.001)continue;const F=c(g,b,_,a.min,a.max);m(F)>m(B)&&(B=F)}let L={outcome:"no"};const R=E.outcome==="direct"||E.outcome==="retune",P=B.outcome==="direct"||B.outcome==="retune";if(!R&&!P)for(let T=1;T<=19&&L.outcome!=="direct";T+=1){const _=c(g,b,T*.05,0,G);m(_)>m(L)&&(L=_)}const H=Et(E,B,L),v=`${M.outcome}|${H}`;let k=W.get(v);k||(k=[],W.set(v,k)),k.push(l)}for(const[l,d]of W){const g=l.indexOf("|"),b=l.slice(0,g),w=l.slice(g+1),M=d.map(([L,R])=>`"${L}"/"${R}"`),E=M.length>1?`${M.slice(0,-1).join(", ")} and ${M[M.length-1]}`:M[0],B=b==="near"?`Status colors ${E} may not separate by retuning as rendered: at the action stop's lightness (${u}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), the closest reachable retune found comes within the audit's search margin of the ${O} threshold`:`Status colors ${E} cannot be separated as rendered: at the action stop's lightness (${u}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), no intent retuning can pull ${d.length>1?"these pairs":"the pair"} ${O} apart`;p.push(B+w)}return p}function Et(e,n,t){if(e.outcome==="direct"&&n.outcome==="direct")return" \u2014 widen the chroma band or move the action lightness stop.";if(e.outcome==="direct")return n.outcome==="no"?"; no other action lightness stop can help while the band holds \u2014 widen the chroma band.":" \u2014 widen the chroma band.";if(n.outcome==="direct")return e.outcome==="no"?"; no wider chroma band can help at this lightness \u2014 move the action lightness stop.":" \u2014 move the action lightness stop.";if(e.outcome==="retune"&&n.outcome==="retune")return` \u2014 widen the chroma band or move the action lightness stop, then retune ${e.target} via intents.`;if(e.outcome==="retune")return n.outcome==="no"?`; no other action lightness stop can help while the band holds \u2014 widen the chroma band, then retune ${e.target} via intents.`:` \u2014 widen the chroma band, then retune ${e.target} via intents.`;if(n.outcome==="retune")return e.outcome==="no"?`; no wider chroma band can help at this lightness \u2014 move the action lightness stop, then retune ${n.target} via intents.`:` \u2014 move the action lightness stop, then retune ${n.target} via intents.`;const s=e.outcome==="no"&&n.outcome==="no"?"; neither a wider chroma band alone nor another stop alone can help":"; neither a wider chroma band alone nor another stop alone provably helps";return t.outcome==="direct"?`${s} \u2014 change the band and the stop together.`:t.outcome==="retune"?`${s} \u2014 change the band and the stop together, then retune ${t.target} via intents.`:"; no explored band or stop change provably separates this pair."}function Ft(e,n){const t=ke(e),s=ke(n),a=t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:Ae(t.value),u=s.error!==void 0?{valid:!1,errors:[s.error],warnings:[]}:Ae(s.value,We),f=[...a.errors.map(p=>`light: ${p}`),...u.errors.map(p=>`dark: ${p}`)],h=[...a.warnings.map(p=>`light: ${p}`),...u.warnings.map(p=>`dark: ${p}`)];if(a.valid&&u.valid){const p=new Set(Object.keys(t.value?.contexts??{})),S=new Set(Object.keys(s.value?.contexts??{})),$=[...S].filter(C=>!p.has(C)).sort(),x=[...p].filter(C=>!S.has(C)).sort();($.length>0||x.length>0)&&f.push(`contexts must declare the same names in both schemes. Missing from light: ${$.join(", ")||"(none)"}. Missing from dark: ${x.join(", ")||"(none)"}.`)}return{valid:f.length===0,errors:f,warnings:h}}const _t=["anchors","angles","contexts","dataPalette","dataRamps","intents","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function It(e,n){const t={};for(const[s,a]of Object.entries(e))A(s)&&(t[s]=a);for(const[s,a]of Object.entries(n))a!==void 0&&A(s)&&(t[s]=a);for(const s of _t){const a=e[s],u=n[s];if(a&&typeof a=="object"&&!Array.isArray(a)&&u&&typeof u=="object"&&!Array.isArray(u)){if(s==="anchors"){t[s]=Ke(a,u);continue}if(s==="contexts"){t[s]=vt(a,u);continue}if(s==="dataRamps"){t[s]=Ge(a,u);continue}const f={};for(const[h,p]of Object.entries(a))A(h)&&(f[h]=p);for(const[h,p]of Object.entries(u))p!==void 0&&A(h)&&(f[h]=p);t[s]=f}}return t}function Wt(...e){let n={};for(const t of e){if(!t)continue;const s=xt(t);s&&(n=It(n,s))}return xe(n)}function Xe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const Ze={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function jt(e){return xe({...Ze,pageBackgroundImage:`url("${Xe(e)}")`,pageBackgroundImageOpacity:.5})}function Kt(e){return xe({...Ze,pageBackgroundImage:`url("${Xe(e)}")`,pageBackgroundImageOpacity:.55})}export{z as ANCHOR_SLUG_PATTERN,ye as COLOR_SOURCES,$t as DEFAULT_DARK_LIGHTNESS,We as DEFAULT_DARK_THEME,bt as DEFAULT_LIGHT_LIGHTNESS,Se as DEFAULT_LIGHT_THEME,be as DEFAULT_SEMANTIC_MAPPINGS,U as LIGHTNESS_KEYS,_t as NESTED_THEME_KEYS,Z as ROLE_NAMES,pt as ROLE_PAIRED_INK,He as ROLE_TOKEN_PLAN,ge as SEMANTIC_COLOR_NAMES,Q as STATUS_COLOR_SOURCES,Ne as TOKEN_PAIRINGS,yt as VARIANT_COLOR_SOURCES,Kt as buildTaprootDarkTheme,jt as buildTaprootLightTheme,De as compileRoles,xe as encodeTheme,Wt as layerThemes,It as mergePartials,se as mergeTheme,de as parseAnchorSource,xt as parseTheme,Le as resolveAnchorColor,ut as resolveDataColorSource,Dt as semanticToCSS,Nt as validateTheme,Ft as validateThemePair};
@@ -1 +1 @@
1
- import{parseCssColor as u,rotateHue as o}from"./color-engine.js";const m=/^anchor:([^.]+)(?:\.(.+))?$/;function s(t){const l=m.exec(t);return l?l[2]===void 0?{name:l[1]}:{name:l[1],slot:l[2]}:null}function h(t,l){const n=t[l.name];if(n===void 0)return null;if(typeof n=="string")return l.slot===void 0?n:null;const a=n[l.slot??"color"];return typeof a=="string"?a:null}function y(t,l,n){const a=s(t);if(!a)return l[t]??null;const c=h(n,a);return c===null?null:u(c)}const p=.6,g=.85;function S(t,l){const{angles:n,semanticHues:a,variantChroma:c}=l,r=e=>c[e]??t.c,i=Math.min(g,Math.max(p,t.l));return{primary:t,"analogous-left":{l:t.l,c:r("analogous-left"),h:o(t.h,-n.analogous)},"analogous-right":{l:t.l,c:r("analogous-right"),h:o(t.h,n.analogous)},complementary:{l:t.l,c:r("complementary"),h:o(t.h,n.complementary)},"split-complementary-left":{l:t.l,c:r("split-complementary-left"),h:o(t.h,n.complementary-n.splitComplementary)},"split-complementary-right":{l:t.l,c:r("split-complementary-right"),h:o(t.h,n.complementary+n.splitComplementary)},"triadic-left":{l:t.l,c:r("triadic-left"),h:o(t.h,n.triadic)},"triadic-right":{l:t.l,c:r("triadic-right"),h:o(t.h,-n.triadic)},danger:{l:i,c:r("danger"),h:o(a.danger,0)},success:{l:i,c:r("success"),h:o(a.success,0)},warning:{l:i,c:r("warning"),h:o(a.warning,0)}}}export{S as computeVariants,s as parseAnchorSource,h as resolveAnchorColor,y as resolveMappingSource};
1
+ import{gamutMapToSRGB as A,parseCssColor as g,rotateHue as o}from"./color-engine.js";const x=/^anchor:([^.]+)(?:\.(.+))?$/;function y(n){const r=x.exec(n);return r?r[2]===void 0?{name:r[1]}:{name:r[1],slot:r[2]}:null}function S(n,r){const a=n[r.name];if(a===void 0)return null;if(typeof a=="string")return r.slot===void 0?a:null;const t=a[r.slot??"color"];return typeof t=="string"?t:null}function w(n,r,a){const t=y(n);if(!t)return r[n]??null;const c=S(a,t);return c===null?null:g(c)}const M=.6,_=.85;function H(n,r){const{anchors:a,angles:t,intents:c,semanticHues:i,variantChroma:T}=r,l=u=>T[u]??n.c,e=Math.min(_,Math.max(M,n.l)),s=(u,C)=>{const m=c[u];if(typeof m=="string"){const h=y(m),p=h?S(a,h):m,f=p===null?null:g(p);if(f)return A(f)}return C()};return{primary:n,"analogous-left":{l:n.l,c:l("analogous-left"),h:o(n.h,-t.analogous)},"analogous-right":{l:n.l,c:l("analogous-right"),h:o(n.h,t.analogous)},complementary:{l:n.l,c:l("complementary"),h:o(n.h,t.complementary)},"split-complementary-left":{l:n.l,c:l("split-complementary-left"),h:o(n.h,t.complementary-t.splitComplementary)},"split-complementary-right":{l:n.l,c:l("split-complementary-right"),h:o(n.h,t.complementary+t.splitComplementary)},"triadic-left":{l:n.l,c:l("triadic-left"),h:o(n.h,t.triadic)},"triadic-right":{l:n.l,c:l("triadic-right"),h:o(n.h,-t.triadic)},danger:s("danger",()=>({l:e,c:l("danger"),h:o(i.danger,0)})),success:s("success",()=>({l:e,c:l("success"),h:o(i.success,0)})),warning:s("warning",()=>({l:e,c:l("warning"),h:o(i.warning,0)})),info:s("info",()=>({l:e,c:l("info"),h:o(i.info,0)}))}}export{H as computeVariants,y as parseAnchorSource,S as resolveAnchorColor,w as resolveMappingSource};
@@ -252,6 +252,11 @@
252
252
  "category": "root-theme",
253
253
  "description": ""
254
254
  },
255
+ {
256
+ "name": "--esp-color-info",
257
+ "category": "root-theme",
258
+ "description": ""
259
+ },
255
260
  {
256
261
  "name": "--esp-color-input-caret",
257
262
  "category": "root-theme",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "packageManager": "bun@1.3.12",
5
5
  "description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
6
6
  "customElements": "custom-elements.json",
@@ -226,6 +226,10 @@
226
226
  "types": "./dist/status-indicator/esp-status-indicator.d.ts",
227
227
  "import": "./dist/status-indicator/esp-status-indicator.js"
228
228
  },
229
+ "./switch": {
230
+ "types": "./dist/switch/esp-switch.d.ts",
231
+ "import": "./dist/switch/esp-switch.js"
232
+ },
229
233
  "./tabs": {
230
234
  "types": "./dist/tabs/esp-tab-group.d.ts",
231
235
  "import": "./dist/tabs/esp-tab-group.js"