From 25d3eee84034a677b0fd8bccadb4fed27b1fb947 Mon Sep 17 00:00:00 2001 From: arjun-vegeta <149392539+arjun-vegeta@users.noreply.github.com> Date: Sun, 2 Aug 2026 01:49:27 +0530 Subject: [PATCH] feat(marketing): add minimalistic TUI-centric marketing website --- website/app.js | 392 ++++++++++++++++++++++++++++ website/index.html | 348 +++++++++++++++++++++++++ website/style.css | 633 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 1373 insertions(+) create mode 100644 website/app.js create mode 100644 website/index.html create mode 100644 website/style.css diff --git a/website/app.js b/website/app.js new file mode 100644 index 0000000..477bb99 --- /dev/null +++ b/website/app.js @@ -0,0 +1,392 @@ +/** + * LoopCode High-Fidelity TUI Simulator + * Replicates the exact state-machine loop, console transcripts, + * and interactive overlays from the actual Ink codebase. + */ + +document.addEventListener('DOMContentLoaded', () => { + // --- Copy Installation script --- + const copyBtn = document.getElementById('copy-cmd-btn'); + if (copyBtn) { + copyBtn.addEventListener('click', () => { + const textToCopy = 'curl -fsSL https://raw.githubusercontent.com/arjun-vegeta/loopCode/main/install.sh | bash'; + navigator.clipboard.writeText(textToCopy).then(() => { + copyBtn.innerHTML = ``; + setTimeout(() => { + copyBtn.innerHTML = ``; + }, 2000); + }); + }); + } + + // --- TUI Spinner Tokens --- + const spinnerChars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; + let spinnerIdx = 0; + let spinnerTimer = null; + + const spinnerEl = document.getElementById('tui-spinner-char'); + + function startSpinner() { + if (spinnerTimer) clearInterval(spinnerTimer); + spinnerTimer = setInterval(() => { + spinnerIdx = (spinnerIdx + 1) % spinnerChars.length; + spinnerEl.innerText = spinnerChars[spinnerIdx]; + }, 80); + } + + function stopSpinner() { + clearInterval(spinnerTimer); + spinnerEl.innerText = '·'; + } + + // --- TUI Interactive Overlays --- + const overlays = { + tasks: document.getElementById('overlay-tasks'), + verify: document.getElementById('overlay-verify'), + budget: document.getElementById('overlay-budget'), + help: document.getElementById('overlay-help'), + }; + + const hintItems = { + tasks: document.getElementById('hint-tasks'), + verify: document.getElementById('hint-verify'), + budget: document.getElementById('hint-budget'), + help: document.getElementById('hint-help'), + }; + + function closeAllOverlays() { + Object.values(overlays).forEach((el) => el.classList.remove('active')); + Object.values(hintItems).forEach((el) => el.classList.remove('active')); + } + + function toggleOverlay(name) { + const isAlreadyActive = overlays[name].classList.contains('active'); + closeAllOverlays(); + if (!isAlreadyActive) { + overlays[name].classList.add('active'); + hintItems[name].classList.add('active'); + } + } + + // Mouse clicks for hint bar buttons + Object.keys(overlays).forEach((name) => { + hintItems[name].addEventListener('click', (e) => { + e.stopPropagation(); + toggleOverlay(name); + }); + // Click overlay itself to close + overlays[name].addEventListener('click', (e) => { + e.stopPropagation(); + closeAllOverlays(); + }); + }); + + // Global keyboard listener to match TUI hotkeys + document.addEventListener('keydown', (e) => { + // Disable hotkeys if user is typing in standard browser forms (if any) + if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return; + + const key = e.key.toLowerCase(); + + if (e.key === 'Escape') { + closeAllOverlays(); + } else if (key === 't') { + toggleOverlay('tasks'); + } else if (key === 'v') { + toggleOverlay('verify'); + } else if (key === 'b') { + toggleOverlay('budget'); + } else if (key === 'h') { + toggleOverlay('help'); + } else if (e.key === ' ') { + e.preventDefault(); + toggleSim(); + } else if (key === 'r') { + restartSim(); + } + }); + + // Close overlays clicking anywhere else inside showcase + document.getElementById('tui-showcase').addEventListener('click', (e) => { + // Only close if click wasn't on overlay or hints + if (!e.target.closest('.tui-overlay-container') && !e.target.closest('.tui-hints')) { + closeAllOverlays(); + } + }); + + // --- TUI Transcript Event logs --- + const tuiEvents = [ + { + type: 'info', + text: '⏺ Initializing LoopCode session context...', + phase: 'init', + detail: 'loading services', + cost: '$0.00', + }, + { type: 'dim', text: '⎿ SQLite local codebase indexing active.', phase: 'indexing', detail: 'parsing file trees' }, + { + type: 'success', + text: '⎿ parsed 48 classes, 129 functions via tree-sitter.', + phase: 'indexing', + detail: 'database synced', + }, + { + type: 'info', + text: '⏺ planning: goal IR mapping generated', + phase: 'planning', + detail: 'analyzing dependencies', + cost: '$0.02', + }, + { + type: 'success', + text: '⎿ budget verified: monthly: $32.40, goal: $0.00', + phase: 'planning', + detail: 'goal limits audited', + }, + { + type: 'info', + text: '⏺ scheduling: topologically sorting tasks...', + phase: 'scheduling', + detail: 'batching queues', + }, + { type: 'dim', text: ' ├─ task 1: fetch db schema (Readonly)' }, + { type: 'dim', text: ' ├─ task 2: write routes/user.ts (writeAllowlist)' }, + { type: 'dim', text: ' ├─ task 3: write controllers/user.ts (writeAllowlist)' }, + { type: 'dim', text: ' └─ task 4: write tests/user.test.ts (writeAllowlist)' }, + { + type: 'info', + text: '◐ executing Task 2 & Task 3 in parallel...', + phase: 'execution', + detail: 'running batches', + cost: '$0.08', + }, + { type: 'success', text: ' ├─ checked out worktree: temp_wt_route', phase: 'execution', detail: 'route appended' }, + { + type: 'success', + text: ' ├─ checked out worktree: temp_wt_controller', + phase: 'execution', + detail: 'implementing services', + }, + { + type: 'error', + text: '✗ L1 verification failed: compile error in user.ts:14', + phase: 'verification', + detail: 'compilation fail', + }, + { + type: 'warning', + text: '⚠ feedback loop: re-injecting diagnostics...', + phase: 'replanning', + detail: 'adjusting AST changes', + cost: '$0.12', + }, + { type: 'success', text: '✓ compile check retry 1: PASS', phase: 'execution', detail: 'retry verify passing' }, + { + type: 'info', + text: '◐ executing Task 4 (integration test)...', + phase: 'execution', + detail: 'running test suite', + cost: '$0.15', + }, + { + type: 'success', + text: '✓ Bun test suite verified: 3 assertions passed', + phase: 'verification', + detail: 'tests passing', + }, + { type: 'info', text: '⏺ AI review: peer analysis passed', phase: 'verification', detail: 'peer reviewing' }, + { + type: 'success', + text: '✓ session merged successfully to main branch. cost $0.18', + phase: 'done', + detail: 'completed', + cost: '$0.18', + }, + ]; + + const transcriptStream = document.getElementById('tui-transcript-stream'); + const phaseTxt = document.getElementById('tui-phase-txt'); + const detailTxt = document.getElementById('tui-detail-txt'); + const costTxt = document.getElementById('tui-cost-txt'); + const composerInput = document.getElementById('tui-composer-input'); + + const simIndicator = document.getElementById('tui-sim-indicator'); + const ctrlSimToggle = document.getElementById('ctrl-sim-toggle'); + const ctrlSimReset = document.getElementById('ctrl-sim-reset'); + + // Overlay nodes snapshot statuses + const taskSnaps = { + 1: document.getElementById('task-snap-1'), + 2: document.getElementById('task-snap-2'), + 3: document.getElementById('task-snap-3'), + 4: document.getElementById('task-snap-4'), + 5: document.getElementById('task-snap-5'), + }; + + const verifyLayers = { + 1: document.getElementById('v-layer-1'), + 2: document.getElementById('v-layer-2'), + 3: document.getElementById('v-layer-3'), + 4: document.getElementById('v-layer-4'), + 5: document.getElementById('v-layer-5'), + }; + + let simIdx = 0; + let isSimRunning = false; + let simTimeoutId = null; + + function renderTuiLine(lineObj) { + const lineEl = document.createElement('div'); + lineEl.classList.add('tui-line'); + + const bulletEl = document.createElement('span'); + bulletEl.classList.add('tui-bullet'); + bulletEl.innerText = '·'; + lineEl.appendChild(bulletEl); + + const contentEl = document.createElement('span'); + contentEl.className = `tui-content ${lineObj.type}`; + contentEl.innerText = lineObj.text; + lineEl.appendChild(contentEl); + + transcriptStream.appendChild(lineEl); + transcriptStream.scrollTop = transcriptStream.scrollHeight; + + // Update Status Indicators + if (lineObj.phase) phaseTxt.innerText = lineObj.phase; + if (lineObj.detail) detailTxt.innerText = lineObj.detail; + if (lineObj.cost) costTxt.innerText = lineObj.cost; + } + + function updateOverlayStates(idx) { + // Task Overlay state updates + if (idx >= 2) taskSnaps[1].innerText = '✓ completed'; + else if (idx >= 0) taskSnaps[1].innerText = '◐ running'; + + if (idx >= 12) taskSnaps[2].innerText = '✓ completed'; + else if (idx >= 10) taskSnaps[2].innerText = '◐ running'; + + if (idx >= 15) taskSnaps[3].innerText = '✓ completed'; + else if (idx === 13) taskSnaps[3].innerText = '✗ failed'; + else if (idx >= 10) taskSnaps[3].innerText = '◐ running'; + + if (idx >= 17) taskSnaps[4].innerText = '✓ completed'; + else if (idx >= 16) taskSnaps[4].innerText = '◐ running'; + + if (idx >= 19) taskSnaps[5].innerText = '✓ completed'; + else if (idx >= 18) taskSnaps[5].innerText = '◐ running'; + + // Verification layers updates + if (idx >= 15) { + verifyLayers[1].className = 'tui-verify-layer passed'; + verifyLayers[1].innerText = '✓ Layer 1: Compilation (compile)'; + } else if (idx >= 13) { + verifyLayers[1].className = 'tui-verify-layer failed'; + verifyLayers[1].innerText = '✗ Layer 1: Compilation (compile)'; + } else if (idx >= 11) { + verifyLayers[1].className = 'tui-verify-layer pending'; + verifyLayers[1].innerText = '◐ Layer 1: Compilation (compile)'; + } + + if (idx >= 12) verifyLayers[2].className = 'tui-verify-layer passed'; + else if (idx >= 10) verifyLayers[2].className = 'tui-verify-layer pending'; + + if (idx >= 17) verifyLayers[3].className = 'tui-verify-layer passed'; + else if (idx >= 16) verifyLayers[3].className = 'tui-verify-layer pending'; + + if (idx >= 18) verifyLayers[4].className = 'tui-verify-layer passed'; + else if (idx >= 17) verifyLayers[4].className = 'tui-verify-layer pending'; + + if (idx >= 19) verifyLayers[5].className = 'tui-verify-layer passed'; + else if (idx >= 18) verifyLayers[5].className = 'tui-verify-layer pending'; + } + + function runSimLoop() { + if (!isSimRunning) return; + + if (simIdx < tuiEvents.length) { + renderTuiLine(tuiEvents[simIdx]); + updateOverlayStates(simIdx); + simIdx++; + simTimeoutId = setTimeout(runSimLoop, 1200); + } else { + // Completed TUI simulation + isSimRunning = false; + stopSpinner(); + simIndicator.innerText = 'simulation finished'; + ctrlSimToggle.innerHTML = '[space] restart'; + } + } + + function startSim() { + isSimRunning = true; + startSpinner(); + simIndicator.innerText = 'simulation running'; + ctrlSimToggle.innerHTML = '[space] pause'; + runSimLoop(); + } + + function pauseSim() { + isSimRunning = false; + clearTimeout(simTimeoutId); + stopSpinner(); + simIndicator.innerText = 'simulation paused'; + ctrlSimToggle.innerHTML = '[space] resume'; + } + + function toggleSim() { + if (simIdx >= tuiEvents.length) { + restartSim(); + } else if (isSimRunning) { + pauseSim(); + } else { + startSim(); + } + } + + function restartSim() { + clearTimeout(simTimeoutId); + transcriptStream.innerHTML = ''; + simIdx = 0; + phaseTxt.innerText = 'init'; + detailTxt.innerText = 'loading services'; + costTxt.innerText = '$0.00'; + + // reset overlay mock text/classes + Object.values(taskSnaps).forEach((el) => { + el.className = 'tui-task-state pending'; + el.innerText = '○ pending'; + }); + Object.values(verifyLayers).forEach((el, index) => { + el.className = 'tui-verify-layer pending'; + el.innerText = `○ Layer ${index + 1}: ${getLayerName(index + 1)}`; + }); + + startSim(); + } + + function getLayerName(layerNum) { + const names = { + 1: 'Compilation (compile)', + 2: 'Formatting & Linters (lint)', + 3: 'Integration test execution (tests)', + 4: 'Static security analysis (semgrep)', + 5: 'Peer review assessment (ai-review)', + }; + return names[layerNum]; + } + + // Bind simulation controls + ctrlSimToggle.addEventListener('click', (e) => { + e.stopPropagation(); + toggleSim(); + }); + + ctrlSimReset.addEventListener('click', (e) => { + e.stopPropagation(); + restartSim(); + }); + + // Start automatically + startSim(); +}); diff --git a/website/index.html b/website/index.html new file mode 100644 index 0000000..8cb0fb3 --- /dev/null +++ b/website/index.html @@ -0,0 +1,348 @@ + + + + + + LoopCode — Autonomous Software Orchestrator + + + + +
+ + +
+
+ + +
+
+ + +
+
+ built on top of opencode +
+ +

Autonomous software engineering

+

+ A headless CLI orchestrator built on OpenCode that decomposes natural language goals into a task DAG, executing + branches concurrently in isolated Git worktrees with strict 5-layer verification. +

+ +
+ curl -fsSL https://raw.githubusercontent.com/arjun-vegeta/loopCode/main/install.sh | bash + +
+ + +
+ +
+
+ LoopCode v2.0.0 + · loopcode · main · claude-3-5-sonnet +
+ simulation running +
+ + +
+ +
+ +
+ + + + +
+
+ Task Execution Graph + esc / click to close +
+
+
+ 1. Index codebase workspace + ✓ completed +
+
+ 2. Write profile route configs + ✓ completed +
+
+ 3. Write profile controller implementation + ✓ completed +
+
+ 4. Write profile endpoint integrations + ✓ completed +
+
+ 5. Validate code & review merge + ✓ completed +
+
+
+ + +
+
+ Verification Detail (5-Layer Gauntlet) + esc / click to close +
+
+
✓ Layer 1: Compilation (compile)
+
✓ Layer 2: Formatting & Linters (lint)
+
✓ Layer 3: Integration test execution (tests)
+
✓ Layer 4: Static security analysis (semgrep)
+
✓ Layer 5: Peer review assessment (ai-review)
+
+
+ + +
+
+ Quota Spend Control + esc / click to close +
+
+
+
Goal cost audit
+
spend: $0.18 / limit: $10.00
+
+ [████░░░░░░░░░░░░░░░░░░░░░] 1.8% +
+
+
+
Monthly cost audit
+
spend: $32.40 / limit: $100.00
+
+ [████████░░░░░░░░░░░░░░░░░] 32.4% +
+
+
+
+ + +
+
+ Keyboard Shortcuts + esc / click to close +
+
+
+ t / Tabopen task list +
+
+ vopen verification details +
+
+ bopen spend limits +
+
+ ctrl+cinterrupt task execution +
+
+
+ + +
+
+ + idle + · + waiting for input +
+
+ spent: $0.00 / $10.00 +
+
+ + +
+ > + "Add a new endpoint for user profile retrieval" + +
+
+ + +
+
[t] tasks
+
[v] verify
+
[b] budget
+
[h] help
+
+
[space] pause
+
[r] restart
+
+
+
+
+ + +
+

engine mechanics

+
+
+

shared sqlite memory

+

+ Central structured persistence decouples agents. Communication happens asynchronously via data contracts, + avoiding direct process dependencies. +

+
+
+

topological schedules

+

+ Sorts task DAGs based on resource allowlists. Spawns independent subtasks in parallel, executing changes in + isolated Git worktrees. +

+
+
+

5-layer verification

+

+ Integrates compilation audits, linter scans, Bun unit testing checks, Semgrep code security patterns, and AI + review loops before merging. +

+
+
+
+ + +
+

cli runtime parameters

+
+
+
loopcode "<goal>"
+
+ Accepts a natural language instruction to plan, construct worktrees, and verify code blocks. +
+
+
+
-d, --db <path>
+
+ Specifies the path to the SQLite persistence database (defaults to loopcode.db). +
+
+
+
-r, --resume <id>
+
Resumes execution from a previously interrupted Session ID or Task ID.
+
+
+
--login
+
+ Launches the in-terminal interactive authentication workflow for platform providers. +
+
+
+
--headless
+
Forces non-interactive execution suite mode (ideal for CI/CD environments).
+
+
+
+ + +
+

controlled configuration

+
+

+ Configure parameters inside ~/.loopcode/config.toml to restrict model routing definitions, set maximum spend + ceilings, and establish validation protocols. +

+

+ Compatible with all 100+ OpenCode model routers. Route subtasks dynamically to the optimal model based on + prompt complexity, cost thresholds, and cached instructions. +

+
+
+
+[model]
+default      = "anthropic/claude-sonnet-4-6"
+planning     = "anthropic/claude-opus-4-6"
+
+[budget]
+maxMonthlyCostUsd = 100.0
+maxGoalCostUsd    = 10.0
+maxTaskCostUsd    = 2.0
+
+[safety]
+permissionMode           = "acceptEdits"
+allowDestructiveRollback = false
+maxParallelAgents        = 5
+
+
+ + +
+
+

Install LoopCode CLI Now

+

+ Run standalone binary anywhere in seconds. Built on top of OpenCode with support for 100+ AI models. +

+
+ curl -fsSL https://raw.githubusercontent.com/arjun-vegeta/loopCode/main/install.sh | bash +
+
+
+ + + + + + + diff --git a/website/style.css b/website/style.css new file mode 100644 index 0000000..fb20b86 --- /dev/null +++ b/website/style.css @@ -0,0 +1,633 @@ +/* + LoopCode Clean Monospace TUI Design System + Replicates the exact terminal experience of LoopCode in a premium browser asset. + Focuses on thin lines, box borders, high-contrast monospace typography, and zero slop. +*/ + +@import url('https://fonts.googleapis.com/css2?family=Geist+Mono:wght@200;300;400;500&family=Geist:wght@200;300;400;500&display=swap'); + +:root { + --bg-page: #000000; + --bg-tui: #050507; + --bg-overlay: #0a0a0d; + + --border-tui: rgba(255, 255, 255, 0.08); + --border-active: rgba(255, 255, 255, 0.25); + + --text-primary: #f5f5f7; + --text-muted: #6e6e73; + --text-dim: #3a3a3c; + + /* TUI Theme Colors */ + --tui-cyan: #00f0ff; + --tui-cyan-dim: #0088cc; + --tui-green: #39d353; + --tui-yellow: #f1e05a; + --tui-red: #ff453a; + --tui-gray: #8e8e93; + --tui-white: #ffffff; + + --font-mono: 'Geist Mono', 'JetBrains Mono', 'Fira Code', monospace; + --font-sans: 'Geist', sans-serif; + + --transition-smooth: all 0.2s cubic-bezier(0.16, 1, 0.3, 1); +} + +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + background-color: var(--bg-page); + color: var(--text-primary); + font-family: var(--font-sans); + -webkit-font-smoothing: antialiased; + scroll-behavior: smooth; +} + +body { + min-height: 100vh; + overflow-x: hidden; + padding-bottom: 80px; +} + +/* Typography */ +h1, +h2, +h3, +h4 { + font-weight: 300; + letter-spacing: -0.02em; + color: var(--tui-white); +} + +p { + color: var(--text-muted); + font-weight: 300; + font-size: 0.95rem; + line-height: 1.5; +} + +a { + color: inherit; + text-decoration: none; +} + +.container { + max-width: 1000px; + margin: 0 auto; + padding: 0 24px; +} + +/* Header */ +header { + height: 64px; + border-bottom: 1px solid var(--border-tui); + display: flex; + align-items: center; + position: sticky; + top: 0; + background: rgba(0, 0, 0, 0.85); + backdrop-filter: blur(12px); + z-index: 100; +} + +.header-inner { + width: 100%; + display: flex; + justify-content: space-between; + align-items: center; +} + +.logo { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.9rem; + font-weight: 400; + letter-spacing: -0.01em; + font-family: var(--font-mono); +} + +.logo svg { + width: 16px; + height: 16px; + color: var(--tui-cyan); +} + +.header-nav { + display: flex; + gap: 24px; + font-size: 0.85rem; + color: var(--text-muted); +} + +.header-nav a:hover { + color: var(--text-primary); +} + +/* Hero */ +.hero { + padding: 60px 0 30px 0; + text-align: center; +} + +.hero h1 { + font-size: clamp(2rem, 5vw, 3rem); + margin-bottom: 12px; +} + +.hero p { + max-width: 540px; + margin: 0 auto 24px auto; + font-size: 0.95rem; +} + +/* Copyable installation badge */ +.cmd-badge { + display: inline-flex; + align-items: center; + background: var(--bg-tui); + border: 1px solid var(--border-tui); + border-radius: 4px; + padding: 8px 16px; + font-family: var(--font-mono); + font-size: 0.8rem; + color: var(--text-primary); + margin-bottom: 40px; +} + +.cmd-badge span { + opacity: 0.8; +} + +.cmd-badge button { + background: none; + border: none; + color: var(--text-muted); + cursor: pointer; + margin-left: 12px; + display: flex; + align-items: center; +} + +.cmd-badge button:hover { + color: var(--tui-white); +} + +/* High Fidelity TUI Component Shell */ +.tui-container { + background: var(--bg-tui); + border: 1px solid var(--border-tui); + border-radius: 8px; + box-shadow: 0 40px 120px rgba(0, 0, 0, 0.9); + overflow: hidden; + position: relative; + width: 100%; + margin-bottom: 60px; +} + +/* Header line in TUI */ +.tui-header { + height: 32px; + border-bottom: 1px dashed var(--border-tui); + display: flex; + align-items: center; + justify-content: space-between; + padding: 0 16px; + font-family: var(--font-mono); + font-size: 0.75rem; + user-select: none; +} + +.tui-title-group { + display: flex; + align-items: center; + gap: 12px; +} + +.tui-title { + color: var(--tui-cyan); +} + +.tui-meta { + color: var(--text-muted); +} + +.tui-status-tag { + color: var(--text-muted); +} + +/* Workspace Panels */ +.tui-body { + height: 440px; + padding: 16px; + font-family: var(--font-mono); + font-size: 0.8rem; + line-height: 1.45; + display: flex; + flex-direction: column; + justify-content: space-between; + position: relative; +} + +/* Scrolling transcript list */ +.tui-transcript { + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 4px; + margin-bottom: 12px; + padding-right: 8px; +} + +/* Custom Scrollbar for Transcript */ +.tui-transcript::-webkit-scrollbar { + width: 4px; +} +.tui-transcript::-webkit-scrollbar-track { + background: transparent; +} +.tui-transcript::-webkit-scrollbar-thumb { + background: var(--border-tui); + border-radius: 2px; +} + +.tui-line { + display: flex; + align-items: flex-start; + gap: 8px; +} + +.tui-bullet { + color: var(--text-muted); + user-select: none; +} + +.tui-content { + color: var(--text-primary); + white-space: pre-wrap; +} + +.tui-content.success { + color: var(--tui-green); +} +.tui-content.error { + color: var(--tui-red); +} +.tui-content.warning { + color: var(--tui-yellow); +} +.tui-content.info { + color: var(--tui-cyan); +} +.tui-content.dim { + color: var(--text-muted); +} + +/* Live Status indicator row */ +.tui-livestatus { + border-top: 1px dashed var(--border-tui); + border-bottom: 1px dashed var(--border-tui); + padding: 10px 0; + margin-bottom: 12px; + display: flex; + justify-content: space-between; + align-items: center; + font-size: 0.75rem; + user-select: none; +} + +.tui-status-left { + display: flex; + align-items: center; + gap: 8px; +} + +.tui-spinner { + color: var(--tui-cyan); +} + +.tui-phase-value { + color: var(--tui-cyan); +} + +.tui-detail-value { + color: var(--tui-white); +} + +.tui-status-right { + display: flex; + align-items: center; + gap: 16px; +} + +.tui-cost-value { + color: var(--tui-green); +} + +/* Composer / Input line */ +.tui-composer { + display: flex; + align-items: center; + gap: 8px; + height: 28px; + font-size: 0.8rem; +} + +.tui-prompt-symbol { + color: var(--tui-cyan); + user-select: none; +} + +.tui-composer-text { + color: var(--text-primary); + flex: 1; +} + +.tui-composer-text.working { + color: var(--text-muted); +} + +.tui-cursor { + display: inline-block; + width: 7px; + height: 14px; + background: var(--tui-white); + vertical-align: middle; + animation: tuiBlink 1s step-end infinite; +} + +@keyframes tuiBlink { + 50% { + opacity: 0; + } +} + +/* Hint Bar / Controls at bottom */ +.tui-hints { + background: rgba(255, 255, 255, 0.01); + border-top: 1px solid var(--border-tui); + height: 36px; + display: flex; + align-items: center; + padding: 0 16px; + font-family: var(--font-mono); + font-size: 0.7rem; + gap: 16px; + user-select: none; +} + +.tui-hint-item { + color: var(--text-muted); + cursor: pointer; + transition: var(--transition-smooth); +} + +.tui-hint-item span { + color: var(--tui-cyan); +} + +.tui-hint-item:hover { + color: var(--text-primary); +} + +.tui-hint-item.active { + color: var(--tui-cyan); +} + +/* TUI Inline Overlays (Box drawing style) */ +.tui-overlay-container { + position: absolute; + top: 16px; + left: 16px; + right: 16px; + bottom: 84px; + background: var(--bg-overlay); + border: 1px solid var(--tui-cyan); + border-radius: 4px; + z-index: 10; + display: none; /* controlled by JS */ + flex-direction: column; + padding: 12px 16px; + box-shadow: 0 10px 50px rgba(0, 0, 0, 0.9); +} + +.tui-overlay-container.active { + display: flex; +} + +.tui-overlay-title { + color: var(--tui-cyan); + font-size: 0.8rem; + border-bottom: 1px dashed var(--border-tui); + padding-bottom: 8px; + margin-bottom: 12px; + display: flex; + justify-content: space-between; +} + +.tui-overlay-title span.title-text { + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.tui-overlay-title span.close-hint { + color: var(--text-muted); + font-size: 0.65rem; +} + +.tui-overlay-content { + flex: 1; + overflow-y: auto; + display: flex; + flex-direction: column; + gap: 8px; +} + +.tui-task-row { + display: flex; + justify-content: space-between; + border-bottom: 1px solid rgba(255, 255, 255, 0.02); + padding-bottom: 4px; +} + +.tui-task-name { + color: var(--tui-white); +} + +.tui-task-state { + font-family: var(--font-mono); + font-size: 0.75rem; +} + +.tui-task-state.success { + color: var(--tui-green); +} +.tui-task-state.failed { + color: var(--tui-red); +} +.tui-task-state.running { + color: var(--purple); +} +.tui-task-state.pending { + color: var(--text-muted); +} + +/* Verification Overlay layers */ +.tui-verify-layer { + display: flex; + align-items: center; + gap: 8px; + margin-left: 12px; +} + +.tui-verify-layer.passed { + color: var(--tui-green); +} +.tui-verify-layer.failed { + color: var(--tui-red); +} +.tui-verify-layer.pending { + color: var(--text-dim); +} + +/* Minimal project breakdown section */ +.section-title { + font-size: 1.5rem; + margin-bottom: 40px; + border-bottom: 1px solid var(--border-tui); + padding-bottom: 12px; +} + +.features-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 32px; + margin-bottom: 80px; +} + +.feature-card { + border: 1px solid var(--border-tui); + background: var(--bg-tui); + border-radius: 4px; + padding: 24px; + display: flex; + flex-direction: column; + gap: 12px; + transition: var(--transition-smooth); +} + +.feature-card:hover { + border-color: var(--border-active); +} + +.feature-card h3 { + font-size: 1rem; + font-family: var(--font-mono); + color: var(--tui-cyan); +} + +.feature-card p { + font-size: 0.85rem; +} + +/* CLI Options block */ +.cli-options { + margin-bottom: 8px; +} + +.cli-option-row { + display: flex; + border-bottom: 1px solid var(--border-tui); + padding: 12px 0; + font-size: 0.85rem; +} + +.cli-option-name { + width: 240px; + font-family: var(--font-mono); + color: var(--tui-cyan-dim); +} + +.cli-option-desc { + flex: 1; + color: var(--text-muted); +} + +/* Monospace toml config layout */ +.config-layout { + display: grid; + grid-template-columns: 1.2fr 1fr; + gap: 40px; + margin: 60px 0 80px 0; + align-items: center; +} + +.config-code-block { + background: var(--bg-tui); + border: 1px solid var(--border-tui); + border-radius: 4px; + padding: 20px; + font-family: var(--font-mono); + font-size: 0.75rem; + line-height: 1.5; + color: var(--tui-white); + overflow-x: auto; +} + +.config-text { + display: flex; + flex-direction: column; + justify-content: center; + gap: 16px; +} + +/* Setup Section */ +.setup-box { + background: radial-gradient(circle at top, rgba(0, 240, 255, 0.04) 0%, rgba(5, 5, 7, 0.95) 100%), var(--bg-tui); + border: 1px solid var(--border-tui); + border-radius: 6px; + padding: 56px 48px; + text-align: center; + margin-bottom: 100px; + box-shadow: 0 20px 80px rgba(0, 240, 255, 0.02); +} + +/* Footer styling */ +footer { + border-top: 1px dashed var(--border-tui); + padding: 40px 0; + font-size: 0.75rem; + color: var(--text-dim); + font-family: var(--font-mono); +} + +.footer-inner { + display: flex; + justify-content: space-between; +} + +@media (max-width: 900px) { + .features-grid { + grid-template-columns: 1fr; + } + .config-layout { + grid-template-columns: 1fr; + } + .tui-livestatus { + flex-direction: column; + align-items: flex-start; + gap: 8px; + } + .cli-option-row { + flex-direction: column; + gap: 4px; + } + .cli-option-name { + width: 100%; + } +}