engine/liquid_glass library
The Liquid Glass family (spec §5.3 #2; motion brief §2.3 "Liquid Glass"): translucent keys over a vivid, slowly drifting mesh-gradient background, with specular highlights, a refraction hint and a jelly press. Glass is for the controls: the display sits on a solid-enough backing panel.
- Background: a mesh of a deep (dark themes) or pale (light themes) base and three vivid colour blobs (BackgroundKind.meshGradient), hues from the harmony scheme. It drifts on a 40–60 s cycle at runtime (never under Reduce Motion or with ambient motion off).
- Keys: glass tints — translucent
KeyColors.faceARGB — smoky dark glass (dark themes) or milky white glass (light themes) for digits, a second tone for function keys, vivid accent glass for the operators and a denser jewel=. Rims (KeyColors.edge) are decorative light catchers, or opaque and ≥ 3:1 under the Accessible lock. - Display: the palette
surface, translucent but dense; every display text is solved on the surface composited over the background (displayBackdrops).
Guardrails on composited colours (research theme-engine.md:
contrast over translucent surfaces). A mesh blends its colours in every
proportion, so its samples are its colour hull (meshHullSamples):
the stops, every pairwise quarter point and every three-way centroid in
encoded sRGB (what the renderer's gradients blend in). Its darkest and
lightest points can lie between stops (encoded-sRGB blends of two
saturated colours are darker than either), which is why the stops alone
are not enough. Labels are checked on each tint composited over every
hull sample (4.5:1, 7:1 accessible), the display on the surface over
every sample, plus the glass rules in validateGlass: labels ≥ 3:1
under the peak press glow, operator / = tints distinct from the digit
tint over the same sample (ΔEOK ≥ 0.08 under every CVD), an honest
weight cue, and opaque ≥ 3:1 rims under the Accessible lock.
The renderer keeps those numbers true: the label zone (the middle 40 % of the key's height, glassLabelZoneTop–glassLabelZoneBottom) shows exactly the tint over the background; the specular highlight and bottom caustic stay outside it; edge thickening only moves the face away from its label; the frost underlay (KeyStyleSpec.frostPermille) is the background's base colour, so a frosted face is still the tint over a point of the hull; Reduce Transparency's solid tint is the tint composited over the base colour, itself a hull sample.
Every draw comes from the generator's named sub-streams (palette with
its retry streams, background, shape, style, type, motion,
name), so a theme is a pure function of (seed, engineVersion,
accessible). The constants here are part of engine version 2's Liquid
Glass definition: changing one changes generated themes.
Constants
- glassAccessibleRimMinCdp → const int
- Smallest rim width the Accessible lock accepts, dp × 100.
- glassBlobChromaCapMilli → const int
- Blob absolute chroma caps (thousandths), dark and light.
- glassDarkBlobChroma → const IntRange
- Blob relative chroma, dark and light.
- glassDarkBlobLMilli → const IntRange
-
Dark mesh: blob lightness (× 1000) and relative chroma (× 1000 of
maxChroma, capped at glassBlobChromaCapMilli). - glassDarkDigitAlpha → const IntRange
- Tint alphas (0–255) per role, dark and light.
- glassDarkEqualsAlpha → const IntRange
- glassDarkFrost → const IntRange
- Frost (backdrop diffusion) × 1000, dark and light.
- glassDarkFunctionAlpha → const IntRange
- glassDarkOperatorAlpha → const IntRange
- glassDarkRanges → const RoleRanges
-
Liquid Glass dark ranges (only what buildGlassCandidate reads): the
mesh base (
background), the digit, function, operator and=tints, label start and chroma. Tints are composited over the background, so their lightness is the glass's colour, not the face the eye sees. - glassDarkSurfaceAlpha → const IntRange
- glassDarkSurfaceLMilli → const IntRange
- Display surface (the backing panel): lightness × 1000 and the starting alpha; the alpha then rises in steps of 10 until the display text reaches its floor (+ 0.15) on every composited sample — glass where the background allows it, denser where it must be.
- glassDriftPeriodMs → const IntRange
- Mesh drift period range, ms (motion brief §4.13: a cycle of ≥ 40 s).
- glassGlowAlpha → const IntRange
-
Peak press-glow alpha range (
Palette.highlight's alpha, 0–255): the motion brief's "+12 % luminance" glow core. - glassHighlight → const IntRange
- Specular highlight and refraction strengths × 1000.
- glassLabelZoneBottom → const double
- Bottom of the label zone (see glassLabelZoneTop).
- glassLabelZoneTop → const double
- Top of the label zone as a fraction of the key's height: the renderer paints nothing but the tint (and the press glow) between this and glassLabelZoneBottom.
- glassLightBlobChroma → const IntRange
- glassLightBlobChromaCapMilli → const int
- glassLightBlobLMilli → const IntRange
- Light mesh: blob lightness (× 1000).
- glassLightDigitAlpha → const IntRange
- glassLightEqualsAlpha → const IntRange
- glassLightFrost → const IntRange
- glassLightFunctionAlpha → const IntRange
- glassLightOperatorAlpha → const IntRange
- glassLightRanges → const RoleRanges
- Liquid Glass light ranges (see glassDarkRanges).
- glassLightSurfaceAlpha → const IntRange
- glassLightSurfaceLMilli → const IntRange
- glassPressedLabelRatio → const double
- The floor for key labels while the press glow lights the face (a transient state under the finger; WCAG 1.4.11 level).
- glassRefraction → const IntRange
- liquidGlassDefinition → const FamilyDefinition
- Liquid Glass (spec §5.3 #2; motion brief §2.3 "Liquid Glass"): translucent glass keys over a vivid drifting mesh, specular highlight and refraction rim, display on a solid-enough backing.
Functions
-
buildGlassCandidate(
int seed, FamilyDefinition def, int engineVersion, {int attempt = 0, bool accessible = false}) → ThemeSpec -
Builds one unvalidated Liquid Glass candidate (the generator repairs
and validates it, retries with
palette/retry/nand finally falls back to a Liquid Glass hero). -
densifyGlassSurface(
int surface, int text, GuardrailLimits lim, List< int> bgs) → int -
The display backing
surfacemade denser (alpha + 10 at a time) until a text oftext's polarity reaches the display and preview floors (+ 0.15) on it composited over every background sample. -
fitGlassGlow(
Palette p, int glow, List< int> bgs) → int -
The press glow
glowdimmed (alpha in steps of 4) until every label ofpkeeps glassPressedLabelRatio under it. -
glassBlobOffsets(
HarmonyScheme scheme) → List< int> -
Blob hue offsets (tenths) per harmony scheme: blob 1, blob 2, blob 3.
Operators take blob 2's hue,
=blob 3's. -
glassDiffuseColor(
BackgroundSpec bg) → int - The colour glass diffuses the background to: the three-way centroid of a mesh's blobs (exactly one of meshHullSamples) — the vivid middle of the mesh — or the base colour for other backgrounds. The renderer's frost underlay and Reduce Transparency's solid tint (the tint composited over it) use it, so both are checked colours.
-
glassPressedLabelContrast(
KeyColors k, int glow, List< int> bgs) → double -
Smallest label contrast of
kunder the peak press glowglow. -
glassPressedSamples(
int face, int glow, List< int> bgs) → List<int> -
The colours a glass face shows under the press glow
glowat its peak: the glow composited over the tint over every background sample. -
glassTintDistance(
int face, int digit, List< int> bgs) → double -
Smallest ΔEOK (normal + CVD) between
faceanddigitcomposited over the same background sample. -
meshHullSamples(
List< int> stops) → List<int> -
The colour hull of a mesh with opaque
stops, sampled: every stop, every pairwise ¼ / ½ / ¾ point and every three-way centroid, blended in encoded sRGB (integer arithmetic, bit-exact). The darkest and lightest colours a mesh can paint are among (or within a hair of) these. -
repairGlassExtras(
Palette p, ThemeSpec spec, GuardrailLimits lim, List< int> bgs) → Palette? - Repairs the glass extras: the press glow (dimmed until labels keep 3:1 under it) and, under the Accessible lock, opaque rims solved to ≥ 3:1 on every background sample. Null when a rim is unreachable.
-
repairGlassKeys(
Palette p, GuardrailLimits lim, List< int> bgs) → Palette? - Repairs translucent glass keys whose labels miss the floor on some composited sample: re-solves the label, then moves and densifies the tint (solveGlassKey). Opaque keys are left to the generic repair. Null when a key cannot reach the floor.
-
separateGlassEquals(
KeyColors eq, KeyColors op, KeyColors digit, GuardrailLimits lim, List< int> bgs) → KeyColors? -
Keeps the
=glass apart from the operators over any two background samples (the genericequalsVsOperatorrule compares every pair) and from the digit tint over the same sample (glassOperatorTint): when it is too close, its tint moves 0.06 at a time in lightness — away from the operator's first, then the other way — at an alpha of at least 230 (a denser jewel varies less across the mesh), re-solving the label each step. Null when no step works. -
solveGlassKey(
{required Lch tint, required int alpha, required Lch label, required List< int> bgs, required double target, required int edge, int rounds = 14}) → KeyColors? -
Solves a glass key: the label (from
label) ontintatalphacomposited over every one ofbgs, totarget. When no label of the same polarity reaches it, the tint moves away from the label (0.04 in lightness) and densifies (+14 alpha) for up toroundsrounds. Null when unreachable. -
validateGlass(
ThemeSpec spec, GuardrailLimits lim, List< int> bgs) → List<GuardrailViolation> -
The Liquid Glass rules (see the library docs);
validateThemeadds them for the family.bgsare the background samples.