/** A 50→900 color ramp. Index roles are stable across light and dark. */ export type ColorScale = { 50: string; 100: string; 200: string; 300: string; 400: string; 500: string; 600: string; 700: string; 800: string; 900: string; }; /** Alpha steps derived from a brand's 500 anchor. */ export type OpacityScale = { 4: string; 8: string; 16: string; 24: string; 32: string; 40: string; 48: string; }; export type BrandScale = ColorScale & { opacity: OpacityScale; }; export type SemanticTone = "success" | "error" | "warning" | "info"; export type SemanticColors = Record; /** Each tone as TEXT on the canvas, resolved to 4.5:1. The `[500]` rung is a fill, never ink. */ export type SemanticTextTokens = Record; /** Named (non-numeric) surface keys. Elevation order inverts between light and dark. */ export type NamedSurfaces = { main: string; secondary: string; tertiary: string; quaternary: string; light: string; medium: string; accent: string; subtle: string; muted: string; neutral: string; base: string; tableHeader: string; }; /** The permanently-dark rail. Accents are derived from the light primary, never hand-written. */ export type SidebarTokens = { background: ColorScale; /** Icon on the active surface, resolved to 3:1. */ activeIcon: string; /** Label on the active surface, resolved to 4.5:1. */ activeLabel: string; /** Flyout/menu surface raised off the rail. `background[200]` is a mid-grey on 6 of 9 brands. */ elevated: string; /** Secondary icon on the rail, resolved to 3:1. Replaces an opacity guess at the call site. */ mutedIcon: string; /** Secondary label on the rail, resolved to 4.5:1. `textMuted` is canvas-relative, not rail. */ mutedLabel: string; /** Status ink resolved against the RAIL. `semanticText` is canvas-relative, not rail. */ semanticText: SemanticTextTokens; /** Row fills, opaque — replace `whiteAlpha` hover/active/divider chrome on the rail. */ hoverBg: string; activeBg: string; divider: string; }; export type FocusRingTokens = { /** Outer band. >=3:1 against the canvas, a card surface, and the control's own fill. */ ring: string; /** Inner band, in the surface tone. >=3:1 against the fill it hugs and against `ring`. */ halo: string; }; export type BoxShadowTokens = { primary: string; error: string; default: string; }; /** Full per-brand colour palette, one per brand per colour mode. */ export type PaletteProps = { gradient: { from: string; to: string; }; primary: BrandScale; secondary: BrandScale; tertiary: BrandScale; transparent: string; black: string; white: string; semantic: SemanticColors; gray: ColorScale; red: ColorScale; orange: ColorScale; yellow: ColorScale; green: ColorScale; teal: ColorScale; blue: ColorScale; cyan: ColorScale; purple: ColorScale; pink: ColorScale; backgroundColor: NamedSurfaces; background: ColorScale; text: ColorScale; header: ColorScale; placeholder: ColorScale; boxShadow: BoxShadowTokens; /** Two-tone `:focus-visible` indicator, resolved to 3:1 (WCAG 1.4.11). Never hand-written. */ focusRing: FocusRingTokens; sidebar: SidebarTokens; boxborder: ColorScale; border: ColorScale; table: { hover: ColorScale; }; disabled: ColorScale; /** Accent color for accent-colored text on the canvas — distinct from `primary[500]`. */ accentText: string; semanticText: SemanticTextTokens; /** Secondary text on the canvas, resolved to 4.5:1 in both modes. */ textMuted: string; /** Ink for a `primary[500]`-FILLED surface — never an ink on the canvas. */ onPrimary: string; /** Ink for a `semantic[tone][500]`-FILLED surface — never an ink on the canvas. */ onSemantic: SemanticTextTokens; /** Dialog/drawer/popover/menu surface: `background[50]` in light, one elevation step up in dark. */ surfaceRaised: string; /** Rating-star gold, the same hue in every brand. Decorative: always pair it with a numeric rating. */ star: string; }; /** What a brand writes by hand; every token required, so a gap is a compile error. */ /** Derived tokens are excluded — `finalizeLightPalette` resolves them per brand. */ export type BrandPaletteSource = Omit & { sidebar: { background: ColorScale; }; }; /** Utility scales carrying no brand identity. The only tokens a brand may inherit. */ export type NeutralPaletteKey = "transparent" | "black" | "white" | "semantic" | "red" | "orange" | "yellow" | "green" | "teal" | "blue" | "cyan" | "purple" | "pink"; export type NeutralPaletteTokens = Pick; /** Everything a brand must state itself — never by spreading another brand. */ export type BrandIdentityTokens = Omit; /** Brand identities shipped by the library. */ export type ThemeName = "lavender" | "meadow" | "radiant" | "skyline" | "slate" | "emerald" | "rosewood" | "storefront" | "zinc"; /** User-selectable color mode. `system` follows the OS setting. */ export type ColorMode = "light" | "dark" | "system"; /** Color mode after `system` has been resolved against the OS. */ export type ResolvedColorMode = "light" | "dark";