@jjlmoya/utils-science 1.31.0 → 1.33.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 (53) 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/mandelbrot-fractal/bibliography.astro +14 -0
  8. package/src/tool/mandelbrot-fractal/bibliography.ts +16 -0
  9. package/src/tool/mandelbrot-fractal/component.astro +242 -0
  10. package/src/tool/mandelbrot-fractal/entry.ts +26 -0
  11. package/src/tool/mandelbrot-fractal/i18n/de.ts +159 -0
  12. package/src/tool/mandelbrot-fractal/i18n/en.ts +160 -0
  13. package/src/tool/mandelbrot-fractal/i18n/es.ts +159 -0
  14. package/src/tool/mandelbrot-fractal/i18n/fr.ts +159 -0
  15. package/src/tool/mandelbrot-fractal/i18n/id.ts +159 -0
  16. package/src/tool/mandelbrot-fractal/i18n/it.ts +159 -0
  17. package/src/tool/mandelbrot-fractal/i18n/ja.ts +159 -0
  18. package/src/tool/mandelbrot-fractal/i18n/ko.ts +159 -0
  19. package/src/tool/mandelbrot-fractal/i18n/nl.ts +159 -0
  20. package/src/tool/mandelbrot-fractal/i18n/pl.ts +159 -0
  21. package/src/tool/mandelbrot-fractal/i18n/pt.ts +159 -0
  22. package/src/tool/mandelbrot-fractal/i18n/ru.ts +159 -0
  23. package/src/tool/mandelbrot-fractal/i18n/sv.ts +159 -0
  24. package/src/tool/mandelbrot-fractal/i18n/tr.ts +159 -0
  25. package/src/tool/mandelbrot-fractal/i18n/zh.ts +159 -0
  26. package/src/tool/mandelbrot-fractal/index.ts +11 -0
  27. package/src/tool/mandelbrot-fractal/logic/MandelbrotEngine.ts +67 -0
  28. package/src/tool/mandelbrot-fractal/mandelbrot-fractal-calculator.css +357 -0
  29. package/src/tool/mandelbrot-fractal/seo.astro +15 -0
  30. package/src/tool/planet-atmosphere-survival/bibliography.astro +14 -0
  31. package/src/tool/planet-atmosphere-survival/bibliography.ts +16 -0
  32. package/src/tool/planet-atmosphere-survival/component.astro +404 -0
  33. package/src/tool/planet-atmosphere-survival/entry.ts +26 -0
  34. package/src/tool/planet-atmosphere-survival/i18n/de.ts +255 -0
  35. package/src/tool/planet-atmosphere-survival/i18n/en.ts +255 -0
  36. package/src/tool/planet-atmosphere-survival/i18n/es.ts +255 -0
  37. package/src/tool/planet-atmosphere-survival/i18n/fr.ts +255 -0
  38. package/src/tool/planet-atmosphere-survival/i18n/id.ts +255 -0
  39. package/src/tool/planet-atmosphere-survival/i18n/it.ts +255 -0
  40. package/src/tool/planet-atmosphere-survival/i18n/ja.ts +255 -0
  41. package/src/tool/planet-atmosphere-survival/i18n/ko.ts +255 -0
  42. package/src/tool/planet-atmosphere-survival/i18n/nl.ts +255 -0
  43. package/src/tool/planet-atmosphere-survival/i18n/pl.ts +255 -0
  44. package/src/tool/planet-atmosphere-survival/i18n/pt.ts +255 -0
  45. package/src/tool/planet-atmosphere-survival/i18n/ru.ts +255 -0
  46. package/src/tool/planet-atmosphere-survival/i18n/sv.ts +255 -0
  47. package/src/tool/planet-atmosphere-survival/i18n/tr.ts +255 -0
  48. package/src/tool/planet-atmosphere-survival/i18n/zh.ts +255 -0
  49. package/src/tool/planet-atmosphere-survival/index.ts +11 -0
  50. package/src/tool/planet-atmosphere-survival/logic.ts +201 -0
  51. package/src/tool/planet-atmosphere-survival/planet-atmosphere-survival-calculator.css +494 -0
  52. package/src/tool/planet-atmosphere-survival/seo.astro +15 -0
  53. package/src/tools.ts +4 -0
@@ -0,0 +1,357 @@
1
+ :root {
2
+ --mandel-bg: #f4f5f2;
3
+ --mandel-ink: #141820;
4
+ --mandel-muted: #5b6472;
5
+ --mandel-line: rgba(20, 24, 32, 0.12);
6
+ --mandel-panel: rgba(255, 255, 255, 0.86);
7
+ --mandel-hot: #e24d2f;
8
+ --mandel-active: #c9361f;
9
+ --mandel-cool: #159a9c;
10
+ --mandel-shadow: rgba(18, 24, 38, 0.14);
11
+ --mandel-radius: 10px;
12
+ }
13
+
14
+ .theme-dark {
15
+ --mandel-bg: #07090d;
16
+ --mandel-ink: #f2f6ff;
17
+ --mandel-muted: #8f98a8;
18
+ --mandel-line: rgba(242, 246, 255, 0.08);
19
+ --mandel-panel: rgba(10, 12, 16, 0.8);
20
+ --mandel-hot: #ff6b4a;
21
+ --mandel-active: #43d8c9;
22
+ --mandel-cool: #43d8c9;
23
+ --mandel-shadow: rgba(0, 0, 0, 0.36);
24
+ }
25
+
26
+ .mandelbrot-root {
27
+ display: grid;
28
+ gap: 1rem;
29
+ max-width: 1120px;
30
+ margin: 0 auto;
31
+ padding: 0.75rem;
32
+ color: var(--mandel-ink);
33
+ background:
34
+ radial-gradient(circle at 8% 0%, color-mix(in srgb, var(--mandel-hot) 16%, transparent), transparent 34%),
35
+ radial-gradient(circle at 92% 100%, color-mix(in srgb, var(--mandel-cool) 14%, transparent), transparent 36%),
36
+ var(--mandel-bg);
37
+ border: 1px solid var(--mandel-line);
38
+ border-radius: var(--mandel-radius);
39
+ }
40
+
41
+ .mandelbrot-stage {
42
+ position: relative;
43
+ min-height: 380px;
44
+ overflow: hidden;
45
+ background: #07080b;
46
+ border: 1px solid color-mix(in srgb, var(--mandel-cool) 24%, var(--mandel-line));
47
+ border-radius: calc(var(--mandel-radius) - 2px);
48
+ box-shadow:
49
+ 0 0 0 1px rgba(255, 255, 255, 0.02) inset,
50
+ 0 24px 70px var(--mandel-shadow),
51
+ 0 0 70px color-mix(in srgb, var(--mandel-hot) 18%, transparent);
52
+ }
53
+
54
+ .mandelbrot-canvas {
55
+ display: block;
56
+ width: 100%;
57
+ height: 100%;
58
+ min-height: 380px;
59
+ cursor: crosshair;
60
+ }
61
+
62
+ .mandelbrot-reticle {
63
+ position: absolute;
64
+ inset: 50% auto auto 50%;
65
+ width: 72px;
66
+ height: 72px;
67
+ border: 1px solid rgba(255, 255, 255, 0.55);
68
+ border-radius: 50%;
69
+ transform: translate(-50%, -50%);
70
+ pointer-events: none;
71
+ }
72
+
73
+ .mandelbrot-reticle::before,
74
+ .mandelbrot-reticle::after {
75
+ position: absolute;
76
+ content: "";
77
+ background: rgba(255, 255, 255, 0.5);
78
+ }
79
+
80
+ .mandelbrot-reticle::before {
81
+ left: 50%;
82
+ top: -18px;
83
+ width: 1px;
84
+ height: 108px;
85
+ }
86
+
87
+ .mandelbrot-reticle::after {
88
+ left: -18px;
89
+ top: 50%;
90
+ width: 108px;
91
+ height: 1px;
92
+ }
93
+
94
+ .mandelbrot-coordinate-strip {
95
+ position: absolute;
96
+ left: 0.75rem;
97
+ right: 0.75rem;
98
+ bottom: 0.75rem;
99
+ display: flex;
100
+ flex-wrap: wrap;
101
+ gap: 0.35rem 0.75rem;
102
+ justify-content: space-between;
103
+ padding: 0.75rem;
104
+ color: #f8fafc;
105
+ background: rgba(7, 8, 11, 0.74);
106
+ border: 1px solid rgba(255, 255, 255, 0.14);
107
+ border-radius: calc(var(--mandel-radius) - 2px);
108
+ backdrop-filter: blur(14px);
109
+ }
110
+
111
+ .mandelbrot-coordinate-strip span,
112
+ .mandelbrot-readouts span,
113
+ .mandelbrot-control span {
114
+ font-size: 0.65rem;
115
+ font-weight: 700;
116
+ letter-spacing: 0.12em;
117
+ text-transform: uppercase;
118
+ color: var(--mandel-muted);
119
+ }
120
+
121
+ .mandelbrot-coordinate-strip span {
122
+ color: rgba(255, 255, 255, 0.72);
123
+ }
124
+
125
+ .mandelbrot-coordinate-strip strong {
126
+ font-size: 0.9rem;
127
+ font-weight: 450;
128
+ color: #fff;
129
+ overflow-wrap: anywhere;
130
+ }
131
+
132
+ .mandelbrot-panel {
133
+ display: flex;
134
+ flex-direction: column;
135
+ gap: 2rem;
136
+ padding: 1.25rem;
137
+ background: var(--mandel-panel);
138
+ border: 1px solid var(--mandel-line);
139
+ border-radius: calc(var(--mandel-radius) - 2px);
140
+ backdrop-filter: blur(12px);
141
+ }
142
+
143
+ .mandelbrot-presets {
144
+ display: grid;
145
+ grid-template-columns: 1fr;
146
+ gap: 0;
147
+ overflow: hidden;
148
+ border: 1px solid var(--mandel-line);
149
+ border-radius: calc(var(--mandel-radius) - 2px);
150
+ }
151
+
152
+ .mandelbrot-preset {
153
+ min-height: 42px;
154
+ padding: 0.7rem 0.85rem;
155
+ color: var(--mandel-ink);
156
+ background: transparent;
157
+ border: 0;
158
+ border-bottom: 1px solid var(--mandel-line);
159
+ font-size: 0.78rem;
160
+ font-weight: 750;
161
+ letter-spacing: 0.02em;
162
+ cursor: pointer;
163
+ }
164
+
165
+ .mandelbrot-preset:last-child {
166
+ border-bottom: 0;
167
+ }
168
+
169
+ .mandelbrot-preset.active,
170
+ .mandelbrot-preset:hover {
171
+ color: var(--mandel-ink);
172
+ background: color-mix(in srgb, var(--mandel-active) 11%, transparent);
173
+ box-shadow: inset 0 -2px 0 var(--mandel-active);
174
+ }
175
+
176
+ .theme-dark .mandelbrot-preset.active,
177
+ .theme-dark .mandelbrot-preset:hover {
178
+ color: #fff;
179
+ background: rgba(255, 255, 255, 0.06);
180
+ box-shadow: inset 0 -2px 0 var(--mandel-active);
181
+ }
182
+
183
+ .mandelbrot-reset-button {
184
+ align-self: flex-start;
185
+ min-height: 30px;
186
+ padding: 0;
187
+ color: var(--mandel-muted);
188
+ background: transparent;
189
+ border: 0;
190
+ border-bottom: 1px solid transparent;
191
+ font-size: 0.68rem;
192
+ font-weight: 700;
193
+ letter-spacing: 0.12em;
194
+ text-transform: uppercase;
195
+ cursor: pointer;
196
+ }
197
+
198
+ .mandelbrot-reset-button:hover {
199
+ color: var(--mandel-ink);
200
+ border-bottom-color: var(--mandel-active);
201
+ }
202
+
203
+ .mandelbrot-readouts {
204
+ display: grid;
205
+ grid-template-columns: 1fr;
206
+ gap: 1.15rem;
207
+ }
208
+
209
+ .mandelbrot-readout {
210
+ display: grid;
211
+ gap: 0.3rem;
212
+ padding-bottom: 1.1rem;
213
+ border-bottom: 1px solid var(--mandel-line);
214
+ }
215
+
216
+ .mandelbrot-readouts strong {
217
+ font-size: 1rem;
218
+ font-weight: 400;
219
+ line-height: 1.1;
220
+ letter-spacing: 0;
221
+ color: var(--mandel-ink);
222
+ overflow-wrap: anywhere;
223
+ }
224
+
225
+ .mandelbrot-readout-hero strong {
226
+ font-size: clamp(2rem, 9vw, 2.65rem);
227
+ font-weight: 300;
228
+ letter-spacing: -0.04em;
229
+ color: var(--mandel-ink);
230
+ text-shadow: 0 0 20px rgba(255, 255, 255, 0.1);
231
+ }
232
+
233
+ .theme-dark .mandelbrot-readout-hero strong {
234
+ color: #fff;
235
+ }
236
+
237
+ .mandelbrot-controls {
238
+ display: grid;
239
+ gap: 1.1rem;
240
+ }
241
+
242
+ .mandelbrot-control {
243
+ display: grid;
244
+ gap: 0.4rem;
245
+ }
246
+
247
+ .mandelbrot-control input,
248
+ .mandelbrot-control select {
249
+ width: 100%;
250
+ min-height: 42px;
251
+ }
252
+
253
+ .mandelbrot-control input[type="range"] {
254
+ -webkit-appearance: none;
255
+ appearance: none;
256
+ min-height: 28px;
257
+ background: transparent;
258
+ cursor: pointer;
259
+ }
260
+
261
+ .mandelbrot-control input[type="range"]::-webkit-slider-runnable-track {
262
+ height: 2px;
263
+ background: var(--mandel-line);
264
+ border-radius: 999px;
265
+ }
266
+
267
+ .mandelbrot-control input[type="range"]::-moz-range-track {
268
+ height: 2px;
269
+ background: var(--mandel-line);
270
+ border-radius: 999px;
271
+ }
272
+
273
+ .mandelbrot-control input[type="range"]::-webkit-slider-thumb {
274
+ -webkit-appearance: none;
275
+ appearance: none;
276
+ width: 8px;
277
+ height: 8px;
278
+ margin-top: -3px;
279
+ background: var(--mandel-ink);
280
+ border: 0;
281
+ border-radius: 50%;
282
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--mandel-ink) 10%, transparent);
283
+ }
284
+
285
+ .mandelbrot-control input[type="range"]::-moz-range-thumb {
286
+ width: 8px;
287
+ height: 8px;
288
+ background: var(--mandel-ink);
289
+ border: 0;
290
+ border-radius: 50%;
291
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--mandel-ink) 10%, transparent);
292
+ }
293
+
294
+ .theme-dark .mandelbrot-control input[type="range"]::-webkit-slider-thumb {
295
+ background: #fff;
296
+ box-shadow: 0 0 14px rgba(255, 255, 255, 0.45);
297
+ }
298
+
299
+ .theme-dark .mandelbrot-control input[type="range"]::-moz-range-thumb {
300
+ background: #fff;
301
+ box-shadow: 0 0 14px rgba(255, 255, 255, 0.45);
302
+ }
303
+
304
+ .mandelbrot-control select {
305
+ -webkit-appearance: none;
306
+ -moz-appearance: none;
307
+ appearance: none;
308
+ padding: 0 1.85rem 0 0;
309
+ color: var(--mandel-ink);
310
+ background-color: transparent;
311
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23141820' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
312
+ background-position: right 0.05rem center;
313
+ background-repeat: no-repeat;
314
+ border: 0;
315
+ border-bottom: 1px solid var(--mandel-line);
316
+ border-radius: 0;
317
+ font-size: 0.95rem;
318
+ }
319
+
320
+ .theme-dark .mandelbrot-control select {
321
+ background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'><path d='m6 9 6 6 6-6'/></svg>");
322
+ }
323
+
324
+ .mandelbrot-control select option {
325
+ color: #141820;
326
+ background: #fff;
327
+ }
328
+
329
+ .theme-dark .mandelbrot-control select option {
330
+ color: #f2f6ff;
331
+ background: #111722;
332
+ }
333
+
334
+ @media (min-width: 760px) {
335
+ .mandelbrot-root {
336
+ grid-template-columns: minmax(0, 1.55fr) minmax(300px, 0.45fr);
337
+ padding: 1rem;
338
+ }
339
+
340
+ .mandelbrot-stage,
341
+ .mandelbrot-canvas {
342
+ min-height: 640px;
343
+ }
344
+
345
+ .mandelbrot-presets {
346
+ grid-template-columns: repeat(3, 1fr);
347
+ }
348
+
349
+ .mandelbrot-preset {
350
+ border-right: 1px solid var(--mandel-line);
351
+ border-bottom: 0;
352
+ }
353
+
354
+ .mandelbrot-preset:last-child {
355
+ border-right: 0;
356
+ }
357
+ }
@@ -0,0 +1,15 @@
1
+ ---
2
+ import { SEORenderer } from '@jjlmoya/utils-shared';
3
+ import { mandelbrotFractal } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'en' } = Astro.props;
11
+ const content = await mandelbrotFractal.i18n[locale]?.();
12
+ if (!content) return null;
13
+ ---
14
+
15
+ {content.seo?.length > 0 && <SEORenderer content={{ locale, sections: content.seo }} />}
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { Bibliography as SharedBibliography } from '@jjlmoya/utils-shared';
3
+ import { planetAtmosphereSurvival } from './index';
4
+ import type { KnownLocale } from '../../types';
5
+
6
+ interface Props {
7
+ locale?: KnownLocale;
8
+ }
9
+
10
+ const { locale = 'en' } = Astro.props;
11
+ const content = await planetAtmosphereSurvival.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <SharedBibliography links={content.bibliography} />}
@@ -0,0 +1,16 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ {
5
+ name: 'NASA Space Science Data Coordinated Archive, Planetary Fact Sheets',
6
+ url: 'https://science.gsfc.nasa.gov/solarsystem/dataarchives/projects/629/',
7
+ },
8
+ {
9
+ name: 'NASA, Human Integration Design Handbook',
10
+ url: 'https://www.nasa.gov/human-integration-design-handbook/',
11
+ },
12
+ {
13
+ name: 'NOAA National Weather Service, Wind Chill Temperature Index',
14
+ url: 'https://www.weather.gov/ddc/windchillddc',
15
+ },
16
+ ];