@jjlmoya/utils-astronomy 1.23.0 → 1.25.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 (71) hide show
  1. package/package.json +2 -2
  2. package/src/category/i18n/de.ts +57 -57
  3. package/src/category/i18n/en.ts +1 -1
  4. package/src/category/i18n/es.ts +1 -1
  5. package/src/category/i18n/fr.ts +58 -58
  6. package/src/category/i18n/it.ts +1 -1
  7. package/src/category/i18n/nl.ts +57 -57
  8. package/src/category/i18n/pl.ts +57 -57
  9. package/src/category/i18n/pt.ts +1 -1
  10. package/src/category/i18n/ru.ts +57 -57
  11. package/src/category/i18n/sv.ts +57 -57
  12. package/src/category/i18n/zh.ts +57 -57
  13. package/src/category/index.ts +30 -30
  14. package/src/category/seo.astro +15 -15
  15. package/src/components/PreviewNavSidebar.astro +116 -116
  16. package/src/components/PreviewToolbar.astro +143 -143
  17. package/src/data.ts +16 -16
  18. package/src/env.d.ts +5 -5
  19. package/src/index.ts +22 -22
  20. package/src/layouts/PreviewLayout.astro +122 -122
  21. package/src/pages/[locale].astro +251 -251
  22. package/src/pages/index.astro +4 -4
  23. package/src/tests/bibliography_wellformed_export.test.ts +46 -0
  24. package/src/tests/category_seo_quality.test.ts +74 -0
  25. package/src/tests/faq_count.test.ts +1 -1
  26. package/src/tests/mocks/astro_mock.js +2 -2
  27. package/src/tests/no_h1_in_components.test.ts +1 -1
  28. package/src/tests/seo_length.test.ts +1 -1
  29. package/src/tests/seo_parity.test.ts +2 -2
  30. package/src/tests/seo_translation_completeness.test.ts +69 -0
  31. package/src/tests/seo_wellformed_export.test.ts +65 -0
  32. package/src/tests/spanish_leakage.test.ts +5 -1
  33. package/src/tests/tool_structure.test.ts +71 -71
  34. package/src/tests/tool_validation.test.ts +146 -146
  35. package/src/tool/bortleVisualizer/bibliography.astro +14 -14
  36. package/src/tool/bortleVisualizer/bibliography.ts +8 -8
  37. package/src/tool/bortleVisualizer/i18n/pl.ts +159 -159
  38. package/src/tool/bortleVisualizer/i18n/ru.ts +159 -159
  39. package/src/tool/deepSpaceScope/bibliography.astro +14 -14
  40. package/src/tool/deepSpaceScope/component.astro +382 -382
  41. package/src/tool/deepSpaceScope/i18n/de.ts +172 -172
  42. package/src/tool/deepSpaceScope/i18n/ko.ts +172 -172
  43. package/src/tool/deepSpaceScope/i18n/pl.ts +172 -172
  44. package/src/tool/deepSpaceScope/i18n/ru.ts +172 -172
  45. package/src/tool/deepSpaceScope/i18n/zh.ts +172 -172
  46. package/src/tool/smartEyepieceCalculator/component.astro +125 -125
  47. package/src/tool/smartEyepieceCalculator/i18n/fr.ts +165 -165
  48. package/src/tool/smartEyepieceCalculator/i18n/ru.ts +165 -165
  49. package/src/tool/smartEyepieceCalculator/i18n/zh.ts +165 -165
  50. package/src/tool/starExposureCalculator/bibliography.astro +14 -14
  51. package/src/tool/starExposureCalculator/bibliography.ts +7 -7
  52. package/src/tool/starExposureCalculator/component.astro +249 -249
  53. package/src/tool/starExposureCalculator/i18n/pl.ts +156 -156
  54. package/src/tool/starExposureCalculator/i18n/ru.ts +156 -156
  55. package/src/tool/telescopeResolution/bibliography.astro +14 -14
  56. package/src/tool/telescopeResolution/component.astro +222 -222
  57. package/src/tool/telescopeResolution/i18n/de.ts +169 -169
  58. package/src/tool/telescopeResolution/i18n/en.ts +169 -169
  59. package/src/tool/telescopeResolution/i18n/es.ts +169 -169
  60. package/src/tool/telescopeResolution/i18n/fr.ts +169 -169
  61. package/src/tool/telescopeResolution/i18n/id.ts +169 -169
  62. package/src/tool/telescopeResolution/i18n/it.ts +169 -169
  63. package/src/tool/telescopeResolution/i18n/ja.ts +169 -169
  64. package/src/tool/telescopeResolution/i18n/ko.ts +169 -169
  65. package/src/tool/telescopeResolution/i18n/nl.ts +169 -169
  66. package/src/tool/telescopeResolution/i18n/pl.ts +169 -169
  67. package/src/tool/telescopeResolution/i18n/pt.ts +169 -169
  68. package/src/tool/telescopeResolution/i18n/ru.ts +169 -169
  69. package/src/tool/telescopeResolution/i18n/sv.ts +169 -169
  70. package/src/tool/telescopeResolution/i18n/tr.ts +169 -169
  71. package/src/tool/telescopeResolution/i18n/zh.ts +169 -169
@@ -1,222 +1,222 @@
1
- ---
2
- import type { TelescopeResolutionUI } from './index';
3
- interface Props {
4
- ui: TelescopeResolutionUI;
5
- }
6
-
7
- const { ui } = Astro.props;
8
- ---
9
-
10
- <script define:vars={{ ui }} is:inline>
11
- window.__telescopeUI = ui;
12
- </script>
13
-
14
- <div class="tscope-wrapper" id="tscope-root">
15
- <div class="tscope-grid">
16
- <div class="tscope-controls">
17
- <div class="tscope-control-group">
18
- <label class="tscope-control-label" for="aperture-input">{ui.apertureLabel}</label>
19
- <div class="tscope-stepper">
20
- <button class="tscope-step-btn" data-action="dec" data-target="aperture">-</button>
21
- <input type="number" id="aperture-input" value="150" min="1" max="2000" class="tscope-stepper-input" />
22
- <button class="tscope-step-btn" data-action="inc" data-target="aperture">+</button>
23
- </div>
24
- </div>
25
-
26
- <div class="tscope-control-group">
27
- <label class="tscope-control-label" for="unit-selector">{ui.unitLabel}</label>
28
- <div class="tscope-select-wrapper">
29
- <select id="unit-selector" class="tscope-select">
30
- <option value="mm">{ui.mmUnit}</option>
31
- <option value="in">{ui.inUnit}</option>
32
- </select>
33
- <svg class="tscope-select-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
34
- <polyline points="6 9 12 15 18 9"></polyline>
35
- </svg>
36
- </div>
37
- </div>
38
-
39
- <div class="tscope-control-group">
40
- <label class="tscope-control-label" for="preset-selector">{ui.presetsLabel}</label>
41
- <div class="tscope-select-wrapper">
42
- <select id="preset-selector" class="tscope-select">
43
- <option value="">{ui.presetsPlaceholder}</option>
44
- {ui.presets.map((preset: { value: string; label: string }) => <option value={preset.value}>{preset.label}</option>)}
45
- </select>
46
- <svg class="tscope-select-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
47
- <polyline points="6 9 12 15 18 9"></polyline>
48
- </svg>
49
- </div>
50
- </div>
51
-
52
- <div class="tscope-control-group">
53
- <label class="tscope-control-label">
54
- {ui.seeingLabel}: <span id="seeing-value">1.0</span>"
55
- </label>
56
- <input type="range" id="seeing-input" min="0.5" max="3.0" step="0.1" value="1.0" class="tscope-range" aria-label={ui.seeingLabel} />
57
- </div>
58
- </div>
59
-
60
- <div class="tscope-results">
61
- <div class="tscope-main-result">
62
- <h4 class="tscope-result-title">{ui.dawesLabel}</h4>
63
- <div class="tscope-resolution-value">
64
- <span id="dawes-result" class="tscope-resolution-number">0.77</span>
65
- <span class="tscope-resolution-unit">{ui.arcsecUnit}</span>
66
- </div>
67
- </div>
68
-
69
- <div class="tscope-seeing-alert" id="seeing-alert">
70
- <span id="seeing-alert-prefix">{ui.seeingAlertPrefix}</span>
71
- <span id="seeing-alert-suffix">{ui.seeingAlertSuffix}</span>
72
- </div>
73
-
74
- <div class="tscope-comp-grid">
75
- <div class="tscope-comp-card">
76
- <h4 class="tscope-comp-title">{ui.rayleighLabel}</h4>
77
- <span class="tscope-comp-value" id="rayleigh-result">0.92</span>"
78
- </div>
79
- <div class="tscope-comp-card">
80
- <h4 class="tscope-comp-title">{ui.maxMagLabel}</h4>
81
- <span class="tscope-comp-value" id="max-mag-result">300</span>x
82
- </div>
83
- </div>
84
-
85
- <div class="tscope-visualization">
86
- <label class="tscope-vis-label">{ui.simLabel}</label>
87
- <div class="tscope-sim-container">
88
- <div class="tscope-binary-system" id="binary-system">
89
- <div class="tscope-star" id="star-1"></div>
90
- <div class="tscope-star" id="star-2"></div>
91
- </div>
92
- </div>
93
- <p class="tscope-sim-explanation">{ui.simExplanation}</p>
94
- </div>
95
- </div>
96
- </div>
97
- </div>
98
-
99
- <script>
100
- import { calculateResolution, inchesToMm, mmToInches } from './logic';
101
-
102
- const seeingAlertPrefix = document.getElementById('seeing-alert-prefix');
103
- const seeingValueDisplay = document.getElementById('seeing-value');
104
-
105
- function updateSeeingAlert() {
106
- if (seeingAlertPrefix && seeingValueDisplay) {
107
- const seeingVal = seeingValueDisplay.textContent;
108
- const originalPrefix = seeingAlertPrefix.textContent || '';
109
- seeingAlertPrefix.textContent = `${originalPrefix} (${seeingVal}")`;
110
- }
111
- }
112
-
113
- class ResolutionApp {
114
- apertureInput: HTMLInputElement;
115
- unitSelector: HTMLSelectElement;
116
- presetSelector: HTMLSelectElement;
117
- seeingInput: HTMLInputElement;
118
- dawesDisplay: HTMLElement;
119
- rayleighDisplay: HTMLElement;
120
- maxMagDisplay: HTMLElement;
121
- seeingDisplay: HTMLElement;
122
- star1: HTMLElement;
123
- star2: HTMLElement;
124
- stepBtns: NodeListOf<HTMLButtonElement> | undefined;
125
-
126
- constructor() {
127
- this.apertureInput = document.getElementById('aperture-input') as HTMLInputElement;
128
- this.unitSelector = document.getElementById('unit-selector') as HTMLSelectElement;
129
- this.presetSelector = document.getElementById('preset-selector') as HTMLSelectElement;
130
- this.seeingInput = document.getElementById('seeing-input') as HTMLInputElement;
131
- this.dawesDisplay = document.getElementById('dawes-result') as HTMLElement;
132
- this.rayleighDisplay = document.getElementById('rayleigh-result') as HTMLElement;
133
- this.maxMagDisplay = document.getElementById('max-mag-result') as HTMLElement;
134
- this.seeingDisplay = document.getElementById('seeing-value') as HTMLElement;
135
- this.star1 = document.getElementById('star-1') as HTMLElement;
136
- this.star2 = document.getElementById('star-2') as HTMLElement;
137
- this.stepBtns = document.querySelectorAll('.tscope-step-btn');
138
- this.init();
139
- }
140
-
141
- bindStepButtons() {
142
- this.stepBtns.forEach((btn) => {
143
- btn.addEventListener('click', () => {
144
- const action = btn.dataset.action;
145
- let val = parseFloat(this.apertureInput.value);
146
- if (action === 'inc') val += this.unitSelector.value === 'mm' ? 10 : 0.5;
147
- if (action === 'dec') val -= this.unitSelector.value === 'mm' ? 10 : 0.5;
148
- this.apertureInput.value = Math.max(1, val).toString();
149
- this.calculate();
150
- });
151
- });
152
- }
153
-
154
- bindUnitSelector() {
155
- this.unitSelector.addEventListener('change', () => {
156
- const val = parseFloat(this.apertureInput.value);
157
- if (this.unitSelector.value === 'in') {
158
- this.apertureInput.value = mmToInches(val).toFixed(1);
159
- } else {
160
- this.apertureInput.value = inchesToMm(val).toFixed(0);
161
- }
162
- this.calculate();
163
- });
164
- }
165
-
166
- init() {
167
- this.bindStepButtons();
168
- this.apertureInput.addEventListener('input', () => this.calculate());
169
- this.bindUnitSelector();
170
- this.presetSelector.addEventListener('change', () => {
171
- const val = this.presetSelector.value;
172
- if (val) {
173
- this.unitSelector.value = 'mm';
174
- this.apertureInput.value = val;
175
- this.calculate();
176
- }
177
- });
178
- this.seeingInput.addEventListener('input', () => {
179
- this.seeingDisplay.textContent = this.seeingInput.value;
180
- updateSeeingAlert();
181
- this.calculate();
182
- });
183
- this.calculate();
184
- }
185
-
186
- calculate() {
187
- let apertureMm = parseFloat(this.apertureInput.value) || 1;
188
- if (this.unitSelector.value === 'in') {
189
- apertureMm = inchesToMm(apertureMm);
190
- }
191
- const seeing = parseFloat(this.seeingInput.value);
192
- const result = calculateResolution(apertureMm, seeing);
193
-
194
- this.dawesDisplay.textContent = result.dawes.toFixed(2);
195
- this.rayleighDisplay.textContent = result.rayleigh.toFixed(2);
196
- this.maxMagDisplay.textContent = Math.round(result.maxMagnification).toString();
197
-
198
- this.updateSimulation(result.dawes);
199
- }
200
-
201
- updateSimulation(dawes: number) {
202
- const baseBlur = Math.max(0, dawes * 3);
203
- const separation = Math.max(8, 30 - dawes * 15);
204
-
205
- if (this.star1 && this.star2) {
206
- this.star1.style.setProperty('--star-blur', `${baseBlur}px`);
207
- this.star2.style.setProperty('--star-blur', `${baseBlur}px`);
208
- const container = document.getElementById('binary-system');
209
- if (container) {
210
- container.style.gap = `${separation}px`;
211
- }
212
- const scale = Math.max(0.5, 2.5 - dawes / 1.5);
213
- this.star1.style.transform = `scale(${scale})`;
214
- this.star2.style.transform = `scale(${scale})`;
215
- }
216
- }
217
- }
218
-
219
- new ResolutionApp();
220
- updateSeeingAlert();
221
- </script>
222
-
1
+ ---
2
+ import type { TelescopeResolutionUI } from './index';
3
+ interface Props {
4
+ ui: TelescopeResolutionUI;
5
+ }
6
+
7
+ const { ui } = Astro.props;
8
+ ---
9
+
10
+ <script define:vars={{ ui }} is:inline>
11
+ window.__telescopeUI = ui;
12
+ </script>
13
+
14
+ <div class="tscope-wrapper" id="tscope-root">
15
+ <div class="tscope-grid">
16
+ <div class="tscope-controls">
17
+ <div class="tscope-control-group">
18
+ <label class="tscope-control-label" for="aperture-input">{ui.apertureLabel}</label>
19
+ <div class="tscope-stepper">
20
+ <button class="tscope-step-btn" data-action="dec" data-target="aperture">-</button>
21
+ <input type="number" id="aperture-input" value="150" min="1" max="2000" class="tscope-stepper-input" />
22
+ <button class="tscope-step-btn" data-action="inc" data-target="aperture">+</button>
23
+ </div>
24
+ </div>
25
+
26
+ <div class="tscope-control-group">
27
+ <label class="tscope-control-label" for="unit-selector">{ui.unitLabel}</label>
28
+ <div class="tscope-select-wrapper">
29
+ <select id="unit-selector" class="tscope-select">
30
+ <option value="mm">{ui.mmUnit}</option>
31
+ <option value="in">{ui.inUnit}</option>
32
+ </select>
33
+ <svg class="tscope-select-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
34
+ <polyline points="6 9 12 15 18 9"></polyline>
35
+ </svg>
36
+ </div>
37
+ </div>
38
+
39
+ <div class="tscope-control-group">
40
+ <label class="tscope-control-label" for="preset-selector">{ui.presetsLabel}</label>
41
+ <div class="tscope-select-wrapper">
42
+ <select id="preset-selector" class="tscope-select">
43
+ <option value="">{ui.presetsPlaceholder}</option>
44
+ {ui.presets.map((preset: { value: string; label: string }) => <option value={preset.value}>{preset.label}</option>)}
45
+ </select>
46
+ <svg class="tscope-select-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
47
+ <polyline points="6 9 12 15 18 9"></polyline>
48
+ </svg>
49
+ </div>
50
+ </div>
51
+
52
+ <div class="tscope-control-group">
53
+ <label class="tscope-control-label">
54
+ {ui.seeingLabel}: <span id="seeing-value">1.0</span>"
55
+ </label>
56
+ <input type="range" id="seeing-input" min="0.5" max="3.0" step="0.1" value="1.0" class="tscope-range" aria-label={ui.seeingLabel} />
57
+ </div>
58
+ </div>
59
+
60
+ <div class="tscope-results">
61
+ <div class="tscope-main-result">
62
+ <h4 class="tscope-result-title">{ui.dawesLabel}</h4>
63
+ <div class="tscope-resolution-value">
64
+ <span id="dawes-result" class="tscope-resolution-number">0.77</span>
65
+ <span class="tscope-resolution-unit">{ui.arcsecUnit}</span>
66
+ </div>
67
+ </div>
68
+
69
+ <div class="tscope-seeing-alert" id="seeing-alert">
70
+ <span id="seeing-alert-prefix">{ui.seeingAlertPrefix}</span>
71
+ <span id="seeing-alert-suffix">{ui.seeingAlertSuffix}</span>
72
+ </div>
73
+
74
+ <div class="tscope-comp-grid">
75
+ <div class="tscope-comp-card">
76
+ <h4 class="tscope-comp-title">{ui.rayleighLabel}</h4>
77
+ <span class="tscope-comp-value" id="rayleigh-result">0.92</span>"
78
+ </div>
79
+ <div class="tscope-comp-card">
80
+ <h4 class="tscope-comp-title">{ui.maxMagLabel}</h4>
81
+ <span class="tscope-comp-value" id="max-mag-result">300</span>x
82
+ </div>
83
+ </div>
84
+
85
+ <div class="tscope-visualization">
86
+ <label class="tscope-vis-label">{ui.simLabel}</label>
87
+ <div class="tscope-sim-container">
88
+ <div class="tscope-binary-system" id="binary-system">
89
+ <div class="tscope-star" id="star-1"></div>
90
+ <div class="tscope-star" id="star-2"></div>
91
+ </div>
92
+ </div>
93
+ <p class="tscope-sim-explanation">{ui.simExplanation}</p>
94
+ </div>
95
+ </div>
96
+ </div>
97
+ </div>
98
+
99
+ <script>
100
+ import { calculateResolution, inchesToMm, mmToInches } from './logic';
101
+
102
+ const seeingAlertPrefix = document.getElementById('seeing-alert-prefix');
103
+ const seeingValueDisplay = document.getElementById('seeing-value');
104
+
105
+ function updateSeeingAlert() {
106
+ if (seeingAlertPrefix && seeingValueDisplay) {
107
+ const seeingVal = seeingValueDisplay.textContent;
108
+ const originalPrefix = seeingAlertPrefix.textContent || '';
109
+ seeingAlertPrefix.textContent = `${originalPrefix} (${seeingVal}")`;
110
+ }
111
+ }
112
+
113
+ class ResolutionApp {
114
+ apertureInput: HTMLInputElement;
115
+ unitSelector: HTMLSelectElement;
116
+ presetSelector: HTMLSelectElement;
117
+ seeingInput: HTMLInputElement;
118
+ dawesDisplay: HTMLElement;
119
+ rayleighDisplay: HTMLElement;
120
+ maxMagDisplay: HTMLElement;
121
+ seeingDisplay: HTMLElement;
122
+ star1: HTMLElement;
123
+ star2: HTMLElement;
124
+ stepBtns: NodeListOf<HTMLButtonElement> | undefined;
125
+
126
+ constructor() {
127
+ this.apertureInput = document.getElementById('aperture-input') as HTMLInputElement;
128
+ this.unitSelector = document.getElementById('unit-selector') as HTMLSelectElement;
129
+ this.presetSelector = document.getElementById('preset-selector') as HTMLSelectElement;
130
+ this.seeingInput = document.getElementById('seeing-input') as HTMLInputElement;
131
+ this.dawesDisplay = document.getElementById('dawes-result') as HTMLElement;
132
+ this.rayleighDisplay = document.getElementById('rayleigh-result') as HTMLElement;
133
+ this.maxMagDisplay = document.getElementById('max-mag-result') as HTMLElement;
134
+ this.seeingDisplay = document.getElementById('seeing-value') as HTMLElement;
135
+ this.star1 = document.getElementById('star-1') as HTMLElement;
136
+ this.star2 = document.getElementById('star-2') as HTMLElement;
137
+ this.stepBtns = document.querySelectorAll('.tscope-step-btn');
138
+ this.init();
139
+ }
140
+
141
+ bindStepButtons() {
142
+ this.stepBtns.forEach((btn) => {
143
+ btn.addEventListener('click', () => {
144
+ const action = btn.dataset.action;
145
+ let val = parseFloat(this.apertureInput.value);
146
+ if (action === 'inc') val += this.unitSelector.value === 'mm' ? 10 : 0.5;
147
+ if (action === 'dec') val -= this.unitSelector.value === 'mm' ? 10 : 0.5;
148
+ this.apertureInput.value = Math.max(1, val).toString();
149
+ this.calculate();
150
+ });
151
+ });
152
+ }
153
+
154
+ bindUnitSelector() {
155
+ this.unitSelector.addEventListener('change', () => {
156
+ const val = parseFloat(this.apertureInput.value);
157
+ if (this.unitSelector.value === 'in') {
158
+ this.apertureInput.value = mmToInches(val).toFixed(1);
159
+ } else {
160
+ this.apertureInput.value = inchesToMm(val).toFixed(0);
161
+ }
162
+ this.calculate();
163
+ });
164
+ }
165
+
166
+ init() {
167
+ this.bindStepButtons();
168
+ this.apertureInput.addEventListener('input', () => this.calculate());
169
+ this.bindUnitSelector();
170
+ this.presetSelector.addEventListener('change', () => {
171
+ const val = this.presetSelector.value;
172
+ if (val) {
173
+ this.unitSelector.value = 'mm';
174
+ this.apertureInput.value = val;
175
+ this.calculate();
176
+ }
177
+ });
178
+ this.seeingInput.addEventListener('input', () => {
179
+ this.seeingDisplay.textContent = this.seeingInput.value;
180
+ updateSeeingAlert();
181
+ this.calculate();
182
+ });
183
+ this.calculate();
184
+ }
185
+
186
+ calculate() {
187
+ let apertureMm = parseFloat(this.apertureInput.value) || 1;
188
+ if (this.unitSelector.value === 'in') {
189
+ apertureMm = inchesToMm(apertureMm);
190
+ }
191
+ const seeing = parseFloat(this.seeingInput.value);
192
+ const result = calculateResolution(apertureMm, seeing);
193
+
194
+ this.dawesDisplay.textContent = result.dawes.toFixed(2);
195
+ this.rayleighDisplay.textContent = result.rayleigh.toFixed(2);
196
+ this.maxMagDisplay.textContent = Math.round(result.maxMagnification).toString();
197
+
198
+ this.updateSimulation(result.dawes);
199
+ }
200
+
201
+ updateSimulation(dawes: number) {
202
+ const baseBlur = Math.max(0, dawes * 3);
203
+ const separation = Math.max(8, 30 - dawes * 15);
204
+
205
+ if (this.star1 && this.star2) {
206
+ this.star1.style.setProperty('--star-blur', `${baseBlur}px`);
207
+ this.star2.style.setProperty('--star-blur', `${baseBlur}px`);
208
+ const container = document.getElementById('binary-system');
209
+ if (container) {
210
+ container.style.gap = `${separation}px`;
211
+ }
212
+ const scale = Math.max(0.5, 2.5 - dawes / 1.5);
213
+ this.star1.style.transform = `scale(${scale})`;
214
+ this.star2.style.transform = `scale(${scale})`;
215
+ }
216
+ }
217
+ }
218
+
219
+ new ResolutionApp();
220
+ updateSeeingAlert();
221
+ </script>
222
+