@@ -410,6 +410,18 @@ func (m Model) buildDebugBody(events []client.APIEvent, cursor int, pw int, ds d
410410 lines = append (lines , lbl + ds .punct .Width (rem ).Render (strings .Repeat ("─" , rem )))
411411 }
412412
413+ // addAccentSection renders the same divider but in colorAccent — used for
414+ // the RESPONSE section to make it visually distinct from the dim REQUEST header.
415+ addAccentSection := func (label string ) {
416+ accentStyle := lipgloss .NewStyle ().Background (ds .panelBg ).Foreground (colorAccent )
417+ lbl := accentStyle .Render (" ── " + label + " " )
418+ rem := pw - lipgloss .Width (lbl )
419+ if rem < 0 {
420+ rem = 0
421+ }
422+ lines = append (lines , lbl + accentStyle .Width (rem ).Render (strings .Repeat ("─" , rem )))
423+ }
424+
413425 // addHeaders renders each "Name: value" header line, dim-styled.
414426 addHeaders := func (headers []string ) {
415427 for _ , h := range headers {
@@ -464,14 +476,14 @@ func (m Model) buildDebugBody(events []client.APIEvent, cursor int, pw int, ds d
464476 if e .ReqBody != "" {
465477 lines = append (lines , ds .bg .Width (pw ).Render ("" ))
466478 for _ , bl := range strings .Split (e .ReqBody , "\n " ) {
467- lines = append (lines , ds .bg .Render (" " )+ colorizeJSONLine (truncateStr (bl , pw - 2 )))
479+ lines = append (lines , ds .bg .Render (" " )+ colorizeJSONLineForPanel (truncateStr (bl , pw - 2 ), ds . panelBg ))
468480 }
469481 }
470482
471483 lines = append (lines , ds .bg .Width (pw ).Render ("" ))
472484
473485 // ── RESPONSE ──────────────────────────────────────────────────────────
474- addSection ("RESPONSE" )
486+ addAccentSection ("RESPONSE" )
475487
476488 if e .Err != "" {
477489 lines = append (lines , statusErrorStyle .Render (" ✗ " + e .Err ))
@@ -494,7 +506,7 @@ func (m Model) buildDebugBody(events []client.APIEvent, cursor int, pw int, ds d
494506 lines = append (lines , ds .bg .Width (pw ).Render ("" ))
495507 if e .RespBody != "" {
496508 for _ , bl := range strings .Split (e .RespBody , "\n " ) {
497- lines = append (lines , ds .bg .Render (" " )+ colorizeJSONLine (truncateStr (bl , pw - 2 )))
509+ lines = append (lines , ds .bg .Render (" " )+ colorizeJSONLineForPanel (truncateStr (bl , pw - 2 ), ds . panelBg ))
498510 }
499511 } else {
500512 lines = append (lines , ds .punct .Render (" (empty body)" ))
@@ -573,3 +585,94 @@ func debugDurLabel(d time.Duration) string {
573585 return fmt .Sprintf ("%.1fs" , d .Seconds ())
574586}
575587
588+ // colorizeJSONLineForPanel colorizes a JSON line using the given panel background
589+ // colour so token backgrounds always match the panel (focused or unfocused).
590+ // This mirrors colorizeJSONLine / tokenizeJSON in svjson.go but builds styles
591+ // dynamically rather than using the global jsonXxxStyle vars which hardcode colorBg.
592+ func colorizeJSONLineForPanel (line string , bg color.Color ) string {
593+ trimmed := strings .TrimLeft (line , " \t " )
594+ if trimmed == "" {
595+ return line
596+ }
597+ indent := line [:len (line )- len (trimmed )]
598+
599+ base := lipgloss .NewStyle ().Background (bg )
600+ pKey := base .Foreground (colorAccent )
601+ pStr := base .Foreground (colorSuccess )
602+ pNum := base .Foreground (colorPurple )
603+ pKwd := base .Foreground (colorLoading )
604+ pPun := base .Foreground (colorDim )
605+
606+ // colorValue tokenizes a value fragment (everything after a colon, or a
607+ // standalone value / array element). Mirrors jsonColorValue from svjson.go.
608+ var colorValue func (s string ) string
609+ colorValue = func (s string ) string {
610+ var out strings.Builder
611+ ws := s [:len (s )- len (strings .TrimLeft (s , " \t " ))]
612+ if ws != "" {
613+ out .WriteString (ws )
614+ }
615+ s = strings .TrimLeft (s , " \t " )
616+ if s == "" {
617+ return out .String ()
618+ }
619+ trailer := ""
620+ if s [len (s )- 1 ] == ',' {
621+ trailer = ","
622+ s = s [:len (s )- 1 ]
623+ }
624+ if s == "" {
625+ out .WriteString (pPun .Render (trailer ))
626+ return out .String ()
627+ }
628+ switch s [0 ] {
629+ case '"' :
630+ out .WriteString (pStr .Render (s ))
631+ case '{' , '[' , '}' , ']' :
632+ out .WriteString (pPun .Render (s ))
633+ case 't' , 'f' , 'n' :
634+ out .WriteString (pKwd .Render (s ))
635+ default :
636+ out .WriteString (pNum .Render (s ))
637+ }
638+ if trailer != "" {
639+ out .WriteString (pPun .Render (trailer ))
640+ }
641+ return out .String ()
642+ }
643+
644+ var out strings.Builder
645+ s := trimmed
646+ switch s [0 ] {
647+ case '"' :
648+ end := jsonStringEnd (s , 0 )
649+ if end < 0 {
650+ return line // truncated string — leave unstyled
651+ }
652+ str := s [:end ]
653+ rest := s [end :]
654+ restTrim := strings .TrimLeft (rest , " " )
655+ if len (restTrim ) > 0 && restTrim [0 ] == ':' {
656+ out .WriteString (pKey .Render (str ))
657+ ws := rest [:len (rest )- len (restTrim )]
658+ out .WriteString (pPun .Render (ws + ":" ))
659+ out .WriteString (colorValue (restTrim [1 :]))
660+ } else {
661+ out .WriteString (pStr .Render (str ))
662+ if rest != "" {
663+ out .WriteString (pPun .Render (rest ))
664+ }
665+ }
666+ case '{' , '}' , '[' , ']' :
667+ out .WriteString (pPun .Render (s ))
668+ default :
669+ out .WriteString (colorValue (s ))
670+ }
671+ // Style the indent with the panel background so it matches rather than
672+ // falling back to the terminal default after the ANSI reset from ds.bg prefix.
673+ if indent != "" {
674+ return base .Render (indent ) + out .String ()
675+ }
676+ return out .String ()
677+ }
678+
0 commit comments