@jjlmoya/utils-health 1.21.0 → 1.23.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 (80) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +4 -1
  3. package/src/entries.ts +7 -1
  4. package/src/index.ts +3 -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/bodyFatPercentageCalculator/bibliography.astro +14 -0
  8. package/src/tool/bodyFatPercentageCalculator/bibliography.ts +24 -0
  9. package/src/tool/bodyFatPercentageCalculator/body-fat-percentage-calculator.css +500 -0
  10. package/src/tool/bodyFatPercentageCalculator/client.ts +330 -0
  11. package/src/tool/bodyFatPercentageCalculator/component.astro +126 -0
  12. package/src/tool/bodyFatPercentageCalculator/entry.ts +27 -0
  13. package/src/tool/bodyFatPercentageCalculator/i18n/de.ts +371 -0
  14. package/src/tool/bodyFatPercentageCalculator/i18n/en.ts +371 -0
  15. package/src/tool/bodyFatPercentageCalculator/i18n/es.ts +371 -0
  16. package/src/tool/bodyFatPercentageCalculator/i18n/fr.ts +371 -0
  17. package/src/tool/bodyFatPercentageCalculator/i18n/id.ts +371 -0
  18. package/src/tool/bodyFatPercentageCalculator/i18n/it.ts +371 -0
  19. package/src/tool/bodyFatPercentageCalculator/i18n/ja.ts +371 -0
  20. package/src/tool/bodyFatPercentageCalculator/i18n/ko.ts +371 -0
  21. package/src/tool/bodyFatPercentageCalculator/i18n/nl.ts +371 -0
  22. package/src/tool/bodyFatPercentageCalculator/i18n/pl.ts +371 -0
  23. package/src/tool/bodyFatPercentageCalculator/i18n/pt.ts +371 -0
  24. package/src/tool/bodyFatPercentageCalculator/i18n/ru.ts +371 -0
  25. package/src/tool/bodyFatPercentageCalculator/i18n/sv.ts +371 -0
  26. package/src/tool/bodyFatPercentageCalculator/i18n/tr.ts +371 -0
  27. package/src/tool/bodyFatPercentageCalculator/i18n/zh.ts +371 -0
  28. package/src/tool/bodyFatPercentageCalculator/index.ts +12 -0
  29. package/src/tool/bodyFatPercentageCalculator/logic.ts +87 -0
  30. package/src/tool/bodyFatPercentageCalculator/seo.astro +15 -0
  31. package/src/tool/bodyFatPercentageCalculator/ui.ts +45 -0
  32. package/src/tool/waistHeightRatioCalculator/bibliography.astro +14 -0
  33. package/src/tool/waistHeightRatioCalculator/bibliography.ts +16 -0
  34. package/src/tool/waistHeightRatioCalculator/component.astro +300 -0
  35. package/src/tool/waistHeightRatioCalculator/entry.ts +27 -0
  36. package/src/tool/waistHeightRatioCalculator/i18n/de.ts +343 -0
  37. package/src/tool/waistHeightRatioCalculator/i18n/en.ts +343 -0
  38. package/src/tool/waistHeightRatioCalculator/i18n/es.ts +343 -0
  39. package/src/tool/waistHeightRatioCalculator/i18n/fr.ts +343 -0
  40. package/src/tool/waistHeightRatioCalculator/i18n/id.ts +343 -0
  41. package/src/tool/waistHeightRatioCalculator/i18n/it.ts +343 -0
  42. package/src/tool/waistHeightRatioCalculator/i18n/ja.ts +343 -0
  43. package/src/tool/waistHeightRatioCalculator/i18n/ko.ts +343 -0
  44. package/src/tool/waistHeightRatioCalculator/i18n/nl.ts +343 -0
  45. package/src/tool/waistHeightRatioCalculator/i18n/pl.ts +343 -0
  46. package/src/tool/waistHeightRatioCalculator/i18n/pt.ts +343 -0
  47. package/src/tool/waistHeightRatioCalculator/i18n/ru.ts +343 -0
  48. package/src/tool/waistHeightRatioCalculator/i18n/sv.ts +343 -0
  49. package/src/tool/waistHeightRatioCalculator/i18n/tr.ts +343 -0
  50. package/src/tool/waistHeightRatioCalculator/i18n/zh.ts +343 -0
  51. package/src/tool/waistHeightRatioCalculator/index.ts +12 -0
  52. package/src/tool/waistHeightRatioCalculator/logic.ts +29 -0
  53. package/src/tool/waistHeightRatioCalculator/seo.astro +15 -0
  54. package/src/tool/waistHeightRatioCalculator/ui.ts +34 -0
  55. package/src/tool/waistHeightRatioCalculator/waist-height-ratio-calculator.css +368 -0
  56. package/src/tool/waistHipRatioCalculator/bibliography.astro +14 -0
  57. package/src/tool/waistHipRatioCalculator/bibliography.ts +24 -0
  58. package/src/tool/waistHipRatioCalculator/component.astro +316 -0
  59. package/src/tool/waistHipRatioCalculator/entry.ts +27 -0
  60. package/src/tool/waistHipRatioCalculator/i18n/de.ts +316 -0
  61. package/src/tool/waistHipRatioCalculator/i18n/en.ts +316 -0
  62. package/src/tool/waistHipRatioCalculator/i18n/es.ts +316 -0
  63. package/src/tool/waistHipRatioCalculator/i18n/fr.ts +316 -0
  64. package/src/tool/waistHipRatioCalculator/i18n/id.ts +316 -0
  65. package/src/tool/waistHipRatioCalculator/i18n/it.ts +316 -0
  66. package/src/tool/waistHipRatioCalculator/i18n/ja.ts +316 -0
  67. package/src/tool/waistHipRatioCalculator/i18n/ko.ts +316 -0
  68. package/src/tool/waistHipRatioCalculator/i18n/nl.ts +316 -0
  69. package/src/tool/waistHipRatioCalculator/i18n/pl.ts +316 -0
  70. package/src/tool/waistHipRatioCalculator/i18n/pt.ts +316 -0
  71. package/src/tool/waistHipRatioCalculator/i18n/ru.ts +316 -0
  72. package/src/tool/waistHipRatioCalculator/i18n/sv.ts +316 -0
  73. package/src/tool/waistHipRatioCalculator/i18n/tr.ts +316 -0
  74. package/src/tool/waistHipRatioCalculator/i18n/zh.ts +316 -0
  75. package/src/tool/waistHipRatioCalculator/index.ts +12 -0
  76. package/src/tool/waistHipRatioCalculator/logic.ts +36 -0
  77. package/src/tool/waistHipRatioCalculator/seo.astro +15 -0
  78. package/src/tool/waistHipRatioCalculator/ui.ts +35 -0
  79. package/src/tool/waistHipRatioCalculator/waist-hip-ratio-calculator.css +433 -0
  80. package/src/tools.ts +4 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jjlmoya/utils-health",
3
- "version": "1.21.0",
3
+ "version": "1.23.0",
4
4
  "type": "module",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
@@ -1,6 +1,9 @@
1
1
  import type { HealthCategoryEntry } from '../types';
2
2
  import { bmiCalculator } from '../tool/bmiCalculator/entry';
3
3
  import { bodyAdiposityIndexCalculator } from '../tool/bodyAdiposityIndexCalculator/entry';
4
+ import { bodyFatPercentageCalculator } from '../tool/bodyFatPercentageCalculator/entry';
5
+ import { waistHipRatioCalculator } from '../tool/waistHipRatioCalculator/entry';
6
+ import { waistHeightRatioCalculator } from '../tool/waistHeightRatioCalculator/entry';
4
7
  import { daltonismSimulator } from '../tool/daltonismSimulator/entry';
5
8
  import { tinnitusReliever } from '../tool/tinnitusReliever/entry';
6
9
  import { breathingVisualizer } from '../tool/breathingVisualizer/entry';
@@ -18,7 +21,7 @@ import { metabolicAgeCalculator } from '../tool/metabolicAgeCalculator/entry';
18
21
 
19
22
  export const healthCategory: HealthCategoryEntry = {
20
23
  icon: 'mdi:heart-pulse',
21
- tools: [bmiCalculator, bodyAdiposityIndexCalculator, leanBodyMassCalculator, metabolicAgeCalculator, caloricDeficitCalculator, dailyProteinCalculator, daltonismSimulator, tinnitusReliever, breathingVisualizer, caffeineTracker, waterPurifier, digestionStopwatch, binauralTuner, pelliRobsonTest, peripheralVisionTrainer, epworthSleepinessScale],
24
+ tools: [bmiCalculator, bodyAdiposityIndexCalculator, bodyFatPercentageCalculator, waistHipRatioCalculator, waistHeightRatioCalculator, leanBodyMassCalculator, metabolicAgeCalculator, caloricDeficitCalculator, dailyProteinCalculator, daltonismSimulator, tinnitusReliever, breathingVisualizer, caffeineTracker, waterPurifier, digestionStopwatch, binauralTuner, pelliRobsonTest, peripheralVisionTrainer, epworthSleepinessScale],
22
25
  i18n: {
23
26
  en: () => import('./i18n/en').then((m) => m.content),
24
27
  es: () => import('./i18n/es').then((m) => m.content),
package/src/entries.ts CHANGED
@@ -2,6 +2,9 @@ export { binauralTuner } from './tool/binauralTuner/entry';
2
2
  export { bloodUnitConverter } from './tool/bloodUnitConverter/entry';
3
3
  export { bmiCalculator } from './tool/bmiCalculator/entry';
4
4
  export { bodyAdiposityIndexCalculator } from './tool/bodyAdiposityIndexCalculator/entry';
5
+ export { bodyFatPercentageCalculator } from './tool/bodyFatPercentageCalculator/entry';
6
+ export { waistHipRatioCalculator } from './tool/waistHipRatioCalculator/entry';
7
+ export { waistHeightRatioCalculator } from './tool/waistHeightRatioCalculator/entry';
5
8
  export { breathingVisualizer } from './tool/breathingVisualizer/entry';
6
9
  export { caffeineTracker } from './tool/caffeineTracker/entry';
7
10
  export { caloricDeficitCalculator } from './tool/caloricDeficitCalculator/entry';
@@ -24,6 +27,9 @@ import { binauralTuner } from './tool/binauralTuner/entry';
24
27
  import { bloodUnitConverter } from './tool/bloodUnitConverter/entry';
25
28
  import { bmiCalculator } from './tool/bmiCalculator/entry';
26
29
  import { bodyAdiposityIndexCalculator } from './tool/bodyAdiposityIndexCalculator/entry';
30
+ import { bodyFatPercentageCalculator } from './tool/bodyFatPercentageCalculator/entry';
31
+ import { waistHipRatioCalculator } from './tool/waistHipRatioCalculator/entry';
32
+ import { waistHeightRatioCalculator } from './tool/waistHeightRatioCalculator/entry';
27
33
  import { breathingVisualizer } from './tool/breathingVisualizer/entry';
28
34
  import { caffeineTracker } from './tool/caffeineTracker/entry';
29
35
  import { caloricDeficitCalculator } from './tool/caloricDeficitCalculator/entry';
@@ -41,4 +47,4 @@ import { screenDecompressionTime } from './tool/screenDecompressionTime/entry';
41
47
  import { tinnitusReliever } from './tool/tinnitusReliever/entry';
42
48
  import { ubeCalculator } from './tool/ubeCalculator/entry';
43
49
  import { waterPurifier } from './tool/waterPurifier/entry';
44
- export const ALL_ENTRIES = [binauralTuner, bloodUnitConverter, bmiCalculator, bodyAdiposityIndexCalculator, breathingVisualizer, caffeineTracker, caloricDeficitCalculator, dailyProteinCalculator, daltonismSimulator, digestionStopwatch, epworthSleepinessScale, hydrationCalculator, leanBodyMassCalculator, metabolicAgeCalculator, pelliRobsonTest, peripheralVisionTrainer, readingDistanceCalculator, screenDecompressionTime, tinnitusReliever, ubeCalculator, waterPurifier];
50
+ export const ALL_ENTRIES = [binauralTuner, bloodUnitConverter, bmiCalculator, bodyAdiposityIndexCalculator, bodyFatPercentageCalculator, waistHipRatioCalculator, waistHeightRatioCalculator, breathingVisualizer, caffeineTracker, caloricDeficitCalculator, dailyProteinCalculator, daltonismSimulator, digestionStopwatch, epworthSleepinessScale, hydrationCalculator, leanBodyMassCalculator, metabolicAgeCalculator, pelliRobsonTest, peripheralVisionTrainer, readingDistanceCalculator, screenDecompressionTime, tinnitusReliever, ubeCalculator, waterPurifier];
package/src/index.ts CHANGED
@@ -16,9 +16,12 @@ export * from './tool/bloodUnitConverter';
16
16
  export * from './tool/readingDistanceCalculator';
17
17
  export * from './tool/hydrationCalculator';
18
18
  export * from './tool/bodyAdiposityIndexCalculator';
19
+ export * from './tool/waistHipRatioCalculator';
20
+ export * from './tool/waistHeightRatioCalculator';
19
21
  export * from './tool/dailyProteinCalculator';
20
22
  export * from './tool/leanBodyMassCalculator';
21
23
  export * from './tool/metabolicAgeCalculator';
24
+ export * from './tool/bodyFatPercentageCalculator';
22
25
 
23
26
  export { healthCategory } from './category';
24
27
  export const healthCategorySEO = () => import('./category/seo.astro').then((m) => m.default);
@@ -35,7 +35,7 @@ describe('Locale Completeness Validation', () => {
35
35
  });
36
36
  });
37
37
 
38
- it('all 21 tools registered', () => {
39
- expect(ALL_TOOLS.length).toBe(21);
38
+ it('all 24 tools registered', () => {
39
+ expect(ALL_TOOLS.length).toBe(24);
40
40
  });
41
41
  });
@@ -4,8 +4,8 @@ import { healthCategory } from '../data';
4
4
 
5
5
  describe('Tool Validation Suite', () => {
6
6
  describe('Library Registration', () => {
7
- it('should have 21 tools in ALL_TOOLS', () => {
8
- expect(ALL_TOOLS.length).toBe(21);
7
+ it('should have 24 tools in ALL_TOOLS', () => {
8
+ expect(ALL_TOOLS.length).toBe(24);
9
9
  });
10
10
 
11
11
  it('healthCategory should be defined', () => {
@@ -0,0 +1,14 @@
1
+ ---
2
+ import { Bibliography } from '@jjlmoya/utils-shared';
3
+ import { bodyFatPercentageCalculator } 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 bodyFatPercentageCalculator.i18n[locale]?.();
12
+ ---
13
+
14
+ {content && <Bibliography links={content.bibliography} />}
@@ -0,0 +1,24 @@
1
+ import type { BibliographyEntry } from '../../types';
2
+
3
+ export const bibliography: BibliographyEntry[] = [
4
+ {
5
+ name: 'Hodgdon JA, Beckett MB: Prediction of percent body fat for U.S. Navy men from body circumferences and height',
6
+ url: 'https://apps.dtic.mil/sti/citations/ADA143890',
7
+ },
8
+ {
9
+ name: 'Deurenberg P, Weststrate JA, Seidell JC: Body mass index as a measure of body fatness',
10
+ url: 'https://doi.org/10.1079/BJN19910073',
11
+ },
12
+ {
13
+ name: 'Jackson AS, Pollock ML: Practical assessment of body composition',
14
+ url: 'https://doi.org/10.1080/00913847.1985.11708790',
15
+ },
16
+ {
17
+ name: 'CDC: About adult BMI',
18
+ url: 'https://www.cdc.gov/bmi/adult-calculator/bmi-categories.html',
19
+ },
20
+ {
21
+ name: 'Wikipedia: Body fat percentage',
22
+ url: 'https://en.wikipedia.org/wiki/Body_fat_percentage',
23
+ },
24
+ ];
@@ -0,0 +1,500 @@
1
+ .bfpc {
2
+ --bfpc-paper: #f7f8f5;
3
+ --bfpc-panel: #fff;
4
+ --bfpc-ink: #20242a;
5
+ --bfpc-muted: #68707b;
6
+ --bfpc-line: #d9dfdf;
7
+ --bfpc-blue: #2e72c2;
8
+ --bfpc-green: #1e8b61;
9
+ --bfpc-yellow: #d3a326;
10
+ --bfpc-orange: #d46f2d;
11
+ --bfpc-red: #c8434a;
12
+ --bfpc-shadow: rgba(22, 30, 36, 0.12);
13
+
14
+ width: 100%;
15
+ }
16
+
17
+ .theme-dark .bfpc {
18
+ --bfpc-paper: #111820;
19
+ --bfpc-panel: #1a232c;
20
+ --bfpc-ink: #f1f5f7;
21
+ --bfpc-muted: #a7b1bb;
22
+ --bfpc-line: #34414b;
23
+ --bfpc-shadow: rgba(0, 0, 0, 0.34);
24
+ }
25
+
26
+ .bfpc__shell {
27
+ overflow: hidden;
28
+ border: 1px solid var(--bfpc-line);
29
+ border-radius: 8px;
30
+ background: var(--bfpc-paper);
31
+ color: var(--bfpc-ink);
32
+ box-shadow: 0 18px 44px var(--bfpc-shadow);
33
+ }
34
+
35
+ .bfpc__toolbar,
36
+ .bfpc__body,
37
+ .bfpc__notes {
38
+ display: grid;
39
+ }
40
+
41
+ .bfpc__toolbar {
42
+ gap: 0.75rem;
43
+ padding: 0.8rem;
44
+ border-bottom: 1px solid var(--bfpc-line);
45
+ background: var(--bfpc-panel);
46
+ }
47
+
48
+ .bfpc__tabs,
49
+ .bfpc__unit,
50
+ .bfpc__sex {
51
+ width: max-content;
52
+ display: grid;
53
+ grid-auto-flow: column;
54
+ gap: 0.28rem;
55
+ padding: 0.28rem;
56
+ border: 1px solid var(--bfpc-line);
57
+ border-radius: 8px;
58
+ background: var(--bfpc-paper);
59
+ }
60
+
61
+ .bfpc__tabs {
62
+ grid-template-columns: repeat(2, minmax(0, 1fr));
63
+ }
64
+
65
+ .bfpc__unit {
66
+ grid-template-columns: repeat(2, minmax(0, 1fr));
67
+ }
68
+
69
+ .bfpc__tab,
70
+ .bfpc__unit-btn,
71
+ .bfpc__sex-btn {
72
+ min-height: 2.45rem;
73
+ min-width: 6.3rem;
74
+ border: 0;
75
+ border-radius: 6px;
76
+ background: transparent;
77
+ color: var(--bfpc-muted);
78
+ font: inherit;
79
+ font-size: 0.84rem;
80
+ font-weight: 850;
81
+ cursor: pointer;
82
+ }
83
+
84
+ .bfpc__tab,
85
+ .bfpc__sex-btn {
86
+ display: inline-grid;
87
+ grid-auto-flow: column;
88
+ gap: 0.4rem;
89
+ align-items: center;
90
+ justify-content: center;
91
+ }
92
+
93
+ .bfpc__tab svg,
94
+ .bfpc__sex-btn svg,
95
+ .bfpc__notes svg {
96
+ width: 1.1rem;
97
+ height: 1.1rem;
98
+ }
99
+
100
+ .bfpc__tab--active,
101
+ .bfpc__unit-btn--active,
102
+ .bfpc__sex-btn--active {
103
+ background: var(--bfpc-ink);
104
+ color: var(--bfpc-panel);
105
+ }
106
+
107
+ .theme-dark .bfpc__tab--active,
108
+ .theme-dark .bfpc__unit-btn--active,
109
+ .theme-dark .bfpc__sex-btn--active {
110
+ background: #eef3f5;
111
+ color: #151a1f;
112
+ }
113
+
114
+ .bfpc__body {
115
+ grid-template-columns: 1fr;
116
+ }
117
+
118
+ .bfpc__panel,
119
+ .bfpc__result {
120
+ padding: clamp(0.95rem, 3vw, 1.35rem);
121
+ }
122
+
123
+ .bfpc__panel {
124
+ display: grid;
125
+ gap: 0.8rem;
126
+ border-bottom: 1px solid var(--bfpc-line);
127
+ align-content: start;
128
+ }
129
+
130
+ .bfpc__caption {
131
+ min-height: 3rem;
132
+ margin: 0;
133
+ color: var(--bfpc-muted);
134
+ font-size: 0.92rem;
135
+ line-height: 1.45;
136
+ }
137
+
138
+ .bfpc__fields {
139
+ display: grid;
140
+ gap: 0.7rem;
141
+ grid-template-columns: 1fr;
142
+ }
143
+
144
+ .bfpc__field {
145
+ display: grid;
146
+ gap: 0.55rem;
147
+ padding: 0.78rem 0.82rem;
148
+ border: 1px solid var(--bfpc-line);
149
+ border-radius: 8px;
150
+ background: var(--bfpc-panel);
151
+ }
152
+
153
+ .bfpc__field[hidden] {
154
+ display: none;
155
+ }
156
+
157
+ .bfpc__field span {
158
+ color: var(--bfpc-muted);
159
+ font-size: 0.74rem;
160
+ font-weight: 900;
161
+ text-transform: uppercase;
162
+ }
163
+
164
+ .bfpc__field div {
165
+ display: grid;
166
+ grid-template-columns: minmax(0, 1fr) auto;
167
+ gap: 0.45rem;
168
+ align-items: baseline;
169
+ }
170
+
171
+ .bfpc__field output {
172
+ width: 100%;
173
+ min-width: 0;
174
+ color: var(--bfpc-ink);
175
+ font: inherit;
176
+ font-size: clamp(1.42rem, 5vw, 1.92rem);
177
+ font-weight: 900;
178
+ line-height: 1;
179
+ font-variant-numeric: tabular-nums;
180
+ }
181
+
182
+ .bfpc__field input {
183
+ -webkit-appearance: none;
184
+ appearance: none;
185
+ width: 100%;
186
+ height: 1.35rem;
187
+ margin: 0;
188
+ border: 0;
189
+ background: transparent;
190
+ accent-color: var(--bfpc-ink);
191
+ cursor: ew-resize;
192
+ }
193
+
194
+ .bfpc__field input:focus {
195
+ outline: 2px solid color-mix(in srgb, var(--bfpc-blue) 55%, transparent);
196
+ outline-offset: 3px;
197
+ }
198
+
199
+ .bfpc__field strong {
200
+ color: var(--bfpc-muted);
201
+ font-size: 0.85rem;
202
+ }
203
+
204
+ .bfpc__field input::-webkit-slider-runnable-track {
205
+ height: 0.42rem;
206
+ border-radius: 999px;
207
+ background: linear-gradient(90deg, color-mix(in srgb, var(--bfpc-blue) 78%, white) 0 var(--range-fill, 50%), color-mix(in srgb, var(--bfpc-ink) 14%, transparent) var(--range-fill, 50%) 100%);
208
+ background-color: color-mix(in srgb, var(--bfpc-ink) 14%, transparent);
209
+ }
210
+
211
+ .bfpc__field input::-webkit-slider-thumb {
212
+ -webkit-appearance: none;
213
+ appearance: none;
214
+ width: 1.28rem;
215
+ height: 1.28rem;
216
+ margin-top: calc((0.42rem - 1.28rem) / 2);
217
+ border: 2px solid var(--bfpc-panel);
218
+ border-radius: 999px;
219
+ background: var(--bfpc-ink);
220
+ box-shadow: 0 4px 14px var(--bfpc-shadow);
221
+ }
222
+
223
+ .bfpc__field input::-moz-range-track {
224
+ height: 0.42rem;
225
+ border: 0;
226
+ border-radius: 999px;
227
+ background: color-mix(in srgb, var(--bfpc-ink) 14%, transparent);
228
+ }
229
+
230
+ .bfpc__field input::-moz-range-progress {
231
+ height: 0.42rem;
232
+ border-radius: 999px;
233
+ background: color-mix(in srgb, var(--bfpc-blue) 78%, white);
234
+ }
235
+
236
+ .bfpc__field input::-moz-range-thumb {
237
+ box-sizing: border-box;
238
+ width: 1.28rem;
239
+ height: 1.28rem;
240
+ border: 2px solid var(--bfpc-panel);
241
+ border-radius: 999px;
242
+ background: var(--bfpc-ink);
243
+ }
244
+
245
+ .bfpc__result {
246
+ display: grid;
247
+ gap: 1rem;
248
+ align-content: start;
249
+ background:
250
+ linear-gradient(to right, color-mix(in srgb, var(--bfpc-line) 26%, transparent) 1px, transparent 1px),
251
+ linear-gradient(to bottom, color-mix(in srgb, var(--bfpc-line) 22%, transparent) 1px, transparent 1px),
252
+ var(--bfpc-paper);
253
+ background-size: 30px 30px;
254
+ }
255
+
256
+ .bfpc__dial {
257
+ position: relative;
258
+ display: grid;
259
+ grid-template-rows: auto auto auto;
260
+ justify-items: center;
261
+ align-content: center;
262
+ gap: 0.35rem;
263
+ min-height: 12.2rem;
264
+ isolation: isolate;
265
+ }
266
+
267
+ .bfpc__dial-ring {
268
+ position: relative;
269
+ grid-row: 2;
270
+ width: min(7.8rem, 48vw);
271
+ aspect-ratio: 1;
272
+ border-radius: 999px;
273
+ background: conic-gradient(var(--bfpc-blue) 0 18%, var(--bfpc-green) 18% 42%, var(--bfpc-yellow) 42% 58%, var(--bfpc-orange) 58% 76%, var(--bfpc-red) 76% 100%);
274
+ opacity: 0.92;
275
+ box-shadow: inset 0 0 0 1px var(--bfpc-line), 0 18px 34px var(--bfpc-shadow);
276
+ }
277
+
278
+ .bfpc__dial-ring::after {
279
+ content: "";
280
+ position: absolute;
281
+ inset: 0.68rem;
282
+ border-radius: inherit;
283
+ background: var(--bfpc-panel);
284
+ }
285
+
286
+ .bfpc__dial strong,
287
+ .bfpc__dial span {
288
+ position: relative;
289
+ z-index: 1;
290
+ }
291
+
292
+ .bfpc__dial strong {
293
+ grid-row: 1;
294
+ padding: 0;
295
+ border-radius: 0;
296
+ background: transparent;
297
+ font-size: clamp(3.15rem, 10vw, 4.7rem);
298
+ line-height: 0.95;
299
+ font-variant-numeric: tabular-nums;
300
+ text-align: center;
301
+ }
302
+
303
+ .bfpc__dial span,
304
+ .bfpc__category span,
305
+ .bfpc__bmi-line {
306
+ color: var(--bfpc-muted);
307
+ font-size: 0.76rem;
308
+ font-weight: 900;
309
+ text-transform: uppercase;
310
+ }
311
+
312
+ .bfpc__dial span {
313
+ grid-row: 3;
314
+ max-width: 100%;
315
+ text-align: center;
316
+ }
317
+
318
+ .bfpc__category {
319
+ min-height: 7.2rem;
320
+ padding: 0.95rem;
321
+ border: 1px solid var(--bfpc-line);
322
+ border-radius: 8px;
323
+ background: var(--bfpc-panel);
324
+ }
325
+
326
+ .bfpc__category strong {
327
+ display: block;
328
+ margin: 0.2rem 0 0.35rem;
329
+ font-size: clamp(1.35rem, 5vw, 1.9rem);
330
+ line-height: 1.05;
331
+ }
332
+
333
+ .bfpc__category p {
334
+ margin: 0;
335
+ color: var(--bfpc-muted);
336
+ font-size: 0.92rem;
337
+ line-height: 1.45;
338
+ }
339
+
340
+ .bfpc__result[data-category="essential"] .bfpc__dial strong,
341
+ .bfpc__result[data-category="essential"] .bfpc__category strong { color: var(--bfpc-blue); }
342
+ .bfpc__result[data-category="athletes"] .bfpc__dial strong,
343
+ .bfpc__result[data-category="athletes"] .bfpc__category strong { color: var(--bfpc-green); }
344
+ .bfpc__result[data-category="fitness"] .bfpc__dial strong,
345
+ .bfpc__result[data-category="fitness"] .bfpc__category strong { color: var(--bfpc-yellow); }
346
+ .bfpc__result[data-category="average"] .bfpc__dial strong,
347
+ .bfpc__result[data-category="average"] .bfpc__category strong { color: var(--bfpc-orange); }
348
+ .bfpc__result[data-category="obesity"] .bfpc__dial strong,
349
+ .bfpc__result[data-category="obesity"] .bfpc__category strong { color: var(--bfpc-red); }
350
+
351
+ .bfpc__bar {
352
+ position: relative;
353
+ display: grid;
354
+ grid-template-columns: 18fr 24fr 16fr 18fr 24fr;
355
+ min-height: 3.35rem;
356
+ margin-top: 1.45rem;
357
+ overflow: visible;
358
+ border: 1px solid var(--bfpc-line);
359
+ border-radius: 8px;
360
+ background: var(--bfpc-panel);
361
+ }
362
+
363
+ .bfpc__bar span {
364
+ display: grid;
365
+ align-items: end;
366
+ padding: 0.55rem 0.35rem;
367
+ color: #fff;
368
+ font-size: 0.62rem;
369
+ font-weight: 900;
370
+ line-height: 1;
371
+ text-align: center;
372
+ text-transform: uppercase;
373
+ }
374
+
375
+ .bfpc__bar span:first-child {
376
+ border-radius: 7px 0 0 7px;
377
+ }
378
+
379
+ .bfpc__bar span:nth-last-child(2) {
380
+ border-radius: 0 7px 7px 0;
381
+ }
382
+
383
+ .bfpc__bar span[data-segment="essential"] { background: var(--bfpc-blue); }
384
+ .bfpc__bar span[data-segment="athletes"] { background: var(--bfpc-green); }
385
+ .bfpc__bar span[data-segment="fitness"] { background: var(--bfpc-yellow); }
386
+ .bfpc__bar span[data-segment="average"] { background: var(--bfpc-orange); }
387
+ .bfpc__bar span[data-segment="obesity"] { background: var(--bfpc-red); }
388
+
389
+ .bfpc__bar i {
390
+ position: absolute;
391
+ top: -1.35rem;
392
+ left: 48%;
393
+ width: 2.3rem;
394
+ height: 1.15rem;
395
+ border: 1px solid color-mix(in srgb, var(--bfpc-panel) 70%, var(--bfpc-ink));
396
+ border-radius: 999px 999px 6px 6px;
397
+ background: var(--bfpc-ink);
398
+ transform: translateX(-50%);
399
+ transition: left 160ms ease;
400
+ box-shadow: 0 6px 16px var(--bfpc-shadow);
401
+ }
402
+
403
+ .bfpc__bar i::before {
404
+ content: "";
405
+ position: absolute;
406
+ left: 50%;
407
+ top: 100%;
408
+ width: 0.18rem;
409
+ height: 1.55rem;
410
+ border-radius: 999px;
411
+ background: var(--bfpc-ink);
412
+ transform: translateX(-50%);
413
+ }
414
+
415
+ .bfpc__bar i::after {
416
+ content: "";
417
+ position: absolute;
418
+ left: 50%;
419
+ top: calc(100% + 1.35rem);
420
+ width: 0;
421
+ height: 0;
422
+ border-left: 0.38rem solid transparent;
423
+ border-right: 0.38rem solid transparent;
424
+ border-top: 0.48rem solid var(--bfpc-ink);
425
+ transform: translateX(-50%);
426
+ }
427
+
428
+ .bfpc__bmi-line[hidden] {
429
+ display: none;
430
+ }
431
+
432
+ .bfpc__notes {
433
+ border-top: 1px solid var(--bfpc-line);
434
+ }
435
+
436
+ .bfpc__notes div {
437
+ display: grid;
438
+ grid-template-columns: 1.35rem 1fr;
439
+ gap: 0.7rem;
440
+ padding: 0.82rem 0.95rem;
441
+ border-bottom: 1px solid var(--bfpc-line);
442
+ background: var(--bfpc-panel);
443
+ color: var(--bfpc-muted);
444
+ }
445
+
446
+ .bfpc__notes div:last-child {
447
+ border-bottom: 0;
448
+ }
449
+
450
+ .bfpc__notes svg {
451
+ color: var(--bfpc-blue);
452
+ }
453
+
454
+ .bfpc__notes p {
455
+ margin: 0;
456
+ font-size: 0.86rem;
457
+ line-height: 1.45;
458
+ }
459
+
460
+ .bfpc__notes strong {
461
+ color: var(--bfpc-ink);
462
+ }
463
+
464
+ @media (max-width: 480px) {
465
+ .bfpc__tab span {
466
+ font-size: 0.76rem;
467
+ }
468
+
469
+ .bfpc__sex {
470
+ width: 100%;
471
+ }
472
+ }
473
+
474
+ @media (min-width: 760px) {
475
+ .bfpc__toolbar {
476
+ grid-template-columns: minmax(0, 1fr) minmax(220px, 0.32fr);
477
+ }
478
+
479
+ .bfpc__body {
480
+ grid-template-columns: minmax(330px, 0.85fr) minmax(360px, 1.15fr);
481
+ }
482
+
483
+ .bfpc__panel {
484
+ border-right: 1px solid var(--bfpc-line);
485
+ border-bottom: 0;
486
+ }
487
+
488
+ .bfpc__notes {
489
+ grid-template-columns: repeat(3, 1fr);
490
+ }
491
+
492
+ .bfpc__notes div {
493
+ border-right: 1px solid var(--bfpc-line);
494
+ border-bottom: 0;
495
+ }
496
+
497
+ .bfpc__notes div:last-child {
498
+ border-right: 0;
499
+ }
500
+ }