clayDropShadow function

int clayDropShadow(
  1. int face, {
  2. required int bodyHueTenths,
  3. required bool dark,
  4. required KeyGroup group,
  5. double baseL = 0,
  6. double baseC = 0,
  7. BileRule bile = BileRule.v2,
})

A key group's drop-shadow colour (KeyColors.edge): coloured, darker than the body, never grey, bile-safe. bodyHueTenths, baseL and baseC describe the body (colors[0]). GuardrailRule.clayShadowTint accepts alpha clayShadowAlphaMin–clayShadowAlphaMax, chroma ≥ min(0.040, 0.75 × maxChroma) (night ≥ 0.035) and a hue within 40° of the key's own (bile-applied; at night the clayNightShadowHue reference, which falls back to the body hue for faces with no chroma at the shadow lightness).

Implementation

int clayDropShadow(
  int face, {
  required int bodyHueTenths,
  required bool dark,
  required KeyGroup group,
  double baseL = 0,
  double baseC = 0,
  BileRule bile = BileRule.v2,
}) {
  final f = argbToOklch(face | 0xFF000000);
  final alpha = (dark ? clayNightShadowAlpha : clayShadowAlpha)[group.index];
  if (dark) {
    final l = clayNightShadowL(baseL);
    final hue = clayNightShadowHue(face, bodyHueTenths, l, bile: bile);
    final c = _min(
      maxChroma(l, hue / 10),
      _max(clayNightShadowMinChroma, baseC),
    );
    return withAlpha(oklchToArgb(l, c, hue / 10), alpha);
  }
  var hue = f.c >= 0.035 ? _hueTenths(f) : _wrap(bodyHueTenths);
  final l = _clamp(f.l - 0.40, 0.32, 0.52);
  // Forced chroma: yellow-band shadows always rotate (a dark yellow is
  // brown).
  hue = bile.apply(hue, l, 0.1);
  final c = _min(_clamp(f.c * 1.25, 0.07, 0.16), maxChroma(l, hue / 10));
  return withAlpha(oklchToArgb(l, c, hue / 10), alpha);
}