@taprootio/espalier 3.4.0 → 3.6.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.
@@ -51,8 +51,10 @@ var o=function(h,e,t,r){var s=arguments.length,i=s<3?e:r===null?r=Object.getOwnP
51
51
  > .field-shell > label > .field-label {
52
52
  grid-column: 1;
53
53
  grid-row: 1;
54
- font-weight: bold;
55
- color: var(--esp-form-item-label-color, var(--esp-color-text));
54
+ font-size: var(--esp-type-label-font-size, var(--esp-type-normal));
55
+ font-weight: var(--esp-type-label-font-weight, var(--esp-font-weight-headings));
56
+ letter-spacing: var(--esp-type-label-letter-spacing, 0.01em);
57
+ color: var(--esp-form-item-label-color, var(--esp-type-label-color, var(--esp-color-text)));
56
58
  }
57
59
 
58
60
  > .field-shell > label > slot,
@@ -87,6 +87,27 @@ export type { SchemeEvents } from "../shared/bus-events.js";
87
87
  * @cssprop --esp-color-series-7-ink - Seventh series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable).
88
88
  * @cssprop --esp-color-series-8-wash - Eighth series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas.
89
89
  * @cssprop --esp-color-series-8-ink - Eighth series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable).
90
+ * @cssprop --esp-color-type-overline - Overline ink enforced to Lc 90 against the local background.
91
+ * @cssprop --esp-color-type-label - Label ink enforced to Lc 75 against the local background.
92
+ * @cssprop --esp-color-type-lead - Lead-paragraph ink enforced to Lc 75 against the local background.
93
+ * @cssprop --esp-color-type-caption - Caption ink enforced to Lc 90 against the local background.
94
+ * @cssprop --esp-type-overline-font-size - Fluid font size for overline text.
95
+ * @cssprop --esp-type-overline-font-weight - Font weight for overline text.
96
+ * @cssprop --esp-type-overline-letter-spacing - Letter spacing for overline text.
97
+ * @cssprop --esp-type-overline-text-transform - Text transform for overline text.
98
+ * @cssprop --esp-type-overline-color - Context-local color alias for overline text.
99
+ * @cssprop --esp-type-label-font-size - Fluid font size for label text.
100
+ * @cssprop --esp-type-label-font-weight - Font weight for label text.
101
+ * @cssprop --esp-type-label-letter-spacing - Letter spacing for label text.
102
+ * @cssprop --esp-type-label-color - Context-local color alias for label text.
103
+ * @cssprop --esp-type-lead-font-size - Fluid font size for lead paragraphs.
104
+ * @cssprop --esp-type-lead-font-weight - Font weight for lead paragraphs.
105
+ * @cssprop --esp-type-lead-letter-spacing - Letter spacing for lead paragraphs.
106
+ * @cssprop --esp-type-lead-color - Context-local color alias for lead paragraphs.
107
+ * @cssprop --esp-type-caption-font-size - Fluid font size for captions.
108
+ * @cssprop --esp-type-caption-font-weight - Font weight for captions.
109
+ * @cssprop --esp-type-caption-letter-spacing - Letter spacing for captions.
110
+ * @cssprop --esp-type-caption-color - Context-local color alias for captions.
90
111
  *
91
112
  * @docPageTitle Root
92
113
  * @docUrl /components/root
@@ -232,6 +253,49 @@ export declare class EspalierRoot extends LitElement implements SeedColorRoot {
232
253
  * @type {string}
233
254
  */
234
255
  iconSpriteUrl: string;
256
+ /**
257
+ * Hold descendant paint until the first author theme resolves
258
+ * (ESP0177) — opt in when the theme is assigned from script.
259
+ *
260
+ * A script-mounted theme lands after the elements upgrade, so without
261
+ * this the page paints one frame on the default palette and then
262
+ * repaints on the brand's. Declaring `theme-pending` keeps the
263
+ * subtree invisible (it still takes its space, so nothing shifts)
264
+ * until the theme applies.
265
+ *
266
+ * Server-rendered `light-theme` / `dark-theme` attributes close a
267
+ * different window: the theme is present when the root upgrades, so
268
+ * it settles on its first update and never renders the defaults. They
269
+ * do not cover the frame before this module runs, when the host is
270
+ * still an unknown element painting its light DOM unstyled — a
271
+ * server-rendered page whose bundle may load after first paint wants
272
+ * this attribute too, plus the page-level gate, and its hold releases
273
+ * the moment it upgrades.
274
+ *
275
+ * The hold always ends: if no theme arrives within
276
+ * {@link THEME_SETTLE_TIMEOUT_MS} the root reveals anyway and warns,
277
+ * so a broken mount degrades to the default palette instead of a
278
+ * blank page.
279
+ */
280
+ themePending: boolean;
281
+ /**
282
+ * `true` once the theme this root will render with is the theme it
283
+ * has — an author theme resolved, or the pre-theme window closed with
284
+ * none. Mirrored to the `data-theme-ready` attribute so page CSS can
285
+ * gate on it. Pair it with the opt-in attribute —
286
+ * `esp-root[theme-pending]:not([data-theme-ready]) { visibility: hidden }`
287
+ * — which is the only frame-zero cover for the window before this
288
+ * module runs, and which scopes the hold to roots that asked for it:
289
+ * unscoped, the rule would also blank a page that never mounts a
290
+ * theme, until its deadline closes the window.
291
+ */
292
+ get themeSettled(): boolean;
293
+ /**
294
+ * Resolves when {@link themeSettled} turns true — the honest moment
295
+ * to judge whether a named context is genuinely missing rather than
296
+ * merely not mounted yet.
297
+ */
298
+ whenThemeSettled(): Promise<void>;
235
299
  /**
236
300
  * Initial color scheme to apply when `scheme` is not set.
237
301
  *
@@ -1,4 +1,4 @@
1
- var a=function(d,e,t,o){var l=arguments.length,s=l<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(d,e,t,o);else for(var n=d.length-1;n>=0;n--)(r=d[n])&&(s=(l<3?r(s):l>3?r(e,t,s):r(e,t))||s);return l>3&&s&&Object.defineProperty(e,t,s),s},h;import{css as b,html as T,LitElement as C}from"lit";import{customElement as E,property as c}from"lit/decorators.js";import{getEspBus as p}from"../shared/bus-events.js";import{subscribeToRootEvent as x}from"../shared/root-event-subscription.js";import{DEFAULT_LIGHT_THEME as f,DEFAULT_DARK_THEME as y,encodeTheme as v,parseTheme as g,mergeTheme as S}from"../shared/theme.js";import{computeThemeProperties as R}from"./helpers/compute-theme-properties.js";import{registerImageTexture as D,registeredImageTextures as L}from"../shared/image-texture-registry.js";import{registerImageTexture as _,registeredImageTextures as H,BUILT_IN_IMAGE_TEXTURES as M}from"../shared/image-texture-registry.js";let i=h=class extends C{constructor(){super(...arguments),this.schemeBacker="",this.schemeExplicitlySet=!1,this.resolvingDefaultScheme=!1,this.themeEventsReady=!1,this.systemSchemeQuery=null,this.lastSeedColor="",this.resolvedLightTheme={...f},this.resolvedDarkTheme={...y},this.appliedDataRampProperties=new Set,this.documentClickRegistrationActive=!1,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.lightThemeAttr="",this.darkThemeAttr="",this.fontCSSRoot="/css/fonts/",this.fontDefinitionsUrl="",this.googleFontLoading="auto",this.iconSpriteUrl="/assets/icons.svg",this.defaultScheme="light",this.resizeObserver=new ResizeObserver(()=>{p().publish("window-resized",{emWidth:window.innerWidth/parseFloat(getComputedStyle(document.documentElement).fontSize),emHeight:window.innerHeight/parseFloat(getComputedStyle(document.documentElement).fontSize),pxWidth:window.innerWidth,pxHeight:window.innerHeight})}),this.handleSystemSchemeChange=e=>{this.schemeExplicitlySet||this.defaultScheme!=="system"||(this.resolvingDefaultScheme=!0,this.scheme=e.matches?"dark":"light",this.resolvingDefaultScheme=!1)}}static registerTexture(e,t){D(e,t)}static registeredTextures(){return L()}subscribeScoped(e,t){return x(this,e,t)}get lightTheme(){return this.lightThemeAttr?g(this.lightThemeAttr):null}set lightTheme(e){this.lightThemeAttr=e?v(e):""}get darkTheme(){return this.darkThemeAttr?g(this.darkThemeAttr):null}set darkTheme(e){this.darkThemeAttr=e?v(e):""}get scheme(){return this.schemeBacker}set scheme(e){const t=e==="dark"?"dark":e==="light"?"light":"",o=this.schemeBacker,l=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const s=t||this.resolveDefaultScheme();l!==this.schemeExplicitlySet&&this.isConnected&&this.syncSystemSchemeListener(),s!==o&&(this.schemeBacker=s,this.requestUpdate("scheme",o),this.themeEventsReady&&p().publish("scheme-changed",{scheme:s,correlationId:this.correlationId}))}get seedColor(){return this.activeTheme.seedColor}static extractFamily(e){if(!e)return"";const t=e.match(/^"([^"]+)"|^'([^']+)'/);return t&&(t[1]||t[2])||""}injectGoogleFontLink(e,t,o){const l="data-esp-font",s=`${this.correlationId}-${e}`,r=document.head.querySelector(`link[${l}="${s}"]`);if(this.googleFontLoading==="none"){r?.remove();return}if(r&&t&&r.dataset.espFamily===t&&r.dataset.espWeight===(o??"")||(r?.remove(),!t))return;const n=encodeURIComponent(t),u=o==="bold"?"700":o==="normal"?"400":o,k=u&&u!=="400"?`:wght@${u}`:"",m=document.createElement("link");m.rel="stylesheet",m.href=`https://fonts.googleapis.com/css2?family=${n}${k}&display=swap`,m.setAttribute(l,s),m.dataset.espFamily=t,m.dataset.espWeight=o??"",document.head.appendChild(m)}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",h.extractFamily(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",h.extractFamily(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",h.extractFamily(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("monospace",h.extractFamily(e.fontMonospace),e.fontWeightMonospace)}removeRuntimeGoogleFontLinks(){for(const e of document.head.querySelectorAll(`link[data-esp-font^="${this.correlationId}-"]`))e.remove();for(const e of document.head.querySelectorAll(`link[data-esp-font-picker-root="${CSS.escape(this.correlationId)}"]`))e.remove()}get activeTheme(){return this.scheme==="dark"?this.resolvedDarkTheme:this.resolvedLightTheme}resolveThemes(){const e=this.lightThemeAttr?g(this.lightThemeAttr):null;this.resolvedLightTheme=e?S(f,e):{...f};const t=this.darkThemeAttr?g(this.darkThemeAttr):null;this.resolvedDarkTheme=t?S(y,t):{...y}}connectedCallback(){super.connectedCallback(),this.registerDocumentClickBridge(),this.resizeObserver.observe(this),this.hasUpdated&&(this.applyDefaultScheme(),this.syncGoogleFontLinks())}willUpdate(e){const t=["lightThemeAttr","darkThemeAttr"];(!this.lastSeedColor||t.some(n=>e.has(n)))&&(this.resolveThemes(),this.themeEventsReady&&p().publish("theme-changed",{correlationId:this.correlationId}));const l=R(this.activeTheme,this.scheme==="dark"?"dark":"light"),s=new Set(Object.keys(l).filter(n=>n.startsWith("--esp-color-ramp-")));for(const n of this.appliedDataRampProperties)s.has(n)||this.style.removeProperty(n);for(const[n,u]of Object.entries(l))this.style.setProperty(n,u);this.appliedDataRampProperties=s;const r=this.activeTheme.seedColor;this.themeEventsReady&&this.lastSeedColor&&this.lastSeedColor!==r&&p().publish("seed-color-changed",{seedColor:r,correlationId:this.correlationId}),this.lastSeedColor=r,this.themeEventsReady&&e.has("iconSpriteUrl")&&p().publish("icon-sprite-url-changed",{iconSpriteUrl:this.iconSpriteUrl,correlationId:this.correlationId}),this.syncGoogleFontLinks()}firstUpdated(){const e=this.activeTheme.stylesheets;if(e.length)for(const t of e){const o=document.createElement("link");o.rel="stylesheet",o.href=t,document.head.appendChild(o)}if(!document.getElementById("esp-root-base-styles")){const t=document.createElement("style");t.id="esp-root-base-styles",t.textContent=h.lightDomStyles,document.head.appendChild(t)}this.applyDefaultScheme(),this.lastSeedColor=this.activeTheme.seedColor,this.themeEventsReady=!0}updated(e){(e.has("defaultScheme")||e.has("scheme"))&&!this.schemeExplicitlySet&&this.applyDefaultScheme()}disconnectedCallback(){this.unregisterDocumentClickBridge(),this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null,this.resizeObserver.disconnect(),this.removeRuntimeGoogleFontLinks(),super.disconnectedCallback()}registerDocumentClickBridge(){this.documentClickRegistrationActive||(this.documentClickRegistrationActive=!0,h.connectedRootCount+=1,h.connectedRootCount===1&&document.addEventListener("click",h.handleDocumentClick))}unregisterDocumentClickBridge(){this.documentClickRegistrationActive&&(this.documentClickRegistrationActive=!1,h.connectedRootCount=Math.max(0,h.connectedRootCount-1),h.connectedRootCount===0&&document.removeEventListener("click",h.handleDocumentClick))}applyDefaultScheme(){this.schemeExplicitlySet||(this.resolvingDefaultScheme=!0,this.scheme=this.resolveDefaultScheme(),this.resolvingDefaultScheme=!1,this.syncSystemSchemeListener())}resolveDefaultScheme(){return this.defaultScheme==="dark"||this.defaultScheme==="system"&&window.matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light"}syncSystemSchemeListener(){if(this.schemeExplicitlySet||this.defaultScheme!=="system"||!window.matchMedia){this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null;return}this.systemSchemeQuery||(this.systemSchemeQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.systemSchemeQuery.addEventListener("change",this.handleSystemSchemeChange))}render(){return T`<slot></slot>`}};i.connectedRootCount=0,i.handleDocumentClick=d=>{const e=d.composedPath().filter(t=>t instanceof HTMLElement&&t.tagName==="ESP-POPOVER");p().publish("close-popovers",{source:d.target??void 0,skipPopovers:e})},i.lightDomStyles=`
1
+ var h=function(c,e,t,i){var l=arguments.length,s=l<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,t):i,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(c,e,t,i);else for(var n=c.length-1;n>=0;n--)(r=c[n])&&(s=(l<3?r(s):l>3?r(e,t,s):r(e,t))||s);return l>3&&s&&Object.defineProperty(e,t,s),s},a;import{css as b,html as w,LitElement as E}from"lit";import{customElement as C,property as m,state as R}from"lit/decorators.js";import{getEspBus as p}from"../shared/bus-events.js";import{subscribeToRootEvent as x}from"../shared/root-event-subscription.js";import{DEFAULT_LIGHT_THEME as f,DEFAULT_DARK_THEME as y,encodeTheme as S,parseTheme as g,mergeTheme as v}from"../shared/theme.js";import{computeThemeProperties as D}from"./helpers/compute-theme-properties.js";import{registerImageTexture as A,registeredImageTextures as L}from"../shared/image-texture-registry.js";import{registerImageTexture as O,registeredImageTextures as j,BUILT_IN_IMAGE_TEXTURES as H}from"../shared/image-texture-registry.js";const T=1e3;let o=a=class extends E{constructor(){super(...arguments),this.schemeBacker="",this.schemeExplicitlySet=!1,this.resolvingDefaultScheme=!1,this.themeEventsReady=!1,this.systemSchemeQuery=null,this.lastSeedColor="",this.resolvedLightTheme={...f},this.resolvedDarkTheme={...y},this.appliedDataRampProperties=new Set,this.documentClickRegistrationActive=!1,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.lightThemeAttr="",this.darkThemeAttr="",this.fontCSSRoot="/css/fonts/",this.fontDefinitionsUrl="",this.googleFontLoading="auto",this.iconSpriteUrl="/assets/icons.svg",this.themePending=!1,this.themeReadyState=!1,this.themeSettleWaiters=[],this.warnedThemeSettleTimeout=!1,this.defaultScheme="light",this.resizeObserver=new ResizeObserver(()=>{p().publish("window-resized",{emWidth:window.innerWidth/parseFloat(getComputedStyle(document.documentElement).fontSize),emHeight:window.innerHeight/parseFloat(getComputedStyle(document.documentElement).fontSize),pxWidth:window.innerWidth,pxHeight:window.innerHeight})}),this.handleSystemSchemeChange=e=>{this.schemeExplicitlySet||this.defaultScheme!=="system"||(this.resolvingDefaultScheme=!0,this.scheme=e.matches?"dark":"light",this.resolvingDefaultScheme=!1)}}static registerTexture(e,t){A(e,t)}static registeredTextures(){return L()}subscribeScoped(e,t){return x(this,e,t)}get lightTheme(){return this.lightThemeAttr?g(this.lightThemeAttr):null}set lightTheme(e){this.lightThemeAttr=e?S(e):""}get darkTheme(){return this.darkThemeAttr?g(this.darkThemeAttr):null}set darkTheme(e){this.darkThemeAttr=e?S(e):""}get themeSettled(){return this.themeReadyState}whenThemeSettled(){return this.themeReadyState?Promise.resolve():new Promise(e=>{this.themeSettleWaiters.push(e)})}get hasAuthorTheme(){return!!(this.scheme==="dark"?this.darkThemeAttr:this.lightThemeAttr)}settleTheme(){if(this.themeSettleTimer!==void 0&&(clearTimeout(this.themeSettleTimer),this.themeSettleTimer=void 0),this.themeReadyState)return;this.themeReadyState=!0;const e=this.themeSettleWaiters;this.themeSettleWaiters=[];for(const t of e)t()}get scheme(){return this.schemeBacker}set scheme(e){const t=e==="dark"?"dark":e==="light"?"light":"",i=this.schemeBacker,l=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const s=t||this.resolveDefaultScheme();l!==this.schemeExplicitlySet&&this.isConnected&&this.syncSystemSchemeListener(),s!==i&&(this.schemeBacker=s,this.requestUpdate("scheme",i),this.themeEventsReady&&p().publish("scheme-changed",{scheme:s,correlationId:this.correlationId}))}get seedColor(){return this.activeTheme.seedColor}static extractFamily(e){if(!e)return"";const t=e.match(/^"([^"]+)"|^'([^']+)'/);return t&&(t[1]||t[2])||""}injectGoogleFontLink(e,t,i){const l="data-esp-font",s=`${this.correlationId}-${e}`,r=document.head.querySelector(`link[${l}="${s}"]`);if(this.googleFontLoading==="none"){r?.remove();return}if(r&&t&&r.dataset.espFamily===t&&r.dataset.espWeight===(i??"")||(r?.remove(),!t))return;const n=encodeURIComponent(t),u=i==="bold"?"700":i==="normal"?"400":i,k=u&&u!=="400"?`:wght@${u}`:"",d=document.createElement("link");d.rel="stylesheet",d.href=`https://fonts.googleapis.com/css2?family=${n}${k}&display=swap`,d.setAttribute(l,s),d.dataset.espFamily=t,d.dataset.espWeight=i??"",document.head.appendChild(d)}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",a.extractFamily(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",a.extractFamily(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",a.extractFamily(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("monospace",a.extractFamily(e.fontMonospace),e.fontWeightMonospace)}removeRuntimeGoogleFontLinks(){for(const e of document.head.querySelectorAll(`link[data-esp-font^="${this.correlationId}-"]`))e.remove();for(const e of document.head.querySelectorAll(`link[data-esp-font-picker-root="${CSS.escape(this.correlationId)}"]`))e.remove()}get activeTheme(){return this.scheme==="dark"?this.resolvedDarkTheme:this.resolvedLightTheme}resolveThemes(){const e=this.lightThemeAttr?g(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(f,e):{...f};const t=this.darkThemeAttr?g(this.darkThemeAttr):null;this.resolvedDarkTheme=t?v(y,t):{...y}}connectedCallback(){super.connectedCallback(),this.registerDocumentClickBridge(),this.resizeObserver.observe(this),this.hasUpdated&&(this.applyDefaultScheme(),this.syncGoogleFontLinks(),this.hasAuthorTheme||this.startThemeSettleTimer())}willUpdate(e){const t=["lightThemeAttr","darkThemeAttr"];(!this.lastSeedColor||t.some(n=>e.has(n)))&&(this.resolveThemes(),this.themeEventsReady&&p().publish("theme-changed",{correlationId:this.correlationId})),this.hasAuthorTheme&&this.settleTheme();const l=D(this.activeTheme,this.scheme==="dark"?"dark":"light"),s=new Set(Object.keys(l).filter(n=>n.startsWith("--esp-color-ramp-")));for(const n of this.appliedDataRampProperties)s.has(n)||this.style.removeProperty(n);for(const[n,u]of Object.entries(l))this.style.setProperty(n,u);this.appliedDataRampProperties=s;const r=this.activeTheme.seedColor;this.themeEventsReady&&this.lastSeedColor&&this.lastSeedColor!==r&&p().publish("seed-color-changed",{seedColor:r,correlationId:this.correlationId}),this.lastSeedColor=r,this.themeEventsReady&&e.has("iconSpriteUrl")&&p().publish("icon-sprite-url-changed",{iconSpriteUrl:this.iconSpriteUrl,correlationId:this.correlationId}),this.syncGoogleFontLinks()}firstUpdated(){const e=this.activeTheme.stylesheets;if(e.length)for(const t of e){const i=document.createElement("link");i.rel="stylesheet",i.href=t,document.head.appendChild(i)}if(!document.getElementById("esp-root-base-styles")){const t=document.createElement("style");t.id="esp-root-base-styles",t.textContent=a.lightDomStyles,document.head.appendChild(t)}this.applyDefaultScheme(),this.lastSeedColor=this.activeTheme.seedColor,this.themeEventsReady=!0,this.startThemeSettleTimer()}startThemeSettleTimer(){if(this.themeReadyState||this.themeSettleTimer!==void 0)return;this.themeSettleDeadline??=performance.now()+T;const e=Math.max(0,this.themeSettleDeadline-performance.now());if(e===0){this.closeThemeWindow();return}this.themeSettleTimer=setTimeout(()=>this.closeThemeWindow(),e)}closeThemeWindow(){this.themeSettleTimer=void 0,this.themePending&&!this.warnedThemeSettleTimeout&&(this.warnedThemeSettleTimeout=!0,console.warn(`Espalier root: theme-pending was declared but no ${this.scheme} theme arrived within ${T}ms, so the default palette is rendering. Assign ${this.scheme==="dark"?"darkTheme":"lightTheme"} (or remove theme-pending).`)),this.settleTheme()}updated(e){this.toggleAttribute("data-theme-ready",this.themeReadyState),(e.has("defaultScheme")||e.has("scheme"))&&!this.schemeExplicitlySet&&this.applyDefaultScheme()}disconnectedCallback(){this.themeSettleTimer!==void 0&&(clearTimeout(this.themeSettleTimer),this.themeSettleTimer=void 0),this.unregisterDocumentClickBridge(),this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null,this.resizeObserver.disconnect(),this.removeRuntimeGoogleFontLinks(),super.disconnectedCallback()}registerDocumentClickBridge(){this.documentClickRegistrationActive||(this.documentClickRegistrationActive=!0,a.connectedRootCount+=1,a.connectedRootCount===1&&document.addEventListener("click",a.handleDocumentClick))}unregisterDocumentClickBridge(){this.documentClickRegistrationActive&&(this.documentClickRegistrationActive=!1,a.connectedRootCount=Math.max(0,a.connectedRootCount-1),a.connectedRootCount===0&&document.removeEventListener("click",a.handleDocumentClick))}applyDefaultScheme(){this.schemeExplicitlySet||(this.resolvingDefaultScheme=!0,this.scheme=this.resolveDefaultScheme(),this.resolvingDefaultScheme=!1,this.syncSystemSchemeListener())}resolveDefaultScheme(){return this.defaultScheme==="dark"||this.defaultScheme==="system"&&window.matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light"}syncSystemSchemeListener(){if(this.schemeExplicitlySet||this.defaultScheme!=="system"||!window.matchMedia){this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null;return}this.systemSchemeQuery||(this.systemSchemeQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.systemSchemeQuery.addEventListener("change",this.handleSystemSchemeChange))}render(){return w`<slot></slot>`}};o.connectedRootCount=0,o.handleDocumentClick=c=>{const e=c.composedPath().filter(t=>t instanceof HTMLElement&&t.tagName==="ESP-POPOVER");p().publish("close-popovers",{source:c.target??void 0,skipPopovers:e})},o.lightDomStyles=`
2
2
 
3
3
  esp-root {
4
4
  font-family: var(--esp-font-body);
@@ -121,8 +121,13 @@ var a=function(d,e,t,o){var l=arguments.length,s=l<3?e:o===null?o=Object.getOwnP
121
121
  max-width: 100%;
122
122
  display: block;
123
123
  }
124
- `,i.styles=b`
124
+ `,o.styles=b`
125
125
  :host {
126
126
  display: block;
127
127
  }
128
- `,a([c({attribute:!1})],i.prototype,"correlationId",void 0),a([c({attribute:"light-theme"})],i.prototype,"lightThemeAttr",void 0),a([c({attribute:"dark-theme"})],i.prototype,"darkThemeAttr",void 0),a([c({attribute:!1})],i.prototype,"lightTheme",null),a([c({attribute:!1})],i.prototype,"darkTheme",null),a([c({attribute:"font-css-root",type:String})],i.prototype,"fontCSSRoot",void 0),a([c({attribute:"font-definitions-url",type:String})],i.prototype,"fontDefinitionsUrl",void 0),a([c({attribute:"google-font-loading",type:String})],i.prototype,"googleFontLoading",void 0),a([c({attribute:"icon-sprite-url",type:String})],i.prototype,"iconSpriteUrl",void 0),a([c({attribute:"default-scheme",type:String,reflect:!0})],i.prototype,"defaultScheme",void 0),a([c({attribute:"scheme",type:String,reflect:!0})],i.prototype,"scheme",null),i=h=a([E("esp-root")],i);export{M as BUILT_IN_IMAGE_TEXTURES,i as EspalierRoot,_ as registerImageTexture,H as registeredImageTextures};
128
+
129
+
130
+ :host([theme-pending]:not([data-theme-ready])) {
131
+ visibility: hidden;
132
+ }
133
+ `,h([m({attribute:!1})],o.prototype,"correlationId",void 0),h([m({attribute:"light-theme"})],o.prototype,"lightThemeAttr",void 0),h([m({attribute:"dark-theme"})],o.prototype,"darkThemeAttr",void 0),h([m({attribute:!1})],o.prototype,"lightTheme",null),h([m({attribute:!1})],o.prototype,"darkTheme",null),h([m({attribute:"font-css-root",type:String})],o.prototype,"fontCSSRoot",void 0),h([m({attribute:"font-definitions-url",type:String})],o.prototype,"fontDefinitionsUrl",void 0),h([m({attribute:"google-font-loading",type:String})],o.prototype,"googleFontLoading",void 0),h([m({attribute:"icon-sprite-url",type:String})],o.prototype,"iconSpriteUrl",void 0),h([m({attribute:"theme-pending",reflect:!0,type:Boolean})],o.prototype,"themePending",void 0),h([R()],o.prototype,"themeReadyState",void 0),h([m({attribute:"default-scheme",type:String,reflect:!0})],o.prototype,"defaultScheme",void 0),h([m({attribute:"scheme",type:String,reflect:!0})],o.prototype,"scheme",null),o=a=h([C("esp-root")],o);export{H as BUILT_IN_IMAGE_TEXTURES,o as EspalierRoot,O as registerImageTexture,j as registeredImageTextures};
@@ -1 +1 @@
1
- import{deriveSemantic as C,deriveSemanticWithContrast as M,serializeOklch as d}from"../../shared/color-engine.js";import{SEMANTIC_COLOR_NAMES as v,TOKEN_PAIRINGS as S,semanticToCSS as R}from"../../shared/theme.js";import{resolveMappingSource as k}from"./compute-variants.js";function x(r,m,t={}){const i={},u={},p=(o,e)=>{const c=t.effectiveSource?.(o,e)??e,s=k(c,m,r.anchors);return s||t.onUnresolvedSource?.(c),{color:s??m.primary,resolved:s!==null,source:c}};for(const o of v){if(S[o])continue;const e=r.semanticMappings[o],c=r.chroma[o],s=p(o,e.source),n=r.lightness[e.lightness],l=C(s.color,n,c.min,c.max),a=R(o);u[o]=l,i[a]=d(l),t.trace&&t.trace.push({token:o,property:a,resolved:i[a],source:s.source,lightness:e.lightness,sourceResolved:s.resolved,base:s.color})}for(const o of v){const e=S[o];if(!e)continue;const c=r.semanticMappings[o],s=r.chroma[o],n=p(o,c.source),l=r.lightness[c.lightness],a=u[e.bg];let f;const h=M(n.color,l,s.min,s.max,a,e.targetLc,t.trace&&(b=>{f=b})),g=R(o);u[o]=h,i[g]=d(h),t.trace&&t.trace.push({token:o,property:g,resolved:i[g],source:n.source,lightness:c.lightness,sourceResolved:n.resolved,base:n.color,requested:f,contrast:{against:e.bg,background:a,targetLc:e.targetLc}})}return i}export{x as computeSemanticProperties};
1
+ import{deriveSemantic as O,deriveSemanticWithContrast as k,serializeOklch as C}from"../../shared/color-engine.js";import{SEMANTIC_COLOR_NAMES as M,TOKEN_PAIRINGS as R,semanticToCSS as y}from"../../shared/theme.js";import{resolveMappingSource as A}from"./compute-variants.js";function E(s,u,r,n,i,g){return[s.l,s.c,s.h,u,r,n,i.l,i.c,i.h,g].join("|")}function q(s,u,r={}){const n={},i={},g=new Map,h=(e,o)=>{const t=r.effectiveSource?.(e,o)??o,c=A(t,u,s.anchors);return c||r.onUnresolvedSource?.(t),{color:c??u.primary,resolved:c!==null,source:t}};for(const e of M){if(R[e])continue;const o=s.semanticMappings[e],t=s.chroma[e],c=h(e,o.source),a=s.lightness[o.lightness],m=O(c.color,a,t.min,t.max),l=y(e);i[e]=m,n[l]=C(m),r.trace&&r.trace.push({token:e,property:l,resolved:n[l],source:c.source,lightness:o.lightness,sourceResolved:c.resolved,base:c.color})}for(const e of M){const o=R[e];if(!o)continue;const t=s.semanticMappings[e],c=s.chroma[e],a=h(e,t.source),m=s.lightness[t.lightness],l=i[o.bg],v=E(a.color,m,c.min,c.max,l,o.targetLc);let f=g.get(v);if(!f){let S;const x=k(a.color,m,c.min,c.max,l,o.targetLc,r.trace&&(N=>{S=N}));f={requested:S,semantic:x},g.set(v,f)}const{requested:L,semantic:d}=f,p=y(e);i[e]=d,n[p]=C(d),r.trace&&r.trace.push({token:e,property:p,resolved:n[p],source:a.source,lightness:t.lightness,sourceResolved:a.resolved,base:a.color,requested:L,contrast:{against:o.bg,background:l,targetLc:o.targetLc}})}return n}export{q as computeSemanticProperties};
@@ -80,7 +80,7 @@ export declare class EspalierElementBase extends LitElement implements SeedColor
80
80
  *
81
81
  * With no context and a `neutral` intent, all semantic tokens cascade
82
82
  * from `<esp-root>` and previous overrides are cleared. A context
83
- * emits the zone's complete nineteen-token table; a non-neutral intent
83
+ * emits the zone's complete twenty-three-token table; a non-neutral intent
84
84
  * then overlays the filled-action pair, derived over the governing
85
85
  * zone's theme — this host's own context, or the nearest ancestor
86
86
  * zone's — so its APCA enforcement runs against the zone's actual
@@ -1,4 +1,4 @@
1
- var c=function(u,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(u,e,t,r);else for(var i=u.length-1;i>=0;i--)(a=u[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 T,LitElement as R}from"lit";import{property as d,state as C}from"lit/decorators.js";import{subscribeToRootEvent as p}from"./root-event-subscription.js";import{traverseToClosest as m}from"./utilities.js";import{parseCssColor as S,serializeOklch as w,gamutMapToSRGB as P}from"./color-engine.js";import{computeVariants as b}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as v}from"../root/helpers/compute-semantic-properties.js";import{DocumentSpriteController as x}from"./document-sprite.js";import{dataCompanionProperties as E}from"../root/helpers/data-companion-properties.js";import{dataSeriesProperties as V}from"../root/helpers/compute-theme-properties.js";import{lightnessRampProperties as U}from"../root/helpers/lightness-ramp-properties.js";import{ELEVATION_PROPERTIES as I}from"./scale-engine.js";import{resolveContextTheme as A,resolveDataColorSource as O,semanticToCSS as D}from"./theme.js";import{alignAttributeTextInheritance as z,focusRing as F}from"./style-fragments.js";import{syncNormalizedAttribute as N}from"./attribute-helpers.js";import{INTENT_VARIANTS as y,normalizeIntentVariant as j}from"./intent-values.js";class n extends R{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=j(e);N(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=m(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=[p(e,"seed-color-changed",this.handleSeedColorChanged),p(e,"scheme-changed",this.handleSchemeChanged),p(e,"theme-changed",this.handleThemeChanged),p(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}}constructor(){super(),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()},new x(this,{reactToSpriteChanges:!1})}traverseToClosest(e){return m(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=S(o.seedColor);if(!s)return;const a=b(s,o),i={};if(r.applied&&(Object.assign(i,v(o,a)),Object.assign(i,U(o)),Object.assign(i,I),Object.assign(i,E(i,V(o,s,l=>(typeof l=="string"?O(l,o.anchors):null)??o.seedColor)))),e){let l=o;r.applied||(l=this.resolveAncestorZoneTheme(t)??o);const g=l===o?a:b(s,l),k=v(l,g,{effectiveSource:(f,h)=>n.semanticActionTokens.has(f)?e:h});i["--esp-color-primary"]=w(P(g[e]));for(const f of n.semanticActionTokens){const h=D(f);i[h]=k[h]}}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){return A(e,t)}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=[F(".esp-field:focus-within","--esp-field-focus-shadow"),z,T`
1
+ var c=function(u,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(u,e,t,r);else for(var i=u.length-1;i>=0;i--)(a=u[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 T,LitElement as C}from"lit";import{property as d,state as S}from"lit/decorators.js";import{subscribeToRootEvent as p}from"./root-event-subscription.js";import{traverseToClosest as m}from"./utilities.js";import{parseCssColor as w,serializeOklch as x,gamutMapToSRGB as P}from"./color-engine.js";import{computeVariants as b}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as v}from"../root/helpers/compute-semantic-properties.js";import{DocumentSpriteController as E}from"./document-sprite.js";import{dataCompanionProperties as U}from"../root/helpers/data-companion-properties.js";import{dataSeriesProperties as V}from"../root/helpers/compute-theme-properties.js";import{lightnessRampProperties as I}from"../root/helpers/lightness-ramp-properties.js";import{ELEVATION_PROPERTIES as O,TYPE_ROLE_COLOR_PROPERTIES as A}from"./scale-engine.js";import{resolveContextTheme as y,resolveDataColorSource as D,semanticToCSS as z}from"./theme.js";import{alignAttributeTextInheritance as F,focusRing as N}from"./style-fragments.js";import{syncNormalizedAttribute as j}from"./attribute-helpers.js";import{INTENT_VARIANTS as k,normalizeIntentVariant as B}from"./intent-values.js";class n extends C{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!==""&&!k.includes(t)&&!this.warnedUnknownIntents.has(t)&&(this.warnedUnknownIntents.add(t),console.warn(`Espalier intent: "${t}" is not an intent; expected one of ${k.join(", ")}. Treating it as "neutral".`));const r=this.intentBacker,o=B(e);j(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=m(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=[p(e,"seed-color-changed",this.handleSeedColorChanged),p(e,"scheme-changed",this.handleSchemeChanged),p(e,"theme-changed",this.handleThemeChanged),p(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}}constructor(){super(),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()},new E(this,{reactToSpriteChanges:!1})}traverseToClosest(e){return m(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=b(s,o),i={};if(r.applied&&(Object.assign(i,v(o,a)),Object.assign(i,I(o)),Object.assign(i,O),Object.assign(i,A),Object.assign(i,U(i,V(o,s,l=>(typeof l=="string"?D(l,o.anchors):null)??o.seedColor)))),e){let l=o;r.applied||(l=this.resolveAncestorZoneTheme(t)??o);const g=l===o?a:b(s,l),R=v(l,g,{effectiveSource:(f,h)=>n.semanticActionTokens.has(f)?e:h});i["--esp-color-primary"]=x(P(g[e]));for(const f of n.semanticActionTokens){const h=z(f);i[h]=R[h]}}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.warnUnknownContextWhenSettled(t),{applied:!1,theme:e})}warnUnknownContextWhenSettled(e){if(this.warnedUnknownContexts.has(e))return;const t=this.espRoot;if(t&&!t.themeSettled){t.whenThemeSettled().then(()=>{if(!this.isConnected||this.espRoot!==t||this.context.trim()!==e)return;const r=t.activeTheme;r&&y(r,e)||this.warnUnknownContextWhenSettled(e)});return}this.warnedUnknownContexts.add(e),console.warn(`Espalier context: "${e}" is not defined by the active theme; inheriting root tokens.`)}resolveNamedContextTheme(e,t){return y(e,t)}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=[N(".esp-field:focus-within","--esp-field-focus-shadow"),F,T`
2
2
  :host {
3
3
 
4
4
  --_esp-field-resolved-hover-bg: var(
@@ -122,4 +122,4 @@ var c=function(u,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
122
122
  .esp-field:has(textarea:disabled):hover {
123
123
  background-color: var(--esp-field-background, var(--esp-color-layer-2));
124
124
  }
125
- `],c([C()],n.prototype,"seedColor",null),c([d({attribute:!1})],n.prototype,"correlationId",void 0),c([d({type:String,reflect:!0})],n.prototype,"scheme",void 0),c([d({type:String,attribute:"intent",reflect:!0,useDefault:!0})],n.prototype,"intent",null),c([d({type:String,attribute:"context",reflect:!0})],n.prototype,"context",null);export{n as EspalierElementBase};
125
+ `],c([S()],n.prototype,"seedColor",null),c([d({attribute:!1})],n.prototype,"correlationId",void 0),c([d({type:String,reflect:!0})],n.prototype,"scheme",void 0),c([d({type:String,attribute:"intent",reflect:!0,useDefault:!0})],n.prototype,"intent",null),c([d({type:String,attribute:"context",reflect:!0})],n.prototype,"context",null);export{n as EspalierElementBase};
@@ -1 +1 @@
1
- const i=["tiny","small","normal","medium","big","large","huge"],w=2,z=1.125,E=1.3333333333333333,g=[["tiny","small"],["small","normal"],["normal","medium"],["medium","big"],["big","large"],["large","huge"]],h=.375,T={rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200};function l(o,e=4){const s=10**e;return Math.round(o*s)/s}function S(o,e,s,t,r){if(Math.abs(e-o)<1e-4)return`${l(o)}rem`;const m=(e-o)*s*100/(r-t),p=o-m*t/(100*s);return`clamp(${l(o)}rem, ${l(p)}rem + ${l(m)}vw, ${l(e)}rem)`}function x(o){const e={};for(let s=0;s<i.length;s++){const t=s-2,r=1.125*o.typeRatio**t;e[i[s]]={min:r,max:r*E}}return e}function _(o){const e={};for(let s=0;s<i.length;s++){const t=h*o.spaceRatio**s;e[i[s]]={min:t,max:t*E}}return e}const v={"--esp-shadow-1":"1px 1px 4px var(--esp-color-shadow)","--esp-shadow-2":"0 2px 8px var(--esp-color-shadow)","--esp-shadow-3":"0 6px 20px var(--esp-color-shadow)"};function A(o){const e={},{rootFontSize:s,viewportMin:t,viewportMax:r,borderRadius:m}=o,p=16,a=s/p,f=x(o);for(const n of i){const{min:c,max:d}=f[n];e[`--esp-type-${n}`]=S(c*a,d*a,p,t,r)}const u=_(o);for(const n of i){const{min:c,max:d}=u[n];e[`--esp-size-${n}`]=S(c*a,d*a,p,t,r)}for(const[n,c]of g)e[`--esp-size-${n}-to-${c}`]=S(u[n].min*a,u[c].max*a,p,t,r);return e["--esp-size-font"]="var(--esp-type-normal)",e["--esp-size-padding"]="var(--esp-size-tiny-to-small)",e["--esp-size-padding-page"]="var(--esp-size-small-to-normal)",e["--esp-size-border-radius"]=`${l(m*a)}rem`,e["--esp-measure"]="66ch",e["--esp-measure-wide"]="90ch",e["--esp-size-section"]="clamp(var(--esp-size-big), 7vw, var(--esp-size-huge))",Object.assign(e,v),e["--esp-card-min"]="16rem",e}export{T as DEFAULT_SCALE_CONFIG,v as ELEVATION_PROPERTIES,i as STEP_NAMES,A as generateScaleProperties};
1
+ const l=["tiny","small","normal","medium","big","large","huge"],O=2,b=1.125,g=1.3333333333333333,f=[["tiny","small"],["small","normal"],["normal","medium"],["medium","big"],["big","large"],["large","huge"]],E=.375,z={rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200};function c(o,e=4){const t=10**e;return Math.round(o*t)/t}function d(o,e,t,s,p){if(Math.abs(e-o)<1e-4)return`${c(o)}rem`;const m=(e-o)*t*100/(p-s),n=o-m*s/(100*t);return`clamp(${c(o)}rem, ${c(n)}rem + ${c(m)}vw, ${c(e)}rem)`}function h(o){const e={};for(let t=0;t<l.length;t++){const s=t-2,p=1.125*o.typeRatio**s;e[l[t]]={min:p,max:p*g}}return e}function x(o){const e={};for(let t=0;t<l.length;t++){const s=E*o.spaceRatio**t;e[l[t]]={min:s,max:s*g}}return e}const S={"--esp-shadow-1":"1px 1px 4px var(--esp-color-shadow)","--esp-shadow-2":"0 2px 8px var(--esp-color-shadow)","--esp-shadow-3":"0 6px 20px var(--esp-color-shadow)"},_={"--esp-type-overline-color":"var(--esp-color-type-overline, var(--esp-color-text))","--esp-type-label-color":"var(--esp-color-type-label, var(--esp-color-text))","--esp-type-lead-color":"var(--esp-color-type-lead, var(--esp-color-text))","--esp-type-caption-color":"var(--esp-color-type-caption, var(--esp-color-text))"},w={"--esp-type-overline-font-size":"var(--esp-type-tiny)","--esp-type-overline-font-weight":"var(--esp-font-weight-headings)","--esp-type-overline-letter-spacing":"0.08em","--esp-type-overline-text-transform":"uppercase","--esp-type-label-font-size":"var(--esp-type-normal)","--esp-type-label-font-weight":"var(--esp-font-weight-headings)","--esp-type-label-letter-spacing":"0.01em","--esp-type-lead-font-size":"var(--esp-type-medium)","--esp-type-lead-font-weight":"var(--esp-font-weight-body)","--esp-type-lead-letter-spacing":"normal","--esp-type-caption-font-size":"var(--esp-type-small)","--esp-type-caption-font-weight":"var(--esp-font-weight-body)","--esp-type-caption-letter-spacing":"normal",..._};function P(o){const e={},{rootFontSize:t,viewportMin:s,viewportMax:p,borderRadius:m}=o,n=16,a=t/n,u=h(o);for(const r of l){const{min:i,max:v}=u[r];e[`--esp-type-${r}`]=d(i*a,v*a,n,s,p)}Object.assign(e,w);const y=x(o);for(const r of l){const{min:i,max:v}=y[r];e[`--esp-size-${r}`]=d(i*a,v*a,n,s,p)}for(const[r,i]of f)e[`--esp-size-${r}-to-${i}`]=d(y[r].min*a,y[i].max*a,n,s,p);return e["--esp-size-font"]="var(--esp-type-normal)",e["--esp-size-padding"]="var(--esp-size-tiny-to-small)",e["--esp-size-padding-page"]="var(--esp-size-small-to-normal)",e["--esp-size-border-radius"]=`${c(m*a)}rem`,e["--esp-measure"]="66ch",e["--esp-measure-wide"]="90ch",e["--esp-size-section"]="clamp(var(--esp-size-big), 7vw, var(--esp-size-huge))",Object.assign(e,S),e["--esp-card-min"]="16rem",e}export{z as DEFAULT_SCALE_CONFIG,S as ELEVATION_PROPERTIES,l as STEP_NAMES,_ as TYPE_ROLE_COLOR_PROPERTIES,w as TYPE_ROLE_PROPERTIES,P as generateScaleProperties};
@@ -186,7 +186,7 @@ export interface ThemeFitLint {
186
186
  id: "action-canvas-separation" | "link-hover-ordering";
187
187
  /** Lints describe design-quality hazards, not validation failures. */
188
188
  severity: "warning";
189
- /** The tokens the finding is about. */
189
+ /** The tokens the finding is about, recommended retune target first. */
190
190
  tokens: SemanticColorName[];
191
191
  /** The measured number the lint fired on (ΔE-OK, or an Lc deficit). */
192
192
  measured: number;
@@ -1 +1 @@
1
- import{apcaContrast as h,deltaEOK as f,parseOklch as p,serializeOklch as v}from"./color-engine.js";import{DEFAULT_DARK_THEME as T,DEFAULT_LIGHT_THEME as R,explicitMappingTokens as $,mergeTheme as m,parseAnchorSource as x,resolveContextTheme as A}from"./theme.js";import{computeThemeProperties as H}from"../root/helpers/compute-theme-properties.js";function _(e,t,n={}){let o=e,r=null;if(n.context!==void 0){const c=A(e,n.context);if(!c)throw new Error(`themeFitReport: context "${n.context}" is not defined by the theme.`);o=c,r=new Set(Object.keys(e.contexts[n.context]?.semanticMappings??{}))}const i=[];H(o,t,i);const l=$(o),u=i.map(c=>{const s=j(c);return l.has(s.token)&&(s.explicit=r===null||r.has(s.token)?"declared":"inherited"),s});return{scheme:t,seedColor:o.seedColor,anchors:M(o.anchors),tokens:u,adjustedTokens:u.filter(c=>c.adjusted).map(c=>c.token)}}function w(e){return e.tokens.map(t=>({token:t.token,source:t.source,requested:t.requested,resolved:t.resolved,apca:I(t),anchor:F(t)}))}function D(e){const t=e.adjustedTokens.length>0?`APCA moved ${e.adjustedTokens.join(", ")}`:"APCA moved nothing";console.info(`Espalier theme fit \u2014 ${e.scheme} scheme, seed ${e.seedColor}. ${t}.`),console.table(w(e))}const L=.045,b=.5,k=75,O=.045;function C(e){const t=[],n=new Map(e.tokens.map(s=>[s.token,s.resolved])),o=s=>{const a=n.get(s);return a===void 0?null:p(a)},r=o("background"),i=o("actionBackground");if(r&&i){const s=f(i,r);if(s<L){const a=d(s,4);t.push({id:"action-canvas-separation",severity:"warning",tokens:["actionBackground","background"],measured:a,message:`actionBackground sits \u0394E ${a} from background (floor ${L}) \u2014 filled actions vanish into this canvas. Retune the surface apart: move the background stop, or pin actionBackground to a separated stop.`})}}const l=o("link"),u=o("linkHover"),c=o("linkHoverBg");if(r&&l&&u&&c){const s=Math.abs(h(l,r)),a=Math.abs(h(u,c));f(c,r)>=O?a+b<k&&t.push({id:"link-hover-ordering",severity:"warning",tokens:["linkHover","linkHoverBg"],measured:d(k-a,1),message:`linkHover reaches only Lc ${d(a,1)} on the linkHoverBg wash it actually paints (tier ${k}) \u2014 retune linkHover or the wash apart until the hovered state clears the text tier.`}):a+b<s&&t.push({id:"link-hover-ordering",severity:"warning",tokens:["linkHover","link"],measured:d(s-a,1),message:`linkHover reads weaker than link on the same canvas (Lc ${d(a,1)} vs ${d(s,1)}) \u2014 a dimming hover feels disabled. Retune linkHover toward more contrast than the resting link.`})}return t}const g=":root";function V(e,t){const n=m(R,e),o=m(T,t),r=[g,...[...new Set([...Object.keys(n.contexts),...Object.keys(o.contexts)])].sort()],i=(l,u)=>{const c=[];for(const s of r){if(s!==g&&!(s in l.contexts))continue;const a=_(l,u,s===g?{}:{context:s});c.push({...a,surface:s,lints:C(a)})}return c};return{surfaces:r,light:i(n,"light"),dark:i(o,"dark")}}function d(e,t){const n=Math.pow(10,t);return Math.round(e*n)/n}function E(e,t){return t===void 0?e:`${e}.${t}`}function M(e){const t={};for(const[n,o]of Object.entries(e)){if(typeof o=="string"){t[n]=o;continue}for(const[r,i]of Object.entries(o))t[r==="color"?n:E(n,r)]=i}return t}function j(e){const t=p(e.resolved),n=e.requested===void 0?e.resolved:v(e.requested),o={token:e.token,property:e.property,source:e.source,lightness:e.lightness,requested:n,resolved:e.resolved,adjusted:n!==e.resolved,sourceResolved:e.sourceResolved},r=x(e.source);if(r&&e.sourceResolved&&(o.anchor={reference:E(r.name,r.slot),color:v(e.base),deltaE:d(f(e.base,t),4)}),e.contrast){const i=e.contrast.background;o.apca={from:n,to:e.resolved,targetLc:e.contrast.targetLc,against:e.contrast.against,againstColor:v(i),fromLc:d(Math.abs(h(p(n),i)),1),toLc:d(Math.abs(h(t,i)),1)}}return o}function I(e){if(!e.apca)return"";const{targetLc:t,against:n,fromLc:o,toLc:r}=e.apca;return e.adjusted?`Lc ${t} vs ${n} \u2014 pushed from Lc ${o} to Lc ${r}`:`Lc ${t} vs ${n} \u2014 met at Lc ${o}`}function F(e){return e.anchor?`${e.anchor.reference} \u0394E ${e.anchor.deltaE}`:e.sourceResolved?"":"unresolved \u2014 seed used"}export{g as ROOT_SURFACE,D as printThemeFitReport,C as themeFitLints,_ as themeFitReport,V as themeFitReportSuite,w as themeFitRows};
1
+ import{apcaContrast as h,deltaEOK as f,parseOklch as p,serializeOklch as k}from"./color-engine.js";import{DEFAULT_DARK_THEME as T,DEFAULT_LIGHT_THEME as R,explicitMappingTokens as $,mergeTheme as m,parseAnchorSource as x,resolveContextTheme as H}from"./theme.js";import{computeThemeProperties as A}from"../root/helpers/compute-theme-properties.js";function _(e,o,n={}){let t=e,r=null;if(n.context!==void 0){const c=H(e,n.context);if(!c)throw new Error(`themeFitReport: context "${n.context}" is not defined by the theme.`);t=c,r=new Set(Object.keys(e.contexts[n.context]?.semanticMappings??{}))}const i=[];A(t,o,i);const l=$(t),u=i.map(c=>{const s=j(c);return l.has(s.token)&&(s.explicit=r===null||r.has(s.token)?"declared":"inherited"),s});return{scheme:o,seedColor:t.seedColor,anchors:M(t.anchors),tokens:u,adjustedTokens:u.filter(c=>c.adjusted).map(c=>c.token)}}function w(e){return e.tokens.map(o=>({token:o.token,source:o.source,requested:o.requested,resolved:o.resolved,apca:I(o),anchor:B(o)}))}function D(e){const o=e.adjustedTokens.length>0?`APCA moved ${e.adjustedTokens.join(", ")}`:"APCA moved nothing";console.info(`Espalier theme fit \u2014 ${e.scheme} scheme, seed ${e.seedColor}. ${o}.`),console.table(w(e))}const L=.045,b=.5,v=75,O=.045;function C(e){const o=[],n=new Map(e.tokens.map(s=>[s.token,s.resolved])),t=s=>{const a=n.get(s);return a===void 0?null:p(a)},r=t("background"),i=t("actionBackground");if(r&&i){const s=f(i,r);if(s<L){const a=d(s,4);o.push({id:"action-canvas-separation",severity:"warning",tokens:["actionBackground","background"],measured:a,message:`actionBackground sits \u0394E ${a} from background (floor ${L}) \u2014 filled actions vanish into this canvas. Retune the surface apart: move the background stop, or pin actionBackground to a separated stop.`})}}const l=t("link"),u=t("linkHover"),c=t("linkHoverBg");if(r&&l&&u&&c){const s=Math.abs(h(l,r)),a=Math.abs(h(u,c));f(c,r)>=O?a+b<v&&o.push({id:"link-hover-ordering",severity:"warning",tokens:["linkHoverBg","linkHover"],measured:d(v-a,1),message:`linkHover reaches only Lc ${d(a,1)} on the linkHoverBg wash it actually paints (tier ${v}) \u2014 retune linkHoverBg before changing linkHover; the wash has one consumer while the ink has many.`}):a+b<s&&o.push({id:"link-hover-ordering",severity:"warning",tokens:["linkHover","link"],measured:d(s-a,1),message:`linkHover reads weaker than link on the same canvas (Lc ${d(a,1)} vs ${d(s,1)}) \u2014 a dimming hover feels disabled. Retune linkHover toward more contrast than the resting link.`})}return o}const g=":root";function V(e,o){const n=m(R,e),t=m(T,o),r=[g,...[...new Set([...Object.keys(n.contexts),...Object.keys(t.contexts)])].sort()],i=(l,u)=>{const c=[];for(const s of r){if(s!==g&&!(s in l.contexts))continue;const a=_(l,u,s===g?{}:{context:s});c.push({...a,surface:s,lints:C(a)})}return c};return{surfaces:r,light:i(n,"light"),dark:i(t,"dark")}}function d(e,o){const n=Math.pow(10,o);return Math.round(e*n)/n}function E(e,o){return o===void 0?e:`${e}.${o}`}function M(e){const o={};for(const[n,t]of Object.entries(e)){if(typeof t=="string"){o[n]=t;continue}for(const[r,i]of Object.entries(t))o[r==="color"?n:E(n,r)]=i}return o}function j(e){const o=p(e.resolved),n=e.requested===void 0?e.resolved:k(e.requested),t={token:e.token,property:e.property,source:e.source,lightness:e.lightness,requested:n,resolved:e.resolved,adjusted:n!==e.resolved,sourceResolved:e.sourceResolved},r=x(e.source);if(r&&e.sourceResolved&&(t.anchor={reference:E(r.name,r.slot),color:k(e.base),deltaE:d(f(e.base,o),4)}),e.contrast){const i=e.contrast.background;t.apca={from:n,to:e.resolved,targetLc:e.contrast.targetLc,against:e.contrast.against,againstColor:k(i),fromLc:d(Math.abs(h(p(n),i)),1),toLc:d(Math.abs(h(o,i)),1)}}return t}function I(e){if(!e.apca)return"";const{targetLc:o,against:n,fromLc:t,toLc:r}=e.apca;return e.adjusted?`Lc ${o} vs ${n} \u2014 pushed from Lc ${t} to Lc ${r}`:`Lc ${o} vs ${n} \u2014 met at Lc ${t}`}function B(e){return e.anchor?`${e.anchor.reference} \u0394E ${e.anchor.deltaE}`:e.sourceResolved?"":"unresolved \u2014 seed used"}export{g as ROOT_SURFACE,D as printThemeFitReport,C as themeFitLints,_ as themeFitReport,V as themeFitReportSuite,w as themeFitRows};
@@ -148,7 +148,7 @@ export declare function resolveAnchorColor(anchors: ThemeAnchors, reference: Anc
148
148
  */
149
149
  export declare function resolveDataColorSource(source: string, anchors: ThemeAnchors): string | null;
150
150
  /** Every semantic color token the system computes. */
151
- export type SemanticColorName = "background" | "layer1" | "layer2" | "layer3" | "layer4" | "actionBackground" | "actionText" | "border" | "shadow" | "text" | "dangerText" | "headings" | "headingsHover" | "link" | "linkHover" | "linkHoverBg" | "inputCaret" | "inputSelection" | "inputSelectionBg";
151
+ export type SemanticColorName = "background" | "layer1" | "layer2" | "layer3" | "layer4" | "actionBackground" | "actionText" | "border" | "shadow" | "text" | "typeOverline" | "typeLabel" | "typeLead" | "typeCaption" | "dangerText" | "headings" | "headingsHover" | "link" | "linkHover" | "linkHoverBg" | "inputCaret" | "inputSelection" | "inputSelectionBg";
152
152
  /** Chroma range enforced on a semantic token before gamut mapping. */
153
153
  export interface ChromaRange {
154
154
  /** Minimum chroma (≥ 0). */
@@ -176,7 +176,7 @@ export type SemanticMappings = Record<SemanticColorName, SemanticMapping>;
176
176
  * The designer-facing color roles.
177
177
  *
178
178
  * `semantic-groups.md` has always described these groups and then warned
179
- * that exposing the nineteen raw tokens is "handing users the engine
179
+ * that exposing the twenty-three raw tokens is "handing users the engine
180
180
  * room instead of the dashboard" — but the groups were documentation
181
181
  * only. Roles make them addressable: a sentence a designer would say
182
182
  * becomes a line of theme.
@@ -249,7 +249,7 @@ export declare const ROLE_NAMES: readonly RoleName[];
249
249
  * Which semantic tokens each role slot paints, and at which ramp stop.
250
250
  *
251
251
  * This is the compilation table: it turns five designer-facing roles
252
- * into the nineteen engine-room tokens. `dangerText` is absent by
252
+ * into the twenty-three engine-room tokens. `dangerText` is absent by
253
253
  * design — the status family is reserved and keeps its own source.
254
254
  *
255
255
  * The `accent` role has no body-text slot on purpose. "Rose is
@@ -1 +1 @@
1
- import{UNSAFE_KEYS as st,isSafeKey as v}from"./unsafe-keys.js";import{ACCEPTED_COLOR_FORMS as te,apcaContrast as rt,clampChannel as me,deltaEOK as at,deriveSemantic as ae,gamutMapToSRGB as de,linearRgbToOklab as it,oklchToSRGB as ct,parseCssColor as W,parseOklch as ut,serializeOklch as ie,srgbToLinearRGB as ft}from"./color-engine.js";import{computeVariants as he,parseAnchorSource as lt,resolveAnchorColor as pt,resolveMappingSource as ce}from"./variant-engine.js";import{auditColorDistances as He,auditDataPalette as mt,DATA_SERIES_KEYS as ue,DEFAULT_DATA_PALETTE as ge,DEFAULT_DATA_RAMP_STEPS as dt,MAX_DATA_RAMP_STEPS as ye,MIN_DATA_RAMP_LIGHTNESS_STEP as Le,MIN_DATA_RAMP_STEPS as be}from"./data-colors.js";const V=/^[a-z][a-z0-9-]*$/;function $e(e){return lt(e)}function Pe(e,n){return pt(e,n)}function ht(e,n){const t=$e(e);if(t){const o=Pe(n,t);return o&&W(o)?o:null}return W(e)?e:null}const ne=["canvas","ink","accent","action","structure"],Se={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"]]}},gt=new Set(["action.color"]),yt={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},bt={"action.ink":{role:"canvas",slot:"color"}},$t=.45,St=.045;function De(e,n,t){const o=We.actionText,a=[...j].sort((g,x)=>e[g]-e[x]||j.indexOf(g)-j.indexOf(x)),c=n?a.filter(g=>n(g)>=o.targetLc):a,f=t?c.filter(g=>t(g)>=St):c,p=f.length>0?f:c,m=p.length>0?p:a;let O,k=1/0;for(const g of m){const x=Math.abs(e[g]-$t);x<k&&(k=x,O=g)}return O??"muted"}function kt(e,n){const t=n[e]>.5;let o=j[0];for(const a of j)(t?n[a]<n[o]:n[a]>n[o])&&(o=a);return o}const xt={"accent.hover":"text"};function At(e,n){const t=new Map;try{const o=le(n,e),a=(c,f,p,m)=>{const O=$e(f),k=O?Pe(m,O):null,g=k===null?null:W(k),x=t.get(c)??[];x.some(P=>P.source===f&&P.chroma===g?.c)||(x.push({source:f,where:p,chroma:g?.c}),t.set(c,x))};for(const[c,f]of Object.entries(o.semanticMappings))f.source.startsWith("anchor:")&&a(c,f.source,"the root table",o.anchors);for(const c of Object.keys(o.contexts)){const f=Xe(o,c);if(f)for(const[p,m]of Object.entries(f.semanticMappings))m.source.startsWith("anchor:")&&a(p,m.source,`contexts.${c}`,f.anchors)}}catch{return new Map}return t}function q(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 Ne(e,n,t,o={}){const a={},c={};for(const[f,p]of Object.entries(o.explicitMappings??{}))p!==void 0&&(c[f]=p.lightness);for(const f of ne){const p=e[f];if(p!==void 0)for(const[m,O]of Object.entries(Se[f])){const k=bt[`${f}.${m}`];let g=q(p,m),x=!1;if(g===void 0){k&&(g=q(e[k.role],k.slot),g??=t[yt[k.role]]?.source,x=g!==void 0);const P=xt[`${f}.${m}`];P!==void 0&&(g??=q(p,P)),g??=q(p,"color")}if(g!==void 0)for(const[P,s]of O){let r=s;if(gt.has(`${f}.${m}`))r=De(n,o.actionSurfaceContrast?i=>o.actionSurfaceContrast(g,i):void 0,o.actionSurfaceSeparation?i=>o.actionSurfaceSeparation(g,i):void 0);else if(x&&k){const i=We[P],u=(i&&c[i.bg])??De(n,o.actionSurfaceContrast?d=>o.actionSurfaceContrast(q(p,"color"),d):void 0,o.actionSurfaceSeparation?d=>o.actionSurfaceSeparation(q(p,"color"),d):void 0);r=kt(u,n)}a[P]={source:g,lightness:r}}}}return a}const We={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:"linkHoverBg",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},Q=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],ke=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],ee=["danger","success","warning","info"],Mt=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],j=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],vt={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},Ot={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},xe={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"}},J=.4;function Ae(){const e={};for(const n of Q)e[n]={min:0,max:J};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:Ae(),semanticMappings:{...xe},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{}},Me={...Fe,chroma:Ae(),semanticMappings:{...xe},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{},lightness:{...vt}},je={...Fe,chroma:Ae(),semanticMappings:{...xe},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{},lightness:{...Ot}},fe=new WeakMap;fe.set(Me,new Set),fe.set(je,new Set);function Rt(e,n){return st.has(e)?void 0:n}function Jt(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function Ct(e){try{const n=Ke(e),t=JSON.parse(n,Rt);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}const ve="\xEF\xBB\xBF";function Tt(e){if(/^[\u0000-\u007f]*$/.test(e))return btoa(e);const n=new TextEncoder().encode(e);let t=ve;for(const o of n)t+=String.fromCharCode(o);return btoa(t)}function Ke(e){const n=atob(e);if(!n.startsWith(ve))return n;const t=Uint8Array.from(n.slice(ve.length),o=>o.charCodeAt(0));return new TextDecoder("utf-8",{fatal:!0}).decode(t)}function Oe(e){return Tt(JSON.stringify(e))}function Bt(e){const n={};for(const t of ee){const o=e[t];typeof o=="string"&&(n[t]=o.startsWith("anchor:")?o:oe(o))}return n}function oe(e){if(ut(e))return e;const n=W(e);return n?ie(n):e}function Ue(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&(t[o]=a);if(!n)return t;for(const[o,a]of Object.entries(n)){if(a===void 0||!v(o))continue;const c=t[o];if(c!==void 0&&typeof a=="object"&&a!==null){const f={};if(typeof c=="string")f.color=c;else for(const[p,m]of Object.entries(c))v(p)&&(f[p]=m);for(const[p,m]of Object.entries(a))m!==void 0&&v(p)&&(f[p]=m);t[o]=f;continue}t[o]=a}return t}function ze(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const n=e,t={};for(const o of ne){const a=n[o];a!==void 0&&(t[o]=a)}if(typeof n.lightness=="object"&&n.lightness!==null&&!Array.isArray(n.lightness)){const o={};for(const a of j){const c=n.lightness[a];c!==void 0&&(o[a]=c)}t.lightness=o}if(typeof n.semanticMappings=="object"&&n.semanticMappings!==null&&!Array.isArray(n.semanticMappings)){const o={};for(const[a,c]of Object.entries(n.semanticMappings)){if(!v(a)||!Q.includes(a)||typeof c!="object"||c===null||Array.isArray(c))continue;const{source:f,lightness:p}=c;typeof f=="string"&&(typeof p!="string"||!j.includes(p)||(o[a]={source:f,lightness:p}))}Object.keys(o).length>0&&(t.semanticMappings=o)}return t}function wt(e,n){const t={};for(const[o,a]of Object.entries(e)){if(!v(o)||!V.test(o))continue;const c=ze(a);c&&(t[o]=c)}if(!n)return t;for(const[o,a]of Object.entries(n)){if(!v(o)||!V.test(o)||a===void 0)continue;const c=ze(a);if(!c)continue;const f=t[o];t[o]={...f??{},...c,...f?.lightness||c.lightness?{lightness:{...f?.lightness,...c.lightness}}:{},...f?.semanticMappings||c.semanticMappings?{semanticMappings:{...f?.semanticMappings,...c.semanticMappings}}:{}}}return t}function K(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function U(e){const n={};for(const[t,o]of Object.entries(e))o!==void 0&&v(t)&&(n[t]=o);return n}function Ge(e){if(!K(e))return e;const n=U(e);return K(e.lightness)&&(n.lightness=U(e.lightness)),n}function Et(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&(t[o]=Ge(a));if(!n)return t;for(const[o,a]of Object.entries(n)){if(!v(o)||a===void 0)continue;const c=t[o];if(!K(c)||!K(a)){t[o]=Ge(a);continue}const f={...U(c),...U(a)};K(c.lightness)&&K(a.lightness)?f.lightness={...U(c.lightness),...U(a.lightness)}:K(a.lightness)&&(f.lightness=U(a.lightness)),K(c.semanticMappings)&&K(a.semanticMappings)?f.semanticMappings={...U(c.semanticMappings),...U(a.semanticMappings)}:K(a.semanticMappings)&&(f.semanticMappings=U(a.semanticMappings)),t[o]=f}return t}function _t(e){const n={};for(const[t,o]of Object.entries(e)){if(!v(t))continue;if(typeof o=="string"){n[t]=oe(o);continue}const a={};for(const[c,f]of Object.entries(o))v(c)&&(a[c]=typeof f=="string"?oe(f):f);n[t]=a}return n}function se(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:oe(e)}function It(e){const n={};for(const t of ue)n[t]=se(e[t]);return n}function Ve(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&V.test(o)&&a&&typeof a=="object"&&!Array.isArray(a)&&(t[o]={...a});if(!n)return t;for(const[o,a]of Object.entries(n)){if(!v(o)||!V.test(o)||!a||typeof a!="object"||Array.isArray(a))continue;const c=t[o],f=c!==void 0&&a.type!==void 0&&a.type!==c.type;t[o]={...f?{}:c??{},...a}}return t}function Ht(e){const n={};for(const[t,o]of Object.entries(e))if(v(t)){if(o.type==="sequential"&&typeof o.source=="string"){n[t]={...o,source:se(o.source)};continue}if(o.type==="diverging"&&typeof o.start=="string"&&typeof o.end=="string"){n[t]={...o,start:se(o.start),end:se(o.end),...typeof o.neutral=="string"?{neutral:se(o.neutral)}:{}};continue}n[t]={...o}}return n}function Je(e){const n=W(e.seedColor);if(!n)return;const t=he(n,e);return(o,a)=>{const c=ce(o,t,e.anchors)??t.primary,f=e.chroma.actionBackground,p=ae(c,e.lightness[a],f.min,f.max),m={l:p.l>.5?0:1,c:0,h:0};return Math.abs(rt(m,p))}}function Lt(e,n,t){if(n?.background)return n.background;const o=q(e.canvas,"color");if(o!==void 0){const a=Se.canvas.color?.find(([c])=>c==="background");if(a)return{source:o,lightness:a[1]}}return t.background}function Ye(e,n){const t=W(e.seedColor);if(!t||!n)return;const o=he(t,e),a=ce(n.source,o,e.anchors)??o.primary,c=e.chroma.background,f=ae(a,e.lightness[n.lightness],c.min,c.max);return(p,m)=>{const O=ce(p,o,e.anchors)??o.primary,k=e.chroma.actionBackground,g=ae(O,e.lightness[m],k.min,k.max);return at(g,f)}}function Pt(e){const n=fe.get(e);if(n)return new Set(n);const t=new Set,o=Ne(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:Je(e),actionSurfaceSeparation:Ye(e,e.semanticMappings.background)});for(const[a,c]of Object.entries(o)){const f=e.semanticMappings[a];(f.source!==c.source||f.lightness!==c.lightness)&&t.add(a)}return t}function le(e,n){const t={...e.roles,...n.roles},o=wt(e.contexts,n.contexts),a={...e.lightness,...n.lightness},c=_t(Ue(e.anchors,n.anchors)),f=typeof n.seedColor=="string"?oe(n.seedColor):e.seedColor,p=n.semanticMappings,m={...e.angles,...n.angles},O={...e.semanticHues,...n.semanticHues},k={...e.variantChroma,...n.variantChroma},g=Bt({...e.intents,...n.intents}),x=re(e.chroma,n.chroma),P=It(re(e.dataPalette,n.dataPalette)),s=Ht(Ve(e.dataRamps,n.dataRamps)),r=Pt(e),i=new Set(r),u={};for(const S of r)u[S]=e.semanticMappings[S];for(const[S,A]of Object.entries(p??{}))A!==void 0&&(i.add(S),u[S]=A);const d=re(e.semanticMappings,p),y={angles:m,anchors:c,chroma:x,intents:g,lightness:a,seedColor:f,semanticHues:O,variantChroma:k},E=Je(y),D=Ye(y,Lt(t,u,d)),l=Ne(t,a,d,{explicitMappings:u,actionSurfaceContrast:E,actionSurfaceSeparation:D}),b={};for(const[S,A]of Object.entries(l))i.has(S)||(b[S]=A);const $=re(re(e.semanticMappings,b),p),h={...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:m,semanticHues:O,variantChroma:k,intents:g,lightness:a,chroma:x,semanticMappings:$,anchors:c,roles:t,contexts:o,dataPalette:P,dataRamps:s};return n.pageBackgroundImage!==void 0&&(h.pageBackgroundImage=n.pageBackgroundImage),n.pageBackgroundImageOpacity!==void 0&&(h.pageBackgroundImageOpacity=n.pageBackgroundImageOpacity),n.boxBackgroundImage!==void 0&&(h.boxBackgroundImage=n.boxBackgroundImage),n.boxBackgroundImageOpacity!==void 0&&(h.boxBackgroundImageOpacity=n.boxBackgroundImageOpacity),n.vellumOpacity!==void 0&&(h.vellumOpacity=n.vellumOpacity),n.vellumBackgroundImage!==void 0&&(h.vellumBackgroundImage=n.vellumBackgroundImage),n.vellumBackgroundImageOpacity!==void 0&&(h.vellumBackgroundImageOpacity=n.vellumBackgroundImageOpacity),fe.set(h,new Set(i)),h}const qe=new WeakMap;function Xe(e,n){const t=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,n)?e.contexts[n]:void 0;if(!t)return null;let o=qe.get(e);const a=o?.get(n);if(a)return a;const c={};for(const p of ne){const m=t[p];m!==void 0&&(c[p]=m)}const f=le(e,{lightness:t.lightness,roles:c,semanticMappings:t.semanticMappings});return o||(o=new Map,qe.set(e,o)),o.set(n,f),f}function re(e,n){if(!n)return{...e};const t={...e};for(const o of Object.keys(n)){const a=n[o];a!==void 0&&(t[o]=a)}return t}function Re(e){let n;try{n=Ke(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 Yt(e){const n=Re(e);return n.error!==void 0?{valid:!1,errors:[n.error],warnings:[]}:Ce(n.value)}function Ce(e,n=Me){const t=[],o=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):W(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${te}.`));for(const s of["fontBody","fontHeadings","fontBrand","fontMonospace"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);const a=["normal","bold","lighter","bolder"],c=["inherit","initial","unset","revert","revert-layer"];for(const s of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(s in e){const r=e[s];if(typeof r=="number")(r<1||r>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got ${r}).`);else if(typeof r=="string"){const i=a.includes(r)||c.includes(r);if(/^\d+$/.test(r)){const d=Number(r);(d<1||d>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got "${r}").`)}else i||o.push(`${s} = "${r}" is not a standard font-weight value.`)}else t.push(`${s} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(s=>typeof s!="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[s,r,i]of f)if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const u=e[s];r!==void 0&&u<r&&t.push(`${s} must be \u2265 ${r} (got ${u}).`),i!==void 0&&u>i&&o.push(`${s} = ${u} is unusually high (max ${i}).`)}for(const s of["typeRatio","spaceRatio"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];r<=1&&t.push(`${s} must be > 1 (got ${r}).`);const i=s==="typeRatio"?1.3:2;r>i&&o.push(`${s} = ${r} is very high (max ${i}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const s=e.viewportMin,r=e.viewportMax;typeof s=="number"&&typeof r=="number"&&s>=r&&t.push(`viewportMin (${s}) 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 s=e.angles;for(const r of["analogous","complementary","splitComplementary","triadic"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`angles.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.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 s=e.semanticHues;for(const r of["danger","success","warning","info"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`semanticHues.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.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 s=e.variantChroma;for(const r of Mt)if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`variantChroma["${r}"] must be a finite number.`);else{const i=s[r];i<0&&t.push(`variantChroma["${r}"] must be \u2265 0 (got ${i}).`),i>J&&o.push(`variantChroma["${r}"] = ${i} exceeds ${J}.`)}}function p(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const u of j)if(u in i)if(typeof i[u]!="number"||!isFinite(i[u]))t.push(`${r}.${u} must be a finite number.`);else{const d=i[u];(d<0||d>1)&&t.push(`${r}.${u} must be 0\u20131 (got ${d}).`)}}if("lightness"in e&&p(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const s=e.chroma,r=At(e,n);for(const i of Q)if(i in s){const u=s[i];if(typeof u!="object"||u===null){t.push(`chroma.${i} must be { min, max }.`);continue}const d=u;for(const E of r.get(i)??[])E.chroma!==void 0&&typeof d.min=="number"&&typeof d.max=="number"&&(E.chroma<d.min-1e-9||E.chroma>d.max+1e-9)&&o.push(`chroma.${i} clamps the anchor-sourced token ${i} ("${E.source}", effective in ${E.where}) and moves it off its declared swatch. Remove the band if that is unintended \u2014 anchors otherwise keep their own chroma.`);const y=u;(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>J)&&t.push(`chroma.${i}.max must be 0\u2013${J}.`),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[s,r]of Object.entries(e.anchors))if(v(s)?V.test(s)||t.push(`anchors: "${s}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${s}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),ke.includes(s)&&t.push(`anchors: "${s}" collides with a reserved color source name.`),typeof r=="string")W(r)||t.push(`anchors.${s} is not a valid CSS color: "${r}". Accepted forms: ${te}.`);else if(typeof r=="object"&&r!==null&&!Array.isArray(r)){const i=r;typeof i.color!="string"&&t.push(`anchors.${s} must declare its base "color".`);for(const[u,d]of Object.entries(i))v(u)?u!=="color"&&!V.test(u)&&t.push(`anchors.${s}: "${u}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${s}: "${u}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof d!="string"?t.push(`anchors.${s}.${u} must be a CSS color string.`):W(d)||t.push(`anchors.${s}.${u} is not a valid CSS color: "${d}". Accepted forms: ${te}.`)}else t.push(`anchors.${s} 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[s,r]of Object.entries(e.anchors))m.set(s,r);function O(s,r){const i=$e(s);if(!i){t.push(`${r} "${s}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!m.has(i.name)){const u=[...m.keys()];t.push(`${r} references undeclared anchor "${i.name}". Declared anchors: ${u.length>0?u.join(", "):"(none)"}.`);return}if(i.slot!==void 0){const u=m.get(i.name);if(typeof(typeof u=="object"&&u!==null&&!Array.isArray(u)?u[i.slot]:void 0)!="string"){const y=typeof u=="object"&&u!==null?Object.keys(u).filter(E=>E!=="color"):[];t.push(`${r} references unknown slot "${i.slot}" on anchor "${i.name}". Declared slots: ${y.length>0?y.join(", "):"(none)"}.`)}}}function k(s,r){if(s.startsWith("anchor:")){O(s,r);return}ke.includes(s)||t.push(`${r} must be one of: ${ke.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[s,r]of Object.entries(e.intents)){const i=`intents.${s}`;if(!ee.includes(s)){t.push(`${i} is not a status family; expected one of: ${ee.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:")){O(r,i);continue}W(r)||t.push(`${i} "${r}" is not a supported color form or anchor: reference. Accepted forms: ${te}, 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 g(s,r){if(s.startsWith("anchor:")){O(s,r);return}W(s)||t.push(`${r} is not a valid CSS color: "${s}". Accepted forms: ${te}, 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 s=e.dataPalette;for(const[r,i]of Object.entries(s)){if(!ue.includes(r)){t.push(`dataPalette.${r} is not a series slot; expected one of: ${ue.join(", ")}.`);continue}typeof i!="string"?t.push(`dataPalette.${r} must be a CSS color or anchor reference string.`):g(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[s,r]of Object.entries(e.dataRamps)){if(v(s)?V.test(s)||t.push(`dataRamps: "${s}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${s}" 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.${s} must be a sequential or diverging ramp object.`);continue}const i=r,u=i.steps??dt;if((typeof u!="number"||!Number.isInteger(u)||u<be||u>ye)&&t.push(`dataRamps.${s}.steps must be an integer from ${be} through ${ye}.`),i.type==="sequential"){typeof i.source!="string"?t.push(`dataRamps.${s}.source must be a CSS color or anchor reference string.`):g(i.source,`dataRamps.${s}.source`);const d=i.lightnessStart??.95,y=i.lightnessEnd??.25;for(const[E,D]of[["lightnessStart",d],["lightnessEnd",y]])(typeof D!="number"||!Number.isFinite(D)||D<0||D>1)&&t.push(`dataRamps.${s}.${E} must be a finite number from 0 through 1.`);typeof d=="number"&&typeof y=="number"&&d<=y?t.push(`dataRamps.${s}.lightnessStart must be greater than lightnessEnd.`):typeof d=="number"&&Number.isFinite(d)&&typeof y=="number"&&Number.isFinite(y)&&typeof u=="number"&&Number.isInteger(u)&&u>=be&&u<=ye&&(d-y)/(u-1)<=Le&&t.push(`dataRamps.${s} lightness bounds must leave more than ${Le} lightness between serialized stops.`);continue}if(i.type==="diverging"){typeof u=="number"&&Number.isInteger(u)&&u%2===0&&t.push(`dataRamps.${s}.steps must be odd so the neutral is the exact midpoint.`);for(const d of["start","end"])typeof i[d]!="string"?t.push(`dataRamps.${s}.${d} must be a CSS color or anchor reference string.`):g(i[d],`dataRamps.${s}.${d}`);"neutral"in i&&(typeof i.neutral!="string"?t.push(`dataRamps.${s}.neutral must be a CSS color or anchor reference string.`):g(i.neutral,`dataRamps.${s}.neutral`));continue}t.push(`dataRamps.${s}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const s=le(Me,e),r={};let i=!0;for(const u of ue){const d=ht(s.dataPalette[u],s.anchors);if(!d){i=!1;break}r[u]=d}if(i)for(const u of mt(r))o.push(`dataPalette.${u.series[0]} and dataPalette.${u.series[1]} are only ${u.distance.toFixed(4)} apart under ${u.simulation} simulation (minimum ${u.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function x(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const[u,d]of Object.entries(i)){const y=`${r}.${u}`;if(!ne.includes(u)){t.push(`${y} is not a role; expected one of: ${ne.join(", ")}. (The status family is reserved and is not a role.)`);continue}const E=u,D=Se[E];if(typeof d=="string"){k(d,y);continue}if(typeof d!="object"||d===null||Array.isArray(d)){t.push(`${y} must be a color source or a { color, \u2026slots } object.`);continue}const l=d;typeof l.color!="string"&&t.push(`${y} must declare its base "color".`);for(const[b,$]of Object.entries(l)){if(!Object.prototype.hasOwnProperty.call(D,b)||!v(b)){const h=Object.keys(D).filter(S=>S!=="color");t.push(`${y}.${b} is not a slot of the ${E} role. Declared slots: ${h.length>0?h.join(", "):"(none)"}.`);continue}typeof $!="string"?t.push(`${y}.${b} must be a color source string.`):k($,`${y}.${b}`)}}}if("roles"in e&&x(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[s,r]of Object.entries(e.contexts)){if(!v(s)||!V.test(s)){t.push(`contexts.${s} must be a lowercase slug matching ${V.source}.`);continue}if(typeof r!="object"||r===null||Array.isArray(r)){x(r,`contexts.${s}`);continue}const i=r,u=Object.fromEntries(Object.entries(i).filter(([d])=>d!=="lightness"&&d!=="semanticMappings"));x(u,`contexts.${s}`),"lightness"in i&&p(i.lightness,`contexts.${s}.lightness`),"semanticMappings"in i&&P(i.semanticMappings,`contexts.${s}.semanticMappings`)}function P(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const u of Object.keys(i))Q.includes(u)||t.push(`${r}.${u} is not a semantic token; expected one of: ${Q.join(", ")}.`);for(const u of Q)if(u in i){const d=i[u];if(typeof d!="object"||d===null){t.push(`${r}.${u} must be { source, lightness }.`);continue}const y=d;typeof y.source!="string"?t.push(`${r}.${u}.source must be a string.`):k(y.source,`${r}.${u}.source`),(typeof y.lightness!="string"||!j.includes(y.lightness))&&t.push(`${r}.${u}.lightness must be one of: ${j.join(", ")}.`)}}"semanticMappings"in e&&P(e.semanticMappings,"semanticMappings");for(const s of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);for(const s of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];(r<0||r>1)&&t.push(`${s} must be 0\u20131 (got ${r}).`)}return o.push(...Dt(e,n)),{valid:t.length===0,errors:t,warnings:o}}const T=.045;function Dt(e,n){try{return Nt(e,n)}catch{return[]}}function Nt(e,n){const t=le(n,e),o=et(t),a=[...o],c=new Set(o);for(const f of Object.keys(t.contexts)){const p=Xe(t,f);if(p)for(const m of et(p))c.has(m)||a.push(`contexts.${f}: ${m}`)}return a}function Wt(e){const n=ct(de(e)),t=ft(n);return it({r:me(t.r),g:me(t.g),b:me(t.b)})}function X(e,n){return Math.hypot(e.L-n.L,e.a-n.a,e.b-n.b)}function Y(e){return Wt(W(ie(de(e))))}function Ze(e){return(Math.floor(e*1e4)/1e4).toFixed(4)}const Z=2,Qe=1e-4;function et(e){const n=W(e.seedColor);if(!n)return[];const t=he(n,e),o=e.semanticMappings.actionBackground,a=e.chroma.actionBackground,c=e.lightness[o.lightness],f=(l,b,$,h)=>de(ae(l,b,$,h)),p=ee.map(l=>({name:l,base:t[l]})),m=[];if(ee.includes(o.source))m.push(`actionBackground is sourced from the "${o.source}" status family: ordinary and ${o.source}-intent action surfaces render identically (their labels may still differ). Remap the action to a non-status source \u2014 retuning "${o.source}" via intents moves both colors together.`);else{const l=ce(o.source,t,e.anchors);l&&p.push({name:"action",base:l})}const O=He(p.map(({name:l,base:b})=>[l,ie(f(b,c,a.min,a.max))]),T,["normal"]);if(O.length===0)return m;const k=new Map,g=(l,b)=>{const $=`${l}:${b}`;let h=k.get($);if(!h){h=[];for(let S=0;S<360;S+=Z)h.push(Y({l,c:b,h:S}));k.set($,h)}return h},x=T-.002,P=(l,b,$,h)=>{const S=Math.hypot(l.a,l.b),A=Math.atan2(l.b,l.a)*180/Math.PI+180;let _=0;for(const B of $===h?[h]:[$,h]){if(B+S<T-1e-4)continue;let H=A,C=X(Y({l:b,c:B,h:A}),l);if(C>=T)return C;const N=g(b,B);for(let R=0;R<N.length;R+=1){const M=X(N[R],l);if(M>=T)return M;M>C&&(C=M,H=R*Z)}let L=H;for(let R=H-Z;R<=H+Z;R+=.1){const M=X(Y({l:b,c:B,h:R}),l);if(M>=T)return M;M>C&&(C=M,L=R)}if(C>=x)for(let R=L-.1;R<=L+.1;R+=.001){const M=X(Y({l:b,c:B,h:R}),l);if(M>=T)return M;M>C&&(C=M)}C>_&&(_=C)}return _},s=(l,b,$)=>{const h=b===$?[$]:[b,$];let S=0;for(const A of h)for(const _ of h){if(A+_<T-1e-4)continue;const B=g(l,A),H=g(l,_);let C=0,N=0,L=-1;for(let I=0;I<B.length;I+=1)for(let F=0;F<H.length;F+=1){const z=X(B[I],H[F]);if(z>=T)return z;z>L&&(L=z,C=I*Z,N=F*Z)}const R=(I,F,z,Te)=>{const Be=[];for(let G=F-z;G<=F+z;G+=Te)Be.push({h:G,lab:Y({l,c:_,h:G})});let pe=-1,we=I,Ee=F;for(let G=I-z;G<=I+z;G+=Te){const ot=Y({l,c:A,h:G});for(const _e of Be){const Ie=X(ot,_e.lab);Ie>pe&&(pe=Ie,we=G,Ee=_e.h)}}return{distance:pe,hueA:we,hueB:Ee}},M=R(C,N,Z,.1);if(M.distance>=T)return M.distance;let w=Math.max(L,M.distance);if(w>=x){const I=R(M.hueA,M.hueB,.1,.001);if(I.distance>w&&(w=I.distance),w>=T)return w}w>S&&(S=w)}return S},r=l=>ee.includes(l),i=(l,b,$,h,S)=>{const A=Y(f(l.base,$,h,S)),_=Y(f(b.base,$,h,S));if(X(A,_)>=T)return{outcome:"direct"};const B=r(l.name)&&r(b.name),H=[l,b].filter(L=>r(L.name)),C=B?"one of them":`"${r(l.name)?l.name:b.name}"`;let N;for(const L of H){const R=P(L===l?_:A,$,h,S);if(R>=T)return{outcome:"retune",target:C};R>=T-Qe&&(N=N??C)}if(B){const L=s($,h,S);if(L>=T)return{outcome:"retune",target:"both"};L>=T-Qe&&(N=N??"both")}return N!==void 0?{outcome:"near",target:N}:{outcome:"no"}},u=l=>l.outcome==="direct"?4:l.outcome==="retune"?l.target==="both"?2:3:l.outcome==="near"?1:0,d=l=>[...l].sort().join("|"),y=new Set(He(p.map(({name:l,base:b})=>[l,ie(f(b,c,0,J))]),T,["normal"]).map(l=>d(l.pair))),E=new Map(p.map(l=>[l.name,l])),D=new Map;for(const{pair:l,distance:b}of O){const $=E.get(l[0]),h=E.get(l[1]),S=r($.name)&&r(h.name),A=i($,h,c,a.min,a.max);if(A.outcome==="direct"||A.outcome==="retune"){const w=A.target??(S?"one of them":`"${r($.name)?$.name:h.name}"`);y.has(d(l))?m.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish under normal vision (distance ${Ze(b)} < ${T}); status meanings must stay distinguishable \u2014 retune ${w} via intents.`):m.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish as rendered (distance ${Ze(b)} < ${T}); the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }) pushes them together \u2014 widen the band, or retune ${w} via intents.`);continue}const _=i($,h,c,0,J);let B={outcome:"no"};for(let w=1;w<=19&&B.outcome!=="direct";w+=1){const I=w*.05;if(Math.abs(I-c)<.001)continue;const F=i($,h,I,a.min,a.max);u(F)>u(B)&&(B=F)}let H={outcome:"no"};const C=_.outcome==="direct"||_.outcome==="retune",N=B.outcome==="direct"||B.outcome==="retune";if(!C&&!N)for(let w=1;w<=19&&H.outcome!=="direct";w+=1){const I=i($,h,w*.05,0,J);u(I)>u(H)&&(H=I)}const L=Ft(_,B,H),R=`${A.outcome}|${L}`;let M=D.get(R);M||(M=[],D.set(R,M)),M.push(l)}for(const[l,b]of D){const $=l.indexOf("|"),h=l.slice(0,$),S=l.slice($+1),A=b.map(([H,C])=>`"${H}"/"${C}"`),_=A.length>1?`${A.slice(0,-1).join(", ")} and ${A[A.length-1]}`:A[0],B=h==="near"?`Status colors ${_} may not separate by retuning as rendered: at the action stop's lightness (${c}) 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 ${T} threshold`:`Status colors ${_} cannot be separated as rendered: at the action stop's lightness (${c}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), no intent retuning can pull ${b.length>1?"these pairs":"the pair"} ${T} apart`;m.push(B+S)}return m}function Ft(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 o=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"?`${o} \u2014 change the band and the stop together.`:t.outcome==="retune"?`${o} \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 qt(e,n){const t=Re(e),o=Re(n),a=t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:Ce(t.value),c=o.error!==void 0?{valid:!1,errors:[o.error],warnings:[]}:Ce(o.value,je),f=[...a.errors.map(m=>`light: ${m}`),...c.errors.map(m=>`dark: ${m}`)],p=[...a.warnings.map(m=>`light: ${m}`),...c.warnings.map(m=>`dark: ${m}`)];if(a.valid&&c.valid){const m=new Set(Object.keys(t.value?.contexts??{})),O=new Set(Object.keys(o.value?.contexts??{})),k=[...O].filter(x=>!m.has(x)).sort(),g=[...m].filter(x=>!O.has(x)).sort();(k.length>0||g.length>0)&&f.push(`contexts must declare the same names in both schemes. Missing from light: ${k.join(", ")||"(none)"}. Missing from dark: ${g.join(", ")||"(none)"}.`)}return{valid:f.length===0,errors:f,warnings:p}}const jt=["anchors","angles","contexts","dataPalette","dataRamps","intents","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function Kt(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&(t[o]=a);for(const[o,a]of Object.entries(n))a!==void 0&&v(o)&&(t[o]=a);for(const o of jt){const a=e[o],c=n[o];if(a&&typeof a=="object"&&!Array.isArray(a)&&c&&typeof c=="object"&&!Array.isArray(c)){if(o==="anchors"){t[o]=Ue(a,c);continue}if(o==="contexts"){t[o]=Et(a,c);continue}if(o==="dataRamps"){t[o]=Ve(a,c);continue}const f={};for(const[p,m]of Object.entries(a))v(p)&&(f[p]=m);for(const[p,m]of Object.entries(c))m!==void 0&&v(p)&&(f[p]=m);t[o]=f}}return t}function Xt(...e){let n={};for(const t of e){if(!t)continue;const o=Ct(t);o&&(n=Kt(n,o))}return Oe(n)}function tt(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const nt={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 Zt(e){return Oe({...nt,pageBackgroundImage:`url("${tt(e)}")`,pageBackgroundImageOpacity:.5})}function Qt(e){return Oe({...nt,pageBackgroundImage:`url("${tt(e)}")`,pageBackgroundImageOpacity:.55})}export{V as ANCHOR_SLUG_PATTERN,ke as COLOR_SOURCES,Ot as DEFAULT_DARK_LIGHTNESS,je as DEFAULT_DARK_THEME,vt as DEFAULT_LIGHT_LIGHTNESS,Me as DEFAULT_LIGHT_THEME,xe as DEFAULT_SEMANTIC_MAPPINGS,j as LIGHTNESS_KEYS,jt as NESTED_THEME_KEYS,ne as ROLE_NAMES,bt as ROLE_PAIRED_INK,Se as ROLE_TOKEN_PLAN,Q as SEMANTIC_COLOR_NAMES,ee as STATUS_COLOR_SOURCES,We as TOKEN_PAIRINGS,Mt as VARIANT_COLOR_SOURCES,Qt as buildTaprootDarkTheme,Zt as buildTaprootLightTheme,Ne as compileRoles,Oe as encodeTheme,Pt as explicitMappingTokens,Xt as layerThemes,Kt as mergePartials,le as mergeTheme,$e as parseAnchorSource,Ct as parseTheme,Pe as resolveAnchorColor,Xe as resolveContextTheme,ht as resolveDataColorSource,Jt as semanticToCSS,Yt as validateTheme,qt as validateThemePair};
1
+ import{UNSAFE_KEYS as st,isSafeKey as C}from"./unsafe-keys.js";import{ACCEPTED_COLOR_FORMS as ne,apcaContrast as rt,clampChannel as de,deltaEOK as at,deriveSemantic as ae,gamutMapToSRGB as me,linearRgbToOklab as it,oklchToSRGB as ct,parseCssColor as W,parseOklch as ut,serializeOklch as ie,srgbToLinearRGB as ft}from"./color-engine.js";import{computeVariants as he,parseAnchorSource as lt,resolveAnchorColor as pt,resolveMappingSource as ce}from"./variant-engine.js";import{auditColorDistances as Le,auditDataPalette as dt,DATA_SERIES_KEYS as ue,DEFAULT_DATA_PALETTE as ge,DEFAULT_DATA_RAMP_STEPS as mt,MAX_DATA_RAMP_STEPS as ye,MIN_DATA_RAMP_LIGHTNESS_STEP as He,MIN_DATA_RAMP_STEPS as be}from"./data-colors.js";const V=/^[a-z][a-z0-9-]*$/;function $e(e){return lt(e)}function Pe(e,n){return pt(e,n)}function ht(e,n){const t=$e(e);if(t){const o=Pe(n,t);return o&&W(o)?o:null}return W(e)?e:null}const oe=["canvas","ink","accent","action","structure"],xe={canvas:{color:[["background","surface"],["layer1","raised1"],["layer2","raised2"],["layer3","raised3"],["layer4","raised4"]]},ink:{color:[["text","text"],["typeOverline","text"],["typeLabel","text"],["typeLead","text"],["typeCaption","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"]]}},gt=new Set(["action.color"]),yt={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},bt={"action.ink":{role:"canvas",slot:"color"}},$t=.45,xt=.045;function De(e,n,t){const o=We.actionText,a=[...j].sort((g,A)=>e[g]-e[A]||j.indexOf(g)-j.indexOf(A)),c=n?a.filter(g=>n(g)>=o.targetLc):a,f=t?c.filter(g=>t(g)>=xt):c,p=f.length>0?f:c,d=p.length>0?p:a;let O,k=1/0;for(const g of d){const A=Math.abs(e[g]-$t);A<k&&(k=A,O=g)}return O??"muted"}function St(e,n){const t=n[e]>.5;let o=j[0];for(const a of j)(t?n[a]<n[o]:n[a]>n[o])&&(o=a);return o}const kt={"accent.hover":"text"};function At(e,n){const t=new Map;try{const o=le(n,e),a=(c,f,p,d)=>{const O=$e(f),k=O?Pe(d,O):null,g=k===null?null:W(k),A=t.get(c)??[];A.some(E=>E.source===f&&E.chroma===g?.c)||(A.push({source:f,where:p,chroma:g?.c}),t.set(c,A))};for(const[c,f]of Object.entries(o.semanticMappings))f.source.startsWith("anchor:")&&a(c,f.source,"the root table",o.anchors);for(const c of Object.keys(o.contexts)){const f=Xe(o,c);if(f)for(const[p,d]of Object.entries(f.semanticMappings))d.source.startsWith("anchor:")&&a(p,d.source,`contexts.${c}`,f.anchors)}}catch{return new Map}return t}function q(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 Ne(e,n,t,o={}){const a={},c={};for(const[f,p]of Object.entries(o.explicitMappings??{}))p!==void 0&&(c[f]=p.lightness);for(const f of oe){const p=e[f];if(p!==void 0)for(const[d,O]of Object.entries(xe[f])){const k=bt[`${f}.${d}`];let g=q(p,d),A=!1;if(g===void 0){k&&(g=q(e[k.role],k.slot),g??=t[yt[k.role]]?.source,A=g!==void 0);const E=kt[`${f}.${d}`];E!==void 0&&(g??=q(p,E)),g??=q(p,"color")}if(g!==void 0)for(const[E,s]of O){let r=s;if(gt.has(`${f}.${d}`))r=De(n,o.actionSurfaceContrast?i=>o.actionSurfaceContrast(g,i):void 0,o.actionSurfaceSeparation?i=>o.actionSurfaceSeparation(g,i):void 0);else if(A&&k){const i=We[E],u=(i&&c[i.bg])??De(n,o.actionSurfaceContrast?m=>o.actionSurfaceContrast(q(p,"color"),m):void 0,o.actionSurfaceSeparation?m=>o.actionSurfaceSeparation(q(p,"color"),m):void 0);r=St(u,n)}a[E]={source:g,lightness:r}}}}return a}const We={text:{bg:"background",targetLc:75},typeOverline:{bg:"background",targetLc:90},typeLabel:{bg:"background",targetLc:75},typeLead:{bg:"background",targetLc:75},typeCaption:{bg:"background",targetLc:90},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"linkHoverBg",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},Q=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","typeOverline","typeLabel","typeLead","typeCaption","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],vt=["typeOverline","typeLabel","typeLead","typeCaption"],Se=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],ee=["danger","success","warning","info"],Mt=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],j=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],Ct={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},Ot={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},ke={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"},typeOverline:{source:"primary",lightness:"text"},typeLabel:{source:"primary",lightness:"text"},typeLead:{source:"primary",lightness:"text"},typeCaption:{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"}},J=.4;function Ae(){const e={};for(const n of Q)e[n]={min:0,max:J};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:Ae(),semanticMappings:{...ke},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{}},ve={...Fe,chroma:Ae(),semanticMappings:{...ke},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{},lightness:{...Ct}},je={...Fe,chroma:Ae(),semanticMappings:{...ke},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{},lightness:{...Ot}},fe=new WeakMap;fe.set(ve,new Set),fe.set(je,new Set);function Rt(e,n){return st.has(e)?void 0:n}function Yt(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function Tt(e){try{const n=Ke(e),t=JSON.parse(n,Rt);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}const Me="\xEF\xBB\xBF";function Bt(e){if(/^[\u0000-\u007f]*$/.test(e))return btoa(e);const n=new TextEncoder().encode(e);let t=Me;for(const o of n)t+=String.fromCharCode(o);return btoa(t)}function Ke(e){const n=atob(e);if(!n.startsWith(Me))return n;const t=Uint8Array.from(n.slice(Me.length),o=>o.charCodeAt(0));return new TextDecoder("utf-8",{fatal:!0}).decode(t)}function Ce(e){return Bt(JSON.stringify(e))}function wt(e){const n={};for(const t of ee){const o=e[t];typeof o=="string"&&(n[t]=o.startsWith("anchor:")?o:se(o))}return n}function se(e){if(ut(e))return e;const n=W(e);return n?ie(n):e}function Ue(e,n){const t={};for(const[o,a]of Object.entries(e))C(o)&&(t[o]=a);if(!n)return t;for(const[o,a]of Object.entries(n)){if(a===void 0||!C(o))continue;const c=t[o];if(c!==void 0&&typeof a=="object"&&a!==null){const f={};if(typeof c=="string")f.color=c;else for(const[p,d]of Object.entries(c))C(p)&&(f[p]=d);for(const[p,d]of Object.entries(a))d!==void 0&&C(p)&&(f[p]=d);t[o]=f;continue}t[o]=a}return t}function ze(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const n=e,t={};for(const o of oe){const a=n[o];a!==void 0&&(t[o]=a)}if(typeof n.lightness=="object"&&n.lightness!==null&&!Array.isArray(n.lightness)){const o={};for(const a of j){const c=n.lightness[a];c!==void 0&&(o[a]=c)}t.lightness=o}if(typeof n.semanticMappings=="object"&&n.semanticMappings!==null&&!Array.isArray(n.semanticMappings)){const o={};for(const[a,c]of Object.entries(n.semanticMappings)){if(!C(a)||!Q.includes(a)||typeof c!="object"||c===null||Array.isArray(c))continue;const{source:f,lightness:p}=c;typeof f=="string"&&(typeof p!="string"||!j.includes(p)||(o[a]={source:f,lightness:p}))}Object.keys(o).length>0&&(t.semanticMappings=o)}return t}function Et(e,n){const t={};for(const[o,a]of Object.entries(e)){if(!C(o)||!V.test(o))continue;const c=ze(a);c&&(t[o]=c)}if(!n)return t;for(const[o,a]of Object.entries(n)){if(!C(o)||!V.test(o)||a===void 0)continue;const c=ze(a);if(!c)continue;const f=t[o];t[o]={...f??{},...c,...f?.lightness||c.lightness?{lightness:{...f?.lightness,...c.lightness}}:{},...f?.semanticMappings||c.semanticMappings?{semanticMappings:{...f?.semanticMappings,...c.semanticMappings}}:{}}}return t}function K(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function U(e){const n={};for(const[t,o]of Object.entries(e))o!==void 0&&C(t)&&(n[t]=o);return n}function Ge(e){if(!K(e))return e;const n=U(e);return K(e.lightness)&&(n.lightness=U(e.lightness)),n}function _t(e,n){const t={};for(const[o,a]of Object.entries(e))C(o)&&(t[o]=Ge(a));if(!n)return t;for(const[o,a]of Object.entries(n)){if(!C(o)||a===void 0)continue;const c=t[o];if(!K(c)||!K(a)){t[o]=Ge(a);continue}const f={...U(c),...U(a)};K(c.lightness)&&K(a.lightness)?f.lightness={...U(c.lightness),...U(a.lightness)}:K(a.lightness)&&(f.lightness=U(a.lightness)),K(c.semanticMappings)&&K(a.semanticMappings)?f.semanticMappings={...U(c.semanticMappings),...U(a.semanticMappings)}:K(a.semanticMappings)&&(f.semanticMappings=U(a.semanticMappings)),t[o]=f}return t}function It(e){const n={};for(const[t,o]of Object.entries(e)){if(!C(t))continue;if(typeof o=="string"){n[t]=se(o);continue}const a={};for(const[c,f]of Object.entries(o))C(c)&&(a[c]=typeof f=="string"?se(f):f);n[t]=a}return n}function re(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:se(e)}function Lt(e){const n={};for(const t of ue)n[t]=re(e[t]);return n}function Ve(e,n){const t={};for(const[o,a]of Object.entries(e))C(o)&&V.test(o)&&a&&typeof a=="object"&&!Array.isArray(a)&&(t[o]={...a});if(!n)return t;for(const[o,a]of Object.entries(n)){if(!C(o)||!V.test(o)||!a||typeof a!="object"||Array.isArray(a))continue;const c=t[o],f=c!==void 0&&a.type!==void 0&&a.type!==c.type;t[o]={...f?{}:c??{},...a}}return t}function Ht(e){const n={};for(const[t,o]of Object.entries(e))if(C(t)){if(o.type==="sequential"&&typeof o.source=="string"){n[t]={...o,source:re(o.source)};continue}if(o.type==="diverging"&&typeof o.start=="string"&&typeof o.end=="string"){n[t]={...o,start:re(o.start),end:re(o.end),...typeof o.neutral=="string"?{neutral:re(o.neutral)}:{}};continue}n[t]={...o}}return n}function Je(e){const n=W(e.seedColor);if(!n)return;const t=he(n,e);return(o,a)=>{const c=ce(o,t,e.anchors)??t.primary,f=e.chroma.actionBackground,p=ae(c,e.lightness[a],f.min,f.max),d={l:p.l>.5?0:1,c:0,h:0};return Math.abs(rt(d,p))}}function Pt(e,n,t){if(n?.background)return n.background;const o=q(e.canvas,"color");if(o!==void 0){const a=xe.canvas.color?.find(([c])=>c==="background");if(a)return{source:o,lightness:a[1]}}return t.background}function Ye(e,n){const t=W(e.seedColor);if(!t||!n)return;const o=he(t,e),a=ce(n.source,o,e.anchors)??o.primary,c=e.chroma.background,f=ae(a,e.lightness[n.lightness],c.min,c.max);return(p,d)=>{const O=ce(p,o,e.anchors)??o.primary,k=e.chroma.actionBackground,g=ae(O,e.lightness[d],k.min,k.max);return at(g,f)}}function Dt(e){const n=fe.get(e);if(n)return new Set(n);const t=new Set,o=Ne(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:Je(e),actionSurfaceSeparation:Ye(e,e.semanticMappings.background)});for(const[a,c]of Object.entries(o)){const f=e.semanticMappings[a];(f.source!==c.source||f.lightness!==c.lightness)&&t.add(a)}return t}function le(e,n){const t={...e.roles,...n.roles},o=Et(e.contexts,n.contexts),a={...e.lightness,...n.lightness},c=It(Ue(e.anchors,n.anchors)),f=typeof n.seedColor=="string"?se(n.seedColor):e.seedColor,p=n.semanticMappings,d={...e.angles,...n.angles},O={...e.semanticHues,...n.semanticHues},k={...e.variantChroma,...n.variantChroma},g=wt({...e.intents,...n.intents}),A=n.chroma,E=te(e.chroma,A),s=Lt(te(e.dataPalette,n.dataPalette)),r=Ht(Ve(e.dataRamps,n.dataRamps)),i=Dt(e),u=new Set(i),m={};for(const x of i)m[x]=e.semanticMappings[x];for(const[x,v]of Object.entries(p??{}))v!==void 0&&(u.add(x),m[x]=v);const h=te(e.semanticMappings,p),_={angles:d,anchors:c,chroma:E,intents:g,lightness:a,seedColor:f,semanticHues:O,variantChroma:k},D=Je(_),l=Ye(_,Pt(t,m,h)),y=Ne(t,a,h,{explicitMappings:m,actionSurfaceContrast:D,actionSurfaceSeparation:l}),b={};for(const[x,v]of Object.entries(y))u.has(x)||(b[x]=v);const $={};for(const x of vt)!u.has(x)&&b[x]===void 0&&($[x]={source:h.text.source,lightness:h.text.lightness},A?.text!==void 0&&A[x]===void 0&&(E[x]={...E.text}));const R=te(te(te(e.semanticMappings,$),b),p),S={...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:d,semanticHues:O,variantChroma:k,intents:g,lightness:a,chroma:E,semanticMappings:R,anchors:c,roles:t,contexts:o,dataPalette:s,dataRamps:r};return n.pageBackgroundImage!==void 0&&(S.pageBackgroundImage=n.pageBackgroundImage),n.pageBackgroundImageOpacity!==void 0&&(S.pageBackgroundImageOpacity=n.pageBackgroundImageOpacity),n.boxBackgroundImage!==void 0&&(S.boxBackgroundImage=n.boxBackgroundImage),n.boxBackgroundImageOpacity!==void 0&&(S.boxBackgroundImageOpacity=n.boxBackgroundImageOpacity),n.vellumOpacity!==void 0&&(S.vellumOpacity=n.vellumOpacity),n.vellumBackgroundImage!==void 0&&(S.vellumBackgroundImage=n.vellumBackgroundImage),n.vellumBackgroundImageOpacity!==void 0&&(S.vellumBackgroundImageOpacity=n.vellumBackgroundImageOpacity),fe.set(S,new Set(u)),S}const qe=new WeakMap;function Xe(e,n){const t=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,n)?e.contexts[n]:void 0;if(!t)return null;let o=qe.get(e);const a=o?.get(n);if(a)return a;const c={};for(const p of oe){const d=t[p];d!==void 0&&(c[p]=d)}const f=le(e,{lightness:t.lightness,roles:c,semanticMappings:t.semanticMappings});return o||(o=new Map,qe.set(e,o)),o.set(n,f),f}function te(e,n){if(!n)return{...e};const t={...e};for(const o of Object.keys(n)){const a=n[o];a!==void 0&&(t[o]=a)}return t}function Oe(e){let n;try{n=Ke(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 qt(e){const n=Oe(e);return n.error!==void 0?{valid:!1,errors:[n.error],warnings:[]}:Re(n.value)}function Re(e,n=ve){const t=[],o=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):W(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${ne}.`));for(const s of["fontBody","fontHeadings","fontBrand","fontMonospace"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);const a=["normal","bold","lighter","bolder"],c=["inherit","initial","unset","revert","revert-layer"];for(const s of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(s in e){const r=e[s];if(typeof r=="number")(r<1||r>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got ${r}).`);else if(typeof r=="string"){const i=a.includes(r)||c.includes(r);if(/^\d+$/.test(r)){const m=Number(r);(m<1||m>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got "${r}").`)}else i||o.push(`${s} = "${r}" is not a standard font-weight value.`)}else t.push(`${s} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(s=>typeof s!="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[s,r,i]of f)if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const u=e[s];r!==void 0&&u<r&&t.push(`${s} must be \u2265 ${r} (got ${u}).`),i!==void 0&&u>i&&o.push(`${s} = ${u} is unusually high (max ${i}).`)}for(const s of["typeRatio","spaceRatio"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];r<=1&&t.push(`${s} must be > 1 (got ${r}).`);const i=s==="typeRatio"?1.3:2;r>i&&o.push(`${s} = ${r} is very high (max ${i}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const s=e.viewportMin,r=e.viewportMax;typeof s=="number"&&typeof r=="number"&&s>=r&&t.push(`viewportMin (${s}) 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 s=e.angles;for(const r of["analogous","complementary","splitComplementary","triadic"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`angles.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.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 s=e.semanticHues;for(const r of["danger","success","warning","info"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`semanticHues.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.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 s=e.variantChroma;for(const r of Mt)if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`variantChroma["${r}"] must be a finite number.`);else{const i=s[r];i<0&&t.push(`variantChroma["${r}"] must be \u2265 0 (got ${i}).`),i>J&&o.push(`variantChroma["${r}"] = ${i} exceeds ${J}.`)}}function p(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const u of j)if(u in i)if(typeof i[u]!="number"||!isFinite(i[u]))t.push(`${r}.${u} must be a finite number.`);else{const m=i[u];(m<0||m>1)&&t.push(`${r}.${u} must be 0\u20131 (got ${m}).`)}}if("lightness"in e&&p(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const s=e.chroma,r=At(e,n);for(const i of Q)if(i in s){const u=s[i];if(typeof u!="object"||u===null){t.push(`chroma.${i} must be { min, max }.`);continue}const m=u;for(const _ of r.get(i)??[])_.chroma!==void 0&&typeof m.min=="number"&&typeof m.max=="number"&&(_.chroma<m.min-1e-9||_.chroma>m.max+1e-9)&&o.push(`chroma.${i} clamps the anchor-sourced token ${i} ("${_.source}", effective in ${_.where}) and moves it off its declared swatch. Remove the band if that is unintended \u2014 anchors otherwise keep their own chroma.`);const h=u;(typeof h.min!="number"||h.min<0)&&t.push(`chroma.${i}.min must be \u2265 0.`),(typeof h.max!="number"||h.max<0||h.max>J)&&t.push(`chroma.${i}.max must be 0\u2013${J}.`),typeof h.min=="number"&&typeof h.max=="number"&&h.min>h.max&&t.push(`chroma.${i}.min (${h.min}) must be \u2264 max (${h.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[s,r]of Object.entries(e.anchors))if(C(s)?V.test(s)||t.push(`anchors: "${s}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${s}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),Se.includes(s)&&t.push(`anchors: "${s}" collides with a reserved color source name.`),typeof r=="string")W(r)||t.push(`anchors.${s} is not a valid CSS color: "${r}". Accepted forms: ${ne}.`);else if(typeof r=="object"&&r!==null&&!Array.isArray(r)){const i=r;typeof i.color!="string"&&t.push(`anchors.${s} must declare its base "color".`);for(const[u,m]of Object.entries(i))C(u)?u!=="color"&&!V.test(u)&&t.push(`anchors.${s}: "${u}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${s}: "${u}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof m!="string"?t.push(`anchors.${s}.${u} must be a CSS color string.`):W(m)||t.push(`anchors.${s}.${u} is not a valid CSS color: "${m}". Accepted forms: ${ne}.`)}else t.push(`anchors.${s} must be a color string or a { color, \u2026slots } object.`);const d=new Map;if("anchors"in e&&typeof e.anchors=="object"&&e.anchors!==null&&!Array.isArray(e.anchors))for(const[s,r]of Object.entries(e.anchors))d.set(s,r);function O(s,r){const i=$e(s);if(!i){t.push(`${r} "${s}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!d.has(i.name)){const u=[...d.keys()];t.push(`${r} references undeclared anchor "${i.name}". Declared anchors: ${u.length>0?u.join(", "):"(none)"}.`);return}if(i.slot!==void 0){const u=d.get(i.name);if(typeof(typeof u=="object"&&u!==null&&!Array.isArray(u)?u[i.slot]:void 0)!="string"){const h=typeof u=="object"&&u!==null?Object.keys(u).filter(_=>_!=="color"):[];t.push(`${r} references unknown slot "${i.slot}" on anchor "${i.name}". Declared slots: ${h.length>0?h.join(", "):"(none)"}.`)}}}function k(s,r){if(s.startsWith("anchor:")){O(s,r);return}Se.includes(s)||t.push(`${r} must be one of: ${Se.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[s,r]of Object.entries(e.intents)){const i=`intents.${s}`;if(!ee.includes(s)){t.push(`${i} is not a status family; expected one of: ${ee.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:")){O(r,i);continue}W(r)||t.push(`${i} "${r}" is not a supported color form or anchor: reference. Accepted forms: ${ne}, 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 g(s,r){if(s.startsWith("anchor:")){O(s,r);return}W(s)||t.push(`${r} is not a valid CSS color: "${s}". Accepted forms: ${ne}, 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 s=e.dataPalette;for(const[r,i]of Object.entries(s)){if(!ue.includes(r)){t.push(`dataPalette.${r} is not a series slot; expected one of: ${ue.join(", ")}.`);continue}typeof i!="string"?t.push(`dataPalette.${r} must be a CSS color or anchor reference string.`):g(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[s,r]of Object.entries(e.dataRamps)){if(C(s)?V.test(s)||t.push(`dataRamps: "${s}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${s}" 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.${s} must be a sequential or diverging ramp object.`);continue}const i=r,u=i.steps??mt;if((typeof u!="number"||!Number.isInteger(u)||u<be||u>ye)&&t.push(`dataRamps.${s}.steps must be an integer from ${be} through ${ye}.`),i.type==="sequential"){typeof i.source!="string"?t.push(`dataRamps.${s}.source must be a CSS color or anchor reference string.`):g(i.source,`dataRamps.${s}.source`);const m=i.lightnessStart??.95,h=i.lightnessEnd??.25;for(const[_,D]of[["lightnessStart",m],["lightnessEnd",h]])(typeof D!="number"||!Number.isFinite(D)||D<0||D>1)&&t.push(`dataRamps.${s}.${_} must be a finite number from 0 through 1.`);typeof m=="number"&&typeof h=="number"&&m<=h?t.push(`dataRamps.${s}.lightnessStart must be greater than lightnessEnd.`):typeof m=="number"&&Number.isFinite(m)&&typeof h=="number"&&Number.isFinite(h)&&typeof u=="number"&&Number.isInteger(u)&&u>=be&&u<=ye&&(m-h)/(u-1)<=He&&t.push(`dataRamps.${s} lightness bounds must leave more than ${He} lightness between serialized stops.`);continue}if(i.type==="diverging"){typeof u=="number"&&Number.isInteger(u)&&u%2===0&&t.push(`dataRamps.${s}.steps must be odd so the neutral is the exact midpoint.`);for(const m of["start","end"])typeof i[m]!="string"?t.push(`dataRamps.${s}.${m} must be a CSS color or anchor reference string.`):g(i[m],`dataRamps.${s}.${m}`);"neutral"in i&&(typeof i.neutral!="string"?t.push(`dataRamps.${s}.neutral must be a CSS color or anchor reference string.`):g(i.neutral,`dataRamps.${s}.neutral`));continue}t.push(`dataRamps.${s}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const s=le(ve,e),r={};let i=!0;for(const u of ue){const m=ht(s.dataPalette[u],s.anchors);if(!m){i=!1;break}r[u]=m}if(i)for(const u of dt(r))o.push(`dataPalette.${u.series[0]} and dataPalette.${u.series[1]} are only ${u.distance.toFixed(4)} apart under ${u.simulation} simulation (minimum ${u.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function A(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const[u,m]of Object.entries(i)){const h=`${r}.${u}`;if(!oe.includes(u)){t.push(`${h} is not a role; expected one of: ${oe.join(", ")}. (The status family is reserved and is not a role.)`);continue}const _=u,D=xe[_];if(typeof m=="string"){k(m,h);continue}if(typeof m!="object"||m===null||Array.isArray(m)){t.push(`${h} must be a color source or a { color, \u2026slots } object.`);continue}const l=m;typeof l.color!="string"&&t.push(`${h} must declare its base "color".`);for(const[y,b]of Object.entries(l)){if(!Object.prototype.hasOwnProperty.call(D,y)||!C(y)){const $=Object.keys(D).filter(R=>R!=="color");t.push(`${h}.${y} is not a slot of the ${_} role. Declared slots: ${$.length>0?$.join(", "):"(none)"}.`);continue}typeof b!="string"?t.push(`${h}.${y} must be a color source string.`):k(b,`${h}.${y}`)}}}if("roles"in e&&A(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[s,r]of Object.entries(e.contexts)){if(!C(s)||!V.test(s)){t.push(`contexts.${s} must be a lowercase slug matching ${V.source}.`);continue}if(typeof r!="object"||r===null||Array.isArray(r)){A(r,`contexts.${s}`);continue}const i=r,u=Object.fromEntries(Object.entries(i).filter(([m])=>m!=="lightness"&&m!=="semanticMappings"));A(u,`contexts.${s}`),"lightness"in i&&p(i.lightness,`contexts.${s}.lightness`),"semanticMappings"in i&&E(i.semanticMappings,`contexts.${s}.semanticMappings`)}function E(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const u of Object.keys(i))Q.includes(u)||t.push(`${r}.${u} is not a semantic token; expected one of: ${Q.join(", ")}.`);for(const u of Q)if(u in i){const m=i[u];if(typeof m!="object"||m===null){t.push(`${r}.${u} must be { source, lightness }.`);continue}const h=m;typeof h.source!="string"?t.push(`${r}.${u}.source must be a string.`):k(h.source,`${r}.${u}.source`),(typeof h.lightness!="string"||!j.includes(h.lightness))&&t.push(`${r}.${u}.lightness must be one of: ${j.join(", ")}.`)}}"semanticMappings"in e&&E(e.semanticMappings,"semanticMappings");for(const s of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);for(const s of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];(r<0||r>1)&&t.push(`${s} must be 0\u20131 (got ${r}).`)}return o.push(...Nt(e,n)),{valid:t.length===0,errors:t,warnings:o}}const w=.045;function Nt(e,n){try{return Wt(e,n)}catch{return[]}}function Wt(e,n){const t=le(n,e),o=et(t),a=[...o],c=new Set(o);for(const f of Object.keys(t.contexts)){const p=Xe(t,f);if(p)for(const d of et(p))c.has(d)||a.push(`contexts.${f}: ${d}`)}return a}function Ft(e){const n=ct(me(e)),t=ft(n);return it({r:de(t.r),g:de(t.g),b:de(t.b)})}function X(e,n){return Math.hypot(e.L-n.L,e.a-n.a,e.b-n.b)}function Y(e){return Ft(W(ie(me(e))))}function Ze(e){return(Math.floor(e*1e4)/1e4).toFixed(4)}const Z=2,Qe=1e-4;function et(e){const n=W(e.seedColor);if(!n)return[];const t=he(n,e),o=e.semanticMappings.actionBackground,a=e.chroma.actionBackground,c=e.lightness[o.lightness],f=(l,y,b,$)=>me(ae(l,y,b,$)),p=ee.map(l=>({name:l,base:t[l]})),d=[];if(ee.includes(o.source))d.push(`actionBackground is sourced from the "${o.source}" status family: ordinary and ${o.source}-intent action surfaces render identically (their labels may still differ). Remap the action to a non-status source \u2014 retuning "${o.source}" via intents moves both colors together.`);else{const l=ce(o.source,t,e.anchors);l&&p.push({name:"action",base:l})}const O=Le(p.map(({name:l,base:y})=>[l,ie(f(y,c,a.min,a.max))]),w,["normal"]);if(O.length===0)return d;const k=new Map,g=(l,y)=>{const b=`${l}:${y}`;let $=k.get(b);if(!$){$=[];for(let R=0;R<360;R+=Z)$.push(Y({l,c:y,h:R}));k.set(b,$)}return $},A=w-.002,E=(l,y,b,$)=>{const R=Math.hypot(l.a,l.b),S=Math.atan2(l.b,l.a)*180/Math.PI+180;let x=0;for(const v of b===$?[$]:[b,$]){if(v+R<w-1e-4)continue;let H=S,B=X(Y({l:y,c:v,h:S}),l);if(B>=w)return B;const N=g(y,v);for(let T=0;T<N.length;T+=1){const M=X(N[T],l);if(M>=w)return M;M>B&&(B=M,H=T*Z)}let P=H;for(let T=H-Z;T<=H+Z;T+=.1){const M=X(Y({l:y,c:v,h:T}),l);if(M>=w)return M;M>B&&(B=M,P=T)}if(B>=A)for(let T=P-.1;T<=P+.1;T+=.001){const M=X(Y({l:y,c:v,h:T}),l);if(M>=w)return M;M>B&&(B=M)}B>x&&(x=B)}return x},s=(l,y,b)=>{const $=y===b?[b]:[y,b];let R=0;for(const S of $)for(const x of $){if(S+x<w-1e-4)continue;const v=g(l,S),H=g(l,x);let B=0,N=0,P=-1;for(let L=0;L<v.length;L+=1)for(let F=0;F<H.length;F+=1){const z=X(v[L],H[F]);if(z>=w)return z;z>P&&(P=z,B=L*Z,N=F*Z)}const T=(L,F,z,Te)=>{const Be=[];for(let G=F-z;G<=F+z;G+=Te)Be.push({h:G,lab:Y({l,c:x,h:G})});let pe=-1,we=L,Ee=F;for(let G=L-z;G<=L+z;G+=Te){const ot=Y({l,c:S,h:G});for(const _e of Be){const Ie=X(ot,_e.lab);Ie>pe&&(pe=Ie,we=G,Ee=_e.h)}}return{distance:pe,hueA:we,hueB:Ee}},M=T(B,N,Z,.1);if(M.distance>=w)return M.distance;let I=Math.max(P,M.distance);if(I>=A){const L=T(M.hueA,M.hueB,.1,.001);if(L.distance>I&&(I=L.distance),I>=w)return I}I>R&&(R=I)}return R},r=l=>ee.includes(l),i=(l,y,b,$,R)=>{const S=Y(f(l.base,b,$,R)),x=Y(f(y.base,b,$,R));if(X(S,x)>=w)return{outcome:"direct"};const v=r(l.name)&&r(y.name),H=[l,y].filter(P=>r(P.name)),B=v?"one of them":`"${r(l.name)?l.name:y.name}"`;let N;for(const P of H){const T=E(P===l?x:S,b,$,R);if(T>=w)return{outcome:"retune",target:B};T>=w-Qe&&(N=N??B)}if(v){const P=s(b,$,R);if(P>=w)return{outcome:"retune",target:"both"};P>=w-Qe&&(N=N??"both")}return N!==void 0?{outcome:"near",target:N}:{outcome:"no"}},u=l=>l.outcome==="direct"?4:l.outcome==="retune"?l.target==="both"?2:3:l.outcome==="near"?1:0,m=l=>[...l].sort().join("|"),h=new Set(Le(p.map(({name:l,base:y})=>[l,ie(f(y,c,0,J))]),w,["normal"]).map(l=>m(l.pair))),_=new Map(p.map(l=>[l.name,l])),D=new Map;for(const{pair:l,distance:y}of O){const b=_.get(l[0]),$=_.get(l[1]),R=r(b.name)&&r($.name),S=i(b,$,c,a.min,a.max);if(S.outcome==="direct"||S.outcome==="retune"){const I=S.target??(R?"one of them":`"${r(b.name)?b.name:$.name}"`);h.has(m(l))?d.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish under normal vision (distance ${Ze(y)} < ${w}); status meanings must stay distinguishable \u2014 retune ${I} via intents.`):d.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish as rendered (distance ${Ze(y)} < ${w}); the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }) pushes them together \u2014 widen the band, or retune ${I} via intents.`);continue}const x=i(b,$,c,0,J);let v={outcome:"no"};for(let I=1;I<=19&&v.outcome!=="direct";I+=1){const L=I*.05;if(Math.abs(L-c)<.001)continue;const F=i(b,$,L,a.min,a.max);u(F)>u(v)&&(v=F)}let H={outcome:"no"};const B=x.outcome==="direct"||x.outcome==="retune",N=v.outcome==="direct"||v.outcome==="retune";if(!B&&!N)for(let I=1;I<=19&&H.outcome!=="direct";I+=1){const L=i(b,$,I*.05,0,J);u(L)>u(H)&&(H=L)}const P=jt(x,v,H),T=`${S.outcome}|${P}`;let M=D.get(T);M||(M=[],D.set(T,M)),M.push(l)}for(const[l,y]of D){const b=l.indexOf("|"),$=l.slice(0,b),R=l.slice(b+1),S=y.map(([H,B])=>`"${H}"/"${B}"`),x=S.length>1?`${S.slice(0,-1).join(", ")} and ${S[S.length-1]}`:S[0],v=$==="near"?`Status colors ${x} may not separate by retuning as rendered: at the action stop's lightness (${c}) 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 ${w} threshold`:`Status colors ${x} cannot be separated as rendered: at the action stop's lightness (${c}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), no intent retuning can pull ${y.length>1?"these pairs":"the pair"} ${w} apart`;d.push(v+R)}return d}function jt(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 o=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"?`${o} \u2014 change the band and the stop together.`:t.outcome==="retune"?`${o} \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 Xt(e,n){const t=Oe(e),o=Oe(n),a=t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:Re(t.value),c=o.error!==void 0?{valid:!1,errors:[o.error],warnings:[]}:Re(o.value,je),f=[...a.errors.map(d=>`light: ${d}`),...c.errors.map(d=>`dark: ${d}`)],p=[...a.warnings.map(d=>`light: ${d}`),...c.warnings.map(d=>`dark: ${d}`)];if(a.valid&&c.valid){const d=new Set(Object.keys(t.value?.contexts??{})),O=new Set(Object.keys(o.value?.contexts??{})),k=[...O].filter(A=>!d.has(A)).sort(),g=[...d].filter(A=>!O.has(A)).sort();(k.length>0||g.length>0)&&f.push(`contexts must declare the same names in both schemes. Missing from light: ${k.join(", ")||"(none)"}. Missing from dark: ${g.join(", ")||"(none)"}.`)}return{valid:f.length===0,errors:f,warnings:p}}const Kt=["anchors","angles","contexts","dataPalette","dataRamps","intents","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function Ut(e,n){const t={};for(const[o,a]of Object.entries(e))C(o)&&(t[o]=a);for(const[o,a]of Object.entries(n))a!==void 0&&C(o)&&(t[o]=a);for(const o of Kt){const a=e[o],c=n[o];if(a&&typeof a=="object"&&!Array.isArray(a)&&c&&typeof c=="object"&&!Array.isArray(c)){if(o==="anchors"){t[o]=Ue(a,c);continue}if(o==="contexts"){t[o]=_t(a,c);continue}if(o==="dataRamps"){t[o]=Ve(a,c);continue}const f={};for(const[p,d]of Object.entries(a))C(p)&&(f[p]=d);for(const[p,d]of Object.entries(c))d!==void 0&&C(p)&&(f[p]=d);t[o]=f}}return t}function Zt(...e){let n={};for(const t of e){if(!t)continue;const o=Tt(t);o&&(n=Ut(n,o))}return Ce(n)}function tt(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const nt={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 Qt(e){return Ce({...nt,pageBackgroundImage:`url("${tt(e)}")`,pageBackgroundImageOpacity:.5})}function en(e){return Ce({...nt,pageBackgroundImage:`url("${tt(e)}")`,pageBackgroundImageOpacity:.55})}export{V as ANCHOR_SLUG_PATTERN,Se as COLOR_SOURCES,Ot as DEFAULT_DARK_LIGHTNESS,je as DEFAULT_DARK_THEME,Ct as DEFAULT_LIGHT_LIGHTNESS,ve as DEFAULT_LIGHT_THEME,ke as DEFAULT_SEMANTIC_MAPPINGS,j as LIGHTNESS_KEYS,Kt as NESTED_THEME_KEYS,oe as ROLE_NAMES,bt as ROLE_PAIRED_INK,xe as ROLE_TOKEN_PLAN,Q as SEMANTIC_COLOR_NAMES,ee as STATUS_COLOR_SOURCES,We as TOKEN_PAIRINGS,Mt as VARIANT_COLOR_SOURCES,en as buildTaprootDarkTheme,Qt as buildTaprootLightTheme,Ne as compileRoles,Ce as encodeTheme,Dt as explicitMappingTokens,Zt as layerThemes,Ut as mergePartials,le as mergeTheme,$e as parseAnchorSource,Tt as parseTheme,Pe as resolveAnchorColor,Xe as resolveContextTheme,ht as resolveDataColorSource,Yt as semanticToCSS,qt as validateTheme,Xt as validateThemePair};