@jjlmoya/utils-finance 1.12.0 → 1.13.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 (26) hide show
  1. package/package.json +5 -3
  2. package/scripts/postinstall.mjs +27 -0
  3. package/src/tool/compoundInterest/component.astro +0 -376
  4. package/src/tool/compoundInterest/compound-interest-calculator.css +79 -0
  5. package/src/tool/courtFeeCalculator/component.astro +0 -237
  6. package/src/tool/courtFeeCalculator/spanish-court-fees-calculator.css +235 -0
  7. package/src/tool/debtSnowball/component.astro +0 -636
  8. package/src/tool/debtSnowball/debt-snowball-calculator.css +634 -0
  9. package/src/tool/fireCalculator/component.astro +0 -334
  10. package/src/tool/fireCalculator/four-percent-rule-fire-calculator.css +332 -0
  11. package/src/tool/ibanBicSwiftConverter/component.astro +0 -414
  12. package/src/tool/ibanBicSwiftConverter/iban-to-bic-swift-converter.css +412 -0
  13. package/src/tool/inflation/component.astro +0 -280
  14. package/src/tool/inflation/inflation-calculator-spain.css +278 -0
  15. package/src/tool/lateInterest/component.astro +0 -400
  16. package/src/tool/lateInterest/late-interest-calculator.css +398 -0
  17. package/src/tool/legalInterestRate/component.astro +0 -509
  18. package/src/tool/legalInterestRate/legal-interest-on-money-spain.css +507 -0
  19. package/src/tool/lotteryOptimizer/component.astro +0 -561
  20. package/src/tool/lotteryOptimizer/spain-lottery-optimizer.css +17 -0
  21. package/src/tool/mortgage/component.astro +0 -641
  22. package/src/tool/mortgage/mortgage-calculator.css +639 -0
  23. package/src/tool/percentageCalculator/component.astro +0 -336
  24. package/src/tool/percentageCalculator/percentage-calculator.css +289 -0
  25. package/src/tool/rentIncreaseCalculator/component.astro +0 -372
  26. package/src/tool/rentIncreaseCalculator/rent-increase-calculator.css +370 -0
@@ -0,0 +1,278 @@
1
+ :root {
2
+ --inflation-color-primary: #f59e0b;
3
+ --inflation-color-primary-dark: #d97706;
4
+ --inflation-color-primary-light: #fcd34d;
5
+ --inflation-color-primary-extra-light: #fef3c7;
6
+ --inflation-color-danger: #ef4444;
7
+ --inflation-color-danger-light: #fee2e2;
8
+ --inflation-color-text-primary: #1f2937;
9
+ --inflation-color-text-secondary: #6b7280;
10
+ --inflation-color-text-light: #9ca3af;
11
+ --inflation-color-bg-primary: #fff;
12
+ --inflation-color-bg-secondary: #f9fafb;
13
+ --inflation-color-border: #e5e7eb;
14
+ }
15
+
16
+ .theme-dark,
17
+ [data-theme='dark'] {
18
+ --inflation-color-primary: #fbbf24;
19
+ --inflation-color-primary-dark: #f59e0b;
20
+ --inflation-color-primary-light: #b45309;
21
+ --inflation-color-primary-extra-light: #78350f;
22
+ --inflation-color-danger: #f87171;
23
+ --inflation-color-danger-light: #7f1d1d;
24
+ --inflation-color-text-primary: #f3f4f6;
25
+ --inflation-color-text-secondary: #d1d5db;
26
+ --inflation-color-text-light: #9ca3af;
27
+ --inflation-color-bg-primary: #1f2937;
28
+ --inflation-color-bg-secondary: #111827;
29
+ --inflation-color-border: #374151;
30
+ }
31
+
32
+ @media (prefers-color-scheme: dark) {
33
+ :root {
34
+ --inflation-color-primary: #fbbf24;
35
+ --inflation-color-primary-dark: #f59e0b;
36
+ --inflation-color-primary-light: #b45309;
37
+ --inflation-color-primary-extra-light: #78350f;
38
+ --inflation-color-danger: #f87171;
39
+ --inflation-color-danger-light: #7f1d1d;
40
+ --inflation-color-text-primary: #f3f4f6;
41
+ --inflation-color-text-secondary: #d1d5db;
42
+ --inflation-color-text-light: #9ca3af;
43
+ --inflation-color-bg-primary: #1f2937;
44
+ --inflation-color-bg-secondary: #111827;
45
+ --inflation-color-border: #374151;
46
+ }
47
+ }
48
+
49
+ .inflation-container {
50
+ background-color: var(--inflation-color-bg-primary);
51
+ border-radius: 1.5rem;
52
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
53
+ border: 1px solid var(--inflation-color-border);
54
+ overflow: hidden;
55
+ }
56
+
57
+ .inflation-header {
58
+ padding: 1.5rem;
59
+ border-bottom: 1px solid var(--inflation-color-border);
60
+ background-color: rgba(245, 158, 11, 0.05);
61
+ }
62
+
63
+ .inflation-header-title-group {
64
+ display: flex;
65
+ align-items: center;
66
+ gap: 0.75rem;
67
+ }
68
+
69
+ .inflation-header-icon {
70
+ width: 2.5rem;
71
+ height: 2.5rem;
72
+ padding: 0.625rem;
73
+ background-color: rgba(245, 158, 11, 0.1);
74
+ border-radius: 0.75rem;
75
+ color: var(--inflation-color-primary);
76
+ flex-shrink: 0;
77
+ }
78
+
79
+ .inflation-header-icon svg {
80
+ width: 100%;
81
+ height: 100%;
82
+ }
83
+
84
+ .inflation-header-title {
85
+ font-size: 1.25rem;
86
+ font-weight: 700;
87
+ color: var(--inflation-color-text-primary);
88
+ margin: 0;
89
+ }
90
+
91
+ .inflation-content {
92
+ padding: 2rem;
93
+ }
94
+
95
+ .inflation-description {
96
+ font-size: 0.875rem;
97
+ color: var(--inflation-color-text-secondary);
98
+ margin: 0 0 2rem;
99
+ text-align: center;
100
+ }
101
+
102
+ .inflation-grid {
103
+ display: flex;
104
+ flex-direction: column;
105
+ gap: 2rem;
106
+ margin-bottom: 2rem;
107
+ }
108
+
109
+ @media (min-width: 768px) {
110
+ .inflation-grid {
111
+ flex-direction: row;
112
+ align-items: center;
113
+ gap: 1.5rem;
114
+ }
115
+ }
116
+
117
+ .inflation-panel {
118
+ flex: 1;
119
+ padding: 2rem;
120
+ border-radius: 1.5rem;
121
+ border: 2px solid var(--inflation-color-border);
122
+ background-color: var(--inflation-color-bg-secondary);
123
+ }
124
+
125
+ .inflation-panel-left {
126
+ border-top: 4px solid var(--inflation-color-border);
127
+ }
128
+
129
+ .inflation-panel-right {
130
+ background-color: rgba(245, 158, 11, 0.05);
131
+ border-color: rgba(245, 158, 11, 0.2);
132
+ border-top: 4px solid var(--inflation-color-primary);
133
+ }
134
+
135
+ .inflation-label {
136
+ display: block;
137
+ font-size: 0.75rem;
138
+ font-weight: 700;
139
+ color: var(--inflation-color-text-light);
140
+ text-transform: uppercase;
141
+ letter-spacing: 0.05em;
142
+ margin-bottom: 0.75rem;
143
+ }
144
+
145
+ .inflation-input-wrapper {
146
+ position: relative;
147
+ display: flex;
148
+ align-items: center;
149
+ }
150
+
151
+ .inflation-input {
152
+ width: 100%;
153
+ padding: 1rem;
154
+ background-color: var(--inflation-color-bg-primary);
155
+ border: 2px solid var(--inflation-color-border);
156
+ border-radius: 0.75rem;
157
+ font-size: 1.875rem;
158
+ font-weight: 700;
159
+ color: var(--inflation-color-text-primary);
160
+ text-align: center;
161
+ transition: all 0.2s ease;
162
+ }
163
+
164
+ .inflation-input:focus {
165
+ border-color: var(--inflation-color-primary);
166
+ outline: none;
167
+ }
168
+
169
+ .inflation-currency {
170
+ position: absolute;
171
+ right: 1rem;
172
+ color: var(--inflation-color-text-light);
173
+ font-size: 0.875rem;
174
+ }
175
+
176
+ .inflation-select {
177
+ width: 100%;
178
+ padding: 0.875rem 1rem;
179
+ background-color: var(--inflation-color-bg-primary);
180
+ border: 2px solid var(--inflation-color-border);
181
+ border-radius: 0.75rem;
182
+ font-size: 1.125rem;
183
+ font-weight: 700;
184
+ color: var(--inflation-color-text-primary);
185
+ cursor: pointer;
186
+ transition: all 0.2s ease;
187
+ }
188
+
189
+ .inflation-select:focus {
190
+ border-color: var(--inflation-color-primary);
191
+ outline: none;
192
+ }
193
+
194
+ .inflation-select:hover {
195
+ border-color: var(--inflation-color-primary);
196
+ }
197
+
198
+ .inflation-arrow {
199
+ display: flex;
200
+ align-items: center;
201
+ justify-content: center;
202
+ color: var(--inflation-color-primary);
203
+ flex-shrink: 0;
204
+ }
205
+
206
+ .inflation-arrow svg {
207
+ width: 2rem;
208
+ height: 2rem;
209
+ }
210
+
211
+ @media (max-width: 767px) {
212
+ .inflation-arrow {
213
+ transform: rotate(90deg);
214
+ margin: 1rem 0;
215
+ }
216
+ }
217
+
218
+ .inflation-result-wrapper {
219
+ display: flex;
220
+ align-items: center;
221
+ justify-content: center;
222
+ min-height: 100px;
223
+ }
224
+
225
+ .inflation-result {
226
+ font-size: 2.25rem;
227
+ font-weight: 700;
228
+ color: var(--inflation-color-primary);
229
+ text-align: center;
230
+ }
231
+
232
+ .inflation-year-badge {
233
+ text-align: center;
234
+ display: inline-block;
235
+ width: 100%;
236
+ padding: 0.5rem 1rem;
237
+ background-color: var(--inflation-color-bg-primary);
238
+ border: 1px solid var(--inflation-color-border);
239
+ border-radius: 0.75rem;
240
+ font-size: 0.875rem;
241
+ font-weight: 700;
242
+ color: var(--inflation-color-text-secondary);
243
+ margin-top: 1rem;
244
+ }
245
+
246
+ .inflation-stat {
247
+ text-align: center;
248
+ animation: fade-in-up 0.7s ease 0.15s both;
249
+ }
250
+
251
+ @keyframes fade-in-up {
252
+ from {
253
+ opacity: 0;
254
+ transform: translateY(1rem);
255
+ }
256
+ to {
257
+ opacity: 1;
258
+ transform: translateY(0);
259
+ }
260
+ }
261
+
262
+ .inflation-stat-badge {
263
+ display: inline-flex;
264
+ align-items: center;
265
+ gap: 0.5rem;
266
+ padding: 0.75rem 1.5rem;
267
+ background-color: var(--inflation-color-danger-light);
268
+ color: var(--inflation-color-danger);
269
+ border-radius: 1.5rem;
270
+ font-weight: 700;
271
+ font-size: 1.125rem;
272
+ border: 1px solid var(--inflation-color-danger);
273
+ }
274
+
275
+ .inflation-stat-badge svg {
276
+ width: 1.25rem;
277
+ height: 1.25rem;
278
+ }
@@ -101,406 +101,6 @@ const { ui } = Astro.props;
101
101
  </div>
102
102
  </div>
103
103
 
104
- <style>
105
- :root {
106
- --li-bg-card: #fff;
107
- --li-bg-card-hover: #f9fafb;
108
- --li-border-card: #e5e7eb;
109
- --li-text-primary: #1f2937;
110
- --li-text-secondary: #6b7280;
111
- --li-text-input: #1f2937;
112
- --li-bg-input: #fff;
113
- --li-border-input: #d1d5db;
114
- --li-focus-ring: rgba(59, 130, 246, 0.1);
115
- --li-focus-border: #3b82f6;
116
- --li-unit-color: #3b82f6;
117
- --li-bg-result: #f3f4f6;
118
- --li-border-result: #d1d5db;
119
- --li-label-result: #6b7280;
120
- --li-value-result: #1f2937;
121
- --li-bg-total-gradient-1: #dbeafe;
122
- --li-bg-total-gradient-2: #bfdbfe;
123
- --li-border-total: #3b82f6;
124
- --li-label-total: #1e40af;
125
- --li-value-total: #1e3a8a;
126
- --li-bg-banner: #fef3c7;
127
- --li-border-banner: #f59e0b;
128
- --li-text-banner: #92400e;
129
- --li-bg-button: #3b82f6;
130
- --li-bg-button-hover: #2563eb;
131
- --li-text-button: #fff;
132
- }
133
-
134
- :global(.theme-dark) {
135
- --li-bg-card: #1f2937;
136
- --li-border-card: #374151;
137
- --li-text-primary: #f3f4f6;
138
- --li-text-secondary: #d1d5db;
139
- --li-text-input: #f3f4f6;
140
- --li-bg-input: #111827;
141
- --li-border-input: #4b5563;
142
- --li-focus-ring: rgba(59, 130, 246, 0.1);
143
- --li-focus-border: #3b82f6;
144
- --li-unit-color: #60a5fa;
145
- --li-bg-result: #111827;
146
- --li-border-result: #374151;
147
- --li-label-result: #d1d5db;
148
- --li-value-result: #f3f4f6;
149
- --li-bg-total-gradient-1: #1e3a8a;
150
- --li-bg-total-gradient-2: #1e40af;
151
- --li-border-total: #3b82f6;
152
- --li-label-total: #93c5fd;
153
- --li-value-total: #dbeafe;
154
- --li-bg-banner: #78350f;
155
- --li-border-banner: #f59e0b;
156
- --li-text-banner: #fef3c7;
157
- --li-bg-button: #3b82f6;
158
- --li-bg-button-hover: #1e40af;
159
- --li-text-button: #fff;
160
- }
161
-
162
- :global([data-theme='dark']) {
163
- --li-bg-card: #1f2937;
164
- --li-border-card: #374151;
165
- --li-text-primary: #f3f4f6;
166
- --li-text-secondary: #d1d5db;
167
- --li-text-input: #f3f4f6;
168
- --li-bg-input: #111827;
169
- --li-border-input: #4b5563;
170
- --li-focus-ring: rgba(59, 130, 246, 0.1);
171
- --li-focus-border: #3b82f6;
172
- --li-unit-color: #60a5fa;
173
- --li-bg-result: #111827;
174
- --li-border-result: #374151;
175
- --li-label-result: #d1d5db;
176
- --li-value-result: #f3f4f6;
177
- --li-bg-total-gradient-1: #1e3a8a;
178
- --li-bg-total-gradient-2: #1e40af;
179
- --li-border-total: #3b82f6;
180
- --li-label-total: #93c5fd;
181
- --li-value-total: #dbeafe;
182
- --li-bg-banner: #78350f;
183
- --li-border-banner: #f59e0b;
184
- --li-text-banner: #fef3c7;
185
- --li-bg-button: #3b82f6;
186
- --li-bg-button-hover: #1e40af;
187
- --li-text-button: #fff;
188
- }
189
-
190
- @media (prefers-color-scheme: dark) {
191
- :root {
192
- --li-bg-card: #1f2937;
193
- --li-border-card: #374151;
194
- --li-text-primary: #f3f4f6;
195
- --li-text-secondary: #d1d5db;
196
- --li-text-input: #f3f4f6;
197
- --li-bg-input: #111827;
198
- --li-border-input: #4b5563;
199
- --li-focus-ring: rgba(59, 130, 246, 0.1);
200
- --li-focus-border: #3b82f6;
201
- --li-unit-color: #60a5fa;
202
- --li-bg-result: #111827;
203
- --li-border-result: #374151;
204
- --li-label-result: #d1d5db;
205
- --li-value-result: #f3f4f6;
206
- --li-bg-total-gradient-1: #1e3a8a;
207
- --li-bg-total-gradient-2: #1e40af;
208
- --li-border-total: #3b82f6;
209
- --li-label-total: #93c5fd;
210
- --li-value-total: #dbeafe;
211
- --li-bg-banner: #78350f;
212
- --li-border-banner: #f59e0b;
213
- --li-text-banner: #fef3c7;
214
- --li-bg-button: #3b82f6;
215
- --li-bg-button-hover: #1e40af;
216
- --li-text-button: #fff;
217
- }
218
- }
219
-
220
- .li-container {
221
- display: flex;
222
- justify-content: center;
223
- width: 100%;
224
- padding: 2rem 1rem;
225
- }
226
-
227
- .li-card {
228
- background: var(--li-bg-card);
229
- border: 1px solid var(--li-border-card);
230
- border-radius: 12px;
231
- padding: 2rem;
232
- width: 100%;
233
- max-width: 600px;
234
- color: var(--li-text-primary);
235
- }
236
-
237
- .li-input-grid {
238
- display: grid;
239
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
240
- gap: 1.5rem;
241
- margin-bottom: 2rem;
242
- }
243
-
244
- .li-input-group {
245
- display: flex;
246
- flex-direction: column;
247
- }
248
-
249
- .li-input-group label {
250
- font-weight: 600;
251
- margin-bottom: 0.5rem;
252
- font-size: 0.9rem;
253
- color: var(--li-text-primary);
254
- }
255
-
256
- .li-input-wrapper {
257
- position: relative;
258
- display: flex;
259
- align-items: center;
260
- }
261
-
262
- .li-input-wrapper input,
263
- .li-input-wrapper select {
264
- width: 100%;
265
- padding: 0.75rem 1rem;
266
- border: 1px solid var(--li-border-input);
267
- border-radius: 8px;
268
- font-size: 1rem;
269
- background: var(--li-bg-input);
270
- color: var(--li-text-input);
271
- color-scheme: light;
272
- }
273
-
274
- :global(.theme-dark) .li-input-wrapper input,
275
- :global(.theme-dark) .li-input-wrapper select,
276
- :global([data-theme='dark']) .li-input-wrapper input,
277
- :global([data-theme='dark']) .li-input-wrapper select {
278
- color-scheme: dark;
279
- }
280
-
281
- .li-input-wrapper select {
282
- padding-right: 2.5rem;
283
- appearance: none;
284
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%233b82f6' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
285
- background-repeat: no-repeat;
286
- background-position: right 0.75rem center;
287
- background-size: 12px 8px;
288
- }
289
-
290
- :global(.theme-dark) .li-input-wrapper select,
291
- :global([data-theme='dark']) .li-input-wrapper select {
292
- background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' viewBox='0 0 12 8'%3E%3Cpath fill='%2360a5fa' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
293
- }
294
-
295
- .li-input-wrapper input:focus,
296
- .li-input-wrapper select:focus {
297
- outline: none;
298
- border-color: var(--li-focus-border);
299
- box-shadow: 0 0 0 3px var(--li-focus-ring);
300
- }
301
-
302
- .li-input-unit {
303
- position: absolute;
304
- right: 1rem;
305
- font-weight: 600;
306
- color: var(--li-unit-color);
307
- pointer-events: none;
308
- }
309
-
310
- .li-results-display {
311
- margin-bottom: 2rem;
312
- }
313
-
314
- .li-total-interest-box {
315
- background: linear-gradient(135deg, var(--li-bg-total-gradient-1), var(--li-bg-total-gradient-2));
316
- border: 2px solid var(--li-border-total);
317
- border-radius: 12px;
318
- padding: 1.5rem;
319
- text-align: center;
320
- margin-bottom: 1.5rem;
321
- }
322
-
323
- .li-total-label {
324
- display: block;
325
- font-size: 0.9rem;
326
- font-weight: 600;
327
- color: var(--li-label-total);
328
- margin-bottom: 0.5rem;
329
- }
330
-
331
- .li-total-value {
332
- display: block;
333
- font-size: 2rem;
334
- font-weight: 800;
335
- color: var(--li-value-total);
336
- }
337
-
338
- .li-breakdown-grid {
339
- display: grid;
340
- grid-template-columns: repeat(3, 1fr);
341
- gap: 1rem;
342
- margin-bottom: 1.5rem;
343
- }
344
-
345
- .li-sub-result-card {
346
- background: var(--li-bg-result);
347
- border: 1px solid var(--li-border-result);
348
- border-radius: 8px;
349
- padding: 1rem;
350
- text-align: center;
351
- }
352
-
353
- .li-sub-label {
354
- display: block;
355
- font-size: 0.8rem;
356
- font-weight: 600;
357
- color: var(--li-label-result);
358
- margin-bottom: 0.5rem;
359
- }
360
-
361
- .li-sub-value {
362
- display: block;
363
- font-size: 1.3rem;
364
- font-weight: 700;
365
- color: var(--li-value-result);
366
- }
367
-
368
- .li-info-banner {
369
- background: var(--li-bg-banner);
370
- border-left: 4px solid var(--li-border-banner);
371
- border-radius: 6px;
372
- padding: 1rem;
373
- margin-bottom: 1.5rem;
374
- }
375
-
376
- .li-info-banner p {
377
- margin: 0;
378
- font-size: 0.9rem;
379
- color: var(--li-text-banner);
380
- }
381
-
382
- .action-row {
383
- display: flex;
384
- gap: 1rem;
385
- }
386
-
387
- .li-btn-primary {
388
- flex: 1;
389
- padding: 0.75rem 1.5rem;
390
- background: var(--li-bg-button);
391
- color: var(--li-text-button);
392
- border: none;
393
- border-radius: 8px;
394
- font-weight: 600;
395
- cursor: pointer;
396
- transition: all 0.2s;
397
- }
398
-
399
- .li-btn-primary:hover {
400
- background: var(--li-bg-button-hover);
401
- transform: translateY(-2px);
402
- }
403
-
404
- .li-btn-primary:active {
405
- transform: translateY(0);
406
- }
407
-
408
- .fade-in {
409
- animation: fade-in-up 0.4s ease-out;
410
- }
411
-
412
- @keyframes fade-in-up {
413
- from {
414
- opacity: 0;
415
- transform: translateY(20px);
416
- }
417
- to {
418
- opacity: 1;
419
- transform: translateY(0);
420
- }
421
- }
422
-
423
- @media (prefers-color-scheme: dark) {
424
- .li-card {
425
- background: #1f2937;
426
- border-color: #374151;
427
- color: #f3f4f6;
428
- }
429
-
430
- .li-input-group label {
431
- color: #d1d5db;
432
- }
433
-
434
- .li-input-wrapper input,
435
- .li-input-wrapper select {
436
- background: #111827;
437
- border-color: #4b5563;
438
- color: #f3f4f6;
439
- }
440
-
441
- .li-input-unit {
442
- color: #60a5fa;
443
- }
444
-
445
- .li-sub-result-card {
446
- background: #111827;
447
- border-color: #374151;
448
- }
449
-
450
- .li-sub-label {
451
- color: #d1d5db;
452
- }
453
-
454
- .li-sub-value {
455
- color: #f3f4f6;
456
- }
457
-
458
- .li-info-banner {
459
- background: #78350f;
460
- color: #fef3c7;
461
- }
462
-
463
- .li-info-banner p {
464
- color: #fef3c7;
465
- }
466
-
467
- .li-total-interest-box {
468
- background: linear-gradient(135deg, #1e3a8a, #1e40af);
469
- border-color: #3b82f6;
470
- }
471
-
472
- .li-total-label {
473
- color: #93c5fd;
474
- }
475
-
476
- .li-total-value {
477
- color: #dbeafe;
478
- }
479
-
480
- .li-btn-primary {
481
- background: #3b82f6;
482
- color: #fff;
483
- }
484
-
485
- .li-btn-primary:hover {
486
- background: #1e40af;
487
- }
488
- }
489
-
490
- @media (max-width: 640px) {
491
- .li-input-grid {
492
- grid-template-columns: 1fr;
493
- }
494
-
495
- .li-breakdown-grid {
496
- grid-template-columns: 1fr;
497
- }
498
-
499
- .li-total-value {
500
- font-size: 1.5rem;
501
- }
502
- }
503
- </style>
504
104
 
505
105
  <script>
506
106
  const principalInput = document.getElementById("principal-amount") as HTMLInputElement | null;