Pairty™ Design Tokens

v1.1.0

Pairty™ Design System

Human Venture Capital Platform

The single source of truth for brand colors, typography, spacing, and component styles. Now includes comprehensive landing page patterns and accessibility guidelines.

Colors

The Pairty color palette is built around three brand colors with supporting background, text, and semantic colors.

Brand Colors

Pairty Blue

#0049E7

--color-brand-primary

Buttons, links, CTAs, primary actions

Bright Blue

#249AE3

--color-brand-secondary

Info states, secondary highlights

Pairty Teal

#47EBE0

--color-brand-accent

Success accents, gradient endpoints

Background Colors

Off White

#EAEAEC

--color-background-light

Light mode backgrounds

Charcoal

#262626

--color-background-dark

Dark mode backgrounds

Dark Alt

#111122

--color-background-dark-alt

Mobile app dark (legacy)

Deep Dark

#0a0a0a

--color-background-deep

Website deep dark

Text Colors

Primary Light

#262626

--color-text-primary-light

Body text on light backgrounds

Primary Dark

#EAEAEC

--color-text-primary-dark

Body text on dark backgrounds

Muted Light

#6b7280

--color-text-muted-light

Secondary text on light

Muted Dark

#9ca3af

--color-text-muted-dark

Secondary text on dark

Semantic Colors

Success

#22c55e

--color-success

Success states, confirmations

Warning

#fbbf24

--color-warning

Warnings, caution states

Error

#ef4444

--color-error

Errors, destructive actions

Info

#249AE3

--color-info

Informational messages

Usage

CSS Variables

.button {
  background: var(--color-brand-primary);
  color: var(--color-text-primary-dark);
}

Tailwind Classes

<button className="bg-pairty-blue text-white">
  Click me
</button>

Typography

Typographic scale and font families for consistent text styling across platforms.

Font Families

Display

Neue Haas Grotesk Display, Inter, system-ui, sans-serif

Headlines, hero text

⚠️ Commercial font - using Inter as fallback until licensed

Aa Bb Cc 123

Body

Inter, system-ui, sans-serif

Body text, UI elements

Aa Bb Cc 123

Body Mobile

Nunito Sans, system-ui, sans-serif

Mobile app body text (legacy)

⚠️ Consider standardizing to Inter

Aa Bb Cc 123

Mono

JetBrains Mono, monospace

Code, data, numbers

Aa Bb Cc 123

Font Sizes

TokenWebMobileLine HeightPreview
xs0.75rem12px1remThe quick brown fox
sm0.875rem14px1.25remThe quick brown fox
base1rem16px1.5remThe quick brown fox
lg1.125rem18px1.75remThe quick brown fox
xl1.25rem20px1.75remThe quick brown fox
2xl1.5rem24px2remThe quick brown fox
3xl1.875rem30px2.25remThe quick brown fox
4xl2.25rem36px2.5remThe quick brown fox
5xl3rem48px1The quick brown fox

Font Weights

Aa

light

300

Aa

normal

400

Aa

medium

500

Aa

semibold

600

Aa

bold

700

Aa

extrabold

800

Aa

black

900

Type Scale

Display Heading

H1 Heading

H2 Heading

H3 Heading

H4 Heading

Large body text for emphasis

Regular body text for paragraphs and UI.

Small text for captions and secondary info.

Extra small text for labels and metadata.

Usage

CSS Variables

.heading {
  font-family: var(--font-display);
  font-size: var(--font-size-4xl);
  font-weight: 700;
}

Tailwind Classes

<h1 className="font-display text-4xl font-bold">
  Heading
</h1>
<p className="font-body text-base">
  Body text
</p>

Spacing & Layout

Consistent spacing scale for margins, padding, gaps, and layout measurements.

Spacing Scale

0

0px

px

1px

0.5

2px

1

4px

1.5

6px

2

8px

2.5

10px

3

12px

3.5

14px

4

16px

5

20px

6

24px

7

28px

TokenValuePixelsPreview
000px
px1px1px
0.50.125rem2px
10.25rem4px
1.50.375rem6px
20.5rem8px
2.50.625rem10px
30.75rem12px
3.50.875rem14px
41rem16px
51.25rem20px
61.5rem24px
71.75rem28px
82rem32px
92.25rem36px
102.5rem40px
112.75rem44px
123rem48px
143.5rem56px
164rem64px
205rem80px
246rem96px

Border Radius

none

0

sm

0.25rem

md

0.375rem

lg

0.5rem

xl

0.75rem

2xl

1rem

3xl

1.25rem

Mobile nav radius

4xl

1.875rem

Mobile content radius

full

9999px

Breakpoints

xsExtra small devices
480px
smSmall devices
640px
mdTablets
768px
lgLaptops
1024px
xlDesktops
1280px
2xlLarge screens
1536px

Usage

CSS Variables

.card {
  padding: var(--spacing-lg);
  border-radius: var(--radius-xl);
  margin-bottom: var(--spacing-md);
}

Tailwind Classes

<div className="p-6 rounded-xl mb-4">
  <h2 className="mb-2">Title</h2>
  <p className="mt-4">Content</p>
</div>

Gradients

Brand gradients for creating depth and visual interest. Updated with landing page patterns.

Text Gradients

Text Heading

--gradient-text-heading

Section headlines (from Figma)

Text Hero

--gradient-text-hero

Hero headline text

Network Worth

--gradient-text-network-worth

Network value display

Background Gradients

Section Background

--gradient-background-section

Landing page sections

Section Alt

--gradient-background-section-alt

Alternate section backgrounds

Card Hover

--gradient-background-card-hover

Feature card hover state

CTA Gradients

--gradient-cta-animated

--gradient-cta-animated-reverse

Overlay Gradients

Hero Overlay
Hero Side Overlay

Border Gradients

Member Card Border

--gradient-border-member-card

Member card gradient border

Footer Top Border

--gradient-border-footer-top

Footer top glow border

Usage

CSS

.section {
  background: linear-gradient(to bottom, #0a1628, #0f1a2e);
}

.gradient-text {
  background: linear-gradient(278deg, #47EBE0 28.45%, #0049E7 100.49%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
}

.gradient-border {
  background: 
    linear-gradient(#0c1829, #0c1829) padding-box,
    linear-gradient(to bottom, #1e3a5f, #0a1628) border-box;
  border: 1px solid transparent;
}

Tailwind Classes

{/* Background */}
<div className="bg-gradient-section">
  Section content
</div>

{/* Text */}
<h1 className="bg-gradient-text-heading 
  bg-clip-text text-transparent">
  Gradient Heading
</h1>

{/* CTA with swap */}
<button className="bg-gradient-cta 
  hover:bg-gradient-cta-reverse">
  Download
</button>

Animations

Keyframe animations, transitions, and Framer Motion easing for consistent motion.

Tailwind Animation Examples

Fade In

animate-fade-in

Element entrance

500msease-out

Slide Up

animate-slide-up

Content reveal on scroll

500msease-out

Scale In

animate-scale-in

Modal entrance

300msease-out

Float

animate-float

Hero floating elements

6sease-in-out

Float Delayed

animate-float-delayed

Secondary floating elements

6s, 2s delayease-in-out

Shimmer

animate-shimmer

CTA button shimmer effect

2slinear

Special Effects

Banner with shimmer

Banner Shimmer

Top banner announcement effect

1,247 online

Live Ping Indicator

Real-time activity indicator

Pulse Glow

Attention-grabbing glow effect

Gradient Shift

Animated gradient backgrounds

Transitions

Fast

150ms ease

Hover states, small interactions

Base

300ms ease

Default transitions

Slow

500ms ease

Page transitions, feature card hovers

Framer Motion Easing

smooth

[0.25, 0.46, 0.45, 0.94]

Page transitions, stagger animations (Framer Motion)

spring

stiffness: 300, damping: 30

Modal entrance, banner appearance (Framer Motion)

tween

type: "tween", duration: 0.4

Standard page transitions (Framer Motion)

Tailwind Keyframe Definitions

// tailwind.config.ts
module.exports = {
  theme: {
    extend: {
      animation: {
        'gradient-shift': 'gradient-shift 3s ease infinite',
        'banner-shimmer': 'banner-shimmer 3s linear infinite',
        'shimmer': 'shimmer 2s linear infinite',
        'ping-slow': 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',
        'float': 'float 6s ease-in-out infinite',
        'float-delayed': 'float 6s ease-in-out 2s infinite',
        'pulse-glow': 'pulse-glow 2s ease-in-out infinite',
        'fade-in': 'fade-in 0.5s ease-out',
        'slide-up': 'slide-up 0.5s ease-out',
        'scale-in': 'scale-in 0.3s ease-out',
      },
      keyframes: {
        'gradient-shift': {
          '0%, 100%': { backgroundPosition: '0% 50%' },
          '50%': { backgroundPosition: '100% 50%' },
        },
        'shimmer': {
          '0%': { backgroundPosition: '-200% 0' },
          '100%': { backgroundPosition: '200% 0' },
        },
        'float': {
          '0%, 100%': { transform: 'translateY(0)' },
          '50%': { transform: 'translateY(-20px)' },
        },
        'pulse-glow': {
          '0%, 100%': { boxShadow: '0 0 20px rgba(71, 235, 224, 0.3)' },
          '50%': { boxShadow: '0 0 40px rgba(71, 235, 224, 0.6)' },
        },
        // ... more keyframes
      },
    },
  },
};

Landing Page Patterns

Design patterns extracted from the Pairty web landing page.

Glassmorphic Patterns

Feature Cards

Feature cards use glassmorphism with backdrop blur and subtle borders. On hover, they transition to a gradient background with all text turning white.

💎

Default State

Glass background with subtle border and blur effect.

Hover State

Gradient background replaces glass, all text becomes white.

🎯

Interactive

Hover to see the transition effect.

/* Feature Card CSS */
.feature-card {
  border-radius: 24px;
  padding: 2rem;
  background: rgba(12, 24, 41, 0.9);
  backdrop-filter: blur(25px);
  border: 1px solid rgba(30, 58, 95, 0.6);
  transition: all 0.5s ease;
}

.feature-card:hover {
  background: linear-gradient(135deg, #0049E7, #47EBE0);
  border-color: transparent;
}

Glass Utilities

Light Glass

Use for subtle overlays on dark backgrounds

glass.light: bg-white/5, backdrop-blur-[12px], border-white/10

Dark Glass

Use for stronger contrast overlays

glass.dark: bg-black/40, backdrop-blur-[12px], border-white/5

Modal Glass

Use for modal and dialog backgrounds

glass.modal: bg-[#0a1628]/95, backdrop-blur-[8px], border-[#1e3a5f]/60

Floating CTA Glass

Use for floating action buttons and CTAs

glass.floatingCTA: bg-[#262626]/95, backdrop-blur-[16px], border-white/10

FAQ Accordion

Glassmorphic accordion with smooth expand/collapse animation.

Member Card

Complex glassmorphic card with gradient border and multi-color glow shadow.

Sarah Chen

Premium Member

127
Connections
$48.2k
Network Worth
24
Introductions

Glow Effects

Teal Glow
Teal Strong
Blue Glow
Blue Strong

Section Layouts

Asymmetric Grid Layout

The landing page uses 55/45 and 60/40 asymmetric splits for visual interest.

55-60%

Content area (text, CTAs)

40-45%

Visual area (images, graphics)

/* Asymmetric grid using Tailwind */
<div className="grid md:grid-cols-12 gap-8">
  <div className="md:col-span-7">Content</div>
  <div className="md:col-span-5">Visual</div>
</div>

Section Badge

Pill-shaped badges introduce each section with a label.

✨ Features💬 Testimonials❓ FAQ
<span className="inline-flex items-center px-4 py-2 rounded-full 
  bg-[rgba(255,255,255,0.05)] border border-[rgba(255,255,255,0.1)] 
  text-sm text-pairty-teal">
  ✨ Features
</span>

Gradient Headlines

Headlines use gradient text with optional text-shadow for glow effect.

Heading Gradient (278deg)

Hero Gradient (90deg)

With Text Glow

/* Gradient text with optional glow */
.gradient-heading {
  background: linear-gradient(278deg, #47EBE0 28.45%, #0049E7 100.49%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  text-shadow: 0 0 40px rgba(71, 235, 224, 0.5); /* optional glow */
}

Ambient Background Glow

Large blurred circles create ambient atmosphere behind content.

Content above ambient glows

Video Background Pattern

Hero sections can use video backgrounds with gradient overlays.

Video Overlay PatternVideo plays behind gradient overlay for readability
/* Video background with overlay */
.hero-video {
  position: absolute;
  inset: 0;
  object-fit: cover;
}

.hero-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, 
    rgba(15, 15, 15, 0.95) 0%, 
    rgba(26, 26, 26, 0.85) 40%, 
    rgba(38, 38, 38, 0.7) 100%);
}

/* Always include poster for loading state */
<video poster="/images/hero-poster.jpg" ...>

Dynamic Hero Corners

Hero sections have rounded corners at bottom that animate on scroll.

Initial (2rem)
Scrolled (4rem)
/* Dynamic corners based on scroll */
const cornerRadius = isScrolled ? '4rem' : '2rem';

<section style={{ borderRadius: `0 0 ${cornerRadius} ${cornerRadius}` }}>
  ...
</section>

Section Backgrounds

Alternating section gradients create visual rhythm.

gradient.background.section
gradient.background.sectionAlt
Footer: #000000

Button Patterns

SmartAppDownloadButton with Shimmer

Primary CTA button with animated shimmer effect and gradient swap on hover.

Default
Hover
/* Shimmer button CSS */
.shimmer-button {
  position: relative;
  overflow: hidden;
  background: linear-gradient(90deg, #47EBE0 0%, #249AE3 50%, #0049E7 100%);
  background-size: 200% 100%;
}

.shimmer-button::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  background-size: 200% 100%;
  animation: shimmer 2s linear infinite;
}

.shimmer-button:hover {
  background: linear-gradient(90deg, #0049E7 0%, #249AE3 50%, #47EBE0 100%);
}

@keyframes shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

Gradient Hover Swap

Gradient direction reverses on hover for visual feedback.

/* Two-layer gradient swap */
.gradient-swap-button {
  position: relative;
}

.gradient-swap-button .default {
  background: linear-gradient(90deg, #47EBE0, #249AE3, #0049E7);
  transition: opacity 300ms;
}

.gradient-swap-button .hover {
  background: linear-gradient(90deg, #0049E7, #249AE3, #47EBE0);
  opacity: 0;
  transition: opacity 300ms;
}

.gradient-swap-button:hover .default { opacity: 0; }
.gradient-swap-button:hover .hover { opacity: 1; }

Size Variants

Consistent sizing across button variants.

/* Size variants */
.btn-sm {
  padding: 0.5rem 1rem;
  font-size: 0.875rem;
  border-radius: 0.5rem;
}

.btn-md {
  padding: 0.75rem 1.5rem;
  font-size: 1rem;
  border-radius: 0.75rem;
}

.btn-lg {
  padding: 1rem 2rem;
  font-size: 1.125rem;
  border-radius: 0.75rem;
}

Touch Target Minimums

All interactive elements maintain minimum 44px touch target for accessibility.

44
Minimum
48
Comfortable
56
Large
/* Touch target tokens */
component.button.minHeight: "44px"

/* WCAG 2.2 requires 44x44px minimum for touch targets */
.touch-target {
  min-width: 44px;
  min-height: 44px;
}

Secondary Buttons

Ghost and outline variants for secondary actions.

Buttons with Icons

Consistent icon spacing using gap property.

/* Icon button token */
component.button.gap: "0.5rem"
component.button.iconSize: "20px"

.icon-button {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}

.icon-button svg {
  width: 20px;
  height: 20px;
}

Interaction Patterns

Header Scroll Show/Hide

Header hides on scroll down (after 300px), shows on scroll up (after 10px).

Header
const [isHeaderVisible, setIsHeaderVisible] = useState(true);
const [lastScrollY, setLastScrollY] = useState(0);

useEffect(() => {
  const handleScroll = () => {
    const currentScrollY = window.scrollY;
    
    if (currentScrollY > 300 && currentScrollY > lastScrollY) {
      setIsHeaderVisible(false); // Scrolling down
    } else if (currentScrollY < lastScrollY - 10) {
      setIsHeaderVisible(true);  // Scrolling up
    }
    
    setLastScrollY(currentScrollY);
  };
  
  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, [lastScrollY]);

Scroll-Spy Navigation

Navigation highlights active section based on scroll position.

// Using Intersection Observer for scroll-spy
const observer = new IntersectionObserver(
  (entries) => {
    entries.forEach((entry) => {
      if (entry.isIntersecting) {
        setActiveSection(entry.target.id);
      }
    });
  },
  { rootMargin: '-50% 0px -50% 0px' }
);

sections.forEach((section) => observer.observe(section));

Top Banner with Shimmer

Announcement banner with shimmer animation and live indicator.

1,247 members networking right now
/* Banner shimmer animation */
@keyframes banner-shimmer {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* Live ping indicator */
<span className="relative flex h-2.5 w-2.5">
  <span className="absolute inline-flex h-full w-full 
    rounded-full bg-emerald-500 opacity-75 animate-ping" />
  <span className="relative inline-flex h-2.5 w-2.5 
    rounded-full bg-emerald-500" />
</span>

Auto-Cycling Carousel

Infinite scroll carousel that pauses on hover.

Card 1
Card 2
Card 3
Card 4
Card 5
Card 1
Card 2
Card 3
Card 4
Card 5
/* Carousel auto-scroll */
@keyframes carousel {
  0% { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}

.carousel-track {
  animation: carousel 20s linear infinite;
}

.carousel-track:hover {
  animation-play-state: paused;
}

Hover Transitions

Consistent hover timing across components.

150ms (fast)Quick interactions
300ms (base)Default transitions
500ms (slow)Complex transitions

Motion Patterns

Framer Motion Easing

Standardized easing curves for consistent motion across the app.

smooth

[0.25, 0.46, 0.45, 0.94]

Page transitions, stagger animations

spring

stiffness: 300, damping: 30

Modal entrance, banner appearance

tween

type: "tween", duration: 0.4

Page transitions

// easing constants
export const EASING = {
  smooth: [0.25, 0.46, 0.45, 0.94],
  spring: { stiffness: 300, damping: 30 },
  tween: { type: 'tween', duration: 0.4 },
};

// Usage
<motion.div
  transition={{ ease: EASING.smooth, duration: 0.5 }}
>

<motion.div
  transition={{ type: 'spring', ...EASING.spring }}
>

PageTransition Component

Wrapper for smooth page transitions using AnimatePresence.

'use client';

import { motion, AnimatePresence } from 'framer-motion';
import { usePathname } from 'next/navigation';

const pageVariants = {
  initial: { opacity: 0, y: 20 },
  animate: { 
    opacity: 1, 
    y: 0,
    transition: { 
      duration: 0.4, 
      ease: [0.25, 0.46, 0.45, 0.94] 
    }
  },
  exit: { 
    opacity: 0, 
    y: -20,
    transition: { duration: 0.3 }
  }
};

export function PageTransition({ children }) {
  const pathname = usePathname();
  
  return (
    <AnimatePresence mode="wait">
      <motion.div
        key={pathname}
        variants={pageVariants}
        initial="initial"
        animate="animate"
        exit="exit"
      >
        {children}
      </motion.div>
    </AnimatePresence>
  );
}

FadeIn Scroll Animation

Elements fade in when they enter the viewport using whileInView.

'use client';

import { motion } from 'framer-motion';

interface FadeInProps {
  children: React.ReactNode;
  delay?: number;
  direction?: 'up' | 'down' | 'left' | 'right';
}

export function FadeIn({ 
  children, 
  delay = 0, 
  direction = 'up' 
}: FadeInProps) {
  const directionOffset = {
    up: { y: 20 },
    down: { y: -20 },
    left: { x: 20 },
    right: { x: -20 },
  };

  return (
    <motion.div
      initial={{ 
        opacity: 0, 
        ...directionOffset[direction] 
      }}
      whileInView={{ 
        opacity: 1, 
        x: 0, 
        y: 0 
      }}
      viewport={{ once: true, margin: '-50px' }}
      transition={{ 
        duration: 0.5, 
        delay,
        ease: [0.25, 0.46, 0.45, 0.94] 
      }}
    >
      {children}
    </motion.div>
  );
}

StaggerContainer Pattern

Parent container that staggers child animations.

Delay: 0s
Delay: 0.1s
Delay: 0.2s
Delay: 0.3s
const containerVariants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
      delayChildren: 0.2,
    },
  },
};

const itemVariants = {
  hidden: { opacity: 0, y: 20 },
  visible: { 
    opacity: 1, 
    y: 0,
    transition: { 
      duration: 0.5,
      ease: [0.25, 0.46, 0.45, 0.94] 
    }
  },
};

// Usage
<motion.div
  variants={containerVariants}
  initial="hidden"
  whileInView="visible"
  viewport={{ once: true }}
>
  {items.map((item) => (
    <motion.div key={item.id} variants={itemVariants}>
      {item.content}
    </motion.div>
  ))}
</motion.div>

Spring Configurations

Physics-based spring animations for natural motion.

Modal Entrance

transition: {
  type: 'spring',
  stiffness: 300,
  damping: 30
}

Bouncy Elements

transition: {
  type: 'spring',
  stiffness: 400,
  damping: 10
}

CSS Animations (Tailwind)

Tailwind keyframe animations for simple effects.

animate-pulse
animate-bounce
animate-spin
animate-ping

Floating CTA Patterns

MobileBottomCTA

Sticky bottom CTA that appears after scrolling past the header. Uses safe-area-inset for notched devices.

Page content area
/* MobileBottomCTA styling */
.mobile-bottom-cta {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 50;
  background: rgba(38, 38, 38, 0.95);
  backdrop-filter: blur(16px);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 24px 24px 0 0;
  padding: 1rem 1rem calc(1rem + env(safe-area-inset-bottom));
}

/* Show/hide based on scroll */
const [showCTA, setShowCTA] = useState(false);

useEffect(() => {
  const handleScroll = () => {
    // Show after scrolling past header
    setShowCTA(window.scrollY > 500);
  };
  window.addEventListener('scroll', handleScroll);
  return () => window.removeEventListener('scroll', handleScroll);
}, []);

CookieConsent

Floating cookie consent banner with glassmorphic styling.

We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.

/* CookieConsent styling */
.cookie-consent {
  position: fixed;
  bottom: 1rem;
  left: 1rem;
  right: 1rem;
  max-width: 450px;
  z-index: 50;
  border-radius: 16px;
  padding: 1.5rem;
  background: rgba(38, 38, 38, 0.95);
  backdrop-filter: blur(16px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

@media (min-width: 768px) {
  .cookie-consent {
    left: auto;
  }
}

Safe Area Handling

Bottom padding accounts for device safe areas (notch, home indicator).

/* Safe area padding */
.floating-cta {
  padding-bottom: calc(1rem + env(safe-area-inset-bottom));
}

/* Tailwind */
className="pb-[calc(1rem+env(safe-area-inset-bottom))]"

/* Or using custom property */
:root {
  --safe-area-bottom: env(safe-area-inset-bottom, 0px);
}

.floating-cta {
  padding-bottom: calc(1rem + var(--safe-area-bottom));
}

Z-Index Layering

Floating elements layer below modals but above content.

z-0
Content
z-50
Header
z-50
Floating CTA
z-100
Modal

Visibility Logic

Floating CTAs have conditional visibility based on scroll position.

// MobileBottomCTA visibility
const [showMobileCTA, setShowMobileCTA] = useState(false);

useEffect(() => {
  const handleScroll = () => {
    // Only show on mobile, after scrolling past hero
    const isMobile = window.innerWidth < 768;
    const scrolledPastHero = window.scrollY > 500;
    setShowMobileCTA(isMobile && scrolledPastHero);
  };
  
  window.addEventListener('scroll', handleScroll);
  window.addEventListener('resize', handleScroll);
  return () => {
    window.removeEventListener('scroll', handleScroll);
    window.removeEventListener('resize', handleScroll);
  };
}, []);

// CookieConsent visibility
const [showCookie, setShowCookie] = useState(false);

useEffect(() => {
  const consent = localStorage.getItem('cookieConsent');
  if (!consent) {
    // Delay showing for better UX
    setTimeout(() => setShowCookie(true), 1500);
  }
}, []);

Icon Patterns

Gradient Stroke Icons

SVG icons with gradient strokes using inline SVG defs.

Gradient Stroke
Dark Solid
Light Solid
/* SVG with gradient stroke */
<svg viewBox="0 0 56 56" fill="none">
  <path 
    stroke="url(#iconGradient)" 
    stroke-width="1.5" 
    stroke-linecap="round"
    d="..." 
  />
  <defs>
    <linearGradient 
      id="iconGradient" 
      x1="7" y1="7" x2="49" y2="49" 
      gradientUnits="userSpaceOnUse"
    >
      <stop stop-color="#0049E7"/>
      <stop offset="1" stop-color="#47EBE0"/>
    </linearGradient>
  </defs>
</svg>

Hover State Icon Switching

Icons switch from gradient to solid white on hover within feature cards.

Hover to see switch
/* Icon hover switching */
.feature-card:hover .icon path {
  stroke: #ffffff;
}

/* React implementation */
<path
  stroke={isHovered ? '#ffffff' : 'url(#iconGradient)'}
  className="transition-colors duration-500"
  ...
/>

Icon Sizes

Standard icon sizes used across the application.

20px
24px
32px
40px
56px

Dollar Icon Asset

Available in gradient and dark variants at assets/icons/

dollar-icon.svg

Gradient version for dark backgrounds

dollar-icon-dark.svg

Dark solid version for light backgrounds

Calculator Patterns

ROI Calculator

Interactive calculator with glassmorphic container and selection cards.

Calculate Your Network Value

Estimated Annual Value$32,500

Selection Card States

Interactive selection cards with clear visual feedback.

Unselected
Option Label
Selected
Option Label
/* Selection card tokens */
component.roiCalculator.scenarioCard: {
  borderRadius: "12px",
  borderDefault: "2px solid rgba(255, 255, 255, 0.1)",
  borderSelected: "2px solid #47EBE0",
  backgroundSelected: "rgba(71, 235, 224, 0.1)"
}

/* Tailwind implementation */
<button className={cn(
  "p-4 rounded-xl border-2 transition-all",
  isSelected
    ? "border-pairty-teal bg-[rgba(71,235,224,0.1)]"
    : "border-[rgba(255,255,255,0.1)] bg-[rgba(255,255,255,0.05)]"
)}>
  ...
</button>

Value Display Formatting

Large numerical values use gradient text for emphasis.

Currency$48,250
Percentage+127%
Count1,247
/* Network worth gradient text */
.value-display {
  background: linear-gradient(90deg, #47EBE0 0%, #249AE3 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  font-size: 2.25rem;
  font-weight: 700;
}

/* Gradient token */
gradient.text.networkWorth: "linear-gradient(90deg, #47EBE0 0%, #249AE3 100%)"

Calculator Container

Glassmorphic container styling for calculator widgets.

/* Calculator container tokens */
component.roiCalculator: {
  borderRadius: "24px",
  background: "rgba(255, 255, 255, 0.05)",
  border: "1px solid rgba(255, 255, 255, 0.1)"
}

/* CSS */
.calculator-container {
  border-radius: 24px;
  padding: 2rem;
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

Components & Assets

Reusable components, logos, and mobile patterns.

Components

DaisyUI components styled with Pairty brand tokens, plus landing page patterns.

Buttons

Landing Page CTA Style:

Button Token Values

  • • Min height: 44px (touch target)
  • • Padding X: 1.5rem
  • • Padding Y: 1rem
  • • Border radius: 0.5rem (DaisyUI) / 0.75rem (Landing)

Cards

Basic Card

Card content goes here with proper spacing.

Image Card

Card with gradient header.

💎

Glassmorphic Card

Landing page feature card style with blur effect.

Form Elements

Helper text

Landing Page Input Style:

Input Token Values

  • • Height: 44px (prevents iOS zoom)
  • • Font size: 16px
  • • Focus ring: 2px solid #47EBE0

Badges & Alerts

DefaultPrimarySecondaryAccentSuccessWarningError

Landing Page Section Badge:

✨ Features
Info alert message
Success alert message
Warning alert message
Error alert message

Component Tokens

// components.json (selected tokens)
{
  "button": {
    "paddingX": "1.5rem",
    "paddingY": "1rem",
    "borderRadius": "0.5rem",
    "minHeight": "44px",
    "shimmer": {
      "gradient": "linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent)",
      "animation": "shimmer 2s linear infinite"
    }
  },
  "featureCard": {
    "padding": "2rem",
    "borderRadius": "24px",
    "background": { "default": "rgba(12, 24, 41, 0.9)" },
    "backdropBlur": "25px",
    "border": { "default": "1px solid rgba(30, 58, 95, 0.6)" }
  },
  "sectionBadge": {
    "paddingX": "1rem",
    "paddingY": "0.5rem",
    "borderRadius": "9999px",
    "background": "rgba(255, 255, 255, 0.05)",
    "textColor": "#47EBE0"
  }
}

Logo & Branding

Logo variants, clearspace rules, and app icon specifications.

Brand Symbol

The Pairty™ symbol features the stylized P letterform with gradient arc motif, representing the connection between people.

Logo Variants

Pairty™

Horizontal Dark

For dark backgrounds

horizontal-dark.svg

Pairty™

Horizontal Light

For light backgrounds

horizontal-light.svg

Pairty™

Vertical Dark

Square layouts, splash screens

vertical-dark.svg

Pairty™

Vertical Light

Light square layouts

vertical-light.svg

Symbol Only

App icons, favicons

symbol-only.svg

Clearspace Rules

Clearspace = Stroke Width
Clearspace
Clearspace
Clearspace
Pairty™

Maintain clearspace equal to the logo stroke width on all sides.

Color Usage

Pairty™
Pairty™

Symbol: Always uses brand gradient
Wordmark: Off White (#EAEAEC) on dark, Charcoal (#262626) on light

App Icon Sizes

16x16

Web favicon

32x32

Web favicon

180x180

Apple touch icon

192x192

Android/PWA

512x512

PWA, Play Store

1024x1024

iOS App Store

Logo Don'ts

Pairty™

Don't blur or distort

Pairty™

Don't change colors

Pairty™

Don't rotate logo

Asset Files

FileFormatUsage
horizontal-dark.svgSVGWeb, dark backgrounds
horizontal-light.svgSVGWeb, light backgrounds
symbol-only.svgSVGIcons, favicons
app-icon-*.pngPNGApp stores, PWA

Logo Usage

Logo Variants

Three logo variants available for different contexts.

Pairty
Full Logovariant="full"
Symbol Onlyvariant="symbol"
PairtyText Onlyvariant="text"

Theme Variants

Logo adapts to light and dark backgrounds.

Pairty
Dark Themetheme="dark"
Pairty
Light Themetheme="light"

Default Dimensions

Standard logo sizing for different contexts.

Header120px
Footer100px
Favicon32px
App Icon48px

Clear Space

Minimum padding around logo equal to the height of the symbol.

1x height
Pairty

Usage Examples

Common logo placement patterns.

Pairty
Pairty

© 2025 Pairty. All rights reserved.

Logo Component

interface LogoProps {
  variant?: 'full' | 'symbol' | 'text';
  theme?: 'light' | 'dark';
  className?: string;
}

export function Logo({ 
  variant = 'full', 
  theme = 'dark',
  className 
}: LogoProps) {
  const textColor = theme === 'dark' ? 'text-white' : 'text-pairty-charcoal';
  
  return (
    <div className={cn('flex items-center gap-2', className)}>
      {variant !== 'text' && (
        <div className="w-10 h-10 rounded-lg bg-gradient-to-br from-pairty-blue to-pairty-teal" />
      )}
      {variant !== 'symbol' && (
        <span className={cn('text-2xl font-bold', textColor)}>
          Pairty
        </span>
      )}
    </div>
  );
}

Logo Don'ts

Pairty
Don't stretch
Pairty
Don't rotate
Pairty
Don't recolor

Mobile Patterns

Platform-specific patterns and tokens for React Native mobile apps.

Bottom Navigation

Screen Content
Home
Search
Messages
Profile

Token Values

  • Background: rgba(0, 0, 0, 0.95)
  • Active: #0049E7 (brand blue)
  • Inactive: rgba(255, 255, 255, 0.6)
  • Border radius: 20px (top corners)
  • Padding: 12px vertical, 20px horizontal

⚠️ Current Inconsistency

Mobile app uses iOS system blue #007AFF instead of brand blue #0049E7. This should be updated for brand consistency.

Touch Targets

44

Minimum

44×44px

48

Comfortable

48×48px

56

Large

56×56px

WCAG 2.2 Success Criterion 2.5.8: Target size minimum of 24×24 CSS pixels, with 44×44px recommended for mobile touch interfaces.

Safe Areas

iOS Safe Areas

Status Bar (44px)
Home Indicator (34px)

Android Safe Areas

Status Bar (24px)
Nav Bar (20px)

Mobile Typography

TokenWeb (rem)Mobile (px)Usage
xs0.75rem12pxLabels, metadata
sm0.875rem14pxCaptions, secondary text
base1rem16pxBody text, inputs
lg1.125rem18pxEmphasized body
xl1.25rem20pxSection headings

Input font size: Use 16px minimum for inputs on mobile to prevent iOS Safari zoom.

Mobile Dark Background

Mobile Dark (Legacy)

linear-gradient(135deg, #111122, #121220, #101020)

Brand Charcoal

#262626 (Brand Standard)

React Native Usage

// Import tokens
import { colors, spacing, mobile } from '@pairty/design-tokens';

// StyleSheet example
const styles = StyleSheet.create({
  container: {
    padding: spacing[4], // 16px
    backgroundColor: colors.background.dark,
  },
  button: {
    minHeight: mobile.touchTarget.min, // 44px
    backgroundColor: colors.brand.primary,
    borderRadius: spacing[2], // 8px
  },
  bottomNav: {
    backgroundColor: mobile.bottomNav.background,
    borderTopLeftRadius: mobile.bottomNav.borderRadius,
    borderTopRightRadius: mobile.bottomNav.borderRadius,
    paddingBottom: Platform.select({
      ios: mobile.safeArea.bottom.ios,
      android: mobile.safeArea.bottom.android,
    }),
  },
  activeTab: {
    color: colors.brand.primary, // Use #0049E7, not #007AFF
  },
  inactiveTab: {
    color: mobile.bottomNav.inactiveColor,
  },
});

Utilities & Accessibility

CSS utilities, accessibility patterns, and guidelines.

Utility Classes

.glass Utility

Quick glassmorphism effect for overlays and cards.

Element with .glass class
.glass {
  background: rgba(255, 255, 255, 0.05);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

Glow Utilities

Box shadow utilities for glow effects.

.glow-teal
Teal glow effect
.glow-blue
Blue glow effect
.glow-teal {
  box-shadow: 0 0 30px rgba(71, 235, 224, 0.25);
}

.glow-teal-strong {
  box-shadow: 0 0 40px rgba(71, 235, 224, 0.3);
}

.glow-blue {
  box-shadow: 0 0 25px rgba(0, 73, 231, 0.2);
}

.glow-blue-strong {
  box-shadow: 0 0 40px rgba(0, 73, 231, 0.3);
}

.gradient-border Utility

Creates gradient borders using background-clip technique.

Element with gradient border
.gradient-border {
  background: 
    linear-gradient(#0c1829, #0c1829) padding-box,
    linear-gradient(to bottom, #1e3a5f, #0a1628) border-box;
  border: 1px solid transparent;
}

Text Selection

Brand-colored text selection for consistent experience.

This text simulates selection - try selecting other text to see the effect.

::selection {
  background-color: rgba(71, 235, 224, 0.3);
  color: #ffffff;
}

::-moz-selection {
  background-color: rgba(71, 235, 224, 0.3);
  color: #ffffff;
}

Focus Ring

Accessible focus indicators using brand teal color.

:focus-visible {
  outline: 2px solid #47EBE0;
  outline-offset: 2px;
}

/* Tailwind */
focus-visible:ring-2 focus-visible:ring-pairty-teal focus-visible:ring-offset-2

Reduced Motion

Respect user preferences for reduced motion.

/* Global reduced motion support */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* Tailwind variant */
motion-reduce:transition-none
motion-reduce:animate-none

.text-gradient Utility

Gradient text effect for headings and emphasis.

Gradient Text Example

.text-gradient {
  background: linear-gradient(to right, #47EBE0, #0049E7);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

/* Tailwind */
bg-gradient-to-r from-pairty-teal to-pairty-blue bg-clip-text text-transparent

Accessibility

Color contrast ratios, focus states, and accessibility guidelines.

Color Contrast Ratios

CombinationPreviewRatioWCAG Level
Charcoal on Off White
Sample
12.6:1AAA
Pairty Blue on Off White
Sample
7.2:1AAA
Off White on Charcoal
Sample
12.6:1AAA
Pairty Teal on Charcoal
Sample
8.4:1AAA
Bright Blue on Off White
Sample
3.2:1AA Large
Pairty Teal on Off White
Sample
1.4:1Fail

WCAG Guidelines

  • Level AA: 4.5:1 for normal text, 3:1 for large text
  • Level AAA: 7:1 for normal text, 4.5:1 for large text
  • Large text: 18pt+ or 14pt+ bold

Focus States

Focused Link

Focus Token Values

  • Color: #47EBE0 (Pairty Teal)
  • Width: 2px
  • Style: solid
  • Offset: 2px

Touch Targets

24×24px

WCAG Minimum

44×44px

Recommended

48×48px

Material Design

Pairty Standard: All interactive elements must have a minimum touch target of44×44px on mobile devices.

Reduced Motion

Respect user preferences for reduced motion using the prefers-reduced-motion media query.

/* CSS */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

/* React Native */
import { AccessibilityInfo } from 'react-native';

const [reduceMotion, setReduceMotion] = useState(false);

useEffect(() => {
  AccessibilityInfo.isReduceMotionEnabled().then(setReduceMotion);
}, []);

Color Blindness Considerations

Do

  • Use icons with color indicators
  • Add text labels to color-coded elements
  • Use patterns in addition to colors
  • Ensure sufficient contrast

Don't

  • Rely on color alone to convey meaning
  • Use red/green as the only differentiator
  • Use low contrast color combinations
Success with icon
Error with icon

Screen Reader Guidelines

Web (ARIA)

<button 
  aria-label="Close dialog"
  aria-pressed="false"
>
  <CloseIcon />
</button>

<img 
  src="logo.svg" 
  alt="Pairty logo"
/>

<nav aria-label="Main navigation">
  ...
</nav>

React Native

<TouchableOpacity
  accessible={true}
  accessibilityLabel="Close dialog"
  accessibilityRole="button"
>
  <CloseIcon />
</TouchableOpacity>

<Image
  source={logo}
  accessibilityLabel="Pairty logo"
/>

Accessibility Patterns

Reduced Motion Support

Respect user preferences for reduced motion with CSS media query.

Default Motion

Reduced Motion

Animation disabled

/* Global reduced motion support */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Framer Motion hook */
import { useReducedMotion } from 'framer-motion';

function AnimatedComponent() {
  const shouldReduceMotion = useReducedMotion();
  
  return (
    <motion.div
      animate={{ x: 100 }}
      transition={shouldReduceMotion ? { duration: 0 } : { duration: 0.5 }}
    />
  );
}

/* Token reference */
effects.reducedMotion: {
  duration: "0.01ms",
  iterations: "1"
}

Focus Ring Styling

Visible focus indicators using brand teal color for keyboard navigation.

Button Focus
Input Focus
Link FocusFocused Link
/* Focus ring styling */
:focus-visible {
  outline: 2px solid #47EBE0;
  outline-offset: 2px;
}

/* Remove default focus, add custom */
button:focus {
  outline: none;
}

button:focus-visible {
  outline: 2px solid #47EBE0;
  outline-offset: 2px;
}

/* Token reference */
effects.focus: {
  ring: "2px solid #47EBE0",
  offset: "2px"
}

Text Selection

Brand-colored text selection for consistent visual experience.

Try selecting this text to see the custom selection color. The selection uses our brand teal color at 30% opacity with white text.

This simulates the selection appearance

/* Custom text selection */
::selection {
  background-color: rgba(71, 235, 224, 0.3);
  color: #ffffff;
}

::-moz-selection {
  background-color: rgba(71, 235, 224, 0.3);
  color: #ffffff;
}

/* Token reference */
color.selection: {
  background: "rgba(71, 235, 224, 0.3)",
  text: "#ffffff"
}

Touch Target Minimums

WCAG 2.2 requires minimum 44x44px touch targets for mobile accessibility.

44
MinimumWCAG 2.2 requirement
48
ComfortableRecommended for mobile
56
LargePrimary CTAs
/* Touch target tokens */
mobile.touchTarget: {
  min: 44,        // WCAG 2.2 minimum
  comfortable: 48, // Better for mobile
  large: 56       // Primary actions
}

/* Ensure minimum size */
.interactive-element {
  min-width: 44px;
  min-height: 44px;
}

Color Contrast

Text colors maintain WCAG AA contrast ratios against backgrounds.

Primary Text (#FFFFFF)✓ AAA
Light Text (#F3EDED)✓ AAA
Muted Text (#9ca3af)✓ AA
Teal (#47EBE0)✓ AA
Primary Text (#262626)✓ AAA
Secondary (#6b7280)✓ AA
Blue (#0049E7)✓ AA

Common ARIA Patterns

Semantic ARIA attributes used throughout the application.

/* Modal dialog */
<div
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
>
  <h2 id="modal-title">Modal Title</h2>
</div>

/* Accordion */
<button
  aria-expanded={isOpen}
  aria-controls="accordion-content"
>
  Toggle
</button>
<div id="accordion-content" hidden={!isOpen}>
  Content
</div>

/* Navigation */
<nav aria-label="Main navigation">
  <a href="#" aria-current={isActive ? 'page' : undefined}>
    Link
  </a>
</nav>

/* Live region for dynamic content */
<div aria-live="polite" aria-atomic="true">
  {statusMessage}
</div>

/* Loading states */
<button aria-busy={isLoading} disabled={isLoading}>
  {isLoading ? 'Loading...' : 'Submit'}
</button>