import type { ReactNode } from 'react'; import { MARK_PATHS } from '@/components/brand/Logo'; import { MAP_HEIGHT, MAP_WIDTH, worldPaths } from '@/lib/map-geo'; /** * Shared building blocks for the OG/Twitter images (next/og ImageResponse → Satori). Satori supports a flex * subset of CSS and inline SVG; no CSS variables, so colours are literal. Dark editorial background, the brand * mark, a faint world map (Equal Earth, world-atlas 110m) as the "wallpaper" motif. Fonts: Satori's bundled * default sans (loading Google fonts at build would make the build network-dependent — avoided on purpose). */ export const OG_BG = '#151513'; export const OG_INK = '#f2f0ea'; export const OG_INK2 = '#c9c6bd'; export const OG_INK3 = '#8a877f'; export const OG_ACCENT = '#5598e7'; export const OG_RULE = '#2c2b28'; export const OG_LAND = '#26364a'; export const OG_LAND_STROKE = '#151513'; export function OgMark({ size = 96, color = OG_ACCENT }: { size?: number; color?: string }) { const m = MARK_PATHS; return ( ); } /** Large, faint globe with meridians and parallels, positioned at the right edge (kept for the entity cards). */ export function OgMeridians({ size = 760, x = 640, y = -80 }: { size?: number; x?: number; y?: number }) { return ( ); } /** * Faint world map wallpaper: every country of the 110m atlas as a filled path (Equal Earth), plus the sphere * outline and a light graticule. `width` in px; positioned absolutely by the caller through `style`. * `highlight` (ISO3 list) fills those countries in the accent colour. */ export function OgWorldMap({ width = 1320, style, opacity = 0.9, highlight = [] }: { width?: number; style?: React.CSSProperties; opacity?: number; highlight?: string[] }) { const { paths, sphere } = worldPaths(); const height = Math.round((width * MAP_HEIGHT) / MAP_WIDTH); const hl = new Set(highlight); return ( {[-60, -30, 0, 30, 60].map((lat) => { const y = MAP_HEIGHT / 2 - (lat / 90) * (MAP_HEIGHT / 2) * 0.98; return ; })} {paths.map((p, i) => ( ))} ); } export function OgFrame({ children, map = false, highlight }: { children: ReactNode; map?: boolean; highlight?: string[] }) { return (
{map ? : }
{children}
); } export function OgWordmark({ size = 34 }: { size?: number }) { return (
Country Atlas
); } /** Row of three or four headline figures: label above, big number below (used by the default share card). */ export function OgFigures({ items }: { items: Array<{ label: string; value: string }> }) { return (
{items.map((it) => (
{it.label}
{it.value}
))}
); }