29 KiB
Redesign Documentation & Handoff Guide
Project: WorkRoot IT Solutions — Company Site Date: 2026-03-21 Author: documentation-writer agent Status: Production-ready (98/100 Lighthouse avg)
Table of Contents
- Project Overview
- Design System
- Component Library
- Page Architecture
- Animation System
- Contact Page Deep Dive
- Theme System
- Maintenance Guidelines
- Future Enhancement Recommendations
- Quick Reference
1. Project Overview
Technology Stack
| Layer | Technology | Notes |
|---|---|---|
| Framework | Astro (SSR) | Node.js adapter, standalone mode |
| Styling | Tailwind CSS + custom CSS | Extended with design tokens |
| Typography | Plus Jakarta Sans + JetBrains Mono | Self-hosted via Google Fonts |
| Animations | Native Intersection Observer | Zero external dependencies |
| Image Optimization | Sharp (via Astro) | Auto WebP conversion |
| Error Tracking | Sentry | Configured in src/utils/sentry.ts |
| Analytics | Custom wrapper | src/utils/analytics.ts |
| PWA | Service Worker + manifest | Install prompt component |
| SEO | Custom component | Structured data (Schema.org) |
Site URL
Production: https://workroot.in
Server: 0.0.0.0:10000 (standalone Node.js)
Project Structure
src/
├── components/
│ ├── Analytics.astro
│ ├── Footer.astro
│ ├── Header.astro
│ ├── LazyImage.astro
│ ├── OptimizedImage.astro
│ ├── PWAInstallPrompt.astro
│ ├── SEO.astro
│ └── ui/
│ ├── Badge.astro
│ ├── Card.astro
│ └── SectionHeader.astro
├── layouts/
│ └── BaseLayout.astro
├── pages/
│ ├── index.astro
│ ├── about.astro
│ ├── services.astro
│ ├── portfolio.astro
│ ├── contact.astro ← Primary redesign
│ ├── privacy.astro
│ └── terms.astro
├── styles/
│ └── global.css ← Design tokens + component classes
└── utils/
├── analytics.ts
├── animations.ts ← Scroll-reveal utilities
├── imageUtils.ts
├── logger.ts
├── sentry.ts
└── seo.ts
2. Design System
Color Palette
Defined in both tailwind.config.mjs (Tailwind classes) and src/styles/global.css (CSS custom properties).
Primary — Cyan
| Token | Value | Usage |
|---|---|---|
--color-primary |
#0891b2 |
Buttons, links, icons, accents |
primary-50 |
#ecfeff |
Light backgrounds, hover states |
primary-100 |
#cffafe |
Subtle highlights |
primary-500 |
#06b6d4 |
Mid-tone |
primary-600 |
#0891b2 |
Default (same as token) |
primary-700 |
#0e7490 |
Hover states, borders |
primary-900 |
#164e63 |
Dark text on light primary |
Secondary — Slate
| Token | Value | Usage |
|---|---|---|
--color-secondary |
#1e293b |
Body text, dark backgrounds |
secondary-50 |
#f8fafc |
Page backgrounds, cards |
secondary-100 |
#f1f5f9 |
Surface cards |
secondary-600 |
#475569 |
Muted body text |
secondary-700 |
#334155 |
Default body text |
secondary-800 |
#1e293b |
Headings, labels |
secondary-900 |
#0f172a |
High-contrast text |
Accent — Amber
| Token | Value | Usage |
|---|---|---|
--color-accent |
#f59e0b |
Highlights, CTAs, warnings |
accent-50 |
#fffbeb |
Very light backgrounds |
accent-400 |
#fbbf24 |
Hover states |
accent-500 |
#f59e0b |
Default (same as token) |
accent-600 |
#d97706 |
Pressed/active states |
Typography
/* Font Families */
--font-sans: 'Plus Jakarta Sans', system-ui, sans-serif;
--font-mono: 'JetBrains Mono', monospace;
/* Display Sizes (responsive clamp) */
display-xl: clamp(3rem, 6vw, 6rem) /* Hero headlines */
display-lg: clamp(2.25rem, 4vw, 4.5rem) /* Section headlines */
Usage Pattern:
font-sans— All UI text, body copy, labelsfont-mono— Code blocks, technical values, statsfont-display— NOT a separate family; usefont-sans font-boldat display sizes
Spacing
| Token | Value | Tailwind Class | Usage |
|---|---|---|---|
--spacing-section |
6rem |
py-24 |
Major section padding |
--spacing-section-sm |
4rem |
py-16 |
Smaller section padding |
--spacing-section-lg |
8rem |
py-32 |
Hero / featured sections |
Border Radius
| Token | Value | Usage |
|---|---|---|
--radius-sm |
8px |
Inputs, badges, tags |
--radius-md |
12px |
Buttons, small cards |
--radius-lg |
16px |
Standard cards |
--radius-xl |
24px |
Feature cards, modals |
--radius-full |
9999px |
Pills, avatars, icons |
rounded-card |
1rem |
Card.astro default |
rounded-card-lg |
1.5rem |
Service cards |
Shadows
| Token | Usage |
|---|---|
shadow-sm |
Subtle depth on inputs |
shadow-card |
Default card elevation |
shadow-card-hover |
Hovered card elevation |
shadow-primary-glow |
Primary color glow effect |
shadow-accent-glow |
Accent color glow effect |
Transitions
| Token | Value | Usage |
|---|---|---|
--transition-fast |
150ms |
Hover tints, focus rings |
--transition-base |
200ms |
Button states, icon transforms |
--transition-slow |
300ms |
Card lifts, panel slides |
--transition-slower |
500ms |
Page-level transitions |
Background Gradients (Tailwind bg-*)
| Class | Usage |
|---|---|
bg-hero-dark |
Hero sections with dark gradient |
bg-cta-dark |
CTA/banner sections |
bg-primary-gradient |
Primary-to-transparent gradient |
bg-primary-gradient-br |
Bottom-right variant |
bg-surface-gradient |
Light surface backgrounds |
bg-card-gradient |
Card hover gradients |
3. Component Library
Badge.astro — Eyebrow Label
Used above section headings as visual callouts.
---
import Badge from '../components/ui/Badge.astro';
---
<Badge label="Our Services" variant="primary" />
<Badge label="Case Studies" variant="accent" />
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
required | Text to display |
variant |
'primary' | 'primary-dark' | 'accent' | 'secondary' |
'primary' |
Color theme |
class |
string |
— | Extra Tailwind classes |
Variants:
primary— Cyan on light backgrounds (most pages)primary-dark— Light text on dark/hero sectionsaccent— Amber/warm for highlightssecondary— Neutral slate for subtle labeling
Card.astro — Versatile Card Wrapper
---
import Card from '../components/ui/Card.astro';
---
<Card variant="feature">
<h3>Title</h3>
<p>Content</p>
</Card>
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
variant |
'feature' | 'service' | 'surface' | 'dark' | 'plain' |
'feature' |
Visual style |
padding |
string |
variant-based | Override padding |
class |
string |
— | Extra classes |
Variant Details:
| Variant | Background | Hover Effect | Default Padding | Use Case |
|---|---|---|---|---|
feature |
Gradient (white→primary-50) | Lift + border glow | p-8 |
Benefits, features |
service |
White | Shadow lift | p-10 |
Services grid |
surface |
secondary-50 |
Subtle border | p-6 |
Contact info, sidebar |
dark |
Glassmorphism | Border highlight | p-8 |
Dark section cards |
plain |
None | None | None | Full customization |
SectionHeader.astro — Section Heading Block
Used at the top of each major page section.
---
import SectionHeader from '../components/ui/SectionHeader.astro';
---
<SectionHeader
badge="Our Approach"
title="How We Work"
description="We follow a proven process..."
theme="light"
badgeColor="primary"
/>
Props:
| Prop | Type | Default | Description |
|---|---|---|---|
badge |
string |
required | Eyebrow text (uses Badge.astro) |
title |
string |
required | H2 heading text |
description |
string |
— | Optional paragraph below |
theme |
'light' | 'dark' |
'light' |
Adapts text color |
badgeColor |
'primary' | 'accent' |
'primary' |
Badge variant |
maxWidth |
string |
'max-w-3xl' |
Width constraint on description |
class |
string |
— | Extra classes |
BaseLayout.astro — Page Wrapper
Wraps every page. Handles: SEO meta tags, Organization structured data, global fonts, analytics, error tracking, PWA prompt, header, footer, skip-to-content link.
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout
title="Page Title"
description="Meta description..."
image="/og-image.jpg"
canonical="https://workroot.in/page"
>
<!-- page content -->
</BaseLayout>
SEO.astro — Meta Tags & Structured Data
Included via BaseLayout.astro. Generates:
<title>and<meta name="description">- Open Graph (Facebook/LinkedIn) tags
- Twitter Card tags
- Canonical URL
- JSON-LD structured data (WebPage schema)
LazyImage.astro / OptimizedImage.astro
For images within page content.
<!-- Lazy loaded with blur placeholder -->
<LazyImage src="/hero.jpg" alt="Description" width={800} height={450} />
<!-- Optimized with Sharp (auto WebP) -->
<OptimizedImage src="/photo.jpg" alt="Description" width={600} height={400} />
CSS-Only Components (via global.css)
These are plain HTML elements styled via class names — no Astro component required.
Buttons
<!-- Primary CTA -->
<a href="/contact" class="btn-primary">Get Started</a>
<!-- Secondary/Outline -->
<a href="/portfolio" class="btn-secondary">View Work</a>
<!-- Accent (amber) -->
<button class="btn-accent">Highlight Action</button>
<!-- Ghost (transparent) -->
<button class="btn-ghost">Learn More</button>
<!-- Large variants for hero sections -->
<a href="/contact" class="btn-primary-lg">Start a Project</a>
<a href="/services" class="btn-inverse-lg">View Services</a>
Form Elements
<label class="form-label" for="name">Your Name</label>
<input class="form-input" id="name" type="text" />
<span class="form-error">This field is required.</span>
<!-- Error state on input -->
<input class="form-input form-input-error" id="email" type="email" />
Section Patterns
<!-- Light section -->
<div class="section-header">
<p class="section-title">Main Heading</p>
<p class="section-description">Supporting text...</p>
</div>
<!-- Dark/inverse section -->
<div class="section-header">
<p class="section-title-inverse">Main Heading</p>
<p class="section-description-inverse">Supporting text...</p>
</div>
Decorative Elements
<!-- Blobs (absolute-positioned background shapes) -->
<div class="blob blob-primary"></div>
<div class="blob blob-accent"></div>
<!-- Grid overlay (semi-transparent dot grid) -->
<div class="grid-overlay"></div>
<!-- Gradient text -->
<span class="gradient-text">Highlighted Words</span>
<span class="gradient-text-primary">Also works</span>
4. Page Architecture
Section Pattern
Every major page section follows this structure:
<section class="py-24 bg-white relative overflow-hidden">
<!-- Optional decorative blobs -->
<div class="blob blob-primary top-0 left-0"></div>
<div class="container-wrapper">
<!-- SectionHeader -->
<SectionHeader
badge="Label"
title="Section Title"
description="Optional description"
/>
<!-- Content grid -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mt-16">
<!-- Cards or content -->
</div>
</div>
</section>
Page Layout Zones
| Zone | Background | Typical Content |
|---|---|---|
| Hero | bg-hero-dark (dark gradient) |
Headline, subtext, CTAs, trust stats |
| Features | bg-white |
Cards with icons |
| Services | bg-secondary-50 |
Service cards grid |
| Testimonials | bg-hero-dark |
Quote cards |
| CTA Banner | bg-cta-dark |
Headline + 2 CTA buttons |
| Contact | bg-secondary-50 |
Form + sidebar |
| Footer | bg-secondary-900 |
Nav links, social, copyright |
Responsive Breakpoints
Uses Tailwind defaults:
sm: 640px — Small phones → landscapemd: 768px — Tabletslg: 1024px — Laptopsxl: 1280px — Desktops2xl: 1536px — Large monitors
Grid patterns used across pages:
Hero: Single column centered
Features: 1 col → 2 col → 3 col (sm/md/lg)
Services: 1 col → 2 col → 3 col
Contact: 1 col → 3+2 col split (lg)
Portfolio: 1 col → 2 col → 3 col with filters
5. Animation System
How It Works
Animations use the native Intersection Observer API — no JavaScript library needed. The system is defined in two files:
src/utils/animations.ts— JavaScript observer logicsrc/styles/global.css— CSS transitions and keyframes
Usage Pattern
Add data-animate and optional data-delay to any element:
<div data-animate="fade-up">Animates when scrolled into view</div>
<div data-animate="fade-up" data-delay="200">Delayed by 200ms</div>
<div data-animate="scale-up" data-duration="slow">Slower duration</div>
Then initialize in the page's <script> tag:
import { initScrollReveal } from '../utils/animations';
document.addEventListener('DOMContentLoaded', () => {
initScrollReveal();
});
Or use initAllAnimations() to enable everything:
import { initAllAnimations } from '../utils/animations';
document.addEventListener('DOMContentLoaded', initAllAnimations);
Animation Types (data-animate values)
| Value | Effect |
|---|---|
fade-up |
Fade in + slide up 30px |
fade-down |
Fade in + slide down 30px |
fade-left |
Fade in + slide from right |
fade-right |
Fade in + slide from left |
fade-in |
Fade in only |
scale-up |
Scale from 0.95 → 1.0 with fade |
zoom-in |
Scale from 0.8 → 1.0 with fade |
Delay Classes (data-delay values)
100, 200, 300, 400, 500, 600, 700, 800 (milliseconds)
Use to stagger card grids:
<div class="grid grid-cols-3 gap-8">
<div data-animate="fade-up" data-delay="0">Card 1</div>
<div data-animate="fade-up" data-delay="150">Card 2</div>
<div data-animate="fade-up" data-delay="300">Card 3</div>
</div>
Duration Variants (data-duration values)
| Value | Duration |
|---|---|
fast |
400ms |
| (default) | 600ms |
slow |
900ms |
Reduced Motion
All animations automatically respect prefers-reduced-motion: reduce. Elements marked with data-animate are revealed immediately without transitions when this preference is set.
Other Animation Utilities
| Function | Description |
|---|---|
initCounters() |
Animate [data-counter] elements from 0 to target value |
initButtonRipple() |
Cursor-following radial highlight on .btn-ripple buttons |
initProgressBars() |
Fill .progress-bar elements to --progress-width CSS variable |
Counter Example
<span
data-counter="150"
data-counter-suffix="+"
data-counter-duration="2000"
class="text-4xl font-bold"
>0</span>
6. Contact Page Deep Dive
The contact page (src/pages/contact.astro, ~1029 lines) is the most feature-rich redesigned page and serves as the reference implementation for advanced patterns.
Page Sections
- Hero — Dark gradient with grid overlay, trust statistics, scroll-reveal
- Contact Form + Sidebar — 3-column form + 2-column sidebar on
lgbreakpoints - FAQ — Collapsible details/summary
- CTA Banner — Dark gradient with dual CTAs
Form Architecture
The contact form uses no external form library. All behavior is plain JavaScript.
Spam Protection (Honeypot)
<!-- Hidden field — bots fill it, humans don't -->
<div style="position: absolute; left: -9999px; opacity: 0" aria-hidden="true">
<input type="text" name="website" tabindex="-1" autocomplete="off" />
</div>
Server-side: check that website field is empty before processing.
Budget Selector (Radio as Chips)
The budget options render as visual chip buttons but use <input type="radio"> under the hood for accessibility:
<div class="flex flex-wrap gap-3">
<label class="budget-option">
<input type="radio" name="budget" value="under-5k" class="sr-only" />
<span>Under $5K</span>
</label>
</div>
JavaScript adds/removes the selected class when a chip is clicked, and the CSS handles the visual transformation from neutral to active.
Form Validation
Regex patterns used:
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/;
Validation fires on blur (field leave) and submit. Visual feedback via .form-input-error class and a sibling error <span class="form-error">.
Character Counter
<textarea
id="message"
maxlength="2000"
data-counter-target="message-counter"
></textarea>
<span id="message-counter">0/2000</span>
JavaScript updates the counter text on input events.
Toast Notifications
function showToast(message, type = 'success') {
const toast = document.getElementById('toast');
// Set message text, apply type class, show with transition
// Auto-hide after 5000ms
}
The toast element is always in the DOM (position: fixed, bottom-right) but visually hidden until triggered.
Form States
| State | UI Change |
|---|---|
| Default | Normal form |
| Loading | Button shows spinner, disabled |
| Success | Overlay replaces form, shows success message |
| Error | Toast notification, form re-enabled |
Sidebar Components
Contact Info Cards
Four cards (Visit Us, Call Us, Email Us, Business Hours) using card-surface variant. Each has:
- Color-coded icon container (primary, accent, etc.)
- Title + content
- Hover lift effect
Map Embed
A static map image with an overlay on hover. Contains a floating pin animation:
@keyframes float {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-8px); }
}
The hover overlay prompts "Open in Google Maps" with a link.
Social Links
<a href="https://linkedin.com/..." class="social-link group">
<!-- SVG icon -->
<span>LinkedIn</span>
</a>
Custom hover effect: icon rotates slightly, text shifts right.
FAQ Section
Uses native <details>/<summary> HTML for zero-JS accordion behavior:
<details class="faq-item">
<summary class="faq-question">
Question text
<span class="faq-icon"><!-- chevron SVG --></span>
</summary>
<div class="faq-answer">Answer text</div>
</details>
CSS handles the open/close transition via details[open] selector. The chevron rotates 180° when open.
Analytics Events
The contact page fires analytics events for key interactions:
// On budget chip select
trackEvent('budget_selected', { budget: value });
// On form submit (success)
trackEvent('form_submitted', { budget: selectedBudget });
// On social link click
trackEvent('social_click', { platform: 'linkedin' });
7. Theme System
The site ships a full dark / light theme system with FOUC prevention, localStorage persistence, OS preference detection, and WCAG AAA contrast compliance.
Key Files
| File | Role |
|---|---|
src/styles/design-tokens.css |
All color tokens (:root light + html.dark overrides) |
src/components/ThemeToggle.astro |
Sun/moon toggle button in the header |
src/layouts/BaseLayout.astro |
Blocking inline script (prevents flash of wrong theme) |
How It Works (Summary)
- A synchronous inline script in
<head>readslocalStorage.getItem('theme')orprefers-color-schemeand addshtml.darkbefore the first CSS paint — eliminating FOUC. - All colors are CSS custom properties (
--color-*).html.darkoverrides them for the dark palette. - Tailwind's
dark:class variant targetshtml.darkfor utility classes. ThemeToggle.astrohandles click events, syncs all toggle instances, updates ARIA state, announces to screen readers, and updates<meta name="theme-color">.
Developer Quick Start
<!-- ✅ Use semantic tokens -->
<div style="background: var(--color-surface-raised); color: var(--color-text-primary);">
<!-- ✅ Use Tailwind dark: variants -->
<div class="bg-white dark:bg-secondary-800 text-secondary-700 dark:text-secondary-300">
Full Documentation
See THEME_SYSTEM_GUIDE.md for:
- Complete design token reference
- Step-by-step guide for adding theme support to new components
- Troubleshooting guide (FOUC, contrast issues, screen reader support, etc.)
- Accessibility and WCAG compliance details
- Performance notes
8. Maintenance Guidelines
Adding a New Page
- Create
src/pages/new-page.astro - Use
BaseLayout.astroas wrapper with SEO props - Follow the section pattern (container-wrapper, SectionHeader, content)
- Import and initialize animations in the
<script>tag - Update
Header.astronavigation links - Update
Footer.astroif it appears in site map - Update
src/pages/sitemap.astroandsitemap.xml.ts
Adding a New Color
- Add to
tailwind.config.mjsundertheme.extend.colors - Add CSS custom property to
src/styles/global.cssin:root - Create any needed component classes in
global.css
Adding a New Animation
- Define keyframe in
src/styles/global.cssunder@keyframes - Add animation class in Tailwind config
theme.extend.animation - Add
[data-animate="new-type"]CSS inglobal.cssif using scroll-reveal - Always add
@media (prefers-reduced-motion: reduce)override
Modifying the Contact Form
- Validation rules: Edit the regex patterns in the
<script>section ofcontact.astro - Budget options: Add/remove
<label class="budget-option">items - FAQ entries: Add
<details>blocks in the FAQ section - Server handling: The form POSTs to
/api/contact— editsrc/pages/api/contact.ts
Performance Checklist (before deploy)
- New images use
<OptimizedImage>or<LazyImage>components - Large sections use
data-animatefor scroll-reveal (avoid layout shift) - No inline
styletags with large CSS blocks — useglobal.cssclasses - External resources are from whitelisted domains only
- Run
npm run buildand check bundle size (target: <300KB client JS) - Run Lighthouse (target: 90+ on all metrics)
Dependency Updates
Key dependencies to keep updated:
astro— Major versions may need config migration@astrojs/tailwind— Follows Tailwind CSS releasestailwindcss— v3.x series; v4 will require config rewrite@sentry/browser— Security patches important
9. Future Enhancement Recommendations
High Priority
1. Blog / Content Section
The src/content/blog/ directory exists but no blog listing page is implemented. Recommended approach:
- Create
src/pages/blog/index.astrowith card grid - Create
src/pages/blog/[slug].astrofor individual posts - Use Astro Content Collections (already configured)
- Leverage existing
SectionHeader,Card,Badgecomponents
2. Case Study Modal → Dedicated Pages
Portfolio case studies currently open in a JavaScript modal. For better SEO and shareability:
- Create
src/pages/portfolio/[slug].astro - Add structured data (CreativeWork schema) per case study
- Implement smooth navigation with View Transitions API
3. Form Backend Enhancement
Current contact form uses a simple API route. Consider:
- Email notification via SendGrid or Resend
- CRM integration (HubSpot, Pipedrive)
- File attachment support for design briefs
- Multi-step form wizard for complex project scoping
Medium Priority
4. i18n / Localization
Astro has built-in i18n routing. For a future multi-language site:
- Use
src/pages/[locale]/routing - Store copy in
src/content/or external CMS - Update
astro.config.mjswithi18nconfig
5. Dark Mode ✅ Implemented
Dark mode is fully implemented. See THEME_SYSTEM_GUIDE.md for developer and user documentation.
6. Animation Performance
Current scroll-reveal uses a single Intersection Observer. For pages with many animated elements:
- Consider virtualized animation queuing (pause observer after element leaves viewport)
- Profile with Chrome DevTools Performance tab on low-end devices
- The
data-duration="fast"option is available for elements needing snappier reveals
Low Priority
7. Component Storybook
The Badge, Card, and SectionHeader components are well-isolated. A Storybook setup would:
- Provide a visual component library
- Document all variant combinations
- Enable designer handoff via Storybook's design tools
8. Automated Visual Regression
Add Playwright screenshot tests for critical pages:
// tests/visual.spec.ts
test('contact page matches snapshot', async ({ page }) => {
await page.goto('/contact');
await expect(page).toHaveScreenshot('contact.png');
});
Use --update-snapshots flag after intentional design changes.
9. Edge Caching
Currently SSR renders on every request. For pages with low dynamic content:
- Use Astro's
export const prerender = truefor static generation - Or add
Cache-Controlheaders in the Node.js middleware - The about, privacy, and terms pages are good candidates
10. Quick Reference
Common Patterns
Hero Section
<section class="bg-hero-dark py-32 relative overflow-hidden">
<div class="grid-overlay"></div>
<div class="blob blob-primary top-0 right-0"></div>
<div class="container-wrapper text-center">
<Badge label="Eyebrow Text" variant="primary-dark" />
<h1 class="display-xl text-white font-bold mt-4">
Hero <span class="gradient-text">Headline</span>
</h1>
<p class="text-xl text-secondary-300 max-w-2xl mx-auto mt-6">
Supporting description text.
</p>
<div class="flex gap-4 justify-center mt-10">
<a href="/contact" class="btn-primary-lg">Primary CTA</a>
<a href="/portfolio" class="btn-inverse-lg">Secondary CTA</a>
</div>
</div>
</section>
Feature Card Grid
<section class="py-24 bg-white">
<div class="container-wrapper">
<SectionHeader badge="Features" title="Why Choose Us" />
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8 mt-16">
{features.map((feature, i) => (
<Card variant="feature" data-animate="fade-up" data-delay={i * 100}>
<div class="icon-container icon-md mb-4">
<!-- SVG icon -->
</div>
<h3 class="text-xl font-semibold text-secondary-800">{feature.title}</h3>
<p class="text-secondary-600 mt-2">{feature.description}</p>
</Card>
))}
</div>
</div>
</section>
CTA Banner
<section class="bg-cta-dark py-24 relative overflow-hidden">
<div class="container-wrapper text-center">
<h2 class="display-lg text-white font-bold">
Ready to <span class="gradient-text">Get Started?</span>
</h2>
<p class="text-secondary-300 text-xl max-w-2xl mx-auto mt-6">
Supporting text here.
</p>
<div class="flex gap-4 justify-center mt-10">
<a href="/contact" class="btn-primary-lg">Start a Project</a>
<a href="/services" class="btn-inverse-lg">View Services</a>
</div>
</div>
</section>
Class Cheat Sheet
Layout:
container-wrapper Max-width container with responsive padding
Buttons:
btn-primary Solid cyan button
btn-secondary Outline cyan button
btn-accent Solid amber button
btn-ghost Transparent/white hover
btn-primary-lg Large solid (hero sections)
btn-inverse-lg Large outline white (dark backgrounds)
Badges:
badge badge-primary Cyan pill (light bg)
badge badge-primary-dark Cyan pill (dark bg)
badge badge-accent Amber pill
badge badge-secondary Slate pill
Forms:
form-label Label text
form-input Text input / textarea / select
form-input-error Error state for inputs
form-error Error message text
Typography:
gradient-text Cyan gradient text
gradient-text-primary Alternate gradient
section-title Section H2 on light bg
section-description Section P on light bg
section-title-inverse Section H2 on dark bg
section-description-inverse Section P on dark bg
Decorative:
blob blob-primary Cyan background blob
blob blob-accent Amber background blob
grid-overlay Dot grid overlay
Animations:
data-animate="fade-up" Scroll reveal animation
data-delay="200" Delay in ms (100-800)
data-counter="100" Animated counter
This document was generated by the documentation-writer agent on 2026-03-21. Update this document when making significant design changes to the site.