Design system
Tokens and components extracted from the Figma file "HUGE ONE" (canvas "MVP launch"). Three-layer architecture: primitive, semantic, component. Source code: css/styles.css.
Token architecture
A raw value (hex, px) should never appear directly in a component. It always goes through a semantic token, which itself is built on a primitive token.
| Layer | Role | Example |
|---|---|---|
| Primitive | Raw value, no intent | --blue-500: #3568b8; |
| Semantic | Alias with meaning | --color-accent: var(--blue-500); |
| Component | Specific use in one component | --button-primary-bg: var(--color-accent); |
Colors
15 named colors, grouped by what they're for rather than what they look like. Down from the 18 the raw Figma export used, most of them near-duplicates of each other, plus a full success/warning/error feedback set the export didn't have at all. Text runs on a neutral gray scale now, not the saturated blue the export shipped with; blue is reserved for interactive moments and surface tinting.
Text
Darkest to lightest. All four pass WCAG AA on both the page background and white.
Background & surface
Lightest to most present. bg is the page canvas; surface-tint is for anything that needs to visibly sit above it (cards, tables, badges, notes).
Interactive (accent)
Buttons, links, active states, focus ring. Also reused as border-strong where a card needs to visibly separate from its own tint.
Feedback
Warning, success, error: three hues, each deliberately far from the brand blue so they never get mistaken for a clickable accent. Info has no color of its own here, it reuses accent (see above) rather than adding a fourth near-blue.
Not used anywhere in this MVP's specs yet (there are no forms or confirmations to show), but the app will need them: form validation errors in the admin back office, a confirmation toast after favoriting or publishing, a failed network request on the feed.
| Semantic token | Value | Usage |
|---|---|---|
--color-accent | #3568b8 | CTAs, active links, active tab, focus ring |
--color-text | #404454 | Content titles (startup name, post text) |
--color-text-muted | #585f6e | Numeric values (KPIs) |
--color-text-subtle | #606485 | Secondary text, descriptions |
--color-heading | #222224 | Navigation labels, UI headings |
--color-warning | #8a5a2b | Roadmap markers, open questions, pending states |
--color-success | #237246 | Confirmations, positive KPI trend, verified / published |
--color-error | #a8322d | Form validation, failed requests, destructive actions |
Typography
Two families: SF Pro Display for the interface, DM Serif Display for editorial moments (startup name, headings). Fonts are not embedded on this demo page (system fallback), they need to be sourced and licensed for the app.
Spacing & radius
Scale observed in the components (button padding, list gaps).
| Token | Value | Usage |
|---|---|---|
--radius-sm | 8px | Small UI elements |
--radius-md | 24px | Inner cards, wide badges |
--radius-lg | 32px | Buttons, container cards, tab bar |
--radius-pill | 999px | Avatars, round buttons, pill badges |
Effects
Soft blue-tinted shadow on cards, blue glow on the primary CTA. Liquid glass (blur, saturation boost, bright top edge, soft elevation) on the tab bar, the secondary button, and tertiary icon buttons, in the style of iOS's layered glass surfaces.
Badges: funding stage
"Funding round status" component, 4 variants depending on the startup's stage.
Tab bar (bottom navigation)
Blurred glass background, active dot highlighted. Used for the app's main navigation.
aria-label is required since these buttons carry no visible text, only an icon.Cards & avatar
White card, 24px rounded corners, soft shadow. Circular avatar with a verification badge (not recreated here, SVG icon sourced from Figma).
Price comparison platform for boat charters & tours worldwide.
Swipe actions (tertiary)
Floating circular icon buttons above the card stack (discovery feed). Tertiary action style: liquid glass, same recipe as the tab bar and the secondary button.
Icons
Reference library: Hugeicons (59,000+ icons), replacing the ad hoc icons from the original Figma file (Phosphor Icons and a custom $icon-line-* set). This site's own nav icons are inlined straight from the Hugeicons free SVG source, not the icon font, to avoid any external font-loading dependency.
| Default style | Stroke Rounded, the only style included in the free tier and consistent with the line-icon style already used in the mockups |
|---|---|
| Flutter integration | the hugeicons package on pub.dev (free), or the Pro guide if premium styles are needed |
| License | Free: Stroke Rounded style only. Pro (paid): 9 other styles (Bulk, Solid, Twotone, Duotone, Sharp...) |
Accessibility
Target: WCAG 2.1 level AA. Checked against the real tokens (computed contrast ratios, not visual guesses). Several gaps were found and fixed in the tokens above.
Contrast fixes
| Token | Before | After | Why |
|---|---|---|---|
--color-accent | Figma export #5790df, 3.25:1 on white | #3568b8, 5.49:1 | Used as button text, link, and label color, below the AA threshold (4.5:1) as it stood |
--color-text-subtle | Figma export #6b6f8c, 4.58:1 on app background | #606485, 5.35:1 | Margin too thin (AA cutoff is 4.5:1), a different font rendering could have pushed it below. Also desaturated toward neutral gray along with the rest of the text scale, see below |
| Note code chips | same tint as their own background, invisible | white with a border, always visible | Code chips reused the surrounding tint, so they disappeared inside table headers and notes |
Keyboard focus
A real :focus-visible rule was added on every interactive element (buttons, tabs, tab bar, nav links): a 3px ring in --color-focus-ring, 2px offset. This is separate from the "Focused" variant in Figma, which documents a visual design state rather than actual keyboard behavior.
Touch targets
44×44px minimum (token --touch-target-min) on every interactive element. The Figma tab bar drew dots at 42px, raised to 44px in the tokens.
Semantics & keyboard
- Tabs (startup profile, tab bar): ARIA
tablist/tab/tabpanelpattern, arrow-key navigation, only one element in the tab order at a time. - Icon-only buttons with no visible label (tab bar):
aria-labelis required. - Heading hierarchy: one
h1per page, no level skipped (h2 to h3 directly, never h2 to h4).
Open questions
- Admin back-office forms (not yet designed): every field will need an associated
<label>and a clear error message, not a placeholder used as the only label. - Startup logos, photos, and uploaded documents: alt text to be entered by the internal team at upload time (needs a field in the back office).
- Swipe action icons (♥ / ✕ / ↺) sit over a variable photo background in production. Contrast needs checking against real startup photos, not just the dark demo background used here.
- No animation is defined yet. Once swipe transitions are implemented, plan a
prefers-reduced-motionalternative that keeps the information instead of just cutting the animation to 0ms.
Usage notes
- SF Pro Display and DM Serif Display need to be sourced and licensed before integrating them into the app. This page uses a system fallback for the demo.
- This extraction covers the components visible on the screens reviewed so far (Feed, buttons, navigation, badges). Other components in the file still need documenting as we go (inputs, modals, empty states).
- Native Figma variables (linked colors/effects) aren't reachable remotely without the desktop app. The tokens above were rebuilt from the resolved values in the design context.