Replace the Grok braille logo with a procedurally generated moon

The welcome logo (hero box, stacked layout, and minimal's welcome card) is
now a braille moon that waxes and wanes through a full 8s lunation,
echoing the Kimi CLI's moon-phase spinner. The disc is rasterized into the
2x4 braille dot grid at render time — round at any size, no art assets —
with the terminator at x = cos(2*pi*p)*sqrt(1-y^2) and a faint outline
ring so the silhouette survives new moon. The full moon grows to 20x10
cells (from the 14x7 slashed-circle art) and the small tier to 10x5; the
old logo*.txt assets are deleted. Geometry is unit-tested (wax/wane
monotonicity, quarter-phase symmetry, right-limb-first waxing, silhouette
at new moon, round raster).
This commit is contained in:
2026-07-17 18:22:00 -04:00
parent 5406fb7d68
commit 0e3d43128e
14 changed files with 298 additions and 313 deletions
@@ -18,7 +18,7 @@ async fn welcome_screen_braille_logo_renders_correctly() {
let content = ContentController::start().await.expect("start content");
let binary = pager_binary().expect("resolve pager binary");
// Use a tall terminal so pick_logo() selects the 7-line logo (≥26 rows).
// Use a tall terminal so pick_logo() selects the full moon (≥26 rows).
let mut harness =
PtyHarness::spawn_with_content(&binary, DEFAULT_ROWS, DEFAULT_COLS, &content, &[])
.expect("spawn pager");
@@ -29,24 +29,22 @@ async fn welcome_screen_braille_logo_renders_correctly() {
let screen = harness.screen_contents();
// The logo contains distinctive Braille characters. If the writer
// thread sends raw UTF-8 bytes through a code-page-dependent API,
// these 3-byte characters would be mangled into 3 separate single-
// byte characters each (e.g. Cyrillic). Check for a few that only
// appear in the logo — not in any ASCII menu label.
//
// From logo07.txt line 2: ⣠⣾⠿⠛
// The moon logo is drawn from Braille Pattern characters. If the writer
// thread sends raw UTF-8 bytes through a code-page-dependent API, these
// 3-byte characters would be mangled into 3 separate single-byte
// characters each (e.g. Cyrillic). The moon is procedurally generated,
// so assert on the character class rather than specific glyphs: a full
// interior cell (⣿) is present through most of the lunation, and there
// must be a healthy number of non-blank braille cells overall.
let braille_dots = screen
.chars()
.filter(|c| ('\u{2801}'..='\u{28FF}').contains(c))
.count();
assert!(
screen.contains('⣾'),
"Braille character ⣾ (U+28FE) not found in screen — \
logo may be garbled by code-page misinterpretation.\n\
Screen contents:\n{screen}"
);
assert!(
screen.contains('⣿'),
"Braille character ⣿ (U+28FF) not found in screen — \
logo may be garbled.\n\
Screen contents:\n{screen}"
braille_dots >= 20,
"expected the braille moon (>= 20 non-blank braille cells), found \
{braille_dots} — logo may be garbled by code-page \
misinterpretation.\nScreen contents:\n{screen}"
);
harness.quit().expect("clean quit");