/* ═══════════════════════════════════════════════════════════════════
   Drive Cheap — Design System
   Dark mode default, light mode via body.light-mode
   ═══════════════════════════════════════════════════════════════════ */

/* ─── CSS Tokens ─────────────────────────────────────────────────── */
:root {
    /* Core palette */
    --accent-cyan:    #06b6d4;
    --accent-emerald: #10b981;
    --accent-amber:   #f59e0b;
    --accent-rose:    #f43f5e;
    --accent-purple:  #8b5cf6;

    /* Dark mode defaults */
    --bg-base:        #0b0f19;
    --bg-card:        rgba(18, 26, 43, 0.88);
    --bg-input:       rgba(255, 255, 255, 0.05);
    --border-glass:   rgba(255, 255, 255, 0.10);
    --text-main:      #f1f5f9;
    --text-muted:     #94a3b8;
    --header-bg:      rgba(11, 15, 25, 0.96);
    --shadow-glow:    0 8px 32px rgba(0, 0, 0, 0.5);
    --map-bg:         #090d16;
    --marker-bg:      rgba(18, 26, 43, 0.92);
    --select-opt-bg:  #121a2b;

    --radius-lg: 16px;
    --radius-md: 10px;
    --radius-sm: 6px;
}

/* ─── Light Mode Override ─────────────────────────────────────────── */
body.light-mode {
    --bg-base:       #f0f4f8;
    --bg-card:       rgba(255, 255, 255, 0.92);
    --bg-input:      rgba(0, 0, 0, 0.04);
    --border-glass:  rgba(0, 0, 0, 0.10);
    --text-main:     #0f172a;
    --text-muted:    #64748b;
    --header-bg:     rgba(255, 255, 255, 0.96);
    --shadow-glow:   0 8px 32px rgba(0, 0, 0, 0.12);
    --map-bg:        #e2e8f0;
    --marker-bg:     rgba(255, 255, 255, 0.95);
    --select-opt-bg: #ffffff;
}

/* ─── Base Reset ──────────────────────────────────────────────────── */
*, *::before, *::after {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    font-family: 'Inter', system-ui, -apple-system, sans-serif;
}

body, html {
    width: 100%;
    height: 100%;
    overflow: hidden;
    background-color: var(--bg-base);
    color: var(--text-main);
    transition: background-color 0.3s ease, color 0.3s ease;
}

#app-container {
    display: flex;
    flex-direction: column;
    width: 100vw;
    height: 100vh;
}

/* ─── Header Bar ─────────────────────────────────────────────────── */
.header-bar {
    height: 64px;
    background: var(--header-bg);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--border-glass);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 24px;
    z-index: 1000;
    transition: background 0.3s ease, border-color 0.3s ease;
}

/* The logo is a <button> that resets the map, so the browser's default button
   styling has to be undone — and it needs to look and feel pressable. */
.header-left .logo {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 4px 8px;
    margin-left: -8px;
    border: none;
    border-radius: var(--radius-md);
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background 0.2s ease;
}

.header-left .logo:hover { background: var(--bg-input); }
.header-left .logo:active { transform: scale(0.98); }
.header-left .logo:focus-visible {
    outline: 2px solid var(--accent-cyan);
    outline-offset: 2px;
}

/* The logo is an inline SVG filled with currentColor, so `color` is what paints
   it; font-size no longer applies. */
.logo-icon {
    display: block;
    flex-shrink: 0;
    color: var(--accent-cyan);
    filter: drop-shadow(0 0 8px rgba(6, 182, 212, 0.6));
}

.logo-text h1 {
    font-size: 18px;
    font-weight: 700;
    letter-spacing: -0.5px;
    color: var(--text-main);
}

.logo-text .highlight { color: var(--accent-cyan); }

/* ─── Stats Ticker ───────────────────────────────────────────────── */
.stats-ticker {
    display: flex;
    align-items: center;
    gap: 10px;
}

.stat-pill {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    padding: 6px 14px;
    border-radius: 20px;
    font-size: 12px;
    display: flex;
    gap: 6px;
    align-items: center;
    transition: background 0.3s ease, border-color 0.3s ease;
}

.stat-pill .label { color: var(--text-muted); }
.stat-pill .val   { font-weight: 600; color: var(--text-main); }

.highlight-pill {
    border-color: rgba(16, 185, 129, 0.4);
    background: rgba(16, 185, 129, 0.08);
}
.highlight-pill .val { color: var(--accent-emerald); }

/* ─── Header Right Controls ──────────────────────────────────────── */
.header-right {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Theme Toggle Button */
.btn-header-action {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-main);
    padding: 8px 14px;
    border-radius: 8px;
    font-weight: 600;
    font-size: 12px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
    transition: all 0.2s ease;
}
.btn-header-action:hover {
    background: var(--accent-cyan);
    border-color: var(--accent-cyan);
    color: #fff;
    transform: translateY(-1px);
}

.trend-pill {
    background: rgba(6, 182, 212, 0.1);
    border-color: rgba(6, 182, 212, 0.3);
}

.theme-select {
    color-scheme: light;
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-main);
    min-width: 88px;
    min-height: 44px;
    padding: 8px;
    border-radius: 10px;
    cursor: pointer;
    font: inherit;
    font-size: 13px;
}

/* Native option popups may use a light surface even with a dark page. */
.theme-select option { background-color: #ffffff; color: #111827; }

.sync-status {
    background: rgba(16, 185, 129, 0.1);
    border: 1px solid rgba(16, 185, 129, 0.3);
    color: var(--accent-emerald);
    padding: 6px 14px;
    border-radius: 20px;
    font-size: 12px;
    font-weight: 600;
    display: flex;
    align-items: center;
    gap: 6px;
}

.btn-primary {
    background: linear-gradient(135deg, var(--accent-cyan), #3b82f6);
    color: white;
    border: none;
    padding: 9px 18px;
    border-radius: 8px;
    font-weight: 600;
    font-size: 13px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 8px;
    transition: all 0.2s ease;
    box-shadow: 0 4px 12px rgba(6, 182, 212, 0.3);
}
.btn-primary:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(6, 182, 212, 0.5);
}

/* ─── Map Workspace ──────────────────────────────────────────────── */
.workspace {
    /* Sliding drawers must not enlarge the page or allow focus to pan it. */
    overflow: clip;
    position: relative;
    flex: 1;
    width: 100%;
    height: calc(100vh - 64px);
}

#map {
    width: 100%;
    height: 100%;
    background: var(--map-bg);
    transition: background 0.3s ease;
}

/* ─── Glass Panels ───────────────────────────────────────────────── */
.glass-panel {
    background: var(--bg-card);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
    border: 1px solid var(--border-glass);
    box-shadow: var(--shadow-glow);
    border-radius: var(--radius-lg);
    transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease;
}

/* ─── Control Panel (Pinned to Left of Map) ──────────────────────── */
.control-panel {
    position: absolute;
    top: 20px;
    left: 20px;
    width: 360px;
    padding: 18px;
    z-index: 900;
    display: flex;
    flex-direction: column;
    gap: 14px;
    max-height: calc(100vh - 120px);
    overflow-y: auto;
    overflow-x: hidden;
}

/* scrollbar */
.control-panel::-webkit-scrollbar { width: 4px; }
.control-panel::-webkit-scrollbar-track { background: transparent; }
.control-panel::-webkit-scrollbar-thumb { background: var(--border-glass); border-radius: 4px; }

.panel-section { display: flex; flex-direction: column; }

.section-label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.7px;
    color: var(--text-muted);
    margin-bottom: 8px;
    display: flex;
    align-items: center;
    gap: 6px;
}

/* ─── UK price averages stack ────────────────────────────────────── */
.stats-stack {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.stat-row {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    padding: 8px 12px;
    border-radius: var(--radius-md);
    font-size: 12px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.stat-row .label { color: var(--text-muted); }
.stat-row .val { font-weight: 700; color: var(--text-main); }

.highlight-row {
    border-color: rgba(16, 185, 129, 0.4);
    background: rgba(16, 185, 129, 0.08);
}
.highlight-row .val { color: var(--accent-emerald); }

/* ─── Map Style Buttons ──────────────────────────────────────────── */
.map-style-btns {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 6px;
}

.map-style-btn {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-muted);
    padding: 8px 4px;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: 11px;
    font-weight: 600;
    text-align: center;
    transition: all 0.2s ease;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 3px;
}

.map-style-btn .style-icon { font-size: 16px; }

.map-style-btn:hover {
    border-color: rgba(6, 182, 212, 0.4);
    color: var(--text-main);
}

.map-style-btn.active {
    background: linear-gradient(135deg, rgba(6, 182, 212, 0.18), rgba(139, 92, 246, 0.18));
    border-color: var(--accent-cyan);
    color: var(--accent-cyan);
}

/* ─── Petrol / Electric mode switch ──────────────────────────────── */
.mode-switch {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 6px;
}

.mode-btn {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-muted);
    padding: 10px 6px;
    border-radius: var(--radius-md);
    cursor: pointer;
    font-size: 12px;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: all 0.2s ease;
    /* 44px so it is a comfortable tap target on a phone. */
    min-height: 44px;
}

.mode-btn:hover { border-color: rgba(6, 182, 212, 0.4); color: var(--text-main); }

.mode-btn[data-mode="petrol"].active {
    background: linear-gradient(135deg, rgba(6, 182, 212, 0.18), rgba(139, 92, 246, 0.18));
    border-color: var(--accent-cyan);
    color: var(--accent-cyan);
}

/* Green for electric, so which mode is live is legible from the colour
   alone rather than only from which button is filled. */
.mode-btn[data-mode="electric"].active {
    background: linear-gradient(135deg, rgba(16, 185, 129, 0.20), rgba(6, 182, 212, 0.15));
    border-color: var(--accent-emerald);
    color: var(--accent-emerald);
}

.mode-btn:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; }

/* Everything that only describes petrol is hidden wholesale in electric mode:
   a fuel grade, a brand filter and a price legend all describe prices that
   chargepoints do not have. The legend stays — it is reused for the density
   scale — but the fuel and brand controls go. */
body.mode-electric #sectionFuel,
body.mode-electric #sectionStats,
body.mode-electric #sectionBrand { display: none !important; }

/* Overlays stays: Heatmap, Pins and Favourites all mean something for
   chargepoints. Alerts does not — a chargepoint has no price to move, so the
   row would be a switch that can never fire. */
body.mode-electric #alertsToggleRow { display: none !important; }

/* Same reasoning inside the Zone Finder: a fuel grade and a target-price alert
   describe nothing about a chargepoint. Charge speed is filtered from the main
   panel's Charge Speed control, which applies to the zone query too. */
body.mode-electric #zoneFuelGroup,
body.mode-electric #zoneAlertBox { display: none !important; }

/* Trends is entirely price-based: a fuel grade, a price chart over 7/30/90
   days, a 30-day price projection, brand price leadership and biggest movers.
   None of it has an equivalent for a chargepoint, so electric mode swaps the
   whole view rather than trying to repurpose the parts. */
body.mode-electric #trendFuelTabs,
body.mode-electric #trendVerdictBanner,
body.mode-electric #trendChartCard,
body.mode-electric #forecastCard,
body.mode-electric #brandLeadershipCard,
body.mode-electric #moversGrid { display: none !important; }

body:not(.mode-electric) #trendsElectric { display: none !important; }

/* Route Saver: MPG and a fuel grade describe a combustion engine, and the
   commute watch notifies on a price that chargepoints do not have. */
body.mode-electric #routeVehicleRow,
body.mode-electric #routeAlertBox { display: none !important; }

/* Power-band bars. Width carries the share; the figure is written out as well,
   because a bar alone cannot be read off precisely. */
.ev-band-row {
    display: grid;
    grid-template-columns: 96px 1fr auto;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
    font-size: 12px;
}

.ev-band-label { color: var(--text-muted); font-weight: 600; }

.ev-band-track {
    background: var(--bg-input);
    border-radius: 999px;
    height: 14px;
    overflow: hidden;
}

.ev-band-fill { height: 100%; border-radius: 999px; }
.ev-band-value { color: var(--text-main); font-weight: 700; font-variant-numeric: tabular-nums; }

/* ...and the electric-only filters are absent from petrol mode. */
body:not(.mode-electric) #sectionChargeFilters { display: none !important; }

/* Build marker under the logo. Deliberately quiet — it is a diagnostic, not
   part of the brand, and it sits inside the logo button so it must not look
   clickable in its own right. */
.app-version {
    display: block;
    font-size: 10px;
    line-height: 1;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    opacity: 0.75;
    margin-top: 2px;
    font-variant-numeric: tabular-nums;
}

.charge-unknown-toggle { margin-top: 10px; }

/* .btn-secondary alone renders 20px tall here, which is not a tap target.
   44px is the floor this project already settled on for the zoom control. */
#btnResetChargeFilters {
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
}

/* The density ramp is one colour deepening rather than the price ramp's hue
   sweep: it encodes one quantity with no meaningful midpoint, so lightness
   alone carries it and it survives greyscale and colour-blindness. */
.gradient-bar.is-density {
    background: linear-gradient(to right,
        rgba(16, 185, 129, 0.15),
        rgba(16, 185, 129, 0.45),
        rgba(16, 185, 129, 0.75),
        rgba(5, 150, 105, 1)) !important;
}

.charge-marker {
    background: none;
    border: none;
}

.charge-pin {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: var(--accent-emerald);
    border: 2px solid rgba(255, 255, 255, 0.85);
    color: #04121c;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45);
    font-weight: 800;
    font-size: 11px;
}

/* Rapid chargers earn a different fill: at 50 kW+ the practical difference to
   a driver is an hour versus a coffee. */
.charge-pin.rapid {
    background: var(--accent-amber);
    width: 34px;
    height: 34px;
    font-size: 12px;
}

.charge-star-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    min-height: 38px;
    margin-top: 10px;
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.15s ease;
}

.charge-star-btn:hover { border-color: var(--accent-emerald); color: var(--text-main); }

.charge-star-btn.saved {
    background: rgba(16, 185, 129, 0.16);
    border-color: var(--accent-emerald);
    color: var(--accent-emerald);
}

.charge-attribution {
    font-size: 10px;
    color: var(--text-muted);
    line-height: 1.4;
    margin-top: 8px;
}

.charge-attribution a { color: var(--accent-cyan); }

/* ─── Panel Row / Inputs ─────────────────────────────────────────── */
.panel-row {
    display: flex;
    gap: 10px;
}
.flex-1 { flex: 1; }

.custom-select {
    width: 100%;
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-main);
    padding: 9px 12px;
    border-radius: var(--radius-md);
    font-size: 13px;
    outline: none;
    cursor: pointer;
    transition: all 0.2s ease;
    -webkit-appearance: none;
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2394a3b8' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 10px center;
    padding-right: 28px;
}

.custom-select:focus { border-color: var(--accent-cyan); }

.custom-select option {
    background: var(--select-opt-bg);
    color: var(--text-main);
}

/* ─── Toggle Switches ────────────────────────────────────────────── */
.toggle-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.toggle-switch {
    display: flex;
    align-items: center;
    gap: 8px;
    cursor: pointer;
    font-size: 12px;
    color: var(--text-muted);
}

.toggle-switch input { display: none; }

.slider {
    width: 34px;
    height: 18px;
    background-color: var(--bg-input);
    border: 1px solid var(--border-glass);
    border-radius: 20px;
    position: relative;
    transition: 0.3s;
    flex-shrink: 0;
}

.slider::before {
    content: "";
    position: absolute;
    height: 12px;
    width: 12px;
    left: 2px;
    bottom: 2px;
    background-color: var(--text-muted);
    border-radius: 50%;
    transition: 0.3s;
}

input:checked + .slider { background-color: var(--accent-cyan); border-color: var(--accent-cyan); }
input:checked + .slider::before { transform: translateX(16px); background-color: #fff; }

/* ─── Search Box ─────────────────────────────────────────────────── */
/* Wraps because four controls do not fit 324px of panel. A flex item's default
   min-width is auto, and for an <input> that resolves to its intrinsic size, so
   `flex: 1` alone could not shrink it: the row demanded 436px, and the panel's
   overflow-x: hidden clipped "Near me" and Share right off the edge. `min-width: 0`
   lets the input give way, and wrapping puts the two action buttons on their own
   line rather than squeezing everything. */
.search-box {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.search-box input {
    flex: 1 1 180px;
    min-width: 0;
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-main);
    padding: 9px 14px;
    border-radius: var(--radius-md);
    font-size: 13px;
    outline: none;
    transition: border-color 0.2s;
}

.search-box input::placeholder { color: var(--text-muted); }
.search-box input:focus { border-color: var(--accent-cyan); }

.btn-search {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-main);
    padding: 0 14px;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all 0.2s;
}
/* ─── Floating Zone Button ───────────────────────────────────────── */
.floating-zone-container {
    position: absolute;
    top: 20px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 910;
    display: flex;
    gap: 10px;
}

.btn-floating-zone {
    position: relative;
    top: auto;
    left: auto;
    transform: none;
    z-index: 910;
    background: rgba(11, 15, 25, 0.85);
    backdrop-filter: blur(16px);
    border: 1px solid var(--accent-cyan);
    color: var(--text-main);
    padding: 10px 20px;
    border-radius: 30px;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    box-shadow: 0 4px 20px rgba(6, 182, 212, 0.35);
    display: flex;
    align-items: center;
    gap: 8px;
    transition: all 0.25s ease;
}

.btn-floating-zone:hover {
    background: var(--accent-cyan);
    color: #fff;
    box-shadow: 0 6px 24px rgba(6, 182, 212, 0.6);
    transform: scale(1.04);
}

.btn-danger-zone {
    border-color: rgba(239, 68, 68, 0.6) !important;
    color: #ef4444 !important;
    background: rgba(239, 68, 68, 0.15) !important;
    box-shadow: 0 4px 20px rgba(239, 68, 68, 0.35) !important;
}

.btn-danger-zone:hover {
    background: #ef4444 !important;
    color: #fff !important;
    box-shadow: 0 6px 24px rgba(239, 68, 68, 0.6) !important;
}

.zone-highlight-marker {
    background: rgba(11, 15, 25, 0.92);
    border: 2px solid var(--accent-emerald);
    color: #fff;
    padding: 4px 10px;
    border-radius: 20px;
    font-weight: 800;
    font-size: 13px;
    box-shadow: 0 0 18px rgba(16, 185, 129, 0.85);
    display: flex;
    align-items: center;
    gap: 6px;
    white-space: nowrap;
}

.zone-center-handle {
    background: rgba(6, 182, 212, 0.92);
    color: #000;
    border: 2px solid #fff;
    border-radius: 20px;
    padding: 3px 10px;
    font-weight: 800;
    font-size: 11px;
    display: flex;
    align-items: center;
    gap: 6px;
    cursor: grab;
    box-shadow: 0 0 20px rgba(6, 182, 212, 0.9);
    white-space: nowrap;
    user-select: none;
}

.zone-center-handle:active {
    cursor: grabbing;
    transform: scale(1.08);
}

/* ─── Persistent Right-Hand Pull-Out Sidebar ──────────────────────── */
.cheapest-sidebar {
    position: fixed;
    right: 0;
    top: 75px;
    bottom: 20px;
    width: 380px;
    z-index: 950;
    transform: translateX(100%);
    transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
    display: flex;
    flex-direction: column;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    box-shadow: -10px 0 30px rgba(0, 0, 0, 0.5);
}

.cheapest-sidebar.open {
    transform: translateX(0);
}

.zone-sidebar {
    position: fixed;
    right: 0;
    top: 75px;
    bottom: 20px;
    width: 440px;
    z-index: 960;
    transform: translateX(100%);
    transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
    display: flex;
    flex-direction: column;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
    box-shadow: -10px 0 30px rgba(0, 0, 0, 0.5);
}

.zone-sidebar.open {
    transform: translateX(0);
}

/* Scrolls rather than clips.

   This was `overflow: hidden`, which is fine for a panel whose content fits and
   silently destructive for one whose content does not: .zone-sidebar is a fixed
   column (top: 75px; bottom: 20px), so anything past that height was cut off
   with no scroll container to reach it — the Zone Price League Table sits at the
   bottom of that panel and was simply unreachable on desktop.

   The same fault was found and fixed for the mobile bottom sheets in 8d5e50d,
   but that fix lives inside `@media (max-width: 820px)`, so desktop kept the
   clipping for another week. Fixing a shared rule inside a breakpoint fixes it
   at that breakpoint only. The sibling drawers (.detail-drawer, .route-drawer)
   already scroll themselves; this brings the zone panel in line. */
.sidebar-content {
    padding: 18px;
    display: flex;
    flex-direction: column;
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
}

.sidebar-header {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--border-glass);
    margin-bottom: 14px;
}

.sidebar-header h3 {
    font-size: 16px;
    font-weight: 700;
    color: var(--text-main);
    display: flex;
    align-items: center;
    gap: 8px;
}

/* ─── Zone Winner Banner & League Table ───────────────────────────── */
.zone-winner-banner {
    background: linear-gradient(135deg, rgba(16, 185, 129, 0.2), rgba(6, 182, 212, 0.15));
    border: 1px solid var(--accent-emerald);
    border-radius: var(--radius-md);
    padding: 12px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    box-shadow: 0 4px 16px rgba(16, 185, 129, 0.25);
}

.zone-winner-banner .trophy-icon {
    font-size: 28px;
}

.zone-winner-banner .winner-title {
    font-weight: 800;
    font-size: 14px;
    color: var(--accent-emerald);
}

.zone-winner-banner .winner-subtitle {
    font-size: 11px;
    color: var(--text-muted);
}

.zone-winner-banner .winner-price {
    font-size: 18px;
    font-weight: 800;
    color: var(--accent-emerald);
    white-space: nowrap;
}

.zone-league-table {
    width: 100%;
    font-size: 12px;
}

.zone-league-table tr {
    cursor: pointer;
    transition: background 0.2s ease;
}

.zone-league-table tr:hover {
    background: rgba(6, 182, 212, 0.12) !important;
}

.zone-league-table td {
    padding: 10px 8px;
}

.saving-tag-green {
    color: var(--accent-emerald);
    font-weight: 700;
    font-size: 11px;
}

.saving-tag-red {
    color: #ef4444;
    font-size: 11px;
}

.zone-radius-btns {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 4px;
}

.zone-radius-btn {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-muted);
    padding: 8px 4px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    text-align: center;
    transition: all 0.2s ease;
}

.zone-radius-btn:hover {
    border-color: var(--accent-cyan);
    color: var(--text-main);
}

.zone-radius-btn.active {
    background: var(--accent-cyan);
    border-color: var(--accent-cyan);
    color: #fff;
    box-shadow: 0 0 10px rgba(6, 182, 212, 0.4);
}

.btn-secondary-sm {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-muted);
    padding: 8px 12px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    transition: all 0.2s ease;
}

.btn-secondary-sm.active {
    background: rgba(6, 182, 212, 0.15);
    border-color: var(--accent-cyan);
    color: var(--accent-cyan);
}

/* ─── Legend Panel ───────────────────────────────────────────────── */
.legend-panel {
    position: absolute;
    bottom: 30px;
    left: 20px;
    width: 340px;
    padding: 14px 18px;
    z-index: 900;
}

.legend-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: 12px;
    margin-bottom: 8px;
    color: var(--text-muted);
}

.badge {
    background: rgba(6, 182, 212, 0.15);
    color: var(--accent-cyan);
    padding: 2px 8px;
    border-radius: 4px;
    font-weight: 600;
    font-size: 11px;
}

/* No gradient is declared here on purpose. app.js paints it from heatGradient,
   the same object the heat layer and cluster circles use. The stops were
   previously duplicated in this file and had drifted (30% here vs 40% in the JS),
   so the legend described colours the map was not drawing. */
.gradient-bar {
    height: 10px;
    border-radius: 5px;
    background: var(--border-glass);
    margin-bottom: 5px;
}

/* No data for this fuel and brand: flatten the bar so it does not imply a scale
   that has nothing on it. */
.gradient-bar.is-empty {
    background: var(--border-glass);
    opacity: 0.45;
}

/* Ticks are absolutely positioned so each price sits directly beneath the colour
   it belongs to, which flexbox spacing could not guarantee for uneven stops. */
.legend-ticks {
    position: relative;
    height: 14px;
    font-size: 11px;
    font-weight: 600;
    color: var(--text-main);
}

.legend-tick {
    position: absolute;
    top: 0;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.legend-footnote {
    margin-top: 4px;
    font-size: 10px;
    color: var(--text-muted);
    line-height: 1.35;
}

/* ─── Detail Drawer ──────────────────────────────────────────────── */
.detail-drawer {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 420px;
    max-height: calc(100vh - 104px);
    overflow-y: auto;
    padding: 24px;
    z-index: 950;
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
    transform: translateX(460px);
    opacity: 0;
    pointer-events: none;
}

.detail-drawer.open {
    transform: translateX(0);
    opacity: 1;
    pointer-events: auto;
}

.btn-close-drawer {
    /* Keep the close target above the sticky mobile resize handle. */
    z-index: 6;
    position: absolute;
    top: 16px;
    right: 16px;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 22px;
    cursor: pointer;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 6px;
    transition: all 0.2s;
}
.btn-close-drawer:hover { background: var(--bg-input); color: var(--text-main); }

.drawer-header-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 8px;
    padding-right: 32px;
}

.btn-star-station {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-muted);
    padding: 4px 10px;
    border-radius: 20px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 5px;
    transition: all 0.2s ease;
}

.btn-star-station:hover {
    border-color: var(--accent-amber);
    color: var(--accent-amber);
}

.btn-star-station.starred {
    background: rgba(245, 158, 11, 0.15);
    border-color: var(--accent-amber);
    color: var(--accent-amber);
}

.brand-badge {
    display: inline-block;
    background: var(--accent-cyan);
    color: #000;
    font-weight: 700;
    font-size: 11px;
    padding: 3px 10px;
    border-radius: 12px;
    text-transform: uppercase;
}

.drawer-header h2 {
    font-size: 18px;
    font-weight: 700;
    margin-bottom: 4px;
    color: var(--text-main);
}

.drawer-sub {
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.5;
    margin-bottom: 20px;
}

.price-cards-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 10px;
    margin-bottom: 20px;
}

.price-card {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    padding: 12px;
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    transition: background 0.3s ease;
}

.fuel-tag { font-size: 11px; color: var(--text-muted); margin-bottom: 4px; }

.price-num {
    font-size: 22px;
    font-weight: 800;
    color: var(--accent-emerald);
}

.unit { font-size: 10px; color: var(--text-muted); }

.chart-container {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    padding: 16px;
}

.chart-container h3 {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 12px;
    display: flex;
    align-items: center;
    gap: 6px;
}

.station-history-canvas { position: relative; height: 260px; margin-top: 12px; }
canvas#historyChart { width: 100% !important; height: 100% !important; }
#stationHistoryDays { min-height: 44px; padding: 6px; background: var(--bg-input); color: var(--text-primary); border: 1px solid var(--border-glass); border-radius: 6px; }
#stationHistoryStatus, #stationForecastStatus { font-size: 12px; line-height: 1.5; margin-top: 10px; }

/* ─── Station Markers ────────────────────────────────────────────── */
.marker-container { background: transparent !important; border: none !important; }

.custom-leaflet-marker {
    background: var(--marker-bg);
    border: 1.5px solid var(--accent-cyan);
    color: var(--text-main);
    border-radius: 20px;
    padding: 3px 9px;
    font-size: 11px;
    font-weight: 700;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
    white-space: nowrap;
    backdrop-filter: blur(6px);
    transition: background 0.3s ease, color 0.3s ease;
}

/* ─── Leaflet Popup Dark/Light ───────────────────────────────────── */
.leaflet-popup-content-wrapper {
    background: var(--bg-card) !important;
    border: 1px solid var(--border-glass) !important;
    border-radius: var(--radius-md) !important;
    box-shadow: var(--shadow-glow) !important;
    color: var(--text-main) !important;
    backdrop-filter: blur(16px);
}
.leaflet-popup-tip { background: var(--bg-card) !important; }

/* ─── Marker Clusters ────────────────────────────────────────────── */
.cluster-icon-container { background: transparent !important; border: none !important; }

/* Cluster fill encodes the mean price of its stations, on the same ramp as the
   heat layer — zoomed out, that is what makes dear areas legible at a glance.
   Size still tracks how many stations are grouped, but colour no longer does:
   having both meanings share one channel made neither readable. */
.custom-cluster-marker {
    width: 46px;
    height: 46px;
    border-radius: 50%;
    background: var(--bg-card);
    border: 2px solid rgba(255, 255, 255, 0.55);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    line-height: 1.05;
    box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
    transition: transform 0.2s ease;
}

.custom-cluster-marker:hover {
    transform: scale(1.12);
}

/* Fallback only. app.js sets colour inline per circle, chosen from the fill's
   luminance, because the viridis ramp runs from near-black indigo to bright
   yellow — no single text colour stays legible across it. */
.custom-cluster-marker.priced {
    color: #f8fafc;
}

.custom-cluster-marker .cluster-price {
    font-weight: 800;
    font-size: 14px;
    font-variant-numeric: tabular-nums;
}

.custom-cluster-marker .cluster-count {
    font-weight: 600;
    font-size: 9px;
    opacity: 0.75;
}

/* No reading for this fuel. The border is dashed and the fill transparent because
   the ramp itself passes through grey around the blue-to-amber midpoint — a solid
   grey circle would be ambiguous with a genuinely mid-priced area. */
.custom-cluster-marker.no-price {
    background: transparent;
    border: 2px dashed var(--text-muted);
    color: var(--text-muted);
    backdrop-filter: blur(10px);
}

.custom-cluster-marker.medium { width: 52px; height: 52px; }
.custom-cluster-marker.medium .cluster-price { font-size: 15px; }
.custom-cluster-marker.large  { width: 58px; height: 58px; }
.custom-cluster-marker.large .cluster-price { font-size: 16px; }

/* ─── Route Planner Drawer & Analytics Modal ───────────────────────── */
.route-drawer {
    position: absolute;
    top: 20px;
    right: 20px;
    width: 440px;
    max-height: calc(100vh - 104px);
    overflow-y: auto;
    padding: 24px;
    z-index: 950;
    transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.3s ease;
    transform: translateX(480px);
    opacity: 0;
    pointer-events: none;
}

.route-drawer.open {
    transform: translateX(0);
    opacity: 1;
    pointer-events: auto;
}

.route-form {
    display: flex;
    flex-direction: column;
    gap: 12px;
    margin-bottom: 20px;
}

.route-input-group {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.route-input-group label {
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    color: var(--text-muted);
}

.route-input-group input {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--text-main);
    padding: 9px 12px;
    border-radius: var(--radius-md);
    font-size: 13px;
    outline: none;
}

.btn-primary-full {
    background: linear-gradient(135deg, var(--accent-cyan), #3b82f6);
    color: white;
    border: none;
    padding: 11px;
    border-radius: var(--radius-md);
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    transition: all 0.2s ease;
    box-shadow: 0 4px 14px rgba(6, 182, 212, 0.3);
    margin-top: 4px;
}

.btn-primary-full:hover {
    transform: translateY(-1px);
    box-shadow: 0 6px 18px rgba(6, 182, 212, 0.5);
}

.route-summary-cards {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-bottom: 18px;
}

.summary-card {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    padding: 10px 8px;
    border-radius: var(--radius-md);
    display: flex;
    flex-direction: column;
    align-items: center;
}

.summary-card .lbl { font-size: 10px; color: var(--text-muted); text-transform: uppercase; }
.summary-card .val { font-size: 16px; font-weight: 800; color: var(--text-main); }
.summary-card.highlight { border-color: rgba(16, 185, 129, 0.4); background: rgba(16, 185, 129, 0.1); }
.summary-card.highlight .val { color: var(--accent-emerald); }

.route-stations-title {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 10px;
}

.route-stations-list {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.route-station-card {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    padding: 10px 12px;
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: all 0.2s ease;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

.route-station-card:hover {
    border-color: var(--accent-cyan);
    background: rgba(6, 182, 212, 0.08);
}

/* ─── Analytics Modal ──────────────────────────────────────────────── */
.modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(8px);
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
}

/* ─── Analytics Fuel Selector Tabs ────────────────────────────────── */
.modal-header-top {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}

.analytics-fuel-tabs {
    display: flex;
    gap: 6px;
    background: var(--bg-input);
    padding: 4px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-glass);
}

.analytics-fuel-tab {
    background: transparent;
    border: none;
    color: var(--text-muted);
    padding: 6px 14px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-size: 12px;
    font-weight: 600;
    transition: all 0.2s ease;
}

.analytics-fuel-tab:hover {
    color: var(--text-main);
}

.analytics-fuel-tab.active {
    background: var(--accent-cyan);
    color: #fff;
    box-shadow: 0 0 10px rgba(6, 182, 212, 0.4);
}

.analytics-modal {
    width: 900px;
    max-width: 95vw;
    max-height: 85vh;
    overflow-y: auto;
    padding: 28px;
    position: relative;
}

.modal-header h2 { font-size: 20px; font-weight: 800; color: var(--text-main); }

.motorway-banner {
    background: rgba(245, 158, 11, 0.12);
    border: 1px solid rgba(245, 158, 11, 0.4);
    border-radius: var(--radius-md);
    padding: 12px 16px;
    margin: 16px 0 20px 0;
    display: flex;
    align-items: center;
    gap: 14px;
    font-size: 12px;
    color: var(--text-main);
}

.analytics-tables-grid {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 20px;
}

@media (max-width: 800px) {
    .analytics-tables-grid { grid-template-columns: 1fr; }
}

.table-card h3 {
    font-size: 13px;
    color: var(--text-muted);
    margin-bottom: 12px;
}

.analytics-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 12px;
}

.analytics-table th {
    text-align: left;
    padding: 8px;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-glass);
    font-size: 11px;
    text-transform: uppercase;
}

.analytics-table td {
    padding: 9px 8px;
    border-bottom: 1px solid rgba(255, 255, 255, 0.04);
}

.analytics-table tr:hover td {
    background: rgba(255, 255, 255, 0.04);
}

/* ─── Mobile Responsiveness ───────────────────────────────────────── */
@media (max-width: 640px) {
    .control-panel {
        top: 10px;
        left: 10px;
        right: 10px;
        width: auto;
        padding: 14px;
        max-height: calc(100vh - 84px);
    }
    
    .detail-drawer {
        top: auto;
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        max-height: 80vh;
        border-radius: 20px 20px 0 0;
        transform: translateY(100%);
    }

    .detail-drawer.open {
        transform: translateY(0);
    }

    .legend-panel {
        bottom: 15px;
        left: 10px;
        width: calc(100% - 20px);
    }
    
    .stats-ticker {
        display: none;
    }
}

/* ─── Trends Modal ──────────────────────────────────────────────────────── */
.trend-chart-card {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    padding: 16px;
    margin-top: 16px;
    height: 320px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.trend-chart-card canvas {
    flex: 1;
    min-height: 0;
}

.trend-range-tabs {
    display: flex;
    gap: 6px;
    flex-wrap: wrap;
}

/* ─── Server-rendered area pages ────────────────────────────────────────── */
/* The area pages share this stylesheet with the map app, which locks scrolling on
   BOTH html and body so the fullscreen map cannot be dragged around. Overriding
   `body` alone left `html { overflow: hidden }` in force and the page could not be
   scrolled at all — so `:root` has to be released too, which only these pages do. */
html.seo-page-root {
    overflow: auto;
    height: auto;
}

body.seo-page {
    background: var(--bg-base);
    color: var(--text-main);
    font-family: 'Inter', system-ui, sans-serif;
    overflow: auto;
    height: auto;
    min-height: 100%;
}

.seo-wrap {
    max-width: 900px;
    margin: 0 auto;
    padding: 24px 20px 60px;
}

.seo-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 12px;
    padding-bottom: 18px;
    border-bottom: 1px solid var(--border-glass);
}

.seo-logo {
    font-size: 20px;
    font-weight: 800;
    color: var(--text-main);
    text-decoration: none;
}

.seo-logo span { color: var(--accent-cyan); }

.seo-header nav a {
    color: var(--text-muted);
    text-decoration: none;
    margin-left: 16px;
    font-size: 14px;
    font-weight: 600;
}

.seo-header nav a:hover { color: var(--accent-cyan); }

.seo-page h1 {
    font-size: clamp(24px, 4vw, 34px);
    font-weight: 800;
    margin: 28px 0 10px;
    line-height: 1.2;
}

.seo-lead {
    color: var(--text-muted);
    font-size: 15px;
    line-height: 1.6;
    margin-bottom: 24px;
}

.seo-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: 12px;
    margin-bottom: 28px;
}

.seo-stat {
    background: var(--bg-card);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.seo-stat .lbl {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    font-weight: 600;
}

.seo-stat .val {
    font-size: 24px;
    font-weight: 800;
    color: var(--accent-emerald);
}

.seo-stat .muted,
.seo-table .muted {
    font-size: 11px;
    color: var(--text-muted);
    font-weight: 500;
}

.seo-table {
    width: 100%;
    border-collapse: collapse;
    background: var(--bg-card);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    overflow: hidden;
    font-size: 14px;
}

.seo-table th {
    text-align: left;
    padding: 12px 14px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    background: var(--bg-input);
    border-bottom: 1px solid var(--border-glass);
}

.seo-table td {
    padding: 12px 14px;
    border-bottom: 1px solid var(--border-glass);
    vertical-align: top;
}

.seo-table tr:last-child td { border-bottom: none; }

.seo-area-list {
    list-style: none;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 10px;
}

.seo-area-list a {
    display: block;
    padding: 14px 16px;
    background: var(--bg-card);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    color: var(--text-main);
    text-decoration: none;
    font-weight: 600;
    font-size: 14px;
    transition: border-color 0.2s, color 0.2s;
}

.seo-area-list a:hover {
    border-color: var(--accent-cyan);
    color: var(--accent-cyan);
}

.seo-cta { margin-top: 28px; }

.seo-btn {
    display: inline-block;
    padding: 13px 22px;
    background: var(--accent-cyan);
    color: #06121a;
    font-weight: 700;
    border-radius: var(--radius-md);
    text-decoration: none;
    font-size: 15px;
}

.seo-footer {
    margin-top: 40px;
    padding-top: 18px;
    border-top: 1px solid var(--border-glass);
    color: var(--text-muted);
    font-size: 12px;
    line-height: 1.6;
}

/* ─── Affiliate block (area pages only) ──────────────────────────────────── */
/* Visually subordinate to the price table on purpose. It sits below the map call
   to action, and is styled to read as an aside rather than competing with the
   data the visitor actually came for. */
.aff-block {
    margin-top: 44px;
    padding-top: 20px;
    border-top: 1px solid var(--border-glass);
}

.aff-head {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 14px;
}

.aff-head h2 {
    font-size: 16px;
    font-weight: 700;
    color: var(--text-main);
    margin: 0;
}

/* Explicit advertising label. The ASA expects affiliate content to be
   identifiable at a glance, not only from small print underneath. */
.aff-tag-label {
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-muted);
    border: 1px solid var(--border-glass);
    border-radius: 4px;
    padding: 2px 6px;
}

.aff-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
    gap: 10px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.aff-link {
    display: flex;
    flex-direction: column;
    gap: 4px;
    height: 100%;
    padding: 12px 14px;
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    text-decoration: none;
    transition: border-color 0.2s ease, transform 0.2s ease;
}

.aff-link:hover {
    border-color: var(--accent-cyan);
    transform: translateY(-1px);
}

.aff-label {
    font-size: 14px;
    font-weight: 600;
    color: var(--text-main);
}

.aff-blurb {
    font-size: 12px;
    line-height: 1.45;
    color: var(--text-muted);
}

.aff-disclosure {
    margin-top: 14px;
    font-size: 11px;
    line-height: 1.6;
    color: var(--text-muted);
    max-width: 68ch;
}

/* ─── Zone / commute alert boxes ────────────────────────────────────────── */
.alert-box {
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    padding: 14px;
    background: var(--bg-input);
    margin-top: 12px;
}

.alert-status {
    font-size: 12px;
    line-height: 1.5;
    margin-top: 8px;
    min-height: 1em;
}

.alert-status.ok  { color: var(--accent-emerald); }
.alert-status.err { color: #ef4444; }

/* ─── Live road conditions panel ────────────────────────────────────────── */
.traffic-panel {
    margin-top: 14px;
    padding: 12px 14px;
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    background: var(--bg-input);
}

.traffic-head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
}

.traffic-dot {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    margin-top: 4px;
    flex-shrink: 0;
    background: var(--text-muted);
}

.traffic-dot.level-clear    { background: var(--accent-emerald); box-shadow: 0 0 8px rgba(16,185,129,0.6); }
.traffic-dot.level-moderate { background: var(--accent-amber);   box-shadow: 0 0 8px rgba(245,158,11,0.6); }
.traffic-dot.level-busy     { background: #f97316;               box-shadow: 0 0 8px rgba(249,115,22,0.6); }
.traffic-dot.level-heavy    { background: #ef4444;               box-shadow: 0 0 8px rgba(239,68,68,0.6); }
.traffic-dot.level-closed   { background: var(--accent-purple);  box-shadow: 0 0 8px rgba(139,92,246,0.6); }

.traffic-label {
    font-size: 13px;
    font-weight: 700;
    color: var(--text-main);
}

.traffic-detail {
    font-size: 11px;
    color: var(--text-muted);
    margin-top: 2px;
    line-height: 1.5;
}

.traffic-caveat {
    font-size: 10px;
    color: var(--text-muted);
    opacity: 0.8;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--border-glass);
    line-height: 1.5;
}

/* ─── 30-day price projection ───────────────────────────────────────────── */
.forecast-chart-wrap {
    height: 260px;
    margin: 14px 0 6px;
}

.forecast-rising  { color: #ef4444 !important; }
.forecast-falling { color: var(--accent-emerald) !important; }
.forecast-steady  { color: var(--text-muted) !important; }

.forecast-assumptions {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
    gap: 8px;
    margin-top: 12px;
}

.fa-item {
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-sm);
    padding: 8px 10px;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fa-item .k {
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    font-weight: 600;
}

.fa-item .v {
    font-size: 14px;
    font-weight: 700;
    color: var(--text-main);
}

.forecast-markets {
    margin-top: 14px;
    padding-top: 12px;
    border-top: 1px solid var(--border-glass);
}

.forecast-markets-title {
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--text-muted);
    font-weight: 700;
    margin-bottom: 8px;
}

.forecast-market {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 12px;
    padding: 8px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-sm);
    margin-bottom: 6px;
    text-decoration: none;
    color: var(--text-main);
    font-size: 12px;
}

.forecast-market:hover { border-color: var(--accent-purple); }
.forecast-market .fm-q { flex: 1; line-height: 1.4; }
.forecast-market .fm-p { font-weight: 800; color: var(--accent-purple); white-space: nowrap; }

.forecast-caveat {
    font-size: 10px;
    color: var(--text-muted);
    opacity: 0.85;
    line-height: 1.6;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px solid var(--border-glass);
}

/* ─── Toasts ────────────────────────────────────────────────────────────── */
/* Push failures were console-only, so a broken alert looked like a working
   one. These surface the reason where the user can actually see it. */
.toast-host {
    position: fixed;
    bottom: 20px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 4000;
    display: flex;
    flex-direction: column;
    gap: 8px;
    width: min(520px, calc(100vw - 32px));
    pointer-events: none;
}

.toast {
    position: relative;
    pointer-events: auto;
    background: var(--bg-card);
    border: 1px solid var(--border-glass);
    border-left-width: 3px;
    border-radius: var(--radius-md);
    padding: 12px 38px 12px 14px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--text-main);
    box-shadow: var(--shadow-glow);
    backdrop-filter: blur(12px);
    animation: toast-in 0.22s ease-out;
}

.toast-ok   { border-left-color: var(--accent-emerald); }
.toast-warn { border-left-color: var(--accent-amber); }
.toast-info { border-left-color: var(--accent-cyan); }

.toast-close {
    position: absolute;
    top: 6px;
    right: 8px;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
}

.toast-close:hover { color: var(--text-main); background: var(--bg-input); }
.toast-close:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 1px; }

@keyframes toast-in {
    from { opacity: 0; transform: translateY(10px); }
    to   { opacity: 1; transform: translateY(0); }
}

@media (max-width: 640px) {
    .toast-host { bottom: 12px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE LAYOUT
   The control panel is a 360px-wide, near-full-height floating block. On a
   phone that covers the entire map, and six vertical fuel tabs made it worse —
   you could not pin or search. On small screens it becomes a slim top bar
   showing only search and a horizontal fuel strip, with everything else behind
   a Filters toggle.
   ═══════════════════════════════════════════════════════════════════════════ */

.btn-toggle-controls { display: none; }

@media (max-width: 820px) {

    /* ── Header: icons only, no wrapping ───────────────────────────────── */
    .header-bar { padding: 8px 10px; gap: 6px; }
    .logo-text h1 { font-size: 15px; }
    .header-right { gap: 4px; }
    .btn-header-action span,
    .sync-status span { display: none; }
    .btn-header-action { padding: 8px 10px; }

    /* ── Filters toggle ────────────────────────────────────────────────── */
    .btn-toggle-controls {
        display: flex;
        align-items: center;
        gap: 6px;
        position: absolute;
        right: 10px;
        bottom: 14px;
        z-index: 1000;
        padding: 11px 15px;
        border-radius: 999px;
        border: 1px solid var(--border-glass);
        background: var(--bg-card);
        color: var(--text-main);
        font-size: 13px;
        font-weight: 700;
        box-shadow: var(--shadow-glow);
        backdrop-filter: blur(12px);
        cursor: pointer;
    }

    /* ── Collapsed: a slim top bar, map fully usable ───────────────────── */
    .control-panel {
        top: 0;
        left: 0;
        right: 0;
        width: auto;
        max-height: none;
        padding: 8px 10px;
        gap: 8px;
        border-radius: 0 0 var(--radius-md) var(--radius-md);
        overflow: visible;
    }

    /* Hidden until Filters is tapped */
    #sectionStats,
    #sectionMapStyle,
    #sectionFilters { display: none; }

    /* Search first: it is the main way to get somewhere on a phone */
    #sectionSearch { order: -1; }
    #sectionSearch .section-label { display: none; }

    #sectionFuel .section-label { display: none; }

    /* ── Expanded: full controls as a scrollable sheet ─────────────────── */
    .control-panel.expanded {
        max-height: 78vh;
        overflow-y: auto;
        padding-bottom: 16px;
    }

    .control-panel.expanded #sectionStats,
    .control-panel.expanded #sectionMapStyle,
    .control-panel.expanded #sectionFilters { display: flex; }

    .control-panel.expanded #sectionFilters { flex-direction: column; gap: 10px; }
    .control-panel.expanded #sectionFuel .section-label,
    .control-panel.expanded #sectionSearch .section-label { display: block; }

    /* ── Keep the legend clear of the collapsed bar ────────────────────── */
    .legend-panel {
        bottom: 70px;
        left: 10px;
        right: 74px;
        width: auto;
    }

    /* ── Side drawers become full-width sheets ─────────────────────────── */
    .route-drawer,
    .cheapest-sidebar,
    .zone-sidebar {
        width: 100%;
        max-width: 100%;
    }

    /* Bigger touch targets */
    .search-box input { min-height: 42px; font-size: 15px; }
    .btn-search { min-width: 44px; min-height: 42px; }
    .custom-select { min-height: 42px; font-size: 14px; }
}

@media (max-width: 480px) {
    /* Five prices will not fit legibly on a phone-width bar, so keep the two
       ends and the midpoint and drop the intermediate stops. */
    .legend-panel .legend-ticks { font-size: 10px; }
    .legend-tick[data-stop="0.4"],
    .legend-tick[data-stop="0.85"] { display: none; }
    .btn-toggle-controls span { display: none; }
    .btn-toggle-controls { padding: 12px; }
}

/* ─── Map zoom control ──────────────────────────────────────────────────── */
/* Moved to bottom-right: within thumb reach on a phone and clear of the
   header. The cheapest/zone sidebar tabs sit at top:100px so there is no
   conflict on desktop. */
.leaflet-bottom.leaflet-right {
    margin-bottom: 6px;
    margin-right: 6px;
}

/* Basemap credit. Leaflet's default is a white box, which glared over the
   dark vector tiles; a neutral dark translucent one reads on dark, light and
   satellite alike. */
.leaflet-control-attribution {
    background: rgba(15, 23, 42, 0.72) !important;
    color: rgba(226, 232, 240, 0.85) !important;
    font-size: 10px;
    padding: 2px 6px;
    border-top-left-radius: 6px;
    backdrop-filter: blur(4px);
    -webkit-backdrop-filter: blur(4px);
}
.leaflet-control-attribution a {
    color: #67e8f9 !important;
    text-decoration: none;
}
.leaflet-control-attribution a:hover { text-decoration: underline; }

.leaflet-touch .leaflet-control-zoom a,
.leaflet-control-zoom a {
    width: 34px;
    height: 34px;
    line-height: 34px;
    background: var(--bg-card);
    color: var(--text-main);
    border-color: var(--border-glass);
    backdrop-filter: blur(12px);
}

.leaflet-control-zoom a:hover {
    background: var(--bg-input);
    color: var(--accent-cyan);
}

@media (max-width: 820px) {
    /* Sit above the Filters button rather than under it, and enlarge the
       targets for touch. */
    .leaflet-bottom.leaflet-right { margin-bottom: 66px; }

    .leaflet-touch .leaflet-control-zoom a,
    .leaflet-control-zoom a {
        width: 44px;
        height: 44px;
        line-height: 44px;
        font-size: 20px;
    }

    /* Keep the legend clear of both the zoom stack and the Filters button. */
    .legend-panel { right: 64px; }
}

/* ─── "Near me" ─────────────────────────────────────────────────────────── */
.btn-near-me {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    /* Grows to fill its wrapped row: this is the primary action, so it should look
       like one rather than a 105px stub next to a gap. */
    flex: 1 1 auto;
    padding: 0 14px;
    min-height: 42px;
    border-radius: var(--radius-md);
    border: 1px solid var(--accent-cyan);
    background: rgba(6, 182, 212, 0.14);
    color: var(--accent-cyan);
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    white-space: nowrap;
}

.btn-near-me:hover:not(:disabled) { background: rgba(6, 182, 212, 0.24); }
.btn-near-me:disabled { opacity: 0.65; cursor: default; }
.btn-near-me:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; }

.near-me-pin {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent-cyan);
    color: #06121a;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 14px;
    box-shadow: 0 0 0 4px rgba(6, 182, 212, 0.3), 0 2px 8px rgba(0,0,0,0.5);
}

.nearby-results {
    margin-top: 10px;
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    background: var(--bg-input);
    overflow: hidden;
}

.nearby-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 8px 10px;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border-glass);
}

.nearby-close {
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    padding: 0 4px;
}

.nearby-close:hover { color: var(--text-main); }

.nearby-item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 9px 10px;
    background: none;
    border: none;
    border-bottom: 1px solid var(--border-glass);
    color: var(--text-main);
    cursor: pointer;
    text-align: left;
    font-family: inherit;
}

.nearby-item:last-child { border-bottom: none; }
.nearby-item:hover { background: rgba(255,255,255,0.04); }
.nearby-item:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: -2px; }

.nearby-price {
    font-size: 15px;
    font-weight: 800;
    color: var(--accent-emerald);
    min-width: 52px;
}

.nearby-info { display: flex; flex-direction: column; flex: 1; min-width: 0; }

.nearby-brand {
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nearby-sub { font-size: 10px; color: var(--text-muted); }

.nearby-best {
    font-size: 9px;
    font-weight: 800;
    text-transform: uppercase;
    color: var(--accent-emerald);
    background: rgba(16,185,129,0.16);
    padding: 2px 6px;
    border-radius: 4px;
    white-space: nowrap;
}

.nearby-diff {
    font-size: 10px;
    color: var(--text-muted);
    white-space: nowrap;
}

.nearby-empty { padding: 12px 10px; font-size: 12px; color: var(--text-muted); }

/* ─── Zoom hint (viewport marker loading) ───────────────────────────────── */
.zoom-hint {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 850;
    pointer-events: none;
    padding: 9px 16px;
    border-radius: 999px;
    background: var(--bg-card);
    border: 1px solid var(--border-glass);
    color: var(--text-muted);
    font-size: 12px;
    font-weight: 600;
    box-shadow: var(--shadow-glow);
    backdrop-filter: blur(10px);
    display: flex;
    align-items: center;
    gap: 8px;
}

@media (max-width: 820px) {
    /* Keep the search row usable: input shrinks, Near me stays tappable. */
    .search-box { flex-wrap: nowrap; }
    .btn-near-me span { display: none; }
    .btn-near-me { padding: 0 12px; min-width: 44px; justify-content: center; }
    #sectionSearch .nearby-results { max-height: 42vh; overflow-y: auto; }
    .zoom-hint { font-size: 11px; padding: 8px 12px; text-align: center; }
}

/* ─── Station drawer: freshness + navigation ───────────────────────────── */
.drawer-freshness {
    font-size: 11px;
    color: var(--text-muted);
    margin: 6px 0 0;
    line-height: 1.5;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.drawer-actions {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 12px;
}

.btn-navigate {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    flex: 1;
    min-height: 44px;
    padding: 0 16px;
    border-radius: var(--radius-md);
    background: var(--accent-cyan);
    color: #06121a;
    font-size: 14px;
    font-weight: 800;
    text-decoration: none;
}

.btn-navigate:hover { filter: brightness(1.1); }
.btn-navigate:focus-visible { outline: 2px solid var(--text-main); outline-offset: 2px; }

.btn-navigate-alt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 44px;
    min-height: 44px;
    border-radius: var(--radius-md);
    border: 1px solid var(--border-glass);
    background: var(--bg-input);
    color: var(--text-muted);
    font-size: 16px;
    cursor: pointer;
    text-decoration: none;
}

.btn-navigate-alt:hover { color: var(--accent-cyan); border-color: var(--accent-cyan); }
.btn-navigate-alt:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; }

/* ─── First-run onboarding ─────────────────────────────────────────────── */
.onboarding {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    z-index: 1500;
    width: min(460px, calc(100vw - 32px));
    max-height: min(84vh, 640px);
    overflow-y: auto;
    padding: 22px;
    border-radius: var(--radius-lg);
    background: var(--bg-card);
    border: 1px solid var(--border-glass);
    box-shadow: var(--shadow-glow);
    backdrop-filter: blur(18px);
}

.onboarding h3 {
    font-size: 17px;
    font-weight: 800;
    margin: 0 0 4px;
    display: flex;
    align-items: center;
    gap: 8px;
}

.onboarding h3 .ic { color: var(--accent-cyan); }

.onboarding-close {
    position: absolute;
    top: 10px;
    right: 12px;
    background: none;
    border: none;
    color: var(--text-muted);
    font-size: 22px;
    line-height: 1;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: var(--radius-sm);
}

.onboarding-close:hover { color: var(--text-main); background: var(--bg-input); }
.onboarding-close:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 1px; }

.onboarding-list {
    list-style: none;
    padding: 0;
    margin: 14px 0 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.onboarding-list li {
    display: flex;
    align-items: flex-start;
    gap: 11px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--text-muted);
}

.onboarding-list strong { color: var(--text-main); font-weight: 700; }

.ob-icon {
    flex-shrink: 0;
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
    background: var(--bg-input);
    border: 1px solid var(--border-glass);
    color: var(--accent-cyan);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 12px;
}

.onboarding-cta {
    width: 100%;
    margin-top: 18px;
    min-height: 44px;
    border: none;
    border-radius: var(--radius-md);
    background: var(--accent-cyan);
    color: #06121a;
    font-size: 14px;
    font-weight: 800;
    cursor: pointer;
}

.onboarding-cta:hover { filter: brightness(1.1); }
.onboarding-cta:focus-visible { outline: 2px solid var(--text-main); outline-offset: 2px; }

@media (max-width: 820px) {
    .onboarding { padding: 18px; max-height: 80vh; }
    .onboarding-list li { font-size: 12.5px; }
}

/* ─── Data availability banner ─────────────────────────────────────────── */
.data-banner {
    position: absolute;
    top: 12px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 1200;
    display: flex;
    align-items: flex-start;
    gap: 11px;
    width: min(560px, calc(100vw - 24px));
    padding: 12px 15px;
    border-radius: var(--radius-md);
    background: rgba(69, 26, 3, 0.94);
    border: 1px solid var(--accent-amber);
    color: #fde68a;
    font-size: 12.5px;
    line-height: 1.55;
    box-shadow: var(--shadow-glow);
    backdrop-filter: blur(12px);
}

.data-banner .ic { color: var(--accent-amber); font-size: 17px; margin-top: 1px; }
.data-banner strong { display: block; color: #fff; font-size: 13px; margin-bottom: 2px; }

@media (max-width: 820px) {
    /* Clear of the collapsed control bar. */
    .data-banner { top: 118px; font-size: 12px; padding: 10px 12px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOBILE: BOTTOM NAV + BOTTOM SHEETS
   Six actions cannot fit a phone's header, and the bottom edge is where thumbs
   reach. Side drawers become bottom sheets for the same reason.
   ═══════════════════════════════════════════════════════════════════════════ */

.bottom-nav { display: none; }

@media (max-width: 820px) {

    /* ── Header keeps only identity and the theme toggle ─────────────────── */
    .header-right .btn-header-action { display: none; }

    /* ── Bottom navigation ──────────────────────────────────────────────── */
    .bottom-nav {
        display: flex;
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        z-index: 1300;
        background: var(--header-bg);
        border-top: 1px solid var(--border-glass);
        backdrop-filter: blur(18px);
        padding: 4px 2px calc(4px + env(safe-area-inset-bottom, 0px));
    }

    .bn-item {
        flex: 1;
        min-width: 0;
        min-height: 52px;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        gap: 3px;
        background: none;
        border: none;
        color: var(--text-muted);
        font-family: inherit;
        font-size: 9.5px;
        font-weight: 600;
        cursor: pointer;
        padding: 4px 2px;
        border-radius: var(--radius-sm);
    }

    .bn-item .ic { font-size: 17px; }
    .bn-item:active { background: var(--bg-input); color: var(--accent-cyan); }
    .bn-item:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: -2px; }

    .bn-item span {
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        max-width: 100%;
    }

    /* ── Everything floating must clear the nav bar ──────────────────────── */
    .btn-toggle-controls { bottom: 74px; }
    .leaflet-bottom.leaflet-right { margin-bottom: 126px; }
    .legend-panel { bottom: 130px; }
    .toast-host { bottom: 72px; }

    /* ── Side drawers become bottom sheets ───────────────────────────────── */
    .route-drawer,
    .zone-sidebar {
        top: auto;
        bottom: 0;
        left: 0;
        right: 0;
        width: 100%;
        max-width: 100%;
        height: auto;
        /* 78vh left only 22vh of map, which the collapsed control bar covered
           entirely — so the zone circle was drawn into the one strip that could not
           be seen, and the feature looked broken while working perfectly. These
           sheets show a result *on the map*, so the map has to stay visible. */
        max-height: 52vh;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        transform: translateY(100%);
        transition: transform 0.28s ease;
        overflow-y: auto;
        padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px));
    }

    .route-drawer.open,
    .zone-sidebar.open { transform: translateY(0); }

    /* The detail drawer keeps a decorative handle; the zone and route sheets get a
       real button instead, because on those the height genuinely needs changing. */
    .detail-drawer::before {
        content: '';
        position: sticky;
        top: 6px;
        display: block;
        width: 38px;
        height: 4px;
        margin: 0 auto 10px;
        border-radius: 2px;
        background: var(--border-glass);
    }

    /* Tap target for cycling the sheet height. Sticky so it stays reachable however
       far the content is scrolled — the panel is taller than the sheet at every
       size, so a handle that scrolled away would be unreachable exactly when
       needed. */
    .sheet-grip {
        position: sticky;
        top: 0;
        z-index: 5;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 100%;
        min-height: 28px;
        margin: -6px 0 6px;
        padding: 0;
        border: none;
        background: none;
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
    }

    .sheet-grip-bar {
        width: 44px;
        height: 5px;
        border-radius: 3px;
        background: var(--text-muted);
        opacity: 0.55;
        transition: opacity 0.2s ease, width 0.2s ease;
    }

    .sheet-grip:active .sheet-grip-bar { opacity: 1; width: 56px; }

    /* Snap heights. Peek shows the title and the first control, leaving most of the
       screen as map so the zone circle can be seen and its handle dragged.
       `dvh` follows the viewport as a mobile browser's toolbar collapses and
       reappears; `vh` on Android is the *largest* the viewport ever gets, so a sheet
       sized in vh extends under the toolbar and its lowest controls become
       unreachable. The vh line is the fallback for anything without dvh. */
    .zone-sidebar.sheet-peek,
    .route-drawer.sheet-peek { max-height: 26vh; max-height: 26dvh; }

    .zone-sidebar.sheet-half,
    .route-drawer.sheet-half { max-height: 52vh; max-height: 52dvh; }

    .zone-sidebar.sheet-full,
    .route-drawer.sheet-full { max-height: 88vh; max-height: 88dvh; }

    .detail-drawer { padding-bottom: calc(64px + env(safe-area-inset-bottom, 0px)); }

    /* Modals need room for the nav too. */
    .analytics-modal { max-height: calc(88vh - 56px); }
}

/* Count beside the Favourites overlay toggle. Muted so the label still reads as
   the label, not as a number with a word attached. */
.toggle-count {
    font-size: 10px;
    font-weight: 600;
    color: var(--text-muted);
    margin-left: 2px;
}

/* Visible to screen readers only. Used to pair medal emoji with text that always
   announces correctly, since a bare 🥇 reads as "1st place medal" or, on some
   combinations of platform and screen reader, as nothing at all. */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ─── Affiliate block in the station drawer ──────────────────────────────── */
/* Sits last in the drawer and is styled to read as an aside. The prices, road
   conditions and trend chart are what the drawer is for. */
.drawer-ads {
    margin-top: 22px;
    padding-top: 16px;
    border-top: 1px solid var(--border-glass);
}

.drawer-ads-head {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 10px;
    font-size: 12px;
    font-weight: 600;
    color: var(--text-muted);
}

.drawer-ads-list {
    display: grid;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
}

.drawer-ads-list a {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding: 10px 12px;
    border: 1px solid var(--border-glass);
    border-radius: var(--radius-md);
    text-decoration: none;
    transition: border-color 0.2s ease;
}

.drawer-ads-list a:hover { border-color: var(--accent-cyan); }

.da-label { font-size: 13px; font-weight: 600; color: var(--text-main); }
.da-blurb { font-size: 11.5px; line-height: 1.4; color: var(--text-muted); }

.drawer-ads-note {
    margin-top: 10px;
    font-size: 10.5px;
    line-height: 1.55;
    color: var(--text-muted);
}

/* The "By Area" entries are anchors rather than buttons, because they navigate to
   a server-rendered page instead of opening a panel. These keep them visually
   identical to their button siblings. */
a.btn-header-action { text-decoration: none; }
a.btn-header-action:hover { color: #06121a; }

@media (max-width: 820px) {
    a.bn-item { text-decoration: none; }
}

/* ─── Coloured navigation icons ──────────────────────────────────────────── */
/* Each action gets its own accent so the row is scannable by colour as well as
   shape. It also means the nav still reads as five distinct things if the icon
   font ever fails to load, which is the state it was stuck in for a while. */
#btnOpenZoneFinder    .ic { color: var(--accent-amber); }
#btnOpenRoutePlanner  .ic { color: var(--accent-emerald); }
#btnOpenAnalytics     .ic { color: var(--accent-rose); }
#btnOpenTrends        .ic { color: var(--accent-purple); }
.header-right a[href="/prices"] .ic { color: var(--accent-cyan); }

/* Hover fills the button with the accent, so the icon has to flip to the dark
   text colour or it disappears into the background. */
.btn-header-action:hover .ic { color: #06121a; }

.bn-item[data-proxy="btnNearMe"]           .ic { color: var(--accent-cyan); }
.bn-item[data-proxy="btnOpenZoneFinder"]   .ic { color: var(--accent-amber); }
.bn-item[data-proxy="btnOpenRoutePlanner"] .ic { color: var(--accent-emerald); }
.bn-item[data-proxy="btnOpenTrends"]       .ic { color: var(--accent-purple); }
.bn-item[data-proxy="btnOpenAnalytics"]    .ic { color: var(--accent-rose); }
a.bn-item[href="/prices"]                  .ic { color: var(--accent-cyan); }

/* Panel section headings, so the left column is easier to scan too. */
.section-label .ic { color: var(--accent-cyan); }

/* The star keeps its conventional gold, filled when starred. */
.btn-star-station .ic { color: var(--accent-amber); }

/* ─── Inline SVG icons ───────────────────────────────────────────────────── */
/* Replaces the FontAwesome webfont. Icons are <svg class="ic"><use href="#i-…"/></svg>
   against the sprite inlined at the top of the body.
   Sized in `em` and filled with currentColor so every existing rule that set a
   font-size or a color on an icon keeps working unchanged — that is what made the
   conversion a search-and-replace rather than a redesign. */
.ic {
    width: 1em;
    height: 1em;
    fill: currentColor;
    /* Matches the optical alignment the icon font had against adjacent text. */
    vertical-align: -0.125em;
    flex-shrink: 0;
}

/* Kept because several buttons swap to a spinner while working. */
.fa-spin { animation: ic-spin 1.4s linear infinite; }
@keyframes ic-spin { to { transform: rotate(360deg); } }

@media (max-width: 820px) {
    /* The price legend sits at a fixed offset from the bottom, so it collides with
       an open sheet whatever height that sheet is. It describes the heat surface,
       which is not what the user is looking at while working a zone or a route, so
       it steps aside. :has() is safe here — if a browser lacks it the legend simply
       stays, which is the behaviour we had before. */
    .workspace:has(.zone-sidebar.open) .legend-panel,
    .workspace:has(.route-drawer.open) .legend-panel {
        display: none;
    }
}

@media (max-width: 820px) {
    /* A full-width range input swallows a vertical drag that starts on it: the
       slider claims the gesture and the sheet does not scroll. `pan-y` hands
       vertical movement back to the scroll container while the slider keeps
       horizontal, which matters here because the radius slider spans the panel and
       sits near the top — exactly where a thumb lands to start scrolling.
       The map itself keeps its own gesture handling; this is scoped to the panels. */
    .zone-sidebar input[type="range"],
    .route-drawer input[type="range"],
    .control-panel input[type="range"] {
        touch-action: pan-y;
    }

    /* Same reasoning for the horizontal chip rows: a vertical drag beginning on one
       should scroll the sheet, not fight the row's own horizontal scroll. */
    .zone-radius-btns,
    .fuel-tabs-vertical {
        touch-action: pan-x pan-y;
    }

    /* Momentum scrolling, and stop a drag that reaches the end of the sheet from
       chaining into the page or the map behind it. */
    .zone-sidebar,
    .route-drawer,
    .detail-drawer {
        -webkit-overflow-scrolling: touch;
        overscroll-behavior: contain;
    }
}

@media (max-width: 820px) {
    /* THE reason the panels appeared cut off with no way to scroll.
       .sidebar-content is `height: 100%; overflow: hidden`, which suits the desktop
       layout where the panel is a full-height column. As a bottom sheet the parent's
       height is pinned by max-height, so that 100% resolves to the sheet's height
       and the wrapper clips everything below it — unreachable, because the element
       doing the clipping is not the element that scrolls.
       Releasing both lets the sheet itself scroll the whole content. */
    .zone-sidebar .sidebar-content,
    .cheapest-sidebar .sidebar-content,
    .route-drawer .sidebar-content {
        height: auto;
        overflow: visible;
    }
}

/* Search-first layout and personal tools. */
.personal-toolbar { display:flex; flex-wrap:wrap; gap:6px; margin:8px 0; }
.personal-toolbar button,.personal-tools button,#localShortlist button { border:1px solid var(--border-color,#334155); border-radius:9px; padding:10px 12px; background:var(--bg-input,#172133); color:var(--text-main,#f1f5f9); cursor:pointer; min-height:44px; }
.personal-tools { width:min(760px,calc(100vw - 24px)); max-height:88dvh; padding:20px; border:1px solid var(--border-color,#334155); border-radius:16px; background:var(--bg-panel,#111827); color:var(--text-main,#f1f5f9); overflow:auto; }
.personal-tools::backdrop { background:rgba(0,0,0,.65); }
.tools-heading { display:flex; align-items:center; justify-content:space-between; gap:12px; }
.tools-tabs { display:flex; flex-wrap:wrap; gap:6px; margin:14px 0; }
.tools-tabs button[aria-pressed=true] { border-color:#06b6d4; color:#06b6d4; }
.tool-form { display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:12px; margin:16px 0; padding:14px; border:1px solid #475569; border-radius:12px; }
.tool-form label { display:flex; flex-direction:column; gap:6px; font-size:13px; }
.tool-form input,.tool-form select,.tool-form textarea { width:100%; box-sizing:border-box; border:1px solid #64748b; border-radius:6px; padding:10px; background:var(--bg-input,#172133); color:inherit; min-height:44px; }
.tool-form .tool-check { flex-direction:row; align-items:center; }.tool-check input { width:20px; min-height:20px; }
.tool-form button[type=submit] { align-self:end; border-color:#06b6d4; }
.personal-tools p,.personal-tools footer { font-size:13px; line-height:1.6; margin:12px 0; }
.tool-list article { border-bottom:1px solid #475569; padding:12px 0; }
#toolStatus { color:var(--accent-cyan,#22d3ee); }#toolStatus:empty{display:none;}
#localShortlist { margin-top:12px; }#localShortlist button { display:block; width:100%; text-align:left; margin:6px 0; }#localShortlist span { display:block; font-size:11px; margin-top:5px; }#localShortlist p{font-size:11px;line-height:1.5;}
.map-appearance summary { cursor:pointer; padding:12px 0; }
[inert] { pointer-events:none; }
button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,[tabindex]:focus-visible { outline:3px solid #22d3ee;outline-offset:3px; }
@media(max-width:600px){.tool-form{grid-template-columns:1fr;}.personal-tools{padding:14px;}.personal-toolbar button{font-size:12px;padding:8px;}.tools-tabs button{flex:1 1 30%;font-size:12px;}}
.personal-tools { margin:auto; }
.personal-tools h3 { margin:16px 0 8px; }
.personal-tools footer { border-top:1px solid #475569; padding-top:12px; }
.seo-table { display:block; overflow-x:auto; }
.detail-drawer[aria-hidden=true],.route-drawer[aria-hidden=true],#zoneDrawer[aria-hidden=true] { visibility:hidden; }
@media(max-width:820px){
    .control-panel { max-height:44dvh; overflow-y:auto; overscroll-behavior:contain; }
    .control-panel.expanded { max-height:60dvh; }
    .map-appearance { display:none; }.control-panel.expanded .map-appearance { display:block; }
    .control-panel.expanded .map-appearance #sectionMapStyle { display:flex; }
}
.control-panel .data-banner { position:static; width:auto; max-width:none; margin:8px 0; transform:none; }

.forecast-horizons { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:12px; margin:16px 0; }
.forecast-horizons article { padding:14px; border:1px solid var(--border-glass); border-radius:10px; background:var(--bg-input); }
.forecast-horizons strong { display:block; font-size:20px; margin:10px 0; }
.forecast-horizons p,.forecast-accuracy p,.market-expectation p { font-size:12px; line-height:1.5; margin:8px 0; color:var(--text-muted); }
.forecast-table-scroll { overflow-x:auto; }
.forecast-assumptions small,.forecast-assumptions a { display:block; font-size:11px; margin-top:5px; }
.market-expectation { padding:14px 0; border-bottom:1px solid var(--border-glass); }
.market-expectation a,.forecast-assumptions a { color:var(--accent-cyan); }
.market-expectation summary { cursor:pointer; font-size:12px; }
.market-expectation details p { white-space:pre-wrap; }
@media(max-width:600px){.forecast-horizons{grid-template-columns:1fr;}}

#trendsElectric .forecast-horizons label { display:flex; flex-direction:column; gap:8px; color:var(--text-main); }
#trendsElectric .forecast-horizons input { width:100%; box-sizing:border-box; padding:10px; border:1px solid var(--border-glass); border-radius:8px; background:var(--bg-input); color:var(--text-main); }

/* Results-led discovery */
.results-sheet { position:absolute; top:20px; right:20px; bottom:20px; width:min(440px,40vw); z-index:700; background:var(--bg-panel,#101827); color:var(--text-main); border:1px solid var(--border-color,#334155); border-radius:18px; padding:16px; overflow:auto; box-shadow:0 16px 48px #0005; }
#localShortlist[hidden],.more-menu[hidden],.show-results[hidden] { display:none; }
#localShortlist.results-sheet { margin:0; }
.result-heading,.purchase-title { display:flex; align-items:start; justify-content:space-between; gap:12px; }
.result-heading h2 { font-size:20px; margin:0; }.result-heading p { margin:6px 0; }
.result-options { display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin:12px 0; }
.result-options select { max-width:170px; color:var(--text-main); background:var(--bg-input); padding:10px; border-radius:8px; }
.purchase-card { padding:16px 0; border-top:1px solid var(--border-color,#334155); }.purchase-card h3 { margin:0; font-size:16px; }.purchase-title>strong { font-size:27px; color:var(--accent-cyan); white-space:nowrap; }.purchase-title small { font-size:12px; }
.purchase-card p { font-size:13px; line-height:1.6; margin:8px 0; }.purchase-actions { display:flex; gap:8px; flex-wrap:wrap; }.purchase-actions a { display:inline-flex; align-items:center; border-radius:9px; padding:10px 14px; background:var(--accent-cyan); color:#07141b; font-weight:700; text-decoration:none; min-height:44px; box-sizing:border-box; }
.fresh-price { color:var(--text-main); }.uncertain-price { color:var(--accent-amber,#fbbf24); }.best-choice { border-radius:10px; padding:12px; background:var(--bg-input); line-height:1.5; }
.show-results { position:absolute; right:20px; bottom:100px; z-index:700; padding:14px 20px; background:var(--accent-cyan); color:#07141b; border:0; border-radius:24px; font-weight:700; }
.more-menu { position:absolute; bottom:78px; right:12px; z-index:1600; background:var(--bg-panel,#101827); padding:12px; border:1px solid var(--border-color,#334155); border-radius:14px; display:grid; gap:8px; }.more-menu button,.more-menu a { background:var(--bg-input); color:var(--text-main); border:0; padding:14px; border-radius:8px; text-decoration:none; text-align:left; }
@media(max-width:768px){
 .results-sheet { top:auto; bottom:72px; right:0; left:0; width:auto; max-height:48dvh; padding:16px; border-radius:20px 20px 0 0; }.results-sheet.expanded { max-height:calc(100dvh - 150px); }
 .control-panel.results-active:not(.expanded)>:not(#sectionSearch):not(#dataBanner) { display:none!important; }
 .control-panel.results-active:not(.expanded) .personal-toolbar { display:none; }
 .bottom-nav { grid-template-columns:repeat(4,1fr); }.bn-item { flex:1; }.bn-item span { font-size:13px; }
 .show-results { bottom:90px; }
}
#localShortlist.results-sheet button { display:inline-flex; align-items:center; justify-content:center; width:auto; margin:0; text-align:center; flex:none; }
#localShortlist.results-sheet p { font-size:13px; line-height:1.6; }
#localShortlist .result-options { display:flex; }
#localShortlist .purchase-actions { display:flex; }
.fuel-confirmation { display:block; font-size:10px; line-height:1.4; color:var(--text-muted); }
.personal-tools details>summary { cursor:pointer; padding:12px 0; font-weight:600; }
@media(max-width:768px){.control-panel:not(.expanded){max-height:28dvh;}.control-panel.results-active:not(.expanded) #dataBanner{display:none;}.result-heading h2{font-size:18px;}}
.results-sheet { z-index:925; }
#map { isolation:isolate; }
@media(max-width:820px){
 body.showing-results #legendCard,body.showing-results .leaflet-control-zoom { display:none; }
 body.showing-results #btnToggleControls { bottom:calc(48dvh + 90px); }
}

/* Readable, keyboard-accessible personal journeys and results. */
.skip-link {position:fixed;left:12px;top:-100px;z-index:10000;background:#fff;color:#111;padding:16px;border:3px solid #006b75;}
.skip-link:focus {top:12px;}
:where(button,a,input,select,textarea,summary):focus-visible {outline:3px solid #009ba9;outline-offset:3px;}
#quickJourneys {display:flex;gap:8px;overflow-x:auto;padding:8px 0;max-width:100%;}
#quickJourneys button {flex-shrink:0;min-height:44px;padding:8px 14px;border:1px solid var(--border-color);border-radius:10px;color:var(--text-main);background:var(--bg-input);}
.personal-tools table {width:100%;border-collapse:collapse;font-size:1rem;}
.personal-tools th,.personal-tools td {padding:10px;text-align:left;border-bottom:1px solid var(--border-color);}
.personal-tools caption {text-align:left;padding:8px 0;}
#localShortlist.results-sheet p,.personal-tools p,.personal-tools label,.personal-tools input,.personal-tools select,.personal-tools button {font-size:1rem;line-height:1.5;}
#localShortlist.results-sheet h3 {font-size:1.125rem;}
#localShortlist.results-sheet .purchase-title {gap:12px;flex-wrap:wrap;}
#localShortlist.results-sheet .purchase-title h3 {overflow-wrap:anywhere;}
.personal-tools {max-width:min(760px,calc(100vw - 24px));}
.personal-tools button,.personal-tools input,.personal-tools select,.personal-tools summary {min-height:44px;}
.personal-tools .tool-form {min-width:0;}
.personal-tools input,.personal-tools select {max-width:100%;box-sizing:border-box;}
.saving-explanation {padding:12px;border-left:4px solid var(--accent-cyan);background:var(--bg-input);}
@media(max-width:768px){#quickJourneys{max-width:calc(100vw - 56px);} .personal-tools .tool-form{grid-template-columns:1fr;}#localShortlist.results-sheet .result-options{flex-wrap:wrap;}}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation-duration:0.01ms!important;transition-duration:0.01ms!important;}}
@media(forced-colors:active){button,a,input,select,.purchase-card{border:1px solid ButtonText!important;}:focus-visible{outline:3px solid Highlight!important;}}

html.large-text {font-size:20px;}

.goal-watch label:has(input[name="threshold"]) {display:none;}
