diff --git a/AGENTS.md b/AGENTS.md
index f33dd57..dfd2071 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -49,7 +49,7 @@ Keep it stable. Prefer pointers to canonical sources over copied structure, file
- Prefer links or pointers to canonical sources over copied lists.
- Avoid project trees, architecture maps, generated inventories, current file sizes, issue lists, TODO inventories, and other snapshots that will rot.
- Stable commands: `cargo run -p hemx-xtask -- test`, `cargo check --workspace`, `redgate health --strict`. Use the xtask runner for full verification so jobs are capped from local CPU and memory. req: test/004
-- Run the workout product exemplar with `cargo run --bin hemx-workout-example` and open `http://127.0.0.1:3028`; set `HEMX_WORKOUT_ADDR=127.0.0.1:3030` if the default port is busy. req: examples/001
+- Run the workout product exemplar with `cargo run --bin hemx-workout-example` and open `http://127.0.0.1:3028`; set `HEMX_WORKOUT_ADDR=127.0.0.1:3030` if the default port is busy. Its durable visual direction lives in `examples/workout/DESIGN.md`. req: examples/001
- hemx core stays small: effects, typed ids, registries, and wire schema only.
- Routing, auth, sessions, transport, transitions, sync, and storage belong in integration/user crates.
- Public examples and beginner APIs should use generated resources and `IntoEffect`, not raw ids or runtime opcodes.
diff --git a/examples/workout/DESIGN.md b/examples/workout/DESIGN.md
new file mode 100644
index 0000000..01129b8
--- /dev/null
+++ b/examples/workout/DESIGN.md
@@ -0,0 +1,19 @@
+# Workout exemplar design
+
+Direction: gym-floor command slate — one heavy next action, thumb-safe command rail, and an inspectable private ledger. req: examples/001
+
+Preserve:
+- First viewport shows one obvious action path before logs or host details.
+- Controls stay large enough for sweaty one-handed use; forms remain secondary to tap actions.
+- Local truth is visible as a ledger/export, not hidden behind dashboard metrics. req: local/001 req: local/003
+- Host capabilities read as a boundary surface, not as app state or a native framework. req: host/002
+
+Avoid:
+- Dashboard/KPI cards, fake charts, bottom-nav app chrome, glass/gradient hero filler, and hidden client state.
+- Equal-weight action grids that make “what now?” ambiguous.
+- Styling that requires handwritten selector UI JavaScript.
+
+Accessibility and responsive boundaries:
+- Keep semantic buttons/forms/labels and visible focus rings.
+- Minimum tap target is defined by `--tap`; do not reduce it for density.
+- Narrow screens are the primary material; wide screens may split the command slate and ledger but must not hide the current action.
diff --git a/examples/workout/src/lib.rs b/examples/workout/src/lib.rs
index c583050..6d783f9 100644
--- a/examples/workout/src/lib.rs
+++ b/examples/workout/src/lib.rs
@@ -667,8 +667,8 @@ mod tests {
let html = render(&WorkoutState::demo()).to_string();
assert!(html.contains("Now-first Workout Copilot"));
assert!(html.contains("Complete set"));
- assert!(html.contains("Export via browser/PWA share"));
- assert!(html.contains("Request native haptic"));
+ assert!(html.contains("Share export"));
+ assert!(html.contains("Haptic"));
assert!(!html.contains(&format!("<{}", "script")));
assert!(!html.contains("querySelector"));
}
diff --git a/examples/workout/src/main.rs b/examples/workout/src/main.rs
index b5fe00d..f879de5 100644
--- a/examples/workout/src/main.rs
+++ b/examples/workout/src/main.rs
@@ -24,6 +24,7 @@ async fn main() {
pub fn app(state: AppState) -> Router {
Router::new()
.route("/", get(page).post(interact))
+ .route("/workout.css", get(workout_css))
.route(runtime_js_path(), get(runtime))
.with_state(state)
}
@@ -41,6 +42,13 @@ async fn interact(
request.dispatch_async(workout_app::registry(state)).await
}
+async fn workout_css() -> impl IntoResponse {
+ (
+ [("content-type", "text/css; charset=utf-8")],
+ include_str!("../templates/workout.css"),
+ )
+}
+
async fn runtime() -> impl IntoResponse {
runtime_js()
}
diff --git a/examples/workout/templates/app_shell.heml b/examples/workout/templates/app_shell.heml
index cbcc637..419dd44 100644
--- a/examples/workout/templates/app_shell.heml
+++ b/examples/workout/templates/app_shell.heml
@@ -4,6 +4,7 @@