Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions docs/superpowers/plans/2026-07-10-dimmer-terminal-coral.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Dimmer Terminal Coral Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Replace the bright terminal coral family with substantially dimmer tones while keeping Ink and raw ANSI output consistent.

**Architecture:** The palette remains centralized in `src/ui/theme.ts`. Change the primary accent in its hex and ANSI forms and add a focused consistency test; all consumers continue using the existing tokens.

**Tech Stack:** TypeScript, Ink, Vitest, tsup

## Global Constraints

- Use `#B85C4A` and RGB `184,92,74` for the primary accent.
- Use `#9E4938` and RGB `158,73,56` for the strong accent.
- Leave all other palette tokens and color-gating behavior unchanged.
- Do not add dependencies or start a server.

---

### Task 1: Dim the primary accent token

**Files:**
- Modify: `src/ui/theme.ts`
- Test: `test/ui/theme.test.ts`

**Interfaces:**
- Consumes: the exported `theme.accent` and `ansi.accent` tokens.
- Produces: matching hex and ANSI values for the dimmed primary and strong coral tokens.

- [ ] **Step 1: Write the failing test**

Add this test to `test/ui/theme.test.ts`:

```ts
it('keeps the muted coral hex and ANSI accent values aligned', () => {
expect(theme.accent).toBe('#B85C4A')
expect(ansi.accent).toBe('\x1b[38;2;184;92;74m')
expect(theme.accentStrong).toBe('#9E4938')
expect(ansi.accentStrong).toBe('\x1b[38;2;158;73;56m')
})
```

Import `ansi` and `theme` from `../../src/ui/theme.js`.

- [ ] **Step 2: Run the focused test to verify it fails**

Run: `npx vitest run test/ui/theme.test.ts`

Expected: FAIL because the current coral tokens still use the brighter values.

- [ ] **Step 3: Update the centralized tokens**

In `src/ui/theme.ts`, set:

```ts
accent: '#B85C4A',
accentStrong: '#9E4938',
```

and:

```ts
accent: '\x1b[38;2;184;92;74m',
accentStrong: '\x1b[38;2;158;73;56m',
```

Update the adjacent comments to describe the muted terminal coral accurately.

- [ ] **Step 4: Run focused and full verification**

Run:

```bash
npx vitest run test/ui/theme.test.ts
npm test
npm run typecheck
npm run build
```

Expected: every command exits successfully.
34 changes: 34 additions & 0 deletions docs/superpowers/specs/2026-07-10-dimmer-terminal-coral-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Dimmer Terminal Coral Design

## Goal

Make Orca's primary coral accent more comfortable for sustained use on dark
terminal backgrounds without changing the CLI's visual hierarchy or color
semantics.

## Design

Replace the primary accent `#FE785D` (RGB `254,120,93`) with the substantially
dimmer coral `#B85C4A` (RGB `184,92,74`). Replace the strong accent `#F0543C`
(RGB `240,84,60`) with `#9E4938` (RGB `158,73,56`). The new colors keep the
existing warm coral hue while reducing brightness and saturation enough to
avoid glare.

Update both representations in `src/ui/theme.ts`:

- `theme.accent`, used by Ink components, becomes `#B85C4A`.
- `ansi.accent`, used by direct terminal output, becomes the matching 24-bit
escape sequence `\x1b[38;2;184;92;74m`.
- `theme.accentStrong` and `ansi.accentStrong` become `#9E4938` and
`\x1b[38;2;158;73;56m` respectively, keeping inline code from retaining the
brighter coral.

Leave status colors, muted text, subtle text, borders, and `NO_COLOR` behavior
unchanged. This is a token-only change; every existing accent consumer inherits
it automatically.

## Verification

Add a focused theme test that locks the Ink and ANSI representations to the
same RGB value. Run the theme test, the full test suite, typecheck, and package
build. Do not start a development server.
12 changes: 6 additions & 6 deletions src/ui/theme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@
import type { RunStatus } from '../lib/types.js'

export const theme = {
// Brand coral, --accent hsl(10 100% 68%) = #FE785D.
accent: '#FE785D',
// --accent-strong hsl(10 90% 58%).
accentStrong: '#F0543C',
// Dim terminal coral: warm enough for the brand, muted for sustained use.
accent: '#B85C4A',
// Strong coral stays darker than the primary accent for inline emphasis.
accentStrong: '#9E4938',
// --text-muted (66%): secondary text, table body.
muted: '#A8A8A8',
// --text-subtle (46%): hints, timestamps, dividers.
Expand All @@ -38,8 +38,8 @@ export const theme = {
// The coral wordmark and subtle grays as raw 24-bit ANSI, for the banner and
// any output that renders outside Ink. Mirrors the hex tokens above.
export const ansi = {
accent: '\x1b[38;2;254;120;93m',
accentStrong: '\x1b[38;2;240;84;60m',
accent: '\x1b[38;2;184;92;74m',
accentStrong: '\x1b[38;2;158;73;56m',
muted: '\x1b[38;2;168;168;168m',
subtle: '\x1b[38;2;117;117;117m',
destructive: '\x1b[38;2;220;60;60m',
Expand Down
3 changes: 2 additions & 1 deletion test/banner.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { afterEach, describe, expect, it, vi } from 'vitest'

import { bannerString } from '../src/ui/banner.js'
import { ansi } from '../src/ui/theme.js'
import { VERSION } from '../src/version.js'

const realIsTTY = process.stdout.isTTY
Expand Down Expand Up @@ -45,7 +46,7 @@ describe('bannerString', () => {
process.stdout.isTTY = true
vi.stubEnv('NO_COLOR', '')
const s = bannerString()
expect(s).toContain('38;2;254;120;93') // coral
expect(s).toContain(ansi.accent)
expect(s).toContain('\x1b[1m') // bold ORCA
})
})
4 changes: 2 additions & 2 deletions test/commands/platform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { registerPlatform, renderTopologyTree } from '../../src/commands/platform.js'
import { saveConfig } from '../../src/lib/config.js'
import { ExitCode } from '../../src/lib/errors.js'
import { glyphs } from '../../src/ui/theme.js'
import { ansi, glyphs } from '../../src/ui/theme.js'
import { jsonResponse, stubFetch } from '../helpers/fetch-mock.js'
import { useTmpConfigDir } from '../helpers/tmp-config.js'

Expand Down Expand Up @@ -104,7 +104,7 @@ describe('renderTopologyTree', () => {
})

it('emits coral ANSI on the conductor node when color is enabled', () => {
expect(renderTopologyTree(TOPOLOGY, { color: true })).toContain('38;2;254;120;93')
expect(renderTopologyTree(TOPOLOGY, { color: true })).toContain(ansi.accent)
})

it('handles an empty pool without throwing', () => {
Expand Down
11 changes: 10 additions & 1 deletion test/ui/theme.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
import { afterEach, describe, expect, it, vi } from 'vitest'

import { glyphs, POINTER, unicodeEnabled } from '../../src/ui/theme.js'
import { ansi, glyphs, POINTER, theme, unicodeEnabled } from '../../src/ui/theme.js'

afterEach(() => {
vi.unstubAllEnvs()
})

describe('coral palette', () => {
it('keeps the dim coral hex and ANSI values aligned', () => {
expect(theme.accent).toBe('#B85C4A')
expect(ansi.accent).toBe('\x1b[38;2;184;92;74m')
expect(theme.accentStrong).toBe('#9E4938')
expect(ansi.accentStrong).toBe('\x1b[38;2;158;73;56m')
})
})

// unicodeEnabled reads env live, so we exercise the tier selection through it.
// glyphs/POINTER are resolved once at module load and are asserted for shape.
describe('unicodeEnabled', () => {
Expand Down