into every app.
Ready-to-use community infrastructure — feeds, chat, and communities inside your app.
communities.
conversation.
real conversations.
community awaits.
Colors
Three primary families — Ultramarine, Slate, Picton Blue — anchored by Slate neutrals and a vivid accent palette for community identities. On dark surfaces, Ultramarine 600 is reserved for fills with white labels; ultramarine text and icons step up to Ultra 400 (--action-accent) to hold WCAG AA contrast.
#111111
#272727
#535353
#A3A3A3
#E6E6E6
#FAFAFA
#FFFFFF
Used exclusively for community avatar gradients, category chips, and user-generated colour identifiers. Never used for UI controls.
Typography
One typeface. Figtree — geometric, warm, confident. ExtraBold carries display moments; Regular and Medium keep body copy clear and human.
Real belonging.
text-hero
3.25rem (52px)
0.95
700
social.plus
text-3xl
2.25rem (36px)
1.05
700
Be part of something
text-2xl
1.75rem (28px)
1.1
700
All your communities
text-xl
1.5rem (24px)
1.15
700 / 400i
Join the community
text-xl-italic
1.5rem (24px)
1.15
400i
Real belonging.
text-lg
1.25rem (20px)
1.3
500
Section heading
text-md
1.0625rem (17px)
1.35
500 / 400
Card title or strong body
text-base
0.9375rem (15px)
1.45
400
Default body text — readable at all sizes
text-sm
0.8125rem (13px)
1.4
400 / 500
Secondary label or metadata
text-xs
0.75rem (12px)
1.4
500 / 600
CAPTION · OVERLINE · BADGE
H1
2.75rem - 5rem (44-80px)clamp(2.75rem, 1.5rem + 2svw, 5rem)
1.1
700
Display
H2
2.25rem - 3.25rem (36-52px)clamp(2.25rem, 1.5rem + 2svw, 3.25rem)
1.25
700
Section
H3
1.75rem - 2.25rem (28-36px)clamp(1.75rem, 1rem + 2svw, 2.25rem)
1.25
700
Sub-section
H4
1.5rem - 1.75rem (24-28px)clamp(1.5rem, 0.875rem + 2svw, 1.75rem)
1.25
700
Small heading
H5
1.25rem (20px)
1.25
700
Compact heading
H6
1.125rem (18px)
1.25
700
Smallest heading
--weight-light: 300--weight-regular: 400--weight-medium: 500--weight-semibold: 600--weight-bold: 700people.
Spacing
A 4px base grid. Every layout decision — padding, gap, margin — maps to a named step. This keeps rhythm consistent across every screen in the app.
--space-1
1 × 4
4px
Icon gap, badge padding, micro nudges
--space-2
2 × 4
8px
Chip inner padding, tight icon + label
--space-3
3 × 4
12px
Button padding (v), input inner padding
--space-4
4 × 4
16px
Button padding (h), card inner gap, nav item
--space-5
5 × 4
20px
Card padding, section inner gap
--space-6
6 × 4
24px
Card padding (large), modal padding
--space-8
8 × 4
32px
Section gap, screen horizontal padding
--space-10
10 × 4
40px
Between major sections on screen
--space-12
12 × 4
48px
Hero padding, large screen breathing room
--space-16
16 × 4
64px
Page-level vertical rhythm
--space-20
20 × 4
80px
Bottom nav safe area clearance
Border Radius
social.plus uses generous, soft curves — echoing the rounded logo mark. Never cold and boxy. Radius scales from sharp utility elements up to fully-circular avatars, with a clear semantic role at each step.
--radius-xs
4px
Tags, code badges, micro chips
--radius-sm
8px
Buttons (small), nav items, tooltips
--radius-md
12px
Buttons (default), input fields, small cards
--radius-lg
16px
Feed cards, list items, dropdowns
--radius-xl
20px
Large cards, context panels
--radius-2xl
24px
Modal sheets, featured cards
--radius-3xl
32px
Bottom sheets, hero images
--radius-pill
100px
Pill buttons, search bar, toggles
--radius-full
50%
Avatars, icon buttons, indicators
Elevation
Shadows create a sense of depth and hierarchy. In light mode they use soft neutral shadows — heavier as the layer rises. Switch to dark mode to see the background layering system. Shadows create a sense of depth and hierarchy. In dark mode they rely on background layering — surfaces get progressively lighter as they rise. No heavy drop shadows needed.
none
Flat
Inline elements, selected states with border, tab items
--shadow-sm
Level 1
Chips, input fields, subtle cards on light background
--shadow-md
Level 2
Cards, dropdowns, context menus
--shadow-lg
Level 3
Floating action buttons, sticky headers, toasts
--shadow-xl
Level 4
Modals, bottom sheets, popovers
--shadow-glow
Glow
Primary CTA buttons on hover/focus, featured items
In light mode, depth is expressed through warm shadows and subtle background steps — from sunken inputs up to pure-white modals. Each layer has a named token.
In dark mode, depth is communicated through progressively lighter backgrounds — not heavier shadows. Each layer has a named token.
--z-base0Page content--z-raised10Sticky cards, inline floats--z-dropdown100Dropdowns, context menus--z-sticky200Sticky headers, bottom nav--z-toast400Toasts, snackbars--z-overlay500Modal backdrop--z-modal600Modals, bottom sheets--z-top900System alerts, debug panelsMotion
Motion should feel warm and alive — never mechanical. Fast for micro-interactions, smooth for transitions, springy for moments of delight. All transitions respect prefers-reduced-motion.
--duration-instant
80ms
State flips — active/inactive toggle, checkbox tick
--duration-fast
150ms
Button press feedback, hover reveals, badge updates
--duration-base
250ms
Default — theme switch, card expand, drawer slide
--duration-enter
320ms
Screen entry, modal appear, page transitions
--duration-slow
400ms
Bottom sheet rise, complex layout changes
--ease-out
cubic-bezier(0.16, 1, 0.3, 1)
Entering elements — things arriving on screen. Fast start, soft landing.
--ease-in-out
cubic-bezier(0.4, 0, 0.2, 1)
Transitions between states — smooth, symmetrical, controlled.
--ease-spring
cubic-bezier(0.34, 1.56, 0.64, 1)
Delight moments — avatar pop, like animation, join confirmation.
Hover or tap each element to see the motion token in action.
prefers-reduced-motion. When enabled, durations collapse to 1ms and transforms are replaced with opacity-only fades.Primitive Tokens
The raw, hardcoded values. These are never used directly in components — they exist solely as a named source of truth that semantic tokens reference. Change a primitive here and it cascades everywhere.
--ultra-50#EDF4FF--ultra-300#A1BAFF--ultra-400#7B94FE--ultra-600#3B41EC--ultra-800#2B2FA8--slate-100#F5F5F5--slate-300#D3D3D3--slate-500#727272--slate-600#535353--picton-50#F1F7FE--picton-300#84C2F5--picton-500#1B89DC--picton-700#0C5598--slate-950#111111--slate-800#272727--slate-600#535353--slate-400#A3A3A3--slate-200#E6E6E6--slate-50#FAFAFA--white#FFFFFF--accent-orange#F66005--accent-orange-light#FF9836--accent-yellow#F7C506--accent-pink#F568F0--accent-sky#45A5ED--accent-periwinkle#7B94FE--accent-magenta#EB4AE5--space-14px--space-28px--space-312px--space-416px--space-520px--space-624px--space-832px--space-1040px--space-1248px--space-1664px--space-2080px--radius-xs4px--radius-sm8px--radius-md12px--radius-lg16px--radius-xl20px--radius-2xl24px--radius-3xl32px--radius-pill100px--radius-full50%--text-xs12px--text-sm13px--text-base15px--text-md17px--text-lg20px--text-xl24px--text-2xl28px--text-3xl36px--text-hero52px--weight-light300--weight-regular400--weight-medium500--weight-semibold600--weight-bold700--duration-instant80ms--duration-fast150ms--duration-base250ms--duration-enter320ms--duration-slow400ms--ease-outcubic-bezier(0.16,1,0.3,1)--ease-in-outcubic-bezier(0.4,0,0.2,1)--ease-springcubic-bezier(0.34,1.56,0.64,1)Semantic Tokens
Named by role, not by value. Components only ever reference semantic tokens — never primitives. This makes theming surgical: swap one semantic token and the whole system updates.
--bg-baseslate-50#FAFAFAApp base — every screen--bg-elevatedwhite#FFFFFFCards, nav bar, modals--bg-cardslate-100#F5F5F5Feed cards, list rows--bg-sunkenderived#E6E6E6Input fields, recessed zones--text-primaryslate-950#111111Headings, body copy--text-secondaryslate-600#535353Supporting text, labels--text-tertiaryslate-400#A3A3A3Timestamps, placeholders--text-inversewhite#FFFFFFText on dark backgrounds--border-faintslate-950/6%rgba(17,17,17,.06)Section dividers, hairlines--border-subtleslate-950/10%rgba(17,17,17,.10)Cards, inputs at rest--border-defaultslate-950/16%rgba(17,17,17,.16)Default interactive borders--border-strongslate-950/28%rgba(17,17,17,.28)Focus rings, strong dividers--action-primaryultra-600#3B41ECCTA buttons, links, highlights--action-primary-hoverultra-700#3133D1Hover state--action-primary-pressultra-800#2B2FA8Pressed/active state--action-primary-subtleultra-50#EDF4FFTinted bg for active tabs--action-accentultra-600#3B41ECText & icon ultramarine — 6.66:1 AA--status-successgreen#1B89DCConfirmations, joined states--status-warningderived#CC9202Alerts, pending states--status-errorderived#FF305AErrors, destructive actions--status-infoderived#1B89DCInformational banners--shadow-smInputs, inline chips--shadow-mdCards, dropdowns--shadow-lgFABs, sticky headers--shadow-xlModals, bottom sheets--shadow-glowPrimary CTA focus/hoverComponent Tokens
The innermost tier. Each component owns a set of tokens that reference semantic tokens. Overriding a component token in a specific context never pollutes the rest of the system.
--btn-bgaction-primary--btn-bg-hoveraction-primary-hover--btn-bg-pressaction-primary-press--btn-texttext-inverse--btn-radiusradius-md--btn-height44px--btn-shadowshadow-glow--input-bgbg-sunken--input-borderborder-default--input-border-focusaction-primary--input-border-errorstatus-error--input-texttext-primary--input-placeholdertext-tertiary--input-radiusradius-md--input-height48px--card-bgbg-card--card-borderborder-subtle--card-radiusradius-lg--card-paddingspace-4--card-shadowshadow-sm--card-shadow-hovershadow-md--avatar-size-xs24px--avatar-size-sm32px--avatar-size-md44px--avatar-size-lg56px--avatar-size-xl72px--avatar-radiusradius-full--avatar-borderbg-elevated 2px--badge-bgaction-primary--badge-texttext-inverse--badge-radiusradius-pill--badge-size18px--badge-fonttext-xs / bold--nav-bgbg-elevated--nav-borderborder-subtle--nav-icon-activeaction-primary--nav-icon-defaulttext-tertiary--nav-height56px--nav-label-activeaction-primary--toast-bgbg-card--toast-borderborder-subtle--toast-shadowshadow-lg--toast-radiusradius-xl--toast-zz-toast (400)--toggle-bg-offborder-default--toggle-bg-onaction-primary--toggle-thumbwhite--toggle-durationduration-fast--toggle-easeease-in-outInputs
Inputs are the primary way users contribute. They should feel open and welcoming — soft background, generous padding, expressive focus state.
Selections
Toggles, checkboxes, radios, and chips. These controls let users make choices — they should be immediately legible and satisfy to interact with.
Avatars
Avatars represent people and communities. User avatars show photos or initials. Community avatars use the gradient palette to give each community a distinct, warm identity.
Each community picks from the gradient palette. The letter mark uses Figtree Bold.
Badges & Tags
Badges communicate counts and status. Tags label content. Both are compact, high-signal, and should never compete with primary content for attention.
Cards
Cards are the primary unit of information in social.plus. They surface communities, posts, members, and events. Soft slate background, generous radius, subtle lift on interaction.
Caught this light at 6am. Alarm at 5 was worth it. What's your favourite time to shoot?
List Items
The repeating unit of every feed, settings screen, and member list. Consistent height, generous touch target, clear visual hierarchy across leading / content / trailing zones.
Overlays
Modals, bottom sheets, and tooltips layer above the current screen. They use the z-index scale and always sit behind a darkened overlay backdrop.
Feedback
Toasts, banners, progress indicators, and skeleton loaders. The system's way of communicating status without disrupting the user's flow.
States
Every interactive element exists in multiple states. This matrix shows how each component responds to user actions, system conditions, and data states — so nothing is left undesigned.
Empty States
The moment before content exists. Empty states should feel warm and inviting — not clinical. Each one has a clear illustration area, a human headline, a supporting line, and one action.