surface(): parent-relative colourThe second plugin on scope() and the same runtime. A surface passes its colour down the tree; a nested surface is that colour with its OKLCH lightness moved, through any number of plain wrappers. These are tonal steps, not a contrast guarantee: contrast() and ink() pick a direction by lightness and never compute a ratio.
import * as import csscss from "cssints" with { type: "cssints" };
import { const surface: () => Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface } from "cssints/surface" with { type: "cssints" };
const const canvas: Token<"color", true, string>canvas = import csscss.const token: {
readonly number: TokenFn<"number">;
readonly length: TokenFn<"length">;
readonly color: TokenFn<"color">;
readonly percentage: TokenFn<"percentage">;
readonly integer: TokenFn<"integer">;
readonly angle: TokenFn<"angle">;
readonly time: TokenFn<"time">;
readonly resolution: TokenFn<"resolution">;
readonly url: TokenFn<"url">;
readonly image: TokenFn<"image">;
readonly shadow: TokenFn<"shadow">;
readonly lengthPercentage: TokenFn<"lengthPercentage">;
readonly customIdent: TokenFn<...>;
readonly transformList: TokenFn<...>;
readonly easingFunction: TokenFn<...>;
} & {
...;
}
`token.<type>(initial, name?)`: a Typed OM value of the type, `var(--name)`. With a name it can be set.token.color: <"#2b3a67", "canvas">(initial: "#2b3a67", name?: "canvas" | undefined) => Token<"color", true, string>color("#2b3a67", "canvas");
// a base, then a lighter card on it (a token or a colour), a field a step darker, a button pushed away from its parent
export const const page: Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, "color">, AliasesOf<...>>
page = function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().color: <readonly [Token<"color", true, string>]>(parts_0: Token<"color", true, string>) => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [...][];
};
readonly ink: {
...;
};
}, "color">, AliasesOf<...>>
color(const canvas: Token<"color", true, string>canvas);
export const const card: css.Stylecard = import csscss.const cn: (...styles: css.Style[]) => css.Stylecn(function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().lighten: <readonly [0.06]>(parts_0: 0.06) => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
...;
};
}, "lighten" | ... 1 more ... | "contrast">, AliasesOf<...>>
lighten(0.06), import csscss.const hover: (...styles: css.Style[]) => css.StyleChrome 1, Edge 12, Firefox 1, Safari 2, iOS 1, Android 18. [MDN](https://developer.mozilla.org/docs/Web/CSS/:hover)hover(function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().lighten: <readonly [0.1]>(parts_0: 0.1) => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
...;
};
}, "lighten" | ... 1 more ... | "contrast">, AliasesOf<...>>
lighten(0.1)));
export const const field: Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, "lighten" | ... 1 more ... | "contrast">, AliasesOf<...>>
field = function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().darken: <readonly [0.03]>(parts_0: 0.03) => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
...;
};
}, "lighten" | ... 1 more ... | "contrast">, AliasesOf<...>>
darken(0.03);
export const const cta: Chain<"surface", Omit<Omit<Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, "color">, "lighten" | ... 1 more ... | "contrast">, "ink">, AliasesOf<...>>
cta = function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().color: <readonly ["oklch(from #e11d48 l c h)"]>(parts_0: "oklch(from #e11d48 l c h)") => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [...][];
};
readonly ink: {
...;
};
}, "color">, AliasesOf<...>>
color("oklch(from #e11d48 l c h)").contrast: <readonly [0.15]>(parts_0: 0.15) => Chain<"surface", Omit<Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
...;
};
}, "color">, "lighten" | ... 1 more ... | "contrast">, AliasesOf<...>>
contrast(0.15).ink: () => Chain<"surface", Omit<Omit<Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, "color">, "lighten" | ... 1 more ... | "contrast">, "ink">, AliasesOf<...>>
ink();
export const const both: anyboth = function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().lighten: <readonly [0.1]>(parts_0: 0.1) => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
...;
};
}, "lighten" | ... 1 more ... | "contrast">, AliasesOf<...>>
lighten(0.1).darken(0.1); // error: lighten, darken and contrast do not go togetherexport const const wide: Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, "color">, AliasesOf<...>>
wide = function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().color: <readonly ["wide"]>(parts_0: "surface.color: unexpected \"wide\" in \"wide\", grammar <color>") => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [...][];
};
readonly ink: {
...;
};
}, "color">, AliasesOf<...>>
color("wide"); // error: not a colourexport const const noValue: Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, "ink">, AliasesOf<...>>
noValue = function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().ink: () => Chain<"surface", Omit<{
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, "ink">, AliasesOf<...>>
ink("black"); // error: ink() takes no valueexport const const own: anyown = function surface(): Chain<"surface", {
readonly color: {
readonly args: "<color>";
readonly emit: (v: string) => [string, string][];
};
readonly lighten: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["darken", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly darken: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "contrast"];
readonly emit: (v: string) => [string, string][];
};
readonly contrast: {
readonly args: "<number [0,1]>";
readonly excludes: readonly ["lighten", "darken"];
readonly emit: (v: string) => [string, string][];
};
readonly ink: {
readonly args: "";
readonly emit: () => [...][];
};
}, AliasesOf<...>>
surface().radius("4px"); // error: a surface chains its own methods onlycolor(<color> | token) is an absolute base (without it the base is the nearest surface around, or Canvas for the outermost); lighten(step), darken(step) and contrast(step) move the lightness of the base by a <number [0,1]>, and only one of the three goes in a chain; ink() sets the text colour to black or white by the lightness of the surface (above 0.5636 black, else white). contrast moves away from the parent: a light parent is darkened, a dark one lightened. The base may be a relative colour (oklch(from var(--brand) l c h)).cn() that holds surface() and background or background-color, bg() included (cssints: surface: surface() sets the background colour: use its methods (this style also sets background-color)). backgroundImage, color and the border colours do not conflict. Conflicts across cx() are not seen, as for any plugin._surface-core and one class per method (._x{--surface-d:0.06}, in _.a, or _.b inside a condition: a hover() or a media query moves every surface below). The kernel surface.core (about 1 kB minified with its registrations and fallback, once, in _.k) is two @container style(--surface-p: ...) rules that alternate two registered <color> properties, --surface-e and --surface-o, because a property cannot read itself; the step --surface-d is not registered, since it may contain l, which only means something inside oklch(from …). Its names are --surface-*; frame's are --frame-*, so a frame and a surface can be one element, or nest in each other, with no collision.ink() on a saturated surface can fall short of WCAG AA. For a ratio, declare the colours as tokens and use css.check.contrast (see Themes): it checks the declared pair at build time, which the kernel cannot do because it never sees the parent.@container style() on custom properties (Chrome 111, Safari 18, Firefox 151), @property (Chrome 85, Safari 16.4, Firefox 128) and relative colour (Chrome 122, Safari 18, Firefox 128). Chrome 119 to 121 and Safari 16.4 to 17.6 have an early relative colour with other channel scales: the steps come out wrong (in Chrome l is a number from 0 to 100), so the kernel's requires asks for the whole feature (exact, see Plugins) and a target set that holds one of them gets the warning. Safari 17 has no style queries, so it gets the runtime as well, which does not change the steps; Chrome 120 has style queries and gets no runtime, only the warning. For a target that has @property and relative colour but lacks style queries (Firefox 128 to 150) the build ships the same fallback as frame(): the shared cssints/parent-vars script (one observer however many plugins use it) copies each surface's colour to its surface children. A surface that is also a frame needs both transition sentinels, so the fallback has a rule for ._surface-core._frame-core (the surface scope embeds the frame scope for that class: &(frame.core)). Below @property or relative colour the kernel is a build warning: a surface keeps no tonal step there.canvas-based colours, and a transition of your own on a surface replaces the sentinel that lets :hover and media conditions reach the script.