cssints 0.11.0 → 0.12.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.
package/dist/clay.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { a as registry } from "./registry-8sYvlzyn.mjs";
2
- import { a as createTokens$1, i as createGlobalTheme$1, j as fail, s as sets } from "./theme-DtEALNIY.mjs";
3
- import { n as valueOf, t as together } from "./contrast-Dw6gXoO3.mjs";
2
+ import { a as createTokens$1, i as createGlobalTheme$1, j as fail, s as sets } from "./theme-Le0IAI8N.mjs";
3
+ import { n as valueOf, t as together } from "./contrast-B1QrUfME.mjs";
4
4
  import { n as parseColor } from "./color-BB8ipynT.mjs";
5
5
  import { Formatter, Predicate } from "effect";
6
6
  import { clampRgb, formatHex } from "culori/fn";
@@ -1,5 +1,5 @@
1
1
  import { a as registry, d as MacroError, o as warn } from "./registry-8sYvlzyn.mjs";
2
- import { l as layerStatements } from "./sheet-qCuMvyUo.mjs";
2
+ import { l as layerStatements } from "./sheet-BVksF2ST.mjs";
3
3
  import { Effect } from "effect";
4
4
  // src/contrast.ts
5
5
  const VAR = /var\((--[^\s,)]+)\)/g;
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { a as registry, d as MacroError, f as MemberError, o as warn, r as forgetKernels, t as Registry } from "./registry-8sYvlzyn.mjs";
2
- import { A as camel, C as hashClass, D as settled, E as minWidth, F as probed, M as failIn, N as isNode, O as toDecls, P as node, S as edge, T as merged, _ as PSEUDOS, a as createTokens, b as checkVars, c as tokensOf, d as style, f as token, g as PROPS, h as LAYER, i as createGlobalTheme, j as fail, k as VAR, l as CSSTokenValue, m as FUNCTIONS, n as addTheme, o as isDone, p as CONTEXTS, r as check$1, t as DONE, u as isStyle, v as carried, w as isFallback, x as dropsOf, y as chainDecl } from "./theme-DtEALNIY.mjs";
3
- import { D as relation, S as addRuntime, _ as addKernel, i as byOrder, n as addGlobal, r as addLayers, y as kernelWarnings } from "./sheet-qCuMvyUo.mjs";
2
+ import { A as camel, C as hashClass, D as settled, E as minWidth, F as probed, M as failIn, N as isNode, O as toDecls, P as node, S as edge, T as merged, _ as PSEUDOS, a as createTokens, b as checkVars, c as tokensOf, d as style, f as token, g as PROPS, h as LAYER, i as createGlobalTheme, j as fail, k as VAR, l as CSSTokenValue, m as FUNCTIONS, n as addTheme, o as isDone, p as CONTEXTS, r as check$1, t as DONE, u as isStyle, v as carried, w as isFallback, x as dropsOf, y as chainDecl } from "./theme-Le0IAI8N.mjs";
3
+ import { D as relation, S as addRuntime, _ as addKernel, i as byOrder, n as addGlobal, r as addLayers, y as kernelWarnings } from "./sheet-BVksF2ST.mjs";
4
4
  import { n as loweredOf } from "./lowered-DOJEDRFM.mjs";
5
- import { i as SCV_CALL, l as groups$1, n as CX_CALL, t as CV_CALL } from "./instrument-D68RkfDU.mjs";
5
+ import { i as SCV_CALL, l as groups$1, n as CX_CALL, t as CV_CALL } from "./instrument-QGVM1E1B.mjs";
6
6
  import { checkDeclarationNow, checkQuery, checkSelector, checkValueNow, isDeclarationError } from "@cssints/css-grammar/check";
7
7
  import { lackingOf, messageOf } from "@cssints/css-grammar/support";
8
8
  import { CSS, CSSColorValue, CSSImageValue, CSSStyleValue, CSSStyleValue as CSSStyleValue$1, CSSUnitValue } from "@cssints/css-grammar/values";
@@ -3637,6 +3637,7 @@ const groups = {
3637
3637
  };
3638
3638
  // src/instrument.ts
3639
3639
  const RUNTIME = "cssints";
3640
+ const LIBRARY = "cssints/eval";
3640
3641
  const CV_CALL = "__cv(";
3641
3642
  const SCV_CALL = "__scv(";
3642
3643
  const CX_CALL = "__cx(";
@@ -3946,9 +3947,9 @@ const instrument = Effect.fn("cssints.instrument")(function* (code, id, client =
3946
3947
  const bind = ns ? ns.local.name : `{ ${d.specifiers.map((x) => `${Formatter.formatJson(importedName(x))}: ${x.local.name}`).join(", ")} }`;
3947
3948
  const id = from.slice(8);
3948
3949
  const source = id && id !== "limited-availability" ? `__group${i}(${Formatter.formatJson(id)})` : `__css${i}`;
3949
- ms.overwrite(d.start, d.end, `import { css as __css${i}, __group as __group${i} } from ${Formatter.formatJson(RUNTIME)}; const ${bind} = ${source};`);
3950
+ ms.overwrite(d.start, d.end, `import { css as __css${i}, __group as __group${i} } from ${Formatter.formatJson(LIBRARY)}; const ${bind} = ${source};`);
3950
3951
  });
3951
- ms.prepend(`import { __at, __cnGroup, __nocn, __site, __unseen } from ${Formatter.formatJson(RUNTIME)};\n`);
3952
+ ms.prepend(`import { __at, __cnGroup, __nocn, __site, __unseen } from ${Formatter.formatJson(LIBRARY)};\n`);
3952
3953
  if (hoisted.length) ms.append(`\nexport function __cssints_hoisted() {\n${hoisted.join("\n")}\n}\n`);
3953
3954
  return {
3954
3955
  code: ms.toString(),
@@ -170,10 +170,13 @@ const KERNEL = "@kernel ";
170
170
  /** The support warnings of the declarations of a kernel written as styles (scope-engine.ts), weighed by `addKernel`. */
171
171
  const kernelWarnings = /* @__PURE__ */ new WeakMap();
172
172
  const VARS = /(--[\w-]+)\s*:|@property\s+(--[\w-]+)/g;
173
+ const scopeOf = (key) => key.slice(0, key.indexOf("."));
174
+ const owns = (scope, property) => property.startsWith(`--${scope}-`);
173
175
  /**
174
176
  * Registers a kernel by key, on first use (a global rule with atProperty: its css in _.k, its atProperty at the top
175
- * of the sheet, both once however many styles use it). The same key with other css, another key that declares one of
176
- * its custom properties, and another key for a marker it prints are build errors at `at`; a `requires` that a target
177
+ * of the sheet, both once however many styles use it). The same key with other css, another key of the same scope that
178
+ * declares one of its names, another scope's key that declares a name neither owns, and another key for a marker it
179
+ * prints are build errors at `at`; a `requires` that a target
177
180
  * lacks is a support warning, unless one of `runtimes` (those of the style) polyfills it and reaches that target
178
181
  * (`uncovered`); so is a declaration of a kernel written as styles that a target lacks (`kernelWarnings`), by the same rule.
179
182
  */
@@ -193,7 +196,9 @@ const addKernel = Effect.fnUntraced(function* (kernel, markers, at, runtimes = [
193
196
  const vars = key.startsWith("@") ? [] : [...`${kernel.css}\n${kernel.atProperty ?? ""}`.matchAll(VARS)].map((m) => m[1] ?? m[2]);
194
197
  for (const [other, e] of kernels) {
195
198
  const v = vars.find((x) => e.vars.includes(x));
196
- if (v) return yield* fail(`kernels ${other} and ${key} both declare ${v}: a plugin picks its own short custom-property names`);
199
+ if (!v) continue;
200
+ const [here, there] = [scopeOf(key), scopeOf(other)];
201
+ if (here === there ? owns(here, v) : ![here, there].some((scope) => owns(scope, v))) return yield* fail(`kernels ${other} and ${key} both declare ${v}: ${here === there ? "two kernels of one scope may not share one of its custom-property names" : "a plugin picks its own short custom-property names"}`);
197
202
  }
198
203
  kernels.set(key, entry = {
199
204
  kernel,
@@ -1,5 +1,5 @@
1
1
  import { a as registry, d as MacroError, f as MemberError, o as warn } from "./registry-8sYvlzyn.mjs";
2
- import { D as relation, E as covers, d as requireLayer, p as standIn } from "./sheet-qCuMvyUo.mjs";
2
+ import { D as relation, E as covers, d as requireLayer, p as standIn } from "./sheet-BVksF2ST.mjs";
3
3
  import { t as fallbackOf } from "./lowered-DOJEDRFM.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { checkSelector } from "@cssints/css-grammar/check";
package/dist/tui.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as registry } from "./registry-8sYvlzyn.mjs";
2
- import { a as createTokens$1, i as createGlobalTheme$1, j as fail, s as sets } from "./theme-DtEALNIY.mjs";
3
- import { g as evaluate, h as css } from "./sheet-qCuMvyUo.mjs";
4
- import { n as valueOf, t as together } from "./contrast-Dw6gXoO3.mjs";
2
+ import { a as createTokens$1, i as createGlobalTheme$1, j as fail, s as sets } from "./theme-Le0IAI8N.mjs";
3
+ import { g as evaluate, h as css } from "./sheet-BVksF2ST.mjs";
4
+ import { n as valueOf, t as together } from "./contrast-B1QrUfME.mjs";
5
5
  import { n as parseColor } from "./color-BB8ipynT.mjs";
6
6
  import { Formatter } from "effect";
7
7
  import { clampRgb, formatHex, formatHex8 } from "culori/fn";
package/dist/vite.d.mts CHANGED
@@ -105,7 +105,7 @@ export declare const renderSheet: (entries: Iterable<string>) => Effect.Effect<s
105
105
  export declare const targets: import("lightningcss").Targets;
106
106
  /** `build: { cssTarget }`, the browserslist query of `targets`, so a minified build keeps `firstThatWorks` fallbacks. */
107
107
  export declare const cssTarget: string[];
108
- export default function cssints({ inner, exclude, devtools, opencode }?: {
108
+ export default function cssints({ inner, exclude, devtools, opencode, evaluation }?: {
109
109
  inner?: boolean;
110
110
  /**
111
111
  * Files the plugin leaves alone, in Vite's filter style (`createFilter`: a picomatch glob, a RegExp or an array of them;
@@ -124,5 +124,15 @@ export default function cssints({ inner, exclude, devtools, opencode }?: {
124
124
  * and tokens plus the instruction. Needs `@opencode/client` installed. Off by default; a build has none of it.
125
125
  */
126
126
  opencode?: boolean | OpenCodeOptions;
127
+ /**
128
+ * The server that evaluates sites, when the app's own ssr environment cannot: a runner that sets `browser` for it (vitest's
129
+ * browser mode) serves every dependency as ESM — its CJS ones fail — and resolves the library to the browser entry. The plugin
130
+ * then starts its own server with the app's aliases, conditions and `noExternal`. When that environment inlines everything
131
+ * (`ssr.noExternal: true`), the list cannot be copied (CJS would break), so `inline` names what a framework needs inlined to
132
+ * resolve its own builds: `["solid-js", "@solidjs/web"]` for Solid.
133
+ */
134
+ evaluation?: {
135
+ readonly inline?: ReadonlyArray<string | RegExp>;
136
+ };
127
137
  }): Plugin[];
128
138
  export type { DevTable, OpenCodeOptions };
package/dist/vite.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { c as EvalError, d as MacroError, f as MemberError, i as forgetWarnings, l as HookError, n as forget, p as SiteMissingError, t as Registry } from "./registry-8sYvlzyn.mjs";
2
- import { C as fallbackEntries, T as runtimeNames, a as closeNames, b as DERIVED, c as layerEntries, f as themedEntries, l as layerStatements, m as usesDerived, n as addGlobal, o as globalEntries, r as addLayers, s as globalNames, t as LAYERS, u as renderSheet, v as kernelEntries, w as runtimeModule, x as RUNTIME_ID } from "./sheet-qCuMvyUo.mjs";
3
- import { a as instrument, c as writeSite, o as runtimeImport, s as tagged } from "./instrument-D68RkfDU.mjs";
4
- import { r as verifyChecks } from "./contrast-Dw6gXoO3.mjs";
2
+ import { C as fallbackEntries, T as runtimeNames, a as closeNames, b as DERIVED, c as layerEntries, f as themedEntries, l as layerStatements, m as usesDerived, n as addGlobal, o as globalEntries, r as addLayers, s as globalNames, t as LAYERS, u as renderSheet, v as kernelEntries, w as runtimeModule, x as RUNTIME_ID } from "./sheet-BVksF2ST.mjs";
3
+ import { a as instrument, c as writeSite, o as runtimeImport, s as tagged } from "./instrument-QGVM1E1B.mjs";
4
+ import { r as verifyChecks } from "./contrast-B1QrUfME.mjs";
5
5
  import { i as serverId, n as gitRoot, o as sessionOf, r as register } from "./devtools-link-DN91p7g5.mjs";
6
6
  import { createRequire } from "node:module";
7
7
  import { targets as targets$1, useTargets } from "@cssints/css-grammar/support";
@@ -652,16 +652,20 @@ const locate = Effect.fn("cssints.locate")(function* (e, code, id) {
652
652
  }
653
653
  return yield* e;
654
654
  });
655
- function cssints({ inner = false, exclude, devtools = false, opencode = false } = {}) {
655
+ function cssints({ inner = false, exclude, devtools = false, opencode = false, evaluation } = {}) {
656
656
  const excluded = [exclude ?? []].flat().length ? createFilter(exclude) : () => false;
657
657
  let server;
658
- let ownServer = false;
659
658
  let runner;
660
659
  let build = false;
661
660
  let root = process.cwd();
662
661
  let rootTargets;
663
662
  let cssPlugins = [];
664
663
  let resolveOf = {};
664
+ const evaluator = {
665
+ server: void 0,
666
+ own: false,
667
+ needed: false
668
+ };
665
669
  const usedBy = /* @__PURE__ */ new Map();
666
670
  const depsOf = /* @__PURE__ */ new Map();
667
671
  const inflight = /* @__PURE__ */ new Set();
@@ -809,7 +813,7 @@ function cssints({ inner = false, exclude, devtools = false, opencode = false }
809
813
  if (inner) return void 0;
810
814
  const parsed = yield* instrument(code, id, true, !!devtools && !build);
811
815
  if (!parsed) return void 0;
812
- const env = server.environments.ssr;
816
+ const env = evaluator.server.environments.ssr;
813
817
  if (!runner || runner.isClosed()) runner = createServerModuleRunner(env, {
814
818
  hmr: false,
815
819
  sourcemapInterceptor: "prepareStackTrace",
@@ -820,7 +824,7 @@ function cssints({ inner = false, exclude, devtools = false, opencode = false }
820
824
  return yield* clientTransform(code, id, parsed, env, (w) => ctx.warn(w), watch).pipe(Effect.ensuring(Effect.sync(() => inflight.delete(id))));
821
825
  });
822
826
  const startServer = Effect.fn("cssints.buildStart")(function* () {
823
- server = yield* Effect.tryPromise({
827
+ const started = yield* Effect.tryPromise({
824
828
  try: () => createServer({
825
829
  configFile: false,
826
830
  root,
@@ -843,11 +847,13 @@ function cssints({ inner = false, exclude, devtools = false, opencode = false }
843
847
  cause
844
848
  })
845
849
  });
846
- ownServer = true;
850
+ evaluator.own = true;
851
+ evaluator.server = started;
852
+ server ??= started;
847
853
  });
848
854
  const stopServer = Effect.fn("cssints.closeBundle")(function* () {
849
- if (!ownServer || !server) return;
850
- const s = server;
855
+ if (!evaluator.own || !evaluator.server) return;
856
+ const s = evaluator.server;
851
857
  yield* Effect.tryPromise({
852
858
  try: () => s.close(),
853
859
  catch: (cause) => new HookError({
@@ -856,8 +862,10 @@ function cssints({ inner = false, exclude, devtools = false, opencode = false }
856
862
  cause
857
863
  })
858
864
  });
859
- server = runner = void 0;
860
- ownServer = false;
865
+ if (server === s) server = void 0;
866
+ evaluator.server = void 0;
867
+ evaluator.own = false;
868
+ runner = void 0;
861
869
  });
862
870
  const renderChunk = Effect.fn("cssints.renderChunk")(function* (ctx, chunk) {
863
871
  if (inner || !Object.hasOwn(chunk.modules, SHEET)) return null;
@@ -931,12 +939,18 @@ function cssints({ inner = false, exclude, devtools = false, opencode = false }
931
939
  buildMap = build && !inner && config.build.sourcemap;
932
940
  root = config.root;
933
941
  if (!inner) rootTargets = Effect.runSync(targets$1(void 0, root));
942
+ evaluator.needed = config.environments.ssr?.resolve?.conditions?.includes("browser") === true;
934
943
  const ssr = config.environments.ssr?.resolve;
935
944
  resolveOf = {
936
- resolve: { alias: config.resolve.alias },
945
+ resolve: {
946
+ alias: config.resolve.alias,
947
+ dedupe: config.resolve.dedupe
948
+ },
937
949
  ...ssr && { environments: { ssr: { resolve: {
938
950
  conditions: ssr.conditions,
939
- externalConditions: ssr.externalConditions
951
+ externalConditions: ssr.externalConditions,
952
+ noExternal: [...Array.isArray(ssr.noExternal) ? ssr.noExternal : [], ...evaluation?.inline ?? []],
953
+ ...ssr.external !== void 0 && { external: ssr.external }
940
954
  } } } }
941
955
  };
942
956
  cssPlugins = ["vite:css", "vite:css-post"].map((n) => config.plugins.find((p) => p.name === n));
@@ -944,6 +958,7 @@ function cssints({ inner = false, exclude, devtools = false, opencode = false }
944
958
  configureServer(s) {
945
959
  server = s;
946
960
  if (inner) return;
961
+ evaluator.server = evaluator.needed ? void 0 : s;
947
962
  s.environments.client.hot.on("cssints:sheet", (v) => {
948
963
  if (!s.environments.client.moduleGraph.getModuleById(SHEET)?.transformResult?.code.includes(v)) Effect.runSync(reloadSheet());
949
964
  });
@@ -951,7 +966,7 @@ function cssints({ inner = false, exclude, devtools = false, opencode = false }
951
966
  buildStart() {
952
967
  if (inner) return;
953
968
  if (build) forgetWarnings();
954
- if (server) return;
969
+ if (evaluator.server) return;
955
970
  return run(hook("vite.buildStart", root, startServer()));
956
971
  },
957
972
  buildEnd() {
package/docs/API.md CHANGED
@@ -881,7 +881,7 @@ export const hidden = ring().core; // error: no such method
881
881
  - **Namespaces.** Everything a scope declares is the scope's own. In the CSS of a kernel, a runtime or a global, and in what `emit` and `build` return, `--_x` is the custom property `--<scope>-x`; in a kernel or a runtime `&` is the class the engine mints for the kernel (`_<scope>-<entry>`, `_ring-core`) and `&(mod.key)` that of the kernel `key` of an embedded scope. A runtime or conflicts entry takes the class of the first kernel in the `uses` of the member. Scope names are lowercase letters, digits and `-`; `cssints` and `derived` are the engine's.
882
882
  - **`uses`** lists what a member needs, by key: kernels, globals, layers, runtimes and conflicts of the scope, or `mod.key` of an embedded one (the types reject a name that is none of these, or a private one). A call member may add more in what `build` returns.
883
883
  - **`group: true`** on a chain or call member makes every style of the member carry the group marker `_g-<scope>`, after the markers of its kernels: `sticky: { uses: ["core"], group: true, chain: {...} }` in scope `stuck` gives `_stuck-core _g-stuck _x`, and `within(attr("data-stuck", "top", "~="), "stuck")(...)` reads that ancestor (2026-10-08, cssints-sbs8). The group's name is the scope's, unique in the process, so two plugins never share one; a user's `group("stuck")` is the same group, so do not name your own groups after a scope you use. It is a marker like a kernel's: a condition around the member with no declaration of its own is a build error (see "Conditions and layers").
884
- - **Kernels** are global CSS, registered once per scope entry (key `<scope>.<entry>`) on first use: the CSS goes into layer `_.k`, below every class layer, and `atProperty` (the `@property` rules) at the top of the sheet. So a kernel cannot be conditional per site: a condition around a member that has only its marker is a build error (see "Conditions and layers"); give the member a method or arguments that set custom properties, which a condition can wrap. A kernel can also be written as styles, `css: (css) => [css.outline("var(--_w)", "solid", "var(--_c)"), css.outlineOffset("2px")]`, which prints the declarations under the kernel's class: they are checked like a user's (grammar, prose rules), conditions, `nest()`, `vars()` and `keyframes()` names are allowed (see below), `firstThatWorks()` and a member's marker are not. Build errors, at the call site: two keys that declare one custom property, two keys that print one marker, and two kernels written as styles in one member's `uses` that set properties of the element that meet (the same property, a shorthand and its longhand, a logical and a physical side, as in `cn()`): `cssints: x: kernels run and view both set animation, animation-timeline (they are one element's styles and print in no set order): write those in one kernel`. Kernels are printed in `_.k` sorted by key (`<scope>.<entry>`), whatever the order of `uses` or of the modules, so two of one member never decide between themselves; in one kernel the sheet's order holds (a shorthand before its longhands). A raw kernel derives no properties and is not compared (2026-10-08, cssints-life). A kernel's `requires` (BCD keys) is a build warning for a target that lacks one, never an error. A key that is also in the `polyfills` of a runtime in the member's `uses` is covered: it warns only for the targets that runtime does not reach (a `parentVars` runtime below `@property`, see below), and a fallback of CSS or a `script` covers it everywhere. The support warning of a declaration in a kernel written as styles is covered by the same rule, by its BCD key (the one in parentheses at the end of the warning): `core: { css: (css) => [css.borderRadius("var(--_r)"), css.cornerShape("squircle")] }` beside `mask: { polyfills: ["css.properties.corner-shape"], css: "..." }` in `uses` warns for nobody, so a plugin keeps derived conflicts without a raw kernel (2026-10-08, cssints-rp0e); a warning or an error of such a declaration prints its value as the sheet does, `var(--squircle-r)`, not `var(--_r)`. As in every support warning, a BCD `partial_implementation` counts as support, because most partial entries are edge cases; an entry `{ key, exact: true }` counts it as lacking, for a feature whose partial form gives other results (`surface()` asks for `{ key: "css.types.color.oklch.relative_syntax", exact: true }`), and the warning says so: `(a partial implementation counts as lacking)`.
884
+ - **Kernels** are global CSS, registered once per scope entry (key `<scope>.<entry>`) on first use: the CSS goes into layer `_.k`, below every class layer, and `atProperty` (the `@property` rules) at the top of the sheet. So a kernel cannot be conditional per site: a condition around a member that has only its marker is a build error (see "Conditions and layers"); give the member a method or arguments that set custom properties, which a condition can wrap. A kernel can also be written as styles, `css: (css) => [css.outline("var(--_w)", "solid", "var(--_c)"), css.outlineOffset("2px")]`, which prints the declarations under the kernel's class: they are checked like a user's (grammar, prose rules), conditions, `nest()`, `vars()` and `keyframes()` names are allowed (see below), `firstThatWorks()` and a member's marker are not. Build errors, at the call site: two kernels of one scope that declare one of its own custom properties (`--reveal-k`), two kernels of different scopes that declare a custom property neither of them owns (`--bx-w`), two keys that print one marker, and two kernels written as styles in one member's `uses` that set properties of the element that meet (the same property, a shorthand and its longhand, a logical and a physical side, as in `cn()`): `cssints: x: kernels run and view both set animation, animation-timeline (they are one element's styles and print in no set order): write those in one kernel`. Kernels are printed in `_.k` sorted by key (`<scope>.<entry>`), whatever the order of `uses` or of the modules, so two of one member never decide between themselves; in one kernel the sheet's order holds (a shorthand before its longhands). A scope **may** declare a custom property another scope owns (`reveal()`'s kernel sets motion's `--motion-*`): that is reuse, and the two can sit on one page, while two of one scope may not share a short name of their own. A raw kernel derives no properties and is not compared (2026-10-08, cssints-life). A kernel's `requires` (BCD keys) is a build warning for a target that lacks one, never an error. A key that is also in the `polyfills` of a runtime in the member's `uses` is covered: it warns only for the targets that runtime does not reach (a `parentVars` runtime below `@property`, see below), and a fallback of CSS or a `script` covers it everywhere. The support warning of a declaration in a kernel written as styles is covered by the same rule, by its BCD key (the one in parentheses at the end of the warning): `core: { css: (css) => [css.borderRadius("var(--_r)"), css.cornerShape("squircle")] }` beside `mask: { polyfills: ["css.properties.corner-shape"], css: "..." }` in `uses` warns for nobody, so a plugin keeps derived conflicts without a raw kernel (2026-10-08, cssints-rp0e); a warning or an error of such a declaration prints its value as the sheet does, `var(--squircle-r)`, not `var(--_r)`. As in every support warning, a BCD `partial_implementation` counts as support, because most partial entries are edge cases; an entry `{ key, exact: true }` counts it as lacking, for a feature whose partial form gives other results (`surface()` asks for `{ key: "css.types.color.oklch.relative_syntax", exact: true }`), and the warning says so: `(a partial implementation counts as lacking)`.
885
885
  - **Chain members** (`chain: { method: { args, spacing?, excludes?, emit } }`) give `() => chain`. `args` is the grammar of the method's parts, checked in the types (the error is on the bad argument and says `ring.width: unexpected "red" ...`) and again at build time. `spacing` makes a lone number a step of the spacing scale (0.25rem), as in `padding`. `emit` returns declarations; a custom property is allowed and its value is not checked, any other property is checked like a `css.*` one. A method is used once: the chain leaves it out. `excludes: ["darken"]` leaves other methods out after this one too, and `args: ""` makes a method that takes no value (`ink()`). A grammar must be a literal type (a `const` variable is fine; if TypeScript has widened it to `string`, the method says so: write `as const`).
886
886
  - **Call members** (`{ args, uses? }` and a function in `build()`) take their arguments by `args`: a grammar (the parts, joined by a space, as a property takes them: `args: "small | large"`), `arg<T>()` (one value of a TypeScript type, which TypeScript checks and `build` gets as it is: `arg<"home" | "star">()`), or a **tuple of positional arguments**, each a grammar (one part), `"$tokens"` (a token set from `createTokens`), `"$overrides"` (values by path for the tokens of the `$tokens` before it, checked in the types against that token set), `"$selector"` (a CSS selector list, checked in the types for brackets and quotes and at build time as a whole), `arg<T>()`, or at the end one object of named leaves (`{ "size?": "<width>", on: "<color>" }`, a key ending in `?` is optional). `build` gets them as written, grammar parts as checked text. The positional form type-checks within the per-call budget; its cost is that an error lands on the call, with the position and the reason in the message, not on the argument. `build` returns `{ decls?, uses?, globals?, themes?, layers? }`.
887
887
  - **`globals`** are global rules that are not classes (`{ rule, layer? }` in the table, or `{ css, layer? }[]` from `build`). A global is identified by its content, not by a name: the same rule from two styles is one, and editing a value replaces it. It is in the sheet of the modules whose styles carry it (as kernels are), and leaves it with them. `layer` sends a rule to a top-level layer of that name (`@layer app`); it must be declared by a `layers` entry (or `layers` from `build`: a list, or `{ layers: [...], before: true }` for layers below the engine's), or by `layers()` in a module imported before. No layer puts it in `_.k`. Unlike a kernel, two globals **may** declare the same custom property; that is what lets a look set the same `--color-*` in several source layers.
@@ -1221,26 +1221,26 @@ export const typo = mdi("clos"); // error: not an icon of mdi
1221
1221
 
1222
1222
  More plugins on `scope()`, each a package of its own with its rules and limits in its README. Import them with the attribute, like `cssints`.
1223
1223
 
1224
- | Package | Members | What it does |
1225
- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1226
- | [`@cssints/fluid`](../packages/fluid/README.md) | `fluid(min, max, { from?, to?, zoom? })`, `fluid.container(...)` | A `clamp()` that grows between two widths, computed at build time; a range that fails WCAG 1.4.4 is a build error |
1227
- | [`@cssints/layout`](../packages/layout/README.md) | `stack()`, `cluster()`, `sidebar()`, `switcher()`, `cover()`, `autoGrid()` | Every Layout primitives as chain members |
1228
- | [`@cssints/fonts`](../packages/fonts/README.md) | `font(family, { provider, ... })` → `.family()`, `.trim()` | `@font-face` and a metric-matched fallback face; cap-height trimming by `text-box`, else capsize's margins |
1229
- | [`@cssints/reset`](../packages/reset/README.md) | `reset({ media?, prose? })` | A modern reset in a top-level `@layer reset` declared before the engine's, below every style; `@cssints/reset/<baseline group>` keeps only the declarations of that group |
1230
- | [`@cssints/tokens`](../packages/tokens/README.md) | `/open-props`, `/radix`, `/flexoki`, `/reasonable-colors`, `/madoromi` | DTCG data for `createTokens` |
1231
- | [`@cssints/gradient`](../packages/gradient/README.md) | `gradient(kind, direction, from, to, easing?, stops?)` | Eased colour stops mixed in oklab at build time |
1232
- | [`@cssints/gradient-2d`](../packages/gradient-2d/README.md) | `meshGradient(mesh)`, `freeformGradient(points)` | `mesh-gradient()` / `freeform-gradient()` where the browser has them, else a runtime's canvas (this package's algorithms; lines and shapes not yet) |
1233
- | [`@cssints/color-names`](../packages/color-names/README.md) | `named(name)`, `colorNames.<sector>(name)`, `/nearest` | The Color Name List (31,939 names) as hex colours; the ten sector members keep an editor's completion short, `nearest()` is the build-time reverse lookup |
1234
- | [`@cssints/motion`](../packages/motion/README.md) | `motion().preset().duration().delay().easing()` | Animation presets over `keyframes()`, with reduced motion |
1235
- | [`@cssints/squircle`](../packages/squircle/README.md) | `squircle().radius()` | `corner-shape: squircle`, else a CSS `mask` of the same shape |
1236
- | [`@cssints/reveal`](../packages/reveal/README.md) | `reveal().preset().range().duration().easing()` | motion's entrance presets on `animation-timeline: view()`; for other targets a script plays it once on entry (delivered by the runtime) |
1237
- | [`@cssints/stuck`](../packages/stuck/README.md) | `sticky().top()`, `stuck(styles)`, `stuck("bottom")(styles)` | Styles inside a sticky element while it is stuck, by `@container scroll-state()`; for other targets an `IntersectionObserver` (delivered by the runtime) |
1238
- | [`@cssints/balance`](../packages/balance/README.md) | `balance()`, `pretty()` | `text-wrap: balance` / `pretty`; for targets without balance a script balances the lines (delivered by the runtime) |
1239
- | [`@cssints/masonry`](../packages/masonry/README.md) | `masonry().columns().gap()` | `display: grid-lanes`, else CSS `columns` (top to bottom per column) |
1240
- | [`@cssints/placeholder`](../packages/placeholder/README.md) | `placeholder(path, { mode? })` | An `<image>` from a JPEG or PNG read at build time: a gradient of its colours laid out as the image, or a tiny thumbhash PNG |
1241
- | [`@cssints/ramp`](../packages/ramp/README.md) | `ramp(base, { mode, steps \| ratios, background })`, `overrides(ramp)` | An OKLCH palette as DTCG data for `createTokens`; the contrast mode meets each ratio against its background |
1242
- | [`@cssints/rybitten`](../packages/rybitten/README.md) | `color(hue, { cube })`, `wheel(steps, { cube })`, `shades(hue, lightness)`, `overrides(group)` | RYBitten's red-yellow-blue colours (36 historical cubes) as DTCG data for `createTokens`: a hue, a wheel of hues, a hue at several lightnesses |
1243
- | [`@cssints/skeleton`](../packages/skeleton/README.md) | `skeleton().radius().color().highlight()` | Loading placeholders whose shimmer is in phase across the page (one clock on `:root`), static under reduced motion |
1224
+ | Package | Members | What it does |
1225
+ | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1226
+ | [`@cssints/fluid`](../packages/fluid/README.md) | `fluid(min, max, { from?, to?, zoom? })`, `fluid.container(...)` | A `clamp()` that grows between two widths, computed at build time; a range that fails WCAG 1.4.4 is a build error |
1227
+ | [`@cssints/layout`](../packages/layout/README.md) | `stack()`, `cluster()`, `sidebar()`, `switcher()`, `cover()`, `autoGrid()` | Every Layout primitives as chain members |
1228
+ | [`@cssints/fonts`](../packages/fonts/README.md) | `font(family, { provider, ... })` → `.family()`, `.trim()` | `@font-face` and a metric-matched fallback face; cap-height trimming by `text-box`, else capsize's margins |
1229
+ | [`@cssints/reset`](../packages/reset/README.md) | `reset({ media?, prose? })` | A modern reset in a top-level `@layer reset` declared before the engine's, below every style; `@cssints/reset/<baseline group>` keeps only the declarations of that group |
1230
+ | [`@cssints/tokens`](../packages/tokens/README.md) | `/open-props`, `/radix`, `/flexoki`, `/reasonable-colors`, `/madoromi` | DTCG data for `createTokens` |
1231
+ | [`@cssints/gradient`](../packages/gradient/README.md) | `gradient(kind, direction, from, to, easing?, stops?)` | Eased colour stops mixed in oklab at build time |
1232
+ | [`@cssints/gradient-2d`](../packages/gradient-2d/README.md) | `meshGradient(mesh)`, `freeformGradient(points)` | `mesh-gradient()` / `freeform-gradient()` where the browser has them, else a runtime's canvas (this package's algorithms; lines and shapes not yet) |
1233
+ | [`@cssints/color-names`](../packages/color-names/README.md) | `named(name)`, `colorNames.<sector>(name)`, `/nearest` | The Color Name List (31,939 names) as hex colours; the ten sector members keep an editor's completion short, `nearest()` is the build-time reverse lookup |
1234
+ | [`@cssints/motion`](../packages/motion/README.md) | `motion().preset().duration().delay().easing()` | Animation presets over `keyframes()`, with reduced motion |
1235
+ | [`@cssints/squircle`](../packages/squircle/README.md) | `squircle().radius()` | `corner-shape: squircle`, else a CSS `mask` of the same shape |
1236
+ | [`@cssints/reveal`](../packages/reveal/README.md) | `reveal().preset().range().duration().easing()`, `appear().preset().range().duration().easing().inOut()` | motion's entrance presets on `animation-timeline: view()` (reveal) or on `timeline-trigger` + `animation-trigger` (appear); for other targets a script plays it once on entry (delivered by the runtime) |
1237
+ | [`@cssints/stuck`](../packages/stuck/README.md) | `sticky().top()`, `stuck(styles)`, `stuck("bottom")(styles)` | Styles inside a sticky element while it is stuck, by `@container scroll-state()`; for other targets an `IntersectionObserver` (delivered by the runtime) |
1238
+ | [`@cssints/balance`](../packages/balance/README.md) | `balance()`, `pretty()` | `text-wrap: balance` / `pretty`; for targets without balance a script balances the lines (delivered by the runtime) |
1239
+ | [`@cssints/masonry`](../packages/masonry/README.md) | `masonry().columns().gap()` | `display: grid-lanes`, else CSS `columns` (top to bottom per column) |
1240
+ | [`@cssints/placeholder`](../packages/placeholder/README.md) | `placeholder(path, { mode? })` | An `<image>` from a JPEG or PNG read at build time: a gradient of its colours laid out as the image, or a tiny thumbhash PNG |
1241
+ | [`@cssints/ramp`](../packages/ramp/README.md) | `ramp(base, { mode, steps \| ratios, background })`, `overrides(ramp)` | An OKLCH palette as DTCG data for `createTokens`; the contrast mode meets each ratio against its background |
1242
+ | [`@cssints/rybitten`](../packages/rybitten/README.md) | `color(hue, { cube })`, `wheel(steps, { cube })`, `shades(hue, lightness)`, `overrides(group)` | RYBitten's red-yellow-blue colours (36 historical cubes) as DTCG data for `createTokens`: a hue, a wheel of hues, a hue at several lightnesses |
1243
+ | [`@cssints/skeleton`](../packages/skeleton/README.md) | `skeleton().radius().color().highlight()` | Loading placeholders whose shimmer is in phase across the page (one clock on `:root`), static under reduced motion |
1244
1244
 
1245
1245
  ### Headless: `createField` and `createConfirm` (`@cssints/headless`)
1246
1246
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cssints",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "CSS in TypeScript: typed css.* calls compiled to atomic CSS at build time (a Vite plugin)",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -68,7 +68,7 @@
68
68
  }
69
69
  },
70
70
  "dependencies": {
71
- "@cssints/css-grammar": "^0.11.0",
71
+ "@cssints/css-grammar": "^0.12.0",
72
72
  "culori": "^4.0.2",
73
73
  "effect": "4.0.6",
74
74
  "happy-dom": "^20.14.5",