paddington-eurostar/templates/base.html
Edward Betts a859b96a23 Split return date nav into separate outbound/return rows; show earlier tube option on inbound
For return journeys, replace the single combined date navigation row with two
separate rows so outbound and return dates can be adjusted independently.

For inbound underground options, show one service before the earliest catchable
(as an "aim for this" option) rather than the next service after it, which
often arrived too late to connect with the GWR train.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-21 14:09:36 +01:00

357 lines
10 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>{% block title %}South West England to Europe via Eurostar{% endblock %}</title>
<meta property="og:type" content="website">
<meta property="og:site_name" content="South West England to Europe via Eurostar">
<meta property="og:title" content="{% block og_title %}South West England to Europe via Eurostar{% endblock %}">
<meta property="og:description" content="{% block og_description %}Find South West England Temple Meads to Europe itineraries via Paddington, St Pancras, and Eurostar.{% endblock %}">
<meta property="og:url" content="{{ request.url }}">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="{% block twitter_title %}South West England to Europe via Eurostar{% endblock %}">
<meta name="twitter:description" content="{% block twitter_description %}Find South West England Temple Meads to Europe itineraries via Paddington, St Pancras, and Eurostar.{% endblock %}">
<link rel="icon" href="{{ url_for('static', filename='favicon.svg') }}" type="image/svg+xml">
<style>
*, *::before, *::after { box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #f0f4f8;
color: #1a202c;
margin: 0;
padding: 0;
}
header {
background: #00539f;
color: #fff;
padding: 1rem 2rem;
}
header h1 {
margin: 0;
font-size: 1.4rem;
font-weight: 600;
}
header p {
margin: 0.2rem 0 0;
font-size: 0.85rem;
opacity: 0.85;
}
main {
max-width: 1100px;
margin: 2rem auto;
padding: 0 1rem;
}
.card {
background: #fff;
border-radius: 8px;
box-shadow: 0 1px 4px rgba(0,0,0,0.12);
padding: 2rem;
}
.field-label {
display: block;
font-weight: 600;
margin-bottom: 0.4rem;
}
.form-control {
width: 100%;
padding: 0.6rem 0.8rem;
font-size: 1rem;
border: 1px solid #cbd5e0;
border-radius: 4px;
}
.fixed-station {
padding: 0.85rem 1rem;
border: 1px solid #cbd5e0;
border-radius: 10px;
background: linear-gradient(180deg, #f8fbff 0%, #eef4fa 100%);
}
.fixed-station strong {
display: block;
color: #0f172a;
font-size: 1rem;
margin-bottom: 0.2rem;
}
.fixed-station span {
display: block;
color: #475569;
font-size: 0.9rem;
}
.destination-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 0.75rem;
}
.destination-option {
position: relative;
}
.destination-option input {
position: absolute;
opacity: 0;
inset: 0;
margin: 0;
cursor: pointer;
}
.destination-option label {
display: block;
min-height: 100%;
padding: 0.95rem 1rem;
border: 1px solid #cbd5e0;
border-radius: 10px;
background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
cursor: pointer;
transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
.destination-option label strong {
display: block;
color: #0f172a;
font-size: 1rem;
margin-bottom: 0.2rem;
}
.destination-option label span {
display: block;
color: #475569;
font-size: 0.9rem;
}
.destination-option input:hover + label {
border-color: #7aa7d9;
box-shadow: 0 4px 12px rgba(0, 83, 159, 0.08);
}
.destination-option input:focus-visible + label {
border-color: #00539f;
box-shadow: 0 0 0 3px rgba(0, 83, 159, 0.2);
}
.destination-option input:checked + label {
border-color: #00539f;
background: linear-gradient(180deg, #eef6ff 0%, #dcecff 100%);
box-shadow: 0 8px 20px rgba(0, 83, 159, 0.16);
transform: translateY(-1px);
}
.chip-row {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.chip-link,
.chip-current {
display: inline-block;
padding: 0.35rem 0.8rem;
border: 1px solid #cbd5e0;
border-radius: 999px;
font-size: 0.9rem;
text-decoration: none;
}
.chip-link {
color: #00539f;
background: #fff;
}
.chip-link:hover {
border-color: #7aa7d9;
background: #f8fbff;
}
.chip-current {
color: #fff;
background: #00539f;
border-color: #00539f;
font-weight: 600;
}
@media (max-width: 640px) {
.card {
padding: 1.25rem;
}
.col-transfer { display: none; }
}
a { color: #00539f; }
/* Card helpers */
.card > h2:first-child { margin-top: 0; }
/* Form groups */
.form-group { margin-bottom: 1.2rem; }
.form-group-lg { margin-bottom: 1.5rem; }
/* Buttons */
.btn-primary {
background: #00539f;
color: #fff;
border: none;
padding: 0.75rem 2rem;
font-size: 1rem;
font-weight: 600;
border-radius: 4px;
cursor: pointer;
}
.btn-nav {
padding: 0.3rem 0.75rem;
border: 1px solid #cbd5e0;
border-radius: 4px;
text-decoration: none;
color: #00539f;
font-size: 0.9rem;
}
/* Inline select */
.select-inline {
padding: 0.3rem 0.6rem;
font-size: 0.9rem;
border: 1px solid #cbd5e0;
border-radius: 4px;
}
/* Alert boxes */
.alert {
margin-top: 1rem;
padding: 0.75rem 1rem;
border-radius: 4px;
}
.alert-error {
background: #fff5f5;
border: 1px solid #fc8181;
color: #c53030;
}
.alert-warning {
background: #fffbeb;
border: 1px solid #f6e05e;
color: #744210;
}
/* Results page layout */
.back-link { margin-bottom: 1rem; }
.date-nav { display: flex; align-items: center; gap: 0.75rem; margin-bottom: 0.5rem; }
.date-nav-label { min-width: 6rem; font-weight: 600; font-size: 0.9rem; }
.switcher-section { margin: 0.9rem 0 1rem; }
.section-label { font-size: 0.9rem; font-weight: 600; margin-bottom: 0.45rem; }
.filter-row { margin-top: 0.75rem; display: flex; gap: 1.5rem; align-items: center; flex-wrap: wrap; }
.filter-label { font-size: 0.9rem; font-weight: 600; margin-right: 0.5rem; }
.btn-secondary {
padding: 0.3rem 0.75rem;
border: 1px solid #00539f;
border-radius: 4px;
color: #00539f;
background: #fff;
cursor: pointer;
font-size: 0.9rem;
}
.btn-secondary:hover { background: #f8fbff; }
.btn-secondary:disabled { opacity: 0.5; cursor: default; }
.card-meta { color: #4a5568; margin: 0; }
.footnote { margin-top: 1rem; font-size: 0.82rem; color: #718096; }
/* Results table */
.results-table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.results-table th,
.results-table td { padding: 0.6rem 0.8rem; }
.results-table thead tr { border-bottom: 2px solid #e2e8f0; text-align: left; }
.results-table tbody tr { border-bottom: 1px solid #e2e8f0; }
.row-fast { background: #f0fff4; }
.row-slow { background: #fff5f5; }
.row-alt { background: #f7fafc; }
.row-unreachable { background: #f7fafc; color: #a0aec0; }
/* Empty state */
.empty-state { color: #4a5568; text-align: center; padding: 3rem 2rem; }
.empty-state p { margin: 0; }
.empty-state p:first-child { font-size: 1.1rem; margin-bottom: 0.5rem; }
.empty-state p:last-child { font-size: 0.9rem; }
/* Ticket class button group */
.btn-group { display: inline-flex; border: 1px solid #cbd5e0; border-radius: 4px; overflow: hidden; vertical-align: middle; }
.btn-group-option { padding: 0.28rem 0.65rem; font-size: 0.82rem; background: #fff; border: none; border-right: 1px solid #cbd5e0; cursor: pointer; color: #374151; white-space: nowrap; }
.btn-group-option:last-child { border-right: none; }
.btn-group-option.active { background: #00539f; color: #fff; font-weight: 600; }
.btn-group-option:hover:not(.active) { background: #f0f4f8; }
/* Flash animation for total price */
@keyframes price-flash { 0%,100% { background-color: transparent; } 40% { background-color: #fef08a; } }
.price-flash { animation: price-flash 0.7s ease-out; border-radius: 3px; }
/* Loading state */
#advance-loading { font-size: 0.82rem; color: #718096; margin-left: 0.5rem; }
.loading-panel {
display: flex;
gap: 1rem;
align-items: flex-start;
margin-top: 1rem;
padding: 1rem;
border: 1px solid #cbd5e0;
border-radius: 6px;
background: #f8fbff;
}
.loading-panel p { margin: 0.25rem 0 0; }
.spinner {
width: 1.5rem;
height: 1.5rem;
border: 3px solid #cbd5e0;
border-top-color: #00539f;
border-radius: 50%;
flex: 0 0 auto;
animation: spin 0.8s linear infinite;
}
.spinner-inline {
width: 0.85rem;
height: 0.85rem;
border-width: 2px;
margin-right: 0.35rem;
}
@keyframes spin { to { transform: rotate(360deg); } }
/* Fare lines — show all, dim inactive */
.fare-line { display: block; line-height: 1.6; transition: opacity 0.15s; }
.fare-inactive { opacity: 0.4; }
/* Utilities */
.text-muted { color: #718096; }
.text-dimmed { color: #a0aec0; }
.text-green { color: #276749; }
.text-red { color: #c53030; }
.text-blue { color: #00539f; }
.text-sm { font-size: 0.85rem; }
.text-xs { font-size: 0.75rem; }
.nowrap { white-space: nowrap; }
.font-bold { font-weight: 600; }
.font-normal { font-weight: 400; }
</style>
</head>
<body>
<header>
<h1>South West England to Europe via Eurostar</h1>
<p>GWR to Paddington &rarr; St Pancras &rarr; Eurostar
&nbsp;&middot;&nbsp;
<a href="https://git.4angle.com/edward/bristol-eurostar"
style="color:rgba(255,255,255,0.75);font-size:0.8rem"
target="_blank" rel="noopener">source</a>
</p>
</header>
<main>
{% block content %}{% endblock %}
</main>
</body>
</html>