Two issues:
1. Flex items default to min-height:auto, which allows them to grow
beyond the flex container instead of being constrained and scrolling.
Add min-height:0 to #sidebar so overflow-y:auto works correctly.
2. WebKit ignores padding-bottom on overflow containers entirely.
Remove it from #sidebar and increase padding-bottom on #stop-list
and #route-master-list (children inside the scroll container, where
padding-bottom is respected) from 1rem to 2rem.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
WebKit/Chrome ignores padding-bottom on overflow-y:auto containers,
so the sidebar's padding: 1rem wasn't creating scroll space below the
last stop. Fix by adding padding-bottom directly to #stop-list and
#route-master-list, which are inside the scrollable container.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All hardcoded paths (/load, /docs, /, /api/route/ etc.) are replaced
with url_for() in templates, so Flask's APPLICATION_ROOT and
ProxyFix generate correct URLs regardless of mount path.
For app.js (a static file), inject a URLS object from the template
alongside RELATION_ID:
URLS.routeApi, .segmentApi, .routeMasterApi, .routePage
Each is generated with url_for(..., relation_id=0)[:-1] to give a
prefix that JS appends relation IDs to. The popstate handler now
strips the URLS.routePage prefix instead of matching a hardcoded
leading slash.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Listen for popstate events and reload the relation from the URL path,
so the back button correctly returns to the route_master view after
navigating to an individual route.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Route links (route_master list, other directions) now intercept clicks
and call loadRoute() + history.pushState() instead of doing a full page
reload, so the map stays at its current position and zooms smoothly into
the new route. Ctrl/cmd/middle-click still opens in a new tab via href.
Introduce currentRelationId (mutable) to track the loaded relation so
loadSegment() uses the correct ID after in-page navigation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add /docs route serving web/templates/api.html: full Bootstrap 5
documentation page covering all three API endpoints with parameter
tables, example requests, and example responses
- Add 'API docs' link to the navbar on the main map page
- Update README.md: add web frontend section with feature list, dev
server instructions, and API endpoint summary table
- Update AGENTS.md: add web/ layout, API endpoint table, Flask run
instructions, and route_master example relation IDs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Refactor core.py: replace sys.exit() calls with OsmError exceptions
so the library is safe to use from Flask and other callers
- Add fetch_sibling_routes and fetch_route_master_routes to core.py
- Add Flask web frontend (web/app.py, templates, static assets):
- Map view with Leaflet; full route drawn in grey on load
- Sidebar stop list; active-slot UX for From/To selection
- Segment preview and download (full route or selected segment)
- Include-stops toggle applied client-side
- Bookmarkable URLs: GET /<relation_id>
- Clear selection button
- Other directions panel (sibling routes from same route_master)
- route_master handling: draws all member routes in colour on map
with links to each individual direction
- Add SVG favicon
- Add py.typed marker; add .gitignore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>