DESIGN.md
Creative North Star: "The Home Office"
Actual feels like a tidy personal desk: familiar, unpretentious, everything within reach. It is a tool people open weekly for years to reconcile accounts and move envelope money around, so the interface optimizes for routine, not first impressions. Density is moderate-to-high (this is a table-driven app), feedback is instant, and decoration is close to zero. The financial numbers are the interface; everything else exists to keep them legible and trustworthy.
The system explicitly rejects fintech-startup gloss (gradient heroes, glassmorphism, crypto-dashboard neon) and corporate banking UI (navy-and-gold enterprise-portal density). It is calm, trustworthy, and practical, and it must render identically well in three themes: light, dark, and midnight.
Key Characteristics:
A calm navy-neutral base with one confident purple accent and strict semantic roles for money.
All hex values in this file (frontmatter included) are the light-theme palette mapping. The dark and midnight themes remap the same semantic roles to different palette values, so never use these hexes directly in components — route every color through the theme.* semantic tokens (see The Semantic Token Rule below).
The Semantic Token Rule. Components never use raw palette values or hex codes. Every color goes through the theme.* semantic layer (--color-* custom properties) so all three themes (light, dark, midnight) stay correct. A hardcoded hex in a component is a bug.
The One Accent Rule. Actual Purple appears on well under 10% of any screen: primary action, current selection, active nav. It never decorates.
The Never-Color-Alone Rule. Positive/negative money state is conveyed by sign and context as well as color; green/red are reinforcement, never the only signal.
Body Font: Inter Variable (with system-ui fallback stack) Label/Mono behavior: Same family; financial figures switch on tabular OpenType features
Character: One workhorse sans at compact sizes. No display serif, no font pairing games: hierarchy comes from weight and size, and the typographic star is the number column.
The Tabular Number Rule. Every standalone financial figure renders with font-feature-settings: "tnum", "ss01", "ss04" (via FinancialText or styles.tnum) so digits align in columns and disambiguate. A proportional-figure money column is a bug.
Flat-first with ambient shadows. Structure comes from 1px borders (Navy Mist) and background shifts (White on Mist, Frost on hover), not depth. Shadows exist only to lift transient surfaces above the page: menus, tooltips, popovers, modals. Persistent surfaces like tables and cards sit flat or carry the faint card shadow at most.
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)): Resting cards and small raised widgets.box-shadow: 0 2px 4px 0 rgba(0,0,0,0.1)): Focused inputs, subtle lift.box-shadow: 0 15px 30px 0 rgba(0,0,0,0.11), 0 5px 15px 0 rgba(0,0,0,0.08)): Tooltips, popovers, floating panels.The Transient-Only Rule. If a surface stays on screen, it gets a border. If it appears on interaction and disappears, it may cast a shadow.
Utilitarian and quick: compact paddings, instant state feedback, built for daily repetition. All values below are the light theme; every color routes through the semantic token layer.
box-shadow .25s)The core surface of the app. White rows on 1px Navy Mist borders, Frost hover, purple-bordered selection, sticky header with Slate 13px text, amounts right-aligned in tabular figures colored by the semantic money tokens. Alternate-row striping is theme-controlled, never hardcoded.
theme.* semantic tokens so light, dark, and midnight themes all work. Test all three.FinancialText or apply styles.tnum.@actual-app/components) before writing new UI.--palette-* colors in components; the semantic layer is the only entry point.border-left/border-right thicker than 1px as a colored accent stripe.box-shadow .25s).