@titan-design/react-ui 0.3.0 → 0.5.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 (90) hide show
  1. package/dist/MesoStatusCard-CQk71hSi.d.mts +77 -0
  2. package/dist/MesoStatusCard-CQk71hSi.d.ts +77 -0
  3. package/dist/bodymap.d.mts +246 -3
  4. package/dist/bodymap.d.ts +246 -3
  5. package/dist/bodymap.js +441 -97
  6. package/dist/bodymap.js.map +1 -1
  7. package/dist/bodymap.mjs +1958 -66
  8. package/dist/bodymap.mjs.map +1 -1
  9. package/dist/index.d.mts +71 -738
  10. package/dist/index.d.ts +71 -738
  11. package/dist/index.js +888 -1583
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.mjs +4515 -2348
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/pages-D7Jlssvp.d.ts +791 -0
  16. package/dist/pages-MO0JCySL.d.mts +791 -0
  17. package/dist/pages.d.mts +4 -0
  18. package/dist/pages.d.ts +4 -0
  19. package/dist/pages.js +6646 -0
  20. package/dist/pages.js.map +1 -0
  21. package/dist/pages.mjs +6626 -0
  22. package/dist/pages.mjs.map +1 -0
  23. package/dist/theme/index.d.mts +28 -2
  24. package/dist/theme/index.d.ts +28 -2
  25. package/dist/theme/index.js +37 -0
  26. package/dist/theme/index.js.map +1 -1
  27. package/dist/theme/index.mjs +1880 -2
  28. package/dist/theme/index.mjs.map +1 -1
  29. package/dist/theme/tokens-css.mjs +573 -1
  30. package/dist/theme/tokens-css.mjs.map +1 -1
  31. package/package.json +9 -7
  32. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +10 -15
  33. package/src/components/custom/Workout/BaseBadge.stories.tsx +3 -3
  34. package/src/components/custom/Workout/BaseBadge.test.tsx +1 -1
  35. package/src/components/custom/Workout/BaseBadge.tsx +1 -1
  36. package/src/components/custom/Workout/BodyMap.tsx +7 -8
  37. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +25 -28
  38. package/src/components/custom/Workout/CapacityBandChart.tsx +2 -3
  39. package/src/components/custom/Workout/ExerciseCard.tsx +17 -28
  40. package/src/components/custom/Workout/ExerciseDetailPage.tsx +38 -31
  41. package/src/components/custom/Workout/InputBar.tsx +10 -11
  42. package/src/components/custom/Workout/IntensityBar.test.tsx +112 -60
  43. package/src/components/custom/Workout/IntensityBar.tsx +109 -58
  44. package/src/components/custom/Workout/MesoCard.tsx +2 -6
  45. package/src/components/custom/Workout/MesoStatusCard.tsx +17 -15
  46. package/src/components/custom/Workout/MuscleGroupChip.tsx +2 -4
  47. package/src/components/custom/Workout/PlaceholderStrip.tsx +5 -10
  48. package/src/components/custom/Workout/PrBadge.tsx +3 -3
  49. package/src/components/custom/Workout/PrHistoryModal.tsx +14 -16
  50. package/src/components/custom/Workout/ProgramPlanningPage.tsx +8 -12
  51. package/src/components/custom/Workout/README.md +50 -0
  52. package/src/components/custom/Workout/ReadinessCheck.tsx +13 -11
  53. package/src/components/custom/Workout/RestTimer.test.tsx +41 -10
  54. package/src/components/custom/Workout/RestTimer.tsx +55 -49
  55. package/src/components/custom/Workout/SetRow.tsx +20 -8
  56. package/src/components/custom/Workout/StrengthTrendChart.tsx +15 -17
  57. package/src/components/custom/Workout/TempoBar.stories.tsx +95 -0
  58. package/src/components/custom/Workout/TempoBar.test.tsx +103 -0
  59. package/src/components/custom/Workout/TempoBar.tsx +215 -0
  60. package/src/components/custom/Workout/TempoDisplay.stories.tsx +69 -2
  61. package/src/components/custom/Workout/TempoDisplay.test.tsx +35 -0
  62. package/src/components/custom/Workout/TempoDisplay.tsx +104 -1
  63. package/src/components/custom/Workout/TrainingStatusPage.tsx +8 -17
  64. package/src/components/custom/Workout/VelocityStrip.test.tsx +89 -2
  65. package/src/components/custom/Workout/VelocityStrip.tsx +210 -43
  66. package/src/components/custom/Workout/WeekRow.test.tsx +2 -2
  67. package/src/components/custom/Workout/WeekRow.tsx +2 -1
  68. package/src/components/custom/Workout/WeightBadge.test.tsx +2 -2
  69. package/src/components/custom/Workout/WeightBadge.tsx +2 -2
  70. package/src/components/custom/Workout/WorkoutCard.tsx +3 -8
  71. package/src/components/custom/Workout/icons.tsx +68 -0
  72. package/src/components/custom/Workout/index.ts +47 -47
  73. package/src/index.ts +3 -2
  74. package/src/pages.ts +61 -0
  75. package/src/test/nativewind-stub.ts +13 -0
  76. package/src/test/stories-smoke.test.tsx +50 -0
  77. package/src/theme/ThemeProvider.test.tsx +24 -0
  78. package/src/theme/ThemeProvider.tsx +50 -0
  79. package/src/theme/barrel.ts +53 -0
  80. package/src/theme/index.ts +8 -41
  81. package/src/theme/native-theming-guard.test.ts +117 -0
  82. package/src/theme/resolve-color.ts +19 -0
  83. package/dist/bodymap-BhG55xHM.d.mts +0 -318
  84. package/dist/bodymap-BhG55xHM.d.ts +0 -318
  85. package/dist/chunk-7XPB4NAO.mjs +0 -1013
  86. package/dist/chunk-7XPB4NAO.mjs.map +0 -1
  87. package/dist/chunk-P7TSQUN6.mjs +0 -846
  88. package/dist/chunk-P7TSQUN6.mjs.map +0 -1
  89. package/dist/chunk-TOD2WQBG.mjs +0 -1048
  90. package/dist/chunk-TOD2WQBG.mjs.map +0 -1
package/dist/bodymap.mjs CHANGED
@@ -1,9 +1,409 @@
1
- import { WORKOUT_TOKENS, jsxs, jsx, cn, Badge, Sparkline, MesoStatusCard } from './chunk-TOD2WQBG.mjs';
2
- import './chunk-P7TSQUN6.mjs';
3
- import './chunk-7XPB4NAO.mjs';
4
- import { useMemo, useState, useEffect } from 'react';
5
- import { Animated, Easing, View, Text, Pressable, ScrollView } from 'react-native';
1
+ import { useMemo, useState, useEffect, Fragment as Fragment$1, useSyncExternalStore } from 'react';
2
+ import { Platform, Animated, Easing, View, Text, Pressable, ScrollView } from 'react-native';
6
3
  import BodyHighlighter from 'react-native-body-highlighter';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { Fragment, jsx as jsx$1, jsxs as jsxs$1 } from 'react/jsx-runtime';
7
+
8
+ // src/components/custom/Workout/BodyMap.tsx
9
+ function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
12
+
13
+ // src/theme/tokens/primitives.ts
14
+ var primitiveColors = {
15
+ // Blue scale (primary brand)
16
+ blue: {
17
+ 400: "#60A5FA",
18
+ 600: "#5048E5",
19
+ // Primary main
20
+ 700: "#3832A0"},
21
+ // Teal scale (success)
22
+ teal: {
23
+ 50: "#F0FDFA",
24
+ 400: "#43C6B7",
25
+ // Success light
26
+ 500: "#14B8A6",
27
+ 700: "#0E8074"},
28
+ // Red scale (error)
29
+ red: {
30
+ 50: "#FEF2F2",
31
+ 400: "#DA6868",
32
+ // Error light
33
+ 500: "#EF4444",
34
+ 600: "#D14343",
35
+ // Error main
36
+ 700: "#922E2E"},
37
+ // Amber scale (warning)
38
+ amber: {
39
+ 50: "#FFFBEB",
40
+ 400: "#FFBF4C",
41
+ // Warning light
42
+ 500: "#FFB020",
43
+ // Warning main
44
+ 600: "#B27B16"},
45
+ // Sky/Blue scale (info)
46
+ sky: {
47
+ 50: "#F0F9FF",
48
+ 400: "#64B6F7",
49
+ // Info light
50
+ 500: "#2196F3",
51
+ 700: "#0B79D0"},
52
+ // Neutral/Gray scale
53
+ neutral: {
54
+ 50: "#FAFAFA",
55
+ 100: "#F3F4F6",
56
+ 300: "#D1D5DB",
57
+ 400: "#9CA3AF",
58
+ 500: "#6B7280",
59
+ 600: "#4B5563",
60
+ 900: "#111827"},
61
+ // Orange scale (accent/brand color)
62
+ accent: {
63
+ 200: "#FF9630",
64
+ 300: "#FF8500",
65
+ 400: "#FF7900",
66
+ 500: "#F56C00",
67
+ 600: "#E06D10",
68
+ 700: "#D0620C"},
69
+ // Charcoal scale (dark backgrounds)
70
+ charcoal: {
71
+ 300: "#2C2C2C",
72
+ 400: "#1F1F1F",
73
+ 500: "#1C1C1C",
74
+ 600: "#191919",
75
+ 700: "#161616",
76
+ 900: "#101010"
77
+ },
78
+ // Steel scale (cool accent)
79
+ steel: {
80
+ 300: "#678498",
81
+ 400: "#557488",
82
+ 500: "#406D87",
83
+ 600: "#39617A",
84
+ 700: "#32556D"},
85
+ // Pure colors
86
+ white: "#FFFFFF"};
87
+ var discreteRainbow = [
88
+ "#E8ECFB",
89
+ "#D9CCE3",
90
+ "#D1BBD7",
91
+ "#CAACCB",
92
+ "#BA8DB4",
93
+ "#AE76A3",
94
+ "#AA6F9E",
95
+ "#994F88",
96
+ "#882E72",
97
+ "#1965B0",
98
+ "#437DBF",
99
+ "#5289C7",
100
+ "#6195CF",
101
+ "#7BAFDE",
102
+ "#4EB265",
103
+ "#90C987",
104
+ "#CAE0AB",
105
+ "#F7F056",
106
+ "#F7CB45",
107
+ "#F6C141",
108
+ "#F4A736",
109
+ "#F1932D",
110
+ "#EE8026",
111
+ "#E8601C",
112
+ "#E65518",
113
+ "#DC050C",
114
+ "#A5170E",
115
+ "#72190E",
116
+ "#42150A"
117
+ ];
118
+
119
+ // src/theme/tokens/semantic.ts
120
+ var semanticColorsLight = {
121
+ // Brand colors (brand-*)
122
+ "brand-primary": primitiveColors.accent[400],
123
+ // #FF7900
124
+ "brand-primary-light": primitiveColors.accent[200],
125
+ // #FF9630
126
+ "brand-primary-dark": primitiveColors.accent[700],
127
+ // #D0620C
128
+ "brand-primary-subtle": "rgba(255, 121, 0, 0.08)",
129
+ "brand-primary-hover": primitiveColors.accent[500],
130
+ "brand-primary-active": primitiveColors.accent[600],
131
+ "brand-secondary": primitiveColors.steel[500],
132
+ // #406D87
133
+ "brand-secondary-light": primitiveColors.steel[300],
134
+ // #678498
135
+ "brand-secondary-dark": primitiveColors.steel[700],
136
+ // #32556D
137
+ "brand-secondary-subtle": "rgba(64, 109, 135, 0.08)",
138
+ "brand-secondary-hover": primitiveColors.steel[600],
139
+ "brand-secondary-active": primitiveColors.steel[700],
140
+ // Text on brand backgrounds (on-*)
141
+ "on-brand-primary": primitiveColors.white,
142
+ "on-brand-secondary": primitiveColors.white,
143
+ // Status colors (status-*)
144
+ "status-success": primitiveColors.teal[500],
145
+ // #14B8A6
146
+ "status-success-light": primitiveColors.teal[400],
147
+ // #43C6B7
148
+ "status-success-dark": primitiveColors.teal[700],
149
+ // #0E8074
150
+ "status-success-subtle": primitiveColors.teal[50],
151
+ "status-error": primitiveColors.red[600],
152
+ // #D14343
153
+ "status-error-light": primitiveColors.red[400],
154
+ // #DA6868
155
+ "status-error-dark": primitiveColors.red[700],
156
+ // #922E2E
157
+ "status-error-subtle": primitiveColors.red[50],
158
+ "status-warning": primitiveColors.amber[500],
159
+ // #FFB020
160
+ "status-warning-light": primitiveColors.amber[400],
161
+ // #FFBF4C
162
+ "status-warning-dark": primitiveColors.amber[600],
163
+ // #B27B16
164
+ "status-warning-subtle": primitiveColors.amber[50],
165
+ "status-info": primitiveColors.sky[500],
166
+ // #2196F3
167
+ "status-info-light": primitiveColors.sky[400],
168
+ // #64B6F7
169
+ "status-info-dark": primitiveColors.sky[700],
170
+ // #0B79D0
171
+ "status-info-subtle": primitiveColors.sky[50],
172
+ // Text on status backgrounds (on-status-*)
173
+ "on-status-success": primitiveColors.white,
174
+ "on-status-error": primitiveColors.white,
175
+ "on-status-warning": primitiveColors.white,
176
+ "on-status-info": primitiveColors.white,
177
+ // Result/outcome indicators (result-*)
178
+ "result-improve": "#4caf50",
179
+ // Green - positive outcome
180
+ "result-improve-light": "rgba(76, 175, 80, 0.12)",
181
+ "result-improve-dark": "#248a24",
182
+ "result-degrade": "#ef5350",
183
+ // Red - negative outcome
184
+ "result-degrade-light": "rgba(239, 83, 80, 0.12)",
185
+ "result-degrade-dark": "#b30000",
186
+ "result-inconclusive": "#9E9A97",
187
+ // Gray - no clear result
188
+ "result-inconclusive-light": "rgba(158, 154, 151, 0.12)",
189
+ "result-neutral": primitiveColors.neutral[500],
190
+ // Neutral baseline
191
+ // Text on result backgrounds (on-result-*)
192
+ "on-result-improve": primitiveColors.white,
193
+ "on-result-degrade": primitiveColors.white,
194
+ "on-result-inconclusive": primitiveColors.white,
195
+ // Data visualization colors (data-*)
196
+ // First 10 colors from discrete rainbow optimized for charts
197
+ "data-1": discreteRainbow[9],
198
+ // #1965B0 - Blue
199
+ "data-2": discreteRainbow[14],
200
+ // #4EB265 - Green
201
+ "data-3": discreteRainbow[17],
202
+ // #F7F056 - Yellow
203
+ "data-4": discreteRainbow[25],
204
+ // #DC050C - Red
205
+ "data-5": discreteRainbow[8],
206
+ // #882E72 - Purple
207
+ "data-6": discreteRainbow[20],
208
+ // #F4A736 - Orange
209
+ "data-7": discreteRainbow[13],
210
+ // #7BAFDE - Light Blue
211
+ "data-8": discreteRainbow[15],
212
+ // #90C987 - Light Green
213
+ "data-9": discreteRainbow[3],
214
+ // #CAACCB - Lavender
215
+ "data-10": discreteRainbow[22],
216
+ // #EE8026 - Dark Orange
217
+ // Text colors (text-*)
218
+ "text-primary": "#121828",
219
+ "text-secondary": "#65748B",
220
+ "text-tertiary": primitiveColors.neutral[400],
221
+ "text-disabled": "rgba(55, 65, 81, 0.48)",
222
+ "text-inverse": primitiveColors.white,
223
+ "text-link": primitiveColors.blue[600],
224
+ "text-link-hover": primitiveColors.blue[700],
225
+ // Surface colors (surface-*) - for elevated containers
226
+ "surface-base": primitiveColors.white,
227
+ "surface-elevated": primitiveColors.neutral[50],
228
+ // #FAFAFA - slightly off-white for elevated cards
229
+ "surface-raised": primitiveColors.neutral[100],
230
+ // #F3F4F6 - light gray for raised cards
231
+ "surface-overlay": primitiveColors.white,
232
+ "surface-input": primitiveColors.neutral[50],
233
+ // Input field background (filled variant)
234
+ // Background colors (background-*)
235
+ "background-base": "#EBEBEB",
236
+ "background-default": primitiveColors.white,
237
+ "background-subtle": primitiveColors.neutral[50],
238
+ // Border colors (border-*)
239
+ "border-default": "#E8E9EB",
240
+ "border-subtle": primitiveColors.neutral[100],
241
+ "border-strong": primitiveColors.neutral[300],
242
+ "border-focus": primitiveColors.blue[600],
243
+ "border-input": primitiveColors.neutral[300],
244
+ // Input field border
245
+ "border-input-hover": primitiveColors.neutral[400],
246
+ // Input field border on hover
247
+ "border-input-focus": primitiveColors.blue[600],
248
+ // Input field border on focus
249
+ "border-input-error": primitiveColors.red[600],
250
+ // Input field border on error
251
+ // Interactive states (interactive-*)
252
+ "interactive-hover": "rgba(55, 65, 81, 0.04)",
253
+ "interactive-focus": "rgba(55, 65, 81, 0.12)",
254
+ "interactive-active": "rgba(55, 65, 81, 0.16)",
255
+ "interactive-selected": "rgba(55, 65, 81, 0.08)",
256
+ "interactive-disabled": "rgba(55, 65, 81, 0.12)",
257
+ "interactive-disabled-text": "rgba(55, 65, 81, 0.26)",
258
+ // Divider
259
+ "divider": "#E8E9EB",
260
+ // Avatar default
261
+ "avatar-background": primitiveColors.neutral[500],
262
+ "avatar-text": primitiveColors.white
263
+ };
264
+ var semanticColorsDark = {
265
+ // Brand colors stay the same in dark mode
266
+ "brand-primary": primitiveColors.accent[400],
267
+ "brand-primary-light": primitiveColors.accent[200],
268
+ "brand-primary-dark": primitiveColors.accent[700],
269
+ "brand-primary-subtle": "rgba(255, 121, 0, 0.12)",
270
+ "brand-primary-hover": primitiveColors.accent[300],
271
+ "brand-primary-active": primitiveColors.accent[200],
272
+ "brand-secondary": primitiveColors.steel[500],
273
+ "brand-secondary-light": primitiveColors.steel[300],
274
+ "brand-secondary-dark": primitiveColors.steel[700],
275
+ "brand-secondary-subtle": "rgba(64, 109, 135, 0.12)",
276
+ "brand-secondary-hover": primitiveColors.steel[400],
277
+ "brand-secondary-active": primitiveColors.steel[300],
278
+ // Text on brand backgrounds
279
+ "on-brand-primary": primitiveColors.white,
280
+ "on-brand-secondary": primitiveColors.white,
281
+ // Status colors
282
+ "status-success": primitiveColors.teal[500],
283
+ "status-success-light": primitiveColors.teal[400],
284
+ "status-success-dark": primitiveColors.teal[700],
285
+ "status-success-subtle": "rgba(20, 184, 166, 0.12)",
286
+ "status-error": primitiveColors.red[600],
287
+ "status-error-light": primitiveColors.red[400],
288
+ "status-error-dark": primitiveColors.red[700],
289
+ "status-error-subtle": "rgba(209, 67, 67, 0.12)",
290
+ "status-warning": primitiveColors.amber[500],
291
+ "status-warning-light": primitiveColors.amber[400],
292
+ "status-warning-dark": primitiveColors.amber[600],
293
+ "status-warning-subtle": "rgba(255, 176, 32, 0.12)",
294
+ "status-info": primitiveColors.sky[500],
295
+ "status-info-light": primitiveColors.sky[400],
296
+ "status-info-dark": primitiveColors.sky[700],
297
+ "status-info-subtle": "rgba(33, 150, 243, 0.12)",
298
+ // Text on status backgrounds
299
+ "on-status-success": primitiveColors.white,
300
+ "on-status-error": primitiveColors.white,
301
+ "on-status-warning": primitiveColors.white,
302
+ "on-status-info": primitiveColors.white,
303
+ // Result/outcome indicators (result-*)
304
+ "result-improve": "#4caf50",
305
+ "result-improve-light": "rgba(76, 175, 80, 0.16)",
306
+ "result-improve-dark": "#248a24",
307
+ "result-degrade": "#ef5350",
308
+ "result-degrade-light": "rgba(239, 83, 80, 0.16)",
309
+ "result-degrade-dark": "#b30000",
310
+ "result-inconclusive": "#9E9A97",
311
+ "result-inconclusive-light": "rgba(158, 154, 151, 0.16)",
312
+ "result-neutral": primitiveColors.neutral[400],
313
+ // Text on result backgrounds
314
+ "on-result-improve": primitiveColors.white,
315
+ "on-result-degrade": primitiveColors.white,
316
+ "on-result-inconclusive": primitiveColors.white,
317
+ // Data visualization colors (same in dark mode for consistency)
318
+ "data-1": discreteRainbow[9],
319
+ "data-2": discreteRainbow[14],
320
+ "data-3": discreteRainbow[17],
321
+ "data-4": discreteRainbow[25],
322
+ "data-5": discreteRainbow[8],
323
+ "data-6": discreteRainbow[20],
324
+ "data-7": discreteRainbow[13],
325
+ "data-8": discreteRainbow[15],
326
+ "data-9": discreteRainbow[3],
327
+ "data-10": discreteRainbow[22],
328
+ // Text colors - inverted for dark mode
329
+ "text-primary": primitiveColors.neutral[100],
330
+ "text-secondary": primitiveColors.neutral[400],
331
+ "text-tertiary": primitiveColors.neutral[500],
332
+ "text-disabled": "rgba(255, 255, 255, 0.38)",
333
+ "text-inverse": primitiveColors.neutral[900],
334
+ "text-link": "#828DF8",
335
+ "text-link-hover": primitiveColors.blue[400],
336
+ // Surface colors - dark backgrounds
337
+ "surface-base": primitiveColors.charcoal[700],
338
+ // #161616 - main surface
339
+ "surface-elevated": primitiveColors.charcoal[600],
340
+ // #191919 - elevated surface
341
+ "surface-raised": primitiveColors.charcoal[500],
342
+ // #1C1C1C - raised surface
343
+ "surface-overlay": primitiveColors.charcoal[600],
344
+ // #191919 - overlay surface
345
+ "surface-input": primitiveColors.charcoal[600],
346
+ // #191919 - input surface
347
+ // Background colors
348
+ "background-base": primitiveColors.charcoal[900],
349
+ // #101010 - darkest charcoal
350
+ "background-default": primitiveColors.charcoal[700],
351
+ // #161616 - main background
352
+ "background-subtle": primitiveColors.charcoal[500],
353
+ // #1C1C1C - subtle background
354
+ // Border colors
355
+ "border-default": primitiveColors.charcoal[400],
356
+ // #1F1F1F - default border
357
+ "border-subtle": primitiveColors.charcoal[500],
358
+ // #1C1C1C - subtle border
359
+ "border-strong": primitiveColors.charcoal[300],
360
+ // #2C2C2C - strong border
361
+ "border-focus": "#828DF8",
362
+ "border-input": primitiveColors.neutral[600],
363
+ "border-input-hover": primitiveColors.neutral[500],
364
+ "border-input-focus": "#828DF8",
365
+ "border-input-error": primitiveColors.red[500],
366
+ // Interactive states
367
+ "interactive-hover": "rgba(255, 255, 255, 0.04)",
368
+ "interactive-focus": "rgba(255, 255, 255, 0.12)",
369
+ "interactive-active": "rgba(255, 255, 255, 0.16)",
370
+ "interactive-selected": "rgba(255, 255, 255, 0.08)",
371
+ "interactive-disabled": "rgba(255, 255, 255, 0.12)",
372
+ "interactive-disabled-text": "rgba(255, 255, 255, 0.26)",
373
+ // Divider
374
+ "divider": primitiveColors.charcoal[400],
375
+ // #1F1F1F - divider color
376
+ // Avatar default
377
+ "avatar-background": primitiveColors.neutral[600],
378
+ "avatar-text": primitiveColors.white
379
+ };
380
+ function getSemanticColors(mode) {
381
+ return mode === "dark" ? semanticColorsDark : semanticColorsLight;
382
+ }
383
+
384
+ // src/theme/resolve-color.ts
385
+ function resolveColor(token, mode = "dark") {
386
+ return Platform.OS === "web" ? `var(--color-${token})` : getSemanticColors(mode)[token];
387
+ }
388
+
389
+ // src/theme/workout-tokens.ts
390
+ var WORKOUT_TOKENS = {
391
+ // BodyMap volume heatmap scale (drive dynamic SVG fills, so inline values).
392
+ // Maps weekly-volume status against MEV/MAV/MRV landmarks to a fill color.
393
+ heatmap: {
394
+ none: "#E0E0E0",
395
+ // gray — no training data
396
+ under: "#4A90D9",
397
+ // cool blue — below MEV
398
+ maintenance: "#F5C842",
399
+ // warm yellow — MEV to MAV
400
+ productive: "#4CAF50",
401
+ // green — MAV to MRV
402
+ approaching: "#FFA502",
403
+ // orange — near MRV
404
+ over: "#FF6B35"
405
+ // red-orange — over MRV
406
+ }};
7
407
 
8
408
  // src/components/custom/Workout/muscleTaxonomy.ts
9
409
  var MuscleGroup = /* @__PURE__ */ ((MuscleGroup5) => {
@@ -188,14 +588,29 @@ var SLUG_TO_PRIMARY_MUSCLE = {
188
588
  abs: "abs" /* ABS */,
189
589
  obliques: "obliques" /* OBLIQUES */
190
590
  };
591
+ function wrapJsx(fn) {
592
+ return function(type, props, ...rest) {
593
+ if (props && typeof props.className === "string" && props.className) {
594
+ const cn2 = props.className;
595
+ const cssStyle = { $$css: true, [cn2]: cn2 };
596
+ const existing = props.style;
597
+ props = {
598
+ ...props,
599
+ style: existing ? [cssStyle, existing] : cssStyle
600
+ };
601
+ delete props.className;
602
+ }
603
+ return fn(type, props, ...rest);
604
+ };
605
+ }
606
+ var jsx = wrapJsx(jsx$1);
607
+ var jsxs = wrapJsx(jsxs$1);
191
608
 
192
609
  // src/components/custom/Workout/BodyMap.tsx
193
610
  var Body = BodyHighlighter.default ?? BodyHighlighter;
194
611
  var OUTLINE_FILL = "rgba(255,255,255,0.08)";
195
612
  var OUTLINE_BORDER = "rgba(255,255,255,0.12)";
196
613
  var BODY_SCALE = 0.8;
197
- var TEXT_PRIMARY = "var(--color-text-primary)";
198
- var TEXT_SECONDARY = "var(--color-text-secondary)";
199
614
  function buildSlugParts(data) {
200
615
  const bySlug = /* @__PURE__ */ new Map();
201
616
  for (const d of data) {
@@ -319,10 +734,10 @@ function BodyMap({
319
734
  legend.length === 0 ? /* @__PURE__ */ jsx(
320
735
  Text,
321
736
  {
737
+ className: "text-text-secondary",
322
738
  style: {
323
739
  marginTop: 8,
324
740
  fontSize: 12,
325
- color: TEXT_SECONDARY,
326
741
  textAlign: "center",
327
742
  fontFamily: "Inter, sans-serif"
328
743
  },
@@ -371,7 +786,7 @@ function ViewToggle({ view, onViewChange }) {
371
786
  borderRadius: 9999,
372
787
  backgroundColor: active ? "rgba(255,121,0,0.16)" : "transparent",
373
788
  borderWidth: 1,
374
- borderColor: active ? "#FF7900" : "var(--color-border-strong)"
789
+ borderColor: active ? "#FF7900" : resolveColor("border-strong")
375
790
  },
376
791
  testID: `body-map-toggle-${side}`,
377
792
  children: /* @__PURE__ */ jsx(
@@ -381,7 +796,7 @@ function ViewToggle({ view, onViewChange }) {
381
796
  fontSize: 12,
382
797
  fontFamily: "Inter, sans-serif",
383
798
  fontWeight: active ? "700" : "500",
384
- color: active ? "#FF7900" : TEXT_SECONDARY,
799
+ color: active ? "#FF7900" : resolveColor("text-secondary"),
385
800
  textTransform: "capitalize"
386
801
  },
387
802
  children: side
@@ -404,6 +819,7 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
404
819
  accessibilityRole: "button",
405
820
  accessibilityLabel: label,
406
821
  "aria-pressed": highlighted,
822
+ className: "bg-surface-raised",
407
823
  style: {
408
824
  flexDirection: "row",
409
825
  alignItems: "center",
@@ -412,8 +828,7 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
412
828
  paddingVertical: 3,
413
829
  borderRadius: 9999,
414
830
  borderWidth: 1,
415
- borderColor: highlighted ? "#FF7900" : "var(--color-border-default)",
416
- backgroundColor: "var(--color-surface-raised)"
831
+ borderColor: highlighted ? "#FF7900" : resolveColor("border-default")
417
832
  },
418
833
  testID: `body-map-muscle-${entry.key}`,
419
834
  children: [
@@ -428,11 +843,11 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
428
843
  /* @__PURE__ */ jsx(
429
844
  Text,
430
845
  {
846
+ className: "text-text-primary",
431
847
  style: {
432
848
  fontSize: 11,
433
849
  fontFamily: "Inter, sans-serif",
434
- fontWeight: "500",
435
- color: TEXT_PRIMARY
850
+ fontWeight: "500"
436
851
  },
437
852
  accessibilityElementsHidden: true,
438
853
  children: entry.name
@@ -442,14 +857,279 @@ function MuscleButton({ entry, highlighted, onMusclePress }) {
442
857
  }
443
858
  );
444
859
  }
445
- var SURFACE_ELEVATED = "var(--color-surface-elevated)";
446
- var SURFACE_RAISED = "var(--color-surface-raised)";
447
- var BORDER_STRONG = "var(--color-border-strong)";
448
- var BORDER_DEFAULT = "var(--color-border-default)";
860
+ var sizeStyles = {
861
+ xs: "w-1 h-1",
862
+ sm: "w-1.5 h-1.5",
863
+ md: "w-2 h-2",
864
+ lg: "w-2.5 h-2.5"
865
+ };
866
+ var colorStyles = {
867
+ default: "bg-text-tertiary",
868
+ primary: "bg-brand-primary",
869
+ success: "bg-status-success",
870
+ error: "bg-status-error",
871
+ warning: "bg-status-warning",
872
+ info: "bg-status-info"
873
+ };
874
+ function Indicator({
875
+ size = "sm",
876
+ color = "default",
877
+ customColor,
878
+ glow = false,
879
+ ring = false,
880
+ className,
881
+ style,
882
+ ...props
883
+ }) {
884
+ const dynamicStyle = {
885
+ ...typeof style === "object" ? style : {},
886
+ ...customColor ? { backgroundColor: customColor } : {},
887
+ ...glow && !customColor ? {} : {},
888
+ ...glow && customColor ? { boxShadow: `0 0 6px ${customColor}` } : {}
889
+ };
890
+ return /* @__PURE__ */ jsx(
891
+ View,
892
+ {
893
+ className: cn(
894
+ "rounded-full shrink-0",
895
+ sizeStyles[size],
896
+ !customColor && colorStyles[color],
897
+ ring && "border-2 border-background-base",
898
+ glow && !customColor && color === "success" && "shadow-[0_0_6px_rgba(20,184,166,0.6)]",
899
+ glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
900
+ glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
901
+ glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
902
+ className
903
+ ),
904
+ style: Object.keys(dynamicStyle).length > 0 ? dynamicStyle : style,
905
+ ...props
906
+ }
907
+ );
908
+ }
909
+
910
+ // src/components/ui/badge/Badge.tsx
911
+ var variantColorStyles = {
912
+ solid: {
913
+ default: "bg-border-strong text-text-inverse",
914
+ primary: "bg-brand-primary text-text-inverse",
915
+ secondary: "bg-brand-secondary text-text-inverse",
916
+ success: "bg-status-success text-text-inverse",
917
+ error: "bg-status-error text-text-inverse",
918
+ warning: "bg-status-warning text-text-inverse",
919
+ info: "bg-status-info text-text-inverse"
920
+ },
921
+ subtle: {
922
+ default: "bg-surface-raised text-text-secondary",
923
+ primary: "bg-brand-primary-subtle text-brand-primary",
924
+ secondary: "bg-brand-secondary-subtle text-brand-secondary",
925
+ success: "bg-status-success-subtle text-status-success",
926
+ error: "bg-status-error-subtle text-status-error",
927
+ warning: "bg-status-warning-subtle text-status-warning",
928
+ info: "bg-status-info-subtle text-status-info"
929
+ },
930
+ outline: {
931
+ default: "border border-border-strong text-text-secondary",
932
+ primary: "border border-brand-primary text-brand-primary",
933
+ secondary: "border border-brand-secondary text-brand-secondary",
934
+ success: "border border-status-success text-status-success",
935
+ error: "border border-status-error text-status-error",
936
+ warning: "border border-status-warning text-status-warning",
937
+ info: "border border-status-info text-status-info"
938
+ }
939
+ };
940
+ var sizeStyles2 = {
941
+ sm: "px-1.5 py-0.5 text-xs",
942
+ md: "px-2 py-0.5 text-xs",
943
+ lg: "px-2.5 py-1 text-sm"
944
+ };
945
+ function Badge({
946
+ variant = "subtle",
947
+ color = "default",
948
+ size = "md",
949
+ dot,
950
+ dotColor,
951
+ className,
952
+ children,
953
+ ...props
954
+ }) {
955
+ return /* @__PURE__ */ jsxs(
956
+ View,
957
+ {
958
+ className: cn(
959
+ "inline-flex items-center justify-center rounded-full font-medium",
960
+ variantColorStyles[variant][color],
961
+ sizeStyles2[size],
962
+ className
963
+ ),
964
+ ...props,
965
+ children: [
966
+ dot && /* @__PURE__ */ jsx(
967
+ Indicator,
968
+ {
969
+ size: "xs",
970
+ color: dotColor ?? (color === "default" || color === "secondary" ? "default" : color),
971
+ className: "mr-0.5"
972
+ }
973
+ ),
974
+ typeof children === "string" ? /* @__PURE__ */ jsx(Text, { className: "text-inherit font-medium", children }) : children
975
+ ]
976
+ }
977
+ );
978
+ }
449
979
  var BRAND_PRIMARY = "#FF7900";
450
- var TEXT_PRIMARY2 = "var(--color-text-primary)";
451
- var TEXT_SECONDARY2 = "var(--color-text-secondary)";
452
- var TEXT_TERTIARY = "var(--color-text-tertiary)";
980
+ function normalizeData(data, height) {
981
+ if (data.length === 0) return [];
982
+ const min = Math.min(...data);
983
+ const max = Math.max(...data);
984
+ const range = max - min || 1;
985
+ return data.map((v) => height - (v - min) / range * height);
986
+ }
987
+ function normalizeValue(value, data, height) {
988
+ const min = Math.min(...data);
989
+ const max = Math.max(...data);
990
+ const range = max - min || 1;
991
+ return height - (value - min) / range * height;
992
+ }
993
+ function Sparkline({
994
+ data,
995
+ width = 80,
996
+ height = 30,
997
+ color,
998
+ showDots = false,
999
+ referenceLines,
1000
+ highlightLast = false,
1001
+ className,
1002
+ ...props
1003
+ }) {
1004
+ if (data.length === 0) {
1005
+ return /* @__PURE__ */ jsx(
1006
+ View,
1007
+ {
1008
+ style: { width, height },
1009
+ className,
1010
+ testID: "sparkline-empty",
1011
+ accessibilityLabel: "Sparkline chart, no data",
1012
+ ...props
1013
+ }
1014
+ );
1015
+ }
1016
+ const resolvedColor = color ?? BRAND_PRIMARY;
1017
+ const normalized = normalizeData(data, height);
1018
+ const stepX = data.length > 1 ? width / (data.length - 1) : 0;
1019
+ const dotSize = 3;
1020
+ const highlightSize = 6;
1021
+ return /* @__PURE__ */ jsxs(
1022
+ View,
1023
+ {
1024
+ style: { width, height, position: "relative" },
1025
+ className: cn(className),
1026
+ accessibilityRole: "image",
1027
+ accessibilityLabel: `Sparkline chart with ${data.length} data points`,
1028
+ testID: "sparkline",
1029
+ ...props,
1030
+ children: [
1031
+ referenceLines?.map((line, i) => {
1032
+ const y = normalizeValue(line.value, data, height);
1033
+ return /* @__PURE__ */ jsx(
1034
+ View,
1035
+ {
1036
+ style: [
1037
+ {
1038
+ position: "absolute",
1039
+ top: y,
1040
+ left: 0,
1041
+ right: 0,
1042
+ opacity: 0.6
1043
+ },
1044
+ line.dashed ? {
1045
+ height: 0,
1046
+ borderStyle: "dashed",
1047
+ borderTopWidth: 1,
1048
+ borderTopColor: line.color
1049
+ } : {
1050
+ height: 1,
1051
+ backgroundColor: line.color
1052
+ }
1053
+ ],
1054
+ accessibilityElementsHidden: true,
1055
+ testID: `sparkline-reference-${i}`,
1056
+ children: line.label && /* @__PURE__ */ jsx(
1057
+ Text,
1058
+ {
1059
+ style: {
1060
+ position: "absolute",
1061
+ right: 0,
1062
+ top: -10,
1063
+ fontSize: 7,
1064
+ color: line.color,
1065
+ opacity: 1
1066
+ },
1067
+ testID: `sparkline-reference-label-${i}`,
1068
+ children: line.label
1069
+ }
1070
+ )
1071
+ },
1072
+ `ref-${i}`
1073
+ );
1074
+ }),
1075
+ normalized.map((y, i) => {
1076
+ if (i === 0) return null;
1077
+ const prevY = normalized[i - 1];
1078
+ const x1 = (i - 1) * stepX;
1079
+ const x2 = i * stepX;
1080
+ const dx = x2 - x1;
1081
+ const dy = y - prevY;
1082
+ const length = Math.sqrt(dx * dx + dy * dy);
1083
+ const angle = Math.atan2(dy, dx) * (180 / Math.PI);
1084
+ return /* @__PURE__ */ jsx(
1085
+ View,
1086
+ {
1087
+ style: {
1088
+ position: "absolute",
1089
+ left: x1,
1090
+ top: prevY,
1091
+ width: length,
1092
+ height: 1.5,
1093
+ backgroundColor: resolvedColor,
1094
+ transformOrigin: "0 0",
1095
+ transform: [{ rotate: `${angle}deg` }]
1096
+ },
1097
+ accessibilityElementsHidden: true,
1098
+ testID: `sparkline-segment-${i}`
1099
+ },
1100
+ `line-${i}`
1101
+ );
1102
+ }),
1103
+ (showDots || highlightLast) && normalized.map((y, i) => {
1104
+ const isLast = i === data.length - 1;
1105
+ const shouldShow = showDots || highlightLast && isLast;
1106
+ if (!shouldShow) return null;
1107
+ const size = highlightLast && isLast ? highlightSize : dotSize;
1108
+ return /* @__PURE__ */ jsx(
1109
+ View,
1110
+ {
1111
+ style: {
1112
+ position: "absolute",
1113
+ left: i * stepX - size / 2,
1114
+ top: y - size / 2,
1115
+ width: size,
1116
+ height: size,
1117
+ borderRadius: size / 2,
1118
+ backgroundColor: resolvedColor
1119
+ },
1120
+ accessibilityElementsHidden: true,
1121
+ testID: `sparkline-dot-${i}`
1122
+ },
1123
+ `dot-${i}`
1124
+ );
1125
+ })
1126
+ ]
1127
+ }
1128
+ );
1129
+ }
1130
+
1131
+ // src/components/custom/Workout/BodyMapDetailPanel.tsx
1132
+ var BRAND_PRIMARY2 = "#FF7900";
453
1133
  var VOLUME_GRADIENT = "linear-gradient(90deg, #2196F3 0%, #14B8A6 50%, #D14343 100%)";
454
1134
  var SLIDE_OFFSET = 400;
455
1135
  var BACKDROP_OPACITY = 0.4;
@@ -549,8 +1229,8 @@ function BodyMapDetailPanel({
549
1229
  accessibilityRole: "dialog",
550
1230
  accessibilityLabel: dialogLabel,
551
1231
  "aria-label": dialogLabel,
1232
+ className: "bg-surface-elevated",
552
1233
  style: {
553
- backgroundColor: SURFACE_ELEVATED,
554
1234
  borderTopLeftRadius: 16,
555
1235
  borderTopRightRadius: 16,
556
1236
  maxHeight: "88%",
@@ -571,7 +1251,8 @@ function BodyMapDetailPanel({
571
1251
  children: /* @__PURE__ */ jsx(
572
1252
  View,
573
1253
  {
574
- style: { width: 40, height: 4, borderRadius: 2, backgroundColor: BORDER_STRONG },
1254
+ className: "bg-border-strong",
1255
+ style: { width: 40, height: 4, borderRadius: 2 },
575
1256
  accessibilityElementsHidden: true
576
1257
  }
577
1258
  )
@@ -596,11 +1277,11 @@ function BodyMapDetailPanel({
596
1277
  Text,
597
1278
  {
598
1279
  accessibilityRole: "header",
1280
+ className: "text-text-primary",
599
1281
  style: {
600
1282
  fontSize: 16,
601
1283
  fontFamily: '"Space Grotesk", sans-serif',
602
- fontWeight: "700",
603
- color: TEXT_PRIMARY2
1284
+ fontWeight: "700"
604
1285
  },
605
1286
  testID: "body-map-detail-panel-title",
606
1287
  children: displayName
@@ -626,7 +1307,7 @@ function BodyMapDetailPanel({
626
1307
  hitSlop: 8,
627
1308
  style: { padding: 4, margin: -4 },
628
1309
  testID: "body-map-detail-panel-close",
629
- children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 22, lineHeight: 22, color: TEXT_SECONDARY2 }, children: "\xD7" })
1310
+ children: /* @__PURE__ */ jsx(Text, { className: "text-text-secondary", style: { fontSize: 22, lineHeight: 22 }, children: "\xD7" })
630
1311
  }
631
1312
  )
632
1313
  ]
@@ -635,7 +1316,8 @@ function BodyMapDetailPanel({
635
1316
  lastTrained != null && /* @__PURE__ */ jsx(
636
1317
  Text,
637
1318
  {
638
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY2 },
1319
+ className: "text-text-secondary",
1320
+ style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
639
1321
  testID: "body-map-detail-panel-last-trained",
640
1322
  children: `Last trained ${lastTrained}`
641
1323
  }
@@ -648,8 +1330,8 @@ function BodyMapDetailPanel({
648
1330
  style: { marginBottom: 6 },
649
1331
  accessibilityElementsHidden: true,
650
1332
  children: [
651
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_TERTIARY }, children: `MEV ${landmarks.mev}` }),
652
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_TERTIARY }, children: `MRV ${landmarks.mrv}` })
1333
+ /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary", style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" }, children: `MEV ${landmarks.mev}` }),
1334
+ /* @__PURE__ */ jsx(Text, { className: "text-text-tertiary", style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600" }, children: `MRV ${landmarks.mrv}` })
653
1335
  ]
654
1336
  }
655
1337
  ),
@@ -675,6 +1357,7 @@ function BodyMapDetailPanel({
675
1357
  /* @__PURE__ */ jsx(
676
1358
  View,
677
1359
  {
1360
+ className: "border-text-primary bg-surface-elevated",
678
1361
  style: {
679
1362
  position: "absolute",
680
1363
  left: `${markerLeft}%`,
@@ -683,8 +1366,6 @@ function BodyMapDetailPanel({
683
1366
  height: 14,
684
1367
  borderRadius: 7,
685
1368
  borderWidth: 2,
686
- borderColor: TEXT_PRIMARY2,
687
- backgroundColor: SURFACE_ELEVATED,
688
1369
  boxShadow: "0 0 4px rgba(0,0,0,0.5)"
689
1370
  },
690
1371
  accessibilityElementsHidden: true,
@@ -699,11 +1380,11 @@ function BodyMapDetailPanel({
699
1380
  /* @__PURE__ */ jsx(
700
1381
  Text,
701
1382
  {
1383
+ className: "text-text-primary",
702
1384
  style: {
703
1385
  fontSize: 24,
704
1386
  fontFamily: '"Space Grotesk", sans-serif',
705
- fontWeight: "700",
706
- color: TEXT_PRIMARY2
1387
+ fontWeight: "700"
707
1388
  },
708
1389
  testID: "body-map-detail-panel-set-count",
709
1390
  children: weeklySets
@@ -712,7 +1393,8 @@ function BodyMapDetailPanel({
712
1393
  /* @__PURE__ */ jsx(
713
1394
  Text,
714
1395
  {
715
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY2 },
1396
+ className: "text-text-secondary",
1397
+ style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
716
1398
  testID: "body-map-detail-panel-mrv-suffix",
717
1399
  children: `/ ${landmarks.mrv} MRV`
718
1400
  }
@@ -722,11 +1404,11 @@ function BodyMapDetailPanel({
722
1404
  /* @__PURE__ */ jsx(
723
1405
  Text,
724
1406
  {
1407
+ className: "text-text-tertiary",
725
1408
  style: {
726
1409
  fontSize: 10,
727
1410
  fontFamily: "Inter, sans-serif",
728
1411
  fontWeight: "600",
729
- color: TEXT_TERTIARY,
730
1412
  marginBottom: 6
731
1413
  },
732
1414
  accessibilityElementsHidden: true,
@@ -739,11 +1421,11 @@ function BodyMapDetailPanel({
739
1421
  /* @__PURE__ */ jsx(
740
1422
  Text,
741
1423
  {
1424
+ className: "text-text-tertiary",
742
1425
  style: {
743
1426
  fontSize: 10,
744
1427
  fontFamily: "Inter, sans-serif",
745
1428
  fontWeight: "600",
746
- color: TEXT_TERTIARY,
747
1429
  marginBottom: 8
748
1430
  },
749
1431
  children: "CONTRIBUTING EXERCISES"
@@ -752,23 +1434,22 @@ function BodyMapDetailPanel({
752
1434
  contributingExercises.map((exercise, index) => /* @__PURE__ */ jsxs(
753
1435
  View,
754
1436
  {
755
- className: "flex-row items-center justify-between",
1437
+ className: "flex-row items-center justify-between bg-surface-raised border-border",
756
1438
  style: {
757
1439
  gap: 10,
758
1440
  paddingVertical: 8,
759
1441
  paddingHorizontal: 12,
760
1442
  marginBottom: 6,
761
1443
  borderRadius: 8,
762
- backgroundColor: SURFACE_RAISED,
763
- borderWidth: 1,
764
- borderColor: BORDER_DEFAULT
1444
+ borderWidth: 1
765
1445
  },
766
1446
  testID: `body-map-detail-panel-contributing-${index}`,
767
1447
  children: [
768
1448
  /* @__PURE__ */ jsx(
769
1449
  Text,
770
1450
  {
771
- style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_PRIMARY2 },
1451
+ className: "text-text-primary",
1452
+ style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600" },
772
1453
  testID: `body-map-detail-panel-contributing-${index}-name`,
773
1454
  children: exercise.name
774
1455
  }
@@ -776,7 +1457,8 @@ function BodyMapDetailPanel({
776
1457
  /* @__PURE__ */ jsx(
777
1458
  Text,
778
1459
  {
779
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY2 },
1460
+ className: "text-text-secondary",
1461
+ style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
780
1462
  testID: `body-map-detail-panel-contributing-${index}-detail`,
781
1463
  children: `${exercise.sets} sets \xB7 ${Math.round(exercise.contributionWeight * 100)}%`
782
1464
  }
@@ -790,11 +1472,11 @@ function BodyMapDetailPanel({
790
1472
  /* @__PURE__ */ jsx(
791
1473
  Text,
792
1474
  {
1475
+ className: "text-text-tertiary",
793
1476
  style: {
794
1477
  fontSize: 10,
795
1478
  fontFamily: "Inter, sans-serif",
796
1479
  fontWeight: "600",
797
- color: TEXT_TERTIARY,
798
1480
  marginBottom: 8
799
1481
  },
800
1482
  children: "UPCOMING"
@@ -810,7 +1492,8 @@ function BodyMapDetailPanel({
810
1492
  /* @__PURE__ */ jsx(
811
1493
  Text,
812
1494
  {
813
- style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_PRIMARY2 },
1495
+ className: "text-text-primary",
1496
+ style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600" },
814
1497
  testID: `body-map-detail-panel-upcoming-${index}-name`,
815
1498
  children: exercise.name
816
1499
  }
@@ -818,7 +1501,8 @@ function BodyMapDetailPanel({
818
1501
  /* @__PURE__ */ jsx(
819
1502
  Text,
820
1503
  {
821
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_TERTIARY },
1504
+ className: "text-text-tertiary",
1505
+ style: { fontSize: 12, fontFamily: "Inter, sans-serif" },
822
1506
  testID: `body-map-detail-panel-upcoming-${index}-detail`,
823
1507
  children: `${exercise.workoutName} \xB7 ${exercise.sets} sets`
824
1508
  }
@@ -844,7 +1528,7 @@ function BodyMapDetailPanel({
844
1528
  borderColor: "rgba(255,121,0,0.3)"
845
1529
  },
846
1530
  testID: "body-map-detail-panel-view-exercises",
847
- children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "700", color: BRAND_PRIMARY }, children: "View exercises" })
1531
+ children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "700", color: BRAND_PRIMARY2 }, children: "View exercises" })
848
1532
  }
849
1533
  )
850
1534
  ]
@@ -857,12 +1541,1222 @@ function BodyMapDetailPanel({
857
1541
  }
858
1542
  );
859
1543
  }
860
- var SURFACE_ELEVATED2 = "var(--color-surface-elevated)";
861
- var BORDER_DEFAULT2 = "var(--color-border-default)";
862
- var TEXT_PRIMARY3 = "var(--color-text-primary)";
863
- var TEXT_SECONDARY3 = "var(--color-text-secondary)";
864
- var TEXT_TERTIARY2 = "var(--color-text-tertiary)";
865
- var PAGE_BG = "var(--color-background-base)";
1544
+ function hexToRgb(hex) {
1545
+ const cleaned = hex.replace("#", "");
1546
+ let r, g, b;
1547
+ if (cleaned.length === 3) {
1548
+ r = parseInt(cleaned[0] + cleaned[0], 16);
1549
+ g = parseInt(cleaned[1] + cleaned[1], 16);
1550
+ b = parseInt(cleaned[2] + cleaned[2], 16);
1551
+ } else if (cleaned.length === 6) {
1552
+ r = parseInt(cleaned.slice(0, 2), 16);
1553
+ g = parseInt(cleaned.slice(2, 4), 16);
1554
+ b = parseInt(cleaned.slice(4, 6), 16);
1555
+ } else {
1556
+ return null;
1557
+ }
1558
+ return { r, g, b };
1559
+ }
1560
+ function rgbToHsv(r, g, b) {
1561
+ const rNorm = r / 255;
1562
+ const gNorm = g / 255;
1563
+ const bNorm = b / 255;
1564
+ const max = Math.max(rNorm, gNorm, bNorm);
1565
+ const min = Math.min(rNorm, gNorm, bNorm);
1566
+ const delta = max - min;
1567
+ const v = max;
1568
+ const s = max === 0 ? 0 : delta / max;
1569
+ let h = 0;
1570
+ if (delta !== 0) {
1571
+ if (max === rNorm) {
1572
+ h = 60 * ((gNorm - bNorm) / delta % 6);
1573
+ } else if (max === gNorm) {
1574
+ h = 60 * ((bNorm - rNorm) / delta + 2);
1575
+ } else {
1576
+ h = 60 * ((rNorm - gNorm) / delta + 4);
1577
+ }
1578
+ }
1579
+ if (h < 0) h += 360;
1580
+ return { h, s, v };
1581
+ }
1582
+ function hsvToRgb(h, s, v) {
1583
+ const c = v * s;
1584
+ const x = c * (1 - Math.abs(h / 60 % 2 - 1));
1585
+ const m = v - c;
1586
+ let rPrime, gPrime, bPrime;
1587
+ if (h >= 0 && h < 60) {
1588
+ rPrime = c;
1589
+ gPrime = x;
1590
+ bPrime = 0;
1591
+ } else if (h >= 60 && h < 120) {
1592
+ rPrime = x;
1593
+ gPrime = c;
1594
+ bPrime = 0;
1595
+ } else if (h >= 120 && h < 180) {
1596
+ rPrime = 0;
1597
+ gPrime = c;
1598
+ bPrime = x;
1599
+ } else if (h >= 180 && h < 240) {
1600
+ rPrime = 0;
1601
+ gPrime = x;
1602
+ bPrime = c;
1603
+ } else if (h >= 240 && h < 300) {
1604
+ rPrime = x;
1605
+ gPrime = 0;
1606
+ bPrime = c;
1607
+ } else {
1608
+ rPrime = c;
1609
+ gPrime = 0;
1610
+ bPrime = x;
1611
+ }
1612
+ return {
1613
+ r: Math.round((rPrime + m) * 255),
1614
+ g: Math.round((gPrime + m) * 255),
1615
+ b: Math.round((bPrime + m) * 255)
1616
+ };
1617
+ }
1618
+ function rgbToHex(r, g, b) {
1619
+ const toHex = (n) => {
1620
+ const clamped = Math.max(0, Math.min(255, Math.round(n)));
1621
+ return clamped.toString(16).padStart(2, "0");
1622
+ };
1623
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
1624
+ }
1625
+ function lighten(hex, amount = 0.1) {
1626
+ const rgb = hexToRgb(hex);
1627
+ if (!rgb) return hex;
1628
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
1629
+ const newV = Math.min(1, hsv.v + amount);
1630
+ const newRgb = hsvToRgb(hsv.h, hsv.s, newV);
1631
+ return rgbToHex(newRgb.r, newRgb.g, newRgb.b);
1632
+ }
1633
+ var shadowColors = {
1634
+ // For charcoal surfaces (~#2C2C2C to #3C3C3C)
1635
+ charcoal: {
1636
+ dark: "rgba(0, 0, 0, 0.5)",
1637
+ light: "rgba(255, 255, 255, 0.12)",
1638
+ // brighter for crisp rim light
1639
+ darker: "rgba(0, 0, 0, 0.6)"
1640
+ },
1641
+ // For neutral dark surfaces (~#1F2937)
1642
+ neutralDark: {
1643
+ dark: "rgba(0, 0, 0, 0.4)",
1644
+ light: "rgba(255, 255, 255, 0.08)",
1645
+ darker: "rgba(0, 0, 0, 0.5)"
1646
+ },
1647
+ // For light surfaces (white/light gray backgrounds)
1648
+ neutralLight: {
1649
+ dark: "rgba(0, 0, 0, 0.15)",
1650
+ // Visible dark shadow for depth on light backgrounds
1651
+ light: "rgba(255, 255, 255, 1)",
1652
+ // Bright highlight for raised effect (visible on light gray)
1653
+ darker: "rgba(0, 0, 0, 0.2)"
1654
+ // Deeper shadow for pressed states
1655
+ }
1656
+ };
1657
+ var intensityConfig = {
1658
+ subtle: { offset: 1, blur: 2 },
1659
+ // very light, barely visible
1660
+ medium: { offset: 2, blur: 4 },
1661
+ // noticeable but restrained
1662
+ strong: { offset: 2, blur: 5 }
1663
+ // slightly deeper blur, same offset as medium
1664
+ };
1665
+ function createRaisedShadow(surface = "charcoal", intensity = "medium") {
1666
+ const colors = shadowColors[surface];
1667
+ const { offset, blur } = intensityConfig[intensity];
1668
+ const rimBlur = 1;
1669
+ return Platform.select({
1670
+ web: {
1671
+ boxShadow: `${offset}px ${offset}px ${blur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`
1672
+ },
1673
+ default: {
1674
+ // React Native shadow approximation (limited compared to web)
1675
+ shadowColor: "#000",
1676
+ shadowOffset: { width: offset, height: offset },
1677
+ shadowOpacity: 0.3,
1678
+ shadowRadius: blur / 2,
1679
+ elevation: offset
1680
+ }
1681
+ });
1682
+ }
1683
+ function createPressedShadow(surface = "charcoal", intensity = "medium") {
1684
+ const colors = shadowColors[surface];
1685
+ const { offset, blur } = intensityConfig[intensity];
1686
+ const rimOffset = 1;
1687
+ const rimBlur = 1;
1688
+ return Platform.select({
1689
+ web: {
1690
+ boxShadow: `inset ${offset}px ${offset}px ${blur}px ${colors.darker}, inset -${rimOffset}px -${rimOffset}px ${rimBlur}px ${colors.light}`
1691
+ },
1692
+ default: {
1693
+ // React Native doesn't support inset shadows, approximate with darker bg
1694
+ shadowOpacity: 0,
1695
+ elevation: 0
1696
+ }
1697
+ });
1698
+ }
1699
+ function createFlatShadow() {
1700
+ return Platform.select({
1701
+ web: {
1702
+ boxShadow: "none"
1703
+ },
1704
+ default: {
1705
+ shadowOpacity: 0,
1706
+ elevation: 0
1707
+ }
1708
+ });
1709
+ }
1710
+ function createRaisedHoverShadow(surface = "charcoal", intensity = "medium") {
1711
+ const colors = shadowColors[surface];
1712
+ const { offset, blur } = intensityConfig[intensity];
1713
+ const hoverOffset = Math.max(1, Math.round(offset / 2));
1714
+ const hoverBlur = Math.max(1, Math.round(blur / 2));
1715
+ const rimBlur = 1;
1716
+ return Platform.select({
1717
+ web: {
1718
+ // Keep same offsets as normal state for rim to prevent "shrinking" effect
1719
+ boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.dark}, -${offset}px -${offset}px ${rimBlur}px ${colors.light}`
1720
+ },
1721
+ default: {
1722
+ shadowColor: "#000",
1723
+ shadowOffset: { width: hoverOffset, height: hoverOffset },
1724
+ shadowOpacity: 0.2,
1725
+ shadowRadius: hoverBlur / 2,
1726
+ elevation: hoverOffset
1727
+ }
1728
+ });
1729
+ }
1730
+ function createPressedHoverShadow(surface = "charcoal", intensity = "medium") {
1731
+ const colors = shadowColors[surface];
1732
+ const { offset, blur } = intensityConfig[intensity];
1733
+ const hoverOffset = Math.max(1, Math.round(offset / 2));
1734
+ const hoverBlur = Math.max(1, Math.round(blur / 2));
1735
+ const rimBlur = 1;
1736
+ return Platform.select({
1737
+ web: {
1738
+ // Keep rim offset at 1px (same as pressed normal) to prevent "shrinking" effect
1739
+ boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${colors.darker}, inset -1px -1px ${rimBlur}px ${colors.light}`
1740
+ },
1741
+ default: {
1742
+ shadowOpacity: 0,
1743
+ elevation: 0
1744
+ }
1745
+ });
1746
+ }
1747
+ ({
1748
+ // Charcoal surface shadows (for dark toolbars, cards)
1749
+ charcoal: {
1750
+ raised: {
1751
+ subtle: createRaisedShadow("charcoal", "subtle"),
1752
+ medium: createRaisedShadow("charcoal", "medium"),
1753
+ strong: createRaisedShadow("charcoal", "strong")
1754
+ },
1755
+ raisedHover: {
1756
+ subtle: createRaisedHoverShadow("charcoal", "subtle"),
1757
+ medium: createRaisedHoverShadow("charcoal", "medium"),
1758
+ strong: createRaisedHoverShadow("charcoal", "strong")
1759
+ },
1760
+ pressed: {
1761
+ subtle: createPressedShadow("charcoal", "subtle"),
1762
+ medium: createPressedShadow("charcoal", "medium"),
1763
+ strong: createPressedShadow("charcoal", "strong")
1764
+ },
1765
+ pressedHover: {
1766
+ subtle: createPressedHoverShadow("charcoal", "subtle"),
1767
+ medium: createPressedHoverShadow("charcoal", "medium"),
1768
+ strong: createPressedHoverShadow("charcoal", "strong")
1769
+ },
1770
+ flat: createFlatShadow()
1771
+ },
1772
+ // Neutral dark surface shadows
1773
+ neutralDark: {
1774
+ raised: {
1775
+ subtle: createRaisedShadow("neutralDark", "subtle"),
1776
+ medium: createRaisedShadow("neutralDark", "medium"),
1777
+ strong: createRaisedShadow("neutralDark", "strong")
1778
+ },
1779
+ raisedHover: {
1780
+ subtle: createRaisedHoverShadow("neutralDark", "subtle"),
1781
+ medium: createRaisedHoverShadow("neutralDark", "medium"),
1782
+ strong: createRaisedHoverShadow("neutralDark", "strong")
1783
+ },
1784
+ pressed: {
1785
+ subtle: createPressedShadow("neutralDark", "subtle"),
1786
+ medium: createPressedShadow("neutralDark", "medium"),
1787
+ strong: createPressedShadow("neutralDark", "strong")
1788
+ },
1789
+ pressedHover: {
1790
+ subtle: createPressedHoverShadow("neutralDark", "subtle"),
1791
+ medium: createPressedHoverShadow("neutralDark", "medium"),
1792
+ strong: createPressedHoverShadow("neutralDark", "strong")
1793
+ },
1794
+ flat: createFlatShadow()
1795
+ },
1796
+ // Neutral light surface shadows
1797
+ neutralLight: {
1798
+ raised: {
1799
+ subtle: createRaisedShadow("neutralLight", "subtle"),
1800
+ medium: createRaisedShadow("neutralLight", "medium"),
1801
+ strong: createRaisedShadow("neutralLight", "strong")
1802
+ },
1803
+ raisedHover: {
1804
+ subtle: createRaisedHoverShadow("neutralLight", "subtle"),
1805
+ medium: createRaisedHoverShadow("neutralLight", "medium"),
1806
+ strong: createRaisedHoverShadow("neutralLight", "strong")
1807
+ },
1808
+ pressed: {
1809
+ subtle: createPressedShadow("neutralLight", "subtle"),
1810
+ medium: createPressedShadow("neutralLight", "medium"),
1811
+ strong: createPressedShadow("neutralLight", "strong")
1812
+ },
1813
+ pressedHover: {
1814
+ subtle: createPressedHoverShadow("neutralLight", "subtle"),
1815
+ medium: createPressedHoverShadow("neutralLight", "medium"),
1816
+ strong: createPressedHoverShadow("neutralLight", "strong")
1817
+ },
1818
+ flat: createFlatShadow()
1819
+ }
1820
+ });
1821
+ var elevationSystem = {
1822
+ // Deep inset (recessed input fields, deeply pressed buttons)
1823
+ [-2]: {
1824
+ name: "deep-inset",
1825
+ colorAdjustment: 0,
1826
+ shadowIntensity: "strong",
1827
+ shadowStyle: "pressed",
1828
+ description: "Deeply recessed elements (e.g., input fields, deeply pressed buttons)"
1829
+ },
1830
+ // Shallow inset (pressed buttons, sunken panels)
1831
+ [-1]: {
1832
+ name: "inset",
1833
+ colorAdjustment: 0,
1834
+ shadowIntensity: "medium",
1835
+ shadowStyle: "pressed",
1836
+ description: "Shallow inset elements (e.g., pressed buttons, sunken panels within cards)"
1837
+ },
1838
+ // Base level (page background, default surface)
1839
+ [0]: {
1840
+ name: "base",
1841
+ colorAdjustment: 0,
1842
+ shadowIntensity: "subtle",
1843
+ shadowStyle: "raised",
1844
+ description: "Base surface level (page background, default containers)"
1845
+ },
1846
+ // Level 1: Subtle elevation (outline cards, subtle containers)
1847
+ [1]: {
1848
+ name: "subtle",
1849
+ colorAdjustment: 0.01,
1850
+ shadowIntensity: "subtle",
1851
+ shadowStyle: "raised",
1852
+ description: "Subtle elevation (outline cards, subtle containers)"
1853
+ },
1854
+ // Level 2: Standard elevation (default cards, buttons)
1855
+ [2]: {
1856
+ name: "standard",
1857
+ colorAdjustment: 0.02,
1858
+ shadowIntensity: "medium",
1859
+ shadowStyle: "raised",
1860
+ description: "Standard elevation (default cards, raised buttons)"
1861
+ },
1862
+ // Level 3: Prominent elevation (important cards, modals)
1863
+ [3]: {
1864
+ name: "prominent",
1865
+ colorAdjustment: 0.04,
1866
+ shadowIntensity: "strong",
1867
+ shadowStyle: "raised",
1868
+ description: "Prominent elevation (important cards, modals, dropdowns)"
1869
+ },
1870
+ // Level 4: High elevation (overlays, popovers)
1871
+ [4]: {
1872
+ name: "high",
1873
+ colorAdjustment: 0.06,
1874
+ shadowIntensity: "strong",
1875
+ shadowStyle: "raised",
1876
+ description: "High elevation (overlays, popovers, tooltips)"
1877
+ },
1878
+ // Level 5: Floating (toasts, floating action buttons)
1879
+ [5]: {
1880
+ name: "floating",
1881
+ colorAdjustment: 0.08,
1882
+ shadowIntensity: "strong",
1883
+ shadowStyle: "raised",
1884
+ description: "Floating elevation (toasts, floating action buttons, highest z-index)"
1885
+ }
1886
+ };
1887
+ function calculateRimLightColor(baseColor, level) {
1888
+ const rgb = hexToRgb(baseColor);
1889
+ if (!rgb) {
1890
+ return "rgba(255, 255, 255, 0.5)";
1891
+ }
1892
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
1893
+ const isLight = hsv.v > 0.6;
1894
+ const isSaturated = hsv.s > 0.3;
1895
+ const absLevel = Math.abs(level);
1896
+ const opacityBoost = Math.max(0, (absLevel - 1) * 0.05);
1897
+ if (isSaturated) {
1898
+ const rimLightValue = 0.95;
1899
+ const rimLightRgb = hsvToRgb(hsv.h, hsv.s * 0.3, rimLightValue);
1900
+ const baseOpacity = isLight ? 0.9 : 0.5;
1901
+ const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
1902
+ return `rgba(${rimLightRgb.r}, ${rimLightRgb.g}, ${rimLightRgb.b}, ${finalOpacity.toFixed(2)})`;
1903
+ } else {
1904
+ const baseOpacity = isLight ? 0.9 : 0.12;
1905
+ const finalOpacity = Math.min(1, baseOpacity + opacityBoost);
1906
+ return `rgba(255, 255, 255, ${finalOpacity.toFixed(2)})`;
1907
+ }
1908
+ }
1909
+ function calculateDarkShadowColors(surfaceColor) {
1910
+ const rgb = hexToRgb(surfaceColor);
1911
+ if (!rgb) {
1912
+ return {
1913
+ dark: "rgba(0, 0, 0, 0.3)",
1914
+ darker: "rgba(0, 0, 0, 0.4)"
1915
+ };
1916
+ }
1917
+ const hsv = rgbToHsv(rgb.r, rgb.g, rgb.b);
1918
+ const isLight = hsv.v > 0.6;
1919
+ const isSaturated = hsv.s > 0.3;
1920
+ if (isSaturated) {
1921
+ const darkShadowValue = 0.15;
1922
+ const darkShadowRgb = hsvToRgb(hsv.h, hsv.s, darkShadowValue);
1923
+ if (isLight) {
1924
+ return {
1925
+ dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.3)`,
1926
+ darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.4)`
1927
+ };
1928
+ } else {
1929
+ return {
1930
+ dark: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.5)`,
1931
+ darker: `rgba(${darkShadowRgb.r}, ${darkShadowRgb.g}, ${darkShadowRgb.b}, 0.6)`
1932
+ };
1933
+ }
1934
+ } else {
1935
+ if (isLight) {
1936
+ return {
1937
+ dark: "rgba(0, 0, 0, 0.2)",
1938
+ darker: "rgba(0, 0, 0, 0.3)"
1939
+ };
1940
+ } else {
1941
+ return {
1942
+ dark: "rgba(0, 0, 0, 0.5)",
1943
+ darker: "rgba(0, 0, 0, 0.6)"
1944
+ };
1945
+ }
1946
+ }
1947
+ }
1948
+ function getRimLightConfig() {
1949
+ return {
1950
+ offset: 1,
1951
+ // Fixed 1px for crisp rim
1952
+ blur: 1
1953
+ // Tight blur for crisp edge
1954
+ };
1955
+ }
1956
+ var elevationSurfaceCache = /* @__PURE__ */ new Map();
1957
+ var MAX_CACHE_SIZE = 100;
1958
+ function getCacheKey(baseColor, level, theme) {
1959
+ return `${baseColor}-${level}-${theme}`;
1960
+ }
1961
+ function calculateElevationSurface(baseColor, level, theme) {
1962
+ const config = elevationSystem[level];
1963
+ if (config.colorAdjustment === 0) {
1964
+ return baseColor;
1965
+ }
1966
+ if (level < 0) {
1967
+ return baseColor;
1968
+ }
1969
+ return lighten(baseColor, config.colorAdjustment);
1970
+ }
1971
+ function getElevationSurface(baseColor, level, theme) {
1972
+ const cacheKey = getCacheKey(baseColor, level, theme);
1973
+ if (elevationSurfaceCache.has(cacheKey)) {
1974
+ return elevationSurfaceCache.get(cacheKey);
1975
+ }
1976
+ const result = calculateElevationSurface(baseColor, level);
1977
+ if (elevationSurfaceCache.size >= MAX_CACHE_SIZE) {
1978
+ const firstKey = elevationSurfaceCache.keys().next().value;
1979
+ elevationSurfaceCache.delete(firstKey);
1980
+ }
1981
+ elevationSurfaceCache.set(cacheKey, result);
1982
+ return result;
1983
+ }
1984
+ var elevationShadowCache = /* @__PURE__ */ new Map();
1985
+ var MAX_SHADOW_CACHE_SIZE = 50;
1986
+ function getShadowCacheKey(baseColor, level, theme, isHovered) {
1987
+ return `${baseColor}-${level}-${theme}-${isHovered}`;
1988
+ }
1989
+ function calculateElevationShadow(baseColor, level, theme, isHovered = false) {
1990
+ const config = elevationSystem[level];
1991
+ if (level === 0) {
1992
+ return {};
1993
+ }
1994
+ const elevatedSurfaceColor = calculateElevationSurface(baseColor, level);
1995
+ const rimLightColor = calculateRimLightColor(baseColor, level);
1996
+ const darkShadowColors = calculateDarkShadowColors(elevatedSurfaceColor);
1997
+ const intensityConfig2 = {
1998
+ subtle: { offset: 1, blur: 2 },
1999
+ medium: { offset: 2, blur: 4 },
2000
+ strong: { offset: 2, blur: 5 }
2001
+ };
2002
+ const { offset, blur } = intensityConfig2[config.shadowIntensity];
2003
+ const rimConfig = getRimLightConfig();
2004
+ if (config.shadowStyle === "pressed") {
2005
+ if (isHovered) {
2006
+ const hoverOffset = Math.max(1, Math.round(offset / 2));
2007
+ const hoverBlur = Math.max(1, Math.round(blur / 2));
2008
+ return Platform.select({
2009
+ web: {
2010
+ boxShadow: `inset ${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
2011
+ },
2012
+ default: {
2013
+ shadowOpacity: 0,
2014
+ elevation: 0
2015
+ }
2016
+ });
2017
+ }
2018
+ return Platform.select({
2019
+ web: {
2020
+ boxShadow: `inset ${offset}px ${offset}px ${blur}px ${darkShadowColors.darker}, inset -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
2021
+ },
2022
+ default: {
2023
+ shadowOpacity: 0,
2024
+ elevation: 0
2025
+ }
2026
+ });
2027
+ } else {
2028
+ if (isHovered) {
2029
+ const hoverOffset = Math.max(1, Math.round(offset / 2));
2030
+ const hoverBlur = Math.max(1, Math.round(blur / 2));
2031
+ return Platform.select({
2032
+ web: {
2033
+ boxShadow: `${hoverOffset}px ${hoverOffset}px ${hoverBlur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
2034
+ },
2035
+ default: {
2036
+ shadowColor: "#000",
2037
+ shadowOffset: { width: hoverOffset, height: hoverOffset },
2038
+ shadowOpacity: 0.2,
2039
+ shadowRadius: hoverBlur / 2,
2040
+ elevation: hoverOffset
2041
+ }
2042
+ });
2043
+ }
2044
+ return Platform.select({
2045
+ web: {
2046
+ boxShadow: `${offset}px ${offset}px ${blur}px ${darkShadowColors.dark}, -${rimConfig.offset}px -${rimConfig.offset}px ${rimConfig.blur}px ${rimLightColor}`
2047
+ },
2048
+ default: {
2049
+ shadowColor: "#000",
2050
+ shadowOffset: { width: offset, height: offset },
2051
+ shadowOpacity: 0.3,
2052
+ shadowRadius: blur / 2,
2053
+ elevation: offset
2054
+ }
2055
+ });
2056
+ }
2057
+ }
2058
+ function getElevationShadow(baseColor, level, theme, isHovered = false) {
2059
+ const cacheKey = getShadowCacheKey(baseColor, level, theme, isHovered);
2060
+ if (elevationShadowCache.has(cacheKey)) {
2061
+ return elevationShadowCache.get(cacheKey);
2062
+ }
2063
+ const result = calculateElevationShadow(baseColor, level, theme, isHovered);
2064
+ if (elevationShadowCache.size >= MAX_SHADOW_CACHE_SIZE) {
2065
+ const firstKey = elevationShadowCache.keys().next().value;
2066
+ elevationShadowCache.delete(firstKey);
2067
+ }
2068
+ elevationShadowCache.set(cacheKey, result);
2069
+ return result;
2070
+ }
2071
+ function getBaseSurfaceColor(theme) {
2072
+ return theme === "light" ? semanticColorsLight["surface-raised"] : semanticColorsDark["surface-elevated"];
2073
+ }
2074
+ var componentElevationRanges = {
2075
+ button: {
2076
+ allowed: [2],
2077
+ default: 2,
2078
+ hover: 3
2079
+ },
2080
+ card: {
2081
+ allowed: [1, 2, 3],
2082
+ default: 2,
2083
+ hover: 3
2084
+ },
2085
+ input: {
2086
+ allowed: [-2, -1, 0],
2087
+ default: -1
2088
+ },
2089
+ overlay: {
2090
+ allowed: [4, 5],
2091
+ default: 4
2092
+ }
2093
+ };
2094
+ function getValidatedElevation(component, requested) {
2095
+ const range = componentElevationRanges[component];
2096
+ if (range.allowed.includes(requested)) {
2097
+ return requested;
2098
+ }
2099
+ const sorted = [...range.allowed].sort((a, b) => a - b);
2100
+ if (requested < sorted[0]) return sorted[0];
2101
+ if (requested > sorted[sorted.length - 1]) return sorted[sorted.length - 1];
2102
+ return sorted.reduce(
2103
+ (prev, curr) => Math.abs(curr - requested) < Math.abs(prev - requested) ? curr : prev
2104
+ );
2105
+ }
2106
+ function getTheme() {
2107
+ if (typeof document === "undefined") return "dark";
2108
+ return document.documentElement.classList.contains("light") ? "light" : "dark";
2109
+ }
2110
+ var listeners = [];
2111
+ function subscribe(listener) {
2112
+ listeners = [...listeners, listener];
2113
+ if (typeof document !== "undefined" && listeners.length === 1) {
2114
+ const observer = new MutationObserver((mutations) => {
2115
+ for (const mutation of mutations) {
2116
+ if (mutation.type === "attributes" && mutation.attributeName === "class") {
2117
+ listeners.forEach((l) => l());
2118
+ }
2119
+ }
2120
+ });
2121
+ observer.observe(document.documentElement, {
2122
+ attributes: true,
2123
+ attributeFilter: ["class"]
2124
+ });
2125
+ subscribe._observer = observer;
2126
+ }
2127
+ return () => {
2128
+ listeners = listeners.filter((l) => l !== listener);
2129
+ if (listeners.length === 0 && subscribe._observer) {
2130
+ subscribe._observer.disconnect();
2131
+ subscribe._observer = null;
2132
+ }
2133
+ };
2134
+ }
2135
+ function getSnapshot() {
2136
+ return getTheme();
2137
+ }
2138
+ function getServerSnapshot() {
2139
+ return "dark";
2140
+ }
2141
+ function useTheme() {
2142
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2143
+ }
2144
+
2145
+ // src/components/ui/card/Card.tsx
2146
+ var variantStyles = {
2147
+ elevated: "",
2148
+ // Will be set dynamically via elevation system
2149
+ outline: "border-2 border-border-strong",
2150
+ // Thicker border with stronger contrast
2151
+ filled: "",
2152
+ // Will be set dynamically via elevation system
2153
+ accent: "border border-border",
2154
+ subtle: "border border-border-subtle"
2155
+ };
2156
+ function Card({
2157
+ variant = "elevated",
2158
+ elevation = 2,
2159
+ isInteractive = false,
2160
+ isLoading = false,
2161
+ onPress,
2162
+ borderColor,
2163
+ bgColor,
2164
+ accentColor,
2165
+ accentWidth,
2166
+ className,
2167
+ children,
2168
+ style,
2169
+ skeletonHasHeader = true,
2170
+ skeletonHasFooter = false,
2171
+ skeletonContentLines = 3,
2172
+ ...props
2173
+ }) {
2174
+ const isClickable = isInteractive || !!onPress;
2175
+ const [isHovered, setIsHovered] = useState(false);
2176
+ const theme = useTheme();
2177
+ const elevationLevel = useMemo(() => {
2178
+ const validated = getValidatedElevation("card", elevation);
2179
+ if (variant === "outline" || variant === "accent" || variant === "subtle") {
2180
+ return 1;
2181
+ }
2182
+ return validated;
2183
+ }, [variant, elevation]);
2184
+ const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme]);
2185
+ const surfaceColor = useMemo(() => {
2186
+ if ((variant === "outline" || variant === "accent") && theme === "light") {
2187
+ return "#FAFAFA";
2188
+ }
2189
+ if (variant === "subtle") {
2190
+ return getElevationSurface(baseColor, 0, theme);
2191
+ }
2192
+ return getElevationSurface(baseColor, elevationLevel, theme);
2193
+ }, [baseColor, elevationLevel, theme, variant]);
2194
+ const shadowStyle = useMemo(() => {
2195
+ const shouldHover = isHovered && isClickable;
2196
+ return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
2197
+ }, [baseColor, elevationLevel, theme, isHovered, isClickable]);
2198
+ const cardContent = isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
2199
+ skeletonHasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
2200
+ /* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
2201
+ /* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
2202
+ ] }),
2203
+ /* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: skeletonContentLines }).map((_, i) => /* @__PURE__ */ jsx(
2204
+ View,
2205
+ {
2206
+ className: cn(
2207
+ "h-4 bg-interactive-disabled rounded",
2208
+ i < skeletonContentLines - 1 ? "mb-2 w-full" : "w-4/5"
2209
+ )
2210
+ },
2211
+ i
2212
+ )) }),
2213
+ skeletonHasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
2214
+ ] }) : children;
2215
+ const baseClassName = cn(
2216
+ "rounded-lg overflow-hidden relative",
2217
+ // Apply variant styles, but only use default border color if no custom borderColor
2218
+ variant === "outline" ? borderColor ? "border-2" : variantStyles[variant] : variantStyles[variant],
2219
+ // Remove Tailwind shadow classes - we're using elevation shadows via style prop
2220
+ isClickable && "web:cursor-pointer web:transition-all web:duration-150",
2221
+ isClickable && "web:hover:-translate-y-0.5 active:scale-[0.99]",
2222
+ isLoading && "pointer-events-none animate-pulse",
2223
+ className
2224
+ );
2225
+ const accentStyle = useMemo(() => variant === "accent" ? {
2226
+ borderLeftWidth: accentWidth ?? 3,
2227
+ borderLeftColor: accentColor ?? "var(--color-brand-primary)"
2228
+ } : {}, [variant, accentWidth, accentColor]);
2229
+ const mergedStyle = useMemo(() => {
2230
+ const elevationStyle = {
2231
+ backgroundColor: bgColor || surfaceColor,
2232
+ borderRadius: 8,
2233
+ overflow: "hidden",
2234
+ ...shadowStyle,
2235
+ ...accentStyle
2236
+ };
2237
+ if (borderColor) {
2238
+ elevationStyle.borderColor = borderColor;
2239
+ }
2240
+ if (!style) return elevationStyle;
2241
+ return [elevationStyle, style];
2242
+ }, [style, surfaceColor, shadowStyle, borderColor, bgColor, accentStyle]);
2243
+ if (isClickable) {
2244
+ return /* @__PURE__ */ jsx(
2245
+ Pressable,
2246
+ {
2247
+ onPress,
2248
+ onHoverIn: () => setIsHovered(true),
2249
+ onHoverOut: () => setIsHovered(false),
2250
+ accessibilityRole: "button",
2251
+ className: baseClassName,
2252
+ style: mergedStyle,
2253
+ ...props,
2254
+ children: cardContent
2255
+ }
2256
+ );
2257
+ }
2258
+ return /* @__PURE__ */ jsx(View, { className: baseClassName, style: mergedStyle, ...props, children: cardContent });
2259
+ }
2260
+ function CardHeader({ children, className }) {
2261
+ return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-6", className), children });
2262
+ }
2263
+ function CardContent({ children, className }) {
2264
+ return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4", className), children });
2265
+ }
2266
+ function CardFooter({ children, className }) {
2267
+ return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
2268
+ }
2269
+ var solidVariantColors = {
2270
+ success: "#14B8A6",
2271
+ warning: "#FFB020",
2272
+ error: "#D14343",
2273
+ neutral: "#6B7280"
2274
+ };
2275
+ var ringVariantStyles = {
2276
+ "on-track": {
2277
+ backgroundColor: "rgba(20,184,166,0.15)",
2278
+ borderWidth: 1,
2279
+ borderColor: "rgba(20,184,166,0.3)"
2280
+ },
2281
+ deviation: {
2282
+ backgroundColor: "rgba(245,158,11,0.15)",
2283
+ borderWidth: 1,
2284
+ borderColor: "rgba(245,158,11,0.25)"
2285
+ },
2286
+ future: {
2287
+ backgroundColor: "rgba(107,114,128,0.1)",
2288
+ borderWidth: 1,
2289
+ borderStyle: "dashed",
2290
+ borderColor: "rgba(107,114,128,0.2)"
2291
+ }
2292
+ };
2293
+ var glowStyles = {
2294
+ success: { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
2295
+ warning: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
2296
+ error: { boxShadow: "0 0 4px rgba(239,68,68,0.4)" },
2297
+ neutral: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" },
2298
+ "on-track": { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
2299
+ deviation: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
2300
+ future: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" }
2301
+ };
2302
+ var iconChars = {
2303
+ check: "\u2713",
2304
+ exclamation: "!",
2305
+ dash: "\u2014"
2306
+ };
2307
+ var iconColors = {
2308
+ success: "#0A5C52",
2309
+ warning: "#6B4000",
2310
+ error: "#5C1A1A",
2311
+ neutral: "#D1D5DB",
2312
+ "on-track": "#14B8A6",
2313
+ deviation: "#FFB020",
2314
+ future: "#6B7280"
2315
+ };
2316
+ var sizeDimensions = {
2317
+ sm: { size: 8, showIcon: false },
2318
+ md: { size: 18, showIcon: true }
2319
+ };
2320
+ function isSolidVariant(variant) {
2321
+ return variant in solidVariantColors;
2322
+ }
2323
+ function StatusDot({
2324
+ variant,
2325
+ icon,
2326
+ size = "sm",
2327
+ glow,
2328
+ label,
2329
+ className,
2330
+ ...props
2331
+ }) {
2332
+ const config = sizeDimensions[size];
2333
+ const solid = isSolidVariant(variant);
2334
+ const ring = ringVariantStyles[variant];
2335
+ const glowStyle = glow ? glowStyles[variant] : null;
2336
+ const dot = /* @__PURE__ */ jsx(
2337
+ View,
2338
+ {
2339
+ style: [
2340
+ {
2341
+ width: config.size,
2342
+ height: config.size,
2343
+ borderRadius: 9999,
2344
+ alignItems: "center",
2345
+ justifyContent: "center",
2346
+ flexShrink: 0
2347
+ },
2348
+ solid ? { backgroundColor: solidVariantColors[variant] } : void 0,
2349
+ ring ? ring : void 0,
2350
+ glowStyle ? glowStyle : void 0
2351
+ ],
2352
+ accessibilityRole: "image",
2353
+ accessibilityLabel: `${variant} status`,
2354
+ testID: "status-dot",
2355
+ children: config.showIcon && icon && /* @__PURE__ */ jsx(
2356
+ Text,
2357
+ {
2358
+ style: {
2359
+ fontSize: 11,
2360
+ lineHeight: 11,
2361
+ fontWeight: "900",
2362
+ color: iconColors[variant]
2363
+ },
2364
+ accessibilityElementsHidden: true,
2365
+ children: iconChars[icon]
2366
+ }
2367
+ )
2368
+ }
2369
+ );
2370
+ if (label) {
2371
+ return /* @__PURE__ */ jsxs(
2372
+ View,
2373
+ {
2374
+ className,
2375
+ style: { flexDirection: "row", alignItems: "center", gap: 6 },
2376
+ accessibilityLabel: `${variant} status: ${label}`,
2377
+ ...props,
2378
+ children: [
2379
+ /* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: dot }),
2380
+ /* @__PURE__ */ jsx(
2381
+ Text,
2382
+ {
2383
+ style: { fontSize: 12, lineHeight: 16, color: "#9CA3AF" },
2384
+ accessibilityElementsHidden: true,
2385
+ children: label
2386
+ }
2387
+ )
2388
+ ]
2389
+ }
2390
+ );
2391
+ }
2392
+ return /* @__PURE__ */ jsx(View, { className, ...props, children: dot });
2393
+ }
2394
+
2395
+ // src/components/custom/Workout/MesoStatusCard.tsx
2396
+ var BRAND_PRIMARY3 = "#FF7900";
2397
+ var BRAND_PRIMARY_DARK = "#C45E00";
2398
+ var BRAND_PRIMARY_LIGHT = "#FFB066";
2399
+ var SUCCESS = "#14B8A6";
2400
+ var WARNING = "#FFB020";
2401
+ var ERROR = "#D14343";
2402
+ var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY3, BRAND_PRIMARY_LIGHT];
2403
+ var CARD_GRADIENT = `linear-gradient(135deg, ${resolveColor("surface-elevated")} 0%, ${resolveColor("surface-raised")} 100%)`;
2404
+ var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(20,184,166,0.25) 0%, rgba(255,176,32,0.25) 50%, rgba(209,67,67,0.25) 100%)";
2405
+ var STATUS_VARIANTS = {
2406
+ success: { bg: "rgba(20,184,166,0.15)", border: "rgba(20,184,166,0.3)", text: SUCCESS },
2407
+ warning: { bg: "rgba(255,176,32,0.15)", border: "rgba(255,176,32,0.3)", text: WARNING },
2408
+ error: { bg: "rgba(209,67,67,0.15)", border: "rgba(209,67,67,0.25)", text: ERROR }
2409
+ };
2410
+ function clamp012(value) {
2411
+ if (!Number.isFinite(value)) return 0;
2412
+ if (value < 0) return 0;
2413
+ if (value > 1) return 1;
2414
+ return value;
2415
+ }
2416
+ function getGaugeZoneColor(level) {
2417
+ if (level >= 0.7) return ERROR;
2418
+ if (level >= 0.4) return WARNING;
2419
+ return SUCCESS;
2420
+ }
2421
+ function renderCoachingText(text, highlights) {
2422
+ if (!highlights || highlights.length === 0) return text;
2423
+ const escaped = highlights.filter(Boolean).map((h) => h.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
2424
+ if (escaped.length === 0) return text;
2425
+ const regex = new RegExp(`(${escaped.join("|")})`, "g");
2426
+ return text.split(regex).map(
2427
+ (part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(
2428
+ Text,
2429
+ {
2430
+ className: "text-text-primary",
2431
+ style: { fontWeight: "700" },
2432
+ children: part
2433
+ },
2434
+ `${part}-${index}`
2435
+ ) : /* @__PURE__ */ jsx(Fragment$1, { children: part }, `t-${index}`)
2436
+ );
2437
+ }
2438
+ function StatusPill({ badge }) {
2439
+ const colors = STATUS_VARIANTS[badge.variant];
2440
+ return /* @__PURE__ */ jsxs(
2441
+ View,
2442
+ {
2443
+ className: "flex-row items-center",
2444
+ style: {
2445
+ gap: 5,
2446
+ paddingVertical: 3,
2447
+ paddingHorizontal: 8,
2448
+ borderRadius: 4,
2449
+ borderWidth: 1,
2450
+ backgroundColor: colors.bg,
2451
+ borderColor: colors.border
2452
+ },
2453
+ testID: "meso-status-card-badge",
2454
+ children: [
2455
+ /* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(StatusDot, { variant: badge.variant, size: "sm" }) }),
2456
+ /* @__PURE__ */ jsx(
2457
+ Text,
2458
+ {
2459
+ style: {
2460
+ fontSize: 10,
2461
+ fontFamily: "Inter, sans-serif",
2462
+ fontWeight: "700",
2463
+ letterSpacing: 0.3,
2464
+ color: colors.text
2465
+ },
2466
+ children: badge.label
2467
+ }
2468
+ )
2469
+ ]
2470
+ }
2471
+ );
2472
+ }
2473
+ function MetricCell({ metric }) {
2474
+ return /* @__PURE__ */ jsxs(View, { style: { width: "48%" }, testID: "meso-status-card-metric", children: [
2475
+ /* @__PURE__ */ jsx(
2476
+ Text,
2477
+ {
2478
+ className: "text-text-tertiary",
2479
+ style: {
2480
+ fontSize: 10,
2481
+ fontFamily: "Inter, sans-serif",
2482
+ fontWeight: "600",
2483
+ letterSpacing: 0.5,
2484
+ textTransform: "uppercase"
2485
+ },
2486
+ children: metric.label
2487
+ }
2488
+ ),
2489
+ /* @__PURE__ */ jsx(
2490
+ Text,
2491
+ {
2492
+ className: "text-text-primary",
2493
+ style: {
2494
+ marginTop: 2,
2495
+ fontSize: 13,
2496
+ fontFamily: "Inter, sans-serif",
2497
+ fontWeight: "600"
2498
+ },
2499
+ children: metric.value
2500
+ }
2501
+ )
2502
+ ] });
2503
+ }
2504
+ function Gauge({ gauge }) {
2505
+ const level = clamp012(gauge.level);
2506
+ const percentage = Math.round(level * 100);
2507
+ const markerColor = getGaugeZoneColor(level);
2508
+ return /* @__PURE__ */ jsxs(
2509
+ View,
2510
+ {
2511
+ style: { gap: 6 },
2512
+ accessibilityRole: "progressbar",
2513
+ accessibilityValue: { min: 0, max: 100, now: percentage },
2514
+ accessibilityLabel: `${gauge.label}: ${percentage}%`,
2515
+ "aria-valuenow": percentage,
2516
+ "aria-valuemin": 0,
2517
+ "aria-valuemax": 100,
2518
+ testID: "meso-status-card-gauge",
2519
+ children: [
2520
+ /* @__PURE__ */ jsxs(
2521
+ View,
2522
+ {
2523
+ className: "flex-row items-center justify-between",
2524
+ accessibilityElementsHidden: true,
2525
+ children: [
2526
+ /* @__PURE__ */ jsx(
2527
+ Text,
2528
+ {
2529
+ className: "text-text-secondary",
2530
+ style: {
2531
+ fontSize: 10,
2532
+ fontFamily: "Inter, sans-serif",
2533
+ fontWeight: "500",
2534
+ letterSpacing: 0.5,
2535
+ textTransform: "uppercase"
2536
+ },
2537
+ children: gauge.label
2538
+ }
2539
+ ),
2540
+ gauge.sublabel != null && /* @__PURE__ */ jsx(
2541
+ Text,
2542
+ {
2543
+ className: "text-text-tertiary",
2544
+ style: {
2545
+ fontSize: 10,
2546
+ fontFamily: "Inter, sans-serif",
2547
+ fontWeight: "500"
2548
+ },
2549
+ children: gauge.sublabel
2550
+ }
2551
+ )
2552
+ ]
2553
+ }
2554
+ ),
2555
+ /* @__PURE__ */ jsxs(
2556
+ View,
2557
+ {
2558
+ style: {
2559
+ height: 8,
2560
+ borderRadius: 4,
2561
+ position: "relative",
2562
+ backgroundImage: GAUGE_GRADIENT
2563
+ },
2564
+ accessibilityElementsHidden: true,
2565
+ children: [
2566
+ /* @__PURE__ */ jsx(
2567
+ View,
2568
+ {
2569
+ style: {
2570
+ position: "absolute",
2571
+ left: "50%",
2572
+ top: 0,
2573
+ bottom: 0,
2574
+ width: 1,
2575
+ marginLeft: -0.5,
2576
+ backgroundColor: "rgba(255,255,255,0.3)"
2577
+ },
2578
+ testID: "meso-status-card-gauge-center"
2579
+ }
2580
+ ),
2581
+ /* @__PURE__ */ jsx(
2582
+ View,
2583
+ {
2584
+ className: "border-text-primary",
2585
+ style: {
2586
+ position: "absolute",
2587
+ left: `${percentage}%`,
2588
+ top: -3,
2589
+ marginLeft: -7,
2590
+ width: 14,
2591
+ height: 14,
2592
+ borderRadius: 9999,
2593
+ borderWidth: 2,
2594
+ backgroundColor: markerColor,
2595
+ boxShadow: "0 0 4px rgba(0,0,0,0.5)"
2596
+ },
2597
+ testID: "meso-status-card-gauge-marker"
2598
+ }
2599
+ )
2600
+ ]
2601
+ }
2602
+ )
2603
+ ]
2604
+ }
2605
+ );
2606
+ }
2607
+ function MesoStatusCard({
2608
+ mesoName,
2609
+ mesoSubtitle,
2610
+ statusBadge,
2611
+ metrics,
2612
+ gauges,
2613
+ coaching,
2614
+ nextTarget,
2615
+ className,
2616
+ ...props
2617
+ }) {
2618
+ return /* @__PURE__ */ jsxs(
2619
+ Card,
2620
+ {
2621
+ variant: "outline",
2622
+ elevation: 1,
2623
+ borderColor: BRAND_PRIMARY_DARK,
2624
+ className,
2625
+ style: {
2626
+ borderColor: BRAND_PRIMARY_DARK,
2627
+ borderWidth: 1,
2628
+ backgroundImage: CARD_GRADIENT
2629
+ },
2630
+ role: "article",
2631
+ "aria-label": `Mesocycle status for ${mesoName}`,
2632
+ testID: "meso-status-card",
2633
+ ...props,
2634
+ children: [
2635
+ /* @__PURE__ */ jsx(
2636
+ View,
2637
+ {
2638
+ className: "flex-row",
2639
+ style: { position: "absolute", top: 0, left: 0, right: 0, height: 3, zIndex: 1 },
2640
+ accessibilityElementsHidden: true,
2641
+ testID: "meso-status-card-accent",
2642
+ children: ACCENT_STOPS.map((color) => /* @__PURE__ */ jsx(View, { style: { flex: 1, backgroundColor: color } }, color))
2643
+ }
2644
+ ),
2645
+ /* @__PURE__ */ jsxs(View, { style: { padding: 14, gap: 14 }, testID: "meso-status-card-body", children: [
2646
+ /* @__PURE__ */ jsxs(View, { testID: "meso-status-card-header", children: [
2647
+ /* @__PURE__ */ jsxs(
2648
+ View,
2649
+ {
2650
+ className: "flex-row items-center justify-between",
2651
+ style: { gap: 8 },
2652
+ children: [
2653
+ /* @__PURE__ */ jsx(
2654
+ Text,
2655
+ {
2656
+ className: "text-text-primary",
2657
+ style: {
2658
+ flexShrink: 1,
2659
+ fontSize: 15,
2660
+ fontFamily: '"Space Grotesk", sans-serif',
2661
+ fontWeight: "700"
2662
+ },
2663
+ testID: "meso-status-card-name",
2664
+ children: mesoName
2665
+ }
2666
+ ),
2667
+ /* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
2668
+ ]
2669
+ }
2670
+ ),
2671
+ /* @__PURE__ */ jsx(
2672
+ Text,
2673
+ {
2674
+ className: "text-text-secondary",
2675
+ style: {
2676
+ marginTop: 4,
2677
+ fontSize: 12,
2678
+ fontFamily: "Inter, sans-serif"
2679
+ },
2680
+ testID: "meso-status-card-subtitle",
2681
+ children: mesoSubtitle
2682
+ }
2683
+ )
2684
+ ] }),
2685
+ metrics.length > 0 && /* @__PURE__ */ jsx(
2686
+ View,
2687
+ {
2688
+ className: "flex-row flex-wrap",
2689
+ style: { gap: 8 },
2690
+ testID: "meso-status-card-metrics",
2691
+ children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`))
2692
+ }
2693
+ ),
2694
+ gauges.length > 0 && /* @__PURE__ */ jsx(View, { style: { gap: 12 }, testID: "meso-status-card-gauges", children: gauges.map((gauge, index) => /* @__PURE__ */ jsx(Gauge, { gauge }, `${gauge.label}-${index}`)) }),
2695
+ coaching != null && /* @__PURE__ */ jsx(
2696
+ View,
2697
+ {
2698
+ style: {
2699
+ backgroundColor: "rgba(255,176,32,0.06)",
2700
+ borderWidth: 1,
2701
+ borderColor: "rgba(255,176,32,0.15)",
2702
+ borderRadius: 8,
2703
+ paddingVertical: 10,
2704
+ paddingHorizontal: 12
2705
+ },
2706
+ testID: "meso-status-card-coaching",
2707
+ children: /* @__PURE__ */ jsx(
2708
+ Text,
2709
+ {
2710
+ className: "text-text-secondary",
2711
+ style: {
2712
+ fontSize: 12,
2713
+ lineHeight: 17,
2714
+ fontFamily: "Inter, sans-serif"
2715
+ },
2716
+ children: renderCoachingText(coaching.text, coaching.highlights)
2717
+ }
2718
+ )
2719
+ }
2720
+ ),
2721
+ nextTarget != null && /* @__PURE__ */ jsxs(
2722
+ View,
2723
+ {
2724
+ className: "flex-row items-center",
2725
+ style: {
2726
+ gap: 8,
2727
+ backgroundColor: "rgba(20,184,166,0.06)",
2728
+ borderWidth: 1,
2729
+ borderColor: "rgba(20,184,166,0.2)",
2730
+ borderRadius: 8,
2731
+ paddingVertical: 10,
2732
+ paddingHorizontal: 12
2733
+ },
2734
+ testID: "meso-status-card-next-target",
2735
+ children: [
2736
+ /* @__PURE__ */ jsx(Text, { style: { fontSize: 14, color: SUCCESS }, accessibilityElementsHidden: true, children: nextTarget.icon }),
2737
+ /* @__PURE__ */ jsx(
2738
+ Text,
2739
+ {
2740
+ style: {
2741
+ flexShrink: 1,
2742
+ fontSize: 12,
2743
+ fontFamily: "Inter, sans-serif",
2744
+ fontWeight: "600",
2745
+ color: SUCCESS
2746
+ },
2747
+ children: nextTarget.text
2748
+ }
2749
+ )
2750
+ ]
2751
+ }
2752
+ )
2753
+ ] })
2754
+ ]
2755
+ }
2756
+ );
2757
+ }
2758
+
2759
+ // src/components/custom/Workout/TrainingStatusPage.tsx
866
2760
  var STATUS_ORDER = ["under", "maintenance", "productive", "over"];
867
2761
  function deriveTrainingSummary(muscles) {
868
2762
  const statusCounts = {
@@ -898,25 +2792,24 @@ function SummaryCards({ summary }) {
898
2792
  return /* @__PURE__ */ jsxs(
899
2793
  View,
900
2794
  {
2795
+ className: "bg-surface-elevated border-border",
901
2796
  style: {
902
2797
  flexGrow: 1,
903
2798
  flexBasis: "46%",
904
2799
  padding: 12,
905
2800
  borderRadius: 10,
906
- backgroundColor: SURFACE_ELEVATED2,
907
- borderWidth: 1,
908
- borderColor: BORDER_DEFAULT2
2801
+ borderWidth: 1
909
2802
  },
910
2803
  testID: `training-status-page-summary-${key}`,
911
2804
  children: [
912
2805
  /* @__PURE__ */ jsx(
913
2806
  Text,
914
2807
  {
2808
+ className: "text-text-primary",
915
2809
  style: {
916
2810
  fontSize: 22,
917
2811
  fontFamily: '"Space Grotesk", sans-serif',
918
- fontWeight: "700",
919
- color: TEXT_PRIMARY3
2812
+ fontWeight: "700"
920
2813
  },
921
2814
  children: value
922
2815
  }
@@ -924,14 +2817,14 @@ function SummaryCards({ summary }) {
924
2817
  /* @__PURE__ */ jsx(
925
2818
  Text,
926
2819
  {
2820
+ className: "text-text-tertiary",
927
2821
  style: {
928
2822
  marginTop: 2,
929
2823
  fontSize: 11,
930
2824
  fontFamily: "Inter, sans-serif",
931
2825
  fontWeight: "600",
932
2826
  letterSpacing: 0.4,
933
- textTransform: "uppercase",
934
- color: TEXT_TERTIARY2
2827
+ textTransform: "uppercase"
935
2828
  },
936
2829
  children: label
937
2830
  }
@@ -971,10 +2864,10 @@ function StatusLegend() {
971
2864
  /* @__PURE__ */ jsx(
972
2865
  Text,
973
2866
  {
2867
+ className: "text-text-secondary",
974
2868
  style: {
975
2869
  fontSize: 11,
976
2870
  fontFamily: "Inter, sans-serif",
977
- color: TEXT_SECONDARY3,
978
2871
  textTransform: "capitalize"
979
2872
  },
980
2873
  children: VOLUME_STATUS_LABELS[status]
@@ -1013,8 +2906,8 @@ function TrainingStatusPage({
1013
2906
  return /* @__PURE__ */ jsxs(
1014
2907
  View,
1015
2908
  {
1016
- className,
1017
- style: { position: "relative", width: 390, backgroundColor: PAGE_BG },
2909
+ className: ["bg-background-base", className].filter(Boolean).join(" "),
2910
+ style: { position: "relative", width: 390 },
1018
2911
  accessibilityRole: "main",
1019
2912
  "aria-label": title,
1020
2913
  testID: "training-status-page",
@@ -1025,11 +2918,11 @@ function TrainingStatusPage({
1025
2918
  Text,
1026
2919
  {
1027
2920
  accessibilityRole: "header",
2921
+ className: "text-text-primary",
1028
2922
  style: {
1029
2923
  fontSize: 20,
1030
2924
  fontFamily: '"Space Grotesk", sans-serif',
1031
- fontWeight: "700",
1032
- color: TEXT_PRIMARY3
2925
+ fontWeight: "700"
1033
2926
  },
1034
2927
  testID: "training-status-page-title",
1035
2928
  children: title
@@ -1040,10 +2933,9 @@ function TrainingStatusPage({
1040
2933
  /* @__PURE__ */ jsxs(
1041
2934
  View,
1042
2935
  {
2936
+ className: "bg-surface-elevated border-border",
1043
2937
  style: {
1044
- backgroundColor: SURFACE_ELEVATED2,
1045
2938
  borderWidth: 1,
1046
- borderColor: BORDER_DEFAULT2,
1047
2939
  borderRadius: 12,
1048
2940
  padding: 12,
1049
2941
  gap: 12