- Add render_trip_element macro to macros.html; use it in trip_item for
the trip list page, giving a consistent one-line-per-element format
with emoji, route, times, duration, operator, distance, and CO₂
- Redesign trip_page.html itinerary: day headers use date-only (no year),
condense check-out to a single accent line, show time-only on transport
cards, humanise duration (Xh Ym), km-only distance, add CO₂ for all
transport modes, fix seat display for integer seat values
- Fix UndefinedError on /trip/past caused by absent 'arrive' key (Jinja2
Undefined is truthy) and date-only depart/arrive fields (no .date())
- Improve mobile map layout: text column before map in HTML order, reduce
mobile map heights, hide toggle button on mobile
- Add trips.css with design system (Playfair Display / Source Sans 3 /
JetBrains Mono, navy/gold/amber palette, card variants by type)
- Add tests/test_trip_list_render.py covering the rendering edge cases
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Transit countries (e.g. Madrid on the Peru trip) were already included
in trip.countries via flight data, but get_destination_timezones only
iterated trip.locations() which comes from accommodation/conferences/events.
Now also extract airport cities from flights and append any that aren't
already covered by a stay, using the airport coordinates for timezone lookup.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Don't write rate-limit/error responses to disk in next_launch_api_data,
so they can't become the "most recent" cache file and cause KeyError crashes
in read_cached_launches. Add defensive results-list checks in
read_cached_launches and get_launches to handle any existing bad files.
Drop refresh=True from the updater's get_active_crewed_flights call so the
2-hour TTL applies; the paginated spacecraft/flight crawl was running on
every hourly cron job and likely causing the burst that triggered throttling.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Show 8-day Bristol home weather on the index and weekends pages.
Show destination weather per day on the trip list and trip page.
Cache forecasts in ~/lib/data/weather/ and refresh via update.py.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When attend_start or attend_end is set, display the full conference
date range in parentheses after the attended dates, e.g.
"Wed 6 Mar to Sun 10 Mar (full conference: Sun 3 Mar to Sun 10 Mar)".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Allows recording when you arrive late or leave early at a multi-day
conference. Both fields accept a plain date or datetime with time.
Trip pages display the attendance dates instead of the official
conference dates when these fields are set.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extract `load_road_transport()` as a shared helper for bus and coach,
combining the near-identical route rendering blocks in `get_trip_routes`
and `Trip.elements()` into single `in ("coach", "bus")` branches.
Document transport type patterns in AGENTS.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add case "bus" to get_locations() and bus route handling to
get_trip_routes() in trip.py. Coach stations now populate a dedicated
"coach_station" dict instead of the train station list. Add
"coach_station" (🚌) and "bus_stop" (🚏) emoji types to map.js.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Use Bootstrap cards and collapsible sections to make the long
lists of airlines, airports, and stations easier to read. Items
are now displayed as badges and hidden by default.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Aggregate yearly stats into overall totals so the trip stats page
shows flight segments by airline, airports used, and stations used
in the summary section at the top.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>