@@ -366,179 +366,104 @@ export default function LiveView() {
366366 ) }
367367
368368 { /* ═══════════════════════════════════════════════════════════════ */ }
369- { /* Pipeline Progress Strip — always visible */ }
369+ { /* Pipeline Progress — full-width animated strip */ }
370370 { /* ═══════════════════════════════════════════════════════════════ */ }
371- < div className = "px-4 py-3 border-b border-gray-200 dark:border-gray-800 bg-white/50 dark:bg-gray-900/50" >
372- < div className = "flex items-center gap-2 mb-2" >
373- < Layers size = { 14 } className = "text-gray-400" />
374- < span className = "text-[10px] font-semibold uppercase tracking-wider text-gray-400" >
375- Pipeline Progress
376- </ span >
377- </ div >
378- < div className = "flex items-center gap-2 flex-wrap" >
379- { groups . map ( ( group , gi ) => {
380- const groupPhaseStates = group . phases . map ( ( p ) => phaseStateMap [ p ] || 'pending' ) ;
381- const hasActive = groupPhaseStates . includes ( 'active' ) ;
382- const allDone = groupPhaseStates . every ( ( s ) => s === 'completed' ) ;
383- const allPending = groupPhaseStates . every ( ( s ) => s === 'pending' ) ;
384-
385- return (
386- < div key = { group . id } className = "flex items-center gap-2" >
387- { /* Separator arrow between groups */ }
388- { gi > 0 && (
389- < ChevronDown
390- size = { 12 }
391- className = "text-gray-300 dark:text-gray-600 rotate-[-90deg] shrink-0"
392- />
393- ) }
394-
395- { /* Group card */ }
396- < div
397- className = { clsx (
398- 'flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg border transition-all duration-300' ,
399- GROUP_BG_COLORS [ group . color ] ,
400- hasActive
401- ? clsx ( GROUP_BORDER_COLORS [ group . color ] , 'shadow-sm' )
402- : allDone
403- ? 'border-emerald-300 dark:border-emerald-700'
404- : 'border-gray-200 dark:border-gray-700' ,
405- ) }
406- >
407- { /* Group label */ }
408- < span
409- className = { clsx (
410- 'text-[10px] font-semibold uppercase tracking-wider mr-1' ,
411- allDone
412- ? 'text-emerald-600 dark:text-emerald-400'
413- : hasActive
414- ? GROUP_TEXT_COLORS [ group . color ]
415- : 'text-gray-400 dark:text-gray-500' ,
416- ) }
417- >
418- { group . label }
419- </ span >
420-
421- { /* Phase dots */ }
422- { group . phases . map ( ( phase ) => {
423- const state = phaseStateMap [ phase ] || 'pending' ;
424- const isActive = state === 'active' ;
425- const isCompleted = state === 'completed' ;
426- const dotColor = PHASE_DOT_COLORS [ phase ] || 'bg-gray-400' ;
427-
428- return (
429- < div
430- key = { phase }
431- className = "relative flex items-center justify-center"
432- title = { `${ phase } ${ isActive ? ' (active)' : isCompleted ? ' (completed)' : '' } ` }
433- >
434- { isCompleted ? (
435- < CheckCircle2
436- size = { 14 }
437- className = "text-emerald-500 dark:text-emerald-400"
438- />
439- ) : isActive ? (
440- < div className = "relative" >
441- < Circle
442- size = { 14 }
443- className = { clsx ( dotColor , 'animate-pulse' ) }
444- fill = "currentColor"
445- />
446- { /* Outer pulse ring */ }
447- < span
448- className = { clsx (
449- 'absolute inset-0 rounded-full animate-ping opacity-40' ,
450- dotColor . replace ( 'bg-' , 'bg-' ) ,
451- ) }
452- />
453- </ div >
454- ) : (
455- < Circle
456- size = { 10 }
457- className = "text-gray-300 dark:text-gray-600"
458- fill = "currentColor"
459- />
460- ) }
461- </ div >
462- ) ;
371+ < div className = "px-4 py-2.5 border-b border-gray-200 dark:border-gray-800 bg-gradient-to-r from-gray-50 via-white to-gray-50 dark:from-gray-900 dark:via-gray-850 dark:to-gray-900" >
372+ < div className = "flex items-center gap-1.5 flex-wrap" >
373+ { groups . map ( ( group , gi ) => {
374+ const done = group . phases . filter ( ( p ) => phaseStateMap [ p ] === 'completed' ) . length ;
375+ const active = group . phases . some ( ( p ) => phaseStateMap [ p ] === 'active' ) ;
376+ const allDone = done === group . phases . length ;
377+ const pct = group . phases . length > 0 ? Math . round ( ( done / group . phases . length ) * 100 ) : 0 ;
378+
379+ return (
380+ < div key = { group . id } className = "flex items-center gap-1" >
381+ { gi > 0 && < ChevronDown size = { 10 } className = "text-gray-300 dark:text-gray-600 -rotate-90 shrink-0" /> }
382+ < div className = { clsx (
383+ 'relative flex items-center gap-2 px-3 py-2 rounded-xl border-2 transition-all duration-500 min-w-[120px]' ,
384+ active ? clsx ( GROUP_BG_COLORS [ group . color ] , 'shadow-md scale-105 border-current' ) :
385+ allDone ? 'bg-emerald-50/50 dark:bg-emerald-950/20 border-emerald-300 dark:border-emerald-700' :
386+ 'bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700 opacity-75'
387+ ) } >
388+ < div className = "flex flex-col gap-0.5" >
389+ < span className = { clsx ( 'text-[10px] font-bold uppercase tracking-wider leading-none' , allDone ? 'text-emerald-600' : active ? 'text-current opacity-80' : 'text-gray-400' ) } > { group . label } </ span >
390+ < span className = "text-[9px] text-gray-400 font-mono tabular-nums leading-none" > { done } /{ group . phases . length } </ span >
391+ </ div >
392+ { /* Progress bar */ }
393+ < div className = "flex-1 h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden min-w-[40px]" >
394+ < div className = { clsx ( 'h-full rounded-full transition-all duration-700' , allDone ? 'bg-emerald-500' : active ? 'bg-current opacity-70' : 'bg-gray-300' ) } style = { { width : `${ pct } %` } } />
395+ </ div >
396+ { /* Phase dots */ }
397+ < div className = "flex items-center gap-0.5 shrink-0" >
398+ { group . phases . map ( ( p ) => {
399+ const s = phaseStateMap [ p ] || 'pending' ;
400+ return s === 'completed' ? < CheckCircle2 key = { p } size = { 12 } className = "text-emerald-500" /> :
401+ s === 'active' ? < div key = { p } className = "relative" > < div className = { clsx ( 'w-2.5 h-2.5 rounded-full animate-pulse' , PHASE_DOT_COLORS [ p ] || 'bg-blue-500' ) } /> </ div > :
402+ < div key = { p } className = "w-2 h-2 rounded-full bg-gray-300 dark:bg-gray-600" /> ;
463403 } ) }
464404 </ div >
405+ { active && < div className = "absolute -top-1 -right-1 w-2 h-2 rounded-full bg-brand-500 animate-ping" /> }
465406 </ div >
466- ) ;
467- } ) }
468- </ div >
407+ </ div >
408+ ) ;
409+ } ) }
469410 </ div >
411+ </ div >
470412
471413 { /* ═══════════════════════════════════════════════════════════════ */ }
472- { /* Stats Dashboard Row — always visible */ }
414+ { /* Live Stats Bar — prominent cards */ }
473415 { /* ═══════════════════════════════════════════════════════════════ */ }
474- < div className = "px-4 py-2.5 border-b border-gray-200 dark:border-gray-800 glass-alt" >
475- < div className = "flex items-center gap-4 flex-wrap" >
476- { /* Phases completed */ }
477- < div className = "flex items-center gap-2 px-3 py-1.5 rounded-lg bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700" >
478- < Target size = { 14 } className = "text-sky-500" />
479- < div >
480- < span className = "text-[10px] text-gray-400 font-medium" > Phases</ span >
481- < span className = "ml-1.5 text-sm font-bold text-gray-800 dark:text-gray-200 tabular-nums" >
482- { stats . phasesCompleted }
483- < span className = "text-gray-400 font-normal" > /{ stats . totalPhases } </ span >
484- </ span >
485- </ div >
416+ < div className = "px-4 py-2 border-b border-gray-200 dark:border-gray-800 bg-gradient-to-r from-gray-50 via-white to-gray-50 dark:from-gray-900 dark:via-gray-850 dark:to-gray-900" >
417+ < div className = "flex items-center gap-3" >
418+ { /* Phases */ }
419+ < div className = "flex items-center gap-2 px-4 py-2 rounded-xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md transition-shadow" >
420+ < div className = "w-8 h-8 rounded-lg bg-sky-100 dark:bg-sky-900/30 flex items-center justify-center" > < Target size = { 16 } className = "text-sky-600" /> </ div >
421+ < div >
422+ < div className = "text-[10px] text-gray-400 font-medium leading-none" > Phases</ div >
423+ < div className = "text-base font-bold text-gray-800 dark:text-white tabular-nums leading-tight" > { stats . phasesCompleted } < span className = "text-sm text-gray-400 font-normal" > /{ stats . totalPhases } </ span > </ div >
486424 </ div >
487-
488- { /* Active agent */ }
489- < div className = "flex items-center gap-2 px-3 py-1.5 rounded-lg bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700" >
490- < Bot size = { 14 } className = "text-violet-500" />
491- < div >
492- < span className = "text-[10px] text-gray-400 font-medium" > Agent</ span >
493- < span className = "ml-1.5 text-sm font-bold text-gray-800 dark:text-gray-200" >
494- { activeAgentId ? (
495- < span className = "text-violet-600 dark:text-violet-400" >
496- { activeAgentSpec ?. title || activeAgentId }
497- </ span >
498- ) : (
499- < span className = "text-gray-400" > —</ span >
500- ) }
501- </ span >
502- </ div >
425+ </ div >
426+ { /* Agent */ }
427+ < div className = "flex items-center gap-2 px-4 py-2 rounded-xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md transition-shadow" >
428+ < div className = { clsx ( 'w-8 h-8 rounded-lg flex items-center justify-center' , activeAgentId ? 'bg-violet-100 dark:bg-violet-900/30' : 'bg-gray-100 dark:bg-gray-800' ) } >
429+ < Bot size = { 16 } className = { activeAgentId ? 'text-violet-600' : 'text-gray-400' } />
503430 </ div >
504-
505- { /* Tasks */ }
506- < div className = "flex items-center gap-2 px-3 py-1.5 rounded-lg bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700" >
507- < Zap size = { 14 } className = "text-amber-500" />
508- < div >
509- < span className = "text-[10px] text-gray-400 font-medium" > Tasks</ span >
510- < span className = "ml-1.5 text-sm font-bold text-gray-800 dark:text-gray-200 tabular-nums" >
511- { stats . tasksSeen > 0 ? (
512- < span className = "text-amber-600 dark:text-amber-400" > { stats . tasksSeen } </ span >
513- ) : (
514- < span className = "text-gray-400" > 0</ span >
515- ) }
516- </ span >
431+ < div >
432+ < div className = "text-[10px] text-gray-400 font-medium leading-none" > Agent</ div >
433+ < div className = "text-sm font-bold text-gray-800 dark:text-white leading-tight truncate max-w-[120px]" >
434+ { activeAgentId ? ( activeAgentSpec ?. title || activeAgentId ) : < span className = "text-gray-400 font-normal" > idle</ span > }
517435 </ div >
518436 </ div >
519-
520- { /* Events count */ }
521- < div className = "flex items-center gap-2 px-3 py-1.5 rounded-lg bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700" >
522- < Activity size = { 14 } className = "text-emerald-500" />
523- < div >
524- < span className = "text-[10px] text-gray-400 font-medium" > Events</ span >
525- < span className = "ml-1.5 text-sm font-bold text-gray-800 dark:text-gray-200 tabular-nums" >
526- { stats . eventsCount }
527- </ span >
528- </ div >
437+ </ div >
438+ { /* Tasks */ }
439+ < div className = "flex items-center gap-2 px-4 py-2 rounded-xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md transition-shadow" >
440+ < div className = "w-8 h-8 rounded-lg bg-amber-100 dark:bg-amber-900/30 flex items-center justify-center" > < Zap size = { 16 } className = "text-amber-600" /> </ div >
441+ < div >
442+ < div className = "text-[10px] text-gray-400 font-medium leading-none" > Tasks</ div >
443+ < div className = { clsx ( 'text-base font-bold tabular-nums leading-tight' , stats . tasksSeen > 0 ? 'text-amber-600' : 'text-gray-400' ) } > { stats . tasksSeen } </ div >
444+ </ div >
445+ </ div >
446+ { /* Events */ }
447+ < div className = "flex items-center gap-2 px-4 py-2 rounded-xl bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-700 shadow-sm hover:shadow-md transition-shadow" >
448+ < div className = "w-8 h-8 rounded-lg bg-emerald-100 dark:bg-emerald-900/30 flex items-center justify-center" > < Activity size = { 16 } className = "text-emerald-600" /> </ div >
449+ < div >
450+ < div className = "text-[10px] text-gray-400 font-medium leading-none" > Events</ div >
451+ < div className = "text-base font-bold text-gray-800 dark:text-white tabular-nums leading-tight" > { stats . eventsCount } </ div >
529452 </ div >
530-
531- { /* Running indicator */ }
532- { running && (
533- < div className = "flex items-center gap-2 px-3 py-1.5 rounded-lg bg-brand-50 dark:bg-brand-950/30 border border-brand-200 dark:border-brand-800" >
534- < Loader2 size = { 14 } className = "text-brand-500 animate-spin" />
535- < span className = "text-[11px] font-semibold text-brand-600 dark:text-brand-400" >
536- Running…
537- </ span >
538- </ div >
539- ) }
453+ </ div >
454+ { /* Running */ }
455+ { running && (
456+ < div className = "flex items-center gap-2 px-4 py-2 rounded-xl bg-brand-50 dark:bg-brand-950/30 border-2 border-brand-300 dark:border-brand-700 shadow-sm animate-pulse" >
457+ < Loader2 size = { 18 } className = "text-brand-500 animate-spin" />
458+ < span className = "text-sm font-bold text-brand-700 dark:text-brand-300" > Running</ span >
459+ </ div >
460+ ) }
461+ { /* Progress bar for overall pipeline */ }
462+ < div className = "flex-1 h-2 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden min-w-[60px]" >
463+ < div className = "h-full bg-gradient-to-r from-brand-400 to-brand-600 rounded-full transition-all duration-1000" style = { { width : `${ totalPhases > 0 ? Math . round ( ( stats . phasesCompleted / totalPhases ) * 100 ) : 0 } %` } } />
540464 </ div >
541465 </ div >
466+ </ div >
542467
543468 { /* ═══════════════════════════════════════════════════════════════ */ }
544469 { /* Active Agent Panel */ }
0 commit comments