Style guide
The living design system for Project Budget. Every component on this page is rendered with the production CSS, so what you see is what the rest of the site uses. Designed against WCAG 2.2 AA contrast and target-size minimums, with AAA touch targets on every default-size button.
Color tokens
Palette is shared with Project Broadsheet — paper / ink / vermillion / slate / gold — so projects feel related without being identical. Variable names stay app-local (--bg, --fg, --accent) so swapping themes touches one file. Every text-on-surface pairing below clears WCAG 2.2 AA (4.5:1 for body, 3:1 for large text and UI surfaces) in both light and dark themes.
--bgpage--bg-elevatedcards, modals--bg-alttable heads, alt rows--fgbody text--fg-mutedsecondary text--fg-subtlesmall print, hints--accentprimary actions, links--linkin-prose links--okpositive available--warnwarnings, due--dangerdestructive, outflowTypography
Four families: Playfair Display for masthead and modal titles, Lora for headlines, Source Serif 4 for body, DM Sans for in-app UI. Type scale is fluid where it counts (KPIs, hero) and a flat ramp everywhere else.
Spacing scale
Nine steps from 3xs (4px) to 3xl (96px). Grids and components compose from this scale — never raw pixels.
--space-3xs4px--space-2xs8px--space-xs12px--space-sm16px--space-md24px--space-lg32px--space-xl48px--space-2xl72px--space-3xl96px
Buttons
Default-size buttons are 44 × 44 CSS pixels minimum (WCAG 2.2 AAA target size). The compact variant btn--sm is 36 × 36 and reserved for dense table rows. Every variant has an explicit :focus-visible ring and a :disabled state.
Primary
Secondary
Ghost
Danger
Forms
Every input is paired with a visible <label>. field__hint is for non-essential help text; required and error messaging live above or beside the input, never as the only signal. Inputs are 44 px tall (matching the button target size) so the form line aligns with the action row.
Cards
The default container for any group of related content inside the app shell. Cards have horizontal overflow on so tables inside them scroll laterally on phones instead of forcing the page wider.
Storage
Profile data is held in your browser's localStorage. Typical quota is 5–10 MB.
182.4 KB used of 5 MB (4%)
Tables
Numeric columns use .num (right-aligned, tabular-nums). Tables inside cards scroll horizontally on phones.
| Date | Payee | Category | Amount |
|---|---|---|---|
| Apr 18 | Whole Foods | Groceries | -$48.22 |
| Apr 17 | Payroll | Income | $2,400.00 |
| Apr 15 | Comcast | Internet | -$79.99 |
Badges
For inline metadata — status, tags, counts. Pair color with a label so the meaning isn't color-only.
Alerts & help blocks
For inline guidance and warnings. The .form-help block carries a left accent border so it reads as advisory, not error.
All imports run in your browser. The file you select never leaves this page.
Toasts
Bottom-right transient notifications. The container is aria-live="polite"; each toast carries role="status" so screen readers announce them without interrupting the user.
Profile 'Household' created.
Delete cancelled — typed name did not match.
Could not save changes. Check browser storage settings.
Modals
Every modal carries role="dialog" and aria-modal="true". Esc closes; click-outside dismisses. Destructive actions require typed-name confirmation (see the delete-profile flow).
Delete profile
Deleting moves the profile to trash for 7 days. You can restore it from Settings during that window.
To confirm, type the profile name exactly: Household
Accessibility checklist
- Target size. Default buttons, header icon buttons, and modal-close buttons are 44 × 44 CSS pixels (WCAG 2.2 AAA). Compact buttons in dense table rows are 36 × 36 (AA, 24 × 24 minimum). Dense controls (
.cleared-toggle) render at 28 × 28 but extend their hit area to 44 × 44 via a transparent pseudo-element. - Focus visible. Every interactive element has a 2 px solid
--accentoutline plus a 4 px soft halo on buttons. Skip-link slides into view on focus. - Contrast. Body text ≥ 4.5:1, large text and UI surfaces ≥ 3:1 in both themes.
--fg-subtlewas retuned to clear 4.5:1 on the paper background for small print. - Color is never the only signal. Amounts pair color with a sign and a number; goal status pairs color with a label; reconciled state pairs background with the lock icon.
- Semantic structure. One
<h1>per page. Landmarks (header,nav,main,footer) wrap their regions. Tables use<th scope="col">. - Keyboard. Esc closes modals. Skip link goes to
#main. Every action available by mouse is available by keyboard. - Reduced motion.
prefers-reduced-motioncollapses every animation and transition to 0.01ms. - Live regions. The toast stack is
aria-live="polite"+aria-atomic="true"; individual toasts userole="status". - Forms. Every input has a paired
<label for="...">. Required state is conveyed by the attribute and the label, not by color.