diff --git a/README.md b/README.md
index c8fbae3..8489c0a 100644
--- a/README.md
+++ b/README.md
@@ -5,9 +5,11 @@ Local **solo EM workbench** for evidence-backed performance reviews and promotio
ICs never log in. Self and peer input arrives as JSON import bundles. Your vault stays on disk: **Lock & encrypt** seals SQLite and dossier files at rest.
-
+
+
Dark · Coral — one of sixteen appearance combinations
+
## Why this exists
Most review tools are either a shared HR portal (everyone logs in) or a blank Google Doc. This app is for one engineering manager who wants:
@@ -61,14 +63,10 @@ pnpm desktop:dev # native window (needs WebView + Rust)
pnpm desktop:build
```
-Desktop installers are built on demand: Actions → **CI** → **Run workflow** (uploads `desktop-windows-x86_64`, `desktop-macos-aarch64`, `desktop-linux-x86_64`). Merges to `main` only run unit tests. Details: [`apps/desktop/README.md`](./apps/desktop/README.md).
-
-The desktop shell spawns a bundled Node API sidecar, serves the UI from that same origin (avoids WebView `Failed to fetch`), injects a launch token into the webview, and stores vault data under the OS app-data directory (not a CI build path). If unlock hangs, check `desktop-api.log` next to the vault.
+Desktop installers are built on demand: Actions → **CI** → **Run workflow** (uploads `desktop-windows-x86_64`, `desktop-macos-aarch64`, `desktop-linux-x86_64`). Merges to `main` only run unit tests + typecheck. Details: [`apps/desktop/README.md`](./apps/desktop/README.md).
### Cursor MCP (bulk load)
-`@prm/mcp` unlocks the vault and writes dossier evidence. Pair it with Jira, Bitbucket, or other MCPs when you need a cold-start backfill instead of typing every note by hand.
-
```bash
pnpm mcp
```
@@ -77,75 +75,104 @@ Setup: [`packages/mcp/README.md`](./packages/mcp/README.md) · [`.cursor/mcp.jso
---
+## Appearance
+
+Settings → Appearance picks **dark / light / system** plus one of **eight accents**. That is sixteen looks on the same product surface.
+
+| Accents | |
+|---------|---|
+| Classic | Teal · Ocean · Forest · Slate |
+| Vibrant | Coral · Amber · Magenta · Citrus |
+
+### Dark accents
+
+| Teal | Ocean | Forest | Slate |
+|:---:|:---:|:---:|:---:|
+|  |  |  |  |
+| **Coral** | **Amber** | **Magenta** | **Citrus** |
+|  |  |  |  |
+
+### Light accents
+
+| Teal | Ocean | Forest | Slate |
+|:---:|:---:|:---:|:---:|
+|  |  |  |  |
+| **Coral** | **Amber** | **Magenta** | **Citrus** |
+|  |  |  |  |
+
+Every main page was also captured in every accent × mode. Browse the matrix under [`docs/screenshots/themes/`](./docs/screenshots/themes/) or the index in [`docs/screenshots/THEMES.md`](./docs/screenshots/THEMES.md).
+
+---
+
## Screens
-Regenerate with `pnpm screenshots` (UI + API running; default password `workbench`).
+Regenerate with `pnpm screenshots` (UI + API running; demo password `workbench`). The tour below rotates accents so you see the product across the palette.
### Unlock
-**Intent:** Keep the workspace sealed when you walk away. The unlock gate is the trust boundary for local data.
+**Intent:** Keep the workspace sealed when you walk away.
-**How it works:** On first run you create a workspace password and choose an empty vault or a seeded demo org. Later sessions decrypt the vault with that password. **Lock & encrypt** re-seals SQLite and files so a stolen laptop disk is not a readable review archive. To wipe and start over, use **Erase workspace** on Unlock or **Delete workspace** in Settings (password + type `DELETE`).
+**How it works:** On first run you create a workspace password and choose an empty vault or a seeded demo org. Later sessions decrypt with that password. **Lock & encrypt** re-seals SQLite and files. Wipe with **Erase workspace** / **Delete workspace** (password + type `DELETE`).

-### Home (command center)
+### Home (command center) — dark Teal
-**Intent:** Answer "who is blocked, and what should I do next?" without hunting through every page.
+**Intent:** Answer "who is blocked, and what should I do next?"
-**How it works:** Pick a cycle to see pipeline status (self / peer / manager), deadline nudges for missing self reviews, and a compact cycle dashboard (writing time, evidence coverage, thin dossiers). Links out to writing desks, backfill, and team performance when the numbers look thin. **Needs director attention** surfaces flags only (stagnant ratings, thin evidence, promo-ready, open concern counts) with a jump into consistency / director packs — no private note bodies. Sticky **On this page** jumps between cycle, attention, dashboard, and queue.
+**How it works:** Pick a cycle for pipeline status, deadline nudges, writing-time / evidence dashboard, and **Needs director attention** (flags only — no private note bodies). Sticky **On this page** jumps between cycle, attention, dashboard, and queue.


-### Team
+### Team — dark Coral
-**Intent:** Maintain the roster of directs you actually manage reviews for.
+**Intent:** Maintain the roster of directs you manage reviews for.
-**How it works:** List, add, or CSV-import people, then open a person to work their dossier. This is the directory, not the evaluation surface. Role assignment and cycle participation hang off these records.
+**How it works:** List, add, or CSV-import people (EM required first), then open a dossier. Role assignment and cycle participation hang off these records.

-### Person dossier
+### Person dossier — dark Magenta
-**Intent:** Build a citation pool all year so the writing desk is not empty in week one of reviews.
+**Intent:** Build a citation pool all year so writing season is not empty.
-**How it works:** Capture achievements, goals, feedback (with optional 1:1 theme tags), documents, concern / underperformance notes, and external links (for example Jira or Bitbucket sync). The **Timeline** panel stitches those events with manager reviews and rating decisions so you can prep a 1:1 without opening five pages. Visibility controls keep EM-only material out of subject exports. AI digests and drafts pull from this pool (and from concerns only when you opt them in). Sticky **On this page** jumps across timeline, integrations, and capture sections.
+**How it works:** Achievements, goals, feedback (optional 1:1 themes), documents, concerns, integrations, and a **Timeline**. Visibility keeps EM-only material out of subject exports.

-### Roles
+### Roles — light Ocean
-**Intent:** Make the evaluation bar explicit. Ratings should map to role expectations, not a private mental model.
+**Intent:** Make the evaluation bar explicit.
-**How it works:** Author or import RoleDefinitions (ladder levels, competency keys, expectations). Assign each person a current role and optionally a next role for promo / gap work. Uploaded R&R docs can be structured manually or with AI extract. Writing desks and promotion packets read from these definitions.
+**How it works:** Author or import RoleDefinitions, assign current / next roles, extract from R&R docs. Writing desks and promo packets read from these definitions.

-### Cycles
+### Cycles — dark Citrus
-**Intent:** Time-box a review season and collect self / peer input without live IC login.
+**Intent:** Time-box a review season without live IC login.
-**How it works:** Create a cycle with a window and soft phases. Export JSON bundles for self and peer forms, collect them outside the app, then import responses. Waive with a reason when someone is not returning a form. Participants snapshot who was on the team for that cycle.
+**How it works:** Create a cycle, export self/peer JSON bundles, import responses, waive with a reason when needed.

-### Writing desk
+### Writing desk — dark Coral
-**Intent:** Produce an evidence-backed manager review in a bounded amount of time (target ≤45 minutes per person).
+**Intent:** Evidence-backed manager review in a bounded time (target ≤45 min/person).
-**How it works:** Score competencies and overall against the assigned role, link dossier evidence to non-middle scores, draft narrative sections (optionally with AI from an allowlisted citation set), run bias / faithfulness lint, log decision reasons when ratings move, then finalize. Finalize freezes citation snapshots. Share exports HTML (print to PDF) with private notes and EM-only sources stripped. For upward share: **Skip-level talking points** (AI, forced achievement cites) and a per-person **Director card** HTML briefing.
+**How it works:** Score against the assigned role, link evidence, draft (optionally with AI), lint, finalize (freezes cites), then share HTML with private / EM-only stripped. Skip-level talking points and a per-person director card for upward share.


-### Promotions
+### Promotions — light Magenta / dark Ocean
-**Intent:** Reuse the same role bar for next-level and promotion cases instead of a parallel doc pile.
+**Intent:** Reuse the same role bar for next-level cases.
-**How it works:** Open a promotion packet against a target RoleDefinition. Mark gaps / demonstrating signals, draft the case (optionally with AI), and keep it alongside the cycle review history so skip-level conversations stay evidence-backed. After submit, **Promo committee export** prints an HTML packet with allowlisted cites and delivery themes (private / EM-only stripped).
+**How it works:** Mark gaps vs demonstrating, draft the case, then **Promo committee export** for a printable packet with allowlisted cites.

@@ -153,55 +180,55 @@ Regenerate with `pnpm screenshots` (UI + API running; default password `workbenc

-### Consistency
+### Consistency — dark Forest
-**Intent:** Catch unfair shape in your own drafts before anyone else sees them (everyone a 4, extreme scores with no cites, missing roles).
+**Intent:** Catch unfair shape in your own drafts before anyone else sees them.
-**How it works:** For a selected cycle, show overall rating distribution and a card per person with competencies, evidence link counts, and flags (thin evidence, extreme overall, unassigned role). Jump into each writing desk to fix gaps. This is single-EM calibration, not a multi-manager room. **Calibration bundles** add director handoff: print calib room pack, cycle director briefing, encrypted read-only `.prm.enc` bundle, plus JSON export/import for decision round-trip.
+**How it works:** Rating distribution, per-person cards, flags (thin evidence, extreme overall, unassigned role). **Calibration bundles** for director handoff and encrypted read-only `.prm.enc` packs.


-### Team performance
+### Team performance — light Coral / Amber
-**Intent:** See the team's rating and coaching shape as graphs, not only as a queue of drafts.
+**Intent:** See rating and coaching shape as graphs.
-**How it works:** Cycle-scoped charts for overall distribution, evidence vs overall, competency averages, promo readiness, writing-time buckets, level mix, and top 1:1 themes. Cross-cycle **rating trends** and **cycle compare** call out movers, repeat thin dossiers, and theme drift. The people table adds competency sparklines and prior-cycle overall deltas when history exists. **Director briefing** opens a printable cycle pack for the skip-level conversation.
+**How it works:** Distribution, evidence scatter, competency averages, promo readiness, writing-time buckets, themes, cross-cycle trends, and a printable director briefing.


-### Sprint pulse
+### Sprint pulse — dark Magenta
-**Intent:** Review the last sprint (or any date window) for coaching, not final ratings.
+**Intent:** Coaching view for a date window, not final ratings.
-**How it works:** Pick last 7 / 14 / 30 days or a custom range. See per-person achievement volume, Jira / Bitbucket throughput, feedback themes, open concerns, and evidence freshness (in-window vs older dossier items, plus stale-only cites on manager drafts).
+**How it works:** Last 7 / 14 / 30 days or custom range — throughput, themes, concerns, evidence freshness.

-### Backfill
+### Backfill — light Citrus
-**Intent:** Unblock writing when dossiers are still empty after you first adopt the tool.
+**Intent:** Unblock writing when dossiers are still thin after first adopt.
-**How it works:** Lists people below the thin-dossier threshold (few achievements / feedback / docs / goals). Walk a short wizard to add starter evidence, or use MCP / integrations for bulk load. The goal is a usable citation pool, not perfect history on day one.
+**How it works:** Wizard for starter evidence, or MCP / integrations for bulk load.

-### AI Chat
+### AI Chat — dark Ocean
-**Intent:** Ask grounded questions over the workspace or a single dossier without inventing evidence.
+**Intent:** Grounded questions over the workspace or a dossier without inventing evidence.
-**How it works:** Chat is scoped to workspace or person context, cites allowlisted ids from real dossier rows, and respects private-tier egress settings. It is for synthesis and retrieval, not a substitute for the writing desk finalize path.
+**How it works:** Scoped chat with allowlisted cites; respects private-tier egress settings.

-### Settings
+### Settings — dark Coral
-**Intent:** Configure providers, privacy gates, appearance, and vault maintenance in one place.
+**Intent:** Providers, privacy gates, appearance, and vault maintenance.
-**How it works:** Set AI provider and models (Anthropic, OpenAI, Cursor gateway, Ollama), toggle egress for private notes / meetings / document extracts, manage Jira / Bitbucket / GitHub / Linear credentials, run encrypted backup / restore, verify the activity log, and choose appearance (system / dark / light plus Teal, Ocean, Forest, or Slate accent). A sticky **On this page** nav jumps between sections. **Danger zone** permanently erases the local vault so you can create a new empty or demo workspace.
+**How it works:** AI providers, egress toggles, Jira / Bitbucket / GitHub / Linear, backup / restore, activity verify, and the eight-accent appearance picker. **Danger zone** erases the vault.

@@ -212,21 +239,17 @@ Regenerate with `pnpm screenshots` (UI + API running; default password `workbenc
- **Encrypted vault** (AES-256-GCM) for DB and dossier files on lock
- **People / roles / cycles** with self and peer JSON bundles
- **Writing desk**: competencies, evidence links, citation freeze, HTML subject packets
-- **Consistency** and **team performance** views before you share (including cross-cycle trends and cycle compare)
-- **Director / upward packs**: briefing HTML, calib room pack, promo committee export, home attention tray, skip-level talking points, encrypted read-only bundle
-- **Sprint pulse** for date-window coaching and evidence freshness
-- **Person timeline** on each dossier
-- **Bias / faithfulness lint** (advisory) on drafts
-- **Promotions** against next-role expectations
-- **Backfill** wizard plus MCP / Jira / Bitbucket paths for thin dossiers
+- **Consistency** and **team performance** views before you share
+- **Director / upward packs**: briefing HTML, calib room pack, promo committee export, skip-level talking points
+- **Sprint pulse** for date-window coaching
+- **Eight accents × dark/light** appearance system (Coral, Amber, Magenta, Citrus plus Teal, Ocean, Forest, Slate)
- **AI**: digests, section draft, peer synthesize, chat, with citation allowlist
-- **Desktop** packaging (Tauri); installers via Actions **Run workflow** (not on every merge)
-- **Dark / light** theme preference plus accent colors
+- **Desktop** packaging (Tauri); installers via Actions **Run workflow**
- **Delete / recreate workspace** from Unlock or Settings
## Docs
-Product and architecture live under [`/docs`](./docs). Start with [`docs/PRODUCT_BRIEF.md`](./docs/PRODUCT_BRIEF.md). Core loop evaluation: [`docs/CORE_LOOP_EVAL.md`](./docs/CORE_LOOP_EVAL.md). Cursor cloud notes: [`AGENTS.md`](./AGENTS.md).
+Product and architecture live under [`/docs`](./docs). Start with [`docs/PRODUCT_BRIEF.md`](./docs/PRODUCT_BRIEF.md). Core loop evaluation: [`docs/CORE_LOOP_EVAL.md`](./docs/CORE_LOOP_EVAL.md). Theme matrix: [`docs/screenshots/THEMES.md`](./docs/screenshots/THEMES.md). Cursor cloud notes: [`AGENTS.md`](./AGENTS.md).
## License & community
diff --git a/apps/ui/src/lib/theme.ts b/apps/ui/src/lib/theme.ts
index 003cc30..16e9f99 100644
--- a/apps/ui/src/lib/theme.ts
+++ b/apps/ui/src/lib/theme.ts
@@ -1,6 +1,14 @@
export type ColorMode = "dark" | "light" | "system";
export type ResolvedTheme = "dark" | "light";
-export type Accent = "teal" | "ocean" | "forest" | "slate";
+export type Accent =
+ | "teal"
+ | "ocean"
+ | "forest"
+ | "slate"
+ | "coral"
+ | "amber"
+ | "magenta"
+ | "citrus";
/** @deprecated Prefer ColorMode; kept for callers that only mean resolved dark/light. */
export type Theme = ResolvedTheme;
@@ -14,13 +22,19 @@ export const DEFAULT_COLOR_MODE: ColorMode = "system";
export const DEFAULT_ACCENT: Accent = "teal";
export const DEFAULT_THEME: ResolvedTheme = "dark";
-export const ACCENTS: Array<{ id: Accent; label: string }> = [
- { id: "teal", label: "Teal" },
- { id: "ocean", label: "Ocean" },
- { id: "forest", label: "Forest" },
- { id: "slate", label: "Slate" },
+export const ACCENTS: Array<{ id: Accent; label: string; swatch: string }> = [
+ { id: "teal", label: "Teal", swatch: "#14b8a6" },
+ { id: "ocean", label: "Ocean", swatch: "#38bdf8" },
+ { id: "forest", label: "Forest", swatch: "#4ade80" },
+ { id: "slate", label: "Slate", swatch: "#94a3b8" },
+ { id: "coral", label: "Coral", swatch: "#ff6b4a" },
+ { id: "amber", label: "Amber", swatch: "#f59e0b" },
+ { id: "magenta", label: "Magenta", swatch: "#ec4899" },
+ { id: "citrus", label: "Citrus", swatch: "#84cc16" },
];
+const ACCENT_IDS = new Set(ACCENTS.map((a) => a.id));
+
export function isColorMode(value: unknown): value is ColorMode {
return value === "dark" || value === "light" || value === "system";
}
@@ -31,7 +45,7 @@ export function isTheme(value: unknown): value is ColorMode {
}
export function isAccent(value: unknown): value is Accent {
- return value === "teal" || value === "ocean" || value === "forest" || value === "slate";
+ return typeof value === "string" && ACCENT_IDS.has(value as Accent);
}
export function systemPrefersDark(): boolean {
diff --git a/apps/ui/src/pages/HomePage.tsx b/apps/ui/src/pages/HomePage.tsx
index d6a61c3..5d3d0ac 100644
--- a/apps/ui/src/pages/HomePage.tsx
+++ b/apps/ui/src/pages/HomePage.tsx
@@ -49,7 +49,11 @@ export function HomePage() {
useEffect(() => {
api("/api/cycles").then((c) => {
setCycles(c);
- if (c[0]) setCycleId(c[0].id);
+ const preferred =
+ c.find((x) => x.status === "manager_open") ||
+ c.find((x) => x.status !== "closed") ||
+ c[0];
+ if (preferred) setCycleId(preferred.id);
});
api("/api/workspace/status").then((s) => {
setThinEvidenceCount(s.thinEvidenceCount ?? 0);
diff --git a/apps/ui/src/pages/SettingsPage.tsx b/apps/ui/src/pages/SettingsPage.tsx
index 05f8400..75eb8ad 100644
--- a/apps/ui/src/pages/SettingsPage.tsx
+++ b/apps/ui/src/pages/SettingsPage.tsx
@@ -134,7 +134,7 @@ export function SettingsPage({
id="settings-appearance"
title="Appearance"
when="Change color mode or accent whenever the UI feels too bright, too dark, or hard to scan."
- how={`Pick a mode and accent below. Preferences stay in this browser; System follows your OS (${resolved} right now).`}
+ how={`Pick a mode and accent below. Eight accents (Teal, Ocean, Forest, Slate, Coral, Amber, Magenta, Citrus) × dark/light. Preferences stay in this browser; System follows your OS (${resolved} right now).`}
>
@@ -160,19 +160,7 @@ export function SettingsPage({
aria-checked={accent === item.id}
onClick={() => setAccent(item.id as Accent)}
>
-
+
{item.label}
))}
diff --git a/apps/ui/src/styles.css b/apps/ui/src/styles.css
index 063bb0d..fb9ff07 100644
--- a/apps/ui/src/styles.css
+++ b/apps/ui/src/styles.css
@@ -158,6 +158,82 @@
--bg-glow-b: rgba(100, 116, 139, 0.04);
}
+[data-theme="dark"][data-accent="coral"] {
+ --brand: #ff6b4a;
+ --brand-strong: #ff8f75;
+ --brand-tint: rgba(255, 107, 74, 0.16);
+ --brand-ring: rgba(255, 107, 74, 0.36);
+ --accent: #ffb4a2;
+ --bg-glow-a: rgba(255, 107, 74, 0.12);
+ --bg-glow-b: rgba(251, 113, 133, 0.07);
+}
+[data-theme="light"][data-accent="coral"] {
+ --brand: #e11d48;
+ --brand-strong: #be123c;
+ --brand-tint: #ffe4e6;
+ --brand-ring: rgba(225, 29, 72, 0.28);
+ --accent: #f43f5e;
+ --bg-glow-a: rgba(225, 29, 72, 0.07);
+ --bg-glow-b: rgba(251, 113, 133, 0.05);
+}
+
+[data-theme="dark"][data-accent="amber"] {
+ --brand: #f59e0b;
+ --brand-strong: #fbbf24;
+ --brand-tint: rgba(245, 158, 11, 0.16);
+ --brand-ring: rgba(245, 158, 11, 0.36);
+ --accent: #fcd34d;
+ --bg-glow-a: rgba(245, 158, 11, 0.12);
+ --bg-glow-b: rgba(251, 191, 36, 0.07);
+}
+[data-theme="light"][data-accent="amber"] {
+ --brand: #c2410c;
+ --brand-strong: #9a3412;
+ --brand-tint: #ffedd5;
+ --brand-ring: rgba(194, 65, 12, 0.28);
+ --accent: #ea580c;
+ --bg-glow-a: rgba(194, 65, 12, 0.07);
+ --bg-glow-b: rgba(234, 88, 12, 0.05);
+}
+
+[data-theme="dark"][data-accent="magenta"] {
+ --brand: #ec4899;
+ --brand-strong: #f472b6;
+ --brand-tint: rgba(236, 72, 153, 0.16);
+ --brand-ring: rgba(236, 72, 153, 0.36);
+ --accent: #f9a8d4;
+ --bg-glow-a: rgba(236, 72, 153, 0.12);
+ --bg-glow-b: rgba(217, 70, 239, 0.07);
+}
+[data-theme="light"][data-accent="magenta"] {
+ --brand: #db2777;
+ --brand-strong: #be185d;
+ --brand-tint: #fce7f3;
+ --brand-ring: rgba(219, 39, 119, 0.28);
+ --accent: #ec4899;
+ --bg-glow-a: rgba(219, 39, 119, 0.07);
+ --bg-glow-b: rgba(236, 72, 153, 0.05);
+}
+
+[data-theme="dark"][data-accent="citrus"] {
+ --brand: #84cc16;
+ --brand-strong: #a3e635;
+ --brand-tint: rgba(132, 204, 22, 0.16);
+ --brand-ring: rgba(132, 204, 22, 0.36);
+ --accent: #d9f99d;
+ --bg-glow-a: rgba(132, 204, 22, 0.12);
+ --bg-glow-b: rgba(250, 204, 21, 0.06);
+}
+[data-theme="light"][data-accent="citrus"] {
+ --brand: #65a30d;
+ --brand-strong: #4d7c0f;
+ --brand-tint: #ecfccb;
+ --brand-ring: rgba(101, 163, 13, 0.28);
+ --accent: #84cc16;
+ --bg-glow-a: rgba(101, 163, 13, 0.07);
+ --bg-glow-b: rgba(132, 204, 22, 0.05);
+}
+
/* Semantic colors (theme-aware, accent-independent) */
:root,
[data-theme="dark"] {
@@ -1259,13 +1335,13 @@ pre { margin: 0; white-space: pre-wrap; word-break: break-word; }
align-items: center;
gap: var(--space-2);
min-height: var(--touch-min);
- padding: 0.4rem 0.75rem;
+ padding: 0.35rem 0.65rem;
border-radius: 999px;
border: 1px solid var(--line-strong);
background: var(--panel);
color: var(--ink-soft);
cursor: pointer;
- font-size: var(--text-sm);
+ font-size: var(--text-xs);
font-weight: 600;
}
.accent-swatch.on {
diff --git a/docs/screenshots/01-unlock.png b/docs/screenshots/01-unlock.png
index d35915b..362e84e 100644
Binary files a/docs/screenshots/01-unlock.png and b/docs/screenshots/01-unlock.png differ
diff --git a/docs/screenshots/02-home.png b/docs/screenshots/02-home.png
index a65bb86..060dc7b 100644
Binary files a/docs/screenshots/02-home.png and b/docs/screenshots/02-home.png differ
diff --git a/docs/screenshots/03-team.png b/docs/screenshots/03-team.png
index d5c4916..85102b7 100644
Binary files a/docs/screenshots/03-team.png and b/docs/screenshots/03-team.png differ
diff --git a/docs/screenshots/04-person.png b/docs/screenshots/04-person.png
index 402b439..49a3492 100644
Binary files a/docs/screenshots/04-person.png and b/docs/screenshots/04-person.png differ
diff --git a/docs/screenshots/05-roles.png b/docs/screenshots/05-roles.png
index 8c94921..b8d63de 100644
Binary files a/docs/screenshots/05-roles.png and b/docs/screenshots/05-roles.png differ
diff --git a/docs/screenshots/06-cycles.png b/docs/screenshots/06-cycles.png
index ac39781..31bdd7a 100644
Binary files a/docs/screenshots/06-cycles.png and b/docs/screenshots/06-cycles.png differ
diff --git a/docs/screenshots/07-writing-desk.png b/docs/screenshots/07-writing-desk.png
index d42f760..92cc3eb 100644
Binary files a/docs/screenshots/07-writing-desk.png and b/docs/screenshots/07-writing-desk.png differ
diff --git a/docs/screenshots/08-promotions.png b/docs/screenshots/08-promotions.png
index 36ec5a6..359842f 100644
Binary files a/docs/screenshots/08-promotions.png and b/docs/screenshots/08-promotions.png differ
diff --git a/docs/screenshots/09-promotion-detail.png b/docs/screenshots/09-promotion-detail.png
index 31a4b01..4a3f50c 100644
Binary files a/docs/screenshots/09-promotion-detail.png and b/docs/screenshots/09-promotion-detail.png differ
diff --git a/docs/screenshots/10-consistency.png b/docs/screenshots/10-consistency.png
index 27fa4c8..5f5feec 100644
Binary files a/docs/screenshots/10-consistency.png and b/docs/screenshots/10-consistency.png differ
diff --git a/docs/screenshots/11-team-performance.png b/docs/screenshots/11-team-performance.png
index 1325293..1ed68ed 100644
Binary files a/docs/screenshots/11-team-performance.png and b/docs/screenshots/11-team-performance.png differ
diff --git a/docs/screenshots/12-backfill.png b/docs/screenshots/12-backfill.png
index 847c3f2..e40770a 100644
Binary files a/docs/screenshots/12-backfill.png and b/docs/screenshots/12-backfill.png differ
diff --git a/docs/screenshots/13-chat.png b/docs/screenshots/13-chat.png
index f1810f7..1b46e7c 100644
Binary files a/docs/screenshots/13-chat.png and b/docs/screenshots/13-chat.png differ
diff --git a/docs/screenshots/14-settings.png b/docs/screenshots/14-settings.png
index 9ac06af..1233d06 100644
Binary files a/docs/screenshots/14-settings.png and b/docs/screenshots/14-settings.png differ
diff --git a/docs/screenshots/15-director-attention.png b/docs/screenshots/15-director-attention.png
index 1a94a5c..dab0881 100644
Binary files a/docs/screenshots/15-director-attention.png and b/docs/screenshots/15-director-attention.png differ
diff --git a/docs/screenshots/16-writing-desk-director.png b/docs/screenshots/16-writing-desk-director.png
index d42f760..f928353 100644
Binary files a/docs/screenshots/16-writing-desk-director.png and b/docs/screenshots/16-writing-desk-director.png differ
diff --git a/docs/screenshots/17-consistency-director-packs.png b/docs/screenshots/17-consistency-director-packs.png
index 27fa4c8..5f5feec 100644
Binary files a/docs/screenshots/17-consistency-director-packs.png and b/docs/screenshots/17-consistency-director-packs.png differ
diff --git a/docs/screenshots/18-team-director-briefing.png b/docs/screenshots/18-team-director-briefing.png
index 1325293..c085698 100644
Binary files a/docs/screenshots/18-team-director-briefing.png and b/docs/screenshots/18-team-director-briefing.png differ
diff --git a/docs/screenshots/19-promo-committee.png b/docs/screenshots/19-promo-committee.png
index 31a4b01..4a3f50c 100644
Binary files a/docs/screenshots/19-promo-committee.png and b/docs/screenshots/19-promo-committee.png differ
diff --git a/docs/screenshots/20-sprint-pulse.png b/docs/screenshots/20-sprint-pulse.png
index 6f591cf..df27a82 100644
Binary files a/docs/screenshots/20-sprint-pulse.png and b/docs/screenshots/20-sprint-pulse.png differ
diff --git a/docs/screenshots/README.md b/docs/screenshots/README.md
index 240e614..8b7ccef 100644
--- a/docs/screenshots/README.md
+++ b/docs/screenshots/README.md
@@ -1,39 +1,45 @@
# Screenshot gallery
-PNG captures used in the root [README](../../README.md).
+PNG captures used in the root [README](../../README.md) and the [theme matrix](./THEMES.md).
-Regenerate (API + UI must be running; unlock password defaults to `workbench`):
+Regenerate (API + UI must be running; demo unlock password `workbench`):
```bash
pnpm screenshots
# or: UI_URL=http://localhost:5173 PRM_PASSWORD=workbench pnpm screenshots
```
-The script **erases and re-seeds** the local demo workspace so shots stay consistent. Requires system Chrome (`google-chrome-stable`) and root `puppeteer-core`.
-
-Numbering matches the README Screens section (`01` unlock through `14` settings), plus director close-ups and sprint pulse:
-
-| File | Surface |
-| --- | --- |
-| `01-unlock.png` | Create workbench — empty vs demo |
-| `02-home.png` | Command center |
-| `03-team.png` | Team roster |
-| `04-person.png` | Person dossier |
-| `05-roles.png` | Roles |
-| `06-cycles.png` | Cycles |
-| `07-writing-desk.png` | Writing desk |
-| `08-promotions.png` | Promotions list |
-| `09-promotion-detail.png` | Promotion packet |
-| `10-consistency.png` | Consistency |
-| `11-team-performance.png` | Team performance |
-| `12-backfill.png` | Backfill |
-| `13-chat.png` | AI Chat |
-| `14-settings.png` | Settings (sticky section nav + appearance) |
-| `15-director-attention.png` | Home — Needs director attention |
-| `16-writing-desk-director.png` | Writing desk — Skip-level / Director card |
-| `17-consistency-director-packs.png` | Consistency — calib / briefing / bundle |
-| `18-team-director-briefing.png` | Team performance — Director briefing |
-| `19-promo-committee.png` | Promotion — Promo committee export |
-| `20-sprint-pulse.png` | Sprint pulse |
-
-`01-unlock` is the empty-vs-demo create screen. Sticky **On this page** nav appears on Home, Person, Writing desk, Team performance, Consistency, Cycles, Roles, Sprint pulse, Promotion detail, and Settings.
+The script **erases and re-seeds** the local demo workspace, then captures:
+
+1. **Theme matrix** — every accent × dark/light × main page under `themes/{mode}-{accent}/`
+2. **README tour** — numbered shots at this folder root (accents rotate through the tour)
+3. **Home strip** — `themes/{mode}-{accent}-home.png` for the Appearance section
+
+Requires system Chrome (`google-chrome-stable`) and root `puppeteer-core`.
+
+## README tour files
+
+| File | Surface | Theme in tour |
+| --- | --- | --- |
+| `01-unlock.png` | Create workbench | dark Coral |
+| `02-home.png` | Command center | dark Teal |
+| `03-team.png` | Team roster | dark Coral |
+| `04-person.png` | Person dossier | dark Magenta |
+| `05-roles.png` | Roles | light Ocean |
+| `06-cycles.png` | Cycles | dark Citrus |
+| `07-writing-desk.png` | Writing desk | dark Coral |
+| `08-promotions.png` | Promotions list | light Magenta |
+| `09-promotion-detail.png` | Promotion packet | dark Ocean |
+| `10-consistency.png` | Consistency | dark Forest |
+| `11-team-performance.png` | Team performance | light Coral |
+| `12-backfill.png` | Backfill | light Citrus |
+| `13-chat.png` | AI Chat | dark Ocean |
+| `14-settings.png` | Settings (8 accents) | dark Coral |
+| `15-director-attention.png` | Home — director attention | dark Amber |
+| `16-writing-desk-director.png` | Writing desk — skip-level | dark Amber |
+| `17-consistency-director-packs.png` | Consistency — calib packs | dark Forest |
+| `18-team-director-briefing.png` | Team performance — briefing | light Amber |
+| `19-promo-committee.png` | Promo committee export | dark Ocean |
+| `20-sprint-pulse.png` | Sprint pulse | dark Magenta |
+
+Accents available in Settings: Teal, Ocean, Forest, Slate, **Coral**, **Amber**, **Magenta**, **Citrus**.
diff --git a/docs/screenshots/THEMES.md b/docs/screenshots/THEMES.md
new file mode 100644
index 0000000..3ec1a6b
--- /dev/null
+++ b/docs/screenshots/THEMES.md
@@ -0,0 +1,43 @@
+# Theme matrix
+
+Every main page captured in **8 accents × dark/light** (16 combinations).
+
+Accents: Teal, Ocean, Forest, Slate, Coral, Amber, Magenta, Citrus.
+
+Regenerate with `pnpm screenshots` (UI + API running).
+
+## Home strip (all combinations)
+
+### Dark
+
+| Accent | Shot |
+|--------|------|
+| Teal |  |
+| Ocean |  |
+| Forest |  |
+| Slate |  |
+| Coral |  |
+| Amber |  |
+| Magenta |  |
+| Citrus |  |
+
+### Light
+
+| Accent | Shot |
+|--------|------|
+| Teal |  |
+| Ocean |  |
+| Forest |  |
+| Slate |  |
+| Coral |  |
+| Amber |  |
+| Magenta |  |
+| Citrus |  |
+
+## Full page folders
+
+Each folder under `themes/{mode}-{accent}/` contains:
+
+`home`, `team`, `person`, `roles`, `cycles`, `writing-desk`, `promotions`, `promotion-detail`, `consistency`, `team-performance`, `sprint-pulse`, `backfill`, `chat`, `settings`
+
+Example: [dark Coral writing desk](./themes/dark-coral/writing-desk.png) · [light Magenta settings](./themes/light-magenta/settings.png) · [dark Citrus sprint pulse](./themes/dark-citrus/sprint-pulse.png)
diff --git a/docs/screenshots/themes/dark-amber-home.png b/docs/screenshots/themes/dark-amber-home.png
new file mode 100644
index 0000000..5485ad2
Binary files /dev/null and b/docs/screenshots/themes/dark-amber-home.png differ
diff --git a/docs/screenshots/themes/dark-amber/backfill.png b/docs/screenshots/themes/dark-amber/backfill.png
new file mode 100644
index 0000000..7780353
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/backfill.png differ
diff --git a/docs/screenshots/themes/dark-amber/chat.png b/docs/screenshots/themes/dark-amber/chat.png
new file mode 100644
index 0000000..55e138a
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/chat.png differ
diff --git a/docs/screenshots/themes/dark-amber/consistency.png b/docs/screenshots/themes/dark-amber/consistency.png
new file mode 100644
index 0000000..2fb4e63
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/consistency.png differ
diff --git a/docs/screenshots/themes/dark-amber/cycles.png b/docs/screenshots/themes/dark-amber/cycles.png
new file mode 100644
index 0000000..ae8dbc9
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/cycles.png differ
diff --git a/docs/screenshots/themes/dark-amber/home.png b/docs/screenshots/themes/dark-amber/home.png
new file mode 100644
index 0000000..5485ad2
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/home.png differ
diff --git a/docs/screenshots/themes/dark-amber/person.png b/docs/screenshots/themes/dark-amber/person.png
new file mode 100644
index 0000000..e3f76fa
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/person.png differ
diff --git a/docs/screenshots/themes/dark-amber/promotion-detail.png b/docs/screenshots/themes/dark-amber/promotion-detail.png
new file mode 100644
index 0000000..0c7bfb3
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-amber/promotions.png b/docs/screenshots/themes/dark-amber/promotions.png
new file mode 100644
index 0000000..12ef8e1
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/promotions.png differ
diff --git a/docs/screenshots/themes/dark-amber/roles.png b/docs/screenshots/themes/dark-amber/roles.png
new file mode 100644
index 0000000..91592f8
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/roles.png differ
diff --git a/docs/screenshots/themes/dark-amber/settings.png b/docs/screenshots/themes/dark-amber/settings.png
new file mode 100644
index 0000000..3d21fd1
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/settings.png differ
diff --git a/docs/screenshots/themes/dark-amber/sprint-pulse.png b/docs/screenshots/themes/dark-amber/sprint-pulse.png
new file mode 100644
index 0000000..eb6ee54
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-amber/team-performance.png b/docs/screenshots/themes/dark-amber/team-performance.png
new file mode 100644
index 0000000..f38e458
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-amber/team.png b/docs/screenshots/themes/dark-amber/team.png
new file mode 100644
index 0000000..c4e8955
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/team.png differ
diff --git a/docs/screenshots/themes/dark-amber/writing-desk.png b/docs/screenshots/themes/dark-amber/writing-desk.png
new file mode 100644
index 0000000..f928353
Binary files /dev/null and b/docs/screenshots/themes/dark-amber/writing-desk.png differ
diff --git a/docs/screenshots/themes/dark-citrus-home.png b/docs/screenshots/themes/dark-citrus-home.png
new file mode 100644
index 0000000..6e2d9dc
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus-home.png differ
diff --git a/docs/screenshots/themes/dark-citrus/backfill.png b/docs/screenshots/themes/dark-citrus/backfill.png
new file mode 100644
index 0000000..97ce983
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/backfill.png differ
diff --git a/docs/screenshots/themes/dark-citrus/chat.png b/docs/screenshots/themes/dark-citrus/chat.png
new file mode 100644
index 0000000..2b0ca28
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/chat.png differ
diff --git a/docs/screenshots/themes/dark-citrus/consistency.png b/docs/screenshots/themes/dark-citrus/consistency.png
new file mode 100644
index 0000000..5b1e618
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/consistency.png differ
diff --git a/docs/screenshots/themes/dark-citrus/cycles.png b/docs/screenshots/themes/dark-citrus/cycles.png
new file mode 100644
index 0000000..31bdd7a
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/cycles.png differ
diff --git a/docs/screenshots/themes/dark-citrus/home.png b/docs/screenshots/themes/dark-citrus/home.png
new file mode 100644
index 0000000..6e2d9dc
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/home.png differ
diff --git a/docs/screenshots/themes/dark-citrus/person.png b/docs/screenshots/themes/dark-citrus/person.png
new file mode 100644
index 0000000..9cbb5bf
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/person.png differ
diff --git a/docs/screenshots/themes/dark-citrus/promotion-detail.png b/docs/screenshots/themes/dark-citrus/promotion-detail.png
new file mode 100644
index 0000000..071f27a
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-citrus/promotions.png b/docs/screenshots/themes/dark-citrus/promotions.png
new file mode 100644
index 0000000..b2d494c
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/promotions.png differ
diff --git a/docs/screenshots/themes/dark-citrus/roles.png b/docs/screenshots/themes/dark-citrus/roles.png
new file mode 100644
index 0000000..815e751
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/roles.png differ
diff --git a/docs/screenshots/themes/dark-citrus/settings.png b/docs/screenshots/themes/dark-citrus/settings.png
new file mode 100644
index 0000000..b6f4e30
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/settings.png differ
diff --git a/docs/screenshots/themes/dark-citrus/sprint-pulse.png b/docs/screenshots/themes/dark-citrus/sprint-pulse.png
new file mode 100644
index 0000000..4e5e8e3
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-citrus/team-performance.png b/docs/screenshots/themes/dark-citrus/team-performance.png
new file mode 100644
index 0000000..d3473c4
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-citrus/team.png b/docs/screenshots/themes/dark-citrus/team.png
new file mode 100644
index 0000000..36c2757
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/team.png differ
diff --git a/docs/screenshots/themes/dark-citrus/writing-desk.png b/docs/screenshots/themes/dark-citrus/writing-desk.png
new file mode 100644
index 0000000..9a8085a
Binary files /dev/null and b/docs/screenshots/themes/dark-citrus/writing-desk.png differ
diff --git a/docs/screenshots/themes/dark-coral-home.png b/docs/screenshots/themes/dark-coral-home.png
new file mode 100644
index 0000000..d5302c3
Binary files /dev/null and b/docs/screenshots/themes/dark-coral-home.png differ
diff --git a/docs/screenshots/themes/dark-coral/backfill.png b/docs/screenshots/themes/dark-coral/backfill.png
new file mode 100644
index 0000000..f74c3d6
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/backfill.png differ
diff --git a/docs/screenshots/themes/dark-coral/chat.png b/docs/screenshots/themes/dark-coral/chat.png
new file mode 100644
index 0000000..aa91df7
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/chat.png differ
diff --git a/docs/screenshots/themes/dark-coral/consistency.png b/docs/screenshots/themes/dark-coral/consistency.png
new file mode 100644
index 0000000..cb85c78
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/consistency.png differ
diff --git a/docs/screenshots/themes/dark-coral/cycles.png b/docs/screenshots/themes/dark-coral/cycles.png
new file mode 100644
index 0000000..6755f9c
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/cycles.png differ
diff --git a/docs/screenshots/themes/dark-coral/home.png b/docs/screenshots/themes/dark-coral/home.png
new file mode 100644
index 0000000..d5302c3
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/home.png differ
diff --git a/docs/screenshots/themes/dark-coral/person.png b/docs/screenshots/themes/dark-coral/person.png
new file mode 100644
index 0000000..9ff928e
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/person.png differ
diff --git a/docs/screenshots/themes/dark-coral/promotion-detail.png b/docs/screenshots/themes/dark-coral/promotion-detail.png
new file mode 100644
index 0000000..93f03a2
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-coral/promotions.png b/docs/screenshots/themes/dark-coral/promotions.png
new file mode 100644
index 0000000..9e8e512
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/promotions.png differ
diff --git a/docs/screenshots/themes/dark-coral/roles.png b/docs/screenshots/themes/dark-coral/roles.png
new file mode 100644
index 0000000..b185f0b
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/roles.png differ
diff --git a/docs/screenshots/themes/dark-coral/settings.png b/docs/screenshots/themes/dark-coral/settings.png
new file mode 100644
index 0000000..1233d06
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/settings.png differ
diff --git a/docs/screenshots/themes/dark-coral/sprint-pulse.png b/docs/screenshots/themes/dark-coral/sprint-pulse.png
new file mode 100644
index 0000000..1c8e656
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-coral/team-performance.png b/docs/screenshots/themes/dark-coral/team-performance.png
new file mode 100644
index 0000000..61ccdec
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-coral/team.png b/docs/screenshots/themes/dark-coral/team.png
new file mode 100644
index 0000000..85102b7
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/team.png differ
diff --git a/docs/screenshots/themes/dark-coral/writing-desk.png b/docs/screenshots/themes/dark-coral/writing-desk.png
new file mode 100644
index 0000000..92cc3eb
Binary files /dev/null and b/docs/screenshots/themes/dark-coral/writing-desk.png differ
diff --git a/docs/screenshots/themes/dark-forest-home.png b/docs/screenshots/themes/dark-forest-home.png
new file mode 100644
index 0000000..2a36db1
Binary files /dev/null and b/docs/screenshots/themes/dark-forest-home.png differ
diff --git a/docs/screenshots/themes/dark-forest/backfill.png b/docs/screenshots/themes/dark-forest/backfill.png
new file mode 100644
index 0000000..e5468b8
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/backfill.png differ
diff --git a/docs/screenshots/themes/dark-forest/chat.png b/docs/screenshots/themes/dark-forest/chat.png
new file mode 100644
index 0000000..34d4004
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/chat.png differ
diff --git a/docs/screenshots/themes/dark-forest/consistency.png b/docs/screenshots/themes/dark-forest/consistency.png
new file mode 100644
index 0000000..5f5feec
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/consistency.png differ
diff --git a/docs/screenshots/themes/dark-forest/cycles.png b/docs/screenshots/themes/dark-forest/cycles.png
new file mode 100644
index 0000000..4e7b825
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/cycles.png differ
diff --git a/docs/screenshots/themes/dark-forest/home.png b/docs/screenshots/themes/dark-forest/home.png
new file mode 100644
index 0000000..2a36db1
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/home.png differ
diff --git a/docs/screenshots/themes/dark-forest/person.png b/docs/screenshots/themes/dark-forest/person.png
new file mode 100644
index 0000000..314cb26
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/person.png differ
diff --git a/docs/screenshots/themes/dark-forest/promotion-detail.png b/docs/screenshots/themes/dark-forest/promotion-detail.png
new file mode 100644
index 0000000..ea2d171
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-forest/promotions.png b/docs/screenshots/themes/dark-forest/promotions.png
new file mode 100644
index 0000000..26db2b2
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/promotions.png differ
diff --git a/docs/screenshots/themes/dark-forest/roles.png b/docs/screenshots/themes/dark-forest/roles.png
new file mode 100644
index 0000000..c6cabf1
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/roles.png differ
diff --git a/docs/screenshots/themes/dark-forest/settings.png b/docs/screenshots/themes/dark-forest/settings.png
new file mode 100644
index 0000000..d24b43f
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/settings.png differ
diff --git a/docs/screenshots/themes/dark-forest/sprint-pulse.png b/docs/screenshots/themes/dark-forest/sprint-pulse.png
new file mode 100644
index 0000000..03aa64d
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-forest/team-performance.png b/docs/screenshots/themes/dark-forest/team-performance.png
new file mode 100644
index 0000000..79a5bae
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-forest/team.png b/docs/screenshots/themes/dark-forest/team.png
new file mode 100644
index 0000000..731404c
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/team.png differ
diff --git a/docs/screenshots/themes/dark-forest/writing-desk.png b/docs/screenshots/themes/dark-forest/writing-desk.png
new file mode 100644
index 0000000..73c5e82
Binary files /dev/null and b/docs/screenshots/themes/dark-forest/writing-desk.png differ
diff --git a/docs/screenshots/themes/dark-magenta-home.png b/docs/screenshots/themes/dark-magenta-home.png
new file mode 100644
index 0000000..f51f338
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta-home.png differ
diff --git a/docs/screenshots/themes/dark-magenta/backfill.png b/docs/screenshots/themes/dark-magenta/backfill.png
new file mode 100644
index 0000000..21ebcbf
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/backfill.png differ
diff --git a/docs/screenshots/themes/dark-magenta/chat.png b/docs/screenshots/themes/dark-magenta/chat.png
new file mode 100644
index 0000000..97786e1
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/chat.png differ
diff --git a/docs/screenshots/themes/dark-magenta/consistency.png b/docs/screenshots/themes/dark-magenta/consistency.png
new file mode 100644
index 0000000..5468501
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/consistency.png differ
diff --git a/docs/screenshots/themes/dark-magenta/cycles.png b/docs/screenshots/themes/dark-magenta/cycles.png
new file mode 100644
index 0000000..c3a870d
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/cycles.png differ
diff --git a/docs/screenshots/themes/dark-magenta/home.png b/docs/screenshots/themes/dark-magenta/home.png
new file mode 100644
index 0000000..f51f338
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/home.png differ
diff --git a/docs/screenshots/themes/dark-magenta/person.png b/docs/screenshots/themes/dark-magenta/person.png
new file mode 100644
index 0000000..49a3492
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/person.png differ
diff --git a/docs/screenshots/themes/dark-magenta/promotion-detail.png b/docs/screenshots/themes/dark-magenta/promotion-detail.png
new file mode 100644
index 0000000..53e7e80
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-magenta/promotions.png b/docs/screenshots/themes/dark-magenta/promotions.png
new file mode 100644
index 0000000..d372efe
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/promotions.png differ
diff --git a/docs/screenshots/themes/dark-magenta/roles.png b/docs/screenshots/themes/dark-magenta/roles.png
new file mode 100644
index 0000000..5eac5dc
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/roles.png differ
diff --git a/docs/screenshots/themes/dark-magenta/settings.png b/docs/screenshots/themes/dark-magenta/settings.png
new file mode 100644
index 0000000..807bc45
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/settings.png differ
diff --git a/docs/screenshots/themes/dark-magenta/sprint-pulse.png b/docs/screenshots/themes/dark-magenta/sprint-pulse.png
new file mode 100644
index 0000000..df27a82
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-magenta/team-performance.png b/docs/screenshots/themes/dark-magenta/team-performance.png
new file mode 100644
index 0000000..0882f9f
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-magenta/team.png b/docs/screenshots/themes/dark-magenta/team.png
new file mode 100644
index 0000000..f0506cf
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/team.png differ
diff --git a/docs/screenshots/themes/dark-magenta/writing-desk.png b/docs/screenshots/themes/dark-magenta/writing-desk.png
new file mode 100644
index 0000000..9fd63d6
Binary files /dev/null and b/docs/screenshots/themes/dark-magenta/writing-desk.png differ
diff --git a/docs/screenshots/themes/dark-ocean-home.png b/docs/screenshots/themes/dark-ocean-home.png
new file mode 100644
index 0000000..175d706
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean-home.png differ
diff --git a/docs/screenshots/themes/dark-ocean/backfill.png b/docs/screenshots/themes/dark-ocean/backfill.png
new file mode 100644
index 0000000..1f68b92
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/backfill.png differ
diff --git a/docs/screenshots/themes/dark-ocean/chat.png b/docs/screenshots/themes/dark-ocean/chat.png
new file mode 100644
index 0000000..1b46e7c
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/chat.png differ
diff --git a/docs/screenshots/themes/dark-ocean/consistency.png b/docs/screenshots/themes/dark-ocean/consistency.png
new file mode 100644
index 0000000..2cf542c
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/consistency.png differ
diff --git a/docs/screenshots/themes/dark-ocean/cycles.png b/docs/screenshots/themes/dark-ocean/cycles.png
new file mode 100644
index 0000000..13231d0
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/cycles.png differ
diff --git a/docs/screenshots/themes/dark-ocean/home.png b/docs/screenshots/themes/dark-ocean/home.png
new file mode 100644
index 0000000..175d706
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/home.png differ
diff --git a/docs/screenshots/themes/dark-ocean/person.png b/docs/screenshots/themes/dark-ocean/person.png
new file mode 100644
index 0000000..66b0bfe
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/person.png differ
diff --git a/docs/screenshots/themes/dark-ocean/promotion-detail.png b/docs/screenshots/themes/dark-ocean/promotion-detail.png
new file mode 100644
index 0000000..4a3f50c
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-ocean/promotions.png b/docs/screenshots/themes/dark-ocean/promotions.png
new file mode 100644
index 0000000..0346b1d
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/promotions.png differ
diff --git a/docs/screenshots/themes/dark-ocean/roles.png b/docs/screenshots/themes/dark-ocean/roles.png
new file mode 100644
index 0000000..7ebc4ba
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/roles.png differ
diff --git a/docs/screenshots/themes/dark-ocean/settings.png b/docs/screenshots/themes/dark-ocean/settings.png
new file mode 100644
index 0000000..83e8e83
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/settings.png differ
diff --git a/docs/screenshots/themes/dark-ocean/sprint-pulse.png b/docs/screenshots/themes/dark-ocean/sprint-pulse.png
new file mode 100644
index 0000000..61efe8a
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-ocean/team-performance.png b/docs/screenshots/themes/dark-ocean/team-performance.png
new file mode 100644
index 0000000..f3a0773
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-ocean/team.png b/docs/screenshots/themes/dark-ocean/team.png
new file mode 100644
index 0000000..0833846
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/team.png differ
diff --git a/docs/screenshots/themes/dark-ocean/writing-desk.png b/docs/screenshots/themes/dark-ocean/writing-desk.png
new file mode 100644
index 0000000..3f885fb
Binary files /dev/null and b/docs/screenshots/themes/dark-ocean/writing-desk.png differ
diff --git a/docs/screenshots/themes/dark-slate-home.png b/docs/screenshots/themes/dark-slate-home.png
new file mode 100644
index 0000000..2039a1f
Binary files /dev/null and b/docs/screenshots/themes/dark-slate-home.png differ
diff --git a/docs/screenshots/themes/dark-slate/backfill.png b/docs/screenshots/themes/dark-slate/backfill.png
new file mode 100644
index 0000000..1cf0ff5
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/backfill.png differ
diff --git a/docs/screenshots/themes/dark-slate/chat.png b/docs/screenshots/themes/dark-slate/chat.png
new file mode 100644
index 0000000..a215c4f
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/chat.png differ
diff --git a/docs/screenshots/themes/dark-slate/consistency.png b/docs/screenshots/themes/dark-slate/consistency.png
new file mode 100644
index 0000000..9074be3
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/consistency.png differ
diff --git a/docs/screenshots/themes/dark-slate/cycles.png b/docs/screenshots/themes/dark-slate/cycles.png
new file mode 100644
index 0000000..2f0cd7f
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/cycles.png differ
diff --git a/docs/screenshots/themes/dark-slate/home.png b/docs/screenshots/themes/dark-slate/home.png
new file mode 100644
index 0000000..2039a1f
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/home.png differ
diff --git a/docs/screenshots/themes/dark-slate/person.png b/docs/screenshots/themes/dark-slate/person.png
new file mode 100644
index 0000000..b1c30aa
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/person.png differ
diff --git a/docs/screenshots/themes/dark-slate/promotion-detail.png b/docs/screenshots/themes/dark-slate/promotion-detail.png
new file mode 100644
index 0000000..80436b7
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-slate/promotions.png b/docs/screenshots/themes/dark-slate/promotions.png
new file mode 100644
index 0000000..2afed4b
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/promotions.png differ
diff --git a/docs/screenshots/themes/dark-slate/roles.png b/docs/screenshots/themes/dark-slate/roles.png
new file mode 100644
index 0000000..aae03dd
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/roles.png differ
diff --git a/docs/screenshots/themes/dark-slate/settings.png b/docs/screenshots/themes/dark-slate/settings.png
new file mode 100644
index 0000000..55a13ab
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/settings.png differ
diff --git a/docs/screenshots/themes/dark-slate/sprint-pulse.png b/docs/screenshots/themes/dark-slate/sprint-pulse.png
new file mode 100644
index 0000000..feab458
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-slate/team-performance.png b/docs/screenshots/themes/dark-slate/team-performance.png
new file mode 100644
index 0000000..a2f5e25
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-slate/team.png b/docs/screenshots/themes/dark-slate/team.png
new file mode 100644
index 0000000..6c4db9c
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/team.png differ
diff --git a/docs/screenshots/themes/dark-slate/writing-desk.png b/docs/screenshots/themes/dark-slate/writing-desk.png
new file mode 100644
index 0000000..286b71b
Binary files /dev/null and b/docs/screenshots/themes/dark-slate/writing-desk.png differ
diff --git a/docs/screenshots/themes/dark-teal-home.png b/docs/screenshots/themes/dark-teal-home.png
new file mode 100644
index 0000000..060dc7b
Binary files /dev/null and b/docs/screenshots/themes/dark-teal-home.png differ
diff --git a/docs/screenshots/themes/dark-teal/backfill.png b/docs/screenshots/themes/dark-teal/backfill.png
new file mode 100644
index 0000000..f860c07
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/backfill.png differ
diff --git a/docs/screenshots/themes/dark-teal/chat.png b/docs/screenshots/themes/dark-teal/chat.png
new file mode 100644
index 0000000..bf4985d
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/chat.png differ
diff --git a/docs/screenshots/themes/dark-teal/consistency.png b/docs/screenshots/themes/dark-teal/consistency.png
new file mode 100644
index 0000000..7d9c9a8
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/consistency.png differ
diff --git a/docs/screenshots/themes/dark-teal/cycles.png b/docs/screenshots/themes/dark-teal/cycles.png
new file mode 100644
index 0000000..faee0dc
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/cycles.png differ
diff --git a/docs/screenshots/themes/dark-teal/home.png b/docs/screenshots/themes/dark-teal/home.png
new file mode 100644
index 0000000..060dc7b
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/home.png differ
diff --git a/docs/screenshots/themes/dark-teal/person.png b/docs/screenshots/themes/dark-teal/person.png
new file mode 100644
index 0000000..2cdc0cd
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/person.png differ
diff --git a/docs/screenshots/themes/dark-teal/promotion-detail.png b/docs/screenshots/themes/dark-teal/promotion-detail.png
new file mode 100644
index 0000000..1d045ec
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/promotion-detail.png differ
diff --git a/docs/screenshots/themes/dark-teal/promotions.png b/docs/screenshots/themes/dark-teal/promotions.png
new file mode 100644
index 0000000..8fcffca
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/promotions.png differ
diff --git a/docs/screenshots/themes/dark-teal/roles.png b/docs/screenshots/themes/dark-teal/roles.png
new file mode 100644
index 0000000..0383750
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/roles.png differ
diff --git a/docs/screenshots/themes/dark-teal/settings.png b/docs/screenshots/themes/dark-teal/settings.png
new file mode 100644
index 0000000..8db9fde
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/settings.png differ
diff --git a/docs/screenshots/themes/dark-teal/sprint-pulse.png b/docs/screenshots/themes/dark-teal/sprint-pulse.png
new file mode 100644
index 0000000..779f0ca
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/dark-teal/team-performance.png b/docs/screenshots/themes/dark-teal/team-performance.png
new file mode 100644
index 0000000..bee25d4
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/team-performance.png differ
diff --git a/docs/screenshots/themes/dark-teal/team.png b/docs/screenshots/themes/dark-teal/team.png
new file mode 100644
index 0000000..8eb680b
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/team.png differ
diff --git a/docs/screenshots/themes/dark-teal/writing-desk.png b/docs/screenshots/themes/dark-teal/writing-desk.png
new file mode 100644
index 0000000..b48e020
Binary files /dev/null and b/docs/screenshots/themes/dark-teal/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-amber-home.png b/docs/screenshots/themes/light-amber-home.png
new file mode 100644
index 0000000..c6cf0e4
Binary files /dev/null and b/docs/screenshots/themes/light-amber-home.png differ
diff --git a/docs/screenshots/themes/light-amber/backfill.png b/docs/screenshots/themes/light-amber/backfill.png
new file mode 100644
index 0000000..d0d7428
Binary files /dev/null and b/docs/screenshots/themes/light-amber/backfill.png differ
diff --git a/docs/screenshots/themes/light-amber/chat.png b/docs/screenshots/themes/light-amber/chat.png
new file mode 100644
index 0000000..47dfc16
Binary files /dev/null and b/docs/screenshots/themes/light-amber/chat.png differ
diff --git a/docs/screenshots/themes/light-amber/consistency.png b/docs/screenshots/themes/light-amber/consistency.png
new file mode 100644
index 0000000..df31cc3
Binary files /dev/null and b/docs/screenshots/themes/light-amber/consistency.png differ
diff --git a/docs/screenshots/themes/light-amber/cycles.png b/docs/screenshots/themes/light-amber/cycles.png
new file mode 100644
index 0000000..e87ee64
Binary files /dev/null and b/docs/screenshots/themes/light-amber/cycles.png differ
diff --git a/docs/screenshots/themes/light-amber/home.png b/docs/screenshots/themes/light-amber/home.png
new file mode 100644
index 0000000..c6cf0e4
Binary files /dev/null and b/docs/screenshots/themes/light-amber/home.png differ
diff --git a/docs/screenshots/themes/light-amber/person.png b/docs/screenshots/themes/light-amber/person.png
new file mode 100644
index 0000000..e2339be
Binary files /dev/null and b/docs/screenshots/themes/light-amber/person.png differ
diff --git a/docs/screenshots/themes/light-amber/promotion-detail.png b/docs/screenshots/themes/light-amber/promotion-detail.png
new file mode 100644
index 0000000..51974dd
Binary files /dev/null and b/docs/screenshots/themes/light-amber/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-amber/promotions.png b/docs/screenshots/themes/light-amber/promotions.png
new file mode 100644
index 0000000..70b8d7b
Binary files /dev/null and b/docs/screenshots/themes/light-amber/promotions.png differ
diff --git a/docs/screenshots/themes/light-amber/roles.png b/docs/screenshots/themes/light-amber/roles.png
new file mode 100644
index 0000000..e225993
Binary files /dev/null and b/docs/screenshots/themes/light-amber/roles.png differ
diff --git a/docs/screenshots/themes/light-amber/settings.png b/docs/screenshots/themes/light-amber/settings.png
new file mode 100644
index 0000000..6ddccf5
Binary files /dev/null and b/docs/screenshots/themes/light-amber/settings.png differ
diff --git a/docs/screenshots/themes/light-amber/sprint-pulse.png b/docs/screenshots/themes/light-amber/sprint-pulse.png
new file mode 100644
index 0000000..65635ac
Binary files /dev/null and b/docs/screenshots/themes/light-amber/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-amber/team-performance.png b/docs/screenshots/themes/light-amber/team-performance.png
new file mode 100644
index 0000000..c085698
Binary files /dev/null and b/docs/screenshots/themes/light-amber/team-performance.png differ
diff --git a/docs/screenshots/themes/light-amber/team.png b/docs/screenshots/themes/light-amber/team.png
new file mode 100644
index 0000000..5fb76c1
Binary files /dev/null and b/docs/screenshots/themes/light-amber/team.png differ
diff --git a/docs/screenshots/themes/light-amber/writing-desk.png b/docs/screenshots/themes/light-amber/writing-desk.png
new file mode 100644
index 0000000..6b10fe5
Binary files /dev/null and b/docs/screenshots/themes/light-amber/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-citrus-home.png b/docs/screenshots/themes/light-citrus-home.png
new file mode 100644
index 0000000..b477dc5
Binary files /dev/null and b/docs/screenshots/themes/light-citrus-home.png differ
diff --git a/docs/screenshots/themes/light-citrus/backfill.png b/docs/screenshots/themes/light-citrus/backfill.png
new file mode 100644
index 0000000..e40770a
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/backfill.png differ
diff --git a/docs/screenshots/themes/light-citrus/chat.png b/docs/screenshots/themes/light-citrus/chat.png
new file mode 100644
index 0000000..eb9fe53
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/chat.png differ
diff --git a/docs/screenshots/themes/light-citrus/consistency.png b/docs/screenshots/themes/light-citrus/consistency.png
new file mode 100644
index 0000000..43aaad8
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/consistency.png differ
diff --git a/docs/screenshots/themes/light-citrus/cycles.png b/docs/screenshots/themes/light-citrus/cycles.png
new file mode 100644
index 0000000..23ed550
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/cycles.png differ
diff --git a/docs/screenshots/themes/light-citrus/home.png b/docs/screenshots/themes/light-citrus/home.png
new file mode 100644
index 0000000..b477dc5
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/home.png differ
diff --git a/docs/screenshots/themes/light-citrus/person.png b/docs/screenshots/themes/light-citrus/person.png
new file mode 100644
index 0000000..33bda77
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/person.png differ
diff --git a/docs/screenshots/themes/light-citrus/promotion-detail.png b/docs/screenshots/themes/light-citrus/promotion-detail.png
new file mode 100644
index 0000000..83d5f7f
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-citrus/promotions.png b/docs/screenshots/themes/light-citrus/promotions.png
new file mode 100644
index 0000000..8a0e1ed
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/promotions.png differ
diff --git a/docs/screenshots/themes/light-citrus/roles.png b/docs/screenshots/themes/light-citrus/roles.png
new file mode 100644
index 0000000..4194a7f
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/roles.png differ
diff --git a/docs/screenshots/themes/light-citrus/settings.png b/docs/screenshots/themes/light-citrus/settings.png
new file mode 100644
index 0000000..b4ce4e9
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/settings.png differ
diff --git a/docs/screenshots/themes/light-citrus/sprint-pulse.png b/docs/screenshots/themes/light-citrus/sprint-pulse.png
new file mode 100644
index 0000000..715c866
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-citrus/team-performance.png b/docs/screenshots/themes/light-citrus/team-performance.png
new file mode 100644
index 0000000..04e013e
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/team-performance.png differ
diff --git a/docs/screenshots/themes/light-citrus/team.png b/docs/screenshots/themes/light-citrus/team.png
new file mode 100644
index 0000000..a94e300
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/team.png differ
diff --git a/docs/screenshots/themes/light-citrus/writing-desk.png b/docs/screenshots/themes/light-citrus/writing-desk.png
new file mode 100644
index 0000000..7e50553
Binary files /dev/null and b/docs/screenshots/themes/light-citrus/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-coral-home.png b/docs/screenshots/themes/light-coral-home.png
new file mode 100644
index 0000000..3be6f91
Binary files /dev/null and b/docs/screenshots/themes/light-coral-home.png differ
diff --git a/docs/screenshots/themes/light-coral/backfill.png b/docs/screenshots/themes/light-coral/backfill.png
new file mode 100644
index 0000000..5c70704
Binary files /dev/null and b/docs/screenshots/themes/light-coral/backfill.png differ
diff --git a/docs/screenshots/themes/light-coral/chat.png b/docs/screenshots/themes/light-coral/chat.png
new file mode 100644
index 0000000..b898c50
Binary files /dev/null and b/docs/screenshots/themes/light-coral/chat.png differ
diff --git a/docs/screenshots/themes/light-coral/consistency.png b/docs/screenshots/themes/light-coral/consistency.png
new file mode 100644
index 0000000..aef86f1
Binary files /dev/null and b/docs/screenshots/themes/light-coral/consistency.png differ
diff --git a/docs/screenshots/themes/light-coral/cycles.png b/docs/screenshots/themes/light-coral/cycles.png
new file mode 100644
index 0000000..916a7ea
Binary files /dev/null and b/docs/screenshots/themes/light-coral/cycles.png differ
diff --git a/docs/screenshots/themes/light-coral/home.png b/docs/screenshots/themes/light-coral/home.png
new file mode 100644
index 0000000..3be6f91
Binary files /dev/null and b/docs/screenshots/themes/light-coral/home.png differ
diff --git a/docs/screenshots/themes/light-coral/person.png b/docs/screenshots/themes/light-coral/person.png
new file mode 100644
index 0000000..14970a6
Binary files /dev/null and b/docs/screenshots/themes/light-coral/person.png differ
diff --git a/docs/screenshots/themes/light-coral/promotion-detail.png b/docs/screenshots/themes/light-coral/promotion-detail.png
new file mode 100644
index 0000000..19b5b66
Binary files /dev/null and b/docs/screenshots/themes/light-coral/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-coral/promotions.png b/docs/screenshots/themes/light-coral/promotions.png
new file mode 100644
index 0000000..55a57fc
Binary files /dev/null and b/docs/screenshots/themes/light-coral/promotions.png differ
diff --git a/docs/screenshots/themes/light-coral/roles.png b/docs/screenshots/themes/light-coral/roles.png
new file mode 100644
index 0000000..cc5cffd
Binary files /dev/null and b/docs/screenshots/themes/light-coral/roles.png differ
diff --git a/docs/screenshots/themes/light-coral/settings.png b/docs/screenshots/themes/light-coral/settings.png
new file mode 100644
index 0000000..1c53682
Binary files /dev/null and b/docs/screenshots/themes/light-coral/settings.png differ
diff --git a/docs/screenshots/themes/light-coral/sprint-pulse.png b/docs/screenshots/themes/light-coral/sprint-pulse.png
new file mode 100644
index 0000000..73e133f
Binary files /dev/null and b/docs/screenshots/themes/light-coral/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-coral/team-performance.png b/docs/screenshots/themes/light-coral/team-performance.png
new file mode 100644
index 0000000..1ed68ed
Binary files /dev/null and b/docs/screenshots/themes/light-coral/team-performance.png differ
diff --git a/docs/screenshots/themes/light-coral/team.png b/docs/screenshots/themes/light-coral/team.png
new file mode 100644
index 0000000..b310973
Binary files /dev/null and b/docs/screenshots/themes/light-coral/team.png differ
diff --git a/docs/screenshots/themes/light-coral/writing-desk.png b/docs/screenshots/themes/light-coral/writing-desk.png
new file mode 100644
index 0000000..d5ba5ac
Binary files /dev/null and b/docs/screenshots/themes/light-coral/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-forest-home.png b/docs/screenshots/themes/light-forest-home.png
new file mode 100644
index 0000000..d91c53e
Binary files /dev/null and b/docs/screenshots/themes/light-forest-home.png differ
diff --git a/docs/screenshots/themes/light-forest/backfill.png b/docs/screenshots/themes/light-forest/backfill.png
new file mode 100644
index 0000000..4baf2ba
Binary files /dev/null and b/docs/screenshots/themes/light-forest/backfill.png differ
diff --git a/docs/screenshots/themes/light-forest/chat.png b/docs/screenshots/themes/light-forest/chat.png
new file mode 100644
index 0000000..bce4065
Binary files /dev/null and b/docs/screenshots/themes/light-forest/chat.png differ
diff --git a/docs/screenshots/themes/light-forest/consistency.png b/docs/screenshots/themes/light-forest/consistency.png
new file mode 100644
index 0000000..434ff53
Binary files /dev/null and b/docs/screenshots/themes/light-forest/consistency.png differ
diff --git a/docs/screenshots/themes/light-forest/cycles.png b/docs/screenshots/themes/light-forest/cycles.png
new file mode 100644
index 0000000..72c9346
Binary files /dev/null and b/docs/screenshots/themes/light-forest/cycles.png differ
diff --git a/docs/screenshots/themes/light-forest/home.png b/docs/screenshots/themes/light-forest/home.png
new file mode 100644
index 0000000..d91c53e
Binary files /dev/null and b/docs/screenshots/themes/light-forest/home.png differ
diff --git a/docs/screenshots/themes/light-forest/person.png b/docs/screenshots/themes/light-forest/person.png
new file mode 100644
index 0000000..9ca7521
Binary files /dev/null and b/docs/screenshots/themes/light-forest/person.png differ
diff --git a/docs/screenshots/themes/light-forest/promotion-detail.png b/docs/screenshots/themes/light-forest/promotion-detail.png
new file mode 100644
index 0000000..718d5f4
Binary files /dev/null and b/docs/screenshots/themes/light-forest/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-forest/promotions.png b/docs/screenshots/themes/light-forest/promotions.png
new file mode 100644
index 0000000..03db25b
Binary files /dev/null and b/docs/screenshots/themes/light-forest/promotions.png differ
diff --git a/docs/screenshots/themes/light-forest/roles.png b/docs/screenshots/themes/light-forest/roles.png
new file mode 100644
index 0000000..6b1d8ed
Binary files /dev/null and b/docs/screenshots/themes/light-forest/roles.png differ
diff --git a/docs/screenshots/themes/light-forest/settings.png b/docs/screenshots/themes/light-forest/settings.png
new file mode 100644
index 0000000..6894fa1
Binary files /dev/null and b/docs/screenshots/themes/light-forest/settings.png differ
diff --git a/docs/screenshots/themes/light-forest/sprint-pulse.png b/docs/screenshots/themes/light-forest/sprint-pulse.png
new file mode 100644
index 0000000..5c4e590
Binary files /dev/null and b/docs/screenshots/themes/light-forest/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-forest/team-performance.png b/docs/screenshots/themes/light-forest/team-performance.png
new file mode 100644
index 0000000..3481d35
Binary files /dev/null and b/docs/screenshots/themes/light-forest/team-performance.png differ
diff --git a/docs/screenshots/themes/light-forest/team.png b/docs/screenshots/themes/light-forest/team.png
new file mode 100644
index 0000000..813f57f
Binary files /dev/null and b/docs/screenshots/themes/light-forest/team.png differ
diff --git a/docs/screenshots/themes/light-forest/writing-desk.png b/docs/screenshots/themes/light-forest/writing-desk.png
new file mode 100644
index 0000000..7f35e87
Binary files /dev/null and b/docs/screenshots/themes/light-forest/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-magenta-home.png b/docs/screenshots/themes/light-magenta-home.png
new file mode 100644
index 0000000..39b4592
Binary files /dev/null and b/docs/screenshots/themes/light-magenta-home.png differ
diff --git a/docs/screenshots/themes/light-magenta/backfill.png b/docs/screenshots/themes/light-magenta/backfill.png
new file mode 100644
index 0000000..30f0e3b
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/backfill.png differ
diff --git a/docs/screenshots/themes/light-magenta/chat.png b/docs/screenshots/themes/light-magenta/chat.png
new file mode 100644
index 0000000..2ab3ad0
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/chat.png differ
diff --git a/docs/screenshots/themes/light-magenta/consistency.png b/docs/screenshots/themes/light-magenta/consistency.png
new file mode 100644
index 0000000..2024473
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/consistency.png differ
diff --git a/docs/screenshots/themes/light-magenta/cycles.png b/docs/screenshots/themes/light-magenta/cycles.png
new file mode 100644
index 0000000..d1188e2
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/cycles.png differ
diff --git a/docs/screenshots/themes/light-magenta/home.png b/docs/screenshots/themes/light-magenta/home.png
new file mode 100644
index 0000000..39b4592
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/home.png differ
diff --git a/docs/screenshots/themes/light-magenta/person.png b/docs/screenshots/themes/light-magenta/person.png
new file mode 100644
index 0000000..d20e9c9
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/person.png differ
diff --git a/docs/screenshots/themes/light-magenta/promotion-detail.png b/docs/screenshots/themes/light-magenta/promotion-detail.png
new file mode 100644
index 0000000..7b7822b
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-magenta/promotions.png b/docs/screenshots/themes/light-magenta/promotions.png
new file mode 100644
index 0000000..359842f
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/promotions.png differ
diff --git a/docs/screenshots/themes/light-magenta/roles.png b/docs/screenshots/themes/light-magenta/roles.png
new file mode 100644
index 0000000..314b842
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/roles.png differ
diff --git a/docs/screenshots/themes/light-magenta/settings.png b/docs/screenshots/themes/light-magenta/settings.png
new file mode 100644
index 0000000..1d06f10
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/settings.png differ
diff --git a/docs/screenshots/themes/light-magenta/sprint-pulse.png b/docs/screenshots/themes/light-magenta/sprint-pulse.png
new file mode 100644
index 0000000..b91029e
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-magenta/team-performance.png b/docs/screenshots/themes/light-magenta/team-performance.png
new file mode 100644
index 0000000..e8bff74
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/team-performance.png differ
diff --git a/docs/screenshots/themes/light-magenta/team.png b/docs/screenshots/themes/light-magenta/team.png
new file mode 100644
index 0000000..aa5b94c
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/team.png differ
diff --git a/docs/screenshots/themes/light-magenta/writing-desk.png b/docs/screenshots/themes/light-magenta/writing-desk.png
new file mode 100644
index 0000000..d7afdce
Binary files /dev/null and b/docs/screenshots/themes/light-magenta/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-ocean-home.png b/docs/screenshots/themes/light-ocean-home.png
new file mode 100644
index 0000000..3da14a1
Binary files /dev/null and b/docs/screenshots/themes/light-ocean-home.png differ
diff --git a/docs/screenshots/themes/light-ocean/backfill.png b/docs/screenshots/themes/light-ocean/backfill.png
new file mode 100644
index 0000000..c8db200
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/backfill.png differ
diff --git a/docs/screenshots/themes/light-ocean/chat.png b/docs/screenshots/themes/light-ocean/chat.png
new file mode 100644
index 0000000..387a8d8
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/chat.png differ
diff --git a/docs/screenshots/themes/light-ocean/consistency.png b/docs/screenshots/themes/light-ocean/consistency.png
new file mode 100644
index 0000000..51f48a8
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/consistency.png differ
diff --git a/docs/screenshots/themes/light-ocean/cycles.png b/docs/screenshots/themes/light-ocean/cycles.png
new file mode 100644
index 0000000..d123417
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/cycles.png differ
diff --git a/docs/screenshots/themes/light-ocean/home.png b/docs/screenshots/themes/light-ocean/home.png
new file mode 100644
index 0000000..3da14a1
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/home.png differ
diff --git a/docs/screenshots/themes/light-ocean/person.png b/docs/screenshots/themes/light-ocean/person.png
new file mode 100644
index 0000000..31869ff
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/person.png differ
diff --git a/docs/screenshots/themes/light-ocean/promotion-detail.png b/docs/screenshots/themes/light-ocean/promotion-detail.png
new file mode 100644
index 0000000..1fa0a27
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-ocean/promotions.png b/docs/screenshots/themes/light-ocean/promotions.png
new file mode 100644
index 0000000..0e0c067
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/promotions.png differ
diff --git a/docs/screenshots/themes/light-ocean/roles.png b/docs/screenshots/themes/light-ocean/roles.png
new file mode 100644
index 0000000..b8d63de
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/roles.png differ
diff --git a/docs/screenshots/themes/light-ocean/settings.png b/docs/screenshots/themes/light-ocean/settings.png
new file mode 100644
index 0000000..e2cba14
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/settings.png differ
diff --git a/docs/screenshots/themes/light-ocean/sprint-pulse.png b/docs/screenshots/themes/light-ocean/sprint-pulse.png
new file mode 100644
index 0000000..279fbc0
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-ocean/team-performance.png b/docs/screenshots/themes/light-ocean/team-performance.png
new file mode 100644
index 0000000..5790130
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/team-performance.png differ
diff --git a/docs/screenshots/themes/light-ocean/team.png b/docs/screenshots/themes/light-ocean/team.png
new file mode 100644
index 0000000..6c01357
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/team.png differ
diff --git a/docs/screenshots/themes/light-ocean/writing-desk.png b/docs/screenshots/themes/light-ocean/writing-desk.png
new file mode 100644
index 0000000..0336729
Binary files /dev/null and b/docs/screenshots/themes/light-ocean/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-slate-home.png b/docs/screenshots/themes/light-slate-home.png
new file mode 100644
index 0000000..5379fd0
Binary files /dev/null and b/docs/screenshots/themes/light-slate-home.png differ
diff --git a/docs/screenshots/themes/light-slate/backfill.png b/docs/screenshots/themes/light-slate/backfill.png
new file mode 100644
index 0000000..850cac3
Binary files /dev/null and b/docs/screenshots/themes/light-slate/backfill.png differ
diff --git a/docs/screenshots/themes/light-slate/chat.png b/docs/screenshots/themes/light-slate/chat.png
new file mode 100644
index 0000000..b1c6739
Binary files /dev/null and b/docs/screenshots/themes/light-slate/chat.png differ
diff --git a/docs/screenshots/themes/light-slate/consistency.png b/docs/screenshots/themes/light-slate/consistency.png
new file mode 100644
index 0000000..76539b4
Binary files /dev/null and b/docs/screenshots/themes/light-slate/consistency.png differ
diff --git a/docs/screenshots/themes/light-slate/cycles.png b/docs/screenshots/themes/light-slate/cycles.png
new file mode 100644
index 0000000..7f5a579
Binary files /dev/null and b/docs/screenshots/themes/light-slate/cycles.png differ
diff --git a/docs/screenshots/themes/light-slate/home.png b/docs/screenshots/themes/light-slate/home.png
new file mode 100644
index 0000000..5379fd0
Binary files /dev/null and b/docs/screenshots/themes/light-slate/home.png differ
diff --git a/docs/screenshots/themes/light-slate/person.png b/docs/screenshots/themes/light-slate/person.png
new file mode 100644
index 0000000..2915bb0
Binary files /dev/null and b/docs/screenshots/themes/light-slate/person.png differ
diff --git a/docs/screenshots/themes/light-slate/promotion-detail.png b/docs/screenshots/themes/light-slate/promotion-detail.png
new file mode 100644
index 0000000..f06e177
Binary files /dev/null and b/docs/screenshots/themes/light-slate/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-slate/promotions.png b/docs/screenshots/themes/light-slate/promotions.png
new file mode 100644
index 0000000..70b1b9a
Binary files /dev/null and b/docs/screenshots/themes/light-slate/promotions.png differ
diff --git a/docs/screenshots/themes/light-slate/roles.png b/docs/screenshots/themes/light-slate/roles.png
new file mode 100644
index 0000000..f68f55f
Binary files /dev/null and b/docs/screenshots/themes/light-slate/roles.png differ
diff --git a/docs/screenshots/themes/light-slate/settings.png b/docs/screenshots/themes/light-slate/settings.png
new file mode 100644
index 0000000..9cfc1a8
Binary files /dev/null and b/docs/screenshots/themes/light-slate/settings.png differ
diff --git a/docs/screenshots/themes/light-slate/sprint-pulse.png b/docs/screenshots/themes/light-slate/sprint-pulse.png
new file mode 100644
index 0000000..17b9669
Binary files /dev/null and b/docs/screenshots/themes/light-slate/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-slate/team-performance.png b/docs/screenshots/themes/light-slate/team-performance.png
new file mode 100644
index 0000000..05b403c
Binary files /dev/null and b/docs/screenshots/themes/light-slate/team-performance.png differ
diff --git a/docs/screenshots/themes/light-slate/team.png b/docs/screenshots/themes/light-slate/team.png
new file mode 100644
index 0000000..988fb31
Binary files /dev/null and b/docs/screenshots/themes/light-slate/team.png differ
diff --git a/docs/screenshots/themes/light-slate/writing-desk.png b/docs/screenshots/themes/light-slate/writing-desk.png
new file mode 100644
index 0000000..a97e06e
Binary files /dev/null and b/docs/screenshots/themes/light-slate/writing-desk.png differ
diff --git a/docs/screenshots/themes/light-teal-home.png b/docs/screenshots/themes/light-teal-home.png
new file mode 100644
index 0000000..dbfc587
Binary files /dev/null and b/docs/screenshots/themes/light-teal-home.png differ
diff --git a/docs/screenshots/themes/light-teal/backfill.png b/docs/screenshots/themes/light-teal/backfill.png
new file mode 100644
index 0000000..4726201
Binary files /dev/null and b/docs/screenshots/themes/light-teal/backfill.png differ
diff --git a/docs/screenshots/themes/light-teal/chat.png b/docs/screenshots/themes/light-teal/chat.png
new file mode 100644
index 0000000..c54ea8c
Binary files /dev/null and b/docs/screenshots/themes/light-teal/chat.png differ
diff --git a/docs/screenshots/themes/light-teal/consistency.png b/docs/screenshots/themes/light-teal/consistency.png
new file mode 100644
index 0000000..8d6367c
Binary files /dev/null and b/docs/screenshots/themes/light-teal/consistency.png differ
diff --git a/docs/screenshots/themes/light-teal/cycles.png b/docs/screenshots/themes/light-teal/cycles.png
new file mode 100644
index 0000000..bd273c4
Binary files /dev/null and b/docs/screenshots/themes/light-teal/cycles.png differ
diff --git a/docs/screenshots/themes/light-teal/home.png b/docs/screenshots/themes/light-teal/home.png
new file mode 100644
index 0000000..dbfc587
Binary files /dev/null and b/docs/screenshots/themes/light-teal/home.png differ
diff --git a/docs/screenshots/themes/light-teal/person.png b/docs/screenshots/themes/light-teal/person.png
new file mode 100644
index 0000000..fbdddee
Binary files /dev/null and b/docs/screenshots/themes/light-teal/person.png differ
diff --git a/docs/screenshots/themes/light-teal/promotion-detail.png b/docs/screenshots/themes/light-teal/promotion-detail.png
new file mode 100644
index 0000000..3424df0
Binary files /dev/null and b/docs/screenshots/themes/light-teal/promotion-detail.png differ
diff --git a/docs/screenshots/themes/light-teal/promotions.png b/docs/screenshots/themes/light-teal/promotions.png
new file mode 100644
index 0000000..591b68c
Binary files /dev/null and b/docs/screenshots/themes/light-teal/promotions.png differ
diff --git a/docs/screenshots/themes/light-teal/roles.png b/docs/screenshots/themes/light-teal/roles.png
new file mode 100644
index 0000000..d9a83a4
Binary files /dev/null and b/docs/screenshots/themes/light-teal/roles.png differ
diff --git a/docs/screenshots/themes/light-teal/settings.png b/docs/screenshots/themes/light-teal/settings.png
new file mode 100644
index 0000000..24500f2
Binary files /dev/null and b/docs/screenshots/themes/light-teal/settings.png differ
diff --git a/docs/screenshots/themes/light-teal/sprint-pulse.png b/docs/screenshots/themes/light-teal/sprint-pulse.png
new file mode 100644
index 0000000..0307648
Binary files /dev/null and b/docs/screenshots/themes/light-teal/sprint-pulse.png differ
diff --git a/docs/screenshots/themes/light-teal/team-performance.png b/docs/screenshots/themes/light-teal/team-performance.png
new file mode 100644
index 0000000..da5e6df
Binary files /dev/null and b/docs/screenshots/themes/light-teal/team-performance.png differ
diff --git a/docs/screenshots/themes/light-teal/team.png b/docs/screenshots/themes/light-teal/team.png
new file mode 100644
index 0000000..4d40fc3
Binary files /dev/null and b/docs/screenshots/themes/light-teal/team.png differ
diff --git a/docs/screenshots/themes/light-teal/writing-desk.png b/docs/screenshots/themes/light-teal/writing-desk.png
new file mode 100644
index 0000000..98d08a2
Binary files /dev/null and b/docs/screenshots/themes/light-teal/writing-desk.png differ
diff --git a/scripts/capture-screenshots.mjs b/scripts/capture-screenshots.mjs
index fb99e3c..ed63760 100644
--- a/scripts/capture-screenshots.mjs
+++ b/scripts/capture-screenshots.mjs
@@ -5,9 +5,9 @@
* UI_URL=http://localhost:5173 PRM_PASSWORD=workbench pnpm screenshots
* Expects UI + API running (defaults: UI :5173, API :8787).
*
- * Recreates a demo workspace so shots stay consistent:
- * 01-unlock = empty vs demo create choice
- * remaining = seeded demo org (password workbench)
+ * Recreates a demo workspace so shots stay consistent, then captures:
+ * 1. Theme matrix — every accent × dark/light for key pages
+ * 2. Product tour — every main page (rotating accents for variety)
*/
import fs from "node:fs";
import path from "node:path";
@@ -17,8 +17,13 @@ const UI = process.env.UI_URL || "http://localhost:5173";
const API = process.env.API_URL || "http://127.0.0.1:8787";
const PASSWORD = process.env.PRM_PASSWORD || "workbench";
const OUT = path.resolve("docs/screenshots");
+const THEMES_OUT = path.join(OUT, "themes");
+
+const ACCENTS = ["teal", "ocean", "forest", "slate", "coral", "amber", "magenta", "citrus"];
+const MODES = ["dark", "light"];
fs.mkdirSync(OUT, { recursive: true });
+fs.mkdirSync(THEMES_OUT, { recursive: true });
async function api(pathName, init = {}, token) {
const res = await fetch(`${API}${pathName}`, {
@@ -40,18 +45,9 @@ async function api(pathName, init = {}, token) {
return json;
}
-async function unlockToken(password = PASSWORD) {
- const json = await api("/api/workspace/unlock", {
- method: "POST",
- body: JSON.stringify({ password }),
- });
- return json.token;
-}
-
async function ensureFreshDemo() {
const status = await api("/api/workspace/status");
if (status.initialized) {
- // Prefer destroy when the vault password matches; fall back to unlock+destroy.
try {
await api("/api/workspace/destroy", {
method: "POST",
@@ -81,10 +77,7 @@ async function ensureSubmittedPromo(token, _people, cycles) {
list.find((p) => p.managerId && p.targetNextRoleDefinitionId) ||
list.find((p) => p.targetNextRoleDefinitionId);
if (!eligible?.id) {
- console.warn(
- "no person with target next role — skipping promo screenshots",
- list.map((p) => ({ name: p.name, next: p.targetNextRoleDefinitionId })),
- );
+ console.warn("no person with target next role — skipping promo screenshots");
return null;
}
const created = await api(
@@ -125,16 +118,37 @@ async function ensureSubmittedPromo(token, _people, cycles) {
return { ...draft, status: "submitted" };
}
-async function shot(page, name) {
- const file = path.join(OUT, `${name}.png`);
+async function shot(page, name, dir = OUT) {
+ const file = path.join(dir, `${name}.png`);
await page.screenshot({ path: file, fullPage: false });
console.log("wrote", file);
}
-async function gotoApp(page, route) {
+async function applyAppearance(page, mode, accent) {
+ await page.emulateMediaFeatures([{ name: "prefers-color-scheme", value: mode }]);
+ await page.evaluate(
+ (m, a) => {
+ localStorage.setItem("prm_theme", m);
+ localStorage.setItem("prm_accent", a);
+ document.documentElement.setAttribute("data-theme", m);
+ document.documentElement.setAttribute("data-color-mode", m);
+ document.documentElement.setAttribute("data-accent", a);
+ document.documentElement.style.colorScheme = m;
+ window.dispatchEvent(new CustomEvent("prm-theme-change", { detail: m }));
+ window.dispatchEvent(new CustomEvent("prm-accent-change", { detail: a }));
+ },
+ mode,
+ accent,
+ );
+ await new Promise((r) => setTimeout(r, 200));
+}
+
+async function gotoApp(page, route, mode, accent) {
+ await applyAppearance(page, mode, accent);
await page.goto(`${UI}${route}`, { waitUntil: "networkidle0" });
- await page.waitForSelector(".main, .app-shell", { timeout: 15000 });
- await new Promise((r) => setTimeout(r, 450));
+ await applyAppearance(page, mode, accent);
+ await page.waitForSelector(".main, .app-shell, .unlock-screen", { timeout: 15000 });
+ await new Promise((r) => setTimeout(r, 400));
}
async function scrollHeadingIntoView(page, text) {
@@ -146,6 +160,55 @@ async function scrollHeadingIntoView(page, text) {
await new Promise((r) => setTimeout(r, 350));
}
+async function preparePage(page, name, route) {
+ if (route === "/chat") {
+ await page.waitForSelector(".chat-composer button", { timeout: 15000 });
+ await page.evaluate(() => {
+ document.querySelector(".chat-composer")?.scrollIntoView({ block: "end" });
+ });
+ }
+ if (route === "/team-performance") {
+ await page.waitForSelector(".tp-metrics, .tp-grid, h2", { timeout: 15000 });
+ }
+ if (route === "/sprint-pulse") {
+ await page.waitForFunction(
+ () =>
+ (document.body?.innerText || "").toLowerCase().includes("sprint") ||
+ (document.body?.innerText || "").toLowerCase().includes("pulse"),
+ { timeout: 15000 },
+ );
+ }
+ if (name.includes("writing-desk")) {
+ await page.waitForFunction(
+ () => (document.body?.innerText || "").includes("Evidence digest"),
+ { timeout: 15000 },
+ );
+ await scrollHeadingIntoView(page, "Evidence digest");
+ }
+ if (name.includes("consistency")) {
+ await page.waitForFunction(
+ () =>
+ Array.from(document.querySelectorAll("h2")).some((h) =>
+ h.textContent?.includes("Calibration bundles"),
+ ),
+ { timeout: 15000 },
+ );
+ await scrollHeadingIntoView(page, "Calibration bundles");
+ }
+ if (name.includes("promotion-detail") || name.includes("promo-committee")) {
+ await page.waitForFunction(
+ () => (document.body?.innerText || "").includes("Promo committee export"),
+ { timeout: 15000 },
+ );
+ }
+ if (name.includes("settings")) {
+ await page.waitForSelector(".page-section-nav, #settings-appearance", { timeout: 15000 });
+ await page.evaluate(() => window.scrollTo(0, 0));
+ await new Promise((r) => setTimeout(r, 300));
+ }
+ await new Promise((r) => setTimeout(r, 350));
+}
+
async function main() {
await ensureFreshDemo();
@@ -161,8 +224,13 @@ async function main() {
// 01 — create workbench (empty vs demo)
await page.goto(UI, { waitUntil: "networkidle0" });
- await page.evaluate(() => localStorage.removeItem("prm_token"));
+ await page.evaluate(() => {
+ localStorage.removeItem("prm_token");
+ localStorage.setItem("prm_theme", "dark");
+ localStorage.setItem("prm_accent", "coral");
+ });
await page.reload({ waitUntil: "networkidle0" });
+ await applyAppearance(page, "dark", "coral");
await page.waitForFunction(
() =>
(document.body?.innerText || "").includes("Create workbench") ||
@@ -172,7 +240,6 @@ async function main() {
await new Promise((r) => setTimeout(r, 500));
await shot(page, "01-unlock");
- // Seed demo org for the rest of the gallery
const init = await api("/api/workspace/init", {
method: "POST",
body: JSON.stringify({ name: "Demo Org", password: PASSWORD, seed: true }),
@@ -193,89 +260,78 @@ async function main() {
const promo = await ensureSubmittedPromo(token, people, cycles);
const directs = people.filter((p) => p.managerId);
const person = directs[0] || people[0];
- const cycle = cycles[0];
+ const cycle = cycles.find((c) => c.status === "manager_open") || cycles[0];
if (!cycle?.id) throw new Error("Demo seed produced no cycle");
if (!promo?.id) throw new Error("Could not create a promotion packet for gallery shots");
- await shot(page, "02-home");
- await scrollHeadingIntoView(page, "Needs director attention");
- await shot(page, "15-director-attention");
-
- const routes = [
- ["03-team", "/team"],
- ["04-person", `/team/${person.id}`],
- ["05-roles", "/roles"],
- ["06-cycles", "/cycles"],
- ["07-writing-desk", `/cycles/${cycle.id}/write/${person.id}`],
- ["08-promotions", "/promotions"],
- ["10-consistency", "/consistency"],
- ["11-team-performance", "/team-performance"],
- ["20-sprint-pulse", "/sprint-pulse"],
- ["12-backfill", "/backfill"],
- ["13-chat", "/chat"],
- ["14-settings", "/settings"],
+ const writeRoute = `/cycles/${cycle.id}/write/${person.id}`;
+ const matrixPages = [
+ ["home", "/"],
+ ["team", "/team"],
+ ["person", `/team/${person.id}`],
+ ["roles", "/roles"],
+ ["cycles", "/cycles"],
+ ["writing-desk", writeRoute],
+ ["promotions", "/promotions"],
+ ["promotion-detail", `/promotions/${promo.id}`],
+ ["consistency", "/consistency"],
+ ["team-performance", "/team-performance"],
+ ["sprint-pulse", "/sprint-pulse"],
+ ["backfill", "/backfill"],
+ ["chat", "/chat"],
+ ["settings", "/settings"],
];
- if (promo?.id) routes.splice(6, 0, ["09-promotion-detail", `/promotions/${promo.id}`]);
- for (const [name, route] of routes) {
- await gotoApp(page, route);
- if (route === "/chat") {
- await page.waitForSelector(".chat-composer button", { timeout: 15000 });
- await page.evaluate(() => {
- document.querySelector(".chat-composer")?.scrollIntoView({ block: "end" });
- });
- }
- if (route === "/team-performance") {
- await page.waitForSelector(".tp-metrics, .tp-grid, h2", { timeout: 15000 });
- }
- if (route === "/sprint-pulse") {
- await page.waitForFunction(
- () => (document.body?.innerText || "").toLowerCase().includes("sprint") ||
- (document.body?.innerText || "").toLowerCase().includes("pulse"),
- { timeout: 15000 },
- );
- }
- if (name === "07-writing-desk") {
- await page.waitForFunction(
- () => (document.body?.innerText || "").includes("Evidence digest"),
- { timeout: 15000 },
- );
- await scrollHeadingIntoView(page, "Evidence digest");
- }
- if (name === "10-consistency") {
- await page.waitForFunction(
- () => Array.from(document.querySelectorAll("h2")).some((h) => h.textContent?.includes("Calibration bundles")),
- { timeout: 15000 },
- );
- await scrollHeadingIntoView(page, "Calibration bundles");
- }
- if (name === "09-promotion-detail") {
- await page.waitForFunction(
- () => (document.body?.innerText || "").includes("Promo committee export"),
- { timeout: 15000 },
- );
- }
- if (name === "14-settings") {
- await page.waitForSelector(".page-section-nav, #settings-appearance", { timeout: 15000 });
- await page.evaluate(() => window.scrollTo(0, 0));
- await new Promise((r) => setTimeout(r, 300));
+ // Full theme × page matrix (every accent × dark/light × page)
+ for (const mode of MODES) {
+ for (const accent of ACCENTS) {
+ const dir = path.join(THEMES_OUT, `${mode}-${accent}`);
+ fs.mkdirSync(dir, { recursive: true });
+ console.log(`theme matrix ${mode}/${accent}`);
+ for (const [slug, route] of matrixPages) {
+ await gotoApp(page, route, mode, accent);
+ await preparePage(page, slug, route);
+ await shot(page, slug, dir);
+ }
}
- await new Promise((r) => setTimeout(r, 450));
+ }
+
+ // README product-tour shots — rotate accents so every theme appears in the tour
+ const tour = [
+ ["02-home", "/", "dark", "teal"],
+ ["15-director-attention", "/", "dark", "amber", "Needs director attention"],
+ ["03-team", "/team", "dark", "coral"],
+ ["04-person", `/team/${person.id}`, "dark", "magenta"],
+ ["05-roles", "/roles", "light", "ocean"],
+ ["06-cycles", "/cycles", "dark", "citrus"],
+ ["07-writing-desk", writeRoute, "dark", "coral"],
+ ["16-writing-desk-director", writeRoute, "dark", "amber", "Evidence digest"],
+ ["08-promotions", "/promotions", "light", "magenta"],
+ ["09-promotion-detail", `/promotions/${promo.id}`, "dark", "ocean"],
+ ["19-promo-committee", `/promotions/${promo.id}`, "dark", "ocean"],
+ ["10-consistency", "/consistency", "dark", "forest"],
+ ["17-consistency-director-packs", "/consistency", "dark", "forest", "Calibration bundles"],
+ ["11-team-performance", "/team-performance", "light", "coral"],
+ ["18-team-director-briefing", "/team-performance", "light", "amber"],
+ ["20-sprint-pulse", "/sprint-pulse", "dark", "magenta"],
+ ["12-backfill", "/backfill", "light", "citrus"],
+ ["13-chat", "/chat", "dark", "ocean"],
+ ["14-settings", "/settings", "dark", "coral"],
+ ];
+
+ for (const [name, route, mode, accent, heading] of tour) {
+ await gotoApp(page, route, mode, accent);
+ await preparePage(page, name, route);
+ if (heading) await scrollHeadingIntoView(page, heading);
await shot(page, name);
+ }
- if (name === "07-writing-desk") {
- await scrollHeadingIntoView(page, "Evidence digest");
- await shot(page, "16-writing-desk-director");
- }
- if (name === "10-consistency") {
- await scrollHeadingIntoView(page, "Calibration bundles");
- await shot(page, "17-consistency-director-packs");
- }
- if (name === "11-team-performance") {
- await shot(page, "18-team-director-briefing");
- }
- if (name === "09-promotion-detail") {
- await shot(page, "19-promo-committee");
+ // Theme strip for README — home in every accent (dark + light)
+ for (const mode of MODES) {
+ for (const accent of ACCENTS) {
+ await gotoApp(page, "/", mode, accent);
+ await preparePage(page, "home", "/");
+ await shot(page, `${mode}-${accent}-home`, THEMES_OUT);
}
}