@jjlmoya/utils-forensic-science 1.20.0 → 1.21.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.
Files changed (36) hide show
  1. package/package.json +2 -2
  2. package/scripts/validate-icons.mjs +57 -0
  3. package/src/category/index.ts +10 -10
  4. package/src/entries.ts +26 -25
  5. package/src/index.ts +7 -6
  6. package/src/tests/locale_completeness.test.ts +23 -23
  7. package/src/tests/tool_validation.test.ts +16 -16
  8. package/src/tool/forensic-evidence-scale-calculator/bibliography.astro +9 -0
  9. package/src/tool/forensic-evidence-scale-calculator/bibliography.ts +16 -0
  10. package/src/tool/forensic-evidence-scale-calculator/component.astro +154 -0
  11. package/src/tool/forensic-evidence-scale-calculator/entry.ts +29 -0
  12. package/src/tool/forensic-evidence-scale-calculator/forensic-evidence-scale-calculator.css +516 -0
  13. package/src/tool/forensic-evidence-scale-calculator/i18n/de.ts +3 -0
  14. package/src/tool/forensic-evidence-scale-calculator/i18n/en.ts +299 -0
  15. package/src/tool/forensic-evidence-scale-calculator/i18n/es.ts +3 -0
  16. package/src/tool/forensic-evidence-scale-calculator/i18n/fr.ts +3 -0
  17. package/src/tool/forensic-evidence-scale-calculator/i18n/id.ts +3 -0
  18. package/src/tool/forensic-evidence-scale-calculator/i18n/it.ts +3 -0
  19. package/src/tool/forensic-evidence-scale-calculator/i18n/ja.ts +3 -0
  20. package/src/tool/forensic-evidence-scale-calculator/i18n/ko.ts +3 -0
  21. package/src/tool/forensic-evidence-scale-calculator/i18n/localized-content.ts +1537 -0
  22. package/src/tool/forensic-evidence-scale-calculator/i18n/nl.ts +3 -0
  23. package/src/tool/forensic-evidence-scale-calculator/i18n/pl.ts +3 -0
  24. package/src/tool/forensic-evidence-scale-calculator/i18n/pt.ts +3 -0
  25. package/src/tool/forensic-evidence-scale-calculator/i18n/ru.ts +3 -0
  26. package/src/tool/forensic-evidence-scale-calculator/i18n/sv.ts +3 -0
  27. package/src/tool/forensic-evidence-scale-calculator/i18n/tr.ts +3 -0
  28. package/src/tool/forensic-evidence-scale-calculator/i18n/zh.ts +3 -0
  29. package/src/tool/forensic-evidence-scale-calculator/index.ts +11 -0
  30. package/src/tool/forensic-evidence-scale-calculator/logic.test.ts +55 -0
  31. package/src/tool/forensic-evidence-scale-calculator/logic.ts +107 -0
  32. package/src/tool/forensic-evidence-scale-calculator/seo.astro +10 -0
  33. package/src/tool/forensic-evidence-scale-calculator/ui.ts +3 -0
  34. package/src/tool/forensic-evidence-scale-calculator/unit-selector.ts +120 -0
  35. package/src/tool/forensic-evidence-scale-calculator/view.ts +203 -0
  36. package/src/tools.ts +8 -6
@@ -0,0 +1,516 @@
1
+ .evidence-scale-tool {
2
+ color-scheme: dark;
3
+
4
+ --evidence-paper: #f3eee2;
5
+ --evidence-muted: #a9aca6;
6
+ --evidence-cyan: #39c2d2;
7
+ --evidence-coral: #db5d55;
8
+ --evidence-border: rgba(205, 214, 204, 0.17);
9
+ --evidence-panel: rgba(17, 22, 24, 0.94);
10
+ --evidence-tool-shadow: rgba(0, 0, 0, 0.24);
11
+ --evidence-tool-start: #111719;
12
+ --evidence-tool-end: #101419;
13
+ --evidence-tool-warm: #281b1d;
14
+ --evidence-line: rgba(205, 214, 204, 0.14);
15
+ --evidence-input-border: rgba(205, 214, 204, 0.24);
16
+ --evidence-input-bg: rgba(5, 8, 9, 0.5);
17
+ --evidence-menu-border: rgba(57, 194, 210, 0.35);
18
+ --evidence-menu-bg: #151d20;
19
+ --evidence-plane-border: rgba(57, 194, 210, 0.26);
20
+ --evidence-plane-bg: rgba(57, 194, 210, 0.08);
21
+ --evidence-result-bg: rgba(111, 34, 34, 0.58);
22
+ --evidence-output: #fff7e8;
23
+ --evidence-result-text: #f0c2af;
24
+ --evidence-label: #e4aaa0;
25
+ --evidence-code: #d9f4f0;
26
+ --evidence-warning-border: rgba(255, 205, 110, 0.4);
27
+ --evidence-warning-text: #ffe0a0;
28
+ --evidence-menu-active-text: #d9f4f0;
29
+ --evidence-active-bg: rgba(57, 194, 210, 0.14);
30
+ --evidence-rail-number: rgba(243, 238, 226, 0.5);
31
+ --evidence-menu-shadow: rgba(0, 0, 0, 0.35);
32
+ --evidence-svg-surface-start: #20252a;
33
+ --evidence-svg-surface-end: #0b0e10;
34
+ --evidence-svg-wash: #8d302e;
35
+ --evidence-svg-grid: #236d79;
36
+ --evidence-svg-silhouette: #131719;
37
+ --evidence-svg-object: #607b7d;
38
+ --evidence-svg-object-border: #e8e2d2;
39
+ --evidence-svg-object-mark: #b8d0cc;
40
+ --evidence-svg-object-shadow: #202c2e;
41
+ --evidence-svg-ruler: #e8e2d2;
42
+ --evidence-svg-ruler-ink: #111517;
43
+
44
+ display: grid;
45
+ grid-template-columns: minmax(0, 1.2fr) minmax(20rem, 0.8fr);
46
+ width: 100%;
47
+ overflow: hidden;
48
+ border: 1px solid var(--evidence-border);
49
+ border-radius: 1.35rem;
50
+ background:
51
+ radial-gradient(
52
+ circle at 12% 12%,
53
+ rgba(57, 194, 210, 0.08),
54
+ transparent 28%
55
+ ),
56
+ linear-gradient(
57
+ 135deg,
58
+ var(--evidence-tool-start),
59
+ var(--evidence-tool-end) 55%,
60
+ var(--evidence-tool-warm)
61
+ );
62
+ color: var(--evidence-paper);
63
+ box-shadow: 0 1.4rem 3rem var(--evidence-tool-shadow);
64
+ }
65
+
66
+ .theme-light .evidence-scale-tool {
67
+ color-scheme: light;
68
+
69
+ --evidence-paper: #17212b;
70
+ --evidence-muted: #52606d;
71
+ --evidence-cyan: #087f8c;
72
+ --evidence-coral: #b83b36;
73
+ --evidence-border: rgba(20, 45, 52, 0.16);
74
+ --evidence-tool-shadow: rgba(26, 69, 75, 0.14);
75
+ --evidence-tool-start: #fffdfa;
76
+ --evidence-tool-end: #f1f7f5;
77
+ --evidence-tool-warm: #fff0e9;
78
+ --evidence-line: rgba(25, 63, 70, 0.14);
79
+ --evidence-input-border: rgba(23, 53, 59, 0.25);
80
+ --evidence-input-bg: rgba(255, 255, 255, 0.82);
81
+ --evidence-menu-border: rgba(8, 127, 140, 0.35);
82
+ --evidence-menu-bg: #fff;
83
+ --evidence-plane-border: rgba(8, 127, 140, 0.26);
84
+ --evidence-plane-bg: rgba(8, 127, 140, 0.08);
85
+ --evidence-result-bg: rgba(184, 59, 54, 0.12);
86
+ --evidence-output: #17212b;
87
+ --evidence-result-text: #8f302d;
88
+ --evidence-label: #8f302d;
89
+ --evidence-code: #0c5963;
90
+ --evidence-warning-border: rgba(173, 112, 16, 0.42);
91
+ --evidence-warning-text: #80570c;
92
+ --evidence-menu-active-text: #075d67;
93
+ --evidence-active-bg: rgba(8, 127, 140, 0.12);
94
+ --evidence-rail-number: rgba(23, 33, 43, 0.48);
95
+ --evidence-menu-shadow: rgba(25, 63, 70, 0.18);
96
+ --evidence-svg-surface-start: #fffefd;
97
+ --evidence-svg-surface-end: #e9f1ef;
98
+ --evidence-svg-wash: #c85048;
99
+ --evidence-svg-grid: #55aab2;
100
+ --evidence-svg-silhouette: #d9e3df;
101
+ --evidence-svg-object: #a9c7c0;
102
+ --evidence-svg-object-border: #375c60;
103
+ --evidence-svg-object-mark: #487f80;
104
+ --evidence-svg-object-shadow: #6e9491;
105
+ --evidence-svg-ruler: #fff9ec;
106
+ --evidence-svg-ruler-ink: #30464b;
107
+ }
108
+
109
+ .evidence-scale-scene,
110
+ .evidence-scale-controls,
111
+ .evidence-scale-results {
112
+ min-width: 0;
113
+ border: 0;
114
+ border-radius: 0;
115
+ background: transparent;
116
+ box-shadow: none;
117
+ }
118
+
119
+ .evidence-scale-scene {
120
+ display: flex;
121
+ min-height: 100%;
122
+ flex-direction: column;
123
+ padding: clamp(1.15rem, 2.5vw, 2rem);
124
+ }
125
+
126
+ .evidence-scale-scene-head,
127
+ .evidence-scale-control-head {
128
+ display: flex;
129
+ justify-content: space-between;
130
+ gap: 1rem;
131
+ }
132
+
133
+ .evidence-scale-scene-head {
134
+ align-items: flex-start;
135
+ }
136
+
137
+ .evidence-scale-kicker {
138
+ display: block;
139
+ color: var(--evidence-cyan);
140
+ font-size: 0.7rem;
141
+ font-weight: 800;
142
+ letter-spacing: 0.13em;
143
+ text-transform: uppercase;
144
+ }
145
+
146
+ .evidence-scale-scene h2 {
147
+ margin: 0.3rem 0 0;
148
+ font-size: clamp(1.25rem, 2vw, 1.75rem);
149
+ letter-spacing: -0.03em;
150
+ }
151
+
152
+ .evidence-scale-scene-note,
153
+ .evidence-scale-control-head p,
154
+ .evidence-scale-field small,
155
+ .evidence-scale-plane small,
156
+ .evidence-scale-rail-item small {
157
+ color: var(--evidence-muted);
158
+ font-size: 0.8rem;
159
+ line-height: 1.4;
160
+ }
161
+
162
+ .evidence-scale-scene-note {
163
+ max-width: 15rem;
164
+ text-align: right;
165
+ }
166
+
167
+ .evidence-scale-illustration {
168
+ display: flex;
169
+ min-height: 22rem;
170
+ flex: 1;
171
+ align-items: center;
172
+ margin: 1rem 0 1.2rem;
173
+ overflow: hidden;
174
+ border: 1px solid var(--evidence-line);
175
+ border-radius: 0.95rem;
176
+ background: var(--evidence-svg-surface-end);
177
+ }
178
+
179
+ .evidence-scale-illustration svg {
180
+ display: block;
181
+ width: 100%;
182
+ height: 100%;
183
+ min-height: 22rem;
184
+ }
185
+
186
+ .evidence-scale-scene-rail {
187
+ display: grid;
188
+ grid-template-columns: repeat(3, minmax(0, 1fr));
189
+ gap: 0.65rem;
190
+ padding-top: 1rem;
191
+ border-top: 1px solid var(--evidence-line);
192
+ }
193
+
194
+ .evidence-scale-rail-item {
195
+ display: grid;
196
+ grid-template-columns: auto auto 1fr;
197
+ align-items: start;
198
+ gap: 0.45rem;
199
+ min-width: 0;
200
+ }
201
+
202
+ .evidence-scale-rail-item > span:last-child {
203
+ display: grid;
204
+ gap: 0.12rem;
205
+ min-width: 0;
206
+ }
207
+
208
+ .evidence-scale-rail-item strong {
209
+ overflow-wrap: anywhere;
210
+ font-size: 0.76rem;
211
+ }
212
+
213
+ .evidence-scale-rail-item small {
214
+ display: block;
215
+ overflow-wrap: anywhere;
216
+ font-size: 0.68rem;
217
+ }
218
+
219
+ .evidence-scale-rail-number {
220
+ color: var(--evidence-rail-number);
221
+ font-size: 0.62rem;
222
+ font-weight: 800;
223
+ letter-spacing: 0.08em;
224
+ }
225
+
226
+ .evidence-scale-rail-dot,
227
+ .evidence-scale-rail-mark {
228
+ display: inline-grid;
229
+ width: 0.65rem;
230
+ height: 0.65rem;
231
+ place-items: center;
232
+ margin-top: 0.12rem;
233
+ border-radius: 50%;
234
+ }
235
+
236
+ .evidence-scale-rail-mark {
237
+ color: var(--evidence-paper);
238
+ font-size: 0.8rem;
239
+ font-weight: 800;
240
+ }
241
+
242
+ .legend-coral {
243
+ background: var(--evidence-coral);
244
+ }
245
+
246
+ .legend-cyan {
247
+ background: var(--evidence-cyan);
248
+ }
249
+
250
+ .evidence-scale-side {
251
+ display: grid;
252
+ grid-template-rows: auto auto;
253
+ align-content: stretch;
254
+ min-width: 0;
255
+ border-left: 1px solid var(--evidence-line);
256
+ }
257
+
258
+ .evidence-scale-controls,
259
+ .evidence-scale-results {
260
+ padding: clamp(1.15rem, 2.5vw, 2rem);
261
+ }
262
+
263
+ .evidence-scale-controls {
264
+ border-bottom: 1px solid var(--evidence-line);
265
+ }
266
+
267
+ .evidence-scale-control-head {
268
+ align-items: baseline;
269
+ margin-bottom: 1rem;
270
+ }
271
+
272
+ .evidence-scale-control-head p {
273
+ max-width: 19rem;
274
+ margin: 0;
275
+ }
276
+
277
+ .evidence-scale-field-grid {
278
+ display: grid;
279
+ grid-template-columns: repeat(2, minmax(0, 1fr));
280
+ gap: 0.8rem;
281
+ }
282
+
283
+ .evidence-scale-field {
284
+ display: grid;
285
+ gap: 0.35rem;
286
+ color: var(--evidence-paper);
287
+ font-size: 0.82rem;
288
+ font-weight: 700;
289
+ }
290
+
291
+ .evidence-scale-field input,
292
+ .evidence-scale-choice-trigger {
293
+ width: 100%;
294
+ min-height: 2.6rem;
295
+ padding: 0.55rem 0.65rem;
296
+ border: 1px solid var(--evidence-input-border);
297
+ border-radius: 0.55rem;
298
+ background: var(--evidence-input-bg);
299
+ color: var(--evidence-paper);
300
+ font-size: inherit;
301
+ font-weight: inherit;
302
+ line-height: inherit;
303
+ }
304
+
305
+ .evidence-scale-field input:focus-visible,
306
+ .evidence-scale-choice-trigger:focus-visible,
307
+ .evidence-scale-choice-menu button:focus-visible,
308
+ .evidence-scale-plane input:focus-visible {
309
+ outline: 2px solid var(--evidence-cyan);
310
+ outline-offset: 2px;
311
+ }
312
+
313
+ .evidence-scale-unit {
314
+ position: relative;
315
+ max-width: 15rem;
316
+ margin-top: 0.8rem;
317
+ }
318
+
319
+ .evidence-scale-choice-trigger {
320
+ display: flex;
321
+ align-items: center;
322
+ justify-content: space-between;
323
+ gap: 0.75rem;
324
+ cursor: pointer;
325
+ text-align: left;
326
+ }
327
+
328
+ .evidence-scale-choice-chevron {
329
+ color: var(--evidence-cyan);
330
+ font-size: 1.1rem;
331
+ line-height: 0.8;
332
+ }
333
+
334
+ .evidence-scale-choice-menu {
335
+ position: absolute;
336
+ z-index: 2;
337
+ right: 0;
338
+ left: 0;
339
+ display: grid;
340
+ gap: 0.25rem;
341
+ margin-top: 0.35rem;
342
+ padding: 0.35rem;
343
+ border: 1px solid var(--evidence-menu-border);
344
+ border-radius: 0.7rem;
345
+ background: var(--evidence-menu-bg);
346
+ box-shadow: 0 1rem 2rem var(--evidence-menu-shadow);
347
+ }
348
+
349
+ .evidence-scale-choice-menu[hidden] {
350
+ display: none;
351
+ }
352
+
353
+ .evidence-scale-choice-menu button {
354
+ padding: 0.65rem 0.7rem;
355
+ border: 0;
356
+ border-radius: 0.45rem;
357
+ background: transparent;
358
+ color: var(--evidence-paper);
359
+ cursor: pointer;
360
+ font-size: inherit;
361
+ font-weight: inherit;
362
+ text-align: left;
363
+ }
364
+
365
+ .evidence-scale-choice-menu button:hover,
366
+ .evidence-scale-choice-menu button[aria-selected="true"] {
367
+ background: var(--evidence-active-bg);
368
+ color: var(--evidence-menu-active-text);
369
+ }
370
+
371
+ .evidence-scale-plane {
372
+ display: flex;
373
+ align-items: flex-start;
374
+ gap: 0.65rem;
375
+ margin-top: 1rem;
376
+ padding: 0.75rem;
377
+ border: 1px solid var(--evidence-plane-border);
378
+ border-radius: 0.7rem;
379
+ background: var(--evidence-plane-bg);
380
+ cursor: pointer;
381
+ }
382
+
383
+ .evidence-scale-plane input {
384
+ margin-top: 0.2rem;
385
+ accent-color: var(--evidence-cyan);
386
+ }
387
+
388
+ .evidence-scale-plane span {
389
+ display: grid;
390
+ gap: 0.25rem;
391
+ }
392
+
393
+ .evidence-scale-plane strong {
394
+ font-size: 0.82rem;
395
+ }
396
+
397
+ .evidence-scale-disclaimer {
398
+ margin: 1rem 0 0;
399
+ color: var(--evidence-muted);
400
+ font-size: 0.72rem;
401
+ line-height: 1.5;
402
+ }
403
+
404
+ .evidence-scale-results {
405
+ background: linear-gradient(
406
+ 145deg,
407
+ var(--evidence-result-bg),
408
+ transparent 72%
409
+ );
410
+ }
411
+
412
+ .evidence-scale-result-lead output {
413
+ display: block;
414
+ margin-top: 0.35rem;
415
+ color: var(--evidence-output);
416
+ font-size: clamp(2.2rem, 5vw, 4rem);
417
+ font-weight: 800;
418
+ letter-spacing: -0.07em;
419
+ line-height: 0.95;
420
+ }
421
+
422
+ .evidence-scale-result-lead p {
423
+ margin: 0.7rem 0 0;
424
+ color: var(--evidence-result-text);
425
+ font-size: 0.82rem;
426
+ }
427
+
428
+ .evidence-scale-readouts {
429
+ display: flex;
430
+ align-items: flex-end;
431
+ justify-content: space-between;
432
+ gap: 1rem;
433
+ margin-top: 1.4rem;
434
+ }
435
+
436
+ .evidence-scale-readouts div {
437
+ display: grid;
438
+ gap: 0.3rem;
439
+ min-width: 0;
440
+ }
441
+
442
+ .evidence-scale-readouts span,
443
+ .evidence-scale-trace > span {
444
+ color: var(--evidence-label);
445
+ font-size: 0.68rem;
446
+ letter-spacing: 0.08em;
447
+ text-transform: uppercase;
448
+ }
449
+
450
+ .evidence-scale-readouts strong {
451
+ overflow-wrap: anywhere;
452
+ font-size: 0.95rem;
453
+ }
454
+
455
+ .evidence-scale-trace {
456
+ display: grid;
457
+ gap: 0.45rem;
458
+ margin-top: 1.2rem;
459
+ padding-top: 1rem;
460
+ border-top: 1px solid var(--evidence-line);
461
+ }
462
+
463
+ .evidence-scale-trace code {
464
+ overflow-wrap: anywhere;
465
+ color: var(--evidence-code);
466
+ font-size: 0.78rem;
467
+ }
468
+
469
+ .evidence-scale-warning {
470
+ display: none;
471
+ margin: 1rem 0 0;
472
+ padding: 0.7rem;
473
+ border: 1px solid var(--evidence-warning-border);
474
+ border-radius: 0.6rem;
475
+ color: var(--evidence-warning-text);
476
+ font-size: 0.76rem;
477
+ line-height: 1.45;
478
+ }
479
+
480
+ .evidence-scale-warning[data-visible="true"] {
481
+ display: block;
482
+ }
483
+
484
+ @media (max-width: 820px) {
485
+ .evidence-scale-tool {
486
+ grid-template-columns: 1fr;
487
+ }
488
+
489
+ .evidence-scale-side {
490
+ border-top: 1px solid var(--evidence-line);
491
+ border-left: 0;
492
+ }
493
+ }
494
+
495
+ @media (max-width: 520px) {
496
+ .evidence-scale-scene-head,
497
+ .evidence-scale-control-head,
498
+ .evidence-scale-readouts {
499
+ display: grid;
500
+ }
501
+
502
+ .evidence-scale-scene-note {
503
+ max-width: none;
504
+ text-align: left;
505
+ }
506
+
507
+ .evidence-scale-field-grid,
508
+ .evidence-scale-scene-rail {
509
+ grid-template-columns: 1fr;
510
+ }
511
+
512
+ .evidence-scale-illustration,
513
+ .evidence-scale-illustration svg {
514
+ min-height: 17rem;
515
+ }
516
+ }
@@ -0,0 +1,3 @@
1
+ import { createLocalizedContent } from "./localized-content";
2
+
3
+ export const content = createLocalizedContent("de");