import { siteSettings } from "@/lib/services/site-settings"; import { FONTS } from "@/lib/theme-presets"; // Injects the DB-driven CSS custom properties into :root, exactly like // AtomCMS's app.blade.php. Falls back to the atom defaults when no DB. Covers // colours, typography, buttons, links + an optional raw custom-CSS block. export async function ThemeVars() { const g = (k: string, d: string) => siteSettings.get(k, d); const [ primary, background, surface, dropdown, navbar, navbarText, text, textMuted, accent, buttonColor, buttonText, buttonSecondary, buttonDanger, linkColor, linkHover, borderColor, borderRadius, fontKey, h1, h2, h3, customCss, ] = await Promise.all([ g("color_primary", "#f59e0b"), g("color_background", "#f8fafc"), g("color_surface", "#ffffff"), g("color_dropdown", "#ffffff"), g("color_navbar", "#ffffff"), g("color_navbar_text", "#1e293b"), g("color_text", "#0f172a"), g("color_text_muted", "#64748b"), g("color_accent", "#10b981"), g("button_primary_color", "#f59e0b"), g("button_text_color", "#1e293b"), g("button_secondary_color", "#22c55e"), g("button_danger_color", "#ef4444"), g("link_color", "#eeb425"), g("link_hover_color", "#cf9d15"), g("border_color", "#eeb425"), g("border_radius", "12"), g("font_family", "nunito"), g("size_heading_h1", "30"), g("size_heading_h2", "22"), g("size_heading_h3", "18"), g("custom_css", ""), ]); // Only hex/keyword color values are admin-controlled — sanitize defensively. const safe = (v: string | null, d: string) => (v && /^[#a-zA-Z0-9(),.\s%-]+$/.test(v) ? v : d); const px = (v: string | null, d: string) => (/^\d{1,3}$/.test(v ?? "") ? (v as string) : d); const font = FONTS[fontKey ?? "nunito"] ?? FONTS.nunito; const css = `:root{ --color-primary:${safe(primary, "#f59e0b")}; --color-background:${safe(background, "#f8fafc")}; --color-surface:${safe(surface, "#ffffff")}; --color-dropdown:${safe(dropdown, "#ffffff")}; --color-navbar:${safe(navbar, "#ffffff")}; --color-navbar-text:${safe(navbarText, "#1e293b")}; --color-text:${safe(text, "#0f172a")}; --color-text-muted:${safe(textMuted, "#64748b")}; --color-accent:${safe(accent, "#10b981")}; --button-color:${safe(buttonColor, "#f59e0b")}; --button-text-color:${safe(buttonText, "#1e293b")}; --button-secondary-color:${safe(buttonSecondary, "#22c55e")}; --button-danger-color:${safe(buttonDanger, "#ef4444")}; --link-color:${safe(linkColor, "#eeb425")}; --link-hover-color:${safe(linkHover, "#cf9d15")}; --border-color:${safe(borderColor, "#eeb425")}; --border-radius:${px(borderRadius, "12")}px; --font-family:${font.stack}; --size-heading-h1:${px(h1, "30")}px; --size-heading-h2:${px(h2, "22")}px; --size-heading-h3:${px(h3, "18")}px; }`; const googleHref = font.google ? `https://fonts.googleapis.com/css2?family=${font.google}&display=swap` : null; return ( <> {googleHref ? : null} {/* biome-ignore lint/security/noDangerouslySetInnerHtml: server-built CSS from sanitized admin settings */}