23 KiB
WorkRoot IT Solutions — Design System
Version: 1.0.0 Last Updated: 2026-03-21 Stack: Astro v4 + Tailwind CSS v3 + Plus Jakarta Sans + JetBrains Mono
Table of Contents
- Design Principles
- Color Palette
- Typography Scale
- Spacing System
- Elevation & Shadows
- Border Radius
- Animation & Motion
- Button Styles
- Form Elements
- Component Patterns
- Layout System
- Icon System
- Accessibility
- Implementation Notes
1. Design Principles
Brand Identity
WorkRoot IT Solutions is a professional B2B tech agency targeting enterprise and startup clients. The visual language must communicate:
| Principle | Application |
|---|---|
| Trust | Consistent, predictable layouts; clear hierarchy |
| Capability | Polished micro-interactions; precise typography |
| Innovation | Gradient accents; modern glassmorphism-lite |
| Clarity | Generous whitespace; high contrast ratios |
Design Decision Framework
- Mobile-first — All breakpoints start at
smand scale up - Performance-first — Prefer CSS-only animations over JS
- Accessibility-first — WCAG AA minimum for all interactive elements
- Consistency — Use design tokens, never magic numbers
2. Color Palette
Primary — Cyan (#0891b2)
The core action color. Used for CTAs, links, highlights, icon backgrounds, focus rings.
| Token | Value | Usage |
|---|---|---|
primary-50 |
#ecfeff |
Subtle tinted backgrounds, badge backgrounds |
primary-100 |
#cffafe |
Hover backgrounds on light surfaces |
primary-200 |
#a5f3fc |
— |
primary-300 |
#67e8f9 |
Light mode decorative elements |
primary-400 |
#22d3ee |
Focus rings, gradient midpoints |
primary-500 / DEFAULT |
#0891b2 |
Main brand color — buttons, icons |
primary-600 |
#0e7490 |
Button hover states |
primary-700 |
#155e75 |
Dark text on light backgrounds |
primary-800 |
#164e63 |
— |
primary-900 |
#083344 |
Dark sections / hero gradient end |
Secondary — Slate (#1e293b)
Neutral palette for text, backgrounds, borders. The backbone of the design.
| Token | Value | Usage |
|---|---|---|
secondary-50 |
#f8fafc |
Page backgrounds, subtle section backgrounds |
secondary-100 |
#f1f5f9 |
Card backgrounds, input backgrounds |
secondary-200 |
#e2e8f0 |
Borders, dividers |
secondary-300 |
#cbd5e1 |
Disabled states, placeholder text |
secondary-400 |
#94a3b8 |
Muted text, icons |
secondary-500 |
#64748b |
Secondary text |
secondary-600 |
#475569 |
Body text on light backgrounds |
secondary-700 |
#334155 |
Strong body text |
secondary-800 / DEFAULT |
#1e293b |
Main text color |
secondary-900 |
#0f172a |
Headings, hero/CTA dark sections |
Accent — Amber (#f59e0b)
Used sparingly for trust signals, testimonials, star ratings, and call-out badges.
| Token | Value | Usage |
|---|---|---|
accent-50 |
#fffbeb |
Badge backgrounds (testimonials, stats) |
accent-400 |
#fbbf24 |
Star ratings, gradient endpoints |
accent-500 / DEFAULT |
#f59e0b |
Accent color — stars, highlights |
accent-600 |
#d97706 |
Accent button hover |
accent-700 |
#b45309 |
Accent text on light backgrounds |
Semantic Colors (Tailwind defaults)
| Purpose | Color | Token |
|---|---|---|
| Error/Danger | Red 500 | text-red-500, border-red-500 |
| Success | Green 500 | bg-green-500 (toast) |
| Warning | Amber (use accent) | text-accent-600 |
| Info | Primary | bg-primary-50 text-primary-700 |
Color Combinations — Key Patterns
Dark Hero Sections:
Background: bg-gradient-to-br from-secondary-900 via-secondary-800 to-primary-900
Text: text-white / text-secondary-200 / text-secondary-300
Badges: bg-primary-400/20 text-primary-300
Light Sections:
Background: bg-white
Alternate: bg-secondary-50 / bg-gradient-to-b from-secondary-50 to-white
Text: text-secondary-900 (headings) / text-secondary-600 (body)
Badges: bg-primary-50 text-primary-700
Cards:
Background: bg-white rounded-2xl/3xl border-2 border-secondary-100
Hover: hover:border-primary/30 hover:shadow-2xl
CTA Dark Sections:
Background: bg-gradient-to-br from-secondary-900 via-primary-900 to-primary-800
3. Typography Scale
Font Families
| Role | Font | Weights | Usage |
|---|---|---|---|
| Display / Body | Plus Jakarta Sans | 200–800 | All UI text, headings |
| Monospace | JetBrains Mono | 100–800 | Code blocks, pre elements |
Load via Google Fonts:
https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,200..800;1,200..800&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap
Type Scale
| Step | Size (Mobile) | Size (Desktop) | Weight | Use Case |
|---|---|---|---|---|
| Display XL | text-5xl (3rem) |
text-8xl (6rem) |
font-bold |
Hero headlines |
| Display LG | text-4xl (2.25rem) |
text-7xl (4.5rem) |
font-bold |
Sub-hero |
| H1 | text-4xl |
text-6xl |
font-bold |
Page titles |
| H2 | text-3xl / text-4xl |
text-5xl |
font-bold |
Section titles |
| H3 | text-2xl |
text-2xl |
font-bold |
Card titles |
| H4 | text-xl |
text-xl |
font-bold / font-semibold |
Subheadings |
| Body LG | text-xl |
text-2xl |
font-normal |
Lead paragraphs |
| Body | text-base |
text-lg |
font-normal |
Standard body |
| Body SM | text-sm |
text-base |
font-normal |
Supporting text |
| Caption | text-xs |
text-sm |
font-medium |
Labels, badges |
| Code | text-sm |
text-sm |
font-normal |
Inline code |
Responsive Typography Patterns
<!-- Hero headline -->
<h1 class="text-5xl sm:text-6xl lg:text-7xl xl:text-8xl font-bold leading-[1.1] tracking-tight">
<!-- Section heading -->
<h2 class="text-4xl sm:text-5xl font-bold text-secondary-900">
<!-- Card heading -->
<h3 class="text-2xl font-bold text-secondary-900">
<!-- Lead paragraph -->
<p class="text-xl sm:text-2xl text-secondary-200 leading-relaxed">
<!-- Body paragraph -->
<p class="text-lg text-secondary-600 leading-relaxed">
<!-- Badge / Label -->
<span class="text-sm font-bold uppercase tracking-wider">
Line Heights
| Context | Class | Value |
|---|---|---|
| Headings | leading-[1.1] or leading-tight |
1.1–1.25 |
| Subheadings | leading-snug |
1.375 |
| Body | leading-relaxed |
1.625 |
| Long-form prose | leading-loose |
2 |
4. Spacing System
Tailwind default 4px base unit. Key spacing values in use:
| Scale | px | rem | Use Case |
|---|---|---|---|
| 1 | 4px | 0.25rem | Micro gaps |
| 2 | 8px | 0.5rem | Icon-to-text gaps |
| 3 | 12px | 0.75rem | Tight form elements |
| 4 | 16px | 1rem | Standard gaps, padding |
| 5 | 20px | 1.25rem | — |
| 6 | 24px | 1.5rem | Section sub-gaps |
| 8 | 32px | 2rem | Card padding |
| 10 | 40px | 2.5rem | Large card padding |
| 12 | 48px | 3rem | CTA button padding |
| 16 | 64px | 4rem | — |
| 20 | 80px | 5rem | Section padding (mobile) |
| 24 | 96px | 6rem | Standard section padding |
Section Padding Convention
<!-- Standard section -->
<section class="py-24 bg-white">
<!-- Compact section -->
<section class="py-16 bg-secondary-50">
<!-- Hero section -->
<section class="min-h-screen py-24">
Container
<div class="container-wrapper">
<!-- = mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 -->
5. Elevation & Shadows
| Level | Class | Use Case |
|---|---|---|
| 0 — Flat | none | Form inputs (unfocused) |
| 1 — Low | shadow-sm |
Subtle card lift |
| 2 — Medium | shadow-lg |
Icon containers, info cards |
| 3 — High | shadow-xl |
Service cards, large icons |
| 4 — Very High | shadow-2xl |
Card hover states, modals |
| Brand Shadow | shadow-2xl shadow-primary/30 |
Primary button hover |
Shadow on Hover Pattern
<div class="shadow-lg hover:shadow-2xl transition-all duration-500">
6. Border Radius
| Scale | Class | px | Use Case |
|---|---|---|---|
| Small | rounded-lg |
8px | Form inputs, small buttons, tags |
| Medium | rounded-xl |
12px | Buttons, small cards |
| Large | rounded-2xl |
16px | Cards, panels, badges |
| XL | rounded-3xl |
24px | Large cards, testimonial blocks |
| Full | rounded-full |
9999px | Pills, avatar circles, dot indicators |
7. Animation & Motion
Keyframes Defined in Pages
/* Entrance animations (page-level) */
@keyframes slide-up { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: translateY(0); } }
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes pulse-slow { 0%, 100% { opacity: 0.4; } 50% { opacity: 0.6; } }
@keyframes pulse-slower { 0%, 100% { opacity: 0.2; } 50% { opacity: 0.4; } }
Animation Classes
| Class | Duration | Use Case |
|---|---|---|
animate-slide-up |
0.8s | Hero text entrance |
animate-fade-in |
0.8s | Scroll indicator |
animate-pulse-slow |
4s loop | Decorative blobs |
animate-pulse-slower |
6s loop | Secondary blobs |
animate-bounce |
Tailwind | Scroll indicators |
animate-spin |
Tailwind | Loading spinners |
Transition Conventions
<!-- Standard interactive transition -->
transition-all duration-300
<!-- Smooth card hover -->
transition-all duration-500
<!-- Color-only transition -->
transition-colors duration-200
<!-- Transform-only -->
transition-transform duration-300
Stagger Pattern (hero entrance)
<span class="opacity-0 animate-slide-up" style="animation-delay: 0.2s;">Line 1</span>
<span class="opacity-0 animate-slide-up" style="animation-delay: 0.4s;">Line 2</span>
Reduced Motion
All animations must respect prefers-reduced-motion:
@media (prefers-reduced-motion: reduce) {
.animate-slide-up, .animate-fade-in { animation: none; opacity: 1; }
}
8. Button Styles
Button System
Primary (.btn-primary)
bg-primary text-white rounded-lg px-6 py-3
hover: bg-primary-600
focus: ring-2 ring-primary-400 ring-offset-2
Use for: Main CTAs, one per section maximum.
Secondary (.btn-secondary)
border-2 border-secondary bg-transparent text-secondary rounded-lg px-6 py-3
hover: bg-secondary text-white
focus: ring-2 ring-secondary-400 ring-offset-2
Use for: Paired with primary, less prominent actions.
Accent (.btn-accent)
bg-accent text-white rounded-lg px-6 py-3
hover: bg-accent-600
focus: ring-2 ring-accent-400 ring-offset-2
Use for: Highlights, promotional actions (use rarely).
Hero CTA (inline, large)
<!-- Primary hero button -->
<a class="rounded-xl bg-gradient-to-r from-primary-500 to-primary-600 px-10 py-5 text-lg font-bold text-white
hover:shadow-2xl hover:shadow-primary/50 hover:scale-105
focus:ring-2 focus:ring-primary-400 focus:ring-offset-2 focus:ring-offset-secondary-900">
<!-- Ghost hero button (dark bg) -->
<a class="rounded-xl border-2 border-white/30 bg-white/5 backdrop-blur-sm px-10 py-5 text-lg font-bold text-white
hover:bg-white/10 hover:border-white/50">
<!-- Inverse (white button on dark bg) -->
<a class="rounded-xl bg-white px-10 py-5 text-lg font-bold text-secondary-900
hover:shadow-2xl hover:scale-105">
Button Sizes
| Size | Padding | Text | Use Case |
|---|---|---|---|
| SM | px-4 py-2 |
text-sm |
Inline, compact |
| MD (default) | px-6 py-3 |
text-base |
Standard actions |
| LG | px-8 py-4 |
text-lg |
Section CTAs |
| XL | px-10 py-5 |
text-lg font-bold |
Hero CTAs |
| Full | w-full py-4 px-6 |
text-base font-semibold |
Form submit |
9. Form Elements
Base Input Style
<input class="w-full px-4 py-3 rounded-lg border border-secondary-300
focus:border-primary focus:ring-2 focus:ring-primary/20
transition-colors duration-200
text-secondary-900 placeholder-secondary-400">
Error State
<input class="border-red-500"> <!-- Applied via JS when invalid -->
<p class="mt-1 text-sm text-red-500 hidden" data-error="fieldname">Error message</p>
Label
<label class="block text-sm font-medium text-secondary-700 mb-2">
Field Name <span class="text-red-500">*</span>
</label>
Select
<select class="w-full px-4 py-3 rounded-lg border border-secondary-300
focus:border-primary focus:ring-2 focus:ring-primary/20
transition-colors duration-200 text-secondary-900 bg-white">
Textarea
<textarea class="w-full px-4 py-3 rounded-lg border border-secondary-300
focus:border-primary focus:ring-2 focus:ring-primary/20
transition-colors duration-200
text-secondary-900 placeholder-secondary-400 resize-none">
Form Container
<div class="bg-secondary-50 rounded-2xl p-8 lg:p-10">
Submit Button (full-width)
<button type="submit"
class="w-full py-4 px-6 bg-gradient-to-r from-primary to-primary-600
text-white font-semibold rounded-lg
hover:from-primary-600 hover:to-primary-700
focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2
transition-all duration-200 flex items-center justify-center gap-2">
10. Component Patterns
Section Header (Reusable Pattern)
<div class="text-center max-w-3xl mx-auto mb-20">
<!-- Badge / eyebrow label -->
<span class="inline-block px-4 py-2 rounded-full bg-primary-50 text-primary-700
text-sm font-bold uppercase tracking-wider mb-4">
Section Label
</span>
<!-- Heading -->
<h2 class="text-4xl sm:text-5xl font-bold text-secondary-900 mb-6">Section Title</h2>
<!-- Subheading -->
<p class="text-xl text-secondary-600">Supporting description text.</p>
</div>
Badge variants:
- Light section:
bg-primary-50 text-primary-700 - Dark section:
bg-primary-400/20 text-primary-300 - Accent:
bg-accent-50 text-accent-700
Card Patterns
Feature Card
<div class="group relative bg-gradient-to-br from-secondary-50 to-white
rounded-2xl p-8 border border-secondary-100
hover:border-primary/30 hover:shadow-2xl
transition-all duration-500 hover:-translate-y-2">
<!-- Icon container -->
<div class="w-16 h-16 rounded-2xl bg-gradient-to-br from-primary-500 to-primary-600
flex items-center justify-center mb-6
group-hover:scale-110 group-hover:rotate-6
transition-all duration-500 shadow-lg">
<!-- SVG icon -->
</div>
<h3 class="text-2xl font-bold text-secondary-900 mb-3">Title</h3>
<p class="text-secondary-600 leading-relaxed">Description</p>
</div>
Service Card (larger)
<div class="group relative bg-white rounded-3xl p-10
shadow-lg border-2 border-secondary-100
hover:border-primary-400 hover:shadow-2xl
transition-all duration-500 overflow-hidden">
Contact Info Card
<div class="bg-secondary-50 rounded-xl p-6 hover:shadow-lg transition-shadow duration-300">
Icon Container Sizes
| Size | Classes | Pixel Size |
|---|---|---|
| SM | w-12 h-12 rounded-lg |
48px |
| MD | w-16 h-16 rounded-2xl |
64px |
| LG | w-20 h-20 rounded-2xl |
80px |
| XL | w-24 h-24 rounded-2xl |
96px |
All icon containers use: bg-gradient-to-br from-primary-500 to-primary-600 flex items-center justify-center shadow-lg
Section Badge / Eyebrow
<!-- Light backgrounds -->
<span class="inline-block px-4 py-2 rounded-full bg-primary-50 text-primary-700
text-sm font-bold uppercase tracking-wider mb-4">
Label
</span>
<!-- Dark backgrounds -->
<span class="inline-block px-4 py-2 rounded-full bg-primary-400/20 text-primary-300
text-sm font-bold uppercase tracking-wider mb-4">
Label
</span>
Toast Notification
<!-- Success -->
<div class="px-6 py-4 rounded-lg shadow-lg bg-green-500 text-white flex items-center gap-3">
<!-- Error -->
<div class="px-6 py-4 rounded-lg shadow-lg bg-red-500 text-white flex items-center gap-3">
Positioned: fixed bottom-4 right-4 z-50 flex flex-col gap-3
Avatar / Initials
<div class="w-16 h-16 rounded-full bg-gradient-to-br from-primary-500 to-primary-600
flex items-center justify-center text-white font-bold text-xl shadow-lg">
AB
</div>
Star Rating
<div class="flex gap-1">
<svg class="w-6 h-6 text-accent-500" fill="currentColor" viewBox="0 0 20 20">
<!-- star path -->
</svg>
</div>
Feature List Item
<li class="flex items-center text-secondary-700">
<svg class="w-5 h-5 text-primary-500 mr-3 flex-shrink-0" fill="currentColor" viewBox="0 0 20 20">
<!-- checkmark path -->
</svg>
<span class="font-medium">Feature text</span>
</li>
Connecting Step Line (horizontal)
<!-- Only visible on lg+ screens -->
<div class="hidden lg:block absolute top-20 left-[60%] w-full h-0.5
bg-gradient-to-r from-primary-500/50 to-transparent">
</div>
11. Layout System
Breakpoints (Tailwind defaults)
| Name | Min Width | Use Case |
|---|---|---|
sm |
640px | Mobile landscape |
md |
768px | Tablets |
lg |
1024px | Desktop nav shows |
xl |
1280px | Wide layouts |
2xl |
1536px | Ultra-wide |
Grid Patterns
<!-- 4-col features (1→2→4) -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<!-- 2-col services (1→2) -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-6xl mx-auto">
<!-- 2-col stats, 4-col on desktop -->
<div class="grid grid-cols-2 lg:grid-cols-4 gap-8">
<!-- Two-column with content (2/5 + 3/5 ratio) -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-16 items-start">
<!-- Footer 4-column (1→2→4) -->
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8">
Max Width Containers
| Container | Class | Width | Use Case |
|---|---|---|---|
| Standard | max-w-7xl |
1280px | Main content |
| Content | max-w-5xl |
1024px | Hero content |
| Prose | max-w-3xl |
768px | Section headers, descriptions |
| Narrow | max-w-2xl |
672px | Modal-width content |
Section Background Alternation
Section 1 (Hero): dark gradient
Section 2: bg-white
Section 3: bg-gradient-to-b from-secondary-50 to-white
Section 4: dark gradient (processes, CTAs)
Section 5: bg-white
Section 6: bg-gradient-to-b from-secondary-50 to-white
Avoid two consecutive dark sections, or two identical background sections.
12. Icon System
All icons are custom inline SVGs from Heroicons v2 outline style:
- Stroke:
stroke="currentColor"(inherits text color) - ViewBox:
0 0 24 24 - Stroke Width:
stroke-width="2"(default) orstroke-width="2.5"(bold emphasis) - Sizes:
w-5 h-5(inline),w-6 h-6(medium),w-8 h-8(card icons),w-10 h-10(large cards)
No icon library dependency — all SVGs are inline for performance.
13. Accessibility
Focus Rings
<!-- Default pattern -->
focus:outline-none focus:ring-2 focus:ring-primary-400 focus:ring-offset-2
<!-- On dark backgrounds -->
focus:ring-2 focus:ring-white/50 focus:ring-offset-2 focus:ring-offset-secondary-900
ARIA Patterns in Use
aria-current="page"— active nav linksaria-expanded— accordion/hamburger statesaria-label— icon-only buttonsaria-hidden="true"— decorative elementsaria-modal="true"— mobile menu overlayrole="menubar"/role="menuitem"— navigation.sr-only— screen-reader-only text
Color Contrast Requirements
- Normal text: 4.5:1 minimum
- Large text (18px+ bold): 3:1 minimum
- Interactive states: 3:1 minimum for UI components
Verified Contrast Pairs
| Text | Background | Ratio | Status |
|---|---|---|---|
secondary-800 (#1e293b) |
white | ~13:1 | ✅ PASS |
secondary-600 (#475569) |
white | ~7:1 | ✅ PASS |
secondary-300 (#cbd5e1) |
secondary-900 |
~4.6:1 | ✅ PASS |
primary-700 (#155e75) |
primary-50 |
~5.2:1 | ✅ PASS |
| white | primary-500 (#0891b2) |
~4.6:1 | ✅ PASS |
14. Implementation Notes
File Structure
src/
styles/
global.css # Base styles, CSS variables, component classes
components/
Header.astro # Sticky nav, mobile hamburger
Footer.astro # Dark footer, newsletter
SEO.astro # Meta tags + JSON-LD
OptimizedImage.astro # WebP with lazy load
LazyImage.astro # Lazy load wrapper
ui/
Badge.astro # Eyebrow/label badges [NEW]
Card.astro # Card wrapper [NEW]
SectionHeader.astro # Section header [NEW]
layouts/
BaseLayout.astro # HTML shell + Header + Footer
pages/
index.astro
about.astro
services.astro
portfolio.astro
contact.astro
tailwind.config.mjs # Extended color/font tokens
Adding New Design Tokens
- Add color values to
tailwind.config.mjsundertheme.extend.colors - Add CSS variables to
global.cssfor non-Tailwind usage - Document in this file under the appropriate section
When NOT to Use @apply
Per Tailwind v3 best practices, avoid @apply for:
- One-off utility combinations (write inline classes)
- Responsive variants (handle in JSX/Astro template)
Use @apply only for globally-reused component classes like .btn-primary, .container-wrapper.
CSS Custom Properties (Available)
The following CSS variables are defined in global.css:
--color-primary: #0891b2;
--color-primary-dark: #0e7490;
--color-secondary: #1e293b;
--color-accent: #f59e0b;
--color-surface: #f8fafc;
--color-border: #e2e8f0;
--color-text-primary: #1e293b;
--color-text-secondary: #475569;
--color-text-muted: #94a3b8;
--font-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
--radius-sm: 0.5rem;
--radius-md: 0.75rem;
--radius-lg: 1rem;
--radius-xl: 1.5rem;
--radius-full: 9999px;
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
--transition-fast: 150ms ease;
--transition-base: 200ms ease;
--transition-slow: 300ms ease;
--transition-slower: 500ms ease;
This document is the single source of truth for the WorkRoot IT Solutions design system. All UI decisions should reference this guide.