# Technical Specification — Nkali Business Advisory Landing Page

## Development Environment

| Technology | Version | Purpose |
|-----------|---------|---------|
| React | 19 | UI framework |
| TypeScript | 5.x | Type safety |
| Vite | 6.x | Build tool / dev server |
| Tailwind CSS | 3.4.x | Utility-first CSS |
| shadcn/ui | latest | UI component primitives (pre-installed) |

## Dependencies

### Runtime

| Package | Version | Purpose |
|---------|---------|---------|
| `gsap` | ^3.12 | Animation engine — ScrollTrigger, timeline sequences, parallax, word-by-word text reveal, staggered reveals |
| `lucide-react` | ^0.468 | Icon library for UI icons (already included with shadcn) |

### Dev

| Package | Version | Purpose |
|---------|---------|---------|
| `autoprefixer` | ^10.4.x | CSS vendor prefixes (via Tailwind) |
| `postcss` | ^8.4.x | CSS processing (via Tailwind) |

No additional libraries required. The GSAP `ScrollTrigger` plugin handles all parallax, scroll-triggered entrance animations, and timeline sequencing. `lucide-react` is already included with the shadcn/ui setup.

---

## Component Inventory

### shadcn/ui Components

| Component | Usage | Customization |
|-----------|-------|---------------|
| `Button` | CTA buttons throughout (Primary, Outline, Ghost variants) | Override to pill shape (`rounded-full`), custom Navy Blue color scheme, hover darkens |
| `Input` | Contact form text fields | Override focus ring to Navy Blue, custom border colors |
| `Textarea` | Contact form message field | Same styling as Input |

### Custom Components — Sections

| Component | File | Description |
|-----------|------|-------------|
| `Hero` | `src/sections/Hero.tsx` | Full-viewport hero with parallax background, word-by-word headline, CTA buttons, scroll indicator |
| `About` | `src/sections/About.tsx` | Split-screen layout: portrait image left, text + animated counters right |
| `CoreServices` | `src/sections/CoreServices.tsx` | 2x2 grid of ServiceCards with gradient overlay at bottom |
| `Industries` | `src/sections/Industries.tsx` | 4-column grid of IndustryCards |
| `WhyChoose` | `src/sections/WhyChoose.tsx` | Parallax background section with value proposition checklist |
| `Workflow` | `src/sections/Workflow.tsx` | 5-step horizontal timeline with SVG connecting line |
| `CallToAction` | `src/sections/CallToAction.tsx` | Full-width parallax CTA with centered content |
| `Contact` | `src/sections/Contact.tsx` | Split layout: contact form left, info + map right |
| `Footer` | `src/sections/Footer.tsx` | 4-column footer with background image, newsletter form |
| `Navigation` | `src/sections/Navigation.tsx` | Fixed header with scroll-aware background, mobile menu panel |

### Custom Components — Reusable

| Component | File | Props | Description |
|-----------|------|-------|-------------|
| `ServiceCard` | `src/components/ServiceCard.tsx` | `icon`, `title`, `description`, `bgColor`, `borderColor`, `iconColor` | Tinted background card with SVG icon, hover lift + icon scale |
| `IndustryCard` | `src/components/IndustryCard.tsx` | `icon`, `label` | Gray background card with icon, hover lift + shadow |
| `WorkflowStep` | `src/components/WorkflowStep.tsx` | `number`, `title`, `description`, `isLast` | Numbered step with connecting line separator |
| `AnimatedCounter` | `src/components/AnimatedCounter.tsx` | `target`, `suffix`, `label` | Count-up animation from 0 to target value |
| `WordReveal` | `src/components/WordReveal.tsx` | `children`, `delay?`, `stagger?`, `duration?` | Wraps text, splits into words, animates each word with GSAP ScrollTrigger |
| `ParallaxBg` | `src/components/ParallaxBg.tsx` | `src`, `speed?`, `overlay?`, `children` | Wrapper component for parallax background image with optional gradient overlay |
| `ScrollIndicator` | `src/components/ScrollIndicator.tsx` | — | Animated chevron with continuous bounce |

### Custom Components — Forms

| Component | File | Description |
|-----------|------|-------------|
| `ContactForm` | `src/components/ContactForm.tsx` | Form with name, email, phone, subject, message fields; loading/success/error states |
| `NewsletterForm` | `src/components/NewsletterForm.tsx` | Email + submit button for footer |

### Custom Hooks

| Hook | File | Description |
|------|------|-------------|
| `useScrollDirection` | `src/hooks/useScrollDirection.ts` | Tracks scroll direction (up/down) for nav background transition |
| `useInView` | `src/hooks/useInView.ts` | IntersectionObserver wrapper for triggering one-off animations (counters, etc.) |

---

## Animation Implementation

### Animation Engine: GSAP

GSAP is the single animation library used for all motion on the page. The `ScrollTrigger` plugin handles all scroll-driven interactions — parallax, entrance animations, and sequence triggering. GSAP timelines manage the hero entrance sequence and staggered reveals.

### Smooth Scroll System

A custom smooth scroll system is implemented using `requestAnimationFrame` with lerp interpolation (factor ~0.08–0.1). The page content is translated via `translateY` to follow a virtual scroll position, while a hidden native scroll container provides the actual scrollable area. On mobile, the system falls back to native scroll for performance and touch compatibility.

| Animation | Library / Plugin | Implementation Approach | Complexity |
|-----------|-----------------|------------------------|------------|
| **Smooth scroll (page-wide)** | Custom RAF + lerp | Custom `useSmoothScroll` hook: RAF loop interpolates scroll position, applies `translateY` to content wrapper. Mobile fallback to native. | **High** 🔒 |
| **Parallax backgrounds** | GSAP ScrollTrigger | `ScrollTrigger` with `scrub: true`, animates `translateY` on background image elements at 60–70% scroll speed | **Medium** |
| **Hero entrance sequence** | GSAP Timeline | Single timeline: (1) accent text fade 500ms → (2) headline word reveal 600ms/word → (3) subtext fadeUp 600ms → (4) CTAs fadeUp 500ms → (5) scroll indicator fade 400ms | **High** 🔒 |
| **Word-by-word text reveal** | GSAP ScrollTrigger | `WordReveal` component: splits text into word spans, each animated with `opacity 0→1` + `translateY(30px→0)`, stagger 80ms, triggered by ScrollTrigger `toggleActions` | **High** 🔒 |
| **Fade in (general)** | GSAP ScrollTrigger | Simple `opacity 0→1`, 800ms, ease-out-quart, triggered at 10% viewport entry | **Low** |
| **Fade in & move** | GSAP ScrollTrigger | `opacity 0→1` + `translateY(50px→0)`, 1000ms, ease-out-quart | **Low** |
| **Fade in & scale** | GSAP ScrollTrigger | `opacity 0→1` + `scale(0.95→1)`, 800ms, ease-out-quart | **Low** |
| **Staggered grid reveal** | GSAP ScrollTrigger | Batch animation on grid children: fade + slide up, 600ms/item, 100ms stagger, triggered on parent container entry | **Medium** |
| **Header scroll behavior** | GSAP ScrollTrigger | ScrollTrigger monitors scroll position; toggles `background-color` and `border-bottom` class on nav. Transition 300ms CSS. | **Low** |
| **Mobile menu** | GSAP | Panel slides from right (`translateX(100%)→0`), backdrop fades in, links stagger in 50ms each. Reverse on close. | **Medium** |
| **Nav link underline** | CSS | `::after` pseudo-element with `scaleX(0→1)` transform, `transform-origin: left`, transition 300ms | **Low** |
| **Button hover effects** | CSS | `background-color` transition 300ms, `transform: scale(1.02)` on hover. Arrow `translateX(0→4px)` on parent hover. | **Low** |
| **Service card hover** | CSS | `translateY(-4px)` + `box-shadow`, icon `scale(1.1)`, 300ms transition | **Low** |
| **Industry card hover** | CSS | `translateY(-6px)` + deeper shadow, icon color intensifies, 300ms transition | **Low** |
| **Scroll indicator bounce** | CSS Keyframes | `@keyframes bounce`: `translateY(0→8px→0)`, 1.5s infinite ease-in-out | **Low** |
| **Counter animation** | Custom RAF | `useInView` triggers `requestAnimationFrame` loop counting from 0 to target over 2000ms with easeOut. Format with suffix. | **Medium** |
| **Workflow step entrance** | GSAP ScrollTrigger | Staggered timeline: each step fades + slides up 30px, 600ms, 150ms stagger between steps. SVG line draws progressively via `stroke-dashoffset`. | **Medium** |
| **Form input focus** | CSS | `border-color` transition 200ms to Navy Blue on `:focus` | **Low** |
| **Footer column entrance** | GSAP ScrollTrigger | Columns stagger fade-in, 500ms, 100ms stagger | **Low** |

---

## State & Logic

### Global State

No global state library is needed. This is a single-page landing site with minimal shared state. Local component state (`useState`) handles:

- Mobile menu open/close (`Navigation`)
- Form submission states: idle → loading → success/error (`ContactForm`, `NewsletterForm`)
- Header background transparency based on scroll position (`Navigation`)

### Data Flow

All data is static/hardcoded. No API calls, no data fetching, no authentication. Form submissions are simulated (no backend endpoint) — they log to console and show success state.

### Scroll Management

The custom smooth scroll system must coordinate with GSAP ScrollTrigger:
1. Initialize custom smooth scroll (RAF loop translating content wrapper)
2. Configure ScrollTrigger to use the virtual scroll position (not native `window.scrollY`)
3. On mobile: disable custom smooth scroll, let ScrollTrigger fall back to native scroll

This requires calling `ScrollTrigger.scrollerProxy()` to bridge the custom scroll container with GSAP's scroll monitoring.

---

## Other Key Decisions

### Font Loading

Google Fonts loaded via `<link>` in `index.html` with `display=swap`:
- DM Sans (weights 400, 500, 600)
- Instrument Serif (weight 400 italic)

Tailwind config extends the `fontFamily` theme with `sans: ['DM Sans', 'system-ui', 'sans-serif']` and `serif: ['Instrument Serif', 'Georgia', 'serif']`.

### Image Strategy

- Hero, Why Choose, CTA, and Footer backgrounds: high-res JPEGs, `loading="lazy"` on all except hero
- About portrait: medium-res JPEG, eager load (above fold)
- All background images use `object-fit: cover` and `will-change: transform` for GPU-accelerated parallax
- Map embed: Google Maps iframe with `loading="lazy"` and CSS grayscale filter

### SVG Icons

All icons are inline SVGs (not from a library) to support custom stroke colors per service/industry:
- Service icons: 4 unique SVGs with colored strokes matching card theme
- Industry icons: 8 unique SVGs with Navy Blue strokes
- UI icons (checkmark, email, phone, location, social): small inline SVGs
- Arrow and close icons: inline SVGs using `currentColor`

### Form Handling

Forms are client-side only. No backend integration. On submit:
1. Set loading state (button shows spinner)
2. Simulate network delay (`setTimeout` 1500ms)
3. Show success message, clear form
4. Error state shows a generic error message

### Responsive Approach

Mobile-first Tailwind breakpoints:
- Default: mobile (<768px)
- `md:`: tablet (768px+)
- `lg:`: desktop (992px+)
- Custom max-width container: `73.75rem` (1180px) via Tailwind config

Parallax and smooth scroll are disabled on mobile. All entrance animations still fire via ScrollTrigger with native scroll.
