diff --git a/README.md b/README.md
index f9126cf..0121891 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
**A desktop workbench for the Pi coding agent.**
**Workspace-first, not chat-first.**
-[Quick Start](#quick-start) · [Architecture](docs/pidex-architecture.md) · [Design tokens](#design-tokens) · [Docs](docs/pidex-project-brief.md)
+[Quick Start](#quick-start) · [Architecture](docs/pidex-architecture.md)
[](https://github.com/echohello-dev/pidex/actions/workflows/ci.yml)
[](https://www.electronjs.org/)
@@ -67,53 +67,16 @@ Pi runs out-of-process over RPC so the UI survives a runtime crash. Pretext hand
| Package manager | Bun |
| Toolchain | mise, all commands via `mise run` |
-## Design tokens
-
-The workbench inherits its palette from the [Pi coding agent](https://pi.dev) so it feels like part of the same family as the runtime. Source of truth: [`scripts/_design.py`](scripts/_design.py), hexes pulled from `pi.dev/style.css`.
-
-| Token | Hex | Role |
-|---|---|---|
-| bg-deep | `#0d1116` | Window background |
-| bg-canvas | `#161d27` | Canvas surface |
-| panel | `#212730` | Sidebar / panel |
-| panel-soft | `#252f3d` | Card surface |
-| parchment | `#dacbc2` | Named cream, primary mark and text |
-| moonstone | `#ebe7e4` | Lighter cream |
-| driftwood | `#5c5752` | Warm mid-gray |
-| terracotta | `#844f3b` | Warm bronze accent |
-| terracotta-light | `#b86b52` | Status dots |
-| sunkissed | `#e1b06e` | Warm gold |
-| sage | `#a3a473` | Sage accent |
-| accent-blue | `#6a9fcc` | Links, focus |
-
-Regenerate assets after a token edit:
-
-```bash
-uv run --with fonttools python scripts/build-icon.py # assets/icon, mark
-uv run --with fonttools python scripts/build-logo.py # assets/logo (composable π + pidex)
-uv run --with fonttools python scripts/build-banner.py # docs/assets/banner-bg
-```
-
-`docs/assets/screenshot.png` is captured from the running app. To refresh: temporarily gate a `webContents.capturePage()` call behind an env var, run `PIDEX_CAPTURE=1 mise run dev`, then revert. The banner composites the screenshot over the design-system background (`docs/assets/banner-bg.png`, built by `scripts/build-banner.py`) with the composable logo watermark, all via `magick`.
-
-The banner background is procedural: `bg-canvas` field with the blueprint grid (96px minor + 480px major, lifted in opacity for hero scale) and a vertical gradient into `bg-deep`. Strictly rectilinear; no generated imagery.
-
-Banner and logo use the design system font pairing: **Georgia** (serif, from `--serif` in `tokens.css`) for the wordmark and body, **Commit Mono** (from `--mono`) for the code surfaces visible in the screenshot.
-
-## What's next
-
-- [ ] Diff viewer with virtualised summaries
-- [ ] Session fork, branch sessions visually
-- [ ] Worktree switching from the UI
-
-## Documentation
+## License
-| Doc | What it covers |
-|---|---|
-| [docs/pidex-project-brief.md](docs/pidex-project-brief.md) | Thesis, pain points, positioning, MVP slice |
-| [docs/pidex-architecture.md](docs/pidex-architecture.md) | Process boundaries, IPC schema, SDK vs RPC |
-| [docs/pidex-pretext-deep-dive.md](docs/pidex-pretext-deep-dive.md) | Why DOM-free text measurement |
+[Apache-2.0](./LICENSE): see the file for full text. Personal project, shared in the open.
-## License
+## Star History
-[MIT](./LICENSE) — see the file for full text. Personal project, shared in the open.
\ No newline at end of file
+
+
+
+
+
+
+
diff --git a/assets/logo.png b/assets/logo.png
index cd49968..dda71d7 100644
Binary files a/assets/logo.png and b/assets/logo.png differ
diff --git a/docs/assets/banner-bg.png b/docs/assets/banner-bg.png
deleted file mode 100644
index 951b364..0000000
Binary files a/docs/assets/banner-bg.png and /dev/null differ
diff --git a/docs/assets/banner-bg.svg b/docs/assets/banner-bg.svg
index 20eb204..676588a 100644
--- a/docs/assets/banner-bg.svg
+++ b/docs/assets/banner-bg.svg
@@ -1,24 +1 @@
-
+
\ No newline at end of file
diff --git a/docs/assets/banner.png b/docs/assets/banner.png
index 8592c8b..8c681f5 100644
Binary files a/docs/assets/banner.png and b/docs/assets/banner.png differ
diff --git a/docs/assets/framed-window.svg b/docs/assets/framed-window.svg
deleted file mode 100644
index 886a5a8..0000000
--- a/docs/assets/framed-window.svg
+++ /dev/null
@@ -1,34 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/assets/screenshot.png b/docs/assets/screenshot.png
deleted file mode 100644
index b6519b5..0000000
Binary files a/docs/assets/screenshot.png and /dev/null differ
diff --git a/scripts/build-banner.py b/scripts/build-banner.py
index 60fee2a..f2e1d95 100644
--- a/scripts/build-banner.py
+++ b/scripts/build-banner.py
@@ -1,85 +1,146 @@
-"""Build the README banner background using the pidex design system.
-
-The background mirrors the app's own chrome (tokens.css base.css body
-background): bg-canvas field with the blueprint grid (96px minor +
-480px major, blue-tinted) and a vertical gradient into bg-deep. Shapes
-are strictly rectilinear; no organic imagery. The real app screenshot
-and the composable logo are laid on top of this background.
-
-Output:
- docs/assets/banner-bg.png (1600x900)
-
-Compose the final banner with:
- magick docs/assets/banner-bg.png \\
- docs/assets/screenshot.png -resize 1000x -geometry +300+80 -composite \\
- assets/logo.png -resize 200x -geometry +70+70 -composite \\
- docs/assets/banner.png
+#!/usr/bin/env python
+"""Build the README banner: the pidex logo (isometric cube with the
+Pi coding agent logo on its top face + wordmark) centered on the
+design-system background (bg-canvas with the blueprint grid + vertical
+gradient into bg-deep).
+
+Outputs:
+ docs/assets/banner.png (1600x600)
+ assets/logo.png (regenerated as part of the build)
+ docs/assets/banner-bg.svg (the background SVG, tracked)
"""
from __future__ import annotations
import shutil
import subprocess
-import sys
from pathlib import Path
REPO = Path(__file__).resolve().parent.parent
-OUT = REPO / "docs" / "assets"
-
-sys.path.insert(0, str(Path(__file__).resolve().parent))
-from _design import BG_DEEP, BG_CANVAS # noqa: E402
-
-W, H = 1600, 900
-
-
-def svg() -> str:
- # Blueprint grid matches tokens.css (96px minor + 480px major, blue
- # tint). At hero scale the token opacities would be invisible, so
- # they're lifted slightly while keeping the same hue.
- return f"""
-"""
+DOCS = REPO / "docs" / "assets"
+ASSETS = REPO / "assets"
+
+BANNER_W, BANNER_H = 1600, 600
+
+INK_BRONZE = "#13110f"
+PARCHMENT = "#dacbc2"
+
+
+def pi_path(font_path):
+ from fontTools.ttLib import TTFont
+ from fontTools.pens.svgPathPen import SVGPathPen
+
+ font = TTFont(font_path)
+ cmap = font.getBestCmap()
+ gname = cmap[ord("π")]
+ pen = SVGPathPen(font.getGlyphSet())
+ font.getGlyphSet()[gname].draw(pen)
+ glyf = font["glyf"][gname]
+ bbox = (glyf.xMin, glyf.yMin, glyf.xMax, glyf.yMax)
+ return pen.getCommands(), bbox, font["head"].unitsPerEm
+
+
+def build_logo_svg(width, height):
+ d, bbox, _ = pi_path("/System/Library/Fonts/Supplemental/Georgia Italic.ttf")
+ gx = (bbox[0] + bbox[2]) / 2
+ gy = (bbox[1] + bbox[3]) / 2
+ e = 200
+ dx = e * 0.866
+ dy = e * 0.5
+ cx, cy = width / 2 - 60, height / 2
+ top = (cx, cy - dy)
+ right = (cx + dx, cy)
+ bot = (cx, cy + dy)
+ left = (cx - dx, cy)
+ a = dx / 470.0
+ b = dy / 470.0
+ # Scale the Pi logo to 65% of the top face so it fits with padding
+ pad_scale = 0.65
+ a *= pad_scale
+ b *= pad_scale
+ transform = f"matrix({a} {b} {-a} {b} {cx} {cy - dy})"
+ p_d = (
+ "M165.29 165.29 H517.36 V400 H400 V517.36 H282.65 V634.72 H165.29 Z "
+ "M282.65 282.65 V400 H400 V282.65 Z"
+ )
+ i_dot_d = "M517.36 400 H634.72 V634.72 H517.36 Z"
+ word_x = right[0] + 60
+ word_y = cy + 20
+ word_size = int(height * 0.22)
+ parts = []
+ parts.append(
+ f''
+ )
+ parts.append(
+ f''
+ )
+ parts.append(
+ f''
+ )
+ parts.append(f'')
+ parts.append(f'')
+ parts.append(f'')
+ parts.append("")
+ parts.append(
+ f'pidex'
+ )
+ inner = "".join(parts)
+ return (
+ f''
+ )
-def render_png(svg: Path, png: Path, width: int) -> None:
+def build_bg_svg():
+ return (
+ f''
+ )
+
+
+def render(svg, out, width):
if not shutil.which("inkscape"):
- sys.exit("inkscape not found on PATH; install via brew install inkscape")
+ raise SystemExit("inkscape not found on PATH")
+ tmp = out.with_suffix(".tmp.svg")
+ tmp.write_text(svg)
subprocess.run(
- ["inkscape", str(svg), "--export-type=png", "--export-filename", str(png), "--export-width", str(width)],
+ ["inkscape", str(tmp), "--export-type=png", "--export-filename", str(out), "--export-width", str(width)],
check=True,
)
+ tmp.unlink()
+
+
+def main():
+ bg_svg = build_bg_svg()
+ (DOCS / "banner-bg.svg").write_text(bg_svg)
+ bg_png = DOCS / "banner-bg.png"
+ render(bg_svg, bg_png, BANNER_W)
+ logo_svg = build_logo_svg(BANNER_W, BANNER_H)
+ logo_png = ASSETS / "logo.png"
+ render(logo_svg, logo_png, BANNER_W)
-def main() -> None:
- OUT.mkdir(parents=True, exist_ok=True)
- svg_path = OUT / "banner-bg.svg"
- png_path = OUT / "banner-bg.png"
- svg_path.write_text(svg())
- render_png(svg_path, png_path, W)
- print(f"wrote {svg_path}")
- print(f"wrote {png_path}")
+ subprocess.run(
+ ["magick", str(bg_png), str(logo_png), "-composite", str(DOCS / "banner.png")],
+ check=True,
+ )
+ bg_png.unlink()
+ print(f"wrote {DOCS / 'banner.png'}")
if __name__ == "__main__":