/** * The AI Atlas mark — an "atlas plate": a rounded-square plate carrying a fine coordinate grid, over which three nodes and * two edges draw the letter A as a graph. The horizontal baseline is a timeline; the accent node at its right end marks "now". * One geometry (32 × 32 viewBox) for every size: 16 px favicon (simplified grid), 32 px tab, 180 px Apple icon, 512 px PWA, * the in-page logo (CSS-variable colours) and the OG images (hex colours — ImageResponse cannot read CSS variables). */ export type MarkColors = { plate: string; ink: string; grid: string; accent: string }; /** Dark plate (favicon / PWA / OG). */ export const MARK_DARK: MarkColors = { plate: '#0b0d11', ink: '#e9ebf0', grid: 'rgba(233,235,240,0.22)', accent: '#6d95ff' }; /** Light plate (lockup on light backgrounds). */ export const MARK_LIGHT: MarkColors = { plate: '#e9ebf0', ink: '#0b0d11', grid: 'rgba(11,13,17,0.2)', accent: '#1f4fd8' }; /** In-page: follows the theme through the `--brand-*` tokens (globals.css). */ export const MARK_TOKENS: MarkColors = { plate: 'var(--brand-plate)', ink: 'var(--brand-ink)', grid: 'var(--brand-grid)', accent: 'var(--brand-accent)' }; export const MARK_GEOMETRY = { apex: { x: 16, y: 8 }, left: { x: 8.5, y: 24 }, now: { x: 23.5, y: 24 }, baseline: { x1: 5, x2: 27, y: 24 }, gridH: [10.5, 17], gridV: [10.5, 21.5], }; type MarkOpts = { simplified?: boolean; plate?: boolean; radius?: number }; /** * Inner artwork (no wrapper) so callers control size/attributes. `simplified` keeps two grid lines only — crisp at 16 px. * `plate=false` draws the graph alone (monochrome contexts). */ export function MarkArt({ colors, simplified = false, plate = true, radius = 7 }: { colors: MarkColors } & MarkOpts) { const g = MARK_GEOMETRY; const strokeW = simplified ? 2 : 1.7; const nodeR = simplified ? 2.4 : 2.1; const gridW = simplified ? 1 : 0.8; return ( <> {plate && } {g.gridH.map((y) => ( ))} {!simplified && g.gridV.map((x) => )} ); } /** The same artwork as a standalone SVG string (static assets, data URIs for ImageResponse). */ export function markSvgString(colors: MarkColors, { simplified = false, plate = true, radius = 7 }: MarkOpts = {}): string { const g = MARK_GEOMETRY; const strokeW = simplified ? 2 : 1.7; const nodeR = simplified ? 2.4 : 2.1; const gridW = simplified ? 1 : 0.8; const parts: string[] = [``]; if (plate) parts.push(``); for (const y of g.gridH) parts.push(``); if (!simplified) for (const x of g.gridV) parts.push(``); parts.push(``); parts.push(``); parts.push(``); parts.push(``); parts.push(``); parts.push(''); return parts.join(''); } export function markDataUri(colors: MarkColors, opts?: MarkOpts): string { return `data:image/svg+xml;utf8,${encodeURIComponent(markSvgString(colors, opts))}`; } /** * The mark for ImageResponse routes (OG images, PWA/Apple icons): a data-URI , which satori rasterises reliably * (nested SVG element trees are not). Fixed hex colours only. */ export function MarkImg({ px, colors = MARK_DARK, simplified = false, plate = true, radius }: { px: number; colors?: MarkColors } & MarkOpts) { // eslint-disable-next-line @next/next/no-img-element return ; }