File size: 13,074 Bytes
71c08ae
 
 
 
 
4ccb3e1
 
 
 
 
 
71c08ae
 
 
 
 
 
 
 
57ffa0b
71c08ae
 
 
 
6a9bb08
71c08ae
 
6a9bb08
 
 
 
 
 
 
 
 
71c08ae
 
590c919
 
71c08ae
 
 
 
 
 
 
 
 
 
 
 
 
590c919
 
 
 
 
 
71c08ae
 
 
cd2d39f
 
 
 
 
 
 
 
 
 
 
71c08ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
590c919
71c08ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57ffa0b
 
 
 
 
 
 
 
 
 
 
 
ed70eb7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
590c919
ed70eb7
71c08ae
 
 
 
 
 
 
b0e598e
 
 
 
 
 
 
eea5f65
 
 
 
71c08ae
 
e6a157d
eea5f65
 
 
e6a157d
71c08ae
 
 
 
e6a157d
590c919
e6a157d
 
 
 
 
 
 
 
 
71c08ae
a5762ed
 
 
57ffa0b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ed70eb7
 
 
 
 
 
 
 
 
 
 
 
 
57ffa0b
 
 
 
 
 
 
71c08ae
 
 
 
 
 
a5762ed
 
 
 
 
6a9bb08
 
 
 
 
57ffa0b
71c08ae
6a9bb08
a5762ed
 
6a9bb08
 
 
 
 
71c08ae
 
ed70eb7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
cd2d39f
ed70eb7
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
/* Petrol Map — styles. Loaded by index.html (served from /styles.css). */

html, body { height: 100%; margin: 0; font-family: -apple-system, "Segoe UI", Roboto, sans-serif; }
#map { position: absolute; inset: 0; height: 100vh; height: 100dvh; width: 100%; }

/* Visually hidden, but available to screen readers and search-engine crawlers */
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0;
  margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Title banner */
.banner {
  position: absolute; left: 50%; transform: translateX(-50%);
  top: calc(8px + env(safe-area-inset-top));
  z-index: 1000; background: rgba(255,255,255,.93); padding: 8px 18px;
  border-radius: 10px; box-shadow: 0 1px 8px rgba(0,0,0,.25); text-align: center;
  max-width: 92vw; box-sizing: border-box;
}
.banner h1 { font-size: 15px; font-weight: 600; margin: 0; display: inline; }
.banner small { display: block; color: #666; font-size: 11px; margin-top: 2px; }

/* Right-hand panel: search + fuel selector + legend */
.panel {
  background: rgba(255,255,255,.96); border-radius: 8px;
  box-shadow: 0 1px 6px rgba(0,0,0,.3); font-size: 13px; line-height: 1.5; min-width: 150px;
}
.panel-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 12px; font-weight: 600; cursor: pointer; user-select: none;
}
.p-caret, #route-caret { color: #666; }
.panel-body { padding: 0 12px 10px; }
.panel.collapsed .panel-body { display: none; }
.panel h4 { margin: 8px 0 6px; font-size: 12px; text-transform: uppercase; letter-spacing: .04em; color: #555; }
.panel-body h4:first-child { margin-top: 2px; }
.panel label { display: block; cursor: pointer; }
.panel input[type=radio] { vertical-align: middle; margin-right: 6px; }
.panel .count { color: #6b7280; font-size: 11px; }
.panel .hint { color: #6b7280; font-size: 11px; margin-top: 3px; }

.search-row { display: flex; gap: 4px; }
.search-row input[type=text] {
  flex: 1; min-width: 0; padding: 5px 7px; font-size: 13px;
  border: 1px solid #ccc; border-radius: 6px; box-sizing: border-box;
}

.btn {
  border: 1px solid #ccc; background: #f4f4f4; border-radius: 6px;
  padding: 4px 8px; font-size: 12px; cursor: pointer; color: #333;
}
.btn:hover { background: #eaeaea; }

/* Visible keyboard focus (only for keyboard users, not mouse clicks) */
:focus-visible { outline: 2px solid #1a73e8; outline-offset: 2px; }
.panel-head:focus-visible, .route-head:focus-visible, .cl-item:focus-visible {
  outline: 2px solid #1a73e8; outline-offset: -2px; border-radius: 6px;
}

.route-status { margin-top: 6px; font-size: 12px; color: #333; }
.route-status .cheapest { color: #1a7a40; font-weight: 600; }

/* Alternative-route comparison (fastest / other motorway / toll-free) */
.route-options { margin: 4px 0; }
.ro-item {
  display: flex; align-items: center; gap: 8px; padding: 5px 4px;
  border-radius: 6px; cursor: pointer;
}
.ro-item:hover, .ro-item.active { background: #e8f0fe; }
.ro-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; box-shadow: 0 0 0 1px rgba(0,0,0,.2); }
.ro-text { line-height: 1.2; }
.ro-text small { display: block; color: #6b7280; font-size: 11px; }

/* Itinerary control (top-left) */
.route-box {
  background: rgba(255,255,255,.96); border-radius: 8px; width: 232px;
  box-shadow: 0 1px 6px rgba(0,0,0,.3); font-size: 13px;
}
.route-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 8px 10px; font-weight: 600; cursor: pointer; user-select: none;
}
.route-body { padding: 0 10px 10px; }
.route-box.collapsed .route-body { display: none; }
.route-box input {
  width: 100%; box-sizing: border-box; padding: 6px 8px;
  font-size: 13px; border: 1px solid #ccc; border-radius: 6px;
}
.route-actions { display: flex; gap: 6px; margin-top: 2px; }
.route-actions .btn { flex: 1; }
#route-msg { margin-top: 6px; min-height: 1em; }

/* City / car autocomplete dropdown */
.ac-wrap { position: relative; margin-bottom: 6px; }
.ac-list {
  position: absolute; left: 0; right: 0; top: 100%; z-index: 1200;
  background: #fff; border: 1px solid #ccc; border-radius: 0 0 6px 6px;
  max-height: 184px; overflow-y: auto; box-shadow: 0 3px 8px rgba(0,0,0,.18);
}
.ac-list .item { padding: 6px 8px; cursor: pointer; line-height: 1.25; }
.ac-list .item.active, .ac-list .item:hover { background: #eef4ff; }
.ac-list .ctx { display: block; color: #6b7280; font-size: 11px; }

/* Vehicle selector + journey cost */
.route-sel {
  width: 100%; box-sizing: border-box; margin-bottom: 6px; padding: 6px 8px;
  font-size: 13px; border: 1px solid #ccc; border-radius: 6px; background: #fff;
}
.cost { margin-top: 8px; line-height: 1.35; color: #1a7a40; }
.cost b { font-size: 16px; }
.cost .hint { color: #888; }

/* Thermique / Électrique segmented toggle */
.seg { display: flex; margin-bottom: 6px; border: 1px solid #ccc; border-radius: 6px; overflow: hidden; }
.seg label { flex: 1; text-align: center; padding: 5px 0; cursor: pointer; font-size: 12px; color: #444; }
.seg label input { display: none; }
.seg label.seg-on { background: #1a73e8; color: #fff; }
.chk { display: flex; align-items: center; gap: 6px; margin: 2px 0 4px; font-size: 12px; cursor: pointer; }
.chk input { margin: 0; }
#charger-msg { color: #7b1fa2; margin-bottom: 4px; }
.ev-stop { font-size: 20px; text-align: center; line-height: 26px; filter: drop-shadow(0 1px 1px rgba(0,0,0,.45)); }

/* Price ceiling slider */
#price-filter { margin-top: 6px; }
#price-slider {
  width: 100%; margin: 2px 0 0; accent-color: #1a9850; cursor: pointer;
}
.slider-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.slider-out { font-size: 12px; font-weight: 600; color: #1a7a40; }
.btn-link {
  border: 0; background: none; padding: 0; cursor: pointer;
  color: #1a73e8; font-size: 11px; text-decoration: underline;
}

/* "Près de moi" button + brand filter */
.btn.near-me { width: 100%; margin: 2px 0 4px; }
#brand-filter { margin-top: 4px; }

/* Median price trend vs the previous build */
.lg-trend { font-size: 12px; margin: 4px 0 2px; }
.lg-trend .up { color: #d73027; font-weight: 600; }    /* price rose */
.lg-trend .down { color: #1a7a40; font-weight: 600; }  /* price fell */

/* Cheapest-stations list */
.cheapest-list { margin-top: 6px; max-height: 240px; overflow-y: auto; }
.cl-item {
  display: flex; align-items: baseline; gap: 8px; padding: 4px 2px;
  border-top: 1px solid #eee; cursor: pointer;
}
.cl-item:hover { background: #eef4ff; }
.cl-price { color: #1a7a40; font-weight: 600; white-space: nowrap; }
.cl-name { line-height: 1.2; }
.cl-name small { display: block; color: #6b7280; font-size: 11px; }

/* Price legend */
.legend-bar {
  height: 12px; border-radius: 3px; margin: 8px 0 3px;
  background: linear-gradient(to right, #1a9850, #91cf60, #fee08b, #fc8d59, #d73027);
}
.legend-scale { display: flex; justify-content: space-between; font-size: 11px; color: #555; }

/* Electric mode legend (charger power) */
.ev-legend { margin: 6px 0 2px; font-size: 12px; color: #444; }
.ev-legend > div { display: flex; align-items: center; gap: 6px; margin: 2px 0; }
.ev-legend .sw { width: 12px; height: 12px; border-radius: 50%; box-shadow: 0 0 0 1px #ccc; }
.ev-legend .sw.fast { background: #7b1fa2; }
.ev-legend .sw.slow { background: #2e86c1; }

/* "Locate me" button */
.locate-ctrl a { text-align: center; font-size: 16px; }
.locate-ctrl a.locating { background: #1a73e8; }

/* Station / charger popups */
.popup b { font-size: 14px; }
.hw-badge, .svc-badge {
  display: inline-block; background: #1a73e8; color: #fff; font-size: 10px;
  font-weight: 700; padding: 1px 5px; border-radius: 4px; vertical-align: middle;
}
.svc-badge { background: #1a7a40; }   /* 24/24 */
.popup .addr { color: #666; margin: 2px 0 6px; }
.popup table { border-collapse: collapse; }
.popup td { padding: 1px 8px 1px 0; }
.popup td.p { text-align: right; font-weight: 600; }
.popup .svc { color: #6b7280; font-size: 11px; margin-top: 4px; line-height: 1.3; }
.popup .upd { margin-top: 6px; color: #6b7280; font-size: 11px; }
.popup-actions { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.fav-btn {
  border: 1px solid #f1c40f; background: #fff; color: #b8860b; border-radius: 6px;
  padding: 3px 8px; font-size: 12px; cursor: pointer; white-space: nowrap;
}
.fav-btn.on { background: #f1c40f; color: #fff; }

/* Station filters block (favourites / 24-7 / price freshness) */
#filters { margin-top: 6px; }

/* Author credit, shown inside the map attribution (always visible, never
 * overlaps the panels or gets hidden behind the attribution bar). */
.leaflet-control-attribution a.credit-link { font-weight: 600; color: #1a73e8; }

/* First-visit "install to home screen" prompt */
.install-prompt {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(14px + env(safe-area-inset-bottom)); z-index: 2000;
  display: flex; align-items: center; gap: 10px; width: min(92vw, 420px);
  box-sizing: border-box; background: #fff; color: #222;
  border-radius: 12px; padding: 10px 12px; box-shadow: 0 4px 20px rgba(0,0,0,.28);
  animation: ip-rise .25s ease-out;
}
@keyframes ip-rise { from { transform: translate(-50%, 14px); opacity: 0; } }
.ip-icon { font-size: 24px; line-height: 1; }
.ip-text { flex: 1; min-width: 0; font-size: 13px; line-height: 1.35; }
.ip-text b { display: block; margin-bottom: 1px; }
.ip-text .ic { font-weight: 700; }
.install-btn {
  border: 0; background: #1a9850; color: #fff; border-radius: 8px;
  padding: 7px 12px; font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
}
.install-btn:hover { background: #157a40; }
.install-close {
  border: 0; background: none; color: #888; font-size: 16px;
  cursor: pointer; padding: 0 2px; line-height: 1;
}

/* "New version available" toast */
.update-prompt {
  position: fixed; left: 50%; transform: translateX(-50%);
  top: calc(8px + env(safe-area-inset-top)); z-index: 2500;
  display: flex; align-items: center; gap: 10px;
  background: #1a73e8; color: #fff; border-radius: 10px;
  padding: 8px 12px; font-size: 13px; box-shadow: 0 3px 14px rgba(0,0,0,.3);
}
.update-btn {
  border: 0; background: #fff; color: #1a73e8; border-radius: 7px;
  padding: 5px 10px; font-size: 13px; font-weight: 600; cursor: pointer;
}

/* Visible only when JavaScript is disabled (also useful for crawlers) */
.noscript {
  position: absolute; inset: 0; z-index: 3000; overflow: auto;
  background: #fff; color: #222; padding: 24px; max-width: 640px; margin: 0 auto;
  font-size: 15px; line-height: 1.5;
}

/* Keep Leaflet controls clear of notches / rounded corners */
.leaflet-top { margin-top: env(safe-area-inset-top); }
.leaflet-left { margin-left: env(safe-area-inset-left); }
.leaflet-right { margin-right: env(safe-area-inset-right); }
.leaflet-bottom { margin-bottom: env(safe-area-inset-bottom); }

/* Mobile / narrow: slim top app-bar + collapsible panels that fit the screen.
 * Breakpoint kept in sync with MOBILE_MQ in app.js. Wide enough to cover large
 * phones, tablets and split-screen windows where the centred banner would
 * otherwise overlap the side panels. */
@media (max-width: 960px) {
  /* Title spans the top as a thin bar */
  .banner {
    top: 0; left: 0; right: 0; transform: none; max-width: none; text-align: left;
    border-radius: 0; padding: 6px 12px; padding-top: calc(6px + env(safe-area-inset-top));
  }
  .banner h1 { font-size: 13px; }
  .banner small { font-size: 10px; }
  .b-tz { display: none; }
  /* Push the Leaflet controls (zoom + both panels) clear below the top bar */
  .leaflet-top { margin-top: calc(58px + env(safe-area-inset-top)); }
  /* Panels: fit the viewport width, scroll if tall, larger touch targets */
  .panel, .route-box { width: 62vw; max-width: 250px; min-width: 0; font-size: 14px; }
  .panel.collapsed, .route-box.collapsed { width: auto; }  /* shrink to a chip */
  .panel-body, .route-body { max-height: 56vh; overflow-y: auto; }
  .panel label { padding: 4px 0; }
  .leaflet-touch .leaflet-bar a { width: 34px; height: 34px; line-height: 34px; }
}

/* Dark mode (follows the OS setting). Panels darken; the light IGN basemap is
 * inverted to a dark map. Popups stay light for readability. */
@media (prefers-color-scheme: dark) {
  .banner, .panel, .route-box, .ac-list, .install-prompt {
    background: rgba(28,30,34,.97); color: #e8eaed;
  }
  .banner small, .panel .count, .panel .hint, .cl-name small, .ac-list .ctx { color: #9aa0a6; }
  .panel h4 { color: #b6bcc4; }
  .search-row input, .route-box input, .route-sel, #place {
    background: #2a2d31; color: #e8eaed; border-color: #4a4d51;
  }
  .btn { background: #34373b; color: #e8eaed; border-color: #4a4d51; }
  .btn:hover { background: #3e4146; }
  .ac-list .item.active, .ac-list .item:hover, .cl-item:hover { background: #2d3340; }
  .ro-item:hover, .ro-item.active { background: #2d3340; }
  .cl-item { border-top-color: #34373b; }
  .leaflet-tile { filter: invert(1) hue-rotate(180deg) brightness(.92) contrast(.95); }
}