/* tokens.css — the design-token foundation for rfc-app's UI. * * Roadmap item #31 (comprehensive UX polish). Before this file the app * had ~98 distinct hardcoded hex colors, font sizes scattered across 16 * values with no scale, and radii across 13 values — classic prototype * sprawl. This module establishes ONE coherent system; the App.css sweep * (and component-scoped CSS) reference these custom properties instead of * literal values, so "what color/size/space is this" has a single answer. * * Imported FIRST in main.jsx so :root is defined before any other sheet. * Custom properties are not cascade-order-sensitive at use time, but * importing first keeps the dependency obvious. * * Conventions for anyone sweeping values to these tokens: * - Map each literal to the NEAREST semantic token, then fall back to a * primitive ramp step. Consolidating near-duplicate grays is the point. * - Never invent a new literal in a component; add a token here instead. * - Spacing/radii/type use the scales below — no off-scale px values. */ :root { /* ===== Color primitives — neutral ramp ===== */ --c-white: #ffffff; --c-gray-50: #fafafa; --c-gray-100: #f3f4f6; --c-gray-150: #f0f0ee; /* the app's warm canvas tint */ --c-gray-200: #e5e7eb; --c-gray-300: #d1d5db; --c-gray-400: #9ca3af; --c-gray-500: #6b7280; --c-gray-600: #4b5563; --c-gray-700: #374151; --c-gray-800: #1f2937; --c-gray-900: #111111; --c-ink: #1a1a1a; /* near-black used for the header + body text */ /* ===== Color primitives — accent (indigo/violet) ===== */ --c-accent: #5b5bd6; --c-accent-strong: #4338ca; --c-violet: #7c3aed; /* ===== Color primitives — status ===== */ --c-success-fg: #166534; --c-success-bg: #dcfce7; --c-danger-fg: #991b1b; --c-danger-fg-strong: #b91c1c; --c-danger-bg: #fef2f2; --c-danger-border: #fecaca; --c-warning-fg: #92400e; --c-warning-accent: #b45309; --c-warning-bg: #fef3c7; --c-warning-bg-soft:#fffbeb; /* ===== Semantic colors ===== */ --color-bg: var(--c-gray-150); --color-surface: var(--c-white); --color-surface-sunken: var(--c-gray-50); --color-surface-muted: var(--c-gray-100); --color-header-bg: var(--c-ink); --color-text: var(--c-ink); --color-text-strong: var(--c-gray-900); --color-text-muted: var(--c-gray-500); --color-text-subtle: var(--c-gray-400); --color-text-inverse: var(--c-white); --color-border: var(--c-gray-200); --color-border-strong: var(--c-gray-300); --color-link: var(--c-accent); --color-accent: var(--c-accent); --color-accent-strong: var(--c-accent-strong); --color-accent-contrast: var(--c-white); --color-success-fg: var(--c-success-fg); --color-success-bg: var(--c-success-bg); --color-danger-fg: var(--c-danger-fg); --color-danger-bg: var(--c-danger-bg); --color-warning-fg: var(--c-warning-fg); --color-warning-bg: var(--c-warning-bg); /* On the dark header, translucent white is the established pattern. */ --color-on-dark-soft: rgba(255, 255, 255, 0.15); --color-on-dark-hover: rgba(255, 255, 255, 0.25); --color-on-dark-muted: #dddddd; --color-focus-ring: rgba(91, 91, 214, 0.45); /* ===== Type ===== */ --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; --text-2xs: 10px; --text-xs: 11px; --text-sm: 12px; --text-base: 13px; /* the app's dominant body size */ --text-md: 14px; --text-lg: 16px; --text-xl: 18px; --text-2xl: 22px; --text-3xl: 28px; --leading-tight: 1.25; --leading-normal: 1.5; --leading-relaxed: 1.65; --weight-normal: 400; --weight-medium: 500; --weight-semibold: 600; --weight-bold: 700; /* ===== Spacing scale (4-based, with the 2/6/10 half-steps the app * already leans on heavily) ===== */ --space-0: 0; --space-1: 2px; --space-2: 4px; --space-3: 6px; --space-4: 8px; --space-5: 10px; --space-6: 12px; --space-7: 16px; --space-8: 20px; --space-9: 24px; --space-10: 32px; --space-11: 48px; --space-12: 64px; /* ===== Radius ===== */ --radius-xs: 2px; --radius-sm: 4px; --radius-md: 6px; --radius-lg: 8px; --radius-xl: 12px; --radius-pill: 999px; /* ===== Elevation ===== */ --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.06); --shadow-md: 0 2px 8px rgba(0, 0, 0, 0.08); --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12); /* ===== Motion ===== */ --motion-fast: 120ms; --motion-base: 150ms; --motion-slow: 200ms; --ease-out: cubic-bezier(0.16, 1, 0.3, 1); --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1); /* ===== Layout ===== */ --header-height: 48px; } /* Honor reduced-motion globally — any transition/animation that reads * these duration tokens collapses to instant. */ @media (prefers-reduced-motion: reduce) { :root { --motion-fast: 0ms; --motion-base: 0ms; --motion-slow: 0ms; } }