imitation
← all crawls

Pomo | Discord's Ultimate Productivity Engine

https://pomofocus.online/

Automatically track voice study time, run Pomodoro sessions, raise study pets, and grow a virtual garden inside Discord.

pomofocus.online screenshot

Visuals

Colors

Primary
#010000
Background
#07080d
Surface
rgba(0, 0, 0, 0)
Text Primary
#f0f2ff
Text Secondary
oklab(0.999994 0.0000455677 0.0000200868 / 0.74)

Typography

Aa
Display
Inter
118px / w950
Aa
Heading
Inter
20px / w900
Aa
Body
Inter
23px / w400
Aa
Label
Inter
14px / w400

Spacing

Xs
6px
Sm
8px
Md
16px
Lg
24px
Xl
40px

Radius

Sm
6px
Md
12px
Lg
16px
Pill
9999px

Mode

Dark mode
Background
Sample text on canvas
Bg#07080d
Text#f0f2ff
Mutedoklab(0.999994 0.0000455677 0.0000200868 / 0.74)

Motion

Levelsubtle
Duration300ms
Easingcubic-bezier(0.4, 0, 0.2, 1)

Stack

Frameworktailwind
Iconslucide

Full Palette · 28 tokens

Brand
accent-blurple
#5865f2
accent-green
#57f287
accent-orange
#e07c24
primary
#010000
primary-active
#1a1a1a
primary-disabled
#0a0a0a
Surface
canvas
#07080d
surface
rgba(0, 0, 0, 0)
surface-card
oklab(0 0 0 / 0.2)
surface-dark
oklab(0 0 0 / 0.35)
surface-darker
oklab(0 0 0 / 0.45)
surface-elevated
oklab(0 0 0 / 0.42)
surface-glass
rgba(255, 255, 255, 0.05)
surface-strong
rgba(255, 255, 255, 0.08)
surface-subtle
oklab(0.999994 0.0000455678 0.0000200868 / 0.04)
Text
body
oklab(0.999994 0.0000455677 0.0000200868 / 0.74)
ink
#f0f2ff
muted
rgba(240, 242, 255, 0.7)
muted-soft
rgba(240, 242, 255, 0.4)
on-dark
#ffffff
on-primary
#ffffff
Hairlines & Borders
border-glass
rgba(255, 255, 255, 0.05)
hairline
rgba(255, 255, 255, 0.08)
hairline-strong
rgba(255, 255, 255, 0.1)
Semantic
link
#5865f2
link-active
#7983f5
success
#57f287
warning
#e07c24

Typography Roles · 9

body-md
Aa
23px / w400
body-sm
Aa
16px / w400
button
Aa
14px / w700
button-lg
Aa
18px / w700
caption
Aa
14px / w400
display-lg
Aa
64px / w950
display-xl
Aa
118px / w950
label-stat
Aa
14px / w500
title-md
Aa
20px / w900

Components · 14

button-primary
backgroundColor{colors.surface}
height56px
padding12px 24px
rounded{rounded.DEFAULT}
textColor{colors.on-primary}
typography{typography.button-lg}
button-primary-nav
backgroundColor{colors.surface}
padding8px 20px
rounded{rounded.DEFAULT}
textColor{colors.on-primary}
typography{typography.button}
button-secondary
backgroundColor{colors.surface-glass}
height56px
padding12px 24px
rounded{rounded.DEFAULT}
textColor{colors.ink}
typography{typography.button-lg}
button-secondary-nav
backgroundColor{colors.surface-glass}
padding8px 16px
rounded{rounded.DEFAULT}
textColor{colors.ink}
typography{typography.button}
cta-row
backgroundColor{colors.canvas}
padding{spacing.md} 0
textColor{colors.ink}
hero-badge
backgroundColor{colors.surface-elevated}
padding6px 16px
rounded{rounded.pill}
textColor{colors.success}
typography{typography.caption}
hero-band
backgroundColor{colors.canvas}
padding{spacing.hero-top} {spacing.md} {spacing.xl} {spacing.md}
textColor{colors.on-primary}
typography{typography.display-xl}
hero-headline
backgroundColor{colors.canvas}
textColor{colors.on-primary}
typography{typography.display-xl}
hero-subhead
backgroundColor{colors.canvas}
textColor{colors.body}
typography{typography.body-md}
nav-link
backgroundColor{colors.surface}
rounded{rounded.full}
textColor{colors.muted}
typography{typography.body-sm}
nav-link-active
backgroundColor{colors.surface}
textColor{colors.ink}
typography{typography.body-sm}
stat-card
backgroundColor{colors.surface-dark}
padding{spacing.lg}
rounded{rounded.lg}
textColor{colors.on-primary}
typography{typography.display-lg}
stat-label
backgroundColor{colors.surface-dark}
textColor{colors.muted}
typography{typography.label-stat}
top-nav
backgroundColor{colors.surface}
height72px
textColor{colors.ink}
typography{typography.body-sm}

design.md

Pomo Design System

Overview

Pomo is a Discord productivity bot whose visual identity occupies the liminal space between developer utility tools and premium SaaS landing pages. The design language is built around a near-black canvas ({colors.canvas}#07080d) that feels deeper than standard #111 surfaces, creating an immersive environment where content appears to float rather than sit. Against this void, the system deploys a luminous periwinkle-white ({colors.ink}#f0f2ff) as its primary voice — a color that reads as pure white but carries subtle violet undertones that harmonize with Discord's brand palette.

The single most distinctive typographic move in this system is its aggressive use of weight. Both {typography.display-xl} and {typography.title-md} operate at font-weight: 950, a Black/Heavy weight that most design systems never touch. This creates headlines that feel architectural and monumental — the "PomoBot" hero text isn't just large; it has physical mass. Body copy, by contrast, drops to a modest font-weight: 400 at a generous 23px size ({typography.body-md}), establishing extreme contrast between the declarative and the conversational.

Brand voltage lives in the glassmorphic treatment of interactive surfaces. Rather than using a solid accent background for CTAs, the system applies {colors.surface-glass} (white at 5% opacity) or pure transparency ({colors.surface}), then relies on a signature blurple-tinted shadow ({extensions.shadows.blurple-glow}) to signal importance. The {colors.accent-blurple} (#5865f2) — Discord's canonical indigo — appears sparingly: in the Login button glow, in status indicators, and as the selection highlight color. This restraint makes each appearance feel intentional.

Shape language favors {rounded.DEFAULT} (12px) for cards and buttons — round enough to feel friendly, sharp enough to maintain technical credibility. Pill shapes appear only in the Live badge component. The overall mood is one of confident minimalism: a tool built by developers who understand that Discord server admins value clarity over decoration.

Key Characteristics:

  • Near-black canvas {colors.canvas} (#07080d) provides immersive depth without pure-black harshness
  • Periwinkle-white ink {colors.ink} (#f0f2ff) serves as all primary text with violet undertones
  • Weight-950 display typography ({typography.display-xl}, {typography.title-md}) creates monumental headline presence
  • Glassmorphic surfaces use low-opacity white ({colors.surface-glass}, {colors.surface-strong}) instead of solid fills
  • Blurple-tinted glow shadow ({extensions.shadows.blurple-glow}) brands primary CTAs without solid-color backgrounds
  • Stat cards use elevated black surfaces ({colors.surface-dark}) with massive numerals at {typography.display-lg}
  • Accent palette draws from Discord's semantic colors: green ({colors.accent-green}), orange ({colors.accent-orange}), blurple ({colors.accent-blurple})
  • Generous vertical rhythm with {spacing.hero-top} (106px) above hero and {spacing.section} (120px) between major sections
  • Fixed transparent navigation ({component.top-nav}) with backdrop transition on scroll
  • Uppercase tracking labels ({typography.label-stat}) at 0.04em letter-spacing for stat card metadata

Colors

Brand & Accent

  • Primary ({colors.primary} — #010000): Ultra-black used as the conceptual "brand fill" — though visually transparent on most surfaces, it defines the deepest surface tokens and disabled states.
  • Primary Active ({colors.primary-active} — #1a1a1a): Slightly lifted black for hover/active states where depth feedback is needed.
  • Primary Disabled ({colors.primary-disabled} — #0a0a0a): Near-imperceptible elevation from pure black for disabled button backgrounds.
  • Accent Blurple ({colors.accent-blurple} — #5865f2): Discord's signature indigo, used exclusively for the Login button glow shadow, link color, and selection highlights. Never a solid background fill.
  • Accent Green ({colors.accent-green} — #57f287): Discord success green, appearing in the "LIVE" badge indicator and positive status states.
  • Accent Orange ({colors.accent-orange} — #e07c24): Discord warning orange, visible in flame/water-drop decorative icons flanking the stat counter.

Surface

  • Canvas ({colors.canvas} — #07080d): The base layer — deeper than typical dark-mode surfaces, this is the page body background and hero band fill.
  • Surface ({colors.surface} — transparent): The default background for navigation and primary buttons — relies on the canvas showing through.
  • Surface Glass ({colors.surface-glass} — white at 5%): Secondary button backgrounds and subtle card fills. Creates the frosted-glass effect against the dark canvas.
  • Surface Strong ({colors.surface-strong} — white at 8%): Secondary button borders and slightly more visible containers.
  • Surface Elevated ({colors.surface-elevated} — black at 42%): The hero badge/pill background — opaque enough to read clearly, translucent enough to feel layered.
  • Surface Dark ({colors.surface-dark} — black at 35%): Stat card backgrounds — these are the darkest elevated surfaces, sitting just above the canvas.
  • Surface Darker ({colors.surface-darker} — black at 45%): Deepest elevated surface, reserved for modals or high-emphasis overlays.
  • Surface Subtle ({colors.surface-subtle} — white at 4%): Faintest surface tint, used for extremely subtle separators or hover zones.
  • Surface Card ({colors.surface-card} — black at 20%): Mid-tone elevated surface for content cards below the hero fold.

Text

  • Ink ({colors.ink} — #f0f2ff): Primary text color — a cool white with perceptible blue-violet shift. Used for all headlines, navigation labels, and primary button text.
  • Body ({colors.body} — white at 74% opacity): Hero subheading and paragraph text — significantly dimmed from ink to establish hierarchy without size change alone.
  • Muted ({colors.muted} — ink at 70% opacity): Secondary navigation text, mobile menu icon color, and supporting metadata.
  • Muted Soft ({colors.muted-soft} — ink at 40% opacity): Tertiary/disabled text states — barely legible, used for placeholder or de-emphasized content.
  • On Primary ({colors.on-primary} — #ffffff): Pure white text reserved for elements sitting on the darkest surfaces (hero headline, stat numbers, button text).
  • On Dark ({colors.on-dark} — #ffffff): Alias for on-primary in this system since all dark surfaces receive white text.

Hairlines & Borders

  • Hairline ({colors.hairline} — white at 8%): Default border for secondary buttons, input outlines, and card boundaries. Nearly invisible against the canvas.
  • Hairline Strong ({colors.hairline-strong} — white at 10%): Slightly more visible variant for primary button borders and focused states.
  • Border Glass ({colors.border-glass} — white at 5%): Faintest border token, matching surface-glass opacity for container edges that should barely register.

Semantic

  • Success ({colors.success} — #57f287): Maps to accent-green; used for live status badges and positive indicators.
  • Warning ({colors.warning} — #e07c24): Maps to accent-orange; used for attention-requiring iconography.
  • Link ({colors.link} — #5865f2): Maps to accent-blurple; hyperlink default state.
  • Link Active ({colors.link-active} — #7983f5): Lightened blurple for visited/focused link states.

Typography

Font Family

The entire system runs on Inter, served through a robust fallback stack: "Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif". Inter was chosen for its exceptional performance at extreme weights — the font-weight: 950 used in display roles remains legible and characterful rather than blob-like, which is not true of most geometric sans-serifs. There is no serif or monospace face in this design system; all content, code references, and numerical displays use Inter. This is unusual for a developer-tool product but aligns with Pomo's positioning as a consumer-friendly Discord extension rather than a technical API platform.

Hierarchy

| Token | Size | Weight | Line Height | Letter Spacing | Use | |---|---|---|---|---|---| | {typography.display-xl} | 118px | 950 | 112.1px | normal | Hero headline ("PomoBot") | | {typography.display-lg} | 64px | 950 | 80px | normal | Stat card numerals | | {typography.title-md} | 20px | 900 | 28px | normal | Section titles, feature headings | | {typography.body-md} | 23px | 400 | 37.95px | normal | Hero subheading, descriptive paragraphs | | {typography.body-sm} | 16px | 400 | 1.5 | normal | Navigation links, body copy | | {typography.caption} | 14px | 400 | 1.38 | normal | Badge text, fine print | | {typography.button} | 14px | 700 | 1.25 | normal | Nav bar buttons | | {typography.button-lg} | 18px | 700 | 1.25 | normal | Hero CTA buttons | | {typography.label-stat} | 14px | 500 | 1.4 | 0.04em uppercase | Stat card metadata labels |

Principles

This system's hierarchy is carried almost entirely through weight and size, with color playing a secondary role. The jump from {typography.body-md} at 400 weight to {typography.display-xl} at 950 weight is among the most aggressive contrasts in contemporary web design — there is no intermediate "semibold" or "bold" step in the main reading hierarchy. This binary (regular vs. ultra-black) forces clear structural decisions: either something is body text or it's a headline.

Size scales exponentially: 23px → 64px → 118px. Each step roughly doubles the previous, creating a sense of dramatic crescendo toward the hero. Line heights remain relatively tight even at display sizes (112.1px leading on 118px type is ~0.95 ratio), which compresses the headline vertically and gives it density. Letter-spacing stays at normal throughout — no tracking adjustments, no negative kerning for headlines, no expanded caps. This is a deliberate choice to let Inter's built-in spacing do the work.

The {typography.label-stat} role is the only exception to the no-tracking rule, applying 0.04em letter-spacing with uppercase transform for the "ACTIVE SERVERS", "WEEKLY COMMAND USES" metadata beneath stat numbers. This micro-typographic detail signals data/metadata without introducing a new font family.

Note on Font Substitutes

Inter is available as a free Google Font (https://fonts.google.com/specimen/Inter), so no substitution is required for implementation. If you must substitute due to licensing constraints in a closed-source environment, use Plus Jakarta Sans as the closest match — it shares Inter's tall x-height, circular bowls, and excellent heavy-weight rendering. Define your font stack as:

--font-sans: 'Inter', 'Plus Jakarta Sans', ui-sans-serif, system-ui, -apple-system, sans-serif;

Layout

Spacing System

  • Base unit: 4px ({spacing.xxs}). All spacing values derive from this multiple or the 4px/8px grid convention.
  • Tokens: {spacing.xxs} 4px (icon gaps, tight internal padding) → {spacing.xs} 6px (badge internal padding) → {spacing.sm} 8px (button internal vertical) → {spacing.md} 16px (card padding horizontal, section gutters) → {spacing.lg} 24px (stat card internal padding, button gap) → {spacing.xl} 40px (inter-block spacing) → {spacing.xxl} 96px (below-hero breathing room) → {spacing.section} 120px (major section vertical rhythm) → {spacing.hero-top} 106px (hero top offset accounting for fixed nav).
  • Section padding (vertical): {spacing.section} (120px) — used between the hero band and the features/stats grid below.
  • Card internal padding: {spacing.lg} (24px) on all sides for stat cards ({component.stat-card}).
  • Gutters: {spacing.md} (16px) horizontal gutter on mobile, scaling to {spacing.lg} (24px) at desktop within the 1180px max-width constraint.

Grid & Container

The layout operates within a max-width of 1180px centered on viewport, with full-bleed bands for colored sections. The hero section uses a flexbox column centering pattern — content stacks vertically with items-center justify-center and min-h-[92vh]. Below the hero, the stats grid uses a responsive 4-column layout that collapses to 2-column on tablet and single-column on mobile.

There are three distinct density modes visible:

  1. Hero mode: Single-column centered, maximum whitespace, 92vh minimum height — editorial/expressive.
  2. Stats grid mode: 4 equal columns with consistent card sizing — dashboard/data-density.
  3. Navigation mode: Full-width fixed bar with distributed children (logo left, links center, actions right) — app-chrome density.

Whitespace Philosophy

Whitespace here is immersive rather than spacious. The system doesn't use white space to create "airy" luxury feeling; it uses deep dark space to create focus-tunnel isolation. The hero's 106px top padding ensures the headline clears the fixed nav with generous margin, while the 92vh minimum height forces the user to scroll to discover what lies beneath — a deliberate reveal pattern. Between components within the same band, gaps are functional ({spacing.lg}) rather than editorial ({spacing.section}). This suggests a product-first mindset where information density increases below the fold.

Header Architecture

┌─────────────────────────────────────────────────────────────────┐
│ [🍅 Logo]   Features  Timeline  Tutorials  Desktop  Community   │
│                                          ❤️ Support  [+ Add] [→Login] │
└─────────────────────────────────────────────────────────────────┘
              ↑ max-width: 1200px, mx-auto, px-6
              ↑ height: 72px (py-5 = 20px × 2 + 32px content)
              ↑ bg: transparent (fixed, transitions to blurred on scroll)

The navigation uses a distributed three-zone layout: logo zone left, navigation links center (hidden on mobile via hidden md:flex), action buttons right. The {component.nav-link} items use {typography.body-sm} at {colors.muted}, switching to {colors.ink} on active/hover. The two rightmost actions are {component.button-secondary-nav} ("Add Bot") and {component.button-primary-nav} ("Login"), sized smaller than hero CTAs.

Hero Section

┌─────────────────────────────────────────────────────────────────┐
│                                                                 │
│                    ┌──────────────────┐                         │
│                    │ 🟢 LIVE  Built..  │  ← {component.hero-badge}       │
│                    └──────────────────┘                         │
│                                                                 │
│                      PomoBot                                   │
│                   ← {typography.display-xl}, 118px, fw 950     │
│                                                                 │
│     Turn your Discord server into a focused study hub with...   │
│                          ↑ {typography.body-md}, 23px           │
│                                                                 │
│        ┌─────────────────────┐  ┌──────────────────────┐       │
│        │ + Add to Discord    │  │ See how it works      │       │
│        └─────────────────────┘  └──────────────────────┘       │
│            ↑ {component.button-primary}     ↑ {component.button-secondary}  │
│                                                                 │
│  ┌────────┐ ┌────────┐ ┌────────┐ ┌────────┐                   │
│  │ 580+   │ │ 42k+   │ │ 1.4k+  │ │ 900+   │                   │
│  │SERVERS │ │MEMBERS │ │ USERS  │ │CMDS    │                   │
│  └────────┘ └────────┘ └────────┘ └────────┘                   │
│       ↑ {component.stat-card} × 4, 4-col grid                  │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
         ↑ min-h-[92vh], px-6, pt-28(md:36), pb-16
         ↑ bg: absolute inset-0 {colors.canvas}
         ↑ content: relative, max-w-[1180px], mx-auto, center

Elevation & Depth

| Level | Treatment | Use | |---|---|---| | 0 — Base | Flat, no shadow, {colors.canvas} background | Page body, hero band | | 1 — Float | No shadow, {colors.surface-glass} (5% white) background, {colors.hairline} border | Secondary buttons ({component.button-secondary}) | | 2 — Elevated | {extensions.shadows.blurple-glow} (blurple 30%, 8px blur, 24px spread) | Primary buttons ({component.button-primary}), Login CTA | | 3 — Card | No shadow, {colors.surface-dark} (35% black) background, implicit depth via darkness | Stat cards ({component.stat-card}) | | 4 — Badge/Pill | No shadow, {colors.surface-elevated} (42% black) background | Hero live badge ({component.hero-badge}) | | 5 — Modal | {extensions.shadows.none} composite (25% black, 25px y, 50px blur) | Future modal/dropdown surfaces |

The elevation philosophy here is color-block over shadow for most surfaces. Because the canvas is already near-black, traditional drop shadows would be invisible. Instead, depth is communicated through opacity modulation of black and white layers — a card sits "above" the canvas because it's 35% black rather than 0%. The one exception to this rule is the primary button family, which uses a colored (blurple) ambient glow to signal interactability and brand affiliation. This glow is the single most expensive visual effect on the page and is therefore reserved for the highest-conversion element.

Decorative Depth

Behind the hero content, the screenshot reveals faint ghostly silhouettes — what appears to be a user profile card, progress bars, and activity widgets rendered at very low opacity (likely 3-6% white). These form an abstract "dashboard preview" wallpaper that gives texture to the canvas without competing with foreground content. These decorative elements use {colors.surface-subtle} tints and should be treated as illustrative background art, not interactive components.

Shapes

Border Radius Scale

| Token | Value | Use | |---|---|---| | {rounded.sm} | 6px | Small internal elements, tag corners | | {rounded.DEFAULT} / {rounded.md} | 12px | All buttons (primary, secondary, nav), default card radius | | {rounded.lg} | 16px | Stat cards ({component.stat-card}) | | {rounded.xl} | 24px | Large containers, image frames (if any) | | {rounded.pill} / {rounded.full} | 9999px | Hero badge ({component.hero-badge}), avatar placeholders |

The shape vocabulary is intentionally narrow: 12px handles 80% of cases, 16px gets the slightly friendlier stat cards, and pill is reserved for the single badge element. There are no sharp corners anywhere in the interface — even the smallest elements get at least 6px rounding. This consistency reinforces the approachable, consumer-product positioning despite the developer-tool subject matter.

Photography Geometry

No photography is present on this page. Imagery consists entirely of vector icons (Lucide), emoji (tomato logo, heart), and CSS-rendered decorative elements. Should photography be added in future iterations (team headshots, Discord screenshot previews), it should use {rounded.lg} (16px) corners to match the stat card language, with optional subtle {colors.hairline} borders to define edges against the dark canvas.

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-active}, {component.text-input-focus}); add hover styling at implementation time per your stack's conventions.

Buttons

{component.button-primary} — The hero-level call-to-action ("Add to Discord"). Uses a transparent background ({colors.surface}) with {colors.on-primary} white text at {typography.button-lg} (18px, weight 700). Bordered with {colors.hairline-strong} (white at 10%) at {rounded.DEFAULT} (12px). The defining characteristic is the {extensions.shadows.blurple-glow} shadow — a diffuse indigo halo that makes the button appear to emit light. Height locked at 56px for comfortable touch targets, padding 12px horizontal × 24px vertical. Appears alongside {component.button-secondary} in the hero CTA row.

{component.button-primary-nav} — Compact variant used in the top navigation for the "Login" action. Same transparent background, white text, and blurple glow treatment as the hero primary, but sized down to {typography.button} (14px) with tighter padding (8px × 20px) and no fixed height constraint. Shares the 12px radius. This size differential establishes visual hierarchy between the page's primary conversion action and secondary auth flow.

{component.button-secondary} — The "See how it works" companion CTA in the hero row, and "Add Bot" in the nav. Background is {colors.surface-glass} (5% white) giving it a faintly visible fill against the canvas. Text uses {colors.ink} at {typography.button-lg} weight 700. Border is {colors.hairline} (8% white) at 12px radius. No shadow — deliberately flat compared to the primary sibling to indicate lower priority. Same 56px height and 12px×24px padding as the primary for rhythmic pairing.

{component.button-secondary-nav} — Navigation-scale secondary button ("Add Bot"). Matches the hero secondary's glass background and ink-colored text, but at {typography.button} 14px scale with 8px×16px padding. Used for non-auth, non-primary conversion actions in the chrome.

Cards & Containers

{component.stat-card} — The four metric display cards at the bottom of the hero (580+ Active Servers, 42k+ Reachable Members, etc.). Background is {colors.surface-dark} (black at 35%) creating a visibly darker rectangle than the canvas. Text is pure {colors.on-primary} white at {typography.display-lg} (64px, weight 950) for the numeral, with {component.stat-label} beneath in {colors.muted} at the small uppercase tracked style. Rounded at {rounded.lg} (16px) — slightly softer than buttons to feel more like a content block than an interaction target. Internal padding is {spacing.lg} (24px) all around. Cards sit in a 4-column grid with {spacing.lg} gaps.

{component.hero-band} — The full-viewport hero section container. Background {colors.canvas} filling the entire area behind the absolutely-positioned content wrapper. Padding of {spacing.hero-top} (106px) top to clear the fixed navigation, {spacing.md} (16px) horizontal gutters, {spacing.xl} (40px) bottom. Contains the centered flex column of badge → headline → subhead → CTA row → stats grid.

{component.cta-row} — The horizontal container holding the primary and secondary CTA buttons. Uses {spacing.md} vertical padding to separate it from the hero subhead above and the stats grid below. Flex layout with {spacing.lg} (24px) gap between the two buttons.

Navigation

{component.top-nav} — The fixed header bar spanning full viewport width. Transparent background ({colors.surface}) that presumably gains a backdrop-filter blur on scroll (detected via transition classes). Height of 72px (from py-5: 20px × 2 + estimated 32px content). Text color {colors.ink} for active elements, {colors.muted} for inactive. Uses a 1200px inner max-width with 24px horizontal padding, distributing children into left (logo), center (links), and right (actions) zones.

{component.nav-link} — Individual navigation items (Features, Timeline, Tutorials, Desktop, Community). Transparent background, {colors.muted} text at {typography.body-sm} (16px, weight 400). Fully rounded ({rounded.full} / pill shape) though likely invisible until hover state applied. Hidden below md breakpoint.

{component.nav-link-active} — Active or hovered state of nav links, switching to {colors.ink} full brightness while maintaining other properties.

Signature Components

{component.hero-badge} — The "🟢 LIVE Built for Discord study servers →" pill positioned above the headline. Background is {colors.surface-elevated} (black at 42% opacity) making it distinctly darker than surrounding canvas. Text uses {colors.success} green for "LIVE" and {colors.caption} style (14px) for the rest. Fully pill-shaped ({rounded.pill} / 9999px) with compact 6px × 16px padding. Includes a chevron-right icon indicating click/tap behavior.

{component.hero-headline} — The "PomoBot" text itself, extracted as a conceptual component. {typography.display-xl} at 118px weight 950, pure white ({colors.on-primary}) against the canvas. Centered alignment. Line height tightly set to 112.1px (~0.95 ratio) keeping the headline compact despite its massive size.

{component.hero-subhead} — The descriptive paragraph beneath the headline. {typography.body-md} at 23px weight 400, using {colors.body} at 74% opacity — noticeably dimmer than the headline to force the eye to hierarchy. Line height of 37.95px (1.65 ratio) providing generous readability. Max-width likely constrained (not detected) to prevent overly long lines.

{component.stat-label} — The uppercase metadata text beneath each stat number ("ACTIVE SERVERS", "REACHABLE MEMBERS", etc.). {typography.label-stat} with 0.04em letter-spacing, 500 weight, 14px size, uppercase transform, in {colors.muted} color. Provides context for the large numerals without competing visually.

Do's and Don'ts

Do

  • Do use {typography.display-xl} at weight 950 for the single hero headline — this aggressive weight is the system's signature typographic move and should not be softened.
  • Do apply {extensions.shadows.blurple-glow} exclusively to primary CTAs ({component.button-primary}, {component.button-primary-nav}) — this blurple ambient shadow is the brand's visual "electricity."
  • Do reserve {colors.accent-blurple} (#5865f2) for links, glows, and status accents — never use it as a solid background fill on any component.
  • Do keep secondary buttons flat (no shadow) with {colors.surface-glass} backgrounds — the contrast between glowing primary and flat secondary is intentional priority signaling.
  • Do use {colors.surface-dark} (35% black) for stat cards and data containers — they should feel embedded in the canvas rather than floating above it.
  • Do maintain {spacing.hero-top} (106px) clearance above hero content when using a fixed navigation bar of 72px height.
  • Do apply {rounded.pill} only to the hero badge component — all other rounded elements stay in the 12–16px range.
  • Do use {typography.body-md} at 23px for all descriptive paragraphs — this larger-than-standard body size is part of the system's confident voice.
  • Do render the canvas at exactly {colors.canvas} (#07080d) — it is measurably bluer/darker than standard #111111 and this distinction matters for the overall atmosphere.
  • Do pair {component.button-primary} and {component.button-secondary} side-by-side with {spacing.lg} (24px) gap in CTA rows — their shared 56px height creates a unified control group.

Don't

  • Don't introduce intermediate font weights (600, 700) into the body/display hierarchy — the system operates on a binary of 400 (body) and 950 (display).
  • Don't replace the glassmorphic button backgrounds with solid color fills — the transparency is essential to the "floating UI" aesthetic.
  • Don't use {colors.ink} (#f0f2ff) interchangeably with {colors.on-primary} (#ffffff) — the former carries violet undertones and is for text-on-canvas; the latter is neutral white for text-on-dark-surfaces.
  • Don't expand the border-radius vocabulary beyond the six defined tokens — the current range (6px → 12px → 16px → 24px → pill) covers every observed case.
  • Don't add gradients to the hero background — the canvas is a flat {colors.canvas} fill with decorative ghost-layer elements, not a gradient wash.
  • Don't shrink the stat card numerals below {typography.display-lg} (64px) — their massive scale is what makes the social proof section impactful.
  • Don't remove the blurple glow from the Login button when implementing auth flows — it maintains visual continuity with the primary Add-to-Discord CTA.
  • Don't use {colors.accent-orange} or {colors.accent-green} as anything other than icon/status accent colors — they map to Discord's semantic palette and should stay in that role.
  • Don't increase line-height on display typography beyond 1.0–0.95x the font size — the tight leading is intentional for dense, monumental headlines.

Motion & Animation

Transition Tokens

--transition-base: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
--transition-color: color 0.15s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), border-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), outline-color 0.15s cubic-bezier(0.4, 0, 0.2, 1), text-decoration-color 0.15s cubic-bezier(0.4, 0, 0.2, 1);
--transition-fade: opacity 0.15s cubic-bezier(0.4, 0, 0.2, 1);
--transition-nav: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); /* detected on fixed nav */

The system uses a standard ease-out timing function (cubic-bezier(0.4, 0, 0.2, 1) — essentially ease-out) across all transitions. Duration splits into two tiers: 150ms for color/opacity changes (snappy, responsive) and 300ms for structural transforms (navigation scroll behavior, panel slides). The all keyword on the navigation transition suggests the entire bar (background, shadow, possibly backdrop-filter) morphs on scroll.

Keyframe Animations

  • spin — Standard rotation animation, likely applied to loading indicators or the tomato logo on auth redirect.
  • ping — Radial pulse/ring expansion, commonly used for notification dots or the "LIVE" badge pulse indicator.
  • pulse — Opacity/breathing oscillation, potentially for the live status dot or CTA attention-drawing.

These three keyframes are inherited from Tailwind's default animation library and suggest standard utility patterns rather than custom motion design.

Interaction Patterns

  • Navigation scroll transition: The fixed {component.top-nav} transitions from transparent to a blurred/solid background on scroll, using the 300ms ease-out curve. This is the most prominent motion event on the page.
  • Button hover lift: While hover states aren't documented, the blurple-glow shadow on {component.button-primary} suggests hover may intensify the shadow spread or opacity.
  • Focus ring expansion: Interactive elements likely gain a subtle outline or shadow expansion on keyboard focus, using the --transition-color timing.
  • Badge ping animation: The "LIVE" dot in {component.hero-badge} probably uses the ping keyframe for a pulsing presence indicator.
  • Logo opacity fade: The logo link has a detected hover:opacity-80 transition-opacity class, suggesting an 80% opacity reduction on hover.

Overall motion level is subtle — this is a static landing page with minimal choreography. Motion exists to reinforce interactivity (buttons, links, nav transformation) rather than to entertain.

Imagery Style

  • No photography present. The hero relies on typographic impact and decorative CSS ghost-layers rather than lifestyle imagery or product screenshots.
  • Decorative ghost layers: Behind the hero content, faint UI mockups (profile cards, progress bars, activity panels) are rendered at 3–6% white opacity against the canvas, creating an abstract "dashboard atmosphere" without distracting from the headline.
  • Icon-driven illustration: The stat area and badge use Lucide icons (flame, water droplet, trophy, checkmark) in {colors.accent-orange} and {colors.accent-green} as spot-color accents.
  • Emoji as brand mark: The tomato emoji (🍅) serves as the logo/app-icon, rendered at native resolution beside the "Pomo" wordmark.
  • Heart icon in nav: A pink/red heart (❤️ or Lucide Heart) precedes the "Support" link, adding a tiny warmth touch to the utilitarian navigation.
  • Color-treated icons: Icons use semantic Discord colors (green for success/life, orange for energy/fire, blurple for connection) rather than the ink color — this makes them pop against dark surfaces.
  • Future imagery direction: If screenshots or photos are added, they should follow the glassmorphic language — slight rounding ({rounded.lg}), possible subtle borders ({colors.hairline}), and no heavy shadows.

Icon System

  • Library: Lucide (detected via Tailwind class analysis and stroke characteristics).
  • Specific icons observed: Plus (add actions), ArrowRight/Login arrow (CTAs), ChevronRight (badge), Flame (fire/streak stat icon), Droplet (water/focus stat icon), Trophy (leaderboard icon), Target/bullseye (pets/activity icon), Heart (support nav item).
  • Treatment: Stroke-based icons (Lucide's default), sized at 18–24px for inline use, rendered in currentColor or explicit accent colors depending on context. The flame and droplet icons use {colors.accent-orange} and a blue tone respectively, while UI icons (plus, arrows, chevrons) inherit text color.
  • Alignment: Icons are vertically center-aligned with adjacent text, with consistent 8–12px gaps (using {spacing.sm} or {spacing.xs}).

Recommended Frontend Stack

- Framework:      Next.js 14+ (App Router detected via __next_f patterns in DOM)
- Styling:        Tailwind CSS v3.4+ (utility classes confirmed throughout)
- Fonts:          Google Fonts CDN → Inter (variable font recommended for weight range)
- Animation:      Tailwind built-in utilities (transition, animation props) + CSS custom properties
- Icons:          Lucide React (@lucide/react)
- Component lib:  None (custom components based on Tailwind primitives)

Responsive Behavior

Breakpoints

| Name | Width | Key Changes | |---|---|---| | Mobile | < 768px | Single-column everything; hamburger menu replaces nav links; stat cards stack vertically; CTA buttons go full-width stacked; hero padding reduces. | | Tablet | 768px – 1024px | Nav links appear; stat grid becomes 2-column; CTA buttons sit side-by-side; hero headline may reduce size slightly (not detected). | | Desktop | 1024px – 1440px | Full layout: 4-column stats, distributed nav, 1180px content max-width. | | Wide | > 1440px | Content remains constrained at 1180px/1200px centers; canvas extends to edges. |

Touch Targets

  • {component.button-primary}: 56px height × variable width — exceeds WCAG AAA 44×44 minimum comfortably.
  • {component.button-secondary}: 56px height × variable width — matches primary for paired rhythm.
  • {component.button-primary-nav}: ~40px height (8px padding × 2 + ~24px content) — meets AA 44px minimum if padded adequately.
  • {component.nav-link}: Inherited from nav height (~72px) — exceeds all minimums.
  • {component.stat-card}: Tap targets not critical (informational), but card area is well above minimums.

Collapsing Strategy

  • Navigation: Horizontal link list (Features, Timeline, etc.) hidden via hidden md:flex; replaced by a mobile hamburger button (md:hidden) with p-2 padding and {colors.muted} text color that shifts to white on hover.
  • Hero headline: {typography.display-xl} at 118px will require responsive scaling (likely via text-5xl md:text-7xl lg:text-[118px] Tailwind fluid pattern) to prevent overflow on narrow viewports.
  • Stat grid: Transitions from 4-column → 2-column (tablet) → 1-column (mobile) using Tailwind's responsive grid prefixes.
  • CTA buttons: On mobile, both {component.button-primary} and {component.button-secondary} expand to w-full with vertical stacking (flex-col); on sm: breakpoint and above they revert to sm:w-auto horizontal arrangement.
  • Hero padding: Vertical padding reduces from pt-28 md:pt-36 (112px → 144px) suggesting actually increases on desktop, with pb-16 (64px) constant bottom.

Image Behavior

  • Ghost-layer decorations: The background UI mockups behind the hero should likely hide or reduce opacity on mobile to save bandwidth and reduce cognitive load on small screens. Consider opacity-0 md:opacity-100 pattern.
  • Logo/icon sizing: The tomato emoji logo and Lucide icons should remain constant or scale subtly (avoid drastic size changes that break recognition).

Iteration Guide

  1. Build a landing page shell using Next.js App Router with Tailwind CSS v4. Initialize with the dark theme: set <html class="dark"> and ensure @layer base sets background-color: {colors.canvas} and color: {colors.ink} on body.
  2. Extract every design token from this DESIGN.md YAML frontmatter. Map them to Tailwind config under theme.extend.colors, theme.extend.fontSize, theme.extend.borderRadius, theme.extend.spacing, theme.extend.boxShadow, and theme.extend.transitionTimingFunction. Never hard-code a hex or pixel value that has a corresponding {token.path} reference.
  3. Implement components in order of visual hierarchy: {component.top-nav}{component.hero-band}{component.hero-badge}{component.hero-headline}{component.hero-subhead} → CTA row ({component.button-primary} + {component.button-secondary}) → stats grid ({component.stat-card} × 4).
  4. For each button, create both the default and nav-sized variants as documented. Add hover/active states using Tailwind's hover: and active: variants — the spec documents default and implies active; hover styling should lighten the glass background or intensify the blurple glow per your judgment.
  5. Apply {extensions.shadows.blurple-glow} to primary buttons via shadow-[rgba(88,101,242,0.3)_0px_8px_24px_0px] Tailwind arbitrary value syntax. Ensure this shadow is only on .btn-primary variants.
  6. Set up the fixed navigation with fixed top-0 w-full z-50 transition-all duration-300 and implement a scroll listener (via useEffect + window.scrollY) to toggle a background class (e.g., bg-{canvas}/80 backdrop-blur-xl) after scrolling past the hero threshold.
  7. Configure Inter from Google Fonts with the variable font syntax to support weights 400, 700, 900, and 950. Define CSS custom properties: --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif; and apply to fontFamily in Tailwind config.
  8. Build the responsive grid for stat cards using grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6. Each card uses {component.stat-card} styling with the large {typography.display-lg} numeral and {typography.label-stat} uppercase metadata.
  9. Run accessibility checks: verify all text meets WCAG AA contrast ratios against {colors.canvas} (the {colors.ink} on #07080d passes easily; check {colors.body} at 74% opacity). Ensure the 56px button heights meet touch-target guidelines.
  10. Test the "ghost layer" decorative background: create absolutely-positioned divs with {colors.surface-subtle} backgrounds containing faint UI-shaped rectangles. Use pointer-events-none and consider select-none to prevent interaction interference.

Font Setup:

Add to <head> or layout.tsx:

<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=Inter:wght@400;700;900;950&display=swap" rel="stylesheet" />

CSS variables to define in globals.css or Tailwind config:

:root {
  --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --color-canvas: #07080d;
  --color-ink: #f0f2ff;
  /* ... remaining tokens mapped from frontmatter */
}

Known Gaps

  • Hover states on all interactive elements: Per the no-hover policy, button hover, link hover, nav-item hover, and card hover styles are inferred rather than extracted. Implementation should add these based on conventional dark-mode patterns (lighten glass backgrounds, intensify glows, shift text opacity).
  • Loading/auth redirection states: The "Add to Discord" and "Login" buttons initiate OAuth flows, but loading spinners, disabled states during redirect, and error-toasts are not visible in the static screenshot.
  • Scroll-triggered navigation background: The nav has transition-all duration-300 classes suggesting it transforms on scroll (likely gaining a backdrop-blur or semi-transparent fill), but the scrolled state is not captured.
  • Mobile navigation drawer contents: The hamburger menu button exists for md:hidden but the drawer/overlay it triggers is absent from the above-fold markup.
  • Below-fold sections: Features, Timeline, Tutorials, Desktop preview, Community section, and footer are referenced in navigation but fall outside the captured viewport. Their component structures, layouts, and potential sub-system dialects (e.g., pricing table, feature comparison) are unknown.
  • Form validation states: No input fields were detected in the extracted CSS, so focus rings, error borders, success checkmarks, and helper text styling are undocumented.
  • Dashboard/authenticated views: The entire post-login experience (server configuration, leaderboard, garden visualization) is outside scope — this DESIGN.md covers only the marketing landing page.
  • Exact oklab color reproduction: Several surface colors use oklab() color function (e.g., {colors.surface-elevated}). Some older browsers don't support oklab natively; consider providing sRGB fallbacks or confirming target browser support before production deployment.
  • Ping/pulse animation application points: The ping, pulse, and spin keyframes are declared but their binding to specific DOM elements (live badge dot? logo spinner?) is inferred, not confirmed via animation-name attributes.