package banking import ( "fmt" "strings" "github.com/charmbracelet/lipgloss" ) const termWidth = 80 // Color palette — green-on-black retro terminal. var ( colorGreen = lipgloss.Color("#00FF00") colorDim = lipgloss.Color("#007700") colorBlack = lipgloss.Color("#000000") colorBright = lipgloss.Color("#AAFFAA") colorRed = lipgloss.Color("#FF3333") ) // Reusable styles. var ( baseStyle = lipgloss.NewStyle(). Foreground(colorGreen). Background(colorBlack) headerStyle = lipgloss.NewStyle(). Foreground(colorBright). Background(colorBlack). Bold(true). Width(termWidth). Align(lipgloss.Center) titleStyle = lipgloss.NewStyle(). Foreground(colorGreen). Background(colorBlack). Bold(true) dimStyle = lipgloss.NewStyle(). Foreground(colorDim). Background(colorBlack) errorStyle = lipgloss.NewStyle(). Foreground(colorRed). Background(colorBlack). Bold(true) inputStyle = lipgloss.NewStyle(). Foreground(colorBright). Background(colorBlack) ) // divider returns an 80-column === line. func divider() string { return dimStyle.Render(strings.Repeat("=", termWidth)) } // thinDivider returns an 80-column --- line. func thinDivider() string { return dimStyle.Render(strings.Repeat("-", termWidth)) } // centerText centers text within 80 columns. func centerText(s string) string { return headerStyle.Render(s) } // padRight pads a string to the given width. func padRight(s string, width int) string { if len(s) >= width { return s[:width] } return s + strings.Repeat(" ", width-len(s)) } // formatCurrency formats cents as $X,XXX.XX func formatCurrency(cents int64) string { negative := cents < 0 if negative { cents = -cents } dollars := cents / 100 remainder := cents % 100 // Add thousands separators. ds := fmt.Sprintf("%d", dollars) if len(ds) > 3 { var parts []string for len(ds) > 3 { parts = append([]string{ds[len(ds)-3:]}, parts...) ds = ds[:len(ds)-3] } parts = append([]string{ds}, parts...) ds = strings.Join(parts, ",") } if negative { return fmt.Sprintf("-$%s.%02d", ds, remainder) } return fmt.Sprintf("$%s.%02d", ds, remainder) } // screenFrame wraps content in the persistent header and footer. func screenFrame(bankName, terminalID, region, content string) string { var b strings.Builder // Header. b.WriteString(divider()) b.WriteString("\n") b.WriteString(centerText(bankName + " FEDERAL RESERVE SYSTEM")) b.WriteString("\n") b.WriteString(centerText("SECURE BANKING TERMINAL")) b.WriteString("\n") b.WriteString(divider()) b.WriteString("\n") // Content. b.WriteString(content) // Footer. b.WriteString("\n") b.WriteString(divider()) b.WriteString("\n") footer := fmt.Sprintf(" TERMINAL: %s | REGION: %s | ENCRYPTED SESSION ACTIVE", terminalID, region) b.WriteString(dimStyle.Render(padRight(footer, termWidth))) return b.String() }