import type { CSSProperties } from 'react'; export type PrivacyMode = 'on-device' | 'cloud' | 'hybrid' | 'unknown'; export interface PrivacyBadgeProps { /** Where does the inference actually run? */ mode: PrivacyMode; /** Short label override (default: 'On device' / 'Cloud' / โ€ฆ). */ label?: string; /** * Optional one-line attribution โ€” e.g. provider/model id, or the * device name. Rendered as a smaller secondary string. */ detail?: string; /** Render with only the dot โ€” no text. Default false. */ iconOnly?: boolean; className?: string; style?: CSSProperties; } const TINTS: Record< PrivacyMode, { bg: string; fg: string; ring: string; dot: string; label: string; icon: string } > = { 'on-device': { bg: 'color-mix(in srgb, var(--bl-success, #10b981) 12%, transparent)', fg: 'var(--bl-success, #047857)', ring: 'color-mix(in srgb, var(--bl-success, #10b981) 35%, transparent)', dot: 'var(--bl-success, #10b981)', label: 'On device', icon: '๐Ÿ“ด', }, cloud: { bg: 'color-mix(in srgb, var(--bl-info, #0ea5e9) 12%, transparent)', fg: 'var(--bl-info, #075985)', ring: 'color-mix(in srgb, var(--bl-info, #0ea5e9) 35%, transparent)', dot: 'var(--bl-info, #0ea5e9)', label: 'Cloud', icon: 'โ˜๏ธ', }, hybrid: { bg: 'color-mix(in srgb, var(--bl-accent, #6366f1) 12%, transparent)', fg: 'var(--bl-accent, #4338ca)', ring: 'color-mix(in srgb, var(--bl-accent, #6366f1) 35%, transparent)', dot: 'var(--bl-accent, #6366f1)', label: 'Hybrid', icon: '๐Ÿ”€', }, unknown: { bg: 'var(--bl-surface-muted, rgba(0,0,0,0.05))', fg: 'var(--bl-text-secondary, #555)', ring: 'var(--bl-border, rgba(0,0,0,0.12))', dot: 'var(--bl-text-tertiary, #999)', label: 'Unknown', icon: 'โ“', }, }; /** * `` โ€” honest indicator of where AI inference happens. * * Trust surface (Wave 13.C.6). Every chat / agent UI should make * privacy state visible to the user โ€” never hidden in settings. * * - `on-device` โ€” fully local (e.g. WebLLM, ollama, Apple Intelligence) * - `cloud` โ€” server-side (OpenAI, Anthropic, your own infra) * - `hybrid` โ€” routing decides per-request (router/llm-router) * - `unknown` โ€” host can't determine; render rather than hide */ export function PrivacyBadge({ mode, label, detail, iconOnly = false, className, style, }: PrivacyBadgeProps) { const tint = TINTS[mode] ?? TINTS.unknown; const text = label ?? tint.label; return ( ); }