Files
Arah2/.planning/phases/01-design-tokens-rams-foundation/01-03-PLAN.md
T

8.8 KiB
Raw Blame History

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, user_setup, must_haves
phase plan type wave depends_on files_modified autonomous requirements user_setup must_haves
01-design-tokens-rams-foundation 03 execute 2
01-01
theme/basemap/liberty-rams.json
theme/basemap/build.mjs
theme/basemap/index.html
theme/package.json
true
DSGN-01
decisions truths artifacts key_links
D-08
D-09
D-10
A Rams-styled MapLibre basemap renders in a browser: grayscale/muted land + water, desaturated roads, muted labels, zero signal-orange in the basemap
Basemap values are derived from the token package, not hand-tuned hex in the style JSON (D-09)
Map labels use the self-hosted Space Grotesk / Geist assets (D-10)
path provides contains
theme/basemap/build.mjs Generates liberty-rams.json by reading token values from theme/src/tokens.css tokens.css
path provides contains
theme/basemap/liberty-rams.json Forked OpenFreeMap liberty style with Rams cartography glyphs
path provides contains
theme/basemap/index.html MapLibre GL browser view proving the basemap renders (success criterion 3) maplibre-gl
from to via pattern
theme/basemap/build.mjs theme/src/tokens.css parse token custom properties tokens.css
from to via pattern
theme/basemap/index.html theme/basemap/liberty-rams.json MapLibre style URL liberty-rams.json
Fork the OpenFreeMap `liberty` basemap style into a Rams-constant cartography output: grayscale/muted grounding, desaturated roads, muted labels in Rams type, `signal-orange` reserved exclusively for the future route line (not used in the basemap itself). Prove it renders in a browser with MapLibre GL.

Purpose: D-08 (full Rams pass on basemap), D-09 (derived from tokens, not hand-tuned), D-10 (Rams font assets for labels), roadmap success criterion 3. Output: theme/basemap/ — build script, generated style JSON, browser proof page.

<read_first> @planning/phases/01-design-tokens-rams-foundation/01-CONTEXT.md @planning/phases/01-design-tokens-rams-foundation/01-01-SUMMARY.md @stitch_minimalist_route_navigator/telemetry_rams/DESIGN.md </read_first>

Derivation targets (map token → cartography role per D-08 / telemetry_rams/DESIGN.md "Grayscale Map Grounding"): - Land/background ground tone: between `soft-beige` (#D9D2C6) and `chassis-subtle` (#CCC4B5) - Water: desaturated mid-gray derived from `matte-black` mixed toward low-saturation (rgba derived, NOT brand hues) - Roads: desaturated, hierarchy by weight only (major roads slightly darker than minor) - Buildings: light gray within the `#D9D2C6 → #1A1A1A` calibrated gray band - Labels: `matte-black` at reduced opacity; fonts Space Grotesk (major) / Geist (minor) — same assets as theme/fonts (D-10) - `signal-orange` (#EB8008), `functional-red` (#ED3F1C), `olive-green` (#736B1E) must NOT appear in the basemap — accent is reserved exclusively for the route line rendered in Phase 5 (D-08).

Style input: https://tiles.openfreemap.org/styles/liberty style JSON (fetch at build time and fork; do not vendor the full original JSON — build.mjs fetches, transforms, writes).

task 1: basemap build script deriving style from tokens theme/basemap/build.mjs, theme/basemap/liberty-rams.json 1. Create `theme/basemap/build.mjs` (Node ESM, no external deps beyond node builtins): fetches `https://tiles.openfreemap.org/styles/liberty` style JSON, transforms it, writes `theme/basemap/liberty-rams.json`. 2. Derivation step: parse `theme/src/tokens.css` extracting the `--color-*` custom property values (deterministic regex `-\-color-([a-z0-9-]+):\s*(#[0-9A-Fa-f]{6})`). Compute the Rams cartography palette IN SCRIPT (D-09: derived, not hand-tuned): desaturate all land/road/water/building colors to the calibrated gray band via a small `desaturate(hex, satMultiplier)` helper (pure function: convert hex→HSL, multiply saturation toward ~0.06–0.12, adjust lightness per role per Interfaces table). Map transformed values onto the liberty style's `layers[].paint` color properties (`background`, `water`, `road-*`, `building-*`, `landcover-*`, `bridge-*`). 3. FONT STEP: replace liberty's glyph/name font stacks. Point the style's `glyphs` to the OpenFreeMap hosted glyphs endpoint (keep `https://tiles.openfreemap.org/fonts/{fontstack}/{range}.pbf` to avoid self-hosting pbf glyphs in Phase 1), and rewrite every `layout["text-font"]` value to `"Space Grotesk Medium"` for major label layers (place-city, place-subtown and above) and `"Noto Sans Regular"` fallback chain ending `"Space Grotesk Regular"`… — IMPORTANT constraint: OpenFreeMap glyphs server only serves font stacks it hosts. If `Space Grotesk` is not available on the glyphs endpoint, detect a 404 at build time and fall back to the closest hosted stack, recording the substitution in a `"metadata"` block (`"rams-font-substitutions": {...}`) — this keeps D-10 satisfied in spirit (Rams typography for labels) with honest fallback provenance. 4. Common concerns: signal-orange/functional-red/olive-green token names are excluded from the derivation set (guard: throw if any of those 3 hex values end up anywhere in the output layers' paint properties). 5. Add npm script to `theme/package.json`: `"basemap": "node basemap/build.mjs"`. 6. Run it; verify `theme/basemap/liberty-rams.json` exists, is valid JSON, has `version: 8`, `glyphs`, `sources`, `layers[0].paint` uses a transformed neutral. npm run basemap --workspace theme && node -e "const s=require('./theme/basemap/liberty-rams.json'); if(!s.layers||!s.glyphs) process.exit(1); const rgx=/EB8008|ED3F1C|736B1E/i; const bad=JSON.stringify(s.layers).match(rgx); if(bad){process.exit(2)} console.log('OK layers='+s.layers.length)" build.mjs derives all basemap colors from tokens.css (no hardcoded cartography hex in the script beyond token parsing), output JSON is a valid MapLibre style, and none of the 3 accent colors appear anywhere in the layer paint properties. task 2: browser proof page (dummy route + rendered basemap) theme/basemap/index.html, theme/package.json 1. Create `theme/basemap/index.html`: static MapLibre GL viewer (CDN unpkg `maplibre-gl@^4`), `<style>` sets page chrome to Rams tokens (`var(--color-surface)` background etc. — import `../dist/rams.css`), init map centered ~3.1513, 101.6958 (KLCC / KL metro, per project region), zoom ~13, style = `./liberty-rams.json`. 2. Draw a placeholder route polyline in `signal-orange` (raw tolerance: the ROUTE line is exactly where signal-orange is allowed per D-08) with a thick 6px stroke so the visual "grayscale guiderail + orange vector" intent is previewable, labeled in a README comment as consumed by Phase 5. 3. Add `"basemap:dev": "npx serve theme/basemap || true"`? No extra server dep — just use `python3 -m http.server` invocation pattern for the verify command instead; document the open command in index.html's comment header. Add npm script `"basemap:preview": "cd theme/basemap && python3 -m http.server 8123"`. 4. Layer order: route layer added LAST in the layer stack so it sits above mapcar/roads but below any label overlap is not required here — keep simple. test -f theme/basemap/index.html && grep -q "maplibre" theme/basemap/index.html && grep -q "liberty-rams.json" theme/basemap/index.html && grep -qE "3\.15|101\.69" theme/basemap/index.html index.html loads liberty-rams.json, centers KLCC, draws a signal-orange route placeholder, and is checkable via `npm run basemap:preview --workspace theme` → http://localhost:8123 (human eyes verify the grayscale+muted+Rams feel, success criterion 3).

<threat_model>

Trust Boundaries

Boundary Description
basemap build → OpenFreeMap API build.mjs fetches external style JSON across network
</threat_model>
- `npm run basemap --workspace theme` → 0 exit, liberty-rams.json regenerated - No accent hex (#EB8008 / #ED3F1C / #736B1E) anywhere in layers' paint - index.html renders the basemap via the preview script - `grep -c "tokens.css" theme/basemap/build.mjs` ≥ 1 (derivation provenance)

<success_criteria> Rams basemap derived from (not decorated with) the token package renders in a browser at KL metro with muted grayscale grounding, Rams label fonts, and zero accent-color leaks into cartography. Route accent visually confirmed against the grayscale base (success criterion 3 of the roadmap). </success_criteria>

After completion, create `.planning/phases/01-design-tokens-rams-foundation/01-03-SUMMARY.md`