@jjlmoya/utils-motor 1.3.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/src/category/index.ts +3 -1
- package/src/entries.ts +5 -1
- package/src/index.ts +10 -0
- package/src/tests/locale_completeness.test.ts +1 -1
- package/src/tests/tool_validation.test.ts +1 -1
- package/src/tool/evChargingTimeCostPlanner/bibliography.astro +6 -0
- package/src/tool/evChargingTimeCostPlanner/bibliography.ts +16 -0
- package/src/tool/evChargingTimeCostPlanner/component.astro +147 -0
- package/src/tool/evChargingTimeCostPlanner/controller.ts +214 -0
- package/src/tool/evChargingTimeCostPlanner/dom-views.ts +124 -0
- package/src/tool/evChargingTimeCostPlanner/entry.ts +30 -0
- package/src/tool/evChargingTimeCostPlanner/ev-charging-time-cost-planner.css +598 -0
- package/src/tool/evChargingTimeCostPlanner/evaluator.ts +10 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/de.ts +22 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/en.ts +161 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/es.ts +16 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/factory.ts +113 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/fr.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/id.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/it.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/ja.ts +13 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/ko.ts +13 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/nl.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/pl.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/pt.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/ru.ts +13 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/sv.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/tr.ts +9 -0
- package/src/tool/evChargingTimeCostPlanner/i18n/zh.ts +13 -0
- package/src/tool/evChargingTimeCostPlanner/index.ts +10 -0
- package/src/tool/evChargingTimeCostPlanner/logic.test.ts +71 -0
- package/src/tool/evChargingTimeCostPlanner/logic.ts +174 -0
- package/src/tool/evChargingTimeCostPlanner/seo.astro +15 -0
- package/src/tool/evChargingTimeCostPlanner/storage.ts +27 -0
- package/src/tool/evChargingTimeCostPlanner/ui.ts +50 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/bibliography.astro +6 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/bibliography.ts +12 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/component.astro +166 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/controller.ts +207 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/dom-views.ts +101 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/entry.ts +30 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/evaluator.ts +7 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/de.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/en.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/es.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/fr.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/id.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/it.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/ja.ts +201 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/ko.ts +201 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/nl.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/pl.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/pt.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/ru.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/sv.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/tr.ts +185 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/i18n/zh.ts +201 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/index.ts +10 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/logic.test.ts +229 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/logic.ts +179 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/motorcycle-skid-mark-speed-estimator.css +523 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/seo.astro +15 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/storage.ts +49 -0
- package/src/tool/motorcycleSkidMarkSpeedEstimator/ui.ts +46 -0
- package/src/tools.ts +5 -1
|
@@ -0,0 +1,598 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--n-ink: #181f27;
|
|
3
|
+
--n-muted: #5d6770;
|
|
4
|
+
--n-paper: #f7f5ef;
|
|
5
|
+
--n-panel: #fffefa;
|
|
6
|
+
--n-line: #d2d2c9;
|
|
7
|
+
--n-sun: #eda43c;
|
|
8
|
+
--n-sun-soft: #ffefcc;
|
|
9
|
+
--n-teal: #1d817e;
|
|
10
|
+
--n-teal-soft: #daf1eb;
|
|
11
|
+
--n-held: #576974;
|
|
12
|
+
--n-empty: #e6e6dc;
|
|
13
|
+
--n-shadow: #181f271f;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.theme-dark {
|
|
17
|
+
--n-ink: #f1efe6;
|
|
18
|
+
--n-muted: #b3b9b7;
|
|
19
|
+
--n-paper: #181c1f;
|
|
20
|
+
--n-panel: #202628;
|
|
21
|
+
--n-line: #4c5655;
|
|
22
|
+
--n-sun: #f4b145;
|
|
23
|
+
--n-sun-soft: #503b1d;
|
|
24
|
+
--n-teal: #5cd1bc;
|
|
25
|
+
--n-teal-soft: #1c4643;
|
|
26
|
+
--n-held: #99abb1;
|
|
27
|
+
--n-empty: #404949;
|
|
28
|
+
--n-shadow: #0005;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.evc-tool {
|
|
32
|
+
--n-ink: #181f27;
|
|
33
|
+
--n-muted: #5d6770;
|
|
34
|
+
--n-paper: #f7f5ef;
|
|
35
|
+
--n-panel: #fffefa;
|
|
36
|
+
--n-line: #d2d2c9;
|
|
37
|
+
--n-sun: #eda43c;
|
|
38
|
+
--n-sun-soft: #ffefcc;
|
|
39
|
+
--n-teal: #1d817e;
|
|
40
|
+
--n-teal-soft: #daf1eb;
|
|
41
|
+
--n-held: #576974;
|
|
42
|
+
--n-empty: #e6e6dc;
|
|
43
|
+
--n-shadow: #181f271f;
|
|
44
|
+
|
|
45
|
+
background: var(--n-paper);
|
|
46
|
+
border: 1px solid var(--n-line);
|
|
47
|
+
border-radius: 1.5rem;
|
|
48
|
+
box-sizing: border-box;
|
|
49
|
+
color: var(--n-ink);
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
width: 100%;
|
|
52
|
+
max-width: calc(100vw - 2rem);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.theme-dark .evc-tool {
|
|
56
|
+
--n-ink: #f1efe6;
|
|
57
|
+
--n-muted: #b3b9b7;
|
|
58
|
+
--n-paper: #181c1f;
|
|
59
|
+
--n-panel: #202628;
|
|
60
|
+
--n-line: #4c5655;
|
|
61
|
+
--n-sun: #f4b145;
|
|
62
|
+
--n-sun-soft: #503b1d;
|
|
63
|
+
--n-teal: #5cd1bc;
|
|
64
|
+
--n-teal-soft: #1c4643;
|
|
65
|
+
--n-held: #99abb1;
|
|
66
|
+
--n-empty: #404949;
|
|
67
|
+
--n-shadow: #0005;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.evc-surface {
|
|
71
|
+
background: var(--n-panel);
|
|
72
|
+
padding: clamp(1.1rem, 3vw, 2rem);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.evc-header,
|
|
76
|
+
.evc-scenes,
|
|
77
|
+
.evc-runway-heading,
|
|
78
|
+
.evc-battery-legend,
|
|
79
|
+
.evc-result-lead,
|
|
80
|
+
.evc-formula {
|
|
81
|
+
align-items: center;
|
|
82
|
+
display: flex;
|
|
83
|
+
gap: 1rem;
|
|
84
|
+
justify-content: space-between;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.evc-header {
|
|
88
|
+
border-bottom: 1px solid var(--n-line);
|
|
89
|
+
padding-bottom: 1.25rem;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.evc-header-copy {
|
|
93
|
+
max-width: 42rem;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.evc-overline {
|
|
97
|
+
color: var(--n-teal);
|
|
98
|
+
font-size: 0.72rem;
|
|
99
|
+
font-weight: 800;
|
|
100
|
+
letter-spacing: 0.11em;
|
|
101
|
+
margin: 0 0 0.45rem;
|
|
102
|
+
text-transform: uppercase;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.evc-intro {
|
|
106
|
+
color: var(--n-muted);
|
|
107
|
+
line-height: 1.5;
|
|
108
|
+
margin: 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.evc-reset,
|
|
112
|
+
.evc-scene-button {
|
|
113
|
+
background: var(--n-paper);
|
|
114
|
+
border: 1px solid var(--n-line);
|
|
115
|
+
color: var(--n-ink);
|
|
116
|
+
cursor: pointer;
|
|
117
|
+
font: inherit;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.evc-reset {
|
|
121
|
+
border-radius: 999px;
|
|
122
|
+
flex: 0 0 auto;
|
|
123
|
+
font-size: 0.8rem;
|
|
124
|
+
font-weight: 750;
|
|
125
|
+
padding: 0.65rem 0.9rem;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.evc-reset:hover,
|
|
129
|
+
.evc-reset:focus-visible {
|
|
130
|
+
border-color: var(--n-teal);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.evc-scenes {
|
|
134
|
+
align-items: stretch;
|
|
135
|
+
border-bottom: 1px solid var(--n-line);
|
|
136
|
+
flex-wrap: wrap;
|
|
137
|
+
padding: 1.25rem 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.evc-scenes-label {
|
|
141
|
+
color: var(--n-muted);
|
|
142
|
+
flex: 1 0 100%;
|
|
143
|
+
font-size: 0.78rem;
|
|
144
|
+
font-weight: 750;
|
|
145
|
+
margin-bottom: 0.1rem;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.evc-scene-button {
|
|
149
|
+
border-radius: 0.85rem;
|
|
150
|
+
display: flex;
|
|
151
|
+
flex: 1 1 10rem;
|
|
152
|
+
flex-direction: column;
|
|
153
|
+
gap: 0.25rem;
|
|
154
|
+
min-height: 4.5rem;
|
|
155
|
+
padding: 0.8rem 0.9rem;
|
|
156
|
+
text-align: left;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
.evc-scene-button strong {
|
|
160
|
+
font-size: 0.9rem;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.evc-scene-button small {
|
|
164
|
+
color: var(--n-muted);
|
|
165
|
+
font-size: 0.72rem;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.evc-scene-button:hover,
|
|
169
|
+
.evc-scene-button:focus-visible,
|
|
170
|
+
.evc-scene-button.is-active {
|
|
171
|
+
border-color: var(--n-sun);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.evc-scene-button.is-active {
|
|
175
|
+
background: var(--n-sun-soft);
|
|
176
|
+
box-shadow: inset 0 -0.2rem 0 var(--n-sun);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.evc-main-grid {
|
|
180
|
+
align-items: start;
|
|
181
|
+
display: grid;
|
|
182
|
+
gap: clamp(1.5rem, 4vw, 3rem);
|
|
183
|
+
grid-template-columns: minmax(16rem, 0.9fr) minmax(20rem, 1.1fr);
|
|
184
|
+
padding-top: 1.75rem;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
.evc-section-heading h2,
|
|
188
|
+
.evc-runway-heading h2 {
|
|
189
|
+
font-size: clamp(1.05rem, 2vw, 1.35rem);
|
|
190
|
+
line-height: 1.2;
|
|
191
|
+
margin: 0;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.evc-soc-row {
|
|
195
|
+
align-items: center;
|
|
196
|
+
display: grid;
|
|
197
|
+
gap: 0.8rem;
|
|
198
|
+
grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
|
|
199
|
+
margin: 1.5rem 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.evc-window-arrow {
|
|
203
|
+
color: var(--n-sun);
|
|
204
|
+
font-size: 1.6rem;
|
|
205
|
+
font-weight: 800;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.evc-field {
|
|
209
|
+
display: block;
|
|
210
|
+
min-width: 0;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.evc-field > span {
|
|
214
|
+
display: block;
|
|
215
|
+
font-size: 0.86rem;
|
|
216
|
+
font-weight: 750;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.evc-field > small {
|
|
220
|
+
color: var(--n-muted);
|
|
221
|
+
display: block;
|
|
222
|
+
font-size: 0.7rem;
|
|
223
|
+
line-height: 1.35;
|
|
224
|
+
margin: 0.25rem 0 0.55rem;
|
|
225
|
+
min-height: 1.9em;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.evc-field strong {
|
|
229
|
+
align-items: center;
|
|
230
|
+
background: var(--n-paper);
|
|
231
|
+
border: 1px solid var(--n-line);
|
|
232
|
+
border-radius: 0.7rem;
|
|
233
|
+
display: flex;
|
|
234
|
+
min-height: 2.9rem;
|
|
235
|
+
padding: 0 0.7rem;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.evc-field input[type='number'],
|
|
239
|
+
.evc-field input[type='text'] {
|
|
240
|
+
background: transparent;
|
|
241
|
+
border: 0;
|
|
242
|
+
color: var(--n-ink);
|
|
243
|
+
font: 700 1.05rem ui-monospace, monospace;
|
|
244
|
+
min-width: 0;
|
|
245
|
+
outline: 0;
|
|
246
|
+
padding: 0.45rem 0;
|
|
247
|
+
width: 100%;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.evc-field em {
|
|
251
|
+
color: var(--n-muted);
|
|
252
|
+
flex: 0 0 auto;
|
|
253
|
+
font-size: 0.72rem;
|
|
254
|
+
font-style: normal;
|
|
255
|
+
margin-left: 0.45rem;
|
|
256
|
+
white-space: nowrap;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.evc-field strong:focus-within {
|
|
260
|
+
border-color: var(--n-teal);
|
|
261
|
+
box-shadow: 0 0 0 3px var(--n-teal-soft);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.evc-field input[type='range'] {
|
|
265
|
+
accent-color: var(--n-teal);
|
|
266
|
+
display: block;
|
|
267
|
+
margin: 0.75rem 0 0;
|
|
268
|
+
width: 100%;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
.evc-field-stack {
|
|
272
|
+
display: grid;
|
|
273
|
+
gap: 1.05rem;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.evc-currency-panel {
|
|
277
|
+
background: var(--n-teal-soft);
|
|
278
|
+
border: 1px solid var(--n-teal);
|
|
279
|
+
border-radius: 0.85rem;
|
|
280
|
+
display: grid;
|
|
281
|
+
gap: 0.65rem;
|
|
282
|
+
margin: 1.25rem 0 1.05rem;
|
|
283
|
+
padding: 0.8rem;
|
|
284
|
+
position: relative;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.evc-currency-panel > div:first-child span,
|
|
288
|
+
.evc-currency-panel > div:first-child small {
|
|
289
|
+
display: block;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.evc-currency-panel > div:first-child span {
|
|
293
|
+
color: var(--n-ink);
|
|
294
|
+
font-size: 0.84rem;
|
|
295
|
+
font-weight: 800;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.evc-currency-panel > div:first-child small,
|
|
299
|
+
.evc-currency-factor {
|
|
300
|
+
color: var(--n-muted);
|
|
301
|
+
font-size: 0.7rem;
|
|
302
|
+
line-height: 1.35;
|
|
303
|
+
margin-top: 0.2rem;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.evc-currency-trigger {
|
|
307
|
+
align-items: center;
|
|
308
|
+
background: var(--n-paper);
|
|
309
|
+
border: 1px solid var(--n-line);
|
|
310
|
+
border-radius: 0.65rem;
|
|
311
|
+
color: var(--n-ink);
|
|
312
|
+
cursor: pointer;
|
|
313
|
+
display: flex;
|
|
314
|
+
gap: 0.65rem;
|
|
315
|
+
justify-content: space-between;
|
|
316
|
+
padding: 0.65rem 0.75rem;
|
|
317
|
+
text-align: left;
|
|
318
|
+
width: 100%;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
.evc-currency-trigger strong {
|
|
322
|
+
font-size: 0.9rem;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
.evc-currency-trigger span {
|
|
326
|
+
color: var(--n-muted);
|
|
327
|
+
flex: 1;
|
|
328
|
+
font-size: 0.72rem;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.evc-currency-trigger i {
|
|
332
|
+
border-bottom: 2px solid var(--n-ink);
|
|
333
|
+
border-right: 2px solid var(--n-ink);
|
|
334
|
+
display: block;
|
|
335
|
+
height: 0.45rem;
|
|
336
|
+
transform: rotate(45deg) translateY(-0.15rem);
|
|
337
|
+
width: 0.45rem;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.evc-currency-menu {
|
|
341
|
+
background: var(--n-panel);
|
|
342
|
+
border: 1px solid var(--n-line);
|
|
343
|
+
border-radius: 0.7rem;
|
|
344
|
+
box-shadow: 0 0.8rem 1.5rem var(--n-shadow);
|
|
345
|
+
display: grid;
|
|
346
|
+
gap: 0.25rem;
|
|
347
|
+
left: 0.8rem;
|
|
348
|
+
max-height: 16rem;
|
|
349
|
+
overflow-y: auto;
|
|
350
|
+
padding: 0.35rem;
|
|
351
|
+
position: absolute;
|
|
352
|
+
right: 0.8rem;
|
|
353
|
+
top: calc(100% - 0.35rem);
|
|
354
|
+
z-index: 2;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.evc-currency-menu[hidden] {
|
|
358
|
+
display: none;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.evc-currency-menu button {
|
|
362
|
+
align-items: center;
|
|
363
|
+
background: transparent;
|
|
364
|
+
border: 0;
|
|
365
|
+
border-radius: 0.45rem;
|
|
366
|
+
color: var(--n-ink);
|
|
367
|
+
cursor: pointer;
|
|
368
|
+
display: flex;
|
|
369
|
+
gap: 0.7rem;
|
|
370
|
+
justify-content: space-between;
|
|
371
|
+
padding: 0.55rem 0.6rem;
|
|
372
|
+
text-align: left;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.evc-currency-menu button:hover,
|
|
376
|
+
.evc-currency-menu button:focus-visible,
|
|
377
|
+
.evc-currency-menu button.is-active {
|
|
378
|
+
background: var(--n-sun-soft);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.evc-currency-menu button strong {
|
|
382
|
+
font-size: 0.78rem;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.evc-currency-menu button span {
|
|
386
|
+
color: var(--n-muted);
|
|
387
|
+
font-size: 0.7rem;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.evc-runway {
|
|
391
|
+
background: var(--n-paper);
|
|
392
|
+
border: 1px solid var(--n-line);
|
|
393
|
+
border-radius: 1rem;
|
|
394
|
+
box-shadow: 0 1rem 2rem var(--n-shadow);
|
|
395
|
+
min-width: 0;
|
|
396
|
+
padding: clamp(1rem, 3vw, 1.5rem);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.evc-runway-heading {
|
|
400
|
+
align-items: flex-start;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
.evc-status {
|
|
404
|
+
background: var(--n-teal-soft);
|
|
405
|
+
border-radius: 999px;
|
|
406
|
+
color: var(--n-teal);
|
|
407
|
+
flex: 0 0 auto;
|
|
408
|
+
font-size: 0.7rem;
|
|
409
|
+
font-weight: 800;
|
|
410
|
+
padding: 0.45rem 0.65rem;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.evc-tool[data-status='empty'] .evc-status {
|
|
414
|
+
background: var(--n-empty);
|
|
415
|
+
color: var(--n-muted);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.evc-tool[data-status='short'] .evc-status {
|
|
419
|
+
background: var(--n-sun-soft);
|
|
420
|
+
color: var(--n-ink);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.evc-battery-wrap {
|
|
424
|
+
margin: 1.25rem -0.6rem 0.5rem;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.evc-battery {
|
|
428
|
+
display: block;
|
|
429
|
+
height: auto;
|
|
430
|
+
overflow: visible;
|
|
431
|
+
width: 100%;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
.evc-battery-shell {
|
|
435
|
+
fill: var(--n-panel);
|
|
436
|
+
stroke: var(--n-line);
|
|
437
|
+
stroke-width: 3;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
.evc-battery-terminal {
|
|
441
|
+
fill: var(--n-line);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
.evc-segments rect {
|
|
445
|
+
fill: var(--n-empty);
|
|
446
|
+
transition: fill 180ms ease, transform 180ms ease;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
.evc-segments rect[data-level='held'] {
|
|
450
|
+
fill: var(--n-held);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
.evc-segments rect[data-level='added'] {
|
|
454
|
+
fill: var(--n-sun);
|
|
455
|
+
transform: translateY(-4px);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.evc-energy-line {
|
|
459
|
+
fill: none;
|
|
460
|
+
stroke: var(--n-teal);
|
|
461
|
+
stroke-dasharray: 5 9;
|
|
462
|
+
stroke-width: 3;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
.evc-energy-node {
|
|
466
|
+
fill: var(--n-teal);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
.evc-battery-legend {
|
|
470
|
+
color: var(--n-muted);
|
|
471
|
+
font-size: 0.72rem;
|
|
472
|
+
justify-content: flex-start;
|
|
473
|
+
padding: 0 0.65rem;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.evc-battery-legend > span {
|
|
477
|
+
align-items: center;
|
|
478
|
+
display: inline-flex;
|
|
479
|
+
gap: 0.3rem;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
.evc-battery-legend strong {
|
|
483
|
+
color: var(--n-ink);
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.evc-dot {
|
|
487
|
+
border-radius: 50%;
|
|
488
|
+
display: inline-block;
|
|
489
|
+
height: 0.6rem;
|
|
490
|
+
width: 0.6rem;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
.evc-dot-held {
|
|
494
|
+
background: var(--n-held);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
.evc-dot-added {
|
|
498
|
+
background: var(--n-sun);
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.evc-result-lead {
|
|
502
|
+
align-items: flex-end;
|
|
503
|
+
border-top: 1px solid var(--n-line);
|
|
504
|
+
margin-top: 1.25rem;
|
|
505
|
+
padding-top: 1rem;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.evc-result-lead span,
|
|
509
|
+
.evc-metrics span {
|
|
510
|
+
color: var(--n-muted);
|
|
511
|
+
display: block;
|
|
512
|
+
font-size: 0.72rem;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.evc-result-lead strong {
|
|
516
|
+
display: block;
|
|
517
|
+
font-size: clamp(1.8rem, 5vw, 2.8rem);
|
|
518
|
+
line-height: 1;
|
|
519
|
+
margin-top: 0.25rem;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
.evc-result-lead small {
|
|
523
|
+
color: var(--n-teal);
|
|
524
|
+
font-size: 0.75rem;
|
|
525
|
+
font-weight: 800;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.evc-metrics {
|
|
529
|
+
border-bottom: 1px solid var(--n-line);
|
|
530
|
+
display: grid;
|
|
531
|
+
gap: 0.9rem 1.25rem;
|
|
532
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
533
|
+
padding: 1.15rem 0;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.evc-metrics strong {
|
|
537
|
+
display: block;
|
|
538
|
+
font-size: 0.98rem;
|
|
539
|
+
margin-top: 0.2rem;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
.evc-summary {
|
|
543
|
+
color: var(--n-muted);
|
|
544
|
+
font-size: 0.82rem;
|
|
545
|
+
line-height: 1.55;
|
|
546
|
+
margin: 1rem 0 0;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.evc-formula {
|
|
550
|
+
align-items: flex-start;
|
|
551
|
+
border-top: 1px solid var(--n-line);
|
|
552
|
+
color: var(--n-muted);
|
|
553
|
+
font-size: 0.76rem;
|
|
554
|
+
line-height: 1.5;
|
|
555
|
+
margin-top: 1.75rem;
|
|
556
|
+
padding-top: 1rem;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
.evc-formula strong {
|
|
560
|
+
color: var(--n-ink);
|
|
561
|
+
flex: 0 0 auto;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.evc-formula span {
|
|
565
|
+
max-width: 56rem;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.evc-reset:focus-visible,
|
|
569
|
+
.evc-scene-button:focus-visible,
|
|
570
|
+
.evc-currency-trigger:focus-visible,
|
|
571
|
+
.evc-currency-menu button:focus-visible,
|
|
572
|
+
.evc-field input:focus-visible {
|
|
573
|
+
outline: 3px solid var(--n-sun);
|
|
574
|
+
outline-offset: 2px;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
@media (max-width: 760px) {
|
|
578
|
+
.evc-main-grid {
|
|
579
|
+
grid-template-columns: 1fr;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
.evc-runway {
|
|
583
|
+
order: -1;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
@media (max-width: 520px) {
|
|
588
|
+
.evc-header,
|
|
589
|
+
.evc-formula {
|
|
590
|
+
align-items: flex-start;
|
|
591
|
+
flex-direction: column;
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
.evc-battery-legend {
|
|
595
|
+
align-items: flex-start;
|
|
596
|
+
flex-direction: column;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ChargingPlan } from './logic';
|
|
2
|
+
|
|
3
|
+
export type ChargingStatus = 'empty' | 'short' | 'standard' | 'long';
|
|
4
|
+
|
|
5
|
+
export function evaluateChargingStatus(plan: ChargingPlan): ChargingStatus {
|
|
6
|
+
if (plan.chargeFraction === 0) return 'empty';
|
|
7
|
+
if (plan.timeMinutes <= 30) return 'short';
|
|
8
|
+
if (plan.timeMinutes <= 240) return 'standard';
|
|
9
|
+
return 'long';
|
|
10
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createLocalizedContent } from './factory';
|
|
2
|
+
|
|
3
|
+
const content = createLocalizedContent({
|
|
4
|
+
locale: 'de', currency: 'EUR', slug: 'e-auto-ladezeit-und-kosten-rechner', title: 'Rechner fuer Ladezeit und Kosten von Elektroautos', description: 'Schaetze Ladezeit, Stromkosten, Ladeverluste und die zusaetzliche Reichweite fuer eine Ladesitzung.', faqTitle: 'Haeufige Fragen', bibliographyTitle: 'Bibliografische Quellen',
|
|
5
|
+
ui: { defaultCurrency: 'EUR', currencyLabel: 'Waehrung', currencyHint: 'Waehle die Waehrung fuer den lokalen Strompreis und die Gesamtkosten.', currencyMenuLabel: 'Waehrung auswaehlen', currencyFactorTemplate: 'Ungefaehrer Offline-Faktor: 1 EUR = {factor} {currency}. Passe den Preis an deinen Tarif an.', presetLabel: 'Mit einer Ladeszene starten', homePreset: 'Zu Hause', publicPreset: 'Oeffentlich', fastPreset: 'Schnell', resetLabel: 'Plan zuruecksetzen', setupLabel: 'Ladefenster festlegen', setupHint: 'Gib an, wie viel nutzbare Batterieenergie du laden moechtest und was der Lader kostet.', chargeWindowLabel: 'Ladefenster', chargeWindowHint: 'Batteriestand vor und nach dieser Sitzung', startSocLabel: 'Startladung', startSocHint: 'Aktueller Batteriestand', endSocLabel: 'Zielladung', endSocHint: 'Batteriestand beim Abstecken', capacityLabel: 'Nutzbare Batteriekapazitaet', chargerPowerLabel: 'Ladeleistung', efficiencyLabel: 'Ladeeffizienz', priceLabel: 'Strompreis', priceHint: 'Ungefaehrer lokaler Preis pro Kilowattstunde. Passe ihn an deinen Tarif an.', consumptionLabel: 'Fahrzeugverbrauch', resultKicker: 'Energie-Reichweite', resultTitle: 'Ein klarer Plan fuer diese Sitzung', startingChargeLabel: 'Bereits gespeichert', targetChargeLabel: 'Zielladung', batteryEnergyLabel: 'Energie in der Batterie', gridEnergyLabel: 'Energie aus dem Netz', lossesLabel: 'Ladeverluste', timeLabel: 'Geschaetzte Zeit', costLabel: 'Geschaetzte Kosten', rangeLabel: 'Zusaetzliche Reichweite', statusEmpty: 'Noch keine Energie geladen', statusShort: 'Kurzes Nachladen', statusStandard: 'Ausgewogene Ladung', statusLong: 'Langes Ladefenster', summaryTemplate: 'Lade {battery} kWh, um etwa {range} km Reichweite zu gewinnen. Bei {power} kW dauert es {time} und kostet {cost}.', formulaLabel: 'So funktioniert die Schaetzung', rangeUnit: 'km' },
|
|
6
|
+
faq: [
|
|
7
|
+
{ question: 'Wie schaetzt der Rechner die Ladesitzung?', answer: 'Er multipliziert die nutzbare Batteriekapazitaet mit dem Unterschied zwischen Start- und Zielladestand. Danach beruecksichtigt er die Ladeeffizienz und teilt die Netzenergie durch die eingegebene Ladeleistung.' },
|
|
8
|
+
{ question: 'Warum ist die Netzenergie hoeher als die gespeicherte Energie?', answer: 'Laden ist nicht vollstaendig effizient. Die Effizienz beschreibt den Anteil des Stroms, der die Batterie erreicht. Der Rest wird als Ladeverlust ausgewiesen.' },
|
|
9
|
+
{ question: 'Beruecksichtigt das Ergebnis die Ladekurve meines Autos?', answer: 'Nein. Der Rechner nutzt die eingegebene dauerhafte Ladeleistung. Fahrzeuge reduzieren die Leistung bei hohem Ladestand oft.' },
|
|
10
|
+
{ question: 'Wie wird die zusaetzliche Reichweite berechnet?', answer: 'Die hinzugefuegte Batterieenergie wird durch den Verbrauch in Kilowattstunden pro 100 Kilometer geteilt.' },
|
|
11
|
+
{ question: 'Wie aendert der Waehrungswaehler den Preis?', answer: 'Der Wechsel nutzt einen ungefaehren Offline-Faktor zum Euro und rechnet Preis und Gesamtkosten um. Passe den Preis an, wenn dein lokaler Tarif abweicht.' },
|
|
12
|
+
],
|
|
13
|
+
howTo: [ { name: 'Eine Ladeszene waehlen', text: 'Waehle Zu Hause, Oeffentlich oder Schnell, um ein realistisches Beispiel zu laden.' }, { name: 'Das Ladefenster festlegen', text: 'Gib Kapazitaet sowie Start- und Zielladestand ein.' }, { name: 'Die Bedingungen anpassen', text: 'Aendere Ladeleistung, Effizienz, Strompreis, Waehrung und Verbrauch.' }, { name: 'Die Energie-Reichweite lesen', text: 'Vergleiche Batterieenergie, Netzenergie, Zeit, Kosten, Verluste und Reichweite.' } ],
|
|
14
|
+
seo: { introTitle: 'Die Energie einer Ladesitzung planen', introText: 'Dieser Rechner macht aus einem Ladefenster eine praktische Schaetzung. Gib Kapazitaet, Ladestand, Ladeleistung, Effizienz, Preis und Verbrauch ein, um Netzbedarf, Dauer, Kosten und zusaetzliche Reichweite zu sehen.', formulaTitle: 'Die verwendeten Formeln', formulaText: 'Batterieenergie entspricht Kapazitaet mal Ladefenster. Netzenergie entspricht Batterieenergie geteilt durch die Effizienz. Die Zeit ergibt sich aus Netzenergie geteilt durch Ladeleistung, die Kosten aus Netzenergie mal lokalem Preis.', tableHeaders: ['Eingabe', 'Berechnung', 'Ergebnis'], tableRows: [['Kapazitaet und Ladefenster', 'Kapazitaet × Ladefenster', 'Gespeicherte Energie'], ['Batterieenergie und Effizienz', 'Batterieenergie ÷ Effizienz', 'Netzenergie'], ['Netzenergie und Ladeleistung', 'Netzenergie ÷ Ladeleistung', 'Geschaetzte Zeit'], ['Netzenergie und Preis', 'Netzenergie × Preis', 'Geschaetzte Kosten']], limitsTitle: 'Das Ergebnis ist eine Planungsschaetzung', limitsText: 'Der Rechner modelliert keine Fahrzeug-Ladekurve, Batterietemperatur, Warteschlange, Steuern, Abos oder geteilte Ladeleistung. Nutze die dauerhafte Leistung fuer eine realistischere Planung.', tipTitle: 'Eine dauerhafte Leistung verwenden', tipText: 'Wenn dein Fahrzeug eine Spitzenleistung nur kurz erreicht, gib die Leistung ein, die es ueber den groessten Teil der Sitzung halten kann.', energyStat: 'Batterie- und Netzenergie', timeStat: 'Geschaetzte Sitzungszeit', costStat: 'Kosten bei deinem Tarif' },
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
content.title = 'Rechner für Ladezeit und Kosten von Elektroautos';
|
|
18
|
+
content.ui.currencyLabel = 'Währung';
|
|
19
|
+
content.ui.currencyHint = 'Wähle die Währung für den lokalen Strompreis und die Gesamtkosten.';
|
|
20
|
+
content.ui.resetLabel = 'Plan zurücksetzen';
|
|
21
|
+
|
|
22
|
+
export { content };
|