ramps.ts

The derived color system's ramp model and fitted default knob values.

This is the numeric single source of truth for the OKLCH palette: the same constants and formulas that variables.ts renders as pure-CSS calc()/pow()/oklch() defaults, evaluated here in TypeScript so design-time tests can gate the defaults (gamut, ramp monotonicity, contrast — see src/test/ramps.test.ts) and derivation scripts can reason about the palette without a browser.

The knob values were fitted against the pre-OKLCH HSL palette to minimize the perceptual delta of the port. Model shapes:

  • lightness: L(t) = L00 + (L100 - L00) * pow(t, curve) with t = stop/100 — the endpoint knobs literally are stops 00/100, so the dark scheme flips direction purely through knob values, and pinning an endpoint stop and turning a knob are the same act
  • chroma: C(t) = min + (max - min) * pow(4t(1-t), curve), a symmetric mid-peaked curve, clamped per stop by the worst-hue gamut caps below
  • the neutral scale rides the same chroma shape scaled by a single knob
view source

Declarations
#

26 declarations

ChromaRampKnobs
#

ramps.ts view source

ChromaRampKnobs import type {ChromaRampKnobs} from '@fuzdev/fuz_css/ramps.js';

Knobs for the symmetric mid-peaked chroma curve, C(t) = min + (max - min) * pow(4t(1-t), curve). The curve expresses the *request*; rendered stops are clamped by PALETTE_CHROMA_CAPS per stop, and --chroma_scale multiplies above the clamp (so vivid themes can knowingly push past the caps and gamut-clip).

chroma_min

Chroma requested at the ramp endpoints (stops 00/100), before capping.

type number

chroma_max

Chroma requested at the ramp midpoint (stop 50), before capping.

type number

curve

Falloff exponent of the peak; higher concentrates chroma at the middle.

type number

LightnessRampKnobs
#

ramps.ts view source

LightnessRampKnobs import type {LightnessRampKnobs} from '@fuzdev/fuz_css/ramps.js';

Knobs for a pow-curve lightness ramp. The endpoints are the ramp's own 00/100 stops, so light and dark schemes differ only in values, never in formula — no direction flag needed.

lightness_00

OKLCH lightness at stop 00, in [0, 1].

type number

lightness_100

OKLCH lightness at stop 100, in [0, 1].

type number

curve

Exponent bending the ramp between the endpoints; 1 is linear.

type number

NEUTRAL_CHROMA
#

ramps.ts view source

Record<"light" | "dark", number> import {NEUTRAL_CHROMA} from '@fuzdev/fuz_css/ramps.js';

Peak chroma of the neutral (shade/text) scales. The neutral rides the palette's chroma shape scaled to this peak, which preserves the old behavior of constant HSL saturation: strong tint at mid lightness, nearly untinted near white and black.

NEUTRAL_HUE
#

ramps.ts view source

number import {NEUTRAL_HUE} from '@fuzdev/fuz_css/ramps.js';

Default OKLCH hue angle of the neutral intent. In CSS the knob chains to the palette (--hue_neutral: var(--hue_f)), porting the old tint_hue behavior; this constant mirrors that default numerically.

PALETTE_CHROMA_CAPS
#

ramps.ts view source

Record<"light" | "dark", Record<"00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", number>> import {PALETTE_CHROMA_CAPS} from '@fuzdev/fuz_css/ramps.js';

Worst-hue safe chroma caps per stop: the largest chroma at that stop's default lightness that stays inside sRGB for every one of the 10 default hues (see oklch_max_srgb_chroma for the non-convexity caveat). Computed at design time from PALETTE_HUES + PALETTE_LIGHTNESS_KNOBS, floored to stay conservative; a drift test recomputes them from the color math.

PALETTE_CHROMA_KNOBS
#

ramps.ts view source

Record<"light" | "dark", ChromaRampKnobs> import {PALETTE_CHROMA_KNOBS} from '@fuzdev/fuz_css/ramps.js';

Fitted chroma-curve knobs for the palette ramps.

Re-fitted ("honest chroma" retune) so the requested curve hugs the effective post-clamp chroma instead of sitting above the caps through the mid-range — turning the knobs down now responds immediately. Turning chroma_max up remains cap-clamped by design; --chroma_scale is the push-past-the-gamut knob. Residual vs the original port is small (mean ΔEOK ≈ 0.005 light / 0.003 dark) except light stop 30 (−0.028 C): the symmetric mid-peaked model can't reach the light cap envelope's peak at stop 30 — recovering it would take an asymmetric shape (peak-position knob).

PALETTE_HUES
#

ramps.ts view source

Record<"g" | "b" | "a" | "c" | "d" | "e" | "f" | "h" | "i" | "j", number> import {PALETTE_HUES} from '@fuzdev/fuz_css/ramps.js';

OKLCH hue angles for the 10 palette hues, fitted from the HSL palette.

PALETTE_LIGHTNESS_KNOBS
#

ramps.ts view source

Record<"light" | "dark", LightnessRampKnobs> import {PALETTE_LIGHTNESS_KNOBS} from '@fuzdev/fuz_css/ramps.js';

Fitted lightness knobs for the palette (palette_X_NN) ramps.

palette_stop_oklch
#

ramps.ts view source

(letter: "g" | "b" | "a" | "c" | "d" | "e" | "f" | "h" | "i" | "j", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "light" | "dark"): Oklch import {palette_stop_oklch} from '@fuzdev/fuz_css/ramps.js';

Computes the default OKLCH color of a palette stop (--palette_X_NN).

letter

type "g" | "b" | "a" | "c" | "d" | "e" | "f" | "h" | "i" | "j"

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

scheme

type "light" | "dark"

returns

Oklch

ramp_chroma
#

ramps.ts view source

(scheme: "light" | "dark", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", chroma_scale?: number): number import {ramp_chroma} from '@fuzdev/fuz_css/ramps.js';

Evaluates the palette chroma at a stop: the knob curve clamped by that stop's worst-hue cap. chroma_scale multiplies above the clamp.

scheme

type "light" | "dark"

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

chroma_scale

type number
default 1

returns

number

ramp_chroma_shape
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", curve: number): number import {ramp_chroma_shape} from '@fuzdev/fuz_css/ramps.js';

Evaluates the normalized chroma shape pow(4t(1-t), curve) at a stop — 0 at the endpoints, 1 at the midpoint.

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

curve

type number

returns

number

ramp_lightness
#

ramps.ts view source

(knobs: LightnessRampKnobs, stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): number import {ramp_lightness} from '@fuzdev/fuz_css/ramps.js';

Evaluates a lightness ramp at a stop.

knobs

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

returns

number

ramp_stop_t
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): number import {ramp_stop_t} from '@fuzdev/fuz_css/ramps.js';

Converts a stop variant to its ramp position t in [0, 1].

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

returns

number

RAMP_STOPS
#

ramps.ts view source

readonly ("00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100")[] import {RAMP_STOPS} from '@fuzdev/fuz_css/ramps.js';

The 13 intensity stops in ramp order (00 → 100).

RampFamily
#

ramps.ts view source

RampFamily import type {RampFamily} from '@fuzdev/fuz_css/ramps.js';

The lightness ramp families and their CSS variable name prefixes.

render_chroma_shape_css
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {render_chroma_shape_css} from '@fuzdev/fuz_css/ramps.js';

Renders the normalized chroma shape of a stop, shared by the palette chroma ramp and the neutral scales: pow(4t(1-t), --palette_chroma_curve). Exactly 0 at the endpoints and 1 at the midpoint.

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

returns

string

render_chroma_stop_css
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "light" | "dark"): string import {render_chroma_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the capped default of a palette chroma ramp stop: the knob curve clamped by that stop's worst-hue gamut cap. Per-scheme because the caps differ; --chroma_scale multiplies outside this clamp, at the color stops.

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

scheme

type "light" | "dark"

returns

string

render_hue_shift_offset_css
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "light" | "dark"): string import {render_hue_shift_offset_css} from '@fuzdev/fuz_css/ramps.js';

Renders a stop's hue-shift offset. --hue_shift is the total rotation in degrees across a ramp, anchored at stop 50; the scheme sign flip is baked into these per-scheme slots so positive values always rotate hue upward toward the dark end.

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

scheme

type "light" | "dark"

returns

string

render_lightness_stop_css
#

ramps.ts view source

(family: RampFamily, stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {render_lightness_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the derived default of an intermediate lightness ramp stop, e.g. --palette_lightness_30: calc(var(--palette_lightness_00) + (var(--palette_lightness_100) - var(--palette_lightness_00)) * pow(0.3, var(--palette_lightness_curve))). Stops 00/100 are the endpoint knobs themselves and have no derived form.

family

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

returns

string

render_neutral_stop_css
#

ramps.ts view source

(family: "text" | "shade", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {render_neutral_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the derived default of a neutral (shade/text) stop. The neutral rides the palette's chroma shape scaled by the --neutral_chroma peak.

family

type "text" | "shade"

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

returns

string

render_palette_stop_css
#

ramps.ts view source

(letter: "g" | "b" | "a" | "c" | "d" | "e" | "f" | "h" | "i" | "j", stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"): string import {render_palette_stop_css} from '@fuzdev/fuz_css/ramps.js';

Renders the derived default of a palette color stop, e.g. --palette_a_50. One definition serves both schemes — the scheme flip lives in the knobs.

letter

type "g" | "b" | "a" | "c" | "d" | "e" | "f" | "h" | "i" | "j"

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

returns

string

render_ramp_color_css
#

ramps.ts view source

(hue_reference: string, stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", alpha?: string | undefined): string import {render_ramp_color_css} from '@fuzdev/fuz_css/ramps.js';

Renders a color derived from the palette ramps at a stop for an arbitrary hue reference — the shared template behind palette stops and intent stops (--accent_50 renders with var(--hue_accent)).

hue_reference

a CSS expression for the hue, e.g. var(--hue_accent)

type string

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

alpha?

optional CSS alpha (e.g. 40%) appended inside the oklch()

type string | undefined
optional

returns

string

SHADE_LIGHTNESS_KNOBS
#

ramps.ts view source

Record<"light" | "dark", LightnessRampKnobs> import {SHADE_LIGHTNESS_KNOBS} from '@fuzdev/fuz_css/ramps.js';

Fitted lightness knobs for the shade (surface) ramps.

shade_stop_oklch
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "light" | "dark"): Oklch import {shade_stop_oklch} from '@fuzdev/fuz_css/ramps.js';

Computes the default OKLCH color of a shade stop (--shade_NN).

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

scheme

type "light" | "dark"

returns

Oklch

TEXT_LIGHTNESS_KNOBS
#

ramps.ts view source

Record<"light" | "dark", LightnessRampKnobs> import {TEXT_LIGHTNESS_KNOBS} from '@fuzdev/fuz_css/ramps.js';

Fitted lightness knobs for the text ramps.

text_stop_oklch
#

ramps.ts view source

(stop: "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100", scheme: "light" | "dark"): Oklch import {text_stop_oklch} from '@fuzdev/fuz_css/ramps.js';

Computes the default OKLCH color of a text stop (--text_NN).

stop

type "00" | "05" | "10" | "20" | "30" | "40" | "50" | "60" | "70" | "80" | "90" | "95" | "100"

scheme

type "light" | "dark"

returns

Oklch

Depends on
#

Imported by
#