diff --git a/apps/web/app/globals.css b/apps/web/app/globals.css
index 46f20bb..7a56b6a 100644
--- a/apps/web/app/globals.css
+++ b/apps/web/app/globals.css
@@ -20,6 +20,7 @@
--blue-soft: oklch(0.72 0.13 247 / 0.11);
--rail-width: 236px;
--topbar-height: 64px;
+ --ease-out-terminal: cubic-bezier(0.22, 1, 0.36, 1);
}
* {
@@ -32,6 +33,29 @@ body {
min-height: 100%;
}
+* {
+ scrollbar-color: oklch(0.78 0.12 74 / 0.24) oklch(0.12 0.01 250 / 0.5);
+}
+
+*::-webkit-scrollbar {
+ width: 10px;
+ height: 10px;
+}
+
+*::-webkit-scrollbar-track {
+ background: oklch(0.12 0.01 250 / 0.5);
+}
+
+*::-webkit-scrollbar-thumb {
+ border: 2px solid oklch(0.12 0.01 250 / 0.72);
+ border-radius: 999px;
+ background: oklch(0.78 0.12 74 / 0.24);
+}
+
+*::-webkit-scrollbar-thumb:hover {
+ background: oklch(0.78 0.12 74 / 0.36);
+}
+
body {
min-height: 100vh;
font-family: var(--font-sans), sans-serif;
@@ -140,7 +164,10 @@ input {
text-transform: uppercase;
letter-spacing: 0.14em;
font-size: 0.76rem;
- transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
+ transition:
+ border-color 160ms var(--ease-out-terminal),
+ background-color 160ms var(--ease-out-terminal),
+ color 160ms var(--ease-out-terminal);
}
.terminal-nav-link:hover {
@@ -160,6 +187,7 @@ input {
border-color: var(--border-strong);
color: var(--text);
background: var(--accent-soft);
+ box-shadow: inset 0 0 0 1px oklch(0.78 0.12 74 / 0.08);
}
.shell-metrics {
@@ -172,7 +200,7 @@ input {
padding: 11px 13px;
border-radius: 10px;
border: 1px solid var(--border);
- background: var(--bg-soft);
+ background: linear-gradient(180deg, oklch(0.97 0.008 250 / 0.05), oklch(0.97 0.008 250 / 0.025));
}
.shell-metric-label,
@@ -383,6 +411,36 @@ input {
text-transform: uppercase;
letter-spacing: 0.12em;
font-size: 0.72rem;
+ transition:
+ border-color 160ms var(--ease-out-terminal),
+ background-color 160ms var(--ease-out-terminal),
+ color 160ms var(--ease-out-terminal),
+ opacity 160ms var(--ease-out-terminal);
+}
+
+.terminal-button:hover:not(:disabled),
+.mode-button:hover:not(:disabled),
+.filter-clear:hover:not(:disabled),
+.jump-button:hover:not(:disabled),
+.pause-button:hover:not(:disabled),
+.interval-button:hover:not(:disabled),
+.overlay-toggle:hover:not(:disabled),
+.drawer-close:hover:not(:disabled) {
+ border-color: oklch(0.78 0.09 74 / 0.36);
+ background: oklch(0.78 0.12 74 / 0.075);
+ color: var(--text);
+}
+
+.terminal-button:active:not(:disabled),
+.mode-button:active:not(:disabled),
+.filter-clear:active:not(:disabled),
+.jump-button:active:not(:disabled),
+.pause-button:active:not(:disabled),
+.interval-button:active:not(:disabled),
+.overlay-toggle:active:not(:disabled),
+.drawer-close:active:not(:disabled) {
+ border-color: oklch(0.78 0.1 74 / 0.5);
+ background: oklch(0.78 0.12 74 / 0.12);
}
.terminal-button:disabled,
@@ -411,7 +469,7 @@ input {
padding: 5px 8px 5px 10px;
border: 1px solid var(--border-strong);
border-radius: 8px;
- background: oklch(0.78 0.12 74 / 0.07);
+ background: linear-gradient(180deg, oklch(0.78 0.12 74 / 0.09), oklch(0.78 0.12 74 / 0.045));
color: var(--text);
font-family: var(--font-mono), monospace;
font-size: 0.72rem;
@@ -456,6 +514,12 @@ input {
outline: none;
}
+.instrument-cell-button:focus-visible {
+ outline: 1px solid oklch(0.83 0.08 74 / 0.82);
+ outline-offset: 3px;
+ border-radius: 4px;
+}
+
.pause-button {
padding: 7px 10px;
font-size: 0.66rem;
@@ -721,7 +785,9 @@ h3 {
flex-direction: column;
border: 1px solid var(--border);
border-radius: 14px;
- background: var(--bg-pane);
+ background:
+ linear-gradient(180deg, oklch(0.21 0.013 250 / 0.42), transparent 140px),
+ var(--bg-pane);
overflow: hidden;
}
@@ -732,7 +798,7 @@ h3 {
gap: 12px;
padding: 15px 18px;
border-bottom: 1px solid var(--border);
- background: oklch(0.2 0.012 250 / 0.38);
+ background: oklch(0.2 0.012 250 / 0.48);
}
.terminal-pane-title-row {
@@ -1022,6 +1088,7 @@ h3 {
overflow-y: hidden;
border-top: 1px solid var(--border);
border-bottom: 1px solid var(--border);
+ border-radius: 10px;
background: oklch(0.14 0.01 250 / 0.72);
}
@@ -1105,6 +1172,10 @@ h3 {
letter-spacing: 0.08em;
}
+.data-table-head .data-table-cell {
+ font-size: inherit;
+}
+
.data-table-row {
width: 100%;
height: 40px;
@@ -1115,6 +1186,9 @@ h3 {
color: inherit;
font: inherit;
text-align: left;
+ transition:
+ background-color 140ms var(--ease-out-terminal),
+ box-shadow 140ms var(--ease-out-terminal);
}
.data-table-row.is-even {
@@ -1130,7 +1204,8 @@ h3 {
.data-table-row:hover,
.data-table-row:focus-visible {
- outline: none;
+ outline: 1px solid oklch(0.78 0.12 74 / 0.36);
+ outline-offset: -1px;
background: oklch(0.78 0.12 74 / 0.05);
}
@@ -1230,6 +1305,7 @@ h3 {
text-overflow: ellipsis;
white-space: nowrap;
font-size: 0.72rem;
+ line-height: 1.25;
}
.data-table-cell-number {
@@ -1568,8 +1644,11 @@ h3 {
padding: 18px;
border-radius: 12px;
border: 1px dashed var(--border);
- background: var(--bg-soft);
+ background:
+ linear-gradient(135deg, oklch(0.78 0.12 74 / 0.045), transparent 42%),
+ var(--bg-soft);
color: var(--text-dim);
+ line-height: 1.45;
}
.drawer {
@@ -2012,12 +2091,13 @@ h3 {
}
.shell-metrics {
- display: flex;
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}
.shell-metric {
- flex: 0 0 156px;
+ min-width: 0;
}
.terminal-content {
@@ -2042,6 +2122,12 @@ h3 {
align-items: flex-start;
}
+ .page-actions {
+ width: 100%;
+ flex-direction: column;
+ align-items: stretch;
+ }
+
.terminal-pane-title-row {
flex-direction: column;
align-items: flex-start;
@@ -2083,9 +2169,11 @@ h3 {
.terminal-topbar-mode .terminal-button,
.terminal-topbar-controls > .terminal-button,
+ .page-actions > .contract-filter-button,
.page-actions > .terminal-button,
.page-actions > .flow-filter-popover {
width: 100%;
+ max-width: none;
}
.instrument-focus-chip {
diff --git a/docs/turns/2026-05-17-1123-polish-terminal-view.html b/docs/turns/2026-05-17-1123-polish-terminal-view.html
new file mode 100644
index 0000000..2fee553
--- /dev/null
+++ b/docs/turns/2026-05-17-1123-polish-terminal-view.html
@@ -0,0 +1,182 @@
+
+
+
+
+
+ 2026-05-17 11:23, Polish Terminal View
+
+
+
+
+
+ Turn Document, 2026-05-17 11:23 ET
+ Polish Terminal View
+
+ Refined the Islandflow web terminal shell so the Tape view feels more deliberate, more keyboard-readable, and more stable across desktop and mobile.
+
+
+
+
+ Summary
+
+ This was a focused product polish pass on apps/web/app/globals.css. The work stayed inside the established Islandflow terminal design language: dark operational surfaces, scarce amber emphasis, compact controls, and clear evidence-console states.
+
+
+
+
+ Changes Made
+
+ - Added a shared terminal easing token for consistent, restrained interaction transitions.
+ - Styled scrollbars to match the terminal surface instead of falling back to browser defaults.
+ - Improved nav, button, and active-control hover and pressed states using the existing OKLCH palette.
+ - Refined shell metrics, pane headers, table shells, row focus states, and empty states for clearer hierarchy.
+ - Adjusted mobile metric cards and Tape action controls so they align cleanly without horizontal page overflow.
+
+
+
+
+ Context
+
+ Islandflow is a serious market-data terminal for traders and researchers. The polish target was product UI, not brand theater, so the changes prioritize trust, legibility, predictable controls, and stable responsive structure.
+
+
+
+
+ Important Implementation Details
+
+ - All new color work uses existing OKLCH roles and keeps amber as a scarce signal rather than a decorative wash.
+ - Keyboard focus on table rows and instrument buttons is now visible without introducing layout shift.
+ - Mobile shell metrics now use a two-column grid, and page actions stretch to the viewport width.
+ - The polish is CSS-only, so no data contracts, route behavior, or live-stream logic changed.
+
+
+
+
+ Expected Impact for End-Users
+
+ Users should experience a terminal that reads as more finished under pressure: clearer controls, cleaner empty states, better keyboard affordances, and less visual friction on narrow screens.
+
+
+
+
+ Validation
+
+ bun install completed to restore missing workspace dependencies.
+ bun test apps/web/app/terminal.test.ts apps/web/app/routes.test.ts passed with 69 tests.
+ bun --cwd=apps/web run build passed.
+ - Playwright visual QA checked
http://localhost:3000/tape at 1440x1000 and 390x900.
+ - Visual QA confirmed no document-level horizontal overflow after the responsive polish.
+
+
+
+
+ Issues, Limitations, and Mitigations
+
+ - The local backend WebSocket at
localhost:4000 was offline during visual QA, so the screen showed disconnected empty states. This was useful for validating the empty-state polish but did not exercise live data density.
+ - Playwright needed a locally cached Chromium executable. The visual check used an existing browser cache path after the default runtime binary was unavailable.
+
+
+
+
+ Follow-up Work
+
+ No new Beads follow-up issue was filed. Live-data density should be rechecked naturally when the full local stack is running, but this polish did not reveal a separate actionable defect.
+
+
+
+
+