Let's Vibe — Brand & Design System
System name: Living Sanctuary Version: 1.0 Audience: Designers and engineers building Let's Vibe surfaces — web, mobile, native, email.
Let's Vibe is the first AI-native wellness system: a unified home for 150+ wellness modalities, the practitioners who lead them, and the gatherings that bring them to life. The brand should feel like the moment you exhale — calm, grounded, premium, and quietly alive. Editorial, botanical, modern. Never clinical, never loud, never busy.
This document is the human-readable companion to the code in /tokens and /css. When the two ever disagree, the token files win — they are the source of truth.
1. Voice & tone
We speak the way a trusted guide speaks: warm, direct, unhurried. Plain verbs. Sentence case. No filler, no hype, no jargon.
- Grounded, not clinical. "Take a breath. Let's check in with how you're really doing." — not "Complete your daily wellness assessment."
- Invitational, not instructive. Buttons name what happens: Declare vibration, Reserve a place, Book a session.
- Consistent vocabulary. A member is a Seeker. A check-in is a vibration. The assistant is Let's AI. An action keeps its name through the whole flow — Publish produces Published.
- Honest about being AI. Let's AI offers wellness guidance, not medical or mental-health treatment. It never diagnoses, and it points people to professionals in a crisis.
Errors explain what happened and how to fix it, in the interface's voice — they don't apologize and they're never vague. Empty states are an invitation to act, not a shrug.
2. Logotype & the orb
Wordmark: "Let's Vibe", set in Fraunces. Always written Let's Vibe (curly apostrophe), never "vibe" alone in product chrome.
The lockup rule: the orb (logo) and the wordmark (type) are one lockup and are never separated. They sit side by side in a single element, vertically centred to each other, with nothing between them: no navigation, buttons, text, dividers, images or extra space beyond the lockup gap. Don't place them in different corners, columns or sections. When a layout resizes or compacts, the pair scales and moves together. Navigation and actions go to the sides of the lockup, never inside it.
The orb is the signature — the one element the brand is remembered by. It's a soft sphere lit from the upper-left, graduating citrine → sage → pine, that breathes on a slow 7-second cycle. It represents a living, present companion.
Rules for the orb:
- Use it once per view, large, as an anchor: a hero, a loading moment, the Let's AI avatar.
- Never repeat it decoratively or shrink it into a bullet.
- It must respect
prefers-reduced-motion— when reduced motion is requested, it holds still. - Gradient is defined once as
--grad-orb; don't hand-tune per placement.
3. Color
A restrained, mostly-green palette on soft off-white, with a single warm accent used sparingly. Greens carry the brand; citrine is the spotlight; everything else is air and ink.
Surfaces
| Token | Hex | Use |
|---|---|---|
--mist |
#EDF0E8 |
App background — the air around everything |
--paper |
#F6F7F2 |
Cards, panels, raised surfaces |
--sand |
#D9D3C4 |
Warm secondary surface |
--line |
#D7DBCF |
Hairline borders and dividers |
Ink
| Token | Hex | Use |
|---|---|---|
--ink |
#1B271E |
Primary text & headlines |
--ink-soft |
#46584A |
Secondary / supporting text |
Brand greens
| Token | Hex | Use |
|---|---|---|
--sage |
#9BA88D |
Brand core — logo, fills, avatars |
--sage-deep |
#7D8C6E |
Eyebrows, icons, links |
--pine |
#2E4034 |
Primary action |
--pine-2 |
#223028 |
Deep / pressed states |
Warm accent — one per screen
| Token | Hex | Use |
|---|---|---|
--citrine |
#C7A24A |
Spotlight: a single highlighted action or moment |
--citrine-soft |
#E4C97E |
Gradient partner, subtle highlights |
The citrine rule: at most one citrine spotlight per screen. If two things are gold, neither is special. Primary actions use the CTA color; citrine is reserved for the one moment you want to glow (e.g. Let's AI).
CTA color — reserved
| Token | Hex | Use |
|---|---|---|
--cta / --grad-cta |
#2E4034 base, #4A6354 highlight, #223028 depth |
Every actionable link and button, and nothing else |
--cta-text |
#2E4034 |
Inline text links on light surfaces |
--cta-on-dark / --grad-cta-on-dark |
#E4C97E, #F1DC9C, #C7A24A |
The same job over dark surfaces (ink text on top: --on-cta-on-dark) |
The gradient is radial, lit from the top-left: radial-gradient(circle at 18% 12%, hi 0%, base 48%, lo 100%).
CTA states: every CTA defines all of these, each as a CSS transition: rest, hover (brightness(1.12)), active/pressed (brightness(.84) and translateY(1px) scale(.97), also held while the control's menu is open or it is aria-pressed), focus-visible (the focus ring) and disabled (50% opacity, no pointer, no press). The active state must be clearly different from hover.
CTA label shadow: every CTA label carries a soft two-layer text shadow so it stays cleanly legible across the whole gradient: --cta-shadow (dark, for light text on the green) and --cta-shadow-on-dark (light glow, for dark text on the warm pair). Apply it to the label text of buttons and button-style links, not to inline text links.
The CTA rule: the CTA color means "you can click this", and only that. It is reserved for links and buttons (including version links and inline links). It must never be used for content or design: not for headings, body text, labels, eyebrows, numbers or step markers, icons, dividers, tags, illustrations, card or section backgrounds, or charts. Content and decoration use ink, sage, sand, paper or the category accents instead. If a non-actionable element and a CTA could share a color, change the non-actionable one. Numbered identifiers (steps, list numbers, counters) are content: ring them in
--sage-deepwith--inktext, never fill them with the CTA gradient. Where CTAs appear, avoid placing them directly on a surface of the same hue (for example a pine button on a pine panel); give them a contrasting light or dark surface.
On-dark text
Over pine or photographs, use --on-dark #EFF2E9 and --on-dark-soft #C9D4BE.
Category accents
Modality families and data visualizations use a fixed accent set — consistent across the product so a color always means the same family.
| Family | Token | Hex |
|---|---|---|
| Mind | --cat-mind |
#5F7E80 |
| Body | --cat-body |
#7D8C6E |
| Energy | --cat-energy |
#C7A24A |
| Spirit | --cat-spirit |
#A07C9A |
| Heart | --cat-heart |
#C98B9E |
Contrast
Body text uses --ink on --mist/--paper (passes WCAG AA). --ink-soft is for secondary text only — don't use it for anything below 14px on busy backgrounds. White text requires a --pine or scrimmed-photo background, never a light surface.
Light and dark
Both modes are part of the system, and every new surface ships with both. Follow prefers-color-scheme and map roles to tokens, never inverting automatically:
| Role | Light | Dark |
|---|---|---|
| Page / card / hairline | --mist / --paper / --line |
--ink / --pine-2 / --pine |
| Text / secondary | --ink / --ink-soft |
--on-dark / --on-dark-soft |
| Eyebrows | darkened --sage-deep |
--sage |
| CTA | --grad-cta, --on-cta |
--grad-cta-on-dark, --on-cta-on-dark |
| Inline links | --cta-text |
--cta-text-on-dark |
Contrast, the CTA rule, the one-citrine-spotlight rule and the orb rules apply equally in both modes.
4. Typography
Two families, deliberately paired:
- Fraunces (display / serif) — warm, optical, a little editorial. Headlines, big numbers, the wordmark. Weights 400–600. Used with restraint.
- Hanken Grotesk (body) — clean, humanist, highly legible. Everything else. Weights 400–700.
Scale
| Role | Size | Family | Notes |
|---|---|---|---|
| H1 | 46px (fluid --h1) |
Fraunces 600 | Page heroes; letter-spacing:-0.01em |
| H2 | 34px (fluid --h2) |
Fraunces 600 | Section titles |
| H3 | 24px | Fraunces 600 | Card / block titles |
| H4 | 21px | Fraunces 600 | Sub-blocks |
| Lead | 18px | Hanken 400 | Intros, hero subtitles |
| Body | 16px | Hanken 400 | Default, line-height:1.6 |
| Small | 14px | Hanken 500 | Dense UI, captions |
| Caption | 13px | Hanken 500 | Metadata |
| Eyebrow | 11px | Hanken 700 | letter-spacing:.28em, uppercase, --sage-deep |
The eyebrow
The eyebrow is the core structural device: a tiny, wide-tracked, uppercase label that sits above a heading to name a section ("GATHER IN PERSON" over "Upcoming events"). It encodes hierarchy — it is never a full sentence and never body copy.
5. Components
Defined in css/components.css. Building blocks, not a full kit — compose them.
Buttons are pill-shaped (--r-pill).
- Primary (
.lv-btn--primary): the CTA gradient (--grad-cta), on-cta text. The default action, and the only thing that wears the CTA color. - Spotlight (
.lv-btn--spotlight): citrine gradient, ink text. One per screen. - Ghost (
.lv-btn--ghost): transparent with a hairline border. Secondary actions.
Chips (.lv-chip) are quiet pills for filters and tags. Category tags (.lv-tag--mind … --heart) carry a modality family in its accent color.
Cards (.lv-card) are --paper on a hairline border with radius --r-lg and the soft --shadow-sm. Shadows are low-contrast and large-radius — presence without heaviness.
Radius climbs with surface size: controls --r-xs/sm, cards --r-lg, hero panels --r-xl, anything fully round is --r-pill.
6. Imagery
Modalities never use photos. There are 150+ of them and no way to source distinct, on-brand imagery at scale — so modality cards are typographic, carrying their category accent instead. This is a deliberate identity choice, not a placeholder.
Practitioners and events use photos — real faces and places build trust.
Always layer photos over a brand gradient. Use the .lv-media helper: the gradient is the base layer and the image sits on top, so a missing, slow, or broken image still looks intentional rather than empty. Text over imagery always sits on a .lv-scrim (a bottom-up dark gradient) for legibility.
Treat cultural variants of a practice as "the same medicine carried by cultures across the world" — surface aliases as lineage, not as mere alternate names.
7. Motion
Calm and purposeful. Motion confirms and orients; it never performs.
- Durations:
--dur-fast150ms (hovers),--dur-base200ms (state changes),--dur-slow400ms (panels). - Easing:
--easecubic-bezier(.2,.7,.3,1)— a gentle settle. - The breath: the orb's 7s
--breathecycle is the one ambient animation. Everything else is reactive. - Always use CSS transitions for state changes (hover, focus, open/close, compact/expand, theme). JavaScript only flips a class or attribute; CSS animates it. Never tween with JS or let a panel pop in instantly.
- Everything animates, nothing snaps. Every property that changes between states (size, height, padding, position, opacity, color, shadow, background) transitions, and related changes move together on one shared progress value so a header's height can't jump while its logo scales. Use
--easefor fades and hovers,--ease-inoutfor size and layout. - Always honor
prefers-reduced-motion: reduce—base.cssalready neutralizes animation when it's set.
8. Accessibility (the quality floor)
Non-negotiable on every surface:
- Visible keyboard focus everywhere (
--focusring; wired inbase.css). - Body text meets WCAG AA contrast; never rely on color alone to convey meaning (pair category color with a label).
- Responsive down to small mobile; touch targets ≥ 44px.
- Reduced motion respected.
- Form fields have real labels; errors are specific and actionable.
9. Quick do / don't
Do
- Lead with the orb or a strong Fraunces headline.
- Keep one citrine spotlight per screen; everything else quiet.
- Use the CTA color (
--grad-cta) for links and buttons only. - Use the eyebrow to label sections.
- Layer every photo over a gradient fallback.
Don't
- Use the CTA color for content or decoration (numbers, labels, headings, icons, backgrounds), or let a non-actionable element look like a button.
- Put photos on modality cards.
- Use citrine for more than one thing per screen.
- Write eyebrows as sentences.
- Add ambient motion beyond the breath.
- Use
--ink-softfor primary reading text.