diff --git a/Home.md b/Home.md
index 254a522..eee0c93 100644
--- a/Home.md
+++ b/Home.md
@@ -1,10 +1,10 @@
-
+
-# arah²
+# arah²
A privacy-respecting, Telegram-first GPS navigator — a waze-like route navigator delivered through a Telegram bot and Mini App instead of an app-store install, built on OpenStreetMap data, and designed to Dieter Rams' "less, but better." First users are in the Kuala Lumpur metro.
@@ -14,7 +14,7 @@ The Telegram bot is **arah2bot**. The product is live — a private beta with re
## Overview
-arah² is an npm-workspaces monorepo with five packages:
+arah² is an npm-workspaces monorepo with five packages:
| Package | Name | What it does |
|---|---|---|
@@ -46,7 +46,7 @@ graph TD
APP -->|"GET /api/location — Bearer token"| W
APP -->|"POST /api/route — Bearer token"| R2
W --> KV
- W -->|"cron */2 → turn cards"| TG
+ W -->|"cron */2 → turn cards"| TG
APP --> MAP
THEME -.->|"inlined at build time"| MAP
THEME -.->|"dist/rams.css"| APP
@@ -109,14 +109,14 @@ cp bot/.dev.vars.example bot/.dev.vars
---
-## Quickstart: clone → production (your own bot, your own Cloudflare)
+## Quickstart: clone → production (your own bot, your own Cloudflare)
The concise path. Full detail lives in [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md); local development in [docs/GETTING-STARTED.md](docs/GETTING-STARTED.md).
**1. Create the bot** — in Telegram, open [@BotFather](https://t.me/BotFather):
-- `/newbot` → pick a name + username → copy the **bot token**
-- `/setuserpic` → upload `assets/logo_arah2.png` (the bot's avatar)
-- Bot Settings → **Main Mini App** → set your future production URL (you'll fill the real one in step 4; BotFather's app *name* is what Telegram shows in the mini-app header)
+- `/newbot` → pick a name + username → copy the **bot token**
+- `/setuserpic` → upload `assets/logo_arah2.png` (the bot's avatar)
+- Bot Settings → **Main Mini App** → set your future production URL (you'll fill the real one in step 4; BotFather's app *name* is what Telegram shows in the mini-app header)
**2. Clone + install**
@@ -139,8 +139,8 @@ MINI_APP_URL=https://.workers.dev
```bash
npx wrangler login # browser auth, once
-npm run build # theme tokens → web/dist
-npm run deploy # theme → web → worker + assets + webhook + commands
+npm run build # theme tokens → web/dist
+npm run deploy # theme → web → worker + assets + webhook + commands
```
**5. Provision the road graph** (engine A's routing data — R2, also free):
@@ -155,7 +155,7 @@ node routing/scripts/upload-road-graph.mjs # builds + uploads the KL graph, ro
```bash
node bot/scripts/set-webhook.mjs # arms the webhook (+ /telegram/webhook path)
node bot/scripts/register-commands.mjs # /help /privacy /cari in every command scope
-node bot/scripts/set-menu-button.mjs # the menu button opens the app ("arah²")
+node bot/scripts/set-menu-button.mjs # the menu button opens the app ("arah²")
```
**7. Verify** — the canaries (read-backs, nothing trusted blindly):
@@ -163,9 +163,9 @@ node bot/scripts/set-menu-button.mjs # the menu button opens the app ("arah
```bash
npm run privacy-audit -- --live && npm run budget-audit -- --live
```
-Then in Telegram: restart the client → open the bot → `/cari KLCC` → venue card → **OPEN** → the map routes. Done: your own private navigator, $0/month.
+Then in Telegram: restart the client → open the bot → `/cari KLCC` → venue card → **OPEN** → the map routes. Done: your own private navigator, $0/month.
-> **Permission notes:** the Cloudflare token (optional, only for the audit `--live` probes) needs Account → Workers KV Storage → **Read** only. The bot itself needs no special Telegram permissions; `/setprivacy` default (off) is correct — the bot never reads non-command messages.
+> **Permission notes:** the Cloudflare token (optional, only for the audit `--live` probes) needs Account → Workers KV Storage → **Read** only. The bot itself needs no special Telegram permissions; `/setprivacy` default (off) is correct — the bot never reads non-command messages.
---
@@ -176,7 +176,7 @@ Then in Telegram: restart the client → open the bot → `/cari KLCC` → venue
- **WASM-router track** — fully client-side routing in the webview (origin+destination never touch a server; static-hosted; the fork-perfect endgame)
- **Battery measurement** — the <10%/hr guidance-drain record (deferred from launch)
- **Bitmap map snapshots** in minimized chat turn-cards (needs a rasterizer in the $0 stack)
-- **Voice guidance** · **live trip share** (`sendLocation(live_period)`) · **toll toggle** · **speed-limit display** — the REQUIREMENTS deferred table
+- **Voice guidance** · **live trip share** (`sendLocation(live_period)`) · **toll toggle** · **speed-limit display** — the REQUIREMENTS deferred table
**v2 (post user-validation):**
- Incident reports + community layer, gamification, traffic-weighted ETAs — per the original vision doc ([IDEAS.md](IDEAS.md))
@@ -195,7 +195,7 @@ The bot answers in English and Bahasa Melayu. Commands are registered into Teleg
| Command | Alias | Behaviour |
|---|---|---|
-| `/start` | `/mula` | One-sentence introduction to arah² and its privacy posture. |
+| `/start` | `/mula` | One-sentence introduction to arah² and its privacy posture. |
| `/help` | — | Lists the commands that exist and points at the known-limits record. |
| `/privacy` | `/privasi` | Names exactly what is stored (user id, chat id, language, ~15 min) and exactly what is never stored (location, routes, trip history, profile). |
| `/cari` | `/search` | Searches the curated KL gazetteer (`/cari KLCC`) and replies with **one** native venue card (`sendVenue`) carrying an OPEN IN ARAHARAH Mini App button plus 2–4 alternates as callback buttons. Out-of-area queries get an honest refusal that names the v1 area, never the query text. |
@@ -204,7 +204,7 @@ The bot answers in English and Bahasa Melayu. Commands are registered into Teleg
1. **Search.** `/cari ` normalizes and scores the query against the KL gazetteer (`@araharah/search`); the best hit ships as a venue card with deep link `MINI_APP_URL/?dest=`.
2. **Open the Mini App.** The webview reads `?dest=` from `location.search`, preloads the destination, and mints a session by posting the verbatim `Telegram.WebApp.initData` string to `/api/session`.
-3. **Acquire a starting point.** The three-link location chain (`web/src/location/chain.ts`) tries **Telegram → WebView → chat pin**, in that locked order.
+3. **Acquire a starting point.** The three-link location chain (`web/src/location/chain.ts`) tries **Telegram → WebView → chat pin**, in that locked order.
4. **Route.** The app posts the origin and destination to `/api/route`; the Worker's router (`bot/src/routing/worker-router.ts`) loads the R2-hosted CSR graph once per cold isolate, snaps, and runs A* (`@araharah/routing`). Every miss class answers `200 null` — router-pending, never a wrong line.
5. **Guidance.** Accepting a route mints a guidance envelope (`POST /api/guidance`, 7200 s TTL); a scheduled cron (`*/2 * * * *`) projects progress along the frozen route snapshot and pushes due turn cards — a maneuver glyph photo with a live caption — into the chat, with a button back into the Mini App at `?g=`.
@@ -224,16 +224,16 @@ The Worker's `fetch` handler routes exactly six paths and returns `404` for anyt
```bash
# Mint a session from a Mini App initData string
curl -X POST http://localhost:8787/api/session --data-binary @initdata.txt
-# → {"token":""}
+# → {"token":""}
# Poll the location relay with the token in memory
curl -H "Authorization: Bearer " http://localhost:8787/api/location
-# → {"pin":null} (honest null, not a fabricated coordinate)
+# → {"pin":null} (honest null, not a fabricated coordinate)
```
### Location acquisition in the Mini App
-`web/src/location/chain.ts` is a three-link state machine with a locked order — **Telegram → WebView → chat pin** — and freshness is a separate axis from availability. A Telegram fix byte-identical to the last accepted one routes to the nudge, never to success; denial is a state, not an exception. The chain exposes a `Fix`-shaped abstraction with a pluggable cadence and hard-codes no interval, so continuous-mode polling is a later decision, not a rewrite. Past 45 seconds the strip flips to `SIGNAL LOST` and the last marker dims.
+`web/src/location/chain.ts` is a three-link state machine with a locked order — **Telegram → WebView → chat pin** — and freshness is a separate axis from availability. A Telegram fix byte-identical to the last accepted one routes to the nudge, never to success; denial is a state, not an exception. The chain exposes a `Fix`-shaped abstraction with a pluggable cadence and hard-codes no interval, so continuous-mode polling is a later decision, not a rewrite. Past 45 seconds the strip flips to `SIGNAL LOST` and the last marker dims.
### Consuming the design tokens
@@ -262,9 +262,9 @@ import ramsStyle from "@araharah/theme/basemap/liberty-rams.json";
The Telemetry Rams design system lives in `theme/` as a Tailwind v4 CSS-first token package — the single source of truth for every color, spacing, typography, and radius value in the project. Consume the tokens by importing `theme/src/tokens.css` (plain CSS custom properties, usable by any stylesheet or the MapLibre basemap) or the compiled stylesheet produced by `npm run build`. The token vocabulary mirrors the mockup screens verbatim, so markup derived from them maps one to one. Rams philosophy lives on in `DESIGN.md`, which is superseded for specifics — values are never restated outside the token package.
```bash
-npm run build -w theme # src/theme.css → dist/rams.css (minified)
+npm run build -w theme # src/theme.css → dist/rams.css (minified)
npm run sheet # build + print the sheet.html path
-npm run gallery # build + screenshot → serve gallery.html and basemap on :8123
+npm run gallery # build + screenshot → serve gallery.html and basemap on :8123
npm run audit # off-token audit of the rendered CSS — exits non-zero on violations
npm run capture # Playwright screenshots of the token sheet
```