@newtonedev/colors 1.0.0 → 1.1.1

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/config.d.ts CHANGED
@@ -34,6 +34,14 @@ export declare const MAX_DARKEST_L = 0.16;
34
34
  export declare const GRADING_REACH: number;
35
35
  /** Maximum amount for global grading. Inputs above this are clamped. */
36
36
  export declare const MAX_GRADING_AMOUNT = 0.25;
37
+ /**
38
+ * Fraction of the gamut boundary injected as chroma when global grading
39
+ * is active. Ensures grading has a visible tinting effect even on
40
+ * achromatic (chroma.amount = 0) palettes.
41
+ *
42
+ * Only global grading injects chroma — per-palette shift does not.
43
+ */
44
+ export declare const GRADING_CHROMA_RATIO = 0.5;
37
45
  /**
38
46
  * How far per-palette hue shift reaches into the scale from each end (0–1).
39
47
  * Slightly wider than GRADING_REACH to give per-palette shifts more room.
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC;AAI7B;;;GAGG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,aAAa,OAAO,CAAC;AAIlC;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,wEAAwE;AACxE,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAIpC;;;;GAIG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,WAAW,IAAI,CAAC;AAI7B;;;GAGG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,aAAa,OAAO,CAAC;AAIlC;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,wEAAwE;AACxE,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAExC;;;GAGG;AACH,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AAIpC;;;;GAIG;AACH,eAAO,MAAM,cAAc,OAAO,CAAC"}
@@ -15,4 +15,6 @@ export declare function oklchToHex(color: Oklch): Hex;
15
15
  export declare function p3ToOklch(color: Srgb): Oklch;
16
16
  /** Convert OKLCH to Display P3. May produce out-of-gamut values (channels outside [0,1]). */
17
17
  export declare function oklchToP3(color: Oklch): Srgb;
18
+ /** Convert OKLCH to a CSS `color(display-p3 r g b)` string. Clamps channels to [0,1]. */
19
+ export declare function oklchToP3Css(color: Oklch): string;
18
20
  //# sourceMappingURL=pipeline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/conversions/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAO3D,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAE9C;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE9C;AAED,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAE9C;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE9C;AAED,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAE7C;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,GAAG,CAO5C;AAED,mCAAmC;AACnC,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAE5C;AAED,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE5C"}
1
+ {"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../src/conversions/pipeline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAO3D,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAE9C;AAED,uFAAuF;AACvF,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE9C;AAED,6BAA6B;AAC7B,wBAAgB,WAAW,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAE9C;AAED,8DAA8D;AAC9D,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE9C;AAED,4BAA4B;AAC5B,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAE7C;AAED,sEAAsE;AACtE,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,GAAG,GAAG,CAO5C;AAED,mCAAmC;AACnC,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,KAAK,CAE5C;AAED,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAE5C;AAED,yFAAyF;AACzF,wBAAgB,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAMjD"}
@@ -3,4 +3,6 @@ import type { Srgb } from "../types.js";
3
3
  export declare function isInGamut(color: Srgb): boolean;
4
4
  /** Clamp sRGB channels to [0, 1]. */
5
5
  export declare function clampSrgb(color: Srgb): Srgb;
6
+ /** Clamp Display P3 channels to [0, 1]. */
7
+ export declare const clampP3: typeof clampSrgb;
6
8
  //# sourceMappingURL=check.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/gamut/check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAS9C;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAM3C"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/gamut/check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGxC,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,OAAO,CAS9C;AAED,qCAAqC;AACrC,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,GAAG,IAAI,CAM3C;AAED,2CAA2C;AAC3C,eAAO,MAAM,OAAO,kBAAY,CAAC"}
package/dist/index.cjs CHANGED
@@ -211,6 +211,13 @@ function p3ToOklch(color) {
211
211
  function oklchToP3(color) {
212
212
  return linearSrgbToSrgb(oklabToLinearP3(oklchToOklab(color)));
213
213
  }
214
+ function oklchToP3Css(color) {
215
+ const p3 = oklchToP3(color);
216
+ const r = Math.max(0, Math.min(1, p3.r)).toFixed(4);
217
+ const g = Math.max(0, Math.min(1, p3.g)).toFixed(4);
218
+ const b = Math.max(0, Math.min(1, p3.b)).toFixed(4);
219
+ return `color(display-p3 ${r} ${g} ${b})`;
220
+ }
214
221
 
215
222
  // src/gamut/check.ts
216
223
  function isInGamut(color) {
@@ -223,6 +230,7 @@ function clampSrgb(color) {
223
230
  b: Math.max(0, Math.min(1, color.b))
224
231
  };
225
232
  }
233
+ var clampP3 = clampSrgb;
226
234
 
227
235
  // src/color/difference.ts
228
236
  function deltaEOK(a, b) {
@@ -358,6 +366,7 @@ var MIN_LIGHTEST_L = 0.96;
358
366
  var MAX_DARKEST_L = 0.16;
359
367
  var GRADING_REACH = 3 / 5;
360
368
  var MAX_GRADING_AMOUNT = 0.25;
369
+ var GRADING_CHROMA_RATIO = 0.5;
361
370
  var SHIFT_REACH = 2 / 3;
362
371
  var MAX_SHIFT_AMOUNT = 0.5;
363
372
  var PERCEPTUAL_JND = 0.02;
@@ -369,28 +378,38 @@ function gradeHue(baseHue, t, grade, reach = GRADING_REACH, maxIntensity = MAX_G
369
378
  if (li === 0 && di === 0) return baseHue;
370
379
  const lightInfluence = t <= reach ? 0.5 * (1 + Math.cos(Math.PI * t / reach)) : 0;
371
380
  const darkInfluence = t >= 1 - reach ? 0.5 * (1 + Math.cos(Math.PI * (1 - t) / reach)) : 0;
372
- const toRad = Math.PI / 180;
373
- const baseRad = baseHue * toRad;
381
+ const toRad2 = Math.PI / 180;
382
+ const baseRad = baseHue * toRad2;
374
383
  const bx = Math.cos(baseRad);
375
384
  const by = Math.sin(baseRad);
376
385
  let dx = 0;
377
386
  let dy = 0;
378
387
  if (lightInfluence > 0 && li > 0) {
379
388
  const blend = lightInfluence * li;
380
- const lRad = grade.light.hue * toRad;
389
+ const lRad = grade.light.hue * toRad2;
381
390
  dx += blend * (Math.cos(lRad) - bx);
382
391
  dy += blend * (Math.sin(lRad) - by);
383
392
  }
384
393
  if (darkInfluence > 0 && di > 0) {
385
394
  const blend = darkInfluence * di;
386
- const dRad = grade.dark.hue * toRad;
395
+ const dRad = grade.dark.hue * toRad2;
387
396
  dx += blend * (Math.cos(dRad) - bx);
388
397
  dy += blend * (Math.sin(dRad) - by);
389
398
  }
390
399
  const rx = bx + dx;
391
400
  const ry = by + dy;
392
401
  if (rx * rx + ry * ry < 1e-20) return baseHue;
393
- return (Math.atan2(ry, rx) / toRad + 360) % 360;
402
+ return (Math.atan2(ry, rx) / toRad2 + 360) % 360;
403
+ }
404
+ function gradingInfluence(t, grading) {
405
+ const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));
406
+ const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));
407
+ if (li === 0 && di === 0) return 0;
408
+ const lightInfluence = t <= GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * t / GRADING_REACH)) : 0;
409
+ const darkInfluence = t >= 1 - GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * (1 - t) / GRADING_REACH)) : 0;
410
+ const lightBlend = lightInfluence * (li / MAX_GRADING_AMOUNT);
411
+ const darkBlend = darkInfluence * (di / MAX_GRADING_AMOUNT);
412
+ return Math.max(lightBlend, darkBlend);
394
413
  }
395
414
  function resolveGradedHue(baseHue, t, globalGrade, localGrade) {
396
415
  let h = baseHue;
@@ -418,6 +437,38 @@ function lightnessToScaleT(L, lightestL, darkestL) {
418
437
  }
419
438
 
420
439
  // src/scale/generate.ts
440
+ var toRad = Math.PI / 180;
441
+ function applyGradingOverlay(C, h, L, t, grading, gamut) {
442
+ const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));
443
+ const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));
444
+ if (li === 0 && di === 0) return { C, h };
445
+ const lightFade = t <= GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * t / GRADING_REACH)) : 0;
446
+ const darkFade = t >= 1 - GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * (1 - t) / GRADING_REACH)) : 0;
447
+ const lightBlend = lightFade * (li / MAX_GRADING_AMOUNT);
448
+ const darkBlend = darkFade * (di / MAX_GRADING_AMOUNT);
449
+ if (lightBlend === 0 && darkBlend === 0) return { C, h };
450
+ const hRad = h * toRad;
451
+ let a = C * Math.cos(hRad);
452
+ let b = C * Math.sin(hRad);
453
+ if (lightBlend > 0) {
454
+ const lh = grading.light.hue;
455
+ const lRad = lh * toRad;
456
+ const lC = maxChroma(L, lh, gamut) * GRADING_CHROMA_RATIO * lightBlend;
457
+ a += lC * Math.cos(lRad);
458
+ b += lC * Math.sin(lRad);
459
+ }
460
+ if (darkBlend > 0) {
461
+ const dh = grading.dark.hue;
462
+ const dRad = dh * toRad;
463
+ const dC = maxChroma(L, dh, gamut) * GRADING_CHROMA_RATIO * darkBlend;
464
+ a += dC * Math.cos(dRad);
465
+ b += dC * Math.sin(dRad);
466
+ }
467
+ let newC = Math.sqrt(a * a + b * b);
468
+ let newH = (Math.atan2(b, a) / toRad + 360) % 360;
469
+ newC = Math.min(newC, maxChroma(L, newH, gamut));
470
+ return { C: newC, h: newH };
471
+ }
421
472
  function generateScale(options = {}) {
422
473
  const {
423
474
  contrast,
@@ -443,8 +494,13 @@ function generateScale(options = {}) {
443
494
  for (let i = 0; i < steps; i++) {
444
495
  const t = i / (steps - 1);
445
496
  const L = lightestL - t * (lightestL - darkestL);
446
- const h = hueAt(t);
447
- const C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));
497
+ let h = hueAt(t);
498
+ let C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));
499
+ if (hueGrade) {
500
+ const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);
501
+ C = overlay.C;
502
+ h = overlay.h;
503
+ }
448
504
  scale2.push({ L, C, h });
449
505
  }
450
506
  return scale2;
@@ -485,7 +541,7 @@ function generateScale(options = {}) {
485
541
  for (let i = 0; i < steps; i++) {
486
542
  const t = i / (steps - 1);
487
543
  const L = lightestL - t * (lightestL - darkestL);
488
- const h = hueAt(t);
544
+ let h = hueAt(t);
489
545
  let tWarped;
490
546
  if (t <= targetT) {
491
547
  tWarped = t * (peakT / targetT);
@@ -495,7 +551,12 @@ function generateScale(options = {}) {
495
551
  const Lwarped = lightestL - tWarped * (lightestL - darkestL);
496
552
  const warpedC = maxChroma(Lwarped, hue, gamut) * ratio;
497
553
  const boundaryC = maxChroma(L, h, gamut);
498
- const C = Math.min(warpedC, boundaryC);
554
+ let C = Math.min(warpedC, boundaryC);
555
+ if (hueGrade) {
556
+ const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);
557
+ C = overlay.C;
558
+ h = overlay.h;
559
+ }
499
560
  scale.push({ L, C, h });
500
561
  }
501
562
  return scale;
@@ -549,6 +610,7 @@ function keyColor(color, options) {
549
610
  exports.APCA_LC_MAX = APCA_LC_MAX;
550
611
  exports.DEFAULT_HUE = DEFAULT_HUE;
551
612
  exports.DEFAULT_SCALE_STEPS = DEFAULT_SCALE_STEPS;
613
+ exports.GRADING_CHROMA_RATIO = GRADING_CHROMA_RATIO;
552
614
  exports.GRADING_REACH = GRADING_REACH;
553
615
  exports.MAX_DARKEST_L = MAX_DARKEST_L;
554
616
  exports.MAX_GRADING_AMOUNT = MAX_GRADING_AMOUNT;
@@ -559,6 +621,7 @@ exports.SHIFT_REACH = SHIFT_REACH;
559
621
  exports.apcaContrast = apcaContrast;
560
622
  exports.apcaToNormalized = apcaToNormalized;
561
623
  exports.buildOneSidedGrade = buildOneSidedGrade;
624
+ exports.clampP3 = clampP3;
562
625
  exports.clampSrgb = clampSrgb;
563
626
  exports.contrastTextHex = contrastTextHex;
564
627
  exports.deltaEOK = deltaEOK;
@@ -566,6 +629,7 @@ exports.deltaEOKLab = deltaEOKLab;
566
629
  exports.gamutMap = gamutMap;
567
630
  exports.generateScale = generateScale;
568
631
  exports.gradeHue = gradeHue;
632
+ exports.gradingInfluence = gradingInfluence;
569
633
  exports.hexToOklch = hexToOklch;
570
634
  exports.hexToSrgb = hexToSrgb;
571
635
  exports.isInGamut = isInGamut;
@@ -585,6 +649,7 @@ exports.oklabToSrgb = oklabToSrgb;
585
649
  exports.oklchToHex = oklchToHex;
586
650
  exports.oklchToOklab = oklchToOklab;
587
651
  exports.oklchToP3 = oklchToP3;
652
+ exports.oklchToP3Css = oklchToP3Css;
588
653
  exports.oklchToSrgb = oklchToSrgb;
589
654
  exports.p3ToOklch = p3ToOklch;
590
655
  exports.resolveGradedHue = resolveGradedHue;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/conversions/oklab.ts","../src/conversions/linear-srgb.ts","../src/conversions/linear-p3.ts","../src/conversions/srgb.ts","../src/conversions/hex.ts","../src/conversions/pipeline.ts","../src/gamut/check.ts","../src/color/difference.ts","../src/gamut/map.ts","../src/gamut/max-chroma.ts","../src/contrast/wcag.ts","../src/contrast/apca.ts","../src/color/interpolation.ts","../src/config.ts","../src/scale/hue-grade.ts","../src/scale/dynamic-range.ts","../src/scale/generate.ts","../src/scale/resolve-color.ts","../src/scale/key-color.ts"],"names":["scale"],"mappings":"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","file":"index.cjs","sourcesContent":["// ── sRGB Gamma Transfer (IEC 61966-2-1) ──\n\nexport const SRGB_GAMMA_THRESHOLD = 0.04045;\nexport const SRGB_GAMMA_THRESHOLD_LINEAR = 0.0031308;\nexport const SRGB_GAMMA_SLOPE = 12.92;\nexport const SRGB_GAMMA_EXPONENT = 2.4;\nexport const SRGB_GAMMA_OFFSET = 0.055;\nexport const SRGB_GAMMA_SCALE = 1.055;\n\n// ── Ottosson M1: Linear sRGB → LMS ──\n\nexport const LINEAR_SRGB_TO_LMS = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n] as const;\n\n// ── Ottosson M2: LMS′ (cube-root) → OKLAB ──\n\nexport const LMS_PRIME_TO_OKLAB = [\n [+0.2104542553, +0.7936177850, -0.0040720468],\n [+1.9779984951, -2.4285922050, +0.4505937099],\n [+0.0259040371, +0.7827717662, -0.8086757660],\n] as const;\n\n// ── Inverse M2: OKLAB → LMS′ ──\n\nexport const OKLAB_TO_LMS_PRIME = [\n [1.0000000000, +0.3963377774, +0.2158037573],\n [1.0000000000, -0.1055613458, -0.0638541728],\n [1.0000000000, -0.0894841775, -1.2914855480],\n] as const;\n\n// ── Inverse M1: LMS → Linear sRGB ──\n\nexport const LMS_TO_LINEAR_SRGB = [\n [+4.0767416621, -3.3077115913, +0.2309699292],\n [-1.2684380046, +2.6097574011, -0.3413193965],\n [-0.0041960863, -0.7034186147, +1.7076147010],\n] as const;\n\n// ── Display P3 M1: Linear Display P3 → LMS ──\n// Derived: XYZ_to_LMS × P3_to_XYZ, where XYZ_to_LMS = M1_srgb × inv(sRGB_to_XYZ)\n\nexport const LINEAR_P3_TO_LMS = [\n [+0.4813791595, +0.4621155872, +0.0565406381],\n [+0.2288319169, +0.6532167007, +0.1179528072],\n [+0.0839457149, +0.2241651052, +0.6918912614],\n] as const;\n\n// ── Inverse P3 M1: LMS → Linear Display P3 ──\n\nexport const LMS_TO_LINEAR_P3 = [\n [+3.1277694390, -2.2570600176, +0.1291828502],\n [-1.0910091977, +2.4133065499, -0.3222615148],\n [-0.0260108068, -0.5080402362, +1.5340494942],\n] as const;\n\n// ── Gamut Mapping ──\n\nexport const GAMUT_EPSILON = 1e-6;\nexport const GAMUT_MAP_JND = 0.02;\nexport const GAMUT_MAP_EPSILON = 1e-4;\nexport const GAMUT_MAP_MAX_ITERATIONS = 50;\n\n// ── Achromatic Threshold ──\n\nexport const ACHROMATIC_THRESHOLD = 1e-10;\n\n// ── WCAG 2.x Luminance Coefficients ──\n\nexport const WCAG_R = 0.2126;\nexport const WCAG_G = 0.7152;\nexport const WCAG_B = 0.0722;\n\n// ── APCA-W3 (SA98G) Constants ──\n\nexport const APCA_MAIN_TRC = 2.4;\nexport const APCA_SRGB_R = 0.2126729;\nexport const APCA_SRGB_G = 0.7151522;\nexport const APCA_SRGB_B = 0.0721750;\nexport const APCA_NORM_BG = 0.56;\nexport const APCA_NORM_TXT = 0.57;\nexport const APCA_REV_TXT = 0.62;\nexport const APCA_REV_BG = 0.65;\nexport const APCA_BLK_THRS = 0.022;\nexport const APCA_BLK_CLMP = 1.414;\nexport const APCA_SCALE_BOW = 1.14;\nexport const APCA_SCALE_WOB = 1.14;\nexport const APCA_LO_BOW_OFFSET = 0.027;\nexport const APCA_LO_WOB_OFFSET = 0.027;\nexport const APCA_DELTA_Y_MIN = 0.0005;\nexport const APCA_LO_CLIP = 0.1;\n\n// ── Angle Math ──\n\nexport const DEG_TO_RAD = Math.PI / 180;\nexport const RAD_TO_DEG = 180 / Math.PI;\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD, DEG_TO_RAD, RAD_TO_DEG } from \"../constants.js\";\n\n/** Convert OKLAB (cartesian) to OKLCH (cylindrical). Achromatic colors get h=0. */\nexport function oklabToOklch(lab: Oklab): Oklch {\n const C = Math.sqrt(lab.a * lab.a + lab.b * lab.b);\n\n if (C < ACHROMATIC_THRESHOLD) {\n return { L: lab.L, C: 0, h: 0 };\n }\n\n let h = Math.atan2(lab.b, lab.a) * RAD_TO_DEG;\n if (h < 0) h += 360;\n\n return { L: lab.L, C, h };\n}\n\n/** Convert OKLCH (cylindrical) to OKLAB (cartesian). */\nexport function oklchToOklab(lch: Oklch): Oklab {\n const hRad = lch.h * DEG_TO_RAD;\n return {\n L: lch.L,\n a: lch.C * Math.cos(hRad),\n b: lch.C * Math.sin(hRad),\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_SRGB_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_SRGB,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear sRGB to OKLAB via Ottosson's direct M1/M2 matrices. */\nexport function linearSrgbToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear sRGB → LMS\n const l =\n LINEAR_SRGB_TO_LMS[0][0] * color.r +\n LINEAR_SRGB_TO_LMS[0][1] * color.g +\n LINEAR_SRGB_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_SRGB_TO_LMS[1][0] * color.r +\n LINEAR_SRGB_TO_LMS[1][1] * color.g +\n LINEAR_SRGB_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_SRGB_TO_LMS[2][0] * color.r +\n LINEAR_SRGB_TO_LMS[2][1] * color.g +\n LINEAR_SRGB_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear sRGB via inverse M2/M1 matrices. */\nexport function oklabToLinearSrgb(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear sRGB\n return {\n r:\n LMS_TO_LINEAR_SRGB[0][0] * l +\n LMS_TO_LINEAR_SRGB[0][1] * m +\n LMS_TO_LINEAR_SRGB[0][2] * s,\n g:\n LMS_TO_LINEAR_SRGB[1][0] * l +\n LMS_TO_LINEAR_SRGB[1][1] * m +\n LMS_TO_LINEAR_SRGB[1][2] * s,\n b:\n LMS_TO_LINEAR_SRGB[2][0] * l +\n LMS_TO_LINEAR_SRGB[2][1] * m +\n LMS_TO_LINEAR_SRGB[2][2] * s,\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_P3_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_P3,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear Display P3 to OKLAB via P3-specific M1 + shared M2. */\nexport function linearP3ToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear P3 → LMS\n const l =\n LINEAR_P3_TO_LMS[0][0] * color.r +\n LINEAR_P3_TO_LMS[0][1] * color.g +\n LINEAR_P3_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_P3_TO_LMS[1][0] * color.r +\n LINEAR_P3_TO_LMS[1][1] * color.g +\n LINEAR_P3_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_P3_TO_LMS[2][0] * color.r +\n LINEAR_P3_TO_LMS[2][1] * color.g +\n LINEAR_P3_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB (shared M2)\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear Display P3 via shared inverse M2 + P3-specific inverse M1. */\nexport function oklabToLinearP3(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′ (shared inverse M2)\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear P3\n return {\n r:\n LMS_TO_LINEAR_P3[0][0] * l +\n LMS_TO_LINEAR_P3[0][1] * m +\n LMS_TO_LINEAR_P3[0][2] * s,\n g:\n LMS_TO_LINEAR_P3[1][0] * l +\n LMS_TO_LINEAR_P3[1][1] * m +\n LMS_TO_LINEAR_P3[1][2] * s,\n b:\n LMS_TO_LINEAR_P3[2][0] * l +\n LMS_TO_LINEAR_P3[2][1] * m +\n LMS_TO_LINEAR_P3[2][2] * s,\n };\n}\n","import type { LinearSrgb, Srgb } from \"../types.js\";\nimport {\n SRGB_GAMMA_EXPONENT,\n SRGB_GAMMA_OFFSET,\n SRGB_GAMMA_SCALE,\n SRGB_GAMMA_SLOPE,\n SRGB_GAMMA_THRESHOLD,\n SRGB_GAMMA_THRESHOLD_LINEAR,\n} from \"../constants.js\";\n\n/** Decode a single sRGB gamma-encoded channel to linear light. */\nexport function srgbChannelToLinear(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD\n ? value / SRGB_GAMMA_SLOPE\n : ((value + SRGB_GAMMA_OFFSET) / SRGB_GAMMA_SCALE) ** SRGB_GAMMA_EXPONENT;\n}\n\n/** Encode a single linear light channel to sRGB gamma. */\nexport function linearChannelToSrgb(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD_LINEAR\n ? value * SRGB_GAMMA_SLOPE\n : SRGB_GAMMA_SCALE * value ** (1 / SRGB_GAMMA_EXPONENT) - SRGB_GAMMA_OFFSET;\n}\n\n/** Convert an sRGB color to Linear sRGB. */\nexport function srgbToLinearSrgb(color: Srgb): LinearSrgb {\n return {\n r: srgbChannelToLinear(color.r),\n g: srgbChannelToLinear(color.g),\n b: srgbChannelToLinear(color.b),\n };\n}\n\n/** Convert a Linear sRGB color to sRGB. */\nexport function linearSrgbToSrgb(color: LinearSrgb): Srgb {\n return {\n r: linearChannelToSrgb(color.r),\n g: linearChannelToSrgb(color.g),\n b: linearChannelToSrgb(color.b),\n };\n}\n","import type { Hex, Srgb } from \"../types.js\";\n\n/** Parse a hex color string (#RGB, #RRGGBB, or bare) to sRGB [0,1]. */\nexport function hexToSrgb(hex: string): Srgb {\n let h = hex.startsWith(\"#\") ? hex.slice(1) : hex;\n\n if (h.length === 3) {\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];\n }\n\n const n = parseInt(h, 16);\n return {\n r: ((n >> 16) & 0xff) / 255,\n g: ((n >> 8) & 0xff) / 255,\n b: (n & 0xff) / 255,\n };\n}\n\n/** Convert sRGB [0,1] to lowercase hex string (#rrggbb). Clamps to [0,1]. */\nexport function srgbToHex(color: Srgb): Hex {\n const r = Math.round(Math.max(0, Math.min(1, color.r)) * 255);\n const g = Math.round(Math.max(0, Math.min(1, color.g)) * 255);\n const b = Math.round(Math.max(0, Math.min(1, color.b)) * 255);\n return `#${((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1)}` as Hex;\n}\n","import type { Hex, Oklab, Oklch, Srgb } from \"../types.js\";\nimport { oklabToOklch, oklchToOklab } from \"./oklab.js\";\nimport { linearSrgbToOklab, oklabToLinearSrgb } from \"./linear-srgb.js\";\nimport { linearP3ToOklab, oklabToLinearP3 } from \"./linear-p3.js\";\nimport { linearSrgbToSrgb, srgbToLinearSrgb } from \"./srgb.js\";\nimport { hexToSrgb, srgbToHex } from \"./hex.js\";\n\n/** Convert sRGB to OKLCH. */\nexport function srgbToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearSrgbToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to sRGB. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToSrgb(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(oklchToOklab(color)));\n}\n\n/** Convert sRGB to OKLAB. */\nexport function srgbToOklab(color: Srgb): Oklab {\n return linearSrgbToOklab(srgbToLinearSrgb(color));\n}\n\n/** Convert OKLAB to sRGB. May produce out-of-gamut values. */\nexport function oklabToSrgb(color: Oklab): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(color));\n}\n\n/** Convert hex to OKLCH. */\nexport function hexToOklch(hex: string): Oklch {\n return srgbToOklch(hexToSrgb(hex));\n}\n\n/** Convert OKLCH to hex. Clamps to sRGB gamut before hex encoding. */\nexport function oklchToHex(color: Oklch): Hex {\n const srgb = oklchToSrgb(color);\n return srgbToHex({\n r: Math.max(0, Math.min(1, srgb.r)),\n g: Math.max(0, Math.min(1, srgb.g)),\n b: Math.max(0, Math.min(1, srgb.b)),\n });\n}\n\n/** Convert Display P3 to OKLCH. */\nexport function p3ToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearP3ToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to Display P3. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToP3(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearP3(oklchToOklab(color)));\n}\n","import type { Srgb } from \"../types.js\";\nimport { GAMUT_EPSILON } from \"../constants.js\";\n\n/** Check if sRGB channels are within [0, 1] (with epsilon tolerance). */\nexport function isInGamut(color: Srgb): boolean {\n return (\n color.r >= -GAMUT_EPSILON &&\n color.r <= 1 + GAMUT_EPSILON &&\n color.g >= -GAMUT_EPSILON &&\n color.g <= 1 + GAMUT_EPSILON &&\n color.b >= -GAMUT_EPSILON &&\n color.b <= 1 + GAMUT_EPSILON\n );\n}\n\n/** Clamp sRGB channels to [0, 1]. */\nexport function clampSrgb(color: Srgb): Srgb {\n return {\n r: Math.max(0, Math.min(1, color.r)),\n g: Math.max(0, Math.min(1, color.g)),\n b: Math.max(0, Math.min(1, color.b)),\n };\n}\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\n\n/** Compute deltaEOK (Euclidean distance in OKLAB) between two OKLCH colors. */\nexport function deltaEOK(a: Oklch, b: Oklch): number {\n return deltaEOKLab(oklchToOklab(a), oklchToOklab(b));\n}\n\n/** Compute deltaEOK directly from OKLAB values. */\nexport function deltaEOKLab(a: Oklab, b: Oklab): number {\n const dL = a.L - b.L;\n const da = a.a - b.a;\n const db = a.b - b.b;\n return Math.sqrt(dL * dL + da * da + db * db);\n}\n","import type { Gamut, Oklch, Srgb } from \"../types.js\";\nimport {\n GAMUT_EPSILON,\n GAMUT_MAP_EPSILON,\n GAMUT_MAP_JND,\n GAMUT_MAP_MAX_ITERATIONS,\n} from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut, clampSrgb } from \"./check.js\";\nimport { deltaEOKLab } from \"../color/difference.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\nimport { linearSrgbToOklab } from \"../conversions/linear-srgb.js\";\nimport { linearP3ToOklab } from \"../conversions/linear-p3.js\";\nimport { srgbToLinearSrgb } from \"../conversions/srgb.js\";\n\n/**\n * Map an OKLCH color into the target gamut using the CSS Color Level 4 algorithm.\n * Reduces chroma at fixed L and h via binary search with deltaEOK JND check.\n * @param gamut Target gamut (default: 'srgb').\n */\nexport function gamutMap(color: Oklch, gamut: Gamut = \"srgb\"): Oklch {\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n const rgbToOklab =\n gamut === \"display-p3\"\n ? (c: Srgb) => linearP3ToOklab(srgbToLinearSrgb(c))\n : (c: Srgb) => linearSrgbToOklab(srgbToLinearSrgb(c));\n\n // Already in gamut\n const rgb = toRgb(color);\n if (isInGamut(rgb)) return color;\n\n // Edge cases: black and white\n if (color.L <= GAMUT_EPSILON) return { L: 0, C: 0, h: color.h };\n if (color.L >= 1 - GAMUT_EPSILON) return { L: 1, C: 0, h: color.h };\n\n let lo = 0;\n let hi = color.C;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const midC = (lo + hi) / 2;\n const candidate: Oklch = { L: color.L, C: midC, h: color.h };\n const candidateRgb = toRgb(candidate);\n\n if (isInGamut(candidateRgb)) {\n lo = midC;\n } else {\n // Clip and check JND\n const clipped = clampSrgb(candidateRgb);\n const clippedLab = rgbToOklab(clipped);\n const candidateLab = oklchToOklab(candidate);\n const dE = deltaEOKLab(clippedLab, candidateLab);\n\n if (dE < GAMUT_MAP_JND) {\n // Clipped version is perceptually close enough — converge here.\n // Return lo (last confirmed in-gamut chroma) to guarantee gamut safety.\n break;\n }\n\n hi = midC;\n }\n\n if (hi - lo < GAMUT_MAP_EPSILON) break;\n }\n\n return { L: color.L, C: lo, h: color.h };\n}\n","import type { Gamut, Oklch } from \"../types.js\";\nimport { GAMUT_MAP_MAX_ITERATIONS } from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"./check.js\";\n\n/**\n * Find the maximum in-gamut chroma for a given OKLCH lightness and hue.\n *\n * Binary search over [0, upperBound], converging to 1e-6 precision.\n * Upper bounds are empirically safe ceilings — no in-gamut color at any\n * lightness or hue exceeds C = 0.4 in sRGB or C = 0.5 in Display P3.\n * Searching beyond these would waste iterations with no benefit.\n *\n * Returns 0 for L ≤ 0 or L ≥ 1 (pure black and white carry no chroma).\n */\nexport function maxChroma(L: number, h: number, gamut: Gamut = \"srgb\"): number {\n if (L <= 0 || L >= 1) return 0;\n\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n let lo = 0;\n let hi = gamut === \"display-p3\" ? 0.5 : 0.4;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const mid = (lo + hi) / 2;\n const color: Oklch = { L, C: mid, h };\n const rgb = toRgb(color);\n\n if (isInGamut(rgb)) {\n lo = mid;\n } else {\n hi = mid;\n }\n\n if (hi - lo < 1e-6) break;\n }\n\n return lo;\n}\n","import type { Srgb } from \"../types.js\";\nimport { WCAG_R, WCAG_G, WCAG_B } from \"../constants.js\";\nimport { srgbChannelToLinear } from \"../conversions/srgb.js\";\n\n/** Compute WCAG 2.x relative luminance [0, 1] from an sRGB color. */\nexport function wcagLuminance(color: Srgb): number {\n return (\n WCAG_R * srgbChannelToLinear(color.r) +\n WCAG_G * srgbChannelToLinear(color.g) +\n WCAG_B * srgbChannelToLinear(color.b)\n );\n}\n\n/**\n * Compute WCAG 2.x contrast ratio between two sRGB colors.\n * Returns a value in [1, 21]. Symmetric (order doesn't matter).\n */\nexport function wcagContrast(a: Srgb, b: Srgb): number {\n const lA = wcagLuminance(a);\n const lB = wcagLuminance(b);\n const lighter = Math.max(lA, lB);\n const darker = Math.min(lA, lB);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Choose black or white text for maximum WCAG contrast against a background.\n * @returns `\"#000000\"` or `\"#ffffff\"`.\n */\nexport function contrastTextHex(background: Srgb): \"#000000\" | \"#ffffff\" {\n const white: Srgb = { r: 1, g: 1, b: 1 };\n const black: Srgb = { r: 0, g: 0, b: 0 };\n return wcagContrast(white, background) > wcagContrast(black, background)\n ? \"#ffffff\"\n : \"#000000\";\n}\n","import type { Srgb } from \"../types.js\";\nimport {\n APCA_MAIN_TRC,\n APCA_SRGB_R,\n APCA_SRGB_G,\n APCA_SRGB_B,\n APCA_NORM_BG,\n APCA_NORM_TXT,\n APCA_REV_TXT,\n APCA_REV_BG,\n APCA_BLK_THRS,\n APCA_BLK_CLMP,\n APCA_SCALE_BOW,\n APCA_SCALE_WOB,\n APCA_LO_BOW_OFFSET,\n APCA_LO_WOB_OFFSET,\n APCA_DELTA_Y_MIN,\n APCA_LO_CLIP,\n} from \"../constants.js\";\n\n/**\n * Compute APCA-W3 Lc (Lightness Contrast) between text and background.\n *\n * Returns a signed value in roughly [-108, +106]:\n * Positive = dark text on light background (BoW)\n * Negative = light text on dark background (WoB)\n * 0 = no meaningful contrast\n *\n * IMPORTANT: Uses its own linearization (simple 2.4 gamma),\n * NOT the IEC piecewise sRGB transfer function.\n */\n/**\n * Practical maximum APCA Lc magnitude used for normalization.\n * BoW tops out at ~+106, WoB at ~-108; we use 108 as a symmetric ceiling.\n */\nexport const APCA_LC_MAX = 108;\n\n/**\n * Normalize a raw APCA Lc value to the range [-1, +1].\n * +1 = maximum dark-on-light contrast (BoW)\n * -1 = maximum light-on-dark contrast (WoB)\n * 0 = no meaningful contrast\n */\nexport function apcaToNormalized(lc: number): number {\n return Math.max(-1, Math.min(1, lc / APCA_LC_MAX));\n}\n\n/**\n * Convert a normalized contrast value [-1, +1] back to a raw APCA Lc value.\n */\nexport function normalizedToApca(normalized: number): number {\n return normalized * APCA_LC_MAX;\n}\n\nexport function apcaContrast(textColor: Srgb, bgColor: Srgb): number {\n // Step 1: Linearize with simple 2.4 gamma and compute Y\n let txtY =\n APCA_SRGB_R * textColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * textColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * textColor.b ** APCA_MAIN_TRC;\n\n let bgY =\n APCA_SRGB_R * bgColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * bgColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * bgColor.b ** APCA_MAIN_TRC;\n\n // Step 2: Soft black clamp\n if (txtY < APCA_BLK_THRS) {\n txtY += (APCA_BLK_THRS - txtY) ** APCA_BLK_CLMP;\n }\n if (bgY < APCA_BLK_THRS) {\n bgY += (APCA_BLK_THRS - bgY) ** APCA_BLK_CLMP;\n }\n\n // Step 3: Delta Y check\n if (Math.abs(bgY - txtY) < APCA_DELTA_Y_MIN) return 0;\n\n // Step 4: Polarity-aware contrast\n let sapc: number;\n\n if (bgY > txtY) {\n // Dark text on light background (BoW)\n sapc = (bgY ** APCA_NORM_BG - txtY ** APCA_NORM_TXT) * APCA_SCALE_BOW;\n return sapc < APCA_LO_CLIP ? 0 : (sapc - APCA_LO_BOW_OFFSET) * 100;\n } else {\n // Light text on dark background (WoB)\n sapc = (bgY ** APCA_REV_BG - txtY ** APCA_REV_TXT) * APCA_SCALE_WOB;\n return sapc > -APCA_LO_CLIP ? 0 : (sapc + APCA_LO_WOB_OFFSET) * 100;\n }\n}\n","import type { Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD } from \"../constants.js\";\n\n/**\n * Linearly interpolate between two OKLCH colors.\n *\n * L and C are linearly interpolated. Hue uses shortest-arc interpolation.\n * Achromatic colors (C near zero) inherit the other color's hue to avoid\n * meaningless hue sweeps through the achromatic pole.\n */\nexport function mix(a: Oklch, b: Oklch, t: number): Oklch {\n const L = a.L + (b.L - a.L) * t;\n const C = a.C + (b.C - a.C) * t;\n\n // Resolve hue — handle achromatic inputs\n const aIsAchromatic = a.C < ACHROMATIC_THRESHOLD;\n const bIsAchromatic = b.C < ACHROMATIC_THRESHOLD;\n\n if (aIsAchromatic && bIsAchromatic) {\n return { L, C, h: 0 };\n }\n\n const hA = aIsAchromatic ? b.h : a.h;\n const hB = bIsAchromatic ? a.h : b.h;\n\n // Shortest-arc hue interpolation\n let delta = hB - hA;\n if (delta > 180) delta -= 360;\n if (delta < -180) delta += 360;\n\n let h = hA + delta * t;\n if (h < 0) h += 360;\n if (h >= 360) h -= 360;\n\n return { L, C, h };\n}\n","/**\n * Design constants — the values you tune by hand.\n *\n * Edit this file to adjust the perceptual behavior of every scale and\n * grading operation across the library.\n */\n\n// ── Scale defaults ────────────────────────────────────────────────────────────\n\n/**\n * Default number of steps in a generated scale.\n * Fixed at 26 — enough for a full design token set with fine lightness\n * increments without redundancy.\n */\nexport const DEFAULT_SCALE_STEPS = 26;\n\n/**\n * Default hue when none is provided.\n * 0° is the start of the OKLCH hue wheel (red region). Arbitrary but\n * deterministic — callers should always supply an explicit hue.\n */\nexport const DEFAULT_HUE = 0;\n\n// ── Dynamic range ─────────────────────────────────────────────────────────────\n\n/**\n * Lightest step's lightness when the whites slider is at 0.\n * slider 0 → L = MIN_LIGHTEST_L, slider 1 → L = 1.0 (pure white).\n */\nexport const MIN_LIGHTEST_L = 0.96;\n\n/**\n * Darkest step's lightness when the darks slider is at 0.\n * slider 0 → L = MAX_DARKEST_L, slider 1 → L = 0.0 (pure black).\n */\nexport const MAX_DARKEST_L = 0.16;\n\n// ── Hue grading ───────────────────────────────────────────────────────────────\n\n/**\n * How far global grading reaches into the scale from each end (0–1).\n * Light grading fades to zero at t = GRADING_REACH.\n * Dark grading fades to zero at t = 1 − GRADING_REACH.\n */\nexport const GRADING_REACH = 3 / 5;\n\n/** Maximum amount for global grading. Inputs above this are clamped. */\nexport const MAX_GRADING_AMOUNT = 0.25;\n\n/**\n * How far per-palette hue shift reaches into the scale from each end (0–1).\n * Slightly wider than GRADING_REACH to give per-palette shifts more room.\n */\nexport const SHIFT_REACH = 2 / 3;\n\n/** Maximum amount for per-palette hue shift. Inputs above this are clamped. */\nexport const MAX_SHIFT_AMOUNT = 0.5;\n\n// ── Color difference ──────────────────────────────────────────────────────────\n\n/**\n * Just-noticeable difference threshold (deltaEOK).\n * Colors with distance below this are considered perceptually identical.\n * Used to classify color matches as exact vs. fallback.\n */\nexport const PERCEPTUAL_JND = 0.02;\n","/**\n * Global hue grading — shifts each palette's base hue toward shared\n * target hues at the light and dark scale endpoints.\n *\n * Light grading fades from full at the lightest step to zero at GRADING_REACH.\n * Dark grading fades from zero at (1 - GRADING_REACH) to full at the darkest step.\n * In the overlap zone, both shifts are additive (commutative).\n */\n\nimport {\n GRADING_REACH,\n MAX_GRADING_AMOUNT,\n SHIFT_REACH,\n MAX_SHIFT_AMOUNT,\n} from \"../config.js\";\n\nexport interface Grading {\n /** Hue grading for the light end of the scale. */\n readonly light?: { readonly hue: number; readonly amount: number };\n /** Hue grading for the dark end of the scale. */\n readonly dark?: { readonly hue: number; readonly amount: number };\n}\n\n/** Per-palette hue shift (one end only). */\nexport interface Shift {\n /** Target hue to shift toward (0–360°). */\n readonly hue: number;\n /** Blend strength (0–MAX_SHIFT_AMOUNT). */\n readonly amount: number;\n /** Which end to affect. `true` = light end, `false`/omitted = dark end (default). */\n readonly light?: boolean;\n}\n\n/**\n * Compute the graded hue at position `t` in the scale.\n *\n * Uses vector interpolation in Cartesian space rather than angular deltas\n * to avoid the shortest-arc discontinuity at 180° (where the direction\n * of rotation flips abruptly). Each grade's displacement is computed as\n * a vector offset from the base hue, and displacements are additive\n * (commutative — order doesn't matter).\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param grade Hue grade configuration.\n * @param reach How far each grade reaches into the scale (default: GRADING_REACH).\n * @param maxIntensity Maximum amount clamp (default: MAX_GRADING_AMOUNT).\n * @returns The graded hue in degrees (0–360).\n */\nexport function gradeHue(\n baseHue: number,\n t: number,\n grade: Grading,\n reach: number = GRADING_REACH,\n maxIntensity: number = MAX_GRADING_AMOUNT,\n): number {\n const li = Math.max(0, Math.min(maxIntensity, grade.light?.amount ?? 0));\n const di = Math.max(0, Math.min(maxIntensity, grade.dark?.amount ?? 0));\n\n // Early exit: no grading\n if (li === 0 && di === 0) return baseHue;\n\n // Light influence: cosine fade from 1 at t=0 to 0 at t=reach\n const lightInfluence =\n t <= reach ? 0.5 * (1 + Math.cos((Math.PI * t) / reach)) : 0;\n\n // Dark influence: cosine fade from 0 at t=(1-reach) to 1 at t=1\n const darkInfluence =\n t >= 1 - reach\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / reach))\n : 0;\n\n // Base hue as unit vector\n const toRad = Math.PI / 180;\n const baseRad = baseHue * toRad;\n const bx = Math.cos(baseRad);\n const by = Math.sin(baseRad);\n\n // Accumulate displacements in Cartesian space\n let dx = 0;\n let dy = 0;\n\n if (lightInfluence > 0 && li > 0) {\n const blend = lightInfluence * li;\n const lRad = (grade.light!.hue) * toRad;\n dx += blend * (Math.cos(lRad) - bx);\n dy += blend * (Math.sin(lRad) - by);\n }\n\n if (darkInfluence > 0 && di > 0) {\n const blend = darkInfluence * di;\n const dRad = (grade.dark!.hue) * toRad;\n dx += blend * (Math.cos(dRad) - bx);\n dy += blend * (Math.sin(dRad) - by);\n }\n\n // Reconstruct hue from displaced vector\n const rx = bx + dx;\n const ry = by + dy;\n\n // Safety: collapsed vector (opposite hues at exactly 50% blend)\n if (rx * rx + ry * ry < 1e-20) return baseHue;\n\n return ((Math.atan2(ry, rx) / toRad) + 360) % 360;\n}\n\n/**\n * Resolve the final hue at position `t`, applying local shift first, then global grading.\n *\n * This is the canonical composition: per-palette shift (using SHIFT_REACH /\n * MAX_SHIFT_AMOUNT) first, then global grading (using GRADING_REACH /\n * MAX_GRADING_AMOUNT) on top — so grading's influence is preserved at full\n * strength across all palettes, keeping them visually coherent.\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param globalGrade Global grading (shared across palettes), or undefined.\n * @param localGrade Local grading (per-palette, expanded from Shift), or undefined.\n * @returns The fully graded hue in degrees (0–360).\n */\nexport function resolveGradedHue(\n baseHue: number,\n t: number,\n globalGrade?: Grading,\n localGrade?: Grading,\n): number {\n let h = baseHue;\n if (localGrade) h = gradeHue(h, t, localGrade, SHIFT_REACH, MAX_SHIFT_AMOUNT);\n if (globalGrade) h = gradeHue(h, t, globalGrade);\n return h;\n}\n\n/**\n * Adapt a Shift into a one-sided Grading so it can be passed to gradeHue.\n *\n * The Shift interface is flat (hue, amount, light?) for ergonomic API use,\n * but gradeHue operates on the Grading shape (light/dark sub-objects).\n * This function bridges the two, activating only the requested end.\n *\n * @param hue Target hue for the active side (0–360°).\n * @param amount Blend strength for the active side.\n * @param light `true` = light end, `false`/omitted = dark end (default).\n */\nexport function buildOneSidedGrade(\n hue: number,\n amount: number,\n light: boolean = false,\n): Grading {\n return light\n ? { light: { hue, amount } }\n : { dark: { hue, amount } };\n}\n","/**\n * Dynamic range resolution — maps slider values (0–1) to OKLCH lightness\n * bounds for the lightest and darkest steps of a color scale.\n */\n\nimport { MIN_LIGHTEST_L, MAX_DARKEST_L } from \"../config.js\";\n\n/**\n * Resolve a whites slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MIN_LIGHTEST_L (0.96), slider 1 → L = 1.0 (pure white)\n */\nexport function resolveLightest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MIN_LIGHTEST_L + s * (1.0 - MIN_LIGHTEST_L);\n}\n\n/**\n * Resolve a darks slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MAX_DARKEST_L (0.16), slider 1 → L = 0.0 (pure black)\n */\nexport function resolveDarkest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MAX_DARKEST_L * (1 - s);\n}\n\n/**\n * Map an OKLCH lightness to a normalized scale position (0–1).\n * 0 = lightest end, 1 = darkest end.\n *\n * Inverse of the lightness interpolation inside generateScale.\n * Useful for deriving chromaPeak from a key color's lightness.\n */\nexport function lightnessToScaleT(L: number, lightestL: number, darkestL: number): number {\n const range = lightestL - darkestL;\n if (range <= 0) return 0.5;\n return Math.max(0, Math.min(1, (lightestL - L) / range));\n}\n","import type { Oklch } from \"../types.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\nimport type { Grading, Shift } from \"./hue-grade.js\";\nimport { resolveGradedHue, buildOneSidedGrade } from \"./hue-grade.js\";\nimport { resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport { DEFAULT_SCALE_STEPS, DEFAULT_HUE } from \"../config.js\";\n\nexport interface ScaleOptions {\n /**\n * Tonal range of the scale.\n * - `light`: how light the lightest step is (0–1). Default: 1.\n * 0 → L = MIN_LIGHTEST_L (0.96), 1 → L = 1.0 (pure white).\n * - `dark`: how dark the darkest step is (0–1). Default: 1.\n * 0 → L = MAX_DARKEST_L (0.16), 1 → L = 0.0 (pure black).\n */\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n /**\n * Hue angle in degrees (0–360). Default: DEFAULT_HUE (0).\n * Every step shares this base hue unless shifted by `grading` or `shift`.\n */\n readonly hue?: number;\n /**\n * Chroma shape of the scale.\n * - `amount`: how much of the available gamut to use (0–1). Default: 0.\n * 0 = fully achromatic (default), 1 = maximum in-gamut chroma at each lightness.\n * - `balance`: how chroma is distributed along the lightness range (0–1).\n * 0 = chroma concentrated toward the lightest end, 1 = toward the darkest end,\n * 0.5 = natural distribution (default, follows gamut boundary shape).\n */\n readonly chroma?: { readonly amount?: number; readonly balance?: number };\n /**\n * Global hue grading. When provided, the hue at each step is shifted\n * toward target hues based on position in the scale.\n * Light grading affects the lightest 3/5, dark grading affects the\n * darkest 3/5, with additive overlap in the middle fifth.\n */\n readonly grading?: Grading;\n /**\n * Per-palette hue shift. A one-sided grade applied before global\n * grading, with its own reach and strength limits (SHIFT_REACH,\n * MAX_SHIFT_AMOUNT). Defaults to the dark end; set `light: true` to target\n * the light end instead.\n */\n readonly shift?: Shift;\n /** Use Display P3 gamut instead of sRGB (default: false). */\n readonly isP3?: boolean;\n}\n\n/**\n * Generate an OKLCH color scale from lightest to darkest.\n *\n * Always produces DEFAULT_SCALE_STEPS colors. Chroma at each step is\n * proportional to the gamut boundary at that lightness, scaled by\n * `chroma.amount`. This guarantees every color is in-gamut — no fallbacks\n * needed — while producing a smooth, natural chroma curve.\n *\n * Use `contrast` to constrain the tonal range\n * (e.g. for scales that don't extend to pure white or pure black).\n *\n * Use `chroma.balance` to shift how chroma is distributed within the boundary.\n * The curve endpoints stay fixed while the distribution shifts smoothly.\n * The effective shift range is proportional to the headroom left by chroma.amount.\n */\nexport function generateScale(options: ScaleOptions = {}): Oklch[] {\n const {\n contrast,\n hue = DEFAULT_HUE,\n chroma,\n isP3 = false,\n grading,\n shift,\n } = options;\n const gamut = isP3 ? \"display-p3\" : \"srgb\";\n\n const steps = DEFAULT_SCALE_STEPS;\n const chromaRatio = chroma?.amount ?? 0;\n const chromaPeak = chroma?.balance ?? 0.5;\n const hueGrade = grading;\n const localHueGrade = shift ? buildOneSidedGrade(shift.hue, shift.amount, shift.light) : undefined;\n\n const ratio = Math.max(0, Math.min(1, chromaRatio));\n const peak = Math.max(0, Math.min(1, chromaPeak));\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n\n // Helper: resolve hue at position t (applies local shift first, then global grading)\n const hueAt = (t: number) => resolveGradedHue(hue, t, hueGrade, localHueGrade);\n\n // Fast path: skip peak skew logic when balance has no effect.\n // - peak === 0.5: already at the natural gamut peak, nothing to shift\n // - ratio === 0: no chroma at all, boundary shape is irrelevant\n // - ratio >= 1: inner triangle equals the boundary triangle, no headroom to slide\n if (peak === 0.5 || ratio === 0 || ratio >= 1) {\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n const h = hueAt(t);\n // Chroma is shaped by the base hue's boundary to keep the curve smooth.\n // The shifted hue's boundary is used as a final in-gamut clamp only —\n // this prevents spikes when the shifted hue has more available chroma\n // than the base (e.g. blue → pink passing through the purple region).\n const C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));\n scale.push({ L, C, h });\n }\n return scale;\n }\n\n // ── Peak skew logic ──\n // Warp the parameter t so the boundary peak appears at a shifted position.\n // Endpoints stay fixed (warp(0)=0, warp(1)=1), only the peak moves.\n\n // 1. Sample boundary to find natural peak and valid shift range\n const N = 100;\n let peakT = 0.5;\n let peakBoundaryC = 0;\n const boundarySamples: { t: number; C: number }[] = [];\n\n for (let i = 0; i <= N; i++) {\n const t = i / N;\n const L = lightestL - t * (lightestL - darkestL);\n // Sample the base hue's boundary — the same reference used when building\n // the warp below. Using the shifted hue here would skew peakT and the\n // valid range toward a hue-specific boundary shape, inconsistent with\n // how chroma is actually computed in step 4.\n const C = maxChroma(L, hue, gamut);\n boundarySamples.push({ t, C });\n if (C > peakBoundaryC) {\n peakBoundaryC = C;\n peakT = t;\n }\n }\n\n // 2. Find valid range: where boundary can accommodate the inner peak height\n const innerPeakC = peakBoundaryC * ratio;\n let validMinT = peakT;\n let validMaxT = peakT;\n\n for (const { t, C } of boundarySamples) {\n if (C >= innerPeakC - 1e-6) {\n if (t < validMinT) validMinT = t;\n if (t > validMaxT) validMaxT = t;\n }\n }\n\n // 3. Map chroma.balance (0–1) to valid range, normalized so 0.5 → peakT\n let targetT: number;\n if (peak <= 0.5) {\n targetT = validMinT + (peak / 0.5) * (peakT - validMinT);\n } else {\n targetT = peakT + ((peak - 0.5) / 0.5) * (validMaxT - peakT);\n }\n\n // Safety: if the piecewise mapping produces a degenerate targetT (outside\n // (0, 1)), fall back to the natural peak. This can occur at floating-point\n // boundaries rather than from any single expected input combination.\n if (targetT <= 0 || targetT >= 1) {\n targetT = peakT;\n }\n\n // 4. Build scale with piecewise-linear warp: targetT → peakT\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n const h = hueAt(t);\n\n // Piecewise-linear warp: maps 0→0, targetT→peakT, 1→1.\n // Two segments scale t independently so the boundary peak (at peakT in\n // warp space) lands at targetT in the output — endpoints stay fixed.\n let tWarped: number;\n if (t <= targetT) {\n tWarped = t * (peakT / targetT);\n } else {\n tWarped = peakT + (t - targetT) * ((1 - peakT) / (1 - targetT));\n }\n\n const Lwarped = lightestL - tWarped * (lightestL - darkestL);\n // Use the base hue for the warped chroma lookup — consistent with step 1\n // and the fast path. The warp is purely a lightness operation; mixing in\n // the shifted hue at tWarped would introduce cross-position hue artifacts.\n const warpedC = maxChroma(Lwarped, hue, gamut) * ratio;\n // Clamp to the shifted hue's actual boundary at this L: the in-gamut\n // guarantee for the final color { L, C, h }.\n const boundaryC = maxChroma(L, h, gamut);\n const C = Math.min(warpedC, boundaryC);\n\n scale.push({ L, C, h });\n }\n\n return scale;\n}\n","import type { Hex, Oklch, Gamut } from \"../types.js\";\nimport {\n hexToOklch,\n oklchToSrgb,\n oklchToP3,\n oklchToHex,\n} from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"../gamut/check.js\";\nimport { gamutMap } from \"../gamut/map.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\n\n/**\n * Result of resolving a color into scale-ready parameters.\n */\nexport interface ResolvedColor {\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Hex representation (sRGB-clamped if the resolved color exceeds sRGB). */\n readonly hex: Hex;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n /** Chroma lost during gamut mapping (0 if in-gamut). */\n readonly chromaShift: number;\n /** Hue from the resolved color. */\n readonly hue: number;\n /** Chroma as a fraction of the gamut boundary at this L/h (0–1). */\n readonly chromaRatio: number;\n}\n\n/**\n * Resolve a color (hex or OKLCH) into scale-ready parameters.\n *\n * If the color is outside the target gamut, it is perceptually mapped to the\n * nearest in-gamut color (chroma reduction at fixed L and h). The result\n * includes the derived hue and chromaRatio.\n *\n * Hex input is always valid sRGB, so `wasRemapped` will be false for hex\n * with gamut=\"srgb\". OKLCH input may be out of gamut and will be mapped.\n *\n * @param input A hex string (#RGB, #RRGGBB) or an OKLCH color.\n * @param isP3 Use Display P3 gamut instead of sRGB (default: false).\n */\nexport function resolveColor(\n input: Hex | Oklch,\n isP3: boolean = false,\n): ResolvedColor {\n const gamut: Gamut = isP3 ? \"display-p3\" : \"srgb\";\n const isHex = typeof input === \"string\";\n const original: Oklch = isHex ? hexToOklch(input) : input;\n\n // Hex encodes valid sRGB by definition, and sRGB ⊂ P3, so hex input\n // is always in-gamut for both supported gamuts. Skipping the round-trip\n // check avoids false negatives from floating-point drift.\n let inGamut: boolean;\n if (isHex) {\n inGamut = true;\n } else {\n const rgb =\n gamut === \"display-p3\" ? oklchToP3(original) : oklchToSrgb(original);\n inGamut = isInGamut(rgb);\n }\n\n const oklch = inGamut ? original : gamutMap(original, gamut);\n\n const boundary = maxChroma(oklch.L, oklch.h, gamut);\n const chromaRatio = boundary > 0 ? oklch.C / boundary : 0;\n\n return {\n oklch,\n hex: oklchToHex(oklch),\n wasRemapped: !inGamut,\n original,\n chromaShift: original.C - oklch.C,\n hue: oklch.h,\n chromaRatio: Math.min(1, chromaRatio),\n };\n}\n","import type { Hex, Oklch } from \"../types.js\";\nimport { resolveColor } from \"./resolve-color.js\";\nimport { lightnessToScaleT, resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport { DEFAULT_SCALE_STEPS } from \"../config.js\";\n\n/**\n * The result of deriving scale parameters from a key color.\n *\n * Spread `hue` and `chroma` directly into ScaleOptions, then use\n * `stepIndex` to locate the key color's position in the generated scale.\n */\nexport interface KeyColorResult {\n /** Derived hue angle — use directly as ScaleOptions.hue. */\n readonly hue: number;\n /**\n * Derived chroma shape — use directly as ScaleOptions.chroma.\n * - `amount`: how saturated the scale is (0–1, relative to gamut boundary).\n * - `balance`: where in the scale the key color's lightness falls (0 = lightest, 1 = darkest).\n */\n readonly chroma: { readonly amount: number; readonly balance: number };\n /** The step index in a scale of `steps` length where this color lands. */\n readonly stepIndex: number;\n /** Hex representation of the resolved color (sRGB-clamped if necessary). */\n readonly hex: Hex;\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n}\n\n/**\n * Derive scale parameters from a known color.\n *\n * Given a hex or OKLCH color, returns the `hue` and `chroma` values\n * ready to spread into ScaleOptions. The chroma balance is derived from\n * where the color's lightness falls within the scale's lightness range,\n * so the chroma distribution is centered around the key color's position.\n *\n * @param color A hex string (#RGB or #RRGGBB) or an OKLCH color object.\n * @param options Scale context — must match the ScaleOptions you will use.\n * `contrast` values are slider values (0–1), same as ScaleOptions.contrast.\n * `steps` is the number of steps in the scale (default: 26).\n *\n * @example\n * const key = keyColor('#3B82F6');\n * const scale = generateScale({ hue: key.hue, chroma: key.chroma });\n * const matchedHex = oklchToHex(scale[key.stepIndex]);\n */\nexport function keyColor(\n color: Hex | Oklch,\n options?: {\n readonly isP3?: boolean;\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n readonly steps?: number;\n },\n): KeyColorResult {\n const { isP3 = false, contrast, steps = DEFAULT_SCALE_STEPS } = options ?? {};\n const resolved = resolveColor(color, isP3);\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n const balance = lightnessToScaleT(resolved.oklch.L, lightestL, darkestL);\n const stepIndex = Math.round(balance * Math.max(0, steps - 1));\n\n return {\n hue: resolved.hue,\n chroma: { amount: resolved.chromaRatio, balance },\n stepIndex,\n hex: resolved.hex,\n oklch: resolved.oklch,\n wasRemapped: resolved.wasRemapped,\n original: resolved.original,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/conversions/oklab.ts","../src/conversions/linear-srgb.ts","../src/conversions/linear-p3.ts","../src/conversions/srgb.ts","../src/conversions/hex.ts","../src/conversions/pipeline.ts","../src/gamut/check.ts","../src/color/difference.ts","../src/gamut/map.ts","../src/gamut/max-chroma.ts","../src/contrast/wcag.ts","../src/contrast/apca.ts","../src/color/interpolation.ts","../src/config.ts","../src/scale/hue-grade.ts","../src/scale/dynamic-range.ts","../src/scale/generate.ts","../src/scale/resolve-color.ts","../src/scale/key-color.ts"],"names":["toRad","scale"],"mappings":";;;AAEO,IAAM,oBAAA,GAAuB,OAAA;AAC7B,IAAM,2BAAA,GAA8B,QAAA;AACpC,IAAM,gBAAA,GAAmB,KAAA;AACzB,IAAM,mBAAA,GAAsB,GAAA;AAC5B,IAAM,iBAAA,GAAoB,KAAA;AAC1B,IAAM,gBAAA,GAAmB,KAAA;AAIzB,IAAM,kBAAA,GAAqB;AAAA,EAChC,CAAC,YAAA,EAAc,YAAA,EAAc,YAAY,CAAA;AAAA,EACzC,CAAC,YAAA,EAAc,YAAA,EAAc,YAAY,CAAA;AAAA,EACzC,CAAC,YAAA,EAAc,YAAA,EAAc,YAAY;AAC3C,CAAA;AAIO,IAAM,kBAAA,GAAqB;AAAA,EAChC,CAAC,YAAA,EAAe,WAAA,EAAe,aAAa,CAAA;AAAA,EAC5C,CAAC,YAAA,EAAe,YAAA,EAAe,YAAa,CAAA;AAAA,EAC5C,CAAC,YAAA,EAAe,YAAA,EAAe,YAAa;AAC9C,CAAA;AAIO,IAAM,kBAAA,GAAqB;AAAA,EAChC,CAAC,CAAA,EAAc,YAAA,EAAe,YAAa,CAAA;AAAA,EAC3C,CAAC,CAAA,EAAc,aAAA,EAAe,aAAa,CAAA;AAAA,EAC3C,CAAC,CAAA,EAAc,aAAA,EAAe,YAAa;AAC7C,CAAA;AAIO,IAAM,kBAAA,GAAqB;AAAA,EAChC,CAAC,YAAA,EAAe,aAAA,EAAe,YAAa,CAAA;AAAA,EAC5C,CAAC,aAAA,EAAe,YAAA,EAAe,aAAa,CAAA;AAAA,EAC5C,CAAC,aAAA,EAAe,aAAA,EAAe,WAAa;AAC9C,CAAA;AAKO,IAAM,gBAAA,GAAmB;AAAA,EAC9B,CAAC,YAAA,EAAe,YAAA,EAAe,YAAa,CAAA;AAAA,EAC5C,CAAC,YAAA,EAAe,YAAA,EAAe,YAAa,CAAA;AAAA,EAC5C,CAAC,YAAA,EAAe,YAAA,EAAe,YAAa;AAC9C,CAAA;AAIO,IAAM,gBAAA,GAAmB;AAAA,EAC9B,CAAC,WAAA,EAAe,aAAA,EAAe,YAAa,CAAA;AAAA,EAC5C,CAAC,aAAA,EAAe,YAAA,EAAe,aAAa,CAAA;AAAA,EAC5C,CAAC,aAAA,EAAe,aAAA,EAAe,YAAa;AAC9C,CAAA;AAIO,IAAM,aAAA,GAAgB,IAAA;AACtB,IAAM,aAAA,GAAgB,IAAA;AACtB,IAAM,iBAAA,GAAoB,IAAA;AAC1B,IAAM,wBAAA,GAA2B,EAAA;AAIjC,IAAM,oBAAA,GAAuB,KAAA;AAI7B,IAAM,MAAA,GAAS,MAAA;AACf,IAAM,MAAA,GAAS,MAAA;AACf,IAAM,MAAA,GAAS,MAAA;AAIf,IAAM,aAAA,GAAgB,GAAA;AACtB,IAAM,WAAA,GAAc,SAAA;AACpB,IAAM,WAAA,GAAc,SAAA;AACpB,IAAM,WAAA,GAAc,QAAA;AACpB,IAAM,YAAA,GAAe,IAAA;AACrB,IAAM,aAAA,GAAgB,IAAA;AACtB,IAAM,YAAA,GAAe,IAAA;AACrB,IAAM,WAAA,GAAc,IAAA;AACpB,IAAM,aAAA,GAAgB,KAAA;AACtB,IAAM,aAAA,GAAgB,KAAA;AACtB,IAAM,cAAA,GAAiB,IAAA;AACvB,IAAM,cAAA,GAAiB,IAAA;AACvB,IAAM,kBAAA,GAAqB,KAAA;AAC3B,IAAM,kBAAA,GAAqB,KAAA;AAC3B,IAAM,gBAAA,GAAmB,IAAA;AACzB,IAAM,YAAA,GAAe,GAAA;AAIrB,IAAM,UAAA,GAAa,KAAK,EAAA,GAAK,GAAA;AAC7B,IAAM,UAAA,GAAa,MAAM,IAAA,CAAK,EAAA;;;AC7F9B,SAAS,aAAa,GAAA,EAAmB;AAC9C,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,IAAI,CAAA,GAAI,GAAA,CAAI,CAAA,GAAI,GAAA,CAAI,CAAC,CAAA;AAEjD,EAAA,IAAI,IAAI,oBAAA,EAAsB;AAC5B,IAAA,OAAO,EAAE,CAAA,EAAG,GAAA,CAAI,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AAAA,EAChC;AAEA,EAAA,IAAI,IAAI,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG,GAAA,CAAI,CAAC,CAAA,GAAI,UAAA;AACnC,EAAA,IAAI,CAAA,GAAI,GAAG,CAAA,IAAK,GAAA;AAEhB,EAAA,OAAO,EAAE,CAAA,EAAG,GAAA,CAAI,CAAA,EAAG,GAAG,CAAA,EAAE;AAC1B;AAGO,SAAS,aAAa,GAAA,EAAmB;AAC9C,EAAA,MAAM,IAAA,GAAO,IAAI,CAAA,GAAI,UAAA;AACrB,EAAA,OAAO;AAAA,IACL,GAAG,GAAA,CAAI,CAAA;AAAA,IACP,CAAA,EAAG,GAAA,CAAI,CAAA,GAAI,IAAA,CAAK,IAAI,IAAI,CAAA;AAAA,IACxB,CAAA,EAAG,GAAA,CAAI,CAAA,GAAI,IAAA,CAAK,IAAI,IAAI;AAAA,GAC1B;AACF;;;AChBO,SAAS,kBAAkB,KAAA,EAA0B;AAE1D,EAAA,MAAM,CAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACnC,EAAA,MAAM,CAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACnC,EAAA,MAAM,CAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AAGnC,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACtB,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACtB,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AAGtB,EAAA,OAAO;AAAA,IACL,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,EAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA;AAAA,IAC7B,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,EAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA;AAAA,IAC7B,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,EAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI;AAAA,GAC/B;AACF;AAGO,SAAS,kBAAkB,KAAA,EAA0B;AAE1D,EAAA,MAAM,EAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACnC,EAAA,MAAM,EAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACnC,EAAA,MAAM,EAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AAGnC,EAAA,MAAM,CAAA,GAAI,KAAK,EAAA,GAAK,EAAA;AACpB,EAAA,MAAM,CAAA,GAAI,KAAK,EAAA,GAAK,EAAA;AACpB,EAAA,MAAM,CAAA,GAAI,KAAK,EAAA,GAAK,EAAA;AAGpB,EAAA,OAAO;AAAA,IACL,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,CAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA;AAAA,IAC7B,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,CAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA;AAAA,IAC7B,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,CAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI;AAAA,GAC/B;AACF;;;ACzEO,SAAS,gBAAgB,KAAA,EAA0B;AAExD,EAAA,MAAM,CAAA,GACJ,iBAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IAC/B,gBAAA,CAAiB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GAC/B,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACjC,EAAA,MAAM,CAAA,GACJ,iBAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IAC/B,gBAAA,CAAiB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GAC/B,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACjC,EAAA,MAAM,CAAA,GACJ,iBAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IAC/B,gBAAA,CAAiB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GAC/B,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AAGjC,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACtB,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AACtB,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AAGtB,EAAA,OAAO;AAAA,IACL,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,EAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA;AAAA,IAC7B,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,EAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA;AAAA,IAC7B,GACE,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,EAAA,GAC3B,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,EAAA,GAC3B,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI;AAAA,GAC/B;AACF;AAGO,SAAS,gBAAgB,KAAA,EAA0B;AAExD,EAAA,MAAM,EAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACnC,EAAA,MAAM,EAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AACnC,EAAA,MAAM,EAAA,GACJ,mBAAmB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,KAAA,CAAM,IACjC,kBAAA,CAAmB,CAAC,EAAE,CAAC,CAAA,GAAI,MAAM,CAAA,GACjC,kBAAA,CAAmB,CAAC,CAAA,CAAE,CAAC,IAAI,KAAA,CAAM,CAAA;AAGnC,EAAA,MAAM,CAAA,GAAI,KAAK,EAAA,GAAK,EAAA;AACpB,EAAA,MAAM,CAAA,GAAI,KAAK,EAAA,GAAK,EAAA;AACpB,EAAA,MAAM,CAAA,GAAI,KAAK,EAAA,GAAK,EAAA;AAGpB,EAAA,OAAO;AAAA,IACL,GACE,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,IAAI,CAAA,GACzB,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,GACzB,iBAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA;AAAA,IAC3B,GACE,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,IAAI,CAAA,GACzB,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,GACzB,iBAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA;AAAA,IAC3B,GACE,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,IAAI,CAAA,GACzB,gBAAA,CAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,GACzB,iBAAiB,CAAC,CAAA,CAAE,CAAC,CAAA,GAAI;AAAA,GAC7B;AACF;;;ACvEO,SAAS,oBAAoB,KAAA,EAAuB;AACzD,EAAA,OAAO,SAAS,oBAAA,GACZ,KAAA,GAAQ,gBAAA,GAAA,CAAA,CACN,KAAA,GAAQ,qBAAqB,gBAAA,KAAqB,mBAAA;AAC1D;AAGO,SAAS,oBAAoB,KAAA,EAAuB;AACzD,EAAA,OAAO,SAAS,2BAAA,GACZ,KAAA,GAAQ,mBACR,gBAAA,GAAmB,KAAA,KAAU,IAAI,mBAAA,CAAA,GAAuB,iBAAA;AAC9D;AAGO,SAAS,iBAAiB,KAAA,EAAyB;AACxD,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,mBAAA,CAAoB,KAAA,CAAM,CAAC,CAAA;AAAA,IAC9B,CAAA,EAAG,mBAAA,CAAoB,KAAA,CAAM,CAAC,CAAA;AAAA,IAC9B,CAAA,EAAG,mBAAA,CAAoB,KAAA,CAAM,CAAC;AAAA,GAChC;AACF;AAGO,SAAS,iBAAiB,KAAA,EAAyB;AACxD,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,mBAAA,CAAoB,KAAA,CAAM,CAAC,CAAA;AAAA,IAC9B,CAAA,EAAG,mBAAA,CAAoB,KAAA,CAAM,CAAC,CAAA;AAAA,IAC9B,CAAA,EAAG,mBAAA,CAAoB,KAAA,CAAM,CAAC;AAAA,GAChC;AACF;;;ACrCO,SAAS,UAAU,GAAA,EAAmB;AAC3C,EAAA,IAAI,CAAA,GAAI,IAAI,UAAA,CAAW,GAAG,IAAI,GAAA,CAAI,KAAA,CAAM,CAAC,CAAA,GAAI,GAAA;AAE7C,EAAA,IAAI,CAAA,CAAE,WAAW,CAAA,EAAG;AAClB,IAAA,CAAA,GAAI,EAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,IAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAC,CAAA,GAAI,EAAE,CAAC,CAAA;AAAA,EAC5C;AAEA,EAAA,MAAM,CAAA,GAAI,QAAA,CAAS,CAAA,EAAG,EAAE,CAAA;AACxB,EAAA,OAAO;AAAA,IACL,CAAA,EAAA,CAAK,CAAA,IAAK,EAAA,GAAM,GAAA,IAAQ,GAAA;AAAA,IACxB,CAAA,EAAA,CAAK,CAAA,IAAK,CAAA,GAAK,GAAA,IAAQ,GAAA;AAAA,IACvB,CAAA,EAAA,CAAI,IAAI,GAAA,IAAQ;AAAA,GAClB;AACF;AAGO,SAAS,UAAU,KAAA,EAAkB;AAC1C,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,IAAI,GAAG,CAAA;AAC5D,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,IAAI,GAAG,CAAA;AAC5D,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,IAAI,GAAG,CAAA;AAC5D,EAAA,OAAO,CAAA,CAAA,EAAA,CAAM,CAAA,IAAK,EAAA,GAAO,CAAA,IAAK,EAAA,GAAO,CAAA,IAAK,CAAA,GAAK,CAAA,EAAG,QAAA,CAAS,EAAE,CAAA,CAAE,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACzE;;;AChBO,SAAS,YAAY,KAAA,EAAoB;AAC9C,EAAA,OAAO,YAAA,CAAa,iBAAA,CAAkB,gBAAA,CAAiB,KAAK,CAAC,CAAC,CAAA;AAChE;AAGO,SAAS,YAAY,KAAA,EAAoB;AAC9C,EAAA,OAAO,gBAAA,CAAiB,iBAAA,CAAkB,YAAA,CAAa,KAAK,CAAC,CAAC,CAAA;AAChE;AAGO,SAAS,YAAY,KAAA,EAAoB;AAC9C,EAAA,OAAO,iBAAA,CAAkB,gBAAA,CAAiB,KAAK,CAAC,CAAA;AAClD;AAGO,SAAS,YAAY,KAAA,EAAoB;AAC9C,EAAA,OAAO,gBAAA,CAAiB,iBAAA,CAAkB,KAAK,CAAC,CAAA;AAClD;AAGO,SAAS,WAAW,GAAA,EAAoB;AAC7C,EAAA,OAAO,WAAA,CAAY,SAAA,CAAU,GAAG,CAAC,CAAA;AACnC;AAGO,SAAS,WAAW,KAAA,EAAmB;AAC5C,EAAA,MAAM,IAAA,GAAO,YAAY,KAAK,CAAA;AAC9B,EAAA,OAAO,SAAA,CAAU;AAAA,IACf,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AAAA,IAClC,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC,CAAA;AAAA,IAClC,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,CAAC,CAAC;AAAA,GACnC,CAAA;AACH;AAGO,SAAS,UAAU,KAAA,EAAoB;AAC5C,EAAA,OAAO,YAAA,CAAa,eAAA,CAAgB,gBAAA,CAAiB,KAAK,CAAC,CAAC,CAAA;AAC9D;AAGO,SAAS,UAAU,KAAA,EAAoB;AAC5C,EAAA,OAAO,gBAAA,CAAiB,eAAA,CAAgB,YAAA,CAAa,KAAK,CAAC,CAAC,CAAA;AAC9D;AAGO,SAAS,aAAa,KAAA,EAAsB;AACjD,EAAA,MAAM,EAAA,GAAK,UAAU,KAAK,CAAA;AAC1B,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAA,CAAG,CAAC,CAAC,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAClD,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAA,CAAG,CAAC,CAAC,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAClD,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,EAAA,CAAG,CAAC,CAAC,CAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAClD,EAAA,OAAO,CAAA,iBAAA,EAAoB,CAAC,CAAA,CAAA,EAAI,CAAC,IAAI,CAAC,CAAA,CAAA,CAAA;AACxC;;;ACvDO,SAAS,UAAU,KAAA,EAAsB;AAC9C,EAAA,OACE,KAAA,CAAM,KAAK,CAAC,aAAA,IACZ,MAAM,CAAA,IAAK,CAAA,GAAI,aAAA,IACf,KAAA,CAAM,CAAA,IAAK,CAAC,iBACZ,KAAA,CAAM,CAAA,IAAK,IAAI,aAAA,IACf,KAAA,CAAM,KAAK,CAAC,aAAA,IACZ,KAAA,CAAM,CAAA,IAAK,CAAA,GAAI,aAAA;AAEnB;AAGO,SAAS,UAAU,KAAA,EAAmB;AAC3C,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,IACnC,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,IACnC,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,KAAA,CAAM,CAAC,CAAC;AAAA,GACrC;AACF;AAGO,IAAM,OAAA,GAAU;;;ACrBhB,SAAS,QAAA,CAAS,GAAU,CAAA,EAAkB;AACnD,EAAA,OAAO,YAAY,YAAA,CAAa,CAAC,CAAA,EAAG,YAAA,CAAa,CAAC,CAAC,CAAA;AACrD;AAGO,SAAS,WAAA,CAAY,GAAU,CAAA,EAAkB;AACtD,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA;AACnB,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA;AACnB,EAAA,MAAM,EAAA,GAAK,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA;AACnB,EAAA,OAAO,KAAK,IAAA,CAAK,EAAA,GAAK,KAAK,EAAA,GAAK,EAAA,GAAK,KAAK,EAAE,CAAA;AAC9C;;;ACMO,SAAS,QAAA,CAAS,KAAA,EAAc,KAAA,GAAe,MAAA,EAAe;AACnE,EAAA,MAAM,KAAA,GAAQ,KAAA,KAAU,YAAA,GAAe,SAAA,GAAY,WAAA;AACnD,EAAA,MAAM,UAAA,GACJ,KAAA,KAAU,YAAA,GACN,CAAC,MAAY,eAAA,CAAgB,gBAAA,CAAiB,CAAC,CAAC,IAChD,CAAC,CAAA,KAAY,iBAAA,CAAkB,gBAAA,CAAiB,CAAC,CAAC,CAAA;AAGxD,EAAA,MAAM,GAAA,GAAM,MAAM,KAAK,CAAA;AACvB,EAAA,IAAI,SAAA,CAAU,GAAG,CAAA,EAAG,OAAO,KAAA;AAG3B,EAAA,IAAI,KAAA,CAAM,CAAA,IAAK,aAAA,EAAe,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,KAAA,CAAM,CAAA,EAAE;AAC9D,EAAA,IAAI,KAAA,CAAM,CAAA,IAAK,CAAA,GAAI,aAAA,EAAe,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,KAAA,CAAM,CAAA,EAAE;AAElE,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,KAAK,KAAA,CAAM,CAAA;AAEf,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,wBAAA,EAA0B,CAAA,EAAA,EAAK;AACjD,IAAA,MAAM,IAAA,GAAA,CAAQ,KAAK,EAAA,IAAM,CAAA;AACzB,IAAA,MAAM,SAAA,GAAmB,EAAE,CAAA,EAAG,KAAA,CAAM,GAAG,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,KAAA,CAAM,CAAA,EAAE;AAC3D,IAAA,MAAM,YAAA,GAAe,MAAM,SAAS,CAAA;AAEpC,IAAA,IAAI,SAAA,CAAU,YAAY,CAAA,EAAG;AAC3B,MAAA,EAAA,GAAK,IAAA;AAAA,IACP,CAAA,MAAO;AAEL,MAAA,MAAM,OAAA,GAAU,UAAU,YAAY,CAAA;AACtC,MAAA,MAAM,UAAA,GAAa,WAAW,OAAO,CAAA;AACrC,MAAA,MAAM,YAAA,GAAe,aAAa,SAAS,CAAA;AAC3C,MAAA,MAAM,EAAA,GAAK,WAAA,CAAY,UAAA,EAAY,YAAY,CAAA;AAE/C,MAAA,IAAI,KAAK,aAAA,EAAe;AAGtB,QAAA;AAAA,MACF;AAEA,MAAA,EAAA,GAAK,IAAA;AAAA,IACP;AAEA,IAAA,IAAI,EAAA,GAAK,KAAK,iBAAA,EAAmB;AAAA,EACnC;AAEA,EAAA,OAAO,EAAE,GAAG,KAAA,CAAM,CAAA,EAAG,GAAG,EAAA,EAAI,CAAA,EAAG,MAAM,CAAA,EAAE;AACzC;;;AClDO,SAAS,SAAA,CAAU,CAAA,EAAW,CAAA,EAAW,KAAA,GAAe,MAAA,EAAgB;AAC7E,EAAA,IAAI,CAAA,IAAK,CAAA,IAAK,CAAA,IAAK,CAAA,EAAG,OAAO,CAAA;AAE7B,EAAA,MAAM,KAAA,GAAQ,KAAA,KAAU,YAAA,GAAe,SAAA,GAAY,WAAA;AACnD,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,EAAA,GAAK,KAAA,KAAU,YAAA,GAAe,GAAA,GAAM,GAAA;AAExC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,wBAAA,EAA0B,CAAA,EAAA,EAAK;AACjD,IAAA,MAAM,GAAA,GAAA,CAAO,KAAK,EAAA,IAAM,CAAA;AACxB,IAAA,MAAM,KAAA,GAAe,EAAE,CAAA,EAAG,CAAA,EAAG,KAAK,CAAA,EAAE;AACpC,IAAA,MAAM,GAAA,GAAM,MAAM,KAAK,CAAA;AAEvB,IAAA,IAAI,SAAA,CAAU,GAAG,CAAA,EAAG;AAClB,MAAA,EAAA,GAAK,GAAA;AAAA,IACP,CAAA,MAAO;AACL,MAAA,EAAA,GAAK,GAAA;AAAA,IACP;AAEA,IAAA,IAAI,EAAA,GAAK,KAAK,IAAA,EAAM;AAAA,EACtB;AAEA,EAAA,OAAO,EAAA;AACT;;;AChCO,SAAS,cAAc,KAAA,EAAqB;AACjD,EAAA,OACE,MAAA,GAAS,mBAAA,CAAoB,KAAA,CAAM,CAAC,CAAA,GACpC,MAAA,GAAS,mBAAA,CAAoB,KAAA,CAAM,CAAC,CAAA,GACpC,MAAA,GAAS,mBAAA,CAAoB,MAAM,CAAC,CAAA;AAExC;AAMO,SAAS,YAAA,CAAa,GAAS,CAAA,EAAiB;AACrD,EAAA,MAAM,EAAA,GAAK,cAAc,CAAC,CAAA;AAC1B,EAAA,MAAM,EAAA,GAAK,cAAc,CAAC,CAAA;AAC1B,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,EAAE,CAAA;AAC/B,EAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,EAAA,EAAI,EAAE,CAAA;AAC9B,EAAA,OAAA,CAAQ,OAAA,GAAU,SAAS,MAAA,GAAS,IAAA,CAAA;AACtC;AAMO,SAAS,gBAAgB,UAAA,EAAyC;AACvE,EAAA,MAAM,QAAc,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AACvC,EAAA,MAAM,QAAc,EAAE,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAE;AACvC,EAAA,OAAO,YAAA,CAAa,OAAO,UAAU,CAAA,GAAI,aAAa,KAAA,EAAO,UAAU,IACnE,SAAA,GACA,SAAA;AACN;;;ACAO,IAAM,WAAA,GAAc;AAQpB,SAAS,iBAAiB,EAAA,EAAoB;AACnD,EAAA,OAAO,IAAA,CAAK,IAAI,EAAA,EAAI,IAAA,CAAK,IAAI,CAAA,EAAG,EAAA,GAAK,WAAW,CAAC,CAAA;AACnD;AAKO,SAAS,iBAAiB,UAAA,EAA4B;AAC3D,EAAA,OAAO,UAAA,GAAa,WAAA;AACtB;AAEO,SAAS,YAAA,CAAa,WAAiB,OAAA,EAAuB;AAEnE,EAAA,IAAI,IAAA,GACF,WAAA,GAAc,SAAA,CAAU,CAAA,IAAK,aAAA,GAC7B,WAAA,GAAc,SAAA,CAAU,CAAA,IAAK,aAAA,GAC7B,WAAA,GAAc,SAAA,CAAU,CAAA,IAAK,aAAA;AAE/B,EAAA,IAAI,GAAA,GACF,WAAA,GAAc,OAAA,CAAQ,CAAA,IAAK,aAAA,GAC3B,WAAA,GAAc,OAAA,CAAQ,CAAA,IAAK,aAAA,GAC3B,WAAA,GAAc,OAAA,CAAQ,CAAA,IAAK,aAAA;AAG7B,EAAA,IAAI,OAAO,aAAA,EAAe;AACxB,IAAA,IAAA,IAAA,CAAS,gBAAgB,IAAA,KAAS,aAAA;AAAA,EACpC;AACA,EAAA,IAAI,MAAM,aAAA,EAAe;AACvB,IAAA,GAAA,IAAA,CAAQ,gBAAgB,GAAA,KAAQ,aAAA;AAAA,EAClC;AAGA,EAAA,IAAI,KAAK,GAAA,CAAI,GAAA,GAAM,IAAI,CAAA,GAAI,kBAAkB,OAAO,CAAA;AAGpD,EAAA,IAAI,IAAA;AAEJ,EAAA,IAAI,MAAM,IAAA,EAAM;AAEd,IAAA,IAAA,GAAA,CAAQ,GAAA,IAAO,YAAA,GAAe,IAAA,IAAQ,aAAA,IAAiB,cAAA;AACvD,IAAA,OAAO,IAAA,GAAO,YAAA,GAAe,CAAA,GAAA,CAAK,IAAA,GAAO,kBAAA,IAAsB,GAAA;AAAA,EACjE,CAAA,MAAO;AAEL,IAAA,IAAA,GAAA,CAAQ,GAAA,IAAO,WAAA,GAAc,IAAA,IAAQ,YAAA,IAAgB,cAAA;AACrD,IAAA,OAAO,IAAA,GAAO,CAAC,YAAA,GAAe,CAAA,GAAA,CAAK,OAAO,kBAAA,IAAsB,GAAA;AAAA,EAClE;AACF;;;AC/EO,SAAS,GAAA,CAAI,CAAA,EAAU,CAAA,EAAU,CAAA,EAAkB;AACxD,EAAA,MAAM,IAAI,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,CAAA,GAAI,EAAE,CAAA,IAAK,CAAA;AAC9B,EAAA,MAAM,IAAI,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,CAAA,GAAI,EAAE,CAAA,IAAK,CAAA;AAG9B,EAAA,MAAM,aAAA,GAAgB,EAAE,CAAA,GAAI,oBAAA;AAC5B,EAAA,MAAM,aAAA,GAAgB,EAAE,CAAA,GAAI,oBAAA;AAE5B,EAAA,IAAI,iBAAiB,aAAA,EAAe;AAClC,IAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE;AAAA,EACtB;AAEA,EAAA,MAAM,EAAA,GAAK,aAAA,GAAgB,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA;AACnC,EAAA,MAAM,EAAA,GAAK,aAAA,GAAgB,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA;AAGnC,EAAA,IAAI,QAAQ,EAAA,GAAK,EAAA;AACjB,EAAA,IAAI,KAAA,GAAQ,KAAK,KAAA,IAAS,GAAA;AAC1B,EAAA,IAAI,KAAA,GAAQ,MAAM,KAAA,IAAS,GAAA;AAE3B,EAAA,IAAI,CAAA,GAAI,KAAK,KAAA,GAAQ,CAAA;AACrB,EAAA,IAAI,CAAA,GAAI,GAAG,CAAA,IAAK,GAAA;AAChB,EAAA,IAAI,CAAA,IAAK,KAAK,CAAA,IAAK,GAAA;AAEnB,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE;AACnB;;;ACrBO,IAAM,mBAAA,GAAsB;AAO5B,IAAM,WAAA,GAAc;AAQpB,IAAM,cAAA,GAAiB;AAMvB,IAAM,aAAA,GAAgB;AAStB,IAAM,gBAAgB,CAAA,GAAI;AAG1B,IAAM,kBAAA,GAAqB;AAS3B,IAAM,oBAAA,GAAuB;AAM7B,IAAM,cAAc,CAAA,GAAI;AAGxB,IAAM,gBAAA,GAAmB;AASzB,IAAM,cAAA,GAAiB;;;ACzBvB,SAAS,SACd,OAAA,EACA,CAAA,EACA,OACA,KAAA,GAAgB,aAAA,EAChB,eAAuB,kBAAA,EACf;AACR,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,KAAA,CAAM,KAAA,EAAO,MAAA,IAAU,CAAC,CAAC,CAAA;AACvE,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,YAAA,EAAc,KAAA,CAAM,IAAA,EAAM,MAAA,IAAU,CAAC,CAAC,CAAA;AAGtE,EAAA,IAAI,EAAA,KAAO,CAAA,IAAK,EAAA,KAAO,CAAA,EAAG,OAAO,OAAA;AAGjC,EAAA,MAAM,cAAA,GACJ,CAAA,IAAK,KAAA,GAAQ,GAAA,IAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAK,IAAA,CAAK,EAAA,GAAK,CAAA,GAAK,KAAK,CAAA,CAAA,GAAK,CAAA;AAG7D,EAAA,MAAM,aAAA,GACJ,CAAA,IAAK,CAAA,GAAI,KAAA,GACL,GAAA,IAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAK,IAAA,CAAK,EAAA,IAAM,CAAA,GAAI,CAAA,CAAA,GAAM,KAAK,CAAA,CAAA,GAC/C,CAAA;AAGN,EAAA,MAAMA,MAAAA,GAAQ,KAAK,EAAA,GAAK,GAAA;AACxB,EAAA,MAAM,UAAU,OAAA,GAAUA,MAAAA;AAC1B,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AAC3B,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA;AAG3B,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,EAAA,GAAK,CAAA;AAET,EAAA,IAAI,cAAA,GAAiB,CAAA,IAAK,EAAA,GAAK,CAAA,EAAG;AAChC,IAAA,MAAM,QAAQ,cAAA,GAAiB,EAAA;AAC/B,IAAA,MAAM,IAAA,GAAQ,KAAA,CAAM,KAAA,CAAO,GAAA,GAAOA,MAAAA;AAClC,IAAA,EAAA,IAAM,KAAA,IAAS,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,GAAI,EAAA,CAAA;AAChC,IAAA,EAAA,IAAM,KAAA,IAAS,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,GAAI,EAAA,CAAA;AAAA,EAClC;AAEA,EAAA,IAAI,aAAA,GAAgB,CAAA,IAAK,EAAA,GAAK,CAAA,EAAG;AAC/B,IAAA,MAAM,QAAQ,aAAA,GAAgB,EAAA;AAC9B,IAAA,MAAM,IAAA,GAAQ,KAAA,CAAM,IAAA,CAAM,GAAA,GAAOA,MAAAA;AACjC,IAAA,EAAA,IAAM,KAAA,IAAS,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,GAAI,EAAA,CAAA;AAChC,IAAA,EAAA,IAAM,KAAA,IAAS,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,GAAI,EAAA,CAAA;AAAA,EAClC;AAGA,EAAA,MAAM,KAAK,EAAA,GAAK,EAAA;AAChB,EAAA,MAAM,KAAK,EAAA,GAAK,EAAA;AAGhB,EAAA,IAAI,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,OAAO,OAAO,OAAA;AAEtC,EAAA,OAAA,CAAS,KAAK,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA,GAAIA,SAAS,GAAA,IAAO,GAAA;AAChD;AAYO,SAAS,gBAAA,CAAiB,GAAW,OAAA,EAA0B;AACpE,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,OAAA,CAAQ,KAAA,EAAO,MAAA,IAAU,CAAC,CAAC,CAAA;AAC/E,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,OAAA,CAAQ,IAAA,EAAM,MAAA,IAAU,CAAC,CAAC,CAAA;AAE9E,EAAA,IAAI,EAAA,KAAO,CAAA,IAAK,EAAA,KAAO,CAAA,EAAG,OAAO,CAAA;AAEjC,EAAA,MAAM,cAAA,GACJ,CAAA,IAAK,aAAA,GAAgB,GAAA,IAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAK,IAAA,CAAK,EAAA,GAAK,CAAA,GAAK,aAAa,CAAA,CAAA,GAAK,CAAA;AAE7E,EAAA,MAAM,aAAA,GACJ,CAAA,IAAK,CAAA,GAAI,aAAA,GACL,GAAA,IAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAK,IAAA,CAAK,EAAA,IAAM,CAAA,GAAI,CAAA,CAAA,GAAM,aAAa,CAAA,CAAA,GACvD,CAAA;AAEN,EAAA,MAAM,UAAA,GAAa,kBAAkB,EAAA,GAAK,kBAAA,CAAA;AAC1C,EAAA,MAAM,SAAA,GAAY,iBAAiB,EAAA,GAAK,kBAAA,CAAA;AAExC,EAAA,OAAO,IAAA,CAAK,GAAA,CAAI,UAAA,EAAY,SAAS,CAAA;AACvC;AAgBO,SAAS,gBAAA,CACd,OAAA,EACA,CAAA,EACA,WAAA,EACA,UAAA,EACQ;AACR,EAAA,IAAI,CAAA,GAAI,OAAA;AACR,EAAA,IAAI,YAAY,CAAA,GAAI,QAAA,CAAS,GAAG,CAAA,EAAG,UAAA,EAAY,aAAa,gBAAgB,CAAA;AAC5E,EAAA,IAAI,WAAA,EAAa,CAAA,GAAI,QAAA,CAAS,CAAA,EAAG,GAAG,WAAW,CAAA;AAC/C,EAAA,OAAO,CAAA;AACT;AAaO,SAAS,kBAAA,CACd,GAAA,EACA,MAAA,EACA,KAAA,GAAiB,KAAA,EACR;AACT,EAAA,OAAO,KAAA,GACH,EAAE,KAAA,EAAO,EAAE,GAAA,EAAK,MAAA,EAAO,EAAE,GACzB,EAAE,IAAA,EAAM,EAAE,GAAA,EAAK,QAAO,EAAE;AAC9B;;;AC1KO,SAAS,gBAAgB,MAAA,EAAwB;AACtD,EAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,MAAM,CAAC,CAAA;AACzC,EAAA,OAAO,cAAA,GAAiB,KAAK,CAAA,GAAM,cAAA,CAAA;AACrC;AAMO,SAAS,eAAe,MAAA,EAAwB;AACrD,EAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,MAAM,CAAC,CAAA;AACzC,EAAA,OAAO,iBAAiB,CAAA,GAAI,CAAA,CAAA;AAC9B;AASO,SAAS,iBAAA,CAAkB,CAAA,EAAW,SAAA,EAAmB,QAAA,EAA0B;AACxF,EAAA,MAAM,QAAQ,SAAA,GAAY,QAAA;AAC1B,EAAA,IAAI,KAAA,IAAS,GAAG,OAAO,GAAA;AACvB,EAAA,OAAO,IAAA,CAAK,IAAI,CAAA,EAAG,IAAA,CAAK,IAAI,CAAA,EAAA,CAAI,SAAA,GAAY,CAAA,IAAK,KAAK,CAAC,CAAA;AACzD;;;ACtBA,IAAM,KAAA,GAAQ,KAAK,EAAA,GAAK,GAAA;AAUxB,SAAS,oBACP,CAAA,EAAW,CAAA,EAAW,CAAA,EAAW,CAAA,EACjC,SAAkB,KAAA,EACQ;AAC1B,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,OAAA,CAAQ,KAAA,EAAO,MAAA,IAAU,CAAC,CAAC,CAAA;AAC/E,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,OAAA,CAAQ,IAAA,EAAM,MAAA,IAAU,CAAC,CAAC,CAAA;AAC9E,EAAA,IAAI,OAAO,CAAA,IAAK,EAAA,KAAO,GAAG,OAAO,EAAE,GAAG,CAAA,EAAE;AAGxC,EAAA,MAAM,SAAA,GAAY,CAAA,IAAK,aAAA,GACnB,GAAA,IAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAK,IAAA,CAAK,EAAA,GAAK,CAAA,GAAK,aAAa,CAAA,CAAA,GAAK,CAAA;AAC1D,EAAA,MAAM,QAAA,GAAW,CAAA,IAAK,CAAA,GAAI,aAAA,GACtB,GAAA,IAAO,CAAA,GAAI,IAAA,CAAK,GAAA,CAAK,IAAA,CAAK,EAAA,IAAM,CAAA,GAAI,CAAA,CAAA,GAAM,aAAa,CAAA,CAAA,GAAK,CAAA;AAEhE,EAAA,MAAM,UAAA,GAAa,aAAa,EAAA,GAAK,kBAAA,CAAA;AACrC,EAAA,MAAM,SAAA,GAAY,YAAY,EAAA,GAAK,kBAAA,CAAA;AACnC,EAAA,IAAI,eAAe,CAAA,IAAK,SAAA,KAAc,GAAG,OAAO,EAAE,GAAG,CAAA,EAAE;AAGvD,EAAA,MAAM,OAAO,CAAA,GAAI,KAAA;AACjB,EAAA,IAAI,CAAA,GAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACzB,EAAA,IAAI,CAAA,GAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AAGzB,EAAA,IAAI,aAAa,CAAA,EAAG;AAClB,IAAA,MAAM,EAAA,GAAK,QAAQ,KAAA,CAAO,GAAA;AAC1B,IAAA,MAAM,OAAO,EAAA,GAAK,KAAA;AAClB,IAAA,MAAM,KAAK,SAAA,CAAU,CAAA,EAAG,EAAA,EAAI,KAAK,IAAI,oBAAA,GAAuB,UAAA;AAC5D,IAAA,CAAA,IAAK,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACvB,IAAA,CAAA,IAAK,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AAAA,EACzB;AACA,EAAA,IAAI,YAAY,CAAA,EAAG;AACjB,IAAA,MAAM,EAAA,GAAK,QAAQ,IAAA,CAAM,GAAA;AACzB,IAAA,MAAM,OAAO,EAAA,GAAK,KAAA;AAClB,IAAA,MAAM,KAAK,SAAA,CAAU,CAAA,EAAG,EAAA,EAAI,KAAK,IAAI,oBAAA,GAAuB,SAAA;AAC5D,IAAA,CAAA,IAAK,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AACvB,IAAA,CAAA,IAAK,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA;AAAA,EACzB;AAGA,EAAA,IAAI,OAAO,IAAA,CAAK,IAAA,CAAK,CAAA,GAAI,CAAA,GAAI,IAAI,CAAC,CAAA;AAClC,EAAA,IAAI,QAAS,IAAA,CAAK,KAAA,CAAM,GAAG,CAAC,CAAA,GAAI,QAAS,GAAA,IAAO,GAAA;AAGhD,EAAA,IAAA,GAAO,KAAK,GAAA,CAAI,IAAA,EAAM,UAAU,CAAA,EAAG,IAAA,EAAM,KAAK,CAAC,CAAA;AAE/C,EAAA,OAAO,EAAE,CAAA,EAAG,IAAA,EAAM,CAAA,EAAG,IAAA,EAAK;AAC5B;AA0DO,SAAS,aAAA,CAAc,OAAA,GAAwB,EAAC,EAAY;AACjE,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IACA,GAAA,GAAM,WAAA;AAAA,IACN,MAAA;AAAA,IACA,IAAA,GAAO,KAAA;AAAA,IACP,OAAA;AAAA,IACA;AAAA,GACF,GAAI,OAAA;AACJ,EAAA,MAAM,KAAA,GAAQ,OAAO,YAAA,GAAe,MAAA;AAEpC,EAAA,MAAM,KAAA,GAAQ,mBAAA;AACd,EAAA,MAAM,WAAA,GAAc,QAAQ,MAAA,IAAU,CAAA;AACtC,EAAA,MAAM,UAAA,GAAa,QAAQ,OAAA,IAAW,GAAA;AACtC,EAAA,MAAM,QAAA,GAAW,OAAA;AACjB,EAAA,MAAM,aAAA,GAAgB,QAAQ,kBAAA,CAAmB,KAAA,CAAM,KAAK,KAAA,CAAM,MAAA,EAAQ,KAAA,CAAM,KAAK,CAAA,GAAI,MAAA;AAEzF,EAAA,MAAM,KAAA,GAAQ,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,WAAW,CAAC,CAAA;AAClD,EAAA,MAAM,IAAA,GAAO,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAC,CAAA;AAChD,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,QAAA,EAAU,KAAA,IAAS,CAAC,CAAA;AACtD,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,QAAA,EAAU,IAAA,IAAQ,CAAC,CAAA;AAGnD,EAAA,MAAM,QAAQ,CAAC,CAAA,KAAc,iBAAiB,GAAA,EAAK,CAAA,EAAG,UAAU,aAAa,CAAA;AAM7E,EAAA,IAAI,IAAA,KAAS,GAAA,IAAO,KAAA,KAAU,CAAA,IAAK,SAAS,CAAA,EAAG;AAC7C,IAAA,MAAMC,SAAiB,EAAC;AACxB,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC9B,MAAA,MAAM,CAAA,GAAI,KAAK,KAAA,GAAQ,CAAA,CAAA;AACvB,MAAA,MAAM,CAAA,GAAI,SAAA,GAAY,CAAA,IAAK,SAAA,GAAY,QAAA,CAAA;AACvC,MAAA,IAAI,CAAA,GAAI,MAAM,CAAC,CAAA;AAKf,MAAA,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,SAAA,CAAU,CAAA,EAAG,GAAA,EAAK,KAAK,CAAA,GAAI,KAAA,EAAO,SAAA,CAAU,CAAA,EAAG,CAAA,EAAG,KAAK,CAAC,CAAA;AAEzE,MAAA,IAAI,QAAA,EAAU;AACZ,QAAA,MAAM,UAAU,mBAAA,CAAoB,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,UAAU,KAAK,CAAA;AAC/D,QAAA,CAAA,GAAI,OAAA,CAAQ,CAAA;AACZ,QAAA,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,MACd;AAEA,MAAAA,OAAM,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA;AAAA,IACxB;AACA,IAAA,OAAOA,MAAAA;AAAA,EACT;AAOA,EAAA,MAAM,CAAA,GAAI,GAAA;AACV,EAAA,IAAI,KAAA,GAAQ,GAAA;AACZ,EAAA,IAAI,aAAA,GAAgB,CAAA;AACpB,EAAA,MAAM,kBAA8C,EAAC;AAErD,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,IAAK,CAAA,EAAG,CAAA,EAAA,EAAK;AAC3B,IAAA,MAAM,IAAI,CAAA,GAAI,CAAA;AACd,IAAA,MAAM,CAAA,GAAI,SAAA,GAAY,CAAA,IAAK,SAAA,GAAY,QAAA,CAAA;AAKvC,IAAA,MAAM,CAAA,GAAI,SAAA,CAAU,CAAA,EAAG,GAAA,EAAK,KAAK,CAAA;AACjC,IAAA,eAAA,CAAgB,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA;AAC7B,IAAA,IAAI,IAAI,aAAA,EAAe;AACrB,MAAA,aAAA,GAAgB,CAAA;AAChB,MAAA,KAAA,GAAQ,CAAA;AAAA,IACV;AAAA,EACF;AAGA,EAAA,MAAM,aAAa,aAAA,GAAgB,KAAA;AACnC,EAAA,IAAI,SAAA,GAAY,KAAA;AAChB,EAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,EAAA,KAAA,MAAW,EAAE,CAAA,EAAG,CAAA,EAAE,IAAK,eAAA,EAAiB;AACtC,IAAA,IAAI,CAAA,IAAK,aAAa,IAAA,EAAM;AAC1B,MAAA,IAAI,CAAA,GAAI,WAAW,SAAA,GAAY,CAAA;AAC/B,MAAA,IAAI,CAAA,GAAI,WAAW,SAAA,GAAY,CAAA;AAAA,IACjC;AAAA,EACF;AAGA,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,QAAQ,GAAA,EAAK;AACf,IAAA,OAAA,GAAU,SAAA,GAAa,IAAA,GAAO,GAAA,IAAQ,KAAA,GAAQ,SAAA,CAAA;AAAA,EAChD,CAAA,MAAO;AACL,IAAA,OAAA,GAAU,KAAA,GAAA,CAAU,IAAA,GAAO,GAAA,IAAO,GAAA,IAAQ,SAAA,GAAY,KAAA,CAAA;AAAA,EACxD;AAKA,EAAA,IAAI,OAAA,IAAW,CAAA,IAAK,OAAA,IAAW,CAAA,EAAG;AAChC,IAAA,OAAA,GAAU,KAAA;AAAA,EACZ;AAGA,EAAA,MAAM,QAAiB,EAAC;AACxB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC9B,IAAA,MAAM,CAAA,GAAI,KAAK,KAAA,GAAQ,CAAA,CAAA;AACvB,IAAA,MAAM,CAAA,GAAI,SAAA,GAAY,CAAA,IAAK,SAAA,GAAY,QAAA,CAAA;AACvC,IAAA,IAAI,CAAA,GAAI,MAAM,CAAC,CAAA;AAKf,IAAA,IAAI,OAAA;AACJ,IAAA,IAAI,KAAK,OAAA,EAAS;AAChB,MAAA,OAAA,GAAU,KAAK,KAAA,GAAQ,OAAA,CAAA;AAAA,IACzB,CAAA,MAAO;AACL,MAAA,OAAA,GAAU,KAAA,GAAA,CAAS,CAAA,GAAI,OAAA,KAAA,CAAa,CAAA,GAAI,UAAU,CAAA,GAAI,OAAA,CAAA,CAAA;AAAA,IACxD;AAEA,IAAA,MAAM,OAAA,GAAU,SAAA,GAAY,OAAA,IAAW,SAAA,GAAY,QAAA,CAAA;AAInD,IAAA,MAAM,OAAA,GAAU,SAAA,CAAU,OAAA,EAAS,GAAA,EAAK,KAAK,CAAA,GAAI,KAAA;AAGjD,IAAA,MAAM,SAAA,GAAY,SAAA,CAAU,CAAA,EAAG,CAAA,EAAG,KAAK,CAAA;AACvC,IAAA,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,OAAA,EAAS,SAAS,CAAA;AAEnC,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,MAAM,UAAU,mBAAA,CAAoB,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,UAAU,KAAK,CAAA;AAC/D,MAAA,CAAA,GAAI,OAAA,CAAQ,CAAA;AACZ,MAAA,CAAA,GAAI,OAAA,CAAQ,CAAA;AAAA,IACd;AAEA,IAAA,KAAA,CAAM,IAAA,CAAK,EAAE,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA;AAAA,EACxB;AAEA,EAAA,OAAO,KAAA;AACT;;;AClOO,SAAS,YAAA,CACd,KAAA,EACA,IAAA,GAAgB,KAAA,EACD;AACf,EAAA,MAAM,KAAA,GAAe,OAAO,YAAA,GAAe,MAAA;AAC3C,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,KAAU,QAAA;AAC/B,EAAA,MAAM,QAAA,GAAkB,KAAA,GAAQ,UAAA,CAAW,KAAK,CAAA,GAAI,KAAA;AAKpD,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,KAAA,EAAO;AACT,IAAA,OAAA,GAAU,IAAA;AAAA,EACZ,CAAA,MAAO;AACL,IAAA,MAAM,MACJ,KAAA,KAAU,YAAA,GAAe,UAAU,QAAQ,CAAA,GAAI,YAAY,QAAQ,CAAA;AACrE,IAAA,OAAA,GAAU,UAAU,GAAG,CAAA;AAAA,EACzB;AAEA,EAAA,MAAM,KAAA,GAAQ,OAAA,GAAU,QAAA,GAAW,QAAA,CAAS,UAAU,KAAK,CAAA;AAE3D,EAAA,MAAM,WAAW,SAAA,CAAU,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,GAAG,KAAK,CAAA;AAClD,EAAA,MAAM,WAAA,GAAc,QAAA,GAAW,CAAA,GAAI,KAAA,CAAM,IAAI,QAAA,GAAW,CAAA;AAExD,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,GAAA,EAAK,WAAW,KAAK,CAAA;AAAA,IACrB,aAAa,CAAC,OAAA;AAAA,IACd,QAAA;AAAA,IACA,WAAA,EAAa,QAAA,CAAS,CAAA,GAAI,KAAA,CAAM,CAAA;AAAA,IAChC,KAAK,KAAA,CAAM,CAAA;AAAA,IACX,WAAA,EAAa,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAW;AAAA,GACtC;AACF;;;AC5BO,SAAS,QAAA,CACd,OACA,OAAA,EAKgB;AAChB,EAAA,MAAM,EAAE,OAAO,KAAA,EAAO,QAAA,EAAU,QAAQ,mBAAA,EAAoB,GAAI,WAAW,EAAC;AAC5E,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,KAAA,EAAO,IAAI,CAAA;AACzC,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,QAAA,EAAU,KAAA,IAAS,CAAC,CAAA;AACtD,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,QAAA,EAAU,IAAA,IAAQ,CAAC,CAAA;AACnD,EAAA,MAAM,UAAU,iBAAA,CAAkB,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,WAAW,QAAQ,CAAA;AACvE,EAAA,MAAM,SAAA,GAAY,KAAK,KAAA,CAAM,OAAA,GAAU,KAAK,GAAA,CAAI,CAAA,EAAG,KAAA,GAAQ,CAAC,CAAC,CAAA;AAE7D,EAAA,OAAO;AAAA,IACL,KAAK,QAAA,CAAS,GAAA;AAAA,IACd,MAAA,EAAQ,EAAE,MAAA,EAAQ,QAAA,CAAS,aAAa,OAAA,EAAQ;AAAA,IAChD,SAAA;AAAA,IACA,KAAK,QAAA,CAAS,GAAA;AAAA,IACd,OAAO,QAAA,CAAS,KAAA;AAAA,IAChB,aAAa,QAAA,CAAS,WAAA;AAAA,IACtB,UAAU,QAAA,CAAS;AAAA,GACrB;AACF","file":"index.cjs","sourcesContent":["// ── sRGB Gamma Transfer (IEC 61966-2-1) ──\n\nexport const SRGB_GAMMA_THRESHOLD = 0.04045;\nexport const SRGB_GAMMA_THRESHOLD_LINEAR = 0.0031308;\nexport const SRGB_GAMMA_SLOPE = 12.92;\nexport const SRGB_GAMMA_EXPONENT = 2.4;\nexport const SRGB_GAMMA_OFFSET = 0.055;\nexport const SRGB_GAMMA_SCALE = 1.055;\n\n// ── Ottosson M1: Linear sRGB → LMS ──\n\nexport const LINEAR_SRGB_TO_LMS = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n] as const;\n\n// ── Ottosson M2: LMS′ (cube-root) → OKLAB ──\n\nexport const LMS_PRIME_TO_OKLAB = [\n [+0.2104542553, +0.7936177850, -0.0040720468],\n [+1.9779984951, -2.4285922050, +0.4505937099],\n [+0.0259040371, +0.7827717662, -0.8086757660],\n] as const;\n\n// ── Inverse M2: OKLAB → LMS′ ──\n\nexport const OKLAB_TO_LMS_PRIME = [\n [1.0000000000, +0.3963377774, +0.2158037573],\n [1.0000000000, -0.1055613458, -0.0638541728],\n [1.0000000000, -0.0894841775, -1.2914855480],\n] as const;\n\n// ── Inverse M1: LMS → Linear sRGB ──\n\nexport const LMS_TO_LINEAR_SRGB = [\n [+4.0767416621, -3.3077115913, +0.2309699292],\n [-1.2684380046, +2.6097574011, -0.3413193965],\n [-0.0041960863, -0.7034186147, +1.7076147010],\n] as const;\n\n// ── Display P3 M1: Linear Display P3 → LMS ──\n// Derived: XYZ_to_LMS × P3_to_XYZ, where XYZ_to_LMS = M1_srgb × inv(sRGB_to_XYZ)\n\nexport const LINEAR_P3_TO_LMS = [\n [+0.4813791595, +0.4621155872, +0.0565406381],\n [+0.2288319169, +0.6532167007, +0.1179528072],\n [+0.0839457149, +0.2241651052, +0.6918912614],\n] as const;\n\n// ── Inverse P3 M1: LMS → Linear Display P3 ──\n\nexport const LMS_TO_LINEAR_P3 = [\n [+3.1277694390, -2.2570600176, +0.1291828502],\n [-1.0910091977, +2.4133065499, -0.3222615148],\n [-0.0260108068, -0.5080402362, +1.5340494942],\n] as const;\n\n// ── Gamut Mapping ──\n\nexport const GAMUT_EPSILON = 1e-6;\nexport const GAMUT_MAP_JND = 0.02;\nexport const GAMUT_MAP_EPSILON = 1e-4;\nexport const GAMUT_MAP_MAX_ITERATIONS = 50;\n\n// ── Achromatic Threshold ──\n\nexport const ACHROMATIC_THRESHOLD = 1e-10;\n\n// ── WCAG 2.x Luminance Coefficients ──\n\nexport const WCAG_R = 0.2126;\nexport const WCAG_G = 0.7152;\nexport const WCAG_B = 0.0722;\n\n// ── APCA-W3 (SA98G) Constants ──\n\nexport const APCA_MAIN_TRC = 2.4;\nexport const APCA_SRGB_R = 0.2126729;\nexport const APCA_SRGB_G = 0.7151522;\nexport const APCA_SRGB_B = 0.0721750;\nexport const APCA_NORM_BG = 0.56;\nexport const APCA_NORM_TXT = 0.57;\nexport const APCA_REV_TXT = 0.62;\nexport const APCA_REV_BG = 0.65;\nexport const APCA_BLK_THRS = 0.022;\nexport const APCA_BLK_CLMP = 1.414;\nexport const APCA_SCALE_BOW = 1.14;\nexport const APCA_SCALE_WOB = 1.14;\nexport const APCA_LO_BOW_OFFSET = 0.027;\nexport const APCA_LO_WOB_OFFSET = 0.027;\nexport const APCA_DELTA_Y_MIN = 0.0005;\nexport const APCA_LO_CLIP = 0.1;\n\n// ── Angle Math ──\n\nexport const DEG_TO_RAD = Math.PI / 180;\nexport const RAD_TO_DEG = 180 / Math.PI;\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD, DEG_TO_RAD, RAD_TO_DEG } from \"../constants.js\";\n\n/** Convert OKLAB (cartesian) to OKLCH (cylindrical). Achromatic colors get h=0. */\nexport function oklabToOklch(lab: Oklab): Oklch {\n const C = Math.sqrt(lab.a * lab.a + lab.b * lab.b);\n\n if (C < ACHROMATIC_THRESHOLD) {\n return { L: lab.L, C: 0, h: 0 };\n }\n\n let h = Math.atan2(lab.b, lab.a) * RAD_TO_DEG;\n if (h < 0) h += 360;\n\n return { L: lab.L, C, h };\n}\n\n/** Convert OKLCH (cylindrical) to OKLAB (cartesian). */\nexport function oklchToOklab(lch: Oklch): Oklab {\n const hRad = lch.h * DEG_TO_RAD;\n return {\n L: lch.L,\n a: lch.C * Math.cos(hRad),\n b: lch.C * Math.sin(hRad),\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_SRGB_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_SRGB,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear sRGB to OKLAB via Ottosson's direct M1/M2 matrices. */\nexport function linearSrgbToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear sRGB → LMS\n const l =\n LINEAR_SRGB_TO_LMS[0][0] * color.r +\n LINEAR_SRGB_TO_LMS[0][1] * color.g +\n LINEAR_SRGB_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_SRGB_TO_LMS[1][0] * color.r +\n LINEAR_SRGB_TO_LMS[1][1] * color.g +\n LINEAR_SRGB_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_SRGB_TO_LMS[2][0] * color.r +\n LINEAR_SRGB_TO_LMS[2][1] * color.g +\n LINEAR_SRGB_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear sRGB via inverse M2/M1 matrices. */\nexport function oklabToLinearSrgb(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear sRGB\n return {\n r:\n LMS_TO_LINEAR_SRGB[0][0] * l +\n LMS_TO_LINEAR_SRGB[0][1] * m +\n LMS_TO_LINEAR_SRGB[0][2] * s,\n g:\n LMS_TO_LINEAR_SRGB[1][0] * l +\n LMS_TO_LINEAR_SRGB[1][1] * m +\n LMS_TO_LINEAR_SRGB[1][2] * s,\n b:\n LMS_TO_LINEAR_SRGB[2][0] * l +\n LMS_TO_LINEAR_SRGB[2][1] * m +\n LMS_TO_LINEAR_SRGB[2][2] * s,\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_P3_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_P3,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear Display P3 to OKLAB via P3-specific M1 + shared M2. */\nexport function linearP3ToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear P3 → LMS\n const l =\n LINEAR_P3_TO_LMS[0][0] * color.r +\n LINEAR_P3_TO_LMS[0][1] * color.g +\n LINEAR_P3_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_P3_TO_LMS[1][0] * color.r +\n LINEAR_P3_TO_LMS[1][1] * color.g +\n LINEAR_P3_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_P3_TO_LMS[2][0] * color.r +\n LINEAR_P3_TO_LMS[2][1] * color.g +\n LINEAR_P3_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB (shared M2)\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear Display P3 via shared inverse M2 + P3-specific inverse M1. */\nexport function oklabToLinearP3(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′ (shared inverse M2)\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear P3\n return {\n r:\n LMS_TO_LINEAR_P3[0][0] * l +\n LMS_TO_LINEAR_P3[0][1] * m +\n LMS_TO_LINEAR_P3[0][2] * s,\n g:\n LMS_TO_LINEAR_P3[1][0] * l +\n LMS_TO_LINEAR_P3[1][1] * m +\n LMS_TO_LINEAR_P3[1][2] * s,\n b:\n LMS_TO_LINEAR_P3[2][0] * l +\n LMS_TO_LINEAR_P3[2][1] * m +\n LMS_TO_LINEAR_P3[2][2] * s,\n };\n}\n","import type { LinearSrgb, Srgb } from \"../types.js\";\nimport {\n SRGB_GAMMA_EXPONENT,\n SRGB_GAMMA_OFFSET,\n SRGB_GAMMA_SCALE,\n SRGB_GAMMA_SLOPE,\n SRGB_GAMMA_THRESHOLD,\n SRGB_GAMMA_THRESHOLD_LINEAR,\n} from \"../constants.js\";\n\n/** Decode a single sRGB gamma-encoded channel to linear light. */\nexport function srgbChannelToLinear(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD\n ? value / SRGB_GAMMA_SLOPE\n : ((value + SRGB_GAMMA_OFFSET) / SRGB_GAMMA_SCALE) ** SRGB_GAMMA_EXPONENT;\n}\n\n/** Encode a single linear light channel to sRGB gamma. */\nexport function linearChannelToSrgb(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD_LINEAR\n ? value * SRGB_GAMMA_SLOPE\n : SRGB_GAMMA_SCALE * value ** (1 / SRGB_GAMMA_EXPONENT) - SRGB_GAMMA_OFFSET;\n}\n\n/** Convert an sRGB color to Linear sRGB. */\nexport function srgbToLinearSrgb(color: Srgb): LinearSrgb {\n return {\n r: srgbChannelToLinear(color.r),\n g: srgbChannelToLinear(color.g),\n b: srgbChannelToLinear(color.b),\n };\n}\n\n/** Convert a Linear sRGB color to sRGB. */\nexport function linearSrgbToSrgb(color: LinearSrgb): Srgb {\n return {\n r: linearChannelToSrgb(color.r),\n g: linearChannelToSrgb(color.g),\n b: linearChannelToSrgb(color.b),\n };\n}\n","import type { Hex, Srgb } from \"../types.js\";\n\n/** Parse a hex color string (#RGB, #RRGGBB, or bare) to sRGB [0,1]. */\nexport function hexToSrgb(hex: string): Srgb {\n let h = hex.startsWith(\"#\") ? hex.slice(1) : hex;\n\n if (h.length === 3) {\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];\n }\n\n const n = parseInt(h, 16);\n return {\n r: ((n >> 16) & 0xff) / 255,\n g: ((n >> 8) & 0xff) / 255,\n b: (n & 0xff) / 255,\n };\n}\n\n/** Convert sRGB [0,1] to lowercase hex string (#rrggbb). Clamps to [0,1]. */\nexport function srgbToHex(color: Srgb): Hex {\n const r = Math.round(Math.max(0, Math.min(1, color.r)) * 255);\n const g = Math.round(Math.max(0, Math.min(1, color.g)) * 255);\n const b = Math.round(Math.max(0, Math.min(1, color.b)) * 255);\n return `#${((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1)}` as Hex;\n}\n","import type { Hex, Oklab, Oklch, Srgb } from \"../types.js\";\nimport { oklabToOklch, oklchToOklab } from \"./oklab.js\";\nimport { linearSrgbToOklab, oklabToLinearSrgb } from \"./linear-srgb.js\";\nimport { linearP3ToOklab, oklabToLinearP3 } from \"./linear-p3.js\";\nimport { linearSrgbToSrgb, srgbToLinearSrgb } from \"./srgb.js\";\nimport { hexToSrgb, srgbToHex } from \"./hex.js\";\n\n/** Convert sRGB to OKLCH. */\nexport function srgbToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearSrgbToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to sRGB. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToSrgb(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(oklchToOklab(color)));\n}\n\n/** Convert sRGB to OKLAB. */\nexport function srgbToOklab(color: Srgb): Oklab {\n return linearSrgbToOklab(srgbToLinearSrgb(color));\n}\n\n/** Convert OKLAB to sRGB. May produce out-of-gamut values. */\nexport function oklabToSrgb(color: Oklab): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(color));\n}\n\n/** Convert hex to OKLCH. */\nexport function hexToOklch(hex: string): Oklch {\n return srgbToOklch(hexToSrgb(hex));\n}\n\n/** Convert OKLCH to hex. Clamps to sRGB gamut before hex encoding. */\nexport function oklchToHex(color: Oklch): Hex {\n const srgb = oklchToSrgb(color);\n return srgbToHex({\n r: Math.max(0, Math.min(1, srgb.r)),\n g: Math.max(0, Math.min(1, srgb.g)),\n b: Math.max(0, Math.min(1, srgb.b)),\n });\n}\n\n/** Convert Display P3 to OKLCH. */\nexport function p3ToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearP3ToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to Display P3. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToP3(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearP3(oklchToOklab(color)));\n}\n\n/** Convert OKLCH to a CSS `color(display-p3 r g b)` string. Clamps channels to [0,1]. */\nexport function oklchToP3Css(color: Oklch): string {\n const p3 = oklchToP3(color);\n const r = Math.max(0, Math.min(1, p3.r)).toFixed(4);\n const g = Math.max(0, Math.min(1, p3.g)).toFixed(4);\n const b = Math.max(0, Math.min(1, p3.b)).toFixed(4);\n return `color(display-p3 ${r} ${g} ${b})`;\n}\n","import type { Srgb } from \"../types.js\";\nimport { GAMUT_EPSILON } from \"../constants.js\";\n\n/** Check if sRGB channels are within [0, 1] (with epsilon tolerance). */\nexport function isInGamut(color: Srgb): boolean {\n return (\n color.r >= -GAMUT_EPSILON &&\n color.r <= 1 + GAMUT_EPSILON &&\n color.g >= -GAMUT_EPSILON &&\n color.g <= 1 + GAMUT_EPSILON &&\n color.b >= -GAMUT_EPSILON &&\n color.b <= 1 + GAMUT_EPSILON\n );\n}\n\n/** Clamp sRGB channels to [0, 1]. */\nexport function clampSrgb(color: Srgb): Srgb {\n return {\n r: Math.max(0, Math.min(1, color.r)),\n g: Math.max(0, Math.min(1, color.g)),\n b: Math.max(0, Math.min(1, color.b)),\n };\n}\n\n/** Clamp Display P3 channels to [0, 1]. */\nexport const clampP3 = clampSrgb;\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\n\n/** Compute deltaEOK (Euclidean distance in OKLAB) between two OKLCH colors. */\nexport function deltaEOK(a: Oklch, b: Oklch): number {\n return deltaEOKLab(oklchToOklab(a), oklchToOklab(b));\n}\n\n/** Compute deltaEOK directly from OKLAB values. */\nexport function deltaEOKLab(a: Oklab, b: Oklab): number {\n const dL = a.L - b.L;\n const da = a.a - b.a;\n const db = a.b - b.b;\n return Math.sqrt(dL * dL + da * da + db * db);\n}\n","import type { Gamut, Oklch, Srgb } from \"../types.js\";\nimport {\n GAMUT_EPSILON,\n GAMUT_MAP_EPSILON,\n GAMUT_MAP_JND,\n GAMUT_MAP_MAX_ITERATIONS,\n} from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut, clampSrgb } from \"./check.js\";\nimport { deltaEOKLab } from \"../color/difference.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\nimport { linearSrgbToOklab } from \"../conversions/linear-srgb.js\";\nimport { linearP3ToOklab } from \"../conversions/linear-p3.js\";\nimport { srgbToLinearSrgb } from \"../conversions/srgb.js\";\n\n/**\n * Map an OKLCH color into the target gamut using the CSS Color Level 4 algorithm.\n * Reduces chroma at fixed L and h via binary search with deltaEOK JND check.\n * @param gamut Target gamut (default: 'srgb').\n */\nexport function gamutMap(color: Oklch, gamut: Gamut = \"srgb\"): Oklch {\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n const rgbToOklab =\n gamut === \"display-p3\"\n ? (c: Srgb) => linearP3ToOklab(srgbToLinearSrgb(c))\n : (c: Srgb) => linearSrgbToOklab(srgbToLinearSrgb(c));\n\n // Already in gamut\n const rgb = toRgb(color);\n if (isInGamut(rgb)) return color;\n\n // Edge cases: black and white\n if (color.L <= GAMUT_EPSILON) return { L: 0, C: 0, h: color.h };\n if (color.L >= 1 - GAMUT_EPSILON) return { L: 1, C: 0, h: color.h };\n\n let lo = 0;\n let hi = color.C;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const midC = (lo + hi) / 2;\n const candidate: Oklch = { L: color.L, C: midC, h: color.h };\n const candidateRgb = toRgb(candidate);\n\n if (isInGamut(candidateRgb)) {\n lo = midC;\n } else {\n // Clip and check JND\n const clipped = clampSrgb(candidateRgb);\n const clippedLab = rgbToOklab(clipped);\n const candidateLab = oklchToOklab(candidate);\n const dE = deltaEOKLab(clippedLab, candidateLab);\n\n if (dE < GAMUT_MAP_JND) {\n // Clipped version is perceptually close enough — converge here.\n // Return lo (last confirmed in-gamut chroma) to guarantee gamut safety.\n break;\n }\n\n hi = midC;\n }\n\n if (hi - lo < GAMUT_MAP_EPSILON) break;\n }\n\n return { L: color.L, C: lo, h: color.h };\n}\n","import type { Gamut, Oklch } from \"../types.js\";\nimport { GAMUT_MAP_MAX_ITERATIONS } from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"./check.js\";\n\n/**\n * Find the maximum in-gamut chroma for a given OKLCH lightness and hue.\n *\n * Binary search over [0, upperBound], converging to 1e-6 precision.\n * Upper bounds are empirically safe ceilings — no in-gamut color at any\n * lightness or hue exceeds C = 0.4 in sRGB or C = 0.5 in Display P3.\n * Searching beyond these would waste iterations with no benefit.\n *\n * Returns 0 for L ≤ 0 or L ≥ 1 (pure black and white carry no chroma).\n */\nexport function maxChroma(L: number, h: number, gamut: Gamut = \"srgb\"): number {\n if (L <= 0 || L >= 1) return 0;\n\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n let lo = 0;\n let hi = gamut === \"display-p3\" ? 0.5 : 0.4;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const mid = (lo + hi) / 2;\n const color: Oklch = { L, C: mid, h };\n const rgb = toRgb(color);\n\n if (isInGamut(rgb)) {\n lo = mid;\n } else {\n hi = mid;\n }\n\n if (hi - lo < 1e-6) break;\n }\n\n return lo;\n}\n","import type { Srgb } from \"../types.js\";\nimport { WCAG_R, WCAG_G, WCAG_B } from \"../constants.js\";\nimport { srgbChannelToLinear } from \"../conversions/srgb.js\";\n\n/** Compute WCAG 2.x relative luminance [0, 1] from an sRGB color. */\nexport function wcagLuminance(color: Srgb): number {\n return (\n WCAG_R * srgbChannelToLinear(color.r) +\n WCAG_G * srgbChannelToLinear(color.g) +\n WCAG_B * srgbChannelToLinear(color.b)\n );\n}\n\n/**\n * Compute WCAG 2.x contrast ratio between two sRGB colors.\n * Returns a value in [1, 21]. Symmetric (order doesn't matter).\n */\nexport function wcagContrast(a: Srgb, b: Srgb): number {\n const lA = wcagLuminance(a);\n const lB = wcagLuminance(b);\n const lighter = Math.max(lA, lB);\n const darker = Math.min(lA, lB);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Choose black or white text for maximum WCAG contrast against a background.\n * @returns `\"#000000\"` or `\"#ffffff\"`.\n */\nexport function contrastTextHex(background: Srgb): \"#000000\" | \"#ffffff\" {\n const white: Srgb = { r: 1, g: 1, b: 1 };\n const black: Srgb = { r: 0, g: 0, b: 0 };\n return wcagContrast(white, background) > wcagContrast(black, background)\n ? \"#ffffff\"\n : \"#000000\";\n}\n","import type { Srgb } from \"../types.js\";\nimport {\n APCA_MAIN_TRC,\n APCA_SRGB_R,\n APCA_SRGB_G,\n APCA_SRGB_B,\n APCA_NORM_BG,\n APCA_NORM_TXT,\n APCA_REV_TXT,\n APCA_REV_BG,\n APCA_BLK_THRS,\n APCA_BLK_CLMP,\n APCA_SCALE_BOW,\n APCA_SCALE_WOB,\n APCA_LO_BOW_OFFSET,\n APCA_LO_WOB_OFFSET,\n APCA_DELTA_Y_MIN,\n APCA_LO_CLIP,\n} from \"../constants.js\";\n\n/**\n * Compute APCA-W3 Lc (Lightness Contrast) between text and background.\n *\n * Returns a signed value in roughly [-108, +106]:\n * Positive = dark text on light background (BoW)\n * Negative = light text on dark background (WoB)\n * 0 = no meaningful contrast\n *\n * IMPORTANT: Uses its own linearization (simple 2.4 gamma),\n * NOT the IEC piecewise sRGB transfer function.\n */\n/**\n * Practical maximum APCA Lc magnitude used for normalization.\n * BoW tops out at ~+106, WoB at ~-108; we use 108 as a symmetric ceiling.\n */\nexport const APCA_LC_MAX = 108;\n\n/**\n * Normalize a raw APCA Lc value to the range [-1, +1].\n * +1 = maximum dark-on-light contrast (BoW)\n * -1 = maximum light-on-dark contrast (WoB)\n * 0 = no meaningful contrast\n */\nexport function apcaToNormalized(lc: number): number {\n return Math.max(-1, Math.min(1, lc / APCA_LC_MAX));\n}\n\n/**\n * Convert a normalized contrast value [-1, +1] back to a raw APCA Lc value.\n */\nexport function normalizedToApca(normalized: number): number {\n return normalized * APCA_LC_MAX;\n}\n\nexport function apcaContrast(textColor: Srgb, bgColor: Srgb): number {\n // Step 1: Linearize with simple 2.4 gamma and compute Y\n let txtY =\n APCA_SRGB_R * textColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * textColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * textColor.b ** APCA_MAIN_TRC;\n\n let bgY =\n APCA_SRGB_R * bgColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * bgColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * bgColor.b ** APCA_MAIN_TRC;\n\n // Step 2: Soft black clamp\n if (txtY < APCA_BLK_THRS) {\n txtY += (APCA_BLK_THRS - txtY) ** APCA_BLK_CLMP;\n }\n if (bgY < APCA_BLK_THRS) {\n bgY += (APCA_BLK_THRS - bgY) ** APCA_BLK_CLMP;\n }\n\n // Step 3: Delta Y check\n if (Math.abs(bgY - txtY) < APCA_DELTA_Y_MIN) return 0;\n\n // Step 4: Polarity-aware contrast\n let sapc: number;\n\n if (bgY > txtY) {\n // Dark text on light background (BoW)\n sapc = (bgY ** APCA_NORM_BG - txtY ** APCA_NORM_TXT) * APCA_SCALE_BOW;\n return sapc < APCA_LO_CLIP ? 0 : (sapc - APCA_LO_BOW_OFFSET) * 100;\n } else {\n // Light text on dark background (WoB)\n sapc = (bgY ** APCA_REV_BG - txtY ** APCA_REV_TXT) * APCA_SCALE_WOB;\n return sapc > -APCA_LO_CLIP ? 0 : (sapc + APCA_LO_WOB_OFFSET) * 100;\n }\n}\n","import type { Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD } from \"../constants.js\";\n\n/**\n * Linearly interpolate between two OKLCH colors.\n *\n * L and C are linearly interpolated. Hue uses shortest-arc interpolation.\n * Achromatic colors (C near zero) inherit the other color's hue to avoid\n * meaningless hue sweeps through the achromatic pole.\n */\nexport function mix(a: Oklch, b: Oklch, t: number): Oklch {\n const L = a.L + (b.L - a.L) * t;\n const C = a.C + (b.C - a.C) * t;\n\n // Resolve hue — handle achromatic inputs\n const aIsAchromatic = a.C < ACHROMATIC_THRESHOLD;\n const bIsAchromatic = b.C < ACHROMATIC_THRESHOLD;\n\n if (aIsAchromatic && bIsAchromatic) {\n return { L, C, h: 0 };\n }\n\n const hA = aIsAchromatic ? b.h : a.h;\n const hB = bIsAchromatic ? a.h : b.h;\n\n // Shortest-arc hue interpolation\n let delta = hB - hA;\n if (delta > 180) delta -= 360;\n if (delta < -180) delta += 360;\n\n let h = hA + delta * t;\n if (h < 0) h += 360;\n if (h >= 360) h -= 360;\n\n return { L, C, h };\n}\n","/**\n * Design constants — the values you tune by hand.\n *\n * Edit this file to adjust the perceptual behavior of every scale and\n * grading operation across the library.\n */\n\n// ── Scale defaults ────────────────────────────────────────────────────────────\n\n/**\n * Default number of steps in a generated scale.\n * Fixed at 26 — enough for a full design token set with fine lightness\n * increments without redundancy.\n */\nexport const DEFAULT_SCALE_STEPS = 26;\n\n/**\n * Default hue when none is provided.\n * 0° is the start of the OKLCH hue wheel (red region). Arbitrary but\n * deterministic — callers should always supply an explicit hue.\n */\nexport const DEFAULT_HUE = 0;\n\n// ── Dynamic range ─────────────────────────────────────────────────────────────\n\n/**\n * Lightest step's lightness when the whites slider is at 0.\n * slider 0 → L = MIN_LIGHTEST_L, slider 1 → L = 1.0 (pure white).\n */\nexport const MIN_LIGHTEST_L = 0.96;\n\n/**\n * Darkest step's lightness when the darks slider is at 0.\n * slider 0 → L = MAX_DARKEST_L, slider 1 → L = 0.0 (pure black).\n */\nexport const MAX_DARKEST_L = 0.16;\n\n// ── Hue grading ───────────────────────────────────────────────────────────────\n\n/**\n * How far global grading reaches into the scale from each end (0–1).\n * Light grading fades to zero at t = GRADING_REACH.\n * Dark grading fades to zero at t = 1 − GRADING_REACH.\n */\nexport const GRADING_REACH = 3 / 5;\n\n/** Maximum amount for global grading. Inputs above this are clamped. */\nexport const MAX_GRADING_AMOUNT = 0.25;\n\n/**\n * Fraction of the gamut boundary injected as chroma when global grading\n * is active. Ensures grading has a visible tinting effect even on\n * achromatic (chroma.amount = 0) palettes.\n *\n * Only global grading injects chroma — per-palette shift does not.\n */\nexport const GRADING_CHROMA_RATIO = 0.5;\n\n/**\n * How far per-palette hue shift reaches into the scale from each end (0–1).\n * Slightly wider than GRADING_REACH to give per-palette shifts more room.\n */\nexport const SHIFT_REACH = 2 / 3;\n\n/** Maximum amount for per-palette hue shift. Inputs above this are clamped. */\nexport const MAX_SHIFT_AMOUNT = 0.5;\n\n// ── Color difference ──────────────────────────────────────────────────────────\n\n/**\n * Just-noticeable difference threshold (deltaEOK).\n * Colors with distance below this are considered perceptually identical.\n * Used to classify color matches as exact vs. fallback.\n */\nexport const PERCEPTUAL_JND = 0.02;\n","/**\n * Global hue grading — shifts each palette's base hue toward shared\n * target hues at the light and dark scale endpoints.\n *\n * Light grading fades from full at the lightest step to zero at GRADING_REACH.\n * Dark grading fades from zero at (1 - GRADING_REACH) to full at the darkest step.\n * In the overlap zone, both shifts are additive (commutative).\n */\n\nimport {\n GRADING_REACH,\n MAX_GRADING_AMOUNT,\n SHIFT_REACH,\n MAX_SHIFT_AMOUNT,\n} from \"../config.js\";\n\nexport interface Grading {\n /** Hue grading for the light end of the scale. */\n readonly light?: { readonly hue: number; readonly amount: number };\n /** Hue grading for the dark end of the scale. */\n readonly dark?: { readonly hue: number; readonly amount: number };\n}\n\n/** Per-palette hue shift (one end only). */\nexport interface Shift {\n /** Target hue to shift toward (0–360°). */\n readonly hue: number;\n /** Blend strength (0–MAX_SHIFT_AMOUNT). */\n readonly amount: number;\n /** Which end to affect. `true` = light end, `false`/omitted = dark end (default). */\n readonly light?: boolean;\n}\n\n/**\n * Compute the graded hue at position `t` in the scale.\n *\n * Uses vector interpolation in Cartesian space rather than angular deltas\n * to avoid the shortest-arc discontinuity at 180° (where the direction\n * of rotation flips abruptly). Each grade's displacement is computed as\n * a vector offset from the base hue, and displacements are additive\n * (commutative — order doesn't matter).\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param grade Hue grade configuration.\n * @param reach How far each grade reaches into the scale (default: GRADING_REACH).\n * @param maxIntensity Maximum amount clamp (default: MAX_GRADING_AMOUNT).\n * @returns The graded hue in degrees (0–360).\n */\nexport function gradeHue(\n baseHue: number,\n t: number,\n grade: Grading,\n reach: number = GRADING_REACH,\n maxIntensity: number = MAX_GRADING_AMOUNT,\n): number {\n const li = Math.max(0, Math.min(maxIntensity, grade.light?.amount ?? 0));\n const di = Math.max(0, Math.min(maxIntensity, grade.dark?.amount ?? 0));\n\n // Early exit: no grading\n if (li === 0 && di === 0) return baseHue;\n\n // Light influence: cosine fade from 1 at t=0 to 0 at t=reach\n const lightInfluence =\n t <= reach ? 0.5 * (1 + Math.cos((Math.PI * t) / reach)) : 0;\n\n // Dark influence: cosine fade from 0 at t=(1-reach) to 1 at t=1\n const darkInfluence =\n t >= 1 - reach\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / reach))\n : 0;\n\n // Base hue as unit vector\n const toRad = Math.PI / 180;\n const baseRad = baseHue * toRad;\n const bx = Math.cos(baseRad);\n const by = Math.sin(baseRad);\n\n // Accumulate displacements in Cartesian space\n let dx = 0;\n let dy = 0;\n\n if (lightInfluence > 0 && li > 0) {\n const blend = lightInfluence * li;\n const lRad = (grade.light!.hue) * toRad;\n dx += blend * (Math.cos(lRad) - bx);\n dy += blend * (Math.sin(lRad) - by);\n }\n\n if (darkInfluence > 0 && di > 0) {\n const blend = darkInfluence * di;\n const dRad = (grade.dark!.hue) * toRad;\n dx += blend * (Math.cos(dRad) - bx);\n dy += blend * (Math.sin(dRad) - by);\n }\n\n // Reconstruct hue from displaced vector\n const rx = bx + dx;\n const ry = by + dy;\n\n // Safety: collapsed vector (opposite hues at exactly 50% blend)\n if (rx * rx + ry * ry < 1e-20) return baseHue;\n\n return ((Math.atan2(ry, rx) / toRad) + 360) % 360;\n}\n\n/**\n * Compute the combined grading influence at position `t` (0–1).\n *\n * Returns a scalar in [0, 1] representing how strongly global grading\n * affects position `t`. This is the maximum of the light and dark\n * cosine-fade envelopes, each scaled by its respective amount.\n *\n * Used by the chroma injection system to tint achromatic palettes\n * proportionally to grading strength.\n */\nexport function gradingInfluence(t: number, grading: Grading): number {\n const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));\n const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));\n\n if (li === 0 && di === 0) return 0;\n\n const lightInfluence =\n t <= GRADING_REACH ? 0.5 * (1 + Math.cos((Math.PI * t) / GRADING_REACH)) : 0;\n\n const darkInfluence =\n t >= 1 - GRADING_REACH\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / GRADING_REACH))\n : 0;\n\n const lightBlend = lightInfluence * (li / MAX_GRADING_AMOUNT);\n const darkBlend = darkInfluence * (di / MAX_GRADING_AMOUNT);\n\n return Math.max(lightBlend, darkBlend);\n}\n\n/**\n * Resolve the final hue at position `t`, applying local shift first, then global grading.\n *\n * This is the canonical composition: per-palette shift (using SHIFT_REACH /\n * MAX_SHIFT_AMOUNT) first, then global grading (using GRADING_REACH /\n * MAX_GRADING_AMOUNT) on top — so grading's influence is preserved at full\n * strength across all palettes, keeping them visually coherent.\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param globalGrade Global grading (shared across palettes), or undefined.\n * @param localGrade Local grading (per-palette, expanded from Shift), or undefined.\n * @returns The fully graded hue in degrees (0–360).\n */\nexport function resolveGradedHue(\n baseHue: number,\n t: number,\n globalGrade?: Grading,\n localGrade?: Grading,\n): number {\n let h = baseHue;\n if (localGrade) h = gradeHue(h, t, localGrade, SHIFT_REACH, MAX_SHIFT_AMOUNT);\n if (globalGrade) h = gradeHue(h, t, globalGrade);\n return h;\n}\n\n/**\n * Adapt a Shift into a one-sided Grading so it can be passed to gradeHue.\n *\n * The Shift interface is flat (hue, amount, light?) for ergonomic API use,\n * but gradeHue operates on the Grading shape (light/dark sub-objects).\n * This function bridges the two, activating only the requested end.\n *\n * @param hue Target hue for the active side (0–360°).\n * @param amount Blend strength for the active side.\n * @param light `true` = light end, `false`/omitted = dark end (default).\n */\nexport function buildOneSidedGrade(\n hue: number,\n amount: number,\n light: boolean = false,\n): Grading {\n return light\n ? { light: { hue, amount } }\n : { dark: { hue, amount } };\n}\n","/**\n * Dynamic range resolution — maps slider values (0–1) to OKLCH lightness\n * bounds for the lightest and darkest steps of a color scale.\n */\n\nimport { MIN_LIGHTEST_L, MAX_DARKEST_L } from \"../config.js\";\n\n/**\n * Resolve a whites slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MIN_LIGHTEST_L (0.96), slider 1 → L = 1.0 (pure white)\n */\nexport function resolveLightest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MIN_LIGHTEST_L + s * (1.0 - MIN_LIGHTEST_L);\n}\n\n/**\n * Resolve a darks slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MAX_DARKEST_L (0.16), slider 1 → L = 0.0 (pure black)\n */\nexport function resolveDarkest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MAX_DARKEST_L * (1 - s);\n}\n\n/**\n * Map an OKLCH lightness to a normalized scale position (0–1).\n * 0 = lightest end, 1 = darkest end.\n *\n * Inverse of the lightness interpolation inside generateScale.\n * Useful for deriving chromaPeak from a key color's lightness.\n */\nexport function lightnessToScaleT(L: number, lightestL: number, darkestL: number): number {\n const range = lightestL - darkestL;\n if (range <= 0) return 0.5;\n return Math.max(0, Math.min(1, (lightestL - L) / range));\n}\n","import type { Oklch } from \"../types.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\nimport type { Grading, Shift } from \"./hue-grade.js\";\nimport { resolveGradedHue, buildOneSidedGrade } from \"./hue-grade.js\";\nimport { resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport {\n DEFAULT_SCALE_STEPS,\n DEFAULT_HUE,\n GRADING_CHROMA_RATIO,\n GRADING_REACH,\n MAX_GRADING_AMOUNT,\n} from \"../config.js\";\n\ntype Gamut = \"srgb\" | \"display-p3\";\nconst toRad = Math.PI / 180;\n\n/**\n * Apply grading as an additive chroma overlay.\n *\n * Builds per-side chroma vectors pointing at the grading TARGET hues\n * (not the palette's hue) and adds them to the palette's existing\n * chroma in Cartesian (a, b) space. This ensures grading tints even\n * fully achromatic palettes without the base hue leaking through.\n */\nfunction applyGradingOverlay(\n C: number, h: number, L: number, t: number,\n grading: Grading, gamut: Gamut,\n): { C: number; h: number } {\n const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));\n const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));\n if (li === 0 && di === 0) return { C, h };\n\n // Per-side cosine-fade influences\n const lightFade = t <= GRADING_REACH\n ? 0.5 * (1 + Math.cos((Math.PI * t) / GRADING_REACH)) : 0;\n const darkFade = t >= 1 - GRADING_REACH\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / GRADING_REACH)) : 0;\n\n const lightBlend = lightFade * (li / MAX_GRADING_AMOUNT);\n const darkBlend = darkFade * (di / MAX_GRADING_AMOUNT);\n if (lightBlend === 0 && darkBlend === 0) return { C, h };\n\n // Palette's existing chroma as Cartesian vector\n const hRad = h * toRad;\n let a = C * Math.cos(hRad);\n let b = C * Math.sin(hRad);\n\n // Add overlay vectors at grading TARGET hues\n if (lightBlend > 0) {\n const lh = grading.light!.hue;\n const lRad = lh * toRad;\n const lC = maxChroma(L, lh, gamut) * GRADING_CHROMA_RATIO * lightBlend;\n a += lC * Math.cos(lRad);\n b += lC * Math.sin(lRad);\n }\n if (darkBlend > 0) {\n const dh = grading.dark!.hue;\n const dRad = dh * toRad;\n const dC = maxChroma(L, dh, gamut) * GRADING_CHROMA_RATIO * darkBlend;\n a += dC * Math.cos(dRad);\n b += dC * Math.sin(dRad);\n }\n\n // Convert back to polar\n let newC = Math.sqrt(a * a + b * b);\n let newH = ((Math.atan2(b, a) / toRad) + 360) % 360;\n\n // Clamp to gamut at the resulting hue\n newC = Math.min(newC, maxChroma(L, newH, gamut));\n\n return { C: newC, h: newH };\n}\n\nexport interface ScaleOptions {\n /**\n * Tonal range of the scale.\n * - `light`: how light the lightest step is (0–1). Default: 1.\n * 0 → L = MIN_LIGHTEST_L (0.96), 1 → L = 1.0 (pure white).\n * - `dark`: how dark the darkest step is (0–1). Default: 1.\n * 0 → L = MAX_DARKEST_L (0.16), 1 → L = 0.0 (pure black).\n */\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n /**\n * Hue angle in degrees (0–360). Default: DEFAULT_HUE (0).\n * Every step shares this base hue unless shifted by `grading` or `shift`.\n */\n readonly hue?: number;\n /**\n * Chroma shape of the scale.\n * - `amount`: how much of the available gamut to use (0–1). Default: 0.\n * 0 = fully achromatic (default), 1 = maximum in-gamut chroma at each lightness.\n * - `balance`: how chroma is distributed along the lightness range (0–1).\n * 0 = chroma concentrated toward the lightest end, 1 = toward the darkest end,\n * 0.5 = natural distribution (default, follows gamut boundary shape).\n */\n readonly chroma?: { readonly amount?: number; readonly balance?: number };\n /**\n * Global hue grading. When provided, the hue at each step is shifted\n * toward target hues based on position in the scale.\n * Light grading affects the lightest 3/5, dark grading affects the\n * darkest 3/5, with additive overlap in the middle fifth.\n */\n readonly grading?: Grading;\n /**\n * Per-palette hue shift. A one-sided grade applied before global\n * grading, with its own reach and strength limits (SHIFT_REACH,\n * MAX_SHIFT_AMOUNT). Defaults to the dark end; set `light: true` to target\n * the light end instead.\n */\n readonly shift?: Shift;\n /** Use Display P3 gamut instead of sRGB (default: false). */\n readonly isP3?: boolean;\n}\n\n/**\n * Generate an OKLCH color scale from lightest to darkest.\n *\n * Always produces DEFAULT_SCALE_STEPS colors. Chroma at each step is\n * proportional to the gamut boundary at that lightness, scaled by\n * `chroma.amount`. This guarantees every color is in-gamut — no fallbacks\n * needed — while producing a smooth, natural chroma curve.\n *\n * Use `contrast` to constrain the tonal range\n * (e.g. for scales that don't extend to pure white or pure black).\n *\n * Use `chroma.balance` to shift how chroma is distributed within the boundary.\n * The curve endpoints stay fixed while the distribution shifts smoothly.\n * The effective shift range is proportional to the headroom left by chroma.amount.\n */\nexport function generateScale(options: ScaleOptions = {}): Oklch[] {\n const {\n contrast,\n hue = DEFAULT_HUE,\n chroma,\n isP3 = false,\n grading,\n shift,\n } = options;\n const gamut = isP3 ? \"display-p3\" : \"srgb\";\n\n const steps = DEFAULT_SCALE_STEPS;\n const chromaRatio = chroma?.amount ?? 0;\n const chromaPeak = chroma?.balance ?? 0.5;\n const hueGrade = grading;\n const localHueGrade = shift ? buildOneSidedGrade(shift.hue, shift.amount, shift.light) : undefined;\n\n const ratio = Math.max(0, Math.min(1, chromaRatio));\n const peak = Math.max(0, Math.min(1, chromaPeak));\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n\n // Helper: resolve hue at position t (applies local shift first, then global grading)\n const hueAt = (t: number) => resolveGradedHue(hue, t, hueGrade, localHueGrade);\n\n // Fast path: skip peak skew logic when balance has no effect.\n // - peak === 0.5: already at the natural gamut peak, nothing to shift\n // - ratio === 0: no chroma at all, boundary shape is irrelevant\n // - ratio >= 1: inner triangle equals the boundary triangle, no headroom to slide\n if (peak === 0.5 || ratio === 0 || ratio >= 1) {\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n let h = hueAt(t);\n // Chroma is shaped by the base hue's boundary to keep the curve smooth.\n // The shifted hue's boundary is used as a final in-gamut clamp only —\n // this prevents spikes when the shifted hue has more available chroma\n // than the base (e.g. blue → pink passing through the purple region).\n let C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));\n\n if (hueGrade) {\n const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);\n C = overlay.C;\n h = overlay.h;\n }\n\n scale.push({ L, C, h });\n }\n return scale;\n }\n\n // ── Peak skew logic ──\n // Warp the parameter t so the boundary peak appears at a shifted position.\n // Endpoints stay fixed (warp(0)=0, warp(1)=1), only the peak moves.\n\n // 1. Sample boundary to find natural peak and valid shift range\n const N = 100;\n let peakT = 0.5;\n let peakBoundaryC = 0;\n const boundarySamples: { t: number; C: number }[] = [];\n\n for (let i = 0; i <= N; i++) {\n const t = i / N;\n const L = lightestL - t * (lightestL - darkestL);\n // Sample the base hue's boundary — the same reference used when building\n // the warp below. Using the shifted hue here would skew peakT and the\n // valid range toward a hue-specific boundary shape, inconsistent with\n // how chroma is actually computed in step 4.\n const C = maxChroma(L, hue, gamut);\n boundarySamples.push({ t, C });\n if (C > peakBoundaryC) {\n peakBoundaryC = C;\n peakT = t;\n }\n }\n\n // 2. Find valid range: where boundary can accommodate the inner peak height\n const innerPeakC = peakBoundaryC * ratio;\n let validMinT = peakT;\n let validMaxT = peakT;\n\n for (const { t, C } of boundarySamples) {\n if (C >= innerPeakC - 1e-6) {\n if (t < validMinT) validMinT = t;\n if (t > validMaxT) validMaxT = t;\n }\n }\n\n // 3. Map chroma.balance (0–1) to valid range, normalized so 0.5 → peakT\n let targetT: number;\n if (peak <= 0.5) {\n targetT = validMinT + (peak / 0.5) * (peakT - validMinT);\n } else {\n targetT = peakT + ((peak - 0.5) / 0.5) * (validMaxT - peakT);\n }\n\n // Safety: if the piecewise mapping produces a degenerate targetT (outside\n // (0, 1)), fall back to the natural peak. This can occur at floating-point\n // boundaries rather than from any single expected input combination.\n if (targetT <= 0 || targetT >= 1) {\n targetT = peakT;\n }\n\n // 4. Build scale with piecewise-linear warp: targetT → peakT\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n let h = hueAt(t);\n\n // Piecewise-linear warp: maps 0→0, targetT→peakT, 1→1.\n // Two segments scale t independently so the boundary peak (at peakT in\n // warp space) lands at targetT in the output — endpoints stay fixed.\n let tWarped: number;\n if (t <= targetT) {\n tWarped = t * (peakT / targetT);\n } else {\n tWarped = peakT + (t - targetT) * ((1 - peakT) / (1 - targetT));\n }\n\n const Lwarped = lightestL - tWarped * (lightestL - darkestL);\n // Use the base hue for the warped chroma lookup — consistent with step 1\n // and the fast path. The warp is purely a lightness operation; mixing in\n // the shifted hue at tWarped would introduce cross-position hue artifacts.\n const warpedC = maxChroma(Lwarped, hue, gamut) * ratio;\n // Clamp to the shifted hue's actual boundary at this L: the in-gamut\n // guarantee for the final color { L, C, h }.\n const boundaryC = maxChroma(L, h, gamut);\n let C = Math.min(warpedC, boundaryC);\n\n if (hueGrade) {\n const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);\n C = overlay.C;\n h = overlay.h;\n }\n\n scale.push({ L, C, h });\n }\n\n return scale;\n}\n","import type { Hex, Oklch, Gamut } from \"../types.js\";\nimport {\n hexToOklch,\n oklchToSrgb,\n oklchToP3,\n oklchToHex,\n} from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"../gamut/check.js\";\nimport { gamutMap } from \"../gamut/map.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\n\n/**\n * Result of resolving a color into scale-ready parameters.\n */\nexport interface ResolvedColor {\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Hex representation (sRGB-clamped if the resolved color exceeds sRGB). */\n readonly hex: Hex;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n /** Chroma lost during gamut mapping (0 if in-gamut). */\n readonly chromaShift: number;\n /** Hue from the resolved color. */\n readonly hue: number;\n /** Chroma as a fraction of the gamut boundary at this L/h (0–1). */\n readonly chromaRatio: number;\n}\n\n/**\n * Resolve a color (hex or OKLCH) into scale-ready parameters.\n *\n * If the color is outside the target gamut, it is perceptually mapped to the\n * nearest in-gamut color (chroma reduction at fixed L and h). The result\n * includes the derived hue and chromaRatio.\n *\n * Hex input is always valid sRGB, so `wasRemapped` will be false for hex\n * with gamut=\"srgb\". OKLCH input may be out of gamut and will be mapped.\n *\n * @param input A hex string (#RGB, #RRGGBB) or an OKLCH color.\n * @param isP3 Use Display P3 gamut instead of sRGB (default: false).\n */\nexport function resolveColor(\n input: Hex | Oklch,\n isP3: boolean = false,\n): ResolvedColor {\n const gamut: Gamut = isP3 ? \"display-p3\" : \"srgb\";\n const isHex = typeof input === \"string\";\n const original: Oklch = isHex ? hexToOklch(input) : input;\n\n // Hex encodes valid sRGB by definition, and sRGB ⊂ P3, so hex input\n // is always in-gamut for both supported gamuts. Skipping the round-trip\n // check avoids false negatives from floating-point drift.\n let inGamut: boolean;\n if (isHex) {\n inGamut = true;\n } else {\n const rgb =\n gamut === \"display-p3\" ? oklchToP3(original) : oklchToSrgb(original);\n inGamut = isInGamut(rgb);\n }\n\n const oklch = inGamut ? original : gamutMap(original, gamut);\n\n const boundary = maxChroma(oklch.L, oklch.h, gamut);\n const chromaRatio = boundary > 0 ? oklch.C / boundary : 0;\n\n return {\n oklch,\n hex: oklchToHex(oklch),\n wasRemapped: !inGamut,\n original,\n chromaShift: original.C - oklch.C,\n hue: oklch.h,\n chromaRatio: Math.min(1, chromaRatio),\n };\n}\n","import type { Hex, Oklch } from \"../types.js\";\nimport { resolveColor } from \"./resolve-color.js\";\nimport { lightnessToScaleT, resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport { DEFAULT_SCALE_STEPS } from \"../config.js\";\n\n/**\n * The result of deriving scale parameters from a key color.\n *\n * Spread `hue` and `chroma` directly into ScaleOptions, then use\n * `stepIndex` to locate the key color's position in the generated scale.\n */\nexport interface KeyColorResult {\n /** Derived hue angle — use directly as ScaleOptions.hue. */\n readonly hue: number;\n /**\n * Derived chroma shape — use directly as ScaleOptions.chroma.\n * - `amount`: how saturated the scale is (0–1, relative to gamut boundary).\n * - `balance`: where in the scale the key color's lightness falls (0 = lightest, 1 = darkest).\n */\n readonly chroma: { readonly amount: number; readonly balance: number };\n /** The step index in a scale of `steps` length where this color lands. */\n readonly stepIndex: number;\n /** Hex representation of the resolved color (sRGB-clamped if necessary). */\n readonly hex: Hex;\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n}\n\n/**\n * Derive scale parameters from a known color.\n *\n * Given a hex or OKLCH color, returns the `hue` and `chroma` values\n * ready to spread into ScaleOptions. The chroma balance is derived from\n * where the color's lightness falls within the scale's lightness range,\n * so the chroma distribution is centered around the key color's position.\n *\n * @param color A hex string (#RGB or #RRGGBB) or an OKLCH color object.\n * @param options Scale context — must match the ScaleOptions you will use.\n * `contrast` values are slider values (0–1), same as ScaleOptions.contrast.\n * `steps` is the number of steps in the scale (default: 26).\n *\n * @example\n * const key = keyColor('#3B82F6');\n * const scale = generateScale({ hue: key.hue, chroma: key.chroma });\n * const matchedHex = oklchToHex(scale[key.stepIndex]);\n */\nexport function keyColor(\n color: Hex | Oklch,\n options?: {\n readonly isP3?: boolean;\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n readonly steps?: number;\n },\n): KeyColorResult {\n const { isP3 = false, contrast, steps = DEFAULT_SCALE_STEPS } = options ?? {};\n const resolved = resolveColor(color, isP3);\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n const balance = lightnessToScaleT(resolved.oklch.L, lightestL, darkestL);\n const stepIndex = Math.round(balance * Math.max(0, steps - 1));\n\n return {\n hue: resolved.hue,\n chroma: { amount: resolved.chromaRatio, balance },\n stepIndex,\n hex: resolved.hex,\n oklch: resolved.oklch,\n wasRemapped: resolved.wasRemapped,\n original: resolved.original,\n };\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -4,18 +4,18 @@ export { linearSrgbToOklab, oklabToLinearSrgb } from "./conversions/linear-srgb.
4
4
  export { linearP3ToOklab, oklabToLinearP3 } from "./conversions/linear-p3.js";
5
5
  export { srgbToLinearSrgb, linearSrgbToSrgb, srgbChannelToLinear, linearChannelToSrgb, } from "./conversions/srgb.js";
6
6
  export { hexToSrgb, srgbToHex } from "./conversions/hex.js";
7
- export { srgbToOklch, oklchToSrgb, srgbToOklab, oklabToSrgb, hexToOklch, oklchToHex, p3ToOklch, oklchToP3, } from "./conversions/pipeline.js";
8
- export { isInGamut, clampSrgb } from "./gamut/check.js";
7
+ export { srgbToOklch, oklchToSrgb, srgbToOklab, oklabToSrgb, hexToOklch, oklchToHex, p3ToOklch, oklchToP3, oklchToP3Css, } from "./conversions/pipeline.js";
8
+ export { isInGamut, clampSrgb, clampP3 } from "./gamut/check.js";
9
9
  export { gamutMap } from "./gamut/map.js";
10
10
  export { maxChroma } from "./gamut/max-chroma.js";
11
11
  export { wcagLuminance, wcagContrast, contrastTextHex } from "./contrast/wcag.js";
12
12
  export { apcaContrast, apcaToNormalized, normalizedToApca, APCA_LC_MAX } from "./contrast/apca.js";
13
13
  export { deltaEOK, deltaEOKLab } from "./color/difference.js";
14
14
  export { mix } from "./color/interpolation.js";
15
- export { DEFAULT_SCALE_STEPS, DEFAULT_HUE, MIN_LIGHTEST_L, MAX_DARKEST_L, GRADING_REACH, MAX_GRADING_AMOUNT, SHIFT_REACH, MAX_SHIFT_AMOUNT, PERCEPTUAL_JND, } from "./config.js";
15
+ export { DEFAULT_SCALE_STEPS, DEFAULT_HUE, MIN_LIGHTEST_L, MAX_DARKEST_L, GRADING_REACH, MAX_GRADING_AMOUNT, GRADING_CHROMA_RATIO, SHIFT_REACH, MAX_SHIFT_AMOUNT, PERCEPTUAL_JND, } from "./config.js";
16
16
  export { generateScale } from "./scale/generate.js";
17
17
  export type { ScaleOptions } from "./scale/generate.js";
18
- export { gradeHue, resolveGradedHue, buildOneSidedGrade } from "./scale/hue-grade.js";
18
+ export { gradeHue, resolveGradedHue, buildOneSidedGrade, gradingInfluence } from "./scale/hue-grade.js";
19
19
  export type { Grading, Shift } from "./scale/hue-grade.js";
20
20
  export { keyColor } from "./scale/key-color.js";
21
21
  export type { KeyColorResult } from "./scale/key-color.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,GACV,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGnG,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAG/C,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,WAAW,EACX,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACtF,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAG7E,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC9E,OAAO,EACL,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAG5D,OAAO,EACL,WAAW,EACX,WAAW,EACX,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,YAAY,GACb,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAGlD,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAClF,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGnG,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAG/C,OAAO,EACL,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,aAAa,EACb,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,WAAW,EACX,gBAAgB,EAChB,cAAc,GACf,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxG,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -209,6 +209,13 @@ function p3ToOklch(color) {
209
209
  function oklchToP3(color) {
210
210
  return linearSrgbToSrgb(oklabToLinearP3(oklchToOklab(color)));
211
211
  }
212
+ function oklchToP3Css(color) {
213
+ const p3 = oklchToP3(color);
214
+ const r = Math.max(0, Math.min(1, p3.r)).toFixed(4);
215
+ const g = Math.max(0, Math.min(1, p3.g)).toFixed(4);
216
+ const b = Math.max(0, Math.min(1, p3.b)).toFixed(4);
217
+ return `color(display-p3 ${r} ${g} ${b})`;
218
+ }
212
219
 
213
220
  // src/gamut/check.ts
214
221
  function isInGamut(color) {
@@ -221,6 +228,7 @@ function clampSrgb(color) {
221
228
  b: Math.max(0, Math.min(1, color.b))
222
229
  };
223
230
  }
231
+ var clampP3 = clampSrgb;
224
232
 
225
233
  // src/color/difference.ts
226
234
  function deltaEOK(a, b) {
@@ -356,6 +364,7 @@ var MIN_LIGHTEST_L = 0.96;
356
364
  var MAX_DARKEST_L = 0.16;
357
365
  var GRADING_REACH = 3 / 5;
358
366
  var MAX_GRADING_AMOUNT = 0.25;
367
+ var GRADING_CHROMA_RATIO = 0.5;
359
368
  var SHIFT_REACH = 2 / 3;
360
369
  var MAX_SHIFT_AMOUNT = 0.5;
361
370
  var PERCEPTUAL_JND = 0.02;
@@ -367,28 +376,38 @@ function gradeHue(baseHue, t, grade, reach = GRADING_REACH, maxIntensity = MAX_G
367
376
  if (li === 0 && di === 0) return baseHue;
368
377
  const lightInfluence = t <= reach ? 0.5 * (1 + Math.cos(Math.PI * t / reach)) : 0;
369
378
  const darkInfluence = t >= 1 - reach ? 0.5 * (1 + Math.cos(Math.PI * (1 - t) / reach)) : 0;
370
- const toRad = Math.PI / 180;
371
- const baseRad = baseHue * toRad;
379
+ const toRad2 = Math.PI / 180;
380
+ const baseRad = baseHue * toRad2;
372
381
  const bx = Math.cos(baseRad);
373
382
  const by = Math.sin(baseRad);
374
383
  let dx = 0;
375
384
  let dy = 0;
376
385
  if (lightInfluence > 0 && li > 0) {
377
386
  const blend = lightInfluence * li;
378
- const lRad = grade.light.hue * toRad;
387
+ const lRad = grade.light.hue * toRad2;
379
388
  dx += blend * (Math.cos(lRad) - bx);
380
389
  dy += blend * (Math.sin(lRad) - by);
381
390
  }
382
391
  if (darkInfluence > 0 && di > 0) {
383
392
  const blend = darkInfluence * di;
384
- const dRad = grade.dark.hue * toRad;
393
+ const dRad = grade.dark.hue * toRad2;
385
394
  dx += blend * (Math.cos(dRad) - bx);
386
395
  dy += blend * (Math.sin(dRad) - by);
387
396
  }
388
397
  const rx = bx + dx;
389
398
  const ry = by + dy;
390
399
  if (rx * rx + ry * ry < 1e-20) return baseHue;
391
- return (Math.atan2(ry, rx) / toRad + 360) % 360;
400
+ return (Math.atan2(ry, rx) / toRad2 + 360) % 360;
401
+ }
402
+ function gradingInfluence(t, grading) {
403
+ const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));
404
+ const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));
405
+ if (li === 0 && di === 0) return 0;
406
+ const lightInfluence = t <= GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * t / GRADING_REACH)) : 0;
407
+ const darkInfluence = t >= 1 - GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * (1 - t) / GRADING_REACH)) : 0;
408
+ const lightBlend = lightInfluence * (li / MAX_GRADING_AMOUNT);
409
+ const darkBlend = darkInfluence * (di / MAX_GRADING_AMOUNT);
410
+ return Math.max(lightBlend, darkBlend);
392
411
  }
393
412
  function resolveGradedHue(baseHue, t, globalGrade, localGrade) {
394
413
  let h = baseHue;
@@ -416,6 +435,38 @@ function lightnessToScaleT(L, lightestL, darkestL) {
416
435
  }
417
436
 
418
437
  // src/scale/generate.ts
438
+ var toRad = Math.PI / 180;
439
+ function applyGradingOverlay(C, h, L, t, grading, gamut) {
440
+ const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));
441
+ const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));
442
+ if (li === 0 && di === 0) return { C, h };
443
+ const lightFade = t <= GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * t / GRADING_REACH)) : 0;
444
+ const darkFade = t >= 1 - GRADING_REACH ? 0.5 * (1 + Math.cos(Math.PI * (1 - t) / GRADING_REACH)) : 0;
445
+ const lightBlend = lightFade * (li / MAX_GRADING_AMOUNT);
446
+ const darkBlend = darkFade * (di / MAX_GRADING_AMOUNT);
447
+ if (lightBlend === 0 && darkBlend === 0) return { C, h };
448
+ const hRad = h * toRad;
449
+ let a = C * Math.cos(hRad);
450
+ let b = C * Math.sin(hRad);
451
+ if (lightBlend > 0) {
452
+ const lh = grading.light.hue;
453
+ const lRad = lh * toRad;
454
+ const lC = maxChroma(L, lh, gamut) * GRADING_CHROMA_RATIO * lightBlend;
455
+ a += lC * Math.cos(lRad);
456
+ b += lC * Math.sin(lRad);
457
+ }
458
+ if (darkBlend > 0) {
459
+ const dh = grading.dark.hue;
460
+ const dRad = dh * toRad;
461
+ const dC = maxChroma(L, dh, gamut) * GRADING_CHROMA_RATIO * darkBlend;
462
+ a += dC * Math.cos(dRad);
463
+ b += dC * Math.sin(dRad);
464
+ }
465
+ let newC = Math.sqrt(a * a + b * b);
466
+ let newH = (Math.atan2(b, a) / toRad + 360) % 360;
467
+ newC = Math.min(newC, maxChroma(L, newH, gamut));
468
+ return { C: newC, h: newH };
469
+ }
419
470
  function generateScale(options = {}) {
420
471
  const {
421
472
  contrast,
@@ -441,8 +492,13 @@ function generateScale(options = {}) {
441
492
  for (let i = 0; i < steps; i++) {
442
493
  const t = i / (steps - 1);
443
494
  const L = lightestL - t * (lightestL - darkestL);
444
- const h = hueAt(t);
445
- const C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));
495
+ let h = hueAt(t);
496
+ let C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));
497
+ if (hueGrade) {
498
+ const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);
499
+ C = overlay.C;
500
+ h = overlay.h;
501
+ }
446
502
  scale2.push({ L, C, h });
447
503
  }
448
504
  return scale2;
@@ -483,7 +539,7 @@ function generateScale(options = {}) {
483
539
  for (let i = 0; i < steps; i++) {
484
540
  const t = i / (steps - 1);
485
541
  const L = lightestL - t * (lightestL - darkestL);
486
- const h = hueAt(t);
542
+ let h = hueAt(t);
487
543
  let tWarped;
488
544
  if (t <= targetT) {
489
545
  tWarped = t * (peakT / targetT);
@@ -493,7 +549,12 @@ function generateScale(options = {}) {
493
549
  const Lwarped = lightestL - tWarped * (lightestL - darkestL);
494
550
  const warpedC = maxChroma(Lwarped, hue, gamut) * ratio;
495
551
  const boundaryC = maxChroma(L, h, gamut);
496
- const C = Math.min(warpedC, boundaryC);
552
+ let C = Math.min(warpedC, boundaryC);
553
+ if (hueGrade) {
554
+ const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);
555
+ C = overlay.C;
556
+ h = overlay.h;
557
+ }
497
558
  scale.push({ L, C, h });
498
559
  }
499
560
  return scale;
@@ -544,6 +605,6 @@ function keyColor(color, options) {
544
605
  };
545
606
  }
546
607
 
547
- export { APCA_LC_MAX, DEFAULT_HUE, DEFAULT_SCALE_STEPS, GRADING_REACH, MAX_DARKEST_L, MAX_GRADING_AMOUNT, MAX_SHIFT_AMOUNT, MIN_LIGHTEST_L, PERCEPTUAL_JND, SHIFT_REACH, apcaContrast, apcaToNormalized, buildOneSidedGrade, clampSrgb, contrastTextHex, deltaEOK, deltaEOKLab, gamutMap, generateScale, gradeHue, hexToOklch, hexToSrgb, isInGamut, keyColor, lightnessToScaleT, linearChannelToSrgb, linearP3ToOklab, linearSrgbToOklab, linearSrgbToSrgb, maxChroma, mix, normalizedToApca, oklabToLinearP3, oklabToLinearSrgb, oklabToOklch, oklabToSrgb, oklchToHex, oklchToOklab, oklchToP3, oklchToSrgb, p3ToOklch, resolveGradedHue, srgbChannelToLinear, srgbToHex, srgbToLinearSrgb, srgbToOklab, srgbToOklch, wcagContrast, wcagLuminance };
608
+ export { APCA_LC_MAX, DEFAULT_HUE, DEFAULT_SCALE_STEPS, GRADING_CHROMA_RATIO, GRADING_REACH, MAX_DARKEST_L, MAX_GRADING_AMOUNT, MAX_SHIFT_AMOUNT, MIN_LIGHTEST_L, PERCEPTUAL_JND, SHIFT_REACH, apcaContrast, apcaToNormalized, buildOneSidedGrade, clampP3, clampSrgb, contrastTextHex, deltaEOK, deltaEOKLab, gamutMap, generateScale, gradeHue, gradingInfluence, hexToOklch, hexToSrgb, isInGamut, keyColor, lightnessToScaleT, linearChannelToSrgb, linearP3ToOklab, linearSrgbToOklab, linearSrgbToSrgb, maxChroma, mix, normalizedToApca, oklabToLinearP3, oklabToLinearSrgb, oklabToOklch, oklabToSrgb, oklchToHex, oklchToOklab, oklchToP3, oklchToP3Css, oklchToSrgb, p3ToOklch, resolveGradedHue, srgbChannelToLinear, srgbToHex, srgbToLinearSrgb, srgbToOklab, srgbToOklch, wcagContrast, wcagLuminance };
548
609
  //# sourceMappingURL=index.js.map
549
610
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts","../src/conversions/oklab.ts","../src/conversions/linear-srgb.ts","../src/conversions/linear-p3.ts","../src/conversions/srgb.ts","../src/conversions/hex.ts","../src/conversions/pipeline.ts","../src/gamut/check.ts","../src/color/difference.ts","../src/gamut/map.ts","../src/gamut/max-chroma.ts","../src/contrast/wcag.ts","../src/contrast/apca.ts","../src/color/interpolation.ts","../src/config.ts","../src/scale/hue-grade.ts","../src/scale/dynamic-range.ts","../src/scale/generate.ts","../src/scale/resolve-color.ts","../src/scale/key-color.ts"],"names":["scale"],"mappings":"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","file":"index.js","sourcesContent":["// ── sRGB Gamma Transfer (IEC 61966-2-1) ──\n\nexport const SRGB_GAMMA_THRESHOLD = 0.04045;\nexport const SRGB_GAMMA_THRESHOLD_LINEAR = 0.0031308;\nexport const SRGB_GAMMA_SLOPE = 12.92;\nexport const SRGB_GAMMA_EXPONENT = 2.4;\nexport const SRGB_GAMMA_OFFSET = 0.055;\nexport const SRGB_GAMMA_SCALE = 1.055;\n\n// ── Ottosson M1: Linear sRGB → LMS ──\n\nexport const LINEAR_SRGB_TO_LMS = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n] as const;\n\n// ── Ottosson M2: LMS′ (cube-root) → OKLAB ──\n\nexport const LMS_PRIME_TO_OKLAB = [\n [+0.2104542553, +0.7936177850, -0.0040720468],\n [+1.9779984951, -2.4285922050, +0.4505937099],\n [+0.0259040371, +0.7827717662, -0.8086757660],\n] as const;\n\n// ── Inverse M2: OKLAB → LMS′ ──\n\nexport const OKLAB_TO_LMS_PRIME = [\n [1.0000000000, +0.3963377774, +0.2158037573],\n [1.0000000000, -0.1055613458, -0.0638541728],\n [1.0000000000, -0.0894841775, -1.2914855480],\n] as const;\n\n// ── Inverse M1: LMS → Linear sRGB ──\n\nexport const LMS_TO_LINEAR_SRGB = [\n [+4.0767416621, -3.3077115913, +0.2309699292],\n [-1.2684380046, +2.6097574011, -0.3413193965],\n [-0.0041960863, -0.7034186147, +1.7076147010],\n] as const;\n\n// ── Display P3 M1: Linear Display P3 → LMS ──\n// Derived: XYZ_to_LMS × P3_to_XYZ, where XYZ_to_LMS = M1_srgb × inv(sRGB_to_XYZ)\n\nexport const LINEAR_P3_TO_LMS = [\n [+0.4813791595, +0.4621155872, +0.0565406381],\n [+0.2288319169, +0.6532167007, +0.1179528072],\n [+0.0839457149, +0.2241651052, +0.6918912614],\n] as const;\n\n// ── Inverse P3 M1: LMS → Linear Display P3 ──\n\nexport const LMS_TO_LINEAR_P3 = [\n [+3.1277694390, -2.2570600176, +0.1291828502],\n [-1.0910091977, +2.4133065499, -0.3222615148],\n [-0.0260108068, -0.5080402362, +1.5340494942],\n] as const;\n\n// ── Gamut Mapping ──\n\nexport const GAMUT_EPSILON = 1e-6;\nexport const GAMUT_MAP_JND = 0.02;\nexport const GAMUT_MAP_EPSILON = 1e-4;\nexport const GAMUT_MAP_MAX_ITERATIONS = 50;\n\n// ── Achromatic Threshold ──\n\nexport const ACHROMATIC_THRESHOLD = 1e-10;\n\n// ── WCAG 2.x Luminance Coefficients ──\n\nexport const WCAG_R = 0.2126;\nexport const WCAG_G = 0.7152;\nexport const WCAG_B = 0.0722;\n\n// ── APCA-W3 (SA98G) Constants ──\n\nexport const APCA_MAIN_TRC = 2.4;\nexport const APCA_SRGB_R = 0.2126729;\nexport const APCA_SRGB_G = 0.7151522;\nexport const APCA_SRGB_B = 0.0721750;\nexport const APCA_NORM_BG = 0.56;\nexport const APCA_NORM_TXT = 0.57;\nexport const APCA_REV_TXT = 0.62;\nexport const APCA_REV_BG = 0.65;\nexport const APCA_BLK_THRS = 0.022;\nexport const APCA_BLK_CLMP = 1.414;\nexport const APCA_SCALE_BOW = 1.14;\nexport const APCA_SCALE_WOB = 1.14;\nexport const APCA_LO_BOW_OFFSET = 0.027;\nexport const APCA_LO_WOB_OFFSET = 0.027;\nexport const APCA_DELTA_Y_MIN = 0.0005;\nexport const APCA_LO_CLIP = 0.1;\n\n// ── Angle Math ──\n\nexport const DEG_TO_RAD = Math.PI / 180;\nexport const RAD_TO_DEG = 180 / Math.PI;\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD, DEG_TO_RAD, RAD_TO_DEG } from \"../constants.js\";\n\n/** Convert OKLAB (cartesian) to OKLCH (cylindrical). Achromatic colors get h=0. */\nexport function oklabToOklch(lab: Oklab): Oklch {\n const C = Math.sqrt(lab.a * lab.a + lab.b * lab.b);\n\n if (C < ACHROMATIC_THRESHOLD) {\n return { L: lab.L, C: 0, h: 0 };\n }\n\n let h = Math.atan2(lab.b, lab.a) * RAD_TO_DEG;\n if (h < 0) h += 360;\n\n return { L: lab.L, C, h };\n}\n\n/** Convert OKLCH (cylindrical) to OKLAB (cartesian). */\nexport function oklchToOklab(lch: Oklch): Oklab {\n const hRad = lch.h * DEG_TO_RAD;\n return {\n L: lch.L,\n a: lch.C * Math.cos(hRad),\n b: lch.C * Math.sin(hRad),\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_SRGB_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_SRGB,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear sRGB to OKLAB via Ottosson's direct M1/M2 matrices. */\nexport function linearSrgbToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear sRGB → LMS\n const l =\n LINEAR_SRGB_TO_LMS[0][0] * color.r +\n LINEAR_SRGB_TO_LMS[0][1] * color.g +\n LINEAR_SRGB_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_SRGB_TO_LMS[1][0] * color.r +\n LINEAR_SRGB_TO_LMS[1][1] * color.g +\n LINEAR_SRGB_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_SRGB_TO_LMS[2][0] * color.r +\n LINEAR_SRGB_TO_LMS[2][1] * color.g +\n LINEAR_SRGB_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear sRGB via inverse M2/M1 matrices. */\nexport function oklabToLinearSrgb(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear sRGB\n return {\n r:\n LMS_TO_LINEAR_SRGB[0][0] * l +\n LMS_TO_LINEAR_SRGB[0][1] * m +\n LMS_TO_LINEAR_SRGB[0][2] * s,\n g:\n LMS_TO_LINEAR_SRGB[1][0] * l +\n LMS_TO_LINEAR_SRGB[1][1] * m +\n LMS_TO_LINEAR_SRGB[1][2] * s,\n b:\n LMS_TO_LINEAR_SRGB[2][0] * l +\n LMS_TO_LINEAR_SRGB[2][1] * m +\n LMS_TO_LINEAR_SRGB[2][2] * s,\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_P3_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_P3,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear Display P3 to OKLAB via P3-specific M1 + shared M2. */\nexport function linearP3ToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear P3 → LMS\n const l =\n LINEAR_P3_TO_LMS[0][0] * color.r +\n LINEAR_P3_TO_LMS[0][1] * color.g +\n LINEAR_P3_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_P3_TO_LMS[1][0] * color.r +\n LINEAR_P3_TO_LMS[1][1] * color.g +\n LINEAR_P3_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_P3_TO_LMS[2][0] * color.r +\n LINEAR_P3_TO_LMS[2][1] * color.g +\n LINEAR_P3_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB (shared M2)\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear Display P3 via shared inverse M2 + P3-specific inverse M1. */\nexport function oklabToLinearP3(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′ (shared inverse M2)\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear P3\n return {\n r:\n LMS_TO_LINEAR_P3[0][0] * l +\n LMS_TO_LINEAR_P3[0][1] * m +\n LMS_TO_LINEAR_P3[0][2] * s,\n g:\n LMS_TO_LINEAR_P3[1][0] * l +\n LMS_TO_LINEAR_P3[1][1] * m +\n LMS_TO_LINEAR_P3[1][2] * s,\n b:\n LMS_TO_LINEAR_P3[2][0] * l +\n LMS_TO_LINEAR_P3[2][1] * m +\n LMS_TO_LINEAR_P3[2][2] * s,\n };\n}\n","import type { LinearSrgb, Srgb } from \"../types.js\";\nimport {\n SRGB_GAMMA_EXPONENT,\n SRGB_GAMMA_OFFSET,\n SRGB_GAMMA_SCALE,\n SRGB_GAMMA_SLOPE,\n SRGB_GAMMA_THRESHOLD,\n SRGB_GAMMA_THRESHOLD_LINEAR,\n} from \"../constants.js\";\n\n/** Decode a single sRGB gamma-encoded channel to linear light. */\nexport function srgbChannelToLinear(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD\n ? value / SRGB_GAMMA_SLOPE\n : ((value + SRGB_GAMMA_OFFSET) / SRGB_GAMMA_SCALE) ** SRGB_GAMMA_EXPONENT;\n}\n\n/** Encode a single linear light channel to sRGB gamma. */\nexport function linearChannelToSrgb(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD_LINEAR\n ? value * SRGB_GAMMA_SLOPE\n : SRGB_GAMMA_SCALE * value ** (1 / SRGB_GAMMA_EXPONENT) - SRGB_GAMMA_OFFSET;\n}\n\n/** Convert an sRGB color to Linear sRGB. */\nexport function srgbToLinearSrgb(color: Srgb): LinearSrgb {\n return {\n r: srgbChannelToLinear(color.r),\n g: srgbChannelToLinear(color.g),\n b: srgbChannelToLinear(color.b),\n };\n}\n\n/** Convert a Linear sRGB color to sRGB. */\nexport function linearSrgbToSrgb(color: LinearSrgb): Srgb {\n return {\n r: linearChannelToSrgb(color.r),\n g: linearChannelToSrgb(color.g),\n b: linearChannelToSrgb(color.b),\n };\n}\n","import type { Hex, Srgb } from \"../types.js\";\n\n/** Parse a hex color string (#RGB, #RRGGBB, or bare) to sRGB [0,1]. */\nexport function hexToSrgb(hex: string): Srgb {\n let h = hex.startsWith(\"#\") ? hex.slice(1) : hex;\n\n if (h.length === 3) {\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];\n }\n\n const n = parseInt(h, 16);\n return {\n r: ((n >> 16) & 0xff) / 255,\n g: ((n >> 8) & 0xff) / 255,\n b: (n & 0xff) / 255,\n };\n}\n\n/** Convert sRGB [0,1] to lowercase hex string (#rrggbb). Clamps to [0,1]. */\nexport function srgbToHex(color: Srgb): Hex {\n const r = Math.round(Math.max(0, Math.min(1, color.r)) * 255);\n const g = Math.round(Math.max(0, Math.min(1, color.g)) * 255);\n const b = Math.round(Math.max(0, Math.min(1, color.b)) * 255);\n return `#${((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1)}` as Hex;\n}\n","import type { Hex, Oklab, Oklch, Srgb } from \"../types.js\";\nimport { oklabToOklch, oklchToOklab } from \"./oklab.js\";\nimport { linearSrgbToOklab, oklabToLinearSrgb } from \"./linear-srgb.js\";\nimport { linearP3ToOklab, oklabToLinearP3 } from \"./linear-p3.js\";\nimport { linearSrgbToSrgb, srgbToLinearSrgb } from \"./srgb.js\";\nimport { hexToSrgb, srgbToHex } from \"./hex.js\";\n\n/** Convert sRGB to OKLCH. */\nexport function srgbToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearSrgbToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to sRGB. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToSrgb(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(oklchToOklab(color)));\n}\n\n/** Convert sRGB to OKLAB. */\nexport function srgbToOklab(color: Srgb): Oklab {\n return linearSrgbToOklab(srgbToLinearSrgb(color));\n}\n\n/** Convert OKLAB to sRGB. May produce out-of-gamut values. */\nexport function oklabToSrgb(color: Oklab): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(color));\n}\n\n/** Convert hex to OKLCH. */\nexport function hexToOklch(hex: string): Oklch {\n return srgbToOklch(hexToSrgb(hex));\n}\n\n/** Convert OKLCH to hex. Clamps to sRGB gamut before hex encoding. */\nexport function oklchToHex(color: Oklch): Hex {\n const srgb = oklchToSrgb(color);\n return srgbToHex({\n r: Math.max(0, Math.min(1, srgb.r)),\n g: Math.max(0, Math.min(1, srgb.g)),\n b: Math.max(0, Math.min(1, srgb.b)),\n });\n}\n\n/** Convert Display P3 to OKLCH. */\nexport function p3ToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearP3ToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to Display P3. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToP3(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearP3(oklchToOklab(color)));\n}\n","import type { Srgb } from \"../types.js\";\nimport { GAMUT_EPSILON } from \"../constants.js\";\n\n/** Check if sRGB channels are within [0, 1] (with epsilon tolerance). */\nexport function isInGamut(color: Srgb): boolean {\n return (\n color.r >= -GAMUT_EPSILON &&\n color.r <= 1 + GAMUT_EPSILON &&\n color.g >= -GAMUT_EPSILON &&\n color.g <= 1 + GAMUT_EPSILON &&\n color.b >= -GAMUT_EPSILON &&\n color.b <= 1 + GAMUT_EPSILON\n );\n}\n\n/** Clamp sRGB channels to [0, 1]. */\nexport function clampSrgb(color: Srgb): Srgb {\n return {\n r: Math.max(0, Math.min(1, color.r)),\n g: Math.max(0, Math.min(1, color.g)),\n b: Math.max(0, Math.min(1, color.b)),\n };\n}\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\n\n/** Compute deltaEOK (Euclidean distance in OKLAB) between two OKLCH colors. */\nexport function deltaEOK(a: Oklch, b: Oklch): number {\n return deltaEOKLab(oklchToOklab(a), oklchToOklab(b));\n}\n\n/** Compute deltaEOK directly from OKLAB values. */\nexport function deltaEOKLab(a: Oklab, b: Oklab): number {\n const dL = a.L - b.L;\n const da = a.a - b.a;\n const db = a.b - b.b;\n return Math.sqrt(dL * dL + da * da + db * db);\n}\n","import type { Gamut, Oklch, Srgb } from \"../types.js\";\nimport {\n GAMUT_EPSILON,\n GAMUT_MAP_EPSILON,\n GAMUT_MAP_JND,\n GAMUT_MAP_MAX_ITERATIONS,\n} from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut, clampSrgb } from \"./check.js\";\nimport { deltaEOKLab } from \"../color/difference.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\nimport { linearSrgbToOklab } from \"../conversions/linear-srgb.js\";\nimport { linearP3ToOklab } from \"../conversions/linear-p3.js\";\nimport { srgbToLinearSrgb } from \"../conversions/srgb.js\";\n\n/**\n * Map an OKLCH color into the target gamut using the CSS Color Level 4 algorithm.\n * Reduces chroma at fixed L and h via binary search with deltaEOK JND check.\n * @param gamut Target gamut (default: 'srgb').\n */\nexport function gamutMap(color: Oklch, gamut: Gamut = \"srgb\"): Oklch {\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n const rgbToOklab =\n gamut === \"display-p3\"\n ? (c: Srgb) => linearP3ToOklab(srgbToLinearSrgb(c))\n : (c: Srgb) => linearSrgbToOklab(srgbToLinearSrgb(c));\n\n // Already in gamut\n const rgb = toRgb(color);\n if (isInGamut(rgb)) return color;\n\n // Edge cases: black and white\n if (color.L <= GAMUT_EPSILON) return { L: 0, C: 0, h: color.h };\n if (color.L >= 1 - GAMUT_EPSILON) return { L: 1, C: 0, h: color.h };\n\n let lo = 0;\n let hi = color.C;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const midC = (lo + hi) / 2;\n const candidate: Oklch = { L: color.L, C: midC, h: color.h };\n const candidateRgb = toRgb(candidate);\n\n if (isInGamut(candidateRgb)) {\n lo = midC;\n } else {\n // Clip and check JND\n const clipped = clampSrgb(candidateRgb);\n const clippedLab = rgbToOklab(clipped);\n const candidateLab = oklchToOklab(candidate);\n const dE = deltaEOKLab(clippedLab, candidateLab);\n\n if (dE < GAMUT_MAP_JND) {\n // Clipped version is perceptually close enough — converge here.\n // Return lo (last confirmed in-gamut chroma) to guarantee gamut safety.\n break;\n }\n\n hi = midC;\n }\n\n if (hi - lo < GAMUT_MAP_EPSILON) break;\n }\n\n return { L: color.L, C: lo, h: color.h };\n}\n","import type { Gamut, Oklch } from \"../types.js\";\nimport { GAMUT_MAP_MAX_ITERATIONS } from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"./check.js\";\n\n/**\n * Find the maximum in-gamut chroma for a given OKLCH lightness and hue.\n *\n * Binary search over [0, upperBound], converging to 1e-6 precision.\n * Upper bounds are empirically safe ceilings — no in-gamut color at any\n * lightness or hue exceeds C = 0.4 in sRGB or C = 0.5 in Display P3.\n * Searching beyond these would waste iterations with no benefit.\n *\n * Returns 0 for L ≤ 0 or L ≥ 1 (pure black and white carry no chroma).\n */\nexport function maxChroma(L: number, h: number, gamut: Gamut = \"srgb\"): number {\n if (L <= 0 || L >= 1) return 0;\n\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n let lo = 0;\n let hi = gamut === \"display-p3\" ? 0.5 : 0.4;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const mid = (lo + hi) / 2;\n const color: Oklch = { L, C: mid, h };\n const rgb = toRgb(color);\n\n if (isInGamut(rgb)) {\n lo = mid;\n } else {\n hi = mid;\n }\n\n if (hi - lo < 1e-6) break;\n }\n\n return lo;\n}\n","import type { Srgb } from \"../types.js\";\nimport { WCAG_R, WCAG_G, WCAG_B } from \"../constants.js\";\nimport { srgbChannelToLinear } from \"../conversions/srgb.js\";\n\n/** Compute WCAG 2.x relative luminance [0, 1] from an sRGB color. */\nexport function wcagLuminance(color: Srgb): number {\n return (\n WCAG_R * srgbChannelToLinear(color.r) +\n WCAG_G * srgbChannelToLinear(color.g) +\n WCAG_B * srgbChannelToLinear(color.b)\n );\n}\n\n/**\n * Compute WCAG 2.x contrast ratio between two sRGB colors.\n * Returns a value in [1, 21]. Symmetric (order doesn't matter).\n */\nexport function wcagContrast(a: Srgb, b: Srgb): number {\n const lA = wcagLuminance(a);\n const lB = wcagLuminance(b);\n const lighter = Math.max(lA, lB);\n const darker = Math.min(lA, lB);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Choose black or white text for maximum WCAG contrast against a background.\n * @returns `\"#000000\"` or `\"#ffffff\"`.\n */\nexport function contrastTextHex(background: Srgb): \"#000000\" | \"#ffffff\" {\n const white: Srgb = { r: 1, g: 1, b: 1 };\n const black: Srgb = { r: 0, g: 0, b: 0 };\n return wcagContrast(white, background) > wcagContrast(black, background)\n ? \"#ffffff\"\n : \"#000000\";\n}\n","import type { Srgb } from \"../types.js\";\nimport {\n APCA_MAIN_TRC,\n APCA_SRGB_R,\n APCA_SRGB_G,\n APCA_SRGB_B,\n APCA_NORM_BG,\n APCA_NORM_TXT,\n APCA_REV_TXT,\n APCA_REV_BG,\n APCA_BLK_THRS,\n APCA_BLK_CLMP,\n APCA_SCALE_BOW,\n APCA_SCALE_WOB,\n APCA_LO_BOW_OFFSET,\n APCA_LO_WOB_OFFSET,\n APCA_DELTA_Y_MIN,\n APCA_LO_CLIP,\n} from \"../constants.js\";\n\n/**\n * Compute APCA-W3 Lc (Lightness Contrast) between text and background.\n *\n * Returns a signed value in roughly [-108, +106]:\n * Positive = dark text on light background (BoW)\n * Negative = light text on dark background (WoB)\n * 0 = no meaningful contrast\n *\n * IMPORTANT: Uses its own linearization (simple 2.4 gamma),\n * NOT the IEC piecewise sRGB transfer function.\n */\n/**\n * Practical maximum APCA Lc magnitude used for normalization.\n * BoW tops out at ~+106, WoB at ~-108; we use 108 as a symmetric ceiling.\n */\nexport const APCA_LC_MAX = 108;\n\n/**\n * Normalize a raw APCA Lc value to the range [-1, +1].\n * +1 = maximum dark-on-light contrast (BoW)\n * -1 = maximum light-on-dark contrast (WoB)\n * 0 = no meaningful contrast\n */\nexport function apcaToNormalized(lc: number): number {\n return Math.max(-1, Math.min(1, lc / APCA_LC_MAX));\n}\n\n/**\n * Convert a normalized contrast value [-1, +1] back to a raw APCA Lc value.\n */\nexport function normalizedToApca(normalized: number): number {\n return normalized * APCA_LC_MAX;\n}\n\nexport function apcaContrast(textColor: Srgb, bgColor: Srgb): number {\n // Step 1: Linearize with simple 2.4 gamma and compute Y\n let txtY =\n APCA_SRGB_R * textColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * textColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * textColor.b ** APCA_MAIN_TRC;\n\n let bgY =\n APCA_SRGB_R * bgColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * bgColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * bgColor.b ** APCA_MAIN_TRC;\n\n // Step 2: Soft black clamp\n if (txtY < APCA_BLK_THRS) {\n txtY += (APCA_BLK_THRS - txtY) ** APCA_BLK_CLMP;\n }\n if (bgY < APCA_BLK_THRS) {\n bgY += (APCA_BLK_THRS - bgY) ** APCA_BLK_CLMP;\n }\n\n // Step 3: Delta Y check\n if (Math.abs(bgY - txtY) < APCA_DELTA_Y_MIN) return 0;\n\n // Step 4: Polarity-aware contrast\n let sapc: number;\n\n if (bgY > txtY) {\n // Dark text on light background (BoW)\n sapc = (bgY ** APCA_NORM_BG - txtY ** APCA_NORM_TXT) * APCA_SCALE_BOW;\n return sapc < APCA_LO_CLIP ? 0 : (sapc - APCA_LO_BOW_OFFSET) * 100;\n } else {\n // Light text on dark background (WoB)\n sapc = (bgY ** APCA_REV_BG - txtY ** APCA_REV_TXT) * APCA_SCALE_WOB;\n return sapc > -APCA_LO_CLIP ? 0 : (sapc + APCA_LO_WOB_OFFSET) * 100;\n }\n}\n","import type { Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD } from \"../constants.js\";\n\n/**\n * Linearly interpolate between two OKLCH colors.\n *\n * L and C are linearly interpolated. Hue uses shortest-arc interpolation.\n * Achromatic colors (C near zero) inherit the other color's hue to avoid\n * meaningless hue sweeps through the achromatic pole.\n */\nexport function mix(a: Oklch, b: Oklch, t: number): Oklch {\n const L = a.L + (b.L - a.L) * t;\n const C = a.C + (b.C - a.C) * t;\n\n // Resolve hue — handle achromatic inputs\n const aIsAchromatic = a.C < ACHROMATIC_THRESHOLD;\n const bIsAchromatic = b.C < ACHROMATIC_THRESHOLD;\n\n if (aIsAchromatic && bIsAchromatic) {\n return { L, C, h: 0 };\n }\n\n const hA = aIsAchromatic ? b.h : a.h;\n const hB = bIsAchromatic ? a.h : b.h;\n\n // Shortest-arc hue interpolation\n let delta = hB - hA;\n if (delta > 180) delta -= 360;\n if (delta < -180) delta += 360;\n\n let h = hA + delta * t;\n if (h < 0) h += 360;\n if (h >= 360) h -= 360;\n\n return { L, C, h };\n}\n","/**\n * Design constants — the values you tune by hand.\n *\n * Edit this file to adjust the perceptual behavior of every scale and\n * grading operation across the library.\n */\n\n// ── Scale defaults ────────────────────────────────────────────────────────────\n\n/**\n * Default number of steps in a generated scale.\n * Fixed at 26 — enough for a full design token set with fine lightness\n * increments without redundancy.\n */\nexport const DEFAULT_SCALE_STEPS = 26;\n\n/**\n * Default hue when none is provided.\n * 0° is the start of the OKLCH hue wheel (red region). Arbitrary but\n * deterministic — callers should always supply an explicit hue.\n */\nexport const DEFAULT_HUE = 0;\n\n// ── Dynamic range ─────────────────────────────────────────────────────────────\n\n/**\n * Lightest step's lightness when the whites slider is at 0.\n * slider 0 → L = MIN_LIGHTEST_L, slider 1 → L = 1.0 (pure white).\n */\nexport const MIN_LIGHTEST_L = 0.96;\n\n/**\n * Darkest step's lightness when the darks slider is at 0.\n * slider 0 → L = MAX_DARKEST_L, slider 1 → L = 0.0 (pure black).\n */\nexport const MAX_DARKEST_L = 0.16;\n\n// ── Hue grading ───────────────────────────────────────────────────────────────\n\n/**\n * How far global grading reaches into the scale from each end (0–1).\n * Light grading fades to zero at t = GRADING_REACH.\n * Dark grading fades to zero at t = 1 − GRADING_REACH.\n */\nexport const GRADING_REACH = 3 / 5;\n\n/** Maximum amount for global grading. Inputs above this are clamped. */\nexport const MAX_GRADING_AMOUNT = 0.25;\n\n/**\n * How far per-palette hue shift reaches into the scale from each end (0–1).\n * Slightly wider than GRADING_REACH to give per-palette shifts more room.\n */\nexport const SHIFT_REACH = 2 / 3;\n\n/** Maximum amount for per-palette hue shift. Inputs above this are clamped. */\nexport const MAX_SHIFT_AMOUNT = 0.5;\n\n// ── Color difference ──────────────────────────────────────────────────────────\n\n/**\n * Just-noticeable difference threshold (deltaEOK).\n * Colors with distance below this are considered perceptually identical.\n * Used to classify color matches as exact vs. fallback.\n */\nexport const PERCEPTUAL_JND = 0.02;\n","/**\n * Global hue grading — shifts each palette's base hue toward shared\n * target hues at the light and dark scale endpoints.\n *\n * Light grading fades from full at the lightest step to zero at GRADING_REACH.\n * Dark grading fades from zero at (1 - GRADING_REACH) to full at the darkest step.\n * In the overlap zone, both shifts are additive (commutative).\n */\n\nimport {\n GRADING_REACH,\n MAX_GRADING_AMOUNT,\n SHIFT_REACH,\n MAX_SHIFT_AMOUNT,\n} from \"../config.js\";\n\nexport interface Grading {\n /** Hue grading for the light end of the scale. */\n readonly light?: { readonly hue: number; readonly amount: number };\n /** Hue grading for the dark end of the scale. */\n readonly dark?: { readonly hue: number; readonly amount: number };\n}\n\n/** Per-palette hue shift (one end only). */\nexport interface Shift {\n /** Target hue to shift toward (0–360°). */\n readonly hue: number;\n /** Blend strength (0–MAX_SHIFT_AMOUNT). */\n readonly amount: number;\n /** Which end to affect. `true` = light end, `false`/omitted = dark end (default). */\n readonly light?: boolean;\n}\n\n/**\n * Compute the graded hue at position `t` in the scale.\n *\n * Uses vector interpolation in Cartesian space rather than angular deltas\n * to avoid the shortest-arc discontinuity at 180° (where the direction\n * of rotation flips abruptly). Each grade's displacement is computed as\n * a vector offset from the base hue, and displacements are additive\n * (commutative — order doesn't matter).\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param grade Hue grade configuration.\n * @param reach How far each grade reaches into the scale (default: GRADING_REACH).\n * @param maxIntensity Maximum amount clamp (default: MAX_GRADING_AMOUNT).\n * @returns The graded hue in degrees (0–360).\n */\nexport function gradeHue(\n baseHue: number,\n t: number,\n grade: Grading,\n reach: number = GRADING_REACH,\n maxIntensity: number = MAX_GRADING_AMOUNT,\n): number {\n const li = Math.max(0, Math.min(maxIntensity, grade.light?.amount ?? 0));\n const di = Math.max(0, Math.min(maxIntensity, grade.dark?.amount ?? 0));\n\n // Early exit: no grading\n if (li === 0 && di === 0) return baseHue;\n\n // Light influence: cosine fade from 1 at t=0 to 0 at t=reach\n const lightInfluence =\n t <= reach ? 0.5 * (1 + Math.cos((Math.PI * t) / reach)) : 0;\n\n // Dark influence: cosine fade from 0 at t=(1-reach) to 1 at t=1\n const darkInfluence =\n t >= 1 - reach\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / reach))\n : 0;\n\n // Base hue as unit vector\n const toRad = Math.PI / 180;\n const baseRad = baseHue * toRad;\n const bx = Math.cos(baseRad);\n const by = Math.sin(baseRad);\n\n // Accumulate displacements in Cartesian space\n let dx = 0;\n let dy = 0;\n\n if (lightInfluence > 0 && li > 0) {\n const blend = lightInfluence * li;\n const lRad = (grade.light!.hue) * toRad;\n dx += blend * (Math.cos(lRad) - bx);\n dy += blend * (Math.sin(lRad) - by);\n }\n\n if (darkInfluence > 0 && di > 0) {\n const blend = darkInfluence * di;\n const dRad = (grade.dark!.hue) * toRad;\n dx += blend * (Math.cos(dRad) - bx);\n dy += blend * (Math.sin(dRad) - by);\n }\n\n // Reconstruct hue from displaced vector\n const rx = bx + dx;\n const ry = by + dy;\n\n // Safety: collapsed vector (opposite hues at exactly 50% blend)\n if (rx * rx + ry * ry < 1e-20) return baseHue;\n\n return ((Math.atan2(ry, rx) / toRad) + 360) % 360;\n}\n\n/**\n * Resolve the final hue at position `t`, applying local shift first, then global grading.\n *\n * This is the canonical composition: per-palette shift (using SHIFT_REACH /\n * MAX_SHIFT_AMOUNT) first, then global grading (using GRADING_REACH /\n * MAX_GRADING_AMOUNT) on top — so grading's influence is preserved at full\n * strength across all palettes, keeping them visually coherent.\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param globalGrade Global grading (shared across palettes), or undefined.\n * @param localGrade Local grading (per-palette, expanded from Shift), or undefined.\n * @returns The fully graded hue in degrees (0–360).\n */\nexport function resolveGradedHue(\n baseHue: number,\n t: number,\n globalGrade?: Grading,\n localGrade?: Grading,\n): number {\n let h = baseHue;\n if (localGrade) h = gradeHue(h, t, localGrade, SHIFT_REACH, MAX_SHIFT_AMOUNT);\n if (globalGrade) h = gradeHue(h, t, globalGrade);\n return h;\n}\n\n/**\n * Adapt a Shift into a one-sided Grading so it can be passed to gradeHue.\n *\n * The Shift interface is flat (hue, amount, light?) for ergonomic API use,\n * but gradeHue operates on the Grading shape (light/dark sub-objects).\n * This function bridges the two, activating only the requested end.\n *\n * @param hue Target hue for the active side (0–360°).\n * @param amount Blend strength for the active side.\n * @param light `true` = light end, `false`/omitted = dark end (default).\n */\nexport function buildOneSidedGrade(\n hue: number,\n amount: number,\n light: boolean = false,\n): Grading {\n return light\n ? { light: { hue, amount } }\n : { dark: { hue, amount } };\n}\n","/**\n * Dynamic range resolution — maps slider values (0–1) to OKLCH lightness\n * bounds for the lightest and darkest steps of a color scale.\n */\n\nimport { MIN_LIGHTEST_L, MAX_DARKEST_L } from \"../config.js\";\n\n/**\n * Resolve a whites slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MIN_LIGHTEST_L (0.96), slider 1 → L = 1.0 (pure white)\n */\nexport function resolveLightest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MIN_LIGHTEST_L + s * (1.0 - MIN_LIGHTEST_L);\n}\n\n/**\n * Resolve a darks slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MAX_DARKEST_L (0.16), slider 1 → L = 0.0 (pure black)\n */\nexport function resolveDarkest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MAX_DARKEST_L * (1 - s);\n}\n\n/**\n * Map an OKLCH lightness to a normalized scale position (0–1).\n * 0 = lightest end, 1 = darkest end.\n *\n * Inverse of the lightness interpolation inside generateScale.\n * Useful for deriving chromaPeak from a key color's lightness.\n */\nexport function lightnessToScaleT(L: number, lightestL: number, darkestL: number): number {\n const range = lightestL - darkestL;\n if (range <= 0) return 0.5;\n return Math.max(0, Math.min(1, (lightestL - L) / range));\n}\n","import type { Oklch } from \"../types.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\nimport type { Grading, Shift } from \"./hue-grade.js\";\nimport { resolveGradedHue, buildOneSidedGrade } from \"./hue-grade.js\";\nimport { resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport { DEFAULT_SCALE_STEPS, DEFAULT_HUE } from \"../config.js\";\n\nexport interface ScaleOptions {\n /**\n * Tonal range of the scale.\n * - `light`: how light the lightest step is (0–1). Default: 1.\n * 0 → L = MIN_LIGHTEST_L (0.96), 1 → L = 1.0 (pure white).\n * - `dark`: how dark the darkest step is (0–1). Default: 1.\n * 0 → L = MAX_DARKEST_L (0.16), 1 → L = 0.0 (pure black).\n */\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n /**\n * Hue angle in degrees (0–360). Default: DEFAULT_HUE (0).\n * Every step shares this base hue unless shifted by `grading` or `shift`.\n */\n readonly hue?: number;\n /**\n * Chroma shape of the scale.\n * - `amount`: how much of the available gamut to use (0–1). Default: 0.\n * 0 = fully achromatic (default), 1 = maximum in-gamut chroma at each lightness.\n * - `balance`: how chroma is distributed along the lightness range (0–1).\n * 0 = chroma concentrated toward the lightest end, 1 = toward the darkest end,\n * 0.5 = natural distribution (default, follows gamut boundary shape).\n */\n readonly chroma?: { readonly amount?: number; readonly balance?: number };\n /**\n * Global hue grading. When provided, the hue at each step is shifted\n * toward target hues based on position in the scale.\n * Light grading affects the lightest 3/5, dark grading affects the\n * darkest 3/5, with additive overlap in the middle fifth.\n */\n readonly grading?: Grading;\n /**\n * Per-palette hue shift. A one-sided grade applied before global\n * grading, with its own reach and strength limits (SHIFT_REACH,\n * MAX_SHIFT_AMOUNT). Defaults to the dark end; set `light: true` to target\n * the light end instead.\n */\n readonly shift?: Shift;\n /** Use Display P3 gamut instead of sRGB (default: false). */\n readonly isP3?: boolean;\n}\n\n/**\n * Generate an OKLCH color scale from lightest to darkest.\n *\n * Always produces DEFAULT_SCALE_STEPS colors. Chroma at each step is\n * proportional to the gamut boundary at that lightness, scaled by\n * `chroma.amount`. This guarantees every color is in-gamut — no fallbacks\n * needed — while producing a smooth, natural chroma curve.\n *\n * Use `contrast` to constrain the tonal range\n * (e.g. for scales that don't extend to pure white or pure black).\n *\n * Use `chroma.balance` to shift how chroma is distributed within the boundary.\n * The curve endpoints stay fixed while the distribution shifts smoothly.\n * The effective shift range is proportional to the headroom left by chroma.amount.\n */\nexport function generateScale(options: ScaleOptions = {}): Oklch[] {\n const {\n contrast,\n hue = DEFAULT_HUE,\n chroma,\n isP3 = false,\n grading,\n shift,\n } = options;\n const gamut = isP3 ? \"display-p3\" : \"srgb\";\n\n const steps = DEFAULT_SCALE_STEPS;\n const chromaRatio = chroma?.amount ?? 0;\n const chromaPeak = chroma?.balance ?? 0.5;\n const hueGrade = grading;\n const localHueGrade = shift ? buildOneSidedGrade(shift.hue, shift.amount, shift.light) : undefined;\n\n const ratio = Math.max(0, Math.min(1, chromaRatio));\n const peak = Math.max(0, Math.min(1, chromaPeak));\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n\n // Helper: resolve hue at position t (applies local shift first, then global grading)\n const hueAt = (t: number) => resolveGradedHue(hue, t, hueGrade, localHueGrade);\n\n // Fast path: skip peak skew logic when balance has no effect.\n // - peak === 0.5: already at the natural gamut peak, nothing to shift\n // - ratio === 0: no chroma at all, boundary shape is irrelevant\n // - ratio >= 1: inner triangle equals the boundary triangle, no headroom to slide\n if (peak === 0.5 || ratio === 0 || ratio >= 1) {\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n const h = hueAt(t);\n // Chroma is shaped by the base hue's boundary to keep the curve smooth.\n // The shifted hue's boundary is used as a final in-gamut clamp only —\n // this prevents spikes when the shifted hue has more available chroma\n // than the base (e.g. blue → pink passing through the purple region).\n const C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));\n scale.push({ L, C, h });\n }\n return scale;\n }\n\n // ── Peak skew logic ──\n // Warp the parameter t so the boundary peak appears at a shifted position.\n // Endpoints stay fixed (warp(0)=0, warp(1)=1), only the peak moves.\n\n // 1. Sample boundary to find natural peak and valid shift range\n const N = 100;\n let peakT = 0.5;\n let peakBoundaryC = 0;\n const boundarySamples: { t: number; C: number }[] = [];\n\n for (let i = 0; i <= N; i++) {\n const t = i / N;\n const L = lightestL - t * (lightestL - darkestL);\n // Sample the base hue's boundary — the same reference used when building\n // the warp below. Using the shifted hue here would skew peakT and the\n // valid range toward a hue-specific boundary shape, inconsistent with\n // how chroma is actually computed in step 4.\n const C = maxChroma(L, hue, gamut);\n boundarySamples.push({ t, C });\n if (C > peakBoundaryC) {\n peakBoundaryC = C;\n peakT = t;\n }\n }\n\n // 2. Find valid range: where boundary can accommodate the inner peak height\n const innerPeakC = peakBoundaryC * ratio;\n let validMinT = peakT;\n let validMaxT = peakT;\n\n for (const { t, C } of boundarySamples) {\n if (C >= innerPeakC - 1e-6) {\n if (t < validMinT) validMinT = t;\n if (t > validMaxT) validMaxT = t;\n }\n }\n\n // 3. Map chroma.balance (0–1) to valid range, normalized so 0.5 → peakT\n let targetT: number;\n if (peak <= 0.5) {\n targetT = validMinT + (peak / 0.5) * (peakT - validMinT);\n } else {\n targetT = peakT + ((peak - 0.5) / 0.5) * (validMaxT - peakT);\n }\n\n // Safety: if the piecewise mapping produces a degenerate targetT (outside\n // (0, 1)), fall back to the natural peak. This can occur at floating-point\n // boundaries rather than from any single expected input combination.\n if (targetT <= 0 || targetT >= 1) {\n targetT = peakT;\n }\n\n // 4. Build scale with piecewise-linear warp: targetT → peakT\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n const h = hueAt(t);\n\n // Piecewise-linear warp: maps 0→0, targetT→peakT, 1→1.\n // Two segments scale t independently so the boundary peak (at peakT in\n // warp space) lands at targetT in the output — endpoints stay fixed.\n let tWarped: number;\n if (t <= targetT) {\n tWarped = t * (peakT / targetT);\n } else {\n tWarped = peakT + (t - targetT) * ((1 - peakT) / (1 - targetT));\n }\n\n const Lwarped = lightestL - tWarped * (lightestL - darkestL);\n // Use the base hue for the warped chroma lookup — consistent with step 1\n // and the fast path. The warp is purely a lightness operation; mixing in\n // the shifted hue at tWarped would introduce cross-position hue artifacts.\n const warpedC = maxChroma(Lwarped, hue, gamut) * ratio;\n // Clamp to the shifted hue's actual boundary at this L: the in-gamut\n // guarantee for the final color { L, C, h }.\n const boundaryC = maxChroma(L, h, gamut);\n const C = Math.min(warpedC, boundaryC);\n\n scale.push({ L, C, h });\n }\n\n return scale;\n}\n","import type { Hex, Oklch, Gamut } from \"../types.js\";\nimport {\n hexToOklch,\n oklchToSrgb,\n oklchToP3,\n oklchToHex,\n} from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"../gamut/check.js\";\nimport { gamutMap } from \"../gamut/map.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\n\n/**\n * Result of resolving a color into scale-ready parameters.\n */\nexport interface ResolvedColor {\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Hex representation (sRGB-clamped if the resolved color exceeds sRGB). */\n readonly hex: Hex;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n /** Chroma lost during gamut mapping (0 if in-gamut). */\n readonly chromaShift: number;\n /** Hue from the resolved color. */\n readonly hue: number;\n /** Chroma as a fraction of the gamut boundary at this L/h (0–1). */\n readonly chromaRatio: number;\n}\n\n/**\n * Resolve a color (hex or OKLCH) into scale-ready parameters.\n *\n * If the color is outside the target gamut, it is perceptually mapped to the\n * nearest in-gamut color (chroma reduction at fixed L and h). The result\n * includes the derived hue and chromaRatio.\n *\n * Hex input is always valid sRGB, so `wasRemapped` will be false for hex\n * with gamut=\"srgb\". OKLCH input may be out of gamut and will be mapped.\n *\n * @param input A hex string (#RGB, #RRGGBB) or an OKLCH color.\n * @param isP3 Use Display P3 gamut instead of sRGB (default: false).\n */\nexport function resolveColor(\n input: Hex | Oklch,\n isP3: boolean = false,\n): ResolvedColor {\n const gamut: Gamut = isP3 ? \"display-p3\" : \"srgb\";\n const isHex = typeof input === \"string\";\n const original: Oklch = isHex ? hexToOklch(input) : input;\n\n // Hex encodes valid sRGB by definition, and sRGB ⊂ P3, so hex input\n // is always in-gamut for both supported gamuts. Skipping the round-trip\n // check avoids false negatives from floating-point drift.\n let inGamut: boolean;\n if (isHex) {\n inGamut = true;\n } else {\n const rgb =\n gamut === \"display-p3\" ? oklchToP3(original) : oklchToSrgb(original);\n inGamut = isInGamut(rgb);\n }\n\n const oklch = inGamut ? original : gamutMap(original, gamut);\n\n const boundary = maxChroma(oklch.L, oklch.h, gamut);\n const chromaRatio = boundary > 0 ? oklch.C / boundary : 0;\n\n return {\n oklch,\n hex: oklchToHex(oklch),\n wasRemapped: !inGamut,\n original,\n chromaShift: original.C - oklch.C,\n hue: oklch.h,\n chromaRatio: Math.min(1, chromaRatio),\n };\n}\n","import type { Hex, Oklch } from \"../types.js\";\nimport { resolveColor } from \"./resolve-color.js\";\nimport { lightnessToScaleT, resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport { DEFAULT_SCALE_STEPS } from \"../config.js\";\n\n/**\n * The result of deriving scale parameters from a key color.\n *\n * Spread `hue` and `chroma` directly into ScaleOptions, then use\n * `stepIndex` to locate the key color's position in the generated scale.\n */\nexport interface KeyColorResult {\n /** Derived hue angle — use directly as ScaleOptions.hue. */\n readonly hue: number;\n /**\n * Derived chroma shape — use directly as ScaleOptions.chroma.\n * - `amount`: how saturated the scale is (0–1, relative to gamut boundary).\n * - `balance`: where in the scale the key color's lightness falls (0 = lightest, 1 = darkest).\n */\n readonly chroma: { readonly amount: number; readonly balance: number };\n /** The step index in a scale of `steps` length where this color lands. */\n readonly stepIndex: number;\n /** Hex representation of the resolved color (sRGB-clamped if necessary). */\n readonly hex: Hex;\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n}\n\n/**\n * Derive scale parameters from a known color.\n *\n * Given a hex or OKLCH color, returns the `hue` and `chroma` values\n * ready to spread into ScaleOptions. The chroma balance is derived from\n * where the color's lightness falls within the scale's lightness range,\n * so the chroma distribution is centered around the key color's position.\n *\n * @param color A hex string (#RGB or #RRGGBB) or an OKLCH color object.\n * @param options Scale context — must match the ScaleOptions you will use.\n * `contrast` values are slider values (0–1), same as ScaleOptions.contrast.\n * `steps` is the number of steps in the scale (default: 26).\n *\n * @example\n * const key = keyColor('#3B82F6');\n * const scale = generateScale({ hue: key.hue, chroma: key.chroma });\n * const matchedHex = oklchToHex(scale[key.stepIndex]);\n */\nexport function keyColor(\n color: Hex | Oklch,\n options?: {\n readonly isP3?: boolean;\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n readonly steps?: number;\n },\n): KeyColorResult {\n const { isP3 = false, contrast, steps = DEFAULT_SCALE_STEPS } = options ?? {};\n const resolved = resolveColor(color, isP3);\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n const balance = lightnessToScaleT(resolved.oklch.L, lightestL, darkestL);\n const stepIndex = Math.round(balance * Math.max(0, steps - 1));\n\n return {\n hue: resolved.hue,\n chroma: { amount: resolved.chromaRatio, balance },\n stepIndex,\n hex: resolved.hex,\n oklch: resolved.oklch,\n wasRemapped: resolved.wasRemapped,\n original: resolved.original,\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/constants.ts","../src/conversions/oklab.ts","../src/conversions/linear-srgb.ts","../src/conversions/linear-p3.ts","../src/conversions/srgb.ts","../src/conversions/hex.ts","../src/conversions/pipeline.ts","../src/gamut/check.ts","../src/color/difference.ts","../src/gamut/map.ts","../src/gamut/max-chroma.ts","../src/contrast/wcag.ts","../src/contrast/apca.ts","../src/color/interpolation.ts","../src/config.ts","../src/scale/hue-grade.ts","../src/scale/dynamic-range.ts","../src/scale/generate.ts","../src/scale/resolve-color.ts","../src/scale/key-color.ts"],"names":["toRad","scale"],"mappings":"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","file":"index.js","sourcesContent":["// ── sRGB Gamma Transfer (IEC 61966-2-1) ──\n\nexport const SRGB_GAMMA_THRESHOLD = 0.04045;\nexport const SRGB_GAMMA_THRESHOLD_LINEAR = 0.0031308;\nexport const SRGB_GAMMA_SLOPE = 12.92;\nexport const SRGB_GAMMA_EXPONENT = 2.4;\nexport const SRGB_GAMMA_OFFSET = 0.055;\nexport const SRGB_GAMMA_SCALE = 1.055;\n\n// ── Ottosson M1: Linear sRGB → LMS ──\n\nexport const LINEAR_SRGB_TO_LMS = [\n [0.4122214708, 0.5363325363, 0.0514459929],\n [0.2119034982, 0.6806995451, 0.1073969566],\n [0.0883024619, 0.2817188376, 0.6299787005],\n] as const;\n\n// ── Ottosson M2: LMS′ (cube-root) → OKLAB ──\n\nexport const LMS_PRIME_TO_OKLAB = [\n [+0.2104542553, +0.7936177850, -0.0040720468],\n [+1.9779984951, -2.4285922050, +0.4505937099],\n [+0.0259040371, +0.7827717662, -0.8086757660],\n] as const;\n\n// ── Inverse M2: OKLAB → LMS′ ──\n\nexport const OKLAB_TO_LMS_PRIME = [\n [1.0000000000, +0.3963377774, +0.2158037573],\n [1.0000000000, -0.1055613458, -0.0638541728],\n [1.0000000000, -0.0894841775, -1.2914855480],\n] as const;\n\n// ── Inverse M1: LMS → Linear sRGB ──\n\nexport const LMS_TO_LINEAR_SRGB = [\n [+4.0767416621, -3.3077115913, +0.2309699292],\n [-1.2684380046, +2.6097574011, -0.3413193965],\n [-0.0041960863, -0.7034186147, +1.7076147010],\n] as const;\n\n// ── Display P3 M1: Linear Display P3 → LMS ──\n// Derived: XYZ_to_LMS × P3_to_XYZ, where XYZ_to_LMS = M1_srgb × inv(sRGB_to_XYZ)\n\nexport const LINEAR_P3_TO_LMS = [\n [+0.4813791595, +0.4621155872, +0.0565406381],\n [+0.2288319169, +0.6532167007, +0.1179528072],\n [+0.0839457149, +0.2241651052, +0.6918912614],\n] as const;\n\n// ── Inverse P3 M1: LMS → Linear Display P3 ──\n\nexport const LMS_TO_LINEAR_P3 = [\n [+3.1277694390, -2.2570600176, +0.1291828502],\n [-1.0910091977, +2.4133065499, -0.3222615148],\n [-0.0260108068, -0.5080402362, +1.5340494942],\n] as const;\n\n// ── Gamut Mapping ──\n\nexport const GAMUT_EPSILON = 1e-6;\nexport const GAMUT_MAP_JND = 0.02;\nexport const GAMUT_MAP_EPSILON = 1e-4;\nexport const GAMUT_MAP_MAX_ITERATIONS = 50;\n\n// ── Achromatic Threshold ──\n\nexport const ACHROMATIC_THRESHOLD = 1e-10;\n\n// ── WCAG 2.x Luminance Coefficients ──\n\nexport const WCAG_R = 0.2126;\nexport const WCAG_G = 0.7152;\nexport const WCAG_B = 0.0722;\n\n// ── APCA-W3 (SA98G) Constants ──\n\nexport const APCA_MAIN_TRC = 2.4;\nexport const APCA_SRGB_R = 0.2126729;\nexport const APCA_SRGB_G = 0.7151522;\nexport const APCA_SRGB_B = 0.0721750;\nexport const APCA_NORM_BG = 0.56;\nexport const APCA_NORM_TXT = 0.57;\nexport const APCA_REV_TXT = 0.62;\nexport const APCA_REV_BG = 0.65;\nexport const APCA_BLK_THRS = 0.022;\nexport const APCA_BLK_CLMP = 1.414;\nexport const APCA_SCALE_BOW = 1.14;\nexport const APCA_SCALE_WOB = 1.14;\nexport const APCA_LO_BOW_OFFSET = 0.027;\nexport const APCA_LO_WOB_OFFSET = 0.027;\nexport const APCA_DELTA_Y_MIN = 0.0005;\nexport const APCA_LO_CLIP = 0.1;\n\n// ── Angle Math ──\n\nexport const DEG_TO_RAD = Math.PI / 180;\nexport const RAD_TO_DEG = 180 / Math.PI;\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD, DEG_TO_RAD, RAD_TO_DEG } from \"../constants.js\";\n\n/** Convert OKLAB (cartesian) to OKLCH (cylindrical). Achromatic colors get h=0. */\nexport function oklabToOklch(lab: Oklab): Oklch {\n const C = Math.sqrt(lab.a * lab.a + lab.b * lab.b);\n\n if (C < ACHROMATIC_THRESHOLD) {\n return { L: lab.L, C: 0, h: 0 };\n }\n\n let h = Math.atan2(lab.b, lab.a) * RAD_TO_DEG;\n if (h < 0) h += 360;\n\n return { L: lab.L, C, h };\n}\n\n/** Convert OKLCH (cylindrical) to OKLAB (cartesian). */\nexport function oklchToOklab(lch: Oklch): Oklab {\n const hRad = lch.h * DEG_TO_RAD;\n return {\n L: lch.L,\n a: lch.C * Math.cos(hRad),\n b: lch.C * Math.sin(hRad),\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_SRGB_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_SRGB,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear sRGB to OKLAB via Ottosson's direct M1/M2 matrices. */\nexport function linearSrgbToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear sRGB → LMS\n const l =\n LINEAR_SRGB_TO_LMS[0][0] * color.r +\n LINEAR_SRGB_TO_LMS[0][1] * color.g +\n LINEAR_SRGB_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_SRGB_TO_LMS[1][0] * color.r +\n LINEAR_SRGB_TO_LMS[1][1] * color.g +\n LINEAR_SRGB_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_SRGB_TO_LMS[2][0] * color.r +\n LINEAR_SRGB_TO_LMS[2][1] * color.g +\n LINEAR_SRGB_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear sRGB via inverse M2/M1 matrices. */\nexport function oklabToLinearSrgb(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear sRGB\n return {\n r:\n LMS_TO_LINEAR_SRGB[0][0] * l +\n LMS_TO_LINEAR_SRGB[0][1] * m +\n LMS_TO_LINEAR_SRGB[0][2] * s,\n g:\n LMS_TO_LINEAR_SRGB[1][0] * l +\n LMS_TO_LINEAR_SRGB[1][1] * m +\n LMS_TO_LINEAR_SRGB[1][2] * s,\n b:\n LMS_TO_LINEAR_SRGB[2][0] * l +\n LMS_TO_LINEAR_SRGB[2][1] * m +\n LMS_TO_LINEAR_SRGB[2][2] * s,\n };\n}\n","import type { LinearSrgb, Oklab } from \"../types.js\";\nimport {\n LINEAR_P3_TO_LMS,\n LMS_PRIME_TO_OKLAB,\n LMS_TO_LINEAR_P3,\n OKLAB_TO_LMS_PRIME,\n} from \"../constants.js\";\n\n/** Convert Linear Display P3 to OKLAB via P3-specific M1 + shared M2. */\nexport function linearP3ToOklab(color: LinearSrgb): Oklab {\n // Step 1: Linear P3 → LMS\n const l =\n LINEAR_P3_TO_LMS[0][0] * color.r +\n LINEAR_P3_TO_LMS[0][1] * color.g +\n LINEAR_P3_TO_LMS[0][2] * color.b;\n const m =\n LINEAR_P3_TO_LMS[1][0] * color.r +\n LINEAR_P3_TO_LMS[1][1] * color.g +\n LINEAR_P3_TO_LMS[1][2] * color.b;\n const s =\n LINEAR_P3_TO_LMS[2][0] * color.r +\n LINEAR_P3_TO_LMS[2][1] * color.g +\n LINEAR_P3_TO_LMS[2][2] * color.b;\n\n // Step 2: Cube root\n const lp = Math.cbrt(l);\n const mp = Math.cbrt(m);\n const sp = Math.cbrt(s);\n\n // Step 3: LMS′ → OKLAB (shared M2)\n return {\n L:\n LMS_PRIME_TO_OKLAB[0][0] * lp +\n LMS_PRIME_TO_OKLAB[0][1] * mp +\n LMS_PRIME_TO_OKLAB[0][2] * sp,\n a:\n LMS_PRIME_TO_OKLAB[1][0] * lp +\n LMS_PRIME_TO_OKLAB[1][1] * mp +\n LMS_PRIME_TO_OKLAB[1][2] * sp,\n b:\n LMS_PRIME_TO_OKLAB[2][0] * lp +\n LMS_PRIME_TO_OKLAB[2][1] * mp +\n LMS_PRIME_TO_OKLAB[2][2] * sp,\n };\n}\n\n/** Convert OKLAB to Linear Display P3 via shared inverse M2 + P3-specific inverse M1. */\nexport function oklabToLinearP3(color: Oklab): LinearSrgb {\n // Step 1: OKLAB → LMS′ (shared inverse M2)\n const lp =\n OKLAB_TO_LMS_PRIME[0][0] * color.L +\n OKLAB_TO_LMS_PRIME[0][1] * color.a +\n OKLAB_TO_LMS_PRIME[0][2] * color.b;\n const mp =\n OKLAB_TO_LMS_PRIME[1][0] * color.L +\n OKLAB_TO_LMS_PRIME[1][1] * color.a +\n OKLAB_TO_LMS_PRIME[1][2] * color.b;\n const sp =\n OKLAB_TO_LMS_PRIME[2][0] * color.L +\n OKLAB_TO_LMS_PRIME[2][1] * color.a +\n OKLAB_TO_LMS_PRIME[2][2] * color.b;\n\n // Step 2: Cube\n const l = lp * lp * lp;\n const m = mp * mp * mp;\n const s = sp * sp * sp;\n\n // Step 3: LMS → Linear P3\n return {\n r:\n LMS_TO_LINEAR_P3[0][0] * l +\n LMS_TO_LINEAR_P3[0][1] * m +\n LMS_TO_LINEAR_P3[0][2] * s,\n g:\n LMS_TO_LINEAR_P3[1][0] * l +\n LMS_TO_LINEAR_P3[1][1] * m +\n LMS_TO_LINEAR_P3[1][2] * s,\n b:\n LMS_TO_LINEAR_P3[2][0] * l +\n LMS_TO_LINEAR_P3[2][1] * m +\n LMS_TO_LINEAR_P3[2][2] * s,\n };\n}\n","import type { LinearSrgb, Srgb } from \"../types.js\";\nimport {\n SRGB_GAMMA_EXPONENT,\n SRGB_GAMMA_OFFSET,\n SRGB_GAMMA_SCALE,\n SRGB_GAMMA_SLOPE,\n SRGB_GAMMA_THRESHOLD,\n SRGB_GAMMA_THRESHOLD_LINEAR,\n} from \"../constants.js\";\n\n/** Decode a single sRGB gamma-encoded channel to linear light. */\nexport function srgbChannelToLinear(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD\n ? value / SRGB_GAMMA_SLOPE\n : ((value + SRGB_GAMMA_OFFSET) / SRGB_GAMMA_SCALE) ** SRGB_GAMMA_EXPONENT;\n}\n\n/** Encode a single linear light channel to sRGB gamma. */\nexport function linearChannelToSrgb(value: number): number {\n return value <= SRGB_GAMMA_THRESHOLD_LINEAR\n ? value * SRGB_GAMMA_SLOPE\n : SRGB_GAMMA_SCALE * value ** (1 / SRGB_GAMMA_EXPONENT) - SRGB_GAMMA_OFFSET;\n}\n\n/** Convert an sRGB color to Linear sRGB. */\nexport function srgbToLinearSrgb(color: Srgb): LinearSrgb {\n return {\n r: srgbChannelToLinear(color.r),\n g: srgbChannelToLinear(color.g),\n b: srgbChannelToLinear(color.b),\n };\n}\n\n/** Convert a Linear sRGB color to sRGB. */\nexport function linearSrgbToSrgb(color: LinearSrgb): Srgb {\n return {\n r: linearChannelToSrgb(color.r),\n g: linearChannelToSrgb(color.g),\n b: linearChannelToSrgb(color.b),\n };\n}\n","import type { Hex, Srgb } from \"../types.js\";\n\n/** Parse a hex color string (#RGB, #RRGGBB, or bare) to sRGB [0,1]. */\nexport function hexToSrgb(hex: string): Srgb {\n let h = hex.startsWith(\"#\") ? hex.slice(1) : hex;\n\n if (h.length === 3) {\n h = h[0] + h[0] + h[1] + h[1] + h[2] + h[2];\n }\n\n const n = parseInt(h, 16);\n return {\n r: ((n >> 16) & 0xff) / 255,\n g: ((n >> 8) & 0xff) / 255,\n b: (n & 0xff) / 255,\n };\n}\n\n/** Convert sRGB [0,1] to lowercase hex string (#rrggbb). Clamps to [0,1]. */\nexport function srgbToHex(color: Srgb): Hex {\n const r = Math.round(Math.max(0, Math.min(1, color.r)) * 255);\n const g = Math.round(Math.max(0, Math.min(1, color.g)) * 255);\n const b = Math.round(Math.max(0, Math.min(1, color.b)) * 255);\n return `#${((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1)}` as Hex;\n}\n","import type { Hex, Oklab, Oklch, Srgb } from \"../types.js\";\nimport { oklabToOklch, oklchToOklab } from \"./oklab.js\";\nimport { linearSrgbToOklab, oklabToLinearSrgb } from \"./linear-srgb.js\";\nimport { linearP3ToOklab, oklabToLinearP3 } from \"./linear-p3.js\";\nimport { linearSrgbToSrgb, srgbToLinearSrgb } from \"./srgb.js\";\nimport { hexToSrgb, srgbToHex } from \"./hex.js\";\n\n/** Convert sRGB to OKLCH. */\nexport function srgbToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearSrgbToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to sRGB. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToSrgb(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(oklchToOklab(color)));\n}\n\n/** Convert sRGB to OKLAB. */\nexport function srgbToOklab(color: Srgb): Oklab {\n return linearSrgbToOklab(srgbToLinearSrgb(color));\n}\n\n/** Convert OKLAB to sRGB. May produce out-of-gamut values. */\nexport function oklabToSrgb(color: Oklab): Srgb {\n return linearSrgbToSrgb(oklabToLinearSrgb(color));\n}\n\n/** Convert hex to OKLCH. */\nexport function hexToOklch(hex: string): Oklch {\n return srgbToOklch(hexToSrgb(hex));\n}\n\n/** Convert OKLCH to hex. Clamps to sRGB gamut before hex encoding. */\nexport function oklchToHex(color: Oklch): Hex {\n const srgb = oklchToSrgb(color);\n return srgbToHex({\n r: Math.max(0, Math.min(1, srgb.r)),\n g: Math.max(0, Math.min(1, srgb.g)),\n b: Math.max(0, Math.min(1, srgb.b)),\n });\n}\n\n/** Convert Display P3 to OKLCH. */\nexport function p3ToOklch(color: Srgb): Oklch {\n return oklabToOklch(linearP3ToOklab(srgbToLinearSrgb(color)));\n}\n\n/** Convert OKLCH to Display P3. May produce out-of-gamut values (channels outside [0,1]). */\nexport function oklchToP3(color: Oklch): Srgb {\n return linearSrgbToSrgb(oklabToLinearP3(oklchToOklab(color)));\n}\n\n/** Convert OKLCH to a CSS `color(display-p3 r g b)` string. Clamps channels to [0,1]. */\nexport function oklchToP3Css(color: Oklch): string {\n const p3 = oklchToP3(color);\n const r = Math.max(0, Math.min(1, p3.r)).toFixed(4);\n const g = Math.max(0, Math.min(1, p3.g)).toFixed(4);\n const b = Math.max(0, Math.min(1, p3.b)).toFixed(4);\n return `color(display-p3 ${r} ${g} ${b})`;\n}\n","import type { Srgb } from \"../types.js\";\nimport { GAMUT_EPSILON } from \"../constants.js\";\n\n/** Check if sRGB channels are within [0, 1] (with epsilon tolerance). */\nexport function isInGamut(color: Srgb): boolean {\n return (\n color.r >= -GAMUT_EPSILON &&\n color.r <= 1 + GAMUT_EPSILON &&\n color.g >= -GAMUT_EPSILON &&\n color.g <= 1 + GAMUT_EPSILON &&\n color.b >= -GAMUT_EPSILON &&\n color.b <= 1 + GAMUT_EPSILON\n );\n}\n\n/** Clamp sRGB channels to [0, 1]. */\nexport function clampSrgb(color: Srgb): Srgb {\n return {\n r: Math.max(0, Math.min(1, color.r)),\n g: Math.max(0, Math.min(1, color.g)),\n b: Math.max(0, Math.min(1, color.b)),\n };\n}\n\n/** Clamp Display P3 channels to [0, 1]. */\nexport const clampP3 = clampSrgb;\n","import type { Oklab, Oklch } from \"../types.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\n\n/** Compute deltaEOK (Euclidean distance in OKLAB) between two OKLCH colors. */\nexport function deltaEOK(a: Oklch, b: Oklch): number {\n return deltaEOKLab(oklchToOklab(a), oklchToOklab(b));\n}\n\n/** Compute deltaEOK directly from OKLAB values. */\nexport function deltaEOKLab(a: Oklab, b: Oklab): number {\n const dL = a.L - b.L;\n const da = a.a - b.a;\n const db = a.b - b.b;\n return Math.sqrt(dL * dL + da * da + db * db);\n}\n","import type { Gamut, Oklch, Srgb } from \"../types.js\";\nimport {\n GAMUT_EPSILON,\n GAMUT_MAP_EPSILON,\n GAMUT_MAP_JND,\n GAMUT_MAP_MAX_ITERATIONS,\n} from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut, clampSrgb } from \"./check.js\";\nimport { deltaEOKLab } from \"../color/difference.js\";\nimport { oklchToOklab } from \"../conversions/oklab.js\";\nimport { linearSrgbToOklab } from \"../conversions/linear-srgb.js\";\nimport { linearP3ToOklab } from \"../conversions/linear-p3.js\";\nimport { srgbToLinearSrgb } from \"../conversions/srgb.js\";\n\n/**\n * Map an OKLCH color into the target gamut using the CSS Color Level 4 algorithm.\n * Reduces chroma at fixed L and h via binary search with deltaEOK JND check.\n * @param gamut Target gamut (default: 'srgb').\n */\nexport function gamutMap(color: Oklch, gamut: Gamut = \"srgb\"): Oklch {\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n const rgbToOklab =\n gamut === \"display-p3\"\n ? (c: Srgb) => linearP3ToOklab(srgbToLinearSrgb(c))\n : (c: Srgb) => linearSrgbToOklab(srgbToLinearSrgb(c));\n\n // Already in gamut\n const rgb = toRgb(color);\n if (isInGamut(rgb)) return color;\n\n // Edge cases: black and white\n if (color.L <= GAMUT_EPSILON) return { L: 0, C: 0, h: color.h };\n if (color.L >= 1 - GAMUT_EPSILON) return { L: 1, C: 0, h: color.h };\n\n let lo = 0;\n let hi = color.C;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const midC = (lo + hi) / 2;\n const candidate: Oklch = { L: color.L, C: midC, h: color.h };\n const candidateRgb = toRgb(candidate);\n\n if (isInGamut(candidateRgb)) {\n lo = midC;\n } else {\n // Clip and check JND\n const clipped = clampSrgb(candidateRgb);\n const clippedLab = rgbToOklab(clipped);\n const candidateLab = oklchToOklab(candidate);\n const dE = deltaEOKLab(clippedLab, candidateLab);\n\n if (dE < GAMUT_MAP_JND) {\n // Clipped version is perceptually close enough — converge here.\n // Return lo (last confirmed in-gamut chroma) to guarantee gamut safety.\n break;\n }\n\n hi = midC;\n }\n\n if (hi - lo < GAMUT_MAP_EPSILON) break;\n }\n\n return { L: color.L, C: lo, h: color.h };\n}\n","import type { Gamut, Oklch } from \"../types.js\";\nimport { GAMUT_MAP_MAX_ITERATIONS } from \"../constants.js\";\nimport { oklchToSrgb, oklchToP3 } from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"./check.js\";\n\n/**\n * Find the maximum in-gamut chroma for a given OKLCH lightness and hue.\n *\n * Binary search over [0, upperBound], converging to 1e-6 precision.\n * Upper bounds are empirically safe ceilings — no in-gamut color at any\n * lightness or hue exceeds C = 0.4 in sRGB or C = 0.5 in Display P3.\n * Searching beyond these would waste iterations with no benefit.\n *\n * Returns 0 for L ≤ 0 or L ≥ 1 (pure black and white carry no chroma).\n */\nexport function maxChroma(L: number, h: number, gamut: Gamut = \"srgb\"): number {\n if (L <= 0 || L >= 1) return 0;\n\n const toRgb = gamut === \"display-p3\" ? oklchToP3 : oklchToSrgb;\n let lo = 0;\n let hi = gamut === \"display-p3\" ? 0.5 : 0.4;\n\n for (let i = 0; i < GAMUT_MAP_MAX_ITERATIONS; i++) {\n const mid = (lo + hi) / 2;\n const color: Oklch = { L, C: mid, h };\n const rgb = toRgb(color);\n\n if (isInGamut(rgb)) {\n lo = mid;\n } else {\n hi = mid;\n }\n\n if (hi - lo < 1e-6) break;\n }\n\n return lo;\n}\n","import type { Srgb } from \"../types.js\";\nimport { WCAG_R, WCAG_G, WCAG_B } from \"../constants.js\";\nimport { srgbChannelToLinear } from \"../conversions/srgb.js\";\n\n/** Compute WCAG 2.x relative luminance [0, 1] from an sRGB color. */\nexport function wcagLuminance(color: Srgb): number {\n return (\n WCAG_R * srgbChannelToLinear(color.r) +\n WCAG_G * srgbChannelToLinear(color.g) +\n WCAG_B * srgbChannelToLinear(color.b)\n );\n}\n\n/**\n * Compute WCAG 2.x contrast ratio between two sRGB colors.\n * Returns a value in [1, 21]. Symmetric (order doesn't matter).\n */\nexport function wcagContrast(a: Srgb, b: Srgb): number {\n const lA = wcagLuminance(a);\n const lB = wcagLuminance(b);\n const lighter = Math.max(lA, lB);\n const darker = Math.min(lA, lB);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\n/**\n * Choose black or white text for maximum WCAG contrast against a background.\n * @returns `\"#000000\"` or `\"#ffffff\"`.\n */\nexport function contrastTextHex(background: Srgb): \"#000000\" | \"#ffffff\" {\n const white: Srgb = { r: 1, g: 1, b: 1 };\n const black: Srgb = { r: 0, g: 0, b: 0 };\n return wcagContrast(white, background) > wcagContrast(black, background)\n ? \"#ffffff\"\n : \"#000000\";\n}\n","import type { Srgb } from \"../types.js\";\nimport {\n APCA_MAIN_TRC,\n APCA_SRGB_R,\n APCA_SRGB_G,\n APCA_SRGB_B,\n APCA_NORM_BG,\n APCA_NORM_TXT,\n APCA_REV_TXT,\n APCA_REV_BG,\n APCA_BLK_THRS,\n APCA_BLK_CLMP,\n APCA_SCALE_BOW,\n APCA_SCALE_WOB,\n APCA_LO_BOW_OFFSET,\n APCA_LO_WOB_OFFSET,\n APCA_DELTA_Y_MIN,\n APCA_LO_CLIP,\n} from \"../constants.js\";\n\n/**\n * Compute APCA-W3 Lc (Lightness Contrast) between text and background.\n *\n * Returns a signed value in roughly [-108, +106]:\n * Positive = dark text on light background (BoW)\n * Negative = light text on dark background (WoB)\n * 0 = no meaningful contrast\n *\n * IMPORTANT: Uses its own linearization (simple 2.4 gamma),\n * NOT the IEC piecewise sRGB transfer function.\n */\n/**\n * Practical maximum APCA Lc magnitude used for normalization.\n * BoW tops out at ~+106, WoB at ~-108; we use 108 as a symmetric ceiling.\n */\nexport const APCA_LC_MAX = 108;\n\n/**\n * Normalize a raw APCA Lc value to the range [-1, +1].\n * +1 = maximum dark-on-light contrast (BoW)\n * -1 = maximum light-on-dark contrast (WoB)\n * 0 = no meaningful contrast\n */\nexport function apcaToNormalized(lc: number): number {\n return Math.max(-1, Math.min(1, lc / APCA_LC_MAX));\n}\n\n/**\n * Convert a normalized contrast value [-1, +1] back to a raw APCA Lc value.\n */\nexport function normalizedToApca(normalized: number): number {\n return normalized * APCA_LC_MAX;\n}\n\nexport function apcaContrast(textColor: Srgb, bgColor: Srgb): number {\n // Step 1: Linearize with simple 2.4 gamma and compute Y\n let txtY =\n APCA_SRGB_R * textColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * textColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * textColor.b ** APCA_MAIN_TRC;\n\n let bgY =\n APCA_SRGB_R * bgColor.r ** APCA_MAIN_TRC +\n APCA_SRGB_G * bgColor.g ** APCA_MAIN_TRC +\n APCA_SRGB_B * bgColor.b ** APCA_MAIN_TRC;\n\n // Step 2: Soft black clamp\n if (txtY < APCA_BLK_THRS) {\n txtY += (APCA_BLK_THRS - txtY) ** APCA_BLK_CLMP;\n }\n if (bgY < APCA_BLK_THRS) {\n bgY += (APCA_BLK_THRS - bgY) ** APCA_BLK_CLMP;\n }\n\n // Step 3: Delta Y check\n if (Math.abs(bgY - txtY) < APCA_DELTA_Y_MIN) return 0;\n\n // Step 4: Polarity-aware contrast\n let sapc: number;\n\n if (bgY > txtY) {\n // Dark text on light background (BoW)\n sapc = (bgY ** APCA_NORM_BG - txtY ** APCA_NORM_TXT) * APCA_SCALE_BOW;\n return sapc < APCA_LO_CLIP ? 0 : (sapc - APCA_LO_BOW_OFFSET) * 100;\n } else {\n // Light text on dark background (WoB)\n sapc = (bgY ** APCA_REV_BG - txtY ** APCA_REV_TXT) * APCA_SCALE_WOB;\n return sapc > -APCA_LO_CLIP ? 0 : (sapc + APCA_LO_WOB_OFFSET) * 100;\n }\n}\n","import type { Oklch } from \"../types.js\";\nimport { ACHROMATIC_THRESHOLD } from \"../constants.js\";\n\n/**\n * Linearly interpolate between two OKLCH colors.\n *\n * L and C are linearly interpolated. Hue uses shortest-arc interpolation.\n * Achromatic colors (C near zero) inherit the other color's hue to avoid\n * meaningless hue sweeps through the achromatic pole.\n */\nexport function mix(a: Oklch, b: Oklch, t: number): Oklch {\n const L = a.L + (b.L - a.L) * t;\n const C = a.C + (b.C - a.C) * t;\n\n // Resolve hue — handle achromatic inputs\n const aIsAchromatic = a.C < ACHROMATIC_THRESHOLD;\n const bIsAchromatic = b.C < ACHROMATIC_THRESHOLD;\n\n if (aIsAchromatic && bIsAchromatic) {\n return { L, C, h: 0 };\n }\n\n const hA = aIsAchromatic ? b.h : a.h;\n const hB = bIsAchromatic ? a.h : b.h;\n\n // Shortest-arc hue interpolation\n let delta = hB - hA;\n if (delta > 180) delta -= 360;\n if (delta < -180) delta += 360;\n\n let h = hA + delta * t;\n if (h < 0) h += 360;\n if (h >= 360) h -= 360;\n\n return { L, C, h };\n}\n","/**\n * Design constants — the values you tune by hand.\n *\n * Edit this file to adjust the perceptual behavior of every scale and\n * grading operation across the library.\n */\n\n// ── Scale defaults ────────────────────────────────────────────────────────────\n\n/**\n * Default number of steps in a generated scale.\n * Fixed at 26 — enough for a full design token set with fine lightness\n * increments without redundancy.\n */\nexport const DEFAULT_SCALE_STEPS = 26;\n\n/**\n * Default hue when none is provided.\n * 0° is the start of the OKLCH hue wheel (red region). Arbitrary but\n * deterministic — callers should always supply an explicit hue.\n */\nexport const DEFAULT_HUE = 0;\n\n// ── Dynamic range ─────────────────────────────────────────────────────────────\n\n/**\n * Lightest step's lightness when the whites slider is at 0.\n * slider 0 → L = MIN_LIGHTEST_L, slider 1 → L = 1.0 (pure white).\n */\nexport const MIN_LIGHTEST_L = 0.96;\n\n/**\n * Darkest step's lightness when the darks slider is at 0.\n * slider 0 → L = MAX_DARKEST_L, slider 1 → L = 0.0 (pure black).\n */\nexport const MAX_DARKEST_L = 0.16;\n\n// ── Hue grading ───────────────────────────────────────────────────────────────\n\n/**\n * How far global grading reaches into the scale from each end (0–1).\n * Light grading fades to zero at t = GRADING_REACH.\n * Dark grading fades to zero at t = 1 − GRADING_REACH.\n */\nexport const GRADING_REACH = 3 / 5;\n\n/** Maximum amount for global grading. Inputs above this are clamped. */\nexport const MAX_GRADING_AMOUNT = 0.25;\n\n/**\n * Fraction of the gamut boundary injected as chroma when global grading\n * is active. Ensures grading has a visible tinting effect even on\n * achromatic (chroma.amount = 0) palettes.\n *\n * Only global grading injects chroma — per-palette shift does not.\n */\nexport const GRADING_CHROMA_RATIO = 0.5;\n\n/**\n * How far per-palette hue shift reaches into the scale from each end (0–1).\n * Slightly wider than GRADING_REACH to give per-palette shifts more room.\n */\nexport const SHIFT_REACH = 2 / 3;\n\n/** Maximum amount for per-palette hue shift. Inputs above this are clamped. */\nexport const MAX_SHIFT_AMOUNT = 0.5;\n\n// ── Color difference ──────────────────────────────────────────────────────────\n\n/**\n * Just-noticeable difference threshold (deltaEOK).\n * Colors with distance below this are considered perceptually identical.\n * Used to classify color matches as exact vs. fallback.\n */\nexport const PERCEPTUAL_JND = 0.02;\n","/**\n * Global hue grading — shifts each palette's base hue toward shared\n * target hues at the light and dark scale endpoints.\n *\n * Light grading fades from full at the lightest step to zero at GRADING_REACH.\n * Dark grading fades from zero at (1 - GRADING_REACH) to full at the darkest step.\n * In the overlap zone, both shifts are additive (commutative).\n */\n\nimport {\n GRADING_REACH,\n MAX_GRADING_AMOUNT,\n SHIFT_REACH,\n MAX_SHIFT_AMOUNT,\n} from \"../config.js\";\n\nexport interface Grading {\n /** Hue grading for the light end of the scale. */\n readonly light?: { readonly hue: number; readonly amount: number };\n /** Hue grading for the dark end of the scale. */\n readonly dark?: { readonly hue: number; readonly amount: number };\n}\n\n/** Per-palette hue shift (one end only). */\nexport interface Shift {\n /** Target hue to shift toward (0–360°). */\n readonly hue: number;\n /** Blend strength (0–MAX_SHIFT_AMOUNT). */\n readonly amount: number;\n /** Which end to affect. `true` = light end, `false`/omitted = dark end (default). */\n readonly light?: boolean;\n}\n\n/**\n * Compute the graded hue at position `t` in the scale.\n *\n * Uses vector interpolation in Cartesian space rather than angular deltas\n * to avoid the shortest-arc discontinuity at 180° (where the direction\n * of rotation flips abruptly). Each grade's displacement is computed as\n * a vector offset from the base hue, and displacements are additive\n * (commutative — order doesn't matter).\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param grade Hue grade configuration.\n * @param reach How far each grade reaches into the scale (default: GRADING_REACH).\n * @param maxIntensity Maximum amount clamp (default: MAX_GRADING_AMOUNT).\n * @returns The graded hue in degrees (0–360).\n */\nexport function gradeHue(\n baseHue: number,\n t: number,\n grade: Grading,\n reach: number = GRADING_REACH,\n maxIntensity: number = MAX_GRADING_AMOUNT,\n): number {\n const li = Math.max(0, Math.min(maxIntensity, grade.light?.amount ?? 0));\n const di = Math.max(0, Math.min(maxIntensity, grade.dark?.amount ?? 0));\n\n // Early exit: no grading\n if (li === 0 && di === 0) return baseHue;\n\n // Light influence: cosine fade from 1 at t=0 to 0 at t=reach\n const lightInfluence =\n t <= reach ? 0.5 * (1 + Math.cos((Math.PI * t) / reach)) : 0;\n\n // Dark influence: cosine fade from 0 at t=(1-reach) to 1 at t=1\n const darkInfluence =\n t >= 1 - reach\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / reach))\n : 0;\n\n // Base hue as unit vector\n const toRad = Math.PI / 180;\n const baseRad = baseHue * toRad;\n const bx = Math.cos(baseRad);\n const by = Math.sin(baseRad);\n\n // Accumulate displacements in Cartesian space\n let dx = 0;\n let dy = 0;\n\n if (lightInfluence > 0 && li > 0) {\n const blend = lightInfluence * li;\n const lRad = (grade.light!.hue) * toRad;\n dx += blend * (Math.cos(lRad) - bx);\n dy += blend * (Math.sin(lRad) - by);\n }\n\n if (darkInfluence > 0 && di > 0) {\n const blend = darkInfluence * di;\n const dRad = (grade.dark!.hue) * toRad;\n dx += blend * (Math.cos(dRad) - bx);\n dy += blend * (Math.sin(dRad) - by);\n }\n\n // Reconstruct hue from displaced vector\n const rx = bx + dx;\n const ry = by + dy;\n\n // Safety: collapsed vector (opposite hues at exactly 50% blend)\n if (rx * rx + ry * ry < 1e-20) return baseHue;\n\n return ((Math.atan2(ry, rx) / toRad) + 360) % 360;\n}\n\n/**\n * Compute the combined grading influence at position `t` (0–1).\n *\n * Returns a scalar in [0, 1] representing how strongly global grading\n * affects position `t`. This is the maximum of the light and dark\n * cosine-fade envelopes, each scaled by its respective amount.\n *\n * Used by the chroma injection system to tint achromatic palettes\n * proportionally to grading strength.\n */\nexport function gradingInfluence(t: number, grading: Grading): number {\n const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));\n const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));\n\n if (li === 0 && di === 0) return 0;\n\n const lightInfluence =\n t <= GRADING_REACH ? 0.5 * (1 + Math.cos((Math.PI * t) / GRADING_REACH)) : 0;\n\n const darkInfluence =\n t >= 1 - GRADING_REACH\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / GRADING_REACH))\n : 0;\n\n const lightBlend = lightInfluence * (li / MAX_GRADING_AMOUNT);\n const darkBlend = darkInfluence * (di / MAX_GRADING_AMOUNT);\n\n return Math.max(lightBlend, darkBlend);\n}\n\n/**\n * Resolve the final hue at position `t`, applying local shift first, then global grading.\n *\n * This is the canonical composition: per-palette shift (using SHIFT_REACH /\n * MAX_SHIFT_AMOUNT) first, then global grading (using GRADING_REACH /\n * MAX_GRADING_AMOUNT) on top — so grading's influence is preserved at full\n * strength across all palettes, keeping them visually coherent.\n *\n * @param baseHue The palette's own hue (0–360°).\n * @param t Position in the scale: 0 = lightest, 1 = darkest.\n * @param globalGrade Global grading (shared across palettes), or undefined.\n * @param localGrade Local grading (per-palette, expanded from Shift), or undefined.\n * @returns The fully graded hue in degrees (0–360).\n */\nexport function resolveGradedHue(\n baseHue: number,\n t: number,\n globalGrade?: Grading,\n localGrade?: Grading,\n): number {\n let h = baseHue;\n if (localGrade) h = gradeHue(h, t, localGrade, SHIFT_REACH, MAX_SHIFT_AMOUNT);\n if (globalGrade) h = gradeHue(h, t, globalGrade);\n return h;\n}\n\n/**\n * Adapt a Shift into a one-sided Grading so it can be passed to gradeHue.\n *\n * The Shift interface is flat (hue, amount, light?) for ergonomic API use,\n * but gradeHue operates on the Grading shape (light/dark sub-objects).\n * This function bridges the two, activating only the requested end.\n *\n * @param hue Target hue for the active side (0–360°).\n * @param amount Blend strength for the active side.\n * @param light `true` = light end, `false`/omitted = dark end (default).\n */\nexport function buildOneSidedGrade(\n hue: number,\n amount: number,\n light: boolean = false,\n): Grading {\n return light\n ? { light: { hue, amount } }\n : { dark: { hue, amount } };\n}\n","/**\n * Dynamic range resolution — maps slider values (0–1) to OKLCH lightness\n * bounds for the lightest and darkest steps of a color scale.\n */\n\nimport { MIN_LIGHTEST_L, MAX_DARKEST_L } from \"../config.js\";\n\n/**\n * Resolve a whites slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MIN_LIGHTEST_L (0.96), slider 1 → L = 1.0 (pure white)\n */\nexport function resolveLightest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MIN_LIGHTEST_L + s * (1.0 - MIN_LIGHTEST_L);\n}\n\n/**\n * Resolve a darks slider value (0–1) to an OKLCH lightness.\n * slider 0 → L = MAX_DARKEST_L (0.16), slider 1 → L = 0.0 (pure black)\n */\nexport function resolveDarkest(slider: number): number {\n const s = Math.max(0, Math.min(1, slider));\n return MAX_DARKEST_L * (1 - s);\n}\n\n/**\n * Map an OKLCH lightness to a normalized scale position (0–1).\n * 0 = lightest end, 1 = darkest end.\n *\n * Inverse of the lightness interpolation inside generateScale.\n * Useful for deriving chromaPeak from a key color's lightness.\n */\nexport function lightnessToScaleT(L: number, lightestL: number, darkestL: number): number {\n const range = lightestL - darkestL;\n if (range <= 0) return 0.5;\n return Math.max(0, Math.min(1, (lightestL - L) / range));\n}\n","import type { Oklch } from \"../types.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\nimport type { Grading, Shift } from \"./hue-grade.js\";\nimport { resolveGradedHue, buildOneSidedGrade } from \"./hue-grade.js\";\nimport { resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport {\n DEFAULT_SCALE_STEPS,\n DEFAULT_HUE,\n GRADING_CHROMA_RATIO,\n GRADING_REACH,\n MAX_GRADING_AMOUNT,\n} from \"../config.js\";\n\ntype Gamut = \"srgb\" | \"display-p3\";\nconst toRad = Math.PI / 180;\n\n/**\n * Apply grading as an additive chroma overlay.\n *\n * Builds per-side chroma vectors pointing at the grading TARGET hues\n * (not the palette's hue) and adds them to the palette's existing\n * chroma in Cartesian (a, b) space. This ensures grading tints even\n * fully achromatic palettes without the base hue leaking through.\n */\nfunction applyGradingOverlay(\n C: number, h: number, L: number, t: number,\n grading: Grading, gamut: Gamut,\n): { C: number; h: number } {\n const li = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.light?.amount ?? 0));\n const di = Math.max(0, Math.min(MAX_GRADING_AMOUNT, grading.dark?.amount ?? 0));\n if (li === 0 && di === 0) return { C, h };\n\n // Per-side cosine-fade influences\n const lightFade = t <= GRADING_REACH\n ? 0.5 * (1 + Math.cos((Math.PI * t) / GRADING_REACH)) : 0;\n const darkFade = t >= 1 - GRADING_REACH\n ? 0.5 * (1 + Math.cos((Math.PI * (1 - t)) / GRADING_REACH)) : 0;\n\n const lightBlend = lightFade * (li / MAX_GRADING_AMOUNT);\n const darkBlend = darkFade * (di / MAX_GRADING_AMOUNT);\n if (lightBlend === 0 && darkBlend === 0) return { C, h };\n\n // Palette's existing chroma as Cartesian vector\n const hRad = h * toRad;\n let a = C * Math.cos(hRad);\n let b = C * Math.sin(hRad);\n\n // Add overlay vectors at grading TARGET hues\n if (lightBlend > 0) {\n const lh = grading.light!.hue;\n const lRad = lh * toRad;\n const lC = maxChroma(L, lh, gamut) * GRADING_CHROMA_RATIO * lightBlend;\n a += lC * Math.cos(lRad);\n b += lC * Math.sin(lRad);\n }\n if (darkBlend > 0) {\n const dh = grading.dark!.hue;\n const dRad = dh * toRad;\n const dC = maxChroma(L, dh, gamut) * GRADING_CHROMA_RATIO * darkBlend;\n a += dC * Math.cos(dRad);\n b += dC * Math.sin(dRad);\n }\n\n // Convert back to polar\n let newC = Math.sqrt(a * a + b * b);\n let newH = ((Math.atan2(b, a) / toRad) + 360) % 360;\n\n // Clamp to gamut at the resulting hue\n newC = Math.min(newC, maxChroma(L, newH, gamut));\n\n return { C: newC, h: newH };\n}\n\nexport interface ScaleOptions {\n /**\n * Tonal range of the scale.\n * - `light`: how light the lightest step is (0–1). Default: 1.\n * 0 → L = MIN_LIGHTEST_L (0.96), 1 → L = 1.0 (pure white).\n * - `dark`: how dark the darkest step is (0–1). Default: 1.\n * 0 → L = MAX_DARKEST_L (0.16), 1 → L = 0.0 (pure black).\n */\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n /**\n * Hue angle in degrees (0–360). Default: DEFAULT_HUE (0).\n * Every step shares this base hue unless shifted by `grading` or `shift`.\n */\n readonly hue?: number;\n /**\n * Chroma shape of the scale.\n * - `amount`: how much of the available gamut to use (0–1). Default: 0.\n * 0 = fully achromatic (default), 1 = maximum in-gamut chroma at each lightness.\n * - `balance`: how chroma is distributed along the lightness range (0–1).\n * 0 = chroma concentrated toward the lightest end, 1 = toward the darkest end,\n * 0.5 = natural distribution (default, follows gamut boundary shape).\n */\n readonly chroma?: { readonly amount?: number; readonly balance?: number };\n /**\n * Global hue grading. When provided, the hue at each step is shifted\n * toward target hues based on position in the scale.\n * Light grading affects the lightest 3/5, dark grading affects the\n * darkest 3/5, with additive overlap in the middle fifth.\n */\n readonly grading?: Grading;\n /**\n * Per-palette hue shift. A one-sided grade applied before global\n * grading, with its own reach and strength limits (SHIFT_REACH,\n * MAX_SHIFT_AMOUNT). Defaults to the dark end; set `light: true` to target\n * the light end instead.\n */\n readonly shift?: Shift;\n /** Use Display P3 gamut instead of sRGB (default: false). */\n readonly isP3?: boolean;\n}\n\n/**\n * Generate an OKLCH color scale from lightest to darkest.\n *\n * Always produces DEFAULT_SCALE_STEPS colors. Chroma at each step is\n * proportional to the gamut boundary at that lightness, scaled by\n * `chroma.amount`. This guarantees every color is in-gamut — no fallbacks\n * needed — while producing a smooth, natural chroma curve.\n *\n * Use `contrast` to constrain the tonal range\n * (e.g. for scales that don't extend to pure white or pure black).\n *\n * Use `chroma.balance` to shift how chroma is distributed within the boundary.\n * The curve endpoints stay fixed while the distribution shifts smoothly.\n * The effective shift range is proportional to the headroom left by chroma.amount.\n */\nexport function generateScale(options: ScaleOptions = {}): Oklch[] {\n const {\n contrast,\n hue = DEFAULT_HUE,\n chroma,\n isP3 = false,\n grading,\n shift,\n } = options;\n const gamut = isP3 ? \"display-p3\" : \"srgb\";\n\n const steps = DEFAULT_SCALE_STEPS;\n const chromaRatio = chroma?.amount ?? 0;\n const chromaPeak = chroma?.balance ?? 0.5;\n const hueGrade = grading;\n const localHueGrade = shift ? buildOneSidedGrade(shift.hue, shift.amount, shift.light) : undefined;\n\n const ratio = Math.max(0, Math.min(1, chromaRatio));\n const peak = Math.max(0, Math.min(1, chromaPeak));\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n\n // Helper: resolve hue at position t (applies local shift first, then global grading)\n const hueAt = (t: number) => resolveGradedHue(hue, t, hueGrade, localHueGrade);\n\n // Fast path: skip peak skew logic when balance has no effect.\n // - peak === 0.5: already at the natural gamut peak, nothing to shift\n // - ratio === 0: no chroma at all, boundary shape is irrelevant\n // - ratio >= 1: inner triangle equals the boundary triangle, no headroom to slide\n if (peak === 0.5 || ratio === 0 || ratio >= 1) {\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n let h = hueAt(t);\n // Chroma is shaped by the base hue's boundary to keep the curve smooth.\n // The shifted hue's boundary is used as a final in-gamut clamp only —\n // this prevents spikes when the shifted hue has more available chroma\n // than the base (e.g. blue → pink passing through the purple region).\n let C = Math.min(maxChroma(L, hue, gamut) * ratio, maxChroma(L, h, gamut));\n\n if (hueGrade) {\n const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);\n C = overlay.C;\n h = overlay.h;\n }\n\n scale.push({ L, C, h });\n }\n return scale;\n }\n\n // ── Peak skew logic ──\n // Warp the parameter t so the boundary peak appears at a shifted position.\n // Endpoints stay fixed (warp(0)=0, warp(1)=1), only the peak moves.\n\n // 1. Sample boundary to find natural peak and valid shift range\n const N = 100;\n let peakT = 0.5;\n let peakBoundaryC = 0;\n const boundarySamples: { t: number; C: number }[] = [];\n\n for (let i = 0; i <= N; i++) {\n const t = i / N;\n const L = lightestL - t * (lightestL - darkestL);\n // Sample the base hue's boundary — the same reference used when building\n // the warp below. Using the shifted hue here would skew peakT and the\n // valid range toward a hue-specific boundary shape, inconsistent with\n // how chroma is actually computed in step 4.\n const C = maxChroma(L, hue, gamut);\n boundarySamples.push({ t, C });\n if (C > peakBoundaryC) {\n peakBoundaryC = C;\n peakT = t;\n }\n }\n\n // 2. Find valid range: where boundary can accommodate the inner peak height\n const innerPeakC = peakBoundaryC * ratio;\n let validMinT = peakT;\n let validMaxT = peakT;\n\n for (const { t, C } of boundarySamples) {\n if (C >= innerPeakC - 1e-6) {\n if (t < validMinT) validMinT = t;\n if (t > validMaxT) validMaxT = t;\n }\n }\n\n // 3. Map chroma.balance (0–1) to valid range, normalized so 0.5 → peakT\n let targetT: number;\n if (peak <= 0.5) {\n targetT = validMinT + (peak / 0.5) * (peakT - validMinT);\n } else {\n targetT = peakT + ((peak - 0.5) / 0.5) * (validMaxT - peakT);\n }\n\n // Safety: if the piecewise mapping produces a degenerate targetT (outside\n // (0, 1)), fall back to the natural peak. This can occur at floating-point\n // boundaries rather than from any single expected input combination.\n if (targetT <= 0 || targetT >= 1) {\n targetT = peakT;\n }\n\n // 4. Build scale with piecewise-linear warp: targetT → peakT\n const scale: Oklch[] = [];\n for (let i = 0; i < steps; i++) {\n const t = i / (steps - 1);\n const L = lightestL - t * (lightestL - darkestL);\n let h = hueAt(t);\n\n // Piecewise-linear warp: maps 0→0, targetT→peakT, 1→1.\n // Two segments scale t independently so the boundary peak (at peakT in\n // warp space) lands at targetT in the output — endpoints stay fixed.\n let tWarped: number;\n if (t <= targetT) {\n tWarped = t * (peakT / targetT);\n } else {\n tWarped = peakT + (t - targetT) * ((1 - peakT) / (1 - targetT));\n }\n\n const Lwarped = lightestL - tWarped * (lightestL - darkestL);\n // Use the base hue for the warped chroma lookup — consistent with step 1\n // and the fast path. The warp is purely a lightness operation; mixing in\n // the shifted hue at tWarped would introduce cross-position hue artifacts.\n const warpedC = maxChroma(Lwarped, hue, gamut) * ratio;\n // Clamp to the shifted hue's actual boundary at this L: the in-gamut\n // guarantee for the final color { L, C, h }.\n const boundaryC = maxChroma(L, h, gamut);\n let C = Math.min(warpedC, boundaryC);\n\n if (hueGrade) {\n const overlay = applyGradingOverlay(C, h, L, t, hueGrade, gamut);\n C = overlay.C;\n h = overlay.h;\n }\n\n scale.push({ L, C, h });\n }\n\n return scale;\n}\n","import type { Hex, Oklch, Gamut } from \"../types.js\";\nimport {\n hexToOklch,\n oklchToSrgb,\n oklchToP3,\n oklchToHex,\n} from \"../conversions/pipeline.js\";\nimport { isInGamut } from \"../gamut/check.js\";\nimport { gamutMap } from \"../gamut/map.js\";\nimport { maxChroma } from \"../gamut/max-chroma.js\";\n\n/**\n * Result of resolving a color into scale-ready parameters.\n */\nexport interface ResolvedColor {\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Hex representation (sRGB-clamped if the resolved color exceeds sRGB). */\n readonly hex: Hex;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n /** Chroma lost during gamut mapping (0 if in-gamut). */\n readonly chromaShift: number;\n /** Hue from the resolved color. */\n readonly hue: number;\n /** Chroma as a fraction of the gamut boundary at this L/h (0–1). */\n readonly chromaRatio: number;\n}\n\n/**\n * Resolve a color (hex or OKLCH) into scale-ready parameters.\n *\n * If the color is outside the target gamut, it is perceptually mapped to the\n * nearest in-gamut color (chroma reduction at fixed L and h). The result\n * includes the derived hue and chromaRatio.\n *\n * Hex input is always valid sRGB, so `wasRemapped` will be false for hex\n * with gamut=\"srgb\". OKLCH input may be out of gamut and will be mapped.\n *\n * @param input A hex string (#RGB, #RRGGBB) or an OKLCH color.\n * @param isP3 Use Display P3 gamut instead of sRGB (default: false).\n */\nexport function resolveColor(\n input: Hex | Oklch,\n isP3: boolean = false,\n): ResolvedColor {\n const gamut: Gamut = isP3 ? \"display-p3\" : \"srgb\";\n const isHex = typeof input === \"string\";\n const original: Oklch = isHex ? hexToOklch(input) : input;\n\n // Hex encodes valid sRGB by definition, and sRGB ⊂ P3, so hex input\n // is always in-gamut for both supported gamuts. Skipping the round-trip\n // check avoids false negatives from floating-point drift.\n let inGamut: boolean;\n if (isHex) {\n inGamut = true;\n } else {\n const rgb =\n gamut === \"display-p3\" ? oklchToP3(original) : oklchToSrgb(original);\n inGamut = isInGamut(rgb);\n }\n\n const oklch = inGamut ? original : gamutMap(original, gamut);\n\n const boundary = maxChroma(oklch.L, oklch.h, gamut);\n const chromaRatio = boundary > 0 ? oklch.C / boundary : 0;\n\n return {\n oklch,\n hex: oklchToHex(oklch),\n wasRemapped: !inGamut,\n original,\n chromaShift: original.C - oklch.C,\n hue: oklch.h,\n chromaRatio: Math.min(1, chromaRatio),\n };\n}\n","import type { Hex, Oklch } from \"../types.js\";\nimport { resolveColor } from \"./resolve-color.js\";\nimport { lightnessToScaleT, resolveLightest, resolveDarkest } from \"./dynamic-range.js\";\nimport { DEFAULT_SCALE_STEPS } from \"../config.js\";\n\n/**\n * The result of deriving scale parameters from a key color.\n *\n * Spread `hue` and `chroma` directly into ScaleOptions, then use\n * `stepIndex` to locate the key color's position in the generated scale.\n */\nexport interface KeyColorResult {\n /** Derived hue angle — use directly as ScaleOptions.hue. */\n readonly hue: number;\n /**\n * Derived chroma shape — use directly as ScaleOptions.chroma.\n * - `amount`: how saturated the scale is (0–1, relative to gamut boundary).\n * - `balance`: where in the scale the key color's lightness falls (0 = lightest, 1 = darkest).\n */\n readonly chroma: { readonly amount: number; readonly balance: number };\n /** The step index in a scale of `steps` length where this color lands. */\n readonly stepIndex: number;\n /** Hex representation of the resolved color (sRGB-clamped if necessary). */\n readonly hex: Hex;\n /** The final OKLCH color, guaranteed in-gamut for the target gamut. */\n readonly oklch: Oklch;\n /** Whether the input was outside the target gamut and was remapped. */\n readonly wasRemapped: boolean;\n /** The original OKLCH before gamut mapping (identical to oklch if in-gamut). */\n readonly original: Oklch;\n}\n\n/**\n * Derive scale parameters from a known color.\n *\n * Given a hex or OKLCH color, returns the `hue` and `chroma` values\n * ready to spread into ScaleOptions. The chroma balance is derived from\n * where the color's lightness falls within the scale's lightness range,\n * so the chroma distribution is centered around the key color's position.\n *\n * @param color A hex string (#RGB or #RRGGBB) or an OKLCH color object.\n * @param options Scale context — must match the ScaleOptions you will use.\n * `contrast` values are slider values (0–1), same as ScaleOptions.contrast.\n * `steps` is the number of steps in the scale (default: 26).\n *\n * @example\n * const key = keyColor('#3B82F6');\n * const scale = generateScale({ hue: key.hue, chroma: key.chroma });\n * const matchedHex = oklchToHex(scale[key.stepIndex]);\n */\nexport function keyColor(\n color: Hex | Oklch,\n options?: {\n readonly isP3?: boolean;\n readonly contrast?: { readonly light?: number; readonly dark?: number };\n readonly steps?: number;\n },\n): KeyColorResult {\n const { isP3 = false, contrast, steps = DEFAULT_SCALE_STEPS } = options ?? {};\n const resolved = resolveColor(color, isP3);\n const lightestL = resolveLightest(contrast?.light ?? 1);\n const darkestL = resolveDarkest(contrast?.dark ?? 1);\n const balance = lightnessToScaleT(resolved.oklch.L, lightestL, darkestL);\n const stepIndex = Math.round(balance * Math.max(0, steps - 1));\n\n return {\n hue: resolved.hue,\n chroma: { amount: resolved.chromaRatio, balance },\n stepIndex,\n hex: resolved.hex,\n oklch: resolved.oklch,\n wasRemapped: resolved.wasRemapped,\n original: resolved.original,\n };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/scale/generate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAKrD,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,YAAiB,GAAG,KAAK,EAAE,CAgIjE"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/scale/generate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAuErD,MAAM,WAAW,YAAY;IAC3B;;;;;;OAMG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxE;;;OAGG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1E;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;IACvB,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,YAAiB,GAAG,KAAK,EAAE,CA6IjE"}
@@ -44,6 +44,17 @@ export interface Shift {
44
44
  * @returns The graded hue in degrees (0–360).
45
45
  */
46
46
  export declare function gradeHue(baseHue: number, t: number, grade: Grading, reach?: number, maxIntensity?: number): number;
47
+ /**
48
+ * Compute the combined grading influence at position `t` (0–1).
49
+ *
50
+ * Returns a scalar in [0, 1] representing how strongly global grading
51
+ * affects position `t`. This is the maximum of the light and dark
52
+ * cosine-fade envelopes, each scaled by its respective amount.
53
+ *
54
+ * Used by the chroma injection system to tint achromatic palettes
55
+ * proportionally to grading strength.
56
+ */
57
+ export declare function gradingInfluence(t: number, grading: Grading): number;
47
58
  /**
48
59
  * Resolve the final hue at position `t`, applying local shift first, then global grading.
49
60
  *
@@ -1 +1 @@
1
- {"version":3,"file":"hue-grade.d.ts","sourceRoot":"","sources":["../../src/scale/hue-grade.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,MAAM,WAAW,OAAO;IACtB,kDAAkD;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAED,4CAA4C;AAC5C,MAAM,WAAW,KAAK;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qFAAqF;IACrF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,MAAsB,EAC7B,YAAY,GAAE,MAA2B,GACxC,MAAM,CAiDR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,CAAC,EAAE,MAAM,EACT,WAAW,CAAC,EAAE,OAAO,EACrB,UAAU,CAAC,EAAE,OAAO,GACnB,MAAM,CAKR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,OAAe,GACrB,OAAO,CAIT"}
1
+ {"version":3,"file":"hue-grade.d.ts","sourceRoot":"","sources":["../../src/scale/hue-grade.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,MAAM,WAAW,OAAO;IACtB,kDAAkD;IAClD,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CACnE;AAED,4CAA4C;AAC5C,MAAM,WAAW,KAAK;IACpB,2CAA2C;IAC3C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,qFAAqF;IACrF,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,QAAQ,CACtB,OAAO,EAAE,MAAM,EACf,CAAC,EAAE,MAAM,EACT,KAAK,EAAE,OAAO,EACd,KAAK,GAAE,MAAsB,EAC7B,YAAY,GAAE,MAA2B,GACxC,MAAM,CAiDR;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAkBpE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,MAAM,EACf,CAAC,EAAE,MAAM,EACT,WAAW,CAAC,EAAE,OAAO,EACrB,UAAU,CAAC,EAAE,OAAO,GACnB,MAAM,CAKR;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,EACd,KAAK,GAAE,OAAe,GACrB,OAAO,CAIT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newtonedev/colors",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Color scale engine — produces accessible color scales from declarative parameters",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",