@tenphi/glaze 0.14.0 → 0.15.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/index.cjs CHANGED
@@ -258,10 +258,48 @@ const getCs = (L, a, b, cusp) => {
258
258
  cMax
259
259
  ];
260
260
  };
261
+ const CYAN_A = Math.cos(199.8 * Math.PI / 180);
262
+ const CYAN_B = Math.sin(199.8 * Math.PI / 180);
263
+ const BLUE_A = Math.cos(267.4 * Math.PI / 180);
264
+ const BLUE_B = Math.sin(267.4 * Math.PI / 180);
265
+ let cyanCusp;
266
+ let blueCusp;
267
+ /**
268
+ * Computes the maximum safe OKLCH chroma that fits inside the sRGB gamut
269
+ * for all possible hues at a given OKLab lightness `L`.
270
+ */
271
+ function computeSafeChromaOKLCH(L) {
272
+ if (!cyanCusp) cyanCusp = findCuspOKLCH(CYAN_A, CYAN_B);
273
+ if (!blueCusp) blueCusp = findCuspOKLCH(BLUE_A, BLUE_B);
274
+ const c1 = findGamutIntersectionOKLCH(CYAN_A, CYAN_B, L, 1, L, cyanCusp);
275
+ const c2 = findGamutIntersectionOKLCH(BLUE_A, BLUE_B, L, 1, L, blueCusp);
276
+ return Math.min(c1, c2);
277
+ }
278
+ /** Per-hue cusp-lightness cache. The cusp is mode-independent, so keying on
279
+ * a rounded hue is safe and keeps the cache small. */
280
+ const cuspLightnessCache = /* @__PURE__ */ new Map();
281
+ /**
282
+ * OKHSL lightness of the gamut cusp for a hue — the lightness where the
283
+ * realizable chroma peaks. Reuses the same `find_cusp` OKHSL already runs for
284
+ * its `s` normalization (no new color math); the OKLab cusp lightness is run
285
+ * through the OKHSL `toe` and clamped to `[0.001, 0.999]` so divisions that
286
+ * key off it stay safe. Cached per (rounded) hue.
287
+ *
288
+ * @param h Hue, 0–360.
289
+ */
290
+ function cuspLightness(h) {
291
+ const key = Math.round(constrainAngle(h) * 100) / 100;
292
+ const cached = cuspLightnessCache.get(key);
293
+ if (cached !== void 0) return cached;
294
+ const hNorm = key / 360;
295
+ const lc = clampVal(toe(findCuspOKLCH(Math.cos(TAU * hNorm), Math.sin(TAU * hNorm))[0]), .001, .999);
296
+ cuspLightnessCache.set(key, lc);
297
+ return lc;
298
+ }
261
299
  /**
262
300
  * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to OKLab [L, a, b].
263
301
  */
264
- function okhslToOklab(h, s, l) {
302
+ function okhslToOklab(h, s, l, pastel = false) {
265
303
  const L = toeInv(l);
266
304
  let a = 0;
267
305
  let b = 0;
@@ -269,24 +307,30 @@ function okhslToOklab(h, s, l) {
269
307
  if (L !== 0 && L !== 1 && s !== 0) {
270
308
  const a_ = Math.cos(TAU * hNorm);
271
309
  const b_ = Math.sin(TAU * hNorm);
272
- const [c0, cMid, cMax] = getCs(L, a_, b_, findCuspOKLCH(a_, b_));
273
- const mid = .8;
274
- const midInv = 1.25;
275
- let t, k0, k1, k2;
276
- if (s < mid) {
277
- t = midInv * s;
278
- k0 = 0;
279
- k1 = mid * c0;
280
- k2 = 1 - k1 / cMid;
310
+ if (pastel) {
311
+ const c = s * computeSafeChromaOKLCH(L);
312
+ a = c * a_;
313
+ b = c * b_;
281
314
  } else {
282
- t = 5 * (s - .8);
283
- k0 = cMid;
284
- k1 = .2 * cMid ** 2 * 1.25 ** 2 / c0;
285
- k2 = 1 - k1 / (cMax - cMid);
315
+ const [c0, cMid, cMax] = getCs(L, a_, b_, findCuspOKLCH(a_, b_));
316
+ const mid = .8;
317
+ const midInv = 1.25;
318
+ let t, k0, k1, k2;
319
+ if (s < mid) {
320
+ t = midInv * s;
321
+ k0 = 0;
322
+ k1 = mid * c0;
323
+ k2 = 1 - k1 / cMid;
324
+ } else {
325
+ t = 5 * (s - .8);
326
+ k0 = cMid;
327
+ k1 = .2 * cMid ** 2 * 1.25 ** 2 / c0;
328
+ k2 = 1 - k1 / (cMax - cMid);
329
+ }
330
+ const c = k0 + t * k1 / (1 - k2 * t);
331
+ a = c * a_;
332
+ b = c * b_;
286
333
  }
287
- const c = k0 + t * k1 / (1 - k2 * t);
288
- a = c * a_;
289
- b = c * b_;
290
334
  }
291
335
  return [
292
336
  L,
@@ -298,8 +342,8 @@ function okhslToOklab(h, s, l) {
298
342
  * Convert OKHSL (h: 0–360, s: 0–1, l: 0–1) to linear sRGB.
299
343
  * Channels may exceed [0, 1] near gamut boundaries — caller must clamp if needed.
300
344
  */
301
- function okhslToLinearSrgb(h, s, l) {
302
- return OKLabToLinearSRGB(okhslToOklab(h, s, l));
345
+ function okhslToLinearSrgb(h, s, l, pastel = false) {
346
+ return OKLabToLinearSRGB(okhslToOklab(h, s, l, pastel));
303
347
  }
304
348
  /**
305
349
  * Compute relative luminance Y from linear sRGB channels.
@@ -329,8 +373,8 @@ const sRGBGammaToLinear = (val) => {
329
373
  /**
330
374
  * Convert OKHSL to gamma-encoded sRGB (clamped to 0–1).
331
375
  */
332
- function okhslToSrgb(h, s, l) {
333
- const lin = okhslToLinearSrgb(h, s, l);
376
+ function okhslToSrgb(h, s, l, pastel = false) {
377
+ const lin = okhslToLinearSrgb(h, s, l, pastel);
334
378
  return [
335
379
  Math.max(0, Math.min(1, sRGBLinearToGamma(lin[0]))),
336
380
  Math.max(0, Math.min(1, sRGBLinearToGamma(lin[1]))),
@@ -372,7 +416,7 @@ const linearSrgbToOklab = (rgb) => {
372
416
  * Input: [L, a, b] where L: 0–1, a/b: roughly -0.5 to 0.5.
373
417
  * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.
374
418
  */
375
- const oklabToOkhsl = (lab) => {
419
+ const oklabToOkhsl = (lab, pastel = false) => {
376
420
  const L = lab[0];
377
421
  const a = lab[1];
378
422
  const b = lab[2];
@@ -392,19 +436,22 @@ const oklabToOkhsl = (lab) => {
392
436
  const b_ = b / C;
393
437
  let h = Math.atan2(b, a) * (180 / Math.PI);
394
438
  h = constrainAngle(h);
395
- const [c0, cMid, cMax] = getCs(L, a_, b_, findCuspOKLCH(a_, b_));
396
- const mid = .8;
397
- const midInv = 1.25;
398
439
  let s;
399
- if (C < cMid) {
400
- const k1 = mid * c0;
401
- s = C / (k1 + C * (1 - k1 / cMid)) / midInv;
402
- } else {
403
- const k0 = cMid;
404
- const k1 = .2 * cMid ** 2 * 1.25 ** 2 / c0;
405
- const k2 = 1 - k1 / (cMax - cMid);
406
- const cDiff = C - k0;
407
- s = mid + cDiff / (k1 + cDiff * k2) / 5;
440
+ if (pastel) s = C / computeSafeChromaOKLCH(L);
441
+ else {
442
+ const [c0, cMid, cMax] = getCs(L, a_, b_, findCuspOKLCH(a_, b_));
443
+ const mid = .8;
444
+ const midInv = 1.25;
445
+ if (C < cMid) {
446
+ const k1 = mid * c0;
447
+ s = C / (k1 + C * (1 - k1 / cMid)) / midInv;
448
+ } else {
449
+ const k0 = cMid;
450
+ const k1 = .2 * cMid ** 2 * 1.25 ** 2 / c0;
451
+ const k2 = 1 - k1 / (cMax - cMid);
452
+ const cDiff = C - k0;
453
+ s = mid + cDiff / (k1 + cDiff * k2) / 5;
454
+ }
408
455
  }
409
456
  const l = toe(L);
410
457
  return [
@@ -417,12 +464,12 @@ const oklabToOkhsl = (lab) => {
417
464
  * Convert gamma-encoded sRGB (0–1 per channel) to OKHSL.
418
465
  * Returns [h, s, l] where h: 0–360, s: 0–1, l: 0–1.
419
466
  */
420
- function srgbToOkhsl(rgb) {
467
+ function srgbToOkhsl(rgb, pastel = false) {
421
468
  return oklabToOkhsl(linearSrgbToOklab([
422
469
  sRGBGammaToLinear(rgb[0]),
423
470
  sRGBGammaToLinear(rgb[1]),
424
471
  sRGBGammaToLinear(rgb[2])
425
- ]));
472
+ ]), pastel);
426
473
  }
427
474
  /**
428
475
  * Convert CSS HSL (sRGB-based) to gamma-encoded sRGB [r, g, b] in 0–1 range.
@@ -537,24 +584,26 @@ function fmt$1(value, decimals) {
537
584
  * Format OKHSL values as a CSS `okhsl(H S% L%)` string.
538
585
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
539
586
  */
540
- function formatOkhsl(h, s, l) {
541
- return `okhsl(${fmt$1(h, 2)} ${fmt$1(s, 2)}% ${fmt$1(l, 2)}%)`;
587
+ function formatOkhsl(h, s, l, pastel = false) {
588
+ let outS = s;
589
+ if (pastel) outS = oklabToOkhsl(okhslToOklab(h, s / 100, l / 100, true), false)[1] * 100;
590
+ return `okhsl(${fmt$1(h, 2)} ${fmt$1(outS, 2)}% ${fmt$1(l, 2)}%)`;
542
591
  }
543
592
  /**
544
593
  * Format OKHSL values as a CSS `rgb(R G B)` string.
545
594
  * Uses 2 decimal places to avoid 8-bit quantization contrast loss.
546
595
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
547
596
  */
548
- function formatRgb(h, s, l) {
549
- const [r, g, b] = okhslToSrgb(h, s / 100, l / 100);
597
+ function formatRgb(h, s, l, pastel = false) {
598
+ const [r, g, b] = okhslToSrgb(h, s / 100, l / 100, pastel);
550
599
  return `rgb(${parseFloat((r * 255).toFixed(2))} ${parseFloat((g * 255).toFixed(2))} ${parseFloat((b * 255).toFixed(2))})`;
551
600
  }
552
601
  /**
553
602
  * Format OKHSL values as a CSS `hsl(H S% L%)` string.
554
603
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
555
604
  */
556
- function formatHsl(h, s, l) {
557
- const [r, g, b] = okhslToSrgb(h, s / 100, l / 100);
605
+ function formatHsl(h, s, l, pastel = false) {
606
+ const [r, g, b] = okhslToSrgb(h, s / 100, l / 100, pastel);
558
607
  const max = Math.max(r, g, b);
559
608
  const min = Math.min(r, g, b);
560
609
  const delta = max - min;
@@ -573,8 +622,8 @@ function formatHsl(h, s, l) {
573
622
  * Format OKHSL values as a CSS `oklch(L C H)` string.
574
623
  * h: 0–360, s: 0–100, l: 0–100 (percentage scale for s and l).
575
624
  */
576
- function formatOklch(h, s, l) {
577
- const [L, a, b] = okhslToOklab(h, s / 100, l / 100);
625
+ function formatOklch(h, s, l, pastel = false) {
626
+ const [L, a, b] = okhslToOklab(h, s / 100, l / 100, pastel);
578
627
  const C = Math.sqrt(a * a + b * b);
579
628
  let hh = Math.atan2(b, a) * (180 / Math.PI);
580
629
  hh = constrainAngle(hh);
@@ -600,7 +649,6 @@ function defaultConfig() {
600
649
  eps: .05
601
650
  },
602
651
  darkDesaturation: .1,
603
- saturationTaper: .15,
604
652
  states: {
605
653
  dark: "@dark",
606
654
  highContrast: "@high-contrast"
@@ -609,7 +657,8 @@ function defaultConfig() {
609
657
  dark: true,
610
658
  highContrast: false
611
659
  },
612
- autoFlip: true
660
+ autoFlip: true,
661
+ pastel: false
613
662
  };
614
663
  }
615
664
  let globalConfig = defaultConfig();
@@ -639,7 +688,6 @@ function configure(config) {
639
688
  lightTone: config.lightTone ?? globalConfig.lightTone,
640
689
  darkTone: config.darkTone ?? globalConfig.darkTone,
641
690
  darkDesaturation: config.darkDesaturation ?? globalConfig.darkDesaturation,
642
- saturationTaper: config.saturationTaper ?? globalConfig.saturationTaper,
643
691
  states: {
644
692
  dark: config.states?.dark ?? globalConfig.states.dark,
645
693
  highContrast: config.states?.highContrast ?? globalConfig.states.highContrast
@@ -649,7 +697,8 @@ function configure(config) {
649
697
  highContrast: config.modes?.highContrast ?? globalConfig.modes.highContrast
650
698
  },
651
699
  shadowTuning: config.shadowTuning ?? globalConfig.shadowTuning,
652
- autoFlip: config.autoFlip ?? globalConfig.autoFlip
700
+ autoFlip: config.autoFlip ?? globalConfig.autoFlip,
701
+ pastel: config.pastel ?? globalConfig.pastel
653
702
  };
654
703
  }
655
704
  function resetConfig() {
@@ -668,11 +717,11 @@ function mergeConfig(base, override) {
668
717
  lightTone: override.lightTone !== void 0 ? override.lightTone : base.lightTone,
669
718
  darkTone: override.darkTone !== void 0 ? override.darkTone : base.darkTone,
670
719
  darkDesaturation: override.darkDesaturation ?? base.darkDesaturation,
671
- saturationTaper: override.saturationTaper ?? base.saturationTaper,
672
720
  states: base.states,
673
721
  modes: base.modes,
674
722
  shadowTuning: override.shadowTuning ?? base.shadowTuning,
675
- autoFlip: override.autoFlip ?? base.autoFlip
723
+ autoFlip: override.autoFlip ?? base.autoFlip,
724
+ pastel: override.pastel ?? base.pastel
676
725
  };
677
726
  }
678
727
 
@@ -765,8 +814,8 @@ function isAbsoluteTone(tone) {
765
814
  * - the `{ h, s, t }` <-> `{ h, s, l }` color-space converters,
766
815
  * - the resolved-variant edge adapter (`variantToOkhsl`),
767
816
  * - the per-scheme tone mapping that replaced the Möbius dark curve
768
- * (`mapToneForScheme`), the saturation reducers, and the solver's
769
- * scheme tone range.
817
+ * (`mapToneForScheme`), the dark desaturation reducer, and the solver's scheme
818
+ * tone range.
770
819
  *
771
820
  * See `docs/okhst.md` for the full specification and the calibrated
772
821
  * default constants.
@@ -909,33 +958,6 @@ function mapSaturationDark(s, mode, config) {
909
958
  if (mode === "static") return s;
910
959
  return s * (1 - config.darkDesaturation);
911
960
  }
912
- /** Smoothstep `0..1`. */
913
- function smoothstep(x) {
914
- const t = clamp(x, 0, 1);
915
- return t * t * (3 - 2 * t);
916
- }
917
- /** Fraction of the tone range over which the taper ramps in, per end. */
918
- const TAPER_REGION = .15;
919
- /**
920
- * Gently taper saturation toward the tone extremes, where in-gamut chroma
921
- * collapses and high saturation reads as noise. `taper` is the *strength*
922
- * (0–1): the maximum fraction of saturation removed at the very edges. The
923
- * rolloff ramps in smoothly over the outer {@link TAPER_REGION} of tone on
924
- * each end, so mid-tones are untouched and high-tone surfaces keep most of
925
- * their color. `taper = 0` disables the effect.
926
- *
927
- * @param s Saturation (0–1).
928
- * @param toneFinal Stored canonical tone (0–1).
929
- * @param taper Strength (0–1); default config is a gentle 0.15.
930
- */
931
- function saturationEnvelope(s, toneFinal, taper) {
932
- if (taper <= 0) return s;
933
- const t = clamp(toneFinal, 0, 1);
934
- const strength = clamp(taper, 0, 1);
935
- const edge = Math.min(t, 1 - t);
936
- if (edge >= TAPER_REGION) return s;
937
- return s * (1 - strength * (1 - smoothstep(edge / TAPER_REGION)));
938
- }
939
961
  /**
940
962
  * Tone search range (0–1) for the contrast solver in a given scheme.
941
963
  * `static` searches the full range; otherwise the scheme window's tone
@@ -1040,12 +1062,12 @@ const cacheOrder = [];
1040
1062
  * the metric's luminance basis. The metric is part of the cache key because
1041
1063
  * WCAG and APCA derive different luminances from the same color.
1042
1064
  */
1043
- function cachedLuminance(metric, h, s, t) {
1065
+ function cachedLuminance(metric, h, s, t, pastel) {
1044
1066
  const tRounded = Math.round(t * 1e4) / 1e4;
1045
- const key = `${metric}|${h}|${s}|${tRounded}`;
1067
+ const key = `${metric}|${h}|${s}|${tRounded}|${pastel}`;
1046
1068
  const cached = luminanceCache.get(key);
1047
1069
  if (cached !== void 0) return cached;
1048
- const y = metricLuminance(metric, okhslToLinearSrgb(h, s, fromTone(tRounded * 100, REF_EPS)));
1070
+ const y = metricLuminance(metric, okhslToLinearSrgb(h, s, fromTone(tRounded * 100, REF_EPS), pastel));
1049
1071
  if (luminanceCache.size >= CACHE_SIZE) {
1050
1072
  const evict = cacheOrder.shift();
1051
1073
  luminanceCache.delete(evict);
@@ -1176,14 +1198,11 @@ function solveNearestContrast(opts) {
1176
1198
  * staying as close to `preferredTone` as possible.
1177
1199
  */
1178
1200
  function findToneForContrast(options) {
1179
- const { hue, saturation, preferredTone, baseLinearRgb, contrast, toneRange = [0, 1], epsilon = 1e-4, maxIterations = 18 } = options;
1201
+ const { hue, saturation, preferredTone, baseLinearRgb, contrast, toneRange = [0, 1], epsilon = 1e-4, maxIterations = 18, pastel = false } = options;
1180
1202
  const { metric, target } = contrast;
1181
1203
  const searchTarget = metric === "wcag" ? target * 1.01 : target + .5;
1182
1204
  const yBase = metricLuminance(metric, baseLinearRgb);
1183
- const taper = options.saturationTaper ?? 0;
1184
- const lum = taper > 0 ? (t) => {
1185
- return metricLuminance(metric, okhslToLinearSrgb(hue, saturationEnvelope(saturation, t, taper), fromTone(t * 100, REF_EPS)));
1186
- } : (t) => cachedLuminance(metric, hue, saturation, t);
1205
+ const lum = (t) => cachedLuminance(metric, hue, saturation, t, pastel);
1187
1206
  const scorePref = metricScore(metric, lum(preferredTone), yBase);
1188
1207
  if (scorePref >= searchTarget) return {
1189
1208
  tone: preferredTone,
@@ -1522,7 +1541,8 @@ function toOkhslVariant(v) {
1522
1541
  h: c.h,
1523
1542
  s: c.s,
1524
1543
  l: c.l,
1525
- alpha: v.alpha
1544
+ alpha: v.alpha,
1545
+ pastel: v.pastel
1526
1546
  };
1527
1547
  }
1528
1548
  /** Edge adapter: OKHSL-lightness variant → resolved variant (`t`). */
@@ -1569,6 +1589,7 @@ function resolveDependentColor(name, def, ctx, isHighContrast, isDark, effective
1569
1589
  const mode = def.mode ?? "auto";
1570
1590
  const satFactor = clamp(def.saturation ?? 1, 0, 1);
1571
1591
  const flip = def.flip ?? ctx.config.autoFlip;
1592
+ const pastel = def.pastel ?? ctx.config.pastel;
1572
1593
  const baseVariant = getSchemeVariant(baseResolved, isDark, isHighContrast);
1573
1594
  const baseTone = baseVariant.t * 100;
1574
1595
  let preferredTone;
@@ -1587,7 +1608,7 @@ function resolveDependentColor(name, def, ctx, isHighContrast, isDark, effective
1587
1608
  const resolvedContrast = resolveContrastSpec(rawContrast, isHighContrast);
1588
1609
  const effectiveSat = isDark ? mapSaturationDark(satFactor * ctx.saturation / 100, mode, ctx.config) : satFactor * ctx.saturation / 100;
1589
1610
  const baseOkhsl = toOkhslVariant(baseVariant);
1590
- const baseLinearRgb = okhslToLinearSrgb(baseOkhsl.h, baseOkhsl.s, baseOkhsl.l);
1611
+ const baseLinearRgb = okhslToLinearSrgb(baseOkhsl.h, baseOkhsl.s, baseOkhsl.l, baseVariant.pastel ?? ctx.config.pastel);
1591
1612
  const toneRange = schemeToneRange(isDark, mode, isHighContrast, ctx.config);
1592
1613
  let initialDirection;
1593
1614
  if (preferredTone < baseTone) initialDirection = "darker";
@@ -1601,7 +1622,7 @@ function resolveDependentColor(name, def, ctx, isHighContrast, isDark, effective
1601
1622
  toneRange: [0, 1],
1602
1623
  initialDirection,
1603
1624
  flip,
1604
- saturationTaper: ctx.config.saturationTaper
1625
+ pastel
1605
1626
  });
1606
1627
  if (!result.met) warnContrastUnmet(name, isDark, isHighContrast, resolvedContrast, result.contrast);
1607
1628
  return {
@@ -1621,6 +1642,7 @@ function resolveColorForScheme(name, def, ctx, isDark, isHighContrast) {
1621
1642
  const mode = regDef.mode ?? "auto";
1622
1643
  const isRoot = isAbsoluteTone(regDef.tone) && !regDef.base;
1623
1644
  const effectiveHue = resolveEffectiveHue(ctx.hue, regDef.hue);
1645
+ const pastel = regDef.pastel ?? ctx.config.pastel;
1624
1646
  let finalTone;
1625
1647
  let satFactor;
1626
1648
  if (isRoot) {
@@ -1633,14 +1655,14 @@ function resolveColorForScheme(name, def, ctx, isDark, isHighContrast) {
1633
1655
  satFactor = dep.satFactor;
1634
1656
  }
1635
1657
  const baseSat = satFactor * ctx.saturation / 100;
1636
- let finalSat = isDark ? mapSaturationDark(baseSat, mode, ctx.config) : baseSat;
1658
+ const finalSat = isDark ? mapSaturationDark(baseSat, mode, ctx.config) : baseSat;
1637
1659
  const toneFraction = clamp(finalTone / 100, 0, 1);
1638
- finalSat = saturationEnvelope(finalSat, toneFraction, ctx.config.saturationTaper);
1639
1660
  return {
1640
1661
  h: effectiveHue,
1641
1662
  s: clamp(finalSat, 0, 1),
1642
1663
  t: toneFraction,
1643
- alpha: regDef.opacity ?? 1
1664
+ alpha: regDef.opacity ?? 1,
1665
+ pastel
1644
1666
  };
1645
1667
  }
1646
1668
  function resolveShadowForScheme(def, ctx, isDark, isHighContrast) {
@@ -1649,10 +1671,13 @@ function resolveShadowForScheme(def, ctx, isDark, isHighContrast) {
1649
1671
  if (def.fg) fgVariant = toOkhslVariant(getSchemeVariant(ctx.resolved.get(def.fg), isDark, isHighContrast));
1650
1672
  const intensity = isHighContrast ? pairHC(def.intensity) : pairNormal(def.intensity);
1651
1673
  const tuning = resolveShadowTuning(def.tuning, ctx.config.shadowTuning);
1652
- return toToneVariant(computeShadow(bgVariant, fgVariant, intensity, tuning));
1674
+ return {
1675
+ ...toToneVariant(computeShadow(bgVariant, fgVariant, intensity, tuning)),
1676
+ pastel: def.pastel ?? ctx.config.pastel
1677
+ };
1653
1678
  }
1654
- function okhslVariantToLinearRgb(v) {
1655
- return okhslToLinearSrgb(v.h, v.s, v.l);
1679
+ function okhslVariantToLinearRgb(v, pastel) {
1680
+ return okhslToLinearSrgb(v.h, v.s, v.l, pastel);
1656
1681
  }
1657
1682
  /**
1658
1683
  * Resolve hue for OKHSL mixing, handling achromatic colors.
@@ -1675,12 +1700,12 @@ function linearSrgbLerp(base, target, t) {
1675
1700
  base[2] + (target[2] - base[2]) * t
1676
1701
  ];
1677
1702
  }
1678
- function linearRgbToToneVariant(rgb) {
1703
+ function linearRgbToToneVariant(rgb, pastel) {
1679
1704
  const [h, s, l] = srgbToOkhsl([
1680
1705
  Math.max(0, Math.min(1, sRGBLinearToGamma(rgb[0]))),
1681
1706
  Math.max(0, Math.min(1, sRGBLinearToGamma(rgb[1]))),
1682
1707
  Math.max(0, Math.min(1, sRGBLinearToGamma(rgb[2])))
1683
- ]);
1708
+ ], pastel);
1684
1709
  return toToneVariant({
1685
1710
  h,
1686
1711
  s,
@@ -1696,15 +1721,16 @@ function resolveMixForScheme(def, ctx, isDark, isHighContrast) {
1696
1721
  let t = clamp(isHighContrast ? pairHC(def.value) : pairNormal(def.value), 0, 100) / 100;
1697
1722
  const blend = def.blend ?? "opaque";
1698
1723
  const space = def.space ?? "okhsl";
1699
- const baseLinear = okhslVariantToLinearRgb(baseVariant);
1700
- const targetLinear = okhslVariantToLinearRgb(targetVariant);
1724
+ const pastel = def.pastel ?? ctx.config.pastel;
1725
+ const baseLinear = okhslVariantToLinearRgb(baseVariant, baseVariant.pastel ?? ctx.config.pastel);
1726
+ const targetLinear = okhslVariantToLinearRgb(targetVariant, targetVariant.pastel ?? ctx.config.pastel);
1701
1727
  if (def.contrast !== void 0) {
1702
1728
  const resolvedContrast = resolveContrastSpec(def.contrast, isHighContrast);
1703
1729
  const metric = resolvedContrast.metric;
1704
1730
  let luminanceAt;
1705
1731
  if (blend === "transparent" || space === "srgb") luminanceAt = (v) => metricLuminance(metric, linearSrgbLerp(baseLinear, targetLinear, v));
1706
1732
  else luminanceAt = (v) => {
1707
- return metricLuminance(metric, okhslToLinearSrgb(mixHue(baseVariant, targetVariant, v), baseVariant.s + (targetVariant.s - baseVariant.s) * v, baseVariant.l + (targetVariant.l - baseVariant.l) * v));
1733
+ return metricLuminance(metric, okhslToLinearSrgb(mixHue(baseVariant, targetVariant, v), baseVariant.s + (targetVariant.s - baseVariant.s) * v, baseVariant.l + (targetVariant.l - baseVariant.l) * v, pastel));
1708
1734
  };
1709
1735
  t = findValueForMixContrast({
1710
1736
  preferredValue: t,
@@ -1715,19 +1741,28 @@ function resolveMixForScheme(def, ctx, isDark, isHighContrast) {
1715
1741
  flip: ctx.config.autoFlip
1716
1742
  }).value;
1717
1743
  }
1718
- if (blend === "transparent") return toToneVariant({
1719
- h: targetVariant.h,
1720
- s: targetVariant.s,
1721
- l: targetVariant.l,
1722
- alpha: clamp(t, 0, 1)
1723
- });
1724
- if (space === "srgb") return linearRgbToToneVariant(linearSrgbLerp(baseLinear, targetLinear, t));
1725
- return toToneVariant({
1726
- h: mixHue(baseVariant, targetVariant, t),
1727
- s: clamp(baseVariant.s + (targetVariant.s - baseVariant.s) * t, 0, 1),
1728
- l: clamp(baseVariant.l + (targetVariant.l - baseVariant.l) * t, 0, 1),
1729
- alpha: 1
1730
- });
1744
+ if (blend === "transparent") return {
1745
+ ...toToneVariant({
1746
+ h: targetVariant.h,
1747
+ s: targetVariant.s,
1748
+ l: targetVariant.l,
1749
+ alpha: clamp(t, 0, 1)
1750
+ }),
1751
+ pastel
1752
+ };
1753
+ if (space === "srgb") return {
1754
+ ...linearRgbToToneVariant(linearSrgbLerp(baseLinear, targetLinear, t), pastel),
1755
+ pastel
1756
+ };
1757
+ return {
1758
+ ...toToneVariant({
1759
+ h: mixHue(baseVariant, targetVariant, t),
1760
+ s: clamp(baseVariant.s + (targetVariant.s - baseVariant.s) * t, 0, 1),
1761
+ l: clamp(baseVariant.l + (targetVariant.l - baseVariant.l) * t, 0, 1),
1762
+ alpha: 1
1763
+ }),
1764
+ pastel
1765
+ };
1731
1766
  }
1732
1767
  function defMode(def) {
1733
1768
  if (isShadowDef(def) || isMixDef(def)) return void 0;
@@ -1778,7 +1813,7 @@ function seedField(order, ctx, field, source) {
1778
1813
  * resolved with a `base` + `contrast` may land slightly under the contrast
1779
1814
  * its tone implies because chromatic luminance drifts from the gray tone.
1780
1815
  */
1781
- function verifyContrastDrift(order, defs, result) {
1816
+ function verifyContrastDrift(order, defs, result, config) {
1782
1817
  for (const name of order) {
1783
1818
  const def = defs[name];
1784
1819
  if (isShadowDef(def) || isMixDef(def)) continue;
@@ -1814,8 +1849,10 @@ function verifyContrastDrift(order, defs, result) {
1814
1849
  const bVariant = base[s.field];
1815
1850
  const cOkhsl = toOkhslVariant(cVariant);
1816
1851
  const bOkhsl = toOkhslVariant(bVariant);
1817
- const yC = metricLuminance(spec.metric, okhslToLinearSrgb(cOkhsl.h, cOkhsl.s, cOkhsl.l));
1818
- const yB = metricLuminance(spec.metric, okhslToLinearSrgb(bOkhsl.h, bOkhsl.s, bOkhsl.l));
1852
+ const cPastel = cVariant.pastel ?? config.pastel;
1853
+ const bPastel = bVariant.pastel ?? config.pastel;
1854
+ const yC = metricLuminance(spec.metric, okhslToLinearSrgb(cOkhsl.h, cOkhsl.s, cOkhsl.l, cPastel));
1855
+ const yB = metricLuminance(spec.metric, okhslToLinearSrgb(bOkhsl.h, bOkhsl.s, bOkhsl.l, bPastel));
1819
1856
  warnContrastDrift(name, s.isDark, s.isHighContrast, spec, yC, yB);
1820
1857
  }
1821
1858
  }
@@ -1848,7 +1885,7 @@ function resolveAllColors(hue, saturation, defs, config, externalBases) {
1848
1885
  darkContrast: darkHCMap.get(name),
1849
1886
  mode: defMode(defs[name])
1850
1887
  });
1851
- verifyContrastDrift(order, defs, result);
1888
+ verifyContrastDrift(order, defs, result, config);
1852
1889
  return result;
1853
1890
  }
1854
1891
 
@@ -1873,9 +1910,10 @@ const formatters = {
1873
1910
  function fmt(value, decimals) {
1874
1911
  return parseFloat(value.toFixed(decimals)).toString();
1875
1912
  }
1876
- function formatVariant(v, format = "okhsl") {
1913
+ function formatVariant(v, format = "okhsl", pastel = false) {
1914
+ const effectivePastel = v.pastel ?? pastel;
1877
1915
  const { l } = variantToOkhsl(v);
1878
- const base = formatters[format](v.h, v.s * 100, l * 100);
1916
+ const base = formatters[format](v.h, v.s * 100, l * 100, effectivePastel);
1879
1917
  if (v.alpha >= 1) return base;
1880
1918
  const closing = base.lastIndexOf(")");
1881
1919
  return `${base.slice(0, closing)} / ${fmt(v.alpha, 4)})`;
@@ -1887,44 +1925,44 @@ function resolveModes(override) {
1887
1925
  highContrast: override?.highContrast ?? cfg.modes.highContrast
1888
1926
  };
1889
1927
  }
1890
- function buildTokenMap(resolved, prefix, states, modes, format = "okhsl") {
1928
+ function buildTokenMap(resolved, prefix, states, modes, format = "okhsl", pastel = false) {
1891
1929
  const tokens = {};
1892
1930
  for (const [name, color] of resolved) {
1893
1931
  const key = `#${prefix}${name}`;
1894
- const entry = { "": formatVariant(color.light, format) };
1895
- if (modes.dark) entry[states.dark] = formatVariant(color.dark, format);
1896
- if (modes.highContrast) entry[states.highContrast] = formatVariant(color.lightContrast, format);
1897
- if (modes.dark && modes.highContrast) entry[`${states.dark} & ${states.highContrast}`] = formatVariant(color.darkContrast, format);
1932
+ const entry = { "": formatVariant(color.light, format, pastel) };
1933
+ if (modes.dark) entry[states.dark] = formatVariant(color.dark, format, pastel);
1934
+ if (modes.highContrast) entry[states.highContrast] = formatVariant(color.lightContrast, format, pastel);
1935
+ if (modes.dark && modes.highContrast) entry[`${states.dark} & ${states.highContrast}`] = formatVariant(color.darkContrast, format, pastel);
1898
1936
  tokens[key] = entry;
1899
1937
  }
1900
1938
  return tokens;
1901
1939
  }
1902
- function buildFlatTokenMap(resolved, prefix, modes, format = "okhsl") {
1940
+ function buildFlatTokenMap(resolved, prefix, modes, format = "okhsl", pastel = false) {
1903
1941
  const result = { light: {} };
1904
1942
  if (modes.dark) result.dark = {};
1905
1943
  if (modes.highContrast) result.lightContrast = {};
1906
1944
  if (modes.dark && modes.highContrast) result.darkContrast = {};
1907
1945
  for (const [name, color] of resolved) {
1908
1946
  const key = `${prefix}${name}`;
1909
- result.light[key] = formatVariant(color.light, format);
1910
- if (modes.dark) result.dark[key] = formatVariant(color.dark, format);
1911
- if (modes.highContrast) result.lightContrast[key] = formatVariant(color.lightContrast, format);
1912
- if (modes.dark && modes.highContrast) result.darkContrast[key] = formatVariant(color.darkContrast, format);
1947
+ result.light[key] = formatVariant(color.light, format, pastel);
1948
+ if (modes.dark) result.dark[key] = formatVariant(color.dark, format, pastel);
1949
+ if (modes.highContrast) result.lightContrast[key] = formatVariant(color.lightContrast, format, pastel);
1950
+ if (modes.dark && modes.highContrast) result.darkContrast[key] = formatVariant(color.darkContrast, format, pastel);
1913
1951
  }
1914
1952
  return result;
1915
1953
  }
1916
- function buildJsonMap(resolved, modes, format = "okhsl") {
1954
+ function buildJsonMap(resolved, modes, format = "okhsl", pastel = false) {
1917
1955
  const result = {};
1918
1956
  for (const [name, color] of resolved) {
1919
- const entry = { light: formatVariant(color.light, format) };
1920
- if (modes.dark) entry.dark = formatVariant(color.dark, format);
1921
- if (modes.highContrast) entry.lightContrast = formatVariant(color.lightContrast, format);
1922
- if (modes.dark && modes.highContrast) entry.darkContrast = formatVariant(color.darkContrast, format);
1957
+ const entry = { light: formatVariant(color.light, format, pastel) };
1958
+ if (modes.dark) entry.dark = formatVariant(color.dark, format, pastel);
1959
+ if (modes.highContrast) entry.lightContrast = formatVariant(color.lightContrast, format, pastel);
1960
+ if (modes.dark && modes.highContrast) entry.darkContrast = formatVariant(color.darkContrast, format, pastel);
1923
1961
  result[name] = entry;
1924
1962
  }
1925
1963
  return result;
1926
1964
  }
1927
- function buildCssMap(resolved, prefix, suffix, format) {
1965
+ function buildCssMap(resolved, prefix, suffix, format, pastel = false) {
1928
1966
  const lines = {
1929
1967
  light: [],
1930
1968
  dark: [],
@@ -1933,10 +1971,10 @@ function buildCssMap(resolved, prefix, suffix, format) {
1933
1971
  };
1934
1972
  for (const [name, color] of resolved) {
1935
1973
  const prop = `--${prefix}${name}${suffix}`;
1936
- lines.light.push(`${prop}: ${formatVariant(color.light, format)};`);
1937
- lines.dark.push(`${prop}: ${formatVariant(color.dark, format)};`);
1938
- lines.lightContrast.push(`${prop}: ${formatVariant(color.lightContrast, format)};`);
1939
- lines.darkContrast.push(`${prop}: ${formatVariant(color.darkContrast, format)};`);
1974
+ lines.light.push(`${prop}: ${formatVariant(color.light, format, pastel)};`);
1975
+ lines.dark.push(`${prop}: ${formatVariant(color.dark, format, pastel)};`);
1976
+ lines.lightContrast.push(`${prop}: ${formatVariant(color.lightContrast, format, pastel)};`);
1977
+ lines.darkContrast.push(`${prop}: ${formatVariant(color.darkContrast, format, pastel)};`);
1940
1978
  }
1941
1979
  return {
1942
1980
  light: lines.light.join("\n"),
@@ -1988,7 +2026,6 @@ function buildValueFormConfigOverride(userOverride) {
1988
2026
  lightTone: userOverride?.lightTone !== void 0 ? userOverride.lightTone : false,
1989
2027
  darkTone: userOverride?.darkTone !== void 0 ? userOverride.darkTone : cfg.darkTone,
1990
2028
  darkDesaturation: userOverride?.darkDesaturation ?? cfg.darkDesaturation,
1991
- saturationTaper: userOverride?.saturationTaper ?? cfg.saturationTaper,
1992
2029
  autoFlip: userOverride?.autoFlip ?? cfg.autoFlip,
1993
2030
  shadowTuning: userOverride?.shadowTuning ?? cfg.shadowTuning
1994
2031
  };
@@ -2005,7 +2042,6 @@ function buildStructuredConfigOverride(userOverride) {
2005
2042
  lightTone: userOverride?.lightTone !== void 0 ? userOverride.lightTone : cfg.lightTone,
2006
2043
  darkTone: userOverride?.darkTone !== void 0 ? userOverride.darkTone : cfg.darkTone,
2007
2044
  darkDesaturation: userOverride?.darkDesaturation ?? cfg.darkDesaturation,
2008
- saturationTaper: userOverride?.saturationTaper ?? cfg.saturationTaper,
2009
2045
  autoFlip: userOverride?.autoFlip ?? cfg.autoFlip,
2010
2046
  shadowTuning: userOverride?.shadowTuning ?? cfg.shadowTuning
2011
2047
  };
@@ -2290,6 +2326,7 @@ function buildStandaloneValueDefs(main, options) {
2290
2326
  mode: options?.mode ?? "auto",
2291
2327
  flip: options?.flip,
2292
2328
  opacity: options?.opacity,
2329
+ pastel: options?.pastel,
2293
2330
  base: hasExternalBase ? STANDALONE_BASE : needsSeedAnchor ? STANDALONE_SEED : void 0
2294
2331
  };
2295
2332
  const defs = { [primary]: valueDef };
@@ -2321,7 +2358,7 @@ function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effect
2321
2358
  };
2322
2359
  };
2323
2360
  const tokenLike = (options) => {
2324
- return buildTokenMap(resolveOnce(), "", resolveStates(options), resolveModes(options?.modes), options?.format)[`#${primary}`];
2361
+ return buildTokenMap(resolveOnce(), "", resolveStates(options), resolveModes(options?.modes), options?.format, effectiveConfig.pastel)[`#${primary}`];
2325
2362
  };
2326
2363
  return {
2327
2364
  resolve() {
@@ -2330,10 +2367,10 @@ function createColorTokenFromDefs(seedHue, seedSaturation, defs, primary, effect
2330
2367
  token: tokenLike,
2331
2368
  tasty: tokenLike,
2332
2369
  json(options) {
2333
- return buildJsonMap(resolveOnce(), resolveModes(options?.modes), options?.format)[primary];
2370
+ return buildJsonMap(resolveOnce(), resolveModes(options?.modes), options?.format, effectiveConfig.pastel)[primary];
2334
2371
  },
2335
2372
  css(options) {
2336
- return buildCssMap(new Map([[options.name, resolveOnce().get(primary)]]), "", options.suffix ?? "-color", options.format ?? "rgb");
2373
+ return buildCssMap(new Map([[options.name, resolveOnce().get(primary)]]), "", options.suffix ?? "-color", options.format ?? "rgb", effectiveConfig.pastel);
2337
2374
  },
2338
2375
  export: exportData
2339
2376
  };
@@ -2390,6 +2427,7 @@ function createColorToken(input, configOverride) {
2390
2427
  flip: input.flip,
2391
2428
  contrast: input.contrast,
2392
2429
  opacity: input.opacity,
2430
+ pastel: input.pastel,
2393
2431
  base: hasExternalBase ? STANDALONE_BASE : needsSeedAnchor ? STANDALONE_SEED : void 0
2394
2432
  } };
2395
2433
  if (needsSeedAnchor) {
@@ -2439,6 +2477,7 @@ function buildOverridesExport(options) {
2439
2477
  if (options.contrast !== void 0) out.contrast = options.contrast;
2440
2478
  if (options.opacity !== void 0) out.opacity = options.opacity;
2441
2479
  if (options.name !== void 0) out.name = options.name;
2480
+ if (options.pastel !== void 0) out.pastel = options.pastel;
2442
2481
  if (options.base !== void 0) out.base = isGlazeColorToken(options.base) ? options.base.export() : options.base;
2443
2482
  return out;
2444
2483
  }
@@ -2454,6 +2493,7 @@ function buildStructuredInputExport(input) {
2454
2493
  if (input.opacity !== void 0) out.opacity = input.opacity;
2455
2494
  if (input.contrast !== void 0) out.contrast = input.contrast;
2456
2495
  if (input.name !== void 0) out.name = input.name;
2496
+ if (input.pastel !== void 0) out.pastel = input.pastel;
2457
2497
  if (input.base !== void 0) out.base = isGlazeColorToken(input.base) ? input.base.export() : input.base;
2458
2498
  return out;
2459
2499
  }
@@ -2474,6 +2514,7 @@ function rehydrateOverrides(data) {
2474
2514
  if (data.contrast !== void 0) out.contrast = data.contrast;
2475
2515
  if (data.opacity !== void 0) out.opacity = data.opacity;
2476
2516
  if (data.name !== void 0) out.name = data.name;
2517
+ if (data.pastel !== void 0) out.pastel = data.pastel;
2477
2518
  if (data.base !== void 0) out.base = isExportedToken(data.base) ? colorFromExport(data.base) : data.base;
2478
2519
  return out;
2479
2520
  }
@@ -2489,6 +2530,7 @@ function rehydrateStructuredInput(data) {
2489
2530
  if (data.opacity !== void 0) out.opacity = data.opacity;
2490
2531
  if (data.contrast !== void 0) out.contrast = data.contrast;
2491
2532
  if (data.name !== void 0) out.name = data.name;
2533
+ if (data.pastel !== void 0) out.pastel = data.pastel;
2492
2534
  if (data.base !== void 0) out.base = isExportedToken(data.base) ? colorFromExport(data.base) : data.base;
2493
2535
  return out;
2494
2536
  }
@@ -2573,9 +2615,10 @@ function buildPaletteOutput(themes, paletteOptions, options, buildOne, merge, em
2573
2615
  const seen = /* @__PURE__ */ new Map();
2574
2616
  for (const [themeName, theme] of Object.entries(themes)) {
2575
2617
  const resolved = theme.resolve();
2618
+ const pastel = theme.getConfig().pastel;
2576
2619
  const prefix = resolvePrefix(options, themeName, true);
2577
- merge(acc, buildOne(filterCollisions(resolved, prefix, seen, themeName), prefix));
2578
- if (themeName === effectivePrimary) merge(acc, buildOne(filterCollisions(resolved, "", seen, themeName, true), ""));
2620
+ merge(acc, buildOne(filterCollisions(resolved, prefix, seen, themeName), prefix, pastel));
2621
+ if (themeName === effectivePrimary) merge(acc, buildOne(filterCollisions(resolved, "", seen, themeName, true), "", pastel));
2579
2622
  }
2580
2623
  return acc;
2581
2624
  }
@@ -2584,7 +2627,7 @@ function createPalette(themes, paletteOptions) {
2584
2627
  return {
2585
2628
  tokens(options) {
2586
2629
  const modes = resolveModes(options?.modes);
2587
- return buildPaletteOutput(themes, paletteOptions, options, (filtered, prefix) => buildFlatTokenMap(filtered, prefix, modes, options?.format), (acc, part) => {
2630
+ return buildPaletteOutput(themes, paletteOptions, options, (filtered, prefix, pastel) => buildFlatTokenMap(filtered, prefix, modes, options?.format, pastel), (acc, part) => {
2588
2631
  for (const variant of Object.keys(part)) {
2589
2632
  if (!acc[variant]) acc[variant] = {};
2590
2633
  Object.assign(acc[variant], part[variant]);
@@ -2598,18 +2641,18 @@ function createPalette(themes, paletteOptions) {
2598
2641
  highContrast: options?.states?.highContrast ?? cfg.states.highContrast
2599
2642
  };
2600
2643
  const modes = resolveModes(options?.modes);
2601
- return buildPaletteOutput(themes, paletteOptions, options, (filtered, prefix) => buildTokenMap(filtered, prefix, states, modes, options?.format), (acc, part) => Object.assign(acc, part), () => ({}));
2644
+ return buildPaletteOutput(themes, paletteOptions, options, (filtered, prefix, pastel) => buildTokenMap(filtered, prefix, states, modes, options?.format, pastel), (acc, part) => Object.assign(acc, part), () => ({}));
2602
2645
  },
2603
2646
  json(options) {
2604
2647
  const modes = resolveModes(options?.modes);
2605
2648
  const result = {};
2606
- for (const [themeName, theme] of Object.entries(themes)) result[themeName] = buildJsonMap(theme.resolve(), modes, options?.format);
2649
+ for (const [themeName, theme] of Object.entries(themes)) result[themeName] = buildJsonMap(theme.resolve(), modes, options?.format, theme.getConfig().pastel);
2607
2650
  return result;
2608
2651
  },
2609
2652
  css(options) {
2610
2653
  const suffix = options?.suffix ?? "-color";
2611
2654
  const format = options?.format ?? "rgb";
2612
- const lines = buildPaletteOutput(themes, paletteOptions, options, (filtered, prefix) => buildCssMap(filtered, prefix, suffix, format), (acc, part) => {
2655
+ const lines = buildPaletteOutput(themes, paletteOptions, options, (filtered, prefix, pastel) => buildCssMap(filtered, prefix, suffix, format, pastel), (acc, part) => {
2613
2656
  for (const key of [
2614
2657
  "light",
2615
2658
  "dark",
@@ -2676,6 +2719,9 @@ function createTheme(hue, saturation, initialColors, configOverride) {
2676
2719
  get saturation() {
2677
2720
  return saturation;
2678
2721
  },
2722
+ getConfig() {
2723
+ return getEffectiveConfig();
2724
+ },
2679
2725
  colors(defs) {
2680
2726
  colorDefs = {
2681
2727
  ...colorDefs,
@@ -2730,7 +2776,7 @@ function createTheme(hue, saturation, initialColors, configOverride) {
2730
2776
  },
2731
2777
  tokens(options) {
2732
2778
  const modes = resolveModes(options?.modes);
2733
- return buildFlatTokenMap(resolveCached(), "", modes, options?.format);
2779
+ return buildFlatTokenMap(resolveCached(), "", modes, options?.format, getEffectiveConfig().pastel);
2734
2780
  },
2735
2781
  tasty(options) {
2736
2782
  const cfg = getEffectiveConfig();
@@ -2739,14 +2785,14 @@ function createTheme(hue, saturation, initialColors, configOverride) {
2739
2785
  highContrast: options?.states?.highContrast ?? cfg.states.highContrast
2740
2786
  };
2741
2787
  const modes = resolveModes(options?.modes);
2742
- return buildTokenMap(resolveCached(), "", states, modes, options?.format);
2788
+ return buildTokenMap(resolveCached(), "", states, modes, options?.format, cfg.pastel);
2743
2789
  },
2744
2790
  json(options) {
2745
2791
  const modes = resolveModes(options?.modes);
2746
- return buildJsonMap(resolveCached(), modes, options?.format);
2792
+ return buildJsonMap(resolveCached(), modes, options?.format, getEffectiveConfig().pastel);
2747
2793
  },
2748
2794
  css(options) {
2749
- return buildCssMap(resolveCached(), "", options?.suffix ?? "-color", options?.format ?? "rgb");
2795
+ return buildCssMap(resolveCached(), "", options?.suffix ?? "-color", options?.format ?? "rgb", getEffectiveConfig().pastel);
2750
2796
  }
2751
2797
  };
2752
2798
  }
@@ -2769,7 +2815,7 @@ function createTheme(hue, saturation, initialColors, configOverride) {
2769
2815
  * Create a single-hue glaze theme.
2770
2816
  *
2771
2817
  * An optional `config` override can be supplied to customize the resolve
2772
- * behavior for this theme (tone windows, saturation taper, etc.). The
2818
+ * behavior for this theme (tone windows, etc.). The
2773
2819
  * override is **merged over the live global config at resolve time** —
2774
2820
  * the theme still reacts to later `configure()` calls for fields it
2775
2821
  * didn't override.
@@ -2829,7 +2875,7 @@ glaze.from = function from(data) {
2829
2875
  *
2830
2876
  * // Config override on any form
2831
2877
  * glaze.color('#26fcb2', { darkTone: false, autoFlip: false })
2832
- * glaze.color({ from: '#fff', base: bg }, { saturationTaper: 0 })
2878
+ * glaze.color({ from: '#fff', base: bg })
2833
2879
  * ```
2834
2880
  *
2835
2881
  * Defaults: every form defaults to `mode: 'auto'`. Value-shorthand forms
@@ -2883,8 +2929,8 @@ glaze.shadow = function shadow(input) {
2883
2929
  };
2884
2930
  };
2885
2931
  /** Format a resolved color variant as a CSS string. */
2886
- glaze.format = function format(variant, colorFormat) {
2887
- return formatVariant(variant, colorFormat);
2932
+ glaze.format = function format(variant, colorFormat, pastel) {
2933
+ return formatVariant(variant, colorFormat, pastel);
2888
2934
  };
2889
2935
  /**
2890
2936
  * Create a theme from a hex color string.
@@ -2941,6 +2987,7 @@ glaze.resetConfig = function resetConfig$1() {
2941
2987
  exports.REF_EPS = REF_EPS;
2942
2988
  exports.apcaContrast = apcaContrast;
2943
2989
  exports.contrastRatioFromLuminance = contrastRatioFromLuminance;
2990
+ exports.cuspLightness = cuspLightness;
2944
2991
  exports.findToneForContrast = findToneForContrast;
2945
2992
  exports.findValueForMixContrast = findValueForMixContrast;
2946
2993
  exports.formatHsl = formatHsl;