feat(learn,todo,train,meditate): the apps' icons on a dark tile (ADR 0031, D8)
All checks were successful
CI / check (push) Successful in 50m47s
CI / deploy (push) Successful in 4m49s

Each icon's Lucide glyph now sits on the apps' dark background (#131520)
instead of white, its cobalt-to-colour gradient lifted 30 % towards white
so the glyph keeps above 4.5 : 1 against the tile. tool/app_icons.py
holds the tile and the lift; the pubspecs give Android's adaptive icon
and iOS's the same background. Every platform's icon is regenerated.

Whats-New: The app's icon now sits on a dark background.
Whats-New-De: Das App-Symbol hat jetzt einen dunklen Hintergrund.
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-07 23:19:19 +01:00
commit 1a3034fd31
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -1,7 +1,9 @@
#!/usr/bin/env python3
"""Makes the apps' icons, one family (ADR 0031): each app's Lucide glyph on a white
square, fading from cobalt through the colours APPS names, top left to bottom right
across Lucide's 24-unit box, the stops evenly spaced, at Lucide's stroke width (2),
"""Makes the apps' icons, one family (ADR 0031): each app's Lucide glyph on a dark
square (TILE, the apps' dark background; D8), fading from cobalt through the colours
APPS names, each lifted towards white (LIFT) so the glyph stands out on the dark tile,
top left to bottom right across Lucide's 24-unit box, the stops evenly spaced, at
Lucide's stroke width (2),
1024 x 1024 pixels (<app>/<flutter package>/assets/icon/<icon>); the launchers and
the launch screens round its corners themselves. Then, for each app:
@ -9,7 +11,7 @@ the launch screens round its corners themselves. Then, for each app:
app registers in its licence list;
- the snap's icon where the app has a snap (Learn's snap/gui/halkyon-learn.png at the
repository's root, Todo's apps/todo/snap/gui/halkyon-todo.png; 512 x 512 pixels, the
Snap Store's size), the icon with rounded corners, as other apps' white tiles
Snap Store's size), the icon with rounded corners, as other apps' tiles
have (radius 142.222 of 512, about 28 %);
- through flutter_launcher_icons, configured in the app's pubspec: Android's adaptive
icon and its older square one, iOS's, macOS's (the rounded tile on Apple's grid,
@ -59,6 +61,12 @@ REEF = "#1DA583"
ENZIAN = "#5252CC"
PURPLE = "#8080FF"
# ADR 0031, D8: the tile is halkyon_ui's dark surface, and every stop is mixed this
# share towards white, so the gradient's darkest part (cobalt) keeps above 4.5 : 1
# against it.
TILE = "#131520"
LIFT = 0.3
@dataclass(frozen=True)
class AppIcon:
@ -130,8 +138,13 @@ def rgb(colour: str) -> tuple[float, float, float]:
return tuple(int(colour[i : i + 2], 16) / 255 for i in (1, 3, 5))
def lifted(colour: str) -> tuple[float, float, float]:
"""[colour] mixed LIFT towards white."""
return tuple(c + (1 - c) * LIFT for c in rgb(colour))
def icon(glyph: str, stops: tuple[str, ...], svg: str) -> Image.Image:
"""[glyph] on white in the gradient of [stops], SIZE pixels square."""
"""[glyph] on TILE in the lifted gradient of [stops], SIZE pixels square."""
if f"lucide-static v{LUCIDE}" not in svg:
raise SystemExit(f"Not lucide-static {LUCIDE}'s {glyph}.")
if 'viewBox="0 0 24 24"' not in svg or 'stroke-width="2"' not in svg:
@ -150,11 +163,11 @@ def icon(glyph: str, stops: tuple[str, ...], svg: str) -> Image.Image:
tile = cairo.ImageSurface(cairo.FORMAT_RGB24, SIZE, SIZE)
context = cairo.Context(tile)
context.set_source_rgb(1, 1, 1)
context.set_source_rgb(*rgb(TILE))
context.paint()
gradient = cairo.LinearGradient(offset, offset, offset + box, offset + box)
for i, colour in enumerate(stops):
gradient.add_color_stop_rgb(i / (len(stops) - 1), *rgb(colour))
gradient.add_color_stop_rgb(i / (len(stops) - 1), *lifted(colour))
context.set_source(gradient)
context.mask_surface(mask)