Move inline styles to CSS classes; update README

Extract repeated inline styles from templates into named CSS classes in
base.html: layout helpers, buttons, form groups, alert boxes, results table
rules, row highlight classes, typography utilities, and empty-state styles.
Remove the per-page <style> block from results.html.

Update README to reflect current destinations, GraphQL data source, Circle
Line timetable, configurable connection range, and GWR fare table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Edward Betts 2026-04-04 15:39:04 +01:00
parent e6f310f517
commit 71be0dd8cf
4 changed files with 214 additions and 97 deletions

View file

@ -2,9 +2,9 @@
Source: https://git.4angle.com/edward/bristol-eurostar
Plan a trip from Bristol Temple Meads to Europe on Eurostar.
Plan a trip from Bristol Temple Meads to Europe via Eurostar.
Combines GWR trains (Bristol → Paddington) with Eurostar services (St Pancras → destination) and shows all valid same-day connections, filtering by journey time and minimum/maximum transfer window at Paddington/St Pancras.
Combines GWR trains (Bristol → Paddington) with Eurostar services (St Pancras → destination) and shows all valid same-day connections, including Circle Line times for the Paddington → St Pancras transfer. Displays GWR walk-on fares, Eurostar Standard prices, seat availability, and total journey cost.
## Destinations
@ -12,23 +12,42 @@ Combines GWR trains (Bristol → Paddington) with Eurostar services (St Pancras
- Brussels Midi
- Lille Europe
- Amsterdam Centraal
- Rotterdam Centraal
- Cologne Hbf
## How it works
Train times are fetched from two sources simultaneously:
Train times and prices are fetched from two sources:
- **GWR** — scraped from [Realtime Trains](https://www.realtimetrains.co.uk/) using httpx
- **Eurostar** — scraped from the Eurostar timetable pages via the embedded `__NEXT_DATA__` JSON (no browser required)
- **Eurostar** — fetched from the Eurostar GraphQL API (single call returns timetable, Standard fares, and seat availability)
The Paddington → St Pancras transfer uses a real Circle Line timetable parsed from a TfL TransXChange XML file, accounting for walk time to the platform at Paddington and walk time from the platform to the St Pancras check-in.
Results are cached to disk by date and destination.
## Connection constraints
Configurable via the search form. Defaults:
| | |
|---|---|
| Minimum Paddington → St Pancras | 75 min |
| Maximum Paddington → St Pancras | 2h 20m |
| Maximum Bristol → Paddington | 1h 50m |
| Minimum Paddington → St Pancras | 50 min |
| Maximum Paddington → St Pancras | 110 min |
Valid range: 45120 min (min), 60180 min (max).
## GWR fares
Walk-on single fares for Bristol Temple Meads → Paddington, selected automatically by departure time:
| Ticket | Price | Restriction (weekdays) |
|---|---|---|
| Super Off-Peak | £45.00 | Not valid 05:0509:57 |
| Off-Peak | £63.60 | Not valid before 08:26 |
| Anytime | £138.70 | No restriction |
Weekends always use Super Off-Peak.
## Setup
@ -36,6 +55,19 @@ Results are cached to disk by date and destination.
pip install -e ".[dev]"
```
### Configuration
Copy or create `config/local.py` (gitignored) to override defaults:
```python
CACHE_DIR = '/var/cache/bristol-eurostar'
CIRCLE_LINE_XML = '/path/to/output_txc_01CIR_.xml'
```
Defaults (in `config/default.py`) use `~/lib/data/tfl/`.
The Circle Line XML is a TfL TransXChange timetable file. The Paddington (H&C Line) stop is `9400ZZLUPAH1`; the King's Cross St Pancras stop is `9400ZZLUKSX3`.
## Running
```bash