diff --git a/docs/plans/2026-03-03-aesthetic-redesign-design.md b/docs/plans/2026-03-03-aesthetic-redesign-design.md new file mode 100644 index 00000000..ab233405 --- /dev/null +++ b/docs/plans/2026-03-03-aesthetic-redesign-design.md @@ -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 (Mon–Fri), 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.4–0.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. diff --git a/docs/plans/2026-03-03-aesthetic-redesign-impl.md b/docs/plans/2026-03-03-aesthetic-redesign-impl.md new file mode 100644 index 00000000..ea77a9c8 --- /dev/null +++ b/docs/plans/2026-03-03-aesthetic-redesign-impl.md @@ -0,0 +1,1400 @@ +# Aesthetic Redesign Implementation Plan + +> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. + +**Goal:** Replace the current purple gradient theme with the approved Slate & Ice Modern design — glassmorphism, ice-cyan accent, new fonts, orchestrated animations, and a redesigned dashboard layout. + +**Architecture:** Token-based theme swap via CSS variables + Tailwind config, followed by component-level updates. The design system tokens (colors, fonts, gradients, shadows) change in 3 files. Components then adopt new glass-card utilities and animation classes. The dashboard gets new panels (calendar, open sessions). No backend changes required. + +**Tech Stack:** React 19, Tailwind CSS v3, CSS custom properties, Google Fonts (Bricolage Grotesque, IBM Plex Sans, JetBrains Mono) + +**Design Doc:** `docs/plans/2026-03-03-aesthetic-redesign-design.md` +**Reference Mockup:** `/tmp/mockup-j-slate-ice-modern.html` + +--- + +## Task 1: Update Google Fonts in index.html + +**Files:** +- Modify: `frontend/index.html:10-13` + +**Step 1: Replace the Google Fonts import** + +Change the font families from Plus Jakarta Sans / Inter / Outfit to Bricolage Grotesque / IBM Plex Sans / JetBrains Mono. + +```html + + + + + + +``` + +Also update the theme-color meta tag from `#09090b` to `#101114`: + +```html + +``` + +**Step 2: Verify the file looks correct** + +Open `frontend/index.html` and confirm the font link and meta tag are updated. + +**Step 3: Run frontend build to verify no errors** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 4: Commit** + +```bash +git add frontend/index.html +git commit -m "chore: update Google Fonts to Bricolage Grotesque, IBM Plex Sans, JetBrains Mono" +``` + +--- + +## Task 2: Update Tailwind config (colors, fonts, gradients) + +**Files:** +- Modify: `frontend/tailwind.config.js` + +**Step 1: Replace the tailwind config** + +Update font families, brand colors, and gradient background images. The shadcn/ui color system stays the same (it references CSS variables). Only the `brand` object, `fontFamily`, and `backgroundImage` change. + +```js +// frontend/tailwind.config.js +/** @type {import('tailwindcss').Config} */ +export default { + darkMode: ["class"], + content: [ + "./index.html", + "./src/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + // ResolutionFlow Brand Colors — Slate & Ice + brand: { + gradient: { + from: '#06b6d4', + to: '#22d3ee', + }, + dark: { + DEFAULT: '#101114', + card: '#14161a', + surface: '#14161a', + }, + text: { + primary: '#f8fafc', + secondary: '#8891a0', + muted: '#5a6170', + }, + border: 'rgba(255, 255, 255, 0.06)', + }, + // shadcn/ui color system (unchanged — references CSS vars) + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + fontFamily: { + sans: ['IBM Plex Sans', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif'], + heading: ['Bricolage Grotesque', 'system-ui', 'sans-serif'], + label: ['JetBrains Mono', 'monospace'], + }, + backgroundImage: { + 'gradient-brand': 'linear-gradient(135deg, #06b6d4 0%, #22d3ee 100%)', + 'gradient-brand-hover': 'linear-gradient(135deg, #0891b2 0%, #06b6d4 100%)', + }, + }, + }, + plugins: [], +} +``` + +Key changes: +- `fontFamily.sans`: `Inter` → `IBM Plex Sans` +- `fontFamily.heading`: `Plus Jakarta Sans` → `Bricolage Grotesque` +- `fontFamily.label`: `Outfit` → `JetBrains Mono` (with `monospace` fallback) +- `brand.gradient.from`: `#818cf8` → `#06b6d4` +- `brand.gradient.to`: `#a78bfa` → `#22d3ee` +- `backgroundImage.gradient-brand`: purple → cyan, angle `90deg` → `135deg` +- `backgroundImage.gradient-brand-hover`: darker purple → darker cyan + +**Step 2: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 3: Commit** + +```bash +git add frontend/tailwind.config.js +git commit -m "chore: update Tailwind config to Slate & Ice theme colors and fonts" +``` + +--- + +## Task 3: Update CSS variables and utilities in index.css + +**Files:** +- Modify: `frontend/src/index.css` + +**Step 1: Update the `:root` CSS variables** + +Replace the existing `:root` block with Slate & Ice values. The key changes: +- `--background`: darker, cooler charcoal +- `--primary`: purple → cyan +- `--card`: slightly transparent for glass effect +- `--border`: uses lower opacity white +- New glass and shadow custom properties + +```css +@layer base { + :root { + /* ResolutionFlow Dark Theme — Slate & Ice Modern */ + --background: 228 12% 7%; /* #101114 */ + --foreground: 210 40% 98%; /* #f8fafc */ + --card: 220 10% 10%; /* #171a1e — fallback for non-glass contexts */ + --card-foreground: 210 40% 98%; + --popover: 220 10% 10%; + --popover-foreground: 210 40% 98%; + --primary: 187 72% 43%; /* #06b6d4 — cyan */ + --primary-foreground: 228 12% 7%; /* dark text on cyan buttons */ + --secondary: 220 8% 14%; + --secondary-foreground: 210 40% 98%; + --muted: 220 8% 14%; + --muted-foreground: 215 10% 58%; /* #8891a0 */ + --accent: 220 8% 14%; + --accent-foreground: 210 40% 98%; + --destructive: 350 81% 55%; /* #f43f5e — rose */ + --destructive-foreground: 210 40% 98%; + --border: 220 8% 14%; + --input: 220 8% 14%; + --ring: 187 72% 43%; /* cyan focus ring */ + --radius: 0.75rem; + + /* App Shell tokens */ + --sidebar-w: 260px; + --sidebar-bg: 228 12% 6%; /* slightly darker than background */ + --sidebar-hover: 220 8% 14%; + --sidebar-active: 187 72% 43% / 0.10; /* cyan with 10% opacity */ + --border-subtle: 220 8% 12%; + --text-dimmed: 218 10% 39%; /* #5a6170 */ + + /* Glass system */ + --glass-bg: rgba(24, 26, 31, 0.55); + --glass-bg-hover: rgba(24, 26, 31, 0.7); + --glass-border: rgba(255, 255, 255, 0.06); + --glass-border-hover: rgba(255, 255, 255, 0.12); + --glass-blur: blur(16px); + --glass-blur-strong: blur(20px); + --glass-blur-light: blur(12px); + + /* Shadow system */ + --shadow-float: 0 8px 32px rgba(0, 0, 0, 0.3); + --shadow-float-hover: 0 12px 40px rgba(0, 0, 0, 0.4), 0 0 0 1px rgba(255, 255, 255, 0.08); + --shadow-cyan-glow: 0 8px 32px rgba(6, 182, 212, 0.08); + + /* Easing */ + --ease-out-smooth: cubic-bezier(0.4, 0, 0.2, 1); + } +} +``` + +**Step 2: Update the body and heading font rules** + +```css +@layer base { + /* ... scrollbar rules stay the same ... */ + + body { + @apply bg-background text-foreground; + font-family: 'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + } + + h1, h2, h3, h4, h5, h6 { + font-family: 'Bricolage Grotesque', system-ui, sans-serif; + font-weight: 700; + letter-spacing: -0.02em; + } +} +``` + +**Step 3: Replace legacy glass-card utilities with the new glass system** + +Remove the old legacy glass utilities and replace with the approved glass-card system: + +```css +@layer utilities { + /* ... keep animate-* and btn-press utilities unchanged ... */ + + /* Brand gradient text */ + .text-gradient-brand { + @apply bg-gradient-brand bg-clip-text text-transparent; + } + + /* Glass card — interactive with hover lift */ + .glass-card { + background: var(--glass-bg); + backdrop-filter: var(--glass-blur); + -webkit-backdrop-filter: var(--glass-blur); + border: 1px solid var(--glass-border); + border-radius: 16px; + box-shadow: var(--shadow-float); + transition: transform 200ms var(--ease-out-smooth), + border-color 200ms var(--ease-out-smooth), + box-shadow 200ms var(--ease-out-smooth); + } + .glass-card:hover { + transform: scale(1.02); + border-color: var(--glass-border-hover); + box-shadow: var(--shadow-float-hover); + } + + /* Glass card — static, no hover transform */ + .glass-card-static { + background: var(--glass-bg); + backdrop-filter: var(--glass-blur); + -webkit-backdrop-filter: var(--glass-blur); + border: 1px solid var(--glass-border); + border-radius: 16px; + box-shadow: var(--shadow-float); + } +} +``` + +**Step 4: Add new animation keyframes** + +Add these after the existing keyframe definitions (keep existing ones, add new): + +```css +@keyframes slideDown { + from { transform: translateY(-100%); opacity: 0; } + to { transform: translateY(0); opacity: 1; } +} + +@keyframes slideInLeft { + from { transform: translateX(-100%); opacity: 0; } + to { transform: translateX(0); opacity: 1; } +} + +@keyframes fadeInRight { + from { transform: translateX(30px); opacity: 0; } + to { transform: translateX(0); opacity: 1; } +} + +@keyframes breatheGlow { + from { box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), 0 0 20px rgba(6, 182, 212, 0.04); } + to { box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3), 0 0 30px rgba(6, 182, 212, 0.12); } +} + +@keyframes bellWobble { + 0% { transform: rotate(0deg); } + 20% { transform: rotate(8deg); } + 40% { transform: rotate(-6deg); } + 60% { transform: rotate(4deg); } + 80% { transform: rotate(-2deg); } + 100% { transform: rotate(0deg); } +} +``` + +**Step 5: Update Sonner toast font reference** + +In the `[data-sonner-toast]` rules, update `font-family` from `'Inter'` to `'IBM Plex Sans'`: + +```css +[data-sonner-toast] { + /* ... */ + font-family: 'IBM Plex Sans', system-ui, sans-serif; +} +[data-sonner-toast] [data-title] { + font-family: 'IBM Plex Sans', system-ui, sans-serif; + /* ... */ +} +``` + +**Step 6: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 7: Commit** + +```bash +git add frontend/src/index.css +git commit -m "feat: update CSS variables and glass-card utilities for Slate & Ice theme" +``` + +--- + +## Task 4: Update BrandLogo and BrandWordmark + +**Files:** +- Modify: `frontend/src/components/common/BrandLogo.tsx` +- Modify: `frontend/src/components/common/BrandWordmark.tsx` + +**Step 1: Recolor BrandLogo SVG to use cyan gradient** + +The structure stays the same, but colors change from white to cyan gradient. Add a `` block with a linear gradient and reference it. + +In `BrandLogo.tsx`, update the SVG to use cyan gradient fills instead of plain white. Change all `fill="white"` to `fill="url(#logoGrad)"` and add the gradient definition: + +```tsx +import { cn } from '@/lib/utils' + +interface BrandLogoProps { + size?: 'sm' | 'lg' + className?: string +} + +export function BrandLogo({ size = 'sm', className }: BrandLogoProps) { + const sizeClasses = size === 'sm' ? 'h-8 w-8' : 'h-20 w-20' + + const strokeBase = size === 'sm' ? 1 : 2 + const strokeThick = size === 'sm' ? 1.25 : 2.5 + const dashArray = size === 'sm' ? '1 1.5' : '2 3' + const nodeR = size === 'sm' ? { outer: 2.5, inner: 2.75 } : { outer: 5, inner: 5.5 } + const hubR = size === 'sm' ? { glow: 5, solid: 3.5 } : { glow: 10, solid: 7 } + + const vb = size === 'sm' ? '0 0 40 40' : '0 0 80 80' + const s = size === 'sm' ? 1 : 2 + const gradId = size === 'sm' ? 'logoGradSm' : 'logoGradLg' + + return ( + + + + + + + + + {/* Input nodes */} + + + + + + {/* Connecting lines */} + + + + + + {/* Central hub */} + + + + {/* Output arrow */} + + + ) +} +``` + +**Step 2: Update BrandWordmark to use cyan gradient for "Flow"** + +In `BrandWordmark.tsx`, split the text so "Resolution" is white and "Flow" uses the gradient text: + +```tsx +import { cn } from '@/lib/utils' + +interface BrandWordmarkProps { + size?: 'sm' | 'lg' + className?: string +} + +export function BrandWordmark({ size = 'sm', className }: BrandWordmarkProps) { + return ( + + Resolution + Flow + + ) +} +``` + +**Step 3: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 4: Commit** + +```bash +git add frontend/src/components/common/BrandLogo.tsx frontend/src/components/common/BrandWordmark.tsx +git commit -m "feat: recolor BrandLogo to cyan gradient, split BrandWordmark for gradient Flow text" +``` + +--- + +## Task 5: Update TopBar with glassmorphism and new styles + +**Files:** +- Modify: `frontend/src/components/layout/TopBar.tsx` + +**Step 1: Update the TopBar component** + +Key changes: +- Remove `bg-gradient-brand` wrapper from logo icon (logo icon is now standalone with gradient fill) +- Avatar: change from `rounded-full` to `rounded-[10px]` (rounded square) +- Add subtle cyan bottom glow line via `after:` pseudo-element (handled in CSS, not JSX) +- Update topbar class for glassmorphism: replace `bg-background` with glass styling + +In `TopBar.tsx`, update the header element's className: + +```tsx +// Line 57 — replace the header className: +
+``` + +Update the logo area (lines 59-70). Remove the gradient wrapper div, show icon directly: + +```tsx + + + + Resolution + Flow + + +``` + +Update the avatar button (line 107-109). Change from `rounded-full` to `rounded-[10px]`: + +```tsx + + ))} + + + ) +} +``` + +**Step 2: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 3: Commit** + +```bash +git add frontend/src/components/dashboard/QuickActions.tsx +git commit -m "feat: add QuickActions dashboard component with 4 action cards" +``` + +--- + +## Task 12: Build OpenSessions dashboard component + +**Files:** +- Create: `frontend/src/components/dashboard/OpenSessions.tsx` + +**Step 1: Create the OpenSessions component** + +Shows 3 oldest open sessions with Resume buttons: + +```tsx +import { Link } from 'react-router-dom' +import { getTreeNavigatePath } from '@/lib/routing' + +interface OpenSession { + id: string + treeName: string + treeId: string + treeType?: string + stepNumber?: number + totalSteps?: number + timeAgo: string +} + +interface OpenSessionsProps { + sessions: OpenSession[] +} + +export function OpenSessions({ sessions }: OpenSessionsProps) { + return ( +
+
+

My Open Sessions

+ + View All + +
+
+ {sessions.length === 0 ? ( +
+

No open sessions

+
+ ) : ( + sessions.map((session, i) => ( +
+ +
+
{session.treeName}
+
+ {session.stepNumber && session.totalSteps + ? `Step ${session.stepNumber} of ${session.totalSteps}` + : 'In progress'} + · + {session.timeAgo} +
+
+ + Resume + +
+ )) + )} +
+
+ ) +} +``` + +**Step 2: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 3: Commit** + +```bash +git add frontend/src/components/dashboard/OpenSessions.tsx +git commit -m "feat: add OpenSessions dashboard component showing 3 oldest open sessions" +``` + +--- + +## Task 13: Build RecentActivity dashboard component + +**Files:** +- Create: `frontend/src/components/dashboard/RecentActivity.tsx` + +**Step 1: Create the RecentActivity component** + +Displays 5 recent activity items with icons and timestamps: + +```tsx +import type { LucideIcon } from 'lucide-react' +import { GitBranch, Play, CheckCircle, FileText, Edit } from 'lucide-react' + +interface ActivityItem { + id: string + icon: LucideIcon + iconColor: string + iconBg: string + description: string + timestamp: string +} + +interface RecentActivityProps { + activities: ActivityItem[] +} + +const DEFAULT_ACTIVITIES: ActivityItem[] = [ + { id: '1', icon: Play, iconColor: '#34d399', iconBg: 'rgba(52, 211, 153, 0.1)', description: 'Started VPN Connectivity Triage session', timestamp: '2 min ago' }, + { id: '2', icon: CheckCircle, iconColor: '#06b6d4', iconBg: 'rgba(6, 182, 212, 0.1)', description: 'Completed M365 License Provisioning', timestamp: '15 min ago' }, + { id: '3', icon: Edit, iconColor: '#fbbf24', iconBg: 'rgba(251, 191, 36, 0.1)', description: 'Updated Printer Troubleshooting flow', timestamp: '1 hr ago' }, + { id: '4', icon: GitBranch, iconColor: '#818cf8', iconBg: 'rgba(129, 140, 248, 0.1)', description: 'Created new DNS Resolution flow', timestamp: '3 hr ago' }, + { id: '5', icon: FileText, iconColor: '#8891a0', iconBg: 'rgba(136, 145, 160, 0.1)', description: 'Exported session report #TK-4821', timestamp: 'Yesterday' }, +] + +export function RecentActivity({ activities = DEFAULT_ACTIVITIES }: Partial) { + return ( +
+
+

Recent Activity

+
+
+ {activities.map((item, i) => ( +
+ + + +
+

{item.description}

+
+ + {item.timestamp} + +
+ ))} +
+
+ ) +} +``` + +**Step 2: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 3: Commit** + +```bash +git add frontend/src/components/dashboard/RecentActivity.tsx +git commit -m "feat: add RecentActivity dashboard component with staggered animations" +``` + +--- + +## Task 14: Redesign the QuickStartPage dashboard layout + +**Files:** +- Modify: `frontend/src/pages/QuickStartPage.tsx` + +**Step 1: Import the new dashboard components** + +Add imports at the top of `QuickStartPage.tsx`: + +```tsx +import { WeeklyCalendar } from '@/components/dashboard/WeeklyCalendar' +import { QuickActions } from '@/components/dashboard/QuickActions' +import { OpenSessions } from '@/components/dashboard/OpenSessions' +import { RecentActivity } from '@/components/dashboard/RecentActivity' +``` + +**Step 2: Prepare open sessions data** + +After the existing stats calculations (around line 212), add open sessions data: + +```tsx +// Open sessions for the new panel (3 oldest) +const openSessionItems = activeSessions + .sort((a, b) => new Date(a.started_at).getTime() - new Date(b.started_at).getTime()) + .slice(0, 3) + .map(s => ({ + id: s.id, + treeName: s.tree_snapshot?.name || 'Unknown', + treeId: s.tree_id, + treeType: s.tree_snapshot?.tree_type, + timeAgo: timeAgo(s.started_at), + })) +``` + +**Step 3: Restructure the dashboard layout** + +Replace the return JSX with the new layout order: +1. Greeting + date (full width) +2. Calendar + Quick Actions (same height row) +3. Open Sessions + Stats 2x2 (same height row) +4. Recent Activity (full width) +5. (Keep existing: Search, Favorites, My Flows tabs — below the fold) + +The new layout should be: + +```tsx +return ( +
+ {/* Greeting */} +
+

+ Good {new Date().getHours() < 12 ? 'morning' : new Date().getHours() < 18 ? 'afternoon' : 'evening'}, {user?.name?.split(' ')[0] || 'there'} +

+

+ {new Date().toLocaleDateString('en-US', { weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' })} +

+
+ + {/* Row 1: Calendar + Quick Actions */} +
+
+ +
+
+ +
+
+ + {/* Row 2: Open Sessions + Stats 2x2 */} +
+
+ +
+
+
+ {/* 4 stat cards in 2x2 grid */} + {[ + { label: 'Active Flows', value: myFlows.length, gradient: true, glow: true }, + { label: 'This Week', value: todaySessions }, + { label: 'Open Sessions', value: openSessions }, + { label: 'Favorites', value: pinnedItems.length }, + ].map((stat, i) => ( +
+

+ {stat.label} +

+

+ {stat.value} +

+
+ ))} +
+
+
+ + {/* Row 3: Recent Activity */} + + + {/* Divider before existing content */} +
+ {/* Keep existing: Search, Favorites, My Flows tabs below */} +
+ + {/* ... rest of existing code (search, favorites, my flows) stays below ... */} +
+) +``` + +Keep the existing Search, Favorites, and My Flows sections below the new dashboard panels. Remove the old `` component call since stats are now inline in the 2x2 grid. + +**Step 4: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 5: Manually verify in browser** + +Run: `cd frontend && npm run dev` +Open http://localhost:5173 and verify: +- Greeting with user's first name +- Calendar + Quick Actions side by side, equal height +- Open Sessions + Stats side by side, equal height +- Recent Activity full width below +- All glass-card effects working (backdrop blur, hover scale) +- Cyan gradient accents throughout + +**Step 6: Commit** + +```bash +git add frontend/src/pages/QuickStartPage.tsx +git commit -m "feat: redesign dashboard layout with calendar, open sessions, and glass-card panels" +``` + +--- + +## Task 15: Update login and register pages + +**Files:** +- Modify: `frontend/src/pages/LoginPage.tsx` +- Modify: `frontend/src/pages/RegisterPage.tsx` + +**Step 1: Search for purple gradient references in auth pages** + +Run: Search both files for `bg-gradient-brand`, `text-gradient-brand`, font family references, and color hardcodes. These should already work with the new Tailwind config since they use design tokens, but verify: +- `bg-gradient-brand` → now produces cyan (from tailwind.config.js) +- `text-gradient-brand` → now produces cyan (from index.css utility) +- `font-heading` → now maps to Bricolage Grotesque +- `font-label` → now maps to JetBrains Mono +- `bg-card` → now references the updated CSS variable + +Most auth page styles should auto-update. Check for any hardcoded purple hex values. + +**Step 2: Run frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds + +**Step 3: Commit (only if changes were needed)** + +```bash +git add frontend/src/pages/LoginPage.tsx frontend/src/pages/RegisterPage.tsx +git commit -m "fix: update auth pages for Slate & Ice theme consistency" +``` + +--- + +## Task 16: Page-by-page sweep — find and fix remaining purple/old-font references + +**Files:** +- Multiple frontend files + +**Step 1: Search for hardcoded purple hex values** + +Run grep searches across the frontend for: +- `#818cf8` — old gradient-from +- `#a78bfa` — old gradient-to +- `#6366f1` — old gradient-hover-from +- `#9333ea` — old gradient-hover-to +- `Plus Jakarta Sans` — old heading font +- `'Inter'` — old body font (note: not in font-stack, just standalone references) +- `'Outfit'` — old label font + +These should only appear in `tailwind.config.js` (already updated) and `index.css` (already updated). If they appear elsewhere, update them. + +**Step 2: Check for `shadow-primary/20` references** + +This shadow color depends on `--primary`, which is now cyan. Existing `shadow-lg shadow-primary/20` will automatically become a cyan shadow, which is correct. No changes needed. + +**Step 3: Verify `bg-primary` references** + +`bg-primary` now renders as cyan instead of purple. Check all usages to ensure cyan makes sense in those contexts (badges, nav indicators). These should all be correct since purple and cyan serve the same accent role. + +**Step 4: Run full frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds with no errors + +**Step 5: Commit any remaining fixes** + +```bash +git add -A +git commit -m "fix: sweep remaining hardcoded purple references across frontend" +``` + +--- + +## Task 17: Update CLAUDE.md branding section + +**Files:** +- Modify: `CLAUDE.md` + +**Step 1: Update the Branding section in CLAUDE.md** + +Update the following in the Branding section: +- Design description: `Dark-first with purple gradient accents (#818cf8 → #a78bfa)` → `Dark glassmorphism with ice-cyan accent (#06b6d4 → #22d3ee)` +- Fonts: `Plus Jakarta Sans (font-heading)` → `Bricolage Grotesque (font-heading)`, `Inter (font-sans)` → `IBM Plex Sans (font-sans)`, `Outfit (font-label)` → `JetBrains Mono (font-label)` +- CSS utilities: mention `glass-card`, `glass-card-static` as primary card patterns + +Update the Component styling rules: +- Primary buttons: `bg-gradient-brand` now produces cyan gradient +- Cards: `glass-card` class replaces `bg-card border border-border rounded-xl` +- Add: glassmorphism backdrop blur on sidebar and topbar + +Update the Design System section: +- Replace purple references with cyan +- Add glass system description +- Add animation descriptions + +**Step 2: Commit** + +```bash +git add CLAUDE.md +git commit -m "docs: update CLAUDE.md branding section for Slate & Ice theme" +``` + +--- + +## Task 18: Final verification and build + +**Step 1: Run full frontend build** + +Run: `cd frontend && npm run build` +Expected: Build succeeds with zero errors + +**Step 2: Run ESLint** + +Run: `cd frontend && npx eslint src/ --quiet` +Expected: No errors (warnings OK) + +**Step 3: Start dev server and visual verification** + +Run: `cd frontend && npm run dev` + +Verify in browser at http://localhost:5173: +- [ ] Cyan gradient accent throughout (buttons, nav, logo "Flow" text) +- [ ] Bricolage Grotesque headings (bold, distinctive) +- [ ] IBM Plex Sans body text +- [ ] JetBrains Mono labels and timestamps (monospace, uppercase) +- [ ] Glass-card effects on all dashboard panels (backdrop blur visible) +- [ ] Atmosphere orbs visible as subtle ambient glow +- [ ] Sidebar has glass backdrop blur +- [ ] Topbar has glass backdrop blur +- [ ] Dashboard layout: Greeting → Calendar+Actions → Sessions+Stats → Activity +- [ ] Weekly calendar with 5 day columns, today highlighted +- [ ] Stat cards with hover scale(1.02) +- [ ] First stat card has breathing glow +- [ ] Login/register pages use new colors and fonts +- [ ] No purple remnants anywhere + +**Step 4: Final commit if any fixes needed** + +```bash +git add -A +git commit -m "fix: final verification fixes for Slate & Ice redesign" +```