---
stepsCompleted: [step-01-init, step-02-discovery, step-03-core-experience, step-04-emotional-response, step-05-inspiration, step-06-design-system, step-07-defining-experience, step-08-visual-foundation, step-09-design-directions, step-10-user-journeys, step-11-component-strategy, step-12-ux-patterns, step-13-responsive-accessibility, step-14-complete]
inputDocuments:
  - "prd.md"
  - "product-brief-gitpulse.md"
  - "product-brief-gitpulse-distillate.md"
  - "architecture.md"
  - "research/market-git-dashboard-ia-research-2026-04-24.md"
workflowType: 'ux-design'
project_name: 'GitPulse'
user_name: 'Ramez'
date: '2025-04-25'
lastStep: 14
status: 'complete'
completedAt: '2025-04-25'
---

# UX Design Specification GitPulse

**Author:** Ramez
**Date:** 2025-04-25

---

<!-- UX design content will be appended sequentially through collaborative workflow steps -->

## Executive Summary

### Project Vision

GitPulse is an open source desktop dashboard that solves multi-repo chaos: a developer launches the app and instantly sees the state of all their Git repositories — status, branches, pending commits, and alerts. The vision is the "command center" for the local code ecosystem.

**Fundamental UX Constraints:**
- Zero-config, zero-login — user sees dashboard in < 30 seconds after download
- Offline-first — no feature depends on network
- Native performance — ~15 MB binary, <200 MB RAM, 60fps
- Cross-platform — same experience on Windows, macOS, Linux

### Target Users

**Persona 1 — Sarah, Indie Dev Poly-Project (primary)**
Freelancer with 10-50+ repos across clients, OSS, personal. Daily context-switching. Loses track of unpushed commits, stale branches. Wants instant visibility, zero configuration. Tool budget: $0-10/month.

**Persona 2 — Leo, Power User / Tech Lead (secondary)**
Senior dev in microservices architecture, 12-30+ repos. Uses CLI + GUI hybrid. Wants batch ops, cross-repo visibility, configures cloud API keys for advanced analysis.

**Persona 3 — Max, Maker / Side-Project Builder (tertiary)**
Creative developer with 20+ side projects, many dormant. Needs dormancy detection and cleanup prompts.

**Persona 4 — Jay, New Dev (onboarding)**
< 10 repos. Experience must remain valuable — no "empty" feeling with a small number of repositories.

### Key Design Challenges

1. **Information density vs readability** — Each repo displays branch, status (clean/dirty/ahead/behind), last commit, stash count, and optionally an AI summary. For 5 to 100+ repos, the challenge is instant pattern recognition without visual overload.

2. **Consistent multi-view navigation** — Card Grid ↔ List View toggle must maintain a consistent visual status language (colors, badges, icons) and preserve selection when switching views (useful for batch ops).

3. **Trust through transparency** — The privacy indicator (FR27) is a key differentiator. Users must always know whether data stays local or transits to cloud, without being intrusive.

4. **"5-Second Wow"** — The conversion moment: first launch → auto-scan → full dashboard in < 30 seconds. The empty experience (0 repos) and small experience (< 10 repos, Jay) must also be engaging.

5. **Platform-specific integration** — System tray, notifications, auto-launch have different native behaviors on Windows, macOS, Linux. UX must be consistent while respecting each platform's conventions.

6. **Progressive AI enhancement** — Smart Status is an enrichment, never a dependency. The interface must be complete without AI, and naturally enriched when a provider is configured.

### Design Opportunities

1. **Unified visual status language** — A consistent color/badge system (green = clean, orange = ahead/behind, red = dirty, grey = dormant) that works across Card Grid, List View, system tray, and notifications. This is the #1 UX lever for instant pattern recognition.

2. **Batch ops with granular feedback** — Selecting 15 repos and seeing results appear in real-time (success/failure per repo) is a major functional differentiator. The partial success UX can transform a tedious task into a satisfying interaction.

3. **Trust as a feature** — The Privacy Badge and local-first default can become a visual selling point. "Your code never leaves your machine" as a design element, not just text.

4. **Smart Status as subtle enrichment** — Rather than a separate AI panel, health summaries can appear naturally in RepoCards as an additional text line, with a discreet "AI" badge indicating the source.

## Core User Experience

### Defining Experience

**Core loop: Scan → See → Act**

The central action is the "visual status check" — the user opens GitPulse and immediately knows which repos need attention. It's a "check-in tool" like a weather app or monitoring dashboard: open, visually scan, act if needed, close.

Usage frequency varies by persona:
- **Sarah**: 2-3x/day (morning check, post-commit check, end-of-day check)
- **Leo**: 1-2x/day + occasional batch ops
- **Max**: 1x/week + monthly cleanup
- **Jay**: 1x/day to build familiarity

**The one interaction to nail: The Card Grid visual scan.** If the user can open GitPulse and in 2 seconds identify the 3 repos that need attention among 30+ repos, everything else follows.

### Platform Strategy

**Platform: Native Desktop (Tauri v2)**
- Windows, macOS, Linux — same codebase, same UX
- Interaction: mouse + keyboard (desktop-first, no touch)
- Native WebView per platform (WebView2/WebKit/WebKitGTK)

**Two interaction surfaces:**

1. **Main Dashboard** — Full desktop window with Card Grid / List View. The complete experience.
2. **System Tray** — Always-present background agent. Push notifications + quick actions (pull, push, status). Functions with dashboard closed.

**Platform constraints:**
- Tray behavior differs by OS (Windows: taskbar, macOS: menu bar, Linux: D-Bus). UX must be functionally identical but visually native.
- OS notifications must respect each platform's system settings.
- Keyboard + shortcuts for all core operations (NFR25).

### Effortless Interactions

**Zero-effort by design:**
- Launch → auto-scan (no action required)
- Scan results → persistent cache (instant reload on next launch)
- Repo status → updated via background batch fetch

**One-effort:**
- Batch pull/push: multi-select → one click → streaming results
- Rescan: single button (or keyboard shortcut)
- View toggle: one click or shortcut (Ctrl/Cmd+G grid, Ctrl/Cmd+L list)

**What should disappear vs competitors:**
- No login/password (vs GitKraken)
- No manual repo config (vs gita)
- No repo-by-repo navigation (vs lazygit)
- No setup wizard — dashboard appears directly

### Critical Success Moments

**Moment 1 — "5-Second Wow" (first launch)**
User downloads, launches, sees full dashboard in < 30 seconds. If repos appear with clear visual status, they instantly understand the value.

**Moment 2 — First status check (first minute)**
User visually identifies a forgotten repo (behind, dirty, or dormant). The "oh, I forgot about that one!" reaction is instant product validation.

**Moment 3 — First batch op (first session)**
Select 5-10 repos → batch pull → see results stream in real-time. Time savings are tangible and measurable.

**Moment 4 — First Smart Status (first week)**
Configure Ollama → see an AI summary appear on a repo. The enrichment is subtle but rewarding.

**Break moment — Empty state or error**
Empty dashboard (0 repos found) or failed scan. If the empty state isn't engaging with a clear call-to-action, the user abandons.

### Experience Principles

1. **Instant Visibility** — All repo states visible at a glance. No navigation, no loading, no setup. Open = know.

2. **Zero Friction Entry** — No obstacles between download and value. No account, no config, no wizard. First scan starts automatically.

3. **Progressive Power** — Base interface is simple (visual status). Power (batch ops, AI, filters) reveals itself as needed, without overwhelming the initial user.

4. **Trust by Default** — Privacy is the default mode. The Privacy Badge isn't an intrusive notification but a reassuring design element, always visible but never blocking.

5. **Native Feel** — No "web app in a window." Native desktop behavior: keyboard shortcuts, system tray, OS notifications, fluid resizing, responsive performance.

## Desired Emotional Response

### Primary Emotional Goals

**Emotion #1 — Relief**
The immediate feeling: "I don't have to check 30 repos manually anymore." GitPulse eliminates the anxiety of the unknown — the developer knows exactly where things stand. This is the emotion that drives recommendations: "You have to try this, it saved me."

**Emotion #2 — Control**
The lasting feeling: "I dominate my code ecosystem." The user feels organized, informed, proactive rather than reactive. The Card Grid is the visual projection of this mastery.

**Emotion #3 — Trust**
The underlying feeling: "My code stays on my machine." Trust isn't a feature but an absence of doubt. The Privacy Badge silently reinforces this confidence with every use.

### Emotional Journey Mapping

**Discovery → First Launch (curiosity → relief)**
User arrives with curiosity ("a free multi-repo tool?") and leaves with relief ("wow, I had 3 repos I forgot about"). The auto-scan is the emotional trigger.

**Daily check-in (routine → confidence)**
After adoption, the daily check becomes routine. The target emotion is quiet confidence — user opens, confirms all is well, closes. No alerts = success.

**Batch operation (hesitation → satisfaction)**
First batch op: user hesitates ("will this work on 15 repos at once?"). Result: tangible satisfaction. Partial failures must inspire confidence ("the failed ones are clearly flagged, I know what to do").

**AI discovery (intrigue → delight)**
First Smart Status: curiosity ("what will the AI say about my repo?"). Result: subtle delight if the summary is relevant. AI must never disappoint — a useless summary is worse than no summary.

**Empty/error state (confusion → clarity)**
0 repos found or scan error. Emotion must shift quickly from confusion to clarity through a clear message/action ("Add directories to scan" with direct button to Settings).

### Micro-Emotions

| Micro-Emotion | GitPulse Context | Design Response |
|---|---|---|
| **Confidence vs Confusion** | Scan results appearing | Progressive results, never a blank screen without feedback |
| **Trust vs Skepticism** | AI/Cloud data flow | Privacy Badge always visible, explicit opt-in for cloud |
| **Accomplishment vs Frustration** | Batch operations | Per-repo success/failure visual, no endless spinners |
| **Delight vs Indifference** | Smart Status summaries | Relevant, concise summaries, no generic filler text |
| **Control vs Overwhelm** | 50+ repos dashboard | Instant filters/sorts, status colors for pattern recognition |
| **Belonging vs Isolation** | Open source community | Discreet GitHub link, contributing hints |

### Design Implications

- **Relief → Visible instant scan**: Scan must show progressive results (repo count climbing), never a blank screen with spinner. Each appearing repo reinforces relief.

- **Control → Immediate visual status**: Colors and badges must be interpretable in < 1 second without a legend. The color pattern must be instinctive (green = ok, red = problem).

- **Trust → Privacy as architecture**: The Privacy Badge isn't a popup or banner but a permanent interface element, like the padlock in a browser. Present, discreet, reassuring.

- **Satisfaction → Streaming batch results**: Each successful repo appears in green as it completes. Failures appear in red with detail. No "all or nothing" — progress is visible.

- **Delight → Subtle AI**: Smart Status appears as a natural text line in the RepoCard, not a separate panel. A micro-badge "AI" indicates the source. If no AI is configured, the slot doesn't exist as an empty hole — it simply isn't there.

### Emotional Design Principles

1. **Show, don't tell** — Value is visible at first glance. No text onboarding, no explanatory tooltips. The dashboard is visually self-explanatory.

2. **Silent reassurance** — Trust is built through absence of problems, not through messages. The Privacy Badge is like the HTTPS padlock — noticed when sought, never intrusive.

3. **Celebrate progress, isolate failure** — Batch ops show each success in real-time. Failures are isolated and actionable, never blocking the whole.

4. **Calm competence** — GitPulse doesn't try to impress. It is competent, reliable, understated. The design reflects this: no flashy animations, no sounds, no confetti. Just a tool that works.

## UX Pattern Analysis & Inspiration

### Inspiring Products Analysis

**Linear (project management)**
The gold standard for developer tools. Keyboard-first interface, clean design, instant performance. Every interaction is fast and predictable. Information density is high without overload. Command palette (Cmd+K) for everything. Transferable: the "fast by default, power on demand" principle matches GitPulse's experience exactly.

**Raycast (productivity launcher)**
Master of "zero-friction entry." Opens instantly, real-time results, closes fast. The "check-in tool" model is identical to GitPulse: open → see → act → close. Silent trust (no unnecessary notifications, no bloat) is a model for the system tray.

**Docker Desktop (container dashboard)**
Multi-item dashboard with colored status indicators (green/yellow/red). Similar to GitPulse: multiple "entities" with visual states, possible batch actions. Their weakness: heavy, slow, Electron. GitPulse can adopt the dashboard pattern but with native lightness.

**1Password (security app)**
The security padlock as a permanent, reassuring design element. Exactly the analogy for GitPulse's Privacy Badge. Trust is integrated into the interface, not added on top. The visual lock/unlock is a model for the local/cloud indicator.

**lazygit (terminal git UI)**
The reference git TUI. Instant, keyboard-driven, all info visible on one screen. Proves developers want speed and density. Its limitation: single repo only. GitPulse extends this pattern to multiple repos.

### Transferable UX Patterns

**Navigation Patterns:**
- **Command palette (Linear/Raycast)** — Cmd/Ctrl+K for quick access to any action (rescan, toggle view, batch pull). Scales without complicating the interface.
- **Single-page dashboard** — No tab-based hierarchical navigation. Everything visible on one page with filters/toggles to change perspective.

**Interaction Patterns:**
- **Inline batch selection** — Checkbox on each card/row for multi-select. Context toolbar appears when items are selected (batch pull/push/fetch).
- **Streaming progress** — Batch results appearing one by one (like Docker Desktop pull progress), no blocking until completion.
- **Zero-setup first experience** — Like Raycast: launch → immediate action, no wizard.

**Visual Patterns:**
- **Status color system (Docker Desktop)** — Green/yellow/red/grey for status with legend integrated into badge (icon + color, not color alone for accessibility).
- **Trust indicator (1Password)** — Permanent badge in a corner of the interface. Small, discreet, always present. Visually changes state when mode changes.
- **Skeleton loading** — Instead of spinners, placeholder cards showing structure while awaiting data.

### Anti-Patterns to Avoid

- **Mandatory login for local features (GitKraken)** — Users must use 100% of local features without an account. Login does not exist in GitPulse.

- **Blocking modal wizards** — No "setup wizard" on first launch. Scan starts automatically, results appear directly.

- **Global spinners without feedback** — Never a central spinner without progress indication. Always show advancement (repo count, progress bar, streaming results).

- **Web-like chrome in a desktop app** — No web app sidebar navigation, no breadcrumbs, no hamburger menu header. The interface is a native dashboard.

- **Excessive notifications** — System tray alerts only when relevant (repo behind, unpushed commits older than X days). No "tip of the day" or marketing notifications.

- **AI as intrusive feature** — No "Configure AI!" popup on launch. AI is discoverable via Settings, and Smart Status appears naturally once configured.

- **Color as sole status indicator** — Status badges use color + icon + label text for accessibility (NFR26-27). Never color alone.

### Design Inspiration Strategy

**What to Adopt:**
- Command palette (Cmd/Ctrl+K) — supports keyboard-first developer workflow
- Status color + icon system (green/yellow/red/grey) — instant pattern recognition
- Streaming batch results — tangible progress visibility
- Privacy Badge as permanent element — trust through consistent presence
- Skeleton loading — no layout shift during loading

**What to Adapt:**
- Card Grid layout — adapt Docker Desktop's multi-entity grid for repo context (branch, status, ahead/behind, stash)
- System tray — adapt Raycast's "silent but present" background model with quick actions
- Empty state — create an engaging first experience for Jay (0-10 repos) that encourages exploration rather than feeling sparse

**What to Avoid:**
- Web navigation patterns (sidebars, breadcrumbs, hamburger menus)
- Setup wizards and mandatory configuration steps
- Modal-heavy workflows
- Notification spam
- AI-first messaging or aggressive AI onboarding

## Design System Foundation

### Design System Choice

**Approach: Tailwind CSS + Radix UI Primitives (Headless)**

GitPulse uses a hybrid approach: Tailwind CSS for styling and the token system, combined with Radix UI for accessible component primitives (Dialog, Select, Tooltip, Dropdown). No full design system like Material/Ant — too heavy and too opinionated for a solo project with a custom visual identity.

**Component Stack:**

| Concern | Solution | Rationale |
|---------|----------|-----------|
| Styling & tokens | Tailwind CSS | Already chosen in architecture. Utility-first, fast for solo dev |
| Component primitives | Radix UI | Accessible by default, unstyled (Tailwind controls visuals), lightweight |
| Icons | Lucide React | Open source, tree-shakeable, consistent linear style |
| Animations | Tailwind transitions + prefers-reduced-motion | Minimal, no animation library |
| Virtualization | @tanstack/react-virtual | For rendering 100+ repos (FR14/NFR6 gap identified in architecture) |

### Rationale for Selection

**Why not a full design system (Material, Ant, Chakra):**
- GitPulse has a specific visual identity (status colors, Privacy Badge, card grid) that doesn't match Material/Ant conventions
- Complete design systems add 50-100 KB to bundle — contradicts ~15 MB binary target
- A solo developer doesn't benefit from full system velocity — customization takes longer than building from scratch with Tailwind
- Desktop native architecture (Tauri webview) benefits from lean CSS

**Why Radix UI over Headless UI or alternatives:**
- Built-in accessibility (ARIA, keyboard nav) — directly addresses NFR25-27
- Unstyled: no CSS override battles, Tailwind controls 100% of visuals
- Exact components GitPulse needs: Dialog (settings), Select (filters), Tooltip (status details), Dropdown (tray menu), Checkbox (batch select)
- Maintained by Radix team, used in production by Linear, Vercel

**Why Lucide React:**
- Linear icon style consistent with "calm competence" aesthetic
- Tree-shakeable — only used icons are included
- Open source (ISC), no license constraints
- 1000+ icons covering git, status, settings, AI

### Implementation Approach

**Design tokens via Tailwind config:**

```
Status colors (core visual language):
  - status-clean: green-500     (clean repo)
  - status-dirty: red-500       (uncommitted changes)
  - status-ahead: blue-500      (ahead of remote)
  - status-behind: orange-500   (behind remote)
  - status-dormant: gray-400    (no activity > threshold)

Neutrals:
  - bg-primary, bg-secondary, bg-surface
  - text-primary, text-secondary, text-muted

Privacy indicator:
  - privacy-local: green-600    (Ollama / no AI)
  - privacy-cloud: amber-500    (cloud API active)
```

**Component architecture:**
- `components/ui/` — Tailwind-styled primitives (Button, Badge, Card, Input, Dialog, Select, Skeleton, Tooltip)
- Each primitive wraps a Radix component with Tailwind styling
- Business components (RepoCard, PrivacyBadge, BatchToolbar) compose from primitives
- No runtime theming — tokens are compiled into CSS

### Customization Strategy

**Custom components (not in Radix, to be built):**
- `RepoCard` / `RepoRow` — Card with status badge, branch label, ahead/behind counter, AI summary line
- `PrivacyBadge` — Permanent local/cloud indicator with icon and label
- `StatusBadge` — Colored badge with icon for each status (clean/dirty/ahead/behind/dormant)
- `BatchProgress` — Repo list with streaming success/failure
- `ViewToggle` — Grid/list toggle with icons
- `EmptyState` — Illustration + CTA for 0 repos and < 10 repos

**Accessibility in each custom component:**
- StatusBadge: color + icon + aria-label (never color alone)
- RepoCard: role="article", tabindex for keyboard nav
- PrivacyBadge: aria-live="polite" when mode changes
- BatchProgress: role="list", aria-label per repo result

## Core User Experience

### Defining Experience

**"Launch and Know" — Open and immediately know.**

The defining experience is the moment the user opens GitPulse and sees the state of all repos at a glance. No navigation, no setup, no searching. The Card Grid is GitPulse's "swipe" — the interaction that, if perfected, makes everything else natural.

**What the user describes to a friend:** *"You launch it and you immediately see which repos are dirty, which are behind, which are dormant. No more checking one by one."*

**The equation:** Repo count × info per repo = instant pattern recognition. If the Card Grid lets Sarah see in 2 seconds that 3 out of 30 repos need attention, the experience succeeds.

### User Mental Model

**How developers currently think:**
- Existing mental model: `cd repo && git status` — one repo at a time, mental stack limited to ~5 repos
- Frustration: "I know I forgot to push something but I don't remember where"
- Workarounds: shell scripts (fragile), mental notes (imperfect), growing anxiety with repo count

**Expectations for GitPulse:**
- Expects an "overview" — not a per-repo tool
- Expects to understand status without reading text — visual recognition
- Expects to act directly from the view — no additional navigation
- Expects it to "just work" without config — like `ls` in a terminal

**Potential confusion points:**
- "Where are my repos?" if scan doesn't cover the right directories → Empty State with clear CTA
- "What does this color mean?" if status system isn't instinctive → icons + labels, not color alone
- "How do I act on a repo?" if actions aren't discoverable → right-click + command palette

### Success Criteria

**The "Launch and Know" interaction succeeds when:**

1. **2-second scan** — User identifies problematic repos in < 2 seconds visually
2. **Zero learning curve** — First use without documentation, status meanings are instinctive
3. **Pattern recognition** — User perceives patterns ("3 repos behind", "all clean") without individual reading
4. **Action proximity** — User can act on a repo in < 2 clicks from the Card Grid
5. **Scale gracefully** — Experience is equally satisfying with 5 repos (Jay) as with 50+ (Sarah)

**Success feedback:**
- Status badges immediately interpretable (color + icon + count)
- Ahead/behind counts visible directly on cards
- "All clean" is a satisfying visual state — all green = peace of mind
- Dirty/dormant repos "pop" visually — the eye is naturally drawn to problems

### Novel UX Patterns

**Established patterns adopted:**
- Card Grid (Docker Desktop, Trello) — familiar, adapted for multi-entity
- Status color system (traffic lights, Docker) — universally understood
- Multi-select + batch actions (email clients, file managers) — known pattern
- Command palette (VS Code, Linear) — developers know it

**GitPulse's unique twist:**
- The **Privacy Badge** is a novel pattern in git tools. No competitor offers a privacy indicator. It's a visual differentiator — the green "local" padlock becomes GitPulse's visual signature.
- **Smart Status inline** — AI summaries aren't in a separate panel but integrated directly into cards as natural content. A discreet "AI" badge indicates the source. This "invisible AI augmentation" pattern is new in git tools.
- **Dormancy glow** — Dormant repos get subtle visual treatment (reduced opacity, "sleeping" badge) that signals inactivity without being alarmist. No red — it's information, not a problem.

### Experience Mechanics

**Flow: Launch and Know**

**1. Initiation:**
- Double-click exe/dmg → window opens directly (no splash screen)
- First launch: auto-scan of home directory. Results appear progressively.
- Subsequent launches: cache loaded instantly, then background rescan for updates.

**2. Visual scan (2-second pattern recognition):**
- Eye scans Card Grid left-to-right, top-to-bottom
- Status badges (color + icon) are first fixation point — brain automatically filters by color
- "Problematic" cards (red, orange) attract attention first
- "Clean" cards (green) form a reassuring background
- "Dormant" cards (grey, reduced opacity) blend into the background

**3. Action proximity:**
- Click on card → expand detail (branch, last commit, stash, AI summary)
- Right-click → context menu (pull, push, fetch, open in terminal)
- Multi-select (checkbox or Shift/Ctrl+click) → batch toolbar appears
- Cmd/Ctrl+K → command palette for quick actions

**4. Feedback loop:**
- Batch op in progress → each repo visually transitions (grey → spinner → green/red)
- Results visible in real-time — no need to wait for batch completion
- Errors displayed inline on the concerned repo's card (no global error modal)

**5. Completion:**
- "All clean" is the resting state — user closes dashboard, confident
- System tray continues passive monitoring
- Notification only if a repo changes state (new behind, dirty detected)

## Visual Design Foundation

### Color System

**Philosophy:** GitPulse is a developer desktop tool. Dark mode is the default (developer preference), with full light mode support. Status colors are the heart of the visual system.

**Dark Mode (default):**

| Token | Value | Usage |
|-------|-------|-------|
| `bg-primary` | `gray-950` (#0a0a0a) | Main background |
| `bg-surface` | `gray-900` (#171717) | Card backgrounds |
| `bg-elevated` | `gray-800` (#262626) | Hovered cards, dropdowns |
| `border` | `gray-700` (#404040) | Card borders, dividers |
| `text-primary` | `gray-50` (#fafafa) | Main text |
| `text-secondary` | `gray-300` (#d4d4d4) | Secondary text, labels |
| `text-muted` | `gray-500` (#737373) | Muted text, timestamps |

**Status Colors (shared dark/light):**

| Status | Color | Icon | Tailwind |
|--------|-------|------|----------|
| Clean | Green | CheckCircle | `text-green-500` / `bg-green-500/10` |
| Dirty | Red | AlertCircle | `text-red-500` / `bg-red-500/10` |
| Ahead | Blue | ArrowUpCircle | `text-blue-500` / `bg-blue-500/10` |
| Behind | Orange | ArrowDownCircle | `text-orange-500` / `bg-orange-500/10` |
| Dormant | Gray | Moon | `text-gray-400` / `bg-gray-400/10` |

**Privacy Indicator:**
- Local: `text-green-600` + shield icon + label "Local"
- Cloud: `text-amber-500` + cloud icon + label provider name

**Accessibility:** All text/background combos meet WCAG AA contrast ratio (4.5:1 normal text, 3:1 large text). Status badges always use color + icon + label, never color alone.

### Typography System

**Principle: "Native feel" = system fonts by default.**

GitPulse uses platform system fonts for native rendering. No web fonts to load — instant performance and OS consistency.

**Font stack:**
```css
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans",
             Helvetica, Arial, sans-serif;
```
- macOS: San Francisco
- Windows: Segoe UI
- Linux: Noto Sans

**Code/monospace (branch names, commit hashes):**
```css
font-family: "SF Mono", "Cascadia Code", "Fira Code", "Consolas", monospace;
```

**Type Scale:**

| Role | Size | Weight | Usage |
|------|------|--------|-------|
| `text-xl` | 20px | Semibold (600) | Window title, empty state heading |
| `text-lg` | 18px | Medium (500) | Section headings |
| `text-base` | 16px | Regular (400) | Card repo name, primary content |
| `text-sm` | 14px | Regular (400) | Branch names, status text, AI summaries |
| `text-xs` | 12px | Medium (500) | Timestamps, badges, counts, muted info |

**Line heights:** 1.5 for body text, 1.2 for headings, 1.0 for single-line data (counts, badges).

### Spacing & Layout Foundation

**Base unit: 4px.** All spacing is a multiple of 4px for consistency.

**Spacing Scale:**

| Token | Value | Usage |
|-------|-------|-------|
| `space-1` | 4px | Inline gaps, icon padding |
| `space-2` | 8px | Tight component spacing, badge padding |
| `space-3` | 12px | Card internal padding |
| `space-4` | 16px | Standard padding, card gaps |
| `space-6` | 24px | Section spacing |
| `space-8` | 32px | Major section breaks |

**Card Grid Layout:**
- Grid gap: 16px (`space-4`)
- Card min-width: 280px, max-width: 360px
- Responsive: auto-fill with `minmax(280px, 1fr)`
- Cards per row: adapts to window width (2-5 cards)

**List View Layout:**
- Row height: 56px
- Columns: checkbox | status icon | repo name | branch | ahead/behind | last commit | actions
- Column widths: fixed for status (32px), flexible for name, fixed for counts

**Window Layout:**
- Min window size: 800×600
- Default window size: 1200×800
- Top bar: 48px (title + view toggle + filters + Privacy Badge)
- No sidebar — single-page dashboard

### Accessibility Considerations

- **Contrast:** All text/background combos meet WCAG AA (4.5:1 normal, 3:1 large text)
- **Status identification:** Never color alone — always color + icon + text label
- **Focus indicators:** Visible focus rings (2px ring, offset 2px) on all interactive elements
- **Keyboard navigation:** Tab order logical (top bar → cards → actions), arrow keys within card grid
- **Screen readers:** ARIA labels on all status badges, live regions for batch results and privacy mode changes
- **Reduced motion:** `prefers-reduced-motion` respected — no animations when OS setting is active
- **High contrast:** OS high contrast mode triggers fallback to system colors with enhanced borders

## Design Direction Decision

### Design Directions Explored

Six design directions were generated and evaluated as interactive HTML mockups (`ux-design-directions.html`):

1. **Compact Grid** — Maximum density, tight cards, status badges pop
2. **Spacious Cards** — Breathing room, metric boxes, AI summaries prominent
3. **List-First** — Table layout, batch-native, power user focus
4. **Stats Dashboard + Grid** — Summary metrics bar above card grid
5. **Hybrid Detail Panel** — Split view with left list + right detail panel
6. **Minimal Zen** — Ultra-clean status dots, click-to-expand

### Chosen Direction

**D1 Compact Grid + D4 Stats Bar (combined)**

The compact card grid delivers the 2-second pattern recognition that defines GitPulse's core experience. The collapsible stats bar adds "mission control" context without sacrificing grid density.

**Layout structure (top to bottom):**

1. **Top bar** (48px) — Title, Grid/List toggle, filter pills with counts, rescan button, Privacy Badge
2. **Stats bar** (collapsible, ~60px) — 5 metric cards: Clean / Dirty / Ahead / Behind / Dormant counts
3. **Card Grid** (main area) — Compact repo cards with status badge, branch, ahead/behind/stash, last commit time
4. **Batch toolbar** (appears on multi-select) — Pull, Push, Fetch, Status actions with count

**Card Grid is default view. List View (D3 table) available via toggle for batch operations and power-user sorting/filtering.**

### Design Rationale

**Why Compact Grid (not Spacious):**
- GitPulse's core value is seeing ALL repos at once. More cards visible = better pattern recognition.
- Sarah (30+ repos) needs density. Jay (< 10 repos) doesn't need spaciousness — the empty space would feel worse, not better.
- AI Smart Status fits as a subtle one-liner in the card footer. It enriches without requiring card expansion.

**Why Stats Bar (collapsible):**
- "7 clean, 1 dirty, 2 behind" visible without scanning cards = instant health overview.
- Collapsible because power users (Leo) may find it redundant after the first week.
- Stats bar doubles as a filter — clicking a stat card filters the grid to that status.

**Why not Hybrid Panel (D5):**
- Only one repo visible in detail at a time contradicts GitPulse's "see everything at a glance" principle.
- Detail info (commits, AI summary) accessible via click-to-expand on individual cards instead.

**Why not Minimal Zen (D6):**
- Too minimal for a tool users rely on daily. Branch names and counts are essential, not optional.
- Risks perception of "incomplete" rather than "elegant."

### Implementation Approach

**Component hierarchy:**
```
App
├── TopBar
│   ├── ViewToggle (Grid/List)
│   ├── FilterPills (All, Dirty, Behind, Dormant) with counts
│   ├── RescanButton
│   └── PrivacyBadge
├── StatsBar (collapsible)
│   └── StatCard × 5 (Clean, Dirty, Ahead, Behind, Dormant)
├── CardGrid (default view, virtualized)
│   └── RepoCard × N
│       ├── StatusBadge
│       ├── BranchLabel
│       ├── CountStats (ahead/behind/stash)
│       ├── SmartStatusLine (optional, when AI configured)
│       └── LastCommitTime
├── ListView (toggled view)
│   ├── ListHeader (sortable columns)
│   └── RepoRow × N (with checkboxes)
└── BatchToolbar (appears on multi-select)
    ├── SelectionCount
    └── ActionButtons (Pull, Push, Fetch, Status)
```

## User Journey Flows

### Journey 1: First Launch (Jay's Journey — 5-Second Wow)

**Goal:** Jay downloads GitPulse, launches, and sees a full dashboard in < 30 seconds. Zero config, zero login.

```mermaid
flowchart TD
    A[Download binary] --> B[Launch GitPulse]
    B --> C{First launch?}
    C -->|Yes| D[Auto-scan home directory]
    C -->|No| E[Load cached repos instantly]
    D --> F[Show scan progress: repo count climbing]
    F --> G{Repos found?}
    G -->|0 repos| H[Empty State: Add scan directories CTA]
    G -->|1-9 repos| I[Card Grid + Stats Bar]
    G -->|10+ repos| I
    E --> I
    H --> J[User adds scan root]
    J --> D
    I --> K[User sees status badges at a glance]
    K --> L{Problem repos visible?}
    L -->|Yes| M[Click dirty/behind card for detail]
    L -->|No| N[All clean = peace of mind]
    M --> O[Right-click context menu: Pull / Open terminal]
    N --> P[Close dashboard or minimize to tray]
```

**Entry points:** Double-click binary, system tray icon click
**Success criteria:** Dashboard visible with repo statuses in < 30 seconds from launch
**Error recovery:** 0 repos → Empty State with clear CTA to add scan directories
**Feedback:** Scan progress shows repo count climbing, skeleton cards during load

### Journey 2: Daily Status Check (Sarah's Journey — Morning Check-in)

**Goal:** Sarah opens GitPulse in the morning, identifies in 2 seconds the 3 repos needing attention among 30+ repos.

```mermaid
flowchart TD
    A[Launch GitPulse] --> B[Cache loads instantly]
    B --> C[Background rescan starts]
    C --> D[Stats Bar: 24 clean, 3 dirty, 2 behind, 1 dormant]
    D --> E[Sarah scans Card Grid visually]
    E --> F[Eye drawn to red/orange cards]
    F --> G[auth-service: Dirty, 3 uncommitted]
    F --> H[shared-libs: Behind 12 commits]
    F --> I[old-experiment: Dormant, 3 months]
    G --> J[Click auth-service card]
    J --> K[Card expands: branch, stash, AI summary]
    K --> L[Right-click: Open in terminal]
    H --> M[Select shared-libs checkbox]
    M --> N[Batch toolbar appears]
    N --> O[Click Pull]
    O --> P[Streaming results: green checkmark appears]
    I --> Q[Note: will clean up later]
    L --> R[Commit and push in terminal]
    P --> S[Stats Bar updates: behind count drops to 0]
    R --> T[Rescan: auth-service turns green]
    T --> U[All clean. Close dashboard. Tray continues monitoring.]
```

**Entry points:** App launch, system tray click
**Success criteria:** Problem repos identified in < 2 seconds, action taken in < 30 seconds
**Feedback:** Stats bar provides numeric context, card colors provide instant pattern recognition
**Error recovery:** Pull fails on shared-libs → red X with error detail inline, other repos unaffected

### Journey 3: Batch Operations (Leo's Journey — Sprint Start)

**Goal:** Leo batch-pulls 12 microservice repos at sprint start, then uses Smart Status to verify overall health.

```mermaid
flowchart TD
    A[Leo opens GitPulse] --> B[Switch to List View]
    B --> C[Click column header: Sort by Behind]
    C --> D[12 repos behind remote]
    D --> E[Select All behind]
    E --> F[Batch toolbar: 12 repos selected]
    F --> G[Click Pull]
    G --> H[Streaming results appear row by row]
    H --> I{Per-repo result}
    I -->|Success| J[Row turns green, checkmark]
    I -->|Auth error| K[Row turns red, error detail inline]
    I -->|Conflict| L[Row turns red, merge conflict message]
    J --> M[10/12 succeeded]
    K --> N[2/12 failed: api-auth, payment-svc]
    L --> N
    M --> O[Click failed repo for error detail]
    N --> O
    O --> P[Resolve in terminal or retry]
    P --> Q[Rescan: all green]
    Q --> R[Configure DeepSeek API key in Settings]
    R --> S[Privacy Badge: Local changes to Cloud DeepSeek]
    S --> T[Smart Status summaries appear on cards]
    T --> U[AI: All microservices synced. Shared auth library version mismatch in 2 repos.]
```

**Entry points:** App launch, Monday morning routine
**Success criteria:** 12 repos pulled in < 30 seconds, partial failures clearly reported
**Feedback:** Streaming per-repo results, success count updating in real-time
**Error recovery:** Failed repos show specific error (auth, conflict), successful repos complete independently

### Journey 4: Dormancy Cleanup (Max's Journey — Monthly Review)

**Goal:** Max discovers 8 dormant repos and decides which to archive.

```mermaid
flowchart TD
    A[Max opens GitPulse] --> B[Filter: Dormant]
    B --> C[8 repos shown with reduced opacity]
    C --> D[Stats Bar: 8 dormant more than 90 days]
    D --> E[Scan cards: old-prototype, tutorial-clone...]
    E --> F[Click old-prototype card]
    F --> G[Smart Status: Last commit 6 months ago. Safe to archive.]
    G --> H{Action?}
    H -->|Archive| I[Right-click: Open in file manager]
    H -->|Keep| J[Move on to next]
    I --> K[Manually archive/move directory]
    J --> L[Rescan: dormant repos update]
    K --> L
    L --> M[Check remaining repos]
    M --> N[3 repos have uncommitted changes from weeks ago]
    N --> O[Select 3 then Batch status]
    O --> P[Review uncommitted changes]
    P --> Q[Decide: commit and push or discard]
```

**Entry points:** Weekly/monthly review, tray notification ("3 repos dormant for 90+ days")
**Success criteria:** Identify and action dormant repos in a single session
**Feedback:** Dormant filter shows only relevant repos, reduced opacity visually deprioritizes them
**Error recovery:** No destructive actions in GitPulse — "archive" opens file manager, user decides

### Journey Patterns

**Navigation Pattern — Filter then Act:**
1. User applies a filter (status, or click stat card) → grid shows only matching repos
2. User scans filtered results → identifies targets
3. User selects and acts → batch toolbar appears
4. Results stream in → grid updates in real-time

**Feedback Pattern — Streaming Progress:**
1. Action triggered → all selected items show "loading" state (grey spinner)
2. Each item completes → transitions to success (green) or failure (red + detail)
3. Progress counter in toolbar: "10/12 complete"
4. Stats bar updates after all items finish

**Error Pattern — Isolate and Report:**
1. Error occurs on one item → only that item affected
2. Item shows inline error detail (not modal)
3. User clicks error for expanded detail
4. Other items continue processing unaffected

### Flow Optimization Principles

1. **Minimize steps to value** — Every journey starts with "open and see." No intermediate screens between launch and dashboard.
2. **Progressive disclosure** — Card shows essential info. Click expands detail. Right-click offers actions. No information overload on first glance.
3. **Batch by default** — Multi-select and batch toolbar make acting on multiple repos as natural as acting on one.
4. **Error isolation** — Failures never block successes. Every batch operation shows per-item results independently.
5. **Stats as navigation** — Clicking a stat card (e.g., "3 dirty") filters the grid, combining overview and action in one interaction.

## Component Strategy

### Design System Components

**From Radix UI (styled with Tailwind tokens):**

| Radix Primitive | GitPulse Usage | Styling |
|----------------|----------------|---------|
| `Dialog` | Settings panels, AI config | Tailwind: bg-surface, border, rounded-xl |
| `Select` | Sort dropdown, filter selector | Tailwind: custom trigger, status-colored options |
| `Tooltip` | Status badge hover details, counts | Tailwind: bg-elevated, text-sm, delay-300 |
| `DropdownMenu` | Right-click context on cards/rows | Tailwind: bg-surface, items with icons |
| `Checkbox` | Batch selection in List View | Tailwind: border, rounded, checked:bg-blue-500 |
| `ToggleGroup` | Grid/List view switch | Tailwind: border, rounded-lg, active:bg-elevated |
| `Popover` | Card detail expansion on click | Tailwind: bg-surface, shadow-xl |
| `Separator` | Stats bar dividers, card sections | Tailwind: bg-border |

**From Lucide React (icons):**

| Icon | Usage | Component |
|------|-------|-----------|
| CheckCircle | Clean status | StatusBadge |
| AlertCircle | Dirty status | StatusBadge |
| ArrowUpCircle | Ahead status | StatusBadge |
| ArrowDownCircle | Behind status | StatusBadge |
| Moon | Dormant status | StatusBadge |
| Shield | Privacy local | PrivacyBadge |
| Cloud | Privacy cloud | PrivacyBadge |
| RefreshCw | Rescan | TopBar |
| Grid / List | View toggle | ViewToggle |
| GitBranch | Branch label | RepoCard |
| Clock | Last commit | RepoCard |
| Inbox | Stash count | RepoCard |

### Custom Components

#### RepoCard

**Purpose:** Display a single repository's status in the Card Grid. The fundamental unit of the GitPulse dashboard.

**Anatomy:**
```
+------------------------------+
|  repo-name          [Badge]  |  header: name + StatusBadge
|  branch-name                 |  monospace branch label
|  Ahead: 3  Behind: 0  S: 0  |  count stats
|  --------------------------- |  subtle divider
|  2h ago        3 unpushed    |  footer: time + action badge
|  AI: 3 unpushed commits...   |  SmartStatusLine (optional)
+------------------------------+
```

**States:** default, hover (border-lighten, bg-elevated), selected (border-blue), loading (skeleton), error (border-red), dormant (opacity-50)

**Accessibility:** role="article", tabindex=0, aria-label="Repository {name}: {status}, {ahead} ahead, {behind} behind", Enter/Space opens detail popover

#### RepoRow

**Purpose:** Table row for List View with sortable columns and checkbox selection.

**Anatomy:**
```
[checkbox] [icon] repo-name  branch  up:3  down:0  2h ago  [menu]
```

**States:** default, hover (bg-elevated), selected (bg-blue/5), loading, error (bg-red/5)

**Accessibility:** role="row", aria-selected, checkbox keyboard accessible

#### StatusBadge

**Purpose:** Compact visual indicator for repository status. Always uses color + icon + label text.

**Variants:**

| Variant | Color | Icon | Label |
|---------|-------|------|-------|
| clean | green-500 | CheckCircle | "Clean" |
| dirty | red-500 | AlertCircle | "Dirty" |
| ahead | blue-500 | ArrowUpCircle | "Ahead" |
| behind | orange-500 | ArrowDownCircle | "Behind" |
| dormant | gray-400 | Moon | "Dormant" |

**Sizes:** sm (10px text, compact cards), md (12px text, default), lg (14px text, stats bar)

**Accessibility:** aria-label="{status} repository", never relies on color alone

#### StatsBar

**Purpose:** Summary metrics bar at top of dashboard. Collapsible. Each stat card is clickable to filter grid.

**Anatomy:**
```
+--------+ +--------+ +--------+ +--------+ +--------+
|   7    | |   1    | |   3    | |   2    | |   1    |
| Clean  | | Dirty  | | Ahead  | | Behind | |Dormant |
+--------+ +--------+ +--------+ +--------+ +--------+
```

**States:** Each stat card: default, hover (cursor-pointer, bg-elevated), active/filtered (border-status-color)

**Accessibility:** Each card has aria-label="{count} {status} repositories", role="button", click filters grid

#### PrivacyBadge

**Purpose:** Permanent indicator showing local vs cloud data processing mode. Always visible in TopBar.

**Variants:**

| Mode | Icon | Color | Label |
|------|------|-------|-------|
| local/no AI | Shield | green-600 | "Local" |
| Ollama | Shield | green-600 | "Local" |
| Cloud provider | Cloud | amber-500 | "{Provider}" |

**States:** Transition animation when mode changes (subtle color crossfade), aria-live="polite" announces change to screen readers

#### BatchToolbar

**Purpose:** Appears when repos are selected. Shows count and action buttons.

**Anatomy:**
```
| 3 selected  [Pull]  [Push]  [Fetch]  [Status]  [Cancel] |
```

**States:** Appears with slide-down animation, disappears when selection clears, buttons disabled during active operation, progress counter replaces selection count during operation

**Accessibility:** role="toolbar", aria-label="{count} repositories selected", each button has aria-label with action + count

#### SmartStatusLine

**Purpose:** AI-generated one-line health summary. Appears in RepoCard footer when AI is configured.

**Anatomy:**
```
| AI: 3 unpushed commits on feature branch. Ready for PR. |
```
Blue left border (2px), text-sm, text-secondary, italic, optional "AI" micro-badge

**States:** loading (skeleton pulse), loaded (text), error (hidden — no error shown, graceful absence)

**Accessibility:** aria-label="AI summary: {text}", visually indicated by left border color

#### EmptyState

**Purpose:** Displayed when no repos are found. Engaging CTA to add scan directories.

**Anatomy:**
```
+----------------------------------+
|         [Git illustration]       |
|    No repositories found         |
|    Add directories to scan       |
|    [Open Settings]               |
|                                  |
|    Tip: GitPulse scans for       |
|    .git folders recursively      |
+----------------------------------+
```

**Accessibility:** role="status", aria-live="polite", CTA button keyboard focusable

### Component Implementation Strategy

**Layer 1 — Radix + Tailwind Primitives** (`components/ui/`):
- Button, Card, Dialog, Select, Tooltip, DropdownMenu, Checkbox, ToggleGroup, Input, Skeleton
- Each wraps Radix with Tailwind styling. No custom logic.

**Layer 2 — GitPulse Domain Components** (`components/dashboard/`, `components/batch/`, `components/ai/`):
- RepoCard, RepoRow, StatusBadge, StatsBar, PrivacyBadge, BatchToolbar, SmartStatusLine, EmptyState
- Composed from Layer 1 primitives + domain logic (Tauri IPC calls via hooks)

**Layer 3 — Feature Compositions** (`App.tsx`):
- TopBar, CardGrid, ListView
- Wire Layer 2 components together with stores and hooks

### Implementation Roadmap

**Phase 1 — Core Dashboard (FR1-FR13):**
1. StatusBadge — foundation for all visual status
2. RepoCard — core card component
3. CardGrid — virtualized grid with @tanstack/react-virtual
4. StatsBar — summary metrics
5. EmptyState — 0 repos experience

**Phase 2 — Batch Operations (FR15-FR21):**
6. RepoRow — list view row with checkbox
7. BatchToolbar — selection actions
8. ListView — sortable table with virtualization

**Phase 3 — AI & Settings (FR22-FR41):**
9. PrivacyBadge — trust indicator
10. SmartStatusLine — AI summary in cards
11. Settings panels — using Radix Dialog + primitives

## UX Consistency Patterns

### Button Hierarchy

| Priority | Style | Usage | Example |
|----------|-------|-------|---------|
| **Primary** | bg-blue-500, text-white, rounded-lg | Main action per context | "Pull", "Save Settings" |
| **Secondary** | bg-elevated, border, text-primary | Alternative actions | "Push", "Fetch", "Cancel" |
| **Destructive** | bg-red-500/10, text-red-500, border-red | Irreversible actions | "Reset All Settings" |
| **Ghost** | transparent, text-secondary, hover:bg-elevated | Low-priority, toolbar | "Rescan", view toggle icons |
| **Disabled** | opacity-50, cursor-not-allowed | Unavailable action | Batch buttons during active op |

**Rules:**
- Only one primary button visible per context
- Destructive actions always require confirmation (Radix Dialog)
- Button text is always a verb ("Pull", not "OK")
- Icon + text for primary, icon-only for ghost/toolbar with tooltip

### Feedback Patterns

**Success:**
- Repo-level: card/row transitions to green checkmark, brief green flash on status badge
- Batch-level: counter updates "10/12 complete", stats bar numbers animate
- No toast/notification for success — the visual state change IS the feedback

**Error:**
- Repo-level: card/row shows red border + inline error text (e.g., "Auth failed", "Merge conflict")
- Batch-level: failed repos highlighted, successful repos remain green. "2/12 failed" in toolbar
- Error detail: click failed repo → popover with full error message + suggested action
- Never modal for batch errors — always inline

**Warning:**
- Privacy mode change: PrivacyBadge transitions with amber flash + aria-live announcement
- Dormancy: reduced opacity + dormant badge, no red/orange alarm

**Info:**
- Scan progress: repo count climbs in real-time ("Scanning... 12 repos found")
- Background rescan: subtle progress indicator in top bar, non-blocking

### Loading States

**Skeleton loading (initial load):**
- Card grid shows skeleton cards (grey rectangles matching RepoCard shape) during first scan
- No central spinner — skeleton cards communicate layout and progress simultaneously
- Skeleton count matches cached repo count if available, otherwise show 6 skeletons

**Streaming loading (batch operations):**
- Each repo transitions individually: default → spinner overlay → green/red result
- Other repos remain interactive during batch — user can still click and explore
- Batch toolbar shows progress counter: "Pulling... 7/12"

**Inline loading (AI queries):**
- SmartStatusLine shows skeleton pulse animation while AI generates summary
- Other card content remains visible and interactive during AI load
- If AI fails or times out: SmartStatusLine simply doesn't appear (graceful absence)

**Never:**
- Never a full-page spinner blocking all interaction
- Never a modal "Loading..." dialog
- Never disable the entire UI during an operation

### Empty States

**0 repos found:**
- Center of dashboard: Git illustration, "No repositories found", "Add directories to scan"
- Primary CTA button: "Open Settings" → opens Settings to Scan Roots tab
- Secondary text: "GitPulse scans for .git folders recursively"
- Stats bar hidden (no data to show)

**0 results after filter:**
- Center of grid area: "No {status} repositories" with filter icon
- Ghost button: "Clear filter" → resets filter to "All"
- Suggestion: "Try a different filter or rescan"

**First launch scanning:**
- "Scanning your directories..." with animated repo count
- First repo appears immediately as skeleton → fills in as discovered
- Transition from empty state to card grid is seamless (cards appear progressively)

### Navigation Patterns

**Primary navigation — single page:**
- No sidebar, no tabs, no routing. The dashboard IS the app.
- Content changes via: filters, view toggle, card expansion

**Context menus — right-click:**
```
[Repo name]
─────────────
Pull
Push
Fetch
─────────────
Open in Terminal
Open in File Manager
Copy Path
─────────────
Refresh Status
```
- Dividers separate action groups (git ops / system / utility)
- Actions use Lucide icons + text label
- Disabled items shown greyed, not hidden

**Command palette — Cmd/Ctrl+K:**
```
+----------------------------------+
|  Search commands...              |
+----------------------------------+
|  Rescan All Repositories         |
|  Toggle Grid / List View         |
|  Filter: Dirty Repos             |
|  Filter: Behind Repos            |
|  Batch Pull Selected             |
|  Open Settings                   |
|  Open AI Configuration           |
|  Check for Updates               |
+----------------------------------+
```
- Fuzzy search on command names
- Keyboard navigable (arrow keys + Enter)
- Esc to close

### Additional Patterns

**Toastless design:**
- GitPulse does not use toast notifications in the dashboard
- All feedback is inline (card states, toolbar counters, stats bar)
- System tray uses native OS notifications for background alerts only

**Keyboard shortcuts:**

| Shortcut | Action |
|----------|--------|
| Cmd/Ctrl+K | Command palette |
| Cmd/Ctrl+G | Switch to Grid view |
| Cmd/Ctrl+L | Switch to List view |
| Cmd/Ctrl+R | Rescan |
| Cmd/Ctrl+, | Open Settings |
| Cmd/Ctrl+A | Select all repos |
| Escape | Clear selection / close palette |
| Space (on card) | Toggle selection |
| Enter (on card) | Expand detail |

**Confirmation patterns:**
- Destructive actions (Reset Settings): Radix Dialog with "This cannot be undone" + Cancel/Confirm
- Batch operations on 10+ repos: no confirmation — progress is visible, user can cancel mid-operation
- Privacy mode change: no confirmation needed — PrivacyBadge updates, user can revert in Settings

**Window behavior:**
- Closing window → minimizes to system tray (app continues running)
- Cmd/Ctrl+Q or tray Quit → actually quits
- Window position/size remembered across launches

## Responsive Design & Accessibility

### Responsive Strategy

**Desktop-only — no mobile, no tablet.**

GitPulse is a native desktop application (Tauri v2). Responsive design is limited to adapting the desktop window between minimum size (800x600) and large screens (2560x1440+).

**No mobile/tablet strategy:**
- No touch interactions
- No bottom navigation
- No hamburger menu
- No mobile breakpoints
- System tray handles the "minimal" context when dashboard is closed

**Window resize adaptation:**

| Window Width | Card Grid Behavior | Stats Bar | Top Bar |
|-------------|-------------------|-----------|---------|
| < 900px | 2 cards per row | Collapsed (icon counts only) | Filters hidden in dropdown |
| 900-1200px | 3 cards per row | Expanded (5 stat cards) | Full top bar |
| 1200-1600px | 4 cards per row | Expanded | Full top bar |
| > 1600px | 5+ cards per row | Expanded | Full top bar, more breathing room |

**Window height adaptation:**
- < 600px (minimum): stats bar auto-collapsed, grid scrollable
- 600-800px: stats bar visible, grid fits ~3 rows of cards
- > 800px: full experience, 4+ rows visible without scroll

**Resize behavior:**
- Card grid reflows immediately (CSS Grid auto-fill)
- Stats bar collapse/expand is smooth, no content jump
- Window position and size persisted via `tauri-plugin-store`
- Min window size enforced: 800x600

### Breakpoint Strategy

**Desktop breakpoints only (CSS media queries within Tauri webview):**

| Breakpoint | Width | Layout Change |
|-----------|-------|---------------|
| `sm` | < 900px | 2-col grid, collapsed stats, compact top bar |
| `md` | 900-1199px | 3-col grid, full stats, full top bar |
| `lg` | 1200-1599px | 4-col grid (default) |
| `xl` | >= 1600px | 5+ col grid, max-width container optional |

**Implementation:** Tailwind breakpoints (`sm:`, `md:`, `lg:`, `xl:`) applied directly in component classes. No CSS-in-JS, no runtime theme switching.

### Accessibility Strategy

**Target: WCAG 2.1 Level AA** (industry standard, addresses NFR25-27)

**1. Color & Contrast (NFR26):**
- All text meets 4.5:1 contrast ratio (normal text), 3:1 (large text/UI components)
- Status indicators never rely on color alone — always color + icon + text label
- StatusBadge tested against: protanopia, deuteranopia, tritanopia, achromatopsia
- High contrast mode: OS setting triggers fallback to system colors + enhanced borders

**2. Keyboard Navigation (NFR25):**
- All interactive elements reachable via Tab
- Arrow keys navigate within card grid (2D grid navigation pattern)
- Enter/Space activates focused element
- Escape closes popovers/command palette
- Focus trap in Dialog (settings) — Tab cycles within dialog
- Visible focus indicators: 2px ring, offset 2px, blue-500 color
- Skip-to-content: Cmd/Ctrl+K serves as universal keyboard entry point

**3. Screen Reader Compatibility (NFR27):**
- ARIA landmarks: main (dashboard), navigation (top bar), toolbar (batch)
- ARIA labels on all status badges: "Repository auth-service: Dirty, 7 commits ahead"
- aria-live="polite" for dynamic content: batch results, privacy mode changes, scan progress
- RepoCard: role="article" with descriptive aria-label
- StatsBar: each stat card has role="button" with aria-label
- SmartStatusLine: aria-label="AI summary: {text}"
- Error states: aria-live="assertive" for critical errors

**4. Motion & Animation:**
- `prefers-reduced-motion` media query respected
- All transitions use `motion-safe:` Tailwind prefix
- No auto-playing animations
- Skeleton loading: static when reduced-motion preferred

**5. Focus Management:**
- Dialog opens → focus trapped in dialog, first interactive element focused
- Dialog closes → focus returns to trigger element
- Command palette → focus trapped in palette list
- Card expansion → focus moves to expanded content
- Tab order: top bar → stats bar → card grid → batch toolbar

### Testing Strategy

**Automated testing:**
- Playwright e2e tests with `@axe-core/playwright` for automated WCAG checks
- Run on every PR via CI
- Key scenarios: dashboard load, card grid rendering, batch operations, settings dialog

**Manual testing (per release):**
- Keyboard-only navigation: complete all core journeys without mouse
- Screen reader testing: macOS VoiceOver (primary), Windows NVDA
- Color blindness simulation: Chrome DevTools color vision deficiency
- High contrast mode: Windows High Contrast, macOS Increase Contrast

**Test matrix:**

| Platform | Screen Reader | Test Focus |
|----------|--------------|------------|
| macOS | VoiceOver | Card grid nav, batch ops, settings |
| Windows | NVDA | Full journey: scan → dashboard → batch |
| Linux | Orca | Basic dashboard navigation |

### Implementation Guidelines

**For AI agents implementing components:**

1. All status indicators must use StatusBadge component — never ad-hoc colored elements
2. All interactive elements must have focus-visible styles and keyboard handlers
3. All dynamic content must have aria-live region for announcements
4. All dialogs must use Radix Dialog (handles focus trap and aria automatically)
5. All icons must have accompanying text or aria-label — never icon-only meaning
6. All batch operations must emit per-repo events with accessible status updates
7. Window resize must use Tailwind responsive classes, never JavaScript resize listeners
8. Reduced motion must use Tailwind `motion-safe:` prefix for all transitions/animations
