@jjlmoya/utils-science 1.32.0 → 1.34.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 (56) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +3 -1
  3. package/src/entries.ts +5 -1
  4. package/src/index.ts +2 -0
  5. package/src/tests/locale_completeness.test.ts +2 -2
  6. package/src/tests/tool_validation.test.ts +2 -2
  7. package/src/tool/natural-selection-drift/component.astro +37 -6
  8. package/src/tool/natural-selection-drift/natural-selection-drift.css +134 -0
  9. package/src/tool/planet-atmosphere-survival/bibliography.astro +14 -0
  10. package/src/tool/planet-atmosphere-survival/bibliography.ts +16 -0
  11. package/src/tool/planet-atmosphere-survival/component.astro +404 -0
  12. package/src/tool/planet-atmosphere-survival/entry.ts +26 -0
  13. package/src/tool/planet-atmosphere-survival/i18n/de.ts +255 -0
  14. package/src/tool/planet-atmosphere-survival/i18n/en.ts +255 -0
  15. package/src/tool/planet-atmosphere-survival/i18n/es.ts +255 -0
  16. package/src/tool/planet-atmosphere-survival/i18n/fr.ts +255 -0
  17. package/src/tool/planet-atmosphere-survival/i18n/id.ts +255 -0
  18. package/src/tool/planet-atmosphere-survival/i18n/it.ts +255 -0
  19. package/src/tool/planet-atmosphere-survival/i18n/ja.ts +255 -0
  20. package/src/tool/planet-atmosphere-survival/i18n/ko.ts +255 -0
  21. package/src/tool/planet-atmosphere-survival/i18n/nl.ts +255 -0
  22. package/src/tool/planet-atmosphere-survival/i18n/pl.ts +255 -0
  23. package/src/tool/planet-atmosphere-survival/i18n/pt.ts +255 -0
  24. package/src/tool/planet-atmosphere-survival/i18n/ru.ts +255 -0
  25. package/src/tool/planet-atmosphere-survival/i18n/sv.ts +255 -0
  26. package/src/tool/planet-atmosphere-survival/i18n/tr.ts +255 -0
  27. package/src/tool/planet-atmosphere-survival/i18n/zh.ts +255 -0
  28. package/src/tool/planet-atmosphere-survival/index.ts +11 -0
  29. package/src/tool/planet-atmosphere-survival/logic.ts +201 -0
  30. package/src/tool/planet-atmosphere-survival/planet-atmosphere-survival-calculator.css +494 -0
  31. package/src/tool/planet-atmosphere-survival/seo.astro +15 -0
  32. package/src/tool/three-body-problem/app.ts +274 -0
  33. package/src/tool/three-body-problem/bibliography.astro +14 -0
  34. package/src/tool/three-body-problem/bibliography.ts +16 -0
  35. package/src/tool/three-body-problem/component.astro +70 -0
  36. package/src/tool/three-body-problem/entry.ts +26 -0
  37. package/src/tool/three-body-problem/i18n/de.ts +162 -0
  38. package/src/tool/three-body-problem/i18n/en.ts +162 -0
  39. package/src/tool/three-body-problem/i18n/es.ts +162 -0
  40. package/src/tool/three-body-problem/i18n/fr.ts +162 -0
  41. package/src/tool/three-body-problem/i18n/id.ts +162 -0
  42. package/src/tool/three-body-problem/i18n/it.ts +162 -0
  43. package/src/tool/three-body-problem/i18n/ja.ts +162 -0
  44. package/src/tool/three-body-problem/i18n/ko.ts +162 -0
  45. package/src/tool/three-body-problem/i18n/nl.ts +162 -0
  46. package/src/tool/three-body-problem/i18n/pl.ts +162 -0
  47. package/src/tool/three-body-problem/i18n/pt.ts +162 -0
  48. package/src/tool/three-body-problem/i18n/ru.ts +162 -0
  49. package/src/tool/three-body-problem/i18n/sv.ts +162 -0
  50. package/src/tool/three-body-problem/i18n/tr.ts +162 -0
  51. package/src/tool/three-body-problem/i18n/zh.ts +162 -0
  52. package/src/tool/three-body-problem/index.ts +11 -0
  53. package/src/tool/three-body-problem/logic/ThreeBodyEngine.ts +179 -0
  54. package/src/tool/three-body-problem/seo.astro +15 -0
  55. package/src/tool/three-body-problem/three-body-problem-simulator.css +503 -0
  56. package/src/tools.ts +4 -0
@@ -0,0 +1,503 @@
1
+ :root {
2
+ --three-body-ink: #24221d;
3
+ --three-body-muted: rgba(36, 34, 29, 0.56);
4
+ --three-body-card: #eee7d8;
5
+ --three-body-card-edge: rgba(73, 62, 42, 0.2);
6
+ --three-body-panel: rgba(255, 252, 239, 0.42);
7
+ --three-body-space: #e8dfc9;
8
+ --three-body-overlay: rgba(250, 246, 232, 0.58);
9
+ --three-body-overlay-strong: rgba(255, 252, 239, 0.8);
10
+ --three-body-control: rgba(49, 45, 36, 0.72);
11
+ --three-body-control-active: #24221d;
12
+ --three-body-shadow: rgba(55, 48, 38, 0.18);
13
+ }
14
+
15
+ .theme-dark {
16
+ --three-body-ink: #e8edf2;
17
+ --three-body-muted: rgba(232, 237, 242, 0.52);
18
+ --three-body-card: #071019;
19
+ --three-body-card-edge: rgba(255, 255, 255, 0.12);
20
+ --three-body-panel: rgba(255, 255, 255, 0.035);
21
+ --three-body-space: #050914;
22
+ --three-body-overlay: rgba(9, 15, 23, 0.55);
23
+ --three-body-overlay-strong: rgba(9, 15, 23, 0.78);
24
+ --three-body-control: rgba(232, 237, 242, 0.66);
25
+ --three-body-control-active: #f8fafc;
26
+ --three-body-shadow: rgba(0, 0, 0, 0.36);
27
+ }
28
+
29
+ .three-body-root {
30
+ display: grid;
31
+ gap: 0.75rem;
32
+ max-width: 1180px;
33
+ margin: 0 auto;
34
+ padding: 0.75rem;
35
+ border: 1px solid var(--three-body-card-edge);
36
+ border-radius: 8px;
37
+ background:
38
+ linear-gradient(90deg, rgba(36, 34, 29, 0.035) 1px, transparent 1px),
39
+ linear-gradient(rgba(36, 34, 29, 0.035) 1px, transparent 1px),
40
+ var(--three-body-card);
41
+ background-size: 24px 24px;
42
+ box-shadow: 0 22px 60px var(--three-body-shadow);
43
+ color: var(--three-body-ink);
44
+ }
45
+
46
+ .three-body-instrument-bar {
47
+ display: flex;
48
+ flex-wrap: wrap;
49
+ gap: 0.45rem;
50
+ justify-content: space-between;
51
+ padding-top: 0.15rem;
52
+ }
53
+
54
+ .theme-dark .three-body-root {
55
+ background:
56
+ radial-gradient(circle at 50% 38%, rgba(61, 79, 96, 0.18), transparent 42%),
57
+ linear-gradient(90deg, rgba(255, 255, 255, 0.035) 1px, transparent 1px),
58
+ linear-gradient(rgba(255, 255, 255, 0.035) 1px, transparent 1px),
59
+ var(--three-body-card);
60
+ background-size: auto, 26px 26px, 26px 26px, auto;
61
+ }
62
+
63
+ .three-body-stage {
64
+ overflow: hidden;
65
+ border: 1px solid var(--three-body-card-edge);
66
+ border-radius: 8px;
67
+ background: var(--three-body-space);
68
+ }
69
+
70
+ .three-body-sky {
71
+ position: relative;
72
+ min-height: 440px;
73
+ overflow: hidden;
74
+ background:
75
+ radial-gradient(circle at center, transparent 0 18%, rgba(36, 34, 29, 0.04) 18.2% 18.5%, transparent 18.8%),
76
+ linear-gradient(90deg, rgba(36, 34, 29, 0.065) 1px, transparent 1px),
77
+ linear-gradient(rgba(36, 34, 29, 0.065) 1px, transparent 1px),
78
+ var(--three-body-space);
79
+ background-size: auto, 32px 32px, 32px 32px, auto;
80
+ }
81
+
82
+ .theme-dark .three-body-sky {
83
+ background:
84
+ radial-gradient(circle at 18% 28%, rgba(89, 116, 135, 0.18), transparent 27%),
85
+ radial-gradient(circle at 82% 18%, rgba(160, 130, 87, 0.08), transparent 24%),
86
+ linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px),
87
+ linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
88
+ var(--three-body-space);
89
+ background-size: auto, auto, 34px 34px, 34px 34px, auto;
90
+ }
91
+
92
+ .three-body-sky canvas {
93
+ display: block;
94
+ width: 100%;
95
+ height: 100%;
96
+ min-height: 440px;
97
+ }
98
+
99
+ .three-body-presets,
100
+ .three-body-actions {
101
+ display: flex;
102
+ flex-wrap: wrap;
103
+ gap: 0.35rem;
104
+ min-width: 0;
105
+ }
106
+
107
+ .three-body-preset,
108
+ .three-body-action {
109
+ min-height: 32px;
110
+ padding: 0 0.72rem;
111
+ border: 1px solid var(--three-body-card-edge);
112
+ border-radius: 8px;
113
+ background: var(--three-body-overlay);
114
+ backdrop-filter: blur(12px);
115
+ color: var(--three-body-control);
116
+ cursor: pointer;
117
+ font-size: 0.72rem;
118
+ font-weight: 700;
119
+ letter-spacing: 0;
120
+ }
121
+
122
+ .three-body-preset.is-active,
123
+ .three-body-action:hover,
124
+ .three-body-preset:hover {
125
+ background: var(--three-body-overlay-strong);
126
+ color: var(--three-body-control-active);
127
+ }
128
+
129
+ .three-body-preset .short {
130
+ display: none;
131
+ }
132
+
133
+ .three-body-readout {
134
+ display: grid;
135
+ grid-template-columns: repeat(3, minmax(0, 1fr));
136
+ gap: 0;
137
+ opacity: 0.58;
138
+ transition: opacity 0.18s ease;
139
+ }
140
+
141
+ .three-body-readout:hover {
142
+ opacity: 1;
143
+ }
144
+
145
+ .three-body-readout div {
146
+ display: grid;
147
+ grid-template-columns: auto 1fr;
148
+ gap: 0.45rem;
149
+ align-items: baseline;
150
+ min-width: 0;
151
+ padding: 0.38rem 0.5rem;
152
+ border-top: 1px solid var(--three-body-card-edge);
153
+ border-right: 1px solid var(--three-body-card-edge);
154
+ background: var(--three-body-overlay);
155
+ backdrop-filter: blur(8px);
156
+ }
157
+
158
+ .three-body-readout div:last-child {
159
+ border-right: 0;
160
+ }
161
+
162
+ .three-body-readout span {
163
+ color: var(--three-body-muted);
164
+ font-size: 0.66rem;
165
+ }
166
+
167
+ .three-body-readout strong {
168
+ color: var(--three-body-control-active);
169
+ font-size: 0.78rem;
170
+ font-weight: 600;
171
+ }
172
+
173
+ .three-body-reticle {
174
+ position: absolute;
175
+ inset: 50% auto auto 50%;
176
+ width: 72px;
177
+ height: 72px;
178
+ border: 1px solid color-mix(in srgb, var(--three-body-control-active) 16%, transparent);
179
+ border-radius: 50%;
180
+ transform: translate(-50%, -50%);
181
+ pointer-events: none;
182
+ }
183
+
184
+ .three-body-reticle::before,
185
+ .three-body-reticle::after {
186
+ position: absolute;
187
+ inset: 50% auto auto 50%;
188
+ width: 142px;
189
+ height: 1px;
190
+ background: color-mix(in srgb, var(--three-body-control-active) 12%, transparent);
191
+ content: "";
192
+ transform: translate(-50%, -50%);
193
+ }
194
+
195
+ .three-body-reticle::after {
196
+ width: 1px;
197
+ height: 142px;
198
+ }
199
+
200
+ .three-body-console {
201
+ display: grid;
202
+ gap: 0.75rem;
203
+ align-content: center;
204
+ padding: 0.1rem;
205
+ }
206
+
207
+ .three-body-global-controls {
208
+ display: grid;
209
+ grid-template-columns: repeat(2, minmax(0, 1fr));
210
+ gap: 0.55rem;
211
+ padding: 0.25rem 0.05rem 0.7rem;
212
+ border-bottom: 1px solid var(--three-body-card-edge);
213
+ }
214
+
215
+ .three-body-body-controls {
216
+ display: grid;
217
+ grid-template-columns: repeat(3, minmax(0, 1fr));
218
+ gap: clamp(0.9rem, 2.5vw, 1.45rem);
219
+ }
220
+
221
+ .three-body-body-tabs {
222
+ display: none;
223
+ }
224
+
225
+ .three-body-panel {
226
+ position: relative;
227
+ display: grid;
228
+ gap: 0.58rem;
229
+ min-width: 0;
230
+ padding: 3.7rem 0 0;
231
+ border: 0;
232
+ border-radius: 0;
233
+ background: transparent;
234
+ overflow: visible;
235
+ }
236
+
237
+ .three-body-panel::before {
238
+ position: absolute;
239
+ inset: -0.35rem auto auto 0;
240
+ color: var(--body-color);
241
+ content: attr(data-body-label);
242
+ font-size: clamp(3rem, 6vw, 4.15rem);
243
+ font-weight: 700;
244
+ line-height: 1;
245
+ opacity: 0.11;
246
+ pointer-events: none;
247
+ }
248
+
249
+ .three-body-panel-title {
250
+ position: relative;
251
+ display: flex;
252
+ justify-content: flex-start;
253
+ min-height: 0;
254
+ }
255
+
256
+ .three-body-panel-title strong {
257
+ position: absolute;
258
+ top: -3.55rem;
259
+ left: 0.08rem;
260
+ font-size: clamp(3rem, 6vw, 4.15rem);
261
+ font-weight: 800;
262
+ line-height: 1;
263
+ opacity: 0.14;
264
+ pointer-events: none;
265
+ }
266
+
267
+ .three-body-scrub-row {
268
+ position: relative;
269
+ display: grid;
270
+ grid-template-columns: 3.2ch minmax(8ch, 1fr);
271
+ gap: 0.72rem;
272
+ align-items: center;
273
+ min-height: 54px;
274
+ padding: 0.5rem 0.25rem;
275
+ border: 1px solid transparent;
276
+ border-radius: 8px;
277
+ transition:
278
+ background 0.15s ease,
279
+ border-color 0.15s ease,
280
+ box-shadow 0.15s ease;
281
+ }
282
+
283
+ .three-body-scrub-row:hover {
284
+ border-color: transparent;
285
+ background: color-mix(in srgb, var(--three-body-overlay-strong) 28%, transparent);
286
+ box-shadow: 0 0 0 1px color-mix(in srgb, currentcolor 7%, transparent);
287
+ }
288
+
289
+ .three-body-scrub-row span {
290
+ color: var(--three-body-muted);
291
+ font-size: 0.95rem;
292
+ font-style: italic;
293
+ }
294
+
295
+ .three-body-scrub-input {
296
+ min-width: 0;
297
+ width: 100%;
298
+ height: 40px;
299
+ padding: 0 0.45rem 0 0.15rem;
300
+ border: 0;
301
+ border-bottom: 1px solid color-mix(in srgb, currentcolor 38%, transparent);
302
+ border-radius: 0;
303
+ background: transparent;
304
+ color: var(--three-body-control-active);
305
+ cursor: ew-resize;
306
+ font-size: clamp(1.12rem, 2vw, 1.42rem);
307
+ font-weight: 700;
308
+ outline: 0;
309
+ text-align: right;
310
+ }
311
+
312
+ .three-body-scrub-input:focus {
313
+ border-bottom-color: currentcolor;
314
+ background: color-mix(in srgb, var(--three-body-overlay-strong) 46%, transparent);
315
+ cursor: text;
316
+ }
317
+
318
+ @media (min-width: 760px) {
319
+ .three-body-root {
320
+ grid-template-areas:
321
+ "stage console"
322
+ "toolbar console";
323
+ grid-template-columns: minmax(0, 1.34fr) minmax(440px, 0.66fr);
324
+ gap: 1rem;
325
+ padding: 0.9rem;
326
+ align-items: stretch;
327
+ }
328
+
329
+ .three-body-stage {
330
+ grid-area: stage;
331
+ }
332
+
333
+ .three-body-console {
334
+ grid-area: console;
335
+ position: sticky;
336
+ top: 1rem;
337
+ min-height: 650px;
338
+ }
339
+
340
+ .three-body-instrument-bar {
341
+ grid-area: toolbar;
342
+ }
343
+
344
+ .three-body-sky,
345
+ .three-body-sky canvas {
346
+ min-height: 650px;
347
+ }
348
+
349
+ }
350
+
351
+ @media (max-width: 759px) {
352
+ .three-body-root {
353
+ gap: 0.55rem;
354
+ padding: 0.55rem;
355
+ }
356
+
357
+ .three-body-sky,
358
+ .three-body-sky canvas {
359
+ min-height: 310px;
360
+ }
361
+
362
+ .three-body-reticle {
363
+ width: 54px;
364
+ height: 54px;
365
+ }
366
+
367
+ .three-body-reticle::before {
368
+ width: 96px;
369
+ }
370
+
371
+ .three-body-reticle::after {
372
+ height: 96px;
373
+ }
374
+
375
+ .three-body-readout {
376
+ opacity: 0.74;
377
+ }
378
+
379
+ .three-body-readout div {
380
+ padding: 0.32rem 0.38rem;
381
+ }
382
+
383
+ .three-body-readout span,
384
+ .three-body-readout strong {
385
+ font-size: 0.62rem;
386
+ line-height: 1.1;
387
+ }
388
+
389
+ .three-body-console {
390
+ gap: 0.45rem;
391
+ align-content: start;
392
+ padding: 0;
393
+ }
394
+
395
+ .three-body-global-controls {
396
+ grid-template-columns: repeat(2, minmax(0, 1fr));
397
+ gap: 0.35rem;
398
+ padding: 0;
399
+ border-bottom: 0;
400
+ }
401
+
402
+ .three-body-global-controls .three-body-scrub-row {
403
+ min-height: 38px;
404
+ padding: 0.18rem 0.35rem;
405
+ }
406
+
407
+ .three-body-global-controls .three-body-scrub-input {
408
+ height: 30px;
409
+ font-size: 0.92rem;
410
+ }
411
+
412
+ .three-body-body-tabs {
413
+ display: grid;
414
+ grid-template-columns: repeat(3, 1fr);
415
+ gap: 0.35rem;
416
+ }
417
+
418
+ .three-body-tab {
419
+ min-height: 38px;
420
+ border: 1px solid var(--three-body-card-edge);
421
+ border-radius: 8px;
422
+ background: transparent;
423
+ color: var(--three-body-muted);
424
+ cursor: pointer;
425
+ font-size: 1.25rem;
426
+ font-weight: 800;
427
+ }
428
+
429
+ .three-body-tab.is-active {
430
+ background: var(--three-body-overlay-strong);
431
+ color: var(--three-body-control-active);
432
+ }
433
+
434
+ .three-body-body-controls {
435
+ grid-template-columns: 1fr;
436
+ min-height: 64px;
437
+ }
438
+
439
+ .three-body-panel {
440
+ display: none;
441
+ grid-template-columns: repeat(3, minmax(0, 1fr));
442
+ gap: 0.25rem;
443
+ padding: 0;
444
+ }
445
+
446
+ .three-body-panel.is-active {
447
+ display: grid;
448
+ }
449
+
450
+ .three-body-panel::before,
451
+ .three-body-panel-title {
452
+ display: none;
453
+ }
454
+
455
+ .three-body-scrub-row {
456
+ grid-template-columns: 1fr;
457
+ gap: 0.12rem;
458
+ min-height: 58px;
459
+ padding: 0.28rem 0.38rem;
460
+ }
461
+
462
+ .three-body-scrub-row span {
463
+ font-size: 0.72rem;
464
+ }
465
+
466
+ .three-body-scrub-input {
467
+ height: 32px;
468
+ padding: 0;
469
+ font-size: 1rem;
470
+ text-align: left;
471
+ }
472
+
473
+ .three-body-instrument-bar {
474
+ display: grid;
475
+ grid-template-columns: minmax(0, 1fr) auto;
476
+ gap: 0.35rem;
477
+ padding-top: 0;
478
+ }
479
+
480
+ .three-body-presets,
481
+ .three-body-actions {
482
+ display: grid;
483
+ grid-auto-flow: column;
484
+ grid-auto-columns: minmax(0, 1fr);
485
+ gap: 0.25rem;
486
+ }
487
+
488
+ .three-body-preset,
489
+ .three-body-action {
490
+ min-height: 34px;
491
+ padding: 0 0.42rem;
492
+ font-size: 0.66rem;
493
+ white-space: nowrap;
494
+ }
495
+
496
+ .three-body-preset .full {
497
+ display: none;
498
+ }
499
+
500
+ .three-body-preset .short {
501
+ display: inline;
502
+ }
503
+ }
package/src/tools.ts CHANGED
@@ -15,6 +15,8 @@ import { ENTROPY_SECOND_LAW_TOOL } from './tool/entropy-second-law/index';
15
15
  import { PHASE_DIAGRAM_CRITICAL_POINTS_TOOL } from './tool/phase-diagram-critical-points/index';
16
16
  import { TWIN_PARADOX_VISUALIZER_TOOL } from './tool/twin-paradox-visualizer/index';
17
17
  import { MANDELBROT_FRACTAL_TOOL } from './tool/mandelbrot-fractal/index';
18
+ import { PLANET_ATMOSPHERE_SURVIVAL_TOOL } from './tool/planet-atmosphere-survival/index';
19
+ import { THREE_BODY_PROBLEM_TOOL } from './tool/three-body-problem/index';
18
20
 
19
21
  export const ALL_TOOLS: ToolDefinition[] = [
20
22
  COLONY_COUNTER_TOOL,
@@ -32,4 +34,6 @@ export const ALL_TOOLS: ToolDefinition[] = [
32
34
  PHASE_DIAGRAM_CRITICAL_POINTS_TOOL,
33
35
  TWIN_PARADOX_VISUALIZER_TOOL,
34
36
  MANDELBROT_FRACTAL_TOOL,
37
+ PLANET_ATMOSPHERE_SURVIVAL_TOOL,
38
+ THREE_BODY_PROBLEM_TOOL,
35
39
  ];