···11+# CLAUDE.md
22+33+This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
44+55+## Commands
66+77+```sh
88+deno task dev # Development server with hot reload
99+deno task build # Production build
1010+deno task fetch:benchmarks # Refresh benchmark data from Moonboard API (requires USERNAME/PASSWORD env vars)
1111+```
1212+1313+Build output goes to `www/dist/`. The build tool is [Civility](https://github.com/bpev/civility) (`civility.json` is its config).
1414+1515+## Architecture
1616+1717+**Moonbound** is an offline-first PWA for browsing Moonboard benchmark climbing problems. It uses Deno + TypeScript with no framework—components are native Web Components.
1818+1919+### Routing & Components
2020+2121+`www/index.ts` initializes a Civility `Router` that maps URL paths to custom elements:
2222+2323+- `/` → `<home-page>` — benchmark listing with search/grade/status filters
2424+- `/climb` → `<climb-page>` — climb detail with canvas route diagram and logbook entry
2525+- `/library` → `<library-page>` — user's personal climb log
2626+- `/stopwatch` → `<stopwatch-page>` — timer with lap tracking
2727+- `/settings` → `<settings-page>` — board type and grade scale preferences
2828+2929+Each route is defined in `www/routes/`. Components extend `HTMLElement`, manage their own state, and re-render as needed.
3030+3131+### Data Flow
3232+3333+- **Benchmark data**: Static `www/static/data/benchmarks.json` (fetched from Moonboard API via `scripts/moon.ts`, then committed). Loaded once and cached in memory by `www/utils/benchmarks.ts`.
3434+- **User data**: Everything persisted to `localStorage`—logbook (`mb_logbook`), board type (`mb_type`), grade scale (`grade_scale`), and filter states.
3535+- **Navigation state**: `www/utils/climb-nav.ts` holds a singleton with the current filtered climb list and index, enabling swipe navigation in `<climb-page>` via Hammer.js.
3636+3737+### Key Utilities
3838+3939+- `www/utils/benchmarks.ts` — grade mappings, board configs (7 models, 2016–2024), canvas drawing logic for hold positions
4040+- `www/utils/logbook.ts` — logbook CRUD, session tracking (date, attempts, sent, rating)
4141+- `www/utils/updates.ts` — service worker registration and 5-minute update polling
4242+4343+### CSS Architecture
4444+4545+All styles live in `www/static/theme.css` inside a single `@layer theme` block, which sits above Civility's `base` and `components` layers. The layering order (declared in `civility.css`) is: `normalize → base → base-theme → components → theme → utilities`.
4646+4747+**Civility elements used for structure:**
4848+4949+- `ui-sub-header` — sticky filter bars in `<home-page>` and `<library-page>`; styled to be a flex column with padding/border
5050+- `ui-main-header` — climb detail header bar inside `<climb-page>` (flex row: back button, title, meta)
5151+- `ui-badge` — grade pills (`.grade` class) and status badges (`variant="success"` for Sent, bare for Project)
5252+- `ui-button-group` — filter button groups; active state driven by `aria-pressed="true"` rather than a class
5353+5454+**Host element styling:** page-level layout (flex column, height, padding) is set directly on the custom element tags (`home-page`, `library-page`, `climb-page`, `settings-page`, `stopwatch-page`) rather than inner wrapper divs.
5555+5656+**Settings page:** uses CSS `:has(input:checked)` on bare `label` elements—no JS needed to toggle selected state.
5757+5858+### PWA / Service Worker
5959+6060+`www/worker.ts` implements a cache-first strategy with network fallback. `www/manifest.json` configures the PWA. The service worker is registered by `www/utils/updates.ts`, which also prompts users when a new version is available.
6161+6262+### Code Style
6363+6464+Deno fmt config (from `deno.json`): single quotes, no semicolons, preserve prose wrap.