refactor: replace cyan accent with ember orange across entire frontend
Swap accent color from cyan (#22d3ee) to ember orange (#f97316) site-wide. Cyan caused contrast issues and felt generic — orange brings warmth and urgency fitting for a troubleshooting tool. Changes: - CSS variables: accent, accent-hover, accent-dim, accent-text, primary, ring - Warning color shifted from amber (#fbbf24) to yellow (#eab308) for semantic separation from orange accent - Brand SVGs: logo gradient updated to orange - 50+ component files: all hardcoded cyan hex values, Tailwind cyan-* classes, and rgba(34,211,238,...) glow values replaced - landing.css: all 45+ cyan references + 5 old border color fixes - DESIGN-SYSTEM.md bumped to v5 with decisions log - CLAUDE.md: all color references synced to charcoal palette + orange accent - PWA theme-color meta tag updated to match sidebar (#10121a) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
26
CLAUDE.md
26
CLAUDE.md
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
- **Design system:** [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) — THE source of truth for all design decisions
|
- **Design system:** [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) — THE source of truth for all design decisions
|
||||||
- **Design aesthetic:** Flat, high-contrast dark theme (Sentry/PostHog-inspired). No glass morphism, no gradients on surfaces, no ambient effects. Light mode planned.
|
- **Design aesthetic:** Flat, high-contrast dark theme (Sentry/PostHog-inspired). No glass morphism, no gradients on surfaces, no ambient effects. Light mode planned.
|
||||||
- **Accent color:** Cyan (#22d3ee / #06b6d4). Used sparingly — ≤5% of the UI.
|
- **Accent color:** Ember orange (#f97316 / #ea580c). Used sparingly — ≤5% of the UI. Warning is yellow (#eab308), not amber, to stay distinct from accent.
|
||||||
- **Fonts:** IBM Plex Sans (`font-sans`, body), Bricolage Grotesque (`font-heading`, headings), JetBrains Mono (`font-mono`, code) — loaded via Google Fonts
|
- **Fonts:** IBM Plex Sans (`font-sans`, body), Bricolage Grotesque (`font-heading`, headings), JetBrains Mono (`font-mono`, code) — loaded via Google Fonts
|
||||||
- **Logo:** 30px gradient square (cyan) + "ResolutionFlow" in Bricolage Grotesque 700
|
- **Logo:** 30px gradient square (cyan) + "ResolutionFlow" in Bricolage Grotesque 700
|
||||||
- **Layout:** Icon rail sidebar (72px default) with hover flyout panels. Pinnable to full 260px sidebar. See [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md)
|
- **Layout:** Icon rail sidebar (72px default) with hover flyout panels. Pinnable to full 260px sidebar. See [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md)
|
||||||
@@ -31,14 +31,14 @@
|
|||||||
|
|
||||||
**Component styling rules:**
|
**Component styling rules:**
|
||||||
|
|
||||||
- Primary buttons: solid `accent` background (#22d3ee), white text, 5px radius
|
- Primary buttons: solid `accent` background (#f97316), white text, 5px radius
|
||||||
- Ghost buttons: transparent with 1px `border-default`, hover `bg-elevated`
|
- Ghost buttons: transparent with 1px `border-default`, hover `bg-elevated`
|
||||||
- Cards: `bg-card` with 1px `border-default`, 8px radius. NO shadows, NO blur, NO gradients.
|
- Cards: `bg-card` with 1px `border-default`, 8px radius. NO shadows, NO blur, NO gradients.
|
||||||
- Badges: pill-shaped (20px radius), semantic dim background + matching text color
|
- Badges: pill-shaped (20px radius), semantic dim background + matching text color
|
||||||
- Active nav: `accent-dim` background + `accent-text` color + 3px left accent bar
|
- Active nav: `accent-dim` background + `accent-text` color + 3px left accent bar
|
||||||
- Stat cards: 3px colored left border (accent/success/warning by position)
|
- Stat cards: 3px colored left border (accent/success/warning by position)
|
||||||
- Code blocks: `bg-code` with JetBrains Mono, material-inspired syntax highlighting
|
- Code blocks: `bg-code` with JetBrains Mono, material-inspired syntax highlighting
|
||||||
- Status colors: green/`#34d399` (success), amber/`#fbbf24` (warning), red/`#f87171` (danger) — ONLY for semantic meaning
|
- Status colors: green/`#34d399` (success), yellow/`#eab308` (warning), red/`#f87171` (danger) — ONLY for semantic meaning
|
||||||
- Section labels: 10px, 600 weight, uppercase, `text-muted`, 1.2px letter-spacing
|
- Section labels: 10px, 600 weight, uppercase, `text-muted`, 1.2px letter-spacing
|
||||||
|
|
||||||
When adding new pages/components: reference [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md). Use flat dark surfaces, 1px borders, no decorative effects. All colors via CSS variables. Use "Flows" not "Trees" in all user-facing text; use "Projects" not "Procedures" for procedural flows.
|
When adding new pages/components: reference [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md). Use flat dark surfaces, 1px borders, no decorative effects. All colors via CSS variables. Use "Flows" not "Trees" in all user-facing text; use "Projects" not "Procedures" for procedural flows.
|
||||||
@@ -364,7 +364,7 @@ gh run view <id> --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusi
|
|||||||
|
|
||||||
**87. FlowPilot must ask GUI vs script preference:** When a task can be done via GUI or script (e.g., creating AD users), FlowPilot must ask the engineer which approach they prefer BEFORE suggesting either. Never assume the user wants a script. See `FLOWPILOT_SYSTEM_PROMPT` rules in `flowpilot_engine.py`.
|
**87. FlowPilot must ask GUI vs script preference:** When a task can be done via GUI or script (e.g., creating AD users), FlowPilot must ask the engineer which approach they prefer BEFORE suggesting either. Never assume the user wants a script. See `FLOWPILOT_SYSTEM_PROMPT` rules in `flowpilot_engine.py`.
|
||||||
|
|
||||||
**88. Charcoal palette — sidebar-darkest approach:** Sidebar `#10121a`, page `#1a1c23`, cards `#22252e`, borders `#2e3240`. This gives more contrast range than true-dark (`#0c0d10`). All colors via CSS variables in `index.css` `@theme` block.
|
**88. Charcoal palette — sidebar-darkest approach:** Sidebar `#10121a`, page `#1a1c23`, cards `#22252e`, borders `#2e3240`. This gives more contrast range than true-dark (`#0c0d10`). All colors via CSS variables in `index.css` `@theme` block. Accent is ember orange (#f97316), not cyan.
|
||||||
|
|
||||||
**89. QuickLaunch merged into CommandPalette:** There is no separate QuickLaunch/lightning bolt. The unified Cmd+K omnibar handles search, navigation, quick actions, and FlowPilot. `QuickLaunch.tsx` was deleted.
|
**89. QuickLaunch merged into CommandPalette:** There is no separate QuickLaunch/lightning bolt. The unified Cmd+K omnibar handles search, navigation, quick actions, and FlowPilot. `QuickLaunch.tsx` was deleted.
|
||||||
|
|
||||||
@@ -380,7 +380,7 @@ gh run view <id> --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusi
|
|||||||
|
|
||||||
**95. Image upload → AI vision pipeline:** Paste/attach images → upload to Railway S3 bucket via `uploadsApi.upload()` → send `upload_ids` with chat message → backend fetches from S3 via `storage_service.download_file()` → resized via `storage_service.resize_image_for_vision()` (Pillow, 1568px max, PNG→JPEG) → base64-encoded → sent as Claude multimodal content blocks. Max 3 images/message. Images are NOT stored in conversation history (text-only). Vision helpers live in `storage_service.py`.
|
**95. Image upload → AI vision pipeline:** Paste/attach images → upload to Railway S3 bucket via `uploadsApi.upload()` → send `upload_ids` with chat message → backend fetches from S3 via `storage_service.download_file()` → resized via `storage_service.resize_image_for_vision()` (Pillow, 1568px max, PNG→JPEG) → base64-encoded → sent as Claude multimodal content blocks. Max 3 images/message. Images are NOT stored in conversation history (text-only). Vision helpers live in `storage_service.py`.
|
||||||
|
|
||||||
**96. `bg-accent` is bright cyan — never use for code/kbd elements:** In Tailwind v4, `bg-accent` maps to `--color-accent: #22d3ee`. Use `bg-code` for code blocks, `bg-white/[0.12] border border-white/[0.06]` for inline code/badges, `bg-white/[0.08]` for kbd shortcuts. Cyan is reserved for interactive elements only (buttons, active nav, links).
|
**96. `bg-accent` is ember orange — never use for code/kbd elements:** In Tailwind v4, `bg-accent` maps to `--color-accent: #f97316`. Use `bg-code` for code blocks, `bg-white/[0.12] border border-white/[0.06]` for inline code/badges, `bg-white/[0.08]` for kbd shortcuts. Orange is reserved for interactive elements only (buttons, active nav, links).
|
||||||
|
|
||||||
**97. Railway Object Storage (S3 bucket) is provisioned:** Bucket `resolutionflow-uploads` on Railway canvas. Variables: `STORAGE_ENDPOINT`, `STORAGE_ACCESS_KEY`, `STORAGE_SECRET_KEY`, `STORAGE_BUCKET_NAME`, `STORAGE_REGION` — mapped via variable references on the `patherly` backend service. Accessed via boto3 in `storage_service.py`. Pillow (`Pillow>=10.0.0`) + `libjpeg-dev`/`zlib1g-dev` in Dockerfile for image resize.
|
**97. Railway Object Storage (S3 bucket) is provisioned:** Bucket `resolutionflow-uploads` on Railway canvas. Variables: `STORAGE_ENDPOINT`, `STORAGE_ACCESS_KEY`, `STORAGE_SECRET_KEY`, `STORAGE_BUCKET_NAME`, `STORAGE_REGION` — mapped via variable references on the `patherly` backend service. Accessed via boto3 in `storage_service.py`. Pillow (`Pillow>=10.0.0`) + `libjpeg-dev`/`zlib1g-dev` in Dockerfile for image resize.
|
||||||
|
|
||||||
@@ -404,15 +404,15 @@ gh run view <id> --json jobs --jq '.jobs[] | {name: .name, conclusion: .conclusi
|
|||||||
**Source of truth:** [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) — always read this before making visual or UI decisions.
|
**Source of truth:** [DESIGN-SYSTEM.md](DESIGN-SYSTEM.md) — always read this before making visual or UI decisions.
|
||||||
|
|
||||||
- **Theme:** Flat, high-contrast dark theme (Sentry/PostHog-inspired). No glass morphism, no backdrop blur, no ambient orbs, no gradient backgrounds on surfaces. Light mode planned.
|
- **Theme:** Flat, high-contrast dark theme (Sentry/PostHog-inspired). No glass morphism, no backdrop blur, no ambient orbs, no gradient backgrounds on surfaces. Light mode planned.
|
||||||
- **Backgrounds:** `bg-page` (`#0c0d10`), `bg-sidebar` (`#0f1118`), `bg-card` (`#14161d`), `bg-elevated` (`#1c1f2a`)
|
- **Backgrounds:** `bg-page` (`#1a1c23`), `bg-sidebar` (`#10121a`), `bg-card` (`#22252e`), `bg-elevated` (`#2e3140`)
|
||||||
- **Cards:** `bg-card` with 1px `border-default` (`#1e2130`), 8px radius. No shadows, no blur, no gradients. Hover: `border-hover` (`#2a2f3d`)
|
- **Cards:** `bg-card` with 1px `border-default` (`#2e3240`), 8px radius. No shadows, no blur, no gradients. Hover: `border-hover` (`#3d4252`)
|
||||||
- **Buttons:** Primary: solid `accent` (#22d3ee), white text, 5px radius. Ghost: transparent + 1px border, hover `bg-elevated`
|
- **Buttons:** Primary: solid `accent` (#f97316), white text, 5px radius. Ghost: transparent + 1px border, hover `bg-elevated`
|
||||||
- **Inputs:** `bg-input` (`#191c25`) with 1px `border-default`, 5px radius. Focus: `border-color: accent` + `box-shadow: 0 0 0 2px accent-dim`
|
- **Inputs:** `bg-input` (`#282b35`) with 1px `border-default`, 5px radius. Focus: `border-color: accent` + `box-shadow: 0 0 0 2px accent-dim`
|
||||||
- **Text:** `text-heading` (`#f0f2f5`) → `text-primary` (`#e2e5eb`) → `text-secondary` (`#848b9b`) → `text-muted` (`#4f5666`)
|
- **Text:** `text-heading` (`#f0f2f5`) → `text-primary` (`#e2e5eb`) → `text-secondary` (`#848b9b`) → `text-muted` (`#4f5666`)
|
||||||
- **Borders:** `border-default` (`#1e2130`), `border-hover` (`#2a2f3d`)
|
- **Borders:** `border-default` (`#2e3240`), `border-hover` (`#3d4252`)
|
||||||
- **Functional colors:** `#34d399` (success), `#fbbf24` (warning), `#f87171` (danger) — each with `-dim` variant at 10% opacity
|
- **Functional colors:** `#34d399` (success), `#eab308` (warning), `#f87171` (danger) — each with `-dim` variant at 10% opacity
|
||||||
- **Accent:** Cyan `#22d3ee` — used sparingly (≤5% of UI). `accent-dim` = `rgba(34,211,238,0.10)`, `accent-text` = `#67e8f9`
|
- **Accent:** Ember orange `#f97316` — used sparingly (≤5% of UI). `accent-dim` = `rgba(249,115,22,0.10)`, `accent-text` = `#fdba74`
|
||||||
- **Deprecated:** Do NOT use `glass-card`, `glass-stat`, `bg-gradient-brand`, `text-gradient-brand`, `backdrop-filter: blur()`, ambient orbs, or purple gradients
|
- **Deprecated:** Do NOT use `glass-card`, `glass-stat`, `bg-gradient-brand`, `text-gradient-brand`, `backdrop-filter: blur()`, ambient orbs, purple gradients, or cyan accent (`#22d3ee`)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
# ResolutionFlow Design System v4
|
# ResolutionFlow Design System v5
|
||||||
|
|
||||||
> **Status:** ACTIVE — This document is the single source of truth for all frontend design decisions.
|
> **Status:** ACTIVE — This document is the single source of truth for all frontend design decisions.
|
||||||
> **Supersedes:** All previous design system docs including `DESIGN_SYSTEM_GUIDE.md`, `UI-DESIGN-SYSTEM.md`, `REBRAND-IMPLEMENTATION-GUIDE.md`, and any `COMPONENT_EXAMPLES.md` files.
|
> **Supersedes:** All previous design system docs including `DESIGN_SYSTEM_GUIDE.md`, `UI-DESIGN-SYSTEM.md`, `REBRAND-IMPLEMENTATION-GUIDE.md`, and any `COMPONENT_EXAMPLES.md` files. Also supersedes the v4 cyan accent system.
|
||||||
> **Last Updated:** March 21, 2026
|
> **Last Updated:** March 24, 2026
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Design Philosophy
|
## Design Philosophy
|
||||||
|
|
||||||
ResolutionFlow uses a **flat, high-contrast dark theme** inspired by Sentry and PostHog. The aesthetic is premium, clean, and minimal — no glass morphism, no backdrop blur, no ambient orbs, no gradient backgrounds on surfaces. The accent color appears in ≤5% of the UI. Every design decision prioritizes **readability over decoration**.
|
ResolutionFlow uses a **flat, high-contrast dark theme** inspired by Sentry and PostHog. The aesthetic is premium, clean, and minimal — no glass morphism, no backdrop blur, no ambient orbs, no gradient backgrounds on surfaces. The accent color (ember orange) appears in ≤5% of the UI. Warm accent on cold charcoal surfaces creates high contrast and distinctive personality — orange conveys urgency and action, fitting for a troubleshooting tool. Every design decision prioritizes **readability over decoration**.
|
||||||
|
|
||||||
**Light mode** is a planned addition (dark/light toggle). Design all components with CSS variables so theming is a variable swap, not a rewrite.
|
**Light mode** is a planned addition (dark/light toggle). Design all components with CSS variables so theming is a variable swap, not a rewrite.
|
||||||
|
|
||||||
@@ -18,39 +18,41 @@ ResolutionFlow uses a **flat, high-contrast dark theme** inspired by Sentry and
|
|||||||
|
|
||||||
All colors are defined as CSS custom properties in `index.css` inside the `@theme` block (Tailwind v4) or `:root` / `.dark` blocks (Tailwind v3).
|
All colors are defined as CSS custom properties in `index.css` inside the `@theme` block (Tailwind v4) or `:root` / `.dark` blocks (Tailwind v3).
|
||||||
|
|
||||||
### Dark Mode (Default)
|
### Dark Mode (Default) — Charcoal Palette
|
||||||
|
|
||||||
```
|
```
|
||||||
Page background: #0c0d10
|
Page background: #1a1c23
|
||||||
Sidebar background: #0f1118
|
Sidebar background: #10121a
|
||||||
Card background: #14161d
|
Card background: #22252e
|
||||||
Card hover: #191c25
|
Card hover: #282b35
|
||||||
Input background: #191c25
|
Input background: #282b35
|
||||||
Code background: #0e1017
|
Code background: #14161e
|
||||||
Elevated surface: #1c1f2a
|
Elevated surface: #2e3140
|
||||||
|
|
||||||
Text primary: #e2e5eb
|
Text primary: #e2e5eb
|
||||||
Text heading: #f0f2f5
|
Text heading: #f0f2f5
|
||||||
Text secondary: #848b9b
|
Text secondary: #848b9b
|
||||||
Text muted: #4f5666
|
Text muted: #4f5666
|
||||||
Text rail label: #6b7280
|
Text rail label: #e2e5eb
|
||||||
|
|
||||||
Border default: #1e2130
|
Border default: #2e3240
|
||||||
Border hover: #2a2f3d
|
Border hover: #3d4252
|
||||||
|
|
||||||
Accent (cyan): #22d3ee
|
Accent (ember): #f97316
|
||||||
Accent hover: #06b6d4
|
Accent hover: #ea580c
|
||||||
Accent dim (8-10%): rgba(34,211,238,0.10)
|
Accent dim (10%): rgba(249,115,22,0.10)
|
||||||
Accent text: #67e8f9
|
Accent text: #fdba74
|
||||||
|
|
||||||
Success: #34d399
|
Success: #34d399
|
||||||
Success dim: rgba(52,211,153,0.10)
|
Success dim: rgba(52,211,153,0.10)
|
||||||
Warning: #fbbf24
|
Warning: #eab308
|
||||||
Warning dim: rgba(251,191,36,0.10)
|
Warning dim: rgba(234,179,8,0.10)
|
||||||
Danger: #f87171
|
Danger: #f87171
|
||||||
Danger dim: rgba(248,113,113,0.10)
|
Danger dim: rgba(248,113,113,0.10)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **Note:** Warning shifted from amber (#fbbf24) to yellow (#eab308) to maintain clear separation from the orange accent.
|
||||||
|
|
||||||
### Light Mode (Planned)
|
### Light Mode (Planned)
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -70,9 +72,9 @@ Text muted: #8b92a1
|
|||||||
Border default: #dde0e7
|
Border default: #dde0e7
|
||||||
Border hover: #c5c9d3
|
Border hover: #c5c9d3
|
||||||
|
|
||||||
Accent: #0891b2
|
Accent: #ea580c
|
||||||
Accent dim: rgba(8,145,178,0.07)
|
Accent dim: rgba(234,88,12,0.07)
|
||||||
Accent text: #0e7490
|
Accent text: #c2410c
|
||||||
```
|
```
|
||||||
|
|
||||||
### What NOT To Use
|
### What NOT To Use
|
||||||
@@ -82,6 +84,7 @@ Accent text: #0e7490
|
|||||||
- No ambient orbs or floating glow elements
|
- No ambient orbs or floating glow elements
|
||||||
- No `bg-white/[0.04]` opacity-based backgrounds
|
- No `bg-white/[0.04]` opacity-based backgrounds
|
||||||
- No purple gradient accent (`#818cf8 → #a78bfa`) — this is deprecated
|
- No purple gradient accent (`#818cf8 → #a78bfa`) — this is deprecated
|
||||||
|
- No cyan accent (`#22d3ee` / `#06b6d4` / `#67e8f9`) — replaced by ember orange in v5
|
||||||
- No `text-gradient-brand` utility — replaced by solid `accent-text` color
|
- No `text-gradient-brand` utility — replaced by solid `accent-text` color
|
||||||
- No `glass-card`, `glass-stat`, `glass-card-glow` CSS utilities
|
- No `glass-card`, `glass-stat`, `glass-card-glow` CSS utilities
|
||||||
|
|
||||||
@@ -236,13 +239,14 @@ Placeholder: text-muted
|
|||||||
|
|
||||||
**Primary:**
|
**Primary:**
|
||||||
```
|
```
|
||||||
Background: accent (#22d3ee)
|
Background: accent (#f97316)
|
||||||
Color: #fff
|
Color: #fff
|
||||||
Border: none
|
Border: none
|
||||||
Border-radius: 5px
|
Border-radius: 5px
|
||||||
Padding: 9px 16px
|
Padding: 9px 16px
|
||||||
Font: 13px, 550 weight
|
Font: 13px, 550 weight
|
||||||
Hover: brightness(1.1)
|
Hover: accent-hover (#ea580c), box-shadow 0 2px 12px rgba(249,115,22,0.25), translateY(-1px)
|
||||||
|
Active: translateY(0), box-shadow 0 0 4px rgba(249,115,22,0.15)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Ghost:**
|
**Ghost:**
|
||||||
@@ -289,7 +293,7 @@ Color: accent-text
|
|||||||
|
|
||||||
## Logo
|
## Logo
|
||||||
|
|
||||||
- **Mark:** 30-32px square, border-radius 8px, `linear-gradient(135deg, #06b6d4, #22d3ee)`, white lightning bolt SVG
|
- **Mark:** 30-32px square, border-radius 8px, `linear-gradient(135deg, #ea580c, #f97316)`, white lightning bolt SVG
|
||||||
- **Wordmark:** "ResolutionFlow" in Bricolage Grotesque, 16-17px, weight 700, text-heading color
|
- **Wordmark:** "ResolutionFlow" in Bricolage Grotesque, 16-17px, weight 700, text-heading color
|
||||||
- **Combined:** Mark + wordmark horizontally, 10px gap
|
- **Combined:** Mark + wordmark horizontally, 10px gap
|
||||||
|
|
||||||
@@ -325,21 +329,21 @@ Shadows communicate **interaction state**, not decoration. On dark backgrounds,
|
|||||||
|
|
||||||
**Resting state:** No shadows. Elements are flat with 1px borders.
|
**Resting state:** No shadows. Elements are flat with 1px borders.
|
||||||
|
|
||||||
**Elevation on dark backgrounds (the principle):** Instead of shadow = darker, elevation = lighter. A "raised" element gets a brighter surface color (`bg-elevated` / `#1c1f2a`) and optionally a very faint cyan glow. This creates perceived depth through contrast.
|
**Elevation on dark backgrounds (the principle):** Instead of shadow = darker, elevation = lighter. A "raised" element gets a brighter surface color (`bg-elevated` / `#2e3140`) and optionally a very faint orange glow. This creates perceived depth through contrast.
|
||||||
|
|
||||||
**Hover state (buttons):** Lift effect with accent glow.
|
**Hover state (buttons):** Lift effect with accent glow.
|
||||||
|
|
||||||
- Primary button hover: `0 2px 10px rgba(34,211,238,0.2)` + `translateY(-1px)` — cyan glow
|
- Primary button hover: `0 2px 12px rgba(249,115,22,0.25)` + `translateY(-1px)` — orange glow
|
||||||
- Ghost button hover: brighter border (`border-hover`) + `translateY(-1px)`, no shadow
|
- Ghost button hover: brighter border (`border-hover`) + `translateY(-1px)`, no shadow
|
||||||
- Active/click: glow fades, element "presses down" to `translateY(0)`
|
- Active/click: glow fades, element "presses down" to `translateY(0)`
|
||||||
|
|
||||||
**Active/selected state (tabs, toggles):** Elevated surface + faint accent glow.
|
**Active/selected state (tabs, toggles):** Elevated surface + faint accent glow.
|
||||||
|
|
||||||
- Active tab: `bg-elevated` + `box-shadow: 0 1px 4px rgba(34,211,238,0.08)` — class: `tab-active-shadow`
|
- Active tab: `bg-elevated` + `box-shadow: 0 1px 4px rgba(249,115,22,0.08)` — class: `tab-active-shadow`
|
||||||
|
|
||||||
**Card hover lift (optional):** For clickable cards.
|
**Card hover lift (optional):** For clickable cards.
|
||||||
|
|
||||||
- Hover: brighter border + `0 2px 8px rgba(34,211,238,0.06)` + `translateY(-2px)` — class: `card-lift`
|
- Hover: brighter border + `0 2px 8px rgba(249,115,22,0.06)` + `translateY(-2px)` — class: `card-lift`
|
||||||
|
|
||||||
**Overlays:** Flyouts, dropdowns, modals get stronger shadows (they overlay lighter content).
|
**Overlays:** Flyouts, dropdowns, modals get stronger shadows (they overlay lighter content).
|
||||||
|
|
||||||
@@ -352,6 +356,7 @@ Shadows communicate **interaction state**, not decoration. On dark backgrounds,
|
|||||||
- No `rgba(0,0,0,...)` shadows on resting elements (invisible on dark bg)
|
- No `rgba(0,0,0,...)` shadows on resting elements (invisible on dark bg)
|
||||||
- No permanent decorative shadows
|
- No permanent decorative shadows
|
||||||
- No heavy glow effects — accent glow should be barely perceptible (≤ 0.1 opacity)
|
- No heavy glow effects — accent glow should be barely perceptible (≤ 0.1 opacity)
|
||||||
|
- No cyan glow effects — all accent glows use orange rgba(249,115,22,...)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -402,3 +407,15 @@ These files contain outdated design information and should be ignored:
|
|||||||
- `REBRAND-IMPLEMENTATION-GUIDE.md` — Old purple rebrand from Patherly
|
- `REBRAND-IMPLEMENTATION-GUIDE.md` — Old purple rebrand from Patherly
|
||||||
- `COMPONENT_EXAMPLES.md` — Old monochrome component patterns
|
- `COMPONENT_EXAMPLES.md` — Old monochrome component patterns
|
||||||
- Any file referencing `glass-card`, `glass-stat`, `bg-gradient-brand`, or `text-gradient-brand`
|
- Any file referencing `glass-card`, `glass-stat`, `bg-gradient-brand`, or `text-gradient-brand`
|
||||||
|
- Any code using cyan accent values (`#22d3ee`, `#06b6d4`, `#67e8f9`, `rgba(34,211,238,...)`) — migrate to ember orange
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Decisions Log
|
||||||
|
|
||||||
|
| Date | Decision | Rationale |
|
||||||
|
|------|----------|-----------|
|
||||||
|
| 2026-03-24 | Accent color changed from cyan (#22d3ee) to ember orange (#f97316) | Cyan caused contrast issues, felt generic "tech SaaS". Orange provides warmth against cold charcoal, conveys urgency fitting for troubleshooting, and is distinctive in the MSP tool space. |
|
||||||
|
| 2026-03-24 | Warning color shifted from amber (#fbbf24) to yellow (#eab308) | Orange accent would clash with amber warning. Yellow provides clear semantic separation from the orange accent. |
|
||||||
|
| 2026-03-24 | Light mode accent set to #ea580c (orange-600) | Darker orange variant ensures proper contrast on white/light surfaces. |
|
||||||
|
| 2026-03-24 | Synced DESIGN-SYSTEM.md to actual charcoal palette | Doc was behind — still showed pre-charcoal values (#0c0d10 page, #14161d card). Updated to match index.css (#1a1c23 page, #22252e card). |
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
<!-- PWA Icons -->
|
<!-- PWA Icons -->
|
||||||
<link rel="apple-touch-icon" href="/icons/app-icon-gradient.svg" />
|
<link rel="apple-touch-icon" href="/icons/app-icon-gradient.svg" />
|
||||||
<meta name="theme-color" content="#101114" />
|
<meta name="theme-color" content="#10121a" />
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Prevent flash of wrong theme on initial load
|
// Prevent flash of wrong theme on initial load
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<svg viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 80 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="resolutionflow-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
<linearGradient id="resolutionflow-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
<stop offset="0%" stop-color="#06b6d4"/>
|
<stop offset="0%" stop-color="#ea580c"/>
|
||||||
<stop offset="100%" stop-color="#22d3ee"/>
|
<stop offset="100%" stop-color="#f97316"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
<!-- Input circles (choices) -->
|
<!-- Input circles (choices) -->
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -1,8 +1,8 @@
|
|||||||
<svg viewBox="0 0 320 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 320 80" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="rf-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
<linearGradient id="rf-gradient" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
<stop offset="0%" stop-color="#06b6d4"/>
|
<stop offset="0%" stop-color="#ea580c"/>
|
||||||
<stop offset="100%" stop-color="#22d3ee"/>
|
<stop offset="100%" stop-color="#f97316"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -1,8 +1,8 @@
|
|||||||
<svg viewBox="0 0 320 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg viewBox="0 0 320 100" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="rf-gradient-tag" x1="0%" y1="0%" x2="100%" y2="0%">
|
<linearGradient id="rf-gradient-tag" x1="0%" y1="0%" x2="100%" y2="0%">
|
||||||
<stop offset="0%" stop-color="#06b6d4"/>
|
<stop offset="0%" stop-color="#ea580c"/>
|
||||||
<stop offset="100%" stop-color="#22d3ee"/>
|
<stop offset="100%" stop-color="#f97316"/>
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -294,7 +294,7 @@ export function NotificationSettings() {
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={config.events_enabled[eventKey] ?? false}
|
checked={config.events_enabled[eventKey] ?? false}
|
||||||
onChange={() => handleToggleEvent(config, eventKey)}
|
onChange={() => handleToggleEvent(config, eventKey)}
|
||||||
className="h-3.5 w-3.5 rounded border-border bg-card text-primary focus:ring-primary/30 focus:ring-offset-0 cursor-pointer accent-[#06b6d4]"
|
className="h-3.5 w-3.5 rounded border-border bg-card text-primary focus:ring-primary/30 focus:ring-offset-0 cursor-pointer accent-[#ea580c]"
|
||||||
/>
|
/>
|
||||||
<span className="text-sm text-foreground">{eventLabel}</span>
|
<span className="text-sm text-foreground">{eventLabel}</span>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import type { FlowAnalyticsResponse, AnalyticsPeriod } from '@/types'
|
|||||||
const CHART_COLORS = {
|
const CHART_COLORS = {
|
||||||
resolved: '#34d399',
|
resolved: '#34d399',
|
||||||
escalated: '#f87171',
|
escalated: '#f87171',
|
||||||
workaround: '#fbbf24',
|
workaround: '#eab308',
|
||||||
unresolved: '#94a3b8',
|
unresolved: '#94a3b8',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -95,21 +95,21 @@ export default function PsaMetricsPanel({ data }: PsaMetricsPanelProps) {
|
|||||||
<Bar
|
<Bar
|
||||||
yAxisId="entries"
|
yAxisId="entries"
|
||||||
dataKey="entries"
|
dataKey="entries"
|
||||||
fill="rgba(34,211,238,0.3)"
|
fill="rgba(249,115,22,0.3)"
|
||||||
radius={[4, 4, 0, 0]}
|
radius={[4, 4, 0, 0]}
|
||||||
/>
|
/>
|
||||||
<Area
|
<Area
|
||||||
yAxisId="hours"
|
yAxisId="hours"
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="hours"
|
dataKey="hours"
|
||||||
stroke="#22d3ee"
|
stroke="#f97316"
|
||||||
fill="url(#psaHoursGradient)"
|
fill="url(#psaHoursGradient)"
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="psaHoursGradient" x1="0" y1="0" x2="0" y2="1">
|
<linearGradient id="psaHoursGradient" x1="0" y1="0" x2="0" y2="1">
|
||||||
<stop offset="5%" stopColor="#22d3ee" stopOpacity={0.3} />
|
<stop offset="5%" stopColor="#f97316" stopOpacity={0.3} />
|
||||||
<stop offset="95%" stopColor="#22d3ee" stopOpacity={0} />
|
<stop offset="95%" stopColor="#f97316" stopOpacity={0} />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</ComposedChart>
|
</ComposedChart>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ export function BrandLogo({ size = 'sm', className }: BrandLogoProps) {
|
|||||||
width: dim,
|
width: dim,
|
||||||
height: dim,
|
height: dim,
|
||||||
borderRadius: size === 'sm' ? 8 : 14,
|
borderRadius: size === 'sm' ? 8 : 14,
|
||||||
background: 'linear-gradient(135deg, #06b6d4, #22d3ee)',
|
background: 'linear-gradient(135deg, #ea580c, #f97316)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/**
|
/**
|
||||||
* SVG illustrations for EmptyState components.
|
* SVG illustrations for EmptyState components.
|
||||||
* Each uses the brand cyan palette (#06b6d4 / #22d3ee) at low opacity.
|
* Each uses the brand orange palette (#ea580c / #f97316) at low opacity.
|
||||||
* ViewBox: 80x60, simple line art style.
|
* ViewBox: 80x60, simple line art style.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -8,19 +8,19 @@ export function FlowIllustration() {
|
|||||||
return (
|
return (
|
||||||
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{/* Root node */}
|
{/* Root node */}
|
||||||
<circle cx="40" cy="10" r="6" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<circle cx="40" cy="10" r="6" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
{/* Branches */}
|
{/* Branches */}
|
||||||
<line x1="40" y1="16" x2="20" y2="34" stroke="#06b6d4" strokeWidth="1.5" />
|
<line x1="40" y1="16" x2="20" y2="34" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<line x1="40" y1="16" x2="60" y2="34" stroke="#06b6d4" strokeWidth="1.5" />
|
<line x1="40" y1="16" x2="60" y2="34" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
{/* Left child */}
|
{/* Left child */}
|
||||||
<circle cx="20" cy="38" r="5" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<circle cx="20" cy="38" r="5" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
{/* Right child */}
|
{/* Right child */}
|
||||||
<circle cx="60" cy="38" r="5" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<circle cx="60" cy="38" r="5" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
{/* Leaf branches */}
|
{/* Leaf branches */}
|
||||||
<line x1="20" y1="43" x2="12" y2="52" stroke="#22d3ee" strokeWidth="1" />
|
<line x1="20" y1="43" x2="12" y2="52" stroke="#f97316" strokeWidth="1" />
|
||||||
<line x1="20" y1="43" x2="28" y2="52" stroke="#22d3ee" strokeWidth="1" />
|
<line x1="20" y1="43" x2="28" y2="52" stroke="#f97316" strokeWidth="1" />
|
||||||
<circle cx="12" cy="54" r="3" fill="rgba(34,211,238,0.15)" stroke="#22d3ee" strokeWidth="1" />
|
<circle cx="12" cy="54" r="3" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1" />
|
||||||
<circle cx="28" cy="54" r="3" fill="rgba(34,211,238,0.15)" stroke="#22d3ee" strokeWidth="1" />
|
<circle cx="28" cy="54" r="3" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -29,12 +29,12 @@ export function AnalyticsIllustration() {
|
|||||||
return (
|
return (
|
||||||
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{/* Bars */}
|
{/* Bars */}
|
||||||
<rect x="12" y="38" width="10" height="16" rx="2" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<rect x="12" y="38" width="10" height="16" rx="2" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<rect x="26" y="28" width="10" height="26" rx="2" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<rect x="26" y="28" width="10" height="26" rx="2" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
<rect x="40" y="20" width="10" height="34" rx="2" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<rect x="40" y="20" width="10" height="34" rx="2" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<rect x="54" y="10" width="10" height="44" rx="2" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<rect x="54" y="10" width="10" height="44" rx="2" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
{/* Baseline */}
|
{/* Baseline */}
|
||||||
<line x1="8" y1="56" x2="72" y2="56" stroke="#06b6d4" strokeWidth="1" opacity="0.5" />
|
<line x1="8" y1="56" x2="72" y2="56" stroke="#ea580c" strokeWidth="1" opacity="0.5" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -43,17 +43,17 @@ export function SessionIllustration() {
|
|||||||
return (
|
return (
|
||||||
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{/* Card 1 */}
|
{/* Card 1 */}
|
||||||
<rect x="12" y="8" width="56" height="12" rx="3" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<rect x="12" y="8" width="56" height="12" rx="3" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<circle cx="22" cy="14" r="2" fill="#06b6d4" />
|
<circle cx="22" cy="14" r="2" fill="#ea580c" />
|
||||||
<line x1="28" y1="14" x2="56" y2="14" stroke="#06b6d4" strokeWidth="1" opacity="0.5" />
|
<line x1="28" y1="14" x2="56" y2="14" stroke="#ea580c" strokeWidth="1" opacity="0.5" />
|
||||||
{/* Card 2 */}
|
{/* Card 2 */}
|
||||||
<rect x="12" y="24" width="56" height="12" rx="3" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<rect x="12" y="24" width="56" height="12" rx="3" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
<circle cx="22" cy="30" r="2" fill="#22d3ee" />
|
<circle cx="22" cy="30" r="2" fill="#f97316" />
|
||||||
<line x1="28" y1="30" x2="52" y2="30" stroke="#22d3ee" strokeWidth="1" opacity="0.5" />
|
<line x1="28" y1="30" x2="52" y2="30" stroke="#f97316" strokeWidth="1" opacity="0.5" />
|
||||||
{/* Card 3 */}
|
{/* Card 3 */}
|
||||||
<rect x="12" y="40" width="56" height="12" rx="3" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<rect x="12" y="40" width="56" height="12" rx="3" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<circle cx="22" cy="46" r="2" fill="#06b6d4" />
|
<circle cx="22" cy="46" r="2" fill="#ea580c" />
|
||||||
<line x1="28" y1="46" x2="48" y2="46" stroke="#06b6d4" strokeWidth="1" opacity="0.5" />
|
<line x1="28" y1="46" x2="48" y2="46" stroke="#ea580c" strokeWidth="1" opacity="0.5" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -62,19 +62,19 @@ export function IntegrationIllustration() {
|
|||||||
return (
|
return (
|
||||||
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{/* Left box */}
|
{/* Left box */}
|
||||||
<rect x="6" y="18" width="22" height="24" rx="4" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<rect x="6" y="18" width="22" height="24" rx="4" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<line x1="12" y1="26" x2="22" y2="26" stroke="#06b6d4" strokeWidth="1" opacity="0.6" />
|
<line x1="12" y1="26" x2="22" y2="26" stroke="#ea580c" strokeWidth="1" opacity="0.6" />
|
||||||
<line x1="12" y1="30" x2="20" y2="30" stroke="#06b6d4" strokeWidth="1" opacity="0.4" />
|
<line x1="12" y1="30" x2="20" y2="30" stroke="#ea580c" strokeWidth="1" opacity="0.4" />
|
||||||
{/* Right box */}
|
{/* Right box */}
|
||||||
<rect x="52" y="18" width="22" height="24" rx="4" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<rect x="52" y="18" width="22" height="24" rx="4" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
<line x1="58" y1="26" x2="68" y2="26" stroke="#22d3ee" strokeWidth="1" opacity="0.6" />
|
<line x1="58" y1="26" x2="68" y2="26" stroke="#f97316" strokeWidth="1" opacity="0.6" />
|
||||||
<line x1="58" y1="30" x2="66" y2="30" stroke="#22d3ee" strokeWidth="1" opacity="0.4" />
|
<line x1="58" y1="30" x2="66" y2="30" stroke="#f97316" strokeWidth="1" opacity="0.4" />
|
||||||
{/* Dashed arrows */}
|
{/* Dashed arrows */}
|
||||||
<line x1="30" y1="26" x2="50" y2="26" stroke="#06b6d4" strokeWidth="1.5" strokeDasharray="3 2" />
|
<line x1="30" y1="26" x2="50" y2="26" stroke="#ea580c" strokeWidth="1.5" strokeDasharray="3 2" />
|
||||||
<line x1="50" y1="34" x2="30" y2="34" stroke="#22d3ee" strokeWidth="1.5" strokeDasharray="3 2" />
|
<line x1="50" y1="34" x2="30" y2="34" stroke="#f97316" strokeWidth="1.5" strokeDasharray="3 2" />
|
||||||
{/* Arrow tips */}
|
{/* Arrow tips */}
|
||||||
<path d="M48 23 L52 26 L48 29" stroke="#06b6d4" strokeWidth="1.5" fill="none" />
|
<path d="M48 23 L52 26 L48 29" stroke="#ea580c" strokeWidth="1.5" fill="none" />
|
||||||
<path d="M32 31 L28 34 L32 37" stroke="#22d3ee" strokeWidth="1.5" fill="none" />
|
<path d="M32 31 L28 34 L32 37" stroke="#f97316" strokeWidth="1.5" fill="none" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -83,14 +83,14 @@ export function StepLibraryIllustration() {
|
|||||||
return (
|
return (
|
||||||
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{/* List items */}
|
{/* List items */}
|
||||||
<circle cx="18" cy="14" r="3" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<circle cx="18" cy="14" r="3" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<line x1="26" y1="14" x2="62" y2="14" stroke="#06b6d4" strokeWidth="1.5" opacity="0.5" />
|
<line x1="26" y1="14" x2="62" y2="14" stroke="#ea580c" strokeWidth="1.5" opacity="0.5" />
|
||||||
<circle cx="18" cy="27" r="3" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<circle cx="18" cy="27" r="3" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
<line x1="26" y1="27" x2="58" y2="27" stroke="#22d3ee" strokeWidth="1.5" opacity="0.5" />
|
<line x1="26" y1="27" x2="58" y2="27" stroke="#f97316" strokeWidth="1.5" opacity="0.5" />
|
||||||
<circle cx="18" cy="40" r="3" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<circle cx="18" cy="40" r="3" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<line x1="26" y1="40" x2="54" y2="40" stroke="#06b6d4" strokeWidth="1.5" opacity="0.5" />
|
<line x1="26" y1="40" x2="54" y2="40" stroke="#ea580c" strokeWidth="1.5" opacity="0.5" />
|
||||||
<circle cx="18" cy="53" r="3" fill="rgba(34,211,238,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<circle cx="18" cy="53" r="3" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
<line x1="26" y1="53" x2="50" y2="53" stroke="#22d3ee" strokeWidth="1.5" opacity="0.5" />
|
<line x1="26" y1="53" x2="50" y2="53" stroke="#f97316" strokeWidth="1.5" opacity="0.5" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -99,16 +99,16 @@ export function ScriptIllustration() {
|
|||||||
return (
|
return (
|
||||||
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{/* Terminal window */}
|
{/* Terminal window */}
|
||||||
<rect x="8" y="4" width="64" height="52" rx="4" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<rect x="8" y="4" width="64" height="52" rx="4" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
{/* Title bar */}
|
{/* Title bar */}
|
||||||
<line x1="8" y1="14" x2="72" y2="14" stroke="#06b6d4" strokeWidth="1" opacity="0.3" />
|
<line x1="8" y1="14" x2="72" y2="14" stroke="#ea580c" strokeWidth="1" opacity="0.3" />
|
||||||
<circle cx="16" cy="9" r="2" fill="#06b6d4" opacity="0.4" />
|
<circle cx="16" cy="9" r="2" fill="#ea580c" opacity="0.4" />
|
||||||
<circle cx="23" cy="9" r="2" fill="#22d3ee" opacity="0.4" />
|
<circle cx="23" cy="9" r="2" fill="#f97316" opacity="0.4" />
|
||||||
{/* Code lines */}
|
{/* Code lines */}
|
||||||
<line x1="16" y1="22" x2="40" y2="22" stroke="#06b6d4" strokeWidth="1.5" opacity="0.6" />
|
<line x1="16" y1="22" x2="40" y2="22" stroke="#ea580c" strokeWidth="1.5" opacity="0.6" />
|
||||||
<line x1="20" y1="30" x2="52" y2="30" stroke="#22d3ee" strokeWidth="1.5" opacity="0.5" />
|
<line x1="20" y1="30" x2="52" y2="30" stroke="#f97316" strokeWidth="1.5" opacity="0.5" />
|
||||||
<line x1="20" y1="38" x2="46" y2="38" stroke="#06b6d4" strokeWidth="1.5" opacity="0.4" />
|
<line x1="20" y1="38" x2="46" y2="38" stroke="#ea580c" strokeWidth="1.5" opacity="0.4" />
|
||||||
<line x1="16" y1="46" x2="36" y2="46" stroke="#22d3ee" strokeWidth="1.5" opacity="0.5" />
|
<line x1="16" y1="46" x2="36" y2="46" stroke="#f97316" strokeWidth="1.5" opacity="0.5" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -117,14 +117,14 @@ export function ShareIllustration() {
|
|||||||
return (
|
return (
|
||||||
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="80" height="60" viewBox="0 0 80 60" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
{/* Center node */}
|
{/* Center node */}
|
||||||
<circle cx="28" cy="30" r="8" fill="rgba(6,182,212,0.15)" stroke="#06b6d4" strokeWidth="1.5" />
|
<circle cx="28" cy="30" r="8" fill="rgba(249,115,22,0.15)" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
{/* Top-right node */}
|
{/* Top-right node */}
|
||||||
<circle cx="58" cy="14" r="6" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<circle cx="58" cy="14" r="6" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
{/* Bottom-right node */}
|
{/* Bottom-right node */}
|
||||||
<circle cx="58" cy="46" r="6" fill="rgba(6,182,212,0.15)" stroke="#22d3ee" strokeWidth="1.5" />
|
<circle cx="58" cy="46" r="6" fill="rgba(249,115,22,0.15)" stroke="#f97316" strokeWidth="1.5" />
|
||||||
{/* Connecting lines */}
|
{/* Connecting lines */}
|
||||||
<line x1="35" y1="25" x2="52" y2="17" stroke="#06b6d4" strokeWidth="1.5" />
|
<line x1="35" y1="25" x2="52" y2="17" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
<line x1="35" y1="35" x2="52" y2="43" stroke="#06b6d4" strokeWidth="1.5" />
|
<line x1="35" y1="35" x2="52" y2="43" stroke="#ea580c" strokeWidth="1.5" />
|
||||||
</svg>
|
</svg>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ export function FiltersBar({ filters, activeFilter, onFilterChange }: FiltersBar
|
|||||||
className={cn(
|
className={cn(
|
||||||
'shrink-0 rounded-lg border px-3 py-1.5 text-[0.8125rem] font-medium transition-colors',
|
'shrink-0 rounded-lg border px-3 py-1.5 text-[0.8125rem] font-medium transition-colors',
|
||||||
activeFilter === f.id
|
activeFilter === f.id
|
||||||
? 'border-[#22d3ee]/30 bg-accent-dim text-primary'
|
? 'border-[#f97316]/30 bg-accent-dim text-primary'
|
||||||
: 'border-border bg-card text-muted-foreground hover:border-border/80 hover:text-foreground'
|
: 'border-border bg-card text-muted-foreground hover:border-border/80 hover:text-foreground'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ export function KnowledgeBaseCards() {
|
|||||||
const items = [
|
const items = [
|
||||||
{ label: 'Flows', value: flowCount, icon: Network, color: '#a78bfa', href: '/trees' },
|
{ label: 'Flows', value: flowCount, icon: Network, color: '#a78bfa', href: '/trees' },
|
||||||
{ label: 'Scripts', value: '\u2014', icon: Code2, color: '#2dd4bf', href: '/scripts' },
|
{ label: 'Scripts', value: '\u2014', icon: Code2, color: '#2dd4bf', href: '/scripts' },
|
||||||
{ label: 'Pending Review', value: '\u2014', icon: ListChecks, color: '#fbbf24', href: '/review-queue' },
|
{ label: 'Pending Review', value: '\u2014', icon: ListChecks, color: '#eab308', href: '/review-queue' },
|
||||||
]
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export function PendingEscalations() {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="card-flat overflow-hidden"
|
className="card-flat overflow-hidden"
|
||||||
style={{ borderColor: 'rgba(251, 191, 36, 0.2)' }}
|
style={{ borderColor: 'rgba(234, 179, 8, 0.2)' }}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className="flex items-center justify-between px-5 py-3"
|
className="flex items-center justify-between px-5 py-3"
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function PerformanceCards() {
|
|||||||
label: 'Avg Resolution',
|
label: 'Avg Resolution',
|
||||||
value: avgMttr > 0 ? `${avgMttr}m` : '\u2014',
|
value: avgMttr > 0 ? `${avgMttr}m` : '\u2014',
|
||||||
icon: Clock,
|
icon: Clock,
|
||||||
iconColor: '#22d3ee',
|
iconColor: '#f97316',
|
||||||
href: '/analytics',
|
href: '/analytics',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -59,7 +59,7 @@ export function PerformanceCards() {
|
|||||||
label: 'Session Time',
|
label: 'Session Time',
|
||||||
value: totalMinutes > 0 ? `${totalMinutes}m` : '\u2014',
|
value: totalMinutes > 0 ? `${totalMinutes}m` : '\u2014',
|
||||||
icon: Timer,
|
icon: Timer,
|
||||||
iconColor: '#fbbf24',
|
iconColor: '#eab308',
|
||||||
href: '/analytics',
|
href: '/analytics',
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ export function PreparedSessions() {
|
|||||||
<div className="card-flat p-5 fade-in" style={{ animationDelay: '200ms' }}>
|
<div className="card-flat p-5 fade-in" style={{ animationDelay: '200ms' }}>
|
||||||
<div className="flex items-center justify-between mb-3">
|
<div className="flex items-center justify-between mb-3">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<ClipboardList className="h-4 w-4 text-cyan-400" />
|
<ClipboardList className="h-4 w-4 text-orange-400" />
|
||||||
<h3 className="font-heading text-sm font-semibold text-foreground">Prepared for You</h3>
|
<h3 className="font-heading text-sm font-semibold text-foreground">Prepared for You</h3>
|
||||||
<span className="flex h-5 w-5 items-center justify-center rounded-full bg-cyan-400/20 text-[0.625rem] font-bold text-cyan-400">
|
<span className="flex h-5 w-5 items-center justify-center rounded-full bg-orange-400/20 text-[0.625rem] font-bold text-orange-400">
|
||||||
{sessions.length}
|
{sessions.length}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -52,7 +52,7 @@ export function PreparedSessions() {
|
|||||||
onClick={() => handleStart(session)}
|
onClick={() => handleStart(session)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'group flex w-full items-center justify-between gap-3 rounded-lg border border-border px-4 py-3',
|
'group flex w-full items-center justify-between gap-3 rounded-lg border border-border px-4 py-3',
|
||||||
'text-left transition-all hover:border-cyan-500/30 hover:bg-cyan-500/5'
|
'text-left transition-all hover:border-orange-500/30 hover:bg-orange-500/5'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
|
|||||||
@@ -2,10 +2,10 @@ import { useNavigate } from 'react-router-dom'
|
|||||||
import { Plus, Play, BookOpen, UserPlus } from 'lucide-react'
|
import { Plus, Play, BookOpen, UserPlus } from 'lucide-react'
|
||||||
|
|
||||||
const ACTIONS = [
|
const ACTIONS = [
|
||||||
{ icon: Plus, label: 'New Flow', description: 'Create a new flow', href: '/trees/new', color: '#06b6d4' },
|
{ icon: Plus, label: 'New Flow', description: 'Create a new flow', href: '/trees/new', color: '#ea580c' },
|
||||||
{ icon: Play, label: 'Resume Session', description: 'Continue where you left off', href: '/sessions', color: '#34d399' },
|
{ icon: Play, label: 'Resume Session', description: 'Continue where you left off', href: '/sessions', color: '#34d399' },
|
||||||
{ icon: BookOpen, label: 'Browse Solutions', description: 'Explore solutions library', href: '/step-library', color: '#fbbf24' },
|
{ icon: BookOpen, label: 'Browse Solutions', description: 'Explore solutions library', href: '/step-library', color: '#eab308' },
|
||||||
{ icon: UserPlus, label: 'Invite Team', description: 'Add team members', href: '/account', color: '#06b6d4' },
|
{ icon: UserPlus, label: 'Invite Team', description: 'Add team members', href: '/account', color: '#ea580c' },
|
||||||
] as const
|
] as const
|
||||||
|
|
||||||
export function QuickActions() {
|
export function QuickActions() {
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ interface RecentActivityProps {
|
|||||||
|
|
||||||
const DEFAULT_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: '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: '2', icon: CheckCircle, iconColor: '#ea580c', iconBg: 'rgba(249, 115, 22, 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: '3', icon: Edit, iconColor: '#eab308', iconBg: 'rgba(234, 179, 8, 0.1)', description: 'Updated Printer Troubleshooting flow', timestamp: '1 hr ago' },
|
||||||
{ id: '4', icon: GitBranch, iconColor: '#06b6d4', iconBg: 'rgba(6, 182, 212, 0.1)', description: 'Created new DNS Resolution flow', timestamp: '3 hr ago' },
|
{ id: '4', icon: GitBranch, iconColor: '#ea580c', iconBg: 'rgba(249, 115, 22, 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' },
|
{ id: '5', icon: FileText, iconColor: '#8891a0', iconBg: 'rgba(136, 145, 160, 0.1)', description: 'Exported session report #TK-4821', timestamp: 'Yesterday' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ function timeAgo(dateStr: string): string {
|
|||||||
|
|
||||||
const STATUS_CONFIG: Record<string, { icon: typeof CheckCircle; color: string }> = {
|
const STATUS_CONFIG: Record<string, { icon: typeof CheckCircle; color: string }> = {
|
||||||
resolved: { icon: CheckCircle, color: '#34d399' },
|
resolved: { icon: CheckCircle, color: '#34d399' },
|
||||||
escalated: { icon: AlertTriangle, color: '#fbbf24' },
|
escalated: { icon: AlertTriangle, color: '#eab308' },
|
||||||
abandoned: { icon: XCircle, color: '#8891a0' },
|
abandoned: { icon: XCircle, color: '#8891a0' },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ export function TeamSummary() {
|
|||||||
if (!isAccountOwner) return null
|
if (!isAccountOwner) return null
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
{ label: 'Escalations', value: escalationCount, icon: AlertTriangle, color: '#fbbf24', href: '/escalations' },
|
{ label: 'Escalations', value: escalationCount, icon: AlertTriangle, color: '#eab308', href: '/escalations' },
|
||||||
{ label: 'Team Activity', value: '\u2014', icon: Activity, color: '#22d3ee', href: '/analytics' },
|
{ label: 'Team Activity', value: '\u2014', icon: Activity, color: '#f97316', href: '/analytics' },
|
||||||
{ label: 'Members', value: '\u2014', icon: Users, color: '#a78bfa', href: '/account' },
|
{ label: 'Members', value: '\u2014', icon: Users, color: '#a78bfa', href: '/account' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
|
|||||||
<div
|
<div
|
||||||
className="px-2 py-2 text-center"
|
className="px-2 py-2 text-center"
|
||||||
style={{
|
style={{
|
||||||
borderBottom: day.isToday ? '2px solid #06b6d4' : '1px solid var(--glass-border)',
|
borderBottom: day.isToday ? '2px solid #ea580c' : '1px solid var(--glass-border)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<span className={`font-sans text-xs text-[0.625rem] uppercase tracking-widest ${day.isToday ? 'text-cyan-400' : 'text-muted-foreground'}`}>
|
<span className={`font-sans text-xs text-[0.625rem] uppercase tracking-widest ${day.isToday ? 'text-orange-400' : 'text-muted-foreground'}`}>
|
||||||
{day.label}
|
{day.label}
|
||||||
</span>
|
</span>
|
||||||
<div className={`text-sm font-heading font-bold ${day.isToday ? 'text-foreground' : 'text-muted-foreground'}`}>
|
<div className={`text-sm font-heading font-bold ${day.isToday ? 'text-foreground' : 'text-muted-foreground'}`}>
|
||||||
@@ -72,7 +72,7 @@ export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
|
|||||||
key={event.id}
|
key={event.id}
|
||||||
className="rounded-md px-2 py-1.5 text-[0.6875rem] cursor-pointer hover:bg-accent/30 transition-colors"
|
className="rounded-md px-2 py-1.5 text-[0.6875rem] cursor-pointer hover:bg-accent/30 transition-colors"
|
||||||
style={{
|
style={{
|
||||||
borderLeft: `3px solid ${event.type === 'maintenance' ? '#fbbf24' : '#06b6d4'}`,
|
borderLeft: `3px solid ${event.type === 'maintenance' ? '#eab308' : '#ea580c'}`,
|
||||||
background: 'rgba(255, 255, 255, 0.02)',
|
background: 'rgba(255, 255, 255, 0.02)',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export function FlowPilotActionBar({
|
|||||||
<button
|
<button
|
||||||
onClick={() => setShowStatusUpdate(true)}
|
onClick={() => setShowStatusUpdate(true)}
|
||||||
disabled={isProcessing}
|
disabled={isProcessing}
|
||||||
className="flex items-center justify-center gap-1.5 rounded-lg bg-cyan-500/10 border border-cyan-500/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-cyan-400 hover:bg-cyan-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
className="flex items-center justify-center gap-1.5 rounded-lg bg-orange-500/10 border border-orange-500/20 px-2.5 sm:px-4 py-2 min-h-[40px] sm:min-h-[44px] text-xs sm:text-sm font-medium text-orange-400 hover:bg-orange-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||||
title="Share Update"
|
title="Share Update"
|
||||||
>
|
>
|
||||||
<FileText size={15} />
|
<FileText size={15} />
|
||||||
@@ -152,7 +152,7 @@ export function FlowPilotActionBar({
|
|||||||
value={resolutionSummary}
|
value={resolutionSummary}
|
||||||
onChange={(e) => setResolutionSummary(e.target.value)}
|
onChange={(e) => setResolutionSummary(e.target.value)}
|
||||||
placeholder="What resolved the issue?"
|
placeholder="What resolved the issue?"
|
||||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
|
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none resize-none"
|
||||||
rows={4}
|
rows={4}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -118,7 +118,7 @@ export function FlowPilotSession({
|
|||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => setShowShareCommunication(true)}
|
onClick={() => setShowShareCommunication(true)}
|
||||||
className="flex items-center gap-2 rounded-lg bg-cyan-500/10 border border-cyan-500/20 px-4 py-2.5 text-sm font-medium text-cyan-400 hover:bg-cyan-500/20 transition-colors"
|
className="flex items-center gap-2 rounded-lg bg-orange-500/10 border border-orange-500/20 px-4 py-2.5 text-sm font-medium text-orange-400 hover:bg-orange-500/20 transition-colors"
|
||||||
>
|
>
|
||||||
<FileText size={16} />
|
<FileText size={16} />
|
||||||
{shareLabel}
|
{shareLabel}
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ export function StatusUpdateModal({ open, onClose, onGenerate, context = 'status
|
|||||||
{/* Step 3: Generating */}
|
{/* Step 3: Generating */}
|
||||||
{step === 'generating' && (
|
{step === 'generating' && (
|
||||||
<div className="flex flex-col items-center justify-center py-8 gap-3">
|
<div className="flex flex-col items-center justify-center py-8 gap-3">
|
||||||
<Loader2 size={24} className="animate-spin text-cyan-400" />
|
<Loader2 size={24} className="animate-spin text-orange-400" />
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-sm text-muted-foreground">
|
||||||
Generating {audience === 'email_draft' ? 'email draft' : audience === 'client_update' ? 'client update' : 'ticket notes'}...
|
Generating {audience === 'email_draft' ? 'email draft' : audience === 'client_update' ? 'client update' : 'ticket notes'}...
|
||||||
</p>
|
</p>
|
||||||
@@ -180,7 +180,7 @@ export function StatusUpdateModal({ open, onClose, onGenerate, context = 'status
|
|||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{/* Meta badges */}
|
{/* Meta badges */}
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-cyan-500/10 text-cyan-400 border border-cyan-500/20">
|
<span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-orange-500/10 text-orange-400 border border-orange-500/20">
|
||||||
{AUDIENCES.find(a => a.value === result.audience)?.label}
|
{AUDIENCES.find(a => a.value === result.audience)?.label}
|
||||||
</span>
|
</span>
|
||||||
<span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-[rgba(255,255,255,0.06)] text-muted-foreground border border-[rgba(255,255,255,0.08)]">
|
<span className="inline-flex items-center gap-1 rounded-full px-2.5 py-0.5 text-xs font-medium bg-[rgba(255,255,255,0.06)] text-muted-foreground border border-[rgba(255,255,255,0.08)]">
|
||||||
@@ -209,7 +209,7 @@ export function StatusUpdateModal({ open, onClose, onGenerate, context = 'status
|
|||||||
'flex items-center gap-2 rounded-lg px-4 py-2 min-h-[44px] text-sm font-medium transition-colors',
|
'flex items-center gap-2 rounded-lg px-4 py-2 min-h-[44px] text-sm font-medium transition-colors',
|
||||||
copied
|
copied
|
||||||
? 'bg-emerald-500/20 border border-emerald-500/30 text-emerald-400'
|
? 'bg-emerald-500/20 border border-emerald-500/30 text-emerald-400'
|
||||||
: 'bg-cyan-500/10 border border-cyan-500/20 text-cyan-400 hover:bg-cyan-500/20'
|
: 'bg-orange-500/10 border border-orange-500/20 text-orange-400 hover:bg-orange-500/20'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{copied ? <Check size={16} /> : <Copy size={16} />}
|
{copied ? <Check size={16} /> : <Copy size={16} />}
|
||||||
|
|||||||
@@ -355,7 +355,7 @@ export function CommandPalette({ open, onClose }: CommandPaletteProps) {
|
|||||||
<div key={group.type}>
|
<div key={group.type}>
|
||||||
{/* Section label */}
|
{/* Section label */}
|
||||||
<div className="px-3 pt-3 pb-1">
|
<div className="px-3 pt-3 pb-1">
|
||||||
<span className="font-mono text-[0.6875rem] uppercase tracking-[0.12em] text-[#fbbf24]">
|
<span className="font-mono text-[0.6875rem] uppercase tracking-[0.12em] text-[#eab308]">
|
||||||
{group.label}
|
{group.label}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ export function Sidebar() {
|
|||||||
'group relative flex items-center gap-3 rounded-lg px-3 py-2 text-[0.8125rem] font-medium transition-all duration-150',
|
'group relative flex items-center gap-3 rounded-lg px-3 py-2 text-[0.8125rem] font-medium transition-all duration-150',
|
||||||
active
|
active
|
||||||
? isParentDimmed
|
? isParentDimmed
|
||||||
? 'bg-[rgba(34,211,238,0.05)] text-foreground/70'
|
? 'bg-[rgba(249,115,22,0.05)] text-foreground/70'
|
||||||
: 'bg-accent-dim text-foreground'
|
: 'bg-accent-dim text-foreground'
|
||||||
: 'text-muted-foreground hover:bg-input hover:text-foreground'
|
: 'text-muted-foreground hover:bg-input hover:text-foreground'
|
||||||
)}
|
)}
|
||||||
@@ -473,7 +473,7 @@ export function Sidebar() {
|
|||||||
>
|
>
|
||||||
{/* Drawer header */}
|
{/* Drawer header */}
|
||||||
<div className="px-3 mb-3">
|
<div className="px-3 mb-3">
|
||||||
<h3 className="text-[0.6875rem] font-mono uppercase tracking-[0.12em] text-[#fbbf24]">
|
<h3 className="text-[0.6875rem] font-mono uppercase tracking-[0.12em] text-[#eab308]">
|
||||||
{activeFlyoutGroup.label}
|
{activeFlyoutGroup.label}
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export function TopBar() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => setUserMenuOpen(!userMenuOpen)}
|
onClick={() => setUserMenuOpen(!userMenuOpen)}
|
||||||
className="flex h-8 w-8 items-center justify-center rounded-[10px] text-xs font-heading font-bold text-white hover:opacity-90 transition-opacity"
|
className="flex h-8 w-8 items-center justify-center rounded-[10px] text-xs font-heading font-bold text-white hover:opacity-90 transition-opacity"
|
||||||
style={{ background: 'linear-gradient(135deg, #06b6d4, #22d3ee)' }}
|
style={{ background: 'linear-gradient(135deg, #ea580c, #f97316)' }}
|
||||||
title={user?.name || user?.email || 'User'}
|
title={user?.name || user?.email || 'User'}
|
||||||
>
|
>
|
||||||
{initials}
|
{initials}
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ export function TreeGridView({
|
|||||||
onClick={() => onPrepareSession(tree)}
|
onClick={() => onPrepareSession(tree)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'rounded-md border border-border p-2 text-muted-foreground',
|
'rounded-md border border-border p-2 text-muted-foreground',
|
||||||
'hover:bg-cyan-500/10 hover:text-cyan-400 hover:border-cyan-500/30'
|
'hover:bg-orange-500/10 hover:text-orange-400 hover:border-orange-500/30'
|
||||||
)}
|
)}
|
||||||
title="Prepare session for engineer"
|
title="Prepare session for engineer"
|
||||||
aria-label="Prepare session"
|
aria-label="Prepare session"
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ export function TreeListView({
|
|||||||
onClick={() => onPrepareSession(tree)}
|
onClick={() => onPrepareSession(tree)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'rounded-md border border-border p-1.5 text-muted-foreground',
|
'rounded-md border border-border p-1.5 text-muted-foreground',
|
||||||
'hover:bg-cyan-500/10 hover:text-cyan-400 hover:border-cyan-500/30'
|
'hover:bg-orange-500/10 hover:text-orange-400 hover:border-orange-500/30'
|
||||||
)}
|
)}
|
||||||
title="Prepare session for engineer"
|
title="Prepare session for engineer"
|
||||||
aria-label="Prepare session"
|
aria-label="Prepare session"
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ export function TreeTableView({
|
|||||||
onClick={() => onPrepareSession(tree)}
|
onClick={() => onPrepareSession(tree)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'rounded-md border border-border p-1.5 text-muted-foreground',
|
'rounded-md border border-border p-1.5 text-muted-foreground',
|
||||||
'hover:bg-cyan-500/10 hover:text-cyan-400 hover:border-cyan-500/30'
|
'hover:bg-orange-500/10 hover:text-orange-400 hover:border-orange-500/30'
|
||||||
)}
|
)}
|
||||||
title="Prepare session for engineer"
|
title="Prepare session for engineer"
|
||||||
aria-label="Prepare session"
|
aria-label="Prepare session"
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ export function InlineVariablePrompt({
|
|||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-sm font-medium transition-all',
|
'inline-flex items-center gap-1.5 rounded-md border px-2.5 py-1 text-sm font-medium transition-all',
|
||||||
'border-cyan-500/40 bg-cyan-500/5 text-cyan-400',
|
'border-orange-500/40 bg-orange-500/5 text-orange-400',
|
||||||
'hover:border-cyan-400/60 hover:bg-cyan-500/10 hover:shadow-[0_0_12px_rgba(6,182,212,0.15)]',
|
'hover:border-orange-400/60 hover:bg-orange-500/10 hover:shadow-[0_0_12px_rgba(249,115,22,0.15)]',
|
||||||
'disabled:opacity-50 disabled:cursor-not-allowed',
|
'disabled:opacity-50 disabled:cursor-not-allowed',
|
||||||
isRequired && 'ring-1 ring-cyan-500/20'
|
isRequired && 'ring-1 ring-orange-500/20'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Variable className="h-3.5 w-3.5" />
|
<Variable className="h-3.5 w-3.5" />
|
||||||
@@ -88,7 +88,7 @@ export function InlineVariablePrompt({
|
|||||||
onBlur={() => {
|
onBlur={() => {
|
||||||
if (!value) setIsEditing(false)
|
if (!value) setIsEditing(false)
|
||||||
}}
|
}}
|
||||||
className="rounded-md border border-cyan-500/40 bg-cyan-500/5 px-2.5 py-1 text-sm text-foreground shadow-[0_0_12px_rgba(6,182,212,0.15)] focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
|
className="rounded-md border border-orange-500/40 bg-orange-500/5 px-2.5 py-1 text-sm text-foreground shadow-[0_0_12px_rgba(249,115,22,0.15)] focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
|
||||||
>
|
>
|
||||||
<option value="">{placeholder}</option>
|
<option value="">{placeholder}</option>
|
||||||
{options.map((opt) => (
|
{options.map((opt) => (
|
||||||
@@ -117,7 +117,7 @@ export function InlineVariablePrompt({
|
|||||||
onBlur={handleSubmit}
|
onBlur={handleSubmit}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
className="w-48 rounded-md border border-cyan-500/40 bg-cyan-500/5 px-2.5 py-1 text-sm text-foreground shadow-[0_0_12px_rgba(6,182,212,0.15)] placeholder:text-muted-foreground focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
|
className="w-48 rounded-md border border-orange-500/40 bg-orange-500/5 px-2.5 py-1 text-sm text-foreground shadow-[0_0_12px_rgba(249,115,22,0.15)] placeholder:text-muted-foreground focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
|
||||||
/>
|
/>
|
||||||
{helpText && (
|
{helpText && (
|
||||||
<span className="absolute -bottom-5 left-0 text-[0.625rem] text-muted-foreground whitespace-nowrap">
|
<span className="absolute -bottom-5 left-0 text-[0.625rem] text-muted-foreground whitespace-nowrap">
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ export function PrepareSessionModal({
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between border-b border-border px-5 py-4">
|
<div className="flex items-center justify-between border-b border-border px-5 py-4">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<FileText className="h-4 w-4 text-cyan-400" />
|
<FileText className="h-4 w-4 text-orange-400" />
|
||||||
<h3 className="text-sm font-semibold text-foreground">Prepare Session</h3>
|
<h3 className="text-sm font-semibold text-foreground">Prepare Session</h3>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
@@ -122,7 +122,7 @@ export function PrepareSessionModal({
|
|||||||
value={ticketNumber}
|
value={ticketNumber}
|
||||||
onChange={(e) => setTicketNumber(e.target.value)}
|
onChange={(e) => setTicketNumber(e.target.value)}
|
||||||
placeholder="e.g. TKT-12345"
|
placeholder="e.g. TKT-12345"
|
||||||
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -132,7 +132,7 @@ export function PrepareSessionModal({
|
|||||||
value={clientName}
|
value={clientName}
|
||||||
onChange={(e) => setClientName(e.target.value)}
|
onChange={(e) => setClientName(e.target.value)}
|
||||||
placeholder="e.g. Acme Corp"
|
placeholder="e.g. Acme Corp"
|
||||||
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -147,7 +147,7 @@ export function PrepareSessionModal({
|
|||||||
<select
|
<select
|
||||||
value={assignedToId}
|
value={assignedToId}
|
||||||
onChange={(e) => setAssignedToId(e.target.value)}
|
onChange={(e) => setAssignedToId(e.target.value)}
|
||||||
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
||||||
>
|
>
|
||||||
<option value="">Unassigned (visible to all)</option>
|
<option value="">Unassigned (visible to all)</option>
|
||||||
{teamMembers.map(m => (
|
{teamMembers.map(m => (
|
||||||
@@ -178,7 +178,7 @@ export function PrepareSessionModal({
|
|||||||
<select
|
<select
|
||||||
value={values[field.variable_name] || ''}
|
value={values[field.variable_name] || ''}
|
||||||
onChange={(e) => handleFieldChange(field.variable_name, e.target.value)}
|
onChange={(e) => handleFieldChange(field.variable_name, e.target.value)}
|
||||||
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
||||||
>
|
>
|
||||||
<option value="">{field.placeholder || 'Select...'}</option>
|
<option value="">{field.placeholder || 'Select...'}</option>
|
||||||
{field.options.map(opt => (
|
{field.options.map(opt => (
|
||||||
@@ -191,7 +191,7 @@ export function PrepareSessionModal({
|
|||||||
onChange={(e) => handleFieldChange(field.variable_name, e.target.value)}
|
onChange={(e) => handleFieldChange(field.variable_name, e.target.value)}
|
||||||
placeholder={field.placeholder}
|
placeholder={field.placeholder}
|
||||||
rows={3}
|
rows={3}
|
||||||
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<input
|
<input
|
||||||
@@ -199,7 +199,7 @@ export function PrepareSessionModal({
|
|||||||
value={values[field.variable_name] || ''}
|
value={values[field.variable_name] || ''}
|
||||||
onChange={(e) => handleFieldChange(field.variable_name, e.target.value)}
|
onChange={(e) => handleFieldChange(field.variable_name, e.target.value)}
|
||||||
placeholder={field.placeholder}
|
placeholder={field.placeholder}
|
||||||
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
className="w-full rounded-md border border-border bg-card px-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{field.help_text && (
|
{field.help_text && (
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ export function SaveToLibraryDialog({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full rounded-lg px-3 py-2 text-sm",
|
"w-full rounded-lg px-3 py-2 text-sm",
|
||||||
"border border-border bg-card text-foreground placeholder:text-muted-foreground",
|
"border border-border bg-card text-foreground placeholder:text-muted-foreground",
|
||||||
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
|
"focus:outline-none focus:border-[rgba(249,115,22,0.3)] transition-colors"
|
||||||
)}
|
)}
|
||||||
placeholder="Script name"
|
placeholder="Script name"
|
||||||
/>
|
/>
|
||||||
@@ -111,7 +111,7 @@ export function SaveToLibraryDialog({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full rounded-lg px-3 py-2 text-sm resize-none",
|
"w-full rounded-lg px-3 py-2 text-sm resize-none",
|
||||||
"border border-border bg-card text-foreground placeholder:text-muted-foreground",
|
"border border-border bg-card text-foreground placeholder:text-muted-foreground",
|
||||||
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
|
"focus:outline-none focus:border-[rgba(249,115,22,0.3)] transition-colors"
|
||||||
)}
|
)}
|
||||||
placeholder="What does this script do?"
|
placeholder="What does this script do?"
|
||||||
/>
|
/>
|
||||||
@@ -128,7 +128,7 @@ export function SaveToLibraryDialog({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"w-full rounded-lg px-3 py-2 text-sm",
|
"w-full rounded-lg px-3 py-2 text-sm",
|
||||||
"border border-border bg-card text-foreground",
|
"border border-border bg-card text-foreground",
|
||||||
"focus:outline-none focus:border-[rgba(6,182,212,0.3)] transition-colors"
|
"focus:outline-none focus:border-[rgba(249,115,22,0.3)] transition-colors"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<option value="">No category</option>
|
<option value="">No category</option>
|
||||||
@@ -144,7 +144,7 @@ export function SaveToLibraryDialog({
|
|||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={shareWithTeam}
|
checked={shareWithTeam}
|
||||||
onChange={(e) => setShareWithTeam(e.target.checked)}
|
onChange={(e) => setShareWithTeam(e.target.checked)}
|
||||||
className="w-4 h-4 rounded border-border bg-card text-cyan-500 focus:ring-cyan-500/20"
|
className="w-4 h-4 rounded border-border bg-card text-orange-500 focus:ring-orange-500/20"
|
||||||
/>
|
/>
|
||||||
<span className="text-sm text-foreground">Share with team</span>
|
<span className="text-sm text-foreground">Share with team</span>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -56,8 +56,8 @@ export function ScriptBuilderChat({
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{msg.role === 'assistant' && (
|
{msg.role === 'assistant' && (
|
||||||
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(6,182,212,0.1)] flex items-center justify-center mt-0.5">
|
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(249,115,22,0.1)] flex items-center justify-center mt-0.5">
|
||||||
<Bot size={16} className="text-cyan-400" />
|
<Bot size={16} className="text-orange-400" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ export function ScriptBuilderChat({
|
|||||||
className={cn(
|
className={cn(
|
||||||
"max-w-[85%] rounded-xl px-4 py-3 text-sm",
|
"max-w-[85%] rounded-xl px-4 py-3 text-sm",
|
||||||
msg.role === 'user'
|
msg.role === 'user'
|
||||||
? "bg-[rgba(6,182,212,0.08)] border border-[rgba(6,182,212,0.15)] text-foreground"
|
? "bg-[rgba(249,115,22,0.08)] border border-[rgba(249,115,22,0.15)] text-foreground"
|
||||||
: "card-flat"
|
: "card-flat"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -98,11 +98,11 @@ export function ScriptBuilderChat({
|
|||||||
|
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<div className="flex gap-3 justify-start">
|
<div className="flex gap-3 justify-start">
|
||||||
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(6,182,212,0.1)] flex items-center justify-center">
|
<div className="shrink-0 w-8 h-8 rounded-lg bg-[rgba(249,115,22,0.1)] flex items-center justify-center">
|
||||||
<Bot size={16} className="text-cyan-400" />
|
<Bot size={16} className="text-orange-400" />
|
||||||
</div>
|
</div>
|
||||||
<div className="card-flat rounded-xl px-4 py-3 text-sm flex items-center gap-2">
|
<div className="card-flat rounded-xl px-4 py-3 text-sm flex items-center gap-2">
|
||||||
<Loader2 size={14} className="animate-spin text-cyan-400" />
|
<Loader2 size={14} className="animate-spin text-orange-400" />
|
||||||
<span className="text-muted-foreground">Generating script...</span>
|
<span className="text-muted-foreground">Generating script...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export function ScriptCodeBlock({
|
|||||||
<div className="mt-3 rounded-lg border bg-[rgba(0,0,0,0.3)] border-[rgba(255,255,255,0.06)] overflow-hidden">
|
<div className="mt-3 rounded-lg border bg-[rgba(0,0,0,0.3)] border-[rgba(255,255,255,0.06)] overflow-hidden">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between px-3 py-2 border-b border-[rgba(255,255,255,0.06)]">
|
<div className="flex items-center justify-between px-3 py-2 border-b border-[rgba(255,255,255,0.06)]">
|
||||||
<span className="font-mono text-xs text-cyan-400 truncate">
|
<span className="font-mono text-xs text-orange-400 truncate">
|
||||||
{filename || 'script'}
|
{filename || 'script'}
|
||||||
</span>
|
</span>
|
||||||
{lineCount != null && (
|
{lineCount != null && (
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export function ScriptPreviewModal({
|
|||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]">
|
<div className="flex items-center justify-between px-5 py-3.5 border-b border-[rgba(255,255,255,0.06)]">
|
||||||
<div className="flex items-center gap-3 min-w-0">
|
<div className="flex items-center gap-3 min-w-0">
|
||||||
<span className="font-mono text-sm text-cyan-400 truncate">
|
<span className="font-mono text-sm text-orange-400 truncate">
|
||||||
{filename || 'script'}
|
{filename || 'script'}
|
||||||
</span>
|
</span>
|
||||||
<span className="shrink-0 font-mono text-[0.625rem] uppercase tracking-wider px-2 py-0.5 rounded-full bg-[rgba(255,255,255,0.06)] text-muted-foreground">
|
<span className="shrink-0 font-mono text-[0.625rem] uppercase tracking-wider px-2 py-0.5 rounded-full bg-[rgba(255,255,255,0.06)] text-muted-foreground">
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export function TicketContextPanel({ context, loading, error, onRefresh }: Ticke
|
|||||||
return (
|
return (
|
||||||
<div className="card-flat overflow-hidden rounded-lg">
|
<div className="card-flat overflow-hidden rounded-lg">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center gap-2 bg-[rgba(34,211,238,0.05)] px-3 py-2.5">
|
<div className="flex items-center gap-2 bg-[rgba(249,115,22,0.05)] px-3 py-2.5">
|
||||||
<Ticket className="h-3.5 w-3.5 text-primary" />
|
<Ticket className="h-3.5 w-3.5 text-primary" />
|
||||||
<span className="flex-1 font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-primary">
|
<span className="flex-1 font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-primary">
|
||||||
Ticket Context
|
Ticket Context
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export function TicketLinkIndicator({ session, hasConnection, onLinkClick, onUnl
|
|||||||
// Ticket linked
|
// Ticket linked
|
||||||
return (
|
return (
|
||||||
<div className="card-flat inline-flex items-start gap-2.5 rounded-lg border border-border px-3 py-2">
|
<div className="card-flat inline-flex items-start gap-2.5 rounded-lg border border-border px-3 py-2">
|
||||||
<Ticket className="mt-0.5 h-4 w-4 shrink-0 text-cyan-400" />
|
<Ticket className="mt-0.5 h-4 w-4 shrink-0 text-orange-400" />
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<p className="text-sm font-medium text-foreground">
|
<p className="text-sm font-medium text-foreground">
|
||||||
CW #{session.psa_ticket_id}
|
CW #{session.psa_ticket_id}
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ export function UpdateTicketModal({ open, onClose, sessionId, onPosted }: Props)
|
|||||||
value={opt.value}
|
value={opt.value}
|
||||||
checked={noteType === opt.value}
|
checked={noteType === opt.value}
|
||||||
onChange={() => setNoteType(opt.value)}
|
onChange={() => setNoteType(opt.value)}
|
||||||
className="mt-0.5 accent-cyan-400"
|
className="mt-0.5 accent-orange-400"
|
||||||
/>
|
/>
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
<span className="text-sm font-medium text-foreground">{opt.label}</span>
|
<span className="text-sm font-medium text-foreground">{opt.label}</span>
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ export function SidebarStatsBar({ resolved, active, completedMinutes, activeSess
|
|||||||
<div className="flex-1 rounded-md bg-[rgba(255,255,255,0.02)] px-1 py-1.5 text-center">
|
<div className="flex-1 rounded-md bg-[rgba(255,255,255,0.02)] px-1 py-1.5 text-center">
|
||||||
<div
|
<div
|
||||||
className="font-mono text-sm font-semibold leading-none"
|
className="font-mono text-sm font-semibold leading-none"
|
||||||
style={{ color: '#22d3ee' }}
|
style={{ color: '#f97316' }}
|
||||||
aria-label={`${active} active sessions`}
|
aria-label={`${active} active sessions`}
|
||||||
>
|
>
|
||||||
{active}
|
{active}
|
||||||
|
|||||||
@@ -54,14 +54,14 @@ export function GlowEdgeDefs() {
|
|||||||
|
|
||||||
{/* Downstream: cyan brand */}
|
{/* Downstream: cyan brand */}
|
||||||
<linearGradient id="edge-gradient-downstream" x1="0%" y1="0%" x2="0%" y2="100%">
|
<linearGradient id="edge-gradient-downstream" x1="0%" y1="0%" x2="0%" y2="100%">
|
||||||
<stop offset="0%" stopColor="#06b6d4" />
|
<stop offset="0%" stopColor="#ea580c" />
|
||||||
<stop offset="100%" stopColor="#22d3ee" />
|
<stop offset="100%" stopColor="#f97316" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
|
|
||||||
{/* Upstream: amber */}
|
{/* Upstream: amber */}
|
||||||
<linearGradient id="edge-gradient-upstream" x1="0%" y1="100%" x2="0%" y2="0%">
|
<linearGradient id="edge-gradient-upstream" x1="0%" y1="100%" x2="0%" y2="0%">
|
||||||
<stop offset="0%" stopColor="#f59e0b" />
|
<stop offset="0%" stopColor="#f59e0b" />
|
||||||
<stop offset="100%" stopColor="#fbbf24" />
|
<stop offset="100%" stopColor="#eab308" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
|
|
||||||
{/* Glow filters */}
|
{/* Glow filters */}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ export const CATEGORY_COLORS = [
|
|||||||
'#f59e0b', // amber
|
'#f59e0b', // amber
|
||||||
'#ef4444', // red
|
'#ef4444', // red
|
||||||
'#8b5cf6', // violet
|
'#8b5cf6', // violet
|
||||||
'#06b6d4', // cyan
|
'#ea580c', // cyan
|
||||||
'#ec4899', // pink
|
'#ec4899', // pink
|
||||||
'#f97316', // orange
|
'#f97316', // orange
|
||||||
'#14b8a6', // teal
|
'#14b8a6', // teal
|
||||||
|
|||||||
@@ -28,17 +28,17 @@
|
|||||||
--color-border-default: #2e3240;
|
--color-border-default: #2e3240;
|
||||||
--color-border-hover: #3d4252;
|
--color-border-hover: #3d4252;
|
||||||
|
|
||||||
/* ── Accent (cyan) ─────────────────────────────── */
|
/* ── Accent (ember orange) ─────────────────────── */
|
||||||
--color-accent: #22d3ee;
|
--color-accent: #f97316;
|
||||||
--color-accent-hover: #06b6d4;
|
--color-accent-hover: #ea580c;
|
||||||
--color-accent-dim: rgba(34,211,238,0.10);
|
--color-accent-dim: rgba(249,115,22,0.10);
|
||||||
--color-accent-text: #67e8f9;
|
--color-accent-text: #fdba74;
|
||||||
|
|
||||||
/* ── Semantic colors ───────────────────────────── */
|
/* ── Semantic colors ───────────────────────────── */
|
||||||
--color-success: #34d399;
|
--color-success: #34d399;
|
||||||
--color-success-dim: rgba(52,211,153,0.10);
|
--color-success-dim: rgba(52,211,153,0.10);
|
||||||
--color-warning: #fbbf24;
|
--color-warning: #eab308;
|
||||||
--color-warning-dim: rgba(251,191,36,0.10);
|
--color-warning-dim: rgba(234,179,8,0.10);
|
||||||
--color-danger: #f87171;
|
--color-danger: #f87171;
|
||||||
--color-danger-dim: rgba(248,113,113,0.10);
|
--color-danger-dim: rgba(248,113,113,0.10);
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
--color-card-foreground: #e2e5eb;
|
--color-card-foreground: #e2e5eb;
|
||||||
--color-popover: #22252e;
|
--color-popover: #22252e;
|
||||||
--color-popover-foreground: #e2e5eb;
|
--color-popover-foreground: #e2e5eb;
|
||||||
--color-primary: #22d3ee;
|
--color-primary: #f97316;
|
||||||
--color-primary-foreground: #ffffff;
|
--color-primary-foreground: #ffffff;
|
||||||
--color-secondary: #2e3140;
|
--color-secondary: #2e3140;
|
||||||
--color-secondary-foreground: #e2e5eb;
|
--color-secondary-foreground: #e2e5eb;
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
--color-destructive-foreground: #ffffff;
|
--color-destructive-foreground: #ffffff;
|
||||||
--color-border: #2e3240;
|
--color-border: #2e3240;
|
||||||
--color-input: #282b35;
|
--color-input: #282b35;
|
||||||
--color-ring: #22d3ee;
|
--color-ring: #f97316;
|
||||||
|
|
||||||
/* ── Radii ─────────────────────────────────────── */
|
/* ── Radii ─────────────────────────────────────── */
|
||||||
--radius-sm: 5px;
|
--radius-sm: 5px;
|
||||||
@@ -191,11 +191,11 @@
|
|||||||
transition: filter 150ms ease, box-shadow 150ms ease, transform 150ms ease;
|
transition: filter 150ms ease, box-shadow 150ms ease, transform 150ms ease;
|
||||||
&:hover {
|
&:hover {
|
||||||
filter: brightness(1.1);
|
filter: brightness(1.1);
|
||||||
box-shadow: 0 2px 10px rgba(34, 211, 238, 0.2);
|
box-shadow: 0 2px 10px rgba(249, 115, 22, 0.2);
|
||||||
transform: translateY(-1px);
|
transform: translateY(-1px);
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
box-shadow: 0 0 4px rgba(34, 211, 238, 0.1);
|
box-shadow: 0 0 4px rgba(249, 115, 22, 0.1);
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,12 +221,12 @@
|
|||||||
|
|
||||||
/* ── Interactive shadow patterns (dark-mode aware) ── */
|
/* ── Interactive shadow patterns (dark-mode aware) ── */
|
||||||
/* On dark backgrounds, use brighter surfaces + faint accent glow
|
/* On dark backgrounds, use brighter surfaces + faint accent glow
|
||||||
instead of black shadows (which are invisible on #0c0d10) */
|
instead of black shadows (which are invisible on #1a1c23) */
|
||||||
|
|
||||||
/* Tab/toggle group: active item gets elevated surface + faint accent glow */
|
/* Tab/toggle group: active item gets elevated surface + faint accent glow */
|
||||||
@utility tab-active-shadow {
|
@utility tab-active-shadow {
|
||||||
background: var(--color-bg-elevated);
|
background: var(--color-bg-elevated);
|
||||||
box-shadow: 0 1px 4px rgba(34, 211, 238, 0.08);
|
box-shadow: 0 1px 4px rgba(249, 115, 22, 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Card hover lift — brighter border + subtle accent glow */
|
/* Card hover lift — brighter border + subtle accent glow */
|
||||||
@@ -234,7 +234,7 @@
|
|||||||
transition: box-shadow 200ms ease, transform 200ms ease, border-color 200ms ease;
|
transition: box-shadow 200ms ease, transform 200ms ease, border-color 200ms ease;
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: var(--color-border-hover);
|
border-color: var(--color-border-hover);
|
||||||
box-shadow: 0 2px 8px rgba(34, 211, 238, 0.06);
|
box-shadow: 0 2px 8px rgba(249, 115, 22, 0.06);
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ export default function FlowPilotAnalyticsPage() {
|
|||||||
icon={BarChart3}
|
icon={BarChart3}
|
||||||
label="Total Sessions"
|
label="Total Sessions"
|
||||||
value={dashboard.total_sessions}
|
value={dashboard.total_sessions}
|
||||||
iconColor="#22d3ee"
|
iconColor="#f97316"
|
||||||
/>
|
/>
|
||||||
<MetricCard
|
<MetricCard
|
||||||
icon={CheckCircle2}
|
icon={CheckCircle2}
|
||||||
@@ -233,7 +233,7 @@ export default function FlowPilotAnalyticsPage() {
|
|||||||
icon={Star}
|
icon={Star}
|
||||||
label="Avg Rating"
|
label="Avg Rating"
|
||||||
value={dashboard.avg_rating ? `${dashboard.avg_rating.toFixed(1)}/5` : '—'}
|
value={dashboard.avg_rating ? `${dashboard.avg_rating.toFixed(1)}/5` : '—'}
|
||||||
iconColor="#fbbf24"
|
iconColor="#eab308"
|
||||||
/>
|
/>
|
||||||
<MetricCard
|
<MetricCard
|
||||||
icon={Ticket}
|
icon={Ticket}
|
||||||
@@ -271,14 +271,14 @@ export default function FlowPilotAnalyticsPage() {
|
|||||||
<Area
|
<Area
|
||||||
type="monotone"
|
type="monotone"
|
||||||
dataKey="mttr_minutes"
|
dataKey="mttr_minutes"
|
||||||
stroke="#22d3ee"
|
stroke="#f97316"
|
||||||
fill="url(#mttrGradient)"
|
fill="url(#mttrGradient)"
|
||||||
strokeWidth={2}
|
strokeWidth={2}
|
||||||
/>
|
/>
|
||||||
<defs>
|
<defs>
|
||||||
<linearGradient id="mttrGradient" x1="0" y1="0" x2="0" y2="1">
|
<linearGradient id="mttrGradient" x1="0" y1="0" x2="0" y2="1">
|
||||||
<stop offset="5%" stopColor="#22d3ee" stopOpacity={0.3} />
|
<stop offset="5%" stopColor="#f97316" stopOpacity={0.3} />
|
||||||
<stop offset="95%" stopColor="#22d3ee" stopOpacity={0} />
|
<stop offset="95%" stopColor="#f97316" stopOpacity={0} />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
</AreaChart>
|
</AreaChart>
|
||||||
@@ -311,7 +311,7 @@ export default function FlowPilotAnalyticsPage() {
|
|||||||
labelStyle={{ color: '#f8fafc' }}
|
labelStyle={{ color: '#f8fafc' }}
|
||||||
/>
|
/>
|
||||||
<Bar dataKey="resolved" name="Resolved" fill="#34d399" radius={[0, 4, 4, 0]} />
|
<Bar dataKey="resolved" name="Resolved" fill="#34d399" radius={[0, 4, 4, 0]} />
|
||||||
<Bar dataKey="escalated" name="Escalated" fill="#fbbf24" radius={[0, 4, 4, 0]} />
|
<Bar dataKey="escalated" name="Escalated" fill="#eab308" radius={[0, 4, 4, 0]} />
|
||||||
</BarChart>
|
</BarChart>
|
||||||
</ResponsiveContainer>
|
</ResponsiveContainer>
|
||||||
) : (
|
) : (
|
||||||
@@ -341,7 +341,7 @@ export default function FlowPilotAnalyticsPage() {
|
|||||||
label="Exploring"
|
label="Exploring"
|
||||||
count={conf.exploring_sessions}
|
count={conf.exploring_sessions}
|
||||||
rate={conf.exploring_resolution_rate}
|
rate={conf.exploring_resolution_rate}
|
||||||
color="#fbbf24"
|
color="#eab308"
|
||||||
total={conf.guided_sessions + conf.exploring_sessions + conf.discovery_sessions}
|
total={conf.guided_sessions + conf.exploring_sessions + conf.discovery_sessions}
|
||||||
/>
|
/>
|
||||||
<ConfidenceTierRow
|
<ConfidenceTierRow
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ export default function FlowPilotSessionPage() {
|
|||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={() => blocker.reset()}
|
onClick={() => blocker.reset()}
|
||||||
className="flex-1 rounded-lg bg-gradient-to-r from-cyan-500 to-cyan-400 px-4 py-2.5 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all"
|
className="flex-1 rounded-lg bg-gradient-to-r from-orange-500 to-orange-400 px-4 py-2.5 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all"
|
||||||
>
|
>
|
||||||
Stay in Session
|
Stay in Session
|
||||||
</button>
|
</button>
|
||||||
@@ -242,7 +242,7 @@ export default function FlowPilotSessionPage() {
|
|||||||
<button
|
<button
|
||||||
onClick={() => setShowStatusUpdate(true)}
|
onClick={() => setShowStatusUpdate(true)}
|
||||||
disabled={fp.isProcessing}
|
disabled={fp.isProcessing}
|
||||||
className="flex items-center gap-1.5 rounded-lg bg-cyan-500/10 border border-cyan-500/20 px-3 py-1.5 text-xs font-medium text-cyan-400 hover:bg-cyan-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
className="flex items-center gap-1.5 rounded-lg bg-orange-500/10 border border-orange-500/20 px-3 py-1.5 text-xs font-medium text-orange-400 hover:bg-orange-500/20 disabled:opacity-40 disabled:pointer-events-none transition-colors"
|
||||||
title="Share Update"
|
title="Share Update"
|
||||||
>
|
>
|
||||||
<FileText size={13} />
|
<FileText size={13} />
|
||||||
@@ -312,7 +312,7 @@ export default function FlowPilotSessionPage() {
|
|||||||
{fp.allSteps.length >= 2 && (
|
{fp.allSteps.length >= 2 && (
|
||||||
<button
|
<button
|
||||||
onClick={() => { setShowOverflow(false); setShowStatusUpdate(true) }}
|
onClick={() => { setShowOverflow(false); setShowStatusUpdate(true) }}
|
||||||
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-cyan-400 hover:bg-cyan-500/10 transition-colors"
|
className="flex w-full items-center gap-2 px-3 py-2.5 text-xs text-orange-400 hover:bg-orange-500/10 transition-colors"
|
||||||
>
|
>
|
||||||
<FileText size={14} />
|
<FileText size={14} />
|
||||||
Share Update
|
Share Update
|
||||||
@@ -390,7 +390,7 @@ export default function FlowPilotSessionPage() {
|
|||||||
value={resolutionSummary}
|
value={resolutionSummary}
|
||||||
onChange={(e) => setResolutionSummary(e.target.value)}
|
onChange={(e) => setResolutionSummary(e.target.value)}
|
||||||
placeholder="What resolved the issue?"
|
placeholder="What resolved the issue?"
|
||||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
|
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none resize-none"
|
||||||
rows={4}
|
rows={4}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ export default function LandingPage() {
|
|||||||
<div className="landing-preview-body">
|
<div className="landing-preview-body">
|
||||||
<div className="landing-preview-sidebar">
|
<div className="landing-preview-sidebar">
|
||||||
<div className="landing-preview-sidebar-item active">
|
<div className="landing-preview-sidebar-item active">
|
||||||
<div className="dot" style={{ background: '#22d3ee' }} />
|
<div className="dot" style={{ background: '#f97316' }} />
|
||||||
FlowPilot
|
FlowPilot
|
||||||
</div>
|
</div>
|
||||||
<div className="landing-preview-sidebar-item">
|
<div className="landing-preview-sidebar-item">
|
||||||
@@ -221,15 +221,15 @@ export default function LandingPage() {
|
|||||||
<span className="text">User can't access shared drive after password reset</span>
|
<span className="text">User can't access shared drive after password reset</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="landing-mock-chat-line">
|
<div className="landing-mock-chat-line">
|
||||||
<span className="label" style={{ color: '#22d3ee' }}>FlowPilot:</span>
|
<span className="label" style={{ color: '#f97316' }}>FlowPilot:</span>
|
||||||
<span className="text">This is likely a cached credential issue. Let's check a few things:</span>
|
<span className="text">This is likely a cached credential issue. Let's check a few things:</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="landing-mock-chat-line">
|
<div className="landing-mock-chat-line">
|
||||||
<span className="label" style={{ color: '#22d3ee' }}>FlowPilot:</span>
|
<span className="label" style={{ color: '#f97316' }}>FlowPilot:</span>
|
||||||
<span className="text">1. Run <code>klist purge</code> to clear Kerberos tickets</span>
|
<span className="text">1. Run <code>klist purge</code> to clear Kerberos tickets</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="landing-mock-chat-line">
|
<div className="landing-mock-chat-line">
|
||||||
<span className="label" style={{ color: '#22d3ee' }}>FlowPilot:</span>
|
<span className="label" style={{ color: '#f97316' }}>FlowPilot:</span>
|
||||||
<span className="text">2. Open Credential Manager → remove saved entries for the share</span>
|
<span className="text">2. Open Credential Manager → remove saved entries for the share</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="landing-mock-chat-line doc">
|
<div className="landing-mock-chat-line doc">
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import type { PersonalAnalyticsResponse, AnalyticsPeriod } from '@/types'
|
|||||||
const OUTCOME_COLORS: Record<string, string> = {
|
const OUTCOME_COLORS: Record<string, string> = {
|
||||||
resolved: '#34d399',
|
resolved: '#34d399',
|
||||||
escalated: '#f87171',
|
escalated: '#f87171',
|
||||||
workaround: '#fbbf24',
|
workaround: '#eab308',
|
||||||
unresolved: '#94a3b8',
|
unresolved: '#94a3b8',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -872,7 +872,7 @@ export function ProceduralNavigationPage() {
|
|||||||
key={field.variable_name}
|
key={field.variable_name}
|
||||||
className={cn(
|
className={cn(
|
||||||
'rounded-lg border px-3 py-2.5',
|
'rounded-lg border px-3 py-2.5',
|
||||||
isFilled ? 'border-border bg-accent' : 'border-cyan-500/20 bg-cyan-500/5'
|
isFilled ? 'border-border bg-accent' : 'border-orange-500/20 bg-orange-500/5'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex items-center justify-between gap-2">
|
<div className="flex items-center justify-between gap-2">
|
||||||
@@ -880,7 +880,7 @@ export function ProceduralNavigationPage() {
|
|||||||
{isFilled ? (
|
{isFilled ? (
|
||||||
<Check className="h-3.5 w-3.5 shrink-0 text-emerald-400" />
|
<Check className="h-3.5 w-3.5 shrink-0 text-emerald-400" />
|
||||||
) : (
|
) : (
|
||||||
<AlertCircle className="h-3.5 w-3.5 shrink-0 text-cyan-400" />
|
<AlertCircle className="h-3.5 w-3.5 shrink-0 text-orange-400" />
|
||||||
)}
|
)}
|
||||||
<span className="text-xs font-medium text-muted-foreground truncate">
|
<span className="text-xs font-medium text-muted-foreground truncate">
|
||||||
{field.label}
|
{field.label}
|
||||||
@@ -903,7 +903,7 @@ export function ProceduralNavigationPage() {
|
|||||||
value={editingVarValue}
|
value={editingVarValue}
|
||||||
onChange={(e) => setEditingVarValue(e.target.value)}
|
onChange={(e) => setEditingVarValue(e.target.value)}
|
||||||
autoFocus
|
autoFocus
|
||||||
className="w-full rounded-md border border-cyan-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
|
className="w-full rounded-md border border-orange-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
|
||||||
>
|
>
|
||||||
<option value="">{field.placeholder || 'Select...'}</option>
|
<option value="">{field.placeholder || 'Select...'}</option>
|
||||||
{field.options.map((opt) => (
|
{field.options.map((opt) => (
|
||||||
@@ -917,7 +917,7 @@ export function ProceduralNavigationPage() {
|
|||||||
autoFocus
|
autoFocus
|
||||||
rows={3}
|
rows={3}
|
||||||
placeholder={field.placeholder}
|
placeholder={field.placeholder}
|
||||||
className="w-full rounded-md border border-cyan-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
|
className="w-full rounded-md border border-orange-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<input
|
<input
|
||||||
@@ -927,7 +927,7 @@ export function ProceduralNavigationPage() {
|
|||||||
onKeyDown={(e) => { if (e.key === 'Enter') saveEditingVar() }}
|
onKeyDown={(e) => { if (e.key === 'Enter') saveEditingVar() }}
|
||||||
autoFocus
|
autoFocus
|
||||||
placeholder={field.placeholder}
|
placeholder={field.placeholder}
|
||||||
className="w-full rounded-md border border-cyan-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-cyan-400 focus:outline-hidden focus:ring-1 focus:ring-cyan-400/30"
|
className="w-full rounded-md border border-orange-500/30 bg-card px-2.5 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-orange-400 focus:outline-hidden focus:ring-1 focus:ring-orange-400/30"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{field.help_text && (
|
{field.help_text && (
|
||||||
|
|||||||
@@ -329,7 +329,7 @@ export function SessionHistoryPage() {
|
|||||||
value={aiSearchInput}
|
value={aiSearchInput}
|
||||||
onChange={(e) => setAiSearchInput(e.target.value)}
|
onChange={(e) => setAiSearchInput(e.target.value)}
|
||||||
placeholder="Search sessions..."
|
placeholder="Search sessions..."
|
||||||
className="w-full rounded-lg border border-border bg-card pl-8 pr-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none"
|
className="w-full rounded-lg border border-border bg-card pl-8 pr-3 py-1.5 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -356,7 +356,7 @@ export function SessionHistoryPage() {
|
|||||||
value={aiFilters.problem_domain}
|
value={aiFilters.problem_domain}
|
||||||
onChange={(e) => setAiFilters((f) => ({ ...f, problem_domain: e.target.value }))}
|
onChange={(e) => setAiFilters((f) => ({ ...f, problem_domain: e.target.value }))}
|
||||||
title="Filter by problem domain"
|
title="Filter by problem domain"
|
||||||
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none [&>option]:bg-card [&>option]:text-foreground"
|
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none [&>option]:bg-card [&>option]:text-foreground"
|
||||||
>
|
>
|
||||||
<option value="">All domains</option>
|
<option value="">All domains</option>
|
||||||
<option value="Active Directory">Active Directory</option>
|
<option value="Active Directory">Active Directory</option>
|
||||||
@@ -396,7 +396,7 @@ export function SessionHistoryPage() {
|
|||||||
value={aiFilters.date_from}
|
value={aiFilters.date_from}
|
||||||
onChange={(e) => setAiFilters((f) => ({ ...f, date_from: e.target.value }))}
|
onChange={(e) => setAiFilters((f) => ({ ...f, date_from: e.target.value }))}
|
||||||
title="From date"
|
title="From date"
|
||||||
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none [color-scheme:dark]"
|
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none [color-scheme:dark]"
|
||||||
/>
|
/>
|
||||||
<span className="text-xs text-muted-foreground">to</span>
|
<span className="text-xs text-muted-foreground">to</span>
|
||||||
<input
|
<input
|
||||||
@@ -404,7 +404,7 @@ export function SessionHistoryPage() {
|
|||||||
value={aiFilters.date_to}
|
value={aiFilters.date_to}
|
||||||
onChange={(e) => setAiFilters((f) => ({ ...f, date_to: e.target.value }))}
|
onChange={(e) => setAiFilters((f) => ({ ...f, date_to: e.target.value }))}
|
||||||
title="To date"
|
title="To date"
|
||||||
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none [color-scheme:dark]"
|
className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none [color-scheme:dark]"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -564,7 +564,7 @@ export function SessionHistoryPage() {
|
|||||||
session.outcome === 'escalated' && 'bg-blue-500/20 text-blue-300',
|
session.outcome === 'escalated' && 'bg-blue-500/20 text-blue-300',
|
||||||
session.outcome === 'unresolved' && 'bg-rose-500/20 text-rose-300',
|
session.outcome === 'unresolved' && 'bg-rose-500/20 text-rose-300',
|
||||||
session.outcome === 'cancelled' && 'bg-zinc-500/20 text-zinc-300',
|
session.outcome === 'cancelled' && 'bg-zinc-500/20 text-zinc-300',
|
||||||
session.outcome === 'resolved_externally' && 'bg-cyan-500/20 text-cyan-300',
|
session.outcome === 'resolved_externally' && 'bg-orange-500/20 text-orange-300',
|
||||||
!session.outcome && 'bg-accent text-muted-foreground'
|
!session.outcome && 'bg-accent text-muted-foreground'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -647,7 +647,7 @@ export function SessionHistoryPage() {
|
|||||||
value={closeOutcome}
|
value={closeOutcome}
|
||||||
onChange={(e) => setCloseOutcome(e.target.value as SessionOutcome)}
|
onChange={(e) => setCloseOutcome(e.target.value as SessionOutcome)}
|
||||||
title="Session outcome"
|
title="Session outcome"
|
||||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none mb-3"
|
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none mb-3"
|
||||||
>
|
>
|
||||||
<option value="">Select outcome...</option>
|
<option value="">Select outcome...</option>
|
||||||
<option value="resolved">Resolved</option>
|
<option value="resolved">Resolved</option>
|
||||||
@@ -664,7 +664,7 @@ export function SessionHistoryPage() {
|
|||||||
onChange={(e) => setCloseNotes(e.target.value)}
|
onChange={(e) => setCloseNotes(e.target.value)}
|
||||||
rows={2}
|
rows={2}
|
||||||
placeholder="Add closure notes..."
|
placeholder="Add closure notes..."
|
||||||
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none mb-3"
|
className="w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(249,115,22,0.3)] focus:outline-none resize-none mb-3"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="flex items-center justify-end gap-2">
|
<div className="flex items-center justify-end gap-2">
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import type { TeamAnalyticsResponse, AnalyticsPeriod } from '@/types'
|
|||||||
const CHART_COLORS = {
|
const CHART_COLORS = {
|
||||||
resolved: '#34d399',
|
resolved: '#34d399',
|
||||||
escalated: '#f87171',
|
escalated: '#f87171',
|
||||||
workaround: '#fbbf24',
|
workaround: '#eab308',
|
||||||
unresolved: '#94a3b8',
|
unresolved: '#94a3b8',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ interface AccountBranding {
|
|||||||
company_name: string | null
|
company_name: string | null
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_COLOR = '#06b6d4'
|
const DEFAULT_COLOR = '#ea580c'
|
||||||
|
|
||||||
export function BrandingSettingsPage() {
|
export function BrandingSettingsPage() {
|
||||||
const [branding, setBranding] = useState<AccountBranding | null>(null)
|
const [branding, setBranding] = useState<AccountBranding | null>(null)
|
||||||
@@ -137,7 +137,7 @@ export function BrandingSettingsPage() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
'mt-1 w-full rounded-lg border border-border bg-card px-3 py-2 text-sm',
|
'mt-1 w-full rounded-lg border border-border bg-card px-3 py-2 text-sm',
|
||||||
'text-foreground placeholder:text-muted-foreground',
|
'text-foreground placeholder:text-muted-foreground',
|
||||||
'focus:border-[rgba(6,182,212,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
|
'focus:border-[rgba(249,115,22,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<p className="mt-1 text-xs text-muted-foreground">
|
<p className="mt-1 text-xs text-muted-foreground">
|
||||||
@@ -163,7 +163,7 @@ export function BrandingSettingsPage() {
|
|||||||
className={cn(
|
className={cn(
|
||||||
'mt-1 w-full rounded-lg border border-border bg-card px-3 py-2 text-sm',
|
'mt-1 w-full rounded-lg border border-border bg-card px-3 py-2 text-sm',
|
||||||
'text-foreground placeholder:text-muted-foreground font-mono',
|
'text-foreground placeholder:text-muted-foreground font-mono',
|
||||||
'focus:border-[rgba(6,182,212,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
|
'focus:border-[rgba(249,115,22,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<p className="mt-1 text-xs text-muted-foreground">
|
<p className="mt-1 text-xs text-muted-foreground">
|
||||||
@@ -207,12 +207,12 @@ export function BrandingSettingsPage() {
|
|||||||
const val = e.target.value
|
const val = e.target.value
|
||||||
setPrimaryColor(val)
|
setPrimaryColor(val)
|
||||||
}}
|
}}
|
||||||
placeholder="#06b6d4"
|
placeholder="#ea580c"
|
||||||
maxLength={7}
|
maxLength={7}
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-32 rounded-lg border border-border bg-card px-3 py-2 text-sm',
|
'w-32 rounded-lg border border-border bg-card px-3 py-2 text-sm',
|
||||||
'text-foreground placeholder:text-muted-foreground font-mono',
|
'text-foreground placeholder:text-muted-foreground font-mono',
|
||||||
'focus:border-[rgba(6,182,212,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
|
'focus:border-[rgba(249,115,22,0.3)] focus:outline-none focus:ring-1 focus:ring-primary/20'
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
@@ -224,7 +224,7 @@ export function BrandingSettingsPage() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<p className="mt-1 text-xs text-muted-foreground">
|
<p className="mt-1 text-xs text-muted-foreground">
|
||||||
Hex color code for the primary accent color (e.g. #06b6d4).
|
Hex color code for the primary accent color (e.g. #ea580c).
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
background: radial-gradient(circle at 50% 0%, rgba(34, 211, 238, 0.12) 0%, transparent 60%);
|
background: radial-gradient(circle at 50% 0%, rgba(249, 115, 22, 0.12) 0%, transparent 60%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-ambient-glow::before,
|
.landing-ambient-glow::before,
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
.landing-nav-logo-icon {
|
.landing-nav-logo-icon {
|
||||||
width: 36px;
|
width: 36px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-nav-wordmark span {
|
.landing-nav-wordmark span {
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-nav-links {
|
.landing-nav-links {
|
||||||
@@ -159,7 +159,7 @@
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.55rem 1.25rem;
|
padding: 0.55rem 1.25rem;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
transition: opacity 0.25s, transform 0.25s;
|
transition: opacity 0.25s, transform 0.25s;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
font-family: 'IBM Plex Sans', sans-serif;
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
letter-spacing: 0.03em;
|
letter-spacing: 0.03em;
|
||||||
animation: landingFadeInDown 0.8s ease-out;
|
animation: landingFadeInDown 0.8s ease-out;
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
width: 6px;
|
width: 6px;
|
||||||
height: 6px;
|
height: 6px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
animation: landingPulse 2s ease-in-out infinite;
|
animation: landingPulse 2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-gradient-text {
|
.landing-gradient-text {
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-hero-sub {
|
.landing-hero-sub {
|
||||||
@@ -256,7 +256,7 @@
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
padding: 0.85rem 2rem;
|
padding: 0.85rem 2rem;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
transition: opacity 0.3s, transform 0.3s;
|
transition: opacity 0.3s, transform 0.3s;
|
||||||
letter-spacing: -0.01em;
|
letter-spacing: -0.01em;
|
||||||
border: none;
|
border: none;
|
||||||
@@ -323,7 +323,7 @@
|
|||||||
font-family: 'Bricolage Grotesque', sans-serif;
|
font-family: 'Bricolage Grotesque', sans-serif;
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-proof-stat .label {
|
.landing-proof-stat .label {
|
||||||
@@ -378,14 +378,14 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-tab-icon {
|
.landing-tab-icon {
|
||||||
width: 14px;
|
width: 14px;
|
||||||
height: 14px;
|
height: 14px;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -482,9 +482,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-preview-sidebar-item.active {
|
.landing-preview-sidebar-item.active {
|
||||||
background: rgba(34, 211, 238, 0.08);
|
background: rgba(249, 115, 22, 0.08);
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
border-left: 3px solid #22d3ee;
|
border-left: 3px solid #f97316;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-preview-sidebar-item .dot {
|
.landing-preview-sidebar-item .dot {
|
||||||
@@ -521,7 +521,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-tree-node.root {
|
.landing-tree-node.root {
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -535,7 +535,7 @@
|
|||||||
.landing-tree-connector {
|
.landing-tree-connector {
|
||||||
width: 2px;
|
width: 2px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
background: rgba(34, 211, 238, 0.2);
|
background: rgba(249, 115, 22, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-tree-branch {
|
.landing-tree-branch {
|
||||||
@@ -552,7 +552,7 @@
|
|||||||
width: calc(100% - 100px);
|
width: calc(100% - 100px);
|
||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
height: 2px;
|
height: 2px;
|
||||||
background: rgba(34, 211, 238, 0.15);
|
background: rgba(249, 115, 22, 0.15);
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-tree-branch-arm {
|
.landing-tree-branch-arm {
|
||||||
@@ -568,7 +568,7 @@
|
|||||||
.landing-tree-label {
|
.landing-tree-label {
|
||||||
font-family: 'IBM Plex Sans', sans-serif;
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
opacity: 0.7;
|
opacity: 0.7;
|
||||||
}
|
}
|
||||||
@@ -587,7 +587,7 @@
|
|||||||
font-family: 'IBM Plex Sans', sans-serif;
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
letter-spacing: 0.12em;
|
letter-spacing: 0.12em;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
@@ -631,7 +631,7 @@
|
|||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: #22252e;
|
background: #22252e;
|
||||||
border: 1px solid #2a2f3d;
|
border: 1px solid #2e3240;
|
||||||
transition: border-color 0.3s, transform 0.3s;
|
transition: border-color 0.3s, transform 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,12 +718,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-eq-operator {
|
.landing-eq-operator {
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-eq-result {
|
.landing-eq-result {
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -749,14 +749,14 @@
|
|||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: #22252e;
|
background: #22252e;
|
||||||
border: 1px solid #2a2f3d;
|
border: 1px solid #2e3240;
|
||||||
position: relative;
|
position: relative;
|
||||||
counter-increment: landing-step;
|
counter-increment: landing-step;
|
||||||
transition: border-color 0.3s, transform 0.3s;
|
transition: border-color 0.3s, transform 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-step-card:hover {
|
.landing-step-card:hover {
|
||||||
border-color: rgba(34, 211, 238, 0.2);
|
border-color: rgba(249, 115, 22, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-step-card::before {
|
.landing-step-card::before {
|
||||||
@@ -764,7 +764,7 @@
|
|||||||
font-family: 'IBM Plex Sans', sans-serif;
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
letter-spacing: 0.05em;
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
@@ -814,9 +814,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-mock-node.start {
|
.landing-mock-node.start {
|
||||||
background: rgba(34, 211, 238, 0.15);
|
background: rgba(249, 115, 22, 0.15);
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
border: 1px solid rgba(34, 211, 238, 0.2);
|
border: 1px solid rgba(249, 115, 22, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-mock-node.step {
|
.landing-mock-node.step {
|
||||||
@@ -852,7 +852,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-mock-chat-line .label {
|
.landing-mock-chat-line .label {
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
min-width: 55px;
|
min-width: 55px;
|
||||||
}
|
}
|
||||||
@@ -879,7 +879,7 @@
|
|||||||
.landing-mock-ticket-header {
|
.landing-mock-ticket-header {
|
||||||
font-family: 'IBM Plex Sans', sans-serif;
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
padding-bottom: 0.35rem;
|
padding-bottom: 0.35rem;
|
||||||
border-bottom: 1px solid #2e3240;
|
border-bottom: 1px solid #2e3240;
|
||||||
@@ -915,12 +915,12 @@
|
|||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: #22252e;
|
background: #22252e;
|
||||||
border: 1px solid #2a2f3d;
|
border: 1px solid #2e3240;
|
||||||
transition: border-color 0.3s ease, transform 0.3s ease;
|
transition: border-color 0.3s ease, transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-feature-card:hover {
|
.landing-feature-card:hover {
|
||||||
border-color: rgba(34, 211, 238, 0.2);
|
border-color: rgba(249, 115, 22, 0.2);
|
||||||
transform: translateY(-3px);
|
transform: translateY(-3px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -928,12 +928,12 @@
|
|||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: rgba(34, 211, 238, 0.08);
|
background: rgba(249, 115, 22, 0.08);
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-bottom: 1.25rem;
|
margin-bottom: 1.25rem;
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-feature-card h3 {
|
.landing-feature-card h3 {
|
||||||
@@ -951,7 +951,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-feature-card.highlight {
|
.landing-feature-card.highlight {
|
||||||
border-color: rgba(34, 211, 238, 0.15);
|
border-color: rgba(249, 115, 22, 0.15);
|
||||||
background: #22252e;
|
background: #22252e;
|
||||||
grid-column: span 2;
|
grid-column: span 2;
|
||||||
}
|
}
|
||||||
@@ -969,7 +969,7 @@
|
|||||||
padding: 2.5rem 2rem;
|
padding: 2.5rem 2rem;
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: #22252e;
|
background: #22252e;
|
||||||
border: 1px solid #2a2f3d;
|
border: 1px solid #2e3240;
|
||||||
transition: border-color 0.3s, transform 0.3s;
|
transition: border-color 0.3s, transform 0.3s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,7 +978,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-pricing-card.featured {
|
.landing-pricing-card.featured {
|
||||||
border-color: #22d3ee;
|
border-color: #f97316;
|
||||||
background: #22252e;
|
background: #22252e;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@@ -991,7 +991,7 @@
|
|||||||
transform: translateX(-50%);
|
transform: translateX(-50%);
|
||||||
padding: 4px 14px;
|
padding: 4px 14px;
|
||||||
border-radius: 100px;
|
border-radius: 100px;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
font-family: 'IBM Plex Sans', sans-serif;
|
font-family: 'IBM Plex Sans', sans-serif;
|
||||||
font-size: 0.65rem;
|
font-size: 0.65rem;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -1029,7 +1029,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-pricing-card.featured .landing-pricing-price .amount {
|
.landing-pricing-card.featured .landing-pricing-price .amount {
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-pricing-price .period {
|
.landing-pricing-price .period {
|
||||||
@@ -1062,7 +1062,7 @@
|
|||||||
|
|
||||||
.landing-pricing-features li::before {
|
.landing-pricing-features li::before {
|
||||||
content: '\2713';
|
content: '\2713';
|
||||||
color: #22d3ee;
|
color: #f97316;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
@@ -1083,7 +1083,7 @@
|
|||||||
|
|
||||||
.landing-pricing-btn.outline {
|
.landing-pricing-btn.outline {
|
||||||
color: #e2e5eb;
|
color: #e2e5eb;
|
||||||
border: 1px solid #2a2f3d;
|
border: 1px solid #2e3240;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1094,7 +1094,7 @@
|
|||||||
|
|
||||||
.landing-pricing-btn.filled {
|
.landing-pricing-btn.filled {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
background: #22d3ee;
|
background: #f97316;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1111,7 +1111,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-pricing-enterprise a {
|
.landing-pricing-enterprise a {
|
||||||
color: #67e8f9;
|
color: #fdba74;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1142,7 +1142,7 @@
|
|||||||
.landing-testimonial-quote::before {
|
.landing-testimonial-quote::before {
|
||||||
content: '\201C';
|
content: '\201C';
|
||||||
font-size: 4rem;
|
font-size: 4rem;
|
||||||
color: #22d3ee;
|
color: #f97316;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
vertical-align: super;
|
vertical-align: super;
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
@@ -1154,7 +1154,7 @@
|
|||||||
.landing-testimonial-quote::after {
|
.landing-testimonial-quote::after {
|
||||||
content: '\201D';
|
content: '\201D';
|
||||||
font-size: 4rem;
|
font-size: 4rem;
|
||||||
color: #22d3ee;
|
color: #f97316;
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
vertical-align: sub;
|
vertical-align: sub;
|
||||||
margin-left: 1rem;
|
margin-left: 1rem;
|
||||||
@@ -1227,8 +1227,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.landing-cta-email-input:focus {
|
.landing-cta-email-input:focus {
|
||||||
border-color: #22d3ee;
|
border-color: #f97316;
|
||||||
box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.1);
|
box-shadow: 0 0 0 3px rgba(249, 115, 22, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.landing-cta-fine-print {
|
.landing-cta-fine-print {
|
||||||
|
|||||||
Reference in New Issue
Block a user