total_lines() was returning sampled_line_count() (only ~300 lines from the initial 64KB scan) during the Loading state, capping the scroll range. Use estimated_lines instead so the user can scroll to any position while indexing runs in the background. get_line() already supports incremental forward scanning on demand.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Replace synchronous file loading with AppLoadingState state machine (Empty/Loading/Ready/Error) for instant interactivity. Add ViewportCache for on-demand viewport computation, replacing global wrap/level caches. Integrate background indexer polling and file watcher events into the TUI event loop. Add loading UI with progress percentage, estimated line numbers with ~ prefix, and error state display. Eliminate all O(N) linear scans using VisualHeightIndex binary search.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Replace Line::styled with Span-based rendering: gutter (DarkGray fg) + content (level-based fg color). Add centered settings popup (S key) with j/k navigation, arrow key color cycling, number key shortcuts, Enter to save, Esc to cancel.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add AppMode enum (Normal/Settings), level_cache field populated in recompute_wrap_cache via detect_level(), color_config loaded from TOML in main.rs. Refactor handle_key for mode dispatch with S key to enter settings.
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Press Tab to switch JSON log lines between raw single-line and indented
multi-line format (2-space indent, like jq output). Only JSON Object lines
are affected; plain text lines stay unchanged.
- Add json_format bool field to App, toggled by Tab
- Add format_json_line() standalone function with serde_json::to_string_pretty
- Integrate into recompute_wrap_cache with \n-split sub-line wrapping
- Center viewport on cursor after cache rebuild to prevent jump on toggle
- Add 12 unit tests covering format, toggle, and edge cases
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>