package ui import ( "math" "strings" ) // logoGlyphs holds 5×7 pixel bitmaps for each letter in "CLIAMP". // Each row is 5 bits wide; bit 4 (0x10) is the leftmost pixel. var logoGlyphs = [6][7]uint8{ {0x0E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0E}, // C {0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1F}, // L {0x1F, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1F}, // I {0x0E, 0x11, 0x11, 0x1F, 0x11, 0x11, 0x11}, // A {0x11, 0x1B, 0x15, 0x11, 0x11, 0x11, 0x11}, // M {0x1E, 0x11, 0x11, 0x1E, 0x10, 0x10, 0x10}, // P } const ( logoLetterW = 5 // pixel columns per glyph logoLetterH = 7 // pixel rows per glyph logoNumLetters = 6 logoGap = 2 // pixel gap between letters logoTotalW = logoNumLetters*logoLetterW + (logoNumLetters-1)*logoGap // 40 ) // renderLogo draws "CLIAMP" in pixel art using Braille dots. Individual dots // within each letter appear and disappear based on the associated frequency // band's energy — loud passages fill the text solid, silence dissolves it // into scattered pixels. A gentle bounce and wave keep things alive. func (v *Visualizer) renderLogo(bands []float64) string { height := v.Rows dotRows := height * 4 dotCols := PanelWidth * 2 grid := make([]bool, dotRows*dotCols) // Scale letters to fill the panel (75% of height for bounce headroom). scaleX := dotCols / logoTotalW scaleY := (dotRows * 3 / 4) / logoLetterH if scaleX < 1 { scaleX = 1 } if scaleY < 1 { scaleY = 1 } renderedW := logoTotalW * scaleX renderedH := logoLetterH * scaleY offsetX := (dotCols - renderedW) / 2 baseOffsetY := (dotRows - renderedH) / 2 // Map 6 letters across the 10 frequency bands. letterBand := [6]int{0, 2, 4, 5, 7, 9} for li := range logoNumLetters { energy := bands[letterBand[li]] // Gentle traveling wave for life during silence + subtle bounce. wave := math.Sin(float64(v.frame)*0.06+float64(li)*0.9) * 1.5 bounce := int(energy*float64(baseOffsetY)*0.3 + wave) letterX := offsetX + li*(logoLetterW+logoGap)*scaleX letterY := baseOffsetY - bounce for py := range logoLetterH { row := logoGlyphs[li][py] for px := range logoLetterW { if row&(1<<(logoLetterW-1-px)) == 0 { continue } // Stamp each glyph pixel as a scaled block of dots. // Each dot's visibility is gated by energy — loud fills // the text solid, silence dissolves it to scattered pixels. fill := energy*energy*0.75 + 0.15 for sy := range scaleY { for sx := range scaleX { dx := letterX + px*scaleX + sx dy := letterY + py*scaleY + sy if dx < 0 || dx >= dotCols || dy < 0 || dy >= dotRows { continue } if scatterHash(li, py*scaleY+sy, px*scaleX+sx, v.frame) > fill { continue } grid[dy*dotCols+dx] = true } } } } } // Convert dot grid to Braille characters. lines := make([]string, height) for row := range height { var content strings.Builder for ch := range PanelWidth { var braille rune = '\u2800' for dr := range 4 { for dc := range 2 { if grid[(row*4+dr)*dotCols+ch*2+dc] { braille |= brailleBit[dr][dc] } } } content.WriteRune(braille) } lines[row] = specWrap(float64(height-1-row)/float64(height), content.String()) } return strings.Join(lines, "\n") }