Mindbloom Design System
Overview
Mindbloom's visual identity centers on warmth without sacrificing credibility—a delicate balance in the mental health space. The design language anchors itself in a signature sunny yellow ({colors.primary}) that functions as both brand voltage and emotional tone-setter, appearing prominently on the primary CTA ({component.button-primary}) and as the headline color within the dark photographic hero. Against this warmth, the system employs near-black ink ({colors.ink}) on white canvas ({colors.canvas}) for navigation and body content, creating high-contrast readability that feels clinical yet approachable.
The typography system is defined by its restraint: ABC Diatype carries every role from {typography.display-xl} headlines down to {typography.caption} legal text, never exceeding weight 500. This uniformity—where even the largest hero text sits at font-weight 400—signals trustworthiness and calm. The single typographic "moment" that defines the brand is the yellow-on-dark headline treatment in the hero band, where {colors.primary} text floats over intimate photography of hands holding medication, visually articulating the "more than medicine" value proposition.
Shape language leans heavily into the pill metaphor: {rounded.pill} (800px radius) buttons dominate conversion points, echoing the rounded form of medication and the softness of the therapeutic relationship. Input fields and cards use a gentler {rounded.DEFAULT} (10px) that feels modern without being playful. The spacing system orbits around a 20px base unit ({spacing.base}), creating rhythm through consistent internal padding and generous section breaks ({spacing.section-xxl} at 96px).
Sub-systems include the hero photography dialect (full-bleed imagery with overlaid yellow type), the navigation dialect (clean white bar with ghost links and singular yellow CTA), and an emerging form/input dialect built on thick black borders and substantial 18px internal padding.
Key Characteristics:
- Signature yellow (
{colors.primary}— #ffdc61) serves as both CTA background and headline accent color on dark surfaces - All type uses ABC Diatype at weights 400–500; bold (700) is reserved for extreme emphasis only
- Pill-shaped buttons (
{rounded.pill}— 800px) for all primary actions;{rounded.DEFAULT}(10px) for inputs and containers - Hero sections use
{colors.surface-dark}backgrounds with photographic imagery and{colors.primary}text - Navigation lives on
{colors.canvas}with{typography.nav-link}(18px/500) ghost links - Generous vertical rhythm:
{spacing.section-xxl}(96px) between major sections,{spacing.base}(20px) for component-internal spacing - Soft gray surfaces (
{colors.surface-soft}— #f1efed) provide subtle differentiation without visual noise - Border-heavy input style: 2px solid
{colors.border-input}with 18px padding creates tactile form presence
Colors
Brand & Accent
- Primary (
{colors.primary}— #ffdc61): The signature sunny yellow. Used as background for{component.button-primary}, text color for hero headlines ({component.hero-headline}), labels ({component.hero-label}), and video trigger elements ({component.video-trigger}). This is the single brand voltage point in the system. - Primary Hover (
{colors.primary-hover}— #ffd93d): Slightly deeper yellow for hover states on{component.button-primary-hover}. Provides subtle interaction feedback while maintaining warmth. - Primary Active (
{colors.primary-active}— #f5c842): Pressed/deeper state for{component.button-primary-active}. Dark enough to register tactile feedback. - Primary Disabled (
{colors.primary-disabled}— #fff3c4): Very pale yellow for disabled button states. Maintains brand association while signaling non-interactivity.
Surface
- Canvas (
{colors.canvas}— #ffffff): Pure white. Background for{component.top-nav},{component.card-elevated},{component.cookie-banner}, and all{component.section-white}areas. The default "nothing here" surface. - Surface Soft (
{colors.surface-soft}— #f1efed): Warm light gray with beige undertone. Used for{component.card}backgrounds,{component.section-surface}bands, and subtle differentiation zones. Feels organic rather than technical. - Surface Warm (
{colors.surface-warm}— #faf8f5): Extremely faint warm off-white. Potential use for nested containers within cards or alternate row striping. - Surface Dark (
{colors.surface-dark}— #1a1a1a): Near-black. Exclusive to{component.hero-band}and any full-bleed photographic overlay areas. Creates the contrast window for{colors.primary}text. - Surface Overlay (
{colors.surface-overlay}— rgba(0, 0, 0, 0.5)): Semi-transparent black. Used to darken photography sufficiently for text legibility in hero contexts.
Text
- Ink (
{colors.ink}— #000000): Pure black. Primary text color for navigation links ({component.nav-link}), body copy, headings on light backgrounds, and all{component.top-nav}elements. - Body (
{colors.body}— #000000): Identical to ink in this system. Used for paragraph text in{typography.body-md}and{typography.body-sm}roles. - Muted (
{colors.muted}— rgba(0, 0, 0, 0.5)): 50% opacity black. Secondary text, descriptions, cookie banner copy ({component.cookie-banner}). - Muted Strong (
{colors.muted-strong}— rgba(0, 0, 0, 0.7)): 70% opacity black. Emphasized secondary text, supporting copy that needs more presence than muted but less than body. - Muted Soft (
{colors.muted-soft}— rgba(0, 0, 0, 0.35)): 35% opacity black. Placeholder text, very secondary metadata. - On Primary (
{colors.on-primary}— #000000): Black text on yellow backgrounds. Used in{component.button-primary}and any element sitting on{colors.primary}. Contrast ratio satisfies AA against the yellow. - On Dark (
{colors.on-dark}— #ffffff): White text. Exclusively for{component.hero-subhead}and any copy overlaid on{colors.surface-dark}or photography. - Inverse (
{colors.inverse}— #ffffff): White. Used for icon buttons ({component.button-icon}) and submit buttons ({component.submit-button}) that appear on dark or colored backgrounds.
Hairlines & Borders
- Hairline (
{colors.hairline}— rgba(0, 0, 0, 0.1)): Very subtle divider lines. Section separators, card borders when minimal separation is needed. - Border Strong (
{colors.border-strong}— #000000): Solid black borders. Used sparingly for high-emphasis outlines or when a border must match text weight. - Border Input (
{colors.border-input}— #000000): 2px solid black border specifically for{component.text-input-border}and form fields. Creates strong visual affordance for interactive inputs. - Border Disabled (
{colors.border-disabled}— #cccccc): Medium gray. Disabled state border for inputs.
Semantic
- Error (
{colors.error}— #c13515): Warm red. Form validation errors, destructive action warnings. - Success (
{colors.success}— #006400): Dark green. Confirmation states, successful submission feedback. - Link (
{colors.link}— #000000): Black. Inline links within body copy—underlined or differentiated by context rather than color in this system. - Link Active (
{colors.link-active}— #333333): Dark gray. Visited or active link state.
Typography
Font Family
Mindbloom's type system is built almost entirely on ABC Diatype, a geometric-humanist sans-serif with excellent readability at both display and text sizes. The font ships in four weights (400 Regular, 500 Medium, 700 Bold, 400 Italic) and serves every role from 64px hero headlines to 13px uppercase labels. Two additional typefaces appear in the loaded font stack: Ivar Text (a serif, likely for long-form editorial content or testimonial pull-quotes not visible in this viewport) and Telegraf (a geometric sans, possibly for UI micro-copy or numeric data). The fallback chain is "ABC Diatype", sans-serif, ensuring system fonts degrade gracefully if web fonts fail.
Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| {typography.display-xl} | 64px | 400 | 1.1 | 0 | Hero headline (h2 equivalent); largest text on page, appears in {colors.primary} on dark backgrounds |
| {typography.display-lg} | 42px | 400 | 1.2 | 0 | Section headlines (h1/h3 equivalent); used in both {colors.primary} (on dark) and {colors.ink} (on light) |
| {typography.title-md} | 24px | 400 | 1.4 | 0 | Subsection headings (h4); card titles, feature names |
| {typography.body-md} | 18px | 400 | 1.4 | 0 | Primary body copy, paragraphs, hero subheadings, input text |
| {typography.body-sm} | 16px | 400 | 1.5 | 0 | Secondary body text, compact paragraphs |
| {typography.caption} | 14px | 400 | 1.4 | 0 | Legal text, timestamps, cookie banner copy |
| {typography.label-md} | 13px | 500 | 1.3 | 0.05em | Uppercase labels, category tags, "THE MINDBLOOM DIFFERENCE" style preheads |
| {typography.button} | 18px | 500 | 1.2 | 0 | Button text (primary, nav CTA, submit), call-to-action labels |
| {typography.nav-link} | 18px | 500 | 1.3 | 0 | Top navigation items (Program, Science, Reviews, Pricing, Learn) |
Principles
The typography system's defining characteristic is weight restraint. Even at 64px—the largest size in the system—the hero headline remains at font-weight 400. This is a deliberate choice that signals calm authority rather than aggressive marketing. Hierarchy is established through size differential (64px → 42px → 24px → 18px) and, critically, through color-context switching: the same 42px {typography.display-lg} size reads as a "headline" when rendered in {colors.primary} on a dark photo, but as a "section heading" when rendered in {colors.ink} on white.
Uppercase appears exactly once in the label role: {typography.label-md} uses text-transform: uppercase with slight letter-spacing expansion (0.05em) for the "THE MINDBLOOM DIFFERENCE" prehead above the hero. This is a signature moment—uppercase is otherwise absent from the system. Letter-spacing remains at normal (0) for all other roles, trusting the typeface's native spacing.
The 18px body size ({typography.body-md}) is notably larger than the web standard of 16px, reflecting Mindbloom's accessibility-forward approach and the need for comfortable reading in a health-context product. Button text matches this 18px size but bumps to weight 500 for subtle emphasis without resorting to bold.
Note on Font Substitutes
ABC Diatype is a commercial typeface from Dinamo Type Foundry. For open-source implementations, the closest Google Fonts equivalent is DM Sans (geometric humanist, similar x-height and openness) or Plus Jakarta Sans (slightly warmer, similar weight distribution). For the serif fallback (Ivar Text), use Lora or Source Serif Pro. For Telegraf's geometric UI role, Space Grotesk or Manrope provide similar character. Define these as CSS variables:
--font-primary: 'DM Sans', 'ABC Diatype', sans-serif;
--font-serif: 'Lora', 'Ivar Text', Georgia, serif;
--font-ui: 'Space Grotesk', 'Telegraf', sans-serif;
Layout
Spacing System
- Base unit: 20px ({spacing.base}) — the most frequently occurring spacing value in the extracted CSS (52 instances).
- Tokens:
{spacing.xxs}(2px) for micro-adjustments;{spacing.xs}(4px) for icon gaps;{spacing.sm}(8px) for tight component internals;{spacing.md}(16px) for standard padding;{spacing.base}(20px) for dominant internal spacing;{spacing.lg}(24px) for loose component padding;{spacing.xl}(32px) for element grouping;{spacing.section-sm}(40px) for small section breaks;{spacing.section-md}(48px) for medium breaks;{spacing.section-lg}(64px) for major vertical rhythm;{spacing.section-xl}(80px) for hero-level breathing room;{spacing.section-xxl}(96px) for maximum section separation. - Section padding (vertical):
{spacing.section-xxl}(96px) — used between major content bands in the main scroll. - Card internal padding:
{spacing.lg}(24px) per{component.card}specification, though some variants may use{spacing.base}(20px). - Gutters: Horizontal page margins appear to be
{spacing.md}(16px) to{spacing.lg}(24px) depending on viewport, with content maxing around 1200–1440px wide based on container widths.
Grid & Container
- Max content width: 1440px (detected from
mainandsectioncontainer widths). Content is centered within the viewport. - Density choice: Editorial-hero density—the above-fold area is dominated by a full-bleed photographic hero with left-aligned text column, suggesting a 2-column grid at desktop (text ~40% width, image ~60% width, or full-bleed image with overlaid text).
- Specific grid behaviors: The hero uses an overlapping layout where text sits atop the photograph (not side-by-side), implying absolute positioning or a negative-margin technique within a relative container. The nav uses a standard flexbox layout with logo left, nav center, utilities right.
- Hero column splits: Left-aligned text block (label + headline + potential subhead + CTA) positioned in the left 40-50% of the hero band, with the photographic subject (hands, medication) filling the remainder and extending edge-to-edge.
Whitespace Philosophy
The system practices generous, confident whitespace. Vertical section padding of 96px ({spacing.section-xxl}) between major content areas signals editorial quality and reduces cognitive load—appropriate for a mental health product where breathing room mirrors the therapeutic experience. Within components, 18–20px internal padding prevents cramped feeling without wasting space. The hero particularly embraces negative space: the headline has room to breathe over the darkened photograph, and the yellow text floats with clear margin from the frame edge.
Header Architecture
|--------------------------------------------------------------------------------|
| [Mindbloom Logo] Program Science Reviews Pricing Learn Login [Get Started] |
|--------------------------------------------------------------------------------|
^ ^ ^ ^ ^ ^ ^ ^
16-20px 12px h-pad each, 18px/500 type, 16-24px 9x18px pad
left margin transparent bg right pad pill btn
(primary)
Max content width: ~1200-1440px centered
Nav height: ~80px
Background: {colors.canvas}
Hero Section
|================================================================================|
| |
| THE MINDBLOOM DIFFERENCE [Photograph: Hands |
| holding medication, |
| More than medicine. A caring warm tones, shallow |
| community and comprehensive DOF, full-bleed] |
| support system that |
| changes lives. |
| |
| [▶ Watch our intro video] |
| |
|================================================================================|
^ ^ ^
label-md display-xl video-trigger
uppercase/13px 64px/400/{colors.primary} pill shape/{colors.primary}
{colors.primary} yellow on dark bg left-aligned below headline
Background: {colors.surface-dark} (near-black) or photographic
Padding: {spacing.section-xl} (80px) vertical, {spacing.md} horizontal
Text column: left-aligned, roughly 50-60% of width
Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| 0 (Flat) | No shadow, no border | {component.top-nav}, {component.hero-band} base, {component.section-white} |
| 1 (Hairline) | 1px {colors.hairline} border or very subtle shadow | Card separators, dividers between list items |
| 2 (Soft) | {extensions.shadows.sm} — 0 1px 3px rgba(0,0,0,0.08) | {component.card-elevated} on white, dropdown menus |
| 3 (Medium) | {extensions.shadows.md} — 0 4px 12px rgba(0,0,0,0.12) | Modal dialogs, sticky elements, cookie banner |
| 4 (Strong) | {extensions.shadows.lg} — 0 8px 24px rgba(0,0,0,0.15) | Hero image overlays, prominent floating elements |
| Focus Ring | {extensions.shadows.focus} — 0 0 0 3px rgba(255,220,97,0.4) | Focus state on {component.text-input-focus}, keyboard-navigable buttons |
The elevation philosophy is layered but restrained. Unlike SaaS products that rely on card stacks to create hierarchy, Mindbloom uses color-block depth—the hero achieves its prominence through the {colors.surface-dark} background and photographic richness, not through drop shadows. Shadows, when they appear, are neutral-toned (no blue or purple tints) and relatively tight, avoiding the "floating card" aesthetic. The one detected shadow (rgba(0, 0, 0, 0.2) 0px 0px 10px -2px) suggests a soft, close shadow for elevated cards or modals.
Decorative Depth
The primary decorative depth mechanism is photographic immersion in the hero band. Rather than using gradient washes or abstract shapes, Mindbloom places intimate, warmly-lit photography (hands, medication, human connection) at full bleed behind the headline. A subtle {colors.surface-overlay} (50% black) ensures text legibility while allowing the photograph's emotional texture to show through. This is not a "design-y" depth—it's narrative depth, where the image does semantic work alongside the words.
Shapes
Border Radius Scale
| Token | Value | Use |
|---|---|---|
| {rounded.sm} | 8px | Submit buttons ({component.submit-button}), small UI chrome |
| {rounded.DEFAULT} / {rounded.md} | 10px | Default radius. Text inputs ({component.text-input}), cards ({component.card}), most containers |
| {rounded.lg} | 12px | Larger cards, modal dialogs (inferred) |
| {rounded.xl} | 16px | Feature highlight cards, testimonial avatars (inferred) |
| {rounded.pill} | 800px | Signature shape. Primary CTA ({component.button-primary}), badges ({component.badge}), video trigger ({component.video-trigger}) |
| {rounded.full} | 9999px | Perfect circles for icon containers, play buttons |
The shape vocabulary is intentionally narrow: two functional radii (8px and 10px) for structural elements, one signature pill radius (800px) for all conversion-oriented actions. This binary—slightly rounded rectangles for content, perfect pills for actions—creates a clear visual grammar where users can identify interactive opportunities by geometry alone. The 10px default is slightly rounder than the industry-standard 8px, contributing to the system's warm, approachable feel.
Photography Geometry
Photography in the hero section is full-bleed, uncropped edge-to-edge, with no border radius applied—it bleeds to the viewport edges. The image appears to use a 3:2 or 16:9 aspect ratio at desktop, showing hands holding a blister pack of pills in warm, natural lighting with shallow depth of field. The photographic style is documentary-intimate: real skin texture, natural imperfections, warm color grading that complements {colors.primary}. No rounded corners, no frames, no overlays beyond the semi-transparent darkening layer for text legibility.
Components
No hover states documented. Hover behavior is unreliable to extract from a single screenshot. State variants live as separate entries in the
components:frontmatter (e.g.{component.button-primary-hover},{component.text-input-focus}); add hover styling at implementation time per your stack's conventions.
Buttons
{component.button-primary} — The signature conversion button. Bright yellow ({colors.primary}) background with black ({colors.on-primary}) text, perfect pill shape ({rounded.pill} — 800px radius), 18px/500 ABC Diatype type ({typography.button}). Padding is 9px horizontal, 18px vertical (asymmetric for optical centering). Appears in the top-right of {component.top-nav} as "Get started"—the single most important action on the page. No box-shadow; relies on color contrast for prominence. State variants: {component.button-primary-hover} (slightly deeper yellow), {component.button-primary-active} (pressed state).
{component.button-primary-hover} — Hover state for {component.button-primary}. Background shifts to {colors.primary-hover} (#ffd93d). All other properties (radius, text color, typography, padding) remain identical. Transition should use the system's 250ms ease-out timing.
{component.button-primary-active} — Active/pressed state. Background deepens further to {colors.primary-active} (#f5c842). This provides tactile feedback for touch and click interactions.
{component.button-nav-ghost} — Navigation menu items (Program, Science, Reviews, Pricing, Learn). Transparent background with {colors.ink} text, {typography.nav-link} (18px/500). Padding 12px horizontal, 8px bottom (note: asymmetric—more padding top than bottom for baseline alignment with the logo). These are effectively text links styled as buttons for consistent hit areas. No border, no radius (0px).
{component.button-text} — Transparent-background text button for secondary actions. Black text at {typography.button} size. Minimal padding (8px). Used for utility actions like "Login" (though Login may be plain link styled).
{component.button-icon} — Icon-only button with transparent background and white ({colors.inverse}) text/color for visibility on dark surfaces. Square 40px size ({size}). Likely used for close buttons, menu toggles, or play icons.
{component.submit-button} — Form submit control. Transparent background with white ({colors.inverse}) text/icon, smaller {rounded.sm} (8px) radius, tight 8px padding. Designed to sit inside or adjacent to {component.text-input} fields, often as an icon button (arrow, search glyph).
Cards & Containers
{component.card} — Standard content card. {colors.surface-soft} (#f1efed) background providing subtle differentiation from white canvas. Black text ({colors.ink}), {typography.body-md} for content. {rounded.DEFAULT} (10px) corner radius. {spacing.lg} (24px) internal padding. Used for feature summaries, pricing tiers, testimonial blocks—any bounded content unit that isn't the primary hero.
{component.card-elevated} — Elevated card variant. White ({colors.canvas}) background (same as page canvas, so it differentiates via shadow rather than color). Would carry {extensions.shadows.sm} or {extensions.shadows.md} to lift from the surface. Same 10px radius and 24px padding as {component.card}. Use for modals, dropdown panels, or tooltip-style content.
{component.cookie-banner} — Bottom-fixed consent banner. White ({colors.canvas}) background spanning full viewport width. Muted text ({colors.muted}) at {typography.caption} size (14px). No border radius (sharp corners, full-width). Minimal padding ({spacing.sm} vertical, {spacing.md} horizontal). Contains legal copy, links, and a close button ({component.cookie-banner-close}). Sticks to viewport bottom with z-index elevation.
{component.cookie-banner-close} — Close/dismiss button for the cookie banner. Transparent background, black ({colors.ink}) "X" icon or symbol. 32px square ({size}). Positioned at the right edge of {component.cookie-banner}.
{component.section-surface} — Full-width section band with {colors.surface-soft} background. Black text. {spacing.section-xxl} (96px) vertical padding creating major rhythmic break. Used to alternate visual texture as user scrolls—white band, gray band, white band.
{component.section-white} — Full-width section band with {colors.canvas} background. The default section surface. Same 96px vertical padding as surface variant.
{component.divider} — Horizontal rule. Transparent background with {colors.hairline} color (10% black). 1px height. Spans content width, not full viewport. Used between content groups within a section.
{component.badge} — Small label/tag. Yellow ({colors.primary}) background with black ({colors.on-primary}) text. {typography.label-md} (13px/500, uppercase, 0.05em letter-spacing). Pill shape ({rounded.pill}). Compact padding (6px horizontal, 16px vertical). Used for category labels like "THE MINDBLOOM DIFFERENCE" or program tags.
Inputs & Forms
{component.text-input} — Standard text/email input field. White ({colors.canvas}) background. Black ({colors.ink}) text at {typography.body-md} (18px). Key characteristic: 2px solid black border ({colors.border-input}) creating strong visual affordance—unusual in modern design but fitting Mindbloom's direct, trustworthy voice. {rounded.DEFAULT} (10px) radius. Generous 18px internal padding on all sides. No intrinsic height set; padding dictates ~54px total height.
{component.text-input-focus} — Focus state for text input. Retains white background and black text. Should gain {extensions.shadows.focus} (yellow-tinted ring: 0 0 0 3px rgba(255,220,97,0.4)) per accessible focus indication patterns. Border may remain black or thicken slightly. Transition: 250ms ease-out matching system timing.
{component.text-input-border} — Variant emphasizing the border treatment. Transparent background (allowing parent surface to show through), black border, 18px padding, 10px radius. Functionally identical to {component.token-input} but documented separately because the extracted CSS shows the border as a distinct stylistic choice worth preserving.
Navigation
{component.top-nav} — Global navigation header. White ({colors.canvas}) background, full viewport width, ~80px height. Contains: Mindbloom wordmark (left), nav links center/left (Program, Science, Reviews, Pricing, Learn as {component.button-nav-ghost}), utility links right (Login), and {component.button-primary} ("Get started") far right. Typography throughout is {typography.nav-link} (18px/500). No border-bottom (clean separation from hero via color change). Fixed or sticky positioning likely (standard pattern).
{component.nav-link} — Individual navigation menu item. Transparent background, black text, 18px/500 weight. Padding 12px horizontal, 8px bottom. No hover/active color documented (would become underline or opacity shift per implementation). These are the clickable labels in the top nav.
Hero & Signature Components
{component.hero-band} — Full-viewport-width hero section. {colors.surface-dark} (near-black #1a1a1a) background, or photographic image with dark overlay. Contains {component.hero-label}, {component.hero-headline}, optional {component.hero-subhead}, and {component.video-trigger}. 80px+ vertical padding. Text is left-aligned in a column occupying roughly the left half.
{component.hero-label} — Uppercase pre-headline label (e.g., "THE MINDBLOOM DIFFERENCE"). {colors.primary} (yellow) text. {typography.label-md} (13px/500, uppercase, expanded tracking). Transparent background. Positioned above the main headline with spacing around {spacing.sm} (8px) to {spacing.md} (16px).
{component.hero-headline} — Primary hero headline. {colors.primary} (yellow) text—this is the signature color-in-context moment. {typography.display-xl} (64px/400) for maximum impact. Line height 1.1 keeping lines tight. Multi-line (the example shows 4 lines). No max-width constraint visible; flows naturally within the text column.
{component.hero-subhead} — Supporting paragraph beneath the headline (visible in meta description though partially obscured in screenshot). White ({colors.on-dark}) text at {typography.body-md} (18px). Provides explanatory context for the headline's claim. Would sit between headline and CTA with {spacing.base} (20px) to {spacing.lg} (24px) gap.
{component.video-trigger} — "Watch our intro video" play button/link. Yellow ({colors.primary}) background (matching the headline color, creating visual echo). Black ({colors.on-primary}) text at {typography.body-md}. Perfect circle/pill ({rounded.full} or {rounded.pill}). Includes a play triangle icon (▶) before the text. Positioned below the hero text block. This is a key engagement driver—video content explains the Mindbloom process.
Do's and Don'ts
Do
- Do use
{colors.primary}(#ffdc61) for both CTA button backgrounds AND headline text on dark surfaces—this dual-role usage is the brand's signature color move. - Do keep all headline weights at 400 (regular) even at
{typography.display-xl}(64px)—bold is not part of the hierarchy strategy; size and color do the work. - Do apply
{rounded.pill}(800px) to every primary action button—this shape is synonymous with conversion in this system. - Do use 2px solid
{colors.border-input}(black) borders on text inputs—this heavy border is intentional, creating tactile form presence that feels trustworthy. - Do maintain
{spacing.section-xxl}(96px) vertical padding between major sections—the generous whitespace reflects the product's therapeutic values. - Do pair
{colors.primary}text with{colors.surface-dark}or photographic backgrounds—never place yellow text on white (insufficient contrast). - Do use
{typography.label-md}(13px/500 uppercase, 0.05em tracking) for category preheads—"THE MINDBLOOM DIFFERENCE" style labels are a recurring motif. - Do keep body text at 18px (
{typography.body-md}) rather than defaulting to 16px—the larger size improves readability for a health-focused audience. - Do allow hero photography to bleed full-viewport-edge with no border radius or frame—image immersion is a core design principle.
- Do use
{colors.surface-soft}(#f1efed) for card backgrounds when you need subtle differentiation without elevation/shadow complexity.
Don't
- Don't use font-weight 700 (bold) for any headline or body text in the main editorial flow—reserve it only for extreme emphasis moments; the system's voice is calm and weight 400 is sufficient.
- Don't apply
{rounded.pill}to non-action elements like cards, inputs, or containers—pill shape is exclusively for buttons and badges. - Don't substitute
{colors.link}(black) for{colors.primary}(yellow) on CTAs—links are understated (black, underlined or contextual), while conversion actions demand the yellow voltage. - Don't add gradients or colorful backdrops to the
{component.hero-band}—depth comes from photography and the dark surface, not from designerly gradient effects. - Don't reduce text input padding below 18px—the generous internal space makes fields feel welcoming and touch-friendly.
- Don't use shadows with colored tints (blue, purple)—all
{extensions.shadows.*}tokens are neutral black-based, maintaining the warm/neutral palette. - Don't uppercase text outside of
{typography.label-md}—the system uses sentence case for headlines, buttons, and navigation; uppercase is reserved for that specific label role. - Don't place
{colors.muted}(50% black) text on{colors.surface-dark}backgrounds—contrast will fail; use{colors.on-dark}(white) instead. - Don't create new border radius values beyond the defined scale (8px, 10px, 12px, 16px, 800px, 9999px)—the limited vocabulary is intentional.
- Don't let the
{component.cookie-banner}have rounded corners—it spans full-width with sharp edges, distinct from the rounded component language elsewhere.
Motion & Animation
Transition Tokens
--transition-color: color 0.25s ease-out, background-color 0.25s ease-out;
--transition-transform: transform 0.25s ease-out;
--transition-filter: filter 0.25s ease-out;
--transition-opacity: opacity 0.25s ease-out;
--transition-box-shadow: box-shadow 0.25s ease-out;
--transition-border: border-color 0.25s ease-out;
--transition-all: all 0.25s ease-out;
All extracted transitions use 250ms duration with ease-out timing. This creates a snappy-but-smooth feel—responsive without being sluggish. The ease-out curve means animations start fast and decelerate, which feels natural for UI state changes (buttons, inputs, toggles).
Keyframe Animations
- spin — Detected in the font/CSS stack; likely used for loading indicators or the play button icon rotation on hover.
- rotation — Similar rotational animation, possibly for decorative elements or the cookie banner close icon micro-interaction.
GSAP (GreenSock Animation Platform) is loaded in the page source (gsap.registerPlugin(ScrollTrigger)), indicating that scroll-driven animations are a core part of the experience. While the specific scroll triggers aren't visible in a single screenshot, the presence of GSAP + ScrollTrigger suggests:
- Parallax on the hero photograph (image moves slower than text as user scrolls)
- Fade-up reveals for content sections as they enter the viewport
- Staggered entrance for card grids or feature lists
- Pinching/sticky behavior for navigation or progress indicators
Interaction Patterns
- Button hover: Background color shift from
{colors.primary}→{colors.primary-hover}over 250ms ease-out. No scale transform detected. - Input focus: Border may intensify or shadow ring ({extensions.shadows.focus}) appears. Transition on
box-shadowandborder-color. - Video trigger hover: Likely a subtle scale (1.02–1.05) or opacity shift, given its prominence as an engagement element.
- Navigation link hover: Underline appearance (border-bottom growth) or opacity reduction to
{colors.muted}. No background fill. - Scroll-triggered reveals: GSAP-driven fade-up and opacity transitions for sections entering the viewport (standard ScrollTrigger pattern).
- Cookie banner slide: Fixed-position banner likely slides up from bottom on page load with transform transition.
If implementing from scratch without the GSAP dependency, use CSS @keyframes with animation-fill-mode: both and Intersection Observer for scroll triggers. Recommended timing: 300ms for scroll entrances (slightly longer than UI state changes to feel "designed"), 200ms for hover/focus states (snappy responsiveness).
Imagery Style
- Photographic, not illustrated: The hero features a real photograph—hands holding a blister pack of round tablets—with documentary intimacy, not flat illustration or 3D render.
- Subject matter: Human-centric, physical, tactile. Hands, medication, clothing textures (denim visible). Grounds the mental health service in bodily reality.
- Color temperature: Warm. Golden hour or indoor-warm lighting that harmonizes with
{colors.primary}(yellow) without matching it exactly. Skin tones read naturally. - Depth of field: Shallow. The hands and medication are in sharp focus; background falls into soft blur (bokeh). Directs attention and adds production value.
- Emotional tone: Intimate, quiet, hopeful. Not clinical-cold, not overly cheerful—balanced. The hands suggest care and self-administration.
- Composition: Close-up, slightly angled. Fills the frame. No negative space in the image itself (the design system provides the whitespace via layout).
- Treatment: Full-bleed, edge-to-edge, no border, no frame, no corner rounding. Darkened with 50% black overlay for text legibility.
- Role: The image is semantic, not decorative—it depicts the actual patient experience (taking medication) that Mindbloom supports.
- Future imagery expectations: Likely continues with human subjects, warm lighting, shallow DOF, intimate framing. May include therapy environments, faces (respectfully), nature/metaphor imagery for transformation concepts.
Icon System
- Library: Custom SVG icons, plus Webflow's embedded
webflow-iconsfont (loaded via@font-facedata URI in the extracted CSS). - Specific icons observed:
- Play/triangle (▶) — in
{component.video-trigger} - Close/X — inferred for
{component.cookie-banner-close} - Mindbloom wordmark (text-as-logo with decorative dot element)
- Possible arrow/right-chevron for submit button
- Play/triangle (▶) — in
- Treatment: Icons appear to use
currentColorinheriting from parent text color. In the video trigger, the play icon would be{colors.on-primary}(black) on the yellow background. In the cookie close, it would be{colors.ink}(black) on white. - Size alignment: The play icon in
{component.video-trigger}appears sized to match{typography.body-md}(18px) or slightly larger (~20–24px) for visual balance beside 18px text. Icon buttons ({component.button-icon},{component.submit-button}) contain icons sized to their square container (40px and 32px respectively, so icons likely 20px and 16px). - Stroke vs fill: The play triangle is a filled shape. The close X is likely stroke-based. Mixed usage depending on icon geometry.
Recommended Frontend Stack
- Framework: Next.js 14+ (App Router) or Remix — SSR-friendly for health-content SEO
- Styling: Tailwind CSS v3.4+ with custom theme extension (or CSS Modules if preferring explicit scoping)
- Fonts: Self-hosted ABC Diatype (WOFF2 from CDN) with CSS @font-face declarations; fallback to DM Sans via Google Fonts
- Animation: Framer Motion (React) or GSAP + ScrollTrigger (framework-agnostic, matches existing site)
- Icons: Lucide React (closest visual match to the clean, geometric icon style) or custom SVG components
- Component lib: Radix UI primitives (for accessible dropdowns, dialogs, cookies) + custom styled components
- Deployment: Vercel or Netlify (CDN-edge for font assets, image optimization)
Font setup note: ABC Diatype is proprietary. For development without licensing, use DM Sans as the primary substitute (geometric humanist, similar proportions) and load via:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,400;0,9..40,500;0,9..40,700;1,9..40,400&display=swap" rel="stylesheet">
CSS variable mapping: --font-primary: 'DM Sans', 'ABC Diatype', sans-serif;
Responsive Behavior
Breakpoints
| Name | Width | Key Changes | |---|---|---| | Mobile | < 640px | Single column everything; nav collapses to hamburger; hero text stacks above/below image or image hides; CTA becomes full-width | | Tablet | 640px – 991px | Two-column possible for simple grids; nav may show abbreviated items; hero text narrows to ~70% width | | Desktop | 992px – 1439px | Full nav visible (current screenshot state); hero 2-column layout (text + image); max content width active | | Wide | ≥ 1440px | Container maxes at 1440px; extra horizontal padding increases; typography may bump slightly |
Note: 992px breakpoint explicitly referenced in extracted CSS media query for nav styling.
Touch Targets
{component.button-primary}: ~160px × 38px (9px+18px+7px vertical, ~80px+ horizontal) — exceeds 44×44px minimum comfortably in both dimensions.{component.text-input}: Height ~54px (18px×2 padding + 18px font + 2px×2 border) — exceeds 44px minimum vertically. Width should be minimum 200px on mobile.{component.nav-link}: Hit area approximately 44px+ height (12px+8px padding + 18px font) — meets WCAG AAA.{component.video-trigger}: Pill shape, likely 48–56px height — well above 44px minimum.{component.cookie-banner-close}: 32px × 32px — below 44px AAA minimum. Recommend increasing to 40–44px for mobile touch compliance.
Collapsing Strategy
- Navigation: Below 992px, the horizontal nav links (Program, Science, Reviews, Pricing, Learn) collapse into a hamburger menu or mega-menu dropdown. The
{component.button-primary}("Get started") remains visible or moves into the mobile menu. Logo stays left-aligned. - Hero layout: On mobile, the hero transitions from "text overlaid on full-bleed photo" to either: (a) stacked layout with photo on top, text below on white/background, or (b) photo hidden/replaced with solid
{colors.surface-dark}and text still in{colors.primary}. The{typography.display-xl}(64px) likely scales down to 36–42px via fluid typography or breakpoint-specific override. - Grid columns: Any multi-card layouts (pricing, features, testimonials) collapse from 2–3 columns to single column on mobile, with cards stacking vertically and
{spacing.lg}(24px) gaps between them. - Section padding:
{spacing.section-xxl}(96px) compresses to{spacing.section-lg}(64px) or{spacing.section-md}(48px) on mobile to avoid excessive scrolling. - Cookie banner: Remains full-width but text may wrap to two lines; close button should increase touch target size.
Image Behavior
- Hero photograph: On desktop, full-bleed edge-to-edge with text overlaid. On mobile, likely switches to contained (max-width, rounded corners
{rounded.lg}) above or below the headline text, OR remains full-bleed with reduced opacity/darker overlay to ensure{colors.primary}text remains legible at smaller size. - Aspect ratio: Hero image likely maintains ~16:9 or 3:2 on desktop; may crop to 4:3 or 1:1 on mobile to preserve subject (hands/medication) visibility.
- Compression: Consider serving WebP/AVIF with lower quality settings for the darkened hero (compression artifacts hidden by overlay).
- Avatars/testimonial photos (if present below fold): Circle clip (
{rounded.full}) at 48–64px on desktop, 40px on mobile.
Iteration Guide
-
Start with the token system. Before writing any component markup, define every value in the YAML frontmatter as CSS custom properties (e.g.,
--color-primary: #ffdc61; --radius-pill: 800px; --space-section: 96px;). Build a "design tokens" CSS file that imports first. Every component references tokens, never hard-coded values. -
Implement the hero first. The hero band (
{component.hero-band}) contains the highest design density—dark surface, yellow typography, photographic depth, video CTA, label prehead. Getting this right validates your color-on-dark, typography scale, and spacing rhythm in one component. Use{colors.surface-dark}background, overlay a<img>withopacity: 0.5–0.6or a pseudo-element with{colors.surface-overlay}, then position text with{typography.display-xl}in{colors.primary}. -
Build the navigation as a flexbox exercise.
{component.top-nav}requires: logo left, nav-links center (or left-of-center), utilities right, CTA far-right. Use{typography.nav-link}(18px/500) for all text. Ensure{component.button-primary}gets its{rounded.pill}(800px) and{colors.primary}background. Test at 992px breakpoint where CSS shows nav behavior change. -
Form inputs need the "heavy border" treatment. When building
{component.text-input}, applyborder: 2px solid {colors.border-input}(black) andpadding: 18px. This is unusual—most systems use 1px gray borders—but it's intentional here. Add:focusstate with{extensions.shadows.focus}(yellow ring) for accessibility. -
Reserve
{rounded.pill}strictly for actions. As you build buttons, badges, and the video trigger, consistently applyborder-radius: 800px(or9999px). Applyborder-radius: 10px({rounded.DEFAULT}) to everything else (cards, inputs, modals). This binary shape language is a core identifier of the system. -
Use 250ms ease-out for all transitions. Every hover, focus, and state change should animate over 250ms with
ease-out(orcubic-bezier(0, 0, 0.2, 1)which approximates it). This timing was extracted from six distinct transition declarations in the source CSS—it's not arbitrary. -
Implement scroll reveals with GSAP or Framer Motion. The page loads GSAP with ScrollTrigger. If you can't use GSAP, replicate with Intersection Observer + CSS animations: elements start at
opacity: 0; transform: translateY(20px)and animate toopacity: 1; transform: translateY(0)over 300ms when.is-visibleclass is added. Stagger child elements by 100ms. -
Test contrast ratios for the yellow-on-dark combination.
{colors.primary}(#ffdc61) on{colors.surface-dark}(#1a1a1a) must meet WCAG AA (4.5:1 for body text, 3:1 for large text). The 64px headline passes at large-text threshold; verify 18px body text on dark if used there. -
Map ABC Diatype to DM Sans for prototyping. Define
--font-family: 'DM Sans', 'ABC Diatype', sans-serif;. DM Sans has similar geometric proportions, x-height, and weight range (400/500/700). It won't be pixel-identical but captures the spirit for development before licensing. -
Run the linter. After completing implementation, run
npx @google/design.md lint DESIGN.mdto catch broken token references, orphaned components missing prose entries, and contrast warnings. Fix anybroken-refororphaned-tokenserrors before shipping.
Final font setup for rapid prototyping:
:root {
--font-primary: 'DM Sans', 'ABC Diatype', -apple-system, BlinkMacSystemFont, sans-serif;
--font-serif: 'Lora', 'Ivar Text', Georgia, serif;
--font-ui: 'Space Grotesk', 'Telegraf', sans-serif;
}
/* Load DM Sans from Google Fonts in your HTML <head> */
/* Replace with self-hosted ABC Diatype WOFF2 files for production */
Known Gaps
- Hover states: Per the no-hover policy, specific hover styles for
{component.button-nav-ghost},{component.video-trigger}, and{component.nav-link}are not documented. Implementation should add opacity shifts, underline growth, or subtle background fills per platform conventions. - Loading/skeleton states: No loading skeletons, spinners (beyond the detected
spinkeyframe name), or pending states were extractable from a static screenshot. Design these using{colors.surface-soft}backgrounds with pulse animations at the extracted 250ms timing. - Form validation states: Only default and focus states for
{component.text-input}are documented. Error state (red border{colors.error}, error message text), success state (green check), and disabled state (gray border{colors.border-disabled}, muted text) require design decisions. - Authenticated/dashboard surfaces: The screenshot shows the marketing landing page only. Patient dashboard, clinician portal, scheduling interfaces, or post-session reflection tools are entirely unknown and may introduce new surface colors, data table components, or status indicators.
- Mobile navigation pattern: While 992px breakpoint suggests a collapsed nav, the exact mobile menu design (slide-down, fullscreen overlay, bottom sheet) is not visible. Common pattern for this design language would be a fullscreen overlay with
{colors.canvas}background and large 24–32px nav links. - Pricing tier card variant: If a pricing section exists (implied by "Pricing" in nav), the featured/popular tier card likely uses
{colors.primary}accent border, elevated shadow, or "Most Popular" badge—none of which are documented here. - Testimonial/quote component: Mental health sites typically feature patient stories. Quote mark treatment, avatar sizing, attribution typography, and card layout for testimonials are not visible in the current viewport.
- Exact hero photograph specifications: The hero image's aspect ratio, focal point coordinates, and responsive art-direction sources (different crops for mobile vs. desktop) are inferable but not precisely extractable from CSS alone.
- CSS variable naming mismatches: The source uses Webflow-generated class names (e.g.,
mega-nav_toggle,button is-nav w-button) that don't semantically map to the component tokens. Implementers must translate these class-name patterns to semantic component names. - Dark mode: The entire system is documented for light mode (
{extensions.mode}: light). A hypothetical dark mode would require inverting canvas/ink, adjusting{colors.primary}contrast (possibly brightening to #ffe066), and re-evaluating photographic overlay opacities. No dark mode evidence exists in the current data.