/** * Tone math (guuey#403 §2) — the two-panel tone pair, its perceptibility * floor, and the chat-palette derivation. * * The floor is CALIBRATED, not invented (ggui#633's scars): the console's * first cut at ΔL* 3.5 measured below perception; their shipped pair * (#F4F3ED warm paper vs #E4E4E2 neutral chrome) reads clearly at ΔL* 5.2 * because the warm→neutral TEMPERATURE step does perceptual work lightness * alone doesn't. Hence the OR-form floor: * * ΔL* ≥ 6 — OR — a hue-temperature step (Δab ≥ 2) with ΔL* ≥ 5 * * Both arms reject the failed 3.5 cut; the strict arm alone would have * rejected the founder-certified shipped pair. The platform's theme-doc * gate applies its own mirror of this rule server-side; this module is the * lib's own honesty (derived defaults satisfy the floor BY CONSTRUCTION — * pairs that land under it get the documented nudge apart, never a silent * pass). Calibration may RAISE the floor; it does not lower it. */ /** A resolved tone pair for one mode: two backgrounds + their foregrounds. */ export interface TonePair { /** Upper panel (app menus) background. */ upper: string; /** Foreground on the upper tone. */ upperOn: string; /** Lower panel (agent) background. */ lower: string; /** Foreground on the lower tone. */ lowerOn: string; } /** * The lib base defaults — the ggui#633 SHIPPED pair for light, and its * temperature-step mirror for dark (warm umber menu vs neutral chrome, * ΔL* 6.5 — the strict arm). Founder-certified "two-toned and * well-distinguished" in light; the dark pair keeps the identical warm→ * neutral grammar so a mode flip changes brightness, not the layout's * character. Both pairs assert the floor in this package's tests. */ export declare const DEFAULT_TONES: Record<"light" | "dark", TonePair>; /** CIELAB (D65) from a `#rrggbb` hex. Throws on a malformed color. */ export declare function hexToLab(hex: string): { L: number; a: number; b: number; }; /** The perceptibility deltas between two backgrounds. */ export declare function toneDelta(upper: string, lower: string): { dL: number; dab: number; }; /** The OR-form floor (module header). */ export declare function meetsToneFloor(upper: string, lower: string): boolean; /** * Reject-under-floor with the explanatory message (the brandAccent * posture): overrides that fail perceptibility throw HERE, at wiring time, * never render as an invisible seam. */ export declare function assertToneFloor(pair: TonePair): void; /** * Base-tier derivation (§2, platform's pick): tones DERIVE from the chat * palette's surface/canvas pair, so an already-themed app gets coherent * tones for free — theming chat themes the layout, no second authoring * step. `surface` grounds the AGENT (lower) panel — it is the chat's own * ground — and `canvas` grounds the MENU (upper) panel. Pairs that land * under the floor get the documented nudge: the upper tone walks away from * the lower along the lightness axis (toward white below L* 50, toward * black above — always INTO the pair's existing contrast direction) until * the strict arm passes. Deterministic, bounded, and asserted by tests. */ export declare function deriveTones(palette: { surface: string; canvas: string; ink: string; }): Pick & { nudged: boolean; }; /** Linear sRGB-space hex mix (`t` toward `target`). Exported for tests. */ export declare function mixHex(base: string, target: string, t: number): string; //# sourceMappingURL=tones.d.ts.map