refactor: replace hardcoded hex values with Tailwind semantic tokens

3,200+ hardcoded color values replaced with CSS variable-backed
Tailwind classes (bg-card, text-foreground, border-border, etc.).
Enables light mode via CSS variable swap. Only syntax highlighting
colors and intentional one-offs remain hardcoded (~15 values).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Michael Chihlas
2026-03-22 04:34:35 -04:00
parent 123fc50af9
commit 303a558432
251 changed files with 3310 additions and 3310 deletions

View File

@@ -39,24 +39,24 @@ export function DeleteAccountModal({ onClose }: Props) {
<div className="card-flat w-full max-w-md p-6"> <div className="card-flat w-full max-w-md p-6">
<div className="flex items-center gap-2 text-rose-500 mb-4"> <div className="flex items-center gap-2 text-rose-500 mb-4">
<AlertTriangle className="h-5 w-5" /> <AlertTriangle className="h-5 w-5" />
<h2 className="text-lg font-semibold font-heading text-[#e2e5eb]">Delete Account</h2> <h2 className="text-lg font-semibold font-heading text-foreground">Delete Account</h2>
</div> </div>
<p className="text-sm text-[#848b9b] mb-4"> <p className="text-sm text-muted-foreground mb-4">
This action is <strong className="text-rose-400">permanent</strong>. Your account, data, This action is <strong className="text-rose-400">permanent</strong>. Your account, data,
and all associated flows will be permanently deleted. and all associated flows will be permanently deleted.
</p> </p>
<form onSubmit={handleDelete} className="space-y-4"> <form onSubmit={handleDelete} className="space-y-4">
<div> <div>
<label className="block text-sm font-medium text-[#e2e5eb]">Confirm Password</label> <label className="block text-sm font-medium text-foreground">Confirm Password</label>
<input <input
type="password" type="password"
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
required required
className={cn( className={cn(
'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2', 'mt-1 block w-full rounded-lg border border-border bg-card px-3 py-2',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden' 'text-foreground focus:border-primary focus:outline-hidden'
)} )}
/> />
</div> </div>
@@ -69,7 +69,7 @@ export function DeleteAccountModal({ onClose }: Props) {
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-lg px-4 py-2 text-sm font-medium', 'rounded-lg px-4 py-2 text-sm font-medium',
'bg-[#191c25] border border-[#1e2130] text-[#e2e5eb]' 'bg-input border border-border text-foreground'
)} )}
> >
Cancel Cancel

View File

@@ -34,10 +34,10 @@ export function LeaveAccountModal({ accountName, onClose }: Props) {
<div className="card-flat w-full max-w-md p-6"> <div className="card-flat w-full max-w-md p-6">
<div className="flex items-center gap-2 text-amber-400 mb-4"> <div className="flex items-center gap-2 text-amber-400 mb-4">
<AlertTriangle className="h-5 w-5" /> <AlertTriangle className="h-5 w-5" />
<h2 className="text-lg font-semibold font-heading text-[#e2e5eb]">Leave Account</h2> <h2 className="text-lg font-semibold font-heading text-foreground">Leave Account</h2>
</div> </div>
<p className="text-sm text-[#848b9b] mb-4"> <p className="text-sm text-muted-foreground mb-4">
Are you sure you want to leave <strong className="text-[#e2e5eb]">{accountName}</strong>? Are you sure you want to leave <strong className="text-foreground">{accountName}</strong>?
A new personal account will be created for you. A new personal account will be created for you.
</p> </p>
<div className="flex justify-end gap-3"> <div className="flex justify-end gap-3">
@@ -45,7 +45,7 @@ export function LeaveAccountModal({ accountName, onClose }: Props) {
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-lg px-4 py-2 text-sm font-medium', 'rounded-lg px-4 py-2 text-sm font-medium',
'bg-[#191c25] border border-[#1e2130] text-[#e2e5eb]' 'bg-input border border-border text-foreground'
)} )}
> >
Cancel Cancel

View File

@@ -173,8 +173,8 @@ export function NotificationSettings() {
{/* Section header */} {/* Section header */}
<div className="mb-6 flex items-center justify-between"> <div className="mb-6 flex items-center justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Bell className="h-6 w-6 text-[#848b9b]" /> <Bell className="h-6 w-6 text-muted-foreground" />
<h2 className="text-xl font-semibold font-heading text-[#e2e5eb]">Notifications</h2> <h2 className="text-xl font-semibold font-heading text-foreground">Notifications</h2>
</div> </div>
<div className="relative" ref={dropdownRef}> <div className="relative" ref={dropdownRef}>
@@ -182,7 +182,7 @@ export function NotificationSettings() {
onClick={() => setShowDropdown(!showDropdown)} onClick={() => setShowDropdown(!showDropdown)}
className={cn( className={cn(
'inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium', 'inline-flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground',
'hover:border-[rgba(255,255,255,0.12)] transition-all' 'hover:border-[rgba(255,255,255,0.12)] transition-all'
)} )}
> >
@@ -192,16 +192,16 @@ export function NotificationSettings() {
</button> </button>
{showDropdown && ( {showDropdown && (
<div className="absolute right-0 mt-1 z-20 w-48 rounded-xl border border-[#1e2130] bg-[#14161d] shadow-xl"> <div className="absolute right-0 mt-1 z-20 w-48 rounded-xl border border-border bg-card shadow-xl">
{(Object.entries(CHANNEL_LABELS) as [ChannelType, string][]).map(([key, label]) => { {(Object.entries(CHANNEL_LABELS) as [ChannelType, string][]).map(([key, label]) => {
const Icon = CHANNEL_ICONS[key] const Icon = CHANNEL_ICONS[key]
return ( return (
<button <button
key={key} key={key}
onClick={() => handleAddChannel(key)} onClick={() => handleAddChannel(key)}
className="flex w-full items-center gap-2.5 px-4 py-2.5 text-sm text-[#e2e5eb] hover:bg-[rgba(255,255,255,0.04)] first:rounded-t-xl last:rounded-b-xl transition-colors" className="flex w-full items-center gap-2.5 px-4 py-2.5 text-sm text-foreground hover:bg-[rgba(255,255,255,0.04)] first:rounded-t-xl last:rounded-b-xl transition-colors"
> >
<Icon className="h-4 w-4 text-[#848b9b]" /> <Icon className="h-4 w-4 text-muted-foreground" />
{label} {label}
</button> </button>
) )
@@ -214,15 +214,15 @@ export function NotificationSettings() {
{/* Loading */} {/* Loading */}
{loading && ( {loading && (
<div className="flex justify-center py-8"> <div className="flex justify-center py-8">
<Loader2 className="h-6 w-6 animate-spin text-[#848b9b]" /> <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
</div> </div>
)} )}
{/* Empty state */} {/* Empty state */}
{!loading && configs.length === 0 && !addingChannel && ( {!loading && configs.length === 0 && !addingChannel && (
<div className="card-flat p-6 text-center"> <div className="card-flat p-6 text-center">
<Bell className="mx-auto h-8 w-8 text-[#848b9b]/50 mb-3" /> <Bell className="mx-auto h-8 w-8 text-muted-foreground/50 mb-3" />
<p className="text-sm text-[#848b9b]"> <p className="text-sm text-muted-foreground">
No notification channels configured. Add a channel to receive alerts for session events. No notification channels configured. Add a channel to receive alerts for session events.
</p> </p>
</div> </div>
@@ -237,8 +237,8 @@ export function NotificationSettings() {
<div key={config.id} className="card-flat p-5"> <div key={config.id} className="card-flat p-5">
{/* Header row */} {/* Header row */}
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center gap-3 mb-4">
<Icon className="h-5 w-5 text-[#848b9b]" /> <Icon className="h-5 w-5 text-muted-foreground" />
<span className="text-sm font-medium text-[#e2e5eb]"> <span className="text-sm font-medium text-foreground">
{CHANNEL_LABELS[config.channel]} {CHANNEL_LABELS[config.channel]}
</span> </span>
<span <span
@@ -249,7 +249,7 @@ export function NotificationSettings() {
/> />
<span className={cn( <span className={cn(
'text-xs font-sans text-xs', 'text-xs font-sans text-xs',
config.is_active ? 'text-emerald-400' : 'text-[#848b9b]' config.is_active ? 'text-emerald-400' : 'text-muted-foreground'
)}> )}>
{config.is_active ? 'Active' : 'Inactive'} {config.is_active ? 'Active' : 'Inactive'}
</span> </span>
@@ -259,20 +259,20 @@ export function NotificationSettings() {
<div className="mb-4"> <div className="mb-4">
{config.webhook_url && ( {config.webhook_url && (
<div> <div>
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Webhook URL Webhook URL
</span> </span>
<p className="mt-0.5 text-sm text-[#e2e5eb] font-mono"> <p className="mt-0.5 text-sm text-foreground font-mono">
{maskWebhookUrl(config.webhook_url)} {maskWebhookUrl(config.webhook_url)}
</p> </p>
</div> </div>
)} )}
{config.email_addresses && config.email_addresses.length > 0 && ( {config.email_addresses && config.email_addresses.length > 0 && (
<div> <div>
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Email Addresses Email Addresses
</span> </span>
<p className="mt-0.5 text-sm text-[#e2e5eb]"> <p className="mt-0.5 text-sm text-foreground">
{config.email_addresses.join(', ')} {config.email_addresses.join(', ')}
</p> </p>
</div> </div>
@@ -281,7 +281,7 @@ export function NotificationSettings() {
{/* Event toggles */} {/* Event toggles */}
<div className="mb-4"> <div className="mb-4">
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Events Events
</span> </span>
<div className="mt-2 grid gap-2 sm:grid-cols-2"> <div className="mt-2 grid gap-2 sm:grid-cols-2">
@@ -294,28 +294,28 @@ 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-[#1e2130] bg-[#14161d] 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-[#06b6d4]"
/> />
<span className="text-sm text-[#e2e5eb]">{eventLabel}</span> <span className="text-sm text-foreground">{eventLabel}</span>
</label> </label>
))} ))}
</div> </div>
</div> </div>
{/* Action buttons */} {/* Action buttons */}
<div className="flex items-center gap-3 pt-2 border-t border-[#1e2130]"> <div className="flex items-center gap-3 pt-2 border-t border-border">
<button <button
onClick={() => handleToggleActive(config)} onClick={() => handleToggleActive(config)}
className={cn( className={cn(
'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium', 'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground',
'hover:border-[rgba(255,255,255,0.12)] transition-all' 'hover:border-[rgba(255,255,255,0.12)] transition-all'
)} )}
> >
{config.is_active ? ( {config.is_active ? (
<ToggleRight className="h-4 w-4 text-emerald-400" /> <ToggleRight className="h-4 w-4 text-emerald-400" />
) : ( ) : (
<ToggleLeft className="h-4 w-4 text-[#848b9b]" /> <ToggleLeft className="h-4 w-4 text-muted-foreground" />
)} )}
{config.is_active ? 'Disable' : 'Enable'} {config.is_active ? 'Disable' : 'Enable'}
</button> </button>
@@ -325,7 +325,7 @@ export function NotificationSettings() {
disabled={testingId === config.id} disabled={testingId === config.id}
className={cn( className={cn(
'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium', 'inline-flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-sm font-medium',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground',
'hover:border-[rgba(255,255,255,0.12)] transition-all', 'hover:border-[rgba(255,255,255,0.12)] transition-all',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}
@@ -349,7 +349,7 @@ export function NotificationSettings() {
) : ( ) : (
<button <button
onClick={() => setConfirmDeleteId(config.id)} onClick={() => setConfirmDeleteId(config.id)}
className="ml-auto inline-flex items-center gap-1.5 text-sm text-[#848b9b] hover:text-red-400 transition-colors" className="ml-auto inline-flex items-center gap-1.5 text-sm text-muted-foreground hover:text-red-400 transition-colors"
> >
<Trash2 className="h-4 w-4" /> <Trash2 className="h-4 w-4" />
Remove Remove
@@ -366,16 +366,16 @@ export function NotificationSettings() {
<div className="flex items-center gap-3 mb-4"> <div className="flex items-center gap-3 mb-4">
{(() => { {(() => {
const Icon = CHANNEL_ICONS[addingChannel] const Icon = CHANNEL_ICONS[addingChannel]
return <Icon className="h-5 w-5 text-[#848b9b]" /> return <Icon className="h-5 w-5 text-muted-foreground" />
})()} })()}
<span className="text-sm font-medium text-[#e2e5eb]"> <span className="text-sm font-medium text-foreground">
Add {CHANNEL_LABELS[addingChannel]} Add {CHANNEL_LABELS[addingChannel]}
</span> </span>
</div> </div>
{addingChannel === 'email' ? ( {addingChannel === 'email' ? (
<div> <div>
<label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Email Addresses Email Addresses
</label> </label>
<Input <Input
@@ -385,13 +385,13 @@ export function NotificationSettings() {
placeholder="user@example.com, team@example.com" placeholder="user@example.com, team@example.com"
className="mt-1" className="mt-1"
/> />
<p className="mt-1 text-xs text-[#848b9b]"> <p className="mt-1 text-xs text-muted-foreground">
Separate multiple addresses with commas Separate multiple addresses with commas
</p> </p>
</div> </div>
) : ( ) : (
<div> <div>
<label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Webhook URL Webhook URL
</label> </label>
<Input <Input
@@ -414,7 +414,7 @@ export function NotificationSettings() {
disabled={isSaving} disabled={isSaving}
className={cn( className={cn(
'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold', 'inline-flex items-center gap-2 rounded-lg px-5 py-2.5 text-sm font-semibold',
'bg-[#22d3ee] text-white', 'bg-primary text-white',
'hover:brightness-110 active:scale-[0.98] transition-all', 'hover:brightness-110 active:scale-[0.98] transition-all',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}
@@ -424,7 +424,7 @@ export function NotificationSettings() {
</button> </button>
<button <button
onClick={() => setAddingChannel(null)} onClick={() => setAddingChannel(null)}
className="text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="text-sm text-muted-foreground hover:text-foreground transition-colors"
> >
Cancel Cancel
</button> </button>

View File

@@ -43,24 +43,24 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
<div className="card-flat w-full max-w-md p-6"> <div className="card-flat w-full max-w-md p-6">
<div className="flex items-center gap-2 text-amber-400 mb-4"> <div className="flex items-center gap-2 text-amber-400 mb-4">
<AlertTriangle className="h-5 w-5" /> <AlertTriangle className="h-5 w-5" />
<h2 className="text-lg font-semibold font-heading text-[#e2e5eb]">Transfer Ownership</h2> <h2 className="text-lg font-semibold font-heading text-foreground">Transfer Ownership</h2>
</div> </div>
<p className="text-sm text-[#848b9b] mb-4"> <p className="text-sm text-muted-foreground mb-4">
This will make the selected member the new account owner. You will become an engineer. This will make the selected member the new account owner. You will become an engineer.
</p> </p>
{nonOwnerMembers.length === 0 ? ( {nonOwnerMembers.length === 0 ? (
<p className="text-sm text-[#848b9b]">No other members to transfer to.</p> <p className="text-sm text-muted-foreground">No other members to transfer to.</p>
) : ( ) : (
<form onSubmit={handleSubmit} className="space-y-4"> <form onSubmit={handleSubmit} className="space-y-4">
<div> <div>
<label className="block text-sm font-medium text-[#e2e5eb]">New Owner</label> <label className="block text-sm font-medium text-foreground">New Owner</label>
<select <select
value={targetUserId} value={targetUserId}
onChange={(e) => setTargetUserId(e.target.value)} onChange={(e) => setTargetUserId(e.target.value)}
className={cn( className={cn(
'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2', 'mt-1 block w-full rounded-lg border border-border bg-card px-3 py-2',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden' 'text-foreground focus:border-primary focus:outline-hidden'
)} )}
> >
{nonOwnerMembers.map((m) => ( {nonOwnerMembers.map((m) => (
@@ -69,15 +69,15 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
</select> </select>
</div> </div>
<div> <div>
<label className="block text-sm font-medium text-[#e2e5eb]">Your Password</label> <label className="block text-sm font-medium text-foreground">Your Password</label>
<input <input
type="password" type="password"
value={password} value={password}
onChange={(e) => setPassword(e.target.value)} onChange={(e) => setPassword(e.target.value)}
required required
className={cn( className={cn(
'mt-1 block w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2', 'mt-1 block w-full rounded-lg border border-border bg-card px-3 py-2',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden' 'text-foreground focus:border-primary focus:outline-hidden'
)} )}
/> />
</div> </div>
@@ -90,7 +90,7 @@ export function TransferOwnershipModal({ members, onClose, onTransferred }: Prop
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-lg px-4 py-2 text-sm font-medium', 'rounded-lg px-4 py-2 text-sm font-medium',
'bg-[#191c25] border border-[#1e2130] text-[#e2e5eb]' 'bg-input border border-border text-foreground'
)} )}
> >
Cancel Cancel

View File

@@ -53,8 +53,8 @@ export function ActionMenu({ items }: ActionMenuProps) {
ref={buttonRef} ref={buttonRef}
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
className={cn( className={cn(
'rounded-md p-1.5 text-[#848b9b] transition-colors', 'rounded-md p-1.5 text-muted-foreground transition-colors',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
> >
<MoreHorizontal className="h-4 w-4" /> <MoreHorizontal className="h-4 w-4" />
@@ -63,8 +63,8 @@ export function ActionMenu({ items }: ActionMenuProps) {
<div <div
ref={menuRef} ref={menuRef}
className={cn( className={cn(
'fixed z-50 min-w-[160px] rounded-md border border-[#1e2130]', 'fixed z-50 min-w-[160px] rounded-md border border-border',
'bg-[#14161d] py-1 shadow-lg animate-scale-in' 'bg-card py-1 shadow-lg animate-scale-in'
)} )}
style={{ style={{
top: `${menuPosition.top}px`, top: `${menuPosition.top}px`,
@@ -81,7 +81,7 @@ export function ActionMenu({ items }: ActionMenuProps) {
'disabled:opacity-50 disabled:pointer-events-none', 'disabled:opacity-50 disabled:pointer-events-none',
item.destructive item.destructive
? 'text-red-400 hover:bg-red-400/10' ? 'text-red-400 hover:bg-red-400/10'
: 'text-[#848b9b] hover:bg-accent' : 'text-muted-foreground hover:bg-accent'
)} )}
> >
{item.icon} {item.icon}

View File

@@ -36,7 +36,7 @@ export function AdminLayout() {
return ( return (
<div className="flex h-full"> <div className="flex h-full">
{/* Desktop sidebar */} {/* Desktop sidebar */}
<div className="hidden w-60 shrink-0 border-r border-[#1e2130] bg-[#14161d] md:block"> <div className="hidden w-60 shrink-0 border-r border-border bg-card md:block">
<AdminSidebar /> <AdminSidebar />
</div> </div>
@@ -44,14 +44,14 @@ export function AdminLayout() {
{mobileOpen && ( {mobileOpen && (
<div className="fixed inset-0 z-40 md:hidden"> <div className="fixed inset-0 z-40 md:hidden">
<div <div
className="absolute inset-0 bg-[#14161d]/80" className="absolute inset-0 bg-card/80"
onClick={() => setMobileOpen(false)} onClick={() => setMobileOpen(false)}
/> />
<div className="absolute inset-y-0 left-0 w-60 border-r border-[#1e2130] bg-[#14161d] shadow-xl"> <div className="absolute inset-y-0 left-0 w-60 border-r border-border bg-card shadow-xl">
<div className="flex h-12 items-center justify-end px-3"> <div className="flex h-12 items-center justify-end px-3">
<button <button
onClick={() => setMobileOpen(false)} onClick={() => setMobileOpen(false)}
className="rounded-md p-1.5 text-[#848b9b] hover:bg-accent" className="rounded-md p-1.5 text-muted-foreground hover:bg-accent"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </button>
@@ -67,7 +67,7 @@ export function AdminLayout() {
{/* Mobile menu button */} {/* Mobile menu button */}
<button <button
onClick={() => setMobileOpen(true)} onClick={() => setMobileOpen(true)}
className="mb-4 rounded-md p-2 text-[#848b9b] hover:bg-accent md:hidden" className="mb-4 rounded-md p-2 text-muted-foreground hover:bg-accent md:hidden"
> >
<Menu className="h-5 w-5" /> <Menu className="h-5 w-5" />
</button> </button>

View File

@@ -45,7 +45,7 @@ export function AdminSidebar({ className, onNavigate }: AdminSidebarProps) {
return ( return (
<aside className={cn('flex h-full flex-col', className)}> <aside className={cn('flex h-full flex-col', className)}>
<div className="p-4"> <div className="p-4">
<h2 className="text-lg font-bold text-[#e2e5eb]">Admin Panel</h2> <h2 className="text-lg font-bold text-foreground">Admin Panel</h2>
</div> </div>
<nav className="flex-1 space-y-1 px-3"> <nav className="flex-1 space-y-1 px-3">
{navItems.map((item) => ( {navItems.map((item) => (
@@ -56,8 +56,8 @@ export function AdminSidebar({ className, onNavigate }: AdminSidebarProps) {
className={cn( className={cn(
'flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors', 'flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium transition-colors',
isActive(item.path, item.end) isActive(item.path, item.end)
? 'bg-accent text-[#e2e5eb]' ? 'bg-accent text-foreground'
: 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
> >
<item.icon className="h-4 w-4" /> <item.icon className="h-4 w-4" />
@@ -65,13 +65,13 @@ export function AdminSidebar({ className, onNavigate }: AdminSidebarProps) {
</Link> </Link>
))} ))}
</nav> </nav>
<div className="border-t border-[#1e2130] p-3"> <div className="border-t border-border p-3">
<Link <Link
to="/trees" to="/trees"
onClick={onNavigate} onClick={onNavigate}
className={cn( className={cn(
'flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium', 'flex items-center gap-3 rounded-md px-3 py-2 text-sm font-medium',
'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]' 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
> >
<ArrowLeft className="h-4 w-4" /> <ArrowLeft className="h-4 w-4" />

View File

@@ -38,7 +38,7 @@ export function CategoryRow({
ref={setNodeRef} ref={setNodeRef}
style={style} style={style}
className={cn( className={cn(
'flex items-center gap-3 bg-[#14161d] border border-[#1e2130] rounded-xl p-4', 'flex items-center gap-3 bg-card border border-border rounded-xl p-4',
isDragging && 'opacity-50' isDragging && 'opacity-50'
)} )}
> >
@@ -47,7 +47,7 @@ export function CategoryRow({
type="button" type="button"
{...attributes} {...attributes}
{...listeners} {...listeners}
className="cursor-grab touch-none text-[#848b9b] hover:text-[#e2e5eb] active:cursor-grabbing" className="cursor-grab touch-none text-muted-foreground hover:text-foreground active:cursor-grabbing"
aria-label="Drag to reorder" aria-label="Drag to reorder"
> >
<GripVertical className="h-5 w-5" /> <GripVertical className="h-5 w-5" />
@@ -56,17 +56,17 @@ export function CategoryRow({
{/* Category Info */} {/* Category Info */}
<div className="flex-1"> <div className="flex-1">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="font-medium text-[#e2e5eb]">{category.name}</h3> <h3 className="font-medium text-foreground">{category.name}</h3>
{!category.is_active && ( {!category.is_active && (
<span className="rounded-full bg-accent px-2 py-0.5 text-xs font-medium text-[#848b9b]"> <span className="rounded-full bg-accent px-2 py-0.5 text-xs font-medium text-muted-foreground">
Archived Archived
</span> </span>
)} )}
</div> </div>
{category.description && ( {category.description && (
<p className="mt-1 text-sm text-[#848b9b]">{category.description}</p> <p className="mt-1 text-sm text-muted-foreground">{category.description}</p>
)} )}
<p className="mt-1 text-xs text-[#848b9b]"> <p className="mt-1 text-xs text-muted-foreground">
{stepCount} step{stepCount !== 1 ? 's' : ''} {stepCount} step{stepCount !== 1 ? 's' : ''}
</p> </p>
</div> </div>
@@ -77,8 +77,8 @@ export function CategoryRow({
type="button" type="button"
onClick={() => onEdit(category)} onClick={() => onEdit(category)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] bg-[#14161d] p-2 text-[#848b9b]', 'rounded-md border border-border bg-card p-2 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Edit category" title="Edit category"
aria-label="Edit category" aria-label="Edit category"
@@ -91,7 +91,7 @@ export function CategoryRow({
type="button" type="button"
onClick={() => onArchive(category.id)} onClick={() => onArchive(category.id)}
className={cn( className={cn(
'rounded-md border border-input bg-[#0c0d10] p-2 text-[#848b9b]', 'rounded-md border border-input bg-background p-2 text-muted-foreground',
'hover:bg-accent hover:text-accent-foreground' 'hover:bg-accent hover:text-accent-foreground'
)} )}
title="Archive category" title="Archive category"
@@ -104,7 +104,7 @@ export function CategoryRow({
type="button" type="button"
onClick={() => onRestore(category.id)} onClick={() => onRestore(category.id)}
className={cn( className={cn(
'rounded-md border border-input bg-[#0c0d10] p-2 text-[#848b9b]', 'rounded-md border border-input bg-background p-2 text-muted-foreground',
'hover:bg-accent hover:text-accent-foreground' 'hover:bg-accent hover:text-accent-foreground'
)} )}
title="Restore category" title="Restore category"

View File

@@ -91,7 +91,7 @@ export function CreateCategoryModal({
)} )}
<div> <div>
<label htmlFor="name" className="mb-1 block text-sm font-medium text-[#e2e5eb]"> <label htmlFor="name" className="mb-1 block text-sm font-medium text-foreground">
Category Name <span className="text-red-400">*</span> Category Name <span className="text-red-400">*</span>
</label> </label>
<Input <Input
@@ -104,14 +104,14 @@ export function CreateCategoryModal({
placeholder="e.g., Network Troubleshooting" placeholder="e.g., Network Troubleshooting"
required required
/> />
<p className="mt-1 text-xs text-[#848b9b]"> <p className="mt-1 text-xs text-muted-foreground">
{name.length}/100 characters {name.length}/100 characters
</p> </p>
</div> </div>
<div> <div>
<label htmlFor="description" className="mb-1 block text-sm font-medium text-[#e2e5eb]"> <label htmlFor="description" className="mb-1 block text-sm font-medium text-foreground">
Description <span className="text-[#848b9b]">(optional)</span> Description <span className="text-muted-foreground">(optional)</span>
</label> </label>
<Textarea <Textarea
id="description" id="description"

View File

@@ -50,16 +50,16 @@ export function DataTable<T>({
} }
return ( return (
<div className="overflow-x-auto rounded-lg border border-[#1e2130]"> <div className="overflow-x-auto rounded-lg border border-border">
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="border-b border-[#1e2130] bg-accent"> <tr className="border-b border-border bg-accent">
{columns.map((col) => ( {columns.map((col) => (
<th <th
key={col.key} key={col.key}
className={cn( className={cn(
'px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-[#848b9b]', 'px-4 py-3 text-left text-xs font-medium uppercase tracking-wider text-muted-foreground',
col.sortable && 'cursor-pointer select-none hover:text-[#e2e5eb]', col.sortable && 'cursor-pointer select-none hover:text-foreground',
col.className col.className
)} )}
onClick={col.sortable ? () => handleSort(col.key) : undefined} onClick={col.sortable ? () => handleSort(col.key) : undefined}
@@ -87,7 +87,7 @@ export function DataTable<T>({
<tbody> <tbody>
{isLoading ? ( {isLoading ? (
Array.from({ length: skeletonRows }).map((_, i) => ( Array.from({ length: skeletonRows }).map((_, i) => (
<tr key={i} className="border-b border-[#1e2130] last:border-0"> <tr key={i} className="border-b border-border last:border-0">
{columns.map((col) => ( {columns.map((col) => (
<td key={col.key} className="px-4 py-3"> <td key={col.key} className="px-4 py-3">
<div className="h-4 w-3/4 animate-pulse rounded bg-accent" /> <div className="h-4 w-3/4 animate-pulse rounded bg-accent" />
@@ -99,7 +99,7 @@ export function DataTable<T>({
<tr> <tr>
<td colSpan={columns.length} className="px-4 py-12 text-center"> <td colSpan={columns.length} className="px-4 py-12 text-center">
{emptyState || ( {emptyState || (
<span className="text-[#848b9b]">No data found</span> <span className="text-muted-foreground">No data found</span>
)} )}
</td> </td>
</tr> </tr>
@@ -107,7 +107,7 @@ export function DataTable<T>({
data.map((item) => ( data.map((item) => (
<tr <tr
key={keyExtractor(item)} key={keyExtractor(item)}
className="border-b border-[#1e2130] last:border-0 hover:bg-accent transition-colors" className="border-b border-border last:border-0 hover:bg-accent transition-colors"
> >
{columns.map((col) => ( {columns.map((col) => (
<td key={col.key} className={cn('px-4 py-3', col.className)}> <td key={col.key} className={cn('px-4 py-3', col.className)}>

View File

@@ -103,7 +103,7 @@ export function EditCategoryModal({
)} )}
<div> <div>
<label htmlFor="edit-name" className="mb-1 block text-sm font-medium text-[#e2e5eb]"> <label htmlFor="edit-name" className="mb-1 block text-sm font-medium text-foreground">
Category Name <span className="text-red-400">*</span> Category Name <span className="text-red-400">*</span>
</label> </label>
<Input <Input
@@ -116,14 +116,14 @@ export function EditCategoryModal({
placeholder="e.g., Network Troubleshooting" placeholder="e.g., Network Troubleshooting"
required required
/> />
<p className="mt-1 text-xs text-[#848b9b]"> <p className="mt-1 text-xs text-muted-foreground">
{name.length}/100 characters {name.length}/100 characters
</p> </p>
</div> </div>
<div> <div>
<label htmlFor="edit-description" className="mb-1 block text-sm font-medium text-[#e2e5eb]"> <label htmlFor="edit-description" className="mb-1 block text-sm font-medium text-foreground">
Description <span className="text-[#848b9b]">(optional)</span> Description <span className="text-muted-foreground">(optional)</span>
</label> </label>
<Textarea <Textarea
id="edit-description" id="edit-description"

View File

@@ -36,20 +36,20 @@ export function Pagination({ page, totalPages, total, pageSize, onPageChange }:
return ( return (
<div className="flex items-center justify-between gap-4 pt-4"> <div className="flex items-center justify-between gap-4 pt-4">
<span className="text-sm text-[#848b9b]"> <span className="text-sm text-muted-foreground">
Showing {start}-{end} of {total} Showing {start}-{end} of {total}
</span> </span>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<button <button
onClick={() => onPageChange(page - 1)} onClick={() => onPageChange(page - 1)}
disabled={page <= 1} disabled={page <= 1}
className={cn(btnBase, 'px-2 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]')} className={cn(btnBase, 'px-2 text-muted-foreground hover:bg-accent hover:text-foreground')}
> >
<ChevronLeft className="h-4 w-4" /> <ChevronLeft className="h-4 w-4" />
</button> </button>
{getPageNumbers().map((p, i) => {getPageNumbers().map((p, i) =>
p === 'ellipsis' ? ( p === 'ellipsis' ? (
<span key={`e${i}`} className="px-1 text-[#848b9b]">...</span> <span key={`e${i}`} className="px-1 text-muted-foreground">...</span>
) : ( ) : (
<button <button
key={p} key={p}
@@ -58,8 +58,8 @@ export function Pagination({ page, totalPages, total, pageSize, onPageChange }:
btnBase, btnBase,
'px-2', 'px-2',
p === page p === page
? 'bg-[#22d3ee] text-white' ? 'bg-primary text-white'
: 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
> >
{p} {p}
@@ -69,7 +69,7 @@ export function Pagination({ page, totalPages, total, pageSize, onPageChange }:
<button <button
onClick={() => onPageChange(page + 1)} onClick={() => onPageChange(page + 1)}
disabled={page >= totalPages} disabled={page >= totalPages}
className={cn(btnBase, 'px-2 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]')} className={cn(btnBase, 'px-2 text-muted-foreground hover:bg-accent hover:text-foreground')}
> >
<ChevronRight className="h-4 w-4" /> <ChevronRight className="h-4 w-4" />
</button> </button>

View File

@@ -40,21 +40,21 @@ export function SearchInput({ value = '', onSearch, placeholder = 'Search...', c
return ( return (
<div className={cn('relative', className)}> <div className={cn('relative', className)}>
<Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-[#848b9b]" /> <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" />
<input <input
type="text" type="text"
value={localValue} value={localValue}
onChange={handleChange} onChange={handleChange}
placeholder={placeholder} placeholder={placeholder}
className={cn( className={cn(
'h-9 w-full rounded-md border border-[#1e2130] bg-[#14161d] pl-9 pr-8 text-sm text-[#e2e5eb]', 'h-9 w-full rounded-md border border-border bg-card pl-9 pr-8 text-sm text-foreground',
'placeholder:text-[#848b9b] focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20' 'placeholder:text-muted-foreground focus:outline-hidden focus:border-primary focus:ring-2 focus:ring-primary/20'
)} )}
/> />
{localValue && ( {localValue && (
<button <button
onClick={handleClear} onClick={handleClear}
className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-[#848b9b] hover:text-[#e2e5eb]" className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-0.5 text-muted-foreground hover:text-foreground"
> >
<X className="h-3.5 w-3.5" /> <X className="h-3.5 w-3.5" />
</button> </button>

View File

@@ -12,7 +12,7 @@ const variantClasses: Record<BadgeVariant, string> = {
success: 'bg-emerald-400/10 text-emerald-400', success: 'bg-emerald-400/10 text-emerald-400',
destructive: 'bg-red-400/10 text-red-400', destructive: 'bg-red-400/10 text-red-400',
warning: 'bg-yellow-400/10 text-yellow-400', warning: 'bg-yellow-400/10 text-yellow-400',
default: 'bg-accent text-[#848b9b]', default: 'bg-accent text-muted-foreground',
} }
export function StatusBadge({ variant = 'default', children, className }: StatusBadgeProps) { export function StatusBadge({ variant = 'default', children, className }: StatusBadgeProps) {

View File

@@ -41,10 +41,10 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
return ( return (
<div className="card-flat p-6"> <div className="card-flat p-6">
<div className="flex items-center gap-2 mb-2"> <div className="flex items-center gap-2 mb-2">
<MapPin size={16} className="text-[#e2e5eb]" /> <MapPin size={16} className="text-foreground" />
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb]">Domain Coverage</h3> <h3 className="font-heading text-sm font-semibold text-foreground">Domain Coverage</h3>
</div> </div>
<p className="text-sm text-[#848b9b]"> <p className="text-sm text-muted-foreground">
No session data for this period. Start using FlowPilot to see coverage metrics. No session data for this period. Start using FlowPilot to see coverage metrics.
</p> </p>
</div> </div>
@@ -55,10 +55,10 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
<div className="card-flat p-3 sm:p-5"> <div className="card-flat p-3 sm:p-5">
<div className="mb-4"> <div className="mb-4">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<MapPin size={16} className="text-[#e2e5eb]" /> <MapPin size={16} className="text-foreground" />
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb]">Domain Coverage</h3> <h3 className="font-heading text-sm font-semibold text-foreground">Domain Coverage</h3>
</div> </div>
<p className="text-xs text-[#848b9b]"> <p className="text-xs text-muted-foreground">
Resolution coverage and knowledge gaps by problem domain Resolution coverage and knowledge gaps by problem domain
</p> </p>
</div> </div>
@@ -66,26 +66,26 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full"> <table className="w-full">
<thead> <thead>
<tr className="border-b border-[#1e2130]"> <tr className="border-b border-border">
<th className="px-3 py-2 text-left font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <th className="px-3 py-2 text-left font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Domain Domain
</th> </th>
<th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Flows Flows
</th> </th>
<th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Sessions Sessions
</th> </th>
<th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Resolution % Resolution %
</th> </th>
<th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Escalation % Escalation %
</th> </th>
<th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Guided % Guided %
</th> </th>
<th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]" <th className="px-3 py-2 text-right font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground"
title="Average time to resolve sessions in this domain. Green: &lt;10 min, Amber: 1020 min, Red: &gt;20 min. Lower is better."> title="Average time to resolve sessions in this domain. Green: &lt;10 min, Amber: 1020 min, Red: &gt;20 min. Lower is better.">
Avg Resolution Avg Resolution
</th> </th>
@@ -93,15 +93,15 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
</thead> </thead>
<tbody> <tbody>
{data.domains.map((row) => ( {data.domains.map((row) => (
<tr key={row.domain} className="border-b border-[#1e2130]"> <tr key={row.domain} className="border-b border-border">
<td className="px-3 py-2 text-sm text-[#e2e5eb] font-medium"> <td className="px-3 py-2 text-sm text-foreground font-medium">
{row.domain} {row.domain}
</td> </td>
<td className="px-3 py-2 text-sm text-right"> <td className="px-3 py-2 text-sm text-right">
{row.flow_count === 0 ? ( {row.flow_count === 0 ? (
<Link <Link
to="/trees/new" to="/trees/new"
className="inline-flex items-center gap-1 text-xs text-[#22d3ee] hover:underline" className="inline-flex items-center gap-1 text-xs text-primary hover:underline"
> >
<Plus size={10} /> <Plus size={10} />
Create Flow Create Flow
@@ -115,7 +115,7 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
</span> </span>
)} )}
</td> </td>
<td className="px-3 py-2 text-sm text-right text-[#848b9b]"> <td className="px-3 py-2 text-sm text-right text-muted-foreground">
{row.session_count} {row.session_count}
</td> </td>
<td className="px-3 py-2 text-sm text-right"> <td className="px-3 py-2 text-sm text-right">
@@ -144,7 +144,7 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
</td> </td>
<td className="px-3 py-2 text-sm text-right"> <td className="px-3 py-2 text-sm text-right">
{row.avg_resolution_minutes == null ? ( {row.avg_resolution_minutes == null ? (
<span className="text-[#848b9b]"></span> <span className="text-muted-foreground"></span>
) : ( ) : (
<span <span
className={cn( className={cn(
@@ -167,7 +167,7 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
{data.unmapped_session_count > 0 && ( {data.unmapped_session_count > 0 && (
<tfoot> <tfoot>
<tr> <tr>
<td colSpan={7} className="px-3 py-2 text-xs text-[#848b9b]"> <td colSpan={7} className="px-3 py-2 text-xs text-muted-foreground">
{data.unmapped_session_count} sessions had no domain classification {data.unmapped_session_count} sessions had no domain classification
</td> </td>
</tr> </tr>
@@ -176,7 +176,7 @@ export default function CoverageHeatmap({ data }: CoverageHeatmapProps) {
</table> </table>
</div> </div>
<div className="flex flex-wrap gap-4 mt-3 text-[0.625rem] font-sans text-xs text-[#848b9b]"> <div className="flex flex-wrap gap-4 mt-3 text-[0.625rem] font-sans text-xs text-muted-foreground">
<span><span className="inline-block w-2 h-2 rounded-full bg-emerald-400 mr-1" />Good</span> <span><span className="inline-block w-2 h-2 rounded-full bg-emerald-400 mr-1" />Good</span>
<span><span className="inline-block w-2 h-2 rounded-full bg-amber-400 mr-1" />Needs Improvement</span> <span><span className="inline-block w-2 h-2 rounded-full bg-amber-400 mr-1" />Needs Improvement</span>
<span><span className="inline-block w-2 h-2 rounded-full bg-rose-500 mr-1" />Critical</span> <span><span className="inline-block w-2 h-2 rounded-full bg-rose-500 mr-1" />Critical</span>

View File

@@ -54,14 +54,14 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
if (loading) { if (loading) {
return ( return (
<div className="flex items-center justify-center py-12"> <div className="flex items-center justify-center py-12">
<Loader2 className="h-6 w-6 animate-spin text-[#848b9b]" /> <Loader2 className="h-6 w-6 animate-spin text-muted-foreground" />
</div> </div>
) )
} }
if (error || !data) { if (error || !data) {
return ( return (
<div className="text-center py-12 text-[#848b9b]"> <div className="text-center py-12 text-muted-foreground">
No analytics data available for this flow. No analytics data available for this flow.
</div> </div>
) )
@@ -73,11 +73,11 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
<div className="space-y-6"> <div className="space-y-6">
{/* Period selector */} {/* Period selector */}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<h3 className="text-lg font-semibold text-[#e2e5eb]">Flow Analytics</h3> <h3 className="text-lg font-semibold text-foreground">Flow Analytics</h3>
<select <select
value={period} value={period}
onChange={(e) => setPeriod(e.target.value as AnalyticsPeriod)} onChange={(e) => setPeriod(e.target.value as AnalyticsPeriod)}
className="rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-1.5 text-sm text-[#e2e5eb] focus:outline-hidden focus:ring-1 focus:ring-ring" className="rounded-lg border border-border bg-card px-3 py-1.5 text-sm text-foreground focus:outline-hidden focus:ring-1 focus:ring-ring"
> >
{PERIOD_OPTIONS.map((opt) => ( {PERIOD_OPTIONS.map((opt) => (
<option key={opt.value} value={opt.value}> <option key={opt.value} value={opt.value}>
@@ -107,8 +107,8 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
{/* Area chart - Sessions over time */} {/* Area chart - Sessions over time */}
{time_series.length > 0 && ( {time_series.length > 0 && (
<div className="bg-[#14161d] border border-[#1e2130] rounded-xl p-4"> <div className="bg-card border border-border rounded-xl p-4">
<p className="text-sm font-semibold text-[#e2e5eb] mb-3">Sessions Over Time</p> <p className="text-sm font-semibold text-foreground mb-3">Sessions Over Time</p>
<ResponsiveContainer width="100%" height={180}> <ResponsiveContainer width="100%" height={180}>
<AreaChart data={time_series}> <AreaChart data={time_series}>
<CartesianGrid <CartesianGrid
@@ -192,7 +192,7 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
className="h-2 w-2 rounded-full" className="h-2 w-2 rounded-full"
style={{ backgroundColor: color }} style={{ backgroundColor: color }}
/> />
<span className="text-xs text-[#848b9b] capitalize"> <span className="text-xs text-muted-foreground capitalize">
{key} {key}
</span> </span>
</div> </div>
@@ -203,16 +203,16 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
{/* Step Feedback Table with Dropoff Metrics */} {/* Step Feedback Table with Dropoff Metrics */}
{step_feedback.length > 0 && ( {step_feedback.length > 0 && (
<div className="bg-[#14161d] border border-[#1e2130] rounded-xl p-4"> <div className="bg-card border border-border rounded-xl p-4">
<p className="text-sm font-semibold text-[#e2e5eb] mb-3">Step Performance</p> <p className="text-sm font-semibold text-foreground mb-3">Step Performance</p>
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="border-b border-[#1e2130]"> <tr className="border-b border-border">
<th className="text-left py-2 pr-4 text-[#e2e5eb] font-medium">Step</th> <th className="text-left py-2 pr-4 text-foreground font-medium">Step</th>
<th className="text-right py-2 pr-4 text-[#e2e5eb] font-medium">Visits</th> <th className="text-right py-2 pr-4 text-foreground font-medium">Visits</th>
<th className="text-right py-2 pr-4 text-[#e2e5eb] font-medium">Dropoffs</th> <th className="text-right py-2 pr-4 text-foreground font-medium">Dropoffs</th>
<th className="text-right py-2 text-[#e2e5eb] font-medium">Dropoff Rate</th> <th className="text-right py-2 text-foreground font-medium">Dropoff Rate</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@@ -220,23 +220,23 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
<tr <tr
key={step.node_id} key={step.node_id}
className={cn( className={cn(
'border-b border-[#1e2130] last:border-0', 'border-b border-border last:border-0',
step.dropoff_rate > 0.2 && 'bg-red-400/5' step.dropoff_rate > 0.2 && 'bg-red-400/5'
)} )}
> >
<td className="py-2 pr-4 text-[#848b9b] truncate max-w-[200px]"> <td className="py-2 pr-4 text-muted-foreground truncate max-w-[200px]">
{step.node_title} {step.node_title}
</td> </td>
<td className="py-2 pr-4 text-right text-[#848b9b]"> <td className="py-2 pr-4 text-right text-muted-foreground">
{step.visit_count} {step.visit_count}
</td> </td>
<td className="py-2 pr-4 text-right text-[#848b9b]"> <td className="py-2 pr-4 text-right text-muted-foreground">
{step.dropoff_count} {step.dropoff_count}
</td> </td>
<td <td
className={cn( className={cn(
'py-2 text-right font-medium', 'py-2 text-right font-medium',
step.dropoff_rate > 0.2 ? 'text-red-400' : 'text-[#848b9b]' step.dropoff_rate > 0.2 ? 'text-red-400' : 'text-muted-foreground'
)} )}
> >
{(step.dropoff_rate * 100).toFixed(1)}% {(step.dropoff_rate * 100).toFixed(1)}%
@@ -251,13 +251,13 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
{/* Recent Comments (Anonymous) */} {/* Recent Comments (Anonymous) */}
{recent_comments.length > 0 && ( {recent_comments.length > 0 && (
<div className="bg-[#14161d] border border-[#1e2130] rounded-xl p-4"> <div className="bg-card border border-border rounded-xl p-4">
<p className="text-sm font-semibold text-[#e2e5eb] mb-3">Recent Feedback</p> <p className="text-sm font-semibold text-foreground mb-3">Recent Feedback</p>
<div className="space-y-3"> <div className="space-y-3">
{recent_comments.map((item, i) => ( {recent_comments.map((item, i) => (
<div <div
key={i} key={i}
className="flex items-start gap-3 border-b border-[#1e2130]/50 pb-3 last:border-0 last:pb-0" className="flex items-start gap-3 border-b border-border/50 pb-3 last:border-0 last:pb-0"
> >
<div className="flex items-center gap-0.5 shrink-0 pt-0.5"> <div className="flex items-center gap-0.5 shrink-0 pt-0.5">
{[1, 2, 3, 4, 5].map((v) => ( {[1, 2, 3, 4, 5].map((v) => (
@@ -267,16 +267,16 @@ export function FlowAnalyticsPanel({ treeId }: FlowAnalyticsPanelProps) {
className={cn( className={cn(
v <= item.rating v <= item.rating
? 'fill-yellow-400 text-yellow-400' ? 'fill-yellow-400 text-yellow-400'
: 'fill-none text-[#848b9b]' : 'fill-none text-muted-foreground'
)} )}
/> />
))} ))}
</div> </div>
<div className="min-w-0"> <div className="min-w-0">
{item.comment && ( {item.comment && (
<p className="text-sm text-[#e2e5eb]">{item.comment}</p> <p className="text-sm text-foreground">{item.comment}</p>
)} )}
<p className="text-xs text-[#848b9b] mt-0.5"> <p className="text-xs text-muted-foreground mt-0.5">
{new Date(item.created_at).toLocaleDateString()} {new Date(item.created_at).toLocaleDateString()}
</p> </p>
</div> </div>
@@ -299,11 +299,11 @@ function StatCard({
subtitle?: string subtitle?: string
}) { }) {
return ( return (
<div className="bg-[#14161d] border border-[#1e2130] rounded-xl p-4"> <div className="bg-card border border-border rounded-xl p-4">
<p className="text-xs text-[#848b9b]">{label}</p> <p className="text-xs text-muted-foreground">{label}</p>
<p className="text-xl font-bold text-[#e2e5eb] mt-1">{value}</p> <p className="text-xl font-bold text-foreground mt-1">{value}</p>
{subtitle && ( {subtitle && (
<p className="text-xs text-[#848b9b] mt-0.5">{subtitle}</p> <p className="text-xs text-muted-foreground mt-0.5">{subtitle}</p>
)} )}
</div> </div>
) )

View File

@@ -13,7 +13,7 @@ type SortColumn = 'name' | 'usage_count' | 'success_rate' | 'last_matched_at' |
type SortDir = 'asc' | 'desc' type SortDir = 'asc' | 'desc'
const TYPE_LABELS: Record<string, { label: string; color: string }> = { const TYPE_LABELS: Record<string, { label: string; color: string }> = {
troubleshooting: { label: 'Troubleshooting', color: 'text-[#22d3ee]' }, troubleshooting: { label: 'Troubleshooting', color: 'text-primary' },
procedural: { label: 'Project', color: 'text-amber-400' }, procedural: { label: 'Project', color: 'text-amber-400' },
maintenance: { label: 'Maintenance', color: 'text-blue-400' }, maintenance: { label: 'Maintenance', color: 'text-blue-400' },
} }
@@ -33,7 +33,7 @@ function formatRelativeTime(dateStr: string | null): string {
} }
function rateColor(value: number | null): string { function rateColor(value: number | null): string {
if (value === null) return 'text-[#848b9b]' if (value === null) return 'text-muted-foreground'
if (value > 75) return 'text-emerald-400' if (value > 75) return 'text-emerald-400'
if (value >= 50) return 'text-amber-400' if (value >= 50) return 'text-amber-400'
return 'text-rose-500' return 'text-rose-500'
@@ -112,7 +112,7 @@ export default function FlowQualityTable({ data }: FlowQualityTableProps) {
return ( return (
<div className="card-flat p-3 sm:p-5"> <div className="card-flat p-3 sm:p-5">
<div className="flex items-center justify-center min-h-[200px]"> <div className="flex items-center justify-center min-h-[200px]">
<p className="text-sm text-[#848b9b]"> <p className="text-sm text-muted-foreground">
No flows found for this account. Create your first flow to start tracking quality. No flows found for this account. Create your first flow to start tracking quality.
</p> </p>
</div> </div>
@@ -133,17 +133,17 @@ export default function FlowQualityTable({ data }: FlowQualityTableProps) {
<div className="card-flat p-3 sm:p-5"> <div className="card-flat p-3 sm:p-5">
<div className="mb-4"> <div className="mb-4">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb]"> <h3 className="font-heading text-sm font-semibold text-foreground">
Flow Quality Scores Flow Quality Scores
</h3> </h3>
<span className="group relative"> <span className="group relative">
<Info size={14} className="text-[#848b9b] cursor-help" /> <Info size={14} className="text-muted-foreground cursor-help" />
<div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-64 p-2 rounded-lg bg-[#14161d] border border-[#1e2130] text-xs text-[#848b9b] opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-10"> <div className="absolute bottom-full left-1/2 -translate-x-1/2 mb-2 w-64 p-2 rounded-lg bg-card border border-border text-xs text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity pointer-events-none z-10">
Quality score combines success rate (50%), AI confidence level (30%), and recent usage (20%). Higher is better. Quality score combines success rate (50%), AI confidence level (30%), and recent usage (20%). Higher is better.
</div> </div>
</span> </span>
</div> </div>
<p className="text-xs text-[#848b9b] mt-1"> <p className="text-xs text-muted-foreground mt-1">
Performance and usage metrics for your troubleshooting flows Performance and usage metrics for your troubleshooting flows
</p> </p>
</div> </div>
@@ -151,7 +151,7 @@ export default function FlowQualityTable({ data }: FlowQualityTableProps) {
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead> <thead>
<tr className="border-b border-[#1e2130]"> <tr className="border-b border-border">
{columns.map((col) => { {columns.map((col) => {
const isActive = sortCol === col.key const isActive = sortCol === col.key
const SortIcon = isActive const SortIcon = isActive
@@ -160,7 +160,7 @@ export default function FlowQualityTable({ data }: FlowQualityTableProps) {
return ( return (
<th <th
key={col.key} key={col.key}
className="text-left py-2 px-2 font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] cursor-pointer select-none hover:text-[#e2e5eb] transition-colors" className="text-left py-2 px-2 font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground cursor-pointer select-none hover:text-foreground transition-colors"
onClick={() => handleSort(col.key)} onClick={() => handleSort(col.key)}
title={col.title} title={col.title}
> >
@@ -207,7 +207,7 @@ function FlowRow({
return ( return (
<tr <tr
className={cn( className={cn(
'border-b border-[#1e2130]/50 hover:bg-[#14161d]/30 transition-colors', 'border-b border-border/50 hover:bg-card/30 transition-colors',
isTopPerformer && 'border-l-2 border-l-emerald-400', isTopPerformer && 'border-l-2 border-l-emerald-400',
needsAttention && 'border-l-2 border-l-rose-500', needsAttention && 'border-l-2 border-l-rose-500',
)} )}
@@ -217,11 +217,11 @@ function FlowRow({
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Link <Link
to={getTreeEditorPath(flow.flow_id, flow.tree_type)} to={getTreeEditorPath(flow.flow_id, flow.tree_type)}
className="text-[#e2e5eb] hover:text-[#22d3ee] transition-colors font-medium truncate max-w-[200px]" className="text-foreground hover:text-primary transition-colors font-medium truncate max-w-[200px]"
> >
{flow.name} {flow.name}
</Link> </Link>
<span className={cn('font-sans text-xs text-[0.5rem] uppercase tracking-wider ml-2 shrink-0', TYPE_LABELS[flow.tree_type]?.color || 'text-[#848b9b]')}> <span className={cn('font-sans text-xs text-[0.5rem] uppercase tracking-wider ml-2 shrink-0', TYPE_LABELS[flow.tree_type]?.color || 'text-muted-foreground')}>
{TYPE_LABELS[flow.tree_type]?.label || flow.tree_type} {TYPE_LABELS[flow.tree_type]?.label || flow.tree_type}
</span> </span>
{needsAttention && ( {needsAttention && (
@@ -233,7 +233,7 @@ function FlowRow({
</td> </td>
{/* Usage */} {/* Usage */}
<td className="py-2.5 px-2 text-[#e2e5eb]">{flow.usage_count}</td> <td className="py-2.5 px-2 text-foreground">{flow.usage_count}</td>
{/* Success Rate */} {/* Success Rate */}
<td className={cn('py-2.5 px-2', rateColor(flow.success_rate))}> <td className={cn('py-2.5 px-2', rateColor(flow.success_rate))}>
@@ -241,7 +241,7 @@ function FlowRow({
</td> </td>
{/* Last Used */} {/* Last Used */}
<td className="py-2.5 px-2 text-[#848b9b]"> <td className="py-2.5 px-2 text-muted-foreground">
{formatRelativeTime(flow.last_matched_at)} {formatRelativeTime(flow.last_matched_at)}
</td> </td>
@@ -259,7 +259,7 @@ function FlowRow({
style={{ width: `${flow.quality_score * 100}%` }} style={{ width: `${flow.quality_score * 100}%` }}
/> />
</div> </div>
<span className="text-xs text-[#e2e5eb]"> <span className="text-xs text-foreground">
{(flow.quality_score * 100).toFixed(0)} {(flow.quality_score * 100).toFixed(0)}
</span> </span>
</div> </div>

View File

@@ -21,7 +21,7 @@ export default function PsaMetricsPanel({ data }: PsaMetricsPanelProps) {
return ( return (
<div className="card-flat p-3 sm:p-5"> <div className="card-flat p-3 sm:p-5">
<div className="flex items-center justify-center min-h-[200px]"> <div className="flex items-center justify-center min-h-[200px]">
<p className="text-sm text-[#848b9b]"> <p className="text-sm text-muted-foreground">
No PSA activity data for this period. Link sessions to PSA tickets to see metrics. No PSA activity data for this period. Link sessions to PSA tickets to see metrics.
</p> </p>
</div> </div>
@@ -34,19 +34,19 @@ export default function PsaMetricsPanel({ data }: PsaMetricsPanelProps) {
{/* Row 1 — Metric cards */} {/* Row 1 — Metric cards */}
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4"> <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
<div className="card-flat p-4"> <div className="card-flat p-4">
<p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#5a6170]">Time Entries</p> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-text-muted">Time Entries</p>
<p className="text-[#67e8f9] font-heading text-2xl mt-1">{data.total_time_entries}</p> <p className="text-accent-text font-heading text-2xl mt-1">{data.total_time_entries}</p>
<p className="text-xs text-[#848b9b] mt-1">logged to PSA</p> <p className="text-xs text-muted-foreground mt-1">logged to PSA</p>
</div> </div>
<div className="card-flat p-4"> <div className="card-flat p-4">
<p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#5a6170]">Hours Logged</p> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-text-muted">Hours Logged</p>
<p className="text-[#67e8f9] font-heading text-2xl mt-1">{data.total_hours_logged.toFixed(1)}</p> <p className="text-accent-text font-heading text-2xl mt-1">{data.total_hours_logged.toFixed(1)}</p>
<p className="text-xs text-[#848b9b] mt-1">total hours tracked</p> <p className="text-xs text-muted-foreground mt-1">total hours tracked</p>
</div> </div>
<div className="card-flat p-4"> <div className="card-flat p-4">
<p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#5a6170]">Avg Hours/Session</p> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-text-muted">Avg Hours/Session</p>
<p className="text-[#67e8f9] font-heading text-2xl mt-1">{data.avg_hours_per_session.toFixed(2)}</p> <p className="text-accent-text font-heading text-2xl mt-1">{data.avg_hours_per_session.toFixed(2)}</p>
<p className="text-xs text-[#848b9b] mt-1">per resolved session</p> <p className="text-xs text-muted-foreground mt-1">per resolved session</p>
</div> </div>
</div> </div>
@@ -56,7 +56,7 @@ export default function PsaMetricsPanel({ data }: PsaMetricsPanelProps) {
{/* Row 3 — Daily Trend Chart */} {/* Row 3 — Daily Trend Chart */}
{data.daily_trend.length > 0 && ( {data.daily_trend.length > 0 && (
<div className="card-flat p-3 sm:p-5"> <div className="card-flat p-3 sm:p-5">
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb] mb-4"> <h3 className="font-heading text-sm font-semibold text-foreground mb-4">
PSA Activity Trend PSA Activity Trend
</h3> </h3>
<ResponsiveContainer width="100%" height={250}> <ResponsiveContainer width="100%" height={250}>
@@ -130,7 +130,7 @@ function FunnelCard({ funnel }: { funnel: PsaFunnel }) {
return ( return (
<div className="card-flat p-3 sm:p-5"> <div className="card-flat p-3 sm:p-5">
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb] mb-4"> <h3 className="font-heading text-sm font-semibold text-foreground mb-4">
Documentation Push Funnel Documentation Push Funnel
</h3> </h3>
@@ -139,15 +139,15 @@ function FunnelCard({ funnel }: { funnel: PsaFunnel }) {
{steps.map((step, i) => ( {steps.map((step, i) => (
<div key={step.label} className="flex items-center gap-2 flex-1"> <div key={step.label} className="flex items-center gap-2 flex-1">
<div className="bg-primary/5 border border-primary/20 rounded-lg p-3 text-center flex-1"> <div className="bg-primary/5 border border-primary/20 rounded-lg p-3 text-center flex-1">
<p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
{step.label} {step.label}
</p> </p>
<p className="text-lg font-heading text-[#e2e5eb]">{step.count}</p> <p className="text-lg font-heading text-foreground">{step.count}</p>
</div> </div>
{i < steps.length - 1 && ( {i < steps.length - 1 && (
<div className="flex flex-col items-center shrink-0 px-1"> <div className="flex flex-col items-center shrink-0 px-1">
<ArrowRight size={14} className="text-[#848b9b]" /> <ArrowRight size={14} className="text-muted-foreground" />
<span className="text-[0.625rem] text-[#848b9b] font-sans text-xs"> <span className="text-[0.625rem] text-muted-foreground font-sans text-xs">
{funnelPct(steps[i].count, steps[i + 1].count)} {funnelPct(steps[i].count, steps[i + 1].count)}
</span> </span>
</div> </div>
@@ -161,15 +161,15 @@ function FunnelCard({ funnel }: { funnel: PsaFunnel }) {
{steps.map((step, i) => ( {steps.map((step, i) => (
<div key={step.label} className="flex flex-col items-center gap-2 w-full"> <div key={step.label} className="flex flex-col items-center gap-2 w-full">
<div className="bg-primary/5 border border-primary/20 rounded-lg p-3 text-center w-full"> <div className="bg-primary/5 border border-primary/20 rounded-lg p-3 text-center w-full">
<p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
{step.label} {step.label}
</p> </p>
<p className="text-lg font-heading text-[#e2e5eb]">{step.count}</p> <p className="text-lg font-heading text-foreground">{step.count}</p>
</div> </div>
{i < steps.length - 1 && ( {i < steps.length - 1 && (
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<ArrowDown size={14} className="text-[#848b9b]" /> <ArrowDown size={14} className="text-muted-foreground" />
<span className="text-[0.625rem] text-[#848b9b] font-sans text-xs"> <span className="text-[0.625rem] text-muted-foreground font-sans text-xs">
{funnelPct(steps[i].count, steps[i + 1].count)} {funnelPct(steps[i].count, steps[i + 1].count)}
</span> </span>
</div> </div>

View File

@@ -16,8 +16,8 @@ export function ChatMessage({ role, content, suggestedFlows }: ChatMessageProps)
<div <div
className={`shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${ className={`shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${
role === 'assistant' role === 'assistant'
? 'bg-primary/15 text-[#22d3ee]' ? 'bg-primary/15 text-primary'
: 'bg-white/[0.08] text-[#848b9b]' : 'bg-white/[0.08] text-muted-foreground'
}`} }`}
> >
{role === 'assistant' ? <Sparkles size={14} /> : <User size={14} />} {role === 'assistant' ? <Sparkles size={14} /> : <User size={14} />}
@@ -28,8 +28,8 @@ export function ChatMessage({ role, content, suggestedFlows }: ChatMessageProps)
<div <div
className={`rounded-2xl px-4 py-3 text-[0.875rem] leading-relaxed ${ className={`rounded-2xl px-4 py-3 text-[0.875rem] leading-relaxed ${
role === 'user' role === 'user'
? 'bg-primary/15 text-[#e2e5eb]' ? 'bg-primary/15 text-foreground'
: 'bg-[#191c25] text-[#e2e5eb] border border-[#1e2130]' : 'bg-input text-foreground border border-border'
}`} }`}
> >
<MarkdownContent content={content} className="text-[0.875rem] leading-relaxed" /> <MarkdownContent content={content} className="text-[0.875rem] leading-relaxed" />
@@ -38,7 +38,7 @@ export function ChatMessage({ role, content, suggestedFlows }: ChatMessageProps)
{/* Suggested flows (assistant only) */} {/* Suggested flows (assistant only) */}
{role === 'assistant' && suggestedFlows && suggestedFlows.length > 0 && ( {role === 'assistant' && suggestedFlows && suggestedFlows.length > 0 && (
<div className="space-y-1.5"> <div className="space-y-1.5">
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground">
Related Flows Related Flows
</span> </span>
{suggestedFlows.map(flow => ( {suggestedFlows.map(flow => (

View File

@@ -31,7 +31,7 @@ export function ChatSidebar({
<div className="px-4 py-3 border-b shrink-0" style={{ borderColor: 'var(--glass-border)' }}> <div className="px-4 py-3 border-b shrink-0" style={{ borderColor: 'var(--glass-border)' }}>
<button <button
onClick={onNewChat} onClick={onNewChat}
className="w-full flex items-center justify-center gap-2 bg-[#22d3ee] text-white font-semibold text-sm rounded-lg px-4 py-2.5 hover:brightness-110 active:scale-[0.98] transition-all" className="w-full flex items-center justify-center gap-2 bg-primary text-white font-semibold text-sm rounded-lg px-4 py-2.5 hover:brightness-110 active:scale-[0.98] transition-all"
> >
<Plus size={16} /> <Plus size={16} />
New Chat New Chat
@@ -42,7 +42,7 @@ export function ChatSidebar({
<div className="flex-1 overflow-y-auto py-2"> <div className="flex-1 overflow-y-auto py-2">
{pinnedChats.length > 0 && ( {pinnedChats.length > 0 && (
<div className="px-3 mb-1"> <div className="px-3 mb-1">
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground">
Pinned Pinned
</span> </span>
</div> </div>
@@ -74,7 +74,7 @@ export function ChatSidebar({
))} ))}
{chats.length === 0 && ( {chats.length === 0 && (
<div className="px-4 py-8 text-center text-[#848b9b] text-sm"> <div className="px-4 py-8 text-center text-muted-foreground text-sm">
No conversations yet No conversations yet
</div> </div>
)} )}
@@ -102,14 +102,14 @@ function ChatItem({
className={cn( className={cn(
'group flex items-center gap-2 px-3 py-2.5 mx-1.5 rounded-lg cursor-pointer transition-colors', 'group flex items-center gap-2 px-3 py-2.5 mx-1.5 rounded-lg cursor-pointer transition-colors',
isActive isActive
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]' ? 'bg-accent-dim text-foreground'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-input hover:text-foreground'
)} )}
> >
<MessageSquare size={14} className="shrink-0" /> <MessageSquare size={14} className="shrink-0" />
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="text-[0.8125rem] font-medium truncate">{chat.title}</div> <div className="text-[0.8125rem] font-medium truncate">{chat.title}</div>
<div className="text-[0.6875rem] text-[#848b9b]"> <div className="text-[0.6875rem] text-muted-foreground">
{chat.message_count} messages {chat.message_count} messages
</div> </div>
</div> </div>
@@ -119,11 +119,11 @@ function ChatItem({
className="p-1 rounded hover:bg-white/[0.08]" className="p-1 rounded hover:bg-white/[0.08]"
title={chat.pinned ? 'Unpin' : 'Pin'} title={chat.pinned ? 'Unpin' : 'Pin'}
> >
<Pin size={12} className={chat.pinned ? 'text-[#22d3ee]' : ''} /> <Pin size={12} className={chat.pinned ? 'text-primary' : ''} />
</button> </button>
<button <button
onClick={e => { e.stopPropagation(); onDelete() }} onClick={e => { e.stopPropagation(); onDelete() }}
className="p-1 rounded hover:bg-white/[0.08] text-[#848b9b] hover:text-rose-400" className="p-1 rounded hover:bg-white/[0.08] text-muted-foreground hover:text-rose-400"
title="Delete" title="Delete"
> >
<Trash2 size={12} /> <Trash2 size={12} />

View File

@@ -155,21 +155,21 @@ export function ConcludeSessionModal({
style={{ borderColor: 'var(--glass-border)' }} style={{ borderColor: 'var(--glass-border)' }}
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<div className="w-9 h-9 rounded-xl bg-[rgba(34,211,238,0.10)] flex items-center justify-center"> <div className="w-9 h-9 rounded-xl bg-accent-dim flex items-center justify-center">
<ClipboardList size={18} className="text-[#22d3ee]" /> <ClipboardList size={18} className="text-primary" />
</div> </div>
<div> <div>
<h2 className="text-base font-heading font-semibold text-[#e2e5eb]"> <h2 className="text-base font-heading font-semibold text-foreground">
Conclude Session Conclude Session
</h2> </h2>
<p className="text-xs text-[#848b9b] truncate max-w-[300px]"> <p className="text-xs text-muted-foreground truncate max-w-[300px]">
{chatTitle} {chatTitle}
</p> </p>
</div> </div>
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="p-2 rounded-lg hover:bg-[#1e2130] text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="p-2 rounded-lg hover:bg-border text-muted-foreground hover:text-foreground transition-colors"
> >
<X size={18} /> <X size={18} />
</button> </button>
@@ -196,10 +196,10 @@ export function ConcludeSessionModal({
className={cn( className={cn(
'w-6 h-6 rounded-full flex items-center justify-center text-[0.6875rem] font-sans text-xs font-medium transition-colors', 'w-6 h-6 rounded-full flex items-center justify-center text-[0.6875rem] font-sans text-xs font-medium transition-colors',
step === s step === s
? 'bg-[#22d3ee] text-white' ? 'bg-primary text-white'
: (i < ['select-outcome', 'add-notes', 'summary'].indexOf(step)) : (i < ['select-outcome', 'add-notes', 'summary'].indexOf(step))
? 'bg-primary/20 text-[#22d3ee]' ? 'bg-primary/20 text-primary'
: 'bg-brand-border text-[#848b9b]' : 'bg-brand-border text-muted-foreground'
)} )}
> >
{i + 1} {i + 1}
@@ -207,7 +207,7 @@ export function ConcludeSessionModal({
<span <span
className={cn( className={cn(
'text-xs font-sans text-xs', 'text-xs font-sans text-xs',
step === s ? 'text-[#e2e5eb]' : 'text-[#848b9b]' step === s ? 'text-foreground' : 'text-muted-foreground'
)} )}
> >
{s === 'select-outcome' ? 'Outcome' : s === 'add-notes' ? 'Notes' : 'Summary'} {s === 'select-outcome' ? 'Outcome' : s === 'add-notes' ? 'Notes' : 'Summary'}
@@ -221,7 +221,7 @@ export function ConcludeSessionModal({
{/* Step 1: Select Outcome */} {/* Step 1: Select Outcome */}
{step === 'select-outcome' && ( {step === 'select-outcome' && (
<div className="space-y-3"> <div className="space-y-3">
<p className="text-sm text-[#848b9b] mb-4"> <p className="text-sm text-muted-foreground mb-4">
How did this session end? How did this session end?
</p> </p>
{OUTCOMES.map(o => { {OUTCOMES.map(o => {
@@ -233,16 +233,16 @@ export function ConcludeSessionModal({
className={cn( className={cn(
'w-full flex items-center gap-4 p-4 rounded-xl border transition-all text-left', 'w-full flex items-center gap-4 p-4 rounded-xl border transition-all text-left',
'hover:scale-[1.01] active:scale-[0.99]', 'hover:scale-[1.01] active:scale-[0.99]',
'bg-[#14161d] border-[#1e2130]', 'bg-card border-border',
'hover:border-[#2a2f3d] hover:bg-[#191c25]' 'hover:border-border-hover hover:bg-input'
)} )}
> >
<div className={cn('w-10 h-10 rounded-xl flex items-center justify-center', o.bg)}> <div className={cn('w-10 h-10 rounded-xl flex items-center justify-center', o.bg)}>
<Icon size={20} className={o.color} /> <Icon size={20} className={o.color} />
</div> </div>
<div> <div>
<span className="text-sm font-semibold text-[#e2e5eb] block">{o.label}</span> <span className="text-sm font-semibold text-foreground block">{o.label}</span>
<span className="text-xs text-[#848b9b]">{o.description}</span> <span className="text-xs text-muted-foreground">{o.description}</span>
</div> </div>
</button> </button>
) )
@@ -261,14 +261,14 @@ export function ConcludeSessionModal({
</div> </div>
<button <button
onClick={() => setStep('select-outcome')} onClick={() => setStep('select-outcome')}
className="text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="text-xs text-muted-foreground hover:text-foreground transition-colors"
> >
Change Change
</button> </button>
</div> </div>
<div> <div>
<label className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-[#848b9b] block mb-2"> <label className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground block mb-2">
Additional Notes (optional) Additional Notes (optional)
</label> </label>
<textarea <textarea
@@ -282,7 +282,7 @@ export function ConcludeSessionModal({
: 'What still needs to be done, where you left off...' : 'What still needs to be done, where you left off...'
} }
rows={4} rows={4}
className="w-full resize-none rounded-xl border bg-[#14161d] text-[#e2e5eb] text-sm placeholder:text-[#848b9b] px-4 py-3 focus:outline-hidden focus:border-primary/30" className="w-full resize-none rounded-xl border bg-card text-foreground text-sm placeholder:text-muted-foreground px-4 py-3 focus:outline-hidden focus:border-primary/30"
style={{ borderColor: 'var(--glass-border)' }} style={{ borderColor: 'var(--glass-border)' }}
/> />
</div> </div>
@@ -308,16 +308,16 @@ export function ConcludeSessionModal({
{/* Generated summary */} {/* Generated summary */}
<div <div
className="rounded-xl border p-5 bg-[#14161d]" className="rounded-xl border p-5 bg-card"
style={{ borderColor: 'var(--glass-border)' }} style={{ borderColor: 'var(--glass-border)' }}
> >
<div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-[#848b9b] flex items-center gap-1.5"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground flex items-center gap-1.5">
<Sparkles size={10} className="text-[#22d3ee]" /> <Sparkles size={10} className="text-primary" />
Generated Ticket Notes Generated Ticket Notes
</span> </span>
</div> </div>
<div className="prose-sm text-[#e2e5eb]"> <div className="prose-sm text-foreground">
<MarkdownContent content={summary} className="text-[0.8125rem] leading-relaxed" /> <MarkdownContent content={summary} className="text-[0.8125rem] leading-relaxed" />
</div> </div>
</div> </div>
@@ -335,7 +335,7 @@ export function ConcludeSessionModal({
<div /> <div />
<button <button
onClick={onClose} onClick={onClose}
className="px-4 py-2 rounded-lg text-sm text-[#848b9b] hover:text-[#e2e5eb] bg-[#191c25] border border-[#1e2130] hover:border-[#2a2f3d] transition-all" className="px-4 py-2 rounded-lg text-sm text-muted-foreground hover:text-foreground bg-input border border-border hover:border-border-hover transition-all"
> >
Cancel Cancel
</button> </button>
@@ -346,14 +346,14 @@ export function ConcludeSessionModal({
<> <>
<button <button
onClick={() => setStep('select-outcome')} onClick={() => setStep('select-outcome')}
className="px-4 py-2 rounded-lg text-sm text-[#848b9b] hover:text-[#e2e5eb] bg-[#191c25] border border-[#1e2130] hover:border-[#2a2f3d] transition-all" className="px-4 py-2 rounded-lg text-sm text-muted-foreground hover:text-foreground bg-input border border-border hover:border-border-hover transition-all"
> >
Back Back
</button> </button>
<button <button
onClick={handleGenerate} onClick={handleGenerate}
disabled={generating} disabled={generating}
className="flex items-center gap-2 bg-[#22d3ee] text-white font-semibold text-sm rounded-lg px-5 py-2.5 hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50" className="flex items-center gap-2 bg-primary text-white font-semibold text-sm rounded-lg px-5 py-2.5 hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50"
> >
{generating ? ( {generating ? (
<> <>
@@ -390,7 +390,7 @@ export function ConcludeSessionModal({
'flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-semibold transition-all', 'flex items-center gap-2 px-4 py-2.5 rounded-lg text-sm font-semibold transition-all',
copied copied
? 'bg-emerald-400/15 text-emerald-400 border border-emerald-400/30' ? 'bg-emerald-400/15 text-emerald-400 border border-emerald-400/30'
: 'bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]' : 'bg-primary text-white hover:brightness-110 active:scale-[0.98]'
)} )}
> >
{copied ? ( {copied ? (
@@ -407,7 +407,7 @@ export function ConcludeSessionModal({
</button> </button>
<button <button
onClick={onClose} onClick={onClose}
className="px-4 py-2.5 rounded-lg text-sm text-[#848b9b] hover:text-[#e2e5eb] bg-[#191c25] border border-[#1e2130] hover:border-[#2a2f3d] transition-all" className="px-4 py-2.5 rounded-lg text-sm text-muted-foreground hover:text-foreground bg-input border border-border hover:border-border-hover transition-all"
> >
Done Done
</button> </button>

View File

@@ -18,24 +18,24 @@ export function SuggestedFlowCard({ flow }: SuggestedFlowCardProps) {
return ( return (
<button <button
onClick={handleClick} onClick={handleClick}
className="w-full text-left card-flat p-3 rounded-xl hover:border-[#2a2f3d] transition-colors group" className="w-full text-left card-flat p-3 rounded-xl hover:border-border-hover transition-colors group"
> >
<div className="flex items-start gap-2"> <div className="flex items-start gap-2">
<Box size={14} className="text-[#22d3ee] mt-0.5 shrink-0" /> <Box size={14} className="text-primary mt-0.5 shrink-0" />
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<span className="text-[0.8125rem] font-medium text-[#e2e5eb] truncate"> <span className="text-[0.8125rem] font-medium text-foreground truncate">
{flow.tree_name} {flow.tree_name}
</span> </span>
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-muted-foreground">
{flow.tree_type} {flow.tree_type}
</span> </span>
</div> </div>
<p className="text-[0.75rem] text-[#848b9b] mt-0.5 line-clamp-2"> <p className="text-[0.75rem] text-muted-foreground mt-0.5 line-clamp-2">
{flow.relevance_snippet} {flow.relevance_snippet}
</p> </p>
</div> </div>
<ArrowRight size={14} className="text-[#848b9b] group-hover:text-[#22d3ee] transition-colors shrink-0 mt-0.5" /> <ArrowRight size={14} className="text-muted-foreground group-hover:text-primary transition-colors shrink-0 mt-0.5" />
</div> </div>
</button> </button>
) )

View File

@@ -53,8 +53,8 @@ export function ActionMenu({ actions, align = 'right' }: ActionMenuProps) {
<button <button
onClick={() => setIsOpen(!isOpen)} onClick={() => setIsOpen(!isOpen)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-2 text-[#848b9b]', 'rounded-md border border-border p-2 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
aria-label="Actions" aria-label="Actions"
> >
@@ -64,7 +64,7 @@ export function ActionMenu({ actions, align = 'right' }: ActionMenuProps) {
{isOpen && ( {isOpen && (
<div <div
className={cn( className={cn(
'absolute z-50 mt-1 min-w-[180px] bg-[#14161d] border border-[#1e2130] rounded-lg p-1', 'absolute z-50 mt-1 min-w-[180px] bg-card border border-border rounded-lg p-1',
align === 'right' ? 'right-0' : 'left-0' align === 'right' ? 'right-0' : 'left-0'
)} )}
> >
@@ -81,7 +81,7 @@ export function ActionMenu({ actions, align = 'right' }: ActionMenuProps) {
? 'cursor-not-allowed opacity-40' ? 'cursor-not-allowed opacity-40'
: action.variant === 'destructive' : action.variant === 'destructive'
? 'text-red-400 hover:bg-accent hover:text-red-300' ? 'text-red-400 hover:bg-accent hover:text-red-300'
: 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
> >
{Icon && <Icon className="h-4 w-4" />} {Icon && <Icon className="h-4 w-4" />}

View File

@@ -9,7 +9,7 @@ export function BrandWordmark({ size = 'sm', className }: BrandWordmarkProps) {
return ( return (
<span <span
className={cn( className={cn(
'font-heading font-bold tracking-tight text-[#f0f2f5]', 'font-heading font-bold tracking-tight text-text-heading',
size === 'sm' ? 'text-xl' : 'text-3xl', size === 'sm' ? 'text-xl' : 'text-3xl',
className className
)} )}

View File

@@ -34,8 +34,8 @@ export function ConfirmDialog({
onClick={onClose} onClick={onClose}
disabled={isLoading} disabled={isLoading}
className={cn( className={cn(
'rounded-xl border border-[#1e2130] px-4 py-2 text-sm font-medium', 'rounded-xl border border-border px-4 py-2 text-sm font-medium',
'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]', 'text-muted-foreground hover:bg-accent hover:text-foreground',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}
> >
@@ -49,7 +49,7 @@ export function ConfirmDialog({
'disabled:opacity-50 disabled:cursor-not-allowed', 'disabled:opacity-50 disabled:cursor-not-allowed',
confirmVariant === 'destructive' confirmVariant === 'destructive'
? 'bg-red-400/10 text-red-400 hover:bg-red-400/20 border border-red-400/20' ? 'bg-red-400/10 text-red-400 hover:bg-red-400/20 border border-red-400/20'
: 'bg-[#22d3ee] text-white hover:brightness-110' : 'bg-primary text-white hover:brightness-110'
)} )}
> >
{isLoading ? 'Processing...' : confirmLabel} {isLoading ? 'Processing...' : confirmLabel}
@@ -57,7 +57,7 @@ export function ConfirmDialog({
</div> </div>
} }
> >
<p className="text-sm text-[#848b9b]">{message}</p> <p className="text-sm text-muted-foreground">{message}</p>
</Modal> </Modal>
) )
} }

View File

@@ -71,12 +71,12 @@ export function ContextMenu({ position, items, onClose }: ContextMenuProps) {
left: position.x, left: position.x,
top: position.y, top: position.y,
}} }}
className="min-w-[200px] rounded-xl border border-[#1e2130] bg-[#14161d] p-1 shadow-lg" className="min-w-[200px] rounded-xl border border-border bg-card p-1 shadow-lg"
> >
{items.map((item) => ( {items.map((item) => (
<div key={item.id}> <div key={item.id}>
{item.separator && ( {item.separator && (
<div className="my-1 border-t border-[#1e2130]" /> <div className="my-1 border-t border-border" />
)} )}
<button <button
onClick={() => { onClick={() => {
@@ -87,11 +87,11 @@ export function ContextMenu({ position, items, onClose }: ContextMenuProps) {
'flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm transition-colors', 'flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm transition-colors',
item.variant === 'danger' item.variant === 'danger'
? 'text-rose-400 hover:bg-rose-500/10' ? 'text-rose-400 hover:bg-rose-500/10'
: 'text-[#e2e5eb] hover:bg-[#1e2130]' : 'text-foreground hover:bg-border'
)} )}
> >
{item.icon && ( {item.icon && (
<span className="flex h-4 w-4 items-center justify-center text-[#848b9b]"> <span className="flex h-4 w-4 items-center justify-center text-muted-foreground">
{item.icon} {item.icon}
</span> </span>
)} )}

View File

@@ -65,7 +65,7 @@ export function CreateFlowDropdown({
<div className={cn('relative', className)}> <div className={cn('relative', className)}>
<button <button
onClick={() => setShowMenu(!showMenu)} onClick={() => setShowMenu(!showMenu)}
className="flex items-center gap-2 rounded-lg bg-[#22d3ee] px-4 py-2 text-sm font-semibold text-white hover:brightness-110 transition-opacity" className="flex items-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-semibold text-white hover:brightness-110 transition-opacity"
> >
<Plus size={16} /> <Plus size={16} />
{label} {label}
@@ -74,17 +74,17 @@ export function CreateFlowDropdown({
{showMenu && ( {showMenu && (
<> <>
<div className="fixed inset-0 z-10" onClick={() => setShowMenu(false)} /> <div className="fixed inset-0 z-10" onClick={() => setShowMenu(false)} />
<div className="absolute right-0 z-20 mt-1 w-64 rounded-lg border border-[#1e2130] bg-[#14161d] p-1 shadow-xl"> <div className="absolute right-0 z-20 mt-1 w-64 rounded-lg border border-border bg-card p-1 shadow-xl">
{/* Troubleshooting */} {/* Troubleshooting */}
<Link <Link
to="/trees/new" to="/trees/new"
onClick={() => setShowMenu(false)} onClick={() => setShowMenu(false)}
className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-[#e2e5eb] hover:bg-accent" className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-foreground hover:bg-accent"
> >
<FolderTree className="h-4 w-4 text-[#848b9b]" /> <FolderTree className="h-4 w-4 text-muted-foreground" />
<div className="flex-1"> <div className="flex-1">
<div className="font-medium">Troubleshooting Tree</div> <div className="font-medium">Troubleshooting Tree</div>
<div className="text-xs text-[#848b9b]">Branching decision flow</div> <div className="text-xs text-muted-foreground">Branching decision flow</div>
</div> </div>
</Link> </Link>
{aiEnabled && ( {aiEnabled && (
@@ -95,27 +95,27 @@ export function CreateFlowDropdown({
setAiPromptFlowType('troubleshooting') setAiPromptFlowType('troubleshooting')
setAiPromptOpen(true) setAiPromptOpen(true)
}} }}
className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-[#e2e5eb] hover:bg-accent" className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-foreground hover:bg-accent"
> >
<Sparkles className="h-3.5 w-3.5 text-[#22d3ee] ml-0.5" /> <Sparkles className="h-3.5 w-3.5 text-primary ml-0.5" />
<div className="text-left"> <div className="text-left">
<div className="text-xs text-[#22d3ee] font-medium">Build with Flow Assist</div> <div className="text-xs text-primary font-medium">Build with Flow Assist</div>
</div> </div>
</button> </button>
)} )}
<div className="my-1 border-t border-[#1e2130]" /> <div className="my-1 border-t border-border" />
{/* Procedural */} {/* Procedural */}
<Link <Link
to="/flows/new" to="/flows/new"
onClick={() => setShowMenu(false)} onClick={() => setShowMenu(false)}
className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-[#e2e5eb] hover:bg-accent" className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-foreground hover:bg-accent"
> >
<ListOrdered className="h-4 w-4 text-[#848b9b]" /> <ListOrdered className="h-4 w-4 text-muted-foreground" />
<div className="flex-1"> <div className="flex-1">
<div className="font-medium">Procedural Flow</div> <div className="font-medium">Procedural Flow</div>
<div className="text-xs text-[#848b9b]">Step-by-step procedure</div> <div className="text-xs text-muted-foreground">Step-by-step procedure</div>
</div> </div>
</Link> </Link>
{aiEnabled && ( {aiEnabled && (
@@ -126,27 +126,27 @@ export function CreateFlowDropdown({
setAiPromptFlowType('procedural') setAiPromptFlowType('procedural')
setAiPromptOpen(true) setAiPromptOpen(true)
}} }}
className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-[#e2e5eb] hover:bg-accent" className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-foreground hover:bg-accent"
> >
<Sparkles className="h-3.5 w-3.5 text-[#22d3ee] ml-0.5" /> <Sparkles className="h-3.5 w-3.5 text-primary ml-0.5" />
<div className="text-left"> <div className="text-left">
<div className="text-xs text-[#22d3ee] font-medium">Build with Flow Assist</div> <div className="text-xs text-primary font-medium">Build with Flow Assist</div>
</div> </div>
</button> </button>
)} )}
<div className="my-1 border-t border-[#1e2130]" /> <div className="my-1 border-t border-border" />
{/* Maintenance */} {/* Maintenance */}
<Link <Link
to="/flows/new?type=maintenance" to="/flows/new?type=maintenance"
onClick={() => setShowMenu(false)} onClick={() => setShowMenu(false)}
className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-[#e2e5eb] hover:bg-accent" className="flex items-center gap-3 rounded-md px-3 py-2.5 text-sm text-foreground hover:bg-accent"
> >
<Wrench className="h-4 w-4 text-amber-400" /> <Wrench className="h-4 w-4 text-amber-400" />
<div className="flex-1"> <div className="flex-1">
<div className="font-medium">Maintenance Flow</div> <div className="font-medium">Maintenance Flow</div>
<div className="text-xs text-[#848b9b]">Scheduled multi-target tasks</div> <div className="text-xs text-muted-foreground">Scheduled multi-target tasks</div>
</div> </div>
</Link> </Link>
{aiEnabled && ( {aiEnabled && (
@@ -157,11 +157,11 @@ export function CreateFlowDropdown({
setAiPromptFlowType('maintenance') setAiPromptFlowType('maintenance')
setAiPromptOpen(true) setAiPromptOpen(true)
}} }}
className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-[#e2e5eb] hover:bg-accent" className="flex w-full items-center gap-3 rounded-md px-3 py-2 text-sm text-foreground hover:bg-accent"
> >
<Sparkles className="h-3.5 w-3.5 text-[#22d3ee] ml-0.5" /> <Sparkles className="h-3.5 w-3.5 text-primary ml-0.5" />
<div className="text-left"> <div className="text-left">
<div className="text-xs text-[#22d3ee] font-medium">Build with Flow Assist</div> <div className="text-xs text-primary font-medium">Build with Flow Assist</div>
</div> </div>
</button> </button>
)} )}

View File

@@ -31,17 +31,17 @@ export function EmptyState({
</div> </div>
)} )}
{!illustration && icon && ( {!illustration && icon && (
<div className="mb-4 text-[#848b9b]">{icon}</div> <div className="mb-4 text-muted-foreground">{icon}</div>
)} )}
<h3 className="text-lg font-semibold text-[#e2e5eb]">{title}</h3> <h3 className="text-lg font-semibold text-foreground">{title}</h3>
{description && ( {description && (
<p className="mt-2 max-w-sm text-sm text-[#848b9b]">{description}</p> <p className="mt-2 max-w-sm text-sm text-muted-foreground">{description}</p>
)} )}
{action && <div className="mt-4">{action}</div>} {action && <div className="mt-4">{action}</div>}
{learnMoreLink && ( {learnMoreLink && (
<Link <Link
to={learnMoreLink} to={learnMoreLink}
className="mt-3 text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="mt-3 text-sm text-muted-foreground hover:text-foreground transition-colors"
> >
{learnMoreText} &rarr; {learnMoreText} &rarr;
</Link> </Link>

View File

@@ -39,10 +39,10 @@ function DefaultFallback({ error, resetError }: FallbackProps) {
<h2 className="mb-2 text-xl font-semibold text-red-400"> <h2 className="mb-2 text-xl font-semibold text-red-400">
Something went wrong Something went wrong
</h2> </h2>
<p className="mb-4 text-[#848b9b]"> <p className="mb-4 text-muted-foreground">
An unexpected error occurred. Please try refreshing the page. An unexpected error occurred. Please try refreshing the page.
</p> </p>
<pre className="mb-4 overflow-auto rounded-xl bg-white/5 border border-[#1e2130] p-3 text-left text-xs text-red-400"> <pre className="mb-4 overflow-auto rounded-xl bg-white/5 border border-border p-3 text-left text-xs text-red-400">
{error.message} {error.message}
</pre> </pre>
<div className="flex justify-center gap-3"> <div className="flex justify-center gap-3">

View File

@@ -5,7 +5,7 @@ interface InfoTipProps {
export function InfoTip({ text }: InfoTipProps) { export function InfoTip({ text }: InfoTipProps) {
return ( return (
<span <span
className="inline-flex items-center justify-center h-3.5 w-3.5 rounded-full border border-muted-foreground/40 text-[9px] text-[#848b9b] cursor-help shrink-0" className="inline-flex items-center justify-center h-3.5 w-3.5 rounded-full border border-muted-foreground/40 text-[9px] text-muted-foreground cursor-help shrink-0"
title={text} title={text}
> >
i i

View File

@@ -134,7 +134,7 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md', a
<div <div
ref={modalRef} ref={modalRef}
className={cn( className={cn(
'relative flex w-full flex-col border border-[#1e2130] bg-[#14161d] shadow-lg', 'relative flex w-full flex-col border border-border bg-card shadow-lg',
'animate-scale-in transition-all duration-200', 'animate-scale-in transition-all duration-200',
isFullScreen isFullScreen
? 'fixed inset-4 max-w-none w-auto h-auto rounded-2xl' ? 'fixed inset-4 max-w-none w-auto h-auto rounded-2xl'
@@ -145,8 +145,8 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md', a
)} )}
> >
{/* Header - Fixed at top */} {/* Header - Fixed at top */}
<div className="flex shrink-0 items-center justify-between border-b border-[#1e2130] px-4 py-3 sm:px-6 sm:py-4"> <div className="flex shrink-0 items-center justify-between border-b border-border px-4 py-3 sm:px-6 sm:py-4">
<h2 id="modal-title" className="text-lg font-semibold text-[#e2e5eb]"> <h2 id="modal-title" className="text-lg font-semibold text-foreground">
{title} {title}
</h2> </h2>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
@@ -154,7 +154,7 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md', a
<button <button
type="button" type="button"
onClick={toggleFullScreen} onClick={toggleFullScreen}
className="rounded-md p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
title={isFullScreen ? 'Exit full screen' : 'Full screen'} title={isFullScreen ? 'Exit full screen' : 'Full screen'}
> >
{isFullScreen {isFullScreen
@@ -166,8 +166,8 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md', a
<button <button
onClick={onClose} onClick={onClose}
className={cn( className={cn(
'rounded-md p-1.5 text-[#848b9b] transition-colors sm:p-1', 'rounded-md p-1.5 text-muted-foreground transition-colors sm:p-1',
'hover:bg-accent hover:text-[#e2e5eb]', 'hover:bg-accent hover:text-foreground',
'focus:outline-hidden focus:ring-2 focus:ring-primary/20' 'focus:outline-hidden focus:ring-2 focus:ring-primary/20'
)} )}
aria-label="Close modal" aria-label="Close modal"
@@ -184,7 +184,7 @@ export function Modal({ isOpen, onClose, title, children, footer, size = 'md', a
{/* Footer - Fixed at bottom */} {/* Footer - Fixed at bottom */}
{footer && ( {footer && (
<div className="shrink-0 border-t border-[#1e2130] px-4 py-3 sm:px-6 sm:py-4"> <div className="shrink-0 border-t border-border px-4 py-3 sm:px-6 sm:py-4">
{footer} {footer}
</div> </div>
)} )}

View File

@@ -25,11 +25,11 @@ export function PageHeader({
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
{icon && <div className="shrink-0">{icon}</div>} {icon && <div className="shrink-0">{icon}</div>}
<div> <div>
<h1 className={cn('text-2xl font-bold font-heading text-[#e2e5eb]', titleClassName)}> <h1 className={cn('text-2xl font-bold font-heading text-foreground', titleClassName)}>
{title} {title}
</h1> </h1>
{description && ( {description && (
<p className={cn('mt-1 text-sm text-[#848b9b]', descriptionClassName)}> <p className={cn('mt-1 text-sm text-muted-foreground', descriptionClassName)}>
{description} {description}
</p> </p>
)} )}

View File

@@ -5,7 +5,7 @@ export function PageLoader() {
<div className="flex h-full items-center justify-center"> <div className="flex h-full items-center justify-center">
<div className="flex flex-col items-center gap-4"> <div className="flex flex-col items-center gap-4">
<Spinner size="lg" /> <Spinner size="lg" />
<p className="text-sm text-[#848b9b]">Loading&hellip;</p> <p className="text-sm text-muted-foreground">Loading&hellip;</p>
</div> </div>
</div> </div>
) )

View File

@@ -19,7 +19,7 @@ export function PasswordInput({ className, ...props }: PasswordInputProps) {
<button <button
type="button" type="button"
onClick={() => setVisible((v) => !v)} onClick={() => setVisible((v) => !v)}
className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="absolute right-2 top-1/2 -translate-y-1/2 rounded p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
tabIndex={-1} tabIndex={-1}
title={visible ? 'Hide password' : 'Show password'} title={visible ? 'Hide password' : 'Show password'}
> >

View File

@@ -233,7 +233,7 @@ export function RichTextInput({
rows={rows} rows={rows}
disabled={disabled} disabled={disabled}
className={cn( className={cn(
'w-full bg-[#14161d] border border-[#1e2130] rounded-xl p-3 text-sm text-[#e2e5eb] placeholder:text-[#848b9b]', 'w-full bg-card border border-border rounded-xl p-3 text-sm text-foreground placeholder:text-muted-foreground',
'focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none transition-colors', 'focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none transition-colors',
isDragOver && 'border-primary/50 bg-primary/5', isDragOver && 'border-primary/50 bg-primary/5',
disabled && 'opacity-50 cursor-not-allowed' disabled && 'opacity-50 cursor-not-allowed'
@@ -243,7 +243,7 @@ export function RichTextInput({
{/* Drag overlay hint */} {/* Drag overlay hint */}
{isDragOver && ( {isDragOver && (
<div className="absolute inset-0 flex items-center justify-center rounded-xl border-2 border-dashed border-primary/50 bg-primary/5 pointer-events-none"> <div className="absolute inset-0 flex items-center justify-center rounded-xl border-2 border-dashed border-primary/50 bg-primary/5 pointer-events-none">
<div className="flex items-center gap-2 text-sm text-[#22d3ee]"> <div className="flex items-center gap-2 text-sm text-primary">
<ImagePlus size={16} /> <ImagePlus size={16} />
Drop image to attach Drop image to attach
</div> </div>
@@ -254,19 +254,19 @@ export function RichTextInput({
{pendingUploads.length > 0 && ( {pendingUploads.length > 0 && (
<div className="flex gap-2 flex-wrap mt-2"> <div className="flex gap-2 flex-wrap mt-2">
{pendingUploads.map((upload) => ( {pendingUploads.map((upload) => (
<div key={upload.id} className="relative w-16 h-16 rounded-lg overflow-hidden border border-[#1e2130]"> <div key={upload.id} className="relative w-16 h-16 rounded-lg overflow-hidden border border-border">
<img src={upload.preview} alt="" className="w-full h-full object-cover" /> <img src={upload.preview} alt="" className="w-full h-full object-cover" />
{upload.status === 'uploading' && ( {upload.status === 'uploading' && (
<div className="absolute inset-0 bg-[#0c0d10]/50 flex items-center justify-center"> <div className="absolute inset-0 bg-background/50 flex items-center justify-center">
<Loader2 size={16} className="animate-spin text-[#22d3ee]" /> <Loader2 size={16} className="animate-spin text-primary" />
</div> </div>
)} )}
{upload.status === 'done' && ( {upload.status === 'done' && (
<button <button
onClick={() => handleRemove(upload.id)} onClick={() => handleRemove(upload.id)}
className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-[#0c0d10]/80 border border-[#1e2130] flex items-center justify-center hover:bg-rose-500/20 transition-colors" className="absolute -top-1 -right-1 w-4 h-4 rounded-full bg-background/80 border border-border flex items-center justify-center hover:bg-rose-500/20 transition-colors"
> >
<X size={10} className="text-[#848b9b]" /> <X size={10} className="text-muted-foreground" />
</button> </button>
)} )}
{upload.status === 'error' && ( {upload.status === 'error' && (
@@ -284,7 +284,7 @@ export function RichTextInput({
{/* Paste hint */} {/* Paste hint */}
{isFocused && !value && pendingUploads.length === 0 && ( {isFocused && !value && pendingUploads.length === 0 && (
<p className="text-[0.625rem] text-[#848b9b]/50 mt-1">Paste screenshots with Ctrl+V</p> <p className="text-[0.625rem] text-muted-foreground/50 mt-1">Paste screenshots with Ctrl+V</p>
)} )}
</div> </div>
) )

View File

@@ -55,12 +55,12 @@ export function RouteError() {
} }
return ( return (
<div className="flex min-h-screen flex-col items-center justify-center bg-[#0c0d10] p-8"> <div className="flex min-h-screen flex-col items-center justify-center bg-background p-8">
<div className="max-w-md text-center"> <div className="max-w-md text-center">
<h1 className="mb-2 text-4xl font-bold text-[#e2e5eb]">Oops!</h1> <h1 className="mb-2 text-4xl font-bold text-foreground">Oops!</h1>
<h2 className="mb-2 text-xl font-semibold text-red-400">{errorMessage}</h2> <h2 className="mb-2 text-xl font-semibold text-red-400">{errorMessage}</h2>
{errorDetails && ( {errorDetails && (
<p className="mb-4 text-[#848b9b]">{errorDetails}</p> <p className="mb-4 text-muted-foreground">{errorDetails}</p>
)} )}
<div className="flex justify-center gap-4"> <div className="flex justify-center gap-4">
<Button variant="secondary" onClick={() => navigate(-1)}> <Button variant="secondary" onClick={() => navigate(-1)}>

View File

@@ -15,7 +15,7 @@ export function Spinner({ size = 'md', className }: SpinnerProps) {
return ( return (
<div <div
className={cn( className={cn(
'animate-spin rounded-full border-[#1e2130] border-t-primary', 'animate-spin rounded-full border-border border-t-primary',
SIZES[size], SIZES[size],
className className
)} )}

View File

@@ -48,14 +48,14 @@ export function StarRating({
sizeClasses[size], sizeClasses[size],
star <= value star <= value
? 'fill-yellow-400 text-yellow-400' ? 'fill-yellow-400 text-yellow-400'
: 'fill-none text-[#848b9b]', : 'fill-none text-muted-foreground',
!readonly && 'hover:text-yellow-300' !readonly && 'hover:text-yellow-300'
)} )}
/> />
</button> </button>
))} ))}
{showCount && ( {showCount && (
<span className="ml-1 text-sm text-[#848b9b]"> <span className="ml-1 text-sm text-muted-foreground">
({value}/5) ({value}/5)
</span> </span>
)} )}

View File

@@ -37,8 +37,8 @@ export function TagBadges({
'rounded-full font-sans text-xs transition-colors', 'rounded-full font-sans text-xs transition-colors',
size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm', size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm',
variant === 'default' variant === 'default'
? 'bg-accent text-[#848b9b] hover:bg-accent' ? 'bg-accent text-muted-foreground hover:bg-accent'
: 'bg-accent/50 text-[#848b9b] hover:bg-accent', : 'bg-accent/50 text-muted-foreground hover:bg-accent',
!onTagClick && 'cursor-default' !onTagClick && 'cursor-default'
)} )}
> >
@@ -50,7 +50,7 @@ export function TagBadges({
className={cn( className={cn(
'rounded-full font-sans text-xs', 'rounded-full font-sans text-xs',
size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm', size === 'sm' ? 'px-2 py-0.5 text-xs' : 'px-2.5 py-1 text-sm',
'bg-accent/50 text-[#848b9b]' 'bg-accent/50 text-muted-foreground'
)} )}
title={tags.slice(maxVisible).join(', ')} title={tags.slice(maxVisible).join(', ')}
> >

View File

@@ -123,10 +123,10 @@ export function TagInput({
<div <div
className={cn( className={cn(
'flex flex-wrap gap-1.5 rounded-xl border px-2 py-1.5', 'flex flex-wrap gap-1.5 rounded-xl border px-2 py-1.5',
'bg-[#14161d] text-[#e2e5eb]', 'bg-card text-foreground',
'focus-within:border-primary focus-within:ring-1 focus-within:ring-primary/20', 'focus-within:border-primary focus-within:ring-1 focus-within:ring-primary/20',
disabled ? 'cursor-not-allowed opacity-50' : '', disabled ? 'cursor-not-allowed opacity-50' : '',
'border-[#1e2130]' 'border-border'
)} )}
onClick={() => inputRef.current?.focus()} onClick={() => inputRef.current?.focus()}
> >
@@ -136,7 +136,7 @@ export function TagInput({
key={tag} key={tag}
className={cn( className={cn(
'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs', 'inline-flex items-center gap-1 rounded-full px-2 py-0.5 text-xs',
'bg-accent text-[#848b9b]' 'bg-accent text-muted-foreground'
)} )}
> >
{tag} {tag}
@@ -184,8 +184,8 @@ export function TagInput({
placeholder={tags.length === 0 ? placeholder : ''} placeholder={tags.length === 0 ? placeholder : ''}
disabled={disabled} disabled={disabled}
className={cn( className={cn(
'flex-1 min-w-[80px] border-0 bg-transparent px-1 py-0.5 text-sm text-[#e2e5eb]', 'flex-1 min-w-[80px] border-0 bg-transparent px-1 py-0.5 text-sm text-foreground',
'placeholder:text-[#848b9b]', 'placeholder:text-muted-foreground',
'focus:outline-hidden focus:ring-0' 'focus:outline-hidden focus:ring-0'
)} )}
/> />
@@ -196,8 +196,8 @@ export function TagInput({
{showSuggestions && suggestions.length > 0 && ( {showSuggestions && suggestions.length > 0 && (
<div <div
className={cn( className={cn(
'absolute z-10 mt-1 w-full rounded-xl border border-[#1e2130]', 'absolute z-10 mt-1 w-full rounded-xl border border-border',
'bg-[#14161d] shadow-lg' 'bg-card shadow-lg'
)} )}
> >
{suggestions.map((suggestion, index) => ( {suggestions.map((suggestion, index) => (
@@ -206,13 +206,13 @@ export function TagInput({
type="button" type="button"
onClick={() => addTag(suggestion.name)} onClick={() => addTag(suggestion.name)}
className={cn( className={cn(
'flex w-full items-center justify-between px-3 py-2 text-sm text-[#848b9b]', 'flex w-full items-center justify-between px-3 py-2 text-sm text-muted-foreground',
'hover:bg-accent', 'hover:bg-accent',
index === selectedIndex && 'bg-accent' index === selectedIndex && 'bg-accent'
)} )}
> >
<span>{suggestion.name}</span> <span>{suggestion.name}</span>
<span className="text-xs text-[#848b9b]"> <span className="text-xs text-muted-foreground">
{suggestion.usage_count} trees {suggestion.usage_count} trees
</span> </span>
</button> </button>
@@ -225,8 +225,8 @@ export function TagInput({
type="button" type="button"
onClick={() => addTag(inputValue)} onClick={() => addTag(inputValue)}
className={cn( className={cn(
'flex w-full items-center gap-2 border-t border-[#1e2130] px-3 py-2 text-sm', 'flex w-full items-center gap-2 border-t border-border px-3 py-2 text-sm',
'hover:bg-accent text-[#e2e5eb]' 'hover:bg-accent text-foreground'
)} )}
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
@@ -237,7 +237,7 @@ export function TagInput({
)} )}
{/* Helper text */} {/* Helper text */}
<p className="mt-1 text-xs text-[#848b9b]"> <p className="mt-1 text-xs text-muted-foreground">
{tags.length}/{maxTags} tags. Press Enter, Tab, comma, or semicolon to add. {tags.length}/{maxTags} tags. Press Enter, Tab, comma, or semicolon to add.
</p> </p>
</div> </div>

View File

@@ -105,12 +105,12 @@ export function CopilotPanel({ isOpen, onClose, treeId, sessionId, currentNodeId
style={{ borderColor: 'var(--glass-border)' }} style={{ borderColor: 'var(--glass-border)' }}
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Sparkles size={16} className="text-[#22d3ee]" /> <Sparkles size={16} className="text-primary" />
<span className="text-sm font-semibold text-[#e2e5eb]">AI Copilot</span> <span className="text-sm font-semibold text-foreground">AI Copilot</span>
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 rounded-lg hover:bg-[#1e2130] text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="p-1.5 rounded-lg hover:bg-border text-muted-foreground hover:text-foreground transition-colors"
> >
<X size={16} /> <X size={16} />
</button> </button>
@@ -123,8 +123,8 @@ export function CopilotPanel({ isOpen, onClose, treeId, sessionId, currentNodeId
<div <div
className={`max-w-[85%] rounded-xl px-3.5 py-2.5 text-[0.8125rem] leading-relaxed ${ className={`max-w-[85%] rounded-xl px-3.5 py-2.5 text-[0.8125rem] leading-relaxed ${
msg.role === 'user' msg.role === 'user'
? 'bg-primary/15 text-[#e2e5eb]' ? 'bg-primary/15 text-foreground'
: 'bg-[#191c25] text-[#e2e5eb] border border-[#1e2130]' : 'bg-input text-foreground border border-border'
}`} }`}
> >
<MarkdownContent content={msg.content} className="text-[0.8125rem] leading-relaxed" /> <MarkdownContent content={msg.content} className="text-[0.8125rem] leading-relaxed" />
@@ -133,8 +133,8 @@ export function CopilotPanel({ isOpen, onClose, treeId, sessionId, currentNodeId
))} ))}
{loading && ( {loading && (
<div className="flex justify-start"> <div className="flex justify-start">
<div className="bg-[#191c25] border border-[#1e2130] rounded-xl px-3.5 py-2.5"> <div className="bg-input border border-border rounded-xl px-3.5 py-2.5">
<Loader2 size={16} className="animate-spin text-[#22d3ee]" /> <Loader2 size={16} className="animate-spin text-primary" />
</div> </div>
</div> </div>
)} )}
@@ -142,7 +142,7 @@ export function CopilotPanel({ isOpen, onClose, treeId, sessionId, currentNodeId
{/* Suggested flows */} {/* Suggested flows */}
{suggestedFlows.length > 0 && ( {suggestedFlows.length > 0 && (
<div className="space-y-2 pt-2"> <div className="space-y-2 pt-2">
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground">
Related Flows Related Flows
</span> </span>
{suggestedFlows.map(flow => ( {suggestedFlows.map(flow => (
@@ -164,19 +164,19 @@ export function CopilotPanel({ isOpen, onClose, treeId, sessionId, currentNodeId
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
placeholder="Ask about this step..." placeholder="Ask about this step..."
rows={1} rows={1}
className="flex-1 resize-none rounded-xl border bg-[#14161d] text-[#e2e5eb] text-[0.8125rem] placeholder:text-[#848b9b] px-3.5 py-2.5 focus:outline-hidden focus:border-primary/30" className="flex-1 resize-none rounded-xl border bg-card text-foreground text-[0.8125rem] placeholder:text-muted-foreground px-3.5 py-2.5 focus:outline-hidden focus:border-primary/30"
style={{ borderColor: 'var(--glass-border)' }} style={{ borderColor: 'var(--glass-border)' }}
disabled={loading || initializing} disabled={loading || initializing}
/> />
<button <button
onClick={handleSend} onClick={handleSend}
disabled={!input.trim() || loading || initializing} disabled={!input.trim() || loading || initializing}
className="bg-[#22d3ee] text-white p-2.5 rounded-xl hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-40" className="bg-primary text-white p-2.5 rounded-xl hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-40"
> >
<Send size={16} /> <Send size={16} />
</button> </button>
</div> </div>
<p className="text-[0.625rem] text-[#848b9b] mt-1.5 px-1">Shift + Enter for a new line</p> <p className="text-[0.625rem] text-muted-foreground mt-1.5 px-1">Shift + Enter for a new line</p>
</div> </div>
</div> </div>
) )

View File

@@ -11,7 +11,7 @@ export function CopilotToggle({ isOpen, onToggle }: CopilotToggleProps) {
return ( return (
<button <button
onClick={onToggle} onClick={onToggle}
className="fixed bottom-6 right-6 z-40 bg-[#22d3ee] text-white p-3.5 rounded-full hover:brightness-110 active:scale-[0.98] transition-all" className="fixed bottom-6 right-6 z-40 bg-primary text-white p-3.5 rounded-full hover:brightness-110 active:scale-[0.98] transition-all"
title="Open AI Copilot" title="Open AI Copilot"
> >
<MessageCircle size={22} /> <MessageCircle size={22} />

View File

@@ -31,11 +31,11 @@ export function ActiveFlowPilotSessions() {
return ( return (
<div className="card-flat"> <div className="card-flat">
<div className="px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}> <div className="px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}>
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">Active Sessions</h3> <h3 className="font-heading text-sm font-bold text-foreground">Active Sessions</h3>
</div> </div>
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 p-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 p-4">
{Array.from({ length: 3 }).map((_, i) => ( {Array.from({ length: 3 }).map((_, i) => (
<div key={i} className="h-24 rounded-xl bg-[#14161d] border border-[#1e2130] animate-pulse" /> <div key={i} className="h-24 rounded-xl bg-card border border-border animate-pulse" />
))} ))}
</div> </div>
</div> </div>
@@ -49,16 +49,16 @@ export function ActiveFlowPilotSessions() {
style={{ borderBottom: '1px solid var(--glass-border)' }} style={{ borderBottom: '1px solid var(--glass-border)' }}
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">Active Sessions</h3> <h3 className="font-heading text-sm font-bold text-foreground">Active Sessions</h3>
{sessions.length > 0 && ( {sessions.length > 0 && (
<span className="inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-[rgba(34,211,238,0.10)] px-1.5 text-[0.625rem] font-bold text-[#22d3ee]"> <span className="inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-accent-dim px-1.5 text-[0.625rem] font-bold text-primary">
{sessions.length} {sessions.length}
</span> </span>
)} )}
</div> </div>
<Link <Link
to="/sessions?filter=active" to="/sessions?filter=active"
className="flex items-center gap-1 text-[0.6875rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1 text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors"
> >
View all <ArrowRight size={10} /> View all <ArrowRight size={10} />
</Link> </Link>
@@ -66,8 +66,8 @@ export function ActiveFlowPilotSessions() {
{sessions.length === 0 ? ( {sessions.length === 0 ? (
<div className="px-5 py-8 text-center"> <div className="px-5 py-8 text-center">
<p className="text-sm text-[#848b9b]">No active sessions</p> <p className="text-sm text-muted-foreground">No active sessions</p>
<p className="mt-1 text-[0.6875rem] text-[#5a6170]">Start typing above to begin troubleshooting</p> <p className="mt-1 text-[0.6875rem] text-text-muted">Start typing above to begin troubleshooting</p>
</div> </div>
) : ( ) : (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 p-4"> <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3 p-4">
@@ -78,23 +78,23 @@ export function ActiveFlowPilotSessions() {
className="card-interactive p-4 text-left" className="card-interactive p-4 text-left"
> >
<div className="flex items-start justify-between gap-2 mb-2"> <div className="flex items-start justify-between gap-2 mb-2">
<Sparkles size={14} className="shrink-0 text-[#22d3ee] mt-0.5" /> <Sparkles size={14} className="shrink-0 text-primary mt-0.5" />
<span <span
className={cn( className={cn(
'font-sans text-xs text-[0.5625rem] uppercase px-1.5 py-0.5 rounded', 'font-sans text-xs text-[0.5625rem] uppercase px-1.5 py-0.5 rounded',
session.confidence_tier === 'guided' && 'bg-emerald-400/10 text-emerald-400', session.confidence_tier === 'guided' && 'bg-emerald-400/10 text-emerald-400',
session.confidence_tier === 'exploring' && 'bg-amber-400/10 text-amber-400', session.confidence_tier === 'exploring' && 'bg-amber-400/10 text-amber-400',
session.confidence_tier === 'discovery' && 'bg-blue-400/10 text-blue-400', session.confidence_tier === 'discovery' && 'bg-blue-400/10 text-blue-400',
!session.confidence_tier && 'bg-[#14161d] text-[#848b9b]', !session.confidence_tier && 'bg-card text-muted-foreground',
)} )}
> >
{session.confidence_tier || 'starting'} {session.confidence_tier || 'starting'}
</span> </span>
</div> </div>
<p className="text-sm font-medium text-[#e2e5eb] truncate"> <p className="text-sm font-medium text-foreground truncate">
{session.problem_summary || 'Session in progress'} {session.problem_summary || 'Session in progress'}
</p> </p>
<div className="mt-2 flex items-center gap-2 text-[0.625rem] text-[#848b9b]"> <div className="mt-2 flex items-center gap-2 text-[0.625rem] text-muted-foreground">
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<Clock size={10} /> <Clock size={10} />
{timeAgo(session.created_at)} {timeAgo(session.created_at)}

View File

@@ -22,15 +22,15 @@ 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-[rgba(34,211,238,0.10)] text-[#22d3ee]' ? 'border-[#22d3ee]/30 bg-accent-dim text-primary'
: 'border-[#1e2130] bg-[#14161d] text-[#848b9b] hover:border-[#1e2130]/80 hover:text-[#e2e5eb]' : 'border-border bg-card text-muted-foreground hover:border-border/80 hover:text-foreground'
)} )}
> >
{f.label} {f.label}
</button> </button>
))} ))}
<div className="mx-1.5 h-5 w-px shrink-0 bg-[#1e2130]" /> <div className="mx-1.5 h-5 w-px shrink-0 bg-border" />
<button className="flex shrink-0 items-center gap-1.5 rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-1.5 text-[0.8125rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors"> <button className="flex shrink-0 items-center gap-1.5 rounded-lg border border-border bg-card px-3 py-1.5 text-[0.8125rem] text-muted-foreground hover:text-foreground transition-colors">
<Filter size={14} /> <Filter size={14} />
More Filters More Filters
</button> </button>

View File

@@ -25,10 +25,10 @@ export function KnowledgeBaseCards() {
className="flex items-center justify-between px-5 py-3" className="flex items-center justify-between px-5 py-3"
style={{ borderBottom: '1px solid var(--glass-border)' }} style={{ borderBottom: '1px solid var(--glass-border)' }}
> >
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">Knowledge Base</h3> <h3 className="font-heading text-sm font-bold text-foreground">Knowledge Base</h3>
<button <button
onClick={() => navigate('/trees')} onClick={() => navigate('/trees')}
className="flex items-center gap-1 text-[0.6875rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1 text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors"
> >
Browse <ArrowRight size={10} /> Browse <ArrowRight size={10} />
</button> </button>
@@ -41,8 +41,8 @@ export function KnowledgeBaseCards() {
className="flex flex-col items-center gap-2 py-5 hover:bg-[rgba(255,255,255,0.02)] transition-colors" className="flex flex-col items-center gap-2 py-5 hover:bg-[rgba(255,255,255,0.02)] transition-colors"
> >
<item.icon size={20} style={{ color: item.color }} /> <item.icon size={20} style={{ color: item.color }} />
<p className="font-heading text-xl font-extrabold text-[#e2e5eb]">{item.value}</p> <p className="font-heading text-xl font-extrabold text-foreground">{item.value}</p>
<p className="font-sans text-xs text-[0.5625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <p className="font-sans text-xs text-[0.5625rem] uppercase tracking-[0.1em] text-muted-foreground">
{item.label} {item.label}
</p> </p>
</button> </button>

View File

@@ -73,7 +73,7 @@ export function OnboardingChecklist() {
{/* Progress bar */} {/* Progress bar */}
<div className="h-1 w-full bg-[rgba(255,255,255,0.04)]"> <div className="h-1 w-full bg-[rgba(255,255,255,0.04)]">
<div <div
className="h-full bg-[#22d3ee] transition-all duration-500 ease-out" className="h-full bg-primary transition-all duration-500 ease-out"
style={{ width: `${progressPercent}%` }} style={{ width: `${progressPercent}%` }}
/> />
</div> </div>
@@ -82,15 +82,15 @@ export function OnboardingChecklist() {
{/* Header */} {/* Header */}
<div className="flex items-center justify-between mb-3"> <div className="flex items-center justify-between mb-3">
<div> <div>
<p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Getting Started Getting Started
</p> </p>
<p className="text-sm text-[#e2e5eb] mt-0.5"> <p className="text-sm text-foreground mt-0.5">
{isAllDone ? ( {isAllDone ? (
<span className="text-[#67e8f9] font-semibold">You're all set!</span> <span className="text-accent-text font-semibold">You're all set!</span>
) : ( ) : (
<span> <span>
<span className="text-[#67e8f9] font-semibold">{completedCount}</span> <span className="text-accent-text font-semibold">{completedCount}</span>
{' '}of {totalCount} complete {' '}of {totalCount} complete
</span> </span>
)} )}
@@ -98,7 +98,7 @@ export function OnboardingChecklist() {
</div> </div>
<button <button
onClick={handleDismiss} onClick={handleDismiss}
className="rounded-md p-1 text-[#848b9b] hover:text-[#e2e5eb] hover:bg-[rgba(255,255,255,0.04)] transition-colors" className="rounded-md p-1 text-muted-foreground hover:text-foreground hover:bg-[rgba(255,255,255,0.04)] transition-colors"
aria-label="Dismiss onboarding checklist" aria-label="Dismiss onboarding checklist"
> >
<X size={16} /> <X size={16} />
@@ -126,8 +126,8 @@ export function OnboardingChecklist() {
className={cn( className={cn(
'flex h-5 w-5 shrink-0 items-center justify-center rounded-md border transition-colors', 'flex h-5 w-5 shrink-0 items-center justify-center rounded-md border transition-colors',
done done
? 'bg-[#22d3ee] border-transparent' ? 'bg-primary border-transparent'
: 'border-[#1e2130]' : 'border-border'
)} )}
> >
{done && <Check size={12} className="text-white" />} {done && <Check size={12} className="text-white" />}
@@ -138,8 +138,8 @@ export function OnboardingChecklist() {
className={cn( className={cn(
'flex-1', 'flex-1',
done done
? 'text-[#848b9b] line-through' ? 'text-muted-foreground line-through'
: 'text-[#e2e5eb]' : 'text-foreground'
)} )}
> >
{item.label} {item.label}
@@ -147,7 +147,7 @@ export function OnboardingChecklist() {
{/* Arrow for incomplete items */} {/* Arrow for incomplete items */}
{!done && ( {!done && (
<ChevronRight size={14} className="text-[#848b9b] shrink-0" /> <ChevronRight size={14} className="text-muted-foreground shrink-0" />
)} )}
</button> </button>
</li> </li>

View File

@@ -19,15 +19,15 @@ export function OpenSessions({ sessions }: OpenSessionsProps) {
return ( return (
<div className="card-flat flex flex-col h-full"> <div className="card-flat flex flex-col h-full">
<div className="flex items-center justify-between px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}> <div className="flex items-center justify-between px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}>
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">My Open Sessions</h3> <h3 className="font-heading text-sm font-bold text-foreground">My Open Sessions</h3>
<Link to="/sessions" className="text-[0.6875rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors"> <Link to="/sessions" className="text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors">
View All View All
</Link> </Link>
</div> </div>
<div className="flex-1 flex flex-col"> <div className="flex-1 flex flex-col">
{sessions.length === 0 ? ( {sessions.length === 0 ? (
<div className="flex-1 flex items-center justify-center"> <div className="flex-1 flex items-center justify-center">
<p className="text-sm text-[#848b9b]">No open sessions</p> <p className="text-sm text-muted-foreground">No open sessions</p>
</div> </div>
) : ( ) : (
sessions.map((session, i) => ( sessions.map((session, i) => (
@@ -40,8 +40,8 @@ export function OpenSessions({ sessions }: OpenSessionsProps) {
> >
<span className="h-2 w-2 shrink-0 rounded-full bg-amber-400" /> <span className="h-2 w-2 shrink-0 rounded-full bg-amber-400" />
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="text-sm text-[#e2e5eb] truncate">{session.treeName}</div> <div className="text-sm text-foreground truncate">{session.treeName}</div>
<div className="text-[0.6875rem] text-[#848b9b]"> <div className="text-[0.6875rem] text-muted-foreground">
{session.stepNumber && session.totalSteps {session.stepNumber && session.totalSteps
? `Step ${session.stepNumber} of ${session.totalSteps}` ? `Step ${session.stepNumber} of ${session.totalSteps}`
: 'In progress'} : 'In progress'}
@@ -52,7 +52,7 @@ export function OpenSessions({ sessions }: OpenSessionsProps) {
<Link <Link
to={getTreeNavigatePath(session.treeId, session.treeType)} to={getTreeNavigatePath(session.treeId, session.treeType)}
state={{ sessionId: session.id }} state={{ sessionId: session.id }}
className="shrink-0 rounded-lg bg-[#22d3ee] px-3 py-1 text-[0.6875rem] font-medium text-white hover:brightness-110 transition-opacity" className="shrink-0 rounded-lg bg-primary px-3 py-1 text-[0.6875rem] font-medium text-white hover:brightness-110 transition-opacity"
> >
Resume Resume
</Link> </Link>

View File

@@ -37,7 +37,7 @@ export function PendingEscalations() {
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<AlertTriangle size={14} className="text-amber-400" /> <AlertTriangle size={14} className="text-amber-400" />
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]"> <h3 className="font-heading text-sm font-bold text-foreground">
Pending Escalations Pending Escalations
<span className="ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-amber-400/10 px-1.5 text-[0.625rem] font-bold text-amber-400"> <span className="ml-2 inline-flex h-5 min-w-5 items-center justify-center rounded-full bg-amber-400/10 px-1.5 text-[0.625rem] font-bold text-amber-400">
{escalations.length} {escalations.length}
@@ -46,7 +46,7 @@ export function PendingEscalations() {
</div> </div>
<Link <Link
to="/escalations" to="/escalations"
className="text-[0.6875rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors"
> >
View all View all
</Link> </Link>
@@ -64,10 +64,10 @@ export function PendingEscalations() {
> >
<span className="h-2 w-2 shrink-0 rounded-full bg-amber-400 animate-pulse" /> <span className="h-2 w-2 shrink-0 rounded-full bg-amber-400 animate-pulse" />
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="text-sm text-[#e2e5eb] truncate"> <div className="text-sm text-foreground truncate">
{esc.problem_summary || 'Escalated session'} {esc.problem_summary || 'Escalated session'}
</div> </div>
<div className="text-[0.6875rem] text-[#848b9b]"> <div className="text-[0.6875rem] text-muted-foreground">
{esc.problem_domain || 'General'} {esc.problem_domain || 'General'}
<span className="mx-1.5 text-[var(--text-dimmed)]">&middot;</span> <span className="mx-1.5 text-[var(--text-dimmed)]">&middot;</span>
<span className="font-sans text-xs">{timeAgo(esc.created_at)}</span> <span className="font-sans text-xs">{timeAgo(esc.created_at)}</span>

View File

@@ -74,14 +74,14 @@ export function PerformanceCards() {
style={{ animationDelay: `${400 + i * 60}ms` }} style={{ animationDelay: `${400 + i * 60}ms` }}
> >
<div className="flex items-center justify-between mb-2"> <div className="flex items-center justify-between mb-2">
<p className="font-sans text-xs text-[0.5625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <p className="font-sans text-xs text-[0.5625rem] uppercase tracking-[0.1em] text-muted-foreground">
{card.label} {card.label}
</p> </p>
<card.icon size={14} style={{ color: card.iconColor }} /> <card.icon size={14} style={{ color: card.iconColor }} />
</div> </div>
<p className={cn( <p className={cn(
'font-heading text-2xl font-extrabold tracking-tight', 'font-heading text-2xl font-extrabold tracking-tight',
card.highlight ? 'text-[#67e8f9]' : 'text-[#e2e5eb]' card.highlight ? 'text-accent-text' : 'text-foreground'
)}> )}>
{card.value} {card.value}
</p> </p>

View File

@@ -32,7 +32,7 @@ export function PreparedSessions() {
<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-cyan-400" />
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb]">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-cyan-400/20 text-[0.625rem] font-bold text-cyan-400">
{sessions.length} {sessions.length}
</span> </span>
@@ -51,13 +51,13 @@ export function PreparedSessions() {
key={session.id} key={session.id}
onClick={() => handleStart(session)} onClick={() => handleStart(session)}
className={cn( className={cn(
'group flex w-full items-center justify-between gap-3 rounded-lg border border-[#1e2130] 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-cyan-500/30 hover:bg-cyan-500/5'
)} )}
> >
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="text-sm font-medium text-[#e2e5eb] truncate">{flowName}</p> <p className="text-sm font-medium text-foreground truncate">{flowName}</p>
<div className="mt-1 flex items-center gap-3 text-xs text-[#848b9b]"> <div className="mt-1 flex items-center gap-3 text-xs text-muted-foreground">
{session.ticket_number && ( {session.ticket_number && (
<span>{session.ticket_number}</span> <span>{session.ticket_number}</span>
)} )}
@@ -73,7 +73,7 @@ export function PreparedSessions() {
</span> </span>
</div> </div>
</div> </div>
<ArrowRight className="h-4 w-4 shrink-0 text-[#848b9b] opacity-0 transition-opacity group-hover:opacity-100" /> <ArrowRight className="h-4 w-4 shrink-0 text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100" />
</button> </button>
) )
})} })}

View File

@@ -14,7 +14,7 @@ export function QuickActions() {
return ( return (
<div className="card-flat flex flex-col h-full"> <div className="card-flat flex flex-col h-full">
<div className="px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}> <div className="px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}>
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">Quick Actions</h3> <h3 className="font-heading text-sm font-bold text-foreground">Quick Actions</h3>
</div> </div>
<div className="flex-1 flex flex-col justify-between p-3 gap-2"> <div className="flex-1 flex flex-col justify-between p-3 gap-2">
{ACTIONS.map(({ icon: Icon, label, description, href, color }) => ( {ACTIONS.map(({ icon: Icon, label, description, href, color }) => (
@@ -30,8 +30,8 @@ export function QuickActions() {
<Icon size={18} style={{ color }} /> <Icon size={18} style={{ color }} />
</span> </span>
<div className="min-w-0"> <div className="min-w-0">
<div className="text-sm font-medium text-[#e2e5eb]">{label}</div> <div className="text-sm font-medium text-foreground">{label}</div>
<div className="text-[0.6875rem] text-[#848b9b] truncate">{description}</div> <div className="text-[0.6875rem] text-muted-foreground truncate">{description}</div>
</div> </div>
</button> </button>
))} ))}

View File

@@ -21,13 +21,13 @@ export function QuickStats({ stats }: QuickStatsProps) {
className={cn('card-interactive p-4 fade-in')} className={cn('card-interactive p-4 fade-in')}
style={{ animationDelay: `${50 + i * 30}ms` }} style={{ animationDelay: `${50 + i * 30}ms` }}
> >
<p className="font-sans text-xs text-[0.625rem] font-medium uppercase tracking-widest text-[#848b9b]"> <p className="font-sans text-xs text-[0.625rem] font-medium uppercase tracking-widest text-muted-foreground">
{stat.label} {stat.label}
</p> </p>
<p <p
className={cn( className={cn(
'mt-1 font-heading text-2xl font-extrabold tracking-tight', 'mt-1 font-heading text-2xl font-extrabold tracking-tight',
stat.gradient && 'text-[#67e8f9]', stat.gradient && 'text-accent-text',
stat.color stat.color
)} )}
style={stat.color && !stat.color.startsWith('text-') ? { color: stat.color } : undefined} style={stat.color && !stat.color.startsWith('text-') ? { color: stat.color } : undefined}

View File

@@ -26,7 +26,7 @@ export function RecentActivity({ activities = DEFAULT_ACTIVITIES }: RecentActivi
return ( return (
<div className="card-flat"> <div className="card-flat">
<div className="px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}> <div className="px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}>
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">Recent Activity</h3> <h3 className="font-heading text-sm font-bold text-foreground">Recent Activity</h3>
</div> </div>
<div> <div>
{activities.map((item, i) => ( {activities.map((item, i) => (
@@ -45,9 +45,9 @@ export function RecentActivity({ activities = DEFAULT_ACTIVITIES }: RecentActivi
<item.icon size={16} style={{ color: item.iconColor }} /> <item.icon size={16} style={{ color: item.iconColor }} />
</span> </span>
<div className="flex-1 min-w-0 pt-0.5"> <div className="flex-1 min-w-0 pt-0.5">
<p className="text-sm text-[#e2e5eb]">{item.description}</p> <p className="text-sm text-foreground">{item.description}</p>
</div> </div>
<span className="shrink-0 font-sans text-xs text-[0.625rem] text-[#848b9b] pt-1"> <span className="shrink-0 font-sans text-xs text-[0.625rem] text-muted-foreground pt-1">
{item.timestamp} {item.timestamp}
</span> </span>
</div> </div>

View File

@@ -46,10 +46,10 @@ export function RecentFlowPilotSessions() {
className="flex items-center justify-between px-5 py-3" className="flex items-center justify-between px-5 py-3"
style={{ borderBottom: '1px solid var(--glass-border)' }} style={{ borderBottom: '1px solid var(--glass-border)' }}
> >
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">Recent Sessions</h3> <h3 className="font-heading text-sm font-bold text-foreground">Recent Sessions</h3>
<Link <Link
to="/sessions" to="/sessions"
className="flex items-center gap-1 text-[0.6875rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1 text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors"
> >
History <ArrowRight size={10} /> History <ArrowRight size={10} />
</Link> </Link>
@@ -69,11 +69,11 @@ export function RecentFlowPilotSessions() {
> >
<StatusIcon size={14} style={{ color: config.color }} className="shrink-0" /> <StatusIcon size={14} style={{ color: config.color }} className="shrink-0" />
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<p className="text-sm text-[#e2e5eb] truncate"> <p className="text-sm text-foreground truncate">
{session.problem_summary || 'Session'} {session.problem_summary || 'Session'}
</p> </p>
</div> </div>
<span className="shrink-0 font-sans text-xs text-[#848b9b]"> <span className="shrink-0 font-sans text-xs text-muted-foreground">
{timeAgo(session.resolved_at || session.created_at)} {timeAgo(session.resolved_at || session.created_at)}
</span> </span>
</button> </button>

View File

@@ -19,19 +19,19 @@ export function SectionGroup({ title, count, defaultOpen = true, delay = 150, ch
onClick={() => setOpen(!open)} onClick={() => setOpen(!open)}
className="flex w-full items-center gap-2 py-2" className="flex w-full items-center gap-2 py-2"
> >
<span className="h-2 w-2 shrink-0 rounded-full bg-[#22d3ee]" /> <span className="h-2 w-2 shrink-0 rounded-full bg-primary" />
<span className="font-heading text-[0.8125rem] font-bold uppercase tracking-[0.04em] text-[#e2e5eb]"> <span className="font-heading text-[0.8125rem] font-bold uppercase tracking-[0.04em] text-foreground">
{title} {title}
</span> </span>
{count !== undefined && ( {count !== undefined && (
<span className="rounded-full bg-secondary px-2 py-0.5 font-sans text-xs text-[#848b9b]"> <span className="rounded-full bg-secondary px-2 py-0.5 font-sans text-xs text-muted-foreground">
{count} {count}
</span> </span>
)} )}
<div className="flex-1" /> <div className="flex-1" />
<ChevronDown <ChevronDown
size={14} size={14}
className={cn('text-[#848b9b] transition-transform', !open && '-rotate-90')} className={cn('text-muted-foreground transition-transform', !open && '-rotate-90')}
/> />
</button> </button>
{open && <div className="mt-1 space-y-1">{children}</div>} {open && <div className="mt-1 space-y-1">{children}</div>}

View File

@@ -23,8 +23,8 @@ export function SessionsPanel({ sessions, delay = 200 }: SessionsPanelProps) {
return ( return (
<div className="card-flat fade-in" style={{ animationDelay: `${delay}ms` }}> <div className="card-flat fade-in" style={{ animationDelay: `${delay}ms` }}>
<div className="flex items-center justify-between px-4 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}> <div className="flex items-center justify-between px-4 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}>
<h3 className="font-heading text-sm font-semibold text-[#e2e5eb]">Recent Sessions</h3> <h3 className="font-heading text-sm font-semibold text-foreground">Recent Sessions</h3>
<Link to="/sessions" className="text-[0.6875rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors"> <Link to="/sessions" className="text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors">
View All View All
</Link> </Link>
</div> </div>
@@ -47,10 +47,10 @@ export function SessionsPanel({ sessions, delay = 200 }: SessionsPanelProps) {
/> />
{/* Name */} {/* Name */}
<span className="text-sm text-[#e2e5eb] truncate">{session.treeName}</span> <span className="text-sm text-foreground truncate">{session.treeName}</span>
{/* Progress */} {/* Progress */}
<span className="text-[0.6875rem] text-[#848b9b] truncate"> <span className="text-[0.6875rem] text-muted-foreground truncate">
{session.status === 'completed' {session.status === 'completed'
? '✓ Resolved' ? '✓ Resolved'
: session.stepNumber && session.totalSteps : session.stepNumber && session.totalSteps
@@ -59,7 +59,7 @@ export function SessionsPanel({ sessions, delay = 200 }: SessionsPanelProps) {
</span> </span>
{/* Ticket */} {/* Ticket */}
<span className="font-sans text-xs text-[0.6875rem] text-[#848b9b] truncate"> <span className="font-sans text-xs text-[0.6875rem] text-muted-foreground truncate">
{session.ticketNumber || '—'} {session.ticketNumber || '—'}
</span> </span>

View File

@@ -37,7 +37,7 @@ export function StartSessionInput() {
<div className="relative"> <div className="relative">
<Sparkles <Sparkles
size={18} size={18}
className="absolute left-4 top-1/2 -translate-y-1/2 text-[#848b9b]" className="absolute left-4 top-1/2 -translate-y-1/2 text-muted-foreground"
/> />
<input <input
ref={inputRef} ref={inputRef}
@@ -46,7 +46,7 @@ export function StartSessionInput() {
onChange={(e) => setValue(e.target.value)} onChange={(e) => setValue(e.target.value)}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
placeholder="What are you troubleshooting?" placeholder="What are you troubleshooting?"
className="w-full rounded-xl border border-[#1e2130] bg-[#0c0d10] py-3.5 pl-11 pr-4 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-hidden focus:ring-1 focus:ring-primary/20" className="w-full rounded-xl border border-border bg-background py-3.5 pl-11 pr-4 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"
/> />
</div> </div>
<div className="mt-3 flex items-center justify-between"> <div className="mt-3 flex items-center justify-between">
@@ -57,8 +57,8 @@ export function StartSessionInput() {
className={cn( className={cn(
'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors', 'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors',
mode === 'guided' mode === 'guided'
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]' ? 'bg-accent-dim text-foreground'
: 'text-[#848b9b] hover:text-[#e2e5eb]' : 'text-muted-foreground hover:text-foreground'
)} )}
> >
<Sparkles size={12} /> <Sparkles size={12} />
@@ -70,15 +70,15 @@ export function StartSessionInput() {
className={cn( className={cn(
'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors', 'flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium transition-colors',
mode === 'chat' mode === 'chat'
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]' ? 'bg-accent-dim text-foreground'
: 'text-[#848b9b] hover:text-[#e2e5eb]' : 'text-muted-foreground hover:text-foreground'
)} )}
> >
<MessageCircle size={12} /> <MessageCircle size={12} />
Open Chat Open Chat
</button> </button>
</div> </div>
<span className="text-[0.625rem] text-[#848b9b]"> <span className="text-[0.625rem] text-muted-foreground">
Press Enter to start Press Enter to start
</span> </span>
</div> </div>

View File

@@ -30,10 +30,10 @@ export function TeamSummary() {
className="flex items-center justify-between px-5 py-3" className="flex items-center justify-between px-5 py-3"
style={{ borderBottom: '1px solid var(--glass-border)' }} style={{ borderBottom: '1px solid var(--glass-border)' }}
> >
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">Team Summary</h3> <h3 className="font-heading text-sm font-bold text-foreground">Team Summary</h3>
<button <button
onClick={() => navigate('/analytics')} onClick={() => navigate('/analytics')}
className="flex items-center gap-1 text-[0.6875rem] text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1 text-[0.6875rem] text-muted-foreground hover:text-foreground transition-colors"
> >
Manage <ArrowRight size={10} /> Manage <ArrowRight size={10} />
</button> </button>
@@ -46,8 +46,8 @@ export function TeamSummary() {
className="flex flex-col items-center gap-2 py-5 hover:bg-[rgba(255,255,255,0.02)] transition-colors" className="flex flex-col items-center gap-2 py-5 hover:bg-[rgba(255,255,255,0.02)] transition-colors"
> >
<item.icon size={20} style={{ color: item.color }} /> <item.icon size={20} style={{ color: item.color }} />
<p className="font-heading text-xl font-extrabold text-[#e2e5eb]">{item.value}</p> <p className="font-heading text-xl font-extrabold text-foreground">{item.value}</p>
<p className="font-sans text-xs text-[0.5625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <p className="font-sans text-xs text-[0.5625rem] uppercase tracking-[0.1em] text-muted-foreground">
{item.label} {item.label}
</p> </p>
</button> </button>

View File

@@ -33,7 +33,7 @@ export function TreeListItem({
return ( return (
<div <div
onClick={() => navigate(getTreeNavigatePath(id, treeType))} onClick={() => navigate(getTreeNavigatePath(id, treeType))}
className="group grid cursor-pointer items-center gap-3 rounded-lg border border-transparent bg-[#14161d] px-4 py-3 transition-colors hover:border-[#1e2130] hover:bg-[var(--sidebar-hover)]" className="group grid cursor-pointer items-center gap-3 rounded-lg border border-transparent bg-card px-4 py-3 transition-colors hover:border-border hover:bg-[var(--sidebar-hover)]"
style={{ gridTemplateColumns: '40px 1fr 130px 80px 100px 40px' }} style={{ gridTemplateColumns: '40px 1fr 130px 80px 100px 40px' }}
> >
{/* Icon box */} {/* Icon box */}
@@ -46,15 +46,15 @@ export function TreeListItem({
{/* Info */} {/* Info */}
<div className="min-w-0"> <div className="min-w-0">
<p className="font-heading text-sm font-semibold text-[#e2e5eb] truncate">{name}</p> <p className="font-heading text-sm font-semibold text-foreground truncate">{name}</p>
<div className="mt-0.5 flex items-center gap-2"> <div className="mt-0.5 flex items-center gap-2">
{tags.slice(0, 3).map(tag => ( {tags.slice(0, 3).map(tag => (
<span key={tag} className="rounded border border-[#1e2130] bg-secondary px-1.5 py-px font-sans text-xs text-[0.625rem] text-[#848b9b]"> <span key={tag} className="rounded border border-border bg-secondary px-1.5 py-px font-sans text-xs text-[0.625rem] text-muted-foreground">
{tag} {tag}
</span> </span>
))} ))}
{description && tags.length === 0 && ( {description && tags.length === 0 && (
<span className="text-[0.6875rem] text-[#848b9b] truncate">{description}</span> <span className="text-[0.6875rem] text-muted-foreground truncate">{description}</span>
)} )}
</div> </div>
</div> </div>
@@ -64,13 +64,13 @@ export function TreeListItem({
{category && ( {category && (
<> <>
<span className="h-2 w-2 shrink-0 rounded-full" style={{ backgroundColor: categoryColor }} /> <span className="h-2 w-2 shrink-0 rounded-full" style={{ backgroundColor: categoryColor }} />
<span className="font-sans text-xs text-[#848b9b] truncate">{category.name}</span> <span className="font-sans text-xs text-muted-foreground truncate">{category.name}</span>
</> </>
)} )}
</div> </div>
{/* Usage count */} {/* Usage count */}
<div className="text-right font-sans text-xs text-[#848b9b]"> <div className="text-right font-sans text-xs text-muted-foreground">
{usageCount} uses {usageCount} uses
</div> </div>
@@ -85,7 +85,7 @@ export function TreeListItem({
e.stopPropagation() e.stopPropagation()
navigate(getTreeEditorPath(id, treeType)) navigate(getTreeEditorPath(id, treeType))
}} }}
className="flex h-8 w-8 items-center justify-center rounded-md text-[#848b9b] opacity-0 transition-opacity hover:bg-accent group-hover:opacity-100" className="flex h-8 w-8 items-center justify-center rounded-md text-muted-foreground opacity-0 transition-opacity hover:bg-accent group-hover:opacity-100"
> >
<MoreHorizontal size={16} /> <MoreHorizontal size={16} />
</button> </button>

View File

@@ -36,8 +36,8 @@ export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
return ( return (
<div className="card-flat flex flex-col h-full"> <div className="card-flat flex flex-col h-full">
<div className="flex items-center gap-2 px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}> <div className="flex items-center gap-2 px-5 py-3" style={{ borderBottom: '1px solid var(--glass-border)' }}>
<Calendar size={16} className="text-[#848b9b]" /> <Calendar size={16} className="text-muted-foreground" />
<h3 className="font-heading text-sm font-bold text-[#e2e5eb]">This Week</h3> <h3 className="font-heading text-sm font-bold text-foreground">This Week</h3>
</div> </div>
<div className="flex flex-1 min-h-0"> <div className="flex flex-1 min-h-0">
{days.map((day, i) => { {days.map((day, i) => {
@@ -56,10 +56,10 @@ export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
borderBottom: day.isToday ? '2px solid #06b6d4' : '1px solid var(--glass-border)', borderBottom: day.isToday ? '2px solid #06b6d4' : '1px solid var(--glass-border)',
}} }}
> >
<span className={`font-sans text-xs text-[0.625rem] uppercase tracking-widest ${day.isToday ? 'text-cyan-400' : 'text-[#848b9b]'}`}> <span className={`font-sans text-xs text-[0.625rem] uppercase tracking-widest ${day.isToday ? 'text-cyan-400' : 'text-muted-foreground'}`}>
{day.label} {day.label}
</span> </span>
<div className={`text-sm font-heading font-bold ${day.isToday ? 'text-[#e2e5eb]' : 'text-[#848b9b]'}`}> <div className={`text-sm font-heading font-bold ${day.isToday ? 'text-foreground' : 'text-muted-foreground'}`}>
{day.date.getDate()} {day.date.getDate()}
</div> </div>
</div> </div>
@@ -76,8 +76,8 @@ export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
background: 'rgba(255, 255, 255, 0.02)', background: 'rgba(255, 255, 255, 0.02)',
}} }}
> >
<div className="font-medium text-[#e2e5eb] truncate">{event.title}</div> <div className="font-medium text-foreground truncate">{event.title}</div>
<div className="font-sans text-xs text-[0.5625rem] text-[#848b9b]">{event.time}</div> <div className="font-sans text-xs text-[0.5625rem] text-muted-foreground">{event.time}</div>
</div> </div>
)) ))
)} )}

View File

@@ -83,14 +83,14 @@ export function AIPromptDialog({
<button <button
onClick={onClose} onClick={onClose}
disabled={isGenerating} disabled={isGenerating}
className="rounded-[10px] bg-[#191c25] border border-[#1e2130] px-4 py-2 text-sm text-foreground hover:border-[#2a2f3d] transition-colors disabled:opacity-50" className="rounded-[10px] bg-input border border-border px-4 py-2 text-sm text-foreground hover:border-border-hover transition-colors disabled:opacity-50"
> >
Cancel Cancel
</button> </button>
<button <button
onClick={handleGenerate} onClick={handleGenerate}
disabled={!prompt.trim() || isGenerating} disabled={!prompt.trim() || isGenerating}
className="flex items-center gap-2 rounded-lg bg-[#22d3ee] px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50" className="flex items-center gap-2 rounded-lg bg-primary px-4 py-2 text-sm font-semibold text-white hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-50"
> >
{isGenerating ? ( {isGenerating ? (
<> <>

View File

@@ -50,7 +50,7 @@ export function ChatTab({ messages, input, onInputChange, onSend, isLoading }: C
className={`max-w-[85%] rounded-xl px-3.5 py-2.5 text-[0.8125rem] leading-relaxed ${ className={`max-w-[85%] rounded-xl px-3.5 py-2.5 text-[0.8125rem] leading-relaxed ${
msg.role === 'user' msg.role === 'user'
? 'bg-primary/15 text-foreground' ? 'bg-primary/15 text-foreground'
: 'bg-[#191c25] text-foreground border border-[#1e2130]' : 'bg-input text-foreground border border-border'
}`} }`}
> >
<MarkdownContent content={msg.content} className="text-[0.8125rem] leading-relaxed" /> <MarkdownContent content={msg.content} className="text-[0.8125rem] leading-relaxed" />
@@ -59,7 +59,7 @@ export function ChatTab({ messages, input, onInputChange, onSend, isLoading }: C
))} ))}
{isLoading && ( {isLoading && (
<div className="flex justify-start"> <div className="flex justify-start">
<div className="bg-[#191c25] border border-[#1e2130] rounded-xl px-3.5 py-2.5"> <div className="bg-input border border-border rounded-xl px-3.5 py-2.5">
<Loader2 size={16} className="animate-spin text-primary" /> <Loader2 size={16} className="animate-spin text-primary" />
</div> </div>
</div> </div>
@@ -84,7 +84,7 @@ export function ChatTab({ messages, input, onInputChange, onSend, isLoading }: C
<button <button
onClick={onSend} onClick={onSend}
disabled={!input.trim() || isLoading} disabled={!input.trim() || isLoading}
className="bg-[#22d3ee] text-white p-2.5 rounded-xl hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-40" className="bg-primary text-white p-2.5 rounded-xl hover:brightness-110 active:scale-[0.98] transition-all disabled:opacity-40"
> >
<Send size={16} /> <Send size={16} />
</button> </button>

View File

@@ -65,7 +65,7 @@ export function EditorAIPanel({
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
className="p-1.5 rounded-lg hover:bg-[#1e2130] text-muted-foreground hover:text-foreground transition-colors" className="p-1.5 rounded-lg hover:bg-border text-muted-foreground hover:text-foreground transition-colors"
> >
<X size={16} /> <X size={16} />
</button> </button>

View File

@@ -26,7 +26,7 @@ export function SuggestionsTab({ suggestions }: SuggestionsTabProps) {
const config = STATUS_CONFIG[s.status] const config = STATUS_CONFIG[s.status]
const StatusIcon = config.icon const StatusIcon = config.icon
return ( return (
<div key={s.id} className="rounded-lg border border-border bg-[#14161d] px-3 py-2"> <div key={s.id} className="rounded-lg border border-border bg-card px-3 py-2">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground"> <span className="font-label text-[0.625rem] uppercase tracking-widest text-muted-foreground">
{s.action_type.replace(/_/g, ' ')} {s.action_type.replace(/_/g, ' ')}
@@ -39,7 +39,7 @@ export function SuggestionsTab({ suggestions }: SuggestionsTabProps) {
{s.target_node_id && ( {s.target_node_id && (
<p className="mt-1 text-xs text-muted-foreground truncate">Node: {s.target_node_id}</p> <p className="mt-1 text-xs text-muted-foreground truncate">Node: {s.target_node_id}</p>
)} )}
<p className="mt-0.5 font-label text-[0.625rem] text-[#4f5666]"> <p className="mt-0.5 font-label text-[0.625rem] text-text-muted">
{new Date(s.created_at).toLocaleDateString()} {new Date(s.created_at).toLocaleDateString()}
</p> </p>
</div> </div>

View File

@@ -8,11 +8,11 @@ interface AISessionListItemProps {
} }
const STATUS_CONFIG = { const STATUS_CONFIG = {
active: { icon: Clock, color: 'text-[#22d3ee]', label: 'Active' }, active: { icon: Clock, color: 'text-primary', label: 'Active' },
paused: { icon: Pause, color: 'text-amber-400', label: 'Paused' }, paused: { icon: Pause, color: 'text-amber-400', label: 'Paused' },
resolved: { icon: CheckCircle2, color: 'text-emerald-400', label: 'Resolved' }, resolved: { icon: CheckCircle2, color: 'text-emerald-400', label: 'Resolved' },
escalated: { icon: ArrowUpRight, color: 'text-amber-400', label: 'Escalated' }, escalated: { icon: ArrowUpRight, color: 'text-amber-400', label: 'Escalated' },
abandoned: { icon: AlertCircle, color: 'text-[#5a6170]', label: 'Abandoned' }, abandoned: { icon: AlertCircle, color: 'text-text-muted', label: 'Abandoned' },
} as const } as const
export function AISessionListItem({ session }: AISessionListItemProps) { export function AISessionListItem({ session }: AISessionListItemProps) {
@@ -26,12 +26,12 @@ export function AISessionListItem({ session }: AISessionListItemProps) {
> >
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<p className="text-sm font-medium text-[#e2e5eb] truncate"> <p className="text-sm font-medium text-foreground truncate">
{session.problem_summary || 'Untitled session'} {session.problem_summary || 'Untitled session'}
</p> </p>
<div className="mt-1.5 flex items-center gap-3 flex-wrap"> <div className="mt-1.5 flex items-center gap-3 flex-wrap">
{session.problem_domain && ( {session.problem_domain && (
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]"> <span className="font-sans text-xs rounded-md bg-accent-dim px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
{session.problem_domain} {session.problem_domain}
</span> </span>
)} )}
@@ -39,10 +39,10 @@ export function AISessionListItem({ session }: AISessionListItemProps) {
<StatusIcon size={12} /> <StatusIcon size={12} />
{config.label} {config.label}
</span> </span>
<span className="text-xs text-[#848b9b]"> <span className="text-xs text-muted-foreground">
{session.step_count} steps {session.step_count} steps
</span> </span>
<span className="text-xs text-[#5a6170]"> <span className="text-xs text-text-muted">
{new Date(session.created_at).toLocaleDateString(undefined, { {new Date(session.created_at).toLocaleDateString(undefined, {
month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit',
})} })}

View File

@@ -30,12 +30,12 @@ export function ConfidenceIndicator({ tier, score, className }: ConfidenceIndica
return ( return (
<div className={cn('group relative inline-flex items-center gap-2', className)}> <div className={cn('group relative inline-flex items-center gap-2', className)}>
<span className={cn('h-2 w-2 rounded-full', config.color)} /> <span className={cn('h-2 w-2 rounded-full', config.color)} />
<span className="font-sans text-xs text-xs text-[#848b9b]">{config.label}</span> <span className="font-sans text-xs text-xs text-muted-foreground">{config.label}</span>
{/* Tooltip */} {/* Tooltip */}
<div className="pointer-events-none absolute left-0 top-full z-50 mt-2 w-56 rounded-lg border border-[#1e2130] bg-[#14161d] p-3 opacity-0 shadow-lg transition-opacity group-hover:pointer-events-auto group-hover:opacity-100"> <div className="pointer-events-none absolute left-0 top-full z-50 mt-2 w-56 rounded-lg border border-border bg-card p-3 opacity-0 shadow-lg transition-opacity group-hover:pointer-events-auto group-hover:opacity-100">
<p className="text-xs text-[#848b9b]">{config.description}</p> <p className="text-xs text-muted-foreground">{config.description}</p>
<p className="mt-1 font-sans text-xs text-[0.625rem] text-[#5a6170]"> <p className="mt-1 font-sans text-xs text-[0.625rem] text-text-muted">
Confidence: {Math.round(score * 100)}% Confidence: {Math.round(score * 100)}%
</p> </p>
</div> </div>

View File

@@ -43,7 +43,7 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
</div> </div>
<div> <div>
<label className="mb-1.5 block text-sm font-medium text-[#e2e5eb]"> <label className="mb-1.5 block text-sm font-medium text-foreground">
Why are you escalating? Why are you escalating?
</label> </label>
<RichTextInput <RichTextInput
@@ -54,7 +54,7 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
placeholder="e.g. I've exhausted all networking diagnostics and suspect this is a firewall policy issue that requires senior admin access..." placeholder="e.g. I've exhausted all networking diagnostics and suspect this is a firewall policy issue that requires senior admin access..."
rows={4} rows={4}
/> />
<p className="mt-1 text-[0.625rem] text-[#5a6170]"> <p className="mt-1 text-[0.625rem] text-text-muted">
Minimum 5 characters. This will be shown to the engineer who picks up. Minimum 5 characters. This will be shown to the engineer who picks up.
</p> </p>
</div> </div>
@@ -63,7 +63,7 @@ export function EscalateModal({ open, onClose, onEscalate, isProcessing, hasPsaT
<button <button
onClick={handleClose} onClick={handleClose}
disabled={isProcessing} disabled={isProcessing}
className="flex-1 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 min-h-[44px] text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] transition-colors disabled:opacity-50" className="flex-1 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 min-h-[44px] text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] transition-colors disabled:opacity-50"
> >
Cancel Cancel
</button> </button>

View File

@@ -42,7 +42,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
if (isLoading) { if (isLoading) {
return ( return (
<div className="flex items-center justify-center py-12"> <div className="flex items-center justify-center py-12">
<Loader2 size={20} className="animate-spin text-[#848b9b]" /> <Loader2 size={20} className="animate-spin text-muted-foreground" />
</div> </div>
) )
} }
@@ -53,7 +53,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
<p className="text-sm text-rose-400">{error}</p> <p className="text-sm text-rose-400">{error}</p>
<button <button
onClick={loadQueue} onClick={loadQueue}
className="mt-2 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="mt-2 text-xs text-muted-foreground hover:text-foreground transition-colors"
> >
Try again Try again
</button> </button>
@@ -64,11 +64,11 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
if (sessions.length === 0) { if (sessions.length === 0) {
return ( return (
<div className="py-12 text-center"> <div className="py-12 text-center">
<AlertTriangle size={24} className="mx-auto mb-2 text-[#848b9b]/40" /> <AlertTriangle size={24} className="mx-auto mb-2 text-muted-foreground/40" />
<p className="text-sm text-[#848b9b]">No sessions awaiting escalation</p> <p className="text-sm text-muted-foreground">No sessions awaiting escalation</p>
<button <button
onClick={loadQueue} onClick={loadQueue}
className="mt-3 flex items-center gap-1.5 mx-auto text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="mt-3 flex items-center gap-1.5 mx-auto text-xs text-muted-foreground hover:text-foreground transition-colors"
> >
<RefreshCw size={12} /> <RefreshCw size={12} />
Refresh Refresh
@@ -80,12 +80,12 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
return ( return (
<div className="space-y-3"> <div className="space-y-3">
<div className="flex items-center justify-between px-1"> <div className="flex items-center justify-between px-1">
<h3 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170]"> <h3 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted">
Awaiting pickup ({sessions.length}) Awaiting pickup ({sessions.length})
</h3> </h3>
<button <button
onClick={loadQueue} onClick={loadQueue}
className="flex items-center gap-1 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
> >
<RefreshCw size={10} /> <RefreshCw size={10} />
Refresh Refresh
@@ -95,7 +95,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
{sessions.map((session) => ( {sessions.map((session) => (
<div key={session.id} className="card-interactive p-3 sm:p-4 space-y-3"> <div key={session.id} className="card-interactive p-3 sm:p-4 space-y-3">
<div> <div>
<p className="text-sm font-semibold text-[#e2e5eb]"> <p className="text-sm font-semibold text-foreground">
{session.problem_summary || 'Untitled session'} {session.problem_summary || 'Untitled session'}
</p> </p>
{session.escalation_reason && ( {session.escalation_reason && (
@@ -105,9 +105,9 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
)} )}
</div> </div>
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-[#848b9b]"> <div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
{session.problem_domain && ( {session.problem_domain && (
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-[#22d3ee]"> <span className="font-sans text-xs rounded-md bg-accent-dim px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-primary">
{session.problem_domain} {session.problem_domain}
</span> </span>
)} )}
@@ -120,7 +120,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
{new Date(session.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} {new Date(session.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
</span> </span>
{session.psa_ticket_id && ( {session.psa_ticket_id && (
<span className="flex items-center gap-1 text-[#22d3ee]"> <span className="flex items-center gap-1 text-primary">
<Ticket size={10} /> <Ticket size={10} />
#{session.psa_ticket_id} #{session.psa_ticket_id}
</span> </span>
@@ -129,7 +129,7 @@ export function EscalationQueue({ onPickup }: EscalationQueueProps) {
<button <button
onClick={() => handlePickup(session.id)} onClick={() => handlePickup(session.id)}
className="w-full min-h-[44px] rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all" className="w-full min-h-[44px] rounded-lg bg-primary text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all"
> >
Pick Up Session Pick Up Session
</button> </button>

View File

@@ -70,7 +70,7 @@ export function FlowPilotActionBar({
<> <>
{/* Bottom bar — fixed to viewport bottom, works regardless of height chain */} {/* Bottom bar — fixed to viewport bottom, works regardless of height chain */}
<div <div
className="fixed bottom-0 right-0 z-40 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3 border-t border-[#1e2130] bg-[#14161d] px-3 py-3 sm:px-5" className="fixed bottom-0 right-0 z-40 flex flex-col gap-2 sm:flex-row sm:items-center sm:gap-3 border-t border-border bg-card px-3 py-3 sm:px-5"
style={{ left: 'var(--sidebar-w, 0px)' }} style={{ left: 'var(--sidebar-w, 0px)' }}
> >
<div className="flex gap-2 sm:gap-3"> <div className="flex gap-2 sm:gap-3">
@@ -96,7 +96,7 @@ export function FlowPilotActionBar({
<button <button
onClick={handlePause} onClick={handlePause}
disabled={isProcessing || submitting} disabled={isProcessing || submitting}
className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors"
> >
<Pause size={16} /> <Pause size={16} />
Pause Pause
@@ -106,7 +106,7 @@ export function FlowPilotActionBar({
<button <button
onClick={() => setShowAbandon(true)} onClick={() => setShowAbandon(true)}
disabled={isProcessing || submitting} disabled={isProcessing || submitting}
className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors" className="flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 min-h-[44px] text-sm font-medium text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 disabled:pointer-events-none transition-colors"
> >
<X size={16} /> <X size={16} />
Close Close
@@ -119,20 +119,20 @@ export function FlowPilotActionBar({
{showResolve && ( {showResolve && (
<div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm"> <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm">
<div className="card-flat w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl"> <div className="card-flat w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl">
<h3 className="font-heading text-lg font-semibold text-[#e2e5eb] mb-1">Resolve Session</h3> <h3 className="font-heading text-lg font-semibold text-foreground mb-1">Resolve Session</h3>
<p className="text-sm text-[#848b9b] mb-4">Summarize what fixed the issue. This will be included in the auto-generated documentation.</p> <p className="text-sm text-muted-foreground mb-4">Summarize what fixed the issue. This will be included in the auto-generated documentation.</p>
<textarea <textarea
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-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] 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(6,182,212,0.3)] focus:outline-none resize-none"
rows={4} rows={4}
autoFocus autoFocus
/> />
<div className="mt-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"> <div className="mt-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
<button <button
onClick={() => setShowResolve(false)} onClick={() => setShowResolve(false)}
className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-muted-foreground hover:text-foreground transition-colors"
> >
Cancel Cancel
</button> </button>
@@ -152,14 +152,14 @@ export function FlowPilotActionBar({
{showAbandon && ( {showAbandon && (
<div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm"> <div className="fixed inset-0 z-50 flex items-end sm:items-center justify-center bg-black/60 backdrop-blur-sm">
<div className="card-flat w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl"> <div className="card-flat w-full max-w-full sm:max-w-lg mx-0 sm:mx-4 p-4 sm:p-6 rounded-t-2xl sm:rounded-2xl">
<h3 className="font-heading text-lg font-semibold text-[#e2e5eb] mb-1">Close Session</h3> <h3 className="font-heading text-lg font-semibold text-foreground mb-1">Close Session</h3>
<p className="text-sm text-[#848b9b] mb-4"> <p className="text-sm text-muted-foreground mb-4">
Are you sure you want to close this session? The session history will be kept but it won't count as resolved. Are you sure you want to close this session? The session history will be kept but it won't count as resolved.
</p> </p>
<div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end"> <div className="flex flex-col-reverse gap-2 sm:flex-row sm:justify-end">
<button <button
onClick={() => setShowAbandon(false)} onClick={() => setShowAbandon(false)}
className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="rounded-lg px-4 py-2 min-h-[44px] text-sm text-muted-foreground hover:text-foreground transition-colors"
> >
Cancel Cancel
</button> </button>

View File

@@ -100,11 +100,11 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
return ( return (
<div className="flex items-center justify-center min-h-[50vh]"> <div className="flex items-center justify-center min-h-[50vh]">
<div className="text-center"> <div className="text-center">
<div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-[rgba(34,211,238,0.10)]"> <div className="mx-auto mb-4 flex h-12 w-12 items-center justify-center rounded-2xl bg-accent-dim">
<Sparkles size={24} className="text-[#22d3ee] animate-pulse" /> <Sparkles size={24} className="text-primary animate-pulse" />
</div> </div>
<p className="text-sm font-medium text-[#e2e5eb]">Analyzing your issue...</p> <p className="text-sm font-medium text-foreground">Analyzing your issue...</p>
<p className="mt-1 text-xs text-[#848b9b]">FlowPilot is classifying the problem and searching for relevant flows</p> <p className="mt-1 text-xs text-muted-foreground">FlowPilot is classifying the problem and searching for relevant flows</p>
</div> </div>
</div> </div>
) )
@@ -118,10 +118,10 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
<div className="flex items-start justify-center px-3 sm:px-4 pt-[6vh] sm:pt-[10vh]"> <div className="flex items-start justify-center px-3 sm:px-4 pt-[6vh] sm:pt-[10vh]">
<div className="w-full max-w-2xl"> <div className="w-full max-w-2xl">
<div className="text-center mb-4 sm:mb-6"> <div className="text-center mb-4 sm:mb-6">
<h1 className="font-heading text-xl sm:text-2xl font-bold tracking-tight text-[#e2e5eb]"> <h1 className="font-heading text-xl sm:text-2xl font-bold tracking-tight text-foreground">
What are you troubleshooting? What are you troubleshooting?
</h1> </h1>
<p className="mt-2 text-sm text-[#848b9b]"> <p className="mt-2 text-sm text-muted-foreground">
Describe the issue, paste an error message, or pull context from a ticket Describe the issue, paste an error message, or pull context from a ticket
</p> </p>
</div> </div>
@@ -132,22 +132,22 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
<div className="rounded-xl border border-primary/20 bg-primary/5 p-4"> <div className="rounded-xl border border-primary/20 bg-primary/5 p-4">
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<p className="text-sm font-semibold text-[#e2e5eb]"> <p className="text-sm font-semibold text-foreground">
<span className="text-[#22d3ee]">#{selectedTicketId}</span> <span className="text-primary">#{selectedTicketId}</span>
{' — '} {' — '}
{selectedTicket.summary} {selectedTicket.summary}
</p> </p>
<div className="mt-1 flex flex-wrap items-center gap-x-2 text-xs text-[#848b9b]"> <div className="mt-1 flex flex-wrap items-center gap-x-2 text-xs text-muted-foreground">
{selectedTicket.company_name && <span>{selectedTicket.company_name}</span>} {selectedTicket.company_name && <span>{selectedTicket.company_name}</span>}
{selectedTicket.priority_name && ( {selectedTicket.priority_name && (
<> <>
<span className="text-[#5a6170]">&bull;</span> <span className="text-text-muted">&bull;</span>
<span>{selectedTicket.priority_name}</span> <span>{selectedTicket.priority_name}</span>
</> </>
)} )}
{selectedTicket.status_name && ( {selectedTicket.status_name && (
<> <>
<span className="text-[#5a6170]">&bull;</span> <span className="text-text-muted">&bull;</span>
<span>{selectedTicket.status_name}</span> <span>{selectedTicket.status_name}</span>
</> </>
)} )}
@@ -155,7 +155,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
</div> </div>
<button <button
onClick={handleClearTicket} onClick={handleClearTicket}
className="ml-2 rounded-md p-1 text-[#848b9b] hover:bg-white/[0.06] hover:text-[#e2e5eb] transition-colors" className="ml-2 rounded-md p-1 text-muted-foreground hover:bg-white/[0.06] hover:text-foreground transition-colors"
> >
<X size={14} /> <X size={14} />
</button> </button>
@@ -166,7 +166,7 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
value={additionalContext} value={additionalContext}
onChange={(e) => setAdditionalContext(e.target.value)} onChange={(e) => setAdditionalContext(e.target.value)}
placeholder="Add extra context (optional) — e.g. 'User called back and said it's also affecting their second monitor'" placeholder="Add extra context (optional) — e.g. 'User called back and said it's also affecting their second monitor'"
className="mt-3 w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none" className="mt-3 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"
rows={3} rows={3}
/> />
</div> </div>
@@ -190,8 +190,8 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
onClick={() => setShowLogs(!showLogs)} onClick={() => setShowLogs(!showLogs)}
className={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${ className={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${
showLogs showLogs
? 'bg-[rgba(34,211,238,0.10)] text-[#22d3ee] border border-primary/20' ? 'bg-accent-dim text-primary border border-primary/20'
: 'bg-[#14161d]/50 text-[#848b9b] border border-[#1e2130] hover:text-[#e2e5eb]' : 'bg-card/50 text-muted-foreground border border-border hover:text-foreground'
}`} }`}
> >
<Terminal size={12} /> <Terminal size={12} />
@@ -206,8 +206,8 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
disabled={!psaChecked || !psaConnection} disabled={!psaChecked || !psaConnection}
className={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${ className={`flex items-center gap-1.5 rounded-lg px-3 py-1.5 text-xs font-medium transition-colors ${
psaConnection psaConnection
? 'bg-[#14161d]/50 text-[#848b9b] border border-[#1e2130] hover:text-[#e2e5eb] hover:border-primary/20' ? 'bg-card/50 text-muted-foreground border border-border hover:text-foreground hover:border-primary/20'
: 'bg-[#14161d]/50 text-[#5a6170] border border-[#1e2130] opacity-50 cursor-not-allowed' : 'bg-card/50 text-text-muted border border-border opacity-50 cursor-not-allowed'
}`} }`}
title={!psaConnection ? 'Connect your PSA in Settings → Integrations' : 'Search for a ConnectWise ticket'} title={!psaConnection ? 'Connect your PSA in Settings → Integrations' : 'Search for a ConnectWise ticket'}
> >
@@ -229,20 +229,20 @@ export function FlowPilotIntake({ onSubmit, isLoading, defaultProblem }: FlowPil
value={logContent} value={logContent}
onChange={(e) => setLogContent(e.target.value)} onChange={(e) => setLogContent(e.target.value)}
placeholder="Paste log output, error messages, or Event Viewer entries here..." placeholder="Paste log output, error messages, or Event Viewer entries here..."
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-4 py-3 font-mono text-xs text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none" className="w-full rounded-lg border border-border bg-card px-4 py-3 font-mono text-xs text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
rows={6} rows={6}
/> />
)} )}
{/* Submit */} {/* Submit */}
<div className="flex flex-col-reverse gap-3 sm:flex-row sm:items-center sm:justify-between"> <div className="flex flex-col-reverse gap-3 sm:flex-row sm:items-center sm:justify-between">
<p className="text-[0.6875rem] text-[#5a6170] text-center sm:text-left"> <p className="text-[0.6875rem] text-text-muted text-center sm:text-left">
FlowPilot will analyze your input and guide you through diagnosis FlowPilot will analyze your input and guide you through diagnosis
</p> </p>
<button <button
onClick={handleSubmit} onClick={handleSubmit}
disabled={!hasContent} disabled={!hasContent}
className="w-full sm:w-auto min-h-[44px] rounded-lg bg-[#22d3ee] text-white px-5 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all whitespace-nowrap" className="w-full sm:w-auto min-h-[44px] rounded-lg bg-primary text-white px-5 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all whitespace-nowrap"
> >
{submitLabel} {submitLabel}
</button> </button>

View File

@@ -48,8 +48,8 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
className={cn( className={cn(
'flex items-end gap-2 rounded-xl border p-3 transition-colors', 'flex items-end gap-2 rounded-xl border p-3 transition-colors',
isDisabled isDisabled
? 'border-[#1e2130]/50 opacity-50' ? 'border-border/50 opacity-50'
: 'border-[#1e2130] focus-within:border-[rgba(6,182,212,0.3)]' : 'border-border focus-within:border-[rgba(6,182,212,0.3)]'
)} )}
style={{ background: '#14161d' }} style={{ background: '#14161d' }}
> >
@@ -61,7 +61,7 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
placeholder={isProcessing ? 'FlowPilot is thinking...' : 'Type a message...'} placeholder={isProcessing ? 'FlowPilot is thinking...' : 'Type a message...'}
disabled={isDisabled} disabled={isDisabled}
rows={1} rows={1}
className="flex-1 resize-none bg-transparent text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:outline-none disabled:cursor-not-allowed py-1.5 px-2" className="flex-1 resize-none bg-transparent text-sm text-foreground placeholder:text-muted-foreground focus:outline-none disabled:cursor-not-allowed py-1.5 px-2"
/> />
<button <button
onClick={handleSubmit} onClick={handleSubmit}
@@ -70,8 +70,8 @@ export function FlowPilotMessageBar({ onRespond, disabled = false, isProcessing
className={cn( className={cn(
'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg transition-all', 'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg transition-all',
message.trim() && !isDisabled message.trim() && !isDisabled
? 'bg-[#22d3ee] text-white hover:brightness-110 active:scale-[0.98]' ? 'bg-primary text-white hover:brightness-110 active:scale-[0.98]'
: 'bg-[rgba(255,255,255,0.04)] text-[#848b9b] cursor-not-allowed' : 'bg-[rgba(255,255,255,0.04)] text-muted-foreground cursor-not-allowed'
)} )}
> >
<Send size={16} /> <Send size={16} />

View File

@@ -32,20 +32,20 @@ export function FlowPilotOptions({ options, onSelect, disabled }: FlowPilotOptio
'hover:border-[rgba(6,182,212,0.3)] hover:shadow-[0_0_20px_rgba(6,182,212,0.08)]', 'hover:border-[rgba(6,182,212,0.3)] hover:shadow-[0_0_20px_rgba(6,182,212,0.08)]',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40', 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/40',
isSelected isSelected
? 'border-primary/40 bg-[rgba(34,211,238,0.10)]' ? 'border-primary/40 bg-accent-dim'
: 'border-[#1e2130] bg-[#14161d]/50', : 'border-border bg-card/50',
disabled && 'pointer-events-none opacity-60' disabled && 'pointer-events-none opacity-60'
)} )}
> >
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">
<div className="flex-1"> <div className="flex-1">
<p className="text-sm font-medium text-[#e2e5eb]">{option.label}</p> <p className="text-sm font-medium text-foreground">{option.label}</p>
{option.followup_hint && ( {option.followup_hint && (
<p className="mt-1 text-xs text-[#848b9b]">{option.followup_hint}</p> <p className="mt-1 text-xs text-muted-foreground">{option.followup_hint}</p>
)} )}
</div> </div>
{isSelected && ( {isSelected && (
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary/20 text-[#22d3ee]"> <span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary/20 text-primary">
<Check size={12} /> <Check size={12} />
</span> </span>
)} )}

View File

@@ -141,9 +141,9 @@ export function FlowPilotSession({
onClick={() => setShowMobileSidebar(!showMobileSidebar)} onClick={() => setShowMobileSidebar(!showMobileSidebar)}
className="flex w-full items-center justify-between px-3 py-2 sm:px-4" className="flex w-full items-center justify-between px-3 py-2 sm:px-4"
> >
<div className="flex items-center gap-3 text-xs text-[#848b9b] overflow-x-auto"> <div className="flex items-center gap-3 text-xs text-muted-foreground overflow-x-auto">
{session.problem_domain && ( {session.problem_domain && (
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-[#22d3ee] shrink-0"> <span className="font-sans text-xs rounded-md bg-accent-dim px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-primary shrink-0">
{session.problem_domain} {session.problem_domain}
</span> </span>
)} )}
@@ -156,7 +156,7 @@ export function FlowPilotSession({
score={currentStep?.confidence_score ?? 0} score={currentStep?.confidence_score ?? 0}
/> />
</div> </div>
{showMobileSidebar ? <ChevronUp size={14} className="text-[#848b9b] shrink-0" /> : <ChevronDown size={14} className="text-[#848b9b] shrink-0" />} {showMobileSidebar ? <ChevronUp size={14} className="text-muted-foreground shrink-0" /> : <ChevronDown size={14} className="text-muted-foreground shrink-0" />}
</button> </button>
{showMobileSidebar && ( {showMobileSidebar && (
<div className="px-3 pb-3 sm:px-4 space-y-3"> <div className="px-3 pb-3 sm:px-4 space-y-3">
@@ -169,7 +169,7 @@ export function FlowPilotSession({
<button <button
onClick={() => setShowTicketPicker(true)} onClick={() => setShowTicketPicker(true)}
disabled={linkingTicket} disabled={linkingTicket}
className="w-full flex items-center gap-2 rounded-xl border border-dashed border-[#1e2130] px-3 py-2.5 text-xs text-[#848b9b] hover:text-[#e2e5eb] hover:border-primary/30 transition-colors disabled:opacity-50 min-h-[44px]" className="w-full flex items-center gap-2 rounded-xl border border-dashed border-border px-3 py-2.5 text-xs text-muted-foreground hover:text-foreground hover:border-primary/30 transition-colors disabled:opacity-50 min-h-[44px]"
> >
<Ticket size={14} /> <Ticket size={14} />
{linkingTicket ? 'Linking...' : 'Link Ticket'} {linkingTicket ? 'Linking...' : 'Link Ticket'}
@@ -177,14 +177,14 @@ export function FlowPilotSession({
) : null} ) : null}
{session.problem_summary && ( {session.problem_summary && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Problem</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">Problem</h4>
<p className="text-sm text-[#e2e5eb]">{session.problem_summary}</p> <p className="text-sm text-foreground">{session.problem_summary}</p>
</div> </div>
)} )}
{session.matched_flow_id && ( {session.matched_flow_id && (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Network size={14} className="text-[#848b9b]" /> <Network size={14} className="text-muted-foreground" />
<span className="text-xs text-[#e2e5eb]"> <span className="text-xs text-foreground">
{session.match_score ? `${Math.round(session.match_score * 100)}% match` : 'Match found'} {session.match_score ? `${Math.round(session.match_score * 100)}% match` : 'Match found'}
</span> </span>
</div> </div>
@@ -228,7 +228,7 @@ export function FlowPilotSession({
<button <button
onClick={() => setShowTicketPicker(true)} onClick={() => setShowTicketPicker(true)}
disabled={linkingTicket} disabled={linkingTicket}
className="w-full flex items-center gap-2 rounded-xl border border-dashed border-[#1e2130] px-3 py-2.5 text-xs text-[#848b9b] hover:text-[#e2e5eb] hover:border-primary/30 transition-colors disabled:opacity-50" className="w-full flex items-center gap-2 rounded-xl border border-dashed border-border px-3 py-2.5 text-xs text-muted-foreground hover:text-foreground hover:border-primary/30 transition-colors disabled:opacity-50"
> >
<Ticket size={14} /> <Ticket size={14} />
{linkingTicket ? 'Linking...' : 'Link Ticket'} {linkingTicket ? 'Linking...' : 'Link Ticket'}
@@ -238,20 +238,20 @@ export function FlowPilotSession({
{/* Problem summary */} {/* Problem summary */}
{session.problem_summary && ( {session.problem_summary && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">
Problem Problem
</h4> </h4>
<p className="text-sm text-[#e2e5eb]">{session.problem_summary}</p> <p className="text-sm text-foreground">{session.problem_summary}</p>
</div> </div>
)} )}
{/* Domain */} {/* Domain */}
{session.problem_domain && ( {session.problem_domain && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">
Domain Domain
</h4> </h4>
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]"> <span className="font-sans text-xs rounded-md bg-accent-dim px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
{session.problem_domain} {session.problem_domain}
</span> </span>
</div> </div>
@@ -259,7 +259,7 @@ export function FlowPilotSession({
{/* Confidence */} {/* Confidence */}
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">
Confidence Confidence
</h4> </h4>
<ConfidenceIndicator <ConfidenceIndicator
@@ -271,12 +271,12 @@ export function FlowPilotSession({
{/* Matched flow */} {/* Matched flow */}
{session.matched_flow_id && ( {session.matched_flow_id && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">
Matched flow Matched flow
</h4> </h4>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Network size={14} className="text-[#848b9b]" /> <Network size={14} className="text-muted-foreground" />
<span className="text-xs text-[#e2e5eb]"> <span className="text-xs text-foreground">
{session.match_score ? `${Math.round(session.match_score * 100)}% match` : 'Match found'} {session.match_score ? `${Math.round(session.match_score * 100)}% match` : 'Match found'}
</span> </span>
</div> </div>
@@ -286,12 +286,12 @@ export function FlowPilotSession({
{/* Steps */} {/* Steps */}
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<Hash size={12} className="text-[#848b9b]" /> <Hash size={12} className="text-muted-foreground" />
<span className="text-xs text-[#848b9b]">{session.step_count} steps</span> <span className="text-xs text-muted-foreground">{session.step_count} steps</span>
</div> </div>
<div className="flex items-center gap-1.5"> <div className="flex items-center gap-1.5">
<Clock size={12} className="text-[#848b9b]" /> <Clock size={12} className="text-muted-foreground" />
<span className="text-xs text-[#848b9b]"> <span className="text-xs text-muted-foreground">
{new Date(session.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })} {new Date(session.created_at).toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
</span> </span>
</div> </div>
@@ -330,12 +330,12 @@ export function FlowPilotSession({
{/* Paused banner */} {/* Paused banner */}
{session.status === 'paused' && onResume && ( {session.status === 'paused' && onResume && (
<div <div
className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between border-t border-[#1e2130] bg-[#14161d] px-3 py-3 sm:px-5" className="flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between border-t border-border bg-card px-3 py-3 sm:px-5"
> >
<span className="text-sm text-[#848b9b]">Session paused</span> <span className="text-sm text-muted-foreground">Session paused</span>
<button <button
onClick={onResume} onClick={onResume}
className="flex items-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all" className="flex items-center gap-2 rounded-lg bg-primary text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all"
> >
<Play size={14} /> <Play size={14} />
Resume Session Resume Session

View File

@@ -65,9 +65,9 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
className="w-full text-left card-flat p-3 sm:p-4 opacity-70 hover:opacity-90 transition-opacity" className="w-full text-left card-flat p-3 sm:p-4 opacity-70 hover:opacity-90 transition-opacity"
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Icon size={16} className="shrink-0 text-[#848b9b]" /> <Icon size={16} className="shrink-0 text-muted-foreground" />
<p className="text-sm text-[#e2e5eb] truncate flex-1">{stepText}</p> <p className="text-sm text-foreground truncate flex-1">{stepText}</p>
<ChevronDown size={14} className="shrink-0 text-[#848b9b]" /> <ChevronDown size={14} className="shrink-0 text-muted-foreground" />
</div> </div>
</button> </button>
) )
@@ -82,14 +82,14 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
className="mb-2 flex w-full items-center justify-between text-left" className="mb-2 flex w-full items-center justify-between text-left"
> >
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Icon size={16} className="text-[#848b9b]" /> <Icon size={16} className="text-muted-foreground" />
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-muted-foreground">
Step {step.step_order + 1} Step {step.step_order + 1}
</span> </span>
</div> </div>
<ChevronUp size={14} className="text-[#848b9b]" /> <ChevronUp size={14} className="text-muted-foreground" />
</button> </button>
<MarkdownContent content={stepText} className="text-sm text-[#e2e5eb]" /> <MarkdownContent content={stepText} className="text-sm text-foreground" />
</div> </div>
) )
} }
@@ -105,7 +105,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
{/* Context message */} {/* Context message */}
{step.context_message && ( {step.context_message && (
<div className="mb-3 rounded-lg bg-primary/5 px-3 py-2 border border-primary/10"> <div className="mb-3 rounded-lg bg-primary/5 px-3 py-2 border border-primary/10">
<MarkdownContent content={step.context_message} className="text-xs text-[#848b9b]" /> <MarkdownContent content={step.context_message} className="text-xs text-muted-foreground" />
</div> </div>
)} )}
@@ -113,14 +113,14 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
<div className="flex items-start gap-3 mb-4"> <div className="flex items-start gap-3 mb-4">
<span className={cn( <span className={cn(
'mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg', 'mt-0.5 flex h-7 w-7 shrink-0 items-center justify-center rounded-lg',
isResolutionSuggestion ? 'bg-emerald-500/10 text-emerald-400' : 'bg-[rgba(34,211,238,0.10)] text-[#22d3ee]' isResolutionSuggestion ? 'bg-emerald-500/10 text-emerald-400' : 'bg-accent-dim text-primary'
)}> )}>
<Icon size={14} /> <Icon size={14} />
</span> </span>
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<MarkdownContent content={stepText} className="text-sm" /> <MarkdownContent content={stepText} className="text-sm" />
{isResolutionSuggestion && typeof content.resolution_summary === 'string' && ( {isResolutionSuggestion && typeof content.resolution_summary === 'string' && (
<p className="mt-2 text-sm text-[#848b9b]"> <p className="mt-2 text-sm text-muted-foreground">
{content.resolution_summary} {content.resolution_summary}
</p> </p>
)} )}
@@ -141,7 +141,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
</button> </button>
<button <button
onClick={() => handleResolutionResponse(false)} onClick={() => handleResolutionResponse(false)}
className="flex-1 min-h-[44px] rounded-lg bg-[#14161d]/50 border border-[#1e2130] px-4 py-2.5 text-sm font-medium text-[#e2e5eb] hover:bg-[#14161d] transition-colors" className="flex-1 min-h-[44px] rounded-lg bg-card/50 border border-border px-4 py-2.5 text-sm font-medium text-foreground hover:bg-card transition-colors"
> >
No, keep investigating No, keep investigating
</button> </button>
@@ -180,7 +180,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
window.open('/script-builder?from=flowpilot', '_blank') window.open('/script-builder?from=flowpilot', '_blank')
onRespond({ action_result: { success: true, details: 'Opened Script Builder' } }) onRespond({ action_result: { success: true, details: 'Opened Script Builder' } })
}} }}
className="flex-1 min-h-[44px] rounded-lg bg-[#22d3ee] text-white px-4 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all" className="flex-1 min-h-[44px] rounded-lg bg-primary text-white px-4 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] transition-all"
> >
Open Script Builder Open Script Builder
</button> </button>
@@ -191,13 +191,13 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
<div className="flex flex-col gap-2 sm:flex-row"> <div className="flex flex-col gap-2 sm:flex-row">
<button <button
onClick={() => handleActionComplete(true)} onClick={() => handleActionComplete(true)}
className="flex-1 min-h-[44px] rounded-lg bg-[rgba(34,211,238,0.10)] border border-primary/20 px-4 py-2.5 text-sm font-medium text-[#22d3ee] hover:bg-primary/20 transition-colors" className="flex-1 min-h-[44px] rounded-lg bg-accent-dim border border-primary/20 px-4 py-2.5 text-sm font-medium text-primary hover:bg-primary/20 transition-colors"
> >
I've completed this action I've completed this action
</button> </button>
<button <button
onClick={() => handleActionComplete(false)} onClick={() => handleActionComplete(false)}
className="flex-1 min-h-[44px] rounded-lg bg-[#14161d]/50 border border-[#1e2130] px-4 py-2.5 text-sm font-medium text-[#e2e5eb] hover:bg-[#14161d] transition-colors" className="flex-1 min-h-[44px] rounded-lg bg-card/50 border border-border px-4 py-2.5 text-sm font-medium text-foreground hover:bg-card transition-colors"
> >
This didn't work This didn't work
</button> </button>
@@ -208,7 +208,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
{!isResolutionSuggestion && step.allow_skip && ( {!isResolutionSuggestion && step.allow_skip && (
<button <button
onClick={handleSkip} onClick={handleSkip}
className="flex items-center gap-1.5 text-xs text-[#5a6170] hover:text-[#848b9b] transition-colors" className="flex items-center gap-1.5 text-xs text-text-muted hover:text-muted-foreground transition-colors"
> >
<SkipForward size={12} /> <SkipForward size={12} />
I can't check this right now I can't check this right now
@@ -221,7 +221,7 @@ export function FlowPilotStepCard({ step, isCurrentStep, isProcessing, sessionId
{isProcessing && ( {isProcessing && (
<div className="flex items-center gap-2 pt-2"> <div className="flex items-center gap-2 pt-2">
<div className="h-1.5 w-1.5 rounded-full bg-primary animate-pulse" /> <div className="h-1.5 w-1.5 rounded-full bg-primary animate-pulse" />
<span className="text-xs text-[#848b9b]">FlowPilot is thinking...</span> <span className="text-xs text-muted-foreground">FlowPilot is thinking...</span>
</div> </div>
)} )}
</div> </div>

View File

@@ -65,14 +65,14 @@ export function InSessionScriptGenerator({
return ( return (
<div className="mt-3 rounded-xl border border-primary/20 bg-primary/5 p-3 sm:p-4 space-y-3"> <div className="mt-3 rounded-xl border border-primary/20 bg-primary/5 p-3 sm:p-4 space-y-3">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<Terminal size={14} className="text-[#22d3ee]" /> <Terminal size={14} className="text-primary" />
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#22d3ee]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-primary">
Script Generator Script Generator
</span> </span>
</div> </div>
{instructions && ( {instructions && (
<p className="text-xs text-[#848b9b]">{instructions}</p> <p className="text-xs text-muted-foreground">{instructions}</p>
)} )}
{/* Parameter editing */} {/* Parameter editing */}
@@ -80,7 +80,7 @@ export function InSessionScriptGenerator({
<> <>
<button <button
onClick={() => setShowParams(!showParams)} onClick={() => setShowParams(!showParams)}
className="flex items-center gap-1.5 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors"
> >
{showParams ? <ChevronDown size={12} /> : <ChevronRight size={12} />} {showParams ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
Parameters ({Object.keys(params).length}) Parameters ({Object.keys(params).length})
@@ -90,13 +90,13 @@ export function InSessionScriptGenerator({
<div className="space-y-2"> <div className="space-y-2">
{Object.entries(params).map(([key, value]) => ( {Object.entries(params).map(([key, value]) => (
<div key={key}> <div key={key}>
<label className="block text-xs font-medium text-[#848b9b] mb-1"> <label className="block text-xs font-medium text-muted-foreground mb-1">
{key.replace(/_/g, ' ')} {key.replace(/_/g, ' ')}
</label> </label>
<input <input
value={value} value={value}
onChange={(e) => setParams(prev => ({ ...prev, [key]: e.target.value }))} onChange={(e) => setParams(prev => ({ ...prev, [key]: e.target.value }))}
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-1.5 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none" className="w-full rounded-lg 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-none"
/> />
</div> </div>
))} ))}
@@ -106,7 +106,7 @@ export function InSessionScriptGenerator({
<button <button
onClick={handleGenerate} onClick={handleGenerate}
disabled={isGenerating} disabled={isGenerating}
className="w-full min-h-[44px] flex items-center justify-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all" className="w-full min-h-[44px] flex items-center justify-center gap-2 rounded-lg bg-primary text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all"
> >
{isGenerating ? ( {isGenerating ? (
<Loader2 size={14} className="animate-spin" /> <Loader2 size={14} className="animate-spin" />
@@ -121,12 +121,12 @@ export function InSessionScriptGenerator({
{/* Generated script display */} {/* Generated script display */}
{generatedScript && ( {generatedScript && (
<> <>
<div className="relative rounded-lg bg-[#14161d]/80 border border-[#1e2130] overflow-hidden"> <div className="relative rounded-lg bg-card/80 border border-border overflow-hidden">
<div className="flex items-center justify-between px-3 py-1.5 border-b border-[#1e2130]/50"> <div className="flex items-center justify-between px-3 py-1.5 border-b border-border/50">
<span className="text-xs text-[#848b9b] font-mono">PowerShell</span> <span className="text-xs text-muted-foreground font-mono">PowerShell</span>
<button <button
onClick={handleCopy} onClick={handleCopy}
className="flex items-center gap-1 text-xs text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
> >
{copied ? <Check size={12} className="text-emerald-400" /> : <Copy size={12} />} {copied ? <Check size={12} className="text-emerald-400" /> : <Copy size={12} />}
{copied ? 'Copied' : 'Copy'} {copied ? 'Copied' : 'Copy'}
@@ -141,13 +141,13 @@ export function InSessionScriptGenerator({
<div className="flex flex-col gap-2 pt-1 sm:flex-row"> <div className="flex flex-col gap-2 pt-1 sm:flex-row">
<button <button
onClick={() => handleContinue(true)} onClick={() => handleContinue(true)}
className="flex-1 min-h-[44px] rounded-lg bg-[rgba(34,211,238,0.10)] border border-primary/20 px-4 py-2 text-sm font-medium text-[#22d3ee] hover:bg-primary/20 transition-colors" className="flex-1 min-h-[44px] rounded-lg bg-accent-dim border border-primary/20 px-4 py-2 text-sm font-medium text-primary hover:bg-primary/20 transition-colors"
> >
Script worked continue Script worked continue
</button> </button>
<button <button
onClick={() => handleContinue(false)} onClick={() => handleContinue(false)}
className="flex-1 min-h-[44px] rounded-lg bg-[#14161d]/50 border border-[#1e2130] px-4 py-2 text-sm font-medium text-[#e2e5eb] hover:bg-[#14161d] transition-colors" className="flex-1 min-h-[44px] rounded-lg bg-card/50 border border-border px-4 py-2 text-sm font-medium text-foreground hover:bg-card transition-colors"
> >
Didn't resolve it Didn't resolve it
</button> </button>

View File

@@ -5,7 +5,7 @@ const TYPE_CONFIG = {
new_flow: { label: 'New Flow', color: 'text-emerald-400 bg-emerald-400/10 border-emerald-400/20', icon: Sparkles }, new_flow: { label: 'New Flow', color: 'text-emerald-400 bg-emerald-400/10 border-emerald-400/20', icon: Sparkles },
enhancement: { label: 'Enhancement', color: 'text-amber-400 bg-amber-400/10 border-amber-400/20', icon: ArrowUpRight }, enhancement: { label: 'Enhancement', color: 'text-amber-400 bg-amber-400/10 border-amber-400/20', icon: ArrowUpRight },
branch_addition: { label: 'Branch', color: 'text-blue-400 bg-blue-400/10 border-blue-400/20', icon: GitBranch }, branch_addition: { label: 'Branch', color: 'text-blue-400 bg-blue-400/10 border-blue-400/20', icon: GitBranch },
auto_reinforced: { label: 'Reinforced', color: 'text-[#848b9b] bg-[#14161d] border-[#1e2130]', icon: Sparkles }, auto_reinforced: { label: 'Reinforced', color: 'text-muted-foreground bg-card border-border', icon: Sparkles },
} as const } as const
interface ProposalCardProps { interface ProposalCardProps {
@@ -24,11 +24,11 @@ export function ProposalCard({ proposal, isSelected, onClick }: ProposalCardProp
className={`w-full text-left rounded-xl border p-3 space-y-2 transition-all ${ className={`w-full text-left rounded-xl border p-3 space-y-2 transition-all ${
isSelected isSelected
? 'border-primary/30 bg-primary/5' ? 'border-primary/30 bg-primary/5'
: 'border-[rgba(255,255,255,0.06)] bg-[#14161d] hover:border-[rgba(255,255,255,0.12)]' : 'border-[rgba(255,255,255,0.06)] bg-card hover:border-[rgba(255,255,255,0.12)]'
}`} }`}
> >
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<p className="text-sm font-semibold text-[#e2e5eb] line-clamp-2">{proposal.title}</p> <p className="text-sm font-semibold text-foreground line-clamp-2">{proposal.title}</p>
<span className={`shrink-0 flex items-center gap-1 rounded-md border px-1.5 py-0.5 font-sans text-xs text-[0.5625rem] uppercase tracking-wider ${typeConfig.color}`}> <span className={`shrink-0 flex items-center gap-1 rounded-md border px-1.5 py-0.5 font-sans text-xs text-[0.5625rem] uppercase tracking-wider ${typeConfig.color}`}>
<TypeIcon size={10} /> <TypeIcon size={10} />
{typeConfig.label} {typeConfig.label}
@@ -36,12 +36,12 @@ export function ProposalCard({ proposal, isSelected, onClick }: ProposalCardProp
</div> </div>
{proposal.description && ( {proposal.description && (
<p className="text-xs text-[#848b9b] line-clamp-2">{proposal.description}</p> <p className="text-xs text-muted-foreground line-clamp-2">{proposal.description}</p>
)} )}
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-[#848b9b]"> <div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-xs text-muted-foreground">
{proposal.problem_domain && ( {proposal.problem_domain && (
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-[#22d3ee]"> <span className="font-sans text-xs rounded-md bg-accent-dim px-1.5 py-0.5 text-[0.5625rem] uppercase tracking-wider text-primary">
{proposal.problem_domain} {proposal.problem_domain}
</span> </span>
)} )}
@@ -53,7 +53,7 @@ export function ProposalCard({ proposal, isSelected, onClick }: ProposalCardProp
<Clock size={10} /> <Clock size={10} />
{new Date(proposal.created_at).toLocaleDateString()} {new Date(proposal.created_at).toLocaleDateString()}
</span> </span>
<span className="text-[#22d3ee]"> <span className="text-primary">
{Math.round(proposal.confidence_score * 100)}% {Math.round(proposal.confidence_score * 100)}%
</span> </span>
</div> </div>

View File

@@ -61,13 +61,13 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<div className="flex h-full flex-col"> <div className="flex h-full flex-col">
{/* Header */} {/* Header */}
<div className="border-b px-6 py-4" style={{ borderColor: 'var(--glass-border)' }}> <div className="border-b px-6 py-4" style={{ borderColor: 'var(--glass-border)' }}>
<h2 className="font-heading text-lg font-semibold text-[#e2e5eb]">{proposal.title}</h2> <h2 className="font-heading text-lg font-semibold text-foreground">{proposal.title}</h2>
{proposal.description && ( {proposal.description && (
<p className="mt-1 text-sm text-[#848b9b]">{proposal.description}</p> <p className="mt-1 text-sm text-muted-foreground">{proposal.description}</p>
)} )}
<div className="mt-3 flex flex-wrap items-center gap-3 text-xs text-[#848b9b]"> <div className="mt-3 flex flex-wrap items-center gap-3 text-xs text-muted-foreground">
{proposal.problem_domain && ( {proposal.problem_domain && (
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]"> <span className="font-sans text-xs rounded-md bg-accent-dim px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
{proposal.problem_domain} {proposal.problem_domain}
</span> </span>
)} )}
@@ -90,11 +90,11 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<div className="flex-1 overflow-y-auto p-6 space-y-5"> <div className="flex-1 overflow-y-auto p-6 space-y-5">
{/* Source session link */} {/* Source session link */}
<div className="card-flat p-4"> <div className="card-flat p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Source Session</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-2">Source Session</h4>
<Link <Link
to={`/pilot/${proposal.source_session_id}`} to={`/pilot/${proposal.source_session_id}`}
target="_blank" target="_blank"
className="flex items-center gap-2 text-sm text-[#22d3ee] hover:underline" className="flex items-center gap-2 text-sm text-primary hover:underline"
> >
<ExternalLink size={12} /> <ExternalLink size={12} />
View session that generated this proposal View session that generated this proposal
@@ -106,15 +106,15 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
const diff = proposal.proposed_diff as { diff_description?: string; new_nodes?: Array<{ title?: string; question?: string; description?: string }> } const diff = proposal.proposed_diff as { diff_description?: string; new_nodes?: Array<{ title?: string; question?: string; description?: string }> }
return ( return (
<div className="card-flat border-l-2 border-l-amber-500 p-4"> <div className="card-flat border-l-2 border-l-amber-500 p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Proposed Changes</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-2">Proposed Changes</h4>
{diff.diff_description && ( {diff.diff_description && (
<p className="text-sm text-[#e2e5eb]">{diff.diff_description}</p> <p className="text-sm text-foreground">{diff.diff_description}</p>
)} )}
{diff.new_nodes && diff.new_nodes.length > 0 && ( {diff.new_nodes && diff.new_nodes.length > 0 && (
<div className="mt-3 space-y-1.5"> <div className="mt-3 space-y-1.5">
<p className="text-xs font-medium text-[#848b9b]">New nodes:</p> <p className="text-xs font-medium text-muted-foreground">New nodes:</p>
{diff.new_nodes.map((node, i) => ( {diff.new_nodes.map((node, i) => (
<div key={i} className="rounded-lg bg-emerald-500/5 border border-emerald-500/10 px-3 py-2 text-xs text-[#e2e5eb]"> <div key={i} className="rounded-lg bg-emerald-500/5 border border-emerald-500/10 px-3 py-2 text-xs text-foreground">
<span className="text-emerald-400">+ </span> <span className="text-emerald-400">+ </span>
{node.title || node.question || node.description || 'New node'} {node.title || node.question || node.description || 'New node'}
</div> </div>
@@ -129,13 +129,13 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<div className="card-flat p-4"> <div className="card-flat p-4">
<button <button
onClick={() => setShowFlowData(!showFlowData)} onClick={() => setShowFlowData(!showFlowData)}
className="flex items-center gap-1.5 font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1.5 font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted hover:text-foreground transition-colors"
> >
{showFlowData ? <ChevronDown size={12} /> : <ChevronRight size={12} />} {showFlowData ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
Flow Data (JSON) Flow Data (JSON)
</button> </button>
{showFlowData && ( {showFlowData && (
<pre className="mt-3 max-h-[400px] overflow-auto rounded-lg bg-[#14161d]/80 p-3 text-xs text-[#848b9b] font-mono"> <pre className="mt-3 max-h-[400px] overflow-auto rounded-lg bg-card/80 p-3 text-xs text-muted-foreground font-mono">
{JSON.stringify(proposal.proposed_flow_data, null, 2)} {JSON.stringify(proposal.proposed_flow_data, null, 2)}
</pre> </pre>
)} )}
@@ -144,7 +144,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{/* Supporting sessions */} {/* Supporting sessions */}
{proposal.supporting_session_ids.length > 1 && ( {proposal.supporting_session_ids.length > 1 && (
<div className="card-flat p-4"> <div className="card-flat p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-2">
Supporting Sessions ({proposal.supporting_session_ids.length}) Supporting Sessions ({proposal.supporting_session_ids.length})
</h4> </h4>
<div className="space-y-1"> <div className="space-y-1">
@@ -153,7 +153,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
key={sid} key={sid}
to={`/pilot/${sid}`} to={`/pilot/${sid}`}
target="_blank" target="_blank"
className="block text-xs text-[#22d3ee] hover:underline truncate" className="block text-xs text-primary hover:underline truncate"
> >
{sid} {sid}
</Link> </Link>
@@ -165,13 +165,13 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{/* Review info (for already-reviewed proposals) */} {/* Review info (for already-reviewed proposals) */}
{proposal.reviewed_at && ( {proposal.reviewed_at && (
<div className="card-flat p-4"> <div className="card-flat p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-2">Review</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-2">Review</h4>
<p className="text-sm text-[#e2e5eb]"> <p className="text-sm text-foreground">
<span className="capitalize">{proposal.status}</span> on{' '} <span className="capitalize">{proposal.status}</span> on{' '}
{new Date(proposal.reviewed_at).toLocaleString()} {new Date(proposal.reviewed_at).toLocaleString()}
</p> </p>
{proposal.reviewer_notes && ( {proposal.reviewer_notes && (
<p className="mt-1 text-xs text-[#848b9b]">{proposal.reviewer_notes}</p> <p className="mt-1 text-xs text-muted-foreground">{proposal.reviewer_notes}</p>
)} )}
</div> </div>
)} )}
@@ -180,14 +180,14 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
{/* Review actions bar */} {/* Review actions bar */}
{canReview && ( {canReview && (
<div <div
className="border-t border-[#1e2130] bg-[#14161d] px-5 py-3 space-y-3" className="border-t border-border bg-card px-5 py-3 space-y-3"
> >
{/* Notes input */} {/* Notes input */}
<input <input
value={reviewNotes} value={reviewNotes}
onChange={(e) => setReviewNotes(e.target.value)} onChange={(e) => setReviewNotes(e.target.value)}
placeholder="Reviewer notes (optional)" placeholder="Reviewer notes (optional)"
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-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(6,182,212,0.3)] focus:outline-none"
/> />
{/* Action buttons */} {/* Action buttons */}
@@ -202,14 +202,14 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
Approve & Publish Approve & Publish
</button> </button>
) : ( ) : (
<span className="text-xs text-[#848b9b] italic px-2"> <span className="text-xs text-muted-foreground italic px-2">
Enhancement proposals require Edit & Publish Enhancement proposals require Edit & Publish
</span> </span>
)} )}
<button <button
onClick={handleEditAndPublish} onClick={handleEditAndPublish}
disabled={isSubmitting} disabled={isSubmitting}
className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors" className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
> >
<Pencil size={14} /> <Pencil size={14} />
Edit & Publish Edit & Publish
@@ -217,7 +217,7 @@ export function ProposalDetail({ proposal, onReview }: ProposalDetailProps) {
<button <button
onClick={() => handleAction('dismiss')} onClick={() => handleAction('dismiss')}
disabled={isSubmitting} disabled={isSubmitting}
className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors ml-auto" className="flex items-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors ml-auto"
> >
<EyeOff size={14} /> <EyeOff size={14} />
Dismiss Dismiss

View File

@@ -40,10 +40,10 @@ export function SessionBriefing({
return ( return (
<div className="card-flat border-l-2 border-l-amber-500 p-5 space-y-4"> <div className="card-flat border-l-2 border-l-amber-500 p-5 space-y-4">
<div> <div>
<h3 className="font-heading text-base font-semibold text-[#e2e5eb]"> <h3 className="font-heading text-base font-semibold text-foreground">
Escalation from {originalEngineerName || 'another engineer'} Escalation from {originalEngineerName || 'another engineer'}
</h3> </h3>
<p className="mt-1 text-sm text-[#848b9b]"> <p className="mt-1 text-sm text-muted-foreground">
Review the briefing below, then choose how to proceed. Review the briefing below, then choose how to proceed.
</p> </p>
</div> </div>
@@ -51,15 +51,15 @@ export function SessionBriefing({
{/* Problem */} {/* Problem */}
{pkg.problem_summary && ( {pkg.problem_summary && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Problem</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">Problem</h4>
<p className="text-sm text-[#e2e5eb]">{pkg.problem_summary}</p> <p className="text-sm text-foreground">{pkg.problem_summary}</p>
</div> </div>
)} )}
{/* Escalation reason */} {/* Escalation reason */}
{pkg.escalation_reason && ( {pkg.escalation_reason && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Why escalated</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">Why escalated</h4>
<p className="text-sm text-amber-400">{pkg.escalation_reason}</p> <p className="text-sm text-amber-400">{pkg.escalation_reason}</p>
</div> </div>
)} )}
@@ -69,7 +69,7 @@ export function SessionBriefing({
<div> <div>
<button <button
onClick={() => setShowSteps(!showSteps)} onClick={() => setShowSteps(!showSteps)}
className="flex items-center gap-1.5 font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] hover:text-[#e2e5eb] transition-colors" className="flex items-center gap-1.5 font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted hover:text-foreground transition-colors"
> >
{showSteps ? <ChevronDown size={12} /> : <ChevronRight size={12} />} {showSteps ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
Steps taken ({pkg.steps_tried.length}) Steps taken ({pkg.steps_tried.length})
@@ -77,10 +77,10 @@ export function SessionBriefing({
{showSteps && ( {showSteps && (
<div className="mt-2 space-y-1.5"> <div className="mt-2 space-y-1.5">
{pkg.steps_tried.map((step, i) => ( {pkg.steps_tried.map((step, i) => (
<div key={i} className="rounded-lg bg-[#14161d]/50 px-3 py-2 text-xs"> <div key={i} className="rounded-lg bg-card/50 px-3 py-2 text-xs">
<p className="text-[#e2e5eb]">{i + 1}. {step.description}</p> <p className="text-foreground">{i + 1}. {step.description}</p>
{step.response && ( {step.response && (
<p className="mt-0.5 text-[#22d3ee]"> {step.response}</p> <p className="mt-0.5 text-primary"> {step.response}</p>
)} )}
</div> </div>
))} ))}
@@ -92,11 +92,11 @@ export function SessionBriefing({
{/* Remaining hypotheses */} {/* Remaining hypotheses */}
{pkg.remaining_hypotheses && pkg.remaining_hypotheses.length > 0 && ( {pkg.remaining_hypotheses && pkg.remaining_hypotheses.length > 0 && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Remaining hypotheses</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">Remaining hypotheses</h4>
<ul className="space-y-1"> <ul className="space-y-1">
{pkg.remaining_hypotheses.map((h, i) => ( {pkg.remaining_hypotheses.map((h, i) => (
<li key={i} className="text-sm text-[#e2e5eb] flex items-start gap-2"> <li key={i} className="text-sm text-foreground flex items-start gap-2">
<span className="text-[#22d3ee] mt-0.5"></span> <span className="text-primary mt-0.5"></span>
{h} {h}
</li> </li>
))} ))}
@@ -107,10 +107,10 @@ export function SessionBriefing({
{/* Suggested next steps */} {/* Suggested next steps */}
{pkg.suggested_next_steps && pkg.suggested_next_steps.length > 0 && ( {pkg.suggested_next_steps && pkg.suggested_next_steps.length > 0 && (
<div> <div>
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170] mb-1">Suggested next steps</h4> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted mb-1">Suggested next steps</h4>
<ul className="space-y-1"> <ul className="space-y-1">
{pkg.suggested_next_steps.map((s, i) => ( {pkg.suggested_next_steps.map((s, i) => (
<li key={i} className="text-sm text-[#e2e5eb] flex items-start gap-2"> <li key={i} className="text-sm text-foreground flex items-start gap-2">
<span className="text-emerald-400 mt-0.5"></span> <span className="text-emerald-400 mt-0.5"></span>
{s} {s}
</li> </li>
@@ -125,7 +125,7 @@ export function SessionBriefing({
<button <button
onClick={onContinue} onClick={onContinue}
disabled={isProcessing} disabled={isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all" className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-primary text-white px-4 py-2.5 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all"
> >
<ArrowRight size={14} /> <ArrowRight size={14} />
Continue Where They Left Off Continue Where They Left Off
@@ -133,7 +133,7 @@ export function SessionBriefing({
<button <button
onClick={() => setFreshMode(true)} onClick={() => setFreshMode(true)}
disabled={isProcessing} disabled={isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors" className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2.5 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
> >
<MessageSquare size={14} /> <MessageSquare size={14} />
Start Fresh With Context Start Fresh With Context
@@ -145,7 +145,7 @@ export function SessionBriefing({
value={freshContext} value={freshContext}
onChange={(e) => setFreshContext(e.target.value)} onChange={(e) => setFreshContext(e.target.value)}
placeholder="What additional information do you have, or what would you like to investigate first?" placeholder="What additional information do you have, or what would you like to investigate first?"
className="w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-4 py-3 text-sm text-[#e2e5eb] placeholder:text-[#848b9b] focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none" className="w-full rounded-lg border border-border bg-card px-4 py-3 text-sm text-foreground placeholder:text-muted-foreground focus:border-[rgba(6,182,212,0.3)] focus:outline-none resize-none"
rows={3} rows={3}
autoFocus autoFocus
/> />
@@ -153,14 +153,14 @@ export function SessionBriefing({
<button <button
onClick={() => setFreshMode(false)} onClick={() => setFreshMode(false)}
disabled={isProcessing} disabled={isProcessing}
className="rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors" className="rounded-lg bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] px-4 py-2 text-sm font-medium text-foreground hover:border-[rgba(255,255,255,0.12)] disabled:opacity-40 transition-colors"
> >
Back Back
</button> </button>
<button <button
onClick={() => freshContext.trim() && onFresh(freshContext.trim())} onClick={() => freshContext.trim() && onFresh(freshContext.trim())}
disabled={!freshContext.trim() || isProcessing} disabled={!freshContext.trim() || isProcessing}
className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-[#22d3ee] text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all" className="flex-1 flex items-center justify-center gap-2 rounded-lg bg-primary text-white px-4 py-2 text-sm font-semibold hover:brightness-110 active:scale-[0.98] disabled:opacity-40 transition-all"
> >
<ArrowRight size={14} /> <ArrowRight size={14} />
Start Diagnosis Start Diagnosis

View File

@@ -109,25 +109,25 @@ export function SessionDocView({
{/* Header */} {/* Header */}
<div className="card-flat p-3 sm:p-4 lg:p-5"> <div className="card-flat p-3 sm:p-4 lg:p-5">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[rgba(34,211,238,0.10)] text-[#22d3ee]"> <span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-accent-dim text-primary">
<FileText size={16} /> <FileText size={16} />
</span> </span>
<div className="flex-1"> <div className="flex-1">
<h3 className="font-heading text-lg font-semibold text-[#e2e5eb]">Session Documentation</h3> <h3 className="font-heading text-lg font-semibold text-foreground">Session Documentation</h3>
<p className="mt-1 text-sm text-[#848b9b]">{documentation.problem_summary}</p> <p className="mt-1 text-sm text-muted-foreground">{documentation.problem_summary}</p>
<div className="mt-2 flex items-center gap-3 flex-wrap"> <div className="mt-2 flex items-center gap-3 flex-wrap">
{documentation.problem_domain && ( {documentation.problem_domain && (
<span className="font-sans text-xs rounded-md bg-[rgba(34,211,238,0.10)] px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-[#22d3ee]"> <span className="font-sans text-xs rounded-md bg-accent-dim px-2 py-0.5 text-[0.625rem] uppercase tracking-wider text-primary">
{documentation.problem_domain} {documentation.problem_domain}
</span> </span>
)} )}
{documentation.duration_display && ( {documentation.duration_display && (
<span className="flex items-center gap-1 text-xs text-[#848b9b]"> <span className="flex items-center gap-1 text-xs text-muted-foreground">
<Clock size={12} /> <Clock size={12} />
{documentation.duration_display} {documentation.duration_display}
</span> </span>
)} )}
<span className="text-xs text-[#848b9b]"> <span className="text-xs text-muted-foreground">
{documentation.total_steps} steps {documentation.total_steps} steps
</span> </span>
</div> </div>
@@ -144,11 +144,11 @@ export function SessionDocView({
) : ( ) : (
<ArrowUpRight size={14} className="text-amber-400" /> <ArrowUpRight size={14} className="text-amber-400" />
)} )}
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-muted-foreground">
{documentation.resolution_summary ? 'Resolved' : 'Escalated'} {documentation.resolution_summary ? 'Resolved' : 'Escalated'}
</span> </span>
</div> </div>
<p className="text-sm text-[#e2e5eb]"> <p className="text-sm text-foreground">
{documentation.resolution_summary || documentation.escalation_reason} {documentation.resolution_summary || documentation.escalation_reason}
</p> </p>
</div> </div>
@@ -156,30 +156,30 @@ export function SessionDocView({
{/* Intake summary */} {/* Intake summary */}
<div className="card-flat p-3 sm:p-4"> <div className="card-flat p-3 sm:p-4">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b] mb-2"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-muted-foreground mb-2">
Original intake Original intake
</h4> </h4>
<p className="text-sm text-[#e2e5eb] whitespace-pre-wrap">{documentation.intake_summary}</p> <p className="text-sm text-foreground whitespace-pre-wrap">{documentation.intake_summary}</p>
</div> </div>
{/* Diagnostic steps */} {/* Diagnostic steps */}
<div className="space-y-2"> <div className="space-y-2">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#848b9b] px-1"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-muted-foreground px-1">
Diagnostic trail Diagnostic trail
</h4> </h4>
{documentation.diagnostic_steps.map((step) => ( {documentation.diagnostic_steps.map((step) => (
<div key={step.step_number} className="card-flat p-3 sm:p-4"> <div key={step.step_number} className="card-flat p-3 sm:p-4">
<div className="flex items-start gap-3"> <div className="flex items-start gap-3">
<span className="font-sans text-xs flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-[#14161d] text-[0.625rem] text-[#848b9b] border border-[#1e2130]"> <span className="font-sans text-xs flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-card text-[0.625rem] text-muted-foreground border border-border">
{step.step_number} {step.step_number}
</span> </span>
<div className="flex-1"> <div className="flex-1">
<p className="text-sm text-[#e2e5eb]">{step.description}</p> <p className="text-sm text-foreground">{step.description}</p>
{step.engineer_response && ( {step.engineer_response && (
<p className="mt-1 text-xs text-[#22d3ee]"> {step.engineer_response}</p> <p className="mt-1 text-xs text-primary"> {step.engineer_response}</p>
)} )}
{step.outcome && ( {step.outcome && (
<p className="mt-1 text-xs text-[#848b9b]">Outcome: {step.outcome}</p> <p className="mt-1 text-xs text-muted-foreground">Outcome: {step.outcome}</p>
)} )}
</div> </div>
</div> </div>
@@ -190,7 +190,7 @@ export function SessionDocView({
{/* Rating */} {/* Rating */}
{onRate && ( {onRate && (
<div className="card-flat p-3 sm:p-4 text-center"> <div className="card-flat p-3 sm:p-4 text-center">
<p className="text-sm text-[#848b9b] mb-2">How helpful was this session?</p> <p className="text-sm text-muted-foreground mb-2">How helpful was this session?</p>
<div className="flex items-center justify-center gap-1"> <div className="flex items-center justify-center gap-1">
{[1, 2, 3, 4, 5].map((star) => ( {[1, 2, 3, 4, 5].map((star) => (
<button <button
@@ -203,7 +203,7 @@ export function SessionDocView({
className={ className={
(currentRating ?? 0) >= star (currentRating ?? 0) >= star
? 'fill-amber-400 text-amber-400' ? 'fill-amber-400 text-amber-400'
: 'text-[#848b9b] hover:text-amber-400' : 'text-muted-foreground hover:text-amber-400'
} }
/> />
</button> </button>

View File

@@ -36,7 +36,7 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
return ( return (
<div className="rounded-xl border border-primary/20 bg-primary/5 p-3 space-y-2"> <div className="rounded-xl border border-primary/20 bg-primary/5 p-3 space-y-2">
<div className="flex items-start justify-between"> <div className="flex items-start justify-between">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-[#5a6170]"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-wider text-text-muted">
Linked Ticket Linked Ticket
</h4> </h4>
{ticketUrl && ( {ticketUrl && (
@@ -44,7 +44,7 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
href={ticketUrl} href={ticketUrl}
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
className="text-[#848b9b] hover:text-[#22d3ee] transition-colors" className="text-muted-foreground hover:text-primary transition-colors"
title="Open in ConnectWise" title="Open in ConnectWise"
> >
<ExternalLink size={12} /> <ExternalLink size={12} />
@@ -52,14 +52,14 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
)} )}
</div> </div>
<p className="text-sm font-semibold text-[#e2e5eb]"> <p className="text-sm font-semibold text-foreground">
<span className="text-[#22d3ee]">#{ticketId}</span> <span className="text-primary">#{ticketId}</span>
{ticket?.summary && ( {ticket?.summary && (
<span> {ticket.summary}</span> <span> {ticket.summary}</span>
)} )}
</p> </p>
<div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-[#848b9b]"> <div className="flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-muted-foreground">
{company?.name && ( {company?.name && (
<span className="flex items-center gap-1"> <span className="flex items-center gap-1">
<Building2 size={10} /> <Building2 size={10} />
@@ -68,33 +68,33 @@ export function SessionTicketCard({ ticketId, ticketData, siteUrl }: SessionTick
)} )}
{ticket?.priority && ( {ticket?.priority && (
<> <>
<span className="text-[#5a6170]">&bull;</span> <span className="text-text-muted">&bull;</span>
<span>{ticket.priority}</span> <span>{ticket.priority}</span>
</> </>
)} )}
{ticket?.status && ( {ticket?.status && (
<> <>
<span className="text-[#5a6170]">&bull;</span> <span className="text-text-muted">&bull;</span>
<span>{ticket.status}</span> <span>{ticket.status}</span>
</> </>
)} )}
</div> </div>
{configs && configs.length > 0 && ( {configs && configs.length > 0 && (
<div className="border-t border-[#1e2130]/50 pt-2 mt-2"> <div className="border-t border-border/50 pt-2 mt-2">
<p className="font-sans text-xs text-[0.5625rem] uppercase tracking-wider text-[#5a6170] mb-1"> <p className="font-sans text-xs text-[0.5625rem] uppercase tracking-wider text-text-muted mb-1">
Devices Devices
</p> </p>
<div className="space-y-0.5"> <div className="space-y-0.5">
{configs.slice(0, 3).map((cfg, i) => ( {configs.slice(0, 3).map((cfg, i) => (
<div key={i} className="flex items-center gap-1.5 text-xs text-[#848b9b]"> <div key={i} className="flex items-center gap-1.5 text-xs text-muted-foreground">
<Cpu size={10} /> <Cpu size={10} />
<span>{cfg.device_identifier}</span> <span>{cfg.device_identifier}</span>
{cfg.type && <span className="text-[#5a6170]">({cfg.type})</span>} {cfg.type && <span className="text-text-muted">({cfg.type})</span>}
</div> </div>
))} ))}
{configs.length > 3 && ( {configs.length > 3 && (
<p className="text-[0.625rem] text-[#5a6170]"> <p className="text-[0.625rem] text-text-muted">
+{configs.length - 3} more +{configs.length - 3} more
</p> </p>
)} )}

View File

@@ -35,8 +35,8 @@ export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
if (loading) { if (loading) {
return ( return (
<div className="flex items-center gap-1.5 py-1"> <div className="flex items-center gap-1.5 py-1">
<Loader2 size={10} className="animate-spin text-[#848b9b]" /> <Loader2 size={10} className="animate-spin text-muted-foreground" />
<span className="text-[0.625rem] text-[#848b9b] font-sans text-xs">Loading similar sessions</span> <span className="text-[0.625rem] text-muted-foreground font-sans text-xs">Loading similar sessions</span>
</div> </div>
) )
} }
@@ -47,7 +47,7 @@ export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
return ( return (
<div className="space-y-2"> <div className="space-y-2">
<h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <h4 className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
Similar Past Sessions Similar Past Sessions
</h4> </h4>
{sessions.map((session) => ( {sessions.map((session) => (
@@ -57,21 +57,21 @@ export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
className="card-interactive p-3 block hover:border-[rgba(255,255,255,0.12)] transition-all" className="card-interactive p-3 block hover:border-[rgba(255,255,255,0.12)] transition-all"
> >
<div className="flex items-start justify-between gap-2"> <div className="flex items-start justify-between gap-2">
<p className="text-xs text-[#e2e5eb] line-clamp-2"> <p className="text-xs text-foreground line-clamp-2">
{session.problem_summary || 'Untitled session'} {session.problem_summary || 'Untitled session'}
</p> </p>
<span className="text-[0.625rem] font-sans text-xs text-[#22d3ee] shrink-0"> <span className="text-[0.625rem] font-sans text-xs text-primary shrink-0">
{Math.round(session.similarity * 100)}% {Math.round(session.similarity * 100)}%
</span> </span>
</div> </div>
{session.resolution_summary && ( {session.resolution_summary && (
<p className="text-[0.625rem] text-[#848b9b] mt-1 line-clamp-1"> <p className="text-[0.625rem] text-muted-foreground mt-1 line-clamp-1">
{session.resolution_summary} {session.resolution_summary}
</p> </p>
)} )}
<div className="flex items-center gap-2 mt-1.5"> <div className="flex items-center gap-2 mt-1.5">
{session.problem_domain && ( {session.problem_domain && (
<span className="text-[0.5rem] font-sans text-xs uppercase tracking-wider text-[#848b9b]/70"> <span className="text-[0.5rem] font-sans text-xs uppercase tracking-wider text-muted-foreground/70">
{session.problem_domain} {session.problem_domain}
</span> </span>
)} )}
@@ -82,7 +82,7 @@ export function SimilarSessions({ sessionId }: SimilarSessionsProps) {
? 'text-emerald-400' ? 'text-emerald-400'
: session.status === 'escalated' : session.status === 'escalated'
? 'text-amber-400' ? 'text-amber-400'
: 'text-[#848b9b]' : 'text-muted-foreground'
)} )}
> >
{session.status} {session.status}

View File

@@ -66,7 +66,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<div className="flex items-start justify-between gap-3"> <div className="flex items-start justify-between gap-3">
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b]"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground">
{node.node_type} {node.node_type}
</span> </span>
<span className={cn('font-sans text-xs text-[0.625rem]', confidenceTextColor(node.confidence_score))}> <span className={cn('font-sans text-xs text-[0.625rem]', confidenceTextColor(node.confidence_score))}>
@@ -85,27 +85,27 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<textarea <textarea
value={editContent} value={editContent}
onChange={e => setEditContent(e.target.value)} onChange={e => setEditContent(e.target.value)}
className="w-full rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb] focus:border-primary/30 focus:outline-hidden" className="w-full rounded-md border border-border bg-card px-3 py-2 text-sm text-foreground focus:border-primary/30 focus:outline-hidden"
rows={3} rows={3}
/> />
<div className="flex gap-2"> <div className="flex gap-2">
<button <button
onClick={() => handleAction('edit', { content: { ...node.content, question: editContent, content: editContent } })} onClick={() => handleAction('edit', { content: { ...node.content, question: editContent, content: editContent } })}
disabled={busy} disabled={busy}
className="px-3 py-1.5 text-xs font-medium rounded-md bg-[#22d3ee] text-white hover:brightness-110" className="px-3 py-1.5 text-xs font-medium rounded-md bg-primary text-white hover:brightness-110"
> >
Save Save
</button> </button>
<button <button
onClick={() => setEditMode(false)} onClick={() => setEditMode(false)}
className="px-3 py-1.5 text-xs font-medium rounded-md bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]" className="px-3 py-1.5 text-xs font-medium rounded-md bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground"
> >
Cancel Cancel
</button> </button>
</div> </div>
</div> </div>
) : ( ) : (
<p className="text-sm text-[#e2e5eb]">{stepContent || question}</p> <p className="text-sm text-foreground">{stepContent || question}</p>
)} )}
</div> </div>
@@ -116,7 +116,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<button <button
onClick={() => handleAction('approve')} onClick={() => handleAction('approve')}
disabled={busy} disabled={busy}
className="p-1.5 rounded-md text-[#848b9b] hover:text-emerald-400 hover:bg-emerald-400/10 transition-colors" className="p-1.5 rounded-md text-muted-foreground hover:text-emerald-400 hover:bg-emerald-400/10 transition-colors"
title="Approve" title="Approve"
> >
<Check size={14} /> <Check size={14} />
@@ -126,7 +126,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<button <button
onClick={() => handleAction('reject')} onClick={() => handleAction('reject')}
disabled={busy} disabled={busy}
className="p-1.5 rounded-md text-[#848b9b] hover:text-amber-400 hover:bg-amber-400/10 transition-colors" className="p-1.5 rounded-md text-muted-foreground hover:text-amber-400 hover:bg-amber-400/10 transition-colors"
title="Unapprove" title="Unapprove"
> >
<X size={14} /> <X size={14} />
@@ -135,7 +135,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<button <button
onClick={startEdit} onClick={startEdit}
disabled={busy} disabled={busy}
className="p-1.5 rounded-md text-[#848b9b] hover:text-blue-400 hover:bg-blue-400/10 transition-colors" className="p-1.5 rounded-md text-muted-foreground hover:text-blue-400 hover:bg-blue-400/10 transition-colors"
title="Edit" title="Edit"
> >
<Pencil size={14} /> <Pencil size={14} />
@@ -143,7 +143,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<button <button
onClick={() => handleAction('regenerate')} onClick={() => handleAction('regenerate')}
disabled={busy} disabled={busy}
className="p-1.5 rounded-md text-[#848b9b] hover:text-[#22d3ee] hover:bg-[rgba(34,211,238,0.10)] transition-colors" className="p-1.5 rounded-md text-muted-foreground hover:text-primary hover:bg-accent-dim transition-colors"
title="Regenerate" title="Regenerate"
> >
<RotateCcw size={14} /> <RotateCcw size={14} />
@@ -151,7 +151,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<button <button
onClick={() => handleAction('insert_after', { content: { question: 'New node', type: node.node_type } })} onClick={() => handleAction('insert_after', { content: { question: 'New node', type: node.node_type } })}
disabled={busy} disabled={busy}
className="p-1.5 rounded-md text-[#848b9b] hover:text-[#22d3ee] hover:bg-[rgba(34,211,238,0.10)] transition-colors" className="p-1.5 rounded-md text-muted-foreground hover:text-primary hover:bg-accent-dim transition-colors"
title="Insert after" title="Insert after"
> >
<Plus size={14} /> <Plus size={14} />
@@ -159,7 +159,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<button <button
onClick={() => handleAction('delete')} onClick={() => handleAction('delete')}
disabled={busy} disabled={busy}
className="p-1.5 rounded-md text-[#848b9b] hover:text-rose-500 hover:bg-rose-500/10 transition-colors" className="p-1.5 rounded-md text-muted-foreground hover:text-rose-500 hover:bg-rose-500/10 transition-colors"
title="Delete" title="Delete"
> >
<Trash2 size={14} /> <Trash2 size={14} />
@@ -173,16 +173,16 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
<div className="mt-3"> <div className="mt-3">
<button <button
onClick={() => setExpanded(!expanded)} onClick={() => setExpanded(!expanded)}
className="flex items-center gap-1 text-xs text-[#848b9b] hover:text-[#e2e5eb]" className="flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground"
> >
{expanded ? <ChevronUp size={12} /> : <ChevronDown size={12} />} {expanded ? <ChevronUp size={12} /> : <ChevronDown size={12} />}
{options.length} option{options.length !== 1 ? 's' : ''} {options.length} option{options.length !== 1 ? 's' : ''}
</button> </button>
{expanded && ( {expanded && (
<div className="mt-2 space-y-1 pl-3 border-l border-[#1e2130]"> <div className="mt-2 space-y-1 pl-3 border-l border-border">
{options.map((opt, i) => ( {options.map((opt, i) => (
<p key={i} className="text-xs text-[#848b9b]"> <p key={i} className="text-xs text-muted-foreground">
{opt.label} {opt.next_node_id && <span className="text-[#5a6170]"> {opt.next_node_id}</span>} {opt.label} {opt.next_node_id && <span className="text-text-muted"> {opt.next_node_id}</span>}
</p> </p>
))} ))}
</div> </div>
@@ -192,7 +192,7 @@ export function NodeCard({ node, onEdit, onHighlight }: NodeCardProps) {
{/* Source excerpt */} {/* Source excerpt */}
{node.source_excerpt && ( {node.source_excerpt && (
<p className="mt-2 text-xs text-[#5a6170] italic truncate" title={node.source_excerpt}> <p className="mt-2 text-xs text-text-muted italic truncate" title={node.source_excerpt}>
Source: {node.source_excerpt} Source: {node.source_excerpt}
</p> </p>
)} )}

View File

@@ -32,21 +32,21 @@ export function ReviewScreen({ kbImport, onEditNode, onApproveAll, onCommit, onD
{/* Header */} {/* Header */}
<div className="card-flat p-4 flex flex-wrap items-center justify-between gap-3"> <div className="card-flat p-4 flex flex-wrap items-center justify-between gap-3">
<div> <div>
<h2 className="text-lg font-heading font-semibold text-[#e2e5eb]">{flowTitle}</h2> <h2 className="text-lg font-heading font-semibold text-foreground">{flowTitle}</h2>
{flowDescription && ( {flowDescription && (
<p className="text-sm text-[#848b9b] mt-0.5">{flowDescription}</p> <p className="text-sm text-muted-foreground mt-0.5">{flowDescription}</p>
)} )}
</div> </div>
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="flex items-center gap-2 text-sm"> <div className="flex items-center gap-2 text-sm">
<BarChart3 size={14} className="text-[#848b9b]" /> <BarChart3 size={14} className="text-muted-foreground" />
<span className="text-[#848b9b]"> <span className="text-muted-foreground">
Avg confidence: <span className="text-[#e2e5eb] font-medium">{Math.round(avgConfidence * 100)}%</span> Avg confidence: <span className="text-foreground font-medium">{Math.round(avgConfidence * 100)}%</span>
</span> </span>
</div> </div>
<div className="flex items-center gap-2 text-sm"> <div className="flex items-center gap-2 text-sm">
<CheckCircle2 size={14} className="text-emerald-400" /> <CheckCircle2 size={14} className="text-emerald-400" />
<span className="text-[#848b9b]"> <span className="text-muted-foreground">
{approvedCount}/{nodes.length} approved {approvedCount}/{nodes.length} approved
</span> </span>
</div> </div>
@@ -90,8 +90,8 @@ export function ReviewScreen({ kbImport, onEditNode, onApproveAll, onCommit, onD
{/* Nodes panel */} {/* Nodes panel */}
<div className="flex flex-col card-flat overflow-hidden"> <div className="flex flex-col card-flat overflow-hidden">
<div className="flex items-center gap-2 px-4 py-3 border-b" style={{ borderColor: 'var(--glass-border)' }}> <div className="flex items-center gap-2 px-4 py-3 border-b" style={{ borderColor: 'var(--glass-border)' }}>
<span className="text-sm font-medium text-[#e2e5eb]">Generated Flow</span> <span className="text-sm font-medium text-foreground">Generated Flow</span>
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] ml-auto"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground ml-auto">
{kbImport.target_type === 'troubleshooting' ? 'Troubleshooting' : 'Project'} {kbImport.target_type === 'troubleshooting' ? 'Troubleshooting' : 'Project'}
</span> </span>
</div> </div>
@@ -105,7 +105,7 @@ export function ReviewScreen({ kbImport, onEditNode, onApproveAll, onCommit, onD
/> />
))} ))}
{nodes.length === 0 && ( {nodes.length === 0 && (
<p className="text-sm text-[#848b9b] text-center py-8"> <p className="text-sm text-muted-foreground text-center py-8">
No nodes generated. Try converting again. No nodes generated. Try converting again.
</p> </p>
)} )}
@@ -120,8 +120,8 @@ export function ReviewScreen({ kbImport, onEditNode, onApproveAll, onCommit, onD
disabled={loading} disabled={loading}
className={cn( className={cn(
'px-4 py-2.5 rounded-lg text-sm font-medium transition-colors', 'px-4 py-2.5 rounded-lg text-sm font-medium transition-colors',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#848b9b]', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-muted-foreground',
'hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]', 'hover:text-foreground hover:border-[rgba(255,255,255,0.12)]',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}
> >
@@ -132,7 +132,7 @@ export function ReviewScreen({ kbImport, onEditNode, onApproveAll, onCommit, onD
disabled={loading || nodes.length === 0} disabled={loading || nodes.length === 0}
className={cn( className={cn(
'flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-semibold transition-all', 'flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-semibold transition-all',
'bg-[#22d3ee] text-white', 'bg-primary text-white',
'hover:brightness-110 active:scale-[0.98]', 'hover:brightness-110 active:scale-[0.98]',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}

View File

@@ -17,7 +17,7 @@ export function SourcePanel({ sourceText, sourceFormat, highlightExcerpt }: Sour
return ( return (
<> <>
<span>{sourceText.slice(0, idx)}</span> <span>{sourceText.slice(0, idx)}</span>
<mark className="bg-primary/20 text-[#e2e5eb] rounded px-0.5">{highlightExcerpt}</mark> <mark className="bg-primary/20 text-foreground rounded px-0.5">{highlightExcerpt}</mark>
<span>{sourceText.slice(idx + highlightExcerpt.length)}</span> <span>{sourceText.slice(idx + highlightExcerpt.length)}</span>
</> </>
) )
@@ -26,14 +26,14 @@ export function SourcePanel({ sourceText, sourceFormat, highlightExcerpt }: Sour
return ( return (
<div className="card-flat flex flex-col h-full"> <div className="card-flat flex flex-col h-full">
<div className="flex items-center gap-2 px-4 py-3 border-b" style={{ borderColor: 'var(--glass-border)' }}> <div className="flex items-center gap-2 px-4 py-3 border-b" style={{ borderColor: 'var(--glass-border)' }}>
<FileText size={16} className="text-[#848b9b]" /> <FileText size={16} className="text-muted-foreground" />
<span className="text-sm font-medium text-[#e2e5eb]">Source Document</span> <span className="text-sm font-medium text-foreground">Source Document</span>
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] ml-auto"> <span className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground ml-auto">
{sourceFormat} {sourceFormat}
</span> </span>
</div> </div>
<div className="flex-1 overflow-y-auto p-4"> <div className="flex-1 overflow-y-auto p-4">
<pre className="text-sm text-[#848b9b] whitespace-pre-wrap font-sans leading-relaxed"> <pre className="text-sm text-muted-foreground whitespace-pre-wrap font-sans leading-relaxed">
{renderedText} {renderedText}
</pre> </pre>
</div> </div>

View File

@@ -18,10 +18,10 @@ export function SuccessScreen({ result, onViewFlow, onConvertAnother }: SuccessS
</div> </div>
<div> <div>
<h2 className="text-xl font-heading font-semibold text-[#e2e5eb]"> <h2 className="text-xl font-heading font-semibold text-foreground">
Flow Created Successfully Flow Created Successfully
</h2> </h2>
<p className="text-sm text-[#848b9b] mt-2"> <p className="text-sm text-muted-foreground mt-2">
Your KB article has been converted into a {result.tree_type === 'troubleshooting' ? 'troubleshooting' : 'project'} flow Your KB article has been converted into a {result.tree_type === 'troubleshooting' ? 'troubleshooting' : 'project'} flow
and added to your library. and added to your library.
</p> </p>
@@ -32,7 +32,7 @@ export function SuccessScreen({ result, onViewFlow, onConvertAnother }: SuccessS
onClick={onViewFlow} onClick={onViewFlow}
className={cn( className={cn(
'flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-semibold transition-all', 'flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-semibold transition-all',
'bg-[#22d3ee] text-white', 'bg-primary text-white',
'hover:brightness-110 active:scale-[0.98]' 'hover:brightness-110 active:scale-[0.98]'
)} )}
> >
@@ -43,7 +43,7 @@ export function SuccessScreen({ result, onViewFlow, onConvertAnother }: SuccessS
onClick={onConvertAnother} onClick={onConvertAnother}
className={cn( className={cn(
'flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-medium transition-colors', 'flex items-center gap-2 px-6 py-2.5 rounded-lg text-sm font-medium transition-colors',
'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#e2e5eb]', 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-foreground',
'hover:border-[rgba(255,255,255,0.12)]' 'hover:border-[rgba(255,255,255,0.12)]'
)} )}
> >

View File

@@ -84,14 +84,14 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
{quota && ( {quota && (
<div className="card-flat p-4 flex items-center justify-between"> <div className="card-flat p-4 flex items-center justify-between">
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Sparkles size={18} className="text-[#22d3ee]" /> <Sparkles size={18} className="text-primary" />
<div> <div>
<p className="text-sm font-medium text-[#e2e5eb]"> <p className="text-sm font-medium text-foreground">
{quota.lifetime_conversions_limit {quota.lifetime_conversions_limit
? `${quota.lifetime_conversions_limit - quota.lifetime_conversions_used} conversions remaining` ? `${quota.lifetime_conversions_limit - quota.lifetime_conversions_used} conversions remaining`
: 'Unlimited conversions'} : 'Unlimited conversions'}
</p> </p>
<p className="text-xs text-[#848b9b]"> <p className="text-xs text-muted-foreground">
{quota.plan.charAt(0).toUpperCase() + quota.plan.slice(1)} plan {quota.plan.charAt(0).toUpperCase() + quota.plan.slice(1)} plan
</p> </p>
</div> </div>
@@ -112,8 +112,8 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
className={cn( className={cn(
'flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors', 'flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors',
mode === 'paste' mode === 'paste'
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb] border border-primary/30' ? 'bg-accent-dim text-foreground border border-primary/30'
: 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]' : 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)]'
)} )}
> >
<ClipboardPaste size={16} /> <ClipboardPaste size={16} />
@@ -125,8 +125,8 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
className={cn( className={cn(
'flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors', 'flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium transition-colors',
mode === 'file' mode === 'file'
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb] border border-primary/30' ? 'bg-accent-dim text-foreground border border-primary/30'
: 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-[#848b9b] hover:text-[#e2e5eb] hover:border-[rgba(255,255,255,0.12)]' : 'bg-[rgba(255,255,255,0.04)] border border-[rgba(255,255,255,0.06)] text-muted-foreground hover:text-foreground hover:border-[rgba(255,255,255,0.12)]'
)} )}
> >
<FileUp size={16} /> <FileUp size={16} />
@@ -140,7 +140,7 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
{mode === 'paste' ? ( {mode === 'paste' ? (
<> <>
<div> <div>
<label htmlFor="kb-title" className="block font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-1.5"> <label htmlFor="kb-title" className="block font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1.5">
Title (optional) Title (optional)
</label> </label>
<Input <Input
@@ -152,7 +152,7 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
/> />
</div> </div>
<div> <div>
<label htmlFor="kb-content" className="block font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-1.5"> <label htmlFor="kb-content" className="block font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-1.5">
KB Article Content KB Article Content
</label> </label>
<Textarea <Textarea
@@ -163,7 +163,7 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
rows={12} rows={12}
maxLength={500000} maxLength={500000}
/> />
<p className="mt-1 text-xs text-[#848b9b]"> <p className="mt-1 text-xs text-muted-foreground">
{content.length.toLocaleString()} / 500,000 characters {content.length.toLocaleString()} / 500,000 characters
</p> </p>
</div> </div>
@@ -183,15 +183,15 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
> >
{file ? ( {file ? (
<> <>
<FileText size={32} className="text-[#22d3ee]" /> <FileText size={32} className="text-primary" />
<div className="text-center"> <div className="text-center">
<p className="text-sm font-medium text-[#e2e5eb]">{file.name}</p> <p className="text-sm font-medium text-foreground">{file.name}</p>
<p className="text-xs text-[#848b9b] mt-1"> <p className="text-xs text-muted-foreground mt-1">
{(file.size / 1024).toFixed(1)} KB {(file.size / 1024).toFixed(1)} KB
</p> </p>
<button <button
onClick={e => { e.stopPropagation(); setFile(null) }} onClick={e => { e.stopPropagation(); setFile(null) }}
className="mt-2 text-xs text-[#22d3ee] hover:underline" className="mt-2 text-xs text-primary hover:underline"
> >
Remove Remove
</button> </button>
@@ -199,12 +199,12 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
</> </>
) : ( ) : (
<> <>
<Upload size={32} className="text-[#848b9b]" /> <Upload size={32} className="text-muted-foreground" />
<div className="text-center"> <div className="text-center">
<p className="text-sm text-[#e2e5eb]"> <p className="text-sm text-foreground">
Drop a file here or <span className="text-[#22d3ee]">browse</span> Drop a file here or <span className="text-primary">browse</span>
</p> </p>
<p className="text-xs text-[#848b9b] mt-1"> <p className="text-xs text-muted-foreground mt-1">
Supported: {fileFormats.map(f => FORMAT_LABELS[f] || f.toUpperCase()).join(', ')} Supported: {fileFormats.map(f => FORMAT_LABELS[f] || f.toUpperCase()).join(', ')}
</p> </p>
</div> </div>
@@ -223,7 +223,7 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
{/* Target type selector */} {/* Target type selector */}
<div> <div>
<p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-[#848b9b] mb-2"> <p className="font-sans text-xs text-[0.625rem] uppercase tracking-[0.1em] text-muted-foreground mb-2">
Target Flow Type Target Flow Type
</p> </p>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3"> <div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
@@ -238,8 +238,8 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
: 'hover:border-[rgba(255,255,255,0.12)]' : 'hover:border-[rgba(255,255,255,0.12)]'
)} )}
> >
<p className="text-sm font-medium text-[#e2e5eb]">{t.label}</p> <p className="text-sm font-medium text-foreground">{t.label}</p>
<p className="text-xs text-[#848b9b] mt-1">{t.description}</p> <p className="text-xs text-muted-foreground mt-1">{t.description}</p>
</button> </button>
))} ))}
</div> </div>
@@ -251,7 +251,7 @@ export function UploadScreen({ quota, onSubmitText, onSubmitFile, loading }: Upl
disabled={!canSubmit || loading || (quota != null && !quota.can_convert)} disabled={!canSubmit || loading || (quota != null && !quota.can_convert)}
className={cn( className={cn(
'w-full flex items-center justify-center gap-2 px-6 py-3 rounded-lg text-sm font-semibold transition-all', 'w-full flex items-center justify-center gap-2 px-6 py-3 rounded-lg text-sm font-semibold transition-all',
'bg-[#22d3ee] text-white', 'bg-primary text-white',
'hover:brightness-110 active:scale-[0.98]', 'hover:brightness-110 active:scale-[0.98]',
'disabled:opacity-50 disabled:cursor-not-allowed' 'disabled:opacity-50 disabled:cursor-not-allowed'
)} )}

View File

@@ -80,7 +80,7 @@ export function AppLayout() {
<button <button
type="button" type="button"
onClick={() => setMobileMenuOpen(true)} onClick={() => setMobileMenuOpen(true)}
className="fixed left-4 top-3.5 z-50 rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors md:hidden" className="fixed left-4 top-3.5 z-50 rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors md:hidden"
aria-label="Open menu" aria-label="Open menu"
> >
<Menu size={20} /> <Menu size={20} />
@@ -101,12 +101,12 @@ export function AppLayout() {
<div className="flex h-14 items-center justify-between px-4" style={{ borderBottom: '1px solid #1e2130' }}> <div className="flex h-14 items-center justify-between px-4" style={{ borderBottom: '1px solid #1e2130' }}>
<Link to="/" className="flex items-center gap-2.5"> <Link to="/" className="flex items-center gap-2.5">
<BrandLogo size="sm" /> <BrandLogo size="sm" />
<span className="text-sm font-heading font-bold text-[#f0f2f5]">ResolutionFlow</span> <span className="text-sm font-heading font-bold text-text-heading">ResolutionFlow</span>
</Link> </Link>
<button <button
type="button" type="button"
onClick={() => setMobileMenuOpen(false)} onClick={() => setMobileMenuOpen(false)}
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb]" className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground"
aria-label="Close menu" aria-label="Close menu"
> >
<X size={18} /> <X size={18} />
@@ -116,9 +116,9 @@ export function AppLayout() {
<div className="flex flex-col p-3"> <div className="flex flex-col p-3">
{/* User info */} {/* User info */}
<div className="mb-3 pb-3 px-3" style={{ borderBottom: '1px solid #1e2130' }}> <div className="mb-3 pb-3 px-3" style={{ borderBottom: '1px solid #1e2130' }}>
<p className="text-sm font-medium text-[#e2e5eb]">{user?.name || user?.email}</p> <p className="text-sm font-medium text-foreground">{user?.name || user?.email}</p>
{effectiveRole && effectiveRole !== 'engineer' && ( {effectiveRole && effectiveRole !== 'engineer' && (
<span className="mt-1 inline-flex items-center gap-1 text-xs text-[#848b9b]"> <span className="mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground">
<Shield size={10} /> <Shield size={10} />
{effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'} {effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'}
</span> </span>
@@ -139,8 +139,8 @@ export function AppLayout() {
className={cn( className={cn(
'flex items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors', 'flex items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors',
isActive isActive
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]' ? 'bg-accent-dim text-foreground'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-input hover:text-foreground'
)} )}
> >
<Icon size={18} /> <Icon size={18} />
@@ -155,7 +155,7 @@ export function AppLayout() {
<button <button
type="button" type="button"
onClick={handleLogout} onClick={handleLogout}
className="flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb] transition-colors" className="flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium text-muted-foreground hover:bg-input hover:text-foreground transition-colors"
> >
<LogOut size={18} /> <LogOut size={18} />
Logout Logout

View File

@@ -48,7 +48,7 @@ export function NavItem({ href, icon: Icon, label, badge, iconColor, matchPaths,
title={label} title={label}
> >
{isActive && ( {isActive && (
<div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-[#22d3ee]" /> <div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-primary" />
)} )}
<Icon size={18} className={cn('shrink-0', isActive ? 'opacity-100' : 'opacity-70')} style={iconColor ? { color: iconColor } : undefined} /> <Icon size={18} className={cn('shrink-0', isActive ? 'opacity-100' : 'opacity-70')} style={iconColor ? { color: iconColor } : undefined} />
{badge !== undefined && badge !== 0 && badge !== 'dot' && ( {badge !== undefined && badge !== 0 && badge !== 'dot' && (
@@ -76,7 +76,7 @@ export function NavItem({ href, icon: Icon, label, badge, iconColor, matchPaths,
> >
{/* Active indicator bar */} {/* Active indicator bar */}
{isActive && !isParentDimmed && ( {isActive && !isParentDimmed && (
<div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-[#22d3ee]" /> <div className="absolute left-0 top-1/2 h-6 w-[3px] -translate-y-1/2 rounded-r-full bg-primary" />
)} )}
<Icon size={18} className={cn('shrink-0', isActive ? 'opacity-100' : 'opacity-70')} style={iconColor ? { color: iconColor } : undefined} /> <Icon size={18} className={cn('shrink-0', isActive ? 'opacity-100' : 'opacity-70')} style={iconColor ? { color: iconColor } : undefined} />

View File

@@ -254,15 +254,15 @@ export function Sidebar() {
className={cn( className={cn(
'group relative flex flex-col items-center justify-center rounded-lg px-1 py-2 transition-all duration-150', 'group relative flex flex-col items-center justify-center rounded-lg px-1 py-2 transition-all duration-150',
active active
? 'bg-[rgba(34,211,238,0.10)] text-[#67e8f9]' ? 'bg-accent-dim text-accent-text'
: 'text-[#6b7280] hover:text-[#848b9b]' : 'text-text-rail-label hover:text-muted-foreground'
)} )}
title={item.label} title={item.label}
> >
<span className="relative"> <span className="relative">
<Icon size={20} className={active ? 'opacity-100' : 'opacity-60 group-hover:opacity-85'} /> <Icon size={20} className={active ? 'opacity-100' : 'opacity-60 group-hover:opacity-85'} />
{item.badge !== undefined && item.badge > 0 && ( {item.badge !== undefined && item.badge > 0 && (
<span className="absolute -right-1.5 -top-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-[#22d3ee] px-1 text-[0.5rem] font-bold text-[#0c0d10]"> <span className="absolute -right-1.5 -top-1.5 flex h-4 min-w-[16px] items-center justify-center rounded-full bg-primary px-1 text-[0.5rem] font-bold text-[#0c0d10]">
{item.badge > 99 ? '99+' : item.badge} {item.badge > 99 ? '99+' : item.badge}
</span> </span>
)} )}
@@ -293,9 +293,9 @@ 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-[#e2e5eb]/70' ? 'bg-[rgba(34,211,238,0.05)] text-foreground/70'
: 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]' : 'bg-accent-dim text-foreground'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-input hover:text-foreground'
)} )}
> >
{active && !isParentDimmed && ( {active && !isParentDimmed && (
@@ -307,7 +307,7 @@ export function Sidebar() {
<Icon size={18} className={cn('shrink-0', active ? 'opacity-100' : 'opacity-70')} /> <Icon size={18} className={cn('shrink-0', active ? 'opacity-100' : 'opacity-70')} />
<span className="truncate">{item.label}</span> <span className="truncate">{item.label}</span>
{item.badge !== undefined && item.badge > 0 && ( {item.badge !== undefined && item.badge > 0 && (
<span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-[#4f5666]" <span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-text-muted"
style={{ background: '#14161d', border: '1px solid #1e2130' }}> style={{ background: '#14161d', border: '1px solid #1e2130' }}>
{item.badge} {item.badge}
</span> </span>
@@ -331,13 +331,13 @@ export function Sidebar() {
className={cn( className={cn(
'flex items-center gap-2 rounded-lg pl-9 pr-3 py-1.5 text-[0.8125rem] font-medium transition-colors', 'flex items-center gap-2 rounded-lg pl-9 pr-3 py-1.5 text-[0.8125rem] font-medium transition-colors',
childActive childActive
? 'bg-[rgba(34,211,238,0.10)] text-[#e2e5eb]' ? 'bg-accent-dim text-foreground'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-input hover:text-foreground'
)} )}
> >
<span className="truncate">{child.label}</span> <span className="truncate">{child.label}</span>
{child.count !== undefined && ( {child.count !== undefined && (
<span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-[#4f5666]" <span className="ml-auto shrink-0 rounded-full px-2 text-[0.6875rem] font-mono text-text-muted"
style={{ background: '#14161d', border: '1px solid #1e2130' }}> style={{ background: '#14161d', border: '1px solid #1e2130' }}>
{child.count} {child.count}
</span> </span>
@@ -373,7 +373,7 @@ export function Sidebar() {
{sections.map((section, si) => ( {sections.map((section, si) => (
<div key={section.title}> <div key={section.title}>
{si > 0 && ( {si > 0 && (
<div className="font-mono text-[0.5625rem] uppercase tracking-[0.12em] text-[#4f5666] px-3 pt-3 pb-1"> <div className="font-mono text-[0.5625rem] uppercase tracking-[0.12em] text-text-muted px-3 pt-3 pb-1">
{section.title} {section.title}
</div> </div>
)} )}
@@ -390,7 +390,7 @@ export function Sidebar() {
<button <button
type="button" type="button"
onClick={toggleSidebarPinned} onClick={toggleSidebarPinned}
className="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-[0.8125rem] font-medium text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb] transition-colors" className="flex w-full items-center gap-3 rounded-lg px-3 py-2 text-[0.8125rem] font-medium text-muted-foreground hover:bg-input hover:text-foreground transition-colors"
title="Unpin sidebar" title="Unpin sidebar"
> >
<PinOff size={18} className="shrink-0" /> <PinOff size={18} className="shrink-0" />
@@ -427,7 +427,7 @@ export function Sidebar() {
<button <button
type="button" type="button"
onClick={toggleSidebarPinned} onClick={toggleSidebarPinned}
className="flex flex-col items-center justify-center rounded-lg px-1 py-2 text-[#6b7280] hover:text-[#848b9b] transition-colors" className="flex flex-col items-center justify-center rounded-lg px-1 py-2 text-text-rail-label hover:text-muted-foreground transition-colors"
title="Pin sidebar" title="Pin sidebar"
> >
<Pin size={18} className="opacity-60 hover:opacity-85" /> <Pin size={18} className="opacity-60 hover:opacity-85" />
@@ -455,7 +455,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-[#4f5666]"> <h3 className="text-[0.6875rem] font-mono uppercase tracking-[0.12em] text-text-muted">
{activeFlyoutGroup.label} {activeFlyoutGroup.label}
</h3> </h3>
</div> </div>
@@ -469,13 +469,13 @@ export function Sidebar() {
className={cn( className={cn(
'flex items-center justify-between rounded-md px-3 py-2 text-[0.8125rem] transition-colors', 'flex items-center justify-between rounded-md px-3 py-2 text-[0.8125rem] transition-colors',
isChildActive(child) isChildActive(child)
? 'bg-[rgba(34,211,238,0.10)] text-[#67e8f9]' ? 'bg-accent-dim text-accent-text'
: 'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-input hover:text-foreground'
)} )}
> >
<span>{child.label}</span> <span>{child.label}</span>
{child.count !== undefined && ( {child.count !== undefined && (
<span className="text-[0.6875rem] font-mono text-[#4f5666]">{child.count}</span> <span className="text-[0.6875rem] font-mono text-text-muted">{child.count}</span>
)} )}
</Link> </Link>
))} ))}
@@ -484,7 +484,7 @@ export function Sidebar() {
{/* Resize handle */} {/* Resize handle */}
<div <div
className="w-1 cursor-col-resize hover:bg-[#22d3ee]/20 active:bg-[#22d3ee]/30 transition-colors shrink-0" className="w-1 cursor-col-resize hover:bg-primary/20 active:bg-primary/30 transition-colors shrink-0"
onPointerDown={handleResizeStart} onPointerDown={handleResizeStart}
title="Drag to resize" title="Drag to resize"
/> />

View File

@@ -67,7 +67,7 @@ export function TopBar() {
className="flex items-center gap-2.5 pr-4 transition-all duration-200" className="flex items-center gap-2.5 pr-4 transition-all duration-200"
> >
<BrandLogo size="sm" /> <BrandLogo size="sm" />
<span className="text-sm font-heading font-bold tracking-tight whitespace-nowrap text-[#f0f2f5]"> <span className="text-sm font-heading font-bold tracking-tight whitespace-nowrap text-text-heading">
ResolutionFlow ResolutionFlow
</span> </span>
</Link> </Link>
@@ -81,9 +81,9 @@ export function TopBar() {
className="hidden sm:relative sm:block w-full text-left" className="hidden sm:relative sm:block w-full text-left"
style={{ maxWidth: '480px' }} style={{ maxWidth: '480px' }}
> >
<Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-[#848b9b]" /> <Search size={16} className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" />
<div <div
className="w-full rounded-md py-2 pl-9 pr-14 text-[0.8125rem] text-[#848b9b] cursor-pointer transition-colors" className="w-full rounded-md py-2 pl-9 pr-14 text-[0.8125rem] text-muted-foreground cursor-pointer transition-colors"
style={{ style={{
background: '#14161d', background: '#14161d',
border: '1px solid #1e2130', border: '1px solid #1e2130',
@@ -94,7 +94,7 @@ export function TopBar() {
Search flows, sessions, tags... Search flows, sessions, tags...
</div> </div>
<span <span
className="absolute right-3 top-1/2 -translate-y-1/2 rounded px-1.5 py-0.5 font-mono text-[0.625rem] text-[#4f5666]" className="absolute right-3 top-1/2 -translate-y-1/2 rounded px-1.5 py-0.5 font-mono text-[0.625rem] text-text-muted"
style={{ background: '#0c0d10', border: '1px solid #1e2130' }} style={{ background: '#0c0d10', border: '1px solid #1e2130' }}
> >
{navigator.platform?.toLowerCase().includes('mac') ? '\u2318K' : 'Ctrl+K'} {navigator.platform?.toLowerCase().includes('mac') ? '\u2318K' : 'Ctrl+K'}
@@ -102,7 +102,7 @@ export function TopBar() {
</button> </button>
<button <button
onClick={() => setCommandPaletteOpen(true)} onClick={() => setCommandPaletteOpen(true)}
className="sm:hidden rounded-lg p-2 text-[#848b9b] hover:text-[#e2e5eb] transition-colors" className="sm:hidden rounded-lg p-2 text-muted-foreground hover:text-foreground transition-colors"
title="Search" title="Search"
> >
<Search size={18} /> <Search size={18} />
@@ -115,14 +115,14 @@ export function TopBar() {
<div className="flex items-center gap-1"> <div className="flex items-center gap-1">
<button <button
onClick={() => setQuickLaunchOpen(true)} onClick={() => setQuickLaunchOpen(true)}
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors" className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors"
title="Quick Launch" title="Quick Launch"
> >
<Zap size={18} /> <Zap size={18} />
</button> </button>
<Link <Link
to="/guides" to="/guides"
className="rounded-lg p-2 text-[#848b9b] hover:bg-[#14161d] hover:text-[#e2e5eb] transition-colors" className="rounded-lg p-2 text-muted-foreground hover:bg-card hover:text-foreground transition-colors"
title="User Guides" title="User Guides"
> >
<HelpCircle size={18} /> <HelpCircle size={18} />
@@ -146,9 +146,9 @@ export function TopBar() {
style={{ background: '#14161d', border: '1px solid #1e2130' }} style={{ background: '#14161d', border: '1px solid #1e2130' }}
> >
<div className="px-3 py-2.5 mb-1" style={{ borderBottom: '1px solid #1e2130' }}> <div className="px-3 py-2.5 mb-1" style={{ borderBottom: '1px solid #1e2130' }}>
<p className="text-sm font-medium text-[#e2e5eb] truncate">{user?.name || user?.email}</p> <p className="text-sm font-medium text-foreground truncate">{user?.name || user?.email}</p>
{effectiveRole && effectiveRole !== 'engineer' && ( {effectiveRole && effectiveRole !== 'engineer' && (
<span className="mt-1 inline-flex items-center gap-1 text-xs text-[#848b9b]"> <span className="mt-1 inline-flex items-center gap-1 text-xs text-muted-foreground">
<Shield size={10} /> <Shield size={10} />
{effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'} {effectiveRole === 'super_admin' ? 'Super Admin' : effectiveRole === 'owner' ? 'Owner' : 'Viewer'}
</span> </span>
@@ -157,7 +157,7 @@ export function TopBar() {
<Link <Link
to="/account" to="/account"
onClick={() => setUserMenuOpen(false)} onClick={() => setUserMenuOpen(false)}
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]" className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-input hover:text-foreground"
> >
<Settings size={14} /> <Settings size={14} />
Account Account
@@ -166,7 +166,7 @@ export function TopBar() {
<Link <Link
to="/admin" to="/admin"
onClick={() => setUserMenuOpen(false)} onClick={() => setUserMenuOpen(false)}
className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]" className="flex items-center gap-2 rounded-md px-3 py-2 text-sm text-muted-foreground hover:bg-input hover:text-foreground"
> >
<Shield size={14} /> <Shield size={14} />
Admin Panel Admin Panel
@@ -177,7 +177,7 @@ export function TopBar() {
onClick={handleLogout} onClick={handleLogout}
className={cn( className={cn(
'flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm', 'flex w-full items-center gap-2 rounded-md px-3 py-2 text-sm',
'text-[#848b9b] hover:bg-[#191c25] hover:text-[#e2e5eb]' 'text-muted-foreground hover:bg-input hover:text-foreground'
)} )}
> >
<LogOut size={14} /> <LogOut size={14} />

View File

@@ -89,8 +89,8 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
setIsOpen(!isOpen) setIsOpen(!isOpen)
}} }}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-1.5 text-[#848b9b]', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Add to folder" title="Add to folder"
aria-label="Add to folder" aria-label="Add to folder"
@@ -101,14 +101,14 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
{isOpen && ( {isOpen && (
<div <div
className={cn( className={cn(
'absolute right-0 top-full z-20 mt-1 w-48 rounded-md border border-[#1e2130]', 'absolute right-0 top-full z-20 mt-1 w-48 rounded-md border border-border',
'bg-[#14161d] py-1 shadow-lg' 'bg-card py-1 shadow-lg'
)} )}
> >
{isLoading ? ( {isLoading ? (
<div className="px-3 py-2 text-sm text-[#848b9b]">Loading...</div> <div className="px-3 py-2 text-sm text-muted-foreground">Loading...</div>
) : folders.length === 0 ? ( ) : folders.length === 0 ? (
<div className="px-3 py-2 text-sm text-[#848b9b]">No folders yet</div> <div className="px-3 py-2 text-sm text-muted-foreground">No folders yet</div>
) : ( ) : (
folders.map((folder) => ( folders.map((folder) => (
<button <button
@@ -117,7 +117,7 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
e.stopPropagation() e.stopPropagation()
toggleFolder(folder.id) toggleFolder(folder.id)
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<div <div
className="h-3 w-3 rounded-sm" className="h-3 w-3 rounded-sm"
@@ -125,13 +125,13 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
/> />
<span className="flex-1 truncate text-left">{folder.name}</span> <span className="flex-1 truncate text-left">{folder.name}</span>
{treeFolderIds.has(folder.id) && ( {treeFolderIds.has(folder.id) && (
<Check className="h-4 w-4 text-[#e2e5eb]" /> <Check className="h-4 w-4 text-foreground" />
)} )}
</button> </button>
)) ))
)} )}
<div className="border-t border-[#1e2130] my-1" /> <div className="border-t border-border my-1" />
<button <button
onClick={(e) => { onClick={(e) => {
@@ -139,7 +139,7 @@ export function AddToFolderMenu({ treeId, onFolderCreated }: AddToFolderMenuProp
setIsOpen(false) setIsOpen(false)
onFolderCreated?.() onFolderCreated?.()
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
Create new folder Create new folder

View File

@@ -53,19 +53,19 @@ export function ExportFlowModal({ treeId, treeName, onClose }: ExportFlowModalPr
onClick={onClose} onClick={onClose}
> >
<div <div
className="w-full max-w-sm rounded-xl border border-[#1e2130] bg-[#14161d] shadow-xl" className="w-full max-w-sm rounded-xl border border-border bg-card shadow-xl"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-[#1e2130] 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">
<Download className="h-4 w-4 text-[#848b9b]" /> <Download className="h-4 w-4 text-muted-foreground" />
<h2 className="text-sm font-semibold text-[#e2e5eb]">Export Flow</h2> <h2 className="text-sm font-semibold text-foreground">Export Flow</h2>
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
aria-label="Close" aria-label="Close"
className="rounded-md p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </button>
@@ -73,13 +73,13 @@ export function ExportFlowModal({ treeId, treeName, onClose }: ExportFlowModalPr
{/* Body */} {/* Body */}
<div className="px-5 py-4"> <div className="px-5 py-4">
<p className="text-sm text-[#848b9b]"> <p className="text-sm text-muted-foreground">
Export <span className="font-medium text-[#e2e5eb]">{treeName}</span> as a <code className="text-xs font-sans text-xs">.rfflow</code> file (JSON format). Export <span className="font-medium text-foreground">{treeName}</span> as a <code className="text-xs font-sans text-xs">.rfflow</code> file (JSON format).
</p> </p>
</div> </div>
{/* Footer */} {/* Footer */}
<div className="flex justify-end gap-2 border-t border-[#1e2130] px-5 py-3"> <div className="flex justify-end gap-2 border-t border-border px-5 py-3">
<Button variant="secondary" onClick={onClose}> <Button variant="secondary" onClick={onClose}>
Cancel Cancel
</Button> </Button>

View File

@@ -178,12 +178,12 @@ export function FolderEditModal({
<div className="absolute inset-0 bg-black/80" onClick={onClose} /> <div className="absolute inset-0 bg-black/80" onClick={onClose} />
{/* Modal */} {/* Modal */}
<div className="relative z-10 w-full max-w-md bg-[#14161d] border border-[#1e2130] rounded-2xl p-6 shadow-lg"> <div className="relative z-10 w-full max-w-md bg-card border border-border rounded-2xl p-6 shadow-lg">
<div className="mb-4 flex items-center justify-between"> <div className="mb-4 flex items-center justify-between">
<h2 className="text-lg font-semibold text-[#e2e5eb]"> <h2 className="text-lg font-semibold text-foreground">
{isEditMode ? 'Edit Folder' : initialParentId ? 'Create Subfolder' : 'Create Folder'} {isEditMode ? 'Edit Folder' : initialParentId ? 'Create Subfolder' : 'Create Folder'}
</h2> </h2>
<button onClick={onClose} className="rounded-md p-1 text-[#848b9b] hover:bg-accent/50 hover:text-[#e2e5eb]"> <button onClick={onClose} className="rounded-md p-1 text-muted-foreground hover:bg-accent/50 hover:text-foreground">
<X className="h-5 w-5" /> <X className="h-5 w-5" />
</button> </button>
</div> </div>
@@ -191,7 +191,7 @@ export function FolderEditModal({
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
{/* Name input */} {/* Name input */}
<div className="mb-4"> <div className="mb-4">
<label htmlFor="folder-name" className="block text-sm font-medium text-[#e2e5eb]"> <label htmlFor="folder-name" className="block text-sm font-medium text-foreground">
Name Name
</label> </label>
<input <input
@@ -202,9 +202,9 @@ export function FolderEditModal({
placeholder="e.g., Citrix Issues" placeholder="e.g., Citrix Issues"
className={cn( className={cn(
'mt-1 block w-full rounded-md border px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border px-3 py-2 text-sm',
'bg-[#14161d] text-[#e2e5eb] placeholder:text-[#848b9b]', 'bg-card text-foreground placeholder:text-muted-foreground',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20', 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
'border-[#1e2130]' 'border-border'
)} )}
autoFocus autoFocus
/> />
@@ -212,7 +212,7 @@ export function FolderEditModal({
{/* Parent folder dropdown */} {/* Parent folder dropdown */}
<div className="mb-4"> <div className="mb-4">
<label htmlFor="folder-parent" className="block text-sm font-medium text-[#e2e5eb]"> <label htmlFor="folder-parent" className="block text-sm font-medium text-foreground">
Parent Folder Parent Folder
</label> </label>
<select <select
@@ -221,9 +221,9 @@ export function FolderEditModal({
onChange={(e) => setParentId(e.target.value || null)} onChange={(e) => setParentId(e.target.value || null)}
className={cn( className={cn(
'mt-1 block w-full rounded-md border px-3 py-2 text-sm', 'mt-1 block w-full rounded-md border px-3 py-2 text-sm',
'bg-[#14161d] text-[#e2e5eb]', 'bg-card text-foreground',
'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20', 'focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20',
'border-[#1e2130]' 'border-border'
)} )}
> >
<option value="">None (root level)</option> <option value="">None (root level)</option>
@@ -233,14 +233,14 @@ export function FolderEditModal({
</option> </option>
))} ))}
</select> </select>
<p className="mt-1 text-xs text-[#848b9b]"> <p className="mt-1 text-xs text-muted-foreground">
Folders can be nested up to 3 levels deep. Folders can be nested up to 3 levels deep.
</p> </p>
</div> </div>
{/* Color picker */} {/* Color picker */}
<div className="mb-6"> <div className="mb-6">
<label className="block text-sm font-medium text-[#e2e5eb]">Color</label> <label className="block text-sm font-medium text-foreground">Color</label>
<div className="mt-2 flex flex-wrap gap-2"> <div className="mt-2 flex flex-wrap gap-2">
{FOLDER_COLORS.map((c) => ( {FOLDER_COLORS.map((c) => (
<button <button

View File

@@ -115,7 +115,7 @@ function FolderItem({
className={cn( className={cn(
'flex w-full items-center gap-1 rounded-md py-1.5 text-sm', 'flex w-full items-center gap-1 rounded-md py-1.5 text-sm',
'transition-colors hover:bg-accent', 'transition-colors hover:bg-accent',
selectedFolderId === folder.id && 'bg-accent text-[#e2e5eb] font-medium' selectedFolderId === folder.id && 'bg-accent text-foreground font-medium'
)} )}
style={{ paddingLeft: `${8 + depth * 16}px`, paddingRight: '8px' }} style={{ paddingLeft: `${8 + depth * 16}px`, paddingRight: '8px' }}
> >
@@ -139,7 +139,7 @@ function FolderItem({
)} )}
<Folder className="h-4 w-4 shrink-0" style={{ color: folder.color }} /> <Folder className="h-4 w-4 shrink-0" style={{ color: folder.color }} />
<span className="flex-1 truncate text-left">{folder.name}</span> <span className="flex-1 truncate text-left">{folder.name}</span>
<span className="text-xs text-[#848b9b] group-hover:hidden">{folder.tree_count}</span> <span className="text-xs text-muted-foreground group-hover:hidden">{folder.tree_count}</span>
</button> </button>
{/* Folder menu button - replaces tree count on hover */} {/* Folder menu button - replaces tree count on hover */}
@@ -161,8 +161,8 @@ function FolderItem({
{menuOpenId === folder.id && ( {menuOpenId === folder.id && (
<div <div
className={cn( className={cn(
'absolute right-0 top-full z-10 mt-1 w-40 rounded-md border border-[#1e2130]', 'absolute right-0 top-full z-10 mt-1 w-40 rounded-md border border-border',
'bg-[#14161d] py-1 shadow-lg' 'bg-card py-1 shadow-lg'
)} )}
> >
<button <button
@@ -171,7 +171,7 @@ function FolderItem({
onEditFolder(folder) onEditFolder(folder)
onMenuToggle(null) onMenuToggle(null)
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<Pencil className="h-3 w-3" /> <Pencil className="h-3 w-3" />
Edit Edit
@@ -183,7 +183,7 @@ function FolderItem({
onAddSubfolder(folder.id) onAddSubfolder(folder.id)
onMenuToggle(null) onMenuToggle(null)
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<FolderPlus className="h-3 w-3" /> <FolderPlus className="h-3 w-3" />
Add Subfolder Add Subfolder
@@ -368,7 +368,7 @@ export function FolderSidebar({
/> />
)} )}
<div className={cn( <div className={cn(
'w-56 shrink-0 border-r border-[#1e2130] bg-transparent', 'w-56 shrink-0 border-r border-border bg-transparent',
'hidden md:block', 'hidden md:block',
mobileOpen && 'fixed inset-y-0 left-0 z-50 block animate-slide-in-left md:relative md:animate-none' mobileOpen && 'fixed inset-y-0 left-0 z-50 block animate-slide-in-left md:relative md:animate-none'
)}> )}>
@@ -376,10 +376,10 @@ export function FolderSidebar({
{/* Mobile close button */} {/* Mobile close button */}
{mobileOpen && ( {mobileOpen && (
<div className="mb-3 flex items-center justify-between md:hidden"> <div className="mb-3 flex items-center justify-between md:hidden">
<span className="text-sm font-medium text-[#e2e5eb]">Folders</span> <span className="text-sm font-medium text-foreground">Folders</span>
<button <button
onClick={onMobileClose} onClick={onMobileClose}
className="rounded-md p-1.5 text-[#848b9b] hover:bg-accent" className="rounded-md p-1.5 text-muted-foreground hover:bg-accent"
aria-label="Close folders" aria-label="Close folders"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
@@ -388,7 +388,7 @@ export function FolderSidebar({
)} )}
<button <button
onClick={() => setIsExpanded(!isExpanded)} onClick={() => setIsExpanded(!isExpanded)}
className="flex w-full items-center gap-2 text-sm font-medium text-[#e2e5eb]" className="flex w-full items-center gap-2 text-sm font-medium text-foreground"
> >
{isExpanded ? ( {isExpanded ? (
<ChevronDown className="h-4 w-4" /> <ChevronDown className="h-4 w-4" />
@@ -406,7 +406,7 @@ export function FolderSidebar({
className={cn( className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm', 'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm',
'transition-colors hover:bg-accent', 'transition-colors hover:bg-accent',
selectedFolderId === null && 'bg-accent text-[#e2e5eb] font-medium' selectedFolderId === null && 'bg-accent text-foreground font-medium'
)} )}
> >
<Folder className="h-4 w-4" /> <Folder className="h-4 w-4" />
@@ -415,7 +415,7 @@ export function FolderSidebar({
{/* Loading state */} {/* Loading state */}
{isLoading ? ( {isLoading ? (
<div className="px-2 py-1.5 text-sm text-[#848b9b]">Loading...</div> <div className="px-2 py-1.5 text-sm text-muted-foreground">Loading...</div>
) : ( ) : (
<> <>
{/* User folders (hierarchical) */} {/* User folders (hierarchical) */}
@@ -445,7 +445,7 @@ export function FolderSidebar({
onClick={() => onCreateFolder(null)} onClick={() => onCreateFolder(null)}
className={cn( className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm', 'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm',
'text-[#848b9b] transition-colors hover:bg-accent hover:text-[#e2e5eb]' 'text-muted-foreground transition-colors hover:bg-accent hover:text-foreground'
)} )}
> >
<Plus className="h-4 w-4" /> <Plus className="h-4 w-4" />
@@ -460,8 +460,8 @@ export function FolderSidebar({
{contextMenu && ( {contextMenu && (
<div <div
className={cn( className={cn(
'fixed z-50 w-44 rounded-md border border-[#1e2130]', 'fixed z-50 w-44 rounded-md border border-border',
'bg-[#14161d] py-1 shadow-lg' 'bg-card py-1 shadow-lg'
)} )}
style={{ left: contextMenu.x, top: contextMenu.y }} style={{ left: contextMenu.x, top: contextMenu.y }}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
@@ -471,7 +471,7 @@ export function FolderSidebar({
onEditFolder(contextMenu.folder) onEditFolder(contextMenu.folder)
closeContextMenu() closeContextMenu()
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<Pencil className="h-3 w-3" /> <Pencil className="h-3 w-3" />
Edit Edit
@@ -482,7 +482,7 @@ export function FolderSidebar({
handleAddSubfolder(contextMenu.folder.id) handleAddSubfolder(contextMenu.folder.id)
closeContextMenu() closeContextMenu()
}} }}
className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="flex w-full items-center gap-2 px-3 py-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<FolderPlus className="h-3 w-3" /> <FolderPlus className="h-3 w-3" />
Add Subfolder Add Subfolder

View File

@@ -54,19 +54,19 @@ export function ForkModal({ treeId, treeName, onClose }: ForkModalProps) {
onClick={onClose} onClick={onClose}
> >
<div <div
className="w-full max-w-md rounded-xl border border-[#1e2130] bg-[#14161d] shadow-xl" className="w-full max-w-md rounded-xl border border-border bg-card shadow-xl"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-[#1e2130] 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">
<GitBranch className="h-4 w-4 text-[#848b9b]" /> <GitBranch className="h-4 w-4 text-muted-foreground" />
<h2 className="text-sm font-semibold text-[#e2e5eb]">Fork Flow</h2> <h2 className="text-sm font-semibold text-foreground">Fork Flow</h2>
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
aria-label="Close" aria-label="Close"
className="rounded-md p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </button>
@@ -75,7 +75,7 @@ export function ForkModal({ treeId, treeName, onClose }: ForkModalProps) {
{/* Body */} {/* Body */}
<form onSubmit={handleSubmit} className="space-y-4 px-5 py-4"> <form onSubmit={handleSubmit} className="space-y-4 px-5 py-4">
<div> <div>
<label htmlFor="fork-name" className="mb-1.5 block text-xs font-medium text-[#848b9b]"> <label htmlFor="fork-name" className="mb-1.5 block text-xs font-medium text-muted-foreground">
Name <span className="text-red-400">*</span> Name <span className="text-red-400">*</span>
</label> </label>
<input <input
@@ -87,16 +87,16 @@ export function ForkModal({ treeId, treeName, onClose }: ForkModalProps) {
autoFocus autoFocus
maxLength={255} maxLength={255}
className={cn( className={cn(
'w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb]', 'w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground',
'placeholder:text-[#848b9b] focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'placeholder:text-muted-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
</div> </div>
<div> <div>
<label htmlFor="fork-reason" className="mb-1.5 block text-xs font-medium text-[#848b9b]"> <label htmlFor="fork-reason" className="mb-1.5 block text-xs font-medium text-muted-foreground">
Reason for Forking{' '} Reason for Forking{' '}
<span className="text-[#848b9b]/60">(optional)</span> <span className="text-muted-foreground/60">(optional)</span>
</label> </label>
<textarea <textarea
id="fork-reason" id="fork-reason"
@@ -105,8 +105,8 @@ export function ForkModal({ treeId, treeName, onClose }: ForkModalProps) {
rows={3} rows={3}
placeholder="e.g. customizing for a specific client…" placeholder="e.g. customizing for a specific client…"
className={cn( className={cn(
'w-full resize-none rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb]', 'w-full resize-none rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground',
'placeholder:text-[#848b9b] focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'placeholder:text-muted-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
</div> </div>

View File

@@ -95,19 +95,19 @@ export function ImportFlowModal({ onClose }: ImportFlowModalProps) {
onClick={onClose} onClick={onClose}
> >
<div <div
className="w-full max-w-md rounded-xl border border-[#1e2130] bg-[#14161d] shadow-xl" className="w-full max-w-md rounded-xl border border-border bg-card shadow-xl"
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-[#1e2130] 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">
<FileUp className="h-4 w-4 text-[#848b9b]" /> <FileUp className="h-4 w-4 text-muted-foreground" />
<h2 className="text-sm font-semibold text-[#e2e5eb]">Import Flow</h2> <h2 className="text-sm font-semibold text-foreground">Import Flow</h2>
</div> </div>
<button <button
onClick={onClose} onClick={onClose}
aria-label="Close" aria-label="Close"
className="rounded-md p-1 text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]" className="rounded-md p-1 text-muted-foreground hover:bg-accent hover:text-foreground"
> >
<X className="h-4 w-4" /> <X className="h-4 w-4" />
</button> </button>
@@ -122,18 +122,18 @@ export function ImportFlowModal({ onClose }: ImportFlowModalProps) {
'flex flex-col items-center justify-center rounded-lg border-2 border-dashed px-4 py-8 text-center transition-colors cursor-pointer', 'flex flex-col items-center justify-center rounded-lg border-2 border-dashed px-4 py-8 text-center transition-colors cursor-pointer',
isDragging isDragging
? 'border-primary/50 bg-primary/5' ? 'border-primary/50 bg-primary/5'
: 'border-[#1e2130] hover:border-[#2a2f3d]' : 'border-border hover:border-border-hover'
)} )}
onClick={() => fileInputRef.current?.click()} onClick={() => fileInputRef.current?.click()}
onDragOver={(e) => { e.preventDefault(); setIsDragging(true) }} onDragOver={(e) => { e.preventDefault(); setIsDragging(true) }}
onDragLeave={() => setIsDragging(false)} onDragLeave={() => setIsDragging(false)}
onDrop={handleDrop} onDrop={handleDrop}
> >
<FileUp className="mb-2 h-8 w-8 text-[#848b9b]" /> <FileUp className="mb-2 h-8 w-8 text-muted-foreground" />
<p className="text-sm text-[#e2e5eb]"> <p className="text-sm text-foreground">
Drop .rfflow file here or <span className="text-[#22d3ee] cursor-pointer">browse</span> Drop .rfflow file here or <span className="text-primary cursor-pointer">browse</span>
</p> </p>
<p className="mt-1 text-xs text-[#848b9b]">JSON format</p> <p className="mt-1 text-xs text-muted-foreground">JSON format</p>
</div> </div>
<input <input
ref={fileInputRef} ref={fileInputRef}
@@ -155,7 +155,7 @@ export function ImportFlowModal({ onClose }: ImportFlowModalProps) {
<div className="space-y-4"> <div className="space-y-4">
{/* Editable name */} {/* Editable name */}
<div> <div>
<label htmlFor="import-name" className="mb-1.5 block text-xs font-medium text-[#848b9b]"> <label htmlFor="import-name" className="mb-1.5 block text-xs font-medium text-muted-foreground">
Name Name
</label> </label>
<input <input
@@ -165,8 +165,8 @@ export function ImportFlowModal({ onClose }: ImportFlowModalProps) {
onChange={(e) => setNameOverride(e.target.value)} onChange={(e) => setNameOverride(e.target.value)}
maxLength={255} maxLength={255}
className={cn( className={cn(
'w-full rounded-lg border border-[#1e2130] bg-[#14161d] px-3 py-2 text-sm text-[#e2e5eb]', 'w-full rounded-lg border border-border bg-card px-3 py-2 text-sm text-foreground',
'placeholder:text-[#848b9b] focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'placeholder:text-muted-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
/> />
</div> </div>
@@ -174,31 +174,31 @@ export function ImportFlowModal({ onClose }: ImportFlowModalProps) {
{/* Flow info */} {/* Flow info */}
<div className="space-y-2 text-xs"> <div className="space-y-2 text-xs">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-[#848b9b]">Type:</span> <span className="text-muted-foreground">Type:</span>
<span className="rounded bg-[rgba(34,211,238,0.10)] px-2 py-0.5 font-sans text-xs text-[#22d3ee]"> <span className="rounded bg-accent-dim px-2 py-0.5 font-sans text-xs text-primary">
{TYPE_LABELS[parsed.flow.tree_type] || parsed.flow.tree_type} {TYPE_LABELS[parsed.flow.tree_type] || parsed.flow.tree_type}
</span> </span>
</div> </div>
{parsed.flow.description && ( {parsed.flow.description && (
<div> <div>
<span className="text-[#848b9b]">Description:</span> <span className="text-muted-foreground">Description:</span>
<p className="mt-0.5 text-[#e2e5eb] line-clamp-2">{parsed.flow.description}</p> <p className="mt-0.5 text-foreground line-clamp-2">{parsed.flow.description}</p>
</div> </div>
)} )}
{parsed.flow.category && ( {parsed.flow.category && (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-[#848b9b]">Category:</span> <span className="text-muted-foreground">Category:</span>
<span className="text-[#e2e5eb]">{parsed.flow.category.name}</span> <span className="text-foreground">{parsed.flow.category.name}</span>
</div> </div>
)} )}
{parsed.flow.tags.length > 0 && ( {parsed.flow.tags.length > 0 && (
<div className="flex flex-wrap items-center gap-1.5"> <div className="flex flex-wrap items-center gap-1.5">
<span className="text-[#848b9b]">Tags:</span> <span className="text-muted-foreground">Tags:</span>
{parsed.flow.tags.map((tag) => ( {parsed.flow.tags.map((tag) => (
<span key={tag} className="rounded bg-[#14161d] border border-[#1e2130] px-2 py-0.5 font-sans text-xs text-[#e2e5eb]"> <span key={tag} className="rounded bg-card border border-border px-2 py-0.5 font-sans text-xs text-foreground">
{tag} {tag}
</span> </span>
))} ))}
@@ -207,26 +207,26 @@ export function ImportFlowModal({ onClose }: ImportFlowModalProps) {
{parsed.flow.author_name && ( {parsed.flow.author_name && (
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-[#848b9b]">Original author:</span> <span className="text-muted-foreground">Original author:</span>
<span className="text-[#e2e5eb]">{parsed.flow.author_name}</span> <span className="text-foreground">{parsed.flow.author_name}</span>
</div> </div>
)} )}
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<span className="text-[#848b9b]">Version:</span> <span className="text-muted-foreground">Version:</span>
<span className="text-[#e2e5eb]">v{parsed.flow.version}</span> <span className="text-foreground">v{parsed.flow.version}</span>
</div> </div>
</div> </div>
<p className="text-xs text-[#848b9b]"> <p className="text-xs text-muted-foreground">
Flow will be imported as a <span className="font-medium text-[#e2e5eb]">draft</span>. Flow will be imported as a <span className="font-medium text-foreground">draft</span>.
</p> </p>
</div> </div>
)} )}
</div> </div>
{/* Footer */} {/* Footer */}
<div className="flex justify-end gap-2 border-t border-[#1e2130] px-5 py-3"> <div className="flex justify-end gap-2 border-t border-border px-5 py-3">
{step === 'preview' && ( {step === 'preview' && (
<Button <Button
variant="secondary" variant="secondary"

View File

@@ -120,13 +120,13 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
/> />
{/* Modal */} {/* Modal */}
<div className="relative w-full max-w-full rounded-t-2xl bg-[#14161d] border border-[#1e2130] shadow-lg sm:max-w-lg sm:rounded-2xl"> <div className="relative w-full max-w-full rounded-t-2xl bg-card border border-border shadow-lg sm:max-w-lg sm:rounded-2xl">
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-[#1e2130] px-6 py-4"> <div className="flex items-center justify-between border-b border-border px-6 py-4">
<h2 className="text-lg font-semibold text-[#e2e5eb]">Share Tree</h2> <h2 className="text-lg font-semibold text-foreground">Share Tree</h2>
<button <button
onClick={onClose} onClick={onClose}
className="rounded-md p-1 text-[#848b9b] hover:bg-accent/50 hover:text-[#e2e5eb]" className="rounded-md p-1 text-muted-foreground hover:bg-accent/50 hover:text-foreground"
> >
<X className="h-5 w-5" /> <X className="h-5 w-5" />
</button> </button>
@@ -136,9 +136,9 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
<div className="px-6 py-4 space-y-6"> <div className="px-6 py-4 space-y-6">
{/* Tree Info */} {/* Tree Info */}
<div> <div>
<h3 className="font-medium text-[#e2e5eb]">{tree.name}</h3> <h3 className="font-medium text-foreground">{tree.name}</h3>
{tree.description && ( {tree.description && (
<p className="mt-1 text-sm text-[#848b9b] line-clamp-2"> <p className="mt-1 text-sm text-muted-foreground line-clamp-2">
{tree.description} {tree.description}
</p> </p>
)} )}
@@ -146,7 +146,7 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
{/* Visibility Settings */} {/* Visibility Settings */}
<div> <div>
<label className="mb-2 block text-sm font-medium text-[#e2e5eb]"> <label className="mb-2 block text-sm font-medium text-foreground">
Visibility Visibility
</label> </label>
<div className="space-y-2"> <div className="space-y-2">
@@ -157,14 +157,14 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
className={cn( className={cn(
'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors', 'flex w-full items-center gap-3 rounded-md border px-4 py-3 text-left transition-colors',
visibility === level visibility === level
? 'border-[#1e2130] bg-accent text-[#e2e5eb]' ? 'border-border bg-accent text-foreground'
: 'border-[#1e2130] bg-transparent text-[#848b9b] hover:border-primary/30 hover:bg-accent/50' : 'border-border bg-transparent text-muted-foreground hover:border-primary/30 hover:bg-accent/50'
)} )}
> >
{getVisibilityIcon(level)} {getVisibilityIcon(level)}
<div className="flex-1"> <div className="flex-1">
<div className="text-sm font-medium capitalize">{level}</div> <div className="text-sm font-medium capitalize">{level}</div>
<div className="text-xs text-[#848b9b]"> <div className="text-xs text-muted-foreground">
{getVisibilityDescription(level)} {getVisibilityDescription(level)}
</div> </div>
</div> </div>
@@ -179,7 +179,7 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
{/* Share Link Generation */} {/* Share Link Generation */}
{visibility !== 'private' && ( {visibility !== 'private' && (
<div> <div>
<label className="mb-2 block text-sm font-medium text-[#e2e5eb]"> <label className="mb-2 block text-sm font-medium text-foreground">
Share Link Share Link
</label> </label>
@@ -190,11 +190,11 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
id="allow-forking" id="allow-forking"
checked={allowForking} checked={allowForking}
onChange={(e) => setAllowForking(e.target.checked)} onChange={(e) => setAllowForking(e.target.checked)}
className="h-4 w-4 rounded border-[#1e2130] bg-[#14161d] text-[#e2e5eb] focus:ring-2 focus:ring-primary/20 focus:ring-offset-2 focus:ring-offset-black" className="h-4 w-4 rounded border-border bg-card text-foreground focus:ring-2 focus:ring-primary/20 focus:ring-offset-2 focus:ring-offset-black"
/> />
<label <label
htmlFor="allow-forking" htmlFor="allow-forking"
className="text-sm text-[#848b9b] cursor-pointer" className="text-sm text-muted-foreground cursor-pointer"
> >
Allow recipients to fork this tree Allow recipients to fork this tree
</label> </label>
@@ -214,20 +214,20 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
{/* Active Share Link */} {/* Active Share Link */}
{activeShare && ( {activeShare && (
<div className="space-y-2"> <div className="space-y-2">
<div className="flex items-center gap-2 rounded-md border border-[#1e2130] bg-[#14161d] p-3"> <div className="flex items-center gap-2 rounded-md border border-border bg-card p-3">
<input <input
type="text" type="text"
value={activeShare.share_url} value={activeShare.share_url}
readOnly readOnly
className="flex-1 bg-transparent text-sm text-[#e2e5eb] outline-hidden" className="flex-1 bg-transparent text-sm text-foreground outline-hidden"
/> />
<button <button
onClick={handleCopyLink} onClick={handleCopyLink}
className={cn( className={cn(
'flex items-center gap-2 rounded-md border border-[#1e2130] px-3 py-1.5 text-sm font-medium transition-colors', 'flex items-center gap-2 rounded-md border border-border px-3 py-1.5 text-sm font-medium transition-colors',
copied copied
? 'border-green-500 bg-green-500/10 text-green-400' ? 'border-green-500 bg-green-500/10 text-green-400'
: 'text-[#848b9b] hover:bg-accent hover:text-[#e2e5eb]' : 'text-muted-foreground hover:bg-accent hover:text-foreground'
)} )}
> >
{copied ? ( {copied ? (
@@ -243,13 +243,13 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
)} )}
</button> </button>
</div> </div>
<p className="text-xs text-[#848b9b]"> <p className="text-xs text-muted-foreground">
{activeShare.allow_forking {activeShare.allow_forking
? 'Recipients can fork this tree' ? 'Recipients can fork this tree'
: 'Forking disabled for this share'} : 'Forking disabled for this share'}
</p> </p>
{shares.length > 1 && ( {shares.length > 1 && (
<p className="text-xs text-[#848b9b]"> <p className="text-xs text-muted-foreground">
{shares.length} active share links {shares.length} active share links
</p> </p>
)} )}
@@ -260,7 +260,7 @@ export function ShareTreeModal({ tree, isOpen, onClose }: ShareTreeModalProps) {
</div> </div>
{/* Footer */} {/* Footer */}
<div className="flex justify-end gap-3 border-t border-[#1e2130] px-6 py-4"> <div className="flex justify-end gap-3 border-t border-border px-6 py-4">
<Button variant="secondary" onClick={onClose}> <Button variant="secondary" onClick={onClose}>
Close Close
</Button> </Button>

View File

@@ -21,7 +21,7 @@ const sortOptions: { value: SortBy; label: string }[] = [
export function SortDropdown({ value, onChange, className }: SortDropdownProps) { export function SortDropdown({ value, onChange, className }: SortDropdownProps) {
return ( return (
<div className={cn('relative inline-flex items-center', className)}> <div className={cn('relative inline-flex items-center', className)}>
<span className="mr-2 flex items-center gap-1.5 text-sm text-[#848b9b]"> <span className="mr-2 flex items-center gap-1.5 text-sm text-muted-foreground">
<ArrowUpDown className="h-4 w-4" /> <ArrowUpDown className="h-4 w-4" />
<span className="hidden sm:inline">Sort:</span> <span className="hidden sm:inline">Sort:</span>
</span> </span>
@@ -29,8 +29,8 @@ export function SortDropdown({ value, onChange, className }: SortDropdownProps)
value={value} value={value}
onChange={(e) => onChange(e.target.value as SortBy)} onChange={(e) => onChange(e.target.value as SortBy)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] bg-[#14161d] px-3 py-1.5 text-sm', 'rounded-md border border-border bg-card px-3 py-1.5 text-sm',
'text-[#e2e5eb] focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20' 'text-foreground focus:border-primary focus:outline-hidden focus:ring-1 focus:ring-primary/20'
)} )}
> >
{sortOptions.map((option) => ( {sortOptions.map((option) => (

View File

@@ -34,11 +34,11 @@ export function TreeGridView({
{trees.map((tree) => ( {trees.map((tree) => (
<div <div
key={tree.id} key={tree.id}
className="relative bg-[#14161d] border border-[#1e2130] rounded-2xl p-4 transition-all hover:-translate-y-0.5 hover:border-primary/30 hover:shadow-md sm:p-6" className="relative bg-card border border-border rounded-2xl p-4 transition-all hover:-translate-y-0.5 hover:border-primary/30 hover:shadow-md sm:p-6"
> >
<div className="mb-2 flex items-start justify-between gap-2"> <div className="mb-2 flex items-start justify-between gap-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
<h3 className="font-semibold text-[#e2e5eb]">{tree.name}</h3> <h3 className="font-semibold text-foreground">{tree.name}</h3>
{tree.status === 'draft' && ( {tree.status === 'draft' && (
<span className="inline-flex items-center gap-1 rounded-full bg-yellow-400/10 px-2 py-0.5 text-xs font-medium text-yellow-400"> <span className="inline-flex items-center gap-1 rounded-full bg-yellow-400/10 px-2 py-0.5 text-xs font-medium text-yellow-400">
<FileText className="h-3 w-3" /> <FileText className="h-3 w-3" />
@@ -60,21 +60,21 @@ export function TreeGridView({
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
{tree.is_public ? ( {tree.is_public ? (
<span title="Public tree"> <span title="Public tree">
<Globe className="h-4 w-4 text-[#848b9b]" /> <Globe className="h-4 w-4 text-muted-foreground" />
</span> </span>
) : ( ) : (
<span title="Private tree"> <span title="Private tree">
<Lock className="h-4 w-4 text-[#848b9b]" /> <Lock className="h-4 w-4 text-muted-foreground" />
</span> </span>
)} )}
{tree.category_info && ( {tree.category_info && (
<span className="rounded-full bg-accent px-2 py-0.5 text-xs text-[#848b9b]"> <span className="rounded-full bg-accent px-2 py-0.5 text-xs text-muted-foreground">
{tree.category_info.name} {tree.category_info.name}
</span> </span>
)} )}
</div> </div>
</div> </div>
<p className="mb-3 text-sm text-[#848b9b] line-clamp-2"> <p className="mb-3 text-sm text-muted-foreground line-clamp-2">
{tree.description || 'No description available'} {tree.description || 'No description available'}
</p> </p>
@@ -86,7 +86,7 @@ export function TreeGridView({
)} )}
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<span className="text-xs text-[#848b9b]"> <span className="text-xs text-muted-foreground">
v{tree.version} · {tree.usage_count} uses v{tree.version} · {tree.usage_count} uses
</span> </span>
<div className="flex items-center gap-2"> <div className="flex items-center gap-2">
@@ -95,8 +95,8 @@ export function TreeGridView({
type="button" type="button"
onClick={() => onExportTree(tree.id)} onClick={() => onExportTree(tree.id)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-2 text-[#848b9b]', 'rounded-md border border-border p-2 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Export flow" title="Export flow"
aria-label="Export flow" aria-label="Export flow"
@@ -109,8 +109,8 @@ export function TreeGridView({
type="button" type="button"
onClick={() => onForkTree(tree.id)} onClick={() => onForkTree(tree.id)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-2 text-[#848b9b]', 'rounded-md border border-border p-2 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Fork tree" title="Fork tree"
aria-label="Fork tree" aria-label="Fork tree"
@@ -122,8 +122,8 @@ export function TreeGridView({
<Link <Link
to={getTreeEditorPath(tree.id, tree.tree_type)} to={getTreeEditorPath(tree.id, tree.tree_type)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-2 text-[#848b9b]', 'rounded-md border border-border p-2 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Edit tree" title="Edit tree"
aria-label="Edit tree" aria-label="Edit tree"
@@ -136,7 +136,7 @@ export function TreeGridView({
type="button" type="button"
onClick={() => onDeleteTree(tree)} onClick={() => onDeleteTree(tree)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-1.5 text-[#848b9b]', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-red-400/10 hover:text-red-400' 'hover:bg-red-400/10 hover:text-red-400'
)} )}
title="Delete tree" title="Delete tree"
@@ -150,7 +150,7 @@ export function TreeGridView({
type="button" type="button"
onClick={() => onPrepareSession(tree)} onClick={() => onPrepareSession(tree)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-2 text-[#848b9b]', '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-cyan-500/10 hover:text-cyan-400 hover:border-cyan-500/30'
)} )}
title="Prepare session for engineer" title="Prepare session for engineer"
@@ -163,7 +163,7 @@ export function TreeGridView({
type="button" type="button"
onClick={() => onStartSession(tree.id, tree.tree_type)} onClick={() => onStartSession(tree.id, tree.tree_type)}
className={cn( className={cn(
'rounded-md bg-[#22d3ee] px-3 py-2 text-sm font-medium text-white', 'rounded-md bg-primary px-3 py-2 text-sm font-medium text-white',
'hover:brightness-110' 'hover:brightness-110'
)} )}
> >

View File

@@ -33,12 +33,12 @@ export function TreeListView({
{trees.map((tree) => ( {trees.map((tree) => (
<div <div
key={tree.id} key={tree.id}
className="flex items-center gap-4 bg-[#14161d] border border-[#1e2130] rounded-2xl p-4 transition-all hover:border-primary/30 hover:shadow-xs" className="flex items-center gap-4 bg-card border border-border rounded-2xl p-4 transition-all hover:border-primary/30 hover:shadow-xs"
> >
{/* Left: Name and Description */} {/* Left: Name and Description */}
<div className="flex-1 min-w-0"> <div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1"> <div className="flex items-center gap-2 mb-1">
<h3 className="font-semibold text-[#e2e5eb] truncate">{tree.name}</h3> <h3 className="font-semibold text-foreground truncate">{tree.name}</h3>
{tree.status === 'draft' && ( {tree.status === 'draft' && (
<span className="inline-flex items-center gap-1 rounded-full bg-yellow-400/10 px-2 py-0.5 text-xs font-medium text-yellow-400 shrink-0"> <span className="inline-flex items-center gap-1 rounded-full bg-yellow-400/10 px-2 py-0.5 text-xs font-medium text-yellow-400 shrink-0">
<FileText className="h-3 w-3" /> <FileText className="h-3 w-3" />
@@ -58,15 +58,15 @@ export function TreeListView({
)} )}
{tree.is_public ? ( {tree.is_public ? (
<span title="Public tree"> <span title="Public tree">
<Globe className="h-3.5 w-3.5 text-[#848b9b] shrink-0" /> <Globe className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
</span> </span>
) : ( ) : (
<span title="Private tree"> <span title="Private tree">
<Lock className="h-3.5 w-3.5 text-[#848b9b] shrink-0" /> <Lock className="h-3.5 w-3.5 text-muted-foreground shrink-0" />
</span> </span>
)} )}
</div> </div>
<p className="text-sm text-[#848b9b] truncate"> <p className="text-sm text-muted-foreground truncate">
{tree.description || 'No description available'} {tree.description || 'No description available'}
</p> </p>
</div> </div>
@@ -74,7 +74,7 @@ export function TreeListView({
{/* Center: Category and Tags */} {/* Center: Category and Tags */}
<div className="hidden lg:flex items-center gap-2 min-w-0" style={{ maxWidth: '300px' }}> <div className="hidden lg:flex items-center gap-2 min-w-0" style={{ maxWidth: '300px' }}>
{tree.category_info && ( {tree.category_info && (
<span className="rounded-full bg-accent px-2 py-0.5 text-xs text-[#848b9b] whitespace-nowrap"> <span className="rounded-full bg-accent px-2 py-0.5 text-xs text-muted-foreground whitespace-nowrap">
{tree.category_info.name} {tree.category_info.name}
</span> </span>
)} )}
@@ -87,7 +87,7 @@ export function TreeListView({
{/* Right: Metadata and Actions */} {/* Right: Metadata and Actions */}
<div className="flex items-center gap-3 shrink-0"> <div className="flex items-center gap-3 shrink-0">
<div className="hidden sm:flex flex-col items-end text-xs text-[#848b9b]"> <div className="hidden sm:flex flex-col items-end text-xs text-muted-foreground">
<span>v{tree.version}</span> <span>v{tree.version}</span>
<span>{tree.usage_count} uses</span> <span>{tree.usage_count} uses</span>
</div> </div>
@@ -98,8 +98,8 @@ export function TreeListView({
type="button" type="button"
onClick={() => onExportTree(tree.id)} onClick={() => onExportTree(tree.id)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-1.5 text-[#848b9b]', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Export flow" title="Export flow"
aria-label="Export flow" aria-label="Export flow"
@@ -112,8 +112,8 @@ export function TreeListView({
type="button" type="button"
onClick={() => onForkTree(tree.id)} onClick={() => onForkTree(tree.id)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-1.5 text-[#848b9b]', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Fork tree" title="Fork tree"
aria-label="Fork tree" aria-label="Fork tree"
@@ -126,8 +126,8 @@ export function TreeListView({
<Link <Link
to={getTreeEditorPath(tree.id, tree.tree_type)} to={getTreeEditorPath(tree.id, tree.tree_type)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-1.5 text-[#848b9b]', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-accent hover:text-[#e2e5eb]' 'hover:bg-accent hover:text-foreground'
)} )}
title="Edit tree" title="Edit tree"
aria-label="Edit tree" aria-label="Edit tree"
@@ -138,7 +138,7 @@ export function TreeListView({
type="button" type="button"
onClick={() => onDeleteTree(tree)} onClick={() => onDeleteTree(tree)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-1.5 text-[#848b9b]', 'rounded-md border border-border p-1.5 text-muted-foreground',
'hover:bg-red-500/20 hover:text-red-400' 'hover:bg-red-500/20 hover:text-red-400'
)} )}
title="Delete tree" title="Delete tree"
@@ -153,7 +153,7 @@ export function TreeListView({
type="button" type="button"
onClick={() => onPrepareSession(tree)} onClick={() => onPrepareSession(tree)}
className={cn( className={cn(
'rounded-md border border-[#1e2130] p-1.5 text-[#848b9b]', '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-cyan-500/10 hover:text-cyan-400 hover:border-cyan-500/30'
)} )}
title="Prepare session for engineer" title="Prepare session for engineer"
@@ -166,7 +166,7 @@ export function TreeListView({
type="button" type="button"
onClick={() => onStartSession(tree.id, tree.tree_type)} onClick={() => onStartSession(tree.id, tree.tree_type)}
className={cn( className={cn(
'rounded-md bg-[#22d3ee] px-3 py-1.5 text-sm font-medium text-white', 'rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-white',
'hover:brightness-110 whitespace-nowrap' 'hover:brightness-110 whitespace-nowrap'
)} )}
> >

Some files were not shown because too many files have changed in this diff Show More