Bootstrapped during the 2026-06-06 BlockNinja consolidation. Was previously an unversioned directory inside ~/src/blockninja-themes/brutalist. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
92 lines
3.8 KiB
Go
92 lines
3.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"fmt"
|
|
|
|
"git.dev.alexdunmow.com/block/core/templates"
|
|
)
|
|
|
|
// BrutalistEmailWrapper renders the Brutalist branded email wrapper:
|
|
// off-white concrete background, 1px ink outer border, Space Grotesk
|
|
// headline, Inter body, JetBrains Mono signoff.
|
|
//
|
|
// Colors flow from emailCtx.Colors when present, falling back to HSL
|
|
// values derived from the spec's concrete-red light palette. The hot
|
|
// accent is reserved for the single CTA button.
|
|
func BrutalistEmailWrapper(body string, emailCtx templates.EmailContext) string {
|
|
var buf bytes.Buffer
|
|
_ = brutalistEmailTemplate(emailCtx, body).Render(context.Background(), &buf)
|
|
return buf.String()
|
|
}
|
|
|
|
// Spec defaults for email rendering (matches concrete-red light preset HSL
|
|
// triples converted to hex-equivalent so email clients can compute colors).
|
|
const (
|
|
brutalistEmailBgDefault = "#F2EFE8" // background 40 14% 93%
|
|
brutalistEmailCardDefault = "#F7F4ED" // card 40 10% 96%
|
|
brutalistEmailFgDefault = "#0A0A0A" // foreground 0 0% 4%
|
|
brutalistEmailMutedFgDefault = "#595959" // mutedForeground 0 0% 35%
|
|
brutalistEmailBorderDefault = "#0A0A0A" // border 0 0% 4%
|
|
)
|
|
|
|
func brutalistEmailColor(v, fallback string) string {
|
|
if v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func brutalistBg(emailCtx templates.EmailContext) string {
|
|
return brutalistEmailColor(emailCtx.Colors.Background, brutalistEmailBgDefault)
|
|
}
|
|
|
|
func brutalistCard(emailCtx templates.EmailContext) string {
|
|
return brutalistEmailColor(emailCtx.Colors.Card, brutalistEmailCardDefault)
|
|
}
|
|
|
|
func brutalistFg(emailCtx templates.EmailContext) string {
|
|
return brutalistEmailColor(emailCtx.Colors.Foreground, brutalistEmailFgDefault)
|
|
}
|
|
|
|
func brutalistMutedFg(emailCtx templates.EmailContext) string {
|
|
return brutalistEmailColor(emailCtx.Colors.MutedForeground, brutalistEmailMutedFgDefault)
|
|
}
|
|
|
|
func brutalistBorder(emailCtx templates.EmailContext) string {
|
|
return brutalistEmailColor(emailCtx.Colors.Border, brutalistEmailBorderDefault)
|
|
}
|
|
|
|
func brutalistEmailBodyStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("background-color: %s; margin: 0; padding: 0; font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif; color: %s;", brutalistBg(emailCtx), brutalistFg(emailCtx))
|
|
}
|
|
|
|
func brutalistEmailOuterCellStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("padding: 48px 16px; background-color: %s;", brutalistBg(emailCtx))
|
|
}
|
|
|
|
func brutalistEmailContainerStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("max-width: 600px; background-color: %s; border: 1px solid %s; border-radius: 0;", brutalistCard(emailCtx), brutalistBorder(emailCtx))
|
|
}
|
|
|
|
func brutalistEmailHeaderStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("padding: 32px 40px; border-bottom: 1px solid %s;", brutalistBorder(emailCtx))
|
|
}
|
|
|
|
func brutalistEmailHeadlineStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("margin: 0; font-family: 'Space Grotesk', 'Inter Tight', Helvetica, Arial, sans-serif; font-weight: 700; font-size: 26px; letter-spacing: -0.02em; color: %s; text-transform: uppercase;", brutalistFg(emailCtx))
|
|
}
|
|
|
|
func brutalistEmailBodyCellStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("padding: 40px 48px; color: %s; font-size: 16px; line-height: 1.7;", brutalistFg(emailCtx))
|
|
}
|
|
|
|
func brutalistEmailFooterStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("padding: 24px 48px 32px; border-top: 1px solid %s; font-family: 'JetBrains Mono', ui-monospace, monospace; font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: %s;", brutalistBorder(emailCtx), brutalistMutedFg(emailCtx))
|
|
}
|
|
|
|
func brutalistEmailLinkStyle(emailCtx templates.EmailContext) string {
|
|
return fmt.Sprintf("color: %s; text-decoration: none; border-bottom: 1px solid %s;", brutalistFg(emailCtx), brutalistBorder(emailCtx))
|
|
}
|