paddington-eurostar/templates/base.html
Edward Betts 4194e8fa64 Improve return date UX on search form
Disable the return date input until Return journey type is selected.
Clicking anywhere in the return date group auto-selects Return and
enables the field. The return date min is kept in sync with the
outbound date, bumping the value forward if it would otherwise fall
before the outbound date.

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

358 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; }
#return-date-group:has(input:disabled) { cursor: pointer; }
/* 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>