feat: Slate & Ice Modern aesthetic redesign (#94)

* chore: update Google Fonts to Bricolage Grotesque, IBM Plex Sans, JetBrains Mono

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* chore: update Tailwind config to Slate & Ice theme colors and fonts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: update CSS variables and glass-card utilities for Slate & Ice theme

- Replace all color variables with Slate & Ice palette
- Add glass system vars (--glass-bg, --glass-blur, --shadow-float)
- Replace legacy glass-card with new variable-driven glass classes
- Add breatheGlow, bellWobble, slideDown, fadeInRight keyframes
- Update font references to IBM Plex Sans and Bricolage Grotesque

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: recolor BrandLogo to cyan gradient, split BrandWordmark for gradient Flow text

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: update TopBar with glassmorphism backdrop and cyan accent styling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: update Sidebar with glassmorphism backdrop

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add ambient atmosphere gradient orbs behind app shell

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: update QuickStats and SessionsPanel with glass-card styling

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add WeeklyCalendar, QuickActions, OpenSessions, RecentActivity dashboard components

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: redesign dashboard layout with calendar, open sessions, and glass-card panels

New layout: greeting → calendar+actions → sessions+stats → activity
Replaces old QuickStats and SessionsPanel with new dashboard components

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: replace remaining purple hex references with ice-cyan accent

Sweep of hardcoded purple hex values (#818cf8, #6366f1) replaced with
new cyan accent (#06b6d4) in QuickActions, RecentActivity, QuickLaunch,
and SVG brand assets.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: update CLAUDE.md branding and design system for Slate & Ice Modern

Updated Last Updated date, branding section (fonts, colors, glass
utilities, atmosphere orbs), component styling rules, and Design System
section to reflect the new ice-cyan glassmorphism theme.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* docs: add Slate & Ice Modern design doc and implementation plan

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: redesign login page with Slate & Ice Modern design system

Apply glassmorphism styling, atmosphere orbs, branded wordmark, and
consistent design tokens to match the updated app shell aesthetic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: raise TopBar z-index so profile dropdown renders above main content

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add AI assistant with in-session copilot and standalone chat with RAG

Implements three-phase AI assistant feature:
- Phase 0: RAG infrastructure with pgvector embeddings, Voyage AI integration,
  tree chunking service, and semantic search over team's flow library
- Phase 1: In-session copilot panel during flow navigation with contextual
  AI help, current step awareness, and suggested related flows
- Phase 2: Standalone AI chat page with persistent conversation history,
  pin/delete, and configurable retention policies (account-level)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add account management, email verification, AI fixes, and user guides

- Profile settings, account transfer, delete/leave account flows
- Email verification with JWT tokens and Resend integration
- AI assistant/copilot fixes: markdown rendering, shared RAG helpers,
  token tracking, input refocus, model_validate usage
- User guides hub + detail pages with 13 topic guides
- Sidebar and top bar navigation for guides

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: prevent stale chunk errors after deployments

- Set Cache-Control no-cache on index.html in nginx so browsers always
  fetch fresh chunk references after a deploy
- Auto-reload on chunk load failures (stale deploy detection) with
  loop prevention via sessionStorage
- Show friendly "App Updated" message if auto-reload doesn't resolve it

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: add email verification toggle to admin settings

Adds platform-level toggle to enable/disable email verification.
When disabled, the verification banner is hidden and the send
endpoint returns 403.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit was merged in pull request #94.
This commit is contained in:
chihlasm
2026-03-04 20:44:25 -05:00
committed by GitHub
parent 554ad84d9e
commit 4d2c4930fd
100 changed files with 8181 additions and 466 deletions

View File

@@ -0,0 +1,263 @@
# Frontend Standardization: Full Audit & Fix
## Objective
Perform a comprehensive audit of the entire ResolutionFlow frontend and standardize four UI patterns that are currently inconsistent across the application. Create reusable components where they don't exist, then retrofit every page and component to use them. When done, the entire app should feel like one developer built every page.
Use every tool, agent, and skill at your disposal. Search every file. Don't ask — fix.
---
## Pattern 1: Loading States → Replace All Spinners with Skeleton Components
### The Problem
Loading states are implemented differently across the app. Some pages use a centered spinning circle, others use pulse-animated rectangles, and some use nothing. There is no shared reusable skeleton component.
### Current Inconsistencies to Find and Fix
**Spinner pattern (replace everywhere you find it):**
```tsx
// THIS PATTERN — find every instance and replace with skeletons
<div className="flex justify-center py-12">
<div className="h-8 w-8 animate-spin rounded-full border-4 border-primary border-t-transparent" />
</div>
```
**Known locations (search for more):**
- `frontend/src/pages/SessionHistoryPage.tsx` — uses spinner
- `frontend/src/pages/TreeLibraryPage.tsx` — uses spinner
- `frontend/src/components/step-library/StepLibraryBrowser.tsx` — uses spinner or loading boolean
- `frontend/src/pages/QuickStartPage.tsx` — uses spinner or loading state
- `frontend/src/pages/TreeEditorPage.tsx` — check for loading state
- `frontend/src/pages/SessionDetailPage.tsx` — check for loading state
- `frontend/src/pages/TreeNavigationPage.tsx` — check for loading state
- `frontend/src/pages/MyTreesPage.tsx` — check for loading state
- Any other page or component with `isLoading` state
### What to Build
**Create `frontend/src/components/common/Skeleton.tsx`:**
A set of composable skeleton primitives:
```tsx
// Base skeleton block with pulse animation
export function Skeleton({ className }: { className?: string }) {
return <div className={cn("animate-pulse rounded bg-muted", className)} />
}
// Pre-built skeleton layouts for common patterns:
export function SkeletonCard() { /* Card-shaped skeleton matching TreeGridView card dimensions */ }
export function SkeletonRow() { /* Row-shaped skeleton matching TreeListView row dimensions */ }
export function SkeletonTableRow() { /* Table row skeleton matching TreeTableView row */ }
export function SkeletonText({ lines = 3 }: { lines?: number }) { /* Text block skeleton */ }
```
### The Standard (enforce everywhere)
- **Page-level data loading:** Show skeleton placeholders that match the shape of the content that will appear. Grid pages get skeleton cards. List pages get skeleton rows. Detail pages get skeleton text blocks.
- **Component-level loading:** Small inline skeletons (e.g., a single line for a name loading).
- **Never show a centered spinner.** The only acceptable spinner is on a button that is performing an action (e.g., "Saving..." with a small inline spinner). Page/section loading always uses skeletons.
- **Skeleton count should match expected content.** If a page typically shows 6 cards, show 6 skeleton cards. If a list shows 10 rows, show 10 skeleton rows.
### Audit Instructions
1. Search the entire `frontend/src/` directory for: `animate-spin`, `border-t-transparent`, `Loader2` (Lucide spinner icon), and any `isLoading` state variable.
2. For every match, determine if it's a page/section loading state or a button action state.
3. Replace all page/section loading states with appropriate skeleton components.
4. Leave button-level spinners alone (e.g., "Saving..." on submit buttons is fine).
---
## Pattern 2: Empty States → Add Meaningful Messages + CTAs Everywhere
### The Problem
Empty states across the app are bare text with no guidance and no call to action. A new user sees "No sessions found." or "No trees found." and has no idea what to do next.
### Current Inconsistencies to Find and Fix
**Known bare empty states:**
- `SessionHistoryPage.tsx`: `"No sessions found."` — no CTA
- `TreeLibraryPage.tsx`: `"No trees found. Try adjusting your filters."` — has filter hint but no create CTA
- `StepLibraryBrowser.tsx`: check for empty state pattern
- `QuickStartPage.tsx`: check for empty state pattern
- `MyTreesPage.tsx`: check for empty state pattern
- Any page that renders a list and has a `length === 0` check
### What to Build
**Create `frontend/src/components/common/EmptyState.tsx`:**
```tsx
interface EmptyStateProps {
icon?: React.ReactNode // Optional icon above the message
title: string // e.g., "No sessions yet"
description?: string // e.g., "Start a troubleshooting session to see it here"
action?: {
label: string // e.g., "Start a Session"
onClick: () => void
}
secondaryAction?: {
label: string // e.g., "Clear filters"
onClick: () => void
}
}
```
### The Standard (enforce everywhere)
Every empty state must have:
1. **A clear title** that says what's empty (not just "No results")
2. **A description** that tells the user why it's empty or what to do
3. **A primary CTA** (when applicable) that lets them take the obvious next action
4. **A secondary action** (when applicable) for filter/search scenarios: "Clear filters" or "Try a different search"
**Context-specific empty states:**
| Page / Section | Title | Description | CTA |
|---|---|---|---|
| Session History (no sessions at all) | "No sessions yet" | "Start a troubleshooting session to see your history here" | "Browse Flows" → navigate to /trees |
| Session History (filter returns empty) | "No matching sessions" | "Try adjusting your filters" | "Clear filters" → reset filter |
| Tree Library (no trees at all) | "No flows available" | "Create your first troubleshooting flow to get started" | "Create Flow" → open create dropdown/navigate |
| Tree Library (search returns empty) | "No flows match your search" | "Try different keywords or clear your filters" | "Clear search" → reset search |
| My Trees (no authored trees) | "You haven't created any flows yet" | "Build a troubleshooting flow to guide your team" | "Create Flow" → open create dropdown |
| Step Library (no steps) | "No steps found" | "Create your first reusable step" | "Create Step" → open create form |
| Dashboard Favorites (no pins) | "No favorites yet" | "Star a flow to pin it here for quick access" | No button (action is contextual) |
| Dashboard My Flows (no authored flows) | "You haven't created any flows yet" | "Build your first troubleshooting flow" | "Create your first flow" → open create dropdown |
### Audit Instructions
1. Search `frontend/src/` for: `length === 0`, `.length === 0`, `sessions.length`, `trees.length`, and any conditional rendering that shows text when a list is empty.
2. For every match, check if the empty state has a title, description, and CTA.
3. Replace bare text empty states with the `EmptyState` component using the appropriate context from the table above.
4. If you find an empty state not listed in the table, follow the same pattern: clear title, helpful description, obvious next action.
---
## Pattern 3: Accessibility — Aria Labels on All Icon-Only Buttons
### The Problem
Some icon-only buttons have proper `aria-label` attributes (e.g., `ThemeToggle` uses `aria-label={`Switch to ${label} theme`}`), but most don't. Icon buttons without aria-labels are invisible to screen readers.
### The Gold Standard (already in the codebase)
From `ThemeToggle.tsx`:
```tsx
<button
onClick={() => setTheme(value)}
className={cn('rounded p-1.5 transition-colors', ...)}
aria-label={`Switch to ${label} theme`}
aria-pressed={theme === value}
>
<Icon className="h-4 w-4" />
</button>
```
From `StepDetailModal.tsx`:
```tsx
<button
onClick={onClose}
className="rounded-md p-1 hover:bg-accent"
aria-label="Close"
>
<X className="h-5 w-5" />
</button>
```
### The Standard (enforce everywhere)
Every `<button>` that contains only an icon (no visible text) MUST have:
1. `aria-label="Descriptive action"` — describes what the button does, not what the icon looks like
2. For toggle buttons: `aria-pressed={isActive}` (like the ThemeToggle pattern)
3. For buttons inside clickable parent containers (cards, rows): `e.stopPropagation()` and `e.preventDefault()` in the onClick handler
**Common icon buttons to look for:**
- Close buttons (X icon) → `aria-label="Close"`
- Delete buttons (Trash icon) → `aria-label="Delete [thing]"`
- Edit buttons (Pencil icon) → `aria-label="Edit [thing]"`
- Filter clear buttons (X in a chip) → `aria-label="Remove [filter name] filter"`
- Expand/collapse buttons (ChevronDown/Up) → `aria-label="Expand"` / `aria-label="Collapse"`
- Copy buttons → `aria-label="Copy to clipboard"`
- Pin/favorite buttons → `aria-label="Add to favorites"` / `aria-label="Remove from favorites"`
- Sort buttons → `aria-label="Sort by [field]"`
- Navigation arrows → `aria-label="Previous page"` / `aria-label="Next page"`
- Menu/hamburger buttons → `aria-label="Open menu"`
- Any icon-only button with `<SomeLucideIcon />` and no text sibling
### Audit Instructions
1. Search `frontend/src/` for all `<button` elements.
2. For each button, check if it contains visible text content (a text node or a `<span>` with text).
3. If the button contains ONLY an icon (Lucide component, SVG, or image) with no visible text, verify it has an `aria-label`.
4. If `aria-label` is missing, add an appropriate one based on the button's purpose (check the onClick handler and surrounding context to determine what the button does).
5. For toggle buttons (pin/unpin, expand/collapse, theme), add `aria-pressed` where appropriate.
6. Also check for `<a>` tags that contain only icons — these need `aria-label` too.
---
## Pattern 4: Error Banners (Verification Only)
### The Current Pattern (already consistent — verify it stays that way)
```tsx
{error && (
<div className="mb-6 rounded-md bg-destructive/10 p-4 text-destructive">
{error}
</div>
)}
```
### Audit Instructions
1. Search for all error display patterns in `frontend/src/`.
2. Verify they all use the same `bg-destructive/10 p-4 text-destructive` pattern.
3. If any page uses a different error display style, update it to match.
4. Do NOT change this pattern — just verify consistency.
---
## Execution Order
1. **Create the reusable components first:**
- `frontend/src/components/common/Skeleton.tsx`
- `frontend/src/components/common/EmptyState.tsx`
2. **Audit and fix Pattern 1 (Loading Skeletons):**
- Search for every spinner and `isLoading` pattern
- Replace with appropriate skeleton components
- Verify each page renders skeletons that match the shape of expected content
3. **Audit and fix Pattern 2 (Empty States):**
- Search for every empty list/empty state pattern
- Replace with `EmptyState` component using context-appropriate messaging
- Ensure every empty state has at minimum a title and description
4. **Audit and fix Pattern 3 (Aria Labels):**
- Search for every icon-only button
- Add `aria-label` to every one that's missing it
- Add `aria-pressed` to toggle buttons
5. **Verify Pattern 4 (Error Banners):**
- Quick scan to confirm consistency
- Fix any outliers
6. **Final verification:**
- `cd frontend && npm run build` — must pass with zero errors
- `cd frontend && npm run test` — must pass
- Visually spot-check: no page should show a centered spinner anymore
---
## Rules
- Do NOT change any business logic. Only change presentation/UI patterns.
- Do NOT change any API calls or data fetching logic.
- Do NOT add new dependencies. Use only Tailwind CSS utilities and existing project patterns.
- Do NOT change the error banner pattern — it's already correct.
- DO use `cn()` from `@/lib/utils` for conditional class merging (existing project standard).
- DO use Lucide icons (existing project standard). No `title` prop on Lucide — wrap in `<span title="...">` if tooltip is needed.
- DO support dark mode in all new components (use Tailwind's `text-foreground`, `bg-muted`, `text-muted-foreground` etc., not hardcoded colors).
- DO keep the new components simple. No over-engineering. The `Skeleton` and `EmptyState` components should be under 100 lines each.

View File

@@ -0,0 +1,368 @@
# ResolutionFlow Aesthetic Redesign — Design Document
> **Date:** March 3, 2026
> **Status:** Approved
> **Reference Mockup:** `/tmp/mockup-j-slate-ice-modern.html`
---
## Problem Statement
The current purple gradient theme (`#818cf8``#a78bfa`) feels generic and AI-generated. It doesn't convey the professional credibility MSP engineers expect from their daily tooling. The redesign aims for a **sharp, modern** aesthetic that stands out while remaining easy on the eyes during long troubleshooting sessions.
## Design Direction: Slate & Ice Modern
Dark glassmorphism with an ice-cyan accent. Cool charcoal backgrounds, frosted-glass cards with backdrop blur, orchestrated page-load animations, and bold display typography.
---
## Color Palette
### Core Colors
| Token | Hex | Usage |
|-------|-----|-------|
| `--background` | `#101114` | Page background, body |
| `--surface` | `#14161a` | Sidebar/topbar base behind blur |
| `--card` / glass-bg | `rgba(24, 26, 31, 0.55)` | Card backgrounds (semi-transparent) |
| `--card-hover` | `rgba(24, 26, 31, 0.7)` | Card hover state |
| `--foreground` | `#f8fafc` | Primary text |
| `--muted-foreground` | `#8891a0` | Secondary text, nav labels |
| `--muted-dim` | `#5a6170` | Section labels, timestamps |
| `--border` | `rgba(255, 255, 255, 0.06)` | Default borders |
| `--border-hover` | `rgba(255, 255, 255, 0.12)` | Hover/active borders |
### Accent Colors
| Token | Hex | Usage |
|-------|-----|-------|
| `--primary` | `#06b6d4` | Accent gradient start, active indicators |
| `--primary-light` | `#22d3ee` | Accent gradient end, highlights |
| `--gradient-brand` | `linear-gradient(135deg, #06b6d4, #22d3ee)` | Primary buttons, avatar, active accent bar, logo "Flow" text |
### Functional Colors (unchanged semantics)
| Token | Hex | Usage |
|-------|-----|-------|
| `--success` | `#34d399` / emerald-400 | Completed, positive |
| `--warning` | `#fbbf24` / amber-400 | In-progress, caution |
| `--error` | `#f43f5e` / rose-500 | Error, critical, notification dots |
| `--info` | `#60a5fa` / blue-400 | Informational |
### Accessibility Notes
- Cyan accent is safe for deuteranopia, protanopia, and tritanopia
- Always pair status colors with icons (not color alone)
- Use shape differentiation (filled vs outline icons) alongside color for colorblind users
- `#f8fafc` on `#101114` background exceeds WCAG AAA contrast ratio
---
## Typography
### Font Stack
| Role | Font | Weights | Google Fonts |
|------|------|---------|-------------|
| `font-heading` | **Bricolage Grotesque** | 400, 600, 700, 800 | Yes |
| `font-body` (default) | **IBM Plex Sans** | 400, 500, 600 | Yes |
| `font-label` | **JetBrains Mono** | 400, 500 | Yes |
### Hierarchy
| Element | Font | Size | Weight | Color |
|---------|------|------|--------|-------|
| Page greeting / hero | Bricolage Grotesque | 36px | 800 | `--foreground` |
| Stat values | Bricolage Grotesque | 30px | 800 | cyan gradient text |
| Card titles | Bricolage Grotesque | 16px | 700 | `--foreground` |
| Body text | IBM Plex Sans | 14px | 400-500 | `--foreground` |
| Nav items | IBM Plex Sans | 14px | 500 | `--muted-foreground``--foreground` on hover/active |
| Section labels | JetBrains Mono | 10px | 500 | `--muted-dim`, uppercase, `letter-spacing: 0.1em` |
| Timestamps / metadata | JetBrains Mono | 11-12px | 400 | `--muted-foreground` |
| Stat labels | IBM Plex Sans | 13px | 500 | `--muted-foreground` |
---
## Glassmorphism System
### Card Variants
**Interactive glass card** (`.glass-card`):
```css
background: rgba(24, 26, 31, 0.55);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.06);
border-radius: 16px;
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
/* Hover */
transform: scale(1.02);
border-color: rgba(255, 255, 255, 0.12);
box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.08);
```
**Static glass card** (`.glass-card-static`): Same as above without hover transform.
### Shell Blur Levels
| Element | Blur | Background |
|---------|------|-----------|
| Sidebar | `blur(12px)` | `rgba(16, 17, 20, 0.5)` |
| Topbar | `blur(20px)` | `rgba(16, 17, 20, 0.6)` |
| Cards | `blur(16px)` | `rgba(24, 26, 31, 0.55)` |
### Ambient Atmosphere
Two fixed `pointer-events: none` gradient orbs behind the app shell:
- **Cyan orb**: top-right, 600x600px, `rgba(6, 182, 212, 0.15)`, blur(60px)
- **Purple orb**: bottom-left, 500x500px, `rgba(99, 102, 241, 0.08)`, blur(50px)
---
## Component Specifications
### Primary Button
```css
background: linear-gradient(135deg, #06b6d4, #22d3ee);
color: #101114;
font-weight: 600;
border-radius: 10px;
padding: 10px 20px;
/* Hover: opacity 0.9; Active: scale(0.97) */
```
### Secondary Button
```css
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.06);
color: #f8fafc;
border-radius: 10px;
/* Hover: border brightens to rgba(255, 255, 255, 0.12) */
```
### Search Bar
- `width: 320px`, expands to `400px` on focus
- Background: `rgba(255, 255, 255, 0.04)`, focus: `rgba(255, 255, 255, 0.06)`
- Focus border: `rgba(6, 182, 212, 0.3)` — cyan tint
- Rounded: `border-radius: 12px`
### Active Nav Item
- Background: `rgba(6, 182, 212, 0.1)` with scaleX reveal animation
- Left accent bar: 3px wide, cyan gradient, `border-radius: 0 3px 3px 0`
- Text: `--foreground` (white)
### Avatar
- 34x34px, `border-radius: 10px` (rounded square)
- Cyan gradient background, dark text
- Hover: `scale(1.08)`
### Notification Dot
- 8px circle, `#f43f5e` (rose), 2px solid `#101114` border
### Scrollbar
- 6px wide, transparent track
- Thumb: `rgba(255,255,255,0.08)`, hover: `rgba(255,255,255,0.12)`
---
## Animations
### Page Load Sequence (orchestrated)
| Element | Animation | Delay | Duration |
|---------|-----------|-------|----------|
| Topbar | slideDown (Y: -100% → 0) | 200ms | 400ms |
| Sidebar | slideInLeft (X: -100% → 0) | 250ms | 400ms |
| Greeting | fadeInUp (Y: 20px → 0) | 400ms | 400ms |
| Stat cards | fadeInUp cascade | 500ms, 570ms, 640ms, 710ms | 350ms each |
| Activity items | fadeInUp stagger | 750ms + 40ms each | 300ms each |
| Quick actions | fadeInRight (X: 30px → 0) | 800ms | 400ms |
### Micro-interactions
| Element | Effect |
|---------|--------|
| Glass cards | `scale(1.02)` + border/shadow upgrade on hover |
| Buttons | `scale(0.97)` on `:active` |
| Notification bell | wobble keyframe (rotate ±8° → 0) on hover |
| First stat card | `breatheGlow` — pulsing cyan shadow, 3s infinite |
| Nav items | Background scaleX reveal from left on hover |
| Search bar | Width expansion 320→400px on focus |
| Avatar | `scale(1.08)` on hover |
### Easing
- Primary: `cubic-bezier(0.4, 0, 0.2, 1)` — smooth deceleration
- Bounce (optional): `cubic-bezier(0.34, 1.56, 0.64, 1)` — slight overshoot
---
## Dashboard Layout
### Grid Structure
```
Row 1: Greeting + date (full width)
Row 2: Weekly Calendar (flex-grow) + Quick Actions (fixed width) — equal height
Row 3: My Open Sessions (flex-grow) + Stats 2x2 grid (fixed width) — equal height
Row 4: Recent Activity (full width)
```
### Weekly Calendar Panel
- 5 tall day columns (MonFri), equal width
- Today column: highlighted with cyan gradient top bar
- Events appear inline within day columns with colored left border (4px)
- Cyan left-border: default events
- Amber left-border: maintenance events
- Empty days show "No events" in muted text
- Calendar and quick actions stretch to match height (`align-items: stretch`)
- Future: Outlook/Gmail/PSA calendar sync integration
### Quick Actions Panel
4 glass cards in a vertical stack:
1. New Flow (+ icon, cyan accent)
2. Resume Session (play icon, emerald accent)
3. Browse Library (book icon, amber accent)
4. Invite Team (user-plus icon, purple accent)
### My Open Sessions Panel
- Shows 3 oldest open sessions
- Each row: colored dot + flow name + "Step X of Y" + time ago + Resume button
- Resume button: small cyan gradient pill
### Stats Panel (2x2 Grid)
4 stat cards:
1. Active Flows — with `breatheGlow` animation
2. This Week (sessions)
3. Avg Resolution (time)
4. Team Members
Each: stat value (30px Bricolage Grotesque, cyan gradient text) + label + trend indicator
### Recent Activity Panel
- Full width, 5 activity items
- Each: icon (colored background circle) + description + JetBrains Mono timestamp
- Staggered fadeInUp animation on page load
---
## Sidebar Structure
1. **Logo bar** (56px height, matches topbar): Decision-tree icon SVG + "Resolution" white + "Flow" cyan gradient
2. **Pinned Flows**: 3 pinned items with cyan pin icons
3. **Divider**
4. **Navigation**:
- Dashboard (active)
- All Flows → Troubleshooting / Projects / Maintenance (sub-items)
- Step Library
- Sessions
- Exports
5. **Divider**
6. **Footer** (pushed to bottom): User avatar + name + role badge
No categories section. No workspace switcher.
---
## Topbar Structure
- Left: Search bar with search icon + "Search flows..." placeholder + keyboard shortcut badge
- Right: Help icon + Notification bell (with dot) + User avatar (rounded square, cyan gradient)
- Subtle cyan gradient underline glow at center-bottom
---
## Logo
The existing decision-tree SVG icon is retained but recolored with the cyan gradient (`#06b6d4``#22d3ee`). Nodes have decreasing opacity down the tree (0.9 → 0.7 → 0.5). Connector lines use the gradient stroke at 0.40.5 opacity.
Wordmark: "Resolution" in `#f8fafc` + "Flow" with `background: linear-gradient(135deg, #06b6d4, #22d3ee)` + `-webkit-background-clip: text`.
---
## Shadow System
| Token | Value | Usage |
|-------|-------|-------|
| `--shadow-float` | `0 8px 32px rgba(0,0,0,0.3)` | Default card shadow |
| `--shadow-float-hover` | `0 12px 40px rgba(0,0,0,0.4), 0 0 0 1px rgba(255,255,255,0.08)` | Hovered card |
| `--shadow-cyan-glow` | `0 8px 32px rgba(6,182,212,0.08)` | Cyan-tinted glow |
---
## Migration Notes
### What Changes
| Current | New |
|---------|-----|
| Purple gradient (`#818cf8``#a78bfa`) | Ice cyan gradient (`#06b6d4``#22d3ee`) |
| Plus Jakarta Sans (headings) | Bricolage Grotesque (headings) |
| Inter (body) | IBM Plex Sans (body) |
| Outfit (labels) | JetBrains Mono (labels) |
| Flat `bg-card` cards | Glassmorphism with `backdrop-filter: blur()` |
| No page-load animations | Orchestrated entrance sequence |
| No hover scaling on cards | `scale(1.02)` hover lift |
| `bg-gradient-brand` = purple | `bg-gradient-brand` = cyan |
| `text-gradient-brand` = purple | `text-gradient-brand` = cyan |
### What Stays the Same
- CSS Grid app shell layout (sidebar + topbar + main)
- Dark-first theme (dark only, no light mode)
- Lucide React icons
- Zustand state management
- Component architecture and routing
- Functional color semantics (green=success, amber=warning, red=error)
- "Flows" terminology, "ResolutionFlow" branding
- BrandLogo.tsx component structure (just recolor the SVG + gradient)
### New Dashboard Panels (Feature Work)
- **Weekly Calendar**: New component, requires date logic, event display, future calendar sync API
- **My Open Sessions**: Queries 3 oldest open sessions (existing API with sort + limit)
- Stat cards and Recent Activity already exist — layout rearrangement only
---
## Implementation Scope
### Phase 1: Design System Foundation
- Update CSS variables in `index.css`
- Update `tailwind.config.js` (colors, fonts, gradients)
- Add Google Fonts imports (Bricolage Grotesque, IBM Plex Sans, JetBrains Mono)
- Create glassmorphism utility classes
- Create animation keyframes and stagger classes
- Update `BrandLogo.tsx` SVG colors
### Phase 2: Shell & Navigation
- Update sidebar glassmorphism + nav item styles
- Update topbar glassmorphism + search bar
- Update active nav indicator (purple → cyan accent bar)
### Phase 3: Component Updates
- Update button variants (primary gradient, secondary)
- Update card components to glass-card pattern
- Update stat cards, activity items, badges
- Update form inputs (focus states)
### Phase 4: Dashboard Redesign
- Rearrange dashboard layout (greeting → calendar+actions → sessions+stats → activity)
- Build Weekly Calendar component
- Build My Open Sessions panel
- Add orchestrated page-load animations
### Phase 5: Page-by-Page Sweep
- Update all remaining pages to use new design tokens
- Ensure consistency across tree editor, session pages, admin pages, etc.

File diff suppressed because it is too large Load Diff