@jjlmoya/utils-nature 1.20.0 → 1.22.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 (139) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +3 -2
  3. package/src/entries.ts +5 -1
  4. package/src/index.ts +4 -0
  5. package/src/pages/[locale]/[slug].astro +5 -4
  6. package/src/tests/diacritics_density.test.ts +1 -1
  7. package/src/tests/inverted_punctuation.test.ts +1 -1
  8. package/src/tests/script_density.test.ts +1 -1
  9. package/src/tests/seo_length.test.ts +1 -0
  10. package/src/tests/seo_translation_completeness.test.ts +69 -0
  11. package/src/tests/title_quality.test.ts +1 -1
  12. package/src/tests/tool_validation.test.ts +2 -3
  13. package/src/tests/translation_copy.test.ts +2 -2
  14. package/src/tool/compostBinVolumeRatioCalculator/bibliography.astro +18 -0
  15. package/src/tool/compostBinVolumeRatioCalculator/bibliography.ts +12 -0
  16. package/src/tool/compostBinVolumeRatioCalculator/component.astro +77 -0
  17. package/src/tool/compostBinVolumeRatioCalculator/compost-bin-volume-ratio-calculator.css +509 -0
  18. package/src/tool/compostBinVolumeRatioCalculator/controller.ts +189 -0
  19. package/src/tool/compostBinVolumeRatioCalculator/dom-views.ts +162 -0
  20. package/src/tool/compostBinVolumeRatioCalculator/entry.ts +28 -0
  21. package/src/tool/compostBinVolumeRatioCalculator/evaluator.ts +26 -0
  22. package/src/tool/compostBinVolumeRatioCalculator/i18n/de.ts +193 -0
  23. package/src/tool/compostBinVolumeRatioCalculator/i18n/en.ts +193 -0
  24. package/src/tool/compostBinVolumeRatioCalculator/i18n/es.ts +193 -0
  25. package/src/tool/compostBinVolumeRatioCalculator/i18n/fr.ts +193 -0
  26. package/src/tool/compostBinVolumeRatioCalculator/i18n/id.ts +185 -0
  27. package/src/tool/compostBinVolumeRatioCalculator/i18n/it.ts +193 -0
  28. package/src/tool/compostBinVolumeRatioCalculator/i18n/ja.ts +190 -0
  29. package/src/tool/compostBinVolumeRatioCalculator/i18n/ko.ts +190 -0
  30. package/src/tool/compostBinVolumeRatioCalculator/i18n/nl.ts +190 -0
  31. package/src/tool/compostBinVolumeRatioCalculator/i18n/pl.ts +190 -0
  32. package/src/tool/compostBinVolumeRatioCalculator/i18n/pt.ts +190 -0
  33. package/src/tool/compostBinVolumeRatioCalculator/i18n/ru.ts +190 -0
  34. package/src/tool/compostBinVolumeRatioCalculator/i18n/sv.ts +190 -0
  35. package/src/tool/compostBinVolumeRatioCalculator/i18n/tr.ts +190 -0
  36. package/src/tool/compostBinVolumeRatioCalculator/i18n/zh.ts +190 -0
  37. package/src/tool/compostBinVolumeRatioCalculator/index.ts +11 -0
  38. package/src/tool/compostBinVolumeRatioCalculator/logic.test.ts +55 -0
  39. package/src/tool/compostBinVolumeRatioCalculator/logic.ts +165 -0
  40. package/src/tool/compostBinVolumeRatioCalculator/seo.astro +23 -0
  41. package/src/tool/compostBinVolumeRatioCalculator/storage.ts +25 -0
  42. package/src/tool/compostBinVolumeRatioCalculator/ui.ts +54 -0
  43. package/src/tool/cricketThermometer/component.astro +1 -1
  44. package/src/tool/cricketThermometer/i18n/de.ts +2 -2
  45. package/src/tool/cricketThermometer/i18n/en.ts +2 -2
  46. package/src/tool/cricketThermometer/i18n/es.ts +2 -2
  47. package/src/tool/cricketThermometer/i18n/fr.ts +2 -2
  48. package/src/tool/cricketThermometer/i18n/id.ts +2 -2
  49. package/src/tool/cricketThermometer/i18n/it.ts +2 -2
  50. package/src/tool/cricketThermometer/i18n/ja.ts +2 -2
  51. package/src/tool/cricketThermometer/i18n/ko.ts +2 -2
  52. package/src/tool/cricketThermometer/i18n/nl.ts +2 -2
  53. package/src/tool/cricketThermometer/i18n/pl.ts +2 -2
  54. package/src/tool/cricketThermometer/i18n/pt.ts +2 -2
  55. package/src/tool/cricketThermometer/i18n/ru.ts +2 -2
  56. package/src/tool/cricketThermometer/i18n/sv.ts +2 -2
  57. package/src/tool/cricketThermometer/i18n/tr.ts +2 -2
  58. package/src/tool/cricketThermometer/i18n/zh.ts +2 -2
  59. package/src/tool/cricketThermometer/index.ts +1 -0
  60. package/src/tool/digitalCarbon/component.astro +3 -3
  61. package/src/tool/digitalCarbon/i18n/de.ts +2 -2
  62. package/src/tool/digitalCarbon/i18n/en.ts +2 -2
  63. package/src/tool/digitalCarbon/i18n/es.ts +2 -2
  64. package/src/tool/digitalCarbon/i18n/fr.ts +2 -2
  65. package/src/tool/digitalCarbon/i18n/id.ts +2 -2
  66. package/src/tool/digitalCarbon/i18n/it.ts +2 -2
  67. package/src/tool/digitalCarbon/i18n/ja.ts +2 -2
  68. package/src/tool/digitalCarbon/i18n/ko.ts +2 -2
  69. package/src/tool/digitalCarbon/i18n/nl.ts +2 -2
  70. package/src/tool/digitalCarbon/i18n/pl.ts +2 -2
  71. package/src/tool/digitalCarbon/i18n/pt.ts +2 -2
  72. package/src/tool/digitalCarbon/i18n/ru.ts +2 -2
  73. package/src/tool/digitalCarbon/i18n/sv.ts +2 -2
  74. package/src/tool/digitalCarbon/i18n/tr.ts +2 -2
  75. package/src/tool/digitalCarbon/i18n/zh.ts +2 -2
  76. package/src/tool/digitalCarbon/index.ts +1 -0
  77. package/src/tool/rainHarvester/i18n/de.ts +2 -2
  78. package/src/tool/rainHarvester/i18n/en.ts +2 -2
  79. package/src/tool/rainHarvester/i18n/es.ts +2 -2
  80. package/src/tool/rainHarvester/i18n/fr.ts +2 -2
  81. package/src/tool/rainHarvester/i18n/id.ts +2 -2
  82. package/src/tool/rainHarvester/i18n/it.ts +2 -2
  83. package/src/tool/rainHarvester/i18n/ja.ts +2 -2
  84. package/src/tool/rainHarvester/i18n/ko.ts +2 -2
  85. package/src/tool/rainHarvester/i18n/nl.ts +2 -2
  86. package/src/tool/rainHarvester/i18n/pl.ts +2 -2
  87. package/src/tool/rainHarvester/i18n/pt.ts +2 -2
  88. package/src/tool/rainHarvester/i18n/ru.ts +2 -2
  89. package/src/tool/rainHarvester/i18n/sv.ts +2 -2
  90. package/src/tool/rainHarvester/i18n/tr.ts +2 -2
  91. package/src/tool/rainHarvester/i18n/zh.ts +2 -2
  92. package/src/tool/rainHarvester/index.ts +1 -0
  93. package/src/tool/seedCalculator/i18n/de.ts +2 -2
  94. package/src/tool/seedCalculator/i18n/en.ts +2 -2
  95. package/src/tool/seedCalculator/i18n/es.ts +2 -2
  96. package/src/tool/seedCalculator/i18n/fr.ts +2 -2
  97. package/src/tool/seedCalculator/i18n/id.ts +2 -2
  98. package/src/tool/seedCalculator/i18n/it.ts +2 -2
  99. package/src/tool/seedCalculator/i18n/ja.ts +2 -2
  100. package/src/tool/seedCalculator/i18n/ko.ts +2 -2
  101. package/src/tool/seedCalculator/i18n/nl.ts +2 -2
  102. package/src/tool/seedCalculator/i18n/pl.ts +2 -2
  103. package/src/tool/seedCalculator/i18n/pt.ts +2 -2
  104. package/src/tool/seedCalculator/i18n/ru.ts +2 -2
  105. package/src/tool/seedCalculator/i18n/sv.ts +2 -2
  106. package/src/tool/seedCalculator/i18n/tr.ts +2 -2
  107. package/src/tool/seedCalculator/i18n/zh.ts +2 -2
  108. package/src/tool/seedCalculator/index.ts +1 -0
  109. package/src/tool/urbanGardenPlanner/bibliography.astro +9 -0
  110. package/src/tool/urbanGardenPlanner/bibliography.ts +16 -0
  111. package/src/tool/urbanGardenPlanner/component.astro +131 -0
  112. package/src/tool/urbanGardenPlanner/controller.ts +88 -0
  113. package/src/tool/urbanGardenPlanner/dom-views.ts +84 -0
  114. package/src/tool/urbanGardenPlanner/entry.ts +29 -0
  115. package/src/tool/urbanGardenPlanner/evaluator.ts +27 -0
  116. package/src/tool/urbanGardenPlanner/i18n/de.ts +50 -0
  117. package/src/tool/urbanGardenPlanner/i18n/en.ts +179 -0
  118. package/src/tool/urbanGardenPlanner/i18n/es.ts +50 -0
  119. package/src/tool/urbanGardenPlanner/i18n/fr.ts +50 -0
  120. package/src/tool/urbanGardenPlanner/i18n/id.ts +50 -0
  121. package/src/tool/urbanGardenPlanner/i18n/it.ts +45 -0
  122. package/src/tool/urbanGardenPlanner/i18n/ja.ts +39 -0
  123. package/src/tool/urbanGardenPlanner/i18n/ko.ts +39 -0
  124. package/src/tool/urbanGardenPlanner/i18n/nl.ts +39 -0
  125. package/src/tool/urbanGardenPlanner/i18n/pl.ts +39 -0
  126. package/src/tool/urbanGardenPlanner/i18n/pt.ts +39 -0
  127. package/src/tool/urbanGardenPlanner/i18n/ru.ts +39 -0
  128. package/src/tool/urbanGardenPlanner/i18n/sv.ts +39 -0
  129. package/src/tool/urbanGardenPlanner/i18n/tr.ts +104 -0
  130. package/src/tool/urbanGardenPlanner/i18n/zh.ts +104 -0
  131. package/src/tool/urbanGardenPlanner/index.ts +11 -0
  132. package/src/tool/urbanGardenPlanner/logic.test.ts +45 -0
  133. package/src/tool/urbanGardenPlanner/logic.ts +55 -0
  134. package/src/tool/urbanGardenPlanner/seo.astro +15 -0
  135. package/src/tool/urbanGardenPlanner/storage.ts +25 -0
  136. package/src/tool/urbanGardenPlanner/ui.ts +38 -0
  137. package/src/tool/urbanGardenPlanner/urban-garden-rainwater-and-soil-planner.css +531 -0
  138. package/src/tools.ts +5 -2
  139. package/src/types.ts +4 -4
@@ -0,0 +1,531 @@
1
+ .ugrp-root {
2
+ --n-page: #f4f1e8;
3
+ --n-surface: #fffdf7;
4
+ --n-surface-soft: #f7f5ed;
5
+ --n-ink: #26342d;
6
+ --n-muted: #718076;
7
+ --n-line: #d8ded0;
8
+ --n-moss: #3f6b4a;
9
+ --n-moss-soft: #dfeadd;
10
+ --n-water: #2f7b87;
11
+ --n-water-soft: #cfe8e7;
12
+ --n-soil: #8a6142;
13
+ --n-soil-dark: #634531;
14
+ --n-gold: #d99a42;
15
+ --n-status: #295d45;
16
+ --n-status-bg: #e2f0e3;
17
+ --ugrp-water-progress: 45%;
18
+ --ugrp-soil-progress: 50%;
19
+ --ugrp-rain-progress: 30%;
20
+
21
+ display: block;
22
+ max-width: 76rem;
23
+ margin: 0 auto;
24
+ padding: 1rem;
25
+ color: var(--n-ink);
26
+ }
27
+
28
+ .theme-dark .ugrp-root {
29
+ --n-page: #171b19;
30
+ --n-surface: #202724;
31
+ --n-surface-soft: #252e2a;
32
+ --n-ink: #edf2e9;
33
+ --n-muted: #a5b2a7;
34
+ --n-line: #3b4940;
35
+ --n-moss: #91c294;
36
+ --n-moss-soft: #2e4434;
37
+ --n-water: #77c7ce;
38
+ --n-water-soft: #24474a;
39
+ --n-soil: #be9168;
40
+ --n-soil-dark: #906747;
41
+ --n-gold: #e6b766;
42
+ --n-status: #b8e1bb;
43
+ --n-status-bg: #294331;
44
+ }
45
+
46
+ .ugrp-shell {
47
+ display: grid;
48
+ grid-template-columns: minmax(18rem, 0.85fr) minmax(22rem, 1.15fr);
49
+ overflow: hidden;
50
+ background: var(--n-surface);
51
+ border: 1px solid var(--n-line);
52
+ border-radius: 1.5rem;
53
+ box-shadow: 0 1rem 2.5rem rgba(38, 52, 45, 0.12);
54
+ }
55
+
56
+ .ugrp-input-panel,
57
+ .ugrp-result-panel {
58
+ padding: clamp(1.4rem, 3vw, 2.5rem);
59
+ }
60
+
61
+ .ugrp-input-panel {
62
+ background: var(--n-surface-soft);
63
+ border-right: 1px solid var(--n-line);
64
+ }
65
+
66
+ .ugrp-result-panel {
67
+ background: var(--n-page);
68
+ }
69
+
70
+ .ugrp-kicker {
71
+ color: var(--n-moss);
72
+ font-size: 0.72rem;
73
+ font-weight: 800;
74
+ letter-spacing: 0.12em;
75
+ line-height: 1.4;
76
+ text-transform: uppercase;
77
+ }
78
+
79
+ .ugrp-heading {
80
+ display: flex;
81
+ align-items: center;
82
+ gap: 0.7rem;
83
+ margin: 0.8rem 0 1.8rem;
84
+ color: var(--n-ink);
85
+ font-size: clamp(1.25rem, 2vw, 1.6rem);
86
+ line-height: 1.15;
87
+ }
88
+
89
+ .ugrp-step {
90
+ display: inline-grid;
91
+ width: 2rem;
92
+ height: 2rem;
93
+ flex: 0 0 auto;
94
+ place-items: center;
95
+ border-radius: 0.65rem;
96
+ background: var(--n-moss);
97
+ color: var(--n-surface);
98
+ font-size: 0.9rem;
99
+ }
100
+
101
+ .ugrp-step-light {
102
+ background: var(--n-water);
103
+ }
104
+
105
+ .ugrp-fields {
106
+ display: grid;
107
+ gap: 1.15rem;
108
+ }
109
+
110
+ .ugrp-field {
111
+ display: grid;
112
+ gap: 0.4rem;
113
+ }
114
+
115
+ .ugrp-label {
116
+ display: flex;
117
+ align-items: center;
118
+ gap: 0.45rem;
119
+ color: var(--n-ink);
120
+ font-size: 0.85rem;
121
+ font-weight: 750;
122
+ }
123
+
124
+ .ugrp-label svg {
125
+ color: var(--n-moss);
126
+ font-size: 1.2rem;
127
+ }
128
+
129
+ .ugrp-input-line {
130
+ display: flex;
131
+ align-items: center;
132
+ overflow: hidden;
133
+ border: 1px solid var(--n-line);
134
+ border-radius: 0.8rem;
135
+ background: var(--n-surface);
136
+ }
137
+
138
+ .ugrp-input-line:focus-within {
139
+ border-color: var(--n-water);
140
+ outline: 2px solid var(--n-water-soft);
141
+ }
142
+
143
+ .ugrp-input-line input {
144
+ width: 100%;
145
+ min-width: 0;
146
+ border: 0;
147
+ outline: 0;
148
+ padding: 0.72rem 0.8rem;
149
+ background: transparent;
150
+ color: var(--n-ink);
151
+ font: inherit;
152
+ font-size: 1.1rem;
153
+ font-weight: 750;
154
+ }
155
+
156
+ .ugrp-input-line > span {
157
+ padding-right: 0.8rem;
158
+ color: var(--n-muted);
159
+ font-size: 0.82rem;
160
+ font-weight: 750;
161
+ }
162
+
163
+ .ugrp-help {
164
+ color: var(--n-muted);
165
+ font-size: 0.73rem;
166
+ line-height: 1.4;
167
+ }
168
+
169
+ .ugrp-presets {
170
+ margin-top: 1.7rem;
171
+ padding-top: 1.4rem;
172
+ border-top: 1px solid var(--n-line);
173
+ }
174
+
175
+ .ugrp-subheading {
176
+ margin-bottom: 0.65rem;
177
+ color: var(--n-muted);
178
+ font-size: 0.72rem;
179
+ font-weight: 800;
180
+ letter-spacing: 0.1em;
181
+ text-transform: uppercase;
182
+ }
183
+
184
+ .ugrp-preset-row {
185
+ display: flex;
186
+ flex-wrap: wrap;
187
+ gap: 0.45rem;
188
+ }
189
+
190
+ .ugrp-preset {
191
+ border: 1px solid var(--n-line);
192
+ border-radius: 99rem;
193
+ padding: 0.5rem 0.72rem;
194
+ background: var(--n-surface);
195
+ color: var(--n-moss);
196
+ cursor: pointer;
197
+ font: inherit;
198
+ font-size: 0.75rem;
199
+ font-weight: 750;
200
+ }
201
+
202
+ .ugrp-preset:hover,
203
+ .ugrp-preset:focus-visible {
204
+ border-color: var(--n-moss);
205
+ background: var(--n-moss-soft);
206
+ outline: 0;
207
+ }
208
+
209
+ .ugrp-note {
210
+ display: flex;
211
+ gap: 0.7rem;
212
+ margin-top: 1.6rem;
213
+ border-top: 1px solid var(--n-line);
214
+ padding-top: 1.1rem;
215
+ color: var(--n-muted);
216
+ font-size: 0.73rem;
217
+ line-height: 1.45;
218
+ }
219
+
220
+ .ugrp-note > svg {
221
+ flex: 0 0 auto;
222
+ color: var(--n-gold);
223
+ font-size: 1.3rem;
224
+ }
225
+
226
+ .ugrp-note div {
227
+ display: grid;
228
+ gap: 0.2rem;
229
+ }
230
+
231
+ .ugrp-note strong {
232
+ color: var(--n-ink);
233
+ font-size: 0.78rem;
234
+ }
235
+
236
+ .ugrp-result-topline {
237
+ display: flex;
238
+ align-items: flex-start;
239
+ justify-content: space-between;
240
+ gap: 1rem;
241
+ }
242
+
243
+ .ugrp-result-topline .ugrp-heading {
244
+ margin-bottom: 1rem;
245
+ }
246
+
247
+ .ugrp-status {
248
+ max-width: 10rem;
249
+ border-radius: 0.7rem;
250
+ padding: 0.55rem 0.7rem;
251
+ background: var(--n-status-bg);
252
+ color: var(--n-status);
253
+ font-size: 0.72rem;
254
+ font-weight: 800;
255
+ line-height: 1.3;
256
+ text-align: right;
257
+ }
258
+
259
+ .ugrp-landscape {
260
+ position: relative;
261
+ min-height: 19rem;
262
+ overflow: hidden;
263
+ border: 1px solid var(--n-line);
264
+ border-radius: 1.1rem;
265
+ background: var(--n-surface);
266
+ }
267
+
268
+ .ugrp-landscape::after {
269
+ position: absolute;
270
+ right: 0;
271
+ bottom: 0;
272
+ left: 0;
273
+ height: 22%;
274
+ background: var(--n-moss-soft);
275
+ content: '';
276
+ }
277
+
278
+ .ugrp-cloud {
279
+ position: absolute;
280
+ top: 1.2rem;
281
+ left: 1.3rem;
282
+ color: var(--n-water);
283
+ font-size: 3rem;
284
+ opacity: 0.65;
285
+ }
286
+
287
+ .ugrp-catchment {
288
+ position: absolute;
289
+ top: 4.7rem;
290
+ left: 1.2rem;
291
+ width: 7rem;
292
+ height: 2.4rem;
293
+ transform: skewX(-22deg);
294
+ border: 2px solid var(--n-soil-dark);
295
+ border-radius: 0.35rem;
296
+ background: var(--n-soil);
297
+ }
298
+
299
+ .ugrp-catchment span {
300
+ position: absolute;
301
+ right: 0.3rem;
302
+ bottom: 0.3rem;
303
+ transform: skewX(22deg);
304
+ color: var(--n-surface);
305
+ font-size: 0.62rem;
306
+ font-weight: 800;
307
+ text-transform: uppercase;
308
+ }
309
+
310
+ .ugrp-pipe {
311
+ position: absolute;
312
+ top: 6.8rem;
313
+ left: 7.5rem;
314
+ width: 4.3rem;
315
+ height: 5rem;
316
+ border-right: 0.35rem solid var(--n-water);
317
+ border-bottom: 0.35rem solid var(--n-water);
318
+ border-radius: 0 0 0.8rem;
319
+ }
320
+
321
+ .ugrp-pipe i,
322
+ .ugrp-pipe b {
323
+ position: absolute;
324
+ display: block;
325
+ width: 0.35rem;
326
+ height: 0.35rem;
327
+ border-radius: 50%;
328
+ background: var(--n-water);
329
+ }
330
+
331
+ .ugrp-pipe i {
332
+ top: 0.3rem;
333
+ right: -0.35rem;
334
+ }
335
+
336
+ .ugrp-pipe b {
337
+ right: 0.1rem;
338
+ bottom: -0.35rem;
339
+ }
340
+
341
+ .ugrp-bed {
342
+ position: absolute;
343
+ right: 1.2rem;
344
+ bottom: 2.2rem;
345
+ width: min(48%, 13rem);
346
+ height: 8.2rem;
347
+ border: 0.45rem solid var(--n-soil-dark);
348
+ border-radius: 0.5rem 0.5rem 0.8rem 0.8rem;
349
+ background: var(--n-soil);
350
+ z-index: 2;
351
+ }
352
+
353
+ .ugrp-bed-frame {
354
+ position: absolute;
355
+ inset: 0;
356
+ border: 0.45rem solid var(--n-soil);
357
+ }
358
+
359
+ .ugrp-soil-fill {
360
+ position: absolute;
361
+ right: 0.45rem;
362
+ bottom: 0.45rem;
363
+ left: 0.45rem;
364
+ height: var(--ugrp-soil-progress);
365
+ border-radius: 0 0 0.25rem 0.25rem;
366
+ background: var(--n-soil-dark);
367
+ transition: height 0.35s ease;
368
+ }
369
+
370
+ .ugrp-bed > span {
371
+ position: absolute;
372
+ right: 0.7rem;
373
+ bottom: 0.7rem;
374
+ left: 0.7rem;
375
+ color: var(--n-surface);
376
+ font-size: 0.65rem;
377
+ font-weight: 800;
378
+ text-transform: uppercase;
379
+ }
380
+
381
+ .ugrp-leaves {
382
+ position: absolute;
383
+ top: -2.1rem;
384
+ left: 15%;
385
+ display: flex;
386
+ gap: 0.6rem;
387
+ color: var(--n-moss);
388
+ font-size: 2.6rem;
389
+ }
390
+
391
+ .ugrp-leaves svg:nth-child(2) { transform: translateY(-0.65rem) scale(0.8); }
392
+ .ugrp-leaves svg:nth-child(3) { transform: translateY(-0.2rem) scale(0.7); }
393
+
394
+ .ugrp-water-vessel {
395
+ position: absolute;
396
+ bottom: 1.5rem;
397
+ left: 1.4rem;
398
+ width: 5.4rem;
399
+ height: 5rem;
400
+ overflow: hidden;
401
+ border: 0.25rem solid var(--n-water);
402
+ border-radius: 0.5rem 0.5rem 1.1rem 1.1rem;
403
+ background: var(--n-water-soft);
404
+ color: var(--n-water);
405
+ z-index: 3;
406
+ }
407
+
408
+ .ugrp-water-vessel > div {
409
+ position: absolute;
410
+ right: 0;
411
+ bottom: 0;
412
+ left: 0;
413
+ height: var(--ugrp-water-progress);
414
+ background: var(--n-water);
415
+ opacity: 0.78;
416
+ transition: height 0.35s ease;
417
+ }
418
+
419
+ .ugrp-water-vessel svg {
420
+ position: absolute;
421
+ top: 0.6rem;
422
+ left: 1.75rem;
423
+ color: var(--n-surface);
424
+ font-size: 1.7rem;
425
+ }
426
+
427
+ .ugrp-water-vessel span {
428
+ position: absolute;
429
+ right: 0.25rem;
430
+ bottom: 0.35rem;
431
+ left: 0.25rem;
432
+ color: var(--n-surface);
433
+ font-size: 0.55rem;
434
+ font-weight: 800;
435
+ text-align: center;
436
+ text-transform: uppercase;
437
+ }
438
+
439
+ .ugrp-rain-dots {
440
+ position: absolute;
441
+ top: 5.1rem;
442
+ left: 4rem;
443
+ width: var(--ugrp-rain-progress);
444
+ max-width: 8rem;
445
+ height: 4rem;
446
+ background-image: radial-gradient(circle, var(--n-water) 0.12rem, transparent 0.13rem);
447
+ background-size: 1rem 1rem;
448
+ opacity: 0.72;
449
+ transition: width 0.35s ease;
450
+ }
451
+
452
+ .ugrp-status-note {
453
+ margin: 0.95rem 0 0;
454
+ color: var(--n-muted);
455
+ font-size: 0.75rem;
456
+ line-height: 1.45;
457
+ }
458
+
459
+ .ugrp-metrics {
460
+ display: grid;
461
+ grid-template-columns: repeat(2, 1fr);
462
+ gap: 0.65rem;
463
+ margin-top: 1.2rem;
464
+ }
465
+
466
+ .ugrp-metric {
467
+ display: grid;
468
+ gap: 0.35rem;
469
+ min-height: 4.2rem;
470
+ border-top: 1px solid var(--n-line);
471
+ padding: 0.75rem 0.1rem 0;
472
+ }
473
+
474
+ .ugrp-metric span {
475
+ color: var(--n-muted);
476
+ font-size: 0.68rem;
477
+ font-weight: 750;
478
+ line-height: 1.25;
479
+ text-transform: uppercase;
480
+ }
481
+
482
+ .ugrp-metric strong {
483
+ color: var(--n-ink);
484
+ font-size: 1.25rem;
485
+ }
486
+
487
+ .ugrp-metric-main {
488
+ grid-column: 1 / -1;
489
+ min-height: 5.2rem;
490
+ border-top: 0;
491
+ border-radius: 0.9rem;
492
+ padding: 1rem;
493
+ background: var(--n-water-soft);
494
+ }
495
+
496
+ .ugrp-metric-main strong {
497
+ color: var(--n-water);
498
+ font-size: clamp(2rem, 5vw, 3.2rem);
499
+ letter-spacing: -0.04em;
500
+ line-height: 1;
501
+ }
502
+
503
+ @media (max-width: 800px) {
504
+ .ugrp-shell {
505
+ grid-template-columns: 1fr;
506
+ }
507
+
508
+ .ugrp-input-panel {
509
+ border-right: 0;
510
+ border-bottom: 1px solid var(--n-line);
511
+ }
512
+ }
513
+
514
+ @media (max-width: 480px) {
515
+ .ugrp-result-topline {
516
+ display: grid;
517
+ }
518
+
519
+ .ugrp-status {
520
+ max-width: none;
521
+ text-align: left;
522
+ }
523
+
524
+ .ugrp-landscape {
525
+ min-height: 17rem;
526
+ }
527
+
528
+ .ugrp-bed {
529
+ width: 48%;
530
+ }
531
+ }
package/src/tools.ts CHANGED
@@ -4,11 +4,14 @@ import { CRICKET_THERMOMETER_TOOL } from './tool/cricketThermometer/index';
4
4
  import { SEED_CALCULATOR_TOOL } from './tool/seedCalculator/index';
5
5
  import { RAIN_HARVESTER_TOOL } from './tool/rainHarvester/index';
6
6
  import { DIGITAL_CARBON_TOOL } from './tool/digitalCarbon/index';
7
+ import { URBAN_GARDEN_PLANNER_TOOL } from './tool/urbanGardenPlanner/index';
8
+ import { COMPOST_BIN_VOLUME_RATIO_CALCULATOR_TOOL } from './tool/compostBinVolumeRatioCalculator/index';
7
9
 
8
10
  export const ALL_TOOLS: ToolDefinition[] = [
9
11
  CRICKET_THERMOMETER_TOOL,
10
12
  SEED_CALCULATOR_TOOL,
11
13
  RAIN_HARVESTER_TOOL,
12
- DIGITAL_CARBON_TOOL
14
+ DIGITAL_CARBON_TOOL,
15
+ URBAN_GARDEN_PLANNER_TOOL,
16
+ COMPOST_BIN_VOLUME_RATIO_CALCULATOR_TOOL
13
17
  ];
14
-
package/src/types.ts CHANGED
@@ -5,7 +5,7 @@ export type { SEOSection };
5
5
 
6
6
  export type KnownLocale =
7
7
  | 'ar' | 'da' | 'de' | 'en' | 'es' | 'fi'
8
- | 'fr' | 'it' | 'ja' | 'ko' | 'nb' | 'nl'
8
+ | 'fr' | 'id' | 'it' | 'ja' | 'ko' | 'nb' | 'nl'
9
9
  | 'pl' | 'pt' | 'ru' | 'sv' | 'tr' | 'zh';
10
10
 
11
11
  export interface FAQItem {
@@ -23,7 +23,7 @@ export interface HowToStep {
23
23
  text: string;
24
24
  }
25
25
 
26
- export interface ToolLocaleContent<TUI extends Record<string, string> = Record<string, string>> {
26
+ export interface ToolLocaleContent<TUI = Record<string, string>> {
27
27
  slug: string;
28
28
  title: string;
29
29
  description: string;
@@ -46,7 +46,7 @@ export type LocaleLoader<T> = () => Promise<T>;
46
46
 
47
47
  export type LocaleMap<T> = Partial<Record<KnownLocale, LocaleLoader<T>>>;
48
48
 
49
- export interface NatureToolEntry<TUI extends Record<string, string> = Record<string, string>> {
49
+ export interface NatureToolEntry<TUI = Record<string, string>> {
50
50
  id: string;
51
51
  icons: {
52
52
  bg: string;
@@ -57,7 +57,7 @@ export interface NatureToolEntry<TUI extends Record<string, string> = Record<str
57
57
 
58
58
  export interface NatureCategoryEntry {
59
59
  icon: string;
60
- tools: NatureToolEntry[];
60
+ tools: NatureToolEntry<Record<string, string>>[];
61
61
  i18n: LocaleMap<CategoryLocaleContent>;
62
62
  }
63
63